Commit | Line | Data |
---|---|---|
85d8a62e | 1 | #ifndef lint |
0f4556f1 | 2 | static char sccsid[] = "@(#)startup.c 4.4 (Berkeley) 5/25/83"; |
85d8a62e SL |
3 | #endif |
4 | ||
5 | /* | |
6 | * Routing Table Management Daemon | |
7 | */ | |
7fe7fe74 | 8 | #include "defs.h" |
85d8a62e SL |
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" }, | |
7fe7fe74 | 21 | { "" }, |
85d8a62e SL |
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); | |
7fe7fe74 | 120 | close(kmem), close(s); |
85d8a62e SL |
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)); | |
85d8a62e SL |
178 | /* format: {net | host} XX gateway XX metric DD [passive]\n */ |
179 | #define readentry(fp) \ | |
180 | fscanf((fp), "%s %s gateway %s metric %d %s\n", \ | |
181 | type, dname, gname, &metric, qual) | |
182 | for (;;) { | |
85d8a62e SL |
183 | if (readentry(fp) == EOF) |
184 | break; | |
7fe7fe74 | 185 | if (!getnetorhostname(type, dname, &dst)) |
85d8a62e | 186 | continue; |
7fe7fe74 | 187 | if (!gethostnameornumber(gname, &gate)) |
85d8a62e | 188 | continue; |
85d8a62e SL |
189 | ifp = (struct interface *)malloc(sizeof (*ifp)); |
190 | bzero((char *)ifp, sizeof (*ifp)); | |
191 | ifp->int_flags = IFF_REMOTE; | |
192 | /* can't identify broadcast capability */ | |
193 | ifp->int_net = inet_netof(dst.sin_addr); | |
194 | if (strcmp(type, "host") == 0) { | |
195 | ifp->int_flags |= IFF_POINTOPOINT; | |
196 | ifp->int_dstaddr = *((struct sockaddr *)&dst); | |
197 | } | |
198 | if (strcmp(qual, "passive") == 0) | |
199 | ifp->int_flags |= IFF_PASSIVE; | |
200 | else | |
201 | /* assume no duplicate entries */ | |
202 | externalinterfaces++; | |
203 | ifp->int_addr = *((struct sockaddr *)&gate); | |
204 | ifp->int_metric = metric; | |
205 | ifp->int_next = ifnet; | |
206 | ifnet = ifp; | |
207 | addrouteforif(ifp); | |
208 | } | |
209 | fclose(fp); | |
210 | } | |
7fe7fe74 SL |
211 | |
212 | getnetorhostname(type, name, sin) | |
213 | char *type, *name; | |
214 | struct sockaddr_in *sin; | |
215 | { | |
216 | ||
217 | if (strcmp(type, "net") == 0) { | |
218 | struct netent *np = getnetbyname(name); | |
219 | int n; | |
220 | ||
7fe7fe74 SL |
221 | if (np == 0) |
222 | n = inet_network(name); | |
20932249 SL |
223 | else { |
224 | if (np->n_addrtype != AF_INET) | |
225 | return (0); | |
7fe7fe74 | 226 | n = np->n_net; |
20932249 | 227 | } |
7fe7fe74 SL |
228 | sin->sin_family = AF_INET; |
229 | sin->sin_addr = inet_makeaddr(n, INADDR_ANY); | |
230 | return (1); | |
231 | } | |
232 | if (strcmp(type, "host") == 0) { | |
233 | struct hostent *hp = gethostbyname(name); | |
234 | ||
7fe7fe74 SL |
235 | if (hp == 0) |
236 | sin->sin_addr.s_addr = inet_addr(name); | |
20932249 SL |
237 | else { |
238 | if (hp->h_addrtype != AF_INET) | |
239 | return (0); | |
7fe7fe74 | 240 | bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); |
20932249 | 241 | } |
7fe7fe74 SL |
242 | sin->sin_family = AF_INET; |
243 | return (1); | |
244 | } | |
245 | return (0); | |
246 | } | |
247 | ||
248 | gethostnameornumber(name, sin) | |
249 | char *name; | |
250 | struct sockaddr_in *sin; | |
251 | { | |
252 | struct hostent *hp; | |
253 | ||
254 | hp = gethostbyname(name); | |
255 | if (hp) { | |
256 | bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); | |
257 | sin->sin_family = hp->h_addrtype; | |
258 | return (1); | |
259 | } | |
260 | sin->sin_addr.s_addr = inet_addr(name); | |
261 | sin->sin_family = AF_INET; | |
262 | return (sin->sin_addr.s_addr != -1); | |
263 | } |