43#include <sys/eventhandler.h>
44#include <sys/callout.h>
46#include <sys/malloc.h>
49#include <sys/socket.h>
50#include <sys/sockio.h>
52#include <sys/kernel.h>
53#include <sys/protosw.h>
55#include <sys/syslog.h>
56#include <sys/rwlock.h>
59#include <sys/sysctl.h>
62#include <net/if_var.h>
64#include <net/if_types.h>
66#include <net/route/route_ctl.h>
67#include <net/route/nhop.h>
70#include <netinet/in.h>
71#include <netinet/in_kdtrace.h>
72#include <net/if_llatbl.h>
73#include <netinet/if_ether.h>
75#include <netinet/ip6.h>
80#include <netinet/icmp6.h>
83#include <sys/limits.h>
85#include <security/mac/mac_framework.h>
87#define ND6_SLOWTIMER_INTERVAL (60 * 60)
88#define ND6_RECALC_REACHTM_INTERVAL (60 * 120)
90#define SIN6(s) ((const struct sockaddr_in6 *)(s))
111#define V_nd6_maxndopt VNET(nd6_maxndopt)
112#define V_nd6_maxqueuelen VNET(nd6_maxqueuelen)
128#define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval)
137static void nd6_free(
struct llentry **,
int);
143 const struct sockaddr_in6 *, u_char *, uint32_t *,
struct llentry **);
147#define V_nd6_slowtimo_ch VNET(nd6_slowtimo_ch)
150#define V_nd6_timer_ch VNET(nd6_timer_ch)
157 struct rt_addrinfo rtinfo;
159 struct sockaddr_dl gw;
164 LLE_WLOCK_ASSERT(lle);
166 if (lltable_get_af(lle->lle_tbl) != AF_INET6)
170 case LLENTRY_RESOLVED:
172 KASSERT(lle->la_flags & LLE_VALID,
173 (
"%s: %p resolved but not valid?", __func__, lle));
175 case LLENTRY_EXPIRED:
182 ifp = lltable_get_ifp(lle->lle_tbl);
184 bzero(&dst,
sizeof(dst));
185 bzero(&gw,
sizeof(gw));
186 bzero(&rtinfo,
sizeof(rtinfo));
187 lltable_fill_sa_entry(lle, (
struct sockaddr *)&dst);
190 gw.sdl_len =
sizeof(
struct sockaddr_dl);
191 gw.sdl_family = AF_LINK;
192 gw.sdl_alen = ifp->if_addrlen;
193 gw.sdl_index = ifp->if_index;
194 gw.sdl_type = ifp->if_type;
195 if (evt == LLENTRY_RESOLVED)
196 bcopy(lle->ll_addr, gw.sdl_data, ifp->if_addrlen);
197 rtinfo.rti_info[RTAX_DST] = (
struct sockaddr *)&dst;
198 rtinfo.rti_info[RTAX_GATEWAY] = (
struct sockaddr *)&gw;
199 rtinfo.rti_addrs = RTA_DST | RTA_GATEWAY;
200 fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS : ifp->if_fib;
201 rt_missmsg_fib(type, &rtinfo, RTF_HOST | RTF_LLDATA | (
202 type == RTM_ADD ? RTF_UP: 0), 0, fibnum);
211 if (ifp->if_afdata[AF_INET6] == NULL)
214 lltable_update_ifaddr(
LLTABLE6(ifp));
236 if (IS_DEFAULT_VNET(curvnet)) {
238 NULL, EVENTHANDLER_PRI_ANY);
253 if (IS_DEFAULT_VNET(curvnet)) {
268 nd = malloc(
sizeof(*nd), M_IP6NDP, M_WAITOK | M_ZERO);
271 nd->
chlim = IPV6_DEFHLIM;
279 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
288 (ifp->if_flags & IFF_LOOPBACK))
298 !(ifp->if_flags & IFF_LOOPBACK) &&
299 (ifp->if_type != IFT_BRIDGE)) {
302 nd->
flags &= ~ND6_IFF_IFDISABLED;
316 struct epoch_tracker et;
317 struct ifaddr *ifa, *next;
320 CK_STAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
321 if (ifa->ifa_addr->sa_family != AF_INET6)
339 if (ifp->if_afdata[AF_INET6] == NULL)
352 ndi->
maxmtu = ifp->if_mtu;
360 if (omaxmtu >= IPV6_MMTU && ndi->
maxmtu < IPV6_MMTU) {
361 log(LOG_NOTICE,
"nd6_setmtu0: "
362 "new link MTU on %s (%lu) is too small for IPv6\n",
363 if_name(ifp), (
unsigned long)ndi->
maxmtu);
375 bzero(ndopts,
sizeof(*ndopts));
376 ndopts->nd_opts_search = (
struct nd_opt_hdr *)opt;
378 = (
struct nd_opt_hdr *)(((u_char *)opt) + icmp6len);
381 ndopts->nd_opts_done = 1;
382 ndopts->nd_opts_search = NULL;
392 struct nd_opt_hdr *nd_opt;
395 KASSERT(ndopts != NULL, (
"%s: ndopts == NULL", __func__));
396 KASSERT(ndopts->nd_opts_last != NULL, (
"%s: uninitialized ndopts",
398 if (ndopts->nd_opts_search == NULL)
400 if (ndopts->nd_opts_done)
403 nd_opt = ndopts->nd_opts_search;
406 if ((caddr_t)&nd_opt->nd_opt_len >= (caddr_t)ndopts->nd_opts_last) {
407 bzero(ndopts,
sizeof(*ndopts));
411 olen = nd_opt->nd_opt_len << 3;
417 bzero(ndopts,
sizeof(*ndopts));
421 ndopts->nd_opts_search = (
struct nd_opt_hdr *)((caddr_t)nd_opt + olen);
422 if (ndopts->nd_opts_search > ndopts->nd_opts_last) {
424 bzero(ndopts,
sizeof(*ndopts));
426 }
else if (ndopts->nd_opts_search == ndopts->nd_opts_last) {
428 ndopts->nd_opts_done = 1;
429 ndopts->nd_opts_search = NULL;
442 struct nd_opt_hdr *nd_opt;
445 KASSERT(ndopts != NULL, (
"%s: ndopts == NULL", __func__));
446 KASSERT(ndopts->nd_opts_last != NULL, (
"%s: uninitialized ndopts",
448 if (ndopts->nd_opts_search == NULL)
453 if (nd_opt == NULL && ndopts->nd_opts_last == NULL) {
458 ICMP6STAT_INC(icp6s_nd_badopt);
459 bzero(ndopts,
sizeof(*ndopts));
466 switch (nd_opt->nd_opt_type) {
467 case ND_OPT_SOURCE_LINKADDR:
468 case ND_OPT_TARGET_LINKADDR:
470 case ND_OPT_REDIRECTED_HEADER:
474 "duplicated ND6 option found (type=%d)\n",
475 nd_opt->nd_opt_type));
482 case ND_OPT_PREFIX_INFORMATION:
487 ndopts->nd_opts_pi_end =
488 (
struct nd_opt_prefix_info *)nd_opt;
504 "nd6_options: unsupported option %d - "
505 "option ignored\n", nd_opt->nd_opt_type));
511 ICMP6STAT_INC(icp6s_nd_toomanyopt);
512 nd6log((LOG_INFO,
"too many loop in nd opt\n"));
516 if (ndopts->nd_opts_done)
531 LLE_WLOCK_ASSERT(ln);
534 if (ln->la_flags & LLE_CHILD)
540 canceled = callout_stop(&ln->lle_timer);
542 ln->la_expire = time_uptime + tick / hz;
544 if (tick > INT_MAX) {
545 ln->ln_ntick = tick - INT_MAX;
546 canceled = callout_reset(&ln->lle_timer, INT_MAX,
550 canceled = callout_reset(&ln->lle_timer, tick,
571 if (ln->la_hold == NULL)
578 if (
sizeof(hdr) > m->m_len)
581 m_copydata(m, 0,
sizeof(hdr), (caddr_t)&hdr);
624 int nd_delay, nd_gctimer;
632 lle_hittime = llentry_get_hittime(lle);
634 if (lle_hittime == 0) {
640 delay = (long)(MIN(nd_gctimer, nd_delay));
642 if (lle->lle_remtime > delay)
643 lle->lle_remtime -= delay;
645 delay = lle->lle_remtime;
646 lle->lle_remtime = 0;
664 delay = (long)(time_uptime - lle_hittime);
665 if (delay < nd_delay) {
671 *pdelay = (long)(nd_delay - delay) * hz;
689 int nd_gctimer, nd_delay;
697 ifp = lle->lle_tbl->llt_ifp;
698 delay = (long)
ND_IFINFO(ifp)->retrans * hz / 1000;
702 ifp = lle->lle_tbl->llt_ifp;
703 delay = (long)
ND_IFINFO(ifp)->reachable * hz;
708 llentry_request_feedback(lle);
712 delay = (long)(MIN(nd_gctimer, nd_delay)) * hz;
713 remtime = (long)nd_gctimer * hz - delay;
724 lle->lle_remtime = remtime;
725 lle->ln_state = newstate;
733static __noinline
void
736 struct epoch_tracker et;
738 struct in6_addr *dst, *pdst, *psrc, src;
741 int do_switch, send_ns;
744 KASSERT(arg != NULL, (
"%s: arg NULL", __func__));
745 ln = (
struct llentry *)arg;
746 ifp = lltable_get_ifp(ln->lle_tbl);
747 CURVNET_SET(ifp->if_vnet);
751 if (callout_pending(&ln->lle_timer)) {
776 dst = &ln->r_l3addr.addr6;
779 if (ln->ln_ntick > 0) {
780 if (ln->ln_ntick > INT_MAX) {
781 ln->ln_ntick -= INT_MAX;
790 if (ln->la_flags & LLE_STATIC) {
794 if (ln->la_flags & LLE_DELETED) {
799 switch (ln->ln_state) {
807 struct mbuf *m = ln->la_hold;
830 while ((n = n->m_next) != NULL) {
831 if (n->m_flags & M_EXTPG)
839 ICMP6_DST_UNREACH_ADDR, 0, ifp);
860 if (do_switch == 0) {
892 panic(
"%s: paths in a dark night can be confusing: %d",
893 __func__, ln->ln_state);
918 CURVNET_SET((
struct vnet *) arg);
919 struct epoch_tracker et;
920 struct nd_prhead prl;
1001 delay = arc4random() %
1011 ((ifp->if_flags & IFF_UP) == 0 ||
1012 (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
1029 LIST_FOREACH_SAFE(pr, &
V_nd_prefix, ndpr_entry, npr) {
1064 while ((pr = LIST_FIRST(&prl)) != NULL) {
1065 LIST_REMOVE(pr, ndpr_entry);
1087 ifp = ia6->
ia_ifa.ifa_ifp;
1088 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1091 if (ifa->ifa_addr->sa_family != AF_INET6)
1126 if (public_ifa6 != NULL)
1127 ifa_ref(&public_ifa6->
ia_ifa);
1129 if (public_ifa6 != NULL) {
1133 ifa_free(&public_ifa6->
ia_ifa);
1134 log(LOG_NOTICE,
"regen_tmpaddr: failed to create a new"
1135 " tmp addr,errno=%d\n", e);
1138 ifa_free(&public_ifa6->
ia_ifa);
1152 struct nd_prhead prl;
1165 LIST_FOREACH_SAFE(pr, &
V_nd_prefix, ndpr_entry, npr) {
1172 while ((pr = LIST_FIRST(&prl)) != NULL) {
1173 LIST_REMOVE(pr, ndpr_entry);
1202 IF_AFDATA_LOCK_ASSERT(ifp);
1204 ln = lla_lookup(
LLTABLE6(ifp), flags, (
struct sockaddr *)&
sin6);
1209static struct llentry *
1220 ln = lltable_alloc_entry(
LLTABLE6(ifp), 0, (
struct sockaddr *)&
sin6);
1237 struct rt_addrinfo info;
1239 const struct sockaddr *dst6;
1266 bzero(&rt_key,
sizeof(rt_key));
1267 bzero(&info,
sizeof(info));
1268 info.rti_info[RTAX_DST] = (
struct sockaddr *)&rt_key;
1289 fibnum = V_rt_add_addr_allfibs ? rt_numfibs - 1 : 0;
1290 for (; fibnum < rt_numfibs; fibnum++) {
1299 error = rib_lookup_info(fibnum, dst6, 0, 0,
1334 if (ifp->if_flags & IFF_POINTOPOINT) {
1335 struct epoch_tracker et;
1337 NET_EPOCH_ENTER(et);
1338 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1339 if (ifa->ifa_addr->sa_family != addr->
sin6_family)
1341 if (ifa->ifa_dstaddr != NULL &&
1342 sa_equal(addr, ifa->ifa_dstaddr)) {
1370 struct llentry *lle;
1374 IF_AFDATA_UNLOCK_ASSERT(ifp);
1389static __noinline
void
1392 struct llentry *child_lle;
1395 LLE_WLOCK_ASSERT(lle);
1397 while ((child_lle = CK_SLIST_FIRST(&lle->lle_children)) != NULL) {
1398 LLE_WLOCK(child_lle);
1399 lltable_unlink_child_entry(child_lle);
1400 llentry_free(child_lle);
1410static __noinline
bool
1413 u_char buf[LLE_MAX_LINKHDR];
1418 if (lltable_calc_llheader(ifp, AF_INET6, lladdr, buf, &sz, &off) != 0)
1422 lltable_set_entry_addr(ifp, lle, buf, sz, off);
1424 struct llentry *child_lle;
1425 CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
1426 LLE_WLOCK(child_lle);
1427 fam = child_lle->r_family;
1429 if (lltable_calc_llheader(ifp, fam, lladdr, buf, &sz, &off) == 0) {
1431 lltable_set_entry_addr(ifp, child_lle, buf, sz, off);
1434 LLE_WUNLOCK(child_lle);
1444 LLE_WLOCK_ASSERT(lle);
1446 if (!lltable_acquire_wlock(ifp, lle))
1449 IF_AFDATA_WUNLOCK(ifp);
1462static __noinline
void
1472 LLE_WLOCK_ASSERT(ln);
1475 KASSERT((ln->la_flags & LLE_CHILD) == 0, (
"child lle"));
1477 ifp = lltable_get_ifp(ln->lle_tbl);
1484 if ((ln->la_flags & LLE_DELETED) == 0)
1485 EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
1496 if (dr != NULL && dr->
expire &&
1510 if (dr->
expire > time_uptime)
1512 (dr->
expire - time_uptime) * hz);
1540 if (ln->ln_router || dr) {
1576 if (ln->la_flags & LLE_REDIRECT)
1579 if (ln->ln_router || dr)
1588 IF_AFDATA_LOCK(
ifp);
1591 if (ln->la_flags & LLE_LINKED) {
1594 lltable_unlink_entry(ln->lle_tbl, ln);
1596 IF_AFDATA_UNLOCK(
ifp);
1606nd6_isdynrte(
const struct rtentry *rt,
const struct nhop_object *nh,
void *xap)
1609 if (nh->nh_flags & NHF_REDIRECT)
1624 struct rt_addrinfo info;
1625 struct rib_cmd_info rc;
1626 struct epoch_tracker et;
1628 lltable_fill_sa_entry(ln, (
struct sockaddr *)&
sin6);
1629 memset(&info, 0,
sizeof(info));
1630 info.rti_info[RTAX_DST] = (
struct sockaddr *)&
sin6;
1633 NET_EPOCH_ENTER(et);
1634 for (fibnum = 0; fibnum < rt_numfibs; fibnum++)
1635 rib_action(fibnum, RTM_DELETE, &info, &rc);
1646 struct nhop_object *nh;
1650 if ((nh != NULL) && (nh->nh_flags & NHF_DEFAULT)) {
1676 struct epoch_tracker et;
1679 if (ifp->if_afdata[AF_INET6] == NULL)
1680 return (EPFNOSUPPORT);
1685 bzero(&
ND,
sizeof(
ND));
1704 if (
ND.linkmtu != 0) {
1705 if (
ND.linkmtu < IPV6_MMTU ||
1713 if (
ND.basereachable != 0) {
1714 int obasereachable =
ND_IFINFO(ifp)->basereachable;
1717 if (
ND.basereachable != obasereachable)
1721 if (
ND.retrans != 0)
1741 NET_EPOCH_ENTER(et);
1742 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1743 if (ifa->ifa_addr->sa_family != AF_INET6)
1755 log(LOG_ERR,
"Cannot enable an interface"
1756 " with a link-local address marked"
1759 ND_IFINFO(ifp)->flags &= ~ND6_IFF_IFDISABLED;
1760 if (ifp->if_flags & IFF_UP)
1771 NET_EPOCH_ENTER(et);
1772 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead,
1774 if (ifa->ifa_addr->sa_family !=
1792 ifp->if_flags & IFF_UP) {
1799 NET_EPOCH_ENTER(et);
1800 CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead,
1802 if (ifa->ifa_addr->sa_family !=
1829 struct nd_prhead prl;
1834 LIST_FOREACH_SAFE(pr, &
V_nd_prefix, ndpr_entry, next) {
1841 while ((pr = LIST_FIRST(&prl)) != NULL) {
1842 LIST_REMOVE(pr, ndpr_entry);
1873 NET_EPOCH_ENTER(et);
1874 ln =
nd6_lookup(&nb_addr, LLE_SF(AF_INET6, 0), ifp);
1881 nbi->
state = ln->ln_state;
1882 nbi->
asked = ln->la_asked;
1884 if (ln->la_expire == 0)
1887 nbi->
expire = ln->la_expire + ln->lle_remtime / hz +
1888 (time_second - time_uptime);
1939 switch (type & 0xff) {
1940 case ND_NEIGHBOR_SOLICIT:
1953 if (code == ND_REDIRECT_ROUTER)
1960 case ND_ROUTER_SOLICIT:
1966 case ND_ROUTER_ADVERT:
1970 if ((!is_new && (old_addr || new_addr)) ||
1971 (is_new && new_addr)) {
1990 int lladdrlen,
int type,
int code)
1992 struct llentry *ln = NULL, *ln_tmp;
1998 uint16_t router = 0;
1999 struct mbuf *chain = NULL;
2000 u_char linkhdr[LLE_MAX_LINKHDR];
2005 IF_AFDATA_UNLOCK_ASSERT(ifp);
2007 KASSERT(ifp != NULL, (
"%s: ifp == NULL", __func__));
2008 KASSERT(from != NULL, (
"%s: from == NULL", __func__));
2023 flags = lladdr ? LLE_EXCLUSIVE : 0;
2024 ln =
nd6_lookup(from, LLE_SF(AF_INET6, flags), ifp);
2027 flags |= LLE_EXCLUSIVE;
2036 if (lladdr != NULL) {
2037 linkhdrsize =
sizeof(linkhdr);
2038 if (lltable_calc_llheader(ifp, AF_INET6, lladdr,
2039 linkhdr, &linkhdrsize, &lladdr_off) != 0)
2041 lltable_set_entry_addr(ifp, ln, linkhdr, linkhdrsize,
2045 IF_AFDATA_WLOCK(ifp);
2048 ln_tmp =
nd6_lookup(from, LLE_SF(AF_INET6, LLE_EXCLUSIVE), ifp);
2050 lltable_link_entry(
LLTABLE6(ifp), ln);
2051 IF_AFDATA_WUNLOCK(ifp);
2052 if (ln_tmp == NULL) {
2055 if (lladdr != NULL) {
2057 EVENTHANDLER_INVOKE(lle_event, ln,
2061 lltable_free_entry(
LLTABLE6(ifp), ln);
2067 if ((ln->la_flags & LLE_STATIC)) {
2068 if (flags & LLE_EXCLUSIVE)
2075 olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
2076 if (olladdr && lladdr) {
2077 llchange = bcmp(lladdr, ln->ll_addr,
2079 }
else if (!olladdr && lladdr)
2096 if (is_newentry == 0 && llchange != 0) {
2111 EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
2113 if (ln->la_hold != NULL)
2119 lladdr != NULL ? 1 : 0, ln->ln_router);
2121 ln->ln_router = router;
2123 if ((type & 0xFF) == ND_REDIRECT && code != ND_REDIRECT_ROUTER)
2124 ln->la_flags |= LLE_REDIRECT;
2126 if (flags & LLE_EXCLUSIVE)
2151 if ((do_update || is_newentry) && router &&
2163 struct epoch_tracker et;
2164 CURVNET_SET((
struct vnet *) arg);
2170 NET_EPOCH_ENTER(et);
2171 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
2172 if (ifp->if_afdata[AF_INET6] == NULL)
2196 LLE_WLOCK_ASSERT(ln);
2198 chain = ln->la_hold;
2223 struct ip6_hdr *ip6;
2227 mac_netinet6_nd6_send(ifp, m);
2238 mtag = m_tag_find(m, PACKET_TAG_ND_OUTGOING, NULL);
2240 ip6 = mtod(m,
struct ip6_hdr *);
2241 ip6len =
sizeof(
struct ip6_hdr) + ntohs(ip6->ip6_plen);
2246 if (error == 0 || error != -1)
2252 IP_PROBE(send, NULL, NULL, mtod(m,
struct ip6_hdr *), ifp, NULL,
2253 mtod(m,
struct ip6_hdr *));
2255 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
2258 error = (*ifp->if_output)(origifp, m, (
struct sockaddr *)dst, ro);
2277 const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags,
2278 struct llentry **plle)
2280 struct llentry *ln = NULL;
2296 if (m != NULL && m->m_flags & M_MCAST) {
2297 switch (ifp->if_type) {
2301 ETHER_MAP_IPV6_MULTICAST(&dst6->
sin6_addr,
2306 return (EAFNOSUPPORT);
2310 int family = gw_flags >> 16;
2311 int lookup_flags = plle ? LLE_EXCLUSIVE : LLE_UNLOCKED;
2313 if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) {
2315 bcopy(ln->r_linkdata, desten, ln->r_hdrlen);
2317 *pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR);
2318 llentry_provide_feedback(ln);
2325 }
else if (plle && ln)
2343static __noinline
struct llentry *
2346 struct llentry *child_lle = NULL;
2347 struct llentry *lle, *lle_tmp;
2350 if (lle != NULL && family != AF_INET6) {
2352 if (child_lle == NULL) {
2353 lltable_free_entry(
LLTABLE6(ifp), lle);
2356 child_lle->r_family = family;
2357 child_lle->la_flags |= LLE_CHILD | LLE_STATIC;
2364 "nd6_get_llentry: can't allocate llinfo for %s "
2370 IF_AFDATA_WLOCK(ifp);
2373 lle_tmp =
nd6_lookup(addr, LLE_SF(AF_INET6, LLE_EXCLUSIVE), ifp);
2374 if (lle_tmp == NULL)
2375 lltable_link_entry(
LLTABLE6(ifp), lle);
2377 lltable_free_entry(
LLTABLE6(ifp), lle);
2380 if (child_lle != NULL) {
2382 lle_tmp = llentry_lookup_family(lle, child_lle->r_family);
2383 LLE_WLOCK(child_lle);
2384 if (lle_tmp == NULL) {
2386 lltable_link_child_entry(lle, child_lle);
2389 lltable_free_entry(
LLTABLE6(ifp), child_lle);
2390 child_lle = lle_tmp;
2395 IF_AFDATA_WUNLOCK(ifp);
2410static __noinline
int
2412 const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags,
2413 struct llentry **plle)
2415 struct llentry *lle = NULL;
2417 int send_ns, ll_len;
2443 LLE_WLOCK_ASSERT(lle);
2461 if (flags & LLE_ADDRONLY) {
2462 lladdr = lle->ll_addr;
2463 ll_len = ifp->if_addrlen;
2465 lladdr = lle->r_linkdata;
2466 ll_len = lle->r_hdrlen;
2468 bcopy(lladdr, desten, ll_len);
2470 *pflags = lle->la_flags;
2486 if (lle->la_hold != NULL) {
2487 struct mbuf *m_hold;
2491 for (m_hold = lle->la_hold; m_hold; m_hold = m_hold->m_nextpkt){
2493 if (m_hold->m_nextpkt == NULL) {
2494 m_hold->m_nextpkt = m;
2499 m_hold = lle->la_hold;
2500 lle->la_hold = lle->la_hold->m_nextpkt;
2519 if (lle->la_flags & LLE_CHILD) {
2520 struct llentry *lle_parent = lle->lle_parent;
2525 if (lle->la_asked == 0) {
2536 return (EWOULDBLOCK);
2551 char *desten, uint32_t *pflags)
2555 flags |= LLE_ADDRONLY;
2557 (
const struct sockaddr_in6 *)dst, desten, pflags, NULL);
2564 struct mbuf *m, *m_head;
2570 struct route_in6 ro = {
2571 .ro_prepend = lle->r_linkdata,
2572 .ro_plen = lle->r_hdrlen,
2575 lltable_fill_sa_entry(lle, (
struct sockaddr *)&dst6);
2580 m_head = m_head->m_nextpkt;
2581 m->m_nextpkt = NULL;
2595 struct llentry *child_lle;
2600 CK_SLIST_FOREACH(child_lle, &lle->lle_children, lle_child_next) {
2601 LLE_WLOCK(child_lle);
2603 LLE_WUNLOCK(child_lle);
2618 switch (ifp->if_type) {
2622 case IFT_INFINIBAND:
2624 case IFT_PROPVIRTUAL:
2646 struct llentry *ln, *ln_tmp;
2647 struct sockaddr *dst;
2649 ifp = ia->
ia_ifa.ifa_ifp;
2653 dst = (
struct sockaddr *)&ia->
ia_addr;
2654 ln = lltable_alloc_entry(
LLTABLE6(ifp), LLE_IFADDR, dst);
2658 IF_AFDATA_WLOCK(ifp);
2661 ln_tmp = lla_lookup(
LLTABLE6(ifp), LLE_SF(AF_INET6, LLE_EXCLUSIVE), dst);
2663 lltable_unlink_entry(
LLTABLE6(ifp), ln_tmp);
2664 lltable_link_entry(
LLTABLE6(ifp), ln);
2665 IF_AFDATA_WUNLOCK(ifp);
2668 EVENTHANDLER_INVOKE(lle_event, ln_tmp, LLENTRY_EXPIRED);
2669 EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
2673 llentry_free(ln_tmp);
2686 struct sockaddr *saddr, *smask;
2689 ifp = ia->
ia_ifa.ifa_ifp;
2692 saddr = (
struct sockaddr *)&addr;
2693 smask = (
struct sockaddr *)&mask;
2696 lltable_prefix_free(AF_INET6, saddr, smask, LLE_STATIC);
2698 lltable_delete_addr(
LLTABLE6(ifp), LLE_IFADDR, saddr);
2704 struct mbuf *m_hold, *m_hold_next;
2706 for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) {
2707 m_hold_next = m_hold->m_nextpkt;
2728 error = sysctl_wire_old_buffer(req, 0);
2732 bzero(&p,
sizeof(p));
2734 bzero(&s6,
sizeof(s6));
2742 log(LOG_ERR,
"scope error in prefix list (%s)\n",
2756 ~((time_t)1 << ((
sizeof(maxexpire) * 8) - 1));
2760 (time_second - time_uptime);
2767 LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry)
2769 error = SYSCTL_OUT(req, &p,
sizeof(p));
2772 LIST_FOREACH(pfr, &pr->ndpr_advrtrs, pfr_entry) {
2776 "scope error in prefix list (%s)\n",
2778 error = SYSCTL_OUT(req, &s6,
sizeof(s6));
2788 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
2791SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen,
2792 CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1,
"");
2794 CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(nd6_gctimer), (60 * 60 * 24),
"");
void icmp6_error2(struct mbuf *m, int type, int code, int param, struct ifnet *ifp)
void in6_purgeaddr(struct ifaddr *ifa)
char * ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
void in6_if_up(struct ifnet *ifp)
int in6_addrscope(const struct in6_addr *)
#define IN6_IS_ADDR_LINKLOCAL(a)
#define IN6_IS_ADDR_UNSPECIFIED(a)
#define IN6_ARE_ADDR_EQUAL(a, b)
#define IFA6_IS_DEPRECATED(a)
#define IFA6_IS_INVALID(a)
void in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m)
#define IN6_IFF_TENTATIVE
#define IN6_IFF_DEPRECATED
#define SIOCGDEFIFACE_IN6
#define SIOCSRTRFLUSH_IN6
#define SIOCSPFXFLUSH_IN6
#define IN6_IFF_TEMPORARY
#define SIOCSIFINFO_FLAGS
#define IN6_IFF_DUPLICATED
#define SIOCSDEFIFACE_IN6
static struct sockaddr_in6 sin6
#define V_ip6_accept_rtadv
#define V_ip6_auto_linklocal
#define V_ip6_use_tempaddr
static __noinline void nd6_free_children(struct llentry *lle)
int nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
static eventhandler_tag lle_event_eh
struct llentry * nd6_lookup(const struct in6_addr *addr6, int flags, struct ifnet *ifp)
static int nd6_is_stale(struct llentry *lle, long *pdelay, int *do_switch)
static void nd6_lle_event(void *arg __unused, struct llentry *lle, int evt)
int nd6_add_ifa_lle(struct in6_ifaddr *ia)
static eventhandler_tag iflladdr_event_eh
MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery")
void nd6_timer(void *arg)
static __noinline struct llentry * nd6_get_llentry(struct ifnet *ifp, const struct in6_addr *addr, int family)
void nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr, int lladdrlen, int type, int code)
SYSCTL_PROC(_net_inet6_icmp6, ICMPV6CTL_ND6_PRLIST, nd6_prlist, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE, NULL, 0, nd6_sysctl_prlist, "S,in6_prefix", "NDP prefix list")
void nd6_subscription_cb(struct rib_head *rnh, struct rib_cmd_info *rc, void *arg)
__noinline void nd6_llinfo_setstate(struct llentry *lle, int newstate)
struct mbuf * nd6_grab_holdchain(struct llentry *ln)
static void nd6_llinfo_timer(void *)
int nd6_flush_holdchain(struct ifnet *ifp, struct llentry *lle, struct mbuf *chain)
int nd6_output_ifp(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m, struct sockaddr_in6 *dst, struct route *ro)
static eventhandler_tag ifnet_link_event_eh
SYSCTL_DECL(_net_inet6_icmp6)
static int nd6_need_cache(struct ifnet *)
static int nd6_is_new_addr_neighbor(const struct sockaddr_in6 *, struct ifnet *)
#define ND6_RECALC_REACHTM_INTERVAL
static void nd6_slowtimo(void *)
int nd6_resolve(struct ifnet *ifp, int gw_flags, struct mbuf *m, const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags, struct llentry **plle)
#define V_nd6_slowtimo_ch
static int regen_tmpaddr(struct in6_ifaddr *)
static void nd6_llinfo_settimer_locked(struct llentry *, long)
static int nd6_resolve_slow(struct ifnet *, int, int, struct mbuf *, const struct sockaddr_in6 *, u_char *, uint32_t *, struct llentry **)
static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *)
static struct llentry * nd6_alloc(const struct in6_addr *addr6, int flags, struct ifnet *ifp)
#define ND6_SLOWTIMER_INTERVAL
#define V_nd6_recalc_reachtm_interval
int nd6_options(union nd_opts *ndopts)
void nd6_rem_ifa_lle(struct in6_ifaddr *ia, int all)
static int nd6_isdynrte(const struct rtentry *rt, const struct nhop_object *nh, void *xap)
struct nd_opt_hdr * nd6_option(union nd_opts *ndopts)
int nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
void nd6_purge(struct ifnet *ifp)
bool nd6_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle, char *lladdr)
int(* send_sendso_input_hook)(struct mbuf *, struct ifnet *, int, int)
void nd6_option_init(void *opt, int icmp6len, union nd_opts *ndopts)
static int nd6_is_router(int type, int code, int is_new, int old_addr, int new_addr, int ln_router)
static __noinline struct in6_addr * nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
void nd6_ifdetach(struct ifnet *ifp, struct nd_ifinfo *nd)
static void nd6_free_redirect(const struct llentry *)
VNET_DEFINE(int, nd6_prune)
static int nd6_sysctl_prlist(SYSCTL_HANDLER_ARGS)
#define V_nd6_maxqueuelen
int nd6_resolve_addr(struct ifnet *ifp, int flags, const struct sockaddr *dst, char *desten, uint32_t *pflags)
static __noinline bool nd6_try_set_entry_addr_locked(struct ifnet *ifp, struct llentry *lle, char *lladdr)
struct nd_ifinfo * nd6_ifattach(struct ifnet *ifp)
VNET_DEFINE_STATIC(int, nd6_maxndopt)
__noinline void nd6_flush_children_holdchain(struct ifnet *ifp, struct llentry *lle)
static void nd6_free(struct llentry **, int)
void nd6_setmtu(struct ifnet *ifp)
static void nd6_iflladdr(void *arg __unused, struct ifnet *ifp)
static void check_release_defrouter(struct rib_cmd_info *rc, void *_cbdata)
static void clear_llinfo_pqueue(struct llentry *)
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXQLEN, nd6_maxqueuelen, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(nd6_maxqueuelen), 1, "")
#define ND6_ONLINK_LOCK()
void defrouter_rele(struct nd_defrouter *)
#define ND6_LLINFO_PERMANENT(n)
void defrouter_select_fib(int fibnum)
#define ND6_LLINFO_INCOMPLETE
int nd6_setdefaultiface(int)
void pfxlist_onlink_check(void)
#define ND6_IFF_PERFORMNUD
#define ND_COMPUTE_RTIME(x)
void nd6_ns_output(struct ifnet *, const struct in6_addr *, const struct in6_addr *, const struct in6_addr *, uint8_t *)
void nd6_dad_start(struct ifaddr *, int)
#define ND6_IFF_AUTO_LINKLOCAL
void nd6_prefix_ref(struct nd_prefix *)
void nd6_dad_stop(struct ifaddr *)
void nd6_prefix_unlink(struct nd_prefix *, struct nd_prhead *)
void nd6_defrouter_init(void)
void nd6_prefix_rele(struct nd_prefix *)
#define ND6_LLINFO_NOSTATE
void rt6_flush(struct in6_addr *, struct ifnet *)
void nd6_defrouter_flush_all(void)
void defrouter_reset(void)
#define ND6_IFF_IFDISABLED
#define ND6_LLINFO_REACHABLE
#define ND6_ONLINK_UNLOCK()
struct nd_defrouter * defrouter_lookup(const struct in6_addr *, struct ifnet *)
void nd6_defrouter_timer(void)
#define ND6_INFINITE_LIFETIME
void nd6_ifnet_link_event(void *, struct ifnet *, int)
#define ND6_IFF_ACCEPT_RTADV
struct nd_defrouter * defrouter_lookup_locked(const struct in6_addr *, struct ifnet *)
#define ND6_RLOCK_ASSERT()
void nd6_prefix_del(struct nd_prefix *)
void nd6_defrouter_purge(struct ifnet *)
bool nd6_defrouter_list_empty(void)
int in6_tmpifadd(const struct in6_ifaddr *, int, int)
int nd6_prefix_offlink(struct nd_prefix *)
#define MAX_RTR_SOLICITATION_DELAY
int in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
int sa6_recoverscope(struct sockaddr_in6 *sin6)
uint32_t in6_getscopezone(const struct ifnet *ifp, int scope)
struct sockaddr_in6 ia_addr
struct nd_prefix * ia6_ndpr
struct sockaddr_in6 ia_prefixmask
struct sockaddr_in6 prefix
struct nd_defrouter * router
u_int32_t ndpr_stateflags
struct sockaddr_in6 ndpr_prefix
struct in6_addr ndpr_mask
struct in6_addr sin6_addr
struct nd_opt_hdr * nd_opt_array[16]