123157Smckusick /* 2*63630Sbostic * Copyright (c) 1980, 1986, 1993 3*63630Sbostic * The Regents of the University of California. All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*63630Sbostic * @(#)if.c 8.1 (Berkeley) 06/29/93 823157Smckusick */ 94944Swnj 1056529Sbostic #include <sys/param.h> 1156529Sbostic #include <sys/mbuf.h> 1256529Sbostic #include <sys/systm.h> 1356529Sbostic #include <sys/proc.h> 1456529Sbostic #include <sys/socket.h> 1556529Sbostic #include <sys/socketvar.h> 1656529Sbostic #include <sys/protosw.h> 1756529Sbostic #include <sys/kernel.h> 1856529Sbostic #include <sys/ioctl.h> 1910872Ssam 2056529Sbostic #include <net/if.h> 2156529Sbostic #include <net/af.h> 2256529Sbostic #include <net/if_dl.h> 2356529Sbostic #include <net/if_types.h> 244944Swnj 256207Swnj int ifqmaxlen = IFQ_MAXLEN; 2654768Storek void if_slowtimo __P((void *arg)); 276207Swnj 286333Ssam /* 296333Ssam * Network interface utility routines. 306333Ssam * 3118544Skarels * Routines with ifa_ifwith* names take sockaddr *'s as 3218544Skarels * parameters. 336333Ssam */ 3461337Sbostic void 355206Swnj ifinit() 365206Swnj { 375206Swnj register struct ifnet *ifp; 385206Swnj 395206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 4024773Skarels if (ifp->if_snd.ifq_maxlen == 0) 4124773Skarels ifp->if_snd.ifq_maxlen = ifqmaxlen; 4254768Storek if_slowtimo(0); 435206Swnj } 445206Swnj 4513049Ssam #ifdef vax 466333Ssam /* 476333Ssam * Call each interface on a Unibus reset. 486333Ssam */ 4961337Sbostic void 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; 6361337Sbostic static char *sprint_d __P((u_int, char *, int)); 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; 7454718Ssklower 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; 8054718Ssklower 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 || 21761337Sbostic rn_refines((caddr_t)ifa->ifa_netmask, 21861337Sbostic (caddr_t)ifa_maybe->ifa_netmask)) 21953454Ssklower ifa_maybe = ifa; 22037549Smckusick } 22153454Ssklower return (ifa_maybe); 2226333Ssam } 2236333Ssam 2246333Ssam /* 2256333Ssam * Find an interface using a specific address family 2266333Ssam */ 22718544Skarels struct ifaddr * 22818544Skarels ifa_ifwithaf(af) 2296333Ssam register int af; 2305083Swnj { 2316333Ssam register struct ifnet *ifp; 23218544Skarels register struct ifaddr *ifa; 2335083Swnj 2346333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 23518544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 23637549Smckusick if (ifa->ifa_addr->sa_family == af) 23718544Skarels return (ifa); 23818544Skarels return ((struct ifaddr *)0); 2395083Swnj } 2405104Swnj 24143335Ssklower /* 24243335Ssklower * Find an interface address specific to an interface best matching 24343335Ssklower * a given address. 24443335Ssklower */ 24543335Ssklower struct ifaddr * 24643335Ssklower ifaof_ifpforaddr(addr, ifp) 24743335Ssklower struct sockaddr *addr; 24843335Ssklower register struct ifnet *ifp; 24943335Ssklower { 25043335Ssklower register struct ifaddr *ifa; 25143335Ssklower register char *cp, *cp2, *cp3; 25243335Ssklower register char *cplim; 25343335Ssklower struct ifaddr *ifa_maybe = 0; 25443335Ssklower u_int af = addr->sa_family; 25543335Ssklower 25643335Ssklower if (af >= AF_MAX) 25743335Ssklower return (0); 25843335Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 25943335Ssklower if (ifa->ifa_addr->sa_family != af) 26043335Ssklower continue; 26143335Ssklower ifa_maybe = ifa; 26243335Ssklower if (ifa->ifa_netmask == 0) { 26343335Ssklower if (equal(addr, ifa->ifa_addr) || 26443335Ssklower (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 26543335Ssklower return (ifa); 26643335Ssklower continue; 26743335Ssklower } 26843335Ssklower cp = addr->sa_data; 26943335Ssklower cp2 = ifa->ifa_addr->sa_data; 27043335Ssklower cp3 = ifa->ifa_netmask->sa_data; 27143335Ssklower cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 27243335Ssklower for (; cp3 < cplim; cp3++) 27343335Ssklower if ((*cp++ ^ *cp2++) & *cp3) 27443335Ssklower break; 27543335Ssklower if (cp3 == cplim) 27643335Ssklower return (ifa); 27743335Ssklower } 27843335Ssklower return (ifa_maybe); 27943335Ssklower } 28056529Sbostic 28156529Sbostic #include <net/route.h> 28256529Sbostic 2836333Ssam /* 28441923Ssklower * Default action when installing a route with a Link Level gateway. 28541923Ssklower * Lookup an appropriate real ifa to point to. 28641923Ssklower * This should be moved to /sys/net/link.c eventually. 28741923Ssklower */ 28854718Ssklower void 28941923Ssklower link_rtrequest(cmd, rt, sa) 29052265Storek int cmd; 29152265Storek register struct rtentry *rt; 29252265Storek struct sockaddr *sa; 29341923Ssklower { 29441923Ssklower register struct ifaddr *ifa; 29541923Ssklower struct sockaddr *dst; 29641923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 29741923Ssklower 29841923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29941923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 30041923Ssklower return; 30143335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 30259063Ssklower IFAFREE(rt->rt_ifa); 30341923Ssklower rt->rt_ifa = ifa; 30459063Ssklower ifa->ifa_refcnt++; 30541923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30641923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30743335Ssklower } 30841923Ssklower } 30941923Ssklower 31041923Ssklower /* 3116582Ssam * Mark an interface down and notify protocols of 3126582Ssam * the transition. 3139184Ssam * NOTE: must be called at splnet or eqivalent. 3146582Ssam */ 31561337Sbostic void 3166582Ssam if_down(ifp) 3176582Ssam register struct ifnet *ifp; 3186582Ssam { 31918544Skarels register struct ifaddr *ifa; 3208173Sroot 3216582Ssam ifp->if_flags &= ~IFF_UP; 32218544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 32337549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 32433984Skarels if_qflush(&ifp->if_snd); 32552562Ssklower rt_ifmsg(ifp); 3266582Ssam } 3277264Ssam 3287264Ssam /* 32952562Ssklower * Mark an interface up and notify protocols of 33052562Ssklower * the transition. 33152562Ssklower * NOTE: must be called at splnet or eqivalent. 33252562Ssklower */ 33361337Sbostic void 33452562Ssklower if_up(ifp) 33552562Ssklower register struct ifnet *ifp; 33652562Ssklower { 33752562Ssklower register struct ifaddr *ifa; 33852562Ssklower 33952562Ssklower ifp->if_flags |= IFF_UP; 34052562Ssklower #ifdef notyet 34152562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 34252562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 34352562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 34460346Storek #endif 34552562Ssklower rt_ifmsg(ifp); 34652562Ssklower } 34752562Ssklower 34852562Ssklower /* 34933984Skarels * Flush an interface queue. 35033984Skarels */ 35161337Sbostic void 35233984Skarels if_qflush(ifq) 35333984Skarels register struct ifqueue *ifq; 35433984Skarels { 35533984Skarels register struct mbuf *m, *n; 35633984Skarels 35733984Skarels n = ifq->ifq_head; 35833984Skarels while (m = n) { 35933984Skarels n = m->m_act; 36033984Skarels m_freem(m); 36133984Skarels } 36233984Skarels ifq->ifq_head = 0; 36333984Skarels ifq->ifq_tail = 0; 36433984Skarels ifq->ifq_len = 0; 36533984Skarels } 36633984Skarels 36733984Skarels /* 3687264Ssam * Handle interface watchdog timer routines. Called 3697264Ssam * from softclock, we decrement timers (if set) and 3707264Ssam * call the appropriate interface routine on expiration. 3717264Ssam */ 37254768Storek void 37354768Storek if_slowtimo(arg) 37454768Storek void *arg; 3757264Ssam { 3767264Ssam register struct ifnet *ifp; 37737549Smckusick int s = splimp(); 3787264Ssam 3799184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3809184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3819184Ssam continue; 3829184Ssam if (ifp->if_watchdog) 3837264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3849184Ssam } 38537549Smckusick splx(s); 38654768Storek timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 3877264Ssam } 38811576Ssam 38911576Ssam /* 39013049Ssam * Map interface name to 39113049Ssam * interface structure pointer. 39211576Ssam */ 39313049Ssam struct ifnet * 39413049Ssam ifunit(name) 39513049Ssam register char *name; 39611576Ssam { 39713049Ssam register char *cp; 39811576Ssam register struct ifnet *ifp; 39913049Ssam int unit; 40036821Skarels unsigned len; 40136821Skarels char *ep, c; 40211576Ssam 40313049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 40411576Ssam if (*cp >= '0' && *cp <= '9') 40511576Ssam break; 40613049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 40713049Ssam return ((struct ifnet *)0); 40836821Skarels /* 40936821Skarels * Save first char of unit, and pointer to it, 41036821Skarels * so we can put a null there to avoid matching 41136821Skarels * initial substrings of interface names. 41236821Skarels */ 41336821Skarels len = cp - name + 1; 41436821Skarels c = *cp; 41536821Skarels ep = cp; 41636821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 41736821Skarels unit = unit * 10 + *cp++ - '0'; 41836821Skarels *ep = 0; 41911576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 42036821Skarels if (bcmp(ifp->if_name, name, len)) 42111576Ssam continue; 42211576Ssam if (unit == ifp->if_unit) 42313049Ssam break; 42411576Ssam } 42536821Skarels *ep = c; 42613049Ssam return (ifp); 42713049Ssam } 42811576Ssam 42913049Ssam /* 43013049Ssam * Interface ioctls. 43113049Ssam */ 43261337Sbostic int 43348453Skarels ifioctl(so, cmd, data, p) 43418544Skarels struct socket *so; 43513049Ssam int cmd; 43613049Ssam caddr_t data; 43748453Skarels struct proc *p; 43813049Ssam { 43913049Ssam register struct ifnet *ifp; 44013049Ssam register struct ifreq *ifr; 44137549Smckusick int error; 44213049Ssam 44311576Ssam switch (cmd) { 44411576Ssam 44513049Ssam case SIOCGIFCONF: 44637549Smckusick case OSIOCGIFCONF: 44713049Ssam return (ifconf(cmd, data)); 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 48854718Ssklower case SIOCADDMULTI: 48954718Ssklower case SIOCDELMULTI: 49054718Ssklower if (error = suser(p->p_ucred, &p->p_acflag)) 49154718Ssklower return (error); 49258027Storek if (ifp->if_ioctl == NULL) 49354718Ssklower return (EOPNOTSUPP); 49454718Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 49554718Ssklower 49611576Ssam default: 49718544Skarels if (so->so_proto == 0) 49813049Ssam return (EOPNOTSUPP); 49937549Smckusick #ifndef COMPAT_43 50018544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50118544Skarels cmd, data, ifp)); 50237549Smckusick #else 50337549Smckusick { 50441545Smckusick int ocmd = cmd; 50537549Smckusick 50637549Smckusick switch (cmd) { 50737549Smckusick 50837549Smckusick case SIOCSIFDSTADDR: 50937549Smckusick case SIOCSIFADDR: 51037549Smckusick case SIOCSIFBRDADDR: 51137549Smckusick case SIOCSIFNETMASK: 51237549Smckusick #if BYTE_ORDER != BIG_ENDIAN 51337549Smckusick if (ifr->ifr_addr.sa_family == 0 && 51437549Smckusick ifr->ifr_addr.sa_len < 16) { 51537549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 51637549Smckusick ifr->ifr_addr.sa_len = 16; 51737549Smckusick } 51837549Smckusick #else 51937549Smckusick if (ifr->ifr_addr.sa_len == 0) 52037549Smckusick ifr->ifr_addr.sa_len = 16; 52137549Smckusick #endif 52237549Smckusick break; 52337549Smckusick 52437549Smckusick case OSIOCGIFADDR: 52537549Smckusick cmd = SIOCGIFADDR; 52637549Smckusick break; 52737549Smckusick 52837549Smckusick case OSIOCGIFDSTADDR: 52937549Smckusick cmd = SIOCGIFDSTADDR; 53037549Smckusick break; 53137549Smckusick 53237549Smckusick case OSIOCGIFBRDADDR: 53337549Smckusick cmd = SIOCGIFBRDADDR; 53437549Smckusick break; 53537549Smckusick 53637549Smckusick case OSIOCGIFNETMASK: 53737549Smckusick cmd = SIOCGIFNETMASK; 53837549Smckusick } 53937549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 54037549Smckusick cmd, data, ifp)); 54137549Smckusick switch (ocmd) { 54237549Smckusick 54337549Smckusick case OSIOCGIFADDR: 54437549Smckusick case OSIOCGIFDSTADDR: 54537549Smckusick case OSIOCGIFBRDADDR: 54637549Smckusick case OSIOCGIFNETMASK: 54737549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 54837549Smckusick } 54937549Smckusick return (error); 55037549Smckusick 55137549Smckusick } 55237549Smckusick #endif 55311576Ssam } 55411576Ssam return (0); 55511576Ssam } 55611576Ssam 55711576Ssam /* 55811576Ssam * Return interface configuration 55911576Ssam * of system. List may be used 56011576Ssam * in later ioctl's (above) to get 56111576Ssam * other information. 56211576Ssam */ 56312783Ssam /*ARGSUSED*/ 56461337Sbostic int 56511576Ssam ifconf(cmd, data) 56611576Ssam int cmd; 56711576Ssam caddr_t data; 56811576Ssam { 56911576Ssam register struct ifconf *ifc = (struct ifconf *)data; 57011576Ssam register struct ifnet *ifp = ifnet; 57118544Skarels register struct ifaddr *ifa; 57211630Ssam register char *cp, *ep; 57311630Ssam struct ifreq ifr, *ifrp; 57411576Ssam int space = ifc->ifc_len, error = 0; 57511576Ssam 57611630Ssam ifrp = ifc->ifc_req; 57711630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 57811576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 57963629Smckusick strncpy(ifr.ifr_name, ifp->if_name, sizeof (ifr.ifr_name) - 2); 58011630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 58152914Storek continue; 58211630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 58318544Skarels if ((ifa = ifp->if_addrlist) == 0) { 58418544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 58563629Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 58663629Smckusick 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