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.235.2.3 retrieving revision 1.259.2.2 diff -u -p -r1.235.2.3 -r1.259.2.2 --- src/sys/kern/uipc_socket.c 2015/09/22 12:06:07 1.235.2.3 +++ src/sys/kern/uipc_socket.c 2018/05/02 07:20:22 1.259.2.2 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_socket.c,v 1.235.2.3 2015/09/22 12:06:07 skrll Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.259.2.2 2018/05/02 07:20:22 pgoyette Exp $ */ /*- * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -71,7 +71,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.235.2.3 2015/09/22 12:06:07 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.259.2.2 2018/05/02 07:20:22 pgoyette Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -80,6 +80,7 @@ __KERNEL_RCSID(0, "$NetBSD: uipc_socket. #include "opt_mbuftrace.h" #include "opt_somaxkva.h" #include "opt_multiprocessor.h" /* XXX */ +#include "opt_sctp.h" #endif #include @@ -294,7 +295,8 @@ sopendfree_thread(void *v) for (; m != NULL; m = next) { next = m->m_next; - KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0); + KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES)) == + 0); KASSERT(m->m_ext.ext_refcnt == 0); rv += m->m_ext.ext_size; @@ -433,17 +435,20 @@ socket_listener_cb(kauth_cred_t cred, ka case KAUTH_REQ_NETWORK_SOCKET_OPEN: /* We allow "raw" routing/bluetooth sockets to anyone. */ - if ((u_long)arg1 == PF_ROUTE || (u_long)arg1 == PF_OROUTE - || (u_long)arg1 == PF_BLUETOOTH) { + switch ((u_long)arg1) { + case PF_ROUTE: + case PF_OROUTE: + case PF_BLUETOOTH: + case PF_CAN: result = KAUTH_RESULT_ALLOW; - } else { + break; + default: /* Privileged, let secmodel handle this. */ if ((u_long)arg2 == SOCK_RAW) break; + result = KAUTH_RESULT_ALLOW; + break; } - - result = KAUTH_RESULT_ALLOW; - break; case KAUTH_REQ_NETWORK_SOCKET_CANSEE: @@ -644,6 +649,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 | @@ -651,16 +657,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; } @@ -991,7 +1002,7 @@ sosend(struct socket *so, struct sockadd 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; @@ -1058,8 +1069,8 @@ sosend(struct socket *so, struct sockadd if (resid > 0) so->so_state |= SS_MORETOCOME; if (flags & MSG_OOB) { - error = (*so->so_proto->pr_usrreqs->pr_sendoob)(so, - top, control); + error = (*so->so_proto->pr_usrreqs->pr_sendoob)( + so, top, control); } else { error = (*so->so_proto->pr_usrreqs->pr_send)(so, top, addr, control, l); @@ -1233,8 +1244,7 @@ soreceive(struct socket *so, struct mbuf if (m != NULL) goto dontblock; error = so->so_error; - if ((flags & MSG_PEEK) == 0) - so->so_error = 0; + so->so_error = 0; goto release; } if (so->so_state & SS_CANTRCVMORE) { @@ -1306,7 +1316,7 @@ soreceive(struct socket *so, struct mbuf orig_resid = 0; if (flags & MSG_PEEK) { if (paddr) - *paddr = m_copy(m, 0, m->m_len); + *paddr = m_copym(m, 0, m->m_len, M_DONTWAIT); m = m->m_next; } else { sbfree(&so->so_rcv, m); @@ -1317,12 +1327,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_copym(m, 0, m->m_len, M_DONTWAIT); + 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 @@ -1337,7 +1370,7 @@ soreceive(struct socket *so, struct mbuf do { if (flags & MSG_PEEK) { if (controlp != NULL) { - *controlp = m_copy(m, 0, m->m_len); + *controlp = m_copym(m, 0, m->m_len, M_DONTWAIT); controlp = &(*controlp)->m_next; } m = m->m_next; @@ -1377,7 +1410,7 @@ soreceive(struct socket *so, struct mbuf */ if (dom->dom_dispose != NULL && type == SCM_RIGHTS) { - sounlock(so); + sounlock(so); (*dom->dom_dispose)(cm); solock(so); } @@ -1457,6 +1490,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; @@ -1469,8 +1506,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 @@ -1688,22 +1724,22 @@ sosetopt1(struct socket *so, const struc KASSERT(solocked(so)); break; - case SO_LINGER: - error = sockopt_get(sopt, &l, sizeof(l)); + case SO_LINGER: + error = sockopt_get(sopt, &l, sizeof(l)); solock(so); - if (error) - break; - if (l.l_linger < 0 || l.l_linger > USHRT_MAX || - l.l_linger > (INT_MAX / hz)) { + if (error) + break; + if (l.l_linger < 0 || l.l_linger > USHRT_MAX || + l.l_linger > (INT_MAX / hz)) { error = EDOM; break; } - so->so_linger = l.l_linger; - if (l.l_onoff) - so->so_options |= SO_LINGER; - else - so->so_options &= ~SO_LINGER; - break; + so->so_linger = l.l_linger; + if (l.l_onoff) + so->so_options |= SO_LINGER; + else + so->so_options &= ~SO_LINGER; + break; case SO_DEBUG: case SO_KEEPALIVE: @@ -2059,7 +2095,7 @@ sockopt_destroy(struct sockopt *sopt) /* * set sockopt value * - value is copied into sockopt - * - memory is allocated when necessary, will not sleep + * - memory is allocated when necessary, will not sleep */ int sockopt_set(struct sockopt *sopt, const void *buf, size_t len) @@ -2072,8 +2108,12 @@ sockopt_set(struct sockopt *sopt, const return error; } - KASSERT(sopt->sopt_size == len); + if (sopt->sopt_size < len) + return EINVAL; + memcpy(sopt->sopt_data, buf, len); + sopt->sopt_retsize = len; + return 0; } @@ -2132,9 +2172,12 @@ sockopt_setmbuf(struct sockopt *sopt, st return error; } - KASSERT(sopt->sopt_size == len); + if (sopt->sopt_size < len) + return EINVAL; + m_copydata(m, 0, len, sopt->sopt_data); m_freem(m); + sopt->sopt_retsize = len; return 0; } @@ -2207,7 +2250,7 @@ filt_soread(struct knote *kn, long hint) kn->kn_flags |= EV_EOF; kn->kn_fflags = so->so_error; rv = 1; - } else if (so->so_error) /* temporary udp error */ + } else if (so->so_error) rv = 1; else if (kn->kn_sfflags & NOTE_LOWAT) rv = (kn->kn_data >= kn->kn_sdata); @@ -2246,7 +2289,7 @@ filt_sowrite(struct knote *kn, long hint kn->kn_flags |= EV_EOF; kn->kn_fflags = so->so_error; rv = 1; - } else if (so->so_error) /* temporary udp error */ + } else if (so->so_error) rv = 1; else if (((so->so_state & SS_ISCONNECTED) == 0) && (so->so_proto->pr_flags & PR_CONNREQUIRED)) @@ -2282,12 +2325,26 @@ filt_solisten(struct knote *kn, long hin return rv; } -static const struct filterops solisten_filtops = - { 1, NULL, filt_sordetach, filt_solisten }; -static const struct filterops soread_filtops = - { 1, NULL, filt_sordetach, filt_soread }; -static const struct filterops sowrite_filtops = - { 1, NULL, filt_sowdetach, filt_sowrite }; +static const struct filterops solisten_filtops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = filt_sordetach, + .f_event = filt_solisten, +}; + +static const struct filterops soread_filtops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = filt_sordetach, + .f_event = filt_soread, +}; + +static const struct filterops sowrite_filtops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = filt_sowdetach, + .f_event = filt_sowrite, +}; int soo_kqfilter(struct file *fp, struct knote *kn) @@ -2373,6 +2430,33 @@ sopoll(struct socket *so, int events) return revents; } +struct mbuf ** +sbsavetimestamp(int opt, struct mbuf **mp) +{ + struct timeval tv; + microtime(&tv); + +#ifdef SO_OTIMESTAMP + if (opt & SO_OTIMESTAMP) { + struct timeval50 tv50; + + timeval_to_timeval50(&tv, &tv50); + *mp = sbcreatecontrol(&tv50, sizeof(tv50), + SCM_OTIMESTAMP, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + } else +#endif + + if (opt & SO_TIMESTAMP) { + *mp = sbcreatecontrol(&tv, sizeof(tv), + SCM_TIMESTAMP, SOL_SOCKET); + if (*mp) + mp = &(*mp)->m_next; + } + return mp; +} + #include