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