Home | History | Annotate | Line # | Download | only in net
if_llatbl.c revision 1.13
      1 /*	$NetBSD: if_llatbl.c,v 1.13 2016/04/06 08:45:46 ozaki-r Exp $	*/
      2 /*
      3  * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
      4  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
      5  * Copyright (c) 2008 Kip Macy. All rights reserved.
      6  * Copyright (c) 2015 The NetBSD Foundation, Inc.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
     22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  * SUCH DAMAGE.
     29  */
     30 #include <sys/cdefs.h>
     31 
     32 #ifdef _KERNEL_OPT
     33 #include "opt_ddb.h"
     34 #include "opt_inet.h"
     35 #include "opt_inet6.h"
     36 #endif
     37 
     38 #include "arp.h"
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/malloc.h>
     43 #include <sys/mbuf.h>
     44 #include <sys/syslog.h>
     45 #include <sys/sysctl.h>
     46 #include <sys/socket.h>
     47 #include <sys/socketvar.h>
     48 #include <sys/kernel.h>
     49 #include <sys/lock.h>
     50 #include <sys/mutex.h>
     51 #include <sys/rwlock.h>
     52 
     53 #ifdef DDB
     54 #include <ddb/ddb.h>
     55 #endif
     56 
     57 #include <netinet/in.h>
     58 #include <net/if_llatbl.h>
     59 #include <net/if.h>
     60 #include <net/if_dl.h>
     61 #include <net/route.h>
     62 #include <netinet/if_inarp.h>
     63 #include <netinet6/in6_var.h>
     64 #include <netinet6/nd6.h>
     65 
     66 static SLIST_HEAD(, lltable) lltables;
     67 krwlock_t lltable_rwlock;
     68 
     69 static void lltable_unlink(struct lltable *llt);
     70 static void llentries_unlink(struct lltable *llt, struct llentries *head);
     71 
     72 static void htable_unlink_entry(struct llentry *lle);
     73 static void htable_link_entry(struct lltable *llt, struct llentry *lle);
     74 static int htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
     75     void *farg);
     76 
     77 int
     78 lltable_dump_entry(struct lltable *llt, struct llentry *lle,
     79     struct rt_walkarg *w, struct sockaddr *sa)
     80 {
     81 	struct ifnet *ifp = llt->llt_ifp;
     82 	int error;
     83 	void *a;
     84 	struct sockaddr_dl sdl;
     85 	int size;
     86 	struct rt_addrinfo info;
     87 
     88 	memset(&info, 0, sizeof(info));
     89 	info.rti_info[RTAX_DST] = sa;
     90 
     91 	a = (lle->la_flags & LLE_VALID) == LLE_VALID ? &lle->ll_addr : NULL;
     92 	if (sockaddr_dl_init(&sdl, sizeof(sdl), ifp->if_index, ifp->if_type,
     93 	    NULL, 0, a, ifp->if_addrlen) == NULL)
     94 		return EINVAL;
     95 
     96 	info.rti_info[RTAX_GATEWAY] = sstocsa(&sdl);
     97 	if (sa->sa_family == AF_INET && lle->la_flags & LLE_PUB) {
     98 		struct sockaddr_inarp *sin;
     99 		sin = (struct sockaddr_inarp *)sa;
    100 		sin->sin_other = SIN_PROXY;
    101 	}
    102 	if ((error = rt_msg3(RTM_GET, &info, 0, w, &size)))
    103 		return error;
    104 	if (w->w_where && w->w_tmem && w->w_needed <= 0) {
    105 		struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
    106 
    107 		/* Need to copy by myself */
    108 		rtm->rtm_rmx.rmx_expire =
    109 		    (lle->la_flags & LLE_STATIC) ? 0 : lle->la_expire;
    110 		rtm->rtm_flags |= RTF_HOST; /* For ndp */
    111 		rtm->rtm_flags |= (lle->la_flags & LLE_STATIC) ? RTF_STATIC : 0;
    112 		if (lle->la_flags & LLE_PUB)
    113 			rtm->rtm_flags |= RTF_ANNOUNCE;
    114 		rtm->rtm_addrs = info.rti_addrs;
    115 		if ((error = copyout(rtm, w->w_where, size)) != 0)
    116 			w->w_where = NULL;
    117 		else
    118 			w->w_where = (char *)w->w_where + size;
    119 	}
    120 
    121 	return error;
    122 }
    123 
    124 /*
    125  * Dump lle state for a specific address family.
    126  */
    127 static int
    128 lltable_dump_af(struct lltable *llt, struct rt_walkarg *w)
    129 {
    130 	int error;
    131 
    132 	LLTABLE_LOCK_ASSERT();
    133 
    134 	if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
    135 		return (0);
    136 	error = 0;
    137 
    138 	IF_AFDATA_RLOCK(llt->llt_ifp);
    139 	error = lltable_foreach_lle(llt,
    140 	    (llt_foreach_cb_t *)llt->llt_dump_entry, w);
    141 	IF_AFDATA_RUNLOCK(llt->llt_ifp);
    142 
    143 	return (error);
    144 }
    145 
    146 /*
    147  * Dump arp state for a specific address family.
    148  */
    149 int
    150 lltable_sysctl_dumparp(int af, struct rt_walkarg *w)
    151 {
    152 	struct lltable *llt;
    153 	int error = 0;
    154 
    155 	LLTABLE_RLOCK();
    156 	SLIST_FOREACH(llt, &lltables, llt_link) {
    157 		if (llt->llt_af == af) {
    158 			error = lltable_dump_af(llt, w);
    159 			if (error != 0)
    160 				goto done;
    161 		}
    162 	}
    163 done:
    164 	LLTABLE_RUNLOCK();
    165 	return (error);
    166 }
    167 
    168 /*
    169  * Common function helpers for chained hash table.
    170  */
    171 
    172 /*
    173  * Runs specified callback for each entry in @llt.
    174  * Caller does the locking.
    175  *
    176  */
    177 static int
    178 htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
    179 {
    180 	struct llentry *lle, *next;
    181 	int i, error;
    182 
    183 	error = 0;
    184 
    185 	for (i = 0; i < llt->llt_hsize; i++) {
    186 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
    187 			error = f(llt, lle, farg);
    188 			if (error != 0)
    189 				break;
    190 		}
    191 	}
    192 
    193 	return (error);
    194 }
    195 
    196 static void
    197 htable_link_entry(struct lltable *llt, struct llentry *lle)
    198 {
    199 	struct llentries *lleh;
    200 	uint32_t hashidx;
    201 
    202 	if ((lle->la_flags & LLE_LINKED) != 0)
    203 		return;
    204 
    205 	IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
    206 
    207 	hashidx = llt->llt_hash(lle, llt->llt_hsize);
    208 	lleh = &llt->lle_head[hashidx];
    209 
    210 	lle->lle_tbl  = llt;
    211 	lle->lle_head = lleh;
    212 	lle->la_flags |= LLE_LINKED;
    213 	LIST_INSERT_HEAD(lleh, lle, lle_next);
    214 
    215 	llt->llt_lle_count++;
    216 }
    217 
    218 static void
    219 htable_unlink_entry(struct llentry *lle)
    220 {
    221 
    222 	if ((lle->la_flags & LLE_LINKED) != 0) {
    223 		IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
    224 		LIST_REMOVE(lle, lle_next);
    225 		lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
    226 #if 0
    227 		lle->lle_tbl = NULL;
    228 		lle->lle_head = NULL;
    229 #endif
    230 		KASSERT(lle->lle_tbl->llt_lle_count != 0);
    231 		lle->lle_tbl->llt_lle_count--;
    232 	}
    233 }
    234 
    235 struct prefix_match_data {
    236 	const struct sockaddr *prefix;
    237 	const struct sockaddr *mask;
    238 	struct llentries dchain;
    239 	u_int flags;
    240 };
    241 
    242 static int
    243 htable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
    244 {
    245 	struct prefix_match_data *pmd;
    246 
    247 	pmd = (struct prefix_match_data *)farg;
    248 
    249 	if (llt->llt_match_prefix(pmd->prefix, pmd->mask, pmd->flags, lle)) {
    250 		LLE_WLOCK(lle);
    251 		LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain);
    252 	}
    253 
    254 	return (0);
    255 }
    256 
    257 static void
    258 htable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
    259     const struct sockaddr *mask, u_int flags)
    260 {
    261 	struct llentry *lle, *next;
    262 	struct prefix_match_data pmd;
    263 
    264 	memset(&pmd, 0, sizeof(pmd));
    265 	pmd.prefix = prefix;
    266 	pmd.mask = mask;
    267 	pmd.flags = flags;
    268 	LIST_INIT(&pmd.dchain);
    269 
    270 	IF_AFDATA_WLOCK(llt->llt_ifp);
    271 	/* Push matching lles to chain */
    272 	lltable_foreach_lle(llt, htable_prefix_free_cb, &pmd);
    273 
    274 	llentries_unlink(llt, &pmd.dchain);
    275 	IF_AFDATA_WUNLOCK(llt->llt_ifp);
    276 
    277 	LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next)
    278 		llt->llt_free_entry(llt, lle);
    279 }
    280 
    281 static void
    282 htable_free_tbl(struct lltable *llt)
    283 {
    284 
    285 	free(llt->lle_head, M_LLTABLE);
    286 	free(llt, M_LLTABLE);
    287 }
    288 
    289 static void
    290 llentries_unlink(struct lltable *llt, struct llentries *head)
    291 {
    292 	struct llentry *lle, *next;
    293 
    294 	LIST_FOREACH_SAFE(lle, head, lle_chain, next)
    295 		llt->llt_unlink_entry(lle);
    296 }
    297 
    298 /*
    299  * Helper function used to drop all mbufs in hold queue.
    300  *
    301  * Returns the number of held packets, if any, that were dropped.
    302  */
    303 size_t
    304 lltable_drop_entry_queue(struct llentry *lle)
    305 {
    306 	size_t pkts_dropped;
    307 	struct mbuf *next;
    308 
    309 	LLE_WLOCK_ASSERT(lle);
    310 
    311 	pkts_dropped = 0;
    312 	while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
    313 		next = lle->la_hold->m_nextpkt;
    314 		m_freem(lle->la_hold);
    315 		lle->la_hold = next;
    316 		lle->la_numheld--;
    317 		pkts_dropped++;
    318 	}
    319 
    320 	KASSERTMSG(lle->la_numheld == 0,
    321 		"la_numheld %d > 0, pkts_droped %zd",
    322 		 lle->la_numheld, pkts_dropped);
    323 
    324 	return (pkts_dropped);
    325 }
    326 
    327 /*
    328  * Deletes an address from the address table.
    329  * This function is called by the timer functions
    330  * such as arptimer() and nd6_llinfo_timer(), and
    331  * the caller does the locking.
    332  *
    333  * Returns the number of held packets, if any, that were dropped.
    334  */
    335 size_t
    336 llentry_free(struct llentry *lle)
    337 {
    338 	struct lltable *llt;
    339 	size_t pkts_dropped;
    340 
    341 	LLE_WLOCK_ASSERT(lle);
    342 
    343 	if ((lle->la_flags & LLE_LINKED) != 0) {
    344 		llt = lle->lle_tbl;
    345 
    346 		IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
    347 		llt->llt_unlink_entry(lle);
    348 	}
    349 
    350 	pkts_dropped = lltable_drop_entry_queue(lle);
    351 
    352 	LLE_FREE_LOCKED(lle);
    353 
    354 	return (pkts_dropped);
    355 }
    356 
    357 /*
    358  * (al)locate an llentry for address dst (equivalent to rtalloc for new-arp).
    359  *
    360  * If found the llentry * is returned referenced and unlocked.
    361  */
    362 struct llentry *
    363 llentry_alloc(struct ifnet *ifp, struct lltable *lt,
    364     struct sockaddr_storage *dst)
    365 {
    366 	struct llentry *la;
    367 
    368 	IF_AFDATA_RLOCK(ifp);
    369 	la = lla_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
    370 	IF_AFDATA_RUNLOCK(ifp);
    371 	if ((la == NULL) &&
    372 #ifdef __FreeBSD__
    373 	    (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
    374 #else /* XXX */
    375 	    (ifp->if_flags & IFF_NOARP) == 0) {
    376 #endif
    377 		IF_AFDATA_WLOCK(ifp);
    378 		la = lla_create(lt, 0, (struct sockaddr *)dst);
    379 		IF_AFDATA_WUNLOCK(ifp);
    380 	}
    381 
    382 	if (la != NULL) {
    383 		LLE_ADDREF(la);
    384 		LLE_WUNLOCK(la);
    385 	}
    386 
    387 	return (la);
    388 }
    389 
    390 /*
    391  * Free all entries from given table and free itself.
    392  */
    393 
    394 static int
    395 lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
    396 {
    397 	struct llentries *dchain;
    398 
    399 	dchain = (struct llentries *)farg;
    400 
    401 	LLE_WLOCK(lle);
    402 	LIST_INSERT_HEAD(dchain, lle, lle_chain);
    403 
    404 	return (0);
    405 }
    406 
    407 /*
    408  * Free all entries from given table.
    409  */
    410 void
    411 lltable_purge_entries(struct lltable *llt)
    412 {
    413 	struct llentry *lle, *next;
    414 	struct llentries dchain;
    415 
    416 	KASSERTMSG(llt != NULL, "llt is NULL");
    417 
    418 	LIST_INIT(&dchain);
    419 	IF_AFDATA_WLOCK(llt->llt_ifp);
    420 	/* Push all lles to @dchain */
    421 	lltable_foreach_lle(llt, lltable_free_cb, &dchain);
    422 	llentries_unlink(llt, &dchain);
    423 	IF_AFDATA_WUNLOCK(llt->llt_ifp);
    424 
    425 	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
    426 		if (callout_halt(&lle->la_timer, &lle->lle_lock))
    427 			LLE_REMREF(lle);
    428 		llentry_free(lle);
    429 	}
    430 
    431 }
    432 
    433 /*
    434  * Free all entries from given table and free itself.
    435  */
    436 void
    437 lltable_free(struct lltable *llt)
    438 {
    439 
    440 	KASSERTMSG(llt != NULL, "llt is NULL");
    441 
    442 	lltable_unlink(llt);
    443 	lltable_purge_entries(llt);
    444 	llt->llt_free_tbl(llt);
    445 }
    446 
    447 void
    448 lltable_drain(int af)
    449 {
    450 	struct lltable	*llt;
    451 	struct llentry	*lle;
    452 	register int i;
    453 
    454 	LLTABLE_RLOCK();
    455 	SLIST_FOREACH(llt, &lltables, llt_link) {
    456 		if (llt->llt_af != af)
    457 			continue;
    458 
    459 		for (i=0; i < llt->llt_hsize; i++) {
    460 			LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
    461 				LLE_WLOCK(lle);
    462 				lltable_drop_entry_queue(lle);
    463 				LLE_WUNLOCK(lle);
    464 			}
    465 		}
    466 	}
    467 	LLTABLE_RUNLOCK();
    468 }
    469 
    470 void
    471 lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask,
    472     u_int flags)
    473 {
    474 	struct lltable *llt;
    475 
    476 	LLTABLE_RLOCK();
    477 	SLIST_FOREACH(llt, &lltables, llt_link) {
    478 		if (llt->llt_af != af)
    479 			continue;
    480 
    481 		llt->llt_prefix_free(llt, prefix, mask, flags);
    482 	}
    483 	LLTABLE_RUNLOCK();
    484 }
    485 
    486 struct lltable *
    487 lltable_allocate_htbl(uint32_t hsize)
    488 {
    489 	struct lltable *llt;
    490 	int i;
    491 
    492 	llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
    493 	llt->llt_hsize = hsize;
    494 	llt->lle_head = malloc(sizeof(struct llentries) * hsize,
    495 	    M_LLTABLE, M_WAITOK | M_ZERO);
    496 
    497 	for (i = 0; i < llt->llt_hsize; i++)
    498 		LIST_INIT(&llt->lle_head[i]);
    499 
    500 	/* Set some default callbacks */
    501 	llt->llt_link_entry = htable_link_entry;
    502 	llt->llt_unlink_entry = htable_unlink_entry;
    503 	llt->llt_prefix_free = htable_prefix_free;
    504 	llt->llt_foreach_entry = htable_foreach_lle;
    505 
    506 	llt->llt_free_tbl = htable_free_tbl;
    507 
    508 	return (llt);
    509 }
    510 
    511 /*
    512  * Links lltable to global llt list.
    513  */
    514 void
    515 lltable_link(struct lltable *llt)
    516 {
    517 
    518 	LLTABLE_WLOCK();
    519 	SLIST_INSERT_HEAD(&lltables, llt, llt_link);
    520 	LLTABLE_WUNLOCK();
    521 }
    522 
    523 static void
    524 lltable_unlink(struct lltable *llt)
    525 {
    526 
    527 	LLTABLE_WLOCK();
    528 	SLIST_REMOVE(&lltables, llt, lltable, llt_link);
    529 	LLTABLE_WUNLOCK();
    530 
    531 }
    532 
    533 /*
    534  * External methods used by lltable consumers
    535  */
    536 
    537 int
    538 lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
    539 {
    540 
    541 	return (llt->llt_foreach_entry(llt, f, farg));
    542 }
    543 
    544 void
    545 lltable_link_entry(struct lltable *llt, struct llentry *lle)
    546 {
    547 
    548 	llt->llt_link_entry(llt, lle);
    549 }
    550 
    551 void
    552 lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
    553 {
    554 
    555 	llt->llt_unlink_entry(lle);
    556 }
    557 
    558 void
    559 lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
    560 {
    561 	struct lltable *llt;
    562 
    563 	llt = lle->lle_tbl;
    564 	llt->llt_fill_sa_entry(lle, sa);
    565 }
    566 
    567 struct ifnet *
    568 lltable_get_ifp(const struct lltable *llt)
    569 {
    570 
    571 	return (llt->llt_ifp);
    572 }
    573 
    574 int
    575 lltable_get_af(const struct lltable *llt)
    576 {
    577 
    578 	return (llt->llt_af);
    579 }
    580 
    581 /*
    582  * Called in route_output when rtm_flags contains RTF_LLDATA.
    583  */
    584 int
    585 lla_rt_output(const u_char rtm_type, const int rtm_flags, const time_t rtm_expire,
    586     struct rt_addrinfo *info, int sdl_index)
    587 {
    588 	const struct sockaddr_dl *dl = satocsdl(info->rti_info[RTAX_GATEWAY]);
    589 	const struct sockaddr *dst = info->rti_info[RTAX_DST];
    590 	struct ifnet *ifp;
    591 	struct lltable *llt;
    592 	struct llentry *lle;
    593 	u_int laflags;
    594 	int error;
    595 
    596 	KASSERTMSG(dl != NULL && dl->sdl_family == AF_LINK, "invalid dl");
    597 
    598 	if (sdl_index != 0)
    599 		ifp = if_byindex(sdl_index);
    600 	else
    601 		ifp = if_byindex(dl->sdl_index);
    602 	if (ifp == NULL) {
    603 		log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
    604 		    __func__, sdl_index != 0 ? sdl_index : dl->sdl_index);
    605 		return EINVAL;
    606 	}
    607 
    608 	/* XXX linked list may be too expensive */
    609 	LLTABLE_RLOCK();
    610 	SLIST_FOREACH(llt, &lltables, llt_link) {
    611 		if (llt->llt_af == dst->sa_family &&
    612 		    llt->llt_ifp == ifp)
    613 			break;
    614 	}
    615 	LLTABLE_RUNLOCK();
    616 	KASSERTMSG(llt != NULL, "Yep, ugly hacks are bad");
    617 
    618 	error = 0;
    619 
    620 	switch (rtm_type) {
    621 	case RTM_ADD:
    622 		/* Add static LLE */
    623 		IF_AFDATA_WLOCK(ifp);
    624 		lle = lla_lookup(llt, 0, dst);
    625 
    626 		/* Cannot overwrite an existing static entry */
    627 		if (lle != NULL &&
    628 		    (lle->la_flags & LLE_STATIC || lle->la_expire == 0)) {
    629 			LLE_RUNLOCK(lle);
    630 			IF_AFDATA_WUNLOCK(ifp);
    631 			return EEXIST;
    632 		}
    633 		if (lle != NULL)
    634 			LLE_RUNLOCK(lle);
    635 
    636 		lle = lla_create(llt, 0, dst);
    637 		if (lle == NULL) {
    638 			IF_AFDATA_WUNLOCK(ifp);
    639 			return (ENOMEM);
    640 		}
    641 
    642 		KASSERT(ifp->if_addrlen <= sizeof(lle->ll_addr));
    643 		memcpy(&lle->ll_addr, CLLADDR(dl), ifp->if_addrlen);
    644 		if ((rtm_flags & RTF_ANNOUNCE))
    645 			lle->la_flags |= LLE_PUB;
    646 		lle->la_flags |= LLE_VALID;
    647 #ifdef INET6
    648 		/*
    649 		 * ND6
    650 		 */
    651 		if (dst->sa_family == AF_INET6)
    652 			lle->ln_state = ND6_LLINFO_REACHABLE;
    653 #endif
    654 		/*
    655 		 * NB: arp and ndp always set (RTF_STATIC | RTF_HOST)
    656 		 */
    657 
    658 		if (rtm_expire == 0) {
    659 			lle->la_flags |= LLE_STATIC;
    660 			lle->la_expire = 0;
    661 		} else
    662 			lle->la_expire = rtm_expire;
    663 		laflags = lle->la_flags;
    664 		LLE_WUNLOCK(lle);
    665 		IF_AFDATA_WUNLOCK(ifp);
    666 #if defined(INET) && NARP > 0
    667 		/* gratuitous ARP */
    668 		if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
    669 			arprequest(ifp,
    670 			    &((const struct sockaddr_in *)dst)->sin_addr,
    671 			    &((const struct sockaddr_in *)dst)->sin_addr,
    672 			    CLLADDR(dl));
    673 #else
    674 		(void)laflags;
    675 #endif
    676 
    677 		break;
    678 
    679 	case RTM_DELETE:
    680 		IF_AFDATA_WLOCK(ifp);
    681 		error = lla_delete(llt, 0, dst);
    682 		IF_AFDATA_WUNLOCK(ifp);
    683 		return (error == 0 ? 0 : ENOENT);
    684 
    685 	default:
    686 		error = EINVAL;
    687 	}
    688 
    689 	return (error);
    690 }
    691 
    692 void
    693 lltableinit(void)
    694 {
    695 
    696 	SLIST_INIT(&lltables);
    697 	rw_init(&lltable_rwlock);
    698 }
    699 
    700 #ifdef __FreeBSD__
    701 #ifdef DDB
    702 struct llentry_sa {
    703 	struct llentry		base;
    704 	struct sockaddr		l3_addr;
    705 };
    706 
    707 static void
    708 llatbl_lle_show(struct llentry_sa *la)
    709 {
    710 	struct llentry *lle;
    711 	uint8_t octet[6];
    712 
    713 	lle = &la->base;
    714 	db_printf("lle=%p\n", lle);
    715 	db_printf(" lle_next=%p\n", lle->lle_next.le_next);
    716 	db_printf(" lle_lock=%p\n", &lle->lle_lock);
    717 	db_printf(" lle_tbl=%p\n", lle->lle_tbl);
    718 	db_printf(" lle_head=%p\n", lle->lle_head);
    719 	db_printf(" la_hold=%p\n", lle->la_hold);
    720 	db_printf(" la_numheld=%d\n", lle->la_numheld);
    721 	db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire);
    722 	db_printf(" la_flags=0x%04x\n", lle->la_flags);
    723 	db_printf(" la_asked=%u\n", lle->la_asked);
    724 	db_printf(" la_preempt=%u\n", lle->la_preempt);
    725 	db_printf(" ln_byhint=%u\n", lle->ln_byhint);
    726 	db_printf(" ln_state=%d\n", lle->ln_state);
    727 	db_printf(" ln_router=%u\n", lle->ln_router);
    728 	db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick);
    729 	db_printf(" lle_refcnt=%d\n", lle->lle_refcnt);
    730 	memcopy(octet, &lle->ll_addr.mac16, sizeof(octet));
    731 	db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
    732 	    octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]);
    733 	db_printf(" lle_timer=%p\n", &lle->lle_timer);
    734 
    735 	switch (la->l3_addr.sa_family) {
    736 #ifdef INET
    737 	case AF_INET:
    738 	{
    739 		struct sockaddr_in *sin;
    740 		char l3s[INET_ADDRSTRLEN];
    741 
    742 		sin = (struct sockaddr_in *)&la->l3_addr;
    743 		inet_ntoa_r(sin->sin_addr, l3s);
    744 		db_printf(" l3_addr=%s\n", l3s);
    745 		break;
    746 	}
    747 #endif
    748 #ifdef INET6
    749 	case AF_INET6:
    750 	{
    751 		struct sockaddr_in6 *sin6;
    752 		char l3s[INET6_ADDRSTRLEN];
    753 
    754 		sin6 = (struct sockaddr_in6 *)&la->l3_addr;
    755 		ip6_sprintf(l3s, &sin6->sin6_addr);
    756 		db_printf(" l3_addr=%s\n", l3s);
    757 		break;
    758 	}
    759 #endif
    760 	default:
    761 		db_printf(" l3_addr=N/A (af=%d)\n", la->l3_addr.sa_family);
    762 		break;
    763 	}
    764 }
    765 
    766 DB_SHOW_COMMAND(llentry, db_show_llentry)
    767 {
    768 
    769 	if (!have_addr) {
    770 		db_printf("usage: show llentry <struct llentry *>\n");
    771 		return;
    772 	}
    773 
    774 	llatbl_lle_show((struct llentry_sa *)addr);
    775 }
    776 
    777 static void
    778 llatbl_llt_show(struct lltable *llt)
    779 {
    780 	int i;
    781 	struct llentry *lle;
    782 
    783 	db_printf("llt=%p llt_af=%d llt_ifp=%p\n",
    784 	    llt, llt->llt_af, llt->llt_ifp);
    785 
    786 	for (i = 0; i < llt->llt_hsize; i++) {
    787 		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
    788 
    789 			llatbl_lle_show((struct llentry_sa *)lle);
    790 			if (db_pager_quit)
    791 				return;
    792 		}
    793 	}
    794 }
    795 
    796 DB_SHOW_COMMAND(lltable, db_show_lltable)
    797 {
    798 
    799 	if (!have_addr) {
    800 		db_printf("usage: show lltable <struct lltable *>\n");
    801 		return;
    802 	}
    803 
    804 	llatbl_llt_show((struct lltable *)addr);
    805 }
    806 
    807 DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables)
    808 {
    809 	VNET_ITERATOR_DECL(vnet_iter);
    810 	struct lltable *llt;
    811 
    812 	VNET_FOREACH(vnet_iter) {
    813 		CURVNET_SET_QUIET(vnet_iter);
    814 #ifdef VIMAGE
    815 		db_printf("vnet=%p\n", curvnet);
    816 #endif
    817 		SLIST_FOREACH(llt, &lltables, llt_link) {
    818 			db_printf("llt=%p llt_af=%d llt_ifp=%p(%s)\n",
    819 			    llt, llt->llt_af, llt->llt_ifp,
    820 			    (llt->llt_ifp != NULL) ?
    821 				llt->llt_ifp->if_xname : "?");
    822 			if (have_addr && addr != 0) /* verbose */
    823 				llatbl_llt_show(llt);
    824 			if (db_pager_quit) {
    825 				CURVNET_RESTORE();
    826 				return;
    827 			}
    828 		}
    829 		CURVNET_RESTORE();
    830 	}
    831 }
    832 #endif /* DDB */
    833 #endif /* __FreeBSD__ */
    834