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