123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*53454Ssklower * @(#)if.c 7.19 (Berkeley) 05/12/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 186*53454Ssklower * 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; 194*53454Ssklower struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 19537549Smckusick u_int af = addr->sa_family; 196*53454Ssklower 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; 206*53454Ssklower 20737549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 208*53454Ssklower next: continue; 209*53454Ssklower 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; 213*53454Ssklower while (cp3 < cplim) 214*53454Ssklower if ((*cp++ ^ *cp2++) & *cp3++) 215*53454Ssklower goto next; 216*53454Ssklower if (ifa_maybe == 0 || 217*53454Ssklower rn_refines(ifa->ifa_netmask, ifa_maybe->ifa_netmask)) 218*53454Ssklower ifa_maybe = ifa; 21937549Smckusick } 220*53454Ssklower 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 */ 28541923Ssklower link_rtrequest(cmd, rt, sa) 28652265Storek int cmd; 28752265Storek register struct rtentry *rt; 28852265Storek struct sockaddr *sa; 28941923Ssklower { 29041923Ssklower register struct ifaddr *ifa; 29141923Ssklower struct sockaddr *dst; 29241923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29341923Ssklower 29441923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29541923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29641923Ssklower return; 29743335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 29841923Ssklower rt->rt_ifa = ifa; 29941923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30041923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30143335Ssklower } 30241923Ssklower } 30341923Ssklower 30441923Ssklower /* 3056582Ssam * Mark an interface down and notify protocols of 3066582Ssam * the transition. 3079184Ssam * NOTE: must be called at splnet or eqivalent. 3086582Ssam */ 3096582Ssam if_down(ifp) 3106582Ssam register struct ifnet *ifp; 3116582Ssam { 31218544Skarels register struct ifaddr *ifa; 3138173Sroot 3146582Ssam ifp->if_flags &= ~IFF_UP; 31518544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 31637549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 31733984Skarels if_qflush(&ifp->if_snd); 31852562Ssklower rt_ifmsg(ifp); 3196582Ssam } 3207264Ssam 3217264Ssam /* 32252562Ssklower * Mark an interface up and notify protocols of 32352562Ssklower * the transition. 32452562Ssklower * NOTE: must be called at splnet or eqivalent. 32552562Ssklower */ 32652562Ssklower if_up(ifp) 32752562Ssklower register struct ifnet *ifp; 32852562Ssklower { 32952562Ssklower register struct ifaddr *ifa; 33052562Ssklower 33152562Ssklower ifp->if_flags |= IFF_UP; 33252562Ssklower #ifdef notyet 33352562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 33452562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 33552562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 33652562Ssklower #endif notyet 33752562Ssklower rt_ifmsg(ifp); 33852562Ssklower } 33952562Ssklower 34052562Ssklower /* 34133984Skarels * Flush an interface queue. 34233984Skarels */ 34333984Skarels if_qflush(ifq) 34433984Skarels register struct ifqueue *ifq; 34533984Skarels { 34633984Skarels register struct mbuf *m, *n; 34733984Skarels 34833984Skarels n = ifq->ifq_head; 34933984Skarels while (m = n) { 35033984Skarels n = m->m_act; 35133984Skarels m_freem(m); 35233984Skarels } 35333984Skarels ifq->ifq_head = 0; 35433984Skarels ifq->ifq_tail = 0; 35533984Skarels ifq->ifq_len = 0; 35633984Skarels } 35733984Skarels 35833984Skarels /* 3597264Ssam * Handle interface watchdog timer routines. Called 3607264Ssam * from softclock, we decrement timers (if set) and 3617264Ssam * call the appropriate interface routine on expiration. 3627264Ssam */ 3637264Ssam if_slowtimo() 3647264Ssam { 3657264Ssam register struct ifnet *ifp; 36637549Smckusick int s = splimp(); 3677264Ssam 3689184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3699184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3709184Ssam continue; 3719184Ssam if (ifp->if_watchdog) 3727264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3739184Ssam } 37437549Smckusick splx(s); 3758692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3767264Ssam } 37711576Ssam 37811576Ssam /* 37913049Ssam * Map interface name to 38013049Ssam * interface structure pointer. 38111576Ssam */ 38213049Ssam struct ifnet * 38313049Ssam ifunit(name) 38413049Ssam register char *name; 38511576Ssam { 38613049Ssam register char *cp; 38711576Ssam register struct ifnet *ifp; 38813049Ssam int unit; 38936821Skarels unsigned len; 39036821Skarels char *ep, c; 39111576Ssam 39213049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 39311576Ssam if (*cp >= '0' && *cp <= '9') 39411576Ssam break; 39513049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 39613049Ssam return ((struct ifnet *)0); 39736821Skarels /* 39836821Skarels * Save first char of unit, and pointer to it, 39936821Skarels * so we can put a null there to avoid matching 40036821Skarels * initial substrings of interface names. 40136821Skarels */ 40236821Skarels len = cp - name + 1; 40336821Skarels c = *cp; 40436821Skarels ep = cp; 40536821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 40636821Skarels unit = unit * 10 + *cp++ - '0'; 40736821Skarels *ep = 0; 40811576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 40936821Skarels if (bcmp(ifp->if_name, name, len)) 41011576Ssam continue; 41111576Ssam if (unit == ifp->if_unit) 41213049Ssam break; 41311576Ssam } 41436821Skarels *ep = c; 41513049Ssam return (ifp); 41613049Ssam } 41711576Ssam 41813049Ssam /* 41913049Ssam * Interface ioctls. 42013049Ssam */ 42148453Skarels ifioctl(so, cmd, data, p) 42218544Skarels struct socket *so; 42313049Ssam int cmd; 42413049Ssam caddr_t data; 42548453Skarels struct proc *p; 42613049Ssam { 42713049Ssam register struct ifnet *ifp; 42813049Ssam register struct ifreq *ifr; 42937549Smckusick int error; 43013049Ssam 43111576Ssam switch (cmd) { 43211576Ssam 43313049Ssam case SIOCGIFCONF: 43437549Smckusick case OSIOCGIFCONF: 43513049Ssam return (ifconf(cmd, data)); 43613049Ssam 43725647Skarels #if defined(INET) && NETHER > 0 43816220Skarels case SIOCSARP: 43916220Skarels case SIOCDARP: 44048453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 44137549Smckusick return (error); 44216220Skarels /* FALL THROUGH */ 44316220Skarels case SIOCGARP: 44437549Smckusick case OSIOCGARP: 44516220Skarels return (arpioctl(cmd, data)); 44616220Skarels #endif 44713049Ssam } 44813049Ssam ifr = (struct ifreq *)data; 44913049Ssam ifp = ifunit(ifr->ifr_name); 45013049Ssam if (ifp == 0) 45113049Ssam return (ENXIO); 45213049Ssam switch (cmd) { 45313049Ssam 45411576Ssam case SIOCGIFFLAGS: 45511576Ssam ifr->ifr_flags = ifp->if_flags; 45611576Ssam break; 45711576Ssam 45826091Skarels case SIOCGIFMETRIC: 45926091Skarels ifr->ifr_metric = ifp->if_metric; 46026091Skarels break; 46126091Skarels 46213053Ssam case SIOCSIFFLAGS: 46348453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 46437549Smckusick return (error); 46513053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 46613053Ssam int s = splimp(); 46713053Ssam if_down(ifp); 46813053Ssam splx(s); 46913053Ssam } 47052562Ssklower if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { 47152562Ssklower int s = splimp(); 47252562Ssklower if_up(ifp); 47352562Ssklower splx(s); 47452562Ssklower } 47518544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 47618544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 47724773Skarels if (ifp->if_ioctl) 47824773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 47913053Ssam break; 48013053Ssam 48126091Skarels case SIOCSIFMETRIC: 48248453Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 48337549Smckusick return (error); 48426091Skarels ifp->if_metric = ifr->ifr_metric; 48526091Skarels break; 48626091Skarels 48711576Ssam default: 48818544Skarels if (so->so_proto == 0) 48913049Ssam return (EOPNOTSUPP); 49037549Smckusick #ifndef COMPAT_43 49118544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 49218544Skarels cmd, data, ifp)); 49337549Smckusick #else 49437549Smckusick { 49541545Smckusick int ocmd = cmd; 49637549Smckusick 49737549Smckusick switch (cmd) { 49837549Smckusick 49937549Smckusick case SIOCSIFDSTADDR: 50037549Smckusick case SIOCSIFADDR: 50137549Smckusick case SIOCSIFBRDADDR: 50237549Smckusick case SIOCSIFNETMASK: 50337549Smckusick #if BYTE_ORDER != BIG_ENDIAN 50437549Smckusick if (ifr->ifr_addr.sa_family == 0 && 50537549Smckusick ifr->ifr_addr.sa_len < 16) { 50637549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 50737549Smckusick ifr->ifr_addr.sa_len = 16; 50837549Smckusick } 50937549Smckusick #else 51037549Smckusick if (ifr->ifr_addr.sa_len == 0) 51137549Smckusick ifr->ifr_addr.sa_len = 16; 51237549Smckusick #endif 51337549Smckusick break; 51437549Smckusick 51537549Smckusick case OSIOCGIFADDR: 51637549Smckusick cmd = SIOCGIFADDR; 51737549Smckusick break; 51837549Smckusick 51937549Smckusick case OSIOCGIFDSTADDR: 52037549Smckusick cmd = SIOCGIFDSTADDR; 52137549Smckusick break; 52237549Smckusick 52337549Smckusick case OSIOCGIFBRDADDR: 52437549Smckusick cmd = SIOCGIFBRDADDR; 52537549Smckusick break; 52637549Smckusick 52737549Smckusick case OSIOCGIFNETMASK: 52837549Smckusick cmd = SIOCGIFNETMASK; 52937549Smckusick } 53037549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 53137549Smckusick cmd, data, ifp)); 53237549Smckusick switch (ocmd) { 53337549Smckusick 53437549Smckusick case OSIOCGIFADDR: 53537549Smckusick case OSIOCGIFDSTADDR: 53637549Smckusick case OSIOCGIFBRDADDR: 53737549Smckusick case OSIOCGIFNETMASK: 53837549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 53937549Smckusick } 54037549Smckusick return (error); 54137549Smckusick 54237549Smckusick } 54337549Smckusick #endif 54411576Ssam } 54511576Ssam return (0); 54611576Ssam } 54711576Ssam 54811576Ssam /* 54911576Ssam * Return interface configuration 55011576Ssam * of system. List may be used 55111576Ssam * in later ioctl's (above) to get 55211576Ssam * other information. 55311576Ssam */ 55412783Ssam /*ARGSUSED*/ 55511576Ssam ifconf(cmd, data) 55611576Ssam int cmd; 55711576Ssam caddr_t data; 55811576Ssam { 55911576Ssam register struct ifconf *ifc = (struct ifconf *)data; 56011576Ssam register struct ifnet *ifp = ifnet; 56118544Skarels register struct ifaddr *ifa; 56211630Ssam register char *cp, *ep; 56311630Ssam struct ifreq ifr, *ifrp; 56411576Ssam int space = ifc->ifc_len, error = 0; 56511576Ssam 56611630Ssam ifrp = ifc->ifc_req; 56711630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 56811576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 56911630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 57011630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 57152914Storek continue; 57211630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 57318544Skarels if ((ifa = ifp->if_addrlist) == 0) { 57418544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 57518544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 57618544Skarels if (error) 57718544Skarels break; 57818544Skarels space -= sizeof (ifr), ifrp++; 57918544Skarels } else 58018544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 58137549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 58237549Smckusick #ifdef COMPAT_43 58337549Smckusick if (cmd == OSIOCGIFCONF) { 58437549Smckusick struct osockaddr *osa = 58537549Smckusick (struct osockaddr *)&ifr.ifr_addr; 58637549Smckusick ifr.ifr_addr = *sa; 58737549Smckusick osa->sa_family = sa->sa_family; 58837549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 58937549Smckusick sizeof (ifr)); 59037549Smckusick ifrp++; 59137549Smckusick } else 59237549Smckusick #endif 59337549Smckusick if (sa->sa_len <= sizeof(*sa)) { 59437549Smckusick ifr.ifr_addr = *sa; 59537549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 59637549Smckusick sizeof (ifr)); 59737549Smckusick ifrp++; 59837549Smckusick } else { 59937549Smckusick space -= sa->sa_len - sizeof(*sa); 60037549Smckusick if (space < sizeof (ifr)) 60137549Smckusick break; 60237549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60337549Smckusick sizeof (ifr.ifr_name)); 60437549Smckusick if (error == 0) 60537549Smckusick error = copyout((caddr_t)sa, 60637549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 60737549Smckusick ifrp = (struct ifreq *) 60837549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 60937549Smckusick } 61018544Skarels if (error) 61118544Skarels break; 61237549Smckusick space -= sizeof (ifr); 61318544Skarels } 61411576Ssam } 61511576Ssam ifc->ifc_len -= space; 61611576Ssam return (error); 61711576Ssam } 61840792Ssklower 61948453Skarels static char * 62048453Skarels sprint_d(n, buf, buflen) 62148453Skarels u_int n; 62248453Skarels char *buf; 62348453Skarels int buflen; 62440792Ssklower { 62548453Skarels register char *cp = buf + buflen - 1; 62648453Skarels 62748453Skarels *cp = 0; 62840792Ssklower do { 62948453Skarels cp--; 63048453Skarels *cp = "0123456789"[n % 10]; 63148453Skarels n /= 10; 63248453Skarels } while (n != 0); 63348453Skarels return (cp); 63440792Ssklower } 635