sync with latest KAME in6_ifaddr/prefix/default router manipulation.
behavior changes: - two iocts used by ndp(8) are now obsolete (backward compat provided). use sysctl path instead. - lo0 does not get ::1 automatically. it will get ::1 when lo0 comes up.
This commit is contained in:
parent
61ef51d198
commit
6d8d0d63d8
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: files,v 1.532 2002/06/06 23:54:48 wrstuden Exp $
|
||||
# $NetBSD: files,v 1.533 2002/06/08 21:22:29 itojun Exp $
|
||||
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
|
@ -1199,7 +1199,6 @@ file netinet6/in6_cksum.c inet6 & !inet6_md_cksum
|
|||
file netinet6/in6_gif.c gif & inet6
|
||||
file netinet6/in6_ifattach.c inet6
|
||||
file netinet6/in6_pcb.c inet6
|
||||
file netinet6/in6_prefix.c inet6
|
||||
file netinet6/in6_proto.c inet6
|
||||
file netinet6/in6_src.c inet6
|
||||
file netinet6/ip6_forward.c inet6
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: icmp6.h,v 1.22 2002/05/29 02:58:28 itojun Exp $ */
|
||||
/* $NetBSD: icmp6.h,v 1.23 2002/06/08 21:22:30 itojun Exp $ */
|
||||
/* $KAME: icmp6.h,v 1.39 2001/02/06 03:48:06 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -570,7 +570,9 @@ struct icmp6stat {
|
|||
#define ICMPV6CTL_MTUDISC_HIWAT 16
|
||||
#define ICMPV6CTL_MTUDISC_LOWAT 17
|
||||
#define ICMPV6CTL_ND6_DEBUG 18
|
||||
#define ICMPV6CTL_MAXID 19
|
||||
#define ICMPV6CTL_ND6_DRLIST 19
|
||||
#define ICMPV6CTL_ND6_PRLIST 20
|
||||
#define ICMPV6CTL_MAXID 21
|
||||
|
||||
#define ICMPV6CTL_NAMES { \
|
||||
{ 0, 0 }, \
|
||||
|
@ -592,6 +594,8 @@ struct icmp6stat {
|
|||
{ "mtudisc_hiwat", CTLTYPE_INT }, \
|
||||
{ "mtudisc_lowat", CTLTYPE_INT }, \
|
||||
{ "nd6_debug", CTLTYPE_INT }, \
|
||||
{ 0, 0 }, \
|
||||
{ 0, 0 }, \
|
||||
}
|
||||
|
||||
#define RTF_PROBEMTU RTF_PROTO1
|
||||
|
|
1142
sys/netinet6/in6.c
1142
sys/netinet6/in6.c
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6.h,v 1.40 2002/05/28 03:04:06 itojun Exp $ */
|
||||
/* $NetBSD: in6.h,v 1.41 2002/06/08 21:22:31 itojun Exp $ */
|
||||
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -358,6 +358,15 @@ extern const struct in6_addr in6addr_linklocal_allrouters;
|
|||
#define IN6_IS_SCOPE_LINKLOCAL(a) \
|
||||
((IN6_IS_ADDR_LINKLOCAL(a)) || \
|
||||
(IN6_IS_ADDR_MC_LINKLOCAL(a)))
|
||||
|
||||
#define IFA6_IS_DEPRECATED(a) \
|
||||
((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
|
||||
(u_int32_t)((time.tv_sec - (a)->ia6_updatetime)) > \
|
||||
(a)->ia6_lifetime.ia6t_pltime)
|
||||
#define IFA6_IS_INVALID(a) \
|
||||
((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
|
||||
(u_int32_t)((time.tv_sec - (a)->ia6_updatetime)) > \
|
||||
(a)->ia6_lifetime.ia6t_vltime)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_ifattach.c,v 1.47 2002/06/07 04:30:40 itojun Exp $ */
|
||||
/* $NetBSD: in6_ifattach.c,v 1.48 2002/06/08 21:22:31 itojun Exp $ */
|
||||
/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.47 2002/06/07 04:30:40 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.48 2002/06/08 21:22:31 itojun Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -60,10 +60,11 @@ __KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.47 2002/06/07 04:30:40 itojun Exp
|
|||
|
||||
unsigned long in6_maxmtu = 0;
|
||||
|
||||
int ip6_auto_linklocal = 1; /* enable by default */
|
||||
|
||||
static int get_rand_ifid __P((struct ifnet *, struct in6_addr *));
|
||||
static int get_hw_ifid __P((struct ifnet *, struct in6_addr *));
|
||||
static int get_ifid __P((struct ifnet *, struct ifnet *, struct in6_addr *));
|
||||
static int in6_ifattach_addaddr __P((struct ifnet *, struct in6_ifaddr *));
|
||||
static int in6_ifattach_linklocal __P((struct ifnet *, struct ifnet *));
|
||||
static int in6_ifattach_loopback __P((struct ifnet *));
|
||||
|
||||
|
@ -156,17 +157,25 @@ found:
|
|||
addr = LLADDR(sdl);
|
||||
addrlen = sdl->sdl_alen;
|
||||
|
||||
switch (ifp->if_type) {
|
||||
case IFT_IEEE1394:
|
||||
case IFT_IEEE80211:
|
||||
/* IEEE1394 uses 16byte length address starting with EUI64 */
|
||||
if (addrlen > 8)
|
||||
addrlen = 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* get EUI64 */
|
||||
switch (ifp->if_type) {
|
||||
/* IEEE802/EUI64 cases - what others? */
|
||||
case IFT_ETHER:
|
||||
case IFT_FDDI:
|
||||
case IFT_ATM:
|
||||
case IFT_IEEE1394:
|
||||
/* IEEE802/EUI64 cases - what others? */
|
||||
/* IEEE1394 uses 16byte length address starting with EUI64 */
|
||||
if (addrlen > 8)
|
||||
addrlen = 8;
|
||||
|
||||
case IFT_IEEE80211:
|
||||
/* look at IEEE802/EUI64 only */
|
||||
if (addrlen != 8 && addrlen != 6)
|
||||
return -1;
|
||||
|
@ -313,191 +322,135 @@ success:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* configure IPv6 interface address. XXX code duplicated with in.c
|
||||
*/
|
||||
static int
|
||||
in6_ifattach_addaddr(ifp, ia)
|
||||
struct ifnet *ifp;
|
||||
struct in6_ifaddr *ia;
|
||||
{
|
||||
struct in6_ifaddr *oia;
|
||||
struct ifaddr *ifa;
|
||||
int error;
|
||||
int rtflag;
|
||||
struct in6_addr llsol;
|
||||
|
||||
/*
|
||||
* initialize if_addrlist, if we are the very first one
|
||||
*/
|
||||
ifa = TAILQ_FIRST(&ifp->if_addrlist);
|
||||
if (ifa == NULL) {
|
||||
TAILQ_INIT(&ifp->if_addrlist);
|
||||
}
|
||||
|
||||
/*
|
||||
* link the interface address to global list
|
||||
*/
|
||||
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
|
||||
IFAREF(&ia->ia_ifa);
|
||||
|
||||
/*
|
||||
* Also link into the IPv6 address chain beginning with in6_ifaddr.
|
||||
* kazu opposed it, but itojun & jinmei wanted.
|
||||
*/
|
||||
if ((oia = in6_ifaddr) != NULL) {
|
||||
for (; oia->ia_next; oia = oia->ia_next)
|
||||
continue;
|
||||
oia->ia_next = ia;
|
||||
} else
|
||||
in6_ifaddr = ia;
|
||||
IFAREF(&ia->ia_ifa);
|
||||
|
||||
/*
|
||||
* give the interface a chance to initialize, in case this
|
||||
* is the first address to be added.
|
||||
*/
|
||||
if (ifp->if_ioctl != NULL) {
|
||||
int s;
|
||||
s = splnet();
|
||||
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
|
||||
splx(s);
|
||||
} else
|
||||
error = 0;
|
||||
if (error) {
|
||||
switch (error) {
|
||||
case EAFNOSUPPORT:
|
||||
printf("%s: IPv6 not supported\n", if_name(ifp));
|
||||
break;
|
||||
default:
|
||||
printf("%s: SIOCSIFADDR error %d\n", if_name(ifp),
|
||||
error);
|
||||
break;
|
||||
}
|
||||
|
||||
/* undo changes */
|
||||
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
|
||||
IFAFREE(&ia->ia_ifa);
|
||||
if (oia)
|
||||
oia->ia_next = ia->ia_next;
|
||||
else
|
||||
in6_ifaddr = ia->ia_next;
|
||||
IFAFREE(&ia->ia_ifa);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* configure link-layer address resolution */
|
||||
rtflag = 0;
|
||||
if (IN6_ARE_ADDR_EQUAL(&ia->ia_prefixmask.sin6_addr, &in6mask128))
|
||||
rtflag = RTF_HOST;
|
||||
else {
|
||||
switch (ifp->if_type) {
|
||||
case IFT_LOOP:
|
||||
#ifdef IFT_STF
|
||||
case IFT_STF:
|
||||
#endif
|
||||
rtflag = 0;
|
||||
break;
|
||||
default:
|
||||
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
|
||||
ia->ia_ifa.ifa_flags |= RTF_CLONING;
|
||||
rtflag = RTF_CLONING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add route to the interface. */
|
||||
rtrequest(RTM_ADD,
|
||||
(struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&ia->ia_prefixmask,
|
||||
RTF_UP | rtflag,
|
||||
(struct rtentry **)0);
|
||||
ia->ia_flags |= IFA_ROUTE;
|
||||
|
||||
if ((rtflag & RTF_CLONING) != 0 &&
|
||||
(ifp->if_flags & IFF_MULTICAST) != 0) {
|
||||
/* Restore saved multicast addresses (if any). */
|
||||
in6_restoremkludge(ia, ifp);
|
||||
|
||||
/*
|
||||
* join solicited multicast address
|
||||
*/
|
||||
bzero(&llsol, sizeof(llsol));
|
||||
llsol.s6_addr16[0] = htons(0xff02);
|
||||
llsol.s6_addr16[1] = htons(ifp->if_index);
|
||||
llsol.s6_addr32[1] = 0;
|
||||
llsol.s6_addr32[2] = htonl(1);
|
||||
llsol.s6_addr32[3] = ia->ia_addr.sin6_addr.s6_addr32[3];
|
||||
llsol.s6_addr8[12] = 0xff;
|
||||
if (!in6_addmulti(&llsol, ifp, &error)) {
|
||||
nd6log((LOG_ERR, "%s: failed to join %s (errno=%d)\n",
|
||||
if_name(ifp), ip6_sprintf(&llsol), error));
|
||||
}
|
||||
|
||||
if (in6if_do_dad(ifp)) {
|
||||
/* mark the address TENTATIVE, if needed. */
|
||||
ia->ia6_flags |= IN6_IFF_TENTATIVE;
|
||||
/* nd6_dad_start() will be called in in6_if_up */
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
in6_ifattach_linklocal(ifp, altifp)
|
||||
struct ifnet *ifp;
|
||||
struct ifnet *altifp; /*secondary EUI64 source*/
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_aliasreq ifra;
|
||||
struct nd_prefix pr0;
|
||||
int i, error;
|
||||
|
||||
/*
|
||||
* configure link-local address
|
||||
* configure link-local address.
|
||||
*/
|
||||
ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
|
||||
bzero((caddr_t)ia, sizeof(*ia));
|
||||
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
|
||||
if (ifp->if_flags & IFF_POINTOPOINT)
|
||||
ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
|
||||
else
|
||||
ia->ia_ifa.ifa_dstaddr = NULL;
|
||||
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
|
||||
ia->ia_ifp = ifp;
|
||||
bzero(&ifra, sizeof(ifra));
|
||||
|
||||
bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
|
||||
ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ia->ia_prefixmask.sin6_family = AF_INET6;
|
||||
ia->ia_prefixmask.sin6_addr = in6mask64;
|
||||
/*
|
||||
* in6_update_ifa() does not use ifra_name, but we accurately set it
|
||||
* for safety.
|
||||
*/
|
||||
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
|
||||
|
||||
/* just in case */
|
||||
bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr));
|
||||
ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ia->ia_dstaddr.sin6_family = AF_INET6;
|
||||
|
||||
bzero(&ia->ia_addr, sizeof(ia->ia_addr));
|
||||
ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ia->ia_addr.sin6_family = AF_INET6;
|
||||
ia->ia_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
|
||||
ia->ia_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
ia->ia_addr.sin6_addr.s6_addr32[1] = 0;
|
||||
if (ifp->if_flags & IFF_LOOPBACK) {
|
||||
ia->ia_addr.sin6_addr.s6_addr32[2] = 0;
|
||||
ia->ia_addr.sin6_addr.s6_addr32[3] = htonl(1);
|
||||
ifra.ifra_addr.sin6_family = AF_INET6;
|
||||
ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
|
||||
ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
|
||||
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
|
||||
} else {
|
||||
if (get_ifid(ifp, altifp, &ia->ia_addr.sin6_addr) != 0) {
|
||||
if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
|
||||
nd6log((LOG_ERR,
|
||||
"%s: no ifid available\n", if_name(ifp)));
|
||||
free(ia, M_IFADDR);
|
||||
return -1;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
|
||||
ia->ia_ifa.ifa_metric = ifp->if_metric;
|
||||
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_prefixmask.sin6_family = AF_INET6;
|
||||
ifra.ifra_prefixmask.sin6_addr = in6mask64;
|
||||
#ifdef SCOPEDROUTING
|
||||
/* take into account the sin6_scope_id field for routing */
|
||||
ifra.ifra_prefixmask.sin6_scope_id = 0xffffffff;
|
||||
#endif
|
||||
/* link-local addresses should NEVER expire. */
|
||||
ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
|
||||
if (in6_ifattach_addaddr(ifp, ia) != 0) {
|
||||
/* ia will be freed on failure */
|
||||
return -1;
|
||||
/*
|
||||
* Do not let in6_update_ifa() do DAD, since we need a random delay
|
||||
* before sending an NS at the first time the interface becomes up.
|
||||
* Instead, in6_if_up() will start DAD with a proper random delay.
|
||||
*/
|
||||
ifra.ifra_flags |= IN6_IFF_NODAD;
|
||||
|
||||
/*
|
||||
* Now call in6_update_ifa() to do a bunch of procedures to configure
|
||||
* a link-local address. We can set NULL to the 3rd argument, because
|
||||
* we know there's no other link-local address on the interface
|
||||
* and therefore we are adding one (instead of updating one).
|
||||
*/
|
||||
if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
|
||||
/*
|
||||
* XXX: When the interface does not support IPv6, this call
|
||||
* would fail in the SIOCSIFADDR ioctl. I believe the
|
||||
* notification is rather confusing in this case, so just
|
||||
* suppress it. (jinmei@kame.net 20010130)
|
||||
*/
|
||||
if (error != EAFNOSUPPORT)
|
||||
log(LOG_NOTICE, "in6_ifattach_linklocal: failed to "
|
||||
"configure a link-local address on %s "
|
||||
"(errno=%d)\n",
|
||||
if_name(ifp), error);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust ia6_flags so that in6_if_up will perform DAD.
|
||||
* XXX: Some P2P interfaces seem not to send packets just after
|
||||
* becoming up, so we skip p2p interfaces for safety.
|
||||
*/
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
|
||||
#ifdef DIAGNOSTIC
|
||||
if (!ia) {
|
||||
panic("ia == NULL in in6_ifattach_linklocal");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
if (in6if_do_dad(ifp) && (ifp->if_flags & IFF_POINTOPOINT) == 0) {
|
||||
ia->ia6_flags &= ~IN6_IFF_NODAD;
|
||||
ia->ia6_flags |= IN6_IFF_TENTATIVE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the link-local prefix (fe80::/64%link) as on-link.
|
||||
* Since we'd like to manage prefixes separately from addresses,
|
||||
* we make an ND6 prefix structure for the link-local prefix,
|
||||
* and add it to the prefix list as a never-expire prefix.
|
||||
* XXX: this change might affect some existing code base...
|
||||
*/
|
||||
bzero(&pr0, sizeof(pr0));
|
||||
pr0.ndpr_ifp = ifp;
|
||||
/* this should be 64 at this moment. */
|
||||
pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
|
||||
pr0.ndpr_mask = ifra.ifra_prefixmask.sin6_addr;
|
||||
pr0.ndpr_prefix = ifra.ifra_addr;
|
||||
/* apply the mask for safety. (nd6_prelist_add will apply it again) */
|
||||
for (i = 0; i < 4; i++) {
|
||||
pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
|
||||
in6mask64.s6_addr32[i];
|
||||
}
|
||||
/*
|
||||
* Initialize parameters. The link-local prefix must always be
|
||||
* on-link, and its lifetimes never expire.
|
||||
*/
|
||||
pr0.ndpr_raf_onlink = 1;
|
||||
pr0.ndpr_raf_auto = 1; /* probably meaningless */
|
||||
pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
|
||||
pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
|
||||
/*
|
||||
* Since there is no other link-local addresses, nd6_prefix_lookup()
|
||||
* probably returns NULL. However, we cannot always expect the result.
|
||||
* For example, if we first remove the (only) existing link-local
|
||||
* address, and then reconfigure another one, the prefix is still
|
||||
* valid with referring to the old link-local address.
|
||||
*/
|
||||
if (nd6_prefix_lookup(&pr0) == NULL) {
|
||||
if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
|
||||
return(error);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -507,52 +460,109 @@ static int
|
|||
in6_ifattach_loopback(ifp)
|
||||
struct ifnet *ifp; /* must be IFT_LOOP */
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_aliasreq ifra;
|
||||
int error;
|
||||
|
||||
bzero(&ifra, sizeof(ifra));
|
||||
|
||||
/*
|
||||
* configure link-local address
|
||||
* in6_update_ifa() does not use ifra_name, but we accurately set it
|
||||
* for safety.
|
||||
*/
|
||||
ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
|
||||
bzero((caddr_t)ia, sizeof(*ia));
|
||||
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
|
||||
ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
|
||||
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
|
||||
ia->ia_ifp = ifp;
|
||||
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
|
||||
|
||||
bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask));
|
||||
ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ia->ia_prefixmask.sin6_family = AF_INET6;
|
||||
ia->ia_prefixmask.sin6_addr = in6mask128;
|
||||
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_prefixmask.sin6_family = AF_INET6;
|
||||
ifra.ifra_prefixmask.sin6_addr = in6mask128;
|
||||
|
||||
/*
|
||||
* Always initialize ia_dstaddr (= broadcast address) to loopback
|
||||
* address, to make getifaddr happier.
|
||||
*
|
||||
* For BSDI, it is mandatory. The BSDI version of
|
||||
* ifa_ifwithroute() rejects to add a route to the loopback
|
||||
* interface. Even for other systems, loopback looks somewhat
|
||||
* special.
|
||||
* address. Follows IPv4 practice - see in_ifinit().
|
||||
*/
|
||||
bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr));
|
||||
ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ia->ia_dstaddr.sin6_family = AF_INET6;
|
||||
ia->ia_dstaddr.sin6_addr = in6addr_loopback;
|
||||
ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_dstaddr.sin6_family = AF_INET6;
|
||||
ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
|
||||
|
||||
bzero(&ia->ia_addr, sizeof(ia->ia_addr));
|
||||
ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ia->ia_addr.sin6_family = AF_INET6;
|
||||
ia->ia_addr.sin6_addr = in6addr_loopback;
|
||||
ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
ifra.ifra_addr.sin6_family = AF_INET6;
|
||||
ifra.ifra_addr.sin6_addr = in6addr_loopback;
|
||||
|
||||
ia->ia_ifa.ifa_metric = ifp->if_metric;
|
||||
/* the loopback address should NEVER expire. */
|
||||
ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
|
||||
if (in6_ifattach_addaddr(ifp, ia) != 0) {
|
||||
/* ia will be freed on failure */
|
||||
return -1;
|
||||
/* we don't need to perform DAD on loopback interfaces. */
|
||||
ifra.ifra_flags |= IN6_IFF_NODAD;
|
||||
|
||||
/*
|
||||
* We are sure that this is a newly assigned address, so we can set
|
||||
* NULL to the 3rd arg.
|
||||
*/
|
||||
if ((error = in6_update_ifa(ifp, &ifra, NULL)) != 0) {
|
||||
log(LOG_ERR, "in6_ifattach_loopback: failed to configure "
|
||||
"the loopback address on %s (errno=%d)\n",
|
||||
if_name(ifp), error);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* compute NI group address, based on the current hostname setting.
|
||||
* see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
|
||||
*
|
||||
* when ifp == NULL, the caller is responsible for filling scopeid.
|
||||
*/
|
||||
int
|
||||
in6_nigroup(ifp, name, namelen, sa6)
|
||||
struct ifnet *ifp;
|
||||
const char *name;
|
||||
int namelen;
|
||||
struct sockaddr_in6 *sa6;
|
||||
{
|
||||
const char *p;
|
||||
u_char *q;
|
||||
MD5_CTX ctxt;
|
||||
u_int8_t digest[16];
|
||||
char l;
|
||||
char n[64]; /* a single label must not exceed 63 chars */
|
||||
|
||||
if (!namelen || !name)
|
||||
return -1;
|
||||
|
||||
p = name;
|
||||
while (p && *p && *p != '.' && p - name < namelen)
|
||||
p++;
|
||||
if (p - name > sizeof(n) - 1)
|
||||
return -1; /* label too long */
|
||||
l = p - name;
|
||||
strncpy(n, name, l);
|
||||
n[(int)l] = '\0';
|
||||
for (q = n; *q; q++) {
|
||||
if ('A' <= *q && *q <= 'Z')
|
||||
*q = *q - 'A' + 'a';
|
||||
}
|
||||
|
||||
/* generate 8 bytes of pseudo-random value. */
|
||||
bzero(&ctxt, sizeof(ctxt));
|
||||
MD5Init(&ctxt);
|
||||
MD5Update(&ctxt, &l, sizeof(l));
|
||||
MD5Update(&ctxt, n, l);
|
||||
MD5Final(digest, &ctxt);
|
||||
|
||||
bzero(sa6, sizeof(*sa6));
|
||||
sa6->sin6_family = AF_INET6;
|
||||
sa6->sin6_len = sizeof(*sa6);
|
||||
sa6->sin6_addr.s6_addr16[0] = htons(0xff02);
|
||||
sa6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
sa6->sin6_addr.s6_addr8[11] = 2;
|
||||
bcopy(digest, &sa6->sin6_addr.s6_addr32[3],
|
||||
sizeof(sa6->sin6_addr.s6_addr32[3]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX multiple loopback interface needs more care. for instance,
|
||||
* nodelocal address needs to be configured onto only one of them.
|
||||
|
@ -563,10 +573,6 @@ in6_ifattach(ifp, altifp)
|
|||
struct ifnet *ifp;
|
||||
struct ifnet *altifp; /* secondary EUI64 source */
|
||||
{
|
||||
struct sockaddr_in6 mltaddr;
|
||||
struct sockaddr_in6 mltmask;
|
||||
struct sockaddr_in6 gate;
|
||||
struct sockaddr_in6 mask;
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_addr in6;
|
||||
|
||||
|
@ -616,125 +622,27 @@ in6_ifattach(ifp, altifp)
|
|||
}
|
||||
|
||||
/*
|
||||
* assign link-local address, if there's none
|
||||
*/
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0);
|
||||
if (ia == NULL) {
|
||||
if (in6_ifattach_linklocal(ifp, altifp) != 0)
|
||||
return;
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0);
|
||||
|
||||
if (ia == NULL) {
|
||||
printf("%s: failed to add link-local address\n",
|
||||
if_name(ifp));
|
||||
|
||||
/* we can't initialize multicasts without link-local */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_POINTOPOINT) {
|
||||
/*
|
||||
* route local address to loopback
|
||||
*/
|
||||
bzero(&gate, sizeof(gate));
|
||||
gate.sin6_len = sizeof(struct sockaddr_in6);
|
||||
gate.sin6_family = AF_INET6;
|
||||
gate.sin6_addr = in6addr_loopback;
|
||||
bzero(&mask, sizeof(mask));
|
||||
mask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
mask.sin6_family = AF_INET6;
|
||||
mask.sin6_addr = in6mask64;
|
||||
rtrequest(RTM_ADD,
|
||||
(struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&gate,
|
||||
(struct sockaddr *)&mask,
|
||||
RTF_UP|RTF_HOST,
|
||||
(struct rtentry **)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* assign loopback address for loopback interface
|
||||
* XXX multiple loopback interface case
|
||||
* assign loopback address for loopback interface.
|
||||
* XXX multiple loopback interface case.
|
||||
*/
|
||||
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
|
||||
in6 = in6addr_loopback;
|
||||
if (ifp->if_flags & IFF_LOOPBACK) {
|
||||
if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
|
||||
if (in6_ifattach_loopback(ifp) != 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (!ia) {
|
||||
panic("ia == NULL in in6_ifattach");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* join multicast
|
||||
* assign a link-local address, if there's none.
|
||||
*/
|
||||
if (ifp->if_flags & IFF_MULTICAST) {
|
||||
int error; /* not used */
|
||||
struct in6_multi *in6m;
|
||||
|
||||
/* Restore saved multicast addresses (if any). */
|
||||
in6_restoremkludge(ia, ifp);
|
||||
|
||||
bzero(&mltmask, sizeof(mltmask));
|
||||
mltmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
mltmask.sin6_family = AF_INET6;
|
||||
mltmask.sin6_addr = in6mask32;
|
||||
|
||||
/*
|
||||
* join link-local all-nodes address
|
||||
*/
|
||||
bzero(&mltaddr, sizeof(mltaddr));
|
||||
mltaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
mltaddr.sin6_family = AF_INET6;
|
||||
mltaddr.sin6_addr = in6addr_linklocal_allnodes;
|
||||
mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
|
||||
IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
|
||||
if (in6m == NULL) {
|
||||
rtrequest(RTM_ADD,
|
||||
(struct sockaddr *)&mltaddr,
|
||||
(struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&mltmask,
|
||||
RTF_UP|RTF_CLONING, /* xxx */
|
||||
(struct rtentry **)0);
|
||||
if (!in6_addmulti(&mltaddr.sin6_addr, ifp, &error)) {
|
||||
nd6log((LOG_ERR, "%s: failed to join %s "
|
||||
"(errno=%d)\n", if_name(ifp),
|
||||
ip6_sprintf(&mltaddr.sin6_addr),
|
||||
error));
|
||||
}
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_LOOPBACK) {
|
||||
in6 = in6addr_loopback;
|
||||
ia = in6ifa_ifpwithaddr(ifp, &in6);
|
||||
/*
|
||||
* join node-local all-nodes address, on loopback
|
||||
*/
|
||||
mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
|
||||
|
||||
IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m);
|
||||
if (in6m == NULL && ia != NULL) {
|
||||
rtrequest(RTM_ADD,
|
||||
(struct sockaddr *)&mltaddr,
|
||||
(struct sockaddr *)&ia->ia_addr,
|
||||
(struct sockaddr *)&mltmask,
|
||||
RTF_UP,
|
||||
(struct rtentry **)0);
|
||||
if (!in6_addmulti(&mltaddr.sin6_addr, ifp,
|
||||
&error)) {
|
||||
nd6log((LOG_ERR, "%s: failed to join "
|
||||
"%s (errno=%d)\n", if_name(ifp),
|
||||
ip6_sprintf(&mltaddr.sin6_addr),
|
||||
error));
|
||||
}
|
||||
if (ip6_auto_linklocal) {
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0);
|
||||
if (ia == NULL) {
|
||||
if (in6_ifattach_linklocal(ifp, altifp) == 0) {
|
||||
/* linklocal address assigned */
|
||||
} else {
|
||||
/* failed to assign linklocal address. bark? */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -754,9 +662,7 @@ in6_ifdetach(ifp)
|
|||
struct rtentry *rt;
|
||||
short rtflags;
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
/* nuke prefix list. this may try to remove some of ifaddrs as well */
|
||||
in6_purgeprefix(ifp);
|
||||
struct in6_multi_mship *imm;
|
||||
|
||||
/* remove neighbor management table */
|
||||
nd6_purge(ifp);
|
||||
|
@ -767,7 +673,7 @@ in6_ifdetach(ifp)
|
|||
next = ifa->ifa_list.tqe_next;
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
in6_purgeaddr(ifa, ifp);
|
||||
in6_purgeaddr(ifa);
|
||||
}
|
||||
|
||||
/* undo everything done by in6_ifattach(), just in case */
|
||||
|
@ -783,9 +689,17 @@ in6_ifdetach(ifp)
|
|||
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
|
||||
/*
|
||||
* leave from multicast groups we have joined for the interface
|
||||
*/
|
||||
while ((imm = ia->ia6_memberships.lh_first) != NULL) {
|
||||
LIST_REMOVE(imm, i6mm_chain);
|
||||
in6_leavegroup(imm);
|
||||
}
|
||||
|
||||
/* remove from the routing table */
|
||||
if ((ia->ia_flags & IFA_ROUTE)
|
||||
&& (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
|
||||
if ((ia->ia_flags & IFA_ROUTE) &&
|
||||
(rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
|
||||
rtflags = rt->rt_flags;
|
||||
rtfree(rt);
|
||||
rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_ifattach.h,v 1.7 2001/10/16 04:57:38 itojun Exp $ */
|
||||
/* $NetBSD: in6_ifattach.h,v 1.8 2002/06/08 21:22:31 itojun Exp $ */
|
||||
/* $KAME: in6_ifattach.h,v 1.8 2000/04/12 03:51:30 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -36,6 +36,7 @@
|
|||
#ifdef _KERNEL
|
||||
void in6_ifattach __P((struct ifnet *, struct ifnet *));
|
||||
void in6_ifdetach __P((struct ifnet *));
|
||||
int in6_nigroup(struct ifnet *, const char *, int, struct sockaddr_in6 *);
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETINET6_IN6_IFATTACH_H_ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_pcb.h,v 1.19 2001/10/24 06:36:38 itojun Exp $ */
|
||||
/* $NetBSD: in6_pcb.h,v 1.20 2002/06/08 21:22:31 itojun Exp $ */
|
||||
/* $KAME: in6_pcb.h,v 1.45 2001/02/09 05:59:46 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -176,11 +176,6 @@ void in6_setpeeraddr __P((struct in6pcb *, struct mbuf *));
|
|||
void in6_setsockaddr __P((struct in6pcb *, struct mbuf *));
|
||||
|
||||
/* in in6_src.c */
|
||||
struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *,
|
||||
struct ip6_pktopts *,
|
||||
struct ip6_moptions *,
|
||||
struct route_in6 *,
|
||||
struct in6_addr *, int *));
|
||||
int in6_selecthlim __P((struct in6pcb *, struct ifnet *));
|
||||
int in6_pcbsetport __P((struct in6_addr *, struct in6pcb *));
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,91 +0,0 @@
|
|||
/* $NetBSD: in6_prefix.h,v 1.5 2001/02/10 04:14:27 itojun Exp $ */
|
||||
/* $KAME: in6_prefix.h,v 1.10 2001/02/08 16:30:30 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, 1998 and 1999 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.
|
||||
*/
|
||||
|
||||
#include <sys/callout.h>
|
||||
|
||||
struct rr_prefix {
|
||||
struct ifprefix rp_ifpr;
|
||||
LIST_ENTRY(rr_prefix) rp_entry;
|
||||
LIST_HEAD(rp_addrhead, rp_addr) rp_addrhead;
|
||||
struct sockaddr_in6 rp_prefix; /* prefix */
|
||||
u_int32_t rp_vltime; /* advertised valid lifetime */
|
||||
u_int32_t rp_pltime; /* advertised preferred lifetime */
|
||||
time_t rp_expire; /* expiration time of the prefix */
|
||||
time_t rp_preferred; /* preferred time of the prefix */
|
||||
struct in6_prflags rp_flags;
|
||||
u_char rp_origin; /* from where this prefix info is obtained */
|
||||
struct rp_stateflags {
|
||||
/* if some prefix should be added to this prefix */
|
||||
u_char addmark : 1;
|
||||
u_char delmark : 1; /* if this prefix will be deleted */
|
||||
} rp_stateflags;
|
||||
};
|
||||
|
||||
#define rp_type rp_ifpr.ifpr_type
|
||||
#define rp_ifp rp_ifpr.ifpr_ifp
|
||||
#define rp_plen rp_ifpr.ifpr_plen
|
||||
|
||||
#define rp_raf rp_flags.prf_ra
|
||||
#define rp_raf_onlink rp_flags.prf_ra.onlink
|
||||
#define rp_raf_auto rp_flags.prf_ra.autonomous
|
||||
|
||||
#define rp_statef_addmark rp_stateflags.addmark
|
||||
#define rp_statef_delmark rp_stateflags.delmark
|
||||
|
||||
#define rp_rrf rp_flags.prf_rr
|
||||
#define rp_rrf_decrvalid rp_flags.prf_rr.decrvalid
|
||||
#define rp_rrf_decrprefd rp_flags.prf_rr.decrprefd
|
||||
|
||||
struct rp_addr {
|
||||
LIST_ENTRY(rp_addr) ra_entry;
|
||||
struct in6_addr ra_ifid;
|
||||
struct in6_ifaddr *ra_addr;
|
||||
struct ra_flags {
|
||||
u_char anycast : 1;
|
||||
} ra_flags;
|
||||
};
|
||||
|
||||
#define ifpr2rp(ifpr) ((struct rr_prefix *)(ifpr))
|
||||
#define rp2ifpr(rp) ((struct ifprefix *)(rp))
|
||||
|
||||
#define RP_IN6(rp) (&(rp)->rp_prefix.sin6_addr)
|
||||
|
||||
#define RR_INFINITE_LIFETIME 0xffffffff
|
||||
|
||||
|
||||
LIST_HEAD(rr_prhead, rr_prefix);
|
||||
|
||||
extern struct rr_prhead rr_prefix;
|
||||
|
||||
void in6_rr_timer __P((void *));
|
||||
extern struct callout in6_rr_timer_ch;
|
||||
int delete_each_prefix __P((struct rr_prefix *rpp, u_char origin));
|
|
@ -1,5 +1,5 @@
|
|||
/* $NetBSD: in6_var.h,v 1.31 2002/06/08 00:07:00 itojun Exp $ */
|
||||
/* $KAME: in6_var.h,v 1.53 2001/02/10 02:44:27 itojun Exp $ */
|
||||
/* $NetBSD: in6_var.h,v 1.32 2002/06/08 21:22:32 itojun Exp $ */
|
||||
/* $KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -111,8 +111,17 @@ struct in6_ifaddr {
|
|||
/* list of multicast addresses */
|
||||
int ia6_flags;
|
||||
|
||||
struct in6_addrlifetime ia6_lifetime; /* NULL = infty */
|
||||
struct ifprefix *ia6_ifpr; /* back pointer to ifprefix */
|
||||
struct in6_addrlifetime ia6_lifetime;
|
||||
time_t ia6_createtime; /* the creation time of this address, which is
|
||||
* currently used for temporary addresses only.
|
||||
*/
|
||||
time_t ia6_updatetime;
|
||||
|
||||
/* back pointer to the ND prefix (for autoconfigured addresses only) */
|
||||
struct nd_prefix *ia6_ndpr;
|
||||
|
||||
/* multicast addresses joined from the kernel */
|
||||
LIST_HEAD(, in6_multi_mship) ia6_memberships;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -270,7 +279,8 @@ struct in6_prflags {
|
|||
struct prf_ra {
|
||||
u_char onlink : 1;
|
||||
u_char autonomous : 1;
|
||||
u_char reserved : 6;
|
||||
u_char router : 1;
|
||||
u_char reserved : 5;
|
||||
} prf_ra;
|
||||
u_char prf_reserved1;
|
||||
u_short prf_reserved2;
|
||||
|
@ -352,8 +362,6 @@ struct in6_rrenumreq {
|
|||
#define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr)
|
||||
#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr)
|
||||
|
||||
#define IFPR_IN6(x) (&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr)
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
|
||||
(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
|
||||
|
@ -387,7 +395,7 @@ struct in6_rrenumreq {
|
|||
#define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq)
|
||||
|
||||
#define SIOCGDRLST_IN6 _IOWR('i', 74, struct in6_drlist)
|
||||
#define SIOCGPRLST_IN6 _IOWR('i', 75, struct in6_prlist)
|
||||
#define SIOCGPRLST_IN6 _IOWR('i', 75, struct in6_oprlist)
|
||||
#ifdef _KERNEL
|
||||
#define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq)
|
||||
#endif
|
||||
|
@ -426,6 +434,10 @@ struct in6_rrenumreq {
|
|||
#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */
|
||||
#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */
|
||||
#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */
|
||||
#define IN6_IFF_NODAD 0x20 /* don't perform DAD on this address
|
||||
* (used only at first SIOC* call)
|
||||
*/
|
||||
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
|
||||
|
||||
/* do not input/output */
|
||||
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)
|
||||
|
@ -564,12 +576,13 @@ void in6_delmulti __P((struct in6_multi *));
|
|||
struct in6_multi_mship *in6_joingroup __P((struct ifnet *, struct in6_addr *,
|
||||
int *));
|
||||
int in6_leavegroup __P((struct in6_multi_mship *));
|
||||
void in6_ifscrub __P((struct ifnet *, struct in6_ifaddr *));
|
||||
int in6_ifindex2scopeid __P((int));
|
||||
int in6_mask2len __P((struct in6_addr *));
|
||||
int in6_mask2len __P((struct in6_addr *, u_char *));
|
||||
int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
|
||||
struct proc *));
|
||||
void in6_purgeaddr __P((struct ifaddr *, struct ifnet *));
|
||||
int in6_update_ifa __P((struct ifnet *, struct in6_aliasreq *,
|
||||
struct in6_ifaddr *));
|
||||
void in6_purgeaddr __P((struct ifaddr *));
|
||||
int in6if_do_dad __P((struct ifnet *));
|
||||
void in6_purgeif __P((struct ifnet *));
|
||||
void in6_savemkludge __P((struct in6_ifaddr *));
|
||||
|
@ -586,12 +599,9 @@ int in6_addr2scopeid __P((struct ifnet *, struct in6_addr *));
|
|||
int in6_matchlen __P((struct in6_addr *, struct in6_addr *));
|
||||
int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int));
|
||||
void in6_prefixlen2mask __P((struct in6_addr *, int));
|
||||
int in6_prefix_ioctl __P((struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ifnet *ifp));
|
||||
int in6_prefix_add_ifid __P((int, struct in6_ifaddr *));
|
||||
void in6_prefix_remove_ifid __P((int, struct in6_ifaddr *));
|
||||
void in6_purgeprefix __P((struct ifnet *));
|
||||
|
||||
int in6_is_addr_deprecated __P((struct sockaddr_in6 *));
|
||||
struct in6pcb;
|
||||
int in6_embedscope __P((struct in6_addr *, const struct sockaddr_in6 *,
|
||||
struct in6pcb *, struct ifnet **));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_forward.c,v 1.30 2002/06/07 04:18:12 itojun Exp $ */
|
||||
/* $NetBSD: ip6_forward.c,v 1.31 2002/06/08 21:22:33 itojun Exp $ */
|
||||
/* $KAME: ip6_forward.c,v 1.74 2001/06/12 23:54:55 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.30 2002/06/07 04:18:12 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.31 2002/06/08 21:22:33 itojun Exp $");
|
||||
|
||||
#include "opt_ipsec.h"
|
||||
#include "opt_pfil_hooks.h"
|
||||
|
@ -528,12 +528,10 @@ ip6_forward(m, srcrt)
|
|||
return;
|
||||
switch (error) {
|
||||
case 0:
|
||||
#if 1
|
||||
if (type == ND_REDIRECT) {
|
||||
icmp6_redirect_output(mcopy, rt);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
goto freecopy;
|
||||
|
||||
case EMSGSIZE:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_input.c,v 1.54 2002/05/28 10:11:51 itojun Exp $ */
|
||||
/* $NetBSD: ip6_input.c,v 1.55 2002/06/08 21:22:33 itojun Exp $ */
|
||||
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -66,7 +66,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.54 2002/05/28 10:11:51 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.55 2002/06/08 21:22:33 itojun Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -109,7 +109,6 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.54 2002/05/28 10:11:51 itojun Exp $"
|
|||
#include <netinet/icmp6.h>
|
||||
#include <netinet6/in6_ifattach.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#include <netinet6/in6_prefix.h>
|
||||
|
||||
#ifdef IPSEC
|
||||
#include <netinet6/ipsec.h>
|
||||
|
@ -193,18 +192,10 @@ static void
|
|||
ip6_init2(dummy)
|
||||
void *dummy;
|
||||
{
|
||||
/*
|
||||
* to route local address of p2p link to loopback,
|
||||
* assign loopback address first.
|
||||
*/
|
||||
in6_ifattach(&loif[0], NULL);
|
||||
|
||||
/* nd6_timer_init */
|
||||
callout_init(&nd6_timer_ch);
|
||||
callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
|
||||
/* router renumbering prefix list maintenance */
|
||||
callout_init(&in6_rr_timer_ch);
|
||||
callout_reset(&in6_rr_timer_ch, hz, in6_rr_timer, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -281,7 +272,7 @@ ip6_input(m)
|
|||
if (m->m_len < sizeof(struct ip6_hdr)) {
|
||||
struct ifnet *inifp;
|
||||
inifp = m->m_pkthdr.rcvif;
|
||||
if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
|
||||
if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
|
||||
ip6stat.ip6s_toosmall++;
|
||||
in6_ifstat_inc(inifp, ifs6_in_hdrerr);
|
||||
return;
|
||||
|
@ -337,6 +328,9 @@ ip6_input(m)
|
|||
*/
|
||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
|
||||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
|
||||
/*
|
||||
* XXX: "badscope" is not very suitable for a multicast source.
|
||||
*/
|
||||
ip6stat.ip6s_badscope++;
|
||||
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
|
||||
goto bad;
|
||||
|
@ -497,6 +491,7 @@ ip6_input(m)
|
|||
if (ip6_forward_rt.ro_rt &&
|
||||
(ip6_forward_rt.ro_rt->rt_flags &
|
||||
(RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
|
||||
!(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
|
||||
#if 0
|
||||
/*
|
||||
* The check below is redundant since the comparison of
|
||||
|
@ -532,7 +527,7 @@ ip6_input(m)
|
|||
}
|
||||
|
||||
/*
|
||||
* FAITH(Firewall Aided Internet Translator)
|
||||
* FAITH (Firewall Aided Internet Translator)
|
||||
*/
|
||||
#if defined(NFAITH) && 0 < NFAITH
|
||||
if (ip6_keepfaith) {
|
||||
|
@ -812,6 +807,10 @@ ip6_hopopts_input(plenp, rtalertp, mp, offp)
|
|||
* This function is separate from ip6_hopopts_input() in order to
|
||||
* handle a case where the sending node itself process its hop-by-hop
|
||||
* options header. In such a case, the function is called from ip6_output().
|
||||
*
|
||||
* The function assumes that hbh header is located right after the IPv6 header
|
||||
* (RFC2460 p7), opthead is pointer into data content in m, and opthead to
|
||||
* opthead + hbhlen is located in continuous memory region.
|
||||
*/
|
||||
int
|
||||
ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
||||
|
@ -826,6 +825,7 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
u_int8_t *opt = opthead;
|
||||
u_int16_t rtalert_val;
|
||||
u_int32_t jumboplen;
|
||||
const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
|
||||
|
||||
for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
|
||||
switch (*opt) {
|
||||
|
@ -846,9 +846,11 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
goto bad;
|
||||
}
|
||||
if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
|
||||
/* XXX: should we discard the packet? */
|
||||
log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
|
||||
*(opt + 1));
|
||||
/* XXX stat */
|
||||
icmp6_error(m, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_HEADER,
|
||||
erroff + opt + 1 - opthead);
|
||||
return (-1);
|
||||
}
|
||||
optlen = IP6OPT_RTALERT_LEN;
|
||||
bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
|
||||
|
@ -861,10 +863,11 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
goto bad;
|
||||
}
|
||||
if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
|
||||
/* XXX: should we discard the packet? */
|
||||
log(LOG_ERR, "length of jumbopayload opt "
|
||||
"is inconsistent(%d)\n",
|
||||
*(opt + 1));
|
||||
/* XXX stat */
|
||||
icmp6_error(m, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_HEADER,
|
||||
erroff + opt + 1 - opthead);
|
||||
return (-1);
|
||||
}
|
||||
optlen = IP6OPT_JUMBO_LEN;
|
||||
|
||||
|
@ -877,10 +880,8 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
ip6stat.ip6s_badoptions++;
|
||||
icmp6_error(m, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_HEADER,
|
||||
sizeof(struct ip6_hdr) +
|
||||
sizeof(struct ip6_hbh) +
|
||||
opt - opthead);
|
||||
return(-1);
|
||||
erroff + opt - opthead);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -903,10 +904,8 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
ip6stat.ip6s_badoptions++;
|
||||
icmp6_error(m, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_HEADER,
|
||||
sizeof(struct ip6_hdr) +
|
||||
sizeof(struct ip6_hbh) +
|
||||
opt + 2 - opthead);
|
||||
return(-1);
|
||||
erroff + opt + 2 - opthead);
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -917,10 +916,8 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
ip6stat.ip6s_badoptions++;
|
||||
icmp6_error(m, ICMP6_PARAM_PROB,
|
||||
ICMP6_PARAMPROB_HEADER,
|
||||
sizeof(struct ip6_hdr) +
|
||||
sizeof(struct ip6_hbh) +
|
||||
opt + 2 - opthead);
|
||||
return(-1);
|
||||
erroff + opt + 2 - opthead);
|
||||
return (-1);
|
||||
}
|
||||
*plenp = jumboplen;
|
||||
|
||||
|
@ -930,21 +927,20 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
|
|||
ip6stat.ip6s_toosmall++;
|
||||
goto bad;
|
||||
}
|
||||
if ((optlen = ip6_unknown_opt(opt, m,
|
||||
sizeof(struct ip6_hdr) +
|
||||
sizeof(struct ip6_hbh) +
|
||||
opt - opthead)) == -1)
|
||||
return(-1);
|
||||
optlen = ip6_unknown_opt(opt, m,
|
||||
erroff + opt - opthead);
|
||||
if (optlen == -1)
|
||||
return (-1);
|
||||
optlen += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
return (0);
|
||||
|
||||
bad:
|
||||
m_freem(m);
|
||||
return(-1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_output.c,v 1.53 2002/06/07 22:03:02 itojun Exp $ */
|
||||
/* $NetBSD: ip6_output.c,v 1.54 2002/06/08 21:22:33 itojun Exp $ */
|
||||
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -66,7 +66,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.53 2002/06/07 22:03:02 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.54 2002/06/08 21:22:33 itojun Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -433,7 +433,7 @@ skip_ipsec2:;
|
|||
|
||||
/* Source address validation */
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
|
||||
(flags & IPV6_DADOUTPUT) == 0) {
|
||||
(flags & IPV6_UNSPECSRC) == 0) {
|
||||
error = EOPNOTSUPP;
|
||||
ip6stat.ip6s_badscope++;
|
||||
goto bad;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_var.h,v 1.20 2002/06/07 22:03:02 itojun Exp $ */
|
||||
/* $NetBSD: ip6_var.h,v 1.21 2002/06/08 21:22:33 itojun Exp $ */
|
||||
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -107,7 +107,7 @@ struct ip6asfrag {
|
|||
u_int16_t ip6af_mff; /* more fragment bit in frag off */
|
||||
};
|
||||
|
||||
#define IP6_REASS_MBUF(ip6af) (*(struct mbuf **)&((ip6af)->ip6af_m))
|
||||
#define IP6_REASS_MBUF(ip6af) ((ip6af)->ip6af_m)
|
||||
|
||||
struct ip6_moptions {
|
||||
struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
|
||||
|
@ -202,7 +202,7 @@ struct ip6stat {
|
|||
|
||||
#ifdef _KERNEL
|
||||
/* flags passed to ip6_output as last parameter */
|
||||
#define IPV6_DADOUTPUT 0x01 /* DAD */
|
||||
#define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */
|
||||
#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */
|
||||
#define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */
|
||||
|
||||
|
@ -232,6 +232,7 @@ extern int ip6_dad_count; /* DupAddrDetectionTransmits */
|
|||
|
||||
extern u_int32_t ip6_flow_seq;
|
||||
extern int ip6_auto_flowlabel;
|
||||
extern int ip6_auto_linklocal;
|
||||
|
||||
extern int ip6_anonportmin; /* minimum ephemeral port */
|
||||
extern int ip6_anonportmax; /* maximum ephemeral port */
|
||||
|
@ -285,6 +286,10 @@ int rip6_usrreq __P((struct socket *,
|
|||
|
||||
int dest6_input __P((struct mbuf **, int *, int));
|
||||
int none_input __P((struct mbuf **, int *, int));
|
||||
|
||||
struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *,
|
||||
struct ip6_pktopts *, struct ip6_moptions *, struct route_in6 *,
|
||||
struct in6_addr *, int *));
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_NETINET6_IP6_VAR_H_ */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mld6.c,v 1.18 2002/01/08 04:37:32 itojun Exp $ */
|
||||
/* $NetBSD: mld6.c,v 1.19 2002/06/08 21:22:34 itojun Exp $ */
|
||||
/* $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -70,7 +70,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.18 2002/01/08 04:37:32 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.19 2002/06/08 21:22:34 itojun Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
|
@ -157,8 +157,9 @@ mld6_start_listening(in6m)
|
|||
in6m->in6m_state = MLD6_OTHERLISTENER;
|
||||
} else {
|
||||
mld6_sendpkt(in6m, MLD6_LISTENER_REPORT, NULL);
|
||||
in6m->in6m_timer = MLD6_RANDOM_DELAY(
|
||||
MLD6_UNSOLICITED_REPORT_INTERVAL * PR_FASTHZ);
|
||||
in6m->in6m_timer =
|
||||
MLD6_RANDOM_DELAY(MLD6_UNSOLICITED_REPORT_INTERVAL *
|
||||
PR_FASTHZ);
|
||||
in6m->in6m_state = MLD6_IREPORTEDLAST;
|
||||
mld6_timers_are_running = 1;
|
||||
}
|
||||
|
@ -339,6 +340,11 @@ mld6_input(m, off)
|
|||
break;
|
||||
default: /* this is impossible */
|
||||
#if 0
|
||||
/*
|
||||
* this case should be impossible because of filtering in
|
||||
* icmp6_input(). But we explicitly disabled this part
|
||||
* just in case.
|
||||
*/
|
||||
log(LOG_ERR, "mld6_input: illegal type(%d)", mldh->mld6_type);
|
||||
#endif
|
||||
break;
|
||||
|
@ -353,7 +359,6 @@ mld6_fasttimeo()
|
|||
struct in6_multi *in6m;
|
||||
struct in6_multistep step;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* Quick check to see if any work needs to be done, in order
|
||||
* to minimize the overhead of fasttimo processing.
|
||||
|
@ -390,14 +395,19 @@ mld6_sendpkt(in6m, type, dst)
|
|||
struct ip6_moptions im6o;
|
||||
struct in6_ifaddr *ia;
|
||||
struct ifnet *ifp = in6m->in6m_ifp;
|
||||
int ignflags;
|
||||
|
||||
/*
|
||||
* At first, find a link local address on the outgoing interface
|
||||
* to use as the source address of the MLD packet.
|
||||
* We do not reject tentative addresses for MLD report to deal with
|
||||
* the case where we first join a link-local address.
|
||||
*/
|
||||
if ((ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST))
|
||||
== NULL)
|
||||
ignflags = (IN6_IFF_NOTREADY|IN6_IFF_ANYCAST) & ~IN6_IFF_TENTATIVE;
|
||||
if ((ia = in6ifa_ifpforlinklocal(ifp, ignflags)) == NULL)
|
||||
return;
|
||||
if ((ia->ia6_flags & IN6_IFF_TENTATIVE))
|
||||
ia = NULL;
|
||||
|
||||
/*
|
||||
* Allocate mbufs to store ip6 header and MLD header.
|
||||
|
@ -414,6 +424,7 @@ mld6_sendpkt(in6m, type, dst)
|
|||
}
|
||||
mh->m_next = md;
|
||||
|
||||
mh->m_pkthdr.rcvif = NULL;
|
||||
mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld6_hdr);
|
||||
mh->m_len = sizeof(struct ip6_hdr);
|
||||
MH_ALIGN(mh, sizeof(struct ip6_hdr));
|
||||
|
@ -426,7 +437,7 @@ mld6_sendpkt(in6m, type, dst)
|
|||
/* ip6_plen will be set later */
|
||||
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
||||
/* ip6_hlim will be set by im6o.im6o_multicast_hlim */
|
||||
ip6->ip6_src = ia->ia_addr.sin6_addr;
|
||||
ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any;
|
||||
ip6->ip6_dst = dst ? *dst : in6m->in6m_addr;
|
||||
|
||||
/* fill in the MLD header */
|
||||
|
@ -458,8 +469,6 @@ mld6_sendpkt(in6m, type, dst)
|
|||
|
||||
/* increment output statictics */
|
||||
icmp6stat.icp6s_outhist[type]++;
|
||||
|
||||
ip6_output(mh, &ip6_opts, NULL, 0, &im6o, NULL);
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_msg);
|
||||
switch (type) {
|
||||
case MLD6_LISTENER_QUERY:
|
||||
|
@ -472,4 +481,6 @@ mld6_sendpkt(in6m, type, dst)
|
|||
icmp6_ifstat_inc(ifp, ifs6_out_mlddone);
|
||||
break;
|
||||
}
|
||||
|
||||
ip6_output(mh, &ip6_opts, NULL, ia ? 0 : IPV6_UNSPECSRC, &im6o, NULL);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $NetBSD: nd6.c,v 1.64 2002/06/07 17:15:12 itojun Exp $ */
|
||||
/* $KAME: nd6.c,v 1.151 2001/06/19 14:24:41 sumikawa Exp $ */
|
||||
/* $NetBSD: nd6.c,v 1.65 2002/06/08 21:22:34 itojun Exp $ */
|
||||
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.64 2002/06/07 17:15:12 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.65 2002/06/08 21:22:34 itojun Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -61,7 +61,6 @@ __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.64 2002/06/07 17:15:12 itojun Exp $");
|
|||
#include <netinet/ip6.h>
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#include <netinet6/in6_prefix.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include "loop.h"
|
||||
|
@ -111,6 +110,9 @@ static struct llinfo_nd6 *nd6_free __P((struct rtentry *, int));
|
|||
struct callout nd6_slowtimo_ch;
|
||||
struct callout nd6_timer_ch;
|
||||
|
||||
static int fill_drlist __P((void *, size_t *, size_t));
|
||||
static int fill_prlist __P((void *, size_t *, size_t));
|
||||
|
||||
void
|
||||
nd6_init()
|
||||
{
|
||||
|
@ -152,7 +154,12 @@ nd6_ifattach(ifp)
|
|||
nd->basereachable = REACHABLE_TIME;
|
||||
nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
|
||||
nd->retrans = RETRANS_TIMER;
|
||||
nd->flags = ND6_IFF_PERFORMNUD;
|
||||
/*
|
||||
* Note that the default value of ip6_accept_rtadv is 0, which means
|
||||
* we won't accept RAs by default even if we set ND6_IFF_ACCEPT_RTADV
|
||||
* here.
|
||||
*/
|
||||
nd->flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);
|
||||
|
||||
/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
|
||||
nd6_setmtu0(ifp, nd);
|
||||
|
@ -374,6 +381,9 @@ nd6_timer(ignored_arg)
|
|||
struct nd_defrouter *dr;
|
||||
struct nd_prefix *pr;
|
||||
long time_second = time.tv_sec;
|
||||
struct ifnet *ifp;
|
||||
struct in6_ifaddr *ia6, *nia6;
|
||||
struct in6_addrlifetime *lt6;
|
||||
|
||||
s = splsoftnet();
|
||||
callout_reset(&nd6_timer_ch, nd6_prune * hz,
|
||||
|
@ -382,7 +392,6 @@ nd6_timer(ignored_arg)
|
|||
ln = llinfo_nd6.ln_next;
|
||||
while (ln && ln != &llinfo_nd6) {
|
||||
struct rtentry *rt;
|
||||
struct ifnet *ifp;
|
||||
struct sockaddr_in6 *dst;
|
||||
struct llinfo_nd6 *next = ln->ln_next;
|
||||
/* XXX: used for the DELAY case only: */
|
||||
|
@ -424,16 +433,15 @@ nd6_timer(ignored_arg)
|
|||
} else {
|
||||
struct mbuf *m = ln->ln_hold;
|
||||
if (m) {
|
||||
if (rt->rt_ifp) {
|
||||
/*
|
||||
* Fake rcvif to make ICMP error
|
||||
* more helpful in diagnosing
|
||||
* for the receiver.
|
||||
* Fake rcvif to make the ICMP error
|
||||
* more helpful in diagnosing for the
|
||||
* receiver.
|
||||
* XXX: should we consider
|
||||
* older rcvif?
|
||||
*/
|
||||
m->m_pkthdr.rcvif = rt->rt_ifp;
|
||||
}
|
||||
|
||||
icmp6_error(m, ICMP6_DST_UNREACH,
|
||||
ICMP6_DST_UNREACH_ADDR, 0);
|
||||
ln->ln_hold = NULL;
|
||||
|
@ -462,8 +470,7 @@ nd6_timer(ignored_arg)
|
|||
ln->ln_expire = time_second +
|
||||
ND6_RETRANS_SEC(ndi->retrans);
|
||||
nd6_ns_output(ifp, &dst->sin6_addr,
|
||||
&dst->sin6_addr,
|
||||
ln, 0);
|
||||
&dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE; /* XXX */
|
||||
ln->ln_expire = time_second + nd6_gctimer;
|
||||
|
@ -496,46 +503,47 @@ nd6_timer(ignored_arg)
|
|||
dr = TAILQ_NEXT(dr, dr_entry);
|
||||
}
|
||||
}
|
||||
pr = nd_prefix.lh_first;
|
||||
while (pr) {
|
||||
struct in6_ifaddr *ia6;
|
||||
struct in6_addrlifetime *lt6;
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
|
||||
ia6 = NULL;
|
||||
else
|
||||
ia6 = in6ifa_ifpwithaddr(pr->ndpr_ifp, &pr->ndpr_addr);
|
||||
|
||||
if (ia6) {
|
||||
/*
|
||||
* expire interface addresses.
|
||||
* in the past the loop was inside prefix expiry processing.
|
||||
* However, from a stricter speci-confrmance standpoint, we should
|
||||
* rather separate address lifetimes and prefix lifetimes.
|
||||
*/
|
||||
for (ia6 = in6_ifaddr; ia6; ia6 = nia6) {
|
||||
nia6 = ia6->ia_next;
|
||||
/* check address lifetime */
|
||||
lt6 = &ia6->ia6_lifetime;
|
||||
if (lt6->ia6t_preferred && lt6->ia6t_preferred < time_second)
|
||||
if (IFA6_IS_INVALID(ia6)) {
|
||||
in6_purgeaddr(&ia6->ia_ifa);
|
||||
}
|
||||
if (IFA6_IS_DEPRECATED(ia6)) {
|
||||
ia6->ia6_flags |= IN6_IFF_DEPRECATED;
|
||||
if (lt6->ia6t_expire && lt6->ia6t_expire < time_second) {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
|
||||
in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
|
||||
/* xxx ND_OPT_PI_FLAG_ONLINK processing */
|
||||
} else {
|
||||
/*
|
||||
* A new RA might have made a deprecated address
|
||||
* preferred.
|
||||
*/
|
||||
ia6->ia6_flags &= ~IN6_IFF_DEPRECATED;
|
||||
}
|
||||
}
|
||||
|
||||
/* expire prefix list */
|
||||
pr = nd_prefix.lh_first;
|
||||
while (pr) {
|
||||
/*
|
||||
* check prefix lifetime.
|
||||
* since pltime is just for autoconf, pltime processing for
|
||||
* prefix is not necessary.
|
||||
*
|
||||
* we offset expire time by NDPR_KEEP_EXPIRE, so that we
|
||||
* can use the old prefix information to validate the
|
||||
* next prefix information to come. See prelist_update()
|
||||
* for actual validation.
|
||||
*/
|
||||
if (pr->ndpr_expire
|
||||
&& pr->ndpr_expire + NDPR_KEEP_EXPIRED < time_second) {
|
||||
if (pr->ndpr_vltime != ND6_INFINITE_LIFETIME &&
|
||||
time_second - pr->ndpr_lastupdate > pr->ndpr_vltime) {
|
||||
struct nd_prefix *t;
|
||||
t = pr->ndpr_next;
|
||||
|
||||
/*
|
||||
* address expiration and prefix expiration are
|
||||
* separate. NEVER perform in6_ifdel here.
|
||||
* separate. NEVER perform in6_purgeaddr here.
|
||||
*/
|
||||
|
||||
prelist_remove(pr);
|
||||
|
@ -555,21 +563,28 @@ nd6_purge(ifp)
|
|||
struct ifnet *ifp;
|
||||
{
|
||||
struct llinfo_nd6 *ln, *nln;
|
||||
struct nd_defrouter *dr, *ndr, drany;
|
||||
struct nd_defrouter *dr, *ndr;
|
||||
struct nd_prefix *pr, *npr;
|
||||
|
||||
/* Nuke default router list entries toward ifp */
|
||||
if ((dr = TAILQ_FIRST(&nd_defrouter)) != NULL) {
|
||||
/*
|
||||
* The first entry of the list may be stored in
|
||||
* the routing table, so we'll delete it later.
|
||||
* Nuke default router list entries toward ifp.
|
||||
* We defer removal of default router list entries that is installed
|
||||
* in the routing table, in order to keep additional side effects as
|
||||
* small as possible.
|
||||
*/
|
||||
for (dr = TAILQ_NEXT(dr, dr_entry); dr; dr = ndr) {
|
||||
for (dr = TAILQ_FIRST(&nd_defrouter); dr; dr = ndr) {
|
||||
ndr = TAILQ_NEXT(dr, dr_entry);
|
||||
if (dr->installed)
|
||||
continue;
|
||||
|
||||
if (dr->ifp == ifp)
|
||||
defrtrlist_del(dr);
|
||||
}
|
||||
dr = TAILQ_FIRST(&nd_defrouter);
|
||||
for (dr = TAILQ_FIRST(&nd_defrouter); dr; dr = ndr) {
|
||||
ndr = TAILQ_NEXT(dr, dr_entry);
|
||||
if (!dr->installed)
|
||||
continue;
|
||||
|
||||
if (dr->ifp == ifp)
|
||||
defrtrlist_del(dr);
|
||||
}
|
||||
|
@ -578,8 +593,14 @@ nd6_purge(ifp)
|
|||
for (pr = nd_prefix.lh_first; pr; pr = npr) {
|
||||
npr = pr->ndpr_next;
|
||||
if (pr->ndpr_ifp == ifp) {
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
|
||||
in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
|
||||
/*
|
||||
* Previously, pr->ndpr_addr is removed as well,
|
||||
* but I strongly believe we don't have to do it.
|
||||
* nd6_purge() is only called from in6_ifdetach(),
|
||||
* which removes all the associated interface addresses
|
||||
* by itself.
|
||||
* (jinmei@kame.net 20010129)
|
||||
*/
|
||||
prelist_remove(pr);
|
||||
}
|
||||
}
|
||||
|
@ -590,8 +611,6 @@ nd6_purge(ifp)
|
|||
|
||||
if (!ip6_forwarding && ip6_accept_rtadv) { /* XXX: too restrictive? */
|
||||
/* refresh default router list */
|
||||
bzero(&drany, sizeof(drany));
|
||||
defrouter_delreq(&drany, 0);
|
||||
defrouter_select();
|
||||
}
|
||||
|
||||
|
@ -667,12 +686,9 @@ nd6_lookup(addr6, create, ifp)
|
|||
* called in rtrequest via ifa->ifa_rtrequest.
|
||||
*/
|
||||
if ((e = rtrequest(RTM_ADD, (struct sockaddr *)&sin6,
|
||||
ifa->ifa_addr,
|
||||
(struct sockaddr *)&all1_sa,
|
||||
(ifa->ifa_flags |
|
||||
RTF_HOST | RTF_LLINFO) &
|
||||
~RTF_CLONING,
|
||||
&rt)) != 0) {
|
||||
ifa->ifa_addr, (struct sockaddr *)&all1_sa,
|
||||
(ifa->ifa_flags | RTF_HOST | RTF_LLINFO) &
|
||||
~RTF_CLONING, &rt)) != 0) {
|
||||
#if 0
|
||||
log(LOG_ERR,
|
||||
"nd6_lookup: failed to add route for a "
|
||||
|
@ -694,19 +710,26 @@ nd6_lookup(addr6, create, ifp)
|
|||
rt->rt_refcnt--;
|
||||
/*
|
||||
* Validation for the entry.
|
||||
* Note that the check for rt_llinfo is necessary because a cloned
|
||||
* route from a parent route that has the L flag (e.g. the default
|
||||
* route to a p2p interface) may have the flag, too, while the
|
||||
* destination is not actually a neighbor.
|
||||
* XXX: we can't use rt->rt_ifp to check for the interface, since
|
||||
* it might be the loopback interface if the entry is for our
|
||||
* own address on a non-loopback interface. Instead, we should
|
||||
* use rt->rt_ifa->ifa_ifp, which would specify the REAL interface.
|
||||
* use rt->rt_ifa->ifa_ifp, which would specify the REAL
|
||||
* interface.
|
||||
*/
|
||||
if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
|
||||
rt->rt_gateway->sa_family != AF_LINK ||
|
||||
rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
|
||||
(ifp && rt->rt_ifa->ifa_ifp != ifp)) {
|
||||
if (create) {
|
||||
log(LOG_DEBUG, "nd6_lookup: failed to lookup %s (if = %s)\n",
|
||||
ip6_sprintf(addr6), ifp ? if_name(ifp) : "unspec");
|
||||
log(LOG_DEBUG,
|
||||
"nd6_lookup: failed to lookup %s (if = %s)\n",
|
||||
ip6_sprintf(addr6),
|
||||
ifp ? if_name(ifp) : "unspec");
|
||||
}
|
||||
return(0);
|
||||
return(NULL);
|
||||
}
|
||||
return(rt);
|
||||
}
|
||||
|
@ -720,11 +743,8 @@ nd6_is_addr_neighbor(addr, ifp)
|
|||
struct sockaddr_in6 *addr;
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int i;
|
||||
|
||||
#define IFADDR6(a) ((((struct in6_ifaddr *)(a))->ia_addr).sin6_addr)
|
||||
#define IFMASK6(a) ((((struct in6_ifaddr *)(a))->ia_prefixmask).sin6_addr)
|
||||
struct nd_prefix *pr;
|
||||
struct rtentry *rt;
|
||||
|
||||
/*
|
||||
* A link-local address is always a neighbor.
|
||||
|
@ -737,22 +757,29 @@ nd6_is_addr_neighbor(addr, ifp)
|
|||
return(1);
|
||||
|
||||
/*
|
||||
* If the address matches one of our addresses,
|
||||
* it should be a neighbor.
|
||||
* If the address matches one of our on-link prefixes, it should be a
|
||||
* neighbor.
|
||||
*/
|
||||
for (ifa = ifp->if_addrlist.tqh_first;
|
||||
ifa;
|
||||
ifa = ifa->ifa_list.tqe_next)
|
||||
{
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
next: continue;
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
|
||||
if (pr->ndpr_ifp != ifp)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if ((IFADDR6(ifa).s6_addr32[i] ^
|
||||
addr->sin6_addr.s6_addr32[i]) &
|
||||
IFMASK6(ifa).s6_addr32[i])
|
||||
goto next;
|
||||
if (!(pr->ndpr_stateflags & NDPRF_ONLINK))
|
||||
continue;
|
||||
|
||||
if (IN6_ARE_MASKED_ADDR_EQUAL(&pr->ndpr_prefix.sin6_addr,
|
||||
&addr->sin6_addr, &pr->ndpr_mask))
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the default router list is empty, all addresses are regarded
|
||||
* as on-link, and thus, as a neighbor.
|
||||
* XXX: we restrict the condition to hosts, because routers usually do
|
||||
* not have the "default router list".
|
||||
*/
|
||||
if (!ip6_forwarding && TAILQ_FIRST(&nd_defrouter) == NULL &&
|
||||
nd6_defifindex == ifp->if_index) {
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
@ -760,12 +787,10 @@ nd6_is_addr_neighbor(addr, ifp)
|
|||
* Even if the address matches none of our addresses, it might be
|
||||
* in the neighbor cache.
|
||||
*/
|
||||
if (nd6_lookup(&addr->sin6_addr, 0, ifp))
|
||||
if ((rt = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL)
|
||||
return(1);
|
||||
|
||||
return(0);
|
||||
#undef IFADDR6
|
||||
#undef IFMASK6
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -846,20 +871,11 @@ nd6_free(rt, gc)
|
|||
*/
|
||||
pfxlist_onlink_check();
|
||||
|
||||
if (dr == TAILQ_FIRST(&nd_defrouter)) {
|
||||
/*
|
||||
* It is used as the current default router,
|
||||
* so we have to move it to the end of the
|
||||
* list and choose a new one.
|
||||
* XXX: it is not very efficient if this is
|
||||
* the only router.
|
||||
* refresh default router list
|
||||
*/
|
||||
TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
|
||||
TAILQ_INSERT_TAIL(&nd_defrouter, dr, dr_entry);
|
||||
|
||||
defrouter_select();
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
@ -946,8 +962,9 @@ nd6_rtrequest(req, rt, info)
|
|||
struct ifnet *ifp = rt->rt_ifp;
|
||||
struct ifaddr *ifa;
|
||||
long time_second = time.tv_sec;
|
||||
int mine = 0;
|
||||
|
||||
if ((rt->rt_flags & RTF_GATEWAY))
|
||||
if ((rt->rt_flags & RTF_GATEWAY) != 0)
|
||||
return;
|
||||
|
||||
if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
|
||||
|
@ -961,6 +978,27 @@ nd6_rtrequest(req, rt, info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (req == RTM_RESOLVE &&
|
||||
(nd6_need_cache(ifp) == 0 || /* stf case */
|
||||
!nd6_is_addr_neighbor((struct sockaddr_in6 *)rt_key(rt), ifp))) {
|
||||
/*
|
||||
* FreeBSD and BSD/OS often make a cloned host route based
|
||||
* on a less-specific route (e.g. the default route).
|
||||
* If the less specific route does not have a "gateway"
|
||||
* (this is the case when the route just goes to a p2p or an
|
||||
* stf interface), we'll mistakenly make a neighbor cache for
|
||||
* the host route, and will see strange neighbor solicitation
|
||||
* for the corresponding destination. In order to avoid the
|
||||
* confusion, we check if the destination of the route is
|
||||
* a neighbor in terms of neighbor discovery, and stop the
|
||||
* process if not. Additionally, we remove the LLINFO flag
|
||||
* so that ndp(8) will not try to get the neighbor information
|
||||
* of the destination.
|
||||
*/
|
||||
rt->rt_flags &= ~RTF_LLINFO;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (req) {
|
||||
case RTM_ADD:
|
||||
/*
|
||||
|
@ -988,13 +1026,13 @@ nd6_rtrequest(req, rt, info)
|
|||
if (ln && ln->ln_expire == 0) {
|
||||
/* kludge for desktops */
|
||||
#if 0
|
||||
printf("nd6_rtequest: time.tv_sec is zero; "
|
||||
printf("nd6_rtrequest: time.tv_sec is zero; "
|
||||
"treat it as 1\n");
|
||||
#endif
|
||||
ln->ln_expire = 1;
|
||||
}
|
||||
#endif
|
||||
if ((rt->rt_flags & RTF_CLONING))
|
||||
if ((rt->rt_flags & RTF_CLONING) != 0)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
|
@ -1026,7 +1064,7 @@ nd6_rtrequest(req, rt, info)
|
|||
#endif
|
||||
/* FALLTHROUGH */
|
||||
case RTM_RESOLVE:
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
|
||||
if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
|
||||
/*
|
||||
* Address resolution isn't necessary for a point to
|
||||
* point link, so we can skip this test for a p2p link.
|
||||
|
@ -1091,6 +1129,7 @@ nd6_rtrequest(req, rt, info)
|
|||
ln->ln_expire = 0;
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
ln->ln_byhint = 0;
|
||||
mine = 1;
|
||||
if (macp) {
|
||||
Bcopy(macp, LLADDR(SDL(gate)), ifp->if_addrlen);
|
||||
SDL(gate)->sdl_alen = ifp->if_addrlen;
|
||||
|
@ -1169,65 +1208,6 @@ nd6_rtrequest(req, rt, info)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nd6_p2p_rtrequest(req, rt, info)
|
||||
int req;
|
||||
struct rtentry *rt;
|
||||
struct rt_addrinfo *info; /* xxx unused */
|
||||
{
|
||||
struct sockaddr *gate = rt->rt_gateway;
|
||||
static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
|
||||
struct ifnet *ifp = rt->rt_ifp;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
if (rt->rt_flags & RTF_GATEWAY)
|
||||
return;
|
||||
|
||||
switch (req) {
|
||||
case RTM_ADD:
|
||||
/*
|
||||
* There is no backward compatibility :)
|
||||
*
|
||||
* if ((rt->rt_flags & RTF_HOST) == 0 &&
|
||||
* SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
|
||||
* rt->rt_flags |= RTF_CLONING;
|
||||
*/
|
||||
if (rt->rt_flags & RTF_CLONING) {
|
||||
/*
|
||||
* Case 1: This route should come from
|
||||
* a route to interface.
|
||||
*/
|
||||
rt_setgate(rt, rt_key(rt),
|
||||
(struct sockaddr *)&null_sdl);
|
||||
gate = rt->rt_gateway;
|
||||
SDL(gate)->sdl_type = ifp->if_type;
|
||||
SDL(gate)->sdl_index = ifp->if_index;
|
||||
break;
|
||||
}
|
||||
/* Announce a new entry if requested. */
|
||||
if (rt->rt_flags & RTF_ANNOUNCE)
|
||||
nd6_na_output(ifp,
|
||||
&SIN6(rt_key(rt))->sin6_addr,
|
||||
&SIN6(rt_key(rt))->sin6_addr,
|
||||
ip6_forwarding ? ND_NA_FLAG_ROUTER : 0,
|
||||
1, NULL);
|
||||
/* FALLTHROUGH */
|
||||
case RTM_RESOLVE:
|
||||
/*
|
||||
* check if rt_key(rt) is one of my address assigned
|
||||
* to the interface.
|
||||
*/
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(rt->rt_ifp,
|
||||
&SIN6(rt_key(rt))->sin6_addr);
|
||||
if (ifa) {
|
||||
if (nd6_useloopback) {
|
||||
rt->rt_ifp = &loif[0]; /*XXX*/
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nd6_ioctl(cmd, data, ifp)
|
||||
u_long cmd;
|
||||
|
@ -1235,11 +1215,11 @@ nd6_ioctl(cmd, data, ifp)
|
|||
struct ifnet *ifp;
|
||||
{
|
||||
struct in6_drlist *drl = (struct in6_drlist *)data;
|
||||
struct in6_prlist *prl = (struct in6_prlist *)data;
|
||||
struct in6_oprlist *oprl = (struct in6_oprlist *)data;
|
||||
struct in6_ndireq *ndi = (struct in6_ndireq *)data;
|
||||
struct in6_nbrinfo *nbi = (struct in6_nbrinfo *)data;
|
||||
struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
|
||||
struct nd_defrouter *dr, any;
|
||||
struct nd_defrouter *dr;
|
||||
struct nd_prefix *pr;
|
||||
struct rtentry *rt;
|
||||
int i = 0, error = 0;
|
||||
|
@ -1247,6 +1227,9 @@ nd6_ioctl(cmd, data, ifp)
|
|||
|
||||
switch (cmd) {
|
||||
case SIOCGDRLST_IN6:
|
||||
/*
|
||||
* obsolete API, use sysctl under net.inet6.icmp6
|
||||
*/
|
||||
bzero(drl, sizeof(*drl));
|
||||
s = splsoftnet();
|
||||
dr = TAILQ_FIRST(&nd_defrouter);
|
||||
|
@ -1271,31 +1254,38 @@ nd6_ioctl(cmd, data, ifp)
|
|||
splx(s);
|
||||
break;
|
||||
case SIOCGPRLST_IN6:
|
||||
/*
|
||||
* obsolete API, use sysctl under net.inet6.icmp6
|
||||
*
|
||||
* XXX the structure in6_prlist was changed in backward-
|
||||
* incompatible manner. in6_oprlist is used for SIOCGPRLST_IN6,
|
||||
* in6_prlist is used for nd6_sysctl() - fill_prlist().
|
||||
*/
|
||||
/*
|
||||
* XXX meaning of fields, especialy "raflags", is very
|
||||
* differnet between RA prefix list and RR/static prefix list.
|
||||
* how about separating ioctls into two?
|
||||
*/
|
||||
bzero(prl, sizeof(*prl));
|
||||
bzero(oprl, sizeof(*oprl));
|
||||
s = splsoftnet();
|
||||
pr = nd_prefix.lh_first;
|
||||
while (pr && i < PRLSTSIZ) {
|
||||
struct nd_pfxrouter *pfr;
|
||||
int j;
|
||||
|
||||
prl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
|
||||
prl->prefix[i].raflags = pr->ndpr_raf;
|
||||
prl->prefix[i].prefixlen = pr->ndpr_plen;
|
||||
prl->prefix[i].vltime = pr->ndpr_vltime;
|
||||
prl->prefix[i].pltime = pr->ndpr_pltime;
|
||||
prl->prefix[i].if_index = pr->ndpr_ifp->if_index;
|
||||
prl->prefix[i].expire = pr->ndpr_expire;
|
||||
oprl->prefix[i].prefix = pr->ndpr_prefix.sin6_addr;
|
||||
oprl->prefix[i].raflags = pr->ndpr_raf;
|
||||
oprl->prefix[i].prefixlen = pr->ndpr_plen;
|
||||
oprl->prefix[i].vltime = pr->ndpr_vltime;
|
||||
oprl->prefix[i].pltime = pr->ndpr_pltime;
|
||||
oprl->prefix[i].if_index = pr->ndpr_ifp->if_index;
|
||||
oprl->prefix[i].expire = pr->ndpr_expire;
|
||||
|
||||
pfr = pr->ndpr_advrtrs.lh_first;
|
||||
j = 0;
|
||||
while (pfr) {
|
||||
if (j < DRLSTSIZ) {
|
||||
#define RTRADDR prl->prefix[i].advrtr[j]
|
||||
#define RTRADDR oprl->prefix[i].advrtr[j]
|
||||
RTRADDR = pfr->router->rtaddr;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&RTRADDR)) {
|
||||
/* XXX: hack for KAME */
|
||||
|
@ -1311,31 +1301,12 @@ nd6_ioctl(cmd, data, ifp)
|
|||
j++;
|
||||
pfr = pfr->pfr_next;
|
||||
}
|
||||
prl->prefix[i].advrtrs = j;
|
||||
prl->prefix[i].origin = PR_ORIG_RA;
|
||||
oprl->prefix[i].advrtrs = j;
|
||||
oprl->prefix[i].origin = PR_ORIG_RA;
|
||||
|
||||
i++;
|
||||
pr = pr->ndpr_next;
|
||||
}
|
||||
{
|
||||
struct rr_prefix *rpp;
|
||||
|
||||
for (rpp = LIST_FIRST(&rr_prefix); rpp;
|
||||
rpp = LIST_NEXT(rpp, rp_entry)) {
|
||||
if (i >= PRLSTSIZ)
|
||||
break;
|
||||
prl->prefix[i].prefix = rpp->rp_prefix.sin6_addr;
|
||||
prl->prefix[i].raflags = rpp->rp_raf;
|
||||
prl->prefix[i].prefixlen = rpp->rp_plen;
|
||||
prl->prefix[i].vltime = rpp->rp_vltime;
|
||||
prl->prefix[i].pltime = rpp->rp_pltime;
|
||||
prl->prefix[i].if_index = rpp->rp_ifp->if_index;
|
||||
prl->prefix[i].expire = rpp->rp_expire;
|
||||
prl->prefix[i].advrtrs = 0;
|
||||
prl->prefix[i].origin = rpp->rp_origin;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
|
||||
break;
|
||||
|
@ -1358,15 +1329,9 @@ nd6_ioctl(cmd, data, ifp)
|
|||
ND_IFINFO(ifp)->flags = ndi->ndi.flags;
|
||||
break;
|
||||
case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */
|
||||
/* flush default router list */
|
||||
/*
|
||||
* xxx sumikawa: should not delete route if default
|
||||
* route equals to the top of default router list
|
||||
*/
|
||||
bzero(&any, sizeof(any));
|
||||
defrouter_delreq(&any, 0);
|
||||
/* sync kernel routing table with the default router list */
|
||||
defrouter_reset();
|
||||
defrouter_select();
|
||||
/* xxx sumikawa: flush prefix list */
|
||||
break;
|
||||
case SIOCSPFXFLUSH_IN6:
|
||||
{
|
||||
|
@ -1375,9 +1340,24 @@ nd6_ioctl(cmd, data, ifp)
|
|||
|
||||
s = splsoftnet();
|
||||
for (pr = nd_prefix.lh_first; pr; pr = next) {
|
||||
struct in6_ifaddr *ia, *ia_next;
|
||||
|
||||
next = pr->ndpr_next;
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
|
||||
in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
|
||||
continue; /* XXX */
|
||||
|
||||
/* do we really have to remove addresses as well? */
|
||||
for (ia = in6_ifaddr; ia; ia = ia_next) {
|
||||
/* ia might be removed. keep the next ptr. */
|
||||
ia_next = ia->ia_next;
|
||||
|
||||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
|
||||
continue;
|
||||
|
||||
if (ia->ia6_ndpr == pr)
|
||||
in6_purgeaddr(&ia->ia_ifa);
|
||||
}
|
||||
prelist_remove(pr);
|
||||
}
|
||||
splx(s);
|
||||
|
@ -1389,17 +1369,12 @@ nd6_ioctl(cmd, data, ifp)
|
|||
struct nd_defrouter *dr, *next;
|
||||
|
||||
s = splsoftnet();
|
||||
if ((dr = TAILQ_FIRST(&nd_defrouter)) != NULL) {
|
||||
/*
|
||||
* The first entry of the list may be stored in
|
||||
* the routing table, so we'll delete it later.
|
||||
*/
|
||||
for (dr = TAILQ_NEXT(dr, dr_entry); dr; dr = next) {
|
||||
defrouter_reset();
|
||||
for (dr = TAILQ_FIRST(&nd_defrouter); dr; dr = next) {
|
||||
next = TAILQ_NEXT(dr, dr_entry);
|
||||
defrtrlist_del(dr);
|
||||
}
|
||||
defrtrlist_del(TAILQ_FIRST(&nd_defrouter));
|
||||
}
|
||||
defrouter_select();
|
||||
splx(s);
|
||||
break;
|
||||
}
|
||||
|
@ -1421,12 +1396,12 @@ nd6_ioctl(cmd, data, ifp)
|
|||
}
|
||||
|
||||
s = splsoftnet();
|
||||
if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL) {
|
||||
if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL ||
|
||||
(ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) {
|
||||
error = EINVAL;
|
||||
splx(s);
|
||||
break;
|
||||
}
|
||||
ln = (struct llinfo_nd6 *)rt->rt_llinfo;
|
||||
nbi->state = ln->ln_state;
|
||||
nbi->asked = ln->ln_asked;
|
||||
nbi->isrouter = ln->ln_router;
|
||||
|
@ -1550,8 +1525,8 @@ fail:
|
|||
}
|
||||
|
||||
if (!is_newentry) {
|
||||
if ((!olladdr && lladdr) /* (3) */
|
||||
|| (olladdr && lladdr && llchange)) { /* (5) */
|
||||
if ((!olladdr && lladdr) || /* (3) */
|
||||
(olladdr && lladdr && llchange)) { /* (5) */
|
||||
do_update = 1;
|
||||
newstate = ND6_LLINFO_STALE;
|
||||
} else /* (1-2,4) */
|
||||
|
@ -1585,8 +1560,7 @@ fail:
|
|||
* set the 2nd argument as the 1st one.
|
||||
*/
|
||||
nd6_output(ifp, ifp, ln->ln_hold,
|
||||
(struct sockaddr_in6 *)rt_key(rt),
|
||||
rt);
|
||||
(struct sockaddr_in6 *)rt_key(rt), rt);
|
||||
ln->ln_hold = NULL;
|
||||
}
|
||||
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
|
||||
|
@ -1653,8 +1627,8 @@ fail:
|
|||
/*
|
||||
* Mark an entry with lladdr as a router.
|
||||
*/
|
||||
if ((!is_newentry && (olladdr || lladdr)) /* (2-5) */
|
||||
|| (is_newentry && lladdr)) { /* (7) */
|
||||
if ((!is_newentry && (olladdr || lladdr)) || /* (2-5) */
|
||||
(is_newentry && lladdr)) { /* (7) */
|
||||
ln->ln_router = 1;
|
||||
}
|
||||
break;
|
||||
|
@ -1736,8 +1710,8 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
|||
*/
|
||||
if (rt) {
|
||||
if ((rt->rt_flags & RTF_UP) == 0) {
|
||||
if ((rt0 = rt = rtalloc1((struct sockaddr *)dst, 1)) !=
|
||||
NULL)
|
||||
if ((rt0 = rt = rtalloc1((struct sockaddr *)dst,
|
||||
1)) != NULL)
|
||||
{
|
||||
rt->rt_refcnt--;
|
||||
if (rt->rt_ifp != ifp) {
|
||||
|
@ -1755,7 +1729,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
|||
/*
|
||||
* We skip link-layer address resolution and NUD
|
||||
* if the gateway is not a neighbor from ND point
|
||||
* of view, regardless the value of nd_ifinfo.flags.
|
||||
* of view, regardless of the value of nd_ifinfo.flags.
|
||||
* The second condition is a bit tricky; we skip
|
||||
* if the gateway is our own address, which is
|
||||
* sometimes used to install a route to a p2p link.
|
||||
|
@ -1970,3 +1944,193 @@ nd6_storelladdr(ifp, rt, m, dst, desten)
|
|||
bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
nd6_sysctl(name, oldp, oldlenp, newp, newlen)
|
||||
int name;
|
||||
void *oldp;
|
||||
size_t *oldlenp;
|
||||
void *newp;
|
||||
size_t newlen;
|
||||
{
|
||||
size_t ol, l;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
l = 0;
|
||||
|
||||
if (newp)
|
||||
return EPERM;
|
||||
if (oldp && !oldlenp)
|
||||
return EINVAL;
|
||||
ol = oldlenp ? *oldlenp : 0;
|
||||
|
||||
switch (name) {
|
||||
case ICMPV6CTL_ND6_DRLIST:
|
||||
error = fill_drlist(oldp, oldlenp, ol);
|
||||
break;
|
||||
|
||||
case ICMPV6CTL_ND6_PRLIST:
|
||||
error = fill_prlist(oldp, oldlenp, ol);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_drlist(oldp, oldlenp, ol)
|
||||
void *oldp;
|
||||
size_t *oldlenp, ol;
|
||||
{
|
||||
int error = 0, s;
|
||||
struct in6_defrouter *d = NULL, *de = NULL;
|
||||
struct nd_defrouter *dr;
|
||||
size_t l;
|
||||
|
||||
s = splsoftnet();
|
||||
|
||||
if (oldp) {
|
||||
d = (struct in6_defrouter *)oldp;
|
||||
de = (struct in6_defrouter *)((caddr_t)oldp + *oldlenp);
|
||||
}
|
||||
l = 0;
|
||||
|
||||
for (dr = TAILQ_FIRST(&nd_defrouter); dr;
|
||||
dr = TAILQ_NEXT(dr, dr_entry)) {
|
||||
|
||||
if (oldp && d + 1 <= de) {
|
||||
bzero(d, sizeof(*d));
|
||||
d->rtaddr.sin6_family = AF_INET6;
|
||||
d->rtaddr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
d->rtaddr.sin6_addr = dr->rtaddr;
|
||||
in6_recoverscope(&d->rtaddr, &d->rtaddr.sin6_addr,
|
||||
dr->ifp);
|
||||
d->flags = dr->flags;
|
||||
d->rtlifetime = dr->rtlifetime;
|
||||
d->expire = dr->expire;
|
||||
d->if_index = dr->ifp->if_index;
|
||||
}
|
||||
|
||||
l += sizeof(*d);
|
||||
if (d)
|
||||
d++;
|
||||
}
|
||||
|
||||
if (oldp) {
|
||||
*oldlenp = l; /* (caddr_t)d - (caddr_t)oldp */
|
||||
if (l > ol)
|
||||
error = ENOMEM;
|
||||
} else
|
||||
*oldlenp = l;
|
||||
|
||||
splx(s);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
static int
|
||||
fill_prlist(oldp, oldlenp, ol)
|
||||
void *oldp;
|
||||
size_t *oldlenp, ol;
|
||||
{
|
||||
int error = 0, s;
|
||||
struct nd_prefix *pr;
|
||||
struct in6_prefix *p = NULL;
|
||||
struct in6_prefix *pe = NULL;
|
||||
size_t l;
|
||||
|
||||
s = splsoftnet();
|
||||
|
||||
if (oldp) {
|
||||
p = (struct in6_prefix *)oldp;
|
||||
pe = (struct in6_prefix *)((caddr_t)oldp + *oldlenp);
|
||||
}
|
||||
l = 0;
|
||||
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
|
||||
u_short advrtrs;
|
||||
size_t advance;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct sockaddr_in6 *s6;
|
||||
struct nd_pfxrouter *pfr;
|
||||
|
||||
if (oldp && p + 1 <= pe)
|
||||
{
|
||||
bzero(p, sizeof(*p));
|
||||
sin6 = (struct sockaddr_in6 *)(p + 1);
|
||||
|
||||
p->prefix = pr->ndpr_prefix;
|
||||
if (in6_recoverscope(&p->prefix,
|
||||
&p->prefix.sin6_addr, pr->ndpr_ifp) != 0)
|
||||
log(LOG_ERR,
|
||||
"scope error in prefix list (%s)\n",
|
||||
ip6_sprintf(&p->prefix.sin6_addr));
|
||||
p->raflags = pr->ndpr_raf;
|
||||
p->prefixlen = pr->ndpr_plen;
|
||||
p->vltime = pr->ndpr_vltime;
|
||||
p->pltime = pr->ndpr_pltime;
|
||||
p->if_index = pr->ndpr_ifp->if_index;
|
||||
if (pr->ndpr_vltime == ND6_INFINITE_LIFETIME)
|
||||
p->expire = 0;
|
||||
else {
|
||||
time_t maxexpire;
|
||||
|
||||
/* XXX: we assume time_t is signed. */
|
||||
maxexpire = (-1) &
|
||||
~(1 << ((sizeof(maxexpire) * 8) - 1));
|
||||
if (pr->ndpr_vltime <
|
||||
maxexpire - pr->ndpr_lastupdate) {
|
||||
p->expire = pr->ndpr_lastupdate +
|
||||
pr->ndpr_vltime;
|
||||
} else
|
||||
p->expire = maxexpire;
|
||||
}
|
||||
p->refcnt = pr->ndpr_refcnt;
|
||||
p->flags = pr->ndpr_stateflags;
|
||||
p->origin = PR_ORIG_RA;
|
||||
advrtrs = 0;
|
||||
for (pfr = pr->ndpr_advrtrs.lh_first; pfr;
|
||||
pfr = pfr->pfr_next) {
|
||||
if ((void *)&sin6[advrtrs + 1] > (void *)pe) {
|
||||
advrtrs++;
|
||||
continue;
|
||||
}
|
||||
s6 = &sin6[advrtrs];
|
||||
s6->sin6_family = AF_INET6;
|
||||
s6->sin6_len = sizeof(struct sockaddr_in6);
|
||||
s6->sin6_addr = pfr->router->rtaddr;
|
||||
in6_recoverscope(s6, &s6->sin6_addr,
|
||||
pfr->router->ifp);
|
||||
advrtrs++;
|
||||
}
|
||||
p->advrtrs = advrtrs;
|
||||
}
|
||||
else {
|
||||
advrtrs = 0;
|
||||
for (pfr = pr->ndpr_advrtrs.lh_first; pfr;
|
||||
pfr = pfr->pfr_next)
|
||||
advrtrs++;
|
||||
}
|
||||
|
||||
advance = sizeof(*p) + sizeof(*sin6) * advrtrs;
|
||||
l += advance;
|
||||
if (p)
|
||||
p = (struct in6_prefix *)((caddr_t)p + advance);
|
||||
}
|
||||
|
||||
if (oldp) {
|
||||
*oldlenp = l; /* (caddr_t)d - (caddr_t)oldp */
|
||||
if (l > ol)
|
||||
error = ENOMEM;
|
||||
} else
|
||||
*oldlenp = l;
|
||||
|
||||
splx(s);
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $NetBSD: nd6.h,v 1.30 2002/06/07 02:31:04 itojun Exp $ */
|
||||
/* $KAME: nd6.h,v 1.93 2002/06/05 00:56:22 itojun Exp $ */
|
||||
/* $NetBSD: nd6.h,v 1.31 2002/06/08 21:22:34 itojun Exp $ */
|
||||
/* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -93,6 +93,7 @@ struct nd_ifinfo {
|
|||
};
|
||||
|
||||
#define ND6_IFF_PERFORMNUD 0x1
|
||||
#define ND6_IFF_ACCEPT_RTADV 0x2
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define ND_IFINFO(ifp) \
|
||||
|
@ -126,7 +127,16 @@ struct in6_drlist {
|
|||
} defrouter[DRLSTSIZ];
|
||||
};
|
||||
|
||||
struct in6_prlist {
|
||||
struct in6_defrouter {
|
||||
struct sockaddr_in6 rtaddr;
|
||||
u_char flags;
|
||||
u_short rtlifetime;
|
||||
u_long expire;
|
||||
u_short if_index;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct in6_oprlist {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
struct in6_addr prefix;
|
||||
|
@ -141,6 +151,38 @@ struct in6_prlist {
|
|||
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
|
||||
} prefix[PRLSTSIZ];
|
||||
};
|
||||
#endif
|
||||
|
||||
struct in6_prlist {
|
||||
char ifname[IFNAMSIZ];
|
||||
struct {
|
||||
struct in6_addr prefix;
|
||||
struct prf_ra raflags;
|
||||
u_char prefixlen;
|
||||
u_char origin;
|
||||
u_int32_t vltime;
|
||||
u_int32_t pltime;
|
||||
time_t expire;
|
||||
u_short if_index;
|
||||
u_short advrtrs; /* number of advertisement routers */
|
||||
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
|
||||
} prefix[PRLSTSIZ];
|
||||
};
|
||||
|
||||
struct in6_prefix {
|
||||
struct sockaddr_in6 prefix;
|
||||
struct prf_ra raflags;
|
||||
u_char prefixlen;
|
||||
u_char origin;
|
||||
u_int32_t vltime;
|
||||
u_int32_t pltime;
|
||||
time_t expire;
|
||||
u_int32_t flags;
|
||||
int refcnt;
|
||||
u_short if_index;
|
||||
u_short advrtrs; /* number of advertisement routers */
|
||||
/* struct sockaddr_in6 advrtr[] */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct in6_ondireq {
|
||||
|
@ -169,6 +211,10 @@ struct in6_ndifreq {
|
|||
u_long ifindex;
|
||||
};
|
||||
|
||||
/* Prefix status */
|
||||
#define NDPRF_ONLINK 0x1
|
||||
#define NDPRF_DETACHED 0x2
|
||||
#define NDPRF_HOME 0x4
|
||||
|
||||
/* protocol constants */
|
||||
#define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */
|
||||
|
@ -192,10 +238,11 @@ TAILQ_HEAD(nd_drhead, nd_defrouter);
|
|||
struct nd_defrouter {
|
||||
TAILQ_ENTRY(nd_defrouter) dr_entry;
|
||||
struct in6_addr rtaddr;
|
||||
u_char flags;
|
||||
u_char flags; /* flags on RA message */
|
||||
u_short rtlifetime;
|
||||
u_long expire;
|
||||
struct ifnet *ifp;
|
||||
int installed; /* is installed into kernel routing table */
|
||||
};
|
||||
|
||||
struct nd_prefix {
|
||||
|
@ -203,19 +250,20 @@ struct nd_prefix {
|
|||
LIST_ENTRY(nd_prefix) ndpr_entry;
|
||||
struct sockaddr_in6 ndpr_prefix; /* prefix */
|
||||
struct in6_addr ndpr_mask; /* netmask derived from the prefix */
|
||||
struct in6_addr ndpr_addr; /* address that is derived from the prefix */
|
||||
|
||||
u_int32_t ndpr_vltime; /* advertised valid lifetime */
|
||||
u_int32_t ndpr_pltime; /* advertised preferred lifetime */
|
||||
|
||||
time_t ndpr_expire; /* expiration time of the prefix */
|
||||
time_t ndpr_preferred; /* preferred time of the prefix */
|
||||
time_t ndpr_lastupdate; /* reception time of last advertisement */
|
||||
|
||||
struct prf_ra ndpr_flags;
|
||||
u_int32_t ndpr_stateflags; /* actual state flags */
|
||||
/* list of routers that advertise the prefix: */
|
||||
LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs;
|
||||
u_char ndpr_plen;
|
||||
struct ndpr_stateflags {
|
||||
/* if this prefix can be regarded as on-link */
|
||||
u_char onlink : 1;
|
||||
} ndpr_stateflags;
|
||||
int ndpr_refcnt; /* reference couter from addresses */
|
||||
};
|
||||
|
||||
#define ndpr_next ndpr_entry.le_next
|
||||
|
@ -223,15 +271,7 @@ struct nd_prefix {
|
|||
#define ndpr_raf ndpr_flags
|
||||
#define ndpr_raf_onlink ndpr_flags.onlink
|
||||
#define ndpr_raf_auto ndpr_flags.autonomous
|
||||
|
||||
#define ndpr_statef_onlink ndpr_stateflags.onlink
|
||||
#define ndpr_statef_addmark ndpr_stateflags.addmark
|
||||
|
||||
/*
|
||||
* We keep expired prefix for certain amount of time, for validation purposes.
|
||||
* 1800s = MaxRtrAdvInterval
|
||||
*/
|
||||
#define NDPR_KEEP_EXPIRED (1800 * 2)
|
||||
#define ndpr_raf_router ndpr_flags.router
|
||||
|
||||
/*
|
||||
* Message format for use in obtaining information about prefixes
|
||||
|
@ -259,9 +299,6 @@ struct inet6_ndpr_msghdr {
|
|||
#define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid
|
||||
#define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd
|
||||
|
||||
#define ifpr2ndpr(ifpr) ((struct nd_prefix *)(ifpr))
|
||||
#define ndpr2ifpr(ndpr) ((struct ifprefix *)(ndpr))
|
||||
|
||||
struct nd_pfxrouter {
|
||||
LIST_ENTRY(nd_pfxrouter) pfr_entry;
|
||||
#define pfr_next pfr_entry.le_next
|
||||
|
@ -332,7 +369,6 @@ void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
|
|||
int nd6_resolve __P((struct ifnet *, struct rtentry *,
|
||||
struct mbuf *, struct sockaddr *, u_char *));
|
||||
void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
|
||||
void nd6_p2p_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
|
||||
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
|
||||
struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
|
||||
char *, int, int, int));
|
||||
|
@ -340,6 +376,7 @@ int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
|
|||
struct sockaddr_in6 *, struct rtentry *));
|
||||
int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *,
|
||||
struct sockaddr *, u_char *));
|
||||
int nd6_sysctl __P((int, void *, size_t *, void *, size_t));
|
||||
int nd6_need_cache __P((struct ifnet *));
|
||||
|
||||
/* nd6_nbr.c */
|
||||
|
@ -359,15 +396,19 @@ void nd6_rs_input __P((struct mbuf *, int, int));
|
|||
void nd6_ra_input __P((struct mbuf *, int, int));
|
||||
void prelist_del __P((struct nd_prefix *));
|
||||
void defrouter_addreq __P((struct nd_defrouter *));
|
||||
void defrouter_delreq __P((struct nd_defrouter *, int));
|
||||
void defrouter_reset __P((void));
|
||||
void defrouter_select __P((void));
|
||||
void defrtrlist_del __P((struct nd_defrouter *));
|
||||
void prelist_remove __P((struct nd_prefix *));
|
||||
int prelist_update __P((struct nd_prefix *, struct nd_defrouter *,
|
||||
struct mbuf *));
|
||||
int nd6_prelist_add __P((struct nd_prefix *, struct nd_defrouter *,
|
||||
struct nd_prefix **));
|
||||
int nd6_prefix_onlink __P((struct nd_prefix *));
|
||||
int nd6_prefix_offlink __P((struct nd_prefix *));
|
||||
void pfxlist_onlink_check __P((void));
|
||||
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *,
|
||||
struct ifnet *));
|
||||
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct ifnet *));
|
||||
struct nd_prefix *nd6_prefix_lookup __P((struct nd_prefix *));
|
||||
int in6_ifdel __P((struct ifnet *, struct in6_addr *));
|
||||
int in6_init_prefix_ltimes __P((struct nd_prefix *ndpr));
|
||||
void rt6_flush __P((struct in6_addr *, struct ifnet *));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6_nbr.c,v 1.38 2002/06/07 07:38:51 itojun Exp $ */
|
||||
/* $NetBSD: nd6_nbr.c,v 1.39 2002/06/08 21:22:34 itojun Exp $ */
|
||||
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.38 2002/06/07 07:38:51 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.39 2002/06/08 21:22:34 itojun Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -105,6 +105,7 @@ nd6_ns_input(m, off, icmp6len)
|
|||
struct ifaddr *ifa;
|
||||
int lladdrlen = 0;
|
||||
int anycast = 0, proxy = 0, tentative = 0;
|
||||
int router = ip6_forwarding;
|
||||
int tlladdr;
|
||||
union nd_opts ndopts;
|
||||
struct sockaddr_dl *proxydl = NULL;
|
||||
|
@ -132,11 +133,11 @@ nd6_ns_input(m, off, icmp6len)
|
|||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
|
||||
/* dst has to be solicited node multicast address. */
|
||||
if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL
|
||||
/* don't check ifindex portion */
|
||||
&& daddr6.s6_addr32[1] == 0
|
||||
&& daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE
|
||||
&& daddr6.s6_addr8[12] == 0xff) {
|
||||
if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
|
||||
daddr6.s6_addr32[1] == 0 &&
|
||||
daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
|
||||
daddr6.s6_addr8[12] == 0xff) {
|
||||
; /* good */
|
||||
} else {
|
||||
nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
|
||||
|
@ -224,6 +225,7 @@ nd6_ns_input(m, off, icmp6len)
|
|||
if (ifa) {
|
||||
proxy = 1;
|
||||
proxydl = SDL(rt->rt_gateway);
|
||||
router = 0; /* XXX */
|
||||
}
|
||||
}
|
||||
if (rt)
|
||||
|
@ -244,16 +246,14 @@ nd6_ns_input(m, off, icmp6len)
|
|||
goto freeit;
|
||||
|
||||
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
|
||||
nd6log((LOG_INFO,
|
||||
"nd6_ns_input: lladdrlen mismatch for %s "
|
||||
nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
|
||||
"(if %d, NS packet %d)\n",
|
||||
ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
|
||||
nd6log((LOG_INFO,
|
||||
"nd6_ns_input: duplicate IP6 address %s\n",
|
||||
nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
|
||||
ip6_sprintf(&saddr6)));
|
||||
goto freeit;
|
||||
}
|
||||
|
@ -296,9 +296,8 @@ nd6_ns_input(m, off, icmp6len)
|
|||
saddr6 = in6addr_linklocal_allnodes;
|
||||
saddr6.s6_addr16[1] = htons(ifp->if_index);
|
||||
nd6_na_output(ifp, &saddr6, &taddr6,
|
||||
((anycast || proxy || !tlladdr)
|
||||
? 0 : ND_NA_FLAG_OVERRIDE)
|
||||
| (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0),
|
||||
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
|
||||
(router ? ND_NA_FLAG_ROUTER : 0),
|
||||
tlladdr, (struct sockaddr *)proxydl);
|
||||
goto freeit;
|
||||
}
|
||||
|
@ -306,9 +305,8 @@ nd6_ns_input(m, off, icmp6len)
|
|||
nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0);
|
||||
|
||||
nd6_na_output(ifp, &saddr6, &taddr6,
|
||||
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE)
|
||||
| (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0)
|
||||
| ND_NA_FLAG_SOLICITED,
|
||||
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
|
||||
(router ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
|
||||
tlladdr, (struct sockaddr *)proxydl);
|
||||
freeit:
|
||||
m_freem(m);
|
||||
|
@ -341,11 +339,14 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
|
|||
struct mbuf *m;
|
||||
struct ip6_hdr *ip6;
|
||||
struct nd_neighbor_solicit *nd_ns;
|
||||
struct in6_ifaddr *ia = NULL;
|
||||
struct sockaddr_in6 src_sa, dst_sa;
|
||||
struct ip6_moptions im6o;
|
||||
int icmp6len;
|
||||
int maxlen;
|
||||
caddr_t mac;
|
||||
struct route_in6 ro;
|
||||
|
||||
bzero(&ro, sizeof(ro));
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(taddr6))
|
||||
return;
|
||||
|
@ -393,16 +394,22 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
|
|||
/* ip6->ip6_plen will be set later */
|
||||
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip6->ip6_hlim = 255;
|
||||
/* determine the source and destination addresses */
|
||||
bzero(&src_sa, sizeof(src_sa));
|
||||
bzero(&dst_sa, sizeof(dst_sa));
|
||||
src_sa.sin6_family = dst_sa.sin6_family = AF_INET6;
|
||||
src_sa.sin6_len = dst_sa.sin6_len = sizeof(struct sockaddr_in6);
|
||||
if (daddr6)
|
||||
ip6->ip6_dst = *daddr6;
|
||||
dst_sa.sin6_addr = *daddr6;
|
||||
else {
|
||||
ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
|
||||
ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
|
||||
ip6->ip6_dst.s6_addr32[1] = 0;
|
||||
ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
|
||||
ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3];
|
||||
ip6->ip6_dst.s6_addr8[12] = 0xff;
|
||||
dst_sa.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
|
||||
dst_sa.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
dst_sa.sin6_addr.s6_addr32[1] = 0;
|
||||
dst_sa.sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
|
||||
dst_sa.sin6_addr.s6_addr32[3] = taddr6->s6_addr32[3];
|
||||
dst_sa.sin6_addr.s6_addr8[12] = 0xff;
|
||||
}
|
||||
ip6->ip6_dst = dst_sa.sin6_addr;
|
||||
if (!dad) {
|
||||
/*
|
||||
* RFC2461 7.2.2:
|
||||
|
@ -417,7 +424,7 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
|
|||
* (saddr6), if:
|
||||
* - saddr6 is given from the caller (by giving "ln"), and
|
||||
* - saddr6 belongs to the outgoing interface.
|
||||
* Otherwise, we perform a scope-wise match.
|
||||
* Otherwise, we perform the source address selection as usual.
|
||||
*/
|
||||
struct ip6_hdr *hip6; /* hold ip6 */
|
||||
struct in6_addr *saddr6;
|
||||
|
@ -432,22 +439,34 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
|
|||
} else
|
||||
saddr6 = NULL;
|
||||
if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6))
|
||||
bcopy(saddr6, &ip6->ip6_src, sizeof(*saddr6));
|
||||
src_sa.sin6_addr = *saddr6;
|
||||
else {
|
||||
ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
|
||||
if (ia == NULL) {
|
||||
m_freem(m);
|
||||
return;
|
||||
struct in6_addr *src0;
|
||||
int error;
|
||||
|
||||
bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
|
||||
src0 = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL,
|
||||
&error);
|
||||
if (src0 == NULL) {
|
||||
nd6log((LOG_DEBUG,
|
||||
"nd6_ns_output: source can't be "
|
||||
"determined: dst=%s, error=%d\n",
|
||||
ip6_sprintf(&dst_sa.sin6_addr), error));
|
||||
goto bad;
|
||||
}
|
||||
ip6->ip6_src = ia->ia_addr.sin6_addr;
|
||||
src_sa.sin6_addr = *src0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Source address for DAD packet must always be IPv6
|
||||
* unspecified address. (0::0)
|
||||
* We actually don't have to 0-clear the address (we did it
|
||||
* above), but we do so here explicitly to make the intention
|
||||
* clearer.
|
||||
*/
|
||||
bzero(&ip6->ip6_src, sizeof(ip6->ip6_src));
|
||||
bzero(&src_sa.sin6_addr, sizeof(src_sa.sin6_addr));
|
||||
}
|
||||
ip6->ip6_src = src_sa.sin6_addr;
|
||||
nd_ns = (struct nd_neighbor_solicit *)(ip6 + 1);
|
||||
nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
|
||||
nd_ns->nd_ns_code = 0;
|
||||
|
@ -486,31 +505,36 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
|
|||
|
||||
ip6->ip6_plen = htons((u_short)icmp6len);
|
||||
nd_ns->nd_ns_cksum = 0;
|
||||
nd_ns->nd_ns_cksum
|
||||
= in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
|
||||
nd_ns->nd_ns_cksum =
|
||||
in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
|
||||
|
||||
#ifdef IPSEC
|
||||
/* Don't lookup socket */
|
||||
(void)ipsec_setsocket(m, NULL);
|
||||
#endif
|
||||
ip6_output(m, NULL, NULL, 0, &im6o, NULL);
|
||||
ip6_output(m, NULL, &ro, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL);
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_msg);
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
|
||||
icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
|
||||
|
||||
if (ro.ro_rt) { /* we don't cache this route. */
|
||||
RTFREE(ro.ro_rt);
|
||||
}
|
||||
return;
|
||||
|
||||
#if 0
|
||||
bad:
|
||||
if (ro.ro_rt) {
|
||||
RTFREE(ro.ro_rt);
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Neighbor advertisement input handling.
|
||||
*
|
||||
* Based on RFC 2461
|
||||
long time_second = time.tv_sec;
|
||||
* Based on RFC 2462 (duplicated address detection)
|
||||
*
|
||||
* the following items are not implemented yet:
|
||||
|
@ -576,8 +600,7 @@ nd6_na_input(m, off, icmp6len)
|
|||
ip6_sprintf(&taddr6)));
|
||||
goto bad;
|
||||
}
|
||||
if (IN6_IS_ADDR_MULTICAST(&daddr6))
|
||||
if (is_solicited) {
|
||||
if (is_solicited && IN6_IS_ADDR_MULTICAST(&daddr6)) {
|
||||
nd6log((LOG_ERR,
|
||||
"nd6_na_input: a solicited adv is multicasted\n"));
|
||||
goto bad;
|
||||
|
@ -623,15 +646,15 @@ nd6_na_input(m, off, icmp6len)
|
|||
}
|
||||
|
||||
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
|
||||
nd6log((LOG_INFO,
|
||||
"nd6_na_input: lladdrlen mismatch for %s "
|
||||
"(if %d, NA packet %d)\n",
|
||||
ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
|
||||
nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
|
||||
"(if %d, NA packet %d)\n", ip6_sprintf(&taddr6),
|
||||
ifp->if_addrlen, lladdrlen - 2));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no neighbor cache entry is found, NA SHOULD silently be discarded.
|
||||
* If no neighbor cache entry is found, NA SHOULD silently be
|
||||
* discarded.
|
||||
*/
|
||||
rt = nd6_lookup(&taddr6, 0, ifp);
|
||||
if ((rt == NULL) ||
|
||||
|
@ -788,7 +811,7 @@ nd6_na_input(m, off, icmp6len)
|
|||
ln->ln_asked = 0;
|
||||
if (ln->ln_hold) {
|
||||
/*
|
||||
* we assume ifp is not a p2p here, so just set the 2nd
|
||||
* we assume ifp is not a loopback here, so just set the 2nd
|
||||
* argument as the 1st one.
|
||||
*/
|
||||
nd6_output(ifp, ifp, ln->ln_hold,
|
||||
|
@ -825,11 +848,15 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
|
|||
struct mbuf *m;
|
||||
struct ip6_hdr *ip6;
|
||||
struct nd_neighbor_advert *nd_na;
|
||||
struct in6_ifaddr *ia = NULL;
|
||||
struct ip6_moptions im6o;
|
||||
int icmp6len;
|
||||
int maxlen;
|
||||
struct sockaddr_in6 src_sa, dst_sa;
|
||||
struct in6_addr *src0;
|
||||
int icmp6len, maxlen, error;
|
||||
caddr_t mac;
|
||||
struct route_in6 ro;
|
||||
|
||||
mac = NULL;
|
||||
bzero(&ro, sizeof(ro));
|
||||
|
||||
/* estimate the size of message */
|
||||
maxlen = sizeof(*ip6) + sizeof(*nd_na);
|
||||
|
@ -873,26 +900,36 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
|
|||
ip6->ip6_vfc |= IPV6_VERSION;
|
||||
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip6->ip6_hlim = 255;
|
||||
bzero(&src_sa, sizeof(src_sa));
|
||||
bzero(&dst_sa, sizeof(dst_sa));
|
||||
src_sa.sin6_len = dst_sa.sin6_len = sizeof(struct sockaddr_in6);
|
||||
src_sa.sin6_family = dst_sa.sin6_family = AF_INET6;
|
||||
dst_sa.sin6_addr = *daddr6;
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
|
||||
/* reply to DAD */
|
||||
ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
|
||||
ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index);
|
||||
ip6->ip6_dst.s6_addr32[1] = 0;
|
||||
ip6->ip6_dst.s6_addr32[2] = 0;
|
||||
ip6->ip6_dst.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
|
||||
dst_sa.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
|
||||
dst_sa.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
|
||||
dst_sa.sin6_addr.s6_addr32[1] = 0;
|
||||
dst_sa.sin6_addr.s6_addr32[2] = 0;
|
||||
dst_sa.sin6_addr.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
|
||||
|
||||
flags &= ~ND_NA_FLAG_SOLICITED;
|
||||
} else
|
||||
ip6->ip6_dst = *daddr6;
|
||||
}
|
||||
ip6->ip6_dst = dst_sa.sin6_addr;
|
||||
|
||||
/*
|
||||
* Select a source whose scope is the same as that of the dest.
|
||||
*/
|
||||
ia = in6_ifawithifp(ifp, &ip6->ip6_dst);
|
||||
if (ia == NULL) {
|
||||
m_freem(m);
|
||||
return;
|
||||
bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
|
||||
src0 = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &error);
|
||||
if (src0 == NULL) {
|
||||
nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
|
||||
"determined: dst=%s, error=%d\n",
|
||||
ip6_sprintf(&dst_sa.sin6_addr), error));
|
||||
goto bad;
|
||||
}
|
||||
ip6->ip6_src = ia->ia_addr.sin6_addr;
|
||||
src_sa.sin6_addr = *src0;
|
||||
ip6->ip6_src = src_sa.sin6_addr;
|
||||
nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
|
||||
nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
|
||||
nd_na->nd_na_code = 0;
|
||||
|
@ -907,7 +944,6 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
|
|||
* target lladdr option SHOULD NOT be included.
|
||||
*/
|
||||
if (tlladdr) {
|
||||
mac = NULL;
|
||||
/*
|
||||
* sdl0 != NULL indicates proxy NA. If we do proxy, use
|
||||
* lladdr in sdl0. If we are not proxying (sending NA for
|
||||
|
@ -954,6 +990,18 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
|
|||
icmp6_ifstat_inc(ifp, ifs6_out_msg);
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
|
||||
icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
|
||||
|
||||
if (ro.ro_rt) { /* we don't cache this route. */
|
||||
RTFREE(ro.ro_rt);
|
||||
}
|
||||
return;
|
||||
|
||||
bad:
|
||||
if (ro.ro_rt) {
|
||||
RTFREE(ro.ro_rt);
|
||||
}
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
||||
caddr_t
|
||||
|
@ -965,6 +1013,9 @@ nd6_ifptomac(ifp)
|
|||
case IFT_ETHER:
|
||||
case IFT_FDDI:
|
||||
case IFT_IEEE1394:
|
||||
case IFT_PROPVIRTUAL:
|
||||
case IFT_L2VLAN:
|
||||
case IFT_IEEE80211:
|
||||
return LLADDR(ifp->if_sadl);
|
||||
break;
|
||||
default:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue