} else { #ifdef INET6 if (inp->inp_flags & INP_IPV6) continue;	 #endif
udp_input(struct mbuf *m, ...)#elseudp_input(m, va_alist)	struct mbuf *m;	va_dcl#endif{	register struct ip *ip;	register struct udphdr *uh;	register struct inpcb *inp;	struct mbuf *opts = 0;	int len;	struct ip save_ip;	int iphlen;	va_list ap;	u_int16_t savesum;	union {		struct sockaddr sa;		struct sockaddr_in sin;#ifdef INET6		struct sockaddr_in6 sin6;#endif /* INET6 */	} srcsa, dstsa;#ifdef INET6	struct ip6_hdr *ipv6;	struct sockaddr_in6 src_v4mapped;#endif /* INET6 */#ifdef IPSEC	struct tdb  *tdb = NULL;#endif /* IPSEC */	va_start(ap, m);	iphlen = va_arg(ap, int);	va_end(ap);	udpstat.udps_ipackets++;#ifdef IPSEC	/* Save the last SA which was used to process the mbuf */	if ((m->m_flags & (M_CONF|M_AUTH)) && m->m_pkthdr.tdbi) {		struct tdb_ident *tdbi = m->m_pkthdr.tdbi;		/* XXX gettdb() should really be called at spltdb().      */		/* XXX this is splsoftnet(), currently they are the same. */		tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);		free(m->m_pkthdr.tdbi, M_TEMP);		m->m_pkthdr.tdbi = NULL;	}#endif /* IPSEC */	switch (mtod(m, struct ip *)->ip_v) {	case 4:		ip = mtod(m, struct ip *);#ifdef INET6		ipv6 = NULL;#endif /* INET6 */		srcsa.sa.sa_family = AF_INET;		break;#ifdef INET6	case 6:		ip = NULL;		ipv6 = mtod(m, struct ip6_hdr *);		srcsa.sa.sa_family = AF_INET6;		break;#endif /* INET6 */	default:		printf("udp_input: received unknown IP version %d",		    mtod(m, struct ip *)->ip_v);		goto bad;	}	/*	 * 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.	 */	/*	 * (contd. from above...)  Furthermore, we may want to strip options	 * for such things as ICMP errors, where options just get in the way.	 */	if (ip && iphlen > sizeof (struct ip)) {		ip_stripoptions(m, (struct mbuf *)0);		iphlen = sizeof(struct ip);	}	/*	 * Get IP and UDP header together in first mbuf.	 */	if (m->m_len < iphlen + sizeof(struct udphdr)) {		if ((m = m_pullup2(m, iphlen + sizeof(struct udphdr))) == 0) {			udpstat.udps_hdrops++;			return;		}#ifdef INET6		if (ipv6)			ipv6 = mtod(m, struct ip6_hdr *);		else#endif /* INET6 */			ip = mtod(m, struct ip *);	}	uh = (struct udphdr *)(mtod(m, caddr_t) + iphlen);	/*	 * Make mbuf data length reflect UDP length.	 * If not enough data to reflect UDP length, drop.	 */	len = ntohs((u_int16_t)uh->uh_ulen);	if (m->m_pkthdr.len - iphlen != len) {		if (len > (m->m_pkthdr.len - iphlen) ||			len < sizeof(struct udphdr)) {			udpstat.udps_badlen++;			goto bad;		}		m_adj(m, len - (m->m_pkthdr.len - iphlen));	}	/*	 * Save a copy of the IP header in case we want restore it	 * for sending an ICMP error message in response.	 */	if (ip)		save_ip = *ip;	/*	 * Checksum extended UDP header and data.	 * from W.R.Stevens: check incoming udp cksums even if	 *	udpcksum is not set.	 */	savesum = uh->uh_sum;#ifdef INET6	if (ipv6) {		/*		 * In IPv6, the UDP checksum is ALWAYS used.		 */		if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) {			udpstat.udps_badsum++;			goto bad;		}	} else#endif /* INET6 */	if (uh->uh_sum) {		bzero(((struct ipovly *)ip)->ih_x1,		    sizeof ((struct ipovly *)ip)->ih_x1);		((struct ipovly *)ip)->ih_len = uh->uh_ulen;		if ((uh->uh_sum = in_cksum(m, len + sizeof (struct ip))) != 0) {			udpstat.udps_badsum++;			m_freem(m);			return;		}	} else		udpstat.udps_nosum++;	switch (srcsa.sa.sa_family) {	case AF_INET:		bzero(&srcsa, sizeof(struct sockaddr_in));		srcsa.sin.sin_len = sizeof(struct sockaddr_in);		srcsa.sin.sin_family = AF_INET;		srcsa.sin.sin_port = uh->uh_sport;		srcsa.sin.sin_addr = ip->ip_src;#ifdef INET6		bzero(&src_v4mapped, sizeof(struct sockaddr_in6));		src_v4mapped.sin6_len = sizeof(struct sockaddr_in6);		src_v4mapped.sin6_family = AF_INET6;		src_v4mapped.sin6_port = uh->uh_sport;		CREATE_IPV6_MAPPED(src_v4mapped.sin6_addr, ip->ip_src.s_addr);#endif /* INET6 */		bzero(&dstsa, sizeof(struct sockaddr_in));		dstsa.sin.sin_len = sizeof(struct sockaddr_in);		dstsa.sin.sin_family = AF_INET;		dstsa.sin.sin_port = uh->uh_dport;		dstsa.sin.sin_addr = ip->ip_dst;		break;#ifdef INET6	case AF_INET6:		bzero(&srcsa, sizeof(struct sockaddr_in6));		srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6);		srcsa.sin6.sin6_family = AF_INET6;		srcsa.sin6.sin6_port = uh->uh_sport;		srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ipv6->ip6_flow;		srcsa.sin6.sin6_addr = ipv6->ip6_src;		if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6.sin6_addr))			srcsa.sin6.sin6_addr.s6_addr16[1] = 0;		if (m->m_pkthdr.rcvif) {			if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6.sin6_addr)) {				srcsa.sin6.sin6_scope_id =					m->m_pkthdr.rcvif->if_index;			} else				srcsa.sin6.sin6_scope_id = 0;		} else			srcsa.sin6.sin6_scope_id = 0;		bzero(&dstsa, sizeof(struct sockaddr_in6));		dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6);		dstsa.sin6.sin6_family = AF_INET6;		dstsa.sin6.sin6_port = uh->uh_dport;		dstsa.sin6.sin6_addr = ipv6->ip6_dst;		break;#endif /* INET6 */	}#ifdef INET6	if ((ipv6 && IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst)) ||	    (ip && IN_MULTICAST(ip->ip_dst.s_addr)) ||	    (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) {#else /* INET6 */	if (IN_MULTICAST(ip->ip_dst.s_addr) ||	    in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {#endif /* INET6 */		struct socket *last;		/*		 * Deliver a multicast or broadcast datagram to *all* sockets		 * for which the local and remote addresses and ports match		 * those of the incoming datagram.  This allows more than		 * one process to receive multi/broadcasts on the same port.		 * (This really ought to be done for unicast datagrams as		 * well, but that would cause problems with existing		 * applications that open both address-specific sockets and		 * a wildcard socket listening to the same port -- they would		 * end up receiving duplicates of every unicast datagram.		 * Those applications open the multiple sockets to overcome an		 * inadequacy of the UDP socket interface, but for backwards		 * compatibility we avoid the problem here rather than		 * fixing the interface.  Maybe 4.5BSD will remedy this?)		 */		iphlen += sizeof(struct udphdr);		/*		 * Locate pcb(s) for datagram.		 * (Algorithm copied from raw_intr().)		 */		last = NULL;		for (inp = udbtable.inpt_queue.cqh_first;		    inp != (struct inpcb *)&udbtable.inpt_queue;		    inp = inp->inp_queue.cqe_next) {			if (inp->inp_lport != uh->uh_dport)				continue;#ifdef INET6			if (ipv6) {				if (!(inp->inp_flags & INP_IPV6))					continue;				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))					if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,					    &ipv6->ip6_dst))						continue;			} else#endif /* INET6 */			if (inp->inp_laddr.s_addr != INADDR_ANY) {				if (inp->inp_laddr.s_addr !=				    ip->ip_dst.s_addr)					continue;			}#ifdef INET6			if (ipv6) {				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))					if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,					    &ipv6->ip6_src) ||					    inp->inp_fport != uh->uh_sport)			        continue;			} else#endif /* INET6 */			if (inp->inp_faddr.s_addr != INADDR_ANY) {				if (inp->inp_faddr.s_addr !=				    ip->ip_src.s_addr ||				    inp->inp_fport != uh->uh_sport)					continue;			}			if (last != NULL) {				struct mbuf *n;				if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {					opts = NULL;#ifdef INET6					if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS))						ip6_savecontrol(inp, &opts, ipv6, n);#endif /* INET6 */					m_adj(n, iphlen);					if (sbappendaddr(&last->so_rcv,#ifdef INET6							 					/*					 * This cruft is needed in (the rare)					 * case I deliver a {multi,broad}cast					 * IPv4 packet to an AF_INET6 socket.					 */					    ((((struct inpcb *)last->so_pcb)->inp_flags					    & INP_IPV6) && ip) ?					    (struct sockaddr *)&src_v4mapped :#endif /* INET6 */					    &srcsa.sa, n, opts) == 0) {						m_freem(n);						udpstat.udps_fullsock++;					} else						sorwakeup(last);				}			}			last = inp->inp_socket;			/*			 * 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->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.udps_noportbcast++;			goto bad;		}		opts = NULL;#ifdef INET6		if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS))			ip6_savecontrol(inp, &opts, ipv6, m);#endif /* INET6 */		m_adj(m, iphlen);		if (sbappendaddr(&last->so_rcv, #ifdef INET6	        /*		 * This cruft is needed in (the rare) case I		 * deliver a {multi,broad}cast IPv4 packet to		 * an AF_INET6 socket.		 */		    ((((struct inpcb *)last->so_pcb)->inp_flags & INP_IPV6) && ip) ?		    (struct sockaddr *)&src_v4mapped :#endif /* INET6 */		    &srcsa.sa, m, opts) == 0) {			udpstat.udps_fullsock++;			goto bad;		}		sorwakeup(last);		return;	}	/*	 * Locate pcb for datagram.	 */#ifdef INET6	if (ipv6)		inp = in6_pcbhashlookup(&udbtable, &ipv6->ip6_src, uh->uh_sport,		    &ipv6->ip6_dst, uh->uh_dport);	else#endif /* INET6 */	inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,	    ip->ip_dst, uh->uh_dport);	if (inp == 0) {		++udpstat.udps_pcbhashmiss;#ifdef INET6		if (ipv6) {			inp = in_pcblookup(&udbtable,			    (struct in_addr *)&(ipv6->ip6_src),			    uh->uh_sport, (struct in_addr *)&(ipv6->ip6_dst),			    uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);		} else#endif /* INET6 */		inp = in_pcblookup(&udbtable, &ip->ip_src, uh->uh_sport,		    &ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD);		if (inp == 0) {			udpstat.udps_noport++;			if (m->m_flags & (M_BCAST | M_MCAST)) {				udpstat.udps_noportbcast++;				goto bad;			}#ifdef INET6			if (ipv6) {				icmp6_error(m, ICMP6_DST_UNREACH,				    ICMP6_DST_UNREACH_NOPORT,0);			} else#endif /* INET6 */			{				*ip = save_ip;				HTONS(ip->ip_len);				HTONS(ip->ip_id);				HTONS(ip->ip_off);				uh->uh_sum = savesum;				icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,					0, 0);			}			return;		}	}#ifdef IPSEC	/* Check if this socket requires security for incoming packets */	if ((inp->inp_seclevel[SL_AUTH] >= IPSEC_LEVEL_REQUIRE &&	     !(m->m_flags & M_AUTH)) ||	    (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE &&	     !(m->m_flags & M_CONF))) {#ifdef notyet#ifdef INET6		if (ipv6)			ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0);		else#endif /* INET6 */		icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0);		m = NULL;#endif /* notyet */		udpstat.udps_nosec++;		goto bad;	}	/* Use tdb_bind_out for this inp's outbound communication */	if (tdb)		tdb_add_inp(tdb, inp);#endif /*IPSEC */	opts = NULL;#ifdef INET6	if (ipv6 && (inp->inp_flags & IN6P_CONTROLOPTS))		ip6_savecontrol(inp, &opts, ipv6, m);#endif /* INET6 */	if (ip && (inp->inp_flags & INP_CONTROLOPTS)) {		struct mbuf **mp = &opts;		if (inp->inp_flags & INP_RECVDSTADDR) {			*mp = udp_saveopt((caddr_t) &ip->ip_dst,			    sizeof(struct in_addr), IP_RECVDSTADDR);			if (*mp)				mp = &(*mp)->m_next;		}#ifdef notyet		/* options were tossed above */		if (inp->inp_flags & INP_RECVOPTS) {			*mp = udp_saveopt((caddr_t) opts_deleted_above,			    sizeof(struct in_addr), IP_RECVOPTS);			if (*mp)				mp = &(*mp)->m_next;		}		/* ip_srcroute doesn't do what we want here, need to fix */		if (inp->inp_flags & INP_RECVRETOPTS) {			*mp = udp_saveopt((caddr_t) ip_srcroute(),			    sizeof(struct in_addr), IP_RECVRETOPTS);			if (*mp)				mp = &(*mp)->m_next;		}#endif	}	iphlen += sizeof(struct udphdr);	m_adj(m, iphlen);	if (sbappendaddr(&inp->inp_socket->so_rcv,#ifdef INET6	    /*	     * This cruft is needed to deliver a IPv4 packet to	     * an AF_INET6 socket.	     */	    ((((struct inpcb *)inp->inp_socket->so_pcb)->inp_flags & INP_IPV6)	    && ip) ? (struct sockaddr *)&src_v4mapped : #endif /* INET6 */		&srcsa.sa, m, opts) == 0) {		udpstat.udps_fullsock++;		goto bad;	}	sorwakeup(inp->inp_socket);	return;bad:	m_freem(m);	if (opts)		m_freem(opts);}