esp8266-std/soft_ap/soft_ap.c

379 lines
14 KiB
C

/*
* ESPRSSIF MIT License
*
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "esp_common.h"
#include "espconn.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "soft_ap.h"
#include "log.h"
#include "user_main.h"
#include "sniffer.h"
#include "cfg.h"
static int g_isNetReady = FALSE;
#if 0
#define DEMO_AP_SSID "WT_TEST"
#define DEMO_AP_PASSWORD "1234567abc"
#define SOFT_AP_SSID "DEMO_AP"
#define SOFT_AP_PASSWORD "12345678"
void wifi_handle_event_cb(System_Event_t *evt)
{
printf("event %x\n", evt->event_id);
switch (evt->event_id) {
case EVENT_STAMODE_CONNECTED:
printf("connect to ssid %s, channel %d\n", evt->event_info.connected.ssid,
evt->event_info.connected.channel);
break;
case EVENT_STAMODE_DISCONNECTED:
printf("disconnect from ssid %s, reason %d\n", evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
printf("mode: %d -> %d\n", evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode);
break;
case EVENT_STAMODE_GOT_IP:
printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR, IP2STR(&evt->event_info.got_ip.ip),
IP2STR(&evt->event_info.got_ip.mask), IP2STR(&evt->event_info.got_ip.gw));
printf("\n");
break;
case EVENT_SOFTAPMODE_STACONNECTED:
printf("station: " MACSTR "join, AID = %d\n", MAC2STR(evt->event_info.sta_connected.mac),
evt->event_info.sta_connected.aid);
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
printf("station: " MACSTR "leave, AID = %d\n", MAC2STR(evt->event_info.sta_disconnected.mac),
evt->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
void conn_ap_init(void)
{
wifi_set_opmode(STATIONAP_MODE);
struct station_config config;
memset(&config,0,sizeof(config)); //set value of config from address of &config to width of size to be value '0'
sprintf(config.ssid, DEMO_AP_SSID);
sprintf(config.password, DEMO_AP_PASSWORD);
wifi_station_set_config(&config);
wifi_set_event_handler_cb(wifi_handle_event_cb);
wifi_station_connect();
}
#endif
void wifi_event_handler_cb(System_Event_t *evt)
{
if (evt == NULL) {
return;
}
//LOG_EX(LOG_Debug, "WIFI event = %d\n", evt->event_id);
switch (evt->event_id) {
case EVENT_STAMODE_CONNECTED:
LOG_EX(LOG_Debug, "connect to ssid %s, channel %d\n", evt->event_info.connected.ssid,
evt->event_info.connected.channel);
break;
case EVENT_STAMODE_DISCONNECTED:
LOG_EX(LOG_Debug, "disconnect from ssid %s, reason %d\n", evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
g_isNetReady = FALSE;
//wifi_station_connect();
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
LOG_EX(LOG_Debug, "mode: %d -> %d\n", evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode);
break;
case EVENT_STAMODE_GOT_IP:
LOG_EX(LOG_Debug, "ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR, IP2STR(&evt->event_info.got_ip.ip),
IP2STR(&evt->event_info.got_ip.mask), IP2STR(&evt->event_info.got_ip.gw));
//init_sntp();
g_isNetReady = TRUE;
break;
case EVENT_SOFTAPMODE_STACONNECTED:
LOG_EX(LOG_Debug, "station: " MACSTR "join, AID = %d\n", MAC2STR(evt->event_info.sta_connected.mac),
evt->event_info.sta_connected.aid);
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
LOG_EX(LOG_Debug, "station: " MACSTR "leave, AID = %d\n", MAC2STR(evt->event_info.sta_disconnected.mac),
evt->event_info.sta_disconnected.aid);
break;
default:
break;
}
}
os_timer_t channel_timer;
uint8 current_channel;
uint16 channel_bits;
os_timer_t check_sniffer;
os_timer_t check_sniffer_2;
SLIST_HEAD(router_info_head, router_info) router_list;
void ICACHE_FLASH_ATTR
sniffer_wifi_promiscuous_rx(uint8 *buf, uint16 buf_len)
{
uint8 *data;
uint16 i;
uint16 len;
uint16 cnt = 0;
if (buf_len == sizeof(struct RxControl)) {
struct RxControl * rxCtrl = (struct RxControl *) buf;
os_printf("[%sM%d%s] rssi%d, len%d\n", rxCtrl->CWB ? "H4" : "H2", rxCtrl->MCS, rxCtrl->FEC_CODING ? "L " : "",
rxCtrl->rssi, rxCtrl->HT_length);
return;
} else if (buf_len == sizeof(struct sniffer_buf2)) {
return; //manage pack
} else {
struct router_info *info = NULL;
struct sniffer_buf * sniffer = (struct sniffer_buf *) buf;
data = buf + sizeof(struct RxControl);
SLIST_FOREACH(info, &router_list, next)
{
if ((data[1] & 0x01) == 0x01) { // just toDS
if (memcmp(info->bssid, data + 4, 6) == 0) {
if (current_channel - 1 != info->channel) { // check channel
return;
} else {
break;
}
}
}
}
if (info == NULL) {
return;
}
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data;
if (sniffer->cnt == 1) {
len = sniffer->ampdu_info[0].length;
//get ieee80211_hdr/data len to do user task
os_printf("[len] %d, rssi %d\n", len, sniffer->rx_ctrl.rssi);
} else {
int i;
os_printf("rx ampdu %d\n", sniffer->cnt);
for (i = 0; i < sniffer->cnt; i++) {
hdr->seq_ctrl = sniffer->ampdu_info[i].seq;
memcpy(&hdr->addr3, sniffer->ampdu_info[i].address3, 6);
len = sniffer->ampdu_info[i].length;
//get ieee80211_hdr/data len to do user task
os_printf("[LEN] %d, RSSI %d\n", len, sniffer->rx_ctrl.rssi);
}
}
}
}
void ICACHE_FLASH_ATTR
sniffer_channel_timer_cb(void *arg)
{
uint8 i;
for (i = current_channel; i < 14; i++) {
if ((channel_bits & (1 << i)) != 0) {
current_channel = i + 1;
wifi_set_channel(i);
os_printf("current channel %d--------------------------------------------%d\n", i, system_get_time());
os_timer_arm(&channel_timer, 1000, 0);
break;
}
}
if (i == 14) {
current_channel = 1;
for (i = current_channel; i < 14; i++) {
if ((channel_bits & (1 << i)) != 0) {
current_channel = i + 1;
wifi_set_channel(i);
os_printf("current channel %d--------------------------------------------%d\n", i, system_get_time());
os_timer_arm(&channel_timer, 1000, 0);
break;
}
}
}
}
void ICACHE_FLASH_ATTR
sniffer_wifi_scan_done(void *arg, STATUS status)
{
uint8 ssid[33];
channel_bits = 0;
current_channel = 1;
struct router_info *info = NULL;
os_printf("%s(%d)\n", __FUNCTION__, __LINE__);
while ((info = SLIST_FIRST(&router_list)) != NULL) {
SLIST_REMOVE_HEAD(&router_list, next);
free(info);
}
os_printf("%s(%d)\n", __FUNCTION__, __LINE__);
if (status == OK) {
uint8 i;
struct bss_info *bss = (struct bss_info *) arg;
while (bss != NULL) {
if (bss->channel != 0) {
struct router_info *info = NULL;
os_printf("ssid %s, channel %d, authmode %d, rssi %d\n", bss->ssid, bss->channel, bss->authmode,
bss->rssi);
IHW_LOG_BUF(LOG_Debug, "***AP", bss->ssid, strlen(bss->ssid));
channel_bits |= 1 << (bss->channel);
info = (struct router_info *) malloc(sizeof(struct router_info));
info->authmode = bss->authmode;
info->channel = bss->channel;
memcpy(info->bssid, bss->bssid, 6);
SLIST_INSERT_HEAD(&router_list, info, next);
}
bss = STAILQ_NEXT(bss, next);
}
for (i = current_channel; i < 14; i++) {
if ((channel_bits & (1 << i)) != 0) {
current_channel = i + 1;
wifi_set_channel(i);
os_printf("current channel1 %d--------------------------------------------%d\n", i, system_get_time());
break;
}
}
wifi_set_channel(1);
wifi_promiscuous_enable(0);
wifi_set_promiscuous_rx_cb(sniffer_wifi_promiscuous_rx);
wifi_promiscuous_enable(1);
os_timer_disarm(&channel_timer);
os_timer_setfn(&channel_timer, sniffer_channel_timer_cb, NULL);
os_timer_arm(&channel_timer, 1000, 0);
} else {
os_printf("err, scan status %d\n", status);
}
os_printf("%s(%d)\n", __FUNCTION__, __LINE__);
}
void wifi_connect_ap(const char* pSSID, int lenSSID, const char* pPasswd, int lenPasswd)
{
char buf[24];
#if 0
wifi_set_opmode(STATION_MODE);
SLIST_INIT(&router_list);
if(wifi_station_scan(NULL,sniffer_wifi_scan_done)){
os_printf("wifi_station_scan ok\n");
}
return;
#endif
memset(buf, 0x3f, 24);
wifi_set_opmode(STATION_MODE);
wifi_set_event_handler_cb(wifi_event_handler_cb);
wifi_station_set_auto_connect(1);
if (pSSID && lenSSID > 0 && lenSSID < 32) {
struct station_config config;
//wifi_station_get_config(&config);
bzero(&config, sizeof(struct station_config));
memcpy(config.ssid, pSSID, lenSSID);
if (pPasswd && lenPasswd > 0 && lenPasswd < 64) {
memcpy(config.password, pPasswd, lenPasswd);
}
wifi_station_set_config(&config);
LOG_EX(LOG_Debug, "WIFI Conect: AP = [%s], Password = [%s]\n", pSSID, pPasswd);
IHW_LOG_BUF(LOG_Debug, "AP", (char*)pSSID, strlen(pSSID));
IHW_LOG_BUF(LOG_Debug, "PD", (char*)pPasswd, strlen(pPasswd));
wifi_station_connect();
}
else
{
LOG_EX(LOG_Debug, "WIFI Reconect......\n");
wifi_station_connect();
}
}
int soft_ap_network_ready(void)
{
return g_isNetReady;
}
void soft_ap_init(void)
{
u8_t mac[6];
uint8_t r_buf[] = {0x3c, 0xf3, 0xff, 0x07, 0x00, 0x03, 0x01, 0x00, 0x00, 0x02};
wifi_set_event_handler_cb(NULL);
wifi_set_opmode(STATIONAP_MODE);
struct softap_config *config = (struct softap_config *) zalloc(sizeof(struct softap_config)); // initialization
wifi_get_macaddr(SOFTAP_IF, mac);
wifi_softap_get_config(config); // Get soft-AP config first.
sprintf(config->ssid, USR_CFG_SOFTAP(SoftAPFormat), mac[4], mac[5]);
//sprintf(config->password, SOFT_AP_PASSWORD);
//config->authmode = AUTH_WPA_WPA2_PSK;
config->authmode = AUTH_OPEN;
config->ssid_len = 0; // or its actual SSID length
config->max_connection = 4;
wifi_softap_set_config(config); // Set ESP8266 soft-AP config
LOG_EX(LOG_Info, "SSID: [%s], AUTH = NONE\n", config->ssid);
free(config);
struct station_info * station = wifi_softap_get_station_info();
while (station) {
LOG_EX(LOG_Info, "bssid : MACSTR, ip : IPSTR/n", MAC2STR(station->bssid), IP2STR(&station->ip));
station = STAILQ_NEXT(station, next);
}
wifi_softap_free_station_info(); // Free it by calling functionss
wifi_softap_dhcps_stop(); // disable soft-AP DHCP server
struct ip_info info;
info.ip.addr = ipaddr_addr(USR_CFG_SOFTAP_DHCP(IPAddr));
info.gw.addr = ipaddr_addr(USR_CFG_SOFTAP_DHCP(Gatway));
info.netmask.addr = ipaddr_addr(USR_CFG_SOFTAP_DHCP(Netmask));
// IP4_ADDR(&info.ip, 192, 168, 5, 1); // set IP
// IP4_ADDR(&info.gw, 192, 168, 5, 1); // set gateway
// IP4_ADDR(&info.netmask, 255, 255, 255, 0); // set netmask
wifi_set_ip_info(SOFTAP_IF, &info);
struct dhcps_lease dhcp_lease;
dhcp_lease.start_ip.addr = ipaddr_addr(USR_CFG_SOFTAP_DHCP(DHCPStartIP));
dhcp_lease.end_ip.addr = ipaddr_addr(USR_CFG_SOFTAP_DHCP(DHCPEndIP));
// IP4_ADDR(&dhcp_lease.start_ip, 192, 168, 5, 100);
// IP4_ADDR(&dhcp_lease.end_ip, 192, 168, 5, 105);
wifi_softap_set_dhcps_lease(&dhcp_lease);
wifi_softap_dhcps_start(); // enable soft-AP DHCP server
ne_general_write(NULL, r_buf, sizeof(r_buf) / sizeof(r_buf[0]));
}