};
static void
-run_cmd(const char *ifname, const char *device, bool up)
+run_cmd(const char *ifname, const char *device, enum interface_event event)
{
char *argv[3];
int pid;
return;
}
- setenv("ACTION", up ? "ifup" : "ifdown", 1);
+ char *eventnames[] = {"ifdown", "ifup", "ifupdate"};
+ setenv("ACTION", eventnames[event], 1);
setenv("INTERFACE", ifname, 1);
if (device)
setenv("DEVICE", device, 1);
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 == IFEV_UP);
+ run_cmd(current->name, device, current_ev);
}
static void
enum interface_event last_ev;
D(SYSTEM, "Queue hotplug handler for interface '%s'\n", iface->name);
- netifd_ubus_interface_event(iface, ev == IFEV_UP);
+ if (ev == IFEV_UP || ev == IFEV_DOWN)
+ netifd_ubus_interface_event(iface, ev == IFEV_UP);
+
+ netifd_ubus_interface_notify(iface, ev != IFEV_DOWN);
+
if (current == iface)
last_ev = current_ev;
else
{
switch (ev) {
case IFEV_UP:
+ case IFEV_UPDATE:
case IFEV_DOWN:
interface_queue_event(iface, ev);
break;
interface_remove_user(dep);
break;
case IFEV_RELOAD:
+ case IFEV_UPDATE:
break;
}
}
switch (ev) {
case IFPEV_UP:
- if (iface->state != IFS_SETUP)
+ if (iface->state != IFS_SETUP) {
+ interface_event(iface, IFEV_UPDATE);
return;
+ }
interface_ip_set_enabled(&iface->config_ip, true);
system_flush_routes();
enum interface_event {
IFEV_DOWN,
IFEV_UP,
+ IFEV_UPDATE,
IFEV_FREE,
IFEV_RELOAD,
};
struct proto_shell_dependency *pdep;
struct proto_shell_state *state;
- if (ev == IFEV_UP)
+ if (ev == IFEV_UP || ev == IFEV_UPDATE)
return;
pdep = container_of(dep, struct proto_shell_dependency, dep);
struct device *dev;
void *a, *inactive;
- blobmsg_add_string(&b, "name", iface->name);
blobmsg_add_u8(&b, "up", iface->state == IFS_UP);
blobmsg_add_u8(&b, "pending", iface->state == IFS_SETUP);
blobmsg_add_u8(&b, "available", iface->available);
struct interface *iface;
vlist_for_each_element(&interfaces, iface, node) {
void *i = blobmsg_open_table(&b, NULL);
+ blobmsg_add_string(&b, "interface", iface->name);
netifd_dump_status(iface);
blobmsg_close_table(&b, i);
}
ubus_send_event(ctx, "network.interface", b.head);
}
+void
+netifd_ubus_interface_notify(struct interface *iface, bool up)
+{
+ const char *event = (up) ? "update" : "down";
+ blob_buf_init(&b, 0);
+ blobmsg_add_string(&b, "interface", iface->name);
+ netifd_dump_status(iface);
+ ubus_notify(ctx, &iface_object, event, b.head, -1);
+ ubus_notify(ctx, &iface->ubus, event, b.head, -1);
+}
+
void
netifd_ubus_add_interface(struct interface *iface)
{
void netifd_ubus_add_interface(struct interface *iface);
void netifd_ubus_remove_interface(struct interface *iface);
void netifd_ubus_interface_event(struct interface *iface, bool up);
+void netifd_ubus_interface_notify(struct interface *iface, bool up);
#endif