Merge branch 'master' of git.sv.gnu.org:/srv/git/lwip

This commit is contained in:
goldsimon 2012-08-13 20:57:55 +02:00
commit 847845027f
5 changed files with 117 additions and 6 deletions

View File

@ -1076,11 +1076,23 @@ lwip_netconn_do_listen(struct api_msg_msg *msg)
if (msg->conn->pcb.tcp != NULL) {
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
if (msg->conn->state == NETCONN_NONE) {
struct tcp_pcb* lpcb;
#if LWIP_IPV6
if ((msg->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) == 0) {
#if TCP_LISTEN_BACKLOG
struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
lpcb = tcp_listen_dual_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
#else /* TCP_LISTEN_BACKLOG */
struct tcp_pcb* lpcb = tcp_listen(msg->conn->pcb.tcp);
lpcb = tcp_listen_dual(msg->conn->pcb.tcp);
#endif /* TCP_LISTEN_BACKLOG */
} else
#endif /* LWIP_IPV6 */
{
#if TCP_LISTEN_BACKLOG
lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
#else /* TCP_LISTEN_BACKLOG */
lpcb = tcp_listen(msg->conn->pcb.tcp);
#endif /* TCP_LISTEN_BACKLOG */
}
if (lpcb == NULL) {
/* in this case, the old pcb is still allocated */
msg->err = ERR_MEM;

View File

@ -1664,6 +1664,27 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
} /* switch (optname) */
break;
#endif /* LWIP_TCP */
#if LWIP_IPV6
/* Level: IPPROTO_IPV6 */
case IPPROTO_IPV6:
switch (optname) {
case IPV6_V6ONLY:
if (*optlen < sizeof(int)) {
err = EINVAL;
}
/* @todo: this does not work for datagram sockets, yet */
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP)
return 0;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
@ -1902,6 +1923,23 @@ lwip_getsockopt_internal(void *arg)
} /* switch (optname) */
break;
#endif /* LWIP_TCP */
#if LWIP_IPV6
/* Level: IPPROTO_IPV6 */
case IPPROTO_IPV6:
switch (optname) {
case IPV6_V6ONLY:
*(int*)optval = ((sock->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) ? 1 : 0);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY) = %d\n",
s, *(int *)optval));
break;
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
@ -2081,6 +2119,29 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
} /* switch (optname) */
break;
#endif /* LWIP_TCP */
#if LWIP_IPV6
/* Level: IPPROTO_IPV6 */
case IPPROTO_IPV6:
switch (optname) {
case IPV6_V6ONLY:
if (optlen < sizeof(int)) {
err = EINVAL;
}
/* @todo: this does not work for datagram sockets, yet */
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP)
return 0;
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
@ -2310,6 +2371,27 @@ lwip_setsockopt_internal(void *arg)
} /* switch (optname) */
break;
#endif /* LWIP_TCP*/
#if LWIP_IPV6
/* Level: IPPROTO_IPV6 */
case IPPROTO_IPV6:
switch (optname) {
case IPV6_V6ONLY:
if (*(int*)optval) {
sock->conn->flags |= NETCONN_FLAG_IPV6_V6ONLY;
} else {
sock->conn->flags &= ~NETCONN_FLAG_IPV6_V6ONLY;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
s, ((sock->conn->flags & NETCONN_FLAG_IPV6_V6ONLY) ? 1 : 0)));
break;
default:
LWIP_ASSERT("unhandled optname", 0);
break;
} /* switch (optname) */
break;
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:

View File

@ -591,11 +591,12 @@ tcp_listen_dual_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
{
struct tcp_pcb *lpcb;
if (!ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
return NULL;
}
lpcb = tcp_listen_with_backlog(pcb, backlog);
if (lpcb != NULL) {
if ((lpcb != NULL) &&
ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
/* The default behavior is to accept connections on either
* IPv4 or IPv6, if not bound. */
/* @see NETCONN_FLAG_IPV6_V6ONLY for changing this behavior */
((struct tcp_pcb_listen*)lpcb)->accept_any_ip_version = 1;
}
return lpcb;

View File

@ -73,6 +73,12 @@ extern "C" {
/** If a nonblocking write has been rejected before, poll_tcp needs to
check if the netconn is writable again */
#define NETCONN_FLAG_CHECK_WRITESPACE 0x10
#if LWIP_IPV6
/** If this flag is set then only IPv6 communication is allowed on the
netconn. As per RFC#3493 this features defaults to OFF allowing
dual-stack usage by default. */
#define NETCONN_FLAG_IPV6_V6ONLY 0x20
#endif /* LWIP_IPV6 */
/* Helpers to process several netconn_types by the same code */

View File

@ -148,6 +148,9 @@ struct linger {
#define IPPROTO_IP 0
#define IPPROTO_TCP 6
#define IPPROTO_UDP 17
#if LWIP_IPV6
#define IPPROTO_IPV6 41
#endif /* LWIP_IPV6 */
#define IPPROTO_UDPLITE 136
/* Flags we can use with send and recv. */
@ -175,6 +178,13 @@ struct linger {
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */
#endif /* LWIP_TCP */
#if LWIP_IPV6
/*
* Options for level IPPROTO_IPV6
*/
#define IPV6_V6ONLY 27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
#endif /* LWIP_IPV6 */
#if LWIP_UDP && LWIP_UDPLITE
/*
* Options for level IPPROTO_UDPLITE