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