xref: /csrg-svn/sys/net/if.c (revision 18544)
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