123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*52265Storek * @(#)if.c 7.15 (Berkeley) 01/29/92 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" 1648453Skarels #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; 6348453Skarels static char *sprint_d(); 6448453Skarels 656333Ssam /* 666333Ssam * Attach an interface to the 676333Ssam * list of "active" interfaces. 686333Ssam */ 69*52265Storek void 705160Swnj if_attach(ifp) 715160Swnj struct ifnet *ifp; 725160Swnj { 7340792Ssklower unsigned socksize, ifasize; 7440792Ssklower int namelen, unitlen; 7548453Skarels char workbuf[12], *unitname; 7643335Ssklower register struct ifnet **p = &ifnet; 7740792Ssklower register struct sockaddr_dl *sdl; 7840792Ssklower register struct ifaddr *ifa; 7943335Ssklower static int if_indexlim = 8; 8043335Ssklower extern link_rtrequest(), ether_output(); 815160Swnj 825698Swnj while (*p) 835698Swnj p = &((*p)->if_next); 845698Swnj *p = ifp; 8540792Ssklower ifp->if_index = ++if_index; 8643335Ssklower if (ifnet_addrs == 0 || if_index >= if_indexlim) { 8743335Ssklower unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 8843335Ssklower struct ifaddr **q = (struct ifaddr **) 8943335Ssklower malloc(n, M_IFADDR, M_WAITOK); 9043335Ssklower if (ifnet_addrs) { 9143335Ssklower bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 9243335Ssklower free((caddr_t)ifnet_addrs, M_IFADDR); 9343335Ssklower } 9443335Ssklower ifnet_addrs = q; 9543335Ssklower } 9643335Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 9743335Ssklower if (ifp->if_output == ether_output) { 9843335Ssklower ifp->if_type = IFT_ETHER; 9943335Ssklower ifp->if_addrlen = 6; 10043335Ssklower ifp->if_hdrlen = 14; 10143335Ssklower } 10241923Ssklower /* 10341923Ssklower * create a Link Level name for this device 10441923Ssklower */ 10548453Skarels unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 10640792Ssklower namelen = strlen(ifp->if_name); 10748453Skarels unitlen = strlen(unitname); 10840792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 10940792Ssklower socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 11040792Ssklower unitlen + namelen + ifp->if_addrlen; 11140792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 11240792Ssklower socksize = ROUNDUP(socksize); 11343335Ssklower if (socksize < sizeof(*sdl)) 11443335Ssklower socksize = sizeof(*sdl); 11540792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 11640792Ssklower ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 11740792Ssklower if (ifa == 0) 11840792Ssklower return; 11943335Ssklower ifnet_addrs[if_index - 1] = ifa; 12040792Ssklower bzero((caddr_t)ifa, ifasize); 12140792Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 12240792Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 12340792Ssklower ifa->ifa_ifp = ifp; 12440792Ssklower sdl->sdl_len = socksize; 12540792Ssklower sdl->sdl_family = AF_LINK; 12640792Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 12748453Skarels bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 12840792Ssklower sdl->sdl_nlen = (namelen += unitlen); 12940792Ssklower sdl->sdl_index = ifp->if_index; 13040792Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 13140792Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 13240792Ssklower sdl->sdl_len = socksize - ifp->if_addrlen; 13340792Ssklower while (namelen != 0) 13440792Ssklower sdl->sdl_data[--namelen] = 0xff; 13540792Ssklower ifa->ifa_next = ifp->if_addrlist; 13641923Ssklower ifa->ifa_rtrequest = link_rtrequest; 13740792Ssklower ifp->if_addrlist = ifa; 1385160Swnj } 1396333Ssam /* 1406333Ssam * Locate an interface based on a complete address. 1416333Ssam */ 1424951Swnj /*ARGSUSED*/ 14318544Skarels struct ifaddr * 14418544Skarels ifa_ifwithaddr(addr) 14537549Smckusick register struct sockaddr *addr; 1464944Swnj { 1474944Swnj register struct ifnet *ifp; 14818544Skarels register struct ifaddr *ifa; 1494944Swnj 1506333Ssam #define equal(a1, a2) \ 15137549Smckusick (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 15218544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 15318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 15437549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 1556333Ssam continue; 15637549Smckusick if (equal(addr, ifa->ifa_addr)) 15718544Skarels return (ifa); 15843335Ssklower if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 15943335Ssklower equal(ifa->ifa_broadaddr, addr)) 16018544Skarels return (ifa); 1616333Ssam } 16218544Skarels return ((struct ifaddr *)0); 1634944Swnj } 16423933Ssklower /* 16523933Ssklower * Locate the point to point interface with a given destination address. 16623933Ssklower */ 16723933Ssklower /*ARGSUSED*/ 16823933Ssklower struct ifaddr * 16923933Ssklower ifa_ifwithdstaddr(addr) 17037549Smckusick register struct sockaddr *addr; 17123933Ssklower { 17223933Ssklower register struct ifnet *ifp; 17323933Ssklower register struct ifaddr *ifa; 1744944Swnj 17523933Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) 17623933Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 17723933Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 17837549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 17923933Ssklower continue; 18037549Smckusick if (equal(addr, ifa->ifa_dstaddr)) 18123933Ssklower return (ifa); 18223933Ssklower } 18323933Ssklower return ((struct ifaddr *)0); 18423933Ssklower } 18523933Ssklower 1866333Ssam /* 1876333Ssam * Find an interface on a specific network. If many, choice 1886333Ssam * is first found. 1896333Ssam */ 19018544Skarels struct ifaddr * 19118544Skarels ifa_ifwithnet(addr) 19237549Smckusick struct sockaddr *addr; 1934944Swnj { 1944944Swnj register struct ifnet *ifp; 19518544Skarels register struct ifaddr *ifa; 19637549Smckusick u_int af = addr->sa_family; 1974944Swnj 1986619Ssam if (af >= AF_MAX) 1996619Ssam return (0); 20043335Ssklower if (af == AF_LINK) { 20143335Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 20243335Ssklower if (sdl->sdl_index && sdl->sdl_index <= if_index) 20343335Ssklower return (ifnet_addrs[sdl->sdl_index - 1]); 20443335Ssklower } 20518544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 20618544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 20743335Ssklower register char *cp, *cp2, *cp3; 20843335Ssklower register char *cplim; 20937549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 2106333Ssam continue; 21137549Smckusick cp = addr->sa_data; 21237549Smckusick cp2 = ifa->ifa_addr->sa_data; 21337549Smckusick cp3 = ifa->ifa_netmask->sa_data; 21437549Smckusick cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 21537549Smckusick for (; cp3 < cplim; cp3++) 21637549Smckusick if ((*cp++ ^ *cp2++) & *cp3) 21737549Smckusick break; 21837549Smckusick if (cp3 == cplim) 21918544Skarels return (ifa); 22037549Smckusick } 22118544Skarels return ((struct ifaddr *)0); 2226333Ssam } 2236333Ssam 2246333Ssam /* 2256333Ssam * Find an interface using a specific address family 2266333Ssam */ 22718544Skarels struct ifaddr * 22818544Skarels ifa_ifwithaf(af) 2296333Ssam register int af; 2305083Swnj { 2316333Ssam register struct ifnet *ifp; 23218544Skarels register struct ifaddr *ifa; 2335083Swnj 2346333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 23518544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 23637549Smckusick if (ifa->ifa_addr->sa_family == af) 23718544Skarels return (ifa); 23818544Skarels return ((struct ifaddr *)0); 2395083Swnj } 2405104Swnj 24143335Ssklower /* 24243335Ssklower * Find an interface address specific to an interface best matching 24343335Ssklower * a given address. 24443335Ssklower */ 24543335Ssklower struct ifaddr * 24643335Ssklower ifaof_ifpforaddr(addr, ifp) 24743335Ssklower struct sockaddr *addr; 24843335Ssklower register struct ifnet *ifp; 24943335Ssklower { 25043335Ssklower register struct ifaddr *ifa; 25143335Ssklower register char *cp, *cp2, *cp3; 25243335Ssklower register char *cplim; 25343335Ssklower struct ifaddr *ifa_maybe = 0; 25443335Ssklower u_int af = addr->sa_family; 25543335Ssklower 25643335Ssklower if (af >= AF_MAX) 25743335Ssklower return (0); 25843335Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 25943335Ssklower if (ifa->ifa_addr->sa_family != af) 26043335Ssklower continue; 26143335Ssklower ifa_maybe = ifa; 26243335Ssklower if (ifa->ifa_netmask == 0) { 26343335Ssklower if (equal(addr, ifa->ifa_addr) || 26443335Ssklower (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 26543335Ssklower return (ifa); 26643335Ssklower continue; 26743335Ssklower } 26843335Ssklower cp = addr->sa_data; 26943335Ssklower cp2 = ifa->ifa_addr->sa_data; 27043335Ssklower cp3 = ifa->ifa_netmask->sa_data; 27143335Ssklower cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 27243335Ssklower for (; cp3 < cplim; cp3++) 27343335Ssklower if ((*cp++ ^ *cp2++) & *cp3) 27443335Ssklower break; 27543335Ssklower if (cp3 == cplim) 27643335Ssklower return (ifa); 27743335Ssklower } 27843335Ssklower return (ifa_maybe); 27943335Ssklower } 28041923Ssklower #include "route.h" 2816333Ssam /* 28241923Ssklower * Default action when installing a route with a Link Level gateway. 28341923Ssklower * Lookup an appropriate real ifa to point to. 28441923Ssklower * This should be moved to /sys/net/link.c eventually. 28541923Ssklower */ 28641923Ssklower link_rtrequest(cmd, rt, sa) 287*52265Storek int cmd; 288*52265Storek register struct rtentry *rt; 289*52265Storek struct sockaddr *sa; 29041923Ssklower { 29141923Ssklower register struct ifaddr *ifa; 29241923Ssklower struct sockaddr *dst; 29341923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29441923Ssklower 29541923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29641923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29741923Ssklower return; 29843335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 29941923Ssklower rt->rt_ifa = ifa; 30041923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30141923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30243335Ssklower } 30341923Ssklower } 30441923Ssklower 30541923Ssklower /* 3066582Ssam * Mark an interface down and notify protocols of 3076582Ssam * the transition. 3089184Ssam * NOTE: must be called at splnet or eqivalent. 3096582Ssam */ 3106582Ssam if_down(ifp) 3116582Ssam register struct ifnet *ifp; 3126582Ssam { 31318544Skarels register struct ifaddr *ifa; 3148173Sroot 3156582Ssam ifp->if_flags &= ~IFF_UP; 31618544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31737549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 31833984Skarels if_qflush(&ifp->if_snd); 3196582Ssam } 3207264Ssam 3217264Ssam /* 32233984Skarels * Flush an interface queue. 32333984Skarels */ 32433984Skarels if_qflush(ifq) 32533984Skarels register struct ifqueue *ifq; 32633984Skarels { 32733984Skarels register struct mbuf *m, *n; 32833984Skarels 32933984Skarels n = ifq->ifq_head; 33033984Skarels while (m = n) { 33133984Skarels n = m->m_act; 33233984Skarels m_freem(m); 33333984Skarels } 33433984Skarels ifq->ifq_head = 0; 33533984Skarels ifq->ifq_tail = 0; 33633984Skarels ifq->ifq_len = 0; 33733984Skarels } 33833984Skarels 33933984Skarels /* 3407264Ssam * Handle interface watchdog timer routines. Called 3417264Ssam * from softclock, we decrement timers (if set) and 3427264Ssam * call the appropriate interface routine on expiration. 3437264Ssam */ 3447264Ssam if_slowtimo() 3457264Ssam { 3467264Ssam register struct ifnet *ifp; 34737549Smckusick int s = splimp(); 3487264Ssam 3499184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3509184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3519184Ssam continue; 3529184Ssam if (ifp->if_watchdog) 3537264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3549184Ssam } 35537549Smckusick splx(s); 3568692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3577264Ssam } 35811576Ssam 35911576Ssam /* 36013049Ssam * Map interface name to 36113049Ssam * interface structure pointer. 36211576Ssam */ 36313049Ssam struct ifnet * 36413049Ssam ifunit(name) 36513049Ssam register char *name; 36611576Ssam { 36713049Ssam register char *cp; 36811576Ssam register struct ifnet *ifp; 36913049Ssam int unit; 37036821Skarels unsigned len; 37136821Skarels char *ep, c; 37211576Ssam 37313049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 37411576Ssam if (*cp >= '0' && *cp <= '9') 37511576Ssam break; 37613049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 37713049Ssam return ((struct ifnet *)0); 37836821Skarels /* 37936821Skarels * Save first char of unit, and pointer to it, 38036821Skarels * so we can put a null there to avoid matching 38136821Skarels * initial substrings of interface names. 38236821Skarels */ 38336821Skarels len = cp - name + 1; 38436821Skarels c = *cp; 38536821Skarels ep = cp; 38636821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 38736821Skarels unit = unit * 10 + *cp++ - '0'; 38836821Skarels *ep = 0; 38911576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 39036821Skarels if (bcmp(ifp->if_name, name, len)) 39111576Ssam continue; 39211576Ssam if (unit == ifp->if_unit) 39313049Ssam break; 39411576Ssam } 39536821Skarels *ep = c; 39613049Ssam return (ifp); 39713049Ssam } 39811576Ssam 39913049Ssam /* 40013049Ssam * Interface ioctls. 40113049Ssam */ 40248453Skarels ifioctl(so, cmd, data, p) 40318544Skarels struct socket *so; 40413049Ssam int cmd; 40513049Ssam caddr_t data; 40648453Skarels struct proc *p; 40713049Ssam { 40813049Ssam register struct ifnet *ifp; 40913049Ssam register struct ifreq *ifr; 41037549Smckusick int error; 41113049Ssam 41211576Ssam switch (cmd) { 41311576Ssam 41413049Ssam case SIOCGIFCONF: 41537549Smckusick case OSIOCGIFCONF: 41613049Ssam return (ifconf(cmd, data)); 41713049Ssam 41825647Skarels #if defined(INET) && NETHER > 0 41916220Skarels case SIOCSARP: 42016220Skarels case SIOCDARP: 42148453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 42237549Smckusick return (error); 42316220Skarels /* FALL THROUGH */ 42416220Skarels case SIOCGARP: 42537549Smckusick case OSIOCGARP: 42616220Skarels return (arpioctl(cmd, data)); 42716220Skarels #endif 42813049Ssam } 42913049Ssam ifr = (struct ifreq *)data; 43013049Ssam ifp = ifunit(ifr->ifr_name); 43113049Ssam if (ifp == 0) 43213049Ssam return (ENXIO); 43313049Ssam switch (cmd) { 43413049Ssam 43511576Ssam case SIOCGIFFLAGS: 43611576Ssam ifr->ifr_flags = ifp->if_flags; 43711576Ssam break; 43811576Ssam 43926091Skarels case SIOCGIFMETRIC: 44026091Skarels ifr->ifr_metric = ifp->if_metric; 44126091Skarels break; 44226091Skarels 44313053Ssam case SIOCSIFFLAGS: 44448453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44537549Smckusick return (error); 44613053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 44713053Ssam int s = splimp(); 44813053Ssam if_down(ifp); 44913053Ssam splx(s); 45013053Ssam } 45118544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 45218544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 45324773Skarels if (ifp->if_ioctl) 45424773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 45513053Ssam break; 45613053Ssam 45726091Skarels case SIOCSIFMETRIC: 45848453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 45937549Smckusick return (error); 46026091Skarels ifp->if_metric = ifr->ifr_metric; 46126091Skarels break; 46226091Skarels 46311576Ssam default: 46418544Skarels if (so->so_proto == 0) 46513049Ssam return (EOPNOTSUPP); 46637549Smckusick #ifndef COMPAT_43 46718544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 46818544Skarels cmd, data, ifp)); 46937549Smckusick #else 47037549Smckusick { 47141545Smckusick int ocmd = cmd; 47237549Smckusick 47337549Smckusick switch (cmd) { 47437549Smckusick 47537549Smckusick case SIOCSIFDSTADDR: 47637549Smckusick case SIOCSIFADDR: 47737549Smckusick case SIOCSIFBRDADDR: 47837549Smckusick case SIOCSIFNETMASK: 47937549Smckusick #if BYTE_ORDER != BIG_ENDIAN 48037549Smckusick if (ifr->ifr_addr.sa_family == 0 && 48137549Smckusick ifr->ifr_addr.sa_len < 16) { 48237549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 48337549Smckusick ifr->ifr_addr.sa_len = 16; 48437549Smckusick } 48537549Smckusick #else 48637549Smckusick if (ifr->ifr_addr.sa_len == 0) 48737549Smckusick ifr->ifr_addr.sa_len = 16; 48837549Smckusick #endif 48937549Smckusick break; 49037549Smckusick 49137549Smckusick case OSIOCGIFADDR: 49237549Smckusick cmd = SIOCGIFADDR; 49337549Smckusick break; 49437549Smckusick 49537549Smckusick case OSIOCGIFDSTADDR: 49637549Smckusick cmd = SIOCGIFDSTADDR; 49737549Smckusick break; 49837549Smckusick 49937549Smckusick case OSIOCGIFBRDADDR: 50037549Smckusick cmd = SIOCGIFBRDADDR; 50137549Smckusick break; 50237549Smckusick 50337549Smckusick case OSIOCGIFNETMASK: 50437549Smckusick cmd = SIOCGIFNETMASK; 50537549Smckusick } 50637549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50737549Smckusick cmd, data, ifp)); 50837549Smckusick switch (ocmd) { 50937549Smckusick 51037549Smckusick case OSIOCGIFADDR: 51137549Smckusick case OSIOCGIFDSTADDR: 51237549Smckusick case OSIOCGIFBRDADDR: 51337549Smckusick case OSIOCGIFNETMASK: 51437549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 51537549Smckusick } 51637549Smckusick return (error); 51737549Smckusick 51837549Smckusick } 51937549Smckusick #endif 52011576Ssam } 52111576Ssam return (0); 52211576Ssam } 52311576Ssam 52411576Ssam /* 52511576Ssam * Return interface configuration 52611576Ssam * of system. List may be used 52711576Ssam * in later ioctl's (above) to get 52811576Ssam * other information. 52911576Ssam */ 53012783Ssam /*ARGSUSED*/ 53111576Ssam ifconf(cmd, data) 53211576Ssam int cmd; 53311576Ssam caddr_t data; 53411576Ssam { 53511576Ssam register struct ifconf *ifc = (struct ifconf *)data; 53611576Ssam register struct ifnet *ifp = ifnet; 53718544Skarels register struct ifaddr *ifa; 53811630Ssam register char *cp, *ep; 53911630Ssam struct ifreq ifr, *ifrp; 54011576Ssam int space = ifc->ifc_len, error = 0; 54111576Ssam 54211630Ssam ifrp = ifc->ifc_req; 54311630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 54411576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 54511630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 54611630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 54711576Ssam ; 54811630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 54918544Skarels if ((ifa = ifp->if_addrlist) == 0) { 55018544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 55118544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 55218544Skarels if (error) 55318544Skarels break; 55418544Skarels space -= sizeof (ifr), ifrp++; 55518544Skarels } else 55618544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 55737549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 55837549Smckusick #ifdef COMPAT_43 55937549Smckusick if (cmd == OSIOCGIFCONF) { 56037549Smckusick struct osockaddr *osa = 56137549Smckusick (struct osockaddr *)&ifr.ifr_addr; 56237549Smckusick ifr.ifr_addr = *sa; 56337549Smckusick osa->sa_family = sa->sa_family; 56437549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 56537549Smckusick sizeof (ifr)); 56637549Smckusick ifrp++; 56737549Smckusick } else 56837549Smckusick #endif 56937549Smckusick if (sa->sa_len <= sizeof(*sa)) { 57037549Smckusick ifr.ifr_addr = *sa; 57137549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57237549Smckusick sizeof (ifr)); 57337549Smckusick ifrp++; 57437549Smckusick } else { 57537549Smckusick space -= sa->sa_len - sizeof(*sa); 57637549Smckusick if (space < sizeof (ifr)) 57737549Smckusick break; 57837549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57937549Smckusick sizeof (ifr.ifr_name)); 58037549Smckusick if (error == 0) 58137549Smckusick error = copyout((caddr_t)sa, 58237549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 58337549Smckusick ifrp = (struct ifreq *) 58437549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 58537549Smckusick } 58618544Skarels if (error) 58718544Skarels break; 58837549Smckusick space -= sizeof (ifr); 58918544Skarels } 59011576Ssam } 59111576Ssam ifc->ifc_len -= space; 59211576Ssam return (error); 59311576Ssam } 59440792Ssklower 59548453Skarels static char * 59648453Skarels sprint_d(n, buf, buflen) 59748453Skarels u_int n; 59848453Skarels char *buf; 59948453Skarels int buflen; 60040792Ssklower { 60148453Skarels register char *cp = buf + buflen - 1; 60248453Skarels 60348453Skarels *cp = 0; 60440792Ssklower do { 60548453Skarels cp--; 60648453Skarels *cp = "0123456789"[n % 10]; 60748453Skarels n /= 10; 60848453Skarels } while (n != 0); 60948453Skarels return (cp); 61040792Ssklower } 611