diff --git a/src/api/sockets.c b/src/api/sockets.c
index 53c58ea4..caf3f182 100644
--- a/src/api/sockets.c
+++ b/src/api/sockets.c
@@ -1213,6 +1213,22 @@ lwip_recvfrom_udp_raw(struct lwip_sock *sock, int flags, struct msghdr *msg, u16
           msg->msg_flags |= MSG_CTRUNC;
         }
 #endif /* LWIP_IPV4 */
+      } else if (IP_IS_V6(&buf->toaddr)) {
+#if LWIP_IPV6
+        if (msg->msg_controllen >= CMSG_SPACE(sizeof(struct in6_pktinfo))) {
+          struct cmsghdr *chdr = CMSG_FIRSTHDR(msg); /* This will always return a header!! */
+          struct in6_pktinfo *pkti = (struct in6_pktinfo *)CMSG_DATA(chdr);
+          chdr->cmsg_level = IPPROTO_IPV6;
+          chdr->cmsg_type = IPV6_PKTINFO;
+          chdr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+          pkti->ipi6_ifindex = buf->p->if_idx;
+          inet6_addr_from_ip6addr(&pkti->ipi6_addr, ip_2_ip6(netbuf_destaddr(buf)));
+          msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
+          wrote_msg = 1;
+        } else {
+          msg->msg_flags |= MSG_CTRUNC;
+        }
+#endif /* LWIP_IPV6 */
       }
     }
 #endif /* LWIP_NETBUF_RECVINFO */
@@ -3649,6 +3665,16 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
           LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IPV6, IPV6_V6ONLY, ..) -> %d\n",
                                       s, (netconn_get_ipv6only(sock->conn) ? 1 : 0)));
           break;
