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.52.2.3 retrieving revision 1.56 diff -u -p -r1.52.2.3 -r1.56 --- src/sys/netinet/udp_usrreq.c 2001/02/11 19:17:19 1.52.2.3 +++ src/sys/netinet/udp_usrreq.c 2000/01/06 15:46:08 1.56 @@ -1,4 +1,4 @@ -/* $NetBSD: udp_usrreq.c,v 1.52.2.3 2001/02/11 19:17:19 bouyer Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.56 2000/01/06 15:46:08 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -65,7 +65,8 @@ */ #include "opt_ipsec.h" -#include "opt_ipkdb.h" + +#include "ipkdb.h" #include #include @@ -79,7 +80,7 @@ #include #include -#include +#include #include #include @@ -115,12 +116,9 @@ #ifdef IPSEC #include #include +#include #endif /*IPSEC*/ -#ifdef IPKDB -#include -#endif - /* * UDP protocol implementation. * Per RFC 768, August, 1980. @@ -131,12 +129,10 @@ int udpcksum = 1; int udpcksum = 0; /* XXX */ #endif -#ifdef INET static void udp4_sendup __P((struct mbuf *, int, struct sockaddr *, struct socket *)); static int udp4_realinput __P((struct sockaddr_in *, struct sockaddr_in *, struct mbuf *, int)); -#endif #ifdef INET6 static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *, struct socket *)); @@ -145,9 +141,7 @@ static int in6_mcmatch __P((struct in6pc static int udp6_realinput __P((int, struct sockaddr_in6 *, struct sockaddr_in6 *, struct mbuf *, int)); #endif -#ifdef INET static void udp_notify __P((struct inpcb *, int)); -#endif #ifndef UDBHASHSIZE #define UDBHASHSIZE 128 @@ -158,13 +152,10 @@ void udp_init() { -#ifdef INET in_pcbinit(&udbtable, udbhashsize, udbhashsize); -#endif } #ifndef UDP6 -#ifdef INET void #if __STDC__ udp_input(struct mbuf *m, ...) @@ -228,17 +219,13 @@ 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 || len < sizeof(struct udphdr)) { + if (ip->ip_len < iphlen + len) { udpstat.udps_badlen++; goto bad; } @@ -249,11 +236,32 @@ 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. */ @@ -293,12 +301,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; } - udpstat.udps_noport++; -#ifdef IPKDB +#if NIPKDB > 0 if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, m, iphlen + sizeof(struct udphdr), m->m_pkthdr.len - iphlen - sizeof(struct udphdr))) { @@ -317,7 +325,6 @@ bad: if (m) m_freem(m); } -#endif #ifdef INET6 int @@ -361,10 +368,6 @@ 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; @@ -373,10 +376,6 @@ 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)) { @@ -401,22 +400,36 @@ udp6_input(mp, offp, proto) bzero(&src, sizeof(src)); src.sin6_family = AF_INET6; src.sin6_len = sizeof(struct sockaddr_in6); - /* KAME hack: recover scopeid */ - (void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif); + 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; + } src.sin6_port = uh->uh_sport; bzero(&dst, sizeof(dst)); dst.sin6_family = AF_INET6; dst.sin6_len = sizeof(struct sockaddr_in6); - /* KAME hack: recover scopeid */ - (void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif); + 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; + } 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; } @@ -428,7 +441,6 @@ bad: } #endif -#ifdef INET static void udp4_sendup(m, off, src, so) struct mbuf *m; @@ -483,7 +495,6 @@ udp4_sendup(m, off, src, so) sorwakeup(so); } } -#endif #ifdef INET6 static void @@ -530,7 +541,6 @@ udp6_sendup(m, off, src, so) } #endif -#ifdef INET static int udp4_realinput(src, dst, m, off) struct sockaddr_in *src; @@ -554,7 +564,7 @@ udp4_realinput(src, dst, m, off) dst4 = &dst->sin_addr; dport = &dst->sin_port; - if (IN_MULTICAST(dst4->s_addr) || + if (IN_MULTICAST(src4->s_addr) || in_broadcast(*dst4, m->m_pkthdr.rcvif)) { struct inpcb *last; /* @@ -575,7 +585,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. @@ -620,6 +630,7 @@ 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; } @@ -636,12 +647,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; } - udpstat.udps_noport++; -#ifdef IPKDB +#if NIPKDB > 0 if (checkipkdb(src4, *sport, *dport, m, off, m->m_pkthdr.len - off)) { /* @@ -667,13 +678,12 @@ udp4_realinput(src, dst, m, off) bad: return rcvcnt; } -#endif #ifdef INET6 static int in6_mcmatch(in6p, ia6, ifp) struct in6pcb *in6p; - struct in6_addr *ia6; + register struct in6_addr *ia6; struct ifnet *ifp; { struct ip6_moptions *im6o = in6p->in6p_moptions; @@ -704,7 +714,7 @@ udp6_realinput(af, src, dst, m, off) u_int16_t *sport, *dport; int rcvcnt; struct in6_addr *src6, *dst6; - struct in_addr *dst4; + struct in_addr *src4; struct in6pcb *in6p; rcvcnt = 0; @@ -719,10 +729,10 @@ udp6_realinput(af, src, dst, m, off) sport = &src->sin6_port; dst6 = &dst->sin6_addr; dport = &dst->sin6_port; - dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr32[12]; + src4 = (struct in_addr *)&src->sin6_addr.s6_addr32[12]; if (IN6_IS_ADDR_MULTICAST(dst6) - || (af == AF_INET && IN_MULTICAST(dst4->s_addr))) { + || (af == AF_INET && IN_MULTICAST(src4->s_addr))) { struct in6pcb *last; /* * Deliver a multicast or broadcast datagram to *all* sockets @@ -742,7 +752,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. @@ -803,9 +813,11 @@ 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; } @@ -827,21 +839,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); @@ -874,9 +886,9 @@ udp_input(m, va_alist) #endif { int proto; - struct ip *ip; - struct udphdr *uh; - struct inpcb *inp; + register struct ip *ip; + register struct udphdr *uh; + register struct inpcb *inp; struct mbuf *opts = 0; int len; struct ip save_ip; @@ -916,17 +928,13 @@ 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 || len < sizeof(struct udphdr)) { + if (ip->ip_len < iphlen + len) { udpstat.udps_badlen++; goto bad; } @@ -983,7 +991,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. @@ -1055,6 +1063,7 @@ 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; } @@ -1088,13 +1097,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; -#ifdef IPKDB +#if NIPKDB > 0 if (checkipkdb(&ip->ip_src, uh->uh_sport, uh->uh_dport, @@ -1139,14 +1148,13 @@ bad: } #endif /*UDP6*/ -#ifdef INET /* * Notify a udp user of an asynchronous error; * just wake up so that he can collect error status. */ static void udp_notify(inp, errno) - struct inpcb *inp; + register struct inpcb *inp; int errno; { @@ -1161,8 +1169,9 @@ udp_ctlinput(cmd, sa, v) struct sockaddr *sa; void *v; { - struct ip *ip = v; - struct udphdr *uh; + register struct ip *ip = v; + register struct udphdr *uh; + extern int inetctlerrmap[]; void (*notify) __P((struct inpcb *, int)) = udp_notify; int errno; @@ -1199,9 +1208,9 @@ udp_output(m, va_alist) va_dcl #endif { - struct inpcb *inp; - struct udpiphdr *ui; - int len = m->m_pkthdr.len; + register struct inpcb *inp; + register struct udpiphdr *ui; + register int len = m->m_pkthdr.len; int error = 0; va_list ap; @@ -1256,10 +1265,7 @@ udp_output(m, va_alist) udpstat.udps_opackets++; #ifdef IPSEC - if (ipsec_setsocket(m, inp->inp_socket) != 0) { - error = ENOBUFS; - goto release; - } + m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket; #endif /*IPSEC*/ return (ip_output(m, inp->inp_options, &inp->inp_route, @@ -1283,20 +1289,14 @@ udp_usrreq(so, req, m, nam, control, p) struct mbuf *m, *nam, *control; struct proc *p; { - struct inpcb *inp; + register struct inpcb *inp; int s; - int error = 0; + register 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 @@ -1330,7 +1330,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(so, &inp->inp_sp); + error = ipsec_init_policy(&inp->inp_sp); if (error != 0) { in_pcbdetach(inp); break; @@ -1478,4 +1478,3 @@ udp_sysctl(name, namelen, oldp, oldlenp, } /* NOTREACHED */ } -#endif