--- a/packages/net/bsd_tcpip/current/ChangeLog +++ b/packages/net/bsd_tcpip/current/ChangeLog @@ -1,5 +1,11 @@ +2010-01-29 Cameron Taylor + + * src//sys/kern/sockio.c: free socket for connection closed while + on the accept queue. Also don't leak the error'd socket handle, + fix checks for NULL anamelen and error on copyout. + 2009-07-22 John Dallaway * include/sys/cdefs.h: Silence undefined macro warning reported by Jay Foster. --- a/packages/net/bsd_tcpip/current/src/sys/kern/sockio.c +++ b/packages/net/bsd_tcpip/current/src/sys/kern/sockio.c @@ -288,18 +288,15 @@ static int bsd_accept(cyg_file *fp, cyg_file *new_fp, struct sockaddr *name, socklen_t *anamelen) { - socklen_t namelen = 0; + socklen_t namelen; int error = 0, s; struct socket *head, *so; struct sockaddr *sa; - if( anamelen != NULL) - namelen = *anamelen; - s = splsoftnet(); head = (struct socket *)fp->f_data; if ((head->so_options & SO_ACCEPTCONN) == 0) { splx(s); @@ -340,108 +337,58 @@ */ so = TAILQ_FIRST(&head->so_comp); TAILQ_REMOVE(&head->so_comp, so, so_list); head->so_qlen--; -#if 0 // FIXME - fflag = lfp->f_flag; - error = falloc(p, &nfp, &fd); - if (error) { - /* - * Probably ran out of file descriptors. Put the - * unaccepted connection back onto the queue and - * do another wakeup so some other process might - * have a chance at it. - */ - TAILQ_INSERT_HEAD(&head->so_comp, so, so_list); - head->so_qlen++; - wakeup_one(&head->so_timeo); - splx(s); - goto done; - } - fhold(nfp); - p->p_retval[0] = fd; - - /* connection has been removed from the listen queue */ - KNOTE(&head->so_rcv.sb_sel.si_note, 0); -#endif - so->so_state &= ~SS_COMP; so->so_head = NULL; cyg_selinit(&so->so_rcv.sb_sel); cyg_selinit(&so->so_snd.sb_sel); - new_fp->f_type = DTYPE_SOCKET; - new_fp->f_flag |= FREAD|FWRITE; - new_fp->f_offset = 0; - new_fp->f_ops = &bsd_sock_fileops; - new_fp->f_data = (CYG_ADDRWORD)so; - new_fp->f_xops = (CYG_ADDRWORD)&bsd_sockops; - - sa = 0; + sa = NULL; error = soaccept(so, &sa); if (error) { + /* If the socket cannot be accepted, then it must be closed and freed */ + soclose(so); /* * return a namelen of zero for older code which might * ignore the return value from accept. */ - if (name != NULL) { + if (anamelen != NULL) { *anamelen = 0; } - goto noconnection; } - if (sa == NULL) { - namelen = 0; - if (name) - goto gotnoname; - splx(s); - error = 0; - goto done; - } - if (name) { - if (namelen > sa->sa_len) - namelen = sa->sa_len; + else { + new_fp->f_type = DTYPE_SOCKET; + new_fp->f_flag |= FREAD|FWRITE; + new_fp->f_offset = 0; + new_fp->f_ops = &bsd_sock_fileops; + new_fp->f_data = (CYG_ADDRWORD)so; + new_fp->f_xops = (CYG_ADDRWORD)&bsd_sockops; + + if (sa == NULL) { + if (anamelen) { + *anamelen = 0; + } + } + else if (name != NULL && anamelen != NULL) { + namelen = *anamelen; + + if (namelen > sa->sa_len) + namelen = sa->sa_len; #ifdef COMPAT_OLDSOCK - if (compat) - ((struct osockaddr *)sa)->sa_family = sa->sa_family; + if (compat) + ((struct osockaddr *)sa)->sa_family = sa->sa_family; #endif - error = copyout(sa, (caddr_t)name, namelen); - if (!error) -gotnoname: - *anamelen = namelen; - } -noconnection: - -#if 0 // FIXME - /* - * close the new descriptor, assuming someone hasn't ripped it - * out from under us. - */ - if (error) { - if (fdp->fd_ofiles[fd] == nfp) { - fdp->fd_ofiles[fd] = NULL; - fdrop(nfp, p); - } - } - splx(s); + memcpy((caddr_t)name, sa, namelen); + } + } - /* - * Release explicitly held references before returning. - */ -done: - if (nfp != NULL) - fdrop(nfp, p); - fdrop(lfp, p); - return (error); - m_freem(nam); -#else - done: splx(s); if (sa) FREE(sa, M_SONAME); -#endif return (error); } // -------------------------------------------------------------------------