Merged from DEVEL into main tree.

This commit is contained in:
likewise 2003-11-14 13:17:23 +00:00
parent bdfdc2bb83
commit e4a6d199fe
45 changed files with 2329 additions and 850 deletions

View File

@ -1,17 +1,30 @@
HISTORY
(todo)
* Fix unaligned 16-bit access in checksum routine.
(current)
++ Bug fixes:
* some debug formatters and casts fixed.
* numerous fixes in PPP.
* Fixed TCP bug induced by bad window resizing with unidirectional TCP traffic.
* Packets sent from ARP queue had invalid source hardware address.
* Some debug formatters and casts fixed.
* Numerous fixes in PPP.
++ Changes:
* DEBUGF now is LWIP_DEBUGF
* pbuf_dechain() has been re-enabled.
* Mentioned the changed use of CVS branches in README.
* Mentioned the use of CVS branches in README.
* Pass-by ARP requests do now update the cache.
++ New features:
* No longer dependent on ctype.h.
* New socket options.
* Raw IP pcb support.
(STABLE-0_6_3)

View File

@ -11,7 +11,7 @@ Table of Contents:
1 Anonymous CVS checkouts and updates
-------------------------------------
Obtain lwIP from the STABLE tree (on the CVS main trunk)
Obtain lwIP from the CVS main trunk (stable)
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout lwip
@ -24,29 +24,37 @@ cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r STABLE-0_6_
Or, obtain a development branch as follows:
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-devel lwip
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip checkout -r DEVEL -d lwip-DEVEL lwip
3 Merging from DEVEL branch to main trunk (stable branch)
3 Merging from DEVEL branch to main trunk (stable)
---------------------------------------------------------
Merging from DEVEL to main requires that the DEVEL branch
has a tag indicating the previous merger. This tag is
called 'merged_from_DEVEL_to_main'.
Merging is a delicate process in CVS and requires the
following disciplined steps in order to prevent conflicts
in the future. Conflicts can be hard to solve!
Merging from branch A to branch B requires that the A branch
has a tag indicating the previous merger. This tag is called
'merged_from_A_to_B'. After merging, the tag is moved in the
A branch to remember this merger for future merge actions.
IMPORTANT: AFTER COMMITTING A SUCCESFUL MERGE IN THE
REPOSITORY, THE TAG MUST BE SET ON THE SOURCE OF THE
MERGE BRANCH (REPLACING EXISTING TAGS WITH THE SAME NAME).
REPOSITORY, THE TAG MUST BE SET ON THE SOURCE BRANCH OF THE
MERGE ACTION (REPLACING EXISTING TAGS WITH THE SAME NAME).
Merge all changes in DEVEL since our last merge to main:
In the working copy of the main trunk:
cvs update -P -jmerged_from_DEVEL_to_main -jDEVEL
Now move the tag in the DEVEL branch to this merge point,
so we can use this for future merges.
(This will apply the changes between 'merged_from_DEVEL_to_main'
and 'DEVEL' to your work set of files)
cvs -z4 rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
If this worked out OK, we now move the tag in the DEVEL branch
to this merge point, so we can use this point for future merges:
cvs rtag -F -r DEVEL merged_from_DEVEL_to_main lwip
4 How to release lwIP
---------------------
@ -61,7 +69,7 @@ is not created locally.
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip login
cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/lwip export -r STABLE-0_6_3 -d lwip-0.6.3 lwip
Archive this directory using tar.
Archive this directory using tar, gzip'd, bzip2'd and zip'd.
tar czvf lwip-0.6.3.tar.gz lwip-0.6.3
@ -74,17 +82,15 @@ Now, make a new release by creating a new directory for it (these are
Savannah conventions so that it shows up in the Files list real nice):
mkdir stable.pkg
cd stable.pkg
mkdir 0.6.3
cd 0.6.3
mkdir stable.pkg 0.6.3
We can now copy the tar archive we made earlier into the release directory:
cp /../../../lwip-0.6.3.tar.gz .
cp ../../../lwip-0.6.3.tar.gz .
Finally, synchronize this directory upwards to Savannah:
rsync -n -e "ssh -1" -t -u -v -r . likewise@savannah.nongnu.org:/upload/lwip
rsync -n -e "ssh -1" -t -u -v -r *.pkg likewise@savannah.nongnu.org:/upload/lwip
This does a "dry run": no files are modified! After you have confirmed that
this is what you intended to do, remove "-n" and actually synchronize for

View File

@ -38,7 +38,7 @@
#include "lwip/api_msg.h"
#include "lwip/memp.h"
/*-----------------------------------------------------------------------------------*/
struct
netbuf *netbuf_new(void)
{
@ -53,7 +53,7 @@ netbuf *netbuf_new(void)
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_delete(struct netbuf *buf)
{
@ -65,7 +65,7 @@ netbuf_delete(struct netbuf *buf)
memp_free(MEMP_NETBUF, buf);
}
}
/*-----------------------------------------------------------------------------------*/
void *
netbuf_alloc(struct netbuf *buf, u16_t size)
{
@ -80,7 +80,7 @@ netbuf_alloc(struct netbuf *buf, u16_t size)
buf->ptr = buf->p;
return buf->p->payload;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_free(struct netbuf *buf)
{
@ -89,7 +89,7 @@ netbuf_free(struct netbuf *buf)
}
buf->p = buf->ptr = NULL;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
{
@ -101,7 +101,7 @@ netbuf_ref(struct netbuf *buf, void *dataptr, u16_t size)
buf->p->len = buf->p->tot_len = size;
buf->ptr = buf->p;
}
/*-----------------------------------------------------------------------------------*/
void
netbuf_chain(struct netbuf *head, struct netbuf *tail)
{
@ -109,13 +109,13 @@ netbuf_chain(struct netbuf *head, struct netbuf *tail)
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)
{
@ -126,7 +126,7 @@ netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
*len = buf->ptr->len;
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
s8_t
netbuf_next(struct netbuf *buf)
{
@ -139,13 +139,13 @@ netbuf_next(struct netbuf *buf)
}
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)
{
@ -154,7 +154,7 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
left = 0;
if (buf == NULL) {
if(buf == NULL || dataptr == NULL) {
return;
}
@ -174,34 +174,38 @@ netbuf_copy_partial(struct netbuf *buf, void *dataptr, u16_t len, u16_t offset)
}
}
}
/*-----------------------------------------------------------------------------------*/
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(enum netconn_type t)
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;
@ -214,25 +218,44 @@ netconn *netconn_new(enum netconn_type t)
conn->sem = SYS_SEM_NULL;
conn->state = NETCONN_NONE;
conn->socket = 0;
conn->callback = 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))
{
struct netconn *conn;
/* get a netconn and then initialize callback pointer and socket */
conn = netconn_new(t);
if (conn)
conn->callback = callback;
return conn;
return netconn_new_with_proto_and_callback(t,0,callback);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_delete(struct netconn *conn)
{
@ -286,18 +309,21 @@ netconn_delete(struct netconn *conn)
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:
@ -316,12 +342,16 @@ netconn_peer(struct netconn *conn, struct ip_addr *addr,
}
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:
@ -335,7 +365,7 @@ netconn_addr(struct netconn *conn, struct ip_addr **addr,
}
return (conn->err = ERR_OK);
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_bind(struct netconn *conn, struct ip_addr *addr,
u16_t port)
@ -366,7 +396,7 @@ netconn_bind(struct netconn *conn, struct ip_addr *addr,
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_connect(struct netconn *conn, struct ip_addr *addr,
u16_t port)
@ -417,7 +447,7 @@ netconn_disconnect(struct netconn *conn)
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_listen(struct netconn *conn)
{
@ -444,7 +474,7 @@ netconn_listen(struct netconn *conn)
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
struct netconn *
netconn_accept(struct netconn *conn)
{
@ -461,7 +491,7 @@ netconn_accept(struct netconn *conn)
return newconn;
}
/*-----------------------------------------------------------------------------------*/
struct netbuf *
netconn_recv(struct netconn *conn)
{
@ -557,7 +587,7 @@ netconn_recv(struct netconn *conn)
return buf;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_send(struct netconn *conn, struct netbuf *buf)
{
@ -585,7 +615,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
{
@ -661,7 +691,7 @@ netconn_write(struct netconn *conn, void *dataptr, u16_t size, u8_t copy)
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_close(struct netconn *conn)
{
@ -689,10 +719,10 @@ netconn_close(struct netconn *conn)
memp_free(MEMP_API_MSG, msg);
return conn->err;
}
/*-----------------------------------------------------------------------------------*/
err_t
netconn_err(struct netconn *conn)
{
return conn->err;
}
/*-----------------------------------------------------------------------------------*/

View File

@ -37,6 +37,37 @@
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#if LWIP_RAW
static int
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,
@ -72,7 +103,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
}
#endif /* LWIP_UDP */
#if LWIP_TCP
/*-----------------------------------------------------------------------------------*/
static err_t
recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
@ -103,7 +134,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
poll_tcp(void *arg, struct tcp_pcb *pcb)
{
@ -117,7 +148,7 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
{
@ -134,7 +165,7 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
err_tcp(void *arg, err_t err)
{
@ -165,7 +196,7 @@ err_tcp(void *arg, err_t err)
sys_sem_signal(conn->sem);
}
}
/*-----------------------------------------------------------------------------------*/
static void
setup_tcp(struct netconn *conn)
{
@ -178,7 +209,7 @@ setup_tcp(struct netconn *conn)
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)
{
@ -234,17 +265,83 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
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 */
@ -287,12 +384,18 @@ do_delconn(struct api_msg_msg *msg)
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();
@ -319,6 +422,11 @@ do_bind(struct api_msg_msg *msg)
}
}
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 */
@ -339,7 +447,7 @@ do_bind(struct api_msg_msg *msg)
sys_mbox_post(msg->conn->mbox, NULL);
}
#if LWIP_TCP
/*-----------------------------------------------------------------------------------*/
static err_t
do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
@ -359,12 +467,18 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
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();
@ -410,6 +524,12 @@ do_connect(struct api_msg_msg *msg)
}
}
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 */
@ -428,6 +548,7 @@ do_connect(struct api_msg_msg *msg)
do_connected);
/*tcp_output(msg->conn->pcb.tcp);*/
#endif
default:
break;
}
@ -438,6 +559,11 @@ 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 */
@ -453,12 +579,17 @@ do_disconnect(struct api_msg_msg *msg)
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 */
@ -491,12 +622,17 @@ do_listen(struct api_msg_msg *msg)
}
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 */
@ -511,12 +647,17 @@ do_accept(struct api_msg_msg *msg)
}
}
}
/*-----------------------------------------------------------------------------------*/
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 */
@ -532,7 +673,7 @@ do_send(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_recv(struct api_msg_msg *msg)
{
@ -545,7 +686,7 @@ do_recv(struct api_msg_msg *msg)
#endif
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_write(struct api_msg_msg *msg)
{
@ -554,6 +695,11 @@ do_write(struct api_msg_msg *msg)
#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 */
@ -571,7 +717,7 @@ do_write(struct api_msg_msg *msg)
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) {
if(err == ERR_OK && (msg->conn->pcb.tcp->unacked == NULL || (msg->conn->pcb.tcp->flags & TF_NODELAY)) ) {
tcp_output(msg->conn->pcb.tcp);
}
msg->conn->err = err;
@ -588,7 +734,7 @@ do_write(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
/*-----------------------------------------------------------------------------------*/
static void
do_close(struct api_msg_msg *msg)
{
@ -598,6 +744,10 @@ do_close(struct api_msg_msg *msg)
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 */
@ -619,7 +769,7 @@ do_close(struct api_msg_msg *msg)
}
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,
@ -639,12 +789,12 @@ api_msg_input(struct api_msg *msg)
{
decode[msg->type](&(msg->msg));
}
/*-----------------------------------------------------------------------------------*/
void
api_msg_post(struct api_msg *msg)
{
tcpip_apimsg(msg);
}
/*-----------------------------------------------------------------------------------*/

View File

@ -47,13 +47,13 @@ static char *err_strerr[] = {"Ok.",
"Address in use."
};
/*-----------------------------------------------------------------------------------*/
char *
lwip_strerr(err_t err)
{
return err_strerr[-err];
}
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_DEBUG */

View File

@ -99,7 +99,7 @@ static int err_to_errno_table[11] = {
set_errno(sk->err); \
} while (0)
/*-----------------------------------------------------------------------------------*/
static struct lwip_socket *
get_socket(int s)
{
@ -121,7 +121,7 @@ get_socket(int s)
return sock;
}
/*-----------------------------------------------------------------------------------*/
static int
alloc_socket(struct netconn *newconn)
{
@ -150,7 +150,7 @@ alloc_socket(struct netconn *newconn)
sys_sem_signal(socksem);
return -1;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
{
@ -164,6 +164,7 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d)...\n", s));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -197,16 +198,14 @@ lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
newconn->socket = newsock;
sys_sem_signal(socksem);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_accept(%d) returning new sock=%d addr=", s, newsock));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", port));
#endif
sock_set_errno(sock, 0);
return newsock;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
{
@ -217,17 +216,16 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
local_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
local_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &local_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(local_port)));
#endif
err = netconn_bind(sock->conn, &local_addr, ntohs(local_port));
@ -241,7 +239,7 @@ lwip_bind(int s, struct sockaddr *name, socklen_t namelen)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_close(int s)
{
@ -257,6 +255,7 @@ lwip_close(int s)
sock = get_socket(s);
if (!sock) {
sys_sem_signal(socksem);
set_errno(EBADF);
return -1;
}
@ -271,7 +270,7 @@ lwip_close(int s)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
{
@ -280,6 +279,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -293,11 +293,9 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
remote_addr.addr = ((struct sockaddr_in *)name)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)name)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_connect(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u)\n", ntohs(remote_port)));
#endif
err = netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
}
@ -312,7 +310,7 @@ lwip_connect(int s, struct sockaddr *name, socklen_t namelen)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_listen(int s, int backlog)
{
@ -322,6 +320,7 @@ lwip_listen(int s, int backlog)
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_listen(%d, backlog=%d)\n", s, backlog));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -336,7 +335,7 @@ lwip_listen(int s, int backlog)
sock_set_errno(sock, 0);
return 0;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen)
@ -351,6 +350,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags));
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -411,11 +411,9 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
memcpy(from, &sin, *fromlen);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen));
#endif
} else {
#if SOCKETS_DEBUG > 0
addr = netbuf_fromaddr(buf);
@ -444,19 +442,19 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags,
sock_set_errno(sock, 0);
return copylen;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_read(int s, void *mem, int len)
{
return lwip_recvfrom(s, mem, len, 0, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_recv(int s, void *mem, int len, unsigned int flags)
{
return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
}
/*-----------------------------------------------------------------------------------*/
int
lwip_send(int s, void *data, int size, unsigned int flags)
{
@ -468,11 +466,15 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
switch (netconn_type(sock->conn)) {
case NETCONN_RAW:
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */
buf = netbuf_new();
@ -509,7 +511,7 @@ lwip_send(int s, void *data, int size, unsigned int flags)
sock_set_errno(sock, 0);
return size;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_sendto(int s, void *data, int size, unsigned int flags,
struct sockaddr *to, socklen_t tolen)
@ -521,6 +523,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -530,11 +533,9 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
remote_port = ((struct sockaddr_in *)to)->sin_port;
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags));
ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port)));
#endif
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port));
@ -548,7 +549,7 @@ lwip_sendto(int s, void *data, int size, unsigned int flags,
netconn_disconnect(sock->conn);
return ret;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_socket(int domain, int type, int protocol)
{
@ -557,6 +558,10 @@ lwip_socket(int domain, int type, int protocol)
/* create a netconn */
switch (type) {
case SOCK_RAW:
conn = netconn_new_with_proto_and_callback(NETCONN_RAW, protocol, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
break;
case SOCK_DGRAM:
conn = netconn_new_with_callback(NETCONN_UDP, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
@ -589,14 +594,14 @@ lwip_socket(int domain, int type, int protocol)
set_errno(0);
return i;
}
/*-----------------------------------------------------------------------------------*/
int
lwip_write(int s, void *data, int size)
{
return lwip_send(s, data, size, 0);
}
/*-----------------------------------------------------------------------------------*/
static int
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
{
@ -643,7 +648,7 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
}
/*-----------------------------------------------------------------------------------*/
int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout)
@ -723,7 +728,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* Wait forever */
msectimeout = 0;
else
msectimeout = ((timeout->tv_sec * 1000) + (timeout->tv_usec /1000));
msectimeout = ((timeout->tv_sec * 1000) + ((timeout->tv_usec + 500)/1000));
i = sys_sem_wait_timeout(select_cb.sem, msectimeout);
@ -789,7 +794,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
return nready;
}
/*-----------------------------------------------------------------------------------*/
static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{
@ -878,7 +883,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
}
/*-----------------------------------------------------------------------------------*/
int lwip_shutdown(int s, int how)
@ -895,6 +900,7 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -905,11 +911,9 @@ int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
/* get the IP address and port of the remote host */
netconn_peer(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getpeername(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, &naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr.addr;
@ -930,6 +934,7 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
sock = get_socket(s);
if (!sock) {
set_errno(EBADF);
return -1;
}
@ -940,11 +945,9 @@ int lwip_getsockname (int s, struct sockaddr *name, socklen_t *namelen)
/* get the IP address and port of the remote host */
netconn_addr(sock->conn, &naddr, &sin.sin_port);
#if SOCKETS_DEBUG
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockname(%d, addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, naddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%d)\n", sin.sin_port));
#endif
sin.sin_port = htons(sin.sin_port);
sin.sin_addr.s_addr = naddr->addr;
@ -959,32 +962,190 @@ 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 err = ENOSYS;
int err = 0;
struct lwip_socket *sock = get_socket(s);
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
if (level == SOL_SOCKET) {
switch (optname) {
if( NULL == optval || NULL == optlen ) {
sock_set_errno( sock, EFAULT );
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch( level ) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_ERROR:
if (!optval || !optlen || (*optlen != sizeof(int))) {
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
case SO_TYPE:
/* UNIMPL case SO_USELOOPBACK: */
if( *optlen < sizeof(int) ) {
err = EINVAL;
break;
}
*(int *)optval = sock->err;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
err = 0;
break;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch(optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if( *optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( *optlen < sizeof(int) ) {
err = EINVAL;
break;
}
} else {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
/* If this is no TCP socket, ignore any options. */
if ( sock->conn->type != NETCONN_TCP ) return 0;
switch( optname ) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch( optname ) {
/* The option flags */
case SO_ACCEPTCONN:
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/*case SO_USELOOPBACK: UNIMPL */
*(int*)optval = sock->conn->pcb.tcp->so_options & optname;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, optname=0x%x, ..) = %s\n", s, optname, (*(int*)optval?"on":"off")));
break;
case SO_TYPE:
switch (sock->conn->type) {
case NETCONN_RAW:
*(int*)optval = SOCK_RAW;
break;
case NETCONN_TCP:
*(int*)optval = SOCK_STREAM;
break;
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
*(int*)optval = SOCK_DGRAM;
break;
default: /* unrecognized socket type */
*(int*)optval = sock->conn->type;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", s, *(int *)optval));
} /* switch */
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval));
break;
case SO_ERROR:
*(int *)optval = sock->err;
sock->err = 0;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_ERROR) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch( optname ) {
case IP_TTL:
*(int*)optval = sock->conn->pcb.tcp->ttl;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TTL) = %d\n", s, *(int *)optval));
break;
case IP_TOS:
*(int*)optval = sock->conn->pcb.tcp->tos;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, IP_TOS) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch( optname ) {
case TCP_NODELAY:
*(int*)optval = (sock->conn->pcb.tcp->flags & TF_NODELAY);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, TCP_NODELAY) = %s\n", s, (*(int*)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
*(int*)optval = sock->conn->pcb.tcp->keepalive;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IP, TCP_KEEPALIVE) = %d\n", s, *(int *)optval));
break;
} /* switch */
break;
}
sock_set_errno(sock, err);
return err ? -1 : 0;
}
@ -992,27 +1153,165 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen)
{
struct lwip_socket *sock = get_socket(s);
int err = ENOSYS;
int err = 0;
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
if (level == SOL_SOCKET) {
switch (optname) {
case SO_REUSEADDR:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, SO_REUSEADDR, ..)\n", s));
/* XXX just pretend we support this for now */
err = 0;
if( NULL == optval ) {
sock_set_errno( sock, EFAULT );
return -1;
}
/* Do length and type checks for the various options first, to keep it readable. */
switch( level ) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINLINE: */
/* UNIMPL case SO_RCVBUF: */
/* UNIMPL case SO_SNDBUF: */
/* UNIMPL case SO_RCVLOWAT: */
/* UNIMPL case SO_SNDLOWAT: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch(optname) {
/* UNIMPL case IP_HDRINCL: */
/* UNIMPL case IP_RCVDSTADDR: */
/* UNIMPL case IP_RCVIF: */
case IP_TTL:
case IP_TOS:
if( optlen < sizeof(int) ) {
err = EINVAL;
}
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, UNIMPL: optname=0x%x, ..)\n", s, optname));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
if( optlen < sizeof(int) ) {
err = EINVAL;
break;
}
} else {
/* If this is no TCP socket, ignore any options. */
if ( sock->conn->type != NETCONN_TCP ) return 0;
switch( optname ) {
case TCP_NODELAY:
case TCP_KEEPALIVE:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
} /* switch */
break;
/* UNDEFINED LEVEL */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", s, level, optname));
err = ENOPROTOOPT;
} /* switch */
if( 0 != err ) {
sock_set_errno(sock, err);
return -1;
}
/* Now do the actual option processing */
switch(level) {
/* Level: SOL_SOCKET */
case SOL_SOCKET:
switch(optname) {
/* The option flags */
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case SO_OOBINCLUDE: */
#ifdef SO_REUSE
case SO_REUSEADDR:
case SO_REUSEPORT:
#endif /* SO_REUSE */
/* UNIMPL case SO_USELOOPBACK: */
if ( *(int*)optval ) {
sock->conn->pcb.tcp->so_options |= optname;
} else {
sock->conn->pcb.tcp->so_options &= ~optname;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_SOCKET, optname=0x%x, ..) -> %s\n", s, optname, (*(int*)optval?"on":"off")));
break;
} /* switch */
break;
/* Level: IPPROTO_IP */
case IPPROTO_IP:
switch( optname ) {
case IP_TTL:
sock->conn->pcb.tcp->ttl = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TTL, ..) -> %u\n", s, sock->conn->pcb.tcp->ttl));
break;
case IP_TOS:
sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
break;
} /* switch */
break;
/* Level: IPPROTO_TCP */
case IPPROTO_TCP:
switch( optname ) {
case TCP_NODELAY:
if ( *(int*)optval ) {
sock->conn->pcb.tcp->flags |= TF_NODELAY;
} else {
sock->conn->pcb.tcp->flags &= ~TF_NODELAY;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) -> %s\n", s, (*(int *)optval)?"on":"off") );
break;
case TCP_KEEPALIVE:
sock->conn->pcb.tcp->keepalive = (u32_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_TCP, TCP_KEEPALIVE) -> %u\n", s, sock->conn->pcb.tcp->keepalive));
break;
} /* switch */
break;
} /* switch */
sock_set_errno(sock, err);
return err ? -1 : 0;
}
@ -1021,7 +1320,8 @@ int lwip_ioctl(int s, long cmd, void *argp)
{
struct lwip_socket *sock = get_socket(s);
if (!sock) {
if(!sock) {
set_errno(EBADF);
return -1;
}
@ -1035,7 +1335,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
*((u16_t*)argp) = sock->conn->recv_avail;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp)));
sock_set_errno(sock, 0);
sock_set_errno(sock, 0);
return 0;
case FIONBIO:
@ -1044,7 +1344,7 @@ int lwip_ioctl(int s, long cmd, void *argp)
else
sock->flags &= ~O_NONBLOCK;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, !!(sock->flags & O_NONBLOCK)));
sock_set_errno(sock, 0);
sock_set_errno(sock, 0);
return 0;
default:

