• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "test_sockets.h"
2 
3 #include "lwip/mem.h"
4 #include "lwip/opt.h"
5 #include "lwip/sockets.h"
6 #include "lwip/priv/sockets_priv.h"
7 #include "lwip/stats.h"
8 
9 #include "lwip/tcpip.h"
10 #include "lwip/priv/tcp_priv.h"
11 #include "lwip/api.h"
12 
13 
14 static int
test_sockets_get_used_count(void)15 test_sockets_get_used_count(void)
16 {
17   int used = 0;
18   int i;
19 
20   for (i = 0; i < NUM_SOCKETS; i++) {
21     struct lwip_sock* s = lwip_socket_dbg_get_socket(i);
22     if (s != NULL) {
23       if (s->fd_used) {
24         used++;
25       }
26     }
27   }
28   return used;
29 }
30 
31 
32 /* Setups/teardown functions */
33 
34 static void
sockets_setup(void)35 sockets_setup(void)
36 {
37   /* expect full free heap */
38   lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
39 }
40 
41 static void
sockets_teardown(void)42 sockets_teardown(void)
43 {
44   fail_unless(test_sockets_get_used_count() == 0);
45   /* poll until all memory is released... */
46   tcpip_thread_poll_one();
47   while (tcp_tw_pcbs) {
48     tcp_abort(tcp_tw_pcbs);
49     tcpip_thread_poll_one();
50   }
51   tcpip_thread_poll_one();
52   /* ensure full free heap */
53   lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
54 }
55 
56 #ifndef NUM_SOCKETS
57 #define NUM_SOCKETS MEMP_NUM_NETCONN
58 #endif
59 
60 #if LWIP_SOCKET
61 static int
test_sockets_alloc_socket_nonblocking(int domain,int type)62 test_sockets_alloc_socket_nonblocking(int domain, int type)
63 {
64   int s = lwip_socket(domain, type, 0);
65   if (s >= 0) {
66     int ret = lwip_fcntl(s, F_SETFL, O_NONBLOCK);
67     fail_unless(ret == 0);
68   }
69   return s;
70 }
71 
72 /* Verify basic sockets functionality
73  */
START_TEST(test_sockets_basics)74 START_TEST(test_sockets_basics)
75 {
76   int s, i, ret;
77   int s2[NUM_SOCKETS];
78   LWIP_UNUSED_ARG(_i);
79 
80   s = lwip_socket(AF_INET, SOCK_STREAM, 0);
81   fail_unless(s >= 0);
82   lwip_close(s);
83 
84   for (i = 0; i < NUM_SOCKETS; i++) {
85     s2[i] = lwip_socket(AF_INET, SOCK_STREAM, 0);
86     fail_unless(s2[i] >= 0);
87   }
88 
89   /* all sockets used, now it should fail */
90   s = lwip_socket(AF_INET, SOCK_STREAM, 0);
91   fail_unless(s == -1);
92   /* close one socket */
93   ret = lwip_close(s2[0]);
94   fail_unless(ret == 0);
95   /* now it should succeed */
96   s2[0] = lwip_socket(AF_INET, SOCK_STREAM, 0);
97   fail_unless(s2[0] >= 0);
98 
99   /* close all sockets */
100   for (i = 0; i < NUM_SOCKETS; i++) {
101     ret = lwip_close(s2[i]);
102     fail_unless(ret == 0);
103   }
104 }
105 END_TEST
106 
test_sockets_allfunctions_basic_domain(int domain)107 static void test_sockets_allfunctions_basic_domain(int domain)
108 {
109   int s, s2, s3, ret;
110   struct sockaddr_storage addr, addr2;
111   socklen_t addrlen, addr2len;
112   char buf[4];
113   /* listen socket */
114   s = lwip_socket(domain, SOCK_STREAM, 0);
115   fail_unless(s >= 0);
116 
117   ret = lwip_listen(s, 0);
118   fail_unless(ret == 0);
119 
120   addrlen = sizeof(addr);
121   ret = lwip_getsockname(s, (struct sockaddr*)&addr, &addrlen);
122   fail_unless(ret == 0);
123 
124   s2 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
125   fail_unless(s2 >= 0);
126   /* nonblocking connect s2 to s (but use loopback address) */
127   if (domain == AF_INET) {
128 #if LWIP_IPV4
129     struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
130     addr4->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
131 #endif
132   } else {
133 #if LWIP_IPV6
134     struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
135     struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
136     addr6->sin6_addr = lo6;
137 #endif
138   }
139   ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
140   fail_unless(ret == -1);
141   fail_unless(errno == EINPROGRESS);
142   ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
143   fail_unless(ret == -1);
144   fail_unless(errno == EALREADY);
145 
146   while(tcpip_thread_poll_one());
147 
148   s3 = lwip_accept(s, (struct sockaddr*)&addr2, &addr2len);
149   fail_unless(s3 >= 0);
150 
151   ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
152   fail_unless(ret == -1);
153   fail_unless(errno == EISCONN);
154 
155   /* write from server to client */
156   ret = write(s3, "test", 4);
157   fail_unless(ret == 4);
158 
159   ret = lwip_shutdown(s3, SHUT_WR);
160   fail_unless(ret == 0);
161 
162   while(tcpip_thread_poll_one());
163 
164   ret = lwip_recv(s2, buf, 3, MSG_PEEK);
165   fail_unless(ret == 3);
166 
167   ret = lwip_recv(s2, buf, 3, MSG_PEEK);
168   fail_unless(ret == 3);
169 
170   ret = lwip_read(s2, buf, 4);
171   fail_unless(ret == 4);
172 
173   ret = lwip_read(s2, buf, 1);
174   fail_unless(ret == 0);
175 
176   ret = lwip_read(s2, buf, 1);
177   fail_unless(ret == -1);
178 
179   ret = lwip_write(s2, "foo", 3);
180   fail_unless(ret == 3);
181 
182   ret = lwip_close(s2);
183   fail_unless(ret == 0);
184 
185   while(tcpip_thread_poll_one());
186 
187   /* read one byte more than available to check handling FIN */
188   ret = lwip_read(s3, buf, 4);
189   fail_unless(ret == 3);
190 
191   ret = lwip_read(s3, buf, 1);
192   fail_unless(ret == 0);
193 
194   ret = lwip_read(s3, buf, 1);
195   fail_unless(ret == -1);
196 
197   while(tcpip_thread_poll_one());
198 
199   ret = lwip_close(s);
200   fail_unless(ret == 0);
201   ret = lwip_close(s3);
202   fail_unless(ret == 0);
203 }
204 
205 /* Try to step through all sockets functions once...
206  */
START_TEST(test_sockets_allfunctions_basic)207 START_TEST(test_sockets_allfunctions_basic)
208 {
209   LWIP_UNUSED_ARG(_i);
210 #if LWIP_IPV4
211   test_sockets_allfunctions_basic_domain(AF_INET);
212 #endif
213 #if LWIP_IPV6
214   test_sockets_allfunctions_basic_domain(AF_INET6);
215 #endif
216 }
217 END_TEST
218 
test_sockets_init_loopback_addr(int domain,struct sockaddr_storage * addr_st,socklen_t * sz)219 static void test_sockets_init_loopback_addr(int domain, struct sockaddr_storage *addr_st, socklen_t *sz)
220 {
221   memset(addr_st, 0, sizeof(*addr_st));
222   switch(domain) {
223 #if LWIP_IPV6
224     case AF_INET6: {
225       struct sockaddr_in6 *addr = (struct sockaddr_in6*)addr_st;
226       struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
227       addr->sin6_family = AF_INET6;
228       addr->sin6_port = 0; /* use ephemeral port */
229       addr->sin6_addr = lo6;
230       *sz = sizeof(*addr);
231    }
232       break;
233 #endif /* LWIP_IPV6 */
234 #if LWIP_IPV4
235     case AF_INET: {
236       struct sockaddr_in *addr = (struct sockaddr_in*)addr_st;
237       addr->sin_family = AF_INET;
238       addr->sin_port = 0; /* use ephemeral port */
239       addr->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
240       *sz = sizeof(*addr);
241     }
242       break;
243 #endif /* LWIP_IPV4 */
244     default:
245       *sz = 0;
246       fail();
247       break;
248   }
249 }
250 
test_sockets_msgapi_update_iovs(struct msghdr * msg,size_t bytes)251 static void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes)
252 {
253   int i;
254 
255   /* note: this modifies the underyling iov_base and iov_len for a partial
256      read for an individual vector. This updates the msg->msg_iov pointer
257      to skip fully consumed vecotrs */
258 
259   /* process fully consumed vectors */
260   for (i = 0; i < msg->msg_iovlen; i++) {
261     if (msg->msg_iov[i].iov_len <= bytes) {
262       /* reduce bytes by amount of this vector */
263       bytes -= msg->msg_iov[i].iov_len;
264     } else {
265       break; /* iov not fully consumed */
266     }
267   }
268 
269   /* slide down over fully consumed vectors */
270   msg->msg_iov = &msg->msg_iov[i];
271   msg->msg_iovlen -= i;
272 
273   /* update new first vector with any remaining amount */
274   msg->msg_iov[0].iov_base = ((u8_t *)msg->msg_iov[0].iov_base + bytes);
275   msg->msg_iov[0].iov_len -= bytes;
276 }
277 
test_sockets_msgapi_tcp(int domain)278 static void test_sockets_msgapi_tcp(int domain)
279 {
280   #define BUF_SZ          (TCP_SND_BUF/4)
281   #define TOTAL_DATA_SZ   (BUF_SZ*8) /* ~(TCP_SND_BUF*2) that accounts for integer rounding */
282   #define NEED_TRAILER    (BUF_SZ % 4 != 0)
283   int listnr, s1, s2, i, ret, opt;
284   int bytes_written, bytes_read;
285   struct sockaddr_storage addr_storage;
286   socklen_t addr_size;
287   struct iovec siovs[8];
288   struct msghdr smsg;
289   u8_t * snd_buf;
290   struct iovec riovs[5];
291   struct iovec riovs_tmp[5];
292   struct msghdr rmsg;
293   u8_t * rcv_buf;
294   int    rcv_off;
295   int    rcv_trailer = 0;
296   u8_t val;
297 
298   test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
299 
300   listnr = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
301   fail_unless(listnr >= 0);
302   s1 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
303   fail_unless(s1 >= 0);
304 
305   /* setup a listener socket on loopback with ephemeral port */
306   ret = lwip_bind(listnr, (struct sockaddr*)&addr_storage, addr_size);
307   fail_unless(ret == 0);
308   ret = lwip_listen(listnr, 0);
309   fail_unless(ret == 0);
310 
311   /* update address with ephemeral port */
312   ret = lwip_getsockname(listnr, (struct sockaddr*)&addr_storage, &addr_size);
313   fail_unless(ret == 0);
314 
315   /* connect, won't complete until we accept it */
316   ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size);
317   fail_unless(ret == -1);
318   fail_unless(errno == EINPROGRESS);
319 
320   while (tcpip_thread_poll_one());
321 
322   /* accept, creating the other side of the connection */
323   s2 = lwip_accept(listnr, NULL, NULL);
324   fail_unless(s2 >= 0);
325 
326   /* double check s1 is connected */
327   ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size);
328   fail_unless(ret == -1);
329   fail_unless(errno == EISCONN);
330 
331   /* set s2 to non-blocking, not inherited from listener */
332   opt = lwip_fcntl(s2, F_GETFL, 0);
333   fail_unless(opt == 6);
334   opt = O_NONBLOCK;
335   ret = lwip_fcntl(s2, F_SETFL, opt);
336   fail_unless(ret == 0);
337 
338   /* we are done with listener, close it */
339   ret = lwip_close(listnr);
340   fail_unless(ret == 0);
341 
342   /* allocate a buffer for a stream of incrementing hex (0x00..0xFF) which we will use
343      to create an input vector set that is larger than the TCP's send buffer. This will
344      force execution of the partial IO vector send case */
345   snd_buf = (u8_t*)mem_malloc(BUF_SZ);
346   val = 0x00;
347   fail_unless(snd_buf != NULL);
348   for (i = 0; i < BUF_SZ; i++,val++) {
349     snd_buf[i] = val;
350   }
351 
352   /* send the buffer 8 times in one message, equating to TOTAL_DATA_SZ */
353   for (i = 0; i < 8; i++) {
354     siovs[i].iov_base = snd_buf;
355     siovs[i].iov_len = BUF_SZ;
356   }
357 
358   /* allocate a receive buffer, same size as snd_buf for easy verification */
359   rcv_buf = (u8_t*)mem_calloc(1, BUF_SZ);
360   fail_unless(rcv_buf != NULL);
361   /* split across iovs */
362   for (i = 0; i < 4; i++) {
363     riovs[i].iov_base = &rcv_buf[i*(BUF_SZ/4)];
364     riovs[i].iov_len = BUF_SZ/4;
365   }
366   /* handling trailing bytes if buffer doesn't evenly divide by 4 */
367 #if NEED_TRAILER
368   if ((BUF_SZ % 4) != 0) {
369     riovs[5].iov_base = &rcv_buf[4*(BUF_SZ/4)];
370     riovs[5].iov_len = BUF_SZ - (4*(BUF_SZ/4));
371     rcv_trailer = 1;
372   }
373 #endif /* NEED_TRAILER */
374 
375   /* we use a copy of riovs since we'll be modifying base and len during
376      receiving. This gives us an easy way to reset the iovs for next recvmsg */
377   memcpy(riovs_tmp, riovs, sizeof(riovs));
378 
379   memset(&smsg, 0, sizeof(smsg));
380   smsg.msg_iov = siovs;
381   smsg.msg_iovlen = 8;
382 
383   memset(&rmsg, 0, sizeof(rmsg));
384   rmsg.msg_iov = riovs_tmp;
385   rmsg.msg_iovlen = (rcv_trailer ? 5 : 4);
386 
387   bytes_written = 0;
388   bytes_read = 0;
389   rcv_off = 0;
390 
391   while (bytes_written < TOTAL_DATA_SZ && (bytes_read < TOTAL_DATA_SZ)) {
392     /* send data */
393     if (bytes_written < TOTAL_DATA_SZ) {
394       ret = lwip_sendmsg(s1, &smsg, 0);
395       /* note: since we always receive after sending, there will be open
396          space in the send buffer */
397       fail_unless(ret > 0);
398 
399       bytes_written += ret;
400       if (bytes_written < TOTAL_DATA_SZ) {
401         test_sockets_msgapi_update_iovs(&smsg, (size_t)ret);
402       }
403     }
404 
405     while (tcpip_thread_poll_one());
406 
407     /* receive and verify data */
408     do {
409       if (bytes_read < TOTAL_DATA_SZ) {
410         ret = lwip_recvmsg(s2, &rmsg, 0);
411         fail_unless(ret > 0 || (ret == -1 && errno == EWOULDBLOCK));
412 
413         if (ret > 0) {
414           rcv_off += ret;
415           /* we have received a full buffer */
416           if (rcv_off == BUF_SZ) {
417             /* note: since iovs are just pointers, compare underlying buf */
418             fail_unless(!memcmp(snd_buf, rcv_buf, BUF_SZ));
419             bytes_read += BUF_SZ;
420             /* reset receive state for next buffer */
421             rcv_off = 0;
422             memset(rcv_buf, 0, BUF_SZ);
423             memcpy(riovs_tmp, riovs, sizeof(riovs));
424             rmsg.msg_iov = riovs_tmp;
425             rmsg.msg_iovlen = (rcv_trailer ? 5 : 4);
426           } else { /* partial read */
427             test_sockets_msgapi_update_iovs(&rmsg, (size_t)ret);
428           }
429         }
430       } else {
431         break;
432       }
433     } while(ret > 0);
434   }
435 
436   ret = lwip_close(s1);
437   fail_unless(ret == 0);
438   ret = lwip_close(s2);
439   fail_unless(ret == 0);
440   mem_free(snd_buf);
441   mem_free(rcv_buf);
442 }
443 
test_sockets_msgapi_udp_send_recv_loop(int s,struct msghdr * smsg,struct msghdr * rmsg)444 static void test_sockets_msgapi_udp_send_recv_loop(int s, struct msghdr *smsg, struct msghdr *rmsg)
445 {
446   int i, ret;
447 
448   /* send/receive our datagram of IO vectors 10 times */
449   for (i = 0; i < 10; i++) {
450     ret = lwip_sendmsg(s, smsg, 0);
451     fail_unless(ret == 4);
452 
453     while (tcpip_thread_poll_one());
454 
455     /* receive the datagram split across 4 buffers */
456     ret = lwip_recvmsg(s, rmsg, 0);
457     fail_unless(ret == 4);
458 
459     /* verify data */
460     fail_unless(*((u8_t*)rmsg->msg_iov[0].iov_base) == 0xDE);
461     fail_unless(*((u8_t*)rmsg->msg_iov[1].iov_base) == 0xAD);
462     fail_unless(*((u8_t*)rmsg->msg_iov[2].iov_base) == 0xBE);
463     fail_unless(*((u8_t*)rmsg->msg_iov[3].iov_base) == 0xEF);
464 
465     /* clear rcv_buf to ensure no data is being skipped */
466     *((u8_t*)rmsg->msg_iov[0].iov_base) = 0x00;
467     *((u8_t*)rmsg->msg_iov[1].iov_base) = 0x00;
468     *((u8_t*)rmsg->msg_iov[2].iov_base) = 0x00;
469     *((u8_t*)rmsg->msg_iov[3].iov_base) = 0x00;
470   }
471 }
472 
test_sockets_msgapi_udp(int domain)473 static void test_sockets_msgapi_udp(int domain)
474 {
475   int s, i, ret;
476   struct sockaddr_storage addr_storage;
477   socklen_t addr_size;
478   struct iovec riovs[4];
479   struct msghdr rmsg;
480   u8_t rcv_buf[4];
481   struct iovec siovs[4];
482   struct msghdr smsg;
483   u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
484 
485   /* initialize IO vectors with data */
486   for (i = 0; i < 4; i++) {
487     siovs[i].iov_base = &snd_buf[i];
488     siovs[i].iov_len = sizeof(u8_t);
489     riovs[i].iov_base = &rcv_buf[i];
490     riovs[i].iov_len = sizeof(u8_t);
491   }
492 
493   test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
494 
495   s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM);
496   fail_unless(s >= 0);
497 
498   ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size);
499   fail_unless(ret == 0);
500 
501   /* Update addr with epehermal port */
502   ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size);
503   fail_unless(ret == 0);
504   switch(domain) {
505 #if LWIP_IPV6
506     case AF_INET6:
507       fail_unless(addr_size == sizeof(struct sockaddr_in6));
508       break;
509 #endif /* LWIP_IPV6 */
510 #if LWIP_IPV4
511     case AF_INET:
512         fail_unless(addr_size == sizeof(struct sockaddr_in));
513         break;
514 #endif /* LWIP_IPV6 */
515     default:
516       fail();
517       break;
518   }
519 
520   /* send and receive the datagram in 4 pieces */
521   memset(&smsg, 0, sizeof(smsg));
522   smsg.msg_iov = siovs;
523   smsg.msg_iovlen = 4;
524   memset(&rmsg, 0, sizeof(rmsg));
525   rmsg.msg_iov = riovs;
526   rmsg.msg_iovlen = 4;
527 
528   /* perform a sendmsg with remote host (self) */
529   smsg.msg_name = &addr_storage;
530   smsg.msg_namelen = addr_size;
531 
532   test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg);
533 
534   /* Connect to self, allowing us to not pass message name */
535   ret = lwip_connect(s, (struct sockaddr*)&addr_storage, addr_size);
536   fail_unless(ret == 0);
537 
538   smsg.msg_name = NULL;
539   smsg.msg_namelen = 0;
540 
541   test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg);
542 
543   ret = lwip_close(s);
544   fail_unless(ret == 0);
545 }
546 
547 #if LWIP_IPV4
test_sockets_msgapi_cmsg(int domain)548 static void test_sockets_msgapi_cmsg(int domain)
549 {
550   int s, ret, enable;
551   struct sockaddr_storage addr_storage;
552   socklen_t addr_size;
553   struct iovec iov;
554   struct msghdr msg;
555   struct cmsghdr *cmsg;
556   struct in_pktinfo *pktinfo;
557   u8_t rcv_buf[4];
558   u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
559   u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
560 
561   test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
562 
563   s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM);
564   fail_unless(s >= 0);
565 
566   ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size);
567   fail_unless(ret == 0);
568 
569   /* Update addr with epehermal port */
570   ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size);
571   fail_unless(ret == 0);
572 
573   enable = 1;
574   ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
575   fail_unless(ret == 0);
576 
577   /* Receive full message, including control message */
578   iov.iov_base = rcv_buf;
579   iov.iov_len = sizeof(rcv_buf);
580   msg.msg_control = cmsg_buf;
581   msg.msg_controllen = sizeof(cmsg_buf);
582   msg.msg_flags = 0;
583   msg.msg_iov = &iov;
584   msg.msg_iovlen = 1;
585   msg.msg_name = NULL;
586   msg.msg_namelen = 0;
587 
588   memset(rcv_buf, 0, sizeof(rcv_buf));
589   ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
590   fail_unless(ret == sizeof(snd_buf));
591 
592   tcpip_thread_poll_one();
593 
594   ret = lwip_recvmsg(s, &msg, 0);
595   fail_unless(ret == sizeof(rcv_buf));
596   fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
597 
598   /* Verify message header */
599   cmsg = CMSG_FIRSTHDR(&msg);
600   fail_unless(cmsg != NULL);
601   fail_unless(cmsg->cmsg_len > 0);
602   fail_unless(cmsg->cmsg_level == IPPROTO_IP);
603   fail_unless(cmsg->cmsg_type == IP_PKTINFO);
604 
605   /* Verify message data */
606   pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
607   /* We only have loopback interface enabled */
608   fail_unless(pktinfo->ipi_ifindex == 1);
609   fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK));
610 
611   /* Verify there are no additional messages */
612   cmsg = CMSG_NXTHDR(&msg, cmsg);
613   fail_unless(cmsg == NULL);
614 
615   /* Send datagram again, testing truncation */
616   memset(rcv_buf, 0, sizeof(rcv_buf));
617   ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
618   fail_unless(ret == sizeof(snd_buf));
619 
620   tcpip_thread_poll_one();
621 
622   msg.msg_controllen = 1;
623   msg.msg_flags = 0;
624   ret = lwip_recvmsg(s, &msg, 0);
625   fail_unless(ret == sizeof(rcv_buf));
626   fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
627   /* Ensure truncation was returned */
628   fail_unless(msg.msg_flags & MSG_CTRUNC);
629   /* Ensure no control messages were returned */
630   fail_unless(msg.msg_controllen == 0);
631 
632   ret = lwip_close(s);
633   fail_unless(ret == 0);
634 }
635 #endif /* LWIP_IPV4 */
636 
START_TEST(test_sockets_msgapis)637 START_TEST(test_sockets_msgapis)
638 {
639   LWIP_UNUSED_ARG(_i);
640 #if LWIP_IPV4
641   test_sockets_msgapi_udp(AF_INET);
642   test_sockets_msgapi_tcp(AF_INET);
643   test_sockets_msgapi_cmsg(AF_INET);
644 #endif
645 #if LWIP_IPV6
646   test_sockets_msgapi_udp(AF_INET6);
647   test_sockets_msgapi_tcp(AF_INET6);
648 #endif
649 }
650 END_TEST
651 
START_TEST(test_sockets_select)652 START_TEST(test_sockets_select)
653 {
654 #if LWIP_SOCKET_SELECT
655   int s;
656   int ret;
657   fd_set readset;
658   fd_set writeset;
659   fd_set errset;
660   struct timeval tv;
661 
662   fail_unless(test_sockets_get_used_count() == 0);
663 
664   s = lwip_socket(AF_INET, SOCK_STREAM, 0);
665   fail_unless(s >= 0);
666   fail_unless(test_sockets_get_used_count() == 0);
667 
668   FD_ZERO(&readset);
669   FD_SET(s, &readset);
670   FD_ZERO(&writeset);
671   FD_SET(s, &writeset);
672   FD_ZERO(&errset);
673   FD_SET(s, &errset);
674 
675   tv.tv_sec = tv.tv_usec = 0;
676   ret = lwip_select(s + 1, &readset, &writeset, &errset, &tv);
677   fail_unless(ret == 0);
678   fail_unless(test_sockets_get_used_count() == 0);
679 
680   ret = lwip_close(s);
681   fail_unless(ret == 0);
682 
683 #endif
684   LWIP_UNUSED_ARG(_i);
685 }
686 END_TEST
687 
START_TEST(test_sockets_recv_after_rst)688 START_TEST(test_sockets_recv_after_rst)
689 {
690   int sl, sact;
691   int spass = -1;
692   int ret;
693   struct sockaddr_in sa_listen;
694   const u16_t port = 1234;
695   int arg;
696   const char txbuf[] = "something";
697   char rxbuf[16];
698   struct lwip_sock *sact_sock;
699   int err;
700   LWIP_UNUSED_ARG(_i);
701 
702   fail_unless(test_sockets_get_used_count() == 0);
703 
704   memset(&sa_listen, 0, sizeof(sa_listen));
705   sa_listen.sin_family = AF_INET;
706   sa_listen.sin_port = PP_HTONS(port);
707   sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
708 
709   /* set up the listener */
710   sl = lwip_socket(AF_INET, SOCK_STREAM, 0);
711   fail_unless(sl >= 0);
712   fail_unless(test_sockets_get_used_count() == 0);
713 
714   ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
715   fail_unless(ret == 0);
716   ret = lwip_listen(sl, 0);
717   fail_unless(ret == 0);
718 
719   /* set up the client */
720   sact = lwip_socket(AF_INET, SOCK_STREAM, 0);
721   fail_unless(sact >= 0);
722   fail_unless(test_sockets_get_used_count() == 0);
723   /* set the client to nonblocking to simplify this test */
724   arg = 1;
725   ret = lwip_ioctl(sact, FIONBIO, &arg);
726   fail_unless(ret == 0);
727   /* connect */
728   do {
729     ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
730     err = errno;
731     fail_unless((ret == 0) || (ret == -1));
732     if (ret != 0) {
733       if (err == EISCONN) {
734         /* Although this is not valid, use EISCONN as an indicator for successful connection.
735            This marks us as "connect phase is done". On error, we would either have a different
736            errno code or "send" fails later... -> good enough for this test. */
737         ret = 0;
738       } else {
739         fail_unless(err == EINPROGRESS);
740         if (err != EINPROGRESS) {
741           goto cleanup;
742         }
743         /* we're in progress: little side check: test for EALREADY */
744         ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
745         err = errno;
746         fail_unless(ret == -1);
747         fail_unless(err == EALREADY);
748         if ((ret != -1) || (err != EALREADY)) {
749           goto cleanup;
750         }
751       }
752       tcpip_thread_poll_one();
753       tcpip_thread_poll_one();
754       tcpip_thread_poll_one();
755       tcpip_thread_poll_one();
756     }
757   } while (ret != 0);
758   fail_unless(ret == 0);
759 
760   /* accept the server connection part */
761   spass = lwip_accept(sl, NULL, NULL);
762   fail_unless(spass >= 0);
763 
764   /* write data from client */
765   ret = lwip_send(sact, txbuf, sizeof(txbuf), 0);
766   fail_unless(ret == sizeof(txbuf));
767 
768   tcpip_thread_poll_one();
769   tcpip_thread_poll_one();
770 
771   /* issue RST (This is a HACK, don't try this in your own app!) */
772   sact_sock = lwip_socket_dbg_get_socket(sact);
773   fail_unless(sact_sock != NULL);
774   if (sact_sock != NULL) {
775     struct netconn *sact_conn = sact_sock->conn;
776     fail_unless(sact_conn != NULL);
777     if (sact_conn != NULL) {
778       struct tcp_pcb *pcb = sact_conn->pcb.tcp;
779       fail_unless(pcb != NULL);
780       if (pcb != NULL) {
781         tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
782                      pcb->local_port, pcb->remote_port);
783       }
784     }
785   }
786   tcpip_thread_poll_one();
787   tcpip_thread_poll_one();
788 
789   /* expect to receive data first */
790   ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
791   fail_unless(ret > 0);
792   tcpip_thread_poll_one();
793   tcpip_thread_poll_one();
794 
795   /* expect to receive RST indication */
796   ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
797   fail_unless(ret == -1);
798   err = errno;
799   fail_unless(err == ECONNRESET);
800   tcpip_thread_poll_one();
801   tcpip_thread_poll_one();
802 
803   /* expect to receive ENOTCONN indication */
804   ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
805   fail_unless(ret == -1);
806   err = errno;
807   fail_unless(err == ENOTCONN);
808   tcpip_thread_poll_one();
809   tcpip_thread_poll_one();
810 
811   /* expect to receive ENOTCONN indication */
812   ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
813   fail_unless(ret == -1);
814   err = errno;
815   fail_unless(err == ENOTCONN);
816   tcpip_thread_poll_one();
817   tcpip_thread_poll_one();
818 
819 cleanup:
820   ret = lwip_close(sl);
821   fail_unless(ret == 0);
822   ret = lwip_close(sact);
823   fail_unless(ret == 0);
824   if (spass >= 0) {
825     ret = lwip_close(spass);
826     fail_unless(ret == 0);
827   }
828 }
829 END_TEST
830 
831 /** Create the suite including all tests for this module */
832 Suite *
sockets_suite(void)833 sockets_suite(void)
834 {
835   testfunc tests[] = {
836     TESTFUNC(test_sockets_basics),
837     TESTFUNC(test_sockets_allfunctions_basic),
838     TESTFUNC(test_sockets_msgapis),
839     TESTFUNC(test_sockets_select),
840     TESTFUNC(test_sockets_recv_after_rst),
841   };
842   return create_suite("SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown);
843 }
844 
845 #else /* LWIP_SOCKET */
846 
847 Suite *
sockets_suite(void)848 sockets_suite(void)
849 {
850   return create_suite("SOCKETS", NULL, 0, NULL, NULL);
851 }
852 #endif /* LWIP_SOCKET */
853