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) {
if ((uh->uh_sum = in4_cksum(m, IPPROTO_UDP, iphlen, len))) {
udp_input(struct mbuf *m, ...){	struct ip *ip;	struct udphdr *uh;	struct inpcb *inp;	struct mbuf *opts = 0;	struct ip save_ip;	int iphlen, len;	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 *ip6;#endif /* INET6 */#ifdef IPSEC	struct m_tag *mtag;	struct tdb_ident *tdbi;	struct tdb *tdb;	int error, s;#endif /* IPSEC */	va_start(ap, m);	iphlen = va_arg(ap, int);	va_end(ap);	udpstat.udps_ipackets++;	switch (mtod(m, struct ip *)->ip_v) {	case 4:		ip = mtod(m, struct ip *);#ifdef INET6		ip6 = NULL;#endif /* INET6 */		srcsa.sa.sa_family = AF_INET;		break;#ifdef INET6	case 6:		ip = NULL;		ip6 = mtod(m, struct ip6_hdr *);		srcsa.sa.sa_family = AF_INET6;		break;#endif /* INET6 */	default:		goto bad;	}	IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));	if (!uh) {		udpstat.udps_hdrops++;		return;	}	/* Check for illegal destination port 0 */	if (uh->uh_dport == 0) {		udpstat.udps_noport++;		goto bad;	}	/*	 * 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 (ip) {		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));		}	}#ifdef INET6	else if (ip6) {		/* jumbograms */		if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff)			len = m->m_pkthdr.len - iphlen;		if (len != m->m_pkthdr.len - iphlen) {			udpstat.udps_badlen++;			goto bad;		}	}#endif	else /* shouldn't happen */		goto bad;	/*	 * 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 (ip6) {		/* Be proactive about malicious use of IPv4 mapped address */		if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||		    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {			/* XXX stat */			goto bad;		}		/*		 * 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) {		if ((m->m_pkthdr.csum & M_UDP_CSUM_IN_OK) == 0) {			if (m->m_pkthdr.csum & M_UDP_CSUM_IN_BAD) {				udpstat.udps_badsum++;				udpstat.udps_inhwcsum++;				m_freem(m);				return;			}			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 {			m->m_pkthdr.csum &= ~M_UDP_CSUM_IN_OK;			udpstat.udps_inhwcsum++;		}	} else		udpstat.udps_nosum++;#ifdef IPSEC	if (udpencap_enable && udpencap_port &&	    uh->uh_dport == htons(udpencap_port)) {		u_int32_t spi;		int skip = iphlen + sizeof(struct udphdr);		if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) {			/* packet too short */			m_freem(m);			return;		}		m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);		/*		 * decapsulate if the SPI is not zero, otherwise pass		 * to userland		 */		if (spi != 0) {			if ((m = m_pullup2(m, skip)) == NULL) {				udpstat.udps_hdrops++;				return;			}			/* remove the UDP header */			bcopy(mtod(m, u_char *),			    mtod(m, u_char *) + sizeof(struct udphdr), iphlen);			m_adj(m, sizeof(struct udphdr));			skip -= sizeof(struct udphdr);			espstat.esps_udpencin++;			ipsec_common_input(m, skip, offsetof(struct ip, ip_p),			    srcsa.sa.sa_family, IPPROTO_ESP, 1);			return;		}	}#endif	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;		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;#if 0 /*XXX inbound flowinfo */		srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow;#endif		/* KAME hack: recover scopeid */		(void)in6_recoverscope(&srcsa.sin6, &ip6->ip6_src,		    m->m_pkthdr.rcvif);		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;		/* KAME hack: recover scopeid */		(void)in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst,		    m->m_pkthdr.rcvif);		break;#endif /* INET6 */	}#ifdef INET6	if ((ip6 && IN6_IS_ADDR_MULTICAST(&ip6->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;		CIRCLEQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {#ifdef INET6			/* don't accept it if AF does not match */			if (ip6 && !(inp->inp_flags & INP_IPV6))				continue;			if (!ip6 && (inp->inp_flags & INP_IPV6))				continue;#endif			if (inp->inp_lport != uh->uh_dport)				continue;#ifdef INET6			if (ip6) {				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))					if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,					    &ip6->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 (ip6) {				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))					if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,					    &ip6->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 (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))						ip6_savecontrol(inp, &opts, ip6, n);#endif /* INET6 */					m_adj(n, iphlen);					if (sbappendaddr(&last->so_rcv,					    &srcsa.sa, n, opts) == 0) {						m_freem(n);						if (opts)							m_freem(opts);						udpstat.udps_fullsock++;					} else						sorwakeup(last);					opts = NULL;				}			}			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 (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))			ip6_savecontrol(inp, &opts, ip6, m);#endif /* INET6 */		m_adj(m, iphlen);		if (sbappendaddr(&last->so_rcv,		    &srcsa.sa, m, opts) == 0) {			udpstat.udps_fullsock++;			goto bad;		}		sorwakeup(last);		return;	}	/*	 * Locate pcb for datagram.	 */#ifdef INET6	if (ip6)		inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, uh->uh_sport,		    &ip6->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 (ip6) {			inp = in6_pcblookup_listen(&udbtable,			    &ip6->ip6_dst, uh->uh_dport, m_tag_find(m,			    PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);		} else#endif /* INET6 */		inp = in_pcblookup_listen(&udbtable,		    ip->ip_dst, uh->uh_dport, m_tag_find(m,		    PACKET_TAG_PF_TRANSLATE_LOCALHOST, NULL) != NULL);		if (inp == 0) {			udpstat.udps_noport++;			if (m->m_flags & (M_BCAST | M_MCAST)) {				udpstat.udps_noportbcast++;				goto bad;			}#ifdef INET6			if (ip6) {				icmp6_error(m, ICMP6_DST_UNREACH,				    ICMP6_DST_UNREACH_NOPORT,0);			} else#endif /* INET6 */			{				*ip = save_ip;				uh->uh_sum = savesum;				icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,				    0, 0);			}			return;		}	}#ifdef IPSEC	mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);	s = splnet();	if (mtag != NULL) {		tdbi = (struct tdb_ident *)(mtag + 1);		tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);	} else		tdb = NULL;	ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error,	    IPSP_DIRECTION_IN, tdb, inp);	if (error) {		splx(s);		goto bad;	}	/* Latch SA only if the socket is connected */	if (inp->inp_tdb_in != tdb &&	    (inp->inp_socket->so_state & SS_ISCONNECTED)) {		if (tdb) {			tdb_add_inp(tdb, inp, 1);			if (inp->inp_ipo == NULL) {				inp->inp_ipo = ipsec_add_policy(inp,				    srcsa.sa.sa_family, IPSP_DIRECTION_OUT);				if (inp->inp_ipo == NULL) {					splx(s);					goto bad;				}			}			if (inp->inp_ipo->ipo_dstid == NULL &&			    tdb->tdb_srcid != NULL) {				inp->inp_ipo->ipo_dstid = tdb->tdb_srcid;				tdb->tdb_srcid->ref_count++;			}			if (inp->inp_ipsec_remotecred == NULL &&			    tdb->tdb_remote_cred != NULL) {				inp->inp_ipsec_remotecred =				    tdb->tdb_remote_cred;				tdb->tdb_remote_cred->ref_count++;			}			if (inp->inp_ipsec_remoteauth == NULL &&			    tdb->tdb_remote_auth != NULL) {				inp->inp_ipsec_remoteauth =				    tdb->tdb_remote_auth;				tdb->tdb_remote_auth->ref_count++;			}		} else { /* Just reset */			TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp,			    inp_tdb_in_next);			inp->inp_tdb_in = NULL;		}	}	splx(s);#endif /*IPSEC */	opts = NULL;#ifdef INET6	if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))		ip6_savecontrol(inp, &opts, ip6, 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, &srcsa.sa, m, opts) == 0) {		udpstat.udps_fullsock++;		goto bad;	}	sorwakeup(inp->inp_socket);	return;bad:	m_freem(m);	if (opts)		m_freem(opts);}