View File

@ -50,7 +50,7 @@ static sys_mbox_t mbox;
static int tcpip_tcp_timer_active = 0;
/*-----------------------------------------------------------------------------------*/
static void
tcpip_tcp_timer(void *arg)
{
@ -73,7 +73,7 @@ tcp_timer_needed(void)
}
}
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/
static void
tcpip_thread(void *arg)
{
@ -113,7 +113,7 @@ tcpip_thread(void *arg)
memp_free(MEMP_TCPIP_MSG, msg);
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_input(struct pbuf *p, struct netif *inp)
{
@ -131,7 +131,7 @@ tcpip_input(struct pbuf *p, struct netif *inp)
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
err_t
tcpip_callback(void (*f)(void *ctx), void *ctx)
{
@ -148,7 +148,7 @@ tcpip_callback(void (*f)(void *ctx), void *ctx)
sys_mbox_post(mbox, msg);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_apimsg(struct api_msg *apimsg)
{
@ -162,7 +162,7 @@ tcpip_apimsg(struct api_msg *apimsg)
msg->msg.apimsg = apimsg;
sys_mbox_post(mbox, msg);
}
/*-----------------------------------------------------------------------------------*/
void
tcpip_init(void (* initfunc)(void *), void *arg)
{
@ -171,7 +171,7 @@ tcpip_init(void (* initfunc)(void *), void *arg)
mbox = sys_mbox_new();
sys_thread_new(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
}
/*-----------------------------------------------------------------------------------*/

View File

@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@ -47,7 +47,7 @@
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
static u16_t
lwip_chksum(void *dataptr, int len)
{
@ -75,12 +75,12 @@ lwip_chksum(void *dataptr, int len)
return (u16_t)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,
@ -124,13 +124,13 @@ inet_chksum_pseudo(struct pbuf *p,
LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%lx\n", acc));
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* 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)
{
@ -142,7 +142,7 @@ inet_chksum(void *dataptr, u16_t len)
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@ -169,7 +169,17 @@ inet_chksum_pbuf(struct pbuf *p)
return ~(acc & 0xffffUL);
}
/*-----------------------------------------------------------------------------------*/
/* Here for now until needed in other places in lwIP */
#ifndef isascii
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
#define isascii(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.
@ -318,24 +328,24 @@ u8_t *inet_ntoa(u32_t addr)
return str;
}
/*-----------------------------------------------------------------------------------*/
#ifndef BYTE_ORDER
#error BYTE_ORDER is not defined
#endif
#if 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)
{
@ -344,11 +354,11 @@ htonl(u32_t n)
((n & 0xff0000) >> 8) |
((n & 0xff000000) >> 24);
}
/*-----------------------------------------------------------------------------------*/
u32_t
ntohl(u32_t n)
{
return htonl(n);
}
/*-----------------------------------------------------------------------------------*/
#endif /* BYTE_ORDER == LITTLE_ENDIAN */

View File

@ -30,14 +30,14 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* inet6.c
*
* Functions common to all TCP/IP modules, such as the Internet checksum and the
* byte order functions.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@ -45,7 +45,7 @@
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
/* chksum:
*
* Sums up all 16 bit words in a memory portion. Also includes any odd byte.
@ -54,7 +54,7 @@
* 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)
{
@ -74,12 +74,12 @@ chksum(void *dataptr, u16_t len)
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,
@ -122,13 +122,13 @@ inet_chksum_pseudo(struct pbuf *p,
}
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)
{
@ -139,7 +139,7 @@ inet_chksum(void *dataptr, u16_t len)
sum += (sum >> 16);
return ~(sum & 0xffff);
}
/*-----------------------------------------------------------------------------------*/
u16_t
inet_chksum_pbuf(struct pbuf *p)
{
@ -165,4 +165,4 @@ inet_chksum_pbuf(struct pbuf *p)
}
return ~(acc & 0xffff);
}
/*-----------------------------------------------------------------------------------*/

View File

@ -43,7 +43,7 @@
#include "lwip/stats.h"
#include "lwip/snmp.h"
/*-----------------------------------------------------------------------------------*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
@ -54,9 +54,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
struct ip_addr tmpaddr;
u16_t hlen;
#ifdef ICMP_STATS
++lwip_stats.icmp.recv;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.recv);
snmp_inc_icmpinmsgs();
@ -65,9 +63,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
}
@ -79,9 +75,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (ip_addr_isbroadcast(&iphdr->dest, &inp->netmask) ||
ip_addr_ismulticast(&iphdr->dest)) {
LWIP_DEBUGF(ICMP_DEBUG, ("Smurf.\n"));
#ifdef ICMP_STATS
++lwip_stats.icmp.err;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.err);
pbuf_free(p);
return;
}
@ -90,9 +84,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (p->tot_len < sizeof(struct icmp_echo_hdr)) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.lenerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.lenerr);
snmp_inc_icmpinerrors();
return;
@ -101,9 +93,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
#ifdef ICMP_STATS
++lwip_stats.icmp.chkerr;
#endif /* ICMP_STATS */
ICMP_STATS_INC(icmp.chkerr);
snmp_inc_icmpinerrors();
return;
}
@ -117,28 +107,24 @@ icmp_input(struct pbuf *p, struct netif *inp)
} else {
iecho->chksum += htons(ICMP_ECHO << 8);
}
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
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), IP_PROTO_ICMP, inp);
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 %d code %d not supported.\n", (int)type, (int)code));
#ifdef ICMP_STATS
++lwip_stats.icmp.proterr;
++lwip_stats.icmp.drop;
#endif /* ICMP_STATS */
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)
{
@ -160,19 +146,17 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
/* calculate checksum */
idur->chksum = 0;
idur->chksum = inet_chksum(idur, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
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, IP_PROTO_ICMP);
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
/*-----------------------------------------------------------------------------------*/
#if IP_FORWARD
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
@ -184,13 +168,11 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);
iphdr = p->payload;
#if ICMP_DEBUG
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"));
#endif /* ICMP_DEBNUG */
tehdr = q->payload;
ICMPH_TYPE_SET(tehdr, ICMP_TE);
@ -202,19 +184,17 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
/* calculate checksum */
tehdr->chksum = 0;
tehdr->chksum = inet_chksum(tehdr, q->len);
#ifdef ICMP_STATS
++lwip_stats.icmp.xmit;
#endif /* ICMP_STATS */
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, IP_PROTO_ICMP);
ICMP_TTL, 0, IP_PROTO_ICMP);
pbuf_free(q);
}
#endif /* IP_FORWARDING > 0 */
#endif /* IP_FORWARD */

View File

