int res_send (const u_char *buf, int buflen, u_char *ans, int anssiz) { hp = (HEADER *) buf; anhp = (HEADER *) ans; ns_buf = (u_char*)buf; ns_ans = ans; ns_buflen = buflen; ns_anssiz = anssiz; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { /* errno should have been set by res_init() in this case */ return (-1); } DprintQ ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), (";; res_send()\n"), buf, buflen); v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; gotsomewhere = 0; connreset = 0; terrno = ETIMEDOUT; badns = 0; /* Send request, RETRY times, or until successful */ for (Try = 0; Try < _res.retry; Try++) { for (ns = 0; ns < _res.nscount; ns++) { struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; int rc; do rc = name_server_send (ns, nsap); while (rc == SAME_NS); if (rc != NEXT_NS) return (rc); } } resolve_close(); if (!v_circuit) { if (!gotsomewhere) SOCK_ERRNO (ECONNREFUSED); /* no nameservers found */ else SOCK_ERRNO (ETIMEDOUT); /* no answer obtained */ } else SOCK_ERRNO (terrno); return (-1); }
static intptr_t do_socket_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr_t len, /* for UDP sendto: */ rktio_addrinfo_t *addr) { rktio_socket_t s = rktio_fd_socket(rktio, rfd); intptr_t sent; int errid = 0; #ifdef RKTIO_SYSTEM_WINDOWS # define SEND_BAD_MSG_SIZE(e) (e == WSAEMSGSIZE) #else # ifdef SEND_IS_NEVER_TOO_BIG # define SEND_BAD_MSG_SIZE(errid) 0 # else # define SEND_BAD_MSG_SIZE(errid) (errid == EMSGSIZE) # endif #endif while (1) { if (addr) { /* Use first address that dosn't result in a bad-address error: */ for (; addr; addr = (rktio_addrinfo_t *)RKTIO_AS_ADDRINFO(addr)->ai_next) { do { sent = sendto(s, buffer, len, 0, RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen); } while ((sent == -1) && NOT_WINSOCK(errno == EINTR)); if (sent >= 0) break; errid = SOCK_ERRNO(); if (!WAS_EBADADDRESS(errid)) break; } } else { do { sent = send(s, buffer, len, 0); } while ((sent == -1) && NOT_WINSOCK(errno == EINTR)); if (sent == -1) errid = SOCK_ERRNO(); } if (sent >= 0) return sent; if (WAS_EAGAIN(errid)) return 0; else if (SEND_BAD_MSG_SIZE(errid) && (len > 1)) { /* split the message and try again: */ len >>= 1; } else {
/* * Handle non-blocking SOCK_STREAM connection. * Only called on 2nd (3rd etc) time a non-blocking * connect() is called. */ static int nblk_connect (Socket *socket) { if (socket->so_state & SS_ISCONNECTED) { SOCK_DEBUGF ((", connected!")); socket->so_error = 0; return (0); } /* Don't let tcp_Retransmitter() timeout this socket * (unless there is a ARP timeout etc.) */ socket->tcp_sock->timeout = 0; if ((socket->so_state & (SS_ISDISCONNECTING | SS_CONN_REFUSED)) || (socket->tcp_sock->state >= tcp_StateCLOSED)) { if (socket->so_error != 0 && socket->so_error != EALREADY) { SOCK_DEBUGF ((", %s", short_strerror(socket->so_error))); SOCK_ERRNO (socket->so_error); } else if (chk_timeout(socket->nb_timer)) { socket->so_state &= ~SS_ISCONNECTING; SOCK_DEBUGF ((", ETIMEDOUT (%s)", socket->tcp_sock->err_msg)); socket->so_error = ETIMEDOUT; SOCK_ERRNO (ETIMEDOUT); } else { SOCK_DEBUGF ((", ECONNREFUSED")); socket->so_error = ECONNREFUSED; SOCK_ERRNO (ECONNREFUSED); /* could also be ECONNRESET */ } return (-1); } if (socket->so_state & SS_ISCONNECTING) { SOCK_DEBUGF ((", EALREADY")); socket->so_error = EALREADY; /* should be redundant */ SOCK_ERRNO (EALREADY); return (-1); } SOCK_FATAL (("%s (%d) Fatal: Unhandled non-block event\n", __FILE__, __LINE__)); return (-1); }
int W32_CALL getsockname (int s, struct sockaddr *name, int *namelen) { Socket *socket = _socklist_find (s); int sa_len; SOCK_PROLOGUE (socket, "\ngetsockname:%d", s); sa_len = (socket->so_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); if (!name || !namelen || (*namelen < sa_len)) { SOCK_DEBUGF ((", EINVAL")); SOCK_ERRNO (EINVAL); if (namelen) *namelen = 0; return (-1); } if (!socket->local_addr) { SOCK_DEBUGF ((", EINVAL")); SOCK_ERRNO (EINVAL); /* according to HP/UX manpage */ return (-1); } VERIFY_RW (name, *namelen); *namelen = sa_len; memcpy (name, socket->local_addr, sa_len); #if defined(USE_IPV6) if (socket->so_family == AF_INET6) { const struct sockaddr_in6 *la = (const struct sockaddr_in6*)socket->local_addr; SOCK_DEBUGF ((", %s (%d)", _inet6_ntoa(&la->sin6_addr), ntohs(la->sin6_port))); ARGSUSED (la); } else #endif { const struct sockaddr_in *la = socket->local_addr; SOCK_DEBUGF ((", %s (%d)", inet_ntoa(la->sin_addr), ntohs(la->sin_port))); ARGSUSED (la); } return (0); }
/* * BSD-style: \n * Make a FQDN from `hostname' & `def_domain'. * Set errno on failure and return -1. */ int W32_CALL gethostname (char *buffer, int buflen) { /* the FQDN when no hostname has been set is "localhost.localdomain". * the FQDN when a hostname has been set, but no domname is set, is 'my_hostname' * the FQDN when both are set is 'my_hostname.my_domname' */ const char *my_hostname = "localhost"; const char *my_domname = "localdomain"; int pos; if (!buffer || buflen < 0) { SOCK_ERRNO (EINVAL); return (-1); } if (buflen == 0) return (0); #if (DOSX) if (!valid_addr((DWORD)buffer, buflen)) { SOCK_ERRNO (EFAULT); return (-1); } #endif if (*hostname) /* otherwise use localhost.localdomain */ { my_hostname = hostname; my_domname = NULL; /* have hostname but no domain name */ if (def_domain && *def_domain) my_domname = def_domain; } pos = 0; while (pos < buflen && *my_hostname) buffer[pos++] = *my_hostname++; if (pos < buflen && my_domname) { buffer[pos++] = '.'; /*@-nullderef@*/ while (pos < buflen && *my_domname) buffer[pos++] = *my_domname++; } if (pos < buflen) buffer[pos] = '\0'; return (0); }
// millisecs std::error_code PollPoller::poll(int timeout, std::unordered_map<int, Dispatcher *> &active_dispatchers) { if (fds_.size() == 0) { ::Sleep(timeout); return LS_OK_ERROR(); } int num_events = ::WSAPoll(&*fds_.begin(), fds_.size(), timeout); if (num_events < 0) { if (SOCK_ERRNO() == CERR(EINTR)) { return LS_OK_ERROR(); } } else if (num_events == 0) { return LS_OK_ERROR(); } else { for (auto it = fds_.begin(); it != fds_.end() && num_events > 0; ++it) { if (it->revents > 0) { --num_events; Dispatcher *dispatcher = dispatchers_[it->fd]; dispatcher->set_poll_event_data( it->revents & (POLLIN | POLLPRI), it->revents & POLLOUT, it->revents & POLLERR, (it->revents & POLLHUP) && !(it->revents & POLLIN)); active_dispatchers[dispatcher->get_fd()] = dispatcher; } } } return LS_OK_ERROR(); }
/** * BSD-style: \n * Expects a "Fully Qualified Domain Name" in `fqdn'. * Split at first `.' and extract `hostname' and `def_domain'. * Set errno on failure and return -1. */ int W32_CALL sethostname (const char *fqdn, int len) { int pos; if (!fqdn || !*fqdn || len < 0 || len > MAX_HOSTLEN) { SOCK_ERRNO (EINVAL); return (-1); } #if (DOSX) if (!valid_addr((DWORD)fqdn, len)) { SOCK_ERRNO (EFAULT); return (-1); } #endif pos = 0; while (pos < len && fqdn[pos] != '.') { if (!fqdn[pos]) /* should do complete alpha/digit/underscore check here */ { pos = 0; break; } pos++; } if (pos == 0) /* leading '.' or invalid char in name */ { SOCK_ERRNO (EINVAL); return (-1); } if (pos >= SIZEOF(hostname)) { SOCK_ERRNO (ERANGE); return (-1); } if (fqdn[pos] == '.') /* a trailing '.' is ok too */ { if (setdomainname(&fqdn[pos+1], len-pos) != 0) return (-1); } memcpy (&hostname[0], fqdn, pos); hostname[pos] = '\0'; return (0); }
static void do_get_socket_error(rktio_t *rktio) { rktio->errid = SOCK_ERRNO(); #ifdef RKTIO_SYSTEM_WINDOWS rktio->errkind = RKTIO_ERROR_KIND_WINDOWS; #else rktio->errkind = RKTIO_ERROR_KIND_POSIX; #endif }
/* * Raise SIGPIPE/SIGURG if signal defined (not needed yet). * Return -1 with errno = EPIPE. */ int _sock_sig_epipe (void) { #if defined(SIGPIPE) raise (SIGPIPE); #endif SOCK_ERRNO (EPIPE); return (-1); }
int W32_CALL getpeername (int s, struct sockaddr *name, int *namelen) { Socket *socket = _socklist_find (s); int sa_len; SOCK_PROLOGUE (socket, "\ngetpeername:%d", s); sa_len = (socket->so_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); if (!name || !namelen || (*namelen < sa_len)) { SOCK_DEBUGF ((", EINVAL")); SOCK_ERRNO (EINVAL); if (namelen) *namelen = 0; return (-1); } if (!(socket->so_state & SS_ISCONNECTED)) { SOCK_DEBUGF ((", ENOTCONN")); SOCK_ERRNO (ENOTCONN); return (-1); } VERIFY_RW (name, *namelen); *namelen = sa_len; memcpy (name, socket->remote_addr, *namelen); #if defined(USE_IPV6) if (socket->so_family == AF_INET6) { const struct sockaddr_in6 *ra = (const struct sockaddr_in6*)socket->remote_addr; SOCK_DEBUGF ((", %s (%d)", _inet6_ntoa(&ra->sin6_addr), ntohs(ra->sin6_port))); ARGSUSED (ra); } else #endif { const struct sockaddr_in *ra = socket->remote_addr; SOCK_DEBUGF ((", %s (%d)", inet_ntoa(ra->sin_addr), ntohs(ra->sin_port))); ARGSUSED (ra); } return (0); }
/* * Check for catched signals */ static int chk_signals (void) { if (_sock_sig_pending()) { SOCK_DEBUGF ((", EINTR")); SOCK_ERRNO (EINTR); return (-1); } return (0); }
/** * BSD-style: \n * Set the host's domain name. * Set errno on failure and return -1. */ int W32_CALL setdomainname (const char *name, int len) { if (!name || len < 0 || len > SIZEOF(defaultdomain)-1) { SOCK_ERRNO (EINVAL); return (-1); } #if (DOSX) if (!valid_addr((DWORD)name, len)) { SOCK_ERRNO (EFAULT); return (-1); } #endif def_domain = StrLcpy (defaultdomain, name, len); return (0); }
/** * BSD-style: \n * Return domain name of this host. * As per BSD spec, the resultant buffer ... * ... "will be null-terminated _unless_there_is_insufficient_space_"; * * Set errno on failure and return -1. */ int W32_CALL getdomainname (char *buffer, int buflen) { const char *my_domainname = def_domain ? def_domain : ""; if (!buffer || buflen < 0 || buflen < (int)strlen(my_domainname)) { SOCK_ERRNO (EINVAL); return (-1); } #if (DOSX) if (!valid_addr((DWORD)buffer, buflen)) { SOCK_ERRNO (EFAULT); return (-1); } #endif strncpy (buffer, my_domainname, buflen); /* no terminating '\0' needs to be forced here per bsd spec */ return (0); }
struct hostent * W32_CALL gethostbyname_r (const char *name, struct hostent *result, char *buffer, int buf_len, int *p_errno) { UNFINISHED(); *p_errno = ERANGE; SOCK_ERRNO (ERANGE); ARGSUSED (name); ARGSUSED (result); ARGSUSED (buffer); ARGSUSED (buf_len); return (NULL); }
int W32_CALL shutdown (int s, int how) { Socket *socket = _socklist_find (s); #if defined(USE_DEBUG) static char fmt[] = "\nshutdown:%d/??"; static char rrw[] = "r w rw"; how &= 3; fmt [sizeof(fmt)-3] = rrw [2*how]; fmt [sizeof(fmt)-2] = rrw [2*how+1]; #endif SOCK_PROLOGUE (socket, fmt, s); switch (how) { case SHUT_RD: socket->so_error = ESHUTDOWN; socket->so_state |= SS_CANTRCVMORE; /* socket->so_options &= ~SO_ACCEPTCONN; */ /** \todo For tcp, should send RST if we get * incoming data. Don't send ICMP error. */ return (0); case SHUT_WR: socket->so_error = ESHUTDOWN; socket->so_state |= SS_CANTSENDMORE; socket->so_state &= ~SS_ISLISTENING; /* socket->so_options &= ~SO_ACCEPTCONN; */ /** \todo For tcp, should send FIN when all Tx data * has been ack'ed. * close_s(s) should be same as shutdown(s,SHUT_WR) */ return (0); case SHUT_RDWR: socket->so_error = ESHUTDOWN; socket->so_state |= (SS_CANTRCVMORE | SS_CANTSENDMORE); socket->so_state &= ~SS_ISLISTENING; /* socket->so_options &= ~SO_ACCEPTCONN; */ return (0); } SOCK_ERRNO (EINVAL); return (-1); }
std::error_code check_socket_error(int fd) { #ifdef WIN32 char err = 0; #else int err = 0; #endif socklen_t len = sizeof(err); int i = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len); if (i == -1) { return LS_GENERIC_ERROR(SOCK_ERRNO()); } else if (err != 0) { return LS_GENERIC_ERROR(err); } return LS_OK_ERROR(); }
/* * Handle SOCK_DGRAM connection. Always blocking in _arp_resolve() */ static int udp_connect (Socket *socket) { #if defined(USE_IPV6) if (socket->so_family == AF_INET6) { const struct sockaddr_in6 *la = (const struct sockaddr_in6*) socket->local_addr; const struct sockaddr_in6 *ra = (const struct sockaddr_in6*) socket->remote_addr; if (!_UDP6_open (socket, &ra->sin6_addr, la->sin6_port, ra->sin6_port)) { SOCK_DEBUGF ((", no route (udp6)")); SOCK_ERRNO (EHOSTUNREACH); STAT (ip6stats.ip6s_noroute++); return (-1); } } else #endif if (!_UDP_open (socket, socket->remote_addr->sin_addr, socket->local_addr->sin_port, socket->remote_addr->sin_port)) { /* errno already set in udp_open() */ SOCK_DEBUGF ((", %s", socket->udp_sock->err_msg)); return (-1); } if ((socket->so_state & SS_PRIV) && socket->bcast_pool) { /* undo what udp_open() did above. * !!Fix me: clears recv data. */ sock_recv_init ((sock_type*)socket->udp_sock, socket->bcast_pool, socket->pool_size); } socket->so_state &= ~SS_UNCONNECTED; socket->so_state |= SS_ISCONNECTED; return (0); }
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len) { rktio_socket_t s = rktio_fd_socket(rktio, rfd); int rn; do { rn = recv(s, buffer, len, 0); } while ((rn == -1) && NOT_WINSOCK(errno == EINTR)); if (rn > 0) return rn; else if (rn == 0) return RKTIO_READ_EOF; else { int err = SOCK_ERRNO(); if (WAS_EAGAIN(err)) return 0; else { get_socket_error(); return RKTIO_READ_ERROR; } } }
int sock_recv_from (sock_type *s, void *hisip, WORD *hisport, void *buffer, unsigned len, int peek) { #if !defined(USE_UDP_ONLY) _tcp_Socket *t; #endif recv_buf *p, *oldest = NULL; recv_data *r = (recv_data*) s->udp.rx_data; long seqnum = LONG_MAX; int i; if (r->recv_sig != RECV_USED) { SOCK_ERRNO (EBADF); /* To differentiate an error from 0-byte probe (also -1) */ return (-1); } switch (s->udp.ip_type) { case UDP_PROTO: p = (recv_buf*) r->recv_bufs; /* find the oldest used UDP buffer. */ for (i = 0; i < r->recv_bufnum; i++, p++) { switch (p->buf_sig) { case RECV_UNUSED: break; case RECV_USED: /* Drop looped packets sent by us (running * under Win32 DOS box using NDIS3PKT or SwsVpkt). */ if ((_eth_ndis3pkt || _eth_SwsVpkt) && !s->tcp.is_ip6 && p->buf_hisip == intel(my_ip_addr)) { p->buf_sig = RECV_UNUSED; continue; } if (p->buf_seqnum < seqnum) /* ignore wraps */ { seqnum = p->buf_seqnum; oldest = p; #if 0 SOCK_DEBUGF (("\nsock_recv_from(): buffer %d, " "seq-num %ld, len %d", i, seqnum, p->buf_len)); #endif } break; default: outsnl (_LANG("ERROR: sock_recv_init data err")); return (0); } } break; #if !defined(USE_UDP_ONLY) case TCP_PROTO: t = &s->tcp; len = min (len, (unsigned)t->rx_datalen); if (len) memcpy (buffer, r->recv_bufs, len); return (len); #endif } if (!oldest) return (0); /* found the oldest UDP packet */ p = oldest; if (p->buf_len < 0) /* a 0-byte probe packet */ len = -1; else { len = min ((unsigned)p->buf_len, len); memcpy (buffer, p->buf_data, len); } #if defined(USE_IPV6) if (s->tcp.is_ip6) { if (hisip) memcpy (hisip, &p->buf_hisip6, sizeof(ip6_address)); } else #endif if (hisip) *(DWORD*)hisip = p->buf_hisip; if (hisport) *hisport = p->buf_hisport; if (!peek) p->buf_sig = RECV_UNUSED; return (len); }
/* * connect() * "connect" will attempt to open a connection on a foreign IP address and * foreign port address. This is achieved by specifying the foreign IP * address and foreign port number in the "servaddr". */ int W32_CALL connect (int s, const struct sockaddr *servaddr, int addrlen) { struct sockaddr_in *addr = (struct sockaddr_in*) servaddr; struct sockaddr_in6 *addr6 = (struct sockaddr_in6*) servaddr; struct Socket *socket = _socklist_find (s); volatile int rc, sa_len; BOOL is_ip6; SOCK_PROLOGUE (socket, "\nconnect:%d", s); is_ip6 = (socket->so_family == AF_INET6); sa_len = is_ip6 ? sizeof(*addr6) : sizeof(*addr); if (_sock_chk_sockaddr(socket, servaddr, addrlen) < 0) return (-1); if (socket->so_type == SOCK_STREAM) { if (socket->so_state & SS_ISCONNECTED) { SOCK_DEBUGF ((", EISCONN")); SOCK_ERRNO (EISCONN); return (-1); } if (socket->so_options & SO_ACCEPTCONN) { SOCK_DEBUGF ((", EOPNOTSUPP (listen sock)")); SOCK_ERRNO (EOPNOTSUPP); return (-1); } if (!is_ip6 && IN_MULTICAST(ntohl(addr->sin_addr.s_addr))) { SOCK_DEBUGF ((", EINVAL (mcast)")); SOCK_ERRNO (EINVAL); return (-1); } else if (is_ip6 && IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)) { SOCK_DEBUGF ((", EINVAL (mcast)")); SOCK_ERRNO (EINVAL); return (-1); } } if (socket->remote_addr) { if ((socket->so_type == SOCK_STREAM) && (socket->so_state & SS_NBIO)) return nblk_connect (socket); SOCK_DEBUGF ((", connect already done!")); SOCK_ERRNO (EISCONN); return (-1); } socket->remote_addr = (struct sockaddr_in*) SOCK_CALLOC (sa_len); if (!socket->remote_addr) { SOCK_DEBUGF ((", ENOMEM (rem)")); SOCK_ERRNO (ENOMEM); return (-1); } #if defined(USE_IPV6) if (is_ip6) { struct sockaddr_in6 *ra = (struct sockaddr_in6*)socket->remote_addr; ra->sin6_family = AF_INET6; ra->sin6_port = addr6->sin6_port; memcpy (&ra->sin6_addr, &addr6->sin6_addr, sizeof(ra->sin6_addr)); } else #endif { socket->remote_addr->sin_family = AF_INET; socket->remote_addr->sin_port = addr->sin_port; socket->remote_addr->sin_addr = addr->sin_addr; } if (!socket->local_addr) { SOCK_DEBUGF ((", auto-binding")); socket->local_addr = (struct sockaddr_in*) SOCK_CALLOC (sa_len); if (!socket->local_addr) { free (socket->remote_addr); socket->remote_addr = NULL; SOCK_DEBUGF ((", ENOMEM (loc)")); SOCK_ERRNO (ENOMEM); return (-1); } #if defined(USE_IPV6) if (is_ip6) { struct sockaddr_in6 *la = (struct sockaddr_in6*)socket->local_addr; la->sin6_family = AF_INET6; la->sin6_port = htons (find_free_port(0,TRUE)); memcpy (&la->sin6_addr, &in6addr_my_ip, sizeof(la->sin6_addr)); } else #endif { socket->local_addr->sin_family = AF_INET; socket->local_addr->sin_port = htons (find_free_port(0,TRUE)); socket->local_addr->sin_addr.s_addr = htonl (my_ip_addr); } } SOCK_DEBUGF ((", src/dest ports: %u/%u", ntohs(socket->local_addr->sin_port), ntohs(socket->remote_addr->sin_port))); /* Not safe to run sock_daemon() now */ _sock_crit_start(); /* Setup SIGINT handler now. */ if (_sock_sig_setup() < 0) { SOCK_ERRNO (EINTR); SOCK_DEBUGF ((", EINTR")); _sock_crit_stop(); return (-1); } switch (socket->so_type) { case SOCK_STREAM: rc = tcp_connect (socket); break; case SOCK_DGRAM: rc = udp_connect (socket); break; case SOCK_RAW: rc = raw_connect (socket); break; default: SOCK_ERRNO (EPROTONOSUPPORT); rc = -1; break; } _sock_sig_restore(); _sock_crit_stop(); return (rc); }
/* WARNING: all parameters MUST be valid, * NULL pointers lead to a crash. */ ret_t cherokee_socket_writev (cherokee_socket_t *socket, const struct iovec *vector, uint16_t vector_len, size_t *pcnt_written) { int re; int i; ret_t ret; size_t cnt; *pcnt_written = 0; /* There must be something to send, otherwise behaviour is undefined * and as we don't want this case, we have to enforce assertions. */ return_if_fail (vector != NULL && vector_len > 0, ret_error); if (likely (socket->is_tls != TLS)) { #ifdef _WIN32 int i; size_t total; for (i = 0, re = 0, total = 0; i < vector_len; i++) { if (vector[i].iov_len == 0) continue; do { re = send (SOCKET_FD(socket), vector[i].iov_base, vector[i].iov_len, 0); } while ((re == -1) && (errno == EINTR)); if (re < 0) break; total += re; /* if it is a partial send, then stop sending data */ if (re != vector[i].iov_len) break; } *pcnt_written = total; /* if we have sent at least one byte, * then return OK. */ if (likely (total > 0)) return ret_ok; if (re == 0) { int err = SOCK_ERRNO(); if (i == vector_len) return ret_ok; /* Retry later. */ return ret_eagain; } #else /* ! WIN32 */ do { re = writev (SOCKET_FD(socket), vector, vector_len); } while ((re == -1) && (errno == EINTR)); if (likely (re > 0)) { *pcnt_written = (size_t) re; return ret_ok; } if (re == 0) { int i; /* Find out whether there was something to send or not. */ for (i = 0; i < vector_len; i++) { if (vector[i].iov_base != NULL && vector[i].iov_len > 0) break; } if (i < vector_len) return ret_eagain; /* No, nothing to send, so return ok. */ return ret_ok; } #endif if (re < 0) { int err = SOCK_ERRNO(); switch (err) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: return ret_eagain; case EPIPE: #ifdef ENOTCONN case ENOTCONN: #endif case ECONNRESET: socket->status = socket_closed; case ETIMEDOUT: case EHOSTUNREACH: return ret_error; } LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_WRITEV, SOCKET_FD(socket)); } return ret_error; } /* TLS connection: Here we don't worry about sparing a few CPU * cycles, so we reuse the single send case for TLS. */ for (i = 0; i < vector_len; i++) { if ((vector[i].iov_len == 0) || (vector[i].iov_base == NULL)) continue; cnt = 0; ret = cherokee_socket_write (socket, vector[i].iov_base, vector[i].iov_len, &cnt); if (ret != ret_ok) { return ret; } *pcnt_written += cnt; if (cnt == vector[i].iov_len) continue; /* Unfinished */ return ret_ok; } /* Did send everything */ return ret_ok; }
/** * _eth_send() does the actual transmission once we are complete with * filling the buffer. Do any last minute patches here, like fix the * size. Send to "loopback" device if it's IP and destination matches * loopback network (127.x.x.x.). * * Return length of network-layer packet (not length of link-layer * packet). */ int _eth_send (WORD len, const void *sock, const char *file, unsigned line) { #if defined(USE_DEBUG) || defined(USE_LOOPBACK) unsigned errline = 0; #endif BOOL send_loopback_to_driver = FALSE; SIO_TRACE (("_eth_send, len %d", len)); if (!_eth_is_init) /* GvB 2002-09, Lets us run without a working eth */ { SOCK_ERRNO (ENETDOWN); return (0); } #if defined(WIN32) /* * Just a test for now; send it to the driver and look what happens.... * They go on the wire and not to the Winsock loopback provider. * No surprise here yet. */ if (loopback_mode & LBACK_MODE_WINSOCK) send_loopback_to_driver = TRUE; #endif if (proto == IP4_TYPE) { /* Sending to loopback device if IPv4. */ const in_Header *ip = (const in_Header*) nw_pkt; if (!send_loopback_to_driver && _ip4_is_loopback_addr(intel(ip->destination))) { #if defined(USE_LOOPBACK) len = send_loopback (*TX_BUF(), FALSE, &errline); #else STAT (ip4stats.ips_odropped++); /* packet dropped (null-device) */ #endif goto debug_tx; } } #if defined(USE_IPV6) else if (proto == IP6_TYPE) { const in6_Header *ip = (const in6_Header*) nw_pkt; if (!send_loopback_to_driver && IN6_IS_ADDR_LOOPBACK(&ip->destination)) { #if defined(USE_LOOPBACK) len = send_loopback (*TX_BUF(), TRUE, &errline); #else STAT (ip6stats.ip6s_odropped++); #endif goto debug_tx; } } #endif /* USE_IPV6 */ #if defined(USE_PPPOE) else if (proto == PPPOE_SESS_TYPE) { pppoe_Packet *pppoe = (pppoe_Packet*) TX_BUF()->eth.data; pppoe->length = intel16 (len+2); len += PPPOE_HDR_SIZE + 2; /* add 2 for protocol */ } #endif /* Store the last Tx CPU timestamp (for debugging). */ #if (DOSX) && !(DOSX & WINWATT) if (_dbugxmit && has_rdtsc) get_rdtsc2 (&_eth_last.tx.tstamp); #endif /* Do the MAC-dependant transmit. `len' on return is total length * of link-layer packet sent. `len' is 0 on failure. The xmit-hook * is used by e.g. libpcap/libnet. */ if (_eth_xmit_hook) len = (*_eth_xmit_hook) (TX_BUF(), len + _pkt_ip_ofs); else len = (*mac_transmit) (TX_BUF(), len + _pkt_ip_ofs); if (len > _pkt_ip_ofs) { _eth_last.tx.size = len; len -= _pkt_ip_ofs; } else { if (debug_on) outs ("Tx failed. "); len = 0; _eth_last.tx.size = 0; } debug_tx: #if defined(NEED_PKT_SPLIT) pkt_split_mac_out (TX_BUF()); #endif #if defined(USE_STATISTICS) if (len > 0) update_out_stat(); #endif #if defined(USE_DEBUG) if (_dbugxmit) (*_dbugxmit) (sock, (const in_Header*)nw_pkt, file, line); if (len == 0) { if (errline && !send_loopback_to_driver) dbug_printf ("** Error in loopback handler, line %u\n", errline); else { const char err[] = "** Transmit fault **\n"; TCP_CONSOLE_MSG (0, ("%s", err)); dbug_printf (err); } } #else ARGSUSED (sock); ARGSUSED (file); ARGSUSED (line); #endif /* Undo hack done in pppoe_mac_format() */ if (proto == PPPOE_SESS_TYPE || _pktdevclass == PDCLASS_ETHER) _pkt_ip_ofs = sizeof(eth_Header); return (len); }
/* WARNING: all parameters MUST be valid, * NULL pointers lead to a crash. */ ret_t cherokee_socket_read (cherokee_socket_t *socket, char *buf, int buf_size, size_t *pcnt_read) { ret_t ret; int err; ssize_t len; *pcnt_read = 0; /* There must be something to read, otherwise behaviour is undefined * and as we don't want this case, we have to enforce assertions. */ return_if_fail (buf != NULL && buf_size > 0, ret_error); if (unlikely (socket->status == socket_closed)) { TRACE(ENTRIES, "Reading a closed socket: fd=%d (TLS=%d)\n", SOCKET_FD(socket), (socket->is_tls == TLS)); return ret_eof; } if (likely (socket->is_tls != TLS)) { /* Plain read */ do { len = recv (SOCKET_FD(socket), buf, buf_size, 0); } while ((len < 0) && (errno == EINTR)); if (likely (len > 0)) { *pcnt_read = len; return ret_ok; } if (len == 0) { socket->status = socket_closed; return ret_eof; } /* Error handling */ err = SOCK_ERRNO(); TRACE(ENTRIES",read", "Socket read error fd=%d: '%s'\n", SOCKET_FD(socket), strerror(errno)); switch (err) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: return ret_eagain; case EPIPE: #ifdef ENOTCONN case ENOTCONN: #endif case ECONNRESET: socket->status = socket_closed; case ETIMEDOUT: case EHOSTUNREACH: return ret_error; } LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_READ, SOCKET_FD(socket)); return ret_error; } else if (socket->cryptor != NULL) { ret = cherokee_cryptor_socket_read (socket->cryptor, buf, buf_size, pcnt_read); switch (ret) { case ret_ok: case ret_error: case ret_eagain: return ret; case ret_eof: socket->status = socket_closed; return ret_eof; default: RET_UNKNOWN(ret); return ret; } } return ret_error; }
/* WARNING: all parameters MUST be valid, * NULL pointers lead to a crash. */ ret_t cherokee_socket_write (cherokee_socket_t *socket, const char *buf, int buf_len, size_t *pcnt_written) { ret_t ret; int err; ssize_t len; *pcnt_written = 0; /* There must be something to send, otherwise behaviour is undefined * and as we don't want this case, we have to enforce assertions. */ return_if_fail (buf != NULL && buf_len > 0, ret_error); if (likely (socket->is_tls != TLS)) { do { len = send (SOCKET_FD(socket), buf, buf_len, 0); } while ((len < 0) && (errno == EINTR)); if (likely (len > 0) ) { /* Return n. of bytes sent. */ *pcnt_written = len; return ret_ok; } if (len == 0) { /* Very strange, socket is ready but nothing * has been written, retry later. */ return ret_eagain; } /* Error handling */ err = SOCK_ERRNO(); switch (err) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: return ret_eagain; case EPIPE: case ECONNRESET: #ifdef ENOTCONN case ENOTCONN: #endif socket->status = socket_closed; case ETIMEDOUT: case EHOSTUNREACH: return ret_error; } LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_WRITE, SOCKET_FD(socket)); return ret_error; } else if (socket->cryptor != NULL) { ret = cherokee_cryptor_socket_write (socket->cryptor, (char *)buf, buf_len, pcnt_written); switch (ret) { case ret_ok: case ret_error: case ret_eagain: return ret; case ret_eof: socket->status = socket_closed; return ret_eof; default: RET_UNKNOWN(ret); return ret; } } return ret_error; }
ret_t cherokee_socket_connect (cherokee_socket_t *sock) { int r; int err; TRACE (ENTRIES",connect", "connect type=%s\n", SOCKET_AF(sock) == AF_INET ? "AF_INET" : SOCKET_AF(sock) == AF_INET6 ? "AF_INET6" : SOCKET_AF(sock) == AF_UNIX ? "AF_UNIX" : "Unknown"); do { switch (SOCKET_AF(sock)) { case AF_INET: r = connect (SOCKET_FD(sock), (struct sockaddr *) &SOCKET_ADDR(sock), sizeof(struct sockaddr_in)); break; #ifdef HAVE_IPV6 case AF_INET6: r = connect (SOCKET_FD(sock), (struct sockaddr *) &SOCKET_ADDR(sock), sizeof(struct sockaddr_in6)); break; #endif #ifdef HAVE_SOCKADDR_UN case AF_UNIX: if (SOCKET_SUN_PATH (socket)[0] != 0) { r = connect (SOCKET_FD(sock), (struct sockaddr *) &SOCKET_ADDR(sock), SUN_LEN (SOCKET_ADDR_UNIX(sock))); } else { r = connect (SOCKET_FD(sock), (struct sockaddr *) &SOCKET_ADDR(sock), SUN_ABSTRACT_LEN (SOCKET_ADDR_UNIX(sock))); } break; #endif default: SHOULDNT_HAPPEN; return ret_no_sys; } } while ((r == -1) && (errno == EINTR)); if (r < 0) { err = SOCK_ERRNO(); TRACE (ENTRIES",connect", "connect error=%d '%s'\n", err, strerror(err)); switch (err) { case EISCONN: break; case EINVAL: case ENOENT: case ECONNRESET: case ECONNREFUSED: case EADDRNOTAVAIL: return ret_deny; case ETIMEDOUT: return ret_error; case EAGAIN: case EALREADY: case EINPROGRESS: #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif return ret_eagain; default: LOG_ERRNO_S (errno, cherokee_err_error, CHEROKEE_ERROR_SOCKET_CONNECT); return ret_error; } } TRACE (ENTRIES",connect", "succeed. fd=%d\n", SOCKET_FD(sock)); sock->status = socket_reading; return ret_ok; }
/* * Handle SOCK_STREAM blocking connection. Or non-blocking connect * the first time connect() is called. */ static int tcp_connect (Socket *socket) { DWORD timeout; int status; #if defined(USE_IPV6) if (socket->so_family == AF_INET6) { const struct sockaddr_in6 *la = (const struct sockaddr_in6*) socket->local_addr; const struct sockaddr_in6 *ra = (const struct sockaddr_in6*) socket->remote_addr; if (!_TCP6_open (socket, &ra->sin6_addr, la->sin6_port, ra->sin6_port)) { /* errno already set in _TCP6_open() */ SOCK_DEBUGF ((", %s", socket->tcp_sock->err_msg)); return (-1); } } else #endif if (!_TCP_open (socket, socket->remote_addr->sin_addr, socket->local_addr->sin_port, socket->remote_addr->sin_port)) { /* errno already set in tcp_open() */ SOCK_DEBUGF ((", %s", socket->tcp_sock->err_msg)); return (-1); } /* Don't let tcp_Retransmitter() kill this socket * before our `socket->timeout' expires */ socket->tcp_sock->locflags |= LF_RCVTIMEO; /* We're here only when connect() is called the 1st time * (blocking or non-blocking socket). */ socket->so_state |= SS_ISCONNECTING; timeout = set_timeout (1000 * socket->timeout); if (socket->so_state & SS_NBIO) { /* if user calls getsockopt(SO_ERROR) before calling connect() again */ socket->so_error = EALREADY; socket->nb_timer = timeout; SOCK_DEBUGF ((", EINPROGRESS")); SOCK_ERRNO (EINPROGRESS); return (-1); } /* Handle blocking stream socket connect. * Maybe we should use select_s() instead ? * Maybe set LF_NOCLOSE for all BSD sockets? */ status = _ip_delay0 ((sock_type*)socket->tcp_sock, socket->timeout, (UserHandler)chk_signals, NULL); if (socket->so_error == EHOSTUNREACH) { SOCK_DEBUGF ((", %s", socket->tcp_sock->err_msg ? socket->tcp_sock->err_msg : "no route")); SOCK_ERRNO (EHOSTUNREACH); return (-1); } /* We got an ICMP_UNREACH from someone */ if (socket->so_state & SS_CONN_REFUSED) { socket->so_state &= ~SS_ISCONNECTING; SOCK_DEBUGF ((", ECONNREFUSED")); SOCK_ERRNO (ECONNREFUSED); return (-1); } if (status < 0 && chk_timeout(timeout)) { socket->so_state &= ~SS_ISCONNECTING; SOCK_DEBUGF ((", ETIMEDOUT")); SOCK_ERRNO (ETIMEDOUT); return (-1); } if (status < 0) { socket->so_state &= ~SS_ISCONNECTING; SOCK_DEBUGF ((", ECONNRESET")); SOCK_ERRNO (ECONNRESET); return (-1); } socket->so_state &= ~(SS_UNCONNECTED | SS_ISCONNECTING); socket->so_state |= SS_ISCONNECTED; return (0); }
/** * Try asking a LAN extension of DOS for a host-name. */ int _get_machine_name (char *buf, int size) { IREGS reg; char *h; char dosBuf[16]; int len; memset (®, 0, sizeof(reg)); reg.r_ax = 0x5E00; #if (DOSX & DJGPP) if (_go32_info_block.size_of_transfer_buffer < sizeof(dosBuf)) return (-1); reg.r_ds = __tb / 16; reg.r_dx = __tb & 15; #elif (DOSX & (PHARLAP|X32VM|POWERPAK)) if (_watt_dosTbSize < sizeof(dosBuf) || !_watt_dosTbr) return (-1); reg.r_ds = RP_SEG (_watt_dosTbr); reg.r_dx = RP_OFF (_watt_dosTbr); #elif (DOSX & DOS4GW) if (_watt_dosTbSize < sizeof(dosBuf) || !_watt_dosTbSeg) return (-1); reg.r_ds = _watt_dosTbSeg; reg.r_dx = 0; #elif (DOSX == 0) reg.r_ds = FP_SEG (dosBuf); reg.r_dx = FP_OFF (dosBuf); #else #error Help me! #endif GEN_INTERRUPT (0x21, ®); if ((reg.r_flags & CARRY_BIT) || hiBYTE(reg.r_cx) == 0) return (-1); #if (DOSX & DJGPP) dosmemget (__tb, sizeof(dosBuf), dosBuf); #elif (DOSX & (PHARLAP|X32VM|POWERPAK)) ReadRealMem ((void*)&dosBuf, _watt_dosTbr, sizeof(dosBuf)); #elif (DOSX & DOS4GW) memcpy (dosBuf, SEG_OFS_TO_LIN(_watt_dosTbSeg,0), sizeof(dosBuf)); #endif /* Remove right space padding */ h = dosBuf + min (strlen(dosBuf), sizeof(dosBuf)-1); while (h > dosBuf && h[-1] == ' ') h--; *h = '\0'; h = dosBuf; len = strlen (h); if (len + 1 > size) { SOCK_ERRNO (ERANGE); return (-1); } strcpy (buf, h); strlwr (buf); return (0); }