summaryrefslogtreecommitdiff
path: root/usr.sbin/rpc.bootparamd/bootparamd.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /usr.sbin/rpc.bootparamd/bootparamd.c
initial import of NetBSD tree
Diffstat (limited to 'usr.sbin/rpc.bootparamd/bootparamd.c')
-rw-r--r--usr.sbin/rpc.bootparamd/bootparamd.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/usr.sbin/rpc.bootparamd/bootparamd.c b/usr.sbin/rpc.bootparamd/bootparamd.c
new file mode 100644
index 00000000000..bd0dabebfcc
--- /dev/null
+++ b/usr.sbin/rpc.bootparamd/bootparamd.c
@@ -0,0 +1,383 @@
+/*
+ * 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>
+ * Parser rewritten (adding YP support) by Roland McGrath <roland@frob.com>
+ *
+ * $Id: bootparamd.c,v 1.1 1995/10/18 08:48:05 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>
+#include <string.h>
+#include "pathnames.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 __P((struct svc_req *, SVCXPRT *));
+
+int _rpcsvcdirty = 0;
+int _rpcpmstart = 0;
+int debug = 0;
+int dolog = 0;
+unsigned long route_addr, inet_addr();
+struct sockaddr_in my_addr;
+char *progname;
+char *bootpfile = _PATH_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_svc(whoami, rqstp)
+ bp_whoami_arg *whoami;
+ struct svc_req *rqstp;
+{
+ 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 (!lookup_bootparam(askname, hostname, NULL, NULL, NULL)) {
+ 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_svc(getfile, rqstp)
+ bp_getfile_arg *getfile;
+ struct svc_req *rqstp;
+{
+ char *where, *index();
+ static bp_getfile_res res;
+ int err;
+
+ 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);
+ err = lookup_bootparam(askname, NULL, getfile->file_id,
+ &res.server_name, &res.server_path);
+ if (err == 0) {
+ he = gethostbyname(res.server_name);
+ if (!he)
+ goto failed;
+ bcopy(he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
+ res.server_address.address_type = IP_ADDR_TYPE;
+ } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) {
+ /* Special for dump, answer with null strings. */
+ res.server_name[0] = '\0';
+ res.server_path[0] = '\0';
+ bzero(&res.server_address.bp_address_u.ip_addr, 4);
+ } else {
+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);
+ }
+
+ 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);
+}
+
+
+int
+lookup_bootparam(client, client_canonical, id, server, path)
+ char *client;
+ char *client_canonical;
+ char *id;
+ char **server;
+ char **path;
+{
+ FILE *f = fopen(bootpfile, "r");
+#ifdef YP
+ static char *ypbuf = NULL;
+ static int ypbuflen = 0;
+#endif
+ static char buf[BUFSIZ];
+ char *bp, *word;
+ size_t idlen = id == NULL ? 0 : strlen(id);
+ int contin = 0;
+ int found = 0;
+
+ if (f == NULL)
+ return EINVAL; /* ? */
+
+ while (fgets(buf, sizeof buf, f)) {
+ int wascontin = contin;
+ contin = buf[strlen(buf) - 2] == '\\';
+ bp = buf + strspn(buf, " \t\n");
+
+ switch (wascontin) {
+ case -1:
+ /* Continuation of uninteresting line */
+ contin *= -1;
+ continue;
+ case 0:
+ /* New line */
+ contin *= -1;
+ if (*bp == '#')
+ continue;
+ if ((word = strsep(&bp, " \t\n")) == NULL)
+ continue;
+#ifdef YP
+ /* A + in the file means try YP now */
+ if (!strcmp(word, "+")) {
+ char *ypdom;
+
+ if (yp_get_default_domain(&ypdom) ||
+ yp_match(ypdom, "bootparams", client,
+ strlen(client), &ypbuf, &ypbuflen))
+ continue;
+ bp = ypbuf;
+ word = client;
+ contin *= -1;
+ break;
+ }
+#endif
+ /* See if this line's client is the one we are
+ * looking for */
+ if (strcmp(word, client) != 0) {
+ /*
+ * If it didn't match, try getting the
+ * canonical host name of the client
+ * on this line and comparing that to
+ * the client we are looking for
+ */
+ struct hostent *hp = gethostbyname(word);
+ if (hp == NULL || strcmp(hp->h_name, client))
+ continue;
+ }
+ contin *= -1;
+ break;
+ case 1:
+ /* Continued line we want to parse below */
+ break;
+ }
+
+ if (client_canonical)
+ strncpy(client_canonical, word, MAX_MACHINE_NAME);
+
+ /* We have found a line for CLIENT */
+ if (id == NULL) {
+ (void) fclose(f);
+ return 0;
+ }
+
+ /* Look for a value for the parameter named by ID */
+ while ((word = strsep(&bp, " \t\n")) != NULL) {
+ if (!strncmp(word, id, idlen) && word[idlen] == '=') {
+ /* We have found the entry we want */
+ *server = &word[idlen + 1];
+ *path = strchr(*server, ':');
+ if (*path == NULL)
+ /* Malformed entry */
+ continue;
+ *(*path)++ = '\0';
+ (void) fclose(f);
+ return 0;
+ }
+ }
+
+ found = 1;
+ }
+
+ (void) fclose(f);
+ return found ? ENOENT : EPERM;
+}