1*08507c14Sitojun /* $NetBSD: bootparamd.c,v 1.22 2000/04/14 12:14:40 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*08507c14Sitojun __RCSID("$NetBSD: bootparamd.c,v 1.22 2000/04/14 12:14:40 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> 32*08507c14Sitojun #include <ifaddrs.h> 330d53a465Smycroft 340d53a465Smycroft #include <netinet/in.h> 350d53a465Smycroft #include <arpa/inet.h> 360d53a465Smycroft 37ae99bc57Sderaadt #include <rpc/rpc.h> 38b5468677Sthorpej #include <rpc/pmap_clnt.h> 39ae99bc57Sderaadt #include <rpcsvc/bootparam_prot.h> 40b5468677Sthorpej #include <rpcsvc/ypclnt.h> 410d53a465Smycroft 420d8ec8d0Sderaadt #include "pathnames.h" 43ae99bc57Sderaadt 44ae99bc57Sderaadt #define MAXLEN 800 45ae99bc57Sderaadt 46ae99bc57Sderaadt static char hostname[MAX_MACHINE_NAME]; 47ae99bc57Sderaadt static char askname[MAX_MACHINE_NAME]; 48ae99bc57Sderaadt static char domain_name[MAX_MACHINE_NAME]; 49ae99bc57Sderaadt 50d8f00aa3Spk extern void bootparamprog_1 __P((struct svc_req *, SVCXPRT *)); 51ae99bc57Sderaadt 52d8f00aa3Spk int _rpcsvcdirty = 0; 53d8f00aa3Spk int _rpcpmstart = 0; 54ae99bc57Sderaadt int debug = 0; 55ae99bc57Sderaadt int dolog = 0; 56b5468677Sthorpej struct in_addr route_addr; 57ae99bc57Sderaadt struct sockaddr_in my_addr; 58ee7207b7Smycroft extern char *__progname; 590d8ec8d0Sderaadt char *bootpfile = _PATH_BOOTPARAMS; 60ae99bc57Sderaadt 61b5468677Sthorpej int main __P((int, char *[])); 62b5468677Sthorpej int lookup_bootparam __P((char *, char *, char *, char **, char **)); 63b5468677Sthorpej void usage __P((void)); 64*08507c14Sitojun static int get_localaddr __P((const char *, struct sockaddr_in *)); 65ae99bc57Sderaadt 66ae99bc57Sderaadt 67ae99bc57Sderaadt /* 68ae99bc57Sderaadt * ever familiar 69ae99bc57Sderaadt */ 70ae99bc57Sderaadt int 71ae99bc57Sderaadt main(argc, argv) 72ae99bc57Sderaadt int argc; 73b5468677Sthorpej char *argv[]; 74ae99bc57Sderaadt { 75ae99bc57Sderaadt SVCXPRT *transp; 76ae99bc57Sderaadt struct hostent *he; 77ae99bc57Sderaadt struct stat buf; 78d907c076Smark int c; 79ae99bc57Sderaadt 80d907c076Smark while ((c = getopt(argc, argv, "dsr:f:")) != -1) 81ae99bc57Sderaadt switch (c) { 82ae99bc57Sderaadt case 'd': 83ae99bc57Sderaadt debug = 1; 84ae99bc57Sderaadt break; 85ae99bc57Sderaadt case 'r': 86ae99bc57Sderaadt if (isdigit(*optarg)) { 87b5468677Sthorpej if (inet_aton(optarg, &route_addr) != 0) 88ae99bc57Sderaadt break; 89ae99bc57Sderaadt } 90ae99bc57Sderaadt he = gethostbyname(optarg); 91b5468677Sthorpej if (he == 0) { 92312c7832Smikel warnx("no such host: %s", optarg); 93ae99bc57Sderaadt usage(); 94ae99bc57Sderaadt } 957e807419Slukem memmove(&route_addr.s_addr, he->h_addr, he->h_length); 96ae99bc57Sderaadt break; 97ae99bc57Sderaadt case 'f': 98ae99bc57Sderaadt bootpfile = optarg; 99ae99bc57Sderaadt break; 100ae99bc57Sderaadt case 's': 101ae99bc57Sderaadt dolog = 1; 102ae99bc57Sderaadt #ifndef LOG_DAEMON 103ee7207b7Smycroft openlog(__progname, 0, 0); 104ae99bc57Sderaadt #else 105ee7207b7Smycroft openlog(__progname, 0, LOG_DAEMON); 106ae99bc57Sderaadt setlogmask(LOG_UPTO(LOG_NOTICE)); 107ae99bc57Sderaadt #endif 108ae99bc57Sderaadt break; 109ae99bc57Sderaadt default: 110ae99bc57Sderaadt usage(); 111ae99bc57Sderaadt } 112ae99bc57Sderaadt 1130d53a465Smycroft if (stat(bootpfile, &buf)) 1140d53a465Smycroft err(1, "%s", bootpfile); 1150d53a465Smycroft 116b5468677Sthorpej if (route_addr.s_addr == 0) { 117*08507c14Sitojun if (get_localaddr(NULL, &my_addr) != 0) 118*08507c14Sitojun errx(1, "router address not found"); 119b5468677Sthorpej route_addr.s_addr = my_addr.sin_addr.s_addr; 120ae99bc57Sderaadt } 1210d53a465Smycroft if (!debug) { 1220d53a465Smycroft if (daemon(0, 0)) 1230d53a465Smycroft err(1, "can't detach from terminal"); 1240d53a465Smycroft } 125653c3855Sthorpej pidfile(NULL); 126ae99bc57Sderaadt 127ae99bc57Sderaadt (void) pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); 128ae99bc57Sderaadt 129ae99bc57Sderaadt transp = svcudp_create(RPC_ANYSOCK); 1300d53a465Smycroft if (transp == NULL) 1310d53a465Smycroft errx(1, "can't create udp service"); 1320d53a465Smycroft 1330d53a465Smycroft if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, 1340d53a465Smycroft IPPROTO_UDP)) 135e8664c71Slukem errx(1, "unable to register BOOTPARAMPROG version %ld, udp", 136ae99bc57Sderaadt BOOTPARAMVERS); 1370d53a465Smycroft 138ae99bc57Sderaadt svc_run(); 1390d53a465Smycroft errx(1, "svc_run returned"); 140ae99bc57Sderaadt } 141ae99bc57Sderaadt 142ae99bc57Sderaadt bp_whoami_res * 143d8f00aa3Spk bootparamproc_whoami_1_svc(whoami, rqstp) 144ae99bc57Sderaadt bp_whoami_arg *whoami; 145d8f00aa3Spk struct svc_req *rqstp; 146ae99bc57Sderaadt { 147ae99bc57Sderaadt static bp_whoami_res res; 148b7dcf10eScgd struct hostent *he; 14988e77501Snathanw struct in_addr haddr; 150d3964689Schristos int e; 1510d8ec8d0Sderaadt 152ae99bc57Sderaadt if (debug) 153312c7832Smikel warnx("whoami got question for %d.%d.%d.%d", 154ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 155ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 156ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 157ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 158ae99bc57Sderaadt if (dolog) 159312c7832Smikel syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d", 160ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.net, 161ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.host, 162ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.lh, 163ae99bc57Sderaadt 255 & whoami->client_address.bp_address_u.ip_addr.impno); 164ae99bc57Sderaadt 1657e807419Slukem memmove((char *) &haddr, 1667e807419Slukem (char *) &whoami->client_address.bp_address_u.ip_addr, 1677e807419Slukem sizeof(haddr)); 168ae99bc57Sderaadt he = gethostbyaddr((char *) &haddr, sizeof(haddr), AF_INET); 169ddc2dd4fSmrg if (he) { 170ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 171ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 172ddc2dd4fSmrg } else { 17388e77501Snathanw strncpy(askname, inet_ntoa(haddr), sizeof(askname)); 174ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 175b7dcf10eScgd } 176ae99bc57Sderaadt 177ae99bc57Sderaadt if (debug) 178312c7832Smikel warnx("This is host %s", askname); 179ae99bc57Sderaadt if (dolog) 180312c7832Smikel syslog(LOG_NOTICE, "This is host %s", askname); 181ae99bc57Sderaadt 182d3964689Schristos if ((e = lookup_bootparam(askname, hostname, NULL, NULL, NULL)) == 0) { 183ae99bc57Sderaadt res.client_name = hostname; 184ae99bc57Sderaadt getdomainname(domain_name, MAX_MACHINE_NAME); 185ae99bc57Sderaadt res.domain_name = domain_name; 186ae99bc57Sderaadt 187ae99bc57Sderaadt if (res.router_address.address_type != IP_ADDR_TYPE) { 188ae99bc57Sderaadt res.router_address.address_type = IP_ADDR_TYPE; 1897e807419Slukem memmove(&res.router_address.bp_address_u.ip_addr, 1907e807419Slukem &route_addr.s_addr,4); 191ae99bc57Sderaadt } 192ae99bc57Sderaadt if (debug) 193312c7832Smikel warnx("Returning %s %s %d.%d.%d.%d", 194ae99bc57Sderaadt res.client_name, res.domain_name, 195ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.net, 196ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.host, 197ae99bc57Sderaadt 255 & res.router_address.bp_address_u.ip_addr.lh, 198ae99bc57Sderaadt 255 &res.router_address.bp_address_u.ip_addr.impno); 199ae99bc57Sderaadt if (dolog) 200312c7832Smikel syslog(LOG_NOTICE, "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 207ae99bc57Sderaadt return (&res); 208ae99bc57Sderaadt } 209d3964689Schristos errno = e; 210ae99bc57Sderaadt if (debug) 211d3964689Schristos warn("whoami failed"); 212ae99bc57Sderaadt if (dolog) 213d3964689Schristos syslog(LOG_NOTICE, "whoami failed %m"); 214ae99bc57Sderaadt return (NULL); 215ae99bc57Sderaadt } 216ae99bc57Sderaadt 217ae99bc57Sderaadt 218ae99bc57Sderaadt bp_getfile_res * 219d8f00aa3Spk bootparamproc_getfile_1_svc(getfile, rqstp) 220ae99bc57Sderaadt bp_getfile_arg *getfile; 221d8f00aa3Spk struct svc_req *rqstp; 222ae99bc57Sderaadt { 223ae99bc57Sderaadt static bp_getfile_res res; 224b7dcf10eScgd struct hostent *he; 2250d8ec8d0Sderaadt int err; 226ae99bc57Sderaadt 227ae99bc57Sderaadt if (debug) 228312c7832Smikel warnx("getfile got question for \"%s\" and file \"%s\"", 229ae99bc57Sderaadt getfile->client_name, getfile->file_id); 230ae99bc57Sderaadt 231ae99bc57Sderaadt if (dolog) 232312c7832Smikel syslog(LOG_NOTICE, 233312c7832Smikel "getfile got question for \"%s\" and file \"%s\"", 234ae99bc57Sderaadt getfile->client_name, getfile->file_id); 235ae99bc57Sderaadt 236ae99bc57Sderaadt he = NULL; 237ae99bc57Sderaadt he = gethostbyname(getfile->client_name); 238ae99bc57Sderaadt if (!he) 239ae99bc57Sderaadt goto failed; 240ae99bc57Sderaadt 241ddc2dd4fSmrg strncpy(askname, he->h_name, sizeof(askname)); 242ddc2dd4fSmrg askname[sizeof(askname)-1] = 0; 2430d8ec8d0Sderaadt err = lookup_bootparam(askname, NULL, getfile->file_id, 2440d8ec8d0Sderaadt &res.server_name, &res.server_path); 2450d8ec8d0Sderaadt if (err == 0) { 2460d8ec8d0Sderaadt he = gethostbyname(res.server_name); 247ae99bc57Sderaadt if (!he) 248ae99bc57Sderaadt goto failed; 2497e807419Slukem memmove(&res.server_address.bp_address_u.ip_addr, 2507e807419Slukem he->h_addr, 4); 251ae99bc57Sderaadt res.server_address.address_type = IP_ADDR_TYPE; 2520d8ec8d0Sderaadt } else if (err == ENOENT && !strcmp(getfile->file_id, "dump")) { 2530d8ec8d0Sderaadt /* Special for dump, answer with null strings. */ 254ae99bc57Sderaadt res.server_name[0] = '\0'; 255ae99bc57Sderaadt res.server_path[0] = '\0'; 2567e807419Slukem memset(&res.server_address.bp_address_u.ip_addr, 0, 4); 2570d8ec8d0Sderaadt } else { 2580d8ec8d0Sderaadt failed: 2590d8ec8d0Sderaadt if (debug) 260312c7832Smikel warnx("getfile failed for %s", 2610d8ec8d0Sderaadt getfile->client_name); 2620d8ec8d0Sderaadt if (dolog) 2630d8ec8d0Sderaadt syslog(LOG_NOTICE, 264312c7832Smikel "getfile failed for %s", getfile->client_name); 2650d8ec8d0Sderaadt return (NULL); 266ae99bc57Sderaadt } 2670d8ec8d0Sderaadt 268ae99bc57Sderaadt if (debug) 2690d53a465Smycroft warnx( 270312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 271ae99bc57Sderaadt res.server_name, res.server_path, 272ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 273ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 274ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 275ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 276ae99bc57Sderaadt if (dolog) 277ae99bc57Sderaadt syslog(LOG_NOTICE, 278312c7832Smikel "returning server:%s path:%s address: %d.%d.%d.%d", 279ae99bc57Sderaadt res.server_name, res.server_path, 280ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.net, 281ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.host, 282ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.lh, 283ae99bc57Sderaadt 255 & res.server_address.bp_address_u.ip_addr.impno); 284ae99bc57Sderaadt return (&res); 285ae99bc57Sderaadt } 286ae99bc57Sderaadt 287ae99bc57Sderaadt 2880d8ec8d0Sderaadt int 2890d8ec8d0Sderaadt lookup_bootparam(client, client_canonical, id, server, path) 2900d8ec8d0Sderaadt char *client; 2910d8ec8d0Sderaadt char *client_canonical; 2920d8ec8d0Sderaadt char *id; 2930d8ec8d0Sderaadt char **server; 2940d8ec8d0Sderaadt char **path; 295ae99bc57Sderaadt { 2960d8ec8d0Sderaadt FILE *f = fopen(bootpfile, "r"); 2970d8ec8d0Sderaadt #ifdef YP 2980d8ec8d0Sderaadt static char *ypbuf = NULL; 2990d8ec8d0Sderaadt static int ypbuflen = 0; 3000d8ec8d0Sderaadt #endif 3010d8ec8d0Sderaadt static char buf[BUFSIZ]; 302b5468677Sthorpej char *bp, *word = NULL; 3030d8ec8d0Sderaadt size_t idlen = id == NULL ? 0 : strlen(id); 3040d8ec8d0Sderaadt int contin = 0; 3050d8ec8d0Sderaadt int found = 0; 306ae99bc57Sderaadt 3070d8ec8d0Sderaadt if (f == NULL) 3080d8ec8d0Sderaadt return EINVAL; /* ? */ 309ae99bc57Sderaadt 3100d8ec8d0Sderaadt while (fgets(buf, sizeof buf, f)) { 3110d8ec8d0Sderaadt int wascontin = contin; 3120d8ec8d0Sderaadt contin = buf[strlen(buf) - 2] == '\\'; 3130d8ec8d0Sderaadt bp = buf + strspn(buf, " \t\n"); 314ae99bc57Sderaadt 3150d8ec8d0Sderaadt switch (wascontin) { 3160d8ec8d0Sderaadt case -1: 3170d8ec8d0Sderaadt /* Continuation of uninteresting line */ 3180d8ec8d0Sderaadt contin *= -1; 319ae99bc57Sderaadt continue; 3200d8ec8d0Sderaadt case 0: 3210d8ec8d0Sderaadt /* New line */ 3220d8ec8d0Sderaadt contin *= -1; 3230d8ec8d0Sderaadt if (*bp == '#') 3240d8ec8d0Sderaadt continue; 3250d8ec8d0Sderaadt if ((word = strsep(&bp, " \t\n")) == NULL) 3260d8ec8d0Sderaadt continue; 3270d8ec8d0Sderaadt #ifdef YP 3280d8ec8d0Sderaadt /* A + in the file means try YP now */ 3290d8ec8d0Sderaadt if (!strcmp(word, "+")) { 3300d8ec8d0Sderaadt char *ypdom; 3310d8ec8d0Sderaadt 3320d8ec8d0Sderaadt if (yp_get_default_domain(&ypdom) || 3330d8ec8d0Sderaadt yp_match(ypdom, "bootparams", client, 3340d8ec8d0Sderaadt strlen(client), &ypbuf, &ypbuflen)) 3350d8ec8d0Sderaadt continue; 3360d8ec8d0Sderaadt bp = ypbuf; 3370d8ec8d0Sderaadt word = client; 3380d8ec8d0Sderaadt contin *= -1; 339ae99bc57Sderaadt break; 340ae99bc57Sderaadt } 3410d8ec8d0Sderaadt #endif 342d3964689Schristos if (debug) 343d3964689Schristos warnx("match %s with %s", word, client); 3440d8ec8d0Sderaadt /* See if this line's client is the one we are 3450d8ec8d0Sderaadt * looking for */ 346010a229cScgd if (strcasecmp(word, client) != 0) { 347ae99bc57Sderaadt /* 3480d8ec8d0Sderaadt * If it didn't match, try getting the 3490d8ec8d0Sderaadt * canonical host name of the client 3500d8ec8d0Sderaadt * on this line and comparing that to 3510d8ec8d0Sderaadt * the client we are looking for 352ae99bc57Sderaadt */ 3530d8ec8d0Sderaadt struct hostent *hp = gethostbyname(word); 354bf094b72Sabs if (hp == NULL ) { 355bf094b72Sabs if (debug) 356bf094b72Sabs warnx( 357bf094b72Sabs "Unknown bootparams host %s", word); 358bf094b72Sabs if (dolog) 359bf094b72Sabs syslog(LOG_NOTICE, 360bf094b72Sabs "Unknown bootparams host %s", word); 361bf094b72Sabs continue; 362bf094b72Sabs } 363bf094b72Sabs if (strcasecmp(hp->h_name, client)) 3640d8ec8d0Sderaadt continue; 3650d8ec8d0Sderaadt } 3660d8ec8d0Sderaadt contin *= -1; 3670d8ec8d0Sderaadt break; 3680d8ec8d0Sderaadt case 1: 3690d8ec8d0Sderaadt /* Continued line we want to parse below */ 3700d8ec8d0Sderaadt break; 3710d8ec8d0Sderaadt } 372ae99bc57Sderaadt 3730d8ec8d0Sderaadt if (client_canonical) 3740d8ec8d0Sderaadt strncpy(client_canonical, word, MAX_MACHINE_NAME); 3750d8ec8d0Sderaadt 3760d8ec8d0Sderaadt /* We have found a line for CLIENT */ 377f392a261Sglass if (id == NULL) { 378f392a261Sglass (void) fclose(f); 3790d8ec8d0Sderaadt return 0; 380f392a261Sglass } 3810d8ec8d0Sderaadt 3820d8ec8d0Sderaadt /* Look for a value for the parameter named by ID */ 3830d8ec8d0Sderaadt while ((word = strsep(&bp, " \t\n")) != NULL) { 3840d8ec8d0Sderaadt if (!strncmp(word, id, idlen) && word[idlen] == '=') { 3850d8ec8d0Sderaadt /* We have found the entry we want */ 3860d8ec8d0Sderaadt *server = &word[idlen + 1]; 3870d8ec8d0Sderaadt *path = strchr(*server, ':'); 3880d8ec8d0Sderaadt if (*path == NULL) 3890d8ec8d0Sderaadt /* Malformed entry */ 3900d8ec8d0Sderaadt continue; 3910d8ec8d0Sderaadt *(*path)++ = '\0'; 3920d8ec8d0Sderaadt (void) fclose(f); 3930d8ec8d0Sderaadt return 0; 394ae99bc57Sderaadt } 395ae99bc57Sderaadt } 3960d8ec8d0Sderaadt 3970d8ec8d0Sderaadt found = 1; 398ae99bc57Sderaadt } 3990d8ec8d0Sderaadt 4000d8ec8d0Sderaadt (void) fclose(f); 4010d8ec8d0Sderaadt return found ? ENOENT : EPERM; 402ae99bc57Sderaadt } 403b5468677Sthorpej 404b5468677Sthorpej void 405b5468677Sthorpej usage() 406b5468677Sthorpej { 407b5468677Sthorpej fprintf(stderr, 408b5468677Sthorpej "usage: %s [-d] [-s] [-r router] [-f bootparmsfile]\n", __progname); 409b5468677Sthorpej exit(1); 410b5468677Sthorpej } 411*08507c14Sitojun 412*08507c14Sitojun static int 413*08507c14Sitojun get_localaddr(ifname, sin) 414*08507c14Sitojun const char *ifname; 415*08507c14Sitojun struct sockaddr_in *sin; 416*08507c14Sitojun { 417*08507c14Sitojun struct ifaddrs *ifap, *ifa; 418*08507c14Sitojun 419*08507c14Sitojun if (getifaddrs(&ifap) != 0) 420*08507c14Sitojun return -1; 421*08507c14Sitojun 422*08507c14Sitojun for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 423*08507c14Sitojun if (ifname && strcmp(ifname, ifa->ifa_name) != 0) 424*08507c14Sitojun continue; 425*08507c14Sitojun if (ifa->ifa_addr->sa_family != AF_INET) 426*08507c14Sitojun continue; 427*08507c14Sitojun if (ifa->ifa_addr->sa_len != sizeof(*sin)) 428*08507c14Sitojun continue; 429*08507c14Sitojun 430*08507c14Sitojun /* no loopback please */ 431*08507c14Sitojun #ifdef IFF_LOOPBACK 432*08507c14Sitojun if (ifa->ifa_flags & IFF_LOOPBACK) 433*08507c14Sitojun continue; 434*08507c14Sitojun #else 435*08507c14Sitojun if (strncmp(ifa->ifa_name, "lo", 2) == 0) 436*08507c14Sitojun continue; 437*08507c14Sitojun #endif 438*08507c14Sitojun 439*08507c14Sitojun /* XXX more sanity checks? */ 440*08507c14Sitojun 441*08507c14Sitojun /* candidate found */ 442*08507c14Sitojun memcpy(sin, ifa->ifa_addr, ifa->ifa_addr->sa_len); 443*08507c14Sitojun freeifaddrs(ifap); 444*08507c14Sitojun return 0; 445*08507c14Sitojun } 446*08507c14Sitojun 447*08507c14Sitojun /* no candidate */ 448*08507c14Sitojun freeifaddrs(ifap); 449*08507c14Sitojun return -1; 450*08507c14Sitojun } 451