summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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;
}