blob: 296095fbc4574253cb153d42a4ed44d1f8972121 [file] [log] [blame]
/*------------------------------------------------------------
(C) Copyright [2006-2014] Marvell International Ltd.
All Rights Reserved
------------------------------------------------------------*/
#include "XmlParser.h"
//////////////////////////////////////////////////////////////////////
// Defines
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Local Prototypes
//////////////////////////////////////////////////////////////////////
#if CONFIG_LIBXML2
void parse_ex_apn(xmlTextReaderPtr reader,Mnc_Apn *get_apn);
void parse_apn(xmlTextReaderPtr reader, Mnc_Apn *get_apn);
int find_matched_apn(xmlTextReaderPtr reader,Mnc_Apn *get_apn);
void parse_ex_params(xmlTextReaderPtr reader,Extra_Apn_Info *ex_info);
static void remove_entry(xmlNodePtr cur,char *mcc,char *mnc,char *carrier);
static xmlDocPtr openXmlFile(char *docname) ;
static void closeXmlFile(xmlDocPtr xmlFilePtr);
static xmlNodePtr getXmlRoot(xmlDocPtr xmlFilePtr);
static xmlDocPtr createXmlFile(char *docname, char *root_name);
static int saveXmlFile(char *docname, xmlDocPtr xmlFilePtr);
#endif
#if CONFIG_LIBMXML
void parse_ex_apn(mxml_node_t *node, Mnc_Apn *get_apn);
void parse_apn(mxml_node_t *node, Mnc_Apn *get_apn);
void parse_ex_params(mxml_node_t *node, Extra_Apn_Info *ex_info);
#endif
//////////////////////////////////////////////////////////////////////
// Global Variables
//////////////////////////////////////////////////////////////////////
extern Mnc_Apn *IMSI_APN;
apn_data apn_params_str[] = {
{APN_PARAM_CARRIER,"carrier"},
{APN_PARAM_MCC,"mcc"},
{APN_PARAM_MNC,"mnc"},
{APN_PARAM_APN,"apn"},
{APN_PARAM_USER,"user"},
{APN_PARAM_SERVER,"server"},
{APN_PARAM_PROXY,"proxy"},
{APN_PARAM_PORT,"port"},
{APN_PARAM_PASSWORD,"password"},
{APN_PARAM_MMSC,"mmsc"},
{APN_PARAM_MMSPROXY,"mmsproxy"},
{APN_PARAM_MMSPORT,"mmsport"},
{APN_PARAM_AUTHTYPE,"authtype"},
{APN_PARAM_TYPE,"type"},
{APN_PARAM_PROTOCOL,"protocol"},
{APN_PARAM_PCO,"pco"},
{APN_PARAM_VENDORSPECIFIC,"vendorspecific"},
{APN_PARAM_ROAMINGPROTOCOL,"roaming_protocol"},
{APN_PARAM_BEARER,"bearer"},
{APN_PARAM_LAST,"last"}
};
extra_apn_data extra_apn_params_str[] = {
{EXTRA_APN_PARAM_AUTOCONNECT,"autoconnect"},
{EXTRA_APN_PARAM_ALWAYSON,"always_on"},
{EXTRA_APN_PARAM_LTEDEFAULT,"lte_default"},
{EXTRA_APN_PARAM_CONFIGONLY,"config_only"},
{EXTRA_APN_PARAM_TETHERABLE,"tetherable"},
{EXTRA_APN_PARAM_ISHOST,"is_host"},
{EXTRA_APN_PARAM_DATAONROAMING,"data_on_roaming"},
{EXTRA_APN_PARAM_MTU,"mtu"},
{EXTRA_APN_PARAM_LAST,"last"}
};
//////////////////////////////////////////////////////////////////////
// Functions implementations
//////////////////////////////////////////////////////////////////////
/*========================== XML API ====================================*/
#if CONFIG_LIBXML2
/**
* remove a given entry {mcc,mnc,carrier} from xml file
*
* @param cur xml file root node
* @param mcc
* @param mnc
* @param carrier PDP carrier
*/
static void remove_entry(xmlNodePtr cur,char *mcc,char *mnc,char *carrier)
{
xmlNodePtr tempPtr,nodePtr = NULL;
xmlChar *mcc_p;
xmlChar *mnc_p;
xmlChar *carrier_p;
if(cur == NULL) {
CM_Log(remove_entry, "XML parser: xmlCurNodePtr = NULL!!!");
} else {
// Get next node, and start walking the XML tree
nodePtr = cur->children;
while (nodePtr != NULL)
{
if ((!xmlStrcmp(nodePtr->name, (const xmlChar *)"apn"))) {
mcc_p = xmlGetProp(nodePtr, (const xmlChar *)"mcc");
mnc_p = xmlGetProp(nodePtr, (const xmlChar *)"mnc");
carrier_p = xmlGetProp(nodePtr, (const xmlChar *)"carrier");
if (!xmlStrcmp(mcc_p, BAD_CAST mcc) && !xmlStrcmp(mnc_p, BAD_CAST mnc) &&
!xmlStrcmp(carrier_p, BAD_CAST carrier)){
/*match found - now delete it*/
tempPtr = nodePtr;
nodePtr = nodePtr->next;
/*delete the node*/
xmlUnlinkNode(tempPtr);
xmlFreeNode(tempPtr);
xmlFree(mcc_p);
xmlFree(mnc_p);
xmlFree(carrier_p);
continue;
}
}
//Get next node
nodePtr = nodePtr->next;
}
}
return;
}
/********************************************************
* Function: openXmlFile
*
* Input: char *docname - The XML file we want to open for parsing
*
* Description: Open the main XML file, and calls the parsing algorithm
*/
static xmlDocPtr openXmlFile(char *docname)
{
xmlDocPtr xmlFilePtr = xmlParseFile(docname);
if (xmlFilePtr == NULL )
{
CM_Log(openXmlFile, "openXmlFile - Error: Could not open XML file - %s !", docname);
}
return xmlFilePtr;
}
/**
* return the root node of the xml file
*
* @param xmlFilePtr pointer of the xml file
*
* @return root node
*/
static xmlNodePtr getXmlRoot(xmlDocPtr xmlFilePtr)
{
xmlNodePtr root = xmlDocGetRootElement(xmlFilePtr);
if (root != NULL){
if (xmlStrcmp(root->name, (const xmlChar *) EXTRA_XML_ROOT_COMPONENT)) {
return NULL;
}
}
return root;
}
/********************************************************
* Function: createXmlFile
*
* Input: char *docname - The XML file we want to create
*
* Description: Create XML file with root element
*/
static xmlDocPtr createXmlFile(char *docname, char *root_name)
{
xmlNodePtr root;
xmlDocPtr xmlFilePtr = xmlNewDoc((const xmlChar *)"1.0");
if (xmlFilePtr == NULL ) {
CM_Log(createXmlFile, "createXmlFile - Could not create XML file - %s !", docname);
return FALSE;
}
root = xmlNewNode(NULL, (const xmlChar *) root_name);
if (root == NULL)
{
CM_Log(createXmlFile1, "createXmlFile - Could not create new node - %s !", root_name);
xmlFreeDoc(xmlFilePtr);
return NULL;
}
xmlDocSetRootElement(xmlFilePtr, root);
if (saveXmlFile(docname, xmlFilePtr) == -1)
{
CM_Log(createXmlFile2, "createXmlFile - Could not save XML file - %s !", docname);
xmlFreeDoc(xmlFilePtr);
return NULL;
}
return xmlFilePtr;
}
/********************************************************
* Function: saveXmlFile
*
* Description: Save the current XML Document to file
*/
static int saveXmlFile(char *docname, xmlDocPtr xmlFilePtr)
{
xmlKeepBlanksDefault(0);
xmlIndentTreeOutput = 1;
return xmlSaveFormatFileEnc(docname, xmlFilePtr, "UTF-8", 1);
}
/********************************************************
* Function: closeXmlFile
*
* Description: Closes the current XML File
*/
static void closeXmlFile(xmlDocPtr xmlFilePtr)
{
if (xmlFilePtr != NULL)
{
xmlFreeDoc(xmlFilePtr);
}
else
{
CM_Log(closeXmlFile, "closeXmlFile - Error: Could not close XML file!");
}
return;
}
/**
* wrapper function:
* copy the given APN information struct to our database files
*
* @param ptr_apn pointer to APN information struct
* @param mcc
* @param mnc
* @param carrier PDP carrier
*
* @return 1 - success
* 0 - failed to set
*/
int set_params(Apn_Info *ptr_apn,char *mcc ,char *mnc ,char *carrier )
{
int rc = 1;
char my_mcc[4];
char my_mnc[4];
if (mcc == NULL || mnc == NULL) {
/* use mcc mnc from sim */
strcpy(my_mcc, IMSI_APN->mcc);
strcpy(my_mnc, IMSI_APN->mnc);
}else{
strcpy(my_mcc, mcc);
strcpy(my_mnc, mnc);
}
/*set the overide params in the database*/
rc &= set_additional_params(ptr_apn,my_mcc,my_mnc,carrier,1);
/*set the extra params in the database*/
rc &= set_additional_params(ptr_apn,my_mcc,my_mnc,carrier,0);
/* return 1 for success */
return rc;
}
/**
* copy the given APN information struct to our overide database
*
* @param node apn node containing the new information
* @param ptr_apn pointer to APN information struct
* @param mcc
* @param mnc
* @param carrier PDP carrier
*/
void set_overide_props(xmlNodePtr node,Apn_Info *ptr_apn,char *mcc,char *mnc,char *carrier)
{
xmlNewProp(node, BAD_CAST "carrier", BAD_CAST carrier);
xmlNewProp(node, BAD_CAST "mcc", BAD_CAST mcc);
xmlNewProp(node, BAD_CAST "mnc", BAD_CAST mnc);
if ((strlen(ptr_apn->type))>0) {
xmlNewProp(node, BAD_CAST "type", BAD_CAST ptr_apn->type);
}
if ((strlen(ptr_apn->apn))>0) {
xmlNewProp(node, BAD_CAST "apn", BAD_CAST ptr_apn->apn);
}
if ((strlen(ptr_apn->protocol))>0) {
xmlNewProp(node, BAD_CAST "protocol", BAD_CAST ptr_apn->protocol);
}
if ((strlen(ptr_apn->usrname))>0) {
xmlNewProp(node, BAD_CAST "usrname", BAD_CAST ptr_apn->usrname);
}
if ((strlen(ptr_apn->paswd))>0) {
xmlNewProp(node, BAD_CAST "paswd", BAD_CAST ptr_apn->paswd);
}
if ((strlen(ptr_apn->server))>0) {
xmlNewProp(node, BAD_CAST "server", BAD_CAST ptr_apn->server);
}
if ((strlen(ptr_apn->proxy))>0) {
xmlNewProp(node, BAD_CAST "proxy", BAD_CAST ptr_apn->proxy);
}
if ((strlen(ptr_apn->port))>0) {
xmlNewProp(node, BAD_CAST "port", BAD_CAST ptr_apn->port);
}
if ((strlen(ptr_apn->mmsproxy))>0) {
xmlNewProp(node, BAD_CAST "mmsproxy", BAD_CAST ptr_apn->mmsproxy);
}
if ((strlen(ptr_apn->mmsport))>0) {
xmlNewProp(node, BAD_CAST "mmsport", BAD_CAST ptr_apn->mmsport);
}
if ((strlen(ptr_apn->mmsc))>0) {
xmlNewProp(node, BAD_CAST "mmsc", BAD_CAST ptr_apn->mmsc);
}
if ((strlen(ptr_apn->authtype))>0) {
xmlNewProp(node, BAD_CAST "authtype", BAD_CAST ptr_apn->authtype);
}
if ((strlen(ptr_apn->pco))>0) {
xmlNewProp(node, BAD_CAST "pco", BAD_CAST ptr_apn->pco);
}
if ((strlen(ptr_apn->vendorSpecific))>0) {
xmlNewProp(node, BAD_CAST "vendorspecific", BAD_CAST ptr_apn->vendorSpecific);
}
if ((strlen(ptr_apn->roamingProtocol))>0) {
xmlNewProp(node, BAD_CAST "roaming_protocol", BAD_CAST ptr_apn->roamingProtocol);
}
if ((strlen(ptr_apn->bearer))>0) {
xmlNewProp(node, BAD_CAST "bearer", BAD_CAST ptr_apn->bearer);
}
return;
}
/**
* copy the given APN information struct to our extra database
*
* @param node apn node containing the new information
* @param ex_apn pointer to APN information struct
* @param mcc
* @param mnc
* @param carrier PDP carrier
*/
void set_extra_props(xmlNodePtr node,Extra_Apn_Info *ex_apn,char *mcc,char *mnc,char *carrier)
{
char buf[10] = {0};
xmlNewProp(node, BAD_CAST "carrier", BAD_CAST carrier);
xmlNewProp(node, BAD_CAST "mcc", BAD_CAST mcc);
xmlNewProp(node, BAD_CAST "mnc", BAD_CAST mnc);
sprintf(buf,"%d",ex_apn->autoconnect);
xmlNewProp(node, BAD_CAST "autoconnect", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->lte_default);
xmlNewProp(node, BAD_CAST "lte_default", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->always_on);
xmlNewProp(node, BAD_CAST "always_on", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->config_only);
xmlNewProp(node, BAD_CAST "config_only", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->tetherable);
xmlNewProp(node, BAD_CAST "tetherable", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->is_host);
xmlNewProp(node, BAD_CAST "is_host", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->data_on_roaming);
xmlNewProp(node, BAD_CAST "data_on_roaming", BAD_CAST buf);
sprintf(buf,"%d",ex_apn->mtu);
xmlNewProp(node, BAD_CAST "mtu", BAD_CAST buf);
return;
}
/**
* check if file is existed
*
* @param fname filename - full path
*
* @return 1 - file exist
* 0 - file doesn't exist
*/
int is_file_existed(char *fname )
{
if( access( fname, F_OK ) != -1 )
/* file exists */
return 1;
else{
/* file NOT exists */
if (errno == ENOENT)
return 0;
//other error that we didn't expect - why retun TRUE if file not exist????
return 1;
}
}
/**
* remove apn entry from our database
*
* @param mcc
* @param mnc
* @param carrier PDP carrier
* @param option 0 - overide DB
* 1 - extra DB
*
* @return 1 - success
* 0 - failure
*/
int remove_apn(char *mcc ,char *mnc ,char *carrier, int option) {
xmlDocPtr xmlFilePtr = NULL;
xmlNodePtr root;
char fname[50] = {0};
if (option == 0)
strcpy(fname,APNS_OVERIDE_FILENAME);
else
strcpy(fname,APNS_EXTRA_FILENAME);
xmlFilePtr = openXmlFile(fname);
if (xmlFilePtr == NULL)
return 0;
root = getXmlRoot(xmlFilePtr);
if (root == NULL)
return 0;
remove_entry(root,mcc,mnc,carrier);
if (saveXmlFile(fname, xmlFilePtr) == -1)
{
CM_Log(remove_apn, "remove_apn - Error: Could not save XML file - %s !", fname);
xmlFreeDoc(xmlFilePtr);
return 0;
}
closeXmlFile(xmlFilePtr);
return 1;
}
/**
* copy the given APN information struct to our database files
*
* @param ptr_apn pointer to APN information struct
* @param mcc
* @param mnc
* @param carrier PDP carrier
* @param option 0 - copy to the overide xml
* 1 - copy to the extra xml
*
* @return 1 - success
* 0 - failed to set
*/
int set_additional_params(Apn_Info *ptr_apn,char *mcc ,char *mnc ,char *carrier,int option ){
xmlDocPtr xmlFilePtr = NULL;
xmlNodePtr root;
xmlNodePtr node;
char fname[50] = {0};
char *tmp_carrier = NULL;
Extra_Apn_Info *ex_apn = &(ptr_apn->Extra_params);
CM_Log(set_additional_params, "set_additional_params: mcc=%s,mnc=%s,carrier=%s,option=%d", mcc, mnc, carrier, option);
if (option == 0)
strcpy(fname,APNS_OVERIDE_FILENAME);
else
strcpy(fname,APNS_EXTRA_FILENAME);
/*check if the databse file is already existed*/
if (is_file_existed(fname)){
CM_Log(set_additional_params1, "set_additional_params - XML file - %s exist!", fname);
xmlFilePtr = openXmlFile(fname);
}
if (xmlFilePtr == NULL) {
CM_Log(set_additional_params2, "set_additional_params - XML file - %s doesn't exist! create it!", fname);
xmlFilePtr = createXmlFile(fname,EXTRA_XML_ROOT_COMPONENT);
xmlFilePtr = openXmlFile(fname);
}
/*get root node*/
root = getXmlRoot(xmlFilePtr);
if (root == NULL)
return 0;
/*if this entry (mcc,mnc,carrier) already existed - need to remove*/
remove_entry(root,mcc,mnc,carrier);
/*if the carrier has changed - need to remove if exist */
if(strcmp(carrier, ptr_apn->carrier)) {
remove_entry(root,mcc,mnc,ptr_apn->carrier);
}
if(!strcmp(ptr_apn->carrier, ""))
tmp_carrier = carrier;
else
tmp_carrier = ptr_apn->carrier;
node=xmlNewChild(root, NULL, BAD_CAST "apn", NULL);
if (option == 0)
set_overide_props(node,ptr_apn,mcc,mnc,tmp_carrier);
else
set_extra_props(node,ex_apn,mcc,mnc,tmp_carrier);
if (saveXmlFile(fname, xmlFilePtr) == -1)
{
CM_Log(set_additional_params3, "set_additional_params - Error: Could not save XML file - %s !", fname);
xmlFreeDoc(xmlFilePtr);
return 0;
}
closeXmlFile(xmlFilePtr);
return 1;
}
#endif
/**
* get default APN information from our database
*
* @param docname xml filename (database of the default params)
* @param ex_apn extra APN struct to fill
*
* @return 0 - no default params are found or error
* 1 - default params are found
*/
int get_default_params(char *docname,Extra_Apn_Info *ex_apn,const char *type) {
#if CONFIG_LIBXML2
xmlTextReaderPtr reader;
xmlChar *name;
#elif CONFIG_LIBMXML
mxml_node_t *root = NULL;
mxml_node_t *cur = NULL;
FILE *fp = NULL;
#endif
int ret,j,i=0;
char *param[7] = {NULL};
char *tok = NULL;
char *tmp_type = malloc(strlen(type)+1);
strcpy(tmp_type, type);
while ((tok = strsep(&tmp_type, ",")) != NULL && i < 7) {
param[i] = tok;
i++;
}
free(tmp_type);
#if CONFIG_LIBMXML
fp = fopen(docname, "r");
if (fp == NULL) {
ret = -1;
goto end;
}
root = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
fclose(fp);
#endif
for (j=0;j<i;j++) {
#if CONFIG_LIBXML2
/*open the xml file*/
reader = xmlNewTextReaderFilename(docname);
if (reader != NULL ) {
/*read the root node*/
ret = xmlTextReaderRead(reader);
while (ret == 1) {
name = xmlTextReaderName(reader);
/*search for default configuration for this PDP type*/
if (!xmlStrcmp(name, (xmlChar*) param[j])){
/*parse deafult apn params to struct*/
parse_ex_params(reader,ex_apn);
xmlFreeTextReader(reader);
return 1;
}
/*read the next node*/
ret = xmlTextReaderRead(reader);
}
/*EOF -no more nodes to read, ret should be 0*/
xmlFreeTextReader(reader);
if (ret != 0) {
CM_Log(get_default_params, "%s : failed to parse\n", docname);
return 0;
}
} else {
CM_Log(get_default_params1, "Unable to open %s\n", docname);
return 0;
}
#elif CONFIG_LIBMXML
CM_Log(get_default_params, "%s: param[%d] %s\n", __func__, j, param[j]);
cur = mxmlFindElement(root, root, param[j], NULL, NULL, MXML_DESCEND);
if (cur == NULL) {
CM_Log(get_default_params604, "%s: can't find node %s\n", __func__, param[j]);
ret = -1;
goto end;
}
parse_ex_params(cur,ex_apn);
ret = 1;
end:
if (root)
mxmlDelete(root);
return ret;
#endif
}
return 1;
}
/**
* transforms given basic apn param string to its enum index
*
* @param str string of basic apn parameter
*
* @return enum index
*/
enum apn_params apn_param_str_to_enum(char *str) {
int i;
for (i=0;i<APN_PARAM_LAST;i++) {
if (!strcmp(str,apn_params_str[i].str)) {
return apn_params_str[i].entry;
}
}
return APN_PARAM_LAST;
}
/**
* transforms given extra apn param string to its enum index
*
* @param str string of extra apn parameter
*
* @return enum index
*/
enum extra_apn_params ex_apn_param_str_to_enum(char *str) {
int i;
for (i=0;i<EXTRA_APN_PARAM_LAST;i++) {
if (!strcmp(str,extra_apn_params_str[i].str)) {
return extra_apn_params_str[i].entry;
}
}
return EXTRA_APN_PARAM_LAST;
}
/**
* parse basic/overide apn information from the database, to our APN struct
*
* @param reader apn node in the extra file with {mcc,mnc} as in our basic struct
* @param get_apn struct contain APN information - mcc&mnc
*/
#if CONFIG_LIBXML2
void parse_apn(xmlTextReaderPtr reader,Mnc_Apn *get_apn){
xmlChar *temp;
#elif CONFIG_LIBMXML
void parse_apn(mxml_node_t *node, Mnc_Apn *get_apn){
const xmlChar *temp;
#endif
int i;
char tmp_apn_param[APN_PARAM_LAST][MAX_STR_LEN] = {{0}};
Apn_Info *tmp_info = NULL;
for (i=0; i<APN_PARAM_LAST; i++) {
#if CONFIG_LIBXML2
temp = xmlTextReaderGetAttribute(reader,(const xmlChar *)apn_params_str[i].str);
#elif CONFIG_LIBMXML
temp = (const xmlChar * )mxmlElementGetAttr(node, apn_params_str[i].str);
#endif
if (temp) {
if(apn_param_str_to_enum(apn_params_str[i].str) < APN_PARAM_LAST) {
//coverity[overrun-local:SUPPRESS]
strncpy(tmp_apn_param[apn_param_str_to_enum(apn_params_str[i].str)],(char *)temp,MAX_STR_LEN-1);
CM_Log(parse_apn681, "found attr:%d - name %s, value %s\n", i, apn_params_str[i].str, temp);
} else {
CM_Log(parse_apn686, "apn_param_str_to_enum overrun %s\n");
}
#if CONFIG_LIBXML2
xmlFree(temp);
#endif
}
}
/* run to the end of the APN list and add new Apn_Info
or if APN carrier is already exist - override!*/
for (i=0; i<MAX_APN_NUM; i++) {
tmp_info = &(get_apn->apn_info_list[i]);
if (tmp_info->basic_set == 0) {
tmp_info->basic_set = 1;
break;
}
CM_Log(parse_apn697, "carrier %s\n", tmp_info->carrier);
if ((strlen(tmp_apn_param[APN_PARAM_CARRIER]) > 0) &&
!strcmp(tmp_info->carrier, tmp_apn_param[APN_PARAM_CARRIER]))
break;
}
if (i == MAX_APN_NUM) //APN list is full
return;
/*fill the APN info struct with the parsed values */
if (strlen(tmp_apn_param[APN_PARAM_CARRIER]) > 0) {
strcpy(tmp_info->carrier,tmp_apn_param[APN_PARAM_CARRIER]);
CM_Log(parse_apn, "found APN:%d - %s\n", i, tmp_info->carrier);
}
if (strlen(tmp_apn_param[APN_PARAM_APN]) > 0) {
strcpy(tmp_info->apn,tmp_apn_param[APN_PARAM_APN]);
strcpy(tmp_info->lte_apn,tmp_apn_param[APN_PARAM_APN]);
CM_Log(parse_apn, "found APN name:%d - %s\n", i, tmp_info->apn);
}
if (strlen(tmp_apn_param[APN_PARAM_TYPE]) > 0) {
strcpy(tmp_info->type,tmp_apn_param[APN_PARAM_TYPE]);
}
if (strlen(tmp_apn_param[APN_PARAM_USER]) > 0) {
strcpy(tmp_info->usrname,tmp_apn_param[APN_PARAM_USER]);
strcpy(tmp_info->lte_usrname,tmp_apn_param[APN_PARAM_USER]);
}
if (strlen(tmp_apn_param[APN_PARAM_PASSWORD]) > 0) {
strcpy(tmp_info->paswd,tmp_apn_param[APN_PARAM_PASSWORD]);
strcpy(tmp_info->lte_paswd,tmp_apn_param[APN_PARAM_PASSWORD]);
}
if (strlen(tmp_apn_param[APN_PARAM_SERVER]) > 0) {
strcpy(tmp_info->server,tmp_apn_param[APN_PARAM_SERVER]);
}
if (strlen(tmp_apn_param[APN_PARAM_PROXY]) > 0) {
strcpy(tmp_info->proxy,tmp_apn_param[APN_PARAM_PROXY]);
}
if (strlen(tmp_apn_param[APN_PARAM_PORT]) > 0) {
strcpy(tmp_info->port,tmp_apn_param[APN_PARAM_PORT]);
}
if (strlen(tmp_apn_param[APN_PARAM_MMSPROXY]) > 0) {
strcpy(tmp_info->mmsproxy,tmp_apn_param[APN_PARAM_MMSPROXY]);
}
if (strlen(tmp_apn_param[APN_PARAM_MMSPORT]) > 0) {
strcpy(tmp_info->mmsport,tmp_apn_param[APN_PARAM_MMSPORT]);
}
if (strlen(tmp_apn_param[APN_PARAM_MMSC]) > 0) {
strcpy(tmp_info->mmsc,tmp_apn_param[APN_PARAM_MMSC]);
}
if (strlen(tmp_apn_param[APN_PARAM_AUTHTYPE]) > 0) {
strcpy(tmp_info->authtype,tmp_apn_param[APN_PARAM_AUTHTYPE]);
strcpy(tmp_info->lte_authtype,tmp_apn_param[APN_PARAM_AUTHTYPE]);
}
if (strlen(tmp_apn_param[APN_PARAM_PROTOCOL]) > 0) {
strcpy(tmp_info->protocol,tmp_apn_param[APN_PARAM_PROTOCOL]);
}
if (strlen(tmp_apn_param[APN_PARAM_PCO]) > 0) {
strcpy(tmp_info->pco,tmp_apn_param[APN_PARAM_PCO]);
}
if (strlen(tmp_apn_param[APN_PARAM_VENDORSPECIFIC]) > 0) {
strcpy(tmp_info->vendorSpecific,tmp_apn_param[APN_PARAM_VENDORSPECIFIC]);
}
if (strlen(tmp_apn_param[APN_PARAM_ROAMINGPROTOCOL]) > 0) {
strcpy(tmp_info->roamingProtocol,tmp_apn_param[APN_PARAM_ROAMINGPROTOCOL]);
}
if (strlen(tmp_apn_param[APN_PARAM_BEARER]) > 0) {
strcpy(tmp_info->bearer,tmp_apn_param[APN_PARAM_BEARER]);
}
//set IPV4 as default
tmp_info->iptype=1;
return;
}
/**
* assuming basic\overide information has already been parsed,
* parse extra apn information from the database,
* to our APN struct
*
* @param reader apn node in the extra file with {mcc,mnc} as in our basic struct
* @param get_apn struct contain APN information - mcc&mnc
*/
#if CONFIG_LIBXML2
void parse_ex_apn(xmlTextReaderPtr reader,Mnc_Apn *get_apn){
xmlChar *carrier;
#elif CONFIG_LIBMXML
void parse_ex_apn(mxml_node_t *node, Mnc_Apn *get_apn){
const xmlChar *carrier;
#endif
Apn_Info *tmp_info;
int i;
//APN type in the extra configuration file
#if CONFIG_LIBXML2
carrier = xmlTextReaderGetAttribute(reader,(const xmlChar *)"carrier");
#endif
#if CONFIG_LIBMXML
carrier = (const xmlChar *)mxmlElementGetAttr(node, "carrier");
#endif
if (carrier == NULL)
return;
/*run through APN list and check APN carrier match*/
for (i=0; i<MAX_APN_NUM; i++) {
/*missing default params*/
if (get_apn->apn_info_list[i].basic_set == 0) {
return;
}
tmp_info = &(get_apn->apn_info_list[i]);
#if CONFIG_LIBXML2
if (!xmlStrcmp(carrier, (const xmlChar *)tmp_info->carrier)){
/*APN carrier match - parse the extra parameters*/
parse_ex_params(reader,&(tmp_info->Extra_params));
}
#endif
#if CONFIG_LIBMXML
CM_Log(parse_ex_apn834, "%s: carrier %s, apn_info_list[%d] carrier %s\n", __func__, carrier, i, tmp_info->carrier);
if (!strcmp((const char *)carrier, (const char *)tmp_info->carrier)){
parse_ex_params(node,&(tmp_info->Extra_params));
}
#endif
tmp_info->extra_set = 1;
}
#if CONFIG_LIBXML2
xmlFree(carrier);
#endif
CM_Log(parse_ex_apn844, "%s: done\n", __func__);
return;
}
/**
* parse extra APN information to struct
*
* @param reader apn node in the extra/default file with {mcc,mnc} as in our basic struct
* @param ex_info extra APN information struct
*/
#if CONFIG_LIBXML2
void parse_ex_params(xmlTextReaderPtr reader,Extra_Apn_Info *ex_info){
xmlChar *temp;
#elif CONFIG_LIBMXML
void parse_ex_params(mxml_node_t *node, Extra_Apn_Info *ex_info){
const xmlChar *temp;
#endif
int i;
char tmp_ex_apn_param[EXTRA_APN_PARAM_LAST][MAX_STR_LEN] = {{0}};
for (i=0; i<EXTRA_APN_PARAM_LAST; i++){
/*search for specific extra param in the apn node*/
#if CONFIG_LIBXML2
temp = xmlTextReaderGetAttribute(reader,(const xmlChar *)extra_apn_params_str[i].str);
#elif CONFIG_LIBMXML
temp = (const xmlChar *)mxmlElementGetAttr(node, (const char*)extra_apn_params_str[i].str);
#endif
if (temp) {
/*extra param has been found, copy to a sorted struct*/
if(ex_apn_param_str_to_enum(extra_apn_params_str[i].str) < EXTRA_APN_PARAM_LAST) {
//coverity[overrun-local:SUPPRESS]
strncpy(tmp_ex_apn_param[ex_apn_param_str_to_enum(extra_apn_params_str[i].str)],(char *)temp,MAX_STR_LEN-1);
CM_Log(parse_ex_params865, "%s: %s - %s\n", __func__, extra_apn_params_str[i].str, tmp_ex_apn_param[ex_apn_param_str_to_enum(extra_apn_params_str[i].str)]);
} else {
CM_Log(parse_ex_params882, "%s: tmp_ex_apn_param overrun\n", __func__);
}
#if CONFIG_LIBXML2
xmlFree(temp);
#endif
}
}
/*now all the extra apn params are in a sorted struct
fill the EXTRA APN info struct with the parsed values */
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_AUTOCONNECT]) > 0) {
ex_info->autoconnect = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_AUTOCONNECT][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_ALWAYSON]) > 0) {
ex_info->always_on = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_ALWAYSON][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_LTEDEFAULT]) > 0) {
ex_info->lte_default = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_LTEDEFAULT][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_CONFIGONLY]) > 0) {
ex_info->config_only = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_CONFIGONLY][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_TETHERABLE]) > 0) {
ex_info->tetherable = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_TETHERABLE][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_ISHOST]) > 0) {
ex_info->is_host = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_ISHOST][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_DATAONROAMING]) > 0) {
ex_info->data_on_roaming = (int)(tmp_ex_apn_param[EXTRA_APN_PARAM_DATAONROAMING][0]-'0');
}
if (strlen(tmp_ex_apn_param[EXTRA_APN_PARAM_MTU]) > 0) {
ex_info->mtu = atoi(tmp_ex_apn_param[EXTRA_APN_PARAM_MTU]);
}
CM_Log(parse_ex_params908, "%s: done\n", __func__);
return;
}
#if CONFIG_LIBXML2
/**
* find APN node with a given mcc,mnc pair
*
* @param reader apn node to search
* @param get_apn struct contain APN information - mcc&mnc
*
* @return 0 - match not found
* 1 - match found
*/
int find_matched_apn(xmlTextReaderPtr reader,Mnc_Apn *get_apn){
xmlChar *mcc;
xmlChar *mnc;
mcc = xmlTextReaderGetAttribute(reader,(const xmlChar *)"mcc");
mnc = xmlTextReaderGetAttribute(reader,(const xmlChar *)"mnc");
if ( (!xmlStrcmp(mcc, (const xmlChar *)get_apn->mcc)) && (!xmlStrcmp(mnc, (const xmlChar *)get_apn->mnc)) ){
xmlFree(mcc);
xmlFree(mnc);
return 1;
}else{
xmlFree(mcc);
xmlFree(mnc);
return 0;
}
}
#endif
/**
* asumming mcc,mnc already received from sim.
* get APN information according to mcc && mnc we got in plmn from sim.
* search for matching APNS in our database
*
* @param docname xml filename (database)
* @param get_apn APN struct to fill, already containing mcc&mnc
* @param option 0 - get basic\overide APN information
* 1 - get extra APN information
*
* @return 0 - no match found for mcc&mnc pair in filename.xml
* 1 - match found for mcc&mnc pair in the filename.xml
*/
int get_apn_info_byMccMnc(char *docname,Mnc_Apn *get_apn,int option) {
#if CONFIG_LIBXML2
xmlTextReaderPtr reader;
int ret,found = 0;
reader = xmlNewTextReaderFilename(docname);
if (reader != NULL ) {
ret = xmlTextReaderRead(reader);
while (ret == 1) {
if (find_matched_apn(reader,get_apn)){
found = 1;
if (option == 0)
parse_apn(reader,get_apn);
else
parse_ex_apn(reader,get_apn);
}
ret = xmlTextReaderRead(reader);
}
xmlFreeTextReader(reader);
if (ret != 0) {
CM_Log(get_apn_info_byMccMnc, "%s : failed to parse\n", docname);
return 0;
}
} else {
CM_Log(get_apn_info_byMccMnc1, "Unable to open %s\n", docname);
return 0;
}
return found;
#elif CONFIG_LIBMXML
mxml_node_t *root = NULL;
mxml_node_t *cur = NULL;
mxml_node_t *node = NULL;
FILE *fp = NULL;
int found = 0;
const xmlChar *temp;
fp = fopen(docname, "r");
if (fp == NULL) {
goto end;
}
root = mxmlLoadFile(NULL, fp, MXML_OPAQUE_CALLBACK);
fclose(fp);
CM_Log(get_apn_info_byMccMnc989, "%s : docname %s, root %x\n",__func__, docname, root);
node = root;
while (1)
{
cur = mxmlFindElement(node, root, "apn", "mcc", get_apn->mcc, MXML_DESCEND);
if (cur == NULL) {
CM_Log(get_apn_info_byMccMnc994, "%s : find mcc=%s failed\n", __func__, get_apn->mcc);
goto end;
}
cur = mxmlFindElement(cur->prev, root, "apn", "mnc", get_apn->mnc, MXML_DESCEND);
if (cur == NULL) {
CM_Log(get_apn_info_byMccMnc1000, "%s : find mnc=%s failed\n", __func__, get_apn->mnc);
goto end;
}
CM_Log(get_apn_info_byMccMnc1013, "%s : find entry for{ mcc=%s, mnc=%s}\n", __func__, get_apn->mcc, get_apn->mnc);
temp = (const xmlChar * )mxmlElementGetAttr(cur, apn_params_str[APN_PARAM_MCC].str);
if (temp && strcmp((char *)temp, get_apn->mcc))
{
/*parsed mcc not match */
CM_Log(get_apn_info_byMccMnc1027, "%s : parsed mcc value %s, not matched, find next\n", __func__, temp);
node = cur->next;
continue;
}
found = 1;
if (option == 0)
parse_apn(cur, get_apn);
else
parse_ex_apn(cur, get_apn);
node = cur->next;
}
end:
if (root)
mxmlDelete(root);
CM_Log(get_apn_info_byMccMnc1028, "%s : found %d\n", __func__, found);
return found;
#endif
}
/**
* run over the apns list,
* and attach default params for each case there is no extra params
*
* @param mnc_data struct containing all the apns for given {mcc,mnc}
* @param default_params
* struct containing the default params
*/
void attachDefaultParams(Mnc_Apn* mnc_data)
{
int i,ret=0;
Apn_Info* apn_ptr;
Extra_Apn_Info default_params;
for (i=0;i<MAX_APN_NUM;i++) {
apn_ptr = &(mnc_data->apn_info_list[i]);
memset(&default_params,0,sizeof(Extra_Apn_Info));
/*check if basic information is set*/
if (apn_ptr->basic_set == 0)
return;
/*check if extra information is set*/
if (apn_ptr->extra_set == 1)
continue;
/*no extra information use default values*/
ret = get_default_params(APNS_DEFAULT_FILENAME,&default_params,apn_ptr->type);
if (ret==0){
CM_Log(attachDefaultParams, "attachDefaultParams - Error: missing default configuration file!");
return;
}
apn_ptr->Extra_params = default_params;
apn_ptr->extra_set = 1;
}
return;
}
/**
* fill APN's struct according to mcc && mnc.
* search for matching APNS in our database and fill the APN's struct
*
* @param mcc
* @param mnc
* @param mnc_data APN's struct to fill
*/
int fillApnInfo (char *mcc,char* mnc,Mnc_Apn *mnc_data){
int ret = 0;
if (mcc == NULL || mnc == NULL) {
/* use mcc mnc from sim */
strcpy(mnc_data->mcc, IMSI_APN->mcc);
strcpy(mnc_data->mnc, IMSI_APN->mnc);
}else{
/*may match many mncs with mcc but has different mnc length*/
strncpy(mnc_data->mcc, mcc, sizeof(mnc_data->mcc) - 1);
strncpy(mnc_data->mnc, mnc, sizeof(mnc_data->mnc) - 1);
}
/* fill basic/overide APN information */
ret |= get_apn_info_byMccMnc(APNS_FULL_FILENAME,mnc_data,0);
ret |= get_apn_info_byMccMnc(APNS_OVERIDE_FILENAME,mnc_data,0);
if (ret == 0){
CM_Log(fillApnInfo, "fillApnInfo - Error: {mcc=%s,mnc=%s} not found !", mcc, mnc);
return ret;
}
/* fill extra APN information */
get_apn_info_byMccMnc(APNS_EXTRA_FILENAME,mnc_data,1);
/*use default APN information in case there is no extra information*/
attachDefaultParams(mnc_data);
return ret;
}
/**
* print APN information
*
* @param apn_ptr APN information struct to print
*/
void printApn(Apn_Info *apn_ptr)
{
UNUSEDPARAM(apn_ptr);
CM_Log(printApn, "carrier=%s\n",apn_ptr->carrier);
CM_Log(printApn1, "apn=%s\n",apn_ptr->apn);
CM_Log(printApn2, "type=%s\n",apn_ptr->type);
CM_Log(printApn3, "protocol=%s\n",apn_ptr->protocol);
CM_Log(printApn4, "authtype=%s\n",apn_ptr->authtype);
CM_Log(printApn5, "mmsc=%s\n",apn_ptr->mmsc);
CM_Log(printApn6, "mmsport=%s\n",apn_ptr->mmsport);
CM_Log(printApn7, "mmsproxy=%s\n",apn_ptr->mmsproxy);
CM_Log(printApn8, "port=%s\n",apn_ptr->port);
CM_Log(printApn9, "proxy=%s\n",apn_ptr->proxy);
CM_Log(printApn10, "server=%s\n",apn_ptr->server);
CM_Log(printApn11, "usrname=%s\n",apn_ptr->usrname);
CM_Log(printApn12, "password=%s\n",apn_ptr->paswd);
CM_Log(printApn13, "pco=%s\n",apn_ptr->pco);
CM_Log(printApn14, "vendorspecific=%s\n",apn_ptr->vendorSpecific);
CM_Log(printApn15, "roaming_protocol=%s\n",apn_ptr->roamingProtocol);
CM_Log(printApn16, "bearer=%s\n",apn_ptr->bearer);
CM_Log(printApn17, "Extra params:\n");
CM_Log(printApn18, "always_on=%d\n",apn_ptr->Extra_params.always_on);
CM_Log(printApn19, "autoconnect=%d\n",apn_ptr->Extra_params.autoconnect);
CM_Log(printApn20, "config_only=%d\n",apn_ptr->Extra_params.config_only);
CM_Log(printApn21, "data_on_roaming=%d\n",apn_ptr->Extra_params.data_on_roaming);
CM_Log(printApn22, "mtu=%d\n",apn_ptr->Extra_params.mtu);
CM_Log(printApn23, "is_host=%d\n",apn_ptr->Extra_params.is_host);
CM_Log(printApn24, "lte_default=%d\n",apn_ptr->Extra_params.lte_default);
CM_Log(printApn25, "tetherable=%d\n",apn_ptr->Extra_params.tetherable);
}
/**
* print all APN's information according to mcc && mnc.
*
* @param mnc_data APN's struct to print,already containing mcc&mnc
*/
void printApnInfo (Mnc_Apn *mnc_data){
int i;
Apn_Info* apn_ptr;
//run over all the APN's for the given mcc,mnc
for (i=0;i<MAX_APN_NUM;i++) {
apn_ptr = &(mnc_data->apn_info_list[i]);
if (!apn_ptr)
return; //we run over all the APN list
/*check that APN params have been configured*/
if (apn_ptr->basic_set == 0)
return;
CM_Log(printApnInfo, "APN %d:\n",i);
CM_Log(printApnInfo1, "=====\n");
printApn(apn_ptr); //print APN params
}
return;
}
#if CONFIG_LIBXML2
/**
* asumming mcc,already received from imsi.
* get mnc length
*
* @param docname xml filename (database)
* @param mcc mcc value
*
* @return mnc length (2 or 3 digits)
*/
int get_mnc_length(char *docname,char *mcc) {
xmlTextReaderPtr reader;
int ret,mnc_len = 2;
xmlChar *node_mcc;
xmlChar *node_mnc;
reader = xmlNewTextReaderFilename(docname);
if (reader != NULL ) {
ret = xmlTextReaderRead(reader);
while (ret == 1) {
node_mcc = xmlTextReaderGetAttribute(reader,(const xmlChar *)"mcc");
node_mnc = xmlTextReaderGetAttribute(reader,(const xmlChar *)"mnc");
if (!xmlStrcmp(node_mcc, (const xmlChar *)mcc)) {
mnc_len=strlen((const char *)node_mnc);
xmlFree(node_mcc);
xmlFree(node_mnc);
break;
}else{
xmlFree(node_mcc);
xmlFree(node_mnc);
}
ret = xmlTextReaderRead(reader);
}
xmlFreeTextReader(reader);
if (ret == -1) {
CM_Log(get_mnc_length, "%s : failed to parse\n", docname);
return 0;
}
} else {
CM_Log(get_mnc_length1, "Unable to open %s\n", docname);
return 0;
}
return mnc_len;
}
#endif