123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*52914Storek * @(#)if.c 7.18 (Berkeley) 03/11/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; 7452562Ssklower int namelen, unitlen, masklen; 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 } 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 1866333Ssam * is first found. 1876333Ssam */ 18818544Skarels struct ifaddr * 18918544Skarels ifa_ifwithnet(addr) 19037549Smckusick struct sockaddr *addr; 1914944Swnj { 1924944Swnj register struct ifnet *ifp; 19318544Skarels register struct ifaddr *ifa; 19437549Smckusick u_int af = addr->sa_family; 1954944Swnj 1966619Ssam if (af >= AF_MAX) 1976619Ssam return (0); 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; 20643335Ssklower register char *cplim; 20737549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 2086333Ssam continue; 20937549Smckusick cp = addr->sa_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; 21337549Smckusick for (; cp3 < cplim; cp3++) 21437549Smckusick if ((*cp++ ^ *cp2++) & *cp3) 21537549Smckusick break; 21637549Smckusick if (cp3 == cplim) 21718544Skarels return (ifa); 21837549Smckusick } 21918544Skarels return ((struct ifaddr *)0); 2206333Ssam } 2216333Ssam 2226333Ssam /* 2236333Ssam * Find an interface using a specific address family 2246333Ssam */ 22518544Skarels struct ifaddr * 22618544Skarels ifa_ifwithaf(af) 2276333Ssam register int af; 2285083Swnj { 2296333Ssam register struct ifnet *ifp; 23018544Skarels register struct ifaddr *ifa; 2315083Swnj 2326333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 23318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 23437549Smckusick if (ifa->ifa_addr->sa_family == af) 23518544Skarels return (ifa); 23618544Skarels return ((struct ifaddr *)0); 2375083Swnj } 2385104Swnj 23943335Ssklower /* 24043335Ssklower * Find an interface address specific to an interface best matching 24143335Ssklower * a given address. 24243335Ssklower */ 24343335Ssklower struct ifaddr * 24443335Ssklower ifaof_ifpforaddr(addr, ifp) 24543335Ssklower struct sockaddr *addr; 24643335Ssklower register struct ifnet *ifp; 24743335Ssklower { 24843335Ssklower register struct ifaddr *ifa; 24943335Ssklower register char *cp, *cp2, *cp3; 25043335Ssklower register char *cplim; 25143335Ssklower struct ifaddr *ifa_maybe = 0; 25243335Ssklower u_int af = addr->sa_family; 25343335Ssklower 25443335Ssklower if (af >= AF_MAX) 25543335Ssklower return (0); 25643335Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 25743335Ssklower if (ifa->ifa_addr->sa_family != af) 25843335Ssklower continue; 25943335Ssklower ifa_maybe = ifa; 26043335Ssklower if (ifa->ifa_netmask == 0) { 26143335Ssklower if (equal(addr, ifa->ifa_addr) || 26243335Ssklower (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 26343335Ssklower return (ifa); 26443335Ssklower continue; 26543335Ssklower } 26643335Ssklower cp = addr->sa_data; 26743335Ssklower cp2 = ifa->ifa_addr->sa_data; 26843335Ssklower cp3 = ifa->ifa_netmask->sa_data; 26943335Ssklower cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 27043335Ssklower for (; cp3 < cplim; cp3++) 27143335Ssklower if ((*cp++ ^ *cp2++) & *cp3) 27243335Ssklower break; 27343335Ssklower if (cp3 == cplim) 27443335Ssklower return (ifa); 27543335Ssklower } 27643335Ssklower return (ifa_maybe); 27743335Ssklower } 27841923Ssklower #include "route.h" 2796333Ssam /* 28041923Ssklower * Default action when installing a route with a Link Level gateway. 28141923Ssklower * Lookup an appropriate real ifa to point to. 28241923Ssklower * This should be moved to /sys/net/link.c eventually. 28341923Ssklower */ 28441923Ssklower link_rtrequest(cmd, rt, sa) 28552265Storek int cmd; 28652265Storek register struct rtentry *rt; 28752265Storek struct sockaddr *sa; 28841923Ssklower { 28941923Ssklower register struct ifaddr *ifa; 29041923Ssklower struct sockaddr *dst; 29141923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29241923Ssklower 29341923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29441923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29541923Ssklower return; 29643335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 29741923Ssklower rt->rt_ifa = ifa; 29841923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 29941923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30043335Ssklower } 30141923Ssklower } 30241923Ssklower 30341923Ssklower /* 3046582Ssam * Mark an interface down and notify protocols of 3056582Ssam * the transition. 3069184Ssam * NOTE: must be called at splnet or eqivalent. 3076582Ssam */ 3086582Ssam if_down(ifp) 3096582Ssam register struct ifnet *ifp; 3106582Ssam { 31118544Skarels register struct ifaddr *ifa; 3128173Sroot 3136582Ssam ifp->if_flags &= ~IFF_UP; 31418544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31537549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 31633984Skarels if_qflush(&ifp->if_snd); 31752562Ssklower rt_ifmsg(ifp); 3186582Ssam } 3197264Ssam 3207264Ssam /* 32152562Ssklower * Mark an interface up and notify protocols of 32252562Ssklower * the transition. 32352562Ssklower * NOTE: must be called at splnet or eqivalent. 32452562Ssklower */ 32552562Ssklower if_up(ifp) 32652562Ssklower register struct ifnet *ifp; 32752562Ssklower { 32852562Ssklower register struct ifaddr *ifa; 32952562Ssklower 33052562Ssklower ifp->if_flags |= IFF_UP; 33152562Ssklower #ifdef notyet 33252562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 33352562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 33452562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 33552562Ssklower #endif notyet 33652562Ssklower rt_ifmsg(ifp); 33752562Ssklower } 33852562Ssklower 33952562Ssklower /* 34033984Skarels * Flush an interface queue. 34133984Skarels */ 34233984Skarels if_qflush(ifq) 34333984Skarels register struct ifqueue *ifq; 34433984Skarels { 34533984Skarels register struct mbuf *m, *n; 34633984Skarels 34733984Skarels n = ifq->ifq_head; 34833984Skarels while (m = n) { 34933984Skarels n = m->m_act; 35033984Skarels m_freem(m); 35133984Skarels } 35233984Skarels ifq->ifq_head = 0; 35333984Skarels ifq->ifq_tail = 0; 35433984Skarels ifq->ifq_len = 0; 35533984Skarels } 35633984Skarels 35733984Skarels /* 3587264Ssam * Handle interface watchdog timer routines. Called 3597264Ssam * from softclock, we decrement timers (if set) and 3607264Ssam * call the appropriate interface routine on expiration. 3617264Ssam */ 3627264Ssam if_slowtimo() 3637264Ssam { 3647264Ssam register struct ifnet *ifp; 36537549Smckusick int s = splimp(); 3667264Ssam 3679184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3689184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3699184Ssam continue; 3709184Ssam if (ifp->if_watchdog) 3717264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3729184Ssam } 37337549Smckusick splx(s); 3748692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3757264Ssam } 37611576Ssam 37711576Ssam /* 37813049Ssam * Map interface name to 37913049Ssam * interface structure pointer. 38011576Ssam */ 38113049Ssam struct ifnet * 38213049Ssam ifunit(name) 38313049Ssam register char *name; 38411576Ssam { 38513049Ssam register char *cp; 38611576Ssam register struct ifnet *ifp; 38713049Ssam int unit; 38836821Skarels unsigned len; 38936821Skarels char *ep, c; 39011576Ssam 39113049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 39211576Ssam if (*cp >= '0' && *cp <= '9') 39311576Ssam break; 39413049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 39513049Ssam return ((struct ifnet *)0); 39636821Skarels /* 39736821Skarels * Save first char of unit, and pointer to it, 39836821Skarels * so we can put a null there to avoid matching 39936821Skarels * initial substrings of interface names. 40036821Skarels */ 40136821Skarels len = cp - name + 1; 40236821Skarels c = *cp; 40336821Skarels ep = cp; 40436821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 40536821Skarels unit = unit * 10 + *cp++ - '0'; 40636821Skarels *ep = 0; 40711576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 40836821Skarels if (bcmp(ifp->if_name, name, len)) 40911576Ssam continue; 41011576Ssam if (unit == ifp->if_unit) 41113049Ssam break; 41211576Ssam } 41336821Skarels *ep = c; 41413049Ssam return (ifp); 41513049Ssam } 41611576Ssam 41713049Ssam /* 41813049Ssam * Interface ioctls. 41913049Ssam */ 42048453Skarels ifioctl(so, cmd, data, p) 42118544Skarels struct socket *so; 42213049Ssam int cmd; 42313049Ssam caddr_t data; 42448453Skarels struct proc *p; 42513049Ssam { 42613049Ssam register struct ifnet *ifp; 42713049Ssam register struct ifreq *ifr; 42837549Smckusick int error; 42913049Ssam 43011576Ssam switch (cmd) { 43111576Ssam 43213049Ssam case SIOCGIFCONF: 43337549Smckusick case OSIOCGIFCONF: 43413049Ssam return (ifconf(cmd, data)); 43513049Ssam 43625647Skarels #if defined(INET) && NETHER > 0 43716220Skarels case SIOCSARP: 43816220Skarels case SIOCDARP: 43948453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44037549Smckusick return (error); 44116220Skarels /* FALL THROUGH */ 44216220Skarels case SIOCGARP: 44337549Smckusick case OSIOCGARP: 44416220Skarels return (arpioctl(cmd, data)); 44516220Skarels #endif 44613049Ssam } 44713049Ssam ifr = (struct ifreq *)data; 44813049Ssam ifp = ifunit(ifr->ifr_name); 44913049Ssam if (ifp == 0) 45013049Ssam return (ENXIO); 45113049Ssam switch (cmd) { 45213049Ssam 45311576Ssam case SIOCGIFFLAGS: 45411576Ssam ifr->ifr_flags = ifp->if_flags; 45511576Ssam break; 45611576Ssam 45726091Skarels case SIOCGIFMETRIC: 45826091Skarels ifr->ifr_metric = ifp->if_metric; 45926091Skarels break; 46026091Skarels 46113053Ssam case SIOCSIFFLAGS: 46248453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 46337549Smckusick return (error); 46413053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 46513053Ssam int s = splimp(); 46613053Ssam if_down(ifp); 46713053Ssam splx(s); 46813053Ssam } 46952562Ssklower if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 47052562Ssklower int s = splimp(); 47152562Ssklower if_up(ifp); 47252562Ssklower splx(s); 47352562Ssklower } 47418544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 47518544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 47624773Skarels if (ifp->if_ioctl) 47724773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 47813053Ssam break; 47913053Ssam 48026091Skarels case SIOCSIFMETRIC: 48148453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 48237549Smckusick return (error); 48326091Skarels ifp->if_metric = ifr->ifr_metric; 48426091Skarels break; 48526091Skarels 48611576Ssam default: 48718544Skarels if (so->so_proto == 0) 48813049Ssam return (EOPNOTSUPP); 48937549Smckusick #ifndef COMPAT_43 49018544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 49118544Skarels cmd, data, ifp)); 49237549Smckusick #else 49337549Smckusick { 49441545Smckusick int ocmd = cmd; 49537549Smckusick 49637549Smckusick switch (cmd) { 49737549Smckusick 49837549Smckusick case SIOCSIFDSTADDR: 49937549Smckusick case SIOCSIFADDR: 50037549Smckusick case SIOCSIFBRDADDR: 50137549Smckusick case SIOCSIFNETMASK: 50237549Smckusick #if BYTE_ORDER != BIG_ENDIAN 50337549Smckusick if (ifr->ifr_addr.sa_family == 0 && 50437549Smckusick ifr->ifr_addr.sa_len < 16) { 50537549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 50637549Smckusick ifr->ifr_addr.sa_len = 16; 50737549Smckusick } 50837549Smckusick #else 50937549Smckusick if (ifr->ifr_addr.sa_len == 0) 51037549Smckusick ifr->ifr_addr.sa_len = 16; 51137549Smckusick #endif 51237549Smckusick break; 51337549Smckusick 51437549Smckusick case OSIOCGIFADDR: 51537549Smckusick cmd = SIOCGIFADDR; 51637549Smckusick break; 51737549Smckusick 51837549Smckusick case OSIOCGIFDSTADDR: 51937549Smckusick cmd = SIOCGIFDSTADDR; 52037549Smckusick break; 52137549Smckusick 52237549Smckusick case OSIOCGIFBRDADDR: 52337549Smckusick cmd = SIOCGIFBRDADDR; 52437549Smckusick break; 52537549Smckusick 52637549Smckusick case OSIOCGIFNETMASK: 52737549Smckusick cmd = SIOCGIFNETMASK; 52837549Smckusick } 52937549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 53037549Smckusick cmd, data, ifp)); 53137549Smckusick switch (ocmd) { 53237549Smckusick 53337549Smckusick case OSIOCGIFADDR: 53437549Smckusick case OSIOCGIFDSTADDR: 53537549Smckusick case OSIOCGIFBRDADDR: 53637549Smckusick case OSIOCGIFNETMASK: 53737549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 53837549Smckusick } 53937549Smckusick return (error); 54037549Smckusick 54137549Smckusick } 54237549Smckusick #endif 54311576Ssam } 54411576Ssam return (0); 54511576Ssam } 54611576Ssam 54711576Ssam /* 54811576Ssam * Return interface configuration 54911576Ssam * of system. List may be used 55011576Ssam * in later ioctl's (above) to get 55111576Ssam * other information. 55211576Ssam */ 55312783Ssam /*ARGSUSED*/ 55411576Ssam ifconf(cmd, data) 55511576Ssam int cmd; 55611576Ssam caddr_t data; 55711576Ssam { 55811576Ssam register struct ifconf *ifc = (struct ifconf *)data; 55911576Ssam register struct ifnet *ifp = ifnet; 56018544Skarels register struct ifaddr *ifa; 56111630Ssam register char *cp, *ep; 56211630Ssam struct ifreq ifr, *ifrp; 56311576Ssam int space = ifc->ifc_len, error = 0; 56411576Ssam 56511630Ssam ifrp = ifc->ifc_req; 56611630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 56711576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 56811630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 56911630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 570*52914Storek continue; 57111630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 57218544Skarels if ((ifa = ifp->if_addrlist) == 0) { 57318544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 57418544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 57518544Skarels if (error) 57618544Skarels break; 57718544Skarels space -= sizeof (ifr), ifrp++; 57818544Skarels } else 57918544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 58037549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 58137549Smckusick #ifdef COMPAT_43 58237549Smckusick if (cmd == OSIOCGIFCONF) { 58337549Smckusick struct osockaddr *osa = 58437549Smckusick (struct osockaddr *)&ifr.ifr_addr; 58537549Smckusick ifr.ifr_addr = *sa; 58637549Smckusick osa->sa_family = sa->sa_family; 58737549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 58837549Smckusick sizeof (ifr)); 58937549Smckusick ifrp++; 59037549Smckusick } else 59137549Smckusick #endif 59237549Smckusick if (sa->sa_len <= sizeof(*sa)) { 59337549Smckusick ifr.ifr_addr = *sa; 59437549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 59537549Smckusick sizeof (ifr)); 59637549Smckusick ifrp++; 59737549Smckusick } else { 59837549Smckusick space -= sa->sa_len - sizeof(*sa); 59937549Smckusick if (space < sizeof (ifr)) 60037549Smckusick break; 60137549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60237549Smckusick sizeof (ifr.ifr_name)); 60337549Smckusick if (error == 0) 60437549Smckusick error = copyout((caddr_t)sa, 60537549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 60637549Smckusick ifrp = (struct ifreq *) 60737549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 60837549Smckusick } 60918544Skarels if (error) 61018544Skarels break; 61137549Smckusick space -= sizeof (ifr); 61218544Skarels } 61311576Ssam } 61411576Ssam ifc->ifc_len -= space; 61511576Ssam return (error); 61611576Ssam } 61740792Ssklower 61848453Skarels static char * 61948453Skarels sprint_d(n, buf, buflen) 62048453Skarels u_int n; 62148453Skarels char *buf; 62248453Skarels int buflen; 62340792Ssklower { 62448453Skarels register char *cp = buf + buflen - 1; 62548453Skarels 62648453Skarels *cp = 0; 62740792Ssklower do { 62848453Skarels cp--; 62948453Skarels *cp = "0123456789"[n % 10]; 63048453Skarels n /= 10; 63148453Skarels } while (n != 0); 63248453Skarels return (cp); 63340792Ssklower } 634