if.c revision 17096
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.32 1996/06/12 19:23:59 gpalmer 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 60static int ifconf __P((int, caddr_t)); 61static void ifinit __P((void *)); 62static void if_qflush __P((struct ifqueue *)); 63static void if_slowtimo __P((void *)); 64static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *)); 65 66SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL) 67 68 69int ifqmaxlen = IFQ_MAXLEN; 70struct 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*/ 81void 82ifinit(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 93static int if_index = 0; 94static struct ifaddr **ifnet_addrs; 95 96 97/* 98 * Attach an interface to the 99 * list of "active" interfaces. 100 */ 101void 102if_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 microtime(&ifp->if_lastchange); 119 if (ifnet_addrs == 0 || if_index >= if_indexlim) { 120 unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 121 struct ifaddr **q = (struct ifaddr **) 122 malloc(n, M_IFADDR, M_WAITOK); 123 bzero((caddr_t)q, n); 124 if (ifnet_addrs) { 125 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 126 free((caddr_t)ifnet_addrs, M_IFADDR); 127 } 128 ifnet_addrs = q; 129 } 130 /* 131 * create a Link Level name for this device 132 */ 133 namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); 134#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 135 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen; 136 socksize = masklen + ifp->if_addrlen; 137#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 138 socksize = ROUNDUP(socksize); 139 if (socksize < sizeof(*sdl)) 140 socksize = sizeof(*sdl); 141 ifasize = sizeof(*ifa) + 2 * socksize; 142 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 143 if (ifa) { 144 bzero((caddr_t)ifa, ifasize); 145 sdl = (struct sockaddr_dl *)(ifa + 1); 146 sdl->sdl_len = socksize; 147 sdl->sdl_family = AF_LINK; 148 bcopy(workbuf, sdl->sdl_data, namelen); 149 sdl->sdl_nlen = namelen; 150 sdl->sdl_index = ifp->if_index; 151 sdl->sdl_type = ifp->if_type; 152 ifnet_addrs[if_index - 1] = ifa; 153 ifa->ifa_ifp = ifp; 154 ifa->ifa_next = ifp->if_addrlist; 155 ifa->ifa_rtrequest = link_rtrequest; 156 ifp->if_addrlist = ifa; 157 ifa->ifa_addr = (struct sockaddr *)sdl; 158 159 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 160 ifa->ifa_netmask = (struct sockaddr *)sdl; 161 sdl->sdl_len = masklen; 162 while (namelen != 0) 163 sdl->sdl_data[--namelen] = 0xff; 164 } 165} 166/* 167 * Locate an interface based on a complete address. 168 */ 169/*ARGSUSED*/ 170struct ifaddr * 171ifa_ifwithaddr(addr) 172 register struct sockaddr *addr; 173{ 174 register struct ifnet *ifp; 175 register struct ifaddr *ifa; 176 177#define equal(a1, a2) \ 178 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 179 for (ifp = ifnet; ifp; ifp = ifp->if_next) 180 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 181 if (ifa->ifa_addr->sa_family != addr->sa_family) 182 continue; 183 if (equal(addr, ifa->ifa_addr)) 184 return (ifa); 185 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 186 equal(ifa->ifa_broadaddr, addr)) 187 return (ifa); 188 } 189 return ((struct ifaddr *)0); 190} 191/* 192 * Locate the point to point interface with a given destination address. 193 */ 194/*ARGSUSED*/ 195struct ifaddr * 196ifa_ifwithdstaddr(addr) 197 register struct sockaddr *addr; 198{ 199 register struct ifnet *ifp; 200 register struct ifaddr *ifa; 201 202 for (ifp = ifnet; ifp; ifp = ifp->if_next) 203 if (ifp->if_flags & IFF_POINTOPOINT) 204 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 205 if (ifa->ifa_addr->sa_family != addr->sa_family) 206 continue; 207 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)) 208 return (ifa); 209 } 210 return ((struct ifaddr *)0); 211} 212 213/* 214 * Find an interface on a specific network. If many, choice 215 * is most specific found. 216 */ 217struct ifaddr * 218ifa_ifwithnet(addr) 219 struct sockaddr *addr; 220{ 221 register struct ifnet *ifp; 222 register struct ifaddr *ifa; 223 struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 224 u_int af = addr->sa_family; 225 char *addr_data = addr->sa_data, *cplim; 226 227 if (af == AF_LINK) { 228 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 229 if (sdl->sdl_index && sdl->sdl_index <= if_index) 230 return (ifnet_addrs[sdl->sdl_index - 1]); 231 } 232 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 233 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 234 register char *cp, *cp2, *cp3; 235 236 if (ifa->ifa_addr->sa_family != af) 237 next: continue; 238 if (ifp->if_flags & IFF_POINTOPOINT) { 239 if (equal(addr, ifa->ifa_dstaddr)) 240 return (ifa); 241 } else { 242 if (ifa->ifa_netmask == 0) 243 continue; 244 cp = addr_data; 245 cp2 = ifa->ifa_addr->sa_data; 246 cp3 = ifa->ifa_netmask->sa_data; 247 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 248 while (cp3 < cplim) 249 if ((*cp++ ^ *cp2++) & *cp3++) 250 goto next; 251 if (ifa_maybe == 0 || 252 rn_refines((caddr_t)ifa->ifa_netmask, 253 (caddr_t)ifa_maybe->ifa_netmask)) 254 ifa_maybe = ifa; 255 } 256 } 257 } 258 return (ifa_maybe); 259} 260 261/* 262 * Find an interface address specific to an interface best matching 263 * a given address. 264 */ 265struct ifaddr * 266ifaof_ifpforaddr(addr, ifp) 267 struct sockaddr *addr; 268 register struct ifnet *ifp; 269{ 270 register struct ifaddr *ifa; 271 register char *cp, *cp2, *cp3; 272 register char *cplim; 273 struct ifaddr *ifa_maybe = 0; 274 u_int af = addr->sa_family; 275 276 if (af >= AF_MAX) 277 return (0); 278 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 279 if (ifa->ifa_addr->sa_family != af) 280 continue; 281 ifa_maybe = ifa; 282 if (ifa->ifa_netmask == 0) { 283 if (equal(addr, ifa->ifa_addr) || 284 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 285 return (ifa); 286 continue; 287 } 288 if (ifp->if_flags & IFF_POINTOPOINT) { 289 if (equal(addr, ifa->ifa_dstaddr)) 290 return (ifa); 291 } else { 292 cp = addr->sa_data; 293 cp2 = ifa->ifa_addr->sa_data; 294 cp3 = ifa->ifa_netmask->sa_data; 295 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 296 for (; cp3 < cplim; cp3++) 297 if ((*cp++ ^ *cp2++) & *cp3) 298 break; 299 if (cp3 == cplim) 300 return (ifa); 301 } 302 } 303 return (ifa_maybe); 304} 305 306#include <net/route.h> 307 308/* 309 * Default action when installing a route with a Link Level gateway. 310 * Lookup an appropriate real ifa to point to. 311 * This should be moved to /sys/net/link.c eventually. 312 */ 313static void 314link_rtrequest(cmd, rt, sa) 315 int cmd; 316 register struct rtentry *rt; 317 struct sockaddr *sa; 318{ 319 register struct ifaddr *ifa; 320 struct sockaddr *dst; 321 struct ifnet *ifp; 322 323 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 324 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 325 return; 326 ifa = ifaof_ifpforaddr(dst, ifp); 327 if (ifa) { 328 IFAFREE(rt->rt_ifa); 329 rt->rt_ifa = ifa; 330 ifa->ifa_refcnt++; 331 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 332 ifa->ifa_rtrequest(cmd, rt, sa); 333 } 334} 335 336/* 337 * Mark an interface down and notify protocols of 338 * the transition. 339 * NOTE: must be called at splnet or eqivalent. 340 */ 341void 342if_down(ifp) 343 register struct ifnet *ifp; 344{ 345 register struct ifaddr *ifa; 346 347 ifp->if_flags &= ~IFF_UP; 348 microtime(&ifp->if_lastchange); 349 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 350 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 351 if_qflush(&ifp->if_snd); 352 rt_ifmsg(ifp); 353} 354 355/* 356 * Mark an interface up and notify protocols of 357 * the transition. 358 * NOTE: must be called at splnet or eqivalent. 359 */ 360void 361if_up(ifp) 362 register struct ifnet *ifp; 363{ 364 365 ifp->if_flags |= IFF_UP; 366 microtime(&ifp->if_lastchange); 367#ifdef notyet 368 register struct ifaddr *ifa; 369 /* this has no effect on IP, and will kill all iso connections XXX */ 370 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 371 pfctlinput(PRC_IFUP, ifa->ifa_addr); 372#endif 373 rt_ifmsg(ifp); 374} 375 376/* 377 * Flush an interface queue. 378 */ 379static void 380if_qflush(ifq) 381 register struct ifqueue *ifq; 382{ 383 register struct mbuf *m, *n; 384 385 n = ifq->ifq_head; 386 while ((m = n) != 0) { 387 n = m->m_act; 388 m_freem(m); 389 } 390 ifq->ifq_head = 0; 391 ifq->ifq_tail = 0; 392 ifq->ifq_len = 0; 393} 394 395/* 396 * Handle interface watchdog timer routines. Called 397 * from softclock, we decrement timers (if set) and 398 * call the appropriate interface routine on expiration. 399 */ 400static void 401if_slowtimo(arg) 402 void *arg; 403{ 404 register struct ifnet *ifp; 405 int s = splimp(); 406 407 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 408 if (ifp->if_timer == 0 || --ifp->if_timer) 409 continue; 410 if (ifp->if_watchdog) 411 (*ifp->if_watchdog)(ifp); 412 } 413 splx(s); 414 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 415} 416 417/* 418 * Map interface name to 419 * interface structure pointer. 420 */ 421struct ifnet * 422ifunit(name) 423 register char *name; 424{ 425 register char *cp; 426 register struct ifnet *ifp; 427 int unit; 428 unsigned len; 429 char *ep, c; 430 431 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 432 if (*cp >= '0' && *cp <= '9') 433 break; 434 if (*cp == '\0' || cp == name + IFNAMSIZ) 435 return ((struct ifnet *)0); 436 /* 437 * Save first char of unit, and pointer to it, 438 * so we can put a null there to avoid matching 439 * initial substrings of interface names. 440 */ 441 len = cp - name + 1; 442 c = *cp; 443 ep = cp; 444 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 445 unit = unit * 10 + *cp++ - '0'; 446 if (*cp != '\0') 447 return 0; /* no trailing garbage allowed */ 448 *ep = 0; 449 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 450 if (bcmp(ifp->if_name, name, len)) 451 continue; 452 if (unit == ifp->if_unit) 453 break; 454 } 455 *ep = c; 456 return (ifp); 457} 458 459/* 460 * Interface ioctls. 461 */ 462int 463ifioctl(so, cmd, data, p) 464 struct socket *so; 465 int cmd; 466 caddr_t data; 467 struct proc *p; 468{ 469 register struct ifnet *ifp; 470 register struct ifreq *ifr; 471 int error; 472 473 switch (cmd) { 474 475 case SIOCGIFCONF: 476 case OSIOCGIFCONF: 477 return (ifconf(cmd, data)); 478 } 479 ifr = (struct ifreq *)data; 480 ifp = ifunit(ifr->ifr_name); 481 if (ifp == 0) 482 return (ENXIO); 483 switch (cmd) { 484 485 case SIOCGIFFLAGS: 486 ifr->ifr_flags = ifp->if_flags; 487 break; 488 489 case SIOCGIFMETRIC: 490 ifr->ifr_metric = ifp->if_metric; 491 break; 492 493 case SIOCGIFMTU: 494 ifr->ifr_mtu = ifp->if_mtu; 495 break; 496 497 case SIOCGIFPHYS: 498 ifr->ifr_phys = ifp->if_physical; 499 break; 500 501 case SIOCSIFFLAGS: 502 error = suser(p->p_ucred, &p->p_acflag); 503 if (error) 504 return (error); 505 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 506 int s = splimp(); 507 if_down(ifp); 508 splx(s); 509 } 510 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 511 int s = splimp(); 512 if_up(ifp); 513 splx(s); 514 } 515 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 516 (ifr->ifr_flags &~ IFF_CANTCHANGE); 517 if (ifp->if_ioctl) 518 (void) (*ifp->if_ioctl)(ifp, cmd, data); 519 microtime(&ifp->if_lastchange); 520 break; 521 522 case SIOCSIFMETRIC: 523 error = suser(p->p_ucred, &p->p_acflag); 524 if (error) 525 return (error); 526 ifp->if_metric = ifr->ifr_metric; 527 microtime(&ifp->if_lastchange); 528 break; 529 530 case SIOCSIFPHYS: 531 error = suser(p->p_ucred, &p->p_acflag); 532 if (error) 533 return error; 534 if (!ifp->if_ioctl) 535 return EOPNOTSUPP; 536 error = (*ifp->if_ioctl)(ifp, cmd, data); 537 if (error == 0) 538 microtime(&ifp->if_lastchange); 539 return(error); 540 541 case SIOCSIFMTU: 542 error = suser(p->p_ucred, &p->p_acflag); 543 if (error) 544 return (error); 545 if (ifp->if_ioctl == NULL) 546 return (EOPNOTSUPP); 547 /* 548 * 72 was chosen below because it is the size of a TCP/IP 549 * header (40) + the minimum mss (32). 550 */ 551 if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535) 552 return (EINVAL); 553 error = (*ifp->if_ioctl)(ifp, cmd, data); 554 if (error == 0) 555 microtime(&ifp->if_lastchange); 556 return(error); 557 558 case SIOCADDMULTI: 559 case SIOCDELMULTI: 560 error = suser(p->p_ucred, &p->p_acflag); 561 if (error) 562 return (error); 563 if (ifp->if_ioctl == NULL) 564 return (EOPNOTSUPP); 565 error = (*ifp->if_ioctl)(ifp, cmd, data); 566 if (error == 0 ) 567 microtime(&ifp->if_lastchange); 568 return(error); 569 570 default: 571 if (so->so_proto == 0) 572 return (EOPNOTSUPP); 573#ifndef COMPAT_43 574 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, 575 data, 576 ifp)); 577#else 578 { 579 int ocmd = cmd; 580 581 switch (cmd) { 582 583 case SIOCSIFDSTADDR: 584 case SIOCSIFADDR: 585 case SIOCSIFBRDADDR: 586 case SIOCSIFNETMASK: 587#if BYTE_ORDER != BIG_ENDIAN 588 if (ifr->ifr_addr.sa_family == 0 && 589 ifr->ifr_addr.sa_len < 16) { 590 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 591 ifr->ifr_addr.sa_len = 16; 592 } 593#else 594 if (ifr->ifr_addr.sa_len == 0) 595 ifr->ifr_addr.sa_len = 16; 596#endif 597 break; 598 599 case OSIOCGIFADDR: 600 cmd = SIOCGIFADDR; 601 break; 602 603 case OSIOCGIFDSTADDR: 604 cmd = SIOCGIFDSTADDR; 605 break; 606 607 case OSIOCGIFBRDADDR: 608 cmd = SIOCGIFBRDADDR; 609 break; 610 611 case OSIOCGIFNETMASK: 612 cmd = SIOCGIFNETMASK; 613 } 614 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, 615 cmd, 616 data, 617 ifp)); 618 switch (ocmd) { 619 620 case OSIOCGIFADDR: 621 case OSIOCGIFDSTADDR: 622 case OSIOCGIFBRDADDR: 623 case OSIOCGIFNETMASK: 624 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 625 } 626 return (error); 627 628 } 629#endif 630 } 631 return (0); 632} 633 634/* 635 * Set/clear promiscuous mode on interface ifp based on the truth value 636 * of pswitch. The calls are reference counted so that only the first 637 * "on" request actually has an effect, as does the final "off" request. 638 * Results are undefined if the "off" and "on" requests are not matched. 639 */ 640int 641ifpromisc(ifp, pswitch) 642 struct ifnet *ifp; 643 int pswitch; 644{ 645 struct ifreq ifr; 646 647 if (pswitch) { 648 /* 649 * If the device is not configured up, we cannot put it in 650 * promiscuous mode. 651 */ 652 if ((ifp->if_flags & IFF_UP) == 0) 653 return (ENETDOWN); 654 if (ifp->if_pcount++ != 0) 655 return (0); 656 ifp->if_flags |= IFF_PROMISC; 657 log(LOG_INFO, "%s%d: promiscuous mode enabled\n", 658 ifp->if_name, ifp->if_unit); 659 } else { 660 if (--ifp->if_pcount > 0) 661 return (0); 662 ifp->if_flags &= ~IFF_PROMISC; 663 } 664 ifr.ifr_flags = ifp->if_flags; 665 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); 666} 667 668/* 669 * Return interface configuration 670 * of system. List may be used 671 * in later ioctl's (above) to get 672 * other information. 673 */ 674/*ARGSUSED*/ 675static int 676ifconf(cmd, data) 677 int cmd; 678 caddr_t data; 679{ 680 register struct ifconf *ifc = (struct ifconf *)data; 681 register struct ifnet *ifp = ifnet; 682 register struct ifaddr *ifa; 683 struct ifreq ifr, *ifrp; 684 int space = ifc->ifc_len, error = 0; 685 686 ifrp = ifc->ifc_req; 687 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 688 char workbuf[64]; 689 int ifnlen; 690 691 ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit); 692 if(ifnlen + 1 > sizeof ifr.ifr_name) { 693 error = ENAMETOOLONG; 694 } else { 695 strcpy(ifr.ifr_name, workbuf); 696 } 697 698 if ((ifa = ifp->if_addrlist) == 0) { 699 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 700 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 701 sizeof (ifr)); 702 if (error) 703 break; 704 space -= sizeof (ifr), ifrp++; 705 } else 706 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 707 register struct sockaddr *sa = ifa->ifa_addr; 708#ifdef COMPAT_43 709 if (cmd == OSIOCGIFCONF) { 710 struct osockaddr *osa = 711 (struct osockaddr *)&ifr.ifr_addr; 712 ifr.ifr_addr = *sa; 713 osa->sa_family = sa->sa_family; 714 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 715 sizeof (ifr)); 716 ifrp++; 717 } else 718#endif 719 if (sa->sa_len <= sizeof(*sa)) { 720 ifr.ifr_addr = *sa; 721 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 722 sizeof (ifr)); 723 ifrp++; 724 } else { 725 space -= sa->sa_len - sizeof(*sa); 726 if (space < sizeof (ifr)) 727 break; 728 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 729 sizeof (ifr.ifr_name)); 730 if (error == 0) 731 error = copyout((caddr_t)sa, 732 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 733 ifrp = (struct ifreq *) 734 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 735 } 736 if (error) 737 break; 738 space -= sizeof (ifr); 739 } 740 } 741 ifc->ifc_len -= space; 742 return (error); 743} 744 745SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); 746SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); 747