struct vlist_tree interfaces;
static LIST_HEAD(iface_all_users);
-static unsigned int interface_serial = 0;
enum {
IFACE_ATTR_IFNAME,
if (!blobmsg_check_attr(data, true))
return UBUS_STATUS_INVALID_ARGUMENT;
- n = calloc(1, sizeof(*n) + blob_pad_len(data));
- memcpy(n->data, data, blob_pad_len(data));
- n->node.key = blobmsg_name(n->data);
+ const char *name = blobmsg_name(data);
+ unsigned len = blob_pad_len(data);
+
+ o = avl_find_element(&iface->data, name, o, node);
+ if (o) {
+ if (blob_pad_len(o->data) == len && !memcmp(o->data, data, len))
+ return 0;
- o = avl_find_element(&iface->data, n->node.key, o, node);
- if (o)
interface_data_del(iface, o);
+ }
+ n = calloc(1, sizeof(*n) + len);
+ memcpy(n->data, data, len);
+ n->node.key = blobmsg_name(n->data);
avl_insert(&iface->data, &n->node);
+
+ iface->updated |= IUF_DATA;
return 0;
}
void
__interface_set_down(struct interface *iface, bool force)
{
- switch (iface->state) {
+ enum interface_state state = iface->state;
+ switch (state) {
case IFS_UP:
- interface_event(iface, IFEV_DOWN);
case IFS_SETUP:
iface->state = IFS_TEARDOWN;
+ if (state == IFS_UP)
+ interface_event(iface, IFEV_DOWN);
+
interface_proto_event(iface->proto, PROTO_CMD_TEARDOWN, force);
if (force)
interface_flush_state(iface);
}
break;
case IFS_DOWN:
- if (iface->enabled && iface->link_state && !config_init)
+ if (iface->autostart && iface->enabled && iface->link_state && !config_init)
__interface_set_up(iface);
break;
default:
case DEV_EVENT_LINK_DOWN:
interface_set_link_state(iface, new_state);
break;
+ case DEV_EVENT_TOPO_CHANGE:
+ interface_proto_event(iface->proto, PROTO_CMD_RENEW, false);
+ return;
default:
break;
}
mark_interface_down(iface);
if (iface->main_dev.dev)
device_release(&iface->main_dev);
+ if (iface->l3_dev.dev)
+ device_remove_user(&iface->l3_dev);
interface_handle_config_change(iface);
break;
case IFPEV_LINK_LOST:
mark_interface_down(iface);
iface->state = IFS_SETUP;
break;
+ default:
+ return;
}
interface_write_resolv_conf();
DPRINTF("Failed to resolve routing table: %s\n", (char *) blobmsg_data(cur));
}
- // Set a default exteranl routing table for IPv6 to do source-based-filtering
- struct interface *iface_old = vlist_find(&interfaces, name, iface_old, node);
- if (iface_old && iface_old->ip6table > 1000 && iface_old->ip6table < 2000)
- iface->ip6table = iface_old->ip6table;
- else
- iface->ip6table = 1000 + ++interface_serial;
-
if ((cur = tb[IFACE_ATTR_IP6TABLE])) {
if (!system_resolve_rt_table(blobmsg_data(cur), &iface->ip6table))
DPRINTF("Failed to resolve routing table: %s\n", (char *) blobmsg_data(cur));
if (iface->device_config)
device_set_config(dev, &simple_device_type, iface->config);
- system_if_apply_settings(dev, &dev->settings);
+ system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
ret = interface_add_link(iface, dev);
} else {
ret = interface_remove_link(iface, dev);
void
interface_update_start(struct interface *iface)
{
+ iface->updated = 0;
interface_ip_update_start(&iface->proto_ip);
}