|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)startup.c 5.7 (Berkeley) 6/3/86";
9: #endif not lint
10:
11: /*
12: * Routing Table Management Daemon
13: */
14: #include "defs.h"
15: #include <sys/ioctl.h>
16: #include <net/if.h>
17: #include <syslog.h>
18:
19: struct interface *ifnet;
20: int lookforinterfaces = 1;
21: int externalinterfaces = 0; /* # of remote and local interfaces */
22:
23: /*
24: * Find the network interfaces which have configured themselves.
25: * If the interface is present but not yet up (for example an
26: * ARPANET IMP), set the lookforinterfaces flag so we'll
27: * come back later and look again.
28: */
29: ifinit()
30: {
31: struct interface ifs, *ifp;
32: int s, n;
33: char buf[BUFSIZ];
34: struct ifconf ifc;
35: struct ifreq ifreq, *ifr;
36: struct sockaddr_in *sin;
37: u_long i;
38:
39: if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
40: syslog(LOG_ERR, "socket: %m");
41: exit(1);
42: }
43: ifc.ifc_len = sizeof (buf);
44: ifc.ifc_buf = buf;
45: if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
46: syslog(LOG_ERR, "ioctl (get interface configuration)");
47: close(s);
48: return (0);
49: }
50: ifr = ifc.ifc_req;
51: lookforinterfaces = 0;
52: for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) {
53: bzero((char *)&ifs, sizeof(ifs));
54: ifs.int_addr = ifr->ifr_addr;
55: ifreq = *ifr;
56: if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
57: syslog(LOG_ERR, "ioctl (get interface flags)");
58: continue;
59: }
60: ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
61: /* no one cares about software loopback interfaces */
62: if (ifs.int_flags & IFF_LOOPBACK)
63: continue;
64: if ((ifs.int_flags & IFF_UP) == 0 ||
65: ifr->ifr_addr.sa_family == AF_UNSPEC) {
66: lookforinterfaces = 1;
67: continue;
68: }
69: /* already known to us? */
70: if (if_ifwithaddr(&ifs.int_addr))
71: continue;
72: /* argh, this'll have to change sometime */
73: if (ifs.int_addr.sa_family != AF_INET)
74: continue;
75: if (ifs.int_flags & IFF_POINTOPOINT) {
76: if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
77: syslog(LOG_ERR, "ioctl (get dstaddr)");
78: continue;
79: }
80: ifs.int_dstaddr = ifreq.ifr_dstaddr;
81: }
82: if (ifs.int_flags & IFF_BROADCAST) {
83: if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
84: syslog(LOG_ERR, "ioctl (get broadaddr)");
85: continue;
86: }
87: ifs.int_broadaddr = ifreq.ifr_broadaddr;
88: }
89: if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0)
90: syslog(LOG_ERR, "ioctl (get metric)");
91: else
92: ifs.int_metric = ifreq.ifr_metric;
93: if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
94: syslog(LOG_ERR, "ioctl (get netmask)");
95: continue;
96: }
97: sin = (struct sockaddr_in *)&ifreq.ifr_addr;
98: ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr);
99: sin = (struct sockaddr_in *)&ifs.int_addr;
100: i = ntohl(sin->sin_addr.s_addr);
101: if (IN_CLASSA(i))
102: ifs.int_netmask = IN_CLASSA_NET;
103: else if (IN_CLASSB(i))
104: ifs.int_netmask = IN_CLASSB_NET;
105: else
106: ifs.int_netmask = IN_CLASSC_NET;
107: ifs.int_net = i & ifs.int_netmask;
108: ifs.int_subnet = i & ifs.int_subnetmask;
109: if (ifs.int_subnetmask != ifs.int_netmask)
110: ifs.int_flags |= IFF_SUBNET;
111: ifp = (struct interface *)malloc(sizeof (struct interface));
112: if (ifp == 0) {
113: printf("routed: out of memory\n");
114: break;
115: }
116: *ifp = ifs;
117: /*
118: * Count the # of directly connected networks
119: * and point to point links which aren't looped
120: * back to ourself. This is used below to
121: * decide if we should be a routing ``supplier''.
122: */
123: if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
124: if_ifwithaddr(&ifs.int_dstaddr) == 0)
125: externalinterfaces++;
126: /*
127: * If we have a point-to-point link, we want to act
128: * as a supplier even if it's our only interface,
129: * as that's the only way our peer on the other end
130: * can tell that the link is up.
131: */
132: if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
133: supplier = 1;
134: ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
135: if (ifp->int_name == 0) {
136: fprintf(stderr, "routed: ifinit: out of memory\n");
137: goto bad; /* ??? */
138: }
139: strcpy(ifp->int_name, ifr->ifr_name);
140: ifp->int_next = ifnet;
141: ifnet = ifp;
142: traceinit(ifp);
143: addrouteforif(ifp);
144: }
145: if (externalinterfaces > 1 && supplier < 0)
146: supplier = 1;
147: close(s);
148: return;
149: bad:
150: sleep(60);
151: close(kmem), close(s);
152: execv("/etc/routed", argv0);
153: _exit(0177);
154: }
155:
156: /*
157: * Add route for interface if not currently installed.
158: * Create route to other end if a point-to-point link,
159: * otherwise a route to this (sub)network.
160: * INTERNET SPECIFIC.
161: */
162: addrouteforif(ifp)
163: struct interface *ifp;
164: {
165: struct sockaddr_in net;
166: struct sockaddr *dst;
167: int state, metric;
168: struct rt_entry *rt;
169:
170: if (ifp->int_flags & IFF_POINTOPOINT)
171: dst = &ifp->int_dstaddr;
172: else {
173: bzero((char *)&net, sizeof (net));
174: net.sin_family = AF_INET;
175: net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
176: dst = (struct sockaddr *)&net;
177: }
178: rt = rtfind(dst);
179: if (rt &&
180: (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
181: return;
182: if (rt)
183: rtdelete(rt);
184: /*
185: * If interface on subnetted network,
186: * install route to network as well.
187: * This is meant for external viewers.
188: */
189: if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
190: net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
191: rt = rtfind(dst);
192: if (rt == 0)
193: rtadd(dst, &ifp->int_addr, ifp->int_metric,
194: ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
195: RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
196: net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
197: }
198: if (ifp->int_transitions++ > 0)
199: syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
200: rtadd(dst, &ifp->int_addr, ifp->int_metric,
201: ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE|IFF_SUBNET));
202:
203: }
204:
205: /*
206: * As a concession to the ARPANET we read a list of gateways
207: * from /etc/gateways and add them to our tables. This file
208: * exists at each ARPANET gateway and indicates a set of ``remote''
209: * gateways (i.e. a gateway which we can't immediately determine
210: * if it's present or not as we can do for those directly connected
211: * at the hardware level). If a gateway is marked ``passive''
212: * in the file, then we assume it doesn't have a routing process
213: * of our design and simply assume it's always present. Those
214: * not marked passive are treated as if they were directly
215: * connected -- they're added into the interface list so we'll
216: * send them routing updates.
217: */
218: gwkludge()
219: {
220: struct sockaddr_in dst, gate;
221: FILE *fp;
222: char *type, *dname, *gname, *qual, buf[BUFSIZ];
223: struct interface *ifp;
224: int metric, n;
225: struct rt_entry route;
226:
227: fp = fopen("/etc/gateways", "r");
228: if (fp == NULL)
229: return;
230: qual = buf;
231: dname = buf + 64;
232: gname = buf + ((BUFSIZ - 64) / 3);
233: type = buf + (((BUFSIZ - 64) * 2) / 3);
234: bzero((char *)&dst, sizeof (dst));
235: bzero((char *)&gate, sizeof (gate));
236: bzero((char *)&route, sizeof(route));
237: /* format: {net | host} XX gateway XX metric DD [passive]\n */
238: #define readentry(fp) \
239: fscanf((fp), "%s %s gateway %s metric %d %s\n", \
240: type, dname, gname, &metric, qual)
241: for (;;) {
242: if ((n = readentry(fp)) == EOF)
243: break;
244: if (!getnetorhostname(type, dname, &dst))
245: continue;
246: if (!gethostnameornumber(gname, &gate))
247: continue;
248: if (strcmp(qual, "passive") == 0) {
249: /*
250: * Passive entries aren't placed in our tables,
251: * only the kernel's, so we don't copy all of the
252: * external routing information within a net.
253: * Internal machines should use the default
254: * route to a suitable gateway (like us).
255: */
256: route.rt_dst = *(struct sockaddr *) &dst;
257: route.rt_router = *(struct sockaddr *) &gate;
258: route.rt_flags = RTF_UP;
259: if (strcmp(type, "host") == 0)
260: route.rt_flags |= RTF_HOST;
261: if (metric)
262: route.rt_flags |= RTF_GATEWAY;
263: (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
264: continue;
265: }
266: if (strcmp(qual, "external") == 0) {
267: /*
268: * Entries marked external are handled
269: * by other means, e.g. EGP,
270: * and are placed in our tables only
271: * to prevent overriding them
272: * with something else.
273: */
274: rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE);
275: continue;
276: }
277: /* assume no duplicate entries */
278: externalinterfaces++;
279: ifp = (struct interface *)malloc(sizeof (*ifp));
280: bzero((char *)ifp, sizeof (*ifp));
281: ifp->int_flags = IFF_REMOTE;
282: /* can't identify broadcast capability */
283: ifp->int_net = inet_netof(dst.sin_addr);
284: if (strcmp(type, "host") == 0) {
285: ifp->int_flags |= IFF_POINTOPOINT;
286: ifp->int_dstaddr = *((struct sockaddr *)&dst);
287: }
288: ifp->int_addr = *((struct sockaddr *)&gate);
289: ifp->int_metric = metric;
290: ifp->int_next = ifnet;
291: ifnet = ifp;
292: addrouteforif(ifp);
293: }
294: fclose(fp);
295: }
296:
297: getnetorhostname(type, name, sin)
298: char *type, *name;
299: struct sockaddr_in *sin;
300: {
301:
302: if (strcmp(type, "net") == 0) {
303: struct netent *np = getnetbyname(name);
304: int n;
305:
306: if (np == 0)
307: n = inet_network(name);
308: else {
309: if (np->n_addrtype != AF_INET)
310: return (0);
311: n = np->n_net;
312: /*
313: * getnetbyname returns right-adjusted value.
314: */
315: if (n < 128)
316: n <<= IN_CLASSA_NSHIFT;
317: else if (n < 65536)
318: n <<= IN_CLASSB_NSHIFT;
319: else
320: n <<= IN_CLASSC_NSHIFT;
321: }
322: sin->sin_family = AF_INET;
323: sin->sin_addr = inet_makeaddr(n, INADDR_ANY);
324: return (1);
325: }
326: if (strcmp(type, "host") == 0) {
327: struct hostent *hp = gethostbyname(name);
328:
329: if (hp == 0)
330: sin->sin_addr.s_addr = inet_addr(name);
331: else {
332: if (hp->h_addrtype != AF_INET)
333: return (0);
334: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
335: }
336: sin->sin_family = AF_INET;
337: return (1);
338: }
339: return (0);
340: }
341:
342: gethostnameornumber(name, sin)
343: char *name;
344: struct sockaddr_in *sin;
345: {
346: struct hostent *hp;
347:
348: hp = gethostbyname(name);
349: if (hp) {
350: bcopy(hp->h_addr, &sin->sin_addr, hp->h_length);
351: sin->sin_family = hp->h_addrtype;
352: return (1);
353: }
354: sin->sin_addr.s_addr = inet_addr(name);
355: sin->sin_family = AF_INET;
356: return (sin->sin_addr.s_addr != -1);
357: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.