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