| #include <unistd.h> |
| #include <assert.h> |
| #include <signal.h> |
| |
| #include <libubox/blobmsg_json.h> |
| #include <libubox/blob.h> |
| #include "libubus.h" |
| #include <uci.h> |
| #include <include/log.h> |
| #include <sys/prctl.h> |
| #include "router_firewall.h" |
| |
| #ifdef CONFIG_LOG_ENABLE |
| |
| #define FW_DBG(format, args...) RDPRINTF("%s " format, __FUNCTION__, ##args); |
| #define FW_ERR(format, args...) RERRMSG("%s " format, __FUNCTION__, ##args); |
| #else |
| #define FW_DBG(format, args...) do {} while (0) |
| #define FW_ERR(format, args...) do {} while (0) |
| #endif |
| #ifndef FW_PACK |
| #define FW_PACK "firewall" |
| #endif |
| #ifndef DHCP_PACK |
| #define DHCP_PACK "dhcp" |
| #endif |
| |
| #ifndef UNUSESET |
| #define UNUSESET(param) (void)(param) |
| #endif |
| |
| static int fw_system(const char *cmd) |
| { |
| FILE *fp; |
| int res; |
| char buf[1024]; |
| if (cmd == NULL) { |
| FW_ERR("my_system cmd is NULL!\n"); |
| return -1; |
| } |
| if ((fp = popen(cmd, "r")) == NULL) { |
| FW_ERR("popen error: %s/n", strerror(errno)); |
| return -1; |
| } else { |
| while (fgets(buf, sizeof(buf), fp)) { |
| FW_DBG("%s", buf); |
| } |
| if ((res = pclose(fp)) == -1) { |
| FW_ERR("close popen file pointer fp error!\n"); |
| return res; |
| } else if (res == 0) { |
| return res; |
| } else { |
| FW_DBG("popen res is :%d\n", res); |
| return res; |
| } |
| } |
| } |
| |
| static struct uci_context *uci_ctx_fw = NULL; |
| |
| /*get uci_ctx*/ |
| static struct uci_context *uci_fw_ctx_get(void) |
| { |
| if (uci_ctx_fw) { |
| return uci_ctx_fw; |
| } |
| uci_ctx_fw = uci_alloc_context(); |
| if (!uci_ctx_fw) { |
| FW_ERR("%s, uci_ctx_api malloc failed", __FUNCTION__); |
| return NULL; |
| } |
| return uci_ctx_fw; |
| } |
| |
| /*free uci_ctx*/ |
| static void free_fw_uci_ctx(void) |
| { |
| if (uci_ctx_fw) { |
| uci_free_context(uci_ctx_fw); |
| uci_ctx_fw = NULL; |
| } |
| } |
| |
| /*blob buf used in Firewall*/ |
| static struct blob_buf fw_buf; |
| /*================================================ |
| <firewall> |
| <disable/> |
| <ip_filter_disable/> |
| <dn_filter_disable/> |
| <dmz_disable/> |
| <upnp_disable/> |
| <port_trigger_disable/> |
| </firewall> |
| Note : add "option filter_type ip_filter/mac_filter" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| |
| int fw_get_disable_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| |
| UNUSESET(msg); |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| FW_DBG("enter"); |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (p) { |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "defaults") == 0) { |
| FW_DBG("get uci_sec defaults"); |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "disable"); |
| if (opt_val) { |
| FW_DBG("get fw disable %s", opt_val); |
| blobmsg_add_string(&fw_buf, "disable", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "disable", "1"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ip_filter_disable"); |
| if (opt_val) { |
| FW_DBG("get ip_filter disable %s", opt_val); |
| blobmsg_add_string(&fw_buf, "ip_filter_disable", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "ip_filter_disable", "1"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dn_filter_disable"); |
| if (opt_val) { |
| FW_DBG("get dn_filter_disable disable %s", opt_val); |
| blobmsg_add_string(&fw_buf, "dn_filter_disable", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "dn_filter_disable", "1"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dmz_disable"); |
| if (opt_val) { |
| FW_DBG("get dmz_disable disable %s", opt_val); |
| blobmsg_add_string(&fw_buf, "dmz_disable", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "dmz_disable", "1"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "upnp_disable"); |
| if (opt_val) { |
| FW_DBG("get upnp_disable disable %s", opt_val); |
| blobmsg_add_string(&fw_buf, "upnp_disable", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "upnp_disable", "1"); |
| } |
| } |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "disable", "1"); |
| } |
| if (tb_fw) { |
| blobmsg_close_table(&fw_buf, tb_fw); |
| } |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| |
| </firewall> |
| Note : add "option filter_type ip_filter/mac_filter" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| int fw_set_disable_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| struct uci_ptr ptr; |
| struct blob_attr *fw_setting[ARRAY_SIZE(fw_setting_pol)]; |
| int ret_val = 0; |
| int FW_set_type = 0; |
| const char *opt_val_2 = NULL; |
| |
| FW_DBG("enter"); |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting, blob_data(msg), blob_len(msg)) != 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| FW_ERR("get firewall failed"); |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "defaults") == 0) { |
| break; |
| } |
| } |
| if (!uci_sec) { |
| FW_DBG("can't find defaults section"); |
| goto EXIT; |
| } |
| if (fw_setting[DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "disable"; |
| ptr.value = blobmsg_get_string(fw_setting[DISABLE]); |
| uci_set(local_ctx, &ptr); |
| if (strcmp(blobmsg_get_string(fw_setting[DISABLE]), "1") == 0) { |
| FW_set_type = UI_FW_DISABLE; |
| } else { |
| FW_set_type = UI_FW_ENABLE; |
| } |
| } |
| if (fw_setting[IP_FILTER_DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[IP_FILTER_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "ip_filter_disable"; |
| ptr.value = blobmsg_get_string(fw_setting[IP_FILTER_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| if (strcmp(blobmsg_get_string(fw_setting[IP_FILTER_DISABLE]), "1") == 0) { |
| FW_set_type = UI_IP_FILTER_DISABLE; |
| } else { |
| FW_set_type = UI_IP_FILTER_ENABLE; |
| } |
| } |
| if (fw_setting[DN_FILTER_DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[DN_FILTER_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dn_filter_disable"; |
| ptr.value = blobmsg_get_string(fw_setting[DN_FILTER_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| if (strcmp(blobmsg_get_string(fw_setting[DN_FILTER_DISABLE]), "1") == 0) { |
| FW_set_type = UI_DN_FILTER_DISABLE; |
| } else { |
| FW_set_type = UI_DN_FILTER_ENABLE; |
| } |
| } |
| if (fw_setting[PORT_MAPPING_DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[PORT_MAPPING_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "port_mapping_disable"; |
| ptr.value = blobmsg_get_string(fw_setting[PORT_MAPPING_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (fw_setting[DMZ_DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[DMZ_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dmz_disable"; |
| ptr.value = blobmsg_get_string(fw_setting[DMZ_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| /*set redirect with fw_type:dmz start */ |
| uci_foreach_element(&p->sections, e) { |
| if (!strcmp(uci_sec->type, "redirect")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "dmz")) { |
| opt_val_2 = uci_lookup_option_string(local_ctx, uci_sec, "dest_ip"); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enabled"; |
| if (strcmp(blobmsg_get_string(fw_setting[DMZ_DISABLE]), "1") == 0) { |
| ptr.value = "0"; |
| } else { |
| ptr.value = "1"; |
| } |
| uci_set(local_ctx, &ptr); |
| } |
| } |
| /*set redirect with fw_type:dmz end */ |
| |
| /*set rule with filter_type:dmz start */ |
| if (opt_val_2 && !strcmp(uci_sec->type, "rule")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val && !strcmp(opt_val, "dmz")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "src_ip"); |
| if (opt_val && !strcmp(opt_val_2, opt_val)) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enabled"; |
| if (strcmp(blobmsg_get_string(fw_setting[DMZ_DISABLE]), "1") == 0) { |
| ptr.value = "0"; |
| } else { |
| ptr.value = "1"; |
| } |
| uci_set(local_ctx, &ptr); |
| } |
| } |
| } |
| /*set rule with filter_type:dmz end */ |
| } |
| } |
| if (fw_setting[UPNP_DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[UPNP_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "upnp_fw_disable"; |
| ptr.value = blobmsg_get_string(fw_setting[UPNP_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (fw_setting[PORT_TRIGGER_DISABLE]) { |
| FW_DBG("disabe is %s", blobmsg_get_string(fw_setting[PORT_TRIGGER_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "port_trigger_disable"; |
| ptr.value = blobmsg_get_string(fw_setting[PORT_TRIGGER_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| switch (FW_set_type) { |
| case UI_FW_ENABLE: |
| fw_system("/lib/router_fw/fw_ui_transfer.sh FW_ENABLE"); |
| fw_system("/etc/init.d/firewall restart"); |
| break; |
| case UI_FW_DISABLE: |
| fw_system("/lib/router_fw/fw_ui_transfer.sh FW_DISABLE"); |
| fw_system("/etc/init.d/firewall restart"); |
| break; |
| case UI_IP_FILTER_ENABLE: |
| fw_system("/lib/router_fw/fw_ui_transfer.sh IP_ENABLE"); |
| fw_system("/etc/init.d/firewall restart"); |
| break; |
| case UI_IP_FILTER_DISABLE: |
| fw_system("/lib/router_fw/fw_ui_transfer.sh IP_DISABLE"); |
| fw_system("/etc/init.d/firewall restart"); |
| break; |
| case UI_DN_FILTER_DISABLE: |
| fw_system("/lib/router_fw/fw_ui_transfer.sh DN_DISABLE"); |
| //fw_system("/etc/init.d/dhcp restart"); |
| break; |
| case UI_DN_FILTER_ENABLE: |
| fw_system("/lib/router_fw/fw_ui_transfer.sh DN_ENABLE"); |
| //fw_system("/etc/init.d/dhcp restart"); |
| break; |
| } |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| if (tb_fw) { |
| blobmsg_close_table(&fw_buf, tb_fw); |
| } |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <ip_filter> |
| <default_policy> |
| <entry_list> |
| <entry_index> |
| <start_time/> |
| <stop_time/> |
| <src_ip/> |
| <src_port/> |
| <dest_ip/> |
| <dest_port/> |
| <proto/> |
| <target/> |
| <enabled/> |
| </entry_index> |
| ... |
| </entry_list> |
| </ip_filter> |
| </firewall> |
| Note : add "option filter_type ip_filter/mac_filter" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| int fw_get_ip_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| void *tb_ip_filter = NULL; |
| void *tb_entry_list = NULL; |
| void *tb_entry_one = NULL; |
| int index = 1; |
| char index_buf[10] = { 0 }; |
| |
| FW_DBG("enter"); |
| |
| UNUSESET(obj); |
| UNUSESET(method); |
| UNUSESET(msg); |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (p) { |
| tb_ip_filter = blobmsg_open_table(&fw_buf, "ip_filter"); |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| |
| #if 0 |
| if (!strcmp(uci_sec->type, "zone")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "name"); |
| if (opt_val && !strcmp(opt_val, "wan")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "output"); |
| if (opt_val) { |
| FW_DBG("zone-->wan-->output is %s", opt_val); |
| blobmsg_add_string(&fw_buf, "default_policy", opt_val); |
| } |
| } else { |
| continue; |
| } |
| } |
| #endif |
| |
| if (!strcmp(uci_sec->type, "defaults")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ip_filter_policy"); |
| if (opt_val) { |
| FW_DBG("defaults.ip_filter_policy %s", opt_val); |
| blobmsg_add_string(&fw_buf, "default_policy", opt_val); |
| } else { |
| /*set default policy as ACCEPT*/ |
| blobmsg_add_string(&fw_buf, "default_policy", "ACCEPT"); |
| } |
| } |
| |
| if (strcmp(uci_sec->type, "rule") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val) { |
| FW_DBG("filter_type is %s", opt_val); |
| } |
| if (opt_val && !strcmp(opt_val, "ip_filter")) { |
| FW_DBG("filter_type is %s", opt_val); |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "last_rule"); |
| if (opt_val && !strcmp(opt_val, "1")) { |
| /*suppress the last rule to webui*/ |
| FW_DBG("last rule in ip filter"); |
| continue; |
| } |
| |
| if (!tb_entry_list) { |
| tb_entry_list = blobmsg_open_table(&fw_buf, "entry_list"); |
| } |
| memset(index_buf, 0, 10); |
| snprintf(index_buf, 10, "entry_%d", index++); |
| FW_DBG("get one ip filter:%s", index_buf); |
| tb_entry_one = blobmsg_open_table(&fw_buf, index_buf); |
| /*start time */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "start_time"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "start_time", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "start_time", "none"); |
| } |
| /*stop time */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "stop_time"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "stop_time", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "stop_time", "none"); |
| } |
| /*src_ip */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "src_ip"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "src_ip", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "src_ip", "0"); |
| } |
| /*src port */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "src_port"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "src_port", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "src_port", "none"); |
| } |
| /*dest ip */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dest_ip"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "dest_ip", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "dest_ip", "0"); |
| } |
| /*dest port */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dest_port"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "dest_port", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "dest_port", "none"); |
| } |
| /*proto; tcp,udp,tcpudp,udplite,icmp,esp,ah,sctp */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "proto"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "proto", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "proto", "none"); |
| } |
| /*target */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "target"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "target", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "target", "none"); |
| } |
| /*enabled */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "enabled"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "enabled", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "enabled", "1"); |
| } |
| blobmsg_close_table(&fw_buf, tb_entry_one); |
| } |
| } |
| } |
| if (tb_entry_list) { |
| blobmsg_close_table(&fw_buf, tb_entry_list); |
| } |
| blobmsg_close_table(&fw_buf, tb_ip_filter); |
| } else { |
| blobmsg_add_string(&fw_buf, "disable", "1"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <ip_filter> |
| <default_policy/> |
| <entry_list> |
| <entry_index> |
| <start_time/> |
| <stop_time/> |
| <src_ip/> |
| <src_port/> |
| <dest_ip/> |
| <dest_port/> |
| <proto/> |
| <target/> |
| </entry_index> |
| ... |
| </entry_list> |
| </ip_filter> |
| </firewall> |
| Note : add "option filter_type ip_filter/mac_filter" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| enum { |
| DEFAULT_IP_FILTER_POL, |
| IP_FILTER_ENTRY_LIST, |
| }; |
| static const struct blobmsg_policy fw_set_ipfilter_pol[] = { |
| [DEFAULT_IP_FILTER_POL] = { |
| .name = "default_policy", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [IP_FILTER_ENTRY_LIST] = { |
| .name = "entry_list", |
| .type = BLOBMSG_TYPE_TABLE, |
| }, |
| }; |
| |
| enum { |
| START_TIME, |
| STOP_TIME, |
| SRC_IP, |
| SRC_PORT, |
| DEST_IP, |
| DEST_PORT, |
| PROTO, |
| TARGET, |
| ENABLED, |
| }; |
| static const struct blobmsg_policy ipfilter_entry_pol[] = { |
| [START_TIME] = { |
| .name = "start_time", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [STOP_TIME] = { |
| .name = "stop_time", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [SRC_IP] = { |
| .name = "src_ip", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [SRC_PORT] = { |
| .name = "src_port", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [DEST_IP] = { |
| .name = "dest_ip", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [DEST_PORT] = { |
| .name = "dest_port", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [PROTO] = { |
| .name = "proto", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [TARGET] = { |
| .name = "target", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [ENABLED] = { |
| .name = "enabled", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| }; |
| |
| enum { |
| SET_ADD_IPFILTER_ENTRY, |
| EDIT_IPFILTER_ENTRY, |
| }; |
| static int fw_set_ip_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg, int type) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| int ret_val = 0; |
| struct uci_ptr ptr; |
| struct blob_attr *attr; |
| struct blobmsg_hdr *hdr; |
| int edit_index = 0; |
| int index = 0; |
| struct blob_attr *fw_setting[ARRAY_SIZE(fw_setting_pol)]; |
| struct blob_attr *ipfilter_pol_arrt[ARRAY_SIZE(fw_set_ipfilter_pol)]; |
| struct blob_attr *entry_pol[ARRAY_SIZE(ipfilter_entry_pol)]; |
| struct blob_attr *attr_head = NULL; |
| int attr_len = 0; |
| bool default_policy_changed = false; |
| bool black_to_white = false; |
| bool last_rule_exist = false; |
| bool default_policy_first_set = false; |
| |
| FW_DBG("enter"); |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting, blob_data(msg), blob_len(msg)) != 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting[IP_FILTER]) { |
| goto EXIT; |
| } |
| |
| if (blobmsg_parse |
| (fw_set_ipfilter_pol, ARRAY_SIZE(fw_set_ipfilter_pol), ipfilter_pol_arrt, |
| blobmsg_data(fw_setting[IP_FILTER]), blobmsg_data_len(fw_setting[IP_FILTER])) != 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL] && !ipfilter_pol_arrt[IP_FILTER_ENTRY_LIST]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| /*SET DEFAULT POL */ |
| if (ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]) { |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| |
| #if 0 |
| if (strcmp(uci_sec->type, "zone") == 0) { |
| FW_DBG("zone->wan->output->%s", blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL])); |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "name"); |
| if (opt_val && !strcmp(opt_val, "wan")) { |
| |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "output"); |
| if (!strcmp(opt_val, blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]))) |
| { |
| /*policy not changed*/ |
| FW_DBG("policy %s not changed", blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL])); |
| break; |
| } |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "output"; |
| ptr.value = blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]); |
| uci_set(local_ctx, &ptr); |
| default_policy_changed = true; |
| break; |
| } |
| } |
| #endif |
| |
| if (strcmp(uci_sec->type, "defaults") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ip_filter_policy"); |
| if (opt_val ) { |
| if ( !strcmp(opt_val, blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]))) { |
| /*policy not changed*/ |
| FW_DBG("policy %s not changed", blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL])); |
| break; |
| } else { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "ip_filter_policy"; |
| ptr.value = blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]); |
| uci_set(local_ctx, &ptr); |
| default_policy_changed = true; |
| } |
| } else { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "ip_filter_policy"; |
| ptr.value = blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]); |
| uci_set(local_ctx, &ptr); |
| |
| default_policy_first_set = true; |
| /*ACCEPT->REJECT*/ |
| if (!strcmp( blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]), "REJECT")) |
| default_policy_changed = true; |
| } |
| break; |
| } |
| } |
| } |
| /*add new ipfilter entry */ |
| if (ipfilter_pol_arrt[IP_FILTER_ENTRY_LIST]) { |
| attr_head = blobmsg_data(ipfilter_pol_arrt[IP_FILTER_ENTRY_LIST]); |
| attr_len = blobmsg_data_len(ipfilter_pol_arrt[IP_FILTER_ENTRY_LIST]); |
| __blob_for_each_attr(attr, attr_head, attr_len) { |
| hdr = blob_data(attr); |
| /*name as entry_index,entry_1, entry_2,eg. */ |
| if (hdr->name) { |
| FW_DBG("add new ipfiter -- %s", hdr->name); |
| } |
| if (!strstr((char *)hdr->name, "entry")) { |
| continue; |
| } |
| if (type == EDIT_IPFILTER_ENTRY) { |
| if (sscanf((char *)hdr->name, "%*5s_%d", &edit_index) == 1) { |
| FW_DBG("get edit index -- %d", edit_index); |
| } else { |
| FW_DBG("get edit index fail"); |
| ret_val = 1; |
| goto EXIT; |
| } |
| |
| } |
| /*type should be table */ |
| if (blob_id(attr) != BLOBMSG_TYPE_TABLE) { |
| continue; |
| } |
| FW_DBG("GOT ONE NEW ENTRY"); |
| if (blobmsg_parse |
| (ipfilter_entry_pol, ARRAY_SIZE(ipfilter_entry_pol), entry_pol, blobmsg_data(attr), |
| blobmsg_data_len(attr)) == 0) { |
| if (type == SET_ADD_IPFILTER_ENTRY) { |
| /*add one section with type :rule */ |
| uci_add_section(local_ctx, p, "rule", &uci_sec); |
| } else if (type == EDIT_IPFILTER_ENTRY) { |
| index = 0; |
| /*find the rule */ |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "rule")) { |
| opt_val = |
| uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val && !strcmp(opt_val, "ip_filter")) { |
| index++; |
| FW_DBG("index : %d, edit_index : %d", index, |
| edit_index); |
| if (index == edit_index) { |
| break; |
| } |
| } |
| } |
| } |
| } |
| if (uci_sec) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src"; |
| ptr.value = "lan"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dest"; |
| ptr.value = "wan"; |
| uci_set(local_ctx, &ptr); |
| |
| if (entry_pol[START_TIME]) { |
| FW_DBG("start_time is %s", blobmsg_get_string(entry_pol[START_TIME])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "start_time"; |
| ptr.value = blobmsg_get_string(entry_pol[START_TIME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[STOP_TIME]) { |
| FW_DBG("STOP_TIME is %s", blobmsg_get_string(entry_pol[STOP_TIME])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "stop_time"; |
| ptr.value = blobmsg_get_string(entry_pol[STOP_TIME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[SRC_IP]) { |
| FW_DBG("SRC_IP is %s", blobmsg_get_string(entry_pol[SRC_IP])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src_ip"; |
| ptr.value = blobmsg_get_string(entry_pol[SRC_IP]); |
| if (!strcmp(ptr.value, "0")) |
| uci_delete(local_ctx, &ptr); |
| else |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[SRC_PORT]) { |
| FW_DBG("SRC_PORT is %s", blobmsg_get_string(entry_pol[SRC_PORT])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src_port"; |
| ptr.value = blobmsg_get_string(entry_pol[SRC_PORT]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[DEST_IP]) { |
| FW_DBG("DEST_IP is %s", blobmsg_get_string(entry_pol[DEST_IP])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dest_ip"; |
| ptr.value = blobmsg_get_string(entry_pol[DEST_IP]); |
| if (!strcmp(ptr.value, "0")) |
| uci_delete(local_ctx, &ptr); |
| else |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[DEST_PORT]) { |
| FW_DBG("DEST_PORT is %s", blobmsg_get_string(entry_pol[DEST_PORT])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dest_port"; |
| ptr.value = blobmsg_get_string(entry_pol[DEST_PORT]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[PROTO]) { |
| FW_DBG("PROTO is %s", blobmsg_get_string(entry_pol[PROTO])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "proto"; |
| ptr.value = blobmsg_get_string(entry_pol[PROTO]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[TARGET]) { |
| FW_DBG("TARGET is %s", blobmsg_get_string(entry_pol[TARGET])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "target"; |
| ptr.value = blobmsg_get_string(entry_pol[TARGET]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_pol[ENABLED]) { |
| FW_DBG("ENABLED is %s", blobmsg_get_string(entry_pol[ENABLED])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "ui_enabled"; |
| ptr.value = blobmsg_get_string(entry_pol[ENABLED]); |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enabled"; |
| ptr.value = blobmsg_get_string(entry_pol[ENABLED]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (type == SET_ADD_IPFILTER_ENTRY) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "filter_type"; |
| ptr.value = "ip_filter"; |
| uci_set(local_ctx, &ptr); |
| } |
| } |
| } |
| } |
| } |
| |
| /*add/reorder last rule*/ |
| if (type == SET_ADD_IPFILTER_ENTRY || default_policy_first_set) { |
| /*check whether exist*/ |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "rule")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val && !strcmp(opt_val, "ip_filter")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "last_rule"); |
| if (opt_val && !strcmp(opt_val, "1")) { |
| FW_DBG("find rule.last_rule for ip filter type, reorder target %s to tail", blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL])); |
| /*reorder the section to tail, make the position enough large*/ |
| uci_reorder_section(local_ctx, uci_sec, 1000); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "target"; |
| ptr.value = blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]); |
| uci_set(local_ctx, &ptr); |
| |
| last_rule_exist = true; |
| break; |
| } |
| } |
| } |
| } |
| |
| if (!last_rule_exist) { |
| uci_add_section(local_ctx, p, "rule", &uci_sec); |
| /*add last rule in tail*/ |
| if (uci_sec) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src"; |
| ptr.value = "lan"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dest"; |
| ptr.value = "wan"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src_ip"; |
| ptr.value = "any"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "proto"; |
| ptr.value = "all"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "target"; |
| ptr.value = blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]); |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "ui_enable"; |
| ptr.value = "1"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enable"; |
| ptr.value = "1"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "filter_type"; |
| ptr.value = "ip_filter"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "last_rule"; |
| ptr.value = "1"; |
| uci_set(local_ctx, &ptr); |
| |
| last_rule_exist = true; |
| } |
| } |
| } |
| |
| if (default_policy_changed) { |
| /*white-list change to black-list*/ |
| if (!strcmp(blobmsg_get_string(ipfilter_pol_arrt[DEFAULT_IP_FILTER_POL]), "REJECT")) |
| black_to_white = true; |
| |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| /*change target for every rule*/ |
| if (strcmp(uci_sec->type, "rule") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val && !strcmp(opt_val, "ip_filter")) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "target"; |
| |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "last_rule"); |
| if (opt_val && !strcmp(opt_val, "1")) { |
| /*the last rule*/ |
| if (black_to_white) |
| ptr.value = "REJECT"; |
| else |
| ptr.value = "ACCEPT"; |
| } else { |
| if (black_to_white) |
| ptr.value = "ACCEPT"; |
| else |
| ptr.value = "REJECT"; |
| } |
| uci_set(local_ctx, &ptr); |
| } |
| } |
| } |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| if (default_policy_changed || default_policy_first_set |
| || ipfilter_pol_arrt[IP_FILTER_ENTRY_LIST]) |
| fw_system("/etc/init.d/firewall restart"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <ip_filter> |
| <entry_list> |
| <entry_index> |
| <start_time/> |
| <stop_time/> |
| <src_ip/> |
| <src_port/> |
| <dest_ip/> |
| <dest_port/> |
| <proto/> |
| <target/> |
| </entry_index> |
| ... |
| </entry_list> |
| </ip_filter> |
| </firewall> |
| Note : add "option filter_type ip_filter/mac_filter" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| int fw_set_add_ip_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_ip_filter_info_cb(ctx, obj, req, method, msg, SET_ADD_IPFILTER_ENTRY); |
| } |
| |
| int fw_update_ip_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_ip_filter_info_cb(ctx, obj, req, method, msg, EDIT_IPFILTER_ENTRY); |
| } |
| |
| /*================================================ |
| <firewall> |
| <delete_ipfilter_index> |
| </firewall> |
| seperate by ',' |
| ================================================*/ |
| int fw_delete_ip_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| struct uci_ptr ptr; |
| int ret_val = 0; |
| struct uci_section **delete_uci_array = NULL; |
| int delete_num = 0; |
| char *begin = NULL; |
| char *end = NULL; |
| int *del_index_array = NULL; |
| char tmp_buf[5] = { 0 }; |
| int cur_index = 0; |
| int tmp_index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| |
| FW_DBG("enter"); |
| UNUSESET(obj); |
| UNUSESET(method); |
| |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_DBG("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[DELETE_IP_FILTER]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| FW_DBG("delete index is %s", blobmsg_get_string(fw_setting_attr[DELETE_IP_FILTER])); |
| if (fw_setting_attr[DELETE_IP_FILTER]) { |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_IP_FILTER]); |
| |
| /*to get the number of delete index */ |
| while ((begin = strchr(begin, ','))) { |
| delete_num++; |
| begin++; |
| } |
| FW_DBG(" delete total is %d", delete_num); |
| if (delete_num == 0) { |
| ret_val = 2; |
| goto EXIT; |
| } |
| /*malloc memory */ |
| delete_uci_array = (struct uci_section **)malloc(delete_num * sizeof(struct uci_section *)); |
| memset(delete_uci_array, 0, delete_num * sizeof(struct uci_section *)); |
| del_index_array = (int *)malloc(delete_num * sizeof(int)); |
| memset(del_index_array, 0, delete_num * sizeof(int)); |
| |
| /*get the index, storing into del_index_array */ |
| cur_index = 0; |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_IP_FILTER]); |
| while ((end = strchr(begin, ','))) { |
| memset(tmp_buf, 0, 5); |
| if (end - begin < 5) { |
| memcpy(tmp_buf, begin, end - begin); |
| FW_DBG("tmp_buf is %s", tmp_buf); |
| } else { |
| FW_DBG("parse deleting index wrong"); |
| break;; |
| } |
| if (cur_index > delete_num) { |
| break; |
| } |
| del_index_array[cur_index++] = atoi(tmp_buf); |
| begin = end + 1; |
| } |
| /*Print the delete index */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| FW_DBG("delete index %d", del_index_array[tmp_index]); |
| } |
| /*travel the sections ,and storing the deleting uci_sec to delete_uci_array */ |
| cur_index = 0; |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "rule") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val && !strcmp(opt_val, "ip_filter")) { |
| cur_index++; |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| if (del_index_array[tmp_index] == 0) { |
| continue; |
| } |
| if (cur_index == del_index_array[tmp_index]) { |
| FW_DBG("find uci_sec with index %d", cur_index); |
| delete_uci_array[tmp_index] = uci_sec; |
| break; |
| |
| } |
| } |
| } |
| } |
| } |
| |
| } |
| /*delete the section */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = (struct uci_section *)delete_uci_array[tmp_index]; |
| uci_delete(local_ctx, &ptr); |
| } |
| |
| EXIT: |
| if (del_index_array) { |
| free(del_index_array); |
| del_index_array = NULL; |
| } |
| if (delete_uci_array) { |
| free(delete_uci_array); |
| delete_uci_array = NULL; |
| } |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/etc/init.d/firewall restart"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <port_mapping> |
| <entry_list> |
| <entry_index> |
| <start_time/> |
| <stop_time/> |
| <src_dport/> |
| <dest_ip/> |
| <proto/> |
| <enabled> |
| </entry_index> |
| ... |
| </entry_list> |
| </port_mapping> |
| </firewall> |
| Note : add "option fw_type mapping/trigger" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| int fw_get_port_mapping_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| void *tb_port_mapping = NULL; |
| void *tb_entry_list = NULL; |
| void *tb_entry_one = NULL; |
| int index = 1; |
| char index_buf[10] = { 0 }; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| UNUSESET(msg); |
| |
| FW_DBG("enter"); |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (!strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (p) { |
| tb_port_mapping = blobmsg_open_table(&fw_buf, "port_mapping"); |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| |
| if (strcmp(uci_sec->type, "redirect") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "mapping")) { |
| FW_DBG("fw_type is %s", opt_val); |
| if (!tb_entry_list) { |
| tb_entry_list = blobmsg_open_table(&fw_buf, "entry_list"); |
| } |
| memset(index_buf, 0, 10); |
| snprintf(index_buf, 10, "entry_%d", index++); |
| FW_DBG("get one port_fw mapping %s", index_buf); |
| tb_entry_one = blobmsg_open_table(&fw_buf, index_buf); |
| /*start time */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "start_time"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "start_time", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "start_time", "none"); |
| } |
| /*stop time */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "stop_time"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "stop_time", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "stop_time", "none"); |
| } |
| /*src dport */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "src_dport"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "src_dport", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "src_dport", "none"); |
| } |
| /*dest ip */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dest_ip"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "dest_ip", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "dest_ip", "none"); |
| } |
| |
| /*proto; tcp,udp,tcpudp,udplite,icmp,esp,ah,sctp */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "proto"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "proto", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "proto", "none"); |
| } |
| /*enabled */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "enabled"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "enabled", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "enabled", "1"); |
| } |
| blobmsg_close_table(&fw_buf, tb_entry_one); |
| } |
| } |
| } |
| if (tb_entry_list) { |
| blobmsg_close_table(&fw_buf, tb_entry_list); |
| } |
| blobmsg_close_table(&fw_buf, tb_port_mapping); |
| } else { |
| blobmsg_add_string(&fw_buf, "disable", "1"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <port_mapping> |
| <entry_list> |
| <entry_index> |
| <start_time/> |
| <stop_time/> |
| <src_dport/> |
| <dest_ip/> |
| <proto/> |
| </entry_index> |
| ... |
| </entry_list> |
| </port_mapping> |
| </firewall> |
| Note : add "option fw_type mapping/trigger" under "config rule" to |
| distinguish between IP filter and mac filter |
| ================================================*/ |
| enum { |
| ADD_PORT_MAPPING_ENTRY, |
| EDIT_PORT_MAPPING_ENTRY, |
| }; |
| enum { |
| MAPPING_START_TIME, |
| MAPPING_STOP_TIME, |
| MAPPING_SRC_DPORT, |
| MAPPING_DEST_IP, |
| MAPPING_PROTO, |
| MAPPING_ENABLED, |
| }; |
| static const struct blobmsg_policy port_mapping_entry_pol[] = { |
| [MAPPING_START_TIME] = { |
| .name = "start_time", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [MAPPING_STOP_TIME] = { |
| .name = "stop_time", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [MAPPING_SRC_DPORT] = { |
| .name = "src_dport", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [MAPPING_DEST_IP] = { |
| .name = "dest_ip", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [MAPPING_PROTO] = { |
| .name = "proto", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [MAPPING_ENABLED] = { |
| .name = "enabled", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| }; |
| |
| enum { |
| PORT_MAPPING_ENTRY_LIST, |
| }; |
| static const struct blobmsg_policy fw_set_port_mapping_pol[] = { |
| [PORT_MAPPING_ENTRY_LIST] = { |
| .name = "entry_list", |
| .type = BLOBMSG_TYPE_TABLE, |
| }, |
| }; |
| |
| static int fw_set_port_mapping_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg, long type) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| int ret_val = 0; |
| struct uci_ptr ptr; |
| struct blob_attr *attr; |
| struct blobmsg_hdr *hdr; |
| int edit_index = 0; |
| int index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| struct blob_attr *port_mapping_attr[ARRAY_SIZE(fw_set_port_mapping_pol)]; |
| struct blob_attr *entry_attr[ARRAY_SIZE(port_mapping_entry_pol)]; |
| struct blob_attr *attr_head = NULL; |
| int attr_len = 0; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| FW_DBG("enter"); |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[PORT_MAPPING]) { |
| goto EXIT; |
| } |
| |
| if (blobmsg_parse |
| (fw_set_port_mapping_pol, ARRAY_SIZE(fw_set_port_mapping_pol), port_mapping_attr, |
| blobmsg_data(fw_setting_attr[PORT_MAPPING]), blobmsg_data_len(fw_setting_attr[PORT_MAPPING])) != 0) { |
| FW_DBG("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!port_mapping_attr[PORT_MAPPING_ENTRY_LIST]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| /*add new port mapping entry */ |
| if (port_mapping_attr[PORT_MAPPING_ENTRY_LIST]) { |
| FW_DBG("add new port mapping"); |
| attr_head = blobmsg_data(port_mapping_attr[PORT_MAPPING_ENTRY_LIST]); |
| attr_len = blobmsg_data_len(port_mapping_attr[PORT_MAPPING_ENTRY_LIST]); |
| __blob_for_each_attr(attr, attr_head, attr_len) { |
| hdr = blob_data(attr); |
| /*name as entry_index,entry_1, entry_2,eg. */ |
| if (hdr->name) { |
| FW_DBG("add new ipfiter -- %s", hdr->name); |
| } |
| if (!strstr((char *)hdr->name, "entry")) { |
| continue; |
| } |
| if (type == EDIT_PORT_MAPPING_ENTRY) { |
| if (sscanf((char *)hdr->name, "%*5s_%d", &edit_index) == 1) { |
| FW_DBG("get edit index -- %d", edit_index); |
| } else { |
| FW_DBG("get edit index fail"); |
| ret_val = 1; |
| goto EXIT; |
| } |
| } |
| /*type should be table */ |
| if (blob_id(attr) != BLOBMSG_TYPE_TABLE) { |
| continue; |
| } |
| FW_DBG("GOT ONE NEW ENTRY"); |
| if (blobmsg_parse |
| (port_mapping_entry_pol, ARRAY_SIZE(port_mapping_entry_pol), entry_attr, blobmsg_data(attr), |
| blobmsg_data_len(attr)) == 0) { |
| if (type == ADD_PORT_MAPPING_ENTRY) { |
| /*add one section with type :rule */ |
| uci_add_section(local_ctx, p, "redirect", &uci_sec); |
| } else if (type == EDIT_PORT_MAPPING_ENTRY) { |
| index = 0; |
| /*find the rule */ |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "redirect")) { |
| opt_val = |
| uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "mapping")) { |
| index++; |
| if (index == edit_index) { |
| FW_DBG("find edit index %d", index); |
| break; |
| } |
| |
| } |
| } |
| } |
| } |
| if (uci_sec) { |
| FW_DBG("uci_sec OK!"); |
| if (entry_attr[MAPPING_START_TIME]) { |
| FW_DBG("start_time is %s", |
| blobmsg_get_string(entry_attr[MAPPING_START_TIME])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "start_time"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_START_TIME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[MAPPING_STOP_TIME]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "stop_time"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_STOP_TIME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[MAPPING_SRC_DPORT]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src_dport"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_SRC_DPORT]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[MAPPING_DEST_IP]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dest_ip"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_DEST_IP]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[MAPPING_PROTO]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "proto"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_PROTO]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[MAPPING_ENABLED]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enabled"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_ENABLED]); |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "ui_enabled"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_ENABLED]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (type == ADD_PORT_MAPPING_ENTRY) { |
| /*add fw type */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "fw_type"; |
| ptr.value = "mapping"; |
| uci_set(local_ctx, &ptr); |
| |
| /*add src */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "src"; |
| ptr.value = "wan"; |
| uci_set(local_ctx, &ptr); |
| |
| /*add dest */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dest"; |
| ptr.value = "lan"; |
| uci_set(local_ctx, &ptr); |
| } |
| } else { |
| FW_DBG("uci_sec is NULL"); |
| } |
| } |
| } |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| FW_DBG("ret_val : %d", ret_val); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/etc/init.d/firewall restart"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| int fw_add_port_mapping_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_port_mapping_cb(ctx, obj, req, method, msg, ADD_PORT_MAPPING_ENTRY); |
| } |
| |
| int fw_update_port_mapping_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_port_mapping_cb(ctx, obj, req, method, msg, EDIT_PORT_MAPPING_ENTRY); |
| } |
| |
| /*================================================ |
| <firewall> |
| <del_port_mapping_index> |
| </firewall> |
| seperate by ',' |
| ================================================*/ |
| int fw_delete_port_mapping_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| struct uci_ptr ptr; |
| int ret_val = 0; |
| struct uci_section **delete_uci_array = NULL; |
| int delete_num = 0; |
| char *begin = NULL; |
| char *end = NULL; |
| int *del_index_array = NULL; |
| char tmp_buf[5] = { 0 }; |
| int cur_index = 0; |
| int tmp_index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| FW_DBG("enter"); |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[DELETE_PORT_MAPPING]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| FW_DBG("delete index is %s", blobmsg_get_string(fw_setting_attr[DELETE_PORT_MAPPING])); |
| if (fw_setting_attr[DELETE_PORT_MAPPING]) { |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_PORT_MAPPING]); |
| |
| /*to get the number of delete index */ |
| while ((begin = strchr(begin, ','))) { |
| delete_num++; |
| begin++; |
| } |
| FW_DBG(" delete total is %d", delete_num); |
| if (delete_num == 0) { |
| ret_val = 2; |
| goto EXIT; |
| } |
| /*malloc memory */ |
| delete_uci_array = (struct uci_section **)malloc(delete_num * sizeof(struct uci_section *)); |
| memset(delete_uci_array, 0, delete_num * sizeof(struct uci_section *)); |
| del_index_array = (int *)malloc(delete_num * sizeof(int)); |
| memset(del_index_array, 0, delete_num * sizeof(int)); |
| |
| /*get the index, storing into del_index_array */ |
| cur_index = 0; |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_PORT_MAPPING]); |
| while ((end = strchr(begin, ','))) { |
| memset(tmp_buf, 0, 5); |
| if (end - begin < 5) { |
| memcpy(tmp_buf, begin, end - begin); |
| } else { |
| continue; |
| } |
| if (cur_index > delete_num) { |
| break; |
| } |
| del_index_array[cur_index++] = atoi(tmp_buf); |
| begin = end + 1; |
| } |
| /*Print the delete index */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| FW_DBG("delete index %d", del_index_array[tmp_index]); |
| } |
| /*travel the sections ,and storing the deleting uci_sec to delete_uci_array */ |
| cur_index = 0; |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "redirect") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "mapping")) { |
| cur_index++; |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| if (del_index_array[tmp_index] == 0) { |
| continue; |
| } |
| if (cur_index == del_index_array[tmp_index]) { |
| FW_DBG("find uci_sec with index %d", cur_index); |
| delete_uci_array[tmp_index] = uci_sec; |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| } |
| /*delete the section */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = delete_uci_array[tmp_index]; |
| uci_delete(local_ctx, &ptr); |
| } |
| |
| EXIT: |
| if (del_index_array) { |
| free(del_index_array); |
| del_index_array = NULL; |
| } |
| if (delete_uci_array) { |
| free(delete_uci_array); |
| delete_uci_array = NULL; |
| } |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/etc/init.d/firewall restart"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <dmz> |
| <entry_list> |
| <entry_index> |
| <dest_ip/> |
| </entry_index> |
| ... |
| </entry_list> |
| </dmz> |
| </firewall> |
| Note : add "option fw_type mapping/trigger/dmz" under "config redirect" |
| ================================================*/ |
| int fw_get_dmz_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| UNUSESET(msg); |
| |
| FW_DBG("enter"); |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (p) { |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| |
| if (strcmp(uci_sec->type, "redirect") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "dmz")) { |
| FW_DBG("fw_type is %s", opt_val); |
| /*dest ip */ |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dest_ip"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "dmz_dest_ip", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "dmz_dest_ip", "none"); |
| } |
| break; |
| } |
| } |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "disable", "1"); |
| } |
| if (tb_fw) { |
| blobmsg_close_table(&fw_buf, tb_fw); |
| } |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <dmz> |
| <entry_list> |
| <entry_index> |
| <dest_ip/> |
| </entry_index> |
| ... |
| </entry_list> |
| </dmz> |
| </firewall> |
| Note : add "option fw_type mapping/trigger/dmz" under "config redirect" |
| ================================================*/ |
| enum { |
| ADD_DMZ_ENTRY, |
| EDIT_DMZ_ENTRY, |
| }; |
| static int fw_set_dmz_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg, long type) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| struct uci_section *uci_dmz = NULL; |
| struct uci_section *uci_rule_sec = NULL; |
| const char *opt_val = NULL; |
| const char *opt_val_2 = NULL; |
| void *tb_fw = NULL; |
| int ret_val = 0; |
| struct uci_ptr ptr; |
| char *malloc_ptr = NULL; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| FW_DBG("enter"); |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[DMZ_HOST]) { |
| goto EXIT; |
| } |
| |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| /*add new ipfilter entry */ |
| if (fw_setting_attr[DMZ_HOST]) { |
| if (type == ADD_DMZ_ENTRY) { |
| /*add one section with type :rule */ |
| uci_add_section(local_ctx, p, "redirect", &uci_dmz); |
| } else if (type == EDIT_DMZ_ENTRY) { |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "redirect")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "dmz")) { |
| opt_val_2 = uci_lookup_option_string(local_ctx, uci_sec, "dest_ip"); |
| uci_dmz = uci_sec; |
| FW_DBG("find the edit redirect section"); |
| } |
| } |
| if (opt_val_2 && !strcmp(uci_sec->type, "rule")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val && !strcmp(opt_val, "dmz")) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "src_ip"); |
| if (opt_val && !strcmp(opt_val_2, opt_val)) { |
| FW_DBG("find the dmz rule"); |
| uci_rule_sec = uci_sec; |
| } |
| } |
| } |
| |
| } |
| } |
| |
| if (uci_dmz) { |
| if (fw_setting_attr[DMZ_HOST]) { |
| FW_DBG("DMZ_DEST_IP is %s", blobmsg_get_string(fw_setting_attr[DMZ_HOST])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_dmz; |
| ptr.option = "dest_ip"; |
| ptr.value = blobmsg_get_string(fw_setting_attr[DMZ_HOST]); |
| uci_set(local_ctx, &ptr); |
| |
| if (type == ADD_PORT_MAPPING_ENTRY) { |
| /*add fw type */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_dmz; |
| ptr.option = "fw_type"; |
| ptr.value = "dmz"; |
| uci_set(local_ctx, &ptr); |
| |
| /*add src */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_dmz; |
| ptr.option = "src"; |
| ptr.value = "wan"; |
| uci_set(local_ctx, &ptr); |
| |
| /*add dest */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_dmz; |
| ptr.option = "proto"; |
| ptr.value = "all"; |
| uci_set(local_ctx, &ptr); |
| |
| /*add enabled */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_dmz; |
| ptr.option = "enabled"; |
| ptr.value = "1"; |
| uci_set(local_ctx, &ptr); |
| |
| /*add another rule to block this ip to access anthor IP in lan */ |
| uci_add_section(local_ctx, p, "rule", &uci_rule_sec); /*need rule to block this IP to another client in lan */ |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "src"; |
| ptr.value = "lan"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "dest"; |
| ptr.value = "lan"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "src_ip"; |
| ptr.value = blobmsg_get_string(fw_setting_attr[DMZ_HOST]); |
| uci_set(local_ctx, &ptr); |
| |
| malloc_ptr = malloc(strlen(blobmsg_get_string(fw_setting_attr[DMZ_HOST])) + 5); |
| if (malloc_ptr) { |
| memset(malloc_ptr, 0, |
| strlen(blobmsg_get_string(fw_setting_attr[DMZ_HOST])) + 5); |
| snprintf(malloc_ptr, |
| strlen(blobmsg_get_string(fw_setting_attr[DMZ_HOST])) + 5, |
| "!%s", blobmsg_get_string(fw_setting_attr[DMZ_HOST])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "dest_ip"; |
| ptr.value = malloc_ptr; |
| uci_set(local_ctx, &ptr); |
| free(malloc_ptr); |
| malloc_ptr = NULL; |
| } |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "proto"; |
| ptr.value = "all"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "target"; |
| ptr.value = "reject"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "filter_type"; |
| ptr.value = "dmz"; |
| uci_set(local_ctx, &ptr); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "enabled"; |
| ptr.value = "1"; |
| uci_set(local_ctx, &ptr); |
| |
| } else if (type == EDIT_PORT_MAPPING_ENTRY) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "src_ip"; |
| ptr.value = blobmsg_get_string(fw_setting_attr[DMZ_HOST]); |
| uci_set(local_ctx, &ptr); |
| |
| malloc_ptr = malloc(strlen(blobmsg_get_string(fw_setting_attr[DMZ_HOST])) + 5); |
| if (malloc_ptr) { |
| memset(malloc_ptr, 0, |
| strlen(blobmsg_get_string(fw_setting_attr[DMZ_HOST])) + 5); |
| snprintf(malloc_ptr, |
| strlen(blobmsg_get_string(fw_setting_attr[DMZ_HOST])) + 5, |
| "!%s", blobmsg_get_string(fw_setting_attr[DMZ_HOST])); |
| |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_rule_sec; |
| ptr.option = "dest_ip"; |
| ptr.value = malloc_ptr; |
| uci_set(local_ctx, &ptr); |
| free(malloc_ptr); |
| malloc_ptr = NULL; |
| } |
| } |
| } |
| } |
| |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/etc/init.d/firewall restart"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| int fw_add_dmz_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_dmz_cb(ctx, obj, req, method, msg, ADD_DMZ_ENTRY); |
| } |
| |
| int fw_edit_dmz_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_dmz_cb(ctx, obj, req, method, msg, EDIT_DMZ_ENTRY); |
| } |
| |
| /*================================================ |
| <firewall> |
| <del_port_mapping_index> |
| </firewall> |
| seperate by ',' |
| ================================================*/ |
| int fw_delete_dmz_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| struct uci_section *uci_dmz_sec = NULL; |
| const char *opt_val = NULL; |
| const char *opt_val_2 = NULL; |
| void *tb_fw = NULL; |
| struct uci_ptr ptr; |
| int ret_val = 0; |
| |
| FW_DBG("enter"); |
| UNUSESET(method); |
| UNUSESET(obj); |
| UNUSESET(msg); |
| |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| if (local_ctx) { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "redirect") == 0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "fw_type"); |
| if (opt_val && !strcmp(opt_val, "dmz")) { |
| uci_dmz_sec = uci_sec; |
| break; |
| } |
| } |
| } |
| |
| /*delete the section */ |
| if (uci_dmz_sec) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_dmz_sec, "dest_ip"); |
| /*delete the rule */ |
| if (opt_val) { |
| FW_DBG("going to delet the rule--filter_type--dmz with ip: %s", opt_val); |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "rule") == 0) { |
| opt_val_2 = uci_lookup_option_string(local_ctx, uci_sec, "filter_type"); |
| if (opt_val_2 && !strcmp(opt_val_2, "dmz")) { |
| opt_val_2 = uci_lookup_option_string(local_ctx, uci_sec, "src_ip"); |
| if (opt_val_2) { |
| FW_DBG("rule->dmz->src_ip : %s", opt_val_2); |
| } |
| if (opt_val_2 && !strcmp(opt_val, opt_val_2)) { |
| FW_DBG("find the rule--filter_type--dmz with: %s", opt_val_2); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| uci_delete(local_ctx, &ptr); |
| break; |
| } |
| } |
| } |
| } |
| } |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_dmz_sec; |
| uci_delete(local_ctx, &ptr); |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/etc/init.d/firewall restart"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return 0; |
| } |
| |
| /*================================================ |
| <firewall> |
| <dn_filter> |
| <entry_list> |
| <entry_index> |
| <start_time/> |
| <stop_time/> |
| <domain_name/> |
| <enabled/> |
| </entry_index> |
| ... |
| </entry_list> |
| </dn_filter> |
| </firewall> |
| ================================================*/ |
| |
| int fw_get_dns_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| void *tb_dn_filter = NULL; |
| void *tb_entry_list = NULL; |
| int index = 1; |
| char index_buf[10] = { 0 }; |
| void *tb_entry_one = NULL; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| UNUSESET(msg); |
| |
| FW_DBG("enter"); |
| /*load /etc/config/dhcp */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (p) { |
| tb_dn_filter = blobmsg_open_table(&fw_buf, "dn_filter"); |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "dnsblacklist") == 0) { |
| FW_DBG("get one blacklist"); |
| if (!tb_entry_list) { |
| tb_entry_list = blobmsg_open_table(&fw_buf, "entry_list"); |
| } |
| memset(index_buf, 0, 10); |
| snprintf(index_buf, 10, "entry_%d", index++); |
| FW_DBG("get one port_fw mapping %s", index_buf); |
| tb_entry_one = blobmsg_open_table(&fw_buf, index_buf); |
| if (tb_entry_one) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "start_time"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "start_time", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "start_time", "00:00"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "stop_time"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "stop_time", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "stop_time", "00:00"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "domain_name"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "domain_name", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "domain_name", "NA"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "enabled"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "enabled", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "enabled", "NA"); |
| } |
| blobmsg_close_table(&fw_buf, tb_entry_one); |
| } |
| } |
| } |
| if (tb_entry_list) { |
| blobmsg_close_table(&fw_buf, tb_entry_list); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "dn_filter_disable", "1"); |
| } |
| if (tb_dn_filter) { |
| blobmsg_close_table(&fw_buf, tb_dn_filter); |
| } |
| if (tb_fw) { |
| blobmsg_close_table(&fw_buf, tb_fw); |
| } |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| return 0; |
| FW_DBG("leave"); |
| } |
| |
| enum { |
| ADD_DNS_FILTER_ENTRY, |
| EDIT_DNS_FILTER_ENTRY, |
| }; |
| |
| enum { |
| DNS_START_TIME, |
| DNS_STOP_TIME, |
| DNS_DOMAIN_NAME, |
| DNS_ENABLED, |
| }; |
| const struct blobmsg_policy dns_filter_entry_pol[] = { |
| [DNS_START_TIME] = { |
| .name = "start_time", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [DNS_STOP_TIME] = { |
| .name = "stop_time", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [DNS_DOMAIN_NAME] = { |
| .name = "domain_name", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [DNS_ENABLED] = { |
| .name = "enabled", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| }; |
| |
| enum { |
| DNS_FILTER_ENTRY_LIST, |
| }; |
| const struct blobmsg_policy fw_set_dns_filter_pol[] = { |
| [DNS_FILTER_ENTRY_LIST] = { |
| .name = "entry_list", |
| .type = BLOBMSG_TYPE_TABLE, |
| }, |
| }; |
| |
| static int fw_set_dns_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg, int type) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| void *tb_fw = NULL; |
| int ret_val = 0; |
| struct uci_ptr ptr; |
| struct blob_attr *attr; |
| struct blobmsg_hdr *hdr; |
| int edit_index = 0; |
| int index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| struct blob_attr *dns_filter_attr[ARRAY_SIZE(fw_set_dns_filter_pol)]; |
| struct blob_attr *entry_attr[ARRAY_SIZE(dns_filter_entry_pol)]; |
| struct blob_attr *attr_head = NULL; |
| int attr_len = 0; |
| int dns_filter_enable = 0; |
| const char *opt_val = NULL; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| FW_DBG("enter"); |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[DN_FILTER]) { |
| goto EXIT; |
| } |
| |
| if (blobmsg_parse |
| (fw_set_dns_filter_pol, ARRAY_SIZE(fw_set_dns_filter_pol), dns_filter_attr, |
| blobmsg_data(fw_setting_attr[DN_FILTER]), blobmsg_data_len(fw_setting_attr[DN_FILTER])) != 0) { |
| FW_DBG("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!dns_filter_attr[DNS_FILTER_ENTRY_LIST]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| if (fw_setting_attr[DN_FILTER_DISABLE]) { |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "defaults")) { |
| break; |
| } |
| } |
| FW_DBG("dns disabe is %s", blobmsg_get_string(fw_setting_attr[DN_FILTER_DISABLE])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "dn_filter_disable"; |
| ptr.value = blobmsg_get_string(fw_setting_attr[DN_FILTER_DISABLE]); |
| uci_set(local_ctx, &ptr); |
| if (strcmp(blobmsg_get_string(fw_setting_attr[DN_FILTER_DISABLE]), "0") == 0) { |
| dns_filter_enable = 1; |
| } |
| } |
| else{ |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "defaults")==0) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dn_filter_disable"); |
| if (opt_val) { |
| FW_DBG("dn_filter_disable string %s", opt_val); |
| if (strcmp(opt_val, "0") == 0){ |
| dns_filter_enable = 1; |
| }else{ |
| dns_filter_enable = 0; |
| } |
| } else { |
| dns_filter_enable = 0; |
| } |
| FW_DBG("dn_filter_disable is %d", dns_filter_enable); |
| break; |
| } |
| } |
| |
| } |
| if (dns_filter_attr[DNS_FILTER_ENTRY_LIST]) { |
| FW_DBG("add new dns filter"); |
| attr_head = blobmsg_data(dns_filter_attr[DNS_FILTER_ENTRY_LIST]); |
| attr_len = blobmsg_data_len(dns_filter_attr[DNS_FILTER_ENTRY_LIST]); |
| __blob_for_each_attr(attr, attr_head, attr_len) { |
| hdr = blob_data(attr); |
| /*name as entry_index,entry_1, entry_2,eg. */ |
| if (hdr->name) { |
| FW_DBG("add new ipfiter -- %s", hdr->name); |
| } |
| if (!strstr((char *)hdr->name, "entry")) { |
| continue; |
| } |
| if (type == EDIT_DNS_FILTER_ENTRY) { |
| if (sscanf((char *)hdr->name, "%*5s_%d", &edit_index) == 1) { |
| FW_DBG("get edit index -- %d", edit_index); |
| } else { |
| FW_DBG("get edit index fail"); |
| ret_val = 1; |
| goto EXIT; |
| } |
| } |
| /*type should be table */ |
| if (blob_id(attr) != BLOBMSG_TYPE_TABLE) { |
| continue; |
| } |
| FW_DBG("GOT ONE NEW ENTRY"); |
| if (blobmsg_parse |
| (dns_filter_entry_pol, ARRAY_SIZE(dns_filter_entry_pol), entry_attr, blobmsg_data(attr), |
| blobmsg_data_len(attr)) == 0) { |
| if (type == ADD_DNS_FILTER_ENTRY) { |
| /*add one section with type :dnsbacklist */ |
| uci_add_section(local_ctx, p, "dnsblacklist", &uci_sec); |
| } else if (type == EDIT_DNS_FILTER_ENTRY) { |
| index = 0; |
| /*find the rule */ |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "dnsblacklist")) { |
| index++; |
| if (index == edit_index) { |
| FW_DBG("find edit index %d", index); |
| break; |
| } |
| } |
| } |
| } |
| if (uci_sec) { |
| FW_DBG("uci_sec OK!"); |
| if (entry_attr[DNS_START_TIME]) { |
| FW_DBG("start_time is %s", |
| blobmsg_get_string(entry_attr[DNS_START_TIME])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "start_time"; |
| ptr.value = blobmsg_get_string(entry_attr[DNS_START_TIME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[DNS_STOP_TIME]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "stop_time"; |
| ptr.value = blobmsg_get_string(entry_attr[DNS_STOP_TIME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[DNS_DOMAIN_NAME]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "domain_name"; |
| ptr.value = blobmsg_get_string(entry_attr[DNS_DOMAIN_NAME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[DNS_ENABLED]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enabled"; |
| ptr.value = blobmsg_get_string(entry_attr[DNS_ENABLED]); |
| uci_set(local_ctx, &ptr); |
| } |
| } else { |
| FW_DBG("uci_sec is NULL"); |
| } |
| } |
| } |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| if (dns_filter_enable == 1) { |
| FW_DBG("exec fw_ui_transfer.sh "); |
| fw_system("/lib/router_fw/fw_ui_transfer.sh DN_RESET"); |
| //fw_system("/etc/init.d/dnsmasq restart"); |
| } |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return ret_val; |
| } |
| |
| int fw_add_dns_filter_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_dns_filter_info_cb(ctx, obj, req, method, msg, ADD_DNS_FILTER_ENTRY); |
| } |
| |
| int fw_update_dns_filter_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_dns_filter_info_cb(ctx, obj, req, method, msg, EDIT_DNS_FILTER_ENTRY); |
| } |
| |
| int fw_delete_dns_filter_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| struct uci_ptr ptr; |
| int ret_val = 0; |
| struct uci_section **delete_uci_array = NULL; |
| int delete_num = 0; |
| char *begin = NULL; |
| char *end = NULL; |
| int *del_index_array = NULL; |
| char tmp_buf[5] = { 0 }; |
| int cur_index = 0; |
| int tmp_index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| int dns_filter_enable = 0; |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_DBG("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[DELETE_DNS_ENTRY]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| FW_DBG("delete index is %s", blobmsg_get_string(fw_setting_attr[DELETE_DNS_ENTRY])); |
| if (fw_setting_attr[DELETE_DNS_ENTRY]) { |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_DNS_ENTRY]); |
| |
| /*to get the number of delete index */ |
| while ((begin = strchr(begin, ','))) { |
| delete_num++; |
| begin++; |
| } |
| FW_DBG(" delete total is %d", delete_num); |
| if (delete_num == 0) { |
| ret_val = 2; |
| goto EXIT; |
| } |
| /*malloc memory */ |
| delete_uci_array = (struct uci_section **)malloc(delete_num * sizeof(struct uci_section *)); |
| memset(delete_uci_array, 0, delete_num * sizeof(struct uci_section *)); |
| del_index_array = (int *)malloc(delete_num * sizeof(int)); |
| memset(del_index_array, 0, delete_num * sizeof(int)); |
| |
| /*get the index, storing into del_index_array */ |
| cur_index = 0; |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_DNS_ENTRY]); |
| while ((end = strchr(begin, ','))) { |
| memset(tmp_buf, 0, 5); |
| if (end - begin < 5) { |
| memcpy(tmp_buf, begin, end - begin); |
| } else { |
| continue; |
| } |
| if (cur_index > delete_num) { |
| break; |
| } |
| del_index_array[cur_index++] = atoi(tmp_buf); |
| begin = end + 1; |
| } |
| /*Print the delete index */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| FW_DBG("delete index %d", del_index_array[tmp_index]); |
| } |
| /*travel the sections ,and storing the deleting uci_sec to delete_uci_array */ |
| cur_index = 0; |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "dnsblacklist") == 0) { |
| cur_index++; |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| if (del_index_array[tmp_index] == 0) { |
| continue; |
| } |
| if (cur_index == del_index_array[tmp_index]) { |
| FW_DBG("find uci_sec with index %d", cur_index); |
| delete_uci_array[tmp_index] = uci_sec; |
| break; |
| } |
| } |
| } |
| } |
| |
| } |
| /*delete the section */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = delete_uci_array[tmp_index]; |
| uci_delete(local_ctx, &ptr); |
| } |
| |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "defaults")) { |
| break; |
| } |
| } |
| if (uci_sec) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dn_filter_disable"); |
| if (opt_val && strcmp(opt_val, "0") == 0) { |
| dns_filter_enable = 1; |
| } |
| } |
| |
| EXIT: |
| if (del_index_array) { |
| free(del_index_array); |
| del_index_array = NULL; |
| } |
| if (delete_uci_array) { |
| free(delete_uci_array); |
| delete_uci_array = NULL; |
| } |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| if (dns_filter_enable == 1) { |
| fw_system("/lib/router_fw/fw_ui_transfer.sh DN_RESET"); |
| //fw_system("/etc/init.d/dnsmasq restart"); |
| } |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return ret_val; |
| } |
| |
| /*================================================ |
| <firewall> |
| <port_trigger> |
| <entry_list> |
| <entry_index> |
| <rule_name/> |
| <trigger_proto/> |
| <out_port/> |
| <in_port/> |
| <enabled/> |
| |
| </entry_index> |
| ... |
| </entry_list> |
| </port_trigger> |
| </firewall> |
| ================================================*/ |
| |
| int fw_get_port_trigger_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| const char *opt_val = NULL; |
| void *tb_fw = NULL; |
| void *tb_port_trigger = NULL; |
| void *tb_entry_list = NULL; |
| int index = 1; |
| char index_buf[10] = { 0 }; |
| void *tb_entry_one = NULL; |
| |
| FW_DBG("enter"); |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| UNUSESET(msg); |
| /*load /etc/config/dhcp */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (tb_fw) { |
| tb_port_trigger = blobmsg_open_table(&fw_buf, "port_trigger"); |
| if (tb_port_trigger) { |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "port_trigger_rule") == 0) { |
| FW_DBG("get one port_trigger entry"); |
| if (!tb_entry_list) { |
| tb_entry_list = blobmsg_open_table(&fw_buf, "entry_list"); |
| } |
| memset(index_buf, 0, 10); |
| snprintf(index_buf, 10, "entry_%d", index++); |
| FW_DBG("get one port_trigger %s", index_buf); |
| tb_entry_one = blobmsg_open_table(&fw_buf, index_buf); |
| if (tb_entry_one) { |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "rule_name"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "rule_name", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "rule_name", "NA"); |
| } |
| |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "out_proto"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "out_proto", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "out_proto", "NA"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "in_proto"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "in_proto", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "in_proto", "NA"); |
| } |
| |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "out_port"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "out_port", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "out_port", "NA"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "in_port"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "in_port", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "in_port", "NA"); |
| } |
| opt_val = uci_lookup_option_string(local_ctx, uci_sec, "enabled"); |
| if (opt_val) { |
| blobmsg_add_string(&fw_buf, "enabled", opt_val); |
| } else { |
| blobmsg_add_string(&fw_buf, "enabled", "NA"); |
| } |
| blobmsg_close_table(&fw_buf, tb_entry_one); |
| } |
| } |
| } |
| if (tb_entry_list) { |
| blobmsg_close_table(&fw_buf, tb_entry_list); |
| } |
| blobmsg_close_table(&fw_buf, tb_port_trigger); |
| } |
| } else { |
| //blobmsg_add_string(&fw_buf, "disable", "1"); |
| } |
| if (tb_fw) { |
| blobmsg_close_table(&fw_buf, tb_fw); |
| } |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| return 0; |
| FW_DBG("leave"); |
| |
| } |
| |
| enum { |
| ADD_PORT_TRIGGER_ENTRY, |
| EDIT_PORT_TRIGGER_ENTRY, |
| }; |
| enum { |
| TRIGGER_RULE_NAME, |
| TRIGGER_OUT_PORT, |
| TRIGGER_IN_PORT, |
| TRIGGER_OUT_PROTO, |
| TRIGGER_IN_PROTO, |
| TRIGGER_ENABLED, |
| }; |
| static const struct blobmsg_policy port_trigger_entry_pol[] = { |
| [TRIGGER_RULE_NAME] = { |
| .name = "rule_name", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [TRIGGER_OUT_PORT] = { |
| .name = "out_port", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [TRIGGER_IN_PORT] = { |
| .name = "in_port", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [TRIGGER_OUT_PROTO] = { |
| .name = "out_proto", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [TRIGGER_IN_PROTO] = { |
| .name = "in_proto", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| [TRIGGER_ENABLED] = { |
| .name = "enabled", |
| .type = BLOBMSG_TYPE_STRING, |
| }, |
| }; |
| |
| enum { |
| PORT_TRIGGER_ENTRY_LIST, |
| }; |
| const struct blobmsg_policy fw_set_port_trigger_pol[] = { |
| [PORT_TRIGGER_ENTRY_LIST] = { |
| .name = "entry_list", |
| .type = BLOBMSG_TYPE_TABLE, |
| }, |
| }; |
| |
| static int fw_set_port_trigger_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, |
| struct blob_attr *msg, int type) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| void *tb_fw = NULL; |
| int ret_val = 0; |
| struct uci_ptr ptr; |
| struct blob_attr *attr; |
| struct blobmsg_hdr *hdr; |
| int edit_index = 0; |
| int index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| struct blob_attr *port_trigger_attr[ARRAY_SIZE(fw_set_port_mapping_pol)]; |
| struct blob_attr *entry_attr[ARRAY_SIZE(port_trigger_entry_pol)]; |
| struct blob_attr *attr_head = NULL; |
| int attr_len = 0; |
| |
| FW_DBG("enter"); |
| UNUSESET(method); |
| UNUSESET(obj); |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[PORT_TRIGGER]) { |
| goto EXIT; |
| } |
| |
| if (blobmsg_parse |
| (fw_set_port_trigger_pol, ARRAY_SIZE(fw_set_port_trigger_pol), port_trigger_attr, |
| blobmsg_data(fw_setting_attr[PORT_TRIGGER]), blobmsg_data_len(fw_setting_attr[PORT_TRIGGER])) != 0) { |
| FW_ERR("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!port_trigger_attr[PORT_TRIGGER_ENTRY_LIST]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| |
| /*load /etc/config/firewall */ |
| local_ctx = (struct uci_context *)uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| /*add new port trigger entry */ |
| if (port_trigger_attr[PORT_MAPPING_ENTRY_LIST]) { |
| FW_DBG("add/edit new port trigger"); |
| attr_head = blobmsg_data(port_trigger_attr[PORT_TRIGGER_ENTRY_LIST]); |
| attr_len = blobmsg_data_len(port_trigger_attr[PORT_TRIGGER_ENTRY_LIST]); |
| __blob_for_each_attr(attr, attr_head, attr_len) { |
| hdr = blob_data(attr); |
| /*name as entry_index,entry_1, entry_2,eg. */ |
| if (hdr->name) { |
| FW_DBG("add new ipfiter -- %s", hdr->name); |
| } |
| if (!strstr((char *)hdr->name, "entry")) { |
| continue; |
| } |
| if (type == EDIT_PORT_TRIGGER_ENTRY) { |
| if (sscanf((char *)hdr->name, "%*5s_%d", &edit_index) == 1) { |
| FW_DBG("get edit index -- %d", edit_index); |
| } else { |
| FW_DBG("get edit index fail"); |
| ret_val = 1; |
| goto EXIT; |
| } |
| } |
| /*type should be table */ |
| if (blob_id(attr) != BLOBMSG_TYPE_TABLE) { |
| continue; |
| } |
| FW_DBG("GOT ONE NEW ENTRY"); |
| if (blobmsg_parse |
| (port_trigger_entry_pol, ARRAY_SIZE(port_trigger_entry_pol), entry_attr, blobmsg_data(attr), |
| blobmsg_data_len(attr)) == 0) { |
| if (type == ADD_PORT_TRIGGER_ENTRY) { |
| /*add one section with type :port_trigger */ |
| uci_add_section(local_ctx, p, "port_trigger_rule", &uci_sec); |
| } else if (type == EDIT_PORT_TRIGGER_ENTRY) { |
| index = 0; |
| /*find the rule */ |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (!strcmp(uci_sec->type, "port_trigger_rule")) { |
| index++; |
| if (index == edit_index) { |
| FW_DBG("find edit index %d", index); |
| break; |
| } |
| |
| } |
| } |
| } |
| if (uci_sec) { |
| FW_DBG("uci_sec OK!"); |
| if (entry_attr[TRIGGER_RULE_NAME]) { |
| FW_DBG("TRIGGER_RULE_NAME is %s", |
| blobmsg_get_string(entry_attr[TRIGGER_RULE_NAME])); |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "rule_name"; |
| ptr.value = blobmsg_get_string(entry_attr[TRIGGER_RULE_NAME]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[TRIGGER_OUT_PORT]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "out_port"; |
| ptr.value = blobmsg_get_string(entry_attr[TRIGGER_OUT_PORT]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[TRIGGER_IN_PORT]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "in_port"; |
| ptr.value = blobmsg_get_string(entry_attr[TRIGGER_IN_PORT]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[TRIGGER_OUT_PROTO]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "out_proto"; |
| ptr.value = blobmsg_get_string(entry_attr[TRIGGER_OUT_PROTO]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[TRIGGER_IN_PROTO]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "in_proto"; |
| ptr.value = blobmsg_get_string(entry_attr[TRIGGER_IN_PROTO]); |
| uci_set(local_ctx, &ptr); |
| } |
| if (entry_attr[MAPPING_ENABLED]) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = uci_sec; |
| ptr.option = "enabled"; |
| ptr.value = blobmsg_get_string(entry_attr[MAPPING_ENABLED]); |
| uci_set(local_ctx, &ptr); |
| } |
| } else { |
| FW_DBG("uci_sec is NULL"); |
| } |
| } |
| } |
| } |
| |
| EXIT: |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| FW_DBG("ret_val : %d", ret_val); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/lib/router_fw/fw_ui_transfer.sh PORT_TRIGGER_RESET"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return ret_val; |
| FW_DBG("leave"); |
| } |
| |
| int fw_add_port_trigger_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_port_trigger_info_cb(ctx, obj, req, method, msg, ADD_PORT_TRIGGER_ENTRY); |
| } |
| |
| int fw_update_port_trigger_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| return fw_set_port_trigger_info_cb(ctx, obj, req, method, msg, EDIT_PORT_TRIGGER_ENTRY); |
| } |
| |
| /*================================================ |
| <firewall> |
| <del_port_trigger_index> |
| </firewall> |
| seperate by ',' |
| ================================================*/ |
| int fw_delete_port_trigger_info_cb(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, struct blob_attr *msg) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_element *e = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *uci_sec = NULL; |
| void *tb_fw = NULL; |
| struct uci_ptr ptr; |
| int ret_val = 0; |
| struct uci_section **delete_uci_array = NULL; |
| int delete_num = 0; |
| char *begin = NULL; |
| char *end = NULL; |
| int *del_index_array = NULL; |
| char tmp_buf[5] = { 0 }; |
| int cur_index = 0; |
| int tmp_index = 0; |
| struct blob_attr *fw_setting_attr[ARRAY_SIZE(fw_setting_pol)]; |
| FW_DBG("enter"); |
| |
| UNUSESET(method); |
| UNUSESET(obj); |
| |
| if (blobmsg_parse(fw_setting_pol, ARRAY_SIZE(fw_setting_pol), fw_setting_attr, blob_data(msg), blob_len(msg)) != |
| 0) { |
| FW_DBG("Parse failed\n"); |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| if (!fw_setting_attr[DELETE_PORT_TRIGGER]) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto EXIT; |
| } |
| /*load /etc/config/firewall */ |
| local_ctx = uci_fw_ctx_get(); |
| if (!local_ctx) { |
| assert(0); |
| } |
| FW_DBG("get uci ctx OK\r\n"); |
| |
| { |
| uci_foreach_element(&local_ctx->root, e) { |
| if (strcmp(e->name, FW_PACK) != 0) |
| continue; |
| p = uci_to_package(e); //have found |
| } |
| } |
| if (!p) { |
| uci_load(local_ctx, FW_PACK, &p); |
| } |
| if (!p) { |
| ret_val = UBUS_STATUS_NO_DATA; |
| goto EXIT; |
| } |
| FW_DBG("delete index is %s", blobmsg_get_string(fw_setting_attr[DELETE_PORT_TRIGGER])); |
| if (fw_setting_attr[DELETE_PORT_TRIGGER]) { |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_PORT_TRIGGER]); |
| |
| /*to get the number of delete index */ |
| while ((begin = strchr(begin, ','))) { |
| delete_num++; |
| begin++; |
| } |
| FW_DBG(" delete total is %d", delete_num); |
| if (delete_num == 0) { |
| ret_val = 2; |
| goto EXIT; |
| } |
| /*malloc memory */ |
| delete_uci_array = (struct uci_section **)malloc(delete_num * sizeof(struct uci_section *)); |
| memset(delete_uci_array, 0, delete_num * sizeof(struct uci_section *)); |
| del_index_array = (int *)malloc(delete_num * sizeof(int)); |
| memset(del_index_array, 0, delete_num * sizeof(int)); |
| |
| /*get the index, storing into del_index_array */ |
| cur_index = 0; |
| begin = blobmsg_get_string(fw_setting_attr[DELETE_PORT_TRIGGER]); |
| while ((end = strchr(begin, ','))) { |
| memset(tmp_buf, 0, 5); |
| if (end - begin < 5) { |
| memcpy(tmp_buf, begin, end - begin); |
| } else { |
| continue; |
| } |
| if (cur_index > delete_num) { |
| break; |
| } |
| del_index_array[cur_index++] = atoi(tmp_buf); |
| begin = end + 1; |
| } |
| /*Print the delete index */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| FW_DBG("delete index %d", del_index_array[tmp_index]); |
| } |
| /*travel the sections ,and storing the deleting uci_sec to delete_uci_array */ |
| cur_index = 0; |
| uci_foreach_element(&p->sections, e) { |
| uci_sec = uci_to_section(e); |
| if (strcmp(uci_sec->type, "port_trigger_rule") == 0) { |
| cur_index++; |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| if (del_index_array[tmp_index] == 0) { |
| continue; |
| } |
| if (cur_index == del_index_array[tmp_index]) { |
| FW_DBG("find uci_sec with index %d", cur_index); |
| delete_uci_array[tmp_index] = uci_sec; |
| break; |
| } |
| } |
| } |
| } |
| |
| } |
| /*delete the section */ |
| for (tmp_index = 0; tmp_index < delete_num; tmp_index++) { |
| memset(&ptr, 0, sizeof(struct uci_ptr)); |
| ptr.p = p; |
| ptr.s = delete_uci_array[tmp_index]; |
| uci_delete(local_ctx, &ptr); |
| } |
| |
| EXIT: |
| if (del_index_array) { |
| free(del_index_array); |
| del_index_array = NULL; |
| } |
| if (delete_uci_array) { |
| free(delete_uci_array); |
| delete_uci_array = NULL; |
| } |
| blobmsg_buf_init(&fw_buf); |
| tb_fw = blobmsg_open_table(&fw_buf, "firewall"); |
| if (ret_val == 0) { |
| blobmsg_add_string(&fw_buf, "setting_response", "OK"); |
| if (p) { |
| uci_commit(local_ctx, &p, false); |
| fw_system("/lib/router_fw/fw_ui_transfer.sh PORT_TRIGGER_RESET"); |
| } |
| } else { |
| blobmsg_add_string(&fw_buf, "setting_response", "ERROR"); |
| } |
| blobmsg_close_table(&fw_buf, tb_fw); |
| ubus_send_reply(ctx, req, fw_buf.head); |
| blob_buf_free(&fw_buf); |
| free_fw_uci_ctx(); |
| FW_DBG("leave"); |
| return ret_val; |
| } |
| #if 0 |
| static struct ubus_context *fw_ubus_ctx = NULL; |
| static const struct ubus_method fw_methods[] = { |
| UBUS_METHOD_NOARG("fw_get_disable_info", fw_get_disable_info_cb), |
| UBUS_METHOD("fw_set_disable_info", fw_set_disable_cb, fw_setting_pol), |
| UBUS_METHOD_NOARG("fw_get_ip_filter_info", fw_get_ip_filter_info_cb), |
| UBUS_METHOD("set_ip_filter_default_pol", fw_set_add_ip_filter_info_cb, fw_setting_pol), |
| UBUS_METHOD("add_ip_filter_entry", fw_set_add_ip_filter_info_cb, fw_setting_pol), |
| UBUS_METHOD("edit_ip_filter_entry", fw_update_ip_filter_info_cb, fw_setting_pol), |
| UBUS_METHOD("delete_ip_filter_entry", fw_delete_ip_filter_info_cb, fw_setting_pol), |
| UBUS_METHOD_NOARG("fw_get_port_mapping_info", fw_get_port_mapping_cb), |
| UBUS_METHOD("add_port_mapping_entry", fw_add_port_mapping_info_cb, fw_setting_pol), |
| UBUS_METHOD("edit_port_mapping_entry", fw_update_port_mapping_info_cb, fw_setting_pol), |
| UBUS_METHOD("delete_port_mapping_entry", fw_delete_port_mapping_info_cb, fw_setting_pol), |
| UBUS_METHOD_NOARG("fw_get_dmz_info", fw_get_dmz_cb), |
| UBUS_METHOD("fw_add_dmz_entry", fw_add_dmz_cb, fw_setting_pol), |
| UBUS_METHOD("fw_edit_dmz_entry", fw_edit_dmz_cb, fw_setting_pol), |
| UBUS_METHOD_NOARG("delete_dmz", fw_delete_dmz_cb), |
| UBUS_METHOD_NOARG("fw_get_port_trigger_info", fw_get_port_trigger_info_cb), |
| UBUS_METHOD("add_port_trigger_entry", fw_add_port_trigger_info_cb, fw_setting_pol), |
| UBUS_METHOD("edit_port_trigger_entry", fw_update_port_trigger_info_cb, fw_setting_pol), |
| UBUS_METHOD("delete_port_trigger_entry", fw_delete_port_trigger_info_cb, fw_setting_pol), |
| UBUS_METHOD_NOARG("fw_get_dn_filter_info", fw_get_dns_filter_info_cb), |
| UBUS_METHOD("add_dn_filter_entry", fw_add_dns_filter_cb, fw_setting_pol), |
| UBUS_METHOD("edit_dn_filter_entry", fw_update_dns_filter_cb, fw_setting_pol), |
| UBUS_METHOD("delete_dn_filter_entry", fw_delete_dns_filter_info_cb, fw_setting_pol), |
| }; |
| |
| static struct ubus_object_type fw_object_type = UBUS_OBJECT_TYPE("firewall", fw_methods); |
| |
| static struct ubus_object fw_service_object = { |
| .name = "firewall", |
| .type = &fw_object_type, |
| .methods = fw_methods, |
| .n_methods = ARRAY_SIZE(fw_methods), |
| }; |
| |
| static void fw_server_main(void) |
| { |
| int ret; |
| |
| FW_DBG("enter"); |
| ret = ubus_add_object(fw_ubus_ctx, &fw_service_object); |
| if (ret) |
| fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret)); |
| uloop_run(); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| const char *ubus_socket = NULL; |
| int ch; |
| |
| set_service_log_tag("router_fw"); |
| prctl(PR_SET_NAME, "router_firewall"); |
| |
| while ((ch = getopt(argc, argv, "cs:")) != -1) { |
| switch (ch) { |
| case 's': |
| ubus_socket = optarg; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| argc -= optind; |
| argv += optind; |
| |
| uloop_init(); |
| |
| signal(SIGPIPE, SIG_IGN); |
| fw_ubus_ctx = ubus_connect(ubus_socket); |
| |
| if (!fw_ubus_ctx) { |
| fprintf(stderr, "Failed to connect to ubus\n"); |
| return -1; |
| } |
| fw_system("/lib/router_fw/fw_ui_transfer.sh DN_RESET"); |
| //fw_system("/lib/router_fw/fw_ui_transfer.sh PORT_TRIGGER_RESET"); |
| |
| ubus_add_uloop(fw_ubus_ctx); |
| |
| fw_server_main(); |
| |
| ubus_free(fw_ubus_ctx); |
| uloop_done(); |
| |
| return 0; |
| } |
| #endif |