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) 29static int 30interface_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 45static int 46lws_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_vhost_err(vh, "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 128const char * 129lws_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 145const char * 146lws_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 153void 154lws_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_wsi_warn(wsi, "getpeername: %s", strerror(LWS_ERRNO)); 181 goto bail; 182 } 183 184 lws_get_addresses(wsi->a.vhost, p, name, name_len, rip, rip_len); 185 186bail: 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 206int 207lws_socket_bind(struct lws_vhost *vhost, struct lws *wsi, 208 lws_sockfd_type sockfd, int port, const char *iface, 209 int af) 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 = 0; 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 switch (af) { 235#if defined(LWS_WITH_UNIX_SOCK) 236 case AF_UNIX: 237 v = (struct sockaddr *)&serv_unix; 238 memset(&serv_unix, 0, sizeof(serv_unix)); 239 serv_unix.sun_family = AF_UNIX; 240 if (!iface) 241 return LWS_ITOSA_NOT_EXIST; 242 if (sizeof(serv_unix.sun_path) <= strlen(iface)) { 243 lwsl_wsi_err(wsi, "\"%s\" too long for UNIX domain socket", 244 iface); 245 return LWS_ITOSA_NOT_EXIST; 246 } 247 n = (int)(sizeof(uint16_t) + strlen(iface)); 248 strcpy(serv_unix.sun_path, iface); 249 if (serv_unix.sun_path[0] == '@') 250 serv_unix.sun_path[0] = '\0'; 251 else 252 unlink(serv_unix.sun_path); 253 254 // lwsl_hexdump_notice(v, n); 255 break; 256#endif 257#if defined(LWS_WITH_IPV6) && !defined(LWS_PLAT_FREERTOS) 258 case AF_INET6: 259 v = (struct sockaddr *)&serv_addr6; 260 n = sizeof(struct sockaddr_in6); 261 262 memset(&serv_addr6, 0, sizeof(serv_addr6)); 263 serv_addr6.sin6_family = AF_INET6; 264 if (iface) { 265 m = interface_to_sa(vhost, iface, 266 (struct sockaddr_in *)v, (unsigned int)n, 1); 267 if (m == LWS_ITOSA_NOT_USABLE) { 268 lwsl_wsi_info(wsi, "netif %s: Not usable", 269 iface); 270 return m; 271 } 272 if (m == LWS_ITOSA_NOT_EXIST) { 273 lwsl_wsi_info(wsi, "netif %s: Does not exist", 274 iface); 275 return m; 276 } 277 serv_addr6.sin6_scope_id = (unsigned int)htonl((uint32_t) 278 lws_get_addr_scope(wsi, iface)); 279 } 280 281 serv_addr6.sin6_port = (uint16_t)htons((uint16_t)port); 282 break; 283#endif 284 285 case AF_INET: 286 v = (struct sockaddr *)&serv_addr4; 287 n = sizeof(serv_addr4); 288 memset(&serv_addr4, 0, sizeof(serv_addr4)); 289 serv_addr4.sin_addr.s_addr = INADDR_ANY; 290 serv_addr4.sin_family = AF_INET; 291 292#if !defined(LWS_PLAT_FREERTOS) && !defined(LWS_PLAT_OPTEE) 293 if (iface) { 294 m = interface_to_sa(vhost, iface, 295 (struct sockaddr_in *)v, (unsigned int)n, 0); 296 if (m == LWS_ITOSA_NOT_USABLE) { 297 lwsl_wsi_info(wsi, "netif %s: Not usable", 298 iface); 299 return m; 300 } 301 if (m == LWS_ITOSA_NOT_EXIST) { 302 lwsl_wsi_info(wsi, "netif %s: Does not exist", 303 iface); 304 return m; 305 } 306 } 307#endif 308 serv_addr4.sin_port = htons((uint16_t)(unsigned int)port); 309 break; 310 default: 311 return -1; 312 } /* switch */ 313 314 /* just checking for the interface extant */ 315 if (sockfd == LWS_SOCK_INVALID) 316 return LWS_ITOSA_USABLE; 317 318 n = bind(sockfd, v, (socklen_t)n); 319#ifdef LWS_WITH_UNIX_SOCK 320 if (n < 0 && af == AF_UNIX) { 321 lwsl_wsi_err(wsi, "ERROR on binding fd %d to \"%s\" (%d %d)", 322 sockfd, iface, n, LWS_ERRNO); 323 324 return LWS_ITOSA_NOT_EXIST; 325 } else 326#endif 327 if (n < 0) { 328 int _lws_errno = LWS_ERRNO; 329 330 lwsl_wsi_err(wsi, "ERROR on binding fd %d to port %d (%d %d)", 331 sockfd, port, n, _lws_errno); 332 333 /* if something already listening, tell caller to fail permanently */ 334 335 if (_lws_errno == LWS_EADDRINUSE) 336 return LWS_ITOSA_BUSY; 337 338 /* otherwise ask caller to retry later */ 339 340 return LWS_ITOSA_NOT_EXIST; 341 } 342 343#if defined(LWS_WITH_UNIX_SOCK) && !defined(WIN32) 344 if (af == AF_UNIX) { 345 uid_t uid = vhost->context->uid; 346 gid_t gid = vhost->context->gid; 347 348 if (vhost->unix_socket_perms) { 349 if (lws_plat_user_colon_group_to_ids( 350 vhost->unix_socket_perms, &uid, &gid)) { 351 lwsl_wsi_err(wsi, "Failed to translate %s", 352 vhost->unix_socket_perms); 353 return LWS_ITOSA_NOT_EXIST; 354 } 355 } 356 if (iface && iface[0] != '@' && uid && gid) { 357 if (chown(iface, uid, gid)) { 358 lwsl_wsi_err(wsi, "failed to set %s perms %u:%u", 359 iface, (unsigned int)uid, 360 (unsigned int)gid); 361 362 return LWS_ITOSA_NOT_EXIST; 363 } 364 lwsl_wsi_notice(wsi, "vh %s unix skt %s perms %u:%u", 365 vhost->name, iface, 366 (unsigned int)uid, 367 (unsigned int)gid); 368 369 if (chmod(iface, 0660)) { 370 lwsl_wsi_err(wsi, "0600 mode on %s fail", iface); 371 372 return LWS_ITOSA_NOT_EXIST; 373 } 374 } 375 } 376#endif 377 378#ifndef LWS_PLAT_OPTEE 379 if (getsockname(sockfd, (struct sockaddr *)psin, &len) == -1) 380 lwsl_wsi_warn(wsi, "getsockname: %s", strerror(LWS_ERRNO)); 381 else 382#endif 383#if defined(LWS_WITH_IPV6) 384 port = (sin.ss_family == AF_INET6) ? 385 ntohs(((struct sockaddr_in6 *)psin)->sin6_port) : 386 ntohs(((struct sockaddr_in *)psin)->sin_port); 387#else 388 { 389 struct sockaddr_in sain; 390 memcpy(&sain, psin, sizeof(sain)); 391 port = ntohs(sain.sin_port); 392 } 393#endif 394 395 { 396 char buf[72]; 397 lws_sa46_write_numeric_address((lws_sockaddr46 *)psin, 398 buf, sizeof(buf)); 399 400 lwsl_vhost_notice(vhost, "source ads %s", buf); 401 } 402 403 return port; 404} 405 406#if defined(LWS_WITH_CLIENT) 407 408unsigned int 409lws_retry_get_delay_ms(struct lws_context *context, 410 const lws_retry_bo_t *retry, uint16_t *ctry, 411 char *conceal) 412{ 413 uint64_t ms = 3000, pc = 30; /* sane-ish defaults if no retry table */ 414 uint16_t ra; 415 416 if (conceal) 417 *conceal = 0; 418 419 if (retry) { 420 if (retry->retry_ms_table_count) { 421 if (*ctry < retry->retry_ms_table_count) 422 ms = retry->retry_ms_table[*ctry]; 423 else 424 ms = retry->retry_ms_table[ 425 retry->retry_ms_table_count - 1]; 426 } 427 428 /* if no percent given, use the default 30% */ 429 if (retry->jitter_percent) 430 pc = retry->jitter_percent; 431 } 432 433 if (lws_get_random(context, &ra, sizeof(ra)) == sizeof(ra)) 434 ms += ((ms * pc * ra) >> 16) / 100; 435 else 436 assert(0); 437 438 if (*ctry < 0xffff) 439 (*ctry)++; 440 441 if (retry && conceal) 442 *conceal = (int)*ctry <= retry->conceal_count; 443 444 return (unsigned int)ms; 445} 446 447int 448lws_retry_sul_schedule(struct lws_context *context, int tid, 449 lws_sorted_usec_list_t *sul, 450 const lws_retry_bo_t *retry, sul_cb_t cb, uint16_t *ctry) 451{ 452 char conceal; 453 uint64_t ms = lws_retry_get_delay_ms(context, retry, ctry, &conceal); 454 455 if (!conceal) 456 return 1; 457 458 lwsl_cx_info(context, "sul %p: scheduling retry in %dms", sul, (int)ms); 459 460 lws_sul_schedule(context, tid, sul, cb, (int64_t)(ms * 1000)); 461 462 return 0; 463} 464 465int 466lws_retry_sul_schedule_retry_wsi(struct lws *wsi, lws_sorted_usec_list_t *sul, 467 sul_cb_t cb, uint16_t *ctry) 468{ 469 char conceal; 470 lws_usec_t us = lws_retry_get_delay_ms(wsi->a.context, 471 wsi->retry_policy, ctry, 472 &conceal) * LWS_US_PER_MS; 473 474 if (!conceal) 475 /* if our reties are up, they're up... */ 476 return 1; 477 478#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 479 if ( 480#if defined(LWS_ROLE_H1) 481 wsi->role_ops == &role_ops_h1 482#endif 483#if defined(LWS_ROLE_H1) && defined(LWS_ROLE_H2) 484 || 485#endif 486#if defined(LWS_ROLE_H2) 487 wsi->role_ops == &role_ops_h2 488#endif 489 ) 490 /* 491 * Since we're doing it by wsi, we're in a position to check for 492 * http retry-after, it will increase us accordingly if found 493 */ 494 lws_http_check_retry_after(wsi, &us); 495#endif 496 lws_sul_schedule(wsi->a.context, wsi->tsi, sul, cb, us); 497 498 return 0; 499} 500 501#endif 502 503#if defined(LWS_WITH_IPV6) 504unsigned long 505lws_get_addr_scope(struct lws *wsi, const char *ifname_or_ipaddr) 506{ 507 unsigned long scope; 508 char ip[NI_MAXHOST]; 509 unsigned int i; 510#if !defined(WIN32) 511 struct ifaddrs *addrs, *addr; 512#else 513 PIP_ADAPTER_ADDRESSES adapter, addrs = NULL; 514 PIP_ADAPTER_UNICAST_ADDRESS addr; 515 struct sockaddr_in6 *sockaddr; 516 ULONG size = 0; 517 int found = 0; 518 DWORD ret; 519#endif 520 521 /* 522 * First see if we can look the string up as a network interface name... 523 * windows vista+ also has this 524 */ 525 526 scope = if_nametoindex(ifname_or_ipaddr); 527 if (scope > 0) 528 /* we found it from the interface name lookup */ 529 return scope; 530 531 /* 532 * if not, try to look it up as an IP -> interface -> interface index 533 */ 534 535 scope = 0; 536 537#if !defined(WIN32) 538 539 getifaddrs(&addrs); 540 for (addr = addrs; addr; addr = addr->ifa_next) { 541 if (!addr->ifa_addr || 542 addr->ifa_addr->sa_family != AF_INET6) 543 continue; 544 545 ip[0] = '\0'; 546 getnameinfo(addr->ifa_addr, sizeof(struct sockaddr_in6), 547 ip, sizeof(ip), 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 ret = GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, 566 NULL, addrs, &size); 567 if (ret == NO_ERROR || ret == ERROR_NO_DATA) 568 break; 569 570 if (addrs) 571 free(addrs); 572 573 if (ret != ERROR_BUFFER_OVERFLOW) { 574 addrs = NULL; 575 lwsl_wsi_err(wsi, "Get IPv6 ads table fail (%d)", ret); 576 break; 577 } 578 579 addrs = (IP_ADAPTER_ADDRESSES *)malloc(size); 580 } 581 582 if ((ret == NO_ERROR) && (addrs)) { 583 adapter = addrs; 584 while (adapter && !found) { 585 addr = adapter->FirstUnicastAddress; 586 while (addr && !found) { 587 if (addr->Address.lpSockaddr->sa_family == 588 AF_INET6) { 589 sockaddr = (struct sockaddr_in6 *) 590 (addr->Address.lpSockaddr); 591 592 lws_plat_inet_ntop(sockaddr->sin6_family, 593 &sockaddr->sin6_addr, 594 ip, sizeof(ip)); 595 596 if (!strcmp(ip, ifname_or_ipaddr)) { 597 scope = sockaddr->sin6_scope_id; 598 found = 1; 599 break; 600 } 601 } 602 addr = addr->Next; 603 } 604 adapter = adapter->Next; 605 } 606 } 607 if (addrs) 608 free(addrs); 609#endif 610 611 return scope; 612} 613#endif 614 615/* 616 * https://en.wikipedia.org/wiki/IPv6_address 617 * 618 * An IPv6 address is represented as eight groups of four hexadecimal digits, 619 * each group representing 16 bits (two octets, a group sometimes also called a 620 * hextet[6][7]). The groups are separated by colons (:). An example of an IPv6 621 * address is: 622 * 623 * 2001:0db8:85a3:0000:0000:8a2e:0370:7334 624 * 625 * The hexadecimal digits are case-insensitive, but IETF recommendations suggest 626 * the use of lower case letters. The full representation of eight 4-digit 627 * groups may be simplified by several techniques, eliminating parts of the 628 * representation. 629 * 630 * Leading zeroes in a group may be omitted, but each group must retain at least 631 * one hexadecimal digit.[1] Thus, the example address may be written as: 632 * 633 * 2001:db8:85a3:0:0:8a2e:370:7334 634 * 635 * One or more consecutive groups containing zeros only may be replaced with a 636 * single empty group, using two consecutive colons (::).[1] The substitution 637 * may only be applied once in the address, however, because multiple 638 * occurrences would create an ambiguous representation. Thus, the example 639 * address can be further simplified: 640 * 641 * 2001:db8:85a3::8a2e:370:7334 642 * 643 * The localhost (loopback) address, 0:0:0:0:0:0:0:1, and the IPv6 unspecified 644 * address, 0:0:0:0:0:0:0:0, are reduced to ::1 and ::, respectively. 645 * 646 * During the transition of the Internet from IPv4 to IPv6, it is typical to 647 * operate in a mixed addressing environment. For such use cases, a special 648 * notation has been introduced, which expresses IPv4-mapped and IPv4-compatible 649 * IPv6 addresses by writing the least-significant 32 bits of an address in the 650 * familiar IPv4 dot-decimal notation, whereas the other 96 (most significant) 651 * bits are written in IPv6 format. For example, the IPv4-mapped IPv6 address 652 * ::ffff:c000:0280 is written as ::ffff:192.0.2.128, thus expressing clearly 653 * the original IPv4 address that was mapped to IPv6. 654 */ 655 656int 657lws_parse_numeric_address(const char *ads, uint8_t *result, size_t max_len) 658{ 659 struct lws_tokenize ts; 660 uint8_t *orig = result, temp[16]; 661 int sects = 0, ipv6 = !!strchr(ads, ':'), skip_point = -1, dm = 0; 662 char t[5]; 663 size_t n; 664 long u; 665 666 lws_tokenize_init(&ts, ads, LWS_TOKENIZE_F_NO_INTEGERS | 667 LWS_TOKENIZE_F_MINUS_NONTERM); 668 ts.len = strlen(ads); 669 if (!ipv6 && ts.len < 7) 670 return -1; 671 672 if (ipv6 && ts.len < 2) 673 return -2; 674 675 if (!ipv6 && max_len < 4) 676 return -3; 677 678 if (ipv6 && max_len < 16) 679 return -4; 680 681 if (ipv6) 682 memset(result, 0, max_len); 683 684 do { 685 ts.e = (int8_t)lws_tokenize(&ts); 686 switch (ts.e) { 687 case LWS_TOKZE_TOKEN: 688 dm = 0; 689 if (ipv6) { 690 if (ts.token_len > 4) 691 return -1; 692 memcpy(t, ts.token, ts.token_len); 693 t[ts.token_len] = '\0'; 694 for (n = 0; n < ts.token_len; n++) 695 if (t[n] < '0' || t[n] > 'f' || 696 (t[n] > '9' && t[n] < 'A') || 697 (t[n] > 'F' && t[n] < 'a')) 698 return -1; 699 u = strtol(t, NULL, 16); 700 if (u > 0xffff) 701 return -5; 702 *result++ = (uint8_t)(u >> 8); 703 } else { 704 if (ts.token_len > 3) 705 return -1; 706 memcpy(t, ts.token, ts.token_len); 707 t[ts.token_len] = '\0'; 708 for (n = 0; n < ts.token_len; n++) 709 if (t[n] < '0' || t[n] > '9') 710 return -1; 711 u = strtol(t, NULL, 10); 712 if (u > 0xff) 713 return -6; 714 } 715 if (u < 0) 716 return -7; 717 *result++ = (uint8_t)u; 718 sects++; 719 break; 720 721 case LWS_TOKZE_DELIMITER: 722 if (dm++) { 723 if (dm > 2) 724 return -8; 725 if (*ts.token != ':') 726 return -9; 727 /* back to back : */ 728 *result++ = 0; 729 *result++ = 0; 730 skip_point = lws_ptr_diff(result, orig); 731 break; 732 } 733 if (ipv6 && orig[2] == 0xff && orig[3] == 0xff && 734 skip_point == 2) { 735 /* ipv4 backwards compatible format */ 736 ipv6 = 0; 737 memset(orig, 0, max_len); 738 orig[10] = 0xff; 739 orig[11] = 0xff; 740 skip_point = -1; 741 result = &orig[12]; 742 sects = 0; 743 break; 744 } 745 if (ipv6 && *ts.token != ':') 746 return -10; 747 if (!ipv6 && *ts.token != '.') 748 return -11; 749 break; 750 751 case LWS_TOKZE_ENDED: 752 if (!ipv6 && sects == 4) 753 return lws_ptr_diff(result, orig); 754 if (ipv6 && sects == 8) 755 return lws_ptr_diff(result, orig); 756 if (skip_point != -1) { 757 int ow = lws_ptr_diff(result, orig); 758 /* 759 * contains ...::... 760 */ 761 if (ow == 16) 762 return 16; 763 memcpy(temp, &orig[skip_point], (unsigned int)(ow - skip_point)); 764 memset(&orig[skip_point], 0, (unsigned int)(16 - skip_point)); 765 memcpy(&orig[16 - (ow - skip_point)], temp, 766 (unsigned int)(ow - skip_point)); 767 768 return 16; 769 } 770 return -12; 771 772 default: /* includes ENDED */ 773 lwsl_err("%s: malformed ip address\n", 774 __func__); 775 776 return -13; 777 } 778 } while (ts.e > 0 && result - orig <= (int)max_len); 779 780 lwsl_err("%s: ended on e %d\n", __func__, ts.e); 781 782 return -14; 783} 784 785int 786lws_sa46_parse_numeric_address(const char *ads, lws_sockaddr46 *sa46) 787{ 788 uint8_t a[16]; 789 int n; 790 791 n = lws_parse_numeric_address(ads, a, sizeof(a)); 792 if (n < 0) 793 return -1; 794 795#if defined(LWS_WITH_IPV6) 796 if (n == 16) { 797 sa46->sa6.sin6_family = AF_INET6; 798 memcpy(sa46->sa6.sin6_addr.s6_addr, a, 799 sizeof(sa46->sa6.sin6_addr.s6_addr)); 800 801 return 0; 802 } 803#endif 804 805 if (n != 4) 806 return -1; 807 808 sa46->sa4.sin_family = AF_INET; 809 memcpy(&sa46->sa4.sin_addr.s_addr, a, 810 sizeof(sa46->sa4.sin_addr.s_addr)); 811 812 return 0; 813} 814 815int 816lws_write_numeric_address(const uint8_t *ads, int size, char *buf, size_t len) 817{ 818 char c, elided = 0, soe = 0, zb = (char)-1, n, ipv4 = 0; 819 const char *e = buf + len; 820 char *obuf = buf; 821 int q = 0; 822 823 if (size == 4) 824 return lws_snprintf(buf, len, "%u.%u.%u.%u", 825 ads[0], ads[1], ads[2], ads[3]); 826 827 if (size != 16) 828 return -1; 829 830 for (c = 0; c < (char)size / 2; c++) { 831 uint16_t v = (uint16_t)((ads[q] << 8) | ads[q + 1]); 832 833 if (buf + 8 > e) 834 return -1; 835 836 q += 2; 837 if (soe) { 838 if (v) 839 *buf++ = ':'; 840 /* fall thru to print hex value */ 841 } else 842 if (!elided && !soe && !v) { 843 elided = soe = 1; 844 zb = c; 845 continue; 846 } 847 848 if (ipv4) { 849 n = (char)lws_snprintf(buf, lws_ptr_diff_size_t(e, buf), "%u.%u", 850 ads[q - 2], ads[q - 1]); 851 buf += n; 852 if (c == 6) 853 *buf++ = '.'; 854 } else { 855 if (soe && !v) 856 continue; 857 if (c) 858 *buf++ = ':'; 859 860 buf += lws_snprintf(buf, lws_ptr_diff_size_t(e, buf), "%x", v); 861 862 if (soe && v) { 863 soe = 0; 864 if (c == 5 && v == 0xffff && !zb) { 865 ipv4 = 1; 866 *buf++ = ':'; 867 } 868 } 869 } 870 } 871 if (buf + 3 > e) 872 return -1; 873 874 if (soe) { /* as is the case for all zeros */ 875 *buf++ = ':'; 876 *buf++ = ':'; 877 *buf = '\0'; 878 } 879 880 return lws_ptr_diff(buf, obuf); 881} 882 883int 884lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len) 885{ 886 *buf = '\0'; 887#if defined(LWS_WITH_IPV6) 888 if (sa46->sa4.sin_family == AF_INET6) 889 return lws_write_numeric_address( 890 (uint8_t *)&sa46->sa6.sin6_addr, 16, buf, len); 891#endif 892 if (sa46->sa4.sin_family == AF_INET) 893 return lws_write_numeric_address( 894 (uint8_t *)&sa46->sa4.sin_addr, 4, buf, len); 895 896#if defined(LWS_WITH_UNIX_SOCK) 897 if (sa46->sa4.sin_family == AF_UNIX) 898 return lws_snprintf(buf, len, "(unix skt)"); 899#endif 900 901 if (!sa46->sa4.sin_family) 902 return lws_snprintf(buf, len, "(unset)"); 903 904 if (sa46->sa4.sin_family == AF_INET6) 905 return lws_snprintf(buf, len, "(ipv6 unsupp)"); 906 907 lws_snprintf(buf, len, "(AF%d unsupp)", (int)sa46->sa4.sin_family); 908 909 return -1; 910} 911 912int 913lws_sa46_compare_ads(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46b) 914{ 915 if (sa46a->sa4.sin_family != sa46b->sa4.sin_family) 916 return 1; 917 918#if defined(LWS_WITH_IPV6) 919 if (sa46a->sa4.sin_family == AF_INET6) 920 return memcmp(&sa46a->sa6.sin6_addr, &sa46b->sa6.sin6_addr, 16); 921#endif 922 923 if (sa46a->sa4.sin_family == AF_INET) 924 return sa46a->sa4.sin_addr.s_addr != sa46b->sa4.sin_addr.s_addr; 925 926 return 0; 927} 928 929void 930lws_4to6(uint8_t *v6addr, const uint8_t *v4addr) 931{ 932 v6addr[12] = v4addr[0]; 933 v6addr[13] = v4addr[1]; 934 v6addr[14] = v4addr[2]; 935 v6addr[15] = v4addr[3]; 936 937 memset(v6addr, 0, 10); 938 939 v6addr[10] = v6addr[11] = 0xff; 940} 941 942#if defined(LWS_WITH_IPV6) 943void 944lws_sa46_4to6(lws_sockaddr46 *sa46, const uint8_t *v4addr, uint16_t port) 945{ 946 sa46->sa4.sin_family = AF_INET6; 947 948 lws_4to6((uint8_t *)&sa46->sa6.sin6_addr.s6_addr[0], v4addr); 949 950 sa46->sa6.sin6_port = htons(port); 951} 952#endif 953 954int 955lws_sa46_on_net(const lws_sockaddr46 *sa46a, const lws_sockaddr46 *sa46_net, 956 int net_len) 957{ 958 uint8_t mask = 0xff, norm[16]; 959 const uint8_t *p1, *p2; 960 961 if (sa46a->sa4.sin_family == AF_INET) { 962 p1 = (uint8_t *)&sa46a->sa4.sin_addr; 963 if (sa46_net->sa4.sin_family == AF_INET6) { 964 /* ip is v4, net is v6, promote ip to v6 */ 965 966 lws_4to6(norm, p1); 967 p1 = norm; 968 } 969#if defined(LWS_WITH_IPV6) 970 } else 971 if (sa46a->sa4.sin_family == AF_INET6) { 972 p1 = (uint8_t *)&sa46a->sa6.sin6_addr; 973#endif 974 } else 975 return 1; 976 977 if (sa46_net->sa4.sin_family == AF_INET) { 978 p2 = (uint8_t *)&sa46_net->sa4.sin_addr; 979 if (sa46a->sa4.sin_family == AF_INET6) { 980 /* ip is v6, net is v4, promote net to v6 */ 981 982 lws_4to6(norm, p2); 983 p2 = norm; 984 /* because the mask length is for net v4 address */ 985 net_len += 12 * 8; 986 } 987#if defined(LWS_WITH_IPV6) 988 } else 989 if (sa46a->sa4.sin_family == AF_INET6) { 990 p2 = (uint8_t *)&sa46_net->sa6.sin6_addr; 991#endif 992 } else 993 return 1; 994 995 while (net_len > 0) { 996 if (net_len < 8) 997 mask = (uint8_t)(mask << (8 - net_len)); 998 999 if (((*p1++) & mask) != ((*p2++) & mask)) 1000 return 1; 1001 1002 net_len -= 8; 1003 } 1004 1005 return 0; 1006} 1007 1008void 1009lws_sa46_copy_address(lws_sockaddr46 *sa46a, const void *in, int af) 1010{ 1011 sa46a->sa4.sin_family = (sa_family_t)af; 1012 1013 if (af == AF_INET) 1014 memcpy(&sa46a->sa4.sin_addr, in, 4); 1015#if defined(LWS_WITH_IPV6) 1016 else if (af == AF_INET6) 1017 memcpy(&sa46a->sa6.sin6_addr, in, sizeof(sa46a->sa6.sin6_addr)); 1018#endif 1019} 1020 1021#if defined(LWS_WITH_SYS_STATE) 1022lws_state_manager_t * 1023lws_system_get_state_manager(struct lws_context *context) 1024{ 1025 return &context->mgr_system; 1026} 1027#endif 1028