sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible to corrupt remote addr/port connection state". Reduce problems "not enought memory" with netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function. WARNING, if you directly access to "fromaddr" & "fromport" field from netbuf struct, these fields are now renamed "addr" & "port".

This commit is contained in:
fbernon 2007-05-04 15:18:29 +00:00
parent 05ea5f05ae
commit 5a12aeb4a1
6 changed files with 102 additions and 124 deletions

View File

@ -23,6 +23,14 @@ HISTORY
++ New features: ++ New features:
2007-05-04 Frédéric Bernon, Jonathan Larmour
* sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c: Fix bug #19162 "lwip_sento: a possible
to corrupt remote addr/port connection state". Reduce problems "not enought memory" with
netbuf (if we receive lot of datagrams). Improve lwip_sendto (only one exchange between
sockets api and api_msg which run in tcpip_thread context). Add netconn_sento function.
Warning, if you directly access to "fromaddr" & "fromport" field from netbuf struct,
these fields are now renamed "addr" & "port".
2007-04-11 Jonathan Larmour 2007-04-11 Jonathan Larmour
* sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new * sys.h, api_lib.c: Provide new sys_mbox_tryfetch function. Require ports to provide new
sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return sys_arch_mbox_tryfetch function to get a message if one is there, otherwise return
@ -503,9 +511,9 @@ HISTORY
2004-10-16 Kieran Mansley <kjm25@cam.ac.uk> 2004-10-16 Kieran Mansley <kjm25@cam.ac.uk>
* tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately, * tcp.c: Add code to tcp_recved() to send an ACK (window update) immediately,
even if one is already pending, if the rcv_wnd is above a threshold even if one is already pending, if the rcv_wnd is above a threshold
(currently TCP_WND/2). This avoids waiting for a timer to expire to send a (currently TCP_WND/2). This avoids waiting for a timer to expire to send a
delayed ACK in order to open the window if the stack is only receiving data. delayed ACK in order to open the window if the stack is only receiving data.
2004-09-12 Kieran Mansley <kjm25@cam.ac.uk> 2004-09-12 Kieran Mansley <kjm25@cam.ac.uk>
* tcp*.*: Retransmit time-out handling improvement by Sam Jansen. * tcp*.*: Retransmit time-out handling improvement by Sam Jansen.

View File

@ -49,6 +49,7 @@ netbuf *netbuf_new(void)
if (buf != NULL) { if (buf != NULL) {
buf->p = NULL; buf->p = NULL;
buf->ptr = NULL; buf->ptr = NULL;
buf->addr = NULL;
return buf; return buf;
} else { } else {
return NULL; return NULL;
@ -116,12 +117,6 @@ netbuf_chain(struct netbuf *head, struct netbuf *tail)
memp_free(MEMP_NETBUF, tail); memp_free(MEMP_NETBUF, tail);
} }
u16_t
netbuf_len(struct netbuf *buf)
{
return buf->p->tot_len;
}
err_t err_t
netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len) netbuf_data(struct netbuf *buf, void **dataptr, u16_t *len)
{ {
@ -184,24 +179,6 @@ 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 struct
netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
void (*callback)(struct netconn *, enum netconn_evt, u16_t len)) void (*callback)(struct netconn *, enum netconn_evt, u16_t len))
@ -253,7 +230,6 @@ netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto,
return conn; return conn;
} }
struct struct
netconn *netconn_new(enum netconn_type t) netconn *netconn_new(enum netconn_type t)
{ {
@ -267,7 +243,6 @@ netconn *netconn_new_with_callback(enum netconn_type t,
return netconn_new_with_proto_and_callback(t,0,callback); return netconn_new_with_proto_and_callback(t,0,callback);
} }
err_t err_t
netconn_delete(struct netconn *conn) netconn_delete(struct netconn *conn)
{ {
@ -487,8 +462,10 @@ netconn_recv(struct netconn *conn)
} }
if (conn->recvmbox == SYS_MBOX_NULL) { if (conn->recvmbox == SYS_MBOX_NULL) {
conn->err = ERR_CONN; if ((conn->recvmbox = sys_mbox_new()) == SYS_MBOX_NULL) {
return NULL; conn->err = ERR_CONN;
return NULL;
}
} }
if (conn->err != ERR_OK) { if (conn->err != ERR_OK) {
@ -533,8 +510,8 @@ netconn_recv(struct netconn *conn)
buf->p = p; buf->p = p;
buf->ptr = p; buf->ptr = p;
buf->fromport = 0; buf->port = 0;
buf->fromaddr = NULL; buf->addr = NULL;
/* Let the stack know that we have taken the data. */ /* Let the stack know that we have taken the data. */
msg.type = API_MSG_RECV; msg.type = API_MSG_RECV;
@ -564,6 +541,16 @@ netconn_recv(struct netconn *conn)
return buf; return buf;
} }
err_t
netconn_sendto(struct netconn *conn, struct netbuf *buf, struct ip_addr *addr, u16_t port)
{ if (buf!=NULL) {
buf->addr = addr;
buf->port = port;
return netconn_send( conn, buf);
}
return ERR_VAL;
}
err_t err_t
netconn_send(struct netconn *conn, struct netbuf *buf) netconn_send(struct netconn *conn, struct netbuf *buf)
{ {
@ -580,7 +567,7 @@ netconn_send(struct netconn *conn, struct netbuf *buf)
LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len)); LWIP_DEBUGF(API_LIB_DEBUG, ("netconn_send: sending %d bytes\n", buf->p->tot_len));
msg.type = API_MSG_SEND; msg.type = API_MSG_SEND;
msg.msg.conn = conn; msg.msg.conn = conn;
msg.msg.msg.p = buf->p; msg.msg.msg.b = buf;
api_msg_post(&msg); api_msg_post(&msg);
return conn->err; return conn->err;
} }

