bootparamd.c revision 1.1 1 /*
2 * This code is not copyright, and is placed in the public domain.
3 * Feel free to use and modify. Please send modifications and/or
4 * suggestions + bug fixes to Klas Heggemann <klas (at) nada.kth.se>
5 *
6 * Various small changes by Theo de Raadt <deraadt (at) fsa.ca>
7 *
8 * $Id: bootparamd.c,v 1.1 1994/01/08 13:22:04 deraadt Exp $
9 */
10
11 #include <sys/types.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14 #include <sys/socket.h>
15 #include <rpc/rpc.h>
16 #include <rpcsvc/bootparam_prot.h>
17 #include <stdio.h>
18 #include <netdb.h>
19 #include <ctype.h>
20 #include <syslog.h>
21
22 #define MAXLEN 800
23
24 struct hostent *he;
25 static char buffer[MAXLEN];
26 static char hostname[MAX_MACHINE_NAME];
27 static char askname[MAX_MACHINE_NAME];
28 static char path[MAX_PATH_LEN];
29 static char domain_name[MAX_MACHINE_NAME];
30
31 extern void bootparamprog_1();
32
33 int debug = 0;
34 int dolog = 0;
35 unsigned long route_addr, inet_addr();
36 struct sockaddr_in my_addr;
37 char *progname;
38 char *bootpfile = "/etc/bootparams";
39
40 extern char *optarg;
41 extern int optind;
42
43 void
44 usage()
45 {
46 fprintf(stderr,
47 "usage: rpc.bootparamd [-d] [-s] [-r router] [-f bootparmsfile]\n");
48 }
49
50
51 /*
52 * ever familiar
53 */
54 int
55 main(argc, argv)
56 int argc;
57 char **argv;
58 {
59 SVCXPRT *transp;
60 int i, s, pid;
61 char *rindex();
62 struct hostent *he;
63 struct stat buf;
64 char *optstring;
65 char c;
66
67 progname = rindex(argv[0], '/');
68 if (progname)
69 progname++;
70 else
71 progname = argv[0];
72
73 while ((c = getopt(argc, argv, "dsr:f:")) != EOF)
74 switch (c) {
75 case 'd':
76 debug = 1;
77 break;
78 case 'r':
79 if (isdigit(*optarg)) {
80 route_addr = inet_addr(optarg);
81 break;
82 }
83 he = gethostbyname(optarg);
84 if (!he) {
85 fprintf(stderr, "%s: No such host %s\n",
86 progname, optarg);
87 usage();
88 exit(1);
89 }
90 bcopy(he->h_addr, (char *) &route_addr, sizeof(route_addr));
91 break;
92 case 'f':
93 bootpfile = optarg;
94 break;
95 case 's':
96 dolog = 1;
97 #ifndef LOG_DAEMON
98 openlog(progname, 0, 0);
99 #else
100 openlog(progname, 0, LOG_DAEMON);
101 setlogmask(LOG_UPTO(LOG_NOTICE));
102 #endif
103 break;
104 default:
105 usage();
106 exit(1);
107 }
108
109 if (stat(bootpfile, &buf)) {
110 fprintf(stderr, "%s: ", progname);
111 perror(bootpfile);
112 exit(1);
113 }
114 if (!route_addr) {
115 get_myaddress(&my_addr);
116 bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof(route_addr));
117 }
118 if (!debug)
119 daemon();
120
121 (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS);
122
123 transp = svcudp_create(RPC_ANYSOCK);
124 if (transp == NULL) {
125 fprintf(stderr, "cannot create udp service.\n");
126 exit(1);
127 }
128 if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS,
129 bootparamprog_1, IPPROTO_UDP)) {
130 fprintf(stderr,
131 "bootparamd: unable to register BOOTPARAMPROG version %d, udp)\n",
132 BOOTPARAMVERS);
133 exit(1);
134 }
135 svc_run();
136 fprintf(stderr, "svc_run returned\n");
137 exit(1);
138 }
139
140 bp_whoami_res *
141 bootparamproc_whoami_1(whoami)
142 bp_whoami_arg *whoami;
143 {
144 long haddr;
145 static bp_whoami_res res;
146 if (debug)
147 fprintf(stderr, "whoami got question for %d.%d.%d.%d\n",
148 255 & whoami->client_address.bp_address_u.ip_addr.net,
149 255 & whoami->client_address.bp_address_u.ip_addr.host,
150 255 & whoami->client_address.bp_address_u.ip_addr.lh,
151 255 & whoami->client_address.bp_address_u.ip_addr.impno);
152 if (dolog)
153 syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
154 255 & whoami->client_address.bp_address_u.ip_addr.net,
155 255 & whoami->client_address.bp_address_u.ip_addr.host,
156 255 & whoami->client_address.bp_address_u.ip_addr.lh,
157 255 & whoami->client_address.bp_address_u.ip_addr.impno);
158
159 bcopy((char *) &whoami->client_address.bp_address_u.ip_addr, (char *) &haddr,
160 sizeof(haddr));
161 he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET);
162 if (!he)
163 goto failed;
164
165 if (debug)
166 fprintf(stderr, "This is host %s\n", he->h_name);
167 if (dolog)
168 syslog(LOG_NOTICE, "This is host %s\n", he->h_name);
169
170 strcpy(askname, he->h_name);
171 if (checkhost(askname, hostname)) {
172 res.client_name = hostname;
173 getdomainname(domain_name, MAX_MACHINE_NAME);
174 res.domain_name = domain_name;
175
176 if (res.router_address.address_type != IP_ADDR_TYPE) {
177 res.router_address.address_type = IP_ADDR_TYPE;
178 bcopy(&route_addr, &res.router_address.bp_address_u.ip_addr, 4);
179 }
180 if (debug)
181 fprintf(stderr, "Returning %s %s %d.%d.%d.%d\n",
182 res.client_name, res.domain_name,
183 255 & res.router_address.bp_address_u.ip_addr.net,
184 255 & res.router_address.bp_address_u.ip_addr.host,
185 255 & res.router_address.bp_address_u.ip_addr.lh,
186 255 & res.router_address.bp_address_u.ip_addr.impno);
187 if (dolog)
188 syslog(LOG_NOTICE, "Returning %s %s %d.%d.%d.%d\n",
189 res.client_name, res.domain_name,
190 255 & res.router_address.bp_address_u.ip_addr.net,
191 255 & res.router_address.bp_address_u.ip_addr.host,
192 255 & res.router_address.bp_address_u.ip_addr.lh,
193 255 & res.router_address.bp_address_u.ip_addr.impno);
194
195 return (&res);
196 }
197 failed:
198 if (debug)
199 fprintf(stderr, "whoami failed\n");
200 if (dolog)
201 syslog(LOG_NOTICE, "whoami failed\n");
202 return (NULL);
203 }
204
205
206 bp_getfile_res *
207 bootparamproc_getfile_1(getfile)
208 bp_getfile_arg *getfile;
209 {
210 char *where, *index();
211 static bp_getfile_res res;
212
213 if (debug)
214 fprintf(stderr, "getfile got question for \"%s\" and file \"%s\"\n",
215 getfile->client_name, getfile->file_id);
216
217 if (dolog)
218 syslog(LOG_NOTICE, "getfile got question for \"%s\" and file \"%s\"\n",
219 getfile->client_name, getfile->file_id);
220
221 he = NULL;
222 he = gethostbyname(getfile->client_name);
223 if (!he)
224 goto failed;
225
226 strcpy(askname, he->h_name);
227 if (getthefile(askname, getfile->file_id, buffer)) {
228 if (where = index(buffer, ':')) {
229 /* buffer is re-written to contain the name of the
230 * info of file */
231 strncpy(hostname, buffer, where - buffer);
232 hostname[where - buffer] = '\0';
233 where++;
234 strcpy(path, where);
235 he = gethostbyname(hostname);
236 if (!he)
237 goto failed;
238 bcopy(he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
239 res.server_name = hostname;
240 res.server_path = path;
241 res.server_address.address_type = IP_ADDR_TYPE;
242 } else { /* special for dump, answer with null strings */
243 if (!strcmp(getfile->file_id, "dump")) {
244 res.server_name[0] = '\0';
245 res.server_path[0] = '\0';
246 bzero(&res.server_address.bp_address_u.ip_addr, 4);
247 } else
248 goto failed;
249 }
250 if (debug)
251 fprintf(stderr,
252 "returning server:%s path:%s address: %d.%d.%d.%d\n",
253 res.server_name, res.server_path,
254 255 & res.server_address.bp_address_u.ip_addr.net,
255 255 & res.server_address.bp_address_u.ip_addr.host,
256 255 & res.server_address.bp_address_u.ip_addr.lh,
257 255 & res.server_address.bp_address_u.ip_addr.impno);
258 if (dolog)
259 syslog(LOG_NOTICE,
260 "returning server:%s path:%s address: %d.%d.%d.%d\n",
261 res.server_name, res.server_path,
262 255 & res.server_address.bp_address_u.ip_addr.net,
263 255 & res.server_address.bp_address_u.ip_addr.host,
264 255 & res.server_address.bp_address_u.ip_addr.lh,
265 255 & res.server_address.bp_address_u.ip_addr.impno);
266 return (&res);
267 }
268 failed:
269 if (debug)
270 fprintf(stderr, "getfile failed for %s\n", getfile->client_name);
271 if (dolog)
272 syslog(LOG_NOTICE,
273 "getfile failed for %s\n", getfile->client_name);
274 return (NULL);
275 }
276
277
278 /*
279 * getthefile return 1 and fills the buffer with the information
280 * of the file, e g "host:/export/root/client" if it can be found.
281 * If the host is in the database, but the file is not, the buffer
282 * will be empty. (This makes it possible to give the special
283 * empty answer for the file "dump")
284 */
285 getthefile(askname, fileid, buffer)
286 char *askname;
287 char *fileid, *buffer;
288 {
289 FILE *bpf;
290 char *where;
291
292 int ch, pch, fid_len, res = 0;
293 int match = 0;
294 char info[MAX_FILEID + MAX_PATH_LEN + MAX_MACHINE_NAME + 3];
295
296 bpf = fopen(bootpfile, "r");
297 if (!bpf) {
298 fprintf(stderr, "No %s\n", bootpfile);
299 exit(1);
300 }
301 while (fscanf(bpf, "%s", hostname) > 0 && !match) {
302 if (*hostname != '#') { /* comment */
303 if (!strcmp(hostname, askname)) {
304 match = 1;
305 } else {
306 he = gethostbyname(hostname);
307 if (he && !strcmp(he->h_name, askname))
308 match = 1;
309 }
310 }
311 /* skip to next entry */
312 if (match)
313 break;
314 pch = ch = getc(bpf);
315 while (!(ch == '\n' && pch != '\\') && ch != EOF) {
316 pch = ch;
317 ch = getc(bpf);
318 }
319 }
320
321 /* if match is true we read the rest of the line to get the info of
322 * the file */
323
324 if (match) {
325 fid_len = strlen(fileid);
326 while (!res && (fscanf(bpf, "%s", info)) > 0) { /* read a string */
327 ch = getc(bpf); /* and a character */
328 if (*info != '#') { /* Comment ? */
329 if (!strncmp(info, fileid, fid_len) &&
330 *(info + fid_len) == '=') {
331 where = info + fid_len + 1;
332 if (isprint(*where)) {
333 strcpy(buffer, where);
334 res = 1;
335 break;
336 }
337 } else {
338 while (isspace(ch) && ch != '\n')
339 ch = getc(bpf);
340 if (ch == '\n') {
341 res = -1;
342 break;
343 }
344 if (ch == '\\') {
345 ch = getc(bpf);
346 if (ch == '\n')
347 continue;
348 ungetc(ch, bpf);
349 ungetc('\\', bpf);
350 } else
351 ungetc(ch, bpf);
352 }
353 } else
354 break;
355 }
356 }
357 if (fclose(bpf)) {
358 fprintf(stderr, "Could not close %s\n", bootpfile);
359 }
360 if (res == -1)
361 buffer[0] = '\0'; /* host found, file not */
362 return (match);
363 }
364
365
366 /*
367 * checkhost puts the hostname found in the database file in
368 * the hostname-variable and returns 1, if askname is a valid
369 * name for a host in the database
370 */
371 checkhost(askname, hostname)
372 char *askname;
373 char *hostname;
374 {
375 int ch, pch;
376 FILE *bpf;
377 int res = 0;
378
379 bpf = fopen(bootpfile, "r");
380 if (!bpf) {
381 fprintf(stderr, "No %s\n", bootpfile);
382 exit(1);
383 }
384 while (fscanf(bpf, "%s", hostname) > 0) {
385 if (!strcmp(hostname, askname)) {
386 /* return true for match of hostname */
387 res = 1;
388 break;
389 } else {
390 /* check the alias list */
391 he = NULL;
392 he = gethostbyname(hostname);
393 if (he && !strcmp(askname, he->h_name)) {
394 res = 1;
395 break;
396 }
397 }
398 /* skip to next entry */
399 pch = ch = getc(bpf);
400 while (!(ch == '\n' && pch != '\\') && ch != EOF) {
401 pch = ch;
402 ch = getc(bpf);
403 }
404 }
405 fclose(bpf);
406 return (res);
407 }
408