summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface-event.c17
-rw-r--r--interface-ip.c10
-rw-r--r--interface.c19
-rw-r--r--interface.h8
-rw-r--r--proto-shell.c6
-rw-r--r--ubus.c15
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;
}
diff --git a/ubus.c b/ubus.c
index 399d46b..22b75e4 100644
--- a/ubus.c
+++ b/ubus.c
@@ -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)