1 /**
2  * @file src/net.c Networking code
3  *
4  * Copyright (C) 2010 - 2016 Creytiv.com
5  */
6 #include <re.h>
7 #include <baresip.h>
8 #include "core.h"
9 
10 
11 struct network {
12 	struct config_net cfg;
13 	struct sa laddr;
14 	char ifname[16];
15 #ifdef HAVE_INET6
16 	struct sa laddr6;
17 	char ifname6[16];
18 #endif
19 	struct tmr tmr;
20 	struct dnsc *dnsc;
21 	struct sa nsv[NET_MAX_NS];/**< Configured name servers      */
22 	uint32_t nsn;        /**< Number of configured name servers */
23 	uint32_t interval;
24 	int af;              /**< Preferred address family          */
25 	char domain[64];     /**< DNS domain from network           */
26 	net_change_h *ch;
27 	void *arg;
28 };
29 
30 
net_dnssrv_add(struct network * net,const struct sa * sa)31 static int net_dnssrv_add(struct network *net, const struct sa *sa)
32 {
33 	if (!net)
34 		return EINVAL;
35 
36 	if (net->nsn >= ARRAY_SIZE(net->nsv))
37 		return E2BIG;
38 
39 	sa_cpy(&net->nsv[net->nsn++], sa);
40 
41 	return 0;
42 }
43 
44 
net_dns_srv_get(const struct network * net,struct sa * srvv,uint32_t * n,bool * from_sys)45 static int net_dns_srv_get(const struct network *net,
46 			   struct sa *srvv, uint32_t *n, bool *from_sys)
47 {
48 	struct sa nsv[NET_MAX_NS];
49 	uint32_t i, nsn = ARRAY_SIZE(nsv);
50 	int err;
51 
52 	err = dns_srv_get(NULL, 0, nsv, &nsn);
53 	if (err) {
54 		nsn = 0;
55 	}
56 
57 	if (net->nsn) {
58 
59 		if (net->nsn > *n)
60 			return E2BIG;
61 
62 		/* Use any configured nameservers */
63 		for (i=0; i<net->nsn; i++) {
64 			srvv[i] = net->nsv[i];
65 		}
66 
67 		*n = net->nsn;
68 
69 		if (from_sys)
70 			*from_sys = false;
71 	}
72 	else {
73 		if (nsn > *n)
74 			return E2BIG;
75 
76 		for (i=0; i<nsn; i++)
77 			srvv[i] = nsv[i];
78 
79 		*n = nsn;
80 
81 		if (from_sys)
82 			*from_sys = true;
83 	}
84 
85 	return 0;
86 }
87 
88 
89 /**
90  * Check for DNS Server updates
91  */
dns_refresh(struct network * net)92 static void dns_refresh(struct network *net)
93 {
94 	struct sa nsv[NET_MAX_NS];
95 	uint32_t nsn;
96 	int err;
97 
98 	nsn = ARRAY_SIZE(nsv);
99 
100 	err = net_dns_srv_get(net, nsv, &nsn, NULL);
101 	if (err)
102 		return;
103 
104 	(void)dnsc_srv_set(net->dnsc, nsv, nsn);
105 }
106 
107 
108 /**
109  * Detect changes in IP address(es)
110  */
ipchange_handler(void * arg)111 static void ipchange_handler(void *arg)
112 {
113 	struct network *net = arg;
114 	bool change;
115 
116 	tmr_start(&net->tmr, net->interval * 1000, ipchange_handler, net);
117 
118 	dns_refresh(net);
119 
120 	change = net_check(net);
121 	if (change && net->ch) {
122 		net->ch(net->arg);
123 	}
124 }
125 
126 
127 /**
128  * Check if local IP address(es) changed
129  *
130  * @param net Network instance
131  *
132  * @return True if changed, otherwise false
133  */
net_check(struct network * net)134 bool net_check(struct network *net)
135 {
136 	struct sa laddr = net->laddr;
137 #ifdef HAVE_INET6
138 	struct sa laddr6 = net->laddr6;
139 #endif
140 	bool change = false;
141 
142 	if (!net)
143 		return false;
144 
145 	if (str_isset(net->cfg.ifname)) {
146 
147 		(void)net_if_getaddr(net->cfg.ifname, AF_INET, &net->laddr);
148 
149 #ifdef HAVE_INET6
150 		(void)net_if_getaddr(net->cfg.ifname, AF_INET6, &net->laddr6);
151 #endif
152 	}
153 	else {
154 		(void)net_default_source_addr_get(AF_INET, &net->laddr);
155 		(void)net_rt_default_get(AF_INET, net->ifname,
156 					 sizeof(net->ifname));
157 
158 #ifdef HAVE_INET6
159 		(void)net_default_source_addr_get(AF_INET6, &net->laddr6);
160 		(void)net_rt_default_get(AF_INET6, net->ifname6,
161 					 sizeof(net->ifname6));
162 #endif
163 	}
164 
165 	if (sa_isset(&net->laddr, SA_ADDR) &&
166 	    !sa_cmp(&laddr, &net->laddr, SA_ADDR)) {
167 		change = true;
168 		info("net: local IPv4 address changed: %j -> %j\n",
169 		     &laddr, &net->laddr);
170 	}
171 
172 #ifdef HAVE_INET6
173 	if (sa_isset(&net->laddr6, SA_ADDR) &&
174 	    !sa_cmp(&laddr6, &net->laddr6, SA_ADDR)) {
175 		change = true;
176 		info("net: local IPv6 address changed: %j -> %j\n",
177 		     &laddr6, &net->laddr6);
178 	}
179 #endif
180 
181 	return change;
182 }
183 
184 
dns_init(struct network * net)185 static int dns_init(struct network *net)
186 {
187 	struct sa nsv[NET_MAX_NS];
188 	uint32_t nsn = ARRAY_SIZE(nsv);
189 	int err;
190 
191 	err = net_dns_srv_get(net, nsv, &nsn, NULL);
192 	if (err)
193 		return err;
194 
195 	return dnsc_alloc(&net->dnsc, NULL, nsv, nsn);
196 }
197 
198 
199 /**
200  * Return TRUE if libre supports IPv6
201  */
check_ipv6(void)202 static bool check_ipv6(void)
203 {
204 	struct sa sa;
205 
206 	return 0 == sa_set_str(&sa, "::1", 2000);
207 }
208 
209 
net_destructor(void * data)210 static void net_destructor(void *data)
211 {
212 	struct network *net = data;
213 
214 	tmr_cancel(&net->tmr);
215 	mem_deref(net->dnsc);
216 }
217 
218 
219 /**
220  * Initialise networking
221  *
222  * @param netp Pointer to allocated network instance
223  * @param cfg  Network configuration
224  * @param af   Preferred address family
225  *
226  * @return 0 if success, otherwise errorcode
227  */
net_alloc(struct network ** netp,const struct config_net * cfg,int af)228 int net_alloc(struct network **netp, const struct config_net *cfg, int af)
229 {
230 	struct network *net;
231 	struct sa nsv[NET_MAX_NS];
232 	uint32_t nsn = ARRAY_SIZE(nsv);
233 	char buf4[128] = "", buf6[128] = "";
234 	int err;
235 
236 	if (!netp || !cfg)
237 		return EINVAL;
238 
239 	/*
240 	 * baresip/libre must be built with matching HAVE_INET6 value.
241 	 * if different the size of `struct sa' will not match and the
242 	 * application is very likely to crash.
243 	 */
244 #ifdef HAVE_INET6
245 	if (!check_ipv6()) {
246 		error_msg("libre was compiled without IPv6-support"
247 		      ", but baresip was compiled with\n");
248 		return EAFNOSUPPORT;
249 	}
250 #else
251 	if (check_ipv6()) {
252 		error_msg("libre was compiled with IPv6-support"
253 		      ", but baresip was compiled without\n");
254 		return EAFNOSUPPORT;
255 	}
256 #endif
257 
258 	net = mem_zalloc(sizeof(*net), net_destructor);
259 	if (!net)
260 		return ENOMEM;
261 
262 	net->cfg = *cfg;
263 	net->af  = af;
264 
265 	tmr_init(&net->tmr);
266 
267 	if (cfg->nsc) {
268 		size_t i;
269 
270 		for (i=0; i<cfg->nsc; i++) {
271 
272 			const char *ns = cfg->nsv[i].addr;
273 			struct sa sa;
274 
275 			err = sa_decode(&sa, ns, str_len(ns));
276 			if (err) {
277 				warning("net: dns_server:"
278 					" could not decode `%s' (%m)\n",
279 					ns, err);
280 				goto out;
281 			}
282 
283 			err = net_dnssrv_add(net, &sa);
284 			if (err) {
285 				warning("net: failed to add nameserver: %m\n",
286 					err);
287 				goto out;
288 			}
289 		}
290 	}
291 
292 	/* Initialise DNS resolver */
293 	err = dns_init(net);
294 	if (err) {
295 		warning("net: dns_init: %m\n", err);
296 		goto out;
297 	}
298 
299 	sa_init(&net->laddr, AF_INET);
300 	(void)sa_set_str(&net->laddr, "127.0.0.1", 0);
301 
302 	if (str_isset(cfg->ifname)) {
303 
304 		bool got_it = false;
305 
306 		info("Binding to interface '%s'\n", cfg->ifname);
307 
308 		str_ncpy(net->ifname, cfg->ifname, sizeof(net->ifname));
309 
310 		err = net_if_getaddr(cfg->ifname,
311 				     AF_INET, &net->laddr);
312 		if (err) {
313 			info("net: %s: could not get IPv4 address (%m)\n",
314 			     cfg->ifname, err);
315 		}
316 		else
317 			got_it = true;
318 
319 #ifdef HAVE_INET6
320 		str_ncpy(net->ifname6, cfg->ifname,
321 			 sizeof(net->ifname6));
322 
323 		err = net_if_getaddr(cfg->ifname,
324 				     AF_INET6, &net->laddr6);
325 		if (err) {
326 			info("net: %s: could not get IPv6 address (%m)\n",
327 			     cfg->ifname, err);
328 		}
329 		else
330 			got_it = true;
331 #endif
332 		if (got_it)
333 			err = 0;
334 		else {
335 			warning("net: %s: could not get network address\n",
336 				cfg->ifname);
337 			err = EADDRNOTAVAIL;
338 			goto out;
339 		}
340 	}
341 	else {
342 		(void)net_default_source_addr_get(AF_INET, &net->laddr);
343 		(void)net_rt_default_get(AF_INET, net->ifname,
344 					 sizeof(net->ifname));
345 
346 #ifdef HAVE_INET6
347 		sa_init(&net->laddr6, AF_INET6);
348 
349 		(void)net_default_source_addr_get(AF_INET6, &net->laddr6);
350 		(void)net_rt_default_get(AF_INET6, net->ifname6,
351 					 sizeof(net->ifname6));
352 #endif
353 	}
354 
355 	if (sa_isset(&net->laddr, SA_ADDR)) {
356 		re_snprintf(buf4, sizeof(buf4), " IPv4=%s:%j",
357 			    net->ifname, &net->laddr);
358 	}
359 #ifdef HAVE_INET6
360 	if (sa_isset(&net->laddr6, SA_ADDR)) {
361 		re_snprintf(buf6, sizeof(buf6), " IPv6=%s:%j",
362 			    net->ifname6, &net->laddr6);
363 	}
364 #endif
365 
366 	(void)dns_srv_get(net->domain, sizeof(net->domain), nsv, &nsn);
367 
368 	info("Local network address: %s %s\n",
369 	     buf4, buf6);
370 
371  out:
372 	if (err)
373 		mem_deref(net);
374 	else
375 		*netp = net;
376 
377 	return err;
378 }
379 
380 
381 /**
382  * Use a specific DNS server
383  *
384  * @param net Network instance
385  * @param ns  DNS Server IP address and port
386  *
387  * @return 0 if success, otherwise errorcode
388  */
net_use_nameserver(struct network * net,const struct sa * ns)389 int net_use_nameserver(struct network *net, const struct sa *ns)
390 {
391 	struct dnsc *dnsc;
392 	int err;
393 
394 	if (!net || !ns)
395 		return EINVAL;
396 
397 	err = dnsc_alloc(&dnsc, NULL, ns, 1);
398 	if (err)
399 		return err;
400 
401 	mem_deref(net->dnsc);
402 	net->dnsc = dnsc;
403 
404 	return 0;
405 }
406 
407 
408 /**
409  * Check for networking changes with a regular interval
410  *
411  * @param net       Network instance
412  * @param interval  Interval in seconds
413  * @param ch        Handler called when a change was detected
414  * @param arg       Handler argument
415  */
net_change(struct network * net,uint32_t interval,net_change_h * ch,void * arg)416 void net_change(struct network *net, uint32_t interval,
417 		net_change_h *ch, void *arg)
418 {
419 	if (!net)
420 		return;
421 
422 	net->interval = interval;
423 	net->ch = ch;
424 	net->arg = arg;
425 
426 	if (interval)
427 		tmr_start(&net->tmr, interval * 1000, ipchange_handler, net);
428 	else
429 		tmr_cancel(&net->tmr);
430 }
431 
432 
net_force_change(struct network * net)433 void net_force_change(struct network *net)
434 {
435 	if (net && net->ch) {
436 		net->ch(net->arg);
437 	}
438 }
439 
440 
dns_debug(struct re_printf * pf,const struct network * net)441 static int dns_debug(struct re_printf *pf, const struct network *net)
442 {
443 	struct sa nsv[NET_MAX_NS];
444 	uint32_t i, nsn = ARRAY_SIZE(nsv);
445 	bool from_sys = false;
446 	int err;
447 
448 	if (!net)
449 		return 0;
450 
451 	err = net_dns_srv_get(net, nsv, &nsn, &from_sys);
452 	if (err)
453 		nsn = 0;
454 
455 	err = re_hprintf(pf, " DNS Servers from %s: (%u)\n",
456 			 from_sys ? "System" : "Config", nsn);
457 	for (i=0; i<nsn; i++)
458 		err |= re_hprintf(pf, "   %u: %J\n", i, &nsv[i]);
459 
460 	return err;
461 }
462 
463 
net_af(const struct network * net)464 int net_af(const struct network *net)
465 {
466 	if (!net)
467 		return AF_UNSPEC;
468 
469 	return net->af;
470 }
471 
472 
473 /**
474  * Print networking debug information
475  *
476  * @param pf     Print handler for debug output
477  * @param net    Network instance
478  *
479  * @return 0 if success, otherwise errorcode
480  */
net_debug(struct re_printf * pf,const struct network * net)481 int net_debug(struct re_printf *pf, const struct network *net)
482 {
483 	int err;
484 
485 	if (!net)
486 		return 0;
487 
488 	err  = re_hprintf(pf, "--- Network debug ---\n");
489 	err |= re_hprintf(pf, " Preferred AF:  %s\n", net_af2name(net->af));
490 	err |= re_hprintf(pf, " Local IPv4: %9s - %j\n",
491 			  net->ifname, &net->laddr);
492 #ifdef HAVE_INET6
493 	err |= re_hprintf(pf, " Local IPv6: %9s - %j\n",
494 			  net->ifname6, &net->laddr6);
495 #endif
496 	err |= re_hprintf(pf, " Domain: %s\n", net->domain);
497 
498 	err |= net_if_debug(pf, NULL);
499 
500 	err |= net_rt_debug(pf, NULL);
501 
502 	err |= dns_debug(pf, net);
503 
504 	return err;
505 }
506 
507 
508 /**
509  * Get the local IP Address for a specific Address Family (AF)
510  *
511  * @param net Network instance
512  * @param af  Address Family
513  *
514  * @return Local IP Address
515  */
net_laddr_af(const struct network * net,int af)516 const struct sa *net_laddr_af(const struct network *net, int af)
517 {
518 	if (!net)
519 		return NULL;
520 
521 	switch (af) {
522 
523 	case AF_INET:  return &net->laddr;
524 #ifdef HAVE_INET6
525 	case AF_INET6: return &net->laddr6;
526 #endif
527 	default:       return NULL;
528 	}
529 }
530 
531 
532 /**
533  * Get the DNS Client
534  *
535  * @param net Network instance
536  *
537  * @return DNS Client
538  */
net_dnsc(const struct network * net)539 struct dnsc *net_dnsc(const struct network *net)
540 {
541 	if (!net)
542 		return NULL;
543 
544 	return net->dnsc;
545 }
546 
547 
548 /**
549  * Get the network domain name
550  *
551  * @param net Network instance
552  *
553  * @return Network domain
554  */
net_domain(const struct network * net)555 const char *net_domain(const struct network *net)
556 {
557 	if (!net)
558 		return NULL;
559 
560 	return net->domain[0] ? net->domain : NULL;
561 }
562