@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@ -49,6 +49,7 @@
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/icmp.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@ -61,23 +62,23 @@
# include "lwip/dhcp.h"
#endif /* LWIP_DHCP */
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* ip_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
ip_lookup(void *header, struct netif *inp)
@ -106,11 +107,12 @@ ip_lookup(void *header, struct netif *inp)
#endif /* IP_OPTIONS == 0 */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
#if LWIP_UDP
case IP_PROTO_UDP:
case IP_PROTO_UDPLITE:
return udp_lookup(iphdr, inp);
#endif /* LWIP_UDP */
#if LWIP_TCP > 0
#if LWIP_TCP
case IP_PROTO_TCP:
return 1;
#endif /* LWIP_TCP */
@ -121,7 +123,7 @@ ip_lookup(void *header, struct netif *inp)
}
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
* Finds the appropriate network interface for a given IP address. It
@ -129,7 +131,7 @@ ip_lookup(void *header, struct netif *inp)
* 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)
{
@ -147,14 +149,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
#if IP_FORWARD
/*-----------------------------------------------------------------------------------*/
/* 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 void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
{
@ -199,10 +201,8 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
LWIP_DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
iphdr->dest.addr));
#ifdef IP_STATS
++lwip_stats.ip.fw;
++lwip_stats.ip.xmit;
#endif /* IP_STATS */
IP_STATS_INC(ip.fw);
IP_STATS_INC(ip.xmit);
snmp_inc_ipforwdatagrams();
PERF_STOP("ip_forward");
@ -210,7 +210,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
#endif /* IP_FORWARD */
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when
@ -221,30 +221,24 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_input(struct pbuf *p, struct netif *inp) {
static struct ip_hdr *iphdr;
static struct netif *netif;
static u16_t iphdrlen;
#ifdef IP_STATS
++lwip_stats.ip.recv;
#endif /* IP_STATS */
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 %u\n", IPH_V(iphdr)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.err;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@ -259,10 +253,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
iphdrlen, p->len));
/* free (drop) packet pbufs */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.lenerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.lenerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
@ -271,14 +263,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
if (inet_chksum(iphdr, iphdrlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
pbuf_free(p);
#ifdef IP_STATS
++lwip_stats.ip.chkerr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipindiscards();
return ERR_OK;
}
@ -363,10 +351,8 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_free(p);
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
ntohs(IPH_OFFSET(iphdr))));
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
@ -376,30 +362,31 @@ ip_input(struct pbuf *p, struct netif *inp) {
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);
#ifdef IP_STATS
++lwip_stats.ip.opterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.opterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
return ERR_OK;
}
#endif /* IP_OPTIONS == 0 */
/* send to upper layers */
#if IP_DEBUG
LWIP_DEBUGF(IP_DEBUG, ("ip_input: \n"));
ip_debug_print(p);
LWIP_DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
#endif /* IP_DEBUG */
#if LWIP_RAW
if (!raw_input(p, inp)) {
#endif /* LWIP_RAW */
switch (IPH_PROTO(iphdr)) {
#if LWIP_UDP > 0
#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 > 0
#if LWIP_TCP
case IP_PROTO_TCP:
snmp_inc_ipindelivers();
tcp_input(p, inp);
@ -420,17 +407,18 @@ ip_input(struct pbuf *p, struct netif *inp) {
LWIP_DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
#ifdef IP_STATS
++lwip_stats.ip.proterr;
++lwip_stats.ip.drop;
#endif /* IP_STATS */
IP_STATS_INC(ip.proterr);
IP_STATS_INC(ip.drop);
snmp_inc_ipunknownprotos();
}
#if LWIP_RAW
} /* LWIP_RAW */
#endif
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* Sends an IP packet on a network interface. This function constructs
@ -438,10 +426,10 @@ ip_input(struct pbuf *p, struct netif *inp) {
* IP address is NULL, the IP address of the outgoing network
* interface is filled in as source address.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
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)
{
static struct ip_hdr *iphdr;
@ -453,9 +441,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
if (pbuf_header(p, IP_HLEN)) {
LWIP_DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
#ifdef IP_STATS
++lwip_stats.ip.err;
#endif /* IP_STATS */
IP_STATS_INC(ip.err);
snmp_inc_ipoutdiscards();
return ERR_BUF;
}
@ -467,7 +453,7 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
ip_addr_set(&(iphdr->dest), dest);
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
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));
@ -492,44 +478,39 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_frag(p,netif,dest);
#endif
#ifdef IP_STATS
lwip_stats.ip.xmit++;
#endif /* IP_STATS */
IP_STATS_INC(ip.xmit);
LWIP_DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
#if IP_DEBUG
ip_debug_print(p);
#endif /* IP_DEBUG */
LWIP_DEBUGF(IP_DEBUG, ("netif->output()"));
return netif->output(netif, p, dest);
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
* 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 proto)
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%lx\n", dest->addr));
#ifdef IP_STATS
++lwip_stats.ip.rterr;
#endif /* IP_STATS */
IP_STATS_INC(ip.rterr);
snmp_inc_ipoutdiscards();
return ERR_RTE;
}
return ip_output_if (p, src, dest, ttl, proto, netif);
return ip_output_if(p, src, dest, ttl, tos, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@ -573,7 +554,7 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@ -31,13 +31,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* ip_frag.c
*
* This is the code for IP segmentation and reassembly
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/sys.h"
@ -109,9 +109,7 @@ ip_reass(struct pbuf *p)
u16_t offset, len;
u16_t i;
#ifdef IP_STATS
++lwip_stats.ip_frag.recv;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.recv);
iphdr = (struct ip_hdr *) ip_reassbuf;
fraghdr = (struct ip_hdr *) p->payload;
@ -135,9 +133,7 @@ ip_reass(struct pbuf *p)
ip_addr_cmp(&iphdr->dest, &fraghdr->dest) &&
IPH_ID(iphdr) == IPH_ID(fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching old packet\n"));
#ifdef IP_STATS
++lwip_stats.ip_frag.cachehit;
#endif /* IP_STATS */
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;
@ -255,13 +251,9 @@ ip_reass(struct pbuf *p)
q->len > ip_reasslen - i ? ip_reasslen - i : q->len);
i += q->len;
}
#ifdef IP_STATS
++lwip_stats.ip_frag.fw;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.fw);
} else {
#ifdef IP_STATS
++lwip_stats.ip_frag.memerr;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.memerr);
}
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: p %p\n", (void*)p));
return p;
@ -269,9 +261,7 @@ ip_reass(struct pbuf *p)
}
nullreturn:
#ifdef IP_STATS
++lwip_stats.ip_frag.drop;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
}
@ -347,9 +337,7 @@ ip_frag(struct pbuf *p, struct netif *netif, struct ip_addr *dest)
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);
pbuf_chain(header, rambuf);
netif->output(netif, header, dest);
#ifdef IP_STATS
++lwip_stats.ip_frag.xmit;
#endif /* IP_STATS */
IPFRAG_STATS_INC(ip_frag.xmit);
pbuf_free(header);
left -= cop;

View File

@ -42,7 +42,7 @@
#include "lwip/stats.h"
/*-----------------------------------------------------------------------------------*/
void
icmp_input(struct pbuf *p, struct netif *inp)
{
@ -113,7 +113,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
pbuf_free(p);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
{
@ -143,7 +143,7 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
(struct ip_addr *)&(iphdr->src), ICMP_TTL, IP_PROTO_ICMP);
pbuf_free(q);
}
/*-----------------------------------------------------------------------------------*/
void
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
{

View File

@ -31,13 +31,13 @@
*/
/*-----------------------------------------------------------------------------------*/
/* ip.c
*
* This is the code for the IP layer for IPv6.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@ -53,24 +53,24 @@
#include "lwip/stats.h"
#include "arch/perf.h"
/*-----------------------------------------------------------------------------------*/
/* ip_init:
*
* Initializes the IP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_init(void)
{
}
/*-----------------------------------------------------------------------------------*/
/* ip_route:
*
* 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)
{
@ -84,14 +84,14 @@ ip_route(struct ip_addr *dest)
return netif_default;
}
/*-----------------------------------------------------------------------------------*/
/* 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 void
ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
{
@ -142,7 +142,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
}
/*-----------------------------------------------------------------------------------*/
/* ip_input:
*
* This function is called by the network interface device driver when an IP packet is
@ -152,7 +152,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr)
*
* Finally, the packet is sent to the upper layer protocol input function.
*/
/*-----------------------------------------------------------------------------------*/
void
ip_input(struct pbuf *p, struct netif *inp) {
struct ip_hdr *iphdr;
@ -249,14 +249,14 @@ ip_input(struct pbuf *p, struct netif *inp) {
PERF_STOP("ip_input");
}
/*-----------------------------------------------------------------------------------*/
/* ip_output_if:
*
* 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.
*/
/*-----------------------------------------------------------------------------------*/
err_t
ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
u8_t ttl,
@ -311,13 +311,13 @@ ip_output_if (struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
PERF_STOP("ip_output_if");
return netif->output(netif, p, dest);
}
/*-----------------------------------------------------------------------------------*/
/* ip_output:
*
* 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 proto)
@ -333,7 +333,7 @@ ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
return ip_output_if (p, src, dest, ttl, proto, netif);
}
/*-----------------------------------------------------------------------------------*/
#if IP_DEBUG
void
ip_debug_print(struct pbuf *p)
@ -383,4 +383,4 @@ ip_debug_print(struct pbuf *p)
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@ -33,7 +33,7 @@
#include "lwip/ip_addr.h"
#include "lwip/inet.h"
/*-----------------------------------------------------------------------------------*/
int
ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
struct ip_addr *mask)
@ -44,7 +44,7 @@ ip_addr_maskcmp(struct ip_addr *addr1, struct ip_addr *addr2,
(addr1->addr[3] & mask->addr[3]) == (addr2->addr[3] & mask->addr[3]));
}
/*-----------------------------------------------------------------------------------*/
int
ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
{
@ -53,7 +53,7 @@ ip_addr_cmp(struct ip_addr *addr1, struct ip_addr *addr2)
addr1->addr[2] == addr2->addr[2] &&
addr1->addr[3] == addr2->addr[3]);
}
/*-----------------------------------------------------------------------------------*/
void
ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
{
@ -63,7 +63,7 @@ ip_addr_set(struct ip_addr *dest, struct ip_addr *src)
dest->addr[2] = src->addr[2];
dest->addr[3] = src->addr[3];*/
}
/*-----------------------------------------------------------------------------------*/
int
ip_addr_isany(struct ip_addr *addr)
{
@ -71,7 +71,7 @@ ip_addr_isany(struct ip_addr *addr)
return((addr->addr[0] | addr->addr[1] | addr->addr[2] | addr->addr[3]) == 0);
}
/*-----------------------------------------------------------------------------------*/
/*#if IP_DEBUG*/
void
ip_addr_debug_print(struct ip_addr *addr)
@ -87,4 +87,4 @@ ip_addr_debug_print(struct ip_addr *addr)
ntohl(addr->addr[3]) & 0xffff);
}
/*#endif*/ /* IP_DEBUG */
/*-----------------------------------------------------------------------------------*/

View File

@ -127,7 +127,7 @@ mem_init(void)
lfree = (struct mem *)ram;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.avail = MEM_SIZE;
#endif /* MEM_STATS */
}
@ -148,7 +148,7 @@ mem_free(void *rmem)
if ((u8_t *)rmem < (u8_t *)ram || (u8_t *)rmem >= (u8_t *)ram_end) {
LWIP_DEBUGF(MEM_DEBUG | 3, ("mem_free: illegal memory\n"));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);
@ -164,7 +164,7 @@ mem_free(void *rmem)
lfree = mem;
}
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= mem->next - ((u8_t *)mem - ram);
#endif /* MEM_STATS */
@ -183,7 +183,7 @@ mem_reallocm(void *rmem, mem_size_t newsize)
mem_free(rmem);
return nmem;
}
/*-----------------------------------------------------------------------------------*/
void *
mem_realloc(void *rmem, mem_size_t newsize)
{
@ -215,7 +215,7 @@ mem_realloc(void *rmem, mem_size_t newsize)
ptr = (u8_t *)mem - ram;
size = mem->next - ptr - SIZEOF_STRUCT_MEM;
#ifdef MEM_STATS
#if MEM_STATS
lwip_stats.mem.used -= (size - newsize);
#endif /* MEM_STATS */
@ -273,7 +273,7 @@ mem_malloc(mem_size_t size)
mem2->used = 0;
mem->used = 1;
#ifdef MEM_STATS
#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;
@ -299,7 +299,7 @@ mem_malloc(mem_size_t size)
}
}
LWIP_DEBUGF(MEM_DEBUG | 2, ("mem_malloc: could not allocate %d bytes\n", (int)size));
#ifdef MEM_STATS
#if MEM_STATS
++lwip_stats.mem.err;
#endif /* MEM_STATS */
sys_sem_signal(mem_sem);

View File

