xref: /netbsd-src/sys/net/if_llatbl.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
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