123157Smckusick /* 229061Smckusick * Copyright (c) 1980, 1986 Regents of the University of California. 333183Sbostic * All rights reserved. 423157Smckusick * 533183Sbostic * Redistribution and use in source and binary forms are permitted 634844Sbostic * provided that the above copyright notice and this paragraph are 734844Sbostic * duplicated in all such forms and that any documentation, 834844Sbostic * advertising materials, and other materials related to such 934844Sbostic * distribution and use acknowledge that the software was developed 1034844Sbostic * by the University of California, Berkeley. The name of the 1134844Sbostic * University may not be used to endorse or promote products derived 1234844Sbostic * from this software without specific prior written permission. 1334844Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434844Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534844Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633183Sbostic * 17*43335Ssklower * @(#)if.c 7.12 (Berkeley) 06/20/90 1823157Smckusick */ 194944Swnj 2017036Sbloom #include "param.h" 2133984Skarels #include "mbuf.h" 2217036Sbloom #include "systm.h" 2317036Sbloom #include "socket.h" 2418544Skarels #include "socketvar.h" 2517036Sbloom #include "protosw.h" 2617036Sbloom #include "user.h" 2717036Sbloom #include "kernel.h" 2817036Sbloom #include "ioctl.h" 2917036Sbloom #include "errno.h" 3010872Ssam 3117036Sbloom #include "if.h" 3217036Sbloom #include "af.h" 3340792Ssklower #include "if_dl.h" 34*43335Ssklower #include "if_types.h" 354944Swnj 3616220Skarels #include "ether.h" 3716220Skarels 386207Swnj int ifqmaxlen = IFQ_MAXLEN; 396207Swnj 406333Ssam /* 416333Ssam * Network interface utility routines. 426333Ssam * 4318544Skarels * Routines with ifa_ifwith* names take sockaddr *'s as 4418544Skarels * parameters. 456333Ssam */ 466333Ssam 475206Swnj ifinit() 485206Swnj { 495206Swnj register struct ifnet *ifp; 505206Swnj 515206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 5224773Skarels if (ifp->if_snd.ifq_maxlen == 0) 5324773Skarels ifp->if_snd.ifq_maxlen = ifqmaxlen; 548173Sroot if_slowtimo(); 555206Swnj } 565206Swnj 5713049Ssam #ifdef vax 586333Ssam /* 596333Ssam * Call each interface on a Unibus reset. 606333Ssam */ 615206Swnj ifubareset(uban) 625206Swnj int uban; 635206Swnj { 645206Swnj register struct ifnet *ifp; 655206Swnj 665206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 678974Sroot if (ifp->if_reset) 6815116Ssam (*ifp->if_reset)(ifp->if_unit, uban); 695206Swnj } 708393Swnj #endif 715206Swnj 7240792Ssklower int if_index = 0; 73*43335Ssklower struct ifaddr **ifnet_addrs; 746333Ssam /* 756333Ssam * Attach an interface to the 766333Ssam * list of "active" interfaces. 776333Ssam */ 785160Swnj if_attach(ifp) 795160Swnj struct ifnet *ifp; 805160Swnj { 8140792Ssklower unsigned socksize, ifasize; 8240792Ssklower int namelen, unitlen; 8340792Ssklower char workbuf[16]; 84*43335Ssklower register struct ifnet **p = &ifnet; 8540792Ssklower register struct sockaddr_dl *sdl; 8640792Ssklower register struct ifaddr *ifa; 87*43335Ssklower static int if_indexlim = 8; 88*43335Ssklower extern link_rtrequest(), ether_output(); 895160Swnj 905698Swnj while (*p) 915698Swnj p = &((*p)->if_next); 925698Swnj *p = ifp; 9340792Ssklower ifp->if_index = ++if_index; 94*43335Ssklower if (ifnet_addrs == 0 || if_index >= if_indexlim) { 95*43335Ssklower unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 96*43335Ssklower struct ifaddr **q = (struct ifaddr **) 97*43335Ssklower malloc(n, M_IFADDR, M_WAITOK); 98*43335Ssklower if (ifnet_addrs) { 99*43335Ssklower bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 100*43335Ssklower free((caddr_t)ifnet_addrs, M_IFADDR); 101*43335Ssklower } 102*43335Ssklower ifnet_addrs = q; 103*43335Ssklower } 104*43335Ssklower /* XXX -- Temporary fix before changing 10 ethernet drivers */ 105*43335Ssklower if (ifp->if_output == ether_output) { 106*43335Ssklower ifp->if_type = IFT_ETHER; 107*43335Ssklower ifp->if_addrlen = 6; 108*43335Ssklower ifp->if_hdrlen = 14; 109*43335Ssklower } 11041923Ssklower /* 11141923Ssklower * create a Link Level name for this device 11241923Ssklower */ 11340792Ssklower sprint_d(workbuf, ifp->if_unit); 11440792Ssklower namelen = strlen(ifp->if_name); 11540792Ssklower unitlen = strlen(workbuf); 11640792Ssklower #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 11740792Ssklower socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 11840792Ssklower unitlen + namelen + ifp->if_addrlen; 11940792Ssklower #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 12040792Ssklower socksize = ROUNDUP(socksize); 121*43335Ssklower if (socksize < sizeof(*sdl)) 122*43335Ssklower socksize = sizeof(*sdl); 12340792Ssklower ifasize = sizeof(*ifa) + 2 * socksize; 12440792Ssklower ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 12540792Ssklower if (ifa == 0) 12640792Ssklower return; 127*43335Ssklower ifnet_addrs[if_index - 1] = ifa; 12840792Ssklower bzero((caddr_t)ifa, ifasize); 12940792Ssklower sdl = (struct sockaddr_dl *)(ifa + 1); 13040792Ssklower ifa->ifa_addr = (struct sockaddr *)sdl; 13140792Ssklower ifa->ifa_ifp = ifp; 13240792Ssklower sdl->sdl_len = socksize; 13340792Ssklower sdl->sdl_family = AF_LINK; 13440792Ssklower bcopy(ifp->if_name, sdl->sdl_data, namelen); 13540792Ssklower bcopy((caddr_t)workbuf, namelen + (caddr_t)sdl->sdl_data, unitlen); 13640792Ssklower sdl->sdl_nlen = (namelen += unitlen); 13740792Ssklower sdl->sdl_index = ifp->if_index; 13840792Ssklower sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 13940792Ssklower ifa->ifa_netmask = (struct sockaddr *)sdl; 14040792Ssklower sdl->sdl_len = socksize - ifp->if_addrlen; 14140792Ssklower while (namelen != 0) 14240792Ssklower sdl->sdl_data[--namelen] = 0xff; 14340792Ssklower ifa->ifa_next = ifp->if_addrlist; 14441923Ssklower ifa->ifa_rtrequest = link_rtrequest; 14540792Ssklower ifp->if_addrlist = ifa; 1465160Swnj } 1476333Ssam /* 1486333Ssam * Locate an interface based on a complete address. 1496333Ssam */ 1504951Swnj /*ARGSUSED*/ 15118544Skarels struct ifaddr * 15218544Skarels ifa_ifwithaddr(addr) 15337549Smckusick register struct sockaddr *addr; 1544944Swnj { 1554944Swnj register struct ifnet *ifp; 15618544Skarels register struct ifaddr *ifa; 1574944Swnj 1586333Ssam #define equal(a1, a2) \ 15937549Smckusick (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 16018544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 16118544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 16237549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 1636333Ssam continue; 16437549Smckusick if (equal(addr, ifa->ifa_addr)) 16518544Skarels return (ifa); 166*43335Ssklower if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 167*43335Ssklower equal(ifa->ifa_broadaddr, addr)) 16818544Skarels return (ifa); 1696333Ssam } 17018544Skarels return ((struct ifaddr *)0); 1714944Swnj } 17223933Ssklower /* 17323933Ssklower * Locate the point to point interface with a given destination address. 17423933Ssklower */ 17523933Ssklower /*ARGSUSED*/ 17623933Ssklower struct ifaddr * 17723933Ssklower ifa_ifwithdstaddr(addr) 17837549Smckusick register struct sockaddr *addr; 17923933Ssklower { 18023933Ssklower register struct ifnet *ifp; 18123933Ssklower register struct ifaddr *ifa; 1824944Swnj 18323933Ssklower for (ifp = ifnet; ifp; ifp = ifp->if_next) 18423933Ssklower if (ifp->if_flags & IFF_POINTOPOINT) 18523933Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 18637549Smckusick if (ifa->ifa_addr->sa_family != addr->sa_family) 18723933Ssklower continue; 18837549Smckusick if (equal(addr, ifa->ifa_dstaddr)) 18923933Ssklower return (ifa); 19023933Ssklower } 19123933Ssklower return ((struct ifaddr *)0); 19223933Ssklower } 19323933Ssklower 1946333Ssam /* 1956333Ssam * Find an interface on a specific network. If many, choice 1966333Ssam * is first found. 1976333Ssam */ 19818544Skarels struct ifaddr * 19918544Skarels ifa_ifwithnet(addr) 20037549Smckusick struct sockaddr *addr; 2014944Swnj { 2024944Swnj register struct ifnet *ifp; 20318544Skarels register struct ifaddr *ifa; 20437549Smckusick u_int af = addr->sa_family; 2054944Swnj 2066619Ssam if (af >= AF_MAX) 2076619Ssam return (0); 208*43335Ssklower if (af == AF_LINK) { 209*43335Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 210*43335Ssklower if (sdl->sdl_index && sdl->sdl_index <= if_index) 211*43335Ssklower return (ifnet_addrs[sdl->sdl_index - 1]); 212*43335Ssklower } 21318544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 21418544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 215*43335Ssklower register char *cp, *cp2, *cp3; 216*43335Ssklower register char *cplim; 21737549Smckusick if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 2186333Ssam continue; 21937549Smckusick cp = addr->sa_data; 22037549Smckusick cp2 = ifa->ifa_addr->sa_data; 22137549Smckusick cp3 = ifa->ifa_netmask->sa_data; 22237549Smckusick cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 22337549Smckusick for (; cp3 < cplim; cp3++) 22437549Smckusick if ((*cp++ ^ *cp2++) & *cp3) 22537549Smckusick break; 22637549Smckusick if (cp3 == cplim) 22718544Skarels return (ifa); 22837549Smckusick } 22918544Skarels return ((struct ifaddr *)0); 2306333Ssam } 2316333Ssam 2326333Ssam /* 2336333Ssam * Find an interface using a specific address family 2346333Ssam */ 23518544Skarels struct ifaddr * 23618544Skarels ifa_ifwithaf(af) 2376333Ssam register int af; 2385083Swnj { 2396333Ssam register struct ifnet *ifp; 24018544Skarels register struct ifaddr *ifa; 2415083Swnj 2426333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 24318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 24437549Smckusick if (ifa->ifa_addr->sa_family == af) 24518544Skarels return (ifa); 24618544Skarels return ((struct ifaddr *)0); 2475083Swnj } 2485104Swnj 249*43335Ssklower /* 250*43335Ssklower * Find an interface address specific to an interface best matching 251*43335Ssklower * a given address. 252*43335Ssklower */ 253*43335Ssklower struct ifaddr * 254*43335Ssklower ifaof_ifpforaddr(addr, ifp) 255*43335Ssklower struct sockaddr *addr; 256*43335Ssklower register struct ifnet *ifp; 257*43335Ssklower { 258*43335Ssklower register struct ifaddr *ifa; 259*43335Ssklower register char *cp, *cp2, *cp3; 260*43335Ssklower register char *cplim; 261*43335Ssklower struct ifaddr *ifa_maybe = 0; 262*43335Ssklower u_int af = addr->sa_family; 263*43335Ssklower 264*43335Ssklower if (af >= AF_MAX) 265*43335Ssklower return (0); 266*43335Ssklower for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 267*43335Ssklower if (ifa->ifa_addr->sa_family != af) 268*43335Ssklower continue; 269*43335Ssklower ifa_maybe = ifa; 270*43335Ssklower if (ifa->ifa_netmask == 0) { 271*43335Ssklower if (equal(addr, ifa->ifa_addr) || 272*43335Ssklower (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 273*43335Ssklower return (ifa); 274*43335Ssklower continue; 275*43335Ssklower } 276*43335Ssklower cp = addr->sa_data; 277*43335Ssklower cp2 = ifa->ifa_addr->sa_data; 278*43335Ssklower cp3 = ifa->ifa_netmask->sa_data; 279*43335Ssklower cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 280*43335Ssklower for (; cp3 < cplim; cp3++) 281*43335Ssklower if ((*cp++ ^ *cp2++) & *cp3) 282*43335Ssklower break; 283*43335Ssklower if (cp3 == cplim) 284*43335Ssklower return (ifa); 285*43335Ssklower } 286*43335Ssklower return (ifa_maybe); 287*43335Ssklower } 28841923Ssklower #include "route.h" 2896333Ssam /* 29041923Ssklower * Default action when installing a route with a Link Level gateway. 29141923Ssklower * Lookup an appropriate real ifa to point to. 29241923Ssklower * This should be moved to /sys/net/link.c eventually. 29341923Ssklower */ 29441923Ssklower link_rtrequest(cmd, rt, sa) 29541923Ssklower register struct rtentry *rt; 29641923Ssklower struct sockaddr *sa; 29741923Ssklower { 29841923Ssklower register struct ifaddr *ifa; 29941923Ssklower struct sockaddr *dst; 30041923Ssklower struct ifnet *ifp, *oldifnet = ifnet; 30141923Ssklower 30241923Ssklower if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 30341923Ssklower ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 30441923Ssklower return; 305*43335Ssklower if (ifa = ifaof_ifpforaddr(dst, ifp)) { 30641923Ssklower rt->rt_ifa = ifa; 30741923Ssklower if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 30841923Ssklower ifa->ifa_rtrequest(cmd, rt, sa); 309*43335Ssklower } 31041923Ssklower } 31141923Ssklower 31241923Ssklower /* 3136582Ssam * Mark an interface down and notify protocols of 3146582Ssam * the transition. 3159184Ssam * NOTE: must be called at splnet or eqivalent. 3166582Ssam */ 3176582Ssam if_down(ifp) 3186582Ssam register struct ifnet *ifp; 3196582Ssam { 32018544Skarels register struct ifaddr *ifa; 3218173Sroot 3226582Ssam ifp->if_flags &= ~IFF_UP; 32318544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 32437549Smckusick pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 32533984Skarels if_qflush(&ifp->if_snd); 3266582Ssam } 3277264Ssam 3287264Ssam /* 32933984Skarels * Flush an interface queue. 33033984Skarels */ 33133984Skarels if_qflush(ifq) 33233984Skarels register struct ifqueue *ifq; 33333984Skarels { 33433984Skarels register struct mbuf *m, *n; 33533984Skarels 33633984Skarels n = ifq->ifq_head; 33733984Skarels while (m = n) { 33833984Skarels n = m->m_act; 33933984Skarels m_freem(m); 34033984Skarels } 34133984Skarels ifq->ifq_head = 0; 34233984Skarels ifq->ifq_tail = 0; 34333984Skarels ifq->ifq_len = 0; 34433984Skarels } 34533984Skarels 34633984Skarels /* 3477264Ssam * Handle interface watchdog timer routines. Called 3487264Ssam * from softclock, we decrement timers (if set) and 3497264Ssam * call the appropriate interface routine on expiration. 3507264Ssam */ 3517264Ssam if_slowtimo() 3527264Ssam { 3537264Ssam register struct ifnet *ifp; 35437549Smckusick int s = splimp(); 3557264Ssam 3569184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 3579184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 3589184Ssam continue; 3599184Ssam if (ifp->if_watchdog) 3607264Ssam (*ifp->if_watchdog)(ifp->if_unit); 3619184Ssam } 36237549Smckusick splx(s); 3638692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 3647264Ssam } 36511576Ssam 36611576Ssam /* 36713049Ssam * Map interface name to 36813049Ssam * interface structure pointer. 36911576Ssam */ 37013049Ssam struct ifnet * 37113049Ssam ifunit(name) 37213049Ssam register char *name; 37311576Ssam { 37413049Ssam register char *cp; 37511576Ssam register struct ifnet *ifp; 37613049Ssam int unit; 37736821Skarels unsigned len; 37836821Skarels char *ep, c; 37911576Ssam 38013049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 38111576Ssam if (*cp >= '0' && *cp <= '9') 38211576Ssam break; 38313049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 38413049Ssam return ((struct ifnet *)0); 38536821Skarels /* 38636821Skarels * Save first char of unit, and pointer to it, 38736821Skarels * so we can put a null there to avoid matching 38836821Skarels * initial substrings of interface names. 38936821Skarels */ 39036821Skarels len = cp - name + 1; 39136821Skarels c = *cp; 39236821Skarels ep = cp; 39336821Skarels for (unit = 0; *cp >= '0' && *cp <= '9'; ) 39436821Skarels unit = unit * 10 + *cp++ - '0'; 39536821Skarels *ep = 0; 39611576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 39736821Skarels if (bcmp(ifp->if_name, name, len)) 39811576Ssam continue; 39911576Ssam if (unit == ifp->if_unit) 40013049Ssam break; 40111576Ssam } 40236821Skarels *ep = c; 40313049Ssam return (ifp); 40413049Ssam } 40511576Ssam 40613049Ssam /* 40713049Ssam * Interface ioctls. 40813049Ssam */ 40918544Skarels ifioctl(so, cmd, data) 41018544Skarels struct socket *so; 41113049Ssam int cmd; 41213049Ssam caddr_t data; 41313049Ssam { 41413049Ssam register struct ifnet *ifp; 41513049Ssam register struct ifreq *ifr; 41637549Smckusick int error; 41713049Ssam 41811576Ssam switch (cmd) { 41911576Ssam 42013049Ssam case SIOCGIFCONF: 42137549Smckusick case OSIOCGIFCONF: 42213049Ssam return (ifconf(cmd, data)); 42313049Ssam 42425647Skarels #if defined(INET) && NETHER > 0 42516220Skarels case SIOCSARP: 42616220Skarels case SIOCDARP: 42737549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 42837549Smckusick return (error); 42916220Skarels /* FALL THROUGH */ 43016220Skarels case SIOCGARP: 43137549Smckusick case OSIOCGARP: 43216220Skarels return (arpioctl(cmd, data)); 43316220Skarels #endif 43413049Ssam } 43513049Ssam ifr = (struct ifreq *)data; 43613049Ssam ifp = ifunit(ifr->ifr_name); 43713049Ssam if (ifp == 0) 43813049Ssam return (ENXIO); 43913049Ssam switch (cmd) { 44013049Ssam 44111576Ssam case SIOCGIFFLAGS: 44211576Ssam ifr->ifr_flags = ifp->if_flags; 44311576Ssam break; 44411576Ssam 44526091Skarels case SIOCGIFMETRIC: 44626091Skarels ifr->ifr_metric = ifp->if_metric; 44726091Skarels break; 44826091Skarels 44913053Ssam case SIOCSIFFLAGS: 45037549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 45137549Smckusick return (error); 45213053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 45313053Ssam int s = splimp(); 45413053Ssam if_down(ifp); 45513053Ssam splx(s); 45613053Ssam } 45718544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 45818544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 45924773Skarels if (ifp->if_ioctl) 46024773Skarels (void) (*ifp->if_ioctl)(ifp, cmd, data); 46113053Ssam break; 46213053Ssam 46326091Skarels case SIOCSIFMETRIC: 46437549Smckusick if (error = suser(u.u_cred, &u.u_acflag)) 46537549Smckusick return (error); 46626091Skarels ifp->if_metric = ifr->ifr_metric; 46726091Skarels break; 46826091Skarels 46911576Ssam default: 47018544Skarels if (so->so_proto == 0) 47113049Ssam return (EOPNOTSUPP); 47237549Smckusick #ifndef COMPAT_43 47318544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 47418544Skarels cmd, data, ifp)); 47537549Smckusick #else 47637549Smckusick { 47741545Smckusick int ocmd = cmd; 47837549Smckusick 47937549Smckusick switch (cmd) { 48037549Smckusick 48137549Smckusick case SIOCSIFDSTADDR: 48237549Smckusick case SIOCSIFADDR: 48337549Smckusick case SIOCSIFBRDADDR: 48437549Smckusick case SIOCSIFNETMASK: 48537549Smckusick #if BYTE_ORDER != BIG_ENDIAN 48637549Smckusick if (ifr->ifr_addr.sa_family == 0 && 48737549Smckusick ifr->ifr_addr.sa_len < 16) { 48837549Smckusick ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 48937549Smckusick ifr->ifr_addr.sa_len = 16; 49037549Smckusick } 49137549Smckusick #else 49237549Smckusick if (ifr->ifr_addr.sa_len == 0) 49337549Smckusick ifr->ifr_addr.sa_len = 16; 49437549Smckusick #endif 49537549Smckusick break; 49637549Smckusick 49737549Smckusick case OSIOCGIFADDR: 49837549Smckusick cmd = SIOCGIFADDR; 49937549Smckusick break; 50037549Smckusick 50137549Smckusick case OSIOCGIFDSTADDR: 50237549Smckusick cmd = SIOCGIFDSTADDR; 50337549Smckusick break; 50437549Smckusick 50537549Smckusick case OSIOCGIFBRDADDR: 50637549Smckusick cmd = SIOCGIFBRDADDR; 50737549Smckusick break; 50837549Smckusick 50937549Smckusick case OSIOCGIFNETMASK: 51037549Smckusick cmd = SIOCGIFNETMASK; 51137549Smckusick } 51237549Smckusick error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 51337549Smckusick cmd, data, ifp)); 51437549Smckusick switch (ocmd) { 51537549Smckusick 51637549Smckusick case OSIOCGIFADDR: 51737549Smckusick case OSIOCGIFDSTADDR: 51837549Smckusick case OSIOCGIFBRDADDR: 51937549Smckusick case OSIOCGIFNETMASK: 52037549Smckusick *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 52137549Smckusick } 52237549Smckusick return (error); 52337549Smckusick 52437549Smckusick } 52537549Smckusick #endif 52611576Ssam } 52711576Ssam return (0); 52811576Ssam } 52911576Ssam 53011576Ssam /* 53111576Ssam * Return interface configuration 53211576Ssam * of system. List may be used 53311576Ssam * in later ioctl's (above) to get 53411576Ssam * other information. 53511576Ssam */ 53612783Ssam /*ARGSUSED*/ 53711576Ssam ifconf(cmd, data) 53811576Ssam int cmd; 53911576Ssam caddr_t data; 54011576Ssam { 54111576Ssam register struct ifconf *ifc = (struct ifconf *)data; 54211576Ssam register struct ifnet *ifp = ifnet; 54318544Skarels register struct ifaddr *ifa; 54411630Ssam register char *cp, *ep; 54511630Ssam struct ifreq ifr, *ifrp; 54611576Ssam int space = ifc->ifc_len, error = 0; 54711576Ssam 54811630Ssam ifrp = ifc->ifc_req; 54911630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 55011576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 55111630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 55211630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 55311576Ssam ; 55411630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 55518544Skarels if ((ifa = ifp->if_addrlist) == 0) { 55618544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 55718544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 55818544Skarels if (error) 55918544Skarels break; 56018544Skarels space -= sizeof (ifr), ifrp++; 56118544Skarels } else 56218544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 56337549Smckusick register struct sockaddr *sa = ifa->ifa_addr; 56437549Smckusick #ifdef COMPAT_43 56537549Smckusick if (cmd == OSIOCGIFCONF) { 56637549Smckusick struct osockaddr *osa = 56737549Smckusick (struct osockaddr *)&ifr.ifr_addr; 56837549Smckusick ifr.ifr_addr = *sa; 56937549Smckusick osa->sa_family = sa->sa_family; 57037549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57137549Smckusick sizeof (ifr)); 57237549Smckusick ifrp++; 57337549Smckusick } else 57437549Smckusick #endif 57537549Smckusick if (sa->sa_len <= sizeof(*sa)) { 57637549Smckusick ifr.ifr_addr = *sa; 57737549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 57837549Smckusick sizeof (ifr)); 57937549Smckusick ifrp++; 58037549Smckusick } else { 58137549Smckusick space -= sa->sa_len - sizeof(*sa); 58237549Smckusick if (space < sizeof (ifr)) 58337549Smckusick break; 58437549Smckusick error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 58537549Smckusick sizeof (ifr.ifr_name)); 58637549Smckusick if (error == 0) 58737549Smckusick error = copyout((caddr_t)sa, 58837549Smckusick (caddr_t)&ifrp->ifr_addr, sa->sa_len); 58937549Smckusick ifrp = (struct ifreq *) 59037549Smckusick (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 59137549Smckusick } 59218544Skarels if (error) 59318544Skarels break; 59437549Smckusick space -= sizeof (ifr); 59518544Skarels } 59611576Ssam } 59711576Ssam ifc->ifc_len -= space; 59811576Ssam return (error); 59911576Ssam } 60040792Ssklower 60140792Ssklower static sprint_d(cp, n) 60240792Ssklower register char *cp; 60340792Ssklower u_short n; 60440792Ssklower { 60540792Ssklower register int q, m; 60640792Ssklower do { 60740792Ssklower if (n >= 10000) m = 10000; 60840792Ssklower else if (n >= 1000) m = 1000; 60940792Ssklower else if (n >= 100) m = 100; 61040792Ssklower else if (n >= 10) m = 10; 61140792Ssklower else m = 1; 61240792Ssklower q = n / m; 61340792Ssklower n -= m * q; 61440792Ssklower if (q > 9) q = 10; /* For crays with more than 100K interfaces */ 61540792Ssklower *cp++ = "0123456789Z"[q]; 61640792Ssklower } while (n > 0); 61740792Ssklower *cp++ = 0; 61840792Ssklower } 619