Mercurial > dovecot > core-2.2
changeset 19680:55831f9d2e66
lib: Added net_str2hostport()
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Fri, 29 Jan 2016 17:32:30 +0200 |
parents | 74f8b5be8f59 |
children | 5a3aac8f8ee1 |
files | src/lib/net.c src/lib/net.h src/lib/test-net.c |
diffstat | 3 files changed, 92 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/net.c Fri Jan 29 16:23:57 2016 +0200 +++ b/src/lib/net.c Fri Jan 29 17:32:30 2016 +0200 @@ -977,6 +977,42 @@ return 0; } +int net_str2hostport(const char *str, in_port_t default_port, + const char **host_r, in_port_t *port_r) +{ + const char *p, *host; + in_port_t port; + + if (str[0] == '[') { + /* [IPv6] address, possibly followed by :port */ + p = strchr(str, ']'); + if (p == NULL) + return -1; + host = t_strdup_until(str+1, p++); + } else { + p = strchr(str, ':'); + if (p == NULL || strchr(p+1, ':') != NULL) { + /* host or IPv6 address */ + *host_r = str; + *port_r = default_port; + return 0; + } + host = t_strdup_until(str, p); + } + if (p[0] == '\0') { + *host_r = host; + *port_r = default_port; + return 0; + } + if (p[0] != ':') + return -1; + if (net_str2port(p+1, &port) < 0) + return -1; + *host_r = host; + *port_r = port; + return 0; +} + int net_ipv6_mapped_ipv4_convert(const struct ip_addr *src, struct ip_addr *dest) {
--- a/src/lib/net.h Fri Jan 29 16:23:57 2016 +0200 +++ b/src/lib/net.h Fri Jan 29 17:32:30 2016 +0200 @@ -152,6 +152,13 @@ int net_str2port(const char *str, in_port_t *port_r); /* char* -> net_port_t translation (allows port zero) */ int net_str2port_zero(const char *str, in_port_t *port_r); +/* Parse "host", "host:port", "IPv4", "IPv4:port", "IPv6", "[IPv6]" or + "[IPv6]:port" to its host and port components. [IPv6] address is returned + without []. If no port is given, return default_port. The :port in the + parsed string isn't allowed to be zero, but default_port=0 is passed + through. */ +int net_str2hostport(const char *str, in_port_t default_port, + const char **host_r, in_port_t *port_r); /* Convert IPv6 mapped IPv4 address to an actual IPv4 address. Returns 0 if successful, -1 if the source address isn't IPv6 mapped IPv4 address. */
--- a/src/lib/test-net.c Fri Jan 29 16:23:57 2016 +0200 +++ b/src/lib/test-net.c Fri Jan 29 17:32:30 2016 +0200 @@ -84,8 +84,57 @@ test_end(); } +static void test_net_str2hostport(void) +{ + const char *host; + in_port_t port; + + test_begin("net_str2hostport()"); + /* [IPv6] */ + test_assert(net_str2hostport("[1::4]", 0, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 0); + test_assert(net_str2hostport("[1::4]", 1234, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 1234); + test_assert(net_str2hostport("[1::4]:78", 1234, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 78); + host = NULL; + test_assert(net_str2hostport("[1::4]:", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("[1::4]:0", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("[1::4]:x", 1234, &host, &port) < 0 && host == NULL); + /* IPv6 */ + test_assert(net_str2hostport("1::4", 0, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 0); + test_assert(net_str2hostport("1::4", 1234, &host, &port) == 0 && + strcmp(host, "1::4") == 0 && port == 1234); + /* host */ + test_assert(net_str2hostport("foo", 0, &host, &port) == 0 && + strcmp(host, "foo") == 0 && port == 0); + test_assert(net_str2hostport("foo", 1234, &host, &port) == 0 && + strcmp(host, "foo") == 0 && port == 1234); + test_assert(net_str2hostport("foo:78", 1234, &host, &port) == 0 && + strcmp(host, "foo") == 0 && port == 78); + host = NULL; + test_assert(net_str2hostport("foo:", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("foo:0", 1234, &host, &port) < 0 && host == NULL); + test_assert(net_str2hostport("foo:x", 1234, &host, &port) < 0 && host == NULL); + /* edge cases with multiple ':' - currently these don't return errors, + but perhaps they should. */ + test_assert(net_str2hostport("foo::78", 1234, &host, &port) == 0 && + strcmp(host, "foo::78") == 0 && port == 1234); + test_assert(net_str2hostport("::foo:78", 1234, &host, &port) == 0 && + strcmp(host, "::foo:78") == 0 && port == 1234); + test_assert(net_str2hostport("[::foo]:78", 1234, &host, &port) == 0 && + strcmp(host, "::foo") == 0 && port == 78); + test_assert(net_str2hostport("[::::]", 1234, &host, &port) == 0 && + strcmp(host, "::::") == 0 && port == 1234); + test_assert(net_str2hostport("[::::]:78", 1234, &host, &port) == 0 && + strcmp(host, "::::") == 0 && port == 78); + test_end(); +} + void test_net(void) { test_net_is_in_network(); test_net_ip2addr(); + test_net_str2hostport(); }