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 970