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