View File

@ -57,8 +57,8 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
pbuf_ref(p); pbuf_ref(p);
buf->p = p; buf->p = p;
buf->ptr = p; buf->ptr = p;
buf->fromaddr = addr; buf->addr = addr;
buf->fromport = pcb->protocol; buf->port = pcb->protocol;
conn->recv_avail += p->tot_len; conn->recv_avail += p->tot_len;
/* Register event with callback */ /* Register event with callback */
@ -95,8 +95,8 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
} else { } else {
buf->p = p; buf->p = p;
buf->ptr = p; buf->ptr = p;
buf->fromaddr = addr; buf->addr = addr;
buf->fromport = port; buf->port = port;
} }
conn->recv_avail += p->tot_len; conn->recv_avail += p->tot_len;
@ -581,7 +581,11 @@ do_send(struct api_msg_msg *msg)
switch (msg->conn->type) { switch (msg->conn->type) {
#if LWIP_RAW #if LWIP_RAW
case NETCONN_RAW: case NETCONN_RAW:
raw_send(msg->conn->pcb.raw, msg->msg.p); if (msg->msg.b->addr==NULL) {
raw_send(msg->conn->pcb.raw, msg->msg.b->p);
} else {
raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, msg->msg.b->addr);
}
break; break;
#endif #endif
#if LWIP_UDP #if LWIP_UDP
@ -590,7 +594,11 @@ do_send(struct api_msg_msg *msg)
case NETCONN_UDPNOCHKSUM: case NETCONN_UDPNOCHKSUM:
/* FALLTHROUGH */ /* FALLTHROUGH */
case NETCONN_UDP: case NETCONN_UDP:
udp_send(msg->conn->pcb.udp, msg->msg.p); if (msg->msg.b->addr==NULL) {
udp_send(msg->conn->pcb.udp, msg->msg.b->p);
} else {
udp_sendto(msg->conn->pcb.udp, msg->msg.b->p, msg->msg.b->addr, msg->msg.b->port);
}
break; break;
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
case NETCONN_TCP: case NETCONN_TCP:

View File

@ -461,7 +461,6 @@ int
lwip_send(int s, const void *data, int size, unsigned int flags) lwip_send(int s, const void *data, int size, unsigned int flags)
{ {
struct lwip_socket *sock; struct lwip_socket *sock;
struct netbuf *buf;
err_t err; err_t err;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d, data=%p, size=%d, flags=0x%x)\n", s, data, size, flags));
@ -470,45 +469,14 @@ lwip_send(int s, const void *data, int size, unsigned int flags)
if (!sock) if (!sock)
return -1; return -1;
switch (netconn_type(sock->conn)) { if (sock->conn->type!=NETCONN_TCP)
case NETCONN_RAW: return lwip_sendto( s, data, size, flags, NULL, 0);
case NETCONN_UDP:
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
/* create a buffer */
buf = netbuf_new();
if (!buf) { err = netconn_write( sock->conn, data, size, NETCONN_COPY);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ENOBUFS\n", s));
sock_set_errno(sock, ENOBUFS);
return -1;
}
/* make the buffer point to the data that should be sent */ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d size=%d\n", s, err, size));
if ((err = netbuf_ref(buf, data, size))==ERR_OK) { sock_set_errno(sock, err_to_errno(err));
/* send the data */ return (err==ERR_OK?size:-1);
err = netconn_send(sock->conn, buf);
}
/* deallocated the buffer */
netbuf_delete(buf);
break;
case NETCONN_TCP:
err = netconn_write(sock->conn, data, size, NETCONN_COPY);
break;
default:
err = ERR_ARG;
break;
}
if (err != ERR_OK) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) err=%d\n", s, err));
sock_set_errno(sock, err_to_errno(err));
return -1;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_send(%d) ok size=%d\n", s, size));
sock_set_errno(sock, 0);
return size;
} }
int int
@ -516,37 +484,51 @@ lwip_sendto(int s, const void *data, int size, unsigned int flags,
struct sockaddr *to, socklen_t tolen) struct sockaddr *to, socklen_t tolen)
{ {
struct lwip_socket *sock; struct lwip_socket *sock;
struct ip_addr remote_addr, addr; struct netbuf buf;
u16_t remote_port, port; struct ip_addr remote_addr;
int err,connected; u16_t remote_port;
int err;
sock = get_socket(s); sock = get_socket(s);
if (!sock) if (!sock)
return -1; return -1;
LWIP_ASSERT("lwip_sendto: invalid address", (tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET)); if (sock->conn->type==NETCONN_TCP)
return lwip_send( s, data, size, flags);
/* get the peer if currently connected */ LWIP_ASSERT("lwip_sendto: invalid address", (((to==NULL) && (tolen==0)) || ((tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET))) );
connected = (netconn_peer(sock->conn, &addr, &port) == ERR_OK);
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr; /* initialize a buffer */
remote_port = ((struct sockaddr_in *)to)->sin_port; buf.p = buf.ptr = NULL;
if (to) {
remote_addr.addr = ((struct sockaddr_in *)to)->sin_addr.s_addr;
remote_port = ntohs(((struct sockaddr_in *)to)->sin_port);
buf.addr = &remote_addr;
buf.port = remote_port;
} else {
remote_addr.addr = 0;
remote_port = 0;
buf.addr = NULL;
buf.port = 0;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, size=%d, flags=0x%x to=", s, data, size, flags)); 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); ip_addr_debug_print(SOCKETS_DEBUG, &remote_addr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", ntohs(remote_port))); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u\n", remote_port));
netconn_connect(sock->conn, &remote_addr, ntohs(remote_port)); /* make the buffer point to the data that should be sent */
if ((err = netbuf_ref(&buf, data, size))==ERR_OK) {
/* send the data */
err = netconn_send(sock->conn, &buf);
}
err = lwip_send(s, data, size, flags); /* deallocated the buffer */
if (buf.p != NULL) {
pbuf_free(buf.p);
}
/* reset the remote address and port number sock_set_errno(sock, err_to_errno(err));
of the connection */ return (err==ERR_OK?size:-1);
if (connected)
netconn_connect(sock->conn, &addr, port);
else
netconn_disconnect(sock->conn);
return err;
} }
int int
@ -600,7 +582,6 @@ lwip_write(int s, const void *data, int size)
return lwip_send(s, data, size, 0); return lwip_send(s, data, size, 0);
} }
static int static int
lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset) lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
{ {
@ -646,8 +627,6 @@ lwip_selscan(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset)
return nready; return nready;
} }
int int
lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
struct timeval *timeout) struct timeval *timeout)
@ -794,7 +773,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
return nready; return nready;
} }
static void static void
event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
{ {
@ -877,12 +855,8 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
break; break;
} }
} }
} }
int lwip_shutdown(int s, int how) int lwip_shutdown(int s, int how)
{ {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how)); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_shutdown(%d, how=%d)\n", s, how));
@ -1063,7 +1037,6 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
return -1; return -1;
} }
/* Now do the actual option processing */ /* Now do the actual option processing */
switch(level) { switch(level) {
@ -1167,7 +1140,6 @@ int lwip_getsockopt (int s, int level, int optname, void *optval, socklen_t *opt
break; break;
} }
sock_set_errno(sock, err); sock_set_errno(sock, err);
return err ? -1 : 0; return err ? -1 : 0;
} }
@ -1185,7 +1157,6 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
return -1; return -1;
} }
/* Do length and type checks for the various options first, to keep it readable. */ /* Do length and type checks for the various options first, to keep it readable. */
switch( level ) { switch( level ) {
@ -1420,15 +1391,15 @@ int lwip_ioctl(int s, long cmd, void *argp)
*((u16_t*)argp) = sock->conn->recv_avail; *((u16_t*)argp) = sock->conn->recv_avail;
/* Check if there is data left from the last recv operation. /maq 041215 */ /* Check if there is data left from the last recv operation. /maq 041215 */
if (sock->lastdata) { if (sock->lastdata) {
buflen = netbuf_len(sock->lastdata); buflen = netbuf_len(sock->lastdata);
buflen -= sock->lastoffset; buflen -= sock->lastoffset;
*((u16_t*)argp) += buflen; *((u16_t*)argp) += buflen;
} }
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %u\n", s, argp, *((u16_t*)argp))); 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; return 0;

View File

@ -80,8 +80,8 @@ enum netconn_igmp {
struct netbuf { struct netbuf {
struct pbuf *p, *ptr; struct pbuf *p, *ptr;
struct ip_addr *fromaddr; struct ip_addr *addr;
u16_t fromport; u16_t port;
}; };
struct netconn { struct netconn {
@ -121,12 +121,13 @@ err_t netbuf_data (struct netbuf *buf,
s8_t netbuf_next (struct netbuf *buf); s8_t netbuf_next (struct netbuf *buf);
void netbuf_first (struct netbuf *buf); void netbuf_first (struct netbuf *buf);
void netbuf_copy (struct netbuf *buf,
void *dataptr, u16_t len);
void netbuf_copy_partial(struct netbuf *buf, void *dataptr, void netbuf_copy_partial(struct netbuf *buf, void *dataptr,
u16_t len, u16_t offset); u16_t len, u16_t offset);
struct ip_addr * netbuf_fromaddr (struct netbuf *buf);
u16_t netbuf_fromport (struct netbuf *buf); #define netbuf_copy(buf,dataptr,len) netbuf_copy_partial(buf, dataptr, len, 0)
#define netbuf_len(buf) ((buf)->p->tot_len)
#define netbuf_fromaddr(buf) ((buf)->addr)
#define netbuf_fromport(buf) ((buf)->port)
/* Network connection functions: */ /* Network connection functions: */
struct netconn * netconn_new (enum netconn_type type); struct netconn * netconn_new (enum netconn_type type);
@ -154,6 +155,8 @@ err_t netconn_disconnect (struct netconn *conn);
err_t netconn_listen (struct netconn *conn); err_t netconn_listen (struct netconn *conn);
struct netconn * netconn_accept (struct netconn *conn); struct netconn * netconn_accept (struct netconn *conn);
struct netbuf * netconn_recv (struct netconn *conn); struct netbuf * netconn_recv (struct netconn *conn);
err_t netconn_sendto (struct netconn *conn,
struct netbuf *buf, struct ip_addr *addr, u16_t port);
err_t netconn_send (struct netconn *conn, err_t netconn_send (struct netconn *conn,
struct netbuf *buf); struct netbuf *buf);
err_t netconn_write (struct netconn *conn, err_t netconn_write (struct netconn *conn,

View File

@ -71,6 +71,7 @@ struct api_msg_msg {
enum netconn_type conntype; enum netconn_type conntype;
union { union {
struct pbuf *p; struct pbuf *p;
struct netbuf *b;
struct { struct {
struct ip_addr *ipaddr; struct ip_addr *ipaddr;
u16_t port; u16_t port;