blob: aac713db83b4ede313872da63a69a3f8dd26688f [file] [log] [blame]
/**
* @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;
}