Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet/udp_usrreq.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet/udp_usrreq.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.55 retrieving revision 1.71 diff -u -p -r1.55 -r1.71 --- src/sys/netinet/udp_usrreq.c 2000/01/06 06:41:19 1.55 +++ src/sys/netinet/udp_usrreq.c 2000/08/30 15:04:45 1.71 @@ -1,4 +1,4 @@ -/* $NetBSD: udp_usrreq.c,v 1.55 2000/01/06 06:41:19 itojun Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.71 2000/08/30 15:04:45 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -65,8 +65,7 @@ */ #include "opt_ipsec.h" - -#include "ipkdb.h" +#include "opt_ipkdb.h" #include #include @@ -80,7 +79,7 @@ #include #include -#include +#include #include #include @@ -116,9 +115,12 @@ #ifdef IPSEC #include #include -#include #endif /*IPSEC*/ +#ifdef IPKDB +#include +#endif + /* * UDP protocol implementation. * Per RFC 768, August, 1980. @@ -155,6 +157,7 @@ udp_init() in_pcbinit(&udbtable, udbhashsize, udbhashsize); } +#ifndef UDP6 void #if __STDC__ udp_input(struct mbuf *m, ...) @@ -218,13 +221,17 @@ udp_input(m, va_alist) } #endif + /* destination port of 0 is illegal, based on RFC768. */ + if (uh->uh_dport == 0) + 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->ip_len != iphlen + len) { - if (ip->ip_len < iphlen + len) { + if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { udpstat.udps_badlen++; goto bad; } @@ -235,32 +242,11 @@ udp_input(m, va_alist) * Checksum extended UDP header and data. */ if (uh->uh_sum) { -#ifndef PULLDOWN_TEST - struct ip save_ip; - - /* - * Save a copy of the IP header in case we want restore it - * for sending an ICMP error message in response. - */ - save_ip = *ip; - - bzero(((struct ipovly *)ip)->ih_x1, - sizeof ((struct ipovly *)ip)->ih_x1); - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - if (in_cksum(m, len + sizeof (struct ip)) != 0) { - udpstat.udps_badsum++; - m_freem(m); - return; - } - - *ip = save_ip; -#else if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0) { udpstat.udps_badsum++; m_freem(m); return; } -#endif } /* construct source and dst sockaddrs. */ @@ -300,12 +286,12 @@ udp_input(m, va_alist) #endif if (n == 0) { - udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat.udps_noportbcast++; goto bad; } -#if NIPKDB > 0 + udpstat.udps_noport++; +#ifdef IPKDB if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, m, iphlen + sizeof(struct udphdr), m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) { @@ -367,6 +353,10 @@ udp6_input(mp, offp, proto) } #endif ulen = ntohs((u_short)uh->uh_ulen); + /* + * RFC2675 section 4: jumbograms will have 0 in the UDP header field, + * iff payload length > 0xffff. + */ if (ulen == 0 && plen > 0xffff) ulen = plen; @@ -375,6 +365,10 @@ udp6_input(mp, offp, proto) goto bad; } + /* destination port of 0 is illegal, based on RFC768. */ + if (uh->uh_dport == 0) + goto bad; + /* Be proactive about malicious use of IPv4 mapped address */ if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { @@ -399,36 +393,22 @@ udp6_input(mp, offp, proto) bzero(&src, sizeof(src)); src.sin6_family = AF_INET6; src.sin6_len = sizeof(struct sockaddr_in6); - bcopy(&ip6->ip6_src, &src.sin6_addr, sizeof(src.sin6_addr)); - if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6_addr)) - src.sin6_addr.s6_addr16[1] = 0; - if (m->m_pkthdr.rcvif) { - if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6_addr)) - src.sin6_scope_id = m->m_pkthdr.rcvif->if_index; - else - src.sin6_scope_id = 0; - } + /* KAME hack: recover scopeid */ + (void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif); src.sin6_port = uh->uh_sport; bzero(&dst, sizeof(dst)); dst.sin6_family = AF_INET6; dst.sin6_len = sizeof(struct sockaddr_in6); - bcopy(&ip6->ip6_dst, &dst.sin6_addr, sizeof(dst.sin6_addr)); - if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6_addr)) - dst.sin6_addr.s6_addr16[1] = 0; - if (m->m_pkthdr.rcvif) { - if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6_addr)) - dst.sin6_scope_id = m->m_pkthdr.rcvif->if_index; - else - dst.sin6_scope_id = 0; - } + /* KAME hack: recover scopeid */ + (void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif); dst.sin6_port = uh->uh_dport; if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) { - udp6stat.udp6s_noport++; if (m->m_flags & M_MCAST) { udp6stat.udp6s_noportmcast++; goto bad; } + udp6stat.udp6s_noport++; icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); m = NULL; } @@ -584,7 +564,7 @@ udp4_realinput(src, dst, m, off) /* * KAME note: usually we drop udpiphdr from mbuf here. - * we need udpiphdr for iPsec processing so we do that later. + * we need udpiphdr for IPsec processing so we do that later. */ /* * Locate pcb(s) for datagram. @@ -629,7 +609,6 @@ udp4_realinput(src, dst, m, off) * (No need to send an ICMP Port Unreachable * for a broadcast or multicast datgram.) */ - udpstat.udps_noport++; udpstat.udps_noportbcast++; goto bad; } @@ -646,12 +625,12 @@ udp4_realinput(src, dst, m, off) #if 0 struct mbuf *n; - udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat.udps_noportbcast++; goto bad; } -#if NIPKDB > 0 + udpstat.udps_noport++; +#ifdef IPKDB if (checkipkdb(src4, *sport, *dport, m, off, m->m_pkthdr.len - off)) { /* @@ -682,7 +661,7 @@ bad: static int in6_mcmatch(in6p, ia6, ifp) struct in6pcb *in6p; - register struct in6_addr *ia6; + struct in6_addr *ia6; struct ifnet *ifp; { struct ip6_moptions *im6o = in6p->in6p_moptions; @@ -751,7 +730,7 @@ udp6_realinput(af, src, dst, m, off) /* * KAME note: usually we drop udpiphdr from mbuf here. - * we need udpiphdr for iPsec processing so we do that later. + * we need udpiphdr for IPsec processing so we do that later. */ /* * Locate pcb(s) for datagram. @@ -812,11 +791,9 @@ udp6_realinput(af, src, dst, m, off) */ switch (af) { case AF_INET: - udpstat.udps_noport++; udpstat.udps_noportbcast++; break; case AF_INET6: - udp6stat.udp6s_noport++; udp6stat.udp6s_noportmcast++; break; } @@ -838,21 +815,21 @@ udp6_realinput(af, src, dst, m, off) n = m_copy(m, 0, M_COPYALL); switch (af) { case AF_INET: - udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat.udps_noportbcast++; goto bad; } + udpstat.udps_noport++; if (n != NULL) icmp_error(n, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); break; case AF_INET6: - udp6stat.udp6s_noport++; if (m->m_flags & M_MCAST) { udp6stat.udp6s_noportmcast++; goto bad; } + udp6stat.udp6s_noport++; if (n != NULL) icmp6_error(n, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); @@ -873,7 +850,8 @@ bad: } #endif -#if 0 +#else /*UDP6*/ + void #if __STDC__ udp_input(struct mbuf *m, ...) @@ -884,9 +862,9 @@ udp_input(m, va_alist) #endif { int proto; - register struct ip *ip; - register struct udphdr *uh; - register struct inpcb *inp; + struct ip *ip; + struct udphdr *uh; + struct inpcb *inp; struct mbuf *opts = 0; int len; struct ip save_ip; @@ -926,13 +904,17 @@ udp_input(m, va_alist) } uh = (struct udphdr *)((caddr_t)ip + iphlen); + /* destination port of 0 is illegal, based on RFC768. */ + if (uh->uh_dport == 0) + 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->ip_len != iphlen + len) { - if (ip->ip_len < iphlen + len) { + if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { udpstat.udps_badlen++; goto bad; } @@ -989,7 +971,7 @@ udp_input(m, va_alist) iphlen += sizeof(struct udphdr); /* * KAME note: usually we drop udpiphdr from mbuf here. - * we need udpiphdr for iPsec processing so we do that later. + * we need udpiphdr for IPsec processing so we do that later. */ /* * Locate pcb(s) for datagram. @@ -1061,7 +1043,6 @@ udp_input(m, va_alist) * (No need to send an ICMP Port Unreachable * for a broadcast or multicast datgram.) */ - udpstat.udps_noport++; udpstat.udps_noportbcast++; goto bad; } @@ -1095,13 +1076,13 @@ udp_input(m, va_alist) ++udpstat.udps_pcbhashmiss; inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport); if (inp == 0) { - udpstat.udps_noport++; if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat.udps_noportbcast++; goto bad; } + udpstat.udps_noport++; *ip = save_ip; -#if NIPKDB > 0 +#ifdef IPKDB if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, @@ -1144,7 +1125,7 @@ bad: if (opts) m_freem(opts); } -#endif +#endif /*UDP6*/ /* * Notify a udp user of an asynchronous error; @@ -1152,7 +1133,7 @@ bad: */ static void udp_notify(inp, errno) - register struct inpcb *inp; + struct inpcb *inp; int errno; { @@ -1167,9 +1148,8 @@ udp_ctlinput(cmd, sa, v) struct sockaddr *sa; void *v; { - register struct ip *ip = v; - register struct udphdr *uh; - extern int inetctlerrmap[]; + struct ip *ip = v; + struct udphdr *uh; void (*notify) __P((struct inpcb *, int)) = udp_notify; int errno; @@ -1206,9 +1186,9 @@ udp_output(m, va_alist) va_dcl #endif { - register struct inpcb *inp; - register struct udpiphdr *ui; - register int len = m->m_pkthdr.len; + struct inpcb *inp; + struct udpiphdr *ui; + int len = m->m_pkthdr.len; int error = 0; va_list ap; @@ -1263,7 +1243,7 @@ udp_output(m, va_alist) udpstat.udps_opackets++; #ifdef IPSEC - m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket; + ipsec_setsocket(m, inp->inp_socket); #endif /*IPSEC*/ return (ip_output(m, inp->inp_options, &inp->inp_route, @@ -1287,14 +1267,20 @@ udp_usrreq(so, req, m, nam, control, p) struct mbuf *m, *nam, *control; struct proc *p; { - register struct inpcb *inp; + struct inpcb *inp; int s; - register int error = 0; + int error = 0; if (req == PRU_CONTROL) return (in_control(so, (long)m, (caddr_t)nam, (struct ifnet *)control, p)); + if (req == PRU_PURGEIF) { + in_purgeif((struct ifnet *)control); + in_pcbpurgeif(&udbtable, (struct ifnet *)control); + return (0); + } + s = splsoftnet(); inp = sotoinpcb(so); #ifdef DIAGNOSTIC @@ -1328,7 +1314,7 @@ udp_usrreq(so, req, m, nam, control, p) inp = sotoinpcb(so); inp->inp_ip.ip_ttl = ip_defttl; #ifdef IPSEC - error = ipsec_init_policy(&inp->inp_sp); + error = ipsec_init_policy(so, &inp->inp_sp); if (error != 0) { in_pcbdetach(inp); break;