| /****************************************************************************** |
| *(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; |
| } |
| |