- fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can be used to revert to the old 'winsock' style behaviour);

- Fixed implementation of SO_ACCEPTCONN to just look at the pcb state;
- cleaned up the SO/SOF defines (only 3 left a ip_pcb level);
This commit is contained in:
sg 2014-12-10 21:46:49 +01:00
parent 8e13bcd43d
commit 7ca4fd817e
7 changed files with 129 additions and 61 deletions

View File

@ -143,6 +143,12 @@ HISTORY
++ Bugfixes:
2014-12-10: Simon Goldschmidt
* sockets.c, tcp.c, others: fixed bug #43797 set/getsockopt: SO_SNDTIMEO/SO_RCVTIMEO
take int as option but should take timeval (LWIP_SO_SNDRCVTIMEO_STANDARD==0 can
be used to revert to the old 'winsock' style behaviour)
Fixed implementation of SO_ACCEPTCONN to just look at the pcb state
2014-12-09: Simon Goldschmidt
* ip4.c: fixed bug #43596 IGMP queries from 0.0.0.0 are discarded

View File

@ -1536,7 +1536,7 @@ lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
int
lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
err_t err = ERR_OK;
u8_t err = 0;
struct lwip_sock *sock = get_socket(s);
LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
@ -1563,12 +1563,6 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
case SO_ERROR:
case SO_KEEPALIVE:
/* UNIMPL case SO_CONTIMEO: */
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
case SO_RCVBUF:
#endif /* LWIP_SO_RCVBUF */
@ -1586,6 +1580,24 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
err = EINVAL;
}
break;
#if LWIP_SO_SNDTIMEO || LWIP_SO_RCVTIMEO
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
if (*optlen <
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
sizeof(int)
#else /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
sizeof(struct timeval)
#endif /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD*/
) {
err = EINVAL;
}
break;
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_RCVTIMEO */
case SO_NO_CHECK:
if (*optlen < sizeof(int)) {
@ -1746,7 +1758,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
} /* switch */
if (err != ERR_OK) {
if (err != 0) {
sock_set_errno(sock, err);
return -1;
}
@ -1811,8 +1823,19 @@ lwip_getsockopt_internal(void *arg)
case SOL_SOCKET:
switch (optname) {
/* The option flags */
case SO_ACCEPTCONN:
if (NETCONNTYPE_GROUP(sock->conn->type) == NETCONN_TCP) {
if ((sock->conn->pcb.tcp != NULL) && (sock->conn->pcb.tcp->state == LISTEN)) {
*(int*)optval = 1;
} else {
*(int*)optval = 0;
}
} else {
data->err = ENOPROTOOPT;
}
break;
/* The option flags */
case SO_BROADCAST:
/* UNIMPL case SO_DEBUG: */
/* UNIMPL case SO_DONTROUTE: */
@ -1862,12 +1885,28 @@ lwip_getsockopt_internal(void *arg)
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
*(int *)optval = netconn_get_sendtimeout(sock->conn);
{
s32_t val = netconn_get_sendtimeout(sock->conn);
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
*(int *)optval = val;
#else /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
((struct timeval *)optval)->tv_sec = val / 1000U;
((struct timeval *)optval)->tv_sec = (val % 1000U) * 1000U;
#endif /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
}
break;
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
*(int *)optval = netconn_get_recvtimeout(sock->conn);
{
s32_t val = netconn_get_recvtimeout(sock->conn);
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
*(int *)optval = (int)val;
#else /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
((struct timeval *)optval)->tv_sec = val / 1000U;
((struct timeval *)optval)->tv_sec = (val % 1000U) * 1000U;
#endif /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
}
break;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
@ -2033,7 +2072,7 @@ int
lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
{
struct lwip_sock *sock = get_socket(s);
err_t err = ERR_OK;
u8_t err = 0;
LWIP_SETGETSOCKOPT_DATA_VAR_DECLARE(data);
if (!sock) {
@ -2057,12 +2096,6 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
/* UNIMPL case SO_DONTROUTE: */
case SO_KEEPALIVE:
/* UNIMPL case case SO_CONTIMEO: */
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
case SO_RCVBUF:
#endif /* LWIP_SO_RCVBUF */
@ -2079,6 +2112,24 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
err = EINVAL;
}
break;
#if LWIP_SO_SNDTIMEO || LWIP_SO_RCVTIMEO
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
#endif /* LWIP_SO_RCVTIMEO */
if (optlen <
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
sizeof(int)
#else /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
sizeof(struct timeval)
#endif /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD*/
) {
err = EINVAL;
}
break;
#endif /* LWIP_SO_SNDTIMEO || LWIP_SO_RCVTIMEO */
case SO_NO_CHECK:
if (optlen < sizeof(int)) {
err = EINVAL;
@ -2269,7 +2320,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
} /* switch (level) */
if (err != ERR_OK) {
if (err != 0) {
sock_set_errno(sock, err);
return -1;
}
@ -2356,12 +2407,28 @@ lwip_setsockopt_internal(void *arg)
break;
#if LWIP_SO_SNDTIMEO
case SO_SNDTIMEO:
netconn_set_sendtimeout(sock->conn, (s32_t)*(int*)optval);
{
s32_t val;
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
val = (s32_t)*(int*)optval;
#else /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
val = (((struct timeval *)optval)->tv_sec * 1000U) + (((struct timeval *)optval)->tv_usec / 1000U);
#endif /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
netconn_set_sendtimeout(sock->conn, val);
}
break;
#endif /* LWIP_SO_SNDTIMEO */
#if LWIP_SO_RCVTIMEO
case SO_RCVTIMEO:
netconn_set_recvtimeout(sock->conn, *(int*)optval);
{
s32_t val;
#if LWIP_SO_SNDRCVTIMEO_NONSTANDARD
val = (s32_t)*(int*)optval;
#else /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
val = (((struct timeval *)optval)->tv_sec * 1000U) + (((struct timeval *)optval)->tv_usec / 1000U);
#endif /* LWIP_SO_SNDRCVTIMEO_NONSTANDARD */
netconn_set_recvtimeout(sock->conn, (int)val);
}
break;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
@ -2415,17 +2482,18 @@ lwip_setsockopt_internal(void *arg)
case IP_DROP_MEMBERSHIP:
{
/* If this is a TCP or a RAW socket, ignore these options. */
err_t err;
struct ip_mreq *imr = (struct ip_mreq *)optval;
ip_addr_t if_addr;
ip_addr_t multi_addr;
inet_addr_to_ipaddr(&if_addr, &imr->imr_interface);
inet_addr_to_ipaddr(&multi_addr, &imr->imr_multiaddr);
if(optname == IP_ADD_MEMBERSHIP){
data->err = igmp_joingroup(&if_addr, &multi_addr);
err = igmp_joingroup(&if_addr, &multi_addr);
} else {
data->err = igmp_leavegroup(&if_addr, &multi_addr);
err = igmp_leavegroup(&if_addr, &multi_addr);
}
if(data->err != ERR_OK) {
if(err != ERR_OK) {
data->err = EADDRNOTAVAIL;
}
}

View File

@ -213,9 +213,6 @@
#endif /* LWIP_NETCONN && LWIP_TCP */
#if LWIP_SOCKET
/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
#if SO_ACCEPTCONN != SOF_ACCEPTCONN
#error "SO_ACCEPTCONN != SOF_ACCEPTCONN"
#endif
#if SO_REUSEADDR != SOF_REUSEADDR
#error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
#endif
@ -225,9 +222,6 @@
#if SO_BROADCAST != SOF_BROADCAST
#error "WARNING: SO_BROADCAST != SOF_BROADCAST"
#endif
#if SO_LINGER != SOF_LINGER
#error "WARNING: SO_LINGER != SOF_LINGER"
#endif
#endif /* LWIP_SOCKET */

View File

@ -563,7 +563,6 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
lpcb->state = LISTEN;
lpcb->prio = pcb->prio;
lpcb->so_options = pcb->so_options;
ip_set_option(lpcb, SOF_ACCEPTCONN);
lpcb->ttl = pcb->ttl;
lpcb->tos = pcb->tos;
#if LWIP_IPV6

View File

@ -98,21 +98,14 @@ struct ip_pcb {
};
/*
* Option flags per-socket. These are the same like SO_XXX.
* Option flags per-socket. These are the same like SO_XXX in sockets.h
*/
/*#define SOF_DEBUG 0x01U Unimplemented: turn on debugging info recording */
#define SOF_ACCEPTCONN 0x02U /* socket has had listen() */
#define SOF_REUSEADDR 0x04U /* allow local address reuse */
#define SOF_KEEPALIVE 0x08U /* keep connections alive */
/*#define SOF_DONTROUTE 0x10U Unimplemented: just use interface addresses */
#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
/*#define SOF_USELOOPBACK 0x40U Unimplemented: bypass hardware when possible */
#define SOF_LINGER 0x80U /* linger on close if data present */
/*#define SOF_OOBINLINE 0x0100U Unimplemented: leave received OOB data in line */
/*#define SOF_REUSEPORT 0x0200U Unimplemented: allow local address & port reuse */
/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */
#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE|SOF_LINGER/*|SOF_DEBUG|SOF_DONTROUTE|SOF_OOBINLINE*/)
#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE)
/* Global variables of this module, kept in a struct for efficient access using base+index. */
struct ip_globals

View File

@ -1548,6 +1548,14 @@
#define LWIP_SO_RCVTIMEO 0
#endif
/**
* LWIP_SO_SNDRCVTIMEO_NONSTANDARD==1: SO_RCVTIMEO/SO_SNDTIMEO take an int
* (milliseconds, much like winsock does) instead of a struct timeval (default).
*/
#ifndef LWIP_SO_SNDRCVTIMEO_NONSTANDARD
#define LWIP_SO_SNDRCVTIMEO_NONSTANDARD 0
#endif
/**
* LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing.
*/

View File

@ -142,22 +142,22 @@ struct lwip_setgetsockopt_data {
/*
* Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c)
*/
#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_REUSEADDR 0x0004 /* Allow local address reuse */
#define SO_KEEPALIVE 0x0008 /* keep connections alive */
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */
#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */
#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */
#define SO_DONTLINGER ((int)(~SO_LINGER))
/*
* Additional options, not kept in so_options.
*/
#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */
#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */
#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_DONTLINGER ((int)(~SO_LINGER))
#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */
#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */
#define SO_RCVBUF 0x1002 /* receive buffer size */
#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */