1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)if.c 8.3 (Berkeley) 1/4/94 34 * $Id: if.c,v 1.28 1996/02/08 21:34:56 wollman Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/queue.h> 39 #include <sys/mbuf.h> 40 #include <sys/systm.h> 41 #include <sys/proc.h> 42 #include <sys/socket.h> 43 #include <sys/socketvar.h> 44 #include <sys/protosw.h> 45 #include <sys/kernel.h> 46 #include <sys/ioctl.h> 47 #include <sys/errno.h> 48 #include <sys/syslog.h> 49 #include <sys/sysctl.h> 50 51 #include <net/if.h> 52 #include <net/if_dl.h> 53 #include <net/if_types.h> 54 #include <net/radix.h> 55 56 /* 57 * System initialization 58 */ 59 60 static int ifconf __P((int, caddr_t)); 61 static void ifinit __P((void *)); 62 static void if_qflush __P((struct ifqueue *)); 63 static void if_slowtimo __P((void *)); 64 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); 65 66 SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL) 67 68 69 int ifqmaxlen = IFQ_MAXLEN; 70 struct ifnet *ifnet; 71 72 /* 73 * Network interface utility routines. 74 * 75 * Routines with ifa_ifwith* names take sockaddr *'s as 76 * parameters. 77 * 78 * This routine assumes that it will be called at splimp() or higher. 79 */ 80 /* ARGSUSED*/ 81 void 82 ifinit(dummy) 83 void *dummy; 84 { 85 register struct ifnet *ifp; 86 87 for (ifp = ifnet; ifp; ifp = ifp->if_next) 88 if (ifp->if_snd.ifq_maxlen == 0) 89 ifp->if_snd.ifq_maxlen = ifqmaxlen; 90 if_slowtimo(0); 91 } 92 93 static int if_index = 0; 94 static struct ifaddr **ifnet_addrs; 95 96 97 /* 98 * Attach an interface to the 99 * list of "active" interfaces. 100 */ 101 void 102 if_attach(ifp) 103 struct ifnet *ifp; 104 { 105 unsigned socksize, ifasize; 106 int namelen, masklen; 107 char workbuf[64]; 108 register struct ifnet **p = &ifnet; 109 register struct sockaddr_dl *sdl; 110 register struct ifaddr *ifa; 111 static int if_indexlim = 8; 112 113 114 while (*p) 115 p = &((*p)->if_next); 116 *p = ifp; 117 ifp->if_index = ++if_index; 118 if (ifnet_addrs == 0 || if_index >= if_indexlim) { 119 unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 120 struct ifaddr **q = (struct ifaddr **) 121 malloc(n, M_IFADDR, M_WAITOK); 122 bzero((caddr_t)q, n); 123 if (ifnet_addrs) { 124 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 125 free((caddr_t)ifnet_addrs, M_IFADDR); 126 } 127 ifnet_addrs = q; 128 } 129 /* 130 * create a Link Level name for this device 131 */ 132 namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); 133 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 134 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; 135 socksize = masklen + ifp->if_addrlen; 136 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 137 socksize = ROUNDUP(socksize); 138 if (socksize < sizeof(*sdl)) 139 socksize = sizeof(*sdl); 140 ifasize = sizeof(*ifa) + 2 * socksize; 141 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 142 if (ifa) { 143 bzero((caddr_t)ifa, ifasize); 144 sdl = (struct sockaddr_dl *)(ifa + 1); 145 sdl->sdl_len = socksize; 146 sdl->sdl_family = AF_LINK; 147 bcopy(workbuf, sdl->sdl_data, namelen); 148 sdl->sdl_nlen = namelen; 149 sdl->sdl_index = ifp->if_index; 150 sdl->sdl_type = ifp->if_type; 151 ifnet_addrs[if_index - 1] = ifa; 152 ifa->ifa_ifp = ifp; 153 ifa->ifa_next = ifp->if_addrlist; 154 ifa->ifa_rtrequest = link_rtrequest; 155 ifp->if_addrlist = ifa; 156 ifa->ifa_addr = (struct sockaddr *)sdl; 157 158 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 159 ifa->ifa_netmask = (struct sockaddr *)sdl; 160 sdl->sdl_len = masklen; 161 while (namelen != 0) 162 sdl->sdl_data[--namelen] = 0xff; 163 } 164 /* 165 * If they provided a slow input queue, initialize it. 166 */ 167 if (ifp->if_poll_slowq) { 168 struct ifqueue *ifq = ifp->if_poll_slowq; 169 170 bzero(ifq, sizeof *ifq); 171 ifq->ifq_maxlen = ifqmaxlen; 172 #ifdef POLLING 173 ifq->if_poll_recv = if_poll_recv_slow; 174 #endif 175 } 176 } 177 /* 178 * Locate an interface based on a complete address. 179 */ 180 /*ARGSUSED*/ 181 struct ifaddr * 182 ifa_ifwithaddr(addr) 183 register struct sockaddr *addr; 184 { 185 register struct ifnet *ifp; 186 register struct ifaddr *ifa; 187 188 #define equal(a1, a2) \ 189 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 190 for (ifp = ifnet; ifp; ifp = ifp->if_next) 191 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 192 if (ifa->ifa_addr->sa_family != addr->sa_family) 193 continue; 194 if (equal(addr, ifa->ifa_addr)) 195 return (ifa); 196 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 197 equal(ifa->ifa_broadaddr, addr)) 198 return (ifa); 199 } 200 return ((struct ifaddr *)0); 201 } 202 /* 203 * Locate the point to point interface with a given destination address. 204 */ 205 /*ARGSUSED*/ 206 struct ifaddr * 207 ifa_ifwithdstaddr(addr) 208 register struct sockaddr *addr; 209 { 210 register struct ifnet *ifp; 211 register struct ifaddr *ifa; 212 213 for (ifp = ifnet; ifp; ifp = ifp->if_next) 214 if (ifp->if_flags & IFF_POINTOPOINT) 215 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 216 if (ifa->ifa_addr->sa_family != addr->sa_family) 217 continue; 218 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) 219 return (ifa); 220 } 221 return ((struct ifaddr *)0); 222 } 223 224 /* 225 * Find an interface on a specific network. If many, choice 226 * is most specific found. 227 */ 228 struct ifaddr * 229 ifa_ifwithnet(addr) 230 struct sockaddr *addr; 231 { 232 register struct ifnet *ifp; 233 register struct ifaddr *ifa; 234 struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 235 u_int af = addr->sa_family; 236 char *addr_data = addr->sa_data, *cplim; 237 238 if (af == AF_LINK) { 239 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 240 if (sdl->sdl_index && sdl->sdl_index <= if_index) 241 return (ifnet_addrs[sdl->sdl_index - 1]); 242 } 243 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 244 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 245 register char *cp, *cp2, *cp3; 246 247 if (ifa->ifa_addr->sa_family != af) 248 next: continue; 249 if (ifp->if_flags & IFF_POINTOPOINT) { 250 if (equal(addr, ifa->ifa_dstaddr)) 251 return (ifa); 252 } else { 253 if (ifa->ifa_netmask == 0) 254 continue; 255 cp = addr_data; 256 cp2 = ifa->ifa_addr->sa_data; 257 cp3 = ifa->ifa_netmask->sa_data; 258 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 259 while (cp3 < cplim) 260 if ((*cp++ ^ *cp2++) & *cp3++) 261 goto next; 262 if (ifa_maybe == 0 || 263 rn_refines((caddr_t)ifa->ifa_netmask, 264 (caddr_t)ifa_maybe->ifa_netmask)) 265 ifa_maybe = ifa; 266 } 267 } 268 } 269 return (ifa_maybe); 270 } 271 272 /* 273 * Find an interface address specific to an interface best matching 274 * a given address. 275 */ 276 struct ifaddr * 277 ifaof_ifpforaddr(addr, ifp) 278 struct sockaddr *addr; 279 register struct ifnet *ifp; 280 { 281 register struct ifaddr *ifa; 282 register char *cp, *cp2, *cp3; 283 register char *cplim; 284 struct ifaddr *ifa_maybe = 0; 285 u_int af = addr->sa_family; 286 287 if (af >= AF_MAX) 288 return (0); 289 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 290 if (ifa->ifa_addr->sa_family != af) 291 continue; 292 ifa_maybe = ifa; 293 if (ifa->ifa_netmask == 0) { 294 if (equal(addr, ifa->ifa_addr) || 295 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 296 return (ifa); 297 continue; 298 } 299 if (ifp->if_flags & IFF_POINTOPOINT) { 300 if (equal(addr, ifa->ifa_dstaddr)) 301 return (ifa); 302 } else { 303 cp = addr->sa_data; 304 cp2 = ifa->ifa_addr->sa_data; 305 cp3 = ifa->ifa_netmask->sa_data; 306 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 307 for (; cp3 < cplim; cp3++) 308 if ((*cp++ ^ *cp2++) & *cp3) 309 break; 310 if (cp3 == cplim) 311 return (ifa); 312 } 313 } 314 return (ifa_maybe); 315 } 316 317 #include <net/route.h> 318 319 /* 320 * Default action when installing a route with a Link Level gateway. 321 * Lookup an appropriate real ifa to point to. 322 * This should be moved to /sys/net/link.c eventually. 323 */ 324 static void 325 link_rtrequest(cmd, rt, sa) 326 int cmd; 327 register struct rtentry *rt; 328 struct sockaddr *sa; 329 { 330 register struct ifaddr *ifa; 331 struct sockaddr *dst; 332 struct ifnet *ifp; 333 334 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 335 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 336 return; 337 ifa = ifaof_ifpforaddr(dst, ifp); 338 if (ifa) { 339 IFAFREE(rt->rt_ifa); 340 rt->rt_ifa = ifa; 341 ifa->ifa_refcnt++; 342 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 343 ifa->ifa_rtrequest(cmd, rt, sa); 344 } 345 } 346 347 /* 348 * Mark an interface down and notify protocols of 349 * the transition. 350 * NOTE: must be called at splnet or eqivalent. 351 */ 352 void 353 if_down(ifp) 354 register struct ifnet *ifp; 355 { 356 register struct ifaddr *ifa; 357 358 ifp->if_flags &= ~IFF_UP; 359 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 360 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 361 if_qflush(&ifp->if_snd); 362 rt_ifmsg(ifp); 363 } 364 365 /* 366 * Mark an interface up and notify protocols of 367 * the transition. 368 * NOTE: must be called at splnet or eqivalent. 369 */ 370 void 371 if_up(ifp) 372 register struct ifnet *ifp; 373 { 374 375 ifp->if_flags |= IFF_UP; 376 #ifdef notyet 377 register struct ifaddr *ifa; 378 /* this has no effect on IP, and will kill all iso connections XXX */ 379 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 380 pfctlinput(PRC_IFUP, ifa->ifa_addr); 381 #endif 382 rt_ifmsg(ifp); 383 } 384 385 /* 386 * Flush an interface queue. 387 */ 388 static void 389 if_qflush(ifq) 390 register struct ifqueue *ifq; 391 { 392 register struct mbuf *m, *n; 393 394 n = ifq->ifq_head; 395 while ((m = n) != 0) { 396 n = m->m_act; 397 m_freem(m); 398 } 399 ifq->ifq_head = 0; 400 ifq->ifq_tail = 0; 401 ifq->ifq_len = 0; 402 } 403 404 /* 405 * Handle interface watchdog timer routines. Called 406 * from softclock, we decrement timers (if set) and 407 * call the appropriate interface routine on expiration. 408 */ 409 static void 410 if_slowtimo(arg) 411 void *arg; 412 { 413 register struct ifnet *ifp; 414 int s = splimp(); 415 416 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 417 if (ifp->if_timer == 0 || --ifp->if_timer) 418 continue; 419 if (ifp->if_watchdog) 420 (*ifp->if_watchdog)(ifp); 421 } 422 splx(s); 423 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 424 } 425 426 /* 427 * Map interface name to 428 * interface structure pointer. 429 */ 430 struct ifnet * 431 ifunit(name) 432 register char *name; 433 { 434 register char *cp; 435 register struct ifnet *ifp; 436 int unit; 437 unsigned len; 438 char *ep, c; 439 440 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 441 if (*cp >= '0' && *cp <= '9') 442 break; 443 if (*cp == '\0' || cp == name + IFNAMSIZ) 444 return ((struct ifnet *)0); 445 /* 446 * Save first char of unit, and pointer to it, 447 * so we can put a null there to avoid matching 448 * initial substrings of interface names. 449 */ 450 len = cp - name + 1; 451 c = *cp; 452 ep = cp; 453 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 454 unit = unit * 10 + *cp++ - '0'; 455 *ep = 0; 456 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 457 if (bcmp(ifp->if_name, name, len)) 458 continue; 459 if (unit == ifp->if_unit) 460 break; 461 } 462 *ep = c; 463 return (ifp); 464 } 465 466 /* 467 * Interface ioctls. 468 */ 469 int 470 ifioctl(so, cmd, data, p) 471 struct socket *so; 472 int cmd; 473 caddr_t data; 474 struct proc *p; 475 { 476 register struct ifnet *ifp; 477 register struct ifreq *ifr; 478 int error; 479 480 switch (cmd) { 481 482 case SIOCGIFCONF: 483 case OSIOCGIFCONF: 484 return (ifconf(cmd, data)); 485 } 486 ifr = (struct ifreq *)data; 487 ifp = ifunit(ifr->ifr_name); 488 if (ifp == 0) 489 return (ENXIO); 490 switch (cmd) { 491 492 case SIOCGIFFLAGS: 493 ifr->ifr_flags = ifp->if_flags; 494 break; 495 496 case SIOCGIFMETRIC: 497 ifr->ifr_metric = ifp->if_metric; 498 break; 499 500 case SIOCGIFMTU: 501 ifr->ifr_mtu = ifp->if_mtu; 502 break; 503 504 case SIOCGIFPHYS: 505 ifr->ifr_phys = ifp->if_physical; 506 break; 507 508 case SIOCSIFFLAGS: 509 error = suser(p->p_ucred, &p->p_acflag); 510 if (error) 511 return (error); 512 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 513 int s = splimp(); 514 if_down(ifp); 515 splx(s); 516 } 517 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 518 int s = splimp(); 519 if_up(ifp); 520 splx(s); 521 } 522 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 523 (ifr->ifr_flags &~ IFF_CANTCHANGE); 524 if (ifp->if_ioctl) 525 (void) (*ifp->if_ioctl)(ifp, cmd, data); 526 break; 527 528 case SIOCSIFMETRIC: 529 error = suser(p->p_ucred, &p->p_acflag); 530 if (error) 531 return (error); 532 ifp->if_metric = ifr->ifr_metric; 533 break; 534 535 case SIOCSIFPHYS: 536 error = suser(p->p_ucred, &p->p_acflag); 537 if (error) return error; 538 539 if (!ifp->if_ioctl) return EOPNOTSUPP; 540 return ifp->if_ioctl(ifp, cmd, data); 541 542 case SIOCSIFMTU: 543 error = suser(p->p_ucred, &p->p_acflag); 544 if (error) 545 return (error); 546 if (ifp->if_ioctl == NULL) 547 return (EOPNOTSUPP); 548 /* 549 * 72 was chosen below because it is the size of a TCP/IP 550 * header (40) + the minimum mss (32). 551 */ 552 if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535) 553 return (EINVAL); 554 return ((*ifp->if_ioctl)(ifp, cmd, data)); 555 556 case SIOCADDMULTI: 557 case SIOCDELMULTI: 558 error = suser(p->p_ucred, &p->p_acflag); 559 if (error) 560 return (error); 561 if (ifp->if_ioctl == NULL) 562 return (EOPNOTSUPP); 563 return ((*ifp->if_ioctl)(ifp, cmd, data)); 564 565 default: 566 if (so->so_proto == 0) 567 return (EOPNOTSUPP); 568 #ifndef COMPAT_43 569 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 570 (struct mbuf *)cmd, (struct mbuf *)data, 571 (struct mbuf *)ifp)); 572 #else 573 { 574 int ocmd = cmd; 575 576 switch (cmd) { 577 578 case SIOCSIFDSTADDR: 579 case SIOCSIFADDR: 580 case SIOCSIFBRDADDR: 581 case SIOCSIFNETMASK: 582 #if BYTE_ORDER != BIG_ENDIAN 583 if (ifr->ifr_addr.sa_family == 0 && 584 ifr->ifr_addr.sa_len < 16) { 585 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 586 ifr->ifr_addr.sa_len = 16; 587 } 588 #else 589 if (ifr->ifr_addr.sa_len == 0) 590 ifr->ifr_addr.sa_len = 16; 591 #endif 592 break; 593 594 case OSIOCGIFADDR: 595 cmd = SIOCGIFADDR; 596 break; 597 598 case OSIOCGIFDSTADDR: 599 cmd = SIOCGIFDSTADDR; 600 break; 601 602 case OSIOCGIFBRDADDR: 603 cmd = SIOCGIFBRDADDR; 604 break; 605 606 case OSIOCGIFNETMASK: 607 cmd = SIOCGIFNETMASK; 608 } 609 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 610 /* 611 * XXX callees reverse the following bogus casts, 612 * but it would be easier to use a separate 613 * interface that is guaranteed to work. 614 */ 615 (struct mbuf *)cmd, (struct mbuf *)data, 616 (struct mbuf *)ifp)); 617 switch (ocmd) { 618 619 case OSIOCGIFADDR: 620 case OSIOCGIFDSTADDR: 621 case OSIOCGIFBRDADDR: 622 case OSIOCGIFNETMASK: 623 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 624 } 625 return (error); 626 627 } 628 #endif 629 } 630 return (0); 631 } 632 633 /* 634 * Set/clear promiscuous mode on interface ifp based on the truth value 635 * of pswitch. The calls are reference counted so that only the first 636 * "on" request actually has an effect, as does the final "off" request. 637 * Results are undefined if the "off" and "on" requests are not matched. 638 */ 639 int 640 ifpromisc(ifp, pswitch) 641 struct ifnet *ifp; 642 int pswitch; 643 { 644 struct ifreq ifr; 645 646 if (pswitch) { 647 /* 648 * If the device is not configured up, we cannot put it in 649 * promiscuous mode. 650 */ 651 if ((ifp->if_flags & IFF_UP) == 0) 652 return (ENETDOWN); 653 if (ifp->if_pcount++ != 0) 654 return (0); 655 ifp->if_flags |= IFF_PROMISC; 656 log(LOG_INFO, "%s%d: promiscuous mode enabled\n", 657 ifp->if_name, ifp->if_unit); 658 } else { 659 if (--ifp->if_pcount > 0) 660 return (0); 661 ifp->if_flags &= ~IFF_PROMISC; 662 } 663 ifr.ifr_flags = ifp->if_flags; 664 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); 665 } 666 667 /* 668 * Return interface configuration 669 * of system. List may be used 670 * in later ioctl's (above) to get 671 * other information. 672 */ 673 /*ARGSUSED*/ 674 static int 675 ifconf(cmd, data) 676 int cmd; 677 caddr_t data; 678 { 679 register struct ifconf *ifc = (struct ifconf *)data; 680 register struct ifnet *ifp = ifnet; 681 register struct ifaddr *ifa; 682 struct ifreq ifr, *ifrp; 683 int space = ifc->ifc_len, error = 0; 684 685 ifrp = ifc->ifc_req; 686 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 687 char workbuf[64]; 688 int ifnlen; 689 690 ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); 691 if(ifnlen + 1 > sizeof ifr.ifr_name) { 692 error = ENAMETOOLONG; 693 } else { 694 strcpy(ifr.ifr_name, workbuf); 695 } 696 697 if ((ifa = ifp->if_addrlist) == 0) { 698 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 699 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 700 sizeof (ifr)); 701 if (error) 702 break; 703 space -= sizeof (ifr), ifrp++; 704 } else 705 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 706 register struct sockaddr *sa = ifa->ifa_addr; 707 #ifdef COMPAT_43 708 if (cmd == OSIOCGIFCONF) { 709 struct osockaddr *osa = 710 (struct osockaddr *)&ifr.ifr_addr; 711 ifr.ifr_addr = *sa; 712 osa->sa_family = sa->sa_family; 713 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 714 sizeof (ifr)); 715 ifrp++; 716 } else 717 #endif 718 if (sa->sa_len <= sizeof(*sa)) { 719 ifr.ifr_addr = *sa; 720 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 721 sizeof (ifr)); 722 ifrp++; 723 } else { 724 space -= sa->sa_len - sizeof(*sa); 725 if (space < sizeof (ifr)) 726 break; 727 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 728 sizeof (ifr.ifr_name)); 729 if (error == 0) 730 error = copyout((caddr_t)sa, 731 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 732 ifrp = (struct ifreq *) 733 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 734 } 735 if (error) 736 break; 737 space -= sizeof (ifr); 738 } 739 } 740 ifc->ifc_len -= space; 741 return (error); 742 } 743 744 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); 745