Index: sys/netinet/udp_usrreq.c =================================================================== --- sys/netinet/udp_usrreq.c +++ sys/netinet/udp_usrreq.c @@ -386,6 +386,28 @@ return (0); } +static bool +udp_inpcb_eq_ip_uh(struct inpcb *inp, struct ip *ip, struct udphdr *uh) +{ + if (inp->inp_lport != uh->uh_dport) + return false; +#ifdef INET6 + if ((inp->inp_vflag & INP_IPV4) == 0) + return false; +#endif + if (inp->inp_laddr.s_addr != INADDR_ANY && + inp->inp_laddr.s_addr != ip->ip_dst.s_addr) + return false; + if (inp->inp_faddr.s_addr != INADDR_ANY && + inp->inp_faddr.s_addr != ip->ip_src.s_addr) + return false; + if (inp->inp_fport != 0 && + inp->inp_fport != uh->uh_sport) + return false; + + return true; +} + int udp_input(struct mbuf **mp, int *offp, int proto) { @@ -533,21 +555,8 @@ pcblist = udp_get_pcblist(proto); last = NULL; CK_LIST_FOREACH(inp, pcblist, inp_list) { - if (inp->inp_lport != uh->uh_dport) + if (!udp_inpcb_eq_ip_uh(inp, ip, uh)) continue; -#ifdef INET6 - if ((inp->inp_vflag & INP_IPV4) == 0) - continue; -#endif - if (inp->inp_laddr.s_addr != INADDR_ANY && - inp->inp_laddr.s_addr != ip->ip_dst.s_addr) - continue; - if (inp->inp_faddr.s_addr != INADDR_ANY && - inp->inp_faddr.s_addr != ip->ip_src.s_addr) - continue; - if (inp->inp_fport != 0 && - inp->inp_fport != uh->uh_sport) - continue; INP_RLOCK(inp); @@ -556,12 +565,10 @@ 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 held. - */ + if (!udp_inpcb_eq_ip_uh(inp, ip, uh)) { + INP_RUNLOCK(inp); + continue; + } /* * Handle socket delivery policy for any-source