| version 1.47, 1999/01/19 23:03:22 |
version 1.47.6.1, 1999/06/28 06:37:02 |
|
|
| #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 107 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 117 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 185 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 213 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 241 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 295 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 353 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 370 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; |
| } |
} |
|
|
| m_freem(m); |
m_freem(m); |
| if (opts) |
if (opts) |
| m_freem(opts); |
m_freem(opts); |
| |
return; |
| } |
} |
| |
|
| /* |
/* |
| Line 447 udp_output(m, va_alist) |
|
| Line 500 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 566 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: |