xref: /csrg-svn/sbin/XNSrouted/startup.c (revision 26170)
124322Ssklower /*
224322Ssklower  * Copyright (c) 1985 Regents of the University of California.
324322Ssklower  * All rights reserved.  The Berkeley software License Agreement
424322Ssklower  * specifies the terms and conditions for redistribution.
524322Ssklower  *
624322Ssklower  * Includes material written at Cornell University by Bill Nesheim,
724322Ssklower  * by permission of the author.
824322Ssklower  */
924322Ssklower 
1024322Ssklower 
1124312Ssklower #ifndef lint
12*26170Ssklower static char sccsid[] = "@(#)startup.c	5.5 (Berkeley) 02/14/86";
1324322Ssklower #endif not lint
1424312Ssklower 
1524312Ssklower /*
1624312Ssklower  * Routing Table Management Daemon
1724312Ssklower  */
1824312Ssklower #include "defs.h"
1924312Ssklower #include <sys/ioctl.h>
2024312Ssklower #include <net/if.h>
2124312Ssklower #include <nlist.h>
2224317Ssklower #include <syslog.h>
2324312Ssklower 
2424312Ssklower struct	interface *ifnet;
2524312Ssklower int	lookforinterfaces = 1;
2624312Ssklower int	performnlist = 1;
27*26170Ssklower int	gateway = 0;
2824312Ssklower int	externalinterfaces = 0;		/* # of remote and local interfaces */
2924312Ssklower char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3024312Ssklower 
3124312Ssklower 
3224312Ssklower /*
3324317Ssklower  * Find the network interfaces which have configured themselves.
3424317Ssklower  * If the interface is present but not yet up (for example an
3524312Ssklower  * ARPANET IMP), set the lookforinterfaces flag so we'll
3624312Ssklower  * come back later and look again.
3724312Ssklower  */
3824312Ssklower ifinit()
3924312Ssklower {
4024317Ssklower 	struct interface ifs, *ifp;
4124317Ssklower 	int s, n;
4224317Ssklower         struct ifconf ifc;
4324874Ssklower 	char buf[(sizeof (struct ifreq ) * 20)];
4424317Ssklower         struct ifreq ifreq, *ifr;
4524317Ssklower 	u_long i;
4624312Ssklower 
4724317Ssklower 	if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) {
4824317Ssklower 		syslog(LOG_ERR, "socket: %m");
4924317Ssklower 		exit(1);
5024312Ssklower 	}
5124317Ssklower         ifc.ifc_len = sizeof (buf);
5224317Ssklower         ifc.ifc_buf = buf;
5324317Ssklower         if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
5424317Ssklower                 syslog(LOG_ERR, "ioctl (get interface configuration)");
5524317Ssklower 		close(s);
5624317Ssklower                 return (0);
5724317Ssklower         }
5824317Ssklower         ifr = ifc.ifc_req;
5924312Ssklower 	lookforinterfaces = 0;
6024317Ssklower         for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) {
6124317Ssklower 		bzero((char *)&ifs, sizeof(ifs));
6224317Ssklower 		ifs.int_addr = ifr->ifr_addr;
6324317Ssklower 		ifreq = *ifr;
6424317Ssklower                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
6524317Ssklower                         syslog(LOG_ERR, "ioctl (get interface flags)");
6624317Ssklower                         continue;
6724317Ssklower                 }
6824317Ssklower 		ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
6924317Ssklower 		if ((ifs.int_flags & IFF_UP) == 0 ||
7024317Ssklower 		    ifr->ifr_addr.sa_family == AF_UNSPEC) {
7124312Ssklower 			lookforinterfaces = 1;
7224312Ssklower 			continue;
7324312Ssklower 		}
7424317Ssklower 		if (ifs.int_addr.sa_family != AF_NS)
7524317Ssklower 			continue;
7624317Ssklower                 if (ifs.int_flags & IFF_POINTOPOINT) {
7724317Ssklower                         if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
7824874Ssklower                                 syslog(LOG_ERR, "ioctl (get dstaddr): %m");
7924317Ssklower                                 continue;
8024317Ssklower 			}
8124317Ssklower 			ifs.int_dstaddr = ifreq.ifr_dstaddr;
8224312Ssklower 		}
8324317Ssklower                 if (ifs.int_flags & IFF_BROADCAST) {
8424317Ssklower                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
8524874Ssklower                                 syslog(LOG_ERR, "ioctl (get broadaddr: %m");
8624317Ssklower                                 continue;
8724317Ssklower                         }
8824317Ssklower 			ifs.int_broadaddr = ifreq.ifr_broadaddr;
8924317Ssklower 		}
90*26170Ssklower 		/*
91*26170Ssklower 		 * already known to us?
92*26170Ssklower 		 * what makes a POINTOPOINT if unique is its dst addr,
93*26170Ssklower 		 * NOT its source address
94*26170Ssklower 		 */
95*26170Ssklower 		if ( ((ifs.int_flags & IFF_POINTOPOINT) &&
96*26170Ssklower 			if_ifwithdstaddr(&ifs.int_dstaddr)) ||
97*26170Ssklower 			( ((ifs.int_flags & IFF_POINTOPOINT) == 0) &&
98*26170Ssklower 			if_ifwithaddr(&ifs.int_addr)))
99*26170Ssklower 			continue;
10024317Ssklower 		/* no one cares about software loopback interfaces */
101*26170Ssklower 		if (strncmp(ifr->ifr_name,"lo", 2)==0)
10224317Ssklower 			continue;
10324312Ssklower 		ifp = (struct interface *)malloc(sizeof (struct interface));
10424312Ssklower 		if (ifp == 0) {
10524874Ssklower 			syslog(LOG_ERR,"XNSrouted: out of memory\n");
10624312Ssklower 			break;
10724312Ssklower 		}
10824317Ssklower 		*ifp = ifs;
10924312Ssklower 		/*
11024312Ssklower 		 * Count the # of directly connected networks
11124312Ssklower 		 * and point to point links which aren't looped
11224312Ssklower 		 * back to ourself.  This is used below to
11324312Ssklower 		 * decide if we should be a routing ``supplier''.
11424312Ssklower 		 */
11524317Ssklower 		if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
11624317Ssklower 		    if_ifwithaddr(&ifs.int_dstaddr) == 0)
11724312Ssklower 			externalinterfaces++;
118*26170Ssklower 		/*
119*26170Ssklower 		 * If we have a point-to-point link, we want to act
120*26170Ssklower 		 * as a supplier even if it's our only interface,
121*26170Ssklower 		 * as that's the only way our peer on the other end
122*26170Ssklower 		 * can tell that the link is up.
123*26170Ssklower 		 */
124*26170Ssklower 		if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
125*26170Ssklower 			supplier = 1;
12624317Ssklower 		ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
12724312Ssklower 		if (ifp->int_name == 0) {
12824874Ssklower 			syslog(LOG_ERR,"XNSrouted: out of memory\n");
12924312Ssklower 			goto bad;		/* ??? */
13024312Ssklower 		}
13124317Ssklower 		strcpy(ifp->int_name, ifr->ifr_name);
13224312Ssklower 		ifp->int_metric = 0;
13324312Ssklower 		ifp->int_next = ifnet;
13424312Ssklower 		ifnet = ifp;
13524312Ssklower 		traceinit(ifp);
13624312Ssklower 		addrouteforif(ifp);
13724312Ssklower 	}
13824312Ssklower 	if (externalinterfaces > 1 && supplier < 0)
13924312Ssklower 		supplier = 1;
14024317Ssklower 	close(s);
14124312Ssklower 	return;
14224312Ssklower bad:
14324312Ssklower 	sleep(60);
14424317Ssklower 	close(s);
14524874Ssklower 	sleep(60);
14624312Ssklower 	execv("/etc/XNSrouted", argv0);
14724312Ssklower 	_exit(0177);
14824312Ssklower }
14924312Ssklower 
15024312Ssklower addrouteforif(ifp)
15124312Ssklower 	struct interface *ifp;
15224312Ssklower {
15324317Ssklower 	struct sockaddr_ns net;
15424312Ssklower 	struct sockaddr *dst;
15524312Ssklower 	int state, metric;
15624312Ssklower 	struct rt_entry *rt;
15724312Ssklower 
15824322Ssklower 	if (ifp->int_flags & IFF_POINTOPOINT) {
15924322Ssklower 		int (*match)();
16024322Ssklower 		register struct interface *ifp2 = ifnet;
16124322Ssklower 		register struct interface *ifprev = ifnet;
16224322Ssklower 
16324312Ssklower 		dst = &ifp->int_dstaddr;
16424322Ssklower 
16524322Ssklower 		/* Search for interfaces with the same net */
16624322Ssklower 		ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq);
16724322Ssklower 		match = afswitch[dst->sa_family].af_netmatch;
16824322Ssklower 		if (match)
16924322Ssklower 		for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) {
17024322Ssklower 			if (ifp->int_flags & IFF_POINTOPOINT == 0)
17124322Ssklower 				continue;
17224322Ssklower 			if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) {
17324322Ssklower 				insque(&ifp2->int_sq,&ifp->int_sq);
17424322Ssklower 				break;
17524322Ssklower 			}
17624322Ssklower 		}
17724322Ssklower 	} else {
17824317Ssklower 		dst = &ifp->int_broadaddr;
17924312Ssklower 	}
18024312Ssklower 	rt = rtlookup(dst);
18124317Ssklower 	if (rt)
18224317Ssklower 		rtdelete(rt);
183*26170Ssklower 	if (tracing)
184*26170Ssklower 		fprintf(stderr, "Adding route to interface %s\n", ifp->int_name);
185*26170Ssklower 	if (ifp->int_transitions++ > 0)
186*26170Ssklower 		syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
18724312Ssklower 	rtadd(dst, &ifp->int_addr, ifp->int_metric,
18824312Ssklower 		ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
18924312Ssklower }
190*26170Ssklower 
191