diff options
Diffstat (limited to 'usr.sbin/bootparamd')
| -rw-r--r-- | usr.sbin/bootparamd/Makefile | 3 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/Makefile.inc | 5 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/Makefile | 26 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/Makefile.depend | 18 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/README | 60 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/bootparamd.8 | 74 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/bootparamd.c | 352 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/bootparams.5 | 85 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/bootparamd/main.c | 116 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/callbootd/Makefile | 21 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/callbootd/Makefile.depend | 18 | ||||
| -rw-r--r-- | usr.sbin/bootparamd/callbootd/callbootd.c | 191 | 
12 files changed, 969 insertions, 0 deletions
| diff --git a/usr.sbin/bootparamd/Makefile b/usr.sbin/bootparamd/Makefile new file mode 100644 index 000000000000..e89c1859a015 --- /dev/null +++ b/usr.sbin/bootparamd/Makefile @@ -0,0 +1,3 @@ +SUBDIR=	bootparamd callbootd + +.include <bsd.subdir.mk> diff --git a/usr.sbin/bootparamd/Makefile.inc b/usr.sbin/bootparamd/Makefile.inc new file mode 100644 index 000000000000..ec1bce434577 --- /dev/null +++ b/usr.sbin/bootparamd/Makefile.inc @@ -0,0 +1,5 @@ +BINDIR?=	/usr/sbin + +NO_WCAST_ALIGN= +CWARNFLAGS.clang+=	-Wno-incompatible-pointer-types-discards-qualifiers +CWARNFLAGS.gcc+=	-Wno-error=discarded-qualifiers diff --git a/usr.sbin/bootparamd/bootparamd/Makefile b/usr.sbin/bootparamd/bootparamd/Makefile new file mode 100644 index 000000000000..182cd0d13097 --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/Makefile @@ -0,0 +1,26 @@ +.include <src.opts.mk> + +PROG=	bootparamd +MAN=	bootparams.5 bootparamd.8 +SRCS=	bootparamd.c main.c ${GENSRCS} +GENSRCS=bootparam_prot.h bootparam_prot_svc.c bootparam_prot_xdr.c + +CFLAGS+= -DTFTP_DIR=\"/tftpboot\" -I. +.if ${MK_NIS} != "no" +CFLAGS+= -DYP +.endif + +CLEANFILES= ${GENSRCS} + +RPCSRC=	${SYSROOT:U${DESTDIR}}/usr/include/rpcsvc/bootparam_prot.x + +bootparam_prot_svc.c: ${RPCSRC} +	RPCGEN_CPP=${CPP:Q} rpcgen -C -m -o ${.TARGET} ${RPCSRC} + +bootparam_prot_xdr.c: ${RPCSRC} +	RPCGEN_CPP=${CPP:Q} rpcgen -C -c -o ${.TARGET} ${RPCSRC} + +bootparam_prot.h: ${RPCSRC} +	RPCGEN_CPP=${CPP:Q} rpcgen -C -h -o ${.TARGET} ${RPCSRC} + +.include <bsd.prog.mk> diff --git a/usr.sbin/bootparamd/bootparamd/Makefile.depend b/usr.sbin/bootparamd/bootparamd/Makefile.depend new file mode 100644 index 000000000000..732a025c9552 --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/Makefile.depend @@ -0,0 +1,18 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ +	include \ +	include/arpa \ +	include/rpc \ +	include/rpcsvc \ +	include/xlocale \ +	lib/${CSU_DIR} \ +	lib/libc \ +	lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/bootparamd/bootparamd/README b/usr.sbin/bootparamd/bootparamd/README new file mode 100644 index 000000000000..8428cf8634be --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/README @@ -0,0 +1,60 @@ + +This directory contains a version of the rpc.bootparamd, which have been  +written using the Sun's RPC protocol for bootparamd. To use it you must  +have a copy of the bootparam_prot.x file which on Sun systems you find in + +	/usr/include/rpcsvc/bootparam_prot.x + +(( This file was retrieved from the Sun-RPC source package )) + + +This code is not copyright, and is placed in the public domain. Feel free to  +use and modify. Please send modifications and/or suggestions + bug fixes to + +	Klas Heggemann <klas@nada.kth.se> + + +RPC.BOOTPARAMD + + +The rpc.bootparamd program does NOT use the yellow pages for the bootparams +database. This data should reside in /etc/bootparams on the local host, +or another file given when the server is started. + +The default router is set to the address of the machine running the server. +This may not be a good thing to do, so it can be modified using the -r  +option when startning the daemon. + +This program was written with the need to keep short hostnames in the +/etc/bootparams file and long (canonical) names in the hosts database. +It probably also will work in conjunction with a nameserver, since matching +is done by comparing the canonical name of the booting machine with the +canonical name of the hosts found in the bootparams database.  + +It is kept simple, e g there is no caching of data, but the bootparameter file +is read at each request.  + + +CALLBOOTD + +The debugging tool callbootd is used to check the response you get +to a specific (booting) request. It can be used as +	callbootd server inet-address  +or +	callbootd server hostname file  +where "server" is a machine running the rpc.bootparamd program, "inet-address" +is the internet address of a booting machine, "hostname" is the name of a +booting machine and "file" the requested file, typically "root", "swap" or +"dump".  + +You may also use "all" instead of a specific server, in which case a RPC +broadcast is performed. The broadcast is performed 4 times and then the  +program times out, after printing all responses.  + + +TODO + +Cache the date, instead of rereading it.  +Maybe match by comparing the inet address instead. (But beware that caching +will prevent the server from detecting that a machine has changed name +or address.) diff --git a/usr.sbin/bootparamd/bootparamd/bootparamd.8 b/usr.sbin/bootparamd/bootparamd/bootparamd.8 new file mode 100644 index 000000000000..45fa7d2aa918 --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/bootparamd.8 @@ -0,0 +1,74 @@ +.Dd December 14, 2000 +.Dt BOOTPARAMD 8 +.Os +.Sh NAME +.Nm bootparamd +.Nd boot parameter server +.Sh SYNOPSIS +.Nm +.Op Fl ds +.Op Fl r Ar router +.Op Fl f Ar file +.Sh DESCRIPTION +The +.Nm +utility is a server process that provides information to +.Xr diskless 8 +clients necessary for booting. +It consults the +.Pa /etc/bootparams +file. +.Pp +This version will allow the use of aliases on the hostname in the +.Pa /etc/bootparams +file. +The returned hostname to the +.Em whoami +request done by the booting client +will be the name that appears in +.Pa /etc/bootparams +and not the canonical name. +In this way you can keep the answer short enough +so that machines that cannot handle long hostnames will not fail during boot. +.Sh OPTIONS +.Bl -tag -width Fl +.It Fl d +Display the debugging information. +.It Fl s +Log the debugging information with +.Xr syslog 3 . +.It Fl r Ar router +The default router (a machine or an IP-address). +This defaults to the machine running the server. +.It Fl f Ar file +The file to use as boot parameter file instead of +.Pa /etc/bootparams . +.El +.Sh FILES +.Bl -tag -width /etc/bootparams -compact +.It Pa /etc/bootparams +default boot parameter file +.El +.Sh EXAMPLES +When netbooting diskless SunOS/Xkernel SPARCstations the booted SunOS kernel +also broadcasts to the all-0 address. +The SunOS kernel hangs until it receives a reply. +To accommodate this behaviour add an alias address +that responds to an all-0 broadcast. +So, add something like +.Ql "ifconfig xl0 192.168.200.254 netmask 255.255.255.255 broadcast 192.168.200.0 alias" +on the relevant network interface on your +.Nm +server. +The alias address must of course be free for use. +.Sh SEE ALSO +.Xr syslog 3 , +.Xr bootparams 5 , +.Xr diskless 8 +.Sh AUTHORS +Written by +.An Klas Heggemann Aq Mt klas@nada.kth.se . +.Sh BUGS +You may find the +.Xr syslog 3 +loggings to be verbose. diff --git a/usr.sbin/bootparamd/bootparamd/bootparamd.c b/usr.sbin/bootparamd/bootparamd/bootparamd.c new file mode 100644 index 000000000000..5100c64b5d3d --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/bootparamd.c @@ -0,0 +1,352 @@ +/* + +This code is not copyright, and is placed in the public domain. Feel free to +use and modify. Please send modifications and/or suggestions + bug fixes to + +        Klas Heggemann <klas@nada.kth.se> + +*/ + +#include <sys/cdefs.h> +#ifdef YP +#include <rpc/rpc.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#endif +#include "bootparam_prot.h" +#include <ctype.h> +#include <err.h> +#include <netdb.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + +extern int debug, dolog; +extern in_addr_t route_addr; +extern const char *bootpfile; + +#define MAXLEN 800 + +static struct hostent *he; +static char buffer[MAXLEN]; +static char hostname[MAX_MACHINE_NAME + 1]; +static char askname[MAX_MACHINE_NAME]; +static char path[MAX_PATH_LEN]; +static char domain_name[MAX_MACHINE_NAME]; + +static int getthefile(char *, char *, char *, int); +static int checkhost(char *, char *, int); + +bp_whoami_res * +bootparamproc_whoami_1_svc(bp_whoami_arg *whoami, struct svc_req *req __unused) +{ +  in_addr_t haddr; +  static bp_whoami_res res; +  if (debug) +    fprintf(stderr,"whoami got question for %d.%d.%d.%d\n", +	    255 &  whoami->client_address.bp_address_u.ip_addr.net, +	    255 & whoami->client_address.bp_address_u.ip_addr.host, +	    255 &  whoami->client_address.bp_address_u.ip_addr.lh, +	    255 &  whoami->client_address.bp_address_u.ip_addr.impno); +  if (dolog) +    syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n", +	    255 &  whoami->client_address.bp_address_u.ip_addr.net, +	    255 & whoami->client_address.bp_address_u.ip_addr.host, +	    255 &  whoami->client_address.bp_address_u.ip_addr.lh, +	    255 &  whoami->client_address.bp_address_u.ip_addr.impno); + +  bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr, +	sizeof(haddr)); +  he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET); +  if ( ! he ) goto failed; + +  if (debug) warnx("this is host %s", he->h_name); +  if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name); + +  strncpy(askname, he->h_name, sizeof(askname)); +  askname[sizeof(askname)-1] = 0; + +  if (checkhost(askname, hostname, sizeof hostname) ) { +    res.client_name = hostname; +    getdomainname(domain_name, MAX_MACHINE_NAME); +    res.domain_name = domain_name; + +    if (  res.router_address.address_type != IP_ADDR_TYPE ) { +      res.router_address.address_type = IP_ADDR_TYPE; +      bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t)); +    } +    if (debug) fprintf(stderr, +		       "Returning %s   %s    %d.%d.%d.%d\n", +		       res.client_name, +		       res.domain_name, +		       255 &  res.router_address.bp_address_u.ip_addr.net, +		       255 & res.router_address.bp_address_u.ip_addr.host, +		       255 &  res.router_address.bp_address_u.ip_addr.lh, +		       255 & res.router_address.bp_address_u.ip_addr.impno); +    if (dolog) syslog(LOG_NOTICE, +		       "Returning %s   %s    %d.%d.%d.%d\n", +		       res.client_name, +		       res.domain_name, +		       255 &  res.router_address.bp_address_u.ip_addr.net, +		       255 & res.router_address.bp_address_u.ip_addr.host, +		       255 &  res.router_address.bp_address_u.ip_addr.lh, +		       255 & res.router_address.bp_address_u.ip_addr.impno); + +    return(&res); +  } + failed: +  if (debug) warnx("whoami failed"); +  if (dolog) syslog(LOG_NOTICE,"whoami failed\n"); +  return(NULL); +} + + +bp_getfile_res * +bootparamproc_getfile_1_svc(bp_getfile_arg *getfile, struct svc_req *req __unused) +{ +  char *where; +  static bp_getfile_res res; + +  if (debug) +    warnx("getfile got question for \"%s\" and file \"%s\"", +	    getfile->client_name, getfile->file_id); + +  if (dolog) +    syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n", +	    getfile->client_name, getfile->file_id); + +  he = NULL; +  he = gethostbyname(getfile->client_name); +  if (! he ) goto failed; + +  strncpy(askname, he->h_name, sizeof(askname)); +  askname[sizeof(askname)-1] = 0; + +  if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) { +    if ( (where = strchr(buffer,':')) ) { +      /* buffer is re-written to contain the name of the info of file */ +      strncpy(hostname, buffer, where - buffer); +      hostname[where - buffer] = '\0'; +      where++; +      strcpy(path, where); +      he = gethostbyname(hostname); +      if ( !he ) goto failed; +      bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4); +      res.server_name = hostname; +      res.server_path = path; +      res.server_address.address_type = IP_ADDR_TYPE; +    } +    else { /* special for dump, answer with null strings */ +      if (!strcmp(getfile->file_id, "dump")) { +	res.server_name = ""; +	res.server_path = ""; +        res.server_address.address_type = IP_ADDR_TYPE; +	bzero(&res.server_address.bp_address_u.ip_addr,4); +      } else goto failed; +    } +    if (debug) +      fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n", +	     res.server_name, res.server_path, +	     255 &  res.server_address.bp_address_u.ip_addr.net, +	     255 & res.server_address.bp_address_u.ip_addr.host, +	     255 &  res.server_address.bp_address_u.ip_addr.lh, +	     255 & res.server_address.bp_address_u.ip_addr.impno); +    if (dolog) +      syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n", +	     res.server_name, res.server_path, +	     255 &  res.server_address.bp_address_u.ip_addr.net, +	     255 & res.server_address.bp_address_u.ip_addr.host, +	     255 &  res.server_address.bp_address_u.ip_addr.lh, +	     255 & res.server_address.bp_address_u.ip_addr.impno); +    return(&res); +  } +  failed: +  if (debug) warnx("getfile failed for %s", getfile->client_name); +  if (dolog) syslog(LOG_NOTICE, +		    "getfile failed for %s\n", getfile->client_name); +  return(NULL); +} + +/*    getthefile return 1 and fills the buf with the information +      of the file, e g "host:/export/root/client" if it can be found. +      If the host is in the database, but the file is not, the buf +      will be empty. (This makes it possible to give the special +      empty answer for the file "dump")   */ + +static int +getthefile(char *l_askname, char *fileid, char *buf, int blen __unused) +{ +  FILE *bpf; +  char  *where; +#ifdef YP +  static char *result; +  int resultlen; +  static char *yp_domain; +#endif + +  int ch, pch, fid_len, res = 0; +  int match = 0; +#define INFOLEN 1343 +  _Static_assert(INFOLEN >= MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3, +		  "INFOLEN isn't large enough"); +  char info[INFOLEN + 1]; + +  bpf = fopen(bootpfile, "r"); +  if ( ! bpf ) +    errx(1, "no %s", bootpfile); + +  /* XXX see comment below */ +  while ( fscanf(bpf, "%255s", hostname) > 0  && !match ) { +    if ( *hostname != '#' ) { /* comment */ +      if ( ! strcmp(hostname, l_askname) ) { +	match = 1; +      } else { +	he = gethostbyname(hostname); +	if (he && !strcmp(he->h_name, l_askname)) match = 1; +      } +    } +    if (*hostname == '+' ) { /* NIS */ +#ifdef YP +      if (yp_get_default_domain(&yp_domain)) { +	 if (debug) warn("NIS"); +	 return(0); +      } +      if (yp_match(yp_domain, "bootparams", l_askname, strlen(l_askname), +		&result, &resultlen)) +	return (0); +      if (strstr(result, fileid) == NULL) { +	buf[0] = '\0'; +      } else { +	snprintf(buf, blen, +		"%s",strchr(strstr(result,fileid), '=') + 1); +	if (strchr(buf, ' ') != NULL) +	  *(char *)(strchr(buf, ' ')) = '\0'; +      } +      if (fclose(bpf)) +        warnx("could not close %s", bootpfile); +      return(1); +#else +      if (fclose(bpf)) +        warnx("could not close %s", bootpfile); +      return(0);	/* ENOTSUP */ +#endif +    } +    /* skip to next entry */ +    if ( match ) break; +    pch = ch = getc(bpf); +    while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { +      pch = ch; ch = getc(bpf); +    } +  } + +  /* if match is true we read the rest of the line to get the +     info of the file */ + +  if (match) { +    fid_len = strlen(fileid); +#define AS_FORMAT(d)	"%" #d "s" +#define REXPAND(d) AS_FORMAT(d)	/* Force another preprocessor expansion */ +    while ( ! res && (fscanf(bpf, REXPAND(INFOLEN), info)) > 0) { +      ch = getc(bpf);                                /* and a character */ +      if ( *info != '#' ) {                          /* Comment ? */ +	if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') { +	  where = info + fid_len + 1; +	  if ( isprint( *where )) { +	    strcpy(buf, where);                   /* found file */ +	    res = 1; break; +	  } +	} else { +	  while (isspace(ch) && ch != '\n') ch = getc(bpf); +	                                             /* read to end of line */ +	  if ( ch == '\n' ) {                        /* didn't find it */ +	    res = -1; break;                         /* but host is there */ +	  } +	  if ( ch == '\\' ) {                        /* more info */ +	    ch = getc(bpf);                          /* maybe on next line */ +	    if (ch == '\n') continue;                /* read it in next loop */ +	    ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */ +	  } else ungetc(ch, bpf);              /* but who know what a `\` is */ +	}                                      /* needed for. */ +      } else break;                            /* a commented rest-of-line */ +    } +  } +  if (fclose(bpf)) { warnx("could not close %s", bootpfile); } +  if ( res == -1) buf[0] = '\0';            /* host found, file not */ +  return(match); +} + +/* checkhost puts the hostname found in the database file in +   the l_hostname-variable and returns 1, if l_askname is a valid +   name for a host in the database */ + +static int +checkhost(char *l_askname, char *l_hostname, int len __unused) +{ +  int ch, pch; +  FILE *bpf; +  int res = 0; +#ifdef YP +  static char *result; +  int resultlen; +  static char *yp_domain; +#endif + +/*  struct hostent *cmp_he;*/ + +  bpf = fopen(bootpfile, "r"); +  if ( ! bpf ) +    errx(1, "no %s", bootpfile); + +  /* XXX there is no way in ISO C to specify the maximal length for a +     conversion in a variable way */ +  while ( fscanf(bpf, "%254s", l_hostname) > 0 ) { +    if ( *l_hostname != '#' ) { /* comment */ +      if ( ! strcmp(l_hostname, l_askname) ) { +        /* return true for match of l_hostname */ +        res = 1; +        break; +      } else { +        /* check the alias list */ +        he = NULL; +        he = gethostbyname(l_hostname); +        if (he && !strcmp(l_askname, he->h_name)) { +  	  res = 1; +	  break; +        } +      } +    } +    if (*l_hostname == '+' ) { /* NIS */ +#ifdef YP +      if (yp_get_default_domain(&yp_domain)) { +	 if (debug) warn("NIS"); +	 return(0); +      } +      if (!yp_match(yp_domain, "bootparams", l_askname, strlen(l_askname), +		&result, &resultlen)) { +        /* return true for match of hostname */ +        he = NULL; +        he = gethostbyname(l_askname); +        if (he && !strcmp(l_askname, he->h_name)) { +  	  res = 1; +	  snprintf(l_hostname, len, "%s", he->h_name); +	} +      } +      if (fclose(bpf)) +        warnx("could not close %s", bootpfile); +      return(res); +#else +      return(0);	/* ENOTSUP */ +#endif +    } +    /* skip to next entry */ +    pch = ch = getc(bpf); +    while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { +      pch = ch; ch = getc(bpf); +    } +  } +  if (fclose(bpf)) { warnx("could not close %s", bootpfile); } +  return(res); +} diff --git a/usr.sbin/bootparamd/bootparamd/bootparams.5 b/usr.sbin/bootparamd/bootparamd/bootparams.5 new file mode 100644 index 000000000000..1e9c9b5e3166 --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/bootparams.5 @@ -0,0 +1,85 @@ +.\" +.\" Copyright (c) 1994 Gordon W. Ross +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\"    notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\"    notice, this list of conditions and the following disclaimer in the +.\"    documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\"    derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\"	from: Id: bootparams.5,v 1.2 1994/10/03 19:26:13 gwr Exp +.\" +.Dd October 2, 1994 +.Dt BOOTPARAMS 5 +.Os +.Sh NAME +.Nm bootparams +.Nd boot parameter database +.Sh SYNOPSIS +.Nm /etc/bootparams +.Sh DESCRIPTION +The +.Nm +file specifies the boot parameters that +.Xr diskless 8 +clients may request when booting over the network. +Each client supported by this server must have an entry in the +.Nm +file containing the pathnames for its +.Dq root +and (optionally) +.Dq swap +areas. +.Pp +Each line in the file +(other than comment lines that begin with a +.Ql # ) +specifies the client name followed by the pathnames that +the client may request by their logical names. +The components of the line are delimited with blank or tab, +and may be continued onto multiple lines with a backslash. +.Pp +For example: +.Bd -literal -offset indent +dummy	root=host:/export/dummy/root \\ +	swap=host:/export/dummy/swap \\ +	dump=host:/export/dummy/swap +.Ed +.Pp +When the client named +.Dq dummy +requests the pathname for its logical +.Dq root +it will be given the pathname +.Dq Pa host:/export/dummy/root +as the response to its +.Tn RPC +request. +The +.Dq host: +component must be supplied. +.Sh FILES +.Bl -tag -width /etc/bootparams -compact +.It Pa /etc/bootparams +default configuration file +.El +.Sh SEE ALSO +.Xr bootparamd 8 , +.Xr diskless 8 diff --git a/usr.sbin/bootparamd/bootparamd/main.c b/usr.sbin/bootparamd/bootparamd/main.c new file mode 100644 index 000000000000..e0aa85f4b40a --- /dev/null +++ b/usr.sbin/bootparamd/bootparamd/main.c @@ -0,0 +1,116 @@ +/* + +This code is not copyright, and is placed in the public domain. Feel free to +use and modify. Please send modifications and/or suggestions + bug fixes to + +        Klas Heggemann <klas@nada.kth.se> + +*/ + +#include <sys/cdefs.h> +#include <ctype.h> +#include <err.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "bootparam_prot.h" + +extern int debug, dolog; +extern in_addr_t route_addr; +extern const char *bootpfile; + +int debug = 0; +int dolog = 0; +in_addr_t route_addr = -1; +const char *bootpfile = "/etc/bootparams"; + +static struct sockaddr_in my_addr; + +static void usage(void) __dead2; + +int +main(int argc, char **argv) +{ +	SVCXPRT *transp; +	struct hostent *he; +	struct stat buf; +	int c; + +	while ((c = getopt(argc, argv,"dsr:f:")) != -1) +	  switch (c) { +	  case 'd': +	    debug = 1; +	    break; +	  case 'r': +	      if (isdigit((unsigned char)*optarg)) { +		route_addr = inet_addr(optarg); +		break; +	      } else { +		he = gethostbyname(optarg); +		if (he) { +		   bcopy(he->h_addr, (char *)&route_addr, sizeof(route_addr)); +		   break; +		} else { +		   errx(1, "no such host %s", optarg); +		} +	      } +	  case 'f': +	    bootpfile = optarg; +	    break; +	  case 's': +	    dolog = 1; +#ifndef LOG_DAEMON +	    openlog("bootparamd", 0 , 0); +#else +	    openlog("bootparamd", 0 , LOG_DAEMON); +	    setlogmask(LOG_UPTO(LOG_NOTICE)); +#endif +	    break; +	  default: +	    usage(); +	  } + +	if ( stat(bootpfile, &buf ) ) +	  err(1, "%s", bootpfile); + +	if (route_addr == INADDR_NONE) { +	  get_myaddress(&my_addr); +	  bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof (route_addr)); +	} + +	if (!debug) { +	  if (daemon(0,0)) +	    err(1, "fork"); +	} + + +	(void)pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); + +	transp = svcudp_create(RPC_ANYSOCK); +	if (transp == NULL) +		errx(1, "cannot create udp service"); +	if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, IPPROTO_UDP)) +		errx(1, "unable to register (BOOTPARAMPROG, BOOTPARAMVERS, udp)"); + +	svc_run(); +	errx(1, "svc_run returned"); +} + +static void +usage(void) +{ +	fprintf(stderr, +		"usage: bootparamd [-d] [-s] [-r router] [-f bootparmsfile]\n"); +	exit(1); +} diff --git a/usr.sbin/bootparamd/callbootd/Makefile b/usr.sbin/bootparamd/callbootd/Makefile new file mode 100644 index 000000000000..0228b3ef041a --- /dev/null +++ b/usr.sbin/bootparamd/callbootd/Makefile @@ -0,0 +1,21 @@ +PROG=	callbootd +MAN= +SRCS=	callbootd.c ${GENSRCS} +GENSRCS=bootparam_prot.h bootparam_prot_clnt.c bootparam_prot_xdr.c + +CFLAGS+= -I. + +CLEANFILES= ${GENSRCS} + +RPCSRC=	${SYSROOT:U${DESTDIR}}/usr/include/rpcsvc/bootparam_prot.x + +bootparam_prot_clnt.c: ${RPCSRC} +	RPCGEN_CPP=${CPP:Q} rpcgen -C -l -o ${.TARGET} ${RPCSRC} + +bootparam_prot_xdr.c: ${RPCSRC} +	RPCGEN_CPP=${CPP:Q} rpcgen -C -c -o ${.TARGET} ${RPCSRC} + +bootparam_prot.h: ${RPCSRC} +	RPCGEN_CPP=${CPP:Q} rpcgen -C -h -o ${.TARGET} ${RPCSRC} + +.include <bsd.prog.mk> diff --git a/usr.sbin/bootparamd/callbootd/Makefile.depend b/usr.sbin/bootparamd/callbootd/Makefile.depend new file mode 100644 index 000000000000..732a025c9552 --- /dev/null +++ b/usr.sbin/bootparamd/callbootd/Makefile.depend @@ -0,0 +1,18 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ +	include \ +	include/arpa \ +	include/rpc \ +	include/rpcsvc \ +	include/xlocale \ +	lib/${CSU_DIR} \ +	lib/libc \ +	lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/bootparamd/callbootd/callbootd.c b/usr.sbin/bootparamd/callbootd/callbootd.c new file mode 100644 index 000000000000..f9939d83cab9 --- /dev/null +++ b/usr.sbin/bootparamd/callbootd/callbootd.c @@ -0,0 +1,191 @@ +/* + +This code is not copyright, and is placed in the public domain. Feel free to +use and modify. Please send modifications and/or suggestions + bug fixes to + +        Klas Heggemann <klas@nada.kth.se> + +*/ + +#include <sys/cdefs.h> +#include "bootparam_prot.h" +#include <rpc/rpc.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <err.h> +#include <netdb.h> +#include <stdlib.h> + + +/* #define bp_address_u bp_address */ +#include <stdio.h> +#include <string.h> + +static int broadcast; +static char cln[MAX_MACHINE_NAME+1]; +static char dmn[MAX_MACHINE_NAME+1]; +static char path[MAX_PATH_LEN+1]; + +static void usage(void) __dead2; +int printgetfile(bp_getfile_res *); +int printwhoami(bp_whoami_res *); + +static bool_t +eachres_whoami(bp_whoami_res *resultp, struct sockaddr_in *raddr) +{ +  struct hostent *he; + +  he = gethostbyaddr((char *)&raddr->sin_addr.s_addr,4,AF_INET); +  printf("%s answered:\n", he ? he->h_name : inet_ntoa(raddr->sin_addr)); +  printwhoami(resultp); +  printf("\n"); +  return(0); +} + +static bool_t +eachres_getfile(bp_getfile_res *resultp, struct sockaddr_in *raddr) +{ +  struct hostent *he; + +  he = gethostbyaddr((char *)&raddr->sin_addr.s_addr,4,AF_INET); +  printf("%s answered:\n", he ? he->h_name : inet_ntoa(raddr->sin_addr)); +  printgetfile(resultp); +  printf("\n"); +  return(0); +} + + +int +main(int argc, char **argv) +{ +  char *server; + +  bp_whoami_arg whoami_arg; +  bp_whoami_res *whoami_res, stat_whoami_res; +  bp_getfile_arg getfile_arg; +  bp_getfile_res *getfile_res, stat_getfile_res; + + +  in_addr_t the_inet_addr; +  CLIENT *clnt = NULL;		/* Silence warnings */ + +  stat_whoami_res.client_name = cln; +  stat_whoami_res.domain_name = dmn; + +  stat_getfile_res.server_name = cln; +  stat_getfile_res.server_path = path; + +  if (argc < 3) +    usage(); + +  server = argv[1]; +  if ( ! strcmp(server , "all") ) broadcast = 1; + +  if ( ! broadcast ) { +    clnt = clnt_create(server,BOOTPARAMPROG, BOOTPARAMVERS, "udp"); +    if ( clnt == NULL ) +      errx(1, "could not contact bootparam server on host %s", server); +  } + +  switch (argc) { +  case 3: +    whoami_arg.client_address.address_type = IP_ADDR_TYPE; +    the_inet_addr = inet_addr(argv[2]); +    if ( the_inet_addr == INADDR_NONE) +      errx(2, "bogus addr %s", argv[2]); +    bcopy(&the_inet_addr,&whoami_arg.client_address.bp_address_u.ip_addr,4); + +    if (! broadcast ) { +      whoami_res = bootparamproc_whoami_1(&whoami_arg, clnt); +      printf("Whoami returning:\n"); +      if (printwhoami(whoami_res)) { +	errx(1, "bad answer returned from server %s", server); +      } else +	exit(0); +     } else { +       (void)clnt_broadcast(BOOTPARAMPROG, BOOTPARAMVERS, +			       BOOTPARAMPROC_WHOAMI, +			       (xdrproc_t)xdr_bp_whoami_arg, +			       (char *)&whoami_arg, +			       (xdrproc_t)xdr_bp_whoami_res, +			       (char *)&stat_whoami_res, +			       (resultproc_t)eachres_whoami); +       exit(0); +     } + +  case 4: + +    getfile_arg.client_name = argv[2]; +    getfile_arg.file_id = argv[3]; + +    if (! broadcast ) { +      getfile_res = bootparamproc_getfile_1(&getfile_arg,clnt); +      printf("getfile returning:\n"); +      if (printgetfile(getfile_res)) { +	errx(1, "bad answer returned from server %s", server); +      } else +	exit(0); +    } else { +      (void)clnt_broadcast(BOOTPARAMPROG, BOOTPARAMVERS, +			       BOOTPARAMPROC_GETFILE, +			       (xdrproc_t)xdr_bp_getfile_arg, +			       (char *)&getfile_arg, +			       (xdrproc_t)xdr_bp_getfile_res, +			       (char *)&stat_getfile_res, +			       (resultproc_t)eachres_getfile); +      exit(0); +    } + +  default: + +    usage(); +  } + +} + + +static void +usage(void) +{ +	fprintf(stderr, +		"usage: callbootd server procnum (IP-addr | host fileid)\n"); +    exit(1); +} + +int +printwhoami(bp_whoami_res *res) +{ +      if ( res) { +	printf("client_name:\t%s\ndomain_name:\t%s\n", +	     res->client_name, res->domain_name); +	printf("router:\t%d.%d.%d.%d\n", +	     255 &  res->router_address.bp_address_u.ip_addr.net, +	     255 & res->router_address.bp_address_u.ip_addr.host, +	     255 &  res->router_address.bp_address_u.ip_addr.lh, +	     255 & res->router_address.bp_address_u.ip_addr.impno); +	return(0); +      } else { +	warnx("null answer!!!"); +	return(1); +      } +    } + + + + +int +printgetfile(bp_getfile_res *res) +{ +      if (res) { +	printf("server_name:\t%s\nserver_address:\t%s\npath:\t%s\n", +	       res->server_name, +	       inet_ntoa(*(struct in_addr *)&res->server_address.bp_address_u.ip_addr), +	       res->server_path); +	return(0); +      } else { +	warnx("null answer!!!"); +	return(1); +      } +    } | 
