| #include "router_settings.h" |
| #include <sys/prctl.h> |
| #include "router_firewall.h" |
| |
| static struct uci_context *uci_ctx_router = NULL; |
| static struct ubus_subscriber ind_event; |
| |
| static void stop_ntp_timeout_cb(struct uloop_timeout *timeout); |
| void obj_cm_add_ev(struct ubus_context *ctx, char *obj_path); |
| |
| extern void init_util_wan_server(void); |
| extern void init_account_server(void); |
| extern void init_version_server(void); |
| extern void init_ussd_server(void); |
| extern void sim_server_main(void); |
| extern void wifi_server_main(void); |
| extern void sms_service_main(void); |
| extern void stk_server_main(void); |
| extern int pb_main(void); |
| extern int freelocallist(void); |
| extern int freesimlist(void); |
| |
| |
| static struct uloop_timeout stop_ntp_timeout = { |
| .cb = stop_ntp_timeout_cb, |
| }; |
| |
| struct uci_context *uci_router_ctx_get(void) |
| { |
| if (uci_ctx_router) { |
| return uci_ctx_router; |
| } |
| uci_ctx_router = uci_alloc_context(); |
| if (!uci_ctx_router) { |
| ROUTER_DBG("%s, uci_ctx_api malloc failed", __FUNCTION__); |
| return NULL; |
| } |
| return uci_ctx_router; |
| } |
| |
| /*free uci_ctx*/ |
| void free_router_uci_ctx(void) |
| { |
| if (uci_ctx_router) { |
| uci_free_context(uci_ctx_router); |
| uci_ctx_router = NULL; |
| } |
| } |
| |
| int router_system(const char *cmd) |
| { |
| FILE *fp; |
| int res; |
| char buf[1024]; |
| if (cmd == NULL) { |
| ROUTER_ERR("my_system cmd is NULL!\n"); |
| return -1; |
| } |
| if ((fp = popen(cmd, "r")) == NULL) { |
| ROUTER_ERR("popen error: %s/n", strerror(errno)); |
| return -1; |
| } else { |
| while (fgets(buf, sizeof(buf), fp)) { |
| ROUTER_DBG("%s", buf); |
| } |
| if ((res = pclose(fp)) == -1) { |
| ROUTER_ERR("close popen file pointer fp error!\n"); |
| return res; |
| } else if (res == 0) { |
| return res; |
| } else { |
| ROUTER_DBG("pclose res is :%d\n", res); |
| return res; |
| } |
| } |
| } |
| struct ubus_context *router_ubus_ctx = NULL; |
| |
| static const struct ubus_method router_methods[] = { |
| /*dhcp start */ |
| UBUS_METHOD_NOARG("router_get_lan_ip", router_get_lan_ip_cb), |
| UBUS_METHOD("router_set_lan_ip", router_set_lan_ip_cb, dhcp_setting_pol), |
| UBUS_METHOD_NOARG("router_get_dhcp_settings", dhcp_get_info_cb), |
| UBUS_METHOD("router_set_dhcp_settings", dhcp_set_info_cb, dhcp_setting_pol), |
| UBUS_METHOD_NOARG("dhcp_get_fixed_ip", dhcp_get_fixed_ip_cb), |
| UBUS_METHOD("dhcp_add_fixed_ip", dhcp_add_fixed_ip_cb, dhcp_setting_pol), |
| UBUS_METHOD("dhcp_edit_fixed_ip", dhcp_edit_fixed_ip_cb, dhcp_setting_pol), |
| UBUS_METHOD("dhcp_delete_fixed_ip", dhcp_delete_fixed_ip_cb, dhcp_setting_pol), |
| /*dhcp end */ |
| |
| /*time settings begin */ |
| UBUS_METHOD_NOARG("router_get_time_info", router_get_time_cb), |
| UBUS_METHOD("router_set_time_info", router_set_time_cb, time_setting_pol), |
| UBUS_METHOD_NOARG("router_invoke_ntp", invoke_ntp_cb), |
| UBUS_METHOD_NOARG("time_sync", router_time_sync), |
| /*time settings end */ |
| |
| /*management begin */ |
| UBUS_METHOD_NOARG("router_call_reboot", router_reboot), |
| UBUS_METHOD_NOARG("router_call_rst_factory", router_rst_factory), |
| UBUS_METHOD_NOARG("router_poweroff", router_poweroff), |
| UBUS_METHOD_NOARG("get_router_runtime", get_router_runtime), |
| /*management end */ |
| |
| /*management webdav begin */ |
| UBUS_METHOD("webdav_add_shared", webdav_add_shared_cb, webdav_add_shared_policy), |
| UBUS_METHOD("webdav_set_auth_info", webdav_set_auth_info_cb, webdav_auth_policy), |
| UBUS_METHOD("webdav_set_basic_info", webdav_set_basic_info_cb, webdav_basic_policy), |
| UBUS_METHOD_NOARG("webdav_get_management_info", webdav_get_management_info_cb), |
| UBUS_METHOD("webdav_get_path_info", webdav_get_path_info_cb, webdav_path_policy), |
| /*management webdav end */ |
| |
| /*management redirect begin */ |
| UBUS_METHOD("set_redirect_enable", redirect_set_enable_cb, redirect_enable_policy), |
| UBUS_METHOD("redirect_set_info", redirect_set_info_cb, redirect_info_policy), |
| UBUS_METHOD("redirect_set_allowlist", redirect_set_allowlist, redirect_allowlist_policy), |
| UBUS_METHOD_NOARG("get_redirect_enable", redirect_get_enable_cb), |
| UBUS_METHOD_NOARG("redirect_get_info", redirect_get_info_cb), |
| UBUS_METHOD_NOARG("redirect_get_allowlist", redirect_get_allowlist), |
| /*management redirect end */ |
| |
| }; |
| |
| static struct ubus_object_type router_object_type = UBUS_OBJECT_TYPE("router", router_methods); |
| |
| static struct ubus_object router_service_object = { |
| .name = "router", |
| .type = &router_object_type, |
| .methods = router_methods, |
| .n_methods = ARRAY_SIZE(router_methods), |
| }; |
| |
| static int parse_cm_activity_info(struct blob_attr *msg, struct cm_connection_info *connection_info) |
| { |
| struct blob_attr *cm_nwactivity[ARRAY_SIZE(cm_nwactivity_pol)]; |
| |
| if (blobmsg_parse |
| (cm_nwactivity_pol, ARRAY_SIZE(cm_nwactivity_pol), cm_nwactivity, blob_data(msg), blob_len(msg)) != 0) { |
| ROUTER_ERR("Parse failed"); |
| return -1; |
| } |
| if (!cm_nwactivity[CONN_STATUS] || !cm_nwactivity[PDP_CID] || !cm_nwactivity[PDP_IPTYPE]) { |
| ROUTER_ERR("no enough info"); |
| return -1; |
| } |
| |
| memset(connection_info, 0, sizeof(*connection_info)); |
| connection_info->status = blobmsg_get_u32(cm_nwactivity[CONN_STATUS]); |
| connection_info->cid = blobmsg_get_u32(cm_nwactivity[PDP_CID]); |
| connection_info->iptype = blobmsg_get_u32(cm_nwactivity[PDP_IPTYPE]); |
| |
| return 0; |
| } |
| |
| static void router_ubus_async_call_complete(struct ubus_request *req, int ret) |
| { |
| UNUSESET(ret); |
| if (req) { |
| free(req); |
| req = NULL; |
| } |
| } |
| |
| static int handle_cm_connection_ind(struct cm_connection_info *info) |
| { |
| if (!info) |
| return -1; |
| |
| int ret = 0; |
| struct ubus_request * req = NULL; |
| unsigned int router_id = 0; |
| |
| if (info ->status == 1) { |
| |
| if ((ret = ubus_lookup_id(router_ubus_ctx, UBUS_ROUTER_OBJ, &router_id)) != UBUS_STATUS_OK) { |
| ROUTER_ERR("Failed to look up router object\n"); |
| goto done; |
| } |
| |
| req = (struct ubus_request *)malloc(sizeof(struct ubus_request)); |
| if (req == NULL) { |
| ROUTER_ERR("lack of memory\n"); |
| ret = -1; |
| goto done; |
| } |
| |
| /*just wait some seconds to make sure the ccinet is created successfully*/ |
| sleep(3); |
| |
| if ((ret = |
| ubus_invoke_async(router_ubus_ctx, router_id, "time_sync", NULL, req)) != UBUS_STATUS_OK) { |
| ROUTER_ERR("sync time fail: %s\n", ubus_strerror(ret)); |
| free(req); |
| goto done; |
| } else { |
| req->complete_cb = router_ubus_async_call_complete; |
| ubus_complete_request_async(router_ubus_ctx, req); |
| } |
| |
| ROUTER_DBG("sync time done\n"); |
| } |
| |
| done: |
| return ret; |
| } |
| |
| static int router_ubus_ind_event(struct ubus_context *ctx, struct ubus_object *obj, |
| struct ubus_request_data *req, const char *method, |
| struct blob_attr *msg) |
| { |
| UNUSESET(ctx); |
| UNUSESET(obj); |
| UNUSESET(req); |
| int ret = 0; |
| struct cm_connection_info connection_info; |
| |
| ROUTER_DBG("method %s", method); |
| |
| if(!strcmp(method, UNSOL_CM_NWACTIVITY)) { |
| ret = parse_cm_activity_info(msg, &connection_info); |
| if (ret == 0) |
| handle_cm_connection_ind(&connection_info); |
| } |
| return ret; |
| } |
| |
| static int router_ubus_register_ind_sub(struct ubus_context *ctx, struct ubus_subscriber *s) |
| { |
| int ret = 0; |
| |
| ret = ubus_register_subscriber(ctx, s); |
| if (ret) |
| { |
| ROUTER_ERR("Failed to add watch handler: %s\n", ubus_strerror(ret)); |
| return -1; |
| } |
| |
| s->cb = router_ubus_ind_event; |
| |
| return ret; |
| } |
| |
| static int router_subscribe_event(struct ubus_context *ctx, const char *path, struct ubus_subscriber *sub_obj) |
| { |
| unsigned int id; |
| int ret; |
| |
| ret = ubus_lookup_id(ctx, path, &id); |
| if (ret) { |
| ROUTER_ERR("Failed to look up object %s\n", path); |
| goto done; |
| } |
| |
| ret = ubus_subscribe(ctx, sub_obj, id); |
| if (ret) |
| ROUTER_ERR("fail to subscribe object %s, status: %s\n", path, ubus_strerror(ret)); |
| |
| done : |
| return ret; |
| } |
| |
| void obj_cm_add_ev(struct ubus_context *ctx, char *obj_path) |
| { |
| if (strcmp(obj_path, UNSOL_CM_NWACTIVITY)) |
| return; |
| |
| if (router_subscribe_event(ctx, obj_path, &ind_event)) |
| ROUTER_ERR("Fail to subscribe object %s", obj_path); |
| |
| return; |
| } |
| |
| #if 0 |
| static void router_object_add_event_cb(struct ubus_context *ctx, struct ubus_event_handler *ev, |
| const char *type, struct blob_attr *msg) |
| { |
| static const struct blobmsg_policy policy = { |
| "path", BLOBMSG_TYPE_STRING |
| }; |
| struct blob_attr *attr; |
| const char *path; |
| |
| UNUSESET(ev); |
| |
| if (strcmp(type, UBUS_TYPE_OBJECT_ADD)) |
| return; |
| |
| blobmsg_parse(&policy, 1, &attr, blob_data(msg), blob_len(msg)); |
| if (!attr) |
| return; |
| |
| path = blobmsg_data(attr); |
| ROUTER_DBG("object %s added to ubus", path); |
| |
| if (strcmp(path, UNSOL_CM_NWACTIVITY) == 0) { |
| if (router_subscribe_event(ctx, path, &ind_event)) |
| ROUTER_ERR("Fail to subscribe object %s", path); |
| } |
| return; |
| } |
| #endif |
| |
| enum { |
| NET_ACT_ARRAY, |
| NET_ACT_ARRAY_MAX |
| }; |
| |
| static const struct blobmsg_policy net_act_policy[NET_ACT_ARRAY_MAX] = { |
| [NET_ACT_ARRAY] = { .name = "network_activity", .type = BLOBMSG_TYPE_ARRAY }, |
| }; |
| |
| enum { |
| NET_ACT_ITEM_CID, |
| NET_ACT_ITEM_IPTYPE, |
| NET_ACT_ITEM_MAX |
| }; |
| |
| static const struct blobmsg_policy net_act_item_policy[NET_ACT_ITEM_MAX] = { |
| [NET_ACT_ITEM_CID] = { .name = "cid", .type = BLOBMSG_TYPE_INT32 }, |
| [NET_ACT_ITEM_IPTYPE] = { .name = "ip_type", .type = BLOBMSG_TYPE_INT32 }, |
| }; |
| |
| static void router_get_network_activity_async_cb(struct ubus_request *req, int type, struct blob_attr *msg) |
| { |
| UNUSESET(type); |
| UNUSESET(req); |
| |
| struct blob_attr *tb[NET_ACT_ARRAY_MAX]; |
| struct blob_attr *tb_item[NET_ACT_ITEM_MAX]; |
| struct blob_attr *cur; |
| unsigned int rem; |
| struct cm_connection_info connection_info; |
| |
| if (blobmsg_parse |
| (net_act_policy, ARRAY_SIZE(net_act_policy), tb, blob_data(msg), blob_len(msg)) != 0) { |
| return; |
| } |
| |
| if (!tb[NET_ACT_ARRAY]) { |
| return; |
| } |
| |
| blobmsg_for_each_attr(cur, tb[NET_ACT_ARRAY], rem) { |
| if (blobmsg_type(cur) == BLOBMSG_TYPE_TABLE) { |
| if (blobmsg_parse |
| (net_act_item_policy, ARRAY_SIZE(net_act_item_policy), tb_item, blobmsg_data(cur), blobmsg_data_len(cur)) != 0) { |
| return; |
| } |
| |
| memset(&connection_info, 0, sizeof(connection_info)); |
| if (tb_item[NET_ACT_ITEM_CID]) { |
| ROUTER_DBG("get actived cid %d", blobmsg_get_u32(tb_item[NET_ACT_ITEM_CID])); |
| connection_info.status = 1; |
| connection_info.cid = blobmsg_get_u32(tb_item[NET_ACT_ITEM_CID]); |
| if (tb_item[NET_ACT_ITEM_IPTYPE]) |
| connection_info.cid = blobmsg_get_u32(tb_item[NET_ACT_ITEM_IPTYPE]); |
| |
| handle_cm_connection_ind(&connection_info); |
| break; |
| } |
| } |
| } |
| |
| return; |
| } |
| |
| static int router_get_network_activity_async(void) |
| { |
| int ret = 0; |
| struct ubus_request * req = NULL; |
| unsigned int router_id = 0; |
| |
| if ((ret = ubus_lookup_id(router_ubus_ctx, UBUS_CM_OBJ, &router_id)) != UBUS_STATUS_OK) { |
| goto done; |
| } |
| |
| req = (struct ubus_request *)malloc(sizeof(struct ubus_request)); |
| if (req == NULL) { |
| ret = -1; |
| goto done; |
| } |
| |
| if ((ret = |
| ubus_invoke_async(router_ubus_ctx, router_id, "get_network_activity", NULL, req)) != UBUS_STATUS_OK) { |
| free(req); |
| goto done; |
| } else { |
| req->complete_cb = router_ubus_async_call_complete; |
| req->data_cb = router_get_network_activity_async_cb; |
| ubus_complete_request_async(router_ubus_ctx, req); |
| } |
| |
| ROUTER_DBG("done\n"); |
| |
| done: |
| return ret; |
| } |
| |
| static void router_add_subscriber(struct uloop_timeout *timeout) |
| { |
| uint32_t id; |
| |
| if (ubus_lookup_id(router_ubus_ctx, UNSOL_CM_NWACTIVITY, &id)) { |
| ROUTER_ERR("failed to look up %s object\n", UNSOL_CM_NWACTIVITY); |
| goto time_out; |
| } |
| |
| ubus_subscribe(router_ubus_ctx, &ind_event, id); |
| ROUTER_DBG("subscribe %s object ok", UNSOL_CM_NWACTIVITY); |
| |
| router_get_network_activity_async(); |
| return; |
| time_out: |
| uloop_timeout_set(timeout, 2000); |
| return; |
| } |
| |
| static struct uloop_timeout router_add_subscribe_timeout = { |
| .cb = router_add_subscriber, |
| }; |
| |
| static void router_server_main(void) |
| { |
| int ret; |
| |
| ROUTER_DBG("enter"); |
| |
| ret = ubus_add_object(router_ubus_ctx, &router_service_object); |
| if (ret) { |
| ROUTER_ERR("Failed to add object: %s", ubus_strerror(ret)); |
| } |
| |
| ret = router_ubus_register_ind_sub(router_ubus_ctx, &ind_event); |
| if (ret) { |
| ROUTER_ERR("Failed to register subscriber"); |
| } |
| |
| uloop_timeout_set(&router_add_subscribe_timeout, 0); |
| } |
| |
| void stop_ntp_timeout_cb(struct uloop_timeout *timeout) |
| { |
| ROUTER_DBG("stop_ntp_timeout_cb: enter\n"); |
| |
| uloop_timeout_cancel(timeout); |
| |
| router_system("/etc/init.d/sysntpd stop &"); |
| return; |
| } |
| |
| void set_stop_ntp_timeout(int timeout) |
| { |
| uloop_timeout_set(&stop_ntp_timeout, timeout); |
| } |
| |
| static void free_all(void) |
| { |
| freelocallist(); |
| freesimlist(); |
| } |
| |
| |
| 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 init_firewall_server(void) |
| { |
| int ret; |
| |
| ret = ubus_add_object(router_ubus_ctx, &fw_service_object); |
| if (ret) |
| ROUTER_ERR("Failed to add object: %s\n", ubus_strerror(ret)); |
| } |
| |
| |
| int main(int argc, char **argv) |
| { |
| const char *ubus_socket = NULL; |
| int ch; |
| |
| UNUSESET(router_buf); |
| set_service_log_tag("router_settings"); |
| prctl(PR_SET_NAME, "router_settings"); |
| |
| 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); |
| router_ubus_ctx = ubus_connect(ubus_socket); |
| |
| if (!router_ubus_ctx) { |
| ROUTER_ERR("Failed to connect to ubus\n"); |
| return -1; |
| } |
| |
| ubus_add_uloop(router_ubus_ctx); |
| |
| redirect_init(); |
| init_firewall_server(); |
| init_util_wan_server(); |
| init_version_server(); |
| init_account_server(); |
| init_ussd_server(); |
| router_server_main(); |
| sim_server_main(); |
| wifi_server_main(); |
| sms_service_main(); |
| pb_main(); |
| |
| uloop_run(); |
| ubus_free(router_ubus_ctx); |
| uloop_done(); |
| free_all(); |
| |
| return 0; |
| } |