| version 1.47, 1999/01/19 23:03:22 |
version 1.47.4.1, 1999/07/01 23:47:04 |
|
|
| /* $NetBSD$ */ |
/* $NetBSD$ */ |
| |
|
| /* |
/* |
| |
* 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 |
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 |
| * The Regents of the University of California. All rights reserved. |
* The Regents of the University of California. All rights reserved. |
| * |
* |
|
|
| */ |
*/ |
| #include "ipkdb.h" |
#include "ipkdb.h" |
| |
|
| |
/* XXX MAPPED_ADDR_ENABLED should be revisited */ |
| |
|
| #include <sys/param.h> |
#include <sys/param.h> |
| #include <sys/malloc.h> |
#include <sys/malloc.h> |
| #include <sys/mbuf.h> |
#include <sys/mbuf.h> |
| |
#ifdef MAPPED_ADDR_ENABLED |
| |
#include <sys/domain.h> |
| |
#endif /* MAPPED_ADDR_ENABLED */ |
| #include <sys/protosw.h> |
#include <sys/protosw.h> |
| #include <sys/socket.h> |
#include <sys/socket.h> |
| #include <sys/socketvar.h> |
#include <sys/socketvar.h> |
|
|
| |
|
| #include <machine/stdarg.h> |
#include <machine/stdarg.h> |
| |
|
| |
#ifdef IPSEC |
| |
#include <netinet6/ipsec.h> |
| |
#include <netkey/key.h> |
| |
#include <netkey/key_debug.h> |
| |
#endif /*IPSEC*/ |
| |
|
| /* |
/* |
| * UDP protocol implementation. |
* UDP protocol implementation. |
| * Per RFC 768, August, 1980. |
* Per RFC 768, August, 1980. |
| Line 98 udp_input(m, va_alist) |
|
| Line 138 udp_input(m, va_alist) |
|
| va_dcl |
va_dcl |
| #endif |
#endif |
| { |
{ |
| |
int proto; |
| register struct ip *ip; |
register struct ip *ip; |
| register struct udphdr *uh; |
register struct udphdr *uh; |
| register struct inpcb *inp; |
register struct inpcb *inp; |
| Line 107 udp_input(m, va_alist) |
|
| Line 148 udp_input(m, va_alist) |
|
| int iphlen; |
int iphlen; |
| va_list ap; |
va_list ap; |
| struct sockaddr_in udpsrc; |
struct sockaddr_in udpsrc; |
| |
#ifdef MAPPED_ADDR_ENABLED |
| |
struct sockaddr_in6 mapped; |
| |
#endif |
| |
struct sockaddr *sa; |
| |
|
| va_start(ap, m); |
va_start(ap, m); |
| iphlen = va_arg(ap, int); |
iphlen = va_arg(ap, int); |
| |
proto = va_arg(ap, int); |
| va_end(ap); |
va_end(ap); |
| |
|
| udpstat.udps_ipackets++; |
udpstat.udps_ipackets++; |
| Line 170 udp_input(m, va_alist) |
|
| Line 216 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) || |
if (IN_MULTICAST(ip->ip_dst.s_addr) || |
| in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { |
in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { |
| struct inpcb *last; |
struct inpcb *last; |
| Line 189 udp_input(m, va_alist) |
|
| Line 244 udp_input(m, va_alist) |
|
| * fixing the interface. Maybe 4.5BSD will remedy this?) |
* 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. |
* Locate pcb(s) for datagram. |
| * (Algorithm copied from raw_intr().) |
* (Algorithm copied from raw_intr().) |
| Line 225 udp_input(m, va_alist) |
|
| Line 272 udp_input(m, va_alist) |
|
| if (last != NULL) { |
if (last != NULL) { |
| struct mbuf *n; |
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 ((n = m_copy(m, 0, M_COPYALL)) != NULL) { |
| |
m_adj(m, iphlen); |
| if (last->inp_flags & INP_CONTROLOPTS |
if (last->inp_flags & INP_CONTROLOPTS |
| || last->inp_socket->so_options & |
|| last->inp_socket->so_options & |
| SO_TIMESTAMP) { |
SO_TIMESTAMP) { |
| ip_savecontrol(last, &opts, |
ip_savecontrol(last, &opts, |
| ip, n); |
ip, n); |
| } |
} |
| |
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( |
if (sbappendaddr( |
| &last->inp_socket->so_rcv, |
&last->inp_socket->so_rcv, |
| sintosa(&udpsrc), n, opts) == 0) { |
sa, n, opts) == 0) { |
| m_freem(n); |
m_freem(n); |
| if (opts) |
if (opts) |
| m_freem(opts); |
m_freem(opts); |
| Line 263 udp_input(m, va_alist) |
|
| Line 326 udp_input(m, va_alist) |
|
| * (No need to send an ICMP Port Unreachable |
* (No need to send an ICMP Port Unreachable |
| * for a broadcast or multicast datgram.) |
* for a broadcast or multicast datgram.) |
| */ |
*/ |
| |
udpstat.udps_noport++; |
| udpstat.udps_noportbcast++; |
udpstat.udps_noportbcast++; |
| goto bad; |
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 || |
if (last->inp_flags & INP_CONTROLOPTS || |
| last->inp_socket->so_options & SO_TIMESTAMP) |
last->inp_socket->so_options & SO_TIMESTAMP) |
| ip_savecontrol(last, &opts, ip, m); |
ip_savecontrol(last, &opts, ip, m); |
| if (sbappendaddr(&last->inp_socket->so_rcv, |
sa = (struct sockaddr *)&udpsrc; |
| sintosa(&udpsrc), m, opts) == 0) { |
#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++; |
udpstat.udps_fullsock++; |
| goto bad; |
goto bad; |
| } |
} |
| Line 306 udp_input(m, va_alist) |
|
| Line 384 udp_input(m, va_alist) |
|
| return; |
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. |
* 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 || |
if (inp->inp_flags & INP_CONTROLOPTS || |
| inp->inp_socket->so_options & SO_TIMESTAMP) |
inp->inp_socket->so_options & SO_TIMESTAMP) |
| ip_savecontrol(inp, &opts, ip, m); |
ip_savecontrol(inp, &opts, ip, m); |
| Line 324 udp_input(m, va_alist) |
|
| Line 401 udp_input(m, va_alist) |
|
| m->m_len -= iphlen; |
m->m_len -= iphlen; |
| m->m_pkthdr.len -= iphlen; |
m->m_pkthdr.len -= iphlen; |
| m->m_data += iphlen; |
m->m_data += iphlen; |
| if (sbappendaddr(&inp->inp_socket->so_rcv, sintosa(&udpsrc), m, |
sa = (struct sockaddr *)&udpsrc; |
| opts) == 0) { |
#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++; |
udpstat.udps_fullsock++; |
| goto bad; |
goto bad; |
| } |
} |
| Line 447 udp_output(m, va_alist) |
|
| Line 530 udp_output(m, va_alist) |
|
| ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ |
((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ |
| ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
| udpstat.udps_opackets++; |
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, |
return (ip_output(m, inp->inp_options, &inp->inp_route, |
| inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), |
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), |
| inp->inp_moptions)); |
inp->inp_moptions)); |
| Line 508 udp_usrreq(so, req, m, nam, control, p) |
|
| Line 596 udp_usrreq(so, req, m, nam, control, p) |
|
| break; |
break; |
| inp = sotoinpcb(so); |
inp = sotoinpcb(so); |
| inp->inp_ip.ip_ttl = ip_defttl; |
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; |
break; |
| |
|
| case PRU_DETACH: |
case PRU_DETACH: |