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