summaryrefslogtreecommitdiff
path: root/src/basic/in-addr-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/in-addr-util.c')
-rw-r--r--src/basic/in-addr-util.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c
index aed7601d50..411efb242b 100644
--- a/src/basic/in-addr-util.c
+++ b/src/basic/in-addr-util.c
@@ -314,6 +314,7 @@ int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union
}
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) {
+ _cleanup_free_ char *buf = NULL;
const char *suffix;
int r, ifi = 0;
@@ -341,7 +342,11 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
}
}
- s = strndupa(s, suffix - s);
+ buf = strndup(s, suffix - s);
+ if (!buf)
+ return -ENOMEM;
+
+ s = buf;
}
r = in_addr_from_string_auto(s, family, ret);
@@ -357,7 +362,7 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
unsigned char in4_addr_netmask_to_prefixlen(const struct in_addr *addr) {
assert(addr);
- return 32 - u32ctz(be32toh(addr->s_addr));
+ return 32U - u32ctz(be32toh(addr->s_addr));
}
struct in_addr* in4_addr_prefixlen_to_netmask(struct in_addr *addr, unsigned char prefixlen) {
@@ -490,12 +495,14 @@ int in_addr_parse_prefixlen(int family, const char *p, unsigned char *ret) {
return 0;
}
-int in_addr_prefix_from_string(
+int in_addr_prefix_from_string_internal(
const char *p,
+ bool use_default_prefixlen,
int family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
+ _cleanup_free_ char *str = NULL;
union in_addr_union buffer;
const char *e, *l;
unsigned char k;
@@ -507,9 +514,13 @@ int in_addr_prefix_from_string(
return -EAFNOSUPPORT;
e = strchr(p, '/');
- if (e)
- l = strndupa(p, e - p);
- else
+ if (e) {
+ str = strndup(p, e - p);
+ if (!str)
+ return -ENOMEM;
+
+ l = str;
+ } else
l = p;
r = in_addr_from_string(family, l, &buffer);
@@ -520,6 +531,13 @@ int in_addr_prefix_from_string(
r = in_addr_parse_prefixlen(family, e+1, &k);
if (r < 0)
return r;
+ } else if (use_default_prefixlen) {
+ if (family == AF_INET) {
+ r = in4_addr_default_prefixlen(&buffer.in, &k);
+ if (r < 0)
+ return r;
+ } else
+ k = 0;
} else
k = FAMILY_ADDRESS_SIZE(family) * 8;
@@ -531,12 +549,14 @@ int in_addr_prefix_from_string(
return 0;
}
-int in_addr_prefix_from_string_auto(
+int in_addr_prefix_from_string_auto_internal(
const char *p,
+ bool use_default_prefixlen,
int *ret_family,
union in_addr_union *ret_prefix,
unsigned char *ret_prefixlen) {
+ _cleanup_free_ char *str = NULL;
union in_addr_union buffer;
const char *e, *l;
unsigned char k;
@@ -545,9 +565,13 @@ int in_addr_prefix_from_string_auto(
assert(p);
e = strchr(p, '/');
- if (e)
- l = strndupa(p, e - p);
- else
+ if (e) {
+ str = strndup(p, e - p);
+ if (!str)
+ return -ENOMEM;
+
+ l = str;
+ } else
l = p;
r = in_addr_from_string_auto(l, &family, &buffer);
@@ -558,6 +582,13 @@ int in_addr_prefix_from_string_auto(
r = in_addr_parse_prefixlen(family, e+1, &k);
if (r < 0)
return r;
+ } else if (use_default_prefixlen) {
+ if (family == AF_INET) {
+ r = in4_addr_default_prefixlen(&buffer.in, &k);
+ if (r < 0)
+ return r;
+ } else
+ k = 0;
} else
k = FAMILY_ADDRESS_SIZE(family) * 8;
@@ -571,3 +602,20 @@ int in_addr_prefix_from_string_auto(
return 0;
}
+
+static void in_addr_data_hash_func(const struct in_addr_data *a, struct siphash *state) {
+ siphash24_compress(&a->family, sizeof(a->family), state);
+ siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
+}
+
+static int in_addr_data_compare_func(const struct in_addr_data *x, const struct in_addr_data *y) {
+ int r;
+
+ r = CMP(x->family, y->family);
+ if (r != 0)
+ return r;
+
+ return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
+}
+
+DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);