Initial commit
This commit is contained in:
310
user/acl.c
Normal file
310
user/acl.c
Normal file
@@ -0,0 +1,310 @@
|
||||
#include "c_types.h"
|
||||
#include "mem.h"
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "os_type.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
#include "user_interface.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "acl.h"
|
||||
|
||||
acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES];
|
||||
uint8_t acl_freep[MAX_NO_ACLS];
|
||||
uint32_t acl_allow_count;
|
||||
uint32_t acl_deny_count;
|
||||
static packet_deny_cb my_deny_cb;
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
acl_init()
|
||||
{
|
||||
int i;
|
||||
acl_allow_count = acl_deny_count = 0;
|
||||
my_deny_cb = NULL;
|
||||
for(i=0; i< MAX_NO_ACLS; i++)
|
||||
{
|
||||
acl_freep[i] = 0;
|
||||
acl_clear_stats(i);
|
||||
}
|
||||
}
|
||||
|
||||
bool ICACHE_FLASH_ATTR
|
||||
acl_is_empty(uint8_t acl_no)
|
||||
{
|
||||
if (acl_no >= MAX_NO_ACLS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return acl_freep[acl_no] == 0;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
acl_clear(uint8_t acl_no)
|
||||
{
|
||||
if (acl_no >= MAX_NO_ACLS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
acl_freep[acl_no] = 0;
|
||||
acl_clear_stats(acl_no);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
acl_clear_stats(uint8_t acl_no)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (acl_no >= MAX_NO_ACLS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
my_deny_cb = NULL;
|
||||
for(i=0; i< MAX_ACL_ENTRIES; i++)
|
||||
acl[acl_no][i].hit_count = 0;
|
||||
}
|
||||
|
||||
bool ICACHE_FLASH_ATTR
|
||||
acl_add(uint8_t acl_no,
|
||||
uint32_t src,
|
||||
uint32_t s_mask,
|
||||
uint32_t dest,
|
||||
uint32_t d_mask,
|
||||
uint8_t proto,
|
||||
uint16_t s_port,
|
||||
uint16_t d_port,
|
||||
uint8_t allow)
|
||||
{
|
||||
acl_entry *my_entry;
|
||||
|
||||
if (acl_no >= MAX_NO_ACLS || acl_freep[acl_no] >= MAX_ACL_ENTRIES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
my_entry = &acl[acl_no][acl_freep[acl_no]];
|
||||
my_entry->src = src & s_mask;
|
||||
my_entry->s_mask = s_mask;
|
||||
my_entry->dest = dest & d_mask;
|
||||
my_entry->d_mask = d_mask;
|
||||
my_entry->proto = proto;
|
||||
my_entry->s_port = s_port;
|
||||
my_entry->d_port = d_port;
|
||||
my_entry->allow = allow;
|
||||
my_entry->hit_count = 0;
|
||||
|
||||
acl_freep[acl_no]++;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t ICACHE_FLASH_ATTR
|
||||
acl_check_packet(uint8_t acl_no, struct pbuf *p)
|
||||
{
|
||||
struct eth_hdr *mac_h;
|
||||
struct ip_hdr *ip_h;
|
||||
uint8_t proto;
|
||||
struct udp_hdr *udp_h;
|
||||
struct tcp_hdr *tcp_h;
|
||||
uint16_t src_port, dest_port;
|
||||
uint8_t *packet;
|
||||
int i;
|
||||
acl_entry *my_entry;
|
||||
uint8_t allow;
|
||||
|
||||
if (acl_no >= MAX_NO_ACLS)
|
||||
{
|
||||
return ACL_DENY;
|
||||
}
|
||||
|
||||
if (p->len < sizeof(struct eth_hdr))
|
||||
{
|
||||
return ACL_DENY;
|
||||
}
|
||||
|
||||
mac_h = (struct eth_hdr *)p->payload;
|
||||
|
||||
// Allow ARP
|
||||
if (ntohs(mac_h->type) == ETHTYPE_ARP)
|
||||
{
|
||||
acl_allow_count++;
|
||||
return ACL_ALLOW;
|
||||
}
|
||||
|
||||
// Drop anything else if not IPv4
|
||||
if (ntohs(mac_h->type) != ETHTYPE_IP)
|
||||
{
|
||||
acl_deny_count++;
|
||||
return ACL_DENY;
|
||||
}
|
||||
|
||||
if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr))
|
||||
{
|
||||
acl_deny_count++;
|
||||
return ACL_DENY;
|
||||
}
|
||||
|
||||
allow = ACL_DENY;
|
||||
packet = (uint8_t*)p->payload;
|
||||
ip_h = (struct ip_hdr *)&packet[sizeof(struct eth_hdr)];
|
||||
proto = IPH_PROTO(ip_h);
|
||||
|
||||
switch (proto) {
|
||||
case IP_PROTO_UDP:
|
||||
{
|
||||
if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct udp_hdr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
udp_h = (struct udp_hdr *)&packet[sizeof(struct eth_hdr)+sizeof(struct ip_hdr)];
|
||||
src_port = ntohs(udp_h->src);
|
||||
dest_port = ntohs(udp_h->dest);
|
||||
} break;
|
||||
|
||||
case IP_PROTO_TCP:
|
||||
{
|
||||
if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct tcp_hdr))
|
||||
{
|
||||
return;
|
||||
}
|
||||
tcp_h = (struct tcp_hdr *)&packet[sizeof(struct eth_hdr)+sizeof(struct ip_hdr)];
|
||||
src_port = ntohs(tcp_h->src);
|
||||
dest_port = ntohs(tcp_h->dest);
|
||||
} break;
|
||||
|
||||
case IP_PROTO_ICMP:
|
||||
{
|
||||
src_port = dest_port = 0;
|
||||
} break;
|
||||
|
||||
// Drop anything that is not UDP, TCP, or ICMP
|
||||
default:
|
||||
{
|
||||
acl_deny_count++;
|
||||
return ACL_DENY;
|
||||
} break;
|
||||
}
|
||||
|
||||
// os_printf("Src: %d.%d.%d.%d Dst: %d.%d.%d.%d Proto: %s SP:%d DP:%d\n",
|
||||
// IP2STR(&ip_h->src), IP2STR(&ip_h->dest),
|
||||
// proto==IP_PROTO_TCP?"TCP":proto==IP_PROTO_UDP?"UDP":"IP4", src_port, dest_port);
|
||||
|
||||
for(i=0; i<acl_freep[acl_no]; i++)
|
||||
{
|
||||
my_entry = &acl[acl_no][i];
|
||||
if ((my_entry->proto == 0 || proto == my_entry->proto) &&
|
||||
(my_entry->src == 0 || my_entry->src == (ip_h->src.addr&my_entry->s_mask)) &&
|
||||
(my_entry->dest == 0 || my_entry->dest == (ip_h->dest.addr&my_entry->d_mask)) &&
|
||||
(my_entry->s_port == 0 || my_entry->s_port == src_port) &&
|
||||
(my_entry->d_port == 0 || my_entry->d_port == dest_port))
|
||||
{
|
||||
allow = my_entry->allow;
|
||||
my_entry->hit_count++;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (!(allow & ACL_ALLOW) && my_deny_cb != NULL)
|
||||
{
|
||||
allow = my_deny_cb(proto, ip_h->src.addr, src_port,
|
||||
ip_h->dest.addr, dest_port, allow);
|
||||
}
|
||||
if (allow & ACL_ALLOW)
|
||||
{
|
||||
acl_allow_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
acl_deny_count++;
|
||||
}
|
||||
|
||||
// os_printf(" allow: %d\r\n", allow);
|
||||
return allow;
|
||||
}
|
||||
|
||||
void
|
||||
acl_set_deny_cb(packet_deny_cb cb)
|
||||
{
|
||||
my_deny_cb = cb;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
addr2str(uint8_t *buf, uint32_t addr, uint32_t mask)
|
||||
{
|
||||
uint8_t clidr;
|
||||
|
||||
if (addr == 0)
|
||||
{
|
||||
os_sprintf(buf, "any");
|
||||
return;
|
||||
}
|
||||
|
||||
mask = ntohl(mask);
|
||||
for (clidr = 0; mask; mask <<= 1,clidr++);
|
||||
if (clidr < 32)
|
||||
{
|
||||
os_sprintf(buf, "%d.%d.%d.%d/%d", IP2STR((ip_addr_t*)&addr), clidr);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sprintf(buf, "%d.%d.%d.%d", IP2STR((ip_addr_t*)&addr));
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
port2str(uint8_t *buf, uint16_t port)
|
||||
{
|
||||
if (port == 0)
|
||||
{
|
||||
os_sprintf(buf, "any");
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sprintf(buf, "%d", port);
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
acl_show(uint8_t acl_no, uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
acl_entry *my_entry;
|
||||
uint8_t line[80], addr1[21], addr2[21], port1[6], port2[6];
|
||||
|
||||
buf[0] = 0;
|
||||
|
||||
if (acl_no >= MAX_NO_ACLS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; i < acl_freep[acl_no]; i++)
|
||||
{
|
||||
my_entry = &acl[acl_no][i];
|
||||
addr2str(addr1, my_entry->src, my_entry->s_mask);
|
||||
port2str(port1, my_entry->s_port);
|
||||
addr2str(addr2, my_entry->dest, my_entry->d_mask);
|
||||
port2str(port2, my_entry->d_port);
|
||||
if (my_entry->proto != 0)
|
||||
{
|
||||
os_sprintf(line, "%s %s:%s %s:%s %s%s (%d hits)\r\n",
|
||||
my_entry->proto==IP_PROTO_TCP?"TCP":"UDP",
|
||||
addr1, port1, addr2, port2,
|
||||
(my_entry->allow & ACL_ALLOW)?"allow":"deny",
|
||||
(my_entry->allow & ACL_MONITOR)?"_monitor":"",
|
||||
my_entry->hit_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_sprintf(line, "IP %s %s %s%s (%d hits)\r\n",
|
||||
addr1, addr2,
|
||||
(my_entry->allow & ACL_ALLOW)?"allow":"deny",
|
||||
(my_entry->allow & ACL_MONITOR)?"_monitor":"",
|
||||
my_entry->hit_count);
|
||||
}
|
||||
os_memcpy(&buf[os_strlen(buf)], line, os_strlen(line)+1);
|
||||
}
|
||||
}
|
||||
51
user/acl.h
Normal file
51
user/acl.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef _ACL_H_
|
||||
#define _ACL_H_
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#define MAX_NO_ACLS 4
|
||||
#define MAX_ACL_ENTRIES 16
|
||||
|
||||
#define ACL_DENY 0x0
|
||||
#define ACL_ALLOW 0x1
|
||||
#define ACL_MONITOR 0x2
|
||||
|
||||
typedef struct _acl_entry
|
||||
{
|
||||
uint32_t src;
|
||||
uint32_t s_mask;
|
||||
uint32_t dest;
|
||||
uint32_t d_mask;
|
||||
uint16_t s_port;
|
||||
uint16_t d_port;
|
||||
uint8_t proto;
|
||||
uint8_t allow;
|
||||
uint32_t hit_count;
|
||||
} acl_entry;
|
||||
|
||||
extern acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES];
|
||||
extern uint8_t acl_freep[MAX_NO_ACLS];
|
||||
extern uint32_t acl_allow_count;
|
||||
extern uint32_t acl_deny_count;
|
||||
|
||||
typedef uint8_t (*packet_deny_cb)(uint8_t proto, uint32_t saddr, uint16_t s_port, uint32_t daddr, uint16_t d_port, uint8_t allow);
|
||||
|
||||
void acl_init();
|
||||
bool acl_is_empty(uint8_t acl_no);
|
||||
void acl_clear(uint8_t acl_no);
|
||||
void acl_clear_stats(uint8_t acl_no);
|
||||
bool acl_add(uint8_t acl_no,
|
||||
uint32_t src,
|
||||
uint32_t s_mask,
|
||||
uint32_t dest,
|
||||
uint32_t d_mask,
|
||||
uint8_t proto,
|
||||
uint16_t s_port,
|
||||
uint16_t d_port,
|
||||
uint8_t allow);
|
||||
uint8_t acl_check_packet(uint8_t acl_no, struct pbuf *p);
|
||||
void acl_set_deny_cb(packet_deny_cb cb);
|
||||
void acl_show(uint8_t acl_no, uint8_t *buf);
|
||||
|
||||
#endif /* _ACL_H_ */
|
||||
153
user/config_flash.c
Normal file
153
user/config_flash.c
Normal file
@@ -0,0 +1,153 @@
|
||||
#include "user_interface.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "config_flash.h"
|
||||
|
||||
|
||||
/* From the document 99A-SDK-Espressif IOT Flash RW Operation_v0.2 *
|
||||
* -------------------------------------------------------------------------*
|
||||
* Flash is erased sector by sector, which means it has to erase 4Kbytes one
|
||||
* time at least. When you want to change some data in flash, you have to
|
||||
* erase the whole sector, and then write it back with the new data.
|
||||
*--------------------------------------------------------------------------*/
|
||||
void
|
||||
config_load_default(sysconfig_p config)
|
||||
{
|
||||
uint8_t mac[6];
|
||||
|
||||
wifi_get_macaddr(STATION_IF, mac);
|
||||
|
||||
os_memset(config, 0, sizeof(sysconfig_t));
|
||||
os_printf("Loading default configuration\r\n");
|
||||
config->magic_number = MAGIC_NUMBER;
|
||||
config->length = sizeof(sysconfig_t);
|
||||
os_sprintf(config->ssid,"%s", WIFI_SSID);
|
||||
os_sprintf(config->password,"%s", WIFI_PASSWORD);
|
||||
config->auto_connect = 0;
|
||||
os_memset(config->bssid, 0, 6);
|
||||
os_sprintf(config->sta_hostname, "ESP_%02x%02x%02x", mac[3], mac[4], mac[5]);
|
||||
os_sprintf(config->ap_ssid,"%s", WIFI_AP_SSID);
|
||||
|
||||
config->first_run = 1;
|
||||
config->ap_watchdog = -1;
|
||||
config->client_watchdog = -1;
|
||||
|
||||
IP4_ADDR(&config->network_addr, 192, 168, 4, 1);
|
||||
config->dns_addr.addr = 0; // use DHCP
|
||||
config->my_addr.addr = 0; // use DHCP
|
||||
config->my_netmask.addr = 0; // use DHCP
|
||||
config->my_gw.addr = 0; // use DHCP
|
||||
#ifdef PHY_MODE
|
||||
config->phy_mode = 3; // mode n
|
||||
#endif
|
||||
config->clock_speed = 80;
|
||||
config->status_led = STATUS_LED_GPIO;
|
||||
|
||||
wifi_get_macaddr(STATION_IF, config->STA_MAC_address);
|
||||
|
||||
config->dhcps_entries = 0;
|
||||
#ifdef ACLS
|
||||
acl_init(); // initializes the ACLs, written in config during save
|
||||
#endif
|
||||
|
||||
config->current_mac_address = 0;
|
||||
// Interval to change mac address in seconds
|
||||
// Default: 28800 (8 hours)
|
||||
config->mac_change_interval = 600;
|
||||
|
||||
// list of mac addresses
|
||||
// from https://docs.google.com/spreadsheets/d/1su5u-vPrQwkTixR6YnOTWSi_Ls9lV-_XNJHaWIJspv4/edit#gid=0
|
||||
ets_str2macaddr(config->mac_list[0], "4E:53:50:4F:4F:40");
|
||||
ets_str2macaddr(config->mac_list[1], "4E:53:50:4F:4F:41");
|
||||
ets_str2macaddr(config->mac_list[2], "4E:53:50:4F:4F:42");
|
||||
ets_str2macaddr(config->mac_list[3], "4E:53:50:4F:4F:43");
|
||||
ets_str2macaddr(config->mac_list[4], "4E:53:50:4F:4F:44");
|
||||
ets_str2macaddr(config->mac_list[5], "4E:53:50:4F:4F:45");
|
||||
ets_str2macaddr(config->mac_list[6], "4E:53:50:4F:4F:46");
|
||||
ets_str2macaddr(config->mac_list[7], "4E:53:50:4F:4F:47");
|
||||
ets_str2macaddr(config->mac_list[8], "4E:53:50:4F:4F:48");
|
||||
ets_str2macaddr(config->mac_list[9], "4E:53:50:4F:4F:49");
|
||||
ets_str2macaddr(config->mac_list[10], "4E:53:50:4F:4F:4A");
|
||||
ets_str2macaddr(config->mac_list[11], "4E:53:50:4F:4F:4B");
|
||||
ets_str2macaddr(config->mac_list[12], "4E:53:50:4F:4F:4C");
|
||||
ets_str2macaddr(config->mac_list[13], "4E:53:50:4F:4F:4D");
|
||||
ets_str2macaddr(config->mac_list[14], "4E:53:50:4F:4F:4E");
|
||||
ets_str2macaddr(config->mac_list[15], "4E:53:50:4F:4F:4F");
|
||||
}
|
||||
|
||||
int
|
||||
config_load(sysconfig_p config)
|
||||
{
|
||||
if (config == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
uint16_t base_address = FLASH_BLOCK_NO;
|
||||
|
||||
spi_flash_read(base_address* SPI_FLASH_SEC_SIZE, &config->magic_number, 4);
|
||||
|
||||
if((config->magic_number != MAGIC_NUMBER))
|
||||
{
|
||||
os_printf("\r\nNo config found, saving default in flash\r\n");
|
||||
config_load_default(config);
|
||||
config_save(config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
os_printf("\r\nConfig found and loaded\r\n");
|
||||
spi_flash_read(base_address * SPI_FLASH_SEC_SIZE,
|
||||
(uint32 *) config,
|
||||
sizeof(sysconfig_t));
|
||||
if (config->length != sizeof(sysconfig_t))
|
||||
{
|
||||
os_printf("Length Mismatch, probably old version of config, loading defaults\r\n");
|
||||
config_load_default(config);
|
||||
config_save(config);
|
||||
return -1;
|
||||
}
|
||||
#ifdef ACLS
|
||||
os_memcpy(&acl, &(config->acl), sizeof(acl));
|
||||
os_memcpy(&acl_freep, &(config->acl_freep), sizeof(acl_freep));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
config_save(sysconfig_p config)
|
||||
{
|
||||
uint16_t base_address = FLASH_BLOCK_NO;
|
||||
#ifdef ACLS
|
||||
os_memcpy(&(config->acl), &acl, sizeof(acl));
|
||||
os_memcpy(&(config->acl_freep), &acl_freep, sizeof(acl_freep));
|
||||
#endif
|
||||
os_printf("Saving configuration\r\n");
|
||||
spi_flash_erase_sector(base_address);
|
||||
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE,
|
||||
(uint32 *)config,
|
||||
sizeof(sysconfig_t));
|
||||
}
|
||||
|
||||
void
|
||||
blob_save(uint8_t blob_no, uint32_t *data, uint16_t len)
|
||||
{
|
||||
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
|
||||
spi_flash_erase_sector(base_address);
|
||||
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
blob_load(uint8_t blob_no, uint32_t *data, uint16_t len)
|
||||
{
|
||||
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
|
||||
spi_flash_read(base_address * SPI_FLASH_SEC_SIZE, data, len);
|
||||
}
|
||||
|
||||
void
|
||||
blob_zero(uint8_t blob_no, uint16_t len)
|
||||
{
|
||||
int i;
|
||||
uint8_t z[len];
|
||||
os_memset(z, 0,len);
|
||||
uint16_t base_address = FLASH_BLOCK_NO + 1 + blob_no;
|
||||
spi_flash_erase_sector(base_address);
|
||||
spi_flash_write(base_address * SPI_FLASH_SEC_SIZE, (uint32_t *)z, len);
|
||||
}
|
||||
81
user/config_flash.h
Normal file
81
user/config_flash.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef _CONFIG_FLASH_H_
|
||||
#define _CONFIG_FLASH_H_
|
||||
|
||||
#include "c_types.h"
|
||||
#include "mem.h"
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "gpio.h"
|
||||
#include "os_type.h"
|
||||
#include "spi_flash.h"
|
||||
#include "lwip/app/dhcpserver.h"
|
||||
|
||||
#include "user_config.h"
|
||||
#include "acl.h"
|
||||
|
||||
#define FLASH_BLOCK_NO 0xc
|
||||
|
||||
#define MAGIC_NUMBER 0x112005fc
|
||||
|
||||
#define MAX_MAC_LIST_LENGTH 15
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// To check if the structure is initialized or not in flash
|
||||
uint32_t magic_number;
|
||||
|
||||
// Length of the structure, since this is a evolving library,
|
||||
// the variant may change hence used for verification
|
||||
uint16_t length;
|
||||
|
||||
/* Below variables are specific to my code */
|
||||
uint8_t ssid[32]; // SSID of the AP to connect to
|
||||
uint8_t password[64]; // Password of the network
|
||||
uint8_t auto_connect; // Should we auto connect
|
||||
uint8_t bssid[6]; // Optional: BSSID the AP
|
||||
uint8_t sta_hostname[32]; // Name of the station
|
||||
uint8_t ap_ssid[32]; // SSID of the own AP
|
||||
uint8_t first_run; // Has ESPerPass been configured yet?
|
||||
uint8_t current_mac_address; // Holds currently broadcasted HomePass mac address index
|
||||
int32_t mac_change_interval; // Interval to rotate HomePass mac address (in seconds)
|
||||
|
||||
// Seconds without ap traffic will cause reset (-1 off, default)
|
||||
int32_t ap_watchdog;
|
||||
// Seconds without client traffic will cause reset (-1 off, default)
|
||||
int32_t client_watchdog;
|
||||
|
||||
ip_addr_t network_addr; // Address of the internal network
|
||||
ip_addr_t dns_addr; // Optional: address of the dns server
|
||||
|
||||
ip_addr_t my_addr; // Optional (if not DHCP): IP address of the uplink side
|
||||
ip_addr_t my_netmask; // Optional (if not DHCP): IP netmask of the uplink side
|
||||
ip_addr_t my_gw; // Optional (if not DHCP): Gateway of the uplink side
|
||||
#ifdef PHY_MODE
|
||||
uint16_t phy_mode; // WiFi PHY mode
|
||||
#endif
|
||||
uint16_t clock_speed; // Freq of the CPU
|
||||
uint16_t status_led; // GPIO pin os the status LED (>16 disabled)
|
||||
|
||||
uint8_t STA_MAC_address[6]; // MAC address of the STA
|
||||
|
||||
uint16_t dhcps_entries; // number of allocated entries in the following table
|
||||
struct dhcps_pool dhcps_p[MAX_DHCP]; // DHCP entries
|
||||
#ifdef ACLS
|
||||
acl_entry acl[MAX_NO_ACLS][MAX_ACL_ENTRIES]; // ACL entries
|
||||
uint8_t acl_freep[MAX_NO_ACLS]; // ACL free pointers
|
||||
#endif
|
||||
|
||||
// HomePass mac list
|
||||
// Allow 20 slots
|
||||
uint8_t mac_list[19][6];
|
||||
|
||||
} sysconfig_t, *sysconfig_p;
|
||||
|
||||
int config_load(sysconfig_p config);
|
||||
void config_save(sysconfig_p config);
|
||||
|
||||
void blob_save(uint8_t blob_no, uint32_t *data, uint16_t len);
|
||||
void blob_load(uint8_t blob_no, uint32_t *data, uint16_t len);
|
||||
void blob_zero(uint8_t blob_no, uint16_t len);
|
||||
|
||||
#endif
|
||||
250
user/ringbuf.c
Normal file
250
user/ringbuf.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* ringbuf.c - C ring buffer (FIFO) implementation.
|
||||
*
|
||||
* Written in 2011 by Drew Hess <dhess-src@bothan.net>.
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to
|
||||
* the public domain worldwide. This software is distributed without
|
||||
* any warranty.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication
|
||||
* along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
#include "ringbuf.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
|
||||
#define assert(x)
|
||||
|
||||
/*
|
||||
* The code is written for clarity, not cleverness or performance, and
|
||||
* contains many assert()s to enforce invariant assumptions and catch
|
||||
* bugs. Feel free to optimize the code and to remove asserts for use
|
||||
* in your own projects, once you're comfortable that it functions as
|
||||
* intended.
|
||||
*/
|
||||
|
||||
struct ringbuf_t
|
||||
{
|
||||
uint8_t *buf;
|
||||
uint8_t *head, *tail;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
ringbuf_t
|
||||
ringbuf_new(size_t capacity)
|
||||
{
|
||||
ringbuf_t rb = (ringbuf_t)os_malloc(sizeof(struct ringbuf_t));
|
||||
if (rb) {
|
||||
|
||||
/* One byte is used for detecting the full condition. */
|
||||
rb->size = capacity + 1;
|
||||
rb->buf = (uint8_t *)os_malloc(rb->size);
|
||||
if (rb->buf)
|
||||
ringbuf_reset(rb);
|
||||
else {
|
||||
os_free(rb);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rb;
|
||||
}
|
||||
|
||||
size_t
|
||||
ringbuf_buffer_size(const struct ringbuf_t *rb)
|
||||
{
|
||||
return rb->size;
|
||||
}
|
||||
|
||||
void
|
||||
ringbuf_reset(ringbuf_t rb)
|
||||
{
|
||||
rb->head = rb->tail = rb->buf;
|
||||
}
|
||||
|
||||
void
|
||||
ringbuf_free(ringbuf_t *rb)
|
||||
{
|
||||
assert(rb && *rb);
|
||||
os_free((*rb)->buf);
|
||||
os_free(*rb);
|
||||
*rb = 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
ringbuf_capacity(const struct ringbuf_t *rb)
|
||||
{
|
||||
return ringbuf_buffer_size(rb) - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a pointer to one-past-the-end of the ring buffer's
|
||||
* contiguous buffer. You shouldn't normally need to use this function
|
||||
* unless you're writing a new ringbuf_* function.
|
||||
*/
|
||||
static const uint8_t *
|
||||
ringbuf_end(const struct ringbuf_t *rb)
|
||||
{
|
||||
return rb->buf + ringbuf_buffer_size(rb);
|
||||
}
|
||||
|
||||
size_t
|
||||
ringbuf_bytes_free(const struct ringbuf_t *rb)
|
||||
{
|
||||
if (rb->head >= rb->tail)
|
||||
return ringbuf_capacity(rb) - (rb->head - rb->tail);
|
||||
else
|
||||
return rb->tail - rb->head - 1;
|
||||
}
|
||||
|
||||
size_t
|
||||
ringbuf_bytes_used(const struct ringbuf_t *rb)
|
||||
{
|
||||
return ringbuf_capacity(rb) - ringbuf_bytes_free(rb);
|
||||
}
|
||||
|
||||
int
|
||||
ringbuf_is_full(const struct ringbuf_t *rb)
|
||||
{
|
||||
return ringbuf_bytes_free(rb) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
ringbuf_is_empty(const struct ringbuf_t *rb)
|
||||
{
|
||||
return ringbuf_bytes_free(rb) == ringbuf_capacity(rb);
|
||||
}
|
||||
|
||||
const void *
|
||||
ringbuf_tail(const struct ringbuf_t *rb)
|
||||
{
|
||||
return rb->tail;
|
||||
}
|
||||
|
||||
const void *
|
||||
ringbuf_head(const struct ringbuf_t *rb)
|
||||
{
|
||||
return rb->head;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a ring buffer rb and a pointer to a location within its
|
||||
* contiguous buffer, return the a pointer to the next logical
|
||||
* location in the ring buffer.
|
||||
*/
|
||||
static uint8_t *
|
||||
ringbuf_nextp(ringbuf_t rb, const uint8_t *p)
|
||||
{
|
||||
/*
|
||||
* The assert guarantees the expression (++p - rb->buf) is
|
||||
* non-negative; therefore, the modulus operation is safe and
|
||||
* portable.
|
||||
*/
|
||||
assert((p >= rb->buf) && (p < ringbuf_end(rb)));
|
||||
return rb->buf + ((++p - rb->buf) % ringbuf_buffer_size(rb));
|
||||
}
|
||||
|
||||
void *
|
||||
ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count)
|
||||
{
|
||||
const uint8_t *u8src = src;
|
||||
const uint8_t *bufend = ringbuf_end(dst);
|
||||
int overflow = count > ringbuf_bytes_free(dst);
|
||||
size_t nread = 0;
|
||||
|
||||
while (nread != count) {
|
||||
/* don't copy beyond the end of the buffer */
|
||||
assert(bufend > dst->head);
|
||||
size_t n = MIN(bufend - dst->head, count - nread);
|
||||
os_memcpy(dst->head, u8src + nread, n);
|
||||
dst->head += n;
|
||||
nread += n;
|
||||
|
||||
/* wrap? */
|
||||
if (dst->head == bufend)
|
||||
dst->head = dst->buf;
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
dst->tail = ringbuf_nextp(dst, dst->head);
|
||||
assert(ringbuf_is_full(dst));
|
||||
}
|
||||
|
||||
return dst->head;
|
||||
}
|
||||
|
||||
void *
|
||||
ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count)
|
||||
{
|
||||
size_t bytes_used = ringbuf_bytes_used(src);
|
||||
if (count > bytes_used)
|
||||
return 0;
|
||||
|
||||
uint8_t *u8dst = dst;
|
||||
const uint8_t *bufend = ringbuf_end(src);
|
||||
size_t nwritten = 0;
|
||||
while (nwritten != count) {
|
||||
assert(bufend > src->tail);
|
||||
size_t n = MIN(bufend - src->tail, count - nwritten);
|
||||
os_memcpy(u8dst + nwritten, src->tail, n);
|
||||
src->tail += n;
|
||||
nwritten += n;
|
||||
|
||||
/* wrap ? */
|
||||
if (src->tail == bufend)
|
||||
src->tail = src->buf;
|
||||
}
|
||||
|
||||
assert(count + ringbuf_bytes_used(src) == bytes_used);
|
||||
return src->tail;
|
||||
}
|
||||
|
||||
void *
|
||||
ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count)
|
||||
{
|
||||
size_t src_bytes_used = ringbuf_bytes_used(src);
|
||||
if (count > src_bytes_used)
|
||||
return 0;
|
||||
int overflow = count > ringbuf_bytes_free(dst);
|
||||
|
||||
const uint8_t *src_bufend = ringbuf_end(src);
|
||||
const uint8_t *dst_bufend = ringbuf_end(dst);
|
||||
size_t ncopied = 0;
|
||||
while (ncopied != count) {
|
||||
assert(src_bufend > src->tail);
|
||||
size_t nsrc = MIN(src_bufend - src->tail, count - ncopied);
|
||||
assert(dst_bufend > dst->head);
|
||||
size_t n = MIN(dst_bufend - dst->head, nsrc);
|
||||
os_memcpy(dst->head, src->tail, n);
|
||||
src->tail += n;
|
||||
dst->head += n;
|
||||
ncopied += n;
|
||||
|
||||
/* wrap ? */
|
||||
if (src->tail == src_bufend)
|
||||
src->tail = src->buf;
|
||||
if (dst->head == dst_bufend)
|
||||
dst->head = dst->buf;
|
||||
}
|
||||
|
||||
assert(count + ringbuf_bytes_used(src) == src_bytes_used);
|
||||
|
||||
if (overflow) {
|
||||
dst->tail = ringbuf_nextp(dst, dst->head);
|
||||
assert(ringbuf_is_full(dst));
|
||||
}
|
||||
|
||||
return dst->head;
|
||||
}
|
||||
|
||||
167
user/ringbuf.h
Normal file
167
user/ringbuf.h
Normal file
@@ -0,0 +1,167 @@
|
||||
#ifndef INCLUDED_RINGBUF_H
|
||||
#define INCLUDED_RINGBUF_H
|
||||
|
||||
/*
|
||||
* ringbuf.h - C ring buffer (FIFO) interface.
|
||||
*
|
||||
* Written in 2011 by Drew Hess <dhess-src@bothan.net>.
|
||||
*
|
||||
* To the extent possible under law, the author(s) have dedicated all
|
||||
* copyright and related and neighboring rights to this software to
|
||||
* the public domain worldwide. This software is distributed without
|
||||
* any warranty.
|
||||
*
|
||||
* You should have received a copy of the CC0 Public Domain Dedication
|
||||
* along with this software. If not, see
|
||||
* <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A byte-addressable ring buffer FIFO implementation.
|
||||
*
|
||||
* The ring buffer's head pointer points to the starting location
|
||||
* where data should be written when copying data *into* the buffer
|
||||
* (e.g., with ringbuf_read). The ring buffer's tail pointer points to
|
||||
* the starting location where data should be read when copying data
|
||||
* *from* the buffer (e.g., with ringbuf_write).
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct ringbuf_t *ringbuf_t;
|
||||
|
||||
/*
|
||||
* Create a new ring buffer with the given capacity (usable
|
||||
* bytes). Note that the actual internal buffer size may be one or
|
||||
* more bytes larger than the usable capacity, for bookkeeping.
|
||||
*
|
||||
* Returns the new ring buffer object, or 0 if there's not enough
|
||||
* memory to fulfill the request for the given capacity.
|
||||
*/
|
||||
ringbuf_t
|
||||
ringbuf_new(size_t capacity);
|
||||
|
||||
/*
|
||||
* The size of the internal buffer, in bytes. One or more bytes may be
|
||||
* unusable in order to distinguish the "buffer full" state from the
|
||||
* "buffer empty" state.
|
||||
*
|
||||
* For the usable capacity of the ring buffer, use the
|
||||
* ringbuf_capacity function.
|
||||
*/
|
||||
size_t
|
||||
ringbuf_buffer_size(const struct ringbuf_t *rb);
|
||||
|
||||
/*
|
||||
* Deallocate a ring buffer, and, as a side effect, set the pointer to
|
||||
* 0.
|
||||
*/
|
||||
void
|
||||
ringbuf_free(ringbuf_t *rb);
|
||||
|
||||
/*
|
||||
* Reset a ring buffer to its initial state (empty).
|
||||
*/
|
||||
void
|
||||
ringbuf_reset(ringbuf_t rb);
|
||||
|
||||
/*
|
||||
* The usable capacity of the ring buffer, in bytes. Note that this
|
||||
* value may be less than the ring buffer's internal buffer size, as
|
||||
* returned by ringbuf_buffer_size.
|
||||
*/
|
||||
size_t
|
||||
ringbuf_capacity(const struct ringbuf_t *rb);
|
||||
|
||||
/*
|
||||
* The number of free/available bytes in the ring buffer. This value
|
||||
* is never larger than the ring buffer's usable capacity.
|
||||
*/
|
||||
size_t
|
||||
ringbuf_bytes_free(const struct ringbuf_t *rb);
|
||||
|
||||
/*
|
||||
* The number of bytes currently being used in the ring buffer. This
|
||||
* value is never larger than the ring buffer's usable capacity.
|
||||
*/
|
||||
size_t
|
||||
ringbuf_bytes_used(const struct ringbuf_t *rb);
|
||||
|
||||
int
|
||||
ringbuf_is_full(const struct ringbuf_t *rb);
|
||||
|
||||
int
|
||||
ringbuf_is_empty(const struct ringbuf_t *rb);
|
||||
|
||||
/*
|
||||
* Const access to the head and tail pointers of the ring buffer.
|
||||
*/
|
||||
const void *
|
||||
ringbuf_tail(const struct ringbuf_t *rb);
|
||||
|
||||
const void *
|
||||
ringbuf_head(const struct ringbuf_t *rb);
|
||||
|
||||
/*
|
||||
* Copy n bytes from a contiguous memory area src into the ring buffer
|
||||
* dst. Returns the ring buffer's new head pointer.
|
||||
*
|
||||
* It is possible to copy more data from src than is available in the
|
||||
* buffer; i.e., it's possible to overflow the ring buffer using this
|
||||
* function. When an overflow occurs, the state of the ring buffer is
|
||||
* guaranteed to be consistent, including the head and tail pointers;
|
||||
* old data will simply be overwritten in FIFO fashion, as
|
||||
* needed. However, note that, if calling the function results in an
|
||||
* overflow, the value of the ring buffer's tail pointer may be
|
||||
* different than it was before the function was called.
|
||||
*/
|
||||
void *
|
||||
ringbuf_memcpy_into(ringbuf_t dst, const void *src, size_t count);
|
||||
|
||||
/*
|
||||
* Copy n bytes from the ring buffer src, starting from its tail
|
||||
* pointer, into a contiguous memory area dst. Returns the value of
|
||||
* src's tail pointer after the copy is finished.
|
||||
*
|
||||
* Note that this copy is destructive with respect to the ring buffer:
|
||||
* the n bytes copied from the ring buffer are no longer available in
|
||||
* the ring buffer after the copy is complete, and the ring buffer
|
||||
* will have n more free bytes than it did before the function was
|
||||
* called.
|
||||
*
|
||||
* This function will *not* allow the ring buffer to underflow. If
|
||||
* count is greater than the number of bytes used in the ring buffer,
|
||||
* no bytes are copied, and the function will return 0.
|
||||
*/
|
||||
void *
|
||||
ringbuf_memcpy_from(void *dst, ringbuf_t src, size_t count);
|
||||
|
||||
/*
|
||||
* Copy count bytes from ring buffer src, starting from its tail
|
||||
* pointer, into ring buffer dst. Returns dst's new head pointer after
|
||||
* the copy is finished.
|
||||
*
|
||||
* Note that this copy is destructive with respect to the ring buffer
|
||||
* src: any bytes copied from src into dst are no longer available in
|
||||
* src after the copy is complete, and src will have 'count' more free
|
||||
* bytes than it did before the function was called.
|
||||
*
|
||||
* It is possible to copy more data from src than is available in dst;
|
||||
* i.e., it's possible to overflow dst using this function. When an
|
||||
* overflow occurs, the state of dst is guaranteed to be consistent,
|
||||
* including the head and tail pointers; old data will simply be
|
||||
* overwritten in FIFO fashion, as needed. However, note that, if
|
||||
* calling the function results in an overflow, the value dst's tail
|
||||
* pointer may be different than it was before the function was
|
||||
* called.
|
||||
*
|
||||
* It is *not* possible to underflow src; if count is greater than the
|
||||
* number of bytes used in src, no bytes are copied, and the function
|
||||
* returns 0.
|
||||
*/
|
||||
void *
|
||||
ringbuf_copy(ringbuf_t dst, ringbuf_t src, size_t count);
|
||||
|
||||
#endif /* INCLUDED_RINGBUF_H */
|
||||
|
||||
36
user/sys_time.c
Normal file
36
user/sys_time.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "c_types.h"
|
||||
#include "osapi.h"
|
||||
|
||||
typedef union _timer {
|
||||
uint32_t time_s[2];
|
||||
uint64_t time_l;
|
||||
} long_time_t;
|
||||
|
||||
static long_time_t time;
|
||||
static uint32_t old;
|
||||
|
||||
uint64_t ICACHE_FLASH_ATTR
|
||||
get_long_systime()
|
||||
{
|
||||
uint32_t now = system_get_time();
|
||||
if (now < old)
|
||||
{
|
||||
time.time_s[1]++;
|
||||
}
|
||||
old = now;
|
||||
time.time_s[0] = now;
|
||||
return time.time_l;
|
||||
}
|
||||
|
||||
uint64_t ICACHE_FLASH_ATTR
|
||||
get_low_systime()
|
||||
{
|
||||
get_long_systime();
|
||||
return time.time_s[0];
|
||||
}
|
||||
|
||||
void init_long_systime()
|
||||
{
|
||||
old = system_get_time();
|
||||
time.time_l = (uint64_t)old;
|
||||
}
|
||||
13
user/sys_time.h
Normal file
13
user/sys_time.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "c_types.h"
|
||||
|
||||
// returns time until boot in us
|
||||
uint64_t ICACHE_FLASH_ATTR
|
||||
get_long_systime();
|
||||
|
||||
// returns lower half of time until boot in us
|
||||
uint64_t ICACHE_FLASH_ATTR
|
||||
get_low_systime();
|
||||
|
||||
// initializes the timer
|
||||
void
|
||||
init_long_systime();
|
||||
38
user/user_config.h
Normal file
38
user/user_config.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef _USER_CONFIG_
|
||||
#define _USER_CONFIG_
|
||||
|
||||
#define ESPERPASS_VERSION "V0.0.1"
|
||||
|
||||
#define WIFI_SSID "ssid"
|
||||
#define WIFI_PASSWORD "password"
|
||||
|
||||
#define WIFI_AP_SSID "attwifi"
|
||||
|
||||
#define MAX_CLIENTS 8
|
||||
#define MAX_DHCP 8
|
||||
|
||||
//
|
||||
// Size of the console buffers
|
||||
//
|
||||
#define MAX_CON_SEND_SIZE 1024
|
||||
#define MAX_CON_CMD_SIZE 80
|
||||
|
||||
//
|
||||
// Define this if you have a status LED connected to a GPIO pin
|
||||
//
|
||||
#define STATUS_LED_GPIO 2
|
||||
|
||||
//
|
||||
// Define this to support the setting of the WiFi PHY mode
|
||||
//
|
||||
#define PHY_MODE 1
|
||||
|
||||
//
|
||||
// Define this if you want to have ACLs for the SoftAP.
|
||||
//
|
||||
#define ACLS 1
|
||||
|
||||
// Internal
|
||||
typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SIG_CONSOLE_RX, SIG_CONSOLE_TX, SIG_CONSOLE_TX_RAW, SIG_GPIO_INT} USER_SIGNALS;
|
||||
|
||||
#endif
|
||||
1494
user/user_main.c
Normal file
1494
user/user_main.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user