@ -36,6 +36,7 @@
#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"
@ -54,6 +55,7 @@ static struct memp *memp_tab[MEMP_MAX];
static const u16_t memp_sizes[MEMP_MAX] = {
sizeof(struct pbuf),
sizeof(struct raw_pcb),
sizeof(struct udp_pcb),
sizeof(struct tcp_pcb),
sizeof(struct tcp_pcb_listen),
@ -67,6 +69,7 @@ static const u16_t memp_sizes[MEMP_MAX] = {
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,
@ -81,6 +84,9 @@ static const u16_t memp_num[MEMP_MAX] = {
static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct pbuf) +
sizeof(struct memp)) +
MEMP_NUM_RAW_PCB *
MEM_ALIGN_SIZE(sizeof(struct raw_pcb) +
sizeof(struct memp)) +
MEMP_NUM_UDP_PCB *
MEM_ALIGN_SIZE(sizeof(struct udp_pcb) +
sizeof(struct memp)) +
@ -109,12 +115,12 @@ static u8_t memp_memory[(MEMP_NUM_PBUF *
MEM_ALIGN_SIZE(sizeof(struct sys_timeout) +
sizeof(struct memp)))];
/*-----------------------------------------------------------------------------------*/
#if !SYS_LIGHTWEIGHT_PROT
static sys_sem_t mutex;
#endif
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
#ifndef LWIP_NOASSERT
static int
memp_sanity(void)
{
@ -135,7 +141,7 @@ memp_sanity(void)
return 1;
}
#endif /* LWIP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
memp_init(void)
{
@ -143,7 +149,7 @@ memp_init(void)
u16_t i, j;
u16_t size;
#ifdef MEMP_STATS
#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;
@ -176,19 +182,19 @@ memp_init(void)
}
/*-----------------------------------------------------------------------------------*/
void *
memp_malloc(memp_t type)
{
struct memp *memp;
void *mem;
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif
LWIP_ASSERT("memp_malloc: type < MEMP_MAX", type < MEMP_MAX);
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
@ -199,13 +205,13 @@ memp_malloc(memp_t type)
if (memp != NULL) {
memp_tab[type] = memp->next;
memp->next = NULL;
#ifdef MEMP_STATS
#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 */
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_UNPROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_signal(mutex);
@ -219,7 +225,7 @@ memp_malloc(memp_t type)
return mem;
} else {
LWIP_DEBUGF(MEMP_DEBUG | 2, ("memp_malloc: out of memory in pool %d\n", type));
#ifdef MEMP_STATS
#if MEMP_STATS
++lwip_stats.memp[type].err;
#endif /* MEMP_STATS */
#if SYS_LIGHTWEIGHT_PROT
@ -230,12 +236,12 @@ memp_malloc(memp_t type)
return NULL;
}
}
/*-----------------------------------------------------------------------------------*/
void
memp_free(memp_t type, void *mem)
{
struct memp *memp;
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_DECL_PROTECT(old_level);
#endif /* SYS_LIGHTWEIGHT_PROT */
@ -244,13 +250,13 @@ memp_free(memp_t type, void *mem)
}
memp = (struct memp *)((u8_t *)mem - sizeof(struct memp));
#ifdef SYS_LIGHTWEIGHT_PROT
#if SYS_LIGHTWEIGHT_PROT
SYS_ARCH_PROTECT(old_level);
#else /* SYS_LIGHTWEIGHT_PROT */
sys_sem_wait(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef MEMP_STATS
#if MEMP_STATS
lwip_stats.memp[type].used--;
#endif /* MEMP_STATS */
@ -265,4 +271,4 @@ memp_free(memp_t type, void *mem)
sys_sem_signal(mutex);
#endif /* SYS_LIGHTWEIGHT_PROT */
}
/*-----------------------------------------------------------------------------------*/

View File

@ -97,7 +97,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
/* add this netif to the list */
netif->next = netif_list;
netif_list = netif;
#if NETIF_DEBUG
LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP addr ",
netif->name[0], netif->name[1]));
ip_addr_debug_print(NETIF_DEBUG, ipaddr);
@ -106,7 +105,6 @@ netif_add(struct ip_addr *ipaddr, struct ip_addr *netmask,
LWIP_DEBUGF(NETIF_DEBUG, (" gw "));
ip_addr_debug_print(NETIF_DEBUG, gw);
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
#endif /* NETIF_DEBUG */
return netif;
}
@ -170,7 +168,7 @@ netif_find(char *name)
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)
{
@ -191,7 +189,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
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 pcb %p\n", (void *)pcb));
LWIP_DEBUGF(NETIF_DEBUG | 1, ("netif_set_ipaddr: aborting TCP pcb %p\n", (void *)pcb));
tcp_abort(pcb);
pcb = next;
} else {
@ -202,8 +200,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
/* 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
* TODO: how do we know it is _listening_? */
* is set to listen to the new one instead */
ip_addr_set(&(lpcb->local_ip), ipaddr);
}
}
@ -217,7 +214,7 @@ netif_set_ipaddr(struct netif *netif, struct ip_addr *ipaddr)
(unsigned int)(ntohl(netif->ip_addr.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->ip_addr.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_gw(struct netif *netif, struct ip_addr *gw)
{
@ -229,7 +226,7 @@ netif_set_gw(struct netif *netif, struct ip_addr *gw)
(unsigned int)(ntohl(netif->gw.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->gw.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
{
@ -241,7 +238,7 @@ netif_set_netmask(struct netif *netif, struct ip_addr *netmask)
(unsigned int)(ntohl(netif->netmask.addr) >> 8 & 0xff),
(unsigned int)(ntohl(netif->netmask.addr) & 0xff)));
}
/*-----------------------------------------------------------------------------------*/
void
netif_set_default(struct netif *netif)
{
@ -249,10 +246,10 @@ netif_set_default(struct netif *netif)
LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n",
netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\''));
}
/*-----------------------------------------------------------------------------------*/
void
netif_init(void)
{
netif_list = netif_default = NULL;
}
/*-----------------------------------------------------------------------------------*/

View File

@ -102,7 +102,7 @@ pbuf_init(void)
pbuf_pool = (struct pbuf *)&pbuf_pool_memory[0];
LWIP_ASSERT("pbuf_init: pool aligned", (long)pbuf_pool % MEM_ALIGNMENT == 0);
#ifdef PBUF_STATS
#if PBUF_STATS
lwip_stats.pbuf.avail = PBUF_POOL_SIZE;
#endif /* PBUF_STATS */
@ -113,6 +113,7 @@ pbuf_init(void)
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;
}
@ -143,7 +144,7 @@ pbuf_pool_alloc(void)
/* 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) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
return NULL;
@ -156,7 +157,7 @@ pbuf_pool_alloc(void)
pbuf_pool = p->next;
}
#if !SYS_LIGHTWEIGHT_PROT
#ifdef PBUF_STATS
#if PBUF_STATS
} else {
++lwip_stats.pbuf.alloc_locked;
#endif /* PBUF_STATS */
@ -164,7 +165,7 @@ pbuf_pool_alloc(void)
pbuf_pool_alloc_lock = 0;
#endif /* SYS_LIGHTWEIGHT_PROT */
#ifdef PBUF_STATS
#if PBUF_STATS
if (p != NULL) {
++lwip_stats.pbuf.used;
if (lwip_stats.pbuf.used > lwip_stats.pbuf.max) {
@ -243,7 +244,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
p = pbuf_pool_alloc();
LWIP_DEBUGF(PBUF_DEBUG | DBG_TRACE | 3, ("pbuf_alloc: allocated pbuf %p\n", (void *)p));
if (p == NULL) {
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
return NULL;
@ -258,8 +259,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
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 pbuf type */
p->flags = PBUF_FLAG_POOL;
/* set reference count (needed here in case we fail) */
p->ref = 1;
@ -274,7 +273,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
q = pbuf_pool_alloc();
if (q == NULL) {
LWIP_DEBUGF(PBUF_DEBUG | 2, ("pbuf_alloc: Out of pbufs in pool.\n"));
#ifdef PBUF_STATS
#if PBUF_STATS
++lwip_stats.pbuf.err;
#endif /* PBUF_STATS */
/* free chain so far allocated */
@ -289,7 +288,6 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
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->flags = PBUF_FLAG_POOL;
q->payload = (void *)((u8_t *)q + sizeof(struct pbuf));
LWIP_ASSERT("pbuf_alloc: pbuf q->payload properly aligned",
((u32_t)q->payload % MEM_ALIGNMENT) == 0);
@ -345,7 +343,7 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag)
}
#ifdef PBUF_STATS
#if PBUF_STATS
#define DEC_PBUF_STATS do { --lwip_stats.pbuf.used; } while (0)
#else /* PBUF_STATS */
#define DEC_PBUF_STATS
@ -412,7 +410,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len)
/* first, step over any pbufs that should remain in the chain */
rem_len = new_len;
q = p;
/* this pbuf should be kept? */
/* should this pbuf be kept? */
while (rem_len > q->len) {
/* decrease remaining length by pbuf length */
rem_len -= q->len;
@ -511,9 +509,9 @@ pbuf_header(struct pbuf *p, s16_t header_size)
* 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, until
* a non-zero reference count is encountered, or the end of the chain is
* reached.
* For a pbuf chain, this is repeated for each pbuf in the chain, up to the
* pbuf which has a non-zero reference count after decrementing.
* (This might be the whole chain.)
*
* @param pbuf pbuf (chain) to be freed from one user.
*
@ -619,7 +617,6 @@ pbuf_clen(struct pbuf *p)
}
/**
*
* Increment the reference count of the pbuf.
*
* @param p pbuf to increase reference counter of
@ -638,20 +635,16 @@ pbuf_ref(struct pbuf *p)
}
/**
*
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @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.
*
* Concatenate two pbufs (each may be a pbuf chain) and take over
* the reference of the tail pbuf.
*
* @note The caller MAY NOT reference the tail pbuf afterwards.
*
* @see pbuf_chain()
*/
void
pbuf_chain(struct pbuf *h, struct pbuf *t)
pbuf_cat(struct pbuf *h, struct pbuf *t)
{
struct pbuf *p;
@ -670,11 +663,31 @@ pbuf_chain(struct pbuf *h, struct pbuf *t)
LWIP_ASSERT("p->tot_len == p->len (of last pbuf in chain)", p->tot_len == p->len);
/* add total length of second chain to last pbuf total of first chain */
p->tot_len += t->tot_len;
/* chain last pbuf of h chain (p) with first of tail (t) */
/* chain last pbuf of head (p) with first of tail (t) */
p->next = t;
}
/**
* Chain two pbufs (or pbuf chains) together. They must belong to the same packet.
* It's the same as pbuf_cat with the addition that it increases the reference count
* of the tail.
*
* @param h head pbuf (chain)
* @param t tail pbuf (chain)
* @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 to one more time */
pbuf_ref(t);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_chain: %p references %p\n", (void *)p, (void *)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
@ -711,9 +724,9 @@ pbuf_queue(struct pbuf *p, struct pbuf *n)
/* proceed to next packet on queue */
p = p->next;
}
/* chain last pbuf of h chain (p) with first of tail (t) */
/* chain last pbuf of queue with n */
p->next = n;
/* t is now referenced to one more time */
/* n is now referenced to one more time */
pbuf_ref(n);
LWIP_DEBUGF(PBUF_DEBUG | DBG_FRESH | 2, ("pbuf_queue: referencing queued packet %p\n", (void *)n));
}
@ -764,7 +777,7 @@ pbuf_dequeue(struct pbuf *p)
* by pbuf_take()!
*
* @note Any replaced pbufs will be freed through pbuf_free().
* This may allocate them if they become no longer referenced.
* This may deallocate them if they become no longer referenced.
*
* @param p Head of pbuf chain to process
*
@ -889,27 +902,3 @@ pbuf_dechain(struct pbuf *p)
LWIP_ASSERT("p->tot_len == p->len", p->tot_len == p->len);
return (tail_gone > 0? NULL: q);
}
/* TODO: This function is unused in the lwIP stack and will be deprecated. This is due
* to the new way chains are built. */
#if 0
/**
*
* Increment the reference count of all pbufs in a chain.
*
* @param p first pbuf of chain
*
*/
void
pbuf_ref_chain(struct pbuf *p)
{
SYS_ARCH_DECL_PROTECT(old_level);
SYS_ARCH_PROTECT(old_level);
while (p != NULL) {
++p->ref;
p = p->next;
}
SYS_ARCH_UNPROTECT(old_level);
}
#endif

310
src/core/raw.c Normal file
View File

