From: | Hiroki Sato <hrs@xxxxxxxxxx> |
Date: | Sun, 09 Jan 2005 05:06:39 +0900 (JST) |
Hi, Here are patches to add in6_domifattach(), in6_domifdetach(), and ifp->if_afdata from KAME. I am working on merging IPv6 API transition (RFC2292 -> RFC3542) and implementation of source address selection in RFC 3484. These are preparation for them. -- | Hiroki SATO
- Nuke #ifdef SCOPEDROUTING. It was never enabled and is useless now[1]. - Add in6_domifattach(), in6_domifdetach(), and ifp->if_afdata[2]. - ANSIfy. Obtained from: KAME via FreeBSD References (FreeBSD): net/ if.c 1.168[2] if_var.h 1.59[2] netinet/ icmp6.h 1.12[2] tcp_input.c 1.209[2] netinet6/ icmp6.c 1.38[1], 1.39[2] in6.c 1.30[1], 1.31[2] ip6_forward.c 1.20[1] in6_gif.c 1.15[1] in6_proto.c 1.25[2] in6_ifattach.c 1.17[1], 1.18[2] ip6_input.c 1.53[1], 1.57[2] ip6_output.c 1.58[1], 1.59[2] in6_src.c 1.14[2] in6_var.h 1.14[2] nd6.c 1.30[1], 1.32[2] nd6.h 1.13[2] nd6_nbr.c 1.19[2] nd6_rtr.c 1.20[2] scope6.c 1.8[2] scope6_var.h 1.3[2] sys/ domain.h 1.18[2] kernel.h 1.113[2]
Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.24 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.24 if.c --- net/if.c 6 Jan 2005 09:14:13 -0000 1.24 +++ net/if.c 8 Jan 2005 16:18:10 -0000 @@ -53,6 +53,7 @@ #include <sys/sockio.h> #include <sys/syslog.h> #include <sys/sysctl.h> +#include <sys/domain.h> #include <net/if.h> #include <net/if_arp.h> @@ -83,6 +84,8 @@ * System initialization */ +static void if_attachdomain(void *); +static void if_attachdomain1(struct ifnet *); static int ifconf (u_long, caddr_t, struct thread *); static void ifinit (void *); static void if_qflush (struct ifqueue *); @@ -237,10 +240,45 @@ EVENTHANDLER_INVOKE(ifnet_attach_event, ifp); + if (domains) + if_attachdomain1(ifp); + /* Announce the interface. */ rt_ifannouncemsg(ifp, IFAN_ARRIVAL); } +static void +if_attachdomain(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(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. @@ -252,6 +290,7 @@ struct radix_node_head *rnh; int s; int i; + struct domain *dp; EVENTHANDLER_INVOKE(ifnet_detach_event, ifp); @@ -321,6 +360,12 @@ /* 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]); + } + ifindex2ifnet[ifp->if_index] = NULL; TAILQ_REMOVE(&ifnet, ifp, if_link); Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.20 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.20 if_var.h --- net/if_var.h 28 Dec 2004 08:09:59 -0000 1.20 +++ net/if_var.h 8 Jan 2005 16:51:56 -0000 @@ -174,6 +174,7 @@ struct ifqueue if_snd; /* output queue */ struct ifprefixhead if_prefixhead; /* list of prefixes per if */ const uint8_t *if_broadcastaddr; + void *if_afdata[AF_MAX]; }; typedef void if_init_f_t (void *); Index: netinet/icmp6.h =================================================================== RCS file: /cvs/src/sys/netinet/icmp6.h,v retrieving revision 1.5 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.5 icmp6.h --- netinet/icmp6.h 21 Dec 2004 02:54:15 -0000 1.5 +++ netinet/icmp6.h 8 Jan 2005 15:40:31 -0000 @@ -684,11 +684,8 @@ /* 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 (0) #define icmp6_ifoutstat_inc(ifp, type, code) \ @@ -696,7 +693,7 @@ 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) \ Index: netinet/tcp_input.c =================================================================== RCS file: /cvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.50 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.50 tcp_input.c --- netinet/tcp_input.c 8 Jan 2005 09:26:32 -0000 1.50 +++ netinet/tcp_input.c 8 Jan 2005 19:09:58 -0000 @@ -2920,8 +2920,7 @@ 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 { Index: netinet6/icmp6.c =================================================================== RCS file: /cvs/src/sys/netinet6/icmp6.c,v retrieving revision 1.16 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.16 icmp6.c --- netinet6/icmp6.c 6 Jan 2005 17:59:32 -0000 1.16 +++ netinet6/icmp6.c 8 Jan 2005 19:09:58 -0000 @@ -1055,7 +1055,6 @@ icmp6dst.sin6_addr = *finaldst; icmp6dst.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, &icmp6dst.sin6_addr); -#ifndef SCOPEDROUTING if (in6_embedscope(&icmp6dst.sin6_addr, &icmp6dst, NULL, NULL)) { /* should be impossbile */ @@ -1063,7 +1062,6 @@ "icmp6_notify_error: in6_embedscope failed\n")); goto freeit; } -#endif /* * retrieve parameters from the inner IPv6 header, and convert @@ -1075,7 +1073,6 @@ icmp6src.sin6_addr = eip6->ip6_src; icmp6src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, &icmp6src.sin6_addr); -#ifndef SCOPEDROUTING if (in6_embedscope(&icmp6src.sin6_addr, &icmp6src, NULL, NULL)) { /* should be impossbile */ @@ -1083,7 +1080,6 @@ "icmp6_notify_error: in6_embedscope failed\n")); goto freeit; } -#endif icmp6src.sin6_flowinfo = (eip6->ip6_flow & IPV6_FLOWLABEL_MASK); @@ -1277,18 +1273,14 @@ subjlen, (caddr_t)&sin6.sin6_addr); sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, &sin6.sin6_addr); -#ifndef SCOPEDROUTING in6_embedscope(&sin6.sin6_addr, &sin6, NULL, NULL); -#endif bzero(&sin6_d, sizeof(sin6_d)); sin6_d.sin6_family = AF_INET6; /* not used, actually */ sin6_d.sin6_len = sizeof(sin6_d); /* ditto */ sin6_d.sin6_addr = ip6->ip6_dst; sin6_d.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst); -#ifndef SCOPEDROUTING in6_embedscope(&sin6_d.sin6_addr, &sin6_d, NULL, NULL); -#endif subj = (char *)&sin6; if (SA6_ARE_ADDR_EQUAL(&sin6, &sin6_d)) break; @@ -2139,7 +2131,7 @@ 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; Index: netinet6/in6.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6.c,v retrieving revision 1.12 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.12 in6.c --- netinet6/in6.c 6 Jan 2005 17:59:32 -0000 1.12 +++ netinet6/in6.c 8 Jan 2005 19:09:58 -0000 @@ -89,11 +89,9 @@ #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/if_ether.h> -#ifndef SCOPEDROUTING #include <netinet/in_systm.h> #include <netinet/ip.h> #include <netinet/in_pcb.h> -#endif #include <netinet/ip6.h> #include <netinet6/ip6_var.h> @@ -102,9 +100,7 @@ #include <netinet6/ip6_mroute.h> #include <netinet6/in6_ifattach.h> #include <netinet6/scope6_var.h> -#ifndef SCOPEDROUTING #include <netinet6/in6_pcb.h> -#endif #include <net/net_osdep.h> @@ -415,13 +411,16 @@ case SIOCSSCOPE6: if (!privileged) return(EPERM); - return(scope6_set(ifp, ifr->ifr_ifru.ifru_scope_id)); + return(scope6_set(ifp, + (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id)); break; case SIOCGSCOPE6: - return(scope6_get(ifp, ifr->ifr_ifru.ifru_scope_id)); + return(scope6_get(ifp, + (struct scope6_id *)ifr->ifr_ifru.ifru_scope_id)); break; case SIOCGSCOPE6DEF: - return(scope6_get_default(ifr->ifr_ifru.ifru_scope_id)); + return(scope6_get_default((struct scope6_id *) + ifr->ifr_ifru.ifru_scope_id)); break; } @@ -557,26 +556,17 @@ 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: @@ -824,23 +814,19 @@ (dst6.sin6_family == AF_INET6)) { int scopeid; -#ifndef SCOPEDROUTING if ((error = in6_recoverscope(&dst6, &ifra->ifra_dstaddr.sin6_addr, ifp)) != 0) return(error); -#endif scopeid = in6_addr2scopeid(ifp, &dst6.sin6_addr); if (dst6.sin6_scope_id == 0) /* user omit to specify the ID. */ dst6.sin6_scope_id = scopeid; else if (dst6.sin6_scope_id != scopeid) return(EINVAL); /* scope ID mismatch. */ -#ifndef SCOPEDROUTING if ((error = in6_embedscope(&dst6.sin6_addr, &dst6, NULL, NULL)) != 0) return(error); dst6.sin6_scope_id = 0; /* XXX */ -#endif } /* * The destination address can be specified only for a p2p or a @@ -1129,13 +1115,6 @@ 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 * disable DAD. @@ -1467,7 +1446,6 @@ break; bcopy(IFA_IN6(ifa), &candidate, sizeof(candidate)); -#ifndef SCOPEDROUTING /* * XXX: this is adhoc, but is necessary to allow * a user to specify fe80::/64 (not /10) for a @@ -1475,7 +1453,6 @@ */ if (IN6_IS_ADDR_LINKLOCAL(&candidate)) candidate.s6_addr16[1] = 0; -#endif candidate.s6_addr32[0] &= mask.s6_addr32[0]; candidate.s6_addr32[1] &= mask.s6_addr32[1]; candidate.s6_addr32[2] &= mask.s6_addr32[2]; @@ -1488,24 +1465,19 @@ ia = ifa2ia6(ifa); if (cmd == SIOCGLIFADDR) { -#ifndef SCOPEDROUTING struct sockaddr_in6 *s6; -#endif /* fill in the if_laddrreq structure */ bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin6_len); -#ifndef SCOPEDROUTING /* XXX see above */ s6 = (struct sockaddr_in6 *)&iflr->addr; if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) { s6->sin6_addr.s6_addr16[1] = 0; s6->sin6_scope_id = in6_addr2scopeid(ifp, &s6->sin6_addr); } -#endif if ((ifp->if_flags & IFF_POINTOPOINT) != 0) { bcopy(&ia->ia_dstaddr, &iflr->dstaddr, ia->ia_dstaddr.sin6_len); -#ifndef SCOPEDROUTING /* XXX see above */ s6 = (struct sockaddr_in6 *)&iflr->dstaddr; if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) { s6->sin6_addr.s6_addr16[1] = 0; @@ -1513,7 +1485,6 @@ in6_addr2scopeid(ifp, &s6->sin6_addr); } -#endif } else bzero(&iflr->dstaddr, sizeof(iflr->dstaddr)); @@ -1832,9 +1803,6 @@ for (ia = in6_ifaddr; ia; ia = ia->ia_next) { if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &sa6->sin6_addr) && -#ifdef SCOPEDROUTING - ia->ia_addr.sin6_scope_id == sa6->sin6_scope_id && -#endif (ia->ia6_flags & IN6_IFF_DEPRECATED) != 0) return(1); /* true */ @@ -2349,13 +2317,46 @@ 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; } if (maxmtu) /* update only when maxmtu is positive */ in6_maxmtu = maxmtu; } +void * +in6_domifattach(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(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 Index: netinet6/in6_gif.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_gif.c,v retrieving revision 1.11 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.11 in6_gif.c --- netinet6/in6_gif.c 6 Jan 2005 17:59:32 -0000 1.11 +++ netinet6/in6_gif.c 8 Jan 2005 19:09:58 -0000 @@ -323,9 +323,7 @@ sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_addr = ip6->ip6_src; -#ifndef SCOPEDROUTING sin6.sin6_scope_id = 0; /* XXX */ -#endif rt = rtpurelookup((struct sockaddr *)&sin6); if (rt == NULL || rt->rt_ifp != ifp) { Index: netinet6/in6_ifattach.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_ifattach.c,v retrieving revision 1.11 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.11 in6_ifattach.c --- netinet6/in6_ifattach.c 6 Jan 2005 17:59:32 -0000 1.11 +++ netinet6/in6_ifattach.c 8 Jan 2005 19:09:58 -0000 @@ -61,10 +61,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 @@ -437,11 +433,7 @@ ifra.ifra_addr.sin6_family = AF_INET6; ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6); ifra.ifra_addr.sin6_addr.s6_addr16[0] = htons(0xfe80); -#ifdef SCOPEDROUTING - ifra.ifra_addr.sin6_addr.s6_addr16[1] = 0 -#else ifra.ifra_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); /* XXX */ -#endif ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0; if ((ifp->if_flags & IFF_LOOPBACK) != 0) { ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0; @@ -453,18 +445,11 @@ return -1; } } -#ifdef SCOPEDROUTING - ifra.ifra_addr.sin6_scope_id = - in6_addr2scopeid(ifp, &ifra.ifra_addr.sin6_addr); -#endif 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 accound 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; @@ -717,7 +702,6 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp) /* secondary EUI64 source */ { - static size_t if_indexlim = 8; struct in6_ifaddr *ia; struct in6_addr in6; @@ -733,50 +717,6 @@ } /* - * 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 */ switch (ifp->if_type) { @@ -837,20 +777,6 @@ /* 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); } /* @@ -967,7 +893,7 @@ 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) { @@ -988,9 +914,9 @@ void in6_tmpaddrtimer(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, @@ -999,8 +925,8 @@ 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. Index: netinet6/in6_pcb.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_pcb.c,v retrieving revision 1.21 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.21 in6_pcb.c --- netinet6/in6_pcb.c 6 Jan 2005 17:59:32 -0000 1.21 +++ netinet6/in6_pcb.c 8 Jan 2005 19:09:58 -0000 @@ -569,7 +569,7 @@ 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); } Index: netinet6/in6_proto.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_proto.c,v retrieving revision 1.7 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.7 in6_proto.c --- netinet6/in6_proto.c 3 Jan 2005 22:11:51 -0000 1.7 +++ netinet6/in6_proto.c 8 Jan 2005 14:41:23 -0000 @@ -264,7 +264,8 @@ (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); Index: netinet6/in6_src.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_src.c,v retrieving revision 1.9 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.9 in6_src.c --- netinet6/in6_src.c 6 Jan 2005 17:59:32 -0000 1.9 +++ netinet6/in6_src.c 8 Jan 2005 19:09:58 -0000 @@ -316,7 +316,7 @@ 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); } Index: netinet6/in6_var.h =================================================================== RCS file: /cvs/src/sys/netinet6/in6_var.h,v retrieving revision 1.5 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.5 in6_var.h --- netinet6/in6_var.h 2 Aug 2004 13:22:33 -0000 1.5 +++ netinet6/in6_var.h 8 Jan 2005 14:43:43 -0000 @@ -91,6 +91,15 @@ 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 @@ -447,18 +456,11 @@ #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 (0) extern struct ifqueue ip6intrq; /* IP6 packet input queue */ @@ -580,6 +582,8 @@ int in6if_do_dad (struct ifnet *); void in6_purgeif (struct ifnet *); void in6_savemkludge (struct in6_ifaddr *); +void *in6_domifattach (struct ifnet *); +void in6_domifdetach (struct ifnet *, void *); void in6_setmaxmtu (void); void in6_restoremkludge (struct in6_ifaddr *, struct ifnet *); void in6_purgemkludge (struct ifnet *); Index: netinet6/ip6_forward.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v retrieving revision 1.10 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.10 ip6_forward.c --- netinet6/ip6_forward.c 15 Oct 2004 22:59:10 -0000 1.10 +++ netinet6/ip6_forward.c 6 Jan 2005 20:55:09 -0000 @@ -503,14 +503,12 @@ } else origifp = rt->rt_ifp; -#ifndef SCOPEDROUTING /* * clear embedded scope identifiers if necessary. * in6_clearscope will touch the addresses only when necessary. */ in6_clearscope(&ip6->ip6_src); in6_clearscope(&ip6->ip6_dst); -#endif /* * Run through list of hooks for output packets. Index: netinet6/ip6_input.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_input.c,v retrieving revision 1.23 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.23 ip6_input.c --- netinet6/ip6_input.c 3 Jan 2005 22:03:26 -0000 1.23 +++ netinet6/ip6_input.c 8 Jan 2005 14:44:49 -0000 @@ -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> @@ -197,6 +198,7 @@ } netisr_register(NETISR_IPV6, cpu0_portfn, ip6_input); + scope6_init(); nd6_init(); frag6_init(); /* @@ -212,13 +214,6 @@ static void ip6_init2(void *dummy) { - - /* - * to route local address of p2p link to loopback, - * assign loopback address first. - */ - in6_ifattach(&loif[0], NULL); - /* nd6_timer_init */ callout_init(&nd6_timer_ch); callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL); @@ -534,10 +529,6 @@ dst6->sin6_len = sizeof(struct sockaddr_in6); dst6->sin6_family = AF_INET6; dst6->sin6_addr = ip6->ip6_dst; -#ifdef SCOPEDROUTING - ip6_forward_rt.ro_dst.sin6_scope_id = - in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst); -#endif rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING); } Index: netinet6/ip6_output.c =================================================================== RCS file: /cvs/src/sys/netinet6/ip6_output.c,v retrieving revision 1.16 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.16 ip6_output.c --- netinet6/ip6_output.c 6 Jan 2005 17:59:32 -0000 1.16 +++ netinet6/ip6_output.c 8 Jan 2005 19:09:58 -0000 @@ -521,11 +521,6 @@ dst->sin6_family = AF_INET6; dst->sin6_len = sizeof(struct sockaddr_in6); dst->sin6_addr = ip6->ip6_dst; -#ifdef SCOPEDROUTING - /* XXX: sin6_scope_id should already be fixed at this point */ - if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr)) - dst->sin6_scope_id = ntohs(dst->sin6_addr.s6_addr16[1]); -#endif } #if defined(IPSEC) || defined(FAST_IPSEC) if (needipsec && needipsectun) { @@ -788,7 +783,7 @@ } } 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) { @@ -808,7 +803,7 @@ ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */ } } else { - mtu = nd_ifinfo[ifp->if_index].linkmtu; + mtu = ND_IFINFO(ifp)->linkmtu; } /* @@ -855,14 +850,12 @@ } else origifp = ifp; -#ifndef SCOPEDROUTING /* * clear embedded scope identifiers if necessary. * in6_clearscope will touch the addresses only when necessary. */ in6_clearscope(&ip6->ip6_src); in6_clearscope(&ip6->ip6_dst); -#endif /* * Check with the firewall... @@ -2496,14 +2489,12 @@ #endif ip6 = mtod(copym, struct ip6_hdr *); -#ifndef SCOPEDROUTING /* * clear embedded scope identifiers if necessary. * in6_clearscope will touch the addresses only when necessary. */ in6_clearscope(&ip6->ip6_src); in6_clearscope(&ip6->ip6_dst); -#endif (void)if_simloop(ifp, copym, dst->sin6_family, NULL); } Index: netinet6/nd6.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6.c,v retrieving revision 1.14 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.14 nd6.c --- netinet6/nd6.c 6 Jan 2005 17:59:32 -0000 1.14 +++ netinet6/nd6.c 8 Jan 2005 19:12:28 -0000 @@ -106,14 +106,13 @@ 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 (struct ifnet *, struct nd_ifinfo *); static void nd6_slowtimo (void *); static int regen_tmpaddr (struct in6_ifaddr *); @@ -148,58 +147,39 @@ nd6_slowtimo, NULL); } -void +struct nd_ifinfo * { + 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; - - while (if_index >= nd_ifinfo_indexlim) - nd_ifinfo_indexlim <<= 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; - } + nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK); + bzero(nd, sizeof(*nd)); -#define ND nd_ifinfo[ifp->if_index] + nd->initialized = 1; - /* - * 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 = ifindex2ifnet[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 = ifindex2ifnet[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(struct nd_ifinfo *nd) +{ + free(nd, M_IP6NDP); } /* @@ -209,9 +189,18 @@ void nd6_setmtu(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(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 */ @@ -443,7 +432,7 @@ 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) { @@ -465,7 +454,7 @@ 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 { @@ -520,7 +509,7 @@ 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 { @@ -791,9 +780,7 @@ sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = *addr6; -#ifdef SCOPEDROUTING - sin6.sin6_scope_id = in6_addr2scopeid(ifp, addr6); -#endif + if (create) rt = rtlookup((struct sockaddr *)&sin6); else @@ -1066,7 +1053,7 @@ 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 @@ -1439,35 +1426,23 @@ 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 */ @@ -1808,15 +1783,13 @@ nd6_slowtimo(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) { /* @@ -1922,7 +1895,7 @@ } 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", @@ -1980,7 +1953,7 @@ 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); } } Index: netinet6/nd6.h =================================================================== RCS file: /cvs/src/sys/netinet6/nd6.h,v retrieving revision 1.5 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.5 nd6.h --- netinet6/nd6.h 30 Dec 2004 02:26:12 -0000 1.5 +++ netinet6/nd6.h 8 Jan 2005 14:58:54 -0000 @@ -81,6 +81,7 @@ 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) */ @@ -90,6 +91,16 @@ #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 */ @@ -342,7 +353,8 @@ /* XXX: need nd6_var.h?? */ /* nd6.c */ void nd6_init (void); -void nd6_ifattach (struct ifnet *); +struct nd_ifinfo *nd6_ifattach (struct ifnet *); +void nd6_ifdetach (struct nd_ifinfo *); int nd6_is_addr_neighbor (struct sockaddr_in6 *, struct ifnet *); void nd6_option_init (void *, int, union nd_opts *); struct nd_opt_hdr *nd6_option (union nd_opts *); Index: netinet6/nd6_nbr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_nbr.c,v retrieving revision 1.9 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.9 nd6_nbr.c --- netinet6/nd6_nbr.c 6 Jan 2005 17:59:32 -0000 1.9 +++ netinet6/nd6_nbr.c 8 Jan 2005 19:09:59 -0000 @@ -657,7 +657,7 @@ 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; ln->ln_expire = time_second + nd6_gctimer; @@ -738,7 +738,7 @@ 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) { @@ -1088,8 +1088,8 @@ 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; @@ -1178,8 +1178,8 @@ * We have more NS to go. Send NS packet for DAD. */ 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 { /* * We have transmitted sufficient number of DAD packets. Index: netinet6/nd6_rtr.c =================================================================== RCS file: /cvs/src/sys/netinet6/nd6_rtr.c,v retrieving revision 1.7 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.7 nd6_rtr.c --- netinet6/nd6_rtr.c 30 Dec 2004 02:26:12 -0000 1.7 +++ netinet6/nd6_rtr.c 8 Jan 2005 15:00:51 -0000 @@ -205,7 +205,7 @@ 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; Index: netinet6/scope6.c =================================================================== RCS file: /cvs/src/sys/netinet6/scope6.c,v retrieving revision 1.3 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.3 scope6.c --- netinet6/scope6.c 20 May 2004 18:30:36 -0000 1.3 +++ netinet6/scope6.c 8 Jan 2005 17:25:59 -0000 @@ -46,74 +46,55 @@ #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(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(struct scope6_id *sid) +{ + free(sid, M_IFADDR); } int -scope6_set(struct ifnet *ifp, u_int32_t *idlist) +scope6_set(struct ifnet *ifp, 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); /* @@ -129,10 +110,10 @@ 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 @@ -148,7 +129,7 @@ * 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); @@ -157,13 +138,14 @@ } int -scope6_get(struct ifnet *ifp, u_int32_t *idlist) +scope6_get(struct ifnet *ifp, 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); } @@ -231,58 +213,71 @@ in6_addr2scopeid(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 scope6_setdefault(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 { + sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = 0; + sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0; } - else - scope6_ids[0].s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0; } int -scope6_get_default(u_int32_t *idlist) +scope6_get_default(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); } @@ -290,5 +285,12 @@ u_int32_t scope6_addr2default(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)]); } Index: netinet6/scope6_var.h =================================================================== RCS file: /cvs/src/sys/netinet6/scope6_var.h,v retrieving revision 1.3 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.3 scope6_var.h --- netinet6/scope6_var.h 23 Aug 2003 11:02:46 -0000 1.3 +++ netinet6/scope6_var.h 8 Jan 2005 15:12:40 -0000 @@ -35,11 +35,21 @@ #define _NETINET6_SCOPE6_VAR_H_ #ifdef _KERNEL -void scope6_ifattach (struct ifnet *); -int scope6_set (struct ifnet *, u_int32_t *); -int scope6_get (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 (void); +struct scope6_id *scope6_ifattach (struct ifnet *); +void scope6_ifdetach (struct scope6_id *); +int scope6_set (struct ifnet *, struct scope6_id *); +int scope6_get (struct ifnet *, struct scope6_id *); void scope6_setdefault (struct ifnet *); -int scope6_get_default (u_int32_t *); +int scope6_get_default (struct scope6_id *); u_int32_t scope6_in6_addrscope (struct in6_addr *); u_int32_t scope6_addr2default (struct in6_addr *); #endif /* _KERNEL */ Index: sys/domain.h =================================================================== RCS file: /cvs/src/sys/sys/domain.h,v retrieving revision 1.4 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.4 domain.h --- sys/domain.h 14 Dec 2004 18:46:08 -0000 1.4 +++ sys/domain.h 8 Jan 2005 15:57:52 -0000 @@ -46,6 +46,7 @@ * Forward structure declarations for function prototypes [sic]. */ struct mbuf; +struct ifnet; struct domain { int dom_family; /* AF_xxx */ @@ -61,6 +62,9 @@ int (*dom_rtattach)(void **, int); /* initialize routing table */ 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 Index: sys/kernel.h =================================================================== RCS file: /cvs/src/sys/sys/kernel.h,v retrieving revision 1.11 diff -d -u -I\$FreeBSD:.*\$ -I\$NetBSD:.*\$ -I\$OpenBSD:.*\$ -I\$DragonFly:.*\$ -I\$Id:.*\$ -I\$hrs:.*\$ -r1.11 kernel.h --- sys/kernel.h 30 Mar 2004 17:18:58 -0000 1.11 +++ sys/kernel.h 8 Jan 2005 15:58:48 -0000 @@ -140,6 +140,7 @@ 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*/
Attachment:
pgp00013.pgp
Description: PGP signature