123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*60346Storek * @(#)if.c 7.26 (Berkeley) 05/24/93 823157Smckusick */ 94944Swnj 1056529Sbostic #include <sys/param.h> 1156529Sbostic #include <sys/mbuf.h> 1256529Sbostic #include <sys/systm.h> 1356529Sbostic #include <sys/proc.h> 1456529Sbostic #include <sys/socket.h> 1556529Sbostic #include <sys/socketvar.h> 1656529Sbostic #include <sys/protosw.h> 1756529Sbostic #include <sys/kernel.h> 1856529Sbostic #include <sys/ioctl.h> 1910872Ssam 2056529Sbostic #include <net/if.h> 2156529Sbostic #include <net/af.h> 2256529Sbostic #include <net/if_dl.h> 2356529Sbostic #include <net/if_types.h> 244944Swnj 2516220Skarels #include "ether.h" 2616220Skarels 276207Swnj int ifqmaxlen = IFQ_MAXLEN; 2854768Storek void if_slowtimo __P((void *arg)); 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; 4454768Storek if_slowtimo(0); 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; 6448453Skarels static char *sprint_d(); 6548453Skarels 666333Ssam /* 676333Ssam * Attach an interface to the 686333Ssam * list of "active" interfaces. 696333Ssam */ 7052265Storek void 715160Swnj if_attach(ifp) 725160Swnj struct ifnet *ifp; 735160Swnj { 7440792Ssklower unsigned socksize, ifasize; 7554718Ssklower int namelen, unitlen, masklen, ether_output(); 7648453Skarels char workbuf[12], *unitname; 7743335Ssklower register struct ifnet **p = &ifnet; 7840792Ssklower register struct sockaddr_dl *sdl; 7940792Ssklower register struct ifaddr *ifa; 8043335Ssklower static int if_indexlim = 8; 8154718Ssklower extern void link_rtrequest(); 825160Swnj 835698Swnj while (*p) 845698Swnj p = &((*p)->if_next); 855698Swnj *p = ifp; 8640792Ssklower ifp->if_index = ++if_index; 8743335Ssklower if (ifnet_addrs == 0 || if_index >= if_indexlim) { 8843335Ssklower unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 8943335Ssklower struct ifaddr **q = (struct ifaddr **) 9043335Ssklower malloc(n, M_IFADDR, M_WAITOK); 9143335Ssklower if (ifnet_addrs) { 9243335Ssklower bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 9343335Ssklower free((caddr_t)ifnet_addrs, M_IFADDR); 9443335Ssklower } 9543335Ssklower ifnet_addrs = q; 9643335Ssklower } 9741923Ssklower /* 9841923Ssklower * create a Link Level name for this device 9941923Ssklower */ 10048453Skarels unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 10140792Ssklower namelen = strlen(ifp->if_name); 10248453Skarels unitlen = strlen(unitname); 10340792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 10452562Ssklower masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + 10552562Ssklower unitlen + namelen; 10652562Ssklower socksize = masklen + ifp->if_addrlen; 10740792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 10840792Ssklower socksize = ROUNDUP(socksize); 10943335Ssklower if (socksize < sizeof(*sdl)) 11043335Ssklower socksize = sizeof(*sdl); 11140792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 11252562Ssklower if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) { 11352562Ssklower bzero((caddr_t)ifa, ifasize); 11452562Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 11552562Ssklower sdl->sdl_len = socksize; 11652562Ssklower sdl->sdl_family = AF_LINK; 11752562Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 11852562Ssklower bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 11952562Ssklower sdl->sdl_nlen = (namelen += unitlen); 12052562Ssklower sdl->sdl_index = ifp->if_index; 12152562Ssklower sdl->sdl_type = ifp->if_type; 12252562Ssklower ifnet_addrs[if_index - 1] = ifa; 12352562Ssklower ifa->ifa_ifp = ifp; 12452562Ssklower ifa->ifa_next = ifp->if_addrlist; 12552562Ssklower ifa->ifa_rtrequest = link_rtrequest; 12652562Ssklower ifp->if_addrlist = ifa; 12752562Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 12852562Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 12952562Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 13052562Ssklower sdl->sdl_len = masklen; 13152562Ssklower while (namelen != 0) 13252562Ssklower sdl->sdl_data[--namelen] = 0xff; 13352562Ssklower } 13452562Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 13552562Ssklower if (ifp->if_output == ether_output) 13652562Ssklower ether_ifattach(ifp); 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 18753454Ssklower * is most specific found. 1886333Ssam */ 18918544Skarels struct ifaddr * 19018544Skarels ifa_ifwithnet(addr) 19137549Smckusick struct sockaddr *addr; 1924944Swnj { 1934944Swnj register struct ifnet *ifp; 19418544Skarels register struct ifaddr *ifa; 19553454Ssklower struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 19637549Smckusick u_int af = addr->sa_family; 19753454Ssklower char *addr_data = addr->sa_data, *cplim; 1984944Swnj 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; 20753454Ssklower 20837549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 20953454Ssklower next: continue; 21053454Ssklower cp = addr_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; 21453454Ssklower while (cp3 < cplim) 21553454Ssklower if ((*cp++ ^ *cp2++) & *cp3++) 21653454Ssklower goto next; 21753454Ssklower if (ifa_maybe == 0 || 21853454Ssklower rn_refines(ifa->ifa_netmask, ifa_maybe->ifa_netmask)) 21953454Ssklower ifa_maybe = ifa; 22037549Smckusick } 22153454Ssklower return (ifa_maybe); 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 } 28056529Sbostic 28156529Sbostic #include <net/route.h> 28256529Sbostic 2836333Ssam /* 28441923Ssklower * Default action when installing a route with a Link Level gateway. 28541923Ssklower * Lookup an appropriate real ifa to point to. 28641923Ssklower * This should be moved to /sys/net/link.c eventually. 28741923Ssklower */ 28854718Ssklower void 28941923Ssklower link_rtrequest(cmd, rt, sa) 29052265Storek int cmd; 29152265Storek register struct rtentry *rt; 29252265Storek struct sockaddr *sa; 29341923Ssklower { 29441923Ssklower register struct ifaddr *ifa; 29541923Ssklower struct sockaddr *dst; 29641923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29741923Ssklower 29841923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29941923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 30041923Ssklower return; 30143335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 30259063Ssklower IFAFREE(rt->rt_ifa); 30341923Ssklower rt->rt_ifa = ifa; 30459063Ssklower ifa->ifa_refcnt++; 30541923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30641923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30743335Ssklower } 30841923Ssklower } 30941923Ssklower 31041923Ssklower /* 3116582Ssam * Mark an interface down and notify protocols of 3126582Ssam * the transition. 3139184Ssam * NOTE: must be called at splnet or eqivalent. 3146582Ssam */ 3156582Ssam if_down(ifp) 3166582Ssam register struct ifnet *ifp; 3176582Ssam { 31818544Skarels register struct ifaddr *ifa; 3198173Sroot 3206582Ssam ifp->if_flags &= ~IFF_UP; 32118544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 32237549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 32333984Skarels if_qflush(&ifp->if_snd); 32452562Ssklower rt_ifmsg(ifp); 3256582Ssam } 3267264Ssam 3277264Ssam /* 32852562Ssklower * Mark an interface up and notify protocols of 32952562Ssklower * the transition. 33052562Ssklower * NOTE: must be called at splnet or eqivalent. 33152562Ssklower */ 33252562Ssklower if_up(ifp) 33352562Ssklower register struct ifnet *ifp; 33452562Ssklower { 33552562Ssklower register struct ifaddr *ifa; 33652562Ssklower 33752562Ssklower ifp->if_flags |= IFF_UP; 33852562Ssklower #ifdef notyet 33952562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 34052562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 34152562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 342*60346Storek #endif 34352562Ssklower rt_ifmsg(ifp); 34452562Ssklower } 34552562Ssklower 34652562Ssklower /* 34733984Skarels * Flush an interface queue. 34833984Skarels */ 34933984Skarels if_qflush(ifq) 35033984Skarels register struct ifqueue *ifq; 35133984Skarels { 35233984Skarels register struct mbuf *m, *n; 35333984Skarels 35433984Skarels n = ifq->ifq_head; 35533984Skarels while (m = n) { 35633984Skarels n = m->m_act; 35733984Skarels m_freem(m); 35833984Skarels } 35933984Skarels ifq->ifq_head = 0; 36033984Skarels ifq->ifq_tail = 0; 36133984Skarels ifq->ifq_len = 0; 36233984Skarels } 36333984Skarels 36433984Skarels /* 3657264Ssam * Handle interface watchdog timer routines. Called 3667264Ssam * from softclock, we decrement timers (if set) and 3677264Ssam * call the appropriate interface routine on expiration. 3687264Ssam */ 36954768Storek void 37054768Storek if_slowtimo(arg) 37154768Storek void *arg; 3727264Ssam { 3737264Ssam register struct ifnet *ifp; 37437549Smckusick int s = splimp(); 3757264Ssam 3769184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3779184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3789184Ssam continue; 3799184Ssam if (ifp->if_watchdog) 3807264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3819184Ssam } 38237549Smckusick splx(s); 38354768Storek timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 3847264Ssam } 38511576Ssam 38611576Ssam /* 38713049Ssam * Map interface name to 38813049Ssam * interface structure pointer. 38911576Ssam */ 39013049Ssam struct ifnet * 39113049Ssam ifunit(name) 39213049Ssam register char *name; 39311576Ssam { 39413049Ssam register char *cp; 39511576Ssam register struct ifnet *ifp; 39613049Ssam int unit; 39736821Skarels unsigned len; 39836821Skarels char *ep, c; 39911576Ssam 40013049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 40111576Ssam if (*cp >= '0' && *cp <= '9') 40211576Ssam break; 40313049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 40413049Ssam return ((struct ifnet *)0); 40536821Skarels /* 40636821Skarels * Save first char of unit, and pointer to it, 40736821Skarels * so we can put a null there to avoid matching 40836821Skarels * initial substrings of interface names. 40936821Skarels */ 41036821Skarels len = cp - name + 1; 41136821Skarels c = *cp; 41236821Skarels ep = cp; 41336821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 41436821Skarels unit = unit * 10 + *cp++ - '0'; 41536821Skarels *ep = 0; 41611576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 41736821Skarels if (bcmp(ifp->if_name, name, len)) 41811576Ssam continue; 41911576Ssam if (unit == ifp->if_unit) 42013049Ssam break; 42111576Ssam } 42236821Skarels *ep = c; 42313049Ssam return (ifp); 42413049Ssam } 42511576Ssam 42613049Ssam /* 42713049Ssam * Interface ioctls. 42813049Ssam */ 42948453Skarels ifioctl(so, cmd, data, p) 43018544Skarels struct socket *so; 43113049Ssam int cmd; 43213049Ssam caddr_t data; 43348453Skarels struct proc *p; 43413049Ssam { 43513049Ssam register struct ifnet *ifp; 43613049Ssam register struct ifreq *ifr; 43737549Smckusick int error; 43813049Ssam 43911576Ssam switch (cmd) { 44011576Ssam 44113049Ssam case SIOCGIFCONF: 44237549Smckusick case OSIOCGIFCONF: 44313049Ssam return (ifconf(cmd, data)); 44413049Ssam 44525647Skarels #if defined(INET) && NETHER > 0 44616220Skarels case SIOCSARP: 44716220Skarels case SIOCDARP: 44848453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44937549Smckusick return (error); 45016220Skarels /* FALL THROUGH */ 45116220Skarels case SIOCGARP: 45237549Smckusick case OSIOCGARP: 45316220Skarels return (arpioctl(cmd, data)); 45416220Skarels #endif 45513049Ssam } 45613049Ssam ifr = (struct ifreq *)data; 45713049Ssam ifp = ifunit(ifr->ifr_name); 45813049Ssam if (ifp == 0) 45913049Ssam return (ENXIO); 46013049Ssam switch (cmd) { 46113049Ssam 46211576Ssam case SIOCGIFFLAGS: 46311576Ssam ifr->ifr_flags = ifp->if_flags; 46411576Ssam break; 46511576Ssam 46626091Skarels case SIOCGIFMETRIC: 46726091Skarels ifr->ifr_metric = ifp->if_metric; 46826091Skarels break; 46926091Skarels 47013053Ssam case SIOCSIFFLAGS: 47148453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 47237549Smckusick return (error); 47313053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 47413053Ssam int s = splimp(); 47513053Ssam if_down(ifp); 47613053Ssam splx(s); 47713053Ssam } 47852562Ssklower if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 47952562Ssklower int s = splimp(); 48052562Ssklower if_up(ifp); 48152562Ssklower splx(s); 48252562Ssklower } 48318544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 48418544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 48524773Skarels if (ifp->if_ioctl) 48624773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 48713053Ssam break; 48813053Ssam 48926091Skarels case SIOCSIFMETRIC: 49048453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 49137549Smckusick return (error); 49226091Skarels ifp->if_metric = ifr->ifr_metric; 49326091Skarels break; 49426091Skarels 49554718Ssklower case SIOCADDMULTI: 49654718Ssklower case SIOCDELMULTI: 49754718Ssklower if (error = suser(p->p_ucred, &p->p_acflag)) 49854718Ssklower return (error); 49958027Storek if (ifp->if_ioctl == NULL) 50054718Ssklower return (EOPNOTSUPP); 50154718Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 50254718Ssklower 50311576Ssam default: 50418544Skarels if (so->so_proto == 0) 50513049Ssam return (EOPNOTSUPP); 50637549Smckusick #ifndef COMPAT_43 50718544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50818544Skarels cmd, data, ifp)); 50937549Smckusick #else 51037549Smckusick { 51141545Smckusick int ocmd = cmd; 51237549Smckusick 51337549Smckusick switch (cmd) { 51437549Smckusick 51537549Smckusick case SIOCSIFDSTADDR: 51637549Smckusick case SIOCSIFADDR: 51737549Smckusick case SIOCSIFBRDADDR: 51837549Smckusick case SIOCSIFNETMASK: 51937549Smckusick #if BYTE_ORDER != BIG_ENDIAN 52037549Smckusick if (ifr->ifr_addr.sa_family == 0 && 52137549Smckusick ifr->ifr_addr.sa_len < 16) { 52237549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 52337549Smckusick ifr->ifr_addr.sa_len = 16; 52437549Smckusick } 52537549Smckusick #else 52637549Smckusick if (ifr->ifr_addr.sa_len == 0) 52737549Smckusick ifr->ifr_addr.sa_len = 16; 52837549Smckusick #endif 52937549Smckusick break; 53037549Smckusick 53137549Smckusick case OSIOCGIFADDR: 53237549Smckusick cmd = SIOCGIFADDR; 53337549Smckusick break; 53437549Smckusick 53537549Smckusick case OSIOCGIFDSTADDR: 53637549Smckusick cmd = SIOCGIFDSTADDR; 53737549Smckusick break; 53837549Smckusick 53937549Smckusick case OSIOCGIFBRDADDR: 54037549Smckusick cmd = SIOCGIFBRDADDR; 54137549Smckusick break; 54237549Smckusick 54337549Smckusick case OSIOCGIFNETMASK: 54437549Smckusick cmd = SIOCGIFNETMASK; 54537549Smckusick } 54637549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 54737549Smckusick cmd, data, ifp)); 54837549Smckusick switch (ocmd) { 54937549Smckusick 55037549Smckusick case OSIOCGIFADDR: 55137549Smckusick case OSIOCGIFDSTADDR: 55237549Smckusick case OSIOCGIFBRDADDR: 55337549Smckusick case OSIOCGIFNETMASK: 55437549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 55537549Smckusick } 55637549Smckusick return (error); 55737549Smckusick 55837549Smckusick } 55937549Smckusick #endif 56011576Ssam } 56111576Ssam return (0); 56211576Ssam } 56311576Ssam 56411576Ssam /* 56511576Ssam * Return interface configuration 56611576Ssam * of system. List may be used 56711576Ssam * in later ioctl's (above) to get 56811576Ssam * other information. 56911576Ssam */ 57012783Ssam /*ARGSUSED*/ 57111576Ssam ifconf(cmd, data) 57211576Ssam int cmd; 57311576Ssam caddr_t data; 57411576Ssam { 57511576Ssam register struct ifconf *ifc = (struct ifconf *)data; 57611576Ssam register struct ifnet *ifp = ifnet; 57718544Skarels register struct ifaddr *ifa; 57811630Ssam register char *cp, *ep; 57911630Ssam struct ifreq ifr, *ifrp; 58011576Ssam int space = ifc->ifc_len, error = 0; 58111576Ssam 58211630Ssam ifrp = ifc->ifc_req; 58311630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 58411576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 58511630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 58611630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 58752914Storek continue; 58811630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 58918544Skarels if ((ifa = ifp->if_addrlist) == 0) { 59018544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 59118544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 59218544Skarels if (error) 59318544Skarels break; 59418544Skarels space -= sizeof (ifr), ifrp++; 59518544Skarels } else 59618544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 59737549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 59837549Smckusick #ifdef COMPAT_43 59937549Smckusick if (cmd == OSIOCGIFCONF) { 60037549Smckusick struct osockaddr *osa = 60137549Smckusick (struct osockaddr *)&ifr.ifr_addr; 60237549Smckusick ifr.ifr_addr = *sa; 60337549Smckusick osa->sa_family = sa->sa_family; 60437549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60537549Smckusick sizeof (ifr)); 60637549Smckusick ifrp++; 60737549Smckusick } else 60837549Smckusick #endif 60937549Smckusick if (sa->sa_len <= sizeof(*sa)) { 61037549Smckusick ifr.ifr_addr = *sa; 61137549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 61237549Smckusick sizeof (ifr)); 61337549Smckusick ifrp++; 61437549Smckusick } else { 61537549Smckusick space -= sa->sa_len - sizeof(*sa); 61637549Smckusick if (space < sizeof (ifr)) 61737549Smckusick break; 61837549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 61937549Smckusick sizeof (ifr.ifr_name)); 62037549Smckusick if (error == 0) 62137549Smckusick error = copyout((caddr_t)sa, 62237549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 62337549Smckusick ifrp = (struct ifreq *) 62437549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 62537549Smckusick } 62618544Skarels if (error) 62718544Skarels break; 62837549Smckusick space -= sizeof (ifr); 62918544Skarels } 63011576Ssam } 63111576Ssam ifc->ifc_len -= space; 63211576Ssam return (error); 63311576Ssam } 63440792Ssklower 63548453Skarels static char * 63648453Skarels sprint_d(n, buf, buflen) 63748453Skarels u_int n; 63848453Skarels char *buf; 63948453Skarels int buflen; 64040792Ssklower { 64148453Skarels register char *cp = buf + buflen - 1; 64248453Skarels 64348453Skarels *cp = 0; 64440792Ssklower do { 64548453Skarels cp--; 64648453Skarels *cp = "0123456789"[n % 10]; 64748453Skarels n /= 10; 64848453Skarels } while (n != 0); 64948453Skarels return (cp); 65040792Ssklower } 651