1 /* $NetBSD: if.c,v 1.101 2001/12/02 19:44:25 abs Exp $ */ 2 3 /*- 4 * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by William Studnemund and Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. Neither the name of the project nor the names of its contributors 52 * may be used to endorse or promote products derived from this software 53 * without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 */ 67 68 /* 69 * Copyright (c) 1980, 1986, 1993 70 * The Regents of the University of California. All rights reserved. 71 * 72 * Redistribution and use in source and binary forms, with or without 73 * modification, are permitted provided that the following conditions 74 * are met: 75 * 1. Redistributions of source code must retain the above copyright 76 * notice, this list of conditions and the following disclaimer. 77 * 2. Redistributions in binary form must reproduce the above copyright 78 * notice, this list of conditions and the following disclaimer in the 79 * documentation and/or other materials provided with the distribution. 80 * 3. All advertising materials mentioning features or use of this software 81 * must display the following acknowledgement: 82 * This product includes software developed by the University of 83 * California, Berkeley and its contributors. 84 * 4. Neither the name of the University nor the names of its contributors 85 * may be used to endorse or promote products derived from this software 86 * without specific prior written permission. 87 * 88 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 91 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 95 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 96 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 97 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 98 * SUCH DAMAGE. 99 * 100 * @(#)if.c 8.5 (Berkeley) 1/9/95 101 */ 102 103 #include <sys/cdefs.h> 104 __KERNEL_RCSID(0, "$NetBSD: if.c,v 1.101 2001/12/02 19:44:25 abs Exp $"); 105 106 #include "opt_inet.h" 107 108 #include "opt_compat_linux.h" 109 #include "opt_compat_svr4.h" 110 #include "opt_compat_43.h" 111 #include "opt_atalk.h" 112 #include "opt_pfil_hooks.h" 113 114 #include <sys/param.h> 115 #include <sys/mbuf.h> 116 #include <sys/systm.h> 117 #include <sys/callout.h> 118 #include <sys/proc.h> 119 #include <sys/socket.h> 120 #include <sys/socketvar.h> 121 #include <sys/domain.h> 122 #include <sys/protosw.h> 123 #include <sys/kernel.h> 124 #include <sys/ioctl.h> 125 126 #include <net/if.h> 127 #include <net/if_dl.h> 128 #include <net/if_ether.h> 129 #include <net/if_ieee80211.h> 130 #include <net/if_types.h> 131 #include <net/radix.h> 132 #include <net/route.h> 133 #include <net/netisr.h> 134 #ifdef NETATALK 135 #include <netatalk/at_extern.h> 136 #include <netatalk/at.h> 137 #endif 138 139 #ifdef INET6 140 /*XXX*/ 141 #include <netinet/in.h> 142 #include <netinet6/in6_var.h> 143 #endif 144 145 int ifqmaxlen = IFQ_MAXLEN; 146 struct callout if_slowtimo_ch; 147 148 #ifdef INET6 149 /* 150 * XXX: declare here to avoid to include many inet6 related files.. 151 * should be more generalized? 152 */ 153 extern void nd6_setmtu __P((struct ifnet *)); 154 #endif 155 156 int if_rt_walktree __P((struct radix_node *, void *)); 157 158 struct if_clone *if_clone_lookup __P((const char *, int *)); 159 int if_clone_list __P((struct if_clonereq *)); 160 161 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); 162 int if_cloners_count; 163 164 #if defined(INET) || defined(INET6) || defined(NETATALK) || defined(NS) || \ 165 defined(ISO) || defined(CCITT) || defined(NATM) 166 static void if_detach_queues __P((struct ifnet *, struct ifqueue *)); 167 #endif 168 169 /* 170 * Network interface utility routines. 171 * 172 * Routines with ifa_ifwith* names take sockaddr *'s as 173 * parameters. 174 */ 175 void 176 ifinit() 177 { 178 179 callout_init(&if_slowtimo_ch); 180 if_slowtimo(NULL); 181 } 182 183 /* 184 * Null routines used while an interface is going away. These routines 185 * just return an error. 186 */ 187 188 int 189 if_nulloutput(ifp, m, so, rt) 190 struct ifnet *ifp; 191 struct mbuf *m; 192 struct sockaddr *so; 193 struct rtentry *rt; 194 { 195 196 return (ENXIO); 197 } 198 199 void 200 if_nullinput(ifp, m) 201 struct ifnet *ifp; 202 struct mbuf *m; 203 { 204 205 /* Nothing. */ 206 } 207 208 void 209 if_nullstart(ifp) 210 struct ifnet *ifp; 211 { 212 213 /* Nothing. */ 214 } 215 216 int 217 if_nullioctl(ifp, cmd, data) 218 struct ifnet *ifp; 219 u_long cmd; 220 caddr_t data; 221 { 222 223 return (ENXIO); 224 } 225 226 int 227 if_nullinit(ifp) 228 struct ifnet *ifp; 229 { 230 231 return (ENXIO); 232 } 233 234 void 235 if_nullstop(ifp, disable) 236 struct ifnet *ifp; 237 int disable; 238 { 239 240 /* Nothing. */ 241 } 242 243 void 244 if_nullwatchdog(ifp) 245 struct ifnet *ifp; 246 { 247 248 /* Nothing. */ 249 } 250 251 void 252 if_nulldrain(ifp) 253 struct ifnet *ifp; 254 { 255 256 /* Nothing. */ 257 } 258 259 int if_index = 0; 260 struct ifaddr **ifnet_addrs = NULL; 261 struct ifnet **ifindex2ifnet = NULL; 262 263 /* 264 * Allocate the link level name for the specified interface. This 265 * is an attachment helper. It must be called after ifp->if_addrlen 266 * is initialized, which may not be the case when if_attach() is 267 * called. 268 */ 269 void 270 if_alloc_sadl(struct ifnet *ifp) 271 { 272 unsigned socksize, ifasize; 273 int namelen, masklen; 274 struct sockaddr_dl *sdl; 275 struct ifaddr *ifa; 276 277 /* 278 * If the interface already has a link name, release it 279 * now. This is useful for interfaces that can change 280 * link types, and thus switch link names often. 281 */ 282 if (ifp->if_sadl != NULL) 283 if_free_sadl(ifp); 284 285 namelen = strlen(ifp->if_xname); 286 masklen = offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; 287 socksize = masklen + ifp->if_addrlen; 288 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 289 if (socksize < sizeof(*sdl)) 290 socksize = sizeof(*sdl); 291 socksize = ROUNDUP(socksize); 292 ifasize = sizeof(*ifa) + 2 * socksize; 293 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 294 memset((caddr_t)ifa, 0, ifasize); 295 sdl = (struct sockaddr_dl *)(ifa + 1); 296 sdl->sdl_len = socksize; 297 sdl->sdl_family = AF_LINK; 298 bcopy(ifp->if_xname, sdl->sdl_data, namelen); 299 sdl->sdl_nlen = namelen; 300 sdl->sdl_alen = ifp->if_addrlen; 301 sdl->sdl_index = ifp->if_index; 302 sdl->sdl_type = ifp->if_type; 303 ifnet_addrs[ifp->if_index] = ifa; 304 IFAREF(ifa); 305 ifa->ifa_ifp = ifp; 306 ifa->ifa_rtrequest = link_rtrequest; 307 TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list); 308 IFAREF(ifa); 309 ifa->ifa_addr = (struct sockaddr *)sdl; 310 ifp->if_sadl = sdl; 311 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 312 ifa->ifa_netmask = (struct sockaddr *)sdl; 313 sdl->sdl_len = masklen; 314 while (namelen != 0) 315 sdl->sdl_data[--namelen] = 0xff; 316 } 317 318 /* 319 * Free the link level name for the specified interface. This is 320 * a detach helper. This is called from if_detach() or from 321 * link layer type specific detach functions. 322 */ 323 void 324 if_free_sadl(struct ifnet *ifp) 325 { 326 struct ifaddr *ifa; 327 int s; 328 329 ifa = ifnet_addrs[ifp->if_index]; 330 if (ifa == NULL) { 331 KASSERT(ifp->if_sadl == NULL); 332 return; 333 } 334 335 KASSERT(ifp->if_sadl != NULL); 336 337 s = splnet(); 338 rtinit(ifa, RTM_DELETE, 0); 339 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); 340 IFAFREE(ifa); 341 342 ifp->if_sadl = NULL; 343 344 ifnet_addrs[ifp->if_index] = NULL; 345 IFAFREE(ifa); 346 splx(s); 347 } 348 349 /* 350 * Attach an interface to the 351 * list of "active" interfaces. 352 */ 353 void 354 if_attach(ifp) 355 struct ifnet *ifp; 356 { 357 static size_t if_indexlim = 8; 358 359 if (if_index == 0) 360 TAILQ_INIT(&ifnet); 361 TAILQ_INIT(&ifp->if_addrlist); 362 TAILQ_INSERT_TAIL(&ifnet, ifp, if_list); 363 ifp->if_index = ++if_index; 364 365 /* 366 * We have some arrays that should be indexed by if_index. 367 * since if_index will grow dynamically, they should grow too. 368 * struct ifadd **ifnet_addrs 369 * struct ifnet **ifindex2ifnet 370 */ 371 if (ifnet_addrs == 0 || ifindex2ifnet == 0 || 372 ifp->if_index >= if_indexlim) { 373 size_t n; 374 caddr_t q; 375 376 while (ifp->if_index >= if_indexlim) 377 if_indexlim <<= 1; 378 379 /* grow ifnet_addrs */ 380 n = if_indexlim * sizeof(struct ifaddr *); 381 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); 382 memset(q, 0, n); 383 if (ifnet_addrs) { 384 bcopy((caddr_t)ifnet_addrs, q, n/2); 385 free((caddr_t)ifnet_addrs, M_IFADDR); 386 } 387 ifnet_addrs = (struct ifaddr **)q; 388 389 /* grow ifindex2ifnet */ 390 n = if_indexlim * sizeof(struct ifnet *); 391 q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK); 392 memset(q, 0, n); 393 if (ifindex2ifnet) { 394 bcopy((caddr_t)ifindex2ifnet, q, n/2); 395 free((caddr_t)ifindex2ifnet, M_IFADDR); 396 } 397 ifindex2ifnet = (struct ifnet **)q; 398 } 399 400 ifindex2ifnet[ifp->if_index] = ifp; 401 402 /* 403 * Link level name is allocated later by a separate call to 404 * if_alloc_sadl(). 405 */ 406 407 if (ifp->if_snd.ifq_maxlen == 0) 408 ifp->if_snd.ifq_maxlen = ifqmaxlen; 409 ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */ 410 411 ifp->if_link_state = LINK_STATE_UNKNOWN; 412 413 ifp->if_capenable = 0; 414 ifp->if_csum_flags_tx = 0; 415 ifp->if_csum_flags_rx = 0; 416 417 #ifdef ALTQ 418 ifp->if_snd.altq_type = 0; 419 ifp->if_snd.altq_disc = NULL; 420 ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE; 421 ifp->if_snd.altq_tbr = NULL; 422 ifp->if_snd.altq_ifp = ifp; 423 #endif 424 425 #ifdef PFIL_HOOKS 426 ifp->if_pfil.ph_type = PFIL_TYPE_IFNET; 427 ifp->if_pfil.ph_ifnet = ifp; 428 if (pfil_head_register(&ifp->if_pfil) != 0) 429 printf("%s: WARNING: unable to register pfil hook\n", 430 ifp->if_xname); 431 #endif 432 433 /* Announce the interface. */ 434 rt_ifannouncemsg(ifp, IFAN_ARRIVAL); 435 } 436 437 /* 438 * Deactivate an interface. This points all of the procedure 439 * handles at error stubs. May be called from interrupt context. 440 */ 441 void 442 if_deactivate(ifp) 443 struct ifnet *ifp; 444 { 445 int s; 446 447 s = splnet(); 448 449 ifp->if_output = if_nulloutput; 450 ifp->if_input = if_nullinput; 451 ifp->if_start = if_nullstart; 452 ifp->if_ioctl = if_nullioctl; 453 ifp->if_init = if_nullinit; 454 ifp->if_stop = if_nullstop; 455 ifp->if_watchdog = if_nullwatchdog; 456 ifp->if_drain = if_nulldrain; 457 458 /* No more packets may be enqueued. */ 459 ifp->if_snd.ifq_maxlen = 0; 460 461 splx(s); 462 } 463 464 /* 465 * Detach an interface from the list of "active" interfaces, 466 * freeing any resources as we go along. 467 * 468 * NOTE: This routine must be called with a valid thread context, 469 * as it may block. 470 */ 471 void 472 if_detach(ifp) 473 struct ifnet *ifp; 474 { 475 struct socket so; 476 struct ifaddr *ifa; 477 #ifdef IFAREF_DEBUG 478 struct ifaddr *last_ifa = NULL; 479 #endif 480 struct domain *dp; 481 struct protosw *pr; 482 struct radix_node_head *rnh; 483 int s, i, family, purged; 484 485 /* 486 * XXX It's kind of lame that we have to have the 487 * XXX socket structure... 488 */ 489 memset(&so, 0, sizeof(so)); 490 491 s = splnet(); 492 493 /* 494 * Do an if_down() to give protocols a chance to do something. 495 */ 496 if_down(ifp); 497 498 #ifdef ALTQ 499 if (ALTQ_IS_ENABLED(&ifp->if_snd)) 500 altq_disable(&ifp->if_snd); 501 if (ALTQ_IS_ATTACHED(&ifp->if_snd)) 502 altq_detach(&ifp->if_snd); 503 #endif 504 505 #ifdef PFIL_HOOKS 506 (void) pfil_head_unregister(&ifp->if_pfil); 507 #endif 508 509 if_free_sadl(ifp); 510 511 /* 512 * Rip all the addresses off the interface. This should make 513 * all of the routes go away. 514 */ 515 while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) { 516 family = ifa->ifa_addr->sa_family; 517 #ifdef IFAREF_DEBUG 518 printf("if_detach: ifaddr %p, family %d, refcnt %d\n", 519 ifa, family, ifa->ifa_refcnt); 520 if (last_ifa != NULL && ifa == last_ifa) 521 panic("if_detach: loop detected"); 522 last_ifa = ifa; 523 #endif 524 if (family == AF_LINK) { 525 /* 526 * XXX This case may now be obsolete by 527 * XXX the call to if_free_sadl(). 528 */ 529 rtinit(ifa, RTM_DELETE, 0); 530 TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list); 531 IFAFREE(ifa); 532 } else { 533 dp = pffinddomain(family); 534 #ifdef DIAGNOSTIC 535 if (dp == NULL) 536 panic("if_detach: no domain for AF %d\n", 537 family); 538 #endif 539 purged = 0; 540 for (pr = dp->dom_protosw; 541 pr < dp->dom_protoswNPROTOSW; pr++) { 542 so.so_proto = pr; 543 if (pr->pr_usrreq != NULL) { 544 (void) (*pr->pr_usrreq)(&so, 545 PRU_PURGEIF, NULL, NULL, 546 (struct mbuf *) ifp, curproc); 547 purged = 1; 548 } 549 } 550 if (purged == 0) { 551 /* 552 * XXX What's really the best thing to do 553 * XXX here? --thorpej@netbsd.org 554 */ 555 printf("if_detach: WARNING: AF %d not purged\n", 556 family); 557 } 558 } 559 } 560 561 /* Walk the routing table looking for straglers. */ 562 for (i = 0; i <= AF_MAX; i++) { 563 if ((rnh = rt_tables[i]) != NULL) 564 (void) (*rnh->rnh_walktree)(rnh, if_rt_walktree, ifp); 565 } 566 567 /* Announce that the interface is gone. */ 568 rt_ifannouncemsg(ifp, IFAN_DEPARTURE); 569 570 ifindex2ifnet[ifp->if_index] = NULL; 571 572 TAILQ_REMOVE(&ifnet, ifp, if_list); 573 574 /* 575 * remove packets came from ifp, from software interrupt queues. 576 * net/netisr_dispatch.h is not usable, as some of them use 577 * strange queue names. 578 */ 579 #define IF_DETACH_QUEUES(x) \ 580 do { \ 581 extern struct ifqueue x; \ 582 if_detach_queues(ifp, & x); \ 583 } while (0) 584 #ifdef INET 585 #if NARP > 0 586 IF_DETACH_QUEUES(arpintrq); 587 #endif 588 IF_DETACH_QUEUES(ipintrq); 589 #endif 590 #ifdef INET6 591 IF_DETACH_QUEUES(ip6intrq); 592 #endif 593 #ifdef NETATALK 594 IF_DETACH_QUEUES(atintrq1); 595 IF_DETACH_QUEUES(atintrq2); 596 #endif 597 #ifdef NS 598 IF_DETACH_QUEUES(nsintrq); 599 #endif 600 #ifdef ISO 601 IF_DETACH_QUEUES(clnlintrq); 602 #endif 603 #ifdef CCITT 604 IF_DETACH_QUEUES(llcintrq); 605 IF_DETACH_QUEUES(hdintrq); 606 #endif 607 #ifdef NATM 608 IF_DETACH_QUEUES(natmintrq); 609 #endif 610 #undef IF_DETACH_QUEUES 611 612 splx(s); 613 } 614 615 #if defined(INET) || defined(INET6) || defined(NETATALK) || defined(NS) || \ 616 defined(ISO) || defined(CCITT) || defined(NATM) 617 static void 618 if_detach_queues(ifp, q) 619 struct ifnet *ifp; 620 struct ifqueue *q; 621 { 622 struct mbuf *m, *prev, *next; 623 624 prev = NULL; 625 for (m = q->ifq_head; m; m = next) { 626 next = m->m_nextpkt; 627 #ifdef DIAGNOSTIC 628 if ((m->m_flags & M_PKTHDR) == 0) { 629 prev = m; 630 continue; 631 } 632 #endif 633 if (m->m_pkthdr.rcvif != ifp) { 634 prev = m; 635 continue; 636 } 637 638 if (prev) 639 prev->m_nextpkt = m->m_nextpkt; 640 else 641 q->ifq_head = m->m_nextpkt; 642 if (q->ifq_tail == m) 643 q->ifq_tail = prev; 644 q->ifq_len--; 645 646 m->m_nextpkt = NULL; 647 m_freem(m); 648 IF_DROP(q); 649 } 650 } 651 #endif /* defined(INET) || ... */ 652 653 /* 654 * Callback for a radix tree walk to delete all references to an 655 * ifnet. 656 */ 657 int 658 if_rt_walktree(rn, v) 659 struct radix_node *rn; 660 void *v; 661 { 662 struct ifnet *ifp = (struct ifnet *)v; 663 struct rtentry *rt = (struct rtentry *)rn; 664 int error; 665 666 if (rt->rt_ifp == ifp) { 667 /* Delete the entry. */ 668 error = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, 669 rt_mask(rt), rt->rt_flags, NULL); 670 if (error) 671 printf("%s: warning: unable to delete rtentry @ %p, " 672 "error = %d\n", ifp->if_xname, rt, error); 673 } 674 return (0); 675 } 676 677 /* 678 * Create a clone network interface. 679 */ 680 int 681 if_clone_create(name) 682 const char *name; 683 { 684 struct if_clone *ifc; 685 int unit; 686 687 ifc = if_clone_lookup(name, &unit); 688 if (ifc == NULL) 689 return (EINVAL); 690 691 if (ifunit(name) != NULL) 692 return (EEXIST); 693 694 return ((*ifc->ifc_create)(ifc, unit)); 695 } 696 697 /* 698 * Destroy a clone network interface. 699 */ 700 int 701 if_clone_destroy(name) 702 const char *name; 703 { 704 struct if_clone *ifc; 705 struct ifnet *ifp; 706 707 ifc = if_clone_lookup(name, NULL); 708 if (ifc == NULL) 709 return (EINVAL); 710 711 ifp = ifunit(name); 712 if (ifp == NULL) 713 return (ENXIO); 714 715 if (ifc->ifc_destroy == NULL) 716 return (EOPNOTSUPP); 717 718 (*ifc->ifc_destroy)(ifp); 719 return (0); 720 } 721 722 /* 723 * Look up a network interface cloner. 724 */ 725 struct if_clone * 726 if_clone_lookup(name, unitp) 727 const char *name; 728 int *unitp; 729 { 730 struct if_clone *ifc; 731 const char *cp; 732 int i; 733 734 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) { 735 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) { 736 if (ifc->ifc_name[i] != *cp) 737 goto next_ifc; 738 } 739 goto found_name; 740 next_ifc: 741 ifc = LIST_NEXT(ifc, ifc_list); 742 } 743 744 /* No match. */ 745 return (NULL); 746 747 found_name: 748 for (i = 0; *cp != '\0'; cp++) { 749 if (*cp < '0' || *cp > '9') { 750 /* Bogus unit number. */ 751 return (NULL); 752 } 753 i = (i * 10) + (*cp - '0'); 754 } 755 756 if (unitp != NULL) 757 *unitp = i; 758 return (ifc); 759 } 760 761 /* 762 * Register a network interface cloner. 763 */ 764 void 765 if_clone_attach(ifc) 766 struct if_clone *ifc; 767 { 768 769 LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list); 770 if_cloners_count++; 771 } 772 773 /* 774 * Unregister a network interface cloner. 775 */ 776 void 777 if_clone_detach(ifc) 778 struct if_clone *ifc; 779 { 780 781 LIST_REMOVE(ifc, ifc_list); 782 if_cloners_count--; 783 } 784 785 /* 786 * Provide list of interface cloners to userspace. 787 */ 788 int 789 if_clone_list(ifcr) 790 struct if_clonereq *ifcr; 791 { 792 char outbuf[IFNAMSIZ], *dst; 793 struct if_clone *ifc; 794 int count, error = 0; 795 796 ifcr->ifcr_total = if_cloners_count; 797 if ((dst = ifcr->ifcr_buffer) == NULL) { 798 /* Just asking how many there are. */ 799 return (0); 800 } 801 802 if (ifcr->ifcr_count < 0) 803 return (EINVAL); 804 805 count = (if_cloners_count < ifcr->ifcr_count) ? 806 if_cloners_count : ifcr->ifcr_count; 807 808 for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0; 809 ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) { 810 strncpy(outbuf, ifc->ifc_name, IFNAMSIZ); 811 outbuf[IFNAMSIZ - 1] = '\0'; /* sanity */ 812 error = copyout(outbuf, dst, IFNAMSIZ); 813 if (error) 814 break; 815 } 816 817 return (error); 818 } 819 820 /* 821 * Locate an interface based on a complete address. 822 */ 823 /*ARGSUSED*/ 824 struct ifaddr * 825 ifa_ifwithaddr(addr) 826 struct sockaddr *addr; 827 { 828 struct ifnet *ifp; 829 struct ifaddr *ifa; 830 831 #define equal(a1, a2) \ 832 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 833 834 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 835 ifp = TAILQ_NEXT(ifp, if_list)) { 836 if (ifp->if_output == if_nulloutput) 837 continue; 838 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 839 ifa = TAILQ_NEXT(ifa, ifa_list)) { 840 if (ifa->ifa_addr->sa_family != addr->sa_family) 841 continue; 842 if (equal(addr, ifa->ifa_addr)) 843 return (ifa); 844 if ((ifp->if_flags & IFF_BROADCAST) && 845 ifa->ifa_broadaddr && 846 /* IP6 doesn't have broadcast */ 847 ifa->ifa_broadaddr->sa_len != 0 && 848 equal(ifa->ifa_broadaddr, addr)) 849 return (ifa); 850 } 851 } 852 return (NULL); 853 } 854 855 /* 856 * Locate the point to point interface with a given destination address. 857 */ 858 /*ARGSUSED*/ 859 struct ifaddr * 860 ifa_ifwithdstaddr(addr) 861 struct sockaddr *addr; 862 { 863 struct ifnet *ifp; 864 struct ifaddr *ifa; 865 866 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 867 ifp = TAILQ_NEXT(ifp, if_list)) { 868 if (ifp->if_output == if_nulloutput) 869 continue; 870 if (ifp->if_flags & IFF_POINTOPOINT) { 871 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 872 ifa = TAILQ_NEXT(ifa, ifa_list)) { 873 if (ifa->ifa_addr->sa_family != 874 addr->sa_family || 875 ifa->ifa_dstaddr == NULL) 876 continue; 877 if (equal(addr, ifa->ifa_dstaddr)) 878 return (ifa); 879 } 880 } 881 } 882 return (NULL); 883 } 884 885 /* 886 * Find an interface on a specific network. If many, choice 887 * is most specific found. 888 */ 889 struct ifaddr * 890 ifa_ifwithnet(addr) 891 struct sockaddr *addr; 892 { 893 struct ifnet *ifp; 894 struct ifaddr *ifa; 895 struct sockaddr_dl *sdl; 896 struct ifaddr *ifa_maybe = 0; 897 u_int af = addr->sa_family; 898 char *addr_data = addr->sa_data, *cplim; 899 900 if (af == AF_LINK) { 901 sdl = (struct sockaddr_dl *)addr; 902 if (sdl->sdl_index && sdl->sdl_index <= if_index && 903 ifindex2ifnet[sdl->sdl_index]->if_output != if_nulloutput) 904 return (ifnet_addrs[sdl->sdl_index]); 905 } 906 #ifdef NETATALK 907 if (af == AF_APPLETALK) { 908 struct sockaddr_at *sat, *sat2; 909 sat = (struct sockaddr_at *)addr; 910 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 911 ifp = TAILQ_NEXT(ifp, if_list)) { 912 if (ifp->if_output == if_nulloutput) 913 continue; 914 ifa = at_ifawithnet((struct sockaddr_at *)addr, ifp); 915 if (ifa == NULL) 916 continue; 917 sat2 = (struct sockaddr_at *)ifa->ifa_addr; 918 if (sat2->sat_addr.s_net == sat->sat_addr.s_net) 919 return (ifa); /* exact match */ 920 if (ifa_maybe == NULL) { 921 /* else keep the if with the rigth range */ 922 ifa_maybe = ifa; 923 } 924 } 925 return (ifa_maybe); 926 } 927 #endif 928 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 929 ifp = TAILQ_NEXT(ifp, if_list)) { 930 if (ifp->if_output == if_nulloutput) 931 continue; 932 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 933 ifa = TAILQ_NEXT(ifa, ifa_list)) { 934 char *cp, *cp2, *cp3; 935 936 if (ifa->ifa_addr->sa_family != af || 937 ifa->ifa_netmask == 0) 938 next: continue; 939 cp = addr_data; 940 cp2 = ifa->ifa_addr->sa_data; 941 cp3 = ifa->ifa_netmask->sa_data; 942 cplim = (char *)ifa->ifa_netmask + 943 ifa->ifa_netmask->sa_len; 944 while (cp3 < cplim) { 945 if ((*cp++ ^ *cp2++) & *cp3++) { 946 /* want to continue for() loop */ 947 goto next; 948 } 949 } 950 if (ifa_maybe == 0 || 951 rn_refines((caddr_t)ifa->ifa_netmask, 952 (caddr_t)ifa_maybe->ifa_netmask)) 953 ifa_maybe = ifa; 954 } 955 } 956 return (ifa_maybe); 957 } 958 959 /* 960 * Find the interface of the addresss. 961 */ 962 struct ifaddr * 963 ifa_ifwithladdr(addr) 964 struct sockaddr *addr; 965 { 966 struct ifaddr *ia; 967 968 if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr)) || 969 (ia = ifa_ifwithnet(addr))) 970 return (ia); 971 return (NULL); 972 } 973 974 /* 975 * Find an interface using a specific address family 976 */ 977 struct ifaddr * 978 ifa_ifwithaf(af) 979 int af; 980 { 981 struct ifnet *ifp; 982 struct ifaddr *ifa; 983 984 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 985 ifp = TAILQ_NEXT(ifp, if_list)) { 986 if (ifp->if_output == if_nulloutput) 987 continue; 988 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 989 ifa = TAILQ_NEXT(ifa, ifa_list)) { 990 if (ifa->ifa_addr->sa_family == af) 991 return (ifa); 992 } 993 } 994 return (NULL); 995 } 996 997 /* 998 * Find an interface address specific to an interface best matching 999 * a given address. 1000 */ 1001 struct ifaddr * 1002 ifaof_ifpforaddr(addr, ifp) 1003 struct sockaddr *addr; 1004 struct ifnet *ifp; 1005 { 1006 struct ifaddr *ifa; 1007 char *cp, *cp2, *cp3; 1008 char *cplim; 1009 struct ifaddr *ifa_maybe = 0; 1010 u_int af = addr->sa_family; 1011 1012 if (ifp->if_output == if_nulloutput) 1013 return (NULL); 1014 1015 if (af >= AF_MAX) 1016 return (NULL); 1017 1018 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 1019 ifa = TAILQ_NEXT(ifa, ifa_list)) { 1020 if (ifa->ifa_addr->sa_family != af) 1021 continue; 1022 ifa_maybe = ifa; 1023 if (ifa->ifa_netmask == 0) { 1024 if (equal(addr, ifa->ifa_addr) || 1025 (ifa->ifa_dstaddr && 1026 equal(addr, ifa->ifa_dstaddr))) 1027 return (ifa); 1028 continue; 1029 } 1030 cp = addr->sa_data; 1031 cp2 = ifa->ifa_addr->sa_data; 1032 cp3 = ifa->ifa_netmask->sa_data; 1033 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 1034 for (; cp3 < cplim; cp3++) { 1035 if ((*cp++ ^ *cp2++) & *cp3) 1036 break; 1037 } 1038 if (cp3 == cplim) 1039 return (ifa); 1040 } 1041 return (ifa_maybe); 1042 } 1043 1044 /* 1045 * Default action when installing a route with a Link Level gateway. 1046 * Lookup an appropriate real ifa to point to. 1047 * This should be moved to /sys/net/link.c eventually. 1048 */ 1049 void 1050 link_rtrequest(cmd, rt, info) 1051 int cmd; 1052 struct rtentry *rt; 1053 struct rt_addrinfo *info; 1054 { 1055 struct ifaddr *ifa; 1056 struct sockaddr *dst; 1057 struct ifnet *ifp; 1058 1059 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 1060 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 1061 return; 1062 if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { 1063 IFAFREE(rt->rt_ifa); 1064 rt->rt_ifa = ifa; 1065 IFAREF(ifa); 1066 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 1067 ifa->ifa_rtrequest(cmd, rt, info); 1068 } 1069 } 1070 1071 /* 1072 * Mark an interface down and notify protocols of 1073 * the transition. 1074 * NOTE: must be called at splsoftnet or equivalent. 1075 */ 1076 void 1077 if_down(ifp) 1078 struct ifnet *ifp; 1079 { 1080 struct ifaddr *ifa; 1081 1082 ifp->if_flags &= ~IFF_UP; 1083 microtime(&ifp->if_lastchange); 1084 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 1085 ifa = TAILQ_NEXT(ifa, ifa_list)) 1086 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 1087 IFQ_PURGE(&ifp->if_snd); 1088 rt_ifmsg(ifp); 1089 } 1090 1091 /* 1092 * Mark an interface up and notify protocols of 1093 * the transition. 1094 * NOTE: must be called at splsoftnet or equivalent. 1095 */ 1096 void 1097 if_up(ifp) 1098 struct ifnet *ifp; 1099 { 1100 #ifdef notyet 1101 struct ifaddr *ifa; 1102 #endif 1103 1104 ifp->if_flags |= IFF_UP; 1105 microtime(&ifp->if_lastchange); 1106 #ifdef notyet 1107 /* this has no effect on IP, and will kill all ISO connections XXX */ 1108 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; 1109 ifa = TAILQ_NEXT(ifa, ifa_list)) 1110 pfctlinput(PRC_IFUP, ifa->ifa_addr); 1111 #endif 1112 rt_ifmsg(ifp); 1113 #ifdef INET6 1114 in6_if_up(ifp); 1115 #endif 1116 } 1117 1118 /* 1119 * Handle interface watchdog timer routines. Called 1120 * from softclock, we decrement timers (if set) and 1121 * call the appropriate interface routine on expiration. 1122 */ 1123 void 1124 if_slowtimo(arg) 1125 void *arg; 1126 { 1127 struct ifnet *ifp; 1128 int s = splnet(); 1129 1130 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 1131 ifp = TAILQ_NEXT(ifp, if_list)) { 1132 if (ifp->if_timer == 0 || --ifp->if_timer) 1133 continue; 1134 if (ifp->if_watchdog) 1135 (*ifp->if_watchdog)(ifp); 1136 } 1137 splx(s); 1138 callout_reset(&if_slowtimo_ch, hz / IFNET_SLOWHZ, 1139 if_slowtimo, NULL); 1140 } 1141 1142 /* 1143 * Set/clear promiscuous mode on interface ifp based on the truth value 1144 * of pswitch. The calls are reference counted so that only the first 1145 * "on" request actually has an effect, as does the final "off" request. 1146 * Results are undefined if the "off" and "on" requests are not matched. 1147 */ 1148 int 1149 ifpromisc(ifp, pswitch) 1150 struct ifnet *ifp; 1151 int pswitch; 1152 { 1153 int pcount, ret; 1154 short flags; 1155 struct ifreq ifr; 1156 1157 pcount = ifp->if_pcount; 1158 flags = ifp->if_flags; 1159 if (pswitch) { 1160 /* 1161 * Allow the device to be "placed" into promiscuous 1162 * mode even if it is not configured up. It will 1163 * consult IFF_PROMISC when it is is brought up. 1164 */ 1165 if (ifp->if_pcount++ != 0) 1166 return (0); 1167 ifp->if_flags |= IFF_PROMISC; 1168 if ((ifp->if_flags & IFF_UP) == 0) 1169 return (0); 1170 } else { 1171 if (--ifp->if_pcount > 0) 1172 return (0); 1173 ifp->if_flags &= ~IFF_PROMISC; 1174 /* 1175 * If the device is not configured up, we should not need to 1176 * turn off promiscuous mode (device should have turned it 1177 * off when interface went down; and will look at IFF_PROMISC 1178 * again next time interface comes up). 1179 */ 1180 if ((ifp->if_flags & IFF_UP) == 0) 1181 return (0); 1182 } 1183 memset(&ifr, 0, sizeof(ifr)); 1184 ifr.ifr_flags = ifp->if_flags; 1185 ret = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t) &ifr); 1186 /* Restore interface state if not successful. */ 1187 if (ret != 0) { 1188 ifp->if_pcount = pcount; 1189 ifp->if_flags = flags; 1190 } 1191 return (ret); 1192 } 1193 1194 /* 1195 * Map interface name to 1196 * interface structure pointer. 1197 */ 1198 struct ifnet * 1199 ifunit(name) 1200 const char *name; 1201 { 1202 struct ifnet *ifp; 1203 1204 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL; 1205 ifp = TAILQ_NEXT(ifp, if_list)) { 1206 if (ifp->if_output == if_nulloutput) 1207 continue; 1208 if (strcmp(ifp->if_xname, name) == 0) 1209 return (ifp); 1210 } 1211 return (NULL); 1212 } 1213 1214 /* 1215 * Interface ioctls. 1216 */ 1217 int 1218 ifioctl(so, cmd, data, p) 1219 struct socket *so; 1220 u_long cmd; 1221 caddr_t data; 1222 struct proc *p; 1223 { 1224 struct ifnet *ifp; 1225 struct ifreq *ifr; 1226 struct ifcapreq *ifcr; 1227 int s, error = 0; 1228 short oif_flags; 1229 1230 switch (cmd) { 1231 1232 case SIOCGIFCONF: 1233 case OSIOCGIFCONF: 1234 return (ifconf(cmd, data)); 1235 } 1236 ifr = (struct ifreq *)data; 1237 ifcr = (struct ifcapreq *)data; 1238 1239 switch (cmd) { 1240 case SIOCIFCREATE: 1241 case SIOCIFDESTROY: 1242 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1243 return (error); 1244 return ((cmd == SIOCIFCREATE) ? 1245 if_clone_create(ifr->ifr_name) : 1246 if_clone_destroy(ifr->ifr_name)); 1247 1248 case SIOCIFGCLONERS: 1249 return (if_clone_list((struct if_clonereq *)data)); 1250 } 1251 1252 ifp = ifunit(ifr->ifr_name); 1253 if (ifp == 0) 1254 return (ENXIO); 1255 oif_flags = ifp->if_flags; 1256 switch (cmd) { 1257 1258 case SIOCGIFFLAGS: 1259 ifr->ifr_flags = ifp->if_flags; 1260 break; 1261 1262 case SIOCGIFMETRIC: 1263 ifr->ifr_metric = ifp->if_metric; 1264 break; 1265 1266 case SIOCGIFMTU: 1267 ifr->ifr_mtu = ifp->if_mtu; 1268 break; 1269 1270 case SIOCGIFDLT: 1271 ifr->ifr_dlt = ifp->if_dlt; 1272 break; 1273 1274 case SIOCSIFFLAGS: 1275 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1276 return (error); 1277 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 1278 s = splnet(); 1279 if_down(ifp); 1280 splx(s); 1281 } 1282 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 1283 s = splnet(); 1284 if_up(ifp); 1285 splx(s); 1286 } 1287 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 1288 (ifr->ifr_flags &~ IFF_CANTCHANGE); 1289 if (ifp->if_ioctl) 1290 (void) (*ifp->if_ioctl)(ifp, cmd, data); 1291 break; 1292 1293 case SIOCGIFCAP: 1294 ifcr->ifcr_capabilities = ifp->if_capabilities; 1295 ifcr->ifcr_capenable = ifp->if_capenable; 1296 break; 1297 1298 case SIOCSIFCAP: 1299 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1300 return (error); 1301 if ((ifcr->ifcr_capenable & ~ifp->if_capabilities) != 0) 1302 return (EINVAL); 1303 if (ifp->if_ioctl == NULL) 1304 return (EOPNOTSUPP); 1305 1306 /* Must prevent race with packet reception here. */ 1307 s = splnet(); 1308 if (ifcr->ifcr_capenable != ifp->if_capenable) { 1309 struct ifreq ifrq; 1310 1311 ifrq.ifr_flags = ifp->if_flags; 1312 ifp->if_capenable = ifcr->ifcr_capenable; 1313 1314 /* Pre-compute the checksum flags mask. */ 1315 ifp->if_csum_flags_tx = 0; 1316 ifp->if_csum_flags_rx = 0; 1317 if (ifp->if_capenable & IFCAP_CSUM_IPv4) { 1318 ifp->if_csum_flags_tx |= M_CSUM_IPv4; 1319 ifp->if_csum_flags_rx |= M_CSUM_IPv4; 1320 } 1321 1322 if (ifp->if_capenable & IFCAP_CSUM_TCPv4) { 1323 ifp->if_csum_flags_tx |= M_CSUM_TCPv4; 1324 ifp->if_csum_flags_rx |= M_CSUM_TCPv4; 1325 } else if (ifp->if_capenable & IFCAP_CSUM_TCPv4_Rx) 1326 ifp->if_csum_flags_rx |= M_CSUM_TCPv4; 1327 1328 if (ifp->if_capenable & IFCAP_CSUM_UDPv4) { 1329 ifp->if_csum_flags_tx |= M_CSUM_UDPv4; 1330 ifp->if_csum_flags_rx |= M_CSUM_UDPv4; 1331 } else if (ifp->if_capenable & IFCAP_CSUM_UDPv4_Rx) 1332 ifp->if_csum_flags_rx |= M_CSUM_UDPv4; 1333 1334 if (ifp->if_capenable & IFCAP_CSUM_TCPv6) { 1335 ifp->if_csum_flags_tx |= M_CSUM_TCPv6; 1336 ifp->if_csum_flags_rx |= M_CSUM_TCPv6; 1337 } 1338 1339 if (ifp->if_capenable & IFCAP_CSUM_UDPv6) { 1340 ifp->if_csum_flags_tx |= M_CSUM_UDPv6; 1341 ifp->if_csum_flags_rx |= M_CSUM_UDPv6; 1342 } 1343 1344 /* 1345 * Only kick the interface if it's up. If it's 1346 * not up now, it will notice the cap enables 1347 * when it is brought up later. 1348 */ 1349 if (ifp->if_flags & IFF_UP) 1350 (void) (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, 1351 (caddr_t) &ifrq); 1352 } 1353 splx(s); 1354 break; 1355 1356 case SIOCSIFMETRIC: 1357 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1358 return (error); 1359 ifp->if_metric = ifr->ifr_metric; 1360 break; 1361 1362 case SIOCSIFMTU: 1363 { 1364 u_long oldmtu = ifp->if_mtu; 1365 1366 error = suser(p->p_ucred, &p->p_acflag); 1367 if (error) 1368 return (error); 1369 if (ifp->if_ioctl == NULL) 1370 return (EOPNOTSUPP); 1371 error = (*ifp->if_ioctl)(ifp, cmd, data); 1372 1373 /* 1374 * If the link MTU changed, do network layer specific procedure. 1375 */ 1376 if (ifp->if_mtu != oldmtu) { 1377 #ifdef INET6 1378 nd6_setmtu(ifp); 1379 #endif 1380 } 1381 break; 1382 } 1383 case SIOCSIFPHYADDR: 1384 case SIOCDIFPHYADDR: 1385 #ifdef INET6 1386 case SIOCSIFPHYADDR_IN6: 1387 #endif 1388 case SIOCSLIFPHYADDR: 1389 case SIOCADDMULTI: 1390 case SIOCDELMULTI: 1391 case SIOCSIFMEDIA: 1392 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1393 return (error); 1394 /* FALLTHROUGH */ 1395 case SIOCGIFPSRCADDR: 1396 case SIOCGIFPDSTADDR: 1397 case SIOCGLIFPHYADDR: 1398 case SIOCGIFMEDIA: 1399 if (ifp->if_ioctl == 0) 1400 return (EOPNOTSUPP); 1401 error = (*ifp->if_ioctl)(ifp, cmd, data); 1402 break; 1403 1404 case SIOCSDRVSPEC: 1405 case SIOCS80211NWID: 1406 case SIOCS80211NWKEY: 1407 case SIOCS80211POWER: 1408 /* XXX: need to pass proc pointer through to driver... */ 1409 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1410 return (error); 1411 /* FALLTHROUGH */ 1412 default: 1413 if (so->so_proto == 0) 1414 return (EOPNOTSUPP); 1415 #if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4) && !defined(LKM) 1416 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 1417 (struct mbuf *)cmd, (struct mbuf *)data, 1418 (struct mbuf *)ifp, p)); 1419 #else 1420 { 1421 int ocmd = cmd; 1422 1423 switch (cmd) { 1424 1425 case SIOCSIFADDR: 1426 case SIOCSIFDSTADDR: 1427 case SIOCSIFBRDADDR: 1428 case SIOCSIFNETMASK: 1429 #if BYTE_ORDER != BIG_ENDIAN 1430 if (ifr->ifr_addr.sa_family == 0 && 1431 ifr->ifr_addr.sa_len < 16) { 1432 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 1433 ifr->ifr_addr.sa_len = 16; 1434 } 1435 #else 1436 if (ifr->ifr_addr.sa_len == 0) 1437 ifr->ifr_addr.sa_len = 16; 1438 #endif 1439 break; 1440 1441 case OSIOCGIFADDR: 1442 cmd = SIOCGIFADDR; 1443 break; 1444 1445 case OSIOCGIFDSTADDR: 1446 cmd = SIOCGIFDSTADDR; 1447 break; 1448 1449 case OSIOCGIFBRDADDR: 1450 cmd = SIOCGIFBRDADDR; 1451 break; 1452 1453 case OSIOCGIFNETMASK: 1454 cmd = SIOCGIFNETMASK; 1455 } 1456 1457 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 1458 (struct mbuf *)cmd, (struct mbuf *)data, 1459 (struct mbuf *)ifp, p)); 1460 1461 switch (ocmd) { 1462 case OSIOCGIFADDR: 1463 case OSIOCGIFDSTADDR: 1464 case OSIOCGIFBRDADDR: 1465 case OSIOCGIFNETMASK: 1466 *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 1467 } 1468 } 1469 #endif /* COMPAT_43 */ 1470 break; 1471 } 1472 1473 if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) { 1474 #ifdef INET6 1475 if ((ifp->if_flags & IFF_UP) != 0) { 1476 s = splnet(); 1477 in6_if_up(ifp); 1478 splx(s); 1479 } 1480 #endif 1481 } 1482 1483 return (error); 1484 } 1485 1486 /* 1487 * Return interface configuration 1488 * of system. List may be used 1489 * in later ioctl's (above) to get 1490 * other information. 1491 */ 1492 /*ARGSUSED*/ 1493 int 1494 ifconf(cmd, data) 1495 u_long cmd; 1496 caddr_t data; 1497 { 1498 struct ifconf *ifc = (struct ifconf *)data; 1499 struct ifnet *ifp; 1500 struct ifaddr *ifa; 1501 struct ifreq ifr, *ifrp; 1502 int space = ifc->ifc_len, error = 0; 1503 1504 ifrp = ifc->ifc_req; 1505 TAILQ_FOREACH(ifp, &ifnet, if_list) { 1506 bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ); 1507 if ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) == 0) { 1508 memset((caddr_t)&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 1509 if (space >= (int)sizeof (ifr)) { 1510 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 1511 sizeof(ifr)); 1512 if (error) 1513 break; 1514 } 1515 space -= sizeof (ifr), ifrp++; 1516 } else 1517 for (; ifa != 0; ifa = TAILQ_NEXT(ifa, ifa_list)) { 1518 struct sockaddr *sa = ifa->ifa_addr; 1519 #if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) 1520 if (cmd == OSIOCGIFCONF) { 1521 struct osockaddr *osa = 1522 (struct osockaddr *)&ifr.ifr_addr; 1523 ifr.ifr_addr = *sa; 1524 osa->sa_family = sa->sa_family; 1525 if (space >= (int)sizeof (ifr)) { 1526 error = copyout((caddr_t)&ifr, 1527 (caddr_t)ifrp, 1528 sizeof (ifr)); 1529 ifrp++; 1530 } 1531 } else 1532 #endif 1533 if (sa->sa_len <= sizeof(*sa)) { 1534 ifr.ifr_addr = *sa; 1535 if (space >= (int)sizeof (ifr)) { 1536 error = copyout((caddr_t)&ifr, 1537 (caddr_t)ifrp, 1538 sizeof (ifr)); 1539 ifrp++; 1540 } 1541 } else { 1542 space -= sa->sa_len - sizeof(*sa); 1543 if (space >= (int)sizeof (ifr)) { 1544 error = copyout((caddr_t)&ifr, 1545 (caddr_t)ifrp, 1546 sizeof (ifr.ifr_name)); 1547 if (error == 0) { 1548 error = copyout((caddr_t)sa, 1549 (caddr_t)&ifrp->ifr_addr, 1550 sa->sa_len); 1551 } 1552 ifrp = (struct ifreq *) 1553 (sa->sa_len + 1554 (caddr_t)&ifrp->ifr_addr); 1555 } 1556 } 1557 if (error) 1558 break; 1559 space -= sizeof (ifr); 1560 } 1561 } 1562 ifc->ifc_len -= space; 1563 return (error); 1564 } 1565