mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-24 15:31:56 -04:00
Add AVR32 port and demo files.
This commit is contained in:
parent
b578c75c4e
commit
06bbaed27a
13
Demo/Common/ethernet/lwIP/FILES
Normal file
13
Demo/Common/ethernet/lwIP/FILES
Normal file
|
@ -0,0 +1,13 @@
|
|||
api/ - The code for the high-level wrapper API. Not needed if
|
||||
you use the lowel-level call-back/raw API.
|
||||
|
||||
core/ - The core of the TPC/IP stack; protocol implementations,
|
||||
memory and buffer management, and the low-level raw API.
|
||||
|
||||
include/ - lwIP include files.
|
||||
|
||||
netif/ - Generic network interface device drivers are kept here,
|
||||
as well as the ARP module.
|
||||
|
||||
For more information on the various subdirectories, check the FILES
|
||||
file in each directory.
|
722
Demo/Common/ethernet/lwIP/api/api_lib.c
Normal file
722
Demo/Common/ethernet/lwIP/api/api_lib.c
Normal file
|
@ -0,0 +1,722 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* This is the part of the API that is linked with
|
||||
the application */
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
|
||||
struct
|
||||
netbuf *netbuf_new(void)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
if (buf != NULL) {
|
||||
buf->p = NULL;
|
||||
buf->ptr = NULL;
|
||||
return buf;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_delete(struct netbuf *buf)
|
||||
{
|
||||
if (buf != NULL) {
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
buf->p = buf->ptr = NULL;
|
||||
}
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
netbuf_alloc(struct netbuf *buf, u16_t size)
|
||||
{
|
||||
/* Deallocate any previously allocated memory. */
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
|
||||
if (buf->p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
buf->ptr = buf->p;
|
||||
return buf->p->payload;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_free(struct netbuf *buf)
|
||||
{
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = buf->ptr = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
|
||||
{
|
||||
if (buf->p != NULL) {
|
||||
pbuf_free(buf->p);
|
||||
}
|
||||
buf->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF);
|
||||
buf->p->payload = dataptr;
|
||||
buf->p->len = buf->p->tot_len = size;
|
||||
buf->ptr = buf->p;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_chain(struct netbuf *head, struct netbuf *tail)
|
||||
{
|
||||
pbuf_chain(head->p, tail->p);
|
||||
head->ptr = head->p;
|
||||
memp_free(MEMP_NETBUF, tail);
|
||||
}
|
||||
|
||||
u16_t
|
||||
netbuf_len(struct netbuf *buf)
|
||||
{
|
||||
return buf->p->tot_len;
|
||||
}
|
||||
|
||||
err_t
|
||||
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
|
||||
{
|
||||
if (buf->ptr == NULL) {
|
||||
return ERR_BUF;
|
||||
}
|
||||
*dataptr = buf->ptr->payload;
|
||||
*len = buf->ptr->len;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
s8_t
|
||||
netbuf_next(struct netbuf *buf)
|
||||
{
|
||||
if (buf->ptr->next == NULL) {
|
||||
return -1;
|
||||
}
|
||||
buf->ptr = buf->ptr->next;
|
||||
if (buf->ptr->next == NULL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_first(struct netbuf *buf)
|
||||
{
|
||||
buf->ptr = buf->p;
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
|
||||
{
|
||||
struct pbuf *p;
|
||||
u16_t i, left;
|
||||
|
||||
left = 0;
|
||||
|
||||
if(buf == NULL || dataptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* This implementation is bad. It should use bcopy
|
||||
instead. */
|
||||
for(p = buf->p; left < len && p != NULL; p = p->next) {
|
||||
if (offset != 0 && offset >= p->len) {
|
||||
offset -= p->len;
|
||||
} else {
|
||||
for(i = offset; i < p->len; ++i) {
|
||||
((u8_t *)dataptr)[left] = ((u8_t *)p->payload)[i];
|
||||
if (++left >= len) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
netbuf_copy(struct netbuf *buf, void *dataptr, u16_t len)
|
||||
{
|
||||
netbuf_copy_partial(buf, dataptr, len, 0);
|
||||
}
|
||||
|
||||
struct ip_addr *
|
||||
netbuf_fromaddr(struct netbuf *buf)
|
||||
{
|
||||
return buf->fromaddr;
|
||||
}
|
||||
|
||||
u16_t
|
||||
netbuf_fromport(struct netbuf *buf)
|
||||
{
|
||||
return buf->fromport;
|
||||
}
|
||||
|
||||
struct
|
||||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
|
||||
{
|
||||
struct netconn *conn;
|
||||
struct api_msg *msg;
|
||||
|
||||
conn = memp_malloc(MEMP_NETCONN);
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->err = ERR_OK;
|
||||
conn->type = t;
|
||||
conn->pcb.tcp = NULL;
|
||||
|
||||
if ((conn->mbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
conn->recvmbox = SYS_MBOX_NULL;
|
||||
conn->acceptmbox = SYS_MBOX_NULL;
|
||||
conn->sem = sys_sem_new(0);
|
||||
if (conn->sem == SYS_SEM_NULL) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
conn->state = NETCONN_NONE;
|
||||
conn->socket = 0;
|
||||
conn->callback = callback;
|
||||
conn->recv_avail = 0;
|
||||
|
||||
if((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msg->type = API_MSG_NEWCONN;
|
||||
msg->msg.msg.bc.port = proto; /* misusing the port field */
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
|
||||
if ( conn->err != ERR_OK ) {
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
struct
|
||||
netconn *netconn_new(enum netconn_type t)
|
||||
{
|
||||
return netconn_new_with_proto_and_callback(t,0,NULL);
|
||||
}
|
||||
|
||||
struct
|
||||
netconn *netconn_new_with_callback(enum netconn_type t,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
|
||||
{
|
||||
return netconn_new_with_proto_and_callback(t,0,callback);
|
||||
}
|
||||
|
||||
|
||||
err_t
|
||||
netconn_delete(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
void *mem;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = API_MSG_DELCONN;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
|
||||
/* Drain the recvmbox. */
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
while (sys_arch_mbox_fetch(conn->recvmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if(mem != NULL)
|
||||
pbuf_free((struct pbuf *)mem);
|
||||
} else {
|
||||
netbuf_delete((struct netbuf *)mem);
|
||||
}
|
||||
}
|
||||
sys_mbox_free(conn->recvmbox);
|
||||
conn->recvmbox = SYS_MBOX_NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Drain the acceptmbox. */
|
||||
if (conn->acceptmbox != SYS_MBOX_NULL) {
|
||||
while (sys_arch_mbox_fetch(conn->acceptmbox, &mem, 1) != SYS_ARCH_TIMEOUT) {
|
||||
netconn_delete((struct netconn *)mem);
|
||||
}
|
||||
|
||||
sys_mbox_free(conn->acceptmbox);
|
||||
conn->acceptmbox = SYS_MBOX_NULL;
|
||||
}
|
||||
|
||||
sys_mbox_free(conn->mbox);
|
||||
conn->mbox = SYS_MBOX_NULL;
|
||||
if (conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_free(conn->sem);
|
||||
}
|
||||
/* conn->sem = SYS_SEM_NULL;*/
|
||||
memp_free(MEMP_NETCONN, conn);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
enum netconn_type
|
||||
netconn_type(struct netconn *conn)
|
||||
{
|
||||
return conn->type;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_peer(struct netconn *conn, struct ip_addr *addr,
|
||||
u16_t *port)
|
||||
{
|
||||
switch (conn->type) {
|
||||
case NETCONN_RAW:
|
||||
/* return an error as connecting is only a helper for upper layers */
|
||||
return ERR_CONN;
|
||||
case NETCONN_UDPLITE:
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
case NETCONN_UDP:
|
||||
if (conn->pcb.udp == NULL ||
|
||||
((conn->pcb.udp->flags & UDP_FLAGS_CONNECTED) == 0))
|
||||
return ERR_CONN;
|
||||
*addr = (conn->pcb.udp->remote_ip);
|
||||
*port = conn->pcb.udp->remote_port;
|
||||
break;
|
||||
case NETCONN_TCP:
|
||||
if (conn->pcb.tcp == NULL)
|
||||
return ERR_CONN;
|
||||
*addr = (conn->pcb.tcp->remote_ip);
|
||||
*port = conn->pcb.tcp->remote_port;
|
||||
break;
|
||||
}
|
||||
return (conn->err = ERR_OK);
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_addr(struct netconn *conn, struct ip_addr **addr,
|
||||
u16_t *port)
|
||||
{
|
||||
switch (conn->type) {
|
||||
case NETCONN_RAW:
|
||||
*addr = &(conn->pcb.raw->local_ip);
|
||||
*port = conn->pcb.raw->protocol;
|
||||
break;
|
||||
case NETCONN_UDPLITE:
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
case NETCONN_UDP:
|
||||
*addr = &(conn->pcb.udp->local_ip);
|
||||
*port = conn->pcb.udp->local_port;
|
||||
break;
|
||||
case NETCONN_TCP:
|
||||
*addr = &(conn->pcb.tcp->local_ip);
|
||||
*port = conn->pcb.tcp->local_port;
|
||||
break;
|
||||
}
|
||||
return (conn->err = ERR_OK);
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_bind(struct netconn *conn, struct ip_addr *addr,
|
||||
u16_t port)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->type != NETCONN_TCP &&
|
||||
conn->recvmbox == SYS_MBOX_NULL) {
|
||||
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
msg->type = API_MSG_BIND;
|
||||
msg->msg.conn = conn;
|
||||
msg->msg.msg.bc.ipaddr = addr;
|
||||
msg->msg.msg.bc.port = port;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
|
||||
err_t
|
||||
netconn_connect(struct netconn *conn, struct ip_addr *addr,
|
||||
u16_t port)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
|
||||
if (conn->recvmbox == SYS_MBOX_NULL) {
|
||||
if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
msg->type = API_MSG_CONNECT;
|
||||
msg->msg.conn = conn;
|
||||
msg->msg.msg.bc.ipaddr = addr;
|
||||
msg->msg.msg.bc.port = port;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_disconnect(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
msg->type = API_MSG_DISCONNECT;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_listen(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
conn->acceptmbox = sys_mbox_new();
|
||||
if (conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
msg->type = API_MSG_LISTEN;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
struct netconn *
|
||||
netconn_accept(struct netconn *conn)
|
||||
{
|
||||
struct netconn *newconn;
|
||||
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_mbox_fetch(conn->acceptmbox, (void *)&newconn);
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, 0);
|
||||
|
||||
return newconn;
|
||||
}
|
||||
|
||||
struct netbuf *
|
||||
netconn_recv(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
struct netbuf *buf;
|
||||
struct pbuf *p;
|
||||
u16_t len;
|
||||
|
||||
if (conn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->recvmbox == SYS_MBOX_NULL) {
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (conn->pcb.tcp->state == LISTEN) {
|
||||
conn->err = ERR_CONN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
|
||||
if (buf == NULL) {
|
||||
conn->err = ERR_MEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_mbox_fetch(conn->recvmbox, (void *)&p);
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
len = p->tot_len;
|
||||
conn->recv_avail -= len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, len);
|
||||
|
||||
/* If we are closed, we indicate that we no longer wish to receive
|
||||
data by setting conn->recvmbox to SYS_MBOX_NULL. */
|
||||
if (p == NULL) {
|
||||
memp_free(MEMP_NETBUF, buf);
|
||||
sys_mbox_free(conn->recvmbox);
|
||||
conn->recvmbox = SYS_MBOX_NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromport = 0;
|
||||
buf->fromaddr = NULL;
|
||||
|
||||
/* Let the stack know that we have taken the data. */
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
conn->err = ERR_MEM;
|
||||
return buf;
|
||||
}
|
||||
msg->type = API_MSG_RECV;
|
||||
msg->msg.conn = conn;
|
||||
if (buf != NULL) {
|
||||
msg->msg.msg.len = buf->p->tot_len;
|
||||
} else {
|
||||
msg->msg.msg.len = 1;
|
||||
}
|
||||
api_msg_post(msg);
|
||||
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
} else {
|
||||
sys_mbox_fetch(conn->recvmbox, (void *)&buf);
|
||||
conn->recv_avail -= buf->p->tot_len;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_recv: received %p (err %d)\n", (void *)buf, conn->err));
|
||||
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_send(struct netconn *conn, struct netbuf *buf)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
|
||||
msg->type = API_MSG_SEND;
|
||||
msg->msg.conn = conn;
|
||||
msg->msg.msg.p = buf->p;
|
||||
api_msg_post(msg);
|
||||
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
u16_t len;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->err != ERR_OK) {
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
msg->type = API_MSG_WRITE;
|
||||
msg->msg.conn = conn;
|
||||
|
||||
|
||||
conn->state = NETCONN_WRITE;
|
||||
while (conn->err == ERR_OK && size > 0) {
|
||||
msg->msg.msg.w.dataptr = dataptr;
|
||||
msg->msg.msg.w.copy = copy;
|
||||
|
||||
if (conn->type == NETCONN_TCP) {
|
||||
if (tcp_sndbuf(conn->pcb.tcp) == 0) {
|
||||
sys_sem_wait(conn->sem);
|
||||
if (conn->err != ERR_OK) {
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
if (size > tcp_sndbuf(conn->pcb.tcp)) {
|
||||
/* We cannot send more than one send buffer's worth of data at a
|
||||
time. */
|
||||
len = tcp_sndbuf(conn->pcb.tcp);
|
||||
} else {
|
||||
len = size;
|
||||
}
|
||||
} else {
|
||||
len = size;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_write: writing %d bytes (%d)\n", len, copy));
|
||||
msg->msg.msg.w.len = len;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
if (conn->err == ERR_OK) {
|
||||
dataptr = (void *)((u8_t *)dataptr + len);
|
||||
size -= len;
|
||||
} else if (conn->err == ERR_MEM) {
|
||||
conn->err = ERR_OK;
|
||||
sys_sem_wait(conn->sem);
|
||||
} else {
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
ret:
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
conn->state = NETCONN_NONE;
|
||||
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_close(struct netconn *conn)
|
||||
{
|
||||
struct api_msg *msg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
if ((msg = memp_malloc(MEMP_API_MSG)) == NULL) {
|
||||
return (conn->err = ERR_MEM);
|
||||
}
|
||||
|
||||
conn->state = NETCONN_CLOSE;
|
||||
again:
|
||||
msg->type = API_MSG_CLOSE;
|
||||
msg->msg.conn = conn;
|
||||
api_msg_post(msg);
|
||||
sys_mbox_fetch(conn->mbox, NULL);
|
||||
if (conn->err == ERR_MEM &&
|
||||
conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_wait(conn->sem);
|
||||
goto again;
|
||||
}
|
||||
conn->state = NETCONN_NONE;
|
||||
memp_free(MEMP_API_MSG, msg);
|
||||
return conn->err;
|
||||
}
|
||||
|
||||
err_t
|
||||
netconn_err(struct netconn *conn)
|
||||
{
|
||||
return conn->err;
|
||||
}
|
||||
|
807
Demo/Common/ethernet/lwIP/api/api_msg.c
Normal file
807
Demo/Common/ethernet/lwIP/api/api_msg.c
Normal file
|
@ -0,0 +1,807 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
static u8_t
|
||||
recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
if (!conn) return 0;
|
||||
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
if (!(buf = memp_malloc(MEMP_NETBUF))) {
|
||||
return 0;
|
||||
}
|
||||
pbuf_ref(p);
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromaddr = addr;
|
||||
buf->fromport = pcb->protocol;
|
||||
|
||||
conn->recv_avail += p->tot_len;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
|
||||
sys_mbox_post(conn->recvmbox, buf);
|
||||
}
|
||||
|
||||
return 0; /* do not eat the packet */
|
||||
}
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
static void
|
||||
recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
buf = memp_malloc(MEMP_NETBUF);
|
||||
if (buf == NULL) {
|
||||
pbuf_free(p);
|
||||
return;
|
||||
} else {
|
||||
buf->p = p;
|
||||
buf->ptr = p;
|
||||
buf->fromaddr = addr;
|
||||
buf->fromport = port;
|
||||
}
|
||||
|
||||
conn->recv_avail += p->tot_len;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
|
||||
sys_mbox_post(conn->recvmbox, buf);
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
|
||||
static err_t
|
||||
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
|
||||
{
|
||||
struct netconn *conn;
|
||||
u16_t len;
|
||||
|
||||
conn = arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
pbuf_free(p);
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
|
||||
conn->err = err;
|
||||
if (p != NULL) {
|
||||
len = p->tot_len;
|
||||
conn->recv_avail += len;
|
||||
}
|
||||
else
|
||||
len = 0;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, len);
|
||||
sys_mbox_post(conn->recvmbox, p);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
static err_t
|
||||
poll_tcp(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
if (conn != NULL &&
|
||||
(conn->state == NETCONN_WRITE || conn->state == NETCONN_CLOSE) &&
|
||||
conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_signal(conn->sem);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
if (conn != NULL && conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_signal(conn->sem);
|
||||
}
|
||||
|
||||
if (conn && conn->callback)
|
||||
if (tcp_sndbuf(conn->pcb.tcp) > TCP_SNDLOWAT)
|
||||
(*conn->callback)(conn, NETCONN_EVT_SENDPLUS, len);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
err_tcp(void *arg, err_t err)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
|
||||
conn->pcb.tcp = NULL;
|
||||
|
||||
|
||||
conn->err = err;
|
||||
if (conn->recvmbox != SYS_MBOX_NULL) {
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
sys_mbox_post(conn->recvmbox, NULL);
|
||||
}
|
||||
if (conn->mbox != SYS_MBOX_NULL) {
|
||||
sys_mbox_post(conn->mbox, NULL);
|
||||
}
|
||||
if (conn->acceptmbox != SYS_MBOX_NULL) {
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
sys_mbox_post(conn->acceptmbox, NULL);
|
||||
}
|
||||
if (conn->sem != SYS_SEM_NULL) {
|
||||
sys_sem_signal(conn->sem);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_tcp(struct netconn *conn)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
|
||||
pcb = conn->pcb.tcp;
|
||||
tcp_arg(pcb, conn);
|
||||
tcp_recv(pcb, recv_tcp);
|
||||
tcp_sent(pcb, sent_tcp);
|
||||
tcp_poll(pcb, poll_tcp, 4);
|
||||
tcp_err(pcb, err_tcp);
|
||||
}
|
||||
|
||||
static err_t
|
||||
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
|
||||
{
|
||||
sys_mbox_t mbox;
|
||||
struct netconn *newconn;
|
||||
struct netconn *conn;
|
||||
|
||||
#if API_MSG_DEBUG
|
||||
#if TCP_DEBUG
|
||||
tcp_debug_print_state(newpcb->state);
|
||||
#endif /* TCP_DEBUG */
|
||||
#endif /* API_MSG_DEBUG */
|
||||
conn = (struct netconn *)arg;
|
||||
mbox = conn->acceptmbox;
|
||||
newconn = memp_malloc(MEMP_NETCONN);
|
||||
if (newconn == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->recvmbox = sys_mbox_new();
|
||||
if (newconn->recvmbox == SYS_MBOX_NULL) {
|
||||
memp_free(MEMP_NETCONN, newconn);
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->mbox = sys_mbox_new();
|
||||
if (newconn->mbox == SYS_MBOX_NULL) {
|
||||
sys_mbox_free(newconn->recvmbox);
|
||||
memp_free(MEMP_NETCONN, newconn);
|
||||
return ERR_MEM;
|
||||
}
|
||||
newconn->sem = sys_sem_new(0);
|
||||
if (newconn->sem == SYS_SEM_NULL) {
|
||||
sys_mbox_free(newconn->recvmbox);
|
||||
sys_mbox_free(newconn->mbox);
|
||||
memp_free(MEMP_NETCONN, newconn);
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* Allocations were OK, setup the PCB etc */
|
||||
newconn->type = NETCONN_TCP;
|
||||
newconn->pcb.tcp = newpcb;
|
||||
setup_tcp(newconn);
|
||||
newconn->acceptmbox = SYS_MBOX_NULL;
|
||||
newconn->err = err;
|
||||
/* Register event with callback */
|
||||
if (conn->callback)
|
||||
{
|
||||
(*conn->callback)(conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
}
|
||||
/* We have to set the callback here even though
|
||||
* the new socket is unknown. Mark the socket as -1. */
|
||||
newconn->callback = conn->callback;
|
||||
newconn->socket = -1;
|
||||
newconn->recv_avail = 0;
|
||||
|
||||
sys_mbox_post(mbox, newconn);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
static void
|
||||
do_newconn(struct api_msg_msg *msg)
|
||||
{
|
||||
if(msg->conn->pcb.tcp != NULL) {
|
||||
/* This "new" connection already has a PCB allocated. */
|
||||
/* Is this an error condition? Should it be deleted?
|
||||
We currently just are happy and return. */
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
msg->conn->err = ERR_OK;
|
||||
|
||||
/* Allocate a PCB for this connection */
|
||||
switch(msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field */
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if(msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
if(msg->conn->pcb.tcp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
setup_tcp(msg->conn);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_delconn(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_remove(msg->conn->pcb.raw);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp->recv_arg = NULL;
|
||||
udp_remove(msg->conn->pcb.udp);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||
tcp_arg(msg->conn->pcb.tcp, NULL);
|
||||
tcp_accept(msg->conn->pcb.tcp, NULL);
|
||||
tcp_close(msg->conn->pcb.tcp);
|
||||
} else {
|
||||
tcp_arg(msg->conn->pcb.tcp, NULL);
|
||||
tcp_sent(msg->conn->pcb.tcp, NULL);
|
||||
tcp_recv(msg->conn->pcb.tcp, NULL);
|
||||
tcp_poll(msg->conn->pcb.tcp, NULL, 0);
|
||||
tcp_err(msg->conn->pcb.tcp, NULL);
|
||||
if (tcp_close(msg->conn->pcb.tcp) != ERR_OK) {
|
||||
tcp_abort(msg->conn->pcb.tcp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Trigger select() in socket layer */
|
||||
if (msg->conn->callback)
|
||||
{
|
||||
(*msg->conn->callback)(msg->conn, NETCONN_EVT_RCVPLUS, 0);
|
||||
(*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDPLUS, 0);
|
||||
}
|
||||
|
||||
if (msg->conn->mbox != SYS_MBOX_NULL) {
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_bind(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
setup_tcp(msg->conn);
|
||||
#endif /* LWIP_TCP */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->err = raw_bind(msg->conn->pcb.raw,msg->msg.bc.ipaddr);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
msg->conn->err = udp_bind(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->err = tcp_bind(msg->conn->pcb.tcp,
|
||||
msg->msg.bc.ipaddr, msg->msg.bc.port);
|
||||
#endif /* LWIP_TCP */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
#if LWIP_TCP
|
||||
|
||||
static err_t
|
||||
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
|
||||
{
|
||||
struct netconn *conn;
|
||||
|
||||
conn = arg;
|
||||
|
||||
if (conn == NULL) {
|
||||
return ERR_VAL;
|
||||
}
|
||||
|
||||
conn->err = err;
|
||||
if (conn->type == NETCONN_TCP && err == ERR_OK) {
|
||||
setup_tcp(conn);
|
||||
}
|
||||
sys_mbox_post(conn->mbox, NULL);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_connect(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->pcb.raw = raw_new(msg->msg.bc.port); /* misusing the port field as protocol */
|
||||
raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if (msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if (msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM);
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
case NETCONN_UDP:
|
||||
msg->conn->pcb.udp = udp_new();
|
||||
if (msg->conn->pcb.udp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
udp_recv(msg->conn->pcb.udp, recv_udp, msg->conn);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_new();
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_connect(msg->conn->pcb.raw, msg->msg.bc.ipaddr);
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_connect(msg->conn->pcb.udp, msg->msg.bc.ipaddr, msg->msg.bc.port);
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
/* tcp_arg(msg->conn->pcb.tcp, msg->conn);*/
|
||||
setup_tcp(msg->conn);
|
||||
tcp_connect(msg->conn->pcb.tcp, msg->msg.bc.ipaddr, msg->msg.bc.port,
|
||||
do_connected);
|
||||
/*tcp_output(msg->conn->pcb.tcp);*/
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_disconnect(struct api_msg_msg *msg)
|
||||
{
|
||||
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
/* Do nothing as connecting is only a helper for upper lwip layers */
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_disconnect(msg->conn->pcb.udp);
|
||||
break;
|
||||
#endif
|
||||
case NETCONN_TCP:
|
||||
break;
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_listen(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen RAW: cannot listen for RAW.\n"));
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: listen UDP: cannot listen for UDP.\n"));
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
msg->conn->pcb.tcp = tcp_listen(msg->conn->pcb.tcp);
|
||||
if (msg->conn->pcb.tcp == NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
} else {
|
||||
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
msg->conn->acceptmbox = sys_mbox_new();
|
||||
if (msg->conn->acceptmbox == SYS_MBOX_NULL) {
|
||||
msg->conn->err = ERR_MEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
tcp_arg(msg->conn->pcb.tcp, msg->conn);
|
||||
tcp_accept(msg->conn->pcb.tcp, accept_function);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_accept(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept RAW: cannot accept for RAW.\n"));
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
LWIP_DEBUGF(API_MSG_DEBUG, ("api_msg: accept UDP: cannot accept for UDP.\n"));
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
case NETCONN_TCP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_send(struct api_msg_msg *msg)
|
||||
{
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
raw_send(msg->conn->pcb.raw, msg->msg.p);
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
udp_send(msg->conn->pcb.udp, msg->msg.p);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
case NETCONN_TCP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_recv(struct api_msg_msg *msg)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
if (msg->conn->type == NETCONN_TCP) {
|
||||
tcp_recved(msg->conn->pcb.tcp, msg->msg.len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_write(struct api_msg_msg *msg)
|
||||
{
|
||||
#if LWIP_TCP
|
||||
err_t err;
|
||||
#endif
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
msg->conn->err = ERR_VAL;
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
msg->conn->err = ERR_VAL;
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
err = tcp_write(msg->conn->pcb.tcp, msg->msg.w.dataptr,
|
||||
msg->msg.w.len, msg->msg.w.copy);
|
||||
/* This is the Nagle algorithm: inhibit the sending of new TCP
|
||||
segments when new outgoing data arrives from the user if any
|
||||
previously transmitted data on the connection remains
|
||||
unacknowledged. */
|
||||
if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL ||
|
||||
(msg->conn->pcb.tcp->flags & TF_NODELAY) ||
|
||||
(msg->conn->pcb.tcp->snd_queuelen) > 1)) {
|
||||
tcp_output(msg->conn->pcb.tcp);
|
||||
}
|
||||
msg->conn->err = err;
|
||||
if (msg->conn->callback)
|
||||
if (err == ERR_OK)
|
||||
{
|
||||
if (tcp_sndbuf(msg->conn->pcb.tcp) <= TCP_SNDLOWAT)
|
||||
(*msg->conn->callback)(msg->conn, NETCONN_EVT_SENDMINUS, msg->msg.w.len);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
do_close(struct api_msg_msg *msg)
|
||||
{
|
||||
err_t err;
|
||||
|
||||
err = ERR_OK;
|
||||
|
||||
if (msg->conn->pcb.tcp != NULL) {
|
||||
switch (msg->conn->type) {
|
||||
#if LWIP_RAW
|
||||
case NETCONN_RAW:
|
||||
break;
|
||||
#endif
|
||||
#if LWIP_UDP
|
||||
case NETCONN_UDPLITE:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDPNOCHKSUM:
|
||||
/* FALLTHROUGH */
|
||||
case NETCONN_UDP:
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case NETCONN_TCP:
|
||||
if (msg->conn->pcb.tcp->state == LISTEN) {
|
||||
err = tcp_close(msg->conn->pcb.tcp);
|
||||
}
|
||||
else if (msg->conn->pcb.tcp->state == CLOSE_WAIT) {
|
||||
err = tcp_output(msg->conn->pcb.tcp);
|
||||
}
|
||||
msg->conn->err = err;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
sys_mbox_post(msg->conn->mbox, NULL);
|
||||
}
|
||||
|
||||
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
|
||||
static api_msg_decode decode[API_MSG_MAX] = {
|
||||
do_newconn,
|
||||
do_delconn,
|
||||
do_bind,
|
||||
do_connect,
|
||||
do_disconnect,
|
||||
do_listen,
|
||||
do_accept,
|
||||
do_send,
|
||||
do_recv,
|
||||
do_write,
|
||||
do_close
|
||||
};
|
||||
void
|
||||
api_msg_input(struct api_msg *msg)
|
||||
{
|
||||
decode[msg->type](&(msg->msg));
|
||||
}
|
||||
|
||||
void
|
||||
api_msg_post(struct api_msg *msg)
|
||||
{
|
||||
tcpip_apimsg(msg);
|
||||
}
|
||||
|
||||
|
||||
|
59
Demo/Common/ethernet/lwIP/api/err.c
Normal file
59
Demo/Common/ethernet/lwIP/api/err.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
|
||||
static char *err_strerr[] = {"Ok.",
|
||||
"Out of memory error.",
|
||||
"Buffer error.",
|
||||
"Connection aborted.",
|
||||
"Connection reset.",
|
||||
"Connection closed.",
|
||||
"Not connected.",
|
||||
"Illegal value.",
|
||||
"Illegal argument.",
|
||||
"Routing problem.",
|
||||
"Address in use."
|
||||
};
|
||||
|
||||
|
||||
char *
|
||||
lwip_strerr(err_t err)
|
||||
{
|
||||
return err_strerr[-err];
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* LWIP_DEBUG */
|
1362
Demo/Common/ethernet/lwIP/api/sockets.c
Normal file
1362
Demo/Common/ethernet/lwIP/api/sockets.c
Normal file
File diff suppressed because it is too large
Load diff
198
Demo/Common/ethernet/lwIP/api/tcpip.c
Normal file
198
Demo/Common/ethernet/lwIP/api/tcpip.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
static void (* tcpip_init_done)(void *arg) = NULL;
|
||||
static void *tcpip_init_done_arg;
|
||||
static sys_mbox_t mbox;
|
||||
|
||||
#if LWIP_TCP
|
||||
static int tcpip_tcp_timer_active = 0;
|
||||
|
||||
static void
|
||||
tcpip_tcp_timer(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
/* call TCP timer handler */
|
||||
tcp_tmr();
|
||||
/* timer still needed? */
|
||||
if (tcp_active_pcbs || tcp_tw_pcbs) {
|
||||
/* restart timer */
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
} else {
|
||||
/* disable timer */
|
||||
tcpip_tcp_timer_active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
void
|
||||
tcp_timer_needed(void)
|
||||
{
|
||||
/* timer is off but needed again? */
|
||||
if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
|
||||
/* enable and start timer */
|
||||
tcpip_tcp_timer_active = 1;
|
||||
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* !NO_SYS */
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
#if IP_REASSEMBLY
|
||||
static void
|
||||
ip_timer(void *data)
|
||||
{
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip: ip_reass_tmr()\n"));
|
||||
ip_reass_tmr();
|
||||
sys_timeout(1000, ip_timer, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
tcpip_thread(void *arg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
(void)arg;
|
||||
|
||||
ip_init();
|
||||
#if LWIP_UDP
|
||||
udp_init();
|
||||
#endif
|
||||
#if LWIP_TCP
|
||||
tcp_init();
|
||||
#endif
|
||||
#if IP_REASSEMBLY
|
||||
sys_timeout(1000, ip_timer, NULL);
|
||||
#endif
|
||||
if (tcpip_init_done != NULL) {
|
||||
tcpip_init_done(tcpip_init_done_arg);
|
||||
}
|
||||
|
||||
while (1) { /* MAIN Loop */
|
||||
sys_mbox_fetch(mbox, (void *)&msg);
|
||||
switch (msg->type) {
|
||||
case TCPIP_MSG_API:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg));
|
||||
api_msg_input(msg->msg.apimsg);
|
||||
break;
|
||||
case TCPIP_MSG_INPUT:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: IP packet %p\n", (void *)msg));
|
||||
ip_input(msg->msg.inp.p, msg->msg.inp.netif);
|
||||
break;
|
||||
case TCPIP_MSG_CALLBACK:
|
||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg));
|
||||
msg->msg.cb.f(msg->msg.cb.ctx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
memp_free(MEMP_TCPIP_MSG, msg);
|
||||
}
|
||||
}
|
||||
|
||||
err_t
|
||||
tcpip_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG);
|
||||
if (msg == NULL) {
|
||||
pbuf_free(p);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_INPUT;
|
||||
msg->msg.inp.p = p;
|
||||
msg->msg.inp.netif = inp;
|
||||
sys_mbox_post(mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t
|
||||
tcpip_callback(void (*f)(void *ctx), void *ctx)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG);
|
||||
if (msg == NULL) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
msg->type = TCPIP_MSG_CALLBACK;
|
||||
msg->msg.cb.f = f;
|
||||
msg->msg.cb.ctx = ctx;
|
||||
sys_mbox_post(mbox, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
tcpip_apimsg(struct api_msg *apimsg)
|
||||
{
|
||||
struct tcpip_msg *msg;
|
||||
msg = memp_malloc(MEMP_TCPIP_MSG);
|
||||
if (msg == NULL) {
|
||||
memp_free(MEMP_API_MSG, apimsg);
|
||||
return;
|
||||
}
|
||||
msg->type = TCPIP_MSG_API;
|
||||
msg->msg.apimsg = apimsg;
|
||||
sys_mbox_post(mbox, msg);
|
||||
}
|
||||
|
||||
void
|
||||
tcpip_init(void (* initfunc)(void *), void *arg)
|
||||
{
|
||||
tcpip_init_done = initfunc;
|
||||
tcpip_init_done_arg = arg;
|
||||
mbox = sys_mbox_new();
|
||||
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
1464
Demo/Common/ethernet/lwIP/core/dhcp.c
Normal file
1464
Demo/Common/ethernet/lwIP/core/dhcp.c
Normal file
File diff suppressed because it is too large
Load diff
537
Demo/Common/ethernet/lwIP/core/inet.c
Normal file
537
Demo/Common/ethernet/lwIP/core/inet.c
Normal file
|
@ -0,0 +1,537 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* inet.c
|
||||
*
|
||||
* Functions common to all TCP/IP modules, such as the Internet checksum and the
|
||||
* byte order functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/* These are some reference implementations of the checksum algorithm, with the
|
||||
* aim of being simple, correct and fully portable. Checksumming is the
|
||||
* first thing you would want to optimize for your platform. If you create
|
||||
* your own version, link it in and in your sys_arch.h put:
|
||||
*
|
||||
* #define LWIP_CHKSUM <your_checksum_routine>
|
||||
*/
|
||||
#ifndef LWIP_CHKSUM
|
||||
#define LWIP_CHKSUM lwip_standard_chksum
|
||||
|
||||
#if 1 /* Version A */
|
||||
/**
|
||||
* lwip checksum
|
||||
*
|
||||
* @param dataptr points to start of data to be summed at any boundary
|
||||
* @param len length of data to be summed
|
||||
* @return host order (!) lwip checksum (non-inverted Internet sum)
|
||||
*
|
||||
* @note accumulator size limits summable length to 64k
|
||||
* @note host endianess is irrelevant (p3 RFC1071)
|
||||
*/
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
u16_t src;
|
||||
u8_t *octetptr;
|
||||
|
||||
acc = 0;
|
||||
/* dataptr may be at odd or even addresses */
|
||||
octetptr = (u8_t*)dataptr;
|
||||
while (len > 1)
|
||||
{
|
||||
/* declare first octet as most significant
|
||||
thus assume network order, ignoring host order */
|
||||
src = (*octetptr) << 8;
|
||||
octetptr++;
|
||||
/* declare second octet as least significant */
|
||||
src |= (*octetptr);
|
||||
octetptr++;
|
||||
acc += src;
|
||||
len -= 2;
|
||||
}
|
||||
if (len > 0)
|
||||
{
|
||||
/* accumulate remaining octet */
|
||||
src = (*octetptr) << 8;
|
||||
acc += src;
|
||||
}
|
||||
/* add deferred carry bits */
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
if ((acc & 0xffff0000) != 0) {
|
||||
acc = (acc >> 16) + (acc & 0x0000ffffUL);
|
||||
}
|
||||
/* This maybe a little confusing: reorder sum using htons()
|
||||
instead of ntohs() since it has a little less call overhead.
|
||||
The caller must invert bits for Internet sum ! */
|
||||
return htons((u16_t)acc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* Version B */
|
||||
/*
|
||||
* Curt McDowell
|
||||
* Broadcom Corp.
|
||||
* csm@broadcom.com
|
||||
*
|
||||
* IP checksum two bytes at a time with support for
|
||||
* unaligned buffer.
|
||||
* Works for len up to and including 0x20000.
|
||||
* by Curt McDowell, Broadcom Corp. 12/08/2005
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = dataptr;
|
||||
u16_t *ps, t = 0;
|
||||
u32_t sum = 0;
|
||||
int odd = ((u32_t)pb & 1);
|
||||
|
||||
/* Get aligned to u16_t */
|
||||
if (odd && len > 0) {
|
||||
((u8_t *)&t)[1] = *pb++;
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Add the bulk of the data */
|
||||
ps = (u16_t *)pb;
|
||||
while (len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
/* Consume left-over byte, if any */
|
||||
if (len > 0)
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;;
|
||||
|
||||
/* Add end bytes */
|
||||
sum += t;
|
||||
|
||||
/* Fold 32-bit sum to 16 bits */
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
|
||||
/* Swap if alignment was odd */
|
||||
if (odd)
|
||||
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* Version C */
|
||||
/**
|
||||
* An optimized checksum routine. Basically, it uses loop-unrolling on
|
||||
* the checksum loop, treating the head and tail bytes specially, whereas
|
||||
* the inner loop acts on 8 bytes at a time.
|
||||
*
|
||||
* @arg start of buffer to be checksummed. May be an odd byte address.
|
||||
* @len number of bytes in the buffer to be checksummed.
|
||||
*
|
||||
* by Curt McDowell, Broadcom Corp. December 8th, 2005
|
||||
*/
|
||||
|
||||
static u16_t
|
||||
lwip_standard_chksum(void *dataptr, int len)
|
||||
{
|
||||
u8_t *pb = dataptr;
|
||||
u16_t *ps, t = 0;
|
||||
u32_t *pl;
|
||||
u32_t sum = 0, tmp;
|
||||
/* starts at odd byte address? */
|
||||
int odd = ((u32_t)pb & 1);
|
||||
|
||||
if (odd && len > 0) {
|
||||
((u8_t *)&t)[1] = *pb++;
|
||||
len--;
|
||||
}
|
||||
|
||||
ps = (u16_t *)pb;
|
||||
|
||||
if (((u32_t)ps & 3) && len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
pl = (u32_t *)ps;
|
||||
|
||||
while (len > 7) {
|
||||
tmp = sum + *pl++; /* ping */
|
||||
if (tmp < sum)
|
||||
tmp++; /* add back carry */
|
||||
|
||||
sum = tmp + *pl++; /* pong */
|
||||
if (sum < tmp)
|
||||
sum++; /* add back carry */
|
||||
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
/* make room in upper bits */
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
|
||||
ps = (u16_t *)pl;
|
||||
|
||||
/* 16-bit aligned word remaining? */
|
||||
while (len > 1) {
|
||||
sum += *ps++;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
/* dangling tail byte remaining? */
|
||||
if (len > 0) /* include odd byte */
|
||||
((u8_t *)&t)[0] = *(u8_t *)ps;
|
||||
|
||||
sum += t; /* add end bytes */
|
||||
|
||||
while (sum >> 16) /* combine halves */
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
|
||||
if (odd)
|
||||
sum = ((sum & 0xff) << 8) | ((sum & 0xff00) >> 8);
|
||||
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_CHKSUM */
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
/* iterate through all pbuf in chain */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
|
||||
(void *)q, (void *)q->next));
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
/*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
acc += (src->addr & 0xffffUL);
|
||||
acc += ((src->addr >> 16) & 0xffffUL);
|
||||
acc += (dest->addr & 0xffffUL);
|
||||
acc += ((dest->addr >> 16) & 0xffffUL);
|
||||
acc += (u32_t)htons((u16_t)proto);
|
||||
acc += (u32_t)htons(proto_len);
|
||||
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarily for IP
|
||||
* and ICMP.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc;
|
||||
|
||||
acc = LWIP_CHKSUM(dataptr, len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
inet_chksum_pbuf(struct pbuf *p)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += LWIP_CHKSUM(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffffUL) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = (acc & 0x00ffUL << 8) | (acc & 0xff00UL >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0x00ffUL) << 8) | ((acc & 0xff00UL) >> 8);
|
||||
}
|
||||
return (u16_t)~(acc & 0xffffUL);
|
||||
}
|
||||
|
||||
/* Here for now until needed in other places in lwIP */
|
||||
#ifndef isprint
|
||||
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
|
||||
#define isprint(c) in_range(c, 0x20, 0x7f)
|
||||
#define isdigit(c) in_range(c, '0', '9')
|
||||
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
|
||||
#define islower(c) in_range(c, 'a', 'z')
|
||||
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ascii internet address interpretation routine.
|
||||
* The value returned is in network order.
|
||||
*/
|
||||
|
||||
u32_t
|
||||
inet_addr(const char *cp)
|
||||
{
|
||||
struct in_addr val;
|
||||
|
||||
if (inet_aton(cp, &val)) {
|
||||
return (val.s_addr);
|
||||
}
|
||||
return (INADDR_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether "cp" is a valid ascii representation
|
||||
* of an Internet address and convert to a binary address.
|
||||
* Returns 1 if the address is valid, 0 if not.
|
||||
* This replaces inet_addr, the return value from which
|
||||
* cannot distinguish between failure and a local broadcast address.
|
||||
*/
|
||||
int
|
||||
inet_aton(const char *cp, struct in_addr *addr)
|
||||
{
|
||||
u32_t val;
|
||||
int base, n, c;
|
||||
u32_t parts[4];
|
||||
u32_t *pp = parts;
|
||||
|
||||
c = *cp;
|
||||
for (;;) {
|
||||
/*
|
||||
* Collect number up to ``.''.
|
||||
* Values are specified as for C:
|
||||
* 0x=hex, 0=octal, 1-9=decimal.
|
||||
*/
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
val = 0;
|
||||
base = 10;
|
||||
if (c == '0') {
|
||||
c = *++cp;
|
||||
if (c == 'x' || c == 'X') {
|
||||
base = 16;
|
||||
c = *++cp;
|
||||
} else
|
||||
base = 8;
|
||||
}
|
||||
for (;;) {
|
||||
if (isdigit(c)) {
|
||||
val = (val * base) + (int)(c - '0');
|
||||
c = *++cp;
|
||||
} else if (base == 16 && isxdigit(c)) {
|
||||
val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
/*
|
||||
* Internet format:
|
||||
* a.b.c.d
|
||||
* a.b.c (with c treated as 16 bits)
|
||||
* a.b (with b treated as 24 bits)
|
||||
*/
|
||||
if (pp >= parts + 3)
|
||||
return (0);
|
||||
*pp++ = val;
|
||||
c = *++cp;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Check for trailing characters.
|
||||
*/
|
||||
if (c != '\0' && (!isprint(c) || !isspace(c)))
|
||||
return (0);
|
||||
/*
|
||||
* Concoct the address according to
|
||||
* the number of parts specified.
|
||||
*/
|
||||
n = pp - parts + 1;
|
||||
switch (n) {
|
||||
|
||||
case 0:
|
||||
return (0); /* initial nondigit */
|
||||
|
||||
case 1: /* a -- 32 bits */
|
||||
break;
|
||||
|
||||
case 2: /* a.b -- 8.24 bits */
|
||||
if (val > 0xffffff)
|
||||
return (0);
|
||||
val |= parts[0] << 24;
|
||||
break;
|
||||
|
||||
case 3: /* a.b.c -- 8.8.16 bits */
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16);
|
||||
break;
|
||||
|
||||
case 4: /* a.b.c.d -- 8.8.8.8 bits */
|
||||
if (val > 0xff)
|
||||
return (0);
|
||||
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
|
||||
break;
|
||||
}
|
||||
if (addr)
|
||||
addr->s_addr = htonl(val);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Convert numeric IP address into decimal dotted ASCII representation.
|
||||
* returns ptr to static buffer; not reentrant!
|
||||
*/
|
||||
char *
|
||||
inet_ntoa(struct in_addr addr)
|
||||
{
|
||||
static char str[16];
|
||||
u32_t s_addr = addr.s_addr;
|
||||
char inv[3];
|
||||
char *rp;
|
||||
u8_t *ap;
|
||||
u8_t rem;
|
||||
u8_t n;
|
||||
u8_t i;
|
||||
|
||||
rp = str;
|
||||
ap = (u8_t *)&s_addr;
|
||||
for(n = 0; n < 4; n++) {
|
||||
i = 0;
|
||||
do {
|
||||
rem = *ap % (u8_t)10;
|
||||
*ap /= (u8_t)10;
|
||||
inv[i++] = '0' + rem;
|
||||
} while(*ap);
|
||||
while(i--)
|
||||
*rp++ = inv[i];
|
||||
*rp++ = '.';
|
||||
ap++;
|
||||
}
|
||||
*--rp = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* These are reference implementations of the byte swapping functions.
|
||||
* Again with the aim of being simple, correct and fully portable.
|
||||
* Byte swapping is the second thing you would want to optimize. You will
|
||||
* need to port it to your architecture and in your cc.h:
|
||||
*
|
||||
* #define LWIP_PLATFORM_BYTESWAP 1
|
||||
* #define LWIP_PLATFORM_HTONS(x) <your_htons>
|
||||
* #define LWIP_PLATFORM_HTONL(x) <your_htonl>
|
||||
*
|
||||
* Note ntohs() and ntohl() are merely references to the htonx counterparts.
|
||||
*/
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#error BYTE_ORDER is not defined
|
||||
#endif
|
||||
#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
|
||||
u16_t
|
||||
htons(u16_t n)
|
||||
{
|
||||
return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
u16_t
|
||||
ntohs(u16_t n)
|
||||
{
|
||||
return htons(n);
|
||||
}
|
||||
|
||||
u32_t
|
||||
htonl(u32_t n)
|
||||
{
|
||||
return ((n & 0xff) << 24) |
|
||||
((n & 0xff00) << 8) |
|
||||
((n & 0xff0000) >> 8) |
|
||||
((n & 0xff000000) >> 24);
|
||||
}
|
||||
|
||||
u32_t
|
||||
ntohl(u32_t n)
|
||||
{
|
||||
return htonl(n);
|
||||
}
|
||||
|
||||
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */
|
168
Demo/Common/ethernet/lwIP/core/inet6.c
Normal file
168
Demo/Common/ethernet/lwIP/core/inet6.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* inet6.c
|
||||
*
|
||||
* Functions common to all TCP/IP modules, such as the Internet checksum and the
|
||||
* byte order functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/inet.h"
|
||||
|
||||
|
||||
|
||||
/* chksum:
|
||||
*
|
||||
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
|
||||
* This function is used by the other checksum functions.
|
||||
*
|
||||
* For now, this is not optimized. Must be optimized for the particular processor
|
||||
* arcitecture on which it is to run. Preferebly coded in assembler.
|
||||
*/
|
||||
|
||||
static u32_t
|
||||
chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u16_t *sdataptr = dataptr;
|
||||
u32_t acc;
|
||||
|
||||
|
||||
for(acc = 0; len > 1; len -= 2) {
|
||||
acc += *sdataptr++;
|
||||
}
|
||||
|
||||
/* add up any odd byte */
|
||||
if (len == 1) {
|
||||
acc += htons((u16_t)(*(u8_t *)dataptr) << 8);
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
||||
}
|
||||
|
||||
/* inet_chksum_pseudo:
|
||||
*
|
||||
* Calculates the pseudo Internet checksum used by TCP and UDP for a pbuf chain.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u32_t proto_len)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped, i;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += chksum(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
acc += ((u16_t *)src->addr)[i] & 0xffff;
|
||||
acc += ((u16_t *)dest->addr)[i] & 0xffff;
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
}
|
||||
acc += (u16_t)htons((u16_t)proto);
|
||||
acc += ((u16_t *)&proto_len)[0] & 0xffff;
|
||||
acc += ((u16_t *)&proto_len)[1] & 0xffff;
|
||||
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
}
|
||||
|
||||
/* inet_chksum:
|
||||
*
|
||||
* Calculates the Internet checksum over a portion of memory. Used primarely for IP
|
||||
* and ICMP.
|
||||
*/
|
||||
|
||||
u16_t
|
||||
inet_chksum(void *dataptr, u16_t len)
|
||||
{
|
||||
u32_t acc, sum;
|
||||
|
||||
acc = chksum(dataptr, len);
|
||||
sum = (acc & 0xffff) + (acc >> 16);
|
||||
sum += (sum >> 16);
|
||||
return ~(sum & 0xffff);
|
||||
}
|
||||
|
||||
u16_t
|
||||
inet_chksum_pbuf(struct pbuf *p)
|
||||
{
|
||||
u32_t acc;
|
||||
struct pbuf *q;
|
||||
u8_t swapped;
|
||||
|
||||
acc = 0;
|
||||
swapped = 0;
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
acc += chksum(q->payload, q->len);
|
||||
while (acc >> 16) {
|
||||
acc = (acc & 0xffff) + (acc >> 16);
|
||||
}
|
||||
if (q->len % 2 != 0) {
|
||||
swapped = 1 - swapped;
|
||||
acc = (acc & 0xff << 8) | (acc & 0xff00 >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (swapped) {
|
||||
acc = ((acc & 0xff) << 8) | ((acc & 0xff00) >> 8);
|
||||
}
|
||||
return ~(acc & 0xffff);
|
||||
}
|
||||
|
202
Demo/Common/ethernet/lwIP/core/ipv4/icmp.c
Normal file
202
Demo/Common/ethernet/lwIP/core/ipv4/icmp.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/* Some ICMP messages should be passed to the transport protocols. This
|
||||
is not implemented. */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
void
|
||||
icmp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
u8_t type;
|
||||
u8_t code;
|
||||
struct icmp_echo_hdr *iecho;
|
||||
struct ip_hdr *iphdr;
|
||||
struct ip_addr tmpaddr;
|
||||
u16_t hlen;
|
||||
|
||||
ICMP_STATS_INC(icmp.recv);
|
||||
snmp_inc_icmpinmsgs();
|
||||
|
||||
|
||||
iphdr = p->payload;
|
||||
hlen = IPH_HL(iphdr) * 4;
|
||||
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
}
|
||||
|
||||
type = *((u8_t *)p->payload);
|
||||
code = *(((u8_t *)p->payload)+1);
|
||||
switch (type) {
|
||||
case ICMP_ECHO:
|
||||
/* broadcast or multicast destination address? */
|
||||
if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));
|
||||
ICMP_STATS_INC(icmp.err);
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));
|
||||
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.lenerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
|
||||
return;
|
||||
}
|
||||
iecho = p->payload;
|
||||
if (inet_chksum_pbuf(p) != 0) {
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
|
||||
pbuf_free(p);
|
||||
ICMP_STATS_INC(icmp.chkerr);
|
||||
snmp_inc_icmpinerrors();
|
||||
return;
|
||||
}
|
||||
tmpaddr.addr = iphdr->src.addr;
|
||||
iphdr->src.addr = iphdr->dest.addr;
|
||||
iphdr->dest.addr = tmpaddr.addr;
|
||||
ICMPH_TYPE_SET(iecho, ICMP_ER);
|
||||
/* adjust the checksum */
|
||||
if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8) + 1;
|
||||
} else {
|
||||
iecho->chksum += htons(ICMP_ECHO << 8);
|
||||
}
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of echo replies attempted to send */
|
||||
snmp_inc_icmpoutechoreps();
|
||||
|
||||
pbuf_header(p, hlen);
|
||||
ip_output_if(p, &(iphdr->src), IP_HDRINCL,
|
||||
IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code));
|
||||
ICMP_STATS_INC(icmp.proterr);
|
||||
ICMP_STATS_INC(icmp.drop);
|
||||
}
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
void
|
||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_dur_hdr *idur;
|
||||
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
/* ICMP header + IP header + 8 bytes of data */
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
idur = q->payload;
|
||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
||||
ICMPH_CODE_SET(idur, t);
|
||||
|
||||
memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
idur->chksum = 0;
|
||||
idur->chksum = inet_chksum(idur, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of destination unreachable messages attempted to send */
|
||||
snmp_inc_icmpoutdestunreachs();
|
||||
|
||||
ip_output(q, NULL, &(iphdr->src),
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#if IP_FORWARD
|
||||
void
|
||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *iphdr;
|
||||
struct icmp_te_hdr *tehdr;
|
||||
|
||||
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
|
||||
|
||||
iphdr = p->payload;
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, (" to "));
|
||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||
|
||||
tehdr = q->payload;
|
||||
ICMPH_TYPE_SET(tehdr, ICMP_TE);
|
||||
ICMPH_CODE_SET(tehdr, t);
|
||||
|
||||
/* copy fields from original packet */
|
||||
memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);
|
||||
|
||||
/* calculate checksum */
|
||||
tehdr->chksum = 0;
|
||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
||||
ICMP_STATS_INC(icmp.xmit);
|
||||
/* increase number of messages attempted to send */
|
||||
snmp_inc_icmpoutmsgs();
|
||||
/* increase number of destination unreachable messages attempted to send */
|
||||
snmp_inc_icmpouttimeexcds();
|
||||
ip_output(q, NULL, &(iphdr->src),
|
||||
ICMP_TTL, 0, IP_PROTO_ICMP);
|
||||
pbuf_free(q);
|
||||
}
|
||||
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
515
Demo/Common/ethernet/lwIP/core/ipv4/ip.c
Normal file
515
Demo/Common/ethernet/lwIP/core/ipv4/ip.c
Normal file
|
@ -0,0 +1,515 @@
|
|||
/* @file
|
||||
*
|
||||
* This is the IP layer implementation for incoming and outgoing IP traffic.
|
||||
*
|
||||
* @see ip_frag.c
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
|
||||
#include "lwip/snmp.h"
|
||||
#if LWIP_DHCP
|
||||
# include "lwip/dhcp.h"
|
||||
#endif /* LWIP_DHCP */
|
||||
|
||||
/**
|
||||
* Initializes the IP layer.
|
||||
*/
|
||||
|
||||
void
|
||||
ip_init(void)
|
||||
{
|
||||
#if IP_FRAG
|
||||
ip_frag_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the appropriate network interface for a given IP address. It
|
||||
* searches the list of network interfaces linearly. A match is found
|
||||
* if the masked IP address of the network interface equals the masked
|
||||
* IP address given to the function.
|
||||
*/
|
||||
|
||||
struct netif *
|
||||
ip_route(struct ip_addr *dest)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
/* iterate through netifs */
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
/* network mask matches? */
|
||||
if (ip_addr_netcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
|
||||
/* return netif on which to forward IP packet */
|
||||
return netif;
|
||||
}
|
||||
}
|
||||
/* no matching netif found, use default netif */
|
||||
return netif_default;
|
||||
}
|
||||
#if IP_FORWARD
|
||||
|
||||
/**
|
||||
* Forwards an IP packet. It finds an appropriate route for the
|
||||
* packet, decrements the TTL value of the packet, adjusts the
|
||||
* checksum and outputs the packet on the appropriate interface.
|
||||
*/
|
||||
|
||||
static struct netif *
|
||||
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
PERF_START;
|
||||
/* Find network interface where to forward this IP packet to. */
|
||||
netif = ip_route((struct ip_addr *)&(iphdr->dest));
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%"X32_F" found\n",
|
||||
iphdr->dest.addr));
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
/* Do not forward packets onto the same network interface on which
|
||||
* they arrived. */
|
||||
if (netif == inp) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* decrement TTL */
|
||||
IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
|
||||
/* send ICMP if TTL == 0 */
|
||||
if (IPH_TTL(iphdr) == 0) {
|
||||
snmp_inc_ipinhdrerrors();
|
||||
/* Don't send ICMP messages in response to ICMP messages */
|
||||
if (IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
|
||||
icmp_time_exceeded(p, ICMP_TE_TTL);
|
||||
}
|
||||
return (struct netif *)NULL;
|
||||
}
|
||||
|
||||
/* Incrementally update the IP checksum. */
|
||||
if (IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
|
||||
} else {
|
||||
IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%"X32_F"\n",
|
||||
iphdr->dest.addr));
|
||||
|
||||
IP_STATS_INC(ip.fw);
|
||||
IP_STATS_INC(ip.xmit);
|
||||
snmp_inc_ipforwdatagrams();
|
||||
|
||||
PERF_STOP("ip_forward");
|
||||
/* transmit pbuf on chosen interface */
|
||||
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
|
||||
return netif;
|
||||
}
|
||||
#endif /* IP_FORWARD */
|
||||
|
||||
/**
|
||||
* This function is called by the network interface device driver when
|
||||
* an IP packet is received. The function does the basic checks of the
|
||||
* IP header such as packet size being at least larger than the header
|
||||
* size etc. If the packet was not destined for us, the packet is
|
||||
* forwarded (using ip_forward). The IP checksum is always checked.
|
||||
*
|
||||
* Finally, the packet is sent to the upper layer protocol input function.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_input(struct pbuf *p, struct netif *inp) {
|
||||
struct ip_hdr *iphdr;
|
||||
struct netif *netif;
|
||||
u16_t iphdrlen;
|
||||
|
||||
IP_STATS_INC(ip.recv);
|
||||
snmp_inc_ipinreceives();
|
||||
|
||||
/* identify the IP header */
|
||||
iphdr = p->payload;
|
||||
if (IPH_V(iphdr) != 4) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %"U16_F"\n", IPH_V(iphdr)));
|
||||
ip_debug_print(p);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.err);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipinhdrerrors();
|
||||
return ERR_OK;
|
||||
}
|
||||
/* obtain IP header length in number of 32-bit words */
|
||||
iphdrlen = IPH_HL(iphdr);
|
||||
/* calculate IP header length in bytes */
|
||||
iphdrlen *= 4;
|
||||
|
||||
/* header length exceeds first pbuf length? */
|
||||
if (iphdrlen > p->len) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP header (len %"U16_F") does not fit in first pbuf (len %"U16_F"), IP packet droppped.\n",
|
||||
iphdrlen, p->len));
|
||||
/* free (drop) packet pbufs */
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.lenerr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipindiscards();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* verify checksum */
|
||||
#if CHECKSUM_CHECK_IP
|
||||
if (inet_chksum(iphdr, iphdrlen) != 0) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
|
||||
ip_debug_print(p);
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.chkerr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipinhdrerrors();
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Trim pbuf. This should have been done at the netif layer,
|
||||
* but we'll do it anyway just to be sure that its done. */
|
||||
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
|
||||
|
||||
/* match packet against an interface, i.e. is this packet for us? */
|
||||
for (netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
|
||||
iphdr->dest.addr, netif->ip_addr.addr,
|
||||
iphdr->dest.addr & netif->netmask.addr,
|
||||
netif->ip_addr.addr & netif->netmask.addr,
|
||||
iphdr->dest.addr & ~(netif->netmask.addr)));
|
||||
|
||||
/* interface is up and configured? */
|
||||
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
|
||||
{
|
||||
/* unicast to this interface address? */
|
||||
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
|
||||
/* or broadcast on this interface network address? */
|
||||
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
|
||||
netif->name[0], netif->name[1]));
|
||||
/* break out of for loop */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if LWIP_DHCP
|
||||
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
|
||||
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
|
||||
* According to RFC 1542 section 3.1.1, referred by RFC 2131).
|
||||
*/
|
||||
if (netif == NULL) {
|
||||
/* remote port is DHCP server? */
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDP) {
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %"U16_F"\n",
|
||||
ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
|
||||
if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
|
||||
netif = inp;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LWIP_DHCP */
|
||||
/* packet not for us? */
|
||||
if (netif == NULL) {
|
||||
/* packet not for us, route or discard */
|
||||
LWIP_DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
|
||||
#if IP_FORWARD
|
||||
/* non-broadcast packet? */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp)) {
|
||||
/* try to forward IP packet on (other) interfaces */
|
||||
ip_forward(p, iphdr, inp);
|
||||
}
|
||||
else
|
||||
#endif /* IP_FORWARD */
|
||||
{
|
||||
snmp_inc_ipinaddrerrors();
|
||||
snmp_inc_ipindiscards();
|
||||
}
|
||||
pbuf_free(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
/* packet consists of multiple fragments? */
|
||||
if ((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
|
||||
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
|
||||
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
|
||||
/* reassemble the packet*/
|
||||
p = ip_reass(p);
|
||||
/* packet not fully reassembled yet? */
|
||||
if (p == NULL) {
|
||||
return ERR_OK;
|
||||
}
|
||||
iphdr = p->payload;
|
||||
#else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n",
|
||||
ntohs(IPH_OFFSET(iphdr))));
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
/* unsupported protocol feature */
|
||||
snmp_inc_ipinunknownprotos();
|
||||
return ERR_OK;
|
||||
#endif /* IP_REASSEMBLY */
|
||||
}
|
||||
|
||||
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
|
||||
if (iphdrlen > IP_HLEN) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
|
||||
pbuf_free(p);
|
||||
IP_STATS_INC(ip.opterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
/* unsupported protocol feature */
|
||||
snmp_inc_ipinunknownprotos();
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif /* IP_OPTIONS == 0 */
|
||||
|
||||
/* send to upper layers */
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
|
||||
ip_debug_print(p);
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len));
|
||||
|
||||
#if LWIP_RAW
|
||||
/* raw input did not eat the packet? */
|
||||
if (raw_input(p, inp) == 0) {
|
||||
#endif /* LWIP_RAW */
|
||||
|
||||
switch (IPH_PROTO(iphdr)) {
|
||||
#if LWIP_UDP
|
||||
case IP_PROTO_UDP:
|
||||
case IP_PROTO_UDPLITE:
|
||||
snmp_inc_ipindelivers();
|
||||
udp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_UDP */
|
||||
#if LWIP_TCP
|
||||
case IP_PROTO_TCP:
|
||||
snmp_inc_ipindelivers();
|
||||
tcp_input(p, inp);
|
||||
break;
|
||||
#endif /* LWIP_TCP */
|
||||
case IP_PROTO_ICMP:
|
||||
snmp_inc_ipindelivers();
|
||||
icmp_input(p, inp);
|
||||
break;
|
||||
default:
|
||||
/* send ICMP destination protocol unreachable unless is was a broadcast */
|
||||
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&
|
||||
!ip_addr_ismulticast(&(iphdr->dest))) {
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PROTO);
|
||||
}
|
||||
pbuf_free(p);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %"U16_F"\n", IPH_PROTO(iphdr)));
|
||||
|
||||
IP_STATS_INC(ip.proterr);
|
||||
IP_STATS_INC(ip.drop);
|
||||
snmp_inc_ipinunknownprotos();
|
||||
}
|
||||
#if LWIP_RAW
|
||||
} /* LWIP_RAW */
|
||||
#endif
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an IP packet on a network interface. This function constructs
|
||||
* the IP header and calculates the IP header checksum. If the source
|
||||
* IP address is NULL, the IP address of the outgoing network
|
||||
* interface is filled in as source address.
|
||||
*
|
||||
* @note ip_id: RFC791 "some host may be able to simply use
|
||||
* unique identifiers independent of destination"
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos,
|
||||
u8_t proto, struct netif *netif)
|
||||
{
|
||||
struct ip_hdr *iphdr;
|
||||
static u16_t ip_id = 0;
|
||||
|
||||
snmp_inc_ipoutrequests();
|
||||
|
||||
if (dest != IP_HDRINCL) {
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
|
||||
|
||||
IP_STATS_INC(ip.err);
|
||||
snmp_inc_ipoutdiscards();
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
IPH_TTL_SET(iphdr, ttl);
|
||||
IPH_PROTO_SET(iphdr, proto);
|
||||
|
||||
ip_addr_set(&(iphdr->dest), dest);
|
||||
|
||||
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, tos);
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_OFFSET_SET(iphdr, htons(IP_DF));
|
||||
IPH_ID_SET(iphdr, htons(ip_id));
|
||||
++ip_id;
|
||||
|
||||
if (ip_addr_isany(src)) {
|
||||
ip_addr_set(&(iphdr->src), &(netif->ip_addr));
|
||||
} else {
|
||||
ip_addr_set(&(iphdr->src), src);
|
||||
}
|
||||
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
#if CHECKSUM_GEN_IP
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
#endif
|
||||
} else {
|
||||
iphdr = p->payload;
|
||||
dest = &(iphdr->dest);
|
||||
}
|
||||
|
||||
#if IP_FRAG
|
||||
/* don't fragment if interface has mtu set to 0 [loopif] */
|
||||
if (netif->mtu && (p->tot_len > netif->mtu))
|
||||
return ip_frag(p,netif,dest);
|
||||
#endif
|
||||
|
||||
IP_STATS_INC(ip.xmit);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], netif->num));
|
||||
ip_debug_print(p);
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
|
||||
|
||||
return netif->output(netif, p, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple interface to ip_output_if. It finds the outgoing network
|
||||
* interface and calls upon ip_output_if to do the actual work.
|
||||
*/
|
||||
|
||||
err_t
|
||||
ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto)
|
||||
{
|
||||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(dest)) == NULL) {
|
||||
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%"X32_F"\n", dest->addr));
|
||||
|
||||
IP_STATS_INC(ip.rterr);
|
||||
snmp_inc_ipoutnoroutes();
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
|
||||
}
|
||||
|
||||
#if IP_DEBUG
|
||||
void
|
||||
ip_debug_print(struct pbuf *p)
|
||||
{
|
||||
struct ip_hdr *iphdr = p->payload;
|
||||
u8_t *payload;
|
||||
|
||||
payload = (u8_t *)iphdr + IP_HLEN;
|
||||
|
||||
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",
|
||||
IPH_V(iphdr),
|
||||
IPH_HL(iphdr),
|
||||
IPH_TOS(iphdr),
|
||||
ntohs(IPH_LEN(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n",
|
||||
ntohs(IPH_ID(iphdr)),
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
|
||||
ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n",
|
||||
IPH_TTL(iphdr),
|
||||
IPH_PROTO(iphdr),
|
||||
ntohs(IPH_CHKSUM(iphdr))));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n",
|
||||
ip4_addr1(&iphdr->src),
|
||||
ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src),
|
||||
ip4_addr4(&iphdr->src)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (dest)\n",
|
||||
ip4_addr1(&iphdr->dest),
|
||||
ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest),
|
||||
ip4_addr4(&iphdr->dest)));
|
||||
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
78
Demo/Common/ethernet/lwIP/core/ipv4/ip_addr.c
Normal file
78
Demo/Common/ethernet/lwIP/core/ipv4/ip_addr.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#define IP_ADDR_ANY_VALUE 0x00000000UL
|
||||
#define IP_ADDR_BROADCAST_VALUE 0xffffffffUL
|
||||
|
||||
/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
|
||||
const struct ip_addr ip_addr_any = { IP_ADDR_ANY_VALUE };
|
||||
const struct ip_addr ip_addr_broadcast = { IP_ADDR_BROADCAST_VALUE };
|
||||
|
||||
/* Determine if an address is a broadcast address on a network interface
|
||||
*
|
||||
* @param addr address to be checked
|
||||
* @param netif the network interface against which the address is checked
|
||||
* @return returns non-zero if the address is a broadcast address
|
||||
*
|
||||
*/
|
||||
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *addr, struct netif *netif)
|
||||
{
|
||||
u32_t addr2test;
|
||||
|
||||
addr2test = addr->addr;
|
||||
/* all ones (broadcast) or all zeroes (old skool broadcast) */
|
||||
if ((~addr2test == IP_ADDR_ANY_VALUE) ||
|
||||
(addr2test == IP_ADDR_ANY_VALUE))
|
||||
return 1;
|
||||
/* no broadcast support on this network interface? */
|
||||
else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0)
|
||||
/* the given address cannot be a broadcast address
|
||||
* nor can we check against any broadcast addresses */
|
||||
return 0;
|
||||
/* address matches network interface address exactly? => no broadcast */
|
||||
else if (addr2test == netif->ip_addr.addr)
|
||||
return 0;
|
||||
/* on the same (sub) network... */
|
||||
else if (ip_addr_netcmp(addr, &(netif->ip_addr), &(netif->netmask))
|
||||
/* ...and host identifier bits are all ones? =>... */
|
||||
&& ((addr2test & ~netif->netmask.addr) ==
|
||||
(IP_ADDR_BROADCAST_VALUE & ~netif->netmask.addr)))
|
||||
/* => network broadcast address */
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
388
Demo/Common/ethernet/lwIP/core/ipv4/ip_frag.c
Normal file
388
Demo/Common/ethernet/lwIP/core/ipv4/ip_frag.c
Normal file
|
@ -0,0 +1,388 @@
|
|||
/* @file
|
||||
*
|
||||
* This is the IP packet segmentation and reassembly implementation.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Jani Monoses <jani@iv.ro>
|
||||
* original reassembly code by Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
static u8_t ip_reassbuf[IP_HLEN + IP_REASS_BUFSIZE];
|
||||
static u8_t ip_reassbitmap[IP_REASS_BUFSIZE / (8 * 8) + 1];
|
||||
static const u8_t bitmap_bits[8] = { 0xff, 0x7f, 0x3f, 0x1f,
|
||||
0x0f, 0x07, 0x03, 0x01
|
||||
};
|
||||
static u16_t ip_reasslen;
|
||||
static u8_t ip_reassflags;
|
||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||
|
||||
static u8_t ip_reasstmr;
|
||||
|
||||
/*
|
||||
* Copy len bytes from offset in pbuf to buffer
|
||||
*
|
||||
* helper used by both ip_reass and ip_frag
|
||||
*/
|
||||
static struct pbuf *
|
||||
copy_from_pbuf(struct pbuf *p, u16_t * offset,
|
||||
u8_t * buffer, u16_t len)
|
||||
{
|
||||
u16_t l;
|
||||
|
||||
p->payload = (u8_t *)p->payload + *offset;
|
||||
p->len -= *offset;
|
||||
while (len) {
|
||||
l = len < p->len ? len : p->len;
|
||||
memcpy(buffer, p->payload, l);
|
||||
buffer += l;
|
||||
len -= l;
|
||||
if (len)
|
||||
p = p->next;
|
||||
else
|
||||
*offset = l;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes IP reassembly and fragmentation states.
|
||||
*/
|
||||
void
|
||||
ip_frag_init(void)
|
||||
{
|
||||
ip_reasstmr = 0;
|
||||
ip_reassflags = 0;
|
||||
ip_reasslen = 0;
|
||||
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reassembly timer base function
|
||||
* for both NO_SYS == 0 and 1 (!).
|
||||
*
|
||||
* Should be called every 1000 msec.
|
||||
*/
|
||||
void
|
||||
ip_reass_tmr(void)
|
||||
{
|
||||
if (ip_reasstmr > 0) {
|
||||
ip_reasstmr--;
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass_tmr: timer dec %"U16_F"\n",(u16_t)ip_reasstmr));
|
||||
if (ip_reasstmr == 0) {
|
||||
/* reassembly timed out */
|
||||
snmp_inc_ipreasmfails();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reassembles incoming IP fragments into an IP datagram.
|
||||
*
|
||||
* @param p points to a pbuf chain of the fragment
|
||||
* @return NULL if reassembly is incomplete, ? otherwise
|
||||
*/
|
||||
struct pbuf *
|
||||
ip_reass(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
struct ip_hdr *fraghdr, *iphdr;
|
||||
u16_t offset, len;
|
||||
u16_t i;
|
||||
|
||||
IPFRAG_STATS_INC(ip_frag.recv);
|
||||
snmp_inc_ipreasmreqds();
|
||||
|
||||
iphdr = (struct ip_hdr *) ip_reassbuf;
|
||||
fraghdr = (struct ip_hdr *) p->payload;
|
||||
/* If ip_reasstmr is zero, no packet is present in the buffer, so we
|
||||
write the IP header of the fragment into the reassembly
|
||||
buffer. The timer is updated with the maximum age. */
|
||||
if (ip_reasstmr == 0) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: new packet\n"));
|
||||
memcpy(iphdr, fraghdr, IP_HLEN);
|
||||
ip_reasstmr = IP_REASS_MAXAGE;
|
||||
ip_reassflags = 0;
|
||||
/* Clear the bitmap. */
|
||||
memset(ip_reassbitmap, 0, sizeof(ip_reassbitmap));
|
||||
}
|
||||
|
||||
/* Check if the incoming fragment matches the one currently present
|
||||
in the reasembly buffer. If so, we proceed with copying the
|
||||
fragment into the buffer. */
|
||||
if (ip_addr_cmp(&iphdr->src, &fraghdr->src) &&
|
||||
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
|
||||
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
|
||||
ntohs(IPH_ID(fraghdr))));
|
||||
IPFRAG_STATS_INC(ip_frag.cachehit);
|
||||
/* Find out the offset in the reassembly buffer where we should
|
||||
copy the fragment. */
|
||||
len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
|
||||
offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
|
||||
|
||||
/* If the offset or the offset + fragment length overflows the
|
||||
reassembly buffer, we discard the entire packet. */
|
||||
if ((offset > IP_REASS_BUFSIZE) || ((offset + len) > IP_REASS_BUFSIZE)) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: fragment outside of buffer (%"S16_F":%"S16_F"/%"S16_F").\n", offset,
|
||||
offset + len, IP_REASS_BUFSIZE));
|
||||
ip_reasstmr = 0;
|
||||
snmp_inc_ipreasmfails();
|
||||
goto nullreturn;
|
||||
}
|
||||
|
||||
/* Copy the fragment into the reassembly buffer, at the right
|
||||
offset. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: copying with offset %"S16_F" into %"S16_F":%"S16_F"\n", offset,
|
||||
IP_HLEN + offset, IP_HLEN + offset + len));
|
||||
i = IPH_HL(fraghdr) * 4;
|
||||
copy_from_pbuf(p, &i, &ip_reassbuf[IP_HLEN + offset], len);
|
||||
|
||||
/* Update the bitmap. */
|
||||
if (offset / (8 * 8) == (offset + len) / (8 * 8)) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: updating single byte in bitmap.\n"));
|
||||
/* If the two endpoints are in the same byte, we only update that byte. */
|
||||
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||
ip_reassbitmap[offset / (8 * 8)] |=
|
||||
bitmap_bits[(offset / 8) & 7] &
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
} else {
|
||||
/* If the two endpoints are in different bytes, we update the
|
||||
bytes in the endpoints and fill the stuff inbetween with
|
||||
0xff. */
|
||||
LWIP_ASSERT("offset / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||
offset / (8 * 8) < sizeof(ip_reassbitmap));
|
||||
ip_reassbitmap[offset / (8 * 8)] |= bitmap_bits[(offset / 8) & 7];
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: updating many bytes in bitmap (%"S16_F":%"S16_F").\n",
|
||||
1 + offset / (8 * 8), (offset + len) / (8 * 8)));
|
||||
for (i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) {
|
||||
ip_reassbitmap[i] = 0xff;
|
||||
}
|
||||
LWIP_ASSERT("(offset + len) / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||
(offset + len) / (8 * 8) < sizeof(ip_reassbitmap));
|
||||
ip_reassbitmap[(offset + len) / (8 * 8)] |=
|
||||
~bitmap_bits[((offset + len) / 8) & 7];
|
||||
}
|
||||
|
||||
/* If this fragment has the More Fragments flag set to zero, we
|
||||
know that this is the last fragment, so we can calculate the
|
||||
size of the entire packet. We also set the
|
||||
IP_REASS_FLAG_LASTFRAG flag to indicate that we have received
|
||||
the final fragment. */
|
||||
|
||||
if ((ntohs(IPH_OFFSET(fraghdr)) & IP_MF) == 0) {
|
||||
ip_reassflags |= IP_REASS_FLAG_LASTFRAG;
|
||||
ip_reasslen = offset + len;
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, total len %"S16_F"\n",
|
||||
ip_reasslen));
|
||||
}
|
||||
|
||||
/* Finally, we check if we have a full packet in the buffer. We do
|
||||
this by checking if we have the last fragment and if all bits
|
||||
in the bitmap are set. */
|
||||
if (ip_reassflags & IP_REASS_FLAG_LASTFRAG) {
|
||||
/* Check all bytes up to and including all but the last byte in
|
||||
the bitmap. */
|
||||
LWIP_ASSERT("ip_reasslen / (8 * 8) - 1 < sizeof(ip_reassbitmap)",
|
||||
ip_reasslen / (8 * 8) - 1 < ((u16_t) sizeof(ip_reassbitmap)));
|
||||
for (i = 0; i < ip_reasslen / (8 * 8) - 1; ++i) {
|
||||
if (ip_reassbitmap[i] != 0xff) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %"S16_F"/%"S16_F" failed (%"X16_F")\n",
|
||||
i, ip_reasslen / (8 * 8) - 1, ip_reassbitmap[i]));
|
||||
goto nullreturn;
|
||||
}
|
||||
}
|
||||
/* Check the last byte in the bitmap. It should contain just the
|
||||
right amount of bits. */
|
||||
LWIP_ASSERT("ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap)",
|
||||
ip_reasslen / (8 * 8) < sizeof(ip_reassbitmap));
|
||||
if (ip_reassbitmap[ip_reasslen / (8 * 8)] !=
|
||||
(u8_t) ~ bitmap_bits[ip_reasslen / 8 & 7]) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: last fragment seen, bitmap %"S16_F" didn't contain %"X16_F" (%"X16_F")\n",
|
||||
ip_reasslen / (8 * 8), ~bitmap_bits[ip_reasslen / 8 & 7],
|
||||
ip_reassbitmap[ip_reasslen / (8 * 8)]));
|
||||
goto nullreturn;
|
||||
}
|
||||
|
||||
/* Pretend to be a "normal" (i.e., not fragmented) IP packet
|
||||
from now on. */
|
||||
ip_reasslen += IP_HLEN;
|
||||
|
||||
IPH_LEN_SET(iphdr, htons(ip_reasslen));
|
||||
IPH_OFFSET_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
/* If we have come this far, we have a full packet in the
|
||||
buffer, so we allocate a pbuf and copy the packet into it. We
|
||||
also reset the timer. */
|
||||
ip_reasstmr = 0;
|
||||
pbuf_free(p);
|
||||
p = pbuf_alloc(PBUF_LINK, ip_reasslen, PBUF_POOL);
|
||||
if (p != NULL) {
|
||||
i = 0;
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
/* Copy enough bytes to fill this pbuf in the chain. The
|
||||
available data in the pbuf is given by the q->len variable. */
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: memcpy from %p (%"S16_F") to %p, %"S16_F" bytes\n",
|
||||
(void *)&ip_reassbuf[i], i, q->payload,
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len));
|
||||
memcpy(q->payload, &ip_reassbuf[i],
|
||||
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
|
||||
i += q->len;
|
||||
}
|
||||
IPFRAG_STATS_INC(ip_frag.fw);
|
||||
snmp_inc_ipreasmoks();
|
||||
} else {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG,
|
||||
("ip_reass: pbuf_alloc(PBUF_LINK, ip_reasslen=%"U16_F", PBUF_POOL) failed\n", ip_reasslen));
|
||||
IPFRAG_STATS_INC(ip_frag.memerr);
|
||||
snmp_inc_ipreasmfails();
|
||||
}
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
nullreturn:
|
||||
IPFRAG_STATS_INC(ip_frag.drop);
|
||||
pbuf_free(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static u8_t buf[MEM_ALIGN_SIZE(IP_FRAG_MAX_MTU)];
|
||||
|
||||
/**
|
||||
* Fragment an IP datagram if too large for the netif.
|
||||
*
|
||||
* Chop the datagram in MTU sized chunks and send them in order
|
||||
* by using a fixed size static memory buffer (PBUF_ROM)
|
||||
*/
|
||||
err_t
|
||||
ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
|
||||
{
|
||||
struct pbuf *rambuf;
|
||||
struct pbuf *header;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t nfb = 0;
|
||||
u16_t left, cop;
|
||||
u16_t mtu = netif->mtu;
|
||||
u16_t ofo, omf;
|
||||
u16_t last;
|
||||
u16_t poff = IP_HLEN;
|
||||
u16_t tmp;
|
||||
|
||||
/* Get a RAM based MTU sized pbuf */
|
||||
rambuf = pbuf_alloc(PBUF_LINK, 0, PBUF_REF);
|
||||
if (rambuf == NULL) {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc(PBUF_LINK, 0, PBUF_REF) failed\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
rambuf->tot_len = rambuf->len = mtu;
|
||||
rambuf->payload = MEM_ALIGN((void *)buf);
|
||||
|
||||
/* Copy the IP header in it */
|
||||
iphdr = rambuf->payload;
|
||||
memcpy(iphdr, p->payload, IP_HLEN);
|
||||
|
||||
/* Save original offset */
|
||||
tmp = ntohs(IPH_OFFSET(iphdr));
|
||||
ofo = tmp & IP_OFFMASK;
|
||||
omf = tmp & IP_MF;
|
||||
|
||||
left = p->tot_len - IP_HLEN;
|
||||
|
||||
while (left) {
|
||||
last = (left <= mtu - IP_HLEN);
|
||||
|
||||
/* Set new offset and MF flag */
|
||||
ofo += nfb;
|
||||
tmp = omf | (IP_OFFMASK & (ofo));
|
||||
if (!last)
|
||||
tmp = tmp | IP_MF;
|
||||
IPH_OFFSET_SET(iphdr, htons(tmp));
|
||||
|
||||
/* Fill this fragment */
|
||||
nfb = (mtu - IP_HLEN) / 8;
|
||||
cop = last ? left : nfb * 8;
|
||||
|
||||
p = copy_from_pbuf(p, &poff, (u8_t *) iphdr + IP_HLEN, cop);
|
||||
|
||||
/* Correct header */
|
||||
IPH_LEN_SET(iphdr, htons(cop + IP_HLEN));
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
if (last)
|
||||
pbuf_realloc(rambuf, left + IP_HLEN);
|
||||
/* This part is ugly: we alloc a RAM based pbuf for
|
||||
* the link level header for each chunk and then
|
||||
* free it.A PBUF_ROM style pbuf for which pbuf_header
|
||||
* worked would make things simpler.
|
||||
*/
|
||||
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
|
||||
if (header != NULL) {
|
||||
pbuf_chain(header, rambuf);
|
||||
netif->output(netif, header, dest);
|
||||
IPFRAG_STATS_INC(ip_frag.xmit);
|
||||
snmp_inc_ipfragcreates();
|
||||
pbuf_free(header);
|
||||
} else {
|
||||
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_frag: pbuf_alloc() for header failed\n"));
|
||||
pbuf_free(rambuf);
|
||||
return ERR_MEM;
|
||||
}
|
||||
left -= cop;
|
||||
}
|
||||
pbuf_free(rambuf);
|
||||
snmp_inc_ipfragoks();
|
||||
return ERR_OK;
|
||||
}
|
414
Demo/Common/ethernet/lwIP/core/mem.c
Normal file
414
Demo/Common/ethernet/lwIP/core/mem.c
Normal file
|
@ -0,0 +1,414 @@
|
|||
/** @file
|
||||
*
|
||||
* Dynamic memory manager
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#if (MEM_LIBC_MALLOC == 0)
|
||||
/* lwIP replacement for your libc malloc() */
|
||||
|
||||
struct mem {
|
||||
mem_size_t next, prev;
|
||||
#if MEM_ALIGNMENT == 1
|
||||
u8_t used;
|
||||
#elif MEM_ALIGNMENT == 2
|
||||
u16_t used;
|
||||
#elif MEM_ALIGNMENT == 4
|
||||
u32_t used;
|
||||
#elif MEM_ALIGNMENT == 8
|
||||
u64_t used;
|
||||
#else
|
||||
#error "unhandled MEM_ALIGNMENT size"
|
||||
#endif /* MEM_ALIGNMENT */
|
||||
};
|
||||
|
||||
static struct mem *ram_end;
|
||||
#if 1
|
||||
/* Adam original */
|
||||
static u8_t ram[MEM_SIZE + sizeof(struct mem) + MEM_ALIGNMENT];
|
||||
#else
|
||||
/* Christiaan alignment fix */
|
||||
static u8_t *ram;
|
||||
static struct mem ram_heap[1 + ( (MEM_SIZE + sizeof(struct mem) - 1) / sizeof(struct mem))];
|
||||
#endif
|
||||
|
||||
#define MIN_SIZE 12
|
||||
#if 0 /* this one does not align correctly for some, resulting in crashes */
|
||||
#define SIZEOF_STRUCT_MEM (unsigned int)MEM_ALIGN_SIZE(sizeof(struct mem))
|
||||
#else
|
||||
#define SIZEOF_STRUCT_MEM (sizeof(struct mem) + \
|
||||
(((sizeof(struct mem) % MEM_ALIGNMENT) == 0)? 0 : \
|
||||
(4 - (sizeof(struct mem) % MEM_ALIGNMENT))))
|
||||
#endif
|
||||
|
||||
static struct mem *lfree; /* pointer to the lowest free block */
|
||||
|
||||
static sys_sem_t mem_sem;
|
||||
|
||||
static void
|
||||
plug_holes(struct mem *mem)
|
||||
{
|
||||
struct mem *nmem;
|
||||
struct mem *pmem;
|
||||
|
||||
LWIP_ASSERT("plug_holes: mem >= ram", (u8_t *)mem >= ram);
|
||||
LWIP_ASSERT("plug_holes: mem < ram_end", (u8_t *)mem < (u8_t *)ram_end);
|
||||
LWIP_ASSERT("plug_holes: mem->used == 0", mem->used == 0);
|
||||
|
||||
/* plug hole forward */
|
||||
LWIP_ASSERT("plug_holes: mem->next <= MEM_SIZE", mem->next <= MEM_SIZE);
|
||||
|
||||
nmem = (struct mem *)&ram[mem->next];
|
||||
if (mem != nmem && nmem->used == 0 && (u8_t *)nmem != (u8_t *)ram_end) {
|
||||
if (lfree == nmem) {
|
||||
lfree = mem;
|
||||
}
|
||||
mem->next = nmem->next;
|
||||
((struct mem *)&ram[nmem->next])->prev = (u8_t *)mem - ram;
|
||||
}
|
||||
|
||||
/* plug hole backward */
|
||||
pmem = (struct mem *)&ram[mem->prev];
|
||||
if (pmem != mem && pmem->used == 0) {
|
||||
if (lfree == mem) {
|
||||
lfree = pmem;
|
||||
}
|
||||
pmem->next = mem->next;
|
||||
((struct mem *)&ram[mem->next])->prev = (u8_t *)pmem - ram;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mem_init(void)
|
||||
{
|
||||
struct mem *mem;
|
||||
|
||||
#if 1
|
||||
/* Adam original */
|
||||
#else
|
||||
/* Christiaan alignment fix */
|
||||
ram = (u8_t*)ram_heap;
|
||||
#endif
|
||||
memset(ram, 0, MEM_SIZE);
|
||||
mem = (struct mem *)ram;
|
||||
mem->next = MEM_SIZE;
|
||||
mem->prev = 0;
|
||||
mem->used = 0;
|
||||
ram_end = (struct mem *)&ram[MEM_SIZE];
|
||||
ram_end->used = 1;
|
||||
ram_end->next = MEM_SIZE;
|
||||
ram_end->prev = MEM_SIZE;
|
||||
|
||||
mem_sem = sys_sem_new(1);
|
||||
|
||||
lfree = (struct mem *)ram;
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.avail = MEM_SIZE;
|
||||
#endif /* MEM_STATS */
|
||||
}
|
||||
|
||||
void
|
||||
mem_free(void *rmem)
|
||||
{
|
||||
struct mem *mem;
|
||||
|
||||
if (rmem == NULL) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | DBG_TRACE | 2, ("mem_free(p == NULL) was called.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
LWIP_ASSERT("mem_free: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
sys_sem_signal(mem_sem);
|
||||
return;
|
||||
}
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
|
||||
LWIP_ASSERT("mem_free: mem->used", mem->used);
|
||||
|
||||
mem->used = 0;
|
||||
|
||||
if (mem < lfree) {
|
||||
lfree = mem;
|
||||
}
|
||||
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
|
||||
|
||||
#endif /* MEM_STATS */
|
||||
plug_holes(mem);
|
||||
sys_sem_signal(mem_sem);
|
||||
}
|
||||
|
||||
void *
|
||||
mem_realloc(void *rmem, mem_size_t newsize)
|
||||
{
|
||||
mem_size_t size;
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
|
||||
/* Expand the size of the allocated memory region so that we can
|
||||
adjust for alignment. */
|
||||
if ((newsize % MEM_ALIGNMENT) != 0) {
|
||||
newsize += MEM_ALIGNMENT - ((newsize + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
|
||||
}
|
||||
|
||||
if (newsize > MEM_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
LWIP_ASSERT("mem_realloc: legal memory", (u8_t *)rmem >= (u8_t *)ram &&
|
||||
(u8_t *)rmem < (u8_t *)ram_end);
|
||||
|
||||
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
|
||||
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_realloc: illegal memory\n"));
|
||||
return rmem;
|
||||
}
|
||||
mem = (struct mem *)((u8_t *)rmem - SIZEOF_STRUCT_MEM);
|
||||
|
||||
ptr = (u8_t *)mem - ram;
|
||||
|
||||
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used -= (size - newsize);
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) {
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
mem2->next = mem->next;
|
||||
mem2->prev = ptr;
|
||||
mem->next = ptr2;
|
||||
if (mem2->next != MEM_SIZE) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
|
||||
plug_holes(mem2);
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
return rmem;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/**
|
||||
* Adam's mem_malloc(), suffers from bug #17922
|
||||
* Set if to 0 for alternative mem_malloc().
|
||||
*/
|
||||
void *
|
||||
mem_malloc(mem_size_t size)
|
||||
{
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Expand the size of the allocated memory region so that we can
|
||||
adjust for alignment. */
|
||||
if ((size % MEM_ALIGNMENT) != 0) {
|
||||
size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
|
||||
}
|
||||
|
||||
if (size > MEM_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE; ptr = ((struct mem *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)&ram[ptr];
|
||||
if (!mem->used &&
|
||||
mem->next - (ptr + SIZEOF_STRUCT_MEM) >= size + SIZEOF_STRUCT_MEM) {
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
|
||||
mem2->prev = ptr;
|
||||
mem2->next = mem->next;
|
||||
mem->next = ptr2;
|
||||
if (mem2->next != MEM_SIZE) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
|
||||
mem2->used = 0;
|
||||
mem->used = 1;
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
|
||||
/* if (lwip_stats.mem.max < lwip_stats.mem.used) {
|
||||
lwip_stats.mem.max = lwip_stats.mem.used;
|
||||
} */
|
||||
if (lwip_stats.mem.max < ptr2) {
|
||||
lwip_stats.mem.max = ptr2;
|
||||
}
|
||||
#endif /* MEM_STATS */
|
||||
|
||||
if (mem == lfree) {
|
||||
/* Find next free block after mem */
|
||||
while (lfree->used && lfree != ram_end) {
|
||||
lfree = (struct mem *)&ram[lfree->next];
|
||||
}
|
||||
LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
sys_sem_signal(mem_sem);
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
/**
|
||||
* Adam's mem_malloc() plus solution for bug #17922
|
||||
*/
|
||||
void *
|
||||
mem_malloc(mem_size_t size)
|
||||
{
|
||||
mem_size_t ptr, ptr2;
|
||||
struct mem *mem, *mem2;
|
||||
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Expand the size of the allocated memory region so that we can
|
||||
adjust for alignment. */
|
||||
if ((size % MEM_ALIGNMENT) != 0) {
|
||||
size += MEM_ALIGNMENT - ((size + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT);
|
||||
}
|
||||
|
||||
if (size > MEM_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sys_sem_wait(mem_sem);
|
||||
|
||||
for (ptr = (u8_t *)lfree - ram; ptr < MEM_SIZE - size; ptr = ((struct mem *)&ram[ptr])->next) {
|
||||
mem = (struct mem *)&ram[ptr];
|
||||
|
||||
if (!mem->used) {
|
||||
|
||||
ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
|
||||
|
||||
if (mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) >= size) {
|
||||
/* split large block, create empty remainder */
|
||||
mem->next = ptr2;
|
||||
mem->used = 1;
|
||||
/* create mem2 struct */
|
||||
mem2 = (struct mem *)&ram[ptr2];
|
||||
mem2->used = 0;
|
||||
mem2->next = mem->next;
|
||||
mem2->prev = ptr;
|
||||
|
||||
if (mem2->next != MEM_SIZE) {
|
||||
((struct mem *)&ram[mem2->next])->prev = ptr2;
|
||||
}
|
||||
}
|
||||
else if (mem->next - (ptr + SIZEOF_STRUCT_MEM) > size) {
|
||||
/* near fit, no split, no mem2 creation,
|
||||
round up to mem->next */
|
||||
ptr2 = mem->next;
|
||||
mem->used = 1;
|
||||
}
|
||||
else if (mem->next - (ptr + SIZEOF_STRUCT_MEM) == size) {
|
||||
/* exact fit, do not split, no mem2 creation */
|
||||
mem->next = ptr2;
|
||||
mem->used = 1;
|
||||
}
|
||||
|
||||
if (mem->used) {
|
||||
#if MEM_STATS
|
||||
lwip_stats.mem.used += (size + SIZEOF_STRUCT_MEM);
|
||||
if (lwip_stats.mem.max < ptr2) {
|
||||
lwip_stats.mem.max = ptr2;
|
||||
}
|
||||
#endif /* MEM_STATS */
|
||||
if (mem == lfree) {
|
||||
/* Find next free block after mem */
|
||||
while (lfree->used && lfree != ram_end) {
|
||||
lfree = (struct mem *)&ram[lfree->next];
|
||||
}
|
||||
LWIP_ASSERT("mem_malloc: !lfree->used", !lfree->used);
|
||||
}
|
||||
sys_sem_signal(mem_sem);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
|
||||
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
|
||||
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.",
|
||||
(unsigned long)((u8_t *)mem + SIZEOF_STRUCT_MEM) % MEM_ALIGNMENT == 0);
|
||||
return (u8_t *)mem + SIZEOF_STRUCT_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
|
||||
#if MEM_STATS
|
||||
++lwip_stats.mem.err;
|
||||
#endif /* MEM_STATS */
|
||||
sys_sem_signal(mem_sem);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MEM_LIBC_MALLOC == 0 */
|
||||
|
238
Demo/Common/ethernet/lwIP/core/memp.c
Normal file
238
Demo/Common/ethernet/lwIP/core/memp.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
struct memp {
|
||||
struct memp *next;
|
||||
};
|
||||
|
||||
#define MEMP_SIZE MEM_ALIGN_SIZE(sizeof(struct memp))
|
||||
|
||||
static struct memp *memp_tab[MEMP_MAX];
|
||||
|
||||
static const u16_t memp_sizes[MEMP_MAX] = {
|
||||
MEM_ALIGN_SIZE(sizeof(struct pbuf)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct raw_pcb)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct udp_pcb)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcp_pcb)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcp_pcb_listen)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcp_seg)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct netbuf)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct netconn)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct api_msg)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct tcpip_msg)),
|
||||
MEM_ALIGN_SIZE(sizeof(struct sys_timeo))
|
||||
};
|
||||
|
||||
static const u16_t memp_num[MEMP_MAX] = {
|
||||
MEMP_NUM_PBUF,
|
||||
MEMP_NUM_RAW_PCB,
|
||||
MEMP_NUM_UDP_PCB,
|
||||
MEMP_NUM_TCP_PCB,
|
||||
MEMP_NUM_TCP_PCB_LISTEN,
|
||||
MEMP_NUM_TCP_SEG,
|
||||
MEMP_NUM_NETBUF,
|
||||
MEMP_NUM_NETCONN,
|
||||
MEMP_NUM_API_MSG,
|
||||
MEMP_NUM_TCPIP_MSG,
|
||||
MEMP_NUM_SYS_TIMEOUT
|
||||
};
|
||||
|
||||
#define MEMP_TYPE_SIZE(qty, type) \
|
||||
((qty) * (MEMP_SIZE + MEM_ALIGN_SIZE(sizeof(type))))
|
||||
|
||||
static u8_t memp_memory[MEM_ALIGNMENT - 1 +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_PBUF, struct pbuf) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_RAW_PCB, struct raw_pcb) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_UDP_PCB, struct udp_pcb) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_TCP_PCB, struct tcp_pcb) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_TCP_PCB_LISTEN, struct tcp_pcb_listen) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_TCP_SEG, struct tcp_seg) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_NETBUF, struct netbuf) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_NETCONN, struct netconn) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_API_MSG, struct api_msg) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_TCPIP_MSG, struct tcpip_msg) +
|
||||
MEMP_TYPE_SIZE(MEMP_NUM_SYS_TIMEOUT, struct sys_timeo)];
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
static sys_sem_t mutex;
|
||||
#endif
|
||||
|
||||
#if MEMP_SANITY_CHECK
|
||||
static int
|
||||
memp_sanity(void)
|
||||
{
|
||||
s16_t i, c;
|
||||
struct memp *m, *n;
|
||||
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
for (m = memp_tab[i]; m != NULL; m = m->next) {
|
||||
c = 1;
|
||||
for (n = memp_tab[i]; n != NULL; n = n->next) {
|
||||
if (n == m && --c < 0) {
|
||||
return 0; /* LW was: abort(); */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* MEMP_SANITY_CHECK*/
|
||||
|
||||
void
|
||||
memp_init(void)
|
||||
{
|
||||
struct memp *memp;
|
||||
u16_t i, j;
|
||||
|
||||
#if MEMP_STATS
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
lwip_stats.memp[i].used = lwip_stats.memp[i].max =
|
||||
lwip_stats.memp[i].err = 0;
|
||||
lwip_stats.memp[i].avail = memp_num[i];
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
|
||||
memp = MEM_ALIGN(memp_memory);
|
||||
for (i = 0; i < MEMP_MAX; ++i) {
|
||||
memp_tab[i] = NULL;
|
||||
for (j = 0; j < memp_num[i]; ++j) {
|
||||
memp->next = memp_tab[i];
|
||||
memp_tab[i] = memp;
|
||||
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
mutex = sys_sem_new(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *
|
||||
memp_malloc(memp_t type)
|
||||
{
|
||||
struct memp *memp;
|
||||
void *mem;
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
#endif
|
||||
|
||||
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_wait(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
memp = memp_tab[type];
|
||||
|
||||
if (memp != NULL) {
|
||||
memp_tab[type] = memp->next;
|
||||
memp->next = NULL;
|
||||
#if MEMP_STATS
|
||||
++lwip_stats.memp[type].used;
|
||||
if (lwip_stats.memp[type].used > lwip_stats.memp[type].max) {
|
||||
lwip_stats.memp[type].max = lwip_stats.memp[type].used;
|
||||
}
|
||||
#endif /* MEMP_STATS */
|
||||
mem = (u8_t *)memp + MEMP_SIZE;
|
||||
LWIP_ASSERT("memp_malloc: memp properly aligned",
|
||||
((mem_ptr_t)memp % MEM_ALIGNMENT) == 0);
|
||||
} else {
|
||||
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %"S16_F"\n", type));
|
||||
#if MEMP_STATS
|
||||
++lwip_stats.memp[type].err;
|
||||
#endif /* MEMP_STATS */
|
||||
mem = NULL;
|
||||
}
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_signal(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void
|
||||
memp_free(memp_t type, void *mem)
|
||||
{
|
||||
struct memp *memp;
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
if (mem == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
memp = (struct memp *)((u8_t *)mem - MEMP_SIZE);
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_wait(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
#if MEMP_STATS
|
||||
lwip_stats.memp[type].used--;
|
||||
#endif /* MEMP_STATS */
|
||||
|
||||
memp->next = memp_tab[type];
|
||||
memp_tab[type] = memp;
|
||||
|
||||
#if MEMP_SANITY_CHECK
|
||||
LWIP_ASSERT("memp sanity", memp_sanity());
|
||||
#endif
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
sys_sem_signal(mutex);
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
}
|
325
Demo/Common/ethernet/lwIP/core/netif.c
Normal file
325
Demo/Common/ethernet/lwIP/core/netif.c
Normal file
|
@ -0,0 +1,325 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* lwIP network interface abstraction
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
struct netif *netif_list = NULL;
|
||||
struct netif *netif_default = NULL;
|
||||
|
||||
/**
|
||||
* Add a network interface to the list of lwIP netifs.
|
||||
*
|
||||
* @param netif a pre-allocated netif structure
|
||||
* @param ipaddr IP address for the new netif
|
||||
* @param netmask network mask for the new netif
|
||||
* @param gw default gateway IP address for the new netif
|
||||
* @param state opaque data passed to the new netif
|
||||
* @param init callback function that initializes the interface
|
||||
* @param input callback function that is called to pass
|
||||
* ingress packets up in the protocol layer stack.
|
||||
*
|
||||
* @return netif, or NULL if failed.
|
||||
*/
|
||||
struct netif *
|
||||
netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif))
|
||||
{
|
||||
static s16_t netifnum = 0;
|
||||
|
||||
/* reset new interface configuration state */
|
||||
netif->ip_addr.addr = 0;
|
||||
netif->netmask.addr = 0;
|
||||
netif->gw.addr = 0;
|
||||
netif->flags = 0;
|
||||
#if LWIP_DHCP
|
||||
/* netif not under DHCP control by default */
|
||||
netif->dhcp = NULL;
|
||||
#endif
|
||||
/* remember netif specific state information data */
|
||||
netif->state = state;
|
||||
netif->num = netifnum++;
|
||||
netif->input = input;
|
||||
|
||||
netif_set_addr(netif, ipaddr, netmask, gw);
|
||||
|
||||
/* call user specified initialization function for netif */
|
||||
if (init(netif) != ERR_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add this netif to the list */
|
||||
netif->next = netif_list;
|
||||
netif_list = netif;
|
||||
snmp_inc_iflist();
|
||||
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
|
||||
netif->name[0], netif->name[1]));
|
||||
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, (" netmask "));
|
||||
ip_addr_debug_print(NETIF_DEBUG, netmask);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
|
||||
ip_addr_debug_print(NETIF_DEBUG, gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
|
||||
return netif;
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw)
|
||||
{
|
||||
netif_set_ipaddr(netif, ipaddr);
|
||||
netif_set_netmask(netif, netmask);
|
||||
netif_set_gw(netif, gw);
|
||||
}
|
||||
|
||||
void netif_remove(struct netif * netif)
|
||||
{
|
||||
if ( netif == NULL ) return;
|
||||
|
||||
snmp_delete_ipaddridx_tree(netif);
|
||||
|
||||
/* is it the first netif? */
|
||||
if (netif_list == netif) {
|
||||
netif_list = netif->next;
|
||||
snmp_dec_iflist();
|
||||
}
|
||||
else {
|
||||
/* look for netif further down the list */
|
||||
struct netif * tmpNetif;
|
||||
for (tmpNetif = netif_list; tmpNetif != NULL; tmpNetif = tmpNetif->next) {
|
||||
if (tmpNetif->next == netif) {
|
||||
tmpNetif->next = netif->next;
|
||||
snmp_dec_iflist();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tmpNetif == NULL)
|
||||
return; /* we didn't find any netif today */
|
||||
}
|
||||
/* this netif is default? */
|
||||
if (netif_default == netif)
|
||||
/* reset default netif */
|
||||
netif_default = NULL;
|
||||
LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") );
|
||||
}
|
||||
|
||||
struct netif *
|
||||
netif_find(char *name)
|
||||
{
|
||||
struct netif *netif;
|
||||
u8_t num;
|
||||
|
||||
if (name == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
num = name[2] - '0';
|
||||
|
||||
for(netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
if (num == netif->num &&
|
||||
name[0] == netif->name[0] &&
|
||||
name[1] == netif->name[1]) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1]));
|
||||
return netif;
|
||||
}
|
||||
}
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1]));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
|
||||
{
|
||||
/* TODO: Handling of obsolete pcbs */
|
||||
/* See: http://mail.gnu.org/archive/html/lwip-users/2003-03/msg00118.html */
|
||||
#if LWIP_TCP
|
||||
struct tcp_pcb *pcb;
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
|
||||
/* address is actually being changed? */
|
||||
if ((ip_addr_cmp(ipaddr, &(netif->ip_addr))) == 0)
|
||||
{
|
||||
/* extern struct tcp_pcb *tcp_active_pcbs; defined by tcp.h */
|
||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: netif address being changed\n"));
|
||||
pcb = tcp_active_pcbs;
|
||||
while (pcb != NULL) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
|
||||
/* this connection must be aborted */
|
||||
struct tcp_pcb *next = pcb->next;
|
||||
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
|
||||
tcp_abort(pcb);
|
||||
pcb = next;
|
||||
} else {
|
||||
pcb = pcb->next;
|
||||
}
|
||||
}
|
||||
for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
|
||||
/* PCB bound to current local interface address? */
|
||||
if (ip_addr_cmp(&(lpcb->local_ip), &(netif->ip_addr))) {
|
||||
/* The PCB is listening to the old ipaddr and
|
||||
* is set to listen to the new one instead */
|
||||
ip_addr_set(&(lpcb->local_ip), ipaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
snmp_delete_ipaddridx_tree(netif);
|
||||
snmp_delete_iprteidx_tree(0,netif);
|
||||
/* set new IP address to netif */
|
||||
ip_addr_set(&(netif->ip_addr), ipaddr);
|
||||
snmp_insert_ipaddridx_tree(netif);
|
||||
snmp_insert_iprteidx_tree(0,netif);
|
||||
|
||||
#if 0 /* only allowed for Ethernet interfaces TODO: how can we check? */
|
||||
/** For Ethernet network interfaces, we would like to send a
|
||||
* "gratuitous ARP"; this is an ARP packet sent by a node in order
|
||||
* to spontaneously cause other nodes to update an entry in their
|
||||
* ARP cache. From RFC 3220 "IP Mobility Support for IPv4" section 4.6.
|
||||
*/
|
||||
etharp_query(netif, ipaddr, NULL);
|
||||
#endif
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: IP address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->ip_addr),
|
||||
ip4_addr2(&netif->ip_addr),
|
||||
ip4_addr3(&netif->ip_addr),
|
||||
ip4_addr4(&netif->ip_addr)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_gw(struct netif *netif, struct ip_addr *gw)
|
||||
{
|
||||
ip_addr_set(&(netif->gw), gw);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: GW address of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->gw),
|
||||
ip4_addr2(&netif->gw),
|
||||
ip4_addr3(&netif->gw),
|
||||
ip4_addr4(&netif->gw)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
|
||||
{
|
||||
snmp_delete_iprteidx_tree(0, netif);
|
||||
/* set new netmask to netif */
|
||||
ip_addr_set(&(netif->netmask), netmask);
|
||||
snmp_insert_iprteidx_tree(0, netif);
|
||||
LWIP_DEBUGF(NETIF_DEBUG | DBG_TRACE | DBG_STATE | 3, ("netif: netmask of interface %c%c set to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
netif->name[0], netif->name[1],
|
||||
ip4_addr1(&netif->netmask),
|
||||
ip4_addr2(&netif->netmask),
|
||||
ip4_addr3(&netif->netmask),
|
||||
ip4_addr4(&netif->netmask)));
|
||||
}
|
||||
|
||||
void
|
||||
netif_set_default(struct netif *netif)
|
||||
{
|
||||
if (netif == NULL)
|
||||
{
|
||||
/* remove default route */
|
||||
snmp_delete_iprteidx_tree(1, netif);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* install default route */
|
||||
snmp_insert_iprteidx_tree(1, netif);
|
||||
}
|
||||
netif_default = netif;
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
|
||||
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring an interface up, available for processing
|
||||
* traffic.
|
||||
*
|
||||
* @note: Enabling DHCP on a down interface will make it come
|
||||
* up once configured.
|
||||
*
|
||||
* @see dhcp_start()
|
||||
*/
|
||||
void netif_set_up(struct netif *netif)
|
||||
{
|
||||
netif->flags |= NETIF_FLAG_UP;
|
||||
#if LWIP_SNMP
|
||||
snmp_get_sysuptime(&netif->ts);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask if an interface is up
|
||||
*/
|
||||
u8_t netif_is_up(struct netif *netif)
|
||||
{
|
||||
return (netif->flags & NETIF_FLAG_UP)?1:0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring an interface down, disabling any traffic processing.
|
||||
*
|
||||
* @note: Enabling DHCP on a down interface will make it come
|
||||
* up once configured.
|
||||
*
|
||||
* @see dhcp_start()
|
||||
*/
|
||||
void netif_set_down(struct netif *netif)
|
||||
{
|
||||
netif->flags &= ~NETIF_FLAG_UP;
|
||||
#if LWIP_SNMP
|
||||
snmp_get_sysuptime(&netif->ts);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
netif_init(void)
|
||||
{
|
||||
netif_list = netif_default = NULL;
|
||||
}
|
||||
|
964
Demo/Common/ethernet/lwIP/core/pbuf.c
Normal file
964
Demo/Common/ethernet/lwIP/core/pbuf.c
Normal file
|
@ -0,0 +1,964 @@
|
|||
/**
|
||||
* @file
|
||||
* Packet buffer management
|
||||
*
|
||||
* Packets are built from the pbuf data structure. It supports dynamic
|
||||
* memory allocation for packet contents or can reference externally
|
||||
* managed packet contents both in RAM and ROM. Quick allocation for
|
||||
* incoming packets is provided through pools with fixed sized pbufs.
|
||||
*
|
||||
* A packet may span over multiple pbufs, chained as a singly linked
|
||||
* list. This is called a "pbuf chain".
|
||||
*
|
||||
* Multiple packets may be queued, also using this singly linked list.
|
||||
* This is called a "packet queue".
|
||||
*
|
||||
* So, a packet queue consists of one or more pbuf chains, each of
|
||||
* which consist of one or more pbufs. Currently, queues are only
|
||||
* supported in a limited section of lwIP, this is the etharp queueing
|
||||
* code. Outside of this section no packet queues are supported yet.
|
||||
*
|
||||
* The differences between a pbuf chain and a packet queue are very
|
||||
* precise but subtle.
|
||||
*
|
||||
* The last pbuf of a packet has a ->tot_len field that equals the
|
||||
* ->len field. It can be found by traversing the list. If the last
|
||||
* pbuf of a packet has a ->next field other than NULL, more packets
|
||||
* are on the queue.
|
||||
*
|
||||
* Therefore, looping through a pbuf of a single packet, has an
|
||||
* loop end condition (tot_len == p->len), NOT (next == NULL).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "arch/perf.h"
|
||||
|
||||
static u8_t pbuf_pool_memory[MEM_ALIGNMENT - 1 + PBUF_POOL_SIZE * MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE + sizeof(struct pbuf))];
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
static volatile u8_t pbuf_pool_free_lock, pbuf_pool_alloc_lock;
|
||||
static sys_sem_t pbuf_pool_free_sem;
|
||||
#endif
|
||||
|
||||
static struct pbuf *pbuf_pool = NULL;
|
||||
|
||||
/**
|
||||
* Initializes the pbuf module.
|
||||
*
|
||||
* A large part of memory is allocated for holding the pool of pbufs.
|
||||
* The size of the individual pbufs in the pool is given by the size
|
||||
* parameter, and the number of pbufs in the pool by the num parameter.
|
||||
*
|
||||
* After the memory has been allocated, the pbufs are set up. The
|
||||
* ->next pointer in each pbuf is set up to point to the next pbuf in
|
||||
* the pool.
|
||||
*
|
||||
*/
|
||||
void
|
||||
pbuf_init(void)
|
||||
{
|
||||
struct pbuf *p, *q = NULL;
|
||||
u16_t i;
|
||||
|
||||
pbuf_pool = (struct pbuf *)MEM_ALIGN(pbuf_pool_memory);
|
||||
|
||||
#if PBUF_STATS
|
||||
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
|
||||
#endif /* PBUF_STATS */
|
||||
|
||||
/* Set up ->next pointers to link the pbufs of the pool together */
|
||||
p = pbuf_pool;
|
||||
|
||||
for(i = 0; i < PBUF_POOL_SIZE; ++i) {
|
||||
p->next = (struct pbuf *)((u8_t *)p + PBUF_POOL_BUFSIZE + sizeof(struct pbuf));
|
||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf)));
|
||||
p->flags = PBUF_FLAG_POOL;
|
||||
q = p;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
/* The ->next pointer of last pbuf is NULL to indicate that there
|
||||
are no more pbufs in the pool */
|
||||
q->next = NULL;
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
pbuf_pool_alloc_lock = 0;
|
||||
pbuf_pool_free_lock = 0;
|
||||
pbuf_pool_free_sem = sys_sem_new(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal only called from pbuf_alloc()
|
||||
*/
|
||||
static struct pbuf *
|
||||
pbuf_pool_alloc(void)
|
||||
{
|
||||
struct pbuf *p = NULL;
|
||||
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
/* Next, check the actual pbuf pool, but if the pool is locked, we
|
||||
pretend to be out of buffers and return NULL. */
|
||||
if (pbuf_pool_free_lock) {
|
||||
#if PBUF_STATS
|
||||
++lwip_stats.pbuf.alloc_locked;
|
||||
#endif /* PBUF_STATS */
|
||||
return NULL;
|
||||
}
|
||||
pbuf_pool_alloc_lock = 1;
|
||||
if (!pbuf_pool_free_lock) {
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
p = pbuf_pool;
|
||||
if (p) {
|
||||
pbuf_pool = p->next;
|
||||
}
|
||||
#if !SYS_LIGHTWEIGHT_PROT
|
||||
#if PBUF_STATS
|
||||
} else {
|
||||
++lwip_stats.pbuf.alloc_locked;
|
||||
#endif /* PBUF_STATS */
|
||||
}
|
||||
pbuf_pool_alloc_lock = 0;
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
#if PBUF_STATS
|
||||
if (p != NULL) {
|
||||
++lwip_stats.pbuf.used;
|
||||
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
|
||||
lwip_stats.pbuf.max = lwip_stats.pbuf.used;
|
||||
}
|
||||
}
|
||||
#endif /* PBUF_STATS */
|
||||
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allocates a pbuf of the given type (possibly a chain for PBUF_POOL type).
|
||||
*
|
||||
* The actual memory allocated for the pbuf is determined by the
|
||||
* layer at which the pbuf is allocated and the requested size
|
||||
* (from the size parameter).
|
||||
*
|
||||
* @param flag this parameter decides how and where the pbuf
|
||||
* should be allocated as follows:
|
||||
*
|
||||
* - PBUF_RAM: buffer memory for pbuf is allocated as one large
|
||||
* chunk. This includes protocol headers as well.
|
||||
* - PBUF_ROM: no buffer memory is allocated for the pbuf, even for
|
||||
* protocol headers. Additional headers must be prepended
|
||||
* by allocating another pbuf and chain in to the front of
|
||||
* the ROM pbuf. It is assumed that the memory used is really
|
||||
* similar to ROM in that it is immutable and will not be
|
||||
* changed. Memory which is dynamic should generally not
|
||||
* be attached to PBUF_ROM pbufs. Use PBUF_REF instead.
|
||||
* - PBUF_REF: no buffer memory is allocated for the pbuf, even for
|
||||
* protocol headers. It is assumed that the pbuf is only
|
||||
* being used in a single thread. If the pbuf gets queued,
|
||||
* then pbuf_take should be called to copy the buffer.
|
||||
* - PBUF_POOL: the pbuf is allocated as a pbuf chain, with pbufs from
|
||||
* the pbuf pool that is allocated during pbuf_init().
|
||||
*
|
||||
* @return the allocated pbuf. If multiple pbufs where allocated, this
|
||||
* is the first pbuf of a pbuf chain.
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
|
||||
{
|
||||
struct pbuf *p, *q, *r;
|
||||
u16_t offset;
|
||||
s32_t rem_len; /* remaining length */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F")\n", length));
|
||||
|
||||
/* determine header offset */
|
||||
offset = 0;
|
||||
switch (l) {
|
||||
case PBUF_TRANSPORT:
|
||||
/* add room for transport (often TCP) layer header */
|
||||
offset += PBUF_TRANSPORT_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
case PBUF_IP:
|
||||
/* add room for IP layer header */
|
||||
offset += PBUF_IP_HLEN;
|
||||
/* FALLTHROUGH */
|
||||
case PBUF_LINK:
|
||||
/* add room for link layer header */
|
||||
offset += PBUF_LINK_HLEN;
|
||||
break;
|
||||
case PBUF_RAW:
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloc: bad pbuf layer", 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (flag) {
|
||||
case PBUF_POOL:
|
||||
/* allocate head of pbuf chain into p */
|
||||
p = pbuf_pool_alloc();
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
|
||||
if (p == NULL) {
|
||||
#if PBUF_STATS
|
||||
++lwip_stats.pbuf.err;
|
||||
#endif /* PBUF_STATS */
|
||||
return NULL;
|
||||
}
|
||||
p->next = NULL;
|
||||
|
||||
/* make the payload pointer point 'offset' bytes into pbuf data memory */
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + (sizeof(struct pbuf) + offset)));
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf p->payload properly aligned",
|
||||
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||
/* the total length of the pbuf chain is the requested size */
|
||||
p->tot_len = length;
|
||||
/* set the length of the first pbuf in the chain */
|
||||
p->len = length > PBUF_POOL_BUFSIZE - offset? PBUF_POOL_BUFSIZE - offset: length;
|
||||
/* set reference count (needed here in case we fail) */
|
||||
p->ref = 1;
|
||||
|
||||
/* now allocate the tail of the pbuf chain */
|
||||
|
||||
/* remember first pbuf for linkage in next iteration */
|
||||
r = p;
|
||||
/* remaining length to be allocated */
|
||||
rem_len = length - p->len;
|
||||
/* any remaining pbufs to be allocated? */
|
||||
while (rem_len > 0) {
|
||||
q = pbuf_pool_alloc();
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
|
||||
#if PBUF_STATS
|
||||
++lwip_stats.pbuf.err;
|
||||
#endif /* PBUF_STATS */
|
||||
/* free chain so far allocated */
|
||||
pbuf_free(p);
|
||||
/* bail out unsuccesfully */
|
||||
return NULL;
|
||||
}
|
||||
q->next = NULL;
|
||||
/* make previous pbuf point to this pbuf */
|
||||
r->next = q;
|
||||
/* set total length of this pbuf and next in chain */
|
||||
q->tot_len = rem_len;
|
||||
/* this pbuf length is pool size, unless smaller sized tail */
|
||||
q->len = rem_len > PBUF_POOL_BUFSIZE? PBUF_POOL_BUFSIZE: rem_len;
|
||||
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
|
||||
((mem_ptr_t)q->payload % MEM_ALIGNMENT) == 0);
|
||||
q->ref = 1;
|
||||
/* calculate remaining length to be allocated */
|
||||
rem_len -= q->len;
|
||||
/* remember this pbuf for linkage in next iteration */
|
||||
r = q;
|
||||
}
|
||||
/* end of chain */
|
||||
/*r->next = NULL;*/
|
||||
|
||||
break;
|
||||
case PBUF_RAM:
|
||||
/* If pbuf is to be allocated in RAM, allocate memory for it. */
|
||||
p = mem_malloc(MEM_ALIGN_SIZE(sizeof(struct pbuf) + offset) + MEM_ALIGN_SIZE(length));
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
/* Set up internal structure of the pbuf. */
|
||||
p->payload = MEM_ALIGN((void *)((u8_t *)p + sizeof(struct pbuf) + offset));
|
||||
p->len = p->tot_len = length;
|
||||
p->next = NULL;
|
||||
p->flags = PBUF_FLAG_RAM;
|
||||
|
||||
LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned",
|
||||
((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0);
|
||||
break;
|
||||
/* pbuf references existing (non-volatile static constant) ROM payload? */
|
||||
case PBUF_ROM:
|
||||
/* pbuf references existing (externally allocated) RAM payload? */
|
||||
case PBUF_REF:
|
||||
/* only allocate memory for the pbuf structure */
|
||||
p = memp_malloc(MEMP_PBUF);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_alloc: Could not allocate MEMP_PBUF for PBUF_%s.\n", flag == PBUF_ROM?"ROM":"REF"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* caller must set this field properly, afterwards */
|
||||
p->payload = NULL;
|
||||
p->len = p->tot_len = length;
|
||||
p->next = NULL;
|
||||
p->flags = (flag == PBUF_ROM? PBUF_FLAG_ROM: PBUF_FLAG_REF);
|
||||
break;
|
||||
default:
|
||||
LWIP_ASSERT("pbuf_alloc: erroneous flag", 0);
|
||||
return NULL;
|
||||
}
|
||||
/* set reference count */
|
||||
p->ref = 1;
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
#if PBUF_STATS
|
||||
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
|
||||
#else /* PBUF_STATS */
|
||||
#define DEC_PBUF_STATS
|
||||
#endif /* PBUF_STATS */
|
||||
|
||||
#define PBUF_POOL_FAST_FREE(p) do { \
|
||||
p->next = pbuf_pool; \
|
||||
pbuf_pool = p; \
|
||||
DEC_PBUF_STATS; \
|
||||
} while (0)
|
||||
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
#define PBUF_POOL_FREE(p) do { \
|
||||
SYS_ARCH_DECL_PROTECT(old_level); \
|
||||
SYS_ARCH_PROTECT(old_level); \
|
||||
PBUF_POOL_FAST_FREE(p); \
|
||||
SYS_ARCH_UNPROTECT(old_level); \
|
||||
} while (0)
|
||||
#else /* SYS_LIGHTWEIGHT_PROT */
|
||||
#define PBUF_POOL_FREE(p) do { \
|
||||
sys_sem_wait(pbuf_pool_free_sem); \
|
||||
PBUF_POOL_FAST_FREE(p); \
|
||||
sys_sem_signal(pbuf_pool_free_sem); \
|
||||
} while (0)
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
/**
|
||||
* Shrink a pbuf chain to a desired length.
|
||||
*
|
||||
* @param p pbuf to shrink.
|
||||
* @param new_len desired new length of pbuf chain
|
||||
*
|
||||
* Depending on the desired length, the first few pbufs in a chain might
|
||||
* be skipped and left unchanged. The new last pbuf in the chain will be
|
||||
* resized, and any remaining pbufs will be freed.
|
||||
*
|
||||
* @note If the pbuf is ROM/REF, only the ->tot_len and ->len fields are adjusted.
|
||||
* @note May not be called on a packet queue.
|
||||
*
|
||||
* @bug Cannot grow the size of a pbuf (chain) (yet).
|
||||
*/
|
||||
void
|
||||
pbuf_realloc(struct pbuf *p, u16_t new_len)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u16_t rem_len; /* remaining length */
|
||||
s16_t grow;
|
||||
|
||||
LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL ||
|
||||
p->flags == PBUF_FLAG_ROM ||
|
||||
p->flags == PBUF_FLAG_RAM ||
|
||||
p->flags == PBUF_FLAG_REF);
|
||||
|
||||
/* desired length larger than current length? */
|
||||
if (new_len >= p->tot_len) {
|
||||
/* enlarging not yet supported */
|
||||
return;
|
||||
}
|
||||
|
||||
/* the pbuf chain grows by (new_len - p->tot_len) bytes
|
||||
* (which may be negative in case of shrinking) */
|
||||
grow = new_len - p->tot_len;
|
||||
|
||||
/* first, step over any pbufs that should remain in the chain */
|
||||
rem_len = new_len;
|
||||
q = p;
|
||||
/* should this pbuf be kept? */
|
||||
while (rem_len > q->len) {
|
||||
/* decrease remaining length by pbuf length */
|
||||
rem_len -= q->len;
|
||||
/* decrease total length indicator */
|
||||
q->tot_len += grow;
|
||||
/* proceed to next pbuf in chain */
|
||||
q = q->next;
|
||||
}
|
||||
/* we have now reached the new last pbuf (in q) */
|
||||
/* rem_len == desired length for pbuf q */
|
||||
|
||||
/* shrink allocated memory for PBUF_RAM */
|
||||
/* (other types merely adjust their length fields */
|
||||
if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) {
|
||||
/* reallocate and adjust the length of the pbuf that will be split */
|
||||
mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len);
|
||||
}
|
||||
/* adjust length fields for new last pbuf */
|
||||
q->len = rem_len;
|
||||
q->tot_len = q->len;
|
||||
|
||||
/* any remaining pbufs in chain? */
|
||||
if (q->next != NULL) {
|
||||
/* free remaining pbufs in chain */
|
||||
pbuf_free(q->next);
|
||||
}
|
||||
/* q is last packet in chain */
|
||||
q->next = NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the payload pointer to hide or reveal headers in the payload.
|
||||
*
|
||||
* Adjusts the ->payload pointer so that space for a header
|
||||
* (dis)appears in the pbuf payload.
|
||||
*
|
||||
* The ->payload, ->tot_len and ->len fields are adjusted.
|
||||
*
|
||||
* @param hdr_size_inc Number of bytes to increment header size which
|
||||
* increases the size of the pbuf. New space is on the front.
|
||||
* (Using a negative value decreases the header size.)
|
||||
* If hdr_size_inc is 0, this function does nothing and returns succesful.
|
||||
*
|
||||
* PBUF_ROM and PBUF_REF type buffers cannot have their sizes increased, so
|
||||
* the call will fail. A check is made that the increase in header size does
|
||||
* not move the payload pointer in front of the start of the buffer.
|
||||
* @return non-zero on failure, zero on success.
|
||||
*
|
||||
*/
|
||||
u8_t
|
||||
pbuf_header(struct pbuf *p, s16_t header_size_increment)
|
||||
{
|
||||
u16_t flags;
|
||||
void *payload;
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
if ((header_size_increment == 0) || (p == NULL)) return 0;
|
||||
|
||||
flags = p->flags;
|
||||
/* remember current payload pointer */
|
||||
payload = p->payload;
|
||||
|
||||
/* pbuf types containing payloads? */
|
||||
if (flags == PBUF_FLAG_RAM || flags == PBUF_FLAG_POOL) {
|
||||
/* set new payload pointer */
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
/* boundary check fails? */
|
||||
if ((u8_t *)p->payload < (u8_t *)p + sizeof(struct pbuf)) {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_header: failed as %p < %p (not enough space for new header size)\n",
|
||||
(void *)p->payload,
|
||||
(void *)(p + 1)));\
|
||||
/* restore old payload pointer */
|
||||
p->payload = payload;
|
||||
/* bail out unsuccesfully */
|
||||
return 1;
|
||||
}
|
||||
/* pbuf types refering to external payloads? */
|
||||
} else if (flags == PBUF_FLAG_REF || flags == PBUF_FLAG_ROM) {
|
||||
/* hide a header in the payload? */
|
||||
if ((header_size_increment < 0) && (header_size_increment - p->len <= 0)) {
|
||||
/* increase payload pointer */
|
||||
p->payload = (u8_t *)p->payload - header_size_increment;
|
||||
} else {
|
||||
/* cannot expand payload to front (yet!)
|
||||
* bail out unsuccesfully */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* modify pbuf length fields */
|
||||
p->len += header_size_increment;
|
||||
p->tot_len += header_size_increment;
|
||||
|
||||
LWIP_DEBUGF( PBUF_DEBUG, ("pbuf_header: old %p new %p (%"S16_F")\n",
|
||||
(void *)payload, (void *)p->payload, header_size_increment));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereference a pbuf chain or queue and deallocate any no-longer-used
|
||||
* pbufs at the head of this chain or queue.
|
||||
*
|
||||
* Decrements the pbuf reference count. If it reaches zero, the pbuf is
|
||||
* deallocated.
|
||||
*
|
||||
* For a pbuf chain, this is repeated for each pbuf in the chain,
|
||||
* up to the first pbuf which has a non-zero reference count after
|
||||
* decrementing. So, when all reference counts are one, the whole
|
||||
* chain is free'd.
|
||||
*
|
||||
* @param pbuf The pbuf (chain) to be dereferenced.
|
||||
*
|
||||
* @return the number of pbufs that were de-allocated
|
||||
* from the head of the chain.
|
||||
*
|
||||
* @note MUST NOT be called on a packet queue (Not verified to work yet).
|
||||
* @note the reference counter of a pbuf equals the number of pointers
|
||||
* that refer to the pbuf (or into the pbuf).
|
||||
*
|
||||
* @internal examples:
|
||||
*
|
||||
* Assuming existing chains a->b->c with the following reference
|
||||
* counts, calling pbuf_free(a) results in:
|
||||
*
|
||||
* 1->2->3 becomes ...1->3
|
||||
* 3->3->3 becomes 2->3->3
|
||||
* 1->1->2 becomes ......1
|
||||
* 2->1->1 becomes 1->1->1
|
||||
* 1->1->1 becomes .......
|
||||
*
|
||||
*/
|
||||
u8_t
|
||||
pbuf_free(struct pbuf *p)
|
||||
{
|
||||
u16_t flags;
|
||||
struct pbuf *q;
|
||||
u8_t count;
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
|
||||
/* if assertions are disabled, proceed with debug output */
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_free(p == NULL) was called.\n"));
|
||||
return 0;
|
||||
}
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_free(%p)\n", (void *)p));
|
||||
|
||||
PERF_START;
|
||||
|
||||
LWIP_ASSERT("pbuf_free: sane flags",
|
||||
p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM ||
|
||||
p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL);
|
||||
|
||||
count = 0;
|
||||
/* Since decrementing ref cannot be guaranteed to be a single machine operation
|
||||
* we must protect it. Also, the later test of ref must be protected.
|
||||
*/
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
/* de-allocate all consecutive pbufs from the head of the chain that
|
||||
* obtain a zero reference count after decrementing*/
|
||||
while (p != NULL) {
|
||||
/* all pbufs in a chain are referenced at least once */
|
||||
LWIP_ASSERT("pbuf_free: p->ref > 0", p->ref > 0);
|
||||
/* decrease reference count (number of pointers to pbuf) */
|
||||
p->ref--;
|
||||
/* this pbuf is no longer referenced to? */
|
||||
if (p->ref == 0) {
|
||||
/* remember next pbuf in chain for next iteration */
|
||||
q = p->next;
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p));
|
||||
flags = p->flags;
|
||||
/* is this a pbuf from the pool? */
|
||||
if (flags == PBUF_FLAG_POOL) {
|
||||
p->len = p->tot_len = PBUF_POOL_BUFSIZE;
|
||||
p->payload = (void *)((u8_t *)p + sizeof(struct pbuf));
|
||||
PBUF_POOL_FREE(p);
|
||||
/* is this a ROM or RAM referencing pbuf? */
|
||||
} else if (flags == PBUF_FLAG_ROM || flags == PBUF_FLAG_REF) {
|
||||
memp_free(MEMP_PBUF, p);
|
||||
/* flags == PBUF_FLAG_RAM */
|
||||
} else {
|
||||
mem_free(p);
|
||||
}
|
||||
count++;
|
||||
/* proceed to next pbuf */
|
||||
p = q;
|
||||
/* p->ref > 0, this pbuf is still referenced to */
|
||||
/* (and so the remaining pbufs in chain as well) */
|
||||
} else {
|
||||
LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: %p has ref %"U16_F", ending here.\n", (void *)p, (u16_t)p->ref));
|
||||
/* stop walking through the chain */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
PERF_STOP("pbuf_free");
|
||||
/* return number of de-allocated pbufs */
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of pbufs in a chain
|
||||
*
|
||||
* @param p first pbuf of chain
|
||||
* @return the number of pbufs in a chain
|
||||
*/
|
||||
|
||||
u8_t
|
||||
pbuf_clen(struct pbuf *p)
|
||||
{
|
||||
u8_t len;
|
||||
|
||||
len = 0;
|
||||
while (p != NULL) {
|
||||
++len;
|
||||
p = p->next;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the reference count of the pbuf.
|
||||
*
|
||||
* @param p pbuf to increase reference counter of
|
||||
*
|
||||
*/
|
||||
void
|
||||
pbuf_ref(struct pbuf *p)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
/* pbuf given? */
|
||||
if (p != NULL) {
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
++(p->ref);
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate two pbufs (each may be a pbuf chain) and take over
|
||||
* the caller's reference of the tail pbuf.
|
||||
*
|
||||
* @note The caller MAY NOT reference the tail pbuf afterwards.
|
||||
* Use pbuf_chain() for that purpose.
|
||||
*
|
||||
* @see pbuf_chain()
|
||||
*/
|
||||
|
||||
void
|
||||
pbuf_cat(struct pbuf *h, struct pbuf *t)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
LWIP_ASSERT("h != NULL (programmer violates API)", h != NULL);
|
||||
LWIP_ASSERT("t != NULL (programmer violates API)", t != NULL);
|
||||
if ((h == NULL) || (t == NULL)) return;
|
||||
|
||||
/* proceed to last pbuf of chain */
|
||||
for (p = h; p->next != NULL; p = p->next) {
|
||||
/* add total length of second chain to all totals of first chain */
|
||||
p->tot_len += t->tot_len;
|
||||
}
|
||||
/* { p is last pbuf of first h chain, p->next == NULL } */
|
||||
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
|
||||
LWIP_ASSERT("p->next == NULL", p->next == NULL);
|
||||
/* add total length of second chain to last pbuf total of first chain */
|
||||
p->tot_len += t->tot_len;
|
||||
/* chain last pbuf of head (p) with first of tail (t) */
|
||||
p->next = t;
|
||||
/* p->next now references t, but the caller will drop its reference to t,
|
||||
* so netto there is no change to the reference count of t.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Chain two pbufs (or pbuf chains) together.
|
||||
*
|
||||
* The caller MUST call pbuf_free(t) once it has stopped
|
||||
* using it. Use pbuf_cat() instead if you no longer use t.
|
||||
*
|
||||
* @param h head pbuf (chain)
|
||||
* @param t tail pbuf (chain)
|
||||
* @note The pbufs MUST belong to the same packet.
|
||||
* @note MAY NOT be called on a packet queue.
|
||||
*
|
||||
* The ->tot_len fields of all pbufs of the head chain are adjusted.
|
||||
* The ->next field of the last pbuf of the head chain is adjusted.
|
||||
* The ->ref field of the first pbuf of the tail chain is adjusted.
|
||||
*
|
||||
*/
|
||||
void
|
||||
pbuf_chain(struct pbuf *h, struct pbuf *t)
|
||||
{
|
||||
pbuf_cat(h, t);
|
||||
/* t is now referenced by h */
|
||||
pbuf_ref(t);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)h, (void *)t));
|
||||
}
|
||||
|
||||
/* For packet queueing. Note that queued packets MUST be dequeued first
|
||||
* using pbuf_dequeue() before calling other pbuf_() functions. */
|
||||
#if ARP_QUEUEING
|
||||
/**
|
||||
* Add a packet to the end of a queue.
|
||||
*
|
||||
* @param q pointer to first packet on the queue
|
||||
* @param n packet to be queued
|
||||
*
|
||||
* Both packets MUST be given, and must be different.
|
||||
*/
|
||||
void
|
||||
pbuf_queue(struct pbuf *p, struct pbuf *n)
|
||||
{
|
||||
#if PBUF_DEBUG /* remember head of queue */
|
||||
struct pbuf *q = p;
|
||||
#endif
|
||||
/* programmer stupidity checks */
|
||||
LWIP_ASSERT("p == NULL in pbuf_queue: this indicates a programmer error\n", p != NULL);
|
||||
LWIP_ASSERT("n == NULL in pbuf_queue: this indicates a programmer error\n", n != NULL);
|
||||
LWIP_ASSERT("p == n in pbuf_queue: this indicates a programmer error\n", p != n);
|
||||
if ((p == NULL) || (n == NULL) || (p == n)){
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_HALT | 3, ("pbuf_queue: programmer argument error\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* iterate through all packets on queue */
|
||||
while (p->next != NULL) {
|
||||
/* be very picky about pbuf chain correctness */
|
||||
#if PBUF_DEBUG
|
||||
/* iterate through all pbufs in packet */
|
||||
while (p->tot_len != p->len) {
|
||||
/* make sure invariant condition holds */
|
||||
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||
/* make sure each packet is complete */
|
||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||
p = p->next;
|
||||
/* { p->tot_len == p->len => p is last pbuf of a packet } */
|
||||
}
|
||||
/* { p is last pbuf of a packet } */
|
||||
/* proceed to next packet on queue */
|
||||
#endif
|
||||
/* proceed to next pbuf */
|
||||
if (p->next != NULL) p = p->next;
|
||||
}
|
||||
/* { p->tot_len == p->len and p->next == NULL } ==>
|
||||
* { p is last pbuf of last packet on queue } */
|
||||
/* chain last pbuf of queue with n */
|
||||
p->next = n;
|
||||
/* n is now referenced to by the (packet p in the) queue */
|
||||
pbuf_ref(n);
|
||||
#if PBUF_DEBUG
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2,
|
||||
("pbuf_queue: newly queued packet %p sits after packet %p in queue %p\n",
|
||||
(void *)n, (void *)p, (void *)q));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a packet from the head of a queue.
|
||||
*
|
||||
* The caller MUST reference the remainder of the queue (as returned). The
|
||||
* caller MUST NOT call pbuf_ref() as it implicitly takes over the reference
|
||||
* from p.
|
||||
*
|
||||
* @param p pointer to first packet on the queue which will be dequeued.
|
||||
* @return first packet on the remaining queue (NULL if no further packets).
|
||||
*
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_dequeue(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
LWIP_ASSERT("p != NULL", p != NULL);
|
||||
|
||||
/* iterate through all pbufs in packet p */
|
||||
while (p->tot_len != p->len) {
|
||||
/* make sure invariant condition holds */
|
||||
LWIP_ASSERT("p->len < p->tot_len", p->len < p->tot_len);
|
||||
/* make sure each packet is complete */
|
||||
LWIP_ASSERT("p->next != NULL", p->next != NULL);
|
||||
p = p->next;
|
||||
}
|
||||
/* { p->tot_len == p->len } => p is the last pbuf of the first packet */
|
||||
/* remember next packet on queue in q */
|
||||
q = p->next;
|
||||
/* dequeue packet p from queue */
|
||||
p->next = NULL;
|
||||
/* any next packet on queue? */
|
||||
if (q != NULL) {
|
||||
/* although q is no longer referenced by p, it MUST be referenced by
|
||||
* the caller, who is maintaining this packet queue. So, we do not call
|
||||
* pbuf_free(q) here, resulting in an implicit pbuf_ref(q) for the caller. */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: first remaining packet on queue is %p\n", (void *)q));
|
||||
} else {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_dequeue: no further packets on queue\n"));
|
||||
}
|
||||
return q;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* Create PBUF_POOL (or PBUF_RAM) copies of PBUF_REF pbufs.
|
||||
*
|
||||
* Used to queue packets on behalf of the lwIP stack, such as
|
||||
* ARP based queueing.
|
||||
*
|
||||
* Go through a pbuf chain and replace any PBUF_REF buffers
|
||||
* with PBUF_POOL (or PBUF_RAM) pbufs, each taking a copy of
|
||||
* the referenced data.
|
||||
*
|
||||
* @note You MUST explicitly use p = pbuf_take(p);
|
||||
* The pbuf you give as argument, may have been replaced
|
||||
* by a (differently located) copy through pbuf_take()!
|
||||
*
|
||||
* @note Any replaced pbufs will be freed through pbuf_free().
|
||||
* This may deallocate them if they become no longer referenced.
|
||||
*
|
||||
* @param p Head of pbuf chain to process
|
||||
*
|
||||
* @return Pointer to head of pbuf chain
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_take(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q , *prev, *head;
|
||||
LWIP_ASSERT("pbuf_take: p != NULL\n", p != NULL);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_take(%p)\n", (void*)p));
|
||||
|
||||
prev = NULL;
|
||||
head = p;
|
||||
/* iterate through pbuf chain */
|
||||
do
|
||||
{
|
||||
/* pbuf is of type PBUF_REF? */
|
||||
if (p->flags == PBUF_FLAG_REF) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE, ("pbuf_take: encountered PBUF_REF %p\n", (void *)p));
|
||||
/* allocate a pbuf (w/ payload) fully in RAM */
|
||||
/* PBUF_POOL buffers are faster if we can use them */
|
||||
if (p->len <= PBUF_POOL_BUFSIZE) {
|
||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_POOL);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_POOL\n"));
|
||||
}
|
||||
} else {
|
||||
/* no replacement pbuf yet */
|
||||
q = NULL;
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: PBUF_POOL too small to replace PBUF_REF\n"));
|
||||
}
|
||||
/* no (large enough) PBUF_POOL was available? retry with PBUF_RAM */
|
||||
if (q == NULL) {
|
||||
q = pbuf_alloc(PBUF_RAW, p->len, PBUF_RAM);
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 2, ("pbuf_take: Could not allocate PBUF_RAM\n"));
|
||||
}
|
||||
}
|
||||
/* replacement pbuf could be allocated? */
|
||||
if (q != NULL)
|
||||
{
|
||||
/* copy p to q */
|
||||
/* copy successor */
|
||||
q->next = p->next;
|
||||
/* remove linkage from original pbuf */
|
||||
p->next = NULL;
|
||||
/* remove linkage to original pbuf */
|
||||
if (prev != NULL) {
|
||||
/* prev->next == p at this point */
|
||||
LWIP_ASSERT("prev->next == p", prev->next == p);
|
||||
/* break chain and insert new pbuf instead */
|
||||
prev->next = q;
|
||||
/* prev == NULL, so we replaced the head pbuf of the chain */
|
||||
} else {
|
||||
head = q;
|
||||
}
|
||||
/* copy pbuf payload */
|
||||
memcpy(q->payload, p->payload, p->len);
|
||||
q->tot_len = p->tot_len;
|
||||
q->len = p->len;
|
||||
/* in case p was the first pbuf, it is no longer refered to by
|
||||
* our caller, as the caller MUST do p = pbuf_take(p);
|
||||
* in case p was not the first pbuf, it is no longer refered to
|
||||
* by prev. we can safely free the pbuf here.
|
||||
* (note that we have set p->next to NULL already so that
|
||||
* we will not free the rest of the chain by accident.)
|
||||
*/
|
||||
pbuf_free(p);
|
||||
/* do not copy ref, since someone else might be using the old buffer */
|
||||
LWIP_DEBUGF(PBUF_DEBUG, ("pbuf_take: replaced PBUF_REF %p with %p\n", (void *)p, (void *)q));
|
||||
p = q;
|
||||
} else {
|
||||
/* deallocate chain */
|
||||
pbuf_free(head);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_take: failed to allocate replacement pbuf for %p\n", (void *)p));
|
||||
return NULL;
|
||||
}
|
||||
/* p->flags != PBUF_FLAG_REF */
|
||||
} else {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: skipping pbuf not of type PBUF_REF\n"));
|
||||
}
|
||||
/* remember this pbuf */
|
||||
prev = p;
|
||||
/* proceed to next pbuf in original chain */
|
||||
p = p->next;
|
||||
} while (p);
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 1, ("pbuf_take: end of chain reached.\n"));
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dechains the first pbuf from its succeeding pbufs in the chain.
|
||||
*
|
||||
* Makes p->tot_len field equal to p->len.
|
||||
* @param p pbuf to dechain
|
||||
* @return remainder of the pbuf chain, or NULL if it was de-allocated.
|
||||
* @note May not be called on a packet queue.
|
||||
*/
|
||||
struct pbuf *
|
||||
pbuf_dechain(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u8_t tail_gone = 1;
|
||||
/* tail */
|
||||
q = p->next;
|
||||
/* pbuf has successor in chain? */
|
||||
if (q != NULL) {
|
||||
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
||||
LWIP_ASSERT("p->tot_len == p->len + q->tot_len", q->tot_len == p->tot_len - p->len);
|
||||
/* enforce invariant if assertion is disabled */
|
||||
q->tot_len = p->tot_len - p->len;
|
||||
/* decouple pbuf from remainder */
|
||||
p->next = NULL;
|
||||
/* total length of pbuf p is its own length only */
|
||||
p->tot_len = p->len;
|
||||
/* q is no longer referenced by p, free it */
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE, ("pbuf_dechain: unreferencing %p\n", (void *)q));
|
||||
tail_gone = pbuf_free(q);
|
||||
if (tail_gone > 0) {
|
||||
LWIP_DEBUGF(PBUF_DEBUG | DBG_STATE,
|
||||
("pbuf_dechain: deallocated %p (as it is no longer referenced)\n", (void *)q));
|
||||
}
|
||||
/* return remaining tail or NULL if deallocated */
|
||||
}
|
||||
/* assert tot_len invariant: (p->tot_len == p->len + (p->next? p->next->tot_len: 0) */
|
||||
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
|
||||
return (tail_gone > 0? NULL: q);
|
||||
}
|
326
Demo/Common/ethernet/lwIP/core/raw.c
Normal file
326
Demo/Common/ethernet/lwIP/core/raw.c
Normal file
|
@ -0,0 +1,326 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* Implementation of raw protocol PCBs for low-level handling of
|
||||
* different types of protocols besides (or overriding) those
|
||||
* already available in lwIP.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/raw.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if LWIP_RAW
|
||||
|
||||
/** The list of RAW PCBs */
|
||||
static struct raw_pcb *raw_pcbs = NULL;
|
||||
|
||||
void
|
||||
raw_init(void)
|
||||
{
|
||||
raw_pcbs = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if in incoming IP packet is covered by a RAW PCB
|
||||
* and if so, pass it to a user-provided receive callback function.
|
||||
*
|
||||
* Given an incoming IP datagram (as a chain of pbufs) this function
|
||||
* finds a corresponding RAW PCB and calls the corresponding receive
|
||||
* callback function.
|
||||
*
|
||||
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
|
||||
* @param netif network interface on which the datagram was received.
|
||||
* @Return - 1 if the packet has been eaten by a RAW PCB receive
|
||||
* callback function. The caller MAY NOT not reference the
|
||||
* packet any longer, and MAY NOT call pbuf_free().
|
||||
* @return - 0 if packet is not eaten (pbuf is still referenced by the
|
||||
* caller).
|
||||
*
|
||||
*/
|
||||
u8_t
|
||||
raw_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct raw_pcb *pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
s16_t proto;
|
||||
u8_t eaten = 0;
|
||||
|
||||
iphdr = p->payload;
|
||||
proto = IPH_PROTO(iphdr);
|
||||
|
||||
pcb = raw_pcbs;
|
||||
/* loop through all raw pcbs until the packet is eaten by one */
|
||||
/* this allows multiple pcbs to match against the packet by design */
|
||||
while ((eaten == 0) && (pcb != NULL)) {
|
||||
if (pcb->protocol == proto) {
|
||||
/* receive callback function available? */
|
||||
if (pcb->recv != NULL) {
|
||||
/* the receive callback function did not eat the packet? */
|
||||
if (pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)) != 0)
|
||||
{
|
||||
/* receive function ate the packet */
|
||||
p = NULL;
|
||||
eaten = 1;
|
||||
}
|
||||
}
|
||||
/* no receive callback function was set for this raw PCB */
|
||||
/* drop the packet */
|
||||
}
|
||||
pcb = pcb->next;
|
||||
}
|
||||
return eaten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind a RAW PCB.
|
||||
*
|
||||
* @param pcb RAW PCB to be bound with a local address ipaddr.
|
||||
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
|
||||
* bind to all local interfaces.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_USE. The specified IP address is already bound to by
|
||||
* another RAW PCB.
|
||||
*
|
||||
* @see raw_disconnect()
|
||||
*/
|
||||
err_t
|
||||
raw_bind(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect an RAW PCB. This function is required by upper layers
|
||||
* of lwip. Using the raw api you could use raw_sendto() instead
|
||||
*
|
||||
* This will associate the RAW PCB with the remote address.
|
||||
*
|
||||
* @param pcb RAW PCB to be connected with remote address ipaddr and port.
|
||||
* @param ipaddr remote IP address to connect with.
|
||||
*
|
||||
* @return lwIP error code
|
||||
*
|
||||
* @see raw_disconnect() and raw_sendto()
|
||||
*/
|
||||
err_t
|
||||
raw_connect(struct raw_pcb *pcb, struct ip_addr *ipaddr)
|
||||
{
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the callback function for received packets that match the
|
||||
* raw PCB's protocol and binding.
|
||||
*
|
||||
* The callback function MUST either
|
||||
* - eat the packet by calling pbuf_free() and returning non-zero. The
|
||||
* packet will not be passed to other raw PCBs or other protocol layers.
|
||||
* - not free the packet, and return zero. The packet will be matched
|
||||
* against further PCBs and/or forwarded to another protocol layers.
|
||||
*
|
||||
* @return non-zero if the packet was free()d, zero if the packet remains
|
||||
* available for others.
|
||||
*/
|
||||
void
|
||||
raw_recv(struct raw_pcb *pcb,
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *upcb, struct pbuf *p,
|
||||
struct ip_addr *addr),
|
||||
void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
pcb->recv_arg = recv_arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the raw IP packet to the given address. Note that actually you cannot
|
||||
* modify the IP headers (this is inconsistent with the receive callback where
|
||||
* you actually get the IP headers), you can only specify the IP payload here.
|
||||
* It requires some more changes in lwIP. (there will be a raw_send() function
|
||||
* then.)
|
||||
*
|
||||
* @param pcb the raw pcb which to send
|
||||
* @param p the IP payload to send
|
||||
* @param ipaddr the destination address of the IP packet
|
||||
*
|
||||
*/
|
||||
err_t
|
||||
raw_sendto(struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
{
|
||||
err_t err;
|
||||
struct netif *netif;
|
||||
struct ip_addr *src_ip;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_sendto\n"));
|
||||
|
||||
/* not enough space to add an IP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, IP_HLEN)) {
|
||||
/* allocate header in new pbuf */
|
||||
q = pbuf_alloc(PBUF_IP, 0, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 2, ("raw_sendto: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
/* { first pbuf q points to header pbuf } */
|
||||
LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
pbuf_header(q, -IP_HLEN);
|
||||
}
|
||||
|
||||
if ((netif = ip_route(ipaddr)) == NULL) {
|
||||
LWIP_DEBUGF(RAW_DEBUG | 1, ("raw_sendto: No route to 0x%"X32_F"\n", ipaddr->addr));
|
||||
#if RAW_STATS
|
||||
/* ++lwip_stats.raw.rterr;*/
|
||||
#endif /* RAW_STATS */
|
||||
/* free any temporary header pbuf allocated by pbuf_header() */
|
||||
if (q != p) {
|
||||
pbuf_free(q);
|
||||
}
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* use RAW PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip);
|
||||
}
|
||||
|
||||
err = ip_output_if (q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
|
||||
|
||||
/* did we chain a header earlier? */
|
||||
if (q != p) {
|
||||
/* free the header */
|
||||
pbuf_free(q);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the raw IP packet to the address given by raw_connect()
|
||||
*
|
||||
* @param pcb the raw pcb which to send
|
||||
* @param p the IP payload to send
|
||||
* @param ipaddr the destination address of the IP packet
|
||||
*
|
||||
*/
|
||||
err_t
|
||||
raw_send(struct raw_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
return raw_sendto(pcb, p, &pcb->remote_ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an RAW PCB.
|
||||
*
|
||||
* @param pcb RAW PCB to be removed. The PCB is removed from the list of
|
||||
* RAW PCB's and the data structure is freed from memory.
|
||||
*
|
||||
* @see raw_new()
|
||||
*/
|
||||
void
|
||||
raw_remove(struct raw_pcb *pcb)
|
||||
{
|
||||
struct raw_pcb *pcb2;
|
||||
/* pcb to be removed is first in list? */
|
||||
if (raw_pcbs == pcb) {
|
||||
/* make list start at 2nd pcb */
|
||||
raw_pcbs = raw_pcbs->next;
|
||||
/* pcb not 1st in list */
|
||||
} else for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
||||
/* find pcb in raw_pcbs list */
|
||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||
/* remove pcb from list */
|
||||
pcb2->next = pcb->next;
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_RAW_PCB, pcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a RAW PCB.
|
||||
*
|
||||
* @return The RAW PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
* @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP)
|
||||
*
|
||||
* @see raw_remove()
|
||||
*/
|
||||
struct raw_pcb *
|
||||
raw_new(u16_t proto) {
|
||||
struct raw_pcb *pcb;
|
||||
|
||||
LWIP_DEBUGF(RAW_DEBUG | DBG_TRACE | 3, ("raw_new\n"));
|
||||
|
||||
pcb = memp_malloc(MEMP_RAW_PCB);
|
||||
/* could allocate RAW PCB? */
|
||||
if (pcb != NULL) {
|
||||
/* initialize PCB to all zeroes */
|
||||
memset(pcb, 0, sizeof(struct raw_pcb));
|
||||
pcb->protocol = proto;
|
||||
pcb->ttl = RAW_TTL;
|
||||
pcb->next = raw_pcbs;
|
||||
raw_pcbs = pcb;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#endif /* LWIP_RAW */
|
652
Demo/Common/ethernet/lwIP/core/snmp/asn1_dec.c
Normal file
652
Demo/Common/ethernet/lwIP/core/snmp/asn1_dec.c
Normal file
|
@ -0,0 +1,652 @@
|
|||
/**
|
||||
* @file
|
||||
* Abstract Syntax Notation One (ISO 8824, 8825) decoding
|
||||
*
|
||||
* @todo not optimised (yet), favor correctness over speed, favor speed over size
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_SNMP
|
||||
#include "lwip/snmp_asn1.h"
|
||||
|
||||
/**
|
||||
* Retrieves type field from incoming pbuf chain.
|
||||
*
|
||||
* @param p points to a pbuf holding an ASN1 coded type field
|
||||
* @param ofs points to the offset within the pbuf chain of the ASN1 coded type field
|
||||
* @param type return ASN1 type
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
*type = *msg_ptr;
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes length field from incoming pbuf chain into host length.
|
||||
*
|
||||
* @param p points to a pbuf holding an ASN1 coded length
|
||||
* @param ofs points to the offset within the pbuf chain of the ASN1 coded length
|
||||
* @param octets_used returns number of octets used by the length code
|
||||
* @param length return host order length, upto 64k
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (*msg_ptr < 0x80)
|
||||
{
|
||||
/* primitive definite length format */
|
||||
*octets_used = 1;
|
||||
*length = *msg_ptr;
|
||||
return ERR_OK;
|
||||
}
|
||||
else if (*msg_ptr == 0x80)
|
||||
{
|
||||
/* constructed indefinite length format, termination with two zero octets */
|
||||
u8_t zeros;
|
||||
u8_t i;
|
||||
|
||||
*length = 0;
|
||||
zeros = 0;
|
||||
while (zeros != 2)
|
||||
{
|
||||
i = 2;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
(*length) += 1;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
if (*msg_ptr == 0)
|
||||
{
|
||||
zeros++;
|
||||
if (zeros == 2)
|
||||
{
|
||||
/* stop while (i > 0) */
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
zeros = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*octets_used = 1;
|
||||
return ERR_OK;
|
||||
}
|
||||
else if (*msg_ptr == 0x81)
|
||||
{
|
||||
/* constructed definite length format, one octet */
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
*length = *msg_ptr;
|
||||
*octets_used = 2;
|
||||
return ERR_OK;
|
||||
}
|
||||
else if (*msg_ptr == 0x82)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
/* constructed definite length format, two octets */
|
||||
i = 2;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
/* least significant length octet */
|
||||
*length |= *msg_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* most significant length octet */
|
||||
*length = (*msg_ptr) << 8;
|
||||
}
|
||||
}
|
||||
*octets_used = 3;
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* constructed definite length format 3..127 octets, this is too big (>64k) */
|
||||
/** @todo: do we need to accept inefficient codings with many leading zero's? */
|
||||
*octets_used = 1 + ((*msg_ptr) & 0x7f);
|
||||
return ERR_ARG;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes positive integer (counter, gauge, timeticks) into u32_t.
|
||||
*
|
||||
* @param p points to a pbuf holding an ASN1 coded integer
|
||||
* @param ofs points to the offset within the pbuf chain of the ASN1 coded integer
|
||||
* @param len length of the coded integer field
|
||||
* @param value return host order integer
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
|
||||
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
|
||||
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
if ((len > 0) && (len < 6))
|
||||
{
|
||||
/* start from zero */
|
||||
*value = 0;
|
||||
if (*msg_ptr & 0x80)
|
||||
{
|
||||
/* negative, expecting zero sign bit! */
|
||||
return ERR_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* positive */
|
||||
if ((len > 1) && (*msg_ptr == 0))
|
||||
{
|
||||
/* skip leading "sign byte" octet 0x00 */
|
||||
len--;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* OR octets with value */
|
||||
while (len > 1)
|
||||
{
|
||||
len--;
|
||||
*value |= *msg_ptr;
|
||||
*value <<= 8;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
*value |= *msg_ptr;
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ERR_ARG;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes integer into s32_t.
|
||||
*
|
||||
* @param p points to a pbuf holding an ASN1 coded integer
|
||||
* @param ofs points to the offset within the pbuf chain of the ASN1 coded integer
|
||||
* @param len length of the coded integer field
|
||||
* @param value return host order integer
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed!
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
u8_t *lsb_ptr = (u8_t*)value;
|
||||
u8_t sign;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
if ((len > 0) && (len < 5))
|
||||
{
|
||||
if (*msg_ptr & 0x80)
|
||||
{
|
||||
/* negative, start from -1 */
|
||||
*value = -1;
|
||||
sign = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* positive, start from 0 */
|
||||
*value = 0;
|
||||
sign = 0;
|
||||
}
|
||||
/* OR/AND octets with value */
|
||||
while (len > 1)
|
||||
{
|
||||
len--;
|
||||
if (sign)
|
||||
{
|
||||
*lsb_ptr &= *msg_ptr;
|
||||
*value <<= 8;
|
||||
*lsb_ptr |= 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
*lsb_ptr |= *msg_ptr;
|
||||
*value <<= 8;
|
||||
}
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
if (sign)
|
||||
{
|
||||
*lsb_ptr &= *msg_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
*lsb_ptr |= *msg_ptr;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ERR_ARG;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes object identifier from incoming message into array of s32_t.
|
||||
*
|
||||
* @param p points to a pbuf holding an ASN1 coded object identifier
|
||||
* @param ofs points to the offset within the pbuf chain of the ASN1 coded object identifier
|
||||
* @param len length of the coded object identifier
|
||||
* @param oid return object identifier struct
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
s32_t *oid_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
oid->len = 0;
|
||||
oid_ptr = &oid->id[0];
|
||||
if (len > 0)
|
||||
{
|
||||
/* first compressed octet */
|
||||
if (*msg_ptr == 0x2B)
|
||||
{
|
||||
/* (most) common case 1.3 (iso.org) */
|
||||
*oid_ptr = 1;
|
||||
oid_ptr++;
|
||||
*oid_ptr = 3;
|
||||
oid_ptr++;
|
||||
}
|
||||
else if (*msg_ptr < 40)
|
||||
{
|
||||
*oid_ptr = 0;
|
||||
oid_ptr++;
|
||||
*oid_ptr = *msg_ptr;
|
||||
oid_ptr++;
|
||||
}
|
||||
else if (*msg_ptr < 80)
|
||||
{
|
||||
*oid_ptr = 1;
|
||||
oid_ptr++;
|
||||
*oid_ptr = (*msg_ptr) - 40;
|
||||
oid_ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*oid_ptr = 2;
|
||||
oid_ptr++;
|
||||
*oid_ptr = (*msg_ptr) - 80;
|
||||
oid_ptr++;
|
||||
}
|
||||
oid->len = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* accepting zero length identifiers e.g. for
|
||||
getnext operation. uncommon but valid */
|
||||
return ERR_OK;
|
||||
}
|
||||
len--;
|
||||
if (len > 0)
|
||||
{
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
while ((len > 0) && (oid->len < LWIP_SNMP_OBJ_ID_LEN))
|
||||
{
|
||||
/* sub-identifier uses multiple octets */
|
||||
if (*msg_ptr & 0x80)
|
||||
{
|
||||
s32_t sub_id = 0;
|
||||
|
||||
while ((*msg_ptr & 0x80) && (len > 1))
|
||||
{
|
||||
len--;
|
||||
sub_id = (sub_id << 7) + (*msg_ptr & ~0x80);
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
if (!(*msg_ptr & 0x80) && (len > 0))
|
||||
{
|
||||
/* last octet sub-identifier */
|
||||
len--;
|
||||
sub_id = (sub_id << 7) + *msg_ptr;
|
||||
*oid_ptr = sub_id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* !(*msg_ptr & 0x80) sub-identifier uses single octet */
|
||||
len--;
|
||||
*oid_ptr = *msg_ptr;
|
||||
}
|
||||
if (len > 0)
|
||||
{
|
||||
/* remaining oid bytes available ... */
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
oid_ptr++;
|
||||
oid->len++;
|
||||
}
|
||||
if (len == 0)
|
||||
{
|
||||
/* len == 0, end of oid */
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* len > 0, oid->len == LWIP_SNMP_OBJ_ID_LEN or malformed encoding */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding)
|
||||
* from incoming message into array.
|
||||
*
|
||||
* @param p points to a pbuf holding an ASN1 coded raw data
|
||||
* @param ofs points to the offset within the pbuf chain of the ASN1 coded raw data
|
||||
* @param len length of the coded raw data (zero is valid, e.g. empty string!)
|
||||
* @param raw_len length of the raw return value
|
||||
* @param raw return raw bytes
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) decode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
if (raw_len >= len)
|
||||
{
|
||||
while (len > 1)
|
||||
{
|
||||
/* copy len - 1 octets */
|
||||
len--;
|
||||
*raw = *msg_ptr;
|
||||
raw++;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
/* copy last octet */
|
||||
*raw = *msg_ptr;
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* raw_len < len, not enough dst space */
|
||||
return ERR_ARG;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* len == 0, empty string */
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LWIP_SNMP */
|
||||
|
610
Demo/Common/ethernet/lwIP/core/snmp/asn1_enc.c
Normal file
610
Demo/Common/ethernet/lwIP/core/snmp/asn1_enc.c
Normal file
|
@ -0,0 +1,610 @@
|
|||
/**
|
||||
* @file
|
||||
* Abstract Syntax Notation One (ISO 8824, 8825) encoding
|
||||
*
|
||||
* @todo not optimised (yet), favor correctness over speed, favor speed over size
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_SNMP
|
||||
#include "lwip/snmp_asn1.h"
|
||||
|
||||
/**
|
||||
* Returns octet count for length.
|
||||
*
|
||||
* @param length
|
||||
* @param octets_needed points to the return value
|
||||
*/
|
||||
void
|
||||
snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed)
|
||||
{
|
||||
if (length < 0x80U)
|
||||
{
|
||||
*octets_needed = 1;
|
||||
}
|
||||
else if (length < 0x100U)
|
||||
{
|
||||
*octets_needed = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
*octets_needed = 3;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns octet count for an u32_t.
|
||||
*
|
||||
* @param value
|
||||
* @param octets_needed points to the return value
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded
|
||||
* as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value
|
||||
* of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!!
|
||||
*/
|
||||
void
|
||||
snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed)
|
||||
{
|
||||
if (value < 0x80UL)
|
||||
{
|
||||
*octets_needed = 1;
|
||||
}
|
||||
else if (value < 0x8000UL)
|
||||
{
|
||||
*octets_needed = 2;
|
||||
}
|
||||
else if (value < 0x800000UL)
|
||||
{
|
||||
*octets_needed = 3;
|
||||
}
|
||||
else if (value < 0x80000000UL)
|
||||
{
|
||||
*octets_needed = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
*octets_needed = 5;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns octet count for an s32_t.
|
||||
*
|
||||
* @param value
|
||||
* @param octets_needed points to the return value
|
||||
*
|
||||
* @note ASN coded integers are _always_ signed.
|
||||
*/
|
||||
void
|
||||
snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
value = ~value;
|
||||
}
|
||||
if (value < 0x80L)
|
||||
{
|
||||
*octets_needed = 1;
|
||||
}
|
||||
else if (value < 0x8000L)
|
||||
{
|
||||
*octets_needed = 2;
|
||||
}
|
||||
else if (value < 0x800000L)
|
||||
{
|
||||
*octets_needed = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*octets_needed = 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns octet count for an object identifier.
|
||||
*
|
||||
* @param ident_len object identifier array length
|
||||
* @param ident points to object identifier array
|
||||
* @param octets_needed points to the return value
|
||||
*/
|
||||
void
|
||||
snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed)
|
||||
{
|
||||
s32_t sub_id;
|
||||
u8_t cnt;
|
||||
|
||||
cnt = 0;
|
||||
if (ident_len > 1)
|
||||
{
|
||||
/* compressed prefix in one octet */
|
||||
cnt++;
|
||||
ident_len -= 2;
|
||||
ident += 2;
|
||||
}
|
||||
while(ident_len > 0)
|
||||
{
|
||||
ident_len--;
|
||||
sub_id = *ident;
|
||||
|
||||
sub_id >>= 7;
|
||||
cnt++;
|
||||
while(sub_id > 0)
|
||||
{
|
||||
sub_id >>= 7;
|
||||
cnt++;
|
||||
}
|
||||
ident++;
|
||||
}
|
||||
*octets_needed = cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes ASN type field into a pbuf chained ASN1 msg.
|
||||
*
|
||||
* @param p points to output pbuf to encode value into
|
||||
* @param ofs points to the offset within the pbuf chain
|
||||
* @param type input ASN1 type
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
*msg_ptr = type;
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes host order length field into a pbuf chained ASN1 msg.
|
||||
*
|
||||
* @param p points to output pbuf to encode length into
|
||||
* @param ofs points to the offset within the pbuf chain
|
||||
* @param length is the host order length to be encoded
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (length < 0x80)
|
||||
{
|
||||
*msg_ptr = length;
|
||||
return ERR_OK;
|
||||
}
|
||||
else if (length < 0x100)
|
||||
{
|
||||
*msg_ptr = 0x81;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
*msg_ptr = length;
|
||||
return ERR_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
/* length >= 0x100 && length <= 0xFFFF */
|
||||
*msg_ptr = 0x82;
|
||||
i = 2;
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
/* least significant length octet */
|
||||
*msg_ptr = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* most significant length octet */
|
||||
*msg_ptr = length >> 8;
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg.
|
||||
*
|
||||
* @param p points to output pbuf to encode value into
|
||||
* @param ofs points to the offset within the pbuf chain
|
||||
* @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt())
|
||||
* @param value is the host order u32_t value to be encoded
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*
|
||||
* @see snmp_asn1_enc_u32t_cnt()
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (octets_needed == 5)
|
||||
{
|
||||
/* not enough bits in 'value' add leading 0x00 */
|
||||
octets_needed--;
|
||||
*msg_ptr = 0x00;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
while (octets_needed > 1)
|
||||
{
|
||||
octets_needed--;
|
||||
*msg_ptr = value >> (octets_needed << 3);
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
/* (only) one least significant octet */
|
||||
*msg_ptr = value;
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes s32_t integer into a pbuf chained ASN1 msg.
|
||||
*
|
||||
* @param p points to output pbuf to encode value into
|
||||
* @param ofs points to the offset within the pbuf chain
|
||||
* @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt())
|
||||
* @param value is the host order s32_t value to be encoded
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*
|
||||
* @see snmp_asn1_enc_s32t_cnt()
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
while (octets_needed > 1)
|
||||
{
|
||||
octets_needed--;
|
||||
*msg_ptr = value >> (octets_needed << 3);
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
/* (only) one least significant octet */
|
||||
*msg_ptr = value;
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes object identifier into a pbuf chained ASN1 msg.
|
||||
*
|
||||
* @param p points to output pbuf to encode oid into
|
||||
* @param ofs points to the offset within the pbuf chain
|
||||
* @param ident_len object identifier array length
|
||||
* @param ident points to object identifier array
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
if (ident_len > 1)
|
||||
{
|
||||
if ((ident[0] == 1) && (ident[1] == 3))
|
||||
{
|
||||
/* compressed (most common) prefix .iso.org */
|
||||
*msg_ptr = 0x2b;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* calculate prefix */
|
||||
*msg_ptr = (ident[0] * 40) + ident[1];
|
||||
}
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
ident_len -= 2;
|
||||
ident += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */
|
||||
/* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */
|
||||
return ERR_ARG;
|
||||
}
|
||||
while (ident_len > 0)
|
||||
{
|
||||
s32_t sub_id;
|
||||
u8_t shift, tail;
|
||||
|
||||
ident_len--;
|
||||
sub_id = *ident;
|
||||
tail = 0;
|
||||
shift = 28;
|
||||
while(shift > 0)
|
||||
{
|
||||
u8_t code;
|
||||
|
||||
code = sub_id >> shift;
|
||||
if ((code != 0) || (tail != 0))
|
||||
{
|
||||
tail = 1;
|
||||
*msg_ptr = code | 0x80;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
shift -= 7;
|
||||
}
|
||||
*msg_ptr = (u8_t)sub_id & 0x7F;
|
||||
if (ident_len > 0)
|
||||
{
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
/* proceed to next sub-identifier */
|
||||
ident++;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg.
|
||||
*
|
||||
* @param p points to output pbuf to encode raw data into
|
||||
* @param ofs points to the offset within the pbuf chain
|
||||
* @param raw_len raw data length
|
||||
* @param raw points raw data
|
||||
* @return ERR_OK if successfull, ERR_ARG if we can't (or won't) encode
|
||||
*/
|
||||
err_t
|
||||
snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw)
|
||||
{
|
||||
u16_t plen, base;
|
||||
u8_t *msg_ptr;
|
||||
|
||||
plen = 0;
|
||||
while (p != NULL)
|
||||
{
|
||||
base = plen;
|
||||
plen += p->len;
|
||||
if (ofs < plen)
|
||||
{
|
||||
msg_ptr = p->payload;
|
||||
msg_ptr += ofs - base;
|
||||
|
||||
while (raw_len > 1)
|
||||
{
|
||||
/* copy raw_len - 1 octets */
|
||||
raw_len--;
|
||||
*msg_ptr = *raw;
|
||||
raw++;
|
||||
ofs += 1;
|
||||
if (ofs >= plen)
|
||||
{
|
||||
/* next octet in next pbuf */
|
||||
p = p->next;
|
||||
if (p == NULL) { return ERR_ARG; }
|
||||
msg_ptr = p->payload;
|
||||
plen += p->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next octet in same pbuf */
|
||||
msg_ptr++;
|
||||
}
|
||||
}
|
||||
if (raw_len > 0)
|
||||
{
|
||||
/* copy last or single octet */
|
||||
*msg_ptr = *raw;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
/* p == NULL, ofs >= plen */
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
#endif /* LWIP_SNMP */
|
4021
Demo/Common/ethernet/lwIP/core/snmp/mib2.c
Normal file
4021
Demo/Common/ethernet/lwIP/core/snmp/mib2.c
Normal file
File diff suppressed because it is too large
Load diff
1185
Demo/Common/ethernet/lwIP/core/snmp/mib_structs.c
Normal file
1185
Demo/Common/ethernet/lwIP/core/snmp/mib_structs.c
Normal file
File diff suppressed because it is too large
Load diff
1458
Demo/Common/ethernet/lwIP/core/snmp/msg_in.c
Normal file
1458
Demo/Common/ethernet/lwIP/core/snmp/msg_in.c
Normal file
File diff suppressed because it is too large
Load diff
687
Demo/Common/ethernet/lwIP/core/snmp/msg_out.c
Normal file
687
Demo/Common/ethernet/lwIP/core/snmp/msg_out.c
Normal file
|
@ -0,0 +1,687 @@
|
|||
/**
|
||||
* @file
|
||||
* SNMP output message processing (RFC1157).
|
||||
*
|
||||
* Output responses and traps are build in two passes:
|
||||
*
|
||||
* Pass 0: iterate over the output message backwards to determine encoding lengths
|
||||
* Pass 1: the actual forward encoding of internal form into ASN1
|
||||
*
|
||||
* The single-pass encoding method described by Comer & Stevens
|
||||
* requires extra buffer space and copying for reversal of the packet.
|
||||
* The buffer requirement can be prohibitively large for big payloads
|
||||
* (>= 484) therefore we use the two encoding passes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_SNMP
|
||||
#include "arch/cc.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/snmp_asn1.h"
|
||||
#include "lwip/snmp_msg.h"
|
||||
|
||||
struct snmp_trap_dst
|
||||
{
|
||||
/* destination IP address in network order */
|
||||
struct ip_addr dip;
|
||||
/* set to 0 when disabled, >0 when enabled */
|
||||
u8_t enable;
|
||||
};
|
||||
#if (SNMP_TRAP_DESTINATIONS == 0)
|
||||
#error "need at least one trap destination"
|
||||
#endif
|
||||
struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS];
|
||||
|
||||
/** TRAP message structure */
|
||||
struct snmp_msg_trap trap_msg;
|
||||
|
||||
static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len);
|
||||
static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len);
|
||||
static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root);
|
||||
|
||||
static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p);
|
||||
static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p);
|
||||
static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs);
|
||||
|
||||
/**
|
||||
* Sets enable switch for this trap destination.
|
||||
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
|
||||
* @param enable switch if 0 destination is disabled >0 enabled.
|
||||
*/
|
||||
void
|
||||
snmp_trap_dst_enable(u8_t dst_idx, u8_t enable)
|
||||
{
|
||||
if (dst_idx < SNMP_TRAP_DESTINATIONS)
|
||||
{
|
||||
trap_dst[dst_idx].enable = enable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets IPv4 address for this trap destination.
|
||||
* @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1
|
||||
* @param dst IPv4 address in host order.
|
||||
*/
|
||||
void
|
||||
snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst)
|
||||
{
|
||||
if (dst_idx < SNMP_TRAP_DESTINATIONS)
|
||||
{
|
||||
trap_dst[dst_idx].dip.addr = htonl(dst->addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a 'getresponse' message to the request originator.
|
||||
*
|
||||
* @param m_stat points to the current message request state source
|
||||
* @return ERR_OK when success, ERR_MEM if we're out of memory
|
||||
*
|
||||
* @note the caller is responsible for filling in outvb in the m_stat
|
||||
* and provide error-status and index (except for tooBig errors) ...
|
||||
*/
|
||||
err_t
|
||||
snmp_send_response(struct snmp_msg_pstat *m_stat)
|
||||
{
|
||||
struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0};
|
||||
struct pbuf *p;
|
||||
u16_t tot_len;
|
||||
err_t err;
|
||||
|
||||
/* pass 0, calculate length fields */
|
||||
tot_len = snmp_varbind_list_sum(&m_stat->outvb);
|
||||
tot_len = snmp_resp_header_sum(m_stat, tot_len);
|
||||
|
||||
/* try allocating pbuf(s) for complete response */
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);
|
||||
if (p == NULL)
|
||||
{
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n"));
|
||||
|
||||
/* can't construct reply, return error-status tooBig */
|
||||
m_stat->error_status = SNMP_ES_TOOBIG;
|
||||
m_stat->error_index = 0;
|
||||
/* pass 0, recalculate lengths, for empty varbind-list */
|
||||
tot_len = snmp_varbind_list_sum(&emptyvb);
|
||||
tot_len = snmp_resp_header_sum(m_stat, tot_len);
|
||||
/* retry allocation once for header and empty varbind-list */
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);
|
||||
}
|
||||
if (p != NULL)
|
||||
{
|
||||
/* first pbuf alloc try or retry alloc success */
|
||||
u16_t ofs;
|
||||
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n"));
|
||||
|
||||
/* pass 1, size error, encode packet ino the pbuf(s) */
|
||||
ofs = snmp_resp_header_enc(m_stat, p);
|
||||
if (m_stat->error_status == SNMP_ES_TOOBIG)
|
||||
{
|
||||
snmp_varbind_list_enc(&emptyvb, p, ofs);
|
||||
}
|
||||
else
|
||||
{
|
||||
snmp_varbind_list_enc(&m_stat->outvb, p, ofs);
|
||||
}
|
||||
|
||||
switch (m_stat->error_status)
|
||||
{
|
||||
case SNMP_ES_TOOBIG:
|
||||
snmp_inc_snmpouttoobigs();
|
||||
break;
|
||||
case SNMP_ES_NOSUCHNAME:
|
||||
snmp_inc_snmpoutnosuchnames();
|
||||
break;
|
||||
case SNMP_ES_BADVALUE:
|
||||
snmp_inc_snmpoutbadvalues();
|
||||
break;
|
||||
case SNMP_ES_GENERROR:
|
||||
snmp_inc_snmpoutgenerrs();
|
||||
break;
|
||||
}
|
||||
snmp_inc_snmpoutgetresponses();
|
||||
snmp_inc_snmpoutpkts();
|
||||
|
||||
/** @todo do we need separate rx and tx pcbs for threaded case? */
|
||||
/** connect to the originating source */
|
||||
udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp);
|
||||
err = udp_send(m_stat->pcb, p);
|
||||
if (err == ERR_MEM)
|
||||
{
|
||||
/** @todo release some memory, retry and return tooBig? tooMuchHassle? */
|
||||
err = ERR_MEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = ERR_OK;
|
||||
}
|
||||
/** disassociate remote address and port with this pcb */
|
||||
udp_disconnect(m_stat->pcb);
|
||||
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n"));
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* first pbuf alloc try or retry alloc failed
|
||||
very low on memory, couldn't return tooBig */
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends an generic or enterprise specific trap message.
|
||||
*
|
||||
* @param generic_trap is the trap code
|
||||
* @param eoid points to enterprise object identifier
|
||||
* @param specific_trap used for enterprise traps when generic_trap == 6
|
||||
* @return ERR_OK when success, ERR_MEM if we're out of memory
|
||||
*
|
||||
* @note the caller is responsible for filling in outvb in the trap_msg
|
||||
* @note the use of the enterpise identifier field
|
||||
* is per RFC1215.
|
||||
* Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps
|
||||
* and .iso.org.dod.internet.private.enterprises.yourenterprise
|
||||
* (sysObjectID) for specific traps.
|
||||
*/
|
||||
err_t
|
||||
snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap)
|
||||
{
|
||||
struct snmp_trap_dst *td;
|
||||
struct netif *dst_if;
|
||||
struct ip_addr dst_ip;
|
||||
struct pbuf *p;
|
||||
u16_t i,tot_len;
|
||||
|
||||
for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++)
|
||||
{
|
||||
if ((td->enable != 0) && (td->dip.addr != 0))
|
||||
{
|
||||
/* network order trap destination */
|
||||
trap_msg.dip.addr = td->dip.addr;
|
||||
/* lookup current source address for this dst */
|
||||
dst_if = ip_route(&td->dip);
|
||||
dst_ip.addr = ntohl(dst_if->ip_addr.addr);
|
||||
trap_msg.sip_raw[0] = dst_ip.addr >> 24;
|
||||
trap_msg.sip_raw[1] = dst_ip.addr >> 16;
|
||||
trap_msg.sip_raw[2] = dst_ip.addr >> 8;
|
||||
trap_msg.sip_raw[3] = dst_ip.addr;
|
||||
trap_msg.gen_trap = generic_trap;
|
||||
trap_msg.spc_trap = specific_trap;
|
||||
if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC)
|
||||
{
|
||||
/* enterprise-Specific trap */
|
||||
trap_msg.enterprise = eoid;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* generic (MIB-II) trap */
|
||||
snmp_get_snmpgrpid_ptr(&trap_msg.enterprise);
|
||||
}
|
||||
snmp_get_sysuptime(&trap_msg.ts);
|
||||
|
||||
/* pass 0, calculate length fields */
|
||||
tot_len = snmp_varbind_list_sum(&trap_msg.outvb);
|
||||
tot_len = snmp_trap_header_sum(&trap_msg, tot_len);
|
||||
|
||||
/* allocate pbuf(s) */
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL);
|
||||
if (p != NULL)
|
||||
{
|
||||
u16_t ofs;
|
||||
|
||||
/* pass 1, encode packet ino the pbuf(s) */
|
||||
ofs = snmp_trap_header_enc(&trap_msg, p);
|
||||
snmp_varbind_list_enc(&trap_msg.outvb, p, ofs);
|
||||
|
||||
snmp_inc_snmpouttraps();
|
||||
snmp_inc_snmpoutpkts();
|
||||
|
||||
/** connect to the TRAP destination */
|
||||
udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT);
|
||||
udp_send(trap_msg.pcb, p);
|
||||
/** disassociate remote address and port with this pcb */
|
||||
udp_disconnect(trap_msg.pcb);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
snmp_coldstart_trap(void)
|
||||
{
|
||||
trap_msg.outvb.head = NULL;
|
||||
trap_msg.outvb.tail = NULL;
|
||||
trap_msg.outvb.count = 0;
|
||||
snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0);
|
||||
}
|
||||
|
||||
void
|
||||
snmp_authfail_trap(void)
|
||||
{
|
||||
u8_t enable;
|
||||
snmp_get_snmpenableauthentraps(&enable);
|
||||
if (enable == 1)
|
||||
{
|
||||
trap_msg.outvb.head = NULL;
|
||||
trap_msg.outvb.tail = NULL;
|
||||
trap_msg.outvb.count = 0;
|
||||
snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums response header field lengths from tail to head and
|
||||
* returns resp_header_lengths for second encoding pass.
|
||||
*
|
||||
* @param vb_len varbind-list length
|
||||
* @param rhl points to returned header lengths
|
||||
* @return the required lenght for encoding the response header
|
||||
*/
|
||||
static u16_t
|
||||
snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len)
|
||||
{
|
||||
u16_t tot_len;
|
||||
struct snmp_resp_header_lengths *rhl;
|
||||
|
||||
rhl = &m_stat->rhl;
|
||||
tot_len = vb_len;
|
||||
snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen);
|
||||
snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen);
|
||||
tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen;
|
||||
|
||||
snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen);
|
||||
snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen);
|
||||
tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen;
|
||||
|
||||
snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen);
|
||||
snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen);
|
||||
tot_len += 1 + rhl->ridlenlen + rhl->ridlen;
|
||||
|
||||
rhl->pdulen = tot_len;
|
||||
snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen);
|
||||
tot_len += 1 + rhl->pdulenlen;
|
||||
|
||||
rhl->comlen = m_stat->com_strlen;
|
||||
snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen);
|
||||
tot_len += 1 + rhl->comlenlen + rhl->comlen;
|
||||
|
||||
snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen);
|
||||
snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen);
|
||||
tot_len += 1 + rhl->verlen + rhl->verlenlen;
|
||||
|
||||
rhl->seqlen = tot_len;
|
||||
snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen);
|
||||
tot_len += 1 + rhl->seqlenlen;
|
||||
|
||||
return tot_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums trap header field lengths from tail to head and
|
||||
* returns trap_header_lengths for second encoding pass.
|
||||
*
|
||||
* @param vb_len varbind-list length
|
||||
* @param thl points to returned header lengths
|
||||
* @return the required lenght for encoding the trap header
|
||||
*/
|
||||
static u16_t
|
||||
snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len)
|
||||
{
|
||||
u16_t tot_len;
|
||||
struct snmp_trap_header_lengths *thl;
|
||||
|
||||
thl = &m_trap->thl;
|
||||
tot_len = vb_len;
|
||||
|
||||
snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen);
|
||||
snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen);
|
||||
tot_len += 1 + thl->tslen + thl->tslenlen;
|
||||
|
||||
snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen);
|
||||
snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen);
|
||||
tot_len += 1 + thl->strplen + thl->strplenlen;
|
||||
|
||||
snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen);
|
||||
snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen);
|
||||
tot_len += 1 + thl->gtrplen + thl->gtrplenlen;
|
||||
|
||||
thl->aaddrlen = 4;
|
||||
snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen);
|
||||
tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen;
|
||||
|
||||
snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen);
|
||||
snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen);
|
||||
tot_len += 1 + thl->eidlen + thl->eidlenlen;
|
||||
|
||||
thl->pdulen = tot_len;
|
||||
snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen);
|
||||
tot_len += 1 + thl->pdulenlen;
|
||||
|
||||
thl->comlen = sizeof(snmp_publiccommunity) - 1;
|
||||
snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen);
|
||||
tot_len += 1 + thl->comlenlen + thl->comlen;
|
||||
|
||||
snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen);
|
||||
snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen);
|
||||
tot_len += 1 + thl->verlen + thl->verlenlen;
|
||||
|
||||
thl->seqlen = tot_len;
|
||||
snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen);
|
||||
tot_len += 1 + thl->seqlenlen;
|
||||
|
||||
return tot_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums varbind lengths from tail to head and
|
||||
* annotates lengths in varbind for second encoding pass.
|
||||
*
|
||||
* @param root points to the root of the variable binding list
|
||||
* @return the required lenght for encoding the variable bindings
|
||||
*/
|
||||
static u16_t
|
||||
snmp_varbind_list_sum(struct snmp_varbind_root *root)
|
||||
{
|
||||
struct snmp_varbind *vb;
|
||||
u32_t *uint_ptr;
|
||||
s32_t *sint_ptr;
|
||||
u16_t tot_len;
|
||||
|
||||
tot_len = 0;
|
||||
vb = root->tail;
|
||||
while ( vb != NULL )
|
||||
{
|
||||
/* encoded value lenght depends on type */
|
||||
switch (vb->value_type)
|
||||
{
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
|
||||
sint_ptr = vb->value;
|
||||
snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen);
|
||||
break;
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
|
||||
uint_ptr = vb->value;
|
||||
snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen);
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
|
||||
vb->vlen = vb->value_len;
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
|
||||
sint_ptr = vb->value;
|
||||
snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen);
|
||||
break;
|
||||
default:
|
||||
/* unsupported type */
|
||||
vb->vlen = 0;
|
||||
break;
|
||||
};
|
||||
/* encoding length of value length field */
|
||||
snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen);
|
||||
snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen);
|
||||
snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen);
|
||||
|
||||
vb->seqlen = 1 + vb->vlenlen + vb->vlen;
|
||||
vb->seqlen += 1 + vb->olenlen + vb->olen;
|
||||
snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen);
|
||||
|
||||
/* varbind seq */
|
||||
tot_len += 1 + vb->seqlenlen + vb->seqlen;
|
||||
|
||||
vb = vb->prev;
|
||||
}
|
||||
|
||||
/* varbind-list seq */
|
||||
root->seqlen = tot_len;
|
||||
snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen);
|
||||
tot_len += 1 + root->seqlenlen;
|
||||
|
||||
return tot_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes response header from head to tail.
|
||||
*/
|
||||
static u16_t
|
||||
snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p)
|
||||
{
|
||||
u16_t ofs;
|
||||
|
||||
ofs = 0;
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen);
|
||||
ofs += m_stat->rhl.seqlenlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen);
|
||||
ofs += m_stat->rhl.verlenlen;
|
||||
snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version);
|
||||
ofs += m_stat->rhl.verlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen);
|
||||
ofs += m_stat->rhl.comlenlen;
|
||||
snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community);
|
||||
ofs += m_stat->rhl.comlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen);
|
||||
ofs += m_stat->rhl.pdulenlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen);
|
||||
ofs += m_stat->rhl.ridlenlen;
|
||||
snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid);
|
||||
ofs += m_stat->rhl.ridlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen);
|
||||
ofs += m_stat->rhl.errstatlenlen;
|
||||
snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status);
|
||||
ofs += m_stat->rhl.errstatlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen);
|
||||
ofs += m_stat->rhl.erridxlenlen;
|
||||
snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index);
|
||||
ofs += m_stat->rhl.erridxlen;
|
||||
|
||||
return ofs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes trap header from head to tail.
|
||||
*/
|
||||
static u16_t
|
||||
snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p)
|
||||
{
|
||||
u16_t ofs;
|
||||
|
||||
ofs = 0;
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen);
|
||||
ofs += m_trap->thl.seqlenlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen);
|
||||
ofs += m_trap->thl.verlenlen;
|
||||
snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version);
|
||||
ofs += m_trap->thl.verlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen);
|
||||
ofs += m_trap->thl.comlenlen;
|
||||
snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]);
|
||||
ofs += m_trap->thl.comlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen);
|
||||
ofs += m_trap->thl.pdulenlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen);
|
||||
ofs += m_trap->thl.eidlenlen;
|
||||
snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]);
|
||||
ofs += m_trap->thl.eidlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen);
|
||||
ofs += m_trap->thl.aaddrlenlen;
|
||||
snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]);
|
||||
ofs += m_trap->thl.aaddrlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen);
|
||||
ofs += m_trap->thl.gtrplenlen;
|
||||
snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap);
|
||||
ofs += m_trap->thl.gtrplen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen);
|
||||
ofs += m_trap->thl.strplenlen;
|
||||
snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap);
|
||||
ofs += m_trap->thl.strplen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen);
|
||||
ofs += m_trap->thl.tslenlen;
|
||||
snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts);
|
||||
ofs += m_trap->thl.tslen;
|
||||
|
||||
return ofs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes varbind list from head to tail.
|
||||
*/
|
||||
static u16_t
|
||||
snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs)
|
||||
{
|
||||
struct snmp_varbind *vb;
|
||||
s32_t *sint_ptr;
|
||||
u32_t *uint_ptr;
|
||||
u8_t *raw_ptr;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, root->seqlen);
|
||||
ofs += root->seqlenlen;
|
||||
|
||||
vb = root->head;
|
||||
while ( vb != NULL )
|
||||
{
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, vb->seqlen);
|
||||
ofs += vb->seqlenlen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID));
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, vb->olen);
|
||||
ofs += vb->olenlen;
|
||||
snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]);
|
||||
ofs += vb->olen;
|
||||
|
||||
snmp_asn1_enc_type(p, ofs, vb->value_type);
|
||||
ofs += 1;
|
||||
snmp_asn1_enc_length(p, ofs, vb->vlen);
|
||||
ofs += vb->vlenlen;
|
||||
|
||||
switch (vb->value_type)
|
||||
{
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
|
||||
sint_ptr = vb->value;
|
||||
snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr);
|
||||
break;
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
|
||||
uint_ptr = vb->value;
|
||||
snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr);
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
|
||||
case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
|
||||
raw_ptr = vb->value;
|
||||
snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr);
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
|
||||
break;
|
||||
case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
|
||||
sint_ptr = vb->value;
|
||||
snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr);
|
||||
break;
|
||||
default:
|
||||
/* unsupported type */
|
||||
break;
|
||||
};
|
||||
ofs += vb->vlen;
|
||||
vb = vb->next;
|
||||
}
|
||||
return ofs;
|
||||
}
|
||||
|
||||
#endif /* LWIP_SNMP */
|
115
Demo/Common/ethernet/lwIP/core/stats.c
Normal file
115
Demo/Common/ethernet/lwIP/core/stats.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
|
||||
#if LWIP_STATS
|
||||
struct stats_ lwip_stats;
|
||||
|
||||
void
|
||||
stats_init(void)
|
||||
{
|
||||
memset(&lwip_stats, 0, sizeof(struct stats_));
|
||||
}
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void
|
||||
stats_display_proto(struct stats_proto *proto, char *name)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\n%s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("xmit: %"S16_F"\n\t", proto->xmit));
|
||||
LWIP_PLATFORM_DIAG(("rexmit: %"S16_F"\n\t", proto->rexmit));
|
||||
LWIP_PLATFORM_DIAG(("recv: %"S16_F"\n\t", proto->recv));
|
||||
LWIP_PLATFORM_DIAG(("fw: %"S16_F"\n\t", proto->fw));
|
||||
LWIP_PLATFORM_DIAG(("drop: %"S16_F"\n\t", proto->drop));
|
||||
LWIP_PLATFORM_DIAG(("chkerr: %"S16_F"\n\t", proto->chkerr));
|
||||
LWIP_PLATFORM_DIAG(("lenerr: %"S16_F"\n\t", proto->lenerr));
|
||||
LWIP_PLATFORM_DIAG(("memerr: %"S16_F"\n\t", proto->memerr));
|
||||
LWIP_PLATFORM_DIAG(("rterr: %"S16_F"\n\t", proto->rterr));
|
||||
LWIP_PLATFORM_DIAG(("proterr: %"S16_F"\n\t", proto->proterr));
|
||||
LWIP_PLATFORM_DIAG(("opterr: %"S16_F"\n\t", proto->opterr));
|
||||
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", proto->err));
|
||||
LWIP_PLATFORM_DIAG(("cachehit: %"S16_F"\n", proto->cachehit));
|
||||
}
|
||||
|
||||
void
|
||||
stats_display_pbuf(struct stats_pbuf *pbuf)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\nPBUF\n\t"));
|
||||
LWIP_PLATFORM_DIAG(("avail: %"S16_F"\n\t", pbuf->avail));
|
||||
LWIP_PLATFORM_DIAG(("used: %"S16_F"\n\t", pbuf->used));
|
||||
LWIP_PLATFORM_DIAG(("max: %"S16_F"\n\t", pbuf->max));
|
||||
LWIP_PLATFORM_DIAG(("err: %"S16_F"\n\t", pbuf->err));
|
||||
LWIP_PLATFORM_DIAG(("alloc_locked: %"S16_F"\n\t", pbuf->alloc_locked));
|
||||
LWIP_PLATFORM_DIAG(("refresh_locked: %"S16_F"\n", pbuf->refresh_locked));
|
||||
}
|
||||
|
||||
void
|
||||
stats_display_mem(struct stats_mem *mem, char *name)
|
||||
{
|
||||
LWIP_PLATFORM_DIAG(("\n MEM %s\n\t", name));
|
||||
LWIP_PLATFORM_DIAG(("avail: %"MEM_SIZE_F"\n\t", mem->avail));
|
||||
LWIP_PLATFORM_DIAG(("used: %"MEM_SIZE_F"\n\t", mem->used));
|
||||
LWIP_PLATFORM_DIAG(("max: %"MEM_SIZE_F"\n\t", mem->max));
|
||||
LWIP_PLATFORM_DIAG(("err: %"MEM_SIZE_F"\n", mem->err));
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
stats_display(void)
|
||||
{
|
||||
s16_t i;
|
||||
char * memp_names[] = {"PBUF", "RAW_PCB", "UDP_PCB", "TCP_PCB", "TCP_PCB_LISTEN",
|
||||
"TCP_SEG", "NETBUF", "NETCONN", "API_MSG", "TCP_MSG", "TIMEOUT"};
|
||||
stats_display_proto(&lwip_stats.link, "LINK");
|
||||
stats_display_proto(&lwip_stats.ip_frag, "IP_FRAG");
|
||||
stats_display_proto(&lwip_stats.ip, "IP");
|
||||
stats_display_proto(&lwip_stats.icmp, "ICMP");
|
||||
stats_display_proto(&lwip_stats.udp, "UDP");
|
||||
stats_display_proto(&lwip_stats.tcp, "TCP");
|
||||
stats_display_pbuf(&lwip_stats.pbuf);
|
||||
stats_display_mem(&lwip_stats.mem, "HEAP");
|
||||
for (i = 0; i < MEMP_MAX; i++) {
|
||||
stats_display_mem(&lwip_stats.memp[i], memp_names[i]);
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* LWIP_STATS_DISPLAY */
|
||||
#endif /* LWIP_STATS */
|
||||
|
294
Demo/Common/ethernet/lwIP/core/sys.c
Normal file
294
Demo/Common/ethernet/lwIP/core/sys.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#if (NO_SYS == 0)
|
||||
|
||||
struct sswt_cb
|
||||
{
|
||||
s16_t timeflag;
|
||||
sys_sem_t *psem;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void
|
||||
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
|
||||
{
|
||||
u32_t time;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
|
||||
|
||||
again:
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
sys_arch_mbox_fetch(mbox, msg, 0);
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
|
||||
} else {
|
||||
time = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = timeouts->next;
|
||||
timeouts->next = tmptimeout->next;
|
||||
h = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time <= timeouts->next->time) {
|
||||
timeouts->next->time -= time;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_wait(sys_sem_t sem)
|
||||
{
|
||||
u32_t time;
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *tmptimeout;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
|
||||
/* while (sys_arch_sem_wait(sem, 1000) == 0);
|
||||
return;*/
|
||||
|
||||
again:
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (!timeouts || !timeouts->next) {
|
||||
sys_arch_sem_wait(sem, 0);
|
||||
} else {
|
||||
if (timeouts->next->time > 0) {
|
||||
time = sys_arch_sem_wait(sem, timeouts->next->time);
|
||||
} else {
|
||||
time = SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
if (time == SYS_ARCH_TIMEOUT) {
|
||||
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
|
||||
could be fetched. We should now call the timeout handler and
|
||||
deallocate the memory allocated for the timeout. */
|
||||
tmptimeout = timeouts->next;
|
||||
timeouts->next = tmptimeout->next;
|
||||
h = tmptimeout->h;
|
||||
arg = tmptimeout->arg;
|
||||
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
|
||||
if (h != NULL) {
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void *)h, (void *)arg));
|
||||
h(arg);
|
||||
}
|
||||
|
||||
|
||||
/* We try again to fetch a message from the mbox. */
|
||||
goto again;
|
||||
} else {
|
||||
/* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
|
||||
occured. The time variable is set to the number of
|
||||
milliseconds we waited for the message. */
|
||||
if (time <= timeouts->next->time) {
|
||||
timeouts->next->time -= time;
|
||||
} else {
|
||||
timeouts->next->time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *timeout, *t;
|
||||
|
||||
timeout = memp_malloc(MEMP_SYS_TIMEOUT);
|
||||
if (timeout == NULL) {
|
||||
return;
|
||||
}
|
||||
timeout->next = NULL;
|
||||
timeout->h = h;
|
||||
timeout->arg = arg;
|
||||
timeout->time = msecs;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
|
||||
(void *)timeout, msecs, (void *)h, (void *)arg));
|
||||
|
||||
LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL);
|
||||
|
||||
if (timeouts->next == NULL) {
|
||||
timeouts->next = timeout;
|
||||
return;
|
||||
}
|
||||
|
||||
if (timeouts->next->time > msecs) {
|
||||
timeouts->next->time -= msecs;
|
||||
timeout->next = timeouts->next;
|
||||
timeouts->next = timeout;
|
||||
} else {
|
||||
for(t = timeouts->next; t != NULL; t = t->next) {
|
||||
timeout->time -= t->time;
|
||||
if (t->next == NULL || t->next->time > timeout->time) {
|
||||
if (t->next != NULL) {
|
||||
t->next->time -= timeout->time;
|
||||
}
|
||||
timeout->next = t->next;
|
||||
t->next = timeout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Go through timeout list (for this task only) and remove the first matching entry,
|
||||
even though the timeout has not triggered yet.
|
||||
*/
|
||||
|
||||
void
|
||||
sys_untimeout(sys_timeout_handler h, void *arg)
|
||||
{
|
||||
struct sys_timeouts *timeouts;
|
||||
struct sys_timeo *prev_t, *t;
|
||||
|
||||
timeouts = sys_arch_timeouts();
|
||||
|
||||
if (timeouts->next == NULL)
|
||||
return;
|
||||
|
||||
for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next)
|
||||
{
|
||||
if ((t->h == h) && (t->arg == arg))
|
||||
{
|
||||
/* We have a match */
|
||||
/* Unlink from previous in list */
|
||||
if (prev_t == NULL)
|
||||
timeouts->next = t->next;
|
||||
else
|
||||
prev_t->next = t->next;
|
||||
/* If not the last one, add time of this one back to next */
|
||||
if (t->next != NULL)
|
||||
t->next->time += t->time;
|
||||
memp_free(MEMP_SYS_TIMEOUT, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
sswt_handler(void *arg)
|
||||
{
|
||||
struct sswt_cb *sswt_cb = (struct sswt_cb *) arg;
|
||||
|
||||
/* Timeout. Set flag to TRUE and signal semaphore */
|
||||
sswt_cb->timeflag = 1;
|
||||
sys_sem_signal(*(sswt_cb->psem));
|
||||
}
|
||||
|
||||
/* Wait for a semaphore with timeout (specified in ms) */
|
||||
/* timeout = 0: wait forever */
|
||||
/* Returns 0 on timeout. 1 otherwise */
|
||||
|
||||
int
|
||||
sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
|
||||
{
|
||||
struct sswt_cb sswt_cb;
|
||||
|
||||
sswt_cb.psem = &sem;
|
||||
sswt_cb.timeflag = 0;
|
||||
|
||||
/* If timeout is zero, then just wait forever */
|
||||
if (timeout > 0)
|
||||
/* Create a timer and pass it the address of our flag */
|
||||
sys_timeout(timeout, sswt_handler, &sswt_cb);
|
||||
sys_sem_wait(sem);
|
||||
/* Was it a timeout? */
|
||||
if (sswt_cb.timeflag)
|
||||
{
|
||||
/* timeout */
|
||||
return 0;
|
||||
} else {
|
||||
/* Not a timeout. Remove timeout entry */
|
||||
sys_untimeout(sswt_handler, &sswt_cb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sys_msleep(u32_t ms)
|
||||
{
|
||||
sys_sem_t delaysem = sys_sem_new(0);
|
||||
|
||||
sys_sem_wait_timeout(delaysem, ms);
|
||||
|
||||
sys_sem_free(delaysem);
|
||||
}
|
||||
|
||||
|
||||
#endif /* NO_SYS */
|
1182
Demo/Common/ethernet/lwIP/core/tcp.c
Normal file
1182
Demo/Common/ethernet/lwIP/core/tcp.c
Normal file
File diff suppressed because it is too large
Load diff
1209
Demo/Common/ethernet/lwIP/core/tcp_in.c
Normal file
1209
Demo/Common/ethernet/lwIP/core/tcp_in.c
Normal file
File diff suppressed because it is too large
Load diff
727
Demo/Common/ethernet/lwIP/core/tcp_out.c
Normal file
727
Demo/Common/ethernet/lwIP/core/tcp_out.c
Normal file
|
@ -0,0 +1,727 @@
|
|||
/**
|
||||
* @file
|
||||
*
|
||||
* Transmission Control Protocol, outgoing traffic
|
||||
*
|
||||
* The output functions of TCP.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if LWIP_TCP
|
||||
|
||||
/* Forward declarations.*/
|
||||
static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
|
||||
|
||||
err_t
|
||||
tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags)
|
||||
{
|
||||
/* no data, no length, flags, copy=1, no optdata, no optdatalen */
|
||||
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write data for sending (but does not send it immediately).
|
||||
*
|
||||
* It waits in the expectation of more data being sent soon (as
|
||||
* it can send them more efficiently by combining them together).
|
||||
* To prompt the system to send data now, call tcp_output() after
|
||||
* calling tcp_write().
|
||||
*
|
||||
* @arg pcb Protocol control block of the TCP connection to enqueue data for.
|
||||
*
|
||||
* @see tcp_write()
|
||||
*/
|
||||
|
||||
err_t
|
||||
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
|
||||
{
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_write(pcb=%p, arg=%p, len=%"U16_F", copy=%"U16_F")\n", (void *)pcb,
|
||||
arg, len, (u16_t)copy));
|
||||
/* connection is in valid state for data transmission? */
|
||||
if (pcb->state == ESTABLISHED ||
|
||||
pcb->state == CLOSE_WAIT ||
|
||||
pcb->state == SYN_SENT ||
|
||||
pcb->state == SYN_RCVD) {
|
||||
if (len > 0) {
|
||||
return tcp_enqueue(pcb, (void *)arg, len, 0, copy, NULL, 0);
|
||||
}
|
||||
return ERR_OK;
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_STATE | 3, ("tcp_write() called in invalid state\n"));
|
||||
return ERR_CONN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue either data or TCP options (but not both) for tranmission
|
||||
*
|
||||
*
|
||||
*
|
||||
* @arg pcb Protocol control block for the TCP connection to enqueue data for.
|
||||
* @arg arg Pointer to the data to be enqueued for sending.
|
||||
* @arg len Data length in bytes
|
||||
* @arg flags
|
||||
* @arg copy 1 if data must be copied, 0 if data is non-volatile and can be
|
||||
* referenced.
|
||||
* @arg optdata
|
||||
* @arg optlen
|
||||
*/
|
||||
err_t
|
||||
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
|
||||
u8_t flags, u8_t copy,
|
||||
u8_t *optdata, u8_t optlen)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_seg *seg, *useg, *queue;
|
||||
u32_t left, seqno;
|
||||
u16_t seglen;
|
||||
void *ptr;
|
||||
u8_t queuelen;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_enqueue(pcb=%p, arg=%p, len=%"U16_F", flags=%"X16_F", copy=%"U16_F")\n",
|
||||
(void *)pcb, arg, len, (u16_t)flags, (u16_t)copy));
|
||||
LWIP_ASSERT("tcp_enqueue: len == 0 || optlen == 0 (programmer violates API)",
|
||||
len == 0 || optlen == 0);
|
||||
LWIP_ASSERT("tcp_enqueue: arg == NULL || optdata == NULL (programmer violates API)",
|
||||
arg == NULL || optdata == NULL);
|
||||
/* fail on too much data */
|
||||
if (len > pcb->snd_buf) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too much data (len=%"U16_F" > snd_buf=%"U16_F")\n", len, pcb->snd_buf));
|
||||
return ERR_MEM;
|
||||
}
|
||||
left = len;
|
||||
ptr = arg;
|
||||
|
||||
/* seqno will be the sequence number of the first segment enqueued
|
||||
* by the call to this function. */
|
||||
seqno = pcb->snd_lbb;
|
||||
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: queuelen: %"U16_F"\n", (u16_t)pcb->snd_queuelen));
|
||||
|
||||
/* If total number of pbufs on the unsent/unacked queues exceeds the
|
||||
* configured maximum, return an error */
|
||||
queuelen = pcb->snd_queuelen;
|
||||
if (queuelen >= TCP_SND_QUEUELEN) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 3, ("tcp_enqueue: too long queue %"U16_F" (max %"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
return ERR_MEM;
|
||||
}
|
||||
if (queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: pbufs on queue => at least one queue non-empty",
|
||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||
} else {
|
||||
LWIP_ASSERT("tcp_enqueue: no pbufs on queue => both queues empty",
|
||||
pcb->unacked == NULL && pcb->unsent == NULL);
|
||||
}
|
||||
|
||||
/* First, break up the data into segments and tuck them together in
|
||||
* the local "queue" variable. */
|
||||
useg = queue = seg = NULL;
|
||||
seglen = 0;
|
||||
while (queue == NULL || left > 0) {
|
||||
|
||||
/* The segment length should be the MSS if the data to be enqueued
|
||||
* is larger than the MSS. */
|
||||
seglen = left > pcb->mss? pcb->mss: left;
|
||||
|
||||
/* Allocate memory for tcp_seg, and fill in fields. */
|
||||
seg = memp_malloc(MEMP_TCP_SEG);
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for tcp_seg\n"));
|
||||
goto memerr;
|
||||
}
|
||||
seg->next = NULL;
|
||||
seg->p = NULL;
|
||||
|
||||
/* first segment of to-be-queued data? */
|
||||
if (queue == NULL) {
|
||||
queue = seg;
|
||||
}
|
||||
/* subsequent segments of to-be-queued data */
|
||||
else {
|
||||
/* Attach the segment to the end of the queued segments */
|
||||
LWIP_ASSERT("useg != NULL", useg != NULL);
|
||||
useg->next = seg;
|
||||
}
|
||||
/* remember last segment of to-be-queued data for next iteration */
|
||||
useg = seg;
|
||||
|
||||
/* If copy is set, memory should be allocated
|
||||
* and data copied into pbuf, otherwise data comes from
|
||||
* ROM or other static memory, and need not be copied. If
|
||||
* optdata is != NULL, we have options instead of data. */
|
||||
|
||||
/* options? */
|
||||
if (optdata != NULL) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, optlen, PBUF_RAM)) == NULL) {
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* copy from volatile memory? */
|
||||
else if (copy) {
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_RAM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue : could not allocate memory for pbuf copy size %"U16_F"\n", seglen));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
if (arg != NULL) {
|
||||
memcpy(seg->p->payload, ptr, seglen);
|
||||
}
|
||||
seg->dataptr = seg->p->payload;
|
||||
}
|
||||
/* do not copy data */
|
||||
else {
|
||||
/* First, allocate a pbuf for holding the data.
|
||||
* since the referenced data is available at least until it is sent out on the
|
||||
* link (as it has to be ACKed by the remote party) we can safely use PBUF_ROM
|
||||
* instead of PBUF_REF here.
|
||||
*/
|
||||
if ((p = pbuf_alloc(PBUF_TRANSPORT, seglen, PBUF_ROM)) == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for zero-copy pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
/* reference the non-volatile payload data */
|
||||
p->payload = ptr;
|
||||
seg->dataptr = ptr;
|
||||
|
||||
/* Second, allocate a pbuf for the headers. */
|
||||
if ((seg->p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_RAM)) == NULL) {
|
||||
/* If allocation fails, we have to deallocate the data pbuf as
|
||||
* well. */
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: could not allocate memory for header pbuf\n"));
|
||||
goto memerr;
|
||||
}
|
||||
++queuelen;
|
||||
|
||||
/* Concatenate the headers and data pbufs together. */
|
||||
pbuf_cat(seg->p/*header*/, p/*data*/);
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
/* Now that there are more segments queued, we check again if the
|
||||
length of the queue exceeds the configured maximum. */
|
||||
if (queuelen > TCP_SND_QUEUELEN) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));
|
||||
goto memerr;
|
||||
}
|
||||
|
||||
seg->len = seglen;
|
||||
|
||||
/* build TCP header */
|
||||
if (pbuf_header(seg->p, TCP_HLEN)) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
|
||||
TCP_STATS_INC(tcp.err);
|
||||
goto memerr;
|
||||
}
|
||||
seg->tcphdr = seg->p->payload;
|
||||
seg->tcphdr->src = htons(pcb->local_port);
|
||||
seg->tcphdr->dest = htons(pcb->remote_port);
|
||||
seg->tcphdr->seqno = htonl(seqno);
|
||||
seg->tcphdr->urgp = 0;
|
||||
TCPH_FLAGS_SET(seg->tcphdr, flags);
|
||||
/* don't fill in tcphdr->ackno and tcphdr->wnd until later */
|
||||
|
||||
/* Copy the options into the header, if they are present. */
|
||||
if (optdata == NULL) {
|
||||
TCPH_HDRLEN_SET(seg->tcphdr, 5);
|
||||
}
|
||||
else {
|
||||
TCPH_HDRLEN_SET(seg->tcphdr, (5 + optlen / 4));
|
||||
/* Copy options into data portion of segment.
|
||||
Options can thus only be sent in non data carrying
|
||||
segments such as SYN|ACK. */
|
||||
memcpy(seg->dataptr, optdata, optlen);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE, ("tcp_enqueue: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
|
||||
ntohl(seg->tcphdr->seqno),
|
||||
ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
|
||||
(u16_t)flags));
|
||||
|
||||
left -= seglen;
|
||||
seqno += seglen;
|
||||
ptr = (void *)((u8_t *)ptr + seglen);
|
||||
}
|
||||
|
||||
/* Now that the data to be enqueued has been broken up into TCP
|
||||
segments in the queue variable, we add them to the end of the
|
||||
pcb->unsent queue. */
|
||||
if (pcb->unsent == NULL) {
|
||||
useg = NULL;
|
||||
}
|
||||
else {
|
||||
for (useg = pcb->unsent; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
/* { useg is last segment on the unsent queue, NULL if list is empty } */
|
||||
|
||||
/* If there is room in the last pbuf on the unsent queue,
|
||||
chain the first pbuf on the queue together with that. */
|
||||
if (useg != NULL &&
|
||||
TCP_TCPLEN(useg) != 0 &&
|
||||
!(TCPH_FLAGS(useg->tcphdr) & (TCP_SYN | TCP_FIN)) &&
|
||||
!(flags & (TCP_SYN | TCP_FIN)) &&
|
||||
/* fit within max seg size */
|
||||
useg->len + queue->len <= pcb->mss) {
|
||||
/* Remove TCP header from first segment of our to-be-queued list */
|
||||
pbuf_header(queue->p, -TCP_HLEN);
|
||||
pbuf_cat(useg->p, queue->p);
|
||||
useg->len += queue->len;
|
||||
useg->next = queue->next;
|
||||
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | DBG_TRACE | DBG_STATE, ("tcp_enqueue: chaining segments, new len %"U16_F"\n", useg->len));
|
||||
if (seg == queue) {
|
||||
seg = NULL;
|
||||
}
|
||||
memp_free(MEMP_TCP_SEG, queue);
|
||||
}
|
||||
else {
|
||||
/* empty list */
|
||||
if (useg == NULL) {
|
||||
/* initialize list with this segment */
|
||||
pcb->unsent = queue;
|
||||
}
|
||||
/* enqueue segment */
|
||||
else {
|
||||
useg->next = queue;
|
||||
}
|
||||
}
|
||||
if ((flags & TCP_SYN) || (flags & TCP_FIN)) {
|
||||
++len;
|
||||
}
|
||||
pcb->snd_lbb += len;
|
||||
|
||||
pcb->snd_buf -= len;
|
||||
|
||||
/* update number of segments on the queues */
|
||||
pcb->snd_queuelen = queuelen;
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG, ("tcp_enqueue: %"S16_F" (after enqueued)\n", pcb->snd_queuelen));
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: valid queue length",
|
||||
pcb->unacked != NULL || pcb->unsent != NULL);
|
||||
}
|
||||
|
||||
/* Set the PSH flag in the last segment that we enqueued, but only
|
||||
if the segment has data (indicated by seglen > 0). */
|
||||
if (seg != NULL && seglen > 0 && seg->tcphdr != NULL) {
|
||||
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
memerr:
|
||||
TCP_STATS_INC(tcp.memerr);
|
||||
|
||||
if (queue != NULL) {
|
||||
tcp_segs_free(queue);
|
||||
}
|
||||
if (pcb->snd_queuelen != 0) {
|
||||
LWIP_ASSERT("tcp_enqueue: valid queue length", pcb->unacked != NULL ||
|
||||
pcb->unsent != NULL);
|
||||
}
|
||||
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %"S16_F" (with mem err)\n", pcb->snd_queuelen));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
/* find out what we can send and send it */
|
||||
err_t
|
||||
tcp_output(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
struct tcp_seg *seg, *useg;
|
||||
u32_t wnd;
|
||||
#if TCP_CWND_DEBUG
|
||||
s16_t i = 0;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
/* First, check if we are invoked by the TCP input processing
|
||||
code. If so, we do not output anything. Instead, we rely on the
|
||||
input processing code to call us when input processing is done
|
||||
with. */
|
||||
if (tcp_input_pcb == pcb) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
wnd = LWIP_MIN(pcb->snd_wnd, pcb->cwnd);
|
||||
|
||||
seg = pcb->unsent;
|
||||
|
||||
/* useg should point to last segment on unacked queue */
|
||||
useg = pcb->unacked;
|
||||
if (useg != NULL) {
|
||||
for (; useg->next != NULL; useg = useg->next);
|
||||
}
|
||||
|
||||
/* If the TF_ACK_NOW flag is set and no data will be sent (either
|
||||
* because the ->unsent queue is empty or because the window does
|
||||
* not allow it), construct an empty ACK segment and send it.
|
||||
*
|
||||
* If data is to be sent, we will just piggyback the ACK (see below).
|
||||
*/
|
||||
if (pcb->flags & TF_ACK_NOW &&
|
||||
(seg == NULL ||
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: (ACK) could not allocate pbuf\n"));
|
||||
return ERR_BUF;
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: sending ACK for %"U32_F"\n", pcb->rcv_nxt));
|
||||
/* remove ACK flags from the PCB, as we send an empty ACK now */
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = htonl(pcb->snd_nxt);
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
|
||||
tcphdr->wnd = htons(pcb->rcv_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
pbuf_free(p);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#if TCP_OUTPUT_DEBUG
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output: nothing to send (%p)\n", (void*)pcb->unsent));
|
||||
}
|
||||
#endif /* TCP_OUTPUT_DEBUG */
|
||||
#if TCP_CWND_DEBUG
|
||||
if (seg == NULL) {
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", seg == NULL, ack %"U32_F"\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
pcb->lastack));
|
||||
} else {
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack));
|
||||
}
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
/* data available and window allows it to be sent? */
|
||||
while (seg != NULL &&
|
||||
ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
|
||||
#if TCP_CWND_DEBUG
|
||||
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"U32_F", cwnd %"U16_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
|
||||
pcb->snd_wnd, pcb->cwnd, wnd,
|
||||
ntohl(seg->tcphdr->seqno) + seg->len -
|
||||
pcb->lastack,
|
||||
ntohl(seg->tcphdr->seqno), pcb->lastack, i));
|
||||
++i;
|
||||
#endif /* TCP_CWND_DEBUG */
|
||||
|
||||
pcb->unsent = seg->next;
|
||||
|
||||
if (pcb->state != SYN_SENT) {
|
||||
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
|
||||
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
|
||||
}
|
||||
|
||||
tcp_output_segment(seg, pcb);
|
||||
pcb->snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
|
||||
if (TCP_SEQ_LT(pcb->snd_max, pcb->snd_nxt)) {
|
||||
pcb->snd_max = pcb->snd_nxt;
|
||||
}
|
||||
/* put segment on unacknowledged list if length > 0 */
|
||||
if (TCP_TCPLEN(seg) > 0) {
|
||||
seg->next = NULL;
|
||||
/* unacked list is empty? */
|
||||
if (pcb->unacked == NULL) {
|
||||
pcb->unacked = seg;
|
||||
useg = seg;
|
||||
/* unacked list is not empty? */
|
||||
} else {
|
||||
/* In the case of fast retransmit, the packet should not go to the tail
|
||||
* of the unacked queue, but rather at the head. We need to check for
|
||||
* this case. -STJ Jul 27, 2004 */
|
||||
if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))){
|
||||
/* add segment to head of unacked list */
|
||||
seg->next = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
} else {
|
||||
/* add segment to tail of unacked list */
|
||||
useg->next = seg;
|
||||
useg = useg->next;
|
||||
}
|
||||
}
|
||||
/* do not queue empty segments on the unacked list */
|
||||
} else {
|
||||
tcp_seg_free(seg);
|
||||
}
|
||||
seg = pcb->unsent;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually send a TCP segment over IP
|
||||
*/
|
||||
static void
|
||||
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
|
||||
{
|
||||
u16_t len;
|
||||
struct netif *netif;
|
||||
|
||||
/** @bug Exclude retransmitted segments from this count. */
|
||||
snmp_inc_tcpoutsegs();
|
||||
|
||||
/* The TCP header has already been constructed, but the ackno and
|
||||
wnd fields remain. */
|
||||
seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
|
||||
/* silly window avoidance */
|
||||
if (pcb->rcv_wnd < pcb->mss) {
|
||||
seg->tcphdr->wnd = 0;
|
||||
} else {
|
||||
/* advertise our receive window size in this TCP segment */
|
||||
seg->tcphdr->wnd = htons(pcb->rcv_wnd);
|
||||
}
|
||||
|
||||
/* If we don't have a local IP address, we get one by
|
||||
calling ip_route(). */
|
||||
if (ip_addr_isany(&(pcb->local_ip))) {
|
||||
netif = ip_route(&(pcb->remote_ip));
|
||||
if (netif == NULL) {
|
||||
return;
|
||||
}
|
||||
ip_addr_set(&(pcb->local_ip), &(netif->ip_addr));
|
||||
}
|
||||
|
||||
pcb->rtime = 0;
|
||||
|
||||
if (pcb->rttest == 0) {
|
||||
pcb->rttest = tcp_ticks;
|
||||
pcb->rtseq = ntohl(seg->tcphdr->seqno);
|
||||
|
||||
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
|
||||
}
|
||||
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
|
||||
htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
|
||||
seg->len));
|
||||
|
||||
len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
|
||||
|
||||
seg->p->len -= len;
|
||||
seg->p->tot_len -= len;
|
||||
|
||||
seg->p->payload = seg->tcphdr;
|
||||
|
||||
seg->tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
seg->tcphdr->chksum = inet_chksum_pseudo(seg->p,
|
||||
&(pcb->local_ip),
|
||||
&(pcb->remote_ip),
|
||||
IP_PROTO_TCP, seg->p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
|
||||
IP_PROTO_TCP);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rst(u32_t seqno, u32_t ackno,
|
||||
struct ip_addr *local_ip, struct ip_addr *remote_ip,
|
||||
u16_t local_port, u16_t remote_port)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(local_port);
|
||||
tcphdr->dest = htons(remote_port);
|
||||
tcphdr->seqno = htonl(seqno);
|
||||
tcphdr->ackno = htonl(ackno);
|
||||
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
|
||||
tcphdr->wnd = htons(TCP_WND);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
|
||||
IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
snmp_inc_tcpoutrsts();
|
||||
/* Send output with hardcoded TTL since we have no access to the pcb */
|
||||
ip_output(p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
|
||||
pbuf_free(p);
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
|
||||
}
|
||||
|
||||
/* requeue all unacked segments for retransmission */
|
||||
void
|
||||
tcp_rexmit_rto(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
|
||||
if (pcb->unacked == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move all unacked segments to the head of the unsent queue */
|
||||
for (seg = pcb->unacked; seg->next != NULL; seg = seg->next);
|
||||
/* concatenate unsent queue after unacked queue */
|
||||
seg->next = pcb->unsent;
|
||||
/* unsent queue is the concatenated queue (of unacked, unsent) */
|
||||
pcb->unsent = pcb->unacked;
|
||||
/* unacked queue is now empty */
|
||||
pcb->unacked = NULL;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
/* increment number of retransmissions */
|
||||
++pcb->nrtx;
|
||||
|
||||
/* Don't take any RTT measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
|
||||
/* Do the actual retransmission */
|
||||
tcp_output(pcb);
|
||||
}
|
||||
|
||||
void
|
||||
tcp_rexmit(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct tcp_seg *seg;
|
||||
|
||||
if (pcb->unacked == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Move the first unacked segment to the unsent queue */
|
||||
seg = pcb->unacked->next;
|
||||
pcb->unacked->next = pcb->unsent;
|
||||
pcb->unsent = pcb->unacked;
|
||||
pcb->unacked = seg;
|
||||
|
||||
pcb->snd_nxt = ntohl(pcb->unsent->tcphdr->seqno);
|
||||
|
||||
++pcb->nrtx;
|
||||
|
||||
/* Don't take any rtt measurements after retransmitting. */
|
||||
pcb->rttest = 0;
|
||||
|
||||
/* Do the actual retransmission. */
|
||||
snmp_inc_tcpretranssegs();
|
||||
tcp_output(pcb);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tcp_keepalive(struct tcp_pcb *pcb)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct tcp_hdr *tcphdr;
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
|
||||
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt %"U16_F"\n", tcp_ticks, pcb->tmr, pcb->keep_cnt));
|
||||
|
||||
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
|
||||
|
||||
if(p == NULL) {
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: could not allocate memory for pbuf\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
tcphdr = p->payload;
|
||||
tcphdr->src = htons(pcb->local_port);
|
||||
tcphdr->dest = htons(pcb->remote_port);
|
||||
tcphdr->seqno = htonl(pcb->snd_nxt - 1);
|
||||
tcphdr->ackno = htonl(pcb->rcv_nxt);
|
||||
tcphdr->wnd = htons(pcb->rcv_wnd);
|
||||
tcphdr->urgp = 0;
|
||||
TCPH_HDRLEN_SET(tcphdr, 5);
|
||||
|
||||
tcphdr->chksum = 0;
|
||||
#if CHECKSUM_GEN_TCP
|
||||
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
|
||||
#endif
|
||||
TCP_STATS_INC(tcp.xmit);
|
||||
|
||||
/* Send output to IP */
|
||||
ip_output(p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
|
||||
|
||||
pbuf_free(p);
|
||||
|
||||
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F".\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
|
||||
}
|
||||
|
||||
#endif /* LWIP_TCP */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
665
Demo/Common/ethernet/lwIP/core/udp.c
Normal file
665
Demo/Common/ethernet/lwIP/core/udp.c
Normal file
|
@ -0,0 +1,665 @@
|
|||
/**
|
||||
* @file
|
||||
* User Datagram Protocol module
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* udp.c
|
||||
*
|
||||
* The code for the User Datagram Protocol UDP.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/memp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/icmp.h"
|
||||
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "arch/perf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
/* The list of UDP PCBs */
|
||||
#if LWIP_UDP
|
||||
/* exported in udp.h (was static) */
|
||||
struct udp_pcb *udp_pcbs = NULL;
|
||||
|
||||
static struct udp_pcb *pcb_cache = NULL;
|
||||
|
||||
void
|
||||
udp_init(void)
|
||||
{
|
||||
udp_pcbs = pcb_cache = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an incoming UDP datagram.
|
||||
*
|
||||
* Given an incoming UDP datagram (as a chain of pbufs) this function
|
||||
* finds a corresponding UDP PCB and
|
||||
*
|
||||
* @param pbuf pbuf to be demultiplexed to a UDP PCB.
|
||||
* @param netif network interface on which the datagram was received.
|
||||
*
|
||||
*/
|
||||
void
|
||||
udp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct udp_hdr *udphdr;
|
||||
struct udp_pcb *pcb;
|
||||
struct udp_pcb *uncon_pcb;
|
||||
struct ip_hdr *iphdr;
|
||||
u16_t src, dest;
|
||||
u8_t local_match;
|
||||
|
||||
PERF_START;
|
||||
|
||||
UDP_STATS_INC(udp.recv);
|
||||
|
||||
iphdr = p->payload;
|
||||
|
||||
if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN)) {
|
||||
/* drop short packets */
|
||||
// LWIP_DEBUGF(UDP_DEBUG,
|
||||
// ("udp_input: short UDP datagram (%"U16_F" bytes) discarded\n", p->tot_len));
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
|
||||
|
||||
UDP_STATS_INC(udp.lenerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
|
||||
pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4)));
|
||||
|
||||
udphdr = (struct udp_hdr *)p->payload;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
|
||||
|
||||
src = ntohs(udphdr->src);
|
||||
dest = ntohs(udphdr->dest);
|
||||
|
||||
udp_debug_print(udphdr);
|
||||
|
||||
/* print the UDP source and destination */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") <-- "
|
||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||
ip4_addr1(&iphdr->dest), ip4_addr2(&iphdr->dest),
|
||||
ip4_addr3(&iphdr->dest), ip4_addr4(&iphdr->dest), ntohs(udphdr->dest),
|
||||
ip4_addr1(&iphdr->src), ip4_addr2(&iphdr->src),
|
||||
ip4_addr3(&iphdr->src), ip4_addr4(&iphdr->src), ntohs(udphdr->src)));
|
||||
|
||||
local_match = 0;
|
||||
uncon_pcb = NULL;
|
||||
/* Iterate through the UDP pcb list for a matching pcb */
|
||||
for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
/* print the PCB local and remote address */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("pcb (%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F") --- "
|
||||
"(%"U16_F".%"U16_F".%"U16_F".%"U16_F", %"U16_F")\n",
|
||||
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
|
||||
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
|
||||
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
|
||||
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip), pcb->remote_port));
|
||||
|
||||
/* compare PCB local addr+port to UDP destination addr+port */
|
||||
if ((pcb->local_port == dest) &&
|
||||
(ip_addr_isany(&pcb->local_ip) ||
|
||||
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)) ||
|
||||
ip_addr_isbroadcast(&(iphdr->dest), inp))) {
|
||||
local_match = 1;
|
||||
if ((uncon_pcb == NULL) &&
|
||||
((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
|
||||
/* the first unconnected matching PCB */
|
||||
uncon_pcb = pcb;
|
||||
}
|
||||
}
|
||||
/* compare PCB remote addr+port to UDP source addr+port */
|
||||
if ((local_match != 0) &&
|
||||
(pcb->remote_port == src) &&
|
||||
(ip_addr_isany(&pcb->remote_ip) ||
|
||||
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)))) {
|
||||
/* the first fully matching PCB */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* no fully matching pcb found? then look for an unconnected pcb */
|
||||
if (pcb == NULL) {
|
||||
pcb = uncon_pcb;
|
||||
}
|
||||
|
||||
/* Check checksum if this is a match or if it was directed at us. */
|
||||
if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &iphdr->dest)) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: calculating checksum\n"));
|
||||
#ifdef IPv6
|
||||
if (iphdr->nexthdr == IP_PROTO_UDPLITE) {
|
||||
#else
|
||||
if (IPH_PROTO(iphdr) == IP_PROTO_UDPLITE) {
|
||||
#endif /* IPv4 */
|
||||
/* Do the UDP Lite checksum */
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDPLITE, ntohs(udphdr->len)) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 2,
|
||||
("udp_input: UDP Lite datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if CHECKSUM_CHECK_UDP
|
||||
if (udphdr->chksum != 0) {
|
||||
if (inet_chksum_pseudo(p, (struct ip_addr *)&(iphdr->src),
|
||||
(struct ip_addr *)&(iphdr->dest),
|
||||
IP_PROTO_UDP, p->tot_len) != 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 2,
|
||||
("udp_input: UDP datagram discarded due to failing checksum\n"));
|
||||
UDP_STATS_INC(udp.chkerr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpinerrors();
|
||||
pbuf_free(p);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
pbuf_header(p, -UDP_HLEN);
|
||||
if (pcb != NULL) {
|
||||
snmp_inc_udpindatagrams();
|
||||
/* callback */
|
||||
if (pcb->recv != NULL)
|
||||
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
|
||||
} else {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
|
||||
|
||||
/* No match was found, send ICMP destination port unreachable unless
|
||||
destination address was broadcast/multicast. */
|
||||
|
||||
if (!ip_addr_isbroadcast(&iphdr->dest, inp) &&
|
||||
!ip_addr_ismulticast(&iphdr->dest)) {
|
||||
|
||||
/* restore pbuf pointer */
|
||||
p->payload = iphdr;
|
||||
icmp_dest_unreach(p, ICMP_DUR_PORT);
|
||||
}
|
||||
UDP_STATS_INC(udp.proterr);
|
||||
UDP_STATS_INC(udp.drop);
|
||||
snmp_inc_udpnoports();
|
||||
pbuf_free(p);
|
||||
}
|
||||
} else {
|
||||
pbuf_free(p);
|
||||
}
|
||||
end:
|
||||
PERF_STOP("udp_input");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to a specified address using UDP.
|
||||
*
|
||||
* @param pcb UDP PCB used to send the data.
|
||||
* @param pbuf chain of pbuf's to be sent.
|
||||
* @param dst_ip Destination IP address.
|
||||
* @param dst_port Destination UDP port.
|
||||
*
|
||||
* If the PCB already has a remote address association, it will
|
||||
* be restored after the data is sent.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_MEM. Out of memory.
|
||||
* - ERR_RTE. Could not find route to destination address.
|
||||
*
|
||||
* @see udp_disconnect() udp_send()
|
||||
*/
|
||||
err_t
|
||||
udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *dst_ip, u16_t dst_port)
|
||||
{
|
||||
err_t err;
|
||||
/* temporary space for current PCB remote address */
|
||||
struct ip_addr pcb_remote_ip;
|
||||
u16_t pcb_remote_port;
|
||||
/* remember current remote peer address of PCB */
|
||||
pcb_remote_ip.addr = pcb->remote_ip.addr;
|
||||
pcb_remote_port = pcb->remote_port;
|
||||
/* copy packet destination address to PCB remote peer address */
|
||||
pcb->remote_ip.addr = dst_ip->addr;
|
||||
pcb->remote_port = dst_port;
|
||||
/* send to the packet destination address */
|
||||
err = udp_send(pcb, p);
|
||||
/* restore PCB remote peer address */
|
||||
pcb->remote_ip.addr = pcb_remote_ip.addr;
|
||||
pcb->remote_port = pcb_remote_port;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data using UDP.
|
||||
*
|
||||
* @param pcb UDP PCB used to send the data.
|
||||
* @param pbuf chain of pbuf's to be sent.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_MEM. Out of memory.
|
||||
* - ERR_RTE. Could not find route to destination address.
|
||||
*
|
||||
* @see udp_disconnect() udp_sendto()
|
||||
*/
|
||||
err_t
|
||||
udp_send(struct udp_pcb *pcb, struct pbuf *p)
|
||||
{
|
||||
struct udp_hdr *udphdr;
|
||||
struct netif *netif;
|
||||
struct ip_addr *src_ip;
|
||||
err_t err;
|
||||
struct pbuf *q; /* q will be sent down the stack */
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_send\n"));
|
||||
|
||||
/* if the PCB is not yet bound to a port, bind it here */
|
||||
if (pcb->local_port == 0) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: not yet bound to a port, binding now\n"));
|
||||
err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
if (err != ERR_OK) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: forced port bind failed\n"));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/* find the outgoing network interface for this packet */
|
||||
netif = ip_route(&(pcb->remote_ip));
|
||||
/* no outgoing network interface could be found? */
|
||||
if (netif == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%"X32_F"\n", pcb->remote_ip.addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
|
||||
/* not enough space to add an UDP header to first pbuf in given p chain? */
|
||||
if (pbuf_header(p, UDP_HLEN)) {
|
||||
/* allocate header in a seperate new pbuf */
|
||||
q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM);
|
||||
/* new header pbuf could not be allocated? */
|
||||
if (q == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 2, ("udp_send: could not allocate header\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
/* chain header q in front of given pbuf p */
|
||||
pbuf_chain(q, p);
|
||||
/* first pbuf q points to header pbuf */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
|
||||
/* adding a header within p succeeded */
|
||||
} else {
|
||||
/* first pbuf q equals given pbuf */
|
||||
q = p;
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header in given pbuf %p\n", (void *)p));
|
||||
}
|
||||
/* q now represents the packet to be sent */
|
||||
udphdr = q->payload;
|
||||
udphdr->src = htons(pcb->local_port);
|
||||
udphdr->dest = htons(pcb->remote_port);
|
||||
/* in UDP, 0 checksum means 'no checksum' */
|
||||
udphdr->chksum = 0x0000;
|
||||
|
||||
/* PCB local address is IP_ANY_ADDR? */
|
||||
if (ip_addr_isany(&pcb->local_ip)) {
|
||||
/* use outgoing network interface IP address as source address */
|
||||
src_ip = &(netif->ip_addr);
|
||||
} else {
|
||||
/* use UDP PCB local IP address as source address */
|
||||
src_ip = &(pcb->local_ip);
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: sending datagram of length %"U16_F"\n", q->tot_len));
|
||||
|
||||
/* UDP Lite protocol? */
|
||||
if (pcb->flags & UDP_FLAGS_UDPLITE) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
|
||||
/* set UDP message length in UDP header */
|
||||
udphdr->len = htons(pcb->chksum_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
|
||||
IP_PROTO_UDP, pcb->chksum_len);
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000)
|
||||
udphdr->chksum = 0xffff;
|
||||
#else
|
||||
udphdr->chksum = 0x0000;
|
||||
#endif
|
||||
/* output to IP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDPLITE,)\n"));
|
||||
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
|
||||
} else { /* UDP */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
|
||||
udphdr->len = htons(q->tot_len);
|
||||
/* calculate checksum */
|
||||
#if CHECKSUM_GEN_UDP
|
||||
if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
|
||||
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &pcb->remote_ip, IP_PROTO_UDP, q->tot_len);
|
||||
/* chksum zero must become 0xffff, as zero means 'no checksum' */
|
||||
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
|
||||
}
|
||||
#else
|
||||
udphdr->chksum = 0x0000;
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP checksum 0x%04"X16_F"\n", udphdr->chksum));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: ip_output_if (,,,,IP_PROTO_UDP,)\n"));
|
||||
/* output to IP */
|
||||
err = ip_output_if(q, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
|
||||
}
|
||||
/* TODO: must this be increased even if error occured? */
|
||||
snmp_inc_udpoutdatagrams();
|
||||
|
||||
/* did we chain a seperate header pbuf earlier? */
|
||||
if (q != p) {
|
||||
/* free the header pbuf */
|
||||
pbuf_free(q);
|
||||
q = NULL;
|
||||
/* p is still referenced by the caller, and will live on */
|
||||
}
|
||||
|
||||
UDP_STATS_INC(udp.xmit);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind an UDP PCB.
|
||||
*
|
||||
* @param pcb UDP PCB to be bound with a local address ipaddr and port.
|
||||
* @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
|
||||
* bind to all local interfaces.
|
||||
* @param port local UDP port to bind with.
|
||||
*
|
||||
* @return lwIP error code.
|
||||
* - ERR_OK. Successful. No error occured.
|
||||
* - ERR_USE. The specified ipaddr and port are already bound to by
|
||||
* another UDP PCB.
|
||||
*
|
||||
* @see udp_disconnect()
|
||||
*/
|
||||
err_t
|
||||
udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
u8_t rebind;
|
||||
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, ("udp_bind(ipaddr = "));
|
||||
ip_addr_debug_print(UDP_DEBUG, ipaddr);
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | 3, (", port = %"U16_F")\n", port));
|
||||
|
||||
rebind = 0;
|
||||
/* Check for double bind and rebind of the same pcb */
|
||||
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||
/* is this UDP PCB already on active list? */
|
||||
if (pcb == ipcb) {
|
||||
/* pcb may occur at most once in active list */
|
||||
LWIP_ASSERT("rebind == 0", rebind == 0);
|
||||
/* pcb already in list, just rebind */
|
||||
rebind = 1;
|
||||
}
|
||||
|
||||
/* this code does not allow upper layer to share a UDP port for
|
||||
listening to broadcast or multicast traffic (See SO_REUSE_ADDR and
|
||||
SO_REUSE_PORT under *BSD). TODO: See where it fits instead, OR
|
||||
combine with implementation of UDP PCB flags. Leon Woestenberg. */
|
||||
#ifdef LWIP_UDP_TODO
|
||||
/* port matches that of PCB in list? */
|
||||
else
|
||||
if ((ipcb->local_port == port) &&
|
||||
/* IP address matches, or one is IP_ADDR_ANY? */
|
||||
(ip_addr_isany(&(ipcb->local_ip)) ||
|
||||
ip_addr_isany(ipaddr) ||
|
||||
ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
|
||||
/* other PCB already binds to this local IP and port */
|
||||
LWIP_DEBUGF(UDP_DEBUG,
|
||||
("udp_bind: local port %"U16_F" already bound by another pcb\n", port));
|
||||
return ERR_USE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->local_ip, ipaddr);
|
||||
|
||||
/* no port specified? */
|
||||
if (port == 0) {
|
||||
#ifndef UDP_LOCAL_PORT_RANGE_START
|
||||
#define UDP_LOCAL_PORT_RANGE_START 4096
|
||||
#define UDP_LOCAL_PORT_RANGE_END 0x7fff
|
||||
#endif
|
||||
port = UDP_LOCAL_PORT_RANGE_START;
|
||||
ipcb = udp_pcbs;
|
||||
while ((ipcb != NULL) && (port != UDP_LOCAL_PORT_RANGE_END)) {
|
||||
if (ipcb->local_port == port) {
|
||||
port++;
|
||||
ipcb = udp_pcbs;
|
||||
} else
|
||||
ipcb = ipcb->next;
|
||||
}
|
||||
if (ipcb != NULL) {
|
||||
/* no more ports available in local range */
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: out of free UDP ports\n"));
|
||||
return ERR_USE;
|
||||
}
|
||||
}
|
||||
pcb->local_port = port;
|
||||
snmp_insert_udpidx_tree(pcb);
|
||||
/* pcb not active yet? */
|
||||
if (rebind == 0) {
|
||||
/* place the PCB on the active list if not already there */
|
||||
pcb->next = udp_pcbs;
|
||||
udp_pcbs = pcb;
|
||||
}
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE,
|
||||
("udp_bind: bound to %"U16_F".%"U16_F".%"U16_F".%"U16_F", port %"U16_F"\n",
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 24 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) >> 8 & 0xff),
|
||||
(u16_t)(ntohl(pcb->local_ip.addr) & 0xff), pcb->local_port));
|
||||
return ERR_OK;
|
||||
}
|
||||
/**
|
||||
* Connect an UDP PCB.
|
||||
*
|
||||
* This will associate the UDP PCB with the remote address.
|
||||
*
|
||||
* @param pcb UDP PCB to be connected with remote address ipaddr and port.
|
||||
* @param ipaddr remote IP address to connect with.
|
||||
* @param port remote UDP port to connect with.
|
||||
*
|
||||
* @return lwIP error code
|
||||
*
|
||||
* @see udp_disconnect()
|
||||
*/
|
||||
err_t
|
||||
udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
|
||||
{
|
||||
struct udp_pcb *ipcb;
|
||||
|
||||
if (pcb->local_port == 0) {
|
||||
err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
|
||||
if (err != ERR_OK)
|
||||
return err;
|
||||
}
|
||||
|
||||
ip_addr_set(&pcb->remote_ip, ipaddr);
|
||||
pcb->remote_port = port;
|
||||
pcb->flags |= UDP_FLAGS_CONNECTED;
|
||||
/** TODO: this functionality belongs in upper layers */
|
||||
#ifdef LWIP_UDP_TODO
|
||||
/* Nail down local IP for netconn_addr()/getsockname() */
|
||||
if (ip_addr_isany(&pcb->local_ip) && !ip_addr_isany(&pcb->remote_ip)) {
|
||||
struct netif *netif;
|
||||
|
||||
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
|
||||
UDP_STATS_INC(udp.rterr);
|
||||
return ERR_RTE;
|
||||
}
|
||||
/** TODO: this will bind the udp pcb locally, to the interface which
|
||||
is used to route output packets to the remote address. However, we
|
||||
might want to accept incoming packets on any interface! */
|
||||
pcb->local_ip = netif->ip_addr;
|
||||
} else if (ip_addr_isany(&pcb->remote_ip)) {
|
||||
pcb->local_ip.addr = 0;
|
||||
}
|
||||
#endif
|
||||
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE | DBG_STATE,
|
||||
("udp_connect: connected to %"U16_F".%"U16_F".%"U16_F".%"U16_F",port %"U16_F"\n",
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 24 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 16 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) >> 8 & 0xff),
|
||||
(u16_t)(ntohl(pcb->remote_ip.addr) & 0xff), pcb->remote_port));
|
||||
|
||||
/* Insert UDP PCB into the list of active UDP PCBs. */
|
||||
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
|
||||
if (pcb == ipcb) {
|
||||
/* already on the list, just return */
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
/* PCB not yet on the list, add PCB now */
|
||||
pcb->next = udp_pcbs;
|
||||
udp_pcbs = pcb;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
udp_disconnect(struct udp_pcb *pcb)
|
||||
{
|
||||
/* reset remote address association */
|
||||
ip_addr_set(&pcb->remote_ip, IP_ADDR_ANY);
|
||||
pcb->remote_port = 0;
|
||||
/* mark PCB as unconnected */
|
||||
pcb->flags &= ~UDP_FLAGS_CONNECTED;
|
||||
}
|
||||
|
||||
void
|
||||
udp_recv(struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port),
|
||||
void *recv_arg)
|
||||
{
|
||||
/* remember recv() callback and user data */
|
||||
pcb->recv = recv;
|
||||
pcb->recv_arg = recv_arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an UDP PCB.
|
||||
*
|
||||
* @param pcb UDP PCB to be removed. The PCB is removed from the list of
|
||||
* UDP PCB's and the data structure is freed from memory.
|
||||
*
|
||||
* @see udp_new()
|
||||
*/
|
||||
void
|
||||
udp_remove(struct udp_pcb *pcb)
|
||||
{
|
||||
struct udp_pcb *pcb2;
|
||||
|
||||
snmp_delete_udpidx_tree(pcb);
|
||||
/* pcb to be removed is first in list? */
|
||||
if (udp_pcbs == pcb) {
|
||||
/* make list start at 2nd pcb */
|
||||
udp_pcbs = udp_pcbs->next;
|
||||
/* pcb not 1st in list */
|
||||
} else
|
||||
for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
|
||||
/* find pcb in udp_pcbs list */
|
||||
if (pcb2->next != NULL && pcb2->next == pcb) {
|
||||
/* remove pcb from list */
|
||||
pcb2->next = pcb->next;
|
||||
}
|
||||
}
|
||||
memp_free(MEMP_UDP_PCB, pcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a UDP PCB.
|
||||
*
|
||||
* @return The UDP PCB which was created. NULL if the PCB data structure
|
||||
* could not be allocated.
|
||||
*
|
||||
* @see udp_remove()
|
||||
*/
|
||||
struct udp_pcb *
|
||||
udp_new(void)
|
||||
{
|
||||
struct udp_pcb *pcb;
|
||||
pcb = memp_malloc(MEMP_UDP_PCB);
|
||||
/* could allocate UDP PCB? */
|
||||
if (pcb != NULL) {
|
||||
/* initialize PCB to all zeroes */
|
||||
memset(pcb, 0, sizeof(struct udp_pcb));
|
||||
pcb->ttl = UDP_TTL;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
#if UDP_DEBUG
|
||||
void
|
||||
udp_debug_print(struct udp_hdr *udphdr)
|
||||
{
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
|
||||
ntohs(udphdr->src), ntohs(udphdr->dest)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
|
||||
ntohs(udphdr->len), ntohs(udphdr->chksum)));
|
||||
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
|
||||
}
|
||||
#endif /* UDP_DEBUG */
|
||||
|
||||
#endif /* LWIP_UDP */
|
112
Demo/Common/ethernet/lwIP/include/ipv4/lwip/icmp.h
Normal file
112
Demo/Common/ethernet/lwIP/include/ipv4/lwip/icmp.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ICMP_H__
|
||||
#define __LWIP_ICMP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#define ICMP_ER 0 /* echo reply */
|
||||
#define ICMP_DUR 3 /* destination unreachable */
|
||||
#define ICMP_SQ 4 /* source quench */
|
||||
#define ICMP_RD 5 /* redirect */
|
||||
#define ICMP_ECHO 8 /* echo */
|
||||
#define ICMP_TE 11 /* time exceeded */
|
||||
#define ICMP_PP 12 /* parameter problem */
|
||||
#define ICMP_TS 13 /* timestamp */
|
||||
#define ICMP_TSR 14 /* timestamp reply */
|
||||
#define ICMP_IRQ 15 /* information request */
|
||||
#define ICMP_IR 16 /* information reply */
|
||||
|
||||
enum icmp_dur_type {
|
||||
ICMP_DUR_NET = 0, /* net unreachable */
|
||||
ICMP_DUR_HOST = 1, /* host unreachable */
|
||||
ICMP_DUR_PROTO = 2, /* protocol unreachable */
|
||||
ICMP_DUR_PORT = 3, /* port unreachable */
|
||||
ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */
|
||||
ICMP_DUR_SR = 5 /* source route failed */
|
||||
};
|
||||
|
||||
enum icmp_te_type {
|
||||
ICMP_TE_TTL = 0, /* time to live exceeded in transit */
|
||||
ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */
|
||||
};
|
||||
|
||||
void icmp_input(struct pbuf *p, struct netif *inp);
|
||||
|
||||
void icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t);
|
||||
void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_echo_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t id);
|
||||
PACK_STRUCT_FIELD(u16_t seqno);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_dur_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t unused);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
|
||||
PACK_STRUCT_BEGIN
|
||||
struct icmp_te_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u32_t unused);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define ICMPH_TYPE(hdr) (ntohs((hdr)->_type_code) >> 8)
|
||||
#define ICMPH_CODE(hdr) (ntohs((hdr)->_type_code) & 0xff)
|
||||
|
||||
#define ICMPH_TYPE_SET(hdr, type) ((hdr)->_type_code = htons(ICMPH_CODE(hdr) | ((type) << 8)))
|
||||
#define ICMPH_CODE_SET(hdr, code) ((hdr)->_type_code = htons((code) | (ICMPH_TYPE(hdr) << 8)))
|
||||
|
||||
#endif /* __LWIP_ICMP_H__ */
|
||||
|
99
Demo/Common/ethernet/lwIP/include/ipv4/lwip/inet.h
Normal file
99
Demo/Common/ethernet/lwIP/include/ipv4/lwip/inet.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_INET_H__
|
||||
#define __LWIP_INET_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
u16_t inet_chksum(void *dataptr, u16_t len);
|
||||
#if 0 /* optimized routine */
|
||||
u16_t inet_chksum4(u8_t *dataptr, u16_t len);
|
||||
#endif
|
||||
u16_t inet_chksum_pbuf(struct pbuf *p);
|
||||
u16_t inet_chksum_pseudo(struct pbuf *p,
|
||||
struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t proto, u16_t proto_len);
|
||||
|
||||
u32_t inet_addr(const char *cp);
|
||||
int inet_aton(const char *cp, struct in_addr *addr);
|
||||
char *inet_ntoa(struct in_addr addr); /* returns ptr to static buffer; not reentrant! */
|
||||
|
||||
#ifdef htons
|
||||
#undef htons
|
||||
#endif /* htons */
|
||||
#ifdef htonl
|
||||
#undef htonl
|
||||
#endif /* htonl */
|
||||
#ifdef ntohs
|
||||
#undef ntohs
|
||||
#endif /* ntohs */
|
||||
#ifdef ntohl
|
||||
#undef ntohl
|
||||
#endif /* ntohl */
|
||||
|
||||
#ifndef LWIP_PLATFORM_BYTESWAP
|
||||
#define LWIP_PLATFORM_BYTESWAP 0
|
||||
#endif
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define htons(x) (x)
|
||||
#define ntohs(x) (x)
|
||||
#define htonl(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#else /* BYTE_ORDER != BIG_ENDIAN */
|
||||
#ifdef LWIP_PREFIX_BYTEORDER_FUNCS
|
||||
/* workaround for naming collisions on some platforms */
|
||||
#define htons lwip_htons
|
||||
#define ntohs lwip_ntohs
|
||||
#define htonl lwip_htonl
|
||||
#define ntohl lwip_ntohl
|
||||
#endif
|
||||
#if LWIP_PLATFORM_BYTESWAP
|
||||
#define htons(x) LWIP_PLATFORM_HTONS(x)
|
||||
#define ntohs(x) LWIP_PLATFORM_HTONS(x)
|
||||
#define htonl(x) LWIP_PLATFORM_HTONL(x)
|
||||
#define ntohl(x) LWIP_PLATFORM_HTONL(x)
|
||||
#else
|
||||
u16_t htons(u16_t x);
|
||||
u16_t ntohs(u16_t x);
|
||||
u32_t htonl(u32_t x);
|
||||
u32_t ntohl(u32_t x);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_INET_H__ */
|
||||
|
154
Demo/Common/ethernet/lwIP/include/ipv4/lwip/ip.h
Normal file
154
Demo/Common/ethernet/lwIP/include/ipv4/lwip/ip.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_IP_H__
|
||||
#define __LWIP_IP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
|
||||
void ip_init(void);
|
||||
struct netif *ip_route(struct ip_addr *dest);
|
||||
err_t ip_input(struct pbuf *p, struct netif *inp);
|
||||
err_t ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto);
|
||||
err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
|
||||
u8_t ttl, u8_t tos, u8_t proto,
|
||||
struct netif *netif);
|
||||
|
||||
#define IP_HLEN 20
|
||||
|
||||
#define IP_PROTO_ICMP 1
|
||||
#define IP_PROTO_UDP 17
|
||||
#define IP_PROTO_UDPLITE 136
|
||||
#define IP_PROTO_TCP 6
|
||||
|
||||
/* This is passed as the destination address to ip_output_if (not
|
||||
to ip_output), meaning that an IP header already is constructed
|
||||
in the pbuf. This is used when TCP retransmits. */
|
||||
#ifdef IP_HDRINCL
|
||||
#undef IP_HDRINCL
|
||||
#endif /* IP_HDRINCL */
|
||||
#define IP_HDRINCL NULL
|
||||
|
||||
|
||||
/* This is the common part of all PCB types. It needs to be at the
|
||||
beginning of a PCB type definition. It is located here so that
|
||||
changes to this common part are made in one location instead of
|
||||
having to change all PCB structs. */
|
||||
#define IP_PCB struct ip_addr local_ip; \
|
||||
struct ip_addr remote_ip; \
|
||||
/* Socket options */ \
|
||||
u16_t so_options; \
|
||||
/* Type Of Service */ \
|
||||
u8_t tos; \
|
||||
/* Time To Live */ \
|
||||
u8_t ttl
|
||||
|
||||
/*
|
||||
* Option flags per-socket. These are the same like SO_XXX.
|
||||
*/
|
||||
#define SOF_DEBUG (u16_t)0x0001U /* turn on debugging info recording */
|
||||
#define SOF_ACCEPTCONN (u16_t)0x0002U /* socket has had listen() */
|
||||
#define SOF_REUSEADDR (u16_t)0x0004U /* allow local address reuse */
|
||||
#define SOF_KEEPALIVE (u16_t)0x0008U /* keep connections alive */
|
||||
#define SOF_DONTROUTE (u16_t)0x0010U /* just use interface addresses */
|
||||
#define SOF_BROADCAST (u16_t)0x0020U /* permit sending of broadcast msgs */
|
||||
#define SOF_USELOOPBACK (u16_t)0x0040U /* bypass hardware when possible */
|
||||
#define SOF_LINGER (u16_t)0x0080U /* linger on close if data present */
|
||||
#define SOF_OOBINLINE (u16_t)0x0100U /* leave received OOB data in line */
|
||||
#define SOF_REUSEPORT (u16_t)0x0200U /* allow local address & port reuse */
|
||||
|
||||
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_hdr {
|
||||
/* version / header length / type of service */
|
||||
PACK_STRUCT_FIELD(u16_t _v_hl_tos);
|
||||
/* total length */
|
||||
PACK_STRUCT_FIELD(u16_t _len);
|
||||
/* identification */
|
||||
PACK_STRUCT_FIELD(u16_t _id);
|
||||
/* fragment offset field */
|
||||
PACK_STRUCT_FIELD(u16_t _offset);
|
||||
#define IP_RF 0x8000 /* reserved fragment flag */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
/* time to live / protocol*/
|
||||
PACK_STRUCT_FIELD(u16_t _ttl_proto);
|
||||
/* checksum */
|
||||
PACK_STRUCT_FIELD(u16_t _chksum);
|
||||
/* source and destination IP addresses */
|
||||
PACK_STRUCT_FIELD(struct ip_addr src);
|
||||
PACK_STRUCT_FIELD(struct ip_addr dest);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define IPH_V(hdr) (ntohs((hdr)->_v_hl_tos) >> 12)
|
||||
#define IPH_HL(hdr) ((ntohs((hdr)->_v_hl_tos) >> 8) & 0x0f)
|
||||
#define IPH_TOS(hdr) (ntohs((hdr)->_v_hl_tos) & 0xff)
|
||||
#define IPH_LEN(hdr) ((hdr)->_len)
|
||||
#define IPH_ID(hdr) ((hdr)->_id)
|
||||
#define IPH_OFFSET(hdr) ((hdr)->_offset)
|
||||
#define IPH_TTL(hdr) (ntohs((hdr)->_ttl_proto) >> 8)
|
||||
#define IPH_PROTO(hdr) (ntohs((hdr)->_ttl_proto) & 0xff)
|
||||
#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
|
||||
|
||||
#define IPH_VHLTOS_SET(hdr, v, hl, tos) (hdr)->_v_hl_tos = (htons(((v) << 12) | ((hl) << 8) | (tos)))
|
||||
#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
|
||||
#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
|
||||
#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
|
||||
#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl_proto = (htons(IPH_PROTO(hdr) | ((u16_t)(ttl) << 8)))
|
||||
#define IPH_PROTO_SET(hdr, proto) (hdr)->_ttl_proto = (htons((proto) | (IPH_TTL(hdr) << 8)))
|
||||
#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
|
||||
|
||||
#if IP_DEBUG
|
||||
void ip_debug_print(struct pbuf *p);
|
||||
#else
|
||||
#define ip_debug_print(p)
|
||||
#endif /* IP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_IP_H__ */
|
||||
|
||||
|
160
Demo/Common/ethernet/lwIP/include/ipv4/lwip/ip_addr.h
Normal file
160
Demo/Common/ethernet/lwIP/include/ipv4/lwip/ip_addr.h
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_IP_ADDR_H__
|
||||
#define __LWIP_IP_ADDR_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_addr {
|
||||
PACK_STRUCT_FIELD(u32_t addr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* struct ipaddr2 is used in the definition of the ARP packet format in
|
||||
* order to support compilers that don't have structure packing.
|
||||
*/
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip_addr2 {
|
||||
PACK_STRUCT_FIELD(u16_t addrw[2]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/* For compatibility with BSD code */
|
||||
struct in_addr {
|
||||
u32_t s_addr;
|
||||
};
|
||||
|
||||
struct netif;
|
||||
|
||||
extern const struct ip_addr ip_addr_any;
|
||||
extern const struct ip_addr ip_addr_broadcast;
|
||||
|
||||
/** IP_ADDR_ can be used as a fixed IP address
|
||||
* for the wildcard and the broadcast address
|
||||
*/
|
||||
#define IP_ADDR_ANY ((struct ip_addr *)&ip_addr_any)
|
||||
#define IP_ADDR_BROADCAST ((struct ip_addr *)&ip_addr_broadcast)
|
||||
|
||||
#define INADDR_NONE ((u32_t)0xffffffff) /* 255.255.255.255 */
|
||||
#define INADDR_LOOPBACK ((u32_t)0x7f000001) /* 127.0.0.1 */
|
||||
|
||||
/* Definitions of the bits in an Internet address integer.
|
||||
|
||||
On subnets, host and network parts are found according to
|
||||
the subnet mask, not these masks. */
|
||||
|
||||
#define IN_CLASSA(a) ((((u32_t)(a)) & 0x80000000) == 0)
|
||||
#define IN_CLASSA_NET 0xff000000
|
||||
#define IN_CLASSA_NSHIFT 24
|
||||
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
|
||||
#define IN_CLASSA_MAX 128
|
||||
|
||||
#define IN_CLASSB(a) ((((u32_t)(a)) & 0xc0000000) == 0x80000000)
|
||||
#define IN_CLASSB_NET 0xffff0000
|
||||
#define IN_CLASSB_NSHIFT 16
|
||||
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
|
||||
#define IN_CLASSB_MAX 65536
|
||||
|
||||
#define IN_CLASSC(a) ((((u32_t)(a)) & 0xe0000000) == 0xc0000000)
|
||||
#define IN_CLASSC_NET 0xffffff00
|
||||
#define IN_CLASSC_NSHIFT 8
|
||||
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
|
||||
|
||||
#define IN_CLASSD(a) (((u32_t)(a) & 0xf0000000) == 0xe0000000)
|
||||
#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
|
||||
#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
|
||||
#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
|
||||
#define IN_MULTICAST(a) IN_CLASSD(a)
|
||||
|
||||
#define IN_EXPERIMENTAL(a) (((u32_t)(a) & 0xf0000000) == 0xf0000000)
|
||||
#define IN_BADCLASS(a) (((u32_t)(a) & 0xf0000000) == 0xf0000000)
|
||||
|
||||
#define IN_LOOPBACKNET 127 /* official! */
|
||||
|
||||
#define IP4_ADDR(ipaddr, a,b,c,d) \
|
||||
(ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \
|
||||
((u32_t)((b) & 0xff) << 16) | \
|
||||
((u32_t)((c) & 0xff) << 8) | \
|
||||
(u32_t)((d) & 0xff))
|
||||
|
||||
#define ip_addr_set(dest, src) (dest)->addr = \
|
||||
((src) == NULL? 0:\
|
||||
(src)->addr)
|
||||
/**
|
||||
* Determine if two address are on the same network.
|
||||
*
|
||||
* @arg addr1 IP address 1
|
||||
* @arg addr2 IP address 2
|
||||
* @arg mask network identifier mask
|
||||
* @return !0 if the network identifiers of both address match
|
||||
*/
|
||||
#define ip_addr_netcmp(addr1, addr2, mask) (((addr1)->addr & \
|
||||
(mask)->addr) == \
|
||||
((addr2)->addr & \
|
||||
(mask)->addr))
|
||||
#define ip_addr_cmp(addr1, addr2) ((addr1)->addr == (addr2)->addr)
|
||||
|
||||
#define ip_addr_isany(addr1) ((addr1) == NULL || (addr1)->addr == 0)
|
||||
|
||||
u8_t ip_addr_isbroadcast(struct ip_addr *, struct netif *);
|
||||
|
||||
#define ip_addr_ismulticast(addr1) (((addr1)->addr & ntohl(0xf0000000)) == ntohl(0xe0000000))
|
||||
|
||||
#define ip_addr_debug_print(debug, ipaddr) \
|
||||
LWIP_DEBUGF(debug, ("%"U16_F".%"U16_F".%"U16_F".%"U16_F, \
|
||||
ipaddr ? (u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff : 0, \
|
||||
ipaddr ? (u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff : 0, \
|
||||
ipaddr ? (u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff : 0, \
|
||||
ipaddr ? (u16_t)ntohl((ipaddr)->addr) & 0xff : 0))
|
||||
|
||||
/* These are cast to u16_t, with the intent that they are often arguments
|
||||
* to printf using the U16_F format from cc.h. */
|
||||
#define ip4_addr1(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 24) & 0xff)
|
||||
#define ip4_addr2(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 16) & 0xff)
|
||||
#define ip4_addr3(ipaddr) ((u16_t)(ntohl((ipaddr)->addr) >> 8) & 0xff)
|
||||
#define ip4_addr4(ipaddr) ((u16_t)(ntohl((ipaddr)->addr)) & 0xff)
|
||||
|
||||
#endif /* __LWIP_IP_ADDR_H__ */
|
49
Demo/Common/ethernet/lwIP/include/ipv4/lwip/ip_frag.h
Normal file
49
Demo/Common/ethernet/lwIP/include/ipv4/lwip/ip_frag.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Jani Monoses <jani@iv.ro>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_IP_FRAG_H__
|
||||
#define __LWIP_IP_FRAG_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
void ip_frag_init(void);
|
||||
void ip_reass_tmr(void);
|
||||
struct pbuf * ip_reass(struct pbuf *p);
|
||||
err_t ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest);
|
||||
|
||||
#endif /* __LWIP_IP_FRAG_H__ */
|
||||
|
||||
|
159
Demo/Common/ethernet/lwIP/include/lwip/api.h
Normal file
159
Demo/Common/ethernet/lwIP/include/lwip/api.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_API_H__
|
||||
#define __LWIP_API_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#include "lwip/raw.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#define NETCONN_NOCOPY 0x00
|
||||
#define NETCONN_COPY 0x01
|
||||
|
||||
enum netconn_type {
|
||||
NETCONN_TCP,
|
||||
NETCONN_UDP,
|
||||
NETCONN_UDPLITE,
|
||||
NETCONN_UDPNOCHKSUM,
|
||||
NETCONN_RAW
|
||||
};
|
||||
|
||||
enum netconn_state {
|
||||
NETCONN_NONE,
|
||||
NETCONN_WRITE,
|
||||
NETCONN_ACCEPT,
|
||||
NETCONN_RECV,
|
||||
NETCONN_CONNECT,
|
||||
NETCONN_CLOSE
|
||||
};
|
||||
|
||||
enum netconn_evt {
|
||||
NETCONN_EVT_RCVPLUS,
|
||||
NETCONN_EVT_RCVMINUS,
|
||||
NETCONN_EVT_SENDPLUS,
|
||||
NETCONN_EVT_SENDMINUS
|
||||
};
|
||||
|
||||
struct netbuf {
|
||||
struct pbuf *p, *ptr;
|
||||
struct ip_addr *fromaddr;
|
||||
u16_t fromport;
|
||||
err_t err;
|
||||
};
|
||||
|
||||
struct netconn {
|
||||
enum netconn_type type;
|
||||
enum netconn_state state;
|
||||
union {
|
||||
struct tcp_pcb *tcp;
|
||||
struct udp_pcb *udp;
|
||||
struct raw_pcb *raw;
|
||||
} pcb;
|
||||
err_t err;
|
||||
sys_mbox_t mbox;
|
||||
sys_mbox_t recvmbox;
|
||||
sys_mbox_t acceptmbox;
|
||||
sys_sem_t sem;
|
||||
int socket;
|
||||
u16_t recv_avail;
|
||||
void (* callback)(struct netconn *, enum netconn_evt, u16_t len);
|
||||
};
|
||||
|
||||
/* Network buffer functions: */
|
||||
struct netbuf * netbuf_new (void);
|
||||
void netbuf_delete (struct netbuf *buf);
|
||||
void * netbuf_alloc (struct netbuf *buf, u16_t size);
|
||||
void netbuf_free (struct netbuf *buf);
|
||||
void netbuf_ref (struct netbuf *buf,
|
||||
void *dataptr, u16_t size);
|
||||
void netbuf_chain (struct netbuf *head,
|
||||
struct netbuf *tail);
|
||||
|
||||
u16_t netbuf_len (struct netbuf *buf);
|
||||
err_t netbuf_data (struct netbuf *buf,
|
||||
void **dataptr, u16_t *len);
|
||||
s8_t netbuf_next (struct netbuf *buf);
|
||||
void netbuf_first (struct netbuf *buf);
|
||||
|
||||
void netbuf_copy (struct netbuf *buf,
|
||||
void *dataptr, u16_t len);
|
||||
void netbuf_copy_partial(struct netbuf *buf, void *dataptr,
|
||||
u16_t len, u16_t offset);
|
||||
struct ip_addr * netbuf_fromaddr (struct netbuf *buf);
|
||||
u16_t netbuf_fromport (struct netbuf *buf);
|
||||
|
||||
/* Network connection functions: */
|
||||
struct netconn * netconn_new (enum netconn_type type);
|
||||
struct
|
||||
netconn *netconn_new_with_callback(enum netconn_type t,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
|
||||
struct
|
||||
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
|
||||
void (*callback)(struct netconn *, enum netconn_evt, u16_t len));
|
||||
err_t netconn_delete (struct netconn *conn);
|
||||
enum netconn_type netconn_type (struct netconn *conn);
|
||||
err_t netconn_peer (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t *port);
|
||||
err_t netconn_addr (struct netconn *conn,
|
||||
struct ip_addr **addr,
|
||||
u16_t *port);
|
||||
err_t netconn_bind (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t port);
|
||||
err_t netconn_connect (struct netconn *conn,
|
||||
struct ip_addr *addr,
|
||||
u16_t port);
|
||||
err_t netconn_disconnect (struct netconn *conn);
|
||||
err_t netconn_listen (struct netconn *conn);
|
||||
struct netconn * netconn_accept (struct netconn *conn);
|
||||
struct netbuf * netconn_recv (struct netconn *conn);
|
||||
err_t netconn_send (struct netconn *conn,
|
||||
struct netbuf *buf);
|
||||
err_t netconn_write (struct netconn *conn,
|
||||
void *dataptr, u16_t size,
|
||||
u8_t copy);
|
||||
err_t netconn_close (struct netconn *conn);
|
||||
|
||||
err_t netconn_err (struct netconn *conn);
|
||||
|
||||
#endif /* __LWIP_API_H__ */
|
||||
|
||||
|
94
Demo/Common/ethernet/lwIP/include/lwip/api_msg.h
Normal file
94
Demo/Common/ethernet/lwIP/include/lwip/api_msg.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_API_MSG_H__
|
||||
#define __LWIP_API_MSG_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
#include "lwip/api.h"
|
||||
|
||||
enum api_msg_type {
|
||||
API_MSG_NEWCONN,
|
||||
API_MSG_DELCONN,
|
||||
|
||||
API_MSG_BIND,
|
||||
API_MSG_CONNECT,
|
||||
API_MSG_DISCONNECT,
|
||||
|
||||
API_MSG_LISTEN,
|
||||
API_MSG_ACCEPT,
|
||||
|
||||
API_MSG_SEND,
|
||||
API_MSG_RECV,
|
||||
API_MSG_WRITE,
|
||||
|
||||
API_MSG_CLOSE,
|
||||
|
||||
API_MSG_MAX
|
||||
};
|
||||
|
||||
struct api_msg_msg {
|
||||
struct netconn *conn;
|
||||
enum netconn_type conntype;
|
||||
union {
|
||||
struct pbuf *p;
|
||||
struct {
|
||||
struct ip_addr *ipaddr;
|
||||
u16_t port;
|
||||
} bc;
|
||||
struct {
|
||||
void *dataptr;
|
||||
u16_t len;
|
||||
u8_t copy;
|
||||
} w;
|
||||
sys_mbox_t mbox;
|
||||
u16_t len;
|
||||
} msg;
|
||||
};
|
||||
|
||||
struct api_msg {
|
||||
enum api_msg_type type;
|
||||
struct api_msg_msg msg;
|
||||
};
|
||||
|
||||
void api_msg_input(struct api_msg *msg);
|
||||
void api_msg_post(struct api_msg *msg);
|
||||
|
||||
#endif /* __LWIP_API_MSG_H__ */
|
||||
|
218
Demo/Common/ethernet/lwIP/include/lwip/arch.h
Normal file
218
Demo/Common/ethernet/lwIP/include/lwip/arch.h
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ARCH_H__
|
||||
#define __LWIP_ARCH_H__
|
||||
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
#ifndef PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#endif /* PACK_STRUCT_BEGIN */
|
||||
|
||||
#ifndef PACK_STRUCT_END
|
||||
#define PACK_STRUCT_END
|
||||
#endif /* PACK_STRUCT_END */
|
||||
|
||||
#ifndef PACK_STRUCT_FIELD
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#endif /* PACK_STRUCT_FIELD */
|
||||
|
||||
#ifndef PACK_STRUCT_STRUCT
|
||||
#define PACK_STRUCT_STRUCT
|
||||
#endif /* PACK_STRUCT_STRUCT */
|
||||
|
||||
#ifdef LWIP_PROVIDE_ERRNO
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Arg list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
|
||||
#define ENSROK 0 /* DNS server returned answer with no data */
|
||||
#define ENSRNODATA 160 /* DNS server returned answer with no data */
|
||||
#define ENSRFORMERR 161 /* DNS server claims query was misformatted */
|
||||
#define ENSRSERVFAIL 162 /* DNS server returned general failure */
|
||||
#define ENSRNOTFOUND 163 /* Domain name not found */
|
||||
#define ENSRNOTIMP 164 /* DNS server does not implement requested operation */
|
||||
#define ENSRREFUSED 165 /* DNS server refused query */
|
||||
#define ENSRBADQUERY 166 /* Misformatted DNS query */
|
||||
#define ENSRBADNAME 167 /* Misformatted domain name */
|
||||
#define ENSRBADFAMILY 168 /* Unsupported address family */
|
||||
#define ENSRBADRESP 169 /* Misformatted DNS reply */
|
||||
#define ENSRCONNREFUSED 170 /* Could not contact DNS servers */
|
||||
#define ENSRTIMEOUT 171 /* Timeout while contacting DNS servers */
|
||||
#define ENSROF 172 /* End of file */
|
||||
#define ENSRFILE 173 /* Error reading file */
|
||||
#define ENSRNOMEM 174 /* Out of memory */
|
||||
#define ENSRDESTRUCTION 175 /* Application terminated lookup */
|
||||
#define ENSRQUERYDOMAINTOOLONG 176 /* Domain name is too long */
|
||||
#define ENSRCNAMELOOP 177 /* Domain name is too long */
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_PROVIDE_ERRNO */
|
||||
|
||||
#endif /* __LWIP_ARCH_H__ */
|
87
Demo/Common/ethernet/lwIP/include/lwip/debug.h
Normal file
87
Demo/Common/ethernet/lwIP/include/lwip/debug.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_DEBUG_H__
|
||||
#define __LWIP_DEBUG_H__
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
/** lower two bits indicate debug level
|
||||
* - 0 off
|
||||
* - 1 warning
|
||||
* - 2 serious
|
||||
* - 3 severe
|
||||
*/
|
||||
|
||||
#define DBG_LEVEL_OFF 0
|
||||
#define DBG_LEVEL_WARNING 1 /* bad checksums, dropped packets, ... */
|
||||
#define DBG_LEVEL_SERIOUS 2 /* memory allocation failures, ... */
|
||||
#define DBG_LEVEL_SEVERE 3 /* */
|
||||
#define DBG_MASK_LEVEL 3
|
||||
|
||||
/** flag for LWIP_DEBUGF to enable that debug message */
|
||||
#define DBG_ON 0x80U
|
||||
/** flag for LWIP_DEBUGF to disable that debug message */
|
||||
#define DBG_OFF 0x00U
|
||||
|
||||
/** flag for LWIP_DEBUGF indicating a tracing message (to follow program flow) */
|
||||
#define DBG_TRACE 0x40U
|
||||
/** flag for LWIP_DEBUGF indicating a state debug message (to follow module states) */
|
||||
#define DBG_STATE 0x20U
|
||||
/** flag for LWIP_DEBUGF indicating newly added code, not thoroughly tested yet */
|
||||
#define DBG_FRESH 0x10U
|
||||
/** flag for LWIP_DEBUGF to halt after printing this debug message */
|
||||
#define DBG_HALT 0x08U
|
||||
|
||||
#ifndef LWIP_NOASSERT
|
||||
# define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
|
||||
#else
|
||||
# define LWIP_ASSERT(x,y)
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
/** print debug message only if debug message type is enabled...
|
||||
* AND is of correct type AND is at least DBG_LEVEL
|
||||
*/
|
||||
# define LWIP_DEBUGF(debug,x) do { if (((debug) & DBG_ON) && ((debug) & DBG_TYPES_ON) && ((s16_t)((debug) & DBG_MASK_LEVEL) >= DBG_MIN_LEVEL)) { LWIP_PLATFORM_DIAG(x); if ((debug) & DBG_HALT) while(1); } } while(0)
|
||||
# define LWIP_ERROR(x) do { LWIP_PLATFORM_DIAG(x); } while(0)
|
||||
#else /* LWIP_DEBUG */
|
||||
# define LWIP_DEBUGF(debug,x)
|
||||
# define LWIP_ERROR(x)
|
||||
#endif /* LWIP_DEBUG */
|
||||
|
||||
#endif /* __LWIP_DEBUG_H__ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
47
Demo/Common/ethernet/lwIP/include/lwip/def.h
Normal file
47
Demo/Common/ethernet/lwIP/include/lwip/def.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_DEF_H__
|
||||
#define __LWIP_DEF_H__
|
||||
|
||||
/* this might define NULL already */
|
||||
#include "arch/cc.h"
|
||||
|
||||
#define LWIP_MAX(x , y) (x) > (y) ? (x) : (y)
|
||||
#define LWIP_MIN(x , y) (x) < (y) ? (x) : (y)
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* __LWIP_DEF_H__ */
|
||||
|
223
Demo/Common/ethernet/lwIP/include/lwip/dhcp.h
Normal file
223
Demo/Common/ethernet/lwIP/include/lwip/dhcp.h
Normal file
|
@ -0,0 +1,223 @@
|
|||
/** @file
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_DHCP_H__
|
||||
#define __LWIP_DHCP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
/** period (in seconds) of the application calling dhcp_coarse_tmr() */
|
||||
#define DHCP_COARSE_TIMER_SECS 60
|
||||
/** period (in milliseconds) of the application calling dhcp_fine_tmr() */
|
||||
#define DHCP_FINE_TIMER_MSECS 500
|
||||
|
||||
struct dhcp
|
||||
{
|
||||
/** current DHCP state machine state */
|
||||
u8_t state;
|
||||
/** retries of current request */
|
||||
u8_t tries;
|
||||
/** transaction identifier of last sent request */
|
||||
u32_t xid;
|
||||
/** our connection to the DHCP server */
|
||||
struct udp_pcb *pcb;
|
||||
/** (first) pbuf of incoming msg */
|
||||
struct pbuf *p;
|
||||
/** incoming msg */
|
||||
struct dhcp_msg *msg_in;
|
||||
/** incoming msg options */
|
||||
struct dhcp_msg *options_in;
|
||||
/** ingoing msg options length */
|
||||
u16_t options_in_len;
|
||||
|
||||
struct pbuf *p_out; /* pbuf of outcoming msg */
|
||||
struct dhcp_msg *msg_out; /* outgoing msg */
|
||||
u16_t options_out_len; /* outgoing msg options length */
|
||||
u16_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */
|
||||
u16_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */
|
||||
u16_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */
|
||||
struct ip_addr server_ip_addr; /* dhcp server address that offered this lease */
|
||||
struct ip_addr offered_ip_addr;
|
||||
struct ip_addr offered_sn_mask;
|
||||
struct ip_addr offered_gw_addr;
|
||||
struct ip_addr offered_bc_addr;
|
||||
#define DHCP_MAX_DNS 2
|
||||
u32_t dns_count; /* actual number of DNS servers obtained */
|
||||
struct ip_addr offered_dns_addr[DHCP_MAX_DNS]; /* DNS server addresses */
|
||||
|
||||
u32_t offered_t0_lease; /* lease period (in seconds) */
|
||||
u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
|
||||
u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period) */
|
||||
/** Patch #1308
|
||||
* TODO: See dhcp.c "TODO"s
|
||||
*/
|
||||
#if 0
|
||||
struct ip_addr offered_si_addr;
|
||||
u8_t *boot_file_name;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* MUST be compiled with "pack structs" or equivalent! */
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** minimum set of fields of any DHCP message */
|
||||
struct dhcp_msg
|
||||
{
|
||||
PACK_STRUCT_FIELD(u8_t op);
|
||||
PACK_STRUCT_FIELD(u8_t htype);
|
||||
PACK_STRUCT_FIELD(u8_t hlen);
|
||||
PACK_STRUCT_FIELD(u8_t hops);
|
||||
PACK_STRUCT_FIELD(u32_t xid);
|
||||
PACK_STRUCT_FIELD(u16_t secs);
|
||||
PACK_STRUCT_FIELD(u16_t flags);
|
||||
PACK_STRUCT_FIELD(struct ip_addr ciaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr yiaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr siaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr giaddr);
|
||||
#define DHCP_CHADDR_LEN 16U
|
||||
PACK_STRUCT_FIELD(u8_t chaddr[DHCP_CHADDR_LEN]);
|
||||
#define DHCP_SNAME_LEN 64U
|
||||
PACK_STRUCT_FIELD(u8_t sname[DHCP_SNAME_LEN]);
|
||||
#define DHCP_FILE_LEN 128U
|
||||
PACK_STRUCT_FIELD(u8_t file[DHCP_FILE_LEN]);
|
||||
PACK_STRUCT_FIELD(u32_t cookie);
|
||||
#define DHCP_MIN_OPTIONS_LEN 68U
|
||||
/** make sure user does not configure this too small */
|
||||
#if ((defined(DHCP_OPTIONS_LEN)) && (DHCP_OPTIONS_LEN < DHCP_MIN_OPTIONS_LEN))
|
||||
# undef DHCP_OPTIONS_LEN
|
||||
#endif
|
||||
/** allow this to be configured in lwipopts.h, but not too small */
|
||||
#if (!defined(DHCP_OPTIONS_LEN))
|
||||
/** set this to be sufficient for your options in outgoing DHCP msgs */
|
||||
# define DHCP_OPTIONS_LEN DHCP_MIN_OPTIONS_LEN
|
||||
#endif
|
||||
PACK_STRUCT_FIELD(u8_t options[DHCP_OPTIONS_LEN]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** start DHCP configuration */
|
||||
err_t dhcp_start(struct netif *netif);
|
||||
/** enforce early lease renewal (not needed normally)*/
|
||||
err_t dhcp_renew(struct netif *netif);
|
||||
/** release the DHCP lease, usually called before dhcp_stop()*/
|
||||
err_t dhcp_release(struct netif *netif);
|
||||
/** stop DHCP configuration */
|
||||
void dhcp_stop(struct netif *netif);
|
||||
/** inform server of our manual IP address */
|
||||
void dhcp_inform(struct netif *netif);
|
||||
|
||||
/** if enabled, check whether the offered IP address is not in use, using ARP */
|
||||
#if DHCP_DOES_ARP_CHECK
|
||||
void dhcp_arp_reply(struct netif *netif, struct ip_addr *addr);
|
||||
#endif
|
||||
|
||||
/** to be called every minute */
|
||||
void dhcp_coarse_tmr(void);
|
||||
/** to be called every half second */
|
||||
void dhcp_fine_tmr(void);
|
||||
|
||||
/** DHCP message item offsets and length */
|
||||
#define DHCP_MSG_OFS (UDP_DATA_OFS)
|
||||
#define DHCP_OP_OFS (DHCP_MSG_OFS + 0)
|
||||
#define DHCP_HTYPE_OFS (DHCP_MSG_OFS + 1)
|
||||
#define DHCP_HLEN_OFS (DHCP_MSG_OFS + 2)
|
||||
#define DHCP_HOPS_OFS (DHCP_MSG_OFS + 3)
|
||||
#define DHCP_XID_OFS (DHCP_MSG_OFS + 4)
|
||||
#define DHCP_SECS_OFS (DHCP_MSG_OFS + 8)
|
||||
#define DHCP_FLAGS_OFS (DHCP_MSG_OFS + 10)
|
||||
#define DHCP_CIADDR_OFS (DHCP_MSG_OFS + 12)
|
||||
#define DHCP_YIADDR_OFS (DHCP_MSG_OFS + 16)
|
||||
#define DHCP_SIADDR_OFS (DHCP_MSG_OFS + 20)
|
||||
#define DHCP_GIADDR_OFS (DHCP_MSG_OFS + 24)
|
||||
#define DHCP_CHADDR_OFS (DHCP_MSG_OFS + 28)
|
||||
#define DHCP_SNAME_OFS (DHCP_MSG_OFS + 44)
|
||||
#define DHCP_FILE_OFS (DHCP_MSG_OFS + 108)
|
||||
#define DHCP_MSG_LEN 236
|
||||
|
||||
#define DHCP_COOKIE_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN)
|
||||
#define DHCP_OPTIONS_OFS (DHCP_MSG_OFS + DHCP_MSG_LEN + 4)
|
||||
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
#define DHCP_SERVER_PORT 67
|
||||
|
||||
/** DHCP client states */
|
||||
#define DHCP_REQUESTING 1
|
||||
#define DHCP_INIT 2
|
||||
#define DHCP_REBOOTING 3
|
||||
#define DHCP_REBINDING 4
|
||||
#define DHCP_RENEWING 5
|
||||
#define DHCP_SELECTING 6
|
||||
#define DHCP_INFORMING 7
|
||||
#define DHCP_CHECKING 8
|
||||
#define DHCP_PERMANENT 9
|
||||
#define DHCP_BOUND 10
|
||||
/** not yet implemented #define DHCP_RELEASING 11 */
|
||||
#define DHCP_BACKING_OFF 12
|
||||
#define DHCP_OFF 13
|
||||
|
||||
#define DHCP_BOOTREQUEST 1
|
||||
#define DHCP_BOOTREPLY 2
|
||||
|
||||
#define DHCP_DISCOVER 1
|
||||
#define DHCP_OFFER 2
|
||||
#define DHCP_REQUEST 3
|
||||
#define DHCP_DECLINE 4
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_NAK 6
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
|
||||
#define DHCP_HTYPE_ETH 1
|
||||
|
||||
#define DHCP_HLEN_ETH 6
|
||||
|
||||
#define DHCP_BROADCAST_FLAG 15
|
||||
#define DHCP_BROADCAST_MASK (1 << DHCP_FLAG_BROADCAST)
|
||||
|
||||
/** BootP options */
|
||||
#define DHCP_OPTION_PAD 0
|
||||
#define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
|
||||
#define DHCP_OPTION_ROUTER 3
|
||||
#define DHCP_OPTION_DNS_SERVER 6
|
||||
#define DHCP_OPTION_HOSTNAME 12
|
||||
#define DHCP_OPTION_IP_TTL 23
|
||||
#define DHCP_OPTION_MTU 26
|
||||
#define DHCP_OPTION_BROADCAST 28
|
||||
#define DHCP_OPTION_TCP_TTL 37
|
||||
#define DHCP_OPTION_END 255
|
||||
|
||||
/** DHCP options */
|
||||
#define DHCP_OPTION_REQUESTED_IP 50 /* RFC 2132 9.1, requested IP address */
|
||||
#define DHCP_OPTION_LEASE_TIME 51 /* RFC 2132 9.2, time in seconds, in 4 bytes */
|
||||
#define DHCP_OPTION_OVERLOAD 52 /* RFC2132 9.3, use file and/or sname field for options */
|
||||
|
||||
#define DHCP_OPTION_MESSAGE_TYPE 53 /* RFC 2132 9.6, important for DHCP */
|
||||
#define DHCP_OPTION_MESSAGE_TYPE_LEN 1
|
||||
|
||||
|
||||
#define DHCP_OPTION_SERVER_ID 54 /* RFC 2132 9.7, server IP address */
|
||||
#define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 /* RFC 2132 9.8, requested option types */
|
||||
|
||||
#define DHCP_OPTION_MAX_MSG_SIZE 57 /* RFC 2132 9.10, message size accepted >= 576 */
|
||||
#define DHCP_OPTION_MAX_MSG_SIZE_LEN 2
|
||||
|
||||
#define DHCP_OPTION_T1 58 /* T1 renewal time */
|
||||
#define DHCP_OPTION_T2 59 /* T2 rebinding time */
|
||||
#define DHCP_OPTION_CLIENT_ID 61
|
||||
#define DHCP_OPTION_TFTP_SERVERNAME 66
|
||||
#define DHCP_OPTION_BOOTFILE 67
|
||||
|
||||
/** possible combinations of overloading the file and sname fields with options */
|
||||
#define DHCP_OVERLOAD_NONE 0
|
||||
#define DHCP_OVERLOAD_FILE 1
|
||||
#define DHCP_OVERLOAD_SNAME 2
|
||||
#define DHCP_OVERLOAD_SNAME_FILE 3
|
||||
|
||||
#endif /*__LWIP_DHCP_H__*/
|
70
Demo/Common/ethernet/lwIP/include/lwip/err.h
Normal file
70
Demo/Common/ethernet/lwIP/include/lwip/err.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_ERR_H__
|
||||
#define __LWIP_ERR_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
typedef s8_t err_t;
|
||||
|
||||
/* Definitions for error constants. */
|
||||
|
||||
#define ERR_OK 0 /* No error, everything OK. */
|
||||
#define ERR_MEM -1 /* Out of memory error. */
|
||||
#define ERR_BUF -2 /* Buffer error. */
|
||||
|
||||
|
||||
#define ERR_ABRT -3 /* Connection aborted. */
|
||||
#define ERR_RST -4 /* Connection reset. */
|
||||
#define ERR_CLSD -5 /* Connection closed. */
|
||||
#define ERR_CONN -6 /* Not connected. */
|
||||
|
||||
#define ERR_VAL -7 /* Illegal value. */
|
||||
|
||||
#define ERR_ARG -8 /* Illegal argument. */
|
||||
|
||||
#define ERR_RTE -9 /* Routing problem. */
|
||||
|
||||
#define ERR_USE -10 /* Address in use. */
|
||||
|
||||
#define ERR_IF -11 /* Low-level netif error */
|
||||
#define ERR_ISCONN -12 /* Already connected. */
|
||||
|
||||
|
||||
#ifdef LWIP_DEBUG
|
||||
extern char *lwip_strerr(err_t err);
|
||||
#else
|
||||
#define lwip_strerr(x) ""
|
||||
#endif /* LWIP_DEBUG */
|
||||
#endif /* __LWIP_ERR_H__ */
|
69
Demo/Common/ethernet/lwIP/include/lwip/mem.h
Normal file
69
Demo/Common/ethernet/lwIP/include/lwip/mem.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_MEM_H__
|
||||
#define __LWIP_MEM_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#if MEM_SIZE > 64000l
|
||||
typedef u32_t mem_size_t;
|
||||
#define MEM_SIZE_F U32_F
|
||||
#else
|
||||
typedef u16_t mem_size_t;
|
||||
#define MEM_SIZE_F U16_F
|
||||
#endif /* MEM_SIZE > 64000 */
|
||||
|
||||
#if MEM_LIBC_MALLOC
|
||||
/* aliases for C library malloc() */
|
||||
#define mem_init()
|
||||
#define mem_free(x) free(x)
|
||||
#define mem_malloc(x) malloc(x)
|
||||
#define mem_realloc(x, size) realloc(x,size)
|
||||
#else
|
||||
/* lwIP alternative malloc */
|
||||
void mem_init(void);
|
||||
void *mem_malloc(mem_size_t size);
|
||||
void mem_free(void *mem);
|
||||
void *mem_realloc(void *mem, mem_size_t size);
|
||||
#endif
|
||||
|
||||
#ifndef MEM_ALIGN_SIZE
|
||||
#define MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))
|
||||
#endif
|
||||
|
||||
#ifndef MEM_ALIGN
|
||||
#define MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_MEM_H__ */
|
||||
|
63
Demo/Common/ethernet/lwIP/include/lwip/memp.h
Normal file
63
Demo/Common/ethernet/lwIP/include/lwip/memp.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_MEMP_H__
|
||||
#define __LWIP_MEMP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
typedef enum {
|
||||
MEMP_PBUF,
|
||||
MEMP_RAW_PCB,
|
||||
MEMP_UDP_PCB,
|
||||
MEMP_TCP_PCB,
|
||||
MEMP_TCP_PCB_LISTEN,
|
||||
MEMP_TCP_SEG,
|
||||
|
||||
MEMP_NETBUF,
|
||||
MEMP_NETCONN,
|
||||
MEMP_API_MSG,
|
||||
MEMP_TCPIP_MSG,
|
||||
|
||||
MEMP_SYS_TIMEOUT,
|
||||
|
||||
MEMP_MAX
|
||||
} memp_t;
|
||||
|
||||
void memp_init(void);
|
||||
|
||||
void *memp_malloc(memp_t type);
|
||||
void *memp_realloc(memp_t fromtype, memp_t totype, void *mem);
|
||||
void memp_free(memp_t type, void *mem);
|
||||
|
||||
#endif /* __LWIP_MEMP_H__ */
|
||||
|
165
Demo/Common/ethernet/lwIP/include/lwip/netif.h
Normal file
165
Demo/Common/ethernet/lwIP/include/lwip/netif.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_NETIF_H__
|
||||
#define __LWIP_NETIF_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#if LWIP_DHCP
|
||||
# include "lwip/dhcp.h"
|
||||
#endif
|
||||
|
||||
/** must be the maximum of all used hardware address lengths
|
||||
across all types of interfaces in use */
|
||||
#define NETIF_MAX_HWADDR_LEN 6U
|
||||
|
||||
/** TODO: define the use (where, when, whom) of netif flags */
|
||||
|
||||
/** whether the network interface is 'up'. this is
|
||||
* a software flag used to control whether this network
|
||||
* interface is enabled and processes traffic.
|
||||
*/
|
||||
#define NETIF_FLAG_UP 0x1U
|
||||
/** if set, the netif has broadcast capability */
|
||||
#define NETIF_FLAG_BROADCAST 0x2U
|
||||
/** if set, the netif is one end of a point-to-point connection */
|
||||
#define NETIF_FLAG_POINTTOPOINT 0x4U
|
||||
/** if set, the interface is configured using DHCP */
|
||||
#define NETIF_FLAG_DHCP 0x08U
|
||||
/** if set, the interface has an active link
|
||||
* (set by the network interface driver) */
|
||||
#define NETIF_FLAG_LINK_UP 0x10U
|
||||
|
||||
/** Generic data structure used for all lwIP network interfaces.
|
||||
* The following fields should be filled in by the initialization
|
||||
* function for the device driver: hwaddr_len, hwaddr[], mtu, flags */
|
||||
|
||||
struct netif {
|
||||
/** pointer to next in linked list */
|
||||
struct netif *next;
|
||||
|
||||
/** IP address configuration in network byte order */
|
||||
struct ip_addr ip_addr;
|
||||
struct ip_addr netmask;
|
||||
struct ip_addr gw;
|
||||
|
||||
/** This function is called by the network device driver
|
||||
* to pass a packet up the TCP/IP stack. */
|
||||
err_t (* input)(struct pbuf *p, struct netif *inp);
|
||||
/** This function is called by the IP module when it wants
|
||||
* to send a packet on the interface. This function typically
|
||||
* first resolves the hardware address, then sends the packet. */
|
||||
err_t (* output)(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr);
|
||||
/** This function is called by the ARP module when it wants
|
||||
* to send a packet on the interface. This function outputs
|
||||
* the pbuf as-is on the link medium. */
|
||||
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
|
||||
/** This field can be set by the device driver and could point
|
||||
* to state information for the device. */
|
||||
void *state;
|
||||
#if LWIP_DHCP
|
||||
/** the DHCP client state information for this netif */
|
||||
struct dhcp *dhcp;
|
||||
#endif
|
||||
/** number of bytes used in hwaddr */
|
||||
u8_t hwaddr_len;
|
||||
/** link level hardware address of this interface */
|
||||
u8_t hwaddr[NETIF_MAX_HWADDR_LEN];
|
||||
/** maximum transfer unit (in bytes) */
|
||||
u16_t mtu;
|
||||
/** flags (see NETIF_FLAG_ above) */
|
||||
u8_t flags;
|
||||
/** descriptive abbreviation */
|
||||
char name[2];
|
||||
/** number of this interface */
|
||||
u8_t num;
|
||||
#if LWIP_SNMP
|
||||
/** link type (ifType values per RFC1213) */
|
||||
u8_t link_type;
|
||||
/** (estimate) link speed */
|
||||
u32_t link_speed;
|
||||
/** timestamp at last change made (up/down) */
|
||||
u32_t ts;
|
||||
/** counters */
|
||||
u32_t ifinoctets;
|
||||
u32_t ifinucastpkts;
|
||||
u32_t ifinnucastpkts;
|
||||
u32_t ifindiscards;
|
||||
u32_t ifoutoctets;
|
||||
u32_t ifoutucastpkts;
|
||||
u32_t ifoutnucastpkts;
|
||||
u32_t ifoutdiscards;
|
||||
#endif
|
||||
};
|
||||
|
||||
/** The list of network interfaces. */
|
||||
extern struct netif *netif_list;
|
||||
/** The default network interface. */
|
||||
extern struct netif *netif_default;
|
||||
|
||||
/* netif_init() must be called first. */
|
||||
void netif_init(void);
|
||||
|
||||
struct netif *netif_add(struct netif *netif, struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw,
|
||||
void *state,
|
||||
err_t (* init)(struct netif *netif),
|
||||
err_t (* input)(struct pbuf *p, struct netif *netif));
|
||||
|
||||
void
|
||||
netif_set_addr(struct netif *netif,struct ip_addr *ipaddr, struct ip_addr *netmask,
|
||||
struct ip_addr *gw);
|
||||
void netif_remove(struct netif * netif);
|
||||
|
||||
/* Returns a network interface given its name. The name is of the form
|
||||
"et0", where the first two letters are the "name" field in the
|
||||
netif structure, and the digit is in the num field in the same
|
||||
structure. */
|
||||
struct netif *netif_find(char *name);
|
||||
|
||||
void netif_set_default(struct netif *netif);
|
||||
|
||||
void netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr);
|
||||
void netif_set_netmask(struct netif *netif, struct ip_addr *netmast);
|
||||
void netif_set_gw(struct netif *netif, struct ip_addr *gw);
|
||||
void netif_set_up(struct netif *netif);
|
||||
void netif_set_down(struct netif *netif);
|
||||
u8_t netif_is_up(struct netif *netif);
|
||||
|
||||
#endif /* __LWIP_NETIF_H__ */
|
113
Demo/Common/ethernet/lwIP/include/lwip/pbuf.h
Normal file
113
Demo/Common/ethernet/lwIP/include/lwip/pbuf.h
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_PBUF_H__
|
||||
#define __LWIP_PBUF_H__
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
|
||||
#define PBUF_TRANSPORT_HLEN 20
|
||||
#define PBUF_IP_HLEN 20
|
||||
|
||||
typedef enum {
|
||||
PBUF_TRANSPORT,
|
||||
PBUF_IP,
|
||||
PBUF_LINK,
|
||||
PBUF_RAW
|
||||
} pbuf_layer;
|
||||
|
||||
typedef enum {
|
||||
PBUF_RAM,
|
||||
PBUF_ROM,
|
||||
PBUF_REF,
|
||||
PBUF_POOL
|
||||
} pbuf_flag;
|
||||
|
||||
/* Definitions for the pbuf flag field. These are NOT the flags that
|
||||
* are passed to pbuf_alloc(). */
|
||||
#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */
|
||||
#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */
|
||||
#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */
|
||||
#define PBUF_FLAG_REF 0x04U /* Flags thet the pbuf payload refers to RAM */
|
||||
|
||||
/** indicates this packet was broadcast on the link */
|
||||
#define PBUF_FLAG_LINK_BROADCAST 0x80U
|
||||
|
||||
struct pbuf {
|
||||
/** next pbuf in singly linked pbuf chain */
|
||||
struct pbuf *next;
|
||||
|
||||
/** pointer to the actual data in the buffer */
|
||||
void *payload;
|
||||
|
||||
/**
|
||||
* total length of this buffer and all next buffers in chain
|
||||
* belonging to the same packet.
|
||||
*
|
||||
* For non-queue packet chains this is the invariant:
|
||||
* p->tot_len == p->len + (p->next? p->next->tot_len: 0)
|
||||
*/
|
||||
u16_t tot_len;
|
||||
|
||||
/** length of this buffer */
|
||||
u16_t len;
|
||||
|
||||
/** flags telling the type of pbuf, see PBUF_FLAG_ */
|
||||
u16_t flags;
|
||||
|
||||
/**
|
||||
* the reference count always equals the number of pointers
|
||||
* that refer to this pbuf. This can be pointers from an application,
|
||||
* the stack itself, or pbuf->next pointers from a chain.
|
||||
*/
|
||||
u16_t ref;
|
||||
|
||||
};
|
||||
|
||||
void pbuf_init(void);
|
||||
|
||||
struct pbuf *pbuf_alloc(pbuf_layer l, u16_t size, pbuf_flag flag);
|
||||
void pbuf_realloc(struct pbuf *p, u16_t size);
|
||||
u8_t pbuf_header(struct pbuf *p, s16_t header_size);
|
||||
void pbuf_ref(struct pbuf *p);
|
||||
void pbuf_ref_chain(struct pbuf *p);
|
||||
u8_t pbuf_free(struct pbuf *p);
|
||||
u8_t pbuf_clen(struct pbuf *p);
|
||||
void pbuf_cat(struct pbuf *h, struct pbuf *t);
|
||||
void pbuf_chain(struct pbuf *h, struct pbuf *t);
|
||||
struct pbuf *pbuf_take(struct pbuf *f);
|
||||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
||||
void pbuf_queue(struct pbuf *p, struct pbuf *n);
|
||||
struct pbuf * pbuf_dequeue(struct pbuf *p);
|
||||
|
||||
#endif /* __LWIP_PBUF_H__ */
|
74
Demo/Common/ethernet/lwIP/include/lwip/raw.h
Normal file
74
Demo/Common/ethernet/lwIP/include/lwip/raw.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_RAW_H__
|
||||
#define __LWIP_RAW_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
struct raw_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
struct raw_pcb *next;
|
||||
|
||||
u16_t protocol;
|
||||
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr);
|
||||
void *recv_arg;
|
||||
};
|
||||
|
||||
/* The following functions is the application layer interface to the
|
||||
RAW code. */
|
||||
struct raw_pcb * raw_new (u16_t proto);
|
||||
void raw_remove (struct raw_pcb *pcb);
|
||||
err_t raw_bind (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||
err_t raw_connect (struct raw_pcb *pcb, struct ip_addr *ipaddr);
|
||||
|
||||
void raw_recv (struct raw_pcb *pcb,
|
||||
u8_t (* recv)(void *arg, struct raw_pcb *pcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr),
|
||||
void *recv_arg);
|
||||
err_t raw_sendto (struct raw_pcb *pcb, struct pbuf *p, struct ip_addr *ipaddr);
|
||||
err_t raw_send (struct raw_pcb *pcb, struct pbuf *p);
|
||||
|
||||
/* The following functions are the lower layer interface to RAW. */
|
||||
u8_t raw_input (struct pbuf *p, struct netif *inp);
|
||||
void raw_init (void);
|
||||
|
||||
|
||||
#endif /* __LWIP_RAW_H__ */
|
63
Demo/Common/ethernet/lwIP/include/lwip/sio.h
Normal file
63
Demo/Common/ethernet/lwIP/include/lwip/sio.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the interface to the platform specific serial IO module
|
||||
* It needs to be implemented by those platforms which need SLIP or PPP
|
||||
*/
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
#ifndef __sio_fd_t_defined
|
||||
typedef void * sio_fd_t;
|
||||
#endif
|
||||
|
||||
#ifndef sio_open
|
||||
sio_fd_t sio_open(u8_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_send
|
||||
void sio_send(u8_t, sio_fd_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_recv
|
||||
u8_t sio_recv(sio_fd_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_read
|
||||
u32_t sio_read(sio_fd_t, u8_t *, u32_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_write
|
||||
u32_t sio_write(sio_fd_t, u8_t *, u32_t);
|
||||
#endif
|
||||
|
||||
#ifndef sio_read_abort
|
||||
void sio_read_abort(sio_fd_t);
|
||||
#endif
|
309
Demo/Common/ethernet/lwIP/include/lwip/snmp.h
Normal file
309
Demo/Common/ethernet/lwIP/include/lwip/snmp.h
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
* Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_SNMP_H__
|
||||
#define __LWIP_SNMP_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
/* SNMP support available? */
|
||||
#if defined(LWIP_SNMP) && (LWIP_SNMP > 0)
|
||||
|
||||
/** fixed maximum length for object identifier type */
|
||||
#define LWIP_SNMP_OBJ_ID_LEN 32
|
||||
/** internal object identifier representation */
|
||||
struct snmp_obj_id
|
||||
{
|
||||
u8_t len;
|
||||
s32_t id[LWIP_SNMP_OBJ_ID_LEN];
|
||||
};
|
||||
|
||||
/* system */
|
||||
void snmp_set_sysdesr(u8_t* str, u8_t* strlen);
|
||||
void snmp_set_sysobjid(struct snmp_obj_id *oid);
|
||||
void snmp_get_sysobjid_ptr(struct snmp_obj_id **oid);
|
||||
void snmp_inc_sysuptime(void);
|
||||
void snmp_get_sysuptime(u32_t *value);
|
||||
void snmp_set_syscontact(u8_t *ocstr, u8_t *ocstrlen);
|
||||
void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen);
|
||||
void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen);
|
||||
|
||||
/* network interface */
|
||||
void snmp_add_ifinoctets(struct netif *ni, u32_t value);
|
||||
void snmp_inc_ifinucastpkts(struct netif *ni);
|
||||
void snmp_inc_ifinnucastpkts(struct netif *ni);
|
||||
void snmp_inc_ifindiscards(struct netif *ni);
|
||||
void snmp_add_ifoutoctets(struct netif *ni, u32_t value);
|
||||
void snmp_inc_ifoutucastpkts(struct netif *ni);
|
||||
void snmp_inc_ifoutnucastpkts(struct netif *ni);
|
||||
void snmp_inc_ifoutdiscards(struct netif *ni);
|
||||
void snmp_inc_iflist(void);
|
||||
void snmp_dec_iflist(void);
|
||||
|
||||
/* ARP (for atTable and ipNetToMediaTable) */
|
||||
void snmp_insert_arpidx_tree(struct netif *ni, struct ip_addr *ip);
|
||||
void snmp_delete_arpidx_tree(struct netif *ni, struct ip_addr *ip);
|
||||
|
||||
/* IP */
|
||||
void snmp_inc_ipinreceives(void);
|
||||
void snmp_inc_ipinhdrerrors(void);
|
||||
void snmp_inc_ipinaddrerrors(void);
|
||||
void snmp_inc_ipforwdatagrams(void);
|
||||
void snmp_inc_ipinunknownprotos(void);
|
||||
void snmp_inc_ipindiscards(void);
|
||||
void snmp_inc_ipindelivers(void);
|
||||
void snmp_inc_ipoutrequests(void);
|
||||
void snmp_inc_ipoutdiscards(void);
|
||||
void snmp_inc_ipoutnoroutes(void);
|
||||
void snmp_inc_ipreasmreqds(void);
|
||||
void snmp_inc_ipreasmoks(void);
|
||||
void snmp_inc_ipreasmfails(void);
|
||||
void snmp_inc_ipfragoks(void);
|
||||
void snmp_inc_ipfragfails(void);
|
||||
void snmp_inc_ipfragcreates(void);
|
||||
void snmp_inc_iproutingdiscards(void);
|
||||
void snmp_insert_ipaddridx_tree(struct netif *ni);
|
||||
void snmp_delete_ipaddridx_tree(struct netif *ni);
|
||||
void snmp_insert_iprteidx_tree(u8_t dflt, struct netif *ni);
|
||||
void snmp_delete_iprteidx_tree(u8_t dflt, struct netif *ni);
|
||||
|
||||
/* ICMP */
|
||||
void snmp_inc_icmpinmsgs(void);
|
||||
void snmp_inc_icmpinerrors(void);
|
||||
void snmp_inc_icmpindestunreachs(void);
|
||||
void snmp_inc_icmpintimeexcds(void);
|
||||
void snmp_inc_icmpinparmprobs(void);
|
||||
void snmp_inc_icmpinsrcquenchs(void);
|
||||
void snmp_inc_icmpinredirects(void);
|
||||
void snmp_inc_icmpinechos(void);
|
||||
void snmp_inc_icmpinechoreps(void);
|
||||
void snmp_inc_icmpintimestamps(void);
|
||||
void snmp_inc_icmpintimestampreps(void);
|
||||
void snmp_inc_icmpinaddrmasks(void);
|
||||
void snmp_inc_icmpinaddrmaskreps(void);
|
||||
void snmp_inc_icmpoutmsgs(void);
|
||||
void snmp_inc_icmpouterrors(void);
|
||||
void snmp_inc_icmpoutdestunreachs(void);
|
||||
void snmp_inc_icmpouttimeexcds(void);
|
||||
void snmp_inc_icmpoutparmprobs(void);
|
||||
void snmp_inc_icmpoutsrcquenchs(void);
|
||||
void snmp_inc_icmpoutredirects(void);
|
||||
void snmp_inc_icmpoutechos(void);
|
||||
void snmp_inc_icmpoutechoreps(void);
|
||||
void snmp_inc_icmpouttimestamps(void);
|
||||
void snmp_inc_icmpouttimestampreps(void);
|
||||
void snmp_inc_icmpoutaddrmasks(void);
|
||||
void snmp_inc_icmpoutaddrmaskreps(void);
|
||||
|
||||
/* TCP */
|
||||
void snmp_inc_tcpactiveopens(void);
|
||||
void snmp_inc_tcppassiveopens(void);
|
||||
void snmp_inc_tcpattemptfails(void);
|
||||
void snmp_inc_tcpestabresets(void);
|
||||
void snmp_inc_tcpinsegs(void);
|
||||
void snmp_inc_tcpoutsegs(void);
|
||||
void snmp_inc_tcpretranssegs(void);
|
||||
void snmp_inc_tcpinerrs(void);
|
||||
void snmp_inc_tcpoutrsts(void);
|
||||
|
||||
/* UDP */
|
||||
void snmp_inc_udpindatagrams(void);
|
||||
void snmp_inc_udpnoports(void);
|
||||
void snmp_inc_udpinerrors(void);
|
||||
void snmp_inc_udpoutdatagrams(void);
|
||||
void snmp_insert_udpidx_tree(struct udp_pcb *pcb);
|
||||
void snmp_delete_udpidx_tree(struct udp_pcb *pcb);
|
||||
|
||||
/* SNMP */
|
||||
void snmp_inc_snmpinpkts(void);
|
||||
void snmp_inc_snmpoutpkts(void);
|
||||
void snmp_inc_snmpinbadversions(void);
|
||||
void snmp_inc_snmpinbadcommunitynames(void);
|
||||
void snmp_inc_snmpinbadcommunityuses(void);
|
||||
void snmp_inc_snmpinasnparseerrs(void);
|
||||
void snmp_inc_snmpintoobigs(void);
|
||||
void snmp_inc_snmpinnosuchnames(void);
|
||||
void snmp_inc_snmpinbadvalues(void);
|
||||
void snmp_inc_snmpinreadonlys(void);
|
||||
void snmp_inc_snmpingenerrs(void);
|
||||
void snmp_add_snmpintotalreqvars(u8_t value);
|
||||
void snmp_add_snmpintotalsetvars(u8_t value);
|
||||
void snmp_inc_snmpingetrequests(void);
|
||||
void snmp_inc_snmpingetnexts(void);
|
||||
void snmp_inc_snmpinsetrequests(void);
|
||||
void snmp_inc_snmpingetresponses(void);
|
||||
void snmp_inc_snmpintraps(void);
|
||||
void snmp_inc_snmpouttoobigs(void);
|
||||
void snmp_inc_snmpoutnosuchnames(void);
|
||||
void snmp_inc_snmpoutbadvalues(void);
|
||||
void snmp_inc_snmpoutgenerrs(void);
|
||||
void snmp_inc_snmpoutgetrequests(void);
|
||||
void snmp_inc_snmpoutgetnexts(void);
|
||||
void snmp_inc_snmpoutsetrequests(void);
|
||||
void snmp_inc_snmpoutgetresponses(void);
|
||||
void snmp_inc_snmpouttraps(void);
|
||||
void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid);
|
||||
void snmp_set_snmpenableauthentraps(u8_t *value);
|
||||
void snmp_get_snmpenableauthentraps(u8_t *value);
|
||||
|
||||
/* LWIP_SNMP support not available */
|
||||
/* define everything to be empty */
|
||||
#else
|
||||
|
||||
/* system */
|
||||
#define snmp_set_sysdesr(str, strlen)
|
||||
#define snmp_get_sysobjid_ptr(oid)
|
||||
#define snmp_inc_sysuptime()
|
||||
#define snmp_get_sysuptime(value)
|
||||
|
||||
/* network interface */
|
||||
#define snmp_add_ifinoctets(ni,value)
|
||||
#define snmp_inc_ifinucastpkts(ni)
|
||||
#define snmp_inc_ifinnucastpkts(ni)
|
||||
#define snmp_inc_ifindiscards(ni)
|
||||
#define snmp_add_ifoutoctets(ni,value)
|
||||
#define snmp_inc_ifoutucastpkts(ni)
|
||||
#define snmp_inc_ifoutnucastpkts(ni)
|
||||
#define snmp_inc_ifoutdiscards(ni)
|
||||
#define snmp_inc_iflist()
|
||||
#define snmp_dec_iflist()
|
||||
|
||||
/* ARP */
|
||||
#define snmp_insert_arpidx_tree(ni,ip)
|
||||
#define snmp_delete_arpidx_tree(ni,ip)
|
||||
|
||||
/* IP */
|
||||
#define snmp_inc_ipinreceives()
|
||||
#define snmp_inc_ipinhdrerrors()
|
||||
#define snmp_inc_ipinaddrerrors()
|
||||
#define snmp_inc_ipforwdatagrams()
|
||||
#define snmp_inc_ipinunknownprotos()
|
||||
#define snmp_inc_ipindiscards()
|
||||
#define snmp_inc_ipindelivers()
|
||||
#define snmp_inc_ipoutrequests()
|
||||
#define snmp_inc_ipoutdiscards()
|
||||
#define snmp_inc_ipoutnoroutes()
|
||||
#define snmp_inc_ipreasmreqds()
|
||||
#define snmp_inc_ipreasmoks()
|
||||
#define snmp_inc_ipreasmfails()
|
||||
#define snmp_inc_ipfragoks()
|
||||
#define snmp_inc_ipfragfails()
|
||||
#define snmp_inc_ipfragcreates()
|
||||
#define snmp_inc_iproutingdiscards()
|
||||
#define snmp_insert_ipaddridx_tree(ni)
|
||||
#define snmp_delete_ipaddridx_tree(ni)
|
||||
#define snmp_insert_iprteidx_tree(dflt, ni)
|
||||
#define snmp_delete_iprteidx_tree(dflt, ni)
|
||||
|
||||
/* ICMP */
|
||||
#define snmp_inc_icmpinmsgs()
|
||||
#define snmp_inc_icmpinerrors()
|
||||
#define snmp_inc_icmpindestunreachs()
|
||||
#define snmp_inc_icmpintimeexcds()
|
||||
#define snmp_inc_icmpinparmprobs()
|
||||
#define snmp_inc_icmpinsrcquenchs()
|
||||
#define snmp_inc_icmpinredirects()
|
||||
#define snmp_inc_icmpinechos()
|
||||
#define snmp_inc_icmpinechoreps()
|
||||
#define snmp_inc_icmpintimestamps()
|
||||
#define snmp_inc_icmpintimestampreps()
|
||||
#define snmp_inc_icmpinaddrmasks()
|
||||
#define snmp_inc_icmpinaddrmaskreps()
|
||||
#define snmp_inc_icmpoutmsgs()
|
||||
#define snmp_inc_icmpouterrors()
|
||||
#define snmp_inc_icmpoutdestunreachs()
|
||||
#define snmp_inc_icmpouttimeexcds()
|
||||
#define snmp_inc_icmpoutparmprobs()
|
||||
#define snmp_inc_icmpoutsrcquenchs()
|
||||
#define snmp_inc_icmpoutredirects()
|
||||
#define snmp_inc_icmpoutechos()
|
||||
#define snmp_inc_icmpoutechoreps()
|
||||
#define snmp_inc_icmpouttimestamps()
|
||||
#define snmp_inc_icmpouttimestampreps()
|
||||
#define snmp_inc_icmpoutaddrmasks()
|
||||
#define snmp_inc_icmpoutaddrmaskreps()
|
||||
/* TCP */
|
||||
#define snmp_inc_tcpactiveopens()
|
||||
#define snmp_inc_tcppassiveopens()
|
||||
#define snmp_inc_tcpattemptfails()
|
||||
#define snmp_inc_tcpestabresets()
|
||||
#define snmp_inc_tcpinsegs()
|
||||
#define snmp_inc_tcpoutsegs()
|
||||
#define snmp_inc_tcpretranssegs()
|
||||
#define snmp_inc_tcpinerrs()
|
||||
#define snmp_inc_tcpoutrsts()
|
||||
|
||||
/* UDP */
|
||||
#define snmp_inc_udpindatagrams()
|
||||
#define snmp_inc_udpnoports()
|
||||
#define snmp_inc_udpinerrors()
|
||||
#define snmp_inc_udpoutdatagrams()
|
||||
#define snmp_insert_udpidx_tree(pcb)
|
||||
#define snmp_delete_udpidx_tree(pcb)
|
||||
|
||||
/* SNMP */
|
||||
#define snmp_inc_snmpinpkts()
|
||||
#define snmp_inc_snmpoutpkts()
|
||||
#define snmp_inc_snmpinbadversions()
|
||||
#define snmp_inc_snmpinbadcommunitynames()
|
||||
#define snmp_inc_snmpinbadcommunityuses()
|
||||
#define snmp_inc_snmpinasnparseerrs()
|
||||
#define snmp_inc_snmpintoobigs()
|
||||
#define snmp_inc_snmpinnosuchnames()
|
||||
#define snmp_inc_snmpinbadvalues()
|
||||
#define snmp_inc_snmpinreadonlys()
|
||||
#define snmp_inc_snmpingenerrs()
|
||||
#define snmp_add_snmpintotalreqvars(value)
|
||||
#define snmp_add_snmpintotalsetvars(value)
|
||||
#define snmp_inc_snmpingetrequests()
|
||||
#define snmp_inc_snmpingetnexts()
|
||||
#define snmp_inc_snmpinsetrequests()
|
||||
#define snmp_inc_snmpingetresponses()
|
||||
#define snmp_inc_snmpintraps()
|
||||
#define snmp_inc_snmpouttoobigs()
|
||||
#define snmp_inc_snmpoutnosuchnames()
|
||||
#define snmp_inc_snmpoutbadvalues()
|
||||
#define snmp_inc_snmpoutgenerrs()
|
||||
#define snmp_inc_snmpoutgetrequests()
|
||||
#define snmp_inc_snmpoutgetnexts()
|
||||
#define snmp_inc_snmpoutsetrequests()
|
||||
#define snmp_inc_snmpoutgetresponses()
|
||||
#define snmp_inc_snmpouttraps()
|
||||
#define snmp_get_snmpgrpid_ptr(oid)
|
||||
#define snmp_set_snmpenableauthentraps(value)
|
||||
#define snmp_get_snmpenableauthentraps(value)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_SNMP_H__ */
|
90
Demo/Common/ethernet/lwIP/include/lwip/snmp_asn1.h
Normal file
90
Demo/Common/ethernet/lwIP/include/lwip/snmp_asn1.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* @file
|
||||
* Abstract Syntax Notation One (ISO 8824, 8825) codec.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_SNMP_ASN1_H__
|
||||
#define __LWIP_SNMP_ASN1_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "arch/cc.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#define SNMP_ASN1_UNIV (!0x80 | !0x40)
|
||||
#define SNMP_ASN1_APPLIC (!0x80 | 0x40)
|
||||
#define SNMP_ASN1_CONTXT ( 0x80 | !0x40)
|
||||
|
||||
#define SNMP_ASN1_CONSTR (0x20)
|
||||
#define SNMP_ASN1_PRIMIT (!0x20)
|
||||
|
||||
/* universal tags */
|
||||
#define SNMP_ASN1_INTEG 2
|
||||
#define SNMP_ASN1_OC_STR 4
|
||||
#define SNMP_ASN1_NUL 5
|
||||
#define SNMP_ASN1_OBJ_ID 6
|
||||
#define SNMP_ASN1_SEQ 16
|
||||
|
||||
/* application specific (SNMP) tags */
|
||||
#define SNMP_ASN1_IPADDR 0 /* octet string size(4) */
|
||||
#define SNMP_ASN1_COUNTER 1 /* u32_t */
|
||||
#define SNMP_ASN1_GAUGE 2 /* u32_t */
|
||||
#define SNMP_ASN1_TIMETICKS 3 /* u32_t */
|
||||
#define SNMP_ASN1_OPAQUE 4 /* octet string */
|
||||
|
||||
/* context specific (SNMP) tags */
|
||||
#define SNMP_ASN1_PDU_GET_REQ 0
|
||||
#define SNMP_ASN1_PDU_GET_NEXT_REQ 1
|
||||
#define SNMP_ASN1_PDU_GET_RESP 2
|
||||
#define SNMP_ASN1_PDU_SET_REQ 3
|
||||
#define SNMP_ASN1_PDU_TRAP 4
|
||||
|
||||
err_t snmp_asn1_dec_type(struct pbuf *p, u16_t ofs, u8_t *type);
|
||||
err_t snmp_asn1_dec_length(struct pbuf *p, u16_t ofs, u8_t *octets_used, u16_t *length);
|
||||
err_t snmp_asn1_dec_u32t(struct pbuf *p, u16_t ofs, u16_t len, u32_t *value);
|
||||
err_t snmp_asn1_dec_s32t(struct pbuf *p, u16_t ofs, u16_t len, s32_t *value);
|
||||
err_t snmp_asn1_dec_oid(struct pbuf *p, u16_t ofs, u16_t len, struct snmp_obj_id *oid);
|
||||
err_t snmp_asn1_dec_raw(struct pbuf *p, u16_t ofs, u16_t len, u16_t raw_len, u8_t *raw);
|
||||
|
||||
void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed);
|
||||
void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed);
|
||||
void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed);
|
||||
void snmp_asn1_enc_oid_cnt(u8_t ident_len, s32_t *ident, u16_t *octets_needed);
|
||||
err_t snmp_asn1_enc_type(struct pbuf *p, u16_t ofs, u8_t type);
|
||||
err_t snmp_asn1_enc_length(struct pbuf *p, u16_t ofs, u16_t length);
|
||||
err_t snmp_asn1_enc_u32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, u32_t value);
|
||||
err_t snmp_asn1_enc_s32t(struct pbuf *p, u16_t ofs, u8_t octets_needed, s32_t value);
|
||||
err_t snmp_asn1_enc_oid(struct pbuf *p, u16_t ofs, u8_t ident_len, s32_t *ident);
|
||||
err_t snmp_asn1_enc_raw(struct pbuf *p, u16_t ofs, u8_t raw_len, u8_t *raw);
|
||||
|
||||
#endif
|
292
Demo/Common/ethernet/lwIP/include/lwip/snmp_msg.h
Normal file
292
Demo/Common/ethernet/lwIP/include/lwip/snmp_msg.h
Normal file
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* @file
|
||||
* SNMP Agent message handling structures.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_SNMP_MSG_H__
|
||||
#define __LWIP_SNMP_MSG_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "arch/cc.h"
|
||||
#include "lwip/snmp.h"
|
||||
#include "lwip/snmp_structs.h"
|
||||
|
||||
#if SNMP_PRIVATE_MIB
|
||||
#include "private_mib.h"
|
||||
#endif
|
||||
|
||||
#define SNMP_IN_PORT 161
|
||||
#define SNMP_TRAP_PORT 162
|
||||
|
||||
#define SNMP_ES_NOERROR 0
|
||||
#define SNMP_ES_TOOBIG 1
|
||||
#define SNMP_ES_NOSUCHNAME 2
|
||||
#define SNMP_ES_BADVALUE 3
|
||||
#define SNMP_ES_READONLY 4
|
||||
#define SNMP_ES_GENERROR 5
|
||||
|
||||
#define SNMP_GENTRAP_COLDSTART 0
|
||||
#define SNMP_GENTRAP_WARMSTART 1
|
||||
#define SNMP_GENTRAP_AUTHFAIL 4
|
||||
#define SNMP_GENTRAP_ENTERPRISESPC 6
|
||||
|
||||
struct snmp_varbind
|
||||
{
|
||||
/* next pointer, NULL for last in list */
|
||||
struct snmp_varbind *next;
|
||||
/* previous pointer, NULL for first in list */
|
||||
struct snmp_varbind *prev;
|
||||
|
||||
/* object identifier length (in s32_t) */
|
||||
u8_t ident_len;
|
||||
/* object identifier array */
|
||||
s32_t *ident;
|
||||
|
||||
/* object value ASN1 type */
|
||||
u8_t value_type;
|
||||
/* object value length (in u8_t) */
|
||||
u8_t value_len;
|
||||
/* object value */
|
||||
void *value;
|
||||
|
||||
/* encoding varbind seq length length */
|
||||
u8_t seqlenlen;
|
||||
/* encoding object identifier length length */
|
||||
u8_t olenlen;
|
||||
/* encoding object value length length */
|
||||
u8_t vlenlen;
|
||||
/* encoding varbind seq length */
|
||||
u16_t seqlen;
|
||||
/* encoding object identifier length */
|
||||
u16_t olen;
|
||||
/* encoding object value length */
|
||||
u16_t vlen;
|
||||
};
|
||||
|
||||
struct snmp_varbind_root
|
||||
{
|
||||
struct snmp_varbind *head;
|
||||
struct snmp_varbind *tail;
|
||||
/* number of variable bindings in list */
|
||||
u8_t count;
|
||||
/* encoding varbind-list seq length length */
|
||||
u8_t seqlenlen;
|
||||
/* encoding varbind-list seq length */
|
||||
u16_t seqlen;
|
||||
};
|
||||
|
||||
/** output response message header length fields */
|
||||
struct snmp_resp_header_lengths
|
||||
{
|
||||
/* encoding error-index length length */
|
||||
u8_t erridxlenlen;
|
||||
/* encoding error-status length length */
|
||||
u8_t errstatlenlen;
|
||||
/* encoding request id length length */
|
||||
u8_t ridlenlen;
|
||||
/* encoding pdu length length */
|
||||
u8_t pdulenlen;
|
||||
/* encoding community length length */
|
||||
u8_t comlenlen;
|
||||
/* encoding version length length */
|
||||
u8_t verlenlen;
|
||||
/* encoding sequence length length */
|
||||
u8_t seqlenlen;
|
||||
|
||||
/* encoding error-index length */
|
||||
u16_t erridxlen;
|
||||
/* encoding error-status length */
|
||||
u16_t errstatlen;
|
||||
/* encoding request id length */
|
||||
u16_t ridlen;
|
||||
/* encoding pdu length */
|
||||
u16_t pdulen;
|
||||
/* encoding community length */
|
||||
u16_t comlen;
|
||||
/* encoding version length */
|
||||
u16_t verlen;
|
||||
/* encoding sequence length */
|
||||
u16_t seqlen;
|
||||
};
|
||||
|
||||
/** output response message header length fields */
|
||||
struct snmp_trap_header_lengths
|
||||
{
|
||||
/* encoding timestamp length length */
|
||||
u8_t tslenlen;
|
||||
/* encoding specific-trap length length */
|
||||
u8_t strplenlen;
|
||||
/* encoding generic-trap length length */
|
||||
u8_t gtrplenlen;
|
||||
/* encoding agent-addr length length */
|
||||
u8_t aaddrlenlen;
|
||||
/* encoding enterprise-id length length */
|
||||
u8_t eidlenlen;
|
||||
/* encoding pdu length length */
|
||||
u8_t pdulenlen;
|
||||
/* encoding community length length */
|
||||
u8_t comlenlen;
|
||||
/* encoding version length length */
|
||||
u8_t verlenlen;
|
||||
/* encoding sequence length length */
|
||||
u8_t seqlenlen;
|
||||
|
||||
/* encoding timestamp length */
|
||||
u16_t tslen;
|
||||
/* encoding specific-trap length */
|
||||
u16_t strplen;
|
||||
/* encoding generic-trap length */
|
||||
u16_t gtrplen;
|
||||
/* encoding agent-addr length */
|
||||
u16_t aaddrlen;
|
||||
/* encoding enterprise-id length */
|
||||
u16_t eidlen;
|
||||
/* encoding pdu length */
|
||||
u16_t pdulen;
|
||||
/* encoding community length */
|
||||
u16_t comlen;
|
||||
/* encoding version length */
|
||||
u16_t verlen;
|
||||
/* encoding sequence length */
|
||||
u16_t seqlen;
|
||||
};
|
||||
|
||||
/* Accepting new SNMP messages. */
|
||||
#define SNMP_MSG_EMPTY 0
|
||||
/* Search for matching object for variable binding. */
|
||||
#define SNMP_MSG_SEARCH_OBJ 1
|
||||
/* Perform SNMP operation on in-memory object.
|
||||
Pass-through states, for symmetry only. */
|
||||
#define SNMP_MSG_INTERNAL_GET_OBJDEF 2
|
||||
#define SNMP_MSG_INTERNAL_GET_VALUE 3
|
||||
#define SNMP_MSG_INTERNAL_SET_TEST 4
|
||||
#define SNMP_MSG_INTERNAL_GET_OBJDEF_S 5
|
||||
#define SNMP_MSG_INTERNAL_SET_VALUE 6
|
||||
/* Perform SNMP operation on object located externally.
|
||||
In theory this could be used for building a proxy agent.
|
||||
Practical use is for an enterprise spc. app. gateway. */
|
||||
#define SNMP_MSG_EXTERNAL_GET_OBJDEF 7
|
||||
#define SNMP_MSG_EXTERNAL_GET_VALUE 8
|
||||
#define SNMP_MSG_EXTERNAL_SET_TEST 9
|
||||
#define SNMP_MSG_EXTERNAL_GET_OBJDEF_S 10
|
||||
#define SNMP_MSG_EXTERNAL_SET_VALUE 11
|
||||
|
||||
#define SNMP_COMMUNITY_STR_LEN 64
|
||||
struct snmp_msg_pstat
|
||||
{
|
||||
/* lwIP local port (161) binding */
|
||||
struct udp_pcb *pcb;
|
||||
/* source IP address */
|
||||
struct ip_addr sip;
|
||||
/* source UDP port */
|
||||
u16_t sp;
|
||||
/* request type */
|
||||
u8_t rt;
|
||||
/* request ID */
|
||||
s32_t rid;
|
||||
/* error status */
|
||||
s32_t error_status;
|
||||
/* error index */
|
||||
s32_t error_index;
|
||||
/* community name (zero terminated) */
|
||||
u8_t community[SNMP_COMMUNITY_STR_LEN + 1];
|
||||
/* community string length (exclusive zero term) */
|
||||
u8_t com_strlen;
|
||||
/* one out of MSG_EMPTY, MSG_DEMUX, MSG_INTERNAL, MSG_EXTERNAL_x */
|
||||
u8_t state;
|
||||
/* saved arguments for MSG_EXTERNAL_x */
|
||||
struct mib_external_node *ext_mib_node;
|
||||
struct snmp_name_ptr ext_name_ptr;
|
||||
struct obj_def ext_object_def;
|
||||
struct snmp_obj_id ext_oid;
|
||||
/* index into input variable binding list */
|
||||
u8_t vb_idx;
|
||||
/* ptr into input variable binding list */
|
||||
struct snmp_varbind *vb_ptr;
|
||||
/* list of variable bindings from input */
|
||||
struct snmp_varbind_root invb;
|
||||
/* list of variable bindings to output */
|
||||
struct snmp_varbind_root outvb;
|
||||
/* output response lengths used in ASN encoding */
|
||||
struct snmp_resp_header_lengths rhl;
|
||||
};
|
||||
|
||||
struct snmp_msg_trap
|
||||
{
|
||||
/* lwIP local port (161) binding */
|
||||
struct udp_pcb *pcb;
|
||||
/* destination IP address in network order */
|
||||
struct ip_addr dip;
|
||||
|
||||
/* source enterprise ID (sysObjectID) */
|
||||
struct snmp_obj_id *enterprise;
|
||||
/* source IP address, raw network order format */
|
||||
u8_t sip_raw[4];
|
||||
/* generic trap code */
|
||||
u32_t gen_trap;
|
||||
/* specific trap code */
|
||||
u32_t spc_trap;
|
||||
/* timestamp */
|
||||
u32_t ts;
|
||||
/* list of variable bindings to output */
|
||||
struct snmp_varbind_root outvb;
|
||||
/* output trap lengths used in ASN encoding */
|
||||
struct snmp_trap_header_lengths thl;
|
||||
};
|
||||
|
||||
/** Agent Version constant, 0 = v1 oddity */
|
||||
extern const s32_t snmp_version;
|
||||
/** Agent default "public" community string */
|
||||
extern const char snmp_publiccommunity[7];
|
||||
|
||||
extern struct snmp_msg_trap trap_msg;
|
||||
|
||||
/** Agent setup, start listening to port 161. */
|
||||
void snmp_init(void);
|
||||
void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable);
|
||||
void snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst);
|
||||
|
||||
/** Varbind-list functions. */
|
||||
struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len);
|
||||
void snmp_varbind_free(struct snmp_varbind *vb);
|
||||
void snmp_varbind_list_free(struct snmp_varbind_root *root);
|
||||
void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb);
|
||||
struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root);
|
||||
|
||||
/** Handle an internal (recv) or external (private response) event. */
|
||||
void snmp_msg_event(u8_t request_id);
|
||||
err_t snmp_send_response(struct snmp_msg_pstat *m_stat);
|
||||
err_t snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap);
|
||||
void snmp_coldstart_trap(void);
|
||||
void snmp_authfail_trap(void);
|
||||
|
||||
#endif
|
253
Demo/Common/ethernet/lwIP/include/lwip/snmp_structs.h
Normal file
253
Demo/Common/ethernet/lwIP/include/lwip/snmp_structs.h
Normal file
|
@ -0,0 +1,253 @@
|
|||
/**
|
||||
* @file
|
||||
* Generic MIB tree structures.
|
||||
*
|
||||
* @todo namespace prefixes
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* Author: Christiaan Simons <christiaan.simons@axon.tv>
|
||||
*/
|
||||
|
||||
#ifndef __LWIP_SNMP_STRUCTS_H__
|
||||
#define __LWIP_SNMP_STRUCTS_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#if LWIP_SNMP
|
||||
|
||||
#include "arch/cc.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
#if SNMP_PRIVATE_MIB
|
||||
#include "private_mib.h"
|
||||
#endif
|
||||
|
||||
/* MIB object instance */
|
||||
#define MIB_OBJECT_NONE 0
|
||||
#define MIB_OBJECT_SCALAR 1
|
||||
#define MIB_OBJECT_TAB 2
|
||||
|
||||
/* MIB object access */
|
||||
#define MIB_OBJECT_READ_ONLY 0
|
||||
#define MIB_OBJECT_READ_WRITE 1
|
||||
#define MIB_OBJECT_WRITE_ONLY 2
|
||||
#define MIB_OBJECT_NOT_ACCESSIBLE 3
|
||||
|
||||
/** object definition returned by (get_object_def)() */
|
||||
struct obj_def
|
||||
{
|
||||
/* MIB_OBJECT_NONE (0), MIB_OBJECT_SCALAR (1), MIB_OBJECT_TAB (2) */
|
||||
u8_t instance;
|
||||
/* 0 read-only, 1 read-write, 2 write-only, 3 not-accessible */
|
||||
u8_t access;
|
||||
/* ASN type for this object */
|
||||
u8_t asn_type;
|
||||
/* value length (host length) */
|
||||
u16_t v_len;
|
||||
/* length of instance part of supplied object identifier */
|
||||
u8_t id_inst_len;
|
||||
/* instance part of supplied object identifier */
|
||||
s32_t *id_inst_ptr;
|
||||
};
|
||||
|
||||
struct snmp_name_ptr
|
||||
{
|
||||
u8_t ident_len;
|
||||
s32_t *ident;
|
||||
};
|
||||
|
||||
/** MIB const scalar (.0) node */
|
||||
#define MIB_NODE_SC 0x01
|
||||
/** MIB const array node */
|
||||
#define MIB_NODE_AR 0x02
|
||||
/** MIB array node (mem_malloced from RAM) */
|
||||
#define MIB_NODE_RA 0x03
|
||||
/** MIB list root node (mem_malloced from RAM) */
|
||||
#define MIB_NODE_LR 0x04
|
||||
/** MIB node for external objects */
|
||||
#define MIB_NODE_EX 0x05
|
||||
|
||||
/** node "base class" layout, the mandatory fields for a node */
|
||||
struct mib_node
|
||||
{
|
||||
/** returns struct obj_def for the given object identifier */
|
||||
void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
/** returns object value for the given object identifier,
|
||||
@note the caller must allocate at least len bytes for the value */
|
||||
void (*get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
/** tests length and/or range BEFORE setting */
|
||||
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
|
||||
/** sets object value, only to be called when set_test() */
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
/** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */
|
||||
const u8_t node_type;
|
||||
/* array or max list length */
|
||||
const u16_t maxlength;
|
||||
};
|
||||
|
||||
/** derived node for scalars .0 index */
|
||||
typedef struct mib_node mib_scalar_node;
|
||||
|
||||
/** derived node, points to a fixed size const array
|
||||
of sub-identifiers plus a 'child' pointer */
|
||||
struct mib_array_node
|
||||
{
|
||||
/* inherited "base class" members */
|
||||
void (* const get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (* const get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
const u8_t node_type;
|
||||
const u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
const s32_t *objid;
|
||||
struct mib_node* const *nptr;
|
||||
};
|
||||
|
||||
/** derived node, points to a fixed size mem_malloced array
|
||||
of sub-identifiers plus a 'child' pointer */
|
||||
struct mib_ram_array_node
|
||||
{
|
||||
/* inherited "base class" members */
|
||||
void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (*get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
u8_t node_type;
|
||||
u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
s32_t *objid;
|
||||
struct mib_node **nptr;
|
||||
};
|
||||
|
||||
struct mib_list_node
|
||||
{
|
||||
struct mib_list_node *prev;
|
||||
struct mib_list_node *next;
|
||||
s32_t objid;
|
||||
struct mib_node *nptr;
|
||||
};
|
||||
|
||||
/** derived node, points to a doubly linked list
|
||||
of sub-identifiers plus a 'child' pointer */
|
||||
struct mib_list_rootnode
|
||||
{
|
||||
/* inherited "base class" members */
|
||||
void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (*get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
u8_t node_type;
|
||||
u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
struct mib_list_node *head;
|
||||
struct mib_list_node *tail;
|
||||
/* counts list nodes in list */
|
||||
u16_t count;
|
||||
};
|
||||
|
||||
/** derived node, has access functions for mib object in external memory or device
|
||||
using 'tree_level' and 'idx', with a range 0 .. (level_length() - 1) */
|
||||
struct mib_external_node
|
||||
{
|
||||
/* inherited "base class" members */
|
||||
void (*get_object_def)(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (*get_value)(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
|
||||
void (*set_value)(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
u8_t node_type;
|
||||
u16_t maxlength;
|
||||
|
||||
/* aditional struct members */
|
||||
/** points to an extenal (in memory) record of some sort of addressing
|
||||
information, passed to and interpreted by the funtions below */
|
||||
void* addr_inf;
|
||||
/** tree levels under this node */
|
||||
u8_t tree_levels;
|
||||
/** number of objects at this level */
|
||||
u16_t (*level_length)(void* addr_inf, u8_t level);
|
||||
/** compares object sub identifier with external id
|
||||
return zero when equal, nonzero when unequal */
|
||||
s32_t (*ident_cmp)(void* addr_inf, u8_t level, u16_t idx, s32_t sub_id);
|
||||
void (*get_objid)(void* addr_inf, u8_t level, u16_t idx, s32_t *sub_id);
|
||||
|
||||
/** async Questions */
|
||||
void (*get_object_def_q)(void* addr_inf, u8_t rid, u8_t ident_len, s32_t *ident);
|
||||
void (*get_value_q)(u8_t rid, struct obj_def *od);
|
||||
void (*set_test_q)(u8_t rid, struct obj_def *od);
|
||||
void (*set_value_q)(u8_t rid, struct obj_def *od, u16_t len, void *value);
|
||||
/** async Answers */
|
||||
void (*get_object_def_a)(u8_t rid, u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value);
|
||||
u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value);
|
||||
void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value);
|
||||
/** async Panic Close (agent returns error reply,
|
||||
e.g. used for external transaction cleanup) */
|
||||
void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident);
|
||||
void (*get_value_pc)(u8_t rid, struct obj_def *od);
|
||||
void (*set_test_pc)(u8_t rid, struct obj_def *od);
|
||||
void (*set_value_pc)(u8_t rid, struct obj_def *od);
|
||||
};
|
||||
|
||||
/** export MIB tree from mib2.c */
|
||||
extern const struct mib_array_node internet;
|
||||
|
||||
/** dummy function pointers for non-leaf MIB nodes from mib2.c */
|
||||
void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
|
||||
void noleafs_get_value(struct obj_def *od, u16_t len, void *value);
|
||||
u8_t noleafs_set_test(struct obj_def *od, u16_t len, void *value);
|
||||
void noleafs_set_value(struct obj_def *od, u16_t len, void *value);
|
||||
|
||||
void snmp_oidtoip(s32_t *ident, struct ip_addr *ip);
|
||||
void snmp_iptooid(struct ip_addr *ip, s32_t *ident);
|
||||
void snmp_ifindextonetif(s32_t ifindex, struct netif **netif);
|
||||
void snmp_netiftoifindex(struct netif *netif, s32_t *ifidx);
|
||||
|
||||
struct mib_list_node* snmp_mib_ln_alloc(s32_t id);
|
||||
void snmp_mib_ln_free(struct mib_list_node *ln);
|
||||
struct mib_list_rootnode* snmp_mib_lrn_alloc(void);
|
||||
void snmp_mib_lrn_free(struct mib_list_rootnode *lrn);
|
||||
|
||||
s8_t snmp_mib_node_insert(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **insn);
|
||||
s8_t snmp_mib_node_find(struct mib_list_rootnode *rn, s32_t objid, struct mib_list_node **fn);
|
||||
struct mib_list_rootnode *snmp_mib_node_delete(struct mib_list_rootnode *rn, struct mib_list_node *n);
|
||||
|
||||
struct mib_node* snmp_search_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_name_ptr *np);
|
||||
struct mib_node* snmp_expand_tree(struct mib_node *node, u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret);
|
||||
u8_t snmp_iso_prefix_tst(u8_t ident_len, s32_t *ident);
|
||||
u8_t snmp_iso_prefix_expand(u8_t ident_len, s32_t *ident, struct snmp_obj_id *oidret);
|
||||
|
||||
#endif /* LWIP_SNMP */
|
||||
#endif
|
271
Demo/Common/ethernet/lwIP/include/lwip/sockets.h
Normal file
271
Demo/Common/ethernet/lwIP/include/lwip/sockets.h
Normal file
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __LWIP_SOCKETS_H__
|
||||
#define __LWIP_SOCKETS_H__
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
struct sockaddr_in {
|
||||
u8_t sin_len;
|
||||
u8_t sin_family;
|
||||
u16_t sin_port;
|
||||
struct in_addr sin_addr;
|
||||
char sin_zero[8];
|
||||
};
|
||||
|
||||
struct sockaddr {
|
||||
u8_t sa_len;
|
||||
u8_t sa_family;
|
||||
char sa_data[14];
|
||||
};
|
||||
|
||||
#ifndef socklen_t
|
||||
# define socklen_t int
|
||||
#endif
|
||||
|
||||
|
||||
#define SOCK_STREAM 1
|
||||
#define SOCK_DGRAM 2
|
||||
#define SOCK_RAW 3
|
||||
|
||||
/*
|
||||
* Option flags per-socket.
|
||||
*/
|
||||
#define SO_DEBUG 0x0001 /* turn on debugging info recording */
|
||||
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
|
||||
#define SO_REUSEADDR 0x0004 /* allow local address reuse */
|
||||
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
|
||||
#define SO_DONTROUTE 0x0010 /* just use interface addresses */
|
||||
#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
|
||||
#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
|
||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
||||
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
|
||||
|
||||
#define SO_DONTLINGER (int)(~SO_LINGER)
|
||||
|
||||
/*
|
||||
* Additional options, not kept in so_options.
|
||||
*/
|
||||
#define SO_SNDBUF 0x1001 /* send buffer size */
|
||||
#define SO_RCVBUF 0x1002 /* receive buffer size */
|
||||
#define SO_SNDLOWAT 0x1003 /* send low-water mark */
|
||||
#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_ERROR 0x1007 /* get error status and clear */
|
||||
#define SO_TYPE 0x1008 /* get socket type */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Structure used for manipulating linger option.
|
||||
*/
|
||||
struct linger {
|
||||
int l_onoff; /* option on/off */
|
||||
int l_linger; /* linger time */
|
||||
};
|
||||
|
||||
/*
|
||||
* Level number for (get/set)sockopt() to apply to socket itself.
|
||||
*/
|
||||
#define SOL_SOCKET 0xfff /* options for socket level */
|
||||
|
||||
|
||||
#define AF_UNSPEC 0
|
||||
#define AF_INET 2
|
||||
#define PF_INET AF_INET
|
||||
#define PF_UNSPEC AF_UNSPEC
|
||||
|
||||
#define IPPROTO_IP 0
|
||||
#define IPPROTO_TCP 6
|
||||
#define IPPROTO_UDP 17
|
||||
|
||||
#define INADDR_ANY 0
|
||||
#define INADDR_BROADCAST 0xffffffff
|
||||
|
||||
/* Flags we can use with send and recv. */
|
||||
#define MSG_DONTWAIT 0x40 /* Nonblocking i/o for this operation only */
|
||||
|
||||
|
||||
/*
|
||||
* Options for level IPPROTO_IP
|
||||
*/
|
||||
#define IP_TOS 1
|
||||
#define IP_TTL 2
|
||||
|
||||
|
||||
#define IPTOS_TOS_MASK 0x1E
|
||||
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
|
||||
#define IPTOS_LOWDELAY 0x10
|
||||
#define IPTOS_THROUGHPUT 0x08
|
||||
#define IPTOS_RELIABILITY 0x04
|
||||
#define IPTOS_LOWCOST 0x02
|
||||
#define IPTOS_MINCOST IPTOS_LOWCOST
|
||||
|
||||
/*
|
||||
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
|
||||
*/
|
||||
#define IPTOS_PREC_MASK 0xe0
|
||||
#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK)
|
||||
#define IPTOS_PREC_NETCONTROL 0xe0
|
||||
#define IPTOS_PREC_INTERNETCONTROL 0xc0
|
||||
#define IPTOS_PREC_CRITIC_ECP 0xa0
|
||||
#define IPTOS_PREC_FLASHOVERRIDE 0x80
|
||||
#define IPTOS_PREC_FLASH 0x60
|
||||
#define IPTOS_PREC_IMMEDIATE 0x40
|
||||
#define IPTOS_PREC_PRIORITY 0x20
|
||||
#define IPTOS_PREC_ROUTINE 0x00
|
||||
|
||||
|
||||
/*
|
||||
* Commands for ioctlsocket(), taken from the BSD file fcntl.h.
|
||||
*
|
||||
*
|
||||
* Ioctl's have the command encoded in the lower word,
|
||||
* and the size of any in or out parameters in the upper
|
||||
* word. The high 2 bits of the upper word are used
|
||||
* to encode the in/out status of the parameter; for now
|
||||
* we restrict parameters to at most 128 bytes.
|
||||
*/
|
||||
#if !defined(FIONREAD) || !defined(FIONBIO)
|
||||
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
|
||||
#define IOC_VOID 0x20000000 /* no parameters */
|
||||
#define IOC_OUT 0x40000000 /* copy out parameters */
|
||||
#define IOC_IN 0x80000000 /* copy in parameters */
|
||||
#define IOC_INOUT (IOC_IN|IOC_OUT)
|
||||
/* 0x20000000 distinguishes new &
|
||||
old ioctl's */
|
||||
#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
|
||||
|
||||
#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
|
||||
|
||||
#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
|
||||
#endif
|
||||
|
||||
#ifndef FIONREAD
|
||||
#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */
|
||||
#endif
|
||||
#ifndef FIONBIO
|
||||
#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */
|
||||
#endif
|
||||
|
||||
/* Socket I/O Controls */
|
||||
#ifndef SIOCSHIWAT
|
||||
#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */
|
||||
#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */
|
||||
#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */
|
||||
#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */
|
||||
#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */
|
||||
#endif
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 04000U
|
||||
#endif
|
||||
|
||||
#ifndef FD_SET
|
||||
#undef FD_SETSIZE
|
||||
#define FD_SETSIZE 16
|
||||
#define FD_SET(n, p) ((p)->fd_bits[(n)/8] |= (1 << ((n) & 7)))
|
||||
#define FD_CLR(n, p) ((p)->fd_bits[(n)/8] &= ~(1 << ((n) & 7)))
|
||||
#define FD_ISSET(n,p) ((p)->fd_bits[(n)/8] & (1 << ((n) & 7)))
|
||||
#define FD_ZERO(p) memset((void*)(p),0,sizeof(*(p)))
|
||||
|
||||
typedef struct fd_set {
|
||||
unsigned char fd_bits [(FD_SETSIZE+7)/8];
|
||||
} fd_set;
|
||||
|
||||
/*
|
||||
* only define this in sockets.c so it does not interfere
|
||||
* with other projects namespaces where timeval is present
|
||||
*/
|
||||
#ifndef LWIP_TIMEVAL_PRIVATE
|
||||
#define LWIP_TIMEVAL_PRIVATE 1
|
||||
#endif
|
||||
|
||||
#if LWIP_TIMEVAL_PRIVATE
|
||||
struct timeval {
|
||||
long tv_sec; /* seconds */
|
||||
long tv_usec; /* and microseconds */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen);
|
||||
int lwip_bind(int s, struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_shutdown(int s, int how);
|
||||
int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen);
|
||||
int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen);
|
||||
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen);
|
||||
int lwip_close(int s);
|
||||
int lwip_connect(int s, struct sockaddr *name, socklen_t namelen);
|
||||
int lwip_listen(int s, int backlog);
|
||||
int lwip_recv(int s, void *mem, int len, unsigned int flags);
|
||||
int lwip_read(int s, void *mem, int len);
|
||||
int lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen);
|
||||
int lwip_send(int s, void *dataptr, int size, unsigned int flags);
|
||||
int lwip_sendto(int s, void *dataptr, int size, unsigned int flags,
|
||||
struct sockaddr *to, socklen_t tolen);
|
||||
int lwip_socket(int domain, int type, int protocol);
|
||||
int lwip_write(int s, void *dataptr, int size);
|
||||
int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
||||
struct timeval *timeout);
|
||||
int lwip_ioctl(int s, long cmd, void *argp);
|
||||
|
||||
#if LWIP_COMPAT_SOCKETS
|
||||
#define accept(a,b,c) lwip_accept(a,b,c)
|
||||
#define bind(a,b,c) lwip_bind(a,b,c)
|
||||
#define shutdown(a,b) lwip_shutdown(a,b)
|
||||
#define close(s) lwip_close(s)
|
||||
#define connect(a,b,c) lwip_connect(a,b,c)
|
||||
#define getsockname(a,b,c) lwip_getsockname(a,b,c)
|
||||
#define getpeername(a,b,c) lwip_getpeername(a,b,c)
|
||||
#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e)
|
||||
#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e)
|
||||
#define listen(a,b) lwip_listen(a,b)
|
||||
#define recv(a,b,c,d) lwip_recv(a,b,c,d)
|
||||
#define read(a,b,c) lwip_read(a,b,c)
|
||||
#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
|
||||
#define send(a,b,c,d) lwip_send(a,b,c,d)
|
||||
#define sendto(a,b,c,d,e,f) lwip_sendto(a,b,c,d,e,f)
|
||||
#define socket(a,b,c) lwip_socket(a,b,c)
|
||||
#define write(a,b,c) lwip_write(a,b,c)
|
||||
#define select(a,b,c,d,e) lwip_select(a,b,c,d,e)
|
||||
#define ioctlsocket(a,b,c) lwip_ioctl(a,b,c)
|
||||
#endif /* LWIP_COMPAT_SOCKETS */
|
||||
|
||||
#endif /* __LWIP_SOCKETS_H__ */
|
||||
|
158
Demo/Common/ethernet/lwIP/include/lwip/stats.h
Normal file
158
Demo/Common/ethernet/lwIP/include/lwip/stats.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_STATS_H__
|
||||
#define __LWIP_STATS_H__
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "arch/cc.h"
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/memp.h"
|
||||
|
||||
#if LWIP_STATS
|
||||
|
||||
struct stats_proto {
|
||||
u16_t xmit; /* Transmitted packets. */
|
||||
u16_t rexmit; /* Retransmitted packets. */
|
||||
u16_t recv; /* Received packets. */
|
||||
u16_t fw; /* Forwarded packets. */
|
||||
u16_t drop; /* Dropped packets. */
|
||||
u16_t chkerr; /* Checksum error. */
|
||||
u16_t lenerr; /* Invalid length error. */
|
||||
u16_t memerr; /* Out of memory error. */
|
||||
u16_t rterr; /* Routing error. */
|
||||
u16_t proterr; /* Protocol error. */
|
||||
u16_t opterr; /* Error in options. */
|
||||
u16_t err; /* Misc error. */
|
||||
u16_t cachehit;
|
||||
};
|
||||
|
||||
struct stats_mem {
|
||||
mem_size_t avail;
|
||||
mem_size_t used;
|
||||
mem_size_t max;
|
||||
mem_size_t err;
|
||||
};
|
||||
|
||||
struct stats_pbuf {
|
||||
u16_t avail;
|
||||
u16_t used;
|
||||
u16_t max;
|
||||
u16_t err;
|
||||
|
||||
u16_t alloc_locked;
|
||||
u16_t refresh_locked;
|
||||
};
|
||||
|
||||
struct stats_syselem {
|
||||
u16_t used;
|
||||
u16_t max;
|
||||
u16_t err;
|
||||
};
|
||||
|
||||
struct stats_sys {
|
||||
struct stats_syselem sem;
|
||||
struct stats_syselem mbox;
|
||||
};
|
||||
|
||||
struct stats_ {
|
||||
struct stats_proto link;
|
||||
struct stats_proto ip_frag;
|
||||
struct stats_proto ip;
|
||||
struct stats_proto icmp;
|
||||
struct stats_proto udp;
|
||||
struct stats_proto tcp;
|
||||
struct stats_pbuf pbuf;
|
||||
struct stats_mem mem;
|
||||
struct stats_mem memp[MEMP_MAX];
|
||||
struct stats_sys sys;
|
||||
};
|
||||
|
||||
extern struct stats_ lwip_stats;
|
||||
|
||||
|
||||
void stats_init(void);
|
||||
|
||||
#define STATS_INC(x) ++lwip_stats.x
|
||||
#else
|
||||
#define stats_init()
|
||||
#define STATS_INC(x)
|
||||
#endif /* LWIP_STATS */
|
||||
|
||||
#if TCP_STATS
|
||||
#define TCP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define TCP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if UDP_STATS
|
||||
#define UDP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define UDP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if ICMP_STATS
|
||||
#define ICMP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define ICMP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if IP_STATS
|
||||
#define IP_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define IP_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if IPFRAG_STATS
|
||||
#define IPFRAG_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define IPFRAG_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
#if LINK_STATS
|
||||
#define LINK_STATS_INC(x) STATS_INC(x)
|
||||
#else
|
||||
#define LINK_STATS_INC(x)
|
||||
#endif
|
||||
|
||||
/* Display of statistics */
|
||||
#if LWIP_STATS_DISPLAY
|
||||
void stats_display(void);
|
||||
#else
|
||||
#define stats_display()
|
||||
#endif
|
||||
|
||||
#endif /* __LWIP_STATS_H__ */
|
||||
|
||||
|
||||
|
||||
|
183
Demo/Common/ethernet/lwIP/include/lwip/sys.h
Normal file
183
Demo/Common/ethernet/lwIP/include/lwip/sys.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_SYS_H__
|
||||
#define __LWIP_SYS_H__
|
||||
|
||||
#include "arch/cc.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
|
||||
#if NO_SYS
|
||||
|
||||
/* For a totally minimal and standalone system, we provide null
|
||||
definitions of the sys_ functions. */
|
||||
typedef u8_t sys_sem_t;
|
||||
typedef u8_t sys_mbox_t;
|
||||
struct sys_timeo {u8_t dummy;};
|
||||
|
||||
#define sys_init()
|
||||
#define sys_timeout(m,h,a)
|
||||
#define sys_untimeout(m,a)
|
||||
#define sys_sem_new(c) c
|
||||
#define sys_sem_signal(s)
|
||||
#define sys_sem_wait(s)
|
||||
#define sys_sem_free(s)
|
||||
#define sys_mbox_new() 0
|
||||
#define sys_mbox_fetch(m,d)
|
||||
#define sys_mbox_post(m,d)
|
||||
#define sys_mbox_free(m)
|
||||
|
||||
#define sys_thread_new(t,a,p)
|
||||
|
||||
#else /* NO_SYS */
|
||||
|
||||
#include "arch/sys_arch.h"
|
||||
|
||||
/** Return code for timeouts from sys_arch_mbox_fetch and sys_arch_sem_wait */
|
||||
#define SYS_ARCH_TIMEOUT 0xffffffff
|
||||
|
||||
typedef void (* sys_timeout_handler)(void *arg);
|
||||
|
||||
struct sys_timeo {
|
||||
struct sys_timeo *next;
|
||||
u32_t time;
|
||||
sys_timeout_handler h;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct sys_timeouts {
|
||||
struct sys_timeo *next;
|
||||
};
|
||||
|
||||
/* sys_init() must be called before anthing else. */
|
||||
void sys_init(void);
|
||||
|
||||
/*
|
||||
* sys_timeout():
|
||||
*
|
||||
* Schedule a timeout a specified amount of milliseconds in the
|
||||
* future. When the timeout occurs, the specified timeout handler will
|
||||
* be called. The handler will be passed the "arg" argument when
|
||||
* called.
|
||||
*
|
||||
*/
|
||||
void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg);
|
||||
void sys_untimeout(sys_timeout_handler h, void *arg);
|
||||
struct sys_timeouts *sys_arch_timeouts(void);
|
||||
|
||||
/* Semaphore functions. */
|
||||
sys_sem_t sys_sem_new(u8_t count);
|
||||
void sys_sem_signal(sys_sem_t sem);
|
||||
u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout);
|
||||
void sys_sem_free(sys_sem_t sem);
|
||||
void sys_sem_wait(sys_sem_t sem);
|
||||
int sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout);
|
||||
|
||||
/* Time functions. */
|
||||
#ifndef sys_msleep
|
||||
void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */
|
||||
#endif
|
||||
#ifndef sys_jiffies
|
||||
u32_t sys_jiffies(void); /* since power up. */
|
||||
#endif
|
||||
|
||||
/* Mailbox functions. */
|
||||
sys_mbox_t sys_mbox_new(void);
|
||||
void sys_mbox_post(sys_mbox_t mbox, void *msg);
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout);
|
||||
void sys_mbox_free(sys_mbox_t mbox);
|
||||
void sys_mbox_fetch(sys_mbox_t mbox, void **msg);
|
||||
|
||||
|
||||
/* Thread functions. */
|
||||
sys_thread_t sys_thread_new(void (* thread)(void *arg), void *arg, int prio);
|
||||
|
||||
/* The following functions are used only in Unix code, and
|
||||
can be omitted when porting the stack. */
|
||||
/* Returns the current time in microseconds. */
|
||||
unsigned long sys_now(void);
|
||||
|
||||
#endif /* NO_SYS */
|
||||
|
||||
/* Critical Region Protection */
|
||||
/* These functions must be implemented in the sys_arch.c file.
|
||||
In some implementations they can provide a more light-weight protection
|
||||
mechanism than using semaphores. Otherwise semaphores can be used for
|
||||
implementation */
|
||||
#ifndef SYS_ARCH_PROTECT
|
||||
/** SYS_LIGHTWEIGHT_PROT
|
||||
* define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
|
||||
* for certain critical regions during buffer allocation, deallocation and memory
|
||||
* allocation and deallocation.
|
||||
*/
|
||||
#if SYS_LIGHTWEIGHT_PROT
|
||||
|
||||
/** SYS_ARCH_DECL_PROTECT
|
||||
* declare a protection variable. This macro will default to defining a variable of
|
||||
* type sys_prot_t. If a particular port needs a different implementation, then
|
||||
* this macro may be defined in sys_arch.h.
|
||||
*/
|
||||
#define SYS_ARCH_DECL_PROTECT(lev) sys_prot_t lev
|
||||
/** SYS_ARCH_PROTECT
|
||||
* Perform a "fast" protect. This could be implemented by
|
||||
* disabling interrupts for an embedded system or by using a semaphore or
|
||||
* mutex. The implementation should allow calling SYS_ARCH_PROTECT when
|
||||
* already protected. The old protection level is returned in the variable
|
||||
* "lev". This macro will default to calling the sys_arch_protect() function
|
||||
* which should be implemented in sys_arch.c. If a particular port needs a
|
||||
* different implementation, then this macro may be defined in sys_arch.h
|
||||
*/
|
||||
#define SYS_ARCH_PROTECT(lev) lev = sys_arch_protect()
|
||||
/** SYS_ARCH_UNPROTECT
|
||||
* Perform a "fast" set of the protection level to "lev". This could be
|
||||
* implemented by setting the interrupt level to "lev" within the MACRO or by
|
||||
* using a semaphore or mutex. This macro will default to calling the
|
||||
* sys_arch_unprotect() function which should be implemented in
|
||||
* sys_arch.c. If a particular port needs a different implementation, then
|
||||
* this macro may be defined in sys_arch.h
|
||||
*/
|
||||
#define SYS_ARCH_UNPROTECT(lev) sys_arch_unprotect(lev)
|
||||
sys_prot_t sys_arch_protect(void);
|
||||
void sys_arch_unprotect(sys_prot_t pval);
|
||||
|
||||
#else
|
||||
|
||||
#define SYS_ARCH_DECL_PROTECT(lev)
|
||||
#define SYS_ARCH_PROTECT(lev)
|
||||
#define SYS_ARCH_UNPROTECT(lev)
|
||||
|
||||
#endif /* SYS_LIGHTWEIGHT_PROT */
|
||||
|
||||
#endif /* SYS_ARCH_PROTECT */
|
||||
|
||||
#endif /* __LWIP_SYS_H__ */
|
531
Demo/Common/ethernet/lwIP/include/lwip/tcp.h
Normal file
531
Demo/Common/ethernet/lwIP/include/lwip/tcp.h
Normal file
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_TCP_H__
|
||||
#define __LWIP_TCP_H__
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/icmp.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
|
||||
struct tcp_pcb;
|
||||
|
||||
/* Functions for interfacing with TCP: */
|
||||
|
||||
/* Lower layer interface to TCP: */
|
||||
void tcp_init (void); /* Must be called first to
|
||||
initialize TCP. */
|
||||
void tcp_tmr (void); /* Must be called every
|
||||
TCP_TMR_INTERVAL
|
||||
ms. (Typically 250 ms). */
|
||||
/* Application program's interface: */
|
||||
struct tcp_pcb * tcp_new (void);
|
||||
struct tcp_pcb * tcp_alloc (u8_t prio);
|
||||
|
||||
void tcp_arg (struct tcp_pcb *pcb, void *arg);
|
||||
void tcp_accept (struct tcp_pcb *pcb,
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb,
|
||||
err_t err));
|
||||
void tcp_recv (struct tcp_pcb *pcb,
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *tpcb,
|
||||
struct pbuf *p, err_t err));
|
||||
void tcp_sent (struct tcp_pcb *pcb,
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *tpcb,
|
||||
u16_t len));
|
||||
void tcp_poll (struct tcp_pcb *pcb,
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *tpcb),
|
||||
u8_t interval);
|
||||
void tcp_err (struct tcp_pcb *pcb,
|
||||
void (* err)(void *arg, err_t err));
|
||||
|
||||
#define tcp_mss(pcb) ((pcb)->mss)
|
||||
#define tcp_sndbuf(pcb) ((pcb)->snd_buf)
|
||||
|
||||
void tcp_recved (struct tcp_pcb *pcb, u16_t len);
|
||||
err_t tcp_bind (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
err_t tcp_connect (struct tcp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port, err_t (* connected)(void *arg,
|
||||
struct tcp_pcb *tpcb,
|
||||
err_t err));
|
||||
struct tcp_pcb * tcp_listen (struct tcp_pcb *pcb);
|
||||
void tcp_abort (struct tcp_pcb *pcb);
|
||||
err_t tcp_close (struct tcp_pcb *pcb);
|
||||
err_t tcp_write (struct tcp_pcb *pcb, const void *dataptr, u16_t len,
|
||||
u8_t copy);
|
||||
|
||||
void tcp_setprio (struct tcp_pcb *pcb, u8_t prio);
|
||||
|
||||
#define TCP_PRIO_MIN 1
|
||||
#define TCP_PRIO_NORMAL 64
|
||||
#define TCP_PRIO_MAX 127
|
||||
|
||||
/* It is also possible to call these two functions at the right
|
||||
intervals (instead of calling tcp_tmr()). */
|
||||
void tcp_slowtmr (void);
|
||||
void tcp_fasttmr (void);
|
||||
|
||||
|
||||
/* Only used by IP to pass a TCP segment to TCP: */
|
||||
void tcp_input (struct pbuf *p, struct netif *inp);
|
||||
/* Used within the TCP code only: */
|
||||
err_t tcp_output (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit (struct tcp_pcb *pcb);
|
||||
void tcp_rexmit_rto (struct tcp_pcb *pcb);
|
||||
|
||||
|
||||
|
||||
#define TCP_SEQ_LT(a,b) ((s32_t)((a)-(b)) < 0)
|
||||
#define TCP_SEQ_LEQ(a,b) ((s32_t)((a)-(b)) <= 0)
|
||||
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
|
||||
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
|
||||
/* is b<=a<=c? */
|
||||
#if 0 /* see bug #10548 */
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) ((c)-(b) >= (a)-(b))
|
||||
#endif
|
||||
#define TCP_SEQ_BETWEEN(a,b,c) (TCP_SEQ_GEQ(a,b) && TCP_SEQ_LEQ(a,c))
|
||||
#define TCP_FIN 0x01U
|
||||
#define TCP_SYN 0x02U
|
||||
#define TCP_RST 0x04U
|
||||
#define TCP_PSH 0x08U
|
||||
#define TCP_ACK 0x10U
|
||||
#define TCP_URG 0x20U
|
||||
#define TCP_ECE 0x40U
|
||||
#define TCP_CWR 0x80U
|
||||
|
||||
#define TCP_FLAGS 0x3fU
|
||||
|
||||
/* Length of the TCP header, excluding options. */
|
||||
#define TCP_HLEN 20
|
||||
|
||||
#ifndef TCP_TMR_INTERVAL
|
||||
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in
|
||||
milliseconds. */
|
||||
#endif /* TCP_TMR_INTERVAL */
|
||||
|
||||
#ifndef TCP_FAST_INTERVAL
|
||||
#define TCP_FAST_INTERVAL TCP_TMR_INTERVAL /* the fine grained timeout in
|
||||
milliseconds */
|
||||
#endif /* TCP_FAST_INTERVAL */
|
||||
|
||||
#ifndef TCP_SLOW_INTERVAL
|
||||
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in
|
||||
milliseconds */
|
||||
#endif /* TCP_SLOW_INTERVAL */
|
||||
|
||||
#define TCP_FIN_WAIT_TIMEOUT 20000 /* milliseconds */
|
||||
#define TCP_SYN_RCVD_TIMEOUT 20000 /* milliseconds */
|
||||
|
||||
#define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
|
||||
|
||||
#define TCP_MSL 60000 /* The maximum segment lifetime in microseconds */
|
||||
|
||||
/*
|
||||
* User-settable options (used with setsockopt).
|
||||
*/
|
||||
#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
|
||||
#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keepalive miliseconds */
|
||||
|
||||
/* Keepalive values */
|
||||
#define TCP_KEEPDEFAULT 7200000 /* KEEPALIVE timer in miliseconds */
|
||||
#define TCP_KEEPINTVL 75000 /* Time between KEEPALIVE probes in miliseconds */
|
||||
#define TCP_KEEPCNT 9 /* Counter for KEEPALIVE probes */
|
||||
#define TCP_MAXIDLE TCP_KEEPCNT * TCP_KEEPINTVL /* Maximum KEEPALIVE probe time */
|
||||
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct tcp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t src);
|
||||
PACK_STRUCT_FIELD(u16_t dest);
|
||||
PACK_STRUCT_FIELD(u32_t seqno);
|
||||
PACK_STRUCT_FIELD(u32_t ackno);
|
||||
PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
|
||||
PACK_STRUCT_FIELD(u16_t wnd);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
PACK_STRUCT_FIELD(u16_t urgp);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#define TCPH_OFFSET(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 8)
|
||||
#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
|
||||
#define TCPH_FLAGS(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
|
||||
|
||||
#define TCPH_OFFSET_SET(phdr, offset) (phdr)->_hdrlen_rsvd_flags = htons(((offset) << 8) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
|
||||
#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons((ntohs((phdr)->_hdrlen_rsvd_flags) & ~TCP_FLAGS) | (flags))
|
||||
#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (flags))
|
||||
#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
|
||||
|
||||
#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & TCP_FIN || \
|
||||
TCPH_FLAGS((seg)->tcphdr) & TCP_SYN)? 1: 0))
|
||||
|
||||
enum tcp_state {
|
||||
CLOSED = 0,
|
||||
LISTEN = 1,
|
||||
SYN_SENT = 2,
|
||||
SYN_RCVD = 3,
|
||||
ESTABLISHED = 4,
|
||||
FIN_WAIT_1 = 5,
|
||||
FIN_WAIT_2 = 6,
|
||||
CLOSE_WAIT = 7,
|
||||
CLOSING = 8,
|
||||
LAST_ACK = 9,
|
||||
TIME_WAIT = 10
|
||||
};
|
||||
|
||||
/* the TCP protocol control block */
|
||||
struct tcp_pcb {
|
||||
/** common PCB members */
|
||||
IP_PCB;
|
||||
/** protocol specific PCB members */
|
||||
struct tcp_pcb *next; /* for the linked list */
|
||||
enum tcp_state state; /* TCP state */
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
u16_t local_port;
|
||||
u16_t remote_port;
|
||||
|
||||
u8_t flags;
|
||||
#define TF_ACK_DELAY (u8_t)0x01U /* Delayed ACK. */
|
||||
#define TF_ACK_NOW (u8_t)0x02U /* Immediate ACK. */
|
||||
#define TF_INFR (u8_t)0x04U /* In fast recovery. */
|
||||
#define TF_RESET (u8_t)0x08U /* Connection was reset. */
|
||||
#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */
|
||||
#define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */
|
||||
#define TF_NODELAY (u8_t)0x40U /* Disable Nagle algorithm */
|
||||
|
||||
/* receiver variables */
|
||||
u32_t rcv_nxt; /* next seqno expected */
|
||||
u16_t rcv_wnd; /* receiver window */
|
||||
|
||||
/* Timers */
|
||||
u32_t tmr;
|
||||
u8_t polltmr, pollinterval;
|
||||
|
||||
/* Retransmission timer. */
|
||||
u16_t rtime;
|
||||
|
||||
u16_t mss; /* maximum segment size */
|
||||
|
||||
/* RTT (round trip time) estimation variables */
|
||||
u32_t rttest; /* RTT estimate in 500ms ticks */
|
||||
u32_t rtseq; /* sequence number being timed */
|
||||
s16_t sa, sv; /* @todo document this */
|
||||
|
||||
u16_t rto; /* retransmission time-out */
|
||||
u8_t nrtx; /* number of retransmissions */
|
||||
|
||||
/* fast retransmit/recovery */
|
||||
u32_t lastack; /* Highest acknowledged seqno. */
|
||||
u8_t dupacks;
|
||||
|
||||
/* congestion avoidance/control variables */
|
||||
u16_t cwnd;
|
||||
u16_t ssthresh;
|
||||
|
||||
/* sender variables */
|
||||
u32_t snd_nxt, /* next seqno to be sent */
|
||||
snd_max, /* Highest seqno sent. */
|
||||
snd_wnd, /* sender window */
|
||||
snd_wl1, snd_wl2, /* Sequence and acknowledgement numbers of last
|
||||
window update. */
|
||||
snd_lbb; /* Sequence number of next byte to be buffered. */
|
||||
|
||||
u16_t acked;
|
||||
|
||||
u16_t snd_buf; /* Available buffer space for sending (in bytes). */
|
||||
u8_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
|
||||
|
||||
|
||||
/* These are ordered by sequence number: */
|
||||
struct tcp_seg *unsent; /* Unsent (queued) segments. */
|
||||
struct tcp_seg *unacked; /* Sent but unacknowledged segments. */
|
||||
#if TCP_QUEUE_OOSEQ
|
||||
struct tcp_seg *ooseq; /* Received out of sequence segments. */
|
||||
#endif /* TCP_QUEUE_OOSEQ */
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to be called when more send buffer space is available. */
|
||||
err_t (* sent)(void *arg, struct tcp_pcb *pcb, u16_t space);
|
||||
|
||||
/* Function to be called when (in-sequence) data has arrived. */
|
||||
err_t (* recv)(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err);
|
||||
|
||||
/* Function to be called when a connection has been set up. */
|
||||
err_t (* connected)(void *arg, struct tcp_pcb *pcb, err_t err);
|
||||
|
||||
/* Function to call when a listener has been connected. */
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
|
||||
/* Function which is called periodically. */
|
||||
err_t (* poll)(void *arg, struct tcp_pcb *pcb);
|
||||
|
||||
/* Function to be called whenever a fatal error occurs. */
|
||||
void (* errf)(void *arg, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
|
||||
/* idle time before KEEPALIVE is sent */
|
||||
u32_t keepalive;
|
||||
|
||||
/* KEEPALIVE counter */
|
||||
u8_t keep_cnt;
|
||||
};
|
||||
|
||||
struct tcp_pcb_listen {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
struct tcp_pcb_listen *next; /* for the linked list */
|
||||
|
||||
/* Even if state is obviously LISTEN this is here for
|
||||
* field compatibility with tpc_pcb to which it is cast sometimes
|
||||
* Until a cleaner solution emerges this is here.FIXME
|
||||
*/
|
||||
enum tcp_state state; /* TCP state */
|
||||
|
||||
u8_t prio;
|
||||
void *callback_arg;
|
||||
|
||||
u16_t local_port;
|
||||
|
||||
#if LWIP_CALLBACK_API
|
||||
/* Function to call when a listener has been connected. */
|
||||
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err);
|
||||
#endif /* LWIP_CALLBACK_API */
|
||||
};
|
||||
|
||||
#if LWIP_EVENT_API
|
||||
|
||||
enum lwip_event {
|
||||
LWIP_EVENT_ACCEPT,
|
||||
LWIP_EVENT_SENT,
|
||||
LWIP_EVENT_RECV,
|
||||
LWIP_EVENT_CONNECTED,
|
||||
LWIP_EVENT_POLL,
|
||||
LWIP_EVENT_ERR
|
||||
};
|
||||
|
||||
err_t lwip_tcp_event(void *arg, struct tcp_pcb *pcb,
|
||||
enum lwip_event,
|
||||
struct pbuf *p,
|
||||
u16_t size,
|
||||
err_t err);
|
||||
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_ACCEPT, NULL, 0, err)
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_SENT, NULL, space, ERR_OK)
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_RECV, (p), 0, (err))
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_CONNECTED, NULL, 0, (err))
|
||||
#define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\
|
||||
LWIP_EVENT_POLL, NULL, 0, ERR_OK)
|
||||
#define TCP_EVENT_ERR(errf,arg,err) lwip_tcp_event((arg), NULL, \
|
||||
LWIP_EVENT_ERR, NULL, 0, (err))
|
||||
#else /* LWIP_EVENT_API */
|
||||
#define TCP_EVENT_ACCEPT(pcb,err,ret) \
|
||||
if((pcb)->accept != NULL) \
|
||||
(ret = (pcb)->accept((pcb)->callback_arg,(pcb),(err)))
|
||||
#define TCP_EVENT_SENT(pcb,space,ret) \
|
||||
if((pcb)->sent != NULL) \
|
||||
(ret = (pcb)->sent((pcb)->callback_arg,(pcb),(space)))
|
||||
#define TCP_EVENT_RECV(pcb,p,err,ret) \
|
||||
if((pcb)->recv != NULL) \
|
||||
{ ret = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); } else { \
|
||||
if (p) pbuf_free(p); }
|
||||
#define TCP_EVENT_CONNECTED(pcb,err,ret) \
|
||||
if((pcb)->connected != NULL) \
|
||||
(ret = (pcb)->connected((pcb)->callback_arg,(pcb),(err)))
|
||||
#define TCP_EVENT_POLL(pcb,ret) \
|
||||
if((pcb)->poll != NULL) \
|
||||
(ret = (pcb)->poll((pcb)->callback_arg,(pcb)))
|
||||
#define TCP_EVENT_ERR(errf,arg,err) \
|
||||
if((errf) != NULL) \
|
||||
(errf)((arg),(err))
|
||||
#endif /* LWIP_EVENT_API */
|
||||
|
||||
/* This structure represents a TCP segment on the unsent and unacked queues */
|
||||
struct tcp_seg {
|
||||
struct tcp_seg *next; /* used when putting segements on a queue */
|
||||
struct pbuf *p; /* buffer containing data + TCP header */
|
||||
void *dataptr; /* pointer to the TCP data in the pbuf */
|
||||
u16_t len; /* the TCP length of this segment */
|
||||
struct tcp_hdr *tcphdr; /* the TCP header */
|
||||
};
|
||||
|
||||
/* Internal functions and global variables: */
|
||||
struct tcp_pcb *tcp_pcb_copy(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_purge(struct tcp_pcb *pcb);
|
||||
void tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb);
|
||||
|
||||
u8_t tcp_segs_free(struct tcp_seg *seg);
|
||||
u8_t tcp_seg_free(struct tcp_seg *seg);
|
||||
struct tcp_seg *tcp_seg_copy(struct tcp_seg *seg);
|
||||
|
||||
#define tcp_ack(pcb) if((pcb)->flags & TF_ACK_DELAY) { \
|
||||
(pcb)->flags &= ~TF_ACK_DELAY; \
|
||||
(pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb); \
|
||||
} else { \
|
||||
(pcb)->flags |= TF_ACK_DELAY; \
|
||||
}
|
||||
|
||||
#define tcp_ack_now(pcb) (pcb)->flags |= TF_ACK_NOW; \
|
||||
tcp_output(pcb)
|
||||
|
||||
err_t tcp_send_ctrl(struct tcp_pcb *pcb, u8_t flags);
|
||||
err_t tcp_enqueue(struct tcp_pcb *pcb, void *dataptr, u16_t len,
|
||||
u8_t flags, u8_t copy,
|
||||
u8_t *optdata, u8_t optlen);
|
||||
|
||||
void tcp_rexmit_seg(struct tcp_pcb *pcb, struct tcp_seg *seg);
|
||||
|
||||
void tcp_rst(u32_t seqno, u32_t ackno,
|
||||
struct ip_addr *local_ip, struct ip_addr *remote_ip,
|
||||
u16_t local_port, u16_t remote_port);
|
||||
|
||||
u32_t tcp_next_iss(void);
|
||||
|
||||
void tcp_keepalive(struct tcp_pcb *pcb);
|
||||
|
||||
extern struct tcp_pcb *tcp_input_pcb;
|
||||
extern u32_t tcp_ticks;
|
||||
|
||||
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
|
||||
void tcp_debug_print(struct tcp_hdr *tcphdr);
|
||||
void tcp_debug_print_flags(u8_t flags);
|
||||
void tcp_debug_print_state(enum tcp_state s);
|
||||
void tcp_debug_print_pcbs(void);
|
||||
s16_t tcp_pcbs_sane(void);
|
||||
#else
|
||||
# define tcp_debug_print(tcphdr)
|
||||
# define tcp_debug_print_flags(flags)
|
||||
# define tcp_debug_print_state(s)
|
||||
# define tcp_debug_print_pcbs()
|
||||
# define tcp_pcbs_sane() 1
|
||||
#endif /* TCP_DEBUG */
|
||||
|
||||
#if NO_SYS
|
||||
#define tcp_timer_needed()
|
||||
#else
|
||||
void tcp_timer_needed(void);
|
||||
#endif
|
||||
|
||||
/* The TCP PCB lists. */
|
||||
union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
|
||||
struct tcp_pcb_listen *listen_pcbs;
|
||||
struct tcp_pcb *pcbs;
|
||||
};
|
||||
extern union tcp_listen_pcbs_t tcp_listen_pcbs;
|
||||
extern struct tcp_pcb *tcp_active_pcbs; /* List of all TCP PCBs that are in a
|
||||
state in which they accept or send
|
||||
data. */
|
||||
extern struct tcp_pcb *tcp_tw_pcbs; /* List of all TCP PCBs in TIME-WAIT. */
|
||||
|
||||
extern struct tcp_pcb *tcp_tmp_pcb; /* Only used for temporary storage. */
|
||||
|
||||
/* Axioms about the above lists:
|
||||
1) Every TCP PCB that is not CLOSED is in one of the lists.
|
||||
2) A PCB is only in one of the lists.
|
||||
3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.
|
||||
4) All PCBs in the tcp_tw_pcbs list is in TIME-WAIT state.
|
||||
*/
|
||||
|
||||
/* Define two macros, TCP_REG and TCP_RMV that registers a TCP PCB
|
||||
with a PCB list or removes a PCB from a list, respectively. */
|
||||
#if 0
|
||||
#define TCP_REG(pcbs, npcb) do {\
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_REG %p local port %d\n", npcb, npcb->local_port)); \
|
||||
for(tcp_tmp_pcb = *pcbs; \
|
||||
tcp_tmp_pcb != NULL; \
|
||||
tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
LWIP_ASSERT("TCP_REG: already registered\n", tcp_tmp_pcb != npcb); \
|
||||
} \
|
||||
LWIP_ASSERT("TCP_REG: pcb->state != CLOSED", npcb->state != CLOSED); \
|
||||
npcb->next = *pcbs; \
|
||||
LWIP_ASSERT("TCP_REG: npcb->next != npcb", npcb->next != npcb); \
|
||||
*(pcbs) = npcb; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
LWIP_ASSERT("TCP_RMV: pcbs != NULL", *pcbs != NULL); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removing %p from %p\n", npcb, *pcbs)); \
|
||||
if(*pcbs == npcb) { \
|
||||
*pcbs = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
LWIP_ASSERT("TCP_RMV: tcp_pcbs sane", tcp_pcbs_sane()); \
|
||||
LWIP_DEBUGF(TCP_DEBUG, ("TCP_RMV: removed %p from %p\n", npcb, *pcbs)); \
|
||||
} while(0)
|
||||
|
||||
#else /* LWIP_DEBUG */
|
||||
#define TCP_REG(pcbs, npcb) do { \
|
||||
npcb->next = *pcbs; \
|
||||
*(pcbs) = npcb; \
|
||||
tcp_timer_needed(); \
|
||||
} while(0)
|
||||
#define TCP_RMV(pcbs, npcb) do { \
|
||||
if(*(pcbs) == npcb) { \
|
||||
(*(pcbs)) = (*pcbs)->next; \
|
||||
} else for(tcp_tmp_pcb = *pcbs; tcp_tmp_pcb != NULL; tcp_tmp_pcb = tcp_tmp_pcb->next) { \
|
||||
if(tcp_tmp_pcb->next != NULL && tcp_tmp_pcb->next == npcb) { \
|
||||
tcp_tmp_pcb->next = npcb->next; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
npcb->next = NULL; \
|
||||
} while(0)
|
||||
#endif /* LWIP_DEBUG */
|
||||
#endif /* __LWIP_TCP_H__ */
|
||||
|
||||
|
||||
|
68
Demo/Common/ethernet/lwIP/include/lwip/tcpip.h
Normal file
68
Demo/Common/ethernet/lwIP/include/lwip/tcpip.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_TCPIP_H__
|
||||
#define __LWIP_TCPIP_H__
|
||||
|
||||
#include "lwip/api_msg.h"
|
||||
#include "lwip/pbuf.h"
|
||||
|
||||
void tcpip_init(void (* tcpip_init_done)(void *), void *arg);
|
||||
void tcpip_apimsg(struct api_msg *apimsg);
|
||||
err_t tcpip_input(struct pbuf *p, struct netif *inp);
|
||||
err_t tcpip_callback(void (*f)(void *ctx), void *ctx);
|
||||
|
||||
void tcpip_tcp_timer_needed(void);
|
||||
|
||||
enum tcpip_msg_type {
|
||||
TCPIP_MSG_API,
|
||||
TCPIP_MSG_INPUT,
|
||||
TCPIP_MSG_CALLBACK
|
||||
};
|
||||
|
||||
struct tcpip_msg {
|
||||
enum tcpip_msg_type type;
|
||||
sys_sem_t *sem;
|
||||
union {
|
||||
struct api_msg *apimsg;
|
||||
struct {
|
||||
struct pbuf *p;
|
||||
struct netif *netif;
|
||||
} inp;
|
||||
struct {
|
||||
void (*f)(void *ctx);
|
||||
void *ctx;
|
||||
} cb;
|
||||
} msg;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __LWIP_TCPIP_H__ */
|
106
Demo/Common/ethernet/lwIP/include/lwip/udp.h
Normal file
106
Demo/Common/ethernet/lwIP/include/lwip/udp.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __LWIP_UDP_H__
|
||||
#define __LWIP_UDP_H__
|
||||
|
||||
#include "lwip/arch.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#define UDP_HLEN 8
|
||||
|
||||
struct udp_hdr {
|
||||
PACK_STRUCT_FIELD(u16_t src);
|
||||
PACK_STRUCT_FIELD(u16_t dest); /* src/dest UDP ports */
|
||||
PACK_STRUCT_FIELD(u16_t len);
|
||||
PACK_STRUCT_FIELD(u16_t chksum);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
|
||||
#define UDP_FLAGS_NOCHKSUM 0x01U
|
||||
#define UDP_FLAGS_UDPLITE 0x02U
|
||||
#define UDP_FLAGS_CONNECTED 0x04U
|
||||
|
||||
struct udp_pcb {
|
||||
/* Common members of all PCB types */
|
||||
IP_PCB;
|
||||
|
||||
/* Protocol specific PCB members */
|
||||
|
||||
struct udp_pcb *next;
|
||||
|
||||
u8_t flags;
|
||||
u16_t local_port, remote_port;
|
||||
|
||||
u16_t chksum_len;
|
||||
|
||||
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
struct ip_addr *addr, u16_t port);
|
||||
void *recv_arg;
|
||||
};
|
||||
/* udp_pcbs export for exernal reference (e.g. SNMP agent) */
|
||||
extern struct udp_pcb *udp_pcbs;
|
||||
|
||||
/* The following functions is the application layer interface to the
|
||||
UDP code. */
|
||||
struct udp_pcb * udp_new (void);
|
||||
void udp_remove (struct udp_pcb *pcb);
|
||||
err_t udp_bind (struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
err_t udp_connect (struct udp_pcb *pcb, struct ip_addr *ipaddr,
|
||||
u16_t port);
|
||||
void udp_disconnect (struct udp_pcb *pcb);
|
||||
void udp_recv (struct udp_pcb *pcb,
|
||||
void (* recv)(void *arg, struct udp_pcb *upcb,
|
||||
struct pbuf *p,
|
||||
struct ip_addr *addr,
|
||||
u16_t port),
|
||||
void *recv_arg);
|
||||
err_t udp_sendto (struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *dst_ip, u16_t dst_port);
|
||||
err_t udp_send (struct udp_pcb *pcb, struct pbuf *p);
|
||||
|
||||
#define udp_flags(pcb) ((pcb)->flags)
|
||||
#define udp_setflags(pcb, f) ((pcb)->flags = (f))
|
||||
|
||||
/* The following functions are the lower layer interface to UDP. */
|
||||
void udp_input (struct pbuf *p, struct netif *inp);
|
||||
void udp_init (void);
|
||||
|
||||
#if UDP_DEBUG
|
||||
void udp_debug_print(struct udp_hdr *udphdr);
|
||||
#else
|
||||
#define udp_debug_print(udphdr)
|
||||
#endif
|
||||
#endif /* __LWIP_UDP_H__ */
|
||||
|
||||
|
129
Demo/Common/ethernet/lwIP/include/netif/etharp.h
Normal file
129
Demo/Common/ethernet/lwIP/include/netif/etharp.h
Normal file
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
* Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NETIF_ETHARP_H__
|
||||
#define __NETIF_ETHARP_H__
|
||||
|
||||
#ifndef ETH_PAD_SIZE
|
||||
#define ETH_PAD_SIZE 0
|
||||
#endif
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_addr {
|
||||
PACK_STRUCT_FIELD(u8_t addr[6]);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct eth_hdr {
|
||||
#if ETH_PAD_SIZE
|
||||
PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
|
||||
#endif
|
||||
PACK_STRUCT_FIELD(struct eth_addr dest);
|
||||
PACK_STRUCT_FIELD(struct eth_addr src);
|
||||
PACK_STRUCT_FIELD(u16_t type);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
/** the ARP message */
|
||||
struct etharp_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
|
||||
PACK_STRUCT_FIELD(u16_t hwtype);
|
||||
PACK_STRUCT_FIELD(u16_t proto);
|
||||
PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
|
||||
PACK_STRUCT_FIELD(u16_t opcode);
|
||||
PACK_STRUCT_FIELD(struct eth_addr shwaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
|
||||
PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
|
||||
PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/bpstruct.h"
|
||||
#endif
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ethip_hdr {
|
||||
PACK_STRUCT_FIELD(struct eth_hdr eth);
|
||||
PACK_STRUCT_FIELD(struct ip_hdr ip);
|
||||
} PACK_STRUCT_STRUCT;
|
||||
PACK_STRUCT_END
|
||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||
# include "arch/epstruct.h"
|
||||
#endif
|
||||
|
||||
/** 5 seconds period */
|
||||
#define ARP_TMR_INTERVAL 5000
|
||||
|
||||
#define ETHTYPE_ARP 0x0806
|
||||
#define ETHTYPE_IP 0x0800
|
||||
|
||||
|
||||
void etharp_init(void);
|
||||
void etharp_tmr(void);
|
||||
s8_t etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct eth_addr **eth_ret, struct ip_addr **ip_ret);
|
||||
void etharp_ip_input(struct netif *netif, struct pbuf *p);
|
||||
void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr,
|
||||
struct pbuf *p);
|
||||
err_t etharp_output(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct pbuf *q);
|
||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q);
|
||||
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr);
|
||||
|
||||
#endif /* __NETIF_ARP_H__ */
|
39
Demo/Common/ethernet/lwIP/include/netif/loopif.h
Normal file
39
Demo/Common/ethernet/lwIP/include/netif/loopif.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __NETIF_LOOPIF_H__
|
||||
#define __NETIF_LOOPIF_H__
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
err_t loopif_init(struct netif *netif);
|
||||
|
||||
#endif /* __NETIF_LOOPIF_H__ */
|
42
Demo/Common/ethernet/lwIP/include/netif/slipif.h
Normal file
42
Demo/Common/ethernet/lwIP/include/netif/slipif.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2001, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __NETIF_SLIPIF_H__
|
||||
#define __NETIF_SLIPIF_H__
|
||||
|
||||
#include "lwip/netif.h"
|
||||
|
||||
err_t slipif_init(struct netif * netif);
|
||||
|
||||
#endif
|
||||
|
27
Demo/Common/ethernet/lwIP/netif/FILES
Normal file
27
Demo/Common/ethernet/lwIP/netif/FILES
Normal file
|
@ -0,0 +1,27 @@
|
|||
This directory contains generic network interface device drivers that
|
||||
do not contain any hardware or architecture specific code. The files
|
||||
are:
|
||||
|
||||
etharp.c
|
||||
Implements the ARP (Address Resolution Protocol) over
|
||||
Ethernet. The code in this file should be used together with
|
||||
Ethernet device drivers. Note that this module has been
|
||||
largely made Ethernet independent so you should be able to
|
||||
adapt this for other link layers (such as Firewire).
|
||||
|
||||
ethernetif.c
|
||||
An example of how an Ethernet device driver could look. This
|
||||
file can be used as a "skeleton" for developing new Ethernet
|
||||
network device drivers. It uses the etharp.c ARP code.
|
||||
|
||||
loopif.c
|
||||
An example network interface that shows how a "loopback"
|
||||
interface would work. This is not really intended for actual
|
||||
use, but as a very basic example of how initialization and
|
||||
output functions work.
|
||||
|
||||
slipif.c
|
||||
A generic implementation of the SLIP (Serial Line IP)
|
||||
protocol. It requires a sio (serial I/O) module to work.
|
||||
|
||||
ppp/ Point-to-Point Protocol stack
|
892
Demo/Common/ethernet/lwIP/netif/etharp.c
Normal file
892
Demo/Common/ethernet/lwIP/netif/etharp.c
Normal file
|
@ -0,0 +1,892 @@
|
|||
/**
|
||||
* @file
|
||||
* Address Resolution Protocol module for IP over Ethernet
|
||||
*
|
||||
* Functionally, ARP is divided into two parts. The first maps an IP address
|
||||
* to a physical address when sending a packet, and the second part answers
|
||||
* requests from other machines for our physical address.
|
||||
*
|
||||
* This implementation complies with RFC 826 (Ethernet ARP). It supports
|
||||
* Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6
|
||||
* if an interface calls etharp_query(our_netif, its_ip_addr, NULL) upon
|
||||
* address change.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
|
||||
* Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "netif/etharp.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/snmp.h"
|
||||
|
||||
/* ARP needs to inform DHCP of any ARP replies? */
|
||||
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
|
||||
# include "lwip/dhcp.h"
|
||||
#endif
|
||||
|
||||
/** the time an ARP entry stays valid after its last update,
|
||||
* (240 * 5) seconds = 20 minutes.
|
||||
*/
|
||||
#define ARP_MAXAGE 240
|
||||
/** the time an ARP entry stays pending after first request,
|
||||
* (2 * 5) seconds = 10 seconds.
|
||||
*
|
||||
* @internal Keep this number at least 2, otherwise it might
|
||||
* run out instantly if the timeout occurs directly after a request.
|
||||
*/
|
||||
#define ARP_MAXPENDING 2
|
||||
|
||||
#define HWTYPE_ETHERNET 1
|
||||
|
||||
/** ARP message types */
|
||||
#define ARP_REQUEST 1
|
||||
#define ARP_REPLY 2
|
||||
|
||||
#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8)
|
||||
#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff)
|
||||
|
||||
#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8))
|
||||
#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8))
|
||||
|
||||
enum etharp_state {
|
||||
ETHARP_STATE_EMPTY,
|
||||
ETHARP_STATE_PENDING,
|
||||
ETHARP_STATE_STABLE,
|
||||
/** @internal transitional state used in etharp_tmr() for convenience*/
|
||||
ETHARP_STATE_EXPIRED
|
||||
};
|
||||
|
||||
struct etharp_entry {
|
||||
#if ARP_QUEUEING
|
||||
/**
|
||||
* Pointer to queue of pending outgoing packets on this ARP entry.
|
||||
*/
|
||||
struct pbuf *p;
|
||||
#endif
|
||||
struct ip_addr ipaddr;
|
||||
struct eth_addr ethaddr;
|
||||
enum etharp_state state;
|
||||
u8_t ctime;
|
||||
struct netif *netif;
|
||||
};
|
||||
|
||||
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
static struct etharp_entry arp_table[ARP_TABLE_SIZE];
|
||||
|
||||
/**
|
||||
* Try hard to create a new entry - we want the IP address to appear in
|
||||
* the cache (even if this means removing an active entry or so). */
|
||||
#define ETHARP_TRY_HARD 1
|
||||
|
||||
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags);
|
||||
static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags);
|
||||
/**
|
||||
* Initializes ARP module.
|
||||
*/
|
||||
void
|
||||
etharp_init(void)
|
||||
{
|
||||
u8_t i;
|
||||
/* clear ARP entries */
|
||||
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||
#if ARP_QUEUEING
|
||||
arp_table[i].p = NULL;
|
||||
#endif
|
||||
arp_table[i].ctime = 0;
|
||||
arp_table[i].netif = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears expired entries in the ARP table.
|
||||
*
|
||||
* This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds),
|
||||
* in order to expire entries in the ARP table.
|
||||
*/
|
||||
void
|
||||
etharp_tmr(void)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n"));
|
||||
/* remove expired entries from the ARP table */
|
||||
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
arp_table[i].ctime++;
|
||||
/* stable entry? */
|
||||
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
|
||||
/* entry has become old? */
|
||||
(arp_table[i].ctime >= ARP_MAXAGE)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %"U16_F".\n", (u16_t)i));
|
||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||
/* pending entry? */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
/* entry unresolved/pending for too long? */
|
||||
if (arp_table[i].ctime >= ARP_MAXPENDING) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %"U16_F".\n", (u16_t)i));
|
||||
arp_table[i].state = ETHARP_STATE_EXPIRED;
|
||||
#if ARP_QUEUEING
|
||||
} else if (arp_table[i].p != NULL) {
|
||||
/* resend an ARP query here */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* clean up entries that have just been expired */
|
||||
if (arp_table[i].state == ETHARP_STATE_EXPIRED) {
|
||||
/* remove from SNMP ARP index tree */
|
||||
snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
|
||||
#if ARP_QUEUEING
|
||||
/* and empty packet queue */
|
||||
if (arp_table[i].p != NULL) {
|
||||
/* remove all queued packets */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].p)));
|
||||
pbuf_free(arp_table[i].p);
|
||||
arp_table[i].p = NULL;
|
||||
}
|
||||
#endif
|
||||
/* recycle entry for re-use */
|
||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the ARP table for a matching or new entry.
|
||||
*
|
||||
* If an IP address is given, return a pending or stable ARP entry that matches
|
||||
* the address. If no match is found, create a new entry with this address set,
|
||||
* but in state ETHARP_EMPTY. The caller must check and possibly change the
|
||||
* state of the returned entry.
|
||||
*
|
||||
* If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY.
|
||||
*
|
||||
* In all cases, attempt to create new entries from an empty entry. If no
|
||||
* empty entries are available and ETHARP_TRY_HARD flag is set, recycle
|
||||
* old entries. Heuristic choose the least important entry for recycling.
|
||||
*
|
||||
* @param ipaddr IP address to find in ARP cache, or to add if not found.
|
||||
* @param flags
|
||||
* - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of
|
||||
* active (stable or pending) entries.
|
||||
*
|
||||
* @return The ARP entry index that matched or is created, ERR_MEM if no
|
||||
* entry is found or could be recycled.
|
||||
*/
|
||||
static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags)
|
||||
{
|
||||
s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE;
|
||||
s8_t empty = ARP_TABLE_SIZE;
|
||||
u8_t i = 0, age_pending = 0, age_stable = 0;
|
||||
#if ARP_QUEUEING
|
||||
/* oldest entry with packets on queue */
|
||||
s8_t old_queue = ARP_TABLE_SIZE;
|
||||
/* its age */
|
||||
u8_t age_queue = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* a) do a search through the cache, remember candidates
|
||||
* b) select candidate entry
|
||||
* c) create new entry
|
||||
*/
|
||||
|
||||
/* a) in a single search sweep, do all of this
|
||||
* 1) remember the first empty entry (if any)
|
||||
* 2) remember the oldest stable entry (if any)
|
||||
* 3) remember the oldest pending entry without queued packets (if any)
|
||||
* 4) remember the oldest pending entry with queued packets (if any)
|
||||
* 5) search for a matching IP entry, either pending or stable
|
||||
* until 5 matches, or all entries are searched for.
|
||||
*/
|
||||
|
||||
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
|
||||
/* no empty entry found yet and now we do find one? */
|
||||
if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i));
|
||||
/* remember first empty entry */
|
||||
empty = i;
|
||||
}
|
||||
/* pending entry? */
|
||||
else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
/* if given, does IP address match IP address in ARP entry? */
|
||||
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i));
|
||||
/* found exact IP address match, simply bail out */
|
||||
return i;
|
||||
#if ARP_QUEUEING
|
||||
/* pending with queued packets? */
|
||||
} else if (arp_table[i].p != NULL) {
|
||||
if (arp_table[i].ctime >= age_queue) {
|
||||
old_queue = i;
|
||||
age_queue = arp_table[i].ctime;
|
||||
}
|
||||
#endif
|
||||
/* pending without queued packets? */
|
||||
} else {
|
||||
if (arp_table[i].ctime >= age_pending) {
|
||||
old_pending = i;
|
||||
age_pending = arp_table[i].ctime;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* stable entry? */
|
||||
else if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
/* if given, does IP address match IP address in ARP entry? */
|
||||
if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i));
|
||||
/* found exact IP address match, simply bail out */
|
||||
return i;
|
||||
/* remember entry with oldest stable entry in oldest, its age in maxtime */
|
||||
} else if (arp_table[i].ctime >= age_stable) {
|
||||
old_stable = i;
|
||||
age_stable = arp_table[i].ctime;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* { we have no match } => try to create a new entry */
|
||||
|
||||
/* no empty entry found and not allowed to recycle? */
|
||||
if ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0))
|
||||
{
|
||||
return (s8_t)ERR_MEM;
|
||||
}
|
||||
|
||||
/* b) choose the least destructive entry to recycle:
|
||||
* 1) empty entry
|
||||
* 2) oldest stable entry
|
||||
* 3) oldest pending entry without queued packets
|
||||
* 4) oldest pending entry without queued packets
|
||||
*
|
||||
* { ETHARP_TRY_HARD is set at this point }
|
||||
*/
|
||||
|
||||
/* 1) empty entry available? */
|
||||
if (empty < ARP_TABLE_SIZE) {
|
||||
i = empty;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i));
|
||||
}
|
||||
/* 2) found recyclable stable entry? */
|
||||
else if (old_stable < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest stable*/
|
||||
i = old_stable;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i));
|
||||
#if ARP_QUEUEING
|
||||
/* no queued packets should exist on stable entries */
|
||||
LWIP_ASSERT("arp_table[i].p == NULL", arp_table[i].p == NULL);
|
||||
#endif
|
||||
/* 3) found recyclable pending entry without queued packets? */
|
||||
} else if (old_pending < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest pending */
|
||||
i = old_pending;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i));
|
||||
#if ARP_QUEUEING
|
||||
/* 4) found recyclable pending entry with queued packets? */
|
||||
} else if (old_queue < ARP_TABLE_SIZE) {
|
||||
/* recycle oldest pending */
|
||||
i = old_queue;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].p)));
|
||||
pbuf_free(arp_table[i].p);
|
||||
arp_table[i].p = NULL;
|
||||
#endif
|
||||
/* no empty or recyclable entries found */
|
||||
} else {
|
||||
return (s8_t)ERR_MEM;
|
||||
}
|
||||
|
||||
/* { empty or recyclable entry found } */
|
||||
LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE);
|
||||
|
||||
if (arp_table[i].state != ETHARP_STATE_EMPTY)
|
||||
{
|
||||
snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr);
|
||||
}
|
||||
/* recycle entry (no-op for an already empty entry) */
|
||||
arp_table[i].state = ETHARP_STATE_EMPTY;
|
||||
|
||||
/* IP address given? */
|
||||
if (ipaddr != NULL) {
|
||||
/* set IP address */
|
||||
ip_addr_set(&arp_table[i].ipaddr, ipaddr);
|
||||
}
|
||||
arp_table[i].ctime = 0;
|
||||
return (err_t)i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update (or insert) a IP/MAC address pair in the ARP cache.
|
||||
*
|
||||
* If a pending entry is resolved, any queued packets will be sent
|
||||
* at this point.
|
||||
*
|
||||
* @param ipaddr IP address of the inserted ARP entry.
|
||||
* @param ethaddr Ethernet address of the inserted ARP entry.
|
||||
* @param flags Defines behaviour:
|
||||
* - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified,
|
||||
* only existing ARP entries will be updated.
|
||||
*
|
||||
* @return
|
||||
* - ERR_OK Succesfully updated ARP cache.
|
||||
* - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set.
|
||||
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
|
||||
*
|
||||
* @see pbuf_free()
|
||||
*/
|
||||
static err_t
|
||||
update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags)
|
||||
{
|
||||
s8_t i;
|
||||
u8_t k;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 3, ("update_arp_entry()\n"));
|
||||
LWIP_ASSERT("netif->hwaddr_len != 0", netif->hwaddr_len != 0);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n",
|
||||
ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr),
|
||||
ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2],
|
||||
ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5]));
|
||||
/* non-unicast address? */
|
||||
if (ip_addr_isany(ipaddr) ||
|
||||
ip_addr_isbroadcast(ipaddr, netif) ||
|
||||
ip_addr_ismulticast(ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: will not add non-unicast IP address to ARP cache\n"));
|
||||
return ERR_ARG;
|
||||
}
|
||||
/* find or create ARP entry */
|
||||
i = find_entry(ipaddr, flags);
|
||||
/* bail out if no entry could be found */
|
||||
if (i < 0) return (err_t)i;
|
||||
|
||||
/* mark it stable */
|
||||
arp_table[i].state = ETHARP_STATE_STABLE;
|
||||
/* record network interface */
|
||||
arp_table[i].netif = netif;
|
||||
|
||||
/* insert in SNMP ARP index tree */
|
||||
snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr);
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i));
|
||||
/* update address */
|
||||
k = netif->hwaddr_len;
|
||||
while (k > 0) {
|
||||
k--;
|
||||
arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
|
||||
}
|
||||
/* reset time stamp */
|
||||
arp_table[i].ctime = 0;
|
||||
/* this is where we will send out queued packets! */
|
||||
#if ARP_QUEUEING
|
||||
while (arp_table[i].p != NULL) {
|
||||
/* get the first packet on the queue */
|
||||
struct pbuf *p = arp_table[i].p;
|
||||
/* Ethernet header */
|
||||
struct eth_hdr *ethhdr = p->payload;
|
||||
/* remember (and reference) remainder of queue */
|
||||
/* note: this will also terminate the p pbuf chain */
|
||||
arp_table[i].p = pbuf_dequeue(p);
|
||||
/* fill-in Ethernet header */
|
||||
k = netif->hwaddr_len;
|
||||
while(k > 0) {
|
||||
k--;
|
||||
ethhdr->dest.addr[k] = ethaddr->addr[k];
|
||||
ethhdr->src.addr[k] = netif->hwaddr[k];
|
||||
}
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("update_arp_entry: sending queued IP packet %p.\n", (void *)p));
|
||||
/* send the queued IP packet */
|
||||
netif->linkoutput(netif, p);
|
||||
/* free the queued IP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds (stable) ethernet/IP address pair from ARP table
|
||||
* using interface and IP address index.
|
||||
* @note the addresses in the ARP table are in network order!
|
||||
*
|
||||
* @param netif points to interface index
|
||||
* @param ipaddr points to the (network order) IP address index
|
||||
* @param eth_ret points to return pointer
|
||||
* @param ip_ret points to return pointer
|
||||
* @return table index if found, -1 otherwise
|
||||
*/
|
||||
s8_t
|
||||
etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr,
|
||||
struct eth_addr **eth_ret, struct ip_addr **ip_ret)
|
||||
{
|
||||
s8_t i;
|
||||
|
||||
i = 0;
|
||||
while (i < ARP_TABLE_SIZE)
|
||||
{
|
||||
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
|
||||
(arp_table[i].netif == netif) &&
|
||||
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr) )
|
||||
{
|
||||
*eth_ret = &arp_table[i].ethaddr;
|
||||
*ip_ret = &arp_table[i].ipaddr;
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the ARP table using the given IP packet.
|
||||
*
|
||||
* Uses the incoming IP packet's source address to update the
|
||||
* ARP cache for the local network. The function does not alter
|
||||
* or free the packet. This function must be called before the
|
||||
* packet p is passed to the IP layer.
|
||||
*
|
||||
* @param netif The lwIP network interface on which the IP packet pbuf arrived.
|
||||
* @param pbuf The IP packet that arrived on netif.
|
||||
*
|
||||
* @return NULL
|
||||
*
|
||||
* @see pbuf_free()
|
||||
*/
|
||||
void
|
||||
etharp_ip_input(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct ethip_hdr *hdr;
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
/* Only insert an entry if the source IP address of the
|
||||
incoming IP packet comes from a host on the local network. */
|
||||
hdr = p->payload;
|
||||
/* source is not on the local network? */
|
||||
if (!ip_addr_netcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
|
||||
/* do nothing */
|
||||
return;
|
||||
}
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n"));
|
||||
/* update ARP table */
|
||||
/* @todo We could use ETHARP_TRY_HARD if we think we are going to talk
|
||||
* back soon (for example, if the destination IP address is ours. */
|
||||
update_arp_entry(netif, &(hdr->ip.src), &(hdr->eth.src), 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Responds to ARP requests to us. Upon ARP replies to us, add entry to cache
|
||||
* send out queued IP packets. Updates cache with snooped address pairs.
|
||||
*
|
||||
* Should be called for incoming ARP packets. The pbuf in the argument
|
||||
* is freed by this function.
|
||||
*
|
||||
* @param netif The lwIP network interface on which the ARP packet pbuf arrived.
|
||||
* @param pbuf The ARP packet that arrived on netif. Is freed by this function.
|
||||
* @param ethaddr Ethernet address of netif.
|
||||
*
|
||||
* @return NULL
|
||||
*
|
||||
* @see pbuf_free()
|
||||
*/
|
||||
void
|
||||
etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
|
||||
{
|
||||
struct etharp_hdr *hdr;
|
||||
/* these are aligned properly, whereas the ARP header fields might not be */
|
||||
struct ip_addr sipaddr, dipaddr;
|
||||
u8_t i;
|
||||
u8_t for_us;
|
||||
|
||||
LWIP_ASSERT("netif != NULL", netif != NULL);
|
||||
|
||||
/* drop short ARP packets */
|
||||
if (p->tot_len < sizeof(struct etharp_hdr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%"S16_F"/%"S16_F")\n", p->tot_len, (s16_t)sizeof(struct etharp_hdr)));
|
||||
pbuf_free(p);
|
||||
return;
|
||||
}
|
||||
|
||||
hdr = p->payload;
|
||||
|
||||
/* Copy struct ip_addr2 to aligned ip_addr, to support compilers without
|
||||
* structure packing (not using structure copy which breaks strict-aliasing rules). */
|
||||
memcpy(&sipaddr, &hdr->sipaddr, sizeof(sipaddr));
|
||||
memcpy(&dipaddr, &hdr->dipaddr, sizeof(dipaddr));
|
||||
|
||||
/* this interface is not configured? */
|
||||
if (netif->ip_addr.addr == 0) {
|
||||
for_us = 0;
|
||||
} else {
|
||||
/* ARP packet directed to us? */
|
||||
for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr));
|
||||
}
|
||||
|
||||
/* ARP message directed to us? */
|
||||
if (for_us) {
|
||||
/* add IP address in ARP cache; assume requester wants to talk to us.
|
||||
* can result in directly sending the queued packets for this host. */
|
||||
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD);
|
||||
/* ARP message not directed to us? */
|
||||
} else {
|
||||
/* update the source IP address in the cache, if present */
|
||||
update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0);
|
||||
}
|
||||
|
||||
/* now act on the message itself */
|
||||
switch (htons(hdr->opcode)) {
|
||||
/* ARP request? */
|
||||
case ARP_REQUEST:
|
||||
/* ARP request. If it asked for our address, we send out a
|
||||
* reply. In any case, we time-stamp any existing ARP entry,
|
||||
* and possiby send out an IP packet that was queued on it. */
|
||||
|
||||
LWIP_DEBUGF (ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request\n"));
|
||||
/* ARP request for our address? */
|
||||
if (for_us) {
|
||||
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: replying to ARP request for our IP address\n"));
|
||||
/* re-use pbuf to send ARP reply */
|
||||
hdr->opcode = htons(ARP_REPLY);
|
||||
|
||||
hdr->dipaddr = hdr->sipaddr;
|
||||
hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
|
||||
|
||||
i = netif->hwaddr_len;
|
||||
while(i > 0) {
|
||||
i--;
|
||||
hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
|
||||
hdr->shwaddr.addr[i] = ethaddr->addr[i];
|
||||
hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
|
||||
hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
|
||||
}
|
||||
|
||||
hdr->hwtype = htons(HWTYPE_ETHERNET);
|
||||
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
|
||||
|
||||
hdr->proto = htons(ETHTYPE_IP);
|
||||
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
|
||||
|
||||
hdr->ethhdr.type = htons(ETHTYPE_ARP);
|
||||
/* return ARP reply */
|
||||
netif->linkoutput(netif, p);
|
||||
/* we are not configured? */
|
||||
} else if (netif->ip_addr.addr == 0) {
|
||||
/* { for_us == 0 and netif->ip_addr.addr == 0 } */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n"));
|
||||
/* request was not directed to us */
|
||||
} else {
|
||||
/* { for_us == 0 and netif->ip_addr.addr != 0 } */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n"));
|
||||
}
|
||||
break;
|
||||
case ARP_REPLY:
|
||||
/* ARP reply. We already updated the ARP cache earlier. */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
|
||||
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
|
||||
/* DHCP wants to know about ARP replies from any host with an
|
||||
* IP address also offered to us by the DHCP server. We do not
|
||||
* want to take a duplicate IP address on a single network.
|
||||
* @todo How should we handle redundant (fail-over) interfaces?
|
||||
* */
|
||||
dhcp_arp_reply(netif, &sipaddr);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode)));
|
||||
break;
|
||||
}
|
||||
/* free ARP packet */
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve and fill-in Ethernet address header for outgoing packet.
|
||||
*
|
||||
* For IP multicast and broadcast, corresponding Ethernet addresses
|
||||
* are selected and the packet is transmitted on the link.
|
||||
*
|
||||
* For unicast addresses, the packet is submitted to etharp_query(). In
|
||||
* case the IP address is outside the local network, the IP address of
|
||||
* the gateway is used.
|
||||
*
|
||||
* @param netif The lwIP network interface which the IP packet will be sent on.
|
||||
* @param ipaddr The IP address of the packet destination.
|
||||
* @param pbuf The pbuf(s) containing the IP packet to be sent.
|
||||
*
|
||||
* @return
|
||||
* - ERR_RTE No route to destination (no gateway to external networks),
|
||||
* or the return type of either etharp_query() or netif->linkoutput().
|
||||
*/
|
||||
err_t
|
||||
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
{
|
||||
struct eth_addr *dest, *srcaddr, mcastaddr;
|
||||
struct eth_hdr *ethhdr;
|
||||
u8_t i;
|
||||
|
||||
/* make room for Ethernet header - should not fail */
|
||||
if (pbuf_header(q, sizeof(struct eth_hdr)) != 0) {
|
||||
/* bail out */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
|
||||
LINK_STATS_INC(link.lenerr);
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
/* assume unresolved Ethernet address */
|
||||
dest = NULL;
|
||||
/* Determine on destination hardware address. Broadcasts and multicasts
|
||||
* are special, other IP addresses are looked up in the ARP table. */
|
||||
|
||||
/* broadcast destination IP address? */
|
||||
if (ip_addr_isbroadcast(ipaddr, netif)) {
|
||||
/* broadcast on Ethernet also */
|
||||
dest = (struct eth_addr *)ðbroadcast;
|
||||
/* multicast destination IP address? */
|
||||
} else if (ip_addr_ismulticast(ipaddr)) {
|
||||
/* Hash IP multicast address to MAC address.*/
|
||||
mcastaddr.addr[0] = 0x01;
|
||||
mcastaddr.addr[1] = 0x00;
|
||||
mcastaddr.addr[2] = 0x5e;
|
||||
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
|
||||
mcastaddr.addr[4] = ip4_addr3(ipaddr);
|
||||
mcastaddr.addr[5] = ip4_addr4(ipaddr);
|
||||
/* destination Ethernet address is multicast */
|
||||
dest = &mcastaddr;
|
||||
/* unicast destination IP address? */
|
||||
} else {
|
||||
/* outside local network? */
|
||||
if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
|
||||
/* interface has default gateway? */
|
||||
if (netif->gw.addr != 0) {
|
||||
/* send to hardware address of default gateway IP address */
|
||||
ipaddr = &(netif->gw);
|
||||
/* no default gateway available */
|
||||
} else {
|
||||
/* no route to destination error (default gateway missing) */
|
||||
return ERR_RTE;
|
||||
}
|
||||
}
|
||||
/* queue on destination Ethernet address belonging to ipaddr */
|
||||
return etharp_query(netif, ipaddr, q);
|
||||
}
|
||||
|
||||
/* continuation for multicast/broadcast destinations */
|
||||
/* obtain source Ethernet address of the given interface */
|
||||
srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||
ethhdr = q->payload;
|
||||
i = netif->hwaddr_len;
|
||||
while(i > 0) {
|
||||
i--;
|
||||
ethhdr->dest.addr[i] = dest->addr[i];
|
||||
ethhdr->src.addr[i] = srcaddr->addr[i];
|
||||
}
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
/* send packet directly on the link */
|
||||
return netif->linkoutput(netif, q);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an ARP request for the given IP address and/or queue a packet.
|
||||
*
|
||||
* If the IP address was not yet in the cache, a pending ARP cache entry
|
||||
* is added and an ARP request is sent for the given address. The packet
|
||||
* is queued on this entry.
|
||||
*
|
||||
* If the IP address was already pending in the cache, a new ARP request
|
||||
* is sent for the given address. The packet is queued on this entry.
|
||||
*
|
||||
* If the IP address was already stable in the cache, and a packet is
|
||||
* given, it is directly sent and no ARP request is sent out.
|
||||
*
|
||||
* If the IP address was already stable in the cache, and no packet is
|
||||
* given, an ARP request is sent out.
|
||||
*
|
||||
* @param netif The lwIP network interface on which ipaddr
|
||||
* must be queried for.
|
||||
* @param ipaddr The IP address to be resolved.
|
||||
* @param q If non-NULL, a pbuf that must be delivered to the IP address.
|
||||
* q is not freed by this function.
|
||||
*
|
||||
* @return
|
||||
* - ERR_BUF Could not make room for Ethernet header.
|
||||
* - ERR_MEM Hardware address unknown, and no more ARP entries available
|
||||
* to query for address or queue the packet.
|
||||
* - ERR_MEM Could not queue packet due to memory shortage.
|
||||
* - ERR_RTE No route to destination (no gateway to external networks).
|
||||
* - ERR_ARG Non-unicast address given, those will not appear in ARP cache.
|
||||
*
|
||||
*/
|
||||
err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
|
||||
{
|
||||
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||
err_t result = ERR_MEM;
|
||||
s8_t i; /* ARP entry index */
|
||||
u8_t k; /* Ethernet address octet index */
|
||||
|
||||
/* non-unicast address? */
|
||||
if (ip_addr_isbroadcast(ipaddr, netif) ||
|
||||
ip_addr_ismulticast(ipaddr) ||
|
||||
ip_addr_isany(ipaddr)) {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: will not add non-unicast IP address to ARP cache\n"));
|
||||
return ERR_ARG;
|
||||
}
|
||||
|
||||
/* find entry in ARP cache, ask to create entry if queueing packet */
|
||||
i = find_entry(ipaddr, ETHARP_TRY_HARD);
|
||||
|
||||
/* could not find or create entry? */
|
||||
if (i < 0)
|
||||
{
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not create ARP entry\n"));
|
||||
if (q) LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: packet dropped\n"));
|
||||
return (err_t)i;
|
||||
}
|
||||
|
||||
/* mark a fresh entry as pending (we just sent a request) */
|
||||
if (arp_table[i].state == ETHARP_STATE_EMPTY) {
|
||||
arp_table[i].state = ETHARP_STATE_PENDING;
|
||||
}
|
||||
|
||||
/* { i is either a STABLE or (new or existing) PENDING entry } */
|
||||
LWIP_ASSERT("arp_table[i].state == PENDING or STABLE",
|
||||
((arp_table[i].state == ETHARP_STATE_PENDING) ||
|
||||
(arp_table[i].state == ETHARP_STATE_STABLE)));
|
||||
|
||||
/* do we have a pending entry? or an implicit query request? */
|
||||
if ((arp_table[i].state == ETHARP_STATE_PENDING) || (q == NULL)) {
|
||||
/* try to resolve it; send out ARP request */
|
||||
result = etharp_request(netif, ipaddr);
|
||||
}
|
||||
|
||||
/* packet given? */
|
||||
if (q != NULL) {
|
||||
/* stable entry? */
|
||||
if (arp_table[i].state == ETHARP_STATE_STABLE) {
|
||||
/* we have a valid IP->Ethernet address mapping,
|
||||
* fill in the Ethernet header for the outgoing packet */
|
||||
struct eth_hdr *ethhdr = q->payload;
|
||||
k = netif->hwaddr_len;
|
||||
while(k > 0) {
|
||||
k--;
|
||||
ethhdr->dest.addr[k] = arp_table[i].ethaddr.addr[k];
|
||||
ethhdr->src.addr[k] = srcaddr->addr[k];
|
||||
}
|
||||
ethhdr->type = htons(ETHTYPE_IP);
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending packet %p\n", (void *)q));
|
||||
/* send the packet */
|
||||
result = netif->linkoutput(netif, q);
|
||||
/* pending entry? (either just created or already pending */
|
||||
} else if (arp_table[i].state == ETHARP_STATE_PENDING) {
|
||||
#if ARP_QUEUEING /* queue the given q packet */
|
||||
struct pbuf *p;
|
||||
/* copy any PBUF_REF referenced payloads into PBUF_RAM */
|
||||
/* (the caller of lwIP assumes the referenced payload can be
|
||||
* freed after it returns from the lwIP call that brought us here) */
|
||||
p = pbuf_take(q);
|
||||
/* packet could be taken over? */
|
||||
if (p != NULL) {
|
||||
/* queue packet ... */
|
||||
if (arp_table[i].p == NULL) {
|
||||
/* ... in the empty queue */
|
||||
pbuf_ref(p);
|
||||
arp_table[i].p = p;
|
||||
#if 0 /* multi-packet-queueing disabled, see bug #11400 */
|
||||
} else {
|
||||
/* ... at tail of non-empty queue */
|
||||
pbuf_queue(arp_table[i].p, p);
|
||||
#endif
|
||||
}
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i));
|
||||
result = ERR_OK;
|
||||
} else {
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q));
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
}
|
||||
#else /* ARP_QUEUEING == 0 */
|
||||
/* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */
|
||||
/* { result == ERR_MEM } through initialization */
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
err_t etharp_request(struct netif *netif, struct ip_addr *ipaddr)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr;
|
||||
err_t result = ERR_OK;
|
||||
u8_t k; /* ARP entry index */
|
||||
|
||||
/* allocate a pbuf for the outgoing ARP request packet */
|
||||
p = pbuf_alloc(PBUF_LINK, sizeof(struct etharp_hdr), PBUF_RAM);
|
||||
/* could allocate a pbuf for an ARP request? */
|
||||
if (p != NULL) {
|
||||
struct etharp_hdr *hdr = p->payload;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_request: sending ARP request.\n"));
|
||||
hdr->opcode = htons(ARP_REQUEST);
|
||||
k = netif->hwaddr_len;
|
||||
while(k > 0) {
|
||||
k--;
|
||||
hdr->shwaddr.addr[k] = srcaddr->addr[k];
|
||||
/* the hardware address is what we ask for, in
|
||||
* a request it is a don't-care value, we use zeroes */
|
||||
hdr->dhwaddr.addr[k] = 0x00;
|
||||
}
|
||||
hdr->dipaddr = *(struct ip_addr2 *)ipaddr;
|
||||
hdr->sipaddr = *(struct ip_addr2 *)&netif->ip_addr;
|
||||
|
||||
hdr->hwtype = htons(HWTYPE_ETHERNET);
|
||||
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
|
||||
|
||||
hdr->proto = htons(ETHTYPE_IP);
|
||||
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
|
||||
k = netif->hwaddr_len;
|
||||
while(k > 0) {
|
||||
k--;
|
||||
/* broadcast to all network interfaces on the local network */
|
||||
hdr->ethhdr.dest.addr[k] = 0xff;
|
||||
hdr->ethhdr.src.addr[k] = srcaddr->addr[k];
|
||||
}
|
||||
hdr->ethhdr.type = htons(ETHTYPE_ARP);
|
||||
/* send ARP query */
|
||||
result = netif->linkoutput(netif, p);
|
||||
/* free ARP query packet */
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
/* could not allocate pbuf for ARP request */
|
||||
} else {
|
||||
result = ERR_MEM;
|
||||
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_request: could not allocate pbuf for ARP request.\n"));
|
||||
}
|
||||
return result;
|
||||
}
|
326
Demo/Common/ethernet/lwIP/netif/ethernetif.c
Normal file
326
Demo/Common/ethernet/lwIP/netif/ethernetif.c
Normal file
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is a skeleton for developing Ethernet network interface
|
||||
* drivers for lwIP. Add code to the low_level functions and do a
|
||||
* search-and-replace for the word "ethernetif" to replace it with
|
||||
* something that better describes your network interface.
|
||||
*/
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/stats.h>
|
||||
|
||||
#include "netif/etharp.h"
|
||||
|
||||
/* Define those to better describe your network interface. */
|
||||
#define IFNAME0 'e'
|
||||
#define IFNAME1 'n'
|
||||
|
||||
struct ethernetif {
|
||||
struct eth_addr *ethaddr;
|
||||
/* Add whatever per-interface state that is needed here. */
|
||||
};
|
||||
|
||||
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
|
||||
|
||||
/* Forward declarations. */
|
||||
static void ethernetif_input(struct netif *netif);
|
||||
static err_t ethernetif_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr);
|
||||
|
||||
static void
|
||||
low_level_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
|
||||
/* set MAC hardware address length */
|
||||
netif->hwaddr_len = 6;
|
||||
|
||||
/* set MAC hardware address */
|
||||
netif->hwaddr[0] = ;
|
||||
...
|
||||
netif->hwaddr[5] = ;
|
||||
|
||||
/* maximum transfer unit */
|
||||
netif->mtu = 1500;
|
||||
|
||||
/* broadcast capability */
|
||||
netif->flags = NETIF_FLAG_BROADCAST;
|
||||
|
||||
/* Do whatever else is needed to initialize interface. */
|
||||
}
|
||||
|
||||
/*
|
||||
* low_level_output():
|
||||
*
|
||||
* Should do the actual transmission of the packet. The packet is
|
||||
* contained in the pbuf that is passed to the function. This pbuf
|
||||
* might be chained.
|
||||
*
|
||||
*/
|
||||
|
||||
static err_t
|
||||
low_level_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
struct pbuf *q;
|
||||
|
||||
initiate transfer();
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||
#endif
|
||||
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
/* Send the data from the pbuf to the interface, one pbuf at a
|
||||
time. The size of the data in each pbuf is kept in the ->len
|
||||
variable. */
|
||||
send data from(q->payload, q->len);
|
||||
}
|
||||
|
||||
signal that packet should be sent();
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
#endif
|
||||
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.xmit++;
|
||||
#endif /* LINK_STATS */
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* low_level_input():
|
||||
*
|
||||
* Should allocate a pbuf and transfer the bytes of the incoming
|
||||
* packet from the interface into the pbuf.
|
||||
*
|
||||
*/
|
||||
|
||||
static struct pbuf *
|
||||
low_level_input(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif = netif->state;
|
||||
struct pbuf *p, *q;
|
||||
u16_t len;
|
||||
|
||||
/* Obtain the size of the packet and put it into the "len"
|
||||
variable. */
|
||||
len = ;
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
||||
#endif
|
||||
|
||||
/* We allocate a pbuf chain of pbufs from the pool. */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
|
||||
if (p != NULL) {
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||
#endif
|
||||
|
||||
/* We iterate over the pbuf chain until we have read the entire
|
||||
* packet into the pbuf. */
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
/* Read enough bytes to fill this pbuf in the chain. The
|
||||
* available data in the pbuf is given by the q->len
|
||||
* variable. */
|
||||
read data into(q->payload, q->len);
|
||||
}
|
||||
acknowledge that packet has been read();
|
||||
|
||||
#if ETH_PAD_SIZE
|
||||
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||
#endif
|
||||
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.recv++;
|
||||
#endif /* LINK_STATS */
|
||||
} else {
|
||||
drop packet();
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.memerr++;
|
||||
lwip_stats.link.drop++;
|
||||
#endif /* LINK_STATS */
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* ethernetif_output():
|
||||
*
|
||||
* This function is called by the TCP/IP stack when an IP packet
|
||||
* should be sent. It calls the function called low_level_output() to
|
||||
* do the actual transmission of the packet.
|
||||
*
|
||||
*/
|
||||
|
||||
static err_t
|
||||
ethernetif_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr)
|
||||
{
|
||||
|
||||
/* resolve hardware address, then send (or queue) packet */
|
||||
return etharp_output(netif, ipaddr, p);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* ethernetif_input():
|
||||
*
|
||||
* This function should be called when a packet is ready to be read
|
||||
* from the interface. It uses the function low_level_input() that
|
||||
* should handle the actual reception of bytes from the network
|
||||
* interface.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
ethernetif_input(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif;
|
||||
struct eth_hdr *ethhdr;
|
||||
struct pbuf *p;
|
||||
|
||||
ethernetif = netif->state;
|
||||
|
||||
/* move received packet into a new pbuf */
|
||||
p = low_level_input(netif);
|
||||
/* no packet could be read, silently ignore this */
|
||||
if (p == NULL) return;
|
||||
/* points to packet payload, which starts with an Ethernet header */
|
||||
ethhdr = p->payload;
|
||||
|
||||
#if LINK_STATS
|
||||
lwip_stats.link.recv++;
|
||||
#endif /* LINK_STATS */
|
||||
|
||||
ethhdr = p->payload;
|
||||
|
||||
switch (htons(ethhdr->type)) {
|
||||
/* IP packet? */
|
||||
case ETHTYPE_IP:
|
||||
#if 0
|
||||
/* CSi disabled ARP table update on ingress IP packets.
|
||||
This seems to work but needs thorough testing. */
|
||||
/* update ARP table */
|
||||
etharp_ip_input(netif, p);
|
||||
#endif
|
||||
/* skip Ethernet header */
|
||||
pbuf_header(p, -sizeof(struct eth_hdr));
|
||||
/* pass to network layer */
|
||||
netif->input(p, netif);
|
||||
break;
|
||||
|
||||
case ETHTYPE_ARP:
|
||||
/* pass p to ARP module */
|
||||
etharp_arp_input(netif, ethernetif->ethaddr, p);
|
||||
break;
|
||||
default:
|
||||
pbuf_free(p);
|
||||
p = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arp_timer(void *arg)
|
||||
{
|
||||
etharp_tmr();
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* ethernetif_init():
|
||||
*
|
||||
* Should be called at the beginning of the program to set up the
|
||||
* network interface. It calls the function low_level_init() to do the
|
||||
* actual setup of the hardware.
|
||||
*
|
||||
*/
|
||||
|
||||
err_t
|
||||
ethernetif_init(struct netif *netif)
|
||||
{
|
||||
struct ethernetif *ethernetif;
|
||||
|
||||
ethernetif = mem_malloc(sizeof(struct ethernetif));
|
||||
|
||||
if (ethernetif == NULL)
|
||||
{
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
#if LWIP_SNMP
|
||||
/* ifType ethernetCsmacd(6) @see RFC1213 */
|
||||
netif->link_type = 6;
|
||||
/* your link speed here */
|
||||
netif->link_speed = ;
|
||||
netif->ts = 0;
|
||||
netif->ifinoctets = 0;
|
||||
netif->ifinucastpkts = 0;
|
||||
netif->ifinnucastpkts = 0;
|
||||
netif->ifindiscards = 0;
|
||||
netif->ifoutoctets = 0;
|
||||
netif->ifoutucastpkts = 0;
|
||||
netif->ifoutnucastpkts = 0;
|
||||
netif->ifoutdiscards = 0;
|
||||
#endif
|
||||
|
||||
netif->state = ethernetif;
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
netif->output = ethernetif_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
|
||||
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
|
||||
|
||||
low_level_init(netif);
|
||||
|
||||
etharp_init();
|
||||
|
||||
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
119
Demo/Common/ethernet/lwIP/netif/loopif.c
Normal file
119
Demo/Common/ethernet/lwIP/netif/loopif.c
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
|
||||
#include "netif/loopif.h"
|
||||
#include "lwip/mem.h"
|
||||
|
||||
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
||||
#include "netif/tcpdump.h"
|
||||
#endif /* LWIP_DEBUG && LWIP_TCPDUMP */
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/ip.h"
|
||||
|
||||
static void
|
||||
loopif_input( void * arg )
|
||||
{
|
||||
struct netif *netif = (struct netif *)( ((void **)arg)[ 0 ] );
|
||||
struct pbuf *r = (struct pbuf *)( ((void **)arg)[ 1 ] );
|
||||
|
||||
mem_free( arg );
|
||||
netif -> input( r, netif );
|
||||
}
|
||||
|
||||
static err_t
|
||||
loopif_output(struct netif *netif, struct pbuf *p,
|
||||
struct ip_addr *ipaddr)
|
||||
{
|
||||
struct pbuf *q, *r;
|
||||
u8_t *ptr;
|
||||
void **arg;
|
||||
|
||||
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
|
||||
tcpdump(p);
|
||||
#endif /* LWIP_DEBUG && LWIP_TCPDUMP */
|
||||
|
||||
r = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
|
||||
if (r != NULL) {
|
||||
ptr = r->payload;
|
||||
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
memcpy(ptr, q->payload, q->len);
|
||||
ptr += q->len;
|
||||
}
|
||||
|
||||
arg = mem_malloc( sizeof( void *[2]));
|
||||
if( NULL == arg ) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
arg[0] = netif;
|
||||
arg[1] = r;
|
||||
/**
|
||||
* workaround (patch #1779) to try to prevent bug #2595:
|
||||
* When connecting to "localhost" with the loopif interface,
|
||||
* tcp_output doesn't get the opportunity to finnish sending the
|
||||
* segment before tcp_process gets it, resulting in tcp_process
|
||||
* referencing pcb->unacked-> which still is NULL.
|
||||
*
|
||||
* TODO: Is there still a race condition here? Leon
|
||||
*/
|
||||
sys_timeout( 1, loopif_input, arg );
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
err_t
|
||||
loopif_init(struct netif *netif)
|
||||
{
|
||||
netif->name[0] = 'l';
|
||||
netif->name[1] = 'o';
|
||||
#if 0 /** TODO: I think this should be enabled, or not? Leon */
|
||||
netif->input = loopif_input;
|
||||
#endif
|
||||
netif->output = loopif_output;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif /* LWIP_HAVE_LOOPIF */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
927
Demo/Common/ethernet/lwIP/netif/ppp/auth.c
Normal file
927
Demo/Common/ethernet/lwIP/netif/ppp/auth.c
Normal file
|
@ -0,0 +1,927 @@
|
|||
/*****************************************************************************
|
||||
* auth.c - Network Authentication and Phase Control program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Ported from public pppd code.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* auth.c - PPP authentication and phase control.
|
||||
*
|
||||
* Copyright (c) 1993 The Australian National University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the Australian National University. The name of the University
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "fsm.h"
|
||||
#include "lcp.h"
|
||||
#include "pap.h"
|
||||
#include "chap.h"
|
||||
#include "auth.h"
|
||||
#include "ipcp.h"
|
||||
|
||||
#if CBCP_SUPPORT > 0
|
||||
#include "cbcp.h"
|
||||
#endif
|
||||
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
/* Bits in auth_pending[] */
|
||||
#define PAP_WITHPEER 1
|
||||
#define PAP_PEER 2
|
||||
#define CHAP_WITHPEER 4
|
||||
#define CHAP_PEER 8
|
||||
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
/* Used for storing a sequence of words. Usually malloced. */
|
||||
struct wordlist {
|
||||
struct wordlist *next;
|
||||
char word[1];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
extern char *crypt (const char *, const char *);
|
||||
|
||||
/* Prototypes for procedures local to this file. */
|
||||
|
||||
static void network_phase (int);
|
||||
static void check_idle (void *);
|
||||
static void connect_time_expired (void *);
|
||||
#if 0
|
||||
static int login (char *, char *, char **, int *);
|
||||
#endif
|
||||
static void logout (void);
|
||||
static int null_login (int);
|
||||
static int get_pap_passwd (int, char *, char *);
|
||||
static int have_pap_secret (void);
|
||||
static int have_chap_secret (char *, char *, u32_t);
|
||||
static int ip_addr_check (u32_t, struct wordlist *);
|
||||
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */
|
||||
static void set_allowed_addrs(int unit, struct wordlist *addrs);
|
||||
static void free_wordlist (struct wordlist *);
|
||||
#endif
|
||||
#if CBCP_SUPPORT > 0
|
||||
static void callback_phase (int);
|
||||
#endif
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||
/* The name by which the peer authenticated itself to us. */
|
||||
static char peer_authname[MAXNAMELEN];
|
||||
#endif
|
||||
|
||||
/* Records which authentication operations haven't completed yet. */
|
||||
static int auth_pending[NUM_PPP];
|
||||
|
||||
/* Set if we have successfully called login() */
|
||||
static int logged_in;
|
||||
|
||||
/* Set if we have run the /etc/ppp/auth-up script. */
|
||||
static int did_authup;
|
||||
|
||||
/* List of addresses which the peer may use. */
|
||||
static struct wordlist *addresses[NUM_PPP];
|
||||
|
||||
/* Number of network protocols which we have opened. */
|
||||
static int num_np_open;
|
||||
|
||||
/* Number of network protocols which have come up. */
|
||||
static int num_np_up;
|
||||
|
||||
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||
/* Set if we got the contents of passwd[] from the pap-secrets file. */
|
||||
static int passwd_from_file;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* An Open on LCP has requested a change from Dead to Establish phase.
|
||||
* Do what's necessary to bring the physical layer up.
|
||||
*/
|
||||
void link_required(int unit)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "link_required: %d\n", unit));
|
||||
}
|
||||
|
||||
/*
|
||||
* LCP has terminated the link; go to the Dead phase and take the
|
||||
* physical layer down.
|
||||
*/
|
||||
void link_terminated(int unit)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "link_terminated: %d\n", unit));
|
||||
|
||||
if (lcp_phase[unit] == PHASE_DEAD)
|
||||
return;
|
||||
if (logged_in)
|
||||
logout();
|
||||
lcp_phase[unit] = PHASE_DEAD;
|
||||
AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
|
||||
pppMainWakeup(unit);
|
||||
}
|
||||
|
||||
/*
|
||||
* LCP has gone down; it will either die or try to re-establish.
|
||||
*/
|
||||
void link_down(int unit)
|
||||
{
|
||||
int i;
|
||||
struct protent *protp;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "link_down: %d\n", unit));
|
||||
if (did_authup) {
|
||||
/* XXX Do link down processing. */
|
||||
did_authup = 0;
|
||||
}
|
||||
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
|
||||
if (!protp->enabled_flag)
|
||||
continue;
|
||||
if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)
|
||||
(*protp->lowerdown)(unit);
|
||||
if (protp->protocol < 0xC000 && protp->close != NULL)
|
||||
(*protp->close)(unit, "LCP down");
|
||||
}
|
||||
num_np_open = 0;
|
||||
num_np_up = 0;
|
||||
if (lcp_phase[unit] != PHASE_DEAD)
|
||||
lcp_phase[unit] = PHASE_TERMINATE;
|
||||
pppMainWakeup(unit);
|
||||
}
|
||||
|
||||
/*
|
||||
* The link is established.
|
||||
* Proceed to the Dead, Authenticate or Network phase as appropriate.
|
||||
*/
|
||||
void link_established(int unit)
|
||||
{
|
||||
int auth;
|
||||
int i;
|
||||
struct protent *protp;
|
||||
lcp_options *wo = &lcp_wantoptions[unit];
|
||||
lcp_options *go = &lcp_gotoptions[unit];
|
||||
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||
lcp_options *ho = &lcp_hisoptions[unit];
|
||||
#endif
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "link_established: %d\n", unit));
|
||||
/*
|
||||
* Tell higher-level protocols that LCP is up.
|
||||
*/
|
||||
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i)
|
||||
if (protp->protocol != PPP_LCP && protp->enabled_flag
|
||||
&& protp->lowerup != NULL)
|
||||
(*protp->lowerup)(unit);
|
||||
|
||||
if (ppp_settings.auth_required && !(go->neg_chap || go->neg_upap)) {
|
||||
/*
|
||||
* We wanted the peer to authenticate itself, and it refused:
|
||||
* treat it as though it authenticated with PAP using a username
|
||||
* of "" and a password of "". If that's not OK, boot it out.
|
||||
*/
|
||||
if (!wo->neg_upap || !null_login(unit)) {
|
||||
AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));
|
||||
lcp_close(unit, "peer refused to authenticate");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lcp_phase[unit] = PHASE_AUTHENTICATE;
|
||||
auth = 0;
|
||||
#if CHAP_SUPPORT > 0
|
||||
if (go->neg_chap) {
|
||||
ChapAuthPeer(unit, ppp_settings.our_name, go->chap_mdtype);
|
||||
auth |= CHAP_PEER;
|
||||
}
|
||||
#endif
|
||||
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
|
||||
else
|
||||
#endif
|
||||
#if PAP_SUPPORT > 0
|
||||
if (go->neg_upap) {
|
||||
upap_authpeer(unit);
|
||||
auth |= PAP_PEER;
|
||||
}
|
||||
#endif
|
||||
#if CHAP_SUPPORT > 0
|
||||
if (ho->neg_chap) {
|
||||
ChapAuthWithPeer(unit, ppp_settings.user, ho->chap_mdtype);
|
||||
auth |= CHAP_WITHPEER;
|
||||
}
|
||||
#endif
|
||||
#if PAP_SUPPORT > 0 && CHAP_SUPPORT > 0
|
||||
else
|
||||
#endif
|
||||
#if PAP_SUPPORT > 0
|
||||
if (ho->neg_upap) {
|
||||
if (ppp_settings.passwd[0] == 0) {
|
||||
passwd_from_file = 1;
|
||||
if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd))
|
||||
AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));
|
||||
}
|
||||
upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
|
||||
auth |= PAP_WITHPEER;
|
||||
}
|
||||
#endif
|
||||
auth_pending[unit] = auth;
|
||||
|
||||
if (!auth)
|
||||
network_phase(unit);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The peer has failed to authenticate himself using `protocol'.
|
||||
*/
|
||||
void auth_peer_fail(int unit, u16_t protocol)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X\n", unit, protocol));
|
||||
/*
|
||||
* Authentication failure: take the link down
|
||||
*/
|
||||
lcp_close(unit, "Authentication failed");
|
||||
}
|
||||
|
||||
|
||||
#if PAP_SUPPORT > 0 || CHAP_SUPPORT > 0
|
||||
/*
|
||||
* The peer has been successfully authenticated using `protocol'.
|
||||
*/
|
||||
void auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
|
||||
{
|
||||
int pbit;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X\n", unit, protocol));
|
||||
switch (protocol) {
|
||||
case PPP_CHAP:
|
||||
pbit = CHAP_PEER;
|
||||
break;
|
||||
case PPP_PAP:
|
||||
pbit = PAP_PEER;
|
||||
break;
|
||||
default:
|
||||
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
|
||||
protocol));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the authenticated name of the peer for later.
|
||||
*/
|
||||
if (namelen > sizeof(peer_authname) - 1)
|
||||
namelen = sizeof(peer_authname) - 1;
|
||||
BCOPY(name, peer_authname, namelen);
|
||||
peer_authname[namelen] = 0;
|
||||
|
||||
/*
|
||||
* If there is no more authentication still to be done,
|
||||
* proceed to the network (or callback) phase.
|
||||
*/
|
||||
if ((auth_pending[unit] &= ~pbit) == 0)
|
||||
network_phase(unit);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have failed to authenticate ourselves to the peer using `protocol'.
|
||||
*/
|
||||
void auth_withpeer_fail(int unit, u16_t protocol)
|
||||
{
|
||||
int errCode = PPPERR_AUTHFAIL;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X\n", unit, protocol));
|
||||
if (passwd_from_file)
|
||||
BZERO(ppp_settings.passwd, MAXSECRETLEN);
|
||||
/*
|
||||
* XXX Warning: the unit number indicates the interface which is
|
||||
* not necessarily the PPP connection. It works here as long
|
||||
* as we are only supporting PPP interfaces.
|
||||
*/
|
||||
pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode);
|
||||
|
||||
/*
|
||||
* We've failed to authenticate ourselves to our peer.
|
||||
* He'll probably take the link down, and there's not much
|
||||
* we can do except wait for that.
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* We have successfully authenticated ourselves with the peer using `protocol'.
|
||||
*/
|
||||
void auth_withpeer_success(int unit, u16_t protocol)
|
||||
{
|
||||
int pbit;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X\n", unit, protocol));
|
||||
switch (protocol) {
|
||||
case PPP_CHAP:
|
||||
pbit = CHAP_WITHPEER;
|
||||
break;
|
||||
case PPP_PAP:
|
||||
if (passwd_from_file)
|
||||
BZERO(ppp_settings.passwd, MAXSECRETLEN);
|
||||
pbit = PAP_WITHPEER;
|
||||
break;
|
||||
default:
|
||||
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
|
||||
protocol));
|
||||
pbit = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no more authentication still being done,
|
||||
* proceed to the network (or callback) phase.
|
||||
*/
|
||||
if ((auth_pending[unit] &= ~pbit) == 0)
|
||||
network_phase(unit);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* np_up - a network protocol has come up.
|
||||
*/
|
||||
void np_up(int unit, u16_t proto)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X\n", unit, proto));
|
||||
if (num_np_up == 0) {
|
||||
AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit));
|
||||
/*
|
||||
* At this point we consider that the link has come up successfully.
|
||||
*/
|
||||
if (ppp_settings.idle_time_limit > 0)
|
||||
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit);
|
||||
|
||||
/*
|
||||
* Set a timeout to close the connection once the maximum
|
||||
* connect time has expired.
|
||||
*/
|
||||
if (ppp_settings.maxconnect > 0)
|
||||
TIMEOUT(connect_time_expired, 0, ppp_settings.maxconnect);
|
||||
}
|
||||
++num_np_up;
|
||||
}
|
||||
|
||||
/*
|
||||
* np_down - a network protocol has gone down.
|
||||
*/
|
||||
void np_down(int unit, u16_t proto)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "np_down: %d proto=%X\n", unit, proto));
|
||||
if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) {
|
||||
UNTIMEOUT(check_idle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* np_finished - a network protocol has finished using the link.
|
||||
*/
|
||||
void np_finished(int unit, u16_t proto)
|
||||
{
|
||||
AUTHDEBUG((LOG_INFO, "np_finished: %d proto=%X\n", unit, proto));
|
||||
if (--num_np_open <= 0) {
|
||||
/* no further use for the link: shut up shop. */
|
||||
lcp_close(0, "No network protocols running");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* auth_reset - called when LCP is starting negotiations to recheck
|
||||
* authentication options, i.e. whether we have appropriate secrets
|
||||
* to use for authenticating ourselves and/or the peer.
|
||||
*/
|
||||
void auth_reset(int unit)
|
||||
{
|
||||
lcp_options *go = &lcp_gotoptions[unit];
|
||||
lcp_options *ao = &lcp_allowoptions[0];
|
||||
ipcp_options *ipwo = &ipcp_wantoptions[0];
|
||||
u32_t remote;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit));
|
||||
ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL));
|
||||
ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/;
|
||||
|
||||
if (go->neg_upap && !have_pap_secret())
|
||||
go->neg_upap = 0;
|
||||
if (go->neg_chap) {
|
||||
remote = ipwo->accept_remote? 0: ipwo->hisaddr;
|
||||
if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote))
|
||||
go->neg_chap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if PAP_SUPPORT > 0
|
||||
/*
|
||||
* check_passwd - Check the user name and passwd against the PAP secrets
|
||||
* file. If requested, also check against the system password database,
|
||||
* and login the user if OK.
|
||||
*
|
||||
* returns:
|
||||
* UPAP_AUTHNAK: Authentication failed.
|
||||
* UPAP_AUTHACK: Authentication succeeded.
|
||||
* In either case, msg points to an appropriate message.
|
||||
*/
|
||||
int check_passwd(
|
||||
int unit,
|
||||
char *auser,
|
||||
int userlen,
|
||||
char *apasswd,
|
||||
int passwdlen,
|
||||
char **msg,
|
||||
int *msglen
|
||||
)
|
||||
{
|
||||
#if 1
|
||||
*msg = (char *) 0;
|
||||
return UPAP_AUTHACK; /* XXX Assume all entries OK. */
|
||||
#else
|
||||
int ret = 0;
|
||||
struct wordlist *addrs = NULL;
|
||||
char passwd[256], user[256];
|
||||
char secret[MAXWORDLEN];
|
||||
static u_short attempts = 0;
|
||||
|
||||
/*
|
||||
* Make copies of apasswd and auser, then null-terminate them.
|
||||
*/
|
||||
BCOPY(apasswd, passwd, passwdlen);
|
||||
passwd[passwdlen] = '\0';
|
||||
BCOPY(auser, user, userlen);
|
||||
user[userlen] = '\0';
|
||||
*msg = (char *) 0;
|
||||
|
||||
/* XXX Validate user name and password. */
|
||||
ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */
|
||||
|
||||
if (ret == UPAP_AUTHNAK) {
|
||||
if (*msg == (char *) 0)
|
||||
*msg = "Login incorrect";
|
||||
*msglen = strlen(*msg);
|
||||
/*
|
||||
* Frustrate passwd stealer programs.
|
||||
* Allow 10 tries, but start backing off after 3 (stolen from login).
|
||||
* On 10'th, drop the connection.
|
||||
*/
|
||||
if (attempts++ >= 10) {
|
||||
AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));
|
||||
/*ppp_panic("Excess Bad Logins");*/
|
||||
}
|
||||
if (attempts > 3) {
|
||||
sys_msleep((attempts - 3) * 5);
|
||||
}
|
||||
if (addrs != NULL) {
|
||||
free_wordlist(addrs);
|
||||
}
|
||||
} else {
|
||||
attempts = 0; /* Reset count */
|
||||
if (*msg == (char *) 0)
|
||||
*msg = "Login ok";
|
||||
*msglen = strlen(*msg);
|
||||
set_allowed_addrs(unit, addrs);
|
||||
}
|
||||
|
||||
BZERO(passwd, sizeof(passwd));
|
||||
BZERO(secret, sizeof(secret));
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* auth_ip_addr - check whether the peer is authorized to use
|
||||
* a given IP address. Returns 1 if authorized, 0 otherwise.
|
||||
*/
|
||||
int auth_ip_addr(int unit, u32_t addr)
|
||||
{
|
||||
return ip_addr_check(addr, addresses[unit]);
|
||||
}
|
||||
|
||||
/*
|
||||
* bad_ip_adrs - return 1 if the IP address is one we don't want
|
||||
* to use, such as an address in the loopback net or a multicast address.
|
||||
* addr is in network byte order.
|
||||
*/
|
||||
int bad_ip_adrs(u32_t addr)
|
||||
{
|
||||
addr = ntohl(addr);
|
||||
return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
|
||||
|| IN_MULTICAST(addr) || IN_BADCLASS(addr);
|
||||
}
|
||||
|
||||
|
||||
#if CHAP_SUPPORT > 0
|
||||
/*
|
||||
* get_secret - open the CHAP secret file and return the secret
|
||||
* for authenticating the given client on the given server.
|
||||
* (We could be either client or server).
|
||||
*/
|
||||
int get_secret(
|
||||
int unit,
|
||||
char *client,
|
||||
char *server,
|
||||
char *secret,
|
||||
int *secret_len,
|
||||
int save_addrs
|
||||
)
|
||||
{
|
||||
#if 1
|
||||
int len;
|
||||
struct wordlist *addrs;
|
||||
|
||||
addrs = NULL;
|
||||
|
||||
if(!client || !client[0] || strcmp(client, ppp_settings.user)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = strlen(ppp_settings.passwd);
|
||||
if (len > MAXSECRETLEN) {
|
||||
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
|
||||
len = MAXSECRETLEN;
|
||||
}
|
||||
BCOPY(ppp_settings.passwd, secret, len);
|
||||
*secret_len = len;
|
||||
|
||||
return 1;
|
||||
#else
|
||||
int ret = 0, len;
|
||||
struct wordlist *addrs;
|
||||
char secbuf[MAXWORDLEN];
|
||||
|
||||
addrs = NULL;
|
||||
secbuf[0] = 0;
|
||||
|
||||
/* XXX Find secret. */
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
if (save_addrs)
|
||||
set_allowed_addrs(unit, addrs);
|
||||
|
||||
len = strlen(secbuf);
|
||||
if (len > MAXSECRETLEN) {
|
||||
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
|
||||
len = MAXSECRETLEN;
|
||||
}
|
||||
BCOPY(secbuf, secret, len);
|
||||
BZERO(secbuf, sizeof(secbuf));
|
||||
*secret_len = len;
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
/*
|
||||
* auth_check_options - called to check authentication options.
|
||||
*/
|
||||
void auth_check_options(void)
|
||||
{
|
||||
lcp_options *wo = &lcp_wantoptions[0];
|
||||
int can_auth;
|
||||
ipcp_options *ipwo = &ipcp_wantoptions[0];
|
||||
u32_t remote;
|
||||
|
||||
/* Default our_name to hostname, and user to our_name */
|
||||
if (ppp_settings.our_name[0] == 0 || ppp_settings.usehostname)
|
||||
strcpy(ppp_settings.our_name, ppp_settings.hostname);
|
||||
if (ppp_settings.user[0] == 0)
|
||||
strcpy(ppp_settings.user, ppp_settings.our_name);
|
||||
|
||||
/* If authentication is required, ask peer for CHAP or PAP. */
|
||||
if (ppp_settings.auth_required && !wo->neg_chap && !wo->neg_upap) {
|
||||
wo->neg_chap = 1;
|
||||
wo->neg_upap = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether we have appropriate secrets to use
|
||||
* to authenticate the peer.
|
||||
*/
|
||||
can_auth = wo->neg_upap && have_pap_secret();
|
||||
if (!can_auth && wo->neg_chap) {
|
||||
remote = ipwo->accept_remote? 0: ipwo->hisaddr;
|
||||
can_auth = have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote);
|
||||
}
|
||||
|
||||
if (ppp_settings.auth_required && !can_auth) {
|
||||
ppp_panic("No auth secret");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* Proceed to the network phase.
|
||||
*/
|
||||
static void network_phase(int unit)
|
||||
{
|
||||
int i;
|
||||
struct protent *protp;
|
||||
lcp_options *go = &lcp_gotoptions[unit];
|
||||
|
||||
/*
|
||||
* If the peer had to authenticate, run the auth-up script now.
|
||||
*/
|
||||
if ((go->neg_chap || go->neg_upap) && !did_authup) {
|
||||
/* XXX Do setup for peer authentication. */
|
||||
did_authup = 1;
|
||||
}
|
||||
|
||||
#if CBCP_SUPPORT > 0
|
||||
/*
|
||||
* If we negotiated callback, do it now.
|
||||
*/
|
||||
if (go->neg_cbcp) {
|
||||
lcp_phase[unit] = PHASE_CALLBACK;
|
||||
(*cbcp_protent.open)(unit);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
lcp_phase[unit] = PHASE_NETWORK;
|
||||
for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i)
|
||||
if (protp->protocol < 0xC000 && protp->enabled_flag
|
||||
&& protp->open != NULL) {
|
||||
(*protp->open)(unit);
|
||||
if (protp->protocol != PPP_CCP)
|
||||
++num_np_open;
|
||||
}
|
||||
|
||||
if (num_np_open == 0)
|
||||
/* nothing to do */
|
||||
lcp_close(0, "No network protocols running");
|
||||
}
|
||||
|
||||
/*
|
||||
* check_idle - check whether the link has been idle for long
|
||||
* enough that we can shut it down.
|
||||
*/
|
||||
static void check_idle(void *arg)
|
||||
{
|
||||
struct ppp_idle idle;
|
||||
u_short itime;
|
||||
|
||||
(void)arg;
|
||||
if (!get_idle_time(0, &idle))
|
||||
return;
|
||||
itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
|
||||
if (itime >= ppp_settings.idle_time_limit) {
|
||||
/* link is idle: shut it down. */
|
||||
AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n"));
|
||||
lcp_close(0, "Link inactive");
|
||||
} else {
|
||||
TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* connect_time_expired - log a message and close the connection.
|
||||
*/
|
||||
static void connect_time_expired(void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
|
||||
AUTHDEBUG((LOG_INFO, "Connect time expired\n"));
|
||||
lcp_close(0, "Connect time expired"); /* Close connection */
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* login - Check the user name and password against the system
|
||||
* password database, and login the user if OK.
|
||||
*
|
||||
* returns:
|
||||
* UPAP_AUTHNAK: Login failed.
|
||||
* UPAP_AUTHACK: Login succeeded.
|
||||
* In either case, msg points to an appropriate message.
|
||||
*/
|
||||
static int login(char *user, char *passwd, char **msg, int *msglen)
|
||||
{
|
||||
/* XXX Fail until we decide that we want to support logins. */
|
||||
return (UPAP_AUTHNAK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* logout - Logout the user.
|
||||
*/
|
||||
static void logout(void)
|
||||
{
|
||||
logged_in = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* null_login - Check if a username of "" and a password of "" are
|
||||
* acceptable, and iff so, set the list of acceptable IP addresses
|
||||
* and return 1.
|
||||
*/
|
||||
static int null_login(int unit)
|
||||
{
|
||||
(void)unit;
|
||||
/* XXX Fail until we decide that we want to support logins. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* get_pap_passwd - get a password for authenticating ourselves with
|
||||
* our peer using PAP. Returns 1 on success, 0 if no suitable password
|
||||
* could be found.
|
||||
*/
|
||||
static int get_pap_passwd(int unit, char *user, char *passwd)
|
||||
{
|
||||
/* normally we would reject PAP if no password is provided,
|
||||
but this causes problems with some providers (like CHT in Taiwan)
|
||||
who incorrectly request PAP and expect a bogus/empty password, so
|
||||
always provide a default user/passwd of "none"/"none"
|
||||
*/
|
||||
if(user)
|
||||
strcpy(user, "none");
|
||||
if(passwd)
|
||||
strcpy(passwd, "none");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* have_pap_secret - check whether we have a PAP file with any
|
||||
* secrets that we could possibly use for authenticating the peer.
|
||||
*/
|
||||
static int have_pap_secret(void)
|
||||
{
|
||||
/* XXX Fail until we set up our passwords. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* have_chap_secret - check whether we have a CHAP file with a
|
||||
* secret that we could possibly use for authenticating `client'
|
||||
* on `server'. Either can be the null string, meaning we don't
|
||||
* know the identity yet.
|
||||
*/
|
||||
static int have_chap_secret(char *client, char *server, u32_t remote)
|
||||
{
|
||||
(void)client;
|
||||
(void)server;
|
||||
(void)remote;
|
||||
/* XXX Fail until we set up our passwords. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT > 0 */
|
||||
/*
|
||||
* set_allowed_addrs() - set the list of allowed addresses.
|
||||
*/
|
||||
static void set_allowed_addrs(int unit, struct wordlist *addrs)
|
||||
{
|
||||
if (addresses[unit] != NULL)
|
||||
free_wordlist(addresses[unit]);
|
||||
addresses[unit] = addrs;
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If there's only one authorized address we might as well
|
||||
* ask our peer for that one right away
|
||||
*/
|
||||
if (addrs != NULL && addrs->next == NULL) {
|
||||
char *p = addrs->word;
|
||||
struct ipcp_options *wo = &ipcp_wantoptions[unit];
|
||||
u32_t a;
|
||||
struct hostent *hp;
|
||||
|
||||
if (wo->hisaddr == 0 && *p != '!' && *p != '-'
|
||||
&& strchr(p, '/') == NULL) {
|
||||
hp = gethostbyname(p);
|
||||
if (hp != NULL && hp->h_addrtype == AF_INET)
|
||||
a = *(u32_t *)hp->h_addr;
|
||||
else
|
||||
a = inet_addr(p);
|
||||
if (a != (u32_t) -1)
|
||||
wo->hisaddr = a;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ip_addr_check(u32_t addr, struct wordlist *addrs)
|
||||
{
|
||||
|
||||
/* don't allow loopback or multicast address */
|
||||
if (bad_ip_adrs(addr))
|
||||
return 0;
|
||||
|
||||
if (addrs == NULL)
|
||||
return !ppp_settings.auth_required; /* no addresses authorized */
|
||||
|
||||
/* XXX All other addresses allowed. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0 /* PAP_SUPPORT > 0 || CHAP_SUPPORT */
|
||||
/*
|
||||
* free_wordlist - release memory allocated for a wordlist.
|
||||
*/
|
||||
static void free_wordlist(struct wordlist *wp)
|
||||
{
|
||||
struct wordlist *next;
|
||||
|
||||
while (wp != NULL) {
|
||||
next = wp->next;
|
||||
free(wp);
|
||||
wp = next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
94
Demo/Common/ethernet/lwIP/netif/ppp/auth.h
Normal file
94
Demo/Common/ethernet/lwIP/netif/ppp/auth.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*****************************************************************************
|
||||
* auth.h - PPP Authentication and phase control header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original derived from BSD pppd.h.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* pppd.h - PPP daemon global declarations.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
void link_required (int); /* we are starting to use the link */
|
||||
void link_terminated (int); /* we are finished with the link */
|
||||
void link_down (int); /* the LCP layer has left the Opened state */
|
||||
void link_established (int); /* the link is up; authenticate now */
|
||||
void np_up (int, u16_t); /* a network protocol has come up */
|
||||
void np_down (int, u16_t); /* a network protocol has gone down */
|
||||
void np_finished (int, u16_t); /* a network protocol no longer needs link */
|
||||
void auth_peer_fail (int, u16_t);/* peer failed to authenticate itself */
|
||||
|
||||
/* peer successfully authenticated itself */
|
||||
void auth_peer_success (int, u16_t, char *, int);
|
||||
|
||||
/* we failed to authenticate ourselves */
|
||||
void auth_withpeer_fail (int, u16_t);
|
||||
|
||||
/* we successfully authenticated ourselves */
|
||||
void auth_withpeer_success (int, u16_t);
|
||||
|
||||
/* check authentication options supplied */
|
||||
void auth_check_options (void);
|
||||
void auth_reset (int); /* check what secrets we have */
|
||||
|
||||
/* Check peer-supplied username/password */
|
||||
int check_passwd (int, char *, int, char *, int, char **, int *);
|
||||
|
||||
/* get "secret" for chap */
|
||||
int get_secret (int, char *, char *, char *, int *, int);
|
||||
|
||||
/* check if IP address is authorized */
|
||||
int auth_ip_addr (int, u32_t);
|
||||
|
||||
/* check if IP address is unreasonable */
|
||||
int bad_ip_adrs (u32_t);
|
||||
|
||||
|
||||
#endif /* AUTH_H */
|
872
Demo/Common/ethernet/lwIP/netif/ppp/chap.c
Normal file
872
Demo/Common/ethernet/lwIP/netif/ppp/chap.c
Normal file
|
@ -0,0 +1,872 @@
|
|||
/*** WARNING - THIS HAS NEVER BEEN FINISHED ***/
|
||||
/*****************************************************************************
|
||||
* chap.c - Network Challenge Handshake Authentication Protocol program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD chap.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* chap.c - Challenge Handshake Authentication Protocol.
|
||||
*
|
||||
* Copyright (c) 1993 The Australian National University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the Australian National University. The name of the University
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Copyright (c) 1991 Gregory M. Christy.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Gregory M. Christy. The name of the author may not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "magic.h"
|
||||
|
||||
#if CHAP_SUPPORT > 0
|
||||
|
||||
#include "randm.h"
|
||||
#include "auth.h"
|
||||
#include "md5.h"
|
||||
#include "chap.h"
|
||||
#include "chpms.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Protocol entry points.
|
||||
*/
|
||||
static void ChapInit (int);
|
||||
static void ChapLowerUp (int);
|
||||
static void ChapLowerDown (int);
|
||||
static void ChapInput (int, u_char *, int);
|
||||
static void ChapProtocolReject (int);
|
||||
static int ChapPrintPkt (u_char *, int,
|
||||
void (*) (void *, char *, ...), void *);
|
||||
|
||||
static void ChapChallengeTimeout (void *);
|
||||
static void ChapResponseTimeout (void *);
|
||||
static void ChapReceiveChallenge (chap_state *, u_char *, int, int);
|
||||
static void ChapRechallenge (void *);
|
||||
static void ChapReceiveResponse (chap_state *, u_char *, int, int);
|
||||
static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len);
|
||||
static void ChapSendStatus (chap_state *, int);
|
||||
static void ChapSendChallenge (chap_state *);
|
||||
static void ChapSendResponse (chap_state *);
|
||||
static void ChapGenChallenge (chap_state *);
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
|
||||
|
||||
struct protent chap_protent = {
|
||||
PPP_CHAP,
|
||||
ChapInit,
|
||||
ChapInput,
|
||||
ChapProtocolReject,
|
||||
ChapLowerUp,
|
||||
ChapLowerDown,
|
||||
NULL,
|
||||
NULL,
|
||||
#if 0
|
||||
ChapPrintPkt,
|
||||
NULL,
|
||||
#endif
|
||||
1,
|
||||
"CHAP",
|
||||
#if 0
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
static char *ChapCodenames[] = {
|
||||
"Challenge", "Response", "Success", "Failure"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* ChapAuthWithPeer - Authenticate us with our peer (start client).
|
||||
*
|
||||
*/
|
||||
void ChapAuthWithPeer(int unit, char *our_name, int digest)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
cstate->resp_name = our_name;
|
||||
cstate->resp_type = digest;
|
||||
|
||||
if (cstate->clientstate == CHAPCS_INITIAL ||
|
||||
cstate->clientstate == CHAPCS_PENDING) {
|
||||
/* lower layer isn't up - wait until later */
|
||||
cstate->clientstate = CHAPCS_PENDING;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We get here as a result of LCP coming up.
|
||||
* So even if CHAP was open before, we will
|
||||
* have to re-authenticate ourselves.
|
||||
*/
|
||||
cstate->clientstate = CHAPCS_LISTEN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapAuthPeer - Authenticate our peer (start server).
|
||||
*/
|
||||
void ChapAuthPeer(int unit, char *our_name, int digest)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
cstate->chal_name = our_name;
|
||||
cstate->chal_type = digest;
|
||||
|
||||
if (cstate->serverstate == CHAPSS_INITIAL ||
|
||||
cstate->serverstate == CHAPSS_PENDING) {
|
||||
/* lower layer isn't up - wait until later */
|
||||
cstate->serverstate = CHAPSS_PENDING;
|
||||
return;
|
||||
}
|
||||
|
||||
ChapGenChallenge(cstate);
|
||||
ChapSendChallenge(cstate); /* crank it up dude! */
|
||||
cstate->serverstate = CHAPSS_INITIAL_CHAL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* ChapInit - Initialize a CHAP unit.
|
||||
*/
|
||||
static void ChapInit(int unit)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
BZERO(cstate, sizeof(*cstate));
|
||||
cstate->unit = unit;
|
||||
cstate->clientstate = CHAPCS_INITIAL;
|
||||
cstate->serverstate = CHAPSS_INITIAL;
|
||||
cstate->timeouttime = CHAP_DEFTIMEOUT;
|
||||
cstate->max_transmits = CHAP_DEFTRANSMITS;
|
||||
/* random number generator is initialized in magic_init */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapChallengeTimeout - Timeout expired on sending challenge.
|
||||
*/
|
||||
static void ChapChallengeTimeout(void *arg)
|
||||
{
|
||||
chap_state *cstate = (chap_state *) arg;
|
||||
|
||||
/* if we aren't sending challenges, don't worry. then again we */
|
||||
/* probably shouldn't be here either */
|
||||
if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
|
||||
cstate->serverstate != CHAPSS_RECHALLENGE)
|
||||
return;
|
||||
|
||||
if (cstate->chal_transmits >= cstate->max_transmits) {
|
||||
/* give up on peer */
|
||||
CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n"));
|
||||
cstate->serverstate = CHAPSS_BADAUTH;
|
||||
auth_peer_fail(cstate->unit, PPP_CHAP);
|
||||
return;
|
||||
}
|
||||
|
||||
ChapSendChallenge(cstate); /* Re-send challenge */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapResponseTimeout - Timeout expired on sending response.
|
||||
*/
|
||||
static void ChapResponseTimeout(void *arg)
|
||||
{
|
||||
chap_state *cstate = (chap_state *) arg;
|
||||
|
||||
/* if we aren't sending a response, don't worry. */
|
||||
if (cstate->clientstate != CHAPCS_RESPONSE)
|
||||
return;
|
||||
|
||||
ChapSendResponse(cstate); /* re-send response */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapRechallenge - Time to challenge the peer again.
|
||||
*/
|
||||
static void ChapRechallenge(void *arg)
|
||||
{
|
||||
chap_state *cstate = (chap_state *) arg;
|
||||
|
||||
/* if we aren't sending a response, don't worry. */
|
||||
if (cstate->serverstate != CHAPSS_OPEN)
|
||||
return;
|
||||
|
||||
ChapGenChallenge(cstate);
|
||||
ChapSendChallenge(cstate);
|
||||
cstate->serverstate = CHAPSS_RECHALLENGE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapLowerUp - The lower layer is up.
|
||||
*
|
||||
* Start up if we have pending requests.
|
||||
*/
|
||||
static void ChapLowerUp(int unit)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
if (cstate->clientstate == CHAPCS_INITIAL)
|
||||
cstate->clientstate = CHAPCS_CLOSED;
|
||||
else if (cstate->clientstate == CHAPCS_PENDING)
|
||||
cstate->clientstate = CHAPCS_LISTEN;
|
||||
|
||||
if (cstate->serverstate == CHAPSS_INITIAL)
|
||||
cstate->serverstate = CHAPSS_CLOSED;
|
||||
else if (cstate->serverstate == CHAPSS_PENDING) {
|
||||
ChapGenChallenge(cstate);
|
||||
ChapSendChallenge(cstate);
|
||||
cstate->serverstate = CHAPSS_INITIAL_CHAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapLowerDown - The lower layer is down.
|
||||
*
|
||||
* Cancel all timeouts.
|
||||
*/
|
||||
static void ChapLowerDown(int unit)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
/* Timeout(s) pending? Cancel if so. */
|
||||
if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
|
||||
cstate->serverstate == CHAPSS_RECHALLENGE)
|
||||
UNTIMEOUT(ChapChallengeTimeout, cstate);
|
||||
else if (cstate->serverstate == CHAPSS_OPEN
|
||||
&& cstate->chal_interval != 0)
|
||||
UNTIMEOUT(ChapRechallenge, cstate);
|
||||
if (cstate->clientstate == CHAPCS_RESPONSE)
|
||||
UNTIMEOUT(ChapResponseTimeout, cstate);
|
||||
|
||||
cstate->clientstate = CHAPCS_INITIAL;
|
||||
cstate->serverstate = CHAPSS_INITIAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapProtocolReject - Peer doesn't grok CHAP.
|
||||
*/
|
||||
static void ChapProtocolReject(int unit)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
|
||||
if (cstate->serverstate != CHAPSS_INITIAL &&
|
||||
cstate->serverstate != CHAPSS_CLOSED)
|
||||
auth_peer_fail(unit, PPP_CHAP);
|
||||
if (cstate->clientstate != CHAPCS_INITIAL &&
|
||||
cstate->clientstate != CHAPCS_CLOSED)
|
||||
auth_withpeer_fail(unit, PPP_CHAP);
|
||||
ChapLowerDown(unit); /* shutdown chap */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapInput - Input CHAP packet.
|
||||
*/
|
||||
static void ChapInput(int unit, u_char *inpacket, int packet_len)
|
||||
{
|
||||
chap_state *cstate = &chap[unit];
|
||||
u_char *inp;
|
||||
u_char code, id;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* Parse header (code, id and length).
|
||||
* If packet too short, drop it.
|
||||
*/
|
||||
inp = inpacket;
|
||||
if (packet_len < CHAP_HEADERLEN) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < CHAP_HEADERLEN) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n"));
|
||||
return;
|
||||
}
|
||||
if (len > packet_len) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
len -= CHAP_HEADERLEN;
|
||||
|
||||
/*
|
||||
* Action depends on code (as in fact it usually does :-).
|
||||
*/
|
||||
switch (code) {
|
||||
case CHAP_CHALLENGE:
|
||||
ChapReceiveChallenge(cstate, inp, id, len);
|
||||
break;
|
||||
|
||||
case CHAP_RESPONSE:
|
||||
ChapReceiveResponse(cstate, inp, id, len);
|
||||
break;
|
||||
|
||||
case CHAP_FAILURE:
|
||||
ChapReceiveFailure(cstate, inp, id, len);
|
||||
break;
|
||||
|
||||
case CHAP_SUCCESS:
|
||||
ChapReceiveSuccess(cstate, inp, id, len);
|
||||
break;
|
||||
|
||||
default: /* Need code reject? */
|
||||
CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapReceiveChallenge - Receive Challenge and send Response.
|
||||
*/
|
||||
static void ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len)
|
||||
{
|
||||
int rchallenge_len;
|
||||
u_char *rchallenge;
|
||||
int secret_len;
|
||||
char secret[MAXSECRETLEN];
|
||||
char rhostname[256];
|
||||
MD5_CTX mdContext;
|
||||
u_char hash[MD5_SIGNATURE_SIZE];
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id));
|
||||
if (cstate->clientstate == CHAPCS_CLOSED ||
|
||||
cstate->clientstate == CHAPCS_PENDING) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
GETCHAR(rchallenge_len, inp);
|
||||
len -= sizeof (u_char) + rchallenge_len; /* now name field length */
|
||||
if (len < 0) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
rchallenge = inp;
|
||||
INCPTR(rchallenge_len, inp);
|
||||
|
||||
if (len >= sizeof(rhostname))
|
||||
len = sizeof(rhostname) - 1;
|
||||
BCOPY(inp, rhostname, len);
|
||||
rhostname[len] = '\000';
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n",
|
||||
rhostname));
|
||||
|
||||
/* Microsoft doesn't send their name back in the PPP packet */
|
||||
if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) {
|
||||
strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname));
|
||||
rhostname[sizeof(rhostname) - 1] = 0;
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n",
|
||||
rhostname));
|
||||
}
|
||||
|
||||
/* get secret for authenticating ourselves with the specified host */
|
||||
if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
|
||||
secret, &secret_len, 0)) {
|
||||
secret_len = 0; /* assume null secret if can't find one */
|
||||
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname));
|
||||
}
|
||||
|
||||
/* cancel response send timeout if necessary */
|
||||
if (cstate->clientstate == CHAPCS_RESPONSE)
|
||||
UNTIMEOUT(ChapResponseTimeout, cstate);
|
||||
|
||||
cstate->resp_id = id;
|
||||
cstate->resp_transmits = 0;
|
||||
|
||||
/* generate MD based on negotiated type */
|
||||
switch (cstate->resp_type) {
|
||||
|
||||
case CHAP_DIGEST_MD5:
|
||||
MD5Init(&mdContext);
|
||||
MD5Update(&mdContext, &cstate->resp_id, 1);
|
||||
MD5Update(&mdContext, (u_char*)secret, secret_len);
|
||||
MD5Update(&mdContext, rchallenge, rchallenge_len);
|
||||
MD5Final(hash, &mdContext);
|
||||
BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
|
||||
cstate->resp_length = MD5_SIGNATURE_SIZE;
|
||||
break;
|
||||
|
||||
#ifdef CHAPMS
|
||||
case CHAP_MICROSOFT:
|
||||
ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->resp_type));
|
||||
return;
|
||||
}
|
||||
|
||||
BZERO(secret, sizeof(secret));
|
||||
ChapSendResponse(cstate);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapReceiveResponse - Receive and process response.
|
||||
*/
|
||||
static void ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len)
|
||||
{
|
||||
u_char *remmd, remmd_len;
|
||||
int secret_len, old_state;
|
||||
int code;
|
||||
char rhostname[256];
|
||||
MD5_CTX mdContext;
|
||||
char secret[MAXSECRETLEN];
|
||||
u_char hash[MD5_SIGNATURE_SIZE];
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->serverstate == CHAPSS_CLOSED ||
|
||||
cstate->serverstate == CHAPSS_PENDING) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n",
|
||||
cstate->serverstate));
|
||||
return;
|
||||
}
|
||||
|
||||
if (id != cstate->chal_id)
|
||||
return; /* doesn't match ID of last challenge */
|
||||
|
||||
/*
|
||||
* If we have received a duplicate or bogus Response,
|
||||
* we have to send the same answer (Success/Failure)
|
||||
* as we did for the first Response we saw.
|
||||
*/
|
||||
if (cstate->serverstate == CHAPSS_OPEN) {
|
||||
ChapSendStatus(cstate, CHAP_SUCCESS);
|
||||
return;
|
||||
}
|
||||
if (cstate->serverstate == CHAPSS_BADAUTH) {
|
||||
ChapSendStatus(cstate, CHAP_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < 2) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(remmd_len, inp); /* get length of MD */
|
||||
remmd = inp; /* get pointer to MD */
|
||||
INCPTR(remmd_len, inp);
|
||||
|
||||
len -= sizeof (u_char) + remmd_len;
|
||||
if (len < 0) {
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
UNTIMEOUT(ChapChallengeTimeout, cstate);
|
||||
|
||||
if (len >= sizeof(rhostname))
|
||||
len = sizeof(rhostname) - 1;
|
||||
BCOPY(inp, rhostname, len);
|
||||
rhostname[len] = '\000';
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n",
|
||||
rhostname));
|
||||
|
||||
/*
|
||||
* Get secret for authenticating them with us,
|
||||
* do the hash ourselves, and compare the result.
|
||||
*/
|
||||
code = CHAP_FAILURE;
|
||||
if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
|
||||
secret, &secret_len, 1)) {
|
||||
/* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */
|
||||
CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n",
|
||||
rhostname));
|
||||
} else {
|
||||
|
||||
/* generate MD based on negotiated type */
|
||||
switch (cstate->chal_type) {
|
||||
|
||||
case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
|
||||
if (remmd_len != MD5_SIGNATURE_SIZE)
|
||||
break; /* it's not even the right length */
|
||||
MD5Init(&mdContext);
|
||||
MD5Update(&mdContext, &cstate->chal_id, 1);
|
||||
MD5Update(&mdContext, (u_char*)secret, secret_len);
|
||||
MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
|
||||
MD5Final(hash, &mdContext);
|
||||
|
||||
/* compare local and remote MDs and send the appropriate status */
|
||||
if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
|
||||
code = CHAP_SUCCESS; /* they are the same! */
|
||||
break;
|
||||
|
||||
default:
|
||||
CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->chal_type));
|
||||
}
|
||||
}
|
||||
|
||||
BZERO(secret, sizeof(secret));
|
||||
ChapSendStatus(cstate, code);
|
||||
|
||||
if (code == CHAP_SUCCESS) {
|
||||
old_state = cstate->serverstate;
|
||||
cstate->serverstate = CHAPSS_OPEN;
|
||||
if (old_state == CHAPSS_INITIAL_CHAL) {
|
||||
auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
|
||||
}
|
||||
if (cstate->chal_interval != 0)
|
||||
TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
|
||||
} else {
|
||||
CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n"));
|
||||
cstate->serverstate = CHAPSS_BADAUTH;
|
||||
auth_peer_fail(cstate->unit, PPP_CHAP);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ChapReceiveSuccess - Receive Success
|
||||
*/
|
||||
static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
{
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->clientstate == CHAPCS_OPEN)
|
||||
/* presumably an answer to a duplicate response */
|
||||
return;
|
||||
|
||||
if (cstate->clientstate != CHAPCS_RESPONSE) {
|
||||
/* don't know what this is */
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
UNTIMEOUT(ChapResponseTimeout, cstate);
|
||||
|
||||
/*
|
||||
* Print message.
|
||||
*/
|
||||
if (len > 0)
|
||||
PRINTMSG(inp, len);
|
||||
|
||||
cstate->clientstate = CHAPCS_OPEN;
|
||||
|
||||
auth_withpeer_success(cstate->unit, PPP_CHAP);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapReceiveFailure - Receive failure.
|
||||
*/
|
||||
static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len)
|
||||
{
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id));
|
||||
|
||||
if (cstate->clientstate != CHAPCS_RESPONSE) {
|
||||
/* don't know what this is */
|
||||
CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n",
|
||||
cstate->clientstate));
|
||||
return;
|
||||
}
|
||||
|
||||
UNTIMEOUT(ChapResponseTimeout, cstate);
|
||||
|
||||
/*
|
||||
* Print message.
|
||||
*/
|
||||
if (len > 0)
|
||||
PRINTMSG(inp, len);
|
||||
|
||||
CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n"));
|
||||
auth_withpeer_fail(cstate->unit, PPP_CHAP);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapSendChallenge - Send an Authenticate challenge.
|
||||
*/
|
||||
static void ChapSendChallenge(chap_state *cstate)
|
||||
{
|
||||
u_char *outp;
|
||||
int chal_len, name_len;
|
||||
int outlen;
|
||||
|
||||
chal_len = cstate->chal_len;
|
||||
name_len = strlen(cstate->chal_name);
|
||||
outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
|
||||
|
||||
PUTCHAR(CHAP_CHALLENGE, outp);
|
||||
PUTCHAR(cstate->chal_id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
|
||||
PUTCHAR(chal_len, outp); /* put length of challenge */
|
||||
BCOPY(cstate->challenge, outp, chal_len);
|
||||
INCPTR(chal_len, outp);
|
||||
|
||||
BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
|
||||
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id));
|
||||
|
||||
TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
|
||||
++cstate->chal_transmits;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ChapSendStatus - Send a status response (ack or nak).
|
||||
*/
|
||||
static void ChapSendStatus(chap_state *cstate, int code)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen, msglen;
|
||||
char msg[256];
|
||||
|
||||
if (code == CHAP_SUCCESS)
|
||||
strcpy(msg, "Welcome!");
|
||||
else
|
||||
strcpy(msg, "I don't like you. Go 'way.");
|
||||
msglen = strlen(msg);
|
||||
|
||||
outlen = CHAP_HEADERLEN + msglen;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
|
||||
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(cstate->chal_id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
BCOPY(msg, outp, msglen);
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code,
|
||||
cstate->chal_id));
|
||||
}
|
||||
|
||||
/*
|
||||
* ChapGenChallenge is used to generate a pseudo-random challenge string of
|
||||
* a pseudo-random length between min_len and max_len. The challenge
|
||||
* string and its length are stored in *cstate, and various other fields of
|
||||
* *cstate are initialized.
|
||||
*/
|
||||
|
||||
static void ChapGenChallenge(chap_state *cstate)
|
||||
{
|
||||
int chal_len;
|
||||
u_char *ptr = cstate->challenge;
|
||||
int i;
|
||||
|
||||
/* pick a random challenge length between MIN_CHALLENGE_LENGTH and
|
||||
MAX_CHALLENGE_LENGTH */
|
||||
chal_len = (unsigned)
|
||||
((((magic() >> 16) *
|
||||
(MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16)
|
||||
+ MIN_CHALLENGE_LENGTH);
|
||||
cstate->chal_len = chal_len;
|
||||
cstate->chal_id = ++cstate->id;
|
||||
cstate->chal_transmits = 0;
|
||||
|
||||
/* generate a random string */
|
||||
for (i = 0; i < chal_len; i++ )
|
||||
*ptr++ = (char) (magic() & 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* ChapSendResponse - send a response packet with values as specified
|
||||
* in *cstate.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static void ChapSendResponse(chap_state *cstate)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen, md_len, name_len;
|
||||
|
||||
md_len = cstate->resp_length;
|
||||
name_len = strlen(cstate->resp_name);
|
||||
outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
|
||||
outp = outpacket_buf[cstate->unit];
|
||||
|
||||
MAKEHEADER(outp, PPP_CHAP);
|
||||
|
||||
PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
|
||||
PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
|
||||
PUTSHORT(outlen, outp); /* packet length */
|
||||
|
||||
PUTCHAR(md_len, outp); /* length of MD */
|
||||
BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
|
||||
INCPTR(md_len, outp);
|
||||
|
||||
BCOPY(cstate->resp_name, outp, name_len); /* append our name */
|
||||
|
||||
/* send the packet */
|
||||
pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN);
|
||||
|
||||
cstate->clientstate = CHAPCS_RESPONSE;
|
||||
TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
|
||||
++cstate->resp_transmits;
|
||||
}
|
||||
|
||||
/*
|
||||
* ChapPrintPkt - print the contents of a CHAP packet.
|
||||
*/
|
||||
static int ChapPrintPkt(
|
||||
u_char *p,
|
||||
int plen,
|
||||
void (*printer) (void *, char *, ...),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
int code, id, len;
|
||||
int clen, nlen;
|
||||
u_char x;
|
||||
|
||||
if (plen < CHAP_HEADERLEN)
|
||||
return 0;
|
||||
GETCHAR(code, p);
|
||||
GETCHAR(id, p);
|
||||
GETSHORT(len, p);
|
||||
if (len < CHAP_HEADERLEN || len > plen)
|
||||
return 0;
|
||||
|
||||
if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
|
||||
printer(arg, " %s", ChapCodenames[code-1]);
|
||||
else
|
||||
printer(arg, " code=0x%x", code);
|
||||
printer(arg, " id=0x%x", id);
|
||||
len -= CHAP_HEADERLEN;
|
||||
switch (code) {
|
||||
case CHAP_CHALLENGE:
|
||||
case CHAP_RESPONSE:
|
||||
if (len < 1)
|
||||
break;
|
||||
clen = p[0];
|
||||
if (len < clen + 1)
|
||||
break;
|
||||
++p;
|
||||
nlen = len - clen - 1;
|
||||
printer(arg, " <");
|
||||
for (; clen > 0; --clen) {
|
||||
GETCHAR(x, p);
|
||||
printer(arg, "%.2x", x);
|
||||
}
|
||||
printer(arg, ">, name = %.*Z", nlen, p);
|
||||
break;
|
||||
case CHAP_FAILURE:
|
||||
case CHAP_SUCCESS:
|
||||
printer(arg, " %.*Z", len, p);
|
||||
break;
|
||||
default:
|
||||
for (clen = len; clen > 0; --clen) {
|
||||
GETCHAR(x, p);
|
||||
printer(arg, " %.2x", x);
|
||||
}
|
||||
}
|
||||
|
||||
return len + CHAP_HEADERLEN;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
167
Demo/Common/ethernet/lwIP/netif/ppp/chap.h
Normal file
167
Demo/Common/ethernet/lwIP/netif/ppp/chap.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*****************************************************************************
|
||||
* chap.h - Network Challenge Handshake Authentication Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-03 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original built from BSD network code.
|
||||
******************************************************************************/
|
||||
/*
|
||||
* chap.h - Challenge Handshake Authentication Protocol definitions.
|
||||
*
|
||||
* Copyright (c) 1993 The Australian National University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the Australian National University. The name of the University
|
||||
* may not be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Copyright (c) 1991 Gregory M. Christy
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the author.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: chap.h,v 1.1 2003/05/27 14:37:56 jani Exp $
|
||||
*/
|
||||
|
||||
#ifndef CHAP_H
|
||||
#define CHAP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
|
||||
/* Code + ID + length */
|
||||
#define CHAP_HEADERLEN 4
|
||||
|
||||
/*
|
||||
* CHAP codes.
|
||||
*/
|
||||
|
||||
#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */
|
||||
#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */
|
||||
#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */
|
||||
#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */
|
||||
|
||||
#define CHAP_CHALLENGE 1
|
||||
#define CHAP_RESPONSE 2
|
||||
#define CHAP_SUCCESS 3
|
||||
#define CHAP_FAILURE 4
|
||||
|
||||
/*
|
||||
* Challenge lengths (for challenges we send) and other limits.
|
||||
*/
|
||||
#define MIN_CHALLENGE_LENGTH 32
|
||||
#define MAX_CHALLENGE_LENGTH 64
|
||||
#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
|
||||
|
||||
/*
|
||||
* Client (peer) states.
|
||||
*/
|
||||
#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
|
||||
#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
|
||||
#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
|
||||
#define CHAPCS_LISTEN 3 /* Listening for a challenge */
|
||||
#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
|
||||
#define CHAPCS_OPEN 5 /* We've received Success */
|
||||
|
||||
/*
|
||||
* Server (authenticator) states.
|
||||
*/
|
||||
#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
|
||||
#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
|
||||
#define CHAPSS_PENDING 2 /* Auth peer when lower up */
|
||||
#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
|
||||
#define CHAPSS_OPEN 4 /* We've sent a Success msg */
|
||||
#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
|
||||
#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* Each interface is described by a chap structure.
|
||||
*/
|
||||
|
||||
typedef struct chap_state {
|
||||
int unit; /* Interface unit number */
|
||||
int clientstate; /* Client state */
|
||||
int serverstate; /* Server state */
|
||||
u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */
|
||||
u_char chal_len; /* challenge length */
|
||||
u_char chal_id; /* ID of last challenge */
|
||||
u_char chal_type; /* hash algorithm for challenges */
|
||||
u_char id; /* Current id */
|
||||
char *chal_name; /* Our name to use with challenge */
|
||||
int chal_interval; /* Time until we challenge peer again */
|
||||
int timeouttime; /* Timeout time in seconds */
|
||||
int max_transmits; /* Maximum # of challenge transmissions */
|
||||
int chal_transmits; /* Number of transmissions of challenge */
|
||||
int resp_transmits; /* Number of transmissions of response */
|
||||
u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */
|
||||
u_char resp_length; /* length of response */
|
||||
u_char resp_id; /* ID for response messages */
|
||||
u_char resp_type; /* hash algorithm for responses */
|
||||
char *resp_name; /* Our name to send with response */
|
||||
} chap_state;
|
||||
|
||||
|
||||
/******************
|
||||
*** PUBLIC DATA ***
|
||||
******************/
|
||||
extern chap_state chap[];
|
||||
|
||||
extern struct protent chap_protent;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
void ChapAuthWithPeer (int, char *, int);
|
||||
void ChapAuthPeer (int, char *, int);
|
||||
|
||||
#endif /* CHAP_H */
|
||||
|
398
Demo/Common/ethernet/lwIP/netif/ppp/chpms.c
Normal file
398
Demo/Common/ethernet/lwIP/netif/ppp/chpms.c
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*** WARNING - THIS CODE HAS NOT BEEN FINISHED! ***/
|
||||
/*****************************************************************************
|
||||
* chpms.c - Network MicroSoft Challenge Handshake Authentication Protocol program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1997 by Global Election Systems Inc. All rights reserved.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD chap_ms.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* chap_ms.c - Microsoft MS-CHAP compatible implementation.
|
||||
*
|
||||
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
|
||||
* http://www.strataware.com/
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Eric Rosenquist. The name of the author may not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
|
||||
*
|
||||
* Implemented LANManager type password response to MS-CHAP challenges.
|
||||
* Now pppd provides both NT style and LANMan style blocks, and the
|
||||
* prefered is set by option "ms-lanman". Default is to use NT.
|
||||
* The hash text (StdText) was taken from Win95 RASAPI32.DLL.
|
||||
*
|
||||
* You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
|
||||
*/
|
||||
|
||||
#define USE_CRYPT
|
||||
|
||||
|
||||
#include "ppp.h"
|
||||
|
||||
#if MSCHAP_SUPPORT > 0
|
||||
|
||||
#include "md4.h"
|
||||
#ifndef USE_CRYPT
|
||||
#include "des.h"
|
||||
#endif
|
||||
#include "chap.h"
|
||||
#include "chpms.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
typedef struct {
|
||||
u_char LANManResp[24];
|
||||
u_char NTResp[24];
|
||||
u_char UseNT; /* If 1, ignore the LANMan response field */
|
||||
} MS_ChapResponse;
|
||||
/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
|
||||
in case this struct gets padded. */
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
|
||||
/* XXX Don't know what to do with these. */
|
||||
extern void setkey(const char *);
|
||||
extern void encrypt(char *, int);
|
||||
|
||||
static void DesEncrypt (u_char *, u_char *, u_char *);
|
||||
static void MakeKey (u_char *, u_char *);
|
||||
|
||||
#ifdef USE_CRYPT
|
||||
static void Expand (u_char *, u_char *);
|
||||
static void Collapse (u_char *, u_char *);
|
||||
#endif
|
||||
|
||||
static void ChallengeResponse(
|
||||
u_char *challenge, /* IN 8 octets */
|
||||
u_char *pwHash, /* IN 16 octets */
|
||||
u_char *response /* OUT 24 octets */
|
||||
);
|
||||
static void ChapMS_NT(
|
||||
char *rchallenge,
|
||||
int rchallenge_len,
|
||||
char *secret,
|
||||
int secret_len,
|
||||
MS_ChapResponse *response
|
||||
);
|
||||
static u_char Get7Bits(
|
||||
u_char *input,
|
||||
int startBit
|
||||
);
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
void ChapMS(
|
||||
chap_state *cstate,
|
||||
char *rchallenge,
|
||||
int rchallenge_len,
|
||||
char *secret,
|
||||
int secret_len
|
||||
)
|
||||
{
|
||||
MS_ChapResponse response;
|
||||
#ifdef MSLANMAN
|
||||
extern int ms_lanman;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", secret_len, secret));
|
||||
#endif
|
||||
BZERO(&response, sizeof(response));
|
||||
|
||||
/* Calculate both always */
|
||||
ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
|
||||
|
||||
#ifdef MSLANMAN
|
||||
ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
|
||||
|
||||
/* prefered method is set by option */
|
||||
response.UseNT = !ms_lanman;
|
||||
#else
|
||||
response.UseNT = 1;
|
||||
#endif
|
||||
|
||||
BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
|
||||
cstate->resp_length = MS_CHAP_RESPONSE_LEN;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
static void ChallengeResponse(
|
||||
u_char *challenge, /* IN 8 octets */
|
||||
u_char *pwHash, /* IN 16 octets */
|
||||
u_char *response /* OUT 24 octets */
|
||||
)
|
||||
{
|
||||
char ZPasswordHash[21];
|
||||
|
||||
BZERO(ZPasswordHash, sizeof(ZPasswordHash));
|
||||
BCOPY(pwHash, ZPasswordHash, 16);
|
||||
|
||||
#if 0
|
||||
log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
|
||||
#endif
|
||||
|
||||
DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
|
||||
DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
|
||||
DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
|
||||
|
||||
#if 0
|
||||
log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_CRYPT
|
||||
static void DesEncrypt(
|
||||
u_char *clear, /* IN 8 octets */
|
||||
u_char *key, /* IN 7 octets */
|
||||
u_char *cipher /* OUT 8 octets */
|
||||
)
|
||||
{
|
||||
u_char des_key[8];
|
||||
u_char crypt_key[66];
|
||||
u_char des_input[66];
|
||||
|
||||
MakeKey(key, des_key);
|
||||
|
||||
Expand(des_key, crypt_key);
|
||||
setkey(crypt_key);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
|
||||
#endif
|
||||
|
||||
Expand(clear, des_input);
|
||||
encrypt(des_input, 0);
|
||||
Collapse(des_input, cipher);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* USE_CRYPT */
|
||||
|
||||
static void DesEncrypt(
|
||||
u_char *clear, /* IN 8 octets */
|
||||
u_char *key, /* IN 7 octets */
|
||||
u_char *cipher /* OUT 8 octets */
|
||||
)
|
||||
{
|
||||
des_cblock des_key;
|
||||
des_key_schedule key_schedule;
|
||||
|
||||
MakeKey(key, des_key);
|
||||
|
||||
des_set_key(&des_key, key_schedule);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
|
||||
#endif
|
||||
|
||||
des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* USE_CRYPT */
|
||||
|
||||
|
||||
static u_char Get7Bits(
|
||||
u_char *input,
|
||||
int startBit
|
||||
)
|
||||
{
|
||||
register unsigned int word;
|
||||
|
||||
word = (unsigned)input[startBit / 8] << 8;
|
||||
word |= (unsigned)input[startBit / 8 + 1];
|
||||
|
||||
word >>= 15 - (startBit % 8 + 7);
|
||||
|
||||
return word & 0xFE;
|
||||
}
|
||||
|
||||
#ifdef USE_CRYPT
|
||||
|
||||
/* in == 8-byte string (expanded version of the 56-bit key)
|
||||
* out == 64-byte string where each byte is either 1 or 0
|
||||
* Note that the low-order "bit" is always ignored by by setkey()
|
||||
*/
|
||||
static void Expand(u_char *in, u_char *out)
|
||||
{
|
||||
int j, c;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 64; in++){
|
||||
c = *in;
|
||||
for(j = 7; j >= 0; j--)
|
||||
*out++ = (c >> j) & 01;
|
||||
i += 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* The inverse of Expand
|
||||
*/
|
||||
static void Collapse(u_char *in, u_char *out)
|
||||
{
|
||||
int j;
|
||||
int i;
|
||||
unsigned int c;
|
||||
|
||||
for (i = 0; i < 64; i += 8, out++) {
|
||||
c = 0;
|
||||
for (j = 7; j >= 0; j--, in++)
|
||||
c |= *in << j;
|
||||
*out = c & 0xff;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void MakeKey(
|
||||
u_char *key, /* IN 56 bit DES key missing parity bits */
|
||||
u_char *des_key /* OUT 64 bit DES key with parity bits added */
|
||||
)
|
||||
{
|
||||
des_key[0] = Get7Bits(key, 0);
|
||||
des_key[1] = Get7Bits(key, 7);
|
||||
des_key[2] = Get7Bits(key, 14);
|
||||
des_key[3] = Get7Bits(key, 21);
|
||||
des_key[4] = Get7Bits(key, 28);
|
||||
des_key[5] = Get7Bits(key, 35);
|
||||
des_key[6] = Get7Bits(key, 42);
|
||||
des_key[7] = Get7Bits(key, 49);
|
||||
|
||||
#ifndef USE_CRYPT
|
||||
des_set_odd_parity((des_cblock *)des_key);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n",
|
||||
key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
|
||||
CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ChapMS_NT(
|
||||
char *rchallenge,
|
||||
int rchallenge_len,
|
||||
char *secret,
|
||||
int secret_len,
|
||||
MS_ChapResponse *response
|
||||
)
|
||||
{
|
||||
int i;
|
||||
MDstruct md4Context;
|
||||
u_char unicodePassword[MAX_NT_PASSWORD * 2];
|
||||
static int low_byte_first = -1;
|
||||
|
||||
/* Initialize the Unicode version of the secret (== password). */
|
||||
/* This implicitly supports 8-bit ISO8859/1 characters. */
|
||||
BZERO(unicodePassword, sizeof(unicodePassword));
|
||||
for (i = 0; i < secret_len; i++)
|
||||
unicodePassword[i * 2] = (u_char)secret[i];
|
||||
|
||||
MDbegin(&md4Context);
|
||||
MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */
|
||||
|
||||
if (low_byte_first == -1)
|
||||
low_byte_first = (htons((unsigned short int)1) != 1);
|
||||
if (low_byte_first == 0)
|
||||
MDreverse((u_long *)&md4Context); /* sfb 961105 */
|
||||
|
||||
MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */
|
||||
|
||||
ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp);
|
||||
}
|
||||
|
||||
#ifdef MSLANMAN
|
||||
static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
|
||||
|
||||
static ChapMS_LANMan(
|
||||
char *rchallenge,
|
||||
int rchallenge_len,
|
||||
char *secret,
|
||||
int secret_len,
|
||||
MS_ChapResponse *response
|
||||
)
|
||||
{
|
||||
int i;
|
||||
u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
|
||||
u_char PasswordHash[16];
|
||||
|
||||
/* LANMan password is case insensitive */
|
||||
BZERO(UcasePassword, sizeof(UcasePassword));
|
||||
for (i = 0; i < secret_len; i++)
|
||||
UcasePassword[i] = (u_char)toupper(secret[i]);
|
||||
DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
|
||||
DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
|
||||
ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MSCHAP_SUPPORT */
|
||||
|
64
Demo/Common/ethernet/lwIP/netif/ppp/chpms.h
Normal file
64
Demo/Common/ethernet/lwIP/netif/ppp/chpms.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*****************************************************************************
|
||||
* chpms.h - Network Microsoft Challenge Handshake Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-01-30 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original built from BSD network code.
|
||||
******************************************************************************/
|
||||
/*
|
||||
* chap.h - Challenge Handshake Authentication Protocol definitions.
|
||||
*
|
||||
* Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
|
||||
* http://www.strataware.com/
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Eric Rosenquist. The name of the author may not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: chpms.h,v 1.3 2004/02/07 00:30:03 likewise Exp $
|
||||
*/
|
||||
|
||||
#ifndef CHPMS_H
|
||||
#define CHPMS_H
|
||||
|
||||
#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
|
||||
|
||||
void ChapMS (chap_state *, char *, int, char *, int);
|
||||
|
||||
#endif /* CHPMS_H */
|
838
Demo/Common/ethernet/lwIP/netif/ppp/fsm.c
Normal file
838
Demo/Common/ethernet/lwIP/netif/ppp/fsm.c
Normal file
|
@ -0,0 +1,838 @@
|
|||
/*****************************************************************************
|
||||
* fsm.c - Network Control Protocol Finite State Machine program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-01 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD fsm.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* fsm.c - {Link, IP} Control Protocol Finite State Machine.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Randomize fsm id on link/init.
|
||||
* Deal with variable outgoing MTU.
|
||||
*/
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "fsm.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
/*************************/
|
||||
/*** LOCAL DEFINITIONS ***/
|
||||
/*************************/
|
||||
|
||||
|
||||
/************************/
|
||||
/*** LOCAL DATA TYPES ***/
|
||||
/************************/
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
static void fsm_timeout (void *);
|
||||
static void fsm_rconfreq (fsm *, u_char, u_char *, int);
|
||||
static void fsm_rconfack (fsm *, int, u_char *, int);
|
||||
static void fsm_rconfnakrej (fsm *, int, int, u_char *, int);
|
||||
static void fsm_rtermreq (fsm *, int, u_char *, int);
|
||||
static void fsm_rtermack (fsm *);
|
||||
static void fsm_rcoderej (fsm *, u_char *, int);
|
||||
static void fsm_sconfreq (fsm *, int);
|
||||
|
||||
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
int peer_mru[NUM_PPP];
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
|
||||
/*
|
||||
* fsm_init - Initialize fsm.
|
||||
*
|
||||
* Initialize fsm state.
|
||||
*/
|
||||
void fsm_init(fsm *f)
|
||||
{
|
||||
f->state = INITIAL;
|
||||
f->flags = 0;
|
||||
f->id = 0; /* XXX Start with random id? */
|
||||
f->timeouttime = FSM_DEFTIMEOUT;
|
||||
f->maxconfreqtransmits = FSM_DEFMAXCONFREQS;
|
||||
f->maxtermtransmits = FSM_DEFMAXTERMREQS;
|
||||
f->maxnakloops = FSM_DEFMAXNAKLOOPS;
|
||||
f->term_reason_len = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_lowerup - The lower layer is up.
|
||||
*/
|
||||
void fsm_lowerup(fsm *f)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
switch( f->state ){
|
||||
case INITIAL:
|
||||
f->state = CLOSED;
|
||||
break;
|
||||
|
||||
case STARTING:
|
||||
if( f->flags & OPT_SILENT )
|
||||
f->state = STOPPED;
|
||||
else {
|
||||
/* Send an initial configure-request */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = REQSENT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Up event in state %d!\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: lowerup state %d -> %d\n",
|
||||
PROTO_NAME(f), oldState, f->state));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_lowerdown - The lower layer is down.
|
||||
*
|
||||
* Cancel all timeouts and inform upper layers.
|
||||
*/
|
||||
void fsm_lowerdown(fsm *f)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
switch( f->state ){
|
||||
case CLOSED:
|
||||
f->state = INITIAL;
|
||||
break;
|
||||
|
||||
case STOPPED:
|
||||
f->state = STARTING;
|
||||
if( f->callbacks->starting )
|
||||
(*f->callbacks->starting)(f);
|
||||
break;
|
||||
|
||||
case CLOSING:
|
||||
f->state = INITIAL;
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
break;
|
||||
|
||||
case STOPPING:
|
||||
case REQSENT:
|
||||
case ACKRCVD:
|
||||
case ACKSENT:
|
||||
f->state = STARTING;
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
break;
|
||||
|
||||
case OPENED:
|
||||
if( f->callbacks->down )
|
||||
(*f->callbacks->down)(f);
|
||||
f->state = STARTING;
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Down event in state %d!\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: lowerdown state %d -> %d\n",
|
||||
PROTO_NAME(f), oldState, f->state));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_open - Link is allowed to come up.
|
||||
*/
|
||||
void fsm_open(fsm *f)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
switch( f->state ){
|
||||
case INITIAL:
|
||||
f->state = STARTING;
|
||||
if( f->callbacks->starting )
|
||||
(*f->callbacks->starting)(f);
|
||||
break;
|
||||
|
||||
case CLOSED:
|
||||
if( f->flags & OPT_SILENT )
|
||||
f->state = STOPPED;
|
||||
else {
|
||||
/* Send an initial configure-request */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = REQSENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLOSING:
|
||||
f->state = STOPPING;
|
||||
/* fall through */
|
||||
case STOPPED:
|
||||
case OPENED:
|
||||
if( f->flags & OPT_RESTART ){
|
||||
fsm_lowerdown(f);
|
||||
fsm_lowerup(f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: open state %d -> %d\n",
|
||||
PROTO_NAME(f), oldState, f->state));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_close - Start closing connection.
|
||||
*
|
||||
* Cancel timeouts and either initiate close or possibly go directly to
|
||||
* the CLOSED state.
|
||||
*/
|
||||
void fsm_close(fsm *f, char *reason)
|
||||
{
|
||||
int oldState = f->state;
|
||||
|
||||
f->term_reason = reason;
|
||||
f->term_reason_len = (reason == NULL? 0: strlen(reason));
|
||||
switch( f->state ){
|
||||
case STARTING:
|
||||
f->state = INITIAL;
|
||||
break;
|
||||
case STOPPED:
|
||||
f->state = CLOSED;
|
||||
break;
|
||||
case STOPPING:
|
||||
f->state = CLOSING;
|
||||
break;
|
||||
|
||||
case REQSENT:
|
||||
case ACKRCVD:
|
||||
case ACKSENT:
|
||||
case OPENED:
|
||||
if( f->state != OPENED )
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
else if( f->callbacks->down )
|
||||
(*f->callbacks->down)(f); /* Inform upper layers we're down */
|
||||
|
||||
/* Init restart counter, send Terminate-Request */
|
||||
f->retransmits = f->maxtermtransmits;
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
|
||||
f->state = CLOSING;
|
||||
break;
|
||||
}
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d -> %d\n",
|
||||
PROTO_NAME(f), reason, oldState, f->state));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_sdata - Send some data.
|
||||
*
|
||||
* Used for all packets sent to our peer by this module.
|
||||
*/
|
||||
void fsm_sdata(
|
||||
fsm *f,
|
||||
u_char code,
|
||||
u_char id,
|
||||
u_char *data,
|
||||
int datalen
|
||||
)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen;
|
||||
|
||||
/* Adjust length to be smaller than MTU */
|
||||
outp = outpacket_buf[f->unit];
|
||||
if (datalen > peer_mru[f->unit] - (int)HEADERLEN)
|
||||
datalen = peer_mru[f->unit] - HEADERLEN;
|
||||
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
|
||||
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
|
||||
outlen = datalen + HEADERLEN;
|
||||
MAKEHEADER(outp, f->protocol);
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN);
|
||||
FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n",
|
||||
PROTO_NAME(f), code, id, outlen));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_input - Input packet.
|
||||
*/
|
||||
void fsm_input(fsm *f, u_char *inpacket, int l)
|
||||
{
|
||||
u_char *inp = inpacket;
|
||||
u_char code, id;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* Parse header (code, id and length).
|
||||
* If packet too short, drop it.
|
||||
*/
|
||||
if (l < HEADERLEN) {
|
||||
FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < HEADERLEN) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
if (len > l) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n",
|
||||
f->protocol));
|
||||
return;
|
||||
}
|
||||
len -= HEADERLEN; /* subtract header length */
|
||||
|
||||
if( f->state == INITIAL || f->state == STARTING ){
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.\n",
|
||||
f->protocol, f->state));
|
||||
return;
|
||||
}
|
||||
FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l));
|
||||
/*
|
||||
* Action depends on code.
|
||||
*/
|
||||
switch (code) {
|
||||
case CONFREQ:
|
||||
fsm_rconfreq(f, id, inp, len);
|
||||
break;
|
||||
|
||||
case CONFACK:
|
||||
fsm_rconfack(f, id, inp, len);
|
||||
break;
|
||||
|
||||
case CONFNAK:
|
||||
case CONFREJ:
|
||||
fsm_rconfnakrej(f, code, id, inp, len);
|
||||
break;
|
||||
|
||||
case TERMREQ:
|
||||
fsm_rtermreq(f, id, inp, len);
|
||||
break;
|
||||
|
||||
case TERMACK:
|
||||
fsm_rtermack(f);
|
||||
break;
|
||||
|
||||
case CODEREJ:
|
||||
fsm_rcoderej(f, inp, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
if( !f->callbacks->extcode
|
||||
|| !(*f->callbacks->extcode)(f, code, id, inp, len) )
|
||||
fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_protreject - Peer doesn't speak this protocol.
|
||||
*
|
||||
* Treat this as a catastrophic error (RXJ-).
|
||||
*/
|
||||
void fsm_protreject(fsm *f)
|
||||
{
|
||||
switch( f->state ){
|
||||
case CLOSING:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case CLOSED:
|
||||
f->state = CLOSED;
|
||||
if( f->callbacks->finished )
|
||||
(*f->callbacks->finished)(f);
|
||||
break;
|
||||
|
||||
case STOPPING:
|
||||
case REQSENT:
|
||||
case ACKRCVD:
|
||||
case ACKSENT:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
/* fall through */
|
||||
case STOPPED:
|
||||
f->state = STOPPED;
|
||||
if( f->callbacks->finished )
|
||||
(*f->callbacks->finished)(f);
|
||||
break;
|
||||
|
||||
case OPENED:
|
||||
if( f->callbacks->down )
|
||||
(*f->callbacks->down)(f);
|
||||
|
||||
/* Init restart counter, send Terminate-Request */
|
||||
f->retransmits = f->maxtermtransmits;
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
|
||||
f->state = STOPPING;
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
|
||||
/*
|
||||
* fsm_timeout - Timeout expired.
|
||||
*/
|
||||
static void fsm_timeout(void *arg)
|
||||
{
|
||||
fsm *f = (fsm *) arg;
|
||||
|
||||
switch (f->state) {
|
||||
case CLOSING:
|
||||
case STOPPING:
|
||||
if( f->retransmits <= 0 ){
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
/*
|
||||
* We've waited for an ack long enough. Peer probably heard us.
|
||||
*/
|
||||
f->state = (f->state == CLOSING)? CLOSED: STOPPED;
|
||||
if( f->callbacks->finished )
|
||||
(*f->callbacks->finished)(f);
|
||||
} else {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
/* Send Terminate-Request */
|
||||
fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
|
||||
(u_char *) f->term_reason, f->term_reason_len);
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
--f->retransmits;
|
||||
}
|
||||
break;
|
||||
|
||||
case REQSENT:
|
||||
case ACKRCVD:
|
||||
case ACKSENT:
|
||||
if (f->retransmits <= 0) {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
f->state = STOPPED;
|
||||
if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
|
||||
(*f->callbacks->finished)(f);
|
||||
|
||||
} else {
|
||||
FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
/* Retransmit the configure-request */
|
||||
if (f->callbacks->retransmit)
|
||||
(*f->callbacks->retransmit)(f);
|
||||
fsm_sconfreq(f, 1); /* Re-send Configure-Request */
|
||||
if( f->state == ACKRCVD )
|
||||
f->state = REQSENT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rconfreq - Receive Configure-Request.
|
||||
*/
|
||||
static void fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len)
|
||||
{
|
||||
int code, reject_if_disagree;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d\n",
|
||||
PROTO_NAME(f), id, f->state));
|
||||
switch( f->state ){
|
||||
case CLOSED:
|
||||
/* Go away, we're closed */
|
||||
fsm_sdata(f, TERMACK, id, NULL, 0);
|
||||
return;
|
||||
case CLOSING:
|
||||
case STOPPING:
|
||||
return;
|
||||
|
||||
case OPENED:
|
||||
/* Go down and restart negotiation */
|
||||
if( f->callbacks->down )
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||
break;
|
||||
|
||||
case STOPPED:
|
||||
/* Negotiation started by our peer */
|
||||
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||
f->state = REQSENT;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass the requested configuration options
|
||||
* to protocol-specific code for checking.
|
||||
*/
|
||||
if (f->callbacks->reqci){ /* Check CI */
|
||||
reject_if_disagree = (f->nakloops >= f->maxnakloops);
|
||||
code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
|
||||
}
|
||||
else if (len)
|
||||
code = CONFREJ; /* Reject all CI */
|
||||
else
|
||||
code = CONFACK;
|
||||
|
||||
/* send the Ack, Nak or Rej to the peer */
|
||||
fsm_sdata(f, (u_char)code, id, inp, len);
|
||||
|
||||
if (code == CONFACK) {
|
||||
if (f->state == ACKRCVD) {
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
f->state = OPENED;
|
||||
if (f->callbacks->up)
|
||||
(*f->callbacks->up)(f); /* Inform upper layers */
|
||||
}
|
||||
else
|
||||
f->state = ACKSENT;
|
||||
f->nakloops = 0;
|
||||
}
|
||||
else {
|
||||
/* we sent CONFACK or CONFREJ */
|
||||
if (f->state != ACKRCVD)
|
||||
f->state = REQSENT;
|
||||
if( code == CONFNAK )
|
||||
++f->nakloops;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rconfack - Receive Configure-Ack.
|
||||
*/
|
||||
static void fsm_rconfack(fsm *f, int id, u_char *inp, int len)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d\n",
|
||||
PROTO_NAME(f), id, f->state));
|
||||
|
||||
if (id != f->reqid || f->seen_ack) /* Expected id? */
|
||||
return; /* Nope, toss... */
|
||||
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
|
||||
(len == 0)) ){
|
||||
/* Ack is bad - ignore it */
|
||||
FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n",
|
||||
PROTO_NAME(f), len));
|
||||
return;
|
||||
}
|
||||
f->seen_ack = 1;
|
||||
|
||||
switch (f->state) {
|
||||
case CLOSED:
|
||||
case STOPPED:
|
||||
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||
break;
|
||||
|
||||
case REQSENT:
|
||||
f->state = ACKRCVD;
|
||||
f->retransmits = f->maxconfreqtransmits;
|
||||
break;
|
||||
|
||||
case ACKRCVD:
|
||||
/* Huh? an extra valid Ack? oh well... */
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = REQSENT;
|
||||
break;
|
||||
|
||||
case ACKSENT:
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
f->state = OPENED;
|
||||
f->retransmits = f->maxconfreqtransmits;
|
||||
if (f->callbacks->up)
|
||||
(*f->callbacks->up)(f); /* Inform upper layers */
|
||||
break;
|
||||
|
||||
case OPENED:
|
||||
/* Go down and restart negotiation */
|
||||
if (f->callbacks->down)
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||
f->state = REQSENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
|
||||
*/
|
||||
static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len)
|
||||
{
|
||||
int (*proc) (fsm *, u_char *, int);
|
||||
int ret;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d\n",
|
||||
PROTO_NAME(f), id, f->state));
|
||||
|
||||
if (id != f->reqid || f->seen_ack) /* Expected id? */
|
||||
return; /* Nope, toss... */
|
||||
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
|
||||
if (!proc || !(ret = proc(f, inp, len))) {
|
||||
/* Nak/reject is bad - ignore it */
|
||||
FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n",
|
||||
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
|
||||
return;
|
||||
}
|
||||
f->seen_ack = 1;
|
||||
|
||||
switch (f->state) {
|
||||
case CLOSED:
|
||||
case STOPPED:
|
||||
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||
break;
|
||||
|
||||
case REQSENT:
|
||||
case ACKSENT:
|
||||
/* They didn't agree to what we wanted - try another request */
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
if (ret < 0)
|
||||
f->state = STOPPED; /* kludge for stopping CCP */
|
||||
else
|
||||
fsm_sconfreq(f, 0); /* Send Configure-Request */
|
||||
break;
|
||||
|
||||
case ACKRCVD:
|
||||
/* Got a Nak/reject when we had already had an Ack?? oh well... */
|
||||
UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
|
||||
fsm_sconfreq(f, 0);
|
||||
f->state = REQSENT;
|
||||
break;
|
||||
|
||||
case OPENED:
|
||||
/* Go down and restart negotiation */
|
||||
if (f->callbacks->down)
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
fsm_sconfreq(f, 0); /* Send initial Configure-Request */
|
||||
f->state = REQSENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rtermreq - Receive Terminate-Req.
|
||||
*/
|
||||
static void fsm_rtermreq(fsm *f, int id, u_char *p, int len)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d\n",
|
||||
PROTO_NAME(f), id, f->state));
|
||||
|
||||
switch (f->state) {
|
||||
case ACKRCVD:
|
||||
case ACKSENT:
|
||||
f->state = REQSENT; /* Start over but keep trying */
|
||||
break;
|
||||
|
||||
case OPENED:
|
||||
if (len > 0) {
|
||||
FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p));
|
||||
} else {
|
||||
FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f)));
|
||||
}
|
||||
if (f->callbacks->down)
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
f->retransmits = 0;
|
||||
f->state = STOPPING;
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
break;
|
||||
}
|
||||
|
||||
fsm_sdata(f, TERMACK, (u_char)id, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rtermack - Receive Terminate-Ack.
|
||||
*/
|
||||
static void fsm_rtermack(fsm *f)
|
||||
{
|
||||
FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
|
||||
switch (f->state) {
|
||||
case CLOSING:
|
||||
UNTIMEOUT(fsm_timeout, f);
|
||||
f->state = CLOSED;
|
||||
if( f->callbacks->finished )
|
||||
(*f->callbacks->finished)(f);
|
||||
break;
|
||||
case STOPPING:
|
||||
UNTIMEOUT(fsm_timeout, f);
|
||||
f->state = STOPPED;
|
||||
if( f->callbacks->finished )
|
||||
(*f->callbacks->finished)(f);
|
||||
break;
|
||||
|
||||
case ACKRCVD:
|
||||
f->state = REQSENT;
|
||||
break;
|
||||
|
||||
case OPENED:
|
||||
if (f->callbacks->down)
|
||||
(*f->callbacks->down)(f); /* Inform upper layers */
|
||||
fsm_sconfreq(f, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_rcoderej - Receive an Code-Reject.
|
||||
*/
|
||||
static void fsm_rcoderej(fsm *f, u_char *inp, int len)
|
||||
{
|
||||
u_char code, id;
|
||||
|
||||
FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d\n",
|
||||
PROTO_NAME(f), f->state));
|
||||
|
||||
if (len < HEADERLEN) {
|
||||
FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n",
|
||||
PROTO_NAME(f), code, id));
|
||||
|
||||
if( f->state == ACKRCVD )
|
||||
f->state = REQSENT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fsm_sconfreq - Send a Configure-Request.
|
||||
*/
|
||||
static void fsm_sconfreq(fsm *f, int retransmit)
|
||||
{
|
||||
u_char *outp;
|
||||
int cilen;
|
||||
|
||||
if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
|
||||
/* Not currently negotiating - reset options */
|
||||
if( f->callbacks->resetci )
|
||||
(*f->callbacks->resetci)(f);
|
||||
f->nakloops = 0;
|
||||
}
|
||||
|
||||
if( !retransmit ){
|
||||
/* New request - reset retransmission counter, use new ID */
|
||||
f->retransmits = f->maxconfreqtransmits;
|
||||
f->reqid = ++f->id;
|
||||
}
|
||||
|
||||
f->seen_ack = 0;
|
||||
|
||||
/*
|
||||
* Make up the request packet
|
||||
*/
|
||||
outp = outpacket_buf[f->unit] + PPP_HDRLEN + HEADERLEN;
|
||||
if( f->callbacks->cilen && f->callbacks->addci ){
|
||||
cilen = (*f->callbacks->cilen)(f);
|
||||
if( cilen > peer_mru[f->unit] - (int)HEADERLEN )
|
||||
cilen = peer_mru[f->unit] - HEADERLEN;
|
||||
if (f->callbacks->addci)
|
||||
(*f->callbacks->addci)(f, outp, &cilen);
|
||||
} else
|
||||
cilen = 0;
|
||||
|
||||
/* send the request to our peer */
|
||||
fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
|
||||
|
||||
/* start the retransmit timer */
|
||||
--f->retransmits;
|
||||
TIMEOUT(fsm_timeout, f, f->timeouttime);
|
||||
|
||||
FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n",
|
||||
PROTO_NAME(f), f->reqid));
|
||||
}
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
187
Demo/Common/ethernet/lwIP/netif/ppp/fsm.h
Normal file
187
Demo/Common/ethernet/lwIP/netif/ppp/fsm.h
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*****************************************************************************
|
||||
* fsm.h - Network Control Protocol Finite State Machine header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-11-05 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original based on BSD code.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: fsm.h,v 1.1 2003/05/27 14:37:56 jani Exp $
|
||||
*/
|
||||
|
||||
#ifndef FSM_H
|
||||
#define FSM_H
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
************************* PUBLIC DEFINITIONS *********************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* LCP Packet header = Code, id, length.
|
||||
*/
|
||||
#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
|
||||
|
||||
|
||||
/*
|
||||
* CP (LCP, IPCP, etc.) codes.
|
||||
*/
|
||||
#define CONFREQ 1 /* Configuration Request */
|
||||
#define CONFACK 2 /* Configuration Ack */
|
||||
#define CONFNAK 3 /* Configuration Nak */
|
||||
#define CONFREJ 4 /* Configuration Reject */
|
||||
#define TERMREQ 5 /* Termination Request */
|
||||
#define TERMACK 6 /* Termination Ack */
|
||||
#define CODEREJ 7 /* Code Reject */
|
||||
|
||||
/*
|
||||
* Link states.
|
||||
*/
|
||||
#define INITIAL 0 /* Down, hasn't been opened */
|
||||
#define STARTING 1 /* Down, been opened */
|
||||
#define CLOSED 2 /* Up, hasn't been opened */
|
||||
#define STOPPED 3 /* Open, waiting for down event */
|
||||
#define CLOSING 4 /* Terminating the connection, not open */
|
||||
#define STOPPING 5 /* Terminating, but open */
|
||||
#define REQSENT 6 /* We've sent a Config Request */
|
||||
#define ACKRCVD 7 /* We've received a Config Ack */
|
||||
#define ACKSENT 8 /* We've sent a Config Ack */
|
||||
#define OPENED 9 /* Connection available */
|
||||
|
||||
|
||||
/*
|
||||
* Flags - indicate options controlling FSM operation
|
||||
*/
|
||||
#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
|
||||
#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
|
||||
#define OPT_SILENT 4 /* Wait for peer to speak first */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
************************* PUBLIC DATA TYPES **********************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Each FSM is described by an fsm structure and fsm callbacks.
|
||||
*/
|
||||
typedef struct fsm {
|
||||
int unit; /* Interface unit number */
|
||||
u_short protocol; /* Data Link Layer Protocol field value */
|
||||
int state; /* State */
|
||||
int flags; /* Contains option bits */
|
||||
u_char id; /* Current id */
|
||||
u_char reqid; /* Current request id */
|
||||
u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
|
||||
int timeouttime; /* Timeout time in milliseconds */
|
||||
int maxconfreqtransmits;/* Maximum Configure-Request transmissions */
|
||||
int retransmits; /* Number of retransmissions left */
|
||||
int maxtermtransmits; /* Maximum Terminate-Request transmissions */
|
||||
int nakloops; /* Number of nak loops since last ack */
|
||||
int maxnakloops; /* Maximum number of nak loops tolerated */
|
||||
struct fsm_callbacks* callbacks;/* Callback routines */
|
||||
char* term_reason; /* Reason for closing protocol */
|
||||
int term_reason_len; /* Length of term_reason */
|
||||
} fsm;
|
||||
|
||||
|
||||
typedef struct fsm_callbacks {
|
||||
void (*resetci) /* Reset our Configuration Information */
|
||||
(fsm*);
|
||||
int (*cilen) /* Length of our Configuration Information */
|
||||
(fsm*);
|
||||
void (*addci) /* Add our Configuration Information */
|
||||
(fsm*, u_char*, int*);
|
||||
int (*ackci) /* ACK our Configuration Information */
|
||||
(fsm*, u_char*, int);
|
||||
int (*nakci) /* NAK our Configuration Information */
|
||||
(fsm*, u_char*, int);
|
||||
int (*rejci) /* Reject our Configuration Information */
|
||||
(fsm*, u_char*, int);
|
||||
int (*reqci) /* Request peer's Configuration Information */
|
||||
(fsm*, u_char*, int*, int);
|
||||
void (*up) /* Called when fsm reaches OPENED state */
|
||||
(fsm*);
|
||||
void (*down) /* Called when fsm leaves OPENED state */
|
||||
(fsm*);
|
||||
void (*starting) /* Called when we want the lower layer */
|
||||
(fsm*);
|
||||
void (*finished) /* Called when we don't want the lower layer */
|
||||
(fsm*);
|
||||
void (*protreject) /* Called when Protocol-Reject received */
|
||||
(int);
|
||||
void (*retransmit) /* Retransmission is necessary */
|
||||
(fsm*);
|
||||
int (*extcode) /* Called when unknown code received */
|
||||
(fsm*, int, u_char, u_char*, int);
|
||||
char *proto_name; /* String name for protocol (for messages) */
|
||||
} fsm_callbacks;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*********************** PUBLIC DATA STRUCTURES *******************************
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* Variables
|
||||
*/
|
||||
extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
************************** PUBLIC FUNCTIONS **********************************
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
void fsm_init (fsm*);
|
||||
void fsm_lowerup (fsm*);
|
||||
void fsm_lowerdown (fsm*);
|
||||
void fsm_open (fsm*);
|
||||
void fsm_close (fsm*, char*);
|
||||
void fsm_input (fsm*, u_char*, int);
|
||||
void fsm_protreject (fsm*);
|
||||
void fsm_sdata (fsm*, u_char, u_char, u_char*, int);
|
||||
|
||||
|
||||
#endif /* FSM_H */
|
||||
|
1377
Demo/Common/ethernet/lwIP/netif/ppp/ipcp.c
Normal file
1377
Demo/Common/ethernet/lwIP/netif/ppp/ipcp.c
Normal file
File diff suppressed because it is too large
Load diff
126
Demo/Common/ethernet/lwIP/netif/ppp/ipcp.h
Normal file
126
Demo/Common/ethernet/lwIP/netif/ppp/ipcp.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*****************************************************************************
|
||||
* ipcp.h - PPP IP NCP: Internet Protocol Network Control Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* ipcp.h - IP Control Protocol definitions.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: ipcp.h,v 1.1 2003/05/27 14:37:56 jani Exp $
|
||||
*/
|
||||
|
||||
#ifndef IPCP_H
|
||||
#define IPCP_H
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* Options.
|
||||
*/
|
||||
#define CI_ADDRS 1 /* IP Addresses */
|
||||
#define CI_COMPRESSTYPE 2 /* Compression Type */
|
||||
#define CI_ADDR 3
|
||||
|
||||
#define CI_MS_WINS1 128 /* Primary WINS value */
|
||||
#define CI_MS_DNS1 129 /* Primary DNS value */
|
||||
#define CI_MS_WINS2 130 /* Secondary WINS value */
|
||||
#define CI_MS_DNS2 131 /* Secondary DNS value */
|
||||
|
||||
#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
|
||||
#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
|
||||
#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */
|
||||
/* maxslot and slot number compression) */
|
||||
|
||||
#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/
|
||||
#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
|
||||
/* compression option*/
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
typedef struct ipcp_options {
|
||||
u_int neg_addr : 1; /* Negotiate IP Address? */
|
||||
u_int old_addrs : 1; /* Use old (IP-Addresses) option? */
|
||||
u_int req_addr : 1; /* Ask peer to send IP address? */
|
||||
u_int default_route : 1; /* Assign default route through interface? */
|
||||
u_int proxy_arp : 1; /* Make proxy ARP entry for peer? */
|
||||
u_int neg_vj : 1; /* Van Jacobson Compression? */
|
||||
u_int old_vj : 1; /* use old (short) form of VJ option? */
|
||||
u_int accept_local : 1; /* accept peer's value for ouraddr */
|
||||
u_int accept_remote : 1; /* accept peer's value for hisaddr */
|
||||
u_int req_dns1 : 1; /* Ask peer to send primary DNS address? */
|
||||
u_int req_dns2 : 1; /* Ask peer to send secondary DNS address? */
|
||||
u_short vj_protocol; /* protocol value to use in VJ option */
|
||||
u_char maxslotindex; /* VJ slots - 1. */
|
||||
u_char cflag; /* VJ slot compression flag. */
|
||||
u32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
|
||||
u32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
|
||||
u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
|
||||
} ipcp_options;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
extern fsm ipcp_fsm[];
|
||||
extern ipcp_options ipcp_wantoptions[];
|
||||
extern ipcp_options ipcp_gotoptions[];
|
||||
extern ipcp_options ipcp_allowoptions[];
|
||||
extern ipcp_options ipcp_hisoptions[];
|
||||
|
||||
extern struct protent ipcp_protent;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
|
||||
#endif /* IPCP_H */
|
||||
|
1991
Demo/Common/ethernet/lwIP/netif/ppp/lcp.c
Normal file
1991
Demo/Common/ethernet/lwIP/netif/ppp/lcp.c
Normal file
File diff suppressed because it is too large
Load diff
169
Demo/Common/ethernet/lwIP/netif/ppp/lcp.h
Normal file
169
Demo/Common/ethernet/lwIP/netif/ppp/lcp.h
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*****************************************************************************
|
||||
* lcp.h - Network Link Control Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-11-05 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* lcp.h - Link Control Protocol definitions.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: lcp.h,v 1.1 2003/05/27 14:37:56 jani Exp $
|
||||
*/
|
||||
|
||||
#ifndef LCP_H
|
||||
#define LCP_H
|
||||
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
/*
|
||||
* Options.
|
||||
*/
|
||||
#define CI_MRU 1 /* Maximum Receive Unit */
|
||||
#define CI_ASYNCMAP 2 /* Async Control Character Map */
|
||||
#define CI_AUTHTYPE 3 /* Authentication Type */
|
||||
#define CI_QUALITY 4 /* Quality Protocol */
|
||||
#define CI_MAGICNUMBER 5 /* Magic Number */
|
||||
#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
|
||||
#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
|
||||
#define CI_CALLBACK 13 /* callback */
|
||||
#define CI_MRRU 17 /* max reconstructed receive unit; multilink */
|
||||
#define CI_SSNHF 18 /* short sequence numbers for multilink */
|
||||
#define CI_EPDISC 19 /* endpoint discriminator */
|
||||
|
||||
/*
|
||||
* LCP-specific packet types.
|
||||
*/
|
||||
#define PROTREJ 8 /* Protocol Reject */
|
||||
#define ECHOREQ 9 /* Echo Request */
|
||||
#define ECHOREP 10 /* Echo Reply */
|
||||
#define DISCREQ 11 /* Discard Request */
|
||||
#define CBCP_OPT 6 /* Use callback control protocol */
|
||||
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* The state of options is described by an lcp_options structure.
|
||||
*/
|
||||
typedef struct lcp_options {
|
||||
u_int passive : 1; /* Don't die if we don't get a response */
|
||||
u_int silent : 1; /* Wait for the other end to start first */
|
||||
u_int restart : 1; /* Restart vs. exit after close */
|
||||
u_int neg_mru : 1; /* Negotiate the MRU? */
|
||||
u_int neg_asyncmap : 1; /* Negotiate the async map? */
|
||||
u_int neg_upap : 1; /* Ask for UPAP authentication? */
|
||||
u_int neg_chap : 1; /* Ask for CHAP authentication? */
|
||||
u_int neg_magicnumber : 1; /* Ask for magic number? */
|
||||
u_int neg_pcompression : 1; /* HDLC Protocol Field Compression? */
|
||||
u_int neg_accompression : 1; /* HDLC Address/Control Field Compression? */
|
||||
u_int neg_lqr : 1; /* Negotiate use of Link Quality Reports */
|
||||
u_int neg_cbcp : 1; /* Negotiate use of CBCP */
|
||||
#ifdef PPP_MULTILINK
|
||||
u_int neg_mrru : 1; /* Negotiate multilink MRRU */
|
||||
u_int neg_ssnhf : 1; /* Negotiate short sequence numbers */
|
||||
u_int neg_endpoint : 1; /* Negotiate endpoint discriminator */
|
||||
#endif
|
||||
u_short mru; /* Value of MRU */
|
||||
#ifdef PPP_MULTILINK
|
||||
u_short mrru; /* Value of MRRU, and multilink enable */
|
||||
#endif
|
||||
u_char chap_mdtype; /* which MD type (hashing algorithm) */
|
||||
u32_t asyncmap; /* Value of async map */
|
||||
u32_t magicnumber;
|
||||
int numloops; /* Number of loops during magic number neg. */
|
||||
u32_t lqr_period; /* Reporting period for LQR 1/100ths second */
|
||||
#ifdef PPP_MULTILINK
|
||||
struct epdisc endpoint; /* endpoint discriminator */
|
||||
#endif
|
||||
} lcp_options;
|
||||
|
||||
/*
|
||||
* Values for phase from BSD pppd.h based on RFC 1661.
|
||||
*/
|
||||
typedef enum {
|
||||
PHASE_DEAD = 0,
|
||||
PHASE_INITIALIZE,
|
||||
PHASE_ESTABLISH,
|
||||
PHASE_AUTHENTICATE,
|
||||
PHASE_CALLBACK,
|
||||
PHASE_NETWORK,
|
||||
PHASE_TERMINATE
|
||||
} LinkPhase;
|
||||
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
|
||||
extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */
|
||||
extern lcp_options lcp_wantoptions[];
|
||||
extern lcp_options lcp_gotoptions[];
|
||||
extern lcp_options lcp_allowoptions[];
|
||||
extern lcp_options lcp_hisoptions[];
|
||||
extern ext_accm xmit_accm[];
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
void lcp_init (int);
|
||||
void lcp_open (int);
|
||||
void lcp_close (int, char *);
|
||||
void lcp_lowerup (int);
|
||||
void lcp_lowerdown (int);
|
||||
void lcp_sprotrej (int, u_char *, int); /* send protocol reject */
|
||||
|
||||
extern struct protent lcp_protent;
|
||||
|
||||
/* Default number of times we receive our magic number from the peer
|
||||
before deciding the link is looped-back. */
|
||||
#define DEFLOOPBACKFAIL 10
|
||||
|
||||
#endif /* LCP_H */
|
||||
|
79
Demo/Common/ethernet/lwIP/netif/ppp/magic.c
Normal file
79
Demo/Common/ethernet/lwIP/netif/ppp/magic.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*****************************************************************************
|
||||
* magic.c - Network Random Number Generator program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original based on BSD magic.c.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* magic.c - PPP Magic Number routines.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "ppp.h"
|
||||
#include "randm.h"
|
||||
#include "magic.h"
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* magicInit - Initialize the magic number generator.
|
||||
*
|
||||
* Since we use another random number generator that has its own
|
||||
* initialization, we do nothing here.
|
||||
*/
|
||||
void magicInit()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* magic - Returns the next magic number.
|
||||
*/
|
||||
u32_t magic()
|
||||
{
|
||||
return avRandom();
|
||||
}
|
||||
|
||||
|
64
Demo/Common/ethernet/lwIP/netif/ppp/magic.h
Normal file
64
Demo/Common/ethernet/lwIP/netif/ppp/magic.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*****************************************************************************
|
||||
* magic.h - Network Random Number Generator header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-04 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* magic.h - PPP Magic Number definitions.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* $Id: magic.h,v 1.1 2003/05/27 14:37:56 jani Exp $
|
||||
*/
|
||||
|
||||
#ifndef MAGIC_H
|
||||
#define MAGIC_H
|
||||
|
||||
/*****************************************************************************
|
||||
************************** PUBLIC FUNCTIONS **********************************
|
||||
*****************************************************************************/
|
||||
|
||||
void magicInit(void); /* Initialize the magic number generator */
|
||||
u32_t magic(void); /* Returns the next magic number */
|
||||
|
||||
#endif /* MAGIC_H */
|
306
Demo/Common/ethernet/lwIP/netif/ppp/md5.c
Normal file
306
Demo/Common/ethernet/lwIP/netif/ppp/md5.c
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
***********************************************************************
|
||||
** md5.c -- the source code for MD5 routines **
|
||||
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#include "ppp.h"
|
||||
#include "md5.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#if CHAP_SUPPORT > 0 || MD5_SUPPORT > 0
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Message-digest routines: **
|
||||
** To form the message digest for a message M **
|
||||
** (1) Initialize a context buffer mdContext using MD5Init **
|
||||
** (2) Call MD5Update on mdContext and M **
|
||||
** (3) Call MD5Final on mdContext **
|
||||
** The message digest is now in mdContext->digest[0...15] **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/* forward declaration */
|
||||
static void Transform (u32_t *buf, u32_t *in);
|
||||
|
||||
static unsigned char PADDING[64] = {
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/* F, G, H and I are basic MD5 functions */
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits */
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
|
||||
/* Rotation is separate from addition to prevent recomputation */
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{(a) += F ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
#define UL(x) x##UL
|
||||
#else
|
||||
#ifdef WIN32
|
||||
#define UL(x) x##UL
|
||||
#else
|
||||
#define UL(x) x
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The routine MD5Init initializes the message-digest context
|
||||
mdContext. All fields are set to zero.
|
||||
*/
|
||||
void MD5Init (MD5_CTX *mdContext)
|
||||
{
|
||||
mdContext->i[0] = mdContext->i[1] = (u32_t)0;
|
||||
|
||||
/* Load magic initialization constants.
|
||||
*/
|
||||
mdContext->buf[0] = (u32_t)0x67452301UL;
|
||||
mdContext->buf[1] = (u32_t)0xefcdab89UL;
|
||||
mdContext->buf[2] = (u32_t)0x98badcfeUL;
|
||||
mdContext->buf[3] = (u32_t)0x10325476UL;
|
||||
}
|
||||
|
||||
/* The routine MD5Update updates the message-digest context to
|
||||
account for the presence of each of the characters inBuf[0..inLen-1]
|
||||
in the message whose digest is being computed.
|
||||
*/
|
||||
void MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen)
|
||||
{
|
||||
u32_t in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
|
||||
#if 0
|
||||
ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", inLen, MIN(inLen, 20) * 2, inBuf);
|
||||
ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", inLen, inBuf);
|
||||
#endif
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* update number of bits */
|
||||
if ((mdContext->i[0] + ((u32_t)inLen << 3)) < mdContext->i[0])
|
||||
mdContext->i[1]++;
|
||||
mdContext->i[0] += ((u32_t)inLen << 3);
|
||||
mdContext->i[1] += ((u32_t)inLen >> 29);
|
||||
|
||||
while (inLen--) {
|
||||
/* add new character to buffer, increment mdi */
|
||||
mdContext->in[mdi++] = *inBuf++;
|
||||
|
||||
/* transform if necessary */
|
||||
if (mdi == 0x40) {
|
||||
for (i = 0, ii = 0; i < 16; i++, ii += 4)
|
||||
in[i] = (((u32_t)mdContext->in[ii+3]) << 24) |
|
||||
(((u32_t)mdContext->in[ii+2]) << 16) |
|
||||
(((u32_t)mdContext->in[ii+1]) << 8) |
|
||||
((u32_t)mdContext->in[ii]);
|
||||
Transform (mdContext->buf, in);
|
||||
mdi = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The routine MD5Final terminates the message-digest computation and
|
||||
ends with the desired message digest in mdContext->digest[0...15].
|
||||
*/
|
||||
void MD5Final (unsigned char hash[], MD5_CTX *mdContext)
|
||||
{
|
||||
u32_t in[16];
|
||||
int mdi;
|
||||
unsigned int i, ii;
|
||||
unsigned int padLen;
|
||||
|
||||
/* save number of bits */
|
||||
in[14] = mdContext->i[0];
|
||||
in[15] = mdContext->i[1];
|
||||
|
||||
/* compute number of bytes mod 64 */
|
||||
mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
|
||||
|
||||
/* pad out to 56 mod 64 */
|
||||
padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
|
||||
MD5Update (mdContext, PADDING, padLen);
|
||||
|
||||
/* append length in bits and transform */
|
||||
for (i = 0, ii = 0; i < 14; i++, ii += 4)
|
||||
in[i] = (((u32_t)mdContext->in[ii+3]) << 24) |
|
||||
(((u32_t)mdContext->in[ii+2]) << 16) |
|
||||
(((u32_t)mdContext->in[ii+1]) << 8) |
|
||||
((u32_t)mdContext->in[ii]);
|
||||
Transform (mdContext->buf, in);
|
||||
|
||||
/* store buffer in digest */
|
||||
for (i = 0, ii = 0; i < 4; i++, ii += 4) {
|
||||
mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
|
||||
mdContext->digest[ii+1] =
|
||||
(unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
|
||||
mdContext->digest[ii+2] =
|
||||
(unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
|
||||
mdContext->digest[ii+3] =
|
||||
(unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
memcpy(hash, mdContext->digest, 16);
|
||||
}
|
||||
|
||||
/* Basic MD5 step. Transforms buf based on in.
|
||||
*/
|
||||
static void Transform (u32_t *buf, u32_t *in)
|
||||
{
|
||||
u32_t a = buf[0], b = buf[1], c = buf[2], d = buf[3];
|
||||
|
||||
/* Round 1 */
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
|
||||
FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
|
||||
FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
|
||||
FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
|
||||
FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
|
||||
FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
|
||||
FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
|
||||
FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
|
||||
FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
|
||||
FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
|
||||
FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
|
||||
FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
|
||||
FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
|
||||
FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
|
||||
FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
|
||||
FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
|
||||
GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
|
||||
GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
|
||||
GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
|
||||
GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
|
||||
GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
|
||||
GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
|
||||
GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
|
||||
GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
|
||||
GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
|
||||
GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
|
||||
GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
|
||||
GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
|
||||
GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
|
||||
GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
|
||||
GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
|
||||
HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
|
||||
HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
|
||||
HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
|
||||
HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
|
||||
HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
|
||||
HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
|
||||
HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
|
||||
HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
|
||||
HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
|
||||
HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
|
||||
HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
|
||||
HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
|
||||
HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
|
||||
HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
|
||||
HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
|
||||
II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
|
||||
II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
|
||||
II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
|
||||
II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
|
||||
II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
|
||||
II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
|
||||
II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
|
||||
II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
|
||||
II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
|
||||
II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
|
||||
II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
|
||||
II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
|
||||
II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
|
||||
II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
|
||||
II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
55
Demo/Common/ethernet/lwIP/netif/ppp/md5.h
Normal file
55
Demo/Common/ethernet/lwIP/netif/ppp/md5.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
***********************************************************************
|
||||
** md5.h -- header file for implementation of MD5 **
|
||||
** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
|
||||
** Created: 2/17/90 RLR **
|
||||
** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
|
||||
** Revised (for MD5): RLR 4/27/91 **
|
||||
** -- G modified to have y&~z instead of y&z **
|
||||
** -- FF, GG, HH modified to add in last register done **
|
||||
** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
|
||||
** -- distinct additive constant for each step **
|
||||
** -- round 4 added, working mod 7 **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
***********************************************************************
|
||||
** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
|
||||
** **
|
||||
** License to copy and use this software is granted provided that **
|
||||
** it is identified as the "RSA Data Security, Inc. MD5 Message- **
|
||||
** Digest Algorithm" in all material mentioning or referencing this **
|
||||
** software or this function. **
|
||||
** **
|
||||
** License is also granted to make and use derivative works **
|
||||
** provided that such works are identified as "derived from the RSA **
|
||||
** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
|
||||
** material mentioning or referencing the derived work. **
|
||||
** **
|
||||
** RSA Data Security, Inc. makes no representations concerning **
|
||||
** either the merchantability of this software or the suitability **
|
||||
** of this software for any particular purpose. It is provided "as **
|
||||
** is" without express or implied warranty of any kind. **
|
||||
** **
|
||||
** These notices must be retained in any copies of any part of this **
|
||||
** documentation and/or software. **
|
||||
***********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef MD5_H
|
||||
#define MD5_H
|
||||
|
||||
/* Data structure for MD5 (Message-Digest) computation */
|
||||
typedef struct {
|
||||
u32_t i[2]; /* number of _bits_ handled mod 2^64 */
|
||||
u32_t buf[4]; /* scratch buffer */
|
||||
unsigned char in[64]; /* input buffer */
|
||||
unsigned char digest[16]; /* actual digest after MD5Final call */
|
||||
} MD5_CTX;
|
||||
|
||||
void MD5Init (MD5_CTX *mdContext);
|
||||
void MD5Update (MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen);
|
||||
void MD5Final (unsigned char hash[], MD5_CTX *mdContext);
|
||||
|
||||
#endif /* MD5_H */
|
608
Demo/Common/ethernet/lwIP/netif/ppp/pap.c
Normal file
608
Demo/Common/ethernet/lwIP/netif/ppp/pap.c
Normal file
|
@ -0,0 +1,608 @@
|
|||
/*****************************************************************************
|
||||
* pap.c - Network Password Authentication Protocol program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-12-12 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* upap.c - User/Password Authentication Protocol.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "ppp.h"
|
||||
#include "auth.h"
|
||||
#include "pap.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
#if PAP_SUPPORT > 0
|
||||
|
||||
/***********************************/
|
||||
/*** LOCAL FUNCTION DECLARATIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Protocol entry points.
|
||||
*/
|
||||
static void upap_init (int);
|
||||
static void upap_lowerup (int);
|
||||
static void upap_lowerdown (int);
|
||||
static void upap_input (int, u_char *, int);
|
||||
static void upap_protrej (int);
|
||||
|
||||
static void upap_timeout (void *);
|
||||
static void upap_reqtimeout (void *);
|
||||
static void upap_rauthreq (upap_state *, u_char *, int, int);
|
||||
static void upap_rauthack (upap_state *, u_char *, int, int);
|
||||
static void upap_rauthnak (upap_state *, u_char *, int, int);
|
||||
static void upap_sauthreq (upap_state *);
|
||||
static void upap_sresp (upap_state *, u_char, u_char, char *, int);
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************/
|
||||
/*** PUBLIC DATA STRUCTURES ***/
|
||||
/******************************/
|
||||
struct protent pap_protent = {
|
||||
PPP_PAP,
|
||||
upap_init,
|
||||
upap_input,
|
||||
upap_protrej,
|
||||
upap_lowerup,
|
||||
upap_lowerdown,
|
||||
NULL,
|
||||
NULL,
|
||||
#if 0
|
||||
upap_printpkt,
|
||||
NULL,
|
||||
#endif
|
||||
1,
|
||||
"PAP",
|
||||
#if 0
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
#endif
|
||||
};
|
||||
|
||||
upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Set the default login name and password for the pap sessions
|
||||
*/
|
||||
void upap_setloginpasswd(int unit, const char *luser, const char *lpassword)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
/* Save the username and password we're given */
|
||||
u->us_user = luser;
|
||||
u->us_userlen = strlen(luser);
|
||||
u->us_passwd = lpassword;
|
||||
u->us_passwdlen = strlen(lpassword);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_authwithpeer - Authenticate us with our peer (start client).
|
||||
*
|
||||
* Set new state and send authenticate's.
|
||||
*/
|
||||
void upap_authwithpeer(int unit, char *user, char *password)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n",
|
||||
unit, user, password, u->us_clientstate));
|
||||
|
||||
upap_setloginpasswd(unit, user, password);
|
||||
|
||||
u->us_transmits = 0;
|
||||
|
||||
/* Lower layer up yet? */
|
||||
if (u->us_clientstate == UPAPCS_INITIAL ||
|
||||
u->us_clientstate == UPAPCS_PENDING) {
|
||||
u->us_clientstate = UPAPCS_PENDING;
|
||||
return;
|
||||
}
|
||||
|
||||
upap_sauthreq(u); /* Start protocol */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_authpeer - Authenticate our peer (start server).
|
||||
*
|
||||
* Set new state.
|
||||
*/
|
||||
void upap_authpeer(int unit)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
/* Lower layer up yet? */
|
||||
if (u->us_serverstate == UPAPSS_INITIAL ||
|
||||
u->us_serverstate == UPAPSS_PENDING) {
|
||||
u->us_serverstate = UPAPSS_PENDING;
|
||||
return;
|
||||
}
|
||||
|
||||
u->us_serverstate = UPAPSS_LISTEN;
|
||||
if (u->us_reqtimeout > 0)
|
||||
TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************/
|
||||
/*** LOCAL FUNCTION DEFINITIONS ***/
|
||||
/**********************************/
|
||||
/*
|
||||
* upap_init - Initialize a UPAP unit.
|
||||
*/
|
||||
static void upap_init(int unit)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit));
|
||||
u->us_unit = unit;
|
||||
u->us_user = NULL;
|
||||
u->us_userlen = 0;
|
||||
u->us_passwd = NULL;
|
||||
u->us_passwdlen = 0;
|
||||
u->us_clientstate = UPAPCS_INITIAL;
|
||||
u->us_serverstate = UPAPSS_INITIAL;
|
||||
u->us_id = 0;
|
||||
u->us_timeouttime = UPAP_DEFTIMEOUT;
|
||||
u->us_maxtransmits = 10;
|
||||
u->us_reqtimeout = UPAP_DEFREQTIME;
|
||||
}
|
||||
|
||||
/*
|
||||
* upap_timeout - Retransmission timer for sending auth-reqs expired.
|
||||
*/
|
||||
static void upap_timeout(void *arg)
|
||||
{
|
||||
upap_state *u = (upap_state *) arg;
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n",
|
||||
u->us_unit, u->us_timeouttime, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate != UPAPCS_AUTHREQ)
|
||||
return;
|
||||
|
||||
if (u->us_transmits >= u->us_maxtransmits) {
|
||||
/* give up in disgust */
|
||||
UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n"));
|
||||
u->us_clientstate = UPAPCS_BADAUTH;
|
||||
auth_withpeer_fail(u->us_unit, PPP_PAP);
|
||||
return;
|
||||
}
|
||||
|
||||
upap_sauthreq(u); /* Send Authenticate-Request */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_reqtimeout - Give up waiting for the peer to send an auth-req.
|
||||
*/
|
||||
static void upap_reqtimeout(void *arg)
|
||||
{
|
||||
upap_state *u = (upap_state *) arg;
|
||||
|
||||
if (u->us_serverstate != UPAPSS_LISTEN)
|
||||
return; /* huh?? */
|
||||
|
||||
auth_peer_fail(u->us_unit, PPP_PAP);
|
||||
u->us_serverstate = UPAPSS_BADAUTH;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_lowerup - The lower layer is up.
|
||||
*
|
||||
* Start authenticating if pending.
|
||||
*/
|
||||
static void upap_lowerup(int unit)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate == UPAPCS_INITIAL)
|
||||
u->us_clientstate = UPAPCS_CLOSED;
|
||||
else if (u->us_clientstate == UPAPCS_PENDING) {
|
||||
upap_sauthreq(u); /* send an auth-request */
|
||||
}
|
||||
|
||||
if (u->us_serverstate == UPAPSS_INITIAL)
|
||||
u->us_serverstate = UPAPSS_CLOSED;
|
||||
else if (u->us_serverstate == UPAPSS_PENDING) {
|
||||
u->us_serverstate = UPAPSS_LISTEN;
|
||||
if (u->us_reqtimeout > 0)
|
||||
TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_lowerdown - The lower layer is down.
|
||||
*
|
||||
* Cancel all timeouts.
|
||||
*/
|
||||
static void upap_lowerdown(int unit)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
|
||||
UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
|
||||
if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
|
||||
UNTIMEOUT(upap_reqtimeout, u);
|
||||
|
||||
u->us_clientstate = UPAPCS_INITIAL;
|
||||
u->us_serverstate = UPAPSS_INITIAL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_protrej - Peer doesn't speak this protocol.
|
||||
*
|
||||
* This shouldn't happen. In any case, pretend lower layer went down.
|
||||
*/
|
||||
static void upap_protrej(int unit)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
|
||||
if (u->us_clientstate == UPAPCS_AUTHREQ) {
|
||||
UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n"));
|
||||
auth_withpeer_fail(unit, PPP_PAP);
|
||||
}
|
||||
if (u->us_serverstate == UPAPSS_LISTEN) {
|
||||
UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n"));
|
||||
auth_peer_fail(unit, PPP_PAP);
|
||||
}
|
||||
upap_lowerdown(unit);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_input - Input UPAP packet.
|
||||
*/
|
||||
static void upap_input(int unit, u_char *inpacket, int l)
|
||||
{
|
||||
upap_state *u = &upap[unit];
|
||||
u_char *inp;
|
||||
u_char code, id;
|
||||
int len;
|
||||
|
||||
/*
|
||||
* Parse header (code, id and length).
|
||||
* If packet too short, drop it.
|
||||
*/
|
||||
inp = inpacket;
|
||||
if (l < UPAP_HEADERLEN) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(code, inp);
|
||||
GETCHAR(id, inp);
|
||||
GETSHORT(len, inp);
|
||||
if (len < UPAP_HEADERLEN) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n"));
|
||||
return;
|
||||
}
|
||||
if (len > l) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
len -= UPAP_HEADERLEN;
|
||||
|
||||
/*
|
||||
* Action depends on code.
|
||||
*/
|
||||
switch (code) {
|
||||
case UPAP_AUTHREQ:
|
||||
upap_rauthreq(u, inp, id, len);
|
||||
break;
|
||||
|
||||
case UPAP_AUTHACK:
|
||||
upap_rauthack(u, inp, id, len);
|
||||
break;
|
||||
|
||||
case UPAP_AUTHNAK:
|
||||
upap_rauthnak(u, inp, id, len);
|
||||
break;
|
||||
|
||||
default: /* XXX Need code reject */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_rauth - Receive Authenticate.
|
||||
*/
|
||||
static void upap_rauthreq(
|
||||
upap_state *u,
|
||||
u_char *inp,
|
||||
int id,
|
||||
int len
|
||||
)
|
||||
{
|
||||
u_char ruserlen, rpasswdlen;
|
||||
char *ruser, *rpasswd;
|
||||
int retcode;
|
||||
char *msg;
|
||||
int msglen;
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id));
|
||||
|
||||
if (u->us_serverstate < UPAPSS_LISTEN)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If we receive a duplicate authenticate-request, we are
|
||||
* supposed to return the same status as for the first request.
|
||||
*/
|
||||
if (u->us_serverstate == UPAPSS_OPEN) {
|
||||
upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
|
||||
return;
|
||||
}
|
||||
if (u->us_serverstate == UPAPSS_BADAUTH) {
|
||||
upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse user/passwd.
|
||||
*/
|
||||
if (len < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(ruserlen, inp);
|
||||
len -= sizeof (u_char) + ruserlen + sizeof (u_char);
|
||||
if (len < 0) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
ruser = (char *) inp;
|
||||
INCPTR(ruserlen, inp);
|
||||
GETCHAR(rpasswdlen, inp);
|
||||
if (len < rpasswdlen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
rpasswd = (char *) inp;
|
||||
|
||||
/*
|
||||
* Check the username and password given.
|
||||
*/
|
||||
retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
|
||||
rpasswdlen, &msg, &msglen);
|
||||
BZERO(rpasswd, rpasswdlen);
|
||||
|
||||
upap_sresp(u, retcode, id, msg, msglen);
|
||||
|
||||
if (retcode == UPAP_AUTHACK) {
|
||||
u->us_serverstate = UPAPSS_OPEN;
|
||||
auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
|
||||
} else {
|
||||
u->us_serverstate = UPAPSS_BADAUTH;
|
||||
auth_peer_fail(u->us_unit, PPP_PAP);
|
||||
}
|
||||
|
||||
if (u->us_reqtimeout > 0)
|
||||
UNTIMEOUT(upap_reqtimeout, u);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_rauthack - Receive Authenticate-Ack.
|
||||
*/
|
||||
static void upap_rauthack(
|
||||
upap_state *u,
|
||||
u_char *inp,
|
||||
int id,
|
||||
int len
|
||||
)
|
||||
{
|
||||
u_char msglen;
|
||||
char *msg;
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
|
||||
return;
|
||||
|
||||
/*
|
||||
* Parse message.
|
||||
*/
|
||||
if (len < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(msglen, inp);
|
||||
len -= sizeof (u_char);
|
||||
if (len < msglen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
|
||||
u->us_clientstate = UPAPCS_OPEN;
|
||||
|
||||
auth_withpeer_success(u->us_unit, PPP_PAP);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_rauthnak - Receive Authenticate-Nakk.
|
||||
*/
|
||||
static void upap_rauthnak(
|
||||
upap_state *u,
|
||||
u_char *inp,
|
||||
int id,
|
||||
int len
|
||||
)
|
||||
{
|
||||
u_char msglen;
|
||||
char *msg;
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate));
|
||||
|
||||
if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
|
||||
return;
|
||||
|
||||
/*
|
||||
* Parse message.
|
||||
*/
|
||||
if (len < sizeof (u_char)) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
GETCHAR(msglen, inp);
|
||||
len -= sizeof (u_char);
|
||||
if (len < msglen) {
|
||||
UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n"));
|
||||
return;
|
||||
}
|
||||
msg = (char *) inp;
|
||||
PRINTMSG(msg, msglen);
|
||||
|
||||
u->us_clientstate = UPAPCS_BADAUTH;
|
||||
|
||||
UPAPDEBUG((LOG_ERR, "PAP authentication failed\n"));
|
||||
auth_withpeer_fail(u->us_unit, PPP_PAP);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_sauthreq - Send an Authenticate-Request.
|
||||
*/
|
||||
static void upap_sauthreq(upap_state *u)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen;
|
||||
|
||||
outlen = UPAP_HEADERLEN + 2 * sizeof (u_char)
|
||||
+ u->us_userlen + u->us_passwdlen;
|
||||
outp = outpacket_buf[u->us_unit];
|
||||
|
||||
MAKEHEADER(outp, PPP_PAP);
|
||||
|
||||
PUTCHAR(UPAP_AUTHREQ, outp);
|
||||
PUTCHAR(++u->us_id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
PUTCHAR(u->us_userlen, outp);
|
||||
BCOPY(u->us_user, outp, u->us_userlen);
|
||||
INCPTR(u->us_userlen, outp);
|
||||
PUTCHAR(u->us_passwdlen, outp);
|
||||
BCOPY(u->us_passwd, outp, u->us_passwdlen);
|
||||
|
||||
pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id));
|
||||
|
||||
TIMEOUT(upap_timeout, u, u->us_timeouttime);
|
||||
++u->us_transmits;
|
||||
u->us_clientstate = UPAPCS_AUTHREQ;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* upap_sresp - Send a response (ack or nak).
|
||||
*/
|
||||
static void upap_sresp(
|
||||
upap_state *u,
|
||||
u_char code,
|
||||
u_char id,
|
||||
char *msg,
|
||||
int msglen
|
||||
)
|
||||
{
|
||||
u_char *outp;
|
||||
int outlen;
|
||||
|
||||
outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
|
||||
outp = outpacket_buf[u->us_unit];
|
||||
MAKEHEADER(outp, PPP_PAP);
|
||||
|
||||
PUTCHAR(code, outp);
|
||||
PUTCHAR(id, outp);
|
||||
PUTSHORT(outlen, outp);
|
||||
PUTCHAR(msglen, outp);
|
||||
BCOPY(msg, outp, msglen);
|
||||
pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN);
|
||||
|
||||
UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n",
|
||||
code, id, u->us_clientstate));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* upap_printpkt - print the contents of a PAP packet.
|
||||
*/
|
||||
static int upap_printpkt(
|
||||
u_char *p,
|
||||
int plen,
|
||||
void (*printer) (void *, char *, ...),
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
(void)p;
|
||||
(void)plen;
|
||||
(void)printer;
|
||||
(void)arg;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PAP_SUPPORT */
|
||||
|
1631
Demo/Common/ethernet/lwIP/netif/ppp/ppp.c
Normal file
1631
Demo/Common/ethernet/lwIP/netif/ppp/ppp.c
Normal file
File diff suppressed because it is too large
Load diff
446
Demo/Common/ethernet/lwIP/netif/ppp/ppp.h
Normal file
446
Demo/Common/ethernet/lwIP/netif/ppp/ppp.h
Normal file
|
@ -0,0 +1,446 @@
|
|||
/*****************************************************************************
|
||||
* ppp.h - Network Point to Point Protocol header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1997 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 97-11-05 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Original derived from BSD codes.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PPP_H
|
||||
#define PPP_H
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "lwip/sio.h"
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
/*
|
||||
* pppd.h - PPP daemon global declarations.
|
||||
*
|
||||
* Copyright (c) 1989 Carnegie Mellon University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by Carnegie Mellon University. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* ppp_defs.h - PPP definitions.
|
||||
*
|
||||
* Copyright (c) 1994 The Australian National University.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and its
|
||||
* documentation is hereby granted, provided that the above copyright
|
||||
* notice appears in all copies. This software is provided without any
|
||||
* warranty, express or implied. The Australian National University
|
||||
* makes no representations about the suitability of this software for
|
||||
* any purpose.
|
||||
*
|
||||
* IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
|
||||
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
|
||||
* THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
|
||||
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
||||
* OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#define TIMEOUT(f, a, t) sys_untimeout((f), (a)), sys_timeout((t)*1000, (f), (a))
|
||||
#define UNTIMEOUT(f, a) sys_untimeout((f), (a))
|
||||
|
||||
|
||||
# ifndef __u_char_defined
|
||||
|
||||
/* Type definitions for BSD code. */
|
||||
typedef unsigned long u_long;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned char u_char;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constants and structures defined by the internet system,
|
||||
* Per RFC 790, September 1981, and numerous additions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The basic PPP frame.
|
||||
*/
|
||||
#define PPP_HDRLEN 4 /* octets for standard ppp header */
|
||||
#define PPP_FCSLEN 2 /* octets for FCS */
|
||||
|
||||
|
||||
/*
|
||||
* Significant octet values.
|
||||
*/
|
||||
#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
|
||||
#define PPP_UI 0x03 /* Unnumbered Information */
|
||||
#define PPP_FLAG 0x7e /* Flag Sequence */
|
||||
#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
|
||||
#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
|
||||
|
||||
/*
|
||||
* Protocol field values.
|
||||
*/
|
||||
#define PPP_IP 0x21 /* Internet Protocol */
|
||||
#define PPP_AT 0x29 /* AppleTalk Protocol */
|
||||
#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
|
||||
#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
|
||||
#define PPP_COMP 0xfd /* compressed packet */
|
||||
#define PPP_IPCP 0x8021 /* IP Control Protocol */
|
||||
#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
|
||||
#define PPP_CCP 0x80fd /* Compression Control Protocol */
|
||||
#define PPP_LCP 0xc021 /* Link Control Protocol */
|
||||
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
|
||||
#define PPP_LQR 0xc025 /* Link Quality Report protocol */
|
||||
#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
|
||||
#define PPP_CBCP 0xc029 /* Callback Control Protocol */
|
||||
|
||||
/*
|
||||
* Values for FCS calculations.
|
||||
*/
|
||||
#define PPP_INITFCS 0xffff /* Initial FCS value */
|
||||
#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
|
||||
#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
|
||||
|
||||
/*
|
||||
* Extended asyncmap - allows any character to be escaped.
|
||||
*/
|
||||
typedef u_char ext_accm[32];
|
||||
|
||||
/*
|
||||
* What to do with network protocol (NP) packets.
|
||||
*/
|
||||
enum NPmode {
|
||||
NPMODE_PASS, /* pass the packet through */
|
||||
NPMODE_DROP, /* silently drop the packet */
|
||||
NPMODE_ERROR, /* return an error */
|
||||
NPMODE_QUEUE /* save it up for later. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Inline versions of get/put char/short/long.
|
||||
* Pointer is advanced; we assume that both arguments
|
||||
* are lvalues and will already be in registers.
|
||||
* cp MUST be u_char *.
|
||||
*/
|
||||
#define GETCHAR(c, cp) { \
|
||||
(c) = *(cp)++; \
|
||||
}
|
||||
#define PUTCHAR(c, cp) { \
|
||||
*(cp)++ = (u_char) (c); \
|
||||
}
|
||||
|
||||
|
||||
#define GETSHORT(s, cp) { \
|
||||
(s) = *(cp); (cp)++; (s) << 8; \
|
||||
(s) |= *(cp); (cp)++; \
|
||||
}
|
||||
#define PUTSHORT(s, cp) { \
|
||||
*(cp)++ = (u_char) ((s) >> 8); \
|
||||
*(cp)++ = (u_char) (s); \
|
||||
}
|
||||
|
||||
#define GETLONG(l, cp) { \
|
||||
(l) = *(cp); (cp)++; (l) << 8; \
|
||||
(l) |= *(cp); (cp)++; (l) <<= 8; \
|
||||
(l) |= *(cp); (cp)++; (l) <<= 8; \
|
||||
(l) |= *(cp); (cp)++; \
|
||||
}
|
||||
#define PUTLONG(l, cp) { \
|
||||
*(cp)++ = (u_char) ((l) >> 24); \
|
||||
*(cp)++ = (u_char) ((l) >> 16); \
|
||||
*(cp)++ = (u_char) ((l) >> 8); \
|
||||
*(cp)++ = (u_char) (l); \
|
||||
}
|
||||
|
||||
|
||||
#define INCPTR(n, cp) ((cp) += (n))
|
||||
#define DECPTR(n, cp) ((cp) -= (n))
|
||||
|
||||
#define BCMP(s0, s1, l) memcmp((u_char *)(s0), (u_char *)(s1), (l))
|
||||
#define BCOPY(s, d, l) memcpy((d), (s), (l))
|
||||
#define BZERO(s, n) memset(s, 0, n)
|
||||
#if PPP_DEBUG
|
||||
#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); }
|
||||
#else
|
||||
#define PRINTMSG(m, l)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MAKEHEADER - Add PPP Header fields to a packet.
|
||||
*/
|
||||
#define MAKEHEADER(p, t) { \
|
||||
PUTCHAR(PPP_ALLSTATIONS, p); \
|
||||
PUTCHAR(PPP_UI, p); \
|
||||
PUTSHORT(t, p); }
|
||||
|
||||
/*************************
|
||||
*** PUBLIC DEFINITIONS ***
|
||||
*************************/
|
||||
|
||||
/* Error codes. */
|
||||
#define PPPERR_NONE 0 /* No error. */
|
||||
#define PPPERR_PARAM -1 /* Invalid parameter. */
|
||||
#define PPPERR_OPEN -2 /* Unable to open PPP session. */
|
||||
#define PPPERR_DEVICE -3 /* Invalid I/O device for PPP. */
|
||||
#define PPPERR_ALLOC -4 /* Unable to allocate resources. */
|
||||
#define PPPERR_USER -5 /* User interrupt. */
|
||||
#define PPPERR_CONNECT -6 /* Connection lost. */
|
||||
#define PPPERR_AUTHFAIL -7 /* Failed authentication challenge. */
|
||||
#define PPPERR_PROTOCOL -8 /* Failed to meet protocol. */
|
||||
|
||||
/*
|
||||
* PPP IOCTL commands.
|
||||
*/
|
||||
/*
|
||||
* Get the up status - 0 for down, non-zero for up. The argument must
|
||||
* point to an int.
|
||||
*/
|
||||
#define PPPCTLG_UPSTATUS 100 /* Get the up status - 0 down else up */
|
||||
#define PPPCTLS_ERRCODE 101 /* Set the error code */
|
||||
#define PPPCTLG_ERRCODE 102 /* Get the error code */
|
||||
#define PPPCTLG_FD 103 /* Get the fd associated with the ppp */
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
|
||||
/*
|
||||
* The following struct gives the addresses of procedures to call
|
||||
* for a particular protocol.
|
||||
*/
|
||||
struct protent {
|
||||
u_short protocol; /* PPP protocol number */
|
||||
/* Initialization procedure */
|
||||
void (*init) (int unit);
|
||||
/* Process a received packet */
|
||||
void (*input) (int unit, u_char *pkt, int len);
|
||||
/* Process a received protocol-reject */
|
||||
void (*protrej) (int unit);
|
||||
/* Lower layer has come up */
|
||||
void (*lowerup) (int unit);
|
||||
/* Lower layer has gone down */
|
||||
void (*lowerdown) (int unit);
|
||||
/* Open the protocol */
|
||||
void (*open) (int unit);
|
||||
/* Close the protocol */
|
||||
void (*close) (int unit, char *reason);
|
||||
#if 0
|
||||
/* Print a packet in readable form */
|
||||
int (*printpkt) (u_char *pkt, int len,
|
||||
void (*printer) (void *, char *, ...),
|
||||
void *arg);
|
||||
/* Process a received data packet */
|
||||
void (*datainput) (int unit, u_char *pkt, int len);
|
||||
#endif
|
||||
int enabled_flag; /* 0 iff protocol is disabled */
|
||||
char *name; /* Text name of protocol */
|
||||
#if 0
|
||||
/* Check requested options, assign defaults */
|
||||
void (*check_options) (u_long);
|
||||
/* Configure interface for demand-dial */
|
||||
int (*demand_conf) (int unit);
|
||||
/* Say whether to bring up link for this pkt */
|
||||
int (*active_pkt) (u_char *pkt, int len);
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure records the time in seconds since
|
||||
* the last NP packet was sent or received.
|
||||
*/
|
||||
struct ppp_idle {
|
||||
u_short xmit_idle; /* seconds since last NP packet sent */
|
||||
u_short recv_idle; /* seconds since last NP packet received */
|
||||
};
|
||||
|
||||
struct ppp_settings {
|
||||
|
||||
u_int disable_defaultip : 1; /* Don't use hostname for default IP addrs */
|
||||
u_int auth_required : 1; /* Peer is required to authenticate */
|
||||
u_int explicit_remote : 1; /* remote_name specified with remotename opt */
|
||||
u_int refuse_pap : 1; /* Don't wanna auth. ourselves with PAP */
|
||||
u_int refuse_chap : 1; /* Don't wanna auth. ourselves with CHAP */
|
||||
u_int usehostname : 1; /* Use hostname for our_name */
|
||||
u_int usepeerdns : 1; /* Ask peer for DNS adds */
|
||||
|
||||
u_short idle_time_limit; /* Shut down link if idle for this long */
|
||||
int maxconnect; /* Maximum connect time (seconds) */
|
||||
|
||||
char user[MAXNAMELEN + 1];/* Username for PAP */
|
||||
char passwd[MAXSECRETLEN + 1]; /* Password for PAP, secret for CHAP */
|
||||
char our_name[MAXNAMELEN + 1]; /* Our name for authentication purposes */
|
||||
char remote_name[MAXNAMELEN + 1]; /* Peer's name for authentication */
|
||||
};
|
||||
|
||||
struct ppp_addrs {
|
||||
struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2;
|
||||
};
|
||||
|
||||
/*****************************
|
||||
*** PUBLIC DATA STRUCTURES ***
|
||||
*****************************/
|
||||
/* Buffers for outgoing packets. */
|
||||
extern u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
|
||||
|
||||
extern struct ppp_settings ppp_settings;
|
||||
|
||||
extern struct protent *ppp_protocols[];/* Table of pointers to supported protocols */
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
|
||||
/* Initialize the PPP subsystem. */
|
||||
void pppInit(void);
|
||||
|
||||
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
|
||||
* RFC 1994 says:
|
||||
*
|
||||
* In practice, within or associated with each PPP server, there is a
|
||||
* database which associates "user" names with authentication
|
||||
* information ("secrets"). It is not anticipated that a particular
|
||||
* named user would be authenticated by multiple methods. This would
|
||||
* make the user vulnerable to attacks which negotiate the least secure
|
||||
* method from among a set (such as PAP rather than CHAP). If the same
|
||||
* secret was used, PAP would reveal the secret to be used later with
|
||||
* CHAP.
|
||||
*
|
||||
* Instead, for each user name there should be an indication of exactly
|
||||
* one method used to authenticate that user name. If a user needs to
|
||||
* make use of different authentication methods under different
|
||||
* circumstances, then distinct user names SHOULD be employed, each of
|
||||
* which identifies exactly one authentication method.
|
||||
*
|
||||
*/
|
||||
enum pppAuthType {
|
||||
PPPAUTHTYPE_NONE,
|
||||
PPPAUTHTYPE_ANY,
|
||||
PPPAUTHTYPE_PAP,
|
||||
PPPAUTHTYPE_CHAP
|
||||
};
|
||||
|
||||
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd);
|
||||
|
||||
/*
|
||||
* Open a new PPP connection using the given I/O device.
|
||||
* This initializes the PPP control block but does not
|
||||
* attempt to negotiate the LCP session.
|
||||
* Return a new PPP connection descriptor on success or
|
||||
* an error code (negative) on failure.
|
||||
*/
|
||||
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx);
|
||||
|
||||
/*
|
||||
* Close a PPP connection and release the descriptor.
|
||||
* Any outstanding packets in the queues are dropped.
|
||||
* Return 0 on success, an error code on failure.
|
||||
*/
|
||||
int pppClose(int pd);
|
||||
|
||||
/*
|
||||
* Indicate to the PPP process that the line has disconnected.
|
||||
*/
|
||||
void pppSigHUP(int pd);
|
||||
|
||||
/*
|
||||
* Get and set parameters for the given connection.
|
||||
* Return 0 on success, an error code on failure.
|
||||
*/
|
||||
int pppIOCtl(int pd, int cmd, void *arg);
|
||||
|
||||
/*
|
||||
* Return the Maximum Transmission Unit for the given PPP connection.
|
||||
*/
|
||||
u_int pppMTU(int pd);
|
||||
|
||||
/*
|
||||
* Write n characters to a ppp link.
|
||||
* RETURN: >= 0 Number of characters written
|
||||
* -1 Failed to write to device
|
||||
*/
|
||||
int pppWrite(int pd, const u_char *s, int n);
|
||||
|
||||
void pppMainWakeup(int pd);
|
||||
|
||||
/* Configure i/f transmit parameters */
|
||||
void ppp_send_config (int, int, u32_t, int, int);
|
||||
/* Set extended transmit ACCM */
|
||||
void ppp_set_xaccm (int, ext_accm *);
|
||||
/* Configure i/f receive parameters */
|
||||
void ppp_recv_config (int, int, u32_t, int, int);
|
||||
/* Find out how long link has been idle */
|
||||
int get_idle_time (int, struct ppp_idle *);
|
||||
|
||||
/* Configure VJ TCP header compression */
|
||||
int sifvjcomp (int, int, int, int);
|
||||
/* Configure i/f down (for IP) */
|
||||
int sifup (int);
|
||||
/* Set mode for handling packets for proto */
|
||||
int sifnpmode (int u, int proto, enum NPmode mode);
|
||||
/* Configure i/f down (for IP) */
|
||||
int sifdown (int);
|
||||
/* Configure IP addresses for i/f */
|
||||
int sifaddr (int, u32_t, u32_t, u32_t, u32_t, u32_t);
|
||||
/* Reset i/f IP addresses */
|
||||
int cifaddr (int, u32_t, u32_t);
|
||||
/* Create default route through i/f */
|
||||
int sifdefaultroute (int, u32_t, u32_t);
|
||||
/* Delete default route through i/f */
|
||||
int cifdefaultroute (int, u32_t, u32_t);
|
||||
|
||||
/* Get appropriate netmask for address */
|
||||
u32_t GetMask (u32_t);
|
||||
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
||||
#endif /* PPP_H */
|
89
Demo/Common/ethernet/lwIP/netif/ppp/pppdebug.h
Normal file
89
Demo/Common/ethernet/lwIP/netif/ppp/pppdebug.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*****************************************************************************
|
||||
* pppdebug.h - System debugging utilities.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* portions Copyright (c) 1998 Global Election Systems Inc.
|
||||
* portions Copyright (c) 2001 by Cognizant Pty Ltd.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY (please don't use tabs!)
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-07-29 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Original.
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#ifndef PPPDEBUG_H
|
||||
#define PPPDEBUG_H
|
||||
|
||||
/************************
|
||||
*** PUBLIC DATA TYPES ***
|
||||
************************/
|
||||
/* Trace levels. */
|
||||
typedef enum {
|
||||
LOG_CRITICAL = 0,
|
||||
LOG_ERR = 1,
|
||||
LOG_NOTICE = 2,
|
||||
LOG_WARNING = 3,
|
||||
LOG_INFO = 5,
|
||||
LOG_DETAIL = 6,
|
||||
LOG_DEBUG = 7
|
||||
} LogCodes;
|
||||
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
/*
|
||||
* ppp_trace - a form of printf to send tracing information to stderr
|
||||
*/
|
||||
void ppp_trace(int level, const char *format,...);
|
||||
|
||||
#if PPP_DEBUG > 0
|
||||
|
||||
#define AUTHDEBUG(a) ppp_trace a
|
||||
#define IPCPDEBUG(a) ppp_trace a
|
||||
#define UPAPDEBUG(a) ppp_trace a
|
||||
#define LCPDEBUG(a) ppp_trace a
|
||||
#define FSMDEBUG(a) ppp_trace a
|
||||
#define CHAPDEBUG(a) ppp_trace a
|
||||
#define PPPDEBUG(a) ppp_trace a
|
||||
|
||||
#define TRACELCP 1
|
||||
|
||||
#else
|
||||
|
||||
#define AUTHDEBUG(a)
|
||||
#define IPCPDEBUG(a)
|
||||
#define UPAPDEBUG(a)
|
||||
#define LCPDEBUG(a)
|
||||
#define FSMDEBUG(a)
|
||||
#define CHAPDEBUG(a)
|
||||
|
||||
#define PPPDEBUG(a)
|
||||
|
||||
#define TRACELCP 0
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PPPDEBUG_H */
|
242
Demo/Common/ethernet/lwIP/netif/ppp/randm.c
Normal file
242
Demo/Common/ethernet/lwIP/netif/ppp/randm.c
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*****************************************************************************
|
||||
* randm.c - Random number generator program file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1998 by Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-06-03 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
|
||||
* Extracted from avos.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ppp.h"
|
||||
#if PPP_SUPPORT > 0
|
||||
#include "md5.h"
|
||||
#include "randm.h"
|
||||
|
||||
#include "pppdebug.h"
|
||||
|
||||
|
||||
#if MD5_SUPPORT>0 /* this module depends on MD5 */
|
||||
#define RANDPOOLSZ 16 /* Bytes stored in the pool of randomness. */
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
static char randPool[RANDPOOLSZ]; /* Pool of randomness. */
|
||||
static long randCount = 0; /* Pseudo-random incrementer */
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Initialize the random number generator.
|
||||
*
|
||||
* Since this is to be called on power up, we don't have much
|
||||
* system randomess to work with. Here all we use is the
|
||||
* real-time clock. We'll accumulate more randomness as soon
|
||||
* as things start happening.
|
||||
*/
|
||||
void avRandomInit()
|
||||
{
|
||||
avChurnRand(NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Churn the randomness pool on a random event. Call this early and often
|
||||
* on random and semi-random system events to build randomness in time for
|
||||
* usage. For randomly timed events, pass a null pointer and a zero length
|
||||
* and this will use the system timer and other sources to add randomness.
|
||||
* If new random data is available, pass a pointer to that and it will be
|
||||
* included.
|
||||
*
|
||||
* Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
|
||||
*/
|
||||
void avChurnRand(char *randData, u32_t randLen)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
|
||||
/* ppp_trace(LOG_INFO, "churnRand: %u@%P\n", randLen, randData); */
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
|
||||
if (randData)
|
||||
MD5Update(&md5, (u_char *)randData, randLen);
|
||||
else {
|
||||
struct {
|
||||
/* INCLUDE fields for any system sources of randomness */
|
||||
char foobar;
|
||||
} sysData;
|
||||
|
||||
/* Load sysData fields here. */
|
||||
;
|
||||
MD5Update(&md5, (u_char *)&sysData, sizeof(sysData));
|
||||
}
|
||||
MD5Final((u_char *)randPool, &md5);
|
||||
/* ppp_trace(LOG_INFO, "churnRand: -> 0\n"); */
|
||||
}
|
||||
|
||||
/*
|
||||
* Use the random pool to generate random data. This degrades to pseudo
|
||||
* random when used faster than randomness is supplied using churnRand().
|
||||
* Note: It's important that there be sufficient randomness in randPool
|
||||
* before this is called for otherwise the range of the result may be
|
||||
* narrow enough to make a search feasible.
|
||||
*
|
||||
* Ref: Applied Cryptography 2nd Ed. by Bruce Schneier p. 427
|
||||
*
|
||||
* XXX Why does he not just call churnRand() for each block? Probably
|
||||
* so that you don't ever publish the seed which could possibly help
|
||||
* predict future values.
|
||||
* XXX Why don't we preserve md5 between blocks and just update it with
|
||||
* randCount each time? Probably there is a weakness but I wish that
|
||||
* it was documented.
|
||||
*/
|
||||
void avGenRand(char *buf, u32_t bufLen)
|
||||
{
|
||||
MD5_CTX md5;
|
||||
u_char tmp[16];
|
||||
u32_t n;
|
||||
|
||||
while (bufLen > 0) {
|
||||
n = LWIP_MIN(bufLen, RANDPOOLSZ);
|
||||
MD5Init(&md5);
|
||||
MD5Update(&md5, (u_char *)randPool, sizeof(randPool));
|
||||
MD5Update(&md5, (u_char *)&randCount, sizeof(randCount));
|
||||
MD5Final(tmp, &md5);
|
||||
randCount++;
|
||||
memcpy(buf, tmp, n);
|
||||
buf += n;
|
||||
bufLen -= n;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a new random number.
|
||||
*/
|
||||
u32_t avRandom()
|
||||
{
|
||||
u32_t newRand;
|
||||
|
||||
avGenRand((char *)&newRand, sizeof(newRand));
|
||||
|
||||
return newRand;
|
||||
}
|
||||
|
||||
#else /* MD5_SUPPORT */
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*** LOCAL DATA STRUCTURES ***/
|
||||
/*****************************/
|
||||
static int avRandomized = 0; /* Set when truely randomized. */
|
||||
static u32_t avRandomSeed = 0; /* Seed used for random number generation. */
|
||||
|
||||
|
||||
/***********************************/
|
||||
/*** PUBLIC FUNCTION DEFINITIONS ***/
|
||||
/***********************************/
|
||||
/*
|
||||
* Initialize the random number generator.
|
||||
*
|
||||
* Here we attempt to compute a random number seed but even if
|
||||
* it isn't random, we'll randomize it later.
|
||||
*
|
||||
* The current method uses the fields from the real time clock,
|
||||
* the idle process counter, the millisecond counter, and the
|
||||
* hardware timer tick counter. When this is invoked
|
||||
* in startup(), then the idle counter and timer values may
|
||||
* repeat after each boot and the real time clock may not be
|
||||
* operational. Thus we call it again on the first random
|
||||
* event.
|
||||
*/
|
||||
void avRandomInit()
|
||||
{
|
||||
#if 0
|
||||
/* Get a pointer into the last 4 bytes of clockBuf. */
|
||||
u32_t *lptr1 = (u32_t *)((char *)&clockBuf[3]);
|
||||
|
||||
/*
|
||||
* Initialize our seed using the real-time clock, the idle
|
||||
* counter, the millisecond timer, and the hardware timer
|
||||
* tick counter. The real-time clock and the hardware
|
||||
* tick counter are the best sources of randomness but
|
||||
* since the tick counter is only 16 bit (and truncated
|
||||
* at that), the idle counter and millisecond timer
|
||||
* (which may be small values) are added to help
|
||||
* randomize the lower 16 bits of the seed.
|
||||
*/
|
||||
readClk();
|
||||
avRandomSeed += *(u32_t *)clockBuf + *lptr1 + OSIdleCtr
|
||||
+ ppp_mtime() + ((u32_t)TM1 << 16) + TM1;
|
||||
#else
|
||||
avRandomSeed += sys_jiffies(); /* XXX */
|
||||
#endif
|
||||
|
||||
/* Initialize the Borland random number generator. */
|
||||
srand((unsigned)avRandomSeed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Randomize our random seed value. Here we use the fact that
|
||||
* this function is called at *truely random* times by the polling
|
||||
* and network functions. Here we only get 16 bits of new random
|
||||
* value but we use the previous value to randomize the other 16
|
||||
* bits.
|
||||
*/
|
||||
void avRandomize(void)
|
||||
{
|
||||
static u32_t last_jiffies;
|
||||
|
||||
if (!avRandomized) {
|
||||
avRandomized = !0;
|
||||
avRandomInit();
|
||||
/* The initialization function also updates the seed. */
|
||||
} else {
|
||||
/* avRandomSeed += (avRandomSeed << 16) + TM1; */
|
||||
avRandomSeed += (sys_jiffies() - last_jiffies); /* XXX */
|
||||
}
|
||||
last_jiffies = sys_jiffies();
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a new random number.
|
||||
* Here we use the Borland rand() function to supply a pseudo random
|
||||
* number which we make truely random by combining it with our own
|
||||
* seed which is randomized by truely random events.
|
||||
* Thus the numbers will be truely random unless there have been no
|
||||
* operator or network events in which case it will be pseudo random
|
||||
* seeded by the real time clock.
|
||||
*/
|
||||
u32_t avRandom()
|
||||
{
|
||||
return ((((u32_t)rand() << 16) + rand()) + avRandomSeed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* MD5_SUPPORT */
|
||||
#endif /* PPP_SUPPORT */
|
||||
|
81
Demo/Common/ethernet/lwIP/netif/ppp/randm.h
Normal file
81
Demo/Common/ethernet/lwIP/netif/ppp/randm.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*****************************************************************************
|
||||
* randm.h - Random number generator header file.
|
||||
*
|
||||
* Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
|
||||
* Copyright (c) 1998 Global Election Systems Inc.
|
||||
*
|
||||
* The authors hereby grant permission to use, copy, modify, distribute,
|
||||
* and license this software and its documentation for any purpose, provided
|
||||
* that existing copyright notices are retained in all copies and that this
|
||||
* notice and the following disclaimer are included verbatim in any
|
||||
* distributions. No written agreement, license, or royalty fee is required
|
||||
* for any of the authorized uses.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
******************************************************************************
|
||||
* REVISION HISTORY
|
||||
*
|
||||
* 03-01-01 Marc Boucher <marc@mbsi.ca>
|
||||
* Ported to lwIP.
|
||||
* 98-05-29 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
|
||||
* Extracted from avos.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef RANDM_H
|
||||
#define RANDM_H
|
||||
|
||||
/***********************
|
||||
*** PUBLIC FUNCTIONS ***
|
||||
***********************/
|
||||
/*
|
||||
* Initialize the random number generator.
|
||||
*/
|
||||
void avRandomInit(void);
|
||||
|
||||
/*
|
||||
* Churn the randomness pool on a random event. Call this early and often
|
||||
* on random and semi-random system events to build randomness in time for
|
||||
* usage. For randomly timed events, pass a null pointer and a zero length
|
||||
* and this will use the system timer and other sources to add randomness.
|
||||
* If new random data is available, pass a pointer to that and it will be
|
||||
* included.
|
||||
*/
|
||||
void avChurnRand(char *randData, u32_t randLen);
|
||||
|
||||
/*
|
||||
* Randomize our random seed value. To be called for truely random events
|
||||
* such as user operations and network traffic.
|
||||
*/
|
||||
#if MD5_SUPPORT
|
||||
#define avRandomize() avChurnRand(NULL, 0)
|
||||
#else
|
||||
void avRandomize(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use the random pool to generate random data. This degrades to pseudo
|
||||
* random when used faster than randomness is supplied using churnRand().
|
||||
* Thus it's important to make sure that the results of this are not
|
||||
* published directly because one could predict the next result to at
|
||||
* least some degree. Also, it's important to get a good seed before
|
||||
* the first use.
|
||||
*/
|
||||
void avGenRand(char *buf, u32_t bufLen);
|
||||
|
||||
/*
|
||||
* Return a new random number.
|
||||
*/
|
||||
u32_t avRandom(void);
|
||||
|
||||
|
||||
#endif /* RANDM_H */
|
633
Demo/Common/ethernet/lwIP/netif/ppp/vj.c
Normal file
633
Demo/Common/ethernet/lwIP/netif/ppp/vj.c
Normal file
|
@ -0,0 +1,633 @@
|
|||
/*
|
||||
* Routines to compress and uncompess tcp packets (for transmission
|
||||
* over low speed serial lines.
|
||||
*
|
||||
* Copyright (c) 1989 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
|
||||
* - Initial distribution.
|
||||
*
|
||||
* Modified June 1993 by Paul Mackerras, paulus@cs.anu.edu.au,
|
||||
* so that the entire packet being decompressed doesn't have
|
||||
* to be in contiguous memory (just the compressed header).
|
||||
*
|
||||
* Modified March 1998 by Guy Lancaster, glanca@gesn.com,
|
||||
* for a 16 bit processor.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ppp.h"
|
||||
#include "vj.h"
|
||||
#include "pppdebug.h"
|
||||
|
||||
#if VJ_SUPPORT > 0
|
||||
|
||||
#if LINK_STATS
|
||||
#define INCR(counter) ++comp->stats.counter
|
||||
#else
|
||||
#define INCR(counter)
|
||||
#endif
|
||||
|
||||
#if defined(NO_CHAR_BITFIELDS)
|
||||
#define getip_hl(base) ((base).ip_hl_v&0xf)
|
||||
#define getth_off(base) (((base).th_x2_off&0xf0)>>4)
|
||||
#else
|
||||
#define getip_hl(base) ((base).ip_hl)
|
||||
#define getth_off(base) ((base).th_off)
|
||||
#endif
|
||||
|
||||
void vj_compress_init(struct vjcompress *comp)
|
||||
{
|
||||
register u_int i;
|
||||
register struct cstate *tstate = comp->tstate;
|
||||
|
||||
#if MAX_SLOTS == 0
|
||||
memset((char *)comp, 0, sizeof(*comp));
|
||||
#endif
|
||||
comp->maxSlotIndex = MAX_SLOTS - 1;
|
||||
comp->compressSlot = 0; /* Disable slot ID compression by default. */
|
||||
for (i = MAX_SLOTS - 1; i > 0; --i) {
|
||||
tstate[i].cs_id = i;
|
||||
tstate[i].cs_next = &tstate[i - 1];
|
||||
}
|
||||
tstate[0].cs_next = &tstate[MAX_SLOTS - 1];
|
||||
tstate[0].cs_id = 0;
|
||||
comp->last_cs = &tstate[0];
|
||||
comp->last_recv = 255;
|
||||
comp->last_xmit = 255;
|
||||
comp->flags = VJF_TOSS;
|
||||
}
|
||||
|
||||
|
||||
/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
|
||||
* checks for zero (since zero has to be encoded in the long, 3 byte
|
||||
* form).
|
||||
*/
|
||||
#define ENCODE(n) { \
|
||||
if ((u_short)(n) >= 256) { \
|
||||
*cp++ = 0; \
|
||||
cp[1] = (n); \
|
||||
cp[0] = (n) >> 8; \
|
||||
cp += 2; \
|
||||
} else { \
|
||||
*cp++ = (n); \
|
||||
} \
|
||||
}
|
||||
#define ENCODEZ(n) { \
|
||||
if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
|
||||
*cp++ = 0; \
|
||||
cp[1] = (n); \
|
||||
cp[0] = (n) >> 8; \
|
||||
cp += 2; \
|
||||
} else { \
|
||||
*cp++ = (n); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODEL(f) { \
|
||||
if (*cp == 0) {\
|
||||
u32_t tmp = ntohl(f) + ((cp[1] << 8) | cp[2]); \
|
||||
(f) = htonl(tmp); \
|
||||
cp += 3; \
|
||||
} else { \
|
||||
u32_t tmp = ntohl(f) + (u32_t)*cp++; \
|
||||
(f) = htonl(tmp); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODES(f) { \
|
||||
if (*cp == 0) {\
|
||||
u_short tmp = ntohs(f) + (((u_short)cp[1] << 8) | cp[2]); \
|
||||
(f) = htons(tmp); \
|
||||
cp += 3; \
|
||||
} else { \
|
||||
u_short tmp = ntohs(f) + (u_short)*cp++; \
|
||||
(f) = htons(tmp); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DECODEU(f) { \
|
||||
if (*cp == 0) {\
|
||||
(f) = htons(((u_short)cp[1] << 8) | cp[2]); \
|
||||
cp += 3; \
|
||||
} else { \
|
||||
(f) = htons((u_short)*cp++); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* vj_compress_tcp - Attempt to do Van Jacobsen header compression on a
|
||||
* packet. This assumes that nb and comp are not null and that the first
|
||||
* buffer of the chain contains a valid IP header.
|
||||
* Return the VJ type code indicating whether or not the packet was
|
||||
* compressed.
|
||||
*/
|
||||
u_int vj_compress_tcp(
|
||||
struct vjcompress *comp,
|
||||
struct pbuf *pb
|
||||
)
|
||||
{
|
||||
register struct ip *ip = (struct ip *)pb->payload;
|
||||
register struct cstate *cs = comp->last_cs->cs_next;
|
||||
register u_short hlen = getip_hl(*ip);
|
||||
register struct tcphdr *oth;
|
||||
register struct tcphdr *th;
|
||||
register u_short deltaS, deltaA;
|
||||
register u_long deltaL;
|
||||
register u_int changes = 0;
|
||||
u_char new_seq[16];
|
||||
register u_char *cp = new_seq;
|
||||
|
||||
/*
|
||||
* Check that the packet is IP proto TCP.
|
||||
*/
|
||||
if (ip->ip_p != IPPROTO_TCP)
|
||||
return (TYPE_IP);
|
||||
|
||||
/*
|
||||
* Bail if this is an IP fragment or if the TCP packet isn't
|
||||
* `compressible' (i.e., ACK isn't set or some other control bit is
|
||||
* set).
|
||||
*/
|
||||
if ((ip->ip_off & htons(0x3fff)) || pb->tot_len < 40)
|
||||
return (TYPE_IP);
|
||||
th = (struct tcphdr *)&((long *)ip)[hlen];
|
||||
if ((th->th_flags & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK)
|
||||
return (TYPE_IP);
|
||||
|
||||
/*
|
||||
* Packet is compressible -- we're going to send either a
|
||||
* COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
|
||||
* to locate (or create) the connection state. Special case the
|
||||
* most recently used connection since it's most likely to be used
|
||||
* again & we don't have to do any reordering if it's used.
|
||||
*/
|
||||
INCR(vjs_packets);
|
||||
if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr
|
||||
|| ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr
|
||||
|| *(long *)th != ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) {
|
||||
/*
|
||||
* Wasn't the first -- search for it.
|
||||
*
|
||||
* States are kept in a circularly linked list with
|
||||
* last_cs pointing to the end of the list. The
|
||||
* list is kept in lru order by moving a state to the
|
||||
* head of the list whenever it is referenced. Since
|
||||
* the list is short and, empirically, the connection
|
||||
* we want is almost always near the front, we locate
|
||||
* states via linear search. If we don't find a state
|
||||
* for the datagram, the oldest state is (re-)used.
|
||||
*/
|
||||
register struct cstate *lcs;
|
||||
register struct cstate *lastcs = comp->last_cs;
|
||||
|
||||
do {
|
||||
lcs = cs; cs = cs->cs_next;
|
||||
INCR(vjs_searches);
|
||||
if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
|
||||
&& ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
|
||||
&& *(long *)th == ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)])
|
||||
goto found;
|
||||
} while (cs != lastcs);
|
||||
|
||||
/*
|
||||
* Didn't find it -- re-use oldest cstate. Send an
|
||||
* uncompressed packet that tells the other side what
|
||||
* connection number we're using for this conversation.
|
||||
* Note that since the state list is circular, the oldest
|
||||
* state points to the newest and we only need to set
|
||||
* last_cs to update the lru linkage.
|
||||
*/
|
||||
INCR(vjs_misses);
|
||||
comp->last_cs = lcs;
|
||||
hlen += getth_off(*th);
|
||||
hlen <<= 2;
|
||||
/* Check that the IP/TCP headers are contained in the first buffer. */
|
||||
if (hlen > pb->len)
|
||||
return (TYPE_IP);
|
||||
goto uncompressed;
|
||||
|
||||
found:
|
||||
/*
|
||||
* Found it -- move to the front on the connection list.
|
||||
*/
|
||||
if (cs == lastcs)
|
||||
comp->last_cs = lcs;
|
||||
else {
|
||||
lcs->cs_next = cs->cs_next;
|
||||
cs->cs_next = lastcs->cs_next;
|
||||
lastcs->cs_next = cs;
|
||||
}
|
||||
}
|
||||
|
||||
oth = (struct tcphdr *)&((long *)&cs->cs_ip)[hlen];
|
||||
deltaS = hlen;
|
||||
hlen += getth_off(*th);
|
||||
hlen <<= 2;
|
||||
/* Check that the IP/TCP headers are contained in the first buffer. */
|
||||
if (hlen > pb->len) {
|
||||
PPPDEBUG((LOG_INFO, "vj_compress_tcp: header len %d spans buffers\n",
|
||||
hlen));
|
||||
return (TYPE_IP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that only what we expect to change changed. The first
|
||||
* line of the `if' checks the IP protocol version, header length &
|
||||
* type of service. The 2nd line checks the "Don't fragment" bit.
|
||||
* The 3rd line checks the time-to-live and protocol (the protocol
|
||||
* check is unnecessary but costless). The 4th line checks the TCP
|
||||
* header length. The 5th line checks IP options, if any. The 6th
|
||||
* line checks TCP options, if any. If any of these things are
|
||||
* different between the previous & current datagram, we send the
|
||||
* current datagram `uncompressed'.
|
||||
*/
|
||||
if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0]
|
||||
|| ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3]
|
||||
|| ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4]
|
||||
|| getth_off(*th) != getth_off(*oth)
|
||||
|| (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2))
|
||||
|| (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2)))
|
||||
goto uncompressed;
|
||||
|
||||
/*
|
||||
* Figure out which of the changing fields changed. The
|
||||
* receiver expects changes in the order: urgent, window,
|
||||
* ack, seq (the order minimizes the number of temporaries
|
||||
* needed in this section of code).
|
||||
*/
|
||||
if (th->th_flags & TCP_URG) {
|
||||
deltaS = ntohs(th->th_urp);
|
||||
ENCODEZ(deltaS);
|
||||
changes |= NEW_U;
|
||||
} else if (th->th_urp != oth->th_urp)
|
||||
/* argh! URG not set but urp changed -- a sensible
|
||||
* implementation should never do this but RFC793
|
||||
* doesn't prohibit the change so we have to deal
|
||||
* with it. */
|
||||
goto uncompressed;
|
||||
|
||||
if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) != 0) {
|
||||
ENCODE(deltaS);
|
||||
changes |= NEW_W;
|
||||
}
|
||||
|
||||
if ((deltaL = ntohl(th->th_ack) - ntohl(oth->th_ack)) != 0) {
|
||||
if (deltaL > 0xffff)
|
||||
goto uncompressed;
|
||||
deltaA = (u_short)deltaL;
|
||||
ENCODE(deltaA);
|
||||
changes |= NEW_A;
|
||||
}
|
||||
|
||||
if ((deltaL = ntohl(th->th_seq) - ntohl(oth->th_seq)) != 0) {
|
||||
if (deltaL > 0xffff)
|
||||
goto uncompressed;
|
||||
deltaS = (u_short)deltaL;
|
||||
ENCODE(deltaS);
|
||||
changes |= NEW_S;
|
||||
}
|
||||
|
||||
switch(changes) {
|
||||
|
||||
case 0:
|
||||
/*
|
||||
* Nothing changed. If this packet contains data and the
|
||||
* last one didn't, this is probably a data packet following
|
||||
* an ack (normal on an interactive connection) and we send
|
||||
* it compressed. Otherwise it's probably a retransmit,
|
||||
* retransmitted ack or window probe. Send it uncompressed
|
||||
* in case the other side missed the compressed version.
|
||||
*/
|
||||
if (ip->ip_len != cs->cs_ip.ip_len &&
|
||||
ntohs(cs->cs_ip.ip_len) == hlen)
|
||||
break;
|
||||
|
||||
/* (fall through) */
|
||||
|
||||
case SPECIAL_I:
|
||||
case SPECIAL_D:
|
||||
/*
|
||||
* actual changes match one of our special case encodings --
|
||||
* send packet uncompressed.
|
||||
*/
|
||||
goto uncompressed;
|
||||
|
||||
case NEW_S|NEW_A:
|
||||
if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
|
||||
/* special case for echoed terminal traffic */
|
||||
changes = SPECIAL_I;
|
||||
cp = new_seq;
|
||||
}
|
||||
break;
|
||||
|
||||
case NEW_S:
|
||||
if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
|
||||
/* special case for data xfer */
|
||||
changes = SPECIAL_D;
|
||||
cp = new_seq;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
deltaS = (u_short)(ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id));
|
||||
if (deltaS != 1) {
|
||||
ENCODEZ(deltaS);
|
||||
changes |= NEW_I;
|
||||
}
|
||||
if (th->th_flags & TCP_PSH)
|
||||
changes |= TCP_PUSH_BIT;
|
||||
/*
|
||||
* Grab the cksum before we overwrite it below. Then update our
|
||||
* state with this packet's header.
|
||||
*/
|
||||
deltaA = ntohs(th->th_sum);
|
||||
BCOPY(ip, &cs->cs_ip, hlen);
|
||||
|
||||
/*
|
||||
* We want to use the original packet as our compressed packet.
|
||||
* (cp - new_seq) is the number of bytes we need for compressed
|
||||
* sequence numbers. In addition we need one byte for the change
|
||||
* mask, one for the connection id and two for the tcp checksum.
|
||||
* So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
|
||||
* many bytes of the original packet to toss so subtract the two to
|
||||
* get the new packet size.
|
||||
*/
|
||||
deltaS = (u_short)(cp - new_seq);
|
||||
if (!comp->compressSlot || comp->last_xmit != cs->cs_id) {
|
||||
comp->last_xmit = cs->cs_id;
|
||||
hlen -= deltaS + 4;
|
||||
pbuf_header(pb, -hlen);
|
||||
cp = (u_char *)pb->payload;
|
||||
*cp++ = changes | NEW_C;
|
||||
*cp++ = cs->cs_id;
|
||||
} else {
|
||||
hlen -= deltaS + 3;
|
||||
pbuf_header(pb, -hlen);
|
||||
cp = (u_char *)pb->payload;
|
||||
*cp++ = changes;
|
||||
}
|
||||
*cp++ = deltaA >> 8;
|
||||
*cp++ = deltaA;
|
||||
BCOPY(new_seq, cp, deltaS);
|
||||
INCR(vjs_compressed);
|
||||
return (TYPE_COMPRESSED_TCP);
|
||||
|
||||
/*
|
||||
* Update connection state cs & send uncompressed packet (that is,
|
||||
* a regular ip/tcp packet but with the 'conversation id' we hope
|
||||
* to use on future compressed packets in the protocol field).
|
||||
*/
|
||||
uncompressed:
|
||||
BCOPY(ip, &cs->cs_ip, hlen);
|
||||
ip->ip_p = cs->cs_id;
|
||||
comp->last_xmit = cs->cs_id;
|
||||
return (TYPE_UNCOMPRESSED_TCP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when we may have missed a packet.
|
||||
*/
|
||||
void vj_uncompress_err(struct vjcompress *comp)
|
||||
{
|
||||
comp->flags |= VJF_TOSS;
|
||||
INCR(vjs_errorin);
|
||||
}
|
||||
|
||||
/*
|
||||
* "Uncompress" a packet of type TYPE_UNCOMPRESSED_TCP.
|
||||
* Return 0 on success, -1 on failure.
|
||||
*/
|
||||
int vj_uncompress_uncomp(
|
||||
struct pbuf *nb,
|
||||
struct vjcompress *comp
|
||||
)
|
||||
{
|
||||
register u_int hlen;
|
||||
register struct cstate *cs;
|
||||
register struct ip *ip;
|
||||
|
||||
ip = (struct ip *)nb->payload;
|
||||
hlen = getip_hl(*ip) << 2;
|
||||
if (ip->ip_p >= MAX_SLOTS
|
||||
|| hlen + sizeof(struct tcphdr) > nb->len
|
||||
|| (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2)
|
||||
> nb->len
|
||||
|| hlen > MAX_HDR) {
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n",
|
||||
ip->ip_p, hlen, nb->len));
|
||||
comp->flags |= VJF_TOSS;
|
||||
INCR(vjs_errorin);
|
||||
return -1;
|
||||
}
|
||||
cs = &comp->rstate[comp->last_recv = ip->ip_p];
|
||||
comp->flags &=~ VJF_TOSS;
|
||||
ip->ip_p = IPPROTO_TCP;
|
||||
BCOPY(ip, &cs->cs_ip, hlen);
|
||||
cs->cs_hlen = hlen;
|
||||
INCR(vjs_uncompressedin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uncompress a packet of type TYPE_COMPRESSED_TCP.
|
||||
* The packet is composed of a buffer chain and the first buffer
|
||||
* must contain an accurate chain length.
|
||||
* The first buffer must include the entire compressed TCP/IP header.
|
||||
* This procedure replaces the compressed header with the uncompressed
|
||||
* header and returns the length of the VJ header.
|
||||
*/
|
||||
int vj_uncompress_tcp(
|
||||
struct pbuf **nb,
|
||||
struct vjcompress *comp
|
||||
)
|
||||
{
|
||||
u_char *cp;
|
||||
struct tcphdr *th;
|
||||
struct cstate *cs;
|
||||
u_short *bp;
|
||||
struct pbuf *n0 = *nb;
|
||||
u32_t tmp;
|
||||
u_int vjlen, hlen, changes;
|
||||
|
||||
INCR(vjs_compressedin);
|
||||
cp = (u_char *)n0->payload;
|
||||
changes = *cp++;
|
||||
if (changes & NEW_C) {
|
||||
/*
|
||||
* Make sure the state index is in range, then grab the state.
|
||||
* If we have a good state index, clear the 'discard' flag.
|
||||
*/
|
||||
if (*cp >= MAX_SLOTS) {
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: bad cid=%d\n", *cp));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
comp->flags &=~ VJF_TOSS;
|
||||
comp->last_recv = *cp++;
|
||||
} else {
|
||||
/*
|
||||
* this packet has an implicit state index. If we've
|
||||
* had a line error since the last time we got an
|
||||
* explicit state index, we have to toss the packet.
|
||||
*/
|
||||
if (comp->flags & VJF_TOSS) {
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: tossing\n"));
|
||||
INCR(vjs_tossed);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
cs = &comp->rstate[comp->last_recv];
|
||||
hlen = getip_hl(cs->cs_ip) << 2;
|
||||
th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
|
||||
th->th_sum = htons((*cp << 8) | cp[1]);
|
||||
cp += 2;
|
||||
if (changes & TCP_PUSH_BIT)
|
||||
th->th_flags |= TCP_PSH;
|
||||
else
|
||||
th->th_flags &=~ TCP_PSH;
|
||||
|
||||
switch (changes & SPECIALS_MASK) {
|
||||
case SPECIAL_I:
|
||||
{
|
||||
register u32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
|
||||
/* some compilers can't nest inline assembler.. */
|
||||
tmp = ntohl(th->th_ack) + i;
|
||||
th->th_ack = htonl(tmp);
|
||||
tmp = ntohl(th->th_seq) + i;
|
||||
th->th_seq = htonl(tmp);
|
||||
}
|
||||
break;
|
||||
|
||||
case SPECIAL_D:
|
||||
/* some compilers can't nest inline assembler.. */
|
||||
tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
|
||||
th->th_seq = htonl(tmp);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (changes & NEW_U) {
|
||||
th->th_flags |= TCP_URG;
|
||||
DECODEU(th->th_urp);
|
||||
} else
|
||||
th->th_flags &=~ TCP_URG;
|
||||
if (changes & NEW_W)
|
||||
DECODES(th->th_win);
|
||||
if (changes & NEW_A)
|
||||
DECODEL(th->th_ack);
|
||||
if (changes & NEW_S)
|
||||
DECODEL(th->th_seq);
|
||||
break;
|
||||
}
|
||||
if (changes & NEW_I) {
|
||||
DECODES(cs->cs_ip.ip_id);
|
||||
} else {
|
||||
cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1;
|
||||
cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, cp points to the first byte of data in the
|
||||
* packet. Fill in the IP total length and update the IP
|
||||
* header checksum.
|
||||
*/
|
||||
vjlen = (u_short)(cp - (u_char*)n0->payload);
|
||||
if (n0->len < vjlen) {
|
||||
/*
|
||||
* We must have dropped some characters (crc should detect
|
||||
* this but the old slip framing won't)
|
||||
*/
|
||||
PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: head buffer %d too short %d\n",
|
||||
n0->len, vjlen));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
tmp = n0->tot_len - vjlen + cs->cs_hlen;
|
||||
cs->cs_ip.ip_len = htons(tmp);
|
||||
#else
|
||||
cs->cs_ip.ip_len = htons(n0->tot_len - vjlen + cs->cs_hlen);
|
||||
#endif
|
||||
|
||||
/* recompute the ip header checksum */
|
||||
bp = (u_short *) &cs->cs_ip;
|
||||
cs->cs_ip.ip_sum = 0;
|
||||
for (tmp = 0; hlen > 0; hlen -= 2)
|
||||
tmp += *bp++;
|
||||
tmp = (tmp & 0xffff) + (tmp >> 16);
|
||||
tmp = (tmp & 0xffff) + (tmp >> 16);
|
||||
cs->cs_ip.ip_sum = (u_short)(~tmp);
|
||||
|
||||
/* Remove the compressed header and prepend the uncompressed header. */
|
||||
pbuf_header(n0, -vjlen);
|
||||
|
||||
if(MEM_ALIGN(n0->payload) != n0->payload) {
|
||||
struct pbuf *np, *q;
|
||||
u8_t *bufptr;
|
||||
|
||||
np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL);
|
||||
if(!np) {
|
||||
PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n"));
|
||||
*nb = NULL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
pbuf_header(np, -cs->cs_hlen);
|
||||
|
||||
bufptr = n0->payload;
|
||||
for(q = np; q != NULL; q = q->next) {
|
||||
memcpy(q->payload, bufptr, q->len);
|
||||
bufptr += q->len;
|
||||
}
|
||||
|
||||
if(n0->next) {
|
||||
pbuf_chain(np, n0->next);
|
||||
pbuf_dechain(n0);
|
||||
}
|
||||
pbuf_free(n0);
|
||||
n0 = np;
|
||||
}
|
||||
|
||||
if(pbuf_header(n0, cs->cs_hlen)) {
|
||||
struct pbuf *np;
|
||||
|
||||
LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE);
|
||||
np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL);
|
||||
if(!np) {
|
||||
PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: prepend failed\n"));
|
||||
*nb = NULL;
|
||||
goto bad;
|
||||
}
|
||||
pbuf_cat(np, n0);
|
||||
n0 = np;
|
||||
}
|
||||
LWIP_ASSERT("n0->len >= cs->cs_hlen", n0->len >= cs->cs_hlen);
|
||||
memcpy(n0->payload, &cs->cs_ip, cs->cs_hlen);
|
||||
|
||||
*nb = n0;
|
||||
|
||||
return vjlen;
|
||||
|
||||
bad:
|
||||
comp->flags |= VJF_TOSS;
|
||||
INCR(vjs_errorin);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
155
Demo/Common/ethernet/lwIP/netif/ppp/vj.h
Normal file
155
Demo/Common/ethernet/lwIP/netif/ppp/vj.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Definitions for tcp compression routines.
|
||||
*
|
||||
* $Id: vj.h,v 1.4 2004/02/07 00:30:03 likewise Exp $
|
||||
*
|
||||
* Copyright (c) 1989 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
|
||||
* - Initial distribution.
|
||||
*/
|
||||
|
||||
#ifndef VJ_H
|
||||
#define VJ_H
|
||||
|
||||
#include "vjbsdhdr.h"
|
||||
|
||||
#define MAX_SLOTS 16 /* must be > 2 and < 256 */
|
||||
#define MAX_HDR 128
|
||||
|
||||
/*
|
||||
* Compressed packet format:
|
||||
*
|
||||
* The first octet contains the packet type (top 3 bits), TCP
|
||||
* 'push' bit, and flags that indicate which of the 4 TCP sequence
|
||||
* numbers have changed (bottom 5 bits). The next octet is a
|
||||
* conversation number that associates a saved IP/TCP header with
|
||||
* the compressed packet. The next two octets are the TCP checksum
|
||||
* from the original datagram. The next 0 to 15 octets are
|
||||
* sequence number changes, one change per bit set in the header
|
||||
* (there may be no changes and there are two special cases where
|
||||
* the receiver implicitly knows what changed -- see below).
|
||||
*
|
||||
* There are 5 numbers which can change (they are always inserted
|
||||
* in the following order): TCP urgent pointer, window,
|
||||
* acknowlegement, sequence number and IP ID. (The urgent pointer
|
||||
* is different from the others in that its value is sent, not the
|
||||
* change in value.) Since typical use of SLIP links is biased
|
||||
* toward small packets (see comments on MTU/MSS below), changes
|
||||
* use a variable length coding with one octet for numbers in the
|
||||
* range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
|
||||
* range 256 - 65535 or 0. (If the change in sequence number or
|
||||
* ack is more than 65535, an uncompressed packet is sent.)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Packet types (must not conflict with IP protocol version)
|
||||
*
|
||||
* The top nibble of the first octet is the packet type. There are
|
||||
* three possible types: IP (not proto TCP or tcp with one of the
|
||||
* control flags set); uncompressed TCP (a normal IP/TCP packet but
|
||||
* with the 8-bit protocol field replaced by an 8-bit connection id --
|
||||
* this type of packet syncs the sender & receiver); and compressed
|
||||
* TCP (described above).
|
||||
*
|
||||
* LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
|
||||
* is logically part of the 4-bit "changes" field that follows. Top
|
||||
* three bits are actual packet type. For backward compatibility
|
||||
* and in the interest of conserving bits, numbers are chosen so the
|
||||
* IP protocol version number (4) which normally appears in this nibble
|
||||
* means "IP packet".
|
||||
*/
|
||||
|
||||
/* packet types */
|
||||
#define TYPE_IP 0x40
|
||||
#define TYPE_UNCOMPRESSED_TCP 0x70
|
||||
#define TYPE_COMPRESSED_TCP 0x80
|
||||
#define TYPE_ERROR 0x00
|
||||
|
||||
/* Bits in first octet of compressed packet */
|
||||
#define NEW_C 0x40 /* flag bits for what changed in a packet */
|
||||
#define NEW_I 0x20
|
||||
#define NEW_S 0x08
|
||||
#define NEW_A 0x04
|
||||
#define NEW_W 0x02
|
||||
#define NEW_U 0x01
|
||||
|
||||
/* reserved, special-case values of above */
|
||||
#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
|
||||
#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
|
||||
#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
|
||||
|
||||
#define TCP_PUSH_BIT 0x10
|
||||
|
||||
|
||||
/*
|
||||
* "state" data for each active tcp conversation on the wire. This is
|
||||
* basically a copy of the entire IP/TCP header from the last packet
|
||||
* we saw from the conversation together with a small identifier
|
||||
* the transmit & receive ends of the line use to locate saved header.
|
||||
*/
|
||||
struct cstate {
|
||||
struct cstate *cs_next; /* next most recently used state (xmit only) */
|
||||
u_short cs_hlen; /* size of hdr (receive only) */
|
||||
u_char cs_id; /* connection # associated with this state */
|
||||
u_char cs_filler;
|
||||
union {
|
||||
char csu_hdr[MAX_HDR];
|
||||
struct ip csu_ip; /* ip/tcp hdr from most recent packet */
|
||||
} vjcs_u;
|
||||
};
|
||||
#define cs_ip vjcs_u.csu_ip
|
||||
#define cs_hdr vjcs_u.csu_hdr
|
||||
|
||||
|
||||
struct vjstat {
|
||||
unsigned long vjs_packets; /* outbound packets */
|
||||
unsigned long vjs_compressed; /* outbound compressed packets */
|
||||
unsigned long vjs_searches; /* searches for connection state */
|
||||
unsigned long vjs_misses; /* times couldn't find conn. state */
|
||||
unsigned long vjs_uncompressedin; /* inbound uncompressed packets */
|
||||
unsigned long vjs_compressedin; /* inbound compressed packets */
|
||||
unsigned long vjs_errorin; /* inbound unknown type packets */
|
||||
unsigned long vjs_tossed; /* inbound packets tossed because of error */
|
||||
};
|
||||
|
||||
/*
|
||||
* all the state data for one serial line (we need one of these per line).
|
||||
*/
|
||||
struct vjcompress {
|
||||
struct cstate *last_cs; /* most recently used tstate */
|
||||
u_char last_recv; /* last rcvd conn. id */
|
||||
u_char last_xmit; /* last sent conn. id */
|
||||
u_short flags;
|
||||
u_char maxSlotIndex;
|
||||
u_char compressSlot; /* Flag indicating OK to compress slot ID. */
|
||||
#if LINK_STATS
|
||||
struct vjstat stats;
|
||||
#endif
|
||||
struct cstate tstate[MAX_SLOTS]; /* xmit connection states */
|
||||
struct cstate rstate[MAX_SLOTS]; /* receive connection states */
|
||||
};
|
||||
|
||||
/* flag values */
|
||||
#define VJF_TOSS 1U /* tossing rcvd frames because of input err */
|
||||
|
||||
extern void vj_compress_init (struct vjcompress *comp);
|
||||
extern u_int vj_compress_tcp (struct vjcompress *comp, struct pbuf *pb);
|
||||
extern void vj_uncompress_err (struct vjcompress *comp);
|
||||
extern int vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp);
|
||||
extern int vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp);
|
||||
|
||||
#endif /* VJ_H */
|
76
Demo/Common/ethernet/lwIP/netif/ppp/vjbsdhdr.h
Normal file
76
Demo/Common/ethernet/lwIP/netif/ppp/vjbsdhdr.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#ifndef VJBSDHDR_H
|
||||
#define VJBSDHDR_H
|
||||
|
||||
#include "lwip/tcp.h"
|
||||
|
||||
|
||||
/*
|
||||
* Structure of an internet header, naked of options.
|
||||
*
|
||||
* We declare ip_len and ip_off to be short, rather than u_short
|
||||
* pragmatically since otherwise unsigned comparisons can result
|
||||
* against negative integers quite easily, and fail in subtle ways.
|
||||
*/
|
||||
PACK_STRUCT_BEGIN
|
||||
struct ip
|
||||
{
|
||||
#if defined(NO_CHAR_BITFIELDS)
|
||||
u_char ip_hl_v; /* bug in GCC for mips means the bitfield stuff will sometimes break - so we use a char for both and get round it with macro's instead... */
|
||||
#else
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
unsigned ip_hl:4, /* header length */
|
||||
ip_v:4; /* version */
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
unsigned ip_v:4, /* version */
|
||||
ip_hl:4; /* header length */
|
||||
#else
|
||||
COMPLAIN - NO BYTE ORDER SELECTED!
|
||||
#endif
|
||||
#endif
|
||||
u_char ip_tos; /* type of service */
|
||||
u_short ip_len; /* total length */
|
||||
u_short ip_id; /* identification */
|
||||
u_short ip_off; /* fragment offset field */
|
||||
#define IP_DF 0x4000 /* dont fragment flag */
|
||||
#define IP_MF 0x2000 /* more fragments flag */
|
||||
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
|
||||
u_char ip_ttl; /* time to live */
|
||||
u_char ip_p; /* protocol */
|
||||
u_short ip_sum; /* checksum */
|
||||
struct in_addr ip_src,ip_dst; /* source and dest address */
|
||||
};
|
||||
PACK_STRUCT_END
|
||||
|
||||
typedef u32_t tcp_seq;
|
||||
|
||||
/*
|
||||
* TCP header.
|
||||
* Per RFC 793, September, 1981.
|
||||
*/
|
||||
PACK_STRUCT_BEGIN
|
||||
struct tcphdr
|
||||
{
|
||||
u_short th_sport; /* source port */
|
||||
u_short th_dport; /* destination port */
|
||||
tcp_seq th_seq; /* sequence number */
|
||||
tcp_seq th_ack; /* acknowledgement number */
|
||||
#if defined(NO_CHAR_BITFIELDS)
|
||||
u_char th_x2_off;
|
||||
#else
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
unsigned th_x2:4, /* (unused) */
|
||||
th_off:4; /* data offset */
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
unsigned th_off:4, /* data offset */
|
||||
th_x2:4; /* (unused) */
|
||||
#endif
|
||||
#endif
|
||||
u_char th_flags;
|
||||
u_short th_win; /* window */
|
||||
u_short th_sum; /* checksum */
|
||||
u_short th_urp; /* urgent pointer */
|
||||
};
|
||||
PACK_STRUCT_END
|
||||
|
||||
#endif /* VJBSDHDR_H */
|
213
Demo/Common/ethernet/lwIP/netif/slipif.c
Normal file
213
Demo/Common/ethernet/lwIP/netif/slipif.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* This file is built upon the file: src/arch/rtxc/netif/sioslip.c
|
||||
*
|
||||
* Author: Magnus Ivarsson <magnus.ivarsson(at)volvo.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an arch independent SLIP netif. The specific serial hooks must be
|
||||
* provided by another file. They are sio_open, sio_recv and sio_send
|
||||
*/
|
||||
|
||||
#include "netif/slipif.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/sio.h"
|
||||
|
||||
#define SLIP_END 0300
|
||||
#define SLIP_ESC 0333
|
||||
#define SLIP_ESC_END 0334
|
||||
#define SLIP_ESC_ESC 0335
|
||||
|
||||
#define MAX_SIZE 1500
|
||||
|
||||
/**
|
||||
* Send a pbuf doing the necessary SLIP encapsulation
|
||||
*
|
||||
* Uses the serial layer's sio_send()
|
||||
*/
|
||||
err_t
|
||||
slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
|
||||
{
|
||||
struct pbuf *q;
|
||||
u16_t i;
|
||||
u8_t c;
|
||||
|
||||
/* Send pbuf out on the serial I/O device. */
|
||||
sio_send(SLIP_END, netif->state);
|
||||
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
for (i = 0; i < q->len; i++) {
|
||||
c = ((u8_t *)q->payload)[i];
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_END, netif->state);
|
||||
break;
|
||||
case SLIP_ESC:
|
||||
sio_send(SLIP_ESC, netif->state);
|
||||
sio_send(SLIP_ESC_ESC, netif->state);
|
||||
break;
|
||||
default:
|
||||
sio_send(c, netif->state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
sio_send(SLIP_END, netif->state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming SLIP stream character by character
|
||||
*
|
||||
* Poll the serial layer by calling sio_recv()
|
||||
*
|
||||
* @return The IP packet when SLIP_END is received
|
||||
*/
|
||||
static struct pbuf *
|
||||
slipif_input(struct netif *netif)
|
||||
{
|
||||
u8_t c;
|
||||
struct pbuf *p, *q;
|
||||
u16_t recved;
|
||||
u16_t i;
|
||||
|
||||
q = p = NULL;
|
||||
recved = i = 0;
|
||||
c = 0;
|
||||
|
||||
while (1) {
|
||||
c = sio_recv(netif->state);
|
||||
switch (c) {
|
||||
case SLIP_END:
|
||||
if (recved > 0) {
|
||||
/* Received whole packet. */
|
||||
pbuf_realloc(q, recved);
|
||||
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
|
||||
return q;
|
||||
}
|
||||
break;
|
||||
|
||||
case SLIP_ESC:
|
||||
c = sio_recv(netif->state);
|
||||
switch (c) {
|
||||
case SLIP_ESC_END:
|
||||
c = SLIP_END;
|
||||
break;
|
||||
case SLIP_ESC_ESC:
|
||||
c = SLIP_ESC;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
if (p == NULL) {
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
|
||||
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
|
||||
|
||||
if (p == NULL) {
|
||||
LINK_STATS_INC(link.drop);
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
|
||||
}
|
||||
|
||||
if (q != NULL) {
|
||||
pbuf_cat(q, p);
|
||||
} else {
|
||||
q = p;
|
||||
}
|
||||
}
|
||||
if (p != NULL && recved < MAX_SIZE) {
|
||||
((u8_t *)p->payload)[i] = c;
|
||||
recved++;
|
||||
i++;
|
||||
if (i >= p->len) {
|
||||
i = 0;
|
||||
if (p->next != NULL && p->next->len > 0)
|
||||
p = p->next;
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The SLIP input thread.
|
||||
*
|
||||
* Feed the IP layer with incoming packets
|
||||
*/
|
||||
static void
|
||||
slipif_loop(void *nf)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)nf;
|
||||
|
||||
while (1) {
|
||||
p = slipif_input(netif);
|
||||
netif->input(p, netif);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SLIP netif initialization
|
||||
*
|
||||
* Call the arch specific sio_open and remember
|
||||
* the opened device in the state field of the netif.
|
||||
*/
|
||||
err_t
|
||||
slipif_init(struct netif *netif)
|
||||
{
|
||||
|
||||
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num));
|
||||
|
||||
netif->name[0] = 's';
|
||||
netif->name[1] = 'l';
|
||||
netif->output = slipif_output;
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_POINTTOPOINT;
|
||||
|
||||
netif->state = sio_open(netif->num);
|
||||
if (!netif->state)
|
||||
return ERR_IF;
|
||||
|
||||
sys_thread_new(slipif_loop, netif, SLIPIF_THREAD_PRIO);
|
||||
return ERR_OK;
|
||||
}
|
Loading…
Reference in a new issue