blob: aac713db83b4ede313872da63a69a3f8dd26688f [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file ns.c DNS Nameserver configuration
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <stdio.h>
7#include <re_types.h>
8#include <re_fmt.h>
9#include <re_mbuf.h>
10#include <re_list.h>
11#include <re_sa.h>
12#include <re_dns.h>
13#include "dns.h"
14#ifdef __ANDROID__
15#include <sys/system_properties.h>
16#endif
17
18
19#define DEBUG_MODULE "ns"
20#define DEBUG_LEVEL 5
21#include <re_dbg.h>
22
23
24static int parse_resolv_conf(char *domain, size_t dsize,
25 struct sa *srvv, uint32_t *n)
26{
27 FILE *f;
28 struct pl dom = pl_null;
29 uint32_t i = 0;
30 int err = 0;
31
32 if (!srvv || !n || !*n)
33 return EINVAL;
34
35 f = fopen("/etc/resolv.conf", "r");
36 if (!f)
37 return errno;
38
39 for (;;) {
40 char line[128];
41 struct pl srv;
42 size_t len;
43
44 if (1 != fscanf(f, "%127[^\n]\n", line))
45 break;
46
47 if ('#' == line[0])
48 continue;
49
50 len = str_len(line);
51
52 /* Set domain if not already set */
53 if (!pl_isset(&dom)) {
54 if (0 == re_regex(line, len, "domain [^ ]+", &dom)) {
55 (void)pl_strcpy(&dom, domain, dsize);
56 }
57
58 if (0 == re_regex(line, len, "search [^ ]+", &dom)) {
59 (void)pl_strcpy(&dom, domain, dsize);
60 }
61 }
62
63 /* Use the first entry */
64 if (i < *n && 0 == re_regex(line, len, "nameserver [^\n]+",
65 &srv)) {
66 err = sa_set(&srvv[i], &srv, DNS_PORT);
67 if (err) {
68 DEBUG_WARNING("sa_set: %r (%m)\n", &srv, err);
69 }
70 ++i;
71 }
72 }
73
74 *n = i;
75
76 (void)fclose(f);
77
78 return err;
79}
80
81
82#ifdef __ANDROID__
83static int get_android_dns(struct sa *nsv, uint32_t *n)
84{
85 char prop[PROP_NAME_MAX] = {0}, value[PROP_VALUE_MAX] = {0};
86 uint32_t i, count = 0;
87 int err;
88
89 for (i=0; i<*n; i++) {
90 re_snprintf(prop, sizeof(prop), "net.dns%u", 1+i);
91
92 if (__system_property_get(prop, value)) {
93
94 err = sa_set_str(&nsv[count], value, DNS_PORT);
95 if (!err)
96 ++count;
97 }
98 }
99 if (count == 0)
100 return ENOENT;
101
102 *n = count;
103
104 return 0;
105}
106#endif
107
108
109/**
110 * Get the DNS domain and nameservers
111 *
112 * @param domain Returned domain name
113 * @param dsize Size of domain name buffer
114 * @param srvv Returned nameservers
115 * @param n Nameservers capacity, actual on return
116 *
117 * @return 0 if success, otherwise errorcode
118 */
119int dns_srv_get(char *domain, size_t dsize, struct sa *srvv, uint32_t *n)
120{
121 int err;
122
123 /* Try them all in prioritized order */
124
125#ifdef HAVE_RESOLV
126 err = get_resolv_dns(domain, dsize, srvv, n);
127 if (!err)
128 return 0;
129#endif
130
131#ifdef DARWIN
132 err = get_darwin_dns(domain, dsize, srvv, n);
133 if (!err)
134 return 0;
135#endif
136
137 err = parse_resolv_conf(domain, dsize, srvv, n);
138 if (!err)
139 return 0;
140
141#ifdef WIN32
142 err = get_windns(domain, dsize, srvv, n);
143#endif
144
145#ifdef __ANDROID__
146 err = get_android_dns(srvv, n);
147#endif
148
149 return err;
150}