blob: 9e602517122ab11f706cc97a37e8dbde49f25964 [file] [log] [blame]
#include "router_settings.h"
enum {
OPT_GATEWAY_TYPE = 3,
OPT_DNS_TYPE = 6,
};
struct up_ifa_name {
char *name;
struct up_ifa_name *next;
};
/*get Router Gateway*/
static int parse_dhcp_option_str(char *option_str, struct blob_buf *buf, int *option_type)
{
#define space_char 32
#define MAX_VALUE_BUF_SIZE 128
char *entry_start = NULL;
char *entry_end = NULL;
char *del_pos = NULL;
int ret_val = 0;
char *value_buf = NULL;
char tmp[4] = { 0 };
int opt_type = 0;
if (!option_str) {
ret_val = 1;
goto EXIT;
}
entry_start = option_str;
while (*entry_start != space_char) {
break;
entry_start++;
}
ROUTER_DBG("entry_start %x, %s", entry_start, entry_start);
while (*entry_start) {
entry_end = strchr(option_str, space_char);
if (!entry_end) {
entry_end = entry_start + strlen(entry_start) - 1;
}
ROUTER_DBG("entry_start %x, entry_end %x", entry_start, entry_end);
del_pos = strchr(entry_start, ',');
if (del_pos) {
if (del_pos - entry_start < 4) {
memset(tmp, 0, 4);
memcpy(tmp, entry_start, del_pos - entry_start);
opt_type = atoi(tmp);
*option_type = opt_type;
ROUTER_DBG("dhcp option type is %s, %d", tmp, opt_type);
if (buf) {
//value_buf = malloc(entry_end - del_pos + 1);
value_buf = malloc(MAX_VALUE_BUF_SIZE);
if (value_buf) {
//memset(value_buf, 0, entry_end - del_pos + 1);
memset(value_buf, 0, MAX_VALUE_BUF_SIZE);
if (*(del_pos + 1) == ',' && *(del_pos + 2) == '6' && *(del_pos + 3) == ',')
{
/* skip ",,6," */
del_pos += 4;
snprintf(value_buf, MAX_VALUE_BUF_SIZE - 1, "disable,%s", del_pos);
}
else
{
del_pos += 1;
snprintf(value_buf, MAX_VALUE_BUF_SIZE - 1, "%s", del_pos);
}
//memcpy(value_buf, del_pos + 1, entry_end - del_pos);
ROUTER_DBG("dhcp option value : %s", value_buf);
switch (opt_type) {
case OPT_GATEWAY_TYPE:
blobmsg_add_string(buf, "option_gateway", value_buf);
break;
case OPT_DNS_TYPE:
blobmsg_add_string(buf, "option_dns", value_buf);
break;
}
free(value_buf);
}
}
}
} else {
/*with out value, this option is disabled */
if (entry_end - entry_start < 4) {
memset(tmp, 0, 4);
memcpy(tmp, entry_start, entry_end - entry_start + 1);
opt_type = atoi(tmp);
*option_type = opt_type;
ROUTER_DBG("dhcp option type entry_start %x, entry_end %x, is %s, %d",entry_start, entry_end, tmp, opt_type);
if (buf) {
switch (opt_type) {
case OPT_GATEWAY_TYPE:
blobmsg_add_string(buf, "option_gateway", "disable");
break;
case OPT_DNS_TYPE:
blobmsg_add_string(buf, "option_dns", "disable");
break;
}
}
break;
}
}
/*get next first non space character */
while (*++entry_end != space_char) {
entry_start = entry_end;
if (*entry_start == '\0')
break;
}
}
EXIT:
return ret_val;
}
/*================================================
When the service starts to run, check whether the dhcp-option is included
in file /etc/config/dhcp,if not included, add then please
================================================*/
void check_add_dhcp_option(void)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_option *list_opt = NULL;
struct uci_option *uci_opt = NULL;
struct uci_element *e_list = NULL;
struct uci_ptr set_ptr;
const char *opt_val = NULL;
int opt_type = 0;
int gateway_find = 0;
int dns_find = 0;
ROUTER_DBG("enter");
/*load /etc/config/dhcp */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
ROUTER_DBG("get uci ctx OK\r\n");
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, DHCP_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, DHCP_PACK, &p);
}
if (p) {
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "dhcp") == 0) {
ROUTER_DBG("got one dhcp section");
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "interface");
if (opt_val && (strcmp(opt_val, "lan") == 0)) {
ROUTER_DBG("got the dhcp pool settings");
list_opt = uci_lookup_option(local_ctx, uci_sec, "dhcp_option");
if (list_opt && list_opt->type == UCI_TYPE_LIST) {
uci_foreach_element(&list_opt->v.list, e_list) {
uci_opt = uci_to_option(e_list);
if (uci_opt->e.name) {
ROUTER_DBG("got one option : %s", uci_opt->e.name);
parse_dhcp_option_str(uci_opt->e.name, NULL, &opt_type);
switch (opt_type) {
case OPT_GATEWAY_TYPE:
gateway_find = 1;
break;
case OPT_DNS_TYPE:
dns_find = 1;
break;
}
}
}
}
/*add DHCP-GATEWAY */
if (gateway_find == 0) {
memset(&set_ptr, 0, sizeof(struct uci_ptr));
set_ptr.p = p;
set_ptr.s = uci_sec;
set_ptr.option = "dhcp_option";
set_ptr.value = "3";
uci_add_list(local_ctx, &set_ptr);
}
if (dns_find == 0) {
memset(&set_ptr, 0, sizeof(struct uci_ptr));
set_ptr.p = p;
set_ptr.s = uci_sec;
set_ptr.option = "dhcp_option";
set_ptr.value = "6";
uci_add_list(local_ctx, &set_ptr);
}
break;
}
}
}
uci_commit(local_ctx, &p, false);
}
free_router_uci_ctx();
}
#if 1
static void set_dhcp_option_value(struct uci_context *in_ctx, struct uci_package *p, struct uci_section *in_sec,
int in_type, char *msg_value)
{
struct uci_option *uci_opt_list = NULL;
struct uci_option *uci_opt = NULL;
struct uci_element *e_list = NULL;
struct uci_ptr ptr;
int opt_type = 0;
char option_value[100] = { 0 };
bool list_exist = false;
bool valid_value = false;
char *pValue = NULL;
if (!in_ctx || !p || !in_sec || !msg_value)
return;
ROUTER_DBG("in_type %d, msg_value : %s", in_type, msg_value);
memset(option_value, 0, sizeof(option_value));
pValue = strstr(msg_value, "disable");
if ( pValue == NULL)
{
valid_value = true;
snprintf(option_value, sizeof(option_value) - 1, "%d,%s", in_type, msg_value);
}
else
{
if (in_type == OPT_DNS_TYPE)
{
if (pValue == msg_value)
{
if (!strcmp(msg_value, "disable") ||!strcmp(msg_value, "disable,disable"))
{
/* disable dns */
}
else
{
/* primary dns disable */
pValue += strlen("disable,");
snprintf(option_value, sizeof(option_value) - 1, "%d,,%d,%s", in_type, in_type, pValue);
valid_value = true;
}
}
else
{
/* secondary dns disable */
pValue = strchr(msg_value, ',');
if (pValue)
{
int len = (pValue - msg_value);
int size = snprintf(option_value, sizeof(option_value) - 1, "%d,", in_type);
memcpy(option_value + size, msg_value, len);
valid_value = true;
}
}
}
}
/*dhcp_option list */
uci_opt_list = uci_lookup_option(in_ctx, in_sec, "dhcp_option");
if (uci_opt_list && uci_opt_list->type == UCI_TYPE_LIST) {
uci_foreach_element(&uci_opt_list->v.list, e_list) {
uci_opt = uci_to_option(e_list);
if (uci_opt->e.name) {
ROUTER_DBG("got one option : %s", uci_opt->e.name);
parse_dhcp_option_str(uci_opt->e.name, NULL, &opt_type);
if (in_type == opt_type) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.s = in_sec;
ptr.p = p;
ptr.o = uci_opt_list;
ptr.value = uci_opt->e.name;
uci_del_list(in_ctx, &ptr);
if (valid_value)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.s = in_sec;
ptr.p = p;
ptr.o = uci_opt_list;
//memset(option_value, 0, sizeof(option_value));
//snprintf(option_value, sizeof(option_value) - 1, "%d,%s", in_type, msg_value);
ROUTER_DBG("update list value %s", option_value);
ptr.value = option_value;
uci_add_list(in_ctx, &ptr);
}
list_exist = true;
break;
}
}
}
}
if (!list_exist && valid_value)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.s = in_sec;
ptr.p = p;
ptr.option = "dhcp_option";
//memset(option_value, 0, sizeof(option_value));
//snprintf(option_value, sizeof(option_value) - 1, "%d,%s", in_type, msg_value);
ROUTER_DBG("new list value %s", option_value);
ptr.value = option_value;
uci_add_list(in_ctx, &ptr);
}
}
#endif
/*get router lan ip*/
/*================================================
<router>
<lan_ip/>
</router>
Note : the dhcp settings is only included in config 'dhcp' 'lan'
================================================*/
int router_get_lan_ip_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_router = NULL;
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
ROUTER_DBG("enter");
/*load /etc/config/network */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
ROUTER_DBG("get uci ctx OK\r\n");
blobmsg_buf_init(&router_buf);
tb_router = blobmsg_open_table(&router_buf, "router");
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, NW_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, NW_PACK, &p);
}
if (p) {
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "interface") == 0) {
if (uci_sec->e.name && strcmp(uci_sec->e.name, "lan") == 0) {
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ipaddr");
if (opt_val && tb_router) {
blobmsg_add_string(&router_buf, "lan_ip", opt_val);
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "netmask");
if (opt_val && tb_router) {
blobmsg_add_string(&router_buf, "lan_netmask", opt_val);
}
break;
}
}
}
}
if (tb_router) {
blobmsg_close_table(&router_buf, tb_router);
}
free_router_uci_ctx();
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
ROUTER_DBG("leave");
return 0;
}
/*set router lan ip*/
/*================================================
<router>
<lan_ip/>
</router>
Note : the dhcp settings is only included in config 'dhcp' 'lan'
================================================*/
enum {
LAN_IP
};
static const struct blobmsg_policy router_setting_pol[] = {
[LAN_IP] = {
.name = "lan_ip",
.type = BLOBMSG_TYPE_STRING,
},
};
struct up_ifa_name *g_head_if_name;
static int router_restart_lan(struct up_ifa_name *head)
{
struct up_ifa_name *p_if_name = head;
struct up_ifa_name *next_if_name = NULL;
char cmd_buf[MAX_CMD_BUF_SIZE] = { 0 };
/*should down ccinet interface first */
while (p_if_name) {
memset(cmd_buf, 0, MAX_CMD_BUF_SIZE);
snprintf(cmd_buf, MAX_CMD_BUF_SIZE - 1, "/bin/ubus call network.interface.%s down", p_if_name->name);
ROUTER_DBG("cmd:%s", cmd_buf);
router_system(cmd_buf);
p_if_name = p_if_name->next;
}
router_system("/etc/init.d/network reload");
p_if_name = head;
while (p_if_name) {
memset(cmd_buf, 0, MAX_CMD_BUF_SIZE);
snprintf(cmd_buf, MAX_CMD_BUF_SIZE - 1, "/bin/ubus call network.interface.%s up", p_if_name->name);
ROUTER_DBG("cmd:%s", cmd_buf);
router_system(cmd_buf);
p_if_name = p_if_name->next;
}
/*free buffer anyway*/
p_if_name = head;
while(p_if_name) {
next_if_name = p_if_name->next;
if (p_if_name->name)
free(p_if_name->name);
free(p_if_name);
p_if_name = next_if_name;
}
return 0;
}
int router_set_lan_ip_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_router = NULL;
struct uci_ptr ptr;
struct blob_attr *router_setting[ARRAY_SIZE(router_setting_pol)];
int ret_val = 0;
const char *ip_value = NULL, *ip6_value = NULL;
struct up_ifa_name *p_if_name = NULL, *head_if_name = NULL, *next_if_name = NULL;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(router_setting_pol, ARRAY_SIZE(router_setting_pol), router_setting, blob_data(msg), blob_len(msg)) != 0) {
ROUTER_ERR("Parse failed\n");
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!router_setting[LAN_IP]) {
ROUTER_ERR("NO DATA");
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/network */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, NW_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, NW_PACK, &p);
}
if (p) {
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "interface") == 0) {
if (uci_sec->e.name && strcmp(uci_sec->e.name, "lan") == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ipaddr";
ptr.value = blobmsg_get_string(router_setting[LAN_IP]);
uci_set(local_ctx, &ptr);
break;
} else if (uci_sec->e.name && strstr(uci_sec->e.name, "wan") != NULL) {
ip_value = uci_lookup_option_string(local_ctx, uci_sec, "ipaddr");
ip6_value = uci_lookup_option_string(local_ctx, uci_sec, "ip6addr");
if (ip_value || ip6_value) {
p_if_name = (struct up_ifa_name *)malloc(sizeof(struct up_ifa_name));
if (!p_if_name) {
ROUTER_ERR("malloc size %d failed!\n", sizeof(struct up_ifa_name));
ret_val = UBUS_STATUS_UNKNOWN_ERROR;
goto EXIT;
}
memset(p_if_name, 0, sizeof(struct up_ifa_name));
if (!head_if_name) {
head_if_name = p_if_name;
g_head_if_name = head_if_name;
}
p_if_name->name = strdup(uci_sec->e.name);
p_if_name = p_if_name->next;
}
}
}
}
}
EXIT:
blobmsg_buf_init(&router_buf);
tb_router = blobmsg_open_table(&router_buf, "router");
if (tb_router) {
if (ret_val == 0) {
blobmsg_add_string(&router_buf, "setting_response", "OK");
if (p) {
uci_commit(local_ctx, &p, false);
}
} else {
blobmsg_add_string(&router_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&router_buf, tb_router);
}
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
free_router_uci_ctx();
#if 0
if (ret_val == 0) {
/*should down ccinet interface first */
p_if_name = head_if_name;
while (p_if_name) {
memset(cmd_buf, 0, MAX_CMD_BUF_SIZE);
snprintf(cmd_buf, MAX_CMD_BUF_SIZE - 1, "/bin/ubus call network.interface.%s down", p_if_name->name);
ROUTER_DBG("cmd:%s", cmd_buf);
router_system(cmd_buf);
p_if_name = p_if_name->next;
}
router_system("/etc/init.d/network reload");
p_if_name = head_if_name;
while (p_if_name) {
memset(cmd_buf, 0, MAX_CMD_BUF_SIZE);
snprintf(cmd_buf, MAX_CMD_BUF_SIZE - 1, "/bin/ubus call network.interface.%s up", p_if_name->name);
ROUTER_DBG("cmd:%s", cmd_buf);
router_system(cmd_buf);
p_if_name = p_if_name->next;
}
/*free buffer anyway*/
p_if_name = head_if_name;
while(p_if_name) {
next_if_name = p_if_name;
if (p_if_name->name)
free(p_if_name->name);
free(p_if_name);
p_if_name = next_if_name;
}
}
#endif
return 0;
}
/*get DHCP settings*/
/*================================================
<dhcp>
<disable/>
<start/>
<limit/>
<leasetime/>
<option_gateway/>
<option_dns/>
</dhcp>
Note : the dhcp settings is only included in config 'dhcp' 'lan'
================================================*/
int dhcp_get_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;
struct uci_option *list_opt = NULL;
struct uci_option *uci_opt = NULL;
struct uci_element *e_list = NULL;
const char *opt_val = NULL;
void *tb_dhcp = NULL;
int opt_type = 0;
int gateway_find = 0;
int dns_find = 0;
ROUTER_DBG("enter");
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
/*load /etc/config/dhcp */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
ROUTER_DBG("get uci ctx OK\r\n");
blobmsg_buf_init(&router_buf);
tb_dhcp = blobmsg_open_table(&router_buf, "dhcp");
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, DHCP_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, DHCP_PACK, &p);
}
if (p) {
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "dhcp") == 0) {
ROUTER_DBG("got one dhcp section");
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "interface");
if (opt_val && (strcmp(opt_val, "lan") == 0)) {
ROUTER_DBG("got the dhcp pool settings");
/*disabled */
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ignore");
if (opt_val && (strcmp(opt_val, "1") == 0)) {
ROUTER_DBG("DHCP is disabled");
blobmsg_add_string(&router_buf, "disabled", "1");
} else {
blobmsg_add_string(&router_buf, "disabled", "0");
}
/*start addr */
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "start");
if (opt_val) {
blobmsg_add_string(&router_buf, "start", opt_val);
}
/*limit */
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "limit");
if (opt_val) {
blobmsg_add_string(&router_buf, "limit", opt_val);
}
/*leasetime */
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "leasetime");
if (opt_val) {
blobmsg_add_string(&router_buf, "leasetime", opt_val);
}
list_opt = uci_lookup_option(local_ctx, uci_sec, "dhcp_option");
if (list_opt && list_opt->type == UCI_TYPE_LIST) {
uci_foreach_element(&list_opt->v.list, e_list) {
uci_opt = uci_to_option(e_list);
if (uci_opt->e.name) {
ROUTER_DBG("got one list value: %s", uci_opt->e.name);
parse_dhcp_option_str(uci_opt->e.name, &router_buf, &opt_type);
switch (opt_type) {
case OPT_GATEWAY_TYPE:
gateway_find = 1;
break;
case OPT_DNS_TYPE:
dns_find = 1;
break;
default:
break;
}
}
}
}
if (gateway_find == 0)
blobmsg_add_string(&router_buf, "option_gateway", "disable");
if (dns_find == 0)
blobmsg_add_string(&router_buf, "option_dns", "disable,disable");
//blobmsg_add_string(&router_buf, "option_gateway", "disable");
//blobmsg_add_string(&router_buf, "option_dns", "disable,disable");
}
break;
}
}
}
if (tb_dhcp) {
blobmsg_close_table(&router_buf, tb_dhcp);
}
free_router_uci_ctx();
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
ROUTER_DBG("leave");
return 0;
}
/*================================================
<dhcp>
<disable/>
<start/>
<limit/>
<leasetime/>
<option_gateway/>
<option_dns/>
<lanip_changed/>
</dhcp>
Note : the dhcp settings is only included in config 'dhcp' 'lan'
================================================*/
int dhcp_set_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_dhcp = NULL;
struct uci_ptr ptr;
struct blob_attr *dhcp_setting[ARRAY_SIZE(dhcp_setting_pol)];
int ret_val = 0;
int lanip_changed = 0;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse(dhcp_setting_pol, ARRAY_SIZE(dhcp_setting_pol), dhcp_setting, blob_data(msg), blob_len(msg))
!= 0) {
ROUTER_ERR("Parse failed\n");
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/dhcp */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, DHCP_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, DHCP_PACK, &p);
}
if (p) {
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "dhcp") == 0) {
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "interface");
if (opt_val && (strcmp(opt_val, "lan") == 0)) {
ROUTER_DBG("got the lan device settings");
if (dhcp_setting[DHCP_DISABLED]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec, ptr.option = "ignore";
ptr.value = blobmsg_get_string(dhcp_setting[DHCP_DISABLED]);
uci_set(local_ctx, &ptr);
}
if (dhcp_setting[DHCP_START]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec, ptr.option = "start";
ptr.value = blobmsg_get_string(dhcp_setting[DHCP_START]);
uci_set(local_ctx, &ptr);
}
if (dhcp_setting[DHCP_LIMIT]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec, ptr.option = "limit";
ptr.value = blobmsg_get_string(dhcp_setting[DHCP_LIMIT]);
uci_set(local_ctx, &ptr);
}
if (dhcp_setting[DHCP_LEASETIME]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec, ptr.option = "leasetime";
ptr.value = blobmsg_get_string(dhcp_setting[DHCP_LEASETIME]);
uci_set(local_ctx, &ptr);
}
if (dhcp_setting[DHCP_GATEWAY]) {
ROUTER_DBG("got the option_gateway value %s", blobmsg_get_string(dhcp_setting[DHCP_GATEWAY]));
set_dhcp_option_value(local_ctx, p, uci_sec, OPT_GATEWAY_TYPE, blobmsg_get_string(dhcp_setting[DHCP_GATEWAY]));
}
if (dhcp_setting[DHCP_DNS]) {
ROUTER_DBG("got the option_dns %s", blobmsg_get_string(dhcp_setting[DHCP_DNS]));
set_dhcp_option_value(local_ctx, p, uci_sec, OPT_DNS_TYPE, blobmsg_get_string(dhcp_setting[DHCP_DNS]));
}
ROUTER_DBG("dhcp_setting_pol size %d", ARRAY_SIZE(dhcp_setting_pol));
if (dhcp_setting[DHCP_LANIP_CHANGED]) {
ROUTER_DBG("got the lanip_changed %s", blobmsg_get_string(dhcp_setting[DHCP_LANIP_CHANGED]));
lanip_changed = blobmsg_get_string(dhcp_setting[DHCP_LANIP_CHANGED]);
}
}
}
}
}
EXIT:
blobmsg_buf_init(&router_buf);
tb_dhcp = blobmsg_open_table(&router_buf, "dhcp");
if (tb_dhcp) {
if (ret_val == 0) {
blobmsg_add_string(&router_buf, "setting_response", "OK");
if (p) {
uci_commit(local_ctx, &p, false);
}
} else {
blobmsg_add_string(&router_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&router_buf, tb_dhcp);
}
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
free_router_uci_ctx();
if (ret_val == 0) {
if (lanip_changed) {
router_restart_lan(g_head_if_name);
g_head_if_name = NULL;
sleep(1);
}
if (lanip_changed != 2)
router_system("/etc/init.d/dnsmasq reload");
}
return 0;
}
/*================================================
<dhcp>
<fixed_ip_list>
<entry_index>
<ip/>
<mac/>
<name/>
</entry_index>
...
</fixed_ip_list>
</firewall>
================================================*/
int dhcp_get_fixed_ip_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_dhcp = NULL;
void *tb_fixed_ip_list = NULL;
void *tb_entry = NULL;
int entry_index = 1;
char entry_buf[16];
ROUTER_DBG("enter");
UNUSESET(obj);
UNUSESET(method);
UNUSESET(msg);
/*load /etc/config/dhcp */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
ROUTER_DBG("get uci ctx OK\r\n");
blobmsg_buf_init(&router_buf);
tb_dhcp = blobmsg_open_table(&router_buf, "dhcp");
if (!tb_dhcp) {
assert(0);
}
tb_fixed_ip_list = blobmsg_open_table(&router_buf, "fixed_ip_list");
if (!tb_fixed_ip_list) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, DHCP_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, DHCP_PACK, &p);
}
if (p) {
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "host") == 0) {
ROUTER_DBG("got one host section");
memset(entry_buf, 0, sizeof(entry_buf));
snprintf(entry_buf, sizeof(entry_buf), "entry_%d", entry_index++);
ROUTER_DBG("entry_buf : %s", entry_buf);
tb_entry = blobmsg_open_table(&router_buf, entry_buf);
if (tb_entry) {
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ip");
if (opt_val) {
ROUTER_DBG("ip:%s", opt_val);
blobmsg_add_string(&router_buf, "ip", opt_val);
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "mac");
if (opt_val) {
ROUTER_DBG("mac:%s", opt_val);
blobmsg_add_string(&router_buf, "mac", opt_val);
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "name");
if (opt_val) {
ROUTER_DBG("name:%s", opt_val);
blobmsg_add_string(&router_buf, "name", opt_val);
}
blobmsg_close_table(&router_buf, tb_entry);
}
}
}
}
if (tb_fixed_ip_list) {
ROUTER_DBG("close tb_fixed_ip_list");
blobmsg_close_table(&router_buf, tb_fixed_ip_list);
}
if (tb_dhcp) {
ROUTER_DBG("close tb_dhcp");
blobmsg_close_table(&router_buf, tb_dhcp);
}
free_router_uci_ctx();
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
return 0;
}
enum {
ADD_FIXED_IP_ENTRY,
EDIT_FIXED_IP_ENTRY,
};
enum {
FIXED_IP_ADDR,
FIXED_IP_MAC,
FIXED_IP_NAME,
};
static const struct blobmsg_policy dhcp_fixed_ip_pol[] = {
[FIXED_IP_ADDR] = {
.name = "ip",
.type = BLOBMSG_TYPE_STRING,
},
[FIXED_IP_MAC] = {
.name = "mac",
.type = BLOBMSG_TYPE_STRING,
},
[FIXED_IP_NAME] = {
.name = "name",
.type = BLOBMSG_TYPE_STRING,
},
};
static int dhcp_set_fixed_ip_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;
struct uci_ptr ptr;
struct blob_attr *attr_head = NULL;
struct blob_attr *attr;
struct blobmsg_hdr *hdr;
struct blob_attr *entry_attr[ARRAY_SIZE(dhcp_fixed_ip_pol)];
struct blob_attr *dhcp_setting[ARRAY_SIZE(dhcp_setting_pol)];
int attr_len = 0;
int edit_index = 0;
int index = 0;
int ret_val = 0;
void *tb_dhcp = NULL;
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse(dhcp_setting_pol, ARRAY_SIZE(dhcp_setting_pol), dhcp_setting, blob_data(msg), blob_len(msg))
!= 0) {
ROUTER_ERR("Parse failed\n");
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!dhcp_setting[DHCP_FIXED_IP_LIST]) {
ROUTER_ERR("NO DATA");
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/dhcp */
local_ctx = (struct uci_context *)uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, DHCP_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, DHCP_PACK, &p);
}
if (dhcp_setting[DHCP_FIXED_IP_LIST]) {
ROUTER_DBG("add new dns filter");
attr_head = blobmsg_data(dhcp_setting[DHCP_FIXED_IP_LIST]);
attr_len = blobmsg_data_len(dhcp_setting[DHCP_FIXED_IP_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) {
ROUTER_DBG("got one entry_index -- %s", hdr->name);
}
if (!strstr((char *)hdr->name, "entry")) {
continue;
}
if (type == EDIT_FIXED_IP_ENTRY) {
if (sscanf((char *)hdr->name, "%*5s_%d", &edit_index) == 1) {
ROUTER_DBG("get edit index -- %d", edit_index);
} else {
ROUTER_ERR("get edit index fail");
ret_val = 1;
goto EXIT;
}
}
/*type should be table */
if (blob_id(attr) != BLOBMSG_TYPE_TABLE) {
continue;
}
ROUTER_DBG("GOT ONE NEW ENTRY");
if (blobmsg_parse
(dhcp_fixed_ip_pol, ARRAY_SIZE(dhcp_fixed_ip_pol), entry_attr, blobmsg_data(attr),
blobmsg_data_len(attr)) == 0) {
if (type == ADD_FIXED_IP_ENTRY) {
/*add one section with type :host */
uci_add_section(local_ctx, p, "host", &uci_sec);
} else if (type == EDIT_FIXED_IP_ENTRY) {
index = 0;
/*find the rule */
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (!strcmp(uci_sec->type, "host")) {
index++;
if (index == edit_index) {
ROUTER_DBG("find edit index %d", index);
break;
}
}
}
}
if (uci_sec) {
ROUTER_DBG("uci_sec OK!");
if (entry_attr[FIXED_IP_ADDR]) {
ROUTER_DBG("FIXED_IP_ADDR is %s",
blobmsg_get_string(entry_attr[FIXED_IP_ADDR]));
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ip";
ptr.value = blobmsg_get_string(entry_attr[FIXED_IP_ADDR]);
uci_set(local_ctx, &ptr);
}
if (entry_attr[FIXED_IP_MAC]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "mac";
ptr.value = blobmsg_get_string(entry_attr[FIXED_IP_MAC]);
uci_set(local_ctx, &ptr);
}
if (entry_attr[FIXED_IP_NAME]) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "name";
ptr.value = blobmsg_get_string(entry_attr[FIXED_IP_NAME]);
uci_set(local_ctx, &ptr);
}
} else {
ROUTER_DBG("uci_sec is NULL");
}
}
}
}
EXIT:
blobmsg_buf_init(&router_buf);
tb_dhcp = blobmsg_open_table(&router_buf, "dhcp");
if (tb_dhcp) {
if (ret_val == 0) {
blobmsg_add_string(&router_buf, "setting_response", "OK");
if (p) {
uci_commit(local_ctx, &p, false);
}
} else {
blobmsg_add_string(&router_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&router_buf, tb_dhcp);
}
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
free_router_uci_ctx();
if (ret_val == 0) {
router_system("/etc/init.d/dnsmasq reload");
}
return 0;
}
int dhcp_add_fixed_ip_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
return dhcp_set_fixed_ip_cb(ctx, obj, req, method, msg, ADD_FIXED_IP_ENTRY);
}
int dhcp_edit_fixed_ip_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
return dhcp_set_fixed_ip_cb(ctx, obj, req, method, msg, EDIT_FIXED_IP_ENTRY);
}
/*================================================
<dhcp>
<del_fixed_ip_index>
</dhcp>
seperate by ','
================================================*/
int dhcp_delete_fixed_ip_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_dhcp = 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 *dhcp_setting_attr[ARRAY_SIZE(dhcp_setting_pol)];
ROUTER_DBG("enter");
UNUSESET(obj);
UNUSESET(method);
if (blobmsg_parse
(dhcp_setting_pol, ARRAY_SIZE(dhcp_setting_pol), dhcp_setting_attr, blob_data(msg), blob_len(msg)) != 0) {
ROUTER_ERR("Parse failed\n");
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
if (!dhcp_setting_attr[DHCP_DEL_FIXED_IP_INDEX]) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
/*load /etc/config/dhcp */
local_ctx = uci_router_ctx_get();
if (!local_ctx) {
assert(0);
}
ROUTER_DBG("get uci ctx OK\r\n");
{
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, DHCP_PACK) != 0)
continue;
p = uci_to_package(e); //have found
}
}
if (!p) {
uci_load(local_ctx, DHCP_PACK, &p);
}
if (!p) {
ret_val = UBUS_STATUS_NO_DATA;
goto EXIT;
}
ROUTER_DBG("delete index is %s", blobmsg_get_string(dhcp_setting_attr[DHCP_DEL_FIXED_IP_INDEX]));
if (dhcp_setting_attr[DHCP_DEL_FIXED_IP_INDEX]) {
begin = blobmsg_get_string(dhcp_setting_attr[DHCP_DEL_FIXED_IP_INDEX]);
/*to get the number of delete index */
while ((begin = strchr(begin, ','))) {
delete_num += 1;
begin += 1;
}
ROUTER_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(dhcp_setting_attr[DHCP_DEL_FIXED_IP_INDEX]);
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++) {
ROUTER_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, "host") == 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]) {
ROUTER_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(&router_buf);
tb_dhcp = blobmsg_open_table(&router_buf, "firewall");
if (ret_val == 0) {
blobmsg_add_string(&router_buf, "setting_response", "OK");
if (p) {
uci_commit(local_ctx, &p, false);
}
} else {
blobmsg_add_string(&router_buf, "setting_response", "ERROR");
}
blobmsg_close_table(&router_buf, tb_dhcp);
ubus_send_reply(ctx, req, router_buf.head);
blob_buf_free(&router_buf);
free_router_uci_ctx();
ROUTER_DBG("leave");
if (ret_val == 0) {
router_system("/etc/init.d/dnsmasq reload");
}
return ret_val;
}