summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorHans Dedecker <dedeckeh@gmail.com>2017-12-14 14:13:35 +0100
committerHans Dedecker <dedeckeh@gmail.com>2017-12-15 17:21:12 +0100
commit4268193c90bdd1532ee0555dd109a43eb8524b04 (patch)
tree01446f86506959daa1e2007d2753a2fa79bb24b4
parent81ff6d120e8c247b7c714daefd45ae7b90e3b643 (diff)
interface-ip: harden eui64 IPv6 prefix address generation
Check if a mac address is actually present when generating an eui64 based IPv6 address; in case of failure bail out. At the same time make sure the active mac address is used as input for the eui64 based IPv6 address and guarantee IPv6 prefix address generation is based on the actual config by resetting the IPv6 prefix address in the assignment structure when it gets deleted. Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
-rw-r--r--device.c2
-rw-r--r--device.h1
-rw-r--r--interface-ip.c26
3 files changed, 24 insertions, 5 deletions
diff --git a/device.c b/device.c
index 0424658..a851037 100644
--- a/device.c
+++ b/device.c
@@ -193,7 +193,7 @@ struct device_type simple_device_type = {
.free = simple_device_free,
};
-static void
+void
device_merge_settings(struct device *dev, struct device_settings *n)
{
struct device_settings *os = &dev->orig_settings;
diff --git a/device.h b/device.h
index f398dbc..07f1dbd 100644
--- a/device.h
+++ b/device.h
@@ -244,6 +244,7 @@ int device_type_add(struct device_type *devtype);
struct device_type *device_type_get(const char *tname);
struct device *device_create(const char *name, struct device_type *type,
struct blob_attr *config);
+void device_merge_settings(struct device *dev, struct device_settings *n);
void device_init_settings(struct device *dev, struct blob_attr **tb);
void device_init_pending(void);
diff --git a/interface-ip.c b/interface-ip.c
index 716a093..dcf3390 100644
--- a/interface-ip.c
+++ b/interface-ip.c
@@ -712,9 +712,16 @@ random_ifaceid(struct in6_addr *addr)
addr->s6_addr32[3] = (uint32_t)mrand48();
}
-static void
+static bool
eui64_ifaceid(struct interface *iface, struct in6_addr *addr)
{
+ struct device_settings st;
+
+ device_merge_settings(iface->l3_dev.dev, &st);
+
+ if (!(st.flags & DEV_OPT_MACADDR))
+ return false;
+
/* get mac address */
uint8_t *macaddr = iface->l3_dev.dev->settings.macaddr;
uint8_t *ifaceid = addr->s6_addr + 8;
@@ -723,11 +730,15 @@ eui64_ifaceid(struct interface *iface, struct in6_addr *addr)
ifaceid[3] = 0xff;
ifaceid[4] = 0xfe;
ifaceid[0] ^= 0x02;
+
+ return true;
}
-static void
+static bool
generate_ifaceid(struct interface *iface, struct in6_addr *addr)
{
+ bool ret = true;
+
/* generate new iface id */
switch (iface->assignment_iface_id_selection) {
case IFID_FIXED:
@@ -741,9 +752,13 @@ generate_ifaceid(struct interface *iface, struct in6_addr *addr)
break;
case IFID_EUI64:
/* eui64 */
- eui64_ifaceid(iface, addr);
+ ret = eui64_ifaceid(iface, addr);
+ break;
+ default:
+ ret = false;
break;
}
+ return ret;
}
static void
@@ -797,12 +812,15 @@ interface_set_prefix_address(struct device_prefix_assignment *assignment,
system_del_route(l3_downlink, &route);
system_add_address(l3_downlink, &addr);
+ assignment->addr = in6addr_any;
assignment->enabled = false;
} else if (add && (iface->state == IFS_UP || iface->state == IFS_SETUP)) {
if (IN6_IS_ADDR_UNSPECIFIED(&addr.addr.in6)) {
addr.addr.in6 = prefix->addr;
addr.addr.in6.s6_addr32[1] |= htonl(assignment->assigned);
- generate_ifaceid(iface, &addr.addr.in6);
+ if (!generate_ifaceid(iface, &addr.addr.in6))
+ return;
+
assignment->addr = addr.addr.in6;
route.addr = addr.addr;
}