pull latest kame pcbnotify code. synchronizes ICMPv6 path mtu discovery
behavior with other protocols (i.e. validation, use of hiwat/lowat).
This commit is contained in:
parent
9e66537acb
commit
bc5a6e2482
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: tcp_subr.c,v 1.106 2001/01/24 09:04:16 itojun Exp $ */
|
||||
/* $NetBSD: tcp_subr.c,v 1.107 2001/02/11 06:49:49 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -1110,16 +1110,14 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
struct sockaddr *sa;
|
||||
void *d;
|
||||
{
|
||||
struct tcphdr *thp;
|
||||
struct tcphdr th;
|
||||
void (*notify) __P((struct in6pcb *, int)) = tcp6_notify;
|
||||
int nmatch;
|
||||
struct sockaddr_in6 sa6;
|
||||
struct ip6_hdr *ip6;
|
||||
const struct sockaddr_in6 *sa6_src = NULL;
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
struct mbuf *m;
|
||||
int off;
|
||||
struct in6_addr finaldst;
|
||||
struct in6_addr s;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
@ -1144,26 +1142,13 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
|
||||
/* translate addresses into internal form */
|
||||
bcopy(ip6cp->ip6c_finaldst, &finaldst, sizeof(finaldst));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&finaldst)) {
|
||||
finaldst.s6_addr16[1] =
|
||||
htons(m->m_pkthdr.rcvif->if_index);
|
||||
}
|
||||
bcopy(&ip6->ip6_src, &s, sizeof(s));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&s))
|
||||
s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
sa6_src = ip6cp->ip6c_src;
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
sa6_src = &sa6_any;
|
||||
}
|
||||
|
||||
/* translate addresses into internal form */
|
||||
sa6 = *(struct sockaddr_in6 *)sa;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
|
||||
sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
|
||||
if (ip6) {
|
||||
/*
|
||||
* XXX: We assume that when ip6 is non NULL,
|
||||
@ -1174,15 +1159,8 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
if (m->m_pkthdr.len < off + sizeof(th))
|
||||
return;
|
||||
|
||||
if (m->m_len < off + sizeof(th)) {
|
||||
/*
|
||||
* this should be rare case,
|
||||
* so we compromise on this copy...
|
||||
*/
|
||||
m_copydata(m, off, sizeof(th), (caddr_t)&th);
|
||||
thp = &th;
|
||||
} else
|
||||
thp = (struct tcphdr *)(mtod(m, caddr_t) + off);
|
||||
bzero(&th, sizeof(th));
|
||||
m_copydata(m, off, sizeof(th), (caddr_t)&th);
|
||||
|
||||
if (cmd == PRC_MSGSIZE) {
|
||||
int valid = 0;
|
||||
@ -1192,38 +1170,38 @@ tcp6_ctlinput(cmd, sa, d)
|
||||
* corresponding to the address in the ICMPv6 message
|
||||
* payload.
|
||||
*/
|
||||
if (in6_pcblookup_connect(&tcb6, &finaldst,
|
||||
thp->th_dport, &s, thp->th_sport, 0))
|
||||
if (in6_pcblookup_connect(&tcb6, &sa6->sin6_addr,
|
||||
th.th_dport, (struct in6_addr *)&sa6_src->sin6_addr,
|
||||
th.th_sport, 0))
|
||||
valid++;
|
||||
|
||||
/*
|
||||
* Now that we've validated that we are actually
|
||||
* communicating with the host indicated in the ICMPv6
|
||||
* message, recalculate the new MTU, and create the
|
||||
* corresponding routing entry.
|
||||
* Depending on the value of "valid" and routing table
|
||||
* size (mtudisc_{hi,lo}wat), we will:
|
||||
* - recalcurate the new MTU and create the
|
||||
* corresponding routing entry, or
|
||||
* - ignore the MTU change notification.
|
||||
*/
|
||||
icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
|
||||
|
||||
/*
|
||||
* no need to call in6_pcbnotify, it should have been
|
||||
* called via callback if necessary
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
nmatch = in6_pcbnotify(&tcb6, (struct sockaddr *)&sa6,
|
||||
thp->th_dport, &s, thp->th_sport, cmd, notify);
|
||||
nmatch = in6_pcbnotify(&tcb6, sa, th.th_dport,
|
||||
(struct sockaddr *)sa6_src, th.th_sport, cmd, NULL, notify);
|
||||
if (nmatch == 0 && syn_cache_count &&
|
||||
(inet6ctlerrmap[cmd] == EHOSTUNREACH ||
|
||||
inet6ctlerrmap[cmd] == ENETUNREACH ||
|
||||
inet6ctlerrmap[cmd] == EHOSTDOWN)) {
|
||||
struct sockaddr_in6 sin6;
|
||||
bzero(&sin6, sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_port = thp->th_sport;
|
||||
sin6.sin6_addr = s;
|
||||
syn_cache_unreach((struct sockaddr *)&sin6, sa, thp);
|
||||
}
|
||||
inet6ctlerrmap[cmd] == EHOSTDOWN))
|
||||
syn_cache_unreach((struct sockaddr *)sa6_src,
|
||||
sa, &th);
|
||||
} else {
|
||||
(void) in6_pcbnotify(&tcb6, (struct sockaddr *)&sa6, 0,
|
||||
&zeroin6_addr, 0, cmd, notify);
|
||||
(void) in6_pcbnotify(&tcb6, sa, 0, (struct sockaddr *)sa6_src,
|
||||
0, cmd, NULL, notify);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1409,7 +1387,7 @@ tcp6_mtudisc_callback(faddr)
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_addr = *faddr;
|
||||
(void) in6_pcbnotify(&tcb6, (struct sockaddr *)&sin6, 0,
|
||||
&zeroin6_addr, 0, PRC_MSGSIZE, tcp6_mtudisc);
|
||||
(struct sockaddr *)&sa6_any, 0, PRC_MSGSIZE, NULL, tcp6_mtudisc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: ah_input.c,v 1.24 2001/01/24 09:04:16 itojun Exp $ */
|
||||
/* $KAME: ah_input.c,v 1.48 2001/01/23 08:59:37 itojun Exp $ */
|
||||
/* $NetBSD: ah_input.c,v 1.25 2001/02/11 06:49:51 itojun Exp $ */
|
||||
/* $KAME: ah_input.c,v 1.51 2001/02/08 14:24:05 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -1046,9 +1046,9 @@ ah6_ctlinput(cmd, sa, d)
|
||||
struct secasvar *sav;
|
||||
struct ip6_hdr *ip6;
|
||||
struct mbuf *m;
|
||||
struct ip6ctlparam *ip6cp = NULL;
|
||||
int off;
|
||||
struct in6_addr finaldst;
|
||||
struct in6_addr s;
|
||||
struct sockaddr_in6 sa6_src, sa6_dst;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
@ -1058,20 +1058,10 @@ ah6_ctlinput(cmd, sa, d)
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
|
||||
ip6cp = (struct ip6ctlparam *)d;
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
|
||||
/* translate addresses into internal form */
|
||||
bcopy(ip6cp->ip6c_finaldst, &finaldst, sizeof(finaldst));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&finaldst)) {
|
||||
finaldst.s6_addr16[1] =
|
||||
htons(m->m_pkthdr.rcvif->if_index);
|
||||
}
|
||||
bcopy(&ip6->ip6_src, &s, sizeof(s));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&s))
|
||||
s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
@ -1104,8 +1094,10 @@ ah6_ctlinput(cmd, sa, d)
|
||||
* Check to see if we have a valid SA corresponding to
|
||||
* the address in the ICMP message payload.
|
||||
*/
|
||||
sav = key_allocsa(AF_INET6, (caddr_t)&s,
|
||||
(caddr_t)&finaldst, IPPROTO_AH, ahp->ah_spi);
|
||||
sav = key_allocsa(AF_INET6,
|
||||
(caddr_t)&sa6_src.sin6_addr,
|
||||
(caddr_t)&sa6_dst.sin6_addr,
|
||||
IPPROTO_AH, ahp->ah_spi);
|
||||
if (sav) {
|
||||
if (sav->state == SADB_SASTATE_MATURE ||
|
||||
sav->state == SADB_SASTATE_DYING)
|
||||
@ -1116,14 +1108,13 @@ ah6_ctlinput(cmd, sa, d)
|
||||
/* XXX Further validation? */
|
||||
|
||||
/*
|
||||
* Now that we've validated that we are actually
|
||||
* communicating with the host indicated in the ICMPv6
|
||||
* message, recalculate the new MTU, and create the
|
||||
* corresponding routing entry.
|
||||
* Depending on the value of "valid" and routing table
|
||||
* size (mtudisc_{hi,lo}wat), we will:
|
||||
* - recalcurate the new MTU and create the
|
||||
* corresponding routing entry, or
|
||||
* - ignore the MTU change notification.
|
||||
*/
|
||||
icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* we normally notify single pcb here */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: esp_input.c,v 1.14 2001/01/24 09:04:16 itojun Exp $ */
|
||||
/* $KAME: esp_input.c,v 1.50 2001/01/23 08:59:37 itojun Exp $ */
|
||||
/* $NetBSD: esp_input.c,v 1.15 2001/02/11 06:49:51 itojun Exp $ */
|
||||
/* $KAME: esp_input.c,v 1.52 2001/02/07 04:58:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -946,12 +946,12 @@ esp6_ctlinput(cmd, sa, d)
|
||||
{
|
||||
const struct newesp *espp;
|
||||
struct newesp esp;
|
||||
struct ip6ctlparam *ip6cp = NULL, ip6cp1;
|
||||
struct secasvar *sav;
|
||||
struct ip6_hdr *ip6;
|
||||
struct mbuf *m;
|
||||
int off;
|
||||
struct in6_addr finaldst;
|
||||
struct in6_addr s;
|
||||
struct sockaddr_in6 sa6_src, sa6_dst;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
@ -961,20 +961,10 @@ esp6_ctlinput(cmd, sa, d)
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
|
||||
ip6cp = (struct ip6ctlparam *)d;
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
|
||||
/* translate addresses into internal form */
|
||||
bcopy(ip6cp->ip6c_finaldst, &finaldst, sizeof(finaldst));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&finaldst)) {
|
||||
finaldst.s6_addr16[1] =
|
||||
htons(m->m_pkthdr.rcvif->if_index);
|
||||
}
|
||||
bcopy(&ip6->ip6_src, &s, sizeof(s));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&s))
|
||||
s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
@ -982,6 +972,24 @@ esp6_ctlinput(cmd, sa, d)
|
||||
|
||||
if (ip6) {
|
||||
/*
|
||||
* Notify the error to all possible sockets via pfctlinput2.
|
||||
* Since the upper layer information (such as protocol type,
|
||||
* source and destination ports) is embedded in the encrypted
|
||||
* data and might have been cut, we can't directly call
|
||||
* an upper layer ctlinput function. However, the pcbnotify
|
||||
* function will consider source and destination addresses
|
||||
* as well as the flow info value, and may be able to find
|
||||
* some PCB that should be notified.
|
||||
* Although pfctlinput2 will call esp6_ctlinput(), there is
|
||||
* no possibility of an infinite loop of function calls,
|
||||
* because we don't pass the inner IPv6 header.
|
||||
*/
|
||||
bzero(&ip6cp1, sizeof(ip6cp1));
|
||||
ip6cp1.ip6c_src = ip6cp->ip6c_src;
|
||||
pfctlinput2(cmd, sa, (void *)&ip6cp1);
|
||||
|
||||
/*
|
||||
* Then go to special cases that need ESP header information.
|
||||
* XXX: We assume that when ip6 is non NULL,
|
||||
* M and OFF are valid.
|
||||
*/
|
||||
@ -1002,12 +1010,15 @@ esp6_ctlinput(cmd, sa, d)
|
||||
|
||||
if (cmd == PRC_MSGSIZE) {
|
||||
int valid = 0;
|
||||
|
||||
/*
|
||||
* Check to see if we have a valid SA corresponding to
|
||||
* the address in the ICMP message payload.
|
||||
*/
|
||||
sav = key_allocsa(AF_INET6, (caddr_t)&s,
|
||||
(caddr_t)&finaldst, IPPROTO_ESP, espp->esp_spi);
|
||||
sav = key_allocsa(AF_INET6,
|
||||
(caddr_t)&sa6_src.sin6_addr,
|
||||
(caddr_t)&sa6_dst, IPPROTO_ESP,
|
||||
espp->esp_spi);
|
||||
if (sav) {
|
||||
if (sav->state == SADB_SASTATE_MATURE ||
|
||||
sav->state == SADB_SASTATE_DYING)
|
||||
@ -1018,17 +1029,14 @@ esp6_ctlinput(cmd, sa, d)
|
||||
/* XXX Further validation? */
|
||||
|
||||
/*
|
||||
* Now that we've validated that we are actually
|
||||
* communicating with the host indicated in the ICMPv6
|
||||
* message, recalculate the new MTU, and create the
|
||||
* corresponding routing entry.
|
||||
* Depending on the value of "valid" and routing table
|
||||
* size (mtudisc_{hi,lo}wat), we will:
|
||||
* - recalcurate the new MTU and create the
|
||||
* corresponding routing entry, or
|
||||
* - ignore the MTU change notification.
|
||||
*/
|
||||
icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* we normally notify single pcb here */
|
||||
} else {
|
||||
/* we normally notify any pcb here */
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: icmp6.c,v 1.57 2001/02/11 04:53:49 itojun Exp $ */
|
||||
/* $KAME: icmp6.c,v 1.194 2001/02/08 15:19:12 itojun Exp $ */
|
||||
/* $NetBSD: icmp6.c,v 1.58 2001/02/11 06:49:51 itojun Exp $ */
|
||||
/* $KAME: icmp6.c,v 1.198 2001/02/11 04:51:12 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -155,6 +155,7 @@ static int ni6_addrs __P((struct icmp6_nodeinfo *, struct mbuf *,
|
||||
struct ifnet **, char *));
|
||||
static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
|
||||
struct ifnet *, int));
|
||||
static int icmp6_notify_error __P((struct mbuf *, int, int, int));
|
||||
static struct rtentry *icmp6_mtudisc_clone __P((struct sockaddr *));
|
||||
static void icmp6_mtudisc_timeout __P((struct rtentry *, struct rttimer *));
|
||||
static void icmp6_redirect_timeout __P((struct rtentry *, struct rttimer *));
|
||||
@ -404,7 +405,6 @@ icmp6_input(mp, offp, proto)
|
||||
int off = *offp;
|
||||
int icmp6len = m->m_pkthdr.len - *offp;
|
||||
int code, sum, noff;
|
||||
struct sockaddr_in6 icmp6src;
|
||||
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off, sizeof(struct icmp6_hdr), IPPROTO_DONE);
|
||||
@ -841,37 +841,69 @@ icmp6_input(mp, offp, proto)
|
||||
break;
|
||||
}
|
||||
deliver:
|
||||
if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
goto freeit;
|
||||
if (icmp6_notify_error(m, off, icmp6len, code)) {
|
||||
/* In this case, m should've been freed. */
|
||||
return(IPPROTO_DONE);
|
||||
}
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off,
|
||||
sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr),
|
||||
IPPROTO_DONE);
|
||||
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
|
||||
#else
|
||||
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
|
||||
sizeof(*icmp6) + sizeof(struct ip6_hdr));
|
||||
if (icmp6 == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
#endif
|
||||
bzero(&icmp6src, sizeof(icmp6src));
|
||||
icmp6src.sin6_len = sizeof(struct sockaddr_in6);
|
||||
icmp6src.sin6_family = AF_INET6;
|
||||
icmp6src.sin6_addr = ((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
|
||||
break;
|
||||
|
||||
/* Detect the upper level protocol */
|
||||
{
|
||||
badcode:
|
||||
icmp6stat.icp6s_badcode++;
|
||||
break;
|
||||
|
||||
badlen:
|
||||
icmp6stat.icp6s_badlen++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* deliver the packet to appropriate sockets */
|
||||
icmp6_rip6_input(&m, *offp);
|
||||
|
||||
return IPPROTO_DONE;
|
||||
|
||||
freeit:
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
}
|
||||
|
||||
static int
|
||||
icmp6_notify_error(m, off, icmp6len, code)
|
||||
struct mbuf *m;
|
||||
int off, icmp6len;
|
||||
{
|
||||
struct icmp6_hdr *icmp6;
|
||||
struct ip6_hdr *eip6;
|
||||
u_int32_t notifymtu;
|
||||
struct sockaddr_in6 icmp6src, icmp6dst;
|
||||
|
||||
if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
goto freeit;
|
||||
}
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, off,
|
||||
sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr),
|
||||
-1);
|
||||
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
|
||||
#else
|
||||
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
|
||||
sizeof(*icmp6) + sizeof(struct ip6_hdr));
|
||||
if (icmp6 == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
eip6 = (struct ip6_hdr *)(icmp6 + 1);
|
||||
|
||||
/* Detect the upper level protocol */
|
||||
{
|
||||
void (*ctlfunc) __P((int, struct sockaddr *, void *));
|
||||
struct ip6_hdr *eip6 = (struct ip6_hdr *)(icmp6 + 1);
|
||||
u_int8_t nxt = eip6->ip6_nxt;
|
||||
int eoff = off + sizeof(struct icmp6_hdr) +
|
||||
sizeof(struct ip6_hdr);
|
||||
struct ip6ctlparam ip6cp;
|
||||
struct in6_addr *finaldst = NULL;
|
||||
int icmp6type = icmp6->icmp6_type;
|
||||
struct ip6_frag *fh;
|
||||
struct ip6_rthdr *rth;
|
||||
struct ip6_rthdr0 *rth0;
|
||||
@ -887,15 +919,15 @@ icmp6_input(mp, offp, proto)
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, 0, eoff +
|
||||
sizeof(struct ip6_ext),
|
||||
IPPROTO_DONE);
|
||||
-1);
|
||||
eh = (struct ip6_ext *)(mtod(m, caddr_t)
|
||||
+ eoff);
|
||||
#else
|
||||
IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
|
||||
eoff, sizeof(*eh));
|
||||
eoff, sizeof(*eh));
|
||||
if (eh == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -916,15 +948,15 @@ icmp6_input(mp, offp, proto)
|
||||
*/
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, 0, eoff + sizeof(*rth),
|
||||
IPPROTO_DONE);
|
||||
-1);
|
||||
rth = (struct ip6_rthdr *)(mtod(m, caddr_t)
|
||||
+ eoff);
|
||||
#else
|
||||
IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
|
||||
eoff, sizeof(*rth));
|
||||
eoff, sizeof(*rth));
|
||||
if (rth == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
rthlen = (rth->ip6r_len + 1) << 3;
|
||||
@ -942,7 +974,7 @@ icmp6_input(mp, offp, proto)
|
||||
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, 0, eoff + rthlen,
|
||||
IPPROTO_DONE);
|
||||
-1);
|
||||
rth0 = (struct ip6_rthdr0 *)(mtod(m, caddr_t) + eoff);
|
||||
#else
|
||||
IP6_EXTHDR_GET(rth0,
|
||||
@ -950,7 +982,7 @@ icmp6_input(mp, offp, proto)
|
||||
eoff, rthlen);
|
||||
if (rth0 == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
/* just ignore a bogus header */
|
||||
@ -965,15 +997,15 @@ icmp6_input(mp, offp, proto)
|
||||
#ifndef PULLDOWN_TEST
|
||||
IP6_EXTHDR_CHECK(m, 0, eoff +
|
||||
sizeof(struct ip6_frag),
|
||||
IPPROTO_DONE);
|
||||
-1);
|
||||
fh = (struct ip6_frag *)(mtod(m, caddr_t)
|
||||
+ eoff);
|
||||
#else
|
||||
IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
|
||||
eoff, sizeof(*fh));
|
||||
eoff, sizeof(*fh));
|
||||
if (fh == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
@ -1000,49 +1032,87 @@ icmp6_input(mp, offp, proto)
|
||||
goto notify;
|
||||
}
|
||||
}
|
||||
notify:
|
||||
notify:
|
||||
#ifndef PULLDOWN_TEST
|
||||
icmp6 = (struct icmp6_hdr *)(mtod(m, caddr_t) + off);
|
||||
#else
|
||||
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
|
||||
sizeof(*icmp6) + sizeof(struct ip6_hdr));
|
||||
sizeof(*icmp6) + sizeof(struct ip6_hdr));
|
||||
if (icmp6 == NULL) {
|
||||
icmp6stat.icp6s_tooshort++;
|
||||
return IPPROTO_DONE;
|
||||
return(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
eip6 = (struct ip6_hdr *)(icmp6 + 1);
|
||||
bzero(&icmp6dst, sizeof(icmp6dst));
|
||||
icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
|
||||
icmp6dst.sin6_family = AF_INET6;
|
||||
if (finaldst == NULL)
|
||||
finaldst = &((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
|
||||
icmp6dst.sin6_addr = eip6->ip6_dst;
|
||||
else
|
||||
icmp6dst.sin6_addr = *finaldst;
|
||||
icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
|
||||
&icmp6dst.sin6_addr);
|
||||
#ifndef SCOPEDROUTING
|
||||
if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst,
|
||||
NULL, NULL)) {
|
||||
/* should be impossbile */
|
||||
nd6log((LOG_DEBUG,
|
||||
"icmp6_notify_error: in6_embedscope failed\n"));
|
||||
goto freeit;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* retrieve parameters from the inner IPv6 header, and convert
|
||||
* them into sockaddr structures.
|
||||
*/
|
||||
bzero(&icmp6src, sizeof(icmp6src));
|
||||
icmp6src.sin6_len = sizeof(struct sockaddr_in6);
|
||||
icmp6src.sin6_family = AF_INET6;
|
||||
icmp6src.sin6_addr = eip6->ip6_src;
|
||||
icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
|
||||
&icmp6src.sin6_addr);
|
||||
#ifndef SCOPEDROUTING
|
||||
if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src,
|
||||
NULL, NULL)) {
|
||||
/* should be impossbile */
|
||||
nd6log((LOG_DEBUG,
|
||||
"icmp6_notify_error: in6_embedscope failed\n"));
|
||||
goto freeit;
|
||||
}
|
||||
#endif
|
||||
icmp6src.sin6_flowinfo =
|
||||
(eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
|
||||
|
||||
if (finaldst == NULL)
|
||||
finaldst = &eip6->ip6_dst;
|
||||
ip6cp.ip6c_m = m;
|
||||
ip6cp.ip6c_icmp6 = icmp6;
|
||||
ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
|
||||
ip6cp.ip6c_off = eoff;
|
||||
ip6cp.ip6c_finaldst = finaldst;
|
||||
ip6cp.ip6c_src = &icmp6src;
|
||||
ip6cp.ip6c_nxt = nxt;
|
||||
|
||||
if (icmp6type == ICMP6_PACKET_TOO_BIG) {
|
||||
notifymtu = ntohl(icmp6->icmp6_mtu);
|
||||
ip6cp.ip6c_cmdarg = (void *)¬ifymtu;
|
||||
}
|
||||
|
||||
ctlfunc = (void (*) __P((int, struct sockaddr *, void *)))
|
||||
(inet6sw[ip6_protox[nxt]].pr_ctlinput);
|
||||
if (ctlfunc) {
|
||||
(void) (*ctlfunc)(code, (struct sockaddr *)&icmp6src,
|
||||
&ip6cp);
|
||||
(void) (*ctlfunc)(code, (struct sockaddr *)&icmp6dst,
|
||||
&ip6cp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
badcode:
|
||||
icmp6stat.icp6s_badcode++;
|
||||
break;
|
||||
|
||||
badlen:
|
||||
icmp6stat.icp6s_badlen++;
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
|
||||
icmp6_rip6_input(&m, *offp);
|
||||
return IPPROTO_DONE;
|
||||
|
||||
freeit:
|
||||
freeit:
|
||||
m_freem(m);
|
||||
return IPPROTO_DONE;
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: in6.c,v 1.42 2001/02/11 04:29:30 itojun Exp $ */
|
||||
/* $KAME: in6.c,v 1.107 2000/10/06 04:58:30 itojun Exp $ */
|
||||
/* $NetBSD: in6.c,v 1.43 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: in6.c,v 1.175 2001/02/10 15:44:58 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -119,6 +119,9 @@ const struct in6_addr in6mask64 = IN6MASK64;
|
||||
const struct in6_addr in6mask96 = IN6MASK96;
|
||||
const struct in6_addr in6mask128 = IN6MASK128;
|
||||
|
||||
const struct sockaddr_in6 sa6_any = {sizeof(sa6_any), AF_INET6,
|
||||
0, 0, IN6ADDR_ANY_INIT, 0};
|
||||
|
||||
static int in6_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
|
||||
struct ifnet *, struct proc *));
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6.h,v 1.21 2000/10/17 21:46:42 itojun Exp $ */
|
||||
/* $NetBSD: in6.h,v 1.22 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: in6.h,v 1.57 2000/08/26 10:00:45 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -163,6 +163,8 @@ struct sockaddr_in6 {
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern const struct sockaddr_in6 sa6_any;
|
||||
|
||||
extern const struct in6_addr in6mask0;
|
||||
extern const struct in6_addr in6mask32;
|
||||
extern const struct in6_addr in6mask64;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: in6_pcb.c,v 1.34 2001/02/10 04:14:27 itojun Exp $ */
|
||||
/* $KAME: in6_pcb.c,v 1.64 2000/10/01 12:37:20 itojun Exp $ */
|
||||
/* $NetBSD: in6_pcb.c,v 1.35 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -379,12 +379,8 @@ in6_pcbconnect(in6p, nam)
|
||||
|| (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)
|
||||
&& in6p->in6p_laddr.s6_addr32[3] == 0)) {
|
||||
if (in6p->in6p_lport == 0) {
|
||||
#ifdef __NetBSD__
|
||||
(void)in6_pcbbind(in6p, (struct mbuf *)0,
|
||||
(struct proc *)0);
|
||||
#else
|
||||
(void)in6_pcbbind(in6p, (struct mbuf *)0);
|
||||
#endif
|
||||
}
|
||||
in6p->in6p_laddr = *in6a;
|
||||
}
|
||||
@ -482,29 +478,39 @@ in6_setpeeraddr(in6p, nam)
|
||||
* any errors for each matching socket.
|
||||
*
|
||||
* Must be called at splsoftnet.
|
||||
*
|
||||
* Note: src (4th arg) carries the flowlabel value on the original IPv6
|
||||
* header, in sin6_flowinfo member.
|
||||
*/
|
||||
int
|
||||
in6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
|
||||
in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify)
|
||||
struct in6pcb *head;
|
||||
struct sockaddr *dst;
|
||||
struct sockaddr *dst, *src;
|
||||
u_int fport_arg, lport_arg;
|
||||
struct in6_addr *laddr6;
|
||||
int cmd;
|
||||
void *cmdarg;
|
||||
void (*notify) __P((struct in6pcb *, int));
|
||||
{
|
||||
struct in6pcb *in6p, *nin6p;
|
||||
struct in6_addr faddr6;
|
||||
struct sockaddr_in6 sa6_src, *sa6_dst;
|
||||
u_int16_t fport = fport_arg, lport = lport_arg;
|
||||
int errno;
|
||||
int nmatch = 0;
|
||||
int do_rtchange = (notify == in6_rtchange);
|
||||
u_int32_t flowinfo;
|
||||
|
||||
if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
|
||||
return 0;
|
||||
faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
|
||||
|
||||
sa6_dst = (struct sockaddr_in6 *)dst;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* note that src can be NULL when we get notify by local fragmentation.
|
||||
*/
|
||||
sa6_src = (src == NULL) ? sa6_any : *(struct sockaddr_in6 *)src;
|
||||
flowinfo = sa6_src.sin6_flowinfo;
|
||||
|
||||
/*
|
||||
* Redirects go to all references to the destination,
|
||||
* and use in6_rtchange to invalidate the route cache.
|
||||
@ -516,48 +522,85 @@ in6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
|
||||
if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
|
||||
fport = 0;
|
||||
lport = 0;
|
||||
bzero((caddr_t)laddr6, sizeof(*laddr6));
|
||||
bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
|
||||
|
||||
do_rtchange = 1;
|
||||
if (cmd != PRC_HOSTDEAD)
|
||||
notify = in6_rtchange;
|
||||
}
|
||||
|
||||
if (notify == NULL)
|
||||
return 0;
|
||||
|
||||
errno = inet6ctlerrmap[cmd];
|
||||
for (in6p = head->in6p_next; in6p != head; in6p = nin6p) {
|
||||
nin6p = in6p->in6p_next;
|
||||
|
||||
if (do_rtchange) {
|
||||
/*
|
||||
* Since a non-connected PCB might have a cached route,
|
||||
* we always call in6_rtchange without matching
|
||||
* the PCB to the src/dst pair.
|
||||
*
|
||||
* XXX: we assume in6_rtchange does not free the PCB.
|
||||
*/
|
||||
if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_route.ro_dst.sin6_addr,
|
||||
&faddr6)) {
|
||||
in6_rtchange(in6p, errno);
|
||||
/*
|
||||
* Under the following condition, notify of redirects
|
||||
* to the pcb, without making address matches against inpcb.
|
||||
* - redirect notification is arrived.
|
||||
* - the inpcb is unconnected.
|
||||
* - the inpcb is caching !RTF_HOST routing entry.
|
||||
* - the ICMPv6 notification is from the gateway cached in the
|
||||
* inpcb. i.e. ICMPv6 notification is from nexthop gateway
|
||||
* the inpcb used very recently.
|
||||
*
|
||||
* This is to improve interaction between netbsd/openbsd
|
||||
* redirect handling code, and inpcb route cache code.
|
||||
* without the clause, !RTF_HOST routing entry (which carries
|
||||
* gateway used by inpcb right before the ICMPv6 redirect)
|
||||
* will be cached forever in unconnected inpcb.
|
||||
*
|
||||
* There still is a question regarding to what is TRT:
|
||||
* - On bsdi/freebsd, RTF_HOST (cloned) routing entry will be
|
||||
* generated on packet output. inpcb will always cache
|
||||
* RTF_HOST routing entry so there's no need for the clause
|
||||
* (ICMPv6 redirect will update RTF_HOST routing entry,
|
||||
* and inpcb is caching it already).
|
||||
* However, bsdi/freebsd are vulnerable to local DoS attacks
|
||||
* due to the cloned routing entries.
|
||||
* - Specwise, "destination cache" is mentioned in RFC2461.
|
||||
* Jinmei says that it implies bsdi/freebsd behavior, itojun
|
||||
* is not really convinced.
|
||||
* - Having hiwat/lowat on # of cloned host route (redirect/
|
||||
* pmtud) may be a good idea. netbsd/openbsd has it. see
|
||||
* icmp6_mtudisc_update().
|
||||
*/
|
||||
if ((PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
|
||||
in6p->in6p_route.ro_rt &&
|
||||
!(in6p->in6p_route.ro_rt->rt_flags & RTF_HOST)) {
|
||||
struct sockaddr_in6 *dst6;
|
||||
|
||||
if (notify == in6_rtchange) {
|
||||
/* there's nothing to do any more */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
dst6 = (struct sockaddr_in6 *)&in6p->in6p_route.ro_dst;
|
||||
if (IN6_ARE_ADDR_EQUAL(&dst6->sin6_addr,
|
||||
&sa6_dst->sin6_addr))
|
||||
goto do_notify;
|
||||
}
|
||||
|
||||
/* at this point, we can assume that NOTIFY is not NULL. */
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &faddr6) ||
|
||||
/*
|
||||
* Detect if we should notify the error. If no source and
|
||||
* destination ports are specifed, but non-zero flowinfo and
|
||||
* local address match, notify the error. This is the case
|
||||
* when the error is delivered with an encrypted buffer
|
||||
* by ESP. Otherwise, just compare addresses and ports
|
||||
* as usual.
|
||||
*/
|
||||
if (lport == 0 && fport == 0 && flowinfo &&
|
||||
in6p->in6p_socket != NULL &&
|
||||
flowinfo == (in6p->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
|
||||
IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &sa6_src.sin6_addr))
|
||||
goto do_notify;
|
||||
else if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
|
||||
&sa6_dst->sin6_addr) ||
|
||||
in6p->in6p_socket == 0 ||
|
||||
(lport && in6p->in6p_lport != lport) ||
|
||||
(!IN6_IS_ADDR_UNSPECIFIED(laddr6) &&
|
||||
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6)) ||
|
||||
(!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
|
||||
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
|
||||
&sa6_src.sin6_addr)) ||
|
||||
(fport && in6p->in6p_fport != fport))
|
||||
continue;
|
||||
|
||||
(*notify)(in6p, errno);
|
||||
do_notify:
|
||||
if (notify)
|
||||
(*notify)(in6p, errno);
|
||||
nmatch++;
|
||||
}
|
||||
return nmatch;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: in6_pcb.h,v 1.14 2001/02/08 14:56:15 itojun Exp $ */
|
||||
/* $KAME: in6_pcb.h,v 1.44 2001/02/06 09:16:53 itojun Exp $ */
|
||||
/* $NetBSD: in6_pcb.h,v 1.15 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -162,7 +162,7 @@ struct in6pcb *
|
||||
struct in6_addr *, u_int, struct in6_addr *,
|
||||
u_int, int));
|
||||
int in6_pcbnotify __P((struct in6pcb *, struct sockaddr *,
|
||||
u_int, struct in6_addr *, u_int, int,
|
||||
u_int, struct sockaddr *, u_int, int, void *,
|
||||
void (*)(struct in6pcb *, int)));
|
||||
void in6_pcbpurgeif __P((struct in6pcb *, struct ifnet *));
|
||||
void in6_rtchange __P((struct in6pcb *, int));
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: in6_proto.c,v 1.24 2001/02/11 05:25:04 itojun Exp $ */
|
||||
/* $NetBSD: in6_proto.c,v 1.25 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -162,7 +162,7 @@ struct ip6protosw inet6sw[] = {
|
||||
0, 0, 0, 0,
|
||||
},
|
||||
{ SOCK_RAW, &inet6domain, IPPROTO_ICMPV6, PR_ATOMIC | PR_ADDR,
|
||||
icmp6_input, rip6_output, 0, rip6_ctloutput,
|
||||
icmp6_input, rip6_output, rip6_ctlinput, rip6_ctloutput,
|
||||
rip6_usrreq,
|
||||
icmp6_init, icmp6_fasttimo, 0, 0,
|
||||
icmp6_sysctl,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: ip6protosw.h,v 1.9 2001/02/10 04:14:29 itojun Exp $ */
|
||||
/* $KAME: ip6protosw.h,v 1.14 2000/10/18 18:15:53 itojun Exp $ */
|
||||
/* $NetBSD: ip6protosw.h,v 1.10 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: ip6protosw.h,v 1.22 2001/02/08 18:02:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -98,13 +98,21 @@ struct in6_addr;
|
||||
* ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original
|
||||
* (internal) packet carries a routing header, it may point the final
|
||||
* dstination address in the routing header.
|
||||
*
|
||||
* ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6
|
||||
* (beware of flowlabel, if you try to compare it against others)
|
||||
* ip6c_dst: ip6c_finaldst + scope info
|
||||
*/
|
||||
struct ip6ctlparam {
|
||||
struct mbuf *ip6c_m; /* start of mbuf chain */
|
||||
struct icmp6_hdr *ip6c_icmp6; /* icmp6 header of target packet */
|
||||
struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */
|
||||
int ip6c_off; /* offset of the target proto header */
|
||||
struct sockaddr_in6 *ip6c_src; /* srcaddr w/ additional info */
|
||||
struct sockaddr_in6 *ip6c_dst; /* (final) dstaddr w/ additional info */
|
||||
struct in6_addr *ip6c_finaldst; /* final destination address */
|
||||
void *ip6c_cmdarg; /* control command dependent data */
|
||||
u_int8_t ip6c_nxt; /* final next header field */
|
||||
};
|
||||
|
||||
struct ip6protosw {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: raw_ip6.c,v 1.28 2001/02/10 04:14:29 itojun Exp $ */
|
||||
/* $NetBSD: raw_ip6.c,v 1.29 2001/02/11 06:49:52 itojun Exp $ */
|
||||
/* $KAME: raw_ip6.c,v 1.65 2001/02/08 18:36:17 itojun Exp $ */
|
||||
|
||||
/*
|
||||
@ -234,11 +234,14 @@ rip6_ctlinput(cmd, sa, d)
|
||||
struct sockaddr *sa;
|
||||
void *d;
|
||||
{
|
||||
struct sockaddr_in6 sa6;
|
||||
struct ip6_hdr *ip6;
|
||||
struct mbuf *m;
|
||||
int off;
|
||||
struct ip6ctlparam *ip6cp = NULL;
|
||||
const struct sockaddr_in6 *sa6_src = NULL;
|
||||
void *cmdarg;
|
||||
void (*notify) __P((struct in6pcb *, int)) = in6_rtchange;
|
||||
int nxt;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
@ -250,43 +253,82 @@ rip6_ctlinput(cmd, sa, d)
|
||||
notify = in6_rtchange, d = NULL;
|
||||
else if (cmd == PRC_HOSTDEAD)
|
||||
d = NULL;
|
||||
else if (cmd == PRC_MSGSIZE)
|
||||
; /* special code is present, see below */
|
||||
else if (inet6ctlerrmap[cmd] == 0)
|
||||
return;
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
|
||||
ip6cp = (struct ip6ctlparam *)d;
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
cmdarg = ip6cp->ip6c_cmdarg;
|
||||
sa6_src = ip6cp->ip6c_src;
|
||||
nxt = ip6cp->ip6c_nxt;
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
cmdarg = NULL;
|
||||
sa6_src = &sa6_any;
|
||||
nxt = -1;
|
||||
}
|
||||
|
||||
/* translate addresses into internal form */
|
||||
sa6 = *(struct sockaddr_in6 *)sa;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
|
||||
sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
if (ip6 && cmd == PRC_MSGSIZE) {
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
int valid = 0;
|
||||
struct in6pcb *in6p;
|
||||
|
||||
if (ip6) {
|
||||
/*
|
||||
* XXX: We assume that when IPV6 is non NULL,
|
||||
* M and OFF are valid.
|
||||
* Check to see if we have a valid raw IPv6 socket
|
||||
* corresponding to the address in the ICMPv6 message
|
||||
* payload, and the protocol (ip6_nxt) meets the socket.
|
||||
* XXX chase extension headers, or pass final nxt value
|
||||
* from icmp6_notify_error()
|
||||
*/
|
||||
struct in6_addr s;
|
||||
in6p = NULL;
|
||||
in6p = in6_pcblookup_connect(&rawin6pcb,
|
||||
&sa6->sin6_addr, 0,
|
||||
(struct in6_addr *)&sa6_src->sin6_addr, 0, 0);
|
||||
#if 0
|
||||
if (!in6p) {
|
||||
/*
|
||||
* As the use of sendto(2) is fairly popular,
|
||||
* we may want to allow non-connected pcb too.
|
||||
* But it could be too weak against attacks...
|
||||
* We should at least check if the local
|
||||
* address (= s) is really ours.
|
||||
*/
|
||||
in6p = in6_pcblookup_bind(&rawin6pcb,
|
||||
&sa6->sin6_addr, 0, 0))
|
||||
}
|
||||
#endif
|
||||
|
||||
/* translate addresses into internal form */
|
||||
bcopy(&ip6->ip6_src, &s, sizeof(s));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&s))
|
||||
s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
if (in6p && in6p->in6p_ip6.ip6_nxt &&
|
||||
in6p->in6p_ip6.ip6_nxt == nxt)
|
||||
valid++;
|
||||
|
||||
(void) in6_pcbnotify(&rawin6pcb, (struct sockaddr *)&sa6,
|
||||
0, &s, 0, cmd, notify);
|
||||
} else {
|
||||
(void) in6_pcbnotify(&rawin6pcb, (struct sockaddr *)&sa6, 0,
|
||||
&zeroin6_addr, 0, cmd, notify);
|
||||
/*
|
||||
* Depending on the value of "valid" and routing table
|
||||
* size (mtudisc_{hi,lo}wat), we will:
|
||||
* - recalcurate the new MTU and create the
|
||||
* corresponding routing entry, or
|
||||
* - ignore the MTU change notification.
|
||||
*/
|
||||
icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
|
||||
|
||||
/*
|
||||
* regardless of if we called icmp6_mtudisc_update(),
|
||||
* we need to call in6_pcbnotify(), to notify path
|
||||
* MTU change to the userland (2292bis-02), because
|
||||
* some unconnected sockets may share the same
|
||||
* destination and want to know the path MTU.
|
||||
*/
|
||||
}
|
||||
|
||||
(void) in6_pcbnotify(&rawin6pcb, sa, 0,
|
||||
(struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* $NetBSD: udp6_usrreq.c,v 1.39 2001/02/10 04:14:29 itojun Exp $ */
|
||||
/* $KAME: udp6_usrreq.c,v 1.62 2000/10/19 01:11:05 itojun Exp $ */
|
||||
/* $NetBSD: udp6_usrreq.c,v 1.40 2001/02/11 06:49:53 itojun Exp $ */
|
||||
/* $KAME: udp6_usrreq.c,v 1.84 2001/02/07 07:38:25 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
@ -467,15 +467,19 @@ udp6_ctlinput(cmd, sa, d)
|
||||
struct sockaddr *sa;
|
||||
void *d;
|
||||
{
|
||||
struct udphdr *uhp;
|
||||
struct udphdr uh;
|
||||
struct sockaddr_in6 sa6;
|
||||
struct ip6_hdr *ip6;
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
struct mbuf *m;
|
||||
int off;
|
||||
struct in6_addr s;
|
||||
struct in6_addr finaldst;
|
||||
void *cmdarg;
|
||||
struct ip6ctlparam *ip6cp = NULL;
|
||||
const struct sockaddr_in6 *sa6_src = NULL;
|
||||
void (*notify) __P((struct in6pcb *, int)) = udp6_notify;
|
||||
struct udp_portonly {
|
||||
u_int16_t uh_sport;
|
||||
u_int16_t uh_dport;
|
||||
} *uhp;
|
||||
|
||||
if (sa->sa_family != AF_INET6 ||
|
||||
sa->sa_len != sizeof(struct sockaddr_in6))
|
||||
@ -494,30 +498,19 @@ udp6_ctlinput(cmd, sa, d)
|
||||
|
||||
/* if the parameter is from icmp6, decode it. */
|
||||
if (d != NULL) {
|
||||
struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
|
||||
ip6cp = (struct ip6ctlparam *)d;
|
||||
m = ip6cp->ip6c_m;
|
||||
ip6 = ip6cp->ip6c_ip6;
|
||||
off = ip6cp->ip6c_off;
|
||||
|
||||
/* translate addresses into internal form */
|
||||
bcopy(ip6cp->ip6c_finaldst, &finaldst, sizeof(finaldst));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&finaldst)) {
|
||||
finaldst.s6_addr16[1] =
|
||||
htons(m->m_pkthdr.rcvif->if_index);
|
||||
}
|
||||
bcopy(&ip6->ip6_src, &s, sizeof(s));
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&s))
|
||||
s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
cmdarg = ip6cp->ip6c_cmdarg;
|
||||
sa6_src = ip6cp->ip6c_src;
|
||||
} else {
|
||||
m = NULL;
|
||||
ip6 = NULL;
|
||||
cmdarg = NULL;
|
||||
sa6_src = &sa6_any;
|
||||
}
|
||||
|
||||
/* translate addresses into internal form */
|
||||
sa6 = *(struct sockaddr_in6 *)sa;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
|
||||
sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
|
||||
|
||||
if (ip6) {
|
||||
/*
|
||||
* XXX: We assume that when IPV6 is non NULL,
|
||||
@ -525,28 +518,23 @@ udp6_ctlinput(cmd, sa, d)
|
||||
*/
|
||||
|
||||
/* check if we can safely examine src and dst ports */
|
||||
if (m->m_pkthdr.len < off + sizeof(uh))
|
||||
if (m->m_pkthdr.len < off + sizeof(*uhp))
|
||||
return;
|
||||
|
||||
if (m->m_len < off + sizeof(uh)) {
|
||||
/*
|
||||
* this should be rare case,
|
||||
* so we compromise on this copy...
|
||||
*/
|
||||
m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
|
||||
uhp = &uh;
|
||||
} else
|
||||
uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
|
||||
bzero(&uh, sizeof(uh));
|
||||
m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
|
||||
|
||||
if (cmd == PRC_MSGSIZE) {
|
||||
int valid = 0;
|
||||
|
||||
/*
|
||||
* Check to see if we have a valid UDP socket
|
||||
* corresponding to the address in the ICMPv6 message
|
||||
* payload.
|
||||
*/
|
||||
if (in6_pcblookup_connect(&udb6, &finaldst,
|
||||
uhp->uh_dport, &s, uhp->uh_sport, 0))
|
||||
if (in6_pcblookup_connect(&udb6, &sa6->sin6_addr,
|
||||
uh.uh_dport, (struct in6_addr *)&sa6_src->sin6_addr,
|
||||
uh.uh_sport, 0))
|
||||
valid++;
|
||||
#if 0
|
||||
/*
|
||||
@ -556,28 +544,35 @@ udp6_ctlinput(cmd, sa, d)
|
||||
* We should at least check if the local address (= s)
|
||||
* is really ours.
|
||||
*/
|
||||
else if (in6_pcblookup_bind(&udb6, &finaldst,
|
||||
uhp->uh_dport, 0))
|
||||
else if (in6_pcblookup_bind(&udb6, &sa6->sin6_addr,
|
||||
uh.uh_dport, 0))
|
||||
valid++;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now that we've validated that we are actually
|
||||
* communicating with the host indicated in the ICMPv6
|
||||
* message, recalculate the new MTU, and create the
|
||||
* corresponding routing entry.
|
||||
* Depending on the value of "valid" and routing table
|
||||
* size (mtudisc_{hi,lo}wat), we will:
|
||||
* - recalcurate the new MTU and create the
|
||||
* corresponding routing entry, or
|
||||
* - ignore the MTU change notification.
|
||||
*/
|
||||
icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
|
||||
|
||||
return;
|
||||
/*
|
||||
* regardless of if we called icmp6_mtudisc_update(),
|
||||
* we need to call in6_pcbnotify(), to notify path
|
||||
* MTU change to the userland (2292bis-02), because
|
||||
* some unconnected sockets may share the same
|
||||
* destination and want to know the path MTU.
|
||||
*/
|
||||
}
|
||||
|
||||
(void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6,
|
||||
uhp->uh_dport, &s,
|
||||
uhp->uh_sport, cmd, notify);
|
||||
(void) in6_pcbnotify(&udb6, sa, uh.uh_dport,
|
||||
(struct sockaddr *)sa6_src, uh.uh_sport, cmd, cmdarg,
|
||||
notify);
|
||||
} else {
|
||||
(void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6, 0,
|
||||
&zeroin6_addr, 0, cmd, notify);
|
||||
(void) in6_pcbnotify(&udb6, sa, 0, (struct sockaddr *)sa6_src,
|
||||
0, cmd, cmdarg, notify);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user