1*df4795aaSjoerg /* $NetBSD: bootparamd.c,v 1.46 2011/08/30 20:29:41 joerg 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*df4795aaSjoerg __RCSID("$NetBSD: bootparamd.c,v 1.46 2011/08/30 20:29:41 joerg 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 56*df4795aaSjoerg extern void bootparamprog_1(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; 6446c55ef3Slukem const char *bootpfile = _PATH_BOOTPARAMS; 65e195d590Sitojun char *iface = NULL; 66ae99bc57Sderaadt 67*df4795aaSjoerg static int lookup_bootparam(char *, char *, char *, char **, char **); 68*df4795aaSjoerg __dead static void usage(void); 69*df4795aaSjoerg static int get_localaddr(const char *, struct sockaddr_in *); 70ae99bc57Sderaadt 71ae99bc57Sderaadt 72ae99bc57Sderaadt /* 73ae99bc57Sderaadt * ever familiar 74ae99bc57Sderaadt */ 75ae99bc57Sderaadt int 76*df4795aaSjoerg main(int argc, char *argv[]) 77ae99bc57Sderaadt { 78ae99bc57Sderaadt SVCXPRT *transp; 79ae99bc57Sderaadt struct hostent *he; 80ae99bc57Sderaadt struct stat buf; 81d907c076Smark int c; 82ae99bc57Sderaadt 83e195d590Sitojun while ((c = getopt(argc, argv, "di:sr:f:")) != -1) 84ae99bc57Sderaadt switch (c) { 85ae99bc57Sderaadt case 'd': 86ae99bc57Sderaadt debug = 1; 87ae99bc57Sderaadt break; 88e195d590Sitojun case 'i': 89e195d590Sitojun iface = optarg; 90e195d590Sitojun break; 91ae99bc57Sderaadt case 'r': 92e2f49bd9Sdsl if (isdigit((unsigned char)*optarg)) { 93b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 94ae99bc57Sderaadt break; 95ae99bc57Sderaadt } 96ae99bc57Sderaadt he = gethostbyname(optarg); 97b5468677Sthorpej if (he == 0) { 98312c7832Smikel warnx("no such host: %s", optarg); 99ae99bc57Sderaadt usage(); 100ae99bc57Sderaadt } 1017e807419Slukem memmove(&route_addr.s_addr, he->h_addr, he->h_length); 102ae99bc57Sderaadt break; 103ae99bc57Sderaadt case 'f': 104ae99bc57Sderaadt bootpfile = optarg; 105ae99bc57Sderaadt break; 106ae99bc57Sderaadt case 's': 107ae99bc57Sderaadt dolog = 1; 108ae99bc57Sderaadt #ifndef LOG_DAEMON 10913220245Slukem openlog("rpc.bootparamd", 0, 0); 110ae99bc57Sderaadt #else 11113220245Slukem openlog("rpc.bootparamd", 0, LOG_DAEMON); 112ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 113ae99bc57Sderaadt #endif 114ae99bc57Sderaadt break; 115ae99bc57Sderaadt default: 116ae99bc57Sderaadt usage(); 117ae99bc57Sderaadt } 118ae99bc57Sderaadt 1190d53a465Smycroft if (stat(bootpfile, &buf)) 1200d53a465Smycroft err(1, "%s", bootpfile); 1210d53a465Smycroft 122b5468677Sthorpej if (route_addr.s_addr == 0) { 12308507c14Sitojun if (get_localaddr(NULL, &my_addr) != 0) 12408507c14Sitojun errx(1, "router address not found"); 125b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 126ae99bc57Sderaadt } 1270d53a465Smycroft if (!debug) { 1280d53a465Smycroft if (daemon(0, 0)) 1290d53a465Smycroft err(1, "can't detach from terminal"); 1300d53a465Smycroft } 131653c3855Sthorpej pidfile(NULL); 132ae99bc57Sderaadt 133ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 134ae99bc57Sderaadt 135ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1360d53a465Smycroft if (transp == NULL) 1370d53a465Smycroft errx(1, "can't create udp service"); 1380d53a465Smycroft 1390d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1400d53a465Smycroft IPPROTO_UDP)) 141a3b6375dStron /* 142a3b6375dStron * Do NOT change the "%u" in the format string below to "%lu". If your 143a3b6375dStron * build fails update the "rpcgen" program and use "make cleandir" and 144a3b6375dStron * "make includes" in "src/lib/librpcsvc" afterwards. 145a3b6375dStron */ 1467dca1ce9Sexplorer errx(1, "unable to register BOOTPARAMPROG version %u, udp", 147ae99bc57Sderaadt BOOTPARAMVERS); 1480d53a465Smycroft 149ae99bc57Sderaadt svc_run(); 1500d53a465Smycroft errx(1, "svc_run returned"); 151ae99bc57Sderaadt } 152ae99bc57Sderaadt 153ae99bc57Sderaadt bp_whoami_res * 154*df4795aaSjoerg bootparamproc_whoami_1_svc(bp_whoami_arg *whoami, struct svc_req *rqstp) 155ae99bc57Sderaadt { 156ae99bc57Sderaadt static bp_whoami_res res; 157b7dcf10eScgd struct hostent *he; 15888e77501Snathanw struct in_addr haddr; 159d3964689Schristos int e; 1600d8ec8d0Sderaadt 161ae99bc57Sderaadt if (debug) 162312c7832Smikel warnx("whoami got question for %d.%d.%d.%d", 163ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 164ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 165ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 166ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 167ae99bc57Sderaadt if (dolog) 168312c7832Smikel syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d", 169ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 170ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 171ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 172ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 173ae99bc57Sderaadt 1747e807419Slukem memmove((char *) &haddr, 1757e807419Slukem (char *) &whoami->client_address.bp_address_u.ip_addr, 1767e807419Slukem sizeof(haddr)); 177ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 178ddc2dd4fSmrg if (he) { 179190b2e4cSjrf (void)strlcpy(askname, he->h_name, sizeof(askname)); 180ddc2dd4fSmrg } else { 181190b2e4cSjrf (void)strlcpy(askname, inet_ntoa(haddr), sizeof(askname)); 182b7dcf10eScgd } 183ae99bc57Sderaadt 184ae99bc57Sderaadt if (debug) 185312c7832Smikel warnx("This is host %s", askname); 186ae99bc57Sderaadt if (dolog) 187312c7832Smikel syslog(LOG_NOTICE, "This is host %s", askname); 188ae99bc57Sderaadt 189d3964689Schristos if ((e = lookup_bootparam(askname, hostname, NULL, NULL, NULL)) == 0) { 190ae99bc57Sderaadt res.client_name = hostname; 191ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 192ae99bc57Sderaadt res.domain_name = domain_name; 193ae99bc57Sderaadt 194ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 195ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 1967e807419Slukem memmove(&res.router_address.bp_address_u.ip_addr, 1977e807419Slukem &route_addr.s_addr,4); 198ae99bc57Sderaadt } 199ae99bc57Sderaadt if (debug) 200312c7832Smikel warnx("Returning %s %s %d.%d.%d.%d", 201ae99bc57Sderaadt res.client_name, res.domain_name, 202ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 203ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 204ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 205ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 206ae99bc57Sderaadt if (dolog) 207312c7832Smikel syslog(LOG_NOTICE, "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 214ae99bc57Sderaadt return (&res); 215ae99bc57Sderaadt } 216d3964689Schristos errno = e; 217ae99bc57Sderaadt if (debug) 218d3964689Schristos warn("whoami failed"); 219ae99bc57Sderaadt if (dolog) 220d3964689Schristos syslog(LOG_NOTICE, "whoami failed %m"); 221ae99bc57Sderaadt return (NULL); 222ae99bc57Sderaadt } 223ae99bc57Sderaadt 224ae99bc57Sderaadt 225ae99bc57Sderaadt bp_getfile_res * 226*df4795aaSjoerg bootparamproc_getfile_1_svc(bp_getfile_arg *getfile, struct svc_req *rqstp) 227ae99bc57Sderaadt { 228ae99bc57Sderaadt static bp_getfile_res res; 229b7dcf10eScgd struct hostent *he; 23046c55ef3Slukem int error; 231ae99bc57Sderaadt 232ae99bc57Sderaadt if (debug) 233312c7832Smikel warnx("getfile got question for \"%s\" and file \"%s\"", 234ae99bc57Sderaadt getfile->client_name, getfile->file_id); 235ae99bc57Sderaadt 236ae99bc57Sderaadt if (dolog) 237312c7832Smikel syslog(LOG_NOTICE, 238312c7832Smikel "getfile got question for \"%s\" and file \"%s\"", 239ae99bc57Sderaadt getfile->client_name, getfile->file_id); 240ae99bc57Sderaadt 241ae99bc57Sderaadt he = NULL; 242ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 2434ac5e36aSjhawk if (!he) { 2444ac5e36aSjhawk if (debug) 2454ac5e36aSjhawk warnx("getfile can't resolve client %s", 2464ac5e36aSjhawk getfile->client_name); 2474ac5e36aSjhawk if (dolog) 2484ac5e36aSjhawk syslog(LOG_NOTICE, "getfile can't resolve client %s", 2494ac5e36aSjhawk getfile->client_name); 2504ac5e36aSjhawk return (NULL); 2514ac5e36aSjhawk } 252ae99bc57Sderaadt 253190b2e4cSjrf (void)strlcpy(askname, he->h_name, sizeof(askname)); 25446c55ef3Slukem error = lookup_bootparam(askname, NULL, getfile->file_id, 2550d8ec8d0Sderaadt &res.server_name, &res.server_path); 25646c55ef3Slukem if (error == 0) { 2570d8ec8d0Sderaadt he = gethostbyname(res.server_name); 2584ac5e36aSjhawk if (!he) { 2594ac5e36aSjhawk if (debug) 2604ac5e36aSjhawk warnx("getfile can't resolve server %s for %s", 2614ac5e36aSjhawk res.server_name, getfile->client_name); 2624ac5e36aSjhawk if (dolog) 2634ac5e36aSjhawk syslog(LOG_NOTICE, 2644ac5e36aSjhawk "getfile can't resolve server %s for %s", 2654ac5e36aSjhawk res.server_name, getfile->client_name); 2664ac5e36aSjhawk return (NULL); 2674ac5e36aSjhawk 2684ac5e36aSjhawk } 2697e807419Slukem memmove(&res.server_address.bp_address_u.ip_addr, 2707e807419Slukem he->h_addr, 4); 271ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 27246c55ef3Slukem } else if (error == ENOENT && !strcmp(getfile->file_id, "dump")) { 2730d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 274ae99bc57Sderaadt res.server_name[0] = '\0'; 275ae99bc57Sderaadt res.server_path[0] = '\0'; 2767e807419Slukem memset(&res.server_address.bp_address_u.ip_addr, 0, 4); 2770d8ec8d0Sderaadt } else { 2780d8ec8d0Sderaadt if (debug) 2794ac5e36aSjhawk warnx("getfile lookup failed for %s", 2800d8ec8d0Sderaadt getfile->client_name); 2810d8ec8d0Sderaadt if (dolog) 2820d8ec8d0Sderaadt syslog(LOG_NOTICE, 2834ac5e36aSjhawk "getfile lookup failed for %s", 2844ac5e36aSjhawk getfile->client_name); 2850d8ec8d0Sderaadt return (NULL); 286ae99bc57Sderaadt } 2870d8ec8d0Sderaadt 288ae99bc57Sderaadt if (debug) 2890d53a465Smycroft warnx( 290312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 291ae99bc57Sderaadt res.server_name, res.server_path, 292ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 293ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 294ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 295ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 296ae99bc57Sderaadt if (dolog) 297ae99bc57Sderaadt syslog(LOG_NOTICE, 298312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 299ae99bc57Sderaadt res.server_name, res.server_path, 300ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 301ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 302ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 303ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 304ae99bc57Sderaadt return (&res); 305ae99bc57Sderaadt } 306ae99bc57Sderaadt 307ae99bc57Sderaadt 308*df4795aaSjoerg static int 309*df4795aaSjoerg lookup_bootparam(char *client, char *client_canonical, char *id, 310*df4795aaSjoerg char **server, char **path) 311ae99bc57Sderaadt { 3120d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 3130d8ec8d0Sderaadt #ifdef YP 3140d8ec8d0Sderaadt static char *ypbuf = NULL; 3150d8ec8d0Sderaadt static int ypbuflen = 0; 3160d8ec8d0Sderaadt #endif 3170d8ec8d0Sderaadt static char buf[BUFSIZ]; 318c1b4b344Sthorpej char *canon = NULL, *bp, *word = NULL; 3190d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 3200d8ec8d0Sderaadt int contin = 0; 3210d8ec8d0Sderaadt int found = 0; 322ae99bc57Sderaadt 3230d8ec8d0Sderaadt if (f == NULL) 3240d8ec8d0Sderaadt return EINVAL; /* ? */ 325ae99bc57Sderaadt 3260d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3270d8ec8d0Sderaadt int wascontin = contin; 3280d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3290d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 330ae99bc57Sderaadt 3310d8ec8d0Sderaadt switch (wascontin) { 3320d8ec8d0Sderaadt case -1: 3330d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3340d8ec8d0Sderaadt contin *= -1; 335ae99bc57Sderaadt continue; 3360d8ec8d0Sderaadt case 0: 3370d8ec8d0Sderaadt /* New line */ 3380d8ec8d0Sderaadt contin *= -1; 3390d8ec8d0Sderaadt if (*bp == '#') 3400d8ec8d0Sderaadt continue; 3410d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3420d8ec8d0Sderaadt continue; 3430d8ec8d0Sderaadt #ifdef YP 3440d8ec8d0Sderaadt /* A + in the file means try YP now */ 3450d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3460d8ec8d0Sderaadt char *ypdom; 3470d8ec8d0Sderaadt 3480d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3490d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3500d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3510d8ec8d0Sderaadt continue; 3520d8ec8d0Sderaadt bp = ypbuf; 3530d8ec8d0Sderaadt word = client; 3540d8ec8d0Sderaadt contin *= -1; 355ae99bc57Sderaadt break; 356ae99bc57Sderaadt } 3570d8ec8d0Sderaadt #endif 358d3964689Schristos if (debug) 359d3964689Schristos warnx("match %s with %s", word, client); 360c1b4b344Sthorpej 361c1b4b344Sthorpej #define HASGLOB(str) \ 362c1b4b344Sthorpej (strchr(str, '*') != NULL || \ 363c1b4b344Sthorpej strchr(str, '?') != NULL || \ 364c1b4b344Sthorpej strchr(str, '[') != NULL || \ 365c1b4b344Sthorpej strchr(str, ']') != NULL) 366c1b4b344Sthorpej 3670d8ec8d0Sderaadt /* See if this line's client is the one we are 3680d8ec8d0Sderaadt * looking for */ 369c1b4b344Sthorpej if (fnmatch(word, client, FNM_CASEFOLD) == 0) { 370c1b4b344Sthorpej /* 371c1b4b344Sthorpej * Match. The token may be globbed, we 372c1b4b344Sthorpej * can't just return that as the canonical 373c1b4b344Sthorpej * name. Check to see if the token has any 374c1b4b344Sthorpej * globbing characters in it (*, ?, [, ]). 375c1b4b344Sthorpej * If so, just return the name we already 376c1b4b344Sthorpej * have. Otherwise, return the token. 377c1b4b344Sthorpej */ 378c1b4b344Sthorpej if (HASGLOB(word)) 379c1b4b344Sthorpej canon = client; 380c1b4b344Sthorpej else 381c1b4b344Sthorpej canon = word; 382c1b4b344Sthorpej } else { 38329ea834fSthorpej struct hostent *hp; 384ae99bc57Sderaadt /* 3850d8ec8d0Sderaadt * If it didn't match, try getting the 3860d8ec8d0Sderaadt * canonical host name of the client 38729ea834fSthorpej * on this line, if it's not a glob, 38829ea834fSthorpej * and comparing it to the client we 38929ea834fSthorpej * are looking up. 390ae99bc57Sderaadt */ 39129ea834fSthorpej if (HASGLOB(word)) { 392bf094b72Sabs if (debug) 39329ea834fSthorpej warnx("Skipping non-match: %s", 39429ea834fSthorpej word); 395bf094b72Sabs continue; 396bf094b72Sabs } 39729ea834fSthorpej if ((hp = gethostbyname(word)) == NULL) { 39829ea834fSthorpej if (debug) 39929ea834fSthorpej warnx( 40029ea834fSthorpej "Unknown bootparams host %s", 40129ea834fSthorpej word); 40229ea834fSthorpej if (dolog) 40329ea834fSthorpej syslog(LOG_NOTICE, 40429ea834fSthorpej "Unknown bootparams host %s", 40529ea834fSthorpej word); 406e9aaacc8Senami continue; 407c1b4b344Sthorpej } 40829ea834fSthorpej if (strcasecmp(hp->h_name, client) != 0) 40929ea834fSthorpej continue; 41029ea834fSthorpej canon = hp->h_name; 41129ea834fSthorpej } 412c1b4b344Sthorpej 413c1b4b344Sthorpej #undef HASGLOB 414c1b4b344Sthorpej 4150d8ec8d0Sderaadt contin *= -1; 4160d8ec8d0Sderaadt break; 4170d8ec8d0Sderaadt case 1: 4180d8ec8d0Sderaadt /* Continued line we want to parse below */ 4190d8ec8d0Sderaadt break; 4200d8ec8d0Sderaadt } 421ae99bc57Sderaadt 422c1b4b344Sthorpej assert(canon != NULL); 4230d8ec8d0Sderaadt if (client_canonical) 424c1b4b344Sthorpej strncpy(client_canonical, canon, MAX_MACHINE_NAME); 4250d8ec8d0Sderaadt 4260d8ec8d0Sderaadt /* We have found a line for CLIENT */ 427f392a261Sglass if (id == NULL) { 428f392a261Sglass (void) fclose(f); 4290d8ec8d0Sderaadt return 0; 430f392a261Sglass } 4310d8ec8d0Sderaadt 4320d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 4330d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 4340d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 4350d8ec8d0Sderaadt /* We have found the entry we want */ 4360d8ec8d0Sderaadt *server = &word[idlen + 1]; 4370d8ec8d0Sderaadt *path = strchr(*server, ':'); 4380d8ec8d0Sderaadt if (*path == NULL) 4390d8ec8d0Sderaadt /* Malformed entry */ 4400d8ec8d0Sderaadt continue; 4410d8ec8d0Sderaadt *(*path)++ = '\0'; 4420d8ec8d0Sderaadt (void) fclose(f); 4430d8ec8d0Sderaadt return 0; 444ae99bc57Sderaadt } 445ae99bc57Sderaadt } 4460d8ec8d0Sderaadt 4470d8ec8d0Sderaadt found = 1; 448ae99bc57Sderaadt } 4490d8ec8d0Sderaadt 4500d8ec8d0Sderaadt (void) fclose(f); 4510d8ec8d0Sderaadt return found ? ENOENT : EPERM; 452ae99bc57Sderaadt } 453b5468677Sthorpej 454*df4795aaSjoerg static void 455*df4795aaSjoerg usage(void) 456b5468677Sthorpej { 457b5468677Sthorpej fprintf(stderr, 458c594b298Swiz "usage: %s [-ds] [-i interface] [-r router] [-f bootparamsfile]\n", 45925bdbb66Scgd getprogname()); 460b5468677Sthorpej exit(1); 461b5468677Sthorpej } 46208507c14Sitojun 46308507c14Sitojun static int 464*df4795aaSjoerg get_localaddr(const char *ifname, struct sockaddr_in *sin) 46508507c14Sitojun { 46608507c14Sitojun struct ifaddrs *ifap, *ifa; 46708507c14Sitojun 46808507c14Sitojun if (getifaddrs(&ifap) != 0) 46908507c14Sitojun return -1; 47008507c14Sitojun 47108507c14Sitojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 47208507c14Sitojun if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 47308507c14Sitojun continue; 47408507c14Sitojun if (ifa->ifa_addr->sa_family != AF_INET) 47508507c14Sitojun continue; 47608507c14Sitojun if (ifa->ifa_addr->sa_len != sizeof(*sin)) 47708507c14Sitojun continue; 47808507c14Sitojun 47908507c14Sitojun /* no loopback please */ 48008507c14Sitojun #ifdef IFF_LOOPBACK 48108507c14Sitojun if (ifa->ifa_flags & IFF_LOOPBACK) 48208507c14Sitojun continue; 48308507c14Sitojun #else 48403b1bcc6Sitojun if (strncmp(ifa->ifa_name, "lo", 2) == 0 && 48503b1bcc6Sitojun (isdigit(ifa->ifa_name[2]) || ifa->ifa_name[2] == '\0')) 48608507c14Sitojun continue; 48708507c14Sitojun #endif 48808507c14Sitojun 489e195d590Sitojun if (!iface || strcmp(ifa->ifa_name, iface) == 0) 490e195d590Sitojun ; 491e195d590Sitojun else 492e195d590Sitojun continue; 49308507c14Sitojun 49408507c14Sitojun /* candidate found */ 49508507c14Sitojun memcpy(sin, ifa->ifa_addr, ifa->ifa_addr->sa_len); 49608507c14Sitojun freeifaddrs(ifap); 49708507c14Sitojun return 0; 49808507c14Sitojun } 49908507c14Sitojun 50008507c14Sitojun /* no candidate */ 50108507c14Sitojun freeifaddrs(ifap); 50208507c14Sitojun return -1; 50308507c14Sitojun } 504