diff options
| author | Garrett D'Amore <garrett@damore.org> | 2020-07-26 16:45:11 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2020-07-27 19:15:08 -0700 |
| commit | 09d667c49383edb980bcac88de1173c452066128 (patch) | |
| tree | a9732fcf561032c1a10fcc3a3067404046bcc3b7 /src/platform | |
| parent | 166981244eec7699190bf8b70c32ffe99e485b72 (diff) | |
| download | nng-09d667c49383edb980bcac88de1173c452066128.tar.gz nng-09d667c49383edb980bcac88de1173c452066128.tar.bz2 nng-09d667c49383edb980bcac88de1173c452066128.zip | |
fixes #844 WebSocket wildcard host errors
fixes #1224 wss fails on IPV6 address
This fixes bugs and inconsistencies in the way addresses are
handled for HTTP (and consequently websocket). The Host:
address line needs to look at numeric IPs and treat wildcards
as if they are not specified, and needs to understand the IPv6
address format using brackets (e.g. [::1]:80).
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/posix/posix_resolv_gai.c | 111 | ||||
| -rw-r--r-- | src/platform/windows/win_resolv.c | 104 |
2 files changed, 211 insertions, 4 deletions
diff --git a/src/platform/posix/posix_resolv_gai.c b/src/platform/posix/posix_resolv_gai.c index 5cec0570..88313045 100644 --- a/src/platform/posix/posix_resolv_gai.c +++ b/src/platform/posix/posix_resolv_gai.c @@ -1,5 +1,5 @@ // -// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -257,8 +257,9 @@ resolv_ip(const char *host, const char *serv, int passive, int family, // NB: must remain valid until this is completed. So we have to // keep our own copy. - if (host != NULL && nni_strnlen(host, sizeof(item->name_buf)) >= - sizeof(item->name_buf)) { + if (host != NULL && + nni_strnlen(host, sizeof(item->name_buf)) >= + sizeof(item->name_buf)) { NNI_FREE_STRUCT(item); nni_aio_finish_error(aio, NNG_EADDRINVAL); return; @@ -354,6 +355,110 @@ resolv_worker(void *unused) } int +parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) +{ + struct addrinfo hints; + struct addrinfo *results; + int rv; + bool v6 = false; + bool wrapped = false; + char * port; + char * host; + char * buf; + size_t buf_len; + + if (addr == NULL) { + addr = ""; + } + + buf_len = strlen(addr) + 1; + if ((buf = nni_alloc(buf_len)) == NULL) { + return (NNG_ENOMEM); + } + memcpy(buf, addr, buf_len); + host = buf; + if (*host == '[') { + v6 = true; + wrapped = true; + host++; + } else { + char *s; + for (s = host; *s != '\0'; s++) { + if (*s == '.') { + break; + } + if (*s == ':') { + v6 = true; + break; + } + } + } + for (port = host; *port != '\0'; port++) { + if (wrapped) { + if (*port == ']') { + *port++ = '\0'; + wrapped = false; + break; + } + } else if (!v6) { + if (*port == ':') { + break; + } + } + } + + if (wrapped) { + // Never got the closing bracket. + rv = NNG_EADDRINVAL; + goto done; + } + + if ((!want_port) && (*port != '\0')) { + rv = NNG_EADDRINVAL; + goto done; + } else if (*port == ':') { + *port++ = '\0'; + } + + if (*port == '\0') { + port = "0"; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST | AI_PASSIVE; + if (v6) { + hints.ai_family = AF_INET6; + } +#ifdef AI_ADDRCONFIG + hints.ai_flags |= AI_ADDRCONFIG; +#endif + + rv = getaddrinfo(host, port, &hints, &results); + if ((rv != 0) || (results == NULL)) { + rv = nni_plat_errno(rv); + goto done; + } + nni_posix_sockaddr2nn(sa, (void *) results->ai_addr); + freeaddrinfo(results); + +done: + nni_free(buf, buf_len); + return (rv); +} + +int +nni_parse_ip(const char *addr, nni_sockaddr *sa) +{ + return (parse_ip(addr, sa, false)); +} + +int +nni_parse_ip_port(const char *addr, nni_sockaddr *sa) +{ + return (parse_ip(addr, sa, true)); +} + +int nni_posix_resolv_sysinit(void) { nni_mtx_init(&resolv_mtx); diff --git a/src/platform/windows/win_resolv.c b/src/platform/windows/win_resolv.c index ff356700..d80b5ddf 100644 --- a/src/platform/windows/win_resolv.c +++ b/src/platform/windows/win_resolv.c @@ -1,5 +1,5 @@ // -// Copyright 2019 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -317,6 +317,108 @@ resolv_worker(void *notused) } int +parse_ip(const char *addr, nng_sockaddr *sa, bool want_port) +{ + struct addrinfo hints; + struct addrinfo *results; + int rv; + bool v6 = false; + bool wrapped = false; + char * port; + char * host; + char * buf; + size_t buf_len; + + if (addr == NULL) { + addr = ""; + } + + buf_len = strlen(addr) + 1; + if ((buf = nni_alloc(buf_len)) == NULL) { + return (NNG_ENOMEM); + } + memcpy(buf, addr, buf_len); + host = buf; + if (*host == '[') { + v6 = true; + wrapped = true; + host++; + } else { + char *s; + for (s = host; *s != '\0'; s++) { + if (*s == '.') { + break; + } + if (*s == ':') { + v6 = true; + break; + } + } + } + for (port = host; *port != '\0'; port++) { + if (wrapped) { + if (*port == ']') { + *port++ = '\0'; + wrapped = false; + break; + } + } else if (!v6) { + if (*port == ':') { + break; + } + } + } + + if (wrapped) { + // Never got the closing bracket. + rv = NNG_EADDRINVAL; + goto done; + } + + if ((!want_port) && (*port != '\0')) { + rv = NNG_EADDRINVAL; + goto done; + } else if (*port == ':') { + *port++ = '\0'; + } + + if (*port == '\0') { + port = "0"; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = + AI_ADDRCONFIG | AI_NUMERICSERV | AI_NUMERICHOST | AI_PASSIVE; + if (v6) { + hints.ai_family = AF_INET6; + } + + rv = getaddrinfo(host, port, &hints, &results); + if ((rv != 0) || (results == NULL)) { + rv = nni_win_error(rv); + goto done; + } + nni_win_sockaddr2nn(sa, (void *) results->ai_addr); + freeaddrinfo(results); + +done: + nni_free(buf, buf_len); + return (rv); +} + +int +nni_parse_ip(const char *addr, nni_sockaddr *sa) +{ + return (parse_ip(addr, sa, false)); +} + +int +nni_parse_ip_port(const char *addr, nni_sockaddr *sa) +{ + return (parse_ip(addr, sa, true)); +} + +int nni_win_resolv_sysinit(void) { nni_mtx_init(&resolv_mtx); |
