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