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