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:
itojun 2002-06-08 21:22:29 +00:00
parent 61ef51d198
commit 6d8d0d63d8
19 changed files with 2898 additions and 3031 deletions

View File

@ -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 # @(#)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_gif.c gif & inet6
file netinet6/in6_ifattach.c inet6 file netinet6/in6_ifattach.c inet6
file netinet6/in6_pcb.c inet6 file netinet6/in6_pcb.c inet6
file netinet6/in6_prefix.c inet6
file netinet6/in6_proto.c inet6 file netinet6/in6_proto.c inet6
file netinet6/in6_src.c inet6 file netinet6/in6_src.c inet6
file netinet6/ip6_forward.c inet6 file netinet6/ip6_forward.c inet6

View File

@ -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 $ */ /* $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_HIWAT 16
#define ICMPV6CTL_MTUDISC_LOWAT 17 #define ICMPV6CTL_MTUDISC_LOWAT 17
#define ICMPV6CTL_ND6_DEBUG 18 #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 { \ #define ICMPV6CTL_NAMES { \
{ 0, 0 }, \ { 0, 0 }, \
@ -592,6 +594,8 @@ struct icmp6stat {
{ "mtudisc_hiwat", CTLTYPE_INT }, \ { "mtudisc_hiwat", CTLTYPE_INT }, \
{ "mtudisc_lowat", CTLTYPE_INT }, \ { "mtudisc_lowat", CTLTYPE_INT }, \
{ "nd6_debug", CTLTYPE_INT }, \ { "nd6_debug", CTLTYPE_INT }, \
{ 0, 0 }, \
{ 0, 0 }, \
} }
#define RTF_PROBEMTU RTF_PROTO1 #define RTF_PROBEMTU RTF_PROTO1

File diff suppressed because it is too large Load Diff

View File

@ -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 $ */ /* $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) \ #define IN6_IS_SCOPE_LINKLOCAL(a) \
((IN6_IS_ADDR_LINKLOCAL(a)) || \ ((IN6_IS_ADDR_LINKLOCAL(a)) || \
(IN6_IS_ADDR_MC_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 #endif
/* /*
@ -616,7 +625,7 @@ in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst,
if (!IN6_IS_SCOPE_LINKLOCAL(src)) if (!IN6_IS_SCOPE_LINKLOCAL(src))
sum += w[1]; sum += w[1];
sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5]; sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
sum += w[6]; sum += w[7]; sum += w[6]; sum += w[7];
/*LINTED*/ /*LINTED*/
w = (const u_int16_t *) dst; w = (const u_int16_t *) dst;

View File

@ -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 $ */ /* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
/* /*
@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #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/param.h>
#include <sys/systm.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; 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_rand_ifid __P((struct ifnet *, struct in6_addr *));
static int get_hw_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 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_linklocal __P((struct ifnet *, struct ifnet *));
static int in6_ifattach_loopback __P((struct ifnet *)); static int in6_ifattach_loopback __P((struct ifnet *));
@ -156,17 +157,25 @@ found:
addr = LLADDR(sdl); addr = LLADDR(sdl);
addrlen = sdl->sdl_alen; 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 */ /* get EUI64 */
switch (ifp->if_type) { switch (ifp->if_type) {
/* IEEE802/EUI64 cases - what others? */
case IFT_ETHER: case IFT_ETHER:
case IFT_FDDI: case IFT_FDDI:
case IFT_ATM: case IFT_ATM:
case IFT_IEEE1394: case IFT_IEEE1394:
/* IEEE802/EUI64 cases - what others? */ case IFT_IEEE80211:
/* IEEE1394 uses 16byte length address starting with EUI64 */
if (addrlen > 8)
addrlen = 8;
/* look at IEEE802/EUI64 only */ /* look at IEEE802/EUI64 only */
if (addrlen != 8 && addrlen != 6) if (addrlen != 8 && addrlen != 6)
return -1; return -1;
@ -313,191 +322,135 @@ success:
return 0; 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 static int
in6_ifattach_linklocal(ifp, altifp) in6_ifattach_linklocal(ifp, altifp)
struct ifnet *ifp; struct ifnet *ifp;
struct ifnet *altifp; /*secondary EUI64 source*/ struct ifnet *altifp; /*secondary EUI64 source*/
{ {
struct in6_ifaddr *ia; 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(&ifra, sizeof(ifra));
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(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); /*
ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); * in6_update_ifa() does not use ifra_name, but we accurately set it
ia->ia_prefixmask.sin6_family = AF_INET6; * for safety.
ia->ia_prefixmask.sin6_addr = in6mask64; */
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
/* just in case */ ifra.ifra_addr.sin6_family = AF_INET6;
bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr)); ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
ia->ia_dstaddr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
bzero(&ia->ia_addr, sizeof(ia->ia_addr)); if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
ia->ia_addr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
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);
} else { } 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, nd6log((LOG_ERR,
"%s: no ifid available\n", if_name(ifp))); "%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 */ * Do not let in6_update_ifa() do DAD, since we need a random delay
return -1; * 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; return 0;
@ -507,52 +460,109 @@ static int
in6_ifattach_loopback(ifp) in6_ifattach_loopback(ifp)
struct ifnet *ifp; /* must be IFT_LOOP */ 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); strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
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;
bzero(&ia->ia_prefixmask, sizeof(ia->ia_prefixmask)); ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_prefixmask.sin6_family = AF_INET6;
ia->ia_prefixmask.sin6_family = AF_INET6; ifra.ifra_prefixmask.sin6_addr = in6mask128;
ia->ia_prefixmask.sin6_addr = in6mask128;
/* /*
* Always initialize ia_dstaddr (= broadcast address) to loopback * Always initialize ia_dstaddr (= broadcast address) to loopback
* address, to make getifaddr happier. * address. Follows IPv4 practice - see in_ifinit().
*
* 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.
*/ */
bzero(&ia->ia_dstaddr, sizeof(ia->ia_dstaddr)); ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_dstaddr.sin6_family = AF_INET6;
ia->ia_dstaddr.sin6_family = AF_INET6; ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
ia->ia_dstaddr.sin6_addr = in6addr_loopback;
bzero(&ia->ia_addr, sizeof(ia->ia_addr)); ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_addr.sin6_family = AF_INET6;
ia->ia_addr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_addr = in6addr_loopback;
ia->ia_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) { /* we don't need to perform DAD on loopback interfaces. */
/* ia will be freed on failure */ ifra.ifra_flags |= IN6_IFF_NODAD;
return -1;
/*
* 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; 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, * XXX multiple loopback interface needs more care. for instance,
* nodelocal address needs to be configured onto only one of them. * nodelocal address needs to be configured onto only one of them.
@ -563,10 +573,6 @@ in6_ifattach(ifp, altifp)
struct ifnet *ifp; struct ifnet *ifp;
struct ifnet *altifp; /* secondary EUI64 source */ 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_ifaddr *ia;
struct in6_addr in6; struct in6_addr in6;
@ -616,125 +622,27 @@ in6_ifattach(ifp, altifp)
} }
/* /*
* assign link-local address, if there's none * assign loopback address for loopback interface.
* XXX multiple loopback interface case.
*/ */
ia = in6ifa_ifpforlinklocal(ifp, 0); if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
if (ia == NULL) { in6 = in6addr_loopback;
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
*/
in6 = in6addr_loopback;
if (ifp->if_flags & IFF_LOOPBACK) {
if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) { if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
if (in6_ifattach_loopback(ifp) != 0) if (in6_ifattach_loopback(ifp) != 0)
return; 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) { if (ip6_auto_linklocal) {
int error; /* not used */ ia = in6ifa_ifpforlinklocal(ifp, 0);
struct in6_multi *in6m; if (ia == NULL) {
if (in6_ifattach_linklocal(ifp, altifp) == 0) {
/* Restore saved multicast addresses (if any). */ /* linklocal address assigned */
in6_restoremkludge(ia, ifp); } else {
/* failed to assign linklocal address. bark? */
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));
}
} }
} }
} }
@ -754,9 +662,7 @@ in6_ifdetach(ifp)
struct rtentry *rt; struct rtentry *rt;
short rtflags; short rtflags;
struct sockaddr_in6 sin6; struct sockaddr_in6 sin6;
struct in6_multi_mship *imm;
/* nuke prefix list. this may try to remove some of ifaddrs as well */
in6_purgeprefix(ifp);
/* remove neighbor management table */ /* remove neighbor management table */
nd6_purge(ifp); nd6_purge(ifp);
@ -767,7 +673,7 @@ in6_ifdetach(ifp)
next = ifa->ifa_list.tqe_next; next = ifa->ifa_list.tqe_next;
if (ifa->ifa_addr->sa_family != AF_INET6) if (ifa->ifa_addr->sa_family != AF_INET6)
continue; continue;
in6_purgeaddr(ifa, ifp); in6_purgeaddr(ifa);
} }
/* undo everything done by in6_ifattach(), just in case */ /* undo everything done by in6_ifattach(), just in case */
@ -783,9 +689,17 @@ in6_ifdetach(ifp)
ia = (struct in6_ifaddr *)ifa; 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 */ /* remove from the routing table */
if ((ia->ia_flags & IFA_ROUTE) if ((ia->ia_flags & IFA_ROUTE) &&
&& (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) { (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0))) {
rtflags = rt->rt_flags; rtflags = rt->rt_flags;
rtfree(rt); rtfree(rt);
rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr, rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr,
@ -808,7 +722,7 @@ in6_ifdetach(ifp)
if (ia->ia_next) if (ia->ia_next)
ia->ia_next = oia->ia_next; ia->ia_next = oia->ia_next;
else { else {
nd6log((LOG_ERR, nd6log((LOG_ERR,
"%s: didn't unlink in6ifaddr from list\n", "%s: didn't unlink in6ifaddr from list\n",
if_name(ifp))); if_name(ifp)));
} }
@ -839,7 +753,7 @@ in6_ifdetach(ifp)
rt = rtalloc1((struct sockaddr *)&sin6, 0); rt = rtalloc1((struct sockaddr *)&sin6, 0);
if (rt && rt->rt_ifp == ifp) { if (rt && rt->rt_ifp == ifp) {
rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt),
rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0);
rtfree(rt); rtfree(rt);
} }
} }

