1#include "lookup.h" 2#include "stdio_impl.h" 3#include <ctype.h> 4#include <errno.h> 5#include <netinet/in.h> 6#include <string.h> 7 8int __get_resolv_conf(struct resolvconf* conf, char* search, size_t search_sz) { 9 char line[256]; 10 unsigned char _buf[256]; 11 FILE *f, _f; 12 int nns = 0; 13 14 conf->ndots = 1; 15 conf->timeout = 5; 16 conf->attempts = 2; 17 if (search) 18 *search = 0; 19 20 f = __fopen_rb_ca("/etc/resolv.conf", &_f, _buf, sizeof _buf); 21 if (!f) 22 switch (errno) { 23 case ENOENT: 24 case ENOTDIR: 25 case EACCES: 26 goto no_resolv_conf; 27 default: 28 return -1; 29 } 30 31 while (fgets(line, sizeof line, f)) { 32 char *p, *z; 33 if (!strchr(line, '\n') && !feof(f)) { 34 /* Ignore lines that get truncated rather than 35 * potentially misinterpreting them. */ 36 int c; 37 do 38 c = getc(f); 39 while (c != '\n' && c != EOF); 40 continue; 41 } 42 if (!strncmp(line, "options", 7) && isspace(line[7])) { 43 p = strstr(line, "ndots:"); 44 if (p && isdigit(p[6])) { 45 p += 6; 46 unsigned long x = strtoul(p, &z, 10); 47 if (z != p) 48 conf->ndots = x > 15 ? 15 : x; 49 } 50 p = strstr(line, "attempts:"); 51 if (p && isdigit(p[6])) { 52 p += 6; 53 unsigned long x = strtoul(p, &z, 10); 54 if (z != p) 55 conf->attempts = x > 10 ? 10 : x; 56 } 57 p = strstr(line, "timeout:"); 58 if (p && (isdigit(p[8]) || p[8] == '.')) { 59 p += 8; 60 unsigned long x = strtoul(p, &z, 10); 61 if (z != p) 62 conf->timeout = x > 60 ? 60 : x; 63 } 64 continue; 65 } 66 if (!strncmp(line, "nameserver", 10) && isspace(line[10])) { 67 if (nns >= MAXNS) 68 continue; 69 for (p = line + 11; isspace(*p); p++) 70 ; 71 for (z = p; *z && !isspace(*z); z++) 72 ; 73 *z = 0; 74 if (__lookup_ipliteral(conf->ns + nns, p, AF_UNSPEC) > 0) 75 nns++; 76 continue; 77 } 78 79 if (!search) 80 continue; 81 if ((strncmp(line, "domain", 6) && strncmp(line, "search", 6)) || !isspace(line[6])) 82 continue; 83 for (p = line + 7; isspace(*p); p++) 84 ; 85 size_t l = strlen(p); 86 /* This can never happen anyway with chosen buffer sizes. */ 87 if (l >= search_sz) 88 continue; 89 memcpy(search, p, l + 1); 90 } 91 92 __fclose_ca(f); 93 94no_resolv_conf: 95 if (!nns) { 96 __lookup_ipliteral(conf->ns, "127.0.0.1", AF_UNSPEC); 97 nns = 1; 98 } 99 100 conf->nns = nns; 101 102 return 0; 103} 104