123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 5*44463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*44463Sbostic * @(#)if.c 7.13 (Berkeley) 06/28/90 823157Smckusick */ 94944Swnj 1017036Sbloom #include "param.h" 1133984Skarels #include "mbuf.h" 1217036Sbloom #include "systm.h" 1317036Sbloom #include "socket.h" 1418544Skarels #include "socketvar.h" 1517036Sbloom #include "protosw.h" 1617036Sbloom #include "user.h" 1717036Sbloom #include "kernel.h" 1817036Sbloom #include "ioctl.h" 1917036Sbloom #include "errno.h" 2010872Ssam 2117036Sbloom #include "if.h" 2217036Sbloom #include "af.h" 2340792Ssklower #include "if_dl.h" 2443335Ssklower #include "if_types.h" 254944Swnj 2616220Skarels #include "ether.h" 2716220Skarels 286207Swnj int ifqmaxlen = IFQ_MAXLEN; 296207Swnj 306333Ssam /* 316333Ssam * Network interface utility routines. 326333Ssam * 3318544Skarels * Routines with ifa_ifwith* names take sockaddr *'s as 3418544Skarels * parameters. 356333Ssam */ 366333Ssam 375206Swnj ifinit() 385206Swnj { 395206Swnj register struct ifnet *ifp; 405206Swnj 415206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 4224773Skarels if (ifp->if_snd.ifq_maxlen == 0) 4324773Skarels ifp->if_snd.ifq_maxlen = ifqmaxlen; 448173Sroot if_slowtimo(); 455206Swnj } 465206Swnj 4713049Ssam #ifdef vax 486333Ssam /* 496333Ssam * Call each interface on a Unibus reset. 506333Ssam */ 515206Swnj ifubareset(uban) 525206Swnj int uban; 535206Swnj { 545206Swnj register struct ifnet *ifp; 555206Swnj 565206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 578974Sroot if (ifp->if_reset) 5815116Ssam (*ifp->if_reset)(ifp->if_unit, uban); 595206Swnj } 608393Swnj #endif 615206Swnj 6240792Ssklower int if_index = 0; 6343335Ssklower struct ifaddr **ifnet_addrs; 646333Ssam /* 656333Ssam * Attach an interface to the 666333Ssam * list of "active" interfaces. 676333Ssam */ 685160Swnj if_attach(ifp) 695160Swnj struct ifnet *ifp; 705160Swnj { 7140792Ssklower unsigned socksize, ifasize; 7240792Ssklower int namelen, unitlen; 7340792Ssklower char workbuf[16]; 7443335Ssklower register struct ifnet **p = &ifnet; 7540792Ssklower register struct sockaddr_dl *sdl; 7640792Ssklower register struct ifaddr *ifa; 7743335Ssklower static int if_indexlim = 8; 7843335Ssklower extern link_rtrequest(), ether_output(); 795160Swnj 805698Swnj while (*p) 815698Swnj p = &((*p)->if_next); 825698Swnj *p = ifp; 8340792Ssklower ifp->if_index = ++if_index; 8443335Ssklower if (ifnet_addrs == 0 || if_index >= if_indexlim) { 8543335Ssklower unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 8643335Ssklower struct ifaddr **q = (struct ifaddr **) 8743335Ssklower malloc(n, M_IFADDR, M_WAITOK); 8843335Ssklower if (ifnet_addrs) { 8943335Ssklower bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 9043335Ssklower free((caddr_t)ifnet_addrs, M_IFADDR); 9143335Ssklower } 9243335Ssklower ifnet_addrs = q; 9343335Ssklower } 9443335Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 9543335Ssklower if (ifp->if_output == ether_output) { 9643335Ssklower ifp->if_type = IFT_ETHER; 9743335Ssklower ifp->if_addrlen = 6; 9843335Ssklower ifp->if_hdrlen = 14; 9943335Ssklower } 10041923Ssklower /* 10141923Ssklower * create a Link Level name for this device 10241923Ssklower */ 10340792Ssklower sprint_d(workbuf, ifp->if_unit); 10440792Ssklower namelen = strlen(ifp->if_name); 10540792Ssklower unitlen = strlen(workbuf); 10640792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 10740792Ssklower socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 10840792Ssklower unitlen + namelen + ifp->if_addrlen; 10940792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 11040792Ssklower socksize = ROUNDUP(socksize); 11143335Ssklower if (socksize < sizeof(*sdl)) 11243335Ssklower socksize = sizeof(*sdl); 11340792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 11440792Ssklower ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 11540792Ssklower if (ifa == 0) 11640792Ssklower return; 11743335Ssklower ifnet_addrs[if_index - 1] = ifa; 11840792Ssklower bzero((caddr_t)ifa, ifasize); 11940792Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 12040792Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 12140792Ssklower ifa->ifa_ifp = ifp; 12240792Ssklower sdl->sdl_len = socksize; 12340792Ssklower sdl->sdl_family = AF_LINK; 12440792Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 12540792Ssklower bcopy((caddr_t)workbuf, namelen + (caddr_t)sdl->sdl_data, unitlen); 12640792Ssklower sdl->sdl_nlen = (namelen += unitlen); 12740792Ssklower sdl->sdl_index = ifp->if_index; 12840792Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 12940792Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 13040792Ssklower sdl->sdl_len = socksize - ifp->if_addrlen; 13140792Ssklower while (namelen != 0) 13240792Ssklower sdl->sdl_data[--namelen] = 0xff; 13340792Ssklower ifa->ifa_next = ifp->if_addrlist; 13441923Ssklower ifa->ifa_rtrequest = link_rtrequest; 13540792Ssklower ifp->if_addrlist = ifa; 1365160Swnj } 1376333Ssam /* 1386333Ssam * Locate an interface based on a complete address. 1396333Ssam */ 1404951Swnj /*ARGSUSED*/ 14118544Skarels struct ifaddr * 14218544Skarels ifa_ifwithaddr(addr) 14337549Smckusick register struct sockaddr *addr; 1444944Swnj { 1454944Swnj register struct ifnet *ifp; 14618544Skarels register struct ifaddr *ifa; 1474944Swnj 1486333Ssam #define equal(a1, a2) \ 14937549Smckusick (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 15018544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 15118544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 15237549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 1536333Ssam continue; 15437549Smckusick if (equal(addr, ifa->ifa_addr)) 15518544Skarels return (ifa); 15643335Ssklower if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 15743335Ssklower equal(ifa->ifa_broadaddr, addr)) 15818544Skarels return (ifa); 1596333Ssam } 16018544Skarels return ((struct ifaddr *)0); 1614944Swnj } 16223933Ssklower /* 16323933Ssklower * Locate the point to point interface with a given destination address. 16423933Ssklower */ 16523933Ssklower /*ARGSUSED*/ 16623933Ssklower struct ifaddr * 16723933Ssklower ifa_ifwithdstaddr(addr) 16837549Smckusick register struct sockaddr *addr; 16923933Ssklower { 17023933Ssklower register struct ifnet *ifp; 17123933Ssklower register struct ifaddr *ifa; 1724944Swnj 17323933Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) 17423933Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 17523933Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 17637549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 17723933Ssklower continue; 17837549Smckusick if (equal(addr, ifa->ifa_dstaddr)) 17923933Ssklower return (ifa); 18023933Ssklower } 18123933Ssklower return ((struct ifaddr *)0); 18223933Ssklower } 18323933Ssklower 1846333Ssam /* 1856333Ssam * Find an interface on a specific network. If many, choice 1866333Ssam * is first found. 1876333Ssam */ 18818544Skarels struct ifaddr * 18918544Skarels ifa_ifwithnet(addr) 19037549Smckusick struct sockaddr *addr; 1914944Swnj { 1924944Swnj register struct ifnet *ifp; 19318544Skarels register struct ifaddr *ifa; 19437549Smckusick u_int af = addr->sa_family; 1954944Swnj 1966619Ssam if (af >= AF_MAX) 1976619Ssam return (0); 19843335Ssklower if (af == AF_LINK) { 19943335Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 20043335Ssklower if (sdl->sdl_index && sdl->sdl_index <= if_index) 20143335Ssklower return (ifnet_addrs[sdl->sdl_index - 1]); 20243335Ssklower } 20318544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 20418544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 20543335Ssklower register char *cp, *cp2, *cp3; 20643335Ssklower register char *cplim; 20737549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 2086333Ssam continue; 20937549Smckusick cp = addr->sa_data; 21037549Smckusick cp2 = ifa->ifa_addr->sa_data; 21137549Smckusick cp3 = ifa->ifa_netmask->sa_data; 21237549Smckusick cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 21337549Smckusick for (; cp3 < cplim; cp3++) 21437549Smckusick if ((*cp++ ^ *cp2++) & *cp3) 21537549Smckusick break; 21637549Smckusick if (cp3 == cplim) 21718544Skarels return (ifa); 21837549Smckusick } 21918544Skarels return ((struct ifaddr *)0); 2206333Ssam } 2216333Ssam 2226333Ssam /* 2236333Ssam * Find an interface using a specific address family 2246333Ssam */ 22518544Skarels struct ifaddr * 22618544Skarels ifa_ifwithaf(af) 2276333Ssam register int af; 2285083Swnj { 2296333Ssam register struct ifnet *ifp; 23018544Skarels register struct ifaddr *ifa; 2315083Swnj 2326333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 23318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 23437549Smckusick if (ifa->ifa_addr->sa_family == af) 23518544Skarels return (ifa); 23618544Skarels return ((struct ifaddr *)0); 2375083Swnj } 2385104Swnj 23943335Ssklower /* 24043335Ssklower * Find an interface address specific to an interface best matching 24143335Ssklower * a given address. 24243335Ssklower */ 24343335Ssklower struct ifaddr * 24443335Ssklower ifaof_ifpforaddr(addr, ifp) 24543335Ssklower struct sockaddr *addr; 24643335Ssklower register struct ifnet *ifp; 24743335Ssklower { 24843335Ssklower register struct ifaddr *ifa; 24943335Ssklower register char *cp, *cp2, *cp3; 25043335Ssklower register char *cplim; 25143335Ssklower struct ifaddr *ifa_maybe = 0; 25243335Ssklower u_int af = addr->sa_family; 25343335Ssklower 25443335Ssklower if (af >= AF_MAX) 25543335Ssklower return (0); 25643335Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 25743335Ssklower if (ifa->ifa_addr->sa_family != af) 25843335Ssklower continue; 25943335Ssklower ifa_maybe = ifa; 26043335Ssklower if (ifa->ifa_netmask == 0) { 26143335Ssklower if (equal(addr, ifa->ifa_addr) || 26243335Ssklower (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 26343335Ssklower return (ifa); 26443335Ssklower continue; 26543335Ssklower } 26643335Ssklower cp = addr->sa_data; 26743335Ssklower cp2 = ifa->ifa_addr->sa_data; 26843335Ssklower cp3 = ifa->ifa_netmask->sa_data; 26943335Ssklower cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 27043335Ssklower for (; cp3 < cplim; cp3++) 27143335Ssklower if ((*cp++ ^ *cp2++) & *cp3) 27243335Ssklower break; 27343335Ssklower if (cp3 == cplim) 27443335Ssklower return (ifa); 27543335Ssklower } 27643335Ssklower return (ifa_maybe); 27743335Ssklower } 27841923Ssklower #include "route.h" 2796333Ssam /* 28041923Ssklower * Default action when installing a route with a Link Level gateway. 28141923Ssklower * Lookup an appropriate real ifa to point to. 28241923Ssklower * This should be moved to /sys/net/link.c eventually. 28341923Ssklower */ 28441923Ssklower link_rtrequest(cmd, rt, sa) 28541923Ssklower register struct rtentry *rt; 28641923Ssklower struct sockaddr *sa; 28741923Ssklower { 28841923Ssklower register struct ifaddr *ifa; 28941923Ssklower struct sockaddr *dst; 29041923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29141923Ssklower 29241923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29341923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29441923Ssklower return; 29543335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 29641923Ssklower rt->rt_ifa = ifa; 29741923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 29841923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 29943335Ssklower } 30041923Ssklower } 30141923Ssklower 30241923Ssklower /* 3036582Ssam * Mark an interface down and notify protocols of 3046582Ssam * the transition. 3059184Ssam * NOTE: must be called at splnet or eqivalent. 3066582Ssam */ 3076582Ssam if_down(ifp) 3086582Ssam register struct ifnet *ifp; 3096582Ssam { 31018544Skarels register struct ifaddr *ifa; 3118173Sroot 3126582Ssam ifp->if_flags &= ~IFF_UP; 31318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31437549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 31533984Skarels if_qflush(&ifp->if_snd); 3166582Ssam } 3177264Ssam 3187264Ssam /* 31933984Skarels * Flush an interface queue. 32033984Skarels */ 32133984Skarels if_qflush(ifq) 32233984Skarels register struct ifqueue *ifq; 32333984Skarels { 32433984Skarels register struct mbuf *m, *n; 32533984Skarels 32633984Skarels n = ifq->ifq_head; 32733984Skarels while (m = n) { 32833984Skarels n = m->m_act; 32933984Skarels m_freem(m); 33033984Skarels } 33133984Skarels ifq->ifq_head = 0; 33233984Skarels ifq->ifq_tail = 0; 33333984Skarels ifq->ifq_len = 0; 33433984Skarels } 33533984Skarels 33633984Skarels /* 3377264Ssam * Handle interface watchdog timer routines. Called 3387264Ssam * from softclock, we decrement timers (if set) and 3397264Ssam * call the appropriate interface routine on expiration. 3407264Ssam */ 3417264Ssam if_slowtimo() 3427264Ssam { 3437264Ssam register struct ifnet *ifp; 34437549Smckusick int s = splimp(); 3457264Ssam 3469184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3479184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3489184Ssam continue; 3499184Ssam if (ifp->if_watchdog) 3507264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3519184Ssam } 35237549Smckusick splx(s); 3538692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3547264Ssam } 35511576Ssam 35611576Ssam /* 35713049Ssam * Map interface name to 35813049Ssam * interface structure pointer. 35911576Ssam */ 36013049Ssam struct ifnet * 36113049Ssam ifunit(name) 36213049Ssam register char *name; 36311576Ssam { 36413049Ssam register char *cp; 36511576Ssam register struct ifnet *ifp; 36613049Ssam int unit; 36736821Skarels unsigned len; 36836821Skarels char *ep, c; 36911576Ssam 37013049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 37111576Ssam if (*cp >= '0' && *cp <= '9') 37211576Ssam break; 37313049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 37413049Ssam return ((struct ifnet *)0); 37536821Skarels /* 37636821Skarels * Save first char of unit, and pointer to it, 37736821Skarels * so we can put a null there to avoid matching 37836821Skarels * initial substrings of interface names. 37936821Skarels */ 38036821Skarels len = cp - name + 1; 38136821Skarels c = *cp; 38236821Skarels ep = cp; 38336821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 38436821Skarels unit = unit * 10 + *cp++ - '0'; 38536821Skarels *ep = 0; 38611576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 38736821Skarels if (bcmp(ifp->if_name, name, len)) 38811576Ssam continue; 38911576Ssam if (unit == ifp->if_unit) 39013049Ssam break; 39111576Ssam } 39236821Skarels *ep = c; 39313049Ssam return (ifp); 39413049Ssam } 39511576Ssam 39613049Ssam /* 39713049Ssam * Interface ioctls. 39813049Ssam */ 39918544Skarels ifioctl(so, cmd, data) 40018544Skarels struct socket *so; 40113049Ssam int cmd; 40213049Ssam caddr_t data; 40313049Ssam { 40413049Ssam register struct ifnet *ifp; 40513049Ssam register struct ifreq *ifr; 40637549Smckusick int error; 40713049Ssam 40811576Ssam switch (cmd) { 40911576Ssam 41013049Ssam case SIOCGIFCONF: 41137549Smckusick case OSIOCGIFCONF: 41213049Ssam return (ifconf(cmd, data)); 41313049Ssam 41425647Skarels #if defined(INET) && NETHER > 0 41516220Skarels case SIOCSARP: 41616220Skarels case SIOCDARP: 41737549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 41837549Smckusick return (error); 41916220Skarels /* FALL THROUGH */ 42016220Skarels case SIOCGARP: 42137549Smckusick case OSIOCGARP: 42216220Skarels return (arpioctl(cmd, data)); 42316220Skarels #endif 42413049Ssam } 42513049Ssam ifr = (struct ifreq *)data; 42613049Ssam ifp = ifunit(ifr->ifr_name); 42713049Ssam if (ifp == 0) 42813049Ssam return (ENXIO); 42913049Ssam switch (cmd) { 43013049Ssam 43111576Ssam case SIOCGIFFLAGS: 43211576Ssam ifr->ifr_flags = ifp->if_flags; 43311576Ssam break; 43411576Ssam 43526091Skarels case SIOCGIFMETRIC: 43626091Skarels ifr->ifr_metric = ifp->if_metric; 43726091Skarels break; 43826091Skarels 43913053Ssam case SIOCSIFFLAGS: 44037549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 44137549Smckusick return (error); 44213053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 44313053Ssam int s = splimp(); 44413053Ssam if_down(ifp); 44513053Ssam splx(s); 44613053Ssam } 44718544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 44818544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 44924773Skarels if (ifp->if_ioctl) 45024773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 45113053Ssam break; 45213053Ssam 45326091Skarels case SIOCSIFMETRIC: 45437549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 45537549Smckusick return (error); 45626091Skarels ifp->if_metric = ifr->ifr_metric; 45726091Skarels break; 45826091Skarels 45911576Ssam default: 46018544Skarels if (so->so_proto == 0) 46113049Ssam return (EOPNOTSUPP); 46237549Smckusick #ifndef COMPAT_43 46318544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 46418544Skarels cmd, data, ifp)); 46537549Smckusick #else 46637549Smckusick { 46741545Smckusick int ocmd = cmd; 46837549Smckusick 46937549Smckusick switch (cmd) { 47037549Smckusick 47137549Smckusick case SIOCSIFDSTADDR: 47237549Smckusick case SIOCSIFADDR: 47337549Smckusick case SIOCSIFBRDADDR: 47437549Smckusick case SIOCSIFNETMASK: 47537549Smckusick #if BYTE_ORDER != BIG_ENDIAN 47637549Smckusick if (ifr->ifr_addr.sa_family == 0 && 47737549Smckusick ifr->ifr_addr.sa_len < 16) { 47837549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 47937549Smckusick ifr->ifr_addr.sa_len = 16; 48037549Smckusick } 48137549Smckusick #else 48237549Smckusick if (ifr->ifr_addr.sa_len == 0) 48337549Smckusick ifr->ifr_addr.sa_len = 16; 48437549Smckusick #endif 48537549Smckusick break; 48637549Smckusick 48737549Smckusick case OSIOCGIFADDR: 48837549Smckusick cmd = SIOCGIFADDR; 48937549Smckusick break; 49037549Smckusick 49137549Smckusick case OSIOCGIFDSTADDR: 49237549Smckusick cmd = SIOCGIFDSTADDR; 49337549Smckusick break; 49437549Smckusick 49537549Smckusick case OSIOCGIFBRDADDR: 49637549Smckusick cmd = SIOCGIFBRDADDR; 49737549Smckusick break; 49837549Smckusick 49937549Smckusick case OSIOCGIFNETMASK: 50037549Smckusick cmd = SIOCGIFNETMASK; 50137549Smckusick } 50237549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50337549Smckusick cmd, data, ifp)); 50437549Smckusick switch (ocmd) { 50537549Smckusick 50637549Smckusick case OSIOCGIFADDR: 50737549Smckusick case OSIOCGIFDSTADDR: 50837549Smckusick case OSIOCGIFBRDADDR: 50937549Smckusick case OSIOCGIFNETMASK: 51037549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 51137549Smckusick } 51237549Smckusick return (error); 51337549Smckusick 51437549Smckusick } 51537549Smckusick #endif 51611576Ssam } 51711576Ssam return (0); 51811576Ssam } 51911576Ssam 52011576Ssam /* 52111576Ssam * Return interface configuration 52211576Ssam * of system. List may be used 52311576Ssam * in later ioctl's (above) to get 52411576Ssam * other information. 52511576Ssam */ 52612783Ssam /*ARGSUSED*/ 52711576Ssam ifconf(cmd, data) 52811576Ssam int cmd; 52911576Ssam caddr_t data; 53011576Ssam { 53111576Ssam register struct ifconf *ifc = (struct ifconf *)data; 53211576Ssam register struct ifnet *ifp = ifnet; 53318544Skarels register struct ifaddr *ifa; 53411630Ssam register char *cp, *ep; 53511630Ssam struct ifreq ifr, *ifrp; 53611576Ssam int space = ifc->ifc_len, error = 0; 53711576Ssam 53811630Ssam ifrp = ifc->ifc_req; 53911630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 54011576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 54111630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 54211630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 54311576Ssam ; 54411630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 54518544Skarels if ((ifa = ifp->if_addrlist) == 0) { 54618544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 54718544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 54818544Skarels if (error) 54918544Skarels break; 55018544Skarels space -= sizeof (ifr), ifrp++; 55118544Skarels } else 55218544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 55337549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 55437549Smckusick #ifdef COMPAT_43 55537549Smckusick if (cmd == OSIOCGIFCONF) { 55637549Smckusick struct osockaddr *osa = 55737549Smckusick (struct osockaddr *)&ifr.ifr_addr; 55837549Smckusick ifr.ifr_addr = *sa; 55937549Smckusick osa->sa_family = sa->sa_family; 56037549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 56137549Smckusick sizeof (ifr)); 56237549Smckusick ifrp++; 56337549Smckusick } else 56437549Smckusick #endif 56537549Smckusick if (sa->sa_len <= sizeof(*sa)) { 56637549Smckusick ifr.ifr_addr = *sa; 56737549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 56837549Smckusick sizeof (ifr)); 56937549Smckusick ifrp++; 57037549Smckusick } else { 57137549Smckusick space -= sa->sa_len - sizeof(*sa); 57237549Smckusick if (space < sizeof (ifr)) 57337549Smckusick break; 57437549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57537549Smckusick sizeof (ifr.ifr_name)); 57637549Smckusick if (error == 0) 57737549Smckusick error = copyout((caddr_t)sa, 57837549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 57937549Smckusick ifrp = (struct ifreq *) 58037549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 58137549Smckusick } 58218544Skarels if (error) 58318544Skarels break; 58437549Smckusick space -= sizeof (ifr); 58518544Skarels } 58611576Ssam } 58711576Ssam ifc->ifc_len -= space; 58811576Ssam return (error); 58911576Ssam } 59040792Ssklower 59140792Ssklower static sprint_d(cp, n) 59240792Ssklower register char *cp; 59340792Ssklower u_short n; 59440792Ssklower { 59540792Ssklower register int q, m; 59640792Ssklower do { 59740792Ssklower if (n >= 10000) m = 10000; 59840792Ssklower else if (n >= 1000) m = 1000; 59940792Ssklower else if (n >= 100) m = 100; 60040792Ssklower else if (n >= 10) m = 10; 60140792Ssklower else m = 1; 60240792Ssklower q = n / m; 60340792Ssklower n -= m * q; 60440792Ssklower if (q > 9) q = 10; /* For crays with more than 100K interfaces */ 60540792Ssklower *cp++ = "0123456789Z"[q]; 60640792Ssklower } while (n > 0); 60740792Ssklower *cp++ = 0; 60840792Ssklower } 609