1*13220245Slukem /* $NetBSD: bootparamd.c,v 1.37 2001/01/11 01:44:23 lukem 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*13220245Slukem __RCSID("$NetBSD: bootparamd.c,v 1.37 2001/01/11 01:44:23 lukem 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; 62ee7207b7Smycroft extern char *__progname; 630d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 64ae99bc57Sderaadt 65b5468677Sthorpej int main __P((int, char *[])); 66b5468677Sthorpej int lookup_bootparam __P((char *, char *, char *, char **, char **)); 67b5468677Sthorpej void usage __P((void)); 6808507c14Sitojun static int get_localaddr __P((const char *, struct sockaddr_in *)); 69ae99bc57Sderaadt 70ae99bc57Sderaadt 71ae99bc57Sderaadt /* 72ae99bc57Sderaadt * ever familiar 73ae99bc57Sderaadt */ 74ae99bc57Sderaadt int 75ae99bc57Sderaadt main(argc, argv) 76ae99bc57Sderaadt int argc; 77b5468677Sthorpej char *argv[]; 78ae99bc57Sderaadt { 79ae99bc57Sderaadt SVCXPRT *transp; 80ae99bc57Sderaadt struct hostent *he; 81ae99bc57Sderaadt struct stat buf; 82d907c076Smark int c; 83ae99bc57Sderaadt 84d907c076Smark while ((c = getopt(argc, argv, "dsr:f:")) != -1) 85ae99bc57Sderaadt switch (c) { 86ae99bc57Sderaadt case 'd': 87ae99bc57Sderaadt debug = 1; 88ae99bc57Sderaadt break; 89ae99bc57Sderaadt case 'r': 90ae99bc57Sderaadt if (isdigit(*optarg)) { 91b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 92ae99bc57Sderaadt break; 93ae99bc57Sderaadt } 94ae99bc57Sderaadt he = gethostbyname(optarg); 95b5468677Sthorpej if (he == 0) { 96312c7832Smikel warnx("no such host: %s", optarg); 97ae99bc57Sderaadt usage(); 98ae99bc57Sderaadt } 997e807419Slukem memmove(&route_addr.s_addr, he->h_addr, he->h_length); 100ae99bc57Sderaadt break; 101ae99bc57Sderaadt case 'f': 102ae99bc57Sderaadt bootpfile = optarg; 103ae99bc57Sderaadt break; 104ae99bc57Sderaadt case 's': 105ae99bc57Sderaadt dolog = 1; 106ae99bc57Sderaadt #ifndef LOG_DAEMON 107*13220245Slukem openlog("rpc.bootparamd", 0, 0); 108ae99bc57Sderaadt #else 109*13220245Slukem openlog("rpc.bootparamd", 0, LOG_DAEMON); 110ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 111ae99bc57Sderaadt #endif 112ae99bc57Sderaadt break; 113ae99bc57Sderaadt default: 114ae99bc57Sderaadt usage(); 115ae99bc57Sderaadt } 116ae99bc57Sderaadt 1170d53a465Smycroft if (stat(bootpfile, &buf)) 1180d53a465Smycroft err(1, "%s", bootpfile); 1190d53a465Smycroft 120b5468677Sthorpej if (route_addr.s_addr == 0) { 12108507c14Sitojun if (get_localaddr(NULL, &my_addr) != 0) 12208507c14Sitojun errx(1, "router address not found"); 123b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 124ae99bc57Sderaadt } 1250d53a465Smycroft if (!debug) { 1260d53a465Smycroft if (daemon(0, 0)) 1270d53a465Smycroft err(1, "can't detach from terminal"); 1280d53a465Smycroft } 129653c3855Sthorpej pidfile(NULL); 130ae99bc57Sderaadt 131ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 132ae99bc57Sderaadt 133ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1340d53a465Smycroft if (transp == NULL) 1350d53a465Smycroft errx(1, "can't create udp service"); 1360d53a465Smycroft 1370d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1380d53a465Smycroft IPPROTO_UDP)) 139a3b6375dStron /* 140a3b6375dStron * Do NOT change the "%u" in the format string below to "%lu". If your 141a3b6375dStron * build fails update the "rpcgen" program and use "make cleandir" and 142a3b6375dStron * "make includes" in "src/lib/librpcsvc" afterwards. 143a3b6375dStron */ 1447dca1ce9Sexplorer errx(1, "unable to register BOOTPARAMPROG version %u, udp", 145ae99bc57Sderaadt BOOTPARAMVERS); 1460d53a465Smycroft 147ae99bc57Sderaadt svc_run(); 1480d53a465Smycroft errx(1, "svc_run returned"); 149ae99bc57Sderaadt } 150ae99bc57Sderaadt 151ae99bc57Sderaadt bp_whoami_res * 152d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 153ae99bc57Sderaadt bp_whoami_arg *whoami; 154d8f00aa3Spk 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) { 179ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 180ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 181ddc2dd4fSmrg } else { 18288e77501Snathanw strncpy(askname, inet_ntoa(haddr), sizeof(askname)); 183ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 184b7dcf10eScgd } 185ae99bc57Sderaadt 186ae99bc57Sderaadt if (debug) 187312c7832Smikel warnx("This is host %s", askname); 188ae99bc57Sderaadt if (dolog) 189312c7832Smikel syslog(LOG_NOTICE, "This is host %s", askname); 190ae99bc57Sderaadt 191d3964689Schristos if ((e = lookup_bootparam(askname, hostname, NULL, NULL, NULL)) == 0) { 192ae99bc57Sderaadt res.client_name = hostname; 193ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 194ae99bc57Sderaadt res.domain_name = domain_name; 195ae99bc57Sderaadt 196ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 197ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 1987e807419Slukem memmove(&res.router_address.bp_address_u.ip_addr, 1997e807419Slukem &route_addr.s_addr,4); 200ae99bc57Sderaadt } 201ae99bc57Sderaadt if (debug) 202312c7832Smikel warnx("Returning %s %s %d.%d.%d.%d", 203ae99bc57Sderaadt res.client_name, res.domain_name, 204ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 205ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 206ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 207ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 208ae99bc57Sderaadt if (dolog) 209312c7832Smikel syslog(LOG_NOTICE, "Returning %s %s %d.%d.%d.%d", 210ae99bc57Sderaadt res.client_name, res.domain_name, 211ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 212ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 213ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 214ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 215ae99bc57Sderaadt 216ae99bc57Sderaadt return (&res); 217ae99bc57Sderaadt } 218d3964689Schristos errno = e; 219ae99bc57Sderaadt if (debug) 220d3964689Schristos warn("whoami failed"); 221ae99bc57Sderaadt if (dolog) 222d3964689Schristos syslog(LOG_NOTICE, "whoami failed %m"); 223ae99bc57Sderaadt return (NULL); 224ae99bc57Sderaadt } 225ae99bc57Sderaadt 226ae99bc57Sderaadt 227ae99bc57Sderaadt bp_getfile_res * 228d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 229ae99bc57Sderaadt bp_getfile_arg *getfile; 230d8f00aa3Spk struct svc_req *rqstp; 231ae99bc57Sderaadt { 232ae99bc57Sderaadt static bp_getfile_res res; 233b7dcf10eScgd struct hostent *he; 2340d8ec8d0Sderaadt int err; 235ae99bc57Sderaadt 236ae99bc57Sderaadt if (debug) 237312c7832Smikel warnx("getfile got question for \"%s\" and file \"%s\"", 238ae99bc57Sderaadt getfile->client_name, getfile->file_id); 239ae99bc57Sderaadt 240ae99bc57Sderaadt if (dolog) 241312c7832Smikel syslog(LOG_NOTICE, 242312c7832Smikel "getfile got question for \"%s\" and file \"%s\"", 243ae99bc57Sderaadt getfile->client_name, getfile->file_id); 244ae99bc57Sderaadt 245ae99bc57Sderaadt he = NULL; 246ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 247ae99bc57Sderaadt if (!he) 248ae99bc57Sderaadt goto failed; 249ae99bc57Sderaadt 250ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 251ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 2520d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2530d8ec8d0Sderaadt &res.server_name, &res.server_path); 2540d8ec8d0Sderaadt if (err == 0) { 2550d8ec8d0Sderaadt he = gethostbyname(res.server_name); 256ae99bc57Sderaadt if (!he) 257ae99bc57Sderaadt goto failed; 2587e807419Slukem memmove(&res.server_address.bp_address_u.ip_addr, 2597e807419Slukem he->h_addr, 4); 260ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2610d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2620d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 263ae99bc57Sderaadt res.server_name[0] = '\0'; 264ae99bc57Sderaadt res.server_path[0] = '\0'; 2657e807419Slukem memset(&res.server_address.bp_address_u.ip_addr, 0, 4); 2660d8ec8d0Sderaadt } else { 2670d8ec8d0Sderaadt failed: 2680d8ec8d0Sderaadt if (debug) 269312c7832Smikel warnx("getfile failed for %s", 2700d8ec8d0Sderaadt getfile->client_name); 2710d8ec8d0Sderaadt if (dolog) 2720d8ec8d0Sderaadt syslog(LOG_NOTICE, 273312c7832Smikel "getfile failed for %s", getfile->client_name); 2740d8ec8d0Sderaadt return (NULL); 275ae99bc57Sderaadt } 2760d8ec8d0Sderaadt 277ae99bc57Sderaadt if (debug) 2780d53a465Smycroft warnx( 279312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 280ae99bc57Sderaadt res.server_name, res.server_path, 281ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 282ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 283ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 284ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 285ae99bc57Sderaadt if (dolog) 286ae99bc57Sderaadt syslog(LOG_NOTICE, 287312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 288ae99bc57Sderaadt res.server_name, res.server_path, 289ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 290ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 291ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 292ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 293ae99bc57Sderaadt return (&res); 294ae99bc57Sderaadt } 295ae99bc57Sderaadt 296ae99bc57Sderaadt 2970d8ec8d0Sderaadt int 2980d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 2990d8ec8d0Sderaadt char *client; 3000d8ec8d0Sderaadt char *client_canonical; 3010d8ec8d0Sderaadt char *id; 3020d8ec8d0Sderaadt char **server; 3030d8ec8d0Sderaadt char **path; 304ae99bc57Sderaadt { 3050d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 3060d8ec8d0Sderaadt #ifdef YP 3070d8ec8d0Sderaadt static char *ypbuf = NULL; 3080d8ec8d0Sderaadt static int ypbuflen = 0; 3090d8ec8d0Sderaadt #endif 3100d8ec8d0Sderaadt static char buf[BUFSIZ]; 311c1b4b344Sthorpej char *canon = NULL, *bp, *word = NULL; 3120d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 3130d8ec8d0Sderaadt int contin = 0; 3140d8ec8d0Sderaadt int found = 0; 315ae99bc57Sderaadt 3160d8ec8d0Sderaadt if (f == NULL) 3170d8ec8d0Sderaadt return EINVAL; /* ? */ 318ae99bc57Sderaadt 3190d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3200d8ec8d0Sderaadt int wascontin = contin; 3210d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3220d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 323ae99bc57Sderaadt 3240d8ec8d0Sderaadt switch (wascontin) { 3250d8ec8d0Sderaadt case -1: 3260d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3270d8ec8d0Sderaadt contin *= -1; 328ae99bc57Sderaadt continue; 3290d8ec8d0Sderaadt case 0: 3300d8ec8d0Sderaadt /* New line */ 3310d8ec8d0Sderaadt contin *= -1; 3320d8ec8d0Sderaadt if (*bp == '#') 3330d8ec8d0Sderaadt continue; 3340d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3350d8ec8d0Sderaadt continue; 3360d8ec8d0Sderaadt #ifdef YP 3370d8ec8d0Sderaadt /* A + in the file means try YP now */ 3380d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3390d8ec8d0Sderaadt char *ypdom; 3400d8ec8d0Sderaadt 3410d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3420d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3430d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3440d8ec8d0Sderaadt continue; 3450d8ec8d0Sderaadt bp = ypbuf; 3460d8ec8d0Sderaadt word = client; 3470d8ec8d0Sderaadt contin *= -1; 348ae99bc57Sderaadt break; 349ae99bc57Sderaadt } 3500d8ec8d0Sderaadt #endif 351d3964689Schristos if (debug) 352d3964689Schristos warnx("match %s with %s", word, client); 353c1b4b344Sthorpej 354c1b4b344Sthorpej #define HASGLOB(str) \ 355c1b4b344Sthorpej (strchr(str, '*') != NULL || \ 356c1b4b344Sthorpej strchr(str, '?') != NULL || \ 357c1b4b344Sthorpej strchr(str, '[') != NULL || \ 358c1b4b344Sthorpej strchr(str, ']') != NULL) 359c1b4b344Sthorpej 3600d8ec8d0Sderaadt /* See if this line's client is the one we are 3610d8ec8d0Sderaadt * looking for */ 362c1b4b344Sthorpej if (fnmatch(word, client, FNM_CASEFOLD) == 0) { 363c1b4b344Sthorpej /* 364c1b4b344Sthorpej * Match. The token may be globbed, we 365c1b4b344Sthorpej * can't just return that as the canonical 366c1b4b344Sthorpej * name. Check to see if the token has any 367c1b4b344Sthorpej * globbing characters in it (*, ?, [, ]). 368c1b4b344Sthorpej * If so, just return the name we already 369c1b4b344Sthorpej * have. Otherwise, return the token. 370c1b4b344Sthorpej */ 371c1b4b344Sthorpej if (HASGLOB(word)) 372c1b4b344Sthorpej canon = client; 373c1b4b344Sthorpej else 374c1b4b344Sthorpej canon = word; 375c1b4b344Sthorpej } else { 37629ea834fSthorpej struct hostent *hp; 377ae99bc57Sderaadt /* 3780d8ec8d0Sderaadt * If it didn't match, try getting the 3790d8ec8d0Sderaadt * canonical host name of the client 38029ea834fSthorpej * on this line, if it's not a glob, 38129ea834fSthorpej * and comparing it to the client we 38229ea834fSthorpej * are looking up. 383ae99bc57Sderaadt */ 38429ea834fSthorpej if (HASGLOB(word)) { 385bf094b72Sabs if (debug) 38629ea834fSthorpej warnx("Skipping non-match: %s", 38729ea834fSthorpej word); 388bf094b72Sabs continue; 389bf094b72Sabs } 39029ea834fSthorpej if ((hp = gethostbyname(word)) == NULL) { 39129ea834fSthorpej if (debug) 39229ea834fSthorpej warnx( 39329ea834fSthorpej "Unknown bootparams host %s", 39429ea834fSthorpej word); 39529ea834fSthorpej if (dolog) 39629ea834fSthorpej syslog(LOG_NOTICE, 39729ea834fSthorpej "Unknown bootparams host %s", 39829ea834fSthorpej word); 399e9aaacc8Senami continue; 400c1b4b344Sthorpej } 40129ea834fSthorpej if (strcasecmp(hp->h_name, client) != 0) 40229ea834fSthorpej continue; 40329ea834fSthorpej canon = hp->h_name; 40429ea834fSthorpej } 405c1b4b344Sthorpej 406c1b4b344Sthorpej #undef HASGLOB 407c1b4b344Sthorpej 4080d8ec8d0Sderaadt contin *= -1; 4090d8ec8d0Sderaadt break; 4100d8ec8d0Sderaadt case 1: 4110d8ec8d0Sderaadt /* Continued line we want to parse below */ 4120d8ec8d0Sderaadt break; 4130d8ec8d0Sderaadt } 414ae99bc57Sderaadt 415c1b4b344Sthorpej assert(canon != NULL); 4160d8ec8d0Sderaadt if (client_canonical) 417c1b4b344Sthorpej strncpy(client_canonical, canon, MAX_MACHINE_NAME); 4180d8ec8d0Sderaadt 4190d8ec8d0Sderaadt /* We have found a line for CLIENT */ 420f392a261Sglass if (id == NULL) { 421f392a261Sglass (void) fclose(f); 4220d8ec8d0Sderaadt return 0; 423f392a261Sglass } 4240d8ec8d0Sderaadt 4250d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 4260d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 4270d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 4280d8ec8d0Sderaadt /* We have found the entry we want */ 4290d8ec8d0Sderaadt *server = &word[idlen + 1]; 4300d8ec8d0Sderaadt *path = strchr(*server, ':'); 4310d8ec8d0Sderaadt if (*path == NULL) 4320d8ec8d0Sderaadt /* Malformed entry */ 4330d8ec8d0Sderaadt continue; 4340d8ec8d0Sderaadt *(*path)++ = '\0'; 4350d8ec8d0Sderaadt (void) fclose(f); 4360d8ec8d0Sderaadt return 0; 437ae99bc57Sderaadt } 438ae99bc57Sderaadt } 4390d8ec8d0Sderaadt 4400d8ec8d0Sderaadt found = 1; 441ae99bc57Sderaadt } 4420d8ec8d0Sderaadt 4430d8ec8d0Sderaadt (void) fclose(f); 4440d8ec8d0Sderaadt return found ? ENOENT : EPERM; 445ae99bc57Sderaadt } 446b5468677Sthorpej 447b5468677Sthorpej void 448b5468677Sthorpej usage() 449b5468677Sthorpej { 450b5468677Sthorpej fprintf(stderr, 451b5468677Sthorpej "usage: %s [-d] [-s] [-r router] [-f bootparmsfile]\n", __progname); 452b5468677Sthorpej exit(1); 453b5468677Sthorpej } 45408507c14Sitojun 45508507c14Sitojun static int 45608507c14Sitojun get_localaddr(ifname, sin) 45708507c14Sitojun const char *ifname; 45808507c14Sitojun struct sockaddr_in *sin; 45908507c14Sitojun { 46008507c14Sitojun struct ifaddrs *ifap, *ifa; 46108507c14Sitojun 46208507c14Sitojun if (getifaddrs(&ifap) != 0) 46308507c14Sitojun return -1; 46408507c14Sitojun 46508507c14Sitojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 46608507c14Sitojun if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 46708507c14Sitojun continue; 46808507c14Sitojun if (ifa->ifa_addr->sa_family != AF_INET) 46908507c14Sitojun continue; 47008507c14Sitojun if (ifa->ifa_addr->sa_len != sizeof(*sin)) 47108507c14Sitojun continue; 47208507c14Sitojun 47308507c14Sitojun /* no loopback please */ 47408507c14Sitojun #ifdef IFF_LOOPBACK 47508507c14Sitojun if (ifa->ifa_flags & IFF_LOOPBACK) 47608507c14Sitojun continue; 47708507c14Sitojun #else 47803b1bcc6Sitojun if (strncmp(ifa->ifa_name, "lo", 2) == 0 && 47903b1bcc6Sitojun (isdigit(ifa->ifa_name[2]) || ifa->ifa_name[2] == '\0')) 48008507c14Sitojun continue; 48108507c14Sitojun #endif 48208507c14Sitojun 48308507c14Sitojun /* XXX more sanity checks? */ 48408507c14Sitojun 48508507c14Sitojun /* candidate found */ 48608507c14Sitojun memcpy(sin, ifa->ifa_addr, ifa->ifa_addr->sa_len); 48708507c14Sitojun freeifaddrs(ifap); 48808507c14Sitojun return 0; 48908507c14Sitojun } 49008507c14Sitojun 49108507c14Sitojun /* no candidate */ 49208507c14Sitojun freeifaddrs(ifap); 49308507c14Sitojun return -1; 49408507c14Sitojun } 495