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