support aliyun sdk on TencentOS tiny

sample: examples\aliyun_iotkit_csdk_mqtt
project: board\TencentOS_tiny_EVB_MX_Plus\KEIL\aliyun_iotkit_csdk_mqtt
This commit is contained in:
dcxajichu
2019-10-31 16:36:28 +08:00
parent 30ea36a7ab
commit 8c24d921b0
692 changed files with 199829 additions and 0 deletions

View File

@@ -0,0 +1,290 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#ifdef AWSS_SUPPORT_DEV_AP
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#define AWSS_DEV_AP_WAIT_TIME_MAX_MS (2000)
static void *g_awss_dev_ap_mutex = NULL;
static char awss_dev_ap_switchap_done = 0;
static char awss_dev_ap_switchap_resp_suc = 0;
static char awss_dev_ap_ongoing = 0;
static int awss_dev_ap_setup()
{
char ssid[PLATFORM_MAX_SSID_LEN + 1] = {0};
char passwd[PLATFORM_MAX_PASSWD_LEN + 1] = {0};
do { /* reduce stack used */
char pk[OS_PRODUCT_KEY_LEN + 1] = {0};
char mac_str[OS_MAC_LEN + 1] = {0};
HAL_GetProductKey(pk);
os_wifi_get_mac_str(mac_str);
memmove(mac_str + 11, mac_str + 12, 2);
memmove(mac_str + 13, mac_str + 15, 2);
mac_str[15] = '\0';
HAL_Snprintf(ssid, PLATFORM_MAX_SSID_LEN, "adh_%s_%s", pk, &mac_str[9]);
} while (0);
awss_trace("ssid:%s\n", ssid);
return HAL_Awss_Open_Ap(ssid, passwd, 100, 0);
}
extern int awss_success_notify(void);
int awss_dev_ap_start(void)
{
int ret = -1;
if (g_awss_dev_ap_mutex || awss_dev_ap_ongoing) {
awss_trace("dev ap already running");
return -1;
}
if (g_awss_dev_ap_mutex == NULL)
g_awss_dev_ap_mutex = HAL_MutexCreate();
if (g_awss_dev_ap_mutex == NULL) {
awss_trace("awss dev ap start fail");
goto AWSS_DEV_AP_FAIL;
}
HAL_MutexLock(g_awss_dev_ap_mutex);
awss_dev_ap_ongoing = 1;
awss_dev_ap_switchap_done = 0;
awss_dev_ap_switchap_resp_suc = 0;
ret = awss_dev_ap_setup();
HAL_MutexUnlock(g_awss_dev_ap_mutex);
HAL_SleepMs(1000); /* wait for dev ap to work well */
HAL_MutexLock(g_awss_dev_ap_mutex);
if (awss_dev_ap_ongoing) {
awss_cmp_local_init(AWSS_LC_INIT_DEV_AP);
}
while (awss_dev_ap_ongoing) {
HAL_MutexUnlock(g_awss_dev_ap_mutex);
HAL_SleepMs(200);
HAL_MutexLock(g_awss_dev_ap_mutex);
if (awss_dev_ap_switchap_done)
break;
}
HAL_MutexUnlock(g_awss_dev_ap_mutex);
ret = awss_dev_ap_switchap_done == 0 ? -1 : 0;
if (awss_dev_ap_ongoing == 0) { /* interrupt by user */
HAL_SleepMs(1000);
return -1;
}
awss_dev_ap_ongoing = 0;
awss_success_notify();
AWSS_DEV_AP_FAIL:
if (g_awss_dev_ap_mutex) {
HAL_MutexUnlock(g_awss_dev_ap_mutex);
HAL_MutexDestroy(g_awss_dev_ap_mutex);
}
g_awss_dev_ap_mutex = NULL;
return ret;
}
extern int HAL_Awss_Close_Ap(void);
int awss_dev_ap_stop(void)
{
if (awss_dev_ap_ongoing == 0)
return 0;
awss_dev_ap_ongoing = 0;
awss_trace("%s", __func__);
if (g_awss_dev_ap_mutex)
HAL_MutexLock(g_awss_dev_ap_mutex);
HAL_Awss_Close_Ap();
awss_cmp_local_deinit(1);
if (g_awss_dev_ap_mutex) {
HAL_MutexUnlock(g_awss_dev_ap_mutex);
HAL_MutexDestroy(g_awss_dev_ap_mutex);
g_awss_dev_ap_mutex = NULL;
}
awss_dev_ap_switchap_done = 0;
awss_dev_ap_switchap_resp_suc = 0;
awss_trace("%s exit", __func__);
return 0;
}
static int awss_dev_ap_switchap_resp(void *context, int result,
void *userdata, void *remote,
void *message) {
if (result == 2) { /* success */
awss_dev_ap_switchap_resp_suc = 1;
}
return 0;
}
int wifimgr_process_dev_ap_switchap_request(void *ctx, void *resource, void *remote, void *request)
{
#define AWSS_DEV_AP_SWITCHA_RSP_LEN (512)
char ssid[PLATFORM_MAX_SSID_LEN * 2 + 1] = {0}, passwd[PLATFORM_MAX_PASSWD_LEN + 1] = {0};
int str_len = 0, success = 1, len = 0;
char req_msg_id[MSG_REQ_ID_LEN] = {0};
char random[RANDOM_MAX_LEN + 1] = {0};
char *msg = NULL, *dev_info = NULL;
char *str = NULL, *buf = NULL;
char bssid[ETH_ALEN] = {0};
char ssid_found = 0;
int ret = -1;
static char dev_ap_switchap_parsed = 0;
char topic[TOPIC_LEN_MAX] = {0};
uint16_t msgid = -1;
int result = 0;
if (dev_ap_switchap_parsed != 0)
goto DEV_AP_SWITCHAP_END;
dev_ap_switchap_parsed = 1;
AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_TIME_START);
msg = os_zalloc(AWSS_DEV_AP_SWITCHA_RSP_LEN);
if (msg == NULL)
goto DEV_AP_SWITCHAP_END;
dev_info = os_zalloc(AWSS_DEV_AP_SWITCHA_RSP_LEN);
if (dev_info == NULL)
goto DEV_AP_SWITCHAP_END;
buf = awss_cmp_get_coap_payload(request, &len);
str = json_get_value_by_name(buf, len, "id", &str_len, 0);
memcpy(req_msg_id, str, str_len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : str_len);
awss_trace("dev ap, len:%u, %s\r\n", len, buf);
buf = json_get_value_by_name(buf, len, "params", &len, 0);
if (buf == NULL)
goto DEV_AP_SWITCHAP_END;
do {
produce_random(aes_random, sizeof(aes_random));
dev_info[0] = '{';
awss_build_dev_info(AWSS_NOTIFY_DEV_BIND_TOKEN, dev_info + 1, AWSS_DEV_AP_SWITCHA_RSP_LEN - 1);
dev_info[strlen(dev_info)] = '}';
dev_info[AWSS_DEV_AP_SWITCHA_RSP_LEN - 1] = '\0';
HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, 200, dev_info);
str_len = 0;
str = json_get_value_by_name(buf, len, "ssid", &str_len, 0);
awss_trace("ssid, len:%u, %s\r\n", str_len, str != NULL ? str : "NULL");
if (str && (str_len < PLATFORM_MAX_SSID_LEN)) {
memcpy(ssid, str, str_len);
ssid_found = 1;
}
if (!ssid_found) {
str_len = 0;
str = json_get_value_by_name(buf, len, "xssid", &str_len, 0);
if (str && (str_len < PLATFORM_MAX_SSID_LEN * 2 - 1)) {
uint8_t decoded[OS_MAX_SSID_LEN] = {0};
int len = str_len / 2;
memcpy(ssid, str, str_len);
utils_str_to_hex(ssid, str_len, decoded, OS_MAX_SSID_LEN);
memcpy(ssid, (const char *)decoded, len);
ssid[len] = '\0';
} else {
HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -1, "\"ssid error\"");
success = 0;
break;
}
}
str_len = 0;
str = json_get_value_by_name(buf, len, "random", &str_len, 0);
if (str && str_len == RANDOM_MAX_LEN * 2) {
utils_str_to_hex(str, str_len, (unsigned char *)random, RANDOM_MAX_LEN);
} else {
HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -4, "\"random len error\"");
success = 0;
break;
}
str_len = 0;
str = json_get_value_by_name(buf, len, "bssid", &str_len, 0);
if (str) os_wifi_str2mac(str, bssid);
str_len = 0;
str = json_get_value_by_name(buf, len, "passwd", &str_len, 0);
if (str_len < (PLATFORM_MAX_PASSWD_LEN * 2) - 1) {
char encoded[PLATFORM_MAX_PASSWD_LEN * 2 + 1] = {0};
memcpy(encoded, str, str_len);
aes_decrypt_string(encoded, passwd, str_len,
0, awss_get_encrypt_type(), 1, random); /* 64bytes=2x32bytes */
} else {
HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -3, "\"passwd len error\"");
success = 0;
AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
}
if (success && is_utf8(passwd, strlen(passwd)) == 0) {
HAL_Snprintf(msg, AWSS_DEV_AP_SWITCHA_RSP_LEN, AWSS_ACK_FMT, req_msg_id, -3 , "\"passwd content error\"");
success = 0;
AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
}
} while (0);
awss_trace("Sending message to app: %s", msg);
awss_trace("switch to ap: '%s'", ssid);
awss_build_topic((const char *)TOPIC_AWSS_DEV_AP_SWITCHAP, topic, TOPIC_LEN_MAX);
result = awss_cmp_coap_send_resp(msg, strlen(msg), remote, topic, request, awss_dev_ap_switchap_resp, &msgid, 1);
(void)result; /* remove complier warnings */
awss_trace("sending %s.", result == 0 ? "success" : "fail");
do {
int wait_ms = AWSS_DEV_AP_WAIT_TIME_MAX_MS;
if (!success)
break;
while (wait_ms > 0 && awss_dev_ap_switchap_resp_suc == 0 && awss_dev_ap_ongoing) {
HAL_SleepMs(100);
wait_ms -= 100;
}
awss_cmp_coap_cancel_packet(msgid);
AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_START);
if (awss_dev_ap_ongoing == 0) { /* interrupt by user */
ret = -1;
goto DEV_AP_SWITCHAP_END;
}
HAL_Awss_Close_Ap();
ret = HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT_MS, ssid, passwd, 0, 0, (uint8_t *)bssid, 0);
if (ret == 0) {
AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_SUC);
awss_dev_ap_switchap_done = 1;
AWSS_UPDATE_STATIS(AWSS_STATIS_DAP_IDX, AWSS_STATIS_TYPE_TIME_SUC);
} else {
awss_dev_ap_setup();
}
awss_trace("connect '%s' %s\r\n", ssid, ret == 0 ? "success" : "fail");
} while (0);
DEV_AP_SWITCHAP_END:
dev_ap_switchap_parsed = 0;
if (dev_info) HAL_Free(dev_info);
if (msg) HAL_Free(msg);
return ret;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_DEV_AP_H__
#define __AWSS_DEV_AP_H__
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
int awss_dev_ap_stop(void);
int awss_dev_ap_start(void);
int wifimgr_process_dev_ap_switchap_request(void *ctx, void *resource, void *remote, void *request);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,56 @@
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
/*************************************** common hals ***************************************/
int HAL_Timer_Stop(void *timer);
int HAL_Timer_Delete(void *timer);
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
int HAL_Timer_Start(void *timer, int ms);
void HAL_SleepMs(uint32_t ms);
void *HAL_Malloc(uint32_t size);
void HAL_MutexLock(void *mutex);
void HAL_MutexUnlock(void *mutex);
uint64_t HAL_UptimeMs(void);
void HAL_Free(void *ptr);
void *HAL_MutexCreate(void);
void HAL_MutexDestroy(void *mutex);
/*************************************** wifi provision frameworks hals ***************************************/
/* frameworks/awss.c*/
int HAL_Awss_Get_Timeout_Interval_Ms(void);
int HAL_Sys_Net_Is_Ready();
int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
/* awss_crypt.c */
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
int HAL_GetProductSecret(char *product_secret);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
void HAL_Awss_Close_Monitor(void);
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
int HAL_Awss_Get_Channelscan_Interval_Ms(void);
/* zconfig_vendor_common.c */
p_HAL_Aes128_t HAL_Aes128_Init(
_IN_ const uint8_t *key,
_IN_ const uint8_t *iv,
_IN_ AES_DIR_t dir);
int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
int HAL_Aes128_Cbc_Decrypt(
_IN_ p_HAL_Aes128_t aes,
_IN_ const void *src,
_IN_ size_t blockNum,
_OU_ void *dst);
/* os_misc.c */
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
/* awss_main.c */
int HAL_Awss_Connect_Ap(
_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel);
int HAL_Awss_Close_Ap();
/*************************************** dev-ap special hals ***************************************/
int HAL_Awss_Open_Ap(const char *ssid, const char *passwd, int beacon_interval, int hide);

View File

