Skip to content

Commit

Permalink
LwIP v2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
ourairquality committed Jun 7, 2017
1 parent ce298e1 commit ab89e4d
Show file tree
Hide file tree
Showing 21 changed files with 583 additions and 144 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "lwip/lwip"]
path = lwip/lwip
url = https://github.com/SuperHouse/esp-lwip.git
url = https://github.com/ourairquality/lwip.git
[submodule "extras/mbedtls/mbedtls"]
path = extras/mbedtls/mbedtls
url = https://github.com/ARMmbed/mbedtls.git
Expand Down
9 changes: 1 addition & 8 deletions core/include/sdk_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,7 @@ _Static_assert(offsetof(struct netif, state) == 28, "netif->state offset wrong!"
// lwip, so just ensure it is at the expected offset.
_Static_assert(offsetof(struct netif, hwaddr) == 41, "netif->hwaddr offset wrong!");

// Most sdk uses of the netif->flags have been converted to source code. One
// known sdk binary read of the flags remains in wl_cnx.o:sdk_cnx_sta_leave
// which checks the NETIF_FLAG_DHCP flag. The NETIF_FLAG_DHCP has been removed
// in lwip v2, so some lwip hacks are needed to handle this for now until
// wl_cnx.o is converted so source code too.
_Static_assert(offsetof(struct netif, flags) == 47, "netif->flags offset wrong!");

_Static_assert(offsetof(struct pbuf, eb) == 16, "pbuf->eb offset wrong!");
_Static_assert(offsetof(struct pbuf, esf_buf) == 16, "pbuf->esf_buf offset wrong!");


/// Misc.
Expand Down
7 changes: 4 additions & 3 deletions examples/http_get/http_get.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#define WEB_SERVER "chainxor.org"
#define WEB_PORT 80
#define WEB_URL "http://chainxor.org/"
#define WEB_PATH "/"

void http_get_task(void *pvParameters)
{
Expand Down Expand Up @@ -75,7 +75,8 @@ void http_get_task(void *pvParameters)
freeaddrinfo(res);

const char *req =
"GET "WEB_URL"\r\n"
"GET "WEB_PATH" HTTP/1.1\r\n"
"Host: "WEB_SERVER"\r\n"
"User-Agent: esp-open-rtos/0.1 esp8266\r\n"
"\r\n";
if (write(s, req, strlen(req)) < 0) {
Expand Down Expand Up @@ -126,6 +127,6 @@ void user_init(void)
sdk_wifi_set_opmode(STATION_MODE);
sdk_wifi_station_set_config(&config);

xTaskCreate(&http_get_task, "get_task", 256, NULL, 2, NULL);
xTaskCreate(&http_get_task, "get_task", 384, NULL, 2, NULL);
}

5 changes: 2 additions & 3 deletions examples/tls_server/tls_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,8 @@ void tls_server_task(void *pvParameters)
socklen_t peer_addr_len = sizeof(struct sockaddr_in);
getpeername(client_ctx.fd, (struct sockaddr *)&peer_addr, &peer_addr_len);
unsigned char buf[256];
int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\nFree heap size is %d bytes\n",
ip4_addr1(&peer_addr.sin_addr), ip4_addr2(&peer_addr.sin_addr),
ip4_addr3(&peer_addr.sin_addr), ip4_addr4(&peer_addr.sin_addr),
int len = sprintf((char *) buf, "O hai, client " IPSTR ":%d\nFree heap size is %d bytes\n",
IP2STR((ip4_addr_t *)&peer_addr.sin_addr.s_addr),
peer_addr.sin_port, xPortGetFreeHeapSize());
while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
{
Expand Down
5 changes: 2 additions & 3 deletions examples/tls_server_bearssl/tls_server_bearssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,8 @@ void tls_server_task(void *pvParameters)

/* Prepare a message to the client */
unsigned char buf[100];
int len = sprintf((char *) buf, "O hai, client %d.%d.%d.%d:%d\r\nFree heap size is %d bytes\r\n",
ip4_addr1(&sa.sin_addr), ip4_addr2(&sa.sin_addr),
ip4_addr3(&sa.sin_addr), ip4_addr4(&sa.sin_addr),
int len = sprintf((char *) buf, "O hai, client " IPSTR ":%d\r\nFree heap size is %d bytes\r\n",
IP2STR((ip4_addr_t *)&sa.sin_addr.s_addr),
ntohs(sa.sin_port), xPortGetFreeHeapSize());

/* Send the message and close the connection */
Expand Down
106 changes: 58 additions & 48 deletions extras/dhcpserver/dhcpserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* BSD Licensed as described in the file LICENSE
*/
#include <string.h>
#include <strings.h>

#include <FreeRTOS.h>
#include <task.h>
Expand All @@ -25,7 +26,8 @@
full-sized clients send us more than this. */
#define DHCP_OPTIONS_LEN 312

#include <lwip/dhcp.h>
#include <lwip/ip.h>
#include <lwip/prot/dhcp.h>

_Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 312, "dhcp_msg_t should have extended options size");

Expand All @@ -35,13 +37,14 @@ _Static_assert(sizeof(struct dhcp_msg) == offsetof(struct dhcp_msg, options) + 3

typedef struct {
uint8_t hwaddr[NETIF_MAX_HWADDR_LEN];
uint8_t active;
uint32_t expires;
} dhcp_lease_t;

typedef struct {
struct netconn *nc;
uint8_t max_leases;
ip_addr_t first_client_addr;
ip4_addr_t first_client_addr;
struct netif *server_if;
dhcp_lease_t *leases; /* length max_leases */
} server_state_t;
Expand All @@ -68,33 +71,34 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr);

/* Copy IP address as dotted decimal to 'dest', must be at least 16 bytes long */
inline static void sprintf_ipaddr(const ip_addr_t *addr, char *dest)
inline static void sprintf_ipaddr(const ip4_addr_t *addr, char *dest)
{
if(addr == NULL)
if (addr == NULL)
sprintf(dest, "NULL");
else
sprintf(dest, "%d.%d.%d.%d", ip4_addr1(addr),
ip4_addr2(addr), ip4_addr3(addr), ip4_addr4(addr));
}

void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases)
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases)
{
/* Stop any existing running dhcpserver */
if(dhcpserver_task_handle)
if (dhcpserver_task_handle)
dhcpserver_stop();

state = malloc(sizeof(server_state_t));
state->max_leases = max_leases;
state->leases = calloc(max_leases, sizeof(dhcp_lease_t));
bzero(state->leases, max_leases * sizeof(dhcp_lease_t));
// state->server_if is assigned once the task is running - see comment in dhcpserver_task()
ip_addr_copy(state->first_client_addr, *first_client_addr);

xTaskCreate(dhcpserver_task, "DHCPServer", 768, NULL, 8, &dhcpserver_task_handle);
xTaskCreate(dhcpserver_task, "DHCP Server", 448, NULL, 2, &dhcpserver_task_handle);
}

void dhcpserver_stop(void)
{
if(dhcpserver_task_handle) {
if (dhcpserver_task_handle) {
vTaskDelete(dhcpserver_task_handle);
free(state);
dhcpserver_task_handle = NULL;
Expand All @@ -107,12 +111,13 @@ static void dhcpserver_task(void *pxParameter)
state->server_if = netif_list; /* TODO: Make this configurable */

state->nc = netconn_new (NETCONN_UDP);
if(!state->nc) {
if (!state->nc) {
printf("DHCP Server Error: Failed to allocate socket.\r\n");
return;
}

netconn_bind(state->nc, IP_ADDR_ANY, DHCP_SERVER_PORT);
netconn_bind_if (state->nc, netif_get_index(state->server_if));

while(1)
{
Expand All @@ -121,29 +126,32 @@ static void dhcpserver_task(void *pxParameter)

/* Receive a DHCP packet */
err_t err = netconn_recv(state->nc, &netbuf);
if(err != ERR_OK) {
if (err != ERR_OK) {
printf("DHCP Server Error: Failed to receive DHCP packet. err=%d\r\n", err);
continue;
}

/* expire any leases that have passed */
uint32_t now = xTaskGetTickCount();
for(int i = 0; i < state->max_leases; i++) {
uint32_t expires = state->leases[i].expires;
if(expires && expires < now)
state->leases[i].expires = 0;
for (int i = 0; i < state->max_leases; i++) {
if (state->leases[i].active) {
uint32_t expires = state->leases[i].expires - now;
if (expires >= 0x80000000) {
state->leases[i].active = 0;
}
}
}

ip_addr_t received_ip;
ip4_addr_t received_ip;
u16_t port;
netconn_addr(state->nc, &received_ip, &port);

if(netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
if (netbuf_len(netbuf) < offsetof(struct dhcp_msg, options)) {
/* too short to be a valid DHCP client message */
netbuf_delete(netbuf);
continue;
}
if(netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
if (netbuf_len(netbuf) >= sizeof(struct dhcp_msg)) {
printf("DHCP Server Warning: Client sent more options than we know how to parse. len=%d\r\n", netbuf_len(netbuf));
}

Expand All @@ -152,18 +160,18 @@ static void dhcpserver_task(void *pxParameter)

uint8_t *message_type = find_dhcp_option(&received, DHCP_OPTION_MESSAGE_TYPE,
DHCP_OPTION_MESSAGE_TYPE_LEN, NULL);
if(!message_type) {
if (!message_type) {
printf("DHCP Server Error: No message type field found");
continue;
}


printf("State dump. Message type %d\n", *message_type);
for(int i = 0; i < state->max_leases; i++) {
for (int i = 0; i < state->max_leases; i++) {
dhcp_lease_t *lease = &state->leases[i];
printf("lease slot %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, lease->expires, lease->hwaddr[0],
lease->hwaddr[1], lease->hwaddr[2], lease->hwaddr[3], lease->hwaddr[4],
lease->hwaddr[5]);
printf("lease slot %d active %d expiry %d hwaddr %02x:%02x:%02x:%02x:%02x:%02x\r\n", i,
lease->active, lease->expires - now,
lease->hwaddr[0], lease->hwaddr[1], lease->hwaddr[2],
lease->hwaddr[3], lease->hwaddr[4], lease->hwaddr[5]);
}

switch(*message_type) {
Expand All @@ -184,13 +192,13 @@ static void dhcpserver_task(void *pxParameter)

static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
{
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
if (dhcpmsg->htype != DHCP_HTYPE_ETH)
return;
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
return;

dhcp_lease_t *freelease = find_lease_slot(dhcpmsg->chaddr);
if(!freelease) {
if (!freelease) {
printf("DHCP Server: All leases taken.\r\n");
return; /* Nothing available, so do nothing */
}
Expand All @@ -199,8 +207,7 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
dhcpmsg->op = DHCP_BOOTREPLY;
bzero(dhcpmsg->options, DHCP_OPTIONS_LEN);

ip_addr_copy(dhcpmsg->yiaddr, state->first_client_addr);
ip4_addr4(&(dhcpmsg->yiaddr)) += (freelease - state->leases);
dhcpmsg->yiaddr.addr = lwip_htonl(lwip_ntohl(state->first_client_addr.addr) + (freelease - state->leases));

uint8_t *opt = (uint8_t *)&dhcpmsg->options;
opt = add_dhcp_option_byte(opt, DHCP_OPTION_MESSAGE_TYPE, DHCP_OFFER);
Expand All @@ -218,16 +225,16 @@ static void handle_dhcp_discover(struct dhcp_msg *dhcpmsg)
static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
{
static char ipbuf[16];
if(dhcpmsg->htype != DHCP_HTYPE_ETH)
if (dhcpmsg->htype != DHCP_HTYPE_ETH)
return;
if(dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
if (dhcpmsg->hlen > NETIF_MAX_HWADDR_LEN)
return;

ip_addr_t requested_ip;
ip4_addr_t requested_ip;
uint8_t *requested_ip_opt = find_dhcp_option(dhcpmsg, DHCP_OPTION_REQUESTED_IP, 4, NULL);
if(requested_ip_opt) {
memcpy(&requested_ip.addr, requested_ip_opt, 4);
} else if(ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) {
if (requested_ip_opt) {
memcpy(&requested_ip.addr, requested_ip_opt, 4);
} else if (ip_addr_cmp(&requested_ip, IP_ADDR_ANY)) {
ip_addr_copy(requested_ip, dhcpmsg->ciaddr);
} else {
printf("DHCP Server Error: No requested IP\r\n");
Expand All @@ -236,7 +243,7 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
}

/* Test the first 4 octets match */
if(ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
if (ip4_addr1(&requested_ip) != ip4_addr1(&state->first_client_addr)
|| ip4_addr2(&requested_ip) != ip4_addr2(&state->first_client_addr)
|| ip4_addr3(&requested_ip) != ip4_addr3(&state->first_client_addr)) {
sprintf_ipaddr(&requested_ip, ipbuf);
Expand All @@ -246,14 +253,14 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
}
/* Test the last octet is in the MAXCLIENTS range */
int16_t octet_offs = ip4_addr4(&requested_ip) - ip4_addr4(&state->first_client_addr);
if(octet_offs < 0 || octet_offs >= state->max_leases) {
if (octet_offs < 0 || octet_offs >= state->max_leases) {
printf("DHCP Server Error: Address out of range\r\n");
send_dhcp_nak(dhcpmsg);
return;
}

dhcp_lease_t *requested_lease = state->leases + octet_offs;
if(requested_lease->expires != 0 && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
if (requested_lease->active && memcmp(requested_lease->hwaddr, dhcpmsg->chaddr,dhcpmsg->hlen))
{
printf("DHCP Server Error: Lease for address already taken\r\n");
send_dhcp_nak(dhcpmsg);
Expand All @@ -265,7 +272,9 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
printf("DHCP lease addr %s assigned to MAC %02x:%02x:%02x:%02x:%02x:%02x\r\n", ipbuf, requested_lease->hwaddr[0],
requested_lease->hwaddr[1], requested_lease->hwaddr[2], requested_lease->hwaddr[3], requested_lease->hwaddr[4],
requested_lease->hwaddr[5]);
requested_lease->expires = DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
uint32_t now = xTaskGetTickCount();
requested_lease->expires = now + DHCPSERVER_LEASE_TIME * configTICK_RATE_HZ;
requested_lease->active = 1;

/* Reuse the REQUEST message as the ACK message */
dhcpmsg->op = DHCP_BOOTREPLY;
Expand All @@ -291,7 +300,8 @@ static void handle_dhcp_request(struct dhcp_msg *dhcpmsg)
static void handle_dhcp_release(struct dhcp_msg *dhcpmsg)
{
dhcp_lease_t *lease = find_lease_slot(dhcpmsg->chaddr);
if(lease) {
if (lease) {
lease->active = 0;
lease->expires = 0;
}
}
Expand Down Expand Up @@ -319,17 +329,17 @@ static uint8_t *find_dhcp_option(struct dhcp_msg *msg, uint8_t option_num, uint8
uint8_t *start = (uint8_t *)&msg->options;
uint8_t *msg_end = (uint8_t *)msg + sizeof(struct dhcp_msg);

for(uint8_t *p = start; p < msg_end-2;) {
for (uint8_t *p = start; p < msg_end-2;) {
uint8_t type = *p++;
uint8_t len = *p++;
if(type == DHCP_OPTION_END)
if (type == DHCP_OPTION_END)
return NULL;
if(p+len >= msg_end)
if (p+len >= msg_end)
break; /* We've overrun our valid DHCP message size, or this isn't a valid option */
if(type == option_num) {
if(len < min_length)
if (type == option_num) {
if (len < min_length)
break;
if(length)
if (length)
*length = len;
return p; /* start of actual option data */
}
Expand All @@ -349,7 +359,7 @@ static uint8_t *add_dhcp_option_byte(uint8_t *opt, uint8_t type, uint8_t value)
static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, uint8_t len)
{
*opt++ = type;
if(len) {
if (len) {
*opt++ = len;
memcpy(opt, value, len);
}
Expand All @@ -360,8 +370,8 @@ static uint8_t *add_dhcp_option_bytes(uint8_t *opt, uint8_t type, void *value, u
static dhcp_lease_t *find_lease_slot(uint8_t *hwaddr)
{
dhcp_lease_t *empty_lease = NULL;
for(int i = 0; i < state->max_leases; i++) {
if(state->leases[i].expires == 0 && !empty_lease)
for (int i = 0; i < state->max_leases; i++) {
if (!state->leases[i].active && !empty_lease)
empty_lease = &state->leases[i];
else if (memcmp(hwaddr, state->leases[i].hwaddr, 6) == 0)
return &state->leases[i];
Expand Down
4 changes: 2 additions & 2 deletions extras/dhcpserver/include/dhcpserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ extern "C" {
to a client. Subsequent lease addresses are calculated by
incrementing the final octet of the IPv4 address, up to max_leases.
*/
void dhcpserver_start(const ip_addr_t *first_client_addr, uint8_t max_leases);
void dhcpserver_start(const ip4_addr_t *first_client_addr, uint8_t max_leases);

void dhcpserver_get_lease(const ip_addr_t *first_client_addr, uint8_t max_leases);
void dhcpserver_get_lease(const ip4_addr_t *first_client_addr, uint8_t max_leases);

/* Stop DHCP server.
*/
Expand Down
Loading

0 comments on commit ab89e4d

Please sign in to comment.