View File

@ -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 $ */ /* $KAME: in6_ifattach.h,v 1.8 2000/04/12 03:51:30 itojun Exp $ */
/* /*
@ -36,6 +36,7 @@
#ifdef _KERNEL #ifdef _KERNEL
void in6_ifattach __P((struct ifnet *, struct ifnet *)); void in6_ifattach __P((struct ifnet *, struct ifnet *));
void in6_ifdetach __P((struct ifnet *)); void in6_ifdetach __P((struct ifnet *));
int in6_nigroup(struct ifnet *, const char *, int, struct sockaddr_in6 *);
#endif /* _KERNEL */ #endif /* _KERNEL */
#endif /* _NETINET6_IN6_IFATTACH_H_ */ #endif /* _NETINET6_IN6_IFATTACH_H_ */

View File

@ -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 $ */ /* $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 *)); void in6_setsockaddr __P((struct in6pcb *, struct mbuf *));
/* in in6_src.c */ /* 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_selecthlim __P((struct in6pcb *, struct ifnet *));
int in6_pcbsetport __P((struct in6_addr *, struct in6pcb *)); int in6_pcbsetport __P((struct in6_addr *, struct in6pcb *));

File diff suppressed because it is too large Load Diff

View File

@ -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));

View File

@ -1,5 +1,5 @@
/* $NetBSD: in6_var.h,v 1.31 2002/06/08 00:07:00 itojun Exp $ */ /* $NetBSD: in6_var.h,v 1.32 2002/06/08 21:22:32 itojun Exp $ */
/* $KAME: in6_var.h,v 1.53 2001/02/10 02:44:27 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. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -111,8 +111,17 @@ struct in6_ifaddr {
/* list of multicast addresses */ /* list of multicast addresses */
int ia6_flags; int ia6_flags;
struct in6_addrlifetime ia6_lifetime; /* NULL = infty */ struct in6_addrlifetime ia6_lifetime;
struct ifprefix *ia6_ifpr; /* back pointer to ifprefix */ 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 { struct prf_ra {
u_char onlink : 1; u_char onlink : 1;
u_char autonomous : 1; u_char autonomous : 1;
u_char reserved : 6; u_char router : 1;
u_char reserved : 5;
} prf_ra; } prf_ra;
u_char prf_reserved1; u_char prf_reserved1;
u_short prf_reserved2; 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_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr)
#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->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 #ifdef _KERNEL
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \ #define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \ (((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 SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq)
#define SIOCGDRLST_IN6 _IOWR('i', 74, struct in6_drlist) #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 #ifdef _KERNEL
#define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq) #define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq)
#endif #endif
@ -426,6 +434,10 @@ struct in6_rrenumreq {
#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */ #define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */
#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */ #define IN6_IFF_DETACHED 0x08 /* may be detached from the link */
#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */ #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 */ /* do not input/output */
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED) #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 *, struct in6_multi_mship *in6_joingroup __P((struct ifnet *, struct in6_addr *,
int *)); int *));
int in6_leavegroup __P((struct in6_multi_mship *)); int in6_leavegroup __P((struct in6_multi_mship *));
void in6_ifscrub __P((struct ifnet *, struct in6_ifaddr *));
int in6_ifindex2scopeid __P((int)); 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 *, int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
struct proc *)); 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 *)); int in6if_do_dad __P((struct ifnet *));
void in6_purgeif __P((struct ifnet *)); void in6_purgeif __P((struct ifnet *));
void in6_savemkludge __P((struct in6_ifaddr *)); 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_matchlen __P((struct in6_addr *, struct in6_addr *));
int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int)); int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int));
void in6_prefixlen2mask __P((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 *)); void in6_purgeprefix __P((struct ifnet *));
int in6_is_addr_deprecated __P((struct sockaddr_in6 *));
struct in6pcb; struct in6pcb;
int in6_embedscope __P((struct in6_addr *, const struct sockaddr_in6 *, int in6_embedscope __P((struct in6_addr *, const struct sockaddr_in6 *,
struct in6pcb *, struct ifnet **)); struct in6pcb *, struct ifnet **));

