/* FUNCTION: bsd_getsockopt() * * Get a socket option value * * PARAM1: s; IN - socket descriptor * PARAM2: level; IN - the level of the option to get * PARAM3: name; IN - the name of the option to get * PARAM4: opt; OUT - ptr to buffer for return of option value; may be * NULL * PARAM5: optlen; IN/OUT - ptr to int; on entry, specifies the length * in bytes of opt; on successful return, specifies the * length of the returned option; may be NULL if opt is * also NULL * RETURNS: 0 if successful, -1 if an error occurred. The error is * available via bsd_errno(s). */ int bsd_getsockopt(BSD_SOCKET s, int level, int name, void * opt, int * optlen) { struct socket * so; int loptlen; int e; so = LONG2SO(s); SOC_CHECK(so); /* make sure supplied option value is big enough for the * named option, else fail w/error EFAULT */ loptlen = bsd_i_sockoptlen(level, name); if ((optlen == NULL) || (*optlen < loptlen)) { so->so_error = EFAULT; return -1; } e = t_getsockopt(s, level, name, opt, loptlen); /* if it worked, copy the option length back for the caller's use */ if (e == 0) { *optlen = loptlen; } return e; }
int t_errno(long s) { struct socket *so = LONG2SO(s); struct socket *tmp; int errcode = ENOTSOCK; LOCK_NET_RESOURCE(NET_RESID); /* protect soq */ /* search socket queue for passed socket. This routine should * not use SOC_CHECK since it can be ifdeffed out, and we must * be ready to return EPIPE if the socket does not exist. */ for (tmp = (struct socket *)(&soq); tmp; tmp = tmp->next) { if (tmp == so) /* found socket, return error */ { errcode = so->so_error; break; } } UNLOCK_NET_RESOURCE(NET_RESID); return errcode; }
int t_getsockopt(long s, int level, int name, void * arg, int arglen) { struct socket * so; int err; so = LONG2SO(s); SOC_CHECK(so); USE_ARG(level); USE_ARG(arglen); LOCK_NET_RESOURCE (NET_RESID); INET_TRACE (INETM_SOCKET, ("INET: getsockopt: name %x val %x valsize %d\n", name, val)); /* is it a level IP_OPTIONS call? */ if (level != IP_OPTIONS) { if ((err = sogetopt (so, name, arg)) != 0) { so->so_error = err; UNLOCK_NET_RESOURCE (NET_RESID); return SOCKET_ERROR; } } else { /* level 1 options are for the IP packet level. * the info is carried in the socket CB, then put * into the PACKET. */ if (name == IP_TTL_OPT) { if (!so->so_optsPack) *(int *)arg = IP_TTL; else *(int *)arg = (int)so->so_optsPack->ip_ttl; } else if (name == IP_TOS) { if (!so->so_optsPack) *(int *)arg = IP_TOS_DEFVAL; else *(int *)arg = (int)so->so_optsPack->ip_tos; } else { UNLOCK_NET_RESOURCE (NET_RESID); return SOCKET_ERROR; } } so->so_error = 0; UNLOCK_NET_RESOURCE (NET_RESID); return 0; }
/* FUNCTION: bsd_recvfrom() * * Receive data from a socket * * PARAM1: s; IN - socket descriptor * PARAM2: buf; OUT - ptr to buffer for return of received data * PARAM3: len; IN - length (in bytes) of buf * PARAM4: flags; IN - flags to be applied to the recvfrom() operation * PARAM5: from; OUT - ptr to buffer for return of sending peer's name; * may be NULL if return of name is not requested * PARAM6: fromlen; IN/OUT - ptr to int; on entry, specifies the length * in bytes of from; on successful return, specifies the * length of the returned name; may be NULL if * from is also NULL * RETURNS: the number of bytes received (>= 0), or -1 if an error * occurred. The error is available via bsd_errno(s). */ int bsd_recvfrom(BSD_SOCKET s, void * buf, BSD_SIZE_T len, int flags, struct sockaddr * from, int * fromlen) { struct socket * so; struct sockaddr lfrom; int lfromlen = 0; int lret; so = LONG2SO(s); SOC_CHECK(so); /* if we were given a buffer for the peer's address, also get the * buffer's length */ if (from != NULL) { if (fromlen == NULL) { so->so_error = EFAULT; return -1; } lfromlen = *fromlen; } lret = t_recvfrom(s, (char *)buf, len, flags, &lfrom, &lfromlen ); /* if we were successful, and we were given a buffer for the peer's * name: copy the peer's name back into the buffer, but limit * the copy to the lesser of the buffer's length and sizeof(struct * sockaddr_in), which is all that t_recvfrom() can return as a peer * name. * For IPV6 addresses or dual IPV4/IPV6 stack, the max size copied * is sizeof(struct sockaddr_in6) */ if ((lret != -1) && (from != NULL)) { #ifndef IP_V6 if (lfromlen > sizeof(struct sockaddr_in)) lfromlen = sizeof(struct sockaddr_in); #else if (lfromlen > sizeof(struct sockaddr_in6)) lfromlen = sizeof(struct sockaddr_in6); #endif MEMCPY(from, &lfrom, lfromlen); *fromlen = lfromlen; } return lret; }
int t_recv (long s, char * buf, int len, int flag) { #ifdef SOCKDEBUG char logbuf[10]; #endif struct socket * so; int err; int sendlen = len; so = LONG2SO(s); #ifdef SOC_CHECK_ALWAYS SOC_CHECK(so); #endif if ((so->so_state & SO_IO_OK) != SS_ISCONNECTED) { so->so_error = EPIPE; #ifdef SOCKDEBUG sprintf(logbuf, "t_recv: %d", so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } so->so_error = 0; LOCK_NET_RESOURCE(NET_RESID); IN_PROFILER(PF_TCP, PF_ENTRY); /* measure time in TCP */ INET_TRACE (INETM_IO, ("INET:recv: so %x, len %d\n", so, len)); err = soreceive(so, NULL, buf, &len, flag); IN_PROFILER(PF_TCP, PF_EXIT); /* measure time in TCP */ UNLOCK_NET_RESOURCE(NET_RESID); if(err) { so->so_error = err; #ifdef SOCKDEBUG sprintf(logbuf, "t_recv: %d", so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } /* return bytes we sent - the amount we wanted to send minus * the amount left in the buffer. */ return (sendlen - len); }
/* FUNCTION: bsd_getpeername() * * Get the name of the connected peer * * PARAM1: s; IN - socket descriptor * PARAM2: name; OUT - ptr to buffer for return of peer's address * PARAM3: addrlen; IN/OUT - ptr to int; on entry, specifies the length * in bytes of name; on successful return, specifies the * length of the returned name * RETURNS: 0 if successful, -1 if an error occurred. The error is * available via bsd_errno(s). */ int bsd_getpeername(BSD_SOCKET s, struct sockaddr * name, int * namelen) { struct socket * so; struct sockaddr lname; int lnamelen; int lret; so = LONG2SO(s); SOC_CHECK(so); /* if the buffer length is bogus, fail */ if (namelen == NULL) { so->so_error = EFAULT; return -1; } lnamelen = *namelen; lret = t_getpeername(s, &lname, &lnamelen); /* if we were successful: copy the peer's address back into the * buffer, but limit the copy to the lesser of the buffer's length * and sizeof(struct sockaddr_in), which is all that * t_getpeername() can return as a peer address, and pass the * copied length back to the caller. * For IPV6 addresses, or for dual IPV4/IPV6 stack, * the max size is sizeof(struct sockaddr_in6) */ if (lret != -1) { #ifndef IP_V6 if (lnamelen > sizeof(struct sockaddr_in)) lnamelen = sizeof(struct sockaddr_in); #else if (lnamelen > sizeof(struct sockaddr_in6)) lnamelen = sizeof(struct sockaddr_in6); #endif MEMCPY(name, &lname, lnamelen); *namelen = lnamelen; } return lret; }
int t_bind (long s, struct sockaddr * addr, int addrlen) { struct mbuf * nam; struct sockaddr sa; struct sockaddr * sap; struct socket * so; int err; so = LONG2SO(s); /* convert long to socket */ SOC_CHECK(so); DOMAIN_CHECK(so, addrlen); so->so_error = 0; if (addr == (struct sockaddr *)NULL) { MEMSET ((void *)&sa, 0, sizeof(sa)); addrlen = sizeof(sa); sa.sa_family = so->so_domain; sap = &sa; } else sap = addr; if ((nam = sockargs (sap, addrlen, MT_SONAME)) == NULL) { so->so_error = ENOMEM; return SOCKET_ERROR; } LOCK_NET_RESOURCE(NET_RESID); err = sobind (so, nam); m_freem(nam); UNLOCK_NET_RESOURCE(NET_RESID); if (err) { so->so_error = err; return SOCKET_ERROR; } return 0; }
/* FUNCTION: bsd_accept() * * Accept a connection on a socket * * PARAM1: s; IN - socket descriptor for the listening socket * PARAM2: addr; OUT - ptr to buffer for return of accepted peer's address; * may be NULL if return of address is not requested * PARAM3: addrlen; IN/OUT - ptr to int; on entry, specifies the length * in bytes of addr; on successful return, specifies the * length of the returned address; may be NULL if * addr is also NULL * RETURNS: A socket descriptor if successful, -1 if an error occurred. * The error is available via bsd_errno(s). */ BSD_SOCKET bsd_accept(BSD_SOCKET s, struct sockaddr * addr, int * addrlen) { struct socket * so; struct sockaddr laddr; long lret; so = LONG2SO(s); SOC_CHECK(so); /* if we were given a buffer for the peer's address, also get the * buffer's length */ if (addr != NULL) { if (addrlen == 0) { so->so_error = EFAULT; return -1; } } lret = t_accept(s, &laddr, addrlen); /* if we were successful, and we were given a buffer for the peer's * address: copy the peer's address back into the buffer, but limit * the copy to the lesser of the buffer's length and sizeof(struct * sockaddr_in), which is all that t_accept() can return as a peer * address. */ if ((lret != -1) && (addr != NULL)) { if (*addrlen > sizeof(struct sockaddr_in)) *addrlen = sizeof(struct sockaddr_in); MEMCPY(addr, &laddr, *addrlen); } return lret; }
int t_recvfrom(long s, char * buf, int len, int flags, struct sockaddr * from, int * fromlen) { struct socket * so; struct mbuf * sender = NULL; int err; int sendlen = len; so = LONG2SO(s); SOC_CHECK(so); so->so_error = 0; LOCK_NET_RESOURCE(NET_RESID); err = soreceive(so, &sender, buf, &len, flags); /* copy sender info from mbuf to sockaddr */ if (sender) { MEMCPY(from, (mtod(sender, struct sockaddr *)), *fromlen ); m_freem (sender); } UNLOCK_NET_RESOURCE(NET_RESID); if(err) { so->so_error = err; return SOCKET_ERROR; } /* OK return: amount of data actually sent */ return (sendlen - len); }
int t_shutdown(long s, int how) { struct socket *so; int err; so = LONG2SO(s); SOC_CHECK(so); so->so_error = 0; INET_TRACE (INETM_SOCKET, ("INET:shutdown so %x how %d\n", so, how)); LOCK_NET_RESOURCE(NET_RESID); err = soshutdown(so, how); UNLOCK_NET_RESOURCE(NET_RESID); if (err != 0) { so->so_error = err; return SOCKET_ERROR; } return 0; }
/* FUNCTION: bsd_setsockopt() * * Set a socket option value * * PARAM1: s; IN - socket descriptor * PARAM2: level; IN - the level of the option to set * PARAM3: name; IN - the name of the option to set * PARAM4: opt; OUT - ptr to buffer containing option value; may be * NULL * PARAM5: optlen; IN - specifies the length in bytes of the option * value in opt * RETURNS: 0 if successful, -1 if an error occurred. The error is * available via bsd_errno(s). */ int bsd_setsockopt(BSD_SOCKET s, int level, int name, void * opt, int optlen) { struct socket * so; so = LONG2SO(s); SOC_CHECK(so); /* make sure supplied option value is big enough for the * named option, else fail w/error EFAULT */ if (optlen < bsd_i_sockoptlen(level, name)) { so->so_error = EFAULT; return -1; } return t_setsockopt(s, level, name, opt, optlen); }
int t_listen(long s, int backlog) { struct socket * so; int err; so = LONG2SO(s); /* convert long to socket */ SOC_CHECK(so); so->so_error = 0; INET_TRACE (INETM_SOCKET, ("SOCK:listen:qlen %d\n", backlog)); LOCK_NET_RESOURCE(NET_RESID); err = solisten (so, backlog); UNLOCK_NET_RESOURCE(NET_RESID); if (err != 0) { so->so_error = err; return SOCKET_ERROR; } return 0; }
int t_socketclose(long s) { struct socket * so; int err; so = LONG2SO(s); SOC_CHECK(so); so->so_error = 0; INET_TRACE ((INETM_CLOSE|INETM_SOCKET), ("INET:close, so %lx\n",so)); LOCK_NET_RESOURCE(NET_RESID); err = soclose(so); UNLOCK_NET_RESOURCE(NET_RESID); if (err != 0) { /* do not do the following assignment since the socket structure addressed by so has been freed by this point, jharan 12-10-98 */ /* so->so_error = err; */ return SOCKET_ERROR; } return 0; }
/* * FUNCTION: bsd_ioctl() * * Perform a control operation on a socket * * PARAM1: s; IN - socket descriptor * PARAM2: request; IN - requested control operation * PARAM3: arg; IN/OUT - arguments as required for control operation * RETURNS: 0 if successful, -1 if an error occurred. The error is * available via bsd_errno(s). */ int bsd_ioctl(BSD_SOCKET s, unsigned long request, ...) { struct socket * so; va_list argptr; int iarg; so = LONG2SO(s); SOC_CHECK(so); va_start(argptr, request); switch (request) { case FIONBIO: iarg = va_arg(argptr, int); va_end(argptr); return t_setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &iarg, sizeof(iarg)); default: so->so_error = EINVAL; return -1; } }
int t_send(long s, char * buf, int len, int flags) { struct socket * so; int e; /* error holder */ int total_sent = 0; int maxpkt; int sendlen; int sent; so = LONG2SO(s); #ifdef SOC_CHECK_ALWAYS SOC_CHECK(so); #endif if ((so->so_state & SO_IO_OK) != SS_ISCONNECTED) { so->so_error = EPIPE; return SOCKET_ERROR; } so->so_error = 0; /* If this is not a stream socket, assume it is bound and pass to * t_sendto() with a null sockaddr */ if (so->so_type != SOCK_STREAM) return(t_sendto(s, buf, len, flags, NULL, 0)); maxpkt = TCP_MSS; if(so->so_pcb) { struct tcpcb * tp; tp = intotcpcb(so->so_pcb); /* get tcp structure with mss */ if(tp->t_maxseg) /* Make sure it's set */ maxpkt = tp->t_maxseg; } IN_PROFILER(PF_TCP, PF_ENTRY); /* measure time in TCP */ while (len) { if (len > maxpkt) sendlen = maxpkt; /* take biggest block we can */ else sendlen = len; sent = sendlen; LOCK_NET_RESOURCE(NET_RESID); e = sosend (so, NULL, buf, &sendlen, flags); UNLOCK_NET_RESOURCE(NET_RESID); if (e != 0) /* sock_sendit failed? */ { /* if we simply ran out of bufs, report back to caller. */ if ((e == ENOBUFS) || (e == EWOULDBLOCK)) { /* if we actually sent something before running out * of buffers, report what we sent; * else, report the error and let the application * retry the call later */ if (total_sent != 0) { so->so_error = 0; break; /* break out of while(len) loop */ } } so->so_error = e; return SOCKET_ERROR; } /* if we can't send anymore, return now */ if (sendlen != 0) break; /* break out of while(len) loop */ /* adjust numbers & pointers, and go do next send loop */ sent -= sendlen; /* subtract anything that didn't get sent */ buf += sent; len -= sent; total_sent += sent; } IN_PROFILER(PF_TCP, PF_EXIT); /* measure time in TCP */ return total_sent; }
int t_sendto (long s, char * buf, int len, int flags, struct sockaddr * to, int tolen) { struct socket * so; int sendlen; int err; struct mbuf * name; so = LONG2SO(s); SOC_CHECK(so); so->so_error = 0; switch (so->so_type) { case SOCK_STREAM: /* this is a stream socket, so pass this request through * t_send() for its large-send support. */ return t_send(s, buf, len, flags); /*NOTREACHED*/ case SOCK_DGRAM: /* datagram (UDP) socket -- prepare to check length */ sendlen = udp_maxalloc(); break; #ifdef IP_RAW case SOCK_RAW: /* raw socket -- prepare to check length */ sendlen = ip_raw_maxalloc(so->so_options & SO_HDRINCL); break; #endif /* IP_RAW */ default: /* socket has unknown type */ dtrap(); so->so_error = EFAULT; return SOCKET_ERROR; /*NOTREACHED*/ } /* fall through for non-stream sockets: SOCK_DGRAM (UDP) and * SOCK_RAW (raw IP) */ /* check length against underlying stack's maximum */ if (len > sendlen) { so->so_error = EMSGSIZE; return SOCKET_ERROR; } /* if a sockaddr was passed, wrap it in an mbuf and pas it into the * bowels of the BSD code; else assume this is a bound UDP socket * and this call came from t_send() below. */ if (to) /* sockaddr was passed */ { name = sockargs(to, tolen, MT_SONAME); if(name == NULL) { so->so_error = ENOMEM; return SOCKET_ERROR; } } else /* hope user called bind() first... */ name = NULL; sendlen = len; LOCK_NET_RESOURCE(NET_RESID); err = sosend (so, name, buf, &sendlen, flags); if (name) m_freem(name); UNLOCK_NET_RESOURCE(NET_RESID); if (err != 0) { so->so_error = err; return SOCKET_ERROR; } return (len - sendlen); }
long t_accept(long s, struct sockaddr * addr, int * addrlen) { #ifdef SOCKDEBUG char logbuf[10]; #endif struct socket * so; struct mbuf * nam; so = LONG2SO(s); SOC_CHECK(so); DOMAIN_CHECK(so, *addrlen); so->so_error = 0; INET_TRACE (INETM_SOCKET, ("INET:accept:so %x so_qlen %d so_state %x\n", so, so->so_qlen, so->so_state)); if ((so->so_options & SO_ACCEPTCONN) == 0) { so->so_error = EINVAL; #ifdef SOCKDEBUG sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { so->so_error = EWOULDBLOCK; #ifdef SOCKDEBUG sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } LOCK_NET_RESOURCE(NET_RESID); while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { so->so_error = ECONNABORTED; UNLOCK_NET_RESOURCE(NET_RESID); return SOCKET_ERROR; } tcp_sleep ((char *)&so->so_timeo); } if (so->so_error) { #ifdef SOCKDEBUG sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif UNLOCK_NET_RESOURCE(NET_RESID); return SOCKET_ERROR; } nam = m_getwithdata (MT_SONAME, sizeof (struct sockaddr)); if (nam == NULL) { UNLOCK_NET_RESOURCE(NET_RESID); so->so_error = ENOMEM; #ifdef SOCKDEBUG sprintf(logbuf, "t_accept[%d]: %d", __LINE__, so->so_error); glog_with_type(LOG_TYPE_DEBUG, logbuf, 1); #endif return SOCKET_ERROR; } { struct socket *aso = so->so_q; if (soqremque (aso, 1) == 0) panic("accept"); so = aso; } (void)soaccept (so, nam); #ifdef TRACE_DEBUG { struct sockaddr_in *sin; sin = mtod(nam, struct sockaddr_in *); INET_TRACE (INETM_SOCKET, ("INET:accept:done so %lx port %d addr %lx\n", so, sin->sin_port, sin->sin_addr.s_addr)); } #endif /* TRACE_INET */ /* return the addressing info in the passed structure */ if (addr != NULL) MEMCPY(addr, nam->m_data, *addrlen); m_freem (nam); UNLOCK_NET_RESOURCE(NET_RESID); SOC_RANGE(so); return SO2LONG(so); }
int t_setsockopt(long s, int level, int name, void * arg, int arglen) { struct socket * so; int err; so = LONG2SO(s); SOC_CHECK(so); USE_ARG(arglen); LOCK_NET_RESOURCE (NET_RESID); so->so_error = 0; INET_TRACE (INETM_SOCKET, ("INET: setsockopt: name %x val %x valsize %d\n", name, val)); /* is it a level IP_OPTIONS call? */ if (level != IP_OPTIONS) { if ((err = sosetopt (so, name, arg)) != 0) { so->so_error = err; UNLOCK_NET_RESOURCE (NET_RESID); return SOCKET_ERROR; } } else { /* level 1 options are for the IP packet level. * the info is carried in the socket CB, then put * into the PACKET. */ if (!so->so_optsPack) { so->so_optsPack = (struct ip_socopts *) SOCOPT_ALLOC (sizeof(struct ip_socopts *)); if (!so->so_optsPack) { so->so_error = ENOMEM; UNLOCK_NET_RESOURCE (NET_RESID); return SOCKET_ERROR; } } if (name == IP_TTL_OPT) so->so_optsPack->ip_ttl = (u_char)(*(int *)arg); else if (name == IP_TOS) so->so_optsPack->ip_tos = (u_char)(*(int *)arg); else if (name == IP_SCOPEID) so->so_optsPack->ip_scopeid = (u_char)(*(u_int *)arg); else { UNLOCK_NET_RESOURCE (NET_RESID); return SOCKET_ERROR; } } UNLOCK_NET_RESOURCE (NET_RESID); return 0; }
static int t_getname(long s, struct sockaddr * addr, int * addrlen, int opcode) { struct socket * so; struct mbuf * m; int err; so = LONG2SO(s); SOC_CHECK(so); so->so_error = 0; INET_TRACE (INETM_SOCKET, ("INET:get[sock|peer]name so %x\n", so)); if((opcode == PRU_PEERADDR) && (so->so_state & SS_ISCONNECTED) == 0) { so->so_error = ENOTCONN; return SOCKET_ERROR; } LOCK_NET_RESOURCE(NET_RESID); m = m_getwithdata (MT_SONAME, sizeof (struct sockaddr)); if (m == NULL) { so->so_error = ENOMEM; UNLOCK_NET_RESOURCE(NET_RESID); return SOCKET_ERROR; } so->so_req = opcode; if ((err = (*so->so_proto->pr_usrreq)(so, 0, m)) != 0) goto bad; #ifdef IP_V4 if(so->so_domain == AF_INET) { if(*addrlen < sizeof(struct sockaddr_in)) { dtrap(); /* programming error */ m_freem(m); UNLOCK_NET_RESOURCE(NET_RESID); return EINVAL; } MEMCPY(addr, m->m_data, sizeof(struct sockaddr_in)); *addrlen = sizeof(struct sockaddr_in); } #endif /* IP_V4 */ #ifdef IP_V6 if(so->so_domain == AF_INET6) { if(*addrlen < sizeof(struct sockaddr_in6)) { dtrap(); /* programming error */ m_freem(m); UNLOCK_NET_RESOURCE(NET_RESID); return EINVAL; } MEMCPY(addr, m->m_data, sizeof(struct sockaddr_in6)); *addrlen = sizeof(struct sockaddr_in6); } #endif /* IP_V6 */ bad: m_freem(m); UNLOCK_NET_RESOURCE(NET_RESID); if (err) { so->so_error = err; return SOCKET_ERROR; } return 0; }
int t_connect(long s, struct sockaddr * addr, int addrlen) { struct socket * so; struct mbuf * nam; so = LONG2SO(s); SOC_CHECK(so); DOMAIN_CHECK(so, addrlen); #ifdef NB_CONNECT /* need to test non blocking connect bits in case this is a poll of a previous request */ if (so->so_state & SS_NBIO) { if (so->so_state & SS_ISCONNECTING) /* still trying */ { so->so_error = EINPROGRESS; return SOCKET_ERROR; } if (so->so_state & SS_ISCONNECTED) /* connected OK */ { so->so_error = 0; return 0; } if (so->so_state & SS_WASCONNECTING) { so->so_state &= ~SS_WASCONNECTING; if (so->so_error) /* connect error - maybe timeout */ return SOCKET_ERROR; } } #endif /* NB_CONNECT */ so->so_error = 0; if ((nam = sockargs (addr, addrlen, MT_SONAME)) == NULL) { so->so_error = ENOMEM; return SOCKET_ERROR; } #ifdef TRACE_DEBUG { struct sockaddr_in *sin = (struct sockaddr_in *)uap->sap; INET_TRACE (INETM_SOCKET, ("INET: connect, port %d addr %lx\n", sin->sin_port, sin->sin_addr.s_addr)); } #endif /* TRACE_DEBUG */ LOCK_NET_RESOURCE(NET_RESID); if ((so->so_error = soconnect (so, nam)) != 0) goto bad; #ifdef NB_CONNECT /* need to test non blocking connect bits after soconnect() call */ if ((so->so_state & SS_NBIO)&& (so->so_state & SS_ISCONNECTING)) { so->so_error = EINPROGRESS; goto bad; } #endif /* NB_CONNECT */ INET_TRACE (INETM_SOCKET, ("INET: connect, so %x so_state %x so_error %d\n", so, so->so_state, so->so_error)); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { tcp_sleep ((char *)&so->so_timeo); } bad: if (so->so_error != EINPROGRESS) so->so_state &= ~(SS_ISCONNECTING|SS_WASCONNECTING); m_freem (nam); UNLOCK_NET_RESOURCE(NET_RESID); if (so->so_error) { /* printf("t_connect(): so_error = %d\n", so->so_error);*/ return SOCKET_ERROR; } return 0; }