@@ -0,0 +1,405 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#ifdef AWSS_SUPPORT_APLIST
#define CLR_APLIST_MONITOR_TIMEOUT_MS (24 * 60 *60 * 1000)
/* storage to store apinfo */
struct ap_info *zconfig_aplist = NULL;
/* aplist num, less than MAX_APLIST_NUM */
uint8_t zconfig_aplist_num = 0;
static uint8_t clr_aplist = 0;
static void *clr_aplist_timer = NULL;
static void awss_clr_aplist_monitor()
{
clr_aplist = 1;
HAL_Timer_Start(clr_aplist_timer, CLR_APLIST_MONITOR_TIMEOUT_MS);
}
int awss_is_ready_clr_aplist(void)
{
return clr_aplist;
}
int awss_clear_aplist(void)
{
memset(zconfig_aplist, 0, sizeof(struct ap_info) * MAX_APLIST_NUM);
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
memset(adha_aplist, 0, sizeof(*adha_aplist));
#endif
zconfig_aplist_num = 0;
clr_aplist = 0;
return 0;
}
int awss_open_aplist_monitor(void)
{
if (clr_aplist_timer == NULL)
clr_aplist_timer = HAL_Timer_Create("clr_aplist", (void (*)(void *))awss_clr_aplist_monitor, (void *)NULL);
if (clr_aplist_timer == NULL)
return -1;
HAL_Timer_Stop(clr_aplist_timer);
HAL_Timer_Start(clr_aplist_timer, CLR_APLIST_MONITOR_TIMEOUT_MS);
return 0;
}
int awss_close_aplist_monitor(void)
{
if (clr_aplist_timer == NULL)
return 0;
awss_stop_timer(clr_aplist_timer);
clr_aplist_timer = NULL;
return 0;
}
int awss_init_ieee80211_aplist(void)
{
if (zconfig_aplist)
return 0;
zconfig_aplist = (struct ap_info *)os_zalloc(sizeof(struct ap_info) * MAX_APLIST_NUM);
if (zconfig_aplist == NULL)
return -1;
zconfig_aplist_num = 0;
return 0;
}
int awss_deinit_ieee80211_aplist(void)
{
if (zconfig_aplist == NULL)
return 0;
HAL_Free(zconfig_aplist);
zconfig_aplist = NULL;
zconfig_aplist_num = 0;
return 0;
}
struct ap_info *zconfig_get_apinfo(uint8_t *mac)
{
int i;
for (i = 1; i < zconfig_aplist_num; i++) {
if (!memcmp(zconfig_aplist[i].mac, mac, ETH_ALEN))
return &zconfig_aplist[i];
}
return NULL;
}
struct ap_info *zconfig_get_apinfo_by_ssid(uint8_t *ssid)
{
int i;
for (i = 1; i < zconfig_aplist_num; i ++) {
if (!strcmp((char *)zconfig_aplist[i].ssid, (char *)ssid))
return &zconfig_aplist[i];
}
return NULL;
}
/* 通过ssid前缀 */
struct ap_info *zconfig_get_apinfo_by_ssid_prefix(uint8_t *ssid_prefix)
{
int i;
int len = strlen((const char *)ssid_prefix);
if (!len)
return NULL;
for (i = 1; i < zconfig_aplist_num; i++) {
if (!strncmp((char *)zconfig_aplist[i].ssid, (char *)ssid_prefix, len)) {
/* TODO: first match or best match??? */
return &zconfig_aplist[i];/* first match */
}
}
return NULL;
}
int str_end_with(const char *str, const char *suffix)
{
int lenstr, lensuffix;
if (!str || !suffix)
return 0;
lenstr = strlen(str);
lensuffix = strlen(suffix);
if (lensuffix > lenstr)
return 0;
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}
/* 通过ssid后缀 */
struct ap_info *zconfig_get_apinfo_by_ssid_suffix(uint8_t *ssid_suffix)
{
int i;
int len = strlen((const char *)ssid_suffix);
if (!len)
return NULL;
for (i = 1; i < zconfig_aplist_num; i++) {
if (str_end_with((char *)zconfig_aplist[i].ssid, (char *)ssid_suffix)) {
/* TODO: first match or best match??? */
return &zconfig_aplist[i];/* first match */
}
}
return NULL;
}
/**
* save apinfo
*
* @ssid: [IN] ap ssid
* @bssid: [IN] ap bssid
* @channel: [IN] ap channel
* @auth: [IN] optional, ap auth mode, like OPEN/WEP/WPA/WPA2/WPAWPA2
* @encry: [IN], ap encryption mode, i.e. NONE/WEP/TKIP/AES/TKIP-AES
*
* Note:
* 1) if ap num exceed zconfig_aplist[], always save at [0]
* but why...I forgot...
* 2) always update channel if channel != 0
* 3) if chn is locked, save ssid to zc_ssid, because zc_ssid
* can be used for ssid-auto-completion
* Return:
* 0/success, -1/invalid params(empty ssid/bssid)
*/
int awss_save_apinfo(uint8_t *ssid, uint8_t* bssid, uint8_t channel, uint8_t auth,
uint8_t pairwise_cipher, uint8_t group_cipher, signed char rssi)
{
int i;
/* ssid, bssid cannot empty, channel can be 0, auth/encry can be invalid */
if (!(ssid && bssid))
return -1;
/* sanity check */
if (channel > ZC_MAX_CHANNEL || channel < ZC_MIN_CHANNEL)
channel = 0;
else
zconfig_add_active_channel(channel);
if (auth > ZC_AUTH_TYPE_MAX)
auth = ZC_AUTH_TYPE_INVALID;
if (pairwise_cipher > ZC_ENC_TYPE_MAX)
pairwise_cipher = ZC_ENC_TYPE_INVALID;
if (group_cipher > ZC_ENC_TYPE_MAX)
group_cipher = ZC_ENC_TYPE_INVALID;
/* FIXME: */
if (pairwise_cipher == ZC_ENC_TYPE_TKIPAES)
pairwise_cipher = ZC_ENC_TYPE_AES; /* tods */
/*
* start from zconfig_aplist[1], leave [0] for temp use
* if zconfig_aplist[] is full, always replace [0]
*/
if (!zconfig_aplist_num) {
zconfig_aplist_num = 1;
}
for (i = 1; i < zconfig_aplist_num; i++) {
if(!strncmp(zconfig_aplist[i].ssid, (char *)ssid, ZC_MAX_SSID_LEN)
&& !memcmp(zconfig_aplist[i].mac, bssid, ETH_ALEN)) {
/* FIXME: useless? */
/* found the same bss */
if (!zconfig_aplist[i].channel)
zconfig_aplist[i].channel = channel;
if (zconfig_aplist[i].auth == ZC_AUTH_TYPE_INVALID)
zconfig_aplist[i].auth = auth;
if (zconfig_aplist[i].encry[0] == ZC_ENC_TYPE_INVALID)
zconfig_aplist[i].encry[0] = group_cipher;
if (zconfig_aplist[i].encry[1] == ZC_ENC_TYPE_INVALID)
zconfig_aplist[i].encry[1] = pairwise_cipher;
return 0;/* duplicated ssid */
}
}
if (i < MAX_APLIST_NUM) {
zconfig_aplist_num ++;
} else {
i = 0; /* [0] for temp use, always replace [0] */
}
strncpy((char *)&zconfig_aplist[i].ssid, (const char *)&ssid[0], ZC_MAX_SSID_LEN - 1);
memcpy(&zconfig_aplist[i].mac, bssid, ETH_ALEN);
zconfig_aplist[i].auth = auth;
zconfig_aplist[i].rssi = rssi;
zconfig_aplist[i].channel = channel;
zconfig_aplist[i].encry[0] = group_cipher;
zconfig_aplist[i].encry[1] = pairwise_cipher;
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
do {
char save_adha = 0;
#ifdef AWSS_SUPPORT_ADHA
if (!strcmp((void *)ssid, zc_adha_ssid))
save_adha = 1;
#endif
#ifdef AWSS_SUPPORT_AHA
if (!strcmp((void *)ssid, zc_default_ssid))
save_adha = 1;
#endif
if (save_adha) {
if (adha_aplist->cnt < MAX_APLIST_NUM)
adha_aplist->aplist[adha_aplist->cnt ++] = i;
}
} while(0);
#endif
do {
char adha = 0;
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
adha = adha_aplist->cnt;
#endif
awss_trace("[%d] ssid:%s, mac:%02x%02x%02x%02x%02x%02x, chn:%d, rssi:%d, adha:%d\r\n",
i, ssid, bssid[0], bssid[1], bssid[2],
bssid[3], bssid[4], bssid[5], channel,
rssi > 0 ? rssi - 256 : rssi, adha);
} while (0);
/*
* if chn already locked(zc_bssid set),
* copy ssid to zc_ssid for ssid-auto-completiont
*/
if (!memcmp(zc_bssid, bssid, ETH_ALEN) && ssid[0] != '\0') {
strncpy((char *)zc_ssid, (char const *)ssid, ZC_MAX_SSID_LEN - 1);
}
return 0;
}
/*
* [IN] ssid or bssid
* [OUT] auth, encry, channel
*/
int awss_get_auth_info(uint8_t *ssid, uint8_t *bssid, uint8_t *auth,
uint8_t *encry, uint8_t *channel)
{
uint8_t *valid_bssid = NULL;
struct ap_info *ap_info = NULL;
/* sanity check */
if (!bssid || !memcmp(bssid, zero_mac, ETH_ALEN)) {
valid_bssid = NULL;
} else {
valid_bssid = bssid;
}
/* use mac or ssid to search apinfo */
if (valid_bssid) {
ap_info = zconfig_get_apinfo(valid_bssid);
} else {
ap_info = zconfig_get_apinfo_by_ssid(ssid);
}
if (!ap_info)
return 0;
if (auth)
*auth = ap_info->auth;
if (encry)
*encry = ap_info->encry[1]; /* tods side */
if (!valid_bssid && bssid)
memcpy(bssid, ap_info->mac, ETH_ALEN);
if (channel)
*channel = ap_info->channel;
return 1;
}
void aws_try_adjust_chan(void)
{
struct ap_info *ap = NULL;
char ssid[ZC_MAX_SSID_LEN] = {0};
ap = zconfig_get_apinfo(zc_bssid);
if (ap == NULL)
return;
if (zconfig_get_lock_chn() == ap->channel)
return;
if (!zconfig_is_valid_channel(ap->channel))
return;
strncpy(ssid, (const char *)ap->ssid, ZC_MAX_SSID_LEN - 1);
#ifdef AWSS_SUPPORT_AHA
if (strlen(ssid) == strlen(zc_default_ssid) &&
strncmp(ap->ssid, zc_default_ssid, strlen(zc_default_ssid)) == 0)
return;
#endif
#ifdef AWSS_SUPPORT_ADHA
if (strlen(ssid) == strlen(zc_adha_ssid) &&
strncmp(ap->ssid, zc_adha_ssid, strlen(zc_adha_ssid)) == 0)
return;
#endif
aws_set_dst_chan(ap->channel);
aws_switch_channel();
}
int awss_ieee80211_aplist_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
{
uint8_t ssid[ZC_MAX_SSID_LEN] = {0}, bssid[ETH_ALEN] = {0};
uint8_t auth, pairwise_cipher, group_cipher;
struct ieee80211_hdr *hdr;
int fc, ret, channel;
if (mgmt_header == NULL)
return ALINK_INVALID;
hdr = (struct ieee80211_hdr *)mgmt_header;
fc = hdr->frame_control;
/*
* just for save ap in aplist for ssid amend.
*/
if (!ieee80211_is_beacon(fc) && !ieee80211_is_probe_resp(fc))
return ALINK_INVALID;
ret = ieee80211_get_bssid(mgmt_header, bssid);
if (ret < 0)
return ALINK_INVALID;
ret = ieee80211_get_ssid(mgmt_header, len, ssid);
if (ret < 0)
return ALINK_INVALID;
/*
* skip all the adha and aha
*/
#ifdef AWSS_SUPPORT_AHA
if (strcmp((const char *)ssid, zc_default_ssid) == 0)
return ALINK_INVALID;
#endif
#ifdef AWSS_SUPPORT_ADHA
if (strcmp((const char *)ssid, zc_adha_ssid) == 0)
return ALINK_INVALID;
#endif
channel = cfg80211_get_bss_channel(mgmt_header, len);
rssi = rssi > 0 ? rssi - 256 : rssi;
cfg80211_get_cipher_info(mgmt_header, len, &auth,
&pairwise_cipher, &group_cipher);
awss_save_apinfo(ssid, bssid, channel, auth,
pairwise_cipher, group_cipher, rssi);
return ALINK_INVALID;
}
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_APLIST_H__
#define __AWSS_APLIST_H__
#include <stdint.h>
#include "os.h"
#include "zconfig_protocol.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#ifdef AWSS_SUPPORT_APLIST
struct ap_info {
uint8_t auth;
uint8_t channel;
uint8_t encry[2];
uint8_t mac[ETH_ALEN];
char ssid[ZC_MAX_SSID_LEN];
signed char rssi;
};
void aws_try_adjust_chan(void);
int awss_clear_aplist(void);
int awss_is_ready_clr_aplist(void);
int awss_open_aplist_monitor(void);
int awss_close_aplist_monitor(void);
int awss_init_ieee80211_aplist(void);
int awss_deinit_ieee80211_aplist(void);
int awss_get_auth_info(uint8_t *ssid, uint8_t *bssid, uint8_t *auth,
uint8_t *encry, uint8_t *channel);
int awss_ieee80211_aplist_process(uint8_t *mgmt_header, int len, int link_type,
struct parser_res *res, signed char rssi);
int awss_save_apinfo(uint8_t *ssid, uint8_t* bssid, uint8_t channel, uint8_t auth,
uint8_t pairwise_cipher, uint8_t group_cipher, signed char rssi);
/* storage to store apinfo */
extern struct ap_info *zconfig_aplist;
/* aplist num, less than MAX_APLIST_NUM */
extern uint8_t zconfig_aplist_num;
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,109 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWS_LIB_H__
#define __AWS_LIB_H__
#include <stdint.h>
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
/* auth type */
enum AWS_AUTH_TYPE {
AWS_AUTH_TYPE_OPEN,
AWS_AUTH_TYPE_SHARED,
AWS_AUTH_TYPE_WPAPSK,
AWS_AUTH_TYPE_WPA8021X,
AWS_AUTH_TYPE_WPA2PSK,
AWS_AUTH_TYPE_WPA28021X,
AWS_AUTH_TYPE_WPAPSKWPA2PSK,
AWS_AUTH_TYPE_MAX = AWS_AUTH_TYPE_WPAPSKWPA2PSK,
AWS_AUTH_TYPE_INVALID = 0xff,
};
/* encry type */
enum AWS_ENC_TYPE {
AWS_ENC_TYPE_NONE,
AWS_ENC_TYPE_WEP,
AWS_ENC_TYPE_TKIP,
AWS_ENC_TYPE_AES,
AWS_ENC_TYPE_TKIPAES,
AWS_ENC_TYPE_MAX = AWS_ENC_TYPE_TKIPAES,
AWS_ENC_TYPE_INVALID = 0xff,
};
/* link type */
enum AWS_LINK_TYPE {
AWS_LINK_TYPE_NONE,
AWS_LINK_TYPE_PRISM,
AWS_LINK_TYPE_80211_RADIO,
AWS_LINK_TYPE_80211_RADIO_AVS
};
#if 0
/* 将monitor模式下抓到的包传入该函数进行处理
* 参数:
* buf: frame buffer
* length: frame len
* link_type: see enum AWS_LINK_TYPE
* with_fcs: frame include 80211 fcs field, the tailing 4bytes
*
* 说明:
* 适配前执行以下命令, 检查link_type和with_fcs参数
* a) iwconfig wlan0 mode monitor #进入monitor模式
* b) iwconfig wlan0 channel 6 #切换到信道6(以路由器信道为准)
* c) tcpdump -i wlan0 -s0 -w file.pacp #抓包保存文件
* d) 用wireshark或者omnipeek打开检查包头格式及包尾是否包含FCS 4字节
*
* 常见的包头类型为:
* 无额外的包头AWS_LINK_TYPE_NONE
* radio header: hdr_len = *(uint16_t *)(buf + 2)
* avs header: hdr_len = *(unsigned long *)(buf + 4)
* prism header: hdr_len = 144
*/
int aws_80211_frame_handler(char *buf, int length,
int link_type, int with_fcs);
#endif
/* 启动一键配网服务, 该函数会block直到配网成功或者超时退出,
* 超时时间由aws_timeout_period_ms设置
* 参数:
* pk: product key
* dn: device name
* ds: device security
* ps: product security
*/
void aws_start(char *pk, char *dn, char *ds, char *ps);
/* {该函数大致流程如下:
* init();
* platform_monitor_open();
* aws_main_thread_func();
* platform_monitor_close();
* destroy();
* }
* aws_start返回后调用该函数获取ssid和passwd等信息
* aws成功时ssid & passwd一定会返回非NULL字符串, 但bssid和auth, encry, channel
* 有可能会返回NULL或者INVALID值(取决于是否能在wifi列表里搜索命中)
* aws失败超时后该函数会返回0, 且所有参数为NULL或INVALID VALUE
*
* auth defined by enum AWS_AUTH_TYPE
* encry defined by enum AWS_ENC_TYPE
*
* 返回值1--成功0--失败
*/
int aws_get_ssid_passwd(char ssid[32 + 1], char passwd[64 + 1], uint8_t bssid[6],
char *auth, char *encry, uint8_t *channel);
/* 配网结束(成功或失败)后,调用该函数,释放配网库占用的资源 */
void aws_destroy(void);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,219 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
#define AWSS_PRESS_TIMEOUT_MS (60000)
extern int switch_ap_done;
static uint8_t awss_stopped = 1;
static uint8_t g_user_press = 0;
static void *press_timer = NULL;
static void awss_press_timeout(void);
int awss_success_notify(void)
{
g_user_press = 0;
awss_press_timeout();
awss_cmp_local_init(AWSS_LC_INIT_SUC);
awss_suc_notify_stop();
awss_suc_notify();
awss_start_connectap_monitor();
AWSS_DISP_STATIS();
return 0;
}
static void awss_press_timeout(void)
{
awss_stop_timer(press_timer);
press_timer = NULL;
if (g_user_press) {
awss_event_post(IOTX_AWSS_ENABLE_TIMEOUT);
}
g_user_press = 0;
}
#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG)
int awss_start(void)
{
if (awss_stopped == 0) {
awss_debug("awss already running\n");
return -1;
}
awss_stopped = 0;
awss_event_post(IOTX_AWSS_START);
produce_random(aes_random, sizeof(aes_random));
do {
__awss_start();
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
do {
char ssid[PLATFORM_MAX_SSID_LEN + 1] = {0};
#ifdef AWSS_SUPPORT_ADHA
while (1) {
memset(ssid, 0, sizeof(ssid));
HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
awss_debug("start, ssid:%s, strlen:%lu\n", ssid, strlen(ssid));
if (strlen(ssid) > 0 && strcmp(ssid, ADHA_SSID)) { /* not adha AP */
break;
}
if (HAL_Sys_Net_Is_Ready()) { /* skip the adha failed */
awss_cmp_local_init(AWSS_LC_INIT_ROUTER);
awss_open_adha_monitor();
while (!awss_is_ready_switch_next_adha()) {
if (awss_stopped) {
break;
}
HAL_SleepMs(50);
}
awss_cmp_local_deinit(0);
}
if (switch_ap_done || awss_stopped) {
break;
}
__awss_start();
}
#endif
if (awss_stopped) {
break;
}
if (switch_ap_done) {
break;
}
HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
if (strlen(ssid) > 0 && strcmp(ssid, DEFAULT_SSID)) { /* not AHA */
break;
}
if (HAL_Sys_Net_Is_Ready()) {
char dest_ap = 0;
awss_open_aha_monitor();
awss_cmp_local_init(AWSS_LC_INIT_PAP);
while (!awss_aha_monitor_is_timeout()) {
memset(ssid, 0, sizeof(ssid));
HAL_Wifi_Get_Ap_Info(ssid, NULL, NULL);
if (HAL_Sys_Net_Is_Ready() &&
strlen(ssid) > 0 && strcmp(ssid, DEFAULT_SSID)) { /* not AHA */
dest_ap = 1;
break;
}
if (awss_stopped) {
break;
}
HAL_SleepMs(50);
}
awss_cmp_local_deinit(0);
if (switch_ap_done || awss_stopped) {
break;
}
if (dest_ap == 1) {
break;
}
}
awss_event_post(IOTX_AWSS_ENABLE_TIMEOUT);
__awss_start();
} while (1);
#endif
if (awss_stopped) {
break;
}
if (HAL_Sys_Net_Is_Ready()) {
break;
}
} while (1);
if (awss_stopped) {
return -1;
}
#ifdef AWSS_SUPPORT_AHA
awss_close_aha_monitor();
#endif
#ifdef AWSS_SUPPORT_ADHA
awss_close_adha_monitor();
#endif
awss_success_notify();
awss_stopped = 1;
return 0;
}
int awss_stop(void)
{
awss_stopped = 1;
#ifdef AWSS_SUPPORT_AHA
awss_close_aha_monitor();
#endif
#ifdef AWSS_SUPPORT_ADHA
awss_close_adha_monitor();
#endif
awss_stop_connectap_monitor();
g_user_press = 0;
awss_press_timeout();
__awss_stop();
return 0;
}
int awss_config_press(void)
{
int timeout = HAL_Awss_Get_Timeout_Interval_Ms();
awss_trace("enable awss\r\n");
g_user_press = 1;
awss_event_post(IOTX_AWSS_ENABLE);
if (press_timer == NULL) {
press_timer = HAL_Timer_Create("press", (void (*)(void *))awss_press_timeout, NULL);
}
if (press_timer == NULL) {
return -1;
}
HAL_Timer_Stop(press_timer);
if (timeout < AWSS_PRESS_TIMEOUT_MS) {
timeout = AWSS_PRESS_TIMEOUT_MS;
}
HAL_Timer_Start(press_timer, timeout);
return 0;
}
uint8_t awss_get_config_press(void)
{
return g_user_press;
}
void awss_set_config_press(uint8_t press)
{
g_user_press = press;
}
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,133 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG)
char awss_finished = 2;
char awss_stop_connecting = 0;
int __awss_start(void)
{
char ssid[OS_MAX_SSID_LEN + 1] = {0}, passwd[OS_MAX_PASSWD_LEN + 1] = {0};
enum AWSS_AUTH_TYPE auth = AWSS_AUTH_TYPE_INVALID;
enum AWSS_ENC_TYPE encry = AWSS_ENC_TYPE_INVALID;
uint8_t bssid[OS_ETH_ALEN] = {0};
uint8_t channel = 0;
int ret;
awss_stop_connecting = 0;
awss_finished = 0;
/* these params is useless, keep it for compatible reason */
aws_start(NULL, NULL, NULL, NULL);
ret = aws_get_ssid_passwd(&ssid[0], &passwd[0], &bssid[0],
(char *)&auth, (char *)&encry, &channel);
if (!ret) {
awss_warn("awss timeout!");
}
if (awss_stop_connecting) {
awss_finished = 1;
return -1;
}
aws_destroy();
do {
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
char awss_notify_needed = 1;
int adha = 0;
#endif
if (awss_stop_connecting || strlen(ssid) == 0) {
break;
}
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
if ((adha = strcmp(ssid, ADHA_SSID)) == 0 || strcmp(ssid, DEFAULT_SSID) == 0) {
awss_notify_needed = 0;
awss_event_post(adha != 0 ? IOTX_AWSS_CONNECT_AHA : IOTX_AWSS_CONNECT_ADHA);
} else
#endif
{
awss_event_post(IOTX_AWSS_CONNECT_ROUTER);
AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_START);
}
ret = HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT_MS, ssid, passwd,
auth, encry, bssid, channel);
if (!ret) {
awss_debug("awss connect ssid:%s success", ssid);
awss_event_post(IOTX_AWSS_GOT_IP);
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
if (awss_notify_needed == 0) {
awss_dev_bind_notify_stop();
awss_suc_notify_stop();
awss_cmp_local_init(adha == 0 ? AWSS_LC_INIT_ROUTER : AWSS_LC_INIT_PAP);
awss_devinfo_notify();
if (adha == 0) {
AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_SUC);
}
awss_event_post(IOTX_AWSS_SETUP_NOTIFY);
} else
#endif
{
AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_SUC);
awss_devinfo_notify_stop();
produce_random(aes_random, sizeof(aes_random));
}
} else {
awss_debug("awss connect ssid:%s fail", ssid);
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
if (awss_notify_needed == 0) {
awss_event_post(adha != 0 ? IOTX_AWSS_CONNECT_AHA_FAIL : IOTX_AWSS_CONNECT_ADHA_FAIL);
} else
#endif
{
awss_event_post(IOTX_AWSS_CONNECT_ROUTER_FAIL);
}
}
} while (0);
AWSS_DISP_STATIS();
awss_finished = 1;
return 0;
}
int __awss_stop(void)
{
awss_stop_connecting = 1;
aws_destroy();
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
awss_devinfo_notify_stop();
#endif
awss_suc_notify_stop();
#ifndef AWSS_DISABLE_REGISTRAR
awss_registrar_deinit();
#endif
if (awss_finished < 2) {
awss_cmp_local_deinit(1);
} else {
awss_cmp_local_deinit(0);
}
while (1) {
if (awss_finished) {
break;
}
HAL_SleepMs(300);
}
aws_release_mutex();
awss_finished = 2;
return 0;
}
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_MAIN_H__
#define __AWSS_MAIN_H__
#include "awss_log.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#define DEFAULT_SSID zc_default_ssid
#define DEFAULT_PASSWD zc_default_passwd
#define ADHA_SSID zc_adha_ssid
#define ADHA_PASSWD zc_adha_passwd
extern const char *zc_default_ssid;
extern const char *zc_default_passwd;
extern const char *zc_adha_ssid;
extern const char *zc_adha_passwd;
int __awss_start(void);
int __awss_stop(void);
int awss_cancel_aha_monitor(void);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_SMARTCONFIG_H__
#define __AWSS_SMARTCONFIG_H__
#include <stdint.h>
#include "os.h"
#include "zconfig_lib.h"
#include "zconfig_ieee80211.h"
#include "zconfig_protocol.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
/* invalid channel, neither 0, 0xff, nor 1-13 */
#define INVALID_CHANNEL (0)
#define PAYLOAD_BITS_CNT (7)
#define PAYLOAD_BITS_MASK ((1 << PAYLOAD_BITS_CNT) - 1)
extern const uint8_t zconfig_fixed_offset[ZC_ENC_TYPE_MAX + 1][2];
extern const uint16_t zconfig_hint_frame[];
uint8_t is_data_frame(uint16_t len);
uint8_t is_start_frame(uint16_t len);
uint8_t is_group_frame(uint16_t len);
uint8_t get_data_index(uint16_t len);
uint8_t get_group_index(uint16_t len);
int zconfig_recv_completed(uint8_t tods);
int zconfig_get_ssid_passwd(uint8_t tods);
int package_cmp(uint8_t *package, uint8_t *src, uint8_t *dst, uint8_t tods, uint16_t len);
int package_save(uint8_t *package, uint8_t *src, uint8_t *dst, uint8_t tods, uint16_t len);
int awss_recv_callback_smartconfig(struct parser_res *res);
int awss_ieee80211_smartconfig_process(uint8_t *ieee80211, int len, int link_type,
struct parser_res *res, signed char rssi);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,825 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
/**
* ieee80211_is_mgmt - check if type is IEEE80211_FTYPE_MGMT
* @fc: frame control bytes in little-endian byteorder
*/
#if 0
int ieee80211_is_mgmt(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE)) ==
os_htole16(IEEE80211_FTYPE_MGMT);
}
#endif
/**
* ieee80211_is_ctl - check if type is IEEE80211_FTYPE_CTL
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_ctl(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE)) ==
os_htole16(IEEE80211_FTYPE_CTL);
}
/**
* ieee80211_is_data - check if type is IEEE80211_FTYPE_DATA
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_data(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE)) ==
os_htole16(IEEE80211_FTYPE_DATA);
}
/**
* ieee80211_has_tods - check if IEEE80211_FCTL_TODS is set
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_has_tods(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_TODS)) != 0;
}
/**
* ieee80211_has_fromds - check if IEEE80211_FCTL_FROMDS is set
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_has_fromds(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FROMDS)) != 0;
}
/**
* ieee80211_has_a4 - check if IEEE80211_FCTL_TODS and IEEE80211_FCTL_FROMDS are set
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_has_a4(uint16_t fc)
{
uint16_t tmp = os_htole16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
return (fc & tmp) == tmp;
}
/**
* ieee80211_has_order - check if IEEE80211_FCTL_ORDER is set
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_has_order(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_ORDER)) != 0;
}
/**
* ieee80211_has_protected - check if IEEE80211_FCTL_PROTECTED is set
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_has_protected(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_PROTECTED)) != 0;
}
/**
* ieee80211_is_data_qos - check if type is IEEE80211_FTYPE_DATA and IEEE80211_STYPE_QOS_DATA is set
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_data_qos(uint16_t fc)
{
/*
* mask with QOS_DATA rather than IEEE80211_FCTL_STYPE as we just need
* to check the one bit
*/
return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_STYPE_QOS_DATA)) ==
os_htole16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA);
}
/**
* ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and has data
* @fc: frame control bytes in little-endian byteorder
*/
#if 0
int ieee80211_is_data_present(uint16_t fc)
{
/*
* mask with 0x40 and test that that bit is clear to only return true
* for the data-containing substypes.
*/
return (fc & os_htole16(IEEE80211_FCTL_FTYPE | 0x40)) ==
os_htole16(IEEE80211_FTYPE_DATA);
}
#endif
/**
* ieee80211_is_data_present - check if type is IEEE80211_FTYPE_DATA and only data
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_data_exact(uint16_t fc)
{
uint16_t tmp = fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE);
return (tmp == os_htole16(IEEE80211_FTYPE_DATA)) ||
(tmp == os_htole16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA));
}
/**
* ieee80211_is_beacon - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_BEACON
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_beacon(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
}
/**
* ieee80211_is_action - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ACTION
* @fc: frame control bytes in little-endian byteorder
*/
#if 0
int ieee80211_is_action(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_ACTION);
}
#endif
/**
* ieee80211_is_probe_req - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_REQ
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_probe_req(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ);
}
/**
* ieee80211_is_probe_resp - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_PROBE_RESP
* @fc: frame control bytes in little-endian byteorder
*/
int ieee80211_is_probe_resp(uint16_t fc)
{
return (fc & os_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
os_htole16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_RESP);
}
/**
* ieee80211_get_SA - get pointer to SA
* @hdr: the frame
*
* Given an 802.11 frame, this function returns the offset
* to the source address (SA). It does not verify that the
* header is long enough to contain the address, and the
* header must be long enough to contain the frame control
* field.
*/
uint8_t *ieee80211_get_SA(struct ieee80211_hdr *hdr)
{
if (ieee80211_has_a4(hdr->frame_control))
return hdr->addr4;
if (ieee80211_has_fromds(hdr->frame_control))
return hdr->addr3;
return hdr->addr2;
}
/**
* ieee80211_get_DA - get pointer to DA
* @hdr: the frame
*
* Given an 802.11 frame, this function returns the offset
* to the destination address (DA). It does not verify that
* the header is long enough to contain the address, and the
* header must be long enough to contain the frame control
* field.
*/
uint8_t *ieee80211_get_DA(struct ieee80211_hdr *hdr)
{
if (ieee80211_has_tods(hdr->frame_control))
return hdr->addr3;
else
return hdr->addr1;
}
uint8_t *ieee80211_get_BSSID(struct ieee80211_hdr *hdr)
{
if (ieee80211_has_tods(hdr->frame_control)) {
if (!ieee80211_has_fromds(hdr->frame_control))
return hdr->addr1;
else
return NULL;
} else {
if (ieee80211_has_fromds(hdr->frame_control))
return hdr->addr2;
else
return hdr->addr3;
}
}
int ieee80211_get_bssid(uint8_t *in, uint8_t *mac)
{
uint8_t *bssid = ieee80211_get_BSSID((struct ieee80211_hdr *)in);
if (bssid)
memcpy(mac, bssid, ETH_ALEN);
else
return -1;
return 0;
}
int ieee80211_has_frags(uint16_t fc)
{
uint16_t tmp = fc & os_htole16(IEEE80211_FCTL_MOREFRAGS | IEEE80211_FCTL_ORDER);
return !!tmp;
}
/* DATA: 24B */
/* QOS-DATA: 26B */
int ieee80211_hdrlen(uint16_t fc)
{
uint32_t hdrlen = 24;
if (ieee80211_is_data(fc)) {
if (ieee80211_has_a4(fc))
hdrlen = 30;
if (ieee80211_is_data_qos(fc)) {
hdrlen += IEEE80211_QOS_CTL_LEN;
if (ieee80211_has_order(fc))
hdrlen += IEEE80211_HT_CTL_LEN;
}
goto out;
}
if (ieee80211_is_ctl(fc)) {
/*
* ACK and CTS are 10 bytes, all others 16. To see how
* to get this condition consider
* subtype mask: 0b0000000011110000 (0x00F0)
* ACK subtype: 0b0000000011010000 (0x00D0)
* CTS subtype: 0b0000000011000000 (0x00C0)
* bits that matter: ^^^ (0x00E0)
* value of those: 0b0000000011000000 (0x00C0)
*/
if ((fc & os_htole16(0x00E0)) == os_htole16(0x00C0))
hdrlen = 10;
else
hdrlen = 16;
}
out:
return hdrlen;
}
/* helpers */
int ieee80211_get_radiotap_len(uint8_t *data)
{
struct ieee80211_radiotap_header *hdr =
(struct ieee80211_radiotap_header *)data;
return os_get_unaligned_le16((uint8_t *)&hdr->it_len);
}
const uint8_t *cfg80211_find_ie(uint8_t eid, const uint8_t *ies, int len)
{
while (len > 2 && ies[0] != eid) {
len -= ies[1] + 2;
ies += ies[1] + 2;
}
if (len < 2)
return NULL;
if (len < 2 + ies[1])
return NULL;
return ies;
}
/**
* cfg80211_find_vendor_ie - find vendor specific information element in data
*
* @oui: vendor OUI
* @oui_type: vendor-specific OUI type
* @ies: data consisting of IEs
* @len: length of data
*
* Return: %NULL if the vendor specific element ID could not be found or if the
* element is invalid (claims to be longer than the given data), or a pointer to
* the first byte of the requested element, that is the byte containing the
* element ID.
*
* Note: There are no checks on the element length other than having to fit into
* the given data.
*/
const uint8_t *cfg80211_find_vendor_ie(uint32_t oui, uint8_t oui_type, const uint8_t *ies, int len)
{
struct ieee80211_vendor_ie *ie;
const uint8_t *pos = ies, *end = ies + len;
int ie_oui;
while (pos < end) {
pos = cfg80211_find_ie(WLAN_EID_VENDOR_SPECIFIC, pos,
end - pos);
if (!pos)
return NULL;
ie = (struct ieee80211_vendor_ie *)pos;
/* make sure we can access ie->len */
/* BUILD_BUG_ON(offsetof(struct ieee80211_vendor_ie, len) != 1); */
if (ie->len < sizeof(*ie))
goto cont;
ie_oui = ie->oui[0] << 16 | ie->oui[1] << 8 | ie->oui[2];
/* awss_trace("oui=%x, type=%x, len=%d\r\n", ie_oui, oui_type, ie->len); */
if (ie_oui == oui && ie->oui_type == oui_type)
return pos;
cont:
pos += 2 + ie->len;
}
return NULL;
}
/**
* extract ssid from beacon frame or probe resp frame
*
* @beacon_frame: [IN] original 80211 beacon frame
* @frame_len: [IN] len of beacon frame
* @ssid: [OUT] null-terminated string, max len 32 bytes
*
* Return:
* 0/success, -1/failed
*/
int ieee80211_get_ssid(uint8_t *beacon_frame, uint16_t frame_len, uint8_t *ssid)
{
uint16_t ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);/* same as u.probe_resp.variable */
const uint8_t *ptr = cfg80211_find_ie(WLAN_EID_SSID,
beacon_frame + ieoffset, frame_len - ieoffset);
if (ptr) {
uint8_t ssid_len = ptr[1];
if (ssid_len <= 32) { /* ssid 32 octets at most */
memcpy(ssid, ptr + 2, ssid_len);/* eating EID & len */
ssid[ssid_len] = '\0';
return 0;
}
}
return -1;
}
/**
* extract channel from beacon frame or probe resp frame
*
* @beacon_frame: [IN] original 80211 beacon frame
* @frame_len: [IN] len of beacon frame
*
* Return:
* bss channel 1-13, 0--means invalid channel
*/
int cfg80211_get_bss_channel(uint8_t *beacon_frame, uint16_t frame_len)
{
uint16_t ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);/* same as u.probe_resp.variable */
const uint8_t *ie = beacon_frame + ieoffset;
uint16_t ielen = frame_len - ieoffset;
const uint8_t *tmp;
int channel_number = 0;
tmp = cfg80211_find_ie(WLAN_EID_DS_PARAMS, ie, ielen);
if (tmp && tmp[1] == 1) {
channel_number = tmp[2];
} else {
tmp = cfg80211_find_ie(WLAN_EID_HT_OPERATION, ie, ielen);
if (tmp && tmp[1] >= sizeof(struct ieee80211_ht_operation)) {
struct ieee80211_ht_operation *htop = (void *)(tmp + 2);
channel_number = htop->primary_chan;
}
}
return channel_number;
}
static const uint8_t WPA_OUI23A_TYPE[] = {0x00, 0x50, 0xf2, 0x01};
static const uint8_t RSN_SUITE_1X[] = {0x00, 0x0f, 0xac, 0x01};
static const uint8_t WPA_CIPHER_SUITE_NONE23A[] = {0x00, 0x50, 0xf2, 0x00};
static const uint8_t WPA_CIPHER_SUITE_WEP4023A[] = {0x00, 0x50, 0xf2, 0x01};
static const uint8_t WPA_CIPHER_SUITE_TKIP23A[] = {0x00, 0x50, 0xf2, 0x02};
/* static const uint8_t WPA_CIPHER_SUITE_WRAP23A[] = {0x00, 0x50, 0xf2, 0x03}; */
static const uint8_t WPA_CIPHER_SUITE_CCMP23A[] = {0x00, 0x50, 0xf2, 0x04};
static const uint8_t WPA_CIPHER_SUITE_WEP10423A[] = {0x00, 0x50, 0xf2, 0x05};
static const uint8_t RSN_CIPHER_SUITE_NONE23A[] = {0x00, 0x0f, 0xac, 0x00};
static const uint8_t RSN_CIPHER_SUITE_WEP4023A[] = {0x00, 0x0f, 0xac, 0x01};
static const uint8_t RSN_CIPHER_SUITE_TKIP23A[] = {0x00, 0x0f, 0xac, 0x02};
/* static const uint8_t RSN_CIPHER_SUITE_WRAP23A[] = {0x00, 0x0f, 0xac, 0x03}; */
static const uint8_t RSN_CIPHER_SUITE_CCMP23A[] = {0x00, 0x0f, 0xac, 0x04};
static const uint8_t RSN_CIPHER_SUITE_WEP10423A[] = {0x00, 0x0f, 0xac, 0x05};
#define WPA_SELECTOR_LEN (4)
#define RSN_SELECTOR_LEN (4)
#define BIT(x) (1 << (x))
#define WPA_CIPHER_NONE BIT(0)
#define WPA_CIPHER_WEP40 BIT(1)
#define WPA_CIPHER_WEP104 BIT(2)
#define WPA_CIPHER_TKIP BIT(3)
#define WPA_CIPHER_CCMP BIT(4)
static uint8_t map_cipher_to_encry(uint8_t cipher)
{
switch (cipher) {
case WPA_CIPHER_CCMP:
return ZC_ENC_TYPE_AES;
case WPA_CIPHER_TKIP:
return ZC_ENC_TYPE_TKIP;
case WPA_CIPHER_WEP40:
case WPA_CIPHER_WEP104:
return ZC_ENC_TYPE_WEP;
case WPA_CIPHER_NONE:
return ZC_ENC_TYPE_NONE;
case (WPA_CIPHER_TKIP | WPA_CIPHER_CCMP):
return ZC_ENC_TYPE_TKIPAES;
default:
awss_warn("unknow cipher type: %x\r\n", cipher);
return ZC_ENC_TYPE_INVALID;
}
}
static int get_wpa_cipher_suite(const uint8_t *s)
{
if (!memcmp(s, WPA_CIPHER_SUITE_NONE23A, WPA_SELECTOR_LEN))
return WPA_CIPHER_NONE;
if (!memcmp(s, WPA_CIPHER_SUITE_WEP4023A, WPA_SELECTOR_LEN))
return WPA_CIPHER_WEP40;
if (!memcmp(s, WPA_CIPHER_SUITE_TKIP23A, WPA_SELECTOR_LEN))
return WPA_CIPHER_TKIP;
if (!memcmp(s, WPA_CIPHER_SUITE_CCMP23A, WPA_SELECTOR_LEN))
return WPA_CIPHER_CCMP;
if (!memcmp(s, WPA_CIPHER_SUITE_WEP10423A, WPA_SELECTOR_LEN))
return WPA_CIPHER_WEP104;
return 0;
}
static int get_wpa2_cipher_suite(const uint8_t *s)
{
if (!memcmp(s, RSN_CIPHER_SUITE_NONE23A, RSN_SELECTOR_LEN))
return WPA_CIPHER_NONE;
if (!memcmp(s, RSN_CIPHER_SUITE_WEP4023A, RSN_SELECTOR_LEN))
return WPA_CIPHER_WEP40;
if (!memcmp(s, RSN_CIPHER_SUITE_TKIP23A, RSN_SELECTOR_LEN))
return WPA_CIPHER_TKIP;
if (!memcmp(s, RSN_CIPHER_SUITE_CCMP23A, RSN_SELECTOR_LEN))
return WPA_CIPHER_CCMP;
if (!memcmp(s, RSN_CIPHER_SUITE_WEP10423A, RSN_SELECTOR_LEN))
return WPA_CIPHER_WEP104;
return 0;
}
int cfg80211_parse_wpa_info(const uint8_t *wpa_ie, int wpa_ie_len,
uint8_t *group_cipher, uint8_t *pairwise_cipher,
uint8_t *is_8021x)
{
int i, ret = 0;
int left, count;
const uint8_t *pos;
if (wpa_ie_len <= 0) {
/* No WPA IE - fail silently */
return -1;
}
if (wpa_ie[1] != (uint8_t)(wpa_ie_len - 2))
return -1;
pos = wpa_ie;
pos += 8;
left = wpa_ie_len - 8;
/* group_cipher */
if (left >= WPA_SELECTOR_LEN) {
*group_cipher = get_wpa_cipher_suite(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
} else if (left > 0) {
return -1;
}
/* pairwise_cipher */
if (left >= 2) {
/* count = le16_to_cpu(*(uint16_t*)pos); */
count = os_get_unaligned_le16((uint8_t *)pos);
pos += 2;
left -= 2;
if (count == 0 || left < count * WPA_SELECTOR_LEN) {
return -1;
}
for (i = 0; i < count; i++) {
*pairwise_cipher |= get_wpa_cipher_suite(pos);
pos += WPA_SELECTOR_LEN;
left -= WPA_SELECTOR_LEN;
}
} else if (left == 1) {
return -1;
}
if (is_8021x) {
if (left >= 6) {
pos += 2;
if (!memcmp(pos, WPA_OUI23A_TYPE, 4)) {
*is_8021x = 1;
}
}
}
return ret;
}
int cfg80211_parse_wpa2_info(const uint8_t* rsn_ie, int rsn_ie_len, uint8_t *group_cipher,
uint8_t *pairwise_cipher, uint8_t *is_8021x)
{
int i, ret = 0;
int left, count;
const uint8_t *pos;
if (rsn_ie_len <= 0) {
/* No RSN IE - fail silently */
return -1;
}
if (*rsn_ie != WLAN_EID_RSN || *(rsn_ie+1) != (uint8_t)(rsn_ie_len - 2)) {
return -1;
}
pos = rsn_ie;
pos += 4;
left = rsn_ie_len - 4;
/* group_cipher */
if (left >= RSN_SELECTOR_LEN) {
*group_cipher = get_wpa2_cipher_suite(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
} else if (left > 0) {
return -1;
}
/* pairwise_cipher */
if (left >= 2) {
/* count = le16_to_cpu(*(uint16_t*)pos); */
count = os_get_unaligned_le16((uint8_t *)pos);
pos += 2;
left -= 2;
if (count == 0 || left < count * RSN_SELECTOR_LEN) {
return -1;
}
for (i = 0; i < count; i++) {
*pairwise_cipher |= get_wpa2_cipher_suite(pos);
pos += RSN_SELECTOR_LEN;
left -= RSN_SELECTOR_LEN;
}
} else if (left == 1) {
return -1;
}
if (is_8021x) {
if (left >= 6) {
pos += 2;
if (!memcmp(pos, RSN_SUITE_1X, 4)) {
*is_8021x = 1;
}
}
}
return ret;
}
/**
* extract auth/encry type from beacon frame or probe resp frame
*
* @beacon_frame: [IN] original 80211 beacon frame
* @frame_len: [IN] len of beacon frame
*
* Return:
* bss channel 1-13, 0--means invalid channel
*/
int cfg80211_get_cipher_info(uint8_t *beacon_frame, uint16_t frame_len,
uint8_t *auth_type, uint8_t *pairwise_cipher_type,
uint8_t *group_cipher_type)
{
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon_frame;
uint8_t is_privacy = !!(mgmt->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY);
uint16_t ieoffset = offsetof(struct ieee80211_mgmt, u.beacon.variable);/* same as u.probe_resp.variable */
const uint8_t *ie = beacon_frame + ieoffset;
uint16_t ielen = frame_len - ieoffset;
uint8_t auth = 0, group_cipher = 0, pairwise_cipher = 0, is80211X = 0;
const uint8_t *tmp;
int ret = 0;
tmp = cfg80211_find_ie(WLAN_EID_RSN, ie, ielen);
if (tmp && tmp[1]) {
ret = cfg80211_parse_wpa2_info(tmp, tmp[1] + 2, &group_cipher, &pairwise_cipher, &is80211X);
if (is80211X)
auth = ZC_AUTH_TYPE_WPA28021X;
else
auth = ZC_AUTH_TYPE_WPA2PSK;
group_cipher = map_cipher_to_encry(group_cipher);
pairwise_cipher = map_cipher_to_encry(pairwise_cipher);
} else {
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
tmp = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, WLAN_OUI_TYPE_MICROSOFT_WPA, ie, ielen);
if (tmp) {
ret = cfg80211_parse_wpa_info(tmp, tmp[1] + 2, &group_cipher, &pairwise_cipher, &is80211X);
if (is80211X)
auth = ZC_AUTH_TYPE_WPA8021X;
else
auth = ZC_AUTH_TYPE_WPAPSK;
group_cipher = map_cipher_to_encry(group_cipher);
pairwise_cipher = map_cipher_to_encry(pairwise_cipher);
} else
#endif
{
if (is_privacy) {
auth = ZC_AUTH_TYPE_SHARED; /* TODO: WEP */
pairwise_cipher = ZC_ENC_TYPE_WEP;
group_cipher = ZC_ENC_TYPE_WEP;
} else {
auth = ZC_AUTH_TYPE_OPEN;
pairwise_cipher = ZC_ENC_TYPE_NONE;
group_cipher = ZC_ENC_TYPE_NONE;
}
}
}
if (auth_type)
*auth_type = auth;
if (pairwise_cipher_type)
*pairwise_cipher_type = pairwise_cipher;
if (group_cipher_type)
*group_cipher_type = group_cipher;
return ret;
}
/*
* make sure 80211 frame is word align, otherwise struct ieee80211_hdr will bug
* TODO: code refactor, avoid using memmove
*/
#define check_ieee80211_buf_alignment(buf_addr, len) \
do {\
if (((unsigned long)(buf_addr) & 0x1) && len > 0) {\
uint8_t *word_align_addr = (uint8_t *)((unsigned long)(buf_addr) & ~0x1);\
memmove(word_align_addr, buf_addr, len);\
buf_addr = word_align_addr;\
}\
} while (0)
uint8_t *zconfig_remove_link_header(uint8_t **in, int *len, int link_type)
{
int lt_len = 0;
switch (link_type) {
case AWS_LINK_TYPE_NONE:
break;
case AWS_LINK_TYPE_PRISM:
#define PRISM_HDR_LEN 144
*in += PRISM_HDR_LEN;
*len -= PRISM_HDR_LEN;
/* 144, no need to check buf aligment */
break;
case AWS_LINK_TYPE_80211_RADIO:
lt_len = ieee80211_get_radiotap_len(*in);
*in += lt_len;
*len -= lt_len;
check_ieee80211_buf_alignment(*in, *len);
break;
case AWS_LINK_TYPE_80211_RADIO_AVS:
#define WLANCAP_MAGIC_COOKIE_V1 0x80211001
#define WLANCAP_MAGIC_COOKIE_V2 0x80211002
lt_len = *(uint32_t *)(*in + 4);/* first 4 byte is magic code */
*in += lt_len;
*len -= lt_len;
check_ieee80211_buf_alignment(*in, *len);
break;
default:
awss_debug("un-supported link type!\r\n");
break;
}
return *in;
}
struct awss_protocol_couple_type awss_protocol_couple_array[] = {
#ifdef AWSS_SUPPORT_HT40
{ALINK_HT_CTRL, awss_ieee80211_ht_ctrl_process, awss_recv_callback_ht_ctrl},
#endif
#ifdef AWSS_SUPPORT_APLIST
{ALINK_APLIST, awss_ieee80211_aplist_process, NULL},
#endif
#ifdef AWSS_SUPPORT_AHA
{ALINK_DEFAULT_SSID, awss_ieee80211_aha_process, awss_recv_callback_aha_ssid},
#endif
#ifdef AWSS_SUPPORT_ADHA
{ALINK_ADHA_SSID, awss_ieee80211_adha_process, awss_recv_callback_adha_ssid},
#endif
#ifndef AWSS_DISABLE_ENROLLEE
{ALINK_ZERO_CONFIG, awss_ieee80211_zconfig_process, awss_recv_callback_zconfig},
#endif
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
{ALINK_WPS, awss_ieee80211_wps_process, awss_recv_callback_wps},
#endif
#ifdef AWSS_SUPPORT_SMARTCONFIG
{ALINK_BROADCAST, awss_ieee80211_smartconfig_process, awss_recv_callback_smartconfig}
#endif
};
/**
* ieee80211_data_extratct - extract 80211 frame info
*
* @in: [IN] 80211 frame
* @len: [IN] 80211 frame len
* @link_type: [IN] link type @see enum AWS_LINK_TYPE
* @res: [OUT] 80211 frame parser result, see struct parser_res.
*
* @warning: encry_type may collision with aes & tpip in some cases,
* then encry_type will be set to INVALID.
* @Return:
* @see enum ALINK_TYPE
*
* @Note: howto deal with radio RSSI signal
*/
int ieee80211_data_extract(uint8_t *in, int len, int link_type, struct parser_res *res, signed char rssi)
{
struct ieee80211_hdr *hdr;
int alink_type = ALINK_INVALID;
int pkt_type = PKG_INVALID;
int i, fc;
hdr = (struct ieee80211_hdr *)zconfig_remove_link_header(&in, &len, link_type);
if (len <= 0)
goto drop;
fc = hdr->frame_control;
for (i = 0; i < sizeof(awss_protocol_couple_array) / sizeof(awss_protocol_couple_array[0]); i ++) {
awss_protocol_process_func_type protocol_func = awss_protocol_couple_array[i].awss_protocol_process_func;
if (protocol_func == NULL)
continue;
alink_type = protocol_func((uint8_t *)hdr, len, link_type, res, rssi);
if (alink_type != ALINK_INVALID)
break;
}
if (alink_type == ALINK_INVALID)
goto drop;
if (alink_type != ALINK_HT_CTRL) {
/* convert IEEE 802.11 header + possible LLC headers into Ethernet header
* IEEE 802.11 address fields:
* ToDS FromDS Addr1 Addr2 Addr3 Addr4
* 0 0 DA SA BSSID n/a
* 0 1 DA BSSID SA n/a
* 1 0 BSSID SA DA n/a
* 1 1 RA TA DA SA
*/
res->src = ieee80211_get_SA(hdr);
res->dst = ieee80211_get_DA(hdr);
res->bssid = ieee80211_get_BSSID(hdr);
res->tods = ieee80211_has_tods(fc);
}
do {
awss_protocol_finish_func_type finish_func = awss_protocol_couple_array[i].awss_protocol_finish_func;
if (finish_func)
pkt_type = finish_func(res);
} while(0);
drop:
return pkt_type;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,302 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __ZCONFIG_IEEE80211_H__
#define __ZCONFIG_IEEE80211_H__
#include "zconfig_utils.h"
#include "zconfig_protocol.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#define WIFI_RX_SENSITIVITY (-85)
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif
/*
* DS bit usage
*
* TA = transmitter address
* RA = receiver address
* DA = destination address
* SA = source address
*
* ToDS FromDS A1(RA) A2(TA) A3 A4 Use
* -----------------------------------------------------------------
* 0 0 DA SA BSSID - IBSS/DLS
* 0 1 DA BSSID SA - AP -> STA
* 1 0 BSSID SA DA - AP <- STA
* 1 1 RA TA DA SA unspecified (WDS)
*/
#define FCS_LEN (4)
#define IEEE80211_FCTL_VERS (0x0003)
#define IEEE80211_FCTL_FTYPE (0x000c)
#define IEEE80211_FCTL_STYPE (0x00f0)
#define IEEE80211_FCTL_TODS (0x0100)
#define IEEE80211_FCTL_FROMDS (0x0200)
#define IEEE80211_FCTL_MOREFRAGS (0x0400)
#define IEEE80211_FCTL_RETRY (0x0800)
#define IEEE80211_FCTL_PM (0x1000)
#define IEEE80211_FCTL_MOREDATA (0x2000)
#define IEEE80211_FCTL_PROTECTED (0x4000)
#define IEEE80211_FCTL_ORDER (0x8000)
#define IEEE80211_FCTL_CTL_EXT (0x0f00)
#define IEEE80211_SCTL_FRAG (0x000F)
#define IEEE80211_SCTL_SEQ (0xFFF0)
#define IEEE80211_FTYPE_MGMT (0x0000)
#define IEEE80211_FTYPE_CTL (0x0004)
#define IEEE80211_FTYPE_DATA (0x0008)
#define IEEE80211_FTYPE_EXT (0x000c)
#define IEEE80211_STYPE_DATA (0x0000)
#define IEEE80211_STYPE_QOS_DATA (0x0080)
#define IEEE80211_STYPE_PROBE_REQ (0x0040)
#define IEEE80211_STYPE_PROBE_RESP (0x0050)
#define IEEE80211_STYPE_BEACON (0x0080)
#define IEEE80211_STYPE_ACTION (0x00D0)
#define IEEE80211_QOS_CTL_LEN (2)
#define IEEE80211_HT_CTL_LEN (4)
/* beacon capab_info */
#define WLAN_CAPABILITY_PRIVACY (1 << 4)
#define IEEE80211_SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
#define IEEE80211_SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
#define WLAN_CATEGORY_VENDOR_SPECIFIC (127)
#define WLAN_EID_SSID (0)
#define WLAN_EID_DS_PARAMS (3)
#define WLAN_EID_RSN (48)
#define WLAN_EID_HT_OPERATION (61)
#define WLAN_EID_VENDOR_SPECIFIC (221)
#define WLAN_OUI_ALIBABA (0xD896E0)
#define WLAN_OUI_TYPE_ALIBABA (1)
#define WLAN_OUI_TYPE_ENROLLEE (0xAA)
#define WLAN_OUI_TYPE_REGISTRAR (0xAB)
enum ALINK_TYPE {
ALINK_INVALID = 0,
ALINK_BROADCAST = 1,
ALINK_ROUTER = 2,
ALINK_ACTION = 3,
ALINK_WPS = 4,
ALINK_DEFAULT_SSID = 5,
ALINK_ZERO_CONFIG = 6,
ALINK_ADHA_SSID = 7,
ALINK_APLIST,
ALINK_HT_CTRL,
};
/* 80211 frame parser result */
struct parser_res {
union _alink_type_ {
/* for broadcast data frame */
struct broadcast_info {
uint8_t encry_type;/* none/wep/tkip/aes */
uint16_t data_len;/* framelen - 80211 hdr - fcs(4) */
uint16_t sn;
} br;
/* for alink ie frame */
struct ie_info {
uint8_t *alink_ie;
uint16_t alink_ie_len;
} ie;
/* for p2p action frame */
struct action_info {
uint8_t *data;
uint16_t data_len;
} action;
/* for p2p wps frame */
struct wps_info {
uint8_t *data;
uint16_t data_len;
} wps;
/* for ht40 ctrl frame */
struct ht_ctrl_info {
signed char rssi;
uint8_t filter;
uint16_t data_len;
} ht_ctrl;
} u;
uint8_t *src; /* src mac of sender */
uint8_t *dst; /* ff:ff:ff:ff:ff:ff */
uint8_t *bssid; /* mac of AP */
uint8_t tods; /* fromDs or toDs */
uint8_t channel; /* 1 - 13 */
};
struct ieee80211_hdr {
uint16_t frame_control;
uint16_t duration_id;
uint8_t addr1[ETH_ALEN];
uint8_t addr2[ETH_ALEN];
uint8_t addr3[ETH_ALEN];
uint16_t seq_ctrl;
uint8_t addr4[ETH_ALEN];
};
/*
* The radio capture header precedes the 802.11 header.
*
* Note well: all radiotap fields are little-endian.
*/
struct ieee80211_radiotap_header {
uint8_t it_version; /* Version 0. Only increases
* for drastic changes,
* introduction of compatible
* new fields does not count.
*/
uint8_t it_pad;
uint16_t it_len; /* length of the whole
* header in bytes, including
* it_version, it_pad,
* it_len, and data fields.
*/
uint32_t it_present; /* A bitmap telling which
* fields are present. Set bit 31
* (0x80000000) to extend the
* bitmap by another 32 bits.
* Additional extensions are made
* by setting bit 31.
*/
};
/**
* struct ieee80211_ht_operation - HT operation IE
*
* This structure is the "HT operation element" as
* described in 802.11n-2009 7.3.2.57
*/
struct ieee80211_ht_operation {
uint8_t primary_chan;
uint8_t ht_param;
uint16_t operation_mode;
uint16_t stbc_param;
uint8_t basic_set[16];
};
struct ieee80211_vendor_ie {
uint8_t element_id;
uint8_t len;
uint8_t oui[3];
uint8_t oui_type;
};
/*
* i.e. alibaba ie
* @name @len @payload
* element_id 1 221
* len 1 22
* oui 3 0xD896E0
* oui_type 1 1 -- alink router service advertisement
* version 1 1
* challenge 16 non-zero-ascii code
* reserve 1 0
*/
struct ieee80211_mgmt {
uint16_t frame_control;
uint16_t duration;
uint8_t da[ETH_ALEN];
uint8_t sa[ETH_ALEN];
uint8_t bssid[ETH_ALEN];
uint16_t seq_ctrl;
union {
struct {
/* __le64 timestamp; */
uint16_t timestamp[4];
uint16_t beacon_int;
uint16_t capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params, TIM */
uint8_t variable;
} beacon;
struct {
/* only variable items: SSID, Supported rates */
uint8_t variable;
} probe_req;
struct {
/* __le64 timestamp; */
uint16_t timestamp[4];
uint16_t beacon_int;
uint16_t capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params */
uint8_t variable;
} probe_resp;
} u;
};
typedef int (*awss_protocol_process_func_type)(uint8_t *, int, int, struct parser_res *, signed char);
typedef int (*awss_protocol_finish_func_type)(struct parser_res *);
struct awss_protocol_couple_type {
int type;
awss_protocol_process_func_type awss_protocol_process_func;
awss_protocol_finish_func_type awss_protocol_finish_func;
};
int ieee80211_data_extract(uint8_t *in, int len, int link_type,
struct parser_res *res, signed char rssi);
struct ap_info *zconfig_get_apinfo(uint8_t *mac);
struct ap_info *zconfig_get_apinfo_by_ssid(uint8_t *ssid);
struct ap_info *zconfig_get_apinfo_by_ssid_prefix(uint8_t *ssid_prefix);
struct ap_info *zconfig_get_apinfo_by_ssid_suffix(uint8_t *ssid_suffix);
/* add channel to scanning channel list */
int zconfig_add_active_channel(int channel);
uint8_t zconfig_get_press_status();
int ieee80211_hdrlen(uint16_t fc);
int ieee80211_has_a4(uint16_t fc);
int ieee80211_is_ctl(uint16_t fc);
int ieee80211_is_mgmt(uint16_t fc);
int ieee80211_is_data(uint16_t fc);
int ieee80211_has_tods(uint16_t fc);
int ieee80211_has_frags(uint16_t fc);
int ieee80211_has_order(uint16_t fc);
int ieee80211_is_beacon(uint16_t fc);
int ieee80211_is_action(uint16_t fc);
int ieee80211_has_fromds(uint16_t fc);
int ieee80211_is_data_qos(uint16_t fc);
int ieee80211_is_probe_req(uint16_t fc);
int ieee80211_is_probe_resp(uint16_t fc);
int ieee80211_is_data_exact(uint16_t fc);
int ieee80211_has_protected(uint16_t fc);
int ieee80211_is_data_present(uint16_t fc);
int ieee80211_get_radiotap_len(uint8_t *data);
int ieee80211_get_bssid(uint8_t *in, uint8_t *mac);
int ieee80211_get_ssid(uint8_t *beacon_frame, uint16_t frame_len, uint8_t *ssid);
int ieee80211_data_extract(uint8_t *in, int len, int link_type, struct parser_res *res, signed char rssi);
int cfg80211_get_bss_channel(uint8_t *beacon_frame, uint16_t frame_len);
int cfg80211_get_cipher_info(uint8_t *beacon_frame, uint16_t frame_len,
uint8_t *auth_type, uint8_t *pairwise_cipher_type, uint8_t *group_cipher_type);
uint8_t *ieee80211_get_SA(struct ieee80211_hdr *hdr);
uint8_t *ieee80211_get_DA(struct ieee80211_hdr *hdr);
uint8_t *ieee80211_get_BSSID(struct ieee80211_hdr *hdr);
const uint8_t *cfg80211_find_ie(uint8_t eid, const uint8_t *ies, int len);
const uint8_t *cfg80211_find_vendor_ie(uint32_t oui, uint8_t oui_type, const uint8_t *ies, int len);
struct ap_info *zconfig_get_apinfo(uint8_t *mac);
struct ap_info *zconfig_get_apinfo_by_ssid(uint8_t *ssid);
struct ap_info *zconfig_get_apinfo_by_ssid_prefix(uint8_t *ssid_prefix);
struct ap_info *zconfig_get_apinfo_by_ssid_suffix(uint8_t *ssid_suffix);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif /* __IEEE80211_H */

View File

@@ -0,0 +1,457 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#ifdef AWSS_SUPPORT_STATIS
#define DROUTE_START g_awss_statis.droute.conn_router_start
#define DROUTE_END g_awss_statis.droute.conn_router_end
#define DROUTE_CNT g_awss_statis.droute.conn_router_cnt
#define DROUTE_SUC g_awss_statis.droute.conn_router_suc
#define DROUTE_TMIN g_awss_statis.droute.conn_router_time_min
#define DROUTE_TMAX g_awss_statis.droute.conn_router_time_max
#define DROUTE_TMEAN g_awss_statis.droute.conn_router_time_mean
#ifdef AWSS_SUPPORT_SMARTCONFIG
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
#define WPS_CNT g_awss_statis.wps.wps_parse_cnt
#define WPS_CRC_ERR g_awss_statis.wps.wps_parse_crc_err
#define WPS_PW_ERR g_awss_statis.wps.wps_parse_passwd_err
#define WPS_SUC g_awss_statis.wps.wps_parse_suc
#endif
#define SM_CNT g_awss_statis.sm.sm_parse_cnt
#define SM_CRC_ERR g_awss_statis.sm.sm_parse_crc_err
#define SM_PW_ERR g_awss_statis.sm.sm_parse_passwd_err
#define SM_SUC g_awss_statis.sm.sm_parse_suc
#define SM_START g_awss_statis.sm.sm_parse_start
#define SM_END g_awss_statis.sm.sm_parse_end
#define SM_TMIN g_awss_statis.sm.sm_time_min
#define SM_TMAX g_awss_statis.sm.sm_time_max
#define SM_TMEAN g_awss_statis.sm.sm_time_mean
#endif
#ifdef AWSS_SUPPORT_AHA
#define PAP_CNT g_awss_statis.pap.aha_cnt
#define PAP_SUC g_awss_statis.pap.aha_suc
#define PAP_TMIN g_awss_statis.pap.aha_time_min
#define PAP_TMAX g_awss_statis.pap.aha_time_max
#define PAP_TMEAN g_awss_statis.pap.aha_time_mean
#define PAP_START g_awss_statis.pap.aha_start
#define PAP_END g_awss_statis.pap.aha_end
#define PAP_SSTART g_awss_statis.pap.aha_scan_start
#define PAP_SSTOP g_awss_statis.pap.aha_scan_end
#define PAP_SAP g_awss_statis.pap.aha_switch_ap
#define PAP_PW_ERR g_awss_statis.pap.aha_passwd_err
#endif
#ifdef AWSS_SUPPORT_DEV_AP
#define DAP_CNT g_awss_statis.dap.dev_ap_cnt
#define DAP_SUC g_awss_statis.dap.dev_ap_suc
#define DAP_TMIN g_awss_statis.dap.dev_ap_time_min
#define DAP_TMAX g_awss_statis.dap.dev_ap_time_max
#define DAP_TMEAN g_awss_statis.dap.dev_ap_time_mean
#define DAP_START g_awss_statis.dap.dev_ap_start
#define DAP_END g_awss_statis.dap.dev_ap_end
#define DAP_PW_ERR g_awss_statis.dap.dev_ap_passwd_err
#endif
#ifdef AWSS_SUPPORT_ADHA
#define ROUTE_CNT g_awss_statis.route.adha_cnt
#define ROUTE_SUC g_awss_statis.route.adha_suc
#define ROUTE_TMIN g_awss_statis.route.adha_time_min
#define ROUTE_TMAX g_awss_statis.route.adha_time_max
#define ROUTE_TMEAN g_awss_statis.route.adha_time_mean
#define ROUTE_START g_awss_statis.route.adha_start
#define ROUTE_END g_awss_statis.route.adha_end
#endif
#ifndef AWSS_DISABLE_ENROLLEE
#define ZC_CNT g_awss_statis.zconfig.zc_cnt
#define ZC_SUC g_awss_statis.zconfig.zc_suc
#define ZC_PW_ERR g_awss_statis.zconfig.zc_passwd_err
#endif
#define AWSS_STATIS_BUF_LEN (768)
static void *awss_statis_mutex = NULL;
static uint32_t awss_statis_trace_id = 0;
static uint32_t awss_statis_report_id = 0;
static struct awss_statis_t g_awss_statis = {0};
int awss_report_statis(const char *module)
{
const char *elem_fmt = "[%s max:%u min:%u mean:%u cnt:%u suc:%u crc-err:%u pw-err:%u],";
int log_buf_len = AWSS_STATIS_BUF_LEN + strlen(AWSS_STATIS_FMT) + 21;
char statis_topic[TOPIC_LEN_MAX] = {0};
char *log_content = NULL;
char id_str[21] = {0};
char *log_buf = NULL;
int len = 0;
int ret;
log_content = os_zalloc(AWSS_STATIS_BUF_LEN + 1);
if (log_content == NULL)
goto STATIS_ERR;
log_buf = os_zalloc(log_buf_len + 1);
if (log_buf == NULL)
goto STATIS_ERR;
if (awss_build_topic(TOPIC_POST_STATIS, statis_topic, TOPIC_LEN_MAX) == NULL) {
awss_err("awss build statis topic fail\n");
goto STATIS_ERR;
}
if (awss_statis_mutex)
HAL_MutexLock(awss_statis_mutex);
if (DROUTE_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "ConnRouter",
DROUTE_TMAX, DROUTE_TMIN, DROUTE_TMEAN, DROUTE_CNT, DROUTE_SUC, 0, 0);
}
#ifdef AWSS_SUPPORT_SMARTCONFIG
if (SM_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Smartconfig",
SM_TMAX, SM_TMIN, SM_TMEAN, SM_CNT, SM_SUC, SM_CRC_ERR, SM_PW_ERR);
}
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
if (WPS_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Smartconfig-wps",
0, 0, 0, WPS_CNT, WPS_SUC, WPS_CRC_ERR, WPS_PW_ERR);
}
#endif
#endif
#ifdef AWSS_SUPPORT_AHA
if (PAP_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Aha",
PAP_TMAX, PAP_TMIN, PAP_TMEAN, PAP_CNT, PAP_SUC, 0, PAP_PW_ERR);
}
#endif
#ifdef AWSS_SUPPORT_ADHA
if (ROUTE_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Adha",
ROUTE_TMAX, ROUTE_TMIN, ROUTE_TMEAN, ROUTE_CNT, ROUTE_SUC, 0, 0);
}
#endif
#ifndef AWSS_DISABLE_ENROLLEE
if (ZC_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Zconfig",
0, 0, 0, ZC_CNT, ZC_SUC, 0, ZC_PW_ERR);
}
#endif
#ifdef AWSS_SUPPORT_DEV_AP
if (DAP_CNT > 0) {
len += HAL_Snprintf(log_buf + len, log_buf_len - len, elem_fmt, "Dev-ap",
DAP_TMAX, DAP_TMIN, DAP_TMEAN, DAP_CNT, DAP_SUC, 0, DAP_PW_ERR);
}
#endif
do {
if (len == 0) /* no need to report log */
break;
log_buf[len - 1] = '\0'; /* remove end of ',' */
HAL_Snprintf(log_content, AWSS_STATIS_BUF_LEN, AWSS_STATIS_FMT, (uint32_t)HAL_UptimeMs(), "AWSS_TRACE",
module == NULL ? "default" : module, awss_statis_trace_id, log_buf);
HAL_Snprintf(id_str, sizeof(id_str), "%u", ++ awss_statis_report_id);
awss_build_packet(AWSS_CMP_PKT_TYPE_REQ, id_str, ILOP_VER, METHOD_LOG_POST, log_content, 0,
log_buf, &log_buf_len);
awss_debug("%s\n", log_buf);
ret = awss_cmp_mqtt_send(statis_topic, log_buf, strlen(log_buf), 0);
awss_info("awss report statis %s\n", ret == 0 ? "success" : "fail");
} while (0);
if (awss_statis_mutex)
HAL_MutexUnlock(awss_statis_mutex);
HAL_Free(log_buf);
HAL_Free(log_content);
return 0;
STATIS_ERR:
if (log_content) HAL_Free(log_content);
if (log_buf) HAL_Free(log_buf);
return -1;
}
void awss_disp_statis()
{
if (awss_statis_mutex)
HAL_MutexLock(awss_statis_mutex);
awss_debug("--------------------------------AWSS STATIS-----------------------------------");
awss_debug("name\t\tmax\tmin\tmean\tcnt\tsuc\tcrc-err\tpasswd-err");
awss_debug("ConnRouter \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
DROUTE_TMAX, DROUTE_TMIN, DROUTE_TMEAN, DROUTE_CNT, DROUTE_SUC, 0, 0);
#ifdef AWSS_SUPPORT_SMARTCONFIG
awss_debug("Smartconfig \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
SM_TMAX, SM_TMIN, SM_TMEAN, SM_CNT, SM_SUC, SM_CRC_ERR, SM_PW_ERR);
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
awss_debug("Smartconfig-wps \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
0, 0, 0, WPS_CNT, WPS_SUC, WPS_CRC_ERR, WPS_PW_ERR);
#endif
#endif
#ifdef AWSS_SUPPORT_AHA
awss_debug("Aha \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
PAP_TMAX, PAP_TMIN, PAP_TMEAN, PAP_CNT, PAP_SUC, 0, PAP_PW_ERR);
#endif
#ifdef AWSS_SUPPORT_ADHA
awss_debug("Adha \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
ROUTE_TMAX, ROUTE_TMIN, ROUTE_TMEAN, ROUTE_CNT, ROUTE_SUC, 0, 0);
#endif
#ifndef AWSS_DISABLE_ENROLLEE
awss_debug("Zconfig \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
0, 0, 0, ZC_CNT, ZC_SUC, 0, ZC_PW_ERR);
#endif
#ifdef AWSS_SUPPORT_DEV_AP
awss_debug("Dev-ap \t%u\t%u\t%u\t%u\t%u\t%u\t%u\t",
DAP_TMAX, DAP_TMIN, DAP_TMEAN, DAP_CNT, DAP_SUC, 0, DAP_PW_ERR);
#endif
awss_debug("------------------------------------------------------------------------------");
if (awss_statis_mutex)
HAL_MutexUnlock(awss_statis_mutex);
}
void awss_clear_statis()
{
if (awss_statis_mutex)
HAL_MutexLock(awss_statis_mutex);
memset(&g_awss_statis, 0, sizeof(g_awss_statis));
awss_statis_trace_id = 0;
awss_statis_report_id = 0;
if (awss_statis_mutex) {
HAL_MutexUnlock(awss_statis_mutex);
HAL_MutexDestroy(awss_statis_mutex);
}
awss_statis_mutex = NULL;
}
void awss_update_statis(int awss_statis_idx, int type)
{
uint32_t time = HAL_UptimeMs();
if (awss_statis_mutex == NULL) {
awss_statis_mutex = HAL_MutexCreate();
if (awss_statis_mutex == NULL) {
awss_debug("a-statis am fail\n");
return;
}
}
HAL_MutexLock(awss_statis_mutex);
if (type == AWSS_STATIS_TYPE_TIME_START)
awss_statis_trace_id ++;
switch (awss_statis_idx) {
case AWSS_STATIS_CONN_ROUTER_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
DROUTE_CNT ++;
DROUTE_START = time;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
DROUTE_SUC ++;
DROUTE_END = time;
time = (uint32_t)(DROUTE_END - DROUTE_START);
if (DROUTE_SUC > 0) {
DROUTE_TMEAN = (DROUTE_TMEAN + time) / (DROUTE_SUC);
} else {
DROUTE_TMEAN = time;
DROUTE_SUC = 1;
}
if (DROUTE_TMIN == 0 || DROUTE_TMIN > time)
DROUTE_TMIN = time;
if (DROUTE_TMAX == 0 || DROUTE_TMAX < time)
DROUTE_TMAX = time;
break;
default:
break;
}
break;
#ifdef AWSS_SUPPORT_SMARTCONFIG
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
case AWSS_STATIS_WPS_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
WPS_CNT ++;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
WPS_SUC ++;
break;
case AWSS_STATIS_TYPE_PASSWD_ERR:
WPS_PW_ERR ++;
break;
case AWSS_STATIS_TYPE_CRC_ERR:
WPS_CRC_ERR ++;
break;
default:
break;
}
break;
#endif
case AWSS_STATIS_SM_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
SM_CNT ++;
SM_START = time;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
SM_SUC ++;
SM_END = time;
time = (uint32_t)(SM_END - SM_START);
if (SM_SUC > 0) {
SM_TMEAN = (SM_TMEAN + time) / (SM_SUC);
} else {
SM_TMEAN = time;
SM_SUC = 1;
}
if (SM_TMIN == 0 || SM_TMIN > time)
SM_TMIN = time;
if (SM_TMAX == 0 || SM_TMAX < time)
SM_TMAX = time;
break;
case AWSS_STATIS_TYPE_PASSWD_ERR:
SM_PW_ERR ++;
break;
case AWSS_STATIS_TYPE_CRC_ERR:
SM_CRC_ERR ++;
break;
default:
break;
}
break;
#endif
#ifdef AWSS_SUPPORT_AHA
case AWSS_STATIS_PAP_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
PAP_CNT ++;
PAP_START = time;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
PAP_SUC ++;
PAP_END = time;
time = (uint32_t)(PAP_END - PAP_START);
if (PAP_SUC > 0) {
PAP_TMEAN = (PAP_TMEAN + time) / (PAP_SUC);
} else {
PAP_TMEAN = time;
PAP_SUC = 1;
}
if (PAP_TMIN == 0 || PAP_TMIN > time)
PAP_TMIN = time;
if (PAP_TMAX == 0 || PAP_TMAX < time)
PAP_TMAX = time;
break;
case AWSS_STATIS_TYPE_PASSWD_ERR:
PAP_PW_ERR ++;
break;
case AWSS_STATIS_TYPE_SCAN_START:
PAP_SSTART = time;
break;
case AWSS_STATIS_TYPE_SCAN_STOP:
PAP_SSTOP = time;
break;
case AWSS_STATIS_TYPE_SWITCHAP:
PAP_SAP ++;
break;
default:
break;
}
break;
#endif
#ifdef AWSS_SUPPORT_DEV_AP
case AWSS_STATIS_DAP_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
DAP_CNT ++;
DAP_START = time;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
DAP_SUC ++;
DAP_END = time;
time = (uint32_t)(DAP_END - DAP_START);
if (DAP_SUC > 0) {
DAP_TMEAN = (DAP_TMEAN + time) / (DAP_SUC);
} else {
DAP_TMEAN = time;
DAP_SUC = 1;
}
if (DAP_TMIN == 0 || DAP_TMIN > time)
DAP_TMIN = time;
if (DAP_TMAX == 0 || DAP_TMAX < time)
DAP_TMAX = time;
break;
case AWSS_STATIS_TYPE_PASSWD_ERR:
DAP_PW_ERR ++;
break;
default:
break;
}
break;
#endif
#ifdef AWSS_SUPPORT_ADHA
case AWSS_STATIS_ROUTE_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
ROUTE_CNT ++;
ROUTE_START = time;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
ROUTE_SUC ++;
ROUTE_END = time;
time = (uint32_t)(ROUTE_END - ROUTE_START);
if (ROUTE_SUC > 0) {
ROUTE_TMEAN = (ROUTE_TMEAN + time) / (ROUTE_SUC);
} else {
ROUTE_TMEAN = time;
ROUTE_SUC = 1;
}
if (ROUTE_TMIN == 0 || ROUTE_TMIN > time)
ROUTE_TMIN = time;
if (ROUTE_TMAX == 0 || ROUTE_TMAX < time)
ROUTE_TMAX = time;
break;
default:
break;
}
break;
#endif
#ifndef AWSS_DISABLE_ENROLLEE
case AWSS_STATIS_ZCONFIG_IDX:
switch (type) {
case AWSS_STATIS_TYPE_TIME_START:
ZC_CNT ++;
break;
case AWSS_STATIS_TYPE_TIME_SUC:
ZC_SUC ++;
break;
case AWSS_STATIS_TYPE_PASSWD_ERR:
ZC_PW_ERR ++;
break;
default:
break;
}
break;
#endif
default:
break;
}
HAL_MutexUnlock(awss_statis_mutex);
}
#endif