View File

@ -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 $ */ /* $KAME: ip6_forward.c,v 1.74 2001/06/12 23:54:55 itojun Exp $ */
/* /*
@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #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_ipsec.h"
#include "opt_pfil_hooks.h" #include "opt_pfil_hooks.h"
@ -411,7 +411,7 @@ ip6_forward(m, srcrt)
} }
m_freem(m); m_freem(m);
return; return;
} }
if (rt->rt_flags & RTF_GATEWAY) if (rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in6 *)rt->rt_gateway; dst = (struct sockaddr_in6 *)rt->rt_gateway;
@ -528,12 +528,10 @@ ip6_forward(m, srcrt)
return; return;
switch (error) { switch (error) {
case 0: case 0:
#if 1
if (type == ND_REDIRECT) { if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt); icmp6_redirect_output(mcopy, rt);
return; return;
} }
#endif
goto freecopy; goto freecopy;
case EMSGSIZE: case EMSGSIZE:

View File

@ -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 $ */ /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/* /*
@ -66,7 +66,7 @@
*/ */
#include <sys/cdefs.h> #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_inet.h"
#include "opt_ipsec.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 <netinet/icmp6.h>
#include <netinet6/in6_ifattach.h> #include <netinet6/in6_ifattach.h>
#include <netinet6/nd6.h> #include <netinet6/nd6.h>
#include <netinet6/in6_prefix.h>
#ifdef IPSEC #ifdef IPSEC
#include <netinet6/ipsec.h> #include <netinet6/ipsec.h>
@ -193,18 +192,10 @@ static void
ip6_init2(dummy) ip6_init2(dummy)
void *dummy; void *dummy;
{ {
/*
* to route local address of p2p link to loopback,
* assign loopback address first.
*/
in6_ifattach(&loif[0], NULL);
/* nd6_timer_init */ /* nd6_timer_init */
callout_init(&nd6_timer_ch); callout_init(&nd6_timer_ch);
callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL); 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)) { if (m->m_len < sizeof(struct ip6_hdr)) {
struct ifnet *inifp; struct ifnet *inifp;
inifp = m->m_pkthdr.rcvif; 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++; ip6stat.ip6s_toosmall++;
in6_ifstat_inc(inifp, ifs6_in_hdrerr); in6_ifstat_inc(inifp, ifs6_in_hdrerr);
return; return;
@ -337,6 +328,9 @@ ip6_input(m)
*/ */
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
/*
* XXX: "badscope" is not very suitable for a multicast source.
*/
ip6stat.ip6s_badscope++; ip6stat.ip6s_badscope++;
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
goto bad; goto bad;
@ -460,7 +454,7 @@ ip6_input(m)
* Unicast check * Unicast check
*/ */
if (ip6_forward_rt.ro_rt != NULL && if (ip6_forward_rt.ro_rt != NULL &&
(ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 && (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
&((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr)) &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
ip6stat.ip6s_forward_cachehit++; ip6stat.ip6s_forward_cachehit++;
@ -497,6 +491,7 @@ ip6_input(m)
if (ip6_forward_rt.ro_rt && if (ip6_forward_rt.ro_rt &&
(ip6_forward_rt.ro_rt->rt_flags & (ip6_forward_rt.ro_rt->rt_flags &
(RTF_HOST|RTF_GATEWAY)) == RTF_HOST && (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
!(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
#if 0 #if 0
/* /*
* The check below is redundant since the comparison of * The check below is redundant since the comparison of
@ -504,7 +499,7 @@ ip6_input(m)
* already done through looking up the routing table. * already done through looking up the routing table.
*/ */
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
&rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) && &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
#endif #endif
ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) { ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
struct in6_ifaddr *ia6 = struct in6_ifaddr *ia6 =
@ -532,7 +527,7 @@ ip6_input(m)
} }
/* /*
* FAITH(Firewall Aided Internet Translator) * FAITH (Firewall Aided Internet Translator)
*/ */
#if defined(NFAITH) && 0 < NFAITH #if defined(NFAITH) && 0 < NFAITH
if (ip6_keepfaith) { if (ip6_keepfaith) {
@ -609,7 +604,7 @@ ip6_input(m)
/* /*
* Note that if a valid jumbo payload option is * Note that if a valid jumbo payload option is
* contained, ip6_hoptops_input() must set a valid * contained, ip6_hoptops_input() must set a valid
* (non-zero) payload length to the variable plen. * (non-zero) payload length to the variable plen.
*/ */
ip6stat.ip6s_badoptions++; ip6stat.ip6s_badoptions++;
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
@ -812,6 +807,10 @@ ip6_hopopts_input(plenp, rtalertp, mp, offp)
* This function is separate from ip6_hopopts_input() in order to * This function is separate from ip6_hopopts_input() in order to
* handle a case where the sending node itself process its hop-by-hop * 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(). * 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 int
ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp) 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_int8_t *opt = opthead;
u_int16_t rtalert_val; u_int16_t rtalert_val;
u_int32_t jumboplen; u_int32_t jumboplen;
const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
switch (*opt) { switch (*opt) {
@ -846,9 +846,11 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
goto bad; goto bad;
} }
if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
/* XXX: should we discard the packet? */ /* XXX stat */
log(LOG_ERR, "length of router alert opt is inconsitent(%d)", icmp6_error(m, ICMP6_PARAM_PROB,
*(opt + 1)); ICMP6_PARAMPROB_HEADER,
erroff + opt + 1 - opthead);
return (-1);
} }
optlen = IP6OPT_RTALERT_LEN; optlen = IP6OPT_RTALERT_LEN;
bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2); bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
@ -861,10 +863,11 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
goto bad; goto bad;
} }
if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
/* XXX: should we discard the packet? */ /* XXX stat */
log(LOG_ERR, "length of jumbopayload opt " icmp6_error(m, ICMP6_PARAM_PROB,
"is inconsistent(%d)\n", ICMP6_PARAMPROB_HEADER,
*(opt + 1)); erroff + opt + 1 - opthead);
return (-1);
} }
optlen = IP6OPT_JUMBO_LEN; optlen = IP6OPT_JUMBO_LEN;
@ -876,11 +879,9 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
if (ip6->ip6_plen) { if (ip6->ip6_plen) {
ip6stat.ip6s_badoptions++; ip6stat.ip6s_badoptions++;
icmp6_error(m, ICMP6_PARAM_PROB, icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER, ICMP6_PARAMPROB_HEADER,
sizeof(struct ip6_hdr) + erroff + opt - opthead);
sizeof(struct ip6_hbh) + return (-1);
opt - opthead);
return(-1);
} }
/* /*
@ -902,11 +903,9 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
if (*plenp != 0) { if (*plenp != 0) {
ip6stat.ip6s_badoptions++; ip6stat.ip6s_badoptions++;
icmp6_error(m, ICMP6_PARAM_PROB, icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER, ICMP6_PARAMPROB_HEADER,
sizeof(struct ip6_hdr) + erroff + opt + 2 - opthead);
sizeof(struct ip6_hbh) + return (-1);
opt + 2 - opthead);
return(-1);
} }
#endif #endif
@ -916,11 +915,9 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
if (jumboplen <= IPV6_MAXPACKET) { if (jumboplen <= IPV6_MAXPACKET) {
ip6stat.ip6s_badoptions++; ip6stat.ip6s_badoptions++;
icmp6_error(m, ICMP6_PARAM_PROB, icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER, ICMP6_PARAMPROB_HEADER,
sizeof(struct ip6_hdr) + erroff + opt + 2 - opthead);
sizeof(struct ip6_hbh) + return (-1);
opt + 2 - opthead);
return(-1);
} }
*plenp = jumboplen; *plenp = jumboplen;
@ -930,21 +927,20 @@ ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
ip6stat.ip6s_toosmall++; ip6stat.ip6s_toosmall++;
goto bad; goto bad;
} }
if ((optlen = ip6_unknown_opt(opt, m, optlen = ip6_unknown_opt(opt, m,
sizeof(struct ip6_hdr) + erroff + opt - opthead);
sizeof(struct ip6_hbh) + if (optlen == -1)
opt - opthead)) == -1) return (-1);
return(-1);
optlen += 2; optlen += 2;
break; break;
} }
} }
return(0); return (0);
bad: bad:
m_freem(m); m_freem(m);
return(-1); return (-1);
} }
/* /*

View File

@ -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 $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/* /*
@ -66,7 +66,7 @@
*/ */
#include <sys/cdefs.h> #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_inet.h"
#include "opt_ipsec.h" #include "opt_ipsec.h"
@ -433,7 +433,7 @@ skip_ipsec2:;
/* Source address validation */ /* Source address validation */
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) && if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
(flags & IPV6_DADOUTPUT) == 0) { (flags & IPV6_UNSPECSRC) == 0) {
error = EOPNOTSUPP; error = EOPNOTSUPP;
ip6stat.ip6s_badscope++; ip6stat.ip6s_badscope++;
goto bad; goto bad;

View File

@ -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 $ */ /* $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 */ 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 ip6_moptions {
struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */ struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
@ -202,7 +202,7 @@ struct ip6stat {
#ifdef _KERNEL #ifdef _KERNEL
/* flags passed to ip6_output as last parameter */ /* 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_FORWARDING 0x02 /* most of IPv6 header exists */
#define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */ #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 u_int32_t ip6_flow_seq;
extern int ip6_auto_flowlabel; extern int ip6_auto_flowlabel;
extern int ip6_auto_linklocal;
extern int ip6_anonportmin; /* minimum ephemeral port */ extern int ip6_anonportmin; /* minimum ephemeral port */
extern int ip6_anonportmax; /* maximum 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 dest6_input __P((struct mbuf **, int *, int));
int none_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 /* _KERNEL */
#endif /* !_NETINET6_IP6_VAR_H_ */ #endif /* !_NETINET6_IP6_VAR_H_ */

View File

@ -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 $ */ /* $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $ */
/* /*
@ -70,7 +70,7 @@
*/ */
#include <sys/cdefs.h> #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" #include "opt_inet.h"
@ -150,15 +150,16 @@ mld6_start_listening(in6m)
* (reserved) or 1 (node-local). * (reserved) or 1 (node-local).
*/ */
mld6_all_nodes_linklocal.s6_addr16[1] = mld6_all_nodes_linklocal.s6_addr16[1] =
htons(in6m->in6m_ifp->if_index); /* XXX */ htons(in6m->in6m_ifp->if_index); /* XXX */
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal) || if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal) ||
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) { IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) {
in6m->in6m_timer = 0; in6m->in6m_timer = 0;
in6m->in6m_state = MLD6_OTHERLISTENER; in6m->in6m_state = MLD6_OTHERLISTENER;
} else { } else {
mld6_sendpkt(in6m, MLD6_LISTENER_REPORT, NULL); mld6_sendpkt(in6m, MLD6_LISTENER_REPORT, NULL);
in6m->in6m_timer = MLD6_RANDOM_DELAY( in6m->in6m_timer =
MLD6_UNSOLICITED_REPORT_INTERVAL * PR_FASTHZ); MLD6_RANDOM_DELAY(MLD6_UNSOLICITED_REPORT_INTERVAL *
PR_FASTHZ);
in6m->in6m_state = MLD6_IREPORTEDLAST; in6m->in6m_state = MLD6_IREPORTEDLAST;
mld6_timers_are_running = 1; mld6_timers_are_running = 1;
} }
@ -170,15 +171,15 @@ mld6_stop_listening(in6m)
struct in6_multi *in6m; struct in6_multi *in6m;
{ {
mld6_all_nodes_linklocal.s6_addr16[1] = mld6_all_nodes_linklocal.s6_addr16[1] =
htons(in6m->in6m_ifp->if_index); /* XXX */ htons(in6m->in6m_ifp->if_index); /* XXX */
mld6_all_routers_linklocal.s6_addr16[1] = mld6_all_routers_linklocal.s6_addr16[1] =
htons(in6m->in6m_ifp->if_index); /* XXX: necessary when mrouting */ htons(in6m->in6m_ifp->if_index); /* XXX: necessary when mrouting */
if (in6m->in6m_state == MLD6_IREPORTEDLAST && if (in6m->in6m_state == MLD6_IREPORTEDLAST &&
(!IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal)) && (!IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal)) &&
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > IPV6_ADDR_SCOPE_NODELOCAL) IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > IPV6_ADDR_SCOPE_NODELOCAL)
mld6_sendpkt(in6m, MLD6_LISTENER_DONE, mld6_sendpkt(in6m, MLD6_LISTENER_DONE,
&mld6_all_routers_linklocal); &mld6_all_routers_linklocal);
} }
void void
@ -244,7 +245,7 @@ mld6_input(m, off)
break; /* print error or log stat? */ break; /* print error or log stat? */
if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr)) if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr))
mldh->mld6_addr.s6_addr16[1] = mldh->mld6_addr.s6_addr16[1] =
htons(ifp->if_index); /* XXX */ htons(ifp->if_index); /* XXX */
/* /*
* - Start the timers in all of our membership records * - Start the timers in all of our membership records
@ -289,14 +290,14 @@ mld6_input(m, off)
if (timer == 0) { if (timer == 0) {
/* send a report immediately */ /* send a report immediately */
mld6_sendpkt(in6m, MLD6_LISTENER_REPORT, mld6_sendpkt(in6m, MLD6_LISTENER_REPORT,
NULL); NULL);
in6m->in6m_timer = 0; /* reset timer */ in6m->in6m_timer = 0; /* reset timer */
in6m->in6m_state = MLD6_IREPORTEDLAST; in6m->in6m_state = MLD6_IREPORTEDLAST;
} }
else if (in6m->in6m_timer == 0 || /*idle state*/ else if (in6m->in6m_timer == 0 || /*idle state*/
in6m->in6m_timer > timer) { in6m->in6m_timer > timer) {
in6m->in6m_timer = in6m->in6m_timer =
MLD6_RANDOM_DELAY(timer); MLD6_RANDOM_DELAY(timer);
mld6_timers_are_running = 1; mld6_timers_are_running = 1;
} }
} }
@ -339,6 +340,11 @@ mld6_input(m, off)
break; break;
default: /* this is impossible */ default: /* this is impossible */
#if 0 #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); log(LOG_ERR, "mld6_input: illegal type(%d)", mldh->mld6_type);
#endif #endif
break; break;
@ -353,7 +359,6 @@ mld6_fasttimeo()
struct in6_multi *in6m; struct in6_multi *in6m;
struct in6_multistep step; struct in6_multistep step;
int s; int s;
/* /*
* Quick check to see if any work needs to be done, in order * Quick check to see if any work needs to be done, in order
* to minimize the overhead of fasttimo processing. * to minimize the overhead of fasttimo processing.
@ -390,14 +395,19 @@ mld6_sendpkt(in6m, type, dst)
struct ip6_moptions im6o; struct ip6_moptions im6o;
struct in6_ifaddr *ia; struct in6_ifaddr *ia;
struct ifnet *ifp = in6m->in6m_ifp; struct ifnet *ifp = in6m->in6m_ifp;
int ignflags;
/* /*
* At first, find a link local address on the outgoing interface * At first, find a link local address on the outgoing interface
* to use as the source address of the MLD packet. * 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)) ignflags = (IN6_IFF_NOTREADY|IN6_IFF_ANYCAST) & ~IN6_IFF_TENTATIVE;
== NULL) if ((ia = in6ifa_ifpforlinklocal(ifp, ignflags)) == NULL)
return; return;
if ((ia->ia6_flags & IN6_IFF_TENTATIVE))
ia = NULL;
/* /*
* Allocate mbufs to store ip6 header and MLD header. * Allocate mbufs to store ip6 header and MLD header.
@ -414,6 +424,7 @@ mld6_sendpkt(in6m, type, dst)
} }
mh->m_next = md; mh->m_next = md;
mh->m_pkthdr.rcvif = NULL;
mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld6_hdr); mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld6_hdr);
mh->m_len = sizeof(struct ip6_hdr); mh->m_len = sizeof(struct ip6_hdr);
MH_ALIGN(mh, 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_plen will be set later */
ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_nxt = IPPROTO_ICMPV6;
/* ip6_hlim will be set by im6o.im6o_multicast_hlim */ /* 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; ip6->ip6_dst = dst ? *dst : in6m->in6m_addr;
/* fill in the MLD header */ /* fill in the MLD header */
@ -443,7 +454,7 @@ mld6_sendpkt(in6m, type, dst)
mldh->mld6_addr.s6_addr16[1] = 0; /* XXX */ mldh->mld6_addr.s6_addr16[1] = 0; /* XXX */
mldh->mld6_cksum = in6_cksum(mh, IPPROTO_ICMPV6, mldh->mld6_cksum = in6_cksum(mh, IPPROTO_ICMPV6,
sizeof(struct ip6_hdr), sizeof(struct ip6_hdr),
sizeof(struct mld6_hdr)); sizeof(struct mld6_hdr));
/* construct multicast option */ /* construct multicast option */
bzero(&im6o, sizeof(im6o)); bzero(&im6o, sizeof(im6o));
@ -458,8 +469,6 @@ mld6_sendpkt(in6m, type, dst)
/* increment output statictics */ /* increment output statictics */
icmp6stat.icp6s_outhist[type]++; icmp6stat.icp6s_outhist[type]++;
ip6_output(mh, &ip6_opts, NULL, 0, &im6o, NULL);
icmp6_ifstat_inc(ifp, ifs6_out_msg); icmp6_ifstat_inc(ifp, ifs6_out_msg);
switch (type) { switch (type) {
case MLD6_LISTENER_QUERY: case MLD6_LISTENER_QUERY:
@ -472,4 +481,6 @@ mld6_sendpkt(in6m, type, dst)
icmp6_ifstat_inc(ifp, ifs6_out_mlddone); icmp6_ifstat_inc(ifp, ifs6_out_mlddone);
break; break;
} }
ip6_output(mh, &ip6_opts, NULL, ia ? 0 : IPV6_UNSPECSRC, &im6o, NULL);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* $NetBSD: nd6.h,v 1.30 2002/06/07 02:31:04 itojun Exp $ */ /* $NetBSD: nd6.h,v 1.31 2002/06/08 21:22:34 itojun Exp $ */
/* $KAME: nd6.h,v 1.93 2002/06/05 00:56:22 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. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -93,6 +93,7 @@ struct nd_ifinfo {
}; };
#define ND6_IFF_PERFORMNUD 0x1 #define ND6_IFF_PERFORMNUD 0x1
#define ND6_IFF_ACCEPT_RTADV 0x2
#ifdef _KERNEL #ifdef _KERNEL
#define ND_IFINFO(ifp) \ #define ND_IFINFO(ifp) \
@ -126,6 +127,32 @@ struct in6_drlist {
} defrouter[DRLSTSIZ]; } defrouter[DRLSTSIZ];
}; };
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;
struct prf_ra raflags;
u_char prefixlen;
u_char origin;
u_long vltime;
u_long pltime;
u_long expire;
u_short if_index;
u_short advrtrs; /* number of advertisement routers */
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
} prefix[PRLSTSIZ];
};
#endif
struct in6_prlist { struct in6_prlist {
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
struct { struct {
@ -133,15 +160,30 @@ struct in6_prlist {
struct prf_ra raflags; struct prf_ra raflags;
u_char prefixlen; u_char prefixlen;
u_char origin; u_char origin;
u_long vltime; u_int32_t vltime;
u_long pltime; u_int32_t pltime;
u_long expire; time_t expire;
u_short if_index; u_short if_index;
u_short advrtrs; /* number of advertisement routers */ u_short advrtrs; /* number of advertisement routers */
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */ struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
} prefix[PRLSTSIZ]; } 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 #ifdef _KERNEL
struct in6_ondireq { struct in6_ondireq {
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
@ -169,6 +211,10 @@ struct in6_ndifreq {
u_long ifindex; u_long ifindex;
}; };
/* Prefix status */
#define NDPRF_ONLINK 0x1
#define NDPRF_DETACHED 0x2
#define NDPRF_HOME 0x4
/* protocol constants */ /* protocol constants */
#define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */ #define MAX_RTR_SOLICITATION_DELAY 1 /* 1sec */
@ -192,10 +238,11 @@ TAILQ_HEAD(nd_drhead, nd_defrouter);
struct nd_defrouter { struct nd_defrouter {
TAILQ_ENTRY(nd_defrouter) dr_entry; TAILQ_ENTRY(nd_defrouter) dr_entry;
struct in6_addr rtaddr; struct in6_addr rtaddr;
u_char flags; u_char flags; /* flags on RA message */
u_short rtlifetime; u_short rtlifetime;
u_long expire; u_long expire;
struct ifnet *ifp; struct ifnet *ifp;
int installed; /* is installed into kernel routing table */
}; };
struct nd_prefix { struct nd_prefix {
@ -203,19 +250,20 @@ struct nd_prefix {
LIST_ENTRY(nd_prefix) ndpr_entry; LIST_ENTRY(nd_prefix) ndpr_entry;
struct sockaddr_in6 ndpr_prefix; /* prefix */ struct sockaddr_in6 ndpr_prefix; /* prefix */
struct in6_addr ndpr_mask; /* netmask derived from the 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_vltime; /* advertised valid lifetime */
u_int32_t ndpr_pltime; /* advertised preferred lifetime */ u_int32_t ndpr_pltime; /* advertised preferred lifetime */
time_t ndpr_expire; /* expiration time of the prefix */ time_t ndpr_expire; /* expiration time of the prefix */
time_t ndpr_preferred; /* preferred 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; struct prf_ra ndpr_flags;
u_int32_t ndpr_stateflags; /* actual state flags */
/* list of routers that advertise the prefix: */ /* list of routers that advertise the prefix: */
LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs; LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs;
u_char ndpr_plen; u_char ndpr_plen;
struct ndpr_stateflags { int ndpr_refcnt; /* reference couter from addresses */
/* if this prefix can be regarded as on-link */
u_char onlink : 1;
} ndpr_stateflags;
}; };
#define ndpr_next ndpr_entry.le_next #define ndpr_next ndpr_entry.le_next
@ -223,15 +271,7 @@ struct nd_prefix {
#define ndpr_raf ndpr_flags #define ndpr_raf ndpr_flags
#define ndpr_raf_onlink ndpr_flags.onlink #define ndpr_raf_onlink ndpr_flags.onlink
#define ndpr_raf_auto ndpr_flags.autonomous #define ndpr_raf_auto ndpr_flags.autonomous
#define ndpr_raf_router ndpr_flags.router
#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)
/* /*
* Message format for use in obtaining information about prefixes * 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_decrvalid prm_flags.prf_rr.decrvalid
#define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd #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 { struct nd_pfxrouter {
LIST_ENTRY(nd_pfxrouter) pfr_entry; LIST_ENTRY(nd_pfxrouter) pfr_entry;
#define pfr_next pfr_entry.le_next #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 *, int nd6_resolve __P((struct ifnet *, struct rtentry *,
struct mbuf *, struct sockaddr *, u_char *)); struct mbuf *, struct sockaddr *, u_char *));
void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *)); 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 *)); int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *, struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int)); char *, int, int, int));
@ -340,15 +376,16 @@ int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct rtentry *)); struct sockaddr_in6 *, struct rtentry *));
int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *, int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *)); struct sockaddr *, u_char *));
int nd6_sysctl __P((int, void *, size_t *, void *, size_t));
int nd6_need_cache __P((struct ifnet *)); int nd6_need_cache __P((struct ifnet *));
/* nd6_nbr.c */ /* nd6_nbr.c */
void nd6_na_input __P((struct mbuf *, int, int)); void nd6_na_input __P((struct mbuf *, int, int));
void nd6_na_output __P((struct ifnet *, const struct in6_addr *, void nd6_na_output __P((struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *)); const struct in6_addr *, u_long, int, struct sockaddr *));
void nd6_ns_input __P((struct mbuf *, int, int)); void nd6_ns_input __P((struct mbuf *, int, int));
void nd6_ns_output __P((struct ifnet *, const struct in6_addr *, void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
const struct in6_addr *, struct llinfo_nd6 *, int)); const struct in6_addr *, struct llinfo_nd6 *, int));
caddr_t nd6_ifptomac __P((struct ifnet *)); caddr_t nd6_ifptomac __P((struct ifnet *));
void nd6_dad_start __P((struct ifaddr *, int *)); void nd6_dad_start __P((struct ifaddr *, int *));
void nd6_dad_stop __P((struct ifaddr *)); void nd6_dad_stop __P((struct ifaddr *));
@ -359,15 +396,19 @@ void nd6_rs_input __P((struct mbuf *, int, int));
void nd6_ra_input __P((struct mbuf *, int, int)); void nd6_ra_input __P((struct mbuf *, int, int));
void prelist_del __P((struct nd_prefix *)); void prelist_del __P((struct nd_prefix *));
void defrouter_addreq __P((struct nd_defrouter *)); 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 defrouter_select __P((void));
void defrtrlist_del __P((struct nd_defrouter *)); void defrtrlist_del __P((struct nd_defrouter *));
void prelist_remove __P((struct nd_prefix *)); void prelist_remove __P((struct nd_prefix *));
int prelist_update __P((struct nd_prefix *, struct nd_defrouter *, int prelist_update __P((struct nd_prefix *, struct nd_defrouter *,
struct mbuf *)); 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)); void pfxlist_onlink_check __P((void));
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct ifnet *));
struct ifnet *)); struct nd_prefix *nd6_prefix_lookup __P((struct nd_prefix *));
int in6_ifdel __P((struct ifnet *, struct in6_addr *)); int in6_ifdel __P((struct ifnet *, struct in6_addr *));
int in6_init_prefix_ltimes __P((struct nd_prefix *ndpr)); int in6_init_prefix_ltimes __P((struct nd_prefix *ndpr));
void rt6_flush __P((struct in6_addr *, struct ifnet *)); void rt6_flush __P((struct in6_addr *, struct ifnet *));

