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
|
# @(#)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
|
||||||
|
|
|
@ -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
|
||||||
|
|
1270
sys/netinet6/in6.c
1270
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 $ */
|
/* $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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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
|
@ -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 $ */
|
/* $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 **));
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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
|
@ -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 *));
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue