blob: c4a192575b0e526356be9062fb384529d3bae273 [file] [log] [blame]
//////////////////////////////////////////////////////////////////////
// INCLUDE FILES FOR MODULE
//////////////////////////////////////////////////////////////////////
#include "cm_func.h"
#include "dialer_task.h"
#include <regex.h>
//////////////////////////////////////////////////////////////////////
// local Prototypes
//////////////////////////////////////////////////////////////////////
CM_Connection_Context *get_match_pdp(Apn_Info * apninfo);
bool redial_sleep(int count);
void CM_Handle_RoamChange(void);
void CM_Handle_NWChange(void);
void CM_Handle_Redial(int connectionNum);
void CM_Handle_Reject(void);
void CM_Handle_DefaultDataCall(void);
Apn_Info *get_inital_attach_apn(Mnc_Apn * apn_list, char *cur_apn);
Apn_Info *get_fota_apninfo(Mnc_Apn * apn_list);
void ClearETIFlag_data_cb(struct ubus_request *req, int type, struct blob_attr *msg);
//////////////////////////////////////////////////////////////////////
// Global Variables
//////////////////////////////////////////////////////////////////////
pthread_mutex_t cm_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cm_cond;
//global pdp context list
CM_Connection_Context *g_CM_Context = NULL;
//-1 -- initial value, 0 -- 2/3G, 1 -- LTE, 3 -- not registered
extern bool IsRoaming;
extern int NW_status;
#define MAX_ESM_TRY_NUM 2
char g_cid = 0;
extern Mnc_Apn *g_work_apn;
AttachApn_Info * g_attachapn = NULL;
//global redial interval
redial_interval *g_redial_interval = NULL;
extern struct ubus_context *cm_ctx;
extern cm_ubus_ctx_id cm_ubus_id;
extern struct blob_buf cm_b;
extern bool pipe_mode;
extern bool NWReady;
extern UINT8 g_last_default_cid;
//////////////////////////////////////////////////////////////////////
// functions definitions
//////////////////////////////////////////////////////////////////////
unsigned char check_roamStatus(void)
{
return IsRoaming;
}
CM_Connection_Context *CM_GetCtxListHead(void)
{
return g_CM_Context;
}
bool CM_IsDefaultCtxExist()
{
CM_Connection_Context *ctx = g_CM_Context;
bool exist = false;
if (ctx == NULL)
return exist;
while(ctx) {
if (ctx->pdpinfo && ctx->pdpinfo->is_default) {
exist = true;
break;
}
ctx = ctx->next;
}
return exist;
}
int PrimaryCid_Get(int connectionNum)
{
CM_Connection_Context *tmp_CM_Context;
int pri_con;
pri_con = connectionNum & SECONDARYPDP_CONNECTNUM_RANGE;
tmp_CM_Context = g_CM_Context;
while (tmp_CM_Context) {
if (tmp_CM_Context->pdpinfo->connectionNum == pri_con)
return tmp_CM_Context->pdpinfo->primaryCid;
tmp_CM_Context = tmp_CM_Context->next;
}
CM_Log(PrimaryCid_Get, "PrimaryCid_Get, can't find out the primaryCid\n");
return 0;
}
//free PacketFilterInfo, called by CM module
void TFTinfo_free(PacketFilterInfo * src_pfinfo)
{
PacketFilterInfo *tmp_pfinfo;
tmp_pfinfo = src_pfinfo;
while (tmp_pfinfo != NULL) {
tmp_pfinfo = tmp_pfinfo->next;
free(src_pfinfo);
src_pfinfo = tmp_pfinfo;
}
CM_Log(TFTinfo_free1, "TFTinfo_free done\n");
}
void LinkContext_free(Link_Context * linkcontext)
{
Link_Context *tmp_linkcontext;
tmp_linkcontext = linkcontext;
while (tmp_linkcontext != NULL) {
tmp_linkcontext = tmp_linkcontext->next;
free(linkcontext);
linkcontext = tmp_linkcontext;
}
}
//disconnect all secondary pdp when the according primary pdp is disconnect receiving ATNOK
#if 0
static void CM_Disconnect_SecondaryPDP(char con_num)
{
CM_Connection_Context *tmp_CM_Context;
tmp_CM_Context = g_CM_Context;
CM_Log("enter %s\n", __func__);
while (tmp_CM_Context) {
if (((tmp_CM_Context->pdpinfo->connectionNum & SECONDARYPDP_CONNECTNUM_RANGE) == con_num)
&& (tmp_CM_Context->pdpinfo->PDP_Type == 0)) {
tmp_CM_Context->connectStatus = CM_CONNECT_DISCON;
}
tmp_CM_Context = tmp_CM_Context->next;
}
CM_Log("leave %s\n", __func__);
}
#endif
/*===========================================================================
FUNCTION CM_Delete_Cur_Context
DESCRIPTION
Delete the current connection context from the list, called by CM module.
INPUT
CM_Connection_Context
===========================================================================*/
void CM_Delete_Cur_Context(CM_Connection_Context * cur_CM_Context)
{
CM_Connection_Context *tmp_CM_Context;
CM_Connection_Context *tmp_next;
tmp_CM_Context = g_CM_Context;
CM_Log(CM_Delete_Cur_Context, "enter CM_Delete_Cur_Context, delete context 0x%x, head context 0x%x\n", cur_CM_Context, tmp_CM_Context);
if (tmp_CM_Context == NULL) {
return;
}
//the first context is the current delete context
if (tmp_CM_Context == cur_CM_Context) {
g_CM_Context = tmp_CM_Context->next;
CM_Context_free(tmp_CM_Context);
return;
}
tmp_next = tmp_CM_Context->next;
while (tmp_next) {
if (tmp_next == cur_CM_Context) {
tmp_CM_Context->next = tmp_next->next;
CM_Context_free(tmp_next);
return;
}
tmp_CM_Context = tmp_next;
tmp_next = tmp_next->next;
}
}
//free function for CM_Connection_Context, and release CID here, called by CM module
void CM_Context_free(CM_Connection_Context * CM_Context)
{
if (CM_Context == g_CM_Context) {
g_CM_Context = CM_Context->next;
}
if (CM_Context != NULL) {
if (CM_Context->pdpinfo != NULL) {
free(CM_Context->pdpinfo);
}
if (CM_Context->ipv4info != NULL)
free(CM_Context->ipv4info);
if (CM_Context->ipv6info != NULL)
free(CM_Context->ipv6info);
//delete tft info list
if (CM_Context->tftinfo != NULL)
TFTinfo_free(CM_Context->tftinfo);
free(CM_Context);
}
CM_Log(CM_Context_free, "CM_Context_free, context addr:0x%x done\n", CM_Context);
}
void CM_DeleteAllContext(void)
{
CM_Connection_Context *ctx = g_CM_Context;
CM_Connection_Context *ctx_next = NULL;
ctx_next = ctx;
while(ctx)
{
ctx_next = ctx->next;
CM_Delete_Cur_Context(ctx);
ctx = ctx_next;
}
CM_Log(CM_DeleteAllContext, "CM_DeleteAllContext: done, g_CM_Context 0x%x\n", g_CM_Context);
}
#if 0
static CM_Connection_Context *CM_Exist_DefaultPdp(void)
{
CM_Connection_Context *tmp_CM_Context;
tmp_CM_Context = g_CM_Context;
if (tmp_CM_Context == NULL)
return NULL;
while (tmp_CM_Context) {
if (tmp_CM_Context->pdpinfo->connectionNum == 0)
return tmp_CM_Context;
tmp_CM_Context = tmp_CM_Context->next;
}
return NULL;
}
#endif
bool CM_CheckContextValid(CM_Connection_Context * ConInfo)
{
CM_Connection_Context *ctx = g_CM_Context;
bool is_valid = false;
while (ctx)
{
if (ctx == ConInfo)
{
is_valid = true;
break;
}
ctx = ctx->next;
}
CM_Log(CM_CheckContextValid, "CM_CheckContextValid: context 0x%x validation %d", ConInfo, is_valid);
return is_valid;
}
void CM_StartDialer(CM_Connection_Context * ConInfo)
{
Data_Call_Response *p_response = NULL;
system("echo cm.lock > /sys/power/wake_lock");
if (ConInfo->first_dial == 0) {
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
{
int retry_times = 0;
CheckDataCallRegisterStatus();
while(NW_status == CM_NW_STATUS_NOT_REGISTERED && retry_times++ < RETRY_NW_REGISTER_TIMES)
{
sleep(1);
CheckDataCallRegisterStatus();
}
if (retry_times == RETRY_NW_REGISTER_TIMES)
{
/*reach max retry times*/
CM_Log(CM_StartDialer, "CM_StartDialer, [PIPE MANUAL MODE] network not registered");
if (CM_CheckContextValid(ConInfo))
{
ConInfo->connectStatus = CM_CONNECT_DISCON;
ConInfo->dialFailureCode = PDP_FAIL_DATA_REGISTRATION_FAIL;
}
goto Exit;
}
}
#else
/* check the register status anyway*/
CheckDataCallRegisterStatus();
if (NW_status == CM_NW_STATUS_NOT_REGISTERED) { //network not ready if not first dial
CM_Log(CM_StartDialer, "CM_StartDialer, network not registered");
if (CM_CheckContextValid(ConInfo))
{
ConInfo->connectStatus = CM_CONNECT_WAIT_NWCHANGE;
ConInfo->dialFailureCode = 0;
}
goto Exit;
}
#endif
}
else {
CM_Log(CM_StartDialer1, "CM_StartDialer: first dial, check data call register status\n");
CheckDataCallRegisterStatus();
if (CM_CheckContextValid(ConInfo))
ConInfo->first_dial = 0;
}
/* Here check whether context is valid, cause CheckDataCallRegisterStatus is sync invoke,
* context may changed in some indication or async invoke data callback */
if (!CM_CheckContextValid(ConInfo))
goto Exit;
if (check_roamStatus() && ConInfo->pdpinfo->data_on_roaming == 0)
{
CM_Log_E(CM_StartDialer333, "CM_StartDialer disable data on roaming, no need to start dialer");
goto Exit;
}
if (ConInfo->pdpinfo)
CM_Log_D(CM_StartDialer333, "CM_StartDialer: start dialer for apn %s, lteapn %s, ip type %d, cid %d", strlen(ConInfo->pdpinfo->APN) ? ConInfo->pdpinfo->APN : "NULL",
strlen(ConInfo->pdpinfo->LteAPN) ? ConInfo->pdpinfo->LteAPN : "NULL", ConInfo->pdpinfo->IP_Type, ConInfo->pdpinfo->primaryCid);
ConInfo->dialFailureCode = -1;
p_response = StartDialer(ConInfo);
if (!p_response) {
CM_Log_E(CM_StartDialer2, "CM_StartDialer:[ERROR] no dialer response!");
goto Exit;
}
if (!CM_CheckContextValid(ConInfo))
goto Exit;
CM_Log(CM_StartDialer3, "CM_StartDialer: get dialer status %d, ip type %d, cid %d\n", p_response->status, p_response->IP_Type, p_response->cid);
if (p_response->status == PDP_DIAL_STATUS_OK || p_response->status == PDP_FAIL_GET_GLOBALIP) {
if (p_response->status == PDP_DIAL_STATUS_OK) {
ConInfo->connectStatus = CM_CONNECT_CONSUCCESS;
ConInfo->dialFailureCode = 0;
ConInfo->dial_cnt = 0;
}
else {
ConInfo->connectStatus = CM_CONNECT_GET_GLOBALIP_ERR;
ConInfo->dialFailureCode = p_response->status;
}
/*here shoud use mtu in pdp context*/
if (p_response->mtu <= 0)
p_response->mtu = ConInfo->pdpinfo->mtu;
ConInfo->pdpinfo->IP_Type = p_response->IP_Type;
if (ConInfo->pdpinfo->PDP_Type == 1)
ConInfo->pdpinfo->primaryCid = p_response->cid;
else {
ConInfo->pdpinfo->secondaryCid = p_response->cid;
ConInfo->pdpinfo->primaryCid = PrimaryCid_Get(ConInfo->pdpinfo->connectionNum);
}
strcpy(ConInfo->pdpinfo->APN, p_response->apn);
if (p_response->ipv4info != NULL) {
if (ConInfo->ipv4info == NULL) {
ConInfo->ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (ConInfo->ipv4info == NULL) {
goto Exit;
}
}
memcpy(ConInfo->ipv4info, p_response->ipv4info, sizeof(Ipv4Info));
}
if (p_response->ipv6info != NULL) {
if (ConInfo->ipv6info == NULL) {
ConInfo->ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (ConInfo->ipv6info == NULL) {
goto Exit;
}
}
memcpy(ConInfo->ipv6info, p_response->ipv6info, sizeof(Ipv6Info));
}
cm_record_nwactivity(ConInfo, true);
} else {
ConInfo->connectStatus = CM_CONNECT_DISCON;
ConInfo->dialFailureCode = p_response->status;
ConInfo->retryTime = p_response->suggestedRetryTime;
CM_Log(CM_StartDialer6, "CM_StartDialer: FailureCode is %d, retryTime is %d\n", ConInfo->dialFailureCode,
ConInfo->retryTime);
}
Exit:
CM_Log(CM_StartDialer406, "CM_StartDialer: done\n");
system("echo cm.lock > /sys/power/wake_unlock");
}
void CM_DestroyConnection(DisconnectInfo * p_info)
{
CM_Connection_Context *tmp_CM_Context;
CM_Connection_Context *tmp_next;
CM_Connection_Context *back_context;
int match = 0;
tmp_CM_Context = g_CM_Context;
if (tmp_CM_Context == NULL) {
CM_Log(CM_DestroyConnection1, "CM_DestroyConnection: the link context is null!!!\n");
goto end;
}
pthread_mutex_lock(&cm_mutex);
CM_Log(CM_DestroyConnection11, "CM_DestroyConnection: deleteall %d with cm_mutex locked\n", p_info->deleteall);
if (p_info->deleteall) {
while (tmp_CM_Context) {
tmp_next = tmp_CM_Context->next;
CM_disable_pdplist_touci(tmp_CM_Context);
//in lte mode, don't destroy default primary pdp
if ((NW_status == CM_NW_STATUS_LTE) && (tmp_CM_Context->pdpinfo->connectionNum == 0)) {
CM_Log(CM_DestroyConnection3, "CM_DestroyConnection: default primary pdp connect status %d, autoconnect %d", tmp_CM_Context->connectStatus, tmp_CM_Context->pdpinfo->autoconnect);
if(tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) {
StopDialer(tmp_CM_Context->pdpinfo->primaryCid);
if (!CM_CheckContextValid(tmp_CM_Context))
goto end;
tmp_CM_Context->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(tmp_CM_Context, true);
}
} else {
if (tmp_CM_Context->pdpinfo->PDP_Type == 1)
StopDialer(tmp_CM_Context->pdpinfo->primaryCid);
else
StopDialer(tmp_CM_Context->pdpinfo->secondaryCid);
if (!CM_CheckContextValid(tmp_CM_Context))
goto end;
if(tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS) {
tmp_CM_Context->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(tmp_CM_Context, true);
}
}
CM_Context_free(tmp_CM_Context);
tmp_CM_Context = tmp_next;
}
g_CM_Context = NULL;
} else if (p_info->connectionNum & (SECONDARYPDP_CONNECTNUM_RANGE - 1)) {
//secondary pdp
CM_Log(CM_DestroyConnection4, "CM_DestroyConnection: secondary pdp, connectionNum %d\n", p_info->connectionNum);
tmp_next = tmp_CM_Context->next;
//for the first link context
if (tmp_CM_Context->pdpinfo->connectionNum == p_info->connectionNum) {
CM_disable_pdplist_touci(tmp_CM_Context);
if (tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL){
StopDialer(tmp_CM_Context->pdpinfo->secondaryCid);
if (!CM_CheckContextValid(tmp_CM_Context))
goto end;
tmp_CM_Context->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(tmp_CM_Context, true);
}
CM_Context_free(tmp_CM_Context);
g_CM_Context = tmp_next;
goto end;
}
//find the next link contexts whose connect num is dis_coninfo->ConnectNum, then free
while (tmp_next) {
if (tmp_next->pdpinfo->connectionNum == p_info->connectionNum) {
tmp_CM_Context->next = tmp_next->next;
CM_disable_pdplist_touci(tmp_next);
if (tmp_next->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) {
StopDialer(tmp_next->pdpinfo->secondaryCid);
if (!CM_CheckContextValid(tmp_CM_Context))
goto end;
tmp_next->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(tmp_next, true);
}
CM_Context_free(tmp_next);
goto end;
} else
tmp_CM_Context = tmp_next;
tmp_next = tmp_next->next;
}
} else {
//primary pdp
CM_Log(CM_DestroyConnection5, "Primary pdp, set connectionNum %d, pdp context connectionNum\n", p_info->connectionNum, tmp_CM_Context->pdpinfo->connectionNum);
if ((tmp_CM_Context->pdpinfo->connectionNum & SECONDARYPDP_CONNECTNUM_RANGE) == p_info->connectionNum) {
match = 1;
tmp_next = tmp_CM_Context->next;
CM_disable_pdplist_touci(tmp_CM_Context);
if (tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) {
if (tmp_CM_Context->pdpinfo->PDP_Type == 1)
StopDialer(tmp_CM_Context->pdpinfo->primaryCid);
else
StopDialer(tmp_CM_Context->pdpinfo->secondaryCid);
if (!CM_CheckContextValid(tmp_CM_Context))
goto end;
tmp_CM_Context->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(tmp_CM_Context, true);
}
CM_Context_free(tmp_CM_Context);
g_CM_Context = tmp_next;
tmp_CM_Context = g_CM_Context;
} else
tmp_next = tmp_CM_Context->next;
//find the next link contexts whose primary CID is dis_coninfo->CID, then free
while (tmp_next) {
if ((tmp_next->pdpinfo->connectionNum & SECONDARYPDP_CONNECTNUM_RANGE) == p_info->connectionNum) {
match = 1;
CM_disable_pdplist_touci(tmp_next);
//tmp_CM_Context is not the first link context
if (tmp_CM_Context != tmp_next)
tmp_CM_Context->next = tmp_next->next;
if (tmp_next->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) {
if (tmp_CM_Context->pdpinfo->PDP_Type == 1)
StopDialer(tmp_CM_Context->pdpinfo->primaryCid);
else
StopDialer(tmp_CM_Context->pdpinfo->secondaryCid);
if (!CM_CheckContextValid(tmp_CM_Context))
goto end;
tmp_CM_Context->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(tmp_CM_Context, true);
}
back_context = tmp_next;
//modify by qgwang, 20140304, memory leak checked by klocwork
//the current link is the firtst link, and delete the first link
if (tmp_CM_Context == tmp_next) {
tmp_CM_Context = tmp_next->next;
}
tmp_next = tmp_next->next;
CM_Context_free(back_context);
} else {
tmp_CM_Context = tmp_next;
tmp_next = tmp_next->next;
}
}
}
end:
pthread_mutex_unlock(&cm_mutex);
CM_Log(CM_DestroyConnection6, "CM_DestroyConnection: cm_mutex unlocked, %s\n", match ? "find match ctx to destroy done" : "done with out ctx match");
}
Link_Context *CM_GetLinkContext(void)
{
CM_Connection_Context *tmp_CM_Context;
//the head of link context
Link_Context *h_linkcontext;
Link_Context *p_linkcontext;
tmp_CM_Context = g_CM_Context;
//try to find the match connection_num
if (tmp_CM_Context == NULL)
{
return NULL;
}
p_linkcontext = (Link_Context *) malloc(sizeof(Link_Context));
if (!p_linkcontext) {
return NULL;
}
memset(p_linkcontext, 0, sizeof(Link_Context));
h_linkcontext = p_linkcontext;
p_linkcontext->connectionNum = tmp_CM_Context->pdpinfo->connectionNum;
if (tmp_CM_Context->connectStatus == 3)
p_linkcontext->connectStatus = 2;
else
p_linkcontext->connectStatus = tmp_CM_Context->connectStatus;
p_linkcontext->create_by = tmp_CM_Context->create_by;
CM_Log(CM_GetLinkContext1, "CM_GetLinkContext, connect status:%d, pdp type:%d, create_by %d(1: CM 0: WebUI)\n", tmp_CM_Context->connectStatus,
tmp_CM_Context->pdpinfo->PDP_Type, tmp_CM_Context->create_by);
memcpy(&(p_linkcontext->pdpinfo), tmp_CM_Context->pdpinfo, sizeof(p_linkcontext->pdpinfo));
if (p_linkcontext->connectStatus == 1) {
if (tmp_CM_Context->ipv4info != NULL)
memcpy(&(p_linkcontext->ipv4info), tmp_CM_Context->ipv4info, sizeof(p_linkcontext->ipv4info));
if (tmp_CM_Context->ipv6info != NULL)
memcpy(&(p_linkcontext->ipv6info), tmp_CM_Context->ipv6info, sizeof(p_linkcontext->ipv6info));
}
tmp_CM_Context = tmp_CM_Context->next;
while (tmp_CM_Context) {
p_linkcontext->next = malloc(sizeof(Link_Context));
if (!p_linkcontext->next) {
return h_linkcontext;
}
p_linkcontext = p_linkcontext->next;
memset(p_linkcontext, 0, sizeof(Link_Context));
p_linkcontext->connectionNum = tmp_CM_Context->pdpinfo->connectionNum;
if (tmp_CM_Context->connectStatus == 3)
p_linkcontext->connectStatus = 2;
else
p_linkcontext->connectStatus = tmp_CM_Context->connectStatus;
memcpy(&(p_linkcontext->pdpinfo), tmp_CM_Context->pdpinfo, sizeof(p_linkcontext->pdpinfo));
if (p_linkcontext->connectStatus == 1) {
if (tmp_CM_Context->ipv4info != NULL)
memcpy(&(p_linkcontext->ipv4info), tmp_CM_Context->ipv4info,
sizeof(p_linkcontext->ipv4info));
if (tmp_CM_Context->ipv6info != NULL)
memcpy(&(p_linkcontext->ipv6info), tmp_CM_Context->ipv6info,
sizeof(p_linkcontext->ipv6info));
}
tmp_CM_Context = tmp_CM_Context->next;
}
return h_linkcontext;
}
Apn_Info *get_inital_attach_apn(Mnc_Apn * apn_list, char *cur_apn)
{
if (apn_list == NULL)
return NULL;
Apn_Info *apninfo;
int index;
if (cur_apn == NULL) {
for (index = 0; index < MAX_APN_NUM; index++) {
apninfo = &(apn_list->apn_info_list[index]);
/*check enable option first*/
if (apninfo->enable == 0)
continue;
if (strlen(apninfo->type) == 0)
continue;
if (apninfo->Extra_params.lte_default == 1)
return apninfo;
}
} else {
for (index = 0; index < MAX_APN_NUM; index++) {
apninfo = &(apn_list->apn_info_list[index]);
/*check enable option first*/
if (apninfo->enable == 0)
continue;
if (strlen(apninfo->type) == 0)
continue;
if(strlen(apninfo->apn) == 0 && strlen(apninfo->lte_apn) == 0)
continue;
if(strlen(apninfo->lte_apn) == 0)
strcpy(apninfo->lte_apn, apninfo->apn);
if (apninfo->Extra_params.lte_default == 1 && strcmp(apninfo->lte_apn, cur_apn) != 0)
return apninfo;
}
if (index == MAX_APN_NUM || strlen(apninfo->type) == 0) {
apn_list->all_try_fail = 1;
CM_Log(get_inital_attach_apn, "leave get_inital_attach_apn, all try failed\n");
return NULL;
}
}
return NULL;
}
Apn_Info *get_default_apninfo(Mnc_Apn * apn_list, char *cur_apn)
{
if (apn_list == NULL)
return NULL;
Apn_Info *apninfo;
int index;
if (cur_apn == NULL) {
for (index = 0; index < MAX_APN_NUM; index++) {
apninfo = &(apn_list->apn_info_list[index]);
/*check enable option first*/
if (apninfo->enable == 0)
continue;
if (strlen(apninfo->type) == 0)
continue;
//match the "default" type
if (strcmp(apninfo->type, "default") == 0)
return apninfo;
}
} else {
for (index = 0; index < MAX_APN_NUM; index++) {
apninfo = &(apn_list->apn_info_list[index]);
/*check enable option first*/
if (apninfo->enable == 0)
continue;
if (strlen(apninfo->type) == 0)
continue;
//match the "default" type
if(strlen(apninfo->apn) == 0)
continue;
if (strcmp(apninfo->type, "default") == 0 && strcmp(apninfo->apn, cur_apn) != 0)
return apninfo;
}
if (index == MAX_APN_NUM || strlen(apninfo->type) == 0) {
apn_list->all_try_fail = 1;
CM_Log(get_default_apninfo, "leave get_default_apninfo, all try failed \n");
return NULL;
}
}
return NULL;
}
Apn_Info *get_apninfo_from_LteAPN(Mnc_Apn * apn_list, char *LteAPN)
{
if (apn_list == NULL || LteAPN == NULL)
return NULL;
Apn_Info *apninfo;
int index;
for (index = 0; index < MAX_APN_NUM; index++) {
apninfo = &(apn_list->apn_info_list[index]);
/*check enable option first*/
if (apninfo->enable == 0)
continue;
if (strlen(apninfo->type) == 0)
continue;
//match the "default" type
if (strcmp(apninfo->type, "default") == 0 && strcmp(apninfo->apn, LteAPN) == 0)
{
CM_Log(get_apninfo_from_LteAPN, " get_apninfo_from_LteAPN: apnInfp %p for lteApn [%s]\n", apninfo, strlen(LteAPN) ? LteAPN : "NULL");
return apninfo;
}
}
return NULL;
}
Apn_Info *get_fota_apninfo(Mnc_Apn * apn_list)
{
if (apn_list == NULL)
return NULL;
Apn_Info *apninfo;
int index;
for (index = 0; index < MAX_APN_NUM; index++) {
apninfo = &(apn_list->apn_info_list[index]);
/*check enable option first*/
if (apninfo->enable == 0)
continue;
if (strlen(apninfo->type) == 0)
continue;
//match the "default" type
if (strcmp(apninfo->type, "fota") == 0)
return apninfo;
}
return NULL;
}
CM_Connection_Context *get_match_pdp(Apn_Info * apninfo)
{
if (apninfo == NULL)
return NULL;
CM_Connection_Context *tmp_Context;
if (g_CM_Context == NULL)
return NULL;
tmp_Context = g_CM_Context;
while (tmp_Context) {
if(tmp_Context->pdpinfo->connectionNum == apninfo->connection_num)
return tmp_Context;
tmp_Context = tmp_Context->next;
}
return NULL;
}
CM_Connection_Context *create_new_pdp_ctx(Apn_Info * apnInfo)
{
CM_Connection_Context *tmp_Context;
Apn_Info *default_apn = NULL;
Apn_Info *apninfo = apnInfo;
//the first pdp context
if (g_CM_Context == NULL) {
CM_Log(create_new_pdp_ctx, "create_new_pdp_ctx: create the first pdp context\n");
tmp_Context = (CM_Connection_Context *) malloc(sizeof(CM_Connection_Context));
if (!tmp_Context) {
return NULL;
}
memset(tmp_Context, 0, sizeof(CM_Connection_Context));
g_CM_Context = tmp_Context;
}
else {
tmp_Context = g_CM_Context;
while (tmp_Context->next) {
tmp_Context = tmp_Context->next;
}
CM_Log(create_new_pdp_ctx4, "create_new_pdp_ctx: create a new pdp context\n");
tmp_Context->next = (CM_Connection_Context *) malloc(sizeof(CM_Connection_Context));
if (!tmp_Context->next) {
CM_Log_E(create_new_pdp_ctx5, "create_new_pdp_ctx: malloc size %d failed\n", sizeof(CM_Connection_Context));
return NULL;
}
tmp_Context = tmp_Context->next;
memset(tmp_Context, 0, sizeof(CM_Connection_Context));
}
tmp_Context->connectStatus = CM_CONNECT_DISCON;
tmp_Context->first_dial = 1;
tmp_Context->retryTime = -1;
tmp_Context->pdpinfo = (PdpInfo *) malloc(sizeof(PdpInfo));
if (!tmp_Context->pdpinfo) {
return NULL;
}
memset(tmp_Context->pdpinfo, 0, sizeof(PdpInfo));
tmp_Context->pdpinfo->connectionNum = apninfo->connection_num;
tmp_Context->pdpinfo->primaryCid = apninfo->cid;
tmp_Context->pdpinfo->PDP_Type = 1;
if (apninfo->cid == CM_DEFAULT_ATTACH_CID && apninfo->auto_apn)
{
default_apn = get_default_apninfo(g_work_apn, NULL);
if (default_apn && default_apn->auto_apn)
{
apninfo = default_apn;
CM_Log(create_new_pdp_ctx827, "%s: get default apn for default attach cid with auto apn ", __func__);
}
}
if (strlen(apninfo->apn) != 0)
strcpy(tmp_Context->pdpinfo->APN, apninfo->apn);
else if (strlen(apninfo->lte_apn) != 0)
strcpy(tmp_Context->pdpinfo->APN, apninfo->lte_apn);
if (strlen(apninfo->lte_apn) != 0)
strcpy(tmp_Context->pdpinfo->LteAPN, apninfo->lte_apn);
else if (strlen(apninfo->apn) != 0)
strcpy(tmp_Context->pdpinfo->LteAPN, apninfo->apn);
tmp_Context->pdpinfo->IP_Type = apninfo->iptype;
tmp_Context->pdpinfo->IP_Type_back = apninfo->iptype;
tmp_Context->pdpinfo->autoapn = apninfo->auto_apn;
tmp_Context->pdpinfo->autoconnect = apninfo->Extra_params.autoconnect;
tmp_Context->pdpinfo->data_on_roaming = apninfo->Extra_params.data_on_roaming;
tmp_Context->pdpinfo->is_default = apninfo->Extra_params.lte_default;
tmp_Context->pdpinfo->mtu = apninfo->mtu;
tmp_Context->pdpinfo->data_block = apninfo->data_block;
strncpy(tmp_Context->pdpinfo->PDP_name, apninfo->pdp_name, sizeof(tmp_Context->pdpinfo->PDP_name) - 1);
CM_Log(create_new_pdp_ctx3, "create_new_pdp_ctx: ctx [0x%x], auto_apn %d, autoconnect %d, data_on_roaming %d, mtu %d, cid %d, is_default %d, data_block %d, ip_type %d \n", tmp_Context, apninfo->auto_apn,
apninfo->Extra_params.autoconnect, apninfo->Extra_params.data_on_roaming, apninfo->mtu, apninfo->cid, apninfo->Extra_params.lte_default, apninfo->data_block, apninfo->iptype);
if (strlen(apninfo->authtype) != 0)
strcpy(tmp_Context->pdpinfo->Authtype2G3G, apninfo->authtype);
else
strcpy(tmp_Context->pdpinfo->Authtype2G3G, "NONE");
if (strlen(apninfo->usrname) != 0)
strcpy(tmp_Context->pdpinfo->Usr2G3G, apninfo->usrname);
else
strcpy(tmp_Context->pdpinfo->Usr2G3G, "any");
if (strlen(apninfo->paswd) != 0)
strcpy(tmp_Context->pdpinfo->PASWD2G3G, apninfo->paswd);
else
strcpy(tmp_Context->pdpinfo->PASWD2G3G, "any");
if (strlen(apninfo->lte_authtype) != 0)
strcpy(tmp_Context->pdpinfo->Authtype4G, apninfo->lte_authtype);
else
strcpy(tmp_Context->pdpinfo->Authtype4G, "NONE");
if (strlen(apninfo->lte_usrname) != 0)
strcpy(tmp_Context->pdpinfo->Usr4G, apninfo->lte_usrname);
else
strcpy(tmp_Context->pdpinfo->Usr4G, "any");
if (strlen(apninfo->lte_paswd) != 0)
strcpy(tmp_Context->pdpinfo->PASWD4G, apninfo->lte_paswd);
else
strcpy(tmp_Context->pdpinfo->PASWD4G, "any");
if(strlen(apninfo->mmsc) != 0)
strcpy(tmp_Context->pdpinfo->mmsc, apninfo->mmsc);
if(strlen(apninfo->mmsproxy) != 0)
strcpy(tmp_Context->pdpinfo->mmsc, apninfo->mmsproxy);
if(strlen(apninfo->mmsport) != 0)
strcpy(tmp_Context->pdpinfo->mmsc, apninfo->mmsport);
if (apninfo->netif[0] != '\0')
strcpy(tmp_Context->pdpinfo->netif, apninfo->netif);
#ifdef CONFIG_CM_URSP
tmp_Context->pdpinfo->rsd_index = -1;
memcpy(&(tmp_Context->pdpinfo->config_rsd), &(apninfo->config_rsd), sizeof(tmp_Context->pdpinfo->config_rsd));
#endif
return tmp_Context;
}
void ClearETIFlag_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
UNUSED(msg);
CM_Log(ClearETIFlag_data_cb, "enter ClearETIFlag_data_cb");
}
static void complete_clear_eitf_async_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req) {
free(req);
}
CM_Log(complete_clear_eitf_async_cb, "complete_clear_eitf_async_cb(%d)\n", ret);
}
int CM_Clear_ETIFlag(int sync)
{
struct ubus_request *req = NULL;
int ret_val;
CM_Log(CM_Clear_ETIFlag, "CM_Clear_ETIFlag sync mode %d", sync);
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_CLEAR_ETIFLAG, NULL, 0);
if (sync) {
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, ClearETIFlag_data_cb, 0,
0)) != UBUS_STATUS_OK) {
goto end;
}
} else {
req = malloc(sizeof(struct ubus_request));
if (!req) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto end;
}
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
free(req);
goto end;
} else {
req->complete_cb = complete_clear_eitf_async_cb;
ubus_complete_request_async(cm_ctx, req);
}
}
end:
CM_Log(CM_Clear_ETIFlag2, "CM_Clear_ETIFlag done with ret %d", ret_val);
return ret_val;
}
// Workaround: Some NW returns .mcc<MCC>.mnc<MNC>
static int isValidOI(const char *oi)
{
int ret = 0;
if (oi != NULL) {
int i;
int len = strlen(oi);
char * new_oi = (char *)malloc(len + 1);
if (new_oi != NULL) {
for (i = 0; i < len; i++)
new_oi[i] = tolower(oi[i]);
new_oi[len] = 0;
regex_t re;
int regerr = regcomp(&re, ".(mnc[0-9]+.mcc[0-9]+|mcc[0-9]+.mnc[0-9]+).(gprs|(pub.|ipxuni.)?3gppnetwork.org)", REG_EXTENDED);
if (regerr == 0) {
ret = 0 == regexec(&re, new_oi, 0, NULL, 0);
}
regfree(&re);
free(new_oi);
}
}
if (!ret)
{
CM_Log(isValidOI, "'%s' is not a valid Operator Identifier", oi);
}
return ret;
}
/**
* TS 23.003 section 9 definition of Access Point Name
* The APN is composed of two parts Network Identifier + Operator Identifier
* The APN Operator Identifier is composed of three labels. the last labet shall be "gprs".
*/
int matchApnNetworkIdentifier(const char *eps_apn, const char *apn)
{
bool eps_apn_null = false, apn_null= false;
if ((eps_apn && strlen(eps_apn) == 0) || eps_apn == NULL)
eps_apn_null = true;
if ((apn && strlen(apn) == 0) || apn == NULL)
apn_null = true;
if (eps_apn_null && apn_null)
return 1;
else if (eps_apn_null)
return 0;
else if (apn_null)
return 0;
if (eps_apn == NULL ||apn == NULL)
return 0;
size_t len = (strlen(apn) > strlen(eps_apn)) ? strlen(eps_apn) : strlen(apn);
CM_Log(matchApnNetworkIdentifier, "enter matchApnNetworkIdentifier, eps_apn %s: current apn:%s, len %d", eps_apn, apn, len);
if (len > 0)
{
if (strncasecmp(eps_apn, apn, len) == 0) {
const char *oi = eps_apn + len;
return *oi == '\0' || isValidOI(oi);
}
else if (strncasecmp(eps_apn, "3gnet", len) == 0) {
if (strncasecmp(apn, "wonet", len) == 0)
return 1;
}
else if (strncasecmp(eps_apn, "wonet", len) == 0) {
if (strncasecmp(apn, "3gnet", len) == 0)
return 1;
}
}
return 0;
}
CM_Connection_Context *cm_get_partner_ctx(int cid)
{
CM_Connection_Context *ctx = g_CM_Context;
if (cid <= 0)
return NULL;
while (ctx)
{
if (ctx->pdpinfo && ctx->pdpinfo->parent_cid == cid)
{
if (ctx->pdpinfo->primaryCid != cid)
{
CM_Log(cm_get_partner_ctx, "cm_get_partner_ctx: cid %d, parent cid %d\n", ctx->pdpinfo->primaryCid, ctx->pdpinfo->parent_cid);
break;
}
}
ctx = ctx->next;
}
return ctx;
}
extern unsigned char UnknownPdpCause;
//if need to redial, return TRUE; otherwise, return FALSE
bool check_merger_pdpcontext(Apn_Info * apninfo, CM_Connection_Context * coninfo, int apn_info_flag)
{
bool ret;
ret = FALSE;
int roam_iptype = 0;
bool skip_merge = false;
if (apninfo->cid == CM_DEFAULT_ATTACH_CID && apn_info_flag == PDP_CONFIG_ZGDCONT)
{
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (is_pdp_auto_apn(g_work_apn, apninfo->type))
skip_merge = true;
#endif
}
if (skip_merge) {
CM_Log(check_merger_pdpcontext1080, "check_merger_pdpcontext, skip merge for cid [%d] in auto apn mode", apninfo->cid);
return ret;
}
if (coninfo->create_by == 1) {
CM_Log(check_merger_pdpcontext, "check_merger_pdpcontext, the context created by CM self");
}
roam_iptype = cm_get_zroam_iptype();
if (roam_iptype > 0)
{
if (roam_iptype == 3)
roam_iptype = 0;
if (roam_iptype != coninfo->pdpinfo->IP_Type) {
if (get_ipv4_only_allowed() && coninfo->pdpinfo->IP_Type == IPV4
&& (roam_iptype == IPV4 || roam_iptype == IPV4V6))
{
CM_Log(check_merger_pdpcontext1050, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv4_only_allowed, consider same", coninfo->pdpinfo->IP_Type, roam_iptype);
}
else if (get_ipv6_only_allowed() && coninfo->pdpinfo->IP_Type == IPV6
&& (roam_iptype == IPV6 || roam_iptype == IPV4V6))
{
CM_Log(check_merger_pdpcontext1064, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv6_only_allowed, consider same", coninfo->pdpinfo->IP_Type, roam_iptype);
}
else
{
CM_Log(check_merger_pdpcontext999, "check_merger_pdpcontext, IP type changed, %d->%d", coninfo->pdpinfo->IP_Type, roam_iptype);
coninfo->pdpinfo->IP_Type = roam_iptype;
ret = TRUE;
}
}
}
else
{
if (apninfo->iptype != coninfo->pdpinfo->IP_Type) {
if (get_ipv4_only_allowed() && coninfo->pdpinfo->IP_Type == IPV4
&& (apninfo->iptype == IPV4 || apninfo->iptype == IPV4V6))
{
CM_Log(check_merger_pdpcontext1060, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv4_only_allowed, consider same", coninfo->pdpinfo->IP_Type, apninfo->iptype);
}
else if (get_ipv6_only_allowed() && coninfo->pdpinfo->IP_Type == IPV6
&& (apninfo->iptype == IPV6 || apninfo->iptype == IPV4V6))
{
CM_Log(check_merger_pdpcontext1064, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv6_only_allowed, consider same", coninfo->pdpinfo->IP_Type, apninfo->iptype);
}
else
{
if (UnknownPdpCause == 52)
{
if (apninfo->iptype == IPV4V6)
{
if (coninfo->pdpinfo->IP_Type != IPV4V6)
{
CM_Connection_Context *parnter_ctx = NULL;
parnter_ctx = cm_get_partner_ctx(coninfo->pdpinfo->primaryCid);
if (parnter_ctx && parnter_ctx->pdpinfo && parnter_ctx->pdpinfo->IP_Type != coninfo->pdpinfo->IP_Type)
{
CM_Log(check_merger_pdpcontext1202, "check_merger_pdpcontext, UnknownPdpCause 52, iptype exist %d, %d -> %d",
coninfo->pdpinfo->IP_Type, parnter_ctx->pdpinfo->IP_Type, apninfo->iptype);
}
else
{
CM_Log(check_merger_pdpcontext1207, "check_merger_pdpcontext, UnknownPdpCause 52, %d->%d", coninfo->pdpinfo->IP_Type, apninfo->iptype);
coninfo->pdpinfo->IP_Type = apninfo->iptype;
ret = TRUE;
}
}
}
if (apninfo->iptype != IPV4V6 && coninfo->pdpinfo->IP_Type != IPV4V6)
{
CM_Log(check_merger_pdpcontext1216, "check_merger_pdpcontext, UnknownPdpCause 52, %d->%d", coninfo->pdpinfo->IP_Type, apninfo->iptype);
coninfo->pdpinfo->IP_Type = apninfo->iptype;
ret = TRUE;
}
}
else
{
CM_Log(check_merger_pdpcontext1, "check_merger_pdpcontext, IP type changed, %d->%d", coninfo->pdpinfo->IP_Type, apninfo->iptype);
coninfo->pdpinfo->IP_Type = apninfo->iptype;
ret = TRUE;
}
}
}
}
coninfo->pdpinfo->IP_Type_back = apninfo->iptype;
if(matchApnNetworkIdentifier( coninfo->pdpinfo->APN, apninfo->apn) == 0) {
CM_Log(check_merger_pdpcontext2, "check_merger_pdpcontext, APN changed, %s->%s",coninfo->pdpinfo->APN, apninfo->apn);
strcpy(coninfo->pdpinfo->APN, apninfo->apn);
ret = TRUE;
}
if((strlen(apninfo->lte_apn) != 0) ||(strlen(coninfo->pdpinfo->LteAPN) != 0)) {
if(matchApnNetworkIdentifier(coninfo->pdpinfo->LteAPN, apninfo->lte_apn) == 0) {
CM_Log(check_merger_pdpcontext3, "check_merger_pdpcontext, LTE APN changed, %s->%s",coninfo->pdpinfo->LteAPN, apninfo->lte_apn);
strcpy(coninfo->pdpinfo->LteAPN, apninfo->lte_apn);
ret = TRUE;
}
strcpy(coninfo->pdpinfo->LteAPN, apninfo->lte_apn);
}
if (coninfo->pdpinfo->autoconnect == CM_CONTYPE_MANUAL && apninfo->Extra_params.autoconnect == CM_CONTYPE_AUTO) {
CM_Log(check_merger_pdpcontext4, "check_merger_pdpcontext, autoconnect changed, manual->auto");
coninfo->pdpinfo->autoconnect = CM_CONTYPE_AUTO;
//ret = TRUE;
} else if (coninfo->pdpinfo->autoconnect == CM_CONTYPE_AUTO && apninfo->Extra_params.autoconnect == CM_CONTYPE_MANUAL) {
CM_Log(check_merger_pdpcontext5, "check_merger_pdpcontext, autoconnect changed, auto->manual");
coninfo->pdpinfo->autoconnect = CM_CONTYPE_MANUAL;
//ret = TRUE;
}
if (coninfo->pdpinfo->data_on_roaming == 0 && apninfo->Extra_params.data_on_roaming == 1) {
CM_Log(check_merger_pdpcontext6, "check_merger_pdpcontext, data_on_roaming changed, 0->1");
coninfo->pdpinfo->data_on_roaming = 1;
//ret = TRUE;
} else if (coninfo->pdpinfo->data_on_roaming == 1 && apninfo->Extra_params.data_on_roaming == 0) {
CM_Log(check_merger_pdpcontext7, "check_merger_pdpcontext, data_on_roaming changed, 1->0");
coninfo->pdpinfo->data_on_roaming = 0;
//ret = TRUE;
}
if (coninfo->pdpinfo->always_on == 0 && apninfo->Extra_params.always_on == 1) {
CM_Log(check_merger_pdpcontext1145, "check_merger_pdpcontext, always_on(data_on_boot) changed, 0->1");
coninfo->pdpinfo->always_on = 1;
//ret = TRUE;
} else if (coninfo->pdpinfo->always_on == 1 && apninfo->Extra_params.always_on == 0) {
CM_Log(check_merger_pdpcontext1149, "check_merger_pdpcontext, always_on(data_on_boot) changed, 1->0");
coninfo->pdpinfo->always_on = 0;
//ret = TRUE;
}
#ifndef CONFIG_ZGDCONT_MULTI_PDP
if (apninfo->cid && coninfo->pdpinfo->primaryCid != apninfo->cid) {
CM_Log(check_merger_pdpcontext8, "check_merger_pdpcontext, cid changed, %d->%d", coninfo->pdpinfo->primaryCid, apninfo->cid);
ret = TRUE;
}
#endif
if ((strlen(apninfo->authtype) && strlen(coninfo->pdpinfo->Authtype2G3G) && strcasecmp (apninfo->authtype, coninfo->pdpinfo->Authtype2G3G)) ||
(strlen(apninfo->usrname) && strlen(coninfo->pdpinfo->Usr2G3G) && strcasecmp (apninfo->usrname, coninfo->pdpinfo->Usr2G3G)) ||
(strlen(apninfo->paswd) && strlen(coninfo->pdpinfo->PASWD2G3G) && strcasecmp (apninfo->paswd, coninfo->pdpinfo->PASWD2G3G)))
{
CM_Log(check_merger_pdpcontext9, "check_merger_pdpcontext, 23G auth changed, type %s->%s, user %s->%s, password %s->%s",
strlen(coninfo->pdpinfo->Authtype2G3G)? coninfo->pdpinfo->Authtype2G3G: "NULL", strlen(apninfo->authtype)?apninfo->authtype:"NULL",
strlen(coninfo->pdpinfo->Usr2G3G)? coninfo->pdpinfo->Usr2G3G: "NULL", strlen(apninfo->usrname)?apninfo->usrname:"NULL",
strlen(coninfo->pdpinfo->PASWD2G3G)? coninfo->pdpinfo->PASWD2G3G: "NULL", strlen(apninfo->paswd)?apninfo->paswd:"NULL" );
strncpy(coninfo->pdpinfo->Authtype2G3G, apninfo->authtype, sizeof(coninfo->pdpinfo->Authtype2G3G) - 1);
strncpy(coninfo->pdpinfo->Usr2G3G, apninfo->usrname, sizeof(coninfo->pdpinfo->Usr2G3G) - 1);
strncpy(coninfo->pdpinfo->PASWD2G3G, apninfo->paswd, sizeof(coninfo->pdpinfo->PASWD2G3G) - 1);
// ret = TRUE;
}
else if ((strlen(apninfo->authtype) == 0 ||strcasecmp (apninfo->authtype, "NONE")) &&
strlen(coninfo->pdpinfo->Authtype2G3G) && strcasecmp (coninfo->pdpinfo->Authtype2G3G, "NONE"))
{
CM_Log(check_merger_pdpcontext1200, "check_merger_pdpcontext, Authtype2G3G changed, %s->NONE", coninfo->pdpinfo->Authtype2G3G);
strcpy(coninfo->pdpinfo->Authtype2G3G, "NONE");
//ret = TRUE;
}
else if ((strlen(apninfo->usrname) == 0 ||strcasecmp (apninfo->usrname, "any")) &&
strlen(coninfo->pdpinfo->Usr2G3G) && strcasecmp (coninfo->pdpinfo->Usr2G3G, "any"))
{
strcpy(coninfo->pdpinfo->Authtype2G3G, "any");
// ret = TRUE;
}
else if ((strlen(apninfo->paswd) == 0 || strcasecmp (apninfo->paswd, "any")) &&
strlen(coninfo->pdpinfo->PASWD2G3G) && strcasecmp (coninfo->pdpinfo->PASWD2G3G, "any"))
{
strcpy(coninfo->pdpinfo->PASWD2G3G, "any");
// ret = TRUE;
}
if ((strlen(apninfo->lte_authtype) && strcasecmp (apninfo->lte_authtype, coninfo->pdpinfo->Authtype4G) ) ||
(strlen(apninfo->lte_usrname) && strcasecmp (apninfo->lte_usrname, coninfo->pdpinfo->Usr4G)) ||
(strlen(apninfo->lte_paswd) && strcasecmp (apninfo->lte_paswd, coninfo->pdpinfo->PASWD4G)))
{
CM_Log(check_merger_pdpcontext9, "check_merger_pdpcontext, 4G auth changed, type %s->%s, user %s->%s, password %s->%s",
strlen(coninfo->pdpinfo->Authtype4G)? coninfo->pdpinfo->Authtype4G: "NULL", strlen(apninfo->lte_authtype)?apninfo->lte_authtype:"NULL",
strlen(coninfo->pdpinfo->Usr4G)? coninfo->pdpinfo->Usr4G: "NULL", strlen(apninfo->lte_usrname)?apninfo->lte_usrname:"NULL",
strlen(coninfo->pdpinfo->PASWD4G)? coninfo->pdpinfo->PASWD4G: "NULL", strlen(apninfo->lte_paswd)?apninfo->lte_paswd:"NULL" );
strncpy(coninfo->pdpinfo->Authtype4G, apninfo->lte_authtype, sizeof(coninfo->pdpinfo->Authtype4G) - 1);
strncpy(coninfo->pdpinfo->Usr4G, apninfo->lte_usrname, sizeof(coninfo->pdpinfo->Usr4G) - 1);
strncpy(coninfo->pdpinfo->PASWD4G, apninfo->lte_paswd, sizeof(coninfo->pdpinfo->PASWD4G) - 1);
// ret = TRUE;
}
else if ((strlen(apninfo->lte_authtype) == 0 ||strcasecmp (apninfo->lte_authtype, "NONE")) &&
strlen(coninfo->pdpinfo->Authtype4G) && strcasecmp (coninfo->pdpinfo->Authtype4G, "NONE"))
{
CM_Log(check_merger_pdpcontext1235, "check_merger_pdpcontext, Authtype4G changed, %s->NONE", coninfo->pdpinfo->Authtype2G3G);
strcpy(coninfo->pdpinfo->Authtype4G, "NONE");
// ret = TRUE;
}
else if ((strlen(apninfo->lte_usrname) == 0 ||strcasecmp (apninfo->lte_usrname, "any")) &&
strlen(coninfo->pdpinfo->Usr4G) && strcasecmp (coninfo->pdpinfo->Usr4G, "any"))
{
strcpy(coninfo->pdpinfo->Usr4G, "any");
//ret = TRUE;
}
else if ((strlen(apninfo->lte_paswd) == 0 ||strcasecmp (apninfo->lte_paswd, "any")) &&
strlen(coninfo->pdpinfo->PASWD4G) && strcasecmp (coninfo->pdpinfo->PASWD4G, "any"))
{
strcpy(coninfo->pdpinfo->PASWD4G, "any");
// ret = TRUE;
}
memcpy(coninfo->pdpinfo->netif, apninfo->netif, MAX_STR_LEN);
#ifdef CONFIG_CM_URSP
if (memcmp(&(coninfo->pdpinfo->config_rsd), &(apninfo->config_rsd), sizeof(coninfo->pdpinfo->config_rsd)) )
{
memcpy(&(coninfo->pdpinfo->config_rsd), &(apninfo->config_rsd), sizeof(coninfo->pdpinfo->config_rsd));
ret = TRUE;
}
#endif
CM_Log(check_merger_pdpcontext1282, "check_merger_pdpcontext, ret %d", ret);
return ret;
}
//return TRUE, need to sleep and redial
//return FALSE, don't need to sleep and redial
bool redial_sleep(int count)
{
int sleep_interval = 0;
if (!g_redial_interval)
return FALSE;
if (count >= g_redial_interval->total_retry_times)
{
CM_Log(redial_sleep1, "redial_sleep: redial count %d reach max %d", count, g_redial_interval->total_retry_times);
return FALSE;
}
if (count < g_redial_interval->repeat0_times)
sleep_interval = g_redial_interval->interval0;
else if (count < (g_redial_interval->repeat1_times + g_redial_interval->repeat0_times))
sleep_interval = g_redial_interval->interval1;
else if (count <
(g_redial_interval->repeat2_times + g_redial_interval->repeat1_times +
g_redial_interval->repeat0_times))
sleep_interval = g_redial_interval->interval2;
else
sleep_interval = g_redial_interval->interval3;
if (sleep_interval > 0)
{
CM_Log(redial_sleep2, "redial_sleep: will sleep %d seconds", sleep_interval);
sleep(sleep_interval);
}
return TRUE;
}
/***********************************************************************
package name redial_interval
config operation_type CMCC
option connection_num 0
option mcc
option mnc
option interval0 5
option repeat0_times 20
option interval1 0
option repeat1_times 0
option interval2 0
option repeat2_times 0
option interval3 0
option repeat3_times 0
option total_retry_times 20
************************************************************************/
int CM_update_redialinterval(char *imsi)
{
struct uci_context *local_ctx = NULL;
struct uci_package *p = NULL;
struct uci_section *s = NULL;
struct uci_element *e = NULL;
char *mcc_str = NULL;
char *mnc_str = NULL;
char *str = NULL;
int mnc_len = 2;
//get interval from uci according to the g_work_apn.mcc
//default value
if (g_redial_interval == NULL)
g_redial_interval = malloc(sizeof(redial_interval));
if (g_redial_interval == NULL) {
CM_Log(CM_update_redialinterval, "CM_update_redialinterval, malloc failed here");
return CM_ERR_MEM;
}
memset(g_redial_interval, 0, sizeof(redial_interval));
if (imsi == NULL) {
CM_Log(CM_update_redialinterval1, "CM_update_redialinterval, imsi is NULL");
goto end;
}
//find match redial interval from uci file
/*load /etc/config/wan */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(CM_update_redialinterval3, "CM_update_redialinterval: FATAL ERROR!\n");
goto end;
}
memcpy(g_redial_interval->mcc, imsi, 3);
change_mnc:
memcpy(g_redial_interval->mnc, imsi + 3, mnc_len);
CM_Log(CM_update_redialinterval2, "CM_update_redialinterval, mcc:%s,mnc:%s", g_redial_interval->mcc, g_redial_interval->mnc);
p = get_uci_package(local_ctx, REDIAL_INTERVAL_PACKAGE, false);
if (!p) {
CM_Log_E(CM_update_redialinterval4, "CM_update_redialinterval: get package failed \n");
goto end;
}
uci_foreach_element(&p->sections, e) {
s = uci_to_section(e);
if (strcmp(s->type, OPERATION_TYPE_STR)) {
continue;
}
mcc_str = (char *)uci_lookup_option_string(local_ctx, s, MCC_TYPE_STR);
mnc_str = (char *)uci_lookup_option_string(local_ctx, s, MNC_TYPE_STR);
if(mcc_str == NULL || mnc_str == NULL)
goto end;
CM_Log(CM_update_redialinterval5, "mcc:%s, mnc:%s", mcc_str, mnc_str);
if((strcmp(mcc_str, g_redial_interval->mcc) == 0) &&(strcmp(mnc_str, g_redial_interval->mnc) == 0)) {
str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL0_STR);
if(str != NULL)
g_redial_interval->interval0 = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR);
if(str != NULL)
g_redial_interval->repeat0_times = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL1_STR);
if(str != NULL)
g_redial_interval->interval1 = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR);
if(str != NULL)
g_redial_interval->repeat1_times = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL2_STR);
if(str != NULL)
g_redial_interval->interval2 = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR);
if(str != NULL)
g_redial_interval->repeat2_times = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL3_STR);
if(str != NULL)
g_redial_interval->interval3 = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR);
if(str != NULL)
g_redial_interval->repeat3_times = atoi(str);
str = (char *)uci_lookup_option_string(local_ctx, s, TOTAL_RETRY_TIMES_STR);
if(str != NULL)
g_redial_interval->total_retry_times = atoi(str);
CM_Log(CM_update_redialinterval6, "total retry times:%d", g_redial_interval->total_retry_times);
return CM_OK;
}
}
if (mnc_len == 2)
{
mnc_len = 3;
goto change_mnc;
}
end:
//the unit is second
g_redial_interval->interval0 = 5;
g_redial_interval->repeat0_times = 20;
g_redial_interval->total_retry_times = 20;
return CM_OK;
}
static void CM_Try_newAPN(Mnc_Apn * apn_list, CM_Connection_Context * coninfo)
{
Apn_Info *apninfo;
if (apn_list == NULL)
return;
CM_Log(CM_Try_newAPN, "enter CM_Try_newAPN, NW_status:%d, all_try_fail %d\n", NW_status, apn_list->all_try_fail);
if (NW_status == CM_NW_STATUS_23G ||NW_status == CM_NW_STATUS_5G )
{
if (apn_list->all_try_fail == 1) {
apn_list->all_try_fail = 0;
apninfo = get_default_apninfo(apn_list, NULL);
}
else
apninfo = get_default_apninfo(apn_list, coninfo->pdpinfo->APN);
if (apninfo == NULL && apn_list->all_try_fail == 1) {
if (coninfo->pdpinfo->try_num_ESM_false <= MAX_ESM_TRY_NUM) {
CM_Log(CM_Try_newAPN1542, "CM_Try_newAPN [23G case], try_num_ESM_false %d\n", coninfo->pdpinfo->try_num_ESM_false);
send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN);
coninfo->pdpinfo->try_num_ESM_false++;
}
}
else
{
if (apninfo != NULL) {
strcpy(coninfo->pdpinfo->APN, apninfo->apn);
coninfo->pdpinfo->IP_Type = apninfo->iptype;
coninfo->pdpinfo->IP_Type_back = apninfo->iptype;
//setup data call
send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_IMMED);
}
}
} else if (NW_status == CM_NW_STATUS_LTE || NW_status == CM_NW_STATUS_NOT_REGISTERED) {
if (apn_list->all_try_fail == 1) {
apn_list->all_try_fail = 0;
apninfo = get_inital_attach_apn(apn_list, NULL);
} else
apninfo = get_inital_attach_apn(apn_list, coninfo->pdpinfo->LteAPN);
if (apninfo == NULL && apn_list->all_try_fail == 1) {
//clear the eti flag
send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN_CLEARETIF);
if (coninfo->pdpinfo->try_num_ESM_false <= MAX_ESM_TRY_NUM) {
CM_Log(CM_Try_newAPN1340, "CM_Try_newAPN, try_num_ESM_false %d\n", coninfo->pdpinfo->try_num_ESM_false);
send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN);
coninfo->pdpinfo->try_num_ESM_false++;
}
} else {
if (apninfo != NULL) {
strcpy(coninfo->pdpinfo->LteAPN, apninfo->lte_apn);
CM_Log(CM_Try_newAPN1, "CM_Try_newAPN, current use APN:%s\n", apninfo->lte_apn);
send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN);
}
}
}
CM_Log(CM_Try_newAPN2, "leave CM_Try_newAPN\n");
}
//roam status change from non-roaming to roaming
void CM_Handle_ChangetoRoam(void)
{
CM_Connection_Context *tmp_Context;
tmp_Context = g_CM_Context;
int cid;
CM_Log(CM_Handle_ChangetoRoam, "enter CM_Handle_ChangetoRoam");
while (tmp_Context) {
CM_Log(CM_Handle_ChangetoRoam1, "CM_Handle_ChangetoRoam: pdp_type %d connect_status %d data_on_roaming %d", tmp_Context->pdpinfo->PDP_Type,\
tmp_Context->connectStatus, tmp_Context->pdpinfo->data_on_roaming);
if (tmp_Context->pdpinfo->PDP_Type == 1 && tmp_Context->connectStatus == CM_CONNECT_CONSUCCESS
&& tmp_Context->pdpinfo->data_on_roaming == 0) {
cid = tmp_Context->pdpinfo->primaryCid;
if (tmp_Context->pdpinfo->IP_Type == IPV4) //IPV4
DeleteIPInfo(cid - 1, IPV4);
else { //IPV4V6 or IPV6
DeleteIPInfo(cid - 1, IPV4);
DeleteIPInfo(cid - 1, IPV6);
}
send_disconnect_2host(cid - 1, tmp_Context->pdpinfo->IP_Type);
tmp_Context->connectStatus = CM_CONNECT_ROAM;
}
else if (tmp_Context->pdpinfo->PDP_Type == 1
&& ( tmp_Context->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY ||tmp_Context->connectStatus == CM_CONNECT_WAIT_NWCHANGE ||
tmp_Context->connectStatus== CM_CONNECT_REDIAL || tmp_Context->connectStatus == CM_CONNECT_WAIT_PS_ATTACH )
&& tmp_Context->pdpinfo->data_on_roaming == 1)
{
if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_AUTO && pipe_mode == FALSE)
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
tmp_Context = tmp_Context->next;
}
CM_Log(CM_Handle_ChangetoRoam2, "leave CM_Handle_ChangetoRoam");
}
//roam status change from roaming to non-roaming
void CM_Handle_RoamChange(void)
{
CM_Connection_Context *tmp_Context;
CM_Connection_Context *next_Context;
tmp_Context = g_CM_Context;
CM_Log(CM_Handle_RoamChange, "enter CM_Handle_RoamChange");
while (tmp_Context) {
next_Context = tmp_Context->next;
if (tmp_Context->connectStatus == CM_CONNECT_ROAM) {
if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { //manual
CM_Delete_Cur_Context(tmp_Context);
tmp_Context = NULL;
}
else if (check_roamStatus() == FALSE) {
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
}
tmp_Context = next_Context;
}
CM_Log(CM_Handle_RoamChange1, "leave CM_Handle_RoamChange");
}
void CM_Handle_NWChange()
{
CM_Connection_Context *tmp_Context;
CM_Connection_Context *cur_Context;
tmp_Context = g_CM_Context;
CM_Log(CM_Handle_NWChange, "enter CM_Handle_NWChange: tmp_Context=%x", tmp_Context);
while (tmp_Context) {
cur_Context = tmp_Context;
CM_Log(CM_Handle_NWChange1, "CM_Handle_NWChange:connectStatus %d, NWReady %d", tmp_Context->connectStatus, NWReady);
if (tmp_Context->connectStatus == CM_CONNECT_WAIT_NWCHANGE || NWReady) {
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
return;
#endif
if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) {
//need to check the network enviroment
if (tmp_Context->connectStatus != CM_CONNECT_CONSUCCESS &&
tmp_Context->connectStatus != CM_CONNECT_GET_GLOBALIP_ERR &&
tmp_Context->connectStatus != CM_CONNECT_CONNING) {
tmp_Context->connectStatus = CM_CONNECT_DISCON;
CM_Delete_Cur_Context(tmp_Context);
}
} else if (check_roamStatus() == TRUE && tmp_Context->pdpinfo->data_on_roaming == 0) {
tmp_Context->connectStatus = CM_CONNECT_ROAM;
} else {
if (NWReady == 0)
{
CM_Log(CM_Handle_NWChange10, "CM_Handle_NWChange: nw not ready, wait 5 seconds to redial");
sleep(5);
}
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
}
tmp_Context = cur_Context->next;
}
CM_Log(CM_Handle_NWChange2, "leave CM_Handle_NWChange");
}
void CM_Handle_Reject()
{
CM_Connection_Context *tmp_Context;
CM_Connection_Context *cur_Context;
tmp_Context = g_CM_Context;
CM_Log(CM_Handle_Reject, "enter CM_Handle_Reject");
while (tmp_Context) {
cur_Context = tmp_Context;
CM_Log(CM_Handle_Reject1, "connectStatus %d, connectNum %d", tmp_Context->connectStatus, tmp_Context->pdpinfo->connectionNum);
if (tmp_Context->connectStatus == CM_CONNECT_DISCON) {
if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) //manual
CM_Delete_Cur_Context(tmp_Context);
else {
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
}
else if (tmp_Context->connectStatus == CM_CONNECT_WAIT_NWCHANGE) {
if (getErrorIndFlag()) {
if (dialer_pdp_cause_new_apn())
CM_Try_newAPN(g_work_apn, tmp_Context);
}
}
tmp_Context = cur_Context->next;
}
CM_Log(CM_Handle_Reject3, "leave CM_Handle_Reject");
}
void CM_Handle_Redial(int connectionNum)
{
CM_Connection_Context *tmp_Context;
tmp_Context = g_CM_Context;
CM_Log(CM_Handle_Redial_1305, "Enter CM_Handle_Redial, ctx 0x%x", tmp_Context);
while (tmp_Context) {
CM_Log(CM_Handle_Redial_1307, "CM_Handle_Redial, num=%d, Status=%d, retrytime=%d, dialFailureCode=%d",
tmp_Context->pdpinfo->connectionNum, tmp_Context->connectStatus, tmp_Context->retryTime, tmp_Context->dialFailureCode);
if (tmp_Context->pdpinfo->connectionNum == connectionNum &&
(tmp_Context->connectStatus == CM_CONNECT_REDIAL
|| tmp_Context->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY)) {
if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) {
//need to check the network enviroment
tmp_Context->connectStatus = CM_CONNECT_DISCON;
goto redial_continue;
}
if (check_roamStatus() == TRUE && tmp_Context->pdpinfo->data_on_roaming == 0) {
tmp_Context->connectStatus = CM_CONNECT_ROAM;
goto redial_continue;
}
if (tmp_Context->dialFailureCode == 33 || tmp_Context->dialFailureCode == 34
|| tmp_Context->dialFailureCode == 27 || tmp_Context->dialFailureCode == 29) {
CM_Try_newAPN(g_work_apn, tmp_Context);
goto redial_continue;
}
if (tmp_Context->connectStatus == CM_CONNECT_REDIAL) {
if (getUnknownPpdCause() == 0xFF) {
sleep(2);
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
goto redial_continue;
}
}
if (tmp_Context->retryTime >= 0 && tmp_Context->retryTime < CM_INT_MAX) {
if ( tmp_Context->connectStatus != CM_CONNECT_DIAL_IMMEDIATELY) {
CM_Log(CM_Handle_Redial_1334, "CM_Handle_Redial, wait %d ms, then start dial", tmp_Context->retryTime);
usleep(tmp_Context->retryTime * 1000);
}
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
goto redial_continue;
}
if (tmp_Context->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY) {
CM_Log(CM_Handle_Redial, "CM_Handle_Redial, start dial immediately");
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
else if (tmp_Context->dialFailureCode == PDP_FAIL_ERROR_UNSPECIFIED) {
CM_Log(CM_Handle_Redial1, "CM_Handle_Redial, FailureCode is ERROR_UNSPECIFIED");
if (NW_status == CM_NW_STATUS_NOT_REGISTERED) {
CM_Log(CM_Handle_Redial2, "CM_Handle_Redial, network not registered\n");
//need to dial when nw registered
tmp_Context->connectStatus = CM_CONNECT_WAIT_NWCHANGE;
} else {
//need to check network interval array
if (redial_sleep(tmp_Context->dial_cnt)) {
tmp_Context->dial_cnt++;
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
else if (!g_redial_interval)
{
sleep(2);
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
else {
CM_Log(CM_Handle_Redial3, "CM_Handle_Redial, dial count exceeds the max number");
}
}
}//end PDP_FAIL_ERROR_UNSPECIFIED
else {
CM_Log(CM_Handle_Redial4, "CM_Handle_Redial, FailureCode is %d, connect status %d, NW_status %d, dial_cnt %d",
tmp_Context->dialFailureCode, tmp_Context->connectStatus, NW_status, tmp_Context->dial_cnt);
if(NW_status == CM_NW_STATUS_NOT_REGISTERED)
tmp_Context->connectStatus = CM_CONNECT_WAIT_NWCHANGE;
else {
if(redial_sleep(tmp_Context->dial_cnt)) {
tmp_Context->dial_cnt++;
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
else if (!g_redial_interval)
{
sleep(2);
send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED);
}
else
{
CM_Log(CM_Handle_Redial1798, "CM_Handle_Redial, redial count exceeds the max number");
}
}
}
}//end if
redial_continue:
tmp_Context = tmp_Context->next;
}//end while
CM_Log(CM_Handle_Redial5, "CM_Handle_Redial done ");
}
void CM_Handle_DefaultDataCall()
{
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
return;
#endif
CM_Log(CM_Handle_DefaultDataCall, "CM_Handle_DefaultDataCall: wait some seconds and set default data call again");
sleep(4);
send_dialmsg_to_mainthread(-1, REDIAL_DEFAULT_DATACALL);
CM_Log(CM_Handle_DefaultDataCall1, "CM_Handle_DefaultDataCall: send msg REDIAL_DEFAULT_DATACALL done");
}
static void CM_Handle_SingleStack()
{
send_dialmsg_to_mainthread(-1, REDIAL_SINGLE_STACK);
CM_Log(CM_Handle_SingleStack, "CM_Handle_SingleStack: send REDIAL_SINGLE_STACK to mainthread");
}
CM_Connection_Context *findContextByConnum(int connectionNum)
{
CM_Connection_Context *tmp_Context;
tmp_Context = g_CM_Context;
while (tmp_Context) {
if (tmp_Context->pdpinfo->connectionNum == connectionNum)
return tmp_Context;
tmp_Context = tmp_Context->next;
}
return NULL;
}
CM_Connection_Context *cm_get_ctx_by_cid(int cid)
{
CM_Connection_Context *ctx = g_CM_Context;
while (ctx) {
if (ctx->pdpinfo->primaryCid == cid)
return ctx;
ctx = ctx->next;
}
return NULL;
}
int cm_get_conn_num_by_cid(int cid)
{
int conn_num = CM_INT_MAX;
CM_Connection_Context *ctx = cm_get_ctx_by_cid(cid);
if (ctx && ctx->pdpinfo) {
conn_num = ctx->pdpinfo->connectionNum;
}
return conn_num;
}
void CM_Redial_Function(msg_hdr * msg)
{
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
return;
#endif
pthread_mutex_lock(&cm_mutex);
CM_Log(CM_Redial_Function1887, "[redial] CM_Redial_Function, msgtype %d, cm_mutex locked\n", msg->msgtype);
switch (msg->msgtype) {
case REDIAL_ROAMCHANGE:
CM_Handle_RoamChange();
break;
case REDIAL_NWCHANGE:
CM_Handle_NWChange();
break;
case REDIAL_IMMED:
case REDIAL_NEWAPN:
CM_Handle_Redial(msg->connectionNum);
break;
case REDIAL_REJECT:
CM_Handle_Reject();
break;
case REDIAL_DEFAULT_DATACALL:
CM_Handle_DefaultDataCall();
break;
case REDIAL_SINGLE_STACK:
CM_Handle_SingleStack();
break;
default:
CM_Log(CM_Redial_Function1, "CM_Redial_Function, invalid msg type");
break;
}
pthread_mutex_unlock(&cm_mutex);
CM_Log(CM_Redial_Function2, "[redial] CM_Redial_Function done, cm_mutex unlocked\n");
}
static bool check_merger_attachapn(AttachApn_Info * attachapn, Apn_Info * apninfo)
{
bool ret = FALSE;
if(matchApnNetworkIdentifier(attachapn->apn, apninfo->lte_apn) == 0 && matchApnNetworkIdentifier(apninfo->lte_apn,attachapn->apn) == 0) {
CM_Log(check_merger_attachapn, "check_merger_attachapn, attach apn change");
strcpy(attachapn->apn, apninfo->lte_apn);
ret = TRUE;
}
if(attachapn->iptype != apninfo->iptype) {
CM_Log(check_merger_attachapn1, "check_merger_attachapn, ip type change");
attachapn->iptype = apninfo->iptype;
ret = TRUE;
}
if(strcmp(attachapn->authtype, apninfo->lte_authtype)) {
CM_Log(check_merger_attachapn2, "check_merger_attachapn, authtype change");
strcpy(attachapn->authtype, apninfo->lte_authtype);
ret = TRUE;
}
if(strcmp(attachapn->username, apninfo->lte_usrname)) {
CM_Log(check_merger_attachapn3, "check_merger_attachapn, username change");
strcpy(attachapn->username, apninfo->lte_usrname);
ret = TRUE;
}
if(strcmp(attachapn->passwd, apninfo->lte_paswd)) {
CM_Log(check_merger_attachapn4, "check_merger_attachapn, authtype change");
strcpy(attachapn->passwd, apninfo->lte_paswd);
ret = TRUE;
}
return ret;
}
static bool cm_need_reattach_for_ipv6(int iptype)
{
char *imsi = cm_get_cellular_imsi();
bool need_reattach = false;
if (iptype != IPV4V6 && iptype != IPV6)
return need_reattach;
if (get_ipv4_only_allowed())
return need_reattach;
if (imsi)
{
if (strncmp(imsi, "46605", sizeof("46605")) == 0)
need_reattach = true;
}
return need_reattach;
}
int cm_set_cfun(int value)
{
char at_str[MAX_STR_LEN] = { 0 };
int ret = 0, size = 0;
int power_state = 1;
if (value != 1)
{
memset(at_str, 0, MAX_STR_LEN);
snprintf(at_str, MAX_STR_LEN - 1, "AT+CFUN=%d", value);
size = strlen(at_str) + 1;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str, size);
}
else
{
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_RADIO_POWER, &power_state, 1);
}
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, NULL, 0, 0);
if (ret != UBUS_STATUS_OK) {
CM_Log_E(cm_set_cfun1838, "cm_set_cfun, ubus_invoke failed %s\n", ubus_strerror(ret));
}
return ret;
}
int cm_set_psdc(int enable)
{
char at_str[MAX_STR_LEN] = { 0 };
int ret = 0, size = 0;
memset(at_str, 0, MAX_STR_LEN);
snprintf(at_str, MAX_STR_LEN - 1, "AT*PSDC=%d", enable);
size = strlen(at_str) + 1;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str, size);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, NULL, 0, 0);
if (ret != UBUS_STATUS_OK) {
CM_Log_E(cm_set_cfun1838, "%s: ubus_invoke failed %s\n", __func__, ubus_strerror(ret));
}
return ret;
}
static int cm_data_call_list_exist(int cid)
{
Data_Call_Response_List *list = NULL;
bool exist = false;
int num = 0;
QueryDataCall(NULL);
if (get_data_call_response_list())
{
list = get_data_call_response_list();
while(list)
{
if (list->PDP.cid == cid)
exist = true;
num++;
list = list->next;
}
}
if (num > 0)
{
if (exist)
return num;
else
return -1;
}
else
return -1;
}
void cm_set_atcmd_data_call(Apn_Info *apn_info)
{
CM_Connection_Context *ctx = NULL;
int ip_type = -1, connect_status, changed, just_stop = 0;
char value_buf[PROPERTY_VALUE_MAX] = { 0 };
int need_reattach = false;
int exist_type = 0;
ctx = get_match_pdp(apn_info);
CM_Log(cm_set_atcmd_data_call1,"[AT DIAL]: %s , connection num %d, match ctx %x", __func__, apn_info->connection_num,ctx);
if (!ctx) {
if (apn_info->enable == 0) {
CM_Log(cm_set_atcmd_data_call1749,"[AT DIAL]: current cid [%d] in disconnected status, not allow to deactive", apn_info->cid);
return;
}
ctx = create_new_pdp_ctx(apn_info);
/*do NOT set first dial flag, then dialer will check network register status for some seconds*/
ctx->first_dial = 0;
if (cm_need_reattach_for_ipv6(apn_info->iptype)) {
if (ccinet_ipv6_global_ready(apn_info->cid, 0) == false) {
need_reattach = true;
goto stopdial;
}
}
goto startdial;
} else {
ip_type = ctx->pdpinfo->IP_Type;
if (apn_info->enable == 0) {
just_stop = 1;
goto stopdial;
}
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (cm_get_atcmd_apn_state(apn_info->cid) == CM_CONNECT_CONNING) {
CM_Log(cm_set_atcmd_data_call1764,"[AT DIAL]: current cid [%d] in connecting status, not allow to active in the state", apn_info->cid);
return;
}
#endif
if (cm_need_reattach_for_ipv6(apn_info->iptype)) {
if (ccinet_ipv6_global_ready(apn_info->cid, 0) == false) {
need_reattach = true;
goto stopdial;
}
}
changed = check_merger_pdpcontext(apn_info, ctx, PDP_CONFIG_ZGDCONT);
if (!changed)
{
#ifdef CONFIG_ZGDCONT_MULTI_PDP
/* nothing changed, for connected status no need to trigger dialer again */
if (cm_get_atcmd_apn_state(apn_info->cid) == CM_CONNECT_CONSUCCESS) {
CM_Log(cm_set_atcmd_data_call1769,"[AT DIAL]: nothing changed, no need to redail again in connected status");
return;
}
#endif
goto startdial;
}
CM_Log(cm_set_atcmd_data_call1927,"[AT DIAL]:destroy current PDP, cid [%d], ip_type [%d]", ctx->pdpinfo->primaryCid, ip_type);
}
stopdial:
if (need_reattach) {
exist_type = cm_data_call_list_exist(apn_info->cid);
CM_Log(cm_set_atcmd_data_call1934,"[AT DIAL]: data call list exist type [%d] for cid [%d]", exist_type, apn_info->cid);
if (exist_type == -1) {
/* cid not exist, no need deactive */
goto startdial;
}
}
if (ip_type != -1)
DeleteIPInfo(ctx->pdpinfo->primaryCid - 1, ip_type);
connect_status = ctx->connectStatus;
if (exist_type == 1) {
/* only cid exist, need CFUN4->CFUN1 */
cm_set_cfun(4);
sleep(1);
cm_set_cfun(1);
sleep(2);
/* wait register status */
ctx->first_dial = 1;
goto startdial;
} else {
if(ctx->pdpinfo->PDP_Type == 1)
StopDialer(ctx->pdpinfo->primaryCid);
else
StopDialer(ctx->pdpinfo->secondaryCid);
}
if (connect_status == CM_CONNECT_CONSUCCESS)
{
if (ip_type != -1)
send_disconnect_2host(ctx->pdpinfo->primaryCid - 1, ip_type);
ctx->connectStatus = CM_CONNECT_DISCON;
cm_record_nwactivity(ctx, true);
}
ctx->connectStatus = CM_CONNECT_DISCON;
ctx->pdpinfo->primaryCid = apn_info->cid;
ctx->pdpinfo->secondaryCid = 0;
startdial:
if (!just_stop) {
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
ctx->pdpinfo->autoconnect = CM_CONTYPE_MANUAL;
#endif
ctx->pdpinfo->primaryCid = apn_info->cid;
ctx->pdpinfo->is_default = apn_info->Extra_params.lte_default;
CM_Log(cm_set_atcmd_data_call1,"[AT DIAL]: show dial context start");
showConContext(ctx);
CM_Log(cm_set_atcmd_data_call2, "[AT DIAL]: show dial context end");
sprintf(value_buf, "%d", ctx->pdpinfo->primaryCid);
property_set(PROP_DEFINED_CID, value_buf);
CM_Log(cm_set_atcmd_data_call3, "[AT DIAL]: set sys.defined.cid value to %s", value_buf);
if (pipe_mode && g_last_default_cid != 0xFF && ctx->pdpinfo->is_default)
{
send_if_command(g_last_default_cid, DOWN, IPV4);
send_if_command(g_last_default_cid, DOWN, IPV6);
}
if (check_roamStatus() == TRUE && apn_info->Extra_params.data_on_roaming == 0)
{
ctx->connectStatus = CM_CONNECT_ROAM;
CM_Log(cm_set_atcmd_data_call1842, "[AT DIAL]: disable data on roaming");
if (CM_CheckContextValid(ctx))
send_disconnect_2host( ctx->pdpinfo->primaryCid - 1, ctx->pdpinfo->IP_Type);
return;
}
ctx->connectStatus = CM_CONNECT_CONNING;
cm_set_atcmd_apn_state(apn_info->cid, CM_CONNECT_CONNING);
CM_StartDialer(ctx);
if (CM_CheckContextValid(ctx))
{
CM_Log(cm_set_atcmd_data_call4, "[AT DIAL]:connect status %d, dialFailureCode %d, cid %d, auto connect %d, is default %d",
ctx->connectStatus, ctx->dialFailureCode, ctx->pdpinfo->primaryCid, ctx->pdpinfo->autoconnect, ctx->pdpinfo->is_default);
if ((ctx->dialFailureCode != 0) && (ctx->dialFailureCode != PDP_FAIL_GET_GLOBALIP)) {
#if 0
if (ctx->retryTime != CM_INT_MAX) {
ctx->connectStatus = CM_CONNECT_REDIAL;
/*send redial msg*/
send_redialmsg_to_redialthread(ctx->pdpinfo->connectionNum, REDIAL_IMMED);
}
#endif
/*report the dial fail status*/
send_disconnect_2host( ctx->pdpinfo->primaryCid - 1, ctx->pdpinfo->IP_Type);
}
}
}
}
int cm_disconn_partner(int cid)
{
CM_Connection_Context *ctx = g_CM_Context;
int ret = -1;
if (cid <= 0)
return -1;
while (ctx)
{
if (ctx->pdpinfo && ctx->pdpinfo->parent_cid == cid)
{
if (ctx->pdpinfo->primaryCid != cid)
{
CM_Log(cm_disconn_partner, "cm_disconn_partner: disconn cid %d, parent cid %\n", ctx->pdpinfo->primaryCid, ctx->pdpinfo->parent_cid);
StopDialer(ctx->pdpinfo->primaryCid);
CM_Delete_Cur_Context(ctx);
ret = 0;
break;
}
}
ctx = ctx->next;
}
return ret;
}
//create new PDP, parse from apn_list
bool CM_Create_Pdp(Mnc_Apn * apn_list)
{
Apn_Info *attach_apn;
Apn_Info *default_apn;
CM_Connection_Context *match_Context;
bool ret = FALSE;
int back_iptype = 0;
if (apn_list == NULL)
return FALSE;
attach_apn = get_inital_attach_apn(apn_list, NULL);
if (attach_apn != NULL) {
if (strlen(attach_apn->lte_apn) == 0)
strcpy(attach_apn->lte_apn, attach_apn->apn);
CM_Log(CM_Create_Pdp, "CM_Create_Pdp: initial attach apn:%s\n", attach_apn->lte_apn);
if(g_attachapn == NULL) {
g_attachapn = (AttachApn_Info *)malloc(sizeof(AttachApn_Info));
memset(g_attachapn, 0, sizeof(AttachApn_Info));
g_attachapn->iptype = attach_apn->iptype;
strcpy(g_attachapn->apn, attach_apn->lte_apn);
strcpy(g_attachapn->authtype, attach_apn->lte_authtype);
strcpy(g_attachapn->username, attach_apn->lte_usrname);
strcpy(g_attachapn->passwd, attach_apn->paswd);
SetInitialAttachAPN(attach_apn, true);
}else {
ret = check_merger_attachapn(g_attachapn, attach_apn);
if(ret == TRUE)
SetInitialAttachAPN(attach_apn, true);
}
}
default_apn = get_default_apninfo(apn_list, NULL);
if (default_apn) {
CM_Log(CM_Create_Pdp1, "CM_Create_Pdp: default apn %s, iptype %d\n", default_apn->apn, default_apn->iptype);
match_Context = get_match_pdp(default_apn);
if (match_Context == NULL) {
CM_Log(CM_Create_Pdp2, "CM_Create_Pdp: NO matched pdp context find, will create new one\n");
match_Context = create_new_pdp_ctx(default_apn);
ret = TRUE;
} else {
//check and merger pdp context
back_iptype = match_Context->pdpinfo->IP_Type;
CM_Log(CM_Create_Pdp3, "CM_Create_Pdp: check and merge pdp context, back_iptype %d", back_iptype);
ret = check_merger_pdpcontext(default_apn, match_Context, 0);
if(ret == TRUE)
{
if(match_Context->connectStatus == CM_CONNECT_CONSUCCESS || match_Context->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)
{
CM_Log(CM_Create_Pdp4, "CM_Create_Pdp: destroy pdp connection, apn [%s]", match_Context->pdpinfo->APN);
match_Context->connectStatus = CM_CONNECT_DISCON;
if (cm_disconn_partner(match_Context->pdpinfo->primaryCid) == 0)
{
match_Context->pdpinfo->IP_Type = default_apn->iptype;
}
DeleteIPInfo(match_Context->pdpinfo->primaryCid - 1, back_iptype);
if(match_Context->pdpinfo->PDP_Type == 1)
StopDialer(match_Context->pdpinfo->primaryCid);
else
StopDialer(match_Context->pdpinfo->secondaryCid);
match_Context->pdpinfo->primaryCid = 0;
match_Context->pdpinfo->secondaryCid = 0;
}
}
}
showConContext(match_Context);
if (ret == TRUE) {
match_Context->first_dial = 1;
CM_StartDialer(match_Context);
if (CM_CheckContextValid(match_Context))
{
if ((match_Context->dialFailureCode != 0) &&(match_Context->dialFailureCode != PDP_FAIL_GET_GLOBALIP)) {
if (match_Context->retryTime != CM_INT_MAX) {
match_Context->connectStatus = CM_CONNECT_REDIAL;
//call redial method here
send_redialmsg_to_redialthread(match_Context->pdpinfo->connectionNum,
REDIAL_IMMED);
}
}
}
} else {
CM_Log(CM_Create_Pdp5, "CM_Create_Pdp: NO need to dial");
}
} else {
CM_Log(CM_Create_Pdp6, "CM_Create_Pdp: NO default APN");
dialer_query_defaultdatacall();
}
//need to add more type here
Apn_Info *fota_apn;
fota_apn = get_fota_apninfo(apn_list);
if(fota_apn != NULL)
{
CM_Log(CM_Create_Pdp7, "%s: fota apn %s", fota_apn->apn);
}
return TRUE;
}