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)
{
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. */
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();
}