summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>2018-05-09 11:13:54 +1000
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>2018-07-10 14:00:08 +1000
commitbecf2b28d8b0aa561ac7e42db519071f8065d37f (patch)
tree0dfcc6ef5cbcf1a433ec2f116de119b1c5742f07
parent99a1f905f585480cca2c9a43ab18ed8e37365192 (diff)
downloadtalos-petitboot-becf2b28d8b0aa561ac7e42db519071f8065d37f.tar.gz
talos-petitboot-becf2b28d8b0aa561ac7e42db519071f8065d37f.zip
lib: Add support and helpers for IPv6 host addresses
Recognise IPv6 addresses and URLs, and allow an interface_info struct to have both an IPv4 and IPv6 address. The addr_scheme() helper returns the address family of a given address. Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
-rw-r--r--lib/pb-protocol/pb-protocol.c6
-rw-r--r--lib/types/types.h1
-rw-r--r--lib/url/url.c45
-rw-r--r--lib/url/url.h2
-rw-r--r--test/urls/Makefile.am3
-rw-r--r--test/urls/data/ipv6-full.test7
-rw-r--r--test/urls/data/ipv6-multidirs.test7
-rw-r--r--test/urls/data/ipv6-noport.test7
8 files changed, 72 insertions, 6 deletions
diff --git a/lib/pb-protocol/pb-protocol.c b/lib/pb-protocol/pb-protocol.c
index 8e37348..41707da 100644
--- a/lib/pb-protocol/pb-protocol.c
+++ b/lib/pb-protocol/pb-protocol.c
@@ -253,7 +253,8 @@ int pb_protocol_system_info_len(const struct system_info *sysinfo)
len += 4 + if_info->hwaddr_size +
4 + optional_strlen(if_info->name) +
sizeof(if_info->link) +
- 4 + optional_strlen(if_info->address);
+ 4 + optional_strlen(if_info->address) +
+ 4 + optional_strlen(if_info->address_v6);
}
for (i = 0; i < sysinfo->n_blockdevs; i++) {
@@ -509,6 +510,7 @@ int pb_protocol_serialise_system_info(const struct system_info *sysinfo,
pos += sizeof(bool);
pos += pb_protocol_serialise_string(pos, if_info->address);
+ pos += pb_protocol_serialise_string(pos, if_info->address_v6);
}
*(uint32_t *)pos = __cpu_to_be32(sysinfo->n_blockdevs);
@@ -1046,6 +1048,8 @@ int pb_protocol_deserialise_system_info(struct system_info *sysinfo,
if (read_string(if_info, &pos, &len, &if_info->address))
goto out;
+ if (read_string(if_info, &pos, &len, &if_info->address_v6))
+ goto out;
sysinfo->interfaces[i] = if_info;
}
diff --git a/lib/types/types.h b/lib/types/types.h
index 9ab2a43..5f99b58 100644
--- a/lib/types/types.h
+++ b/lib/types/types.h
@@ -110,6 +110,7 @@ struct interface_info {
char *name;
bool link;
char *address;
+ char *address_v6;
};
struct blockdev_info {
diff --git a/lib/url/url.c b/lib/url/url.c
index 6eeced3..f0e8b0e 100644
--- a/lib/url/url.c
+++ b/lib/url/url.c
@@ -197,19 +197,35 @@ struct pb_url *pb_url_parse(void *ctx, const char *url_str)
goto fail;
}
- col = strchr(p, ':');
+ col = strrchr(p, ':');
+ if (col <= p)
+ col = NULL;
+ if (col && strchr(col , ']')) {
+ /*
+ * This is likely an IPv6 address with no port.
+ * See https://www.ietf.org/rfc/rfc2732.txt
+ */
+ col = NULL;
+ }
if (col) {
len = path - col - 1;
url->port = len ? talloc_strndup(url, col + 1, len)
: NULL;
len = col - p;
- url->host = len ? talloc_strndup(url, p, len) : NULL;
} else {
url->port = NULL;
- url->host = talloc_strndup(url, p, path - p);
+ len = path - p;
}
+ if (p[0] == '[' && p[len - 1] == ']')
+ /* IPv6 */
+ url->host = talloc_strndup(url, p + 1, len - 2);
+ else
+ /* IPv4 */
+ url->host = talloc_strndup(url, p, len);
+
+
/* remove multiple leading slashes */
for (; *path && *(path+1) == '/'; path++)
;
@@ -231,13 +247,32 @@ bool is_url(const char *str)
return strstr(str, "://") != NULL;
}
+int addr_scheme(const char *address)
+{
+ uint8_t buf[sizeof(struct in6_addr)];
+ int rc;
+
+ rc = inet_pton(AF_INET, address , buf);
+ if (rc == 1)
+ return AF_INET;
+ rc = inet_pton(AF_INET6, address , buf);
+ if (rc == 1)
+ return AF_INET6;
+
+ return 0;
+}
+
char *pb_url_to_string(struct pb_url *url)
{
const struct pb_scheme_info *scheme = pb_url_scheme_info(url->scheme);
assert(scheme);
- return talloc_asprintf(url, "%s://%s%s", scheme->str,
- scheme->has_host ? url->host : "", url->path);
+ if (scheme->has_host && addr_scheme(url->host) == AF_INET6)
+ return talloc_asprintf(url, "%s://[%s]%s", scheme->str,
+ url->host, url->path);
+ else
+ return talloc_asprintf(url, "%s://%s%s", scheme->str,
+ scheme->has_host ? url->host : "", url->path);
}
static void pb_url_update_full(struct pb_url *url)
diff --git a/lib/url/url.h b/lib/url/url.h
index 9043615..49dff4a 100644
--- a/lib/url/url.h
+++ b/lib/url/url.h
@@ -19,6 +19,7 @@
#if !defined(_PB_URL_PARSER_H)
#define _PB_URL_PARSER_H
+#include <arpa/inet.h>
#include <stdbool.h>
/**
@@ -61,6 +62,7 @@ struct pb_url {
};
bool is_url(const char *str);
+int addr_scheme(const char *address);
struct pb_url *pb_url_parse(void *ctx, const char *url_str);
struct pb_url *pb_url_copy(void *ctx, const struct pb_url *url);
struct pb_url *pb_url_join(void *ctx, const struct pb_url *url, const char *s);
diff --git a/test/urls/Makefile.am b/test/urls/Makefile.am
index ad670b8..aab0f2b 100644
--- a/test/urls/Makefile.am
+++ b/test/urls/Makefile.am
@@ -20,6 +20,9 @@ test_urls_parse_url_LDADD = $(core_lib)
url_TESTS = \
test/urls/data/double-slash.test \
test/urls/data/http-simple.test \
+ test/urls/data/ipv6-full.test \
+ test/urls/data/ipv6-multidirs.test \
+ test/urls/data/ipv6-noport.test \
test/urls/data/join-full.test \
test/urls/data/join-absolute.test \
test/urls/data/join-relative.test \
diff --git a/test/urls/data/ipv6-full.test b/test/urls/data/ipv6-full.test
new file mode 100644
index 0000000..b4943eb
--- /dev/null
+++ b/test/urls/data/ipv6-full.test
@@ -0,0 +1,7 @@
+http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html
+scheme http
+host FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
+port 80
+path /index.html
+dir /
+file index.html
diff --git a/test/urls/data/ipv6-multidirs.test b/test/urls/data/ipv6-multidirs.test
new file mode 100644
index 0000000..68b852a
--- /dev/null
+++ b/test/urls/data/ipv6-multidirs.test
@@ -0,0 +1,7 @@
+tftp://[fd69:d65f:b8b5:61::1]/installers/ubuntu-18.04/vmlinux
+scheme tftp
+host fd69:d65f:b8b5:61::1
+port (null)
+path /installers/ubuntu-18.04/vmlinux
+dir /installers/ubuntu-18.04/
+file vmlinux
diff --git a/test/urls/data/ipv6-noport.test b/test/urls/data/ipv6-noport.test
new file mode 100644
index 0000000..bd3b008
--- /dev/null
+++ b/test/urls/data/ipv6-noport.test
@@ -0,0 +1,7 @@
+http://[1080:0:0:0:8:800:200C:417A]/index.html
+scheme http
+host 1080:0:0:0:8:800:200C:417A
+port (null)
+path /index.html
+dir /
+file index.html
OpenPOWER on IntegriCloud