X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fodhcpd.git;a=blobdiff_plain;f=src%2Fconfig.c;h=068d1a7483a14cba591ec0dd3c1fdbd852e484c1;hp=46137a48ab3dc926047f985c358c9d877cb36aed;hb=72082d2f6c2ee568470575c09ba4984f1a5c44f0;hpb=359a2c478832b41af427f6a96c4d11d81447e65a diff --git a/src/config.c b/src/config.c index 46137a4..068d1a7 100644 --- a/src/config.c +++ b/src/config.c @@ -32,10 +32,14 @@ enum { IFACE_ATTR_NDP, IFACE_ATTR_DNS, IFACE_ATTR_DOMAIN, + IFACE_ATTR_FILTER_CLASS, + IFACE_ATTR_DHCPV6_RAW, IFACE_ATTR_RA_DEFAULT, IFACE_ATTR_RA_MANAGEMENT, IFACE_ATTR_RA_OFFLINK, IFACE_ATTR_RA_PREFERENCE, + IFACE_ATTR_PD_MANAGER, + IFACE_ATTR_PD_CER, IFACE_ATTR_NDPROXY_ROUTING, IFACE_ATTR_NDPROXY_SLAVE, IFACE_ATTR_NDPROXY_STATIC, @@ -59,6 +63,10 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { [IFACE_ATTR_NDP] = { .name = "ndp", .type = BLOBMSG_TYPE_STRING }, [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY }, [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY }, + [IFACE_ATTR_FILTER_CLASS] = { .name = "filter_class", .type = BLOBMSG_TYPE_STRING }, + [IFACE_ATTR_DHCPV6_RAW] = { .name = "dhcpv6_raw", .type = BLOBMSG_TYPE_STRING }, + [IFACE_ATTR_PD_MANAGER] = { .name = "pd_manager", .type = BLOBMSG_TYPE_STRING }, + [IFACE_ATTR_PD_CER] = { .name = "pd_cer", .type = BLOBMSG_TYPE_STRING }, [IFACE_ATTR_RA_DEFAULT] = { .name = "ra_default", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_RA_MANAGEMENT] = { .name = "ra_management", .type = BLOBMSG_TYPE_INT32 }, [IFACE_ATTR_RA_OFFLINK] = { .name = "ra_offlink", .type = BLOBMSG_TYPE_BOOL }, @@ -145,6 +153,8 @@ static void clean_interface(struct interface *iface) free(iface->upstream); free(iface->static_ndp); free(iface->dhcpv4_dns); + free(iface->dhcpv6_raw); + free(iface->filter_class); memset(&iface->ra, 0, sizeof(*iface) - offsetof(struct interface, ra)); } @@ -245,10 +255,12 @@ static int set_lease(struct uci_section *s) lease->duid_len = len; } - if ((c = tb[LEASE_ATTR_HOSTID])) - if (odhcpd_unhexlify((uint8_t*)&lease->hostid, sizeof(lease->hostid), - blobmsg_get_string(c)) < 0) + if ((c = tb[LEASE_ATTR_HOSTID])) { + errno = 0; + lease->hostid = strtoul(blobmsg_get_string(c), NULL, 16); + if (errno) goto err; + } list_add(&lease->head, &leases); return 0; @@ -281,6 +293,7 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr strncpy(iface->name, name, sizeof(iface->name) - 1); list_add(&iface->head, &interfaces); + overwrite = true; } const char *ifname = NULL; @@ -302,6 +315,9 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr if (ifname) strncpy(iface->ifname, ifname, sizeof(iface->ifname) - 1); + if ((iface->ifindex = if_nametoindex(iface->ifname)) <= 0) + return -1; + iface->inuse = true; if ((c = tb[IFACE_ATTR_DYNAMICDHCP])) @@ -433,7 +449,13 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr continue; uint8_t buf[256]; - int len = dn_comp(blobmsg_get_string(cur), buf, sizeof(buf), NULL, NULL); + char *domain = blobmsg_get_string(cur); + size_t domainlen = strlen(domain); + if (domainlen > 0 && domain[domainlen - 1] == '.') + domain[domainlen - 1] = 0; + + int len = dn_comp(domain, buf, sizeof(buf), NULL, NULL); + free(domain); if (len <= 0) goto err; @@ -446,11 +468,24 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr } } + if ((c = tb[IFACE_ATTR_FILTER_CLASS])) { + iface->filter_class = realloc(iface->filter_class, blobmsg_data_len(c) + 1); + memcpy(iface->filter_class, blobmsg_get_string(c), blobmsg_data_len(c) + 1); + } + + if ((c = tb[IFACE_ATTR_DHCPV6_RAW])) { + iface->dhcpv6_raw_len = blobmsg_data_len(c) / 2; + iface->dhcpv6_raw = realloc(iface->dhcpv6_raw, iface->dhcpv6_raw_len); + odhcpd_unhexlify(iface->dhcpv6_raw, iface->dhcpv6_raw_len, blobmsg_get_string(c)); + } + if ((c = tb[IFACE_ATTR_RA_DEFAULT])) iface->default_router = blobmsg_get_u32(c); if ((c = tb[IFACE_ATTR_RA_MANAGEMENT])) iface->managed = blobmsg_get_u32(c); + else if (overwrite) + iface->managed = 1; if ((c = tb[IFACE_ATTR_RA_OFFLINK])) iface->ra_not_onlink = blobmsg_get_bool(c); @@ -468,9 +503,17 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr goto err; } + if ((c = tb[IFACE_ATTR_PD_MANAGER])) + strncpy(iface->dhcpv6_pd_manager, blobmsg_get_string(c), + sizeof(iface->dhcpv6_pd_manager) - 1); + + if ((c = tb[IFACE_ATTR_PD_CER]) && + inet_pton(AF_INET6, blobmsg_get_string(c), &iface->dhcpv6_pd_cer) < 1) + goto err; + if ((c = tb[IFACE_ATTR_NDPROXY_ROUTING])) iface->learn_routes = blobmsg_get_bool(c); - else + else if (overwrite) iface->learn_routes = true; if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE])) @@ -489,12 +532,14 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr if (!iface->static_ndp) goto err; + if (iface->static_ndp_len) + iface->static_ndp[iface->static_ndp_len - 1] = ' '; + memcpy(&iface->static_ndp[iface->static_ndp_len], blobmsg_get_string(cur), len); iface->static_ndp_len += len; } } - iface->ignore = (iface->ifindex = if_nametoindex(iface->ifname)) <= 0; return 0; err: @@ -513,8 +558,8 @@ static int set_interface(struct uci_section *s) void odhcpd_reload(void) { struct uci_context *uci = uci_alloc_context(); - struct lease *l; - list_for_each_entry(l, &leases, head) { + while (!list_empty(&leases)) { + struct lease *l = list_first_entry(&leases, struct lease, head); list_del(&l->head); free(l->duid); free(l); @@ -551,6 +596,23 @@ void odhcpd_reload(void) ubus_apply_network(); #endif + bool any_dhcpv6_slave = false, any_ra_slave = false, any_ndp_slave = false; + + // Test for + list_for_each_entry(i, &interfaces, head) { + if (i->master) + continue; + + if (i->dhcpv6 == RELAYD_HYBRID || i->dhcpv6 == RELAYD_RELAY) + any_dhcpv6_slave = true; + + if (i->ra == RELAYD_HYBRID || i->ra == RELAYD_RELAY) + any_ra_slave = true; + + if (i->ndp == RELAYD_HYBRID || i->ndp == RELAYD_RELAY) + any_ndp_slave = true; + } + // Evaluate hybrid mode for master list_for_each_entry(i, &interfaces, head) { if (!i->master) @@ -558,19 +620,28 @@ void odhcpd_reload(void) enum odhcpd_mode hybrid_mode = RELAYD_DISABLED; #ifdef WITH_UBUS - if (ubus_has_prefix(i->name, i->ifname)) + if (!ubus_has_prefix(i->name, i->ifname)) hybrid_mode = RELAYD_RELAY; #endif if (i->dhcpv6 == RELAYD_HYBRID) i->dhcpv6 = hybrid_mode; + if (i->dhcpv6 == RELAYD_RELAY && !any_dhcpv6_slave) + i->dhcpv6 = RELAYD_DISABLED; + if (i->ra == RELAYD_HYBRID) i->ra = hybrid_mode; + if (i->ra == RELAYD_RELAY && !any_ra_slave) + i->ra = RELAYD_DISABLED; + if (i->ndp == RELAYD_HYBRID) i->ndp = hybrid_mode; + if (i->ndp == RELAYD_RELAY && !any_ndp_slave) + i->ndp = RELAYD_DISABLED; + if (i->dhcpv6 == RELAYD_RELAY || i->ra == RELAYD_RELAY || i->ndp == RELAYD_RELAY) master = i; } @@ -589,7 +660,7 @@ void odhcpd_reload(void) if (i->ndp == RELAYD_HYBRID) i->ndp = (master && master->ndp == RELAYD_RELAY) ? - RELAYD_RELAY : RELAYD_SERVER; + RELAYD_RELAY : RELAYD_DISABLED; setup_router_interface(i, true); setup_dhcpv6_interface(i, true);