From 411cb39eb4f0de2ac2b0e383525b7718b8bc909f Mon Sep 17 00:00:00 2001 From: fbernon Date: Wed, 10 Dec 2008 21:36:44 +0000 Subject: [PATCH] sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and port uses deleted netbuf. --- CHANGELOG | 10 +++-- src/api/sockets.c | 97 ++++++++++++++++++++++++----------------------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index dabb32ac..34b1baa2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,7 +26,7 @@ HISTORY 2008-10-02 Jonathan Larmour and Rishi Khan * sockets.c (lwip_accept): Return EWOULDBLOCK if would block on non-blocking - socket. + socket. 2008-06-30 Simon Goldschmidt * mem.c, opt.h, stats.h: fixed bug #21433: Calling mem_free/pbuf_free from @@ -56,6 +56,10 @@ HISTORY ++ Bugfixes: + 2008-12-10 Tamas Somogyi, Frédéric Bernon + * sockets.c: fixed bug #25051: lwip_recvfrom problem with udp: fromaddr and + port uses deleted netbuf. + 2008-10-18 Simon Goldschmidt * tcp_in.c: fixed bug ##24596: Vulnerability on faulty TCP options length in tcp_parseopt @@ -69,11 +73,11 @@ HISTORY 2008-10-02 Jonathan Larmour * dns.c: Hard-code structure sizes, to avoid issues on some compilers where - padding is included. + padding is included. 2008-09-30 Jonathan Larmour * sockets.c (lwip_accept): check addr isn't NULL. If it's valid, do an - assertion check that addrlen isn't NULL. + assertion check that addrlen isn't NULL. 2008-09-30 Jonathan Larmour * tcp.c: Fix bug #24227, wrong error message in tcp_bind. diff --git a/src/api/sockets.c b/src/api/sockets.c index a03fe0de..2dade4a5 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -530,19 +530,66 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, if (netconn_type(sock->conn) == NETCONN_TCP) { len -= copylen; - if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent) { + if ( (len <= 0) || (buf->p->flags & PBUF_FLAG_PUSH) || !sock->rcvevent || ((flags & MSG_PEEK)!=0)) { done = 1; } } else { done = 1; } + /* Check to see from where the data was.*/ + if (done) { + if (from && fromlen) { + struct sockaddr_in sin; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = (struct ip_addr*)&(sin.sin_addr.s_addr); + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr(buf); + port = netbuf_fromport(buf); + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = addr->addr; + + if (*fromlen > sizeof(sin)) { + *fromlen = sizeof(sin); + } + + SMEMCPY(from, &sin, *fromlen); + + 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, off)); + } else { + #if SOCKETS_DEBUG + struct sockaddr_in sin; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + addr = (struct ip_addr*)&(sin.sin_addr.s_addr); + netconn_getaddr(sock->conn, addr, &port, 0); + } else { + addr = netbuf_fromaddr(buf); + port = netbuf_fromport(buf); + } + + 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, off)); + #endif /* SOCKETS_DEBUG */ + } + } + /* If we don't peek the incoming message... */ if ((flags & MSG_PEEK)==0) { /* If this is a TCP socket, check if there is data left in the buffer. If so, it should be saved in the sock structure for next time around. */ - if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) { + if ((netconn_type(sock->conn) == NETCONN_TCP) && (buflen - copylen > 0)) { sock->lastdata = buf; sock->lastoffset += copylen; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", (void*)buf)); @@ -552,55 +599,9 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", (void*)buf)); netbuf_delete(buf); } - } else { - done = 1; } } while (!done); - /* Check to see from where the data was.*/ - if (from && fromlen) { - struct sockaddr_in sin; - - if (netconn_type(sock->conn) == NETCONN_TCP) { - addr = (struct ip_addr*)&(sin.sin_addr.s_addr); - netconn_getaddr(sock->conn, addr, &port, 0); - } else { - addr = netbuf_fromaddr(buf); - port = netbuf_fromport(buf); - } - - memset(&sin, 0, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - sin.sin_addr.s_addr = addr->addr; - - if (*fromlen > sizeof(sin)) - *fromlen = sizeof(sin); - - SMEMCPY(from, &sin, *fromlen); - - 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, off)); - } else { -#if SOCKETS_DEBUG - struct sockaddr_in sin; - - if (netconn_type(sock->conn) == NETCONN_TCP) { - addr = (struct ip_addr*)&(sin.sin_addr.s_addr); - netconn_getaddr(sock->conn, addr, &port, 0); - } else { - addr = netbuf_fromaddr(buf); - port = netbuf_fromport(buf); - } - - 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, off)); -#endif /* SOCKETS_DEBUG */ - } - sock_set_errno(sock, 0); return off; }