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.46 retrieving revision 1.47.4.2 diff -u -p -r1.46 -r1.47.4.2 --- src/sys/netinet/udp_usrreq.c 1999/01/19 21:58:41 1.46 +++ src/sys/netinet/udp_usrreq.c 1999/08/02 22:35:00 1.47.4.2 @@ -1,4 +1,33 @@ -/* $NetBSD: udp_usrreq.c,v 1.46 1999/01/19 21:58:41 mycroft Exp $ */ +/* $NetBSD: udp_usrreq.c,v 1.47.4.2 1999/08/02 22:35:00 thorpej Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ /* * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 @@ -34,11 +63,19 @@ * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 */ + +#include "opt_ipsec.h" + #include "ipkdb.h" +/* XXX MAPPED_ADDR_ENABLED should be revisited */ + #include #include #include +#ifdef MAPPED_ADDR_ENABLED +#include +#endif /* MAPPED_ADDR_ENABLED */ #include #include #include @@ -65,6 +102,12 @@ #include +#ifdef IPSEC +#include +#include +#include +#endif /*IPSEC*/ + /* * UDP protocol implementation. * Per RFC 768, August, 1980. @@ -98,6 +141,7 @@ udp_input(m, va_alist) va_dcl #endif { + int proto; register struct ip *ip; register struct udphdr *uh; register struct inpcb *inp; @@ -107,9 +151,14 @@ udp_input(m, va_alist) int iphlen; va_list ap; struct sockaddr_in udpsrc; +#ifdef MAPPED_ADDR_ENABLED + struct sockaddr_in6 mapped; +#endif + struct sockaddr *sa; va_start(ap, m); iphlen = va_arg(ap, int); + proto = va_arg(ap, int); va_end(ap); udpstat.udps_ipackets++; @@ -143,13 +192,12 @@ udp_input(m, va_alist) * If not enough data to reflect UDP length, drop. */ len = ntohs((u_int16_t)uh->uh_ulen); - if (ip->ip_len != len) { - if (len > ip->ip_len) { + if (ip->ip_len != iphlen + len) { + if (ip->ip_len < iphlen + len) { udpstat.udps_badlen++; goto bad; } - m_adj(m, len - ip->ip_len); - /* ip->ip_len = len; */ + m_adj(m, iphlen + len - ip->ip_len); } /* * Save a copy of the IP header in case we want restore it @@ -171,6 +219,15 @@ udp_input(m, va_alist) } } + /* + * Construct sockaddr format source address. + */ + udpsrc.sin_family = AF_INET; + udpsrc.sin_len = sizeof(struct sockaddr_in); + udpsrc.sin_addr = ip->ip_src; + udpsrc.sin_port = uh->uh_sport; + bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero)); + if (IN_MULTICAST(ip->ip_dst.s_addr) || in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { struct inpcb *last; @@ -190,19 +247,11 @@ udp_input(m, va_alist) * fixing the interface. Maybe 4.5BSD will remedy this?) */ + iphlen += sizeof(struct udphdr); /* - * Construct sockaddr format source address. + * KAME note: usually we drop udpiphdr from mbuf here. + * we need udpiphdr for iPsec processing so we do that later. */ - udpsrc.sin_family = AF_INET; - udpsrc.sin_len = sizeof(struct sockaddr_in); - udpsrc.sin_addr = ip->ip_src; - udpsrc.sin_port = uh->uh_sport; - bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero)); - - iphlen += sizeof(struct udphdr); - m->m_len -= iphlen; - m->m_pkthdr.len -= iphlen; - m->m_data += iphlen; /* * Locate pcb(s) for datagram. * (Algorithm copied from raw_intr().) @@ -226,6 +275,13 @@ udp_input(m, va_alist) if (last != NULL) { struct mbuf *n; +#ifdef IPSEC + /* check AH/ESP integrity. */ + if (last != NULL && ipsec4_in_reject(m, last)) { + ipsecstat.in_polvio++; + /* do not inject data to pcb */ + } else +#endif /*IPSEC*/ if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & @@ -233,9 +289,19 @@ udp_input(m, va_alist) ip_savecontrol(last, &opts, ip, n); } + m_adj(n, iphlen); + sa = (struct sockaddr *)&udpsrc; +#ifdef MAPPED_ADDR_ENABLED + if (last->inp_socket->so_proto-> + pr_domain->dom_family == AF_INET6) { + in6_sin_2_v4mapsin6(&udpsrc, + &mapped); + sa = (struct sockaddr *)&mapped; + } +#endif /* MAPPED_ADDR_ENABLED */ if (sbappendaddr( &last->inp_socket->so_rcv, - sintosa(&udpsrc), n, opts) == 0) { + sa, n, opts) == 0) { m_freem(n); if (opts) m_freem(opts); @@ -264,14 +330,32 @@ 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; } +#ifdef IPSEC + /* check AH/ESP integrity. */ + if (last != NULL && ipsec4_in_reject(m, last)) { + ipsecstat.in_polvio++; + goto bad; + } +#endif /*IPSEC*/ if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(last, &opts, ip, m); - if (sbappendaddr(&last->inp_socket->so_rcv, - sintosa(&udpsrc), m, opts) == 0) { + m->m_len -= iphlen; + m->m_pkthdr.len -= iphlen; + m->m_data += iphlen; + sa = (struct sockaddr *)&udpsrc; +#ifdef MAPPED_ADDR_ENABLED + if (last->inp_socket->so_proto->pr_domain->dom_family == + AF_INET6) { + in6_sin_2_v4mapsin6(&udpsrc, &mapped); + sa = (struct sockaddr *)&mapped; + } +#endif /* MAPPED_ADDR_ENABLED */ + if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) { udpstat.udps_fullsock++; goto bad; } @@ -303,22 +387,20 @@ udp_input(m, va_alist) /* It was a debugger connect packet, just drop it now */ goto bad; #endif - ip->ip_len += iphlen; icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); return; } } +#ifdef IPSEC + if (inp != NULL && ipsec4_in_reject(m, inp)) { + ipsecstat.in_polvio++; + goto bad; + } +#endif /*IPSEC*/ /* - * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ - udpsrc.sin_family = AF_INET; - udpsrc.sin_len = sizeof(struct sockaddr_in); - udpsrc.sin_addr = ip->ip_src; - udpsrc.sin_port = uh->uh_sport; - bzero((caddr_t)udpsrc.sin_zero, sizeof(udpsrc.sin_zero)); - if (inp->inp_flags & INP_CONTROLOPTS || inp->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(inp, &opts, ip, m); @@ -326,8 +408,14 @@ udp_input(m, va_alist) m->m_len -= iphlen; m->m_pkthdr.len -= iphlen; m->m_data += iphlen; - if (sbappendaddr(&inp->inp_socket->so_rcv, sintosa(&udpsrc), m, - opts) == 0) { + sa = (struct sockaddr *)&udpsrc; +#ifdef MAPPED_ADDR_ENABLED + if (inp->inp_socket->so_proto->pr_domain->dom_family == AF_INET6) { + in6_sin_2_v4mapsin6(&udpsrc, &mapped); + sa = (struct sockaddr *)&mapped; + } +#endif /* MAPPED_ADDR_ENABLED */ + if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) { udpstat.udps_fullsock++; goto bad; } @@ -449,6 +537,11 @@ udp_output(m, va_alist) ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ udpstat.udps_opackets++; + +#ifdef IPSEC + m->m_pkthdr.rcvif = (struct ifnet *)inp->inp_socket; +#endif /*IPSEC*/ + return (ip_output(m, inp->inp_options, &inp->inp_route, inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), inp->inp_moptions)); @@ -510,6 +603,10 @@ udp_usrreq(so, req, m, nam, control, p) break; inp = sotoinpcb(so); inp->inp_ip.ip_ttl = ip_defttl; +#ifdef IPSEC + inp = (struct inpcb *)so->so_pcb; + error = ipsec_init_policy(&inp->inp_sp); +#endif /*IPSEC*/ break; case PRU_DETACH: