1*18544Skarels /* if.c 6.6 85/04/01 */ 24944Swnj 317036Sbloom #include "param.h" 417036Sbloom #include "systm.h" 517036Sbloom #include "socket.h" 6*18544Skarels #include "socketvar.h" 717036Sbloom #include "protosw.h" 817036Sbloom #include "dir.h" 917036Sbloom #include "user.h" 1017036Sbloom #include "kernel.h" 1117036Sbloom #include "ioctl.h" 1217036Sbloom #include "errno.h" 1310872Ssam 1417036Sbloom #include "if.h" 1517036Sbloom #include "af.h" 164944Swnj 1716220Skarels #include "ether.h" 1816220Skarels 196207Swnj int ifqmaxlen = IFQ_MAXLEN; 206207Swnj 216333Ssam /* 226333Ssam * Network interface utility routines. 236333Ssam * 24*18544Skarels * Routines with ifa_ifwith* names take sockaddr *'s as 25*18544Skarels * parameters. 266333Ssam */ 276333Ssam 285206Swnj ifinit() 295206Swnj { 305206Swnj register struct ifnet *ifp; 315206Swnj 325206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 336207Swnj if (ifp->if_init) { 346333Ssam (*ifp->if_init)(ifp->if_unit); 356207Swnj if (ifp->if_snd.ifq_maxlen == 0) 366207Swnj ifp->if_snd.ifq_maxlen = ifqmaxlen; 376207Swnj } 388173Sroot if_slowtimo(); 395206Swnj } 405206Swnj 4113049Ssam #ifdef vax 426333Ssam /* 436333Ssam * Call each interface on a Unibus reset. 446333Ssam */ 455206Swnj ifubareset(uban) 465206Swnj int uban; 475206Swnj { 485206Swnj register struct ifnet *ifp; 495206Swnj 505206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 518974Sroot if (ifp->if_reset) 5215116Ssam (*ifp->if_reset)(ifp->if_unit, uban); 535206Swnj } 548393Swnj #endif 555206Swnj 566333Ssam /* 576333Ssam * Attach an interface to the 586333Ssam * list of "active" interfaces. 596333Ssam */ 605160Swnj if_attach(ifp) 615160Swnj struct ifnet *ifp; 625160Swnj { 635698Swnj register struct ifnet **p = &ifnet; 645160Swnj 655698Swnj while (*p) 665698Swnj p = &((*p)->if_next); 675698Swnj *p = ifp; 685160Swnj } 695160Swnj 706333Ssam /* 716333Ssam * Locate an interface based on a complete address. 726333Ssam */ 734951Swnj /*ARGSUSED*/ 74*18544Skarels struct ifaddr * 75*18544Skarels ifa_ifwithaddr(addr) 766333Ssam struct sockaddr *addr; 774944Swnj { 784944Swnj register struct ifnet *ifp; 79*18544Skarels register struct ifaddr *ifa; 804944Swnj 816333Ssam #define equal(a1, a2) \ 826333Ssam (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) 83*18544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 84*18544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 85*18544Skarels if (ifa->ifa_addr.sa_family != addr->sa_family) 866333Ssam continue; 87*18544Skarels if (equal(&ifa->ifa_addr, addr)) 88*18544Skarels return (ifa); 896333Ssam if ((ifp->if_flags & IFF_BROADCAST) && 90*18544Skarels equal(&ifa->ifa_broadaddr, addr)) 91*18544Skarels return (ifa); 926333Ssam } 93*18544Skarels return ((struct ifaddr *)0); 944944Swnj } 954944Swnj 966333Ssam /* 976333Ssam * Find an interface on a specific network. If many, choice 986333Ssam * is first found. 996333Ssam */ 100*18544Skarels struct ifaddr * 101*18544Skarels ifa_ifwithnet(addr) 1026333Ssam register struct sockaddr *addr; 1034944Swnj { 1044944Swnj register struct ifnet *ifp; 105*18544Skarels register struct ifaddr *ifa; 1068393Swnj register u_int af = addr->sa_family; 1076619Ssam register int (*netmatch)(); 1084944Swnj 1096619Ssam if (af >= AF_MAX) 1106619Ssam return (0); 1116619Ssam netmatch = afswitch[af].af_netmatch; 112*18544Skarels for (ifp = ifnet; ifp; ifp = ifp->if_next) 113*18544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 114*18544Skarels if (ifa->ifa_addr.sa_family != addr->sa_family) 1156333Ssam continue; 116*18544Skarels if ((*netmatch)(&ifa->ifa_addr, addr)) 117*18544Skarels return (ifa); 1186333Ssam } 119*18544Skarels return ((struct ifaddr *)0); 1206333Ssam } 1216333Ssam 1226333Ssam /* 1236333Ssam * Find an interface using a specific address family 1246333Ssam */ 125*18544Skarels struct ifaddr * 126*18544Skarels ifa_ifwithaf(af) 1276333Ssam register int af; 1285083Swnj { 1296333Ssam register struct ifnet *ifp; 130*18544Skarels register struct ifaddr *ifa; 1315083Swnj 1326333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 133*18544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 134*18544Skarels if (ifa->ifa_addr.sa_family == af) 135*18544Skarels return (ifa); 136*18544Skarels return ((struct ifaddr *)0); 1375083Swnj } 1385104Swnj 1396333Ssam /* 1406582Ssam * Mark an interface down and notify protocols of 1416582Ssam * the transition. 1429184Ssam * NOTE: must be called at splnet or eqivalent. 1436582Ssam */ 1446582Ssam if_down(ifp) 1456582Ssam register struct ifnet *ifp; 1466582Ssam { 147*18544Skarels register struct ifaddr *ifa; 1488173Sroot 1496582Ssam ifp->if_flags &= ~IFF_UP; 150*18544Skarels for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 151*18544Skarels pfctlinput(PRC_IFDOWN, (caddr_t)&ifa->ifa_addr); 1526582Ssam } 1537264Ssam 1547264Ssam /* 1557264Ssam * Handle interface watchdog timer routines. Called 1567264Ssam * from softclock, we decrement timers (if set) and 1577264Ssam * call the appropriate interface routine on expiration. 1587264Ssam */ 1597264Ssam if_slowtimo() 1607264Ssam { 1617264Ssam register struct ifnet *ifp; 1627264Ssam 1639184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 1649184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 1659184Ssam continue; 1669184Ssam if (ifp->if_watchdog) 1677264Ssam (*ifp->if_watchdog)(ifp->if_unit); 1689184Ssam } 1698692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 1707264Ssam } 17111576Ssam 17211576Ssam /* 17313049Ssam * Map interface name to 17413049Ssam * interface structure pointer. 17511576Ssam */ 17613049Ssam struct ifnet * 17713049Ssam ifunit(name) 17813049Ssam register char *name; 17911576Ssam { 18013049Ssam register char *cp; 18111576Ssam register struct ifnet *ifp; 18213049Ssam int unit; 18311576Ssam 18413049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 18511576Ssam if (*cp >= '0' && *cp <= '9') 18611576Ssam break; 18713049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 18813049Ssam return ((struct ifnet *)0); 18916135Skarels unit = *cp - '0'; 19011576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 19113049Ssam if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) 19211576Ssam continue; 19311576Ssam if (unit == ifp->if_unit) 19413049Ssam break; 19511576Ssam } 19613049Ssam return (ifp); 19713049Ssam } 19811576Ssam 19913049Ssam /* 20013049Ssam * Interface ioctls. 20113049Ssam */ 202*18544Skarels ifioctl(so, cmd, data) 203*18544Skarels struct socket *so; 20413049Ssam int cmd; 20513049Ssam caddr_t data; 20613049Ssam { 20713049Ssam register struct ifnet *ifp; 20813049Ssam register struct ifreq *ifr; 20913049Ssam 21011576Ssam switch (cmd) { 21111576Ssam 21213049Ssam case SIOCGIFCONF: 21313049Ssam return (ifconf(cmd, data)); 21413049Ssam 21516220Skarels #if defined(INET) && NETHER > 0 21616220Skarels case SIOCSARP: 21716220Skarels case SIOCDARP: 21816220Skarels if (!suser()) 21916220Skarels return (u.u_error); 22016220Skarels /* FALL THROUGH */ 22116220Skarels case SIOCGARP: 22216220Skarels return (arpioctl(cmd, data)); 22316220Skarels #endif 22413049Ssam } 22513049Ssam ifr = (struct ifreq *)data; 22613049Ssam ifp = ifunit(ifr->ifr_name); 22713049Ssam if (ifp == 0) 22813049Ssam return (ENXIO); 22913049Ssam switch (cmd) { 23013049Ssam 23111576Ssam case SIOCGIFFLAGS: 23211576Ssam ifr->ifr_flags = ifp->if_flags; 23311576Ssam break; 23411576Ssam 23513053Ssam case SIOCSIFFLAGS: 23613053Ssam if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 23713053Ssam int s = splimp(); 23813053Ssam if_down(ifp); 23913053Ssam splx(s); 24013053Ssam } 241*18544Skarels ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 242*18544Skarels (ifr->ifr_flags &~ IFF_CANTCHANGE); 24313053Ssam break; 24413053Ssam 24511576Ssam default: 246*18544Skarels if (so->so_proto == 0) 24713049Ssam return (EOPNOTSUPP); 248*18544Skarels return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 249*18544Skarels cmd, data, ifp)); 25011576Ssam } 25111576Ssam return (0); 25211576Ssam } 25311576Ssam 25411576Ssam /* 25511576Ssam * Return interface configuration 25611576Ssam * of system. List may be used 25711576Ssam * in later ioctl's (above) to get 25811576Ssam * other information. 25911576Ssam */ 26012783Ssam /*ARGSUSED*/ 26111576Ssam ifconf(cmd, data) 26211576Ssam int cmd; 26311576Ssam caddr_t data; 26411576Ssam { 26511576Ssam register struct ifconf *ifc = (struct ifconf *)data; 26611576Ssam register struct ifnet *ifp = ifnet; 267*18544Skarels register struct ifaddr *ifa; 26811630Ssam register char *cp, *ep; 26911630Ssam struct ifreq ifr, *ifrp; 27011576Ssam int space = ifc->ifc_len, error = 0; 27111576Ssam 27211630Ssam ifrp = ifc->ifc_req; 27311630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 27411576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 27511630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 27611630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 27711576Ssam ; 27811630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 279*18544Skarels if ((ifa = ifp->if_addrlist) == 0) { 280*18544Skarels bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 281*18544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 282*18544Skarels if (error) 283*18544Skarels break; 284*18544Skarels space -= sizeof (ifr), ifrp++; 285*18544Skarels } else 286*18544Skarels for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 287*18544Skarels ifr.ifr_addr = ifa->ifa_addr; 288*18544Skarels error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 289*18544Skarels if (error) 290*18544Skarels break; 291*18544Skarels space -= sizeof (ifr), ifrp++; 292*18544Skarels } 29311576Ssam } 29411576Ssam ifc->ifc_len -= space; 29511576Ssam return (error); 29611576Ssam } 297