]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/if_llatbl.c
sys/{x86,amd64}: remove one of doubled ;s
[FreeBSD/FreeBSD.git] / sys / net / if_llatbl.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
5  * Copyright (c) 2004-2008 Qing Li. All rights reserved.
6  * Copyright (c) 2008 Kip Macy. All rights reserved.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "opt_ddb.h"
33 #include "opt_inet.h"
34 #include "opt_inet6.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/eventhandler.h>
39 #include <sys/malloc.h>
40 #include <sys/mbuf.h>
41 #include <sys/syslog.h>
42 #include <sys/sysctl.h>
43 #include <sys/socket.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/rwlock.h>
48
49 #ifdef DDB
50 #include <ddb/ddb.h>
51 #endif
52
53 #include <vm/uma.h>
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/if_var.h>
60 #include <net/route.h>
61 #include <net/vnet.h>
62 #include <netinet/if_ether.h>
63 #include <netinet6/in6_var.h>
64 #include <netinet6/nd6.h>
65
66 MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
67
68 VNET_DEFINE_STATIC(SLIST_HEAD(, lltable), lltables) =
69     SLIST_HEAD_INITIALIZER(lltables);
70 #define V_lltables      VNET(lltables)
71
72 static struct rwlock lltable_list_lock;
73 RW_SYSINIT(lltable_list_lock, &lltable_list_lock, "lltable_list_lock");
74 #define LLTABLE_LIST_RLOCK()            rw_rlock(&lltable_list_lock)
75 #define LLTABLE_LIST_RUNLOCK()          rw_runlock(&lltable_list_lock)
76 #define LLTABLE_LIST_WLOCK()            rw_wlock(&lltable_list_lock)
77 #define LLTABLE_LIST_WUNLOCK()          rw_wunlock(&lltable_list_lock)
78 #define LLTABLE_LIST_LOCK_ASSERT()      rw_assert(&lltable_list_lock, RA_LOCKED)
79
80 static void lltable_unlink(struct lltable *llt);
81 static void llentries_unlink(struct lltable *llt, struct llentries *head);
82
83 static void htable_unlink_entry(struct llentry *lle);
84 static void htable_link_entry(struct lltable *llt, struct llentry *lle);
85 static int htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f,
86     void *farg);
87
88 /*
89  * Dump lle state for a specific address family.
90  */
91 static int
92 lltable_dump_af(struct lltable *llt, struct sysctl_req *wr)
93 {
94         struct epoch_tracker et;
95         int error;
96
97         LLTABLE_LIST_LOCK_ASSERT();
98
99         if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
100                 return (0);
101         error = 0;
102
103         NET_EPOCH_ENTER(et);
104         error = lltable_foreach_lle(llt,
105             (llt_foreach_cb_t *)llt->llt_dump_entry, wr);
106         NET_EPOCH_EXIT(et);
107
108         return (error);
109 }
110
111 /*
112  * Dump arp state for a specific address family.
113  */
114 int
115 lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
116 {
117         struct lltable *llt;
118         int error = 0;
119
120         LLTABLE_LIST_RLOCK();
121         SLIST_FOREACH(llt, &V_lltables, llt_link) {
122                 if (llt->llt_af == af) {
123                         error = lltable_dump_af(llt, wr);
124                         if (error != 0)
125                                 goto done;
126                 }
127         }
128 done:
129         LLTABLE_LIST_RUNLOCK();
130         return (error);
131 }
132
133 /*
134  * Common function helpers for chained hash table.
135  */
136
137 /*
138  * Runs specified callback for each entry in @llt.
139  * Caller does the locking.
140  *
141  */
142 static int
143 htable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
144 {
145         struct llentry *lle, *next;
146         int i, error;
147
148         error = 0;
149
150         for (i = 0; i < llt->llt_hsize; i++) {
151                 CK_LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
152                         error = f(llt, lle, farg);
153                         if (error != 0)
154                                 break;
155                 }
156         }
157
158         return (error);
159 }
160
161 static void
162 htable_link_entry(struct lltable *llt, struct llentry *lle)
163 {
164         struct llentries *lleh;
165         uint32_t hashidx;
166
167         if ((lle->la_flags & LLE_LINKED) != 0)
168                 return;
169
170         IF_AFDATA_WLOCK_ASSERT(llt->llt_ifp);
171
172         hashidx = llt->llt_hash(lle, llt->llt_hsize);
173         lleh = &llt->lle_head[hashidx];
174
175         lle->lle_tbl  = llt;
176         lle->lle_head = lleh;
177         lle->la_flags |= LLE_LINKED;
178         CK_LIST_INSERT_HEAD(lleh, lle, lle_next);
179 }
180
181 static void
182 htable_unlink_entry(struct llentry *lle)
183 {
184
185         if ((lle->la_flags & LLE_LINKED) != 0) {
186                 IF_AFDATA_WLOCK_ASSERT(lle->lle_tbl->llt_ifp);
187                 CK_LIST_REMOVE(lle, lle_next);
188                 lle->la_flags &= ~(LLE_VALID | LLE_LINKED);
189 #if 0
190                 lle->lle_tbl = NULL;
191                 lle->lle_head = NULL;
192 #endif
193         }
194 }
195
196 struct prefix_match_data {
197         const struct sockaddr *addr;
198         const struct sockaddr *mask;
199         struct llentries dchain;
200         u_int flags;
201 };
202
203 static int
204 htable_prefix_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
205 {
206         struct prefix_match_data *pmd;
207
208         pmd = (struct prefix_match_data *)farg;
209
210         if (llt->llt_match_prefix(pmd->addr, pmd->mask, pmd->flags, lle)) {
211                 LLE_WLOCK(lle);
212                 CK_LIST_INSERT_HEAD(&pmd->dchain, lle, lle_chain);
213         }
214
215         return (0);
216 }
217
218 static void
219 htable_prefix_free(struct lltable *llt, const struct sockaddr *addr,
220     const struct sockaddr *mask, u_int flags)
221 {
222         struct llentry *lle, *next;
223         struct prefix_match_data pmd;
224
225         bzero(&pmd, sizeof(pmd));
226         pmd.addr = addr;
227         pmd.mask = mask;
228         pmd.flags = flags;
229         CK_LIST_INIT(&pmd.dchain);
230
231         IF_AFDATA_WLOCK(llt->llt_ifp);
232         /* Push matching lles to chain */
233         lltable_foreach_lle(llt, htable_prefix_free_cb, &pmd);
234
235         llentries_unlink(llt, &pmd.dchain);
236         IF_AFDATA_WUNLOCK(llt->llt_ifp);
237
238         CK_LIST_FOREACH_SAFE(lle, &pmd.dchain, lle_chain, next)
239                 lltable_free_entry(llt, lle);
240 }
241
242 static void
243 htable_free_tbl(struct lltable *llt)
244 {
245
246         free(llt->lle_head, M_LLTABLE);
247         free(llt, M_LLTABLE);
248 }
249
250 static void
251 llentries_unlink(struct lltable *llt, struct llentries *head)
252 {
253         struct llentry *lle, *next;
254
255         CK_LIST_FOREACH_SAFE(lle, head, lle_chain, next)
256                 llt->llt_unlink_entry(lle);
257 }
258
259 /*
260  * Helper function used to drop all mbufs in hold queue.
261  *
262  * Returns the number of held packets, if any, that were dropped.
263  */
264 size_t
265 lltable_drop_entry_queue(struct llentry *lle)
266 {
267         size_t pkts_dropped;
268         struct mbuf *next;
269
270         LLE_WLOCK_ASSERT(lle);
271
272         pkts_dropped = 0;
273         while ((lle->la_numheld > 0) && (lle->la_hold != NULL)) {
274                 next = lle->la_hold->m_nextpkt;
275                 m_freem(lle->la_hold);
276                 lle->la_hold = next;
277                 lle->la_numheld--;
278                 pkts_dropped++;
279         }
280
281         KASSERT(lle->la_numheld == 0,
282                 ("%s: la_numheld %d > 0, pkts_droped %zd", __func__,
283                  lle->la_numheld, pkts_dropped));
284
285         return (pkts_dropped);
286 }
287
288 void
289 lltable_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
290     const char *linkhdr, size_t linkhdrsize, int lladdr_off)
291 {
292
293         memcpy(lle->r_linkdata, linkhdr, linkhdrsize);
294         lle->r_hdrlen = linkhdrsize;
295         lle->ll_addr = &lle->r_linkdata[lladdr_off];
296         lle->la_flags |= LLE_VALID;
297         lle->r_flags |= RLLE_VALID;
298 }
299
300 /*
301  * Tries to update @lle link-level address.
302  * Since update requires AFDATA WLOCK, function
303  * drops @lle lock, acquires AFDATA lock and then acquires
304  * @lle lock to maintain lock order.
305  *
306  * Returns 1 on success.
307  */
308 int
309 lltable_try_set_entry_addr(struct ifnet *ifp, struct llentry *lle,
310     const char *linkhdr, size_t linkhdrsize, int lladdr_off)
311 {
312
313         /* Perform real LLE update */
314         /* use afdata WLOCK to update fields */
315         LLE_WLOCK_ASSERT(lle);
316         LLE_ADDREF(lle);
317         LLE_WUNLOCK(lle);
318         IF_AFDATA_WLOCK(ifp);
319         LLE_WLOCK(lle);
320
321         /*
322          * Since we droppped LLE lock, other thread might have deleted
323          * this lle. Check and return
324          */
325         if ((lle->la_flags & LLE_DELETED) != 0) {
326                 IF_AFDATA_WUNLOCK(ifp);
327                 LLE_FREE_LOCKED(lle);
328                 return (0);
329         }
330
331         /* Update data */
332         lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize, lladdr_off);
333
334         IF_AFDATA_WUNLOCK(ifp);
335
336         LLE_REMREF(lle);
337
338         return (1);
339 }
340
341  /*
342  * Helper function used to pre-compute full/partial link-layer
343  * header data suitable for feeding into if_output().
344  */
345 int
346 lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
347     char *buf, size_t *bufsize, int *lladdr_off)
348 {
349         struct if_encap_req ereq;
350         int error;
351
352         bzero(buf, *bufsize);
353         bzero(&ereq, sizeof(ereq));
354         ereq.buf = buf;
355         ereq.bufsize = *bufsize;
356         ereq.rtype = IFENCAP_LL;
357         ereq.family = family;
358         ereq.lladdr = lladdr;
359         ereq.lladdr_len = ifp->if_addrlen;
360         error = ifp->if_requestencap(ifp, &ereq);
361         if (error == 0) {
362                 *bufsize = ereq.bufsize;
363                 *lladdr_off = ereq.lladdr_off;
364         }
365
366         return (error);
367 }
368
369 /*
370  * Update link-layer header for given @lle after
371  * interface lladdr was changed.
372  */
373 static int
374 llentry_update_ifaddr(struct lltable *llt, struct llentry *lle, void *farg)
375 {
376         struct ifnet *ifp;
377         u_char linkhdr[LLE_MAX_LINKHDR];
378         size_t linkhdrsize;
379         u_char *lladdr;
380         int lladdr_off;
381
382         ifp = (struct ifnet *)farg;
383
384         lladdr = lle->ll_addr;
385
386         LLE_WLOCK(lle);
387         if ((lle->la_flags & LLE_VALID) == 0) {
388                 LLE_WUNLOCK(lle);
389                 return (0);
390         }
391
392         if ((lle->la_flags & LLE_IFADDR) != 0)
393                 lladdr = IF_LLADDR(ifp);
394
395         linkhdrsize = sizeof(linkhdr);
396         lltable_calc_llheader(ifp, llt->llt_af, lladdr, linkhdr, &linkhdrsize,
397             &lladdr_off);
398         memcpy(lle->r_linkdata, linkhdr, linkhdrsize);
399         LLE_WUNLOCK(lle);
400
401         return (0);
402 }
403
404 /*
405  * Update all calculated headers for given @llt
406  */
407 void
408 lltable_update_ifaddr(struct lltable *llt)
409 {
410
411         if (llt->llt_ifp->if_flags & IFF_LOOPBACK)
412                 return;
413
414         IF_AFDATA_WLOCK(llt->llt_ifp);
415         lltable_foreach_lle(llt, llentry_update_ifaddr, llt->llt_ifp);
416         IF_AFDATA_WUNLOCK(llt->llt_ifp);
417 }
418
419 /*
420  *
421  * Performs generic cleanup routines and frees lle.
422  *
423  * Called for non-linked entries, with callouts and
424  * other AF-specific cleanups performed.
425  *
426  * @lle must be passed WLOCK'ed
427  *
428  * Returns the number of held packets, if any, that were dropped.
429  */
430 size_t
431 llentry_free(struct llentry *lle)
432 {
433         size_t pkts_dropped;
434
435         LLE_WLOCK_ASSERT(lle);
436
437         KASSERT((lle->la_flags & LLE_LINKED) == 0, ("freeing linked lle"));
438
439         pkts_dropped = lltable_drop_entry_queue(lle);
440
441         /* cancel timer */
442         if (callout_stop(&lle->lle_timer) > 0)
443                 LLE_REMREF(lle);
444         LLE_FREE_LOCKED(lle);
445
446         return (pkts_dropped);
447 }
448
449 /*
450  * (al)locate an llentry for address dst (equivalent to rtalloc for new-arp).
451  *
452  * If found the llentry * is returned referenced and unlocked.
453  */
454 struct llentry *
455 llentry_alloc(struct ifnet *ifp, struct lltable *lt,
456     struct sockaddr_storage *dst)
457 {
458         struct epoch_tracker et;
459         struct llentry *la, *la_tmp;
460
461         NET_EPOCH_ENTER(et);
462         la = lla_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
463         NET_EPOCH_EXIT(et);
464
465         if (la != NULL) {
466                 LLE_ADDREF(la);
467                 LLE_WUNLOCK(la);
468                 return (la);
469         }
470
471         if ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0) {
472                 la = lltable_alloc_entry(lt, 0, (struct sockaddr *)dst);
473                 if (la == NULL)
474                         return (NULL);
475                 IF_AFDATA_WLOCK(ifp);
476                 LLE_WLOCK(la);
477                 /* Prefer any existing LLE over newly-created one */
478                 la_tmp = lla_lookup(lt, LLE_EXCLUSIVE, (struct sockaddr *)dst);
479                 if (la_tmp == NULL)
480                         lltable_link_entry(lt, la);
481                 IF_AFDATA_WUNLOCK(ifp);
482                 if (la_tmp != NULL) {
483                         lltable_free_entry(lt, la);
484                         la = la_tmp;
485                 }
486                 LLE_ADDREF(la);
487                 LLE_WUNLOCK(la);
488         }
489
490         return (la);
491 }
492
493 /*
494  * Free all entries from given table and free itself.
495  */
496
497 static int
498 lltable_free_cb(struct lltable *llt, struct llentry *lle, void *farg)
499 {
500         struct llentries *dchain;
501
502         dchain = (struct llentries *)farg;
503
504         LLE_WLOCK(lle);
505         CK_LIST_INSERT_HEAD(dchain, lle, lle_chain);
506
507         return (0);
508 }
509
510 /*
511  * Free all entries from given table and free itself.
512  */
513 void
514 lltable_free(struct lltable *llt)
515 {
516         struct llentry *lle, *next;
517         struct llentries dchain;
518
519         KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
520
521         lltable_unlink(llt);
522
523         CK_LIST_INIT(&dchain);
524         IF_AFDATA_WLOCK(llt->llt_ifp);
525         /* Push all lles to @dchain */
526         lltable_foreach_lle(llt, lltable_free_cb, &dchain);
527         llentries_unlink(llt, &dchain);
528         IF_AFDATA_WUNLOCK(llt->llt_ifp);
529
530         CK_LIST_FOREACH_SAFE(lle, &dchain, lle_chain, next) {
531                 llentry_free(lle);
532         }
533
534         llt->llt_free_tbl(llt);
535 }
536
537 #if 0
538 void
539 lltable_drain(int af)
540 {
541         struct lltable  *llt;
542         struct llentry  *lle;
543         int i;
544
545         LLTABLE_LIST_RLOCK();
546         SLIST_FOREACH(llt, &V_lltables, llt_link) {
547                 if (llt->llt_af != af)
548                         continue;
549
550                 for (i=0; i < llt->llt_hsize; i++) {
551                         CK_LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
552                                 LLE_WLOCK(lle);
553                                 if (lle->la_hold) {
554                                         m_freem(lle->la_hold);
555                                         lle->la_hold = NULL;
556                                 }
557                                 LLE_WUNLOCK(lle);
558                         }
559                 }
560         }
561         LLTABLE_LIST_RUNLOCK();
562 }
563 #endif
564
565 /*
566  * Deletes an address from given lltable.
567  * Used for userland interaction to remove
568  * individual entries. Skips entries added by OS.
569  */
570 int
571 lltable_delete_addr(struct lltable *llt, u_int flags,
572     const struct sockaddr *l3addr)
573 {
574         struct llentry *lle;
575         struct ifnet *ifp;
576
577         ifp = llt->llt_ifp;
578         IF_AFDATA_WLOCK(ifp);
579         lle = lla_lookup(llt, LLE_EXCLUSIVE, l3addr);
580
581         if (lle == NULL) {
582                 IF_AFDATA_WUNLOCK(ifp);
583                 return (ENOENT);
584         }
585         if ((lle->la_flags & LLE_IFADDR) != 0 && (flags & LLE_IFADDR) == 0) {
586                 IF_AFDATA_WUNLOCK(ifp);
587                 LLE_WUNLOCK(lle);
588                 return (EPERM);
589         }
590
591         lltable_unlink_entry(llt, lle);
592         IF_AFDATA_WUNLOCK(ifp);
593
594         llt->llt_delete_entry(llt, lle);
595
596         return (0);
597 }
598
599 void
600 lltable_prefix_free(int af, struct sockaddr *addr, struct sockaddr *mask,
601     u_int flags)
602 {
603         struct lltable *llt;
604
605         LLTABLE_LIST_RLOCK();
606         SLIST_FOREACH(llt, &V_lltables, llt_link) {
607                 if (llt->llt_af != af)
608                         continue;
609
610                 llt->llt_prefix_free(llt, addr, mask, flags);
611         }
612         LLTABLE_LIST_RUNLOCK();
613 }
614
615 struct lltable *
616 lltable_allocate_htbl(uint32_t hsize)
617 {
618         struct lltable *llt;
619         int i;
620
621         llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK | M_ZERO);
622         llt->llt_hsize = hsize;
623         llt->lle_head = malloc(sizeof(struct llentries) * hsize,
624             M_LLTABLE, M_WAITOK | M_ZERO);
625
626         for (i = 0; i < llt->llt_hsize; i++)
627                 CK_LIST_INIT(&llt->lle_head[i]);
628
629         /* Set some default callbacks */
630         llt->llt_link_entry = htable_link_entry;
631         llt->llt_unlink_entry = htable_unlink_entry;
632         llt->llt_prefix_free = htable_prefix_free;
633         llt->llt_foreach_entry = htable_foreach_lle;
634         llt->llt_free_tbl = htable_free_tbl;
635
636         return (llt);
637 }
638
639 /*
640  * Links lltable to global llt list.
641  */
642 void
643 lltable_link(struct lltable *llt)
644 {
645
646         LLTABLE_LIST_WLOCK();
647         SLIST_INSERT_HEAD(&V_lltables, llt, llt_link);
648         LLTABLE_LIST_WUNLOCK();
649 }
650
651 static void
652 lltable_unlink(struct lltable *llt)
653 {
654
655         LLTABLE_LIST_WLOCK();
656         SLIST_REMOVE(&V_lltables, llt, lltable, llt_link);
657         LLTABLE_LIST_WUNLOCK();
658
659 }
660
661 /*
662  * External methods used by lltable consumers
663  */
664
665 int
666 lltable_foreach_lle(struct lltable *llt, llt_foreach_cb_t *f, void *farg)
667 {
668
669         return (llt->llt_foreach_entry(llt, f, farg));
670 }
671
672 struct llentry *
673 lltable_alloc_entry(struct lltable *llt, u_int flags,
674     const struct sockaddr *l3addr)
675 {
676
677         return (llt->llt_alloc_entry(llt, flags, l3addr));
678 }
679
680 void
681 lltable_free_entry(struct lltable *llt, struct llentry *lle)
682 {
683
684         llt->llt_free_entry(llt, lle);
685 }
686
687 void
688 lltable_link_entry(struct lltable *llt, struct llentry *lle)
689 {
690
691         llt->llt_link_entry(llt, lle);
692 }
693
694 void
695 lltable_unlink_entry(struct lltable *llt, struct llentry *lle)
696 {
697
698         llt->llt_unlink_entry(lle);
699 }
700
701 void
702 lltable_fill_sa_entry(const struct llentry *lle, struct sockaddr *sa)
703 {
704         struct lltable *llt;
705
706         llt = lle->lle_tbl;
707         llt->llt_fill_sa_entry(lle, sa);
708 }
709
710 struct ifnet *
711 lltable_get_ifp(const struct lltable *llt)
712 {
713
714         return (llt->llt_ifp);
715 }
716
717 int
718 lltable_get_af(const struct lltable *llt)
719 {
720
721         return (llt->llt_af);
722 }
723
724 /*
725  * Called in route_output when rtm_flags contains RTF_LLDATA.
726  */
727 int
728 lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
729 {
730         struct sockaddr_dl *dl =
731             (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY];
732         struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST];
733         struct ifnet *ifp;
734         struct lltable *llt;
735         struct llentry *lle, *lle_tmp;
736         uint8_t linkhdr[LLE_MAX_LINKHDR];
737         size_t linkhdrsize;
738         int lladdr_off;
739         u_int laflags = 0;
740         int error;
741
742         KASSERT(dl != NULL && dl->sdl_family == AF_LINK,
743             ("%s: invalid dl\n", __func__));
744
745         ifp = ifnet_byindex(dl->sdl_index);
746         if (ifp == NULL) {
747                 log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
748                     __func__, dl->sdl_index);
749                 return EINVAL;
750         }
751
752         /* XXX linked list may be too expensive */
753         LLTABLE_LIST_RLOCK();
754         SLIST_FOREACH(llt, &V_lltables, llt_link) {
755                 if (llt->llt_af == dst->sa_family &&
756                     llt->llt_ifp == ifp)
757                         break;
758         }
759         LLTABLE_LIST_RUNLOCK();
760         KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
761
762         error = 0;
763
764         switch (rtm->rtm_type) {
765         case RTM_ADD:
766                 /* Add static LLE */
767                 laflags = 0;
768                 if (rtm->rtm_rmx.rmx_expire == 0)
769                         laflags = LLE_STATIC;
770                 lle = lltable_alloc_entry(llt, laflags, dst);
771                 if (lle == NULL)
772                         return (ENOMEM);
773
774                 linkhdrsize = sizeof(linkhdr);
775                 if (lltable_calc_llheader(ifp, dst->sa_family, LLADDR(dl),
776                     linkhdr, &linkhdrsize, &lladdr_off) != 0)
777                         return (EINVAL);
778                 lltable_set_entry_addr(ifp, lle, linkhdr, linkhdrsize,
779                     lladdr_off);
780                 if ((rtm->rtm_flags & RTF_ANNOUNCE))
781                         lle->la_flags |= LLE_PUB;
782                 lle->la_expire = rtm->rtm_rmx.rmx_expire;
783
784                 laflags = lle->la_flags;
785
786                 /* Try to link new entry */
787                 lle_tmp = NULL;
788                 IF_AFDATA_WLOCK(ifp);
789                 LLE_WLOCK(lle);
790                 lle_tmp = lla_lookup(llt, LLE_EXCLUSIVE, dst);
791                 if (lle_tmp != NULL) {
792                         /* Check if we are trying to replace immutable entry */
793                         if ((lle_tmp->la_flags & LLE_IFADDR) != 0) {
794                                 IF_AFDATA_WUNLOCK(ifp);
795                                 LLE_WUNLOCK(lle_tmp);
796                                 lltable_free_entry(llt, lle);
797                                 return (EPERM);
798                         }
799                         /* Unlink existing entry from table */
800                         lltable_unlink_entry(llt, lle_tmp);
801                 }
802                 lltable_link_entry(llt, lle);
803                 IF_AFDATA_WUNLOCK(ifp);
804
805                 if (lle_tmp != NULL) {
806                         EVENTHANDLER_INVOKE(lle_event, lle_tmp,LLENTRY_EXPIRED);
807                         lltable_free_entry(llt, lle_tmp);
808                 }
809
810                 /*
811                  * By invoking LLE handler here we might get
812                  * two events on static LLE entry insertion
813                  * in routing socket. However, since we might have
814                  * other subscribers we need to generate this event.
815                  */
816                 EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_RESOLVED);
817                 LLE_WUNLOCK(lle);
818 #ifdef INET
819                 /* gratuitous ARP */
820                 if ((laflags & LLE_PUB) && dst->sa_family == AF_INET)
821                         arprequest(ifp,
822                             &((struct sockaddr_in *)dst)->sin_addr,
823                             &((struct sockaddr_in *)dst)->sin_addr,
824                             (u_char *)LLADDR(dl));
825 #endif
826
827                 break;
828
829         case RTM_DELETE:
830                 return (lltable_delete_addr(llt, 0, dst));
831
832         default:
833                 error = EINVAL;
834         }
835
836         return (error);
837 }
838
839 #ifdef DDB
840 struct llentry_sa {
841         struct llentry          base;
842         struct sockaddr         l3_addr;
843 };
844
845 static void
846 llatbl_lle_show(struct llentry_sa *la)
847 {
848         struct llentry *lle;
849         uint8_t octet[6];
850
851         lle = &la->base;
852         db_printf("lle=%p\n", lle);
853         db_printf(" lle_next=%p\n", lle->lle_next.cle_next);
854         db_printf(" lle_lock=%p\n", &lle->lle_lock);
855         db_printf(" lle_tbl=%p\n", lle->lle_tbl);
856         db_printf(" lle_head=%p\n", lle->lle_head);
857         db_printf(" la_hold=%p\n", lle->la_hold);
858         db_printf(" la_numheld=%d\n", lle->la_numheld);
859         db_printf(" la_expire=%ju\n", (uintmax_t)lle->la_expire);
860         db_printf(" la_flags=0x%04x\n", lle->la_flags);
861         db_printf(" la_asked=%u\n", lle->la_asked);
862         db_printf(" la_preempt=%u\n", lle->la_preempt);
863         db_printf(" ln_state=%d\n", lle->ln_state);
864         db_printf(" ln_router=%u\n", lle->ln_router);
865         db_printf(" ln_ntick=%ju\n", (uintmax_t)lle->ln_ntick);
866         db_printf(" lle_refcnt=%d\n", lle->lle_refcnt);
867         bcopy(lle->ll_addr, octet, sizeof(octet));
868         db_printf(" ll_addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
869             octet[0], octet[1], octet[2], octet[3], octet[4], octet[5]);
870         db_printf(" lle_timer=%p\n", &lle->lle_timer);
871
872         switch (la->l3_addr.sa_family) {
873 #ifdef INET
874         case AF_INET:
875         {
876                 struct sockaddr_in *sin;
877                 char l3s[INET_ADDRSTRLEN];
878
879                 sin = (struct sockaddr_in *)&la->l3_addr;
880                 inet_ntoa_r(sin->sin_addr, l3s);
881                 db_printf(" l3_addr=%s\n", l3s);
882                 break;
883         }
884 #endif
885 #ifdef INET6
886         case AF_INET6:
887         {
888                 struct sockaddr_in6 *sin6;
889                 char l3s[INET6_ADDRSTRLEN];
890
891                 sin6 = (struct sockaddr_in6 *)&la->l3_addr;
892                 ip6_sprintf(l3s, &sin6->sin6_addr);
893                 db_printf(" l3_addr=%s\n", l3s);
894                 break;
895         }
896 #endif
897         default:
898                 db_printf(" l3_addr=N/A (af=%d)\n", la->l3_addr.sa_family);
899                 break;
900         }
901 }
902
903 DB_SHOW_COMMAND(llentry, db_show_llentry)
904 {
905
906         if (!have_addr) {
907                 db_printf("usage: show llentry <struct llentry *>\n");
908                 return;
909         }
910
911         llatbl_lle_show((struct llentry_sa *)addr);
912 }
913
914 static void
915 llatbl_llt_show(struct lltable *llt)
916 {
917         int i;
918         struct llentry *lle;
919
920         db_printf("llt=%p llt_af=%d llt_ifp=%p\n",
921             llt, llt->llt_af, llt->llt_ifp);
922
923         for (i = 0; i < llt->llt_hsize; i++) {
924                 CK_LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
925
926                         llatbl_lle_show((struct llentry_sa *)lle);
927                         if (db_pager_quit)
928                                 return;
929                 }
930         }
931 }
932
933 DB_SHOW_COMMAND(lltable, db_show_lltable)
934 {
935
936         if (!have_addr) {
937                 db_printf("usage: show lltable <struct lltable *>\n");
938                 return;
939         }
940
941         llatbl_llt_show((struct lltable *)addr);
942 }
943
944 DB_SHOW_ALL_COMMAND(lltables, db_show_all_lltables)
945 {
946         VNET_ITERATOR_DECL(vnet_iter);
947         struct lltable *llt;
948
949         VNET_FOREACH(vnet_iter) {
950                 CURVNET_SET_QUIET(vnet_iter);
951 #ifdef VIMAGE
952                 db_printf("vnet=%p\n", curvnet);
953 #endif
954                 SLIST_FOREACH(llt, &V_lltables, llt_link) {
955                         db_printf("llt=%p llt_af=%d llt_ifp=%p(%s)\n",
956                             llt, llt->llt_af, llt->llt_ifp,
957                             (llt->llt_ifp != NULL) ?
958                                 llt->llt_ifp->if_xname : "?");
959                         if (have_addr && addr != 0) /* verbose */
960                                 llatbl_llt_show(llt);
961                         if (db_pager_quit) {
962                                 CURVNET_RESTORE();
963                                 return;
964                         }
965                 }
966                 CURVNET_RESTORE();
967         }
968 }
969 #endif