| /** |
| * @file ns.c DNS Nameserver configuration |
| * |
| * Copyright (C) 2010 Creytiv.com |
| */ |
| #include <stdio.h> |
| #include <re_types.h> |
| #include <re_fmt.h> |
| #include <re_mbuf.h> |
| #include <re_list.h> |
| #include <re_sa.h> |
| #include <re_dns.h> |
| #include "dns.h" |
| #ifdef __ANDROID__ |
| #include <sys/system_properties.h> |
| #endif |
| |
| |
| #define DEBUG_MODULE "ns" |
| #define DEBUG_LEVEL 5 |
| #include <re_dbg.h> |
| |
| |
| static int parse_resolv_conf(char *domain, size_t dsize, |
| struct sa *srvv, uint32_t *n) |
| { |
| FILE *f; |
| struct pl dom = pl_null; |
| uint32_t i = 0; |
| int err = 0; |
| |
| if (!srvv || !n || !*n) |
| return EINVAL; |
| |
| f = fopen("/etc/resolv.conf", "r"); |
| if (!f) |
| return errno; |
| |
| for (;;) { |
| char line[128]; |
| struct pl srv; |
| size_t len; |
| |
| if (1 != fscanf(f, "%127[^\n]\n", line)) |
| break; |
| |
| if ('#' == line[0]) |
| continue; |
| |
| len = str_len(line); |
| |
| /* Set domain if not already set */ |
| if (!pl_isset(&dom)) { |
| if (0 == re_regex(line, len, "domain [^ ]+", &dom)) { |
| (void)pl_strcpy(&dom, domain, dsize); |
| } |
| |
| if (0 == re_regex(line, len, "search [^ ]+", &dom)) { |
| (void)pl_strcpy(&dom, domain, dsize); |
| } |
| } |
| |
| /* Use the first entry */ |
| if (i < *n && 0 == re_regex(line, len, "nameserver [^\n]+", |
| &srv)) { |
| err = sa_set(&srvv[i], &srv, DNS_PORT); |
| if (err) { |
| DEBUG_WARNING("sa_set: %r (%m)\n", &srv, err); |
| } |
| ++i; |
| } |
| } |
| |
| *n = i; |
| |
| (void)fclose(f); |
| |
| return err; |
| } |
| |
| |
| #ifdef __ANDROID__ |
| static int get_android_dns(struct sa *nsv, uint32_t *n) |
| { |
| char prop[PROP_NAME_MAX] = {0}, value[PROP_VALUE_MAX] = {0}; |
| uint32_t i, count = 0; |
| int err; |
| |
| for (i=0; i<*n; i++) { |
| re_snprintf(prop, sizeof(prop), "net.dns%u", 1+i); |
| |
| if (__system_property_get(prop, value)) { |
| |
| err = sa_set_str(&nsv[count], value, DNS_PORT); |
| if (!err) |
| ++count; |
| } |
| } |
| if (count == 0) |
| return ENOENT; |
| |
| *n = count; |
| |
| return 0; |
| } |
| #endif |
| |
| |
| /** |
| * Get the DNS domain and nameservers |
| * |
| * @param domain Returned domain name |
| * @param dsize Size of domain name buffer |
| * @param srvv Returned nameservers |
| * @param n Nameservers capacity, actual on return |
| * |
| * @return 0 if success, otherwise errorcode |
| */ |
| int dns_srv_get(char *domain, size_t dsize, struct sa *srvv, uint32_t *n) |
| { |
| int err; |
| |
| /* Try them all in prioritized order */ |
| |
| #ifdef HAVE_RESOLV |
| err = get_resolv_dns(domain, dsize, srvv, n); |
| if (!err) |
| return 0; |
| #endif |
| |
| #ifdef DARWIN |
| err = get_darwin_dns(domain, dsize, srvv, n); |
| if (!err) |
| return 0; |
| #endif |
| |
| err = parse_resolv_conf(domain, dsize, srvv, n); |
| if (!err) |
| return 0; |
| |
| #ifdef WIN32 |
| err = get_windns(domain, dsize, srvv, n); |
| #endif |
| |
| #ifdef __ANDROID__ |
| err = get_android_dns(srvv, n); |
| #endif |
| |
| return err; |
| } |