rpc.bootparamd written by Klas Heggemann <klas@nada.kth.se>

(yes, it belongs in usr.sbin, not libexec)
This commit is contained in:
deraadt 1994-01-08 13:22:03 +00:00
parent b38fa5acf8
commit ae99bc57e3
3 changed files with 480 additions and 0 deletions

View File

@ -0,0 +1,17 @@
# $Id: Makefile,v 1.1 1994/01/08 13:22:03 deraadt Exp $
PROG= rpc.bootparamd
SRCS= bootparamd.c bootparam_prot_svc.c
MAN8= rpc.bootparamd.0
DPADD= ${LIBRPCSVC} ${LIBUTIL}
LDADD= -lrpcsvc -lutil
bootparam_prot_svc.c: /usr/include/rpcsvc/bootparam_prot.x
ln -s /usr/include/rpcsvc/bootparam_prot.x .
ln -s /usr/include/rpcsvc/bootparam_prot.h .
rpcgen -m -o $@ bootparam_prot.x
CLEANFILES += bootparam_prot_svc.c bootparam_prot.x bootparam_prot.h
.include <bsd.prog.mk>

View File

@ -0,0 +1,407 @@
/*
* 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>
*
* Various small changes by Theo de Raadt <deraadt@fsa.ca>
*
* $Id: bootparamd.c,v 1.1 1994/01/08 13:22:04 deraadt Exp $
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <rpc/rpc.h>
#include <rpcsvc/bootparam_prot.h>
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <syslog.h>
#define MAXLEN 800
struct hostent *he;
static char buffer[MAXLEN];
static char hostname[MAX_MACHINE_NAME];
static char askname[MAX_MACHINE_NAME];
static char path[MAX_PATH_LEN];
static char domain_name[MAX_MACHINE_NAME];
extern void bootparamprog_1();
int debug = 0;
int dolog = 0;
unsigned long route_addr, inet_addr();
struct sockaddr_in my_addr;
char *progname;
char *bootpfile = "/etc/bootparams";
extern char *optarg;
extern int optind;
void
usage()
{
fprintf(stderr,
"usage: rpc.bootparamd [-d] [-s] [-r router] [-f bootparmsfile]\n");
}
/*
* ever familiar
*/
int
main(argc, argv)
int argc;
char **argv;
{
SVCXPRT *transp;
int i, s, pid;
char *rindex();
struct hostent *he;
struct stat buf;
char *optstring;
char c;
progname = rindex(argv[0], '/');
if (progname)
progname++;
else
progname = argv[0];
while ((c = getopt(argc, argv, "dsr:f:")) != EOF)
switch (c) {
case 'd':
debug = 1;
break;
case 'r':
if (isdigit(*optarg)) {
route_addr = inet_addr(optarg);
break;
}
he = gethostbyname(optarg);
if (!he) {
fprintf(stderr, "%s: No such host %s\n",
progname, optarg);
usage();
exit(1);
}
bcopy(he->h_addr, (char *) &route_addr, sizeof(route_addr));
break;
case 'f':
bootpfile = optarg;
break;
case 's':
dolog = 1;
#ifndef LOG_DAEMON
openlog(progname, 0, 0);
#else
openlog(progname, 0, LOG_DAEMON);
setlogmask(LOG_UPTO(LOG_NOTICE));
#endif
break;
default:
usage();
exit(1);
}
if (stat(bootpfile, &buf)) {
fprintf(stderr, "%s: ", progname);
perror(bootpfile);
exit(1);
}
if (!route_addr) {
get_myaddress(&my_addr);
bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof(route_addr));
}
if (!debug)
daemon();
(void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS);
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL) {
fprintf(stderr, "cannot create udp service.\n");
exit(1);
}
if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS,
bootparamprog_1, IPPROTO_UDP)) {
fprintf(stderr,
"bootparamd: unable to register BOOTPARAMPROG version %d, udp)\n",
BOOTPARAMVERS);
exit(1);
}
svc_run();
fprintf(stderr, "svc_run returned\n");
exit(1);
}
bp_whoami_res *
bootparamproc_whoami_1(whoami)
bp_whoami_arg *whoami;
{
long 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)
fprintf(stderr, "This is host %s\n", he->h_name);
if (dolog)
syslog(LOG_NOTICE, "This is host %s\n", he->h_name);
strcpy(askname, he->h_name);
if (checkhost(askname, 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, 4);
}
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)
fprintf(stderr, "whoami failed\n");
if (dolog)
syslog(LOG_NOTICE, "whoami failed\n");
return (NULL);
}
bp_getfile_res *
bootparamproc_getfile_1(getfile)
bp_getfile_arg *getfile;
{
char *where, *index();
static bp_getfile_res res;
if (debug)
fprintf(stderr, "getfile got question for \"%s\" and file \"%s\"\n",
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;
strcpy(askname, he->h_name);
if (getthefile(askname, getfile->file_id, buffer)) {
if (where = index(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[0] = '\0';
res.server_path[0] = '\0';
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)
fprintf(stderr, "getfile failed for %s\n", getfile->client_name);
if (dolog)
syslog(LOG_NOTICE,
"getfile failed for %s\n", getfile->client_name);
return (NULL);
}
/*
* getthefile return 1 and fills the buffer 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 buffer
* will be empty. (This makes it possible to give the special
* empty answer for the file "dump")
*/
getthefile(askname, fileid, buffer)
char *askname;
char *fileid, *buffer;
{
FILE *bpf;
char *where;
int ch, pch, fid_len, res = 0;
int match = 0;
char info[MAX_FILEID + MAX_PATH_LEN + MAX_MACHINE_NAME + 3];
bpf = fopen(bootpfile, "r");
if (!bpf) {
fprintf(stderr, "No %s\n", bootpfile);
exit(1);
}
while (fscanf(bpf, "%s", hostname) > 0 && !match) {
if (*hostname != '#') { /* comment */
if (!strcmp(hostname, askname)) {
match = 1;
} else {
he = gethostbyname(hostname);
if (he && !strcmp(he->h_name, askname))
match = 1;
}
}
/* 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);
while (!res && (fscanf(bpf, "%s", info)) > 0) { /* read a string */
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(buffer, where);
res = 1;
break;
}
} else {
while (isspace(ch) && ch != '\n')
ch = getc(bpf);
if (ch == '\n') {
res = -1;
break;
}
if (ch == '\\') {
ch = getc(bpf);
if (ch == '\n')
continue;
ungetc(ch, bpf);
ungetc('\\', bpf);
} else
ungetc(ch, bpf);
}
} else
break;
}
}
if (fclose(bpf)) {
fprintf(stderr, "Could not close %s\n", bootpfile);
}
if (res == -1)
buffer[0] = '\0'; /* host found, file not */
return (match);
}
/*
* checkhost puts the hostname found in the database file in
* the hostname-variable and returns 1, if askname is a valid
* name for a host in the database
*/
checkhost(askname, hostname)
char *askname;
char *hostname;
{
int ch, pch;
FILE *bpf;
int res = 0;
bpf = fopen(bootpfile, "r");
if (!bpf) {
fprintf(stderr, "No %s\n", bootpfile);
exit(1);
}
while (fscanf(bpf, "%s", hostname) > 0) {
if (!strcmp(hostname, askname)) {
/* return true for match of hostname */
res = 1;
break;
} else {
/* check the alias list */
he = NULL;
he = gethostbyname(hostname);
if (he && !strcmp(askname, he->h_name)) {
res = 1;
break;
}
}
/* skip to next entry */
pch = ch = getc(bpf);
while (!(ch == '\n' && pch != '\\') && ch != EOF) {
pch = ch;
ch = getc(bpf);
}
}
fclose(bpf);
return (res);
}

