remove unused codepath (unifdef -UUDP6)
This commit is contained in:
parent
7bbe09e1d4
commit
c7e6405a34
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: udp_usrreq.c,v 1.85 2001/10/15 09:51:15 itojun Exp $ */
|
||||
/* $NetBSD: udp_usrreq.c,v 1.86 2001/10/24 06:04:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -197,7 +197,6 @@ udp_init()
|
|||
#endif /* UDP_CSUM_COUNTERS */
|
||||
}
|
||||
|
||||
#ifndef UDP6
|
||||
#ifdef INET
|
||||
void
|
||||
#if __STDC__
|
||||
|
@ -833,309 +832,6 @@ bad:
|
|||
}
|
||||
#endif
|
||||
|
||||
#else /*UDP6*/
|
||||
|
||||
void
|
||||
#if __STDC__
|
||||
udp_input(struct mbuf *m, ...)
|
||||
#else
|
||||
udp_input(m, va_alist)
|
||||
struct mbuf *m;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
int proto;
|
||||
struct ip *ip;
|
||||
struct udphdr *uh;
|
||||
struct inpcb *inp;
|
||||
struct mbuf *opts = 0;
|
||||
int len;
|
||||
struct ip save_ip;
|
||||
int iphlen;
|
||||
va_list ap;
|
||||
struct sockaddr_in udpsrc;
|
||||
struct sockaddr *sa;
|
||||
|
||||
va_start(ap, m);
|
||||
iphlen = va_arg(ap, int);
|
||||
proto = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
|
||||
udpstat.udps_ipackets++;
|
||||
|
||||
/*
|
||||
* Strip IP options, if any; should skip this,
|
||||
* make available to user, and use on returned packets,
|
||||
* but we don't yet have a way to check the checksum
|
||||
* with options still present.
|
||||
*/
|
||||
if (iphlen > sizeof (struct ip)) {
|
||||
ip_stripoptions(m, (struct mbuf *)0);
|
||||
iphlen = sizeof(struct ip);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get IP and UDP header together in first mbuf.
|
||||
*/
|
||||
ip = mtod(m, struct ip *);
|
||||
if (m->m_len < iphlen + sizeof(struct udphdr)) {
|
||||
if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
|
||||
udpstat.udps_hdrops++;
|
||||
return;
|
||||
}
|
||||
ip = mtod(m, struct ip *);
|
||||
}
|
||||
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)) {
|
||||
udpstat.udps_badlen++;
|
||||
goto bad;
|
||||
}
|
||||
m_adj(m, iphlen + len - ip->ip_len);
|
||||
}
|
||||
/*
|
||||
* Save a copy of the IP header in case we want restore it
|
||||
* for sending an ICMP error message in response.
|
||||
*/
|
||||
save_ip = *ip;
|
||||
|
||||
/*
|
||||
* Checksum extended UDP header and data.
|
||||
*/
|
||||
if (uh->uh_sum) {
|
||||
switch (m->m_pkthdr.csum_flags &
|
||||
((m->m_pkthdr.rcvif->if_csum_flags & M_CSUM_UDPv4) |
|
||||
M_CSUM_TCP_UDP_BAD | M_CSUM_DATA)) {
|
||||
case M_CSUM_UDPv4|M_CSUM_TCP_UDP_BAD:
|
||||
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_bad);
|
||||
goto badcsum;
|
||||
|
||||
case M_CSUM_UDPv4|M_CSUM_DATA:
|
||||
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_data);
|
||||
if ((m->m_pkthdr.csum_data ^ 0xffff) != 0)
|
||||
goto badcsum;
|
||||
break;
|
||||
|
||||
case M_CSUM_UDPv4:
|
||||
/* Checksum was okay. */
|
||||
UDP_CSUM_COUNTER_INCR(&udp_hwcsum_ok);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Need to compute it ourselves. */
|
||||
UDP_CSUM_COUNTER_INCR(&udp_swcsum);
|
||||
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)
|
||||
goto badcsum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
/*
|
||||
* Deliver a multicast or broadcast datagram to *all* sockets
|
||||
* for which the local and remote addresses and ports match
|
||||
* those of the incoming datagram. This allows more than
|
||||
* one process to receive multi/broadcasts on the same port.
|
||||
* (This really ought to be done for unicast datagrams as
|
||||
* well, but that would cause problems with existing
|
||||
* applications that open both address-specific sockets and
|
||||
* a wildcard socket listening to the same port -- they would
|
||||
* end up receiving duplicates of every unicast datagram.
|
||||
* Those applications open the multiple sockets to overcome an
|
||||
* inadequacy of the UDP socket interface, but for backwards
|
||||
* compatibility we avoid the problem here rather than
|
||||
* fixing the interface. Maybe 4.5BSD will remedy this?)
|
||||
*/
|
||||
|
||||
iphlen += sizeof(struct udphdr);
|
||||
/*
|
||||
* KAME note: usually we drop udpiphdr from mbuf here.
|
||||
* we need udpiphdr for IPsec processing so we do that later.
|
||||
*/
|
||||
/*
|
||||
* Locate pcb(s) for datagram.
|
||||
* (Algorithm copied from raw_intr().)
|
||||
*/
|
||||
last = NULL;
|
||||
for (inp = udbtable.inpt_queue.cqh_first;
|
||||
inp != (struct inpcb *)&udbtable.inpt_queue;
|
||||
inp = inp->inp_queue.cqe_next) {
|
||||
if (inp->inp_lport != uh->uh_dport)
|
||||
continue;
|
||||
if (!in_nullhost(inp->inp_laddr)) {
|
||||
if (!in_hosteq(inp->inp_laddr, ip->ip_dst))
|
||||
continue;
|
||||
}
|
||||
if (!in_nullhost(inp->inp_faddr)) {
|
||||
if (!in_hosteq(inp->inp_faddr, ip->ip_src) ||
|
||||
inp->inp_fport != uh->uh_sport)
|
||||
continue;
|
||||
}
|
||||
|
||||
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 &
|
||||
SO_TIMESTAMP) {
|
||||
ip_savecontrol(last, &opts,
|
||||
ip, n);
|
||||
}
|
||||
m_adj(n, iphlen);
|
||||
sa = (struct sockaddr *)&udpsrc;
|
||||
if (sbappendaddr(
|
||||
&last->inp_socket->so_rcv,
|
||||
sa, n, opts) == 0) {
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udpstat.udps_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->inp_socket);
|
||||
opts = 0;
|
||||
}
|
||||
}
|
||||
last = inp;
|
||||
/*
|
||||
* Don't look for additional matches if this one does
|
||||
* not have either the SO_REUSEPORT or SO_REUSEADDR
|
||||
* socket options set. This heuristic avoids searching
|
||||
* through all pcbs in the common case of a non-shared
|
||||
* port. It * assumes that an application will never
|
||||
* clear these options after setting them.
|
||||
*/
|
||||
if ((last->inp_socket->so_options &
|
||||
(SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (last == NULL) {
|
||||
/*
|
||||
* No matching pcb found; discard datagram.
|
||||
* (No need to send an ICMP Port Unreachable
|
||||
* for a broadcast or multicast datgram.)
|
||||
*/
|
||||
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);
|
||||
m->m_len -= iphlen;
|
||||
m->m_pkthdr.len -= iphlen;
|
||||
m->m_data += iphlen;
|
||||
sa = (struct sockaddr *)&udpsrc;
|
||||
if (sbappendaddr(&last->inp_socket->so_rcv, sa, m, opts) == 0) {
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(last->inp_socket);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Locate pcb for datagram.
|
||||
*/
|
||||
inp = in_pcblookup_connect(&udbtable, ip->ip_src, uh->uh_sport,
|
||||
ip->ip_dst, uh->uh_dport);
|
||||
if (inp == 0) {
|
||||
++udpstat.udps_pcbhashmiss;
|
||||
inp = in_pcblookup_bind(&udbtable, ip->ip_dst, uh->uh_dport);
|
||||
if (inp == 0) {
|
||||
if (m->m_flags & (M_BCAST | M_MCAST)) {
|
||||
udpstat.udps_noportbcast++;
|
||||
goto bad;
|
||||
}
|
||||
udpstat.udps_noport++;
|
||||
*ip = save_ip;
|
||||
#ifdef IPKDB
|
||||
if (checkipkdb(&ip->ip_src,
|
||||
uh->uh_sport,
|
||||
uh->uh_dport,
|
||||
m,
|
||||
iphlen + sizeof(struct udphdr),
|
||||
len - sizeof(struct udphdr)))
|
||||
/* It was a debugger connect packet, just drop it now */
|
||||
goto bad;
|
||||
#endif
|
||||
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*/
|
||||
|
||||
/*
|
||||
* Stuff source address and datagram in user buffer.
|
||||
*/
|
||||
if (inp->inp_flags & INP_CONTROLOPTS ||
|
||||
inp->inp_socket->so_options & SO_TIMESTAMP)
|
||||
ip_savecontrol(inp, &opts, ip, m);
|
||||
iphlen += sizeof(struct udphdr);
|
||||
m->m_len -= iphlen;
|
||||
m->m_pkthdr.len -= iphlen;
|
||||
m->m_data += iphlen;
|
||||
sa = (struct sockaddr *)&udpsrc;
|
||||
if (sbappendaddr(&inp->inp_socket->so_rcv, sa, m, opts) == 0) {
|
||||
udpstat.udps_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(inp->inp_socket);
|
||||
return;
|
||||
bad:
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
return;
|
||||
|
||||
badcsum:
|
||||
udpstat.udps_badsum++;
|
||||
m_freem(m);
|
||||
}
|
||||
#endif /*UDP6*/
|
||||
|
||||
#ifdef INET
|
||||
/*
|
||||
* Notify a udp user of an asynchronous error;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: udp6_usrreq.c,v 1.47 2001/10/18 07:44:36 itojun Exp $ */
|
||||
/* $NetBSD: udp6_usrreq.c,v 1.48 2001/10/24 06:04:08 itojun Exp $ */
|
||||
/* $KAME: udp6_usrreq.c,v 1.86 2001/05/27 17:33:00 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -114,9 +114,6 @@
|
|||
|
||||
struct in6pcb *udp6_last_in6pcb = &udb6;
|
||||
|
||||
#ifdef UDP6
|
||||
static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, struct ifnet *));
|
||||
#endif
|
||||
static void udp6_detach __P((struct in6pcb *));
|
||||
static void udp6_notify __P((struct in6pcb *, int));
|
||||
|
||||
|
@ -126,329 +123,6 @@ udp6_init()
|
|||
udb6.in6p_next = udb6.in6p_prev = &udb6;
|
||||
}
|
||||
|
||||
#ifdef UDP6
|
||||
static int
|
||||
in6_mcmatch(in6p, ia6, ifp)
|
||||
struct in6pcb *in6p;
|
||||
struct in6_addr *ia6;
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct ip6_moptions *im6o = in6p->in6p_moptions;
|
||||
struct in6_multi_mship *imm;
|
||||
|
||||
if (im6o == NULL)
|
||||
return 0;
|
||||
|
||||
for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
|
||||
imm = imm->i6mm_chain.le_next) {
|
||||
if ((ifp == NULL ||
|
||||
imm->i6mm_maddr->in6m_ifp == ifp) &&
|
||||
IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
|
||||
ia6))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
udp6_input(mp, offp, proto)
|
||||
struct mbuf **mp;
|
||||
int *offp, proto;
|
||||
{
|
||||
struct mbuf *m = *mp;
|
||||
struct ip6_hdr *ip6;
|
||||
struct udphdr *uh;
|
||||
struct in6pcb *in6p;
|
||||
struct mbuf *opts = 0;
|
||||
int off = *offp;
|
||||
u_int32_t plen, ulen;
|
||||
struct sockaddr_in6 udp_in6;
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
|
||||
#if defined(NFAITH) && 0 < NFAITH
|
||||
if (faithprefix(&ip6->ip6_dst)) {
|
||||
/* send icmp6 host unreach? */
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
udp6stat.udp6s_ipackets++;
|
||||
|
||||
/* check for jumbogram is done in ip6_input. we can trust pkthdr.len */
|
||||
plen = m->m_pkthdr.len - off;
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
|
||||
uh = (struct udphdr *)((caddr_t)ip6 + off);
|
||||
#else
|
||||
IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
|
||||
if (uh == NULL) {
|
||||
udp6stat.udp6s_hdrops++;
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#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;
|
||||
|
||||
if (plen != ulen) {
|
||||
udp6stat.udp6s_badlen++;
|
||||
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)) {
|
||||
/* XXX stat */
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checksum extended UDP header and data.
|
||||
*/
|
||||
if (uh->uh_sum == 0)
|
||||
udp6stat.udp6s_nosum++;
|
||||
else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
|
||||
udp6stat.udp6s_badsum++;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
|
||||
struct in6pcb *last;
|
||||
|
||||
/*
|
||||
* Deliver a multicast datagram to all sockets
|
||||
* for which the local and remote addresses and ports match
|
||||
* those of the incoming datagram. This allows more than
|
||||
* one process to receive multicasts on the same port.
|
||||
* (This really ought to be done for unicast datagrams as
|
||||
* well, but that would cause problems with existing
|
||||
* applications that open both address-specific sockets and
|
||||
* a wildcard socket listening to the same port -- they would
|
||||
* end up receiving duplicates of every unicast datagram.
|
||||
* Those applications open the multiple sockets to overcome an
|
||||
* inadequacy of the UDP socket interface, but for backwards
|
||||
* compatibility we avoid the problem here rather than
|
||||
* fixing the interface. Maybe 4.5BSD will remedy this?)
|
||||
*/
|
||||
|
||||
/*
|
||||
* In a case that laddr should be set to the link-local
|
||||
* address (this happens in RIPng), the multicast address
|
||||
* specified in the received packet does not match with
|
||||
* laddr. To cure this situation, the matching is relaxed
|
||||
* if the receiving interface is the same as one specified
|
||||
* in the socket and if the destination multicast address
|
||||
* matches one of the multicast groups specified in the socket.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Construct sockaddr format source address.
|
||||
*/
|
||||
bzero(&udp_in6, sizeof(udp_in6));
|
||||
udp_in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
udp_in6.sin6_family = AF_INET6;
|
||||
udp_in6.sin6_port = uh->uh_sport;
|
||||
#if 0 /*XXX inbound flowinfo */
|
||||
udp_in6.sin6_flowinfo = ip6->ip6_flow & IPV6_FLOWINFO_MASK;
|
||||
#endif
|
||||
/* KAME hack: recover scopeid */
|
||||
(void)in6_recoverscope(&udp_in6, &ip6->ip6_src,
|
||||
m->m_pkthdr.rcvif);
|
||||
|
||||
/*
|
||||
* KAME note: traditionally we dropped udpiphdr from mbuf here.
|
||||
* We need udphdr for IPsec processing so we do that later.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Locate pcb(s) for datagram.
|
||||
* (Algorithm copied from raw_intr().)
|
||||
*/
|
||||
last = NULL;
|
||||
for (in6p = udb6.in6p_next;
|
||||
in6p != &udb6;
|
||||
in6p = in6p->in6p_next) {
|
||||
if (in6p->in6p_lport != uh->uh_dport)
|
||||
continue;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
|
||||
&ip6->ip6_dst) &&
|
||||
!in6_mcmatch(in6p, &ip6->ip6_dst,
|
||||
m->m_pkthdr.rcvif))
|
||||
continue;
|
||||
}
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
|
||||
&ip6->ip6_src) ||
|
||||
in6p->in6p_fport != uh->uh_sport)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (last != NULL) {
|
||||
struct mbuf *n;
|
||||
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (ipsec6_in_reject(m, last)) {
|
||||
ipsec6stat.in_polvio++;
|
||||
/* do not inject data into pcb */
|
||||
} else
|
||||
#endif /*IPSEC*/
|
||||
if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
|
||||
/*
|
||||
* KAME NOTE: do not
|
||||
* m_copy(m, offset, ...) above.
|
||||
* sbappendaddr() expects M_PKTHDR,
|
||||
* and m_copy() will copy M_PKTHDR
|
||||
* only if offset is 0.
|
||||
*/
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| last->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
ip6_savecontrol(last, &opts,
|
||||
ip6, n);
|
||||
}
|
||||
|
||||
m_adj(n, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
n, opts) == 0) {
|
||||
m_freem(n);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
udp6stat.udp6s_fullsock++;
|
||||
} else
|
||||
sorwakeup(last->in6p_socket);
|
||||
opts = 0;
|
||||
}
|
||||
}
|
||||
last = in6p;
|
||||
/*
|
||||
* Don't look for additional matches if this one does
|
||||
* not have either the SO_REUSEPORT or SO_REUSEADDR
|
||||
* socket options set. This heuristic avoids searching
|
||||
* through all pcbs in the common case of a non-shared
|
||||
* port. It assumes that an application will never
|
||||
* clear these options after setting them.
|
||||
*/
|
||||
if ((last->in6p_socket->so_options &
|
||||
(SO_REUSEPORT|SO_REUSEADDR)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (last == NULL) {
|
||||
/*
|
||||
* No matching pcb found; discard datagram.
|
||||
* (No need to send an ICMP Port Unreachable
|
||||
* for a broadcast or multicast datgram.)
|
||||
*/
|
||||
udp6stat.udp6s_noport++;
|
||||
udp6stat.udp6s_noportmcast++;
|
||||
goto bad;
|
||||
}
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (last != NULL && ipsec6_in_reject(m, last)) {
|
||||
ipsec6stat.in_polvio++;
|
||||
goto bad;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
if (last->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| last->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
ip6_savecontrol(last, &opts, ip6, m);
|
||||
}
|
||||
|
||||
m_adj(m, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&last->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
m, opts) == 0) {
|
||||
udp6stat.udp6s_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(last->in6p_socket);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
/*
|
||||
* Locate pcb for datagram.
|
||||
*/
|
||||
in6p = udp6_last_in6pcb;
|
||||
if (in6p->in6p_lport != uh->uh_dport ||
|
||||
in6p->in6p_fport != uh->uh_sport ||
|
||||
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src) ||
|
||||
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) {
|
||||
in6p = in6_pcblookup(&udb6,
|
||||
&ip6->ip6_src, uh->uh_sport,
|
||||
&ip6->ip6_dst, uh->uh_dport,
|
||||
IN6PLOOKUP_WILDCARD);
|
||||
if (in6p)
|
||||
udp6_last_in6pcb = in6p;
|
||||
udp6stat.udp6ps_pcbcachemiss++;
|
||||
}
|
||||
if (in6p == 0) {
|
||||
udp6stat.udp6s_noport++;
|
||||
if (m->m_flags & M_MCAST) {
|
||||
udp6stat.udp6s_noportmcast++;
|
||||
goto bad;
|
||||
}
|
||||
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#ifdef IPSEC
|
||||
/*
|
||||
* Check AH/ESP integrity.
|
||||
*/
|
||||
if (in6p != NULL && ipsec6_in_reject(m, in6p)) {
|
||||
ipsec6stat.in_polvio++;
|
||||
goto bad;
|
||||
}
|
||||
#endif /*IPSEC*/
|
||||
|
||||
/*
|
||||
* Construct sockaddr format source address.
|
||||
* Stuff source address and datagram in user buffer.
|
||||
*/
|
||||
bzero(&udp_in6, sizeof(udp_in6));
|
||||
udp_in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
udp_in6.sin6_family = AF_INET6;
|
||||
udp_in6.sin6_port = uh->uh_sport;
|
||||
/* KAME hack: recover scopeid */
|
||||
(void)in6_recoverscope(&udp_in6, &ip6->ip6_src, m->m_pkthdr.rcvif);
|
||||
if (in6p->in6p_flags & IN6P_CONTROLOPTS
|
||||
|| in6p->in6p_socket->so_options & SO_TIMESTAMP) {
|
||||
ip6_savecontrol(in6p, &opts, ip6, m);
|
||||
}
|
||||
|
||||
m_adj(m, off + sizeof(struct udphdr));
|
||||
if (sbappendaddr(&in6p->in6p_socket->so_rcv,
|
||||
(struct sockaddr *)&udp_in6,
|
||||
m, opts) == 0) {
|
||||
udp6stat.udp6s_fullsock++;
|
||||
goto bad;
|
||||
}
|
||||
sorwakeup(in6p->in6p_socket);
|
||||
return IPPROTO_DONE;
|
||||
bad:
|
||||
if (m)
|
||||
m_freem(m);
|
||||
if (opts)
|
||||
m_freem(opts);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Notify a udp user of an asynchronous error;
|
||||
* just wake up so that he can collect error status.
|
||||
|
|
Loading…
Reference in New Issue