Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet6/udp6_usrreq.c
Show First 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | if (sbappendaddr_locked(&so->so_rcv, (struct sockaddr *)&fromsa[0], n, | ||||
if (opts) | if (opts) | ||||
m_freem(opts); | m_freem(opts); | ||||
UDPSTAT_INC(udps_fullsock); | UDPSTAT_INC(udps_fullsock); | ||||
} else | } else | ||||
sorwakeup_locked(so); | sorwakeup_locked(so); | ||||
return (0); | return (0); | ||||
} | } | ||||
static bool | |||||
udp6_inpcb_eq_ip6_uh(struct inpcb *inp, struct ip6_hdr *ip6, struct udphdr *uh) | |||||
{ | |||||
if ((inp->inp_vflag & INP_IPV6) == 0) | |||||
return false; | |||||
if (inp->inp_lport != uh->uh_dport) | |||||
return false; | |||||
if (inp->inp_fport != 0 && | |||||
inp->inp_fport != uh->uh_sport) | |||||
return false; | |||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { | |||||
if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, | |||||
&ip6->ip6_dst)) | |||||
return false; | |||||
} | |||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | |||||
if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, | |||||
&ip6->ip6_src) || | |||||
inp->inp_fport != uh->uh_sport) | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
int | int | ||||
udp6_input(struct mbuf **mp, int *offp, int proto) | udp6_input(struct mbuf **mp, int *offp, int proto) | ||||
{ | { | ||||
struct mbuf *m = *mp; | struct mbuf *m = *mp; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct udphdr *uh; | struct udphdr *uh; | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | ||||
/* | /* | ||||
* KAME note: traditionally we dropped udpiphdr from mbuf | * KAME note: traditionally we dropped udpiphdr from mbuf | ||||
* here. We need udphdr for IPsec processing so we do that | * here. We need udphdr for IPsec processing so we do that | ||||
* later. | * later. | ||||
*/ | */ | ||||
pcblist = udp_get_pcblist(nxt); | pcblist = udp_get_pcblist(nxt); | ||||
last = NULL; | last = NULL; | ||||
CK_LIST_FOREACH(inp, pcblist, inp_list) { | CK_LIST_FOREACH(inp, pcblist, inp_list) { | ||||
if ((inp->inp_vflag & INP_IPV6) == 0) | if (!udp6_inpcb_eq_ip6_uh(inp, ip6, uh)) | ||||
continue; | continue; | ||||
if (inp->inp_lport != uh->uh_dport) | |||||
continue; | |||||
if (inp->inp_fport != 0 && | |||||
inp->inp_fport != uh->uh_sport) | |||||
continue; | |||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { | |||||
if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, | |||||
&ip6->ip6_dst)) | |||||
continue; | |||||
} | |||||
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { | |||||
if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, | |||||
&ip6->ip6_src) || | |||||
inp->inp_fport != uh->uh_sport) | |||||
continue; | |||||
} | |||||
/* | /* | ||||
* XXXRW: Because we weren't holding either the inpcb | |||||
* or the hash lock when we checked for a match | |||||
* before, we should probably recheck now that the | |||||
* inpcb lock is (supposed to be) held. | |||||
*/ | |||||
/* | |||||
* Handle socket delivery policy for any-source | * Handle socket delivery policy for any-source | ||||
* and source-specific multicast. [RFC3678] | * and source-specific multicast. [RFC3678] | ||||
*/ | */ | ||||
imo = inp->in6p_moptions; | imo = inp->in6p_moptions; | ||||
if (imo && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | if (imo && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | ||||
struct sockaddr_in6 mcaddr; | struct sockaddr_in6 mcaddr; | ||||
int blocked; | int blocked; | ||||
INP_RLOCK(inp); | INP_RLOCK(inp); | ||||
if (__predict_false(inp->inp_flags2 & INP_FREED)) { | if (__predict_false(inp->inp_flags2 & INP_FREED) || !udp6_inpcb_eq_ip6_uh(inp, ip6, uh)) { | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
continue; | continue; | ||||
} | } | ||||
bzero(&mcaddr, sizeof(struct sockaddr_in6)); | bzero(&mcaddr, sizeof(struct sockaddr_in6)); | ||||
mcaddr.sin6_len = sizeof(struct sockaddr_in6); | mcaddr.sin6_len = sizeof(struct sockaddr_in6); | ||||
mcaddr.sin6_family = AF_INET6; | mcaddr.sin6_family = AF_INET6; | ||||
mcaddr.sin6_addr = ip6->ip6_dst; | mcaddr.sin6_addr = ip6->ip6_dst; | ||||
▲ Show 20 Lines • Show All 1,028 Lines • Show Last 20 Lines |