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
+ lpcb = tcp_listen_dual_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
+#else /* TCP_LISTEN_BACKLOG */
+ lpcb = tcp_listen_dual(msg->conn->pcb.tcp);
+#endif /* TCP_LISTEN_BACKLOG */
+ } else
+#endif /* LWIP_IPV6 */
+ {
#if TCP_LISTEN_BACKLOG
- struct tcp_pcb* lpcb = tcp_listen_with_backlog(msg->conn->pcb.tcp, msg->msg.lb.backlog);
+ lpcb = tcp_listen_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(msg->conn->pcb.tcp);
#endif /* TCP_LISTEN_BACKLOG */
+ }
if (lpcb == NULL) {
/* in this case, the old pcb is still allocated */
msg->err = ERR_MEM;
} /* 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;
+ }
+ 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:
} /* 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:
} /* 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;
+ }
+ 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:
} /* 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:
/** 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 */
#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. */
#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