创建TASK,用于sniffer配网
//创建TASK,用于sniffer配网
void jd_innet_start_task(void)
{
xTaskCreate(jd_innet_start, "jd_innet_start", 1024*3, NULL, tskIDLE_PRIORITY + 2, NULL);
}
开启sniffer模式,进行一些配网模式的初始化等,执行到回调函数中接收802.11包
static void jd_innet_start (void *pvParameters)
{
unsigned char* pBuffer = NULL;
joylink_smnt_param_t param;
esp_wifi_set_promiscuous(0);
pBuffer = (unsigned char*)malloc(1024);
if (pBuffer == NULL) {
log_debug("%s,%d\r\n",__func__,__LINE__);
vTaskDelete(NULL);
}
memset(¶m,0x0,sizeof(param));
memcpy(param.secretkey,AES_KEY,sizeof(param.secretkey));
param.switch_channel_callback = esp_switch_channel_callback;
param.get_result_callback = esp_get_result_callback;
joylink_smnt_init(param);
#ifdef CONFIG_TARGET_PLATFORM_ESP8266
esp_wifi_set_promiscuous_data_len(32);
#endif
if (ESP_OK != esp_wifi_set_promiscuous_rx_cb(jd_innet_pack_callback)){
log_debug ("[%s] set_promiscuous fail\n\r",__func__);
}
if (ESP_OK != esp_wifi_set_promiscuous(1)){
log_debug ("[%s] open promiscuous fail\n\r",__func__);
}
if (jd_innet_timer_task_handle != NULL) {
jd_innet_timer_task_flag = true;
while(jd_innet_timer_task_flag) {
vTaskDelay(10);
}
}
xTaskCreate(jd_innet_timer_task, "jd_innet_timer_task", 2048, NULL, tskIDLE_PRIORITY + 5, &jd_innet_timer_task_handle);
vTaskDelete(NULL);
}
重要函数
esp_wifi_set_promiscuous(bool en);/开启/关闭混杂模式/
esp_err_tesp_wifi_set_promiscuous(bool en)
Enable the promiscuous mode.
Return
ESP_OK: succeed
ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
Parameters
en: false - disable, true - enable
esp_wifi_set_promiscuous_data_len(32);
没有找到这个函数,猜测是设置混杂模式获取数据的长度为32.
esp_wifi_set_promiscuous_rx_cb(jd_innet_pack_callback)
esp_err_tesp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_tcb)
Register the RX callback function in the promiscuous mode.
Each time a packet is received, the registered callback function will be called.
Return
ESP_OK: succeed
ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
Parameters
cb: callback
其中:
//特殊配网包格式
typedef struct{
smnt_status_t state;
uint16 syncFirst;
uint8 syncCount;
uint8 syncStepPoint;
uint8 syncFirst_downlink;
uint8 syncCount_downlink;
uint8 syncStepPoint_downlink;
uint8 directTimerSkip;
uint8 broadcastVersion;
uint8 muticastVersion;
uint8 broadIndex;
uint8 broadBuffer[5];
uint16 lastLength;
uint16 lastUploadSeq;
uint16 lastDownSeq;
uint8 syncAppMac[6];
uint8 syncBssid[6];
uint16 syncIsUplink;
uint8 chCurrentIndex;
uint8 chCurrentProbability;
uint8 isProbeReceived;
uint8 payload_multicast[128];
uint8 payload_broadcast[128];
smnt_encrypt_data_t result;
}joylinkSmnt_t;
//配网的状态
typedef enum{
SMART_CH_INIT = 0x1,
SMART_CH_LOCKING = 0x2,
SMART_CH_LOCKED = 0x4,
SMART_FINISH = 0x8
}smnt_status_t;
//加密数据
typedef struct{
unsigned char type; // 0:NotReady, 1:ControlPacketOK, 2:BroadcastOK, 3:MulticastOK
unsigned char encData[1+32+32+32]; // length + EncodeData
}smnt_encrypt_data_t;
接着执行到回调函数 包都到这里来
/*recv packet callback*/
static void jd_innet_pack_callback(void *buf, wifi_promiscuous_pkt_type_t type)
{
wifi_promiscuous_pkt_t *pack_all = NULL;
int len=0;
PHEADER_802_11 frame = NULL;
if (type != WIFI_PKT_MISC) {
pack_all = (wifi_promiscuous_pkt_t *)buf;
frame = (PHEADER_802_11)pack_all->payload;
#ifdef CONFIG_TARGET_PLATFORM_ESP8266
len = pack_all->rx_ctrl.sig_mode ? pack_all->rx_ctrl.HT_length : pack_all->rx_ctrl.legacy_length;
#else
len = pack_all->rx_ctrl.sig_len;
#endif
joylink_smnt_datahandler(frame, len);
}
}
以下是802.11的帧类型
//wifi帧格式
typedef enum {
WIFI_PKT_MGMT, /**< Management frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_CTRL, /**< Control frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_DATA, /**< Data frame, indiciates 'buf' argument is wifi_promiscuous_pkt_t */
WIFI_PKT_MISC, /**< Other type, such as MIMO etc. 'buf' argument is wifi_promiscuous_pkt_t but the payload is zero length. */
} wifi_promiscuous_pkt_type_t;
接下来进行解包,支持组播方式和广播方式
void joylink_smnt_datahandler(PHEADER_802_11 pHeader, int length)
{
uint8 isUplink = 1;
uint8 packetType = 0; // 1-multicast packets 2-broadcast packets 0-thers
uint8 isDifferentAddr = 0;
uint8 *pDest, *pSrc, *pBssid;
uint16 lastLength = 0;
uint16 lastSeq_uplink = 0,lastSeq_downlink = 0;
static uint8 past_channel = 0xFF;
if (pSmnt == NULL)
return;
if ((length > 100) && (pSmnt->state != SMART_CH_LOCKED))
return;
if (pHeader->FC.ToDs){
isUplink = 1;
pBssid = pHeader->Addr1;
pSrc = pHeader->Addr2;
pDest = pHeader->Addr3;
if (!((memcmp(pDest, "\xFF\xFF\xFF\xFF\xFF\xFF", 6) == 0) || (memcmp(pDest, "\x01\x00\x5E", 3) == 0))){
return;
}
lastSeq_uplink = pSmnt->lastUploadSeq;
pSmnt->lastUploadSeq = pHeader->Sequence;
}else{
pDest = pHeader->Addr1;
pBssid = pHeader->Addr2;
pSrc = pHeader->Addr3;
isUplink = 0;
//not broadcast nor multicast package ,return
if (!((memcmp(pDest, "\xFF\xFF\xFF\xFF\xFF\xFF", 6) == 0) || (memcmp(pDest, "\x01\x00\x5E", 3) == 0))){
return;
}
lastSeq_downlink = pSmnt->lastDownSeq;
pSmnt->lastDownSeq = pHeader->Sequence;
}
lastLength = pSmnt->lastLength;
pSmnt->lastLength = length;
if (memcmp(pDest, "\xFF\xFF\xFF\xFF\xFF\xFF", 6) == 0)
{
if (pSmnt->state == SMART_CH_LOCKING)
{
if(isUplink == 1)
printf("uplink:(%02x-%04d)->length:%2x, =length-synfirst:(0x%02x),synfirst:%2x\n", *((uint8*)pHeader) & 0xFF, pHeader->Sequence, length, (uint8)(length - pSmnt->syncFirst +1),pSmnt->syncFirst);
else
printf("downlink:(%02x-%04d)->length:%2x, =length-synfirst:(0x%02x),synfirst:%2x\n", *((uint8*)pHeader) & 0xFF, pHeader->Sequence, length, (uint8)(length - pSmnt->syncFirst_downlink +1),pSmnt->syncFirst_downlink);
}
packetType = 2;
}
else if (memcmp(pDest, "\x01\x00\x5E", 3) == 0)
{
if (pSmnt->state == SMART_CH_LOCKING)
printf("(%02x-%04d):%02x:%02x:%02x->%d\n", *((uint8*)pHeader) & 0xFF, pHeader->Sequence, pDest[3], pDest[4], pDest[5], (uint8)length);
packetType = 1;
}
if (memcmp(pSrc, pSmnt->syncAppMac, 6) != 0)
{
isDifferentAddr = 1;
}
if(pSmnt->state == SMART_CH_LOCKING)
{
if (packetType == 0) return;
if ((isUplink==1) && (pHeader->Sequence == lastSeq_uplink)) return;
if ((isUplink==0) && (pHeader->Sequence == lastSeq_downlink)) return;
if(!isDifferentAddr)
{
if (packetType != 0)
{
if (packetType == 1)
{
if (((pDest[3] >> 6) == ((pDest[4] ^ pDest[5]) & 0x1)) && (pDest[3] != 0) && ((pDest[3]&0x3F) <= PAYLOAD_MAX))
{
/*if receive multicast right message for two times,lock the channel*/
if(past_channel == pSmnt->chCurrentIndex + 1)
{
past_channel = 0xFF;
if (pSmnt->chCurrentProbability < 20)
pSmnt->chCurrentProbability = 10;
memcpy(pSmnt->syncBssid, pBssid, 6);
pSmnt->state = SMART_CH_LOCKED;
}
else
{
past_channel = pSmnt->chCurrentIndex + 1;
}
}
joylink_smnt_muticastadd(pDest); // Internal state machine could delay the ch switching
return;
}
if(isUplink == 1)
{
if (lastLength == length) return;
int expectLength = 1 + pSmnt->syncFirst + pSmnt->syncCount%4 - (pSmnt->syncStepPoint?4:0);
int isStep = (pSmnt->syncStepPoint == 0 && length == (expectLength - 4));
if ( ( length == expectLength ) || isStep)
{
pSmnt->syncCount++;
pSmnt->chCurrentProbability++;
if (isStep) pSmnt->syncStepPoint = pSmnt->syncCount;
if (pSmnt->syncCount >= 3) // Achive SYNC count!
//if (pSmnt->syncCount >= 4) // Achive SYNC count!
{
pSmnt->syncFirst = pSmnt->syncFirst + pSmnt->syncStepPoint - (pSmnt->syncStepPoint ? 4 : 0); // Save sync world
memcpy(pSmnt->syncBssid, pBssid, 6);
pSmnt->state = SMART_CH_LOCKED;
printf("SYNC:(%02X%02X%02X%02X%02X%02X-%02X%02X%02X%02X%02X%02X)------->:CH=%d, WD=%d\n",
pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5],
pBssid[0], pBssid[1], pBssid[2], pBssid[3], pBssid[4], pBssid[5],
pSmnt->chCurrentIndex+1, pSmnt->syncFirst);
pSmnt->syncIsUplink = isUplink;
if(pSmnt->chCurrentProbability < 20)
pSmnt->chCurrentProbability = 20;
printf("--->locked by uplink\n");
}
return;
}
if (pSmnt->syncCount)
{
pSmnt->syncStepPoint = 0;
pSmnt->syncCount = 0;
memcpy(pSmnt->syncAppMac, pSrc, 6);
pSmnt->syncFirst = length;
printf("SYNC LOST\n");
}
}
else
{
if (lastLength == length) return;
int expectLength = 1 + pSmnt->syncFirst_downlink+ pSmnt->syncCount_downlink%4 - (pSmnt->syncStepPoint_downlink?4:0);
int isStep = (pSmnt->syncStepPoint_downlink == 0 && length == (expectLength - 4));
if ( ( length == expectLength ) || isStep)
{
pSmnt->syncCount_downlink++;
pSmnt->chCurrentProbability++;
if (isStep) pSmnt->syncStepPoint_downlink = pSmnt->syncCount_downlink;
if (pSmnt->syncCount_downlink>= 3) // Achive SYNC count!
//if (pSmnt->syncCount_downlink>= 4) // Achive SYNC count!
{
pSmnt->syncFirst_downlink = pSmnt->syncFirst_downlink + pSmnt->syncStepPoint_downlink - (pSmnt->syncStepPoint_downlink? 4 : 0); // Save sync world
memcpy(pSmnt->syncBssid, pBssid, 6);
pSmnt->state = SMART_CH_LOCKED;
printf("SYNC:(%02X%02X%02X%02X%02X%02X-%02X%02X%02X%02X%02X%02X)------->:CH=%d, WD=%d\n",
pSrc[0], pSrc[1], pSrc[2], pSrc[3], pSrc[4], pSrc[5],
pBssid[0], pBssid[1], pBssid[2], pBssid[3], pBssid[4], pBssid[5],
pSmnt->chCurrentIndex+1, pSmnt->syncFirst_downlink);
pSmnt->syncIsUplink = isUplink;
if(pSmnt->chCurrentProbability < 20)
pSmnt->chCurrentProbability = 20;
printf("--->locked by downlink\n");
}
return;
}
pSmnt->syncStepPoint_downlink = 0;
pSmnt->syncCount_downlink = 0;
memcpy(pSmnt->syncAppMac, pSrc, 6);
pSmnt->syncFirst_downlink = length;
printf("SYNC LOST\n");
}
}
return;
}
memcpy(pSmnt->syncAppMac, pSrc, 6);
pSmnt->syncFirst = length;
pSmnt->syncFirst_downlink = length;
printf("Try to SYNC!\n");
return;
}
else if (pSmnt->state == SMART_CH_LOCKED)
{
if (isDifferentAddr) return;
if (packetType == 1){
joylink_smnt_muticastadd(pDest);
return;
}
if ( (packetType != 1)&&(memcmp(pDest, pSmnt->syncBssid, 6) != 0) ){
packetType = 2;
}
if(isUplink == 1)
{
if (length < (pSmnt->syncFirst - 1)) return;
if ( pHeader->Sequence == lastSeq_uplink) return;
}
else
{
if (length < (pSmnt->syncFirst_downlink - 1)) return;
if ( pHeader->Sequence == lastSeq_downlink) return;
}
if (packetType == 2)
{
int ascii;
if(isUplink == 1)
ascii = length - pSmnt->syncFirst + 1;
else
ascii = length - pSmnt->syncFirst_downlink + 1;
if((((ascii >> 8) & 0x01) == 1) && (((ascii >> 3)&0x1F) == 0))
{
;
}
else
{
joylink_smnt_broadcastadd(ascii);
}
if (((length + 4 - lastLength) % 4 == 1)&& (length - pSmnt->syncFirst)<4) // There are SYNC packets even ch locked.
{
if (pSmnt->chCurrentProbability < 20) pSmnt->chCurrentProbability++;
}
}
}
else if (pSmnt->state == SMART_FINISH)
{
printf("SMART_FINISH-1\n");
}
else
{
pSmnt->state = SMART_CH_LOCKING;
memcpy(pSmnt->syncAppMac, pSrc, 6);
pSmnt->syncFirst = length;
pSmnt->syncStepPoint = 0;
pSmnt->syncCount = 0;
printf("Reset All State\n");
}
return;
}
广播包标志:\xFF\xFF\xFF\xFF\xFF\xFF
组播包标志:\x01\x00\x5E
由调试结果可知,通过切换信道来锁定配网包的信道,循环接收包进行补全数据。
得到配网所需的SSID和PASSWORD
本示例说明:下面是调试LOG
downlink:(40-2111)->length:38, =length-synfirst:(0x01),synfirst:38
downlink:(40-0033)->length:38, =length-synfirst:(0x01),synfirst:38
downlink:(40-1855)->length:39, =length-synfirst:(0x02),synfirst:38
------------------->SYNC (CH:13) 0
uplink:(88-3624)->length:53, =length-synfirst:(0x1c),synfirst:38
Try to SYNC!
uplink:(88-3626)->length:54, =length-synfirst:(0x02),synfirst:53
------------------->SYNC (CH:1) 0
downlink:(80-0747)->length:60, =length-synfirst:(0x0e),synfirst:53
Try to SYNC