Index: sys/netinet6/udp6_usrreq.c =================================================================== --- sys/netinet6/udp6_usrreq.c +++ sys/netinet6/udp6_usrreq.c @@ -233,7 +233,7 @@ plen = ntohs(ip6->ip6_plen) - off + sizeof(*ip6); ulen = ntohs((u_short)uh->uh_ulen); - nxt = ip6->ip6_nxt; + nxt = proto; cscov_partial = (nxt == IPPROTO_UDPLITE) ? 1 : 0; if (nxt == IPPROTO_UDPLITE) { /* Zero means checksum over the complete packet. */ @@ -668,9 +668,11 @@ return (error); } + nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? + IPPROTO_UDP : IPPROTO_UDPLITE; if (control) { if ((error = ip6_setpktopts(control, &opt, - inp->in6p_outputopts, td->td_ucred, IPPROTO_UDP)) != 0) + inp->in6p_outputopts, td->td_ucred, nxt)) != 0) goto release; optp = &opt; } else @@ -794,8 +796,6 @@ /* * Stuff checksum and output datagram. */ - nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? - IPPROTO_UDP : IPPROTO_UDPLITE; udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen); udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */ udp6->uh_dport = fport; @@ -912,17 +912,21 @@ inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_abort: inp == NULL")); + INP_WLOCK(inp); #ifdef INET if (inp->inp_vflag & INP_IPV4) { struct pr_usrreqs *pru; + uint8_t nxt; - pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; + nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? + IPPROTO_UDP : IPPROTO_UDPLITE; + INP_WUNLOCK(inp); + pru = inetsw[ip_protox[nxt]].pr_usrreqs; (*pru->pru_abort)(so); return; } #endif - INP_WLOCK(inp); if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { INP_HASH_WLOCK(pcbinfo); in6_pcbdisconnect(inp); @@ -1036,16 +1040,20 @@ inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_close: inp == NULL")); + INP_WLOCK(inp); #ifdef INET if (inp->inp_vflag & INP_IPV4) { struct pr_usrreqs *pru; + uint8_t nxt; - pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; + nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? + IPPROTO_UDP : IPPROTO_UDPLITE; + INP_WUNLOCK(inp); + pru = inetsw[ip_protox[nxt]].pr_usrreqs; (*pru->pru_disconnect)(so); return; } #endif - INP_WLOCK(inp); if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { INP_HASH_WLOCK(pcbinfo); in6_pcbdisconnect(inp); @@ -1151,18 +1159,21 @@ inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL")); + INP_WLOCK(inp); #ifdef INET if (inp->inp_vflag & INP_IPV4) { struct pr_usrreqs *pru; + uint8_t nxt; - pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; + nxt = (inp->inp_socket->so_proto->pr_protocol == IPPROTO_UDP) ? + IPPROTO_UDP : IPPROTO_UDPLITE; + INP_WUNLOCK(inp); + pru = inetsw[ip_protox[nxt]].pr_usrreqs; (void)(*pru->pru_disconnect)(so); return (0); } #endif - INP_WLOCK(inp); - if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) { error = ENOTCONN; goto out; @@ -1218,7 +1229,10 @@ } if (hasv4addr) { struct pr_usrreqs *pru; + uint8_t nxt; + nxt = (inp->inp_socket->so_proto->pr_protocol == + IPPROTO_UDP) ? IPPROTO_UDP : IPPROTO_UDPLITE; /* * XXXRW: We release UDP-layer locks before calling * udp_send() in order to avoid recursion. However, @@ -1230,7 +1244,7 @@ INP_WUNLOCK(inp); if (sin6) in6_sin6_2_sin_in_sock(addr); - pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; + pru = inetsw[ip_protox[nxt]].pr_usrreqs; /* addr will just be freed in sendit(). */ return ((*pru->pru_send)(so, flags, m, addr, control, td));