View File

@ -0,0 +1,56 @@
.\" $Id: rpc.bootparamd.8,v 1.1 1994/01/08 13:22:06 deraadt Exp $
.\" @(#)bootparamd.8
.Dd Jan 8, 1994
.Dt BOOTPARAMD 8
.Os NetBSD
.Sh NAME
.Nm bootparamd
.Nd boot parameter server
.Sh SYNOPSIS
.Nm /usr/libexec/rpc.bootparamd
.Op Fl d
.Op Fl s
.Op Fl r router
.Op Fl f file
.Sh DESCRIPTION
.Nm \&Bootparamd
is a server process that provides information to diskless clients
necessary for booting. It consults the file
.Dq Pa /etc/bootparams .
It should normally be started from
.Dq Pa /etc/rc .
.Pp
This version will allow the use of aliases on the hostname in the
.Dq Pa /etc/bootparams
file. The hostname returned in response to the booting client's whoami request
will be the name that appears in the config file, not the canonical name.
In this way you can keep the answer short enough
so that machines that cannot handle long hostnames won't fail during boot.
.Sh OPTIONS
.Bl -tag -width indent
.It Fl d
Display the debugging information. The daemon does not fork in this
case.
.It Fl s
Log the debugging information with syslog.
.It Fl r
Set the default router (a hostname or IP-address).
This defaults to the machine running the server.
.It Fl f
Specify the file to use as boot parameter file instead of
.Dq Pa /etc/bootparams .
.El
.Pp
.Sh FILES
.Bl -tag -width /etc/bootparams -compact
.It Pa /etc/bootparams
default configuration file
.El
.Sh BUGS
You may find the syslog loggings too verbose.
.Pp
It's not clear if the non-cannonical hack mentioned above is a good idea.
.Sh TODO
Support YP with a '+' line in the file
.Sh AUTHOR
Originally written by Klas Heggemann <klas@nada.kth.se>