1*13049Ssam /* if.c 4.29 83/06/12 */ 24944Swnj 34944Swnj #include "../h/param.h" 44944Swnj #include "../h/systm.h" 56333Ssam #include "../h/socket.h" 66582Ssam #include "../h/protosw.h" 7*13049Ssam #include "../h/dir.h" 8*13049Ssam #include "../h/user.h" 910872Ssam #include "../h/kernel.h" 1011576Ssam #include "../h/ioctl.h" 1111576Ssam #include "../h/errno.h" 1210872Ssam 134944Swnj #include "../net/if.h" 146333Ssam #include "../net/af.h" 154944Swnj 166207Swnj int ifqmaxlen = IFQ_MAXLEN; 176207Swnj 186333Ssam /* 196333Ssam * Network interface utility routines. 206333Ssam * 216333Ssam * Routines with if_ifwith* names take sockaddr *'s as 226333Ssam * parameters. Other routines take value parameters, 236333Ssam * e.g. if_ifwithnet takes the network number. 246333Ssam */ 256333Ssam 265206Swnj ifinit() 275206Swnj { 285206Swnj register struct ifnet *ifp; 295206Swnj 305206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 316207Swnj if (ifp->if_init) { 326333Ssam (*ifp->if_init)(ifp->if_unit); 336207Swnj if (ifp->if_snd.ifq_maxlen == 0) 346207Swnj ifp->if_snd.ifq_maxlen = ifqmaxlen; 356207Swnj } 368173Sroot if_slowtimo(); 375206Swnj } 385206Swnj 39*13049Ssam #ifdef vax 406333Ssam /* 416333Ssam * Call each interface on a Unibus reset. 426333Ssam */ 435206Swnj ifubareset(uban) 445206Swnj int uban; 455206Swnj { 465206Swnj register struct ifnet *ifp; 475206Swnj 485206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 498974Sroot if (ifp->if_reset) 508974Sroot (*ifp->if_reset)(uban); 515206Swnj } 528393Swnj #endif 535206Swnj 546333Ssam /* 556333Ssam * Attach an interface to the 566333Ssam * list of "active" interfaces. 576333Ssam */ 585160Swnj if_attach(ifp) 595160Swnj struct ifnet *ifp; 605160Swnj { 615698Swnj register struct ifnet **p = &ifnet; 625160Swnj 635698Swnj while (*p) 645698Swnj p = &((*p)->if_next); 655698Swnj *p = ifp; 665160Swnj } 675160Swnj 686333Ssam /* 696333Ssam * Locate an interface based on a complete address. 706333Ssam */ 714951Swnj /*ARGSUSED*/ 724951Swnj struct ifnet * 736333Ssam if_ifwithaddr(addr) 746333Ssam struct sockaddr *addr; 754944Swnj { 764944Swnj register struct ifnet *ifp; 774944Swnj 786333Ssam #define equal(a1, a2) \ 796333Ssam (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) 806333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 816333Ssam if (ifp->if_addr.sa_family != addr->sa_family) 826333Ssam continue; 836333Ssam if (equal(&ifp->if_addr, addr)) 844944Swnj break; 856333Ssam if ((ifp->if_flags & IFF_BROADCAST) && 866333Ssam equal(&ifp->if_broadaddr, addr)) 876333Ssam break; 886333Ssam } 894944Swnj return (ifp); 904944Swnj } 914944Swnj 926333Ssam /* 936333Ssam * Find an interface on a specific network. If many, choice 946333Ssam * is first found. 956333Ssam */ 964951Swnj struct ifnet * 976333Ssam if_ifwithnet(addr) 986333Ssam register struct sockaddr *addr; 994944Swnj { 1004944Swnj register struct ifnet *ifp; 1018393Swnj register u_int af = addr->sa_family; 1026619Ssam register int (*netmatch)(); 1034944Swnj 1046619Ssam if (af >= AF_MAX) 1056619Ssam return (0); 1066619Ssam netmatch = afswitch[af].af_netmatch; 1076333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 1086333Ssam if (af != ifp->if_addr.sa_family) 1096333Ssam continue; 1106333Ssam if ((*netmatch)(addr, &ifp->if_addr)) 1116333Ssam break; 1126333Ssam } 1136333Ssam return (ifp); 1146333Ssam } 1156333Ssam 1166333Ssam /* 1176333Ssam * As above, but parameter is network number. 1186333Ssam */ 1196333Ssam struct ifnet * 1206333Ssam if_ifonnetof(net) 1216333Ssam register int net; 1226333Ssam { 1236333Ssam register struct ifnet *ifp; 1246333Ssam 1254944Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 1264944Swnj if (ifp->if_net == net) 1274944Swnj break; 1284944Swnj return (ifp); 1294944Swnj } 1304944Swnj 1316333Ssam /* 1326333Ssam * Find an interface using a specific address family 1336333Ssam */ 1345083Swnj struct ifnet * 1356333Ssam if_ifwithaf(af) 1366333Ssam register int af; 1375083Swnj { 1386333Ssam register struct ifnet *ifp; 1395083Swnj 1406333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 1416333Ssam if (ifp->if_addr.sa_family == af) 1426333Ssam break; 1436333Ssam return (ifp); 1445083Swnj } 1455104Swnj 1466333Ssam /* 1476582Ssam * Mark an interface down and notify protocols of 1486582Ssam * the transition. 1499184Ssam * NOTE: must be called at splnet or eqivalent. 1506582Ssam */ 1516582Ssam if_down(ifp) 1526582Ssam register struct ifnet *ifp; 1536582Ssam { 1548173Sroot 1556582Ssam ifp->if_flags &= ~IFF_UP; 1566582Ssam pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr); 1576582Ssam } 1587264Ssam 1597264Ssam /* 1607264Ssam * Handle interface watchdog timer routines. Called 1617264Ssam * from softclock, we decrement timers (if set) and 1627264Ssam * call the appropriate interface routine on expiration. 1637264Ssam */ 1647264Ssam if_slowtimo() 1657264Ssam { 1667264Ssam register struct ifnet *ifp; 1677264Ssam 1689184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 1699184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 1709184Ssam continue; 1719184Ssam if (ifp->if_watchdog) 1727264Ssam (*ifp->if_watchdog)(ifp->if_unit); 1739184Ssam } 1748692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 1757264Ssam } 17611576Ssam 17711576Ssam /* 178*13049Ssam * Map interface name to 179*13049Ssam * interface structure pointer. 18011576Ssam */ 181*13049Ssam struct ifnet * 182*13049Ssam ifunit(name) 183*13049Ssam register char *name; 18411576Ssam { 185*13049Ssam register char *cp; 18611576Ssam register struct ifnet *ifp; 187*13049Ssam int unit; 18811576Ssam 189*13049Ssam for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 19011576Ssam if (*cp >= '0' && *cp <= '9') 19111576Ssam break; 192*13049Ssam if (*cp == '\0' || cp == name + IFNAMSIZ) 193*13049Ssam return ((struct ifnet *)0); 19411576Ssam unit = *cp - '0', *cp = 0; 19511576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 196*13049Ssam if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) 19711576Ssam continue; 19811576Ssam if (unit == ifp->if_unit) 199*13049Ssam break; 20011576Ssam } 201*13049Ssam return (ifp); 202*13049Ssam } 20311576Ssam 204*13049Ssam /* 205*13049Ssam * Interface ioctls. 206*13049Ssam */ 207*13049Ssam ifioctl(cmd, data) 208*13049Ssam int cmd; 209*13049Ssam caddr_t data; 210*13049Ssam { 211*13049Ssam register struct ifnet *ifp; 212*13049Ssam register struct ifreq *ifr; 213*13049Ssam 21411576Ssam switch (cmd) { 21511576Ssam 216*13049Ssam case SIOCGIFCONF: 217*13049Ssam return (ifconf(cmd, data)); 218*13049Ssam 219*13049Ssam case SIOCSIFADDR: 220*13049Ssam case SIOCSIFFLAGS: 221*13049Ssam case SIOCSIFDSTADDR: 222*13049Ssam if (!suser()) 223*13049Ssam return (u.u_error); 224*13049Ssam break; 225*13049Ssam } 226*13049Ssam ifr = (struct ifreq *)data; 227*13049Ssam ifp = ifunit(ifr->ifr_name); 228*13049Ssam if (ifp == 0) 229*13049Ssam return (ENXIO); 230*13049Ssam switch (cmd) { 231*13049Ssam 23211576Ssam case SIOCGIFADDR: 23311576Ssam ifr->ifr_addr = ifp->if_addr; 23411576Ssam break; 23511576Ssam 23611576Ssam case SIOCGIFDSTADDR: 23711576Ssam if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 23811576Ssam return (EINVAL); 23911576Ssam ifr->ifr_dstaddr = ifp->if_dstaddr; 24011576Ssam break; 24111576Ssam 24211576Ssam case SIOCGIFFLAGS: 24311576Ssam ifr->ifr_flags = ifp->if_flags; 24411576Ssam break; 24511576Ssam 24611576Ssam default: 247*13049Ssam if (ifp->if_ioctl == 0) 248*13049Ssam return (EOPNOTSUPP); 249*13049Ssam return ((*ifp->if_ioctl)(cmd, data)); 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; 26711630Ssam register char *cp, *ep; 26811630Ssam struct ifreq ifr, *ifrp; 26911576Ssam int space = ifc->ifc_len, error = 0; 27011576Ssam 27111630Ssam ifrp = ifc->ifc_req; 27211630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 27311576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 27411630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 27511630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 27611576Ssam ; 27711630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 27811576Ssam ifr.ifr_addr = ifp->if_addr; 27911630Ssam error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 28011576Ssam if (error) 28111576Ssam break; 28211630Ssam space -= sizeof (ifr), ifrp++; 28311576Ssam } 28411576Ssam ifc->ifc_len -= space; 28511576Ssam return (error); 28611576Ssam } 287