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