--- //depot/projects/smpng/sys/kern/uipc_sockbuf.c 2008/09/17 20:27:47 +++ //depot/user/jhb/lock/kern/uipc_sockbuf.c 2008/09/30 18:25:15 @@ -615,45 +615,36 @@ /* * Append address and data, and optionally, control (ancillary) data to the * receive queue of a socket. If present, m0 must include a packet header - * with total length. Returns 0 if no space in sockbuf or insufficient - * mbufs. + * with total length. Returns 0 if no space in sockbuf. The sockaddr + * should be present in the MT_SONAME mbuf 'sa'. */ int -sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, - struct mbuf *m0, struct mbuf *control) +sbappendaddr_mbuf(struct sockbuf *sb, struct mbuf *sa, struct mbuf *m0, + struct mbuf *control) { - struct mbuf *m, *n, *nlast; - int space = asa->sa_len; + struct mbuf *n, *nlast; + int space = sa->m_len; SOCKBUF_LOCK_ASSERT(sb); if (m0 && (m0->m_flags & M_PKTHDR) == 0) - panic("sbappendaddr_locked"); + panic("sbappendaddr_mbuf"); if (m0) space += m0->m_pkthdr.len; space += m_length(control, &n); if (space > sbspace(sb)) return (0); -#if MSIZE <= 256 - if (asa->sa_len > MLEN) - return (0); -#endif - MGET(m, M_DONTWAIT, MT_SONAME); - if (m == 0) - return (0); - m->m_len = asa->sa_len; - bcopy(asa, mtod(m, caddr_t), asa->sa_len); if (n) n->m_next = m0; /* concatenate data to control */ else control = m0; - m->m_next = control; - for (n = m; n->m_next != NULL; n = n->m_next) + sa->m_next = control; + for (n = sa; n->m_next != NULL; n = n->m_next) sballoc(sb, n); sballoc(sb, n); nlast = n; - SBLINKRECORD(sb, m); + SBLINKRECORD(sb, sa); sb->sb_mbtail = nlast; SBLASTMBUFCHK(sb); @@ -669,6 +660,25 @@ * mbufs. */ int +sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, + struct mbuf *m0, struct mbuf *control) +{ + struct mbuf *m; + + SOCKBUF_LOCK_ASSERT(sb); + m = soputsockaddr(asa); + if (m == NULL) + return (0); + return (sbappendaddr_mbuf(sb, m, m0, control)); +} + +/* + * Append address and data, and optionally, control (ancillary) data to the + * receive queue of a socket. If present, m0 must include a packet header + * with total length. Returns 0 if no space in sockbuf or insufficient + * mbufs. + */ +int sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control) { --- //depot/projects/smpng/sys/kern/uipc_socket.c 2008/09/17 20:27:47 +++ //depot/user/jhb/lock/kern/uipc_socket.c 2008/09/30 18:25:15 @@ -3173,6 +3162,26 @@ } /* + * Make a copy of a sockaddr in an mbuf. + */ +struct mbuf * +soputsockaddr(const struct sockaddr *asa) +{ + struct mbuf *m; + +#if MSIZE <= 256 + if (asa->sa_len > MLEN) + return (NULL); +#endif + MGET(m, M_DONTWAIT, MT_SONAME); + if (m == NULL) + return (NULL); + m->m_len = asa->sa_len; + bcopy(asa, mtod(m, caddr_t), asa->sa_len); + return (m); +} + +/* * Create an external-format (``xsocket'') structure using the information in * the kernel-format socket structure pointed to by so. This is done to * reduce the spew of irrelevant information over this interface, to isolate --- //depot/projects/smpng/sys/netinet/udp_usrreq.c 2008/08/25 16:33:41 +++ //depot/user/jhb/lock/netinet/udp_usrreq.c 2008/09/30 18:31:17 @@ -192,7 +192,7 @@ { struct sockaddr *append_sa; struct socket *so; - struct mbuf *opts = 0; + struct mbuf *opts = 0, *msa; #ifdef INET6 struct sockaddr_in6 udp_in6; #endif @@ -213,15 +213,6 @@ return; } #endif - if (inp->inp_flags & INP_CONTROLOPTS || - inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) { -#ifdef INET6 - if (inp->inp_vflag & INP_IPV6) - (void)ip6_savecontrol_v4(inp, n, &opts, NULL); - else -#endif - ip_savecontrol(inp, &opts, ip, n); - } #ifdef INET6 if (inp->inp_vflag & INP_IPV6) { bzero(&udp_in6, sizeof(udp_in6)); @@ -232,13 +223,28 @@ } else #endif append_sa = (struct sockaddr *)udp_in; + msa = soputsockaddr(append_sa); + if (msa == NULL) { + m_freem(n); + return; + } + if (inp->inp_flags & INP_CONTROLOPTS || + inp->inp_socket->so_options & (SO_TIMESTAMP | SO_BINTIME)) { +#ifdef INET6 + if (inp->inp_vflag & INP_IPV6) + (void)ip6_savecontrol_v4(inp, n, &opts, NULL); + else +#endif + ip_savecontrol(inp, &opts, ip, n); + } m_adj(n, off); so = inp->inp_socket; SOCKBUF_LOCK(&so->so_rcv); - if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) { + if (sbappendaddr_mbuf(&so->so_rcv, msa, n, opts) == 0) { SOCKBUF_UNLOCK(&so->so_rcv); m_freem(n); + m_freem(msa); if (opts) m_freem(opts); V_udpstat.udps_fullsock++; --- //depot/projects/smpng/sys/sys/sockbuf.h 2008/08/05 21:26:01 +++ //depot/user/jhb/lock/sys/sockbuf.h 2008/09/30 18:25:15 @@ -121,6 +121,8 @@ void sbappend_locked(struct sockbuf *sb, struct mbuf *m); void sbappendstream(struct sockbuf *sb, struct mbuf *m); void sbappendstream_locked(struct sockbuf *sb, struct mbuf *m); +int sbappendaddr_mbuf(struct sockbuf *sb, struct mbuf *sa, struct mbuf *m0, + struct mbuf *control); int sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control); int sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa, --- //depot/projects/smpng/sys/sys/socketvar.h 2008/08/05 21:26:01 +++ //depot/user/jhb/lock/sys/socketvar.h 2008/09/30 18:25:15 @@ -332,6 +332,7 @@ struct thread *td); int sopoll_generic(struct socket *so, int events, struct ucred *active_cred, struct thread *td); +struct mbuf *soputsockaddr(const struct sockaddr *asa); int soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp); int soreceive_dgram(struct socket *so, struct sockaddr **paddr,