+#if LWIP_NETBUF_RECVINFO
+        case IPV6_RECVPKTINFO:
+          LWIP_SOCKOPT_CHECK_OPTLEN_CONN_PCB_TYPE(sock, optlen, int, NETCONN_UDP);
+          if (*(const int *)optval) {
+            sock->conn->flags |= NETCONN_FLAG_PKTINFO;
+          } else {
+            sock->conn->flags &= ~NETCONN_FLAG_PKTINFO;
+          }
+          break;
+#endif /* LWIP_NETBUF_RECVINFO */
 #if LWIP_IPV6_MLD
         case IPV6_JOIN_GROUP:
         case IPV6_LEAVE_GROUP: {
diff --git a/src/include/lwip/sockets.h b/src/include/lwip/sockets.h
index b6f3d524..fd58027d 100644
--- a/src/include/lwip/sockets.h
+++ b/src/include/lwip/sockets.h
@@ -298,6 +298,8 @@ struct linger {
  */
 #define IPV6_CHECKSUM       7  /* RFC3542: calculate and insert the ICMPv6 checksum for raw sockets. */
 #define IPV6_V6ONLY         27 /* RFC3493: boolean control to restrict AF_INET6 sockets to IPv6 communications only. */
+#define IPV6_RECVPKTINFO    49 /* RFC3542: enables the receiving of ancillary data via setsockopt() */
+#define IPV6_PKTINFO        50 /* RFC3542: ancillary data in recvmsg() received */
 #endif /* LWIP_IPV6 */
 
 #if LWIP_UDP && LWIP_UDPLITE
@@ -338,6 +340,13 @@ struct in_pktinfo {
 };
 #endif /* LWIP_IPV4 */
 
+#if LWIP_IPV6
+struct in6_pktinfo {
+  unsigned int    ipi6_ifindex;  /* Interface index */
+  struct in6_addr ipi6_addr;     /* Destination (from header) address */
+};
+#endif /* LWIP_IPV6 */
+
 #if LWIP_IPV6_MLD
 /*
  * Options and types related to IPv6 multicast membership
diff --git a/test/unit/api/test_sockets.c b/test/unit/api/test_sockets.c
index 3faa5ff9..01c6d6d7 100644
--- a/test/unit/api/test_sockets.c
+++ b/test/unit/api/test_sockets.c
@@ -10,6 +10,7 @@
 #include "lwip/priv/tcp_priv.h"
 #include "lwip/api.h"
 
+#define MAX(a,b) (((a) > (b)) ? (a) : (b))
 
 static int
 test_sockets_get_used_count(void)
@@ -255,7 +256,7 @@ static void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes)
   /* note: this modifies the underyling iov_base and iov_len for a partial
      read for an individual vector. This updates the msg->msg_iov pointer
      to skip fully consumed vectors */
-  
+
   /* process fully consumed vectors */
   for (i = 0; i < msg->msg_iovlen; i++) {
     if (msg->msg_iov[i].iov_len <= bytes) {
@@ -395,7 +396,7 @@ static void test_sockets_msgapi_tcp(int domain)
       /* note: since we always receive after sending, there will be open
          space in the send buffer */
       fail_unless(ret > 0);
-    
+
       bytes_written += ret;
       if (bytes_written < TOTAL_DATA_SZ) {
         test_sockets_msgapi_update_iovs(&smsg, (size_t)ret);
@@ -432,7 +433,7 @@ static void test_sockets_msgapi_tcp(int domain)
       }
     } while(ret > 0);
   }
-  
+
   ret = lwip_close(s1);
   fail_unless(ret == 0);
   ret = lwip_close(s2);
@@ -544,7 +545,6 @@ static void test_sockets_msgapi_udp(int domain)
   fail_unless(ret == 0);
 }
 
-#if LWIP_IPV4
 static void test_sockets_msgapi_cmsg(int domain)
 {
   int s, ret, enable;
@@ -553,10 +553,10 @@ static void test_sockets_msgapi_cmsg(int domain)
   struct iovec iov;
   struct msghdr msg;
   struct cmsghdr *cmsg;
-  struct in_pktinfo *pktinfo;
   u8_t rcv_buf[4];
   u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
-  u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
+  u8_t cmsg_buf[CMSG_SPACE(MAX(sizeof(struct in_pktinfo),
+                               sizeof(struct in6_pktinfo)))];
 
   test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
 
@@ -571,7 +571,15 @@ static void test_sockets_msgapi_cmsg(int domain)
   fail_unless(ret == 0);
 
   enable = 1;
-  ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
+  if (domain == AF_INET) {
+#if LWIP_IPV4
+    ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
+#endif
+  } else {
+#if LWIP_IPV6
+    ret = lwip_setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &enable, sizeof(enable));
+#endif
+  }
   fail_unless(ret == 0);
 
   /* Receive full message, including control message */
@@ -588,25 +596,42 @@ static void test_sockets_msgapi_cmsg(int domain)
   memset(rcv_buf, 0, sizeof(rcv_buf));
   ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
   fail_unless(ret == sizeof(snd_buf));
-  
+
   tcpip_thread_poll_one();
 
   ret = lwip_recvmsg(s, &msg, 0);
   fail_unless(ret == sizeof(rcv_buf));
   fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
-  
+
   /* Verify message header */
   cmsg = CMSG_FIRSTHDR(&msg);
   fail_unless(cmsg != NULL);
   fail_unless(cmsg->cmsg_len > 0);
-  fail_unless(cmsg->cmsg_level == IPPROTO_IP);
-  fail_unless(cmsg->cmsg_type == IP_PKTINFO);
 
-  /* Verify message data */
-  pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
-  /* We only have loopback interface enabled */
-  fail_unless(pktinfo->ipi_ifindex == 1);
-  fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK));
+  if (domain == AF_INET) {
+    struct in_pktinfo *pktinfo;
+
+    fail_unless(cmsg->cmsg_level == IPPROTO_IP);
+    fail_unless(cmsg->cmsg_type == IP_PKTINFO);
+
+    /* Verify message data */
+    pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
+    /* We only have loopback interface enabled */
+    fail_unless(pktinfo->ipi_ifindex == 1);
+    fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK));
+  } else {
+    struct in6_pktinfo *pktinfo;
+    struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
+
+    fail_unless(cmsg->cmsg_level == IPPROTO_IPV6);
+    fail_unless(cmsg->cmsg_type == IPV6_PKTINFO);
+
+    /* Verify message data */
+    pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+    /* We only have loopback interface enabled */
+    fail_unless(pktinfo->ipi6_ifindex == 1);
+    fail_unless(!memcmp(&pktinfo->ipi6_addr, &lo6, sizeof(pktinfo->ipi6_addr)));
+  }
 
   /* Verify there are no additional messages */
   cmsg = CMSG_NXTHDR(&msg, cmsg);
@@ -632,7 +657,6 @@ static void test_sockets_msgapi_cmsg(int domain)
   ret = lwip_close(s);
   fail_unless(ret == 0);
 }
-#endif /* LWIP_IPV4 */
 
 START_TEST(test_sockets_msgapis)
 {
@@ -645,6 +669,7 @@ START_TEST(test_sockets_msgapis)
 #if LWIP_IPV6
   test_sockets_msgapi_udp(AF_INET6);
   test_sockets_msgapi_tcp(AF_INET6);
+  test_sockets_msgapi_cmsg(AF_INET6);
 #endif
 }
 END_TEST
