xref: /csrg-svn/sbin/XNSrouted/startup.c (revision 24874)
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*24874Ssklower static char sccsid[] = "@(#)startup.c	5.4 (Berkeley) 09/17/85";
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;
2724312Ssklower int	externalinterfaces = 0;		/* # of remote and local interfaces */
2824312Ssklower int	gateway = 0;		/* 1 if we are a gateway to parts beyond */
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;
43*24874Ssklower 	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 		}
74*24874Ssklower #ifdef notdef
7524317Ssklower 		/* already known to us? */
76*24874Ssklower 		/* We can have more than one point to point link
77*24874Ssklower 		   with the same local address.
78*24874Ssklower 		   It is not clear what this was guarding against
79*24874Ssklower 		   anyway.
80*24874Ssklower 		if (if_ifwithaddr(ifr->ifr_addr))
81*24874Ssklower 			continue;
82*24874Ssklower 		   */
83*24874Ssklower #endif
8424317Ssklower 		if (ifs.int_addr.sa_family != AF_NS)
8524317Ssklower 			continue;
8624317Ssklower                 if (ifs.int_flags & IFF_POINTOPOINT) {
8724317Ssklower                         if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
88*24874Ssklower                                 syslog(LOG_ERR, "ioctl (get dstaddr): %m");
8924317Ssklower                                 continue;
9024317Ssklower 			}
9124317Ssklower 			ifs.int_dstaddr = ifreq.ifr_dstaddr;
9224312Ssklower 		}
9324317Ssklower                 if (ifs.int_flags & IFF_BROADCAST) {
9424317Ssklower                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
95*24874Ssklower                                 syslog(LOG_ERR, "ioctl (get broadaddr: %m");
9624317Ssklower                                 continue;
9724317Ssklower                         }
9824317Ssklower 			ifs.int_broadaddr = ifreq.ifr_broadaddr;
9924317Ssklower 		}
10024317Ssklower 		/* no one cares about software loopback interfaces */
10124317Ssklower 		if (strcmp(ifr->ifr_name,"lo0")==0)
10224317Ssklower 			continue;
10324312Ssklower 		ifp = (struct interface *)malloc(sizeof (struct interface));
10424312Ssklower 		if (ifp == 0) {
105*24874Ssklower 			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++;
11824317Ssklower 		ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
11924312Ssklower 		if (ifp->int_name == 0) {
120*24874Ssklower 			syslog(LOG_ERR,"XNSrouted: out of memory\n");
12124312Ssklower 			goto bad;		/* ??? */
12224312Ssklower 		}
12324317Ssklower 		strcpy(ifp->int_name, ifr->ifr_name);
12424312Ssklower 		ifp->int_metric = 0;
12524312Ssklower 		ifp->int_next = ifnet;
12624312Ssklower 		ifnet = ifp;
12724312Ssklower 		traceinit(ifp);
12824312Ssklower 		addrouteforif(ifp);
12924312Ssklower 	}
13024312Ssklower 	if (externalinterfaces > 1 && supplier < 0)
13124312Ssklower 		supplier = 1;
13224317Ssklower 	close(s);
13324312Ssklower 	return;
13424312Ssklower bad:
13524312Ssklower 	sleep(60);
13624317Ssklower 	close(s);
137*24874Ssklower 	sleep(60);
13824312Ssklower 	execv("/etc/XNSrouted", argv0);
13924312Ssklower 	_exit(0177);
14024312Ssklower }
14124312Ssklower 
14224312Ssklower addrouteforif(ifp)
14324312Ssklower 	struct interface *ifp;
14424312Ssklower {
14524317Ssklower 	struct sockaddr_ns net;
14624312Ssklower 	struct sockaddr *dst;
14724312Ssklower 	int state, metric;
14824312Ssklower 	struct rt_entry *rt;
14924312Ssklower 
15024322Ssklower 	if (ifp->int_flags & IFF_POINTOPOINT) {
15124322Ssklower 		int (*match)();
15224322Ssklower 		register struct interface *ifp2 = ifnet;
15324322Ssklower 		register struct interface *ifprev = ifnet;
15424322Ssklower 
15524312Ssklower 		dst = &ifp->int_dstaddr;
15624322Ssklower 
15724322Ssklower 		/* Search for interfaces with the same net */
15824322Ssklower 		ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq);
15924322Ssklower 		match = afswitch[dst->sa_family].af_netmatch;
16024322Ssklower 		if (match)
16124322Ssklower 		for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) {
16224322Ssklower 			if (ifp->int_flags & IFF_POINTOPOINT == 0)
16324322Ssklower 				continue;
16424322Ssklower 			if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) {
16524322Ssklower 				insque(&ifp2->int_sq,&ifp->int_sq);
16624322Ssklower 				break;
16724322Ssklower 			}
16824322Ssklower 		}
16924322Ssklower 	} else {
17024317Ssklower 		dst = &ifp->int_broadaddr;
17124312Ssklower 	}
17224312Ssklower 	rt = rtlookup(dst);
17324317Ssklower 	if (rt)
17424317Ssklower 		rtdelete(rt);
17524312Ssklower 	rtadd(dst, &ifp->int_addr, ifp->int_metric,
17624312Ssklower 		ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
17724312Ssklower }
178