@ -0,0 +1,310 @@
/**
* @file
* Raw Access module
*
*/
/*
* Copyright (c) 2001-2003 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>
*
*/
/* raw.c
*
* The code for the Raw Access to the IP
*
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/memp.h"
#include "lwip/inet.h"
#include "lwip/netif.h"
#include "lwip/ip_addr.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
* and process it if possible
*
* Given an incoming IP datagram (as a chain of pbufs) this function
* finds a corresponding RAW PCB and
*
* @param pbuf pbuf to be demultiplexed to a RAW PCB.
* @param netif network interface on which the datagram was received.
* @return 0 if packet is not eated (pbuf needs to be freed then)
* or 1 if the packet has been eaten (pbuf needs not to be freed
* then)
*
*/
int
raw_input(struct pbuf *p, struct netif *inp)
{
struct raw_pcb *pcb;
struct ip_hdr *iphdr;
int proto;
int rc = 0;
iphdr = p->payload;
proto = IPH_PROTO(iphdr);
for(pcb = raw_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->protocol == proto) {
if (pcb->recv) {
if (!pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src)))
return 0;
}
pbuf_free(p);
rc = 1;
break;
}
}
return rc;
}
/**
* 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 ipaddr 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_send_to() 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_send_to()
*/
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 if a RAW packet with the pcb's protocol
* is received. If the callback function returns a value unequal 0
* the raw packet is "eaten" and not forwarded to any other raw pcb
* including lwip itself
*/
void
raw_recv(struct raw_pcb *pcb,
int (* 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 inconsitent with the receive callback where
* you actually get the IP headers), you can only specifiy 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 whole IP packet
*
*/
err_t
raw_send_to(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_send_to\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_send_to: 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_send_to: 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_send_to: No route to 0x%lx\n", ipaddr->addr));
#if RAW_STATS
/* ++lwip_stats.raw.rterr;*/
#endif /* RAW_STATS */
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 whole IP packet
*
*/
err_t
raw_send(struct raw_pcb *pcb, struct pbuf *p)
{
return raw_send_to(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 */

View File

@ -41,11 +41,11 @@
#if LWIP_STATS
struct stats_ lwip_stats;
/*-----------------------------------------------------------------------------------*/
void
stats_init(void)
{
memset(&lwip_stats, 0, sizeof(struct stats_));
}
#endif /* LWIP_STATS */
/*-----------------------------------------------------------------------------------*/

View File

@ -44,7 +44,7 @@ struct sswt_cb
};
/*-----------------------------------------------------------------------------------*/
void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
@ -96,7 +96,7 @@ sys_mbox_fetch(sys_mbox_t mbox, void **msg)
}
}
/*-----------------------------------------------------------------------------------*/
void
sys_sem_wait(sys_sem_t sem)
{
@ -152,7 +152,7 @@ sys_sem_wait(sys_sem_t sem)
}
}
/*-----------------------------------------------------------------------------------*/
void
sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{
@ -203,7 +203,7 @@ sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
/* 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)
{
@ -238,7 +238,7 @@ sys_untimeout(sys_timeout_handler h, void *arg)
/*-----------------------------------------------------------------------------------*/
static void
sswt_handler(void *arg)
{
@ -252,7 +252,7 @@ sswt_handler(void *arg)
/* 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)
{
@ -279,7 +279,7 @@ sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout)
}
/*-----------------------------------------------------------------------------------*/
void
sys_msleep(u32_t ms)
{
@ -289,6 +289,6 @@ sys_msleep(u32_t ms)
sys_sem_free(delaysem);
}
/*-----------------------------------------------------------------------------------*/
#endif /* NO_SYS */

View File

@ -36,7 +36,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp.c
*
* This file contains common functions for the TCP implementation, such as functinos
@ -44,7 +44,7 @@
* related to input and output is found in tcp_input.c and tcp_output.c respectively.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
@ -74,13 +74,13 @@ static u8_t tcp_timer;
static u16_t tcp_new_port(void);
/*-----------------------------------------------------------------------------------*/
/*
* tcp_init():
*
* Initializes the TCP layer.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_init(void)
{
@ -95,41 +95,34 @@ tcp_init(void)
tcp_timer = 0;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_tmr():
*
* Called periodically to dispatch TCP timers.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_tmr(void)
{
++tcp_timer;
if (tcp_timer == 10) {
tcp_timer = 0;
}
if (tcp_timer & 1) {
/* Call tcp_fasttmr() every 200 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_fasttmr();
}
if (tcp_timer == 0 || tcp_timer == 5) {
/* Call tcp_slowtmr() every 500 ms, i.e., every fifth timer
/* Call tcp_fasttmr() every 250 ms */
tcp_fasttmr();
if (++tcp_timer & 1) {
/* Call tcp_tmr() every 500 ms, i.e., every other timer
tcp_tmr() is called. */
tcp_slowtmr();
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_close():
*
* Closes the connection held by the PCB.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_close(struct tcp_pcb *pcb)
{
@ -183,7 +176,7 @@ tcp_close(struct tcp_pcb *pcb)
}
return err;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_abort()
*
@ -192,7 +185,7 @@ tcp_close(struct tcp_pcb *pcb)
* killed because of shortage of memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_abort(struct tcp_pcb *pcb)
{
@ -240,7 +233,7 @@ tcp_abort(struct tcp_pcb *pcb)
tcp_rst(seqno, ackno, &local_ip, &remote_ip, local_port, remote_port);
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_bind():
*
@ -249,16 +242,19 @@ tcp_abort(struct tcp_pcb *pcb)
* the outgoing network interface is used instead.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct tcp_pcb *cpcb;
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
if (port == 0) {
port = tcp_new_port();
}
#ifndef SO_REUSE
/* Check if the address already is in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs;
cpcb != NULL; cpcb = cpcb->next) {
@ -280,6 +276,102 @@ tcp_bind(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
}
}
}
#else /* SO_REUSE */
/* Search through list of PCB's in LISTEN state.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = (struct tcp_pcb *)tcp_listen_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's: SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in listening PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in a state in which they can accept or send data. Same decription as for
PCB's in state LISTEN applies to this PCB's regarding the options SOF_REUSEADDR and SOF_REUSEPORT. */
for(cpcb = tcp_active_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(cpcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(cpcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
else {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in active PCB's SO_REUSEPORT or SO_REUSEADDR set and not the same address.\n"));
}
}
}
}
/* Search through list of PCB's in TIME_WAIT state. If SO_REUSEADDR is set a bound combination [IP, port}
can be rebound. The same applies when SOF_REUSEPORT is set.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
for(cpcb = tcp_tw_pcbs; cpcb != NULL; cpcb = cpcb->next) {
if(cpcb->local_port == port) {
if(ip_addr_cmp(&(cpcb->local_ip), ipaddr)) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT or SO_REUSEADDR not set and same address.\n"));
return ERR_USE;
}
else if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: in TIME_WAIT PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (cpcb->so_options & SOF_REUSEPORT));
}
}
}
}
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
if (!ip_addr_isany(ipaddr)) {
pcb->local_ip = *ipaddr;
}
@ -298,7 +390,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
return ERR_ABRT;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_listen():
*
@ -308,7 +400,7 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
* connection to LISTEN is an irreversible process.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_listen(struct tcp_pcb *pcb)
{
@ -325,6 +417,10 @@ tcp_listen(struct tcp_pcb *pcb)
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
lpcb->state = LISTEN;
lpcb->so_options = pcb->so_options;
lpcb->so_options |= SOF_ACCEPTCONN;
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
ip_addr_set(&lpcb->local_ip, &pcb->local_ip);
memp_free(MEMP_TCP_PCB, pcb);
#if LWIP_CALLBACK_API
@ -333,7 +429,7 @@ tcp_listen(struct tcp_pcb *pcb)
TCP_REG(&tcp_listen_pcbs, lpcb);
return (struct tcp_pcb *)lpcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_recved():
*
@ -342,13 +438,14 @@ tcp_listen(struct tcp_pcb *pcb)
* when the data has been processed.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_recved(struct tcp_pcb *pcb, u16_t len)
{
pcb->rcv_wnd += len;
if (pcb->rcv_wnd > TCP_WND) {
if ((u32_t)pcb->rcv_wnd + len > TCP_WND) {
pcb->rcv_wnd = TCP_WND;
} else {
pcb->rcv_wnd += len;
}
if (!(pcb->flags & TF_ACK_DELAY) &&
!(pcb->flags & TF_ACK_NOW)) {
@ -358,14 +455,14 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: recveived %u bytes, wnd %u (%u).\n",
len, pcb->rcv_wnd, TCP_WND - pcb->rcv_wnd));
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new_port():
*
* A nastly hack featuring 'goto' statements that allocates a
* new TCP local port.
*/
/*-----------------------------------------------------------------------------------*/
static u16_t
tcp_new_port(void)
{
@ -398,7 +495,7 @@ tcp_new_port(void)
}
return port;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_connect():
*
@ -406,7 +503,7 @@ tcp_new_port(void)
* argument will be called when the connection has been established.
*
*/
/*-----------------------------------------------------------------------------------*/
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))
@ -453,7 +550,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
}
return ret;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_slowtmr():
*
@ -461,7 +558,7 @@ tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,
* removes PCBs that have been in TIME-WAIT for enough time. It also increments
* various timers such as the inactivity timer in each PCB.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_slowtmr(void)
{
@ -527,6 +624,21 @@ tcp_slowtmr(void)
}
}
/* Check if KEEPALIVE should be sent */
if((pcb->so_options & SOF_KEEPALIVE) && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + TCP_MAXIDLE) / TCP_SLOW_INTERVAL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: KEEPALIVE timeout. Aborting connection to %u.%u.%u.%u.\n",
ip4_addr1(&pcb->remote_ip), ip4_addr2(&pcb->remote_ip),
ip4_addr3(&pcb->remote_ip), ip4_addr4(&pcb->remote_ip)));
tcp_abort(pcb);
}
else if((u32_t)(tcp_ticks - pcb->tmr) > (pcb->keepalive + pcb->keep_cnt * TCP_KEEPINTVL) / TCP_SLOW_INTERVAL) {
tcp_keepalive(pcb);
pcb->keep_cnt++;
}
}
/* If this PCB has queued out of sequence data, but has been
inactive for too long, will drop the data (it will eventually
be retransmitted). */
@ -622,13 +734,13 @@ tcp_slowtmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_fasttmr():
*
* Is called every TCP_FINE_TIMEOUT (100 ms) and sends delayed ACKs.
* Is called every TCP_FAST_INTERVAL (250 ms) and sends delayed ACKs.
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_fasttmr(void)
{
@ -643,75 +755,72 @@ tcp_fasttmr(void)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_segs_free():
*
* Deallocates a list of TCP segments (tcp_seg structures).
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_segs_free(struct tcp_seg *seg)
{
u8_t count = 0;
struct tcp_seg *next;
again:
if (seg != NULL) {
while (seg != NULL) {
next = seg->next;
count += tcp_seg_free(seg);
seg = next;
goto again;
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_seg_free():
*
* Frees a TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
u8_t
tcp_seg_free(struct tcp_seg *seg)
{
u8_t count = 0;
if (seg != NULL) {
if (seg->p == NULL) {
memp_free(MEMP_TCP_SEG, seg);
} else {
if (seg->p != NULL) {
count = pbuf_free(seg->p);
#if TCP_DEBUG
seg->p = NULL;
#endif /* TCP_DEBUG */
memp_free(MEMP_TCP_SEG, seg);
}
memp_free(MEMP_TCP_SEG, seg);
}
return count;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_setprio():
*
* Sets the priority of a connection.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_setprio(struct tcp_pcb *pcb, u8_t prio)
{
pcb->prio = prio;
}
/*-----------------------------------------------------------------------------------*/
#if TCP_QUEUE_OOSEQ
/*
* tcp_seg_copy():
*
* Returns a copy of the given TCP segment.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_seg *
tcp_seg_copy(struct tcp_seg *seg)
{
@ -725,7 +834,8 @@ tcp_seg_copy(struct tcp_seg *seg)
pbuf_ref(cseg->p);
return cseg;
}
/*-----------------------------------------------------------------------------------*/
#endif
#if LWIP_CALLBACK_API
static err_t
tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
@ -739,7 +849,7 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
return ERR_OK;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_prio(u8_t prio)
{
@ -770,7 +880,7 @@ tcp_kill_prio(u8_t prio)
}
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_kill_timewait(void)
{
@ -792,8 +902,8 @@ tcp_kill_timewait(void)
}
}
/*-----------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_alloc(u8_t prio)
{
@ -817,6 +927,8 @@ tcp_alloc(u8_t prio)
pcb->snd_buf = TCP_SND_BUF;
pcb->snd_queuelen = 0;
pcb->rcv_wnd = TCP_WND;
pcb->tos = 0;
pcb->ttl = TCP_TTL;
pcb->mss = TCP_MSS;
pcb->rto = 3000 / TCP_SLOW_INTERVAL;
pcb->sa = 0;
@ -836,10 +948,14 @@ tcp_alloc(u8_t prio)
#if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */
/* Init KEEPALIVE timer */
pcb->keepalive = TCP_KEEPDEFAULT;
pcb->keep_cnt = 0;
}
return pcb;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_new():
*
@ -847,13 +963,13 @@ tcp_alloc(u8_t prio)
* any of the TCP PCB lists.
*
*/
/*-----------------------------------------------------------------------------------*/
struct tcp_pcb *
tcp_new(void)
{
return tcp_alloc(TCP_PRIO_NORMAL);
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_arg():
*
@ -861,13 +977,14 @@ tcp_new(void)
* functions.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_arg(struct tcp_pcb *pcb, void *arg)
{
pcb->callback_arg = arg;
}
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
/*
* tcp_recv():
*
@ -875,16 +992,14 @@ tcp_arg(struct tcp_pcb *pcb, void *arg)
* connection receives data.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_recv(struct tcp_pcb *pcb,
err_t (* recv)(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err))
{
pcb->recv = recv;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_sent():
*
@ -892,16 +1007,14 @@ tcp_recv(struct tcp_pcb *pcb,
* has been successfully delivered to the remote host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_sent(struct tcp_pcb *pcb,
err_t (* sent)(void *arg, struct tcp_pcb *tpcb, u16_t len))
{
pcb->sent = sent;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_err():
*
@ -909,16 +1022,31 @@ tcp_sent(struct tcp_pcb *pcb,
* has occured on the connection.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_err(struct tcp_pcb *pcb,
void (* errf)(void *arg, err_t err))
{
pcb->errf = errf;
}
/*
* tcp_accept():
*
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
*
*/
void
tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_poll():
*
@ -927,7 +1055,7 @@ tcp_err(struct tcp_pcb *pcb,
* timer interval, which is called twice a second.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_poll(struct tcp_pcb *pcb,
err_t (* poll)(void *arg, struct tcp_pcb *tpcb), u8_t interval)
@ -937,31 +1065,14 @@ tcp_poll(struct tcp_pcb *pcb,
#endif /* LWIP_CALLBACK_API */
pcb->pollinterval = interval;
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_accept():
*
* Used for specifying the function that should be called when a
* LISTENing connection has been connected to another host.
*
*/
/*-----------------------------------------------------------------------------------*/
#if LWIP_CALLBACK_API
void
tcp_accept(struct tcp_pcb *pcb,
err_t (* accept)(void *arg, struct tcp_pcb *newpcb, err_t err))
{
((struct tcp_pcb_listen *)pcb)->accept = accept;
}
#endif /* LWIP_CALLBACK_API */
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_purge():
*
* Purges a TCP PCB. Removes any buffered data and frees the buffer memory.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_purge(struct tcp_pcb *pcb)
{
@ -996,14 +1107,14 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
NULL;
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_pcb_remove():
*
* Purges the PCB and removes it from a PCB list. Any delayed ACKs are sent first.
*
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
{
@ -1022,14 +1133,14 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane());
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_next_iss():
*
* Calculates a new initial sequence number for new connections.
*
*/
/*-----------------------------------------------------------------------------------*/
u32_t
tcp_next_iss(void)
{
@ -1038,31 +1149,31 @@ tcp_next_iss(void)
iss += tcp_ticks; /* XXX */
return iss;
}
/*-----------------------------------------------------------------------------------*/
#if TCP_DEBUG || TCP_INPUT_DEBUG || TCP_OUTPUT_DEBUG
void
tcp_debug_print(struct tcp_hdr *tcphdr)
{
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %04x | %04x | (src port, dest port)\n",
tcphdr->src, tcphdr->dest));
LWIP_DEBUGF(TCP_DEBUG, ("| %5u | %5u | (src port, dest port)\n",
ntohs(tcphdr->src), ntohs(tcphdr->dest)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (seq no)\n",
tcphdr->seqno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (seq no)\n",
ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %08lu | (ack no)\n",
tcphdr->ackno));
LWIP_DEBUGF(TCP_DEBUG, ("| %010lu | (ack no)\n",
ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u| %5u | (offset, flags (",
TCPH_OFFSET(tcphdr),
TCPH_FLAGS(tcphdr) >> 4 & 1,
LWIP_DEBUGF(TCP_DEBUG, ("| %2u | |%u%u%u%u%u%u| %5u | (hdrlen, flags (",
TCPH_HDRLEN(tcphdr),
TCPH_FLAGS(tcphdr) >> 5 & 1,
TCPH_FLAGS(tcphdr) >> 4 & 1,
TCPH_FLAGS(tcphdr) >> 3 & 1,
TCPH_FLAGS(tcphdr) >> 2 & 1,
TCPH_FLAGS(tcphdr) >> 1 & 1,
TCPH_FLAGS(tcphdr) & 1,
tcphdr->wnd));
ntohs(tcphdr->wnd)));
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
@ -1070,7 +1181,7 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_state(enum tcp_state s)
{
@ -1111,7 +1222,7 @@ tcp_debug_print_state(enum tcp_state s)
break;
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_flags(u8_t flags)
{
@ -1133,8 +1244,14 @@ tcp_debug_print_flags(u8_t flags)
if (flags & TCP_URG) {
LWIP_DEBUGF(TCP_DEBUG, ("URG "));
}
if (flags & TCP_ECE) {
LWIP_DEBUGF(TCP_DEBUG, ("ECE "));
}
if (flags & TCP_CWR) {
LWIP_DEBUGF(TCP_DEBUG, ("CWR "));
}
}
/*-----------------------------------------------------------------------------------*/
void
tcp_debug_print_pcbs(void)
{
@ -1161,7 +1278,7 @@ tcp_debug_print_pcbs(void)
tcp_debug_print_state(pcb->state);
}
}
/*-----------------------------------------------------------------------------------*/
int
tcp_pcbs_sane(void)
{
@ -1178,7 +1295,7 @@ tcp_pcbs_sane(void)
}
#endif /* TCP_DEBUG */
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@ -36,7 +36,7 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_input.c
*
* The input processing functions of TCP.
@ -45,7 +45,7 @@
* tcp_process() -> tcp_receive() (-> application).
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
@ -85,7 +85,7 @@ static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
static err_t tcp_timewait_input(struct tcp_pcb *pcb);
/*-----------------------------------------------------------------------------------*/
/* tcp_input:
*
* The initial input processing of TCP. It verifies the TCP header, demultiplexes
@ -93,34 +93,38 @@ static err_t tcp_timewait_input(struct tcp_pcb *pcb);
* the TCP finite state machine. This function is called by the IP layer (in
* ip_input()).
*/
/*-----------------------------------------------------------------------------------*/
void
tcp_input(struct pbuf *p, struct netif *inp)
{
struct tcp_pcb *pcb, *prev;
struct tcp_pcb_listen *lpcb;
u8_t offset;
u8_t hdrlen;
err_t err;
#ifdef SO_REUSE
struct tcp_pcb *pcb_temp;
int reuse = 0;
int reuse_port = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef TCP_STATS
++lwip_stats.tcp.recv;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.recv);
iphdr = p->payload;
tcphdr = (struct tcp_hdr *)((u8_t *)p->payload + IPH_HL(iphdr) * 4);
#if TCP_INPUT_DEBUG
tcp_debug_print(tcphdr);
#endif
/* remove header from payload */
if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) {
/* drop short packets */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%u bytes) discarded\n", p->tot_len));
#ifdef TCP_STATS
++lwip_stats.tcp.lenerr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.lenerr);
TCP_STATS_INC(tcp.drop);
pbuf_free(p);
return;
}
@ -142,10 +146,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
#if TCP_DEBUG
tcp_debug_print(tcphdr);
#endif /* TCP_DEBUG */
#ifdef TCP_STATS
++lwip_stats.tcp.chkerr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.chkerr);
TCP_STATS_INC(tcp.drop);
pbuf_free(p);
return;
@ -154,8 +156,8 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Move the payload pointer in the pbuf so that it points to the
TCP data instead of the TCP header. */
offset = TCPH_OFFSET(tcphdr) >> 4;
pbuf_header(p, -(offset * 4));
hdrlen = TCPH_HDRLEN(tcphdr);
pbuf_header(p, -(hdrlen * 4));
/* Convert fields in TCP header to host byte order. */
tcphdr->src = ntohs(tcphdr->src);
@ -170,7 +172,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Demultiplex an incoming segment. First, we check if it is destined
for an active connection. */
prev = NULL;
#ifdef SO_REUSE
pcb_temp = tcp_active_pcbs;
again_1:
/* Iterate through the TCP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED);
LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT);
LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN);
@ -179,6 +191,32 @@ tcp_input(struct pbuf *p, struct netif *inp)
ip_addr_cmp(&(pcb->remote_ip), &(iphdr->src)) &&
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest))) {
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(TCP_INPUT_DEBUG,("tcp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port = 1;
p->ref++;
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
/* Move this PCB to the front of the list so that subsequent
lookups will be faster (we exploit locality in TCP segment
arrivals). */
@ -323,33 +361,50 @@ tcp_input(struct pbuf *p, struct netif *inp)
tcp_debug_print_state(pcb->state);
#endif /* TCP_DEBUG */
#endif /* TCP_INPUT_DEBUG */
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: searching next PCB.\n"));
reuse_port = 0;
/* We are searching connected sockets */
goto again_1;
}
#endif /* SO_REUSE */
} else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
/* If no matching PCB was found, send a TCP RST (reset) to the
sender. */
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_input: no PCB match found, resetting.\n"));
if (!(TCPH_FLAGS(tcphdr) & TCP_RST)) {
#ifdef TCP_STATS
++lwip_stats.tcp.proterr;
++lwip_stats.tcp.drop;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.proterr);
TCP_STATS_INC(tcp.drop);
tcp_rst(ackno, seqno + tcplen,
&(iphdr->dest), &(iphdr->src),
tcphdr->dest, tcphdr->src);
}
pbuf_free(p);
}
#ifdef SO_REUSE
end:
#endif /* SO_REUSE */
LWIP_ASSERT("tcp_input: tcp_pcbs_sane()", tcp_pcbs_sane());
PERF_STOP("tcp_input");
}
/*-----------------------------------------------------------------------------------*/
/* tcp_listen_input():
*
* Called by tcp_input() when a segment arrives for a listening
* connection.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
@ -373,9 +428,7 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
SYN at a time when we have more memory available. */
if (npcb == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_listen_input: could not allocate PCB\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
return ERR_MEM;
}
/* Set up the new PCB. */
@ -387,12 +440,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->rcv_nxt = seqno + 1;
npcb->snd_wnd = tcphdr->wnd;
npcb->ssthresh = npcb->snd_wnd;
npcb->snd_wl1 = seqno;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API
npcb->accept = pcb->accept;
#endif /* LWIP_CALLBACK_API */
/* inherit socket options */
npcb->so_options = pcb->so_options & (SOF_DEBUG|SOF_DONTROUTE|SOF_KEEPALIVE|SOF_OOBINLINE|SOF_LINGER);
/* Register the new PCB so that we can begin receiving segments
for it. */
TCP_REG(&tcp_active_pcbs, npcb);
@ -411,13 +465,13 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* tcp_timewait_input():
*
* Called by tcp_input() when a segment arrives for a connection in
* TIME_WAIT.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_timewait_input(struct tcp_pcb *pcb)
{
@ -429,7 +483,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
}
return tcp_output(pcb);
}
/*-----------------------------------------------------------------------------------*/
/* tcp_process
*
* Implements the TCP state machine. Called by tcp_input. In some
@ -437,7 +491,7 @@ tcp_timewait_input(struct tcp_pcb *pcb)
* argument will be freed by the caller (tcp_input()) unless the
* recv_data pointer in the pcb is set.
*/
/*-----------------------------------------------------------------------------------*/
static err_t
tcp_process(struct tcp_pcb *pcb)
{
@ -479,6 +533,7 @@ tcp_process(struct tcp_pcb *pcb)
/* Update the PCB (in)activity timer. */
pcb->tmr = tcp_ticks;
pcb->keep_cnt = 0;
/* Do different things depending on the TCP state. */
switch (pcb->state) {
@ -489,7 +544,8 @@ tcp_process(struct tcp_pcb *pcb)
ackno == ntohl(pcb->unacked->tcphdr->seqno) + 1) {
pcb->rcv_nxt = seqno + 1;
pcb->lastack = ackno;
pcb->snd_wnd = pcb->snd_wl1 = tcphdr->wnd;
pcb->snd_wnd = tcphdr->wnd;
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
pcb->state = ESTABLISHED;
pcb->cwnd = pcb->mss;
--pcb->snd_queuelen;
@ -594,7 +650,7 @@ tcp_process(struct tcp_pcb *pcb)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/* tcp_receive:
*
* Called by tcp_process. Checks if the given segment is an ACK for outstanding
@ -606,7 +662,7 @@ tcp_process(struct tcp_pcb *pcb)
* If the incoming segment constitutes an ACK for a segment that was used for RTT
* estimation, the RTT is estimated here as well.
*/
/*-----------------------------------------------------------------------------------*/
static void
tcp_receive(struct tcp_pcb *pcb)
{
@ -934,7 +990,7 @@ tcp_receive(struct tcp_pcb *pcb)
inseg.p = NULL;
}
if (TCPH_FLAGS(inseg.tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN."));
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: received FIN.\n"));
recv_flags = TF_GOT_FIN;
}
@ -957,15 +1013,14 @@ tcp_receive(struct tcp_pcb *pcb)
/* Chain this pbuf onto the pbuf that we will pass to
the application. */
if (recv_data) {
pbuf_chain(recv_data, cseg->p);
pbuf_free(cseg->p);
pbuf_cat(recv_data, cseg->p);
} else {
recv_data = cseg->p;
}
cseg->p = NULL;
}
if (flags & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN."));
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
}
@ -1103,7 +1158,7 @@ tcp_receive(struct tcp_pcb *pcb)
}
}
}
/*-----------------------------------------------------------------------------------*/
/*
* tcp_parseopt:
*
@ -1111,7 +1166,7 @@ tcp_receive(struct tcp_pcb *pcb)
* from uIP with only small changes.)
*
*/
/*-----------------------------------------------------------------------------------*/
static void
tcp_parseopt(struct tcp_pcb *pcb)
{
@ -1122,8 +1177,8 @@ tcp_parseopt(struct tcp_pcb *pcb)
opts = (u8_t *)tcphdr + TCP_HLEN;
/* Parse the TCP MSS option, if present. */
if ((TCPH_OFFSET(tcphdr) & 0xf0) > 0x50) {
for(c = 0; c < ((TCPH_OFFSET(tcphdr) >> 4) - 5) << 2 ;) {
if(TCPH_HDRLEN(tcphdr) > 0x5) {
for(c = 0; c < (TCPH_HDRLEN(tcphdr) - 5) << 2 ;) {
opt = opts[c];
if (opt == 0x00) {
/* End of options. */
@ -1153,5 +1208,5 @@ tcp_parseopt(struct tcp_pcb *pcb)
}
}
#endif /* LWIP_TCP */
/*-----------------------------------------------------------------------------------*/

View File

@ -35,13 +35,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* tcp_output.c
*
* The output functions of TCP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/def.h"
@ -64,14 +64,14 @@
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)
{
return tcp_enqueue(pcb, NULL, 0, flags, 1, NULL, 0);
}
/*-----------------------------------------------------------------------------------*/
err_t
tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
{
@ -90,7 +90,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t copy)
return ERR_CONN;
}
}
/*-----------------------------------------------------------------------------------*/
err_t
tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
u8_t flags, u8_t copy,
@ -154,12 +154,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
seg->p = NULL;
if (queue == NULL) {
queue = seg;
useg = queue = seg;
}
else {
/* Attach the segment to the end of the queued segments. */
for (useg = queue; useg->next != NULL; useg = useg->next);
useg->next = seg;
useg = seg;
}
/* If copy is set, memory should be allocated
@ -210,9 +210,8 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
}
++queuelen;
/* Chain the headers and data pbufs together. */
pbuf_chain(seg->p, p);
pbuf_free(p);
/* Concatenate the headers and data pbufs together. */
pbuf_cat(seg->p, p);
p = NULL;
}
@ -234,9 +233,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: no room for TCP header in pbuf.\n"));
#ifdef TCP_STATS
++lwip_stats.tcp.err;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.err);
goto memerr;
}
seg->tcphdr = seg->p->payload;
@ -249,10 +246,10 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* Copy the options into the header, if they are present. */
if (optdata == NULL) {
TCPH_OFFSET_SET(seg->tcphdr, 5 << 4);
TCPH_HDRLEN_SET(seg->tcphdr, 5);
}
else {
TCPH_OFFSET_SET(seg->tcphdr, (5 + optlen / 4) << 4);
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. */
@ -288,11 +285,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
useg->len + queue->len <= pcb->mss) {
/* Remove TCP header from first segment. */
pbuf_header(queue->p, -TCP_HLEN);
pbuf_chain(useg->p, queue->p);
/* Free buffer which was merged. Note that the previous pbuf_chain call
* will have incremented the ref count, so here the ref count will still
* be 1 for the 1 pointer still being used on this buffer. */
pbuf_free(queue->p);
pbuf_cat(useg->p, queue->p);
useg->len += queue->len;
useg->next = queue->next;
@ -327,14 +320,12 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
/* 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_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_PSH);
TCPH_SET_FLAG(seg->tcphdr, TCP_PSH);
}
return ERR_OK;
memerr:
#ifdef TCP_STATS
++lwip_stats.tcp.memerr;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.memerr);
if (queue != NULL) {
tcp_segs_free(queue);
@ -347,7 +338,7 @@ tcp_enqueue(struct tcp_pcb *pcb, void *arg, u16_t len,
LWIP_DEBUGF(TCP_QLEN_DEBUG | DBG_STATE, ("tcp_enqueue: %d (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)
@ -373,6 +364,13 @@ tcp_output(struct tcp_pcb *pcb)
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, we check if there is data that is
to be sent. If data is to be sent out, we'll just piggyback our
acknowledgement with the outgoing segment. If no data will be
@ -398,13 +396,14 @@ tcp_output(struct tcp_pcb *pcb)
TCPH_FLAGS_SET(tcphdr, TCP_ACK);
tcphdr->wnd = htons(pcb->rcv_wnd);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, &(pcb->local_ip), &(pcb->remote_ip),
IP_PROTO_TCP, p->tot_len);
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
ip_output(p, &(pcb->local_ip), &(pcb->remote_ip), pcb->ttl, pcb->tos,
IP_PROTO_TCP);
pbuf_free(p);
@ -443,7 +442,7 @@ tcp_output(struct tcp_pcb *pcb)
pcb->unsent = seg->next;
if (pcb->state != SYN_SENT) {
TCPH_FLAGS_SET(seg->tcphdr, TCPH_FLAGS(seg->tcphdr) | TCP_ACK);
TCPH_SET_FLAG(seg->tcphdr, TCP_ACK);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
@ -457,11 +456,10 @@ tcp_output(struct tcp_pcb *pcb)
seg->next = NULL;
if (pcb->unacked == NULL) {
pcb->unacked = seg;
useg = seg;
} else {
for (useg = pcb->unacked; useg->next != NULL; useg = useg->next);
useg->next = seg;
useg = useg->next;
}
} else {
tcp_seg_free(seg);
@ -470,7 +468,7 @@ tcp_output(struct tcp_pcb *pcb)
}
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static void
tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
{
@ -523,14 +521,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
&(pcb->local_ip),
&(pcb->remote_ip),
IP_PROTO_TCP, seg->p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
TCP_STATS_INC(tcp.xmit);
ip_output(seg->p, &(pcb->local_ip), &(pcb->remote_ip), TCP_TTL,
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,
@ -552,20 +548,19 @@ tcp_rst(u32_t seqno, u32_t ackno,
TCPH_FLAGS_SET(tcphdr, TCP_RST | TCP_ACK);
tcphdr->wnd = htons(TCP_WND);
tcphdr->urgp = 0;
TCPH_OFFSET_SET(tcphdr, 5 << 4);
TCPH_HDRLEN_SET(tcphdr, 5);
tcphdr->chksum = 0;
tcphdr->chksum = inet_chksum_pseudo(p, local_ip, remote_ip,
IP_PROTO_TCP, p->tot_len);
#ifdef TCP_STATS
++lwip_stats.tcp.xmit;
#endif /* TCP_STATS */
ip_output(p, local_ip, remote_ip, TCP_TTL, IP_PROTO_TCP);
TCP_STATS_INC(tcp.xmit);
/* 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 %lu ackno %lu.\n", seqno, ackno));
}
/*-----------------------------------------------------------------------------------*/
void
tcp_rexmit(struct tcp_pcb *pcb)
{
@ -595,6 +590,48 @@ tcp_rexmit(struct tcp_pcb *pcb)
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 %u.%u.%u.%u\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 %ld pcb->tmr %ld pcb->keep_cnt %ld\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;
tcphdr->chksum = inet_chksum_pseudo(p, &pcb->local_ip, &pcb->remote_ip, IP_PROTO_TCP, p->tot_len);
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 %lu ackno %lu.\n", pcb->snd_nxt - 1, pcb->rcv_nxt));
}
#endif /* LWIP_TCP */

View File

@ -35,13 +35,13 @@
*
*/
/*-----------------------------------------------------------------------------------*/
/* udp.c
*
* The code for the User Datagram Protocol UDP.
*
*/
/*-----------------------------------------------------------------------------------*/
#include "lwip/opt.h"
#include "lwip/def.h"
@ -64,24 +64,20 @@ struct udp_pcb *udp_pcbs = NULL;
static struct udp_pcb *pcb_cache = NULL;
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
void
udp_init(void)
{
udp_pcbs = pcb_cache = NULL;
}
/*-----------------------------------------------------------------------------------*/
/* udp_lookup:
*
* An experimental feature that will be changed in future versions. Do
* not depend on it yet...
*/
/*-----------------------------------------------------------------------------------*/
#ifdef LWIP_DEBUG
u8_t
udp_lookup(struct ip_hdr *iphdr, struct netif *inp)
@ -163,21 +159,24 @@ udp_input(struct pbuf *p, struct netif *inp)
struct ip_hdr *iphdr;
u16_t src, dest;
#ifdef SO_REUSE
struct udp_pcb *pcb_temp;
int reuse = 0;
int reuse_port_1 = 0;
int reuse_port_2 = 0;
#endif /* SO_REUSE */
PERF_START;
#ifdef UDP_STATS
++lwip_stats.udp.recv;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.recv);
iphdr = p->payload;
if (pbuf_header(p, -((s16_t)(UDP_HLEN + IPH_HL(iphdr) * 4)))) {
/* drop short packets */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: short UDP datagram (%u bytes) discarded\n", p->tot_len));
#ifdef UDP_STATS
++lwip_stats.udp.lenerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.lenerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@ -190,9 +189,7 @@ udp_input(struct pbuf *p, struct netif *inp)
src = ntohs(udphdr->src);
dest = ntohs(udphdr->dest);
#if UDP_DEBUG
udp_debug_print(udphdr);
#endif /* UDP_DEBUG */
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp (%u.%u.%u.%u, %u) <-- (%u.%u.%u.%u, %u)\n",
@ -200,8 +197,18 @@ udp_input(struct pbuf *p, struct netif *inp)
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)));
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_1:
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
/* Iterate through the UDP pcb list for a fully matching pcb */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
/* print the PCB local and remote address */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
@ -221,6 +228,27 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* PCB local IP address matches UDP destination IP address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_1 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
@ -228,7 +256,16 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb == NULL) {
/* Iterate through the UDP PCB list for a pcb that matches
the local address. */
#ifdef SO_REUSE
pcb_temp = udp_pcbs;
again_2:
for(pcb = pcb_temp; pcb != NULL; pcb = pcb->next) {
#else /* SO_REUSE */
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG, ("pcb (%u.%u.%u.%u, %u) --- (%u.%u.%u.%u, %u)\n",
ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip),
ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), pcb->local_port,
@ -242,7 +279,28 @@ udp_input(struct pbuf *p, struct netif *inp)
(ip_addr_isany(&pcb->local_ip) ||
/* ...matching interface address? */
ip_addr_cmp(&(pcb->local_ip), &(iphdr->dest)))) {
break;
#ifdef SO_REUSE
if(pcb->so_options & SOF_REUSEPORT) {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB and SOF_REUSEPORT set.\n"));
} else {
/* First PCB with this address */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: first PCB and SOF_REUSEPORT set.\n"));
reuse = 1;
}
reuse_port_2 = 1;
p->ref++;
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: reference counter on PBUF set to %i\n", p->ref));
} else {
if(reuse) {
/* We processed one PCB already */
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: second or later PCB but SOF_REUSEPORT not set !\n"));
}
}
#endif /* SO_REUSE */
break;
}
}
}
@ -262,10 +320,8 @@ udp_input(struct pbuf *p, struct netif *inp)
(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"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@ -277,10 +333,8 @@ udp_input(struct pbuf *p, struct netif *inp)
IP_PROTO_UDP, p->tot_len) != 0) {
LWIP_DEBUGF(UDP_DEBUG | 2, ("udp_input: UDP datagram discarded due to failing checksum\n"));
#ifdef UDP_STATS
++lwip_stats.udp.chkerr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.chkerr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpinerrors();
pbuf_free(p);
goto end;
@ -291,7 +345,33 @@ udp_input(struct pbuf *p, struct netif *inp)
if (pcb != NULL) {
snmp_inc_udpindatagrams();
pcb->recv(pcb->recv_arg, pcb, p, &(iphdr->src), src);
#ifdef SO_REUSE
/* First socket should receive now */
if(reuse_port_1 || reuse_port_2) {
/* We want to search on next socket after receiving */
pcb_temp = pcb->next;
if(reuse_port_1) {
/* We are searching connected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_1;
} else {
/* We are searching unconnected sockets */
reuse_port_1 = 0;
reuse_port_2 = 0;
goto again_2;
}
}
#endif /* SO_REUSE */
} else {
#ifdef SO_REUSE
if(reuse) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: freeing PBUF with reference counter set to %i\n", p->ref));
pbuf_free(p);
goto end;
}
#endif /* SO_REUSE */
LWIP_DEBUGF(UDP_DEBUG | DBG_TRACE, ("udp_input: not for us.\n"));
/* No match was found, send ICMP destination port unreachable unless
@ -304,10 +384,8 @@ udp_input(struct pbuf *p, struct netif *inp)
p->payload = iphdr;
icmp_dest_unreach(p, ICMP_DUR_PORT);
}
#ifdef UDP_STATS
++lwip_stats.udp.proterr;
++lwip_stats.udp.drop;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.proterr);
UDP_STATS_INC(udp.drop);
snmp_inc_udpnoports();
pbuf_free(p);
}
@ -380,9 +458,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG | 1, ("udp_send: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/* using IP_ANY_ADDR? */
@ -407,7 +483,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) udphdr->chksum = 0xffff;
/* output to IP */
err = ip_output_if (q, src_ip, &pcb->remote_ip, UDP_TTL, IP_PROTO_UDPLITE, netif);
err = ip_output_if (p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDPLITE, netif);
snmp_inc_udpoutdatagrams();
} else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %u\n", q->tot_len));
@ -422,7 +498,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
snmp_inc_udpoutdatagrams();
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, UDP_TTL, IP_PROTO_UDP, netif);
err = ip_output_if(p, src_ip, &pcb->remote_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
}
/* did we chain a header earlier? */
@ -431,9 +507,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
pbuf_free(q);
}
#ifdef UDP_STATS
++lwip_stats.udp.xmit;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.xmit);
return err;
}
@ -457,9 +531,13 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
u8_t rebind;
#ifdef SO_REUSE
int reuse_port_all_set = 1;
#endif /* SO_REUSE */
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 = %u)\n", port));
rebind = 0;
/* Check for double bind and rebind of the same pcb */
for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
@ -470,6 +548,8 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
/* pcb already in list, just rebind */
rebind = 1;
}
#ifndef SO_REUSE
/* 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
@ -486,8 +566,52 @@ udp_bind(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
return ERR_USE;
}
#endif
#else /* SO_REUSE */
/* Search through list of PCB's.
If there is a PCB bound to specified port and IP_ADDR_ANY another PCB can be bound to the interface IP
or to the loopback address on the same port if SOF_REUSEADDR is set. Any combination of PCB's bound to
the same local port, but to one address out of {IP_ADDR_ANY, 127.0.0.1, interface IP} at a time is valid.
But no two PCB's bound to same local port and same local address is valid.
If SOF_REUSEPORT is set several PCB's can be bound to same local port and same local address also. But then
all PCB's must have the SOF_REUSEPORT option set.
When the two options aren't set and specified port is already bound, ERR_USE is returned saying that
address is already in use. */
else if (ipcb->local_port == port) {
if(ip_addr_cmp(&(ipcb->local_ip), ipaddr)) {
if(pcb->so_options & SOF_REUSEPORT) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT set and same address.\n"));
reuse_port_all_set = (reuse_port_all_set && (ipcb->so_options & SOF_REUSEPORT));
}
else {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT not set and same address.\n"));
return ERR_USE;
}
}
else if((ip_addr_isany(ipaddr) && !ip_addr_isany(&(ipcb->local_ip))) ||
(!ip_addr_isany(ipaddr) && ip_addr_isany(&(ipcb->local_ip)))) {
if(!(pcb->so_options & SOF_REUSEADDR) && !(pcb->so_options & SOF_REUSEPORT)) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: in UDP PCB's SO_REUSEPORT or SO_REUSEADDR not set and not the same address.\n"));
return ERR_USE;
}
}
}
#endif /* SO_REUSE */
}
/* bind local address */
#ifdef SO_REUSE
/* If SOF_REUSEPORT isn't set in all PCB's bound to specified port and local address specified then
{IP, port} can't be reused. */
if(!reuse_port_all_set) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_bind: not all sockets have SO_REUSEPORT set.\n"));
return ERR_USE;
}
#endif /* SO_REUSE */
ip_addr_set(&pcb->local_ip, ipaddr);
/* no port specified? */
if (port == 0) {
@ -559,9 +683,7 @@ udp_connect(struct udp_pcb *pcb, struct ip_addr *ipaddr, u16_t port)
if ((netif = ip_route(&(pcb->remote_ip))) == NULL) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_connect: No route to 0x%lx\n", pcb->remote_ip.addr));
#ifdef UDP_STATS
++lwip_stats.udp.rterr;
#endif /* UDP_STATS */
UDP_STATS_INC(udp.rterr);
return ERR_RTE;
}
/** TODO: this will bind the udp pcb locally, to the interface which
@ -596,7 +718,7 @@ udp_disconnect(struct udp_pcb *pcb)
{
pcb->flags &= ~UDP_FLAGS_CONNECTED;
}
/*-----------------------------------------------------------------------------------*/
void
udp_recv(struct udp_pcb *pcb,
void (* recv)(void *arg, struct udp_pcb *upcb, struct pbuf *p,
@ -650,9 +772,12 @@ udp_new(void) {
/* initialize PCB to all zeroes */
memset(pcb, 0, sizeof(struct udp_pcb));
}
pcb->ttl = UDP_TTL;
return pcb;
}
/*-----------------------------------------------------------------------------------*/
#if UDP_DEBUG
int
udp_debug_print(struct udp_hdr *udphdr)
@ -668,7 +793,7 @@ udp_debug_print(struct udp_hdr *udphdr)
return 0;
}
#endif /* UDP_DEBUG */
/*-----------------------------------------------------------------------------------*/
#endif /* LWIP_UDP */

