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