• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "lookup.h"
2 #include "stdio_impl.h"
3 #include <ctype.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <netinet/in.h>
8 
9 #include "hilog_adapter.h"
10 
11 #if 1
12 #define SIGCHAIN_LOG_DOMAIN 0xD003F00
13 #define SIGCHAIN_LOG_TAG "ressolvconf"
14 #define GETADDRINFO_PRINT_DEBUG(...) ((void)HiLogAdapterPrint(LOG_CORE, LOG_INFO, \
15 	SIGCHAIN_LOG_DOMAIN, SIGCHAIN_LOG_TAG, __VA_ARGS__))
16 #else
17 #define GETADDRINFO_PRINT_DEBUG(...)
18 #endif
19 
20 #define DNS_RESOLV_CONF_PATH "/etc/resolv.conf"
21 
22 #if OHOS_DNS_PROXY_BY_NETSYS | OHOS_FWMARK_CLIENT_BY_NETSYS
23 #include "atomic.h"
24 
25 #include <dlfcn.h>
26 
open_dns_lib(void)27 static void *open_dns_lib(void)
28 {
29 	static void *dns_lib_handle = NULL;
30 	if (dns_lib_handle != NULL) {
31 		a_barrier();
32 		return dns_lib_handle;
33 	}
34 
35 	void *lib = dlopen(DNS_SO_PATH, RTLD_LAZY);
36 	if (lib == NULL) {
37 		DNS_CONFIG_PRINT("%s: dlopen %s failed: %s",
38 			__func__, DNS_SO_PATH, dlerror());
39 		return NULL;
40 	}
41 
42 	void *old_lib = a_cas_p(&dns_lib_handle, NULL, lib);
43 	if (old_lib == NULL) {
44 		DNS_CONFIG_PRINT("%s: %s loaded", __func__, DNS_SO_PATH);
45 		return lib;
46 	} else {
47 		/* Another thread has already loaded the library,
48 		 * dlclose is invoked to make refcount correct */
49 		DNS_CONFIG_PRINT("%s: %s has been loaded by another thread",
50 			__func__, DNS_SO_PATH);
51 		if (dlclose(lib)) {
52 			DNS_CONFIG_PRINT("%s: dlclose %s failed: %s",
53 				__func__, DNS_SO_PATH, dlerror());
54 		}
55 		return old_lib;
56 	}
57 }
58 
load_from_dns_lib(const char * symbol)59 static void *load_from_dns_lib(const char *symbol)
60 {
61 	void *lib_handle = open_dns_lib();
62 	if (lib_handle == NULL) {
63 		return NULL;
64 	}
65 
66 	void *sym_addr = dlsym(lib_handle, symbol);
67 	if (sym_addr == NULL) {
68 		DNS_CONFIG_PRINT("%s: loading symbol %s with dlsym failed: %s",
69 			__func__, symbol, dlerror());
70 	}
71 	return sym_addr;
72 }
73 
resolve_dns_sym(void ** holder,const char * symbol)74 void resolve_dns_sym(void **holder, const char *symbol)
75 {
76 	if (*holder != NULL) {
77 		a_barrier();
78 		return;
79 	}
80 
81 	void *ptr = load_from_dns_lib(symbol);
82 	if (ptr == NULL) {
83 		return;
84 	}
85 
86 	void *old_ptr = a_cas_p(holder, NULL, ptr);
87 	if (old_ptr != NULL) {
88 		DNS_CONFIG_PRINT("%s: %s has been found by another thread",
89 			__func__, symbol);
90 	} else {
91 		DNS_CONFIG_PRINT("%s: %s found", __func__, symbol);
92 	}
93 }
94 
load_config_getter(void)95 static GetConfig load_config_getter(void)
96 {
97 	static GetConfig config_getter = NULL;
98 	resolve_dns_sym((void **) &config_getter, OHOS_GET_CONFIG_FUNC_NAME);
99 	return config_getter;
100 }
101 
102 #endif
103 
__get_resolv_conf(struct resolvconf * conf,char * search,size_t search_sz)104 int __get_resolv_conf(struct resolvconf *conf, char *search, size_t search_sz)
105 {
106        return get_resolv_conf_ext(conf, search, search_sz, 0);
107 }
108 
get_resolv_conf_ext(struct resolvconf * conf,char * search,size_t search_sz,int netid)109 int get_resolv_conf_ext(struct resolvconf *conf, char *search, size_t search_sz, int netid)
110 {
111 	char line[256];
112 	unsigned char _buf[256];
113 	FILE *f, _f;
114 	int nns = 0;
115 
116 	conf->ndots = 1;
117 	conf->timeout = 5;
118 	conf->attempts = 2;
119 #if OHOS_DNS_PROXY_BY_NETSYS
120     conf->non_public = 0;
121 #endif
122 	if (search) *search = 0;
123 
124 #if OHOS_DNS_PROXY_BY_NETSYS
125 	GetConfig func = load_config_getter();
126 	if (!func) {
127 		DNS_CONFIG_PRINT("%s: loading %s failed, use %s as a fallback",
128 			__func__, OHOS_GET_CONFIG_FUNC_NAME, DNS_RESOLV_CONF_PATH);
129 		goto etc_resolv_conf;
130 	}
131 
132 	struct resolv_config config = {0};
133 	int ret = func(netid, &config);
134 	if (ret < 0) {
135 		DNS_CONFIG_PRINT("__get_resolv_conf OHOS_GET_CONFIG_FUNC_NAME err %d\n", ret);
136 #ifndef __LITEOS__
137 		MUSL_LOGE("%{public}s: %{public}d: resolv_config return: %{public}d for netid %{public}d",
138 			__func__, __LINE__, ret, netid);
139 #endif
140 		return EAI_NONAME;
141 	}
142 	int32_t timeout_second = config.timeout_ms / 1000;
143 	if (timeout_second > 0) {
144 		if (timeout_second >= 60) {
145 			conf->timeout = 60;
146 		} else {
147 			conf->timeout = timeout_second;
148 		}
149 	}
150 	if (config.retry_count > 0) {
151 		if (config.retry_count >= 10) {
152 			conf->attempts = 10;
153 		} else {
154 			conf->attempts = config.retry_count;
155 		}
156 	}
157 	for (int i = 0; i < MAX_SERVER_NUM; ++i) {
158 		if (config.nameservers[i] == NULL || config.nameservers[i][0] == 0 || nns >= MAXNS) {
159 			continue;
160 		}
161 		if (__lookup_ipliteral(conf->ns + nns, config.nameservers[i], AF_UNSPEC) > 0) {
162 			nns++;
163 		}
164 	}
165     conf->non_public = config.non_public_num;
166 
167         if (nns != 0) {
168             goto get_conf_ok;
169         }
170 
171 etc_resolv_conf:
172 #endif
173 	f = __fopen_rb_ca(DNS_RESOLV_CONF_PATH, &_f, _buf, sizeof _buf);
174 	if (!f) switch (errno) {
175 	case ENOENT:
176 	case ENOTDIR:
177 	case EACCES:
178 		goto no_resolv_conf;
179 	default:
180 #ifndef __LITEOS__
181 		MUSL_LOGE("%{public}s: %{public}d: open resolv.conf failed with Unexpected errno: %{public}d",
182 			__func__, __LINE__, errno);
183 #endif
184 		return -1;
185 	}
186 
187 	while (fgets(line, sizeof line, f)) {
188 		char *p, *z;
189 		if (!strchr(line, '\n') && !feof(f)) {
190 			/* Ignore lines that get truncated rather than
191 			 * potentially misinterpreting them. */
192 			int c;
193 			do c = getc(f);
194 			while (c != '\n' && c != EOF);
195 			continue;
196 		}
197 		if (!strncmp(line, "options", 7) && isspace(line[7])) {
198 			p = strstr(line, "ndots:");
199 			if (p && isdigit(p[6])) {
200 				p += 6;
201 				unsigned long x = strtoul(p, &z, 10);
202 				if (z != p) conf->ndots = x > 15 ? 15 : x;
203 			}
204 			p = strstr(line, "attempts:");
205 			if (p && isdigit(p[9])) {
206 				p += 9;
207 				unsigned long x = strtoul(p, &z, 10);
208 				if (z != p) conf->attempts = x > 10 ? 10 : x;
209 			}
210 			p = strstr(line, "timeout:");
211 			if (p && (isdigit(p[8]) || p[8]=='.')) {
212 				p += 8;
213 				unsigned long x = strtoul(p, &z, 10);
214 				if (z != p) conf->timeout = x > 60 ? 60 : x;
215 			}
216 			continue;
217 		}
218 		if (!strncmp(line, "nameserver", 10) && isspace(line[10])) {
219 			if (nns >= MAXNS) continue;
220 			for (p=line+11; isspace(*p); p++);
221 			for (z=p; *z && !isspace(*z); z++);
222 			*z=0;
223 			if (__lookup_ipliteral(conf->ns+nns, p, AF_UNSPEC) > 0)
224 				nns++;
225 			continue;
226 		}
227 
228 		if (!search) continue;
229 		if ((strncmp(line, "domain", 6) && strncmp(line, "search", 6))
230 		    || !isspace(line[6]))
231 			continue;
232 		for (p=line+7; isspace(*p); p++);
233 		size_t l = strlen(p);
234 		/* This can never happen anyway with chosen buffer sizes. */
235 		if (l >= search_sz) continue;
236 		memcpy(search, p, l+1);
237 	}
238 
239 	__fclose_ca(f);
240 
241 no_resolv_conf:
242 	if (!nns) {
243 		__lookup_ipliteral(conf->ns, "127.0.0.1", AF_UNSPEC);
244 		nns = 1;
245 	}
246 
247 get_conf_ok:
248 	conf->nns = nns;
249 
250 	return 0;
251 }
252 
res_bind_socket(int fd,int netid)253 int res_bind_socket(int fd, int netid)
254 {
255 	int ret = -1;
256 	void* libhandler;
257 
258 	GETADDRINFO_PRINT_DEBUG("res_bind_socket netid:%{public}d \n", netid);
259 
260 #ifdef OHOS_FWMARK_CLIENT_BY_NETSYS
261 	libhandler = dlopen(FWMARKCLIENT_SO_PATH, RTLD_LAZY);
262 	if (libhandler == NULL) {
263 		GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache dlopen err %s\n", dlerror());
264 		return -1;
265 	}
266 
267 	BindSocket_Ext func = dlsym(libhandler, OHOS_BIND_SOCKET_FUNC_NAME);
268 	if (func == NULL) {
269 		GETADDRINFO_PRINT_DEBUG("dns_get_addr_info_from_netsys_cache dlsym err %s\n", dlerror());
270 		dlclose(libhandler);
271 		return -1;
272 	} else {
273 		ret = func(fd, netid);
274 		GETADDRINFO_PRINT_DEBUG("res_bind_socket ret %{public}d \n", ret);
275 		dlclose(libhandler);
276 	}
277 #endif
278 	return ret;
279 }
280 
281