View File

@@ -0,0 +1,147 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_STATIS_H__
#define __AWSS_STATIS_H__
#include <stdint.h>
#ifdef AWSS_SUPPORT_DEV_AP
#include "awss_dev_ap.h"
#endif
enum {
AWSS_STATIS_CONN_ROUTER_IDX = 0, /* Statistic for connection with router */
AWSS_STATIS_SM_IDX, /* Statistic for smartconfig with bcast */
AWSS_STATIS_WPS_IDX, /* Statistic for smartconfig with wps */
AWSS_STATIS_PAP_IDX, /* Statistic for phone as AP */
AWSS_STATIS_DAP_IDX, /* Statistic for device AP */
AWSS_STATIS_ROUTE_IDX, /* Statistic for route solution */
AWSS_STATIS_ZCONFIG_IDX, /* Statistic for zero config */
};
enum {
AWSS_STATIS_TYPE_TIME_START = 0, /* Begining of operation */
AWSS_STATIS_TYPE_TIME_SUC, /* Success of operation */
AWSS_STATIS_TYPE_PASSWD_ERR, /* Failure of parsing PASSWD of router*/
AWSS_STATIS_TYPE_CRC_ERR, /* Failure of CRC check */
AWSS_STATIS_TYPE_SCAN_START, /* Start of scan operation */
AWSS_STATIS_TYPE_SCAN_STOP, /* Stop of scan operation */
AWSS_STATIS_TYPE_SWITCHAP /* Increase count of switch ap */
};
#ifndef AWSS_SUPPORT_STATIS
#define AWSS_SUPPORT_STATIS
#endif
#ifdef AWSS_SUPPORT_STATIS
struct awss_statis_conn_router_t {
uint32_t conn_router_cnt; /* the count of connect router */
uint32_t conn_router_suc; /* the success count of connect router */
uint32_t conn_router_time_mean; /* the mean time of success connection with router */
uint32_t conn_router_time_max; /* the max time of success connection with router */
uint32_t conn_router_time_min; /* the min time of success connection with router */
uint32_t conn_router_start; /* the start time to connect router */
uint32_t conn_router_end; /* the end time of connect router */
}; /* statistics for connection with router */
struct awss_statis_sm_t {
uint32_t sm_parse_cnt; /* the count of smartconfig */
uint32_t sm_parse_crc_err; /* the count of crc error */
uint32_t sm_parse_passwd_err; /* the count of passwd error */
uint32_t sm_parse_suc; /* the count of smartconfig success */
uint32_t sm_parse_start; /* the start time to smartconfig */
uint32_t sm_parse_end; /* the ene time of smartconfig */
uint32_t sm_time_mean; /* the mean time of smartconfig */
uint32_t sm_time_max; /* the max time of smartconfig */
uint32_t sm_time_min; /* the min time of smartconfig */
}; /* smartconfig-bcast statistic */
struct awss_statis_wps_t {
uint32_t wps_parse_cnt; /* the count of smartconfig-wps */
uint32_t wps_parse_crc_err; /* the count of crc error */
uint32_t wps_parse_passwd_err; /* the count of passwd error */
uint32_t wps_parse_suc; /* the count of smartconfig-wps success */
}; /* smartconfig-wps statistic */
struct awss_statis_phone_ap_t {
uint32_t aha_cnt;
uint32_t aha_suc;
uint32_t aha_time_mean; /* mean time of phone as AP solution */
uint32_t aha_time_max; /* max time of phone as AP solution */
uint32_t aha_time_min; /* min time of phone as AP solution */
uint32_t aha_start;
uint32_t aha_end;
uint32_t aha_scan_start;
uint32_t aha_scan_end;
uint32_t aha_switch_ap;
uint32_t aha_passwd_err;
}; /* Phone as AP */
struct awss_statis_dev_ap_t {
uint32_t dev_ap_cnt;
uint32_t dev_ap_suc;
uint32_t dev_ap_time_mean; /* mean time of device AP solution */
uint32_t dev_ap_time_max; /* max time of device AP solution */
uint32_t dev_ap_time_min; /* min time of device AP solution */
uint32_t dev_ap_start;
uint32_t dev_ap_end;
uint32_t dev_ap_passwd_err;
}; /* device work as AP */
struct awss_statis_route_t {
uint32_t adha_cnt;
uint32_t adha_suc;
uint32_t adha_time_mean; /* mean time of discovery of route solution */
uint32_t adha_time_max; /* min time of discovery of route solution */
uint32_t adha_time_min; /* max time of discovery of route solution */
uint32_t adha_start;
uint32_t adha_end;
}; /* discovery of route solution */
struct awss_statis_zconfig_t {
uint32_t zc_cnt;
uint32_t zc_suc;
uint32_t zc_passwd_err;
}; /* zero configure solution */
struct awss_statis_t {
struct awss_statis_conn_router_t droute;
#ifdef AWSS_SUPPORT_SMARTCONFIG
struct awss_statis_sm_t sm;
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
struct awss_statis_wps_t wps;
#endif
#endif
#ifdef AWSS_SUPPORT_AHA
struct awss_statis_phone_ap_t pap;
#endif
#ifdef AWSS_SUPPORT_DEV_AP
struct awss_statis_dev_ap_t dap;
#endif
#ifdef AWSS_SUPPORT_ADHA
struct awss_statis_route_t route;
#endif
#ifndef AWSS_DISABLE_ENROLLEE
struct awss_statis_zconfig_t zconfig;
#endif
};
int awss_report_statis(const char *module);
void awss_update_statis(int awss_statis_idx, int type);
void awss_clear_statis();
void awss_disp_statis();
#define AWSS_UPDATE_STATIS(idx, type) awss_update_statis(idx, type)
#define AWSS_CLEAR_STATIS() awss_clear_statis()
#define AWSS_DISP_STATIS() awss_disp_statis()
#define AWSS_REPORT_STATIS(m) awss_disp_statis(m)
#else
#define AWSS_UPDATE_STATIS(idx, type)
#define AWSS_CLEAR_STATIS()
#define AWSS_DISP_STATIS()
#define AWSS_REPORT_STATIS(m)
#endif
#endif

View File

@@ -0,0 +1,118 @@
#include "wifi_provision_internal.h"
#if defined(HAL_CRYPTO)
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include <string.h>
#include <stdlib.h>
#include "infra_compat.h"
#if defined(INFRA_AES)
#include "infra_aes.h"
#endif
#define AES_BLOCK_SIZE 16
#if defined(INFRA_AES)
typedef struct {
infra_aes_context ctx;
uint8_t iv[16];
uint8_t key[16];
} platform_aes_t;
#endif
p_HAL_Aes128_t awss_Aes128_Init(
const uint8_t *key,
const uint8_t *iv)
{
#if defined(INFRA_AES)
int ret = 0;
platform_aes_t *p_aes128 = NULL;
if (!key || !iv) return p_aes128;
p_aes128 = (platform_aes_t *)calloc(1, sizeof(platform_aes_t));
if (!p_aes128) return p_aes128;
infra_aes_init(&p_aes128->ctx);
ret = infra_aes_setkey_dec(&p_aes128->ctx, key, 128);
if (ret == 0) {
memcpy(p_aes128->iv, iv, 16);
memcpy(p_aes128->key, key, 16);
} else {
free(p_aes128);
p_aes128 = NULL;
}
return (p_HAL_Aes128_t *)p_aes128;
#else
return (p_HAL_Aes128_t *)HAL_Aes128_Init(key, iv, HAL_AES_DECRYPTION);
#endif
}
int awss_Aes128_Destroy(p_HAL_Aes128_t aes)
{
#if defined(INFRA_AES)
if (!aes) return -1;
infra_aes_free(&((platform_aes_t *)aes)->ctx);
free(aes);
return 0;
#else
return HAL_Aes128_Destroy(aes);
#endif
}
int awss_Aes128_Cbc_Decrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t blockNum,
void *dst)
{
#if defined(INFRA_AES)
int i = 0;
int ret = -1;
platform_aes_t *p_aes128 = (platform_aes_t *)aes;
if (!aes || !src || !dst) return ret;
for (i = 0; i < blockNum; ++i) {
ret = infra_aes_crypt_cbc(&p_aes128->ctx, INFRA_AES_DECRYPT, AES_BLOCK_SIZE,
p_aes128->iv, src, dst);
src += 16;
dst += 16;
}
return ret;
#else
return HAL_Aes128_Cbc_Decrypt(aes, src, blockNum, dst);
#endif
}
int awss_Aes128_Cfb_Decrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t length,
void *dst)
{
#if defined(INFRA_AES)
size_t offset = 0;
int ret = -1;
platform_aes_t *p_aes128 = (platform_aes_t *)aes;
if (!aes || !src || !dst) return ret;
ret = infra_aes_setkey_enc(&p_aes128->ctx, p_aes128->key, 128);
ret = infra_aes_crypt_cfb128(&p_aes128->ctx, INFRA_AES_DECRYPT, length,
&offset, p_aes128->iv, src, dst);
return ret;
#else
return HAL_Aes128_Cfb_Decrypt(aes, src, length, dst);
#endif
}
#endif /* #if defined(HAL_CRYPTO) */

View File

@@ -0,0 +1,20 @@
#include "wifi_provision_internal.h"
p_HAL_Aes128_t awss_Aes128_Init(
const uint8_t *key,
const uint8_t *iv);
int awss_Aes128_Destroy(p_HAL_Aes128_t aes);
int awss_Aes128_Cbc_Decrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t blockNum,
void *dst);
int awss_Aes128_Cfb_Decrypt(
p_HAL_Aes128_t aes,
const void *src,
size_t length,
void *dst);

View File

