1*11630Ssam /* if.c 4.27 83/03/19 */ 24944Swnj 34944Swnj #include "../h/param.h" 44944Swnj #include "../h/systm.h" 56333Ssam #include "../h/socket.h" 66582Ssam #include "../h/protosw.h" 710872Ssam #include "../h/time.h" 810872Ssam #include "../h/kernel.h" 911576Ssam #include "../h/ioctl.h" 1011576Ssam #include "../h/errno.h" 1110872Ssam 124944Swnj #include "../net/if.h" 136333Ssam #include "../net/af.h" 144944Swnj 156207Swnj int ifqmaxlen = IFQ_MAXLEN; 166207Swnj 176333Ssam /* 186333Ssam * Network interface utility routines. 196333Ssam * 206333Ssam * Routines with if_ifwith* names take sockaddr *'s as 216333Ssam * parameters. Other routines take value parameters, 226333Ssam * e.g. if_ifwithnet takes the network number. 236333Ssam */ 246333Ssam 255206Swnj ifinit() 265206Swnj { 275206Swnj register struct ifnet *ifp; 285206Swnj 295206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 306207Swnj if (ifp->if_init) { 316333Ssam (*ifp->if_init)(ifp->if_unit); 326207Swnj if (ifp->if_snd.ifq_maxlen == 0) 336207Swnj ifp->if_snd.ifq_maxlen = ifqmaxlen; 346207Swnj } 358173Sroot if_slowtimo(); 365206Swnj } 375206Swnj 388393Swnj #if vax 396333Ssam /* 406333Ssam * Call each interface on a Unibus reset. 416333Ssam */ 425206Swnj ifubareset(uban) 435206Swnj int uban; 445206Swnj { 455206Swnj register struct ifnet *ifp; 465206Swnj 475206Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 488974Sroot if (ifp->if_reset) 498974Sroot (*ifp->if_reset)(uban); 505206Swnj } 518393Swnj #endif 525206Swnj 536333Ssam /* 546333Ssam * Attach an interface to the 556333Ssam * list of "active" interfaces. 566333Ssam */ 575160Swnj if_attach(ifp) 585160Swnj struct ifnet *ifp; 595160Swnj { 605698Swnj register struct ifnet **p = &ifnet; 615160Swnj 625698Swnj while (*p) 635698Swnj p = &((*p)->if_next); 645698Swnj *p = ifp; 655160Swnj } 665160Swnj 676333Ssam /* 686333Ssam * Locate an interface based on a complete address. 696333Ssam */ 704951Swnj /*ARGSUSED*/ 714951Swnj struct ifnet * 726333Ssam if_ifwithaddr(addr) 736333Ssam struct sockaddr *addr; 744944Swnj { 754944Swnj register struct ifnet *ifp; 764944Swnj 776333Ssam #define equal(a1, a2) \ 786333Ssam (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) 796333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 806333Ssam if (ifp->if_addr.sa_family != addr->sa_family) 816333Ssam continue; 826333Ssam if (equal(&ifp->if_addr, addr)) 834944Swnj break; 846333Ssam if ((ifp->if_flags & IFF_BROADCAST) && 856333Ssam equal(&ifp->if_broadaddr, addr)) 866333Ssam break; 876333Ssam } 884944Swnj return (ifp); 894944Swnj } 904944Swnj 916333Ssam /* 926333Ssam * Find an interface on a specific network. If many, choice 936333Ssam * is first found. 946333Ssam */ 954951Swnj struct ifnet * 966333Ssam if_ifwithnet(addr) 976333Ssam register struct sockaddr *addr; 984944Swnj { 994944Swnj register struct ifnet *ifp; 1008393Swnj register u_int af = addr->sa_family; 1016619Ssam register int (*netmatch)(); 1024944Swnj 1036619Ssam if (af >= AF_MAX) 1046619Ssam return (0); 1056619Ssam netmatch = afswitch[af].af_netmatch; 1066333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 1076333Ssam if (af != ifp->if_addr.sa_family) 1086333Ssam continue; 1096333Ssam if ((*netmatch)(addr, &ifp->if_addr)) 1106333Ssam break; 1116333Ssam } 1126333Ssam return (ifp); 1136333Ssam } 1146333Ssam 1156333Ssam /* 1166333Ssam * As above, but parameter is network number. 1176333Ssam */ 1186333Ssam struct ifnet * 1196333Ssam if_ifonnetof(net) 1206333Ssam register int net; 1216333Ssam { 1226333Ssam register struct ifnet *ifp; 1236333Ssam 1244944Swnj for (ifp = ifnet; ifp; ifp = ifp->if_next) 1254944Swnj if (ifp->if_net == net) 1264944Swnj break; 1274944Swnj return (ifp); 1284944Swnj } 1294944Swnj 1306333Ssam /* 1316333Ssam * Find an interface using a specific address family 1326333Ssam */ 1335083Swnj struct ifnet * 1346333Ssam if_ifwithaf(af) 1356333Ssam register int af; 1365083Swnj { 1376333Ssam register struct ifnet *ifp; 1385083Swnj 1396333Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) 1406333Ssam if (ifp->if_addr.sa_family == af) 1416333Ssam break; 1426333Ssam return (ifp); 1435083Swnj } 1445104Swnj 1456333Ssam /* 1466582Ssam * Mark an interface down and notify protocols of 1476582Ssam * the transition. 1489184Ssam * NOTE: must be called at splnet or eqivalent. 1496582Ssam */ 1506582Ssam if_down(ifp) 1516582Ssam register struct ifnet *ifp; 1526582Ssam { 1538173Sroot 1546582Ssam ifp->if_flags &= ~IFF_UP; 1556582Ssam pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr); 1566582Ssam } 1577264Ssam 1587264Ssam /* 1597264Ssam * Handle interface watchdog timer routines. Called 1607264Ssam * from softclock, we decrement timers (if set) and 1617264Ssam * call the appropriate interface routine on expiration. 1627264Ssam */ 1637264Ssam if_slowtimo() 1647264Ssam { 1657264Ssam register struct ifnet *ifp; 1667264Ssam 1679184Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 1689184Ssam if (ifp->if_timer == 0 || --ifp->if_timer) 1699184Ssam continue; 1709184Ssam if (ifp->if_watchdog) 1717264Ssam (*ifp->if_watchdog)(ifp->if_unit); 1729184Ssam } 1738692Sroot timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 1747264Ssam } 17511576Ssam 17611576Ssam /* 17711576Ssam * Service a socket ioctl request directed 17811576Ssam * to an interface. 17911576Ssam */ 18011576Ssam ifrequest(cmd, data) 18111576Ssam int cmd; 18211576Ssam caddr_t data; 18311576Ssam { 18411576Ssam register struct ifnet *ifp; 18511576Ssam register struct ifreq *ifr; 18611576Ssam register char *cp; 18711576Ssam int unit, s; 18811576Ssam 18911576Ssam ifr = (struct ifreq *)data; 19011576Ssam for (cp = ifr->ifr_name; *cp; cp++) 19111576Ssam if (*cp >= '0' && *cp <= '9') 19211576Ssam break; 19311576Ssam if (*cp == 0) 19411576Ssam return (ENXIO); /* couldn't find unit */ 19511576Ssam unit = *cp - '0', *cp = 0; 19611576Ssam for (ifp = ifnet; ifp; ifp = ifp->if_next) { 19711576Ssam if (bcmp(ifp->if_name, ifr->ifr_name, cp - ifr->ifr_name)) 19811576Ssam continue; 19911576Ssam if (unit == ifp->if_unit) 20011576Ssam goto found; 20111576Ssam } 20211576Ssam return (ENXIO); 20311576Ssam 20411576Ssam found: 20511576Ssam switch (cmd) { 20611576Ssam 20711576Ssam case SIOCGIFADDR: 20811576Ssam ifr->ifr_addr = ifp->if_addr; 20911576Ssam break; 21011576Ssam 21111576Ssam case SIOCSIFADDR: 21211576Ssam if_rtinit(ifp, -1); /* delete previous route */ 21311576Ssam s = splimp(); 21411576Ssam ifp->if_addr = ifr->ifr_addr; 21511576Ssam (*ifp->if_init)(unit); 21611576Ssam splx(s); 21711576Ssam break; 21811576Ssam 21911576Ssam case SIOCGIFDSTADDR: 22011576Ssam if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 22111576Ssam return (EINVAL); 22211576Ssam ifr->ifr_dstaddr = ifp->if_dstaddr; 22311576Ssam break; 22411576Ssam 22511576Ssam case SIOCSIFDSTADDR: 22611576Ssam if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 22711576Ssam return (EINVAL); 22811576Ssam s = splimp(); 22911576Ssam ifp->if_dstaddr = ifr->ifr_dstaddr; 23011576Ssam splx(s); 23111576Ssam break; 23211576Ssam 23311576Ssam case SIOCGIFFLAGS: 23411576Ssam ifr->ifr_flags = ifp->if_flags; 23511576Ssam break; 23611576Ssam 23711576Ssam case SIOCSIFFLAGS: 23811576Ssam if ((ifr->ifr_flags & IFF_UP) == 0 && 23911576Ssam (ifp->if_flags & IFF_UP)) { 24011576Ssam s = splimp(); 24111576Ssam if_down(ifp); 24211576Ssam splx(s); 24311576Ssam } 24411576Ssam ifp->if_flags = ifr->ifr_flags; 24511576Ssam break; 24611576Ssam 24711576Ssam default: 24811576Ssam return (EINVAL); 24911576Ssam } 25011576Ssam return (0); 25111576Ssam } 25211576Ssam 25311576Ssam /* 25411576Ssam * Return interface configuration 25511576Ssam * of system. List may be used 25611576Ssam * in later ioctl's (above) to get 25711576Ssam * other information. 25811576Ssam */ 25911576Ssam ifconf(cmd, data) 26011576Ssam int cmd; 26111576Ssam caddr_t data; 26211576Ssam { 26311576Ssam register struct ifconf *ifc = (struct ifconf *)data; 26411576Ssam register struct ifnet *ifp = ifnet; 265*11630Ssam register char *cp, *ep; 266*11630Ssam struct ifreq ifr, *ifrp; 26711576Ssam int space = ifc->ifc_len, error = 0; 26811576Ssam 269*11630Ssam ifrp = ifc->ifc_req; 270*11630Ssam ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 27111576Ssam for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 272*11630Ssam bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 273*11630Ssam for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 27411576Ssam ; 275*11630Ssam *cp++ = '0' + ifp->if_unit; *cp = '\0'; 27611576Ssam ifr.ifr_addr = ifp->if_addr; 277*11630Ssam error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 27811576Ssam if (error) 27911576Ssam break; 280*11630Ssam space -= sizeof (ifr), ifrp++; 28111576Ssam } 28211576Ssam ifc->ifc_len -= space; 28311576Ssam return (error); 28411576Ssam } 285