View File

@ -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 $ */ /* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/* /*
@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #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_inet.h"
#include "opt_ipsec.h" #include "opt_ipsec.h"
@ -105,6 +105,7 @@ nd6_ns_input(m, off, icmp6len)
struct ifaddr *ifa; struct ifaddr *ifa;
int lladdrlen = 0; int lladdrlen = 0;
int anycast = 0, proxy = 0, tentative = 0; int anycast = 0, proxy = 0, tentative = 0;
int router = ip6_forwarding;
int tlladdr; int tlladdr;
union nd_opts ndopts; union nd_opts ndopts;
struct sockaddr_dl *proxydl = NULL; struct sockaddr_dl *proxydl = NULL;
@ -132,15 +133,15 @@ nd6_ns_input(m, off, icmp6len)
if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) { if (IN6_IS_ADDR_UNSPECIFIED(&saddr6)) {
/* dst has to be solicited node multicast address. */ /* dst has to be solicited node multicast address. */
if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL /* don't check ifindex portion */
/* don't check ifindex portion */ if (daddr6.s6_addr16[0] == IPV6_ADDR_INT16_MLL &&
&& daddr6.s6_addr32[1] == 0 daddr6.s6_addr32[1] == 0 &&
&& daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE daddr6.s6_addr32[2] == IPV6_ADDR_INT32_ONE &&
&& daddr6.s6_addr8[12] == 0xff) { daddr6.s6_addr8[12] == 0xff) {
; /* good */ ; /* good */
} else { } else {
nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet " nd6log((LOG_INFO, "nd6_ns_input: bad DAD packet "
"(wrong ip6 dst)\n")); "(wrong ip6 dst)\n"));
goto bad; goto bad;
} }
} }
@ -224,6 +225,7 @@ nd6_ns_input(m, off, icmp6len)
if (ifa) { if (ifa) {
proxy = 1; proxy = 1;
proxydl = SDL(rt->rt_gateway); proxydl = SDL(rt->rt_gateway);
router = 0; /* XXX */
} }
} }
if (rt) if (rt)
@ -244,16 +246,14 @@ nd6_ns_input(m, off, icmp6len)
goto freeit; goto freeit;
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
nd6log((LOG_INFO, nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
"nd6_ns_input: lladdrlen mismatch for %s "
"(if %d, NS packet %d)\n", "(if %d, NS packet %d)\n",
ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2)); ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
goto bad; goto bad;
} }
if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) { if (IN6_ARE_ADDR_EQUAL(&myaddr6, &saddr6)) {
nd6log((LOG_INFO, nd6log((LOG_INFO, "nd6_ns_input: duplicate IP6 address %s\n",
"nd6_ns_input: duplicate IP6 address %s\n",
ip6_sprintf(&saddr6))); ip6_sprintf(&saddr6)));
goto freeit; goto freeit;
} }
@ -296,20 +296,18 @@ nd6_ns_input(m, off, icmp6len)
saddr6 = in6addr_linklocal_allnodes; saddr6 = in6addr_linklocal_allnodes;
saddr6.s6_addr16[1] = htons(ifp->if_index); saddr6.s6_addr16[1] = htons(ifp->if_index);
nd6_na_output(ifp, &saddr6, &taddr6, nd6_na_output(ifp, &saddr6, &taddr6,
((anycast || proxy || !tlladdr) ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
? 0 : ND_NA_FLAG_OVERRIDE) (router ? ND_NA_FLAG_ROUTER : 0),
| (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0), tlladdr, (struct sockaddr *)proxydl);
tlladdr, (struct sockaddr *)proxydl);
goto freeit; goto freeit;
} }
nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0); nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_NEIGHBOR_SOLICIT, 0);
nd6_na_output(ifp, &saddr6, &taddr6, nd6_na_output(ifp, &saddr6, &taddr6,
((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) ((anycast || proxy || !tlladdr) ? 0 : ND_NA_FLAG_OVERRIDE) |
| (ip6_forwarding ? ND_NA_FLAG_ROUTER : 0) (router ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
| ND_NA_FLAG_SOLICITED, tlladdr, (struct sockaddr *)proxydl);
tlladdr, (struct sockaddr *)proxydl);
freeit: freeit:
m_freem(m); m_freem(m);
return; return;
@ -341,11 +339,14 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
struct mbuf *m; struct mbuf *m;
struct ip6_hdr *ip6; struct ip6_hdr *ip6;
struct nd_neighbor_solicit *nd_ns; struct nd_neighbor_solicit *nd_ns;
struct in6_ifaddr *ia = NULL; struct sockaddr_in6 src_sa, dst_sa;
struct ip6_moptions im6o; struct ip6_moptions im6o;
int icmp6len; int icmp6len;
int maxlen; int maxlen;
caddr_t mac; caddr_t mac;
struct route_in6 ro;
bzero(&ro, sizeof(ro));
if (IN6_IS_ADDR_MULTICAST(taddr6)) if (IN6_IS_ADDR_MULTICAST(taddr6))
return; return;
@ -393,16 +394,22 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
/* ip6->ip6_plen will be set later */ /* ip6->ip6_plen will be set later */
ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_nxt = IPPROTO_ICMPV6;
ip6->ip6_hlim = 255; 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) if (daddr6)
ip6->ip6_dst = *daddr6; dst_sa.sin6_addr = *daddr6;
else { else {
ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; dst_sa.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); dst_sa.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
ip6->ip6_dst.s6_addr32[1] = 0; dst_sa.sin6_addr.s6_addr32[1] = 0;
ip6->ip6_dst.s6_addr32[2] = IPV6_ADDR_INT32_ONE; dst_sa.sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
ip6->ip6_dst.s6_addr32[3] = taddr6->s6_addr32[3]; dst_sa.sin6_addr.s6_addr32[3] = taddr6->s6_addr32[3];
ip6->ip6_dst.s6_addr8[12] = 0xff; dst_sa.sin6_addr.s6_addr8[12] = 0xff;
} }
ip6->ip6_dst = dst_sa.sin6_addr;
if (!dad) { if (!dad) {
/* /*
* RFC2461 7.2.2: * RFC2461 7.2.2:
@ -417,7 +424,7 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
* (saddr6), if: * (saddr6), if:
* - saddr6 is given from the caller (by giving "ln"), and * - saddr6 is given from the caller (by giving "ln"), and
* - saddr6 belongs to the outgoing interface. * - 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 ip6_hdr *hip6; /* hold ip6 */
struct in6_addr *saddr6; struct in6_addr *saddr6;
@ -432,22 +439,34 @@ nd6_ns_output(ifp, daddr6, taddr6, ln, dad)
} else } else
saddr6 = NULL; saddr6 = NULL;
if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6)) if (saddr6 && in6ifa_ifpwithaddr(ifp, saddr6))
bcopy(saddr6, &ip6->ip6_src, sizeof(*saddr6)); src_sa.sin6_addr = *saddr6;
else { else {
ia = in6_ifawithifp(ifp, &ip6->ip6_dst); struct in6_addr *src0;
if (ia == NULL) { int error;
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_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 { } else {
/* /*
* Source address for DAD packet must always be IPv6 * Source address for DAD packet must always be IPv6
* unspecified address. (0::0) * 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 = (struct nd_neighbor_solicit *)(ip6 + 1);
nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT; nd_ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
nd_ns->nd_ns_code = 0; 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); ip6->ip6_plen = htons((u_short)icmp6len);
nd_ns->nd_ns_cksum = 0; nd_ns->nd_ns_cksum = 0;
nd_ns->nd_ns_cksum nd_ns->nd_ns_cksum =
= in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len); in6_cksum(m, IPPROTO_ICMPV6, sizeof(*ip6), icmp6len);
#ifdef IPSEC #ifdef IPSEC
/* Don't lookup socket */ /* Don't lookup socket */
(void)ipsec_setsocket(m, NULL); (void)ipsec_setsocket(m, NULL);
#endif #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_msg);
icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++; icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
if (ro.ro_rt) { /* we don't cache this route. */
RTFREE(ro.ro_rt);
}
return; return;
#if 0
bad: bad:
if (ro.ro_rt) {
RTFREE(ro.ro_rt);
}
m_freem(m); m_freem(m);
return; return;
#endif
} }
/* /*
* Neighbor advertisement input handling. * Neighbor advertisement input handling.
* *
* Based on RFC 2461 * Based on RFC 2461
long time_second = time.tv_sec;
* Based on RFC 2462 (duplicated address detection) * Based on RFC 2462 (duplicated address detection)
* *
* the following items are not implemented yet: * the following items are not implemented yet:
@ -576,12 +600,11 @@ nd6_na_input(m, off, icmp6len)
ip6_sprintf(&taddr6))); ip6_sprintf(&taddr6)));
goto bad; goto bad;
} }
if (IN6_IS_ADDR_MULTICAST(&daddr6)) if (is_solicited && IN6_IS_ADDR_MULTICAST(&daddr6)) {
if (is_solicited) { nd6log((LOG_ERR,
nd6log((LOG_ERR, "nd6_na_input: a solicited adv is multicasted\n"));
"nd6_na_input: a solicited adv is multicasted\n")); goto bad;
goto bad; }
}
icmp6len -= sizeof(*nd_na); icmp6len -= sizeof(*nd_na);
nd6_option_init(nd_na + 1, icmp6len, &ndopts); nd6_option_init(nd_na + 1, icmp6len, &ndopts);
@ -623,15 +646,15 @@ nd6_na_input(m, off, icmp6len)
} }
if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) { if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
nd6log((LOG_INFO, nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
"nd6_na_input: lladdrlen mismatch for %s " "(if %d, NA packet %d)\n", ip6_sprintf(&taddr6),
"(if %d, NA packet %d)\n", ifp->if_addrlen, lladdrlen - 2));
ip6_sprintf(&taddr6), ifp->if_addrlen, lladdrlen - 2));
goto bad; 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); rt = nd6_lookup(&taddr6, 0, ifp);
if ((rt == NULL) || if ((rt == NULL) ||
@ -788,7 +811,7 @@ nd6_na_input(m, off, icmp6len)
ln->ln_asked = 0; ln->ln_asked = 0;
if (ln->ln_hold) { 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. * argument as the 1st one.
*/ */
nd6_output(ifp, ifp, ln->ln_hold, nd6_output(ifp, ifp, ln->ln_hold,
@ -825,11 +848,15 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
struct mbuf *m; struct mbuf *m;
struct ip6_hdr *ip6; struct ip6_hdr *ip6;
struct nd_neighbor_advert *nd_na; struct nd_neighbor_advert *nd_na;
struct in6_ifaddr *ia = NULL;
struct ip6_moptions im6o; struct ip6_moptions im6o;
int icmp6len; struct sockaddr_in6 src_sa, dst_sa;
int maxlen; struct in6_addr *src0;
int icmp6len, maxlen, error;
caddr_t mac; caddr_t mac;
struct route_in6 ro;
mac = NULL;
bzero(&ro, sizeof(ro));
/* estimate the size of message */ /* estimate the size of message */
maxlen = sizeof(*ip6) + sizeof(*nd_na); 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_vfc |= IPV6_VERSION;
ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_nxt = IPPROTO_ICMPV6;
ip6->ip6_hlim = 255; 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)) { if (IN6_IS_ADDR_UNSPECIFIED(daddr6)) {
/* reply to DAD */ /* reply to DAD */
ip6->ip6_dst.s6_addr16[0] = IPV6_ADDR_INT16_MLL; dst_sa.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
ip6->ip6_dst.s6_addr16[1] = htons(ifp->if_index); dst_sa.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
ip6->ip6_dst.s6_addr32[1] = 0; dst_sa.sin6_addr.s6_addr32[1] = 0;
ip6->ip6_dst.s6_addr32[2] = 0; dst_sa.sin6_addr.s6_addr32[2] = 0;
ip6->ip6_dst.s6_addr32[3] = IPV6_ADDR_INT32_ONE; dst_sa.sin6_addr.s6_addr32[3] = IPV6_ADDR_INT32_ONE;
flags &= ~ND_NA_FLAG_SOLICITED; 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. * Select a source whose scope is the same as that of the dest.
*/ */
ia = in6_ifawithifp(ifp, &ip6->ip6_dst); bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
if (ia == NULL) { src0 = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, &error);
m_freem(m); if (src0 == NULL) {
return; 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 = (struct nd_neighbor_advert *)(ip6 + 1);
nd_na->nd_na_type = ND_NEIGHBOR_ADVERT; nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
nd_na->nd_na_code = 0; 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. * target lladdr option SHOULD NOT be included.
*/ */
if (tlladdr) { if (tlladdr) {
mac = NULL;
/* /*
* sdl0 != NULL indicates proxy NA. If we do proxy, use * sdl0 != NULL indicates proxy NA. If we do proxy, use
* lladdr in sdl0. If we are not proxying (sending NA for * lladdr in sdl0. If we are not proxying (sending NA for
@ -943,7 +979,7 @@ nd6_na_output(ifp, daddr6, taddr6, flags, tlladdr, sdl0)
nd_na->nd_na_flags_reserved = flags; nd_na->nd_na_flags_reserved = flags;
nd_na->nd_na_cksum = 0; nd_na->nd_na_cksum = 0;
nd_na->nd_na_cksum = nd_na->nd_na_cksum =
in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len); in6_cksum(m, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), icmp6len);
#ifdef IPSEC #ifdef IPSEC
/* Don't lookup socket */ /* Don't lookup socket */
@ -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_msg);
icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++; 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 caddr_t
@ -965,6 +1013,9 @@ nd6_ifptomac(ifp)
case IFT_ETHER: case IFT_ETHER:
case IFT_FDDI: case IFT_FDDI:
case IFT_IEEE1394: case IFT_IEEE1394:
case IFT_PROPVIRTUAL:
case IFT_L2VLAN:
case IFT_IEEE80211:
return LLADDR(ifp->if_sadl); return LLADDR(ifp->if_sadl);
break; break;
default: default:

File diff suppressed because it is too large Load Diff