summaryrefslogtreecommitdiffstats
path: root/src/privsep-root.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-09-30 17:25:32 +0100
committerRoy Marples <roy@marples.name>2020-09-30 17:25:32 +0100
commitc4c15d9a6423827ea80cc537e6f7fcf7d6fc172d (patch)
tree5dbd87c6936b170bb34a7c372f3299ad4f316978 /src/privsep-root.c
parent3ef993986b2ac5aca49ecf10f04fe5fc067473cd (diff)
downloaddhcpcd-c4c15d9a6423827ea80cc537e6f7fcf7d6fc172d.tar.xz
privsep: We now need to carry ifa_data for BSD
Diffstat (limited to 'src/privsep-root.c')
-rw-r--r--src/privsep-root.c58
1 files changed, 41 insertions, 17 deletions
diff --git a/src/privsep-root.c b/src/privsep-root.c
index 92faec4c..770dd953 100644
--- a/src/privsep-root.c
+++ b/src/privsep-root.c
@@ -346,15 +346,14 @@ ps_root_monordm(uint64_t *rdm, size_t len)
#endif
#ifdef PRIVSEP_GETIFADDRS
-#define IFA_NADDRS 3
+#define IFA_NADDRS 4
static ssize_t
ps_root_dogetifaddrs(void **rdata, size_t *rlen)
{
- struct ifaddrs *ifaddrs, *ifa, *ifa_next;
+ struct ifaddrs *ifaddrs, *ifa;
size_t len;
uint8_t *buf, *sap;
socklen_t salen;
- void *ifa_data;
if (getifaddrs(&ifaddrs) == -1)
return -1;
@@ -380,6 +379,15 @@ ps_root_dogetifaddrs(void **rdata, size_t *rlen)
len += ALIGN(sa_len(ifa->ifa_netmask));
if (ifa->ifa_broadaddr != NULL)
len += ALIGN(sa_len(ifa->ifa_broadaddr));
+#ifdef BSD
+ /*
+ * On BSD we need to carry ifa_data so we can access
+ * if_data->ifi_link_state
+ */
+ if (ifa->ifa_addr != NULL &&
+ ifa->ifa_addr->sa_family == AF_LINK)
+ len += ALIGN(sizeof(struct if_data));
+#endif
}
/* Use calloc to set everything to zero.
@@ -394,15 +402,8 @@ ps_root_dogetifaddrs(void **rdata, size_t *rlen)
*rlen = len;
for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
- /* Don't carry ifa_data or ifa_next. */
- ifa_data = ifa->ifa_data;
- ifa_next = ifa->ifa_next;
- ifa->ifa_data = NULL;
- ifa->ifa_next = NULL;
memcpy(buf, ifa, sizeof(*ifa));
buf += ALIGN(sizeof(*ifa));
- ifa->ifa_data = ifa_data;
- ifa->ifa_next = ifa_next;
strlcpy((char *)buf, ifa->ifa_name, IFNAMSIZ);
buf += ALIGN(IFNAMSIZ);
@@ -411,7 +412,10 @@ ps_root_dogetifaddrs(void **rdata, size_t *rlen)
#define COPYINSA(addr) \
do { \
- salen = sa_len((addr)); \
+ if ((addr) != NULL) \
+ salen = sa_len((addr)); \
+ else \
+ salen = 0; \
if (salen != 0) { \
memcpy(sap, &salen, sizeof(salen)); \
memcpy(buf, (addr), salen); \
@@ -420,12 +424,21 @@ ps_root_dogetifaddrs(void **rdata, size_t *rlen)
sap += sizeof(salen); \
} while (0 /*CONSTCOND */)
- if (ifa->ifa_addr != NULL)
- COPYINSA(ifa->ifa_addr);
- if (ifa->ifa_netmask != NULL)
- COPYINSA(ifa->ifa_netmask);
- if (ifa->ifa_broadaddr != NULL)
- COPYINSA(ifa->ifa_broadaddr);
+ COPYINSA(ifa->ifa_addr);
+ COPYINSA(ifa->ifa_netmask);
+ COPYINSA(ifa->ifa_broadaddr);
+
+#ifdef BSD
+ if (ifa->ifa_addr != NULL &&
+ ifa->ifa_addr->sa_family == AF_LINK)
+ {
+ salen = (socklen_t)sizeof(struct if_data);
+ memcpy(buf, ifa->ifa_data, salen);
+ buf += ALIGN(salen);
+ } else
+#endif
+ salen = 0;
+ memcpy(sap, &salen, sizeof(salen));
}
freeifaddrs(ifaddrs);
@@ -948,6 +961,17 @@ ps_root_getifaddrs(struct dhcpcd_ctx *ctx, struct ifaddrs **ifahead)
COPYOUTSA(ifa->ifa_addr);
COPYOUTSA(ifa->ifa_netmask);
COPYOUTSA(ifa->ifa_broadaddr);
+
+ memcpy(&salen, sap, sizeof(salen));
+ if (len < salen)
+ goto err;
+ if (salen != 0) {
+ ifa->ifa_data = bp;
+ bp += ALIGN(salen);
+ len -= ALIGN(salen);
+ } else
+ ifa->ifa_data = NULL;
+
if (len != 0)
ifa->ifa_next = (struct ifaddrs *)(void *)bp;
else