blob: f83bbed692feafbc57010181a026185313229f6c [file] [log] [blame]
#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;
}