xref: /original-bsd/sbin/routed/startup.c (revision f0fd5f8a)
1 #ifndef lint
2 static char sccsid[] = "@(#)startup.c	4.1 11/02/82";
3 #endif
4 
5 /*
6  * Routing Table Management Daemon
7  */
8 #include "router.h"
9 #include <net/if.h>
10 #include <nlist.h>
11 
12 struct	interface *ifnet;
13 int	kmem = -1;
14 int	lookforinterfaces = 1;
15 int	performnlist = 1;
16 int	externalinterfaces = 0;		/* # of remote and local interfaces */
17 
18 struct nlist nl[] = {
19 #define	N_IFNET		0
20 	{ "_ifnet" },
21 	0,
22 };
23 
24 /*
25  * Probe the kernel through /dev/kmem to find the network
26  * interfaces which have configured themselves.  If the
27  * interface is present but not yet up (for example an
28  * ARPANET IMP), set the lookforinterfaces flag so we'll
29  * come back later and look again.
30  */
31 ifinit()
32 {
33 	struct interface *ifp;
34 	struct ifnet ifs, *next;
35 	char name[32], *cp, *index();
36 
37 	if (performnlist) {
38 		nlist("/vmunix", nl);
39 		if (nl[N_IFNET].n_value == 0) {
40 			printf("ifnet: not in namelist\n");
41 			goto bad;
42 		}
43 		performnlist = 0;
44 	}
45 	if (kmem < 0) {
46 		kmem = open("/dev/kmem", 0);
47 		if (kmem < 0) {
48 			perror("/dev/kmem");
49 			goto bad;
50 		}
51 	}
52 	if (lseek(kmem, (long)nl[N_IFNET].n_value, 0) == -1 ||
53 	    read(kmem, (char *)&next, sizeof (next)) != sizeof (next)) {
54 		printf("ifnet: error reading kmem\n");
55 		goto bad;
56 	}
57 	lookforinterfaces = 0;
58 	while (next) {
59 		if (lseek(kmem, (long)next, 0) == -1 ||
60 		    read(kmem, (char *)&ifs, sizeof (ifs)) != sizeof (ifs)) {
61 			perror("read");
62 			goto bad;
63 		}
64 		next = ifs.if_next;
65 		if ((ifs.if_flags & IFF_UP) == 0) {
66 			lookforinterfaces = 1;
67 			continue;
68 		}
69 		/* already known to us? */
70 		if (if_ifwithaddr(&ifs.if_addr))
71 			continue;
72 		/* argh, this'll have to change sometime */
73 		if (ifs.if_addr.sa_family != AF_INET)
74 			continue;
75 		/* no one cares about software loopback interfaces */
76 		if (ifs.if_net == LOOPBACKNET)
77 			continue;
78 		ifp = (struct interface *)malloc(sizeof (struct interface));
79 		if (ifp == 0) {
80 			printf("routed: out of memory\n");
81 			break;
82 		}
83 		/*
84 		 * Count the # of directly connected networks
85 		 * and point to point links which aren't looped
86 		 * back to ourself.  This is used below to
87 		 * decide if we should be a routing ``supplier''.
88 		 */
89 		if ((ifs.if_flags & IFF_POINTOPOINT) == 0 ||
90 		    if_ifwithaddr(&ifs.if_dstaddr) == 0)
91 			externalinterfaces++;
92 		lseek(kmem, ifs.if_name, 0);
93 		read(kmem, name, sizeof (name));
94 		name[sizeof (name) - 1] = '\0';
95 		cp = index(name, '\0');
96 		*cp++ = ifs.if_unit + '0';
97 		*cp = '\0';
98 		ifp->int_name = malloc(strlen(name) + 1);
99 		if (ifp->int_name == 0) {
100 			fprintf(stderr, "routed: ifinit: out of memory\n");
101 			goto bad;		/* ??? */
102 		}
103 		strcpy(ifp->int_name, name);
104 		ifp->int_addr = ifs.if_addr;
105 		ifp->int_flags = ifs.if_flags | IFF_INTERFACE;
106 		/* this works because broadaddr overlaps dstaddr */
107 		ifp->int_broadaddr = ifs.if_broadaddr;
108 		ifp->int_net = ifs.if_net;
109 		ifp->int_metric = 0;
110 		ifp->int_next = ifnet;
111 		ifnet = ifp;
112 		traceinit(ifp);
113 		addrouteforif(ifp);
114 	}
115 	if (externalinterfaces > 1 && supplier < 0)
116 		supplier = 1;
117 	return;
118 bad:
119 	sleep(60);
120 	close(kmem), close(s), close(snoroute);
121 	execv("/etc/routed", argv0);
122 	_exit(0177);
123 }
124 
125 addrouteforif(ifp)
126 	struct interface *ifp;
127 {
128 	struct sockaddr_in net;
129 	struct sockaddr *dst;
130 	int state, metric;
131 	struct rt_entry *rt;
132 
133 	if (ifp->int_flags & IFF_POINTOPOINT)
134 		dst = &ifp->int_dstaddr;
135 	else {
136 		bzero((char *)&net, sizeof (net));
137 		net.sin_family = AF_INET;
138 		net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
139 		dst = (struct sockaddr *)&net;
140 	}
141 	rt = rtlookup(dst);
142 	rtadd(dst, &ifp->int_addr, ifp->int_metric,
143 		ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
144 	if (rt)
145 		rtdelete(rt);
146 }
147 
148 /*
149  * As a concession to the ARPANET we read a list of gateways
150  * from /etc/gateways and add them to our tables.  This file
151  * exists at each ARPANET gateway and indicates a set of ``remote''
152  * gateways (i.e. a gateway which we can't immediately determine
153  * if it's present or not as we can do for those directly connected
154  * at the hardware level).  If a gateway is marked ``passive''
155  * in the file, then we assume it doesn't have a routing process
156  * of our design and simply assume it's always present.  Those
157  * not marked passive are treated as if they were directly
158  * connected -- they're added into the interface list so we'll
159  * send them routing updates.
160  */
161 gwkludge()
162 {
163 	struct sockaddr_in dst, gate;
164 	FILE *fp;
165 	char *type, *dname, *gname, *qual, buf[BUFSIZ];
166 	struct interface *ifp;
167 	int metric;
168 
169 	fp = fopen("/etc/gateways", "r");
170 	if (fp == NULL)
171 		return;
172 	qual = buf;
173 	dname = buf + 64;
174 	gname = buf + ((BUFSIZ - 64) / 3);
175 	type = buf + (((BUFSIZ - 64) * 2) / 3);
176 	bzero((char *)&dst, sizeof (dst));
177 	bzero((char *)&gate, sizeof (gate));
178 	dst.sin_family = gate.sin_family = AF_INET;
179 	/* format: {net | host} XX gateway XX metric DD [passive]\n */
180 #define	readentry(fp) \
181 	fscanf((fp), "%s %s gateway %s metric %d %s\n", \
182 		type, dname, gname, &metric, qual)
183 	for (;;) {
184 		struct hostent *host;
185 		struct netent *net;
186 
187 		if (readentry(fp) == EOF)
188 			break;
189 		if (strcmp(type, "net") == 0) {
190 			net = getnetbyname(dname);
191 			if (net == 0 || net->n_addrtype != AF_INET)
192 				continue;
193 			dst.sin_addr = inet_makeaddr(net->n_net, INADDR_ANY);
194 		} else if (strcmp(type, "host") == 0) {
195 			host = gethostbyname(dname);
196 			if (host == 0)
197 				continue;
198 			bcopy(host->h_addr, &dst.sin_addr, host->h_length);
199 		} else
200 			continue;
201 		host = gethostbyname(gname);
202 		if (host == 0)
203 			continue;
204 		bcopy(host->h_addr, &gate.sin_addr, host->h_length);
205 		ifp = (struct interface *)malloc(sizeof (*ifp));
206 		bzero((char *)ifp, sizeof (*ifp));
207 		ifp->int_flags = IFF_REMOTE;
208 		/* can't identify broadcast capability */
209 		ifp->int_net = inet_netof(dst.sin_addr);
210 		if (strcmp(type, "host") == 0) {
211 			ifp->int_flags |= IFF_POINTOPOINT;
212 			ifp->int_dstaddr = *((struct sockaddr *)&dst);
213 		}
214 		if (strcmp(qual, "passive") == 0)
215 			ifp->int_flags |= IFF_PASSIVE;
216 		else
217 			/* assume no duplicate entries */
218 			externalinterfaces++;
219 		ifp->int_addr = *((struct sockaddr *)&gate);
220 		ifp->int_metric = metric;
221 		ifp->int_next = ifnet;
222 		ifnet = ifp;
223 		addrouteforif(ifp);
224 	}
225 	fclose(fp);
226 }
227