version 1.68, 2000/07/06 12:51:40 |
version 1.77, 2001/05/31 19:56:13 |
|
|
* @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 |
* @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 |
*/ |
*/ |
|
|
|
#include "opt_inet.h" |
#include "opt_ipsec.h" |
#include "opt_ipsec.h" |
#include "opt_ipkdb.h" |
#include "opt_ipkdb.h" |
|
|
|
|
#endif |
#endif |
#endif |
#endif |
|
|
|
#include "faith.h" |
|
#if defined(NFAITH) && NFAITH > 0 |
|
#include <net/if_faith.h> |
|
#endif |
|
|
#include <machine/stdarg.h> |
#include <machine/stdarg.h> |
|
|
#ifdef IPSEC |
#ifdef IPSEC |
Line 131 int udpcksum = 1; |
|
Line 137 int udpcksum = 1; |
|
int udpcksum = 0; /* XXX */ |
int udpcksum = 0; /* XXX */ |
#endif |
#endif |
|
|
|
#ifdef INET |
static void udp4_sendup __P((struct mbuf *, int, struct sockaddr *, |
static void udp4_sendup __P((struct mbuf *, int, struct sockaddr *, |
struct socket *)); |
struct socket *)); |
static int udp4_realinput __P((struct sockaddr_in *, struct sockaddr_in *, |
static int udp4_realinput __P((struct sockaddr_in *, struct sockaddr_in *, |
struct mbuf *, int)); |
struct mbuf *, int)); |
|
#endif |
#ifdef INET6 |
#ifdef INET6 |
static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *, |
static void udp6_sendup __P((struct mbuf *, int, struct sockaddr *, |
struct socket *)); |
struct socket *)); |
Line 143 static int in6_mcmatch __P((struct in6pc |
|
Line 151 static int in6_mcmatch __P((struct in6pc |
|
static int udp6_realinput __P((int, struct sockaddr_in6 *, |
static int udp6_realinput __P((int, struct sockaddr_in6 *, |
struct sockaddr_in6 *, struct mbuf *, int)); |
struct sockaddr_in6 *, struct mbuf *, int)); |
#endif |
#endif |
|
#ifdef INET |
static void udp_notify __P((struct inpcb *, int)); |
static void udp_notify __P((struct inpcb *, int)); |
|
#endif |
|
|
#ifndef UDBHASHSIZE |
#ifndef UDBHASHSIZE |
#define UDBHASHSIZE 128 |
#define UDBHASHSIZE 128 |
|
|
udp_init() |
udp_init() |
{ |
{ |
|
|
|
#ifdef INET |
in_pcbinit(&udbtable, udbhashsize, udbhashsize); |
in_pcbinit(&udbtable, udbhashsize, udbhashsize); |
|
#endif |
} |
} |
|
|
#ifndef UDP6 |
#ifndef UDP6 |
|
#ifdef INET |
void |
void |
#if __STDC__ |
#if __STDC__ |
udp_input(struct mbuf *m, ...) |
udp_input(struct mbuf *m, ...) |
Line 231 udp_input(m, va_alist) |
|
Line 244 udp_input(m, va_alist) |
|
*/ |
*/ |
len = ntohs((u_int16_t)uh->uh_ulen); |
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) { |
if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { |
udpstat.udps_badlen++; |
udpstat.udps_badlen++; |
goto bad; |
goto bad; |
} |
} |
|
|
if (m) |
if (m) |
m_freem(m); |
m_freem(m); |
} |
} |
|
#endif |
|
|
#ifdef INET6 |
#ifdef INET6 |
int |
int |
Line 324 udp6_input(mp, offp, proto) |
|
Line 338 udp6_input(mp, offp, proto) |
|
struct udphdr *uh; |
struct udphdr *uh; |
u_int32_t plen, ulen; |
u_int32_t plen, ulen; |
|
|
|
#ifndef PULLDOWN_TEST |
|
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); |
|
#endif |
|
ip6 = mtod(m, struct ip6_hdr *); |
|
|
#if defined(NFAITH) && 0 < NFAITH |
#if defined(NFAITH) && 0 < NFAITH |
if (m->m_pkthdr.rcvif) { |
if (faithprefix(&ip6->ip6_dst)) { |
if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) { |
/* send icmp6 host unreach? */ |
/* send icmp6 host unreach? */ |
m_freem(m); |
m_freem(m); |
return IPPROTO_DONE; |
return IPPROTO_DONE; |
|
} |
|
} |
} |
#endif |
#endif |
|
|
udp6stat.udp6s_ipackets++; |
udp6stat.udp6s_ipackets++; |
|
|
#ifndef PULLDOWN_TEST |
|
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); |
|
#endif |
|
|
|
ip6 = mtod(m, struct ip6_hdr *); |
|
/* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ |
/* check for jumbogram is done in ip6_input. we can trust pkthdr.len */ |
plen = m->m_pkthdr.len - off; |
plen = m->m_pkthdr.len - off; |
#ifndef PULLDOWN_TEST |
#ifndef PULLDOWN_TEST |
Line 353 udp6_input(mp, offp, proto) |
|
Line 365 udp6_input(mp, offp, proto) |
|
} |
} |
#endif |
#endif |
ulen = ntohs((u_short)uh->uh_ulen); |
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) |
if (ulen == 0 && plen > 0xffff) |
ulen = plen; |
ulen = plen; |
|
|
Line 389 udp6_input(mp, offp, proto) |
|
Line 405 udp6_input(mp, offp, proto) |
|
bzero(&src, sizeof(src)); |
bzero(&src, sizeof(src)); |
src.sin6_family = AF_INET6; |
src.sin6_family = AF_INET6; |
src.sin6_len = sizeof(struct sockaddr_in6); |
src.sin6_len = sizeof(struct sockaddr_in6); |
bcopy(&ip6->ip6_src, &src.sin6_addr, sizeof(src.sin6_addr)); |
/* KAME hack: recover scopeid */ |
if (IN6_IS_SCOPE_LINKLOCAL(&src.sin6_addr)) |
(void)in6_recoverscope(&src, &ip6->ip6_src, m->m_pkthdr.rcvif); |
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; |
src.sin6_port = uh->uh_sport; |
bzero(&dst, sizeof(dst)); |
bzero(&dst, sizeof(dst)); |
dst.sin6_family = AF_INET6; |
dst.sin6_family = AF_INET6; |
dst.sin6_len = sizeof(struct sockaddr_in6); |
dst.sin6_len = sizeof(struct sockaddr_in6); |
bcopy(&ip6->ip6_dst, &dst.sin6_addr, sizeof(dst.sin6_addr)); |
/* KAME hack: recover scopeid */ |
if (IN6_IS_SCOPE_LINKLOCAL(&dst.sin6_addr)) |
(void)in6_recoverscope(&dst, &ip6->ip6_dst, m->m_pkthdr.rcvif); |
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; |
dst.sin6_port = uh->uh_dport; |
|
|
if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) { |
if (udp6_realinput(AF_INET6, &src, &dst, m, off) == 0) { |
|
|
} |
} |
#endif |
#endif |
|
|
|
#ifdef INET |
static void |
static void |
udp4_sendup(m, off, src, so) |
udp4_sendup(m, off, src, so) |
struct mbuf *m; |
struct mbuf *m; |
Line 484 udp4_sendup(m, off, src, so) |
|
Line 487 udp4_sendup(m, off, src, so) |
|
sorwakeup(so); |
sorwakeup(so); |
} |
} |
} |
} |
|
#endif |
|
|
#ifdef INET6 |
#ifdef INET6 |
static void |
static void |
Line 530 udp6_sendup(m, off, src, so) |
|
Line 534 udp6_sendup(m, off, src, so) |
|
} |
} |
#endif |
#endif |
|
|
|
#ifdef INET |
static int |
static int |
udp4_realinput(src, dst, m, off) |
udp4_realinput(src, dst, m, off) |
struct sockaddr_in *src; |
struct sockaddr_in *src; |
Line 553 udp4_realinput(src, dst, m, off) |
|
Line 558 udp4_realinput(src, dst, m, off) |
|
dst4 = &dst->sin_addr; |
dst4 = &dst->sin_addr; |
dport = &dst->sin_port; |
dport = &dst->sin_port; |
|
|
if (IN_MULTICAST(src4->s_addr) || |
if (IN_MULTICAST(dst4->s_addr) || |
in_broadcast(*dst4, m->m_pkthdr.rcvif)) { |
in_broadcast(*dst4, m->m_pkthdr.rcvif)) { |
struct inpcb *last; |
struct inpcb *last; |
/* |
/* |
Line 574 udp4_realinput(src, dst, m, off) |
|
Line 579 udp4_realinput(src, dst, m, off) |
|
|
|
/* |
/* |
* KAME note: usually we drop udpiphdr from mbuf here. |
* 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. |
* Locate pcb(s) for datagram. |
Line 666 udp4_realinput(src, dst, m, off) |
|
Line 671 udp4_realinput(src, dst, m, off) |
|
bad: |
bad: |
return rcvcnt; |
return rcvcnt; |
} |
} |
|
#endif |
|
|
#ifdef INET6 |
#ifdef INET6 |
static int |
static int |
Line 702 udp6_realinput(af, src, dst, m, off) |
|
Line 708 udp6_realinput(af, src, dst, m, off) |
|
u_int16_t *sport, *dport; |
u_int16_t *sport, *dport; |
int rcvcnt; |
int rcvcnt; |
struct in6_addr *src6, *dst6; |
struct in6_addr *src6, *dst6; |
struct in_addr *src4; |
struct in_addr *dst4; |
struct in6pcb *in6p; |
struct in6pcb *in6p; |
|
|
rcvcnt = 0; |
rcvcnt = 0; |
Line 717 udp6_realinput(af, src, dst, m, off) |
|
Line 723 udp6_realinput(af, src, dst, m, off) |
|
sport = &src->sin6_port; |
sport = &src->sin6_port; |
dst6 = &dst->sin6_addr; |
dst6 = &dst->sin6_addr; |
dport = &dst->sin6_port; |
dport = &dst->sin6_port; |
src4 = (struct in_addr *)&src->sin6_addr.s6_addr32[12]; |
dst4 = (struct in_addr *)&dst->sin6_addr.s6_addr32[12]; |
|
|
if (IN6_IS_ADDR_MULTICAST(dst6) |
if (IN6_IS_ADDR_MULTICAST(dst6) |
|| (af == AF_INET && IN_MULTICAST(src4->s_addr))) { |
|| (af == AF_INET && IN_MULTICAST(dst4->s_addr))) { |
struct in6pcb *last; |
struct in6pcb *last; |
/* |
/* |
* Deliver a multicast or broadcast datagram to *all* sockets |
* Deliver a multicast or broadcast datagram to *all* sockets |
Line 740 udp6_realinput(af, src, dst, m, off) |
|
Line 746 udp6_realinput(af, src, dst, m, off) |
|
|
|
/* |
/* |
* KAME note: usually we drop udpiphdr from mbuf here. |
* 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. |
* Locate pcb(s) for datagram. |
Line 924 udp_input(m, va_alist) |
|
Line 930 udp_input(m, va_alist) |
|
*/ |
*/ |
len = ntohs((u_int16_t)uh->uh_ulen); |
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) { |
if (ip->ip_len < iphlen + len || len < sizeof(struct udphdr)) { |
udpstat.udps_badlen++; |
udpstat.udps_badlen++; |
goto bad; |
goto bad; |
} |
} |
Line 981 udp_input(m, va_alist) |
|
Line 987 udp_input(m, va_alist) |
|
iphlen += sizeof(struct udphdr); |
iphlen += sizeof(struct udphdr); |
/* |
/* |
* KAME note: usually we drop udpiphdr from mbuf here. |
* 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. |
* Locate pcb(s) for datagram. |
|
|
} |
} |
#endif /*UDP6*/ |
#endif /*UDP6*/ |
|
|
|
#ifdef INET |
/* |
/* |
* Notify a udp user of an asynchronous error; |
* Notify a udp user of an asynchronous error; |
* just wake up so that he can collect error status. |
* just wake up so that he can collect error status. |
Line 1253 udp_output(m, va_alist) |
|
Line 1260 udp_output(m, va_alist) |
|
udpstat.udps_opackets++; |
udpstat.udps_opackets++; |
|
|
#ifdef IPSEC |
#ifdef IPSEC |
ipsec_setsocket(m, inp->inp_socket); |
if (ipsec_setsocket(m, inp->inp_socket) != 0) { |
|
error = ENOBUFS; |
|
goto release; |
|
} |
#endif /*IPSEC*/ |
#endif /*IPSEC*/ |
|
|
return (ip_output(m, inp->inp_options, &inp->inp_route, |
return (ip_output(m, inp->inp_options, &inp->inp_route, |
Line 1472 udp_sysctl(name, namelen, oldp, oldlenp, |
|
Line 1482 udp_sysctl(name, namelen, oldp, oldlenp, |
|
} |
} |
/* NOTREACHED */ |
/* NOTREACHED */ |
} |
} |
|
#endif |