Index: udp_usrreq.c =================================================================== --- udp_usrreq.c (revision 220359) +++ udp_usrreq.c (working copy) @@ -220,56 +220,65 @@ } #ifdef VIMAGE void udp_destroy(void) { in_pcbinfo_destroy(&V_udbinfo); uma_zdestroy(V_udpcb_zone); } #endif /* * Subroutine of udp_input(), which appends the provided mbuf chain to the * passed pcb/socket. The caller must provide a sockaddr_in via udp_in that * contains the source address. If the socket ends up being an IPv6 socket, * udp_append() will convert to a sockaddr_in6 before passing the address * into the socket code. */ static void -udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off, +udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int iphlen, struct sockaddr_in *udp_in) { struct sockaddr *append_sa; struct socket *so; struct mbuf *opts = 0; #ifdef INET6 struct sockaddr_in6 udp_in6; #endif -#ifdef IPSEC -#ifdef IPSEC_NAT_T -#ifdef INET struct udpcb *up; -#endif -#endif -#endif + int off; + + /* + * Engage the tunneling protocol. + */ + up = intoudpcb(inp); + if (up->u_tun_func != NULL) { + (*up->u_tun_func)(n, iphlen, inp); + return; + } + + if (n == NULL) + return; + + off = iphlen + sizeof(struct udphdr); INP_RLOCK_ASSERT(inp); #ifdef IPSEC /* Check AH/ESP integrity. */ if (ipsec4_in_reject(n, inp)) { m_freem(n); V_ipsec4stat.in_polvio++; return; } #ifdef IPSEC_NAT_T #ifdef INET up = intoudpcb(inp); KASSERT(up != NULL, ("%s: udpcb NULL", __func__)); if (up->u_flags & UF_ESPINUDP_ALL) { /* IPSec UDP encaps. */ n = udp4_espdecap(inp, n, off); if (n == NULL) /* Consumed. */ return; } #endif /* INET */ @@ -305,41 +314,40 @@ so = inp->inp_socket; SOCKBUF_LOCK(&so->so_rcv); if (sbappendaddr_locked(&so->so_rcv, append_sa, n, opts) == 0) { SOCKBUF_UNLOCK(&so->so_rcv); m_freem(n); if (opts) m_freem(opts); UDPSTAT_INC(udps_fullsock); } else sorwakeup_locked(so); } void udp_input(struct mbuf *m, int off) { int iphlen = off; struct ip *ip; struct udphdr *uh; struct ifnet *ifp; struct inpcb *inp; - struct udpcb *up; int len; struct ip save_ip; struct sockaddr_in udp_in; #ifdef IPFIREWALL_FORWARD struct m_tag *fwd_tag; #endif ifp = m->m_pkthdr.rcvif; UDPSTAT_INC(udps_ipackets); /* * Strip IP options, if any; should skip this, make available to * user, and use on returned packets, but we don't yet have a way to * check the checksum with options still present. */ if (iphlen > sizeof (struct ip)) { ip_stripoptions(m, (struct mbuf *)0); iphlen = sizeof(struct ip); } @@ -491,93 +499,67 @@ group.sin_family = AF_INET; group.sin_addr = ip->ip_dst; blocked = imo_multi_filter(imo, ifp, (struct sockaddr *)&group, (struct sockaddr *)&udp_in); if (blocked != MCAST_PASS) { if (blocked == MCAST_NOTGMEMBER) IPSTAT_INC(ips_notmember); if (blocked == MCAST_NOTSMEMBER || blocked == MCAST_MUTED) UDPSTAT_INC(udps_filtermcast); INP_RUNLOCK(inp); continue; } } if (last != NULL) { struct mbuf *n; n = m_copy(m, 0, M_COPYALL); - up = intoudpcb(last); - if (up->u_tun_func == NULL) { - if (n != NULL) - udp_append(last, - ip, n, - iphlen + - sizeof(struct udphdr), - &udp_in); - } else { - /* - * Engage the tunneling protocol we - * will have to leave the info_lock - * up, since we are hunting through - * multiple UDP's. - */ - - (*up->u_tun_func)(n, iphlen, last); - } + udp_append(last, ip, n, iphlen, &udp_in); INP_RUNLOCK(last); } last = inp; /* * Don't look for additional matches if this one does * not have either the SO_REUSEPORT or SO_REUSEADDR * socket options set. This heuristic avoids * searching through all pcbs in the common case of a * non-shared port. It assumes that an application * will never clear these options after setting them. */ if ((last->inp_socket->so_options & (SO_REUSEPORT|SO_REUSEADDR)) == 0) break; } if (last == NULL) { /* * No matching pcb found; discard datagram. (No need * to send an ICMP Port Unreachable for a broadcast * or multicast datgram.) */ UDPSTAT_INC(udps_noportbcast); goto badheadlocked; } - up = intoudpcb(last); - if (up->u_tun_func == NULL) { - udp_append(last, ip, m, iphlen + sizeof(struct udphdr), - &udp_in); - } else { - /* - * Engage the tunneling protocol. - */ - (*up->u_tun_func)(m, iphlen, last); - } + udp_append(last, ip, m, iphlen, &udp_in); INP_RUNLOCK(last); INP_INFO_RUNLOCK(&V_udbinfo); return; } /* * Locate pcb for datagram. */ inp = in_pcblookup_hash(&V_udbinfo, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, 1, ifp); if (inp == NULL) { if (udp_log_in_vain) { char buf[4*sizeof "123"]; strcpy(buf, inet_ntoa(ip->ip_dst)); log(LOG_INFO, "Connection attempt to UDP %s:%d from %s:%d\n", buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src), ntohs(uh->uh_sport)); } @@ -589,50 +571,41 @@ if (V_udp_blackhole) goto badheadlocked; if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0) goto badheadlocked; *ip = save_ip; ip->ip_len += iphlen; icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); INP_INFO_RUNLOCK(&V_udbinfo); return; } /* * Check the minimum TTL for socket. */ INP_RLOCK(inp); INP_INFO_RUNLOCK(&V_udbinfo); if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) { INP_RUNLOCK(inp); goto badunlocked; } - up = intoudpcb(inp); - if (up->u_tun_func == NULL) { - udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in); - } else { - /* - * Engage the tunneling protocol. - */ - - (*up->u_tun_func)(m, iphlen, inp); - } + udp_append(inp, ip, m, iphlen, &udp_in); INP_RUNLOCK(inp); return; badheadlocked: if (inp) INP_RUNLOCK(inp); INP_INFO_RUNLOCK(&V_udbinfo); badunlocked: m_freem(m); } /* * Notify a udp user of an asynchronous error; just wake up so that they can * collect error status. */ struct inpcb * udp_notify(struct inpcb *inp, int errno) { /*