@@ -0,0 +1,151 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#include "awss_aes_wrapper.h"
#include "infra_sha256.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#ifndef SHA256_DIGEST_SIZE
#define SHA256_DIGEST_SIZE (32)
#endif
static const char *cal_passwd(void *key, void *random, void *passwd)
{
uint16_t key_len;
uint8_t digest[SHA256_DIGEST_SIZE + 1] = {0};
uint8_t passwd_src[KEY_MAX_LEN + RANDOM_MAX_LEN + 2] = {0};
if (!passwd || !key || !random)
return NULL;
/* combine key and random, with split of comma */
key_len = strlen(key);
if (key_len > KEY_MAX_LEN)
key_len = KEY_MAX_LEN;
memcpy(passwd_src, key, key_len);
passwd_src[key_len ++] = ',';
memcpy(passwd_src + key_len, random, RANDOM_MAX_LEN);
key_len += RANDOM_MAX_LEN;
utils_sha256(passwd_src, key_len, digest);
/* use the first 128bits as AES-Key */
memcpy(passwd, digest, AES128_KEY_LEN);
return passwd;
}
int aes_decrypt_string(char *cipher, char *plain, int len, int cipher_hex, int sec_lvl, char cbc, const char *rand)
{
char res = 0;
char decrypt = 1;
uint8_t iv[AES128_KEY_LEN] = {0};
uint8_t key[AES128_KEY_LEN] = {0};
uint8_t random[RANDOM_MAX_LEN] = {0};
uint8_t *decoded = (uint8_t *)os_zalloc(len + 1);
if (decoded == NULL)
return -1;
if (cipher_hex == 0) {
/*
* mobile-ap, router, dev-ap
*/
utils_str_to_hex(cipher, len, decoded, len);
} else { /* for smartconfig/wps, zconfig, */
/*
* smartconfig/wps, zconfig
*/
memcpy(decoded, cipher, len);
}
if (rand) {
/*
* smartconfig/wps uses zero
* zconfig/dev-ap/mobile-ap/router uses random
*/
memcpy(random, rand, sizeof(random));
}
awss_debug("security level: %d", sec_lvl);
switch (sec_lvl) {
case SEC_LVL_AES128_PRODUCT:
{
char product_sec[OS_PRODUCT_SECRET_LEN + 1] = {0};
HAL_GetProductSecret(product_sec);
cal_passwd(product_sec, random, key);
memcpy(iv, random, sizeof(random));
break;
}
case SEC_LVL_AES128_DEVICE:
{
char dev_sec[OS_DEVICE_SECRET_LEN + 1] = {0};
HAL_GetDeviceSecret(dev_sec);
cal_passwd(dev_sec, random, key);
memcpy(iv, random, sizeof(random));
break;
}
default:
{
decrypt = 0;
awss_debug("wrong security level: %d\n", sec_lvl);
res = -2;
break;
}
}
plain[0] = '\0';
if (decrypt) {
p_aes128_t aes = (p_aes128_t)awss_Aes128_Init(key, iv);
if (cbc) { /* AP */
/*
* mobile-ap, dev-ap, router
*/
res = awss_Aes128_Cbc_Decrypt(aes, decoded, len / AES128_KEY_LEN / 2, plain);
} else { /* smartconfig */
/*
* smartconfig/wps, zconfig
*/
res = awss_Aes128_Cfb_Decrypt(aes, decoded, len, plain);
}
awss_Aes128_Destroy(aes);
}
HAL_Free(decoded);
return res;
}
/**
* @brief 获取配网服务的安全等级
*
* @param None.
* @return The security level:
@verbatim
0: open (no encrypt)
1: aes256cfb with default aes-key and aes-iv
2: aes128cfb with default aes-key and aes-iv
3: aes128cfb with aes-key per product and aes-iv = 0
4: aes128cfb with aes-key per device and aes-iv = 0
5: aes128cfb with aes-key per manufacture and aes-iv = 0
others: invalid
@endverbatim
* @see None.
*/
int awss_get_encrypt_type()
{
return 3;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,20 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_CRYPT_H__
#define __AWSS_CRYPT_H__
enum {
SEC_LVL_OPEN = 0, /* open */
SEC_LVL_AES256, /* AES256 */
SEC_LVL_AES128_DEFAULT, /* AES128 with default key */
SEC_LVL_AES128_PRODUCT, /* AES128 with key from product_sec */
SEC_LVL_AES128_DEVICE, /* AES128 with key from device_sec */
SEC_LVL_AES128_MANU, /* AES128 with key from manufacturer_sec */
};
int aes_decrypt_string(char *cipher, char *plain, int len, int cipher_hex, int sec_lvl, char cbc, const char *rand);
int awss_get_encrypt_type();
#endif

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
void dump_hex(uint8_t *data, int len, int tab_num)
{
int i;
for (i = 0; i < len; i++) {
HAL_Printf("%02x ", data[i]);
if (!((i + 1) % tab_num))
HAL_Printf("\r\n");
}
HAL_Printf("\r\n");
}
#if 0
void dump_ascii(uint8_t *data, int len, int tab_num)
{
int i;
for (i = 0; i < len; i++) {
HAL_Printf("%-2c ", data[i]);
if (!((i + 1) % tab_num))
HAL_Printf(" ");
}
HAL_Printf("\r\n");
}
void dump_mac(uint8_t *src, uint8_t *dst)
{
uint8_t *mac;
mac = src;
HAL_Printf("%02x:%02x:%02x:%02x:%02x:%02x > ",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
mac = dst;
HAL_Printf("%02x:%02x:%02x:%02x:%02x:%02x\r\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
/* elimite compiler warning */
mac = mac;
}
#endif
/* for smartconfig with encrypt */
uint16_t zconfig_checksum_v3(uint8_t *data, uint8_t len)
{
uint8_t i;
uint16_t sum = 0, res;
for (i = 0; i < len; i++)
sum += data[i];
res = sum & (0x3F << 0);
res |= (sum & (0x3F << 6)) << 2;
if (!(res & 0x00FF))
res |= 0x0001;
if (!(res & 0xFF00))
res |= 0x0100;
return res;
}
char is_utf8(const char *ansi_str, int length)
{
int i = 0;
char utf8 = 1;
while (i < length) {
if ((0x80 & ansi_str[i]) == 0) { /* ASCII */
i++;
continue;
} else if ((0xE0 & ansi_str[i]) == 0xC0) { /* 110xxxxx */
if (ansi_str[i + 1] == '\0') {
utf8 = 0;
break;
}
if ((0xC0 & ansi_str[i + 1]) == 0x80) { /* 10xxxxxx */
i += 2;
continue;
} else {
utf8 = 0;
break;
}
} else if ((0xF0 & ansi_str[i]) == 0xE0) { /* 1110xxxx */
if (ansi_str[i + 1] == '\0') {
utf8 = 0;
break;
}
if (ansi_str[i + 2] == '\0') {
utf8 = 0;
break;
}
if (((0xC0 & ansi_str[i + 1]) == 0x80) && ((0xC0 & ansi_str[i + 2]) == 0x80)) { /* 10xxxxxx 10xxxxxx */
i += 3;
continue;
} else {
utf8 = 0;
break;
}
} else {
utf8 = 0;
break;
}
}
return utf8;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __ZCONFIG_UTILS_H__
#define __ZCONFIG_UTILS_H__
#include "os.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
void dump_mac(uint8_t *src, uint8_t *dst);
void dump_hex(uint8_t *data, int len, int tab_num);
void dump_ascii(uint8_t *data, int len, int tab_num);
uint16_t zconfig_checksum_v3(uint8_t *data, uint8_t len);
char is_utf8(const char *ansi_str, int length);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __ZCONFIG_LIB_H__
#define __ZCONFIG_LIB_H__
#include "os.h"
#ifndef ETH_ALEN
#define ETH_ALEN (6)
#endif
#define ZC_MAX_SSID_LEN (32 + 1)/* ssid: 32 octets at most, include the NULL-terminated */
#define ZC_MAX_PASSWD_LEN (64 + 1)/* 8-63 ascii */
#define MAX_APLIST_NUM (100)
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
enum _ZC_AUTH_TYPE_ {
ZC_AUTH_TYPE_OPEN,
ZC_AUTH_TYPE_SHARED,
ZC_AUTH_TYPE_WPAPSK,
ZC_AUTH_TYPE_WPA8021X,
ZC_AUTH_TYPE_WPA2PSK,
ZC_AUTH_TYPE_WPA28021X,
ZC_AUTH_TYPE_WPAPSKWPA2PSK,
ZC_AUTH_TYPE_MAX = ZC_AUTH_TYPE_WPAPSKWPA2PSK,
ZC_AUTH_TYPE_INVALID = 0xff,
};
enum _ZC_ENC_TYPE_ {
ZC_ENC_TYPE_NONE,
ZC_ENC_TYPE_WEP,
ZC_ENC_TYPE_TKIP,
ZC_ENC_TYPE_AES,
ZC_ENC_TYPE_TKIPAES,
ZC_ENC_TYPE_MAX = ZC_ENC_TYPE_TKIPAES,
ZC_ENC_TYPE_INVALID = 0xff,
};
enum _ZC_PKG_TYPE_ {
PKG_INVALID, /* invalid pkg, --无效包 */
PKG_BC_FRAME, /* broadcast frame, --信道扫描阶段收到收到该返回值建议延长在当前信道停留时间可以延长T1 */
PKG_START_FRAME, /* start frame, --信道扫描阶段,收到该返回值用于锁定信道 */
PKG_DATA_FRAME, /* data frame, --数据包锁定信道后长时间T2收不到数据包需重新进入扫描阶段 */
PKG_ALINK_ROUTER, /* alink router */
PKG_GROUP_FRAME, /* group frame */
PKG_END /* --配网结束事件已拿到ssid和passwd通过回调函数去获取ssid和passwd */
/*
* 参考值:
* T1: 400ms >= T2 >= 100ms
* T2: 3s
*/
};
/*进入monitor模式前后调用该函数 */
void zconfig_init();
/* 配网成功后,调用该函数,释放内存资源 */
void zconfig_destroy(void);
/*
进入monitor/sniffer模式后将收到的包传给该函数进行处理
若进入monitor时进行包过滤配置以下几种包不能过滤
1) 数据包,目的地址为广播地址
2) 长度>40的管理帧
厂家需要自行切换信道,切信道时间按照自身平台需要进行调整,建议取值范围[100ms - 300ms]
其中6号信道需作为固定信道放在信道列表里
input:
pkt_data: 80211 wireless raw package, include data frame & management frame
pkt_length: radio_hdr + 80211 hdr + payload, without fcs(4B)
return:
见enum _PKG_TYPE_结构体说明
*/
int zconfig_recv_callback(void *pkt_data, uint32_t pkt_length, uint8_t channel,
int link_type, int with_fcs, signed char rssi);
/*
* save apinfo
* 0 -- success, otherwise, failed.
*/
int zconfig_set_apinfo(uint8_t *ssid, uint8_t* bssid, uint8_t channel, uint8_t auth,
uint8_t pairwise_cipher, uint8_t group_cipher, signed char rssi);
uint8_t zconfig_get_lock_chn(void);
/* add channel to global scanning channel list */
int zconfig_add_active_channel(int channel);
/* channel locked callback */
void zconfig_channel_locked_callback(uint8_t primary_channel,
uint8_t secondary_channel, uint8_t *bssid);
/* got ssid&passwd callback */
void zconfig_got_ssid_passwd_callback(uint8_t *ssid, uint8_t *passwd, uint8_t *bssid,
uint8_t auth, uint8_t encry, uint8_t channel);
void zconfig_force_rescan(void);
void aws_set_dst_chan(int channel);
void aws_switch_channel(void);
void aws_release_mutex(void);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,341 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG)
/* broadcast mac address */
uint8_t br_mac[ETH_ALEN];
/* all zero mac address */
uint8_t zero_mac[ETH_ALEN];
/* which channel lock at */
uint8_t zconfig_channel_locked = INVALID_CHANNEL;/* locked channel */
/*
* avoid zconfig_callback_over() was called twice,
* once from tods, once from fromds
*/
uint8_t zconfig_finished;
/* global data structure, which hold all broadcast data */
struct zconfig_data *zconfig_data;
/*
* 8bit -> x bit
*
* serialize chinese char from 8bit to x bit
*/
void encode_chinese(uint8_t *in, uint8_t in_len,
uint8_t *out, uint8_t *out_len, uint8_t bits)
{
if (bits == 0 || bits > 7) {
return;
}
do {
uint8_t i, j;
uint8_t bit[ZC_MAX_SSID_LEN * 8] = {0};
uint8_t output_len = ((in_len * 8) + bits - 1) / bits;
/* char to bit stream */
for (i = 0; i < in_len; i ++) {
for (j = 0; j < 8; j ++) {
bit[i * 8 + j] = (in[i] >> j) & 0x01;
}
}
out[output_len] = '\0'; /* NULL-terminated */
for (i = 0; i < output_len; i ++) {
for (j = 0, out[i] = 0; j < bits; j ++) {
out[i] |= bit[i * bits + j] << j;
}
}
if (out_len) {
*out_len = output_len;
}
} while (0);
}
/* x bit -> 8bit */
void decode_chinese(uint8_t *in, uint8_t in_len,
uint8_t *out, uint8_t *out_len, uint8_t bits)
{
if (bits == 0 || bits > 7 || in_len == 0) {
return;
}
do {
uint8_t i, j;
uint8_t output_len = (in_len * bits) / 8;
uint8_t *bit = (uint8_t *)os_zalloc(in_len * bits);
if (bit == NULL) {
awss_crit("decode malloc failed!\r\n");
return;
}
/* char to bit stream */
for (i = 0; i < in_len; i ++) {
for (j = 0; j < bits; j ++) {
bit[i * bits + j] = (in[i] >> j) & 0x01;
}
}
out[output_len] = '\0'; /* NULL-terminated */
for (i = 0; i < output_len; i++) {
for (j = 0, out[i] = 0; j < 8; j ++) {
out[i] |= bit[i * 8 + j] << j;
}
}
HAL_Free(bit);
if (out_len) {
*out_len = output_len;
}
} while (0);
}
/*
* 1/locked, 0/not locked
*/
uint8_t is_channel_locked(void)
{
return zconfig_channel_locked != INVALID_CHANNEL;
}
/*
* Note: this notification will be kept called, in case of
* user clear the channel locked state to re-scanning
* channel because of waiting timeout.
*/
uint8_t zconfig_callback_channel_locked(uint8_t channel)
{
if (channel != zconfig_channel_locked) {
awss_info("channel lock @ %d\r\n", channel);
zconfig_channel_locked = channel;
}
/*
* if recv timeout, vendor may re-scanning channel,
* so keep calling channel locked notification here.
*/
zconfig_channel_locked_callback(channel, 0, zc_bssid);
return 0;
}
uint8_t zconfig_callback_over(uint8_t *ssid, uint8_t *passwd, uint8_t *bssid)
{
uint8_t auth = ZC_AUTH_TYPE_INVALID, encry = ZC_ENC_TYPE_INVALID, channel = 0;
awss_info("zconfig done. ssid:%s, mac:%02x%02x%02x%02x%02x%02x\r\n",
ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
if (zconfig_finished) {
return 0;
}
#ifdef AWSS_SUPPORT_APLIST
awss_get_auth_info(ssid, bssid, &auth, &encry, &channel);
#endif
zconfig_got_ssid_passwd_callback(ssid, passwd, bssid, auth, encry, channel);
zconfig_finished = 1;
HAL_Awss_Close_Monitor();
return 0;
}
void zconfig_set_state(uint8_t state, uint8_t tods, uint8_t channel)
{
/* state change callback */
switch (state) {
case STATE_CHN_SCANNING:
break;
case STATE_CHN_LOCKED_BY_P2P:
/* locked state used by action/wps frame */
zconfig_callback_channel_locked(channel);
break;
case STATE_CHN_LOCKED_BY_BR:
/* locked state used by br frame */
zconfig_callback_channel_locked(zc_channel ? zc_channel : channel);
break;
case STATE_RCV_DONE:
/* prevent main_thread_func to free zconfig_data until curent task is finished. */
HAL_MutexLock(zc_mutex);
/*
* in case of p2p/router, direct into RCV_DONE state,
* skiped the chn lock state, so better to call channel lock here
*/
if (!is_channel_locked()) {
zconfig_callback_channel_locked(channel);
}
zconfig_callback_over(zc_ssid, zc_passwd, zc_bssid);
break;
default:
break;
}
/*
* state machine loop:
* scanning -> p2p lock -> rcv_done
* scanning -> (p2p) rcv_done
* scanning -> br lock -> (br) rcv_done
* scanning -> br lock -> (p2p) recv_done
* scanning -> p2p lock -> br lock -> (br) recv_done
*
* watch out zc_state rolling back.
* zconfig_set_state(CHN_LOCKED) will be called more than once,
*/
if (zc_state < state) {
zc_state = state;
}
if (state == STATE_RCV_DONE) {
HAL_MutexUnlock(zc_mutex);
}
}
/*
pkt_data & pkt_length:
radio_hdr + 80211 hdr + payload, without fcs(4B)
return:
PKG_INVALID -- invalid pkt,
PKG_START_FRAME -- start frame,
PKG_DATA_FRAME -- data frame,
PKG_ALINK_ROUTER -- alink router,
PKG_GROUP_FRAME -- group frame,
PKG_BC_FRAME -- broadcast frame
*/
int is_invalid_pkg(void *pkt_data, uint32_t pkt_length)
{
#define MIN_PKG (33)
#define MAX_PKG (1480 + 56 + 200)
if (pkt_length < MIN_PKG || pkt_length > MAX_PKG) {
return 1;
}
return 0;
}
/*
* zconfig_recv_callback()
*
* ieee80211 package parser
*
* @Return:
* zconfig state
*/
int zconfig_recv_callback(void *pkt_data, uint32_t pkt_length, uint8_t channel,
int link_type, int with_fcs, signed char rssi)
{
int pkt_type = PKG_INVALID;
struct parser_res res;
memset(&res, 0, sizeof(res));
/* remove FCS filed */
if (with_fcs) {
pkt_length -= 4;
}
/* useless, will be removed */
if (is_invalid_pkg(pkt_data, pkt_length)) {
return PKG_INVALID;
}
res.channel = channel;
pkt_type = ieee80211_data_extract(pkt_data, pkt_length, link_type, &res, rssi);
return pkt_type;
}
/* init mem & timer */
void zconfig_init()
{
awss_info("%s\r\n", __func__);
zconfig_channel_locked = INVALID_CHANNEL;
zconfig_finished = 0;
memset(br_mac, 0xff, ETH_ALEN);
memset(zero_mac, 0x00, ETH_ALEN);
zconfig_data = (struct zconfig_data *)os_zalloc(sizeof(struct zconfig_data));
if (zconfig_data == NULL) {
goto ZCONFIG_INIT_FAIL;
}
zc_mutex = HAL_MutexCreate();
if (zc_mutex == NULL) {
goto ZCONFIG_INIT_FAIL;
}
#ifdef AWSS_SUPPORT_APLIST
if (awss_init_ieee80211_aplist()) {
goto ZCONFIG_INIT_FAIL;
}
#endif
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
if (awss_init_adha_aplist()) {
goto ZCONFIG_INIT_FAIL;
}
#endif
#ifdef AWSS_SUPPORT_HT40
ht40_init();
#endif
return;
ZCONFIG_INIT_FAIL:
awss_crit("malloc failed!\r\n");
zconfig_destroy();
#ifdef AWSS_SUPPORT_APLIST
awss_deinit_ieee80211_aplist();
#endif
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
awss_deinit_adha_aplist();
#endif
return;
}
void zconfig_destroy(void)
{
if (zconfig_data) {
if (zc_mutex) {
HAL_MutexDestroy(zc_mutex);
}
HAL_Free((void *)zconfig_data);
zconfig_data = NULL;
}
}
void zconfig_force_destroy(void)
{
zconfig_destroy();
#ifdef AWSS_SUPPORT_APLIST
awss_deinit_ieee80211_aplist();
awss_close_aplist_monitor();
#endif
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
awss_deinit_adha_aplist();
#endif
}
int zconfig_is_valid_channel(int channel)
{
return (ZC_MIN_CHANNEL <= channel && channel <= ZC_MAX_CHANNEL);
}
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __ZCONFIG_PROTOCOL_H__
#define __ZCONFIG_PROTOCOL_H__
#include <stdint.h>
#include "zconfig_utils.h"
#include "zconfig_ieee80211.h"
#include "zconfig_lib.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
enum state_machine {
STATE_CHN_SCANNING,
STATE_CHN_LOCKED_BY_P2P, /* wps/action used for enrollee */
STATE_CHN_LOCKED_BY_BR, /* broadcast used for smartconfig */
STATE_GOT_BEACON,
STATE_RCV_IN_PROGRESS,
STATE_RCV_COMPLETE,
STATE_RCV_DONE
};
enum _GOT_RESULT_ {
GOT_NOTHING = 0,
GOT_CHN_LOCK = 1,
GOT_SSID_PASSWD = 2,
};
#define PASSWD_ENCRYPT_BIT_OFFSET (1)
#define PASSWD_ENCRYPT_MASK (0x06)
#define SSID_EXIST_BIT (0)
#define SSID_EXIST_MASK (1 << SSID_EXIST_BIT)
#define SSID_ENCODE_BIT (5)
#define SSID_ENCODE_MASK (1 << SSID_ENCODE_BIT)
enum passwd_encpyt_type {
PASSWD_ENCRYPT_OPEN = 0,
PASSWD_ENCRYPT_CIPHER,
PASSWD_ENCRYPT_AESCFB,
PASSWD_ENCRYPT_AESOFB,
};
#define flag_tods(tods) ((tods) ? 'T' : 'F')
#define ZC_MAX_CHANNEL (14)
#define ZC_MIN_CHANNEL (1)
int zconfig_is_valid_channel(int channel);
#define P2P_ENCODE_TYPE_OFFSET (0x05)
#define P2P_SSID_LEN_MASK ((1 << P2P_ENCODE_TYPE_OFFSET) - 1)
#define P2P_ENCRYPT_BIT_MASK ((uint8_t)(~P2P_SSID_LEN_MASK))
enum p2p_encode_type {
P2P_ENCODE_TYPE_DICT = 0x00,
P2P_ENCODE_TYPE_ENCRYPT,
};
/* global data */
/* max: 48(ssid gbk encode) + 64 (passwd) + 6 (1(tlen) + 1(flag) + 1(ssid_len) + 1(passwd_len) + 2(crc)) */
#define MAX_PKG_NUMS (128)
/* zconfig protocol */
#define START_FRAME (0x4E0) /* 0x4E0 is group 0 */
#define GROUP_FRAME (0x3E0) /* exclusive, 0x401 is group 1, 0x400 is not used */
#define GROUP_FRAME_END (GROUP_FRAME + MAX_PKG_NUMS / GROUP_NUMBER) /* exclusive */
#define GROUP_NUMBER (8)
#define ZC_GRP_PKT_IDX_START (2)
#define ZC_GRP_PKT_IDX_END (ZC_GRP_PKT_IDX_START + GROUP_NUMBER - 1)
struct package {
uint16_t len;
char score;
};
struct zconfig_data {
struct {
uint8_t state_machine; /* state for tods/fromds */
uint8_t frame_offset; /* frame fixed offset */
uint8_t group_pos; /* latest group pkg pos */
uint8_t cur_pos; /* data abs. position */
uint8_t max_pos; /* data max len */
uint8_t last_index;
uint8_t replace; /* whether pkg has been replaced recently */
uint8_t score_uplimit;
#define score_max (100)
#define score_high (98)
#define score_mid (50)
#define score_low (1)
#define score_min (0)
uint8_t pos_unsync;
uint16_t group_sn; /* latest group pkg sn */
uint16_t prev_sn; /* last sn */
uint16_t last_len; /* len pkg len */
uint32_t timestamp; /* last timestamp */
#define time_interval (300) /* ms */
} data[2];
/* package store */
struct package pkg[2][MAX_PKG_NUMS];
struct package tmp_pkg[2][GROUP_NUMBER + 1];
uint8_t src_mac[ETH_ALEN];
uint8_t channel; /* from 1 -- 13 */
/* result, final result */
uint8_t ssid[ZC_MAX_SSID_LEN];
uint8_t passwd[ZC_MAX_PASSWD_LEN];
uint8_t bssid[ETH_ALEN];
uint8_t ssid_is_gbk;
uint8_t ssid_auto_complete_disable;
/* used by v2 android p2p protocol, for gbk ssid correctness */
uint8_t android_pre_ssid[ZC_MAX_SSID_LEN];
uint8_t android_ssid[ZC_MAX_SSID_LEN];
uint8_t android_bssid[ETH_ALEN];
uint8_t android_src[ETH_ALEN];
void *mutex;
};
#define zc_state zconfig_data->data[tods].state_machine
#define zc_frame_offset zconfig_data->data[tods].frame_offset
#define zc_group_pos zconfig_data->data[tods].group_pos
#define zc_group_sn zconfig_data->data[tods].group_sn
#define zc_prev_sn zconfig_data->data[tods].prev_sn
#define zc_cur_pos zconfig_data->data[tods].cur_pos
#define zc_max_pos zconfig_data->data[tods].max_pos
#define zc_last_index zconfig_data->data[tods].last_index
#define zc_last_len zconfig_data->data[tods].last_len
#define zc_replace zconfig_data->data[tods].replace
#define zc_score_uplimit zconfig_data->data[tods].score_uplimit
#define zc_timestamp zconfig_data->data[tods].timestamp
#define zc_pos_unsync zconfig_data->data[tods].pos_unsync
#define zc_src_mac &zconfig_data->src_mac[0]
#define zc_channel zconfig_data->channel
#define zc_ssid (&zconfig_data->ssid[0])
#define zc_passwd (&zconfig_data->passwd[0])
#define zc_bssid (&zconfig_data->bssid[0])
#define zc_ssid_is_gbk (zconfig_data->ssid_is_gbk)
#define zc_ssid_auto_complete_disable (zconfig_data->ssid_auto_complete_disable)
#define pkg_score(n) zconfig_data->pkg[tods][n].score
#define pkg_len(n) zconfig_data->pkg[tods][n].len
#define pkg(n) &zconfig_data->pkg[tods][n]
#define tmp_score(n) zconfig_data->tmp_pkg[tods][n].score
#define tmp_len(n) zconfig_data->tmp_pkg[tods][n].len
#define tmp(n) &zconfig_data->tmp_pkg[tods][n]
#define zc_pre_ssid (&zconfig_data->android_pre_ssid[0])
#define zc_android_ssid (&zconfig_data->android_ssid[0])
#define zc_android_bssid (&zconfig_data->android_bssid[0])
#define zc_android_src (&zconfig_data->android_src[0])
#define zc_mutex zconfig_data->mutex
void zconfig_force_destroy(void);
void encode_chinese(uint8_t *in, uint8_t in_len, uint8_t *out, uint8_t *out_len, uint8_t bits);
void decode_chinese(uint8_t *in, uint8_t in_len, uint8_t *out, uint8_t *out_len, uint8_t bits);
void zconfig_set_state(uint8_t state, uint8_t tods, uint8_t channel);
int is_ascii_string(uint8_t *str);
/*
* [IN] ssid or bssid
* [OUT] auth, encry, channel
*/
uint8_t zconfig_get_auth_info(uint8_t *ssid, uint8_t *bssid, uint8_t *auth, uint8_t *encry, uint8_t *channel);
uint8_t zconfig_callback_over(uint8_t *ssid, uint8_t *passwd, uint8_t *bssid);
#define MAC_FORMAT "%02x%02x%02x%02x%02x%02x"
#define MAC_VALUE(mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
extern const char *zc_default_ssid;
extern const char *zc_default_passwd;
extern struct zconfig_data *zconfig_data;
extern uint8_t zconfig_finished;
/* broadcast mac address */
extern uint8_t br_mac[ETH_ALEN];
/* all zero mac address */
extern uint8_t zero_mac[ETH_ALEN];
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif /* __IEEE80211_123_H */

View File

@@ -0,0 +1,577 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
#if defined(AWSS_SUPPORT_SMARTCONFIG) || defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_SMARTCONFIG_WPS) || defined(AWSS_SUPPORT_SMARTCONFIG_MCAST) || defined(AWSS_SUPPORT_ZEROCONFIG)
/* aws state machine */
enum {
/* used by aws_state */
AWS_SCANNING,
AWS_CHN_LOCKED,
AWS_SUCCESS,
AWS_TIMEOUT,
/* used by aws_stop */
AWS_STOPPING,
AWS_STOPPED
};
struct aws_info {
uint8_t state;
uint8_t cur_chn; /* current working channel */
uint8_t chn_index;
uint8_t locked_chn;
#define AWS_MAX_CHN_NUMS (2 * 13 + 5) /* +5 for safety gap */
uint8_t chn_list[AWS_MAX_CHN_NUMS];
uint8_t stop;
uint32_t chn_timestamp;/* channel start time */
uint32_t start_timestamp;/* aws start time */
} *aws_info;
#define aws_state (aws_info->state)
#define aws_locked_chn (aws_info->locked_chn)
#define aws_cur_chn (aws_info->cur_chn)
#define aws_chn_index (aws_info->chn_index)
#define aws_chn_list (aws_info->chn_list)
#define aws_chn_timestamp (aws_info->chn_timestamp)
#define aws_start_timestamp (aws_info->start_timestamp)
#define aws_stop (aws_info->stop)
#define aws_channel_lock_timeout_ms (8 * 1000)
static const uint8_t aws_fixed_scanning_channels[] = {
1, 6, 11, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
};
static void *rescan_timer = NULL;
static void rescan_monitor(void);
#define RESCAN_MONITOR_TIMEOUT_MS (5 * 60 * 1000)
static uint8_t rescan_available = 0;
/*
* sniffer result/storage
* use global variable/buffer to keep it usable after zconfig_destroy
*/
uint8_t aws_result_ssid[ZC_MAX_SSID_LEN + 1];
uint8_t aws_result_passwd[ZC_MAX_PASSWD_LEN + 1];
uint8_t aws_result_bssid[ETH_ALEN];/* mac addr */
uint8_t aws_result_channel = 0;
uint8_t aws_result_encry;
uint8_t aws_result_auth;
int aws_80211_frame_handler(char *, int, enum AWSS_LINK_TYPE, int, signed char);
uint8_t zconfig_get_lock_chn(void)
{
return aws_locked_chn;
}
void zconfig_force_rescan(void)
{
if (aws_info) {
aws_state = AWS_SCANNING;
}
}
void zconfig_channel_locked_callback(uint8_t primary_channel,
uint8_t secondary_channel, uint8_t *bssid)
{
aws_locked_chn = primary_channel;
if (aws_state == AWS_SCANNING) {
aws_state = AWS_CHN_LOCKED;
}
awss_event_post(IOTX_AWSS_LOCK_CHAN);
}
void zconfig_got_ssid_passwd_callback(uint8_t *ssid, uint8_t *passwd,
uint8_t *bssid, uint8_t auth, uint8_t encry, uint8_t channel)
{
if (bssid) {
awss_debug("ssid:%s, bssid:%02x%02x%02x%02x%02x%02x, %d\r\n",
ssid, bssid[0], bssid[1], bssid[2],
bssid[3], bssid[4], bssid[5], channel);
} else {
awss_debug("ssid:%s, bssid:--, %d\r\n",
ssid, channel);
}
memset(aws_result_ssid, 0, sizeof(aws_result_ssid));
memset(aws_result_passwd, 0, sizeof(aws_result_passwd));
strncpy((char *)aws_result_ssid, (const char *)ssid, ZC_MAX_SSID_LEN - 1);
strncpy((char *)aws_result_passwd, (const char *)passwd, ZC_MAX_PASSWD_LEN - 1);
if (bssid) {
memcpy(aws_result_bssid, bssid, ETH_ALEN);
}
aws_result_auth = auth;
aws_result_encry = encry;
aws_result_channel = channel;
aws_state = AWS_SUCCESS;
awss_event_post(IOTX_AWSS_GOT_SSID_PASSWD);
}
uint8_t aws_next_channel(void)
{
/* aws_chn_index start from -1 */
while (1) {
aws_chn_index ++;
if (aws_chn_index >= AWS_MAX_CHN_NUMS) {
aws_chn_index = 0; /* rollback to start */
}
if (aws_chn_list[aws_chn_index]) { /* valid channel */
break;
}
}
aws_cur_chn = aws_chn_list[aws_chn_index];
return aws_cur_chn;
}
static void aws_switch_dst_chan(int channel);
static int aws_amend_dst_chan = 0;
void aws_switch_channel(void)
{
HAL_MutexLock(zc_mutex);
if (aws_amend_dst_chan != 0) {
aws_switch_dst_chan(aws_amend_dst_chan);
aws_amend_dst_chan = 0;
HAL_MutexUnlock(zc_mutex);
return;
}
if (aws_state == AWS_CHN_LOCKED) {
HAL_MutexUnlock(zc_mutex);
return;
}
do {
int channel = aws_next_channel();
aws_chn_timestamp = os_get_time_ms();
HAL_Awss_Switch_Channel(channel, 0, NULL);
awss_trace("chan %d\r\n", channel);
} while (0);
HAL_MutexUnlock(zc_mutex);
}
void aws_set_dst_chan(int channel)
{
HAL_MutexLock(zc_mutex);
aws_amend_dst_chan = channel;
HAL_MutexUnlock(zc_mutex);
}
static void aws_switch_dst_chan(int channel)
{
int i = aws_chn_index;
for (; i < AWS_MAX_CHN_NUMS; i ++) {
if (aws_chn_list[i] == 0) {
continue;
}
if (aws_chn_list[i] == channel) {
break;
}
}
if (i >= AWS_MAX_CHN_NUMS) {
for (i = 0; i < aws_chn_index; i ++) {
if (aws_chn_list[i] == 0) {
continue;
}
if (aws_chn_list[i] == channel) {
break;
}
}
}
if (i == aws_chn_index) { /* no need to switch channel. */
return;
}
aws_chn_index = i;
aws_locked_chn = channel;
aws_cur_chn = channel;
aws_chn_timestamp = os_get_time_ms();
if (aws_state == AWS_SCANNING) {
aws_state = AWS_CHN_LOCKED;
}
HAL_Awss_Switch_Channel(channel, 0, NULL);
awss_trace("adjust chan %d\r\n", channel);
}
enum {
CHNSCAN_ONGOING, /* no timeout, continue */
CHNSCAN_NEXT_CHN, /* should swith to next channel */
CHNSCAN_TIMEOUT /* aws timeout */
};
int aws_is_chnscan_timeout(void)
{
if (aws_stop == AWS_STOPPING) {
awss_debug("aws will stop...\r\n");
return CHNSCAN_TIMEOUT;
}
if (time_elapsed_ms_since(aws_chn_timestamp) > HAL_Awss_Get_Channelscan_Interval_Ms()) {
if ((0 != HAL_Awss_Get_Timeout_Interval_Ms()) &&
(time_elapsed_ms_since(aws_start_timestamp) > HAL_Awss_Get_Timeout_Interval_Ms())) {
return CHNSCAN_TIMEOUT;
} else {
return CHNSCAN_NEXT_CHN;
}
}
return CHNSCAN_ONGOING;
}
int zconfig_add_active_channel(int channel)
{
int fixed_channel_nums = sizeof(aws_fixed_scanning_channels);
if (!zconfig_is_valid_channel(channel)) {
return -1;
}
aws_chn_list[fixed_channel_nums + channel] = channel;
return 0;
}
/*
* channel scanning/re-scanning control
* Note: 修改该函数时,需考虑到各平台差异
* 庆科平台:
* --aws_switch_channel() 为空
* --zconfig_destroy()会被调用两次一次被aws_main_thread_fun(),一次被庆科驱动
* linux/rtos平台差异
* --vendor_recv_80211_frame()有实现rtos平台该函数通常为空通过注册callback方式收包
*/
void aws_main_thread_func(void)
{
int interval = 0;
aws_start_timestamp = os_get_time_ms();
/* channel switch init */
aws_switch_channel();
rescanning:
/* start scaning channel */
memset(zc_bssid, 0, ETH_ALEN);
while (aws_amend_dst_chan != 0 || aws_state == AWS_SCANNING) {
switch (aws_is_chnscan_timeout()) {
case CHNSCAN_ONGOING:
break;
case CHNSCAN_NEXT_CHN:
aws_switch_channel();
break;
case CHNSCAN_TIMEOUT:
goto timeout_scanning;
default:
break;
}
if (aws_stop == AWS_STOPPING) { /* interrupt by user */
goto timeout_scanning;
}
if (aws_state != AWS_SCANNING) { /* channel is locked, don't need to tx probe req */
break;
}
interval = (HAL_Awss_Get_Channelscan_Interval_Ms() + 2) / 3;
if (interval < 1) {
interval = 1;
}
/* 80211 frame handled by callback */
HAL_SleepMs(interval);
#ifndef AWSS_DISABLE_ENROLLEE
awss_broadcast_enrollee_info();
#endif
HAL_SleepMs(interval);
#ifdef AWSS_SUPPORT_ADHA
aws_send_adha_probe_req();
#endif
HAL_SleepMs(interval);
#ifdef AWSS_SUPPORT_AHA
aws_send_aha_probe_req();
#endif
}
/* channel lock */
awss_debug("[channel scanning] %d ms\r\n",
time_elapsed_ms_since(aws_start_timestamp));
/*
* make sure switch to locked channel,
* in case of inconsistent with aws_cur_chn
*/
#ifdef AWSS_SUPPORT_APLIST
aws_try_adjust_chan();
#endif
awss_debug("final channel %d\r\n", aws_locked_chn);
while (aws_state != AWS_SUCCESS) {
/* 80211 frame handled by callback */
HAL_SleepMs(300);
if (aws_stop == AWS_STOPPING) {
goto timeout_recving;
}
#ifdef AWSS_SUPPORT_APLIST
aws_try_adjust_chan();
#endif
if (aws_is_chnscan_timeout() == CHNSCAN_TIMEOUT) {
goto timeout_recving;
}
if (aws_state == AWS_SCANNING) {
awss_debug("channel rescanning...\n");
if (zconfig_data != NULL) {
void *tmp_mutex = zc_mutex;
memset(zconfig_data, 0, sizeof(struct zconfig_data));
zc_mutex = tmp_mutex;
}
goto rescanning;
}
}
awss_debug("[channel recving] %d ms\r\n",
time_elapsed_ms_since(aws_start_timestamp));
goto success;
timeout_scanning:
awss_debug("aws timeout scanning!\r\n");
timeout_recving:
awss_debug("aws timeout recving!\r\n");
do {
if (aws_stop == AWS_STOPPING) {
break;
}
if (rescan_timer == NULL) {
rescan_timer = HAL_Timer_Create("rescan", (void(*)(void *))rescan_monitor, NULL);
}
HAL_Timer_Stop(rescan_timer);
HAL_Timer_Start(rescan_timer, RESCAN_MONITOR_TIMEOUT_MS);
HAL_Awss_Close_Monitor();
while (rescan_available == 0) {
if (awss_get_config_press() ||
aws_stop == AWS_STOPPING) { /* user interrupt sleep */
HAL_Timer_Stop(rescan_timer);
break;
}
HAL_SleepMs(200);
}
rescan_available = 0;
} while (0);
if (aws_stop == AWS_STOPPING) { /* interrupt by user */
aws_stop = AWS_STOPPED;
goto success;
}
aws_state = AWS_SCANNING;
#ifdef AWSS_SUPPORT_APLIST
if (awss_is_ready_clr_aplist()) {
awss_clear_aplist();
}
#endif
aws_start_timestamp = os_get_time_ms();
HAL_Awss_Open_Monitor(aws_80211_frame_handler);
goto rescanning;
success:
awss_stop_timer(rescan_timer);
rescan_timer = NULL;
/* don't destroy zconfig_data until monitor_cb is finished. */
HAL_MutexLock(zc_mutex);
HAL_MutexUnlock(zc_mutex);
/*
* zconfig_destroy() after os_awss_monitor_close() beacause
* zconfig_destroy will release mem/buffer that
* zconfig_recv_callback will use
*
* Note: hiflying will reboot after calling this func, so
* aws_get_ssid_passwd() was called in os_awss_monitor_close()
*/
if (aws_stop == AWS_STOPPED) {
zconfig_force_destroy();
}
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
else if (strcmp((const char *)aws_result_ssid, (const char *)zc_adha_ssid) == 0 ||
strcmp((const char *)aws_result_ssid, (const char *)zc_default_ssid) == 0) {
zconfig_destroy();
}
#endif
else {
zconfig_force_destroy();
}
}
static void rescan_monitor(void)
{
rescan_available = 1;
}
int aws_80211_frame_handler(char *buf, int length, enum AWSS_LINK_TYPE link_type, int with_fcs, signed char rssi)
{
static uint32_t lock_start;
int ret = zconfig_recv_callback(buf, length, aws_cur_chn, link_type, with_fcs, rssi);
if (aws_state == AWS_CHN_LOCKED) {
switch (ret) {
case PKG_START_FRAME:
case PKG_DATA_FRAME:
case PKG_GROUP_FRAME:
lock_start = os_get_time_ms();
break;
default:
/* set to rescanning */
if (time_elapsed_ms_since(lock_start) > aws_channel_lock_timeout_ms) {
aws_state = AWS_SCANNING;
}
break;
}
}
return ret;
}
void aws_start(char *pk, char *dn, char *ds, char *ps)
{
aws_info = os_zalloc(sizeof(struct aws_info));
if (!aws_info) {
return;
}
aws_state = AWS_SCANNING;
/* start from -1 */
aws_chn_index = 0xff;
memcpy(aws_chn_list, aws_fixed_scanning_channels,
sizeof(aws_fixed_scanning_channels));
memset(aws_result_ssid, 0, sizeof(aws_result_ssid));
memset(aws_result_passwd, 0, sizeof(aws_result_passwd));
memset(aws_result_bssid, 0, sizeof(aws_result_bssid));
aws_result_auth = ZC_AUTH_TYPE_INVALID;
aws_result_encry = ZC_ENC_TYPE_INVALID;
aws_result_channel = 0;
zconfig_init();
#ifdef AWSS_SUPPORT_APLIST
awss_open_aplist_monitor();
#endif
HAL_Awss_Open_Monitor(aws_80211_frame_handler);
#ifndef AWSS_DISABLE_ENROLLEE
awss_init_enrollee_info();
#endif
aws_main_thread_func();
}
static void *aws_mutex = NULL;
void aws_destroy(void)
{
if (aws_mutex == NULL) {
aws_mutex = HAL_MutexCreate();
}
if (aws_mutex) {
HAL_MutexLock(aws_mutex);
}
if (aws_info == NULL) {
return;
}
if (aws_stop == AWS_STOPPED) {
return;
}
aws_stop = AWS_STOPPING;
HAL_Awss_Close_Monitor();
while (aws_stop != AWS_STOPPED) {
if (aws_state == AWS_SUCCESS) {
break;
}
HAL_MutexUnlock(aws_mutex);
HAL_SleepMs(100);
HAL_MutexLock(aws_mutex);
}
if (NULL != aws_info) {
HAL_Free(aws_info);
}
aws_info = NULL;
#ifndef AWSS_DISABLE_ENROLLEE
awss_destroy_enrollee_info();
#endif
if (aws_mutex) {
HAL_MutexUnlock(aws_mutex);
}
}
void aws_release_mutex()
{
if (aws_mutex) {
HAL_MutexDestroy(aws_mutex);
aws_mutex = NULL;
}
}
int aws_get_ssid_passwd(char *ssid, char *passwd, uint8_t *bssid,
char *auth, char *encry, uint8_t *channel)
{
if (aws_state != AWS_SUCCESS) {
return 0;
}
if (ssid) {
strncpy((char *)ssid, (const char *)aws_result_ssid, ZC_MAX_SSID_LEN - 1);
}
if (passwd) {
strncpy((char *)passwd, (const char *)aws_result_passwd, ZC_MAX_PASSWD_LEN - 1);
}
if (bssid) {
memcpy(bssid, aws_result_bssid, ETH_ALEN);
}
if (auth) {
*auth = aws_result_auth;
}
if (encry) {
*encry = aws_result_encry;
}
if (channel) {
*channel = aws_result_channel;
}
return 1;
}
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif

View File

@@ -0,0 +1,363 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#ifdef AWSS_SUPPORT_HT40
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
/* Variable
* Qos: 2Byte
* auth offset: 36 44 52 56
* group frame: 4e0 3e1~3e7
*/
uint8_t ht40_hint_frame_cnt[64];
uint8_t ht40_filter;
signed char ht40_rssi_low, ht40_rssi_high;
#define ht40_rssi_range (15) /* suggested by Fuzhibo */
/* for ios: start frame interval is 20/100 ms */
#define HIT_FRAME_PER_CHANNEL (2)
#define IEEE80211_MIN_HDRLEN (24)
uint32_t ht40_timestamp;
uint8_t ht40_channel[ZC_MAX_CHANNEL + 1];
uint8_t ht40_channel_filter[ZC_MAX_CHANNEL + 1];
uint8_t ht40_state;
int ht40_init(void)
{
ht40_state = 0;
ht40_filter = 0;
ht40_rssi_low = 0;
ht40_rssi_high = 0;
ht40_timestamp = 0;
memset(ht40_channel, 0, sizeof(ht40_channel));
memset(ht40_channel_filter, 0, sizeof(ht40_channel_filter));
memset(ht40_hint_frame_cnt, 0, sizeof(ht40_hint_frame_cnt));
return 0;
}
int ht40_lock_channel(uint8_t channel, uint8_t filter)
{
if (channel < 1 || channel > 14)
return 0;
if (!ht40_channel[channel]) { // replace when 0
ht40_channel[channel] ++;
ht40_channel_filter[channel] = filter;
} else if (filter == ht40_channel_filter[channel]) {
ht40_channel[channel] ++; /* increase */
} else {
ht40_channel[channel] --; /* decrease */
}
if (ht40_channel[channel] >= HIT_FRAME_PER_CHANNEL)
return 1;
return 0;
}
int ht40_scanning_hint_frame(uint8_t filter, signed char rssi, uint32_t length, uint8_t channel)
{
uint8_t channel_locked = 0, next_loop = 0;
int hint_pos = -1;
int tods = 1;
int i, j, k;
if (ht40_state != STATE_CHN_SCANNING)
return -1;
/* range check, max: 0x4e0 + tkip + qos, min: 0x3e0 + open */
if (length > START_FRAME + zconfig_fixed_offset[2][0] + 2 ||
length <= GROUP_FRAME + zconfig_fixed_offset[0][0]) {
return -1;
}
for (i = 1; i >= 0; i--) //Qos or not
for (j = 3; j >= 0; j--) //auth type, without open
for (k = 0; k < 8; k++) {//group frame
if (zconfig_hint_frame[k] + zconfig_fixed_offset[j][0] + i * 2 == length) {
hint_pos = i * 32 + j * 8 + k;
#if 1
awss_trace("\r\nfilter:%x, rssi:%d, len:%d, Qos:%d, auth:%d, group:%d, %s\r\n",
filter, rssi, length, i, j, k,
next_loop ? "DUP" : "");
#endif
if (!next_loop) {
channel_locked = ht40_lock_channel(channel, filter);
if (channel_locked)
zconfig_set_state(STATE_CHN_LOCKED_BY_BR, tods, channel);
next_loop = 1;/* don't enter this loop again */
}
ht40_hint_frame_cnt[hint_pos]++;
}
}//end of for
if (channel_locked) {
ht40_rssi_high = rssi + ht40_rssi_range;
if (ht40_rssi_high > -1)
ht40_rssi_high = -1;
ht40_rssi_low = rssi - ht40_rssi_range;
if (ht40_rssi_low < -128)
ht40_rssi_low = -128;
ht40_filter = filter;
awss_trace("filter:%x, rssi range:[%d, %d]\r\n",
filter, ht40_rssi_low, ht40_rssi_high);
}
return hint_pos;
}
int ht40_get_qos_auth_group_info(uint32_t length)
{
int count = 0, max_count = 0, max_count_pos = 0;
int continues = 0, max_continues = 0, max_continues_pos = 0, second_continues = 0;
int tods = 1;
int i, j, k;
if (zc_state != STATE_CHN_LOCKED_BY_BR ||
ht40_state != STATE_CHN_SCANNING) {
return 0;
}
for (i = 1; i >= 0; i--) //Qos or not
for (j = 3; j >= 0; j--) //auth type
for (count = 0, continues = 0, k = 0; k < 8; k++) {//group frame
int pos = i * 32 + j * 8 + k;
if (ht40_hint_frame_cnt[pos]) {
count += ht40_hint_frame_cnt[pos];
if (count > max_count) {//NOTE: not >=, see continues
max_count = count;
max_count_pos = pos;
}
continues += 1;
if (continues >= max_continues) {
second_continues = max_continues;
max_continues = continues;
max_continues_pos = pos;
}
}
}
awss_debug("max_cont:%d, sec_cont:%d, max_count:%d, max_cont_pos:%d, max_count_pos:%d\r\n",
max_continues, second_continues, max_count, max_count_pos, max_continues_pos);
if (max_continues > second_continues // not >=
&& max_count_pos == max_continues_pos) {
uint8_t qos = max_count_pos / 32;
uint8_t auth = (max_count_pos % 32) / 8;
zc_frame_offset = zconfig_fixed_offset[auth][0] + qos * 2;
length -= zc_frame_offset;
if (is_start_frame(length) || is_group_frame(length)) {
uint8_t group = get_group_index(length);
zc_group_pos = group;
zc_cur_pos = group;
zc_score_uplimit = score_mid;
ht40_timestamp = os_get_time_ms();
ht40_state = STATE_RCV_IN_PROGRESS;
awss_debug("len:%d, qos:%d, auth:%d, group:%d, offset:%d\r\n",
length, qos, auth, group, zc_frame_offset);
}
}
return 0;
}
int awss_ieee80211_ht_ctrl_process(uint8_t *ht_ctrl, int len, int link_type, struct parser_res *res, signed char rssi)
{
struct ht40_ctrl *ctrl = NULL;
/*
* when device try to connect current router (include adha and aha)
* skip the new packet.
*/
if (ht_ctrl == NULL || zconfig_finished)
return ALINK_INVALID;
/*
* we don't process smartconfig until user press configure button
*/
if (awss_get_config_press() == 0)
return ALINK_INVALID;
/*
* just process ht ctrl
*/
if (link_type != AWSS_LINK_TYPE_HT40_CTRL)
return ALINK_INVALID;
ctrl = (struct ht40_ctrl *)ht_ctrl;
res->u.ht_ctrl.rssi = rssi;
res->u.ht_ctrl.filter = ctrl->filter;
res->u.ht_ctrl.data_len = len;
return ALINK_HT_CTRL;
}
int awss_recv_callback_ht_ctrl(struct parser_res *res)
{
uint8_t tods = 1, equal = 0, score = 0;
uint16_t pos = 0, index = 0, len = 0;
uint32_t now = os_get_time_ms();
int pkg_type = PKG_INVALID;
int hint_pos = -1;
signed char rssi;
uint16_t length;
uint8_t channel;
uint8_t filter;
rssi = res->u.ht_ctrl.rssi;
length = res->u.ht_ctrl.data_len;
filter = res->u.ht_ctrl.filter;
channel = res->channel;
if (length > IEEE80211_MIN_HDRLEN) {
length -= IEEE80211_MIN_HDRLEN;
len = length;
} else {
goto drop;
}
hint_pos = ht40_scanning_hint_frame(filter, rssi, length, channel);
if (hint_pos >= 0) {
ht40_get_qos_auth_group_info(length);
return PKG_GROUP_FRAME;
}
if (ht40_state == STATE_RCV_IN_PROGRESS) {
if (rssi <= ht40_rssi_low && rssi >= ht40_rssi_high)
goto drop;
if (filter != ht40_filter)
goto drop;
if (len <= zc_frame_offset) /* length invalid */
goto drop;
len -= zc_frame_offset;
if (is_data_frame(len)) {
pkg_type = PKG_DATA_FRAME;
index = get_data_index(len);
pos = zc_group_pos + index;
if (now - ht40_timestamp > time_interval) {
awss_debug("\t\t\t\t\ttimestamp = %d, pos:%d, len:%x\r\n",
now - ht40_timestamp, pos, len);
goto drop;
}
/*
* pos_unsync: 进入条件,任一条
* case1: index rollback
* case2: index equal but len not equal
* case3: data frame & timeout
* 退出条件:
* case1: 进入条件同时也是退出条件
* case2: 收到同步帧
*/
if (pos < zc_cur_pos) {
awss_debug("drop: index rollback. prev:%d, cur:%d\n", zc_cur_pos, pos);
goto drop;
}
if (pos == zc_cur_pos && len != pkg_len(zc_cur_pos)) {
awss_debug("drop: index equal, but len not. prev:%x, cur:%x\n",
pkg_len(pos), len);
pkg_score(pos)--;
goto drop;
}
if (pos > zc_cur_pos + 4) {
awss_debug("drop: over range too much, prev:%d, cur:%d\n",
zc_cur_pos, pos);
goto drop;
}
score = zc_score_uplimit - (pos - zc_cur_pos - 1);
zc_score_uplimit = score;
awss_trace("ht40 %d+%d [%d] -- T %-3x\r\n", zc_group_pos, index, score, len);
/*
score now > last:
1) data equal: pkg_score = now
2) not equal: pkg_score = now, data replace
score now == last:
1) data equal: pkg_score++ and ???
2) not equal: pkg_score cut down & give warning & try_to_replace
score now < last:
1) data equal: score_uplimit up???
2) not equal: goto pos_unsync
*/
equal = !package_cmp((uint8_t *)pkg(pos), NULL, NULL, tods, len);
if (score > pkg_score(pos)) {
pkg_score(pos) = score; //update score first
if (!equal) {
zc_replace = 1;
package_save((uint8_t *)pkg(pos), NULL, NULL, tods, len);
}
} else if (score == pkg_score(pos)) {/* range check ? */
if (equal) {
pkg_score(pos)++;
} else {
pkg_score(pos)--;
}
} else {//pkg_score(pos) > score
/* do nothing */
}
zc_cur_pos = pos;
zc_max_pos = (zc_max_pos < zc_cur_pos) ? zc_cur_pos : zc_max_pos;
if (zc_replace && zconfig_recv_completed(tods)) {
zc_replace = 0;
if (!zconfig_get_ssid_passwd(tods)) {
/* we got it! */
zconfig_set_state(STATE_RCV_DONE, tods, channel);
return PKG_END;
}
}
ht40_timestamp = now;
return pkg_type;
} else {
if (is_start_frame(len) || is_group_frame(len)) {
uint8_t group = get_group_index(len);
if (!group || group == zc_group_pos + 8) {
zc_group_pos = group;
zc_score_uplimit = score_mid;
if (zc_cur_pos + 1 == group)
pkg_score(zc_cur_pos) += 1;
zc_cur_pos = group;
awss_trace("%d+%d [%d] -- T %-3x\r\n", group, 0, zc_score_uplimit, len);
//ignore PKG_GROUP_FRAME here
pkg_type = PKG_START_FRAME;
ht40_timestamp = now;
return pkg_type;
}
}
}
}
drop:
return PKG_INVALID;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_HT40_H__
#define __AWSS_HT40_H__
#ifdef AWSS_SUPPORT_HT40
#include <stdint.h>
#include "os.h"
#include "zconfig_ieee80211.h"
#include "zconfig_protocol.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
struct ht40_ctrl {
uint16_t length;
uint8_t filter;
signed char rssi;
};
int ht40_init(void);
int awss_ieee80211_ht_ctrl_process(uint8_t *ht_ctrl, int len, int link_type,
struct parser_res *res, signed char rssi);
int awss_recv_callback_ht_ctrl(struct parser_res *res);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif
#endif

View File

@@ -0,0 +1,12 @@
LIBA_TARGET := libiot_awss.a
LIB_SRCS_PATTERN := *.c
$(call Append_Conditional, LIB_SRCS_PATTERN, smartconfig/*.c, AWSS_SUPPORT_SMARTCONFIG)
$(call Append_Conditional, LIB_SRCS_PATTERN, p2p/*.c, AWSS_SUPPORT_SMARTCONFIG_WPS)
$(call Append_Conditional, LIB_SRCS_PATTERN, zero_config/*.c, AWSS_SUPPORT_ZEROCONFIG)
$(call Append_Conditional, LIB_SRCS_PATTERN, phone_ap/*.c, AWSS_SUPPORT_AHA)
$(call Append_Conditional, LIB_SRCS_PATTERN, router_ap/*.c, AWSS_SUPPORT_ADHA)
$(call Append_Conditional, LIB_SRCS_PATTERN, dev_ap/*.c, AWSS_SUPPORT_DEV_AP)
$(call Append_Conditional, LIB_SRCS_PATTERN, frameworks/*.c, AWSS_FRAMEWORKS)
$(call Append_Conditional, LIB_SRCS_PATTERN, frameworks/*/*.c, AWSS_FRAMEWORKS)

View File

@@ -0,0 +1,391 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
int is_ascii_string(uint8_t *str)
{
int i = 0;
while (str[i] != '\0') {
if (str[i] < 128) {
i ++;
} else {
return 0;
}
}
return 1;
}
/**
* extract device name attribute from wps ie struct
*
* @wps_ie: [IN] wps ie struct
* @len: [OUT] len of dev name attr if exist
*
* Return:
* %NULL if dev name attr could not be found, otherwise return a
* pointer to dev name attr
*/
static uint8_t *get_device_name_attr_from_wps(uint8_t *wps_ie, uint8_t *len)
{
/* 6 = 1(Element ID) + 1(Length) + 4(WPS OUI) */
uint8_t *attr_ptr = wps_ie + 6; /* goto first attr */
uint8_t wps_ielen = wps_ie[1];
#define device_name_id (0x1011)
while (attr_ptr - wps_ie < wps_ielen) {
/* 4 = 2(Attribute ID) + 2(Length) */
uint16_t attr_id = os_get_unaligned_be16(attr_ptr);
uint16_t attr_data_len = os_get_unaligned_be16(attr_ptr + 2);
uint16_t attr_len = attr_data_len + 4;
if (attr_id == device_name_id) {
*len = attr_len;
return attr_ptr;
} else {
attr_ptr += attr_len; /* goto next */
}
}
return NULL;
}
/*
* passwd_check_utf8()
*
* @Note: see andriod smartconfig with p2p
* if the byte in passwd is zero, jave will change 0x00 with 0xc080
* the function will restore 0xc080 to 0x00
*/
void passwd_check_utf8(uint8_t *passwd, int *passwd_len)
{
int i, len;
if (!passwd || !passwd_len) {
return;
}
len = *passwd_len;
for (i = 0; i < len; i ++) {
if (passwd[i] < 0x80) { /* [0x01 ~ 0x7F] */
continue;
}
passwd[i] = 0; /* resetore to 0x00 */
if (i + 2 < len) { /* move the rest to overwrite useless content. */
memmove(passwd + i + 1, passwd + i + 2, len - i - 2);
}
len --;
}
*passwd_len = len;
}
/*
* get_ssid_passwd_from_wps()
*
* @Note: see andriod zconfig protocol
* android sdk limit sizeof(passwd) <= 23
*
* @Return: _GOT_RESULT_
*
* use src mac to do ssid completion
*/
static int get_ssid_passwd_from_w(uint8_t *in, int total_len, uint8_t *src, uint8_t *bssid)
{
uint8_t tmp_ssid[ZC_MAX_SSID_LEN + 1] = {0}, tmp_passwd[ZC_MAX_PASSWD_LEN + 1] = {0};
int ssid_len, passwd_len, ssid_truncated = 0;
uint16_t crc, cal_crc;
char encrypt = 0;
/* used by prepare frame */
char *magic_p_w_d = "zl&ws";/* FIXME: Maybe it will be dangerous when opening source. */
static uint32_t start_time = 0;
#define W_LEN (32) /* total_len */
#define EXTRA_LEN (3) /* ssid_len(1B) + checksum(2B) */
if (!in || total_len <= 4 + EXTRA_LEN) {
return GOT_NOTHING;
}
/* attr_id(2) + attr_len(2) = 4 */
in += 4;
total_len -= 4;
if (total_len > W_LEN) {
awss_warn("ssid len > 32\r\n");
}
/* total_len: ssid_len(1B), ssid, passwd, crc(2B) */
ssid_len = in[0];
if (ssid_len & P2P_ENCRYPT_BIT_MASK) {
encrypt = (ssid_len & P2P_ENCRYPT_BIT_MASK) >> P2P_ENCODE_TYPE_OFFSET;
ssid_len &= P2P_SSID_LEN_MASK;
}
if (encrypt > P2P_ENCODE_TYPE_ENCRYPT) {
return GOT_NOTHING;
}
passwd_len = total_len - ssid_len - EXTRA_LEN; /* ssid_len(1B), crc(2B) */
if (ssid_len > W_LEN - EXTRA_LEN || passwd_len < 0) {
return GOT_NOTHING;
}
AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_TIME_START);
/* ssid_len(1B), ssid, passwd, crc(2B) */
crc = os_get_unaligned_be16(in + 1 + ssid_len + passwd_len);
/* restore 0xc080 to 0x00 */
passwd_check_utf8(in + 1 + ssid_len, &passwd_len);
cal_crc = zconfig_checksum_v3(in, 1 + ssid_len + passwd_len);
if (crc != cal_crc) {
memset(zc_android_src, 0, sizeof(zconfig_data->android_src));
memset(zc_pre_ssid, 0, sizeof(zconfig_data->android_pre_ssid));
memset(zc_android_ssid, 0, sizeof(zconfig_data->android_ssid));
memset(zc_android_bssid, 0, sizeof(zconfig_data->android_bssid));
awss_debug("rx illegal p2p (0x%x != 0x%x)\r\n", crc, cal_crc);
awss_event_post(IOTX_AWSS_CS_ERR);
AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_CRC_ERR);
/*
* use zconfig_checksum_v3() because
* java modified UTF-8, U+C080 equal U+00,
* ssid len & ssid & crc is not be 0,
* the content of passwd encrypted may be 0
*/
return GOT_NOTHING;
}
if (start_time == 0) {
start_time = os_get_time_ms();
}
#define MAC_LOCAL_ADMINISTERED_BIT (0x02)
memcpy(zc_android_src, src, ETH_ALEN);
if (zc_android_src[0] & MAC_LOCAL_ADMINISTERED_BIT) {
zc_android_src[0] &= ~MAC_LOCAL_ADMINISTERED_BIT;
/*awss_debug("android src: %02x%02x%02x\r\n", zc_android_src[0], src[1], src[2]); */
} else {
awss_warn("local administered bit not set: %02x%02x%02x\r\n",
src[0], src[1], src[2]);
}
in += 1;/* eating ssid_len(1B) */
memset(tmp_ssid, 0, ZC_MAX_SSID_LEN);
memset(tmp_passwd, 0, ZC_MAX_PASSWD_LEN);
memcpy(tmp_ssid, in, ssid_len);
in += ssid_len;
if (passwd_len) {
memcpy(tmp_passwd, in, passwd_len);
}
awss_dict_crypt(SSID_DECODE_TABLE, tmp_ssid, ssid_len);
switch (encrypt) {
case P2P_ENCODE_TYPE_ENCRYPT: {
/* decypt passwd using aes128-cfb */
uint8_t passwd_cipher_len = 0;
uint8_t *passwd_cipher = os_zalloc(128);
if (passwd_cipher == NULL) {
return GOT_NOTHING;
}
decode_chinese(tmp_passwd, passwd_len, passwd_cipher, &passwd_cipher_len, 7);
passwd_len = passwd_cipher_len;
memset(tmp_passwd, 0, ZC_MAX_PASSWD_LEN);
aes_decrypt_string((char *)passwd_cipher, (char *)tmp_passwd, passwd_len,
1, awss_get_encrypt_type(), 0, NULL);
HAL_Free(passwd_cipher);
if (is_utf8((const char *)tmp_passwd, passwd_len) == 0) {
/* memset(zconfig_data, 0, sizeof(*zconfig_data)); */
memset(zc_android_src, 0, sizeof(zconfig_data->android_src));
memset(zc_pre_ssid, 0, sizeof(zconfig_data->android_pre_ssid));
memset(zc_android_ssid, 0, sizeof(zconfig_data->android_ssid));
memset(zc_android_bssid, 0, sizeof(zconfig_data->android_bssid));
awss_warn("p2p decrypt passwd content err\r\n");
awss_event_post(IOTX_AWSS_PASSWD_ERR);
AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
return GOT_NOTHING;
}
break;
}
default: {
void *tmp_mutex = zc_mutex;
awss_warn("p2p encypt:%d not support\r\n", encrypt);
memset(zconfig_data, 0, sizeof(*zconfig_data));
zc_mutex = tmp_mutex;
return GOT_NOTHING;
}
}
awss_debug("ssid:%s, tlen:%d\r\n", tmp_ssid, total_len);
if (passwd_len && !memcmp(tmp_passwd, magic_p_w_d, passwd_len)) {
/* Note: when v2 rollback to v1, zc_preapre_ssid will useless */
strncpy((char *)zc_pre_ssid, (char const *)tmp_ssid, ZC_MAX_SSID_LEN - 1);
return GOT_CHN_LOCK;
}
/*
// for ascii ssid, max length is 29(32 - 1 - 2).
// for utf-8 ssid, max length is 29 - 2 or 29 - 3
// gbk ssid also encoded as utf-8
// SAMSUNG S4 max name length = 22
*/
if (!is_ascii_string((uint8_t *)tmp_ssid)) { /* chinese ssid */
ssid_truncated = 1; /* in case of gbk chinese */
} else if (total_len >= W_LEN - EXTRA_LEN) {
ssid_truncated = 1;
}
if (ssid_truncated) {
uint8_t *best_ssid;
int cur_ssid_len = strlen((const char *)tmp_ssid); /* current_ssid */
int pre_ssid_len = strlen((const char *)zc_pre_ssid); /* prepare_ssid */
if (pre_ssid_len && pre_ssid_len < cur_ssid_len) {
/* should not happen */
awss_warn("pre:%s < cur:%s\r\n", zc_pre_ssid, tmp_ssid);
best_ssid = tmp_ssid; /* current ssid */
} else if (pre_ssid_len) {
best_ssid = zc_pre_ssid; /* prepare ssid */
} else {
best_ssid = tmp_ssid; /* default use current ssid */
}
/* awss_debug("ssid truncated, best ssid: %s\r\n", best_ssid); */
do {
#ifdef AWSS_SUPPORT_APLIST
struct ap_info *ap_info;
ap_info = zconfig_get_apinfo_by_ssid_suffix(best_ssid);
if (ap_info) {
awss_debug("ssid truncated, got ssid from aplist:%s\r\n", best_ssid);
strncpy((char *)zc_ssid, (const char *)ap_info->ssid, ZC_MAX_SSID_LEN - 1);
memcpy(zc_bssid, ap_info->mac, ETH_ALEN);
} else
#endif
{
if (memcmp(bssid, zero_mac, ETH_ALEN) && memcmp(bssid, br_mac, ETH_ALEN)) {
memcpy(zc_android_bssid, bssid, ETH_ALEN);
}
#ifdef AWSS_SUPPORT_APLIST
ap_info = zconfig_get_apinfo(zc_android_bssid);
if (ap_info) {
if (ap_info->ssid[0] == '\0') { /* hide ssid, MUST not truncate */
strncpy((char *)zc_android_ssid, (const char *)best_ssid, ZC_MAX_SSID_LEN - 1);
} else { /* not hide ssid, amend ssid according to ap list */
strncpy((char *)zc_android_ssid, (const char *)ap_info->ssid, ZC_MAX_SSID_LEN - 1);
}
} else
#endif
if (time_elapsed_ms_since(start_time) > HAL_Awss_Get_Channelscan_Interval_Ms() * (13 + 3) * 2) {
start_time = 0;
strncpy((char *)zc_android_ssid, (const char *)best_ssid, ZC_MAX_SSID_LEN - 1);
}
if (zc_android_ssid[0] == '\0') {
return GOT_NOTHING;
}
strncpy((char *)zc_ssid, (const char *)zc_android_ssid, ZC_MAX_SSID_LEN - 1);
memcpy(zc_bssid, zc_android_bssid, ETH_ALEN);
}
} while (0);
} else {
strncpy((char *)zc_ssid, (char const *)tmp_ssid, ZC_MAX_SSID_LEN - 1);
if (memcmp(bssid, zero_mac, ETH_ALEN) && memcmp(bssid, br_mac, ETH_ALEN)) {
memcpy(zc_bssid, bssid, ETH_ALEN);
}
}
strncpy((char *)zc_passwd, (char const *)tmp_passwd, ZC_MAX_PASSWD_LEN - 1);
start_time = 0;
return GOT_SSID_PASSWD;
}
int awss_recv_callback_wps(struct parser_res *res)
{
uint8_t *data = res->u.wps.data;
uint16_t len = res->u.wps.data_len;
uint8_t tods = res->tods;
uint8_t channel = res->channel;
int ret = get_ssid_passwd_from_w(data, len, res->src, res->bssid);
if (ret == GOT_CHN_LOCK) {
awss_debug("callback for v2:%02x%02x%02x\r\n",
res->src[0], res->src[1], res->src[2]);
goto chn_locked;
} else if (ret == GOT_SSID_PASSWD) {
goto rcv_done;
} else if (ret == GOT_NOTHING) {
return PKG_INVALID;
} else {
return PKG_INVALID;
}
chn_locked:
zconfig_set_state(STATE_CHN_LOCKED_BY_P2P, tods, channel);
return PKG_START_FRAME;
rcv_done:
AWSS_UPDATE_STATIS(AWSS_STATIS_WPS_IDX, AWSS_STATIS_TYPE_TIME_SUC);
zconfig_set_state(STATE_RCV_DONE, tods, channel);
return PKG_END;
}
int awss_ieee80211_wps_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
{
const uint8_t *wps_ie = NULL;
struct ieee80211_hdr *hdr;
uint8_t attr_len = 0;
uint16_t ieoffset;
int fc;
/*
* when device try to connect current router (include adha and aha)
* skip the wps packet.
*/
if (mgmt_header == NULL || zconfig_finished) {
return ALINK_INVALID;
}
/*
* we don't process wps until user press configure button
*/
if (awss_get_config_press() == 0) {
return ALINK_INVALID;
}
hdr = (struct ieee80211_hdr *)mgmt_header;
fc = hdr->frame_control;
if (!ieee80211_is_probe_req(fc)) {
return ALINK_INVALID;
}
ieoffset = offsetof(struct ieee80211_mgmt, u.probe_req.variable);
if (ieoffset > len) {
return ALINK_INVALID;
}
/* get wps ie */
wps_ie = (const uint8_t *)cfg80211_find_vendor_ie(WLAN_OUI_WPS, WLAN_OUI_TYPE_WPS,
mgmt_header + ieoffset, len - ieoffset);
if (wps_ie == NULL) {
return ALINK_INVALID;
}
/* get wps name in wps ie */
wps_ie = (const uint8_t *)get_device_name_attr_from_wps((uint8_t *)wps_ie, &attr_len);
if (wps_ie == NULL) {
return ALINK_INVALID;
}
res->u.wps.data_len = attr_len;
res->u.wps.data = (uint8_t *)wps_ie;
return ALINK_WPS;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_WPS_H__
#define __AWSS_WPS_H__
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
#include <stdint.h>
#include "os.h"
#include "zconfig_ieee80211.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#define WLAN_OUI_MICROSOFT (0x0050F2)
#define WLAN_OUI_WPS (0x0050F2)
#define WLAN_OUI_TYPE_MICROSOFT_WPA (1)
#define WLAN_OUI_TYPE_WPS (4)
int awss_recv_callback_wps(struct parser_res *res);
int awss_ieee80211_wps_process(uint8_t *mgmt_header, int len, int link_type,
struct parser_res *res, signed char rssi);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif /* end AWSS_SUPPORT_SMARTCONFIG_WPS */
#endif

View File

@@ -0,0 +1,52 @@
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
/*************************************** common hals ***************************************/
int HAL_Timer_Stop(void *timer);
int HAL_Timer_Delete(void *timer);
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
int HAL_Timer_Start(void *timer, int ms);
void HAL_SleepMs(uint32_t ms);
void *HAL_Malloc(uint32_t size);
void HAL_MutexLock(void *mutex);
void HAL_MutexUnlock(void *mutex);
uint64_t HAL_UptimeMs(void);
void HAL_Free(void *ptr);
void *HAL_MutexCreate(void);
void HAL_MutexDestroy(void *mutex);
/*************************************** wifi provision frameworks hals ***************************************/
/* frameworks/awss.c*/
int HAL_Awss_Get_Timeout_Interval_Ms(void);
int HAL_Sys_Net_Is_Ready();
int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
/* awss_crypt.c */
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
int HAL_GetProductSecret(char *product_secret);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
/* zconfig_vendor_common.c */
void HAL_Awss_Close_Monitor(void);
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
int HAL_Awss_Get_Channelscan_Interval_Ms(void);
p_HAL_Aes128_t HAL_Aes128_Init(
_IN_ const uint8_t *key,
_IN_ const uint8_t *iv,
_IN_ AES_DIR_t dir);
int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
int HAL_Aes128_Cfb_Decrypt(
_IN_ p_HAL_Aes128_t aes,
_IN_ const void *src,
_IN_ size_t length,
_OU_ void *dst);
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
int HAL_Awss_Connect_Ap(
_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel);

View File

@@ -0,0 +1,57 @@
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
/*************************************** common hals ***************************************/
int HAL_Timer_Stop(void *timer);
int HAL_Timer_Delete(void *timer);
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
int HAL_Timer_Start(void *timer, int ms);
void HAL_SleepMs(uint32_t ms);
void *HAL_Malloc(uint32_t size);
void HAL_MutexLock(void *mutex);
void HAL_MutexUnlock(void *mutex);
uint64_t HAL_UptimeMs(void);
void HAL_Free(void *ptr);
void *HAL_MutexCreate(void);
void HAL_MutexDestroy(void *mutex);
/*************************************** wifi provision frameworks hals ***************************************/
/* frameworks/awss.c*/
int HAL_Awss_Get_Timeout_Interval_Ms(void);
int HAL_Sys_Net_Is_Ready();
int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
/* awss_crypt.c */
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
int HAL_GetProductSecret(char *product_secret);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
void HAL_Awss_Close_Monitor(void);
void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
int HAL_Awss_Get_Channelscan_Interval_Ms(void);
/* zconfig_vendor_common.c */
p_HAL_Aes128_t HAL_Aes128_Init(
_IN_ const uint8_t *key,
_IN_ const uint8_t *iv,
_IN_ AES_DIR_t dir);
int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
int HAL_Aes128_Cbc_Decrypt(
_IN_ p_HAL_Aes128_t aes,
_IN_ const void *src,
_IN_ size_t blockNum,
_OU_ void *dst);
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
int HAL_Awss_Connect_Ap(
_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel);
/*************************************** phone ap specially required hals ***************************************/
int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
_IN_ uint8_t *buffer, _IN_ int len);
int HAL_Wifi_Scan(awss_wifi_scan_result_cb_t cb);

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#ifdef AWSS_SUPPORT_AHA
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#define AHA_SA_OFFSET (10)
#define AHA_PROBE_PKT_LEN (49)
#define AHA_MONITOR_TIMEOUT_MS (1 * 60 * 1000)
const char *zc_default_ssid = "aha";
const char *zc_default_passwd = "12345678";
static const uint8_t aha_probe_req_frame[AHA_PROBE_PKT_LEN] = {
0x40, 0x00, /* mgnt type, frame control */
0x00, 0x00, /* duration */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
0xC0, 0x79, /* seq */
0x00, 0x03, 0x61, 0x68, 0x61, /* ssid, aha */
0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x8C, 0x92, 0x98, 0xA4, /* supported rates */
0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
0x3F, 0x84, 0x10, 0x9E /* FCS */
};
static void *aha_timer = NULL;
static volatile char aha_timeout = 0;
static void aha_monitor(void);
static void aha_monitor(void)
{
aha_timeout = 1;
}
int awss_aha_monitor_is_timeout(void)
{
return aha_timeout > 0;
}
int awss_open_aha_monitor(void)
{
aha_timeout = 0;
if (aha_timer == NULL)
aha_timer = (void *)HAL_Timer_Create("aha", (void (*)(void *))aha_monitor, NULL);
if (aha_timer == NULL)
return -1;
HAL_Timer_Stop(aha_timer);
HAL_Timer_Start(aha_timer, AHA_MONITOR_TIMEOUT_MS);
return 0;
}
int awss_close_aha_monitor(void)
{
awss_stop_timer(aha_timer);
aha_timer = NULL;
aha_timeout = 0;
return 0;
}
int awss_recv_callback_aha_ssid(struct parser_res *res)
{
uint8_t tods = res->tods;
uint8_t channel = res->channel;
awss_debug("found default ssid: %s\r\n", zc_default_ssid);
AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_TIME_START);
strncpy((char *)zc_ssid, zc_default_ssid, ZC_MAX_SSID_LEN - 1);
strncpy((char *)zc_passwd, zc_default_passwd, ZC_MAX_PASSWD_LEN - 1);
zconfig_set_state(STATE_RCV_DONE, tods, channel);
return PKG_END;
}
int aws_send_aha_probe_req(void)
{
uint8_t probe[AHA_PROBE_PKT_LEN];
memcpy(probe, aha_probe_req_frame, sizeof(probe));
os_wifi_get_mac(&probe[AHA_SA_OFFSET]);
HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, probe, sizeof(probe));
return 0;
}
int awss_ieee80211_aha_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
{
uint8_t ssid[ZC_MAX_SSID_LEN] = {0}, bssid[ETH_ALEN] = {0};
uint8_t auth, pairwise_cipher, group_cipher;
struct ieee80211_hdr *hdr;
int fc, ret, channel;
/*
* when device try to connect current router (include adha and aha)
* skip the new aha and process the new aha in the next scope.
*/
if (mgmt_header == NULL || zconfig_finished)
return ALINK_INVALID;
/*
* we don't process aha until user press configure button
*/
if (awss_get_config_press() == 0)
return ALINK_INVALID;
hdr = (struct ieee80211_hdr *)mgmt_header;
fc = hdr->frame_control;
if (!ieee80211_is_beacon(fc) && !ieee80211_is_probe_resp(fc))
return ALINK_INVALID;
ret = ieee80211_get_bssid(mgmt_header, bssid);
if (ret < 0)
return ALINK_INVALID;
ret = ieee80211_get_ssid(mgmt_header, len, ssid);
if (ret < 0)
return ALINK_INVALID;
/*
* skip ap which is not aha
*/
if (strcmp((const char *)ssid, zc_default_ssid))
return ALINK_INVALID;
channel = cfg80211_get_bss_channel(mgmt_header, len);
rssi = rssi > 0 ? rssi - 256 : rssi;
cfg80211_get_cipher_info(mgmt_header, len, &auth,
&pairwise_cipher, &group_cipher);
awss_save_apinfo(ssid, bssid, channel, auth,
pairwise_cipher, group_cipher, rssi);
/*
* If user press the configure button,
* device just process aha, and skip all the adha.
*/
if (adha_aplist->cnt > adha_aplist->try_idx) {
uint8_t ap_idx = adha_aplist->aplist[adha_aplist->try_idx ++];
#ifdef AWSS_SUPPORT_APLIST
memcpy(zc_bssid, zconfig_aplist[ap_idx].mac, ETH_ALEN);
#endif
awss_set_config_press(0);
return ALINK_DEFAULT_SSID;
}
return ALINK_INVALID;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_AHA_H__
#define __AWSS_AHA_H__
#include <stdint.h>
#include "os.h"
#include "zconfig_ieee80211.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
int awss_open_aha_monitor(void);
int awss_close_aha_monitor(void);
int awss_aha_monitor_is_timeout(void);
int aws_send_aha_probe_req(void);
int awss_recv_callback_aha_ssid(struct parser_res *res);
int awss_ieee80211_aha_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi);
extern const char *zc_default_ssid;
extern const char *zc_default_passwd;
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,401 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
#define WIFI_APINFO_LIST_LEN (512)
#define DEV_SIMPLE_ACK_LEN (64)
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
static char g_req_msg_id[MSG_REQ_ID_LEN];
static platform_netaddr_t g_wifimgr_req_sa;
static void *scan_req_timer = NULL;
static void *scan_tx_wifilist_timer = NULL;
static void wifimgr_scan_request();
static void wifimgr_scan_tx_wifilist();
static char wifi_scan_runninng = 0;
static void *g_scan_mutex;
typedef struct scan_list {
list_head_t entry;
void *data;
} scan_list_t;
static LIST_HEAD(g_scan_list);
int wifimgr_scan_init(void)
{
if (wifi_scan_runninng)
return 0;
g_scan_mutex = HAL_MutexCreate();
INIT_LIST_HEAD(&g_scan_list);
wifi_scan_runninng = 1;
return 0;
}
static void wifimgr_scan_tx_wifilist()
{
scan_list_t *item = NULL, *next = NULL;
char topic[TOPIC_LEN_MAX] = {0};
awss_build_topic((const char *)TOPIC_AWSS_WIFILIST, topic, TOPIC_LEN_MAX);
HAL_MutexLock(g_scan_mutex);
list_for_each_entry_safe(item, next, &g_scan_list, entry, scan_list_t) {
if (item && item->data) {
if (0 != awss_cmp_coap_ob_send(item->data, strlen((char *)item->data),
&g_wifimgr_req_sa, topic, NULL)) {
awss_debug("sending failed.");
}
HAL_Free(item->data);
}
list_del(&item->entry);
HAL_Free(item);
item= NULL;
}
HAL_MutexUnlock(g_scan_mutex);
}
static int awss_scan_cb(const char ssid[PLATFORM_MAX_SSID_LEN],
const uint8_t bssid[ETH_ALEN],
enum AWSS_AUTH_TYPE auth,
enum AWSS_ENC_TYPE encry,
uint8_t channel, signed char rssi,
int last_ap)
{
#define ONE_AP_INFO_LEN_MAX (141)
static char *aplist = NULL;
static int msg_len = 0;
if (aplist == NULL) {
aplist = os_zalloc(WIFI_APINFO_LIST_LEN);
if (aplist == NULL)
return SHUB_ERR;
msg_len = 0;
msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1, "{\"awssVer\":%s, \"wifiList\":[", AWSS_VER);
}
if ((ssid != NULL) && (ssid[0] != '\0')) {
uint8_t bssid_connected[ETH_ALEN] = {0};
char *other_apinfo = os_zalloc(64);
char *encode_ssid = os_zalloc(OS_MAX_SSID_LEN * 2 + 1);
int ssid_len = strlen(ssid);
ssid_len = ssid_len > OS_MAX_SSID_LEN - 1 ? OS_MAX_SSID_LEN - 1 : ssid_len;
HAL_Wifi_Get_Ap_Info(NULL, NULL, bssid_connected);
if (other_apinfo && encode_ssid) {
if (memcmp(bssid_connected, bssid, ETH_ALEN) == 0) {
HAL_Snprintf(other_apinfo, 64 - 1, "\"auth\":\"%d\",\"connected\":\"1\"", auth);
} else {
HAL_Snprintf(other_apinfo, 64 - 1, "\"auth\":\"%d\"", auth);
}
if (is_utf8(ssid, ssid_len)) {
strncpy(encode_ssid, (const char *)ssid, ssid_len);
msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1,
"{\"ssid\":\"%s\",\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\"rssi\":\"%d\",%s},",
encode_ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
rssi > 0 ? rssi - 256 : rssi, other_apinfo);
} else {
utils_hex_to_str((uint8_t *)ssid, ssid_len, encode_ssid, OS_MAX_SSID_LEN * 2);
msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1,
"{\"xssid\":\"%s\",\"bssid\":\"%02X:%02X:%02X:%02X:%02X:%02X\",\"rssi\":\"%d\",%s},",
encode_ssid, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5],
rssi > 0 ? rssi - 256 : rssi, other_apinfo);
}
}
if (other_apinfo) HAL_Free(other_apinfo);
if (encode_ssid) HAL_Free(encode_ssid);
}
awss_debug("last_ap:%u\r\n", last_ap);
if (last_ap || WIFI_APINFO_LIST_LEN < msg_len + ONE_AP_INFO_LEN_MAX + strlen(AWSS_ACK_FMT)) {
uint32_t tlen;
char *msg_aplist = NULL;
scan_list_t *list = NULL;
if (last_ap)
AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_SCAN_STOP);
if (aplist[msg_len - 1] == ',')
msg_len--; /* eating the last ',' */
msg_len += HAL_Snprintf(aplist + msg_len, WIFI_APINFO_LIST_LEN - msg_len - 1, "]}");
tlen = DEV_SIMPLE_ACK_LEN + msg_len;
msg_len = 0;
msg_aplist = os_zalloc(tlen + 1);
if (!msg_aplist) {
HAL_Free(aplist);
aplist = NULL;
return SHUB_ERR;
}
HAL_Snprintf(msg_aplist, tlen, AWSS_ACK_FMT, g_req_msg_id, 200, aplist);
HAL_Free(aplist);
aplist = NULL;
list = (scan_list_t *)os_zalloc(sizeof(scan_list_t));
if (!list) {
awss_debug("scan list fail\n");
HAL_Free(msg_aplist);
return SHUB_ERR;
}
list->data = msg_aplist;
HAL_MutexLock(g_scan_mutex);
list_add(&list->entry, &g_scan_list);
HAL_MutexUnlock(g_scan_mutex);
if (last_ap) {
if (scan_tx_wifilist_timer == NULL)
scan_tx_wifilist_timer = HAL_Timer_Create("wifilist", (void (*)(void *))wifimgr_scan_tx_wifilist, NULL);
HAL_Timer_Stop(scan_tx_wifilist_timer);
HAL_Timer_Start(scan_tx_wifilist_timer, 1);
}
awss_debug("sending message to app: %s\n", msg_aplist);
}
return 0;
}
static void wifimgr_scan_request()
{
wifimgr_scan_init();
AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_SCAN_START);
HAL_Wifi_Scan(&awss_scan_cb);
}
/*
* @desc: ????getWifiList??Ϣ
*
*/
int wifimgr_process_get_wifilist_request(void *ctx, void *resource, void *remote, void *request)
{
char buf[DEV_SIMPLE_ACK_LEN] = {0};
char *msg = NULL, *id = NULL;
int len = 0, id_len = 0;
char topic[TOPIC_LEN_MAX] = {0};
msg = awss_cmp_get_coap_payload(request, &len);
if (msg == NULL || len == 0)
return -1;
if (scan_req_timer == NULL)
scan_req_timer = HAL_Timer_Create("scan_req", (void (*)(void *))wifimgr_scan_request, NULL);
HAL_Timer_Stop(scan_req_timer);
id = json_get_value_by_name(msg, len, "id", &id_len, 0);
memset(g_req_msg_id, 0, sizeof(g_req_msg_id));
if (id && id_len < sizeof(g_req_msg_id) - 1)
memcpy(g_req_msg_id, id, id_len);
HAL_Snprintf(buf, DEV_SIMPLE_ACK_LEN - 1, AWSS_ACK_FMT, g_req_msg_id, 200, "\"success\"");
awss_debug("sending message to app: %s\n", buf);
awss_build_topic((const char *)TOPIC_AWSS_WIFILIST, topic, TOPIC_LEN_MAX);
memcpy(&g_wifimgr_req_sa, remote, sizeof(g_wifimgr_req_sa));
if (0 != awss_cmp_coap_send_resp(buf, strlen(buf), &g_wifimgr_req_sa, topic, request, NULL, NULL, 0))
awss_debug("sending failed.");
HAL_Timer_Start(scan_req_timer, 1);
return SHUB_OK;
}
int wifimgr_process_mcast_get_device_info(void *ctx, void *resource, void *remote, void *request)
{
return process_get_device_info(ctx, resource, remote, request, 1, AWSS_NOTIFY_DEV_RAND_SIGN);
}
int wifimgr_process_ucast_get_device_info(void *ctx, void *resource, void *remote, void *request)
{
return process_get_device_info(ctx, resource, remote, request, 0, AWSS_NOTIFY_DEV_RAND_SIGN);
}
#define WLAN_CONNECTION_TIMEOUT (30 * 1000) /* 30 seconds */
int switch_ap_done = 0;
void zconfig_force_destroy(void);
int wifimgr_process_switch_ap_request(void *ctx, void *resource, void *remote, void *request)
{
char ssid[PLATFORM_MAX_SSID_LEN * 2 + 1] = {0}, passwd[PLATFORM_MAX_PASSWD_LEN + 1] = {0};
int str_len = 0, success = 1, i = 0, len = 0, enc_lvl = SEC_LVL_OPEN;
char req_msg_id[MSG_REQ_ID_LEN] = {0};
char *str = NULL, *buf = NULL;
char bssid[ETH_ALEN] = {0};
char msg[128] = {0};
char ssid_found = 0;
char topic[TOPIC_LEN_MAX] = {0};
static char switch_ap_parsed = 0;
if (switch_ap_parsed != 0)
return SHUB_ERR;
switch_ap_parsed = 1;
buf = awss_cmp_get_coap_payload(request, &len);
str = json_get_value_by_name(buf, len, "id", &str_len, 0);
memcpy(req_msg_id, str, str_len > MSG_REQ_ID_LEN - 1 ? MSG_REQ_ID_LEN - 1 : str_len);
awss_debug("switch ap, len:%u, %s\r\n", len, buf);
buf = json_get_value_by_name(buf, len, "params", &len, 0);
do {
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, 200, "\"success\"");
str_len = 0;
str = json_get_value_by_name(buf, len, "ssid", &str_len, 0);
awss_debug("ssid, len:%u, %s\r\n", str_len, str != NULL ? str : "NULL");
if (str && (str_len < PLATFORM_MAX_SSID_LEN)) {
memcpy(ssid, str, str_len);
ssid_found = 1;
}
if (!ssid_found) {
str_len = 0;
str = json_get_value_by_name(buf, len, "xssid", &str_len, 0);
if (str && (str_len < PLATFORM_MAX_SSID_LEN * 2 - 1)) {
uint8_t decoded[OS_MAX_SSID_LEN] = {0};
int len = str_len / 2;
memcpy(ssid, str, str_len);
utils_str_to_hex(ssid, str_len, decoded, OS_MAX_SSID_LEN);
memcpy(ssid, (const char *)decoded, len);
ssid[len] = '\0';
} else {
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -1, "\"ssid error\"");
success = 0;
break;
}
}
str_len = 0;
str = json_get_value_by_name(buf, len, "bssid", &str_len, 0);
if (str) os_wifi_str2mac(str, bssid);
str_len = 0;
str = json_get_value_by_name(buf, len, "cipherType", &str_len, 0);
if (!str) {
success = 0;
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4, "\"no security level error\"");
break;
}
enc_lvl = atoi(str);
if (enc_lvl != awss_get_encrypt_type()) {
success = 0;
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4, "\"security level error\"");
break;
}
str_len = 0;
str = json_get_value_by_name(buf, len, "passwd", &str_len, 0);
/* TODO: empty passwd is allow? json parse "passwd":"" result is NULL? */
switch (enc_lvl) {
case SEC_LVL_AES256:
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -4, "\"aes256 not support\"");
success = 0;
break;
default:
break;
}
if (success == 0)
break;
if (0 == enc_lvl) {
if (str_len < PLATFORM_MAX_PASSWD_LEN) {
memcpy(passwd, str, str_len);
} else {
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -2, "\"passwd len error\"");
success = 0;
}
} else {
if (str_len < (PLATFORM_MAX_PASSWD_LEN * 2) - 1) {
char encoded[PLATFORM_MAX_PASSWD_LEN * 2 + 1] = {0};
memcpy(encoded, str, str_len);
aes_decrypt_string(encoded, passwd, str_len,
0, awss_get_encrypt_type(), 1, (const char *)aes_random);
} else {
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id, -3, "\"passwd len error\"");
AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
success = 0;
}
}
if (success && is_utf8(passwd, strlen(passwd)) == 0) {
HAL_Snprintf(msg, sizeof(msg) - 1, AWSS_ACK_FMT, req_msg_id,
enc_lvl == SEC_LVL_OPEN ? -2 : -3 , "\"passwd content error\"");
AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
success = 0;
}
} while (0);
awss_devinfo_notify_stop();
awss_dev_bind_notify_stop();
awss_debug("Sending message to app: %s", msg);
awss_debug("switch to ap: '%s'", ssid);
awss_build_topic((const char *)TOPIC_AWSS_SWITCHAP, topic, TOPIC_LEN_MAX);
for (i = 0; i < 5; i ++) {
if (0 != awss_cmp_coap_send_resp(msg, strlen(msg), remote, topic, request, NULL, NULL, 0)) {
awss_debug("sending failed.");
} else {
awss_debug("sending succeeded.");
}
}
HAL_SleepMs(1000);
if (!success)
goto SWITCH_AP_END;
#ifdef AWSS_SUPPORT_APLIST
do {
struct ap_info * aplist = NULL;
aplist = zconfig_get_apinfo_by_ssid((uint8_t *)ssid);
awss_debug("connect '%s'", ssid);
if (aplist) {
memcpy(bssid, aplist->mac, ETH_ALEN);
awss_debug("bssid: %02x:%02x:%02x:%02x:%02x:%02x", \
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
}
} while (0);
#endif
AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_START);
if (0 != HAL_Awss_Connect_Ap(WLAN_CONNECTION_TIMEOUT,
ssid, passwd,
AWSS_AUTH_TYPE_INVALID,
AWSS_ENC_TYPE_INVALID,
(uint8_t *)bssid, 0)) {
} else {
AWSS_UPDATE_STATIS(AWSS_STATIS_CONN_ROUTER_IDX, AWSS_STATIS_TYPE_TIME_SUC);
AWSS_UPDATE_STATIS(AWSS_STATIS_PAP_IDX, AWSS_STATIS_TYPE_TIME_SUC);
switch_ap_done = 1;
awss_close_aha_monitor();
HAL_MutexDestroy(g_scan_mutex);
g_scan_mutex = NULL;
wifi_scan_runninng = 0;
awss_stop_timer(scan_req_timer);
scan_req_timer = NULL;
awss_stop_timer(scan_tx_wifilist_timer);
scan_tx_wifilist_timer = NULL;
zconfig_force_destroy();
produce_random(aes_random, sizeof(aes_random));
}
awss_debug("connect '%s' %s\r\n", ssid, switch_ap_done == 1 ? "success" : "fail");
SWITCH_AP_END:
switch_ap_parsed = 0;
return SHUB_OK;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_WIFIMGR_H__
#define __AWSS_WIFIMGR_H__
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
enum {
SHUB_ERR,
SHUB_OK
};
int wifimgr_process_get_wifilist_request(void *ctx, void *resource, void *remote, void *request);
int wifimgr_process_mcast_get_device_info(void *ctx, void *resource, void *remote, void *request);
int wifimgr_process_ucast_get_device_info(void *ctx, void *resource, void *remote, void *request);
int wifimgr_process_switch_ap_request(void *ctx, void *resource, void *remote, void *request);
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
struct adha_info *adha_aplist = NULL;
const char *zc_adha_ssid = "adha";
const char *zc_adha_passwd = "08d9f22c60157fd01f57645d791a0b610fe0a558c104d6a1f9d9c0a9913c";
#ifdef AWSS_SUPPORT_ADHA
#define ADHA_WORK_CYCLE (5 * 1000)
#define ADHA_PROBE_PKT_LEN (50)
#define ADHA_SA_OFFSET (10)
static const uint8_t adha_probe_req_frame[ADHA_PROBE_PKT_LEN] = {
0x40, 0x00, /* mgnt type, frame control */
0x00, 0x00, /* duration */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
0xC0, 0x79, /* seq */
0x00, 0x04, 0x61, 0x64, 0x68, 0x61, /* ssid, adha */
0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x8C, 0x92, 0x98, 0xA4, /*supported rates */
0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
0x3F, 0x84, 0x10, 0x9E /* FCS */
};
static void *adha_timer = NULL;
static volatile char adha_switch = 0;
static void adha_monitor(void);
static void adha_monitor(void)
{
adha_switch = 1;
}
int awss_is_ready_switch_next_adha(void)
{
return adha_switch > 0;
}
int awss_open_adha_monitor(void)
{
adha_switch = 0;
if (adha_timer == NULL)
adha_timer = (void *)HAL_Timer_Create("adha", (void (*)(void *))adha_monitor, NULL);
if (adha_timer == NULL)
return -1;
HAL_Timer_Stop(adha_timer);
HAL_Timer_Start(adha_timer, ADHA_WORK_CYCLE);
return 0;
}
int awss_close_adha_monitor(void)
{
awss_stop_timer(adha_timer);
adha_timer = NULL;
adha_switch = 0;
return 0;
}
int awss_recv_callback_adha_ssid(struct parser_res *res)
{
uint8_t tods = res->tods;
uint8_t channel = res->channel;
AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_START);
awss_debug("found adha ssid: %s\r\n", zc_adha_ssid);
strncpy((char *)zc_ssid, zc_adha_ssid, ZC_MAX_SSID_LEN - 1);
strncpy((char *)zc_passwd, zc_adha_passwd, ZC_MAX_PASSWD_LEN - 1);
zconfig_set_state(STATE_RCV_DONE, tods, channel);
return PKG_END;
}
int aws_send_adha_probe_req(void)
{
uint8_t probe[ADHA_PROBE_PKT_LEN];
memcpy(probe, adha_probe_req_frame, sizeof(probe));
os_wifi_get_mac(&probe[ADHA_SA_OFFSET]);
HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, probe, sizeof(probe));
return 0;
}
int awss_ieee80211_adha_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
{
uint8_t ssid[ZC_MAX_SSID_LEN] = {0}, bssid[ETH_ALEN] = {0};
uint8_t auth, pairwise_cipher, group_cipher;
struct ieee80211_hdr *hdr;
int fc, ret, channel;
/*
* when device try to connect current router (include adha and aha)
* skip the new aha and process the new aha in the next scope.
*/
if (mgmt_header == NULL || zconfig_finished)
return ALINK_INVALID;
/*
* if user press configure button, drop all adha
*/
if (awss_get_config_press())
return ALINK_INVALID;
hdr = (struct ieee80211_hdr *)mgmt_header;
fc = hdr->frame_control;
if (!ieee80211_is_beacon(fc) && !ieee80211_is_probe_resp(fc))
return ALINK_INVALID;
ret = ieee80211_get_bssid(mgmt_header, bssid);
if (ret < 0)
return ALINK_INVALID;
ret = ieee80211_get_ssid(mgmt_header, len, ssid);
if (ret < 0)
return ALINK_INVALID;
/*
* skip ap which is not adha
*/
if (strcmp((const char *)ssid, zc_adha_ssid))
return ALINK_INVALID;
channel = cfg80211_get_bss_channel(mgmt_header, len);
rssi = rssi > 0 ? rssi - 256 : rssi;
cfg80211_get_cipher_info(mgmt_header, len, &auth,
&pairwise_cipher, &group_cipher);
#ifdef AWSS_SUPPORT_APLIST
awss_save_apinfo(ssid, bssid, channel, auth,
pairwise_cipher, group_cipher, rssi);
#endif
/*
* If user press the configure button,
* skip all the adha.
*/
if (adha_aplist->cnt > adha_aplist->try_idx) {
uint8_t ap_idx = adha_aplist->aplist[adha_aplist->try_idx ++];
#ifdef AWSS_SUPPORT_APLIST
memcpy(zc_bssid, zconfig_aplist[ap_idx].mac, ETH_ALEN);
#endif
return ALINK_ADHA_SSID;
}
return ALINK_INVALID;
}
#endif
int awss_init_adha_aplist(void)
{
if (adha_aplist)
return 0;
adha_aplist = (struct adha_info *)os_zalloc(sizeof(struct adha_info));
if (adha_aplist == NULL)
return -1;
return 0;
}
int awss_deinit_adha_aplist(void)
{
if (adha_aplist == NULL)
return 0;
HAL_Free(adha_aplist);
adha_aplist = NULL;
return 0;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_ADHA_H__
#define __AWSS_ADHA_H__
#if defined(AWSS_SUPPORT_ADHA) || defined(AWSS_SUPPORT_AHA)
#include "zconfig_lib.h"
#include "zconfig_protocol.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
struct adha_info {
uint8_t try_idx;
uint8_t cnt;
uint8_t aplist[MAX_APLIST_NUM];
};
int awss_init_adha_aplist(void);
int awss_deinit_adha_aplist(void);
extern struct adha_info *adha_aplist;
extern const char *zc_adha_passwd;
extern const char *zc_adha_ssid;
#ifdef AWSS_SUPPORT_ADHA
int awss_open_adha_monitor(void);
int awss_close_adha_monitor(void);
int aws_send_adha_probe_req(void);
int awss_is_ready_switch_next_adha(void);
int awss_recv_callback_adha_ssid(struct parser_res *res);
int awss_ieee80211_adha_process(uint8_t *mgmt_header, int len, int link_type,
struct parser_res *res, signed char rssi);
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif /* end AWSS_SUPPORT_ADHA || AWSS_SUPPORT_AHA */
#endif

View File

@@ -0,0 +1,52 @@
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
/*************************************** common hals ***************************************/
int HAL_Timer_Stop(void *timer);
int HAL_Timer_Delete(void *timer);
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
int HAL_Timer_Start(void *timer, int ms);
void HAL_SleepMs(uint32_t ms);
void *HAL_Malloc(uint32_t size);
void HAL_MutexLock(void *mutex);
void HAL_MutexUnlock(void *mutex);
uint64_t HAL_UptimeMs(void);
void HAL_Free(void *ptr);
void *HAL_MutexCreate(void);
void HAL_MutexDestroy(void *mutex);
/*************************************** wifi provision frameworks hals ***************************************/
/* frameworks/awss.c*/
int HAL_Awss_Get_Timeout_Interval_Ms(void);
int HAL_Sys_Net_Is_Ready();
int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
/* awss_crypt.c */
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
int HAL_GetProductSecret(char *product_secret);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
/* zconfig_vendor_common.c */
void HAL_Awss_Close_Monitor(void);
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
int HAL_Awss_Get_Channelscan_Interval_Ms(void);
p_HAL_Aes128_t HAL_Aes128_Init(
_IN_ const uint8_t *key,
_IN_ const uint8_t *iv,
_IN_ AES_DIR_t dir);
int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
int HAL_Aes128_Cfb_Decrypt(
_IN_ p_HAL_Aes128_t aes,
_IN_ const void *src,
_IN_ size_t length,
_OU_ void *dst);
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
int HAL_Awss_Connect_Ap(
_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel);

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_H__
#define __AWSS_H__
#include <stdint.h>
#include "infra_defs.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
#ifndef _IN_
#define _IN_
#endif
int awss_start(void);
/**
* @brief stop wifi setup service
*
* @retval -1 : failure
* @retval 0 : sucess
* @note
* if awss_stop is called before exit of awss_start, awss and notify will stop.
*/
int awss_stop(void);
/**
* @brief make sure user touches device belong to themselves
*
* @retval -1 : failure
* @retval 0 : sucess
* @note: AWSS doesn't parse awss packet until user touches deivce use this api.
*/
int awss_config_press(void);
/**
* @brief get the awss config press status in realtime.
*
* @retval 1 : user has touched device
* @retval 0 : user don't touch device
*/
uint8_t awss_get_config_press(void);
void awss_set_config_press(uint8_t press);
/**
* @brief check reset flag in perisistent storage.
*
* @retval -1 : failure
* @retval 0 : sucess
* @note
* check reset flag in perisistent storage, if device failed to report reset message last time, retry it.
*/
int awss_check_reset(void);
/**
* @brief report reset to cloud.
*
* @retval -1 : failure
* @retval 0 : sucess
* @note
* device will save reset flag if device dosen't connect cloud, device will fails to send reset to cloud.
* when connection between device and cloud is ready, device will retry to report reset to cloud.
*/
int awss_report_reset(void);
/**
* @brief stop to report reset to cloud.
*
* @retval -1 : failure
* @retval 0 : sucess
* @note
* just stop report reset to cloud without any touch reset flag in flash.
*/
int awss_stop_report_reset(void);
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,83 @@
#include "infra_config.h"
#include <string.h>
#include <stdio.h>
#include "aws_lib.h"
#include "awss_aplist.h"
#include "zconfig_lib.h"
#include "zconfig_utils.h"
#include "zconfig_protocol.h"
#include "zconfig_ieee80211.h"
#include "awss_event.h"
#include "awss_timer.h"
#include "awss_main.h"
#include "iot_import_awss.h"
#include "os.h"
#include "infra_compat.h"
#include "awss_smartconfig.h"
#include "infra_sha1.h"
#include "passwd.h"
#include "awss_utils.h"
#include "awss_statis.h"
#include "awss_packet.h"
#include "awss_notify.h"
#include "awss_cmp.h"
#include "wifi_provision_api.h"
#include "awss_cmp.h"
#include "awss_crypt.h"
#include <stdlib.h>
#include "infra_json_parser.h"
#include "mqtt_api.h"
#include "awss_dev_reset_internal.h"
#include "awss_info.h"
#include "awss_bind_statis.h"
#include "dev_bind_wrapper.h"
#include "awss_aplist.h"
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
#include "awss_wps.h"
#endif
#ifdef AWSS_SUPPORT_HT40
#include "awss_ht40.h"
#endif
#if defined(AWSS_SUPPORT_AHA) || defined(AWSS_SUPPORT_ADHA)
#include "awss_wifimgr.h"
#endif
#ifndef AWSS_DISABLE_ENROLLEE
#include "awss_enrollee.h"
#endif
#if defined(AWSS_SUPPORT_AHA)
#include "awss_aha.h"
#endif
#if defined(AWSS_SUPPORT_ADHA)
#include "awss_adha.h"
#endif
#if defined(WIFI_PROVISION_ENABLED) || defined(DEV_BIND_ENABLED)
#include "coap_api.h"
#include "iotx_coap.h"
#endif
#ifdef AWSS_SUPPORT_SMARTCONFIG_WPS
#include "p2p_wrapper.h"
#endif
#ifdef AWSS_SUPPORT_SMARTCONFIG
#include "smartconfig_wrapper.h"
#endif
#ifdef AWSS_SUPPORT_ZEROCONFIG
#include "zeroconfig_wrapper.h"
#endif
#ifdef AWSS_SUPPORT_AHA
#include "aha_wrapper.h"
#endif
#ifdef AWSS_SUPPORT_DEV_AP
#include "dev_ap_wrapper.h"
#endif

View File

@@ -0,0 +1,290 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#include "wifi_provision_internal.h"
#ifndef AWSS_DISABLE_ENROLLEE
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
const uint8_t probe_req_frame[ZC_PROBE_LEN] = {
0x40, 0x00, /* mgnt type, frame control */
0x00, 0x00, /* duration */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* DA */
0x28, 0xC2, 0xDD, 0x61, 0x68, 0x83, /* SA, to be replaced with wifi mac */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* BSSID */
0xC0, 0x79, /* seq */
0x00, 0x00, /* hide ssid, */
0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x8C, 0x92, 0x98, 0xA4, /* supported rates */
0x32, 0x04, 0xB0, 0x48, 0x60, 0x6C, /* extended supported rates */
0x3F, 0x84, 0x10, 0x9E /* FCS */
};
static uint8_t *g_dev_sign; /* pointer to dev_name_len start pos */
static uint8_t *g_product_key; /* pointer to model_len start pos */
static uint8_t *enrollee_frame;
static uint16_t enrollee_frame_len;
static int decrypt_ssid_passwd(uint8_t *ie, uint8_t ie_len,
uint8_t out_ssid[OS_MAX_SSID_LEN],
uint8_t out_passwd[OS_MAX_PASSWD_LEN],
uint8_t out_bssid[ETH_ALEN]);
void awss_init_enrollee_info(void) /* void enrollee_raw_frame_init(void) */
{
char *pk = NULL, *dev_name = NULL, *text = NULL;
uint8_t sign[ENROLLEE_SIGN_SIZE + 1] = {0};
char key[OS_DEVICE_SECRET_LEN + 1] = {0};
int dev_name_len, pk_len;
int len, ie_len;
if (enrollee_frame_len)
return;
dev_name = os_zalloc(OS_DEVICE_NAME_LEN + 1);
if (NULL == dev_name) {
return;
}
pk = os_zalloc(OS_PRODUCT_KEY_LEN + 1);
if (NULL == pk) {
HAL_Free(dev_name);
return;
}
HAL_GetProductKey(pk);
pk_len = strlen(pk);
HAL_GetDeviceName(dev_name);
dev_name_len = strlen(dev_name);
len = RANDOM_MAX_LEN + dev_name_len + pk_len;
text = os_zalloc(len + 1); /* +1 for string print */
awss_build_sign_src(text, &len);
if (awss_get_encrypt_type() == 3) { /* aes-key per product */
HAL_GetProductSecret(key);
} else { /* aes-key per device */
HAL_GetDeviceSecret(key);
}
produce_signature(sign, (uint8_t *)text, len, key);
HAL_Free(text);
ie_len = pk_len + dev_name_len + ENROLLEE_IE_FIX_LEN;
enrollee_frame_len = sizeof(probe_req_frame) + ie_len;
enrollee_frame = os_zalloc(enrollee_frame_len);
/* construct the enrollee frame right now */
len = sizeof(probe_req_frame) - FCS_SIZE;
memcpy(enrollee_frame, probe_req_frame, len);
enrollee_frame[len ++] = 221; /* vendor ie */
enrollee_frame[len ++] = ie_len - 2; /* exclude 221 & len */
enrollee_frame[len ++] = 0xD8;
enrollee_frame[len ++] = 0x96;
enrollee_frame[len ++] = 0xE0;
enrollee_frame[len ++] = 0xAA;/* OUI type */
enrollee_frame[len ++] = DEVICE_TYPE_VERSION;/* version & dev type */
enrollee_frame[len ++] = dev_name_len;/* dev name len*/
memcpy(&enrollee_frame[len], dev_name, dev_name_len);
len += dev_name_len;
enrollee_frame[len ++] = ENROLLEE_FRAME_TYPE;/* frame type */
g_product_key = &enrollee_frame[len]; /* pointer to pk len, see decrypt func */
enrollee_frame[len ++] = pk_len;
memcpy(&enrollee_frame[len], pk, pk_len);
len += pk_len;
enrollee_frame[len ++] = RANDOM_MAX_LEN;
memcpy(&enrollee_frame[len], aes_random, RANDOM_MAX_LEN);
len += RANDOM_MAX_LEN;
enrollee_frame[len ++] = awss_get_encrypt_type(); /*encrypt type */
enrollee_frame[len ++] = 0; /* signature method, 0: hmacsha1, 1: hmacsha256 */
enrollee_frame[len ++] = ENROLLEE_SIGN_SIZE; /* signature length */
g_dev_sign = &enrollee_frame[len];
memcpy(&enrollee_frame[len], sign, ENROLLEE_SIGN_SIZE);
len += ENROLLEE_SIGN_SIZE;
memcpy(&enrollee_frame[len],
&probe_req_frame[sizeof(probe_req_frame) - FCS_SIZE], FCS_SIZE);
/* update probe request frame src mac */
os_wifi_get_mac(enrollee_frame + SA_POS);
HAL_Free(pk);
HAL_Free(dev_name);
}
void awss_destroy_enrollee_info(void)
{
if (enrollee_frame_len) {
if (NULL != enrollee_frame) {
HAL_Free(enrollee_frame);
}
enrollee_frame_len = 0;
enrollee_frame = NULL;
g_dev_sign = NULL;
g_product_key = NULL;
}
}
void awss_broadcast_enrollee_info(void)
{
if (enrollee_frame_len == 0 || enrollee_frame == NULL)
return;
HAL_Wifi_Send_80211_Raw_Frame(FRAME_PROBE_REQ, enrollee_frame,
enrollee_frame_len);
}
/* return 0 for success, -1 dev_name not match, otherwise return -2 */
static int decrypt_ssid_passwd(
uint8_t *ie, uint8_t ie_len,
uint8_t out_ssid[OS_MAX_SSID_LEN],
uint8_t out_passwd[OS_MAX_PASSWD_LEN],
uint8_t out_bssid[ETH_ALEN])
{
uint8_t tmp_ssid[OS_MAX_SSID_LEN + 1] = {0}, tmp_passwd[OS_MAX_PASSWD_LEN + 1] = {0};
uint8_t *p_dev_name_sign = NULL, *p_ssid = NULL, *p_passwd = NULL, *p_bssid = NULL;
/* ignore ie hdr: 221, len, oui[3], type(0xAB) */
#define REGISTRAR_IE_HDR (6)
ie += REGISTRAR_IE_HDR;
if (ie[0] != DEVICE_TYPE_VERSION) {
awss_debug("registrar(devtype/ver=%d not supported!", ie[0]);
return -1;
}
ie ++; /* skip version */
p_dev_name_sign = ie;
if (!g_dev_sign || memcmp(g_dev_sign, p_dev_name_sign + 1, p_dev_name_sign[0])) {
p_dev_name_sign[p_dev_name_sign[0]] = '\0';
awss_debug("dev_name not match, expect:");
if (g_dev_sign) dump_hex(g_dev_sign, p_dev_name_sign[0], 16);
awss_debug("\r\nbut recv:");
dump_hex(p_dev_name_sign + 1, p_dev_name_sign[0], 16);
return -2;
}
ie += ie[0] + 1; /* eating device name sign length & device name sign[n] */
if (ie[0] != REGISTRAR_FRAME_TYPE) {
awss_debug("registrar(frametype=%d not supported!", ie[0]);
return -1;
}
ie ++; /* eating frame type */
p_ssid = ie;
if (ie[0] >= OS_MAX_SSID_LEN) {
awss_debug("registrar(ssidlen=%d invalid!", ie[0]);
return -1;
}
memcpy(tmp_ssid, &p_ssid[1], p_ssid[0]);
awss_debug("Registrar ssid:%s", tmp_ssid);
ie += ie[0] + 1; /* eating ssid_len & ssid[n] */
p_passwd = ie;
if (p_passwd[0] >= OS_MAX_PASSWD_LEN) {
awss_debug("registrar(passwdlen=%d invalid!", p_passwd[0]);
return -1;
}
ie += ie[0] + 1; /* eating passwd_len & passwd */
p_bssid = ie;
ie += ETH_ALEN; /* eating bssid len */
AWSS_UPDATE_STATIS(AWSS_STATIS_ZCONFIG_IDX, AWSS_STATIS_TYPE_TIME_START);
aes_decrypt_string((char *)p_passwd + 1, (char *)tmp_passwd, p_passwd[0],
1, awss_get_encrypt_type(), 0, (const char *)aes_random); /* aes128 cfb */
if (is_utf8((const char *)tmp_passwd, p_passwd[0]) != 1) {
awss_debug("registrar(passwd invalid!");
AWSS_UPDATE_STATIS(AWSS_STATIS_ZCONFIG_IDX, AWSS_STATIS_TYPE_PASSWD_ERR);
return -1;
}
awss_debug("ssid:%s\r\n", tmp_ssid);
strncpy((char *)out_passwd, (const char *)tmp_passwd, OS_MAX_PASSWD_LEN - 1);
strncpy((char *)out_ssid, (const char *)tmp_ssid, OS_MAX_SSID_LEN - 1);
memcpy((char *)out_bssid, (char *)p_bssid, ETH_ALEN);
return 0;/* success */
}
int awss_ieee80211_zconfig_process(uint8_t *mgmt_header, int len, int link_type, struct parser_res *res, signed char rssi)
{
const uint8_t *registrar_ie = NULL;
struct ieee80211_hdr *hdr;
uint16_t ieoffset;
int fc;
/*
* when device try to connect current router (include adha and aha)
* skip the new aha and process the new aha in the next scope.
*/
if (mgmt_header == NULL || zconfig_finished)
return ALINK_INVALID;
/*
* we don't process zconfig used by enrollee until user press configure button
*/
if (awss_get_config_press() == 0)
return ALINK_INVALID;
hdr = (struct ieee80211_hdr *)mgmt_header;
fc = hdr->frame_control;
if (!ieee80211_is_probe_req(fc) && !ieee80211_is_probe_resp(fc))
return ALINK_INVALID;
ieoffset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
if (ieoffset > len)
return ALINK_INVALID;
registrar_ie = (const uint8_t *)cfg80211_find_vendor_ie(WLAN_OUI_ALIBABA,
WLAN_OUI_TYPE_REGISTRAR, mgmt_header + ieoffset, len - ieoffset);
if (registrar_ie == NULL)
return ALINK_INVALID;
res->u.ie.alink_ie_len = len - (registrar_ie - mgmt_header);
res->u.ie.alink_ie = (uint8_t *)registrar_ie;
return ALINK_ZERO_CONFIG;
}
int awss_recv_callback_zconfig(struct parser_res *res)
{
uint8_t tods = res->tods;
uint8_t channel = res->channel;
uint8_t *ie = res->u.ie.alink_ie;
uint8_t ie_len = ie[1];
int ret;
if (res->u.ie.alink_ie_len < ie_len)
return PKG_INVALID;
ret = decrypt_ssid_passwd(ie, ie_len, zc_ssid, zc_passwd, zc_bssid);
if (ret)
return PKG_INVALID;
zconfig_set_state(STATE_RCV_DONE, tods, channel);
AWSS_UPDATE_STATIS(AWSS_STATIS_ROUTE_IDX, AWSS_STATIS_TYPE_TIME_SUC);
return PKG_END;
}
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,184 @@
/*
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
*/
#ifndef __AWSS_ENROLLEE_H__
#define __AWSS_ENROLLEE_H__
#include <stdint.h>
#include "infra_sha1.h"
#include "infra_sha256.h"
#include "passwd.h"
#include "os.h"
#include "zconfig_ieee80211.h"
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
extern "C"
{
#endif
/* enrollee/registrar doc see following
* http://docs.alibaba-inc.com/pages/viewpage.action?pageId=450855381
*/
/* ie oui def. */
#define WLAN_OUI_ALIBABA (0xD896E0)
#define WLAN_OUI_TYPE_ENROLLEE (0xAA)
#define WLAN_OUI_TYPE_REGISTRAR (0xAB)
#define DEVICE_TYPE_VERSION (1)
#define ENROLLEE_FRAME_TYPE (0)
#define REGISTRAR_FRAME_TYPE (1)
#define REGISTRAR_IDLE_DUTY (1)
struct ieee80211_enrollee_alibaba_ie {
uint8_t element_id; /* 221 */
uint8_t len; /* len of this struct, exclude element id & len field */
uint8_t oui[3]; /* D896E0 */
uint8_t oui_type; /* 0xAA, device request */
uint8_t version:4; /* bit7 - bit4 */
uint8_t dev_type:4; /* bit3 - bit0; alink=0, alink_cloud=1, yoc=8 */
uint8_t dn_len; /* device name length*/
#ifdef __GNUC__
uint8_t dev_name[0]; /* device name, unique name for device */
#endif
uint8_t frame_type; /* frame_type = 0 */
uint8_t pk_len; /* product key length */
#ifdef __GNUC__
uint8_t pk[0]; /* product key */
#endif
uint8_t rand_len; /* random length */
#ifdef __GNUC__
uint8_t random[0]; /* random salt */
#endif
uint8_t security; /* securation type, per product(3) or device(4) or manufacture(5) */
uint8_t sign_method; /* 0: hmacsha1, 1:hmacsha256 */
uint8_t sign_len; /* signature length */
#ifdef __GNUC__
uint8_t sign[0]; /* sign = hmacsha1(secret, random+dev_name+product_key) */
#endif
};
/* len = 17 + sign[n] + ssid[n] + passwd[n] */
struct ieee80211_registrar_alibaba_ie {
uint8_t element_id; /* 221 */
uint8_t len; /* len of this struct, exclude element id & len field */
uint8_t oui[3]; /* D896E0 */
uint8_t oui_type; /* 0xAB, device response */
uint8_t version:4; /* bit7 - bit4 */
uint8_t dev_type:4; /* bit3 - bit0; alink=0, alink_cloud=1, yoc=8 */
uint8_t sign_len; /* signature length */
#ifdef __GNUC__
uint8_t sign[0]; /* sign = hmacsha1(secret, random+dev_name+product_key)*/
#endif
uint8_t frame_type; /* frame_type = 0 */
uint8_t ssid_len; /* AP's SSID length */
#ifdef __GNUC__
uint8_t ssid[0]; /* SSID of AP */
#endif
uint8_t passwd_len; /* AP's PASSWORD length */
#ifdef __GNUC__
uint8_t passwd[0]; /* PASSWORD of AP */
#endif
uint8_t bssid[6]; /* BSSID of AP */
};
#define MAX_DEV_NAME_LEN (64)
#define MAX_PK_LEN (20)
#define MAX_KEY_LEN (32)
#define MAX_TOKEN_LEN (32)
#define ZC_PROBE_LEN (46)
#define ENROLLEE_SIGN_SIZE (SHA1_DIGEST_SIZE)
#define ENROLLEE_IE_FIX_LEN (sizeof(struct ieee80211_enrollee_alibaba_ie) + RANDOM_MAX_LEN + ENROLLEE_SIGN_SIZE)
#define REGISTRAR_IE_FIX_LEN (sizeof(struct ieee80211_registrar_alibaba_ie))
#define ENROLLEE_INFO_HDR_SIZE (ENROLLEE_IE_FIX_LEN - 6 + MAX_DEV_NAME_LEN + 1 + MAX_PK_LEN + 1)
#ifndef AWSS_DISABLE_REGISTRAR
struct enrollee_info {
uint8_t dev_type_ver;
uint8_t dev_name_len;
uint8_t dev_name[MAX_DEV_NAME_LEN + 1];
uint8_t frame_type;
uint8_t pk_len;
uint8_t pk[MAX_PK_LEN + 1];
uint8_t rand_len;
uint8_t random[RANDOM_MAX_LEN];
uint8_t security; /* encryption per product(3) or device(4) or manufacture(5) */
uint8_t sign_method; /* 0:hmacsha1, 1:hmacsha256 */
uint8_t sign_len;
uint8_t sign[ENROLLEE_SIGN_SIZE];
signed char rssi;
uint8_t key[MAX_KEY_LEN + 1]; /* aes key */
uint8_t state; /* free or not */
uint8_t checkin_priority; /* smaller means high pri */
uint32_t checkin_timestamp;
uint32_t report_timestamp;
uint32_t interval; /* report timeout */
uint32_t checkin_timeout;
};
#endif
/* registrar configuration */
#define MAX_ENROLLEE_NUM (5) /* Note: max enrollee num supported */
/*
* ENR_FREE --producer--> ENR_IN_QUEUE
* ENR_IN_QUEUE --cloud-----> ENR_CHECKIN_ENABLE
* ENR_CHECKIN_ENABLE --consumer--> ENR_CHECKIN_ONGOING --> ENR_CHECKIN_END/ENR_FREE
* *any state* --consumer--> ENR_FREE
*/
enum enrollee_state {
ENR_FREE = 0,
ENR_IN_QUEUE,
ENR_FOUND,
ENR_CHECKIN_ENABLE,
ENR_CHECKIN_CIPHER,
ENR_CHECKIN_ONGOING,
ENR_CHECKIN_END,
/* ENR_OUTOFDATE = 0 */
};
#define AES_KEY_LEN (16)
/* return 0 for success, -1 dev_name not match, otherwise return -2 */
extern const uint8_t probe_req_frame[ZC_PROBE_LEN];
#define SA_POS (10) /* source mac pos */
#define FCS_SIZE (4)
/* enrollee API */
#ifdef AWSS_DISABLE_ENROLLEE
#if 0
static inline void awss_init_enrollee_info(void) { }
static inline void awss_broadcast_enrollee_info(void) { }
static inline void awss_destroy_enrollee_info(void) { }
#endif
#else
void awss_init_enrollee_info(void);
void awss_broadcast_enrollee_info(void);
void awss_destroy_enrollee_info(void);
int awss_recv_callback_zconfig(struct parser_res *res);
int awss_ieee80211_zconfig_process(uint8_t *mgmt_header, int len, int link_type,
struct parser_res *res, signed char rssi);
#endif
/* registrar API */
#ifdef AWSS_DISABLE_REGISTRAR
#if 0
static inline void awss_registrar_deinit(void) { }
static inline void awss_registrar_init(void) { }
#endif
#else
void awss_registrar_init(void);
void awss_registrar_deinit(void);
#endif
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
}
#endif
#endif

View File

@@ -0,0 +1,67 @@
#include "infra_types.h"
#include "infra_defs.h"
#include "wrappers_defs.h"
/*************************************** common hals ***************************************/
int HAL_Timer_Stop(void *timer);
int HAL_Timer_Delete(void *timer);
void *HAL_Timer_Create(const char *name, void (*func)(void *), void *user_data);
int HAL_Timer_Start(void *timer, int ms);
void HAL_SleepMs(uint32_t ms);
void *HAL_Malloc(uint32_t size);
void HAL_MutexLock(void *mutex);
void HAL_MutexUnlock(void *mutex);
uint64_t HAL_UptimeMs(void);
void HAL_Free(void *ptr);
void *HAL_MutexCreate(void);
void HAL_MutexDestroy(void *mutex);
/*************************************** wifi provision frameworks hals ***************************************/
/* frameworks/awss.c*/
int HAL_Awss_Get_Timeout_Interval_Ms(void);
int HAL_Sys_Net_Is_Ready();
int HAL_Wifi_Get_Ap_Info(char ssid[HAL_MAX_SSID_LEN],char passwd[HAL_MAX_PASSWD_LEN],uint8_t bssid[ETH_ALEN]);
/* awss_crypt.c */
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN]);
int HAL_GetProductSecret(char *product_secret);
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN]);
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN]);
/* zconfig_vendor_common.c */
void HAL_Awss_Close_Monitor(void);
void HAL_Awss_Open_Monitor(_IN_ awss_recv_80211_frame_cb_t cb);
void HAL_Awss_Switch_Channel(char primary_channel, char secondary_channel, uint8_t bssid[ETH_ALEN]);
int HAL_Awss_Get_Channelscan_Interval_Ms(void);
p_HAL_Aes128_t HAL_Aes128_Init(
_IN_ const uint8_t *key,
_IN_ const uint8_t *iv,
_IN_ AES_DIR_t dir);
int HAL_Aes128_Destroy(_IN_ p_HAL_Aes128_t aes);
int HAL_Aes128_Cfb_Decrypt(
_IN_ p_HAL_Aes128_t aes,
_IN_ const void *src,
_IN_ size_t length,
_OU_ void *dst);
int HAL_Aes128_Cfb_Encrypt(
_IN_ p_HAL_Aes128_t aes,
_IN_ const void *src,
_IN_ size_t length,
_OU_ void *dst);
char *HAL_Wifi_Get_Mac(_OU_ char mac_str[HAL_MAC_LEN]);
int HAL_Awss_Connect_Ap(
_IN_ uint32_t connection_timeout_ms,
_IN_ char ssid[HAL_MAX_SSID_LEN],
_IN_ char passwd[HAL_MAX_PASSWD_LEN],
_IN_OPT_ enum AWSS_AUTH_TYPE auth,
_IN_OPT_ enum AWSS_ENC_TYPE encry,
_IN_OPT_ uint8_t bssid[ETH_ALEN],
_IN_OPT_ uint8_t channel);
/*************************************** zero-config special hals ***************************************/
int HAL_Wifi_Enable_Mgmt_Frame_Filter(
_IN_ uint32_t filter_mask,
_IN_OPT_ uint8_t vendor_oui[3],
_IN_ awss_wifi_mgmt_frame_cb_t callback);
int HAL_Wifi_Send_80211_Raw_Frame(_IN_ enum HAL_Awss_Frame_Type type,
_IN_ uint8_t *buffer, _IN_ int len);