X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fconfig.c;h=6c0954101386b8d23d0620313815f5accc7b9f23;hp=7700c7eead4f8a977f22a9b5140a4d031b7b98bb;hb=16cee36ff3cf1895f87368709dabd3ffd5f24e4f;hpb=7fd9d455c7f0d19a87f97ce11942d532c71de05f diff --git a/src/config.c b/src/config.c index 7700c7e..6c09541 100644 --- a/src/config.c +++ b/src/config.c @@ -1,6 +1,8 @@ +#include #include #include #include +#include #include #include @@ -8,6 +10,7 @@ #include "odhcpd.h" static struct blob_buf b; +static int reload_pipe[2]; struct list_head leases = LIST_HEAD_INIT(leases); struct list_head interfaces = LIST_HEAD_INIT(interfaces); struct config config = {false, NULL, NULL}; @@ -270,33 +273,33 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr iface = calloc(1, sizeof(*iface)); strncpy(iface->name, name, sizeof(iface->name) - 1); list_add(&iface->head, &interfaces); - } else if (overwrite) { - clean_interface(iface); } const char *ifname = NULL; #ifdef WITH_UBUS - if (overwrite) + if (overwrite || !iface->ifname[0]) ifname = ubus_get_ifname(name); #endif - if ((c = tb[IFACE_ATTR_IFNAME])) - ifname = blobmsg_get_string(c); - else if ((c = tb[IFACE_ATTR_NETWORKID])) - ifname = blobmsg_get_string(c); + + if (overwrite) { + if ((c = tb[IFACE_ATTR_IFNAME])) + ifname = blobmsg_get_string(c); + else if ((c = tb[IFACE_ATTR_NETWORKID])) + ifname = blobmsg_get_string(c); + } if (!iface->ifname[0] && !ifname) return -1; - strncpy(iface->ifname, ifname, sizeof(iface->ifname) - 1); - iface->inuse = true; + if (ifname) + strncpy(iface->ifname, ifname, sizeof(iface->ifname) - 1); - if (overwrite) - clean_interface(iface); + iface->inuse = true; if ((c = tb[IFACE_ATTR_DYNAMICDHCP])) iface->no_dynamic_dhcp = !blobmsg_get_bool(c); - if ((c = tb[IFACE_ATTR_IGNORE])) + if (overwrite && (c = tb[IFACE_ATTR_IGNORE])) iface->ignore = blobmsg_get_bool(c); if ((c = tb[IFACE_ATTR_LEASETIME])) { @@ -335,7 +338,7 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr if ((c = tb[IFACE_ATTR_MASTER])) iface->master = blobmsg_get_bool(c); - if ((c = tb[IFACE_ATTR_UPSTREAM])) { + if (overwrite && (c = tb[IFACE_ATTR_UPSTREAM])) { struct blob_attr *cur; unsigned rem; @@ -485,110 +488,133 @@ static int set_interface(struct uci_section *s) } -static volatile int do_reload = false; -static void set_stop(int signal) -{ - uloop_end(); - do_reload = (signal == SIGHUP); -} - -void odhcpd_run(void) +void odhcpd_reload(void) { struct uci_context *uci = uci_alloc_context(); - signal(SIGTERM, set_stop); - signal(SIGHUP, set_stop); - signal(SIGINT, set_stop); - -#ifdef WITH_UBUS - init_ubus(); -#endif - - do { - do_reload = uloop_cancelled = false; + struct lease *l; + list_for_each_entry(l, &leases, head) { + list_del(&l->head); + free(l->duid); + free(l); + } - struct lease *l; - list_for_each_entry(l, &leases, head) { - list_del(&l->head); - free(l->duid); - free(l); + struct interface *master = NULL, *i, *n; + list_for_each_entry(i, &interfaces, head) + clean_interface(i); + + struct uci_package *dhcp = NULL; + if (!uci_load(uci, "dhcp", &dhcp)) { + struct uci_element *e; + uci_foreach_element(&dhcp->sections, e) { + struct uci_section *s = uci_to_section(e); + if (!strcmp(s->type, "lease")) + set_lease(s); + else if (!strcmp(s->type, "odhcpd")) + set_config(s); } - struct uci_package *dhcp = NULL; - if (!uci_load(uci, "dhcp", &dhcp)) { - struct uci_element *e; - uci_foreach_element(&dhcp->sections, e) { - struct uci_section *s = uci_to_section(e); - if (!strcmp(s->type, "lease")) - set_lease(s); - else if (!strcmp(s->type, "odhcpd")) - set_config(s); - } - - uci_foreach_element(&dhcp->sections, e) { - struct uci_section *s = uci_to_section(e); - if (!strcmp(s->type, "dhcp")) - set_interface(s); - } + uci_foreach_element(&dhcp->sections, e) { + struct uci_section *s = uci_to_section(e); + if (!strcmp(s->type, "dhcp")) + set_interface(s); } + } + #ifdef WITH_UBUS - ubus_apply_network(); + ubus_apply_network(); #endif - // Evaluate hybrid mode for master - struct interface *master = NULL, *i, *n; - list_for_each_entry(i, &interfaces, head) { - if (!i->master) - continue; + // Evaluate hybrid mode for master + list_for_each_entry(i, &interfaces, head) { + if (!i->master) + continue; - enum odhcpd_mode hybrid_mode = RELAYD_DISABLED; + enum odhcpd_mode hybrid_mode = RELAYD_DISABLED; #ifdef WITH_UBUS - if (ubus_has_prefix(i->name, i->ifname)) - hybrid_mode = RELAYD_RELAY; + if (ubus_has_prefix(i->name, i->ifname)) + hybrid_mode = RELAYD_RELAY; #endif + if (i->dhcpv6 == RELAYD_HYBRID) + i->dhcpv6 = hybrid_mode; + + if (i->ra == RELAYD_HYBRID) + i->ra = hybrid_mode; + + if (i->ndp == RELAYD_HYBRID) + i->ndp = hybrid_mode; + + if (i->dhcpv6 == RELAYD_RELAY || i->ra == RELAYD_RELAY || i->ndp == RELAYD_RELAY) + master = i; + } + + + list_for_each_entry_safe(i, n, &interfaces, head) { + if (i->inuse) { + // Resolve hybrid mode if (i->dhcpv6 == RELAYD_HYBRID) - i->dhcpv6 = hybrid_mode; + i->dhcpv6 = (master && master->dhcpv6 == RELAYD_RELAY) ? + RELAYD_RELAY : RELAYD_SERVER; if (i->ra == RELAYD_HYBRID) - i->ra = hybrid_mode; + i->ra = (master && master->ra == RELAYD_RELAY) ? + RELAYD_RELAY : RELAYD_SERVER; if (i->ndp == RELAYD_HYBRID) - i->ndp = hybrid_mode; - - if (i->dhcpv6 == RELAYD_RELAY || i->ra == RELAYD_RELAY || i->ndp == RELAYD_RELAY) - master = i; + i->ndp = (master && master->ndp == RELAYD_RELAY) ? + RELAYD_RELAY : RELAYD_SERVER; + + setup_router_interface(i, true); + setup_dhcpv6_interface(i, true); + setup_ndp_interface(i, true); + setup_dhcpv4_interface(i, true); + } else { + close_interface(i); } + } + uci_unload(uci, dhcp); + uci_free_context(uci); +} - list_for_each_entry_safe(i, n, &interfaces, head) { - if (i->inuse) { - // Resolve hybrid mode - if (i->dhcpv6 == RELAYD_HYBRID) - i->dhcpv6 = (master && master->dhcpv6 == RELAYD_RELAY) ? - RELAYD_RELAY : RELAYD_SERVER; - if (i->ra == RELAYD_HYBRID) - i->ra = (master && master->ra == RELAYD_RELAY) ? - RELAYD_RELAY : RELAYD_SERVER; +static void handle_signal(int signal) +{ + char b[1] = {0}; + if (signal == SIGHUP) + write(reload_pipe[1], b, sizeof(b)); + else + uloop_end(); +} - if (i->ndp == RELAYD_HYBRID) - i->ndp = (master && master->ndp == RELAYD_RELAY) ? - RELAYD_RELAY : RELAYD_SERVER; - setup_router_interface(i, true); - setup_dhcpv6_interface(i, true); - setup_ndp_interface(i, true); - setup_dhcpv4_interface(i, true); - } else { - close_interface(i); - } - } - uloop_run(); +static void reload_cb(struct uloop_fd *u, _unused unsigned int events) +{ + char b[512]; + read(u->fd, b, sizeof(b)); + odhcpd_reload(); +} + +static struct uloop_fd reload_fd = { .cb = reload_cb }; + +void odhcpd_run(void) +{ + pipe2(reload_pipe, O_NONBLOCK | O_CLOEXEC); + reload_fd.fd = reload_pipe[0]; + uloop_fd_add(&reload_fd, ULOOP_READ); + + signal(SIGTERM, handle_signal); + signal(SIGINT, handle_signal); + signal(SIGHUP, handle_signal); + +#ifdef WITH_UBUS + while (init_ubus()) + sleep(1); +#endif - if (dhcp) - uci_unload(uci, dhcp); - } while (do_reload); + odhcpd_reload(); + uloop_run(); }