diff options
author | rwatson <rwatson@FreeBSD.org> | 2006-05-01 21:39:48 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2006-05-01 21:39:48 +0000 |
commit | 517c01ed07a72ed13f0bb2fb42f28481a270baa1 (patch) | |
tree | 83be6db8b0eecd150711c853a1d821724e10a937 /sys/netinet6 | |
parent | ca8d347695197fe6855a628e0325e9ab16820d5f (diff) | |
download | FreeBSD-src-517c01ed07a72ed13f0bb2fb42f28481a270baa1.zip FreeBSD-src-517c01ed07a72ed13f0bb2fb42f28481a270baa1.tar.gz |
Break out socket access control and delivery logic from udp6_input()
into its own function, udp6_append(). This mirrors a similar structure
in udp_input() and udp_append(), and makes the whole thing a lot more
readable.
While here, add missing inpcb locking in UDP6 input path.
Reviewed by: bz
MFC after: 3 months
Diffstat (limited to 'sys/netinet6')
-rw-r--r-- | sys/netinet6/udp6_usrreq.c | 151 |
1 files changed, 55 insertions, 96 deletions
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 7157845..7f398f7 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -119,12 +119,53 @@ extern struct protosw inetsw[]; static void udp6_detach __P((struct socket *so)); +static void +udp6_append(struct inpcb *in6p, struct mbuf *n, int off, + struct sockaddr_in6 *fromsa) +{ + struct socket *so; + struct mbuf *opts; + + /* XXXRW: Not yet: INP_LOCK_ASSERT(in6p); */ + +#if defined(IPSEC) || defined(FAST_IPSEC) + /* + * Check AH/ESP integrity. + */ + if (ipsec6_in_reject(n, in6p)) { + m_freem(n); +#ifdef IPSEC + ipsec6stat.in_polvio++; +#endif /* IPSEC */ + return; + } +#endif /*IPSEC || FAST_IPSEC*/ + + opts = NULL; + if (in6p->in6p_flags & IN6P_CONTROLOPTS || + in6p->inp_socket->so_options & SO_TIMESTAMP) + ip6_savecontrol(in6p, n, &opts); + m_adj(n, off + sizeof(struct udphdr)); + + so = in6p->inp_socket; + SOCKBUF_LOCK(&so->so_rcv); + if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)fromsa, n, + opts) == 0) { + SOCKBUF_UNLOCK(&so->so_rcv); + m_freem(n); + if (opts) + m_freem(opts); + udpstat.udps_fullsock++; + } else + sorwakeup_locked(so); +} + int udp6_input(mp, offp, proto) struct mbuf **mp; int *offp, proto; { - struct mbuf *m = *mp, *opts; + struct mbuf *m = *mp; register struct ip6_hdr *ip6; register struct udphdr *uh; register struct inpcb *in6p; @@ -132,8 +173,6 @@ udp6_input(mp, offp, proto) int plen, ulen; struct sockaddr_in6 fromsa; - opts = NULL; - ip6 = mtod(m, struct ip6_hdr *); if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { @@ -174,6 +213,12 @@ udp6_input(mp, offp, proto) goto bad_unlocked; } + /* + * Construct sockaddr format source address. + */ + init_sin6(&fromsa, m); + fromsa.sin6_port = uh->uh_sport; + INP_INFO_RLOCK(&udbinfo); if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { struct inpcb *last; @@ -205,11 +250,6 @@ udp6_input(mp, offp, proto) */ /* - * Construct sockaddr format source address. - */ - init_sin6(&fromsa, m); - fromsa.sin6_port = uh->uh_sport; - /* * KAME note: traditionally we dropped udpiphdr from mbuf here. * We need udphdr for IPsec processing so we do that later. */ @@ -242,40 +282,10 @@ udp6_input(mp, offp, proto) if (last != NULL) { struct mbuf *n; -#if defined(IPSEC) || defined(FAST_IPSEC) - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject(m, last)) { -#ifdef IPSEC - ipsec6stat.in_polvio++; -#endif /* IPSEC */ - /* do not inject data into pcb */ - } else -#endif /*IPSEC || FAST_IPSEC*/ if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { - /* - * KAME NOTE: do not - * m_copy(m, offset, ...) above. - * sbappendaddr() expects M_PKTHDR, - * and m_copy() will copy M_PKTHDR - * only if offset is 0. - */ - if (last->in6p_flags & IN6P_CONTROLOPTS - || last->in6p_socket->so_options & SO_TIMESTAMP) - ip6_savecontrol(last, n, &opts); - - m_adj(n, off + sizeof(struct udphdr)); - if (sbappendaddr(&last->in6p_socket->so_rcv, - (struct sockaddr *)&fromsa, - n, opts) == 0) { - m_freem(n); - if (opts) - m_freem(opts); - udpstat.udps_fullsock++; - } else - sorwakeup(last->in6p_socket); - opts = NULL; + INP_LOCK(in6p); + udp6_append(in6p, n, off, &fromsa); + INP_UNLOCK(in6p); } } last = in6p; @@ -302,29 +312,9 @@ udp6_input(mp, offp, proto) udpstat.udps_noportmcast++; goto bad; } -#if defined(IPSEC) || defined(FAST_IPSEC) - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject(m, last)) { -#ifdef IPSEC - ipsec6stat.in_polvio++; -#endif /* IPSEC */ - goto bad; - } -#endif /*IPSEC || FAST_IPSEC*/ - if (last->in6p_flags & IN6P_CONTROLOPTS - || last->in6p_socket->so_options & SO_TIMESTAMP) - ip6_savecontrol(last, m, &opts); - - m_adj(m, off + sizeof(struct udphdr)); - if (sbappendaddr(&last->in6p_socket->so_rcv, - (struct sockaddr *)&fromsa, - m, opts) == 0) { - udpstat.udps_fullsock++; - goto bad; - } - sorwakeup(last->in6p_socket); + INP_LOCK(last); + udp6_append(last, m, off, &fromsa); + INP_UNLOCK(last); INP_INFO_RUNLOCK(&udbinfo); return IPPROTO_DONE; } @@ -355,36 +345,7 @@ udp6_input(mp, offp, proto) return IPPROTO_DONE; } INP_LOCK(in6p); -#if defined(IPSEC) || defined(FAST_IPSEC) - /* - * Check AH/ESP integrity. - */ - if (ipsec6_in_reject(m, in6p)) { - INP_UNLOCK(in6p); -#ifdef IPSEC - ipsec6stat.in_polvio++; -#endif /* IPSEC */ - goto bad; - } -#endif /*IPSEC || FAST_IPSEC*/ - - /* - * Construct sockaddr format source address. - * Stuff source address and datagram in user buffer. - */ - init_sin6(&fromsa, m); - fromsa.sin6_port = uh->uh_sport; - if (in6p->in6p_flags & IN6P_CONTROLOPTS - || in6p->in6p_socket->so_options & SO_TIMESTAMP) - ip6_savecontrol(in6p, m, &opts); - m_adj(m, off + sizeof(struct udphdr)); - if (sbappendaddr(&in6p->in6p_socket->so_rcv, - (struct sockaddr *)&fromsa, m, opts) == 0) { - INP_UNLOCK(in6p); - udpstat.udps_fullsock++; - goto bad; - } - sorwakeup(in6p->in6p_socket); + udp6_append(in6p, m, off, &fromsa); INP_UNLOCK(in6p); INP_INFO_RUNLOCK(&udbinfo); return IPPROTO_DONE; @@ -393,8 +354,6 @@ bad: bad_unlocked: if (m) m_freem(m); - if (opts) - m_freem(opts); return IPPROTO_DONE; } |