1*e195d590Sitojun /* $NetBSD: bootparamd.c,v 1.41 2003/06/26 05:38:45 itojun 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*e195d590Sitojun __RCSID("$NetBSD: bootparamd.c,v 1.41 2003/06/26 05:38:45 itojun 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> 449c33b55eSthorpej #ifdef YP 45b5468677Sthorpej #include <rpcsvc/ypclnt.h> 469c33b55eSthorpej #endif 470d53a465Smycroft 480d8ec8d0Sderaadt #include "pathnames.h" 49ae99bc57Sderaadt 50ae99bc57Sderaadt #define MAXLEN 800 51ae99bc57Sderaadt 52ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME]; 53ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME]; 54ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME]; 55ae99bc57Sderaadt 56d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *)); 57ae99bc57Sderaadt 58d8f00aa3Spk int _rpcsvcdirty = 0; 59d8f00aa3Spk int _rpcpmstart = 0; 60ae99bc57Sderaadt int debug = 0; 61ae99bc57Sderaadt int dolog = 0; 62b5468677Sthorpej struct in_addr route_addr; 63ae99bc57Sderaadt struct sockaddr_in my_addr; 640d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 65*e195d590Sitojun char *iface = NULL; 66ae99bc57Sderaadt 67b5468677Sthorpej int main __P((int, char *[])); 68b5468677Sthorpej int lookup_bootparam __P((char *, char *, char *, char **, char **)); 69b5468677Sthorpej void usage __P((void)); 7008507c14Sitojun static int get_localaddr __P((const char *, struct sockaddr_in *)); 71ae99bc57Sderaadt 72ae99bc57Sderaadt 73ae99bc57Sderaadt /* 74ae99bc57Sderaadt * ever familiar 75ae99bc57Sderaadt */ 76ae99bc57Sderaadt int 77ae99bc57Sderaadt main(argc, argv) 78ae99bc57Sderaadt int argc; 79b5468677Sthorpej char *argv[]; 80ae99bc57Sderaadt { 81ae99bc57Sderaadt SVCXPRT *transp; 82ae99bc57Sderaadt struct hostent *he; 83ae99bc57Sderaadt struct stat buf; 84d907c076Smark int c; 85ae99bc57Sderaadt 86*e195d590Sitojun while ((c = getopt(argc, argv, "di:sr:f:")) != -1) 87ae99bc57Sderaadt switch (c) { 88ae99bc57Sderaadt case 'd': 89ae99bc57Sderaadt debug = 1; 90ae99bc57Sderaadt break; 91*e195d590Sitojun case 'i': 92*e195d590Sitojun iface = optarg; 93*e195d590Sitojun break; 94ae99bc57Sderaadt case 'r': 95ae99bc57Sderaadt if (isdigit(*optarg)) { 96b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 97ae99bc57Sderaadt break; 98ae99bc57Sderaadt } 99ae99bc57Sderaadt he = gethostbyname(optarg); 100b5468677Sthorpej if (he == 0) { 101312c7832Smikel warnx("no such host: %s", optarg); 102ae99bc57Sderaadt usage(); 103ae99bc57Sderaadt } 1047e807419Slukem memmove(&route_addr.s_addr, he->h_addr, he->h_length); 105ae99bc57Sderaadt break; 106ae99bc57Sderaadt case 'f': 107ae99bc57Sderaadt bootpfile = optarg; 108ae99bc57Sderaadt break; 109ae99bc57Sderaadt case 's': 110ae99bc57Sderaadt dolog = 1; 111ae99bc57Sderaadt #ifndef LOG_DAEMON 11213220245Slukem openlog("rpc.bootparamd", 0, 0); 113ae99bc57Sderaadt #else 11413220245Slukem openlog("rpc.bootparamd", 0, LOG_DAEMON); 115ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 116ae99bc57Sderaadt #endif 117ae99bc57Sderaadt break; 118ae99bc57Sderaadt default: 119ae99bc57Sderaadt usage(); 120ae99bc57Sderaadt } 121ae99bc57Sderaadt 1220d53a465Smycroft if (stat(bootpfile, &buf)) 1230d53a465Smycroft err(1, "%s", bootpfile); 1240d53a465Smycroft 125b5468677Sthorpej if (route_addr.s_addr == 0) { 12608507c14Sitojun if (get_localaddr(NULL, &my_addr) != 0) 12708507c14Sitojun errx(1, "router address not found"); 128b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 129ae99bc57Sderaadt } 1300d53a465Smycroft if (!debug) { 1310d53a465Smycroft if (daemon(0, 0)) 1320d53a465Smycroft err(1, "can't detach from terminal"); 1330d53a465Smycroft } 134653c3855Sthorpej pidfile(NULL); 135ae99bc57Sderaadt 136ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 137ae99bc57Sderaadt 138ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1390d53a465Smycroft if (transp == NULL) 1400d53a465Smycroft errx(1, "can't create udp service"); 1410d53a465Smycroft 1420d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1430d53a465Smycroft IPPROTO_UDP)) 144a3b6375dStron /* 145a3b6375dStron * Do NOT change the "%u" in the format string below to "%lu". If your 146a3b6375dStron * build fails update the "rpcgen" program and use "make cleandir" and 147a3b6375dStron * "make includes" in "src/lib/librpcsvc" afterwards. 148a3b6375dStron */ 1497dca1ce9Sexplorer errx(1, "unable to register BOOTPARAMPROG version %u, udp", 150ae99bc57Sderaadt BOOTPARAMVERS); 1510d53a465Smycroft 152ae99bc57Sderaadt svc_run(); 1530d53a465Smycroft errx(1, "svc_run returned"); 154ae99bc57Sderaadt } 155ae99bc57Sderaadt 156ae99bc57Sderaadt bp_whoami_res * 157d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 158ae99bc57Sderaadt bp_whoami_arg *whoami; 159d8f00aa3Spk struct svc_req *rqstp; 160ae99bc57Sderaadt { 161ae99bc57Sderaadt static bp_whoami_res res; 162b7dcf10eScgd struct hostent *he; 16388e77501Snathanw struct in_addr haddr; 164d3964689Schristos int e; 1650d8ec8d0Sderaadt 166ae99bc57Sderaadt if (debug) 167312c7832Smikel warnx("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 if (dolog) 173312c7832Smikel syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d", 174ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 175ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 176ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 177ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 178ae99bc57Sderaadt 1797e807419Slukem memmove((char *) &haddr, 1807e807419Slukem (char *) &whoami->client_address.bp_address_u.ip_addr, 1817e807419Slukem sizeof(haddr)); 182ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 183ddc2dd4fSmrg if (he) { 184ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 185ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 186ddc2dd4fSmrg } else { 18788e77501Snathanw strncpy(askname, inet_ntoa(haddr), sizeof(askname)); 188ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 189b7dcf10eScgd } 190ae99bc57Sderaadt 191ae99bc57Sderaadt if (debug) 192312c7832Smikel warnx("This is host %s", askname); 193ae99bc57Sderaadt if (dolog) 194312c7832Smikel syslog(LOG_NOTICE, "This is host %s", askname); 195ae99bc57Sderaadt 196d3964689Schristos if ((e = lookup_bootparam(askname, hostname, NULL, NULL, NULL)) == 0) { 197ae99bc57Sderaadt res.client_name = hostname; 198ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 199ae99bc57Sderaadt res.domain_name = domain_name; 200ae99bc57Sderaadt 201ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 202ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 2037e807419Slukem memmove(&res.router_address.bp_address_u.ip_addr, 2047e807419Slukem &route_addr.s_addr,4); 205ae99bc57Sderaadt } 206ae99bc57Sderaadt if (debug) 207312c7832Smikel warnx("Returning %s %s %d.%d.%d.%d", 208ae99bc57Sderaadt res.client_name, res.domain_name, 209ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 210ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 211ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 212ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 213ae99bc57Sderaadt if (dolog) 214312c7832Smikel syslog(LOG_NOTICE, "Returning %s %s %d.%d.%d.%d", 215ae99bc57Sderaadt res.client_name, res.domain_name, 216ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 217ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 218ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 219ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 220ae99bc57Sderaadt 221ae99bc57Sderaadt return (&res); 222ae99bc57Sderaadt } 223d3964689Schristos errno = e; 224ae99bc57Sderaadt if (debug) 225d3964689Schristos warn("whoami failed"); 226ae99bc57Sderaadt if (dolog) 227d3964689Schristos syslog(LOG_NOTICE, "whoami failed %m"); 228ae99bc57Sderaadt return (NULL); 229ae99bc57Sderaadt } 230ae99bc57Sderaadt 231ae99bc57Sderaadt 232ae99bc57Sderaadt bp_getfile_res * 233d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 234ae99bc57Sderaadt bp_getfile_arg *getfile; 235d8f00aa3Spk struct svc_req *rqstp; 236ae99bc57Sderaadt { 237ae99bc57Sderaadt static bp_getfile_res res; 238b7dcf10eScgd struct hostent *he; 2390d8ec8d0Sderaadt int err; 240ae99bc57Sderaadt 241ae99bc57Sderaadt if (debug) 242312c7832Smikel warnx("getfile got question for \"%s\" and file \"%s\"", 243ae99bc57Sderaadt getfile->client_name, getfile->file_id); 244ae99bc57Sderaadt 245ae99bc57Sderaadt if (dolog) 246312c7832Smikel syslog(LOG_NOTICE, 247312c7832Smikel "getfile got question for \"%s\" and file \"%s\"", 248ae99bc57Sderaadt getfile->client_name, getfile->file_id); 249ae99bc57Sderaadt 250ae99bc57Sderaadt he = NULL; 251ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 2524ac5e36aSjhawk if (!he) { 2534ac5e36aSjhawk if (debug) 2544ac5e36aSjhawk warnx("getfile can't resolve client %s", 2554ac5e36aSjhawk getfile->client_name); 2564ac5e36aSjhawk if (dolog) 2574ac5e36aSjhawk syslog(LOG_NOTICE, "getfile can't resolve client %s", 2584ac5e36aSjhawk getfile->client_name); 2594ac5e36aSjhawk return (NULL); 2604ac5e36aSjhawk } 261ae99bc57Sderaadt 262ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 263ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 2640d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2650d8ec8d0Sderaadt &res.server_name, &res.server_path); 2660d8ec8d0Sderaadt if (err == 0) { 2670d8ec8d0Sderaadt he = gethostbyname(res.server_name); 2684ac5e36aSjhawk if (!he) { 2694ac5e36aSjhawk if (debug) 2704ac5e36aSjhawk warnx("getfile can't resolve server %s for %s", 2714ac5e36aSjhawk res.server_name, getfile->client_name); 2724ac5e36aSjhawk if (dolog) 2734ac5e36aSjhawk syslog(LOG_NOTICE, 2744ac5e36aSjhawk "getfile can't resolve server %s for %s", 2754ac5e36aSjhawk res.server_name, getfile->client_name); 2764ac5e36aSjhawk return (NULL); 2774ac5e36aSjhawk 2784ac5e36aSjhawk } 2797e807419Slukem memmove(&res.server_address.bp_address_u.ip_addr, 2807e807419Slukem he->h_addr, 4); 281ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2820d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2830d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 284ae99bc57Sderaadt res.server_name[0] = '\0'; 285ae99bc57Sderaadt res.server_path[0] = '\0'; 2867e807419Slukem memset(&res.server_address.bp_address_u.ip_addr, 0, 4); 2870d8ec8d0Sderaadt } else { 2880d8ec8d0Sderaadt if (debug) 2894ac5e36aSjhawk warnx("getfile lookup failed for %s", 2900d8ec8d0Sderaadt getfile->client_name); 2910d8ec8d0Sderaadt if (dolog) 2920d8ec8d0Sderaadt syslog(LOG_NOTICE, 2934ac5e36aSjhawk "getfile lookup failed for %s", 2944ac5e36aSjhawk getfile->client_name); 2950d8ec8d0Sderaadt return (NULL); 296ae99bc57Sderaadt } 2970d8ec8d0Sderaadt 298ae99bc57Sderaadt if (debug) 2990d53a465Smycroft warnx( 300312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 301ae99bc57Sderaadt res.server_name, res.server_path, 302ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 303ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 304ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 305ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 306ae99bc57Sderaadt if (dolog) 307ae99bc57Sderaadt syslog(LOG_NOTICE, 308312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 309ae99bc57Sderaadt res.server_name, res.server_path, 310ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 311ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 312ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 313ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 314ae99bc57Sderaadt return (&res); 315ae99bc57Sderaadt } 316ae99bc57Sderaadt 317ae99bc57Sderaadt 3180d8ec8d0Sderaadt int 3190d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 3200d8ec8d0Sderaadt char *client; 3210d8ec8d0Sderaadt char *client_canonical; 3220d8ec8d0Sderaadt char *id; 3230d8ec8d0Sderaadt char **server; 3240d8ec8d0Sderaadt char **path; 325ae99bc57Sderaadt { 3260d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 3270d8ec8d0Sderaadt #ifdef YP 3280d8ec8d0Sderaadt static char *ypbuf = NULL; 3290d8ec8d0Sderaadt static int ypbuflen = 0; 3300d8ec8d0Sderaadt #endif 3310d8ec8d0Sderaadt static char buf[BUFSIZ]; 332c1b4b344Sthorpej char *canon = NULL, *bp, *word = NULL; 3330d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 3340d8ec8d0Sderaadt int contin = 0; 3350d8ec8d0Sderaadt int found = 0; 336ae99bc57Sderaadt 3370d8ec8d0Sderaadt if (f == NULL) 3380d8ec8d0Sderaadt return EINVAL; /* ? */ 339ae99bc57Sderaadt 3400d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3410d8ec8d0Sderaadt int wascontin = contin; 3420d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3430d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 344ae99bc57Sderaadt 3450d8ec8d0Sderaadt switch (wascontin) { 3460d8ec8d0Sderaadt case -1: 3470d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3480d8ec8d0Sderaadt contin *= -1; 349ae99bc57Sderaadt continue; 3500d8ec8d0Sderaadt case 0: 3510d8ec8d0Sderaadt /* New line */ 3520d8ec8d0Sderaadt contin *= -1; 3530d8ec8d0Sderaadt if (*bp == '#') 3540d8ec8d0Sderaadt continue; 3550d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3560d8ec8d0Sderaadt continue; 3570d8ec8d0Sderaadt #ifdef YP 3580d8ec8d0Sderaadt /* A + in the file means try YP now */ 3590d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3600d8ec8d0Sderaadt char *ypdom; 3610d8ec8d0Sderaadt 3620d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3630d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3640d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3650d8ec8d0Sderaadt continue; 3660d8ec8d0Sderaadt bp = ypbuf; 3670d8ec8d0Sderaadt word = client; 3680d8ec8d0Sderaadt contin *= -1; 369ae99bc57Sderaadt break; 370ae99bc57Sderaadt } 3710d8ec8d0Sderaadt #endif 372d3964689Schristos if (debug) 373d3964689Schristos warnx("match %s with %s", word, client); 374c1b4b344Sthorpej 375c1b4b344Sthorpej #define HASGLOB(str) \ 376c1b4b344Sthorpej (strchr(str, '*') != NULL || \ 377c1b4b344Sthorpej strchr(str, '?') != NULL || \ 378c1b4b344Sthorpej strchr(str, '[') != NULL || \ 379c1b4b344Sthorpej strchr(str, ']') != NULL) 380c1b4b344Sthorpej 3810d8ec8d0Sderaadt /* See if this line's client is the one we are 3820d8ec8d0Sderaadt * looking for */ 383c1b4b344Sthorpej if (fnmatch(word, client, FNM_CASEFOLD) == 0) { 384c1b4b344Sthorpej /* 385c1b4b344Sthorpej * Match. The token may be globbed, we 386c1b4b344Sthorpej * can't just return that as the canonical 387c1b4b344Sthorpej * name. Check to see if the token has any 388c1b4b344Sthorpej * globbing characters in it (*, ?, [, ]). 389c1b4b344Sthorpej * If so, just return the name we already 390c1b4b344Sthorpej * have. Otherwise, return the token. 391c1b4b344Sthorpej */ 392c1b4b344Sthorpej if (HASGLOB(word)) 393c1b4b344Sthorpej canon = client; 394c1b4b344Sthorpej else 395c1b4b344Sthorpej canon = word; 396c1b4b344Sthorpej } else { 39729ea834fSthorpej struct hostent *hp; 398ae99bc57Sderaadt /* 3990d8ec8d0Sderaadt * If it didn't match, try getting the 4000d8ec8d0Sderaadt * canonical host name of the client 40129ea834fSthorpej * on this line, if it's not a glob, 40229ea834fSthorpej * and comparing it to the client we 40329ea834fSthorpej * are looking up. 404ae99bc57Sderaadt */ 40529ea834fSthorpej if (HASGLOB(word)) { 406bf094b72Sabs if (debug) 40729ea834fSthorpej warnx("Skipping non-match: %s", 40829ea834fSthorpej word); 409bf094b72Sabs continue; 410bf094b72Sabs } 41129ea834fSthorpej if ((hp = gethostbyname(word)) == NULL) { 41229ea834fSthorpej if (debug) 41329ea834fSthorpej warnx( 41429ea834fSthorpej "Unknown bootparams host %s", 41529ea834fSthorpej word); 41629ea834fSthorpej if (dolog) 41729ea834fSthorpej syslog(LOG_NOTICE, 41829ea834fSthorpej "Unknown bootparams host %s", 41929ea834fSthorpej word); 420e9aaacc8Senami continue; 421c1b4b344Sthorpej } 42229ea834fSthorpej if (strcasecmp(hp->h_name, client) != 0) 42329ea834fSthorpej continue; 42429ea834fSthorpej canon = hp->h_name; 42529ea834fSthorpej } 426c1b4b344Sthorpej 427c1b4b344Sthorpej #undef HASGLOB 428c1b4b344Sthorpej 4290d8ec8d0Sderaadt contin *= -1; 4300d8ec8d0Sderaadt break; 4310d8ec8d0Sderaadt case 1: 4320d8ec8d0Sderaadt /* Continued line we want to parse below */ 4330d8ec8d0Sderaadt break; 4340d8ec8d0Sderaadt } 435ae99bc57Sderaadt 436c1b4b344Sthorpej assert(canon != NULL); 4370d8ec8d0Sderaadt if (client_canonical) 438c1b4b344Sthorpej strncpy(client_canonical, canon, MAX_MACHINE_NAME); 4390d8ec8d0Sderaadt 4400d8ec8d0Sderaadt /* We have found a line for CLIENT */ 441f392a261Sglass if (id == NULL) { 442f392a261Sglass (void) fclose(f); 4430d8ec8d0Sderaadt return 0; 444f392a261Sglass } 4450d8ec8d0Sderaadt 4460d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 4470d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 4480d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 4490d8ec8d0Sderaadt /* We have found the entry we want */ 4500d8ec8d0Sderaadt *server = &word[idlen + 1]; 4510d8ec8d0Sderaadt *path = strchr(*server, ':'); 4520d8ec8d0Sderaadt if (*path == NULL) 4530d8ec8d0Sderaadt /* Malformed entry */ 4540d8ec8d0Sderaadt continue; 4550d8ec8d0Sderaadt *(*path)++ = '\0'; 4560d8ec8d0Sderaadt (void) fclose(f); 4570d8ec8d0Sderaadt return 0; 458ae99bc57Sderaadt } 459ae99bc57Sderaadt } 4600d8ec8d0Sderaadt 4610d8ec8d0Sderaadt found = 1; 462ae99bc57Sderaadt } 4630d8ec8d0Sderaadt 4640d8ec8d0Sderaadt (void) fclose(f); 4650d8ec8d0Sderaadt return found ? ENOENT : EPERM; 466ae99bc57Sderaadt } 467b5468677Sthorpej 468b5468677Sthorpej void 469b5468677Sthorpej usage() 470b5468677Sthorpej { 471b5468677Sthorpej fprintf(stderr, 472*e195d590Sitojun "usage: %s [-ds] [-i interface] [-r router] [-f bootparmsfile]\n", 47325bdbb66Scgd getprogname()); 474b5468677Sthorpej exit(1); 475b5468677Sthorpej } 47608507c14Sitojun 47708507c14Sitojun static int 47808507c14Sitojun get_localaddr(ifname, sin) 47908507c14Sitojun const char *ifname; 48008507c14Sitojun struct sockaddr_in *sin; 48108507c14Sitojun { 48208507c14Sitojun struct ifaddrs *ifap, *ifa; 48308507c14Sitojun 48408507c14Sitojun if (getifaddrs(&ifap) != 0) 48508507c14Sitojun return -1; 48608507c14Sitojun 48708507c14Sitojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 48808507c14Sitojun if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 48908507c14Sitojun continue; 49008507c14Sitojun if (ifa->ifa_addr->sa_family != AF_INET) 49108507c14Sitojun continue; 49208507c14Sitojun if (ifa->ifa_addr->sa_len != sizeof(*sin)) 49308507c14Sitojun continue; 49408507c14Sitojun 49508507c14Sitojun /* no loopback please */ 49608507c14Sitojun #ifdef IFF_LOOPBACK 49708507c14Sitojun if (ifa->ifa_flags & IFF_LOOPBACK) 49808507c14Sitojun continue; 49908507c14Sitojun #else 50003b1bcc6Sitojun if (strncmp(ifa->ifa_name, "lo", 2) == 0 && 50103b1bcc6Sitojun (isdigit(ifa->ifa_name[2]) || ifa->ifa_name[2] == '\0')) 50208507c14Sitojun continue; 50308507c14Sitojun #endif 50408507c14Sitojun 505*e195d590Sitojun if (!iface || strcmp(ifa->ifa_name, iface) == 0) 506*e195d590Sitojun ; 507*e195d590Sitojun else 508*e195d590Sitojun continue; 50908507c14Sitojun 51008507c14Sitojun /* candidate found */ 51108507c14Sitojun memcpy(sin, ifa->ifa_addr, ifa->ifa_addr->sa_len); 51208507c14Sitojun freeifaddrs(ifap); 51308507c14Sitojun return 0; 51408507c14Sitojun } 51508507c14Sitojun 51608507c14Sitojun /* no candidate */ 51708507c14Sitojun freeifaddrs(ifap); 51808507c14Sitojun return -1; 51908507c14Sitojun } 520