145405Smsmith/*
245405Smsmith
345405SmsmithThis code is not copyright, and is placed in the public domain. Feel free to
445405Smsmithuse and modify. Please send modifications and/or suggestions + bug fixes to
545405Smsmith
645405Smsmith        Klas Heggemann <klas@nada.kth.se>
745405Smsmith
845405Smsmith*/
945405Smsmith
1045405Smsmith#ifndef lint
1145405Smsmithstatic const char rcsid[] =
1245405Smsmith  "$FreeBSD$";
1345405Smsmith#endif /* not lint */
1445405Smsmith
1545405Smsmith#ifdef YP
1645405Smsmith#include <rpc/rpc.h>
1745405Smsmith#include <rpcsvc/yp_prot.h>
1845405Smsmith#include <rpcsvc/ypclnt.h>
1945405Smsmith#endif
2045405Smsmith#include "bootparam_prot.h"
2145405Smsmith#include <ctype.h>
2245405Smsmith#include <err.h>
2345405Smsmith#include <netdb.h>
2445405Smsmith#include <stdio.h>
2545405Smsmith#include <string.h>
2650477Speter#include <syslog.h>
2745405Smsmith#include <unistd.h>
2845405Smsmith#include <sys/types.h>
2945405Smsmith#include <sys/socket.h>
3045405Smsmithextern int debug, dolog;
3145405Smsmithextern in_addr_t route_addr;
3245405Smsmithextern char *bootpfile;
3345405Smsmith
3476078Sjhb#define MAXLEN 800
3545405Smsmith
3645405Smsmithstruct hostent *he;
3745405Smsmithstatic char buffer[MAXLEN];
3845405Smsmithstatic char hostname[MAX_MACHINE_NAME];
3945405Smsmithstatic char askname[MAX_MACHINE_NAME];
4045405Smsmithstatic char path[MAX_PATH_LEN];
4145405Smsmithstatic char domain_name[MAX_MACHINE_NAME];
4245405Smsmith
4345405Smsmithint getthefile(char *, char *, char *, int);
4445405Smsmithint checkhost(char *, char *, int);
4545405Smsmith
4645405Smsmithbp_whoami_res *
4745405Smsmithbootparamproc_whoami_1_svc(whoami, req)
4845405Smsmithbp_whoami_arg *whoami;
4945405Smsmithstruct svc_req *req;
5045405Smsmith{
5145405Smsmith  in_addr_t haddr;
5245405Smsmith  static bp_whoami_res res;
5345405Smsmith  if (debug)
5445405Smsmith    fprintf(stderr,"whoami got question for %d.%d.%d.%d\n",
5545405Smsmith	    255 &  whoami->client_address.bp_address_u.ip_addr.net,
5645405Smsmith	    255 & whoami->client_address.bp_address_u.ip_addr.host,
5745405Smsmith	    255 &  whoami->client_address.bp_address_u.ip_addr.lh,
5845405Smsmith	    255 &  whoami->client_address.bp_address_u.ip_addr.impno);
5945405Smsmith  if (dolog)
6045405Smsmith    syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
6145405Smsmith	    255 &  whoami->client_address.bp_address_u.ip_addr.net,
6245405Smsmith	    255 & whoami->client_address.bp_address_u.ip_addr.host,
6346215Smsmith	    255 &  whoami->client_address.bp_address_u.ip_addr.lh,
6446215Smsmith	    255 &  whoami->client_address.bp_address_u.ip_addr.impno);
6546215Smsmith
6646215Smsmith  bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr,
6746215Smsmith	sizeof(haddr));
6845405Smsmith  he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET);
6945405Smsmith  if ( ! he ) goto failed;
7045405Smsmith
7146215Smsmith  if (debug) warnx("this is host %s", he->h_name);
7246215Smsmith  if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name);
7345405Smsmith
7445405Smsmith  strncpy(askname, he->h_name, sizeof(askname));
7546215Smsmith  askname[sizeof(askname)-1] = 0;
7646215Smsmith
7746215Smsmith  if (checkhost(askname, hostname, sizeof hostname) ) {
7845405Smsmith    res.client_name = hostname;
7945405Smsmith    getdomainname(domain_name, MAX_MACHINE_NAME);
8045405Smsmith    res.domain_name = domain_name;
8145405Smsmith
8294683Sdwmalone    if (  res.router_address.address_type != IP_ADDR_TYPE ) {
8394683Sdwmalone      res.router_address.address_type = IP_ADDR_TYPE;
8448925Smsmith      bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t));
8548925Smsmith    }
8645405Smsmith    if (debug) fprintf(stderr,
8745405Smsmith		       "Returning %s   %s    %d.%d.%d.%d\n",
8845405Smsmith		       res.client_name,
8945405Smsmith		       res.domain_name,
9045405Smsmith		       255 &  res.router_address.bp_address_u.ip_addr.net,
9145405Smsmith		       255 & res.router_address.bp_address_u.ip_addr.host,
9245405Smsmith		       255 &  res.router_address.bp_address_u.ip_addr.lh,
9345405Smsmith		       255 & res.router_address.bp_address_u.ip_addr.impno);
9445405Smsmith    if (dolog) syslog(LOG_NOTICE,
9545405Smsmith		       "Returning %s   %s    %d.%d.%d.%d\n",
9645405Smsmith		       res.client_name,
9745405Smsmith		       res.domain_name,
9845405Smsmith		       255 &  res.router_address.bp_address_u.ip_addr.net,
9994683Sdwmalone		       255 & res.router_address.bp_address_u.ip_addr.host,
10094683Sdwmalone		       255 &  res.router_address.bp_address_u.ip_addr.lh,
10145405Smsmith		       255 & res.router_address.bp_address_u.ip_addr.impno);
10245405Smsmith
10345405Smsmith    return(&res);
10445405Smsmith  }
10545405Smsmith failed:
10694683Sdwmalone  if (debug) warnx("whoami failed");
10794683Sdwmalone  if (dolog) syslog(LOG_NOTICE,"whoami failed\n");
10894683Sdwmalone  return(NULL);
10994683Sdwmalone}
11094683Sdwmalone
11194683Sdwmalone
11294683Sdwmalonebp_getfile_res *
11394683Sdwmalone  bootparamproc_getfile_1_svc(getfile, req)
11494683Sdwmalonebp_getfile_arg *getfile;
11548925Smsmithstruct svc_req *req;
11694683Sdwmalone{
11748925Smsmith  char *where, *index();
11894683Sdwmalone  static bp_getfile_res res;
11994683Sdwmalone
12094683Sdwmalone  if (debug)
12194683Sdwmalone    warnx("getfile got question for \"%s\" and file \"%s\"",
12294683Sdwmalone	    getfile->client_name, getfile->file_id);
12394683Sdwmalone
12494683Sdwmalone  if (dolog)
12594683Sdwmalone    syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n",
12694683Sdwmalone	    getfile->client_name, getfile->file_id);
12794683Sdwmalone
12845405Smsmith  he = NULL;
12945405Smsmith  he = gethostbyname(getfile->client_name);
13045405Smsmith  if (! he ) goto failed;
13145405Smsmith
13245405Smsmith  strncpy(askname, he->h_name, sizeof(askname));
13345405Smsmith  askname[sizeof(askname)-1] = 0;
13445405Smsmith
13545405Smsmith  if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) {
13645405Smsmith    if ( (where = index(buffer,':')) ) {
13745405Smsmith      /* buffer is re-written to contain the name of the info of file */
13845405Smsmith      strncpy(hostname, buffer, where - buffer);
13945405Smsmith      hostname[where - buffer] = '\0';
14045405Smsmith      where++;
14145405Smsmith      strcpy(path, where);
14245405Smsmith      he = gethostbyname(hostname);
14345405Smsmith      if ( !he ) goto failed;
14445405Smsmith      bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
14545405Smsmith      res.server_name = hostname;
14645405Smsmith      res.server_path = path;
14745405Smsmith      res.server_address.address_type = IP_ADDR_TYPE;
14845405Smsmith    }
14945405Smsmith    else { /* special for dump, answer with null strings */
15045405Smsmith      if (!strcmp(getfile->file_id, "dump")) {
15145405Smsmith	res.server_name = "";
15245405Smsmith	res.server_path = "";
15345405Smsmith        res.server_address.address_type = IP_ADDR_TYPE;
15445405Smsmith	bzero(&res.server_address.bp_address_u.ip_addr,4);
15545405Smsmith      } else goto failed;
15645405Smsmith    }
15745405Smsmith    if (debug)
15845405Smsmith      fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n",
15945405Smsmith	     res.server_name, res.server_path,
16045405Smsmith	     255 &  res.server_address.bp_address_u.ip_addr.net,
16145405Smsmith	     255 & res.server_address.bp_address_u.ip_addr.host,
16245405Smsmith	     255 &  res.server_address.bp_address_u.ip_addr.lh,
16345405Smsmith	     255 & res.server_address.bp_address_u.ip_addr.impno);
16445405Smsmith    if (dolog)
16545405Smsmith      syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n",
16694683Sdwmalone	     res.server_name, res.server_path,
16745405Smsmith	     255 &  res.server_address.bp_address_u.ip_addr.net,
16845405Smsmith	     255 & res.server_address.bp_address_u.ip_addr.host,
16945405Smsmith	     255 &  res.server_address.bp_address_u.ip_addr.lh,
17045405Smsmith	     255 & res.server_address.bp_address_u.ip_addr.impno);
17145405Smsmith    return(&res);
17245405Smsmith  }
17345405Smsmith  failed:
17445405Smsmith  if (debug) warnx("getfile failed for %s", getfile->client_name);
17545405Smsmith  if (dolog) syslog(LOG_NOTICE,
17645405Smsmith		    "getfile failed for %s\n", getfile->client_name);
17745405Smsmith  return(NULL);
17894683Sdwmalone}
17945405Smsmith
18045405Smsmith/*    getthefile return 1 and fills the buffer with the information
18145405Smsmith      of the file, e g "host:/export/root/client" if it can be found.
18245405Smsmith      If the host is in the database, but the file is not, the buffer
18345405Smsmith      will be empty. (This makes it possible to give the special
18445405Smsmith      empty answer for the file "dump")   */
18545405Smsmith
18645405Smsmithint
18745405Smsmithgetthefile(askname,fileid,buffer,blen)
18845405Smsmithchar *askname;
18945405Smsmithchar *fileid, *buffer;
19094683Sdwmaloneint blen;
19145405Smsmith{
19245405Smsmith  FILE *bpf;
19345405Smsmith  char  *where;
19445405Smsmith#ifdef YP
19545405Smsmith  static char *result;
19645405Smsmith  int resultlen;
19745405Smsmith  static char *yp_domain;
19845405Smsmith#endif
19945405Smsmith
20045405Smsmith  int ch, pch, fid_len, res = 0;
20145405Smsmith  int match = 0;
20245405Smsmith  char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3];
20345405Smsmith
20494683Sdwmalone  bpf = fopen(bootpfile, "r");
20545405Smsmith  if ( ! bpf )
20645405Smsmith    errx(1, "no %s", bootpfile);
20745405Smsmith
20845405Smsmith  /* XXX see comment below */
20945405Smsmith  while ( fscanf(bpf, "%255s", hostname) > 0  && !match ) {
21045405Smsmith    if ( *hostname != '#' ) { /* comment */
21145405Smsmith      if ( ! strcmp(hostname, askname) ) {
21245405Smsmith	match = 1;
21345405Smsmith      } else {
21445405Smsmith	he = gethostbyname(hostname);
21545405Smsmith	if (he && !strcmp(he->h_name, askname)) match = 1;
21645405Smsmith      }
21745405Smsmith    }
21845405Smsmith    if (*hostname == '+' ) { /* NIS */
21945405Smsmith#ifdef YP
22045405Smsmith      if (yp_get_default_domain(&yp_domain)) {
22145405Smsmith	 if (debug) warn("NIS");
22245405Smsmith	 return(0);
22345405Smsmith      }
22445405Smsmith      if (yp_match(yp_domain, "bootparams", askname, strlen(askname),
22545405Smsmith		&result, &resultlen))
22645405Smsmith	return (0);
22745405Smsmith      if (strstr(result, fileid) == NULL) {
22845405Smsmith	buffer[0] = '\0';
22945405Smsmith      } else {
23094683Sdwmalone	snprintf(buffer, blen,
23194683Sdwmalone		"%s",strchr(strstr(result,fileid), '=') + 1);
23245405Smsmith	if (strchr(buffer, ' ') != NULL)
23345405Smsmith	  *(char *)(strchr(buffer, ' ')) = '\0';
23445405Smsmith      }
23545405Smsmith      if (fclose(bpf))
23645405Smsmith        warnx("could not close %s", bootpfile);
23745405Smsmith      return(1);
23845405Smsmith#else
23994683Sdwmalone      return(0);	/* ENOTSUP */
24094683Sdwmalone#endif
24194683Sdwmalone    }
24294683Sdwmalone    /* skip to next entry */
24394683Sdwmalone    if ( match ) break;
24494683Sdwmalone    pch = ch = getc(bpf);
24594683Sdwmalone    while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
24694683Sdwmalone      pch = ch; ch = getc(bpf);
24794683Sdwmalone    }
24894683Sdwmalone  }
24945405Smsmith
25046215Smsmith  /* if match is true we read the rest of the line to get the
25146215Smsmith     info of the file */
25246215Smsmith
25346215Smsmith  if (match) {
25445405Smsmith    fid_len = strlen(fileid);
25548925Smsmith    while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */
25645405Smsmith      ch = getc(bpf);                                /* and a character */
25745405Smsmith      if ( *info != '#' ) {                          /* Comment ? */
25845405Smsmith	if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') {
25945405Smsmith	  where = info + fid_len + 1;
26075421Sjhb	  if ( isprint( *where )) {
26145405Smsmith	    strcpy(buffer, where);                   /* found file */
26245405Smsmith	    res = 1; break;
26345405Smsmith	  }
26445405Smsmith	} else {
26548925Smsmith	  while (isspace(ch) && ch != '\n') ch = getc(bpf);
26648925Smsmith	                                             /* read to end of line */
26745405Smsmith	  if ( ch == '\n' ) {                        /* didn't find it */
26849421Smsmith	    res = -1; break;                         /* but host is there */
26946215Smsmith	  }
27048925Smsmith	  if ( ch == '\\' ) {                        /* more info */
27146215Smsmith	    ch = getc(bpf);                          /* maybe on next line */
27246215Smsmith	    if (ch == '\n') continue;                /* read it in next loop */
27346215Smsmith	    ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */
27446215Smsmith	  } else ungetc(ch, bpf);              /* but who know what a `\` is */
27548925Smsmith	}                                      /* needed for. */
27648925Smsmith      } else break;                            /* a commented rest-of-line */
27746215Smsmith    }
27848925Smsmith  }
27948925Smsmith  if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
28046215Smsmith  if ( res == -1) buffer[0] = '\0';            /* host found, file not */
28148925Smsmith  return(match);
28246215Smsmith}
28394683Sdwmalone
28446215Smsmith/* checkhost puts the hostname found in the database file in
28546215Smsmith   the hostname-variable and returns 1, if askname is a valid
28646215Smsmith   name for a host in the database */
28748925Smsmith
28846215Smsmithint
28945405Smsmithcheckhost(askname, hostname, len)
29045405Smsmithchar *askname;
29145405Smsmithchar *hostname;
29245405Smsmithint len;
29348925Smsmith{
29445405Smsmith  int ch, pch;
29545405Smsmith  FILE *bpf;
29645405Smsmith  int res = 0;
29745405Smsmith#ifdef YP
29845405Smsmith  static char *result;
29945405Smsmith  int resultlen;
30045405Smsmith  static char *yp_domain;
30194683Sdwmalone#endif
30245405Smsmith
30345405Smsmith/*  struct hostent *cmp_he;*/
30494683Sdwmalone
30545405Smsmith  bpf = fopen(bootpfile, "r");
30645405Smsmith  if ( ! bpf )
30745405Smsmith    errx(1, "no %s", bootpfile);
30845405Smsmith
30945405Smsmith  /* XXX there is no way in ISO C to specify the maximal length for a
31045405Smsmith     conversion in a variable way */
31145405Smsmith  while ( fscanf(bpf, "%254s", hostname) > 0 ) {
31294683Sdwmalone    if ( *hostname != '#' ) { /* comment */
31345405Smsmith      if ( ! strcmp(hostname, askname) ) {
31445405Smsmith        /* return true for match of hostname */
31594683Sdwmalone        res = 1;
31645405Smsmith        break;
31745405Smsmith      } else {
31845405Smsmith        /* check the alias list */
31945405Smsmith        he = NULL;
32045405Smsmith        he = gethostbyname(hostname);
32145405Smsmith        if (he && !strcmp(askname, he->h_name)) {
32245405Smsmith  	  res = 1;
32394683Sdwmalone	  break;
32445405Smsmith        }
32545405Smsmith      }
32694683Sdwmalone    }
32745405Smsmith    if (*hostname == '+' ) { /* NIS */
32845405Smsmith#ifdef YP
32945405Smsmith      if (yp_get_default_domain(&yp_domain)) {
33045405Smsmith	 if (debug) warn("NIS");
33145405Smsmith	 return(0);
33245405Smsmith      }
33345405Smsmith      if (!yp_match(yp_domain, "bootparams", askname, strlen(askname),
33445405Smsmith		&result, &resultlen)) {
33545405Smsmith        /* return true for match of hostname */
33645405Smsmith        he = NULL;
33794683Sdwmalone        he = gethostbyname(askname);
33845405Smsmith        if (he && !strcmp(askname, he->h_name)) {
33945405Smsmith  	  res = 1;
34094683Sdwmalone	  snprintf(hostname, len, "%s", he->h_name);
34145405Smsmith	}
34245405Smsmith      }
34345405Smsmith      if (fclose(bpf))
34445405Smsmith        warnx("could not close %s", bootpfile);
34545405Smsmith      return(res);
34645405Smsmith#else
34745405Smsmith      return(0);	/* ENOTSUP */
34845405Smsmith#endif
34945405Smsmith    }
35045405Smsmith    /* skip to next entry */
35145405Smsmith    pch = ch = getc(bpf);
35245405Smsmith    while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
35345405Smsmith      pch = ch; ch = getc(bpf);
35448925Smsmith    }
35545405Smsmith  }
35645405Smsmith  if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
35745405Smsmith  return(res);
35845405Smsmith}
35945405Smsmith