From cced3a7f8d1da2a63230bbd3c1a8d746a18cfa00 Mon Sep 17 00:00:00 2001 From: Amin Ben Ramdhane Date: Tue, 12 Jan 2021 16:56:30 +0100 Subject: [PATCH] IP.Interface: interface proto can't be set to static if it is dhcp by default --- dmtree/tr181/ip.c | 268 ++++++++++++++++++++++++---------------------- 1 file changed, 141 insertions(+), 127 deletions(-) diff --git a/dmtree/tr181/ip.c b/dmtree/tr181/ip.c index 5c01ad76..3f35e7f1 100644 --- a/dmtree/tr181/ip.c +++ b/dmtree/tr181/ip.c @@ -81,6 +81,31 @@ static void create_firewall_zone_config(char *iface) dmuci_set_value_by_section(s, "network", iface); } +static struct uci_section *check_dmmap_network_interface_ipv4(char *dmmap_file_name, char *dmmap_sec_name, char *parent_section, char *section_name) +{ + struct uci_section *dmmap_section = NULL; + char *sec_name; + + uci_path_foreach_option_eq(bbfdm, dmmap_file_name, dmmap_sec_name, "parent_section", parent_section, dmmap_section) { + dmuci_get_value_by_section_string(dmmap_section, "section_name", &sec_name); + if (strcmp(sec_name, section_name) == 0) + return dmmap_section; + } + + return NULL; +} + +static struct uci_section *add_dmmap_network_interface_ipv4(char *dmmap_file_name, char *dmmap_sec_name, char *parent_section, char *section_name) +{ + struct uci_section *dmmap_section = NULL; + + dmuci_add_section_bbfdm(dmmap_file_name, dmmap_sec_name, &dmmap_section); + dmuci_set_value_by_section_bbfdm(dmmap_section, "parent_section", parent_section); + dmuci_set_value_by_section_bbfdm(dmmap_section, "section_name", section_name); + + return dmmap_section; +} + static struct uci_section *update_dmmap_network_interface(char *dmmap_file_name, char *dmmap_sec_name, char *parent_section, char *section_name, char *option, char *value, bool assign) { struct uci_section *dmmap_section = NULL; @@ -104,42 +129,6 @@ static struct uci_section *update_dmmap_network_interface(char *dmmap_file_name, return dmmap_section; } -static void synchronize_intf_ipv4_sections_with_dmmap(void) -{ - json_object *res = NULL, *ipv4_obj = NULL, *arrobj = NULL; - struct uci_section *s = NULL, *ss = NULL, *stmp = NULL; - char *dmmap_intf_s, *dmmap_address, *ipaddr = NULL; - bool found = false; - int i = 0; - - uci_path_foreach_sections_safe(bbfdm, "dmmap_network_ipv4", "intf_ipv4", stmp, s) { - dmuci_get_value_by_section_string(s, "section_name", &dmmap_intf_s); - dmuci_get_value_by_section_string(s, "address", &dmmap_address); - found = false; - - ss = get_origin_section_from_config("network", "interface", dmmap_intf_s); - dmuci_get_value_by_section_string(ss, "ipaddr", &ipaddr); - - if (ipaddr && *ipaddr != '\0' && strcmp(ipaddr, dmmap_address) == 0) - continue; - - dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", dmmap_intf_s, String}}, 1, &res); - - dmjson_foreach_obj_in_array(res, arrobj, ipv4_obj, i, 1, "ipv4-address") { - - char *address = dmjson_get_value(ipv4_obj, 1, "address"); - if (address && *address && strcmp(address, dmmap_address) == 0) { - found = true; - break; - } - - } - - if (!found) - dmuci_delete_by_section(s, NULL, NULL); - } -} - static void synchronize_intf_ipv6_sections_with_dmmap(void) { json_object *res = NULL, *ipv6_obj = NULL, *arrobj = NULL; @@ -381,13 +370,18 @@ static bool interface_section_with_dhcpv6_exists(const char *sec_name) return false; } -static void set_ip_interface_ifname_option(struct uci_section *section, char *linker, char *instance) +static void set_ip_interface_ifname_option(struct uci_section *section, char *linker, char *instance, bool is_br_sec) { struct uci_section *s = NULL; bool device_exists = false; char ifname[64]; - snprintf(ifname, sizeof(ifname), "%s.1", linker); + if (is_br_sec) { + snprintf(ifname, sizeof(ifname), "%s", linker); + goto end; + } else { + snprintf(ifname, sizeof(ifname), "%s.1", linker); + } // Check if device exists uci_foreach_option_eq("network", "device", "name", ifname, s) { @@ -408,6 +402,7 @@ static void set_ip_interface_ifname_option(struct uci_section *section, char *li dmuci_set_value_by_section(s, "name", ifname); } +end: dmuci_set_value_by_section(section, "ifname", ifname); } @@ -496,67 +491,47 @@ static int browseIPInterfaceInst(struct dmctx *dmctx, DMNODE *parent_node, void static int browseIPInterfaceIPv4AddressInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) { struct uci_section *parent_sec = (struct uci_section *)prev_data, *intf_s = NULL, *dmmap_s = NULL; - char *inst = NULL, *max_inst = NULL, *ipaddr, *ifname, buf[32] = {0}; - json_object *res = NULL, *ipv4_obj = NULL, *arrobj = NULL; + char *inst = NULL, *max_inst = NULL, *ipaddr, *added_by_user = NULL, *ifname, buf[32] = {0}; + json_object *res = NULL, *ipv4_obj = NULL; struct intf_ip_args curr_intf_ip_args = {0}; struct browse_args browse_args = {0}; - int i = 0; snprintf(buf, sizeof(buf), "@%s", section_name(parent_sec)); - synchronize_intf_ipv4_sections_with_dmmap(); uci_foreach_sections("network", "interface", intf_s) { dmuci_get_value_by_section_string(intf_s, "ifname", &ifname); if (strcmp(section_name(intf_s), section_name(parent_sec)) != 0 && strcmp(ifname, buf) != 0) continue; + dmmap_s = check_dmmap_network_interface_ipv4("dmmap_network_ipv4", "intf_ipv4", section_name(parent_sec), section_name(intf_s)); + dmuci_get_value_by_section_string(dmmap_s, "added_by_user", &added_by_user); + dmuci_get_value_by_section_string(intf_s, "ipaddr", &ipaddr); - if (*ipaddr == '\0') { - dmubus_call("network.interface", "status", UBUS_ARGS{{"interface", section_name(intf_s), String}}, 1, &res); - - dmjson_foreach_obj_in_array(res, arrobj, ipv4_obj, i, 1, "ipv4-address") { - - char *address = dmjson_get_value(ipv4_obj, 1, "address"); - if (*address == '\0') - continue; - - dmmap_s = update_dmmap_network_interface("dmmap_network_ipv4", "intf_ipv4", section_name(parent_sec), section_name(intf_s), "address", address, false); - - init_interface_ip_args(&curr_intf_ip_args, intf_s, dmmap_s, ipv4_obj); - - browse_args.option = "parent_section"; - browse_args.value = section_name(parent_sec); - - inst = handle_update_instance(2, dmctx, &max_inst, update_instance_alias, 5, - dmmap_s, "ipv4_instance", "ipv4_alias", - check_browse_section, (void *)&browse_args); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_intf_ip_args, inst) == DM_STOP) - goto end; - } - - } else { - - dmmap_s = update_dmmap_network_interface("dmmap_network_ipv4", "intf_ipv4", section_name(parent_sec), section_name(intf_s), "address", ipaddr, false); - - init_interface_ip_args(&curr_intf_ip_args, intf_s, dmmap_s, NULL); - - browse_args.option = "parent_section"; - browse_args.value = section_name(parent_sec); - - inst = handle_update_instance(2, dmctx, &max_inst, update_instance_alias, 5, - dmmap_s, "ipv4_instance", "ipv4_alias", - check_browse_section, (void *)&browse_args); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_intf_ip_args, inst) == DM_STOP) - goto end; + ipv4_obj = dmjson_select_obj_in_array_idx(res, 0, 1, "ipv4-address"); + ipaddr = dmjson_get_value(ipv4_obj, 1, "address"); } - } -end: + if (*ipaddr == '\0' && added_by_user && strcmp(added_by_user, "1") != 0) + continue; + + if (dmmap_s == NULL) + dmmap_s = add_dmmap_network_interface_ipv4("dmmap_network_ipv4", "intf_ipv4", section_name(parent_sec), section_name(intf_s)); + + init_interface_ip_args(&curr_intf_ip_args, intf_s, dmmap_s, res); + + browse_args.option = "parent_section"; + browse_args.value = section_name(parent_sec); + + inst = handle_update_instance(2, dmctx, &max_inst, update_instance_alias, 5, + dmmap_s, "ipv4_instance", "ipv4_alias", + check_browse_section, (void *)&browse_args); + + if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&curr_intf_ip_args, inst) == DM_STOP) + break; + } return 0; } @@ -754,7 +729,7 @@ static int addObjIPInterface(char *refparam, struct dmctx *ctx, void *data, char snprintf(ip_name, sizeof(ip_name), "ip_interface_%d", last_inst ? atoi(last_inst) + 1 : 1); dmuci_set_value("network", ip_name, "", "interface"); - dmuci_set_value("network", ip_name, "proto", "static"); + dmuci_set_value("network", ip_name, "proto", "none"); dmuci_add_section_bbfdm("dmmap_network", "interface", &dmmap_ip_interface); dmuci_set_value_by_section(dmmap_ip_interface, "section_name", ip_name); @@ -790,12 +765,6 @@ static int delObjIPInterface(char *refparam, struct dmctx *ctx, void *data, char static int addObjIPInterfaceIPv4Address(char *refparam, struct dmctx *ctx, void *data, char **instance) { - // check the proto option from the interface section parent, if proto="static" ==> we can add a new object, else return 9001 error - char *proto; - dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &proto); - if (strcmp(proto, "static") != 0) - return FAULT_9001; - char *last_inst = NULL, *ip_inst, ipv4_name[64] = {0}, buf[32] = {0}; struct uci_section *dmmap_ip_interface = NULL, *dmmap_ip_interface_ipv4; struct browse_args browse_args = {0}; @@ -812,11 +781,11 @@ static int addObjIPInterfaceIPv4Address(char *refparam, struct dmctx *ctx, void dmuci_set_value("network", ipv4_name, "", "interface"); dmuci_set_value("network", ipv4_name, "ifname", buf); dmuci_set_value("network", ipv4_name, "proto", "static"); - dmuci_set_value("network", ipv4_name, "ipaddr", "0.0.0.0"); - dmuci_set_value("network", ipv4_name, "netmask", "0.0.0.0"); } else { - dmuci_set_value_by_section((struct uci_section *)data, "ipaddr", "0.0.0.0"); - dmuci_set_value_by_section((struct uci_section *)data, "netmask", "0.0.0.0"); + char *proto; + + dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &proto); + dmuci_set_value_by_section((struct uci_section *)data, "proto", strcmp(proto, "dhcp") == 0 ? proto : "static"); } browse_args.option = "parent_section"; @@ -825,7 +794,7 @@ static int addObjIPInterfaceIPv4Address(char *refparam, struct dmctx *ctx, void dmuci_add_section_bbfdm("dmmap_network_ipv4", "intf_ipv4", &dmmap_ip_interface_ipv4); dmuci_set_value_by_section(dmmap_ip_interface_ipv4, "parent_section", section_name((struct uci_section *)data)); dmuci_set_value_by_section(dmmap_ip_interface_ipv4, "section_name", last_inst ? ipv4_name : section_name((struct uci_section *)data)); - dmuci_set_value_by_section(dmmap_ip_interface_ipv4, "address", "0.0.0.0"); + dmuci_set_value_by_section(dmmap_ip_interface_ipv4, "added_by_user", "1"); *instance = update_instance(last_inst, 5, dmmap_ip_interface_ipv4, "ipv4_instance", NULL, check_browse_section, (void *)&browse_args); return 0; @@ -885,12 +854,6 @@ static int delObjIPInterfaceIPv4Address(char *refparam, struct dmctx *ctx, void static int addObjIPInterfaceIPv6Address(char *refparam, struct dmctx *ctx, void *data, char **instance) { - // check the proto option from the interface section parent, if proto="static" ==> you can add a new object, else return 9001 error - char *proto; - dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &proto); - if (strcmp(proto, "static") != 0 || (strcmp(proto, "static") == 0 && interface_section_with_dhcpv6_exists(section_name((struct uci_section *)data)))) - return FAULT_9001; - char *last_inst = NULL, *ip_inst, ipv6_name[64] = {0}, buf[32] = {0}; struct uci_section *dmmap_ip_interface = NULL, *dmmap_ip_interface_ipv6; struct browse_args browse_args = {0}; @@ -926,12 +889,6 @@ static int delObjIPInterfaceIPv6Address(char *refparam, struct dmctx *ctx, void static int addObjIPInterfaceIPv6Prefix(char *refparam, struct dmctx *ctx, void *data, char **instance) { - // check the proto option from the interface section parent, if proto="static" ==> you can add a new object, else return 9001 error - char *proto; - dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &proto); - if (strcmp(proto, "static") != 0 || (strcmp(proto, "static") == 0 && interface_section_with_dhcpv6_exists(section_name((struct uci_section *)data)))) - return FAULT_9001; - char *last_inst = NULL, *ip_inst, ipv6_prefix_name[64] = {0}, buf[32] = {0}; struct uci_section *dmmap_ip_interface = NULL, *dmmap_ip_interface_ipv6_prefix; struct browse_args browse_args = {0}; @@ -1369,18 +1326,20 @@ static int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void * if (!interface) { bool ip_interface_s = false; - // Update the new interface section with proto=dhcp if its proto is empty + bool is_br_sec = false; + // Update the new interface section with proto=none if its proto is empty uci_foreach_sections("network", "interface", s) { if (strcmp(section_name(s), interface_list) == 0) { char *proto, *type; dmuci_get_value_by_section_string(s, "proto", &proto); dmuci_get_value_by_section_string(s, "type", &type); if (*proto == '\0') { - dmuci_set_value_by_section(s, "proto", "dhcp"); + dmuci_set_value_by_section(s, "proto", "none"); if (strcmp(type, "bridge") != 0) - set_ip_interface_ifname_option(s, ip_linker, instance); + set_ip_interface_ifname_option(s, ip_linker, instance, false); } else { ip_interface_s = true; + is_br_sec = (strcmp(type, "bridge") == 0) ? true : false; } break; } @@ -1406,10 +1365,10 @@ static int set_IPInterface_LowerLayers(char *refparam, struct dmctx *ctx, void * // remove the current interface section dmuci_delete_by_section((struct uci_section *)data, NULL, NULL); } else { - set_ip_interface_ifname_option((struct uci_section *)data, ip_linker, instance); + set_ip_interface_ifname_option((struct uci_section *)data, ip_linker, instance, is_br_sec); } } else { - set_ip_interface_ifname_option((struct uci_section *)data, ip_linker, instance); + set_ip_interface_ifname_option((struct uci_section *)data, ip_linker, instance, false); } } break; @@ -1514,7 +1473,6 @@ static int get_IPInterface_IPv4AddressNumberOfEntries(char *refparam, struct dmc struct uci_section *s = NULL; int cnt = 0; - synchronize_intf_ipv4_sections_with_dmmap(); uci_path_foreach_option_eq(bbfdm, "dmmap_network_ipv4", "intf_ipv4", "parent_section", section_name((struct uci_section *)data), s) { cnt++; } @@ -1548,6 +1506,40 @@ static int get_IPInterface_IPv6PrefixNumberOfEntries(char *refparam, struct dmct return 0; } +/*#Device.IP.Interface.{i}.AutoIPEnable!UCI:network/interface,@i-1/proto*/ +static int get_IPInterface_AutoIPEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) +{ + char *proto = NULL; + dmuci_get_value_by_section_string((struct uci_section *)data, "proto", &proto); + *value = (proto && strcmp(proto, "dhcp") == 0) ? "1" : "0"; + return 0; +} + +static int set_IPInterface_AutoIPEnable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) +{ + char *ip_addr = NULL; + bool b; + + switch (action) { + case VALUECHECK: + if (dm_validate_boolean(value)) + return FAULT_9007; + break; + case VALUESET: + string_to_bool(value, &b); + dmuci_get_value_by_section_string((struct uci_section *)data, "ipaddr", &ip_addr); + if (b) { + dmuci_set_value_by_section((struct uci_section *)data, "proto", "dhcp"); + dmuci_set_value_by_section((struct uci_section *)data, "ipaddr", ""); + } else { + dmuci_set_value_by_section((struct uci_section *)data, "proto", (ip_addr && *ip_addr) ? "static" : "none"); + dmuci_set_value_by_section((struct uci_section *)data, "ipaddr", (ip_addr && *ip_addr) ? ip_addr : ""); + } + break; + } + return 0; +} + static int get_IPInterface_TWAMPReflectorNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { struct uci_section *s = NULL; @@ -1563,14 +1555,23 @@ static int get_IPInterface_TWAMPReflectorNumberOfEntries(char *refparam, struct /*#Device.IP.Interface.{i}.IPv4Address.{i}.Enable!UCI:network/interface,@i-1/disabled*/ static int get_IPInterfaceIPv4Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { - char *disabled = NULL; - dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "disabled", &disabled); - *value = (disabled && *disabled == '1') ? "0" : "1"; + char *proto = NULL; + + dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "proto", &proto); + if (strcmp(proto, "none") != 0) { + char *disabled = NULL; + + dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "disabled", &disabled); + *value = (disabled && *disabled == '1') ? "0" : "1"; + } else { + *value = "0"; + } return 0; } static int set_IPInterfaceIPv4Address_Enable(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { + char *proto; bool b; switch (action) { @@ -1580,7 +1581,15 @@ static int set_IPInterfaceIPv4Address_Enable(char *refparam, struct dmctx *ctx, break; case VALUESET: string_to_bool(value, &b); + dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "proto", &proto); + if (strcmp(proto, "none") == 0) { + char *ip_addr; + + dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "ipaddr", &ip_addr); + dmuci_set_value_by_section(((struct intf_ip_args *)data)->interface_sec, "proto", b ? (*ip_addr == '\0' ? "dhcp" : "static") : "none"); + } dmuci_set_value_by_section(((struct intf_ip_args *)data)->interface_sec, "disabled", b ? "0" : "1"); + break; } return 0; @@ -1605,13 +1614,17 @@ static int get_IPInterfaceIPv4Address_Alias(char *refparam, struct dmctx *ctx, v static int set_IPInterfaceIPv4Address_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) { + char *proto = NULL; + switch (action) { case VALUECHECK: if (dm_validate_string(value, -1, 64, NULL, 0, NULL, 0)) return FAULT_9007; break; case VALUESET: - dmuci_set_value_by_section(((struct intf_ip_args *)data)->dmmap_sec, "ipv4_alias", value); + dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "proto", &proto); + if (proto && strcmp(proto, "static") == 0) + dmuci_set_value_by_section(((struct intf_ip_args *)data)->dmmap_sec, "ipv4_alias", value); break; } return 0; @@ -1624,10 +1637,12 @@ static int get_IPInterfaceIPv4Address_IPAddress(char *refparam, struct dmctx *ct dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "ipaddr", &ip_addr); - if (ip_addr[0] == '\0') - ip_addr = dmjson_get_value(((struct intf_ip_args *)data)->interface_obj, 1, "address"); + if (ip_addr[0] == '\0') { + json_object *ipv4_obj = dmjson_select_obj_in_array_idx(((struct intf_ip_args *)data)->interface_obj, 0, 1, "ipv4-address"); + ip_addr = dmjson_get_value(ipv4_obj, 1, "address"); + } - *value = ip_addr; + *value = (ip_addr && *ip_addr) ? ip_addr : "0.0.0.0"; return 0; } @@ -1642,10 +1657,8 @@ static int set_IPInterfaceIPv4Address_IPAddress(char *refparam, struct dmctx *ct break; case VALUESET: dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "proto", &proto_intf); - if (proto_intf && strcmp(proto_intf, "static") == 0) { + if (proto_intf && strcmp(proto_intf, "static") == 0) dmuci_set_value_by_section(((struct intf_ip_args *)data)->interface_sec, "ipaddr", value); - dmuci_set_value_by_section(((struct intf_ip_args *)data)->dmmap_sec, "address", value); - } break; } return 0; @@ -1659,11 +1672,12 @@ static int get_IPInterfaceIPv4Address_SubnetMask(char *refparam, struct dmctx *c dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "netmask", &mask); if (mask[0] == '\0') { - mask = dmjson_get_value(((struct intf_ip_args *)data)->interface_obj, 1, "mask"); + json_object *ipv4_obj = dmjson_select_obj_in_array_idx(((struct intf_ip_args *)data)->interface_obj, 0, 1, "ipv4-address"); + mask = dmjson_get_value(ipv4_obj, 1, "mask"); mask = (mask && *mask) ? dmstrdup(cidr2netmask(atoi(mask))) : ""; } - *value = mask; + *value = (mask && *mask) ? mask : "0.0.0.0"; return 0; } @@ -1689,7 +1703,7 @@ static int set_IPInterfaceIPv4Address_SubnetMask(char *refparam, struct dmctx *c static int get_IPInterfaceIPv4Address_AddressingType(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) { dmuci_get_value_by_section_string(((struct intf_ip_args *)data)->interface_sec, "proto", value); - *value = (strcmp(*value, "dhcp") == 0) ? "DHCP" : "Static"; + *value = (strcmp(*value, "static") == 0) ? "Static" : "DHCP"; return 0; } @@ -2263,7 +2277,7 @@ DMLEAF tIPInterfaceParams[] = { {"IPv4AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_IPv4AddressNumberOfEntries, NULL, BBFDM_BOTH}, {"IPv6AddressNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_IPv6AddressNumberOfEntries, NULL, BBFDM_BOTH}, {"IPv6PrefixNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_IPv6PrefixNumberOfEntries, NULL, BBFDM_BOTH}, -//{"AutoIPEnable", &DMWRITE, DMT_BOOL, get_IPInterface_AutoIPEnable, set_IPInterface_AutoIPEnable, BBFDM_BOTH}, +{"AutoIPEnable", &DMWRITE, DMT_BOOL, get_IPInterface_AutoIPEnable, set_IPInterface_AutoIPEnable, BBFDM_BOTH}, {"TWAMPReflectorNumberOfEntries", &DMREAD, DMT_UNINT, get_IPInterface_TWAMPReflectorNumberOfEntries, NULL, BBFDM_BOTH}, {0} };