1*03b1bcc6Sitojun /* $NetBSD: bootparamd.c,v 1.23 2000/04/27 09:48:59 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*03b1bcc6Sitojun __RCSID("$NetBSD: bootparamd.c,v 1.23 2000/04/27 09:48:59 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 220d53a465Smycroft #include <ctype.h> 23d3964689Schristos #include <errno.h> 240d53a465Smycroft #include <err.h> 250d53a465Smycroft #include <netdb.h> 26b5468677Sthorpej #include <stdlib.h> 270d53a465Smycroft #include <stdio.h> 280d53a465Smycroft #include <string.h> 290d53a465Smycroft #include <syslog.h> 30b5468677Sthorpej #include <unistd.h> 31653c3855Sthorpej #include <util.h> 3208507c14Sitojun #include <ifaddrs.h> 330d53a465Smycroft 34*03b1bcc6Sitojun #include <net/if.h> 35*03b1bcc6Sitojun 360d53a465Smycroft #include <netinet/in.h> 370d53a465Smycroft #include <arpa/inet.h> 380d53a465Smycroft 39ae99bc57Sderaadt #include <rpc/rpc.h> 40b5468677Sthorpej #include <rpc/pmap_clnt.h> 41ae99bc57Sderaadt #include <rpcsvc/bootparam_prot.h> 42b5468677Sthorpej #include <rpcsvc/ypclnt.h> 430d53a465Smycroft 440d8ec8d0Sderaadt #include "pathnames.h" 45ae99bc57Sderaadt 46ae99bc57Sderaadt #define MAXLEN 800 47ae99bc57Sderaadt 48ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME]; 49ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME]; 50ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME]; 51ae99bc57Sderaadt 52d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *)); 53ae99bc57Sderaadt 54d8f00aa3Spk int _rpcsvcdirty = 0; 55d8f00aa3Spk int _rpcpmstart = 0; 56ae99bc57Sderaadt int debug = 0; 57ae99bc57Sderaadt int dolog = 0; 58b5468677Sthorpej struct in_addr route_addr; 59ae99bc57Sderaadt struct sockaddr_in my_addr; 60ee7207b7Smycroft extern char *__progname; 610d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 62ae99bc57Sderaadt 63b5468677Sthorpej int main __P((int, char *[])); 64b5468677Sthorpej int lookup_bootparam __P((char *, char *, char *, char **, char **)); 65b5468677Sthorpej void usage __P((void)); 6608507c14Sitojun static int get_localaddr __P((const char *, struct sockaddr_in *)); 67ae99bc57Sderaadt 68ae99bc57Sderaadt 69ae99bc57Sderaadt /* 70ae99bc57Sderaadt * ever familiar 71ae99bc57Sderaadt */ 72ae99bc57Sderaadt int 73ae99bc57Sderaadt main(argc, argv) 74ae99bc57Sderaadt int argc; 75b5468677Sthorpej char *argv[]; 76ae99bc57Sderaadt { 77ae99bc57Sderaadt SVCXPRT *transp; 78ae99bc57Sderaadt struct hostent *he; 79ae99bc57Sderaadt struct stat buf; 80d907c076Smark int c; 81ae99bc57Sderaadt 82d907c076Smark while ((c = getopt(argc, argv, "dsr:f:")) != -1) 83ae99bc57Sderaadt switch (c) { 84ae99bc57Sderaadt case 'd': 85ae99bc57Sderaadt debug = 1; 86ae99bc57Sderaadt break; 87ae99bc57Sderaadt case 'r': 88ae99bc57Sderaadt if (isdigit(*optarg)) { 89b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 90ae99bc57Sderaadt break; 91ae99bc57Sderaadt } 92ae99bc57Sderaadt he = gethostbyname(optarg); 93b5468677Sthorpej if (he == 0) { 94312c7832Smikel warnx("no such host: %s", optarg); 95ae99bc57Sderaadt usage(); 96ae99bc57Sderaadt } 977e807419Slukem memmove(&route_addr.s_addr, he->h_addr, he->h_length); 98ae99bc57Sderaadt break; 99ae99bc57Sderaadt case 'f': 100ae99bc57Sderaadt bootpfile = optarg; 101ae99bc57Sderaadt break; 102ae99bc57Sderaadt case 's': 103ae99bc57Sderaadt dolog = 1; 104ae99bc57Sderaadt #ifndef LOG_DAEMON 105ee7207b7Smycroft openlog(__progname, 0, 0); 106ae99bc57Sderaadt #else 107ee7207b7Smycroft openlog(__progname, 0, LOG_DAEMON); 108ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 109ae99bc57Sderaadt #endif 110ae99bc57Sderaadt break; 111ae99bc57Sderaadt default: 112ae99bc57Sderaadt usage(); 113ae99bc57Sderaadt } 114ae99bc57Sderaadt 1150d53a465Smycroft if (stat(bootpfile, &buf)) 1160d53a465Smycroft err(1, "%s", bootpfile); 1170d53a465Smycroft 118b5468677Sthorpej if (route_addr.s_addr == 0) { 11908507c14Sitojun if (get_localaddr(NULL, &my_addr) != 0) 12008507c14Sitojun errx(1, "router address not found"); 121b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 122ae99bc57Sderaadt } 1230d53a465Smycroft if (!debug) { 1240d53a465Smycroft if (daemon(0, 0)) 1250d53a465Smycroft err(1, "can't detach from terminal"); 1260d53a465Smycroft } 127653c3855Sthorpej pidfile(NULL); 128ae99bc57Sderaadt 129ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 130ae99bc57Sderaadt 131ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1320d53a465Smycroft if (transp == NULL) 1330d53a465Smycroft errx(1, "can't create udp service"); 1340d53a465Smycroft 1350d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1360d53a465Smycroft IPPROTO_UDP)) 137e8664c71Slukem errx(1, "unable to register BOOTPARAMPROG version %ld, udp", 138ae99bc57Sderaadt BOOTPARAMVERS); 1390d53a465Smycroft 140ae99bc57Sderaadt svc_run(); 1410d53a465Smycroft errx(1, "svc_run returned"); 142ae99bc57Sderaadt } 143ae99bc57Sderaadt 144ae99bc57Sderaadt bp_whoami_res * 145d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 146ae99bc57Sderaadt bp_whoami_arg *whoami; 147d8f00aa3Spk struct svc_req *rqstp; 148ae99bc57Sderaadt { 149ae99bc57Sderaadt static bp_whoami_res res; 150b7dcf10eScgd struct hostent *he; 15188e77501Snathanw struct in_addr haddr; 152d3964689Schristos int e; 1530d8ec8d0Sderaadt 154ae99bc57Sderaadt if (debug) 155312c7832Smikel warnx("whoami got question for %d.%d.%d.%d", 156ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 157ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 158ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 159ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 160ae99bc57Sderaadt if (dolog) 161312c7832Smikel syslog(LOG_NOTICE, "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 1677e807419Slukem memmove((char *) &haddr, 1687e807419Slukem (char *) &whoami->client_address.bp_address_u.ip_addr, 1697e807419Slukem sizeof(haddr)); 170ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 171ddc2dd4fSmrg if (he) { 172ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 173ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 174ddc2dd4fSmrg } else { 17588e77501Snathanw strncpy(askname, inet_ntoa(haddr), sizeof(askname)); 176ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 177b7dcf10eScgd } 178ae99bc57Sderaadt 179ae99bc57Sderaadt if (debug) 180312c7832Smikel warnx("This is host %s", askname); 181ae99bc57Sderaadt if (dolog) 182312c7832Smikel syslog(LOG_NOTICE, "This is host %s", askname); 183ae99bc57Sderaadt 184d3964689Schristos if ((e = lookup_bootparam(askname, hostname, NULL, NULL, NULL)) == 0) { 185ae99bc57Sderaadt res.client_name = hostname; 186ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 187ae99bc57Sderaadt res.domain_name = domain_name; 188ae99bc57Sderaadt 189ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 190ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 1917e807419Slukem memmove(&res.router_address.bp_address_u.ip_addr, 1927e807419Slukem &route_addr.s_addr,4); 193ae99bc57Sderaadt } 194ae99bc57Sderaadt if (debug) 195312c7832Smikel warnx("Returning %s %s %d.%d.%d.%d", 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 if (dolog) 202312c7832Smikel syslog(LOG_NOTICE, "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 209ae99bc57Sderaadt return (&res); 210ae99bc57Sderaadt } 211d3964689Schristos errno = e; 212ae99bc57Sderaadt if (debug) 213d3964689Schristos warn("whoami failed"); 214ae99bc57Sderaadt if (dolog) 215d3964689Schristos syslog(LOG_NOTICE, "whoami failed %m"); 216ae99bc57Sderaadt return (NULL); 217ae99bc57Sderaadt } 218ae99bc57Sderaadt 219ae99bc57Sderaadt 220ae99bc57Sderaadt bp_getfile_res * 221d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 222ae99bc57Sderaadt bp_getfile_arg *getfile; 223d8f00aa3Spk struct svc_req *rqstp; 224ae99bc57Sderaadt { 225ae99bc57Sderaadt static bp_getfile_res res; 226b7dcf10eScgd struct hostent *he; 2270d8ec8d0Sderaadt int err; 228ae99bc57Sderaadt 229ae99bc57Sderaadt if (debug) 230312c7832Smikel warnx("getfile got question for \"%s\" and file \"%s\"", 231ae99bc57Sderaadt getfile->client_name, getfile->file_id); 232ae99bc57Sderaadt 233ae99bc57Sderaadt if (dolog) 234312c7832Smikel syslog(LOG_NOTICE, 235312c7832Smikel "getfile got question for \"%s\" and file \"%s\"", 236ae99bc57Sderaadt getfile->client_name, getfile->file_id); 237ae99bc57Sderaadt 238ae99bc57Sderaadt he = NULL; 239ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 240ae99bc57Sderaadt if (!he) 241ae99bc57Sderaadt goto failed; 242ae99bc57Sderaadt 243ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 244ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 2450d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2460d8ec8d0Sderaadt &res.server_name, &res.server_path); 2470d8ec8d0Sderaadt if (err == 0) { 2480d8ec8d0Sderaadt he = gethostbyname(res.server_name); 249ae99bc57Sderaadt if (!he) 250ae99bc57Sderaadt goto failed; 2517e807419Slukem memmove(&res.server_address.bp_address_u.ip_addr, 2527e807419Slukem he->h_addr, 4); 253ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2540d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2550d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 256ae99bc57Sderaadt res.server_name[0] = '\0'; 257ae99bc57Sderaadt res.server_path[0] = '\0'; 2587e807419Slukem memset(&res.server_address.bp_address_u.ip_addr, 0, 4); 2590d8ec8d0Sderaadt } else { 2600d8ec8d0Sderaadt failed: 2610d8ec8d0Sderaadt if (debug) 262312c7832Smikel warnx("getfile failed for %s", 2630d8ec8d0Sderaadt getfile->client_name); 2640d8ec8d0Sderaadt if (dolog) 2650d8ec8d0Sderaadt syslog(LOG_NOTICE, 266312c7832Smikel "getfile failed for %s", getfile->client_name); 2670d8ec8d0Sderaadt return (NULL); 268ae99bc57Sderaadt } 2690d8ec8d0Sderaadt 270ae99bc57Sderaadt if (debug) 2710d53a465Smycroft warnx( 272312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 273ae99bc57Sderaadt res.server_name, res.server_path, 274ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 275ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 276ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 277ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 278ae99bc57Sderaadt if (dolog) 279ae99bc57Sderaadt syslog(LOG_NOTICE, 280312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 281ae99bc57Sderaadt res.server_name, res.server_path, 282ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 283ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 284ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 285ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 286ae99bc57Sderaadt return (&res); 287ae99bc57Sderaadt } 288ae99bc57Sderaadt 289ae99bc57Sderaadt 2900d8ec8d0Sderaadt int 2910d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 2920d8ec8d0Sderaadt char *client; 2930d8ec8d0Sderaadt char *client_canonical; 2940d8ec8d0Sderaadt char *id; 2950d8ec8d0Sderaadt char **server; 2960d8ec8d0Sderaadt char **path; 297ae99bc57Sderaadt { 2980d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 2990d8ec8d0Sderaadt #ifdef YP 3000d8ec8d0Sderaadt static char *ypbuf = NULL; 3010d8ec8d0Sderaadt static int ypbuflen = 0; 3020d8ec8d0Sderaadt #endif 3030d8ec8d0Sderaadt static char buf[BUFSIZ]; 304b5468677Sthorpej char *bp, *word = NULL; 3050d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 3060d8ec8d0Sderaadt int contin = 0; 3070d8ec8d0Sderaadt int found = 0; 308ae99bc57Sderaadt 3090d8ec8d0Sderaadt if (f == NULL) 3100d8ec8d0Sderaadt return EINVAL; /* ? */ 311ae99bc57Sderaadt 3120d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3130d8ec8d0Sderaadt int wascontin = contin; 3140d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3150d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 316ae99bc57Sderaadt 3170d8ec8d0Sderaadt switch (wascontin) { 3180d8ec8d0Sderaadt case -1: 3190d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3200d8ec8d0Sderaadt contin *= -1; 321ae99bc57Sderaadt continue; 3220d8ec8d0Sderaadt case 0: 3230d8ec8d0Sderaadt /* New line */ 3240d8ec8d0Sderaadt contin *= -1; 3250d8ec8d0Sderaadt if (*bp == '#') 3260d8ec8d0Sderaadt continue; 3270d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3280d8ec8d0Sderaadt continue; 3290d8ec8d0Sderaadt #ifdef YP 3300d8ec8d0Sderaadt /* A + in the file means try YP now */ 3310d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3320d8ec8d0Sderaadt char *ypdom; 3330d8ec8d0Sderaadt 3340d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3350d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3360d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3370d8ec8d0Sderaadt continue; 3380d8ec8d0Sderaadt bp = ypbuf; 3390d8ec8d0Sderaadt word = client; 3400d8ec8d0Sderaadt contin *= -1; 341ae99bc57Sderaadt break; 342ae99bc57Sderaadt } 3430d8ec8d0Sderaadt #endif 344d3964689Schristos if (debug) 345d3964689Schristos warnx("match %s with %s", word, client); 3460d8ec8d0Sderaadt /* See if this line's client is the one we are 3470d8ec8d0Sderaadt * looking for */ 348010a229cScgd if (strcasecmp(word, client) != 0) { 349ae99bc57Sderaadt /* 3500d8ec8d0Sderaadt * If it didn't match, try getting the 3510d8ec8d0Sderaadt * canonical host name of the client 3520d8ec8d0Sderaadt * on this line and comparing that to 3530d8ec8d0Sderaadt * the client we are looking for 354ae99bc57Sderaadt */ 3550d8ec8d0Sderaadt struct hostent *hp = gethostbyname(word); 356bf094b72Sabs if (hp == NULL ) { 357bf094b72Sabs if (debug) 358bf094b72Sabs warnx( 359bf094b72Sabs "Unknown bootparams host %s", word); 360bf094b72Sabs if (dolog) 361bf094b72Sabs syslog(LOG_NOTICE, 362bf094b72Sabs "Unknown bootparams host %s", word); 363bf094b72Sabs continue; 364bf094b72Sabs } 365bf094b72Sabs if (strcasecmp(hp->h_name, client)) 3660d8ec8d0Sderaadt continue; 3670d8ec8d0Sderaadt } 3680d8ec8d0Sderaadt contin *= -1; 3690d8ec8d0Sderaadt break; 3700d8ec8d0Sderaadt case 1: 3710d8ec8d0Sderaadt /* Continued line we want to parse below */ 3720d8ec8d0Sderaadt break; 3730d8ec8d0Sderaadt } 374ae99bc57Sderaadt 3750d8ec8d0Sderaadt if (client_canonical) 3760d8ec8d0Sderaadt strncpy(client_canonical, word, MAX_MACHINE_NAME); 3770d8ec8d0Sderaadt 3780d8ec8d0Sderaadt /* We have found a line for CLIENT */ 379f392a261Sglass if (id == NULL) { 380f392a261Sglass (void) fclose(f); 3810d8ec8d0Sderaadt return 0; 382f392a261Sglass } 3830d8ec8d0Sderaadt 3840d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 3850d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 3860d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 3870d8ec8d0Sderaadt /* We have found the entry we want */ 3880d8ec8d0Sderaadt *server = &word[idlen + 1]; 3890d8ec8d0Sderaadt *path = strchr(*server, ':'); 3900d8ec8d0Sderaadt if (*path == NULL) 3910d8ec8d0Sderaadt /* Malformed entry */ 3920d8ec8d0Sderaadt continue; 3930d8ec8d0Sderaadt *(*path)++ = '\0'; 3940d8ec8d0Sderaadt (void) fclose(f); 3950d8ec8d0Sderaadt return 0; 396ae99bc57Sderaadt } 397ae99bc57Sderaadt } 3980d8ec8d0Sderaadt 3990d8ec8d0Sderaadt found = 1; 400ae99bc57Sderaadt } 4010d8ec8d0Sderaadt 4020d8ec8d0Sderaadt (void) fclose(f); 4030d8ec8d0Sderaadt return found ? ENOENT : EPERM; 404ae99bc57Sderaadt } 405b5468677Sthorpej 406b5468677Sthorpej void 407b5468677Sthorpej usage() 408b5468677Sthorpej { 409b5468677Sthorpej fprintf(stderr, 410b5468677Sthorpej "usage: %s [-d] [-s] [-r router] [-f bootparmsfile]\n", __progname); 411b5468677Sthorpej exit(1); 412b5468677Sthorpej } 41308507c14Sitojun 41408507c14Sitojun static int 41508507c14Sitojun get_localaddr(ifname, sin) 41608507c14Sitojun const char *ifname; 41708507c14Sitojun struct sockaddr_in *sin; 41808507c14Sitojun { 41908507c14Sitojun struct ifaddrs *ifap, *ifa; 42008507c14Sitojun 42108507c14Sitojun if (getifaddrs(&ifap) != 0) 42208507c14Sitojun return -1; 42308507c14Sitojun 42408507c14Sitojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 42508507c14Sitojun if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 42608507c14Sitojun continue; 42708507c14Sitojun if (ifa->ifa_addr->sa_family != AF_INET) 42808507c14Sitojun continue; 42908507c14Sitojun if (ifa->ifa_addr->sa_len != sizeof(*sin)) 43008507c14Sitojun continue; 43108507c14Sitojun 43208507c14Sitojun /* no loopback please */ 43308507c14Sitojun #ifdef IFF_LOOPBACK 43408507c14Sitojun if (ifa->ifa_flags & IFF_LOOPBACK) 43508507c14Sitojun continue; 43608507c14Sitojun #else 437*03b1bcc6Sitojun if (strncmp(ifa->ifa_name, "lo", 2) == 0 && 438*03b1bcc6Sitojun (isdigit(ifa->ifa_name[2]) || ifa->ifa_name[2] == '\0')) 43908507c14Sitojun continue; 44008507c14Sitojun #endif 44108507c14Sitojun 44208507c14Sitojun /* XXX more sanity checks? */ 44308507c14Sitojun 44408507c14Sitojun /* candidate found */ 44508507c14Sitojun memcpy(sin, ifa->ifa_addr, ifa->ifa_addr->sa_len); 44608507c14Sitojun freeifaddrs(ifap); 44708507c14Sitojun return 0; 44808507c14Sitojun } 44908507c14Sitojun 45008507c14Sitojun /* no candidate */ 45108507c14Sitojun freeifaddrs(ifap); 45208507c14Sitojun return -1; 45308507c14Sitojun } 454