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*68168Scgd * @(#)if.c 8.5 (Berkeley) 01/09/95
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
ifinit()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
ifubareset(uban)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
if_attach(ifp)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 *
ifa_ifwithaddr(addr)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 *
ifa_ifwithdstaddr(addr)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) {
17567465Ssklower if (ifa->ifa_addr->sa_family != addr->sa_family ||
17667465Ssklower ifa->ifa_dstaddr == NULL)
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 *
ifa_ifwithnet(addr)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 *
ifa_ifwithaf(af)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 *
ifaof_ifpforaddr(addr,ifp)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
link_rtrequest(cmd,rt,sa)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;
29665452Sbostic struct ifnet *ifp;
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
if_down(ifp)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
if_up(ifp)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
if_qflush(ifq)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
if_slowtimo(arg)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 *
ifunit(name)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
ifioctl(so,cmd,data,p)43348453Skarels ifioctl(so, cmd, data, p)
43418544Skarels struct socket *so;
435*68168Scgd u_long 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
ifconf(cmd,data)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 *
sprint_d(n,buf,buflen)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