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>
.free = simple_device_free,
};
.free = simple_device_free,
};
device_merge_settings(struct device *dev, struct device_settings *n)
{
struct device_settings *os = &dev->orig_settings;
device_merge_settings(struct device *dev, struct device_settings *n)
{
struct device_settings *os = &dev->orig_settings;
struct device_type *device_type_get(const char *tname);
struct device *device_create(const char *name, struct device_type *type,
struct blob_attr *config);
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);
void device_init_settings(struct device *dev, struct blob_attr **tb);
void device_init_pending(void);
addr->s6_addr32[3] = (uint32_t)mrand48();
}
addr->s6_addr32[3] = (uint32_t)mrand48();
}
eui64_ifaceid(struct interface *iface, struct in6_addr *addr)
{
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;
/* get mac address */
uint8_t *macaddr = iface->l3_dev.dev->settings.macaddr;
uint8_t *ifaceid = addr->s6_addr + 8;
ifaceid[3] = 0xff;
ifaceid[4] = 0xfe;
ifaceid[0] ^= 0x02;
ifaceid[3] = 0xff;
ifaceid[4] = 0xfe;
ifaceid[0] ^= 0x02;
generate_ifaceid(struct interface *iface, struct in6_addr *addr)
{
generate_ifaceid(struct interface *iface, struct in6_addr *addr)
{
/* generate new iface id */
switch (iface->assignment_iface_id_selection) {
case IFID_FIXED:
/* generate new iface id */
switch (iface->assignment_iface_id_selection) {
case IFID_FIXED:
break;
case IFID_EUI64:
/* eui64 */
break;
case IFID_EUI64:
/* eui64 */
- eui64_ifaceid(iface, addr);
+ ret = eui64_ifaceid(iface, addr);
+ break;
+ default:
+ ret = false;
system_del_route(l3_downlink, &route);
system_add_address(l3_downlink, &addr);
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);
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;
}
assignment->addr = addr.addr.in6;
route.addr = addr.addr;
}