1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include "private-lib-core.h"
26 #include <errno.h>
27 
28 #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE)
29 static int
interface_to_sa(struct lws_vhost * vh,const char * ifname,struct sockaddr_in * addr,size_t addrlen,int allow_ipv6)30 interface_to_sa(struct lws_vhost *vh, const char *ifname,
31 		struct sockaddr_in *addr, size_t addrlen, int allow_ipv6)
32 {
33 	int ipv6 = 0;
34 #ifdef LWS_WITH_IPV6
35 	if (allow_ipv6)
36 		ipv6 = LWS_IPV6_ENABLED(vh);
37 #endif
38 	(void)vh;
39 
40 	return lws_interface_to_sa(ipv6, ifname, addr, addrlen);
41 }
42 #endif
43 
44 #ifndef LWS_PLAT_OPTEE
45 static int
lws_get_addresses(struct lws_vhost * vh,void * ads,char * name,int name_len,char * rip,int rip_len)46 lws_get_addresses(struct lws_vhost *vh, void *ads, char *name,
47 		  int name_len, char *rip, int rip_len)
48 {
49 	struct addrinfo ai, *res;
50 	struct sockaddr_in addr4;
51 
52 	rip[0] = '\0';
53 	name[0] = '\0';
54 	addr4.sin_family = AF_UNSPEC;
55 
56 #ifdef LWS_WITH_IPV6
57 	if (LWS_IPV6_ENABLED(vh)) {
58 		if (!lws_plat_inet_ntop(AF_INET6,
59 					&((struct sockaddr_in6 *)ads)->sin6_addr,
60 					rip, (socklen_t)rip_len)) {
61 			lwsl_err("inet_ntop: %s", strerror(LWS_ERRNO));
62 			return -1;
63 		}
64 
65 		// Strip off the IPv4 to IPv6 header if one exists
66 		if (strncmp(rip, "::ffff:", 7) == 0)
67 			memmove(rip, rip + 7, strlen(rip) - 6);
68 
69 		getnameinfo((struct sockaddr *)ads, sizeof(struct sockaddr_in6),
70 			    name,
71 #if defined(__ANDROID__)
72 			    (size_t)name_len,
73 #else
74 			    (socklen_t)name_len,
75 #endif
76 			    NULL, 0, 0);
77 
78 		return 0;
79 	} else
80 #endif
81 	{
82 		struct addrinfo *result;
83 
84 		memset(&ai, 0, sizeof ai);
85 		ai.ai_family = PF_UNSPEC;
86 		ai.ai_socktype = SOCK_STREAM;
87 #if !defined(LWS_PLAT_FREERTOS)
88 		if (getnameinfo((struct sockaddr *)ads,
89 				sizeof(struct sockaddr_in),
90 				name,
91 #if defined(__ANDROID__)
92 				(size_t)name_len,
93 #else
94 				(socklen_t)name_len,
95 #endif
96 				NULL, 0, 0))
97 			return -1;
98 #endif
99 
100 		if (getaddrinfo(name, NULL, &ai, &result))
101 			return -1;
102 
103 		res = result;
104 		while (addr4.sin_family == AF_UNSPEC && res) {
105 			switch (res->ai_family) {
106 			case AF_INET:
107 				addr4.sin_addr =
108 				 ((struct sockaddr_in *)res->ai_addr)->sin_addr;
109 				addr4.sin_family = AF_INET;
110 				break;
111 			}
112 
113 			res = res->ai_next;
114 		}
115 		freeaddrinfo(result);
116 	}
117 
118 	if (addr4.sin_family == AF_UNSPEC)
119 		return -1;
120 
121 	if (lws_plat_inet_ntop(AF_INET, &addr4.sin_addr, rip,
122 			       (socklen_t)rip_len) == NULL)
123 		return -1;
124 
125 	return 0;
126 }
127 
128 const char *
lws_get_peer_simple_fd(lws_sockfd_type fd,char * name,size_t namelen)129 lws_get_peer_simple_fd(lws_sockfd_type fd, char *name, size_t namelen)
130 {
131 	lws_sockaddr46 sa46;
132 	socklen_t len = sizeof(sa46);
133 
134 	if (getpeername(fd, (struct sockaddr *)&sa46, &len) < 0) {
135 		lws_snprintf(name, namelen, "getpeername: %s",
136 				strerror(LWS_ERRNO));
137 		return name;
138 	}
139 
140 	lws_sa46_write_numeric_address(&sa46, name, namelen);
141 
142 	return name;
143 }
144 
145 const char *
lws_get_peer_simple(struct lws * wsi,char * name,size_t namelen)146 lws_get_peer_simple(struct lws *wsi, char *name, size_t namelen)
147 {
148 	wsi = lws_get_network_wsi(wsi);
149 	return lws_get_peer_simple_fd(wsi->desc.sockfd, name, namelen);
150 }
151 #endif
152 
153 void
lws_get_peer_addresses(struct lws * wsi,lws_sockfd_type fd,char * name,int name_len,char * rip,int rip_len)154 lws_get_peer_addresses(struct lws *wsi, lws_sockfd_type fd, char *name,
155 		       int name_len, char *rip, int rip_len)
156 {
157 #ifndef LWS_PLAT_OPTEE
158 	socklen_t len;
159 #ifdef LWS_WITH_IPV6
160 	struct sockaddr_in6 sin6;
161 #endif
162 	struct sockaddr_in sin4;
163 	void *p;
164 
165 	rip[0] = '\0';
166 	name[0] = '\0';
167 
168 #ifdef LWS_WITH_IPV6
169 	if (LWS_IPV6_ENABLED(wsi->a.vhost)) {
170 		len = sizeof(sin6);
171 		p = &sin6;
172 	} else
173 #endif
174 	{
175 		len = sizeof(sin4);
176 		p = &sin4;
177 	}
178 
179 	if (getpeername(fd, p, &len) < 0) {
180 		lwsl_warn("getpeername: %s\n", strerror(LWS_ERRNO));
181 		goto bail;
182 	}
183 
184 	lws_get_addresses(wsi->a.vhost, p, name, name_len, rip, rip_len);
185 
186 bail:
187 #endif
188 	(void)wsi;
189 	(void)fd;
190 	(void)name;
191 	(void)name_len;
192 	(void)rip;
193 	(void)rip_len;
194 }
195 
196 
197 
198 /* note: this returns a random port, or one of these <= 0 return codes:
199  *
200  * LWS_ITOSA_USABLE:     the interface is usable, returned if so and sockfd invalid
201  * LWS_ITOSA_NOT_EXIST:  the requested iface does not even exist
202  * LWS_ITOSA_NOT_USABLE: the requested iface exists but is not usable (eg, no IP)
203  * LWS_ITOSA_BUSY:       the port at the requested iface + port is already in use
204  */
205 
206 int
lws_socket_bind(struct lws_vhost * vhost,struct lws * wsi,lws_sockfd_type sockfd,int port,const char * iface,int ipv6_allowed)207 lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi,
208 		lws_sockfd_type sockfd, int port, const char *iface,
209 		int ipv6_allowed)
210 {
211 #ifdef LWS_WITH_UNIX_SOCK
212 	struct sockaddr_un serv_unix;
213 #endif
214 #ifdef LWS_WITH_IPV6
215 	struct sockaddr_in6 serv_addr6;
216 #endif
217 	struct sockaddr_in serv_addr4;
218 #ifndef LWS_PLAT_OPTEE
219 	socklen_t len = sizeof(struct sockaddr_storage);
220 #endif
221 	int n;
222 #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE)
223 	int m;
224 #endif
225 	struct sockaddr_storage sin, *psin = &sin;
226 	struct sockaddr *v;
227 
228 	memset(&sin, 0, sizeof(sin));
229 
230 	/* if there's a wsi, we want to mark it with our source ads:port */
231 	if (wsi)
232 		psin = (struct sockaddr_storage *)&wsi->sa46_local;
233 
234 #if defined(LWS_WITH_UNIX_SOCK)
235 	if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) {
236 		v = (struct sockaddr *)&serv_unix;
237 		memset(&serv_unix, 0, sizeof(serv_unix));
238 		serv_unix.sun_family = AF_UNIX;
239 		if (!iface)
240 			return LWS_ITOSA_NOT_EXIST;
241 		if (sizeof(serv_unix.sun_path) <= strlen(iface)) {
242 			lwsl_err("\"%s\" too long for UNIX domain socket\n",
243 			         iface);
244 			return LWS_ITOSA_NOT_EXIST;
245 		}
246 		n = (int)(sizeof(uint16_t) + strlen(iface));
247 		strcpy(serv_unix.sun_path, iface);
248 		if (serv_unix.sun_path[0] == '@')
249 			serv_unix.sun_path[0] = '\0';
250 		else
251 			unlink(serv_unix.sun_path);
252 
253 		// lwsl_hexdump_notice(v, n);
254 
255 	} else
256 #endif
257 #if defined(LWS_WITH_IPV6) && !defined(LWS_PLAT_FREERTOS)
258 	if (ipv6_allowed && LWS_IPV6_ENABLED(vhost)) {
259 		v = (struct sockaddr *)&serv_addr6;
260 		n = sizeof(struct sockaddr_in6);
261 		memset(&serv_addr6, 0, sizeof(serv_addr6));
262 		if (iface) {
263 			m = interface_to_sa(vhost, iface,
264 				    (struct sockaddr_in *)v, (unsigned int)n, 1);
265 			if (m == LWS_ITOSA_NOT_USABLE) {
266 				lwsl_info("%s: netif %s: Not usable\n",
267 					 __func__, iface);
268 				return m;
269 			}
270 			if (m == LWS_ITOSA_NOT_EXIST) {
271 				lwsl_info("%s: netif %s: Does not exist\n",
272 					 __func__, iface);
273 				return m;
274 			}
275 			if (serv_addr6.sin6_family == AF_INET6)
276 				serv_addr6.sin6_scope_id = (unsigned int)htonl((uint32_t)
277 						lws_get_addr_scope(iface));
278 		} else
279 			serv_addr6.sin6_family = AF_INET6;
280 
281 		if (serv_addr6.sin6_family == AF_INET6)
282 			serv_addr6.sin6_port = (uint16_t)htons((uint16_t)port);
283 		else
284 			((struct sockaddr_in *)v)->sin_port = (uint16_t)htons((uint16_t)port);
285 	} else
286 #endif
287 	{
288 		v = (struct sockaddr *)&serv_addr4;
289 		n = sizeof(serv_addr4);
290 		memset(&serv_addr4, 0, sizeof(serv_addr4));
291 		serv_addr4.sin_addr.s_addr = INADDR_ANY;
292 		serv_addr4.sin_family = AF_INET;
293 
294 #if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE)
295 		if (iface) {
296 		    m = interface_to_sa(vhost, iface,
297 				    (struct sockaddr_in *)v, (unsigned int)n, 0);
298 			if (m == LWS_ITOSA_NOT_USABLE) {
299 				lwsl_info("%s: netif %s: Not usable\n",
300 					 __func__, iface);
301 				return m;
302 			}
303 			if (m == LWS_ITOSA_NOT_EXIST) {
304 				lwsl_info("%s: netif %s: Does not exist\n",
305 					 __func__, iface);
306 				return m;
307 			}
308 		}
309 #endif
310 		serv_addr4.sin_port = htons((uint16_t)(unsigned int)port);
311 	} /* ipv4 */
312 
313 	/* just checking for the interface extant */
314 	if (sockfd == LWS_SOCK_INVALID)
315 		return LWS_ITOSA_USABLE;
316 
317 	n = bind(sockfd, v, (socklen_t)n);
318 #ifdef LWS_WITH_UNIX_SOCK
319 	if (n < 0 && LWS_UNIX_SOCK_ENABLED(vhost)) {
320 		lwsl_err("ERROR on binding fd %d to \"%s\" (%d %d)\n",
321 			 sockfd, iface, n, LWS_ERRNO);
322 		return LWS_ITOSA_NOT_EXIST;
323 	} else
324 #endif
325 	if (n < 0) {
326 		int _lws_errno = LWS_ERRNO;
327 
328 		lwsl_err("ERROR on binding fd %d to port %d (%d %d)\n",
329 			 sockfd, port, n, _lws_errno);
330 
331 		/* if something already listening, tell caller to fail permanently */
332 
333 		if (_lws_errno == LWS_EADDRINUSE)
334 			return LWS_ITOSA_BUSY;
335 
336 		/* otherwise ask caller to retry later */
337 
338 		return LWS_ITOSA_NOT_EXIST;
339 	}
340 
341 #if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32)
342 	if (!port && LWS_UNIX_SOCK_ENABLED(vhost)) {
343 		uid_t uid = vhost->context->uid;
344 		gid_t gid = vhost->context->gid;
345 
346 		if (vhost->unix_socket_perms) {
347 			if (lws_plat_user_colon_group_to_ids(
348 				vhost->unix_socket_perms, &uid, &gid)) {
349 				lwsl_err("%s: Failed to translate %s\n",
350 					  __func__, vhost->unix_socket_perms);
351 				return LWS_ITOSA_NOT_EXIST;
352 			}
353 		}
354 		if (iface && iface[0] != '@' && uid && gid) {
355 			if (chown(iface, uid, gid)) {
356 				lwsl_err("%s: failed to set %s perms %u:%u\n",
357 					 __func__, iface,
358 					 (unsigned int)uid, (unsigned int)gid);
359 
360 				return LWS_ITOSA_NOT_EXIST;
361 			}
362 			lwsl_notice("%s: vh %s unix skt %s perms %u:%u\n",
363 				    __func__, vhost->name, iface,
364 				    (unsigned int)uid, (unsigned int)gid);
365 
366 			if (chmod(iface, 0660)) {
367 				lwsl_err("%s: failed to set %s to 0600 mode\n",
368 					 __func__, iface);
369 
370 				return LWS_ITOSA_NOT_EXIST;
371 			}
372 		}
373 	}
374 #endif
375 
376 #ifndef LWS_PLAT_OPTEE
377 	if (getsockname(sockfd, (struct sockaddr *)psin, &len) == -1)
378 		lwsl_warn("getsockname: %s\n", strerror(LWS_ERRNO));
379 	else
380 #endif
381 #if defined(LWS_WITH_IPV6)
382 		port = (sin.ss_family == AF_INET6) ?
383 			ntohs(((struct sockaddr_in6 *)psin)->sin6_port) :
384 			ntohs(((struct sockaddr_in *)psin)->sin_port);
385 #else
386 		{
387 			struct sockaddr_in sain;
388 			memcpy(&sain, psin, sizeof(sain));
389 			port = ntohs(sain.sin_port);
390 		}
391 #endif
392 
393 		{
394 			char buf[72];
395 			lws_sa46_write_numeric_address((lws_sockaddr46 *)psin,
396 							buf, sizeof(buf));
397 
398 			lwsl_notice("%s: %s: source ads %s\n", __func__,
399 					wsi ? wsi->lc.gutag : "nowsi", buf);
400 		}
401 
402 	return port;
403 }
404 
405 #if defined(LWS_WITH_CLIENT)
406 
407 unsigned int
lws_retry_get_delay_ms(struct lws_context * context,const lws_retry_bo_t * retry,uint16_t * ctry,char * conceal)408 lws_retry_get_delay_ms(struct lws_context *context,
409 		       const lws_retry_bo_t *retry, uint16_t *ctry,
410 		       char *conceal)
411 {
412 	uint64_t ms = 3000, pc = 30; /* sane-ish defaults if no retry table */
413 	uint16_t ra;
414 
415 	if (conceal)
416 		*conceal = 0;
417 
418 	if (retry) {
419 		if (*ctry < retry->retry_ms_table_count)
420 			ms = retry->retry_ms_table[*ctry];
421 		else
422 			ms = retry->retry_ms_table[
423 				retry->retry_ms_table_count - 1];
424 
425 		/* if no percent given, use the default 30% */
426 		if (retry->jitter_percent)
427 			pc = retry->jitter_percent;
428 	}
429 
430 	if (lws_get_random(context, &ra, sizeof(ra)) == sizeof(ra))
431 		ms += ((ms * pc * ra) >> 16) / 100;
432 	else
433 		assert(0);
434 
435 	if (*ctry < 0xffff)
436 		(*ctry)++;
437 
438 	if (retry && conceal)
439 		*conceal = (int)*ctry <= retry->conceal_count;
440 
441 	return (unsigned int)ms;
442 }
443 
444 int
lws_retry_sul_schedule(struct lws_context * context,int tid,lws_sorted_usec_list_t * sul,const lws_retry_bo_t * retry,sul_cb_t cb,uint16_t * ctry)445 lws_retry_sul_schedule(struct lws_context *context, int tid,
446 		       lws_sorted_usec_list_t *sul,
447 		       const lws_retry_bo_t *retry, sul_cb_t cb, uint16_t *ctry)
448 {
449 	char conceal;
450 	uint64_t ms = lws_retry_get_delay_ms(context, retry, ctry, &conceal);
451 
452 	if (!conceal)
453 		return 1;
454 
455 	lwsl_info("%s: sul %p: scheduling retry in %dms\n", __func__, sul,
456 			(int)ms);
457 
458 	lws_sul_schedule(context, tid, sul, cb, (int64_t)(ms * 1000));
459 
460 	return 0;
461 }
462 
463 int
lws_retry_sul_schedule_retry_wsi(struct lws * wsi,lws_sorted_usec_list_t * sul,sul_cb_t cb,uint16_t * ctry)464 lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul,
465 				 sul_cb_t cb, uint16_t *ctry)
466 {
467 	char conceal;
468 	lws_usec_t us = lws_retry_get_delay_ms(wsi->a.context,
469 					       wsi->retry_policy, ctry,
470 					       &conceal) * LWS_US_PER_MS;
471 
472 	if (!conceal)
473 		/* if our reties are up, they're up... */
474 		return 1;
475 
476 #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
477 	if (
478 #if defined(LWS_ROLE_H1)
479 		wsi->role_ops == &role_ops_h1
480 #endif
481 #if defined(LWS_ROLE_H1) && defined(LWS_ROLE_H2)
482 		||
483 #endif
484 #if defined(LWS_ROLE_H2)
485 		wsi->role_ops == &role_ops_h2
486 #endif
487 		)
488 		/*
489 		 * Since we're doing it by wsi, we're in a position to check for
490 		 * http retry-after, it will increase us accordingly if found
491 		 */
492 		lws_http_check_retry_after(wsi, &us);
493 #endif
494 	lws_sul_schedule(wsi->a.context, wsi->tsi, sul, cb, us);
495 
496 	return 0;
497 }
498 
499 #endif
500 
501 #if defined(LWS_WITH_IPV6)
502 unsigned long
lws_get_addr_scope(const char * ifname_or_ipaddr)503 lws_get_addr_scope(const char *ifname_or_ipaddr)
504 {
505 	unsigned long scope;
506 	char ip[NI_MAXHOST];
507 	unsigned int i;
508 #if !defined(WIN32)
509 	struct ifaddrs *addrs, *addr;
510 #else
511 	PIP_ADAPTER_ADDRESSES adapter, addrs = NULL;
512 	PIP_ADAPTER_UNICAST_ADDRESS addr;
513 	struct sockaddr_in6 *sockaddr;
514 	ULONG size = 0;
515 	int found = 0;
516 	DWORD ret;
517 #endif
518 
519 	/*
520 	 * First see if we can look the string up as a network interface name...
521 	 * windows vista+ also has this
522 	 */
523 
524 	scope = if_nametoindex(ifname_or_ipaddr);
525 	if (scope > 0)
526 		/* we found it from the interface name lookup */
527 		return scope;
528 
529 	/*
530 	 * if not, try to look it up as an IP -> interface -> interface index
531 	 */
532 
533 	scope = 0;
534 
535 #if !defined(WIN32)
536 
537 	getifaddrs(&addrs);
538 	for (addr = addrs; addr; addr = addr->ifa_next) {
539 		if (!addr->ifa_addr ||
540 			addr->ifa_addr->sa_family != AF_INET6)
541 			continue;
542 
543 		ip[0] = '\0';
544 		getnameinfo(addr->ifa_addr,
545 				sizeof(struct sockaddr_in6),
546 				ip, sizeof(ip),
547 				NULL, 0, NI_NUMERICHOST);
548 
549 		i = 0;
550 		while (ip[i])
551 			if (ip[i++] == '%') {
552 				ip[i - 1] = '\0';
553 				break;
554 			}
555 
556 		if (!strcmp(ip, ifname_or_ipaddr)) {
557 			scope = if_nametoindex(addr->ifa_name);
558 			break;
559 		}
560 	}
561 	freeifaddrs(addrs);
562 #else
563 
564 	for (i = 0; i < 5; i++)
565 	{
566 		ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX,
567 					   NULL, addrs, &size);
568 		if ((ret == NO_ERROR) || (ret == ERROR_NO_DATA)) {
569 			break;
570 		} else if (ret == ERROR_BUFFER_OVERFLOW)
571 		{
572 			if (addrs)
573 				free(addrs);
574 			addrs = (IP_ADAPTER_ADDRESSES *)malloc(size);
575 		} else
576 		{
577 			if (addrs)
578 			{
579 				free(addrs);
580 				addrs = NULL;
581 			}
582 			lwsl_err("Failed to get IPv6 address table (%d)", ret);
583 			break;
584 		}
585 	}
586 
587 	if ((ret == NO_ERROR) && (addrs)) {
588 		adapter = addrs;
589 		while (adapter && !found) {
590 			addr = adapter->FirstUnicastAddress;
591 			while (addr && !found) {
592 				if (addr->Address.lpSockaddr->sa_family ==
593 				    AF_INET6) {
594 					sockaddr = (struct sockaddr_in6 *)
595 						(addr->Address.lpSockaddr);
596 
597 					lws_plat_inet_ntop(sockaddr->sin6_family,
598 							&sockaddr->sin6_addr,
599 							ip, sizeof(ip));
600 
601 					if (!strcmp(ip, ifname_or_ipaddr)) {
602 						scope = sockaddr->sin6_scope_id;
603 						found = 1;
604 						break;
605 					}
606 				}
607 				addr = addr->Next;
608 			}
609 			adapter = adapter->Next;
610 		}
611 	}
612 	if (addrs)
613 		free(addrs);
614 #endif
615 
616 	return scope;
617 }
618 #endif
619 
620 /*
621  * https://en.wikipedia.org/wiki/IPv6_address
622  *
623  * An IPv6 address is represented as eight groups of four hexadecimal digits,
624  * each group representing 16 bits (two octets, a group sometimes also called a
625  * hextet[6][7]). The groups are separated by colons (:). An example of an IPv6
626  * address is:
627  *
628  *    2001:0db8:85a3:0000:0000:8a2e:0370:7334
629  *
630  * The hexadecimal digits are case-insensitive, but IETF recommendations suggest
631  * the use of lower case letters. The full representation of eight 4-digit
632  * groups may be simplified by several techniques, eliminating parts of the
633  * representation.
634  *
635  * Leading zeroes in a group may be omitted, but each group must retain at least
636  * one hexadecimal digit.[1] Thus, the example address may be written as:
637  *
638  *    2001:db8:85a3:0:0:8a2e:370:7334
639  *
640  * One or more consecutive groups containing zeros only may be replaced with a
641  * single empty group, using two consecutive colons (::).[1] The substitution
642  * may only be applied once in the address, however, because multiple
643  * occurrences would create an ambiguous representation. Thus, the example
644  * address can be further simplified:
645  *
646  *    2001:db8:85a3::8a2e:370:7334
647  *
648  * The localhost (loopback) address, 0:0:0:0:0:0:0:1, and the IPv6 unspecified
649  * address, 0:0:0:0:0:0:0:0, are reduced to ::1 and ::, respectively.
650  *
651  * During the transition of the Internet from IPv4 to IPv6, it is typical to
652  * operate in a mixed addressing environment. For such use cases, a special
653  * notation has been introduced, which expresses IPv4-mapped and IPv4-compatible
654  * IPv6 addresses by writing the least-significant 32 bits of an address in the
655  * familiar IPv4 dot-decimal notation, whereas the other 96 (most significant)
656  * bits are written in IPv6 format. For example, the IPv4-mapped IPv6 address
657  * ::ffff:c000:0280 is written as ::ffff:192.0.2.128, thus expressing clearly
658  * the original IPv4 address that was mapped to IPv6.
659  */
660 
661 int
lws_parse_numeric_address(const char * ads,uint8_t * result,size_t max_len)662 lws_parse_numeric_address(const char *ads, uint8_t *result, size_t max_len)
663 {
664 	struct lws_tokenize ts;
665 	uint8_t *orig = result, temp[16];
666 	int sects = 0, ipv6 = !!strchr(ads, ':'), skip_point = -1, dm = 0;
667 	char t[5];
668 	size_t n;
669 	long u;
670 
671 	lws_tokenize_init(&ts, ads, LWS_TOKENIZE_F_NO_INTEGERS |
672 				    LWS_TOKENIZE_F_MINUS_NONTERM);
673 	ts.len = strlen(ads);
674 	if (!ipv6 && ts.len < 7)
675 		return -1;
676 
677 	if (ipv6 && ts.len < 2)
678 		return -2;
679 
680 	if (!ipv6 && max_len < 4)
681 		return -3;
682 
683 	if (ipv6 && max_len < 16)
684 		return -4;
685 
686 	if (ipv6)
687 		memset(result, 0, max_len);
688 
689 	do {
690 		ts.e = (int8_t)lws_tokenize(&ts);
691 		switch (ts.e) {
692 		case LWS_TOKZE_TOKEN:
693 			dm = 0;
694 			if (ipv6) {
695 				if (ts.token_len > 4)
696 					return -1;
697 				memcpy(t, ts.token, ts.token_len);
698 				t[ts.token_len] = '\0';
699 				for (n = 0; n < ts.token_len; n++)
700 					if (t[n] < '0' || t[n] > 'f' ||
701 					    (t[n] > '9' && t[n] < 'A') ||
702 					    (t[n] > 'F' && t[n] < 'a'))
703 						return -1;
704 				u = strtol(t, NULL, 16);
705 				if (u > 0xffff)
706 					return -5;
707 				*result++ = (uint8_t)(u >> 8);
708 			} else {
709 				if (ts.token_len > 3)
710 					return -1;
711 				memcpy(t, ts.token, ts.token_len);
712 				t[ts.token_len] = '\0';
713 				for (n = 0; n < ts.token_len; n++)
714 					if (t[n] < '0' || t[n] > '9')
715 						return -1;
716 				u = strtol(t, NULL, 10);
717 				if (u > 0xff)
718 					return -6;
719 			}
720 			if (u < 0)
721 				return -7;
722 			*result++ = (uint8_t)u;
723 			sects++;
724 			break;
725 
726 		case LWS_TOKZE_DELIMITER:
727 			if (dm++) {
728 				if (dm > 2)
729 					return -8;
730 				if (*ts.token != ':')
731 					return -9;
732 				/* back to back : */
733 				*result++ = 0;
734 				*result++ = 0;
735 				skip_point = lws_ptr_diff(result, orig);
736 				break;
737 			}
738 			if (ipv6 && orig[2] == 0xff && orig[3] == 0xff &&
739 			    skip_point == 2) {
740 				/* ipv4 backwards compatible format */
741 				ipv6 = 0;
742 				memset(orig, 0, max_len);
743 				orig[10] = 0xff;
744 				orig[11] = 0xff;
745 				skip_point = -1;
746 				result = &orig[12];
747 				sects = 0;
748 				break;
749 			}
750 			if (ipv6 && *ts.token != ':')
751 				return -10;
752 			if (!ipv6 && *ts.token != '.')
753 				return -11;
754 			break;
755 
756 		case LWS_TOKZE_ENDED:
757 			if (!ipv6 && sects == 4)
758 				return lws_ptr_diff(result, orig);
759 			if (ipv6 && sects == 8)
760 				return lws_ptr_diff(result, orig);
761 			if (skip_point != -1) {
762 				int ow = lws_ptr_diff(result, orig);
763 				/*
764 				 * contains ...::...
765 				 */
766 				if (ow == 16)
767 					return 16;
768 				memcpy(temp, &orig[skip_point], (unsigned int)(ow - skip_point));
769 				memset(&orig[skip_point], 0, (unsigned int)(16 - skip_point));
770 				memcpy(&orig[16 - (ow - skip_point)], temp,
771 						   (unsigned int)(ow - skip_point));
772 
773 				return 16;
774 			}
775 			return -12;
776 
777 		default: /* includes ENDED */
778 			lwsl_err("%s: malformed ip address\n",
779 				 __func__);
780 
781 			return -13;
782 		}
783 	} while (ts.e > 0 && result - orig <= (int)max_len);
784 
785 	lwsl_err("%s: ended on e %d\n", __func__, ts.e);
786 
787 	return -14;
788 }
789 
790 int
lws_sa46_parse_numeric_address(const char * ads,lws_sockaddr46 * sa46)791 lws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46)
792 {
793 	uint8_t a[16];
794 	int n;
795 
796 	n = lws_parse_numeric_address(ads, a, sizeof(a));
797 	if (n < 0)
798 		return -1;
799 
800 #if defined(LWS_WITH_IPV6)
801 	if (n == 16) {
802 		sa46->sa6.sin6_family = AF_INET6;
803 		memcpy(sa46->sa6.sin6_addr.s6_addr, a,
804 		       sizeof(sa46->sa6.sin6_addr.s6_addr));
805 
806 		return 0;
807 	}
808 #endif
809 
810 	if (n != 4)
811 		return -1;
812 
813 	sa46->sa4.sin_family = AF_INET;
814 	memcpy(&sa46->sa4.sin_addr.s_addr, a,
815 	       sizeof(sa46->sa4.sin_addr.s_addr));
816 
817 	return 0;
818 }
819 
820 int
lws_write_numeric_address(const uint8_t * ads,int size,char * buf,size_t len)821 lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len)
822 {
823 	char c, elided = 0, soe = 0, zb = (char)-1, n, ipv4 = 0;
824 	const char *e = buf + len;
825 	char *obuf = buf;
826 	int q = 0;
827 
828 	if (size == 4)
829 		return lws_snprintf(buf, len, "%u.%u.%u.%u",
830 				    ads[0], ads[1], ads[2], ads[3]);
831 
832 	if (size != 16)
833 		return -1;
834 
835 	for (c = 0; c < (char)size / 2; c++) {
836 		uint16_t v = (uint16_t)((ads[q] << 8) | ads[q + 1]);
837 
838 		if (buf + 8 > e)
839 			return -1;
840 
841 		q += 2;
842 		if (soe) {
843 			if (v)
844 				*buf++ = ':';
845 				/* fall thru to print hex value */
846 		} else
847 			if (!elided && !soe && !v) {
848 				elided = soe = 1;
849 				zb = c;
850 				continue;
851 			}
852 
853 		if (ipv4) {
854 			n = (char)lws_snprintf(buf, lws_ptr_diff_size_t(e, buf), "%u.%u",
855 					ads[q - 2], ads[q - 1]);
856 			buf += n;
857 			if (c == 6)
858 				*buf++ = '.';
859 		} else {
860 			if (soe && !v)
861 				continue;
862 			if (c)
863 				*buf++ = ':';
864 
865 			buf += lws_snprintf(buf, lws_ptr_diff_size_t(e, buf), "%x", v);
866 
867 			if (soe && v) {
868 				soe = 0;
869 				if (c == 5 && v == 0xffff && !zb) {
870 					ipv4 = 1;
871 					*buf++ = ':';
872 				}
873 			}
874 		}
875 	}
876 	if (buf + 3 > e)
877 		return -1;
878 
879 	if (soe) { /* as is the case for all zeros */
880 		*buf++ = ':';
881 		*buf++ = ':';
882 		*buf = '\0';
883 	}
884 
885 	return lws_ptr_diff(buf, obuf);
886 }
887 
888 int
lws_sa46_write_numeric_address(lws_sockaddr46 * sa46,char * buf,size_t len)889 lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len)
890 {
891 	*buf = '\0';
892 #if defined(LWS_WITH_IPV6)
893 	if (sa46->sa4.sin_family == AF_INET6)
894 		return lws_write_numeric_address(
895 				(uint8_t *)&sa46->sa6.sin6_addr, 16, buf, len);
896 #endif
897 	if (sa46->sa4.sin_family == AF_INET)
898 		return lws_write_numeric_address(
899 				(uint8_t *)&sa46->sa4.sin_addr, 4, buf, len);
900 
901 #if defined(LWS_WITH_UNIX_SOCK)
902 	if (sa46->sa4.sin_family == AF_UNIX)
903 		return lws_snprintf(buf, len, "(unix skt)");
904 #endif
905 
906 	if (!sa46->sa4.sin_family)
907 		return lws_snprintf(buf, len, "(unset)");
908 
909 	if (sa46->sa4.sin_family == AF_INET6)
910 		return lws_snprintf(buf, len, "(ipv6 unsupp)");
911 
912 	lws_snprintf(buf, len, "(AF%d unsupp)", (int)sa46->sa4.sin_family);
913 
914 	return -1;
915 }
916 
917 int
lws_sa46_compare_ads(const lws_sockaddr46 * sa46a,const lws_sockaddr46 * sa46b)918 lws_sa46_compare_ads(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46b)
919 {
920 	if (sa46a->sa4.sin_family != sa46b->sa4.sin_family)
921 		return 1;
922 
923 #if defined(LWS_WITH_IPV6)
924 	if (sa46a->sa4.sin_family == AF_INET6)
925 		return memcmp(&sa46a->sa6.sin6_addr, &sa46b->sa6.sin6_addr, 16);
926 #endif
927 
928 	if (sa46a->sa4.sin_family == AF_INET)
929 		return sa46a->sa4.sin_addr.s_addr != sa46b->sa4.sin_addr.s_addr;
930 
931 	return 0;
932 }
933 
934 void
lws_4to6(uint8_t * v6addr,const uint8_t * v4addr)935 lws_4to6(uint8_t *v6addr, const uint8_t *v4addr)
936 {
937 	v6addr[12] = v4addr[0];
938 	v6addr[13] = v4addr[1];
939 	v6addr[14] = v4addr[2];
940 	v6addr[15] = v4addr[3];
941 
942 	memset(v6addr, 0, 10);
943 
944 	v6addr[10] = v6addr[11] = 0xff;
945 }
946 
947 #if defined(LWS_WITH_IPV6)
948 void
lws_sa46_4to6(lws_sockaddr46 * sa46,const uint8_t * v4addr,uint16_t port)949 lws_sa46_4to6(lws_sockaddr46 *sa46, const uint8_t *v4addr, uint16_t port)
950 {
951 	sa46->sa4.sin_family = AF_INET6;
952 
953 	lws_4to6((uint8_t *)&sa46->sa6.sin6_addr.s6_addr[0], v4addr);
954 
955 	sa46->sa6.sin6_port = htons(port);
956 }
957 #endif
958 
959 int
lws_sa46_on_net(const lws_sockaddr46 * sa46a,const lws_sockaddr46 * sa46_net,int net_len)960 lws_sa46_on_net(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46_net,
961 		int net_len)
962 {
963 	uint8_t mask = 0xff, norm[16];
964 	const uint8_t *p1, *p2;
965 
966 	if (sa46a->sa4.sin_family == AF_INET) {
967 		p1 = (uint8_t *)&sa46a->sa4.sin_addr;
968 		if (sa46_net->sa4.sin_family == AF_INET6) {
969 			/* ip is v4, net is v6, promote ip to v6 */
970 
971 			lws_4to6(norm, p1);
972 			p1 = norm;
973 		}
974 #if defined(LWS_WITH_IPV6)
975 	} else
976 		if (sa46a->sa4.sin_family == AF_INET6) {
977 			p1 = (uint8_t *)&sa46a->sa6.sin6_addr;
978 #endif
979 		} else
980 			return 1;
981 
982 	if (sa46_net->sa4.sin_family == AF_INET) {
983 		p2 = (uint8_t *)&sa46_net->sa4.sin_addr;
984 		if (sa46a->sa4.sin_family == AF_INET6) {
985 			/* ip is v6, net is v4, promote net to v6 */
986 
987 			lws_4to6(norm, p2);
988 			p2 = norm;
989 			/* because the mask length is for net v4 address */
990 			net_len += 12 * 8;
991 		}
992 #if defined(LWS_WITH_IPV6)
993 	} else
994 		if (sa46a->sa4.sin_family == AF_INET6) {
995 			p2 = (uint8_t *)&sa46_net->sa6.sin6_addr;
996 #endif
997 		} else
998 			return 1;
999 
1000 	while (net_len > 0) {
1001 		if (net_len < 8)
1002 			mask = (uint8_t)(mask << (8 - net_len));
1003 
1004 		if (((*p1++) & mask) != ((*p2++) & mask))
1005 			return 1;
1006 
1007 		net_len -= 8;
1008 	}
1009 
1010 	return 0;
1011 }
1012 
1013 void
lws_sa46_copy_address(lws_sockaddr46 * sa46a,const void * in,int af)1014 lws_sa46_copy_address(lws_sockaddr46 *sa46a, const void *in, int af)
1015 {
1016 	sa46a->sa4.sin_family = (sa_family_t)af;
1017 
1018 	if (af == AF_INET)
1019 		memcpy(&sa46a->sa4.sin_addr, in, 4);
1020 #if defined(LWS_WITH_IPV6)
1021 	else if (af == AF_INET6)
1022 		memcpy(&sa46a->sa6.sin6_addr, in, sizeof(sa46a->sa6.sin6_addr));
1023 #endif
1024 }
1025 
1026 #if defined(LWS_WITH_SYS_STATE)
1027 lws_state_manager_t *
lws_system_get_state_manager(struct lws_context * context)1028 lws_system_get_state_manager(struct lws_context *context)
1029 {
1030 	return &context->mgr_system;
1031 }
1032 #endif
1033