blob: 1fe247da9f65ba90969928469840add82ac7bc0d [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2014 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/* -------------------------------------------------------------------------------------------------------------------
*
* Filename: chl_agent_uci.c
*
* Authors: Hagai zalach
*
* Description: An agent to the CHL application
*
* HISTORY:
*
* AUG 13, 2015 - Initial Version
*
* Notes:
*
******************************************************************************/
/******************************************************************************
* Include files
******************************************************************************/
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <include/log.h>
#include <uci.h>
#include <chl.h>
#include "chl_agent.h"
#include "chl_agent_uci.h"
/******************************************************************************
* Defines
******************************************************************************/
/******************************************************************************
* Structs
******************************************************************************/
/******************************************************************************
* Methods
******************************************************************************/
/*Static Declarations*/
static int uci_del_section(struct uci_context *c, struct uci_package *p,
struct uci_section *s);
static int uci_del_named_section(struct uci_context *c, char *p_name,
char *sec_type, char *sec_name);
static int uci_add_named_section(struct uci_context *c, char *pname, char *type,
char *sec_name, struct uci_section **res);
static int uci_PtrAction(struct uci_context * ctx,
struct uci_package * p,
struct uci_section * uci_sec,
char * option,
void * pValue,
int op);
static int uci_parse_bool(char *b);
static enum ip_type uci_parse_iptype(char *b);
static void load_routes(struct agent_pdp *pdp, struct uci_list *l);
static void parse_pdp_section(struct uci_context *c,
struct uci_section *s,struct agent_pdp *pdp);
static void parse_global_section(struct uci_context *c, struct uci_section *s,
struct global_conf *conf);
static int uci_del_section(struct uci_context *c, struct uci_package *p,
struct uci_section *s)
{
struct uci_ptr ptr;
ptr.p = p;
ptr.s = s;
return uci_delete(c, &ptr);
}
__maybe_unused static int uci_del_named_section(struct uci_context *c, char *p_name,
char *sec_type, char *sec_name)
{
struct uci_element *e, *tmp;
struct uci_section *s;
struct uci_package *p = NULL;
if (strlen(sec_type) <= 0 || strlen(sec_name) <= 0)
goto err;
p = uci_lookup_package(c, p_name);
if (!p)
uci_load(c, p_name, &p);
if (!p)
goto err;
uci_foreach_element_safe(&p->sections, tmp, e) {
s = uci_to_section(e);
if (strcmp(s->type, sec_type))
continue;
if (strcmp(s->e.name, sec_name))
continue;
if (uci_del_section(c, p, s))
goto err;
}
return 0;
err:
AGT_ERR("failed to delete named section: %s\n", sec_name);
return 1;
}
__maybe_unused static int uci_add_named_section(struct uci_context *c, char *pname, char *type,
char *sec_name, struct uci_section **res)
{
struct uci_package *p;
struct uci_section *s;
struct uci_ptr ptr;
p = uci_lookup_package(c, pname);
if (p)
goto found;
uci_load(c, pname, &p);
if (!p)
goto err;
found:
if (uci_add_section(c, p, type, &s))
goto err;
ptr.p = p;
ptr.s = s;
ptr.value = sec_name;
if (uci_rename(c, &ptr))
goto err;
*res = s;
return 0;
err:
AGT_ERR("failed add named section %s\n", sec_name);
return 1;
}
int agt_uci_init(struct uci_context **c, char *pname)
{
struct uci_package *p = NULL;
*c = uci_alloc_context();
if (!*c) {
AGT_ERR("failed to allocate context\n");
return 1;
}
uci_load(*c, pname, &p);
if (!p) {
uci_free_context(*c);
AGT_ERR("failed to load %s package\n", pname);
return 1;
}
return 0;
}
void agt_uci_done(struct uci_context *c, bool commit, char *pname)
{
struct uci_package *p;
if (!c)
return;
if (commit) {
if((p = uci_lookup_package(c, pname)))
uci_commit(c, &p, false);
}
uci_free_context(c);
}
static int uci_PtrAction(struct uci_context * ctx,
struct uci_package * p,
struct uci_section * uci_sec,
char * option,
void * pValue,
int op)
{
struct uci_ptr ptr;
memset (&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = option;
ptr.value = pValue;
switch (op)
{
case 0:
return uci_set (ctx, &ptr);
break;
case 1:
return uci_delete (ctx, &ptr);
break;
case 2:
return uci_add_list (ctx, &ptr);
break;
case 3:
return uci_rename (ctx, &ptr);
break;
default:
return 1;
break;
}
}
int uci_SetPtr(struct uci_context * pCtx,
struct uci_package * p,
struct uci_section * uci_sec,
char * option,
void * pValue)
{
return uci_PtrAction(pCtx,p,uci_sec,option,pValue,0);
}
int uci_DelPtr(struct uci_context * pCtx,
struct uci_package * p,
struct uci_section * uci_sec,
char * option,
void * pValue)
{
return uci_PtrAction(pCtx,p,uci_sec,option,pValue,1);
}
int uci_AddListPtr(struct uci_context * pCtx,
struct uci_package * p,
struct uci_section * uci_sec,
char * option,
void * pValue)
{
return uci_PtrAction(pCtx,p,uci_sec,option,pValue,2);
}
int uci_RenamePtr(struct uci_context * pCtx,
struct uci_package * p,
struct uci_section * uci_sec,
char * option,
void * pValue)
{
return uci_PtrAction(pCtx,p,uci_sec,option,pValue,3);
}
static int uci_parse_bool(char *b)
{
if (!strcmp(b, "true") || !strcmp(b, "1"))
return 1;
else if (!strcmp(b, "false") || !strcmp(b, "0"))
return 0;
return -1;
}
static enum ip_type uci_parse_iptype(char *b)
{
if (!strcmp(b, "ipv4") || !strcmp(b, "IPV4"))
return IPV4;
else if (!strcmp(b, "ipv6") || !strcmp(b, "IPV6"))
return IPV6;
else
return IPV4V6;
}
static void load_routes(struct agent_pdp *pdp, struct uci_list *l)
{
struct uci_element *e;
int i = 0;
uci_foreach_element(l, e) {
if (strlen(e->name))
AGT_DBG("%s:\troute=%s\n", __func__,e->name);
strcpy(pdp->route_dst[i], e->name);
i++;
}
}
static void parse_pdp_section(struct uci_context *c,
struct uci_section *s,struct agent_pdp *pdp)
{
struct uci_element *e;
struct uci_option *o;
uci_foreach_element(&s->options, e) {
o = uci_to_option(e);
if (strlen(o->v.string) &&
strlen(e->name) && o->type != UCI_TYPE_LIST)
AGT_DBG("%s:\toption: name=%s\tvalue=%s\n", __func__,e->name,o->v.string);
if (!strcmp(e->name, UCI_OPT_PDP_ENABLE))
pdp->pdp_enable = uci_parse_bool(o->v.string);
else if (!strcmp(e->name, UCI_OPT_APN))
strcpy(pdp->apn, o->v.string);
else if (!strcmp(e->name, UCI_OPT_IP))
pdp->ip_type = uci_parse_iptype(o->v.string);
else if (!strcmp(e->name, UCI_OPT_LTEDFLT))
pdp->is_lte_default = uci_parse_bool(o->v.string);
else if (!strcmp(e->name, UCI_OPT_DFLTGW))
pdp->is_default_gw = uci_parse_bool(o->v.string);
else if (!strcmp(e->name, UCI_OPT_ROUTE) &&
o->type == UCI_TYPE_LIST) {
load_routes(pdp, &o->v.list);
}
}
}
static void parse_global_section(struct uci_context *c, struct uci_section *s,
struct global_conf *conf )
{
struct uci_element *e;
struct uci_option *o;
uci_foreach_element(&s->options, e) {
o = uci_to_option(e);
if (strlen(o->v.string) && strlen(e->name))
AGT_DBG("%s:\toption: name=%s\tvalue=%s\n", __func__,e->name,o->v.string);
if (!strcmp(e->name, UCI_OPT_DATA_ENABLE))
conf->data_enable = uci_parse_bool(o->v.string);
else if (!strcmp(e->name, UCI_OPT_HOST_IP))
strcpy(conf->host_ip, o->v.string);
else if (!strcmp(e->name, UCI_OPT_DWNLNK))
conf->downlink_only = uci_parse_bool(o->v.string);
else if (!strcmp(e->name, UCI_OPT_AGT_ACTIVE))
conf->agent_active = uci_parse_bool(o->v.string);
else if (!strcmp(e->name, UCI_OPT_WIFI))
conf->wifi_enable = uci_parse_bool(o->v.string);
}
}
int parse_ucifile(struct agent_conf *agent_conf)
{
struct uci_context *c = NULL;
struct uci_package *p;
struct uci_section *s;
struct uci_element *e;
int i=0;
char buf[6]={0};
agt_uci_init(&c, UCI_PKG_AGT);
p = uci_lookup_package(c, UCI_PKG_AGT);
if (!p)
uci_load(c, UCI_PKG_AGT, &p);
if (!p) {
AGT_ERR("%s: uci_load failed\n", __func__);
return 1;
}
uci_foreach_element(&p->sections, e) {
if (i >= MAX_PDPS) //the limit is max 8 PDP's
break;
s = uci_to_section(e);
if (strlen(s->e.name))
AGT_DBG("%s:section:\tname=%s\n", __func__,s->e.name);
sprintf(buf,"pdp_%d", i);
if (!strcmp(s->type,UCI_PDP_SEC) && !strcmp(s->e.name, buf) ){
parse_pdp_section(c,s,&(agent_conf->agent_pdps[i]));
i++;
}else if (!strcmp(s->type,UCI_GLOBAL_SEC))
parse_global_section(c,s,&(agent_conf->global_conf));
else{
AGT_ERR("%s: unknown section - failed\n", __func__);
return 1;
}
}
agt_uci_done(c,true,UCI_PKG_AGT);
AGT_DBG("finish parsing uci file\n\n\n\n\n\n\n\n\n\n\n");
return 0;
}