#include #include #include #include #include #include #include #include "wifi_event.h" #include "network_manager.h" #include "wifi_intf.h" #include "wifi.h" #include "tool.h" #define WAITING_CLK_COUNTS 50 #define SSID_LEN 512 #define UTF8_BYTES_MAX 4096 #define UTF8_MULTI_BYTES_MASK 0x80 #define ESCAP_CHAR_ASCII '\\' #define DQUOT_CHAR_ASCII '\"' #define QUOT_CHAR_ASCII '\'' /* scan thread */ static pthread_t scan_thread_id; static int scan_running = 0; static int scan_terminating = 0; static pthread_mutex_t scan_mutex; static pthread_cond_t scan_cond; static int scan_pause = 0; static int scan_error = 0; static int do_scan_flag = 1; /* run scan immediately */ static pthread_mutex_t thread_run_mutex; static pthread_cond_t thread_run_cond; /*stop restart scan*/ static pthread_mutex_t scan_stop_restart_mutex; static pthread_cond_t scan_stop_restart_cond; /* store scan results */ static char scan_results[SCAN_BUF_LEN]; static int scan_results_len = 0; static int scan_completed = 0; enum wpa_states wpa_supplicant_state_convert(char *str) { if(!strncmp(str,"DISCONNECTED",16)){ return WPA_DISCONNECTED; } if(!strncmp(str,"INTERFACE_DISABLED",22)){ return WPA_INTERFACE_DISABLED; } if(!strncmp(str,"INACTIVE",12)){ return WPA_INACTIVE; } if(!strncmp(str,"SCANNING",12)){ return WPA_SCANNING; } if(!strncmp(str,"AUTHENTICATING",18)){ return WPA_AUTHENTICATING; } if(!strncmp(str,"ASSOCIATED",14)){ return WPA_ASSOCIATED; } if(!strncmp(str,"4WAY_HANDSHAKE",19)){ return WPA_4WAY_HANDSHAKE; } if(!strncmp(str,"GROUP_HANDSHAKE",19)){ return WPA_GROUP_HANDSHAKE; } if(!strncmp(str,"COMPLETED",13)){ return WPA_COMPLETED; } if(!strncmp(str,"DISCONNECTED",16)){ return WPA_DISCONNECTED; } return WPA_UNKNOWN; } static const char * wpa_supplicant_state_txt(enum wpa_states state) { switch (state) { case WPA_DISCONNECTED: return "DISCONNECTED"; case WPA_INACTIVE: return "INACTIVE"; case WPA_INTERFACE_DISABLED: return "INTERFACE_DISABLED"; case WPA_SCANNING: return "SCANNING"; case WPA_AUTHENTICATING: return "AUTHENTICATING"; case WPA_ASSOCIATING: return "ASSOCIATING"; case WPA_ASSOCIATED: return "ASSOCIATED"; case WPA_4WAY_HANDSHAKE: return "4WAY_HANDSHAKE"; case WPA_GROUP_HANDSHAKE: return "GROUP_HANDSHAKE"; case WPA_COMPLETED: return "COMPLETED"; default: return "UNKNOWN"; } } void print_wpa_status(struct wpa_status *wpa_sta) { LOG_EX(LOG_Debug, "obtained wpa_supplicant status,as follow:\n"); LOG_EX(LOG_Debug, "==============================\n"); if(wpa_sta->id >= 0) LOG_EX(LOG_Debug, "id:%d\n",wpa_sta->id); if(wpa_sta->bssid) LOG_EX(LOG_Debug, "bssid:%s\n",wpa_sta->bssid); if(wpa_sta->freq >=0) LOG_EX(LOG_Debug, "freq:%d\n",wpa_sta->freq); if(wpa_sta->ssid) LOG_EX(LOG_Debug, "ssid:%s\n",wpa_sta->ssid); if(wpa_sta->wpa_state) LOG_EX(LOG_Debug, "wpa_state:%s\n",wpa_supplicant_state_txt(wpa_sta->wpa_state)); if(wpa_sta->ip_address) LOG_EX(LOG_Debug, "ip_address:%s\n",wpa_sta->ip_address); if(wpa_sta->key_mgmt) LOG_EX(LOG_Debug, "key_mgmt:%s\n",wpa_sta->key_mgmt); if(wpa_sta->mac_address) LOG_EX(LOG_Debug, "mac_address:%s\n",wpa_sta->mac_address); LOG_EX(LOG_Debug, "==============================\n"); } static char *strstr_wpa(const char *src,const char *obj, const char pre_str[2],int pst_len) { const char *p=src; int length; int i=0; if(src == NULL || obj == NULL || pre_str ==NULL){ LOG_EX(LOG_Debug, "src or obj or pre_str is NULL"); return NULL; } if(pst_len > strlen(pre_str)){ LOG_EX(LOG_Debug, "pst_len length is illegal"); return NULL; } length = strlen(obj); for(;;p++,i++){ p=strchr(p,*obj); if(p == NULL){ LOG_EX(LOG_Debug, "%s is not exist",obj); return NULL; } if(strncmp(p,obj,length) == 0){ if(i > 1 && *(p-1) != pre_str[0] && *(p-1) != pre_str[1]){ return (char*)p; } } } } static int search_wpa_string(const char *src,const char *obj,int max,char *get_str) { int i=0; const char *sptr = NULL; const char *pnext = NULL; if(obj == NULL || src == NULL){ wmg_printf(MSG_DEBUG,"src or obj is NULL"); return 0; } if(!strncmp("id=",obj,3)){ sptr = strstr_wpa(src,obj,"su",2); }else if(!strncmp("ssid=",obj,5)){ sptr = strstr_wpa(src,obj,"bb",2); }else if(!strncmp("address=",obj,8)){ sptr = strstr_wpa(src,obj,"__",2); }else{ sptr = strstr(src, obj); } if(sptr !=NULL){ pnext=sptr+strlen(obj); i=0; while(1){ i++; if(i >max ){ LOG_EX(LOG_Debug, "Data overflow"); break; } pnext++; if(*pnext == '\n') break; } strncpy(get_str,sptr+strlen(obj),i); get_str[i]='\0'; return 1; } return -1; } static struct wpa_status *gstatus; static struct wpa_status* wpa_status_init() { int i; if(gstatus == NULL) gstatus = (struct wpa_status *)wgos_zalloc(sizeof(struct wpa_status)); if(gstatus == NULL){ LOG_EX(LOG_Debug, "MALLOC STATUS STRUCT FAILED!\n"); return NULL; } gstatus->id = -1; gstatus->freq = -1; for(i = 0;i< WPA_STA_MAX_SSID;i++){ gstatus->ssid[i] = '\0'; if(i < WPA_STA_MAX_BSSID) gstatus->bssid[i] = '\0'; if(i < WPA_STA_MAX_IP_ADDR) gstatus->ip_address[i] = '\0'; if(i < WPA_STA_MAX_KEY_MGMT) gstatus->key_mgmt[i]='\0'; if(i < WPA_STA_MAX_MAC_ADDR) gstatus->mac_address[i]='\0'; } gstatus->wpa_state = WPA_UNKNOWN; return gstatus; } void wpa_status_free() { if(gstatus !=NULL) free(gstatus); } struct wpa_status * get_wpa_status() { char reply[4096] = {0}; char wpa_result[32]; struct wpa_status *wpa_sta; wpa_sta = wpa_status_init(); wifi_command("STATUS", reply, sizeof(reply)); if(reply !=NULL){ if(search_wpa_string(reply,"ssid=",32,wpa_result) >0) strncpy(wpa_sta->ssid,wpa_result,strlen(wpa_result)); if(search_wpa_string(reply,"id=",4,wpa_result) >0) wpa_sta->id = atoi(wpa_result); if(search_wpa_string(reply,"freq=",6,wpa_result) >0) wpa_sta->freq = atoi(wpa_result); if(search_wpa_string(reply,"bssid=",18,wpa_result) >0) strncpy(wpa_sta->bssid,wpa_result,strlen(wpa_result)); if(search_wpa_string(reply,"key_mgmt=",16,wpa_result) >0) strncpy(wpa_sta->key_mgmt,wpa_result,strlen(wpa_result)); if(search_wpa_string(reply,"wpa_state=",32,wpa_result) >0) wpa_sta->wpa_state = wpa_supplicant_state_convert(wpa_result); if(search_wpa_string(reply,"address=",18,wpa_result) >0) strncpy(wpa_sta->mac_address,wpa_result,strlen(wpa_result)); if(search_wpa_string(reply,"ip_address=",16,wpa_result) >0) strncpy(wpa_sta->ip_address,wpa_result,strlen(wpa_result)); } if(wmg_get_debug_level() >= MSG_DEBUG){ print_wpa_status(wpa_sta); } return wpa_sta; } int update_scan_results() { int i=0; LOG_EX(LOG_Debug, "update scan results enter\n"); pthread_mutex_lock(&thread_run_mutex); scan_completed = 0; pthread_cond_signal(&thread_run_cond); pthread_mutex_unlock(&thread_run_mutex); while(i <= 15){ usleep(200*1000); if(scan_completed == 1){ break; } i++; } return 0; } int remove_slash_from_scan_results() { char *ptr = NULL; char *ptr_s = NULL; char *ftr = NULL; ptr_s = scan_results; while(1) { ptr = strchr(ptr_s,'\"'); if(ptr == NULL) break; ptr_s = ptr; if((*(ptr-1)) == '\\') { ftr = ptr; ptr -= 1; while(*ftr != '\0') *(ptr++) = *(ftr++); *ptr = '\0'; continue; //restart new search at ptr_s after removing slash } else ptr_s++; //restart new search at ptr_s++ } ptr_s = scan_results; while(1) { ptr = strchr(ptr_s,'\\'); if(ptr == NULL) break; ptr_s = ptr; if((*(ptr-1)) == '\\') { ftr = ptr; ptr -= 1; while(*ftr != '\0') *(ptr++) = *(ftr++); *ptr = '\0'; continue; //restart new search at ptr_s after removing slash } else ptr_s++; //restart new search at ptr_s++ } return 0; } int get_scan_results_inner(char *result, int *len) { int index = 0; char *ptr = NULL; int ret = 0; pthread_mutex_lock(&scan_mutex); if(0 != scan_error) { // prinf("%s: scan or scan_results ERROR in scan_thread!\n", __func__); ret = -1; } remove_slash_from_scan_results(); if(*len <= scan_results_len){ strncpy(result, scan_results, *len-1); index = *len -1; result[index] = '\0'; ptr=strrchr(result, '\n'); if(ptr != NULL){ *ptr = '\0'; } }else{ strncpy(result, scan_results, scan_results_len); result[scan_results_len] = '\0'; } pthread_mutex_unlock(&scan_mutex); return ret; } int is_network_exist(const char *ssid, tKEY_MGMT key_mgmt) { int ret = 0, i = 0, key[4] = {0}; for(i=0; i<4; i++){ key[i]=0; } get_key_mgmt(ssid, key); if(key_mgmt == WIFIMG_NONE){ if(key[0] == 1){ ret = 1; } }else if(key_mgmt == WIFIMG_WPA_PSK || key_mgmt == WIFIMG_WPA2_PSK){ if(key[1] == 1){ ret = 1; } }else if(key_mgmt == WIFIMG_WEP){ if(key[2] == 1){ ret = 1; } }else{ ; } return ret; } char getHalfByteCharac(char val) { char ret =-1; if(9 >= (val&0x0f)) ret = (val&0x0f)+'0'; else ret = (val&0x0f)-10+'a'; return ret; } int utf8BytesExchangeEx(char *pCharIn,char ** pCharOut) { int size =0; char * p_data = NULL; char buf[UTF8_BYTES_MAX]={0x00}; int index =0; int cpPos=0; if(NULL == pCharIn) { return -1; } size =strlen(pCharIn); p_data = pCharIn; while(index<= size) { if(0 != ( (*p_data)&UTF8_MULTI_BYTES_MASK)) { buf[cpPos++]='\\'; buf[cpPos++]='x'; buf[cpPos++]= getHalfByteCharac((*p_data)>>4); buf[cpPos++]= getHalfByteCharac((*p_data)&0xf); }else if( (*p_data) == ESCAP_CHAR_ASCII) { buf[cpPos++] = ESCAP_CHAR_ASCII; buf[cpPos++] = ESCAP_CHAR_ASCII; }else if( (*p_data) == DQUOT_CHAR_ASCII) { buf[cpPos++] = ESCAP_CHAR_ASCII; buf[cpPos++] = DQUOT_CHAR_ASCII; }else if((*p_data) == QUOT_CHAR_ASCII) { buf[cpPos++] = QUOT_CHAR_ASCII; } else { buf[cpPos++] = *p_data; } index++; p_data++; } * pCharOut = malloc(strlen(buf)+1); if(NULL == * pCharOut) return -1; memset(* pCharOut,0x00,strlen(buf)+1); memcpy(* pCharOut,buf,strlen(buf)); return 0; } int get_key_mgmt(const char *ssid, int key_mgmt_info[]) { char *ptr = NULL, *pssid_start = NULL, *pssid_end = NULL; char *pst = NULL, *pend = NULL; char *pflag = NULL; char flag[128], pssid[SSID_LEN + 1]; int len = 0, i = 0; LOG_EX(LOG_Debug, "enter get_key_mgmt, ssid %s\n", ssid); key_mgmt_info[KEY_NONE_INDEX] = 0; key_mgmt_info[KEY_WEP_INDEX] = 0; key_mgmt_info[KEY_WPA_PSK_INDEX] = 0; pthread_mutex_lock(&scan_mutex); /* first line end */ ptr = strchr(scan_results, '\n'); if(!ptr){ pthread_mutex_unlock(&scan_mutex); LOG_EX(LOG_Debug, "no ap scan, return\n"); return 0; } //point second line of scan results ptr++; remove_slash_from_scan_results(); while(1){ /* line end */ pend = strchr(ptr, '\n'); if (pend != NULL){ *pend = '\0'; } /* line start */ pst = ptr; /* abstract ssid */ pssid_start = strrchr(pst, '\t') + 1; strncpy(pssid, pssid_start, SSID_LEN); pssid[SSID_LEN] = '\0'; /* find ssid in scan results */ if(strcmp(pssid, ssid) == 0){ pflag = pst; for(i=0; i<3; i++){ pflag = strchr(pflag, '\t'); pflag++; } len = pssid_start - pflag; len = len - 1; strncpy(flag, pflag, len); flag[len] = '\0'; LOG_EX(LOG_Debug, "ssid %s, flag %s\n", ssid, flag); if((strstr(flag, "WPA-PSK-") != NULL) || (strstr(flag, "WPA2-PSK-") != NULL)){ key_mgmt_info[KEY_WPA_PSK_INDEX] = 1; }else if(strstr(flag, "WEP") != NULL){ key_mgmt_info[KEY_WEP_INDEX] = 1; }else if((strcmp(flag, "[ESS]") == 0) || (strcmp(flag, "[WPS][ESS]") == 0)){ key_mgmt_info[KEY_NONE_INDEX] = 1; }else{ ; } } if(pend != NULL){ *pend = '\n'; //point next line ptr = pend+1; }else{ break; } } pthread_mutex_unlock(&scan_mutex); return 0; } void *wifi_scan_thread(void *args) { int ret = -1, i = 0; char cmd[16] = {0}, reply[16] = {0}; struct timeval now; struct timespec outtime; while(scan_running){ pthread_mutex_lock(&scan_stop_restart_mutex); while(do_scan_flag == 0){ pthread_cond_wait(&scan_stop_restart_cond, &scan_stop_restart_mutex); } if(scan_terminating) { pthread_mutex_unlock(&scan_stop_restart_mutex); continue; } pthread_mutex_unlock(&scan_stop_restart_mutex); pthread_mutex_lock(&scan_mutex); while(scan_pause == 1){ pthread_cond_wait(&scan_cond, &scan_mutex); } /* set scan start flag */ set_scan_start_flag(); /* scan cmd */ strncpy(cmd, "SCAN", 15); ret = wifi_command(cmd, reply, sizeof(reply)); if(ret){ scan_error = 1; pthread_mutex_unlock(&scan_mutex); usleep(5000*1000); continue; } for(i=0;i