123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*54718Ssklower * @(#)if.c 7.20 (Berkeley) 07/06/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; 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 */ 6952265Storek void 705160Swnj if_attach(ifp) 715160Swnj struct ifnet *ifp; 725160Swnj { 7340792Ssklower unsigned socksize, ifasize; 74*54718Ssklower int namelen, unitlen, masklen, ether_output(); 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; 80*54718Ssklower extern void link_rtrequest(); 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 } 9641923Ssklower /* 9741923Ssklower * create a Link Level name for this device 9841923Ssklower */ 9948453Skarels unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 10040792Ssklower namelen = strlen(ifp->if_name); 10148453Skarels unitlen = strlen(unitname); 10240792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 10352562Ssklower masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + 10452562Ssklower unitlen + namelen; 10552562Ssklower socksize = masklen + ifp->if_addrlen; 10640792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 10740792Ssklower socksize = ROUNDUP(socksize); 10843335Ssklower if (socksize < sizeof(*sdl)) 10943335Ssklower socksize = sizeof(*sdl); 11040792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 11152562Ssklower if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) { 11252562Ssklower bzero((caddr_t)ifa, ifasize); 11352562Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 11452562Ssklower sdl->sdl_len = socksize; 11552562Ssklower sdl->sdl_family = AF_LINK; 11652562Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 11752562Ssklower bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 11852562Ssklower sdl->sdl_nlen = (namelen += unitlen); 11952562Ssklower sdl->sdl_index = ifp->if_index; 12052562Ssklower sdl->sdl_type = ifp->if_type; 12152562Ssklower ifnet_addrs[if_index - 1] = ifa; 12252562Ssklower ifa->ifa_ifp = ifp; 12352562Ssklower ifa->ifa_next = ifp->if_addrlist; 12452562Ssklower ifa->ifa_rtrequest = link_rtrequest; 12552562Ssklower ifp->if_addrlist = ifa; 12652562Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 12752562Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 12852562Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 12952562Ssklower sdl->sdl_len = masklen; 13052562Ssklower while (namelen != 0) 13152562Ssklower sdl->sdl_data[--namelen] = 0xff; 13252562Ssklower } 13352562Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 13452562Ssklower if (ifp->if_output == ether_output) 13552562Ssklower ether_ifattach(ifp); 1365160Swnj } 1376333Ssam /* 1386333Ssam * Locate an interface based on a complete address. 1396333Ssam */ 1404951Swnj /*ARGSUSED*/ 14118544Skarels struct ifaddr * 14218544Skarels ifa_ifwithaddr(addr) 14337549Smckusick register struct sockaddr *addr; 1444944Swnj { 1454944Swnj register struct ifnet *ifp; 14618544Skarels register struct ifaddr *ifa; 1474944Swnj 1486333Ssam #define equal(a1, a2) \ 14937549Smckusick (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 15018544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 15118544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 15237549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 1536333Ssam continue; 15437549Smckusick if (equal(addr, ifa->ifa_addr)) 15518544Skarels return (ifa); 15643335Ssklower if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 15743335Ssklower equal(ifa->ifa_broadaddr, addr)) 15818544Skarels return (ifa); 1596333Ssam } 16018544Skarels return ((struct ifaddr *)0); 1614944Swnj } 16223933Ssklower /* 16323933Ssklower * Locate the point to point interface with a given destination address. 16423933Ssklower */ 16523933Ssklower /*ARGSUSED*/ 16623933Ssklower struct ifaddr * 16723933Ssklower ifa_ifwithdstaddr(addr) 16837549Smckusick register struct sockaddr *addr; 16923933Ssklower { 17023933Ssklower register struct ifnet *ifp; 17123933Ssklower register struct ifaddr *ifa; 1724944Swnj 17323933Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) 17423933Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 17523933Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 17637549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 17723933Ssklower continue; 17837549Smckusick if (equal(addr, ifa->ifa_dstaddr)) 17923933Ssklower return (ifa); 18023933Ssklower } 18123933Ssklower return ((struct ifaddr *)0); 18223933Ssklower } 18323933Ssklower 1846333Ssam /* 1856333Ssam * Find an interface on a specific network. If many, choice 18653454Ssklower * is most specific found. 1876333Ssam */ 18818544Skarels struct ifaddr * 18918544Skarels ifa_ifwithnet(addr) 19037549Smckusick struct sockaddr *addr; 1914944Swnj { 1924944Swnj register struct ifnet *ifp; 19318544Skarels register struct ifaddr *ifa; 19453454Ssklower struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 19537549Smckusick u_int af = addr->sa_family; 19653454Ssklower char *addr_data = addr->sa_data, *cplim; 1974944Swnj 19843335Ssklower if (af == AF_LINK) { 19943335Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 20043335Ssklower if (sdl->sdl_index && sdl->sdl_index <= if_index) 20143335Ssklower return (ifnet_addrs[sdl->sdl_index - 1]); 20243335Ssklower } 20318544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 20418544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 20543335Ssklower register char *cp, *cp2, *cp3; 20653454Ssklower 20737549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 20853454Ssklower next: continue; 20953454Ssklower cp = addr_data; 21037549Smckusick cp2 = ifa->ifa_addr->sa_data; 21137549Smckusick cp3 = ifa->ifa_netmask->sa_data; 21237549Smckusick cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 21353454Ssklower while (cp3 < cplim) 21453454Ssklower if ((*cp++ ^ *cp2++) & *cp3++) 21553454Ssklower goto next; 21653454Ssklower if (ifa_maybe == 0 || 21753454Ssklower rn_refines(ifa->ifa_netmask, ifa_maybe->ifa_netmask)) 21853454Ssklower ifa_maybe = ifa; 21937549Smckusick } 22053454Ssklower return (ifa_maybe); 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 */ 285*54718Ssklower void 28641923Ssklower link_rtrequest(cmd, rt, sa) 28752265Storek int cmd; 28852265Storek register struct rtentry *rt; 28952265Storek 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); 31952562Ssklower rt_ifmsg(ifp); 3206582Ssam } 3217264Ssam 3227264Ssam /* 32352562Ssklower * Mark an interface up and notify protocols of 32452562Ssklower * the transition. 32552562Ssklower * NOTE: must be called at splnet or eqivalent. 32652562Ssklower */ 32752562Ssklower if_up(ifp) 32852562Ssklower register struct ifnet *ifp; 32952562Ssklower { 33052562Ssklower register struct ifaddr *ifa; 33152562Ssklower 33252562Ssklower ifp->if_flags |= IFF_UP; 33352562Ssklower #ifdef notyet 33452562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 33552562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 33652562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 33752562Ssklower #endif notyet 33852562Ssklower rt_ifmsg(ifp); 33952562Ssklower } 34052562Ssklower 34152562Ssklower /* 34233984Skarels * Flush an interface queue. 34333984Skarels */ 34433984Skarels if_qflush(ifq) 34533984Skarels register struct ifqueue *ifq; 34633984Skarels { 34733984Skarels register struct mbuf *m, *n; 34833984Skarels 34933984Skarels n = ifq->ifq_head; 35033984Skarels while (m = n) { 35133984Skarels n = m->m_act; 35233984Skarels m_freem(m); 35333984Skarels } 35433984Skarels ifq->ifq_head = 0; 35533984Skarels ifq->ifq_tail = 0; 35633984Skarels ifq->ifq_len = 0; 35733984Skarels } 35833984Skarels 35933984Skarels /* 3607264Ssam * Handle interface watchdog timer routines. Called 3617264Ssam * from softclock, we decrement timers (if set) and 3627264Ssam * call the appropriate interface routine on expiration. 3637264Ssam */ 3647264Ssam if_slowtimo() 3657264Ssam { 3667264Ssam register struct ifnet *ifp; 36737549Smckusick int s = splimp(); 3687264Ssam 3699184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3709184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3719184Ssam continue; 3729184Ssam if (ifp->if_watchdog) 3737264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3749184Ssam } 37537549Smckusick splx(s); 3768692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3777264Ssam } 37811576Ssam 37911576Ssam /* 38013049Ssam * Map interface name to 38113049Ssam * interface structure pointer. 38211576Ssam */ 38313049Ssam struct ifnet * 38413049Ssam ifunit(name) 38513049Ssam register char *name; 38611576Ssam { 38713049Ssam register char *cp; 38811576Ssam register struct ifnet *ifp; 38913049Ssam int unit; 39036821Skarels unsigned len; 39136821Skarels char *ep, c; 39211576Ssam 39313049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 39411576Ssam if (*cp >= '0' && *cp <= '9') 39511576Ssam break; 39613049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 39713049Ssam return ((struct ifnet *)0); 39836821Skarels /* 39936821Skarels * Save first char of unit, and pointer to it, 40036821Skarels * so we can put a null there to avoid matching 40136821Skarels * initial substrings of interface names. 40236821Skarels */ 40336821Skarels len = cp - name + 1; 40436821Skarels c = *cp; 40536821Skarels ep = cp; 40636821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 40736821Skarels unit = unit * 10 + *cp++ - '0'; 40836821Skarels *ep = 0; 40911576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 41036821Skarels if (bcmp(ifp->if_name, name, len)) 41111576Ssam continue; 41211576Ssam if (unit == ifp->if_unit) 41313049Ssam break; 41411576Ssam } 41536821Skarels *ep = c; 41613049Ssam return (ifp); 41713049Ssam } 41811576Ssam 41913049Ssam /* 42013049Ssam * Interface ioctls. 42113049Ssam */ 42248453Skarels ifioctl(so, cmd, data, p) 42318544Skarels struct socket *so; 42413049Ssam int cmd; 42513049Ssam caddr_t data; 42648453Skarels struct proc *p; 42713049Ssam { 42813049Ssam register struct ifnet *ifp; 42913049Ssam register struct ifreq *ifr; 43037549Smckusick int error; 43113049Ssam 43211576Ssam switch (cmd) { 43311576Ssam 43413049Ssam case SIOCGIFCONF: 43537549Smckusick case OSIOCGIFCONF: 43613049Ssam return (ifconf(cmd, data)); 43713049Ssam 43825647Skarels #if defined(INET) && NETHER > 0 43916220Skarels case SIOCSARP: 44016220Skarels case SIOCDARP: 44148453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44237549Smckusick return (error); 44316220Skarels /* FALL THROUGH */ 44416220Skarels case SIOCGARP: 44537549Smckusick case OSIOCGARP: 44616220Skarels return (arpioctl(cmd, data)); 44716220Skarels #endif 44813049Ssam } 44913049Ssam ifr = (struct ifreq *)data; 45013049Ssam ifp = ifunit(ifr->ifr_name); 45113049Ssam if (ifp == 0) 45213049Ssam return (ENXIO); 45313049Ssam switch (cmd) { 45413049Ssam 45511576Ssam case SIOCGIFFLAGS: 45611576Ssam ifr->ifr_flags = ifp->if_flags; 45711576Ssam break; 45811576Ssam 45926091Skarels case SIOCGIFMETRIC: 46026091Skarels ifr->ifr_metric = ifp->if_metric; 46126091Skarels break; 46226091Skarels 46313053Ssam case SIOCSIFFLAGS: 46448453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 46537549Smckusick return (error); 46613053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 46713053Ssam int s = splimp(); 46813053Ssam if_down(ifp); 46913053Ssam splx(s); 47013053Ssam } 47152562Ssklower if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 47252562Ssklower int s = splimp(); 47352562Ssklower if_up(ifp); 47452562Ssklower splx(s); 47552562Ssklower } 47618544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 47718544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 47824773Skarels if (ifp->if_ioctl) 47924773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 48013053Ssam break; 48113053Ssam 48226091Skarels case SIOCSIFMETRIC: 48348453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 48437549Smckusick return (error); 48526091Skarels ifp->if_metric = ifr->ifr_metric; 48626091Skarels break; 48726091Skarels 488*54718Ssklower #ifdef MULTICAST 489*54718Ssklower case SIOCADDMULTI: 490*54718Ssklower case SIOCDELMULTI: 491*54718Ssklower if (error = suser(p->p_ucred, &p->p_acflag)) 492*54718Ssklower return (error); 493*54718Ssklower if (ifp->if_ioctl) 494*54718Ssklower return (EOPNOTSUPP); 495*54718Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 496*54718Ssklower #endif 497*54718Ssklower 49811576Ssam default: 49918544Skarels if (so->so_proto == 0) 50013049Ssam return (EOPNOTSUPP); 50137549Smckusick #ifndef COMPAT_43 50218544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50318544Skarels cmd, data, ifp)); 50437549Smckusick #else 50537549Smckusick { 50641545Smckusick int ocmd = cmd; 50737549Smckusick 50837549Smckusick switch (cmd) { 50937549Smckusick 51037549Smckusick case SIOCSIFDSTADDR: 51137549Smckusick case SIOCSIFADDR: 51237549Smckusick case SIOCSIFBRDADDR: 51337549Smckusick case SIOCSIFNETMASK: 51437549Smckusick #if BYTE_ORDER != BIG_ENDIAN 51537549Smckusick if (ifr->ifr_addr.sa_family == 0 && 51637549Smckusick ifr->ifr_addr.sa_len < 16) { 51737549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 51837549Smckusick ifr->ifr_addr.sa_len = 16; 51937549Smckusick } 52037549Smckusick #else 52137549Smckusick if (ifr->ifr_addr.sa_len == 0) 52237549Smckusick ifr->ifr_addr.sa_len = 16; 52337549Smckusick #endif 52437549Smckusick break; 52537549Smckusick 52637549Smckusick case OSIOCGIFADDR: 52737549Smckusick cmd = SIOCGIFADDR; 52837549Smckusick break; 52937549Smckusick 53037549Smckusick case OSIOCGIFDSTADDR: 53137549Smckusick cmd = SIOCGIFDSTADDR; 53237549Smckusick break; 53337549Smckusick 53437549Smckusick case OSIOCGIFBRDADDR: 53537549Smckusick cmd = SIOCGIFBRDADDR; 53637549Smckusick break; 53737549Smckusick 53837549Smckusick case OSIOCGIFNETMASK: 53937549Smckusick cmd = SIOCGIFNETMASK; 54037549Smckusick } 54137549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 54237549Smckusick cmd, data, ifp)); 54337549Smckusick switch (ocmd) { 54437549Smckusick 54537549Smckusick case OSIOCGIFADDR: 54637549Smckusick case OSIOCGIFDSTADDR: 54737549Smckusick case OSIOCGIFBRDADDR: 54837549Smckusick case OSIOCGIFNETMASK: 54937549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 55037549Smckusick } 55137549Smckusick return (error); 55237549Smckusick 55337549Smckusick } 55437549Smckusick #endif 55511576Ssam } 55611576Ssam return (0); 55711576Ssam } 55811576Ssam 55911576Ssam /* 56011576Ssam * Return interface configuration 56111576Ssam * of system. List may be used 56211576Ssam * in later ioctl's (above) to get 56311576Ssam * other information. 56411576Ssam */ 56512783Ssam /*ARGSUSED*/ 56611576Ssam ifconf(cmd, data) 56711576Ssam int cmd; 56811576Ssam caddr_t data; 56911576Ssam { 57011576Ssam register struct ifconf *ifc = (struct ifconf *)data; 57111576Ssam register struct ifnet *ifp = ifnet; 57218544Skarels register struct ifaddr *ifa; 57311630Ssam register char *cp, *ep; 57411630Ssam struct ifreq ifr, *ifrp; 57511576Ssam int space = ifc->ifc_len, error = 0; 57611576Ssam 57711630Ssam ifrp = ifc->ifc_req; 57811630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 57911576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 58011630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 58111630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 58252914Storek continue; 58311630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 58418544Skarels if ((ifa = ifp->if_addrlist) == 0) { 58518544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 58618544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 58718544Skarels if (error) 58818544Skarels break; 58918544Skarels space -= sizeof (ifr), ifrp++; 59018544Skarels } else 59118544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 59237549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 59337549Smckusick #ifdef COMPAT_43 59437549Smckusick if (cmd == OSIOCGIFCONF) { 59537549Smckusick struct osockaddr *osa = 59637549Smckusick (struct osockaddr *)&ifr.ifr_addr; 59737549Smckusick ifr.ifr_addr = *sa; 59837549Smckusick osa->sa_family = sa->sa_family; 59937549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60037549Smckusick sizeof (ifr)); 60137549Smckusick ifrp++; 60237549Smckusick } else 60337549Smckusick #endif 60437549Smckusick if (sa->sa_len <= sizeof(*sa)) { 60537549Smckusick ifr.ifr_addr = *sa; 60637549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60737549Smckusick sizeof (ifr)); 60837549Smckusick ifrp++; 60937549Smckusick } else { 61037549Smckusick space -= sa->sa_len - sizeof(*sa); 61137549Smckusick if (space < sizeof (ifr)) 61237549Smckusick break; 61337549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 61437549Smckusick sizeof (ifr.ifr_name)); 61537549Smckusick if (error == 0) 61637549Smckusick error = copyout((caddr_t)sa, 61737549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 61837549Smckusick ifrp = (struct ifreq *) 61937549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 62037549Smckusick } 62118544Skarels if (error) 62218544Skarels break; 62337549Smckusick space -= sizeof (ifr); 62418544Skarels } 62511576Ssam } 62611576Ssam ifc->ifc_len -= space; 62711576Ssam return (error); 62811576Ssam } 62940792Ssklower 63048453Skarels static char * 63148453Skarels sprint_d(n, buf, buflen) 63248453Skarels u_int n; 63348453Skarels char *buf; 63448453Skarels int buflen; 63540792Ssklower { 63648453Skarels register char *cp = buf + buflen - 1; 63748453Skarels 63848453Skarels *cp = 0; 63940792Ssklower do { 64048453Skarels cp--; 64148453Skarels *cp = "0123456789"[n % 10]; 64248453Skarels n /= 10; 64348453Skarels } while (n != 0); 64448453Skarels return (cp); 64540792Ssklower } 646