1*52110e02Sthorpej /* $NetBSD: bootparamd.c,v 1.7 1996/08/30 20:10:26 thorpej Exp $ */ 2*52110e02Sthorpej 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 12ae99bc57Sderaadt #include <sys/types.h> 13ae99bc57Sderaadt #include <sys/ioctl.h> 14ae99bc57Sderaadt #include <sys/stat.h> 15ae99bc57Sderaadt #include <sys/socket.h> 16ae99bc57Sderaadt #include <rpc/rpc.h> 17ae99bc57Sderaadt #include <rpcsvc/bootparam_prot.h> 18ae99bc57Sderaadt #include <stdio.h> 19ae99bc57Sderaadt #include <netdb.h> 20ae99bc57Sderaadt #include <ctype.h> 21ae99bc57Sderaadt #include <syslog.h> 220d8ec8d0Sderaadt #include <string.h> 230d8ec8d0Sderaadt #include "pathnames.h" 24ae99bc57Sderaadt 25ae99bc57Sderaadt #define MAXLEN 800 26ae99bc57Sderaadt 27ae99bc57Sderaadt struct hostent *he; 28ae99bc57Sderaadt static char buffer[MAXLEN]; 29ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME]; 30ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME]; 31ae99bc57Sderaadt static char path[MAX_PATH_LEN]; 32ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME]; 33ae99bc57Sderaadt 34d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *)); 35ae99bc57Sderaadt 36d8f00aa3Spk int _rpcsvcdirty = 0; 37d8f00aa3Spk int _rpcpmstart = 0; 38ae99bc57Sderaadt int debug = 0; 39ae99bc57Sderaadt int dolog = 0; 40ae99bc57Sderaadt unsigned long route_addr, inet_addr(); 41ae99bc57Sderaadt struct sockaddr_in my_addr; 42ae99bc57Sderaadt char *progname; 430d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 44ae99bc57Sderaadt 45ae99bc57Sderaadt extern char *optarg; 46ae99bc57Sderaadt extern int optind; 47ae99bc57Sderaadt 48ae99bc57Sderaadt void 49ae99bc57Sderaadt usage() 50ae99bc57Sderaadt { 51ae99bc57Sderaadt fprintf(stderr, 52ae99bc57Sderaadt "usage: rpc.bootparamd [-d] [-s] [-r router] [-f bootparmsfile]\n"); 53ae99bc57Sderaadt } 54ae99bc57Sderaadt 55ae99bc57Sderaadt 56ae99bc57Sderaadt /* 57ae99bc57Sderaadt * ever familiar 58ae99bc57Sderaadt */ 59ae99bc57Sderaadt int 60ae99bc57Sderaadt main(argc, argv) 61ae99bc57Sderaadt int argc; 62ae99bc57Sderaadt char **argv; 63ae99bc57Sderaadt { 64ae99bc57Sderaadt SVCXPRT *transp; 65ae99bc57Sderaadt int i, s, pid; 66ae99bc57Sderaadt char *rindex(); 67ae99bc57Sderaadt struct hostent *he; 68ae99bc57Sderaadt struct stat buf; 69ae99bc57Sderaadt char *optstring; 70d907c076Smark int c; 71ae99bc57Sderaadt 72ae99bc57Sderaadt progname = rindex(argv[0], '/'); 73ae99bc57Sderaadt if (progname) 74ae99bc57Sderaadt progname++; 75ae99bc57Sderaadt else 76ae99bc57Sderaadt progname = argv[0]; 77ae99bc57Sderaadt 78d907c076Smark while ((c = getopt(argc, argv, "dsr:f:")) != -1) 79ae99bc57Sderaadt switch (c) { 80ae99bc57Sderaadt case 'd': 81ae99bc57Sderaadt debug = 1; 82ae99bc57Sderaadt break; 83ae99bc57Sderaadt case 'r': 84ae99bc57Sderaadt if (isdigit(*optarg)) { 85ae99bc57Sderaadt route_addr = inet_addr(optarg); 86ae99bc57Sderaadt break; 87ae99bc57Sderaadt } 88ae99bc57Sderaadt he = gethostbyname(optarg); 89ae99bc57Sderaadt if (!he) { 90ae99bc57Sderaadt fprintf(stderr, "%s: No such host %s\n", 91ae99bc57Sderaadt progname, optarg); 92ae99bc57Sderaadt usage(); 93ae99bc57Sderaadt exit(1); 94ae99bc57Sderaadt } 95ae99bc57Sderaadt bcopy(he->h_addr, (char *) &route_addr, sizeof(route_addr)); 96ae99bc57Sderaadt break; 97ae99bc57Sderaadt case 'f': 98ae99bc57Sderaadt bootpfile = optarg; 99ae99bc57Sderaadt break; 100ae99bc57Sderaadt case 's': 101ae99bc57Sderaadt dolog = 1; 102ae99bc57Sderaadt #ifndef LOG_DAEMON 103ae99bc57Sderaadt openlog(progname, 0, 0); 104ae99bc57Sderaadt #else 105ae99bc57Sderaadt openlog(progname, 0, LOG_DAEMON); 106ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 107ae99bc57Sderaadt #endif 108ae99bc57Sderaadt break; 109ae99bc57Sderaadt default: 110ae99bc57Sderaadt usage(); 111ae99bc57Sderaadt exit(1); 112ae99bc57Sderaadt } 113ae99bc57Sderaadt 114ae99bc57Sderaadt if (stat(bootpfile, &buf)) { 115ae99bc57Sderaadt fprintf(stderr, "%s: ", progname); 116ae99bc57Sderaadt perror(bootpfile); 117ae99bc57Sderaadt exit(1); 118ae99bc57Sderaadt } 119ae99bc57Sderaadt if (!route_addr) { 120ae99bc57Sderaadt get_myaddress(&my_addr); 121ae99bc57Sderaadt bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof(route_addr)); 122ae99bc57Sderaadt } 123ae99bc57Sderaadt if (!debug) 124ae99bc57Sderaadt daemon(); 125ae99bc57Sderaadt 126ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 127ae99bc57Sderaadt 128ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 129ae99bc57Sderaadt if (transp == NULL) { 130ae99bc57Sderaadt fprintf(stderr, "cannot create udp service.\n"); 131ae99bc57Sderaadt exit(1); 132ae99bc57Sderaadt } 133ae99bc57Sderaadt if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, 134ae99bc57Sderaadt bootparamprog_1, IPPROTO_UDP)) { 135ae99bc57Sderaadt fprintf(stderr, 136ae99bc57Sderaadt "bootparamd: unable to register BOOTPARAMPROG version %d, udp)\n", 137ae99bc57Sderaadt BOOTPARAMVERS); 138ae99bc57Sderaadt exit(1); 139ae99bc57Sderaadt } 140ae99bc57Sderaadt svc_run(); 141ae99bc57Sderaadt fprintf(stderr, "svc_run returned\n"); 142ae99bc57Sderaadt exit(1); 143ae99bc57Sderaadt } 144ae99bc57Sderaadt 145ae99bc57Sderaadt bp_whoami_res * 146d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 147ae99bc57Sderaadt bp_whoami_arg *whoami; 148d8f00aa3Spk struct svc_req *rqstp; 149ae99bc57Sderaadt { 150ae99bc57Sderaadt long haddr; 151ae99bc57Sderaadt static bp_whoami_res res; 1520d8ec8d0Sderaadt 153ae99bc57Sderaadt if (debug) 154ae99bc57Sderaadt fprintf(stderr, "whoami got question for %d.%d.%d.%d\n", 155ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 156ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 157ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 158ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 159ae99bc57Sderaadt if (dolog) 160ae99bc57Sderaadt syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n", 161ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 162ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 163ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 164ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 165ae99bc57Sderaadt 166ae99bc57Sderaadt bcopy((char *) &whoami->client_address.bp_address_u.ip_addr, (char *) &haddr, 167ae99bc57Sderaadt sizeof(haddr)); 168ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 169ae99bc57Sderaadt if (!he) 170ae99bc57Sderaadt goto failed; 171ae99bc57Sderaadt 172ae99bc57Sderaadt if (debug) 173ae99bc57Sderaadt fprintf(stderr, "This is host %s\n", he->h_name); 174ae99bc57Sderaadt if (dolog) 175ae99bc57Sderaadt syslog(LOG_NOTICE, "This is host %s\n", he->h_name); 176ae99bc57Sderaadt 177ae99bc57Sderaadt strcpy(askname, he->h_name); 1780d8ec8d0Sderaadt if (!lookup_bootparam(askname, hostname, NULL, NULL, NULL)) { 179ae99bc57Sderaadt res.client_name = hostname; 180ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 181ae99bc57Sderaadt res.domain_name = domain_name; 182ae99bc57Sderaadt 183ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 184ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 185ae99bc57Sderaadt bcopy(&route_addr, &res.router_address.bp_address_u.ip_addr, 4); 186ae99bc57Sderaadt } 187ae99bc57Sderaadt if (debug) 188ae99bc57Sderaadt fprintf(stderr, "Returning %s %s %d.%d.%d.%d\n", 189ae99bc57Sderaadt res.client_name, res.domain_name, 190ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 191ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 192ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 193ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.impno); 194ae99bc57Sderaadt if (dolog) 195ae99bc57Sderaadt syslog(LOG_NOTICE, "Returning %s %s %d.%d.%d.%d\n", 196ae99bc57Sderaadt res.client_name, res.domain_name, 197ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 198ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 199ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 200ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.impno); 201ae99bc57Sderaadt 202ae99bc57Sderaadt return (&res); 203ae99bc57Sderaadt } 204ae99bc57Sderaadt failed: 205ae99bc57Sderaadt if (debug) 206ae99bc57Sderaadt fprintf(stderr, "whoami failed\n"); 207ae99bc57Sderaadt if (dolog) 208ae99bc57Sderaadt syslog(LOG_NOTICE, "whoami failed\n"); 209ae99bc57Sderaadt return (NULL); 210ae99bc57Sderaadt } 211ae99bc57Sderaadt 212ae99bc57Sderaadt 213ae99bc57Sderaadt bp_getfile_res * 214d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 215ae99bc57Sderaadt bp_getfile_arg *getfile; 216d8f00aa3Spk struct svc_req *rqstp; 217ae99bc57Sderaadt { 218ae99bc57Sderaadt char *where, *index(); 219ae99bc57Sderaadt static bp_getfile_res res; 2200d8ec8d0Sderaadt int err; 221ae99bc57Sderaadt 222ae99bc57Sderaadt if (debug) 223ae99bc57Sderaadt fprintf(stderr, "getfile got question for \"%s\" and file \"%s\"\n", 224ae99bc57Sderaadt getfile->client_name, getfile->file_id); 225ae99bc57Sderaadt 226ae99bc57Sderaadt if (dolog) 227ae99bc57Sderaadt syslog(LOG_NOTICE, "getfile got question for \"%s\" and file \"%s\"\n", 228ae99bc57Sderaadt getfile->client_name, getfile->file_id); 229ae99bc57Sderaadt 230ae99bc57Sderaadt he = NULL; 231ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 232ae99bc57Sderaadt if (!he) 233ae99bc57Sderaadt goto failed; 234ae99bc57Sderaadt 235ae99bc57Sderaadt strcpy(askname, he->h_name); 2360d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2370d8ec8d0Sderaadt &res.server_name, &res.server_path); 2380d8ec8d0Sderaadt if (err == 0) { 2390d8ec8d0Sderaadt he = gethostbyname(res.server_name); 240ae99bc57Sderaadt if (!he) 241ae99bc57Sderaadt goto failed; 242ae99bc57Sderaadt bcopy(he->h_addr, &res.server_address.bp_address_u.ip_addr, 4); 243ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2440d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2450d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 246ae99bc57Sderaadt res.server_name[0] = '\0'; 247ae99bc57Sderaadt res.server_path[0] = '\0'; 248ae99bc57Sderaadt bzero(&res.server_address.bp_address_u.ip_addr, 4); 2490d8ec8d0Sderaadt } else { 2500d8ec8d0Sderaadt failed: 2510d8ec8d0Sderaadt if (debug) 2520d8ec8d0Sderaadt fprintf(stderr, "getfile failed for %s\n", 2530d8ec8d0Sderaadt getfile->client_name); 2540d8ec8d0Sderaadt if (dolog) 2550d8ec8d0Sderaadt syslog(LOG_NOTICE, 2560d8ec8d0Sderaadt "getfile failed for %s\n", getfile->client_name); 2570d8ec8d0Sderaadt return (NULL); 258ae99bc57Sderaadt } 2590d8ec8d0Sderaadt 260ae99bc57Sderaadt if (debug) 261ae99bc57Sderaadt fprintf(stderr, 262ae99bc57Sderaadt "returning server:%s path:%s address: %d.%d.%d.%d\n", 263ae99bc57Sderaadt res.server_name, res.server_path, 264ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 265ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 266ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 267ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 268ae99bc57Sderaadt if (dolog) 269ae99bc57Sderaadt syslog(LOG_NOTICE, 270ae99bc57Sderaadt "returning server:%s path:%s address: %d.%d.%d.%d\n", 271ae99bc57Sderaadt res.server_name, res.server_path, 272ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 273ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 274ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 275ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 276ae99bc57Sderaadt return (&res); 277ae99bc57Sderaadt } 278ae99bc57Sderaadt 279ae99bc57Sderaadt 2800d8ec8d0Sderaadt int 2810d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 2820d8ec8d0Sderaadt char *client; 2830d8ec8d0Sderaadt char *client_canonical; 2840d8ec8d0Sderaadt char *id; 2850d8ec8d0Sderaadt char **server; 2860d8ec8d0Sderaadt char **path; 287ae99bc57Sderaadt { 2880d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 2890d8ec8d0Sderaadt #ifdef YP 2900d8ec8d0Sderaadt static char *ypbuf = NULL; 2910d8ec8d0Sderaadt static int ypbuflen = 0; 2920d8ec8d0Sderaadt #endif 2930d8ec8d0Sderaadt static char buf[BUFSIZ]; 2940d8ec8d0Sderaadt char *bp, *word; 2950d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 2960d8ec8d0Sderaadt int contin = 0; 2970d8ec8d0Sderaadt int found = 0; 298ae99bc57Sderaadt 2990d8ec8d0Sderaadt if (f == NULL) 3000d8ec8d0Sderaadt return EINVAL; /* ? */ 301ae99bc57Sderaadt 3020d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3030d8ec8d0Sderaadt int wascontin = contin; 3040d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3050d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 306ae99bc57Sderaadt 3070d8ec8d0Sderaadt switch (wascontin) { 3080d8ec8d0Sderaadt case -1: 3090d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3100d8ec8d0Sderaadt contin *= -1; 311ae99bc57Sderaadt continue; 3120d8ec8d0Sderaadt case 0: 3130d8ec8d0Sderaadt /* New line */ 3140d8ec8d0Sderaadt contin *= -1; 3150d8ec8d0Sderaadt if (*bp == '#') 3160d8ec8d0Sderaadt continue; 3170d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3180d8ec8d0Sderaadt continue; 3190d8ec8d0Sderaadt #ifdef YP 3200d8ec8d0Sderaadt /* A + in the file means try YP now */ 3210d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3220d8ec8d0Sderaadt char *ypdom; 3230d8ec8d0Sderaadt 3240d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3250d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3260d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3270d8ec8d0Sderaadt continue; 3280d8ec8d0Sderaadt bp = ypbuf; 3290d8ec8d0Sderaadt word = client; 3300d8ec8d0Sderaadt contin *= -1; 331ae99bc57Sderaadt break; 332ae99bc57Sderaadt } 3330d8ec8d0Sderaadt #endif 3340d8ec8d0Sderaadt /* See if this line's client is the one we are 3350d8ec8d0Sderaadt * looking for */ 3360d8ec8d0Sderaadt if (strcmp(word, client) != 0) { 337ae99bc57Sderaadt /* 3380d8ec8d0Sderaadt * If it didn't match, try getting the 3390d8ec8d0Sderaadt * canonical host name of the client 3400d8ec8d0Sderaadt * on this line and comparing that to 3410d8ec8d0Sderaadt * the client we are looking for 342ae99bc57Sderaadt */ 3430d8ec8d0Sderaadt struct hostent *hp = gethostbyname(word); 344031bfeccSderaadt if (hp == NULL || strcmp(hp->h_name, client)) 3450d8ec8d0Sderaadt continue; 3460d8ec8d0Sderaadt } 3470d8ec8d0Sderaadt contin *= -1; 3480d8ec8d0Sderaadt break; 3490d8ec8d0Sderaadt case 1: 3500d8ec8d0Sderaadt /* Continued line we want to parse below */ 3510d8ec8d0Sderaadt break; 3520d8ec8d0Sderaadt } 353ae99bc57Sderaadt 3540d8ec8d0Sderaadt if (client_canonical) 3550d8ec8d0Sderaadt strncpy(client_canonical, word, MAX_MACHINE_NAME); 3560d8ec8d0Sderaadt 3570d8ec8d0Sderaadt /* We have found a line for CLIENT */ 358f392a261Sglass if (id == NULL) { 359f392a261Sglass (void) fclose(f); 3600d8ec8d0Sderaadt return 0; 361f392a261Sglass } 3620d8ec8d0Sderaadt 3630d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 3640d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 3650d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 3660d8ec8d0Sderaadt /* We have found the entry we want */ 3670d8ec8d0Sderaadt *server = &word[idlen + 1]; 3680d8ec8d0Sderaadt *path = strchr(*server, ':'); 3690d8ec8d0Sderaadt if (*path == NULL) 3700d8ec8d0Sderaadt /* Malformed entry */ 3710d8ec8d0Sderaadt continue; 3720d8ec8d0Sderaadt *(*path)++ = '\0'; 3730d8ec8d0Sderaadt (void) fclose(f); 3740d8ec8d0Sderaadt return 0; 375ae99bc57Sderaadt } 376ae99bc57Sderaadt } 3770d8ec8d0Sderaadt 3780d8ec8d0Sderaadt found = 1; 379ae99bc57Sderaadt } 3800d8ec8d0Sderaadt 3810d8ec8d0Sderaadt (void) fclose(f); 3820d8ec8d0Sderaadt return found ? ENOENT : EPERM; 383ae99bc57Sderaadt } 384