1*4ac5e36aSjhawk /* $NetBSD: bootparamd.c,v 1.39 2001/04/11 06:21:49 jhawk 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 12b5468677Sthorpej #include <sys/cdefs.h> 13b5468677Sthorpej #ifndef lint 14*4ac5e36aSjhawk __RCSID("$NetBSD: bootparamd.c,v 1.39 2001/04/11 06:21:49 jhawk Exp $"); 15b5468677Sthorpej #endif 16b5468677Sthorpej 17ae99bc57Sderaadt #include <sys/types.h> 18ae99bc57Sderaadt #include <sys/ioctl.h> 19ae99bc57Sderaadt #include <sys/stat.h> 20ae99bc57Sderaadt #include <sys/socket.h> 210d53a465Smycroft 22c1b4b344Sthorpej #include <assert.h> 230d53a465Smycroft #include <ctype.h> 24d3964689Schristos #include <errno.h> 250d53a465Smycroft #include <err.h> 26c1b4b344Sthorpej #include <fnmatch.h> 270d53a465Smycroft #include <netdb.h> 28b5468677Sthorpej #include <stdlib.h> 290d53a465Smycroft #include <stdio.h> 300d53a465Smycroft #include <string.h> 310d53a465Smycroft #include <syslog.h> 32b5468677Sthorpej #include <unistd.h> 33653c3855Sthorpej #include <util.h> 3408507c14Sitojun #include <ifaddrs.h> 350d53a465Smycroft 3603b1bcc6Sitojun #include <net/if.h> 3703b1bcc6Sitojun 380d53a465Smycroft #include <netinet/in.h> 390d53a465Smycroft #include <arpa/inet.h> 400d53a465Smycroft 41ae99bc57Sderaadt #include <rpc/rpc.h> 42b5468677Sthorpej #include <rpc/pmap_clnt.h> 43ae99bc57Sderaadt #include <rpcsvc/bootparam_prot.h> 44b5468677Sthorpej #include <rpcsvc/ypclnt.h> 450d53a465Smycroft 460d8ec8d0Sderaadt #include "pathnames.h" 47ae99bc57Sderaadt 48ae99bc57Sderaadt #define MAXLEN 800 49ae99bc57Sderaadt 50ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME]; 51ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME]; 52ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME]; 53ae99bc57Sderaadt 54d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *)); 55ae99bc57Sderaadt 56d8f00aa3Spk int _rpcsvcdirty = 0; 57d8f00aa3Spk int _rpcpmstart = 0; 58ae99bc57Sderaadt int debug = 0; 59ae99bc57Sderaadt int dolog = 0; 60b5468677Sthorpej struct in_addr route_addr; 61ae99bc57Sderaadt struct sockaddr_in my_addr; 620d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 63ae99bc57Sderaadt 64b5468677Sthorpej int main __P((int, char *[])); 65b5468677Sthorpej int lookup_bootparam __P((char *, char *, char *, char **, char **)); 66b5468677Sthorpej void usage __P((void)); 6708507c14Sitojun static int get_localaddr __P((const char *, struct sockaddr_in *)); 68ae99bc57Sderaadt 69ae99bc57Sderaadt 70ae99bc57Sderaadt /* 71ae99bc57Sderaadt * ever familiar 72ae99bc57Sderaadt */ 73ae99bc57Sderaadt int 74ae99bc57Sderaadt main(argc, argv) 75ae99bc57Sderaadt int argc; 76b5468677Sthorpej char *argv[]; 77ae99bc57Sderaadt { 78ae99bc57Sderaadt SVCXPRT *transp; 79ae99bc57Sderaadt struct hostent *he; 80ae99bc57Sderaadt struct stat buf; 81d907c076Smark int c; 82ae99bc57Sderaadt 83d907c076Smark while ((c = getopt(argc, argv, "dsr:f:")) != -1) 84ae99bc57Sderaadt switch (c) { 85ae99bc57Sderaadt case 'd': 86ae99bc57Sderaadt debug = 1; 87ae99bc57Sderaadt break; 88ae99bc57Sderaadt case 'r': 89ae99bc57Sderaadt if (isdigit(*optarg)) { 90b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 91ae99bc57Sderaadt break; 92ae99bc57Sderaadt } 93ae99bc57Sderaadt he = gethostbyname(optarg); 94b5468677Sthorpej if (he == 0) { 95312c7832Smikel warnx("no such host: %s", optarg); 96ae99bc57Sderaadt usage(); 97ae99bc57Sderaadt } 987e807419Slukem memmove(&route_addr.s_addr, he->h_addr, he->h_length); 99ae99bc57Sderaadt break; 100ae99bc57Sderaadt case 'f': 101ae99bc57Sderaadt bootpfile = optarg; 102ae99bc57Sderaadt break; 103ae99bc57Sderaadt case 's': 104ae99bc57Sderaadt dolog = 1; 105ae99bc57Sderaadt #ifndef LOG_DAEMON 10613220245Slukem openlog("rpc.bootparamd", 0, 0); 107ae99bc57Sderaadt #else 10813220245Slukem openlog("rpc.bootparamd", 0, LOG_DAEMON); 109ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 110ae99bc57Sderaadt #endif 111ae99bc57Sderaadt break; 112ae99bc57Sderaadt default: 113ae99bc57Sderaadt usage(); 114ae99bc57Sderaadt } 115ae99bc57Sderaadt 1160d53a465Smycroft if (stat(bootpfile, &buf)) 1170d53a465Smycroft err(1, "%s", bootpfile); 1180d53a465Smycroft 119b5468677Sthorpej if (route_addr.s_addr == 0) { 12008507c14Sitojun if (get_localaddr(NULL, &my_addr) != 0) 12108507c14Sitojun errx(1, "router address not found"); 122b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 123ae99bc57Sderaadt } 1240d53a465Smycroft if (!debug) { 1250d53a465Smycroft if (daemon(0, 0)) 1260d53a465Smycroft err(1, "can't detach from terminal"); 1270d53a465Smycroft } 128653c3855Sthorpej pidfile(NULL); 129ae99bc57Sderaadt 130ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 131ae99bc57Sderaadt 132ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1330d53a465Smycroft if (transp == NULL) 1340d53a465Smycroft errx(1, "can't create udp service"); 1350d53a465Smycroft 1360d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1370d53a465Smycroft IPPROTO_UDP)) 138a3b6375dStron /* 139a3b6375dStron * Do NOT change the "%u" in the format string below to "%lu". If your 140a3b6375dStron * build fails update the "rpcgen" program and use "make cleandir" and 141a3b6375dStron * "make includes" in "src/lib/librpcsvc" afterwards. 142a3b6375dStron */ 1437dca1ce9Sexplorer errx(1, "unable to register BOOTPARAMPROG version %u, udp", 144ae99bc57Sderaadt BOOTPARAMVERS); 1450d53a465Smycroft 146ae99bc57Sderaadt svc_run(); 1470d53a465Smycroft errx(1, "svc_run returned"); 148ae99bc57Sderaadt } 149ae99bc57Sderaadt 150ae99bc57Sderaadt bp_whoami_res * 151d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 152ae99bc57Sderaadt bp_whoami_arg *whoami; 153d8f00aa3Spk struct svc_req *rqstp; 154ae99bc57Sderaadt { 155ae99bc57Sderaadt static bp_whoami_res res; 156b7dcf10eScgd struct hostent *he; 15788e77501Snathanw struct in_addr haddr; 158d3964689Schristos int e; 1590d8ec8d0Sderaadt 160ae99bc57Sderaadt if (debug) 161312c7832Smikel warnx("whoami got question for %d.%d.%d.%d", 162ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 163ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 164ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 165ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 166ae99bc57Sderaadt if (dolog) 167312c7832Smikel syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d", 168ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 169ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 170ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 171ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 172ae99bc57Sderaadt 1737e807419Slukem memmove((char *) &haddr, 1747e807419Slukem (char *) &whoami->client_address.bp_address_u.ip_addr, 1757e807419Slukem sizeof(haddr)); 176ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 177ddc2dd4fSmrg if (he) { 178ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 179ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 180ddc2dd4fSmrg } else { 18188e77501Snathanw strncpy(askname, inet_ntoa(haddr), sizeof(askname)); 182ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 183b7dcf10eScgd } 184ae99bc57Sderaadt 185ae99bc57Sderaadt if (debug) 186312c7832Smikel warnx("This is host %s", askname); 187ae99bc57Sderaadt if (dolog) 188312c7832Smikel syslog(LOG_NOTICE, "This is host %s", askname); 189ae99bc57Sderaadt 190d3964689Schristos if ((e = lookup_bootparam(askname, hostname, NULL, NULL, NULL)) == 0) { 191ae99bc57Sderaadt res.client_name = hostname; 192ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 193ae99bc57Sderaadt res.domain_name = domain_name; 194ae99bc57Sderaadt 195ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 196ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 1977e807419Slukem memmove(&res.router_address.bp_address_u.ip_addr, 1987e807419Slukem &route_addr.s_addr,4); 199ae99bc57Sderaadt } 200ae99bc57Sderaadt if (debug) 201312c7832Smikel warnx("Returning %s %s %d.%d.%d.%d", 202ae99bc57Sderaadt res.client_name, res.domain_name, 203ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 204ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 205ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 206ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 207ae99bc57Sderaadt if (dolog) 208312c7832Smikel syslog(LOG_NOTICE, "Returning %s %s %d.%d.%d.%d", 209ae99bc57Sderaadt res.client_name, res.domain_name, 210ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 211ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 212ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 213ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 214ae99bc57Sderaadt 215ae99bc57Sderaadt return (&res); 216ae99bc57Sderaadt } 217d3964689Schristos errno = e; 218ae99bc57Sderaadt if (debug) 219d3964689Schristos warn("whoami failed"); 220ae99bc57Sderaadt if (dolog) 221d3964689Schristos syslog(LOG_NOTICE, "whoami failed %m"); 222ae99bc57Sderaadt return (NULL); 223ae99bc57Sderaadt } 224ae99bc57Sderaadt 225ae99bc57Sderaadt 226ae99bc57Sderaadt bp_getfile_res * 227d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 228ae99bc57Sderaadt bp_getfile_arg *getfile; 229d8f00aa3Spk struct svc_req *rqstp; 230ae99bc57Sderaadt { 231ae99bc57Sderaadt static bp_getfile_res res; 232b7dcf10eScgd struct hostent *he; 2330d8ec8d0Sderaadt int err; 234ae99bc57Sderaadt 235ae99bc57Sderaadt if (debug) 236312c7832Smikel warnx("getfile got question for \"%s\" and file \"%s\"", 237ae99bc57Sderaadt getfile->client_name, getfile->file_id); 238ae99bc57Sderaadt 239ae99bc57Sderaadt if (dolog) 240312c7832Smikel syslog(LOG_NOTICE, 241312c7832Smikel "getfile got question for \"%s\" and file \"%s\"", 242ae99bc57Sderaadt getfile->client_name, getfile->file_id); 243ae99bc57Sderaadt 244ae99bc57Sderaadt he = NULL; 245ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 246*4ac5e36aSjhawk if (!he) { 247*4ac5e36aSjhawk if (debug) 248*4ac5e36aSjhawk warnx("getfile can't resolve client %s", 249*4ac5e36aSjhawk getfile->client_name); 250*4ac5e36aSjhawk if (dolog) 251*4ac5e36aSjhawk syslog(LOG_NOTICE, "getfile can't resolve client %s", 252*4ac5e36aSjhawk getfile->client_name); 253*4ac5e36aSjhawk return (NULL); 254*4ac5e36aSjhawk } 255ae99bc57Sderaadt 256ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 257ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 2580d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2590d8ec8d0Sderaadt &res.server_name, &res.server_path); 2600d8ec8d0Sderaadt if (err == 0) { 2610d8ec8d0Sderaadt he = gethostbyname(res.server_name); 262*4ac5e36aSjhawk if (!he) { 263*4ac5e36aSjhawk if (debug) 264*4ac5e36aSjhawk warnx("getfile can't resolve server %s for %s", 265*4ac5e36aSjhawk res.server_name, getfile->client_name); 266*4ac5e36aSjhawk if (dolog) 267*4ac5e36aSjhawk syslog(LOG_NOTICE, 268*4ac5e36aSjhawk "getfile can't resolve server %s for %s", 269*4ac5e36aSjhawk res.server_name, getfile->client_name); 270*4ac5e36aSjhawk return (NULL); 271*4ac5e36aSjhawk 272*4ac5e36aSjhawk } 2737e807419Slukem memmove(&res.server_address.bp_address_u.ip_addr, 2747e807419Slukem he->h_addr, 4); 275ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2760d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2770d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 278ae99bc57Sderaadt res.server_name[0] = '\0'; 279ae99bc57Sderaadt res.server_path[0] = '\0'; 2807e807419Slukem memset(&res.server_address.bp_address_u.ip_addr, 0, 4); 2810d8ec8d0Sderaadt } else { 2820d8ec8d0Sderaadt if (debug) 283*4ac5e36aSjhawk warnx("getfile lookup failed for %s", 2840d8ec8d0Sderaadt getfile->client_name); 2850d8ec8d0Sderaadt if (dolog) 2860d8ec8d0Sderaadt syslog(LOG_NOTICE, 287*4ac5e36aSjhawk "getfile lookup failed for %s", 288*4ac5e36aSjhawk getfile->client_name); 2890d8ec8d0Sderaadt return (NULL); 290ae99bc57Sderaadt } 2910d8ec8d0Sderaadt 292ae99bc57Sderaadt if (debug) 2930d53a465Smycroft warnx( 294312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 295ae99bc57Sderaadt res.server_name, res.server_path, 296ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 297ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 298ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 299ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 300ae99bc57Sderaadt if (dolog) 301ae99bc57Sderaadt syslog(LOG_NOTICE, 302312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 303ae99bc57Sderaadt res.server_name, res.server_path, 304ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 305ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 306ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 307ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 308ae99bc57Sderaadt return (&res); 309ae99bc57Sderaadt } 310ae99bc57Sderaadt 311ae99bc57Sderaadt 3120d8ec8d0Sderaadt int 3130d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 3140d8ec8d0Sderaadt char *client; 3150d8ec8d0Sderaadt char *client_canonical; 3160d8ec8d0Sderaadt char *id; 3170d8ec8d0Sderaadt char **server; 3180d8ec8d0Sderaadt char **path; 319ae99bc57Sderaadt { 3200d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 3210d8ec8d0Sderaadt #ifdef YP 3220d8ec8d0Sderaadt static char *ypbuf = NULL; 3230d8ec8d0Sderaadt static int ypbuflen = 0; 3240d8ec8d0Sderaadt #endif 3250d8ec8d0Sderaadt static char buf[BUFSIZ]; 326c1b4b344Sthorpej char *canon = NULL, *bp, *word = NULL; 3270d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 3280d8ec8d0Sderaadt int contin = 0; 3290d8ec8d0Sderaadt int found = 0; 330ae99bc57Sderaadt 3310d8ec8d0Sderaadt if (f == NULL) 3320d8ec8d0Sderaadt return EINVAL; /* ? */ 333ae99bc57Sderaadt 3340d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3350d8ec8d0Sderaadt int wascontin = contin; 3360d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3370d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 338ae99bc57Sderaadt 3390d8ec8d0Sderaadt switch (wascontin) { 3400d8ec8d0Sderaadt case -1: 3410d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3420d8ec8d0Sderaadt contin *= -1; 343ae99bc57Sderaadt continue; 3440d8ec8d0Sderaadt case 0: 3450d8ec8d0Sderaadt /* New line */ 3460d8ec8d0Sderaadt contin *= -1; 3470d8ec8d0Sderaadt if (*bp == '#') 3480d8ec8d0Sderaadt continue; 3490d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3500d8ec8d0Sderaadt continue; 3510d8ec8d0Sderaadt #ifdef YP 3520d8ec8d0Sderaadt /* A + in the file means try YP now */ 3530d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3540d8ec8d0Sderaadt char *ypdom; 3550d8ec8d0Sderaadt 3560d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3570d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3580d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3590d8ec8d0Sderaadt continue; 3600d8ec8d0Sderaadt bp = ypbuf; 3610d8ec8d0Sderaadt word = client; 3620d8ec8d0Sderaadt contin *= -1; 363ae99bc57Sderaadt break; 364ae99bc57Sderaadt } 3650d8ec8d0Sderaadt #endif 366d3964689Schristos if (debug) 367d3964689Schristos warnx("match %s with %s", word, client); 368c1b4b344Sthorpej 369c1b4b344Sthorpej #define HASGLOB(str) \ 370c1b4b344Sthorpej (strchr(str, '*') != NULL || \ 371c1b4b344Sthorpej strchr(str, '?') != NULL || \ 372c1b4b344Sthorpej strchr(str, '[') != NULL || \ 373c1b4b344Sthorpej strchr(str, ']') != NULL) 374c1b4b344Sthorpej 3750d8ec8d0Sderaadt /* See if this line's client is the one we are 3760d8ec8d0Sderaadt * looking for */ 377c1b4b344Sthorpej if (fnmatch(word, client, FNM_CASEFOLD) == 0) { 378c1b4b344Sthorpej /* 379c1b4b344Sthorpej * Match. The token may be globbed, we 380c1b4b344Sthorpej * can't just return that as the canonical 381c1b4b344Sthorpej * name. Check to see if the token has any 382c1b4b344Sthorpej * globbing characters in it (*, ?, [, ]). 383c1b4b344Sthorpej * If so, just return the name we already 384c1b4b344Sthorpej * have. Otherwise, return the token. 385c1b4b344Sthorpej */ 386c1b4b344Sthorpej if (HASGLOB(word)) 387c1b4b344Sthorpej canon = client; 388c1b4b344Sthorpej else 389c1b4b344Sthorpej canon = word; 390c1b4b344Sthorpej } else { 39129ea834fSthorpej struct hostent *hp; 392ae99bc57Sderaadt /* 3930d8ec8d0Sderaadt * If it didn't match, try getting the 3940d8ec8d0Sderaadt * canonical host name of the client 39529ea834fSthorpej * on this line, if it's not a glob, 39629ea834fSthorpej * and comparing it to the client we 39729ea834fSthorpej * are looking up. 398ae99bc57Sderaadt */ 39929ea834fSthorpej if (HASGLOB(word)) { 400bf094b72Sabs if (debug) 40129ea834fSthorpej warnx("Skipping non-match: %s", 40229ea834fSthorpej word); 403bf094b72Sabs continue; 404bf094b72Sabs } 40529ea834fSthorpej if ((hp = gethostbyname(word)) == NULL) { 40629ea834fSthorpej if (debug) 40729ea834fSthorpej warnx( 40829ea834fSthorpej "Unknown bootparams host %s", 40929ea834fSthorpej word); 41029ea834fSthorpej if (dolog) 41129ea834fSthorpej syslog(LOG_NOTICE, 41229ea834fSthorpej "Unknown bootparams host %s", 41329ea834fSthorpej word); 414e9aaacc8Senami continue; 415c1b4b344Sthorpej } 41629ea834fSthorpej if (strcasecmp(hp->h_name, client) != 0) 41729ea834fSthorpej continue; 41829ea834fSthorpej canon = hp->h_name; 41929ea834fSthorpej } 420c1b4b344Sthorpej 421c1b4b344Sthorpej #undef HASGLOB 422c1b4b344Sthorpej 4230d8ec8d0Sderaadt contin *= -1; 4240d8ec8d0Sderaadt break; 4250d8ec8d0Sderaadt case 1: 4260d8ec8d0Sderaadt /* Continued line we want to parse below */ 4270d8ec8d0Sderaadt break; 4280d8ec8d0Sderaadt } 429ae99bc57Sderaadt 430c1b4b344Sthorpej assert(canon != NULL); 4310d8ec8d0Sderaadt if (client_canonical) 432c1b4b344Sthorpej strncpy(client_canonical, canon, MAX_MACHINE_NAME); 4330d8ec8d0Sderaadt 4340d8ec8d0Sderaadt /* We have found a line for CLIENT */ 435f392a261Sglass if (id == NULL) { 436f392a261Sglass (void) fclose(f); 4370d8ec8d0Sderaadt return 0; 438f392a261Sglass } 4390d8ec8d0Sderaadt 4400d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 4410d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 4420d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 4430d8ec8d0Sderaadt /* We have found the entry we want */ 4440d8ec8d0Sderaadt *server = &word[idlen + 1]; 4450d8ec8d0Sderaadt *path = strchr(*server, ':'); 4460d8ec8d0Sderaadt if (*path == NULL) 4470d8ec8d0Sderaadt /* Malformed entry */ 4480d8ec8d0Sderaadt continue; 4490d8ec8d0Sderaadt *(*path)++ = '\0'; 4500d8ec8d0Sderaadt (void) fclose(f); 4510d8ec8d0Sderaadt return 0; 452ae99bc57Sderaadt } 453ae99bc57Sderaadt } 4540d8ec8d0Sderaadt 4550d8ec8d0Sderaadt found = 1; 456ae99bc57Sderaadt } 4570d8ec8d0Sderaadt 4580d8ec8d0Sderaadt (void) fclose(f); 4590d8ec8d0Sderaadt return found ? ENOENT : EPERM; 460ae99bc57Sderaadt } 461b5468677Sthorpej 462b5468677Sthorpej void 463b5468677Sthorpej usage() 464b5468677Sthorpej { 465b5468677Sthorpej fprintf(stderr, 46625bdbb66Scgd "usage: %s [-d] [-s] [-r router] [-f bootparmsfile]\n", 46725bdbb66Scgd getprogname()); 468b5468677Sthorpej exit(1); 469b5468677Sthorpej } 47008507c14Sitojun 47108507c14Sitojun static int 47208507c14Sitojun get_localaddr(ifname, sin) 47308507c14Sitojun const char *ifname; 47408507c14Sitojun struct sockaddr_in *sin; 47508507c14Sitojun { 47608507c14Sitojun struct ifaddrs *ifap, *ifa; 47708507c14Sitojun 47808507c14Sitojun if (getifaddrs(&ifap) != 0) 47908507c14Sitojun return -1; 48008507c14Sitojun 48108507c14Sitojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 48208507c14Sitojun if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 48308507c14Sitojun continue; 48408507c14Sitojun if (ifa->ifa_addr->sa_family != AF_INET) 48508507c14Sitojun continue; 48608507c14Sitojun if (ifa->ifa_addr->sa_len != sizeof(*sin)) 48708507c14Sitojun continue; 48808507c14Sitojun 48908507c14Sitojun /* no loopback please */ 49008507c14Sitojun #ifdef IFF_LOOPBACK 49108507c14Sitojun if (ifa->ifa_flags & IFF_LOOPBACK) 49208507c14Sitojun continue; 49308507c14Sitojun #else 49403b1bcc6Sitojun if (strncmp(ifa->ifa_name, "lo", 2) == 0 && 49503b1bcc6Sitojun (isdigit(ifa->ifa_name[2]) || ifa->ifa_name[2] == '\0')) 49608507c14Sitojun continue; 49708507c14Sitojun #endif 49808507c14Sitojun 49908507c14Sitojun /* XXX more sanity checks? */ 50008507c14Sitojun 50108507c14Sitojun /* candidate found */ 50208507c14Sitojun memcpy(sin, ifa->ifa_addr, ifa->ifa_addr->sa_len); 50308507c14Sitojun freeifaddrs(ifap); 50408507c14Sitojun return 0; 50508507c14Sitojun } 50608507c14Sitojun 50708507c14Sitojun /* no candidate */ 50808507c14Sitojun freeifaddrs(ifap); 50908507c14Sitojun return -1; 51008507c14Sitojun } 511