blob: 221e26d01239c546e3878b8a9ef87d75fe93ec52 [file] [log] [blame]
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
DIALER TASK Module
GENERAL DESCRIPTION
This module contains the Position Determination Client Interface Block
EXTERNALIZED FUNCTIONS
INITIALIZATION AND SEQUENCING REQUIREMENTS
Copyright (c) 2011 by MARVELL INCORPORATED. All Rights Reserved.
Export of this technology or software is regulated by the U.S. Government.
Diversion contrary to U.S. law prohibited.
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*
<EJECT> */
/*===========================================================================
EDIT HISTORY FOR MODULE
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
when who what, where, why
-------- ------- -------------------------------------------------------------
11/16/08 yhuang Create dialer Task file
===========================================================================*/
/*
<EJECT> */
/*===========================================================================
INCLUDE FILES FOR MODULE
===========================================================================*/
#include "dialer_task.h"
#define CSC_file_size 128*1024 //128K
#define ADDITIONAL_APN_FILE_NAME "additionalAPN.txt"
//////////////////////////////////////////////////////////////////////
// Global Variables
//////////////////////////////////////////////////////////////////////
#define PATH_PROC_IFINET6 "/proc/net/if_inet6"
#define IPV6_ADDR_SCOPE_MASK 0x00f0U
#define UCI_NETWORK_FILE ((pipe_mode == TRUE) ? "pipe" : "network")
#define UBUS_NETWORK_OBJ ((pipe_mode == TRUE) ? "piped" : "network")
#define UBUS_NETWORK_IF_OBJ ((pipe_mode == TRUE) ? "piped" : "network.interface")
#define UCI_DHCP_FILE "dhcp"
#define UCI_ODHCPD_OBJ "dhcp"
#define UCI_WAN_FILE
#define MPIPE_IP6_PATH "/sys/kernel/mpipe/devices/usbnet0/ll6addr"
//need to re-define according to the version number
typedef RIL_SignalStrength_v6 RIL_SignalStrength;
Mnc_Apn *IMSI_APN = NULL;
int dialerReasonCode = 0;
int CMCurrentCid = -1;
unsigned char UnknownPdpCause = FALSE;
bool ErrorIndFlag = FALSE;
Data_Call_Response_List *DataCallRsponseList = NULL;
char IMSI[16] = { 0 };
bool allow_redial_ipv6_err = FALSE;
bool may_need_reload = FALSE;
char default_apn[MAX_STR_LEN];
int default_iptype = -1;
bool attach_ipv4_only_allowed[3];
bool attach_ipv6_only_allowed[3];
bool g_test_sim = false;
Data_Call_Response DataCallRsp;
const struct vzw_extra_info vzw_param_table[] = {
{1, 300, 1023, 0},
{2, 300, 1023, 0},
{3, 300, 1023, 0},
{4, 300, 1023, 0},
{5, 300, 1023, 0}
};
const char *telcel_mccmnc_table[] = {
"33402",
"334020",
};
const char *vzw_mccmnc_table[] = {
"311390",
"311480",
"311489",
"310028"
};
const char *ctcc_mccmnc_table[] = {
"46003",
"46005",
"46011",
"46012"
};
//////////////////////////////////////////////////////////////////////
// static Variables
//////////////////////////////////////////////////////////////////////
unsigned char V4_network_intf_status[MAX_CID_LIMITATION] = {0};
unsigned char V6_network_intf_status[MAX_CID_LIMITATION] = {0};
static struct ubus_subscriber ind_event;
cm_ubus_ctx_id cm_ubus_id;
static int pin_status = -1;
static int wait_for_sim_ready = 1;
UINT8 g_last_default_cid = 0xFF;
//////////////////////////////////////////////////////////////////////
// extern Variables
//////////////////////////////////////////////////////////////////////
extern unsigned char RegStatus;
extern int NW_status;
extern bool NWReady;
extern bool IsRoaming;
extern int g_auto_apn_parsed;
extern Mnc_Apn *g_work_apn;
extern CM_Connection_Context *g_CM_Context;
extern struct ubus_context *cm_ctx;
extern s_cellular_info g_cell_basic_info;
//indication that we chck reg status in indication callback
extern int checkregsta_indication;
extern struct blob_buf cm_b;
extern bool pipe_mode;
extern bool imsi_changed;
extern pthread_mutex_t cm_mutex;
//////////////////////////////////////////////////////////////////////
// local Prototypes
//////////////////////////////////////////////////////////////////////
int ConvertIPType(const char *protocol);
static int Ind_notify(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
void delete_route_info(void);
void cm_ifup_complete(struct ubus_request *req, int ret);
void cm_ifdown_complete(struct ubus_request *req, int ret);
void reload_network_complete(struct ubus_request *req, int ret);
void config_lan_ipv6(char *ip);
void config_route_ipv6(char *ip);
void QueryDataCall_Indnotify_data_cb(struct ubus_request *req, int type, struct blob_attr *msg);
bool ProcessRILDeactInd(int in_cid);
int SimReady(void);
Mnc_Apn *wan_get_apn(char *imsi);
void async_invoke_complete(struct ubus_request *req, int ret);
int send_ip_info_request_2ril_async(RIL_IPDNSInfo *ip_info, int len);
static void send_ip_info_2host(Data_Call_Response *rsp);
static int is_default_pdp_bearer(int cid);
void send_zgdcont_info_2atcmd(Apn_Info *apn_info);
int up_down_br_lan(if_command cmd, char* name, int sync);
static int cm_system(const char *cmd, char *res_buf, int rsp_len);
/*==============================================================
*Update @ 131129, by shoujunl
*before: mcc, mnc, "operator", "apn", "lteapn"
*after : mcc, mnc, "operator", "apn", "network type","authtype", "usrname", "password",
*Note : 1) no such fileds in apn_txt,be consider as NULL
2) authtype: NONE/PAP/CHAP,CHAP is not supported by PS.
3) NWTYPE: 0 -- common
1 -- 2/3g
2 -- lte
3 -- 2g
4 -- 3g
4) usrname/password : any is consider to be no usrname or password
Update @ 131213, by shoujunl ,add IPTYPE
before : mcc, mnc, "operator", "apn", "network type","authtype", "usrname", "password"
after : mcc, mnc, "operator", "apn", "network type","authtype", "usrname", "password","IPTYPE"
Note : 1) IPTYPE in apn text, IPV4/IPV6/IPV4V6
in Apn_info : 0--IPV4V6, 1--IPV4, 2 -- IPV6
if do not find in apn_text, iptype wii be set to 1.(Set to IPV4, modified by shoujunl @131231)
*===============================================================*/
Mnc_Apn *wan_get_apn(char *imsi)
{
char mcc_buf[4] = { 0 }, mnc_buf[4] = {
0};
Mnc_Apn *get_Apn = NULL;
int ret;
if (strlen(imsi) < 7) {
CM_Log_E(wan_get_apn1, "wan_get_apn return cause IMSI error\n");
return NULL;
}
memcpy(mcc_buf, imsi, 3);
memcpy(mnc_buf, imsi + 3, cm_get_mnc_length());
get_Apn = malloc(sizeof(Mnc_Apn));
if (!get_Apn) {
return NULL;
}
memset(get_Apn, 0, sizeof(Mnc_Apn));
get_Apn->all_try_fail = FALSE;
ret=fillApnInfo(mcc_buf, mnc_buf, get_Apn);
#if 0
if (ret == 0) {
CM_Log(wan_get_apn3, "wan_get_apn mcc is %s, mnc is %s, fail to get APN. So switch mnc to 3 digits\n",
get_Apn->mcc, get_Apn->mnc);
memcpy(mcc_buf, imsi, 3);
memcpy(mnc_buf, imsi + 3, 3);
memset(get_Apn, 0, sizeof(Mnc_Apn));
get_Apn->all_try_fail = FALSE;
ret=fillApnInfo(mcc_buf, mnc_buf, get_Apn);
}
#endif
CM_Log(wan_get_apn4, "Exit wan_get_apn: mcc is %s, mnc is %s, ret=%d\n", get_Apn->mcc, get_Apn->mnc, ret);
if (ret == 0)
{
free(get_Apn);
return NULL;
}
else
return get_Apn;
}
int ConvertIPType(const char *protocol)
{
if (!protocol) {
return -1;
} else if (strcasecmp(protocol, "IP") == 0) {
return 1;
} else if (strcasecmp(protocol, "IPV6") == 0) {
return 2;
} else if (strcasecmp(protocol, "IPV4V6") == 0) {
return 0;
} else {
return -1;
}
}
static void dialer_remove_apn_suffix(char *apn)
{
char tmp[MAX_STR_LEN + 1];
char *pEnd = NULL;
if (apn == NULL || strlen(apn) == 0)
return;
memset(tmp, 0 , MAX_STR_LEN + 1);
pEnd = strstr(apn, ".mnc");
if (pEnd)
{
memcpy(tmp, apn, pEnd - apn);
tmp[pEnd - apn] = '\0';
strcpy(apn, tmp);
}
else
{
pEnd = strstr(apn, ".MNC");
if (pEnd)
{
memcpy(tmp, apn, pEnd - apn);
tmp[pEnd - apn] = '\0';
strcpy(apn, tmp);
}
}
return;
}
static void dialer_set_default_apn(char *apn, char *lte_apn, bool persist)
{
if (lte_apn)
strncpy(default_apn, lte_apn, sizeof(default_apn) - 1);
if (persist)
cm_save_default_apn(apn, lte_apn);
}
static char *dialer_get_default_apn()
{
if (default_apn[0] == '\0')
return NULL;
else
return default_apn;
}
static void dialer_set_default_iptype(int ip_type)
{
default_iptype = ip_type;
}
#ifdef CONFIG_ZGDCONT_MULTI_PDP
static int dialer_get_default_iptype(void)
{
return default_iptype;
}
#endif
static void CM_Handle_CPAssert(void)
{
CM_Connection_Context *tmp_Context = NULL;
tmp_Context = g_CM_Context;
int cid;
CM_Log(CM_Handle_CPAssert, "enter CM_Handle_CPAssert");
while(tmp_Context)
{
if(tmp_Context->connectStatus == CM_CONNECT_CONSUCCESS)
{
if(tmp_Context->pdpinfo->PDP_Type == 1)
cid = tmp_Context->pdpinfo->primaryCid - 1;
else
cid = tmp_Context->pdpinfo->secondaryCid - 1;
DeleteIPInfo(cid, tmp_Context->pdpinfo->IP_Type);
send_disconnect_2host(cid, tmp_Context->pdpinfo->IP_Type);
tmp_Context->connectStatus = CM_CONNECT_WAIT_NWCHANGE;
tmp_Context->dial_cnt = 0;
tmp_Context->first_dial = 1;
}
tmp_Context = tmp_Context->next;
}
cm_reset_nw_last_param();
CM_Log(CM_Handle_CPAssert1, "leave CM_Handle_CPAssert");
}
static CM_Connection_Context *CM_Create_Ltedefault(void *data, int datalen)
{
CM_Connection_Context *tmp_Context = NULL;
Data_Call_Response_List *Dstpdp = NULL;
Ubus_Data_Call_Response *ptr = NULL;
int len;
Apn_Info *apninfo = NULL;
ptr = data;
if (ptr == NULL) {
return NULL;
}
for (len = 0; (len < datalen); len += sizeof(Ubus_Data_Call_Response), ptr++) {
#ifdef CONFIG_DEFAULT_CID_5
if (ptr->cid == 5) {
#else
if (ptr->cid == 1) {
#endif
tmp_Context = (CM_Connection_Context *) malloc(sizeof(CM_Connection_Context));
if (tmp_Context == NULL) {
return NULL;
}
memset(tmp_Context, 0, sizeof(CM_Connection_Context));
tmp_Context->connectStatus = CM_CONNECT_CONSUCCESS;
tmp_Context->dialFailureCode = ptr->status;
tmp_Context->create_by = 1;
tmp_Context->pdpinfo = (PdpInfo *) malloc(sizeof(PdpInfo));
if (tmp_Context->pdpinfo == NULL) {
return NULL;
}
memset(tmp_Context->pdpinfo, 0, sizeof(PdpInfo));
tmp_Context->pdpinfo->connectionNum = ptr->cid;
tmp_Context->pdpinfo->primaryCid = ptr->cid;
tmp_Context->pdpinfo->PDP_Type = 1;
strcpy(tmp_Context->pdpinfo->APN, ptr->apn);
strcpy(tmp_Context->pdpinfo->LteAPN, ptr->apn);
#ifdef CONFIG_CM_URSP
tmp_Context->pdpinfo->rsd_index = -1;
#endif
if (cm_get_nw_status_cache() == CM_NW_STATUS_LTE)
dialer_set_default_apn(NULL, ptr->apn, true);
else
dialer_set_default_apn(ptr->apn, NULL, true);
apninfo = get_default_apninfo(g_work_apn, NULL);
if (apninfo)
{
tmp_Context->pdpinfo->data_on_roaming = apninfo->Extra_params.data_on_roaming;
tmp_Context->pdpinfo->autoconnect = apninfo->Extra_params.autoconnect;
tmp_Context->pdpinfo->is_default = apninfo->Extra_params.lte_default;
tmp_Context->pdpinfo->always_on = apninfo->Extra_params.always_on;
tmp_Context->pdpinfo->data_block = apninfo->data_block;
}
else if (is_pdp_auto_apn(g_work_apn, "default"))
{
Extra_Apn_Info default_params = { 0 };
if (get_default_params(APNS_DEFAULT_FILENAME, &default_params, "default") == 0)
{
CM_Log(CM_Create_Ltedefault383, "CM_Create_Ltedefault: missing default configuration file!");
tmp_Context->pdpinfo->data_on_roaming = true;
tmp_Context->pdpinfo->autoconnect = CM_CONTYPE_AUTO;
tmp_Context->pdpinfo->is_default = 1;
tmp_Context->pdpinfo->always_on = 1;
}
else
{
tmp_Context->pdpinfo->data_on_roaming = default_params.data_on_roaming;
tmp_Context->pdpinfo->autoconnect = default_params.autoconnect;
tmp_Context->pdpinfo->is_default = default_params.lte_default;
tmp_Context->pdpinfo->always_on = default_params.always_on;
}
}
else
{
tmp_Context->pdpinfo->data_on_roaming = true;
tmp_Context->pdpinfo->autoconnect = CM_CONTYPE_AUTO;
tmp_Context->pdpinfo->is_default = 1;
tmp_Context->pdpinfo->always_on = 1;
}
CM_Log(CM_Create_Ltedefault373, "CM_Create_Ltedefault, data_on_roaming %d", tmp_Context->pdpinfo->data_on_roaming);
tmp_Context->pdpinfo->mtu = cm_get_config_mtu(ptr->cid);
/*network indicate the mtu form PCO list*/
if (ptr->mtu > 0 && (tmp_Context->pdpinfo->mtu == 0 || ptr->mtu < tmp_Context->pdpinfo->mtu)) {
CM_Log(CM_Create_Ltedefault5, "CM_Create_Ltedefault, Get mtu %d from PCO", ptr->mtu);
tmp_Context->pdpinfo->mtu = ptr->mtu;
}
Dstpdp = malloc(sizeof(Data_Call_Response_List));
if (!Dstpdp) {
return NULL;
}
memset(Dstpdp, 0, sizeof(Data_Call_Response_List));
Dstpdp->next = NULL;
Dstpdp->PDP.cid = ptr->cid;
Dstpdp->PDP.IP_Type = ConvertIPType(ptr->type);
Dstpdp->PDP.status = ptr->status;
if (ptr->mtu > 0 )
Dstpdp->PDP.mtu = ptr->mtu;
Dstpdp->PDP.suggestedRetryTime = ptr->suggestedRetryTime;
CM_Log(CM_Create_Ltedefault7, "CM_Create_Ltedefault: cid %d ip_type %d status %d mtu %d data_on_roaming %d suggestedRetryTime %d\n",
Dstpdp->PDP.cid, Dstpdp->PDP.IP_Type, Dstpdp->PDP.status, Dstpdp->PDP.mtu, Dstpdp->PDP.suggestedRetryTime);
if ((Dstpdp->PDP.IP_Type == IPV4) || (Dstpdp->PDP.IP_Type == IPV4V6)) //IPV4 or IPV4V6
{
if (Dstpdp->PDP.ipv4info == NULL) {
Dstpdp->PDP.ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (!Dstpdp->PDP.ipv4info) {
CM_Log_E(CM_Create_Ltedefault8, "CM_Create_Ltedefault: malloc size %d failed\n", sizeof(Ipv4Info));
goto EXIT;
}
memset(Dstpdp->PDP.ipv4info, 0, sizeof(Ipv4Info));
}
}
if ((Dstpdp->PDP.IP_Type == IPV6) || (Dstpdp->PDP.IP_Type == IPV4V6)) //IPV6 or IPV4V6
{
if (Dstpdp->PDP.ipv6info == NULL) {
Dstpdp->PDP.ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (!Dstpdp->PDP.ipv6info) {
CM_Log_E(CM_Create_Ltedefault9, "CM_Create_Ltedefault: malloc size %d failed\n", sizeof(Ipv6Info));
goto EXIT;
}
memset(Dstpdp->PDP.ipv6info, 0, sizeof(Ipv6Info));
}
}
configure_pdp_para(ptr, Dstpdp, "addr");
configure_pdp_para(ptr, Dstpdp, "gateway");
configure_pdp_para(ptr, Dstpdp, "dns");
DataCallRsp.cid = Dstpdp->PDP.cid;
DataCallRsp.suggestedRetryTime = Dstpdp->PDP.suggestedRetryTime;
DataCallRsp.IP_Type = Dstpdp->PDP.IP_Type;
tmp_Context->pdpinfo->IP_Type = Dstpdp->PDP.IP_Type;
DataCallRsp.status = Dstpdp->PDP.status;
if (Dstpdp->PDP.mtu > 0 && (DataCallRsp.mtu == 0 ||Dstpdp->PDP.mtu < DataCallRsp.mtu))
DataCallRsp.mtu = Dstpdp->PDP.mtu;
if (Dstpdp->PDP.ipv4info != NULL) {
if (DataCallRsp.ipv4info == NULL) {
DataCallRsp.ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (!DataCallRsp.ipv4info) {
goto EXIT;
}
memset(DataCallRsp.ipv4info, 0, sizeof(Ipv4Info));
}
if (tmp_Context->ipv4info == NULL) {
tmp_Context->ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (tmp_Context->ipv4info == NULL) {
goto EXIT;
}
memset(tmp_Context->ipv4info, 0, sizeof(Ipv4Info));
}
memcpy(DataCallRsp.ipv4info, Dstpdp->PDP.ipv4info, sizeof(Ipv4Info));
memcpy(tmp_Context->ipv4info, Dstpdp->PDP.ipv4info, sizeof(Ipv4Info));
}
if (Dstpdp->PDP.ipv6info != NULL) {
if (DataCallRsp.ipv6info == NULL) {
DataCallRsp.ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (!DataCallRsp.ipv6info) {
goto EXIT;
}
memset(DataCallRsp.ipv6info, 0, sizeof(Ipv6Info));
}
if (tmp_Context->ipv6info == NULL) {
tmp_Context->ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (tmp_Context->ipv6info == NULL) {
goto EXIT;
}
memset(tmp_Context->ipv6info, 0, sizeof(Ipv6Info));
}
memcpy(DataCallRsp.ipv6info, Dstpdp->PDP.ipv6info, sizeof(Ipv6Info));
memcpy(tmp_Context->ipv6info, Dstpdp->PDP.ipv6info, sizeof(Ipv6Info));
}
EXIT:
if (Dstpdp != NULL)
FreeDataCallRsponseList(Dstpdp);
return tmp_Context;
}//end if
}//end for
return NULL;
}
static int process_lte_svc_info(s_cellular_info *info, void *data, int len)
{
s_lte_svc_info *lte_info = (s_lte_svc_info *)data;
if (len == sizeof(s_lte_svc_info))
memcpy(&(info->lte_info), lte_info, len);
else
return UBUS_STATUS_INVALID_ARGUMENT;
return UBUS_STATUS_OK;
}
static int process_umts_svc_info(s_cellular_info *info, void *data, int len)
{
s_umts_svc_info *umts_info = (s_umts_svc_info *)data;
if (len == sizeof(s_umts_svc_info))
memcpy(&(info->umts_info), umts_info, len);
else
return UBUS_STATUS_INVALID_ARGUMENT;
return UBUS_STATUS_OK;
}
bool dialer_pdp_cause_new_apn(void)
{
UINT8 cause = getUnknownPpdCause();
if (cause == 27 ||cause == 29 || cause == 33 || cause == 34)
return true;
else
return false;
}
#ifdef CM_CONFIG_TOE
static int process_unsol_star_cgtft(void *data, int len)
{
if (len == 0)
{
cm_toe_tft_param_init();
return UBUS_STATUS_OK;
}
cm_toe_tft_pf_update(data, len);
cm_toe_tft_pf_list_clear();
cm_toe_tuple_send();
return UBUS_STATUS_OK;
}
static int process_unsol_cgtft(void *data, int len)
{
if (len == 0)
{
cm_toe_tft_param_init();
return UBUS_STATUS_OK;
}
cm_toe_tft_pf_prepare(data, len);
//cm_toe_tft_param_update(data, len);
//cm_toe_tuple_send();
return UBUS_STATUS_OK;
}
#endif
void set_ipv4_only_allowed(int flag)
{
if (cm_get_nw_status_cache() == CM_NW_STATUS_23G)
attach_ipv4_only_allowed[0] = flag;
else if (cm_get_nw_status_cache() == CM_NW_STATUS_LTE || cm_get_nw_status_cache() == CM_NW_STATUS_NOT_REGISTERED)
attach_ipv4_only_allowed[1] = flag;
else
attach_ipv4_only_allowed[2] = flag;
}
int get_ipv4_only_allowed()
{
if (cm_get_nw_status_cache() == CM_NW_STATUS_23G)
return attach_ipv4_only_allowed[0];
else if (cm_get_nw_status_cache() == CM_NW_STATUS_LTE || cm_get_nw_status_cache() == CM_NW_STATUS_NOT_REGISTERED)
return attach_ipv4_only_allowed[1];
else
return attach_ipv4_only_allowed[2];
}
void set_ipv6_only_allowed(int flag)
{
if (cm_get_nw_status_cache() == CM_NW_STATUS_23G)
attach_ipv6_only_allowed[0] = flag;
else if (cm_get_nw_status_cache() == CM_NW_STATUS_LTE || cm_get_nw_status_cache() == CM_NW_STATUS_NOT_REGISTERED)
attach_ipv6_only_allowed[1] = flag;
else
attach_ipv6_only_allowed[2] = flag;
}
int get_ipv6_only_allowed()
{
if (cm_get_nw_status_cache() == CM_NW_STATUS_23G)
return attach_ipv6_only_allowed[0];
else if (cm_get_nw_status_cache() == CM_NW_STATUS_LTE || cm_get_nw_status_cache() == CM_NW_STATUS_NOT_REGISTERED)
return attach_ipv6_only_allowed[1];
else
return attach_ipv6_only_allowed[2];
}
static void redial_timeout_cb(struct uloop_timeout *timeout);
static struct uloop_timeout redial_timeout = {
.cb = redial_timeout_cb,
};
#define REDIAL_TIMEOUT_MSEC (2*60*60*1000)
static void redial_timeout_cb(struct uloop_timeout *timeout)
{
uloop_timeout_cancel(timeout);
CM_Log(redial_timeout_cb1, "redial_timeout_cb: 2hours redial timeout happened\n");
send_redialmsg_to_redialthread(-1, REDIAL_IMMED);
}
void start_2hours_redial_timer(void)
{
if (is_telcel_sim(g_cell_basic_info.IMSI))
{
uloop_timeout_set(&redial_timeout, REDIAL_TIMEOUT_MSEC);
CM_Log(cm_start_2hours_redial_timer1, "cm_start_2hours_redial_timer: 2hours redial timer triggered\n");
}
}
void stop_2hours_redial_timer(void)
{
if (is_telcel_sim(g_cell_basic_info.IMSI))
{
uloop_timeout_cancel(&redial_timeout);
CM_Log(cm_start_2hours_redial_timer1, "cm_start_2hours_redial_timer: 2hours redial timer canceled\n");
}
}
static int Ind_notify(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(ctx);
UNUSED(obj);
UNUSED(req);
UNUSED(method);
unsigned int id = 0, errorNo = 0;
void *data = NULL;
int datalen = 0;
int ps_reg_state = 0, reject_cid = 0, deactiveCid = 0;
RIL_SignalStrength * signal = NULL;
if (rilutil_parseResponseDSMaster(msg, &id, &errorNo, (void **)&data, &datalen)) {
return -1;
}
if (errorNo != 0)
goto end;
CM_Log(Ind_notify1, "Ind_notify: ind %s, datalen:0x%x, errorNo:%d need_reload=%d\n", RilRequestToString(id), datalen, errorNo, may_need_reload);
switch (id) {
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:
get_imsi(false, false);
//CheckDataCallRegisterStatus_IndCallback();
break;
case RIL_UNSOL_PDP_REJECT_CAUSE:
if(data)
{
reject_cid = ( (int *) data)[1];
if (reject_cid == CM_DEFAULT_ATTACH_CID ||reject_cid == 0xFF || reject_cid == CMCurrentCid)
{
setUnknownPpdCause((unsigned char)( (int *) data)[0]);
/* CIRC_PS_ESM_PDN_TYPE_IPV4_ONLY_ALLOWED,
CIRC_PS_ESM_PDN_TYPE_IPV6_ONLY_ALLOWED,
CIRC_PS_ESM_SINGLE_ADDRESS_BEARERS_ONLY_ALLOWED*/
if (reject_cid == CM_DEFAULT_ATTACH_CID ||reject_cid == 0xFF)
{
if (getUnknownPpdCause() == 50)
set_ipv4_only_allowed(true);
else if (getUnknownPpdCause() == 51)
set_ipv6_only_allowed(true);
}
}
if (dialer_pdp_cause_new_apn()) {
ErrorIndFlag = TRUE;
//need to add here
send_redialmsg_to_redialthread(-1, REDIAL_REJECT);
}
else if (getUnknownPpdCause() == 52)
{
send_redialmsg_to_redialthread(-1, REDIAL_SINGLE_STACK);
}
else if (getUnknownPpdCause() == 33)
{
start_2hours_redial_timer();
}
CM_Log(Ind_notify3, "Ind_notify: cid %d, ErrorIndFlag is %d\n", reject_cid, ErrorIndFlag);
}
break;
case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
QueryDataCall_Indnotify();
break;
case RIL_UNSOL_PDP_DEACTIVE_CID:
if(data)
{
deactiveCid = *(int*)data;
CM_Log(Ind_notify5, "Ind_notify: deactiveCid:%d", deactiveCid);
if (ProcessRILDeactInd(deactiveCid))
{
/* should query datacall list anyway, no matter the ind report sequence */
QueryDataCall_Indnotify();
}
#if 0
if (deactiveCid == 5)
{
attach_ipv4_only_allowed = false;
attach_ipv6_only_allowed = false;
}
#endif
}
break;
case RIL_UNSOL_PS_ATTACH_STATUS:
if(data)
{
ps_reg_state = *(int *)data;
CM_Log(Ind_notify6, "Ind_notify: PS_ATTACH_STATUS is %d\n", ps_reg_state);
}
break;
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
QuerySimStatus();
CM_Log(Ind_notify7, "Ind_notify: wait_for_sim_ready:%d pin_status:%d \n", wait_for_sim_ready, pin_status);
if (wait_for_sim_ready && pin_status == RIL_APPSTATE_READY) {
uloop_cancelled = true;
}
//TBD handle sim removal after cm init successfully
break;
case RIL_UNSOL_SIGNAL_STRENGTH:
if(data)
{
signal = data;
if(signal && (signal->GW_SignalStrength.bitErrorRate == 89) && (signal->GW_SignalStrength.signalStrength == 67))
{
CM_Log(Ind_notify8, "Ind_notify, cp assert here");
CM_Handle_CPAssert();
}
}
break;
case RIL_UNSOL_EEM_LTESVC:
process_lte_svc_info(&g_cell_basic_info, data, datalen);
break;
case RIL_UNSOL_EEM_UMTSSVC:
process_umts_svc_info(&g_cell_basic_info, data, datalen);
break;
#ifdef CM_CONFIG_TOE
case RIL_UNSOL_STAR_CGTFT:
process_unsol_star_cgtft(data, datalen);
break;
case RIL_UNSOL_PDP_TFT_MODIFY:
{
if(data)
{
int p_cid,cid;
cid = ( (int *) data)[0];
p_cid = ( (int *) data)[1];
CM_Log(Ind_notify708, "Ind_notify, RIL_UNSOL_PDP_TFT_MODIFY cid %d, p_cid %d", cid, p_cid);
if ( p_cid > 0 && p_cid < 255 )
p_cid = p_cid - 1;
else
p_cid = 255;
cid = cid -1;
cm_toe_tft_pf_delete(p_cid, cid);
cm_trigger_tft_query(true);
}
break;
}
case RIL_UNSOL_CGTFT:
process_unsol_cgtft(data, datalen);
break;
#endif
default:
CM_Log(Ind_notify9, "Ind_notify: ind(%d) %s is not supported in CM\n", id, RilRequestToString(id));
}
end:
if (data)
rilutil_freeResponseData(id, data, datalen);
return 0;
}
void dialer_query_defaultdatacall(void)
{
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
return;
#endif
CM_Log(dialer_query_defaultdatacall, "enter dialer_query_defaultdatacall");
CheckDataCallRegisterStatus_IndCallback();
QueryDataCall_Indnotify();
CM_Log(dialer_query_defaultdatacall1, "leave dialer_query_defaultdatacall");
}
struct network_lan
{
char lan_ifname[64];
char lan_ipaddr[16];
char lan_netmask[16];
};
struct network_lan network_lan_data;
static void dialer_load_network_lan(struct network_lan *data)
{
char cmd[128];
char rsp[128];
snprintf(cmd, sizeof(cmd), "uci get network.lan.ifname");
cm_system(cmd, rsp, sizeof(rsp));
strncpy(data->lan_ifname, rsp, sizeof(data->lan_ifname) - 1);
snprintf(cmd, sizeof(cmd), "uci get network.lan.ipaddr");
cm_system(cmd, rsp, sizeof(rsp));
strncpy(data->lan_ipaddr, rsp, sizeof(data->lan_ipaddr) - 1);
snprintf(cmd, sizeof(cmd), "uci get network.lan.netmask");
cm_system(cmd, rsp, sizeof(rsp));
strncpy(data->lan_netmask, rsp, sizeof(data->lan_netmask) - 1);
CM_Log(dialer_load_network_lan1, "dialer_load_network_lan, lan_ifname [%s], lan_ipaddr [%s], lan_netmask [%s]\n",
data->lan_ifname, data->lan_ipaddr, data->lan_netmask);
}
int g_sim2_base_cid = 8;
static void dialer_init_sim2_base_cid(void)
{
/* need read from cmdline */
char res[32];
int ret;
memset(res, 0, sizeof(res));
ret = cm_system("uci get cmdline.cid_base 2> /dev/null", res, sizeof(res) - 1);
CM_Log_E(init_sim2_base_cid1, "init_sim2_base_cid: system with res %s", res);
if (ret != 0 || strlen(res) == 0) {
return;
}
g_sim2_base_cid = atoi(res);
}
static int get_sim2_base_cid(void)
{
return g_sim2_base_cid;
}
int dialer_init(void)
{
#define MAX_RETRY_TIMES 20
int ret;
#if defined(CM_DELETE_IPINFO)
int i;
#endif
uint32_t id;
int retries = 0;
//register to receive PS unsolicated message
if (ubus_lookup_id(cm_ctx, "ril.unsol.ps", &id)) {
goto fail;
}
ret = ubus_subscribe(cm_ctx, &ind_event, id);
//register to receive MM unsolicated message
if (ubus_lookup_id(cm_ctx, "ril.unsol.mm", &id)) {
goto fail;
}
ret = ubus_subscribe(cm_ctx, &ind_event, id);
(void)ret;
do {
//get id of network object
if (ubus_lookup_id(cm_ctx, UBUS_NETWORK_OBJ, &cm_ubus_id.network_id)) {
usleep(100 * 1000);
}
else
break;
} while (retries++ < MAX_RETRY_TIMES);
if (retries >= MAX_RETRY_TIMES) {
CM_Log_E(dialer_init4, "dialer_init, Failed to look up network object\n");
goto fail;
}
/*
//get id of odhcpd object
if (ubus_lookup_id(cm_ctx, UCI_ODHCPD_OBJ, &cm_ubus_id.odhcpd_id)) {
CM_Log_E("%s, Failed to look up UCI_ODHCPD_OBJ\n", __func__);
goto fail;
}
*/
//get id of network.interface object
if (ubus_lookup_id(cm_ctx, UBUS_NETWORK_IF_OBJ, &cm_ubus_id.network_interface_id)) {
goto fail;
}
//get id of cm object
if (ubus_lookup_id(cm_ctx, CMName, &cm_ubus_id.cm_id)) {
goto fail;
}
dialer_init_sim2_base_cid();
dialer_load_network_lan(&network_lan_data);
CM_Log(dialer_init7, "dialer_init: delete IP info in network\n");
#if defined(CM_DELETE_IPINFO)
for (i = 0; i < 8; i++) {
//delete network configuration for all ccinet interface
DeleteIPInfo(i, IPV4);
DeleteIPInfo(i, IPV6);
}
delete_route_info();
reload_network(true);
#endif
cm_query_admindata();
return 0;
fail:
CM_Log(dialer_init8, "fail leave dialer_init\n");
return -1;
}
void showPFInfo(PacketFilterInfo * PF_info)
{
int i;
char ipbuf[68] = { 0 };
char tmp[8] = { 0 };
if (PF_info) {
CM_Log(showPFInfo, "<<<< showPFInfo START\n");
CM_Log(showPFInfo2, "CID [%d], direction [%d], pfIdx [%d], epIdx [%d], IPType [%d]\n", PF_info->secondaryCid, PF_info->direction, PF_info->PfIdx, PF_info->EpIdx, PF_info->IPType);
if (PF_info->localPortRangePresent)
{
CM_Log(showPFInfo7, "showPFInfo localPort Ranges from %d to %d\n", PF_info->localPortRange.min,
PF_info->localPortRange.max);
}
if (PF_info->remotePortRangePresent)
{
CM_Log(showPFInfo9, "RemotePort Ranges from %d to %d\n", PF_info->remotePortRange.min,
PF_info->remotePortRange.max);
}
if (PF_info->pnNextHdrPresent)
{
CM_Log(showPFInfo11, "pnNextHdr is %d\n", PF_info->pnNextHdr);
}
if (PF_info->FlowLablePresent)
{
CM_Log(showPFInfo13, "FlowLable is %d\n", PF_info->FlowLable);
}
if (PF_info->SpiPresent)
{
CM_Log(showPFInfo15, "Spi is %d\n", PF_info->SPI);
}
if (PF_info->TosPresent)
{
CM_Log(showPFInfo17, "Tos is %d, Tos mask is %d\n", PF_info->Tos, PF_info->TosMask);
}
if (PF_info->RemoteAddressPresent)
{
sprintf(ipbuf, "%d", PF_info->RemoteAddress[0]);
for (i = 1; i < 16; i++) {
sprintf(tmp, ".%d", PF_info->RemoteAddress[i]);
strcat(ipbuf, tmp);
}
CM_Log(showPFInfo19, "RemoteAddress is %s\n", ipbuf);
}
memset(ipbuf, 0, 68);
if (PF_info->SubnetMaskPresent)
{
sprintf(ipbuf, "%d", PF_info->SubnetMask[0]);
for (i = 1; i < 16; i++) {
sprintf(tmp, ".%d", PF_info->SubnetMask[i]);
strcat(ipbuf, tmp);
}
}
CM_Log(showPFInfo20, "SubnetMask is %s\n", ipbuf);
CM_Log(showPFInfo21, "showPFInfo END >>>>\n");
} else {
CM_Log(showPFInfo22, "showPFInfo: pf_info is NULL\n");
}
}
void showConContext(CM_Connection_Context * Pdp)
{
if (Pdp == NULL) {
CM_Log_E(showConContext, "exit showConContext: pdp is NULL\n");
return;
}
CM_Log(showConContext1, "showConContext: START\n");
CM_Log(showConContext2, "showConContext: PDP_name %s\n", Pdp->pdpinfo->PDP_name);
CM_Log(showConContext3, "connectstatus %d, connectionNum %d, PDP_Type %d, IP_Type %d, PrimaryCID %d, SecondaryCID %d, QCI %d\n", Pdp->connectStatus, Pdp->pdpinfo->connectionNum,
Pdp->pdpinfo->PDP_Type, Pdp->pdpinfo->IP_Type, Pdp->pdpinfo->primaryCid, Pdp->pdpinfo->secondaryCid, Pdp->pdpinfo->QCI);
CM_Log(showConContext4, "APN %s, LTE_APN %s, Usr2G3G %s, PASWD2G3G %s, Authtype2G3G %s, Usr4G %s, PASWD4G %s, Authtype4G %s\n", Pdp->pdpinfo->APN, Pdp->pdpinfo->LteAPN,
Pdp->pdpinfo->Usr2G3G, Pdp->pdpinfo->PASWD2G3G, Pdp->pdpinfo->Authtype2G3G, Pdp->pdpinfo->Usr4G, Pdp->pdpinfo->PASWD4G, Pdp->pdpinfo->Authtype4G);
CM_Log(showConContext5, "dialfailurecode %d, autoapn %d, data_on_roaming %d, autoconnect %d\n", Pdp->dialFailureCode, Pdp->pdpinfo->autoapn, Pdp->pdpinfo->data_on_roaming, Pdp->pdpinfo->autoconnect);
showPFInfo(Pdp->tftinfo);
CM_Log(showConContext6, "showConContext: END\n");
}
void showDataCallResponse(Data_Call_Response_List * DcRsp)
{
Data_Call_Response_List *Ptr = NULL;
int i = 0, j = 0;
Ptr = DcRsp;
if (Ptr == NULL) {
return;
}
if (Ptr != NULL) {
CM_Log(showDataCallResponse1, "showDataCallResponse: START");
CM_Log(showDataCallResponse2, "list[%d]: cid %d, status %d, IP_Type %d, suggestedRetryTime %d, apn [%s]\n", j, Ptr->PDP.cid, Ptr->PDP.status,
Ptr->PDP.IP_Type, Ptr->PDP.suggestedRetryTime, Ptr->PDP.apn);
if (Ptr->PDP.ipv4info) {
CM_Log(showDataCallResponse3, "IPV4 Addr [%u.%u.%u.%u], PrimaryDNS [%u.%u.%u.%u], SecondaryDNS [%u.%u.%u.%u], Mask[%X], GateWay [%u.%u.%u.%u]\n",
(Ptr->PDP.ipv4info->IPAddr & 0xff), (Ptr->PDP.ipv4info->IPAddr & 0xff00) >> 8, (Ptr->PDP.ipv4info->IPAddr & 0xff0000) >> 16, (Ptr->PDP.ipv4info->IPAddr & 0xff000000) >> 24,
(Ptr->PDP.ipv4info->PrimaryDNS & 0xff), (Ptr->PDP.ipv4info->PrimaryDNS & 0xff00) >> 8, (Ptr->PDP.ipv4info->PrimaryDNS & 0xff0000) >> 16, (Ptr->PDP.ipv4info->PrimaryDNS & 0xff000000) >> 24,
(Ptr->PDP.ipv4info->SecondaryDNS & 0xff), (Ptr->PDP.ipv4info->SecondaryDNS & 0xff00) >> 8, (Ptr->PDP.ipv4info->SecondaryDNS & 0xff0000) >> 16, (Ptr->PDP.ipv4info->SecondaryDNS & 0xff000000) >> 24,
(Ptr->PDP.ipv4info->Mask),
(Ptr->PDP.ipv4info->GateWay & 0xff), (Ptr->PDP.ipv4info->GateWay & 0xff00) >> 8, (Ptr->PDP.ipv4info->GateWay & 0xff0000) >> 16, (Ptr->PDP.ipv4info->GateWay & 0xff000000) >> 24);
}
if (Ptr->PDP.ipv6info) {
for (i = 0; i < 4; i++) {
CM_Log(showDataCallResponse9, "IPV6 Addr[%d]=%X\n", i, Ptr->PDP.ipv6info->IPV6Addr[i]);
}
for (i = 0; i < 4; i++) {
CM_Log(showDataCallResponse10, "IPV6 PrimaryDns[%d]=%X\n", i, Ptr->PDP.ipv6info->PrimaryDNS[i]);
}
for (i = 0; i < 4; i++) {
CM_Log(showDataCallResponse11, "IPV6 SecondaryDns[%d]=%X\n", i, Ptr->PDP.ipv6info->SecondaryDNS[i]);
}
for (i = 0; i < 4; i++) {
CM_Log(showDataCallResponse12, "IPV6 Mask[%d]=%X\n", i, Ptr->PDP.ipv6info->Mask[i]);
}
for (i = 0; i < 4; i++) {
CM_Log(showDataCallResponse13, "IPV6 GateWay[%d]=%X\n", i, Ptr->PDP.ipv6info->GateWay[i]);
}
}
j++;
Ptr = Ptr->next;
}
CM_Log(showDataCallResponse15, "showDataCallResponse: END\n");
}
void FreeDataCallRsponseList(Data_Call_Response_List * pList)
{
Data_Call_Response_List *pdp = NULL;
Data_Call_Response_List *pdptmp = NULL;
if (pList == NULL)
return;
for (pdp = pList; pdp != NULL;) {
pdptmp = pdp->next;
if (pdp->PDP.ipv4info) {
free(pdp->PDP.ipv4info);
pdp->PDP.ipv4info = NULL;
}
if (pdp->PDP.ipv6info) {
free(pdp->PDP.ipv6info);
pdp->PDP.ipv6info = NULL;
}
free(pdp);
pdp = pdptmp;
}
CM_Log(FreeDataCallRsponseList1, "FreeDataCallRsponseList: done\n");
}
void configure_pdp_para(Ubus_Data_Call_Response * src, Data_Call_Response_List * dst, char *item)
{
char *tmpPtr[3] = { NULL };
char *ip4 = NULL;
char *ip4_1 = NULL;
char *ip6 = NULL;
char *ip6_1 = NULL;
char *src_para = NULL;
void *dst_para_v4 = NULL;
void *dst_para_v4_1 = NULL;
void *dst_para_v6 = NULL;
void *dst_para_v6_1 = NULL;
int protocol = 1;
int i = 0;
bool dns_v6_exist = false;
protocol = dst->PDP.IP_Type;
//define source and destination parameter
if (strcmp(item, "addr") == 0) {
src_para = src->addresses;
if ((protocol == IPV4) || (protocol == IPV4V6))
dst_para_v4 = &(dst->PDP.ipv4info->IPAddr);
if ((protocol == IPV6) || (protocol == IPV4V6))
dst_para_v6 = dst->PDP.ipv6info->IPV6Addr;
} else if (strcmp(item, "gateway") == 0) {
src_para = src->gateways;
if ((protocol == IPV4) || (protocol == IPV4V6))
dst_para_v4 = &(dst->PDP.ipv4info->GateWay);
if ((protocol == IPV6) || (protocol == IPV4V6))
dst_para_v6 = dst->PDP.ipv6info->GateWay;
} else if (strcmp(item, "dns") == 0) {
src_para = src->dnses;
if ((protocol == IPV4) || (protocol == IPV4V6)) {
dst_para_v4 = &(dst->PDP.ipv4info->PrimaryDNS);
dst_para_v4_1 = &(dst->PDP.ipv4info->SecondaryDNS);
}
if ((protocol == IPV6) || (protocol == IPV4V6)) {
dst_para_v6 = dst->PDP.ipv6info->PrimaryDNS;
dst_para_v6_1 = dst->PDP.ipv6info->SecondaryDNS;
}
}
//parse parameter in input string
ip4 = src_para;
if(src_para)
tmpPtr[0] = strchr(src_para, ' ');
if (!tmpPtr[0]) {
return;
}
*tmpPtr[0] = '\0';
ip6 = tmpPtr[0] + 1;
if (strcmp(item, "dns") == 0) {
if (protocol == IPV4)
ip4_1 = ip6;
else if (protocol == IPV6) {
ip6_1 = ip6;
ip6 = ip4;
dns_v6_exist = true;
} else if (protocol == IPV4V6) {
ip4_1 = tmpPtr[0] + 1;
tmpPtr[1] = strchr(ip4_1, ' ');
if (!tmpPtr[1]) {
ip6 = NULL;
goto CONFIG;
}
*tmpPtr[1] = '\0';
ip6 = tmpPtr[1] + 1;
tmpPtr[2] = strchr(ip6, ' ');
if (!tmpPtr[2]) {
goto CONFIG;
}
dns_v6_exist = true;
*tmpPtr[2] = '\0';
ip6_1 = tmpPtr[2] + 1;
}
}
CONFIG:
//get IPV4 parameter.
if (dst_para_v4 && ((protocol == IPV4) || (protocol == IPV4V6))) {
inet_pton(AF_INET, ip4, dst_para_v4);
if (dst_para_v4_1 && (strcmp(item, "dns") == 0)) {
inet_pton(AF_INET, ip4_1, dst_para_v4_1);
}
}
//get ipv6 parameter
if ((protocol == IPV6) || (protocol == IPV4V6)) {
if (ip6 && dst_para_v6)
inet_pton(AF_INET6, ip6, dst_para_v6);
if (dst_para_v6_1 && (strcmp(item, "dns") == 0) && dns_v6_exist) {
inet_pton(AF_INET6, ip6_1, dst_para_v6_1);
}
}
for (i = 0; i < 3; i++) {
if (tmpPtr[i])
*tmpPtr[i] = ' ';
}
CM_Log(configure_pdp_para3, "configure_pdp_para: config item %s done", item);
}
void CreateDataCallResponseList(CM_Connection_Context *setupCtx, Ubus_Data_Call_Response * SrcData, int SrcDataLen, int cid)
{
Data_Call_Response_List *Dstpdp = NULL;
Ubus_Data_Call_Response *ptr = NULL;
int i = 0;
int len = 0;
int eps_ip_type = 0;
for (ptr = SrcData, len = 0; len < SrcDataLen; len += sizeof(Ubus_Data_Call_Response), ptr++) {
if (i == 0) {
if (DataCallRsponseList) {
FreeDataCallRsponseList(DataCallRsponseList);
DataCallRsponseList = NULL;
}
Dstpdp = malloc(sizeof(Data_Call_Response_List));
if (!Dstpdp) {
return;
}
DataCallRsponseList = Dstpdp;
} else {
Dstpdp->next = malloc(sizeof(Data_Call_Response_List));
if (!Dstpdp->next) {
return;
}
Dstpdp = Dstpdp->next;
}
memset(Dstpdp, 0, sizeof(Data_Call_Response_List));
Dstpdp->next = NULL;
Dstpdp->PDP.cid = ptr->cid;
Dstpdp->PDP.v6_partner_cid = ptr->v6_parnter_cid;
if (setupCtx && setupCtx->pdpinfo->parent_cid > 0)
Dstpdp->PDP.parent_cid = setupCtx->pdpinfo->parent_cid;
eps_ip_type = ConvertIPType(ptr->type);
if (setupCtx && ptr->cid == cid)
{
if (setupCtx->pdpinfo->IP_Type == IPV4V6 &&
(eps_ip_type == IPV4 || eps_ip_type == IPV6))
Dstpdp->PDP.IP_Type = eps_ip_type;
else
Dstpdp->PDP.IP_Type = setupCtx->pdpinfo->IP_Type;
}
else
Dstpdp->PDP.IP_Type = eps_ip_type;
if (setupCtx)
setupCtx->pdpinfo->eps_ipType = eps_ip_type;
Dstpdp->PDP.status = ptr->status;
Dstpdp->PDP.suggestedRetryTime = ptr->suggestedRetryTime;
strcpy(Dstpdp->PDP.apn, ptr->apn);
/*Network indicate the MTU form PCO*/
if (ptr->mtu > 0 )
Dstpdp->PDP.mtu = ptr->mtu;
CM_Log(CreateDataCallResponseList2, "CreateDataCallResponseList: index[%d]:cid %d (v6_partner_cid %d), eps IP_Type %d(%s), setup IP_Type %d, status %d, suggestedRetryTime %d, nw mtu %d, apn [%s]\n", i,\
Dstpdp->PDP.cid, Dstpdp->PDP.v6_partner_cid, eps_ip_type, ptr->type, setupCtx ? ( setupCtx->pdpinfo->IP_Type) : -1, Dstpdp->PDP.status, Dstpdp->PDP.suggestedRetryTime, Dstpdp->PDP.mtu, Dstpdp->PDP.apn);
if ((Dstpdp->PDP.IP_Type == IPV4) || (Dstpdp->PDP.IP_Type == IPV4V6)) //IPV4 or IPV4V6
{
if (Dstpdp->PDP.ipv4info == NULL) {
Dstpdp->PDP.ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (!Dstpdp->PDP.ipv4info) {
return;
}
memset(Dstpdp->PDP.ipv4info, 0, sizeof(Ipv4Info));
}
}
if ((Dstpdp->PDP.IP_Type == IPV6) || (Dstpdp->PDP.IP_Type == IPV4V6)) //IPV6 or IPV4V6
{
if (Dstpdp->PDP.ipv6info == NULL) {
Dstpdp->PDP.ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (!Dstpdp->PDP.ipv6info) {
return;
}
memset(Dstpdp->PDP.ipv6info, 0, sizeof(Ipv6Info));
}
}
if (Dstpdp->PDP.v6_partner_cid > 0)
{
if (Dstpdp->PDP.ipv6info == NULL) {
Dstpdp->PDP.ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (!Dstpdp->PDP.ipv6info) {
return;
}
memset(Dstpdp->PDP.ipv6info, 0, sizeof(Ipv6Info));
}
}
configure_pdp_para(ptr, Dstpdp, "addr");
configure_pdp_para(ptr, Dstpdp, "gateway");
configure_pdp_para(ptr, Dstpdp, "dns");
CM_Log(CreateDataCallResponseList1040, "CreateDataCallResponseList: setup cid%d, list cid %d\n", cid, ptr->cid);
if (ptr->cid == cid) {
DataCallRsp.cid = Dstpdp->PDP.cid;
DataCallRsp.v6_partner_cid = Dstpdp->PDP.v6_partner_cid;
DataCallRsp.parent_cid = Dstpdp->PDP.parent_cid;
DataCallRsp.suggestedRetryTime = Dstpdp->PDP.suggestedRetryTime;
DataCallRsp.IP_Type = Dstpdp->PDP.IP_Type;
DataCallRsp.status = dialerReasonCode;
strcpy(DataCallRsp.apn, Dstpdp->PDP.apn);
dialer_remove_apn_suffix(DataCallRsp.apn);
if (cm_get_nw_status_cache() == CM_NW_STATUS_LTE)
cm_save_default_apn(NULL, DataCallRsp.apn);
else
cm_save_default_apn(DataCallRsp.apn, NULL);
if (Dstpdp->PDP.mtu > 0 && (DataCallRsp.mtu == 0 ||Dstpdp->PDP.mtu < DataCallRsp.mtu))
DataCallRsp.mtu = Dstpdp->PDP.mtu;
CM_Log(CreateDataCallResponseList1300, "CreateDataCallResponseList: setup cid[%d],v6_partner_cid[%d],parent_cid[%d],suggestedRetryTime[%d], IP_Type[%d],apn[%s], status[%d]\n",
DataCallRsp.cid, DataCallRsp.v6_partner_cid, DataCallRsp.parent_cid, DataCallRsp.suggestedRetryTime, DataCallRsp.IP_Type, DataCallRsp.apn, DataCallRsp.status);
if (Dstpdp->PDP.ipv4info != NULL) {
if (DataCallRsp.ipv4info == NULL) {
DataCallRsp.ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (!DataCallRsp.ipv4info) {
return;
}
memset(DataCallRsp.ipv4info, 0, sizeof(Ipv4Info));
}
memcpy(DataCallRsp.ipv4info, Dstpdp->PDP.ipv4info, sizeof(Ipv4Info));
} else {
if (DataCallRsp.ipv4info != NULL)
{
free(DataCallRsp.ipv4info);
DataCallRsp.ipv4info = NULL;
}
}
if (Dstpdp->PDP.ipv6info != NULL) {
if (DataCallRsp.ipv6info == NULL) {
DataCallRsp.ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (!DataCallRsp.ipv6info) {
return;
}
memset(DataCallRsp.ipv6info, 0, sizeof(Ipv6Info));
}
memcpy(DataCallRsp.ipv6info, Dstpdp->PDP.ipv6info, sizeof(Ipv6Info));
} else {
if (DataCallRsp.ipv6info != NULL)
{
free(DataCallRsp.ipv6info);
DataCallRsp.ipv6info = NULL;
}
}
}
i++;
}
showDataCallResponse(DataCallRsponseList);
return;
}
unsigned char setUnknownPpdCause(unsigned char setVaue)
{
UnknownPdpCause = setVaue;
CM_Log(setUnknownPpdCause, "setUnknownPpdCause: UnknownPdpCause is %d\n", UnknownPdpCause);
return 0;
}
unsigned char getUnknownPpdCause(void)
{
CM_Log(getUnknownPpdCause, "getUnknownPpdCause: UnknownPdpCause is %d\n", UnknownPdpCause);
return UnknownPdpCause;
}
void clearUnknownPpdCause(void)
{
UnknownPdpCause = 0; //CIRC_PS_SUCCESS;
CM_Log(clearUnknownPpdCause, "clearUnknownPpdCause: UnknownPdpCause is %d\n", UnknownPdpCause);
}
bool getErrorIndFlag()
{
CM_Log(getErrorIndFlag, "getErrorIndFlag: ErrorIndFlag is %d\n", ErrorIndFlag);
return ErrorIndFlag;
}
void clearErrorIndFlag()
{
ErrorIndFlag = FALSE;
CM_Log(clearErrorIndFlag, "clearErrorIndFlag: ErrorIndFlag is %d\n", ErrorIndFlag);
}
/* cid matched with ccinet */
int cm_get_current_cid(void)
{
int cid = CMCurrentCid - 1;
if (!isMasterSim0() && cid < get_sim2_base_cid())
cid += get_sim2_base_cid();
return cid;
}
// get global ipv6 address
int getInterfaceAddr6(const char *ifname, char *ipaddress, size_t ipsize)
{
int ret = -1;
char devname[20];
int plen, scope, dad_status, if_idx;
char addr6p[8][5];
char strprefix[INET6_ADDRSTRLEN];
int i, len = 0;
char cmd[128];
char rsp[128];
struct in6_addr addr6;
FILE *f = fopen(PATH_PROC_IFINET6, "r");
if (f == NULL) {
CM_Log_E(getInterfaceAddr6, "Cannot open file: %s", PATH_PROC_IFINET6);
goto exit;
}
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
addr6p[5], addr6p[6], addr6p[7], &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
if (!strcmp(devname, ifname)) {
if ((scope & IPV6_ADDR_SCOPE_MASK) == 0) {
snprintf(ipaddress, ipsize, "%s:%s:%s:%s:%s:%s:%s:%s",
addr6p[0], addr6p[1], addr6p[2], addr6p[3],
addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
CM_Log(getInterfaceAddr61, "%s Global inet6 addr: %s/%d", ifname, ipaddress, plen);
for (i = 0; i < plen / 16; i++)
len += snprintf(strprefix + len, ipsize - len, "%s:", addr6p[i]);
len += snprintf(strprefix + len, ipsize - len, ":");
inet_pton(AF_INET6, strprefix, &addr6);
inet_ntop(AF_INET6, &addr6, strprefix, INET6_ADDRSTRLEN);
len = strlen(strprefix);
snprintf(strprefix + len, ipsize - len, "/%d", plen);
snprintf(cmd, sizeof(cmd), "uci set network.wan%s.ip6prefix=%s", ifname + 6, strprefix);
cm_system(cmd, rsp, sizeof(rsp));
snprintf(cmd, sizeof(cmd), "uci commit network && /etc/init.d/network reload");
cm_system(cmd, rsp, sizeof(rsp));
ret = 0;
break;
}
}
}
fclose(f);
exit:
return ret;
}
int get_current_cid(void)
{
return CMCurrentCid;
}
Data_Call_Response *StartDialer(CM_Connection_Context * ConInfo)
{
int roam_iptype = 0;
#ifdef CONFIG_ZGDCONT_MULTI_PDP
char tmp[16] = { 0 };
#endif
if (ConInfo == NULL ||ConInfo->pdpinfo == NULL) {
CM_Log_E(StartDialer, "StartDialer: no connection context\n");
return NULL;
}
roam_iptype = cm_get_zroam_iptype();
if (roam_iptype > 0) {
if (roam_iptype == 3)
ConInfo->pdpinfo->IP_Type = 0;
else
ConInfo->pdpinfo->IP_Type = roam_iptype;
}
if (matchApnNetworkIdentifier(ConInfo->pdpinfo->APN, dialer_get_default_apn()))
{
if (get_ipv4_only_allowed())
{
ConInfo->pdpinfo->IP_Type = 1;
goto dialer;
}
else if (get_ipv6_only_allowed())
{
ConInfo->pdpinfo->IP_Type = 2;
goto dialer;
}
}
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (ConInfo->pdpinfo->connectionNum == 0 && ConInfo->pdpinfo->autoconnect)
{
if (!matchApnNetworkIdentifier(ConInfo->pdpinfo->LteAPN, dialer_get_default_apn()) ||
ConInfo->pdpinfo->IP_Type != dialer_get_default_iptype())
{
if (dialer_get_default_apn())
{
/* APN may correct by network, if APN and lteAPN not same, means APN has been corrected by network
*/
if (!matchApnNetworkIdentifier(ConInfo->pdpinfo->APN, ConInfo->pdpinfo->LteAPN))
{
CM_Log(StartDialer1272, "StartDialer: configure APN [%s], network APN [%s] \n", ConInfo->pdpinfo->LteAPN, ConInfo->pdpinfo->APN);
if (strlen(ConInfo->pdpinfo->APN) != 0 && strlen(ConInfo->pdpinfo->LteAPN) != 0)
{
CM_Log(StartDialer1274, "StartDialer: default apn may changed [%s] -> [%s] \n", ConInfo->pdpinfo->LteAPN, dialer_get_default_apn());
strcpy(ConInfo->pdpinfo->APN, dialer_get_default_apn());
strcpy(ConInfo->pdpinfo->LteAPN, dialer_get_default_apn());
}
}
}
#if 0
if (dialer_get_default_iptype() != -1)
{
CM_Log(StartDialer1282, "StartDialer: default iptype may changed [%d] -> [%d] \n", ConInfo->pdpinfo->IP_Type, dialer_get_default_iptype());
ConInfo->pdpinfo->IP_Type = dialer_get_default_iptype();
}
#endif
}
}
if (ConInfo->pdpinfo->autoconnect && ConInfo->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY)
{
if (ConInfo->pdpinfo->connectionNum == 0)
snprintf(tmp, sizeof(tmp) - 1, "%d", CM_DEFAULT_ATTACH_CID);
else
snprintf(tmp, sizeof(tmp) - 1, "%d", ConInfo->pdpinfo->connectionNum);
property_set(PROP_DEFINED_CID, tmp);
CM_Log(StartDialer1290, "StartDialer: set defined cid to %s for auto connect\n", tmp);
}
#endif
dialer:
CM_Log(StartDialer1, "StartDialer: call dialer function\n");
CMCurrentCid = -1;
dialer_function(ConInfo);
if (CMCurrentCid != -1) {
QueryDataCall(ConInfo);
}
else {
/* setup fail with cause, notify*/
cm_notify_dial_failure(ConInfo->pdpinfo->connectionNum, -1, DataCallRsp.status);
}
if ((DataCallRsp.status == 0) && ((DataCallRsp.IP_Type == IPV4V6) || (DataCallRsp.IP_Type == IPV6))) {
reload_network(true);
}
return &DataCallRsp;
}
void dialer_MT_function_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
UNUSED(msg);
}
void dialer_MT_function(CM_Connection_Context * ConInfo)
{
Dialer_Connection_Context DialerSetupInfo;
int ret_val = UBUS_STATUS_OK;
blob_buf_init(&cm_b, 0);
blobmsg_add_u32(&cm_b, "reqid", RIL_REQUEST_SET_INITIAL_ATTACH_APN);
memset(&DialerSetupInfo, 0, sizeof(Dialer_Connection_Context));
// DialerSetupInfo.connectionNum = ConInfo->connectionNum;
DialerSetupInfo.connectStatus = ConInfo->connectStatus;
DialerSetupInfo.dialFailureCode = ConInfo->dialFailureCode;
DialerSetupInfo.retryTime = ConInfo->retryTime;
//memcpy(DialerSetupInfo.PDP_name, ConInfo->PDP_name, strlen(ConInfo->PDP_name)>63?63:strlen(ConInfo->PDP_name));
memcpy(&(DialerSetupInfo.pdpinfo), ConInfo->pdpinfo, sizeof(PdpInfo));
memcpy(&(DialerSetupInfo.tftinfo), ConInfo->tftinfo, sizeof(PacketFilterInfo));
blob_put(&cm_b, 0, &DialerSetupInfo, sizeof(Dialer_Connection_Context));
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, dialer_MT_function_data_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(dialer_MT_function1, "dialer_MT_function, ubus_invoke RIL_REQUEST_SET_INITIAL_ATTACH_APN failed %s\n",
ubus_strerror(ret_val));
}
CM_Log(dialer_MT_function2, "dialer_MT_function done\n");
}
Data_Call_Response *StartMTDialer(CM_Connection_Context * ConInfo)
{
dialer_MT_function(ConInfo);
dialer_function(ConInfo);
//sendDialResponse(dialerReasonCode);
CM_Log(StartMTDialer1, "StartMTDialer done\n");
return &DataCallRsp;
}
void StopDialer_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
UNUSED(msg);
}
void StopDialer(int cid)
{
char tmp[16];
int ret_val = UBUS_STATUS_OK;
rilutilstrings data = { 0 };
CM_Log(StopDialer, "StopDialer: cid %d\n", cid);
if (cid <= 0)
{
CM_Log_E(StopDialer1446, "StopDialer: cid %d no need stop\n", cid);
return;
}
DeleteIPInfo(cid-1, IPV4);
DeleteIPInfo(cid-1, IPV6);
blob_buf_init(&cm_b, 0);
data.num = 1;
data.str = (char **)malloc(data.num * sizeof(char *));
if (!data.str)
return;
snprintf(tmp, sizeof(tmp) - 1, "%d", cid);
data.str[0] = tmp;
#if 0
blobmsg_add_u32(&cm_b, "reqid", RIL_REQUEST_DEACTIVATE_DATA_CALL);
snprintf(tmp, sizeof(tmp) - 1, "%d", cid);
blob_put(&cm_b, 0, tmp, strlen(tmp) + 1);
#endif
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_DEACTIVATE_DATA_CALL, (void *)&data, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, StopDialer_data_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(StopDialer1, "StopDialer, ubus_invoke RIL_REQUEST_DEACTIVATE_DATA_CALL failed %s\n",
ubus_strerror(ret_val));
}
if (data.str)
free(data.str);
}
void DialerUpdateTFT_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
UNUSED(msg);
}
void DialerUpdateTFT(PacketFilterInfo * PF_info)
{
UNUSED(PF_info);
#if 0
int ret_val = UBUS_STATUS_OK;
blob_buf_init(&cm_b, 0);
blobmsg_add_u32(&cm_b, "reqid", RIL_REQUEST_CONFIGURE_TFT);
blob_put(&cm_b, 0, PF_info, sizeof(PacketFilterInfo));
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, DialerUpdateTFT_data_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(DialerUpdateTFT1, "DialerUpdateTFT, ubus_invoke RIL_REQUEST_CONFIGURE_TFT failed %s\n", ubus_strerror(ret_val));
}
#endif
CM_Log(DialerUpdateTFT2, "DialerUpdateTFT done\n");
}
/*===========================================================================
FUNCTION dialer_function
DESCRIPTION
Initializing a at client.
This function must be called exactly once on a client object before
it is being used, in any way, place, or form.
In case this function is called more than once, then same client data structure
gets reallocated.
Note that in order to get notified of at response, a client still needs
to do the following:
1. Register its callback functions and specific events with each functional group
DEPENDENCIES
none
RETURN VALUE
return staus
SIDE EFFECTS
none
===========================================================================*/
void dialer_function(CM_Connection_Context * ConInfo)
{
//CheckDataCallRegisterStatus();
DataCallRsp.status = PDP_FAIL_ERROR_UNSPECIFIED;
DataCallRsp.mtu = ConInfo->pdpinfo->mtu;
if (ConInfo->pdpinfo->PDP_Type == 1) //default bearer
SetupDataCall(ConInfo);
else if (ConInfo->pdpinfo->PDP_Type == 0) //dedicated bearer
SetupDedicatedDataCall(ConInfo);
return;
}
void SetupDataCall_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
Ubus_Data_Call_Response *rsp = NULL;
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, (void **)&response_data, &response_len)) {
CM_Log_E(SetupDataCall_data_cb, "Parse failed\n");
return;
}
if (requestid != RIL_REQUEST_SETUP_DATA_CALL) {
CM_Log_E(SetupDataCall_data_cb1, "The response not for the request\n");
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (rilerrno != 0) {
CM_Log_E(SetupDataCall_data_cb2, "exit SetupDataCall_data_cb: errorNo %d\n", rilerrno);
goto done;
}
rsp = (Ubus_Data_Call_Response *) response_data;
if (rilerrno == 0) {
dialerReasonCode = rsp->status;
DataCallRsp.status = rsp->status;
DataCallRsp.cid = rsp->cid;
if (dialerReasonCode == PDP_FAIL_NONE) {
CMCurrentCid = rsp->cid;
if (rsp->mtu && ( DataCallRsp.mtu == 0 || rsp->mtu < DataCallRsp.mtu))
DataCallRsp.mtu = rsp->mtu;
} else {
DataCallRsp.suggestedRetryTime = rsp->suggestedRetryTime;
}
}
CM_Log(SetupDataCall_data_cb3, "SetupDataCall_data_cb: rilerrno=%d, status %d, retryTime %d, CMCurrentCid %d, cid %d, mtu %d\n",
rilerrno, rsp->status, rsp->suggestedRetryTime, CMCurrentCid, rsp->cid, rsp->mtu);
CM_Log(SetupDataCall_data_cb4, "SetupDataCall_data_cb: IP Type %s, ip address %s\n", rsp->type, rsp->addresses);
done:
if (response_data)
rilutil_freeResponseData(requestid, response_data, response_len);
}
void SetInitialAttachAPN_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
UNUSED(msg);
}
void SetInitialAttachAPN(Apn_Info * apninfo, bool saveNVM)
{
RIL_InitialAttachApn *data;
int size;
int ret_val = UBUS_STATUS_OK;
blob_buf_init(&cm_b, 0);
size = 0;
data = (RIL_InitialAttachApn *) malloc(sizeof(RIL_InitialAttachApn));
if (!data) {
CM_Log_E(SetInitialAttachAPN, "SetInitialAttachAPN: malloc size %d failed\n", sizeof(RIL_InitialAttachApn));
return;
}
memset(data, 0, sizeof(RIL_InitialAttachApn));
if (strlen(apninfo->lte_apn) != 0) {
data->apn = (char *)malloc(strlen(apninfo->lte_apn) + 1);
if (!data->apn) {
CM_Log_E(SetInitialAttachAPN1, "SetInitialAttachAPN: malloc size %d failed\n", strlen(apninfo->lte_apn) + 1);
return;
}
memset(data->apn, 0, strlen(apninfo->lte_apn) + 1);
strcpy(data->apn, apninfo->lte_apn);
size += strlen(data->apn) + 1;
} else
data->apn = NULL;
//protocol
switch (apninfo->iptype) {
case IPV4V6:
data->protocol = strdup("IPV4V6");
break;
case IPV4:
data->protocol = strdup("IP");
break;
case IPV6:
data->protocol = strdup("IPV6");
break;
case TYPE_ETH:
data->protocol = strdup("ethernet");
break;
default:
CM_Log(SetInitialAttachAPN2, "SetInitialAttachAPN: unexpected IP_Type:%d", apninfo->iptype);
break;
}
if(data->protocol)
size += strlen(data->protocol) + 1;
data->authtype = convert_authtype_by_str((apninfo->lte_authtype));
size += sizeof(data->authtype);
if (data->authtype > 0)
{
if ((strlen(apninfo->lte_usrname) != 0) && strcmp(apninfo->lte_usrname, "any")) {
data->username = (char *)malloc(strlen(apninfo->lte_usrname) + 1);
if (!data->username) {
return;
}
memset(data->username, 0, strlen(apninfo->lte_usrname) + 1);
strcpy(data->username, apninfo->lte_usrname);
size += strlen(data->username) + 1;
} else
data->username = NULL;
if ((strlen(apninfo->lte_paswd) != 0) && strcmp(apninfo->lte_paswd, "any")) {
data->password = (char *)malloc(strlen(apninfo->lte_paswd) + 1);
if (!data->password) {
return;
}
memset(data->password, 0, strlen(apninfo->lte_paswd) + 1);
strcpy(data->password, apninfo->lte_paswd);
size += strlen(data->password) + 1;
} else
data->password = NULL;
}
data->saveNVM = saveNVM;
CM_Log(SetInitialAttachAPN5, "SetInitialAttachAPN: apn %s, protocol %s, authtype %d, username %s, password %s\n", data->apn, data->protocol, data->authtype,
data->username, data->password);
if (data->apn && data->protocol)
{
dialer_set_default_apn(NULL, data->apn, false);
dialer_set_default_iptype(apninfo->iptype);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SET_INITIAL_ATTACH_APN, (void *)data, size);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, SetInitialAttachAPN_data_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(SetInitialAttachAPN6, "SetInitialAttachAPN, ubus_invoke RIL_REQUEST_SET_INITIAL_ATTACH_APN failed %s\n",
ubus_strerror(ret_val));
}
}
if (data->apn)
free(data->apn);
if (data->protocol)
free(data->protocol);
if (data->username)
free(data->username);
if (data->password)
free(data->password);
free(data);
}
void SetupDataCall(CM_Connection_Context * ConInfo)
{
rilutilstrings data = { 0 };
int size = 0;
int num = 0;
int ret_val = UBUS_STATUS_OK;
int auth_type = 0;
int data_num_max = 8;
bool need_unlock = true;
pthread_mutex_lock(&cm_mutex);
CM_Log_D(SetupDataCall1901, "SetupDataCall: cm_mutex locked\n");
memset(&data, 0, sizeof(data));
if (!ConInfo || !CM_CheckContextValid(ConInfo))
goto end;
blob_buf_init(&cm_b, 0);
CM_Log_D(SetupDataCall, "SetupDataCall: apn %s, lteapn %s, ip type %d, mtu %d, cid %d\n",ConInfo->pdpinfo->APN, ConInfo->pdpinfo->LteAPN,
ConInfo->pdpinfo->IP_Type, ConInfo->pdpinfo->mtu, ConInfo->pdpinfo->primaryCid);
CM_Log_D(SetupDataCall1, "SetupDataCall: user %s, password %s, auth %s\n",ConInfo->pdpinfo->Usr2G3G, ConInfo->pdpinfo->PASWD2G3G,
ConInfo->pdpinfo->Authtype2G3G);
#ifdef CONFIG_CM_URSP
data_num_max += 3;
#endif
data.str = (char **)malloc(data_num_max * sizeof(char *));
if (!data.str) {
goto end;
}
//radio_technology
data.str[data.num++] = strdup("0");
//profile type
data.str[data.num++] = strdup("0");
//apn
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
//check network mode
if (NW_status == CM_NW_STATUS_LTE)
strcpy(data.str[data.num], ConInfo->pdpinfo->LteAPN);
else
strcpy(data.str[data.num], ConInfo->pdpinfo->APN);
data.num++;
//user
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
strcpy(data.str[data.num], ConInfo->pdpinfo->Usr2G3G);
data.num++;
//password
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
strcpy(data.str[data.num], ConInfo->pdpinfo->PASWD2G3G);
data.num++;
//auth
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
auth_type = convert_authtype_by_str(ConInfo->pdpinfo->Authtype2G3G);
sprintf(data.str[data.num], "%d", auth_type);
data.num++;
//IP type
switch (ConInfo->pdpinfo->IP_Type) {
case IPV4V6:
data.str[data.num] = strdup("IPV4V6");
break;
case IPV4:
data.str[data.num] = strdup("IP");
break;
case IPV6:
data.str[data.num] = strdup("IPV6");
break;
case TYPE_ETH:
data.str[data.num] = strdup("ethernet");
break;
default:
CM_Log_E(SetupDataCall7, "dispatchDataCall: unexpected IP_Type:%d", ConInfo->pdpinfo->IP_Type);
break;
}
data.num++;
#ifdef CONFIG_CM_URSP
int rsd_index = ConInfo->pdpinfo->rsd_index;
RSD *rsd = NULL;
CM_Log_D(SetupDataCall1692, "SetupDataCall: rsd_index %d", rsd_index);
if (rsd_index >= 0 && ConInfo->pdpinfo->ursp_list)
rsd = &(ConInfo->pdpinfo->ursp_list->ursp.matchedUrspInfo.rsd[rsd_index]);
//scc mode
if (rsd && rsd->rsdComponents.sscModePresent)
{
CM_Log_D(SetupDataCall1699, "SetupDataCall: sscMode %d", rsd->rsdComponents.sscMode);
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
sprintf(data.str[data.num], "%d", rsd->rsdComponents.sscMode);
}
else if (ConInfo->pdpinfo->config_rsd.sscModePresent)
{
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
sprintf(data.str[data.num], "%d", ConInfo->pdpinfo->config_rsd.sscMode);
}
else
{
data.str[data.num] = strdup("255");
}
data.num++;
//S-NSSAI
if (rsd && rsd->rsdComponents.snssaiPresent)
{
int index = 0;
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
CM_Log_D(SetupDataCall1722, "SetupDataCall: snssai[%d].length %d", index, rsd->rsdComponents.snssai[index].length);
switch ( rsd->rsdComponents.snssai[index].length )
{
case PS_SNSSAI_CONTENT_SST:
sprintf(data.str[data.num], "%02x", rsd->rsdComponents.snssai[index].sst);
break;
case PS_SNSSAI_CONTENT_SST_AND_MAPPED_HPLMN_SST:
sprintf(data.str[data.num], "%02x;%02x", rsd->rsdComponents.snssai[index].sst, rsd->rsdComponents.snssai[index].mappedSst);
break;
case PS_SNSSAI_CONTENT_SST_AND_SD:
sprintf(data.str[data.num], "%02x.%06x", rsd->rsdComponents.snssai[index].sst, rsd->rsdComponents.snssai[index].sd);
break;
case PS_SNSSAI_CONTENT_SST_SD_AND_MAPPED_HPLMN_SST:
sprintf(data.str[data.num], "%02x.%06x;%02x", rsd->rsdComponents.snssai[index].sst, rsd->rsdComponents.snssai[index].sd, rsd->rsdComponents.snssai[index].mappedSst);
break;
case PS_SNSSAI_CONTENT_SST_SD_AND_MAPPED_HPLMN_SST_SD:
sprintf(data.str[data.num], "%02x.%06x;%02x.%06x", rsd->rsdComponents.snssai[index].sst, rsd->rsdComponents.snssai[index].sd, rsd->rsdComponents.snssai[index].mappedSst, rsd->rsdComponents.snssai[index].mappedSd);
break;
default:
break;
}
}
else if (ConInfo->pdpinfo->config_rsd.snssaiPresent)
{
data.str[data.num] = strdup(ConInfo->pdpinfo->config_rsd.snssai);
}
else
{
data.str[data.num] = strdup("");
}
data.num++;
//prefer access type
if (rsd && rsd->rsdComponents.preferredAccessTypePresent)
{
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
sprintf(data.str[data.num], "%d", rsd->rsdComponents.preferredAccessType);
}
else if (ConInfo->pdpinfo->config_rsd.prefAccessTypePresent)
{
data.str[data.num] = (char *)malloc(MAX_STR_LEN);
if (!data.str[data.num]) {
goto end;
}
memset(data.str[data.num], 0, MAX_STR_LEN);
sprintf(data.str[data.num], "%d", ConInfo->pdpinfo->config_rsd.prefAccessType);
}
else
{
data.str[data.num] = strdup("255");
}
data.num++;
#endif
for (num = 0; num < data.num; num++) {
size += strlen(data.str[num]) + 1;
}
CMCurrentCid = -1;
DataCallRsp.status = PDP_FAIL_ERROR_UNSPECIFIED;
DataCallRsp.mtu = ConInfo->pdpinfo->mtu;
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SETUP_DATA_CALL, (void *)&data, size);
pthread_mutex_unlock(&cm_mutex);
CM_Log_D(SetupDataCall2077, "SetupDataCall: cm_mutex unlocked\n");
need_unlock = false;
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, SetupDataCall_data_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(SetupDataCall8, "SetupDataCall, ubus_invoke RIL_REQUEST_SETUP_DATA_CALL failed %s\n",
ubus_strerror(ret_val));
}
CM_Log(SetupDataCall1787, "SetupDataCall: data.num %d\n", data.num);
end:
//free data memory
for (num = 0; num < data.num; num++) {
if (data.str[num]) {
free(data.str[num]);
data.str[num] = NULL;
}
}
if (data.str != NULL)
free(data.str);
if (need_unlock) {
pthread_mutex_unlock(&cm_mutex);
CM_Log_D(SetupDataCall2103, "SetupDataCall: cm_mutex unlocked\n");
}
}
void SetupDedicatedDataCall(CM_Connection_Context * ConInfo)
{
int ret;
rilutilstrings data = { 0 };
char buf[MAX_STR_LEN] = { 0 };
blob_buf_init(&cm_b, 0);
data.num = 8;
data.str= (char **)malloc(data.num * sizeof(char *));
data.str[0] = "0";
data.str[1] = "0";
//check network mode
if (NW_status == CM_NW_STATUS_LTE)
{
data.str[2] = ConInfo->pdpinfo->LteAPN;
data.str[3] = ConInfo->pdpinfo->Usr4G;
data.str[4] = ConInfo->pdpinfo->PASWD4G;
data.str[5] = ConInfo->pdpinfo->Authtype4G;
}
else
{
data.str[2] = ConInfo->pdpinfo->APN;
data.str[3] = ConInfo->pdpinfo->Usr2G3G;
data.str[4] = ConInfo->pdpinfo->PASWD2G3G;
data.str[5] = ConInfo->pdpinfo->Authtype2G3G;
}
switch (ConInfo->pdpinfo->IP_Type) {
case IPV4V6:
data.str[6] = "IPV4V6";
break;
case IPV4:
data.str[6] = "IP";
break;
case IPV6:
data.str[6] = "IPV6";
break;
case TYPE_ETH:
data.str[6] = "ethernet";
break;
default:
data.str[6] = "IPV4V6";
break;
}
/* atcmd cid */
snprintf(buf, sizeof(buf), "%d", ConInfo->pdpinfo->primaryCid);
data.str[7] = buf;
/*UNUSED len*/
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SETUP_DATA_CALL_DEDICATED_BEARER, (void *)&data, 0);
CM_Log(SetupDedicatedDataCall, "SetupDedicatedDataCall: apn %s\n", data.str[2]);
/*sync */
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, SetupDataCall_data_cb, 0, 0); //timeout is 1min
if (ret != UBUS_STATUS_OK) {
CM_Log_E(SetupDedicatedDataCall1, "SetupDedicatedDataCall, ubus_invoke RIL_REQUEST_SETUP_DATA_CALL_DEDICATED_BEARER failed %s\n",
ubus_strerror(ret));
}
if (data.str)
free(data.str);
}
int g_brlan_up_triggered;
void cm_ifup_complete(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req && req->priv)
{
CM_Log(cm_ifup_complete1848, "cm_ifup_complete: interface cmd %d", *(int *)req->priv);
if (*(int *)req->priv == UP)
g_brlan_up_triggered = 0;
free(req->priv);
}
if (req) {
free(req);
req = NULL;
}
CM_Log(cm_ifup_complete, "cm_ifup_complete: interface up done!");
}
void cm_ifdown_complete(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req && req->priv)
{
CM_Log(cm_ifdown_complete1867, "cm_ifdown_complete: interface cmd %d", *(int *)req->priv);
if (*(int *)req->priv == UP)
{
if (g_brlan_up_triggered == 0)
{
up_down_br_lan(FORCEUP, "lan", 0);
}
}
free(req->priv);
}
if (req) {
free(req);
req = NULL;
}
CM_Log(cm_ifdown_complete, "cm_ifdown_complete: interface down done!");
}
int up_down_br_lan(if_command cmd, char* name, int sync)
{
int ret_val = 0;
char interface_name[16] = { 0 };
struct ubus_request *req = NULL;
int *priv_data = NULL;
if (cmd != DOWN && cmd != UP && cmd != FORCEUP)
return -1;
sprintf(interface_name, "%s", name);
CM_Log(up_down_br_lan1, "up_down_br_lan: cmd %d(0:down, 1:up), interface %s\n", cmd, interface_name);
blob_buf_init(&cm_b, 0);
blobmsg_add_string(&cm_b, "interface", interface_name);
if (sync)
{
if ((ret_val = ubus_invoke(cm_ctx, cm_ubus_id.network_interface_id, "down", cm_b.head, NULL,0, 0 )) != UBUS_STATUS_OK) {
CM_Log_E(up_down_br_lan1860, "exit up_down_br_lan: ifdown fail: %s\n", ubus_strerror(ret_val));
}
}
else if (cmd != FORCEUP)
{
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
ret_val = -2;
goto done;
}
memset(req, 0, sizeof(struct ubus_request));
priv_data = malloc(sizeof(int));
if (priv_data == NULL)
{
free(req);
ret_val = -2;
goto done;
}
*priv_data = cmd;
/* down first anyway*/
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.network_interface_id, "down", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(up_down_br_lan1875, "exit up_down_br_lan: ifdown fail: %s\n", ubus_strerror(ret_val));
if (priv_data)
free(priv_data);
free(req);
ret_val = -4;
goto done;
} else {
req->complete_cb = cm_ifdown_complete;
req->priv = priv_data;
ubus_complete_request_async(cm_ctx, req);
}
usleep(200*1000);
}
if (cmd == UP || cmd == FORCEUP) {
blob_buf_init(&cm_b, 0);
blobmsg_add_string(&cm_b, "interface", interface_name);
if (sync)
{
if ((ret_val =ubus_invoke(cm_ctx, cm_ubus_id.network_interface_id, "up", cm_b.head, NULL,0, 0 )) != UBUS_STATUS_OK) {
CM_Log_E(up_down_br_lan1891, "exit up_down_br_lan: ifup fail: %s\n", ubus_strerror(ret_val));
}
}
else
{
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
ret_val = -2;
goto done;
}
memset(req, 0, sizeof(struct ubus_request));
priv_data = malloc(sizeof(int));
if (priv_data == NULL)
{
free(req);
ret_val = -2;
goto done;
}
*priv_data = cmd;
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.network_interface_id, "up", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(up_down_br_lan1906, "exit up_down_br_lan: ifup fail: %s\n", ubus_strerror(ret_val));
if (priv_data)
free(priv_data);
free(req);
ret_val = -4;
goto done;
} else {
req->complete_cb = cm_ifup_complete;
req->priv = priv_data;
if (cmd == UP)
g_brlan_up_triggered = 1;
ubus_complete_request_async(cm_ctx, req);
}
}
}
done:
return ret_val;
}
#define PIPE_SYS_DEVICE "/sys/kernel/mpipe/devices"
/* check sys mode in pipe mode */
static bool pipe_ccinet_status_up(int cid, pdp_type protocol)
{
bool ret = false;
char status_path[MAX_STR_LEN] = { 0 };
char status[4] = { 0 };
FILE *fp = NULL;
char *line = NULL;
if (!pipe_mode)
return ret;
/* check status in sys fs */
if (protocol == IPV4)
snprintf(status_path, MAX_STR_LEN, "%s/ccinet%d/up", PIPE_SYS_DEVICE, cid);
else
snprintf(status_path, MAX_STR_LEN, "%s/ccinet%d/up6", PIPE_SYS_DEVICE, cid);
fp = fopen(status_path, "r");
if (!fp)
return ret;
line = fgets(status, sizeof(status), fp);
if (!line)
goto end;
CM_Log(pipe_ccinet_status_up, "%s: get status %s for ccinet%d with protocol %d\n", __func__, status, cid, protocol);
if (!strncmp(status, "1", 1))
ret = true;
end:
if (fp)
fclose(fp);
return ret;
}
int send_if_command(int cid, if_command cmd, pdp_type protocol)
{
int ret_val = 0;
char interface_name[16] = { 0 };
struct ubus_request *req = NULL;
if (cid >= MAX_CID_LIMITATION) {
CM_Log_E(send_if_command, "leave send_if_command: input cid is beyond limitation\n");
ret_val = -1;
goto done;
}
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
ret_val = -2;
goto done;
}
memset(req, 0, sizeof(struct ubus_request));
if (protocol == IPV4)
sprintf(interface_name, "wan%d", cid);
else if (protocol == IPV6)
sprintf(interface_name, "wan6%d", cid);
else {
CM_Log_E(send_if_command2, "send_if_command: unsupport iptype %d\n", protocol);
ret_val = -3;
goto done;
}
CM_Log(send_if_command3, "send_if_command: cid %d, cmd %d(0:down, 1:up), protocol %d(1:IPV4,2:IPV6), interface %s, status %d,%d\n",
cid, cmd, protocol, interface_name, V4_network_intf_status[cid], V6_network_intf_status[cid]);
blob_buf_init(&cm_b, 0);
blobmsg_add_string(&cm_b, "interface", interface_name);
if (cmd == DOWN) {
if ( ((protocol == IPV4 && V4_network_intf_status[cid] == 1) || (protocol == IPV6 && V6_network_intf_status[cid] == 1)) &&
pipe_ccinet_status_up(cid, protocol) == false) {
CM_Log_E(send_if_command1715, "send_if_command: interface has down\n");
} else {
if (protocol == IPV4) {
V4_network_intf_status[cid] = 1; // 1 for down
}
if (protocol == IPV6) {
V6_network_intf_status[cid] = 1; // 1 for down
}
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
ret_val = -2;
goto done;
}
memset(req, 0, sizeof(struct ubus_request));
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.network_interface_id, "down", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(send_if_command4, "exit send_if_command: ifdown fail: %s\n", ubus_strerror(ret_val));
free(req);
ret_val = -4;
goto done;
} else {
req->complete_cb = cm_ifdown_complete;
ubus_complete_request_async(cm_ctx, req);
CM_Log_E(send_if_command_down_0, "send_if_command:down interface for DOWN command!cmd=%d", cmd);
}
}
}
if (cmd == UP) {
if (protocol == IPV4) {
V4_network_intf_status[cid] = 0; // 1 for down
}
if (protocol == IPV6) {
V6_network_intf_status[cid] = 0; // 1 for down
}
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
ret_val = -2;
goto done;
}
//need to memset 20150717
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.network_interface_id, "up", cm_b.head,
req)) != UBUS_STATUS_OK) {
CM_Log_E(send_if_command6, "exit send_if_command: ifup fail: %s\n", ubus_strerror(ret_val));
free(req);
ret_val = -4;
goto done;
} else {
req->complete_cb = cm_ifup_complete;
ubus_complete_request_async(cm_ctx, req);
}
}
done:
return ret_val;
}
void reload_network_complete(struct ubus_request *req, int ret)
{
UNUSED(ret);
CM_Log(reload_network_complete, "reload_network_complete: reload network done!");
if (req)
free(req);
}
int reload_network(int sync)
{
int ret_val = 0;
struct ubus_request *req = NULL;
if (sync) {
if ((ret_val = ubus_invoke(cm_ctx, cm_ubus_id.network_id, "reload", NULL, NULL,0, 10*1000)) != UBUS_STATUS_OK) {
CM_Log_E(reload_network2345, "exit reload_network, [ERR] ubus_invoke fail: %s\n", ubus_strerror(ret_val));
return -1;
}
CM_Log(reload_network2347, "reload_network: done \n");
}
else
{
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
return -1;
}
memset(req, 0, sizeof(struct ubus_request));
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.network_id, "reload", NULL, req)) != UBUS_STATUS_OK) {
CM_Log_E(reload_network1, "reload_network: [ERR] ubus_invoke_async fail %s\n", ubus_strerror(ret_val));
free(req);
return -1;
}
req->complete_cb = reload_network_complete;
ubus_complete_request_async(cm_ctx, req);
}
return 0;
}
int reload_odhcpd()
{
char rsp[128];
static int count = 0;
if (count < 1000) {
cm_system("/etc/init.d/odhcpd reload", rsp, sizeof(rsp));
count += 1;
} else {
cm_system("/etc/init.d/odhcpd restart", rsp, sizeof(rsp));
cm_system("/etc/init.d/lighttpd restart", rsp, sizeof(rsp));
count = 0;
}
CM_Log(reload_odhcpd, "reload_odhcpd: reload odhcpd done!\n");
return 0;
}
void async_invoke_complete(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req)
free(req);
}
bool address_v6_null(int v6_address[])
{
int *p = v6_address;
int len = 0;
while (!*p && len < 4)
{
p++;
len++;
}
return (len == 4)?true:false;
}
int send_ip_info_request_2ril_async(RIL_IPDNSInfo *ip_info, int len)
{
int ret_val = 0;
struct ubus_request *req = NULL;
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
return -1;
}
memset(req, 0, sizeof(struct ubus_request));
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_REPORT_IP_DNS, (void *)ip_info, len);
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(send_ip_info_request_2ril_async1, "send_ip_info_request_2ril_async: [ERR] ubus_invoke fail %s\n", ubus_strerror(ret_val));
free(req);
return -1;
}
req->complete_cb = async_invoke_complete;
ubus_complete_request_async(cm_ctx, req);
return 0;
}
static int send_zgdcont_request_2ril_async(RIL_ZGDCONTInfo *ip_info, int len)
{
int ret_val = 0;
struct ubus_request *req = NULL;
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
return -1;
}
memset(req, 0, sizeof(struct ubus_request));
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_REPORT_ZGDCONT, (void *)ip_info, len);
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(send_zgdcont_request_2ril_async2, "send_zgdcont_request_2ril_async: [ERR] ubus_invoke fail %s\n", ubus_strerror(ret_val));
free(req);
return -1;
}
req->complete_cb = async_invoke_complete;
ubus_complete_request_async(cm_ctx, req);
return 0;
}
static int get_usbnet0_ipv6(char *addr, int nbytes)
{
int fid, read_size, ret;
fid = open(MPIPE_IP6_PATH, O_RDONLY);
if (fid < 0) {
CM_Log(get_usbnet0_ipv6, "%s: open file %s failed: %s", __func__, MPIPE_IP6_PATH, strerror(errno));
return fid;
}
read_size = read(fid, addr, nbytes);
if (read_size <= 0) {
ret = -1;
goto exit;
}
CM_Log(get_usbnet0_ipv61, "%s: ipv6 len %d, ipv6 %s", __func__, read_size, addr);
if (addr[read_size - 1] == '\n')
addr[read_size - 1] = '\0';
ret = 0;
exit:
close(fid);
return ret;
}
void send_disconnect_2host(int cid, pdp_type protocol)
{
Data_Call_Response rsp = { 0 };
memset(&rsp, 0, sizeof(rsp));
rsp.cid = cid + 1; /*plus 1 from CP cid*/
rsp.IP_Type = (int)protocol;
rsp.status = 1;/*disconnect*/
CM_Log(send_disconnect_2host, "%s:cid %d, ip_type %d, status %d", __func__,rsp.cid, rsp.IP_Type, rsp.status);
send_ip_info_2host(&rsp);
}
static void send_ip_info_2host(Data_Call_Response *rsp)
{
RIL_IPDNSInfo ip_info = { 0 };
char tmp_addr[MAX_STR_LEN] = { 0 };
int len = 0, i = 0;
int ipv6_host[4] = { 0 };
memset(&ip_info, 0, sizeof(ip_info));
ip_info.state = (rsp->status == 0)? 1: 0;
ip_info.cid = rsp->cid;
CM_Log(send_ip_info_2host1, "%s:cid %d, ip_type %d, state %d ", __func__,ip_info.cid, rsp->IP_Type, ip_info.state);
if (rsp->IP_Type == 0)
ip_info.ip_type = strdup("IPV4V6");
else if (rsp->IP_Type == 1)
ip_info.ip_type = strdup("IP");
else if (rsp->IP_Type == 2)
ip_info.ip_type = strdup("IPV6");
else
ip_info.ip_type = strdup("IP");
ip_info.ip = malloc(MAX_STR_LEN);
if (ip_info.ip == NULL)
goto end;
memset(ip_info.ip, 0, MAX_STR_LEN);
ip_info.gateway = malloc(MAX_STR_LEN);
if (ip_info.gateway == NULL)
goto end;
memset(ip_info.gateway, 0, MAX_STR_LEN);
ip_info.primary_dns = malloc(MAX_STR_LEN);
if (ip_info.primary_dns == NULL)
goto end;
memset(ip_info.primary_dns, 0, MAX_STR_LEN);
ip_info.secondary_dns = malloc(MAX_STR_LEN);
if (ip_info.secondary_dns == NULL)
goto end;
memset(ip_info.secondary_dns, 0, MAX_STR_LEN);
if (ip_info.state == 0) {
strcpy(ip_info.ip, "0.0.0.0");
strcpy(ip_info.gateway, "0.0.0.0");
strcpy(ip_info.primary_dns, "0.0.0.0");
strcpy(ip_info.secondary_dns, "0.0.0.0");
} else {
if ((rsp->IP_Type == IPV4) || (rsp->IP_Type == IPV4V6)) {
if (!rsp->ipv4info)
goto end;
inet_ntop(AF_INET, &(rsp->ipv4info->IPAddr), ip_info.ip, MAX_STR_LEN);
if (rsp->ipv4info->GateWay == 0) {
rsp->ipv4info->GateWay = rsp->ipv4info->IPAddr;
}
inet_ntop(AF_INET, &(rsp->ipv4info->GateWay), ip_info.gateway, MAX_STR_LEN);
inet_ntop(AF_INET, &(rsp->ipv4info->PrimaryDNS), ip_info.primary_dns, MAX_STR_LEN);
inet_ntop(AF_INET, &(rsp->ipv4info->SecondaryDNS), ip_info.secondary_dns, MAX_STR_LEN);
if (rsp->ipv6info) {
for ( i = 0; i < 4; i++)
ipv6_host[i] =ntohl(rsp->ipv6info->IPV6Addr[i]);
snprintf(tmp_addr, MAX_STR_LEN, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", (ipv6_host[0] >>16) & 0xFFFF, ipv6_host[0] & 0xFFFF,\
(ipv6_host[1] >>16) & 0xFFFF, ipv6_host[1] & 0xFFFF,\
(ipv6_host[2] >>16) & 0xFFFF, ipv6_host[2] & 0xFFFF,\
(ipv6_host[3] >>16) & 0xFFFF, ipv6_host[3] & 0xFFFF);
strcat(ip_info.ip, " ");
strcat(ip_info.ip, tmp_addr);
memset(tmp_addr, 0, MAX_STR_LEN);
if (!address_v6_null(rsp->ipv6info->GateWay)) {
inet_ntop(AF_INET6, &(rsp->ipv6info->GateWay), tmp_addr, MAX_STR_LEN);
strcat(ip_info.gateway, " ");
strcat(ip_info.gateway, tmp_addr);
} else {
if (0 == get_usbnet0_ipv6(tmp_addr, MAX_STR_LEN)) {
strcat(ip_info.gateway, " ");
strcat(ip_info.gateway, tmp_addr);
}
}
if (!address_v6_null(rsp->ipv6info->PrimaryDNS)) {
memset(tmp_addr, 0, MAX_STR_LEN);
inet_ntop(AF_INET6, &(rsp->ipv6info->PrimaryDNS), tmp_addr, MAX_STR_LEN);
strcat(ip_info.primary_dns, " ");
strcat(ip_info.primary_dns, tmp_addr);
}
if (!address_v6_null(rsp->ipv6info->SecondaryDNS)) {
memset(tmp_addr, 0, MAX_STR_LEN);
inet_ntop(AF_INET6, &(rsp->ipv6info->SecondaryDNS), tmp_addr, MAX_STR_LEN);
strcat(ip_info.secondary_dns, " ");
strcat(ip_info.secondary_dns, tmp_addr);
}
}
} else if (rsp->IP_Type == IPV6) {
if (!rsp->ipv6info)
goto end;
for ( i = 0; i < 4; i++)
ipv6_host[i] =ntohl(rsp->ipv6info->IPV6Addr[i]);
snprintf(ip_info.ip, MAX_STR_LEN, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", (ipv6_host[0] >>16) & 0xFFFF, ipv6_host[0] & 0xFFFF,\
(ipv6_host[1] >>16) & 0xFFFF, ipv6_host[1] & 0xFFFF,\
(ipv6_host[2] >>16) & 0xFFFF, ipv6_host[2] & 0xFFFF,\
(ipv6_host[3] >>16) & 0xFFFF, ipv6_host[3] & 0xFFFF);
if (!address_v6_null(rsp->ipv6info->GateWay))
inet_ntop(AF_INET6, &(rsp->ipv6info->GateWay), ip_info.gateway, MAX_STR_LEN);
else {
if (0 == get_usbnet0_ipv6(tmp_addr, MAX_STR_LEN))
strcat(ip_info.gateway, tmp_addr);
}
if (!address_v6_null(rsp->ipv6info->PrimaryDNS))
inet_ntop(AF_INET6, &(rsp->ipv6info->PrimaryDNS), ip_info.primary_dns, MAX_STR_LEN);
if (!address_v6_null(rsp->ipv6info->SecondaryDNS))
inet_ntop(AF_INET6, &(rsp->ipv6info->SecondaryDNS), ip_info.secondary_dns, MAX_STR_LEN);
CM_Log(send_ip_info_2host1, "%s: cid %d, ip_type %s, ip %s, gateway %s, primary dns %s, secondary dns %s", __func__, ip_info.cid, \
ip_info.ip_type, ip_info.ip, ip_info.gateway, ip_info.primary_dns, ip_info.secondary_dns);
} else
goto end;
}
len = 2*sizeof(int);
len += strlen(ip_info.ip_type) + 1;
len += strlen(ip_info.ip) + 1;
len += strlen(ip_info.gateway) + 1;
len += strlen(ip_info.primary_dns) + 1;
len += strlen(ip_info.secondary_dns) + 1;
CM_Log(send_ip_info_2host, "%s: state %d, cid %d, ip_type %s, ip %s, gateway %s, primary dns %s, secondary dns %s", __func__, ip_info.state, ip_info.cid, \
ip_info.ip_type, ip_info.ip, ip_info.gateway, ip_info.primary_dns, ip_info.secondary_dns);
if (ip_info.state)
cm_set_atcmd_apn_state( ip_info.cid, CM_CONNECT_CONSUCCESS);
else
cm_set_atcmd_apn_state( ip_info.cid, CM_CONNECT_DISCON);
send_ip_info_request_2ril_async(&ip_info, len);
end:
if (ip_info.ip_type)
free(ip_info.ip_type);
if (ip_info.ip)
free(ip_info.ip);
if (ip_info.gateway)
free(ip_info.gateway);
if (ip_info.primary_dns)
free(ip_info.primary_dns);
if (ip_info.secondary_dns)
free(ip_info.secondary_dns);
}
void send_zgdcont_info_2atcmd(Apn_Info *apn_info)
{
RIL_ZGDCONTInfo info = { 0 };
int len = 0;
if (apn_info->cid == 0)
return;
info.cid = apn_info->cid;
if (apn_info->iptype == 0)
info.ip_type= strdup("IPV4V6");
else if (apn_info->iptype == 1)
info.ip_type = strdup("IP");
else if (apn_info->iptype == 2)
info.ip_type = strdup("IPV6");
else
info.ip_type = strdup("IP");
info.apn = strdup(apn_info->apn);
len = sizeof(int);
len += strlen(info.ip_type) + 1;
len += strlen(info.apn) + 1;
info.data_on_roaming = apn_info->Extra_params.data_on_roaming;
len += sizeof(info.data_on_roaming);
info.connect_mode = apn_info->Extra_params.autoconnect;
len += sizeof(info.connect_mode);
info.data_on_boot = apn_info->Extra_params.always_on;
len += sizeof(info.data_on_boot);
CM_Log(send_zgdcont_request_2ril_async1, "%s: cid %d, ip_type %s, apn %s, data_on_roaming %d, connect_mode %d, data_on_boot %d", __func__,
info.cid, info.ip_type, info.apn, info.data_on_roaming, info.connect_mode, info.data_on_boot);
send_zgdcont_request_2ril_async(&info, len);
if (info.ip_type)
free(info.ip_type);
if (info.apn)
free(info.apn);
}
static int cm_set_ifru_ivalue(const char* ifname, int cmd, int value)
{
int ret;
struct ifreq ifr;
int ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (ifc_ctl_sock < 0) {
CM_Log(cm_set_ifru_ivalue, "%s:socket failed: %s", __func__, strerror(errno));
return -1;
}
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
ifr.ifr_ifru.ifru_ivalue = value;
ret = ioctl(ifc_ctl_sock, cmd, &ifr);
if (ret < 0) {
CM_Log(cm_set_ifru_ivalue1, "%s(ifname:%s,cmd:%d,value:%d) failed: %s", __func__, ifname, cmd, value, strerror(errno));
}
close(ifc_ctl_sock);
return ret;
}
static int cm_system(const char *cmd, char *res_buf, int rsp_len)
{
FILE *fp = NULL;
int res = -1;
int size = 0;
char *buf = res_buf;
char tmp[512] = { 0 };
char *line = NULL;
if (cmd == NULL || buf == NULL) {
CM_Log_E(cm_system, "%s: invalid inpout param\n", __func__);
return -1;
}
if ((fp = popen(cmd, "r")) == NULL) {
CM_Log_E(cm_system1, "%s: popen error: %s/n", __func__, strerror(errno));
return -1;
} else {
while ((line = fgets(tmp, sizeof(tmp), fp)) != NULL) {
CM_Log(cm_system2, "%s: %s", __func__, line);
size += snprintf(buf + size, rsp_len - size -1, "%s", line);
}
if ((res = pclose(fp)) == -1) {
CM_Log_E(cm_system3, "%s: close popen file pointer fp error: %s\n", __func__, strerror(errno));
return -1;
} else {
if (WIFEXITED(res))
{
CM_Log_E(cm_system4, "%s: normal exit the child process with status %d and exit value %d\n", __func__, res, WEXITSTATUS(res));
}
else
{
CM_Log_E(cm_system5, "%s: abnormal exit the child process\n", __func__);
}
return 0;
}
}
}
static bool cm_has_ccinet_if()
{
char res_buf[5*1024] = { 0 };
char cmd[32] = "ifconfig |grep ccinet";
int ret = 0;
ret = cm_system(cmd, res_buf, sizeof(res_buf));
if (ret == 0) {
CM_Log(cm_has_ccinet_if, "%s: %s", __func__, res_buf);
if (strstr(res_buf, "ccinet"))
return true;
}
return false;
}
static bool is_dnsmasq_reload_success()
{
bool is_success = false;
if((access("/tmp/dnsmasq_success", F_OK)) == 0)
{
is_success = true;
}
else
{
is_success = false;
}
return is_success;
}
static int remove_dnsmasq_success_file()
{
int ret = 0;
ret = remove("/tmp/dnsmasq_success");
return ret;
}
static bool is_ccinet_if_up(int cid)
{
char res_buf[512] = { 0 };
char cmd[32] = "ifconfig |grep ccinet";
char ccinetName[32] = { '\0' };
int ret = 0;
ret = cm_system(cmd, res_buf, sizeof(res_buf));
if (ret == 0) {
sprintf(ccinetName, "ccinet%d", cid);
CM_Log(cm_has_ccinet_if, "%s: find %s in %s", __func__, ccinetName, res_buf);
if (strstr(res_buf, ccinetName))
return true;
}
return false;
}
int is_default_pdp_bearer(int cid)
{
CM_Connection_Context *ctx = g_CM_Context ;
while (ctx) {
if (ctx->pdpinfo && cid == ctx->pdpinfo->primaryCid)
return ctx->pdpinfo->is_default;
ctx= ctx->next;
}
return 1;
}
static char * get_bind_netif(int cid)
{
CM_Connection_Context *ctx = g_CM_Context ;
while (ctx) {
if (ctx->pdpinfo && cid == ctx->pdpinfo->primaryCid)
return ctx->pdpinfo->netif;
ctx= ctx->next;
}
return NULL;
}
bool g_vlan_enable = 0;
int g_vlan_baseid = 0;
bool g_default_pdp_vlan_enable=0;
static void get_vlan_config(void)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
const char *opt_val = NULL;
g_vlan_enable = 0;
g_vlan_baseid = 0;
free_wan_uci_ctx();
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(get_vlan_config2607, "get_vlan_config:fail to get uci ctx\r\n");
return;
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WAN_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
}
if (!p) {
CM_Log_E(get_vlan_config2613, "get_vlan_config: load wan file failed\r\n");
free_wan_uci_ctx();
return;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "vlan-config") == 0)
{
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "enable");
if (opt_val)
g_vlan_enable = atoi(opt_val);
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "base_id");
if (opt_val)
g_vlan_baseid = atoi(opt_val);
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "default_pdp_vlan");
if (opt_val)
g_default_pdp_vlan_enable = atoi(opt_val);
break;
}
}
CM_Log(get_vlan_config2635, "get_vlan_config: vlan_enable %d, vlan_base %d, default_pdp_vlan %d", g_vlan_enable, g_vlan_baseid, g_default_pdp_vlan_enable);
free_wan_uci_ctx();
}
static int get_vlan_base_id(void)
{
return g_vlan_baseid;
}
static bool is_vlan_enable(void)
{
/*when vlan_base_id is over 4096, it's invalid and used to other scenes*/
return g_vlan_enable && (4096 > get_vlan_base_id());
}
static bool is_default_pdp_vlan_enable(void)
{
return g_default_pdp_vlan_enable;
}
static bool is_zvlan_enable(void)
{
/*zvlan/zvlan_id is used to China Telecom 5G Slice when vlan_base_id equal to 10000*/
return g_vlan_enable && (10000 == get_vlan_base_id());
}
#if 1
static void config_network_switch_section(struct uci_context *local_ctx, struct uci_package *p, bool enable_vlan)
{
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char tmp[16] = { 0 };
bool found_sec = false;
int ret = 0;
const char *opt_val = NULL;
if (local_ctx == NULL || p == NULL)
return;
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, "switch") == 0)
{
found_sec = true;
break;
}
}
if (found_sec == false) {
uci_add_section(local_ctx, p, "switch", &uci_sec);
CM_Log_D(config_network_switch_section2624, "config_network_switch_section: add new section %x\r\n", uci_sec);
}
if (!uci_sec) {
CM_Log_E(config_network_switch_section2627, "config_network_switch_section:fail to add switch section\r\n");
return;
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "name");
if (opt_val == NULL)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "name";
ptr.value = "switch0";
ret = uci_set(local_ctx, &ptr);
CM_Log_D(config_network_switch_section2637, "config_network_switch_section: add option name switch0 with ret %d\r\n", ret);
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "reset");
if (opt_val == NULL)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "reset";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "enable_vlan");
if (opt_val == NULL)
{
sprintf(tmp, "%d", enable_vlan);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "enable_vlan";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
}
return;
}
#endif
#define UCI_LOW_LAYER_API 1
static void config_network_lan_interface(struct uci_context *local_ctx, struct uci_package *p, int cid, Ipv4Info *ipinfo, int zvlan_id)
{
#if UCI_LOW_LAYER_API
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
bool found_sec = false;
#endif
char tmp[100] = { 0 };
char name[32] = { 0 };
char interface_name[32] = { 0 };
int vlan_id = 0;
int ipaddr_xor = 0;
char *paddr = NULL;
int ret = UCI_OK;
if (local_ctx == NULL || p == NULL)
return;
if (cid > 16)
return;
if (is_default_pdp_vlan_enable())
{
if ((cid <= 0) && !is_zvlan_enable())
return;
}
else
{
if ((cid <= 1) && !is_zvlan_enable())
return;
}
#if 0
if (cid == 1)
{
snprintf(interface_name, sizeof(interface_name) - 1, "lan");
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, interface_name) == 0)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ipaddr";
ptr.value = "192.168.1.1";
uci_set(local_ctx, &ptr);
break;
}
}
}
#endif
if ((cid == 1) && !is_zvlan_enable())
snprintf(interface_name, sizeof(interface_name) - 1, "lan");
else
snprintf(interface_name, sizeof(interface_name) - 1, "lan%d", cid - 1);
#if UCI_LOW_LAYER_API
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, interface_name) == 0)
{
found_sec = true;
break;
}
}
if (found_sec == false) {
uci_add_section(local_ctx, p, "interface", &uci_sec);
CM_Log_E(config_network_lan_interface2695, "config_network_lan_interface: add interface section uci_sec %x\r\n", uci_sec);
if (uci_sec) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.value = interface_name;
ret = uci_rename(local_ctx, &ptr);
}
}
if (!uci_sec) {
CM_Log_E(config_network_lan_interface2690, "config_network_lan_interface:fail to add switch section\r\n");
return;
}
#endif
vlan_id = get_vlan_base_id() + cid - 1;
if (zvlan_id > 0 && zvlan_id < 4096)
vlan_id = zvlan_id;
sprintf(name, "usbnet0.%d", vlan_id);
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ifname";
ptr.value = name;
ret = uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "ifname", name);
#endif
CM_Log_D(config_network_lan_interface2711, "config_network_lan_interface: set ifname %s with ret %d\r\n", name, ret);
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "type";
ptr.value = "bridge";
uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "type", "bridge");
#endif
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "bridge_empty";
ptr.value = "1";
uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "bridge_empty", "1");
#endif
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "proto";
ptr.value = "static";
uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "proto", "static");
#endif
ipaddr_xor = ipinfo->IPAddr;
paddr = (char *)&ipaddr_xor;
CM_Log_E(config_network_lan_interface2747, "config_network_lan_interface: input ipaddr %d.%d.%d.%d\r\n", paddr[0], paddr[1], paddr[2], paddr[3]);
paddr[3] = 0xFF - (unsigned char)( paddr[3] & 0xFF);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &ipaddr_xor, tmp, sizeof(tmp));
if(is_zvlan_enable() && zvlan_id && !pipe_mode)
sprintf(tmp, "192.168.%d.1", (zvlan_id * 10) % 256);
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ipaddr";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "ipaddr", tmp);
CM_Log_D(config_network_lan_interface2762, "config_network_lan_interface: set ipaddr %s with ret %d\r\n", tmp, ret);
#endif
if (ipinfo->Mask == 0)
ipinfo->Mask = htonl(0xFFFFFF00);
inet_ntop(AF_INET, &(ipinfo->Mask), tmp, sizeof(tmp));
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "netmask";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "netmask", tmp);
CM_Log_D(config_network_lan_interface2774, "config_network_lan_interface: set netmask %s with ret %d\r\n", tmp, ret);
#endif
#if UCI_LOW_LAYER_API
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ip6assign";
ptr.value = "60";
uci_set(local_ctx, &ptr);
#else
ret = uci_set_option(local_ctx, "network", "interface", interface_name, "ip6assign", "60");
#endif
CM_Log_E(config_network_lan_interface2806, "config_network_lan_interface: done, p %x\r\n", p);
return;
}
static void delete_network_lan_interface(struct uci_context *local_ctx, struct uci_package *p, int cid)
{
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
bool found_sec = false;
char interface_name[32] = { 0 };
int ds_cid = cid;
if (local_ctx == NULL || p == NULL)
return;
if (cid > 15)
return;
if (is_default_pdp_vlan_enable())
{
if ((cid < 0) && !is_zvlan_enable())
return;
}
else
{
if ((cid < 1) && !is_zvlan_enable())
return;
}
if ((cid == 0) && !is_zvlan_enable())
snprintf(interface_name, sizeof(interface_name) - 1, "lan");
else
snprintf(interface_name, sizeof(interface_name) - 1, "lan%d", cid);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, interface_name) == 0)
{
found_sec = true;
break;
}
}
if (found_sec == false) {
return;
}
if (cid == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ipaddr";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "netmask";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ifname";
ptr.value = "usbnet0 hsicnet0 eth0";
uci_set(local_ctx, &ptr);
} else {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
uci_delete(local_ctx, &ptr);
}
if (!isMasterSim0())
{
if (ds_cid < get_sim2_base_cid())
ds_cid += get_sim2_base_cid();
}
sprintf(interface_name, "wan%d", ds_cid);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, interface_name) == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto";
ptr.value = "0";
uci_set(local_ctx, &ptr);
}
}
CM_Log_E(delete_network_lan_interface, "delete_network_lan_interface: delete options for section %s done, p %x\r\n", interface_name, p);
return;
}
static void config_dhcp_lan_section(struct uci_context *local_ctx, struct uci_package *p, Data_Call_Response *resp)
{
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_option *opt = NULL;
struct uci_ptr ptr;
char tmp[64] = { 0 };
char dhcp_option[68] = { 0 };
char name[32] = { 0 };
bool found_sec = false;
int ipaddr_xor = 0;
char *paddr = NULL;
if (local_ctx == NULL || p == NULL || resp == NULL)
return;
if (resp->cid > 16)
return;
if (is_default_pdp_vlan_enable())
{
if (resp->cid <= 0 && !is_zvlan_enable())
return;
}
else
{
if (resp->cid <= 1 && !is_zvlan_enable())
return;
}
#if 0
if (resp->cid == 1)
{
sprintf(name, "lan");
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, name) == 0)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "start";
ptr.value = "100";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "limit";
ptr.value = "150";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcp_option";
uci_delete(local_ctx, &ptr);
break;
}
}
}
#endif
if (resp->cid == 1 && !is_zvlan_enable())
{
sprintf(name, "lan");
return;
}
else
sprintf(name, "lan%d", resp->cid - 1);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, name) == 0)
{
found_sec = true;
break;
}
}
if (found_sec == false) {
uci_add_section(local_ctx, p, "dhcp", &uci_sec);
if (uci_sec) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.value = name;
uci_rename(local_ctx, &ptr);
}
}
if (!uci_sec) {
CM_Log_E(config_dhcp_lan_section2843, "config_dhcp_lan_section:fail to add dhcp section\r\n");
return;
}
CM_Log_D(config_dhcp_lan_section2847, "config_dhcp_lan_section: add option interface %s\r\n", name);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "interface";
ptr.value = name;
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "leasetime";
ptr.value = "2h";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcpv6";
ptr.value = "server";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ra";
ptr.value = "relay";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ndp";
ptr.value = "relay";
uci_set(local_ctx, &ptr);
ipaddr_xor = resp->ipv4info->IPAddr;
paddr = (char *)&ipaddr_xor;
memset(&ptr, 0, sizeof(struct uci_ptr));
sprintf(tmp, "%d", paddr[3]);
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "start";
ptr.value = (is_zvlan_enable() && !pipe_mode) ? "100" : tmp;
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "limit";
ptr.value = (is_zvlan_enable() && !pipe_mode) ? "150" : "0";
uci_set(local_ctx, &ptr);
if (!pipe_mode)
return;
/* delete existed dhcp_option list */
opt = uci_lookup_option(local_ctx, uci_sec, "dhcp_option");
if ((opt != NULL) && (opt->type == UCI_TYPE_LIST)) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcp_option";
uci_delete(local_ctx, &ptr);
}
paddr[3] = 0xFF - (unsigned char)( paddr[3] & 0xFF);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &ipaddr_xor, tmp, sizeof(tmp));
memset(dhcp_option, 0, sizeof(dhcp_option));
sprintf(dhcp_option, "3,%s",tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcp_option";
ptr.value = dhcp_option;
uci_add_list(local_ctx, &ptr);
CM_Log_D(config_dhcp_lan_section2923, "config_dhcp_lan_section: add list dhcp_option %s\r\n", dhcp_option);
memset(dhcp_option, 0, sizeof(dhcp_option));
if (resp->ipv4info->Mask == 0)
resp->ipv4info->Mask = htonl(0xFFFFFF00);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(resp->ipv4info->Mask), tmp, sizeof(tmp));
sprintf(dhcp_option, "1,%s",tmp);
if (strlen(dhcp_option))
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcp_option";
ptr.value = dhcp_option;
uci_add_list(local_ctx, &ptr);
CM_Log_D(config_dhcp_lan_section2923, "config_dhcp_lan_section: add list dhcp_option %s\r\n", dhcp_option);
}
memset(dhcp_option, 0, sizeof(dhcp_option));
if (resp->ipv4info->PrimaryDNS > 0)
{
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(resp->ipv4info->PrimaryDNS), tmp, sizeof(tmp));
sprintf(dhcp_option, "6,%s,",tmp);
}
if (resp->ipv4info->SecondaryDNS > 0)
{
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(resp->ipv4info->SecondaryDNS), tmp, sizeof(tmp));
strcat(dhcp_option, tmp);
}
if (strlen(dhcp_option))
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcp_option";
ptr.value = dhcp_option;
uci_add_list(local_ctx, &ptr);
CM_Log_D(config_dhcp_lan_section2974, "config_dhcp_lan_section: add list dhcp_option %s\r\n", dhcp_option);
}
/* delete existed dns list */
opt = uci_lookup_option(local_ctx, uci_sec, "dns");
if ((opt != NULL) && (opt->type == UCI_TYPE_LIST)) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
uci_delete(local_ctx, &ptr);
}
if (resp->IP_Type == IPV4V6 || resp->IP_Type == IPV6)
{
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(DataCallRsp.ipv6info->PrimaryDNS), tmp, sizeof(tmp));
CM_Log(config_dhcp_lan_section2946, "config_dhcp_lan_section: add V6 PrimaryDNS : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
ptr.value = tmp;
uci_add_list(local_ctx, &ptr);
CM_Log_D(config_dhcp_lan_section2974, "config_dhcp_lan_section: add list dns %s\r\n", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(DataCallRsp.ipv6info->SecondaryDNS), tmp, sizeof(tmp));
CM_Log(config_dhcp_lan_section2995, "config_dhcp_lan_section: add V6 SecondaryDNS : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
ptr.value = tmp;
uci_add_list(local_ctx, &ptr);
CM_Log_D(config_dhcp_lan_section3002, "config_dhcp_lan_section: add list dns %s\r\n", tmp);
}
return;
}
static void delete_dhcp_lan_section(struct uci_context *local_ctx, struct uci_package *p, int cid)
{
struct uci_element *e = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char name[32] = { 0 };
bool found_sec = false;
if (local_ctx == NULL || p == NULL)
return;
if (cid > 15)
return;
if (is_default_pdp_vlan_enable())
{
if ((cid < 0) && !is_zvlan_enable())
return;
}
else
{
if ((cid < 1) && !is_zvlan_enable())
return;
}
sprintf(name, "lan%d", cid);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, name) == 0)
{
found_sec = true;
break;
}
}
if (found_sec == false) {
return;
}
if (is_zvlan_enable()) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
uci_delete(local_ctx, &ptr);
}
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ra";
ptr.value = "relay";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ndp";
ptr.value = "relay";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "start";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "limit";
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dhcp_option";
// uci_del_list(local_ctx, &ptr);
uci_delete(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
//uci_del_list(local_ctx, &ptr);
uci_delete(local_ctx, &ptr);
CM_Log_D(delete_dhcp_lan_section3198, "delete_dhcp_lan_section:f delete options for section %s done\r\n", name);
return;
}
#define SYS_MPIPE_DEVICE_PATH "/sys/kernel/mpipe/devices"
static int config_vlan(int cid, if_command cmd, int zvlan_id)
{
char cmd_buf[256] = { 0 };
char vlan_interface[16] = { 0 };
char res_buf[64] = { 0 };
int ret = 0;
int vlan_id = get_vlan_base_id() + cid;
if (zvlan_id > 0 && zvlan_id < 4096)
vlan_id = zvlan_id;
sprintf(vlan_interface, "usbnet0.%d", vlan_id);
CM_Log_D(config_vlan3303, "config_vlan: pipe_mode %d, cid %d, cmd %d, vlan interface %s", pipe_mode, cid, cmd, vlan_interface);
if (pipe_mode)
{
sprintf(cmd_buf, "/etc/init.d/network reload");
memset(res_buf, 0, sizeof(res_buf));
ret = cm_system(cmd_buf, res_buf, sizeof(res_buf));
if (ret != 0) {
CM_Log_E(config_vlan3167, "config_vlan: system %s failed with res %s", cmd_buf, res_buf);
goto end;
}
sleep(3);
}
if (cmd == UP)
{
sprintf(cmd_buf, "echo `ifconfig br-lan | grep inet6 | awk '{print $3}'` > %s/%s/ll6addr", SYS_MPIPE_DEVICE_PATH, vlan_interface);
ret = cm_system(cmd_buf, res_buf, sizeof(res_buf));
sprintf(cmd_buf, "cat %s/usbnet0/ipaddr > %s/%s/ipaddr", SYS_MPIPE_DEVICE_PATH, SYS_MPIPE_DEVICE_PATH, vlan_interface);
ret = cm_system(cmd_buf, res_buf, sizeof(res_buf));
}
/* bind vlan to ccinet */
if (cmd == UP)
sprintf(cmd_buf, "echo %s > %s/ccinet%d/combineif", vlan_interface, SYS_MPIPE_DEVICE_PATH, cid);
else
sprintf(cmd_buf, "echo > %s/ccinet%d/combineif", SYS_MPIPE_DEVICE_PATH, cid);
memset(res_buf, 0, sizeof(res_buf));
ret = cm_system(cmd_buf, res_buf, sizeof(res_buf));
if (ret != 0) {
CM_Log_E(config_vlan3120, "config_vlan: system %s failed with res %s", cmd_buf, res_buf);
goto end;
}
if (cmd == UP)
{
/*disable option readethers in mult_apn*/
cm_system("uci set dhcp.@dnsmasq[0].readethers=0", res_buf, sizeof(res_buf));
cm_system("uci commit dhcp", res_buf, sizeof(res_buf));
sprintf(cmd_buf, "/etc/init.d/dnsmasq reload");
memset(res_buf, 0, sizeof(res_buf));
ret = cm_system(cmd_buf, res_buf, sizeof(res_buf));
if (ret != 0) {
CM_Log_E(config_vlan3175, "config_vlan: system %s failed with res %s", cmd_buf, res_buf);
goto end;
}
CM_Log_D(config_vlan3394, "config_vlan: dnsmasq reload done");
}
end:
return ret;
}
static void ConfigETHInfo(int sync, int cid)
{
char ifname[50] = { 0 };
char cmd[200] = { 0 };
char res_buf[100] = { 0 };
char tmp[50] = { 0 };
snprintf(ifname, sizeof(ifname), "ccinet%d", cid);
if (cm_set_ifru_ivalue(ifname, CCINET_IOCTL_IF_LAN_ENABLE, cid) < 0)
{
CM_Log_E(ConfigETHInfo1, "%s: fail to enable lan", __func__);
return;
}
snprintf(cmd, sizeof(cmd), "uci del network.wan%d", cid);
cm_system(cmd, res_buf, sizeof(res_buf));
snprintf(cmd, sizeof(cmd), "uci del network.wan6%d", cid);
cm_system(cmd, res_buf, sizeof(res_buf));
snprintf(cmd, sizeof(cmd), "uci get network.lan.ifname");
cm_system(cmd, tmp, sizeof(tmp));
if (tmp[strlen(tmp) - 1] == '\n')
tmp[strlen(tmp) - 1] = '\0';
/* add ccinetX into bridge*/
snprintf(res_buf, sizeof(res_buf), "%s %s", tmp, ifname);
snprintf(cmd, sizeof(cmd), "uci set network.lan.ifname='%s'", res_buf);
cm_system(cmd, res_buf, sizeof(res_buf));
snprintf(cmd, sizeof(cmd), "uci del network.lan.ipaddr");
cm_system(cmd, res_buf, sizeof(res_buf));
snprintf(cmd, sizeof(cmd), "uci del network.lan.netmask");
cm_system(cmd, res_buf, sizeof(res_buf));
snprintf(cmd, sizeof(cmd), "uci commit network");
cm_system(cmd, res_buf, sizeof(res_buf));
reload_network(sync);
return;
}
void ConfigIPInfo(int sync)
{
#define MAX_TMP_BUF_SIZE 256
#define MAX_CCINET_QUERY_IPV6_PARTNER_SECONDS 5
#define MAX_CCINET_QUERY_SECONDS 60
#define MAX_CCINET_QUERY_INTERVAL (200 * 1000)
#define MAX_DNSMASQ_STATUS_QUERY_SECONDS 60
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_option *opt = NULL;
struct uci_ptr ptr;
char tmp[MAX_TMP_BUF_SIZE] = { 0 };
char section_name[16] = { 0 };
char section6_name[16] = { 0 };
char ifname[32] = { 0 };
int count = 0, is_default;
int status = 0, max_count = 0;
char *netif_name = NULL;
CM_Connection_Context *connect_ctx;
bool is_vlan_enabled = false;
int configured_cid = 0;
bool is_zvlan = false;
const char *pvalue = NULL;
int zvlan_id = 0;
char res_buf[64] = { 0 };
static int ipv6_bootflag = 0;
get_vlan_config();
/* skip cid1 */
if (is_vlan_enable() && DataCallRsp.cid > 0 && pipe_mode)
is_vlan_enabled = true;
is_zvlan = is_zvlan_enable() ? true : false;
/*load /etc/config/network */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(ConfigIPInfo, "ConfigIPInfo:fail to get uci ctx\r\n");
return;
}
if (DataCallRsp.IP_Type == TYPE_ETH) {
ConfigETHInfo(sync, DataCallRsp.cid - 1);
CM_Log(ConfigIPInfo4052, "ConfigIPInfo: configure ETH info done\r\n");
return;
}
uci_load(local_ctx, UCI_NETWORK_FILE, &p);
if (!p) {
CM_Log_E(ConfigIPInfo, "ConfigIPInfo: load network file failed\r\n");
return;
}
if (DataCallRsp.status != 0)
{
status = -1;
goto end;
}
if (DataCallRsp.parent_cid > 0)
configured_cid = DataCallRsp.parent_cid - 1;
else
configured_cid = DataCallRsp.cid - 1;
if (!isMasterSim0())
configured_cid += get_sim2_base_cid();
CM_Log_E(ConfigIPInfo2662, "ConfigIPInfo: configured_cid %d, base_cid %d, sync %d\r\n", configured_cid, get_sim2_base_cid(), sync);
sprintf(section_name, "wan%d", configured_cid);
sprintf(section6_name, "wan6%d", configured_cid);
is_default = is_default_pdp_bearer(configured_cid);
netif_name = get_bind_netif(configured_cid);
if (is_vlan_enabled) {
if (DataCallRsp.cid == CM_DEFAULT_ATTACH_CID)
is_default = 1;
else
is_default = 0;
}
if (is_zvlan)
is_default = 1;
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, section_name) == 0) {
if (DataCallRsp.parent_cid > 0)
goto config_ipv6;
if (is_zvlan) {
pvalue = uci_lookup_option_string(local_ctx, uci_sec, "vid");
if (NULL != pvalue)
zvlan_id = atoi(pvalue);
is_zvlan = zvlan_id ? true : false;
}
CM_Log_D(ConfigIPInfo1, "ConfigIPInfo: mtu %d, iptype %d, zvlan %d, zvlanid %d\n", DataCallRsp.mtu, DataCallRsp.IP_Type, is_zvlan, zvlan_id);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "proto";
ptr.value = "static";
uci_set(local_ctx, &ptr);
if (DataCallRsp.mtu > 0) {
memset(tmp, 0, MAX_TMP_BUF_SIZE);
snprintf(tmp, MAX_TMP_BUF_SIZE - 1, "%d", DataCallRsp.mtu);
CM_Log_D(ConfigIPInfo2, "add mtu : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "mtu";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
}
//set option "auto" as 1
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto";
ptr.value = "1";
uci_set(local_ctx, &ptr);
//set option "dedicate"
memset(tmp, 0, MAX_TMP_BUF_SIZE);
snprintf(tmp, MAX_TMP_BUF_SIZE - 1, "%d", is_default?0:1);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dedicate";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
//set option "combineif"
if (netif_name && netif_name[0] != '\0' )
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "combineif";
ptr.value = netif_name;
uci_set(local_ctx, &ptr);
}
CM_Log_D(ConfigIPInfo298, "ConfigIPInfo: ipv4info %p, ipv6info %p\n", DataCallRsp.ipv4info, DataCallRsp.ipv6info);
if (DataCallRsp.ipv4info && (DataCallRsp.IP_Type == IPV4 || DataCallRsp.IP_Type == IPV4V6)) {
memset(tmp, 0, MAX_TMP_BUF_SIZE);
inet_ntop(AF_INET, &(DataCallRsp.ipv4info->IPAddr), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo3, "add ipaddr : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ipaddr";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
memset(tmp, 0, MAX_TMP_BUF_SIZE);
if (DataCallRsp.ipv4info->GateWay == 0) {
CM_Log(ConfigIPInfo4, "gateway is NULL, will use IP address as gateway\n");
DataCallRsp.ipv4info->GateWay = DataCallRsp.ipv4info->IPAddr;
}
if (DataCallRsp.ipv4info->Mask == 0) {
CM_Log(ConfigIPInfo3899, "gateway is %x\n", DataCallRsp.ipv4info->GateWay);
if ((DataCallRsp.ipv4info->GateWay >> 24 & 0xFF) == 0xFF || (DataCallRsp.ipv4info->GateWay >> 24 & 0xFF) == 0) {
if ((DataCallRsp.ipv4info->GateWay >> 16 & 0xFFFF) == 0xFFFF || (DataCallRsp.ipv4info->GateWay >> 16 & 0xFFFF) == 0)
DataCallRsp.ipv4info->Mask = htonl(0xFF000000);
else
DataCallRsp.ipv4info->Mask = htonl(0xFFFF0000);
}
else
DataCallRsp.ipv4info->Mask = htonl(0xFFFFFF00 |cm_get_netmask_last_oct());
CM_Log(ConfigIPInfo3908, "netmask is NULL, config to %x as default\n", DataCallRsp.ipv4info->Mask);
}
inet_ntop(AF_INET, &(DataCallRsp.ipv4info->GateWay), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo5, "add gateway : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "gateway";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
memset(tmp, 0, MAX_TMP_BUF_SIZE);
inet_ntop(AF_INET, &(DataCallRsp.ipv4info->Mask), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo6, "add SubnetMask : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "netmask";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
//delete existed DNS
opt = uci_lookup_option(local_ctx, uci_sec, "dns");
if ((opt != NULL) && (opt->type == UCI_TYPE_LIST)) {
CM_Log(ConfigIPInfo7, "delete DNS \n");
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
uci_delete(local_ctx, &ptr);
}
memset(tmp, 0, MAX_TMP_BUF_SIZE);
inet_ntop(AF_INET, &(DataCallRsp.ipv4info->PrimaryDNS), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo9, "add PrimaryDNS : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
ptr.value = tmp;
uci_add_list(local_ctx, &ptr);
memset(tmp, 0, MAX_TMP_BUF_SIZE);
inet_ntop(AF_INET, &(DataCallRsp.ipv4info->SecondaryDNS), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo8, "add SecondaryDNS : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
ptr.value = tmp;
uci_add_list(local_ctx, &ptr);
}
config_ipv6:
#ifndef PIPE_MANUAL_CONNECT
if( DataCallRsp.ipv6info && (DataCallRsp.IP_Type == IPV6 || DataCallRsp.IP_Type == IPV4V6)) {
if (!address_v6_null(DataCallRsp.ipv6info->PrimaryDNS))
{
memset(tmp, 0, MAX_TMP_BUF_SIZE);
inet_ntop(AF_INET6, &(DataCallRsp.ipv6info->PrimaryDNS), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo2372, "add V6 PrimaryDNS : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
ptr.value = tmp;
uci_add_list(local_ctx, &ptr);
}
if (!address_v6_null(DataCallRsp.ipv6info->SecondaryDNS))
{
memset(tmp, 0, MAX_TMP_BUF_SIZE);
inet_ntop(AF_INET6, &(DataCallRsp.ipv6info->SecondaryDNS), tmp, MAX_TMP_BUF_SIZE);
CM_Log(ConfigIPInfo2383, "add V6 SecondaryDNS : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
ptr.value = tmp;
uci_add_list(local_ctx, &ptr);
}
}
#endif
if ( DataCallRsp.ipv6info && (DataCallRsp.IP_Type == IPV6 || DataCallRsp.IP_Type == IPV4V6)) {
memset(tmp, 0, MAX_TMP_BUF_SIZE);
DataCallRsp.ipv6info->IPV6Addr[0] = htonl(0xfe800000);
DataCallRsp.ipv6info->IPV6Addr[1] = 0;
inet_ntop(AF_INET6, &(DataCallRsp.ipv6info->IPV6Addr), tmp, MAX_TMP_BUF_SIZE);
strcat(tmp,"/64");
CM_Log(ConfigIPInfo10, "add ipv6addr : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ip6addr";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
}
}
if (!pipe_mode && ((DataCallRsp.IP_Type == IPV6) || (DataCallRsp.IP_Type == IPV4V6))) {
if (strcmp(uci_sec->e.name, section6_name) == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
}
}
uci_commit(local_ctx, &p, false);
if (pipe_mode || is_zvlan) {
uci_load(local_ctx, "network", &p);
if (!p) {
CM_Log_E(ConfigIPInfo, "ConfigIPInfo: load network file failed\r\n");
return;
}
config_network_switch_section(local_ctx, p, is_vlan_enabled || is_zvlan);
if (is_vlan_enabled || is_zvlan)
{
config_network_lan_interface(local_ctx, p, DataCallRsp.cid, DataCallRsp.ipv4info, zvlan_id);
}
sprintf(section_name, "wan%d", configured_cid);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, section_name) == 0) {
//set option "auto" as 1
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
}
uci_commit(local_ctx, &p, false);
}
uci_load(local_ctx, UCI_DHCP_FILE, &p);
if (!p) {
CM_Log_E(ConfigIPInfo, "ConfigIPInfo: load dhcp file failed\r\n");
return;
}
sprintf(section_name, "wan%d", configured_cid);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (pipe_mode && strcmp(uci_sec->e.name, "lan") == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ra";
ptr.value = "relay";
uci_set(local_ctx, &ptr);
}
if (strcmp(uci_sec->e.name, section_name) == 0) {
//if ((DataCallRsp.IP_Type == IPV6) || (DataCallRsp.IP_Type == IPV4V6))
{
CM_Log(ConfigIPInfo11, "ConfigIPInfo: start to configure dhcp to master 1 ra relay ndp realy\n");
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "master";
ptr.value = "1";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ra";
ptr.value = "relay";
uci_set(local_ctx, &ptr);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ndp";
ptr.value = "relay";
uci_set(local_ctx, &ptr);
}
}
}
if (is_vlan_enabled || is_zvlan)
{
config_dhcp_lan_section(local_ctx, p, &DataCallRsp);
}
uci_commit(local_ctx, &p, false);
if (pipe_mode)
{
remove_dnsmasq_success_file();
}
reload_network(sync);
if (sync)
usleep(MAX_CCINET_QUERY_INTERVAL);
else
usleep(2*MAX_CCINET_QUERY_INTERVAL);
if (!pipe_mode) {
reload_odhcpd();
if ((DataCallRsp.IP_Type == IPV6) || (DataCallRsp.IP_Type == IPV4V6)) {
if (ipv6_bootflag) {
up_down_br_lan(UP, "lan", sync);
usleep(100*1000);
} else {
cm_system("/etc/init.d/firewall restart", res_buf, sizeof(res_buf));
ipv6_bootflag = 1;
}
}
}
if (is_vlan_enabled || (is_zvlan && pipe_mode))
config_vlan(DataCallRsp.cid -1, UP, zvlan_id);
//ifup interface
if (DataCallRsp.IP_Type == IPV4 && V4_network_intf_status[configured_cid] == 1) //IPV4
send_if_command(configured_cid, UP, IPV4);
else { //IPV4V6 or IPV6
if (V4_network_intf_status[configured_cid] == 1)
send_if_command(configured_cid, UP, IPV4);
usleep(MAX_CCINET_QUERY_INTERVAL);
if (V6_network_intf_status[configured_cid] == 1)
send_if_command(configured_cid, UP, IPV6);
if (is_vlan_enabled || (is_zvlan && pipe_mode)) {
int tmp_vlan_id = 0;
if (is_vlan_enabled)
tmp_vlan_id = get_vlan_base_id() + DataCallRsp.cid - 1;
else if (is_zvlan && pipe_mode)
tmp_vlan_id = zvlan_id;
sprintf(tmp, "echo 1 > %s/usbnet0.%d/up6", SYS_MPIPE_DEVICE_PATH, tmp_vlan_id);
cm_system(tmp, res_buf, sizeof(res_buf));
}
}
usleep(MAX_CCINET_QUERY_INTERVAL);
if (DataCallRsp.v6_partner_cid > 0)
{
CM_Log(ConfigIPInfo13, "%s: v6_partner_cid %d", __func__, DataCallRsp.v6_partner_cid);
max_count = (MAX_CCINET_QUERY_IPV6_PARTNER_SECONDS * 1000 * 1000)/MAX_CCINET_QUERY_INTERVAL;
while (!cm_has_ccinet_if() && count < max_count)
{
usleep(MAX_CCINET_QUERY_INTERVAL);
count++;
}
sprintf(ifname, "ccinet%d", configured_cid);
if (cm_set_ifru_ivalue(ifname, CCINET_IOCTL_SET_V6_CID, DataCallRsp.v6_partner_cid - 1) < 0)
{
CM_Log(ConfigIPInfo14, "%s: failed to config v6_cid", __func__);
}
}
max_count = (MAX_CCINET_QUERY_SECONDS * 1000 * 1000)/MAX_CCINET_QUERY_INTERVAL;
while (!is_ccinet_if_up(configured_cid) && count < max_count)
{
usleep(MAX_CCINET_QUERY_INTERVAL);
count++;
}
if (count == max_count)
{
CM_Log(ConfigIPInfo15, "ccinet%d up failed in 15s ", configured_cid);
status = -2;
goto end;
}
else
{
count = 0;
max_count = (MAX_DNSMASQ_STATUS_QUERY_SECONDS * 1000 * 1000)/MAX_CCINET_QUERY_INTERVAL;
if (pipe_mode && is_default)
{
if (DataCallRsp.IP_Type != IPV6)
{
while(!is_dnsmasq_reload_success() && count < max_count)
{
usleep(100 * 1000);
count++;
}
if (count == max_count)
{
CM_Log(ConfigIPInfo16, "%s: dnsmasq reload not ready", __func__);
status = -3;
goto end;
}
} else {
CM_Log(ConfigIPInfo2548, "%s: not check dnsmasq reload is ready or not when IPV6 Only", __func__);
}
}
}
if (pipe_mode == FALSE && DataCallRsp.parent_cid > 0)
{
CM_Log(ConfigIPInfo2993, "%s: parent cid %d, current cid %d", __func__, DataCallRsp.parent_cid, DataCallRsp.cid);
max_count = (MAX_CCINET_QUERY_IPV6_PARTNER_SECONDS * 1000 * 1000)/MAX_CCINET_QUERY_INTERVAL;
count = 0;
while (!cm_has_ccinet_if() && count < max_count)
{
usleep(MAX_CCINET_QUERY_INTERVAL);
count++;
}
sprintf(ifname, "ccinet%d", DataCallRsp.parent_cid - 1);
if (DataCallRsp.IP_Type == IPV6)
{
if (cm_set_ifru_ivalue(ifname, CCINET_IOCTL_SET_V6_CID, DataCallRsp.cid - 1) < 0)
{
CM_Log(ConfigIPInfo3003, "%s: failed to config v6_cid", __func__);
}
}
else if (DataCallRsp.IP_Type == IPV4)
{
if (cm_set_ifru_ivalue(ifname, CCINET_IOCTL_SET_V4_CID, DataCallRsp.cid - 1) < 0)
{
CM_Log(ConfigIPInfo4078, "%s: failed to config v4_cid", __func__);
}
}
}
end:
if (status == 0)
{
#if 0
if (!pipe_mode)
{
if ((DataCallRsp.IP_Type == IPV6) || (DataCallRsp.IP_Type == IPV4V6))
{
up_down_br_lan(UP, "lan");
usleep(100*1000);
}
}
#endif
send_ip_info_2host(&DataCallRsp);
remove_dnsmasq_success_file();
if (pipe_mode && is_default)
g_last_default_cid = configured_cid;
if (!pipe_mode && is_zvlan) {
// add route and firewall, zvlan_id = table id
sprintf(tmp, "ip rule add iif br-lan%d table %d", DataCallRsp.cid - 1, zvlan_id);
cm_system(tmp, res_buf, sizeof(res_buf));
sprintf(tmp, "ip route add default dev ccinet%d table %d", DataCallRsp.cid - 1, zvlan_id);
cm_system(tmp, res_buf, sizeof(res_buf));
sprintf(tmp, "uci add_list firewall.@zone[0].network=lan%d", DataCallRsp.cid - 1);
cm_system(tmp, res_buf, sizeof(res_buf));
cm_system("uci commit firewall && /etc/init.d/firewall reload", res_buf, sizeof(res_buf));
}
}
else
{
send_disconnect_2host(configured_cid, DataCallRsp.IP_Type);
connect_ctx = cm_get_ctx_by_cid(configured_cid + 1);
if (connect_ctx)
cm_notify_dial_failure(connect_ctx->pdpinfo->connectionNum, status, DataCallRsp.status);
else
cm_notify_dial_failure(0, status, DataCallRsp.status);
}
free_wan_uci_ctx();
CM_Log(ConfigIPInfo12, "done for cid %d, APN [%s] ", configured_cid + 1, DataCallRsp.apn);
}
static void DeleteETHInfo(int cid)
{
char ifname[50] = { 0 };
char cmd[200] = { 0 };
char res_buf[100] = { 0 };
char *ccinet_start = NULL;
int len = 0;
snprintf(ifname, sizeof(ifname), "ccinet%d", cid);
if (cm_set_ifru_ivalue(ifname, CCINET_IOCTL_IF_LAN_DISABLE, cid) < 0)
CM_Log_E(DeleteETHInfo1,"%s: failed to disable lan", __func__);
snprintf(cmd, sizeof(cmd), "uci get network.lan.ifname");
cm_system(cmd, res_buf, sizeof(res_buf));
CM_Log_E(DeleteETHInfo2,"%s: network.lan.ifname %s", __func__, res_buf);
ccinet_start = strstr(res_buf, "ccinet");
if (ccinet_start)
{
len = ccinet_start - res_buf;
res_buf[len - 1] = '\0';
snprintf(cmd, sizeof(cmd), "uci set network.lan.ifname='%s'", res_buf);
cm_system(cmd, res_buf, sizeof(res_buf));
snprintf(cmd, sizeof(cmd), "uci commit network");
cm_system(cmd, res_buf, sizeof(res_buf));
}
}
void DeleteIPInfo(int cid, pdp_type protocol)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_option *opt = NULL;
const char *opt_val = NULL;
struct uci_ptr ptr;
char section_name[32] = { 0 };
char section6_name[32] = { 0 };
char interface_name[64] = { 0 };
bool is_vlan_enabled = false;
bool is_zvlan = false;
int zvlan_id = 0;
char tmp[100] = { 0 };
char res_buf[64] = { 0 };
int ds_cid = cid;
CM_Log_D(DeleteIPInfo, "DeleteIPInfo: cid %d, protocol %d (0: IPV4V6, 1: IPV4, 2:IPV6)\n", cid, protocol);
if (cid < 0)
{
CM_Log_E(DeleteIPInfo4095, "DeleteIPInfo: cid %d invalid\n", cid);
return;
}
if (protocol == TYPE_ETH)
DeleteETHInfo(cid);
get_vlan_config();
/* skip cid0 */
if (is_vlan_enable() && cid >= 0 && pipe_mode)
is_vlan_enabled = true;
is_zvlan = is_zvlan_enable()? true : false;
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(DeleteIPInfo1, "DeleteIPInfo:fail to get uci ctx\r\n");
return;
}
if (is_vlan_enabled || is_zvlan)
{
uci_load(local_ctx, "network", &p);
if (!p)
goto EXIT;
if (is_vlan_enabled || is_zvlan)
{
delete_network_lan_interface(local_ctx, p, cid);
}
uci_commit(local_ctx, &p, false);
}
uci_load(local_ctx, UCI_NETWORK_FILE, &p);
if (!p) {
CM_Log_E(DeleteIPInfo, "DeleteIPInfo: load network file failed\r\n");
return;
}
if (!isMasterSim0())
{
if (ds_cid < get_sim2_base_cid())
ds_cid += get_sim2_base_cid();
}
if (protocol == IPV4) {
sprintf(interface_name, "network.interface.wan%d", ds_cid);
} else if (protocol == IPV6) {
sprintf(interface_name, "network.interface.wan6%d", ds_cid);
} else
goto EXIT;
sprintf(section_name, "wan%d", ds_cid);
sprintf(section6_name, "wan6%d", ds_cid);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(e->name, section_name) == 0) {
CM_Log(DeleteIPInfo2, "DeleteIPInfo: delete %s section in network", section_name);
//get zvlan_id
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "vid");
if (opt_val != NULL) {
zvlan_id = atoi(opt_val);
is_zvlan = zvlan_id ? true : false;
}
//delete existed ipaddr
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ipaddr");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ipaddr";
uci_delete(local_ctx, &ptr);
}
//delete existed mtu
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "mtu");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "mtu";
uci_delete(local_ctx, &ptr);
}
//delete existed netmask
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "netmask");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "netmask";
uci_delete(local_ctx, &ptr);
}
//delete existed gateway
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "gateway");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "gateway";
uci_delete(local_ctx, &ptr);
}
//delete existed DNS
opt = uci_lookup_option(local_ctx, uci_sec, "dns");
if ((opt != NULL) && (opt->type == UCI_TYPE_LIST)) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dns";
uci_delete(local_ctx, &ptr);
}
//delete existed ip6prefix
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ip6prefix");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ip6prefix";
uci_delete(local_ctx, &ptr);
}
//delete existed ip6addr
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ip6addr");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ip6addr";
uci_delete(local_ctx, &ptr);
}
//set option "auto" as 0
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "auto");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto";
ptr.value = "0";
uci_set(local_ctx, &ptr);
}
//delete dedicate ip6addr
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "dedicate");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "dedicate";
uci_delete(local_ctx, &ptr);
}
}
if (!pipe_mode) {
if (strcmp(uci_sec->e.name, section6_name) == 0) {
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "auto");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "auto";
ptr.value = "0";
uci_set(local_ctx, &ptr);
}
}
}
}
uci_commit(local_ctx, &p, false);
uci_load(local_ctx, UCI_DHCP_FILE, &p);
if (!p) {
CM_Log_E(DeleteIPInfo, "DeleteIPInfo: load dhcp file failed\r\n");
return;
}
if (is_vlan_enabled || is_zvlan)
{
delete_dhcp_lan_section(local_ctx, p, cid);
}
if (!pipe_mode && is_zvlan) {
// delete route and firewall, zvlan_id = table id
sprintf(tmp, "ip rule del table %d", zvlan_id);
cm_system(tmp, res_buf, sizeof(res_buf));
sprintf(tmp, "ip route del default dev ccinet%d table %d", cid, zvlan_id);
cm_system(tmp, res_buf, sizeof(res_buf));
sprintf(tmp, "uci del_list firewall.@zone[0].network=lan%d", cid);
cm_system(tmp, res_buf, sizeof(res_buf));
cm_system("uci commit firewall && /etc/init.d/firewall reload", res_buf, sizeof(res_buf));
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(e->name, section_name) == 0) {
CM_Log(DeleteIPInfo3, "DeleteIPInfo: delete %s section in dhcp \n", section_name);
//delete existed matser
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "master");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "master";
uci_delete(local_ctx, &ptr);
}
//delete existed ra
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ra");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ra";
uci_delete(local_ctx, &ptr);
}
//delete existed ndp
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "ndp");
if (opt_val != NULL) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ndp";
uci_delete(local_ctx, &ptr);
}
}
}
uci_commit(local_ctx, &p, false);
if (is_vlan_enabled || (is_zvlan && pipe_mode))
config_vlan(cid, DOWN, zvlan_id);
send_if_command(ds_cid, DOWN, protocol);
EXIT:
free_wan_uci_ctx();
}
void delete_route_info()
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
const char *opt_val = NULL;
struct uci_ptr ptr;
CM_Log(delete_route_info, "enter delete_route_info\n");
if (pipe_mode == TRUE)
return;
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(delete_route_info1, "delete_route_info:fail to get uci ctx\r\n");
return;
}
uci_load(local_ctx, UCI_NETWORK_FILE, &p);
if (!p) {
CM_Log_E(delete_route_info, "delete_route_info: load network file failed\r\n");
return;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (!strcmp(uci_sec->type, "route6")) {
CM_Log(delete_route_info2, "delete_route_info: delete route6 section in network\n");
//delete existed interface
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "interface");
if (opt_val != NULL) {
CM_Log_D(delete_route_info3, "delete interface \r\n");
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "interface";
uci_delete(local_ctx, &ptr);
}
//delete existed target
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "target");
if (opt_val != NULL) {
CM_Log_D(delete_route_info4, "delete target \r\n");
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "target";
uci_delete(local_ctx, &ptr);
}
//delete existed metric
opt_val = uci_lookup_option_string(local_ctx, uci_sec, "metric");
if (opt_val != NULL) {
CM_Log_D(delete_route_info5, "delete metric \r\n");
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "metric";
uci_delete(local_ctx, &ptr);
}
}
}
uci_commit(local_ctx, &p, false);
free_wan_uci_ctx();
}
void config_lan_ipv6(char *ip)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char tmp[68] = { 0 };
char section_name[32] = { 0 };
CM_Log(config_lan_ipv6, "enter config_lan_ipv6\n");
if (pipe_mode == TRUE)
return;
/*load /etc/config/firewall */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(config_lan_ipv61, "config_lan_ipv6:fail to get uci ctx\r\n");
return;
}
uci_load(local_ctx, UCI_NETWORK_FILE, &p);
if (!p) {
CM_Log_E(config_lan_ipv6, "config_lan_ipv6: load network file failed\r\n");
return;
}
sprintf(section_name, "wan%d", DataCallRsp.cid - 1);
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->e.name, section_name) == 0) {
sprintf(tmp, "%s/64", ip);
CM_Log(config_lan_ipv62, "add ip6prefix : %s\n", tmp);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "ip6prefix";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
}
}
uci_commit(local_ctx, &p, false);
free_wan_uci_ctx();
CM_Log(config_lan_ipv63, "exit config_lan_ipv6\n");
}
void config_route_ipv6(char *ip)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char tmp[68] = { 0 };
CM_Log(config_route_ipv6, "enter config_route_ipv6\n");
if (pipe_mode == TRUE)
return;
/*load /etc/config/firewall */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
CM_Log_E(config_route_ipv61, "config_route_ipv6:fail to get uci ctx\r\n");
return;
}
uci_load(local_ctx, UCI_NETWORK_FILE, &p);
if (!p) {
CM_Log_E(config_lan_ipv6, "config_lan_ipv6: load network file failed\r\n");
return;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (!strcmp(uci_sec->type, "route6")) {
CM_Log_D(config_route_ipv62, "add interface lan\n");
sprintf(tmp, "%s/64", ip);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "interface";
ptr.value = "lan";
uci_set(local_ctx, &ptr);
CM_Log_D(config_route_ipv63, "add target : %s\n", tmp);
sprintf(tmp, "%s/64", ip);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "target";
ptr.value = tmp;
uci_set(local_ctx, &ptr);
CM_Log_D(config_route_ipv64, "add metric lan\n");
sprintf(tmp, "%s/64", ip);
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "metric";
ptr.value = "1";
uci_set(local_ctx, &ptr);
}
}
uci_commit(local_ctx, &p, false);
free_wan_uci_ctx();
CM_Log(config_route_ipv65, "exit config_route_ipv6\n");
}
bool ccinet_ipv6_global_ready(int cid, int query_seconds)
{
char interface_name[32] = { 0 };
char ipaddress[INET6_ADDRSTRLEN];
bool get_global_ip = false;
int count;
snprintf(interface_name, sizeof(interface_name) - 1, "ccinet%d", cid - 1);
if (query_seconds == 0)
{
if (getInterfaceAddr6(interface_name, ipaddress, sizeof(ipaddress)) == 0)
{
get_global_ip = true;
}
}
else
{
for (count = query_seconds; count > 0; count--)
{
sleep(1);
if (getInterfaceAddr6(interface_name, ipaddress, sizeof(ipaddress)) == 0)
{
get_global_ip = 1;
CM_Log(ccinet_ipv6_global_ready3461, "ccinet_ipv6_global_ready: get global ip after %ds", query_seconds - count);
break;
}
}
}
CM_Log(ccinet_ipv6_global_ready3466, "ccinet_ipv6_global_ready: get global ip %d", get_global_ip);
return get_global_ip;
}
void QueryDataCall_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
void *data = NULL;
int datalen = 0;
unsigned int requestid, rilerrno;
CM_Connection_Context *setup_ctx = (CM_Connection_Context *)(req->priv);
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, (void **)&data, &datalen)) {
return;
}
if (requestid != RIL_REQUEST_DATA_CALL_LIST || rilerrno != 0) {
goto end;
}
CM_Log(QueryDataCall_data_cb2, "QueryDataCall_data_cb: CMCurrentCid %d, dialerReasonCode %d", CMCurrentCid, dialerReasonCode);
if (setup_ctx && !CM_CheckContextValid(setup_ctx))
{
CM_Log(QueryDataCall_data_cb3413, "QueryDataCall_data_cb: ctx %x has been delete, just return", setup_ctx);
goto end;
}
if (CMCurrentCid != -1) {
CreateDataCallResponseList(setup_ctx, data, datalen, CMCurrentCid);
CM_Log(QueryDataCall_data_cb4531, "QueryDataCall_data_cb, CMCurrentCid %d, data_block %d", CMCurrentCid, g_CM_Context->pdpinfo->data_block);
if (setup_ctx && (setup_ctx->pdpinfo->data_block == 0))
ConfigIPInfo(1);
} else
{
CreateDataCallResponseList(setup_ctx, data, datalen, 0xFFFF);
CM_Log(QueryDataCall_data_cb3488, "QueryDataCall_data_cb: just create datacall list done");
goto end;
}
CM_Log(QueryDataCall_data_cb3, "QueryDataCall_data_cb: DataCallRsp status %d, IP_type %d", DataCallRsp.status , DataCallRsp.IP_Type);
/* no need get global IPV6 address*/
if (pipe_mode)
goto end;
if ((DataCallRsp.status == 0) && ((DataCallRsp.IP_Type == IPV4V6) || (DataCallRsp.IP_Type == IPV6))) {
//Wait to get the gloabal address
int get_global_ip = 0;
get_global_ip = ccinet_ipv6_global_ready(cm_get_current_cid() + 1, 12);
if (!get_global_ip) {
CM_Log(QueryDataCall_data_cb5, "QueryDataCall_data_cb: get global IP failed");
DataCallRsp.status = PDP_FAIL_GET_GLOBALIP;
}
}
end:
if (data)
rilutil_freeResponseData(requestid, data, datalen);
}
Data_Call_Response_List *get_data_call_response_list(void)
{
return DataCallRsponseList;
}
void QueryDataCall(CM_Connection_Context *ctx)
{
int ret_val = 0;
#if 0
if (DataCallRsponseList) {
FreeDataCallRsponseList(DataCallRsponseList);
DataCallRsponseList = NULL;
}
#endif
blob_buf_init(&cm_b, 0);
//blobmsg_add_u32(&cm_b, "reqid", RIL_REQUEST_DATA_CALL_LIST);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_DATA_CALL_LIST, NULL, 0);
CM_Log(QueryDataCall4573, "QueryDataCall, cm_ctx %x, ril_id %x, priv_ctx %x\n", cm_ctx, cm_ubus_id.ril_id, ctx);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, QueryDataCall_data_cb, ctx,
0)) != UBUS_STATUS_OK) {
CM_Log_E(QueryDataCall, "QueryDataCall, ubus_invoke RIL_REQUEST_DATA_CALL_LIST failed %s\n",
ubus_strerror(ret_val));
}
}
bool ProcessRILDeactInd(int in_cid)
{
CM_Connection_Context *tmp_Context;
int cid;
tmp_Context = g_CM_Context;
bool cid_tracked = false;
CM_Log(ProcessRILDeactInd, "enter ProcessRILDeactInd, cid:%d\n", in_cid);
while (tmp_Context) {
if (tmp_Context->pdpinfo->PDP_Type == 1)
cid = tmp_Context->pdpinfo->primaryCid;
else
cid = tmp_Context->pdpinfo->secondaryCid;
if (cid == in_cid)
{
CM_Log(ProcessRILDeactInd1, "ProcessRILDeactInd: change cid=%d status from %d to deactivated, clear dial_cnt\n", cid, tmp_Context->connectStatus);
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
{
if (tmp_Context->connectStatus == CM_CONNECT_CONSUCCESS)
{
tmp_Context->connectStatus = CM_CONNECT_DEACTIVATED;
}
}
#else
tmp_Context->connectStatus = CM_CONNECT_DEACTIVATED;
#endif
tmp_Context->dial_cnt = 0;
/* For deact trigger by CGATT, need wait some ticks for NAS update laster NW status */
tmp_Context->retryTime = 500;
cid_tracked = true;
}
tmp_Context = tmp_Context->next;
}
CM_Log(ProcessRILDeactInd2, "ProcessRILDeactInd: cid %d tracked %d", in_cid, cid_tracked);
return cid_tracked;
}
static int cm_tear_down_iface(CM_Connection_Context *list_head)
{
int cid= 0;
CM_Connection_Context *ctx = list_head;
if (!ctx)
return 0;
while (ctx) {
CM_Log(cm_tear_down_iface, "cm_tear_down_iface: [INFO] pdp_type %d cid %d connect_status %d\n", ctx->pdpinfo->PDP_Type, ctx->pdpinfo->primaryCid, ctx->connectStatus);
if ((ctx->pdpinfo->PDP_Type == CM_PDP_TYPE_PRIMARY) &&
(ctx->connectStatus == CM_CONNECT_CONSUCCESS || ctx->connectStatus == CM_CONNECT_DEACTIVATED ||
ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)) {
cid = ctx->pdpinfo->primaryCid;
if (ctx->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, ctx->pdpinfo->IP_Type);
/* If the PDP is deactived by NW, should record status as CM_CONNECT_WAIT_PS_ATTACH, then redial*/
if ( ctx->connectStatus != CM_CONNECT_GET_GLOBALIP_ERR)
ctx->connectStatus = CM_CONNECT_WAIT_PS_ATTACH;
cm_record_nwactivity(ctx, false);
return 0;
}
ctx = ctx->next;
}
return 0;
}
static bool cm_datacall_exist(int cid, void *resp, int resp_len)
{
Ubus_Data_Call_Response *ptr = NULL;
int len ;
bool exist = false;
for (len = 0, ptr = resp; (len < resp_len && ptr ); len += sizeof(Ubus_Data_Call_Response), ptr++) {
if (cid == ptr->cid)
{
exist = true;
break;
}
}
return exist;
}
static bool cm_datacall_ip_changed(CM_Connection_Context *ctx, void *resp, int resp_len)
{
Ubus_Data_Call_Response *ptr = NULL;
int len ;
bool changed = true;
int cid = ctx->pdpinfo->primaryCid;
Data_Call_Response_List data_call_rsp;
memset(&data_call_rsp, 0, sizeof(Data_Call_Response_List));
for (len = 0, ptr = resp; (len < resp_len && ptr ); len += sizeof(Ubus_Data_Call_Response), ptr++) {
if (cid == ptr->cid)
{
data_call_rsp.PDP.IP_Type = ConvertIPType(ptr->type);
if ((data_call_rsp.PDP.IP_Type == IPV4) || (data_call_rsp.PDP.IP_Type == IPV4V6)) //IPV4 or IPV4V6
{
if (data_call_rsp.PDP.ipv4info == NULL) {
data_call_rsp.PDP.ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info));
if (!data_call_rsp.PDP.ipv4info) {
changed = false;
break;
}
memset(data_call_rsp.PDP.ipv4info, 0, sizeof(Ipv4Info));
}
}
if ((data_call_rsp.PDP.IP_Type == IPV6) || (data_call_rsp.PDP.IP_Type == IPV4V6)) //IPV6 or IPV4V6
{
if (data_call_rsp.PDP.ipv6info == NULL) {
data_call_rsp.PDP.ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info));
if (!data_call_rsp.PDP.ipv6info) {
changed = false;
break;
}
memset(data_call_rsp.PDP.ipv6info, 0, sizeof(Ipv6Info));
}
}
configure_pdp_para(ptr, &data_call_rsp, "addr");
CM_Log(cm_datacall_ip_changed3602, "%s: cm.iptype %d, datacall.iptype %d", __func__, ctx->pdpinfo->IP_Type, data_call_rsp.PDP.IP_Type);
if (ctx->pdpinfo->IP_Type == IPV4 && ctx->ipv4info)
{
CM_Log(cm_datacall_ip_changed3604, "%s: [IPV4], cm.ipaddr 0x%x", __func__, ctx->ipv4info->IPAddr);
if (data_call_rsp.PDP.ipv4info)
CM_Log(cm_datacall_ip_changed3606, "%s: [IPV4], datacall.ipaddr 0x%x", __func__, data_call_rsp.PDP.ipv4info->IPAddr);
if (data_call_rsp.PDP.ipv4info && ctx->ipv4info->IPAddr == data_call_rsp.PDP.ipv4info->IPAddr)
changed = false;
}
if (ctx->pdpinfo->IP_Type == IPV6 && ctx->ipv6info)
{
CM_Log(cm_datacall_ip_changed3611, "%s: [IPV6], cm.ip6addr[0] 0x%x ip6addr[1] 0x%x ip6addr[2] 0x%x ip6addr[3] 0x%x", __func__,
ctx->ipv6info->IPV6Addr[0], ctx->ipv6info->IPV6Addr[1],ctx->ipv6info->IPV6Addr[2],ctx->ipv6info->IPV6Addr[3]);
if (data_call_rsp.PDP.ipv6info)
CM_Log(cm_datacall_ip_changed3619, "%s: [IPV6], datacall.ip6addr[0] 0x%x ip6addr[1] 0x%x ip6addr[2] 0x%x ip6addr[3] 0x%x", __func__,
data_call_rsp.PDP.ipv6info->IPV6Addr[0], data_call_rsp.PDP.ipv6info->IPV6Addr[1], data_call_rsp.PDP.ipv6info->IPV6Addr[2], data_call_rsp.PDP.ipv6info->IPV6Addr[3]);
if (data_call_rsp.PDP.ipv6info && memcmp(&(ctx->ipv6info->IPV6Addr[2]), &(data_call_rsp.PDP.ipv6info->IPV6Addr[2]), 8) == 0 )
changed = false;
}
if (ctx->pdpinfo->IP_Type == IPV4V6)
{
if (ctx->ipv4info)
CM_Log(cm_datacall_ip_changed3627, "%s: [IPV4V6], cm.ipaddr 0x%x", __func__, ctx->ipv4info->IPAddr);
if (ctx->ipv6info)
CM_Log(cm_datacall_ip_changed3630, "%s: [IPV4V6], cm.ip6addr[0] 0x%x ip6addr[1] 0x%x ip6addr[2] 0x%x ip6addr[3] 0x%x", __func__,
ctx->ipv6info->IPV6Addr[0], ctx->ipv6info->IPV6Addr[1], ctx->ipv6info->IPV6Addr[2], ctx->ipv6info->IPV6Addr[3]);
if (data_call_rsp.PDP.ipv4info)
CM_Log(cm_datacall_ip_changed3631, "%s: [IPV4V6], datacall.ipaddr 0x%x", __func__, data_call_rsp.PDP.ipv4info->IPAddr);
if (data_call_rsp.PDP.ipv6info)
CM_Log(cm_datacall_ip_changed3634, "%s: [IPV4V6], datacall.ip6addr[0] 0x%x ip6addr[1] 0x%x ip6addr[2] 0x%x ip6addr[3] 0x%x", __func__,
data_call_rsp.PDP.ipv6info->IPV6Addr[0], data_call_rsp.PDP.ipv6info->IPV6Addr[1], data_call_rsp.PDP.ipv6info->IPV6Addr[2], data_call_rsp.PDP.ipv6info->IPV6Addr[3]);
if (ctx->ipv6info == NULL && ctx->ipv4info && data_call_rsp.PDP.ipv4info &&
ctx->ipv4info->IPAddr == data_call_rsp.PDP.ipv4info->IPAddr)
changed = false;
else if (ctx->ipv4info == NULL && ctx->ipv6info && data_call_rsp.PDP.ipv6info &&
memcmp(&(ctx->ipv6info->IPV6Addr[2]), &(data_call_rsp.PDP.ipv6info->IPV6Addr[2]), 8) == 0)
changed = false;
else if (ctx->ipv6info && ctx->ipv4info)
{
if ((data_call_rsp.PDP.ipv4info && ctx->ipv4info->IPAddr == data_call_rsp.PDP.ipv4info->IPAddr) &&
(data_call_rsp.PDP.ipv6info && memcmp(&(ctx->ipv6info->IPV6Addr[2]), &(data_call_rsp.PDP.ipv6info->IPV6Addr[2]), 8) == 0))
changed = false;
}
}
if (ctx->pdpinfo->IP_Type == TYPE_ETH)
changed = false;
break;
}
}
if (data_call_rsp.PDP.ipv4info)
free(data_call_rsp.PDP.ipv4info);
if (data_call_rsp.PDP.ipv6info)
free(data_call_rsp.PDP.ipv6info);
CM_Log(cm_datacall_ip_changed3617, "%s: changed %d", __func__, changed);
return changed;
}
static int cm_datacall_tear_down_iface(CM_Connection_Context *list_head, void *resp, int resp_len)
{
int cid= 0;
CM_Connection_Context *ctx = list_head;
if (!ctx)
return 0;
while (ctx) {
CM_Log(cm_datacall_tear_down_iface, "cm_datacall_tear_down_iface: [INFO] pdp_type %d cid %d IP_Type %d connect_status %d\n",
ctx->pdpinfo->PDP_Type, ctx->pdpinfo->primaryCid, ctx->pdpinfo->IP_Type, ctx->connectStatus);
if ((ctx->pdpinfo->PDP_Type == CM_PDP_TYPE_PRIMARY) &&
(ctx->connectStatus == CM_CONNECT_CONSUCCESS || ctx->connectStatus == CM_CONNECT_DEACTIVATED ||
ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)) {
cid = ctx->pdpinfo->primaryCid;
if (cm_datacall_exist(cid, resp, resp_len))
{
if (!cm_datacall_ip_changed(ctx, resp, resp_len))
{
if (ctx->connectStatus == CM_CONNECT_DEACTIVATED)
ctx->connectStatus = CM_CONNECT_CONSUCCESS;
CM_Log(cm_datacall_tear_down_iface1, "cm_datacall_tear_down_iface: [INFO] datacall[%d] exist, no need teardown.\n", cid);
return 0;
}
}
if (ctx->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, ctx->pdpinfo->IP_Type);
/* If the PDP is deactived by NW, should record status as CM_CONNECT_WAIT_PS_ATTACH, then redial*/
if ( ctx->connectStatus != CM_CONNECT_GET_GLOBALIP_ERR)
ctx->connectStatus = CM_CONNECT_WAIT_PS_ATTACH;
cm_record_nwactivity(ctx, false);
if (ctx->pdpinfo->IP_Type != ctx->pdpinfo->IP_Type_back)
{
ctx->pdpinfo->IP_Type = ctx->pdpinfo->IP_Type_back;
CM_Log(cm_datacall_tear_down_iface5107, "cm_datacall_tear_down_iface: reset ip_type %d\n", ctx->pdpinfo->IP_Type);
}
CM_Log(cm_datacall_tear_down_iface5109, "cm_datacall_tear_down_iface: tear down cid %d done\n", cid);
}
ctx = ctx->next;
}
CM_Log(cm_datacall_tear_down_iface5114, "cm_datacall_tear_down_iface: tear down all done\n");
return 0;
}
static void cm_redial_connection(CM_Connection_Context *list_head)
{
CM_Connection_Context *ctx = list_head;
CM_Connection_Context *partner_ctx = NULL;
if (!ctx)
return;
while (ctx) {
if (ctx->pdpinfo->PDP_Type == CM_PDP_TYPE_PRIMARY) {
if (ctx->connectStatus != CM_CONNECT_DISCON) {
CM_Log(cm_redial_connection, "cm_redial_connection: may need to redial, cid %d, connect_status %d, allow dial for IPV6 err %d(1: allow 0: not allow)", ctx->pdpinfo->primaryCid, ctx->connectStatus, allow_redial_ipv6_err);
if (ctx->connectStatus == CM_CONNECT_CONSUCCESS) {
ctx = ctx->next;
continue;
}
if (ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR && !allow_redial_ipv6_err) {
ctx = ctx->next;
continue;
}
if (ctx->connectStatus == CM_CONNECT_DEACTIVATED) {
cm_tear_down_iface(ctx);
}
partner_ctx = cm_get_partner_ctx(ctx->pdpinfo->primaryCid);
if (partner_ctx && partner_ctx->pdpinfo && partner_ctx != ctx)
{
CM_Log(cm_redial_connection4926, "cm_redial_connection: find partner ctx 0x%x, iptype %d, cid %d",
partner_ctx, partner_ctx->pdpinfo->IP_Type, partner_ctx->pdpinfo->primaryCid);
if (partner_ctx->pdpinfo->IP_Type != ctx->pdpinfo->IP_Type)
{
/* set back to IPV4V6 */
ctx->pdpinfo->IP_Type = IPV4V6;
CM_Delete_Cur_Context(partner_ctx);
property_set(PROP_SINGLE_STACK_CID, "-1");
}
}
if (ctx->connectStatus != CM_CONNECT_REDIAL)
ctx->connectStatus = CM_CONNECT_DIAL_IMMEDIATELY;
ctx->dialFailureCode = 0;
CM_Log(cm_redial_connection4927, "cm_redial_connection: redial connectionNum %d, connectStatus %d, retryTime %d",
ctx->pdpinfo->connectionNum, ctx->connectStatus, ctx->retryTime);
send_redialmsg_to_redialthread(ctx->pdpinfo->connectionNum, REDIAL_IMMED);
}
}
ctx = ctx->next;
}
return;
}
void QueryDataCall_Indnotify_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int errorNo , id;
void *data = NULL;
int datalen = 0;
bool datalink;
if (rilutil_parseResponseDSMaster(msg, &id, &errorNo, (void **)&data, &datalen)) {
return;
}
if (id != RIL_REQUEST_DATA_CALL_LIST || errorNo != 0)
goto end;
pthread_mutex_lock(&cm_mutex);
CM_Log_D(QueryDataCall_Indnotify_data_cb4967, "QueryDataCall_Indnotify_data_cb: check netif status, cm_mutex locked\n");
if (g_CM_Context == NULL && datalen != 0) {
datalink = cm_allow_datalink();
CM_Log(QueryDataCall_Indnotify_data_cb3, "QueryDataCall_Indnotify_data_cb, cm_allow_datalink %d", datalink);
if (datalink) {
g_CM_Context = CM_Create_Ltedefault(data, datalen);
if (g_CM_Context != NULL) {
CM_Log(QueryDataCall_Indnotify_data_cb4901, "QueryDataCall_Indnotify_data_cb, data_block %d", g_CM_Context->pdpinfo->data_block);
if (g_CM_Context->pdpinfo->data_block == 0)
{
ConfigIPInfo(0);
cm_record_nwactivity(g_CM_Context, false);
}
}
}
} else if (g_CM_Context != NULL) {
/*tear down tracked connection interface*/
cm_datacall_tear_down_iface(g_CM_Context, data, datalen);
datalink = cm_allow_datalink();
if (datalink == FALSE) {
pthread_mutex_unlock(&cm_mutex);
CM_Log_D(QueryDataCall_Indnotify_data_cb4, "needn't to redial, exit QueryDataCall_Indnotify_data_cb, cm_mutex unlocked\n");
goto end;
}
/*ONLY redial tracked connection if needed*/
cm_redial_connection(g_CM_Context);
}
pthread_mutex_unlock(&cm_mutex);
end:
if (data)
rilutil_freeResponseData(id, data, datalen);
CM_Log_D(QueryDataCall_Indnotify_data_cb5, "QueryDataCall_Indnotify_data_cb: done for req 0x%x, cm_mutex unlocked\n", req);
}
void QueryDataCall_Indnotify_complete_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
CM_Log_D(QueryDataCall_Indnotify_complete_cb, "QueryDataCall_Indnotify_complete_cb: enter, ret = %d, req 0x%x", ret, req);
if (req) {
free(req);
req = NULL;
}
}
void QueryDataCall_Indnotify()
{
int ret_val = 0;
struct ubus_request * req;
blob_buf_init(&cm_b, 0);
//blobmsg_add_u32(&cm_b, "reqid", RIL_REQUEST_DATA_CALL_LIST);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_DATA_CALL_LIST, NULL, 0);
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
CM_Log(QueryDataCall_Indnotify, "enter QueryDataCall_Indnotify, req 0x%x\n", req);
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(QueryDataCall_Indnotify1, "exit QueryDataCall_Indnotify, fail: %s\n", ubus_strerror(ret_val));
free(req);
return;
} else {
CM_Log(QueryDataCall_Indnotify2, "QueryDataCall_Indnotify: ubus_invoke_async success");
req->data_cb = QueryDataCall_Indnotify_data_cb;
req->complete_cb = QueryDataCall_Indnotify_complete_cb;
ubus_complete_request_async(cm_ctx, req);
}
return;
}
void QuerySimStatus_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int id = 0;
unsigned int errorNo = 0;
void *data = NULL;
int datalen = 0;
RIL_CardStatus_v6 *p = NULL;
if (rilutil_parseResponseDSMaster(msg, &id, &errorNo, (void **)&data, &datalen)) {
CM_Log_E(QuerySimStatus_cb, "Parse failed\n");
goto done;
}
if (errorNo != 0) {
CM_Log_E(QuerySimStatus_cb1, "exit QuerySimStatus_cb: errorNo %d\n", errorNo);
goto done;
}
p = (RIL_CardStatus_v6 *) data;
pin_status = p->applications[0].app_state;
CM_Log(QuerySimStatus_cb2, "QuerySimStatus_cb: pin_status is %d\n", pin_status);
done:
if(data)
rilutil_freeResponseData(id, data, datalen);
}
int QuerySimStatus()
{
int ret_val = 0;
getMasterSimID();
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_SIM_STATUS, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, QuerySimStatus_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(QuerySimStatus, "exit QuerySimStatus: ubus_invoke RIL_REQUEST_GET_SIM_STATUS fail %s\n",
ubus_strerror(ret_val));
return ret_val;
}
if (pin_status < 0) {
CM_Log_E(QuerySimStatus1, "QuerySimStatus: invalid pin status\n");
return UBUS_STATUS_INVALID_ARGUMENT;
}
return UBUS_STATUS_OK;
}
/*value, 1: close the power ind*/
/*0: open the power ind*/
int SetCPPowerInd(int value)
{
int ret_val = 0;
CM_Log(SetCPPowerInd, "Enter SetCPPowerInd: value is %d\n", value);
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SET_CPPOWERIND, &value, 1);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, NULL, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(SetCPPowerInd1, "exit SetCPPowerInd: ubus_invoke RIL_REQUEST_SET_CPPOWERIND fail %s\n", ubus_strerror(ret_val));
}
CM_Log(SetCPPowerInd2, "Exit SetCPPowerInd: ret_val is %d\n", ret_val);
return ret_val;
}
bool is_telcel_sim(char *imsi)
{
bool ret = false;
int apn_num = (int)sizeof(telcel_mccmnc_table)/ sizeof(telcel_mccmnc_table[0]);
int i;
char mccmnc[MAX_STR_LEN] = { '\0' };
if (strlen(imsi) < 7) {
CM_Log_E(is_telcel_sim1, "%s: return cause IMSI error\n", __func__);
ret = false;
goto END;
}
memcpy(mccmnc, imsi, 6);
CM_Log(is_telcel_sim2, "%s: mcc/mnc %s\n", __func__, mccmnc);
for (i = 0; i < apn_num; i++) {
if (!strncmp(telcel_mccmnc_table[i], mccmnc, strlen(telcel_mccmnc_table[i]))) {
ret = true;
goto END;
}
}
END:
CM_Log(is_telcel_sim3, "%s: leave (%d)\n", __func__, ret);
return ret;
}
static bool is_test_sim(char *imsi)
{
bool ret = false;
char mcc[MAX_STR_LEN] = { '\0' };
if (strlen(imsi) < 7) {
CM_Log_E(is_vzw_sim, "is_test_sim return cause IMSI error\n");
ret = false;
goto end;
}
memcpy(mcc, imsi, 3);
if(!strcmp(mcc, "001"))
ret = true;
end:
CM_Log(is_test_sim1, "is_test_sim: leave (%d)\n", ret);
g_test_sim = ret;
return ret;
}
bool is_vzw_sim(char *imsi)
{
bool ret = false;
int vzwapn_num = (int)sizeof(vzw_mccmnc_table)/ sizeof(vzw_mccmnc_table[0]);
int i;
char mccmnc[MAX_STR_LEN] = { '\0' };
if (strlen(imsi) < 7) {
CM_Log_E(is_vzw_sim, "is_vzw_sim return cause IMSI error\n");
ret = false;
goto END;
}
memcpy(mccmnc, imsi, 6);
CM_Log(is_vzw_sim1, "is_vzw_sim: mcc/mnc %s\n", mccmnc);
for (i = 0; i < vzwapn_num; i++) {
if (!strncmp(vzw_mccmnc_table[i], mccmnc, strlen(mccmnc))) {
ret = true;
goto END;
}
}
END:
CM_Log(is_vzw_sim2, "is_vzw_sim: leave (%d)\n", ret);
return ret;
}
bool is_ctcc_sim(char *imsi)
{
bool ret = false;
int apn_num = (int)sizeof(ctcc_mccmnc_table)/ sizeof(ctcc_mccmnc_table[0]);
int i;
char mccmnc[MAX_STR_LEN] = { '\0' };
if (strlen(imsi) < 7) {
CM_Log_E(is_ctcc_sim1, "is_ctcc_sim: return cause IMSI error\n");
ret = false;
goto END;
}
memcpy(mccmnc, imsi, 5);
CM_Log(is_ctcc_sim2, "is_ctcc_sim: mcc/mnc %s\n", mccmnc);
for (i = 0; i < apn_num; i++) {
if (!strncmp(ctcc_mccmnc_table[i], mccmnc, strlen(mccmnc))) {
ret = true;
goto END;
}
}
END:
CM_Log(is_ctcc_sim3, "is_ctcc_sim: leave (%d)\n", ret);
return ret;
}
static void complete_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req) {
if (req->priv)
{
if (*(int *)(req->priv) == RIL_REQUEST_GET_IMSI)
{
CheckDataCallRegisterStatus_IndCallback();
free(req->priv);
}
}
free(req);
req = NULL;
}
}
int get_imsi(int sync, int switch_sim_done)
{
struct ubus_request *req = NULL;
int ret_val = UBUS_STATUS_OK;
int *priv_data = NULL;
CM_Log(get_imsi, "get_imsi: enter\n");
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_IMSI, NULL, 0);
if (sync) {
priv_data = malloc(sizeof(int));
if (!priv_data) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
*priv_data = switch_sim_done;
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, sim_info_request_cb, priv_data, 0)) != UBUS_STATUS_OK) {
CM_Log_E(get_imsi1, "get_imsi: ubus_invoke RIL_REQUEST_GET_IMSI failed %s\n", ubus_strerror(ret_val));
free(priv_data);
goto EXIT;
}
} else {
req = malloc(sizeof(struct ubus_request));
if (!req) {
CM_Log_E(get_imsi2, "get_imsi: malloc size %d failed\n", sizeof(struct ubus_request));
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
priv_data = malloc(sizeof(int));
if (!priv_data) {
CM_Log_E(get_imsi4, "get_imsi: malloc size %d failed\n", sizeof(int));
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
free(req);
goto EXIT;
}
*priv_data = RIL_REQUEST_GET_IMSI;
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(get_imsi3, "get_imsi: ubus_invoke RIL_REQUEST_GET_IMSI failed %s\n", ubus_strerror(ret_val));
free(req);
free(priv_data);
goto EXIT;
}
req->data_cb = sim_info_request_cb;
req->complete_cb = complete_cb;
req->priv = priv_data;
ubus_complete_request_async(cm_ctx, req);
}
if (ret_val > UBUS_STATUS_OK)
ret_val = -1;
else
ret_val = imsi_changed;
EXIT:
CM_Log(get_imsi4, "get_imsi: leave %d %d\n", ret_val, imsi_changed);
return ret_val;
}
void fill_data_profile_by_class(int apn_class, RIL_DataProfileInfo *data_profile)
{
int i;
Apn_Info *apn_info = NULL;
CM_Log(fill_data_profile_by_class, "fill_data_profile_by_class: enter\n");
for (i = 0; i < MAX_APN_NUM; i++) {
apn_info = &(g_work_apn->apn_info_list[i]);
if (apn_info->apn_class == apn_class) {
data_profile->profileId = apn_class;
if (strlen(apn_info->lte_apn))
data_profile->apn = strdup(apn_info->lte_apn);
else if (strlen(apn_info->apn))
data_profile->apn = strdup(apn_info->apn);
if (apn_info->iptype == 0)
data_profile->protocol = strdup("IPV4V6");
else if (apn_info->iptype == 1)
data_profile->protocol = strdup("IPV4");
else if (apn_info->iptype == 2)
data_profile->protocol = strdup("IPV6");
if (strlen(apn_info->lte_authtype))
data_profile->authType = convert_authtype_by_str(apn_info->lte_authtype);
else if (strlen(apn_info->authtype))
data_profile->authType = convert_authtype_by_str(apn_info->authtype);
if (strlen(apn_info->lte_usrname))
data_profile->user = strdup(apn_info->lte_usrname);
else if (strlen(apn_info->usrname))
data_profile->user = strdup(apn_info->usrname);
if (strlen(apn_info->lte_paswd))
data_profile->password = strdup(apn_info->lte_paswd);
else if (strlen(apn_info->paswd))
data_profile->password = strdup(apn_info->paswd);
data_profile->maxConnsTime = vzw_param_table[apn_class - 1].max_conn_time;
data_profile->maxConns= vzw_param_table[apn_class - 1].max_conn;
data_profile->waitTime= vzw_param_table[apn_class - 1].wait_time;
data_profile->enabled = 1;
CM_Log(fill_data_profile_by_class1, "fill_data_profile_by_class: apn class %d, apn %s, enabled %d\n", data_profile->profileId, data_profile->apn, data_profile->enabled );
/*TODO, set to 0 as default*/
data_profile->type = 1;
}
}
CM_Log(fill_data_profile_by_class2, "fill_data_profile_by_class: leave\n");
}
int config_vzw_apn_list()
{
int num = get_apn_list_number(g_work_apn);
RIL_DataProfileInfo dataProfiles[num];
RIL_DataProfileInfo *dataProfilePtrs[num];
int i, size, ret = UBUS_STATUS_OK;
CM_Log(config_vzw_apn_list, "config_vzw_apn_list: enter\n");
for (i = 0; i < num; i++) {
memset(&dataProfiles[i], 0, sizeof(RIL_DataProfileInfo));
dataProfilePtrs[i] = &dataProfiles[i];
fill_data_profile_by_class(i+1, dataProfilePtrs[i]);
}
/*here we should fill rilutil adapt*/
blob_buf_init(&cm_b, 0);
size = num * sizeof(RIL_DataProfileInfo *);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SET_DATA_PROFILE, (void *)dataProfilePtrs, size);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, NULL, 0, 0);
if (ret != CM_OK) {
CM_Log_E(config_vzw_apn_list1, "config_vzw_apn_list, ubus_invoke failed %s\n", ubus_strerror(ret));
}
for (i = 0; i < num; i++) {
if (dataProfiles[i].apn)
free(dataProfiles[i].apn);
if (dataProfiles[i].protocol)
free(dataProfiles[i].protocol);
if (dataProfiles[i].user)
free(dataProfiles[i].user);
if (dataProfiles[i].password)
free(dataProfiles[i].password);
}
CM_Log(config_vzw_apn_list2, "config_vzw_apn_list: leace, %d\n", ret);
return ret;
}
int config_apn_to_imsd(Mnc_Apn * work_apn, bool vzw_mode)
{
int i, size;
Apn_Info *apn_info = NULL;
int ret = UBUS_STATUS_OK;
char at_str[MAX_STR_LEN] = { '\0' };
char at_str_2[2*MAX_STR_LEN] = { '\0' };
char ip_type[MAX_STR_LEN] = { '\0' };
if (!work_apn) {
ret = UBUS_STATUS_INVALID_ARGUMENT;
goto end;
}
for (i = 0; i < MAX_APN_NUM; i++) {
apn_info = &(work_apn->apn_info_list[i]);
/*ONLY config when IMS APN enabled and connect mode is auto*/
if (apn_info->enable == 0 || apn_info->Extra_params.autoconnect == 0)
continue;
if (strlen(apn_info->type) == 0)
continue;
CM_Log(config_apn_to_imsd, "config_apn_to_imsd: type %s\n", apn_info->type);
if (!strcmp(apn_info->type, "ims")) {
CM_Log(config_apn_to_imsd1, "config_apn_to_imsd: found ims type\n");
if (apn_info->iptype == 0)
strncpy(ip_type, "IPv4v6", MAX_STR_LEN -1);
else if (apn_info->iptype == 1)
strncpy(ip_type, "IPv4", MAX_STR_LEN -1);
else if (apn_info->iptype ==2)
strncpy(ip_type, "IPv6", MAX_STR_LEN -1);
else
strncpy(ip_type, "IPv4v6", MAX_STR_LEN -1);
memset(at_str, 0, MAX_STR_LEN);
if (strlen(apn_info->lte_apn)) {
snprintf(at_str, MAX_STR_LEN - 1, "AT*IMSCFG=KEY_IMS_PDP_APN,%s,1", apn_info->lte_apn);
} else if (strlen(apn_info->apn)) {
snprintf(at_str, MAX_STR_LEN - 1, "AT*IMSCFG=KEY_IMS_PDP_APN,%s,1", apn_info->apn);
} else {
/*no APN info in work apn list, break*/
ret = UBUS_STATUS_NO_DATA;
CM_Log_E(config_apn_to_imsd2, "config_apn_to_imsd, no ims APN found\n");
goto end;
}
size = strlen(at_str) + 1;
CM_Log(config_apn_to_imsd3, "config_apn_to_imsd: configuring %s\n", at_str);
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(config_apn_to_imsd4, "config_apn_to_imsd, ubus_invoke failed %s\n", ubus_strerror(ret));
}
memset(at_str_2, 0, 2*MAX_STR_LEN);
snprintf(at_str_2, 2*MAX_STR_LEN - 1, "AT*IMSCFG=KEY_IMS_PDP_TYPE,%s,1", ip_type);
size = strlen(at_str_2) + 1;
CM_Log(config_apn_to_imsd5, "config_apn_to_imsd: configuring %s\n", at_str_2);
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str_2, 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(config_apn_to_imsd6, "config_apn_to_imsd, ubus_invoke failed %s\n", ubus_strerror(ret));
}
memset(at_str, 0, MAX_STR_LEN);
if (vzw_mode)
snprintf(at_str, MAX_STR_LEN - 1, "AT*IMSCFG=KEY_VERIZON_MODE,true,1");
else
snprintf(at_str, MAX_STR_LEN - 1, "AT*IMSCFG=KEY_VERIZON_MODE,false,1");
size = strlen(at_str) + 1;
CM_Log(config_apn_to_imsd7, "config_apn_to_imsd: configuring %s\n", at_str);
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(config_apn_to_imsd8, "config_apn_to_imsd, ubus_invoke failed %s\n", ubus_strerror(ret));
}
memset(at_str, 0, MAX_STR_LEN);
snprintf(at_str, MAX_STR_LEN - 1, "AT*IMSCFG=KEY_IMS_SUPPORT,true");
size = strlen(at_str) + 1;
CM_Log(config_apn_to_imsd9, "config_apn_to_imsd: configuring %s\n", at_str);
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(config_apn_to_imsd10, "config_apn_to_imsd, ubus_invoke failed %s\n", ubus_strerror(ret));
}
break;
}
}
end:
CM_Log(config_apn_to_imsd11, "config_apn_to_imsd: leave, %d\n", ret);
return ret;
}
Mnc_Apn *get_mnc_apn_info()
{
Mnc_Apn *apn_info = NULL;
if (strlen(g_cell_basic_info.IMSI) < 7) {
/* IMSI not get first */
CM_Log_E(get_mnc_apn_info1, "get_mnc_apn_info: imsi not get first\n");
goto end;
}
if (is_test_sim(g_cell_basic_info.IMSI)) {
CM_Log_E(get_mnc_apn_info2, "get_mnc_apn_info: test sim\n");
goto end;
}
if (!g_auto_apn_parsed) {
if (!IMSI_APN)
IMSI_APN = (Mnc_Apn *) wan_get_apn(g_cell_basic_info.IMSI);
if (IMSI_APN) {
g_auto_apn_parsed = 1;
apn_info = IMSI_APN;
} else {
CM_Log_E(get_mnc_apn_info3, "get_mnc_apn_info: wan get apn failed\n");
goto end;
}
}
else
{
apn_info = IMSI_APN;
}
end:
return apn_info;
}
int init_apn_list(void)
{
int ret_val = UBUS_STATUS_OK;
static int enter_times = 0;
bool is_vzw;
blob_buf_init(&cm_b, 0);
if (enter_times == 0) {
ret_val = set_dial_switch_to_cellular();
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(init_apn_list, "init_apn_list: set dial switch failed\n");
goto EXIT;
}
enter_times++;
}
ret_val = get_imsi(true, false);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(init_apn_list1, "init_apn_list: get imsi failed\n");
goto EXIT;
}
ret_val = CM_update_redialinterval(g_cell_basic_info.IMSI);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(init_apn_list5, "init_apn_list: update redial interval failed\n");
}
if (is_test_sim(g_cell_basic_info.IMSI)) {
CM_Log_E(init_apn_list3673, "init_apn_list: test sim\n");
goto update_apn;
}
if (!g_auto_apn_parsed) {
if (!IMSI_APN)
IMSI_APN = (Mnc_Apn *) wan_get_apn(g_cell_basic_info.IMSI);
if (IMSI_APN) {
g_auto_apn_parsed = 1;
} else {
CM_Log_E(init_apn_list2, "init_apn_list: wan get apn failed\n");
goto update_apn;
}
}
if (is_ctcc_sim(g_cell_basic_info.IMSI))
{
/* For NULL APN attached, dial with NULL APN will reuse APN from NW*/
get_etiflag();
}
is_vzw = is_vzw_sim(g_cell_basic_info.IMSI);
if (is_vzw) {
ret_val = update_vzw_work_apn();
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(init_apn_list3, "init_apn_list: update vzw work apn failed\n");
goto EXIT;
}
/*AP may do not need config the VZW APN LIST*/
#ifdef CONFIG_VZW_APN_LIST
config_vzw_apn_list();
#endif
} else {
update_apn:
ret_val = update_work_apn(IMSI_APN);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(init_apn_list4, "init_apn_list: update work apn failed\n");
goto EXIT;
}
}
/*here need config the APN info to IMSD*/
ret_val = config_apn_to_imsd(g_work_apn, is_vzw);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(init_apn_list6, "init_apn_list: config apn to imsd failed\n");
}
init_zgdcont_pdp_info();
EXIT:
CM_Log(init_apn_list7, "init_apn_list: done ret %d\n", ret_val);
return ret_val;
}
int reinit_apn_list()
{
int ret_val = UBUS_STATUS_OK;
bool is_vzw;
if (IMSI_APN) {
free(IMSI_APN);
IMSI_APN = NULL;
g_auto_apn_parsed = 0;
}
cm_query_admindata();
IMSI_APN = (Mnc_Apn *) wan_get_apn(g_cell_basic_info.IMSI);
if (IMSI_APN) {
g_auto_apn_parsed = 1;
}
is_vzw = is_vzw_sim(g_cell_basic_info.IMSI);
if (is_vzw) {
ret_val = update_vzw_work_apn();
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(reinit_apn_list0, "reinit_apn_list: update vzw work apn failed\n");
goto EXIT;
}
/*AP may do not need config the VZW APN LIST*/
#ifdef CONFIG_VZW_APN_LIST
config_vzw_apn_list();
#endif
} else {
ret_val = update_work_apn(IMSI_APN);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(reinit_apn_list1, "reinit_apn_list: update work apn failed\n");
goto EXIT;
}
}
ret_val = CM_update_redialinterval(g_cell_basic_info.IMSI);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(reinit_apn_list2, "reinit_apn_list: update redial interval failed\n");
}
#if 0
/*here need config the APN info to IMSD*/
ret_val = config_apn_to_imsd(g_work_apn, is_vzw);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(reinit_apn_list3, "reinit_apn_list: config apn to imsd failed\n");
}
#endif
/*clearup context*/
pthread_mutex_lock(&cm_mutex);
CM_Log(reinit_apn_list6057, "reinit_apn_list: cm_mutex locked\n");
CM_DeleteAllContext();
pthread_mutex_unlock(&cm_mutex);
CM_Log(reinit_apn_list6060, "reinit_apn_list: cm_mutex unlocked\n");
if (!cm_allow_datalink())
{
CM_Log(reinit_apn_list5853, "reinit_apn_list: cm not allow datalink\n");
return ret_val;
}
if (is_pdp_auto_mode(g_work_apn, "default")) {
CM_Log(reinit_apn_lis4, "reinit_apn_list: auto connect\n");
ret_val = connection_handler(g_work_apn);
}else {
CM_Log(reinit_apn_list5, "reinit_apn_list: query default data call\n");
dialer_query_defaultdatacall();
}
EXIT:
CM_Log(reinit_apn_list4, "reinit_apn_list: done\n");
return ret_val;
}
int RilIdReady(void)
{
if (!ubus_lookup_id(cm_ctx, RildName, &cm_ubus_id.ril_id))
return 1;
return 0;
}
int SimReady(void)
{
if (!ubus_lookup_id(cm_ctx, "ril.unsol.sim", &cm_ubus_id.sim_id))
return 1;
return 0;
}
int WaitForSimReady(void)
{
int ret;
int retries = 0;
CM_Log(WaitForSimReady, "WaitForSimReady: enter\n");
ret = ubus_register_subscriber(cm_ctx, &ind_event);
if (ret) {
CM_Log_E(WaitForSimReady1, "WaitForSimReady: Failed to register subscriber %s\n", ubus_strerror(ret));
return -1;
}
ind_event.cb = Ind_notify;
do {
if (SimReady()) {
CM_Log(WaitForSimReady2, "WaitForSimReady: SIM ind object ready\n");
break;
}
sleep(1);
} while (retries++ < RIL_MAX_RETRIES);
if (retries >= RIL_MAX_RETRIES) {
CM_Log_E(WaitForSimReady3, "WaitForSimReady: Failed to look up ril.unsol.sim object\n");
return -1;
}
ret = ubus_subscribe(cm_ctx, &ind_event, cm_ubus_id.sim_id);
if (ret) {
CM_Log_E(WaitForSimReady4, "WaitForSimReady: Failed to subscribe object:ril.unsol.sim %s\n", ubus_strerror(ret));
return -1;
}
if (QuerySimStatus() < 0)
return -1;
SetCPPowerInd(1);
if (pin_status == RIL_APPSTATE_READY)
wait_for_sim_ready = 0;
if (wait_for_sim_ready) {
CM_Log(WaitForSimReady5, "WaitForSimReady: wait for sim ready\n");
uloop_run();
wait_for_sim_ready = 0;
}
if (pin_status != RIL_APPSTATE_READY) {
CM_Log_E(WaitForSimReady6, "WaitForSimReady: pin is not ready\n");
return -1;
}
CM_Log(WaitForSimReady7, "WaitForSimReady: leave\n");
return 0;
}
const char *RilRequestToString(int request)
{
switch (request) {
case RIL_REQUEST_GET_SIM_STATUS:
return "GET_SIM_STATUS";
case RIL_REQUEST_ENTER_SIM_PIN:
return "ENTER_SIM_PIN";
case RIL_REQUEST_ENTER_SIM_PUK:
return "ENTER_SIM_PUK";
case RIL_REQUEST_ENTER_SIM_PIN2:
return "ENTER_SIM_PIN2";
case RIL_REQUEST_ENTER_SIM_PUK2:
return "ENTER_SIM_PUK2";
case RIL_REQUEST_CHANGE_SIM_PIN:
return "CHANGE_SIM_PIN";
case RIL_REQUEST_CHANGE_SIM_PIN2:
return "CHANGE_SIM_PIN2";
case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION:
return "ENTER_NETWORK_DEPERSONALIZATION";
case RIL_REQUEST_GET_CURRENT_CALLS:
return "GET_CURRENT_CALLS";
case RIL_REQUEST_DIAL:
return "DIAL";
case RIL_REQUEST_GET_IMSI:
return "GET_IMSI";
case RIL_REQUEST_HANGUP:
return "HANGUP";
case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:
return "HANGUP_WAITING_OR_BACKGROUND";
case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:
return "HANGUP_FOREGROUND_RESUME_BACKGROUND";
case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:
return "SWITCH_WAITING_OR_HOLDING_AND_ACTIVE";
case RIL_REQUEST_CONFERENCE:
return "CONFERENCE";
case RIL_REQUEST_UDUB:
return "UDUB";
case RIL_REQUEST_LAST_CALL_FAIL_CAUSE:
return "LAST_CALL_FAIL_CAUSE";
case RIL_REQUEST_SIGNAL_STRENGTH:
return "SIGNAL_STRENGTH";
case RIL_REQUEST_VOICE_REGISTRATION_STATE:
return "VOICE_REGISTRATION_STATE";
case RIL_REQUEST_DATA_REGISTRATION_STATE:
return "DATA_REGISTRATION_STATE";
case RIL_REQUEST_OPERATOR:
return "OPERATOR";
case RIL_REQUEST_RADIO_POWER:
return "RADIO_POWER";
case RIL_REQUEST_DTMF:
return "DTMF";
case RIL_REQUEST_SEND_SMS:
return "SEND_SMS";
case RIL_REQUEST_SEND_SMS_EXPECT_MORE:
return "SEND_SMS_EXPECT_MORE";
case RIL_REQUEST_SETUP_DATA_CALL:
return "SETUP_DATA_CALL";
case RIL_REQUEST_SIM_IO:
return "SIM_IO";
case RIL_REQUEST_SEND_USSD:
return "SEND_USSD";
case RIL_REQUEST_CANCEL_USSD:
return "CANCEL_USSD";
case RIL_REQUEST_GET_CLIR:
return "GET_CLIR";
case RIL_REQUEST_SET_CLIR:
return "SET_CLIR";
case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS:
return "QUERY_CALL_FORWARD_STATUS";
case RIL_REQUEST_SET_CALL_FORWARD:
return "SET_CALL_FORWARD";
case RIL_REQUEST_QUERY_CALL_WAITING:
return "QUERY_CALL_WAITING";
case RIL_REQUEST_SET_CALL_WAITING:
return "SET_CALL_WAITING";
case RIL_REQUEST_SMS_ACKNOWLEDGE:
return "SMS_ACKNOWLEDGE";
case RIL_REQUEST_GET_IMEI:
return "GET_IMEI";
case RIL_REQUEST_GET_IMEISV:
return "GET_IMEISV";
case RIL_REQUEST_ANSWER:
return "ANSWER";
case RIL_REQUEST_DEACTIVATE_DATA_CALL:
return "DEACTIVATE_DATA_CALL";
case RIL_REQUEST_QUERY_FACILITY_LOCK:
return "QUERY_FACILITY_LOCK";
case RIL_REQUEST_SET_FACILITY_LOCK:
return "SET_FACILITY_LOCK";
case RIL_REQUEST_CHANGE_BARRING_PASSWORD:
return "CHANGE_BARRING_PASSWORD";
case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:
return "QUERY_NETWORK_SELECTION_MODE";
case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:
return "SET_NETWORK_SELECTION_AUTOMATIC";
case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL:
return "SET_NETWORK_SELECTION_MANUAL";
case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS:
return "QUERY_AVAILABLE_NETWORKS ";
case RIL_REQUEST_DTMF_START:
return "DTMF_START";
case RIL_REQUEST_DTMF_STOP:
return "DTMF_STOP";
case RIL_REQUEST_BASEBAND_VERSION:
return "BASEBAND_VERSION";
case RIL_REQUEST_SEPARATE_CONNECTION:
return "SEPARATE_CONNECTION";
case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE:
return "SET_PREFERRED_NETWORK_TYPE";
case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE:
return "GET_PREFERRED_NETWORK_TYPE";
case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS:
return "GET_NEIGHBORING_CELL_IDS";
case RIL_REQUEST_SET_MUTE:
return "SET_MUTE";
case RIL_REQUEST_GET_MUTE:
return "GET_MUTE";
case RIL_REQUEST_QUERY_CLIP:
return "QUERY_CLIP";
case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE:
return "LAST_DATA_CALL_FAIL_CAUSE";
case RIL_REQUEST_DATA_CALL_LIST:
return "DATA_CALL_LIST";
case RIL_REQUEST_RESET_RADIO:
return "RESET_RADIO";
case RIL_REQUEST_OEM_HOOK_RAW:
return "OEM_HOOK_RAW";
case RIL_REQUEST_OEM_HOOK_STRINGS:
return "OEM_HOOK_STRINGS";
case RIL_REQUEST_SET_BAND_MODE:
return "SET_BAND_MODE";
case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE:
return "QUERY_AVAILABLE_BAND_MODE";
case RIL_REQUEST_STK_GET_PROFILE:
return "STK_GET_PROFILE";
case RIL_REQUEST_STK_SET_PROFILE:
return "STK_SET_PROFILE";
case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND:
return "STK_SEND_ENVELOPE_COMMAND";
case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE:
return "STK_SEND_TERMINAL_RESPONSE";
case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM:
return "STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM";
case RIL_REQUEST_SCREEN_STATE:
return "SCREEN_STATE";
case RIL_REQUEST_EXPLICIT_CALL_TRANSFER:
return "EXPLICIT_CALL_TRANSFER";
case RIL_REQUEST_SET_LOCATION_UPDATES:
return "SET_LOCATION_UPDATES";
case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE:
return "CDMA_SET_SUBSCRIPTION_SOURCE";
case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE:
return "CDMA_SET_ROAMING_PREFERENCE";
case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE:
return "CDMA_QUERY_ROAMING_PREFERENCE";
case RIL_REQUEST_SET_TTY_MODE:
return "SET_TTY_MODE";
case RIL_REQUEST_QUERY_TTY_MODE:
return "QUERY_TTY_MODE";
case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE:
return "CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE";
case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE:
return "CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE";
case RIL_REQUEST_CDMA_FLASH:
return "CDMA_FLASH";
case RIL_REQUEST_CDMA_BURST_DTMF:
return "CDMA_BURST_DTMF";
case RIL_REQUEST_CDMA_SEND_SMS:
return "CDMA_SEND_SMS";
case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE:
return "CDMA_SMS_ACKNOWLEDGE";
case RIL_REQUEST_GSM_GET_BROADCAST_SMS_CONFIG:
return "GSM_GET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_GSM_SET_BROADCAST_SMS_CONFIG:
return "GSM_SET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG:
return "CDMA_GET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG:
return "CDMA_SET_BROADCAST_SMS_CONFIG";
case RIL_REQUEST_CDMA_SMS_BROADCAST_ACTIVATION:
return "CDMA_SMS_BROADCAST_ACTIVATION";
case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY:
return "CDMA_VALIDATE_AND_WRITE_AKEY";
case RIL_REQUEST_CDMA_SUBSCRIPTION:
return "CDMA_SUBSCRIPTION";
case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM:
return "CDMA_WRITE_SMS_TO_RUIM";
case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM:
return "CDMA_DELETE_SMS_ON_RUIM";
case RIL_REQUEST_DEVICE_IDENTITY:
return "DEVICE_IDENTITY";
case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE:
return "EXIT_EMERGENCY_CALLBACK_MODE";
case RIL_REQUEST_GET_SMSC_ADDRESS:
return "GET_SMSC_ADDRESS";
case RIL_REQUEST_SET_SMSC_ADDRESS:
return "SET_SMSC_ADDRESS";
case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS:
return "REPORT_SMS_MEMORY_STATUS";
case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING:
return "REPORT_STK_SERVICE_IS_RUNNING";
case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE:
return "CDMA_GET_SUBSCRIPTION_SOURCE";
case RIL_REQUEST_ISIM_AUTHENTICATION:
return "ISIM_AUTHENTICATION";
case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU:
return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU";
case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS:
return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS";
case RIL_REQUEST_VOICE_RADIO_TECH:
return "VOICE_RADIO_TECH";
case RIL_REQUEST_GET_CELL_INFO_LIST:
return "GET_CELL_INFO_LIST";
case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE:
return "SET_UNSOL_CELL_INFO_LIST_RATE";
case RIL_REQUEST_SET_INITIAL_ATTACH_APN:
return "RIL_REQUEST_SET_INITIAL_ATTACH_APN";
case RIL_REQUEST_IMS_REGISTRATION_STATE:
return "IMS_REGISTRATION_STATE";
case RIL_REQUEST_IMS_SEND_SMS:
return "IMS_SEND_SMS";
case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC:
return "SIM_TRANSMIT_APDU_BASIC";
case RIL_REQUEST_SIM_OPEN_CHANNEL:
return "SIM_OPEN_CHANNEL";
case RIL_REQUEST_SIM_CLOSE_CHANNEL:
return "SIM_CLOSE_CHANNEL";
case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
return "SIM_TRANSMIT_APDU_CHANNEL";
case RIL_REQUEST_SET_UICC_SUBSCRIPTION:
return "SET_UICC_SUBSCRIPTION";
case RIL_REQUEST_ALLOW_DATA:
return "ALLOW_DATA";
case RIL_REQUEST_GET_HARDWARE_CONFIG:
return "GET_HARDWARE_CONFIG";
case RIL_REQUEST_SIM_AUTHENTICATION:
return "SIM_AUTHENTICATION";
case RIL_REQUEST_GET_DC_RT_INFO:
return "GET_DC_RT_INFO";
case RIL_REQUEST_SET_DC_RT_INFO_RATE:
return "SET_DC_RT_INFO_RATE";
case RIL_REQUEST_SET_DATA_PROFILE:
return "SET_DATA_PROFILE";
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
return "UNSOL_RESPONSE_RADIO_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
return "UNSOL_RESPONSE_CALL_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:
return "UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED";
case RIL_UNSOL_RESPONSE_NEW_SMS:
return "UNSOL_RESPONSE_NEW_SMS";
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:
return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT";
case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM:
return "UNSOL_RESPONSE_NEW_SMS_ON_SIM";
case RIL_UNSOL_ON_USSD:
return "UNSOL_ON_USSD";
case RIL_UNSOL_ON_USSD_REQUEST:
return "UNSOL_ON_USSD_REQUEST(obsolete)";
case RIL_UNSOL_NITZ_TIME_RECEIVED:
return "UNSOL_NITZ_TIME_RECEIVED";
case RIL_UNSOL_SIGNAL_STRENGTH:
return "UNSOL_SIGNAL_STRENGTH";
case RIL_UNSOL_STK_SESSION_END:
return "UNSOL_STK_SESSION_END";
case RIL_UNSOL_STK_PROACTIVE_COMMAND:
return "UNSOL_STK_PROACTIVE_COMMAND";
case RIL_UNSOL_STK_EVENT_NOTIFY:
return "UNSOL_STK_EVENT_NOTIFY";
case RIL_UNSOL_STK_CALL_SETUP:
return "UNSOL_STK_CALL_SETUP";
case RIL_UNSOL_SIM_SMS_STORAGE_FULL:
return "UNSOL_SIM_SMS_STORAGE_FUL";
case RIL_UNSOL_SIM_REFRESH:
return "UNSOL_SIM_REFRESH";
case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
return "UNSOL_DATA_CALL_LIST_CHANGED";
case RIL_UNSOL_CALL_RING:
return "UNSOL_CALL_RING";
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
return "UNSOL_RESPONSE_SIM_STATUS_CHANGED";
case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:
return "UNSOL_NEW_CDMA_SMS";
case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:
return "UNSOL_NEW_BROADCAST_SMS";
case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:
return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL";
case RIL_UNSOL_RESTRICTED_STATE_CHANGED:
return "UNSOL_RESTRICTED_STATE_CHANGED";
case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE:
return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE";
case RIL_UNSOL_CDMA_CALL_WAITING:
return "UNSOL_CDMA_CALL_WAITING";
case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS:
return "UNSOL_CDMA_OTA_PROVISION_STATUS";
case RIL_UNSOL_CDMA_INFO_REC:
return "UNSOL_CDMA_INFO_REC";
case RIL_UNSOL_OEM_HOOK_RAW:
return "UNSOL_OEM_HOOK_RAW";
case RIL_UNSOL_RINGBACK_TONE:
return "UNSOL_RINGBACK_TONE";
case RIL_UNSOL_RESEND_INCALL_MUTE:
return "UNSOL_RESEND_INCALL_MUTE";
case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
return "UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED";
case RIL_UNSOL_CDMA_PRL_CHANGED:
return "UNSOL_CDMA_PRL_CHANGED";
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE:
return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE";
case RIL_UNSOL_RIL_CONNECTED:
return "UNSOL_RIL_CONNECTED";
case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED:
return "UNSOL_VOICE_RADIO_TECH_CHANGED";
case RIL_UNSOL_CELL_INFO_LIST:
return "UNSOL_CELL_INFO_LIST";
case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED:
return "RESPONSE_IMS_NETWORK_STATE_CHANGED";
case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED:
return "UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED";
case RIL_UNSOL_SRVCC_STATE_NOTIFY:
return "UNSOL_SRVCC_STATE_NOTIFY";
case RIL_UNSOL_HARDWARE_CONFIG_CHANGED:
return "HARDWARE_CONFIG_CHANGED";
case RIL_UNSOL_DC_RT_INFO_CHANGED:
return "UNSOL_DC_RT_INFO_CHANGED";
case RIL_REQUEST_SHUTDOWN:
return "SHUTDOWN";
#ifdef MARVELL_EXTENDED
case RIL_REQUEST_DIAL_VT:
return "DIAL_VT";
case RIL_REQUEST_HANGUP_VT:
return "HANGUP_VT";
case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL_EXT:
return "SET_NETWORK_SELECTION_MANUAL_EXT";
case RIL_REQUEST_QUERY_COLP:
return "QUERY_COLP";
case RIL_REQUEST_SET_CLIP:
return "SET_CLIP";
case RIL_REQUEST_SET_COLP:
return "SET_COLP";
case RIL_REQUEST_GET_CNAP:
return "GET_CNAP";
case RIL_REQUEST_SET_CNAP:
return "SET_CNAP";
case RIL_REQUEST_QUERY_COLR:
return "QUERY_COLR";
case RIL_REQUEST_SET_COLR:
return "SET_COLR";
case RIL_REQUEST_LOCK_INFO:
return "LOCK_INFO";
case RIL_REQUEST_SIM_GET_ATR:
return "SIM_GET_ATR";
case RIL_UNSOL_STK_CALL_SETUP_STATUS:
return "UNSOL_STK_CALL_SETUP_STATUS";
case RIL_UNSOL_STK_CALL_SETUP_RESULT:
return "UNSOL_STK_CALL_SETUP_RESULT";
case RIL_UNSOL_STK_SEND_SM_STATUS:
return "UNSOL_STK_SEND_SM_STATUS";
case RIL_UNSOL_STK_SEND_SM_RESULT:
return "UNSOL_STK_SEND_SM_RESULT";
case RIL_UNSOL_STK_SEND_USSD_RESULT:
return "UNSOL_STK_SEND_USSD_RESULT";
case RIL_UNSOL_CP_PHONEBOOK_INITED:
return "UNSOL_CP_PHONEBOOK_INITED";
case RIL_REQUEST_GET_CP_PHONEBOOK_STATUS:
return "GET_CP_PHONEBOOK_STATUS";
case RIL_UNSOL_VZW_PCO_ACTION:
return "RIL_UNSOL_VZW_PCO_ACTION";
case RIL_UNSOL_SIM_HOT_PLUG_EVENT:
return "UNSOL_SIM_HOT_PLUG_EVENT";
case RIL_REQUEST_SET_CSCS:
return "SET DTE charset";
case RIL_REQUEST_GET_SIM_CONTACT:
return "Get contact from SIM";
case RIL_REQUEST_ADD_CONTACT_IN_SIM:
return "Add contact to SIM";
case RIL_REQUEST_DELETE_CONTACT_IN_SIM:
return "Delete contact from SIM";
case RIL_REQUEST_UPDATE_CONTACT_IN_SIM:
return "Update contact from SIM";
case RIL_REQUEST_SET_PS_ATTACH_STATUS:
return "SET_PS_ATTACH_STATUS";
case RIL_REQUEST_GET_PS_ATTACH_STATUS:
return "GET_PS_ATTACH_STATUS";
case RIL_UNSOL_PDP_REJECT_CAUSE:
return "UNSOL_PDP_REJECT_CAUSE";
case RIL_UNSOL_PS_ATTACH_STATUS:
return "UNSOL_PS_ATTACH_STATUS";
case RIL_REQUEST_SET_EMBMS:
return "Send eMBMS Command";
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT:
return "UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT";
case RIL_UNSOL_CALL_NO_CARRIER_EXT:
return "RIL_UNSOL_CALL_NO_CARRIER_EXT";
case RIL_REQUEST_CLEAR_ETIFLAG:
return "Clear ETI FLAG";
case RIL_REQUEST_SET_EEMOPT:
return "RIL_REQUEST_SET_EEMOPT";
case RIL_REQUEST_GET_EEMGINFO:
return "RIL_REQUEST_GET_EEMGINFO";
case RIL_REQUEST_SET_MODEM_VERSION:
return "RIL_REQUEST_SET_MODEM_VERSION";
case RIL_UNSOL_EEM_INFOSVC:
return "RIL_UNSOL_EEM_INFOSVC";
case RIL_UNSOL_EEM_UMTSSVC:
return "RIL_UNSOL_EEM_UMTSSVC";
case RIL_UNSOL_EEM_LTESVC:
return "RIL_UNSOL_EEM_LTESVC";
case RIL_UNSOL_EEM_MODESTATE:
return "RIL_UNSOL_EEM_MODESTATE";
case RIL_UNSOL_EEM_INFOPS:
return "RIL_UNSOL_EEM_INFOPS";
case RIL_UNSOL_EEM_INFONC:
return "RIL_UNSOL_EEM_INFONC";
case RIL_UNSOL_EEM_INBFTM:
return "RIL_UNSOL_EEM_INBFTM";
case RIL_UNSOL_EEM_INFOGMM:
return "RIL_UNSOL_EEM_INFOGMM";
case RIL_UNSOL_EEM_LTEINTRA:
return "RIL_UNSOL_EEM_LTEINTRA";
case RIL_UNSOL_EEM_LTEINTER:
return "RIL_UNSOL_EEM_LTEINTER";
case RIL_UNSOL_EEM_UMTSINTER:
return "RIL_UNSOL_EEM_UMTSINTER";
case RIL_UNSOL_EEM_UMTSINTRA:
return "RIL_UNSOL_EEM_UMTSINTRA";
case RIL_UNSOL_EEM_UMTSINTERRAT:
return "RIL_UNSOL_EEM_UMTSINTERRAT";
case RIL_UNSOL_PDP_DEACTIVE_CID:
return "RIL_UNSOL_PDP_DEACTIVE_CID";
case RIL_UNSOL_STAR_CGTFT:
return "RIL_UNSOL_STAR_CGTFT";
case RIL_UNSOL_PDP_TFT_MODIFY:
return "RIL_UNSOL_PDP_TFT_MODIFY";
case RIL_UNSOL_CGTFT:
return "RIL_UNSOL_CGTFT";
#endif
default:
return "<unknown request>";
}
}