xref: /csrg-svn/sys/net/if.c (revision 6582)
1*6582Ssam /*	if.c	4.14	82/04/24	*/
24944Swnj 
34944Swnj #include "../h/param.h"
44944Swnj #include "../h/systm.h"
56333Ssam #include "../h/socket.h"
6*6582Ssam #include "../h/protosw.h"
75083Swnj #include "../net/in.h"
85083Swnj #include "../net/in_systm.h"
94944Swnj #include "../net/if.h"
106333Ssam #include "../net/af.h"
114944Swnj 
126207Swnj int	ifqmaxlen = IFQ_MAXLEN;
136207Swnj 
146333Ssam /*
156333Ssam  * Network interface utility routines.
166333Ssam  *
176333Ssam  * Routines with if_ifwith* names take sockaddr *'s as
186333Ssam  * parameters.  Other routines take value parameters,
196333Ssam  * e.g. if_ifwithnet takes the network number.
206333Ssam  */
216333Ssam 
225206Swnj ifinit()
235206Swnj {
245206Swnj 	register struct ifnet *ifp;
255206Swnj 
265206Swnj 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
276207Swnj 		if (ifp->if_init) {
286333Ssam 			(*ifp->if_init)(ifp->if_unit);
296207Swnj 			if (ifp->if_snd.ifq_maxlen == 0)
306207Swnj 				ifp->if_snd.ifq_maxlen = ifqmaxlen;
316207Swnj 		}
325206Swnj }
335206Swnj 
346333Ssam /*
356333Ssam  * Call each interface on a Unibus reset.
366333Ssam  */
375206Swnj ifubareset(uban)
385206Swnj 	int uban;
395206Swnj {
405206Swnj 	register struct ifnet *ifp;
415206Swnj 
425206Swnj 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
435206Swnj 		if (ifp->if_ubareset)
445206Swnj 			(*ifp->if_ubareset)(uban);
455206Swnj }
465206Swnj 
476333Ssam /*
486333Ssam  * Attach an interface to the
496333Ssam  * list of "active" interfaces.
506333Ssam  */
515160Swnj if_attach(ifp)
525160Swnj 	struct ifnet *ifp;
535160Swnj {
545698Swnj 	register struct ifnet **p = &ifnet;
555160Swnj 
565160Swnj COUNT(IF_ATTACH);
575698Swnj 	while (*p)
585698Swnj 		p = &((*p)->if_next);
595698Swnj 	*p = ifp;
605160Swnj }
615160Swnj 
626333Ssam /*
636333Ssam  * Locate an interface based on a complete address.
646333Ssam  */
654951Swnj /*ARGSUSED*/
664951Swnj struct ifnet *
676333Ssam if_ifwithaddr(addr)
686333Ssam 	struct sockaddr *addr;
694944Swnj {
704944Swnj 	register struct ifnet *ifp;
714944Swnj 
724951Swnj COUNT(IF_IFWITHADDR);
736333Ssam #define	equal(a1, a2) \
746333Ssam 	(bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
756333Ssam 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
766333Ssam 		if (ifp->if_addr.sa_family != addr->sa_family)
776333Ssam 			continue;
786333Ssam 		if (equal(&ifp->if_addr, addr))
794944Swnj 			break;
806333Ssam 		if ((ifp->if_flags & IFF_BROADCAST) &&
816333Ssam 		    equal(&ifp->if_broadaddr, addr))
826333Ssam 			break;
836333Ssam 	}
844944Swnj 	return (ifp);
854944Swnj }
864944Swnj 
876333Ssam /*
886333Ssam  * Find an interface on a specific network.  If many, choice
896333Ssam  * is first found.
906333Ssam  */
914951Swnj struct ifnet *
926333Ssam if_ifwithnet(addr)
936333Ssam 	register struct sockaddr *addr;
944944Swnj {
954944Swnj 	register struct ifnet *ifp;
966333Ssam 	register int af = addr->sa_family;
976333Ssam 	register int (*netmatch)() = afswitch[af].af_netmatch;
984944Swnj 
996333Ssam 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
1006333Ssam 		if (af != ifp->if_addr.sa_family)
1016333Ssam 			continue;
1026333Ssam 		if ((*netmatch)(addr, &ifp->if_addr))
1036333Ssam 			break;
1046333Ssam 	}
1056333Ssam 	return (ifp);
1066333Ssam }
1076333Ssam 
1086333Ssam /*
1096333Ssam  * As above, but parameter is network number.
1106333Ssam  */
1116333Ssam struct ifnet *
1126333Ssam if_ifonnetof(net)
1136333Ssam 	register int net;
1146333Ssam {
1156333Ssam 	register struct ifnet *ifp;
1166333Ssam 
1174944Swnj 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
1184944Swnj 		if (ifp->if_net == net)
1194944Swnj 			break;
1204944Swnj 	return (ifp);
1214944Swnj }
1224944Swnj 
1236333Ssam /*
1246333Ssam  * Find an interface using a specific address family
1256333Ssam  */
1265083Swnj struct ifnet *
1276333Ssam if_ifwithaf(af)
1286333Ssam 	register int af;
1295083Swnj {
1306333Ssam 	register struct ifnet *ifp;
1315083Swnj 
1326333Ssam 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
1336333Ssam 		if (ifp->if_addr.sa_family == af)
1346333Ssam 			break;
1356333Ssam 	return (ifp);
1365083Swnj }
1375104Swnj 
1386333Ssam /*
139*6582Ssam  * Mark an interface down and notify protocols of
140*6582Ssam  * the transition.
141*6582Ssam  */
142*6582Ssam if_down(ifp)
143*6582Ssam 	register struct ifnet *ifp;
144*6582Ssam {
145*6582Ssam 	ifp->if_flags &= ~IFF_UP;
146*6582Ssam 	pfctlinput(PRC_IFDOWN, (caddr_t)&ifp->if_addr);
147*6582Ssam }
148*6582Ssam 
149*6582Ssam /*
1506333Ssam  * Formulate an Internet address from network + host.  Used in
1516333Ssam  * building addresses stored in the ifnet structure.
1526333Ssam  */
1535104Swnj struct in_addr
1545104Swnj if_makeaddr(net, host)
1555104Swnj 	int net, host;
1565104Swnj {
1575104Swnj 	u_long addr;
1585104Swnj 
1595104Swnj 	if (net < 128)
1605206Swnj 		addr = (net << 24) | host;
1615104Swnj 	else if (net < 65536)
1625206Swnj 		addr = (net << 16) | host;
1635104Swnj 	else
1645206Swnj 		addr = (net << 8) | host;
1655685Ssam #ifdef vax
1665104Swnj 	addr = htonl(addr);
1675685Ssam #endif
1685104Swnj 	return (*(struct in_addr *)&addr);
1695104Swnj }
1706363Ssam 
1716363Ssam /*
1726363Ssam  * Initialize an interface's routing
1736363Ssam  * table entry according to the network.
1746363Ssam  * INTERNET SPECIFIC.
1756363Ssam  */
1766363Ssam if_rtinit(ifp, flags)
1776363Ssam 	register struct ifnet *ifp;
1786363Ssam 	int flags;
1796363Ssam {
1806363Ssam 	struct sockaddr_in sin;
1816363Ssam 
1826363Ssam 	if (ifp->if_flags & IFF_ROUTE)
1836363Ssam 		return;
1846363Ssam 	bzero((caddr_t)&sin, sizeof (sin));
1856363Ssam 	sin.sin_family = AF_INET;
1866363Ssam 	sin.sin_addr = if_makeaddr(ifp->if_net, 0);
1876377Ssam 	rtinit(&sin, &ifp->if_addr, flags);
1886363Ssam }
189