Home | History | Annotate | Line # | Download | only in net
if_llatbl.c revision 1.9
      1 /*	$NetBSD: if_llatbl.c,v 1.9 2015/11/26 01:41:20 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 /*
     78  * Dump lle state for a specific address family.
     79  */
     80 static int
     81 lltable_dump_af(struct lltable *llt, struct sysctl_req *wr)
     82 {
     83 	int error;
     84 
     85 	LLTABLE_LOCK_ASSERT();
     86 
     87 	if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
     88 		return (0);
     89 	error = 0;
     90 
     91 	IF_AFDATA_RLOCK(llt->llt_ifp);
     92 	error = lltable_foreach_lle(llt,
     93 	    (llt_foreach_cb_t *)llt->llt_dump_entry, wr);
     94 	IF_AFDATA_RUNLOCK(llt->llt_ifp);
     95 
     96 	return (error);
     97 }
     98 
     99 /*
    100  * Dump arp state for a specific address family.
    101  */
    102 int
    103 lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
    104 {
    105 	struct lltable *llt;
    106 	int error = 0;
    107 
    108 	LLTABLE_RLOCK();
    109 	SLIST_FOREACH(llt, &lltables, llt_link) {
    110 		if (llt->llt_af == af) {
    111 			error = lltable_dump_af(llt, wr);
    112 			if (error != 0)
    113 				goto done;
    114 		}
    115 	}
    116 done:
    117 	LLTABLE_RUNLOCK();
    118 	return (error);
    119 }
    120 
    121 /*
    122  * Common function helpers for chained hash table.
    123  */
    124 
    125 /*
    126  * Runs specified callback for each entry in @llt.
    127  * Caller does the locking.
    128  *
    129  */
    130 static int
    131 htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
    132 {
    133 	struct llentry *lle, *next;
    134 	int i, error;
    135 
    136 	error = 0;
    137 
    138 	for (i = 0; i < llt->llt_hsize; i++) {
    139 		LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
    140 			error = f(llt, lle, farg);
    141 			if (error != 0)
    142 				break;
    143 		}
    144 	}
    145 
    146 	return (error);
    147 }
    148 
    149 static void
    150 htable_link_entry(struct lltable *llt, struct llentry *lle)
    151 {
    152 	struct llentries *lleh;
    153 	uint32_t hashidx;
    154 
    155 	if ((lle->la_flags & LLE_LINKED) != 0)
    156 		return;
    157 
    158 	IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
    159 
    160 	hashidx = llt->llt_hash(lle, llt->llt_hsize);
    161 	lleh = &llt->lle_head[hashidx];
    162 
    163 	lle->lle_tbl  = llt;
    164 	lle->lle_head = lleh;
    165 	lle->la_flags |= LLE_LINKED;
    166 	LIST_INSERT_HEAD(lleh, lle, lle_next);
    167 
    168 	llt->llt_lle_count++;
    169 }
    170 
    171 static void
    172 htable_unlink_entry(struct llentry *lle)
    173 {
    174 
    175 	if ((lle->la_flags & LLE_LINKED) != 0) {
    176 		IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
    177 		LIST_REMOVE(lle, lle_next);
    178 		lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
    179 #if 0
    180 		lle->lle_tbl = NULL;
    181 		lle->lle_head = NULL;
    182 #endif
    183 		KASSERT(lle->lle_tbl->llt_lle_count != 0);
    184 		lle->lle_tbl->llt_lle_count--;
    185 	}
    186 }
    187 
    188 struct prefix_match_data {
    189 	const struct sockaddr *prefix;
    190 	const struct sockaddr *mask;
    191 	struct llentries dchain;
    192 	u_int flags;
    193 };
    194 
    195 static int
    196 htable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
    197 {
    198 	struct prefix_match_data *pmd;
    199 
    200 	pmd = (struct prefix_match_data *)farg;
    201 
    202 	if (llt->llt_match_prefix(pmd->prefix, pmd->mask, pmd->flags, lle)) {
    203 		LLE_WLOCK(lle);
    204 		LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain);
    205 	}
    206 
    207 	return (0);
    208 }
    209 
    210 static void
    211 htable_prefix_free(struct lltable *llt, const struct sockaddr *prefix,
    212     const struct sockaddr *mask, u_int flags)
    213 {
    214 	struct llentry *lle, *next;
    215 	struct prefix_match_data pmd;
    216 
    217 	memset(&pmd, 0, sizeof(pmd));
    218 	pmd.prefix = prefix;
    219 	pmd.mask = mask;
    220 	pmd.flags = flags;
    221 	LIST_INIT(&pmd.dchain);
    222 
    223 	IF_AFDATA_WLOCK(llt->llt_ifp);
    224 	/* Push matching lles to chain */
    225 	lltable_foreach_lle(llt, htable_prefix_free_cb, &pmd);
    226 
    227 	llentries_unlink(llt, &pmd.dchain);
    228 	IF_AFDATA_WUNLOCK(llt->llt_ifp);
    229 
    230 	LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next)
    231 		llt->llt_free_entry(llt, lle);
    232 }
    233 
    234 static void
    235 htable_free_tbl(struct lltable *llt)
    236 {
    237 
    238 	free(llt->lle_head, M_LLTABLE);
    239 	free(llt, M_LLTABLE);
    240 }
    241 
    242 static void
    243 llentries_unlink(struct lltable *llt, struct llentries *head)
    244 {
    245 	struct llentry *lle, *next;
    246 
    247 	LIST_FOREACH_SAFE(lle, head, lle_chain, next)
    248 		llt->llt_unlink_entry(lle);
    249 }
    250 
    251 /*
    252  * Helper function used to drop all mbufs in hold queue.
    253  *
    254  * Returns the number of held packets, if any, that were dropped.
    255  */
    256 size_t
    257 lltable_drop_entry_queue(struct llentry *lle)
    258 {
    259 	size_t pkts_dropped;
    260 	struct mbuf *next;
    261 
    262 	LLE_WLOCK_ASSERT(lle);
    263 
    264 	pkts_dropped = 0;
    265 	while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
    266 		next = lle->la_hold->m_nextpkt;
    267 		m_freem(lle->la_hold);
    268 		lle->la_hold = next;
    269 		lle->la_numheld--;
    270 		pkts_dropped++;
    271 	}
    272 
    273 	KASSERTMSG(lle->la_numheld == 0,
    274 		"la_numheld %d > 0, pkts_droped %zd",
    275 		 lle->la_numheld, pkts_dropped);
    276 
    277 	return (pkts_dropped);
    278 }
    279 
    280 /*
    281  * Deletes an address from the address table.
    282  * This function is called by the timer functions
    283  * such as arptimer() and nd6_llinfo_timer(), and
    284  * the caller does the locking.
    285  *
    286  * Returns the number of held packets, if any, that were dropped.
    287  */
    288 size_t
    289 llentry_free(struct llentry *lle)
    290 {
    291 	struct lltable *llt;
    292 	size_t pkts_dropped;
    293 
    294 	LLE_WLOCK_ASSERT(lle);
    295 
    296 	if ((lle->la_flags & LLE_LINKED) != 0) {
    297 		llt = lle->lle_tbl;
    298 
    299 		IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
    300 		llt->llt_unlink_entry(lle);
    301 	}
    302 
    303 	pkts_dropped = lltable_drop_entry_queue(lle);
    304 
    305 	LLE_FREE_LOCKED(lle);
    306 
    307 	return (pkts_dropped);
    308 }
    309 
    310 /*
    311  * (al)locate an llentry for address dst (equivalent to rtalloc for new-arp).
    312  *
    313  * If found the llentry * is returned referenced and unlocked.
    314  */
    315 struct llentry *
    316 llentry_alloc(struct ifnet *ifp, struct lltable *lt,
    317     struct sockaddr_storage *dst)
    318 {
    319 	struct llentry *la;
    320 
    321 	IF_AFDATA_RLOCK(ifp);
    322 	la = lla_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
    323 	IF_AFDATA_RUNLOCK(ifp);
    324 	if ((la == NULL) &&
    325 #ifdef __FreeBSD__
    326 	    (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
    327 #else /* XXX */
    328 	    (ifp->if_flags & IFF_NOARP) == 0) {
    329 #endif
    330 		IF_AFDATA_WLOCK(ifp);
    331 		la = lla_create(lt, 0, (struct sockaddr *)dst);
    332 		IF_AFDATA_WUNLOCK(ifp);
    333 	}
    334 
    335 	if (la != NULL) {
    336 		LLE_ADDREF(la);
    337 		LLE_WUNLOCK(la);
    338 	}
    339 
    340 	return (la);
    341 }
    342 
    343 /*
    344  * Free all entries from given table and free itself.
    345  */
    346 
    347 static int
    348 lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
    349 {
    350 	struct llentries *dchain;
    351 
    352 	dchain = (struct llentries *)farg;
    353 
    354 	LLE_WLOCK(lle);
    355 	LIST_INSERT_HEAD(dchain, lle, lle_chain);
    356 
    357 	return (0);
    358 }
    359 
    360 /*
    361  * Free all entries from given table.
    362  */
    363 void
    364 lltable_purge_entries(struct lltable *llt)
    365 {
    366 	struct llentry *lle, *next;
    367 	struct llentries dchain;
    368 
    369 	KASSERTMSG(llt != NULL, "llt is NULL");
    370 
    371 	LIST_INIT(&dchain);
    372 	IF_AFDATA_WLOCK(llt->llt_ifp);
    373 	/* Push all lles to @dchain */
    374 	lltable_foreach_lle(llt, lltable_free_cb, &dchain);
    375 	llentries_unlink(llt, &dchain);
    376 	IF_AFDATA_WUNLOCK(llt->llt_ifp);
    377 
    378 	LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
    379 		if (callout_halt(&lle->la_timer, &lle->lle_lock))
    380 			LLE_REMREF(lle);
    381 #if defined(__NetBSD__)
    382 		/* XXX should have callback? */
    383 		if (lle->la_rt != NULL) {
    384 			struct rtentry *rt = lle->la_rt;
    385 			lle->la_rt = NULL;
    386 #ifdef GATEWAY
    387 			/* XXX cannot call rtfree with holding mutex(IPL_NET) */
    388 			LLE_ADDREF(lle);
    389 			LLE_WUNLOCK(lle);
    390 #endif
    391 			rtfree(rt);
    392 #ifdef GATEWAY
    393 			LLE_WLOCK(lle);
    394 			LLE_REMREF(lle);
    395 #endif
    396 		}
    397 #endif
    398 		llentry_free(lle);
    399 	}
    400 
    401 }
    402 
    403 /*
    404  * Free all entries from given table and free itself.
    405  */
    406 void
    407 lltable_free(struct lltable *llt)
    408 {
    409 
    410 	KASSERTMSG(llt != NULL, "llt is NULL");
    411 
    412 	lltable_unlink(llt);
    413 	lltable_purge_entries(llt);
    414 	llt->llt_free_tbl(llt);
    415 }
    416 
    417 void
    418 lltable_drain(int af)
    419 {
    420 	struct lltable	*llt;
    421 	struct llentry	*lle;
    422 	register int i;
    423 
    424 	LLTABLE_RLOCK();
    425 	SLIST_FOREACH(llt, &lltables, llt_link) {
    426 		if (llt->llt_af != af)
    427 			continue;
    428 
    429 		for (i=0; i < llt->llt_hsize; i++) {
    430 			LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
    431 				LLE_WLOCK(lle);
    432 				lltable_drop_entry_queue(lle);
    433 				LLE_WUNLOCK(lle);
    434 			}
    435 		}
    436 	}
    437 	LLTABLE_RUNLOCK();
    438 }
    439 
    440 void
    441 lltable_prefix_free(int af, struct sockaddr *prefix, struct sockaddr *mask,
    442     u_int flags)
    443 {
    444 	struct lltable *llt;
    445 
    446 	LLTABLE_RLOCK();
    447 	SLIST_FOREACH(llt, &lltables, llt_link) {
    448 		if (llt->llt_af != af)
    449 			continue;
    450 
    451 		llt->llt_prefix_free(llt, prefix, mask, flags);
    452 	}
    453 	LLTABLE_RUNLOCK();
    454 }
    455 
    456 struct lltable *
    457 lltable_allocate_htbl(uint32_t hsize)
    458 {
    459 	struct lltable *llt;
    460 	int i;
    461 
    462 	llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
    463 	llt->llt_hsize = hsize;
    464 	llt->lle_head = malloc(sizeof(struct llentries) * hsize,
    465 	    M_LLTABLE, M_WAITOK | M_ZERO);
    466 
    467 	for (i = 0; i < llt->llt_hsize; i++)
    468 		LIST_INIT(&llt->lle_head[i]);
    469 
    470 	/* Set some default callbacks */
    471 	llt->llt_link_entry = htable_link_entry;
    472 	llt->llt_unlink_entry = htable_unlink_entry;
    473 	llt->llt_prefix_free = htable_prefix_free;
    474 	llt->llt_foreach_entry = htable_foreach_lle;
    475 
    476 	llt->llt_free_tbl = htable_free_tbl;
    477 
    478 	return (llt);
    479 }
    480 
    481 /*
    482  * Links lltable to global llt list.
    483  */
    484 void
    485 lltable_link(struct lltable *llt)
    486 {
    487 
    488 	LLTABLE_WLOCK();
    489 	SLIST_INSERT_HEAD(&lltables, llt, llt_link);
    490 	LLTABLE_WUNLOCK();
    491 }
    492 
    493 static void
    494 lltable_unlink(struct lltable *llt)
    495 {
    496 
    497 	LLTABLE_WLOCK();
    498 	SLIST_REMOVE(&lltables, llt, lltable, llt_link);
    499 	LLTABLE_WUNLOCK();
    500 
    501 }
    502 
    503 /*
    504  * External methods used by lltable consumers
    505  */
    506 
    507 int
    508 lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
    509 {
    510 
    511 	return (llt->llt_foreach_entry(llt, f, farg));
    512 }
    513 
    514 void
    515 lltable_link_entry(struct lltable *llt, struct llentry *lle)
    516 {
    517 
    518 	llt->llt_link_entry(llt, lle);
    519 }
    520 
    521 void
    522 lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
    523 {
    524 
    525 	llt->llt_unlink_entry(lle);
    526 }
    527 
    528 void
    529 lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
    530 {
    531 	struct lltable *llt;
    532 
    533 	llt = lle->lle_tbl;
    534 	llt->llt_fill_sa_entry(lle, sa);
    535 }
    536 
    537 struct ifnet *
    538 lltable_get_ifp(const struct lltable *llt)
    539 {
    540 
    541 	return (llt->llt_ifp);
    542 }
    543 
    544 int
    545 lltable_get_af(const struct lltable *llt)
    546 {
    547 
    548 	return (llt->llt_af);
    549 }
    550 
    551 /*
    552  * Called in route_output when rtm_flags contains RTF_LLDATA.
    553  */
    554 int
    555 lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
    556 {
    557 	const struct sockaddr_dl *dl = satocsdl(info->rti_info[RTAX_GATEWAY]);
    558 	const struct sockaddr *dst = info->rti_info[RTAX_DST];
    559 	struct ifnet *ifp;
    560 	struct lltable *llt;
    561 	struct llentry *lle;
    562 	u_int laflags;
    563 	int error;
    564 
    565 	KASSERTMSG(dl != NULL && dl->sdl_family == AF_LINK, "invalid dl");
    566 
    567 	ifp = if_byindex(dl->sdl_index);
    568 	if (ifp == NULL) {
    569 		log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
    570 		    __func__, dl->sdl_index);
    571 		return EINVAL;
    572 	}
    573 
    574 	/* XXX linked list may be too expensive */
    575 	LLTABLE_RLOCK();
    576 	SLIST_FOREACH(llt, &lltables, llt_link) {
    577 		if (llt->llt_af == dst->sa_family &&
    578 		    llt->llt_ifp == ifp)
    579 			break;
    580 	}
    581 	LLTABLE_RUNLOCK();
    582 	KASSERTMSG(llt != NULL, "Yep, ugly hacks are bad");
    583 
    584 	error = 0;
    585 
    586 	switch (rtm->rtm_type) {
    587 	case RTM_ADD:
    588 		/* Add static LLE */
    589 		IF_AFDATA_WLOCK(ifp);
    590 		lle = lla_create(llt, 0, dst);
    591 		if (lle == NULL) {
    592 			IF_AFDATA_WUNLOCK(ifp);
    593 			return (ENOMEM);
    594 		}
    595 
    596 
    597 		memcpy(&lle->ll_addr, CLLADDR(dl), ifp->if_addrlen);
    598 		if ((rtm->rtm_flags & RTF_ANNOUNCE))
    599 			lle->la_flags |= LLE_PUB;
    600 		lle->la_flags |= LLE_VALID;
    601 #ifdef INET6
    602 		/*
    603 		 * ND6
    604 		 */
    605 		if (dst->sa_family == AF_INET6)
    606 			lle->ln_state = ND6_LLINFO_REACHABLE;
    607 #endif
    608 		/*
    609 		 * NB: arp and ndp always set (RTF_STATIC | RTF_HOST)
    610 		 */
    611 
    612 		if (rtm->rtm_rmx.rmx_expire == 0) {
    613 			lle->la_flags |= LLE_STATIC;
    614 			lle->la_expire = 0;
    615 		} else
    616 			lle->la_expire = rtm->rtm_rmx.rmx_expire;
    617 		laflags = lle->la_flags;
    618 		LLE_WUNLOCK(lle);
    619 		IF_AFDATA_WUNLOCK(ifp);
    620 #if defined(INET) && NARP > 0
    621 		/* gratuitous ARP */
    622 		if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
    623 			arprequest(ifp,
    624 			    &((const struct sockaddr_in *)dst)->sin_addr,
    625 			    &((const struct sockaddr_in *)dst)->sin_addr,
    626 			    CLLADDR(dl));
    627 #else
    628 		(void)laflags;
    629 #endif
    630 
    631 		break;
    632 
    633 	case RTM_DELETE:
    634 		IF_AFDATA_WLOCK(ifp);
    635 		error = lla_delete(llt, 0, dst);
    636 		IF_AFDATA_WUNLOCK(ifp);
    637 		return (error == 0 ? 0 : ENOENT);
    638 
    639 	default:
    640 		error = EINVAL;
    641 	}
    642 
    643 	return (error);
    644 }
    645 
    646 void
    647 lltableinit(void)
    648 {
    649 
    650 	SLIST_INIT(&lltables);
    651 	rw_init(&lltable_rwlock);
    652 }
    653 
    654 #ifdef __FreeBSD__
    655 #ifdef DDB
    656 struct llentry_sa {
    657 	struct llentry		base;
    658 	struct sockaddr		l3_addr;
    659 };
    660 
    661 static void
    662 llatbl_lle_show(struct llentry_sa *la)
    663 {
    664 	struct llentry *lle;
    665 	uint8_t octet[6];
    666 
    667 	lle = &la->base;
    668 	db_printf("lle=%p\n", lle);
    669 	db_printf(" lle_next=%p\n", lle->lle_next.le_next);
    670 	db_printf(" lle_lock=%p\n", &lle->lle_lock);
    671 	db_printf(" lle_tbl=%p\n", lle->lle_tbl);
    672 	db_printf(" lle_head=%p\n", lle->lle_head);
    673 	db_printf(" la_hold=%p\n", lle->la_hold);
    674 	db_printf(" la_numheld=%d\n", lle->la_numheld);
    675 	db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire);
    676 	db_printf(" la_flags=0x%04x\n", lle->la_flags);
    677 	db_printf(" la_asked=%u\n", lle->la_asked);
    678 	db_printf(" la_preempt=%u\n", lle->la_preempt);
    679 	db_printf(" ln_byhint=%u\n", lle->ln_byhint);
    680 	db_printf(" ln_state=%d\n", lle->ln_state);
    681 	db_printf(" ln_router=%u\n", lle->ln_router);
    682 	db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick);
    683 	db_printf(" lle_refcnt=%d\n", lle->lle_refcnt);
    684 	memcopy(octet, &lle->ll_addr.mac16, sizeof(octet));
    685 	db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
    686 	    octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]);
    687 	db_printf(" lle_timer=%p\n", &lle->lle_timer);
    688 
    689 	switch (la->l3_addr.sa_family) {
    690 #ifdef INET
    691 	case AF_INET:
    692 	{
    693 		struct sockaddr_in *sin;
    694 		char l3s[INET_ADDRSTRLEN];
    695 
    696 		sin = (struct sockaddr_in *)&la->l3_addr;
    697 		inet_ntoa_r(sin->sin_addr, l3s);
    698 		db_printf(" l3_addr=%s\n", l3s);
    699 		break;
    700 	}
    701 #endif
    702 #ifdef INET6
    703 	case AF_INET6:
    704 	{
    705 		struct sockaddr_in6 *sin6;
    706 		char l3s[INET6_ADDRSTRLEN];
    707 
    708 		sin6 = (struct sockaddr_in6 *)&la->l3_addr;
    709 		ip6_sprintf(l3s, &sin6->sin6_addr);
    710 		db_printf(" l3_addr=%s\n", l3s);
    711 		break;
    712 	}
    713 #endif
    714 	default:
    715 		db_printf(" l3_addr=N/A (af=%d)\n", la->l3_addr.sa_family);
    716 		break;
    717 	}
    718 }
    719 
    720 DB_SHOW_COMMAND(llentry, db_show_llentry)
    721 {
    722 
    723 	if (!have_addr) {
    724 		db_printf("usage: show llentry <struct llentry *>\n");
    725 		return;
    726 	}
    727 
    728 	llatbl_lle_show((struct llentry_sa *)addr);
    729 }
    730 
    731 static void
    732 llatbl_llt_show(struct lltable *llt)
    733 {
    734 	int i;
    735 	struct llentry *lle;
    736 
    737 	db_printf("llt=%p llt_af=%d llt_ifp=%p\n",
    738 	    llt, llt->llt_af, llt->llt_ifp);
    739 
    740 	for (i = 0; i < llt->llt_hsize; i++) {
    741 		LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
    742 
    743 			llatbl_lle_show((struct llentry_sa *)lle);
    744 			if (db_pager_quit)
    745 				return;
    746 		}
    747 	}
    748 }
    749 
    750 DB_SHOW_COMMAND(lltable, db_show_lltable)
    751 {
    752 
    753 	if (!have_addr) {
    754 		db_printf("usage: show lltable <struct lltable *>\n");
    755 		return;
    756 	}
    757 
    758 	llatbl_llt_show((struct lltable *)addr);
    759 }
    760 
    761 DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables)
    762 {
    763 	VNET_ITERATOR_DECL(vnet_iter);
    764 	struct lltable *llt;
    765 
    766 	VNET_FOREACH(vnet_iter) {
    767 		CURVNET_SET_QUIET(vnet_iter);
    768 #ifdef VIMAGE
    769 		db_printf("vnet=%p\n", curvnet);
    770 #endif
    771 		SLIST_FOREACH(llt, &lltables, llt_link) {
    772 			db_printf("llt=%p llt_af=%d llt_ifp=%p(%s)\n",
    773 			    llt, llt->llt_af, llt->llt_ifp,
    774 			    (llt->llt_ifp != NULL) ?
    775 				llt->llt_ifp->if_xname : "?");
    776 			if (have_addr && addr != 0) /* verbose */
    777 				llatbl_llt_show(llt);
    778 			if (db_pager_quit) {
    779 				CURVNET_RESTORE();
    780 				return;
    781 			}
    782 		}
    783 		CURVNET_RESTORE();
    784 	}
    785 }
    786 #endif /* DDB */
    787 #endif /* __FreeBSD__ */
    788