Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / bootparamd / bootparamd / bootparamd.c
1 /*
2
3 This code is not copyright, and is placed in the public domain. Feel free to
4 use and modify. Please send modifications and/or suggestions + bug fixes to
5
6         Klas Heggemann <klas@nada.kth.se>
7
8 */
9
10 /*
11  * $FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.10 1999/08/28 01:15:39 peter Exp $
12  * $DragonFly: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.2 2003/06/17 04:29:52 dillon Exp $
13  */
14 #include <rpc/rpc.h>
15 #include <rpcsvc/yp_prot.h>
16 #include <rpcsvc/ypclnt.h>
17 #include "bootparam_prot.h"
18 #include <ctype.h>
19 #include <err.h>
20 #include <netdb.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <syslog.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 extern int debug, dolog;
28 extern unsigned long route_addr;
29 extern char *bootpfile;
30
31 #define MAXLEN 800
32
33 struct hostent *he;
34 static char buffer[MAXLEN];
35 static char hostname[MAX_MACHINE_NAME];
36 static char askname[MAX_MACHINE_NAME];
37 static char path[MAX_PATH_LEN];
38 static char domain_name[MAX_MACHINE_NAME];
39
40 int getthefile __P((char *, char *, char *, int));
41 int checkhost __P((char *, char *, int));
42
43 bp_whoami_res *
44 bootparamproc_whoami_1(whoami)
45 bp_whoami_arg *whoami;
46 {
47   long haddr;
48   static bp_whoami_res res;
49   if (debug)
50     fprintf(stderr,"whoami got question for %d.%d.%d.%d\n",
51             255 &  whoami->client_address.bp_address_u.ip_addr.net,
52             255 & whoami->client_address.bp_address_u.ip_addr.host,
53             255 &  whoami->client_address.bp_address_u.ip_addr.lh,
54             255 &  whoami->client_address.bp_address_u.ip_addr.impno);
55   if (dolog)
56     syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
57             255 &  whoami->client_address.bp_address_u.ip_addr.net,
58             255 & whoami->client_address.bp_address_u.ip_addr.host,
59             255 &  whoami->client_address.bp_address_u.ip_addr.lh,
60             255 &  whoami->client_address.bp_address_u.ip_addr.impno);
61
62   bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr,
63         sizeof(haddr));
64   he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET);
65   if ( ! he ) goto failed;
66
67   if (debug) warnx("this is host %s", he->h_name);
68   if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name);
69
70   strncpy(askname, he->h_name, sizeof(askname));
71   askname[sizeof(askname)-1] = 0;
72
73   if (checkhost(askname, hostname, sizeof hostname) ) {
74     res.client_name = hostname;
75     getdomainname(domain_name, MAX_MACHINE_NAME);
76     res.domain_name = domain_name;
77
78     if (  res.router_address.address_type != IP_ADDR_TYPE ) {
79       res.router_address.address_type = IP_ADDR_TYPE;
80       bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, 4);
81     }
82     if (debug) fprintf(stderr,
83                        "Returning %s   %s    %d.%d.%d.%d\n",
84                        res.client_name,
85                        res.domain_name,
86                        255 &  res.router_address.bp_address_u.ip_addr.net,
87                        255 & res.router_address.bp_address_u.ip_addr.host,
88                        255 &  res.router_address.bp_address_u.ip_addr.lh,
89                        255 & res.router_address.bp_address_u.ip_addr.impno);
90     if (dolog) syslog(LOG_NOTICE,
91                        "Returning %s   %s    %d.%d.%d.%d\n",
92                        res.client_name,
93                        res.domain_name,
94                        255 &  res.router_address.bp_address_u.ip_addr.net,
95                        255 & res.router_address.bp_address_u.ip_addr.host,
96                        255 &  res.router_address.bp_address_u.ip_addr.lh,
97                        255 & res.router_address.bp_address_u.ip_addr.impno);
98
99     return(&res);
100   }
101  failed:
102   if (debug) warnx("whoami failed");
103   if (dolog) syslog(LOG_NOTICE,"whoami failed\n");
104   return(NULL);
105 }
106
107
108 bp_getfile_res *
109   bootparamproc_getfile_1(getfile)
110 bp_getfile_arg *getfile;
111 {
112   char *where, *index();
113   static bp_getfile_res res;
114
115   if (debug)
116     warnx("getfile got question for \"%s\" and file \"%s\"",
117             getfile->client_name, getfile->file_id);
118
119   if (dolog)
120     syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n",
121             getfile->client_name, getfile->file_id);
122
123   he = NULL;
124   he = gethostbyname(getfile->client_name);
125   if (! he ) goto failed;
126
127   strncpy(askname, he->h_name, sizeof(askname));
128   askname[sizeof(askname)-1] = 0;
129
130   if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) {
131     if ( (where = index(buffer,':')) ) {
132       /* buffer is re-written to contain the name of the info of file */
133       strncpy(hostname, buffer, where - buffer);
134       hostname[where - buffer] = '\0';
135       where++;
136       strcpy(path, where);
137       he = gethostbyname(hostname);
138       if ( !he ) goto failed;
139       bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
140       res.server_name = hostname;
141       res.server_path = path;
142       res.server_address.address_type = IP_ADDR_TYPE;
143     }
144     else { /* special for dump, answer with null strings */
145       if (!strcmp(getfile->file_id, "dump")) {
146         res.server_name = "";
147         res.server_path = "";
148         res.server_address.address_type = IP_ADDR_TYPE;
149         bzero(&res.server_address.bp_address_u.ip_addr,4);
150       } else goto failed;
151     }
152     if (debug)
153       fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n",
154              res.server_name, res.server_path,
155              255 &  res.server_address.bp_address_u.ip_addr.net,
156              255 & res.server_address.bp_address_u.ip_addr.host,
157              255 &  res.server_address.bp_address_u.ip_addr.lh,
158              255 & res.server_address.bp_address_u.ip_addr.impno);
159     if (dolog)
160       syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n",
161              res.server_name, res.server_path,
162              255 &  res.server_address.bp_address_u.ip_addr.net,
163              255 & res.server_address.bp_address_u.ip_addr.host,
164              255 &  res.server_address.bp_address_u.ip_addr.lh,
165              255 & res.server_address.bp_address_u.ip_addr.impno);
166     return(&res);
167   }
168   failed:
169   if (debug) warnx("getfile failed for %s", getfile->client_name);
170   if (dolog) syslog(LOG_NOTICE,
171                     "getfile failed for %s\n", getfile->client_name);
172   return(NULL);
173 }
174
175 /*    getthefile return 1 and fills the buffer with the information
176       of the file, e g "host:/export/root/client" if it can be found.
177       If the host is in the database, but the file is not, the buffer
178       will be empty. (This makes it possible to give the special
179       empty answer for the file "dump")   */
180
181 int
182 getthefile(askname,fileid,buffer,blen)
183 char *askname;
184 char *fileid, *buffer;
185 int blen;
186 {
187   FILE *bpf;
188   char  *where;
189   static char *result;
190   int resultlen;
191   static char *yp_domain;
192
193   int ch, pch, fid_len, res = 0;
194   int match = 0;
195   char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3];
196
197   bpf = fopen(bootpfile, "r");
198   if ( ! bpf )
199     errx(1, "no %s", bootpfile);
200
201   /* XXX see comment below */
202   while ( fscanf(bpf, "%255s", hostname) > 0  && !match ) {
203     if ( *hostname != '#' ) { /* comment */
204       if ( ! strcmp(hostname, askname) ) {
205         match = 1;
206       } else {
207         he = gethostbyname(hostname);
208         if (he && !strcmp(he->h_name, askname)) match = 1;
209       }
210     }
211     if (*hostname == '+' ) { /* NIS */
212       if (yp_get_default_domain(&yp_domain)) {
213          if (debug) warn("NIS");
214          return(0);
215       }
216       if (yp_match(yp_domain, "bootparams", askname, strlen(askname),
217                 &result, &resultlen))
218         return (0);
219       if (strstr(result, fileid) == NULL) {
220         buffer[0] = '\0';
221       } else {
222         snprintf(buffer, blen,
223                 "%s",strchr(strstr(result,fileid), '=') + 1);
224         if (strchr(buffer, ' ') != NULL)
225           *(char *)(strchr(buffer, ' ')) = '\0';
226       }
227       if (fclose(bpf))
228         warnx("could not close %s", bootpfile);
229       return(1);
230     }
231     /* skip to next entry */
232     if ( match ) break;
233     pch = ch = getc(bpf);
234     while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
235       pch = ch; ch = getc(bpf);
236     }
237   }
238
239   /* if match is true we read the rest of the line to get the
240      info of the file */
241
242   if (match) {
243     fid_len = strlen(fileid);
244     while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */
245       ch = getc(bpf);                                /* and a character */
246       if ( *info != '#' ) {                          /* Comment ? */
247         if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') {
248           where = info + fid_len + 1;
249           if ( isprint( *where )) {
250             strcpy(buffer, where);                   /* found file */
251             res = 1; break;
252           }
253         } else {
254           while (isspace(ch) && ch != '\n') ch = getc(bpf);
255                                                      /* read to end of line */
256           if ( ch == '\n' ) {                        /* didn't find it */
257             res = -1; break;                         /* but host is there */
258           }
259           if ( ch == '\\' ) {                        /* more info */
260             ch = getc(bpf);                          /* maybe on next line */
261             if (ch == '\n') continue;                /* read it in next loop */
262             ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */
263           } else ungetc(ch, bpf);              /* but who know what a `\` is */
264         }                                      /* needed for. */
265       } else break;                            /* a commented rest-of-line */
266     }
267   }
268   if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
269   if ( res == -1) buffer[0] = '\0';            /* host found, file not */
270   return(match);
271 }
272
273 /* checkhost puts the hostname found in the database file in
274    the hostname-variable and returns 1, if askname is a valid
275    name for a host in the database */
276
277 int
278 checkhost(askname, hostname, len)
279 char *askname;
280 char *hostname;
281 int len;
282 {
283   int ch, pch;
284   FILE *bpf;
285   int res = 0;
286   static char *result;
287   int resultlen;
288   static char *yp_domain;
289
290 /*  struct hostent *cmp_he;*/
291
292   bpf = fopen(bootpfile, "r");
293   if ( ! bpf )
294     errx(1, "no %s", bootpfile);
295
296   /* XXX there is no way in ISO C to specify the maximal length for a
297      conversion in a variable way */
298   while ( fscanf(bpf, "%254s", hostname) > 0 ) {
299     if ( *hostname != '#' ) { /* comment */
300       if ( ! strcmp(hostname, askname) ) {
301         /* return true for match of hostname */
302         res = 1;
303         break;
304       } else {
305         /* check the alias list */
306         he = NULL;
307         he = gethostbyname(hostname);
308         if (he && !strcmp(askname, he->h_name)) {
309           res = 1;
310           break;
311         }
312       }
313     }
314     if (*hostname == '+' ) { /* NIS */
315       if (yp_get_default_domain(&yp_domain)) {
316          if (debug) warn("NIS");
317          return(0);
318       }
319       if (!yp_match(yp_domain, "bootparams", askname, strlen(askname),
320                 &result, &resultlen)) {
321         /* return true for match of hostname */
322         he = NULL;
323         he = gethostbyname(askname);
324         if (he && !strcmp(askname, he->h_name)) {
325           res = 1;
326           snprintf(hostname, len, "%s", he->h_name);
327         }
328       }
329       if (fclose(bpf))
330         warnx("could not close %s", bootpfile);
331       return(res);
332     }
333     /* skip to next entry */
334     pch = ch = getc(bpf);
335     while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
336       pch = ch; ch = getc(bpf);
337     }
338   }
339   if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
340   return(res);
341 }