Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/uipc_socket.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/uipc_socket.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.231 retrieving revision 1.251 diff -u -p -r1.231 -r1.251 --- src/sys/kern/uipc_socket.c 2014/08/05 05:24:26 1.231 +++ src/sys/kern/uipc_socket.c 2016/10/10 01:22:51 1.251 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_socket.c,v 1.231 2014/08/05 05:24:26 rtr Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.251 2016/10/10 01:22:51 dholland Exp $ */ /*- * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -71,14 +71,17 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.231 2014/08/05 05:24:26 rtr Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.251 2016/10/10 01:22:51 dholland Exp $"); +#ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" #include "opt_sock_counters.h" #include "opt_sosend_loan.h" #include "opt_mbuftrace.h" #include "opt_somaxkva.h" #include "opt_multiprocessor.h" /* XXX */ +#include "opt_sctp.h" +#endif #include #include @@ -343,7 +346,7 @@ sosend_loan(struct socket *so, struct ui int i; if (VMSPACE_IS_KERNEL_P(uio->uio_vmspace)) - return (0); + return 0L; if (iov->iov_len < (size_t) space) space = iov->iov_len; @@ -359,13 +362,13 @@ sosend_loan(struct socket *so, struct ui lva = sokvaalloc(sva, len, so); if (lva == 0) - return 0; + return 0L; error = uvm_loan(&uio->uio_vmspace->vm_map, sva, len, m->m_ext.ext_pgs, UVM_LOAN_TOPAGE); if (error) { sokvafree(lva, len); - return (0); + return 0L; } for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE) @@ -600,7 +603,7 @@ fsocreate(int domain, struct socket **so if (flags & SOCK_NONBLOCK) { so->so_state |= SS_NBIO; } - fp->f_data = so; + fp->f_socket = so; fd_affix(curproc, fp, fd); if (sop != NULL) { @@ -624,11 +627,15 @@ sofamily(const struct socket *so) } int -sobind(struct socket *so, struct mbuf *nam, struct lwp *l) +sobind(struct socket *so, struct sockaddr *nam, struct lwp *l) { int error; solock(so); + if (nam->sa_family != so->so_proto->pr_domain->dom_family) { + sounlock(so); + return EAFNOSUPPORT; + } error = (*so->so_proto->pr_usrreqs->pr_bind)(so, nam, l); sounlock(so); return error; @@ -638,6 +645,7 @@ int solisten(struct socket *so, int backlog, struct lwp *l) { int error; + short oldopt, oldqlimit; solock(so); if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | @@ -645,16 +653,21 @@ solisten(struct socket *so, int backlog, sounlock(so); return EINVAL; } - error = (*so->so_proto->pr_usrreqs->pr_listen)(so, l); - if (error != 0) { - sounlock(so); - return error; - } + oldopt = so->so_options; + oldqlimit = so->so_qlimit; if (TAILQ_EMPTY(&so->so_q)) so->so_options |= SO_ACCEPTCONN; if (backlog < 0) backlog = 0; so->so_qlimit = min(backlog, somaxconn); + + error = (*so->so_proto->pr_usrreqs->pr_listen)(so, l); + if (error != 0) { + so->so_options = oldopt; + so->so_qlimit = oldqlimit; + sounlock(so); + return error; + } sounlock(so); return 0; } @@ -789,7 +802,7 @@ soabort(struct socket *so) } int -soaccept(struct socket *so, struct mbuf *nam) +soaccept(struct socket *so, struct sockaddr *nam) { int error; @@ -807,7 +820,7 @@ soaccept(struct socket *so, struct mbuf } int -soconnect(struct socket *so, struct mbuf *nam, struct lwp *l) +soconnect(struct socket *so, struct sockaddr *nam, struct lwp *l) { int error; @@ -823,10 +836,14 @@ soconnect(struct socket *so, struct mbuf */ if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) && ((so->so_proto->pr_flags & PR_CONNREQUIRED) || - (error = sodisconnect(so)))) + (error = sodisconnect(so)))) { error = EISCONN; - else + } else { + if (nam->sa_family != so->so_proto->pr_domain->dom_family) { + return EAFNOSUPPORT; + } error = (*so->so_proto->pr_usrreqs->pr_connect)(so, nam, l); + } return error; } @@ -836,8 +853,7 @@ soconnect2(struct socket *so1, struct so { KASSERT(solocked2(so1, so2)); - return (*so1->so_proto->pr_usrreqs->pr_generic)(so1, - PRU_CONNECT2, NULL, (struct mbuf *)so2, NULL, NULL); + return (*so1->so_proto->pr_usrreqs->pr_connect2)(so1, so2); } int @@ -876,8 +892,8 @@ sodisconnect(struct socket *so) * Data and control buffers are freed on return. */ int -sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top, - struct mbuf *control, int flags, struct lwp *l) +sosend(struct socket *so, struct sockaddr *addr, struct uio *uio, + struct mbuf *top, struct mbuf *control, int flags, struct lwp *l) { struct mbuf **mp, *m; long space, len, resid, clen, mlen; @@ -934,7 +950,7 @@ sosend(struct socket *so, struct mbuf *a error = ENOTCONN; goto release; } - } else if (addr == 0) { + } else if (addr == NULL) { error = EDESTADDRREQ; goto release; } @@ -982,7 +998,7 @@ sosend(struct socket *so, struct mbuf *a m = m_gethdr(M_WAIT, MT_DATA); mlen = MHLEN; m->m_pkthdr.len = 0; - m->m_pkthdr.rcvif = NULL; + m_reset_rcvif(m); } else { m = m_get(M_WAIT, MT_DATA); mlen = MLEN; @@ -992,7 +1008,7 @@ sosend(struct socket *so, struct mbuf *a uio->uio_iov->iov_len >= sock_loan_thresh && space >= sock_loan_thresh && (len = sosend_loan(so, uio, m, - space)) != 0) { + space)) != 0L) { SOSEND_COUNTER_INCR(&sosend_loan_big); space -= len; goto have_data; @@ -1048,12 +1064,13 @@ sosend(struct socket *so, struct mbuf *a so->so_options |= SO_DONTROUTE; if (resid > 0) so->so_state |= SS_MORETOCOME; - if (flags & MSG_OOB) + if (flags & MSG_OOB) { error = (*so->so_proto->pr_usrreqs->pr_sendoob)(so, top, control); - else - error = (*so->so_proto->pr_usrreqs->pr_generic)(so, - PRU_SEND, top, addr, control, curlwp); + } else { + error = (*so->so_proto->pr_usrreqs->pr_send)(so, + top, addr, control, l); + } if (dontroute) so->so_options &= ~SO_DONTROUTE; if (resid > 0) @@ -1158,7 +1175,7 @@ soreceive(struct socket *so, struct mbuf if (controlp != NULL) *controlp = NULL; if (flagsp != NULL) - flags = *flagsp &~ MSG_EOR; + flags = *flagsp & ~MSG_EOR; else flags = 0; @@ -1307,12 +1324,35 @@ soreceive(struct socket *so, struct mbuf m->m_next = NULL; m = so->so_rcv.sb_mb; } else { - MFREE(m, so->so_rcv.sb_mb); - m = so->so_rcv.sb_mb; + m = so->so_rcv.sb_mb = m_free(m); } sbsync(&so->so_rcv, nextrecord); } } + if (pr->pr_flags & PR_ADDR_OPT) { + /* + * For SCTP we may be getting a + * whole message OR a partial delivery. + */ + if (m->m_type == MT_SONAME) { + orig_resid = 0; + if (flags & MSG_PEEK) { + if (paddr) + *paddr = m_copy(m, 0, m->m_len); + m = m->m_next; + } else { + sbfree(&so->so_rcv, m); + if (paddr) { + *paddr = m; + so->so_rcv.sb_mb = m->m_next; + m->m_next = 0; + m = so->so_rcv.sb_mb; + } else { + m = so->so_rcv.sb_mb = m_free(m); + } + } + } + } /* * Process one or more MT_CONTROL mbufs present before any data mbufs @@ -1447,6 +1487,10 @@ soreceive(struct socket *so, struct mbuf if (len == m->m_len - moff) { if (m->m_flags & M_EOR) flags |= MSG_EOR; +#ifdef SCTP + if (m->m_flags & M_NOTIFICATION) + flags |= MSG_NOTIFICATION; +#endif /* SCTP */ if (flags & MSG_PEEK) { m = m->m_next; moff = 0; @@ -1459,8 +1503,7 @@ soreceive(struct socket *so, struct mbuf so->so_rcv.sb_mb = m = m->m_next; *mp = NULL; } else { - MFREE(m, so->so_rcv.sb_mb); - m = so->so_rcv.sb_mb; + m = so->so_rcv.sb_mb = m_free(m); } /* * If m != NULL, we also know that @@ -1532,8 +1575,7 @@ soreceive(struct socket *so, struct mbuf * get it filled again. */ if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb) - (*pr->pr_usrreqs->pr_generic)(so, PRU_RCVD, - NULL, (struct mbuf *)(long)flags, NULL, l); + (*pr->pr_usrreqs->pr_rcvd)(so, flags, l); SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); if (wakeup_state & SS_RESTARTSYS) @@ -1574,8 +1616,7 @@ soreceive(struct socket *so, struct mbuf SBLASTRECORDCHK(&so->so_rcv, "soreceive 4"); SBLASTMBUFCHK(&so->so_rcv, "soreceive 4"); if (pr->pr_flags & PR_WANTRCVD && so->so_pcb) - (*pr->pr_usrreqs->pr_generic)(so, PRU_RCVD, NULL, - (struct mbuf *)(long)flags, NULL, l); + (*pr->pr_usrreqs->pr_rcvd)(so, flags, l); } if (orig_resid == uio->uio_resid && orig_resid && (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) { @@ -2176,7 +2217,7 @@ filt_sordetach(struct knote *kn) { struct socket *so; - so = ((file_t *)kn->kn_obj)->f_data; + so = ((file_t *)kn->kn_obj)->f_socket; solock(so); SLIST_REMOVE(&so->so_rcv.sb_sel.sel_klist, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_rcv.sb_sel.sel_klist)) @@ -2191,7 +2232,7 @@ filt_soread(struct knote *kn, long hint) struct socket *so; int rv; - so = ((file_t *)kn->kn_obj)->f_data; + so = ((file_t *)kn->kn_obj)->f_socket; if (hint != NOTE_SUBMIT) solock(so); kn->kn_data = so->so_rcv.sb_cc; @@ -2215,7 +2256,7 @@ filt_sowdetach(struct knote *kn) { struct socket *so; - so = ((file_t *)kn->kn_obj)->f_data; + so = ((file_t *)kn->kn_obj)->f_socket; solock(so); SLIST_REMOVE(&so->so_snd.sb_sel.sel_klist, kn, knote, kn_selnext); if (SLIST_EMPTY(&so->so_snd.sb_sel.sel_klist)) @@ -2230,7 +2271,7 @@ filt_sowrite(struct knote *kn, long hint struct socket *so; int rv; - so = ((file_t *)kn->kn_obj)->f_data; + so = ((file_t *)kn->kn_obj)->f_socket; if (hint != NOTE_SUBMIT) solock(so); kn->kn_data = sbspace(&so->so_snd); @@ -2259,7 +2300,7 @@ filt_solisten(struct knote *kn, long hin struct socket *so; int rv; - so = ((file_t *)kn->kn_obj)->f_data; + so = ((file_t *)kn->kn_obj)->f_socket; /* * Set kn_data to number of incoming connections, not @@ -2287,7 +2328,7 @@ soo_kqfilter(struct file *fp, struct kno struct socket *so; struct sockbuf *sb; - so = ((file_t *)kn->kn_obj)->f_data; + so = ((file_t *)kn->kn_obj)->f_socket; solock(so); switch (kn->kn_filter) { case EVFILT_READ: