123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*48453Skarels * @(#)if.c 7.14 (Berkeley) 04/20/91 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" 16*48453Skarels #include "proc.h" 1717036Sbloom #include "kernel.h" 1817036Sbloom #include "ioctl.h" 1910872Ssam 2017036Sbloom #include "if.h" 2117036Sbloom #include "af.h" 2240792Ssklower #include "if_dl.h" 2343335Ssklower #include "if_types.h" 244944Swnj 2516220Skarels #include "ether.h" 2616220Skarels 276207Swnj int ifqmaxlen = IFQ_MAXLEN; 286207Swnj 296333Ssam /* 306333Ssam * Network interface utility routines. 316333Ssam * 3218544Skarels * Routines with ifa_ifwith* names take sockaddr *'s as 3318544Skarels * parameters. 346333Ssam */ 356333Ssam 365206Swnj ifinit() 375206Swnj { 385206Swnj register struct ifnet *ifp; 395206Swnj 405206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 4124773Skarels if (ifp->if_snd.ifq_maxlen == 0) 4224773Skarels ifp->if_snd.ifq_maxlen = ifqmaxlen; 438173Sroot if_slowtimo(); 445206Swnj } 455206Swnj 4613049Ssam #ifdef vax 476333Ssam /* 486333Ssam * Call each interface on a Unibus reset. 496333Ssam */ 505206Swnj ifubareset(uban) 515206Swnj int uban; 525206Swnj { 535206Swnj register struct ifnet *ifp; 545206Swnj 555206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 568974Sroot if (ifp->if_reset) 5715116Ssam (*ifp->if_reset)(ifp->if_unit, uban); 585206Swnj } 598393Swnj #endif 605206Swnj 6140792Ssklower int if_index = 0; 6243335Ssklower struct ifaddr **ifnet_addrs; 63*48453Skarels static char *sprint_d(); 64*48453Skarels 656333Ssam /* 666333Ssam * Attach an interface to the 676333Ssam * list of "active" interfaces. 686333Ssam */ 695160Swnj if_attach(ifp) 705160Swnj struct ifnet *ifp; 715160Swnj { 7240792Ssklower unsigned socksize, ifasize; 7340792Ssklower int namelen, unitlen; 74*48453Skarels char workbuf[12], *unitname; 7543335Ssklower register struct ifnet **p = &ifnet; 7640792Ssklower register struct sockaddr_dl *sdl; 7740792Ssklower register struct ifaddr *ifa; 7843335Ssklower static int if_indexlim = 8; 7943335Ssklower extern link_rtrequest(), ether_output(); 805160Swnj 815698Swnj while (*p) 825698Swnj p = &((*p)->if_next); 835698Swnj *p = ifp; 8440792Ssklower ifp->if_index = ++if_index; 8543335Ssklower if (ifnet_addrs == 0 || if_index >= if_indexlim) { 8643335Ssklower unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 8743335Ssklower struct ifaddr **q = (struct ifaddr **) 8843335Ssklower malloc(n, M_IFADDR, M_WAITOK); 8943335Ssklower if (ifnet_addrs) { 9043335Ssklower bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 9143335Ssklower free((caddr_t)ifnet_addrs, M_IFADDR); 9243335Ssklower } 9343335Ssklower ifnet_addrs = q; 9443335Ssklower } 9543335Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 9643335Ssklower if (ifp->if_output == ether_output) { 9743335Ssklower ifp->if_type = IFT_ETHER; 9843335Ssklower ifp->if_addrlen = 6; 9943335Ssklower ifp->if_hdrlen = 14; 10043335Ssklower } 10141923Ssklower /* 10241923Ssklower * create a Link Level name for this device 10341923Ssklower */ 104*48453Skarels unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 10540792Ssklower namelen = strlen(ifp->if_name); 106*48453Skarels unitlen = strlen(unitname); 10740792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 10840792Ssklower socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 10940792Ssklower unitlen + namelen + ifp->if_addrlen; 11040792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 11140792Ssklower socksize = ROUNDUP(socksize); 11243335Ssklower if (socksize < sizeof(*sdl)) 11343335Ssklower socksize = sizeof(*sdl); 11440792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 11540792Ssklower ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 11640792Ssklower if (ifa == 0) 11740792Ssklower return; 11843335Ssklower ifnet_addrs[if_index - 1] = ifa; 11940792Ssklower bzero((caddr_t)ifa, ifasize); 12040792Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 12140792Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 12240792Ssklower ifa->ifa_ifp = ifp; 12340792Ssklower sdl->sdl_len = socksize; 12440792Ssklower sdl->sdl_family = AF_LINK; 12540792Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 126*48453Skarels bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 12740792Ssklower sdl->sdl_nlen = (namelen += unitlen); 12840792Ssklower sdl->sdl_index = ifp->if_index; 12940792Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 13040792Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 13140792Ssklower sdl->sdl_len = socksize - ifp->if_addrlen; 13240792Ssklower while (namelen != 0) 13340792Ssklower sdl->sdl_data[--namelen] = 0xff; 13440792Ssklower ifa->ifa_next = ifp->if_addrlist; 13541923Ssklower ifa->ifa_rtrequest = link_rtrequest; 13640792Ssklower ifp->if_addrlist = ifa; 1375160Swnj } 1386333Ssam /* 1396333Ssam * Locate an interface based on a complete address. 1406333Ssam */ 1414951Swnj /*ARGSUSED*/ 14218544Skarels struct ifaddr * 14318544Skarels ifa_ifwithaddr(addr) 14437549Smckusick register struct sockaddr *addr; 1454944Swnj { 1464944Swnj register struct ifnet *ifp; 14718544Skarels register struct ifaddr *ifa; 1484944Swnj 1496333Ssam #define equal(a1, a2) \ 15037549Smckusick (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 15118544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 15218544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 15337549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 1546333Ssam continue; 15537549Smckusick if (equal(addr, ifa->ifa_addr)) 15618544Skarels return (ifa); 15743335Ssklower if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 15843335Ssklower equal(ifa->ifa_broadaddr, addr)) 15918544Skarels return (ifa); 1606333Ssam } 16118544Skarels return ((struct ifaddr *)0); 1624944Swnj } 16323933Ssklower /* 16423933Ssklower * Locate the point to point interface with a given destination address. 16523933Ssklower */ 16623933Ssklower /*ARGSUSED*/ 16723933Ssklower struct ifaddr * 16823933Ssklower ifa_ifwithdstaddr(addr) 16937549Smckusick register struct sockaddr *addr; 17023933Ssklower { 17123933Ssklower register struct ifnet *ifp; 17223933Ssklower register struct ifaddr *ifa; 1734944Swnj 17423933Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) 17523933Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 17623933Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 17737549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 17823933Ssklower continue; 17937549Smckusick if (equal(addr, ifa->ifa_dstaddr)) 18023933Ssklower return (ifa); 18123933Ssklower } 18223933Ssklower return ((struct ifaddr *)0); 18323933Ssklower } 18423933Ssklower 1856333Ssam /* 1866333Ssam * Find an interface on a specific network. If many, choice 1876333Ssam * is first found. 1886333Ssam */ 18918544Skarels struct ifaddr * 19018544Skarels ifa_ifwithnet(addr) 19137549Smckusick struct sockaddr *addr; 1924944Swnj { 1934944Swnj register struct ifnet *ifp; 19418544Skarels register struct ifaddr *ifa; 19537549Smckusick u_int af = addr->sa_family; 1964944Swnj 1976619Ssam if (af >= AF_MAX) 1986619Ssam return (0); 19943335Ssklower if (af == AF_LINK) { 20043335Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 20143335Ssklower if (sdl->sdl_index && sdl->sdl_index <= if_index) 20243335Ssklower return (ifnet_addrs[sdl->sdl_index - 1]); 20343335Ssklower } 20418544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 20518544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 20643335Ssklower register char *cp, *cp2, *cp3; 20743335Ssklower register char *cplim; 20837549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 2096333Ssam continue; 21037549Smckusick cp = addr->sa_data; 21137549Smckusick cp2 = ifa->ifa_addr->sa_data; 21237549Smckusick cp3 = ifa->ifa_netmask->sa_data; 21337549Smckusick cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 21437549Smckusick for (; cp3 < cplim; cp3++) 21537549Smckusick if ((*cp++ ^ *cp2++) & *cp3) 21637549Smckusick break; 21737549Smckusick if (cp3 == cplim) 21818544Skarels return (ifa); 21937549Smckusick } 22018544Skarels return ((struct ifaddr *)0); 2216333Ssam } 2226333Ssam 2236333Ssam /* 2246333Ssam * Find an interface using a specific address family 2256333Ssam */ 22618544Skarels struct ifaddr * 22718544Skarels ifa_ifwithaf(af) 2286333Ssam register int af; 2295083Swnj { 2306333Ssam register struct ifnet *ifp; 23118544Skarels register struct ifaddr *ifa; 2325083Swnj 2336333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 23418544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 23537549Smckusick if (ifa->ifa_addr->sa_family == af) 23618544Skarels return (ifa); 23718544Skarels return ((struct ifaddr *)0); 2385083Swnj } 2395104Swnj 24043335Ssklower /* 24143335Ssklower * Find an interface address specific to an interface best matching 24243335Ssklower * a given address. 24343335Ssklower */ 24443335Ssklower struct ifaddr * 24543335Ssklower ifaof_ifpforaddr(addr, ifp) 24643335Ssklower struct sockaddr *addr; 24743335Ssklower register struct ifnet *ifp; 24843335Ssklower { 24943335Ssklower register struct ifaddr *ifa; 25043335Ssklower register char *cp, *cp2, *cp3; 25143335Ssklower register char *cplim; 25243335Ssklower struct ifaddr *ifa_maybe = 0; 25343335Ssklower u_int af = addr->sa_family; 25443335Ssklower 25543335Ssklower if (af >= AF_MAX) 25643335Ssklower return (0); 25743335Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 25843335Ssklower if (ifa->ifa_addr->sa_family != af) 25943335Ssklower continue; 26043335Ssklower ifa_maybe = ifa; 26143335Ssklower if (ifa->ifa_netmask == 0) { 26243335Ssklower if (equal(addr, ifa->ifa_addr) || 26343335Ssklower (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 26443335Ssklower return (ifa); 26543335Ssklower continue; 26643335Ssklower } 26743335Ssklower cp = addr->sa_data; 26843335Ssklower cp2 = ifa->ifa_addr->sa_data; 26943335Ssklower cp3 = ifa->ifa_netmask->sa_data; 27043335Ssklower cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 27143335Ssklower for (; cp3 < cplim; cp3++) 27243335Ssklower if ((*cp++ ^ *cp2++) & *cp3) 27343335Ssklower break; 27443335Ssklower if (cp3 == cplim) 27543335Ssklower return (ifa); 27643335Ssklower } 27743335Ssklower return (ifa_maybe); 27843335Ssklower } 27941923Ssklower #include "route.h" 2806333Ssam /* 28141923Ssklower * Default action when installing a route with a Link Level gateway. 28241923Ssklower * Lookup an appropriate real ifa to point to. 28341923Ssklower * This should be moved to /sys/net/link.c eventually. 28441923Ssklower */ 28541923Ssklower link_rtrequest(cmd, rt, sa) 28641923Ssklower register struct rtentry *rt; 28741923Ssklower struct sockaddr *sa; 28841923Ssklower { 28941923Ssklower register struct ifaddr *ifa; 29041923Ssklower struct sockaddr *dst; 29141923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29241923Ssklower 29341923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29441923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29541923Ssklower return; 29643335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 29741923Ssklower rt->rt_ifa = ifa; 29841923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 29941923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30043335Ssklower } 30141923Ssklower } 30241923Ssklower 30341923Ssklower /* 3046582Ssam * Mark an interface down and notify protocols of 3056582Ssam * the transition. 3069184Ssam * NOTE: must be called at splnet or eqivalent. 3076582Ssam */ 3086582Ssam if_down(ifp) 3096582Ssam register struct ifnet *ifp; 3106582Ssam { 31118544Skarels register struct ifaddr *ifa; 3128173Sroot 3136582Ssam ifp->if_flags &= ~IFF_UP; 31418544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31537549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 31633984Skarels if_qflush(&ifp->if_snd); 3176582Ssam } 3187264Ssam 3197264Ssam /* 32033984Skarels * Flush an interface queue. 32133984Skarels */ 32233984Skarels if_qflush(ifq) 32333984Skarels register struct ifqueue *ifq; 32433984Skarels { 32533984Skarels register struct mbuf *m, *n; 32633984Skarels 32733984Skarels n = ifq->ifq_head; 32833984Skarels while (m = n) { 32933984Skarels n = m->m_act; 33033984Skarels m_freem(m); 33133984Skarels } 33233984Skarels ifq->ifq_head = 0; 33333984Skarels ifq->ifq_tail = 0; 33433984Skarels ifq->ifq_len = 0; 33533984Skarels } 33633984Skarels 33733984Skarels /* 3387264Ssam * Handle interface watchdog timer routines. Called 3397264Ssam * from softclock, we decrement timers (if set) and 3407264Ssam * call the appropriate interface routine on expiration. 3417264Ssam */ 3427264Ssam if_slowtimo() 3437264Ssam { 3447264Ssam register struct ifnet *ifp; 34537549Smckusick int s = splimp(); 3467264Ssam 3479184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3489184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3499184Ssam continue; 3509184Ssam if (ifp->if_watchdog) 3517264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3529184Ssam } 35337549Smckusick splx(s); 3548692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3557264Ssam } 35611576Ssam 35711576Ssam /* 35813049Ssam * Map interface name to 35913049Ssam * interface structure pointer. 36011576Ssam */ 36113049Ssam struct ifnet * 36213049Ssam ifunit(name) 36313049Ssam register char *name; 36411576Ssam { 36513049Ssam register char *cp; 36611576Ssam register struct ifnet *ifp; 36713049Ssam int unit; 36836821Skarels unsigned len; 36936821Skarels char *ep, c; 37011576Ssam 37113049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 37211576Ssam if (*cp >= '0' && *cp <= '9') 37311576Ssam break; 37413049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 37513049Ssam return ((struct ifnet *)0); 37636821Skarels /* 37736821Skarels * Save first char of unit, and pointer to it, 37836821Skarels * so we can put a null there to avoid matching 37936821Skarels * initial substrings of interface names. 38036821Skarels */ 38136821Skarels len = cp - name + 1; 38236821Skarels c = *cp; 38336821Skarels ep = cp; 38436821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 38536821Skarels unit = unit * 10 + *cp++ - '0'; 38636821Skarels *ep = 0; 38711576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 38836821Skarels if (bcmp(ifp->if_name, name, len)) 38911576Ssam continue; 39011576Ssam if (unit == ifp->if_unit) 39113049Ssam break; 39211576Ssam } 39336821Skarels *ep = c; 39413049Ssam return (ifp); 39513049Ssam } 39611576Ssam 39713049Ssam /* 39813049Ssam * Interface ioctls. 39913049Ssam */ 400*48453Skarels ifioctl(so, cmd, data, p) 40118544Skarels struct socket *so; 40213049Ssam int cmd; 40313049Ssam caddr_t data; 404*48453Skarels struct proc *p; 40513049Ssam { 40613049Ssam register struct ifnet *ifp; 40713049Ssam register struct ifreq *ifr; 40837549Smckusick int error; 40913049Ssam 41011576Ssam switch (cmd) { 41111576Ssam 41213049Ssam case SIOCGIFCONF: 41337549Smckusick case OSIOCGIFCONF: 41413049Ssam return (ifconf(cmd, data)); 41513049Ssam 41625647Skarels #if defined(INET) && NETHER > 0 41716220Skarels case SIOCSARP: 41816220Skarels case SIOCDARP: 419*48453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 42037549Smckusick return (error); 42116220Skarels /* FALL THROUGH */ 42216220Skarels case SIOCGARP: 42337549Smckusick case OSIOCGARP: 42416220Skarels return (arpioctl(cmd, data)); 42516220Skarels #endif 42613049Ssam } 42713049Ssam ifr = (struct ifreq *)data; 42813049Ssam ifp = ifunit(ifr->ifr_name); 42913049Ssam if (ifp == 0) 43013049Ssam return (ENXIO); 43113049Ssam switch (cmd) { 43213049Ssam 43311576Ssam case SIOCGIFFLAGS: 43411576Ssam ifr->ifr_flags = ifp->if_flags; 43511576Ssam break; 43611576Ssam 43726091Skarels case SIOCGIFMETRIC: 43826091Skarels ifr->ifr_metric = ifp->if_metric; 43926091Skarels break; 44026091Skarels 44113053Ssam case SIOCSIFFLAGS: 442*48453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44337549Smckusick return (error); 44413053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 44513053Ssam int s = splimp(); 44613053Ssam if_down(ifp); 44713053Ssam splx(s); 44813053Ssam } 44918544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 45018544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 45124773Skarels if (ifp->if_ioctl) 45224773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 45313053Ssam break; 45413053Ssam 45526091Skarels case SIOCSIFMETRIC: 456*48453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 45737549Smckusick return (error); 45826091Skarels ifp->if_metric = ifr->ifr_metric; 45926091Skarels break; 46026091Skarels 46111576Ssam default: 46218544Skarels if (so->so_proto == 0) 46313049Ssam return (EOPNOTSUPP); 46437549Smckusick #ifndef COMPAT_43 46518544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 46618544Skarels cmd, data, ifp)); 46737549Smckusick #else 46837549Smckusick { 46941545Smckusick int ocmd = cmd; 47037549Smckusick 47137549Smckusick switch (cmd) { 47237549Smckusick 47337549Smckusick case SIOCSIFDSTADDR: 47437549Smckusick case SIOCSIFADDR: 47537549Smckusick case SIOCSIFBRDADDR: 47637549Smckusick case SIOCSIFNETMASK: 47737549Smckusick #if BYTE_ORDER != BIG_ENDIAN 47837549Smckusick if (ifr->ifr_addr.sa_family == 0 && 47937549Smckusick ifr->ifr_addr.sa_len < 16) { 48037549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 48137549Smckusick ifr->ifr_addr.sa_len = 16; 48237549Smckusick } 48337549Smckusick #else 48437549Smckusick if (ifr->ifr_addr.sa_len == 0) 48537549Smckusick ifr->ifr_addr.sa_len = 16; 48637549Smckusick #endif 48737549Smckusick break; 48837549Smckusick 48937549Smckusick case OSIOCGIFADDR: 49037549Smckusick cmd = SIOCGIFADDR; 49137549Smckusick break; 49237549Smckusick 49337549Smckusick case OSIOCGIFDSTADDR: 49437549Smckusick cmd = SIOCGIFDSTADDR; 49537549Smckusick break; 49637549Smckusick 49737549Smckusick case OSIOCGIFBRDADDR: 49837549Smckusick cmd = SIOCGIFBRDADDR; 49937549Smckusick break; 50037549Smckusick 50137549Smckusick case OSIOCGIFNETMASK: 50237549Smckusick cmd = SIOCGIFNETMASK; 50337549Smckusick } 50437549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50537549Smckusick cmd, data, ifp)); 50637549Smckusick switch (ocmd) { 50737549Smckusick 50837549Smckusick case OSIOCGIFADDR: 50937549Smckusick case OSIOCGIFDSTADDR: 51037549Smckusick case OSIOCGIFBRDADDR: 51137549Smckusick case OSIOCGIFNETMASK: 51237549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 51337549Smckusick } 51437549Smckusick return (error); 51537549Smckusick 51637549Smckusick } 51737549Smckusick #endif 51811576Ssam } 51911576Ssam return (0); 52011576Ssam } 52111576Ssam 52211576Ssam /* 52311576Ssam * Return interface configuration 52411576Ssam * of system. List may be used 52511576Ssam * in later ioctl's (above) to get 52611576Ssam * other information. 52711576Ssam */ 52812783Ssam /*ARGSUSED*/ 52911576Ssam ifconf(cmd, data) 53011576Ssam int cmd; 53111576Ssam caddr_t data; 53211576Ssam { 53311576Ssam register struct ifconf *ifc = (struct ifconf *)data; 53411576Ssam register struct ifnet *ifp = ifnet; 53518544Skarels register struct ifaddr *ifa; 53611630Ssam register char *cp, *ep; 53711630Ssam struct ifreq ifr, *ifrp; 53811576Ssam int space = ifc->ifc_len, error = 0; 53911576Ssam 54011630Ssam ifrp = ifc->ifc_req; 54111630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 54211576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 54311630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 54411630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 54511576Ssam ; 54611630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 54718544Skarels if ((ifa = ifp->if_addrlist) == 0) { 54818544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 54918544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 55018544Skarels if (error) 55118544Skarels break; 55218544Skarels space -= sizeof (ifr), ifrp++; 55318544Skarels } else 55418544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 55537549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 55637549Smckusick #ifdef COMPAT_43 55737549Smckusick if (cmd == OSIOCGIFCONF) { 55837549Smckusick struct osockaddr *osa = 55937549Smckusick (struct osockaddr *)&ifr.ifr_addr; 56037549Smckusick ifr.ifr_addr = *sa; 56137549Smckusick osa->sa_family = sa->sa_family; 56237549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 56337549Smckusick sizeof (ifr)); 56437549Smckusick ifrp++; 56537549Smckusick } else 56637549Smckusick #endif 56737549Smckusick if (sa->sa_len <= sizeof(*sa)) { 56837549Smckusick ifr.ifr_addr = *sa; 56937549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57037549Smckusick sizeof (ifr)); 57137549Smckusick ifrp++; 57237549Smckusick } else { 57337549Smckusick space -= sa->sa_len - sizeof(*sa); 57437549Smckusick if (space < sizeof (ifr)) 57537549Smckusick break; 57637549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57737549Smckusick sizeof (ifr.ifr_name)); 57837549Smckusick if (error == 0) 57937549Smckusick error = copyout((caddr_t)sa, 58037549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 58137549Smckusick ifrp = (struct ifreq *) 58237549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 58337549Smckusick } 58418544Skarels if (error) 58518544Skarels break; 58637549Smckusick space -= sizeof (ifr); 58718544Skarels } 58811576Ssam } 58911576Ssam ifc->ifc_len -= space; 59011576Ssam return (error); 59111576Ssam } 59240792Ssklower 593*48453Skarels static char * 594*48453Skarels sprint_d(n, buf, buflen) 595*48453Skarels u_int n; 596*48453Skarels char *buf; 597*48453Skarels int buflen; 59840792Ssklower { 599*48453Skarels register char *cp = buf + buflen - 1; 600*48453Skarels 601*48453Skarels *cp = 0; 60240792Ssklower do { 603*48453Skarels cp--; 604*48453Skarels *cp = "0123456789"[n % 10]; 605*48453Skarels n /= 10; 606*48453Skarels } while (n != 0); 607*48453Skarels return (cp); 60840792Ssklower } 609