123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*54768Storek * @(#)if.c 7.21 (Berkeley) 07/07/92 823157Smckusick */ 94944Swnj 1017036Sbloom #include "param.h" 1133984Skarels #include "mbuf.h" 1217036Sbloom #include "systm.h" 1352514Smckusick #include "proc.h" 1417036Sbloom #include "socket.h" 1518544Skarels #include "socketvar.h" 1617036Sbloom #include "protosw.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; 28*54768Storek 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; 44*54768Storek 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 } 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 */ 28654718Ssklower void 28741923Ssklower link_rtrequest(cmd, rt, sa) 28852265Storek int cmd; 28952265Storek register struct rtentry *rt; 29052265Storek struct sockaddr *sa; 29141923Ssklower { 29241923Ssklower register struct ifaddr *ifa; 29341923Ssklower struct sockaddr *dst; 29441923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29541923Ssklower 29641923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29741923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29841923Ssklower return; 29943335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 30041923Ssklower rt->rt_ifa = ifa; 30141923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30241923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30343335Ssklower } 30441923Ssklower } 30541923Ssklower 30641923Ssklower /* 3076582Ssam * Mark an interface down and notify protocols of 3086582Ssam * the transition. 3099184Ssam * NOTE: must be called at splnet or eqivalent. 3106582Ssam */ 3116582Ssam if_down(ifp) 3126582Ssam register struct ifnet *ifp; 3136582Ssam { 31418544Skarels register struct ifaddr *ifa; 3158173Sroot 3166582Ssam ifp->if_flags &= ~IFF_UP; 31718544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31837549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 31933984Skarels if_qflush(&ifp->if_snd); 32052562Ssklower rt_ifmsg(ifp); 3216582Ssam } 3227264Ssam 3237264Ssam /* 32452562Ssklower * Mark an interface up and notify protocols of 32552562Ssklower * the transition. 32652562Ssklower * NOTE: must be called at splnet or eqivalent. 32752562Ssklower */ 32852562Ssklower if_up(ifp) 32952562Ssklower register struct ifnet *ifp; 33052562Ssklower { 33152562Ssklower register struct ifaddr *ifa; 33252562Ssklower 33352562Ssklower ifp->if_flags |= IFF_UP; 33452562Ssklower #ifdef notyet 33552562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 33652562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 33752562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 33852562Ssklower #endif notyet 33952562Ssklower rt_ifmsg(ifp); 34052562Ssklower } 34152562Ssklower 34252562Ssklower /* 34333984Skarels * Flush an interface queue. 34433984Skarels */ 34533984Skarels if_qflush(ifq) 34633984Skarels register struct ifqueue *ifq; 34733984Skarels { 34833984Skarels register struct mbuf *m, *n; 34933984Skarels 35033984Skarels n = ifq->ifq_head; 35133984Skarels while (m = n) { 35233984Skarels n = m->m_act; 35333984Skarels m_freem(m); 35433984Skarels } 35533984Skarels ifq->ifq_head = 0; 35633984Skarels ifq->ifq_tail = 0; 35733984Skarels ifq->ifq_len = 0; 35833984Skarels } 35933984Skarels 36033984Skarels /* 3617264Ssam * Handle interface watchdog timer routines. Called 3627264Ssam * from softclock, we decrement timers (if set) and 3637264Ssam * call the appropriate interface routine on expiration. 3647264Ssam */ 365*54768Storek void 366*54768Storek if_slowtimo(arg) 367*54768Storek void *arg; 3687264Ssam { 3697264Ssam register struct ifnet *ifp; 37037549Smckusick int s = splimp(); 3717264Ssam 3729184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3739184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3749184Ssam continue; 3759184Ssam if (ifp->if_watchdog) 3767264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3779184Ssam } 37837549Smckusick splx(s); 379*54768Storek timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 3807264Ssam } 38111576Ssam 38211576Ssam /* 38313049Ssam * Map interface name to 38413049Ssam * interface structure pointer. 38511576Ssam */ 38613049Ssam struct ifnet * 38713049Ssam ifunit(name) 38813049Ssam register char *name; 38911576Ssam { 39013049Ssam register char *cp; 39111576Ssam register struct ifnet *ifp; 39213049Ssam int unit; 39336821Skarels unsigned len; 39436821Skarels char *ep, c; 39511576Ssam 39613049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 39711576Ssam if (*cp >= '0' && *cp <= '9') 39811576Ssam break; 39913049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 40013049Ssam return ((struct ifnet *)0); 40136821Skarels /* 40236821Skarels * Save first char of unit, and pointer to it, 40336821Skarels * so we can put a null there to avoid matching 40436821Skarels * initial substrings of interface names. 40536821Skarels */ 40636821Skarels len = cp - name + 1; 40736821Skarels c = *cp; 40836821Skarels ep = cp; 40936821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 41036821Skarels unit = unit * 10 + *cp++ - '0'; 41136821Skarels *ep = 0; 41211576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 41336821Skarels if (bcmp(ifp->if_name, name, len)) 41411576Ssam continue; 41511576Ssam if (unit == ifp->if_unit) 41613049Ssam break; 41711576Ssam } 41836821Skarels *ep = c; 41913049Ssam return (ifp); 42013049Ssam } 42111576Ssam 42213049Ssam /* 42313049Ssam * Interface ioctls. 42413049Ssam */ 42548453Skarels ifioctl(so, cmd, data, p) 42618544Skarels struct socket *so; 42713049Ssam int cmd; 42813049Ssam caddr_t data; 42948453Skarels struct proc *p; 43013049Ssam { 43113049Ssam register struct ifnet *ifp; 43213049Ssam register struct ifreq *ifr; 43337549Smckusick int error; 43413049Ssam 43511576Ssam switch (cmd) { 43611576Ssam 43713049Ssam case SIOCGIFCONF: 43837549Smckusick case OSIOCGIFCONF: 43913049Ssam return (ifconf(cmd, data)); 44013049Ssam 44125647Skarels #if defined(INET) && NETHER > 0 44216220Skarels case SIOCSARP: 44316220Skarels case SIOCDARP: 44448453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44537549Smckusick return (error); 44616220Skarels /* FALL THROUGH */ 44716220Skarels case SIOCGARP: 44837549Smckusick case OSIOCGARP: 44916220Skarels return (arpioctl(cmd, data)); 45016220Skarels #endif 45113049Ssam } 45213049Ssam ifr = (struct ifreq *)data; 45313049Ssam ifp = ifunit(ifr->ifr_name); 45413049Ssam if (ifp == 0) 45513049Ssam return (ENXIO); 45613049Ssam switch (cmd) { 45713049Ssam 45811576Ssam case SIOCGIFFLAGS: 45911576Ssam ifr->ifr_flags = ifp->if_flags; 46011576Ssam break; 46111576Ssam 46226091Skarels case SIOCGIFMETRIC: 46326091Skarels ifr->ifr_metric = ifp->if_metric; 46426091Skarels break; 46526091Skarels 46613053Ssam case SIOCSIFFLAGS: 46748453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 46837549Smckusick return (error); 46913053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 47013053Ssam int s = splimp(); 47113053Ssam if_down(ifp); 47213053Ssam splx(s); 47313053Ssam } 47452562Ssklower if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 47552562Ssklower int s = splimp(); 47652562Ssklower if_up(ifp); 47752562Ssklower splx(s); 47852562Ssklower } 47918544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 48018544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 48124773Skarels if (ifp->if_ioctl) 48224773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 48313053Ssam break; 48413053Ssam 48526091Skarels case SIOCSIFMETRIC: 48648453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 48737549Smckusick return (error); 48826091Skarels ifp->if_metric = ifr->ifr_metric; 48926091Skarels break; 49026091Skarels 49154718Ssklower #ifdef MULTICAST 49254718Ssklower case SIOCADDMULTI: 49354718Ssklower case SIOCDELMULTI: 49454718Ssklower if (error = suser(p->p_ucred, &p->p_acflag)) 49554718Ssklower return (error); 49654718Ssklower if (ifp->if_ioctl) 49754718Ssklower return (EOPNOTSUPP); 49854718Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 49954718Ssklower #endif 50054718Ssklower 50111576Ssam default: 50218544Skarels if (so->so_proto == 0) 50313049Ssam return (EOPNOTSUPP); 50437549Smckusick #ifndef COMPAT_43 50518544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50618544Skarels cmd, data, ifp)); 50737549Smckusick #else 50837549Smckusick { 50941545Smckusick int ocmd = cmd; 51037549Smckusick 51137549Smckusick switch (cmd) { 51237549Smckusick 51337549Smckusick case SIOCSIFDSTADDR: 51437549Smckusick case SIOCSIFADDR: 51537549Smckusick case SIOCSIFBRDADDR: 51637549Smckusick case SIOCSIFNETMASK: 51737549Smckusick #if BYTE_ORDER != BIG_ENDIAN 51837549Smckusick if (ifr->ifr_addr.sa_family == 0 && 51937549Smckusick ifr->ifr_addr.sa_len < 16) { 52037549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 52137549Smckusick ifr->ifr_addr.sa_len = 16; 52237549Smckusick } 52337549Smckusick #else 52437549Smckusick if (ifr->ifr_addr.sa_len == 0) 52537549Smckusick ifr->ifr_addr.sa_len = 16; 52637549Smckusick #endif 52737549Smckusick break; 52837549Smckusick 52937549Smckusick case OSIOCGIFADDR: 53037549Smckusick cmd = SIOCGIFADDR; 53137549Smckusick break; 53237549Smckusick 53337549Smckusick case OSIOCGIFDSTADDR: 53437549Smckusick cmd = SIOCGIFDSTADDR; 53537549Smckusick break; 53637549Smckusick 53737549Smckusick case OSIOCGIFBRDADDR: 53837549Smckusick cmd = SIOCGIFBRDADDR; 53937549Smckusick break; 54037549Smckusick 54137549Smckusick case OSIOCGIFNETMASK: 54237549Smckusick cmd = SIOCGIFNETMASK; 54337549Smckusick } 54437549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 54537549Smckusick cmd, data, ifp)); 54637549Smckusick switch (ocmd) { 54737549Smckusick 54837549Smckusick case OSIOCGIFADDR: 54937549Smckusick case OSIOCGIFDSTADDR: 55037549Smckusick case OSIOCGIFBRDADDR: 55137549Smckusick case OSIOCGIFNETMASK: 55237549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 55337549Smckusick } 55437549Smckusick return (error); 55537549Smckusick 55637549Smckusick } 55737549Smckusick #endif 55811576Ssam } 55911576Ssam return (0); 56011576Ssam } 56111576Ssam 56211576Ssam /* 56311576Ssam * Return interface configuration 56411576Ssam * of system. List may be used 56511576Ssam * in later ioctl's (above) to get 56611576Ssam * other information. 56711576Ssam */ 56812783Ssam /*ARGSUSED*/ 56911576Ssam ifconf(cmd, data) 57011576Ssam int cmd; 57111576Ssam caddr_t data; 57211576Ssam { 57311576Ssam register struct ifconf *ifc = (struct ifconf *)data; 57411576Ssam register struct ifnet *ifp = ifnet; 57518544Skarels register struct ifaddr *ifa; 57611630Ssam register char *cp, *ep; 57711630Ssam struct ifreq ifr, *ifrp; 57811576Ssam int space = ifc->ifc_len, error = 0; 57911576Ssam 58011630Ssam ifrp = ifc->ifc_req; 58111630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 58211576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 58311630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 58411630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 58552914Storek continue; 58611630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 58718544Skarels if ((ifa = ifp->if_addrlist) == 0) { 58818544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 58918544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 59018544Skarels if (error) 59118544Skarels break; 59218544Skarels space -= sizeof (ifr), ifrp++; 59318544Skarels } else 59418544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 59537549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 59637549Smckusick #ifdef COMPAT_43 59737549Smckusick if (cmd == OSIOCGIFCONF) { 59837549Smckusick struct osockaddr *osa = 59937549Smckusick (struct osockaddr *)&ifr.ifr_addr; 60037549Smckusick ifr.ifr_addr = *sa; 60137549Smckusick osa->sa_family = sa->sa_family; 60237549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60337549Smckusick sizeof (ifr)); 60437549Smckusick ifrp++; 60537549Smckusick } else 60637549Smckusick #endif 60737549Smckusick if (sa->sa_len <= sizeof(*sa)) { 60837549Smckusick ifr.ifr_addr = *sa; 60937549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 61037549Smckusick sizeof (ifr)); 61137549Smckusick ifrp++; 61237549Smckusick } else { 61337549Smckusick space -= sa->sa_len - sizeof(*sa); 61437549Smckusick if (space < sizeof (ifr)) 61537549Smckusick break; 61637549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 61737549Smckusick sizeof (ifr.ifr_name)); 61837549Smckusick if (error == 0) 61937549Smckusick error = copyout((caddr_t)sa, 62037549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 62137549Smckusick ifrp = (struct ifreq *) 62237549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 62337549Smckusick } 62418544Skarels if (error) 62518544Skarels break; 62637549Smckusick space -= sizeof (ifr); 62718544Skarels } 62811576Ssam } 62911576Ssam ifc->ifc_len -= space; 63011576Ssam return (error); 63111576Ssam } 63240792Ssklower 63348453Skarels static char * 63448453Skarels sprint_d(n, buf, buflen) 63548453Skarels u_int n; 63648453Skarels char *buf; 63748453Skarels int buflen; 63840792Ssklower { 63948453Skarels register char *cp = buf + buflen - 1; 64048453Skarels 64148453Skarels *cp = 0; 64240792Ssklower do { 64348453Skarels cp--; 64448453Skarels *cp = "0123456789"[n % 10]; 64548453Skarels n /= 10; 64648453Skarels } while (n != 0); 64748453Skarels return (cp); 64840792Ssklower } 649