- add dom_if{attach,detach} framework.
- transition to use ifp->if_afdata. Obtained from: KAME
This commit is contained in:
parent
3efeb2b693
commit
31b1bfe1b0
48
sys/net/if.c
48
sys/net/if.c
@ -54,6 +54,7 @@
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/jail.h>
|
||||
#include <machine/stdarg.h>
|
||||
|
||||
@ -78,6 +79,8 @@
|
||||
#include <netinet/if_ether.h>
|
||||
#endif
|
||||
|
||||
static void if_attachdomain(void *);
|
||||
static void if_attachdomain1(struct ifnet *);
|
||||
static int ifconf(u_long, caddr_t);
|
||||
static void if_grow(void);
|
||||
static void if_init(void *);
|
||||
@ -442,10 +445,48 @@ if_attach(ifp)
|
||||
}
|
||||
ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
|
||||
|
||||
if (domains)
|
||||
if_attachdomain1(ifp);
|
||||
|
||||
/* Announce the interface. */
|
||||
rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
|
||||
}
|
||||
|
||||
static void
|
||||
if_attachdomain(dummy)
|
||||
void *dummy;
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
int s;
|
||||
|
||||
s = splnet();
|
||||
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
|
||||
if_attachdomain1(ifp);
|
||||
splx(s);
|
||||
}
|
||||
SYSINIT(domainifattach, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST,
|
||||
if_attachdomain, NULL);
|
||||
|
||||
static void
|
||||
if_attachdomain1(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct domain *dp;
|
||||
int s;
|
||||
|
||||
s = splnet();
|
||||
|
||||
/* address family dependent data region */
|
||||
bzero(ifp->if_afdata, sizeof(ifp->if_afdata));
|
||||
for (dp = domains; dp; dp = dp->dom_next) {
|
||||
if (dp->dom_ifattach)
|
||||
ifp->if_afdata[dp->dom_family] =
|
||||
(*dp->dom_ifattach)(ifp);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach an interface, removing it from the
|
||||
* list of "active" interfaces.
|
||||
@ -458,6 +499,7 @@ if_detach(ifp)
|
||||
struct radix_node_head *rnh;
|
||||
int s;
|
||||
int i;
|
||||
struct domain *dp;
|
||||
|
||||
/*
|
||||
* Remove routes and flush queues.
|
||||
@ -538,6 +580,12 @@ if_detach(ifp)
|
||||
/* Announce that the interface is gone. */
|
||||
rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
|
||||
|
||||
for (dp = domains; dp; dp = dp->dom_next) {
|
||||
if (dp->dom_ifdetach && ifp->if_afdata[dp->dom_family])
|
||||
(*dp->dom_ifdetach)(ifp,
|
||||
ifp->if_afdata[dp->dom_family]);
|
||||
}
|
||||
|
||||
#ifdef MAC
|
||||
mac_destroy_ifnet(ifp);
|
||||
#endif /* MAC */
|
||||
|
@ -178,6 +178,8 @@ struct ifnet {
|
||||
struct ifprefixhead if_prefixhead; /* list of prefixes per if */
|
||||
u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */
|
||||
struct label if_label; /* interface MAC label */
|
||||
|
||||
void *if_afdata[AF_MAX];
|
||||
};
|
||||
|
||||
typedef void if_init_f_t(void *);
|
||||
|
@ -649,11 +649,8 @@ void icmp6_mtudisc_update(struct ip6ctlparam *, int);
|
||||
/* XXX: is this the right place for these macros? */
|
||||
#define icmp6_ifstat_inc(ifp, tag) \
|
||||
do { \
|
||||
if ((ifp) && (ifp)->if_index <= if_index \
|
||||
&& (ifp)->if_index < icmp6_ifstatmax \
|
||||
&& icmp6_ifstat && icmp6_ifstat[(ifp)->if_index]) { \
|
||||
icmp6_ifstat[(ifp)->if_index]->tag++; \
|
||||
} \
|
||||
if (ifp) \
|
||||
((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->icmp6_ifstat->tag++; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
#define icmp6_ifoutstat_inc(ifp, type, code) \
|
||||
@ -661,7 +658,7 @@ do { \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_msg); \
|
||||
if (type < ICMP6_INFOMSG_MASK) \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_error); \
|
||||
switch(type) { \
|
||||
switch (type) { \
|
||||
case ICMP6_DST_UNREACH: \
|
||||
icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \
|
||||
if (code == ICMP6_DST_UNREACH_ADMIN) \
|
||||
|
@ -2712,8 +2712,7 @@ tcp_mss(tp, offer)
|
||||
mss = rt->rt_rmx.rmx_mtu - min_protoh;
|
||||
else {
|
||||
if (isipv6) {
|
||||
mss = nd_ifinfo[rt->rt_ifp->if_index].linkmtu -
|
||||
min_protoh;
|
||||
mss = ND_IFINFO(rt->rt_ifp)->linkmtu - min_protoh;
|
||||
if (!in6_localaddr(&inp->in6p_faddr))
|
||||
mss = min(mss, tcp_v6mssdflt);
|
||||
} else {
|
||||
|
@ -2712,8 +2712,7 @@ tcp_mss(tp, offer)
|
||||
mss = rt->rt_rmx.rmx_mtu - min_protoh;
|
||||
else {
|
||||
if (isipv6) {
|
||||
mss = nd_ifinfo[rt->rt_ifp->if_index].linkmtu -
|
||||
min_protoh;
|
||||
mss = ND_IFINFO(rt->rt_ifp)->linkmtu - min_protoh;
|
||||
if (!in6_localaddr(&inp->in6p_faddr))
|
||||
mss = min(mss, tcp_v6mssdflt);
|
||||
} else {
|
||||
|
@ -2158,7 +2158,7 @@ icmp6_reflect(m, off)
|
||||
ip6->ip6_nxt = IPPROTO_ICMPV6;
|
||||
if (m->m_pkthdr.rcvif) {
|
||||
/* XXX: This may not be the outgoing interface */
|
||||
ip6->ip6_hlim = nd_ifinfo[m->m_pkthdr.rcvif->if_index].chlim;
|
||||
ip6->ip6_hlim = ND_IFINFO(m->m_pkthdr.rcvif)->chlim;
|
||||
} else
|
||||
ip6->ip6_hlim = ip6_defhlim;
|
||||
|
||||
|
@ -420,14 +420,14 @@ in6_control(so, cmd, data, ifp, td)
|
||||
case SIOCSSCOPE6:
|
||||
if (!privileged)
|
||||
return (EPERM);
|
||||
return (scope6_set(ifp, ifr->ifr_ifru.ifru_scope_id));
|
||||
break;
|
||||
return (scope6_set(ifp,
|
||||
(struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
|
||||
case SIOCGSCOPE6:
|
||||
return (scope6_get(ifp, ifr->ifr_ifru.ifru_scope_id));
|
||||
break;
|
||||
return (scope6_get(ifp,
|
||||
(struct scope6_id *)ifr->ifr_ifru.ifru_scope_id));
|
||||
case SIOCGSCOPE6DEF:
|
||||
return (scope6_get_default(ifr->ifr_ifru.ifru_scope_id));
|
||||
break;
|
||||
return (scope6_get_default((struct scope6_id *)
|
||||
ifr->ifr_ifru.ifru_scope_id));
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
@ -560,28 +560,19 @@ in6_control(so, cmd, data, ifp, td)
|
||||
break;
|
||||
|
||||
case SIOCGIFSTAT_IN6:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
if (in6_ifstat == NULL || ifp->if_index >= in6_ifstatmax
|
||||
|| in6_ifstat[ifp->if_index] == NULL) {
|
||||
/* return EAFNOSUPPORT? */
|
||||
bzero(&ifr->ifr_ifru.ifru_stat,
|
||||
sizeof(ifr->ifr_ifru.ifru_stat));
|
||||
} else
|
||||
ifr->ifr_ifru.ifru_stat = *in6_ifstat[ifp->if_index];
|
||||
bzero(&ifr->ifr_ifru.ifru_stat,
|
||||
sizeof(ifr->ifr_ifru.ifru_stat));
|
||||
ifr->ifr_ifru.ifru_stat =
|
||||
*((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->in6_ifstat;
|
||||
break;
|
||||
|
||||
case SIOCGIFSTAT_ICMP6:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
if (icmp6_ifstat == NULL || ifp->if_index >= icmp6_ifstatmax ||
|
||||
icmp6_ifstat[ifp->if_index] == NULL) {
|
||||
/* return EAFNOSUPPORT? */
|
||||
bzero(&ifr->ifr_ifru.ifru_stat,
|
||||
sizeof(ifr->ifr_ifru.ifru_icmp6stat));
|
||||
} else
|
||||
ifr->ifr_ifru.ifru_icmp6stat =
|
||||
*icmp6_ifstat[ifp->if_index];
|
||||
bzero(&ifr->ifr_ifru.ifru_stat,
|
||||
sizeof(ifr->ifr_ifru.ifru_icmp6stat));
|
||||
ifr->ifr_ifru.ifru_icmp6stat =
|
||||
*((struct in6_ifextra *)ifp->if_afdata[AF_INET6])->icmp6_ifstat;
|
||||
break;
|
||||
|
||||
case SIOCGIFALIFETIME_IN6:
|
||||
@ -1109,13 +1100,6 @@ in6_update_ifa(ifp, ifra, ia)
|
||||
} else
|
||||
ia->ia6_lifetime.ia6t_preferred = 0;
|
||||
|
||||
/*
|
||||
* make sure to initialize ND6 information. this is to workaround
|
||||
* issues with interfaces with IPv6 addresses, which have never brought
|
||||
* up. We are assuming that it is safe to nd6_ifattach multiple times.
|
||||
*/
|
||||
nd6_ifattach(ifp);
|
||||
|
||||
/*
|
||||
* Perform DAD, if needed.
|
||||
* XXX It may be of use, if we can administratively
|
||||
@ -2341,14 +2325,51 @@ in6_setmaxmtu()
|
||||
IFNET_RLOCK();
|
||||
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
|
||||
if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
|
||||
nd_ifinfo[ifp->if_index].linkmtu > maxmtu)
|
||||
maxmtu = nd_ifinfo[ifp->if_index].linkmtu;
|
||||
ND_IFINFO(ifp)->linkmtu > maxmtu)
|
||||
maxmtu = ND_IFINFO(ifp)->linkmtu;
|
||||
}
|
||||
IFNET_RUNLOCK();
|
||||
if (maxmtu) /* update only when maxmtu is positive */
|
||||
in6_maxmtu = maxmtu;
|
||||
}
|
||||
|
||||
void *
|
||||
in6_domifattach(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct in6_ifextra *ext;
|
||||
|
||||
ext = (struct in6_ifextra *)malloc(sizeof(*ext), M_IFADDR, M_WAITOK);
|
||||
bzero(ext, sizeof(*ext));
|
||||
|
||||
ext->in6_ifstat = (struct in6_ifstat *)malloc(sizeof(struct in6_ifstat),
|
||||
M_IFADDR, M_WAITOK);
|
||||
bzero(ext->in6_ifstat, sizeof(*ext->in6_ifstat));
|
||||
|
||||
ext->icmp6_ifstat =
|
||||
(struct icmp6_ifstat *)malloc(sizeof(struct icmp6_ifstat),
|
||||
M_IFADDR, M_WAITOK);
|
||||
bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
|
||||
|
||||
ext->nd_ifinfo = nd6_ifattach(ifp);
|
||||
ext->scope6_id = scope6_ifattach(ifp);
|
||||
return ext;
|
||||
}
|
||||
|
||||
void
|
||||
in6_domifdetach(ifp, aux)
|
||||
struct ifnet *ifp;
|
||||
void *aux;
|
||||
{
|
||||
struct in6_ifextra *ext = (struct in6_ifextra *)aux;
|
||||
|
||||
scope6_ifdetach(ext->scope6_id);
|
||||
nd6_ifdetach(ext->nd_ifinfo);
|
||||
free(ext->in6_ifstat, M_IFADDR);
|
||||
free(ext->icmp6_ifstat, M_IFADDR);
|
||||
free(ext, M_IFADDR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert sockaddr_in6 to sockaddr_in. Original sockaddr_in6 must be
|
||||
* v4 mapped addr or v4 compat addr
|
||||
|
@ -60,10 +60,6 @@
|
||||
|
||||
#include <net/net_osdep.h>
|
||||
|
||||
struct in6_ifstat **in6_ifstat = NULL;
|
||||
struct icmp6_ifstat **icmp6_ifstat = NULL;
|
||||
size_t in6_ifstatmax = 0;
|
||||
size_t icmp6_ifstatmax = 0;
|
||||
unsigned long in6_maxmtu = 0;
|
||||
|
||||
#ifdef IP6_AUTO_LINKLOCAL
|
||||
@ -727,7 +723,6 @@ in6_ifattach(ifp, altifp)
|
||||
struct ifnet *ifp;
|
||||
struct ifnet *altifp; /* secondary EUI64 source */
|
||||
{
|
||||
static size_t if_indexlim = 8;
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_addr in6;
|
||||
|
||||
@ -739,50 +734,6 @@ in6_ifattach(ifp, altifp)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* We have some arrays that should be indexed by if_index.
|
||||
* since if_index will grow dynamically, they should grow too.
|
||||
* struct in6_ifstat **in6_ifstat
|
||||
* struct icmp6_ifstat **icmp6_ifstat
|
||||
*/
|
||||
if (in6_ifstat == NULL || icmp6_ifstat == NULL ||
|
||||
if_index >= if_indexlim) {
|
||||
size_t n;
|
||||
caddr_t q;
|
||||
size_t olim;
|
||||
|
||||
olim = if_indexlim;
|
||||
while (if_index >= if_indexlim)
|
||||
if_indexlim <<= 1;
|
||||
|
||||
/* grow in6_ifstat */
|
||||
n = if_indexlim * sizeof(struct in6_ifstat *);
|
||||
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
|
||||
bzero(q, n);
|
||||
if (in6_ifstat) {
|
||||
bcopy((caddr_t)in6_ifstat, q,
|
||||
olim * sizeof(struct in6_ifstat *));
|
||||
free((caddr_t)in6_ifstat, M_IFADDR);
|
||||
}
|
||||
in6_ifstat = (struct in6_ifstat **)q;
|
||||
in6_ifstatmax = if_indexlim;
|
||||
|
||||
/* grow icmp6_ifstat */
|
||||
n = if_indexlim * sizeof(struct icmp6_ifstat *);
|
||||
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
|
||||
bzero(q, n);
|
||||
if (icmp6_ifstat) {
|
||||
bcopy((caddr_t)icmp6_ifstat, q,
|
||||
olim * sizeof(struct icmp6_ifstat *));
|
||||
free((caddr_t)icmp6_ifstat, M_IFADDR);
|
||||
}
|
||||
icmp6_ifstat = (struct icmp6_ifstat **)q;
|
||||
icmp6_ifstatmax = if_indexlim;
|
||||
}
|
||||
|
||||
/* initialize scope identifiers */
|
||||
scope6_ifattach(ifp);
|
||||
|
||||
/*
|
||||
* quirks based on interface type
|
||||
*/
|
||||
@ -844,20 +795,6 @@ in6_ifattach(ifp, altifp)
|
||||
/* update dynamically. */
|
||||
if (in6_maxmtu < ifp->if_mtu)
|
||||
in6_maxmtu = ifp->if_mtu;
|
||||
|
||||
if (in6_ifstat[ifp->if_index] == NULL) {
|
||||
in6_ifstat[ifp->if_index] = (struct in6_ifstat *)
|
||||
malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);
|
||||
bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));
|
||||
}
|
||||
if (icmp6_ifstat[ifp->if_index] == NULL) {
|
||||
icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)
|
||||
malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);
|
||||
bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));
|
||||
}
|
||||
|
||||
/* initialize NDP variables */
|
||||
nd6_ifattach(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -987,7 +924,7 @@ in6_get_tmpifid(ifp, retbuf, baseid, generate)
|
||||
int generate;
|
||||
{
|
||||
u_int8_t nullbuf[8];
|
||||
struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
|
||||
struct nd_ifinfo *ndi = ND_IFINFO(ifp);
|
||||
|
||||
bzero(nullbuf, sizeof(nullbuf));
|
||||
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
|
||||
@ -1009,9 +946,9 @@ void
|
||||
in6_tmpaddrtimer(ignored_arg)
|
||||
void *ignored_arg;
|
||||
{
|
||||
int i;
|
||||
struct nd_ifinfo *ndi;
|
||||
u_int8_t nullbuf[8];
|
||||
struct ifnet *ifp;
|
||||
int s = splnet();
|
||||
|
||||
callout_reset(&in6_tmpaddrtimer_ch,
|
||||
@ -1019,8 +956,8 @@ in6_tmpaddrtimer(ignored_arg)
|
||||
ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);
|
||||
|
||||
bzero(nullbuf, sizeof(nullbuf));
|
||||
for (i = 1; i < if_index + 1; i++) {
|
||||
ndi = &nd_ifinfo[i];
|
||||
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
|
||||
ndi = ND_IFINFO(ifp);
|
||||
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
|
||||
/*
|
||||
* We've been generating a random ID on this interface.
|
||||
|
@ -264,7 +264,8 @@ struct domain inet6domain =
|
||||
(struct protosw *)&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])], 0,
|
||||
in6_inithead,
|
||||
offsetof(struct sockaddr_in6, sin6_addr) << 3,
|
||||
sizeof(struct sockaddr_in6) };
|
||||
sizeof(struct sockaddr_in6),
|
||||
in6_domifattach, in6_domifdetach, };
|
||||
|
||||
DOMAIN_SET(inet6);
|
||||
|
||||
|
@ -300,7 +300,7 @@ in6_selecthlim(in6p, ifp)
|
||||
if (in6p && in6p->in6p_hops >= 0)
|
||||
return (in6p->in6p_hops);
|
||||
else if (ifp)
|
||||
return (nd_ifinfo[ifp->if_index].chlim);
|
||||
return (ND_IFINFO(ifp)->chlim);
|
||||
else
|
||||
return (ip6_defhlim);
|
||||
}
|
||||
|
@ -90,6 +90,15 @@ struct in6_addrlifetime {
|
||||
u_int32_t ia6t_pltime; /* prefix lifetime */
|
||||
};
|
||||
|
||||
struct nd_ifinfo;
|
||||
struct scope6_id;
|
||||
struct in6_ifextra {
|
||||
struct in6_ifstat *in6_ifstat;
|
||||
struct icmp6_ifstat *icmp6_ifstat;
|
||||
struct nd_ifinfo *nd_ifinfo;
|
||||
struct scope6_id *scope6_id;
|
||||
};
|
||||
|
||||
struct in6_ifaddr {
|
||||
struct ifaddr ia_ifa; /* protocol-independent info */
|
||||
#define ia_ifp ia_ifa.ifa_ifp
|
||||
@ -445,18 +454,11 @@ struct in6_rrenumreq {
|
||||
#ifdef _KERNEL
|
||||
extern struct in6_ifaddr *in6_ifaddr;
|
||||
|
||||
extern struct in6_ifstat **in6_ifstat;
|
||||
extern size_t in6_ifstatmax;
|
||||
extern struct icmp6stat icmp6stat;
|
||||
extern struct icmp6_ifstat **icmp6_ifstat;
|
||||
extern size_t icmp6_ifstatmax;
|
||||
#define in6_ifstat_inc(ifp, tag) \
|
||||
do { \
|
||||
if ((ifp) && (ifp)->if_index <= if_index \
|
||||
&& (ifp)->if_index < in6_ifstatmax \
|
||||
&& in6_ifstat && in6_ifstat[(ifp)->if_index]) { \
|
||||
in6_ifstat[(ifp)->if_index]->tag++; \
|
||||
} \
|
||||
if (ifp) \
|
||||
((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->in6_ifstat->tag++; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
extern struct in6_addr zeroin6_addr;
|
||||
@ -576,6 +578,8 @@ void in6_purgeaddr __P((struct ifaddr *));
|
||||
int in6if_do_dad __P((struct ifnet *));
|
||||
void in6_purgeif __P((struct ifnet *));
|
||||
void in6_savemkludge __P((struct in6_ifaddr *));
|
||||
void *in6_domifattach __P((struct ifnet *));
|
||||
void in6_domifdetach __P((struct ifnet *, void *));
|
||||
void in6_setmaxmtu __P((void));
|
||||
void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *));
|
||||
void in6_purgemkludge __P((struct ifnet *));
|
||||
|
@ -106,6 +106,7 @@
|
||||
#include <netinet6/ip6_var.h>
|
||||
#include <netinet/in_pcb.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
#include <netinet6/in6_ifattach.h>
|
||||
#include <netinet6/nd6.h>
|
||||
#include <netinet6/in6_prefix.h>
|
||||
@ -196,6 +197,7 @@ ip6_init()
|
||||
ip6intrq.ifq_maxlen = ip6qmaxlen;
|
||||
mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF);
|
||||
netisr_register(NETISR_IPV6, ip6_input, &ip6intrq);
|
||||
scope6_init();
|
||||
nd6_init();
|
||||
frag6_init();
|
||||
#ifndef RANDOM_IP_ID
|
||||
@ -209,12 +211,6 @@ ip6_init2(dummy)
|
||||
void *dummy;
|
||||
{
|
||||
|
||||
/*
|
||||
* to route local address of p2p link to loopback,
|
||||
* assign loopback address first.
|
||||
*/
|
||||
in6_ifattach(&loif[0], NULL);
|
||||
|
||||
/* nd6_timer_init */
|
||||
callout_init(&nd6_timer_ch, 0);
|
||||
callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
|
||||
|
@ -794,7 +794,7 @@ skip_ipsec2:;
|
||||
}
|
||||
}
|
||||
if (ro_pmtu->ro_rt != NULL) {
|
||||
u_int32_t ifmtu = nd_ifinfo[ifp->if_index].linkmtu;
|
||||
u_int32_t ifmtu = ND_IFINFO(ifp)->linkmtu;
|
||||
|
||||
mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
|
||||
if (mtu > ifmtu || mtu == 0) {
|
||||
@ -814,7 +814,7 @@ skip_ipsec2:;
|
||||
ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
|
||||
}
|
||||
} else {
|
||||
mtu = nd_ifinfo[ifp->if_index].linkmtu;
|
||||
mtu = ND_IFINFO(ifp)->linkmtu;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -98,14 +98,13 @@ int nd6_debug = 0;
|
||||
static int nd6_inuse, nd6_allocated;
|
||||
|
||||
struct llinfo_nd6 llinfo_nd6 = {&llinfo_nd6, &llinfo_nd6};
|
||||
static size_t nd_ifinfo_indexlim = 8;
|
||||
struct nd_ifinfo *nd_ifinfo = NULL;
|
||||
struct nd_drhead nd_defrouter;
|
||||
struct nd_prhead nd_prefix = { 0 };
|
||||
|
||||
int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL;
|
||||
static struct sockaddr_in6 all1_sa;
|
||||
|
||||
static void nd6_setmtu0 __P((struct ifnet *, struct nd_ifinfo *));
|
||||
static void nd6_slowtimo __P((void *));
|
||||
static int regen_tmpaddr __P((struct in6_ifaddr *));
|
||||
|
||||
@ -139,59 +138,42 @@ nd6_init()
|
||||
nd6_slowtimo, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
struct nd_ifinfo *
|
||||
nd6_ifattach(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct nd_ifinfo *nd;
|
||||
|
||||
/*
|
||||
* We have some arrays that should be indexed by if_index.
|
||||
* since if_index will grow dynamically, they should grow too.
|
||||
*/
|
||||
if (nd_ifinfo == NULL || if_index >= nd_ifinfo_indexlim) {
|
||||
size_t n;
|
||||
caddr_t q;
|
||||
nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK);
|
||||
bzero(nd, sizeof(*nd));
|
||||
|
||||
while (if_index >= nd_ifinfo_indexlim)
|
||||
nd_ifinfo_indexlim <<= 1;
|
||||
nd->initialized = 1;
|
||||
|
||||
/* grow nd_ifinfo */
|
||||
n = nd_ifinfo_indexlim * sizeof(struct nd_ifinfo);
|
||||
q = (caddr_t)malloc(n, M_IP6NDP, M_WAITOK);
|
||||
bzero(q, n);
|
||||
if (nd_ifinfo) {
|
||||
bcopy((caddr_t)nd_ifinfo, q, n/2);
|
||||
free((caddr_t)nd_ifinfo, M_IP6NDP);
|
||||
}
|
||||
nd_ifinfo = (struct nd_ifinfo *)q;
|
||||
}
|
||||
|
||||
#define ND nd_ifinfo[ifp->if_index]
|
||||
|
||||
/*
|
||||
* Don't initialize if called twice.
|
||||
* XXX: to detect this, we should choose a member that is never set
|
||||
* before initialization of the ND structure itself. We formaly used
|
||||
* the linkmtu member, which was not suitable because it could be
|
||||
* initialized via "ifconfig mtu".
|
||||
*/
|
||||
if (ND.basereachable)
|
||||
return;
|
||||
|
||||
ND.linkmtu = ifnet_byindex(ifp->if_index)->if_mtu;
|
||||
ND.chlim = IPV6_DEFHLIM;
|
||||
ND.basereachable = REACHABLE_TIME;
|
||||
ND.reachable = ND_COMPUTE_RTIME(ND.basereachable);
|
||||
ND.retrans = RETRANS_TIMER;
|
||||
ND.receivedra = 0;
|
||||
nd->linkmtu = ifnet_byindex(ifp->if_index)->if_mtu;
|
||||
nd->chlim = IPV6_DEFHLIM;
|
||||
nd->basereachable = REACHABLE_TIME;
|
||||
nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
|
||||
nd->retrans = RETRANS_TIMER;
|
||||
nd->receivedra = 0;
|
||||
/*
|
||||
* Note that the default value of ip6_accept_rtadv is 0, which means
|
||||
* we won't accept RAs by default even if we set ND6_IFF_ACCEPT_RTADV
|
||||
* here.
|
||||
*/
|
||||
ND.flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);
|
||||
nd6_setmtu(ifp);
|
||||
#undef ND
|
||||
nd->flags = (ND6_IFF_PERFORMNUD | ND6_IFF_ACCEPT_RTADV);
|
||||
|
||||
/* XXX: we cannot call nd6_setmtu since ifp is not fully initialized */
|
||||
nd6_setmtu0(ifp, nd);
|
||||
|
||||
return nd;
|
||||
}
|
||||
|
||||
void
|
||||
nd6_ifdetach(nd)
|
||||
struct nd_ifinfo *nd;
|
||||
{
|
||||
|
||||
free(nd, M_IP6NDP);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -202,9 +184,21 @@ void
|
||||
nd6_setmtu(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
|
||||
u_long oldmaxmtu = ndi->maxmtu;
|
||||
u_long oldlinkmtu = ndi->linkmtu;
|
||||
|
||||
nd6_setmtu0(ifp, ND_IFINFO(ifp));
|
||||
}
|
||||
|
||||
/* XXX todo: do not maintain copy of ifp->if_mtu in ndi->maxmtu */
|
||||
void
|
||||
nd6_setmtu0(ifp, ndi)
|
||||
struct ifnet *ifp;
|
||||
struct nd_ifinfo *ndi;
|
||||
{
|
||||
u_long oldmaxmtu;
|
||||
u_long oldlinkmtu;
|
||||
|
||||
oldmaxmtu = ndi->maxmtu;
|
||||
oldlinkmtu = ndi->linkmtu;
|
||||
|
||||
switch (ifp->if_type) {
|
||||
case IFT_ARCNET: /* XXX MTU handling needs more work */
|
||||
@ -446,7 +440,7 @@ nd6_timer(ignored_arg)
|
||||
ln = next;
|
||||
continue;
|
||||
}
|
||||
ndi = &nd_ifinfo[ifp->if_index];
|
||||
ndi = ND_IFINFO(ifp);
|
||||
dst = (struct sockaddr_in6 *)rt_key(rt);
|
||||
|
||||
if (ln->ln_expire > time_second) {
|
||||
@ -468,7 +462,7 @@ nd6_timer(ignored_arg)
|
||||
if (ln->ln_asked < nd6_mmaxtries) {
|
||||
ln->ln_asked++;
|
||||
ln->ln_expire = time_second +
|
||||
nd_ifinfo[ifp->if_index].retrans / 1000;
|
||||
ND_IFINFO(ifp)->retrans / 1000;
|
||||
nd6_ns_output(ifp, NULL, &dst->sin6_addr,
|
||||
ln, 0);
|
||||
} else {
|
||||
@ -523,7 +517,7 @@ nd6_timer(ignored_arg)
|
||||
if (ln->ln_asked < nd6_umaxtries) {
|
||||
ln->ln_asked++;
|
||||
ln->ln_expire = time_second +
|
||||
nd_ifinfo[ifp->if_index].retrans / 1000;
|
||||
ND_IFINFO(ifp)->retrans / 1000;
|
||||
nd6_ns_output(ifp, &dst->sin6_addr,
|
||||
&dst->sin6_addr, ln, 0);
|
||||
} else {
|
||||
@ -1079,7 +1073,7 @@ nd6_nud_hint(rt, dst6, force)
|
||||
ln->ln_state = ND6_LLINFO_REACHABLE;
|
||||
if (ln->ln_expire)
|
||||
ln->ln_expire = time_second +
|
||||
nd_ifinfo[rt->rt_ifp->if_index].reachable;
|
||||
ND_IFINFO(rt->rt_ifp)->reachable;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1453,35 +1447,23 @@ nd6_ioctl(cmd, data, ifp)
|
||||
|
||||
break;
|
||||
case OSIOCGIFINFO_IN6:
|
||||
if (!nd_ifinfo || i >= nd_ifinfo_indexlim) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
ndi->ndi.linkmtu = nd_ifinfo[ifp->if_index].linkmtu;
|
||||
ndi->ndi.maxmtu = nd_ifinfo[ifp->if_index].maxmtu;
|
||||
ndi->ndi.basereachable =
|
||||
nd_ifinfo[ifp->if_index].basereachable;
|
||||
ndi->ndi.reachable = nd_ifinfo[ifp->if_index].reachable;
|
||||
ndi->ndi.retrans = nd_ifinfo[ifp->if_index].retrans;
|
||||
ndi->ndi.flags = nd_ifinfo[ifp->if_index].flags;
|
||||
ndi->ndi.recalctm = nd_ifinfo[ifp->if_index].recalctm;
|
||||
ndi->ndi.chlim = nd_ifinfo[ifp->if_index].chlim;
|
||||
ndi->ndi.receivedra = nd_ifinfo[ifp->if_index].receivedra;
|
||||
/* XXX: old ndp(8) assumes a positive value for linkmtu. */
|
||||
bzero(&ndi->ndi, sizeof(ndi->ndi));
|
||||
ndi->ndi.linkmtu = ND_IFINFO(ifp)->linkmtu;
|
||||
ndi->ndi.maxmtu = ND_IFINFO(ifp)->maxmtu;
|
||||
ndi->ndi.basereachable = ND_IFINFO(ifp)->basereachable;
|
||||
ndi->ndi.reachable = ND_IFINFO(ifp)->reachable;
|
||||
ndi->ndi.retrans = ND_IFINFO(ifp)->retrans;
|
||||
ndi->ndi.flags = ND_IFINFO(ifp)->flags;
|
||||
ndi->ndi.recalctm = ND_IFINFO(ifp)->recalctm;
|
||||
ndi->ndi.chlim = ND_IFINFO(ifp)->chlim;
|
||||
ndi->ndi.receivedra = ND_IFINFO(ifp)->receivedra;
|
||||
break;
|
||||
case SIOCGIFINFO_IN6:
|
||||
if (!nd_ifinfo || i >= nd_ifinfo_indexlim) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
ndi->ndi = nd_ifinfo[ifp->if_index];
|
||||
ndi->ndi = *ND_IFINFO(ifp);
|
||||
break;
|
||||
case SIOCSIFINFO_FLAGS:
|
||||
/* XXX: almost all other fields of ndi->ndi is unused */
|
||||
if (!nd_ifinfo || i >= nd_ifinfo_indexlim) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
nd_ifinfo[ifp->if_index].flags = ndi->ndi.flags;
|
||||
ND_IFINFO(ifp)->flags = ndi->ndi.flags;
|
||||
break;
|
||||
case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */
|
||||
/* flush default router list */
|
||||
@ -1824,15 +1806,13 @@ nd6_slowtimo(ignored_arg)
|
||||
void *ignored_arg;
|
||||
{
|
||||
int s = splnet();
|
||||
int i;
|
||||
struct nd_ifinfo *nd6if;
|
||||
struct ifnet *ifp;
|
||||
|
||||
callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
|
||||
nd6_slowtimo, NULL);
|
||||
for (i = 1; i < if_index + 1; i++) {
|
||||
if (!nd_ifinfo || i >= nd_ifinfo_indexlim)
|
||||
continue;
|
||||
nd6if = &nd_ifinfo[i];
|
||||
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list)) {
|
||||
nd6if = ND_IFINFO(ifp);
|
||||
if (nd6if->basereachable && /* already initialized */
|
||||
(nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
|
||||
/*
|
||||
@ -1946,7 +1926,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
||||
}
|
||||
if (!ln || !rt) {
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
|
||||
!(nd_ifinfo[ifp->if_index].flags & ND6_IFF_PERFORMNUD)) {
|
||||
!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
|
||||
log(LOG_DEBUG,
|
||||
"nd6_output: can't allocate llinfo for %s "
|
||||
"(ln=%p, rt=%p)\n",
|
||||
@ -2004,7 +1984,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
|
||||
ln->ln_expire < time_second) {
|
||||
ln->ln_asked++;
|
||||
ln->ln_expire = time_second +
|
||||
nd_ifinfo[ifp->if_index].retrans / 1000;
|
||||
ND_IFINFO(ifp)->retrans / 1000;
|
||||
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ struct nd_ifinfo {
|
||||
int recalctm; /* BaseReacable re-calculation timer */
|
||||
u_int8_t chlim; /* CurHopLimit */
|
||||
u_int8_t receivedra;
|
||||
u_int8_t initialized; /* Flag to see the entry is initialized */
|
||||
/* the following 3 members are for privacy extension for addrconf */
|
||||
u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
|
||||
u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */
|
||||
@ -89,6 +90,16 @@ struct nd_ifinfo {
|
||||
#define ND6_IFF_PERFORMNUD 0x1
|
||||
#define ND6_IFF_ACCEPT_RTADV 0x2
|
||||
|
||||
#ifdef _KERNEL
|
||||
#define ND_IFINFO(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
|
||||
#define IN6_LINKMTU(ifp) \
|
||||
((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \
|
||||
? ND_IFINFO(ifp)->linkmtu \
|
||||
: ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) \
|
||||
? ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu))
|
||||
#endif
|
||||
|
||||
struct in6_nbrinfo {
|
||||
char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
|
||||
struct in6_addr addr; /* IPv6 address of the neighbor */
|
||||
@ -341,7 +352,8 @@ union nd_opts {
|
||||
/* XXX: need nd6_var.h?? */
|
||||
/* nd6.c */
|
||||
void nd6_init __P((void));
|
||||
void nd6_ifattach __P((struct ifnet *));
|
||||
struct nd_ifinfo *nd6_ifattach __P((struct ifnet *));
|
||||
void nd6_ifdetach __P((struct nd_ifinfo *));
|
||||
int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
|
||||
void nd6_option_init __P((void *, int, union nd_opts *));
|
||||
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
|
||||
|
@ -641,7 +641,7 @@ nd6_na_input(m, off, icmp6len)
|
||||
ln->ln_byhint = 0;
|
||||
if (ln->ln_expire) {
|
||||
ln->ln_expire = time_second +
|
||||
nd_ifinfo[rt->rt_ifp->if_index].reachable;
|
||||
ND_IFINFO(rt->rt_ifp)->reachable;
|
||||
}
|
||||
} else {
|
||||
ln->ln_state = ND6_LLINFO_STALE;
|
||||
@ -723,7 +723,7 @@ nd6_na_input(m, off, icmp6len)
|
||||
ln->ln_byhint = 0;
|
||||
if (ln->ln_expire) {
|
||||
ln->ln_expire = time_second +
|
||||
nd_ifinfo[ifp->if_index].reachable;
|
||||
ND_IFINFO(ifp)->reachable;
|
||||
}
|
||||
} else {
|
||||
if (lladdr && llchange) {
|
||||
@ -1081,8 +1081,8 @@ nd6_dad_start(ifa, tick)
|
||||
dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
|
||||
if (tick == NULL) {
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
|
||||
nd6_dad_starttimer(dp,
|
||||
ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
} else {
|
||||
int ntick;
|
||||
|
||||
@ -1174,7 +1174,7 @@ nd6_dad_timer(ifa)
|
||||
*/
|
||||
nd6_dad_ns_output(dp, ifa);
|
||||
nd6_dad_starttimer(dp,
|
||||
nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
|
||||
ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
|
||||
} else {
|
||||
/*
|
||||
* We have transmitted sufficient number of DAD packets.
|
||||
|
@ -202,7 +202,7 @@ nd6_ra_input(m, off, icmp6len)
|
||||
int off, icmp6len;
|
||||
{
|
||||
struct ifnet *ifp = m->m_pkthdr.rcvif;
|
||||
struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
|
||||
struct nd_ifinfo *ndi = ND_IFINFO(ifp);
|
||||
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
|
||||
struct nd_router_advert *nd_ra;
|
||||
struct in6_addr saddr6 = ip6->ip6_src;
|
||||
|
@ -45,77 +45,61 @@
|
||||
#include <netinet6/in6_var.h>
|
||||
#include <netinet6/scope6_var.h>
|
||||
|
||||
struct scope6_id {
|
||||
/*
|
||||
* 16 is correspondent to 4bit multicast scope field.
|
||||
* i.e. from node-local to global with some reserved/unassigned types.
|
||||
*/
|
||||
u_int32_t s6id_list[16];
|
||||
};
|
||||
static size_t if_indexlim = 8;
|
||||
struct scope6_id *scope6_ids = NULL;
|
||||
static struct scope6_id sid_default;
|
||||
#define SID(ifp) \
|
||||
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->scope6_id)
|
||||
|
||||
void
|
||||
scope6_init()
|
||||
{
|
||||
|
||||
bzero(&sid_default, sizeof(sid_default));
|
||||
}
|
||||
|
||||
struct scope6_id *
|
||||
scope6_ifattach(ifp)
|
||||
struct ifnet *ifp;
|
||||
{
|
||||
int s = splnet();
|
||||
struct scope6_id *sid;
|
||||
|
||||
/*
|
||||
* We have some arrays that should be indexed by if_index.
|
||||
* since if_index will grow dynamically, they should grow too.
|
||||
*/
|
||||
if (scope6_ids == NULL || if_index >= if_indexlim) {
|
||||
size_t n;
|
||||
caddr_t q;
|
||||
|
||||
while (if_index >= if_indexlim)
|
||||
if_indexlim <<= 1;
|
||||
|
||||
/* grow scope index array */
|
||||
n = if_indexlim * sizeof(struct scope6_id);
|
||||
/* XXX: need new malloc type? */
|
||||
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
|
||||
bzero(q, n);
|
||||
if (scope6_ids) {
|
||||
bcopy((caddr_t)scope6_ids, q, n/2);
|
||||
free((caddr_t)scope6_ids, M_IFADDR);
|
||||
}
|
||||
scope6_ids = (struct scope6_id *)q;
|
||||
}
|
||||
|
||||
#define SID scope6_ids[ifp->if_index]
|
||||
|
||||
/* don't initialize if called twice */
|
||||
if (SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]) {
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
sid = (struct scope6_id *)malloc(sizeof(*sid), M_IFADDR, M_WAITOK);
|
||||
bzero(sid, sizeof(*sid));
|
||||
|
||||
/*
|
||||
* XXX: IPV6_ADDR_SCOPE_xxx macros are not standard.
|
||||
* Should we rather hardcode here?
|
||||
*/
|
||||
SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index;
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = ifp->if_index;
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index;
|
||||
#ifdef MULTI_SCOPE
|
||||
/* by default, we don't care about scope boundary for these scopes. */
|
||||
SID.s6id_list[IPV6_ADDR_SCOPE_SITELOCAL] = 1;
|
||||
SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1;
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL] = 1;
|
||||
sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1;
|
||||
#endif
|
||||
#undef SID
|
||||
|
||||
splx(s);
|
||||
return sid;
|
||||
}
|
||||
|
||||
void
|
||||
scope6_ifdetach(sid)
|
||||
struct scope6_id *sid;
|
||||
{
|
||||
|
||||
free(sid, M_IFADDR);
|
||||
}
|
||||
|
||||
int
|
||||
scope6_set(ifp, idlist)
|
||||
struct ifnet *ifp;
|
||||
u_int32_t *idlist;
|
||||
struct scope6_id *idlist;
|
||||
{
|
||||
int i, s;
|
||||
int error = 0;
|
||||
struct scope6_id *sid = SID(ifp);
|
||||
|
||||
if (scope6_ids == NULL) /* paranoid? */
|
||||
if (!sid) /* paranoid? */
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
@ -131,10 +115,10 @@ scope6_set(ifp, idlist)
|
||||
s = splnet();
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (idlist[i] &&
|
||||
idlist[i] != scope6_ids[ifp->if_index].s6id_list[i]) {
|
||||
if (idlist->s6id_list[i] &&
|
||||
idlist->s6id_list[i] != sid->s6id_list[i]) {
|
||||
if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
|
||||
idlist[i] > if_index) {
|
||||
idlist->s6id_list[i] > if_index) {
|
||||
/*
|
||||
* XXX: theoretically, there should be no
|
||||
* relationship between link IDs and interface
|
||||
@ -150,7 +134,7 @@ scope6_set(ifp, idlist)
|
||||
* but we simply set the new value in this initial
|
||||
* implementation.
|
||||
*/
|
||||
scope6_ids[ifp->if_index].s6id_list[i] = idlist[i];
|
||||
sid->s6id_list[i] = idlist->s6id_list[i];
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
@ -161,13 +145,14 @@ scope6_set(ifp, idlist)
|
||||
int
|
||||
scope6_get(ifp, idlist)
|
||||
struct ifnet *ifp;
|
||||
u_int32_t *idlist;
|
||||
struct scope6_id *idlist;
|
||||
{
|
||||
if (scope6_ids == NULL) /* paranoid? */
|
||||
struct scope6_id *sid = SID(ifp);
|
||||
|
||||
if (sid == NULL) /* paranoid? */
|
||||
return (EINVAL);
|
||||
|
||||
bcopy(scope6_ids[ifp->if_index].s6id_list, idlist,
|
||||
sizeof(scope6_ids[ifp->if_index].s6id_list));
|
||||
*idlist = *sid;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -237,31 +222,45 @@ in6_addr2scopeid(ifp, addr)
|
||||
struct ifnet *ifp; /* must not be NULL */
|
||||
struct in6_addr *addr; /* must not be NULL */
|
||||
{
|
||||
int scope = in6_addrscope(addr);
|
||||
int scope;
|
||||
struct scope6_id *sid = SID(ifp);
|
||||
|
||||
if (scope6_ids == NULL) /* paranoid? */
|
||||
return (0); /* XXX */
|
||||
if (ifp->if_index >= if_indexlim)
|
||||
return (0); /* XXX */
|
||||
#ifdef DIAGNOSTIC
|
||||
if (sid == NULL) { /* should not happen */
|
||||
panic("in6_addr2zoneid: scope array is NULL");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* special case: the loopback address can only belong to a loopback
|
||||
* interface.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LOOPBACK(addr)) {
|
||||
if (!(ifp->if_flags & IFF_LOOPBACK))
|
||||
return (-1);
|
||||
else
|
||||
return (0); /* there's no ambiguity */
|
||||
}
|
||||
|
||||
scope = in6_addrscope(addr);
|
||||
|
||||
#define SID scope6_ids[ifp->if_index]
|
||||
switch(scope) {
|
||||
case IPV6_ADDR_SCOPE_NODELOCAL:
|
||||
return (-1); /* XXX: is this an appropriate value? */
|
||||
|
||||
case IPV6_ADDR_SCOPE_LINKLOCAL:
|
||||
return (SID.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]);
|
||||
return (sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]);
|
||||
|
||||
case IPV6_ADDR_SCOPE_SITELOCAL:
|
||||
return (SID.s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]);
|
||||
return (sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]);
|
||||
|
||||
case IPV6_ADDR_SCOPE_ORGLOCAL:
|
||||
return (SID.s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]);
|
||||
return (sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]);
|
||||
|
||||
default:
|
||||
return (0); /* XXX: treat as global. */
|
||||
}
|
||||
#undef SID
|
||||
}
|
||||
|
||||
void
|
||||
@ -269,28 +268,27 @@ scope6_setdefault(ifp)
|
||||
struct ifnet *ifp; /* note that this might be NULL */
|
||||
{
|
||||
/*
|
||||
* Currently, this function just set the default "link" according to
|
||||
* the given interface.
|
||||
* Currently, this function just set the default "interfaces"
|
||||
* and "links" according to the given interface.
|
||||
* We might eventually have to separate the notion of "link" from
|
||||
* "interface" and provide a user interface to set the default.
|
||||
*/
|
||||
if (ifp) {
|
||||
scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
|
||||
sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] =
|
||||
ifp->if_index;
|
||||
sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
|
||||
ifp->if_index;
|
||||
} else {
|
||||
scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
|
||||
sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = 0;
|
||||
sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
scope6_get_default(idlist)
|
||||
u_int32_t *idlist;
|
||||
struct scope6_id *idlist;
|
||||
{
|
||||
if (scope6_ids == NULL) /* paranoid? */
|
||||
return (EINVAL);
|
||||
|
||||
bcopy(scope6_ids[0].s6id_list, idlist,
|
||||
sizeof(scope6_ids[0].s6id_list));
|
||||
*idlist = sid_default;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -299,5 +297,12 @@ u_int32_t
|
||||
scope6_addr2default(addr)
|
||||
struct in6_addr *addr;
|
||||
{
|
||||
return (scope6_ids[0].s6id_list[in6_addrscope(addr)]);
|
||||
/*
|
||||
* special case: The loopback address should be considered as
|
||||
* link-local, but there's no ambiguity in the syntax.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LOOPBACK(addr))
|
||||
return (0);
|
||||
|
||||
return (sid_default.s6id_list[in6_addrscope(addr)]);
|
||||
}
|
||||
|
@ -34,11 +34,21 @@
|
||||
#define _NETINET6_SCOPE6_VAR_H_
|
||||
|
||||
#ifdef _KERNEL
|
||||
void scope6_ifattach __P((struct ifnet *));
|
||||
int scope6_set __P((struct ifnet *, u_int32_t *));
|
||||
int scope6_get __P((struct ifnet *, u_int32_t *));
|
||||
struct scope6_id {
|
||||
/*
|
||||
* 16 is correspondent to 4bit multicast scope field.
|
||||
* i.e. from node-local to global with some reserved/unassigned types.
|
||||
*/
|
||||
u_int32_t s6id_list[16];
|
||||
};
|
||||
|
||||
void scope6_init __P((void));
|
||||
struct scope6_id *scope6_ifattach __P((struct ifnet *));
|
||||
void scope6_ifdetach __P((struct scope6_id *));
|
||||
int scope6_set __P((struct ifnet *, struct scope6_id *));
|
||||
int scope6_get __P((struct ifnet *, struct scope6_id *));
|
||||
void scope6_setdefault __P((struct ifnet *));
|
||||
int scope6_get_default __P((u_int32_t *));
|
||||
int scope6_get_default __P((struct scope6_id *));
|
||||
u_int32_t scope6_in6_addrscope __P((struct in6_addr *));
|
||||
u_int32_t scope6_addr2default __P((struct in6_addr *));
|
||||
#endif /* _KERNEL */
|
||||
|
@ -45,6 +45,7 @@
|
||||
* Forward structure declarations for function prototypes [sic].
|
||||
*/
|
||||
struct mbuf;
|
||||
struct ifnet;
|
||||
|
||||
struct domain {
|
||||
int dom_family; /* AF_xxx */
|
||||
@ -61,6 +62,9 @@ struct domain {
|
||||
(void **, int);
|
||||
int dom_rtoffset; /* an arg to rtattach, in bits */
|
||||
int dom_maxrtkey; /* for routing layer */
|
||||
void *(*dom_ifattach)(struct ifnet *);
|
||||
void (*dom_ifdetach)(struct ifnet *, void *);
|
||||
/* af-dependent data on ifnet */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
@ -151,6 +151,7 @@ enum sysinit_sub_id {
|
||||
SI_SUB_PROTO_BEGIN = 0x8000000, /* XXX: set splimp (kludge)*/
|
||||
SI_SUB_PROTO_IF = 0x8400000, /* interfaces*/
|
||||
SI_SUB_PROTO_DOMAIN = 0x8800000, /* domains (address families?)*/
|
||||
SI_SUB_PROTO_IFATTACHDOMAIN = 0x8800001, /* domain dependent data init*/
|
||||
SI_SUB_PROTO_END = 0x8ffffff, /* XXX: set splx (kludge)*/
|
||||
SI_SUB_KPROF = 0x9000000, /* kernel profiling*/
|
||||
SI_SUB_KICK_SCHEDULER = 0xa000000, /* start the timeout events*/
|
||||
|
Loading…
Reference in New Issue
Block a user