View File

@ -47,9 +47,9 @@ u8_t ip_lookup(void *header, struct netif *inp);
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 proto);
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 proto,
u8_t ttl, u8_t tos, u8_t proto,
struct netif *netif);
#define IP_HLEN 20
@ -67,6 +67,36 @@ err_t ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
#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
@ -117,6 +147,8 @@ PACK_STRUCT_END
#if IP_DEBUG
void ip_debug_print(struct pbuf *p);
#else
#define ip_debug_print(p)
#endif /* IP_DEBUG */
#endif /* __LWIP_IP_H__ */

View File

@ -38,6 +38,7 @@
#include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
@ -50,7 +51,8 @@ enum netconn_type {
NETCONN_TCP,
NETCONN_UDP,
NETCONN_UDPLITE,
NETCONN_UDPNOCHKSUM
NETCONN_UDPNOCHKSUM,
NETCONN_RAW
};
enum netconn_state {
@ -82,6 +84,7 @@ struct netconn {
union {
struct tcp_pcb *tcp;
struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb;
err_t err;
sys_mbox_t mbox;
@ -121,6 +124,9 @@ 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,

View File

@ -61,19 +61,19 @@
/** flag for LWIP_DEBUGF to halt after printing this debug message */
#define DBG_HALT 0x08U
#ifdef LWIP_DEBUG
# ifndef LWIP_NOASSERT
#ifndef LWIP_NOASSERT
# define LWIP_ASSERT(x,y) do { if(!(y)) LWIP_PLATFORM_ASSERT(x); } while(0)
# else
#else
# define LWIP_ASSERT(x,y)
# endif
#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) && (((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_ASSERT(x,y)
# define LWIP_DEBUGF(debug,x)
# define LWIP_ERROR(x)
#endif /* LWIP_DEBUG */

View File

@ -49,9 +49,13 @@ void mem_free(void *mem);
void *mem_realloc(void *mem, mem_size_t size);
void *mem_reallocm(void *mem, mem_size_t size);
#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__ */

View File

@ -37,6 +37,7 @@
typedef enum {
MEMP_PBUF,
MEMP_RAW_PCB,
MEMP_UDP_PCB,
MEMP_TCP_PCB,
MEMP_TCP_PCB_LISTEN,

View File

@ -32,9 +32,9 @@
#ifndef __LWIP_OPT_H__
#define __LWIP_OPT_H__
#include "lwip/debug.h"
/* Include user defined options first */
#include "lwipopts.h"
#include "lwip/debug.h"
/* Define default values for unconfigured parameters. */
@ -74,6 +74,11 @@ a lot of data that needs to be copied, this should be set high. */
#define MEMP_NUM_PBUF 16
#endif
/* Number of raw connection PCBs */
#ifndef MEMP_NUM_RAW_PCB
#define MEMP_NUM_RAW_PCB 4
#endif
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#ifndef MEMP_NUM_UDP_PCB
@ -211,6 +216,12 @@ a lot of data that needs to be copied, this should be set high. */
#define ICMP_TTL 255
#endif
/* ---------- RAW options ---------- */
#ifndef RAW_TTL
#define RAW_TTL 255
#endif
/* ---------- DHCP options ---------- */
#ifndef LWIP_DHCP
@ -320,6 +331,14 @@ a lot of data that needs to be copied, this should be set high. */
#define DEFAULT_THREAD_PRIO 1
#endif
/* ---------- Socket Options ---------- */
/* Enable SO_REUSEADDR and SO_REUSEPORT options */
#ifndef SO_REUSE
# define SO_REUSE 1
#endif
/* ---------- Statistics options ---------- */
#ifndef LWIP_STATS
#define LWIP_STATS 1
@ -327,15 +346,63 @@ a lot of data that needs to be copied, this should be set high. */
#if LWIP_STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#ifndef LINK_STATS
#define LINK_STATS 1
#endif
#ifndef IP_STATS
#define IP_STATS 1
#endif
#ifndef IPFRAG_STATS
#define IPFRAG_STATS 1
#endif
#ifndef ICMP_STATS
#define ICMP_STATS 1
#endif
#ifndef UDP_STATS
#define UDP_STATS 1
#endif
#ifndef TCP_STATS
#define TCP_STATS 1
#endif
#ifndef MEM_STATS
#define MEM_STATS 1
#endif
#ifndef MEMP_STATS
#define MEMP_STATS 1
#endif
#ifndef PBUF_STATS
#define PBUF_STATS 1
#endif
#ifndef SYS_STATS
#define SYS_STATS 1
#endif
#ifndef RAW_STATS
#define RAW_STATS 0
#endif
#else
#define LINK_STATS 0
#define IP_STATS 0
#define IPFRAG_STATS 0
#define ICMP_STATS 0
#define UDP_STATS 0
#define TCP_STATS 0
#define MEM_STATS 0
#define MEMP_STATS 0
#define PBUF_STATS 0
#define SYS_STATS 0
#define RAW_STATS 0
#endif /* LWIP_STATS */
@ -477,6 +544,10 @@ a lot of data that needs to be copied, this should be set high. */
#define IP_REASS_DEBUG DBG_OFF
#endif
#ifndef RAW_DEBUG
#define RAW_DEBUG DBG_OFF
#endif
#ifndef MEM_DEBUG
#define MEM_DEBUG DBG_OFF
#endif

View File

@ -29,7 +29,7 @@
* Author: Adam Dunkels <adam@sics.se>
*
*/
/*-----------------------------------------------------------------------------------*/
#ifndef __LWIP_PBUF_H__
#define __LWIP_PBUF_H__
@ -108,6 +108,7 @@ 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);

74
src/include/lwip/raw.h Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2001-2003 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;
int (* 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,
int (* recv)(void *arg, struct raw_pcb *pcb,
struct pbuf *p,
struct ip_addr *addr),
void *recv_arg);
err_t raw_send_to (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. */
int raw_input (struct pbuf *p, struct netif *inp);
void raw_init (void);
#endif /* __LWIP_RAW_H__ */

View File

@ -70,6 +70,7 @@ struct sockaddr {
#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)
@ -117,6 +118,36 @@ struct linger {
#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.
*

View File

@ -101,9 +101,49 @@ 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
#endif /* __LWIP_STATS_H__ */

View File

@ -53,7 +53,7 @@ void tcp_init (void); /* Must be called first to
initialize TCP. */
void tcp_tmr (void); /* Must be called every
TCP_TMR_INTERVAL
ms. (Typically 100 ms). */
ms. (Typically 250 ms). */
/* Application program's interface: */
struct tcp_pcb * tcp_new (void);
struct tcp_pcb * tcp_alloc (u8_t prio);
@ -115,30 +115,32 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#define TCP_SEQ_GT(a,b) ((s32_t)((a)-(b)) > 0)
#define TCP_SEQ_GEQ(a,b) ((s32_t)((a)-(b)) >= 0)
#define TCP_FIN 0x01
#define TCP_SYN 0x02
#define TCP_RST 0x04
#define TCP_PSH 0x08
#define TCP_ACK 0x10
#define TCP_URG 0x20
#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 0x3f
#define TCP_FLAGS 0x3fU
/* Length of the TCP header, excluding options. */
#define TCP_HLEN 20
#ifndef TCP_TMR_INTERVAL
#define TCP_TMR_INTERVAL 100 /* The TCP timer interval in
#define TCP_TMR_INTERVAL 250 /* The TCP timer interval in
milliseconds. */
#endif /* TCP_TMR_INTERVAL */
#ifndef TCP_FAST_INTERVAL
#define TCP_FAST_INTERVAL 200 /* the fine grained timeout in
#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 500 /* the coarse grained timeout in
#define TCP_SLOW_INTERVAL (2*TCP_TMR_INTERVAL) /* the coarse grained timeout in
milliseconds */
#endif /* TCP_SLOW_INTERVAL */
@ -149,6 +151,19 @@ void tcp_rexmit (struct tcp_pcb *pcb);
#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
@ -158,7 +173,7 @@ struct tcp_hdr {
PACK_STRUCT_FIELD(u16_t dest);
PACK_STRUCT_FIELD(u32_t seqno);
PACK_STRUCT_FIELD(u32_t ackno);
PACK_STRUCT_FIELD(u16_t _offset_flags);
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);
@ -168,11 +183,15 @@ PACK_STRUCT_END
# include "arch/epstruct.h"
#endif
#define TCPH_OFFSET(hdr) (ntohs((hdr)->_offset_flags) >> 8)
#define TCPH_FLAGS(hdr) (ntohs((hdr)->_offset_flags) & 0xff)
#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(hdr, offset) (hdr)->_offset_flags = htons(((offset) << 8) | TCPH_FLAGS(hdr))
#define TCPH_FLAGS_SET(hdr, flags) (hdr)->_offset_flags = htons((TCPH_OFFSET(hdr) << 8) | (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))
@ -194,17 +213,30 @@ enum tcp_state {
/* the TCP protocol control block */
struct tcp_pcb {
/* Common members of all PCB types */
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;
struct ip_addr local_ip;
u16_t local_port;
enum tcp_state state; /* TCP state */
struct ip_addr remote_ip;
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 varables */
u32_t rcv_nxt; /* next seqno expected */
u16_t rcv_wnd; /* receiver window */
@ -217,14 +249,6 @@ struct tcp_pcb {
u16_t rtime;
u16_t mss; /* maximum segment size */
u8_t flags;
#define TF_ACK_DELAY 0x01U /* Delayed ACK. */
#define TF_ACK_NOW 0x02U /* Immediate ACK. */
#define TF_INFR 0x04U /* In fast recovery. */
#define TF_RESET 0x08U /* Connection was reset. */
#define TF_CLOSED 0x10U /* Connection was sucessfully closed. */
#define TF_GOT_FIN 0x20U /* Connection was closed by the remote end. */
/* RTT estimation variables. */
u16_t rttest; /* RTT estimate in 500ms ticks */
@ -282,21 +306,32 @@ struct tcp_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 */
u8_t prio;
void *callback_arg;
struct ip_addr local_ip;
u16_t local_port;
/* 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);
@ -396,6 +431,8 @@ void tcp_rst(u32_t seqno, u32_t ackno,
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;
@ -406,7 +443,11 @@ void tcp_debug_print_state(enum tcp_state s);
void tcp_debug_print_pcbs(void);
int tcp_pcbs_sane(void);
#else
#define tcp_pcbs_sane() 1
# 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

View File

@ -52,12 +52,16 @@ struct udp_hdr {
#define UDP_FLAGS_CONNECTED 0x04U
struct udp_pcb {
/* Common members of all PCB types */
IP_PCB;
/* Protocol specific PCB members */
struct udp_pcb *next;
struct ip_addr local_ip, remote_ip;
u8_t flags;
u16_t local_port, remote_port;
u8_t flags;
u16_t chksum_len;
void (* recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
@ -91,7 +95,11 @@ u8_t udp_lookup (struct ip_hdr *iphdr, struct netif *inp);
void udp_input (struct pbuf *p, struct netif *inp);
void udp_init (void);
#if UDP_DEBUG
int udp_debug_print(struct udp_hdr *udphdr);
#else
#define udp_debug_print(udphdr)
#endif
#endif /* __LWIP_UDP_H__ */

View File

@ -4,8 +4,10 @@
*
* 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.
* requests from other machines for our physical address.
*
* This implementation complies with RFC 826 (Ethernet ARP) and supports
* Gratuitious ARP from RFC3220 (IP Mobility Support for IPv4) section 4.6.
*/
/*
@ -156,23 +158,16 @@ etharp_tmr(void)
if ((arp_table[i].state == ETHARP_STATE_STABLE) &&
(arp_table[i].ctime >= ARP_MAXAGE)) {
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired stable entry %u.\n", i));
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
if (arp_table[i].p != NULL) {
/* remove any queued packet */
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
}
#endif
goto empty;
} else if ((arp_table[i].state == ETHARP_STATE_PENDING) &&
(arp_table[i].ctime >= ARP_MAXPENDING)) {
arp_table[i].state = ETHARP_STATE_EMPTY;
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired pending entry %u.\n", i));
empty:
arp_table[i].state = ETHARP_STATE_EMPTY;
#if ARP_QUEUEING
if (arp_table[i].p != NULL) {
/* remove any queued packet */
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing packet queue %p.\n", i, (void *)(arp_table[i].p)));
LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %u, packet queue %p.\n", i, (void *)(arp_table[i].p)));
pbuf_free(arp_table[i].p);
arp_table[i].p = NULL;
}
@ -292,6 +287,7 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e
ethhdr = p->payload;
for (k = 0; k < netif->hwaddr_len; ++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.\n"));
@ -390,7 +386,8 @@ etharp_ip_input(struct netif *netif, struct pbuf *p)
/**
* Responds to ARP requests, updates ARP entries and sends queued IP packets.
* 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.
@ -408,15 +405,24 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
{
struct etharp_hdr *hdr;
u8_t i;
u8_t for_us;
/* drop short ARP packets */
if (p->tot_len < sizeof(struct etharp_hdr)) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 1, ("etharp_arp_input: packet dropped, too short (%d/%d)\n", p->tot_len, sizeof(struct etharp_hdr)));
pbuf_free(p);
return NULL;
}
hdr = p->payload;
/* 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(&(hdr->dipaddr), &(netif->ip_addr));
}
switch (htons(hdr->opcode)) {
/* ARP request? */
@ -432,10 +438,8 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
pbuf_free(p);
return NULL;
}
/* update the ARP cache */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* ARP request for our address? */
if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
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 */
@ -454,41 +458,42 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
hdr->hwtype = htons(HWTYPE_ETHERNET);
ARPH_HWLEN_SET(hdr, netif->hwaddr_len);
hdr->proto = htons(ETHTYPE_IP);
hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
hdr->ethhdr.type = htons(ETHTYPE_ARP);
hdr->ethhdr.type = htons(ETHTYPE_ARP);
/* return ARP reply */
netif->linkoutput(netif, p);
/* request was not directed to us */
} else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP request was not for us.\n"));
}
break;
case ARP_REPLY:
/* ARP reply. We insert or update the ARP table. */
/* ARP reply. We insert or update the ARP table later. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n"));
#if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
/* DHCP needs to know about ARP replies */
dhcp_arp_reply(netif, &hdr->sipaddr);
/* DHCP needs to know about ARP replies to our address */
if (for_us) dhcp_arp_reply(netif, &hdr->sipaddr);
#endif
/* ARP reply directed to us? */
if (ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is for us\n"));
/* update_the ARP cache, ask to insert */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
/* ARP reply not directed to us */
} else {
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: incoming ARP reply is not for us\n"));
/* update the destination address pair */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* update the destination address pair */
update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
}
break;
default:
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %d\n", htons(hdr->opcode)));
break;
}
/* add or update entries in the ARP cache */
if (for_us) {
/* insert IP address in ARP cache (assume requester wants to talk to us)
* we might even send out a queued packet to this host */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), ARP_INSERT_FLAG);
/* request was not directed to us, but snoop anyway */
} else {
/* update or insert the source IP address in the cache */
update_arp_entry(netif, &(hdr->sipaddr), &(hdr->shwaddr), 0);
/* update or insert the destination IP address pair in the cache */
update_arp_entry(netif, &(hdr->dipaddr), &(hdr->dhwaddr), 0);
}
/* free ARP packet */
pbuf_free(p);
p = NULL;
@ -503,9 +508,9 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
* returned, ready to be sent.
*
* If ARP does not have the Ethernet address in cache the packet is
* queued and a ARP request is sent (on a best-effort basis). This
* ARP request is returned as a pbuf, which should be sent by the
* caller.
* queued (if enabled and space available) and a ARP request is sent.
* This ARP request is returned as a pbuf, which should be sent by
* the caller.
*
* If ARP failed to allocate resources, NULL is returned.
*
@ -515,7 +520,8 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
* @param ipaddr The IP address of the packet destination.
* @param pbuf The pbuf(s) containing the IP packet to be sent.
*
* @return If non-NULL, a packet ready to be sent.
* @return If non-NULL, a packet ready to be sent by caller.
*
*/
struct pbuf *
etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
@ -529,9 +535,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* The pbuf_header() call shouldn't fail, and we'll just bail
out if it does.. */
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE | 2, ("etharp_output: could not allocate room for header.\n"));
#ifdef LINK_STATS
++lwip_stats.link.lenerr;
#endif /* LINK_STATS */
LINK_STATS_INC(link.lenerr);
return NULL;
}
@ -541,9 +545,9 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* assume unresolved Ethernet address */
dest = NULL;
/* Construct Ethernet header. Start with looking up deciding which
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
/* destination IP address is an IP broadcast address? */
if (ip_addr_isany(ipaddr) ||
@ -555,7 +559,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address. */
mcastaddr.addr[0] = 0x01;
mcastaddr.addr[1] = 0x0;
mcastaddr.addr[1] = 0x00;
mcastaddr.addr[2] = 0x5e;
mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
mcastaddr.addr[4] = ip4_addr3(ipaddr);
@ -583,7 +587,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
}
/* Ethernet address for IP destination address is in ARP cache? */
for(i = 0; i < ARP_TABLE_SIZE; ++i) {
for (i = 0; i < ARP_TABLE_SIZE; ++i) {
/* match found? */
if (arp_table[i].state == ETHARP_STATE_STABLE &&
ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
@ -594,6 +598,7 @@ etharp_output(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
/* could not find the destination Ethernet address in ARP cache? */
if (dest == NULL) {
/* ARP query for the IP address, submit this IP packet for queueing */
/* TODO: How do we handle netif->ipaddr == ipaddr? */
etharp_query(netif, ipaddr, q);
/* return nothing */
return NULL;
@ -736,10 +741,12 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
LWIP_DEBUGF(ETHARP_DEBUG | DBG_TRACE, ("etharp_query: sending ARP request.\n"));
hdr = p->payload;
hdr->opcode = htons(ARP_REQUEST);
for(j = 0; j < netif->hwaddr_len; ++j)
for (j = 0; j < netif->hwaddr_len; ++j)
{
hdr->dhwaddr.addr[j] = 0x00;
hdr->shwaddr.addr[j] = srcaddr->addr[j];
/* the hardware address is what we ask for, in
* a request it is a don't-care, we use 0's */
hdr->dhwaddr.addr[j] = 0x00;
}
ip_addr_set(&(hdr->dipaddr), ipaddr);
ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
@ -749,7 +756,7 @@ err_t etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q)
hdr->proto = htons(ETHTYPE_IP);
ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
for(j = 0; j < netif->hwaddr_len; ++j)
for (j = 0; j < netif->hwaddr_len; ++j)
{
hdr->ethhdr.dest.addr[j] = 0xff;
hdr->ethhdr.src.addr[j] = srcaddr->addr[j];

View File

@ -63,7 +63,7 @@ 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)
{
@ -87,7 +87,7 @@ low_level_init(struct netif *netif)
/* Do whatever else is needed to initialize interface. */
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_output():
*
@ -96,7 +96,7 @@ low_level_init(struct netif *netif)
* might be chained.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
@ -120,7 +120,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* low_level_input():
*
@ -128,7 +128,7 @@ low_level_output(struct ethernetif *ethernetif, struct pbuf *p)
* packet from the interface into the pbuf.
*
*/
/*-----------------------------------------------------------------------------------*/
static struct pbuf *
low_level_input(struct ethernetif *ethernetif)
{
@ -165,7 +165,7 @@ low_level_input(struct ethernetif *ethernetif)
return p;
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_output():
*
@ -174,7 +174,7 @@ low_level_input(struct ethernetif *ethernetif)
* do the actuall transmission of the packet.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
@ -264,7 +264,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
return low_level_output(ethernetif, p);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_input():
*
@ -274,7 +274,7 @@ ethernetif_output(struct netif *netif, struct pbuf *p,
* interface.
*
*/
/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
@ -314,14 +314,14 @@ ethernetif_input(struct netif *netif)
}
}
}
/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
arp_tmr();
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_init():
*
@ -330,7 +330,7 @@ arp_timer(void *arg)
* actual setup of the hardware.
*
*/
/*-----------------------------------------------------------------------------------*/
void
ethernetif_init(struct netif *netif)
{
@ -350,4 +350,4 @@ ethernetif_init(struct netif *netif)
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/

View File

@ -40,13 +40,23 @@
#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;
char *ptr;
void **arg;
#if defined(LWIP_DEBUG) && defined(LWIP_TCPDUMP)
tcpdump(p);
@ -60,21 +70,42 @@ loopif_output(struct netif *netif, struct pbuf *p,
memcpy(ptr, q->payload, q->len);
ptr += q->len;
}
netif->input(r, netif);
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;
}
/*-----------------------------------------------------------------------------------*/

View File

@ -194,7 +194,7 @@ void link_terminated(int unit)
if (logged_in)
logout();
lcp_phase[unit] = PHASE_DEAD;
ppp_trace(LOG_NOTICE, "Connection terminated.\n");
AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n"));
pppMainWakeup(unit);
}
@ -257,7 +257,7 @@ void link_established(int unit)
* of "" and a password of "". If that's not OK, boot it out.
*/
if (!wo->neg_upap || !null_login(unit)) {
ppp_trace(LOG_WARNING, "peer refused to authenticate\n");
AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n"));
lcp_close(unit, "peer refused to authenticate");
return;
}
@ -294,7 +294,7 @@ void link_established(int unit)
if (ppp_settings.passwd[0] == 0) {
passwd_from_file = 1;
if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd))
ppp_trace(LOG_ERR, "No secret found for PAP login\n");
AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n"));
}
upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd);
auth |= PAP_WITHPEER;
@ -337,8 +337,8 @@ void auth_peer_success(int unit, u16_t protocol, char *name, int namelen)
pbit = PAP_PEER;
break;
default:
ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol);
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol));
return;
}
@ -400,8 +400,8 @@ void auth_withpeer_success(int unit, u16_t protocol)
pbit = PAP_WITHPEER;
break;
default:
ppp_trace(LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol);
AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n",
protocol));
pbit = 0;
}
@ -541,7 +541,7 @@ int check_passwd(
* On 10'th, drop the connection.
*/
if (attempts++ >= 10) {
ppp_trace(LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user);
AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user));
/*ppp_panic("Excess Bad Logins");*/
}
if (attempts > 3) {
@ -616,7 +616,7 @@ int get_secret(
len = strlen(ppp_settings.passwd);
if (len > MAXSECRETLEN) {
ppp_trace(LOG_ERR, "Secret for %s on %s is too long\n", client, server);
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
len = MAXSECRETLEN;
}
BCOPY(ppp_settings.passwd, secret, len);
@ -640,7 +640,7 @@ int get_secret(
len = strlen(secbuf);
if (len > MAXSECRETLEN) {
ppp_trace(LOG_ERR, "Secret for %s on %s is too long\n", client, server);
AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server));
len = MAXSECRETLEN;
}
BCOPY(secbuf, secret, len);
@ -753,7 +753,7 @@ static void check_idle(void *arg)
itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
if (itime >= ppp_settings.idle_time_limit) {
/* link is idle: shut it down. */
ppp_trace(LOG_INFO, "Terminating connection due to lack of activity.\n");
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);
@ -767,7 +767,7 @@ static void connect_time_expired(void *arg)
{
(void)arg;
ppp_trace(LOG_INFO, "Connect time expired\n");
AUTHDEBUG((LOG_INFO, "Connect time expired\n"));
lcp_close(0, "Connect time expired"); /* Close connection */
}

View File

@ -307,7 +307,7 @@ void pppInit(void)
(*protp->init)(i);
}
#ifdef LINK_STATS
#if LINK_STATS
/* Clear the statistics. */
memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
#endif
@ -326,6 +326,29 @@ void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
#endif
ppp_settings.refuse_chap = 1;
break;
case PPPAUTHTYPE_ANY:
/* 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.
*
*/
ppp_settings.refuse_pap = 0;
ppp_settings.refuse_chap = 0;
break;
case PPPAUTHTYPE_PAP:
ppp_settings.refuse_pap = 0;
ppp_settings.refuse_chap = 1;
@ -459,7 +482,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
PPPDEBUG((LOG_WARNING,
"PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.err++;
#endif /* LINK_STATS */
pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
@ -468,7 +491,7 @@ static void nPut(PPPControl *pc, struct pbuf *nb)
}
pbuf_free(nb);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
}
@ -492,7 +515,7 @@ static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
if (tb) {
nb->next = tb;
}
#ifdef LINK_STATS
#if LINK_STATS
else {
lwip_stats.link.memerr++;
}
@ -529,7 +552,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
pd, protocol, pb));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.opterr++;
lwip_stats.link.drop++;
#endif
@ -539,7 +562,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
/* Check that the link is up. */
if (lcp_phase[pd] == PHASE_DEAD) {
PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.rterr++;
lwip_stats.link.drop++;
#endif
@ -550,7 +573,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif /* LINK_STATS */
@ -577,7 +600,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
break;
default:
PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.proterr++;
lwip_stats.link.drop++;
#endif
@ -639,7 +662,7 @@ static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *i
"pppifOutput[%d]: Alloc err - dropping proto=%d\n",
pd, protocol));
pbuf_free(headMB);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
@ -728,7 +751,7 @@ int pppWrite(int pd, const u_char *s, int n)
struct pbuf *headMB = NULL, *tailMB;
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
@ -768,7 +791,7 @@ int pppWrite(int pd, const u_char *s, int n)
"pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
/* "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
pbuf_free(headMB);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.proterr++;
#endif /* LINK_STATS */
@ -1275,7 +1298,7 @@ static void pppInput(void *arg)
pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
@ -1365,7 +1388,7 @@ static void pppInput(void *arg)
}
drop:
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif
@ -1395,7 +1418,7 @@ static void pppDrop(PPPControl *pc)
vj_uncompress_err(&pc->vjComp);
#endif
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif /* LINK_STATS */
}
@ -1433,7 +1456,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_WARNING,
"pppInProc[%d]: Dropping incomplete packet %d\n",
pd, pc->inState));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.lenerr++;
#endif
pppDrop(pc);
@ -1443,7 +1466,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_INFO,
"pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
pd, pc->inFCS, pc->inProtocol));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.chkerr++;
#endif
pppDrop(pc);
@ -1457,14 +1480,12 @@ static void pppInProc(int pd, u_char *s, int l)
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_chain(pc->inHead, pc->inTail);
pbuf_free(pc->inTail);
pbuf_cat(pc->inHead, pc->inTail);
}
} else {
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_chain(pc->inHead, pc->inTail);
pbuf_free(pc->inTail);
pbuf_cat(pc->inHead, pc->inTail);
}
pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
@ -1475,7 +1496,7 @@ static void pppInProc(int pd, u_char *s, int l)
PPPDEBUG((LOG_ERR,
"pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
pbuf_free(pc->inHead);
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.drop++;
#endif
}
@ -1560,8 +1581,7 @@ static void pppInProc(int pd, u_char *s, int l)
if(pc->inTail) {
pc->inTail->tot_len = pc->inTail->len;
if (pc->inTail != pc->inHead) {
pbuf_chain(pc->inHead, pc->inTail);
pbuf_free(pc->inTail);
pbuf_cat(pc->inHead, pc->inTail);
}
}
/* If we haven't started a packet, we need a packet header. */
@ -1571,7 +1591,7 @@ static void pppInProc(int pd, u_char *s, int l)
* higher layers deal with it. Continue processing
* the received pbuf chain in case a new packet starts. */
PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
#ifdef LINK_STATS
#if LINK_STATS
lwip_stats.link.memerr++;
#endif /* LINK_STATS */
pppDrop(pc);

View File

@ -208,8 +208,11 @@ enum NPmode {
#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.
@ -340,8 +343,28 @@ extern struct protent *ppp_protocols[];/* Table of pointers to supported protoco
/* 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
};

View File

@ -115,9 +115,7 @@ slipif_input( struct netif * netif )
/* Received whole packet. */
pbuf_realloc(q, recved);
#ifdef LINK_STATS
++lwip_stats.link.recv;
#endif /* LINK_STATS */
LINK_STATS_INC(link.recv);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet\n"));
return q;
@ -141,16 +139,13 @@ slipif_input( struct netif * netif )
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n"));
p = pbuf_alloc(PBUF_LINK, PBUF_POOL_BUFSIZE, PBUF_POOL);
#ifdef LINK_STATS
if (p == NULL) {
++lwip_stats.link.drop;
LINK_STATS_INC(link.drop);
LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n"));
}
#endif /* LINK_STATS */
if (q != NULL) {
pbuf_chain(q, p);
pbuf_free(p);
pbuf_cat(q, p);
} else {
q = p;
}