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