1*b5468677Sthorpej /* $NetBSD: bootparamd.c,v 1.12 1997/07/28 06:03:54 thorpej Exp $ */ 252110e02Sthorpej 3ae99bc57Sderaadt /* 4ae99bc57Sderaadt * This code is not copyright, and is placed in the public domain. 5ae99bc57Sderaadt * Feel free to use and modify. Please send modifications and/or 6ae99bc57Sderaadt * suggestions + bug fixes to Klas Heggemann <klas@nada.kth.se> 7ae99bc57Sderaadt * 8ae99bc57Sderaadt * Various small changes by Theo de Raadt <deraadt@fsa.ca> 90d8ec8d0Sderaadt * Parser rewritten (adding YP support) by Roland McGrath <roland@frob.com> 10ae99bc57Sderaadt */ 11ae99bc57Sderaadt 12*b5468677Sthorpej #include <sys/cdefs.h> 13*b5468677Sthorpej #ifndef lint 14*b5468677Sthorpej __RCSID("$NetBSD: bootparamd.c,v 1.12 1997/07/28 06:03:54 thorpej Exp $"); 15*b5468677Sthorpej #endif 16*b5468677Sthorpej 17ae99bc57Sderaadt #include <sys/types.h> 18ae99bc57Sderaadt #include <sys/ioctl.h> 19ae99bc57Sderaadt #include <sys/stat.h> 20ae99bc57Sderaadt #include <sys/socket.h> 210d53a465Smycroft 220d53a465Smycroft #include <ctype.h> 230d53a465Smycroft #include <err.h> 240d53a465Smycroft #include <netdb.h> 25*b5468677Sthorpej #include <stdlib.h> 260d53a465Smycroft #include <stdio.h> 270d53a465Smycroft #include <string.h> 280d53a465Smycroft #include <syslog.h> 29*b5468677Sthorpej #include <unistd.h> 300d53a465Smycroft 310d53a465Smycroft #include <netinet/in.h> 320d53a465Smycroft #include <arpa/inet.h> 330d53a465Smycroft 34ae99bc57Sderaadt #include <rpc/rpc.h> 35*b5468677Sthorpej #include <rpc/pmap_clnt.h> 36ae99bc57Sderaadt #include <rpcsvc/bootparam_prot.h> 37*b5468677Sthorpej #include <rpcsvc/ypclnt.h> 380d53a465Smycroft 390d8ec8d0Sderaadt #include "pathnames.h" 40ae99bc57Sderaadt 41ae99bc57Sderaadt #define MAXLEN 800 42ae99bc57Sderaadt 43ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME]; 44ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME]; 45ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME]; 46ae99bc57Sderaadt 47d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *)); 48ae99bc57Sderaadt 49d8f00aa3Spk int _rpcsvcdirty = 0; 50d8f00aa3Spk int _rpcpmstart = 0; 51ae99bc57Sderaadt int debug = 0; 52ae99bc57Sderaadt int dolog = 0; 53*b5468677Sthorpej struct in_addr route_addr; 54ae99bc57Sderaadt struct sockaddr_in my_addr; 55ee7207b7Smycroft extern char *__progname; 560d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 57ae99bc57Sderaadt 58*b5468677Sthorpej int main __P((int, char *[])); 59*b5468677Sthorpej int lookup_bootparam __P((char *, char *, char *, char **, char **)); 60*b5468677Sthorpej void usage __P((void)); 61ae99bc57Sderaadt 62ae99bc57Sderaadt 63ae99bc57Sderaadt /* 64ae99bc57Sderaadt * ever familiar 65ae99bc57Sderaadt */ 66ae99bc57Sderaadt int 67ae99bc57Sderaadt main(argc, argv) 68ae99bc57Sderaadt int argc; 69*b5468677Sthorpej char *argv[]; 70ae99bc57Sderaadt { 71ae99bc57Sderaadt SVCXPRT *transp; 72ae99bc57Sderaadt struct hostent *he; 73ae99bc57Sderaadt struct stat buf; 74d907c076Smark int c; 75ae99bc57Sderaadt 76d907c076Smark while ((c = getopt(argc, argv, "dsr:f:")) != -1) 77ae99bc57Sderaadt switch (c) { 78ae99bc57Sderaadt case 'd': 79ae99bc57Sderaadt debug = 1; 80ae99bc57Sderaadt break; 81ae99bc57Sderaadt case 'r': 82ae99bc57Sderaadt if (isdigit(*optarg)) { 83*b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 84ae99bc57Sderaadt break; 85ae99bc57Sderaadt } 86ae99bc57Sderaadt he = gethostbyname(optarg); 87*b5468677Sthorpej if (he == 0) { 880d53a465Smycroft warnx("no such host: %s\n", optarg); 89ae99bc57Sderaadt usage(); 90ae99bc57Sderaadt } 91*b5468677Sthorpej bcopy(he->h_addr, &route_addr.s_addr, he->h_length); 92ae99bc57Sderaadt break; 93ae99bc57Sderaadt case 'f': 94ae99bc57Sderaadt bootpfile = optarg; 95ae99bc57Sderaadt break; 96ae99bc57Sderaadt case 's': 97ae99bc57Sderaadt dolog = 1; 98ae99bc57Sderaadt #ifndef LOG_DAEMON 99ee7207b7Smycroft openlog(__progname, 0, 0); 100ae99bc57Sderaadt #else 101ee7207b7Smycroft openlog(__progname, 0, LOG_DAEMON); 102ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 103ae99bc57Sderaadt #endif 104ae99bc57Sderaadt break; 105ae99bc57Sderaadt default: 106ae99bc57Sderaadt usage(); 107ae99bc57Sderaadt } 108ae99bc57Sderaadt 1090d53a465Smycroft if (stat(bootpfile, &buf)) 1100d53a465Smycroft err(1, "%s", bootpfile); 1110d53a465Smycroft 112*b5468677Sthorpej if (route_addr.s_addr == 0) { 113ae99bc57Sderaadt get_myaddress(&my_addr); 114*b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 115ae99bc57Sderaadt } 1160d53a465Smycroft if (!debug) { 1170d53a465Smycroft if (daemon(0, 0)) 1180d53a465Smycroft err(1, "can't detach from terminal"); 1190d53a465Smycroft } 120ae99bc57Sderaadt 121ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 122ae99bc57Sderaadt 123ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1240d53a465Smycroft if (transp == NULL) 1250d53a465Smycroft errx(1, "can't create udp service"); 1260d53a465Smycroft 1270d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1280d53a465Smycroft IPPROTO_UDP)) 129*b5468677Sthorpej errx(1, "unable to register BOOTPARAMPROG version %ld, udp", 130ae99bc57Sderaadt BOOTPARAMVERS); 1310d53a465Smycroft 132ae99bc57Sderaadt svc_run(); 1330d53a465Smycroft errx(1, "svc_run returned"); 134ae99bc57Sderaadt } 135ae99bc57Sderaadt 136ae99bc57Sderaadt bp_whoami_res * 137d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 138ae99bc57Sderaadt bp_whoami_arg *whoami; 139d8f00aa3Spk struct svc_req *rqstp; 140ae99bc57Sderaadt { 141ae99bc57Sderaadt static bp_whoami_res res; 142b7dcf10eScgd struct hostent *he; 143b7dcf10eScgd struct in_addr inaddr; 144b7dcf10eScgd long haddr; 1450d8ec8d0Sderaadt 146ae99bc57Sderaadt if (debug) 1470d53a465Smycroft warnx("whoami got question for %d.%d.%d.%d\n", 148ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 149ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 150ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 151ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 152ae99bc57Sderaadt if (dolog) 153ae99bc57Sderaadt syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n", 154ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 155ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 156ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 157ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 158ae99bc57Sderaadt 159ae99bc57Sderaadt bcopy((char *) &whoami->client_address.bp_address_u.ip_addr, (char *) &haddr, 160ae99bc57Sderaadt sizeof(haddr)); 161ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 162b7dcf10eScgd if (he) 163b7dcf10eScgd strcpy(askname, he->h_name); 164b7dcf10eScgd else { 165b7dcf10eScgd inaddr.s_addr = haddr; 166b7dcf10eScgd strcpy(askname, inet_ntoa(inaddr)); 167b7dcf10eScgd } 168ae99bc57Sderaadt 169ae99bc57Sderaadt if (debug) 1700d53a465Smycroft warnx("This is host %s\n", askname); 171ae99bc57Sderaadt if (dolog) 172b7dcf10eScgd syslog(LOG_NOTICE, "This is host %s\n", askname); 173ae99bc57Sderaadt 1740d8ec8d0Sderaadt if (!lookup_bootparam(askname, hostname, NULL, NULL, NULL)) { 175ae99bc57Sderaadt res.client_name = hostname; 176ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 177ae99bc57Sderaadt res.domain_name = domain_name; 178ae99bc57Sderaadt 179ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 180ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 181*b5468677Sthorpej bcopy(&route_addr.s_addr, 182*b5468677Sthorpej &res.router_address.bp_address_u.ip_addr, 4); 183ae99bc57Sderaadt } 184ae99bc57Sderaadt if (debug) 1850d53a465Smycroft warnx("Returning %s %s %d.%d.%d.%d\n", 186ae99bc57Sderaadt res.client_name, res.domain_name, 187ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 188ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 189ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 190ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.impno); 191ae99bc57Sderaadt if (dolog) 192ae99bc57Sderaadt syslog(LOG_NOTICE, "Returning %s %s %d.%d.%d.%d\n", 193ae99bc57Sderaadt res.client_name, res.domain_name, 194ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 195ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 196ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 197ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.impno); 198ae99bc57Sderaadt 199ae99bc57Sderaadt return (&res); 200ae99bc57Sderaadt } 201ae99bc57Sderaadt if (debug) 2020d53a465Smycroft warnx("whoami failed\n"); 203ae99bc57Sderaadt if (dolog) 204ae99bc57Sderaadt syslog(LOG_NOTICE, "whoami failed\n"); 205ae99bc57Sderaadt return (NULL); 206ae99bc57Sderaadt } 207ae99bc57Sderaadt 208ae99bc57Sderaadt 209ae99bc57Sderaadt bp_getfile_res * 210d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 211ae99bc57Sderaadt bp_getfile_arg *getfile; 212d8f00aa3Spk struct svc_req *rqstp; 213ae99bc57Sderaadt { 214ae99bc57Sderaadt static bp_getfile_res res; 215b7dcf10eScgd struct hostent *he; 2160d8ec8d0Sderaadt int err; 217ae99bc57Sderaadt 218ae99bc57Sderaadt if (debug) 2190d53a465Smycroft warnx("getfile got question for \"%s\" and file \"%s\"\n", 220ae99bc57Sderaadt getfile->client_name, getfile->file_id); 221ae99bc57Sderaadt 222ae99bc57Sderaadt if (dolog) 223ae99bc57Sderaadt syslog(LOG_NOTICE, "getfile got question for \"%s\" and file \"%s\"\n", 224ae99bc57Sderaadt getfile->client_name, getfile->file_id); 225ae99bc57Sderaadt 226ae99bc57Sderaadt he = NULL; 227ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 228ae99bc57Sderaadt if (!he) 229ae99bc57Sderaadt goto failed; 230ae99bc57Sderaadt 231ae99bc57Sderaadt strcpy(askname, he->h_name); 2320d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2330d8ec8d0Sderaadt &res.server_name, &res.server_path); 2340d8ec8d0Sderaadt if (err == 0) { 2350d8ec8d0Sderaadt he = gethostbyname(res.server_name); 236ae99bc57Sderaadt if (!he) 237ae99bc57Sderaadt goto failed; 238ae99bc57Sderaadt bcopy(he->h_addr, &res.server_address.bp_address_u.ip_addr, 4); 239ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2400d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2410d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 242ae99bc57Sderaadt res.server_name[0] = '\0'; 243ae99bc57Sderaadt res.server_path[0] = '\0'; 244ae99bc57Sderaadt bzero(&res.server_address.bp_address_u.ip_addr, 4); 2450d8ec8d0Sderaadt } else { 2460d8ec8d0Sderaadt failed: 2470d8ec8d0Sderaadt if (debug) 2480d53a465Smycroft warnx("getfile failed for %s\n", 2490d8ec8d0Sderaadt getfile->client_name); 2500d8ec8d0Sderaadt if (dolog) 2510d8ec8d0Sderaadt syslog(LOG_NOTICE, 2520d8ec8d0Sderaadt "getfile failed for %s\n", getfile->client_name); 2530d8ec8d0Sderaadt return (NULL); 254ae99bc57Sderaadt } 2550d8ec8d0Sderaadt 256ae99bc57Sderaadt if (debug) 2570d53a465Smycroft warnx( 258ae99bc57Sderaadt "returning server:%s path:%s address: %d.%d.%d.%d\n", 259ae99bc57Sderaadt res.server_name, res.server_path, 260ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 261ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 262ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 263ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 264ae99bc57Sderaadt if (dolog) 265ae99bc57Sderaadt syslog(LOG_NOTICE, 266ae99bc57Sderaadt "returning server:%s path:%s address: %d.%d.%d.%d\n", 267ae99bc57Sderaadt res.server_name, res.server_path, 268ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 269ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 270ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 271ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 272ae99bc57Sderaadt return (&res); 273ae99bc57Sderaadt } 274ae99bc57Sderaadt 275ae99bc57Sderaadt 2760d8ec8d0Sderaadt int 2770d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 2780d8ec8d0Sderaadt char *client; 2790d8ec8d0Sderaadt char *client_canonical; 2800d8ec8d0Sderaadt char *id; 2810d8ec8d0Sderaadt char **server; 2820d8ec8d0Sderaadt char **path; 283ae99bc57Sderaadt { 2840d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 2850d8ec8d0Sderaadt #ifdef YP 2860d8ec8d0Sderaadt static char *ypbuf = NULL; 2870d8ec8d0Sderaadt static int ypbuflen = 0; 2880d8ec8d0Sderaadt #endif 2890d8ec8d0Sderaadt static char buf[BUFSIZ]; 290*b5468677Sthorpej char *bp, *word = NULL; 2910d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 2920d8ec8d0Sderaadt int contin = 0; 2930d8ec8d0Sderaadt int found = 0; 294ae99bc57Sderaadt 2950d8ec8d0Sderaadt if (f == NULL) 2960d8ec8d0Sderaadt return EINVAL; /* ? */ 297ae99bc57Sderaadt 2980d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 2990d8ec8d0Sderaadt int wascontin = contin; 3000d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3010d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 302ae99bc57Sderaadt 3030d8ec8d0Sderaadt switch (wascontin) { 3040d8ec8d0Sderaadt case -1: 3050d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3060d8ec8d0Sderaadt contin *= -1; 307ae99bc57Sderaadt continue; 3080d8ec8d0Sderaadt case 0: 3090d8ec8d0Sderaadt /* New line */ 3100d8ec8d0Sderaadt contin *= -1; 3110d8ec8d0Sderaadt if (*bp == '#') 3120d8ec8d0Sderaadt continue; 3130d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3140d8ec8d0Sderaadt continue; 3150d8ec8d0Sderaadt #ifdef YP 3160d8ec8d0Sderaadt /* A + in the file means try YP now */ 3170d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3180d8ec8d0Sderaadt char *ypdom; 3190d8ec8d0Sderaadt 3200d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3210d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3220d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3230d8ec8d0Sderaadt continue; 3240d8ec8d0Sderaadt bp = ypbuf; 3250d8ec8d0Sderaadt word = client; 3260d8ec8d0Sderaadt contin *= -1; 327ae99bc57Sderaadt break; 328ae99bc57Sderaadt } 3290d8ec8d0Sderaadt #endif 3300d8ec8d0Sderaadt /* See if this line's client is the one we are 3310d8ec8d0Sderaadt * looking for */ 332010a229cScgd if (strcasecmp(word, client) != 0) { 333ae99bc57Sderaadt /* 3340d8ec8d0Sderaadt * If it didn't match, try getting the 3350d8ec8d0Sderaadt * canonical host name of the client 3360d8ec8d0Sderaadt * on this line and comparing that to 3370d8ec8d0Sderaadt * the client we are looking for 338ae99bc57Sderaadt */ 3390d8ec8d0Sderaadt struct hostent *hp = gethostbyname(word); 340010a229cScgd if (hp == NULL || 341010a229cScgd strcasecmp(hp->h_name, client)) 3420d8ec8d0Sderaadt continue; 3430d8ec8d0Sderaadt } 3440d8ec8d0Sderaadt contin *= -1; 3450d8ec8d0Sderaadt break; 3460d8ec8d0Sderaadt case 1: 3470d8ec8d0Sderaadt /* Continued line we want to parse below */ 3480d8ec8d0Sderaadt break; 3490d8ec8d0Sderaadt } 350ae99bc57Sderaadt 3510d8ec8d0Sderaadt if (client_canonical) 3520d8ec8d0Sderaadt strncpy(client_canonical, word, MAX_MACHINE_NAME); 3530d8ec8d0Sderaadt 3540d8ec8d0Sderaadt /* We have found a line for CLIENT */ 355f392a261Sglass if (id == NULL) { 356f392a261Sglass (void) fclose(f); 3570d8ec8d0Sderaadt return 0; 358f392a261Sglass } 3590d8ec8d0Sderaadt 3600d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 3610d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 3620d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 3630d8ec8d0Sderaadt /* We have found the entry we want */ 3640d8ec8d0Sderaadt *server = &word[idlen + 1]; 3650d8ec8d0Sderaadt *path = strchr(*server, ':'); 3660d8ec8d0Sderaadt if (*path == NULL) 3670d8ec8d0Sderaadt /* Malformed entry */ 3680d8ec8d0Sderaadt continue; 3690d8ec8d0Sderaadt *(*path)++ = '\0'; 3700d8ec8d0Sderaadt (void) fclose(f); 3710d8ec8d0Sderaadt return 0; 372ae99bc57Sderaadt } 373ae99bc57Sderaadt } 3740d8ec8d0Sderaadt 3750d8ec8d0Sderaadt found = 1; 376ae99bc57Sderaadt } 3770d8ec8d0Sderaadt 3780d8ec8d0Sderaadt (void) fclose(f); 3790d8ec8d0Sderaadt return found ? ENOENT : EPERM; 380ae99bc57Sderaadt } 381*b5468677Sthorpej 382*b5468677Sthorpej void 383*b5468677Sthorpej usage() 384*b5468677Sthorpej { 385*b5468677Sthorpej fprintf(stderr, 386*b5468677Sthorpej "usage: %s [-d] [-s] [-r router] [-f bootparmsfile]\n", __progname); 387*b5468677Sthorpej exit(1); 388*b5468677Sthorpej } 389