in6_ifattach.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,344 行 · 第 1/3 页
C
1,344 行
ip6_sprintf(&mltaddr.sin6_addr), error)); } } }}voidin6_nigroup_detach(name, namelen) const char *name; int namelen;{ struct ifnet *ifp; struct sockaddr_in6 mltaddr; struct in6_multi *in6m; bzero(&mltaddr, sizeof(mltaddr)); mltaddr.sin6_family = AF_INET6; mltaddr.sin6_len = sizeof(struct sockaddr_in6); if (in6_nigroup(NULL, name, namelen, &mltaddr.sin6_addr) != 0) return;#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) for (ifp = ifnet; ifp; ifp = ifp->if_next)#else for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)#endif { mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index); IN6_LOOKUP_MULTI(mltaddr.sin6_addr, ifp, in6m); if (in6m) in6_delmulti(in6m); }}#endif/* * XXX multiple loopback interface needs more care. for instance, * nodelocal address needs to be configured onto only one of them. * XXX multiple link-local address case */voidin6_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; /* some of the interfaces are inherently not IPv6 capable */ switch (ifp->if_type) {#ifdef IFT_BRIDGE /* OpenBSD 2.8 */ case IFT_BRIDGE: return;#endif#if defined(__OpenBSD__) || defined(__NetBSD__) case IFT_PROPVIRTUAL: if (strncmp("bridge", ifp->if_xname, sizeof("bridge")) == 0 && '0' <= ifp->if_xname[sizeof("bridge")] && ifp->if_xname[sizeof("bridge")] <= '9') return; break;#endif#ifdef IFT_PFLOG case IFT_PFLOG: return;#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); /* initialize NDP variables */ nd6_ifattach(ifp);#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) /* create a multicast kludge storage (if we have not had one) */ in6_createmkludge(ifp);#endif /* * quirks based on interface type */ switch (ifp->if_type) {#ifdef IFT_STF case IFT_STF: /* * 6to4 interface is a very special kind of beast. * no multicast, no linklocal. RFC2529 specifies how to make * linklocals for 6to4 interface, but there's no use and * it is rather harmful to have one. */ goto statinit;#endif default: break; } /* * usually, we require multicast capability to the interface */ if ((ifp->if_flags & IFF_MULTICAST) == 0) { log(LOG_INFO, "in6_ifattach: " "%s is not multicast capable, IPv6 not enabled\n", if_name(ifp)); return; } /* * assign loopback address for loopback interface. * XXX multiple loopback interface case. */ if ((ifp->if_flags & IFF_LOOPBACK) != 0) { in6 = in6addr_loopback; if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) { if (in6_ifattach_loopback(ifp) != 0) return; } } /* * assign a link-local address, if there's none. */ if (ip6_auto_linklocal) { int s = splnet(); ia = in6ifa_ifpforlinklocal(ifp, 0); if (ia == NULL) { if (in6_ifattach_linklocal(ifp, altifp) == 0) { /* linklocal address assigned */ } else { /* failed to assign linklocal address. bark? */ } } splx(s); }#ifdef IFT_STF /* XXX */statinit: #endif /* 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)); }}/* * NOTE: in6_ifdetach() does not support loopback if at this moment. * We don't need this function in bsdi, because interfaces are never removed * from the ifnet list in bsdi. */#if !(defined(__bsdi__) && _BSDI_VERSION >= 199802)voidin6_ifdetach(ifp) struct ifnet *ifp;{ struct in6_ifaddr *ia, *oia; struct ifaddr *ifa, *next;#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) struct ifaddr *ifaprev = NULL;#endif struct rtentry *rt; short rtflags; struct sockaddr_in6 sin6;#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) struct in6_multi *in6m, *in6m_next;#endif struct in6_multi_mship *imm; /* remove neighbor management table */ nd6_purge(ifp); /* nuke any of IPv6 addresses we have */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) for (ifa = ifp->if_addrlist; ifa; ifa = next)#else for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)#endif {#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) next = ifa->ifa_next;#else next = ifa->ifa_list.tqe_next;#endif if (ifa->ifa_addr->sa_family != AF_INET6) continue; in6_purgeaddr(ifa); } /* undo everything done by in6_ifattach(), just in case */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) for (ifa = ifp->if_addrlist; ifa; ifa = next)#else for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = next)#endif {#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) next = ifa->ifa_next;#else next = ifa->ifa_list.tqe_next;#endif if (ifa->ifa_addr->sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) ifaprev = ifa;#endif continue; } ia = (struct in6_ifaddr *)ifa; /* * leave from multicast groups we have joined for the interface */ while ((imm = ia->ia6_memberships.lh_first) != NULL) { LIST_REMOVE(imm, i6mm_chain); in6_leavegroup(imm); } /* remove from the routing table */ if ((ia->ia_flags & IFA_ROUTE) && (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0#ifdef __FreeBSD__ , 0UL#endif ))) { rtflags = rt->rt_flags; rtfree(rt); rtrequest(RTM_DELETE, (struct sockaddr *)&ia->ia_addr, (struct sockaddr *)&ia->ia_addr, (struct sockaddr *)&ia->ia_prefixmask, rtflags, (struct rtentry **)0); } /* remove from the linked list */#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) if (ifaprev) ifaprev->ifa_next = ifa->ifa_next; else ifp->if_addrlist = ifa->ifa_next;#else TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);#endif IFAFREE(&ia->ia_ifa); /* also remove from the IPv6 address chain(itojun&jinmei) */ oia = ia; if (oia == (ia = in6_ifaddr)) in6_ifaddr = ia->ia_next; else { while (ia->ia_next && (ia->ia_next != oia)) ia = ia->ia_next; if (ia->ia_next) ia->ia_next = oia->ia_next; else { nd6log((LOG_ERR, "%s: didn't unlink in6ifaddr from " "list\n", if_name(ifp))); } } IFAFREE(&oia->ia_ifa); }#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) /* leave from all multicast groups joined */#if (defined(__FreeBSD__) && __FreeBSD__ >= 4) in6_pcbpurgeif0(LIST_FIRST(udbinfo.listhead), ifp); in6_pcbpurgeif0(LIST_FIRST(ripcbinfo.listhead), ifp);#endif for (in6m = LIST_FIRST(&in6_multihead); in6m; in6m = in6m_next) { in6m_next = LIST_NEXT(in6m, in6m_entry); if (in6m->in6m_ifp != ifp) continue; in6_delmulti(in6m); in6m = NULL; }#endif#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) /* cleanup multicast address kludge table, if there is any */ in6_purgemkludge(ifp);#endif /* * remove neighbor management table. we call it twice just to make * sure we nuke everything. maybe we need just one call. * XXX: since the first call did not release addresses, some prefixes * might remain. We should call nd6_purge() again to release the * prefixes after removing all addresses above. * (Or can we just delay calling nd6_purge until at this point?) */ nd6_purge(ifp); /* remove route to link-local allnodes multicast (ff02::1) */ bzero(&sin6, sizeof(sin6)); sin6.sin6_len = sizeof(struct sockaddr_in6); sin6.sin6_family = AF_INET6; sin6.sin6_addr = in6addr_linklocal_allnodes; sin6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);#ifndef __FreeBSD__ rt = rtalloc1((struct sockaddr *)&sin6, 0);#else rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);#endif if (rt && rt->rt_ifp == ifp) { rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt), rt->rt_gateway, rt_mask(rt), rt->rt_flags, 0); rtfree(rt); }}#endifintin6_get_tmpifid(ifp, retbuf, baseid, generate) struct ifnet *ifp; u_int8_t *retbuf; const u_int8_t *baseid; int generate;{ u_int8_t nullbuf[8]; struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index]; bzero(nullbuf, sizeof(nullbuf)); if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) { /* we've never created a random ID. Create a new one. */ generate = 1; } if (generate) { bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1)); /* generate_tmp_ifid will update seedn and buf */ (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1, ndi->randomid); } bcopy(ndi->randomid, retbuf, 8); if (generate && bcmp(retbuf, nullbuf, sizeof(nullbuf)) == 0) { /* generate_tmp_ifid could not found a good ID. */ return(-1); } return(0);}voidin6_tmpaddrtimer(ignored_arg) void *ignored_arg;{ int i; struct nd_ifinfo *ndi; u_int8_t nullbuf[8];#ifdef __NetBSD__ int s = splsoftnet();#else int s = splnet();#endif#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3) callout_reset(&in6_tmpaddrtimer_ch, (ip6_temp_preferred_lifetime - ip6_desync_factor - ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, NULL);#elif defined(__OpenBSD__) timeout_set(&in6_tmpaddrtimer_ch, in6_tmpaddrtimer, NULL); timeout_add(&in6_tmpaddrtimer_ch, (ip6_temp_preferred_lifetime - ip6_desync_factor - ip6_temp_regen_advance) * hz);#else timeout(in6_tmpaddrtimer, (caddr_t)0, (ip6_temp_preferred_lifetime - ip6_desync_factor - ip6_temp_regen_advance) * hz);#endif bzero(nullbuf, sizeof(nullbuf)); for (i = 1; i < if_index + 1; i++) { ndi = &nd_ifinfo[i]; if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { /* * We've been generating a random ID on this interface. * Create a new one. */ (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1, ndi->randomid); } } splx(s);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?