From 17600d6d6ef0edf60bbf64c5bef594a8a07547cc Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Tue, 19 Oct 2021 09:01:27 +0200
Subject: netlink, conf: Actually get prefix/mask length

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
 conf.c    | 10 ++++++++--
 netlink.c | 13 ++++++++-----
 netlink.h |  2 +-
 pasta.c   |  9 +++++++--
 4 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/conf.c b/conf.c
index 4287630..8e96368 100644
--- a/conf.c
+++ b/conf.c
@@ -469,7 +469,11 @@ static void conf_ip(struct ctx *c)
 			nl_route(0, c->ifi, AF_INET, &c->gw4);
 
 		if (!c->addr4) {
-			nl_addr(0, c->ifi, AF_INET, &c->addr4, 0, NULL);
+			int mask_len = 0;
+
+			nl_addr(0, c->ifi, AF_INET, &c->addr4, &mask_len, NULL);
+			c->mask4 = htonl(0xffffffff << (32 - mask_len));
+
 			if (!c->mask4) {
 				if (IN_CLASSA(ntohl(c->addr4)))
 					c->mask4 = htonl(IN_CLASSA_NET);
@@ -492,12 +496,14 @@ static void conf_ip(struct ctx *c)
 		memset(&c->mac_guest, 0xff, sizeof(c->mac_guest));
 
 	if (v6 != IP_VERSION_DISABLED) {
+		int prefix_len = 0;
+
 		if (IN6_IS_ADDR_UNSPECIFIED(&c->gw6))
 			nl_route(0, c->ifi, AF_INET6, &c->gw6);
 
 		nl_addr(0, c->ifi, AF_INET6,
 			IN6_IS_ADDR_UNSPECIFIED(&c->addr6) ? &c->addr6 : NULL,
-			0, &c->addr6_ll);
+			&prefix_len, &c->addr6_ll);
 
 		memcpy(&c->addr6_seen, &c->addr6, sizeof(c->addr4_seen));
 		memcpy(&c->addr6_ll_seen, &c->addr6, sizeof(c->addr4_seen));
diff --git a/netlink.c b/netlink.c
index 4faa697..10d8a92 100644
--- a/netlink.c
+++ b/netlink.c
@@ -346,10 +346,11 @@ next:
  * @ifi:	Interface index
  * @af:		Address family
  * @addr:	Global address to fill if zero, to set if not, ignored if NULL
+ * @prefix_len:	Mask or prefix length, set or fetched (for IPv4)
  * @addr_l:	Link-scoped address to fill, NULL if not requested
  */
 void nl_addr(int ns, unsigned int ifi, sa_family_t af,
-	     void *addr, int prefix_len, void *addr_l)
+	     void *addr, int *prefix_len, void *addr_l)
 {
 	int set = addr && ((af == AF_INET6 && !IN6_IS_ADDR_UNSPECIFIED(addr)) ||
 			   (af == AF_INET && *(uint32_t *)addr));
@@ -380,7 +381,7 @@ void nl_addr(int ns, unsigned int ifi, sa_family_t af,
 
 		.ifa.ifa_family    = af,
 		.ifa.ifa_index     = ifi,
-		.ifa.ifa_prefixlen = prefix_len,
+		.ifa.ifa_prefixlen = *prefix_len,
 	};
 	struct ifaddrmsg *ifa;
 	struct nlmsghdr *nh;
@@ -430,12 +431,14 @@ void nl_addr(int ns, unsigned int ifi, sa_family_t af,
 			if (rta->rta_type != IFA_ADDRESS)
 				continue;
 
-			if (af == AF_INET && addr && !*(uint32_t *)addr)
+			if (af == AF_INET && addr && !*(uint32_t *)addr) {
 				memcpy(addr, RTA_DATA(rta), RTA_PAYLOAD(rta));
-			else if (af == AF_INET6 && addr &&
+				*prefix_len = ifa->ifa_prefixlen;
+			} else if (af == AF_INET6 && addr &&
 				 ifa->ifa_scope == RT_SCOPE_UNIVERSE &&
-				 IN6_IS_ADDR_UNSPECIFIED(addr))
+				 IN6_IS_ADDR_UNSPECIFIED(addr)) {
 				memcpy(addr, RTA_DATA(rta), RTA_PAYLOAD(rta));
+			}
 
 			if (addr_l &&
 			    af == AF_INET6 && ifa->ifa_scope == RT_SCOPE_LINK &&
diff --git a/netlink.h b/netlink.h
index 460c2f1..840e451 100644
--- a/netlink.h
+++ b/netlink.h
@@ -2,5 +2,5 @@ int nl_sock_init(struct ctx *c);
 unsigned int nl_get_ext_if(int *v4, int *v6);
 void nl_route(int ns, unsigned int ifi, sa_family_t af, void *gw);
 void nl_addr(int ns, unsigned int ifi, sa_family_t af,
-	     void *addr, int prefix_len, void *addr_l);
+	     void *addr, int *prefix_len, void *addr_l);
 void nl_link(int ns, unsigned int ifi, void *mac, int up, int mtu);
diff --git a/pasta.c b/pasta.c
index b609e36..fe0bf0e 100644
--- a/pasta.c
+++ b/pasta.c
@@ -233,16 +233,21 @@ void pasta_ns_conf(struct ctx *c)
 	nl_link(1, 1 /* lo */, MAC_ZERO, 1, 0);
 
 	if (c->pasta_conf_ns) {
+		int prefix_len;
+
 		nl_link(1, c->pasta_ifi, c->mac_guest, 1, c->mtu);
 
 		if (c->v4) {
+			prefix_len = __builtin_popcount(c->mask4);
 			nl_addr(1, c->pasta_ifi, AF_INET, &c->addr4,
-				__builtin_popcount(c->mask4), NULL);
+				&prefix_len, NULL);
 			nl_route(1, c->pasta_ifi, AF_INET, &c->gw4);
 		}
 
 		if (c->v6) {
-			nl_addr(1, c->pasta_ifi, AF_INET6, &c->addr6, 64, NULL);
+			prefix_len = 64;
+			nl_addr(1, c->pasta_ifi, AF_INET6, &c->addr6,
+				&prefix_len, NULL);
 			nl_route(1, c->pasta_ifi, AF_INET6, &c->gw6);
 		}
 	} else {
-- 
cgit v1.2.3