diff options
-rw-r--r-- | interface-event.c | 17 | ||||
-rw-r--r-- | interface-ip.c | 10 | ||||
-rw-r--r-- | interface.c | 19 | ||||
-rw-r--r-- | interface.h | 8 | ||||
-rw-r--r-- | proto-shell.c | 6 | ||||
-rw-r--r-- | ubus.c | 15 |
6 files changed, 65 insertions, 10 deletions
diff --git a/interface-event.c b/interface-event.c index 3b0d1fa..c524ee2 100644 --- a/interface-event.c +++ b/interface-event.c @@ -32,7 +32,8 @@ static struct uloop_process task = { }; static void -run_cmd(const char *ifname, const char *device, enum interface_event event) +run_cmd(const char *ifname, const char *device, enum interface_event event, + enum interface_update_flags updated) { char *argv[3]; int pid; @@ -52,6 +53,18 @@ run_cmd(const char *ifname, const char *device, enum interface_event event) setenv("INTERFACE", ifname, 1); if (device) setenv("DEVICE", device, 1); + + if (event == IFEV_UPDATE) { + if (updated & IUF_ADDRESS) + setenv("IFUPDATE_ADDRESSES", "1", 1); + if (updated & IUF_ROUTE) + setenv("IFUPDATE_ROUTES", "1", 1); + if (updated & IUF_PREFIX) + setenv("IFUPDATE_PREFIXES", "1", 1); + if (updated & IUF_DATA) + setenv("IFUPDATE_DATA", "1", 1); + } + argv[0] = hotplug_cmd_path; argv[1] = "iface"; argv[2] = NULL; @@ -74,7 +87,7 @@ call_hotplug(void) device = current->l3_dev.dev->ifname; D(SYSTEM, "Call hotplug handler for interface '%s' (%s)\n", current->name, device ? device : "none"); - run_cmd(current->name, device, current_ev); + run_cmd(current->name, device, current_ev, current->updated); } static void diff --git a/interface-ip.c b/interface-ip.c index 3771b5d..a6a7dca 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -457,6 +457,9 @@ interface_update_proto_addr(struct vlist_tree *tree, iface = ip->iface; dev = iface->l3_dev.dev; + if (!node_new || !node_old) + iface->updated |= IUF_ADDRESS; + if (node_new) { a_new = container_of(node_new, struct device_addr, node); @@ -559,6 +562,9 @@ interface_update_proto_route(struct vlist_tree *tree, iface = ip->iface; dev = iface->l3_dev.dev; + if (!node_new || !node_old) + iface->updated |= IUF_ROUTE; + route_old = container_of(node_old, struct device_route, node); route_new = container_of(node_new, struct device_route, node); @@ -829,6 +835,10 @@ interface_update_prefix(struct vlist_tree *tree, prefix_old = container_of(node_old, struct device_prefix, node); prefix_new = container_of(node_new, struct device_prefix, node); + struct interface_ip_settings *ip = container_of(tree, struct interface_ip_settings, prefix); + if (tree && (!node_new || !node_old)) + ip->iface->updated |= IUF_PREFIX; + struct device_route route; memset(&route, 0, sizeof(route)); route.flags = DEVADDR_INET6; diff --git a/interface.c b/interface.c index 9c208a2..0032e57 100644 --- a/interface.c +++ b/interface.c @@ -151,15 +151,23 @@ interface_add_data(struct interface *iface, const struct blob_attr *data) 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; } @@ -846,6 +854,7 @@ set_config_state(struct interface *iface, enum interface_config_state s) void interface_update_start(struct interface *iface) { + iface->updated = 0; interface_ip_update_start(&iface->proto_ip); } diff --git a/interface.h b/interface.h index 4b7de59..c3a4379 100644 --- a/interface.h +++ b/interface.h @@ -41,6 +41,13 @@ enum interface_config_state { IFC_REMOVE }; +enum interface_update_flags { + IUF_ADDRESS = (1 << 0), + IUF_ROUTE = (1 << 1), + IUF_PREFIX = (1 << 2), + IUF_DATA = (1 << 3), +}; + struct interface_error { struct list_head list; @@ -100,6 +107,7 @@ struct interface { time_t start_time; enum interface_state state; enum interface_config_state config_state; + enum interface_update_flags updated; struct list_head users; diff --git a/proto-shell.c b/proto-shell.c index 6bbfe10..1a69c19 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -479,15 +479,15 @@ proto_shell_update_link(struct proto_shell_state *state, struct blob_attr *data, if ((cur = tb[NOTIFY_DNS_SEARCH])) interface_add_dns_search_list(&iface->proto_ip, cur); + if ((cur = tb[NOTIFY_DATA])) + proto_shell_parse_data(state->proto.iface, cur); + interface_update_complete(state->proto.iface); if (!keep) state->proto.proto_event(&state->proto, IFPEV_UP); state->sm = S_IDLE; - if ((cur = tb[NOTIFY_DATA])) - proto_shell_parse_data(state->proto.iface, cur); - return 0; } @@ -662,6 +662,21 @@ netifd_dump_status(struct interface *iface) blobmsg_add_string(&b, "device", dev->ifname); if (iface->state == IFS_UP) { + if (iface->updated) { + a = blobmsg_open_array(&b, "updated"); + + if (iface->updated & IUF_ADDRESS) + blobmsg_add_string(&b, NULL, "addresses"); + if (iface->updated & IUF_ROUTE) + blobmsg_add_string(&b, NULL, "routes"); + if (iface->updated & IUF_PREFIX) + blobmsg_add_string(&b, NULL, "prefixes"); + if (iface->updated & IUF_DATA) + blobmsg_add_string(&b, NULL, "data"); + + blobmsg_close_array(&b, a); + } + if (iface->ip4table) blobmsg_add_u32(&b, "ip4table", iface->ip4table); if (iface->ip6table) |