123157Smckusick /* 263630Sbostic * Copyright (c) 1980, 1986, 1993 363630Sbostic * The Regents of the University of California. All rights reserved. 423157Smckusick * 544463Sbostic * %sccs.include.redist.c% 633183Sbostic * 7*65452Sbostic * @(#)if.c 8.3 (Berkeley) 01/04/94 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/if_dl.h> 2256529Sbostic #include <net/if_types.h> 234944Swnj 246207Swnj int ifqmaxlen = IFQ_MAXLEN; 2554768Storek void if_slowtimo __P((void *arg)); 266207Swnj 276333Ssam /* 286333Ssam * Network interface utility routines. 296333Ssam * 3018544Skarels * Routines with ifa_ifwith* names take sockaddr *'s as 3118544Skarels * parameters. 326333Ssam */ 3361337Sbostic void 345206Swnj ifinit() 355206Swnj { 365206Swnj register struct ifnet *ifp; 375206Swnj 385206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 3924773Skarels if (ifp->if_snd.ifq_maxlen == 0) 4024773Skarels ifp->if_snd.ifq_maxlen = ifqmaxlen; 4154768Storek if_slowtimo(0); 425206Swnj } 435206Swnj 4413049Ssam #ifdef vax 456333Ssam /* 466333Ssam * Call each interface on a Unibus reset. 476333Ssam */ 4861337Sbostic void 495206Swnj ifubareset(uban) 505206Swnj int uban; 515206Swnj { 525206Swnj register struct ifnet *ifp; 535206Swnj 545206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 558974Sroot if (ifp->if_reset) 5615116Ssam (*ifp->if_reset)(ifp->if_unit, uban); 575206Swnj } 588393Swnj #endif 595206Swnj 6040792Ssklower int if_index = 0; 6143335Ssklower struct ifaddr **ifnet_addrs; 6261337Sbostic static char *sprint_d __P((u_int, char *, int)); 6348453Skarels 646333Ssam /* 656333Ssam * Attach an interface to the 666333Ssam * list of "active" interfaces. 676333Ssam */ 6852265Storek void 695160Swnj if_attach(ifp) 705160Swnj struct ifnet *ifp; 715160Swnj { 7240792Ssklower unsigned socksize, ifasize; 7354718Ssklower int namelen, unitlen, masklen, ether_output(); 7448453Skarels char workbuf[12], *unitname; 7543335Ssklower register struct ifnet **p = &ifnet; 7640792Ssklower register struct sockaddr_dl *sdl; 7740792Ssklower register struct ifaddr *ifa; 7843335Ssklower static int if_indexlim = 8; 7954718Ssklower extern void link_rtrequest(); 805160Swnj 815698Swnj while (*p) 825698Swnj p = &((*p)->if_next); 835698Swnj *p = ifp; 8440792Ssklower ifp->if_index = ++if_index; 8543335Ssklower if (ifnet_addrs == 0 || if_index >= if_indexlim) { 8643335Ssklower unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 8743335Ssklower struct ifaddr **q = (struct ifaddr **) 8843335Ssklower malloc(n, M_IFADDR, M_WAITOK); 8943335Ssklower if (ifnet_addrs) { 9043335Ssklower bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 9143335Ssklower free((caddr_t)ifnet_addrs, M_IFADDR); 9243335Ssklower } 9343335Ssklower ifnet_addrs = q; 9443335Ssklower } 9541923Ssklower /* 9641923Ssklower * create a Link Level name for this device 9741923Ssklower */ 9848453Skarels unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 9940792Ssklower namelen = strlen(ifp->if_name); 10048453Skarels unitlen = strlen(unitname); 10140792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 10252562Ssklower masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + 10352562Ssklower unitlen + namelen; 10452562Ssklower socksize = masklen + ifp->if_addrlen; 10540792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 10640792Ssklower socksize = ROUNDUP(socksize); 10743335Ssklower if (socksize < sizeof(*sdl)) 10843335Ssklower socksize = sizeof(*sdl); 10940792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 11052562Ssklower if (ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK)) { 11152562Ssklower bzero((caddr_t)ifa, ifasize); 11252562Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 11352562Ssklower sdl->sdl_len = socksize; 11452562Ssklower sdl->sdl_family = AF_LINK; 11552562Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 11652562Ssklower bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 11752562Ssklower sdl->sdl_nlen = (namelen += unitlen); 11852562Ssklower sdl->sdl_index = ifp->if_index; 11952562Ssklower sdl->sdl_type = ifp->if_type; 12052562Ssklower ifnet_addrs[if_index - 1] = ifa; 12152562Ssklower ifa->ifa_ifp = ifp; 12252562Ssklower ifa->ifa_next = ifp->if_addrlist; 12352562Ssklower ifa->ifa_rtrequest = link_rtrequest; 12452562Ssklower ifp->if_addrlist = ifa; 12552562Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 12652562Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 12752562Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 12852562Ssklower sdl->sdl_len = masklen; 12952562Ssklower while (namelen != 0) 13052562Ssklower sdl->sdl_data[--namelen] = 0xff; 13152562Ssklower } 13252562Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 13352562Ssklower if (ifp->if_output == ether_output) 13452562Ssklower ether_ifattach(ifp); 1355160Swnj } 1366333Ssam /* 1376333Ssam * Locate an interface based on a complete address. 1386333Ssam */ 1394951Swnj /*ARGSUSED*/ 14018544Skarels struct ifaddr * 14118544Skarels ifa_ifwithaddr(addr) 14237549Smckusick register struct sockaddr *addr; 1434944Swnj { 1444944Swnj register struct ifnet *ifp; 14518544Skarels register struct ifaddr *ifa; 1464944Swnj 1476333Ssam #define equal(a1, a2) \ 14837549Smckusick (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 14918544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 15018544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 15137549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 1526333Ssam continue; 15337549Smckusick if (equal(addr, ifa->ifa_addr)) 15418544Skarels return (ifa); 15543335Ssklower if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 15643335Ssklower equal(ifa->ifa_broadaddr, addr)) 15718544Skarels return (ifa); 1586333Ssam } 15918544Skarels return ((struct ifaddr *)0); 1604944Swnj } 16123933Ssklower /* 16223933Ssklower * Locate the point to point interface with a given destination address. 16323933Ssklower */ 16423933Ssklower /*ARGSUSED*/ 16523933Ssklower struct ifaddr * 16623933Ssklower ifa_ifwithdstaddr(addr) 16737549Smckusick register struct sockaddr *addr; 16823933Ssklower { 16923933Ssklower register struct ifnet *ifp; 17023933Ssklower register struct ifaddr *ifa; 1714944Swnj 17223933Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) 17323933Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 17423933Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 17537549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 17623933Ssklower continue; 17737549Smckusick if (equal(addr, ifa->ifa_dstaddr)) 17823933Ssklower return (ifa); 17923933Ssklower } 18023933Ssklower return ((struct ifaddr *)0); 18123933Ssklower } 18223933Ssklower 1836333Ssam /* 1846333Ssam * Find an interface on a specific network. If many, choice 18553454Ssklower * is most specific found. 1866333Ssam */ 18718544Skarels struct ifaddr * 18818544Skarels ifa_ifwithnet(addr) 18937549Smckusick struct sockaddr *addr; 1904944Swnj { 1914944Swnj register struct ifnet *ifp; 19218544Skarels register struct ifaddr *ifa; 19353454Ssklower struct ifaddr *ifa_maybe = (struct ifaddr *) 0; 19437549Smckusick u_int af = addr->sa_family; 19553454Ssklower char *addr_data = addr->sa_data, *cplim; 1964944Swnj 19743335Ssklower if (af == AF_LINK) { 19843335Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 19943335Ssklower if (sdl->sdl_index && sdl->sdl_index <= if_index) 20043335Ssklower return (ifnet_addrs[sdl->sdl_index - 1]); 20143335Ssklower } 20218544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 20318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 20443335Ssklower register char *cp, *cp2, *cp3; 20553454Ssklower 20637549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 20753454Ssklower next: continue; 20853454Ssklower cp = addr_data; 20937549Smckusick cp2 = ifa->ifa_addr->sa_data; 21037549Smckusick cp3 = ifa->ifa_netmask->sa_data; 21137549Smckusick cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 21253454Ssklower while (cp3 < cplim) 21353454Ssklower if ((*cp++ ^ *cp2++) & *cp3++) 21453454Ssklower goto next; 21553454Ssklower if (ifa_maybe == 0 || 21661337Sbostic rn_refines((caddr_t)ifa->ifa_netmask, 21761337Sbostic (caddr_t)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 } 27956529Sbostic 28056529Sbostic #include <net/route.h> 28156529Sbostic 2826333Ssam /* 28341923Ssklower * Default action when installing a route with a Link Level gateway. 28441923Ssklower * Lookup an appropriate real ifa to point to. 28541923Ssklower * This should be moved to /sys/net/link.c eventually. 28641923Ssklower */ 28754718Ssklower void 28841923Ssklower link_rtrequest(cmd, rt, sa) 28952265Storek int cmd; 29052265Storek register struct rtentry *rt; 29152265Storek struct sockaddr *sa; 29241923Ssklower { 29341923Ssklower register struct ifaddr *ifa; 29441923Ssklower struct sockaddr *dst; 295*65452Sbostic struct ifnet *ifp; 29641923Ssklower 29741923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 29841923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 29941923Ssklower return; 30043335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 30159063Ssklower IFAFREE(rt->rt_ifa); 30241923Ssklower rt->rt_ifa = ifa; 30359063Ssklower ifa->ifa_refcnt++; 30441923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30541923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 30643335Ssklower } 30741923Ssklower } 30841923Ssklower 30941923Ssklower /* 3106582Ssam * Mark an interface down and notify protocols of 3116582Ssam * the transition. 3129184Ssam * NOTE: must be called at splnet or eqivalent. 3136582Ssam */ 31461337Sbostic void 3156582Ssam if_down(ifp) 3166582Ssam register struct ifnet *ifp; 3176582Ssam { 31818544Skarels register struct ifaddr *ifa; 3198173Sroot 3206582Ssam ifp->if_flags &= ~IFF_UP; 32118544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 32237549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 32333984Skarels if_qflush(&ifp->if_snd); 32452562Ssklower rt_ifmsg(ifp); 3256582Ssam } 3267264Ssam 3277264Ssam /* 32852562Ssklower * Mark an interface up and notify protocols of 32952562Ssklower * the transition. 33052562Ssklower * NOTE: must be called at splnet or eqivalent. 33152562Ssklower */ 33261337Sbostic void 33352562Ssklower if_up(ifp) 33452562Ssklower register struct ifnet *ifp; 33552562Ssklower { 33652562Ssklower register struct ifaddr *ifa; 33752562Ssklower 33852562Ssklower ifp->if_flags |= IFF_UP; 33952562Ssklower #ifdef notyet 34052562Ssklower /* this has no effect on IP, and will kill all iso connections XXX */ 34152562Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 34252562Ssklower pfctlinput(PRC_IFUP, ifa->ifa_addr); 34360346Storek #endif 34452562Ssklower rt_ifmsg(ifp); 34552562Ssklower } 34652562Ssklower 34752562Ssklower /* 34833984Skarels * Flush an interface queue. 34933984Skarels */ 35061337Sbostic void 35133984Skarels if_qflush(ifq) 35233984Skarels register struct ifqueue *ifq; 35333984Skarels { 35433984Skarels register struct mbuf *m, *n; 35533984Skarels 35633984Skarels n = ifq->ifq_head; 35733984Skarels while (m = n) { 35833984Skarels n = m->m_act; 35933984Skarels m_freem(m); 36033984Skarels } 36133984Skarels ifq->ifq_head = 0; 36233984Skarels ifq->ifq_tail = 0; 36333984Skarels ifq->ifq_len = 0; 36433984Skarels } 36533984Skarels 36633984Skarels /* 3677264Ssam * Handle interface watchdog timer routines. Called 3687264Ssam * from softclock, we decrement timers (if set) and 3697264Ssam * call the appropriate interface routine on expiration. 3707264Ssam */ 37154768Storek void 37254768Storek if_slowtimo(arg) 37354768Storek void *arg; 3747264Ssam { 3757264Ssam register struct ifnet *ifp; 37637549Smckusick int s = splimp(); 3777264Ssam 3789184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3799184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3809184Ssam continue; 3819184Ssam if (ifp->if_watchdog) 3827264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3839184Ssam } 38437549Smckusick splx(s); 38554768Storek timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ); 3867264Ssam } 38711576Ssam 38811576Ssam /* 38913049Ssam * Map interface name to 39013049Ssam * interface structure pointer. 39111576Ssam */ 39213049Ssam struct ifnet * 39313049Ssam ifunit(name) 39413049Ssam register char *name; 39511576Ssam { 39613049Ssam register char *cp; 39711576Ssam register struct ifnet *ifp; 39813049Ssam int unit; 39936821Skarels unsigned len; 40036821Skarels char *ep, c; 40111576Ssam 40213049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 40311576Ssam if (*cp >= '0' && *cp <= '9') 40411576Ssam break; 40513049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 40613049Ssam return ((struct ifnet *)0); 40736821Skarels /* 40836821Skarels * Save first char of unit, and pointer to it, 40936821Skarels * so we can put a null there to avoid matching 41036821Skarels * initial substrings of interface names. 41136821Skarels */ 41236821Skarels len = cp - name + 1; 41336821Skarels c = *cp; 41436821Skarels ep = cp; 41536821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 41636821Skarels unit = unit * 10 + *cp++ - '0'; 41736821Skarels *ep = 0; 41811576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 41936821Skarels if (bcmp(ifp->if_name, name, len)) 42011576Ssam continue; 42111576Ssam if (unit == ifp->if_unit) 42213049Ssam break; 42311576Ssam } 42436821Skarels *ep = c; 42513049Ssam return (ifp); 42613049Ssam } 42711576Ssam 42813049Ssam /* 42913049Ssam * Interface ioctls. 43013049Ssam */ 43161337Sbostic int 43248453Skarels ifioctl(so, cmd, data, p) 43318544Skarels struct socket *so; 43413049Ssam int cmd; 43513049Ssam caddr_t data; 43648453Skarels struct proc *p; 43713049Ssam { 43813049Ssam register struct ifnet *ifp; 43913049Ssam register struct ifreq *ifr; 44037549Smckusick int error; 44113049Ssam 44211576Ssam switch (cmd) { 44311576Ssam 44413049Ssam case SIOCGIFCONF: 44537549Smckusick case OSIOCGIFCONF: 44613049Ssam return (ifconf(cmd, data)); 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 48754718Ssklower case SIOCADDMULTI: 48854718Ssklower case SIOCDELMULTI: 48954718Ssklower if (error = suser(p->p_ucred, &p->p_acflag)) 49054718Ssklower return (error); 49158027Storek if (ifp->if_ioctl == NULL) 49254718Ssklower return (EOPNOTSUPP); 49354718Ssklower return ((*ifp->if_ioctl)(ifp, cmd, data)); 49454718Ssklower 49511576Ssam default: 49618544Skarels if (so->so_proto == 0) 49713049Ssam return (EOPNOTSUPP); 49837549Smckusick #ifndef COMPAT_43 49918544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 50018544Skarels cmd, data, ifp)); 50137549Smckusick #else 50237549Smckusick { 50341545Smckusick int ocmd = cmd; 50437549Smckusick 50537549Smckusick switch (cmd) { 50637549Smckusick 50737549Smckusick case SIOCSIFDSTADDR: 50837549Smckusick case SIOCSIFADDR: 50937549Smckusick case SIOCSIFBRDADDR: 51037549Smckusick case SIOCSIFNETMASK: 51137549Smckusick #if BYTE_ORDER != BIG_ENDIAN 51237549Smckusick if (ifr->ifr_addr.sa_family == 0 && 51337549Smckusick ifr->ifr_addr.sa_len < 16) { 51437549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 51537549Smckusick ifr->ifr_addr.sa_len = 16; 51637549Smckusick } 51737549Smckusick #else 51837549Smckusick if (ifr->ifr_addr.sa_len == 0) 51937549Smckusick ifr->ifr_addr.sa_len = 16; 52037549Smckusick #endif 52137549Smckusick break; 52237549Smckusick 52337549Smckusick case OSIOCGIFADDR: 52437549Smckusick cmd = SIOCGIFADDR; 52537549Smckusick break; 52637549Smckusick 52737549Smckusick case OSIOCGIFDSTADDR: 52837549Smckusick cmd = SIOCGIFDSTADDR; 52937549Smckusick break; 53037549Smckusick 53137549Smckusick case OSIOCGIFBRDADDR: 53237549Smckusick cmd = SIOCGIFBRDADDR; 53337549Smckusick break; 53437549Smckusick 53537549Smckusick case OSIOCGIFNETMASK: 53637549Smckusick cmd = SIOCGIFNETMASK; 53737549Smckusick } 53837549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 53937549Smckusick cmd, data, ifp)); 54037549Smckusick switch (ocmd) { 54137549Smckusick 54237549Smckusick case OSIOCGIFADDR: 54337549Smckusick case OSIOCGIFDSTADDR: 54437549Smckusick case OSIOCGIFBRDADDR: 54537549Smckusick case OSIOCGIFNETMASK: 54637549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 54737549Smckusick } 54837549Smckusick return (error); 54937549Smckusick 55037549Smckusick } 55137549Smckusick #endif 55211576Ssam } 55311576Ssam return (0); 55411576Ssam } 55511576Ssam 55611576Ssam /* 55711576Ssam * Return interface configuration 55811576Ssam * of system. List may be used 55911576Ssam * in later ioctl's (above) to get 56011576Ssam * other information. 56111576Ssam */ 56212783Ssam /*ARGSUSED*/ 56361337Sbostic int 56411576Ssam ifconf(cmd, data) 56511576Ssam int cmd; 56611576Ssam caddr_t data; 56711576Ssam { 56811576Ssam register struct ifconf *ifc = (struct ifconf *)data; 56911576Ssam register struct ifnet *ifp = ifnet; 57018544Skarels register struct ifaddr *ifa; 57111630Ssam register char *cp, *ep; 57211630Ssam struct ifreq ifr, *ifrp; 57311576Ssam int space = ifc->ifc_len, error = 0; 57411576Ssam 57511630Ssam ifrp = ifc->ifc_req; 57611630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 57711576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 57863629Smckusick strncpy(ifr.ifr_name, ifp->if_name, sizeof (ifr.ifr_name) - 2); 57911630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 58052914Storek continue; 58111630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 58218544Skarels if ((ifa = ifp->if_addrlist) == 0) { 58318544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 58463629Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 58563629Smckusick sizeof (ifr)); 58618544Skarels if (error) 58718544Skarels break; 58818544Skarels space -= sizeof (ifr), ifrp++; 58918544Skarels } else 59018544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 59137549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 59237549Smckusick #ifdef COMPAT_43 59337549Smckusick if (cmd == OSIOCGIFCONF) { 59437549Smckusick struct osockaddr *osa = 59537549Smckusick (struct osockaddr *)&ifr.ifr_addr; 59637549Smckusick ifr.ifr_addr = *sa; 59737549Smckusick osa->sa_family = sa->sa_family; 59837549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 59937549Smckusick sizeof (ifr)); 60037549Smckusick ifrp++; 60137549Smckusick } else 60237549Smckusick #endif 60337549Smckusick if (sa->sa_len <= sizeof(*sa)) { 60437549Smckusick ifr.ifr_addr = *sa; 60537549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 60637549Smckusick sizeof (ifr)); 60737549Smckusick ifrp++; 60837549Smckusick } else { 60937549Smckusick space -= sa->sa_len - sizeof(*sa); 61037549Smckusick if (space < sizeof (ifr)) 61137549Smckusick break; 61237549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 61337549Smckusick sizeof (ifr.ifr_name)); 61437549Smckusick if (error == 0) 61537549Smckusick error = copyout((caddr_t)sa, 61637549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 61737549Smckusick ifrp = (struct ifreq *) 61837549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 61937549Smckusick } 62018544Skarels if (error) 62118544Skarels break; 62237549Smckusick space -= sizeof (ifr); 62318544Skarels } 62411576Ssam } 62511576Ssam ifc->ifc_len -= space; 62611576Ssam return (error); 62711576Ssam } 62840792Ssklower 62948453Skarels static char * 63048453Skarels sprint_d(n, buf, buflen) 63148453Skarels u_int n; 63248453Skarels char *buf; 63348453Skarels int buflen; 63440792Ssklower { 63548453Skarels register char *cp = buf + buflen - 1; 63648453Skarels 63748453Skarels *cp = 0; 63840792Ssklower do { 63948453Skarels cp--; 64048453Skarels *cp = "0123456789"[n % 10]; 64148453Skarels n /= 10; 64248453Skarels } while (n != 0); 64348453Skarels return (cp); 64440792Ssklower } 645