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