bsd_socket.c
Go to the documentation of this file.
1 /**
2  * @file bsd_socket.c
3  * @brief BSD socket API
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL BSD_SOCKET_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "core/bsd_socket.h"
37 #include "core/socket.h"
38 #include "core/socket_misc.h"
39 #include "debug.h"
40 
41 //Check TCP/IP stack configuration
42 #if (BSD_SOCKET_SUPPORT == ENABLED)
43 
44 //Dependencies
46 #include "core/bsd_socket_misc.h"
47 
48 //Common IPv6 addresses
49 const struct in6_addr in6addr_any =
50  {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
51 
52 const struct in6_addr in6addr_loopback =
53  {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
54 
55 
56 /**
57  * @brief Create a socket that is bound to a specific transport service provider
58  * @param[in] family Address family
59  * @param[in] type Type specification for the new socket
60  * @param[in] protocol Protocol to be used
61  * @return On success, a file descriptor for the new socket is returned.
62  * On failure, SOCKET_ERROR is returned
63  **/
64 
66 {
67  Socket *sock;
68 
69  //Check address family
70  if(family == AF_INET || family == AF_INET6)
71  {
72  //Create a socket
73  sock = socketOpen(type, protocol);
74  }
75  else if(family == AF_PACKET)
76  {
77  //Create a socket
79  }
80  else
81  {
82  //The address family is not valid
83  return SOCKET_ERROR;
84  }
85 
86  //Failed to create a new socket?
87  if(sock == NULL)
88  {
89  //Report an error
90  return SOCKET_ERROR;
91  }
92 
93  //Return the socket descriptor
94  return sock->descriptor;
95 }
96 
97 
98 /**
99  * @brief Associate a local address with a socket
100  * @param[in] s Descriptor identifying an unbound socket
101  * @param[in] addr Local address to assign to the bound socket
102  * @param[in] addrlen Length in bytes of the address
103  * @return If no error occurs, bind returns SOCKET_SUCCESS.
104  * Otherwise, it returns SOCKET_ERROR
105  **/
106 
107 int_t bind(int_t s, const struct sockaddr *addr, socklen_t addrlen)
108 {
109  error_t error;
110  uint16_t port;
111  IpAddr ipAddr;
112  NetContext *context;
113  Socket *sock;
114 
115  //Point to the TCP/IP stack context
116  context = netGetDefaultContext();
117 
118  //Make sure the socket descriptor is valid
119  if(s < 0 || s >= SOCKET_MAX_COUNT)
120  {
121  return SOCKET_ERROR;
122  }
123 
124  //Point to the socket structure
125  sock = &context->socketTable[s];
126 
127  //Check the length of the address
128  if(addrlen < (socklen_t) sizeof(SOCKADDR))
129  {
130  //Report an error
131  socketSetErrnoCode(sock, EINVAL);
132  return SOCKET_ERROR;
133  }
134 
135 #if (IPV4_SUPPORT == ENABLED)
136  //IPv4 address?
137  if(addr->sa_family == AF_INET &&
138  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
139  {
140  //Point to the IPv4 address information
141  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
142 
143  //Get port number
144  port = ntohs(sa->sin_port);
145 
146  //Copy IPv4 address
147  ipAddr.length = sizeof(Ipv4Addr);
148  ipAddr.ipv4Addr = sa->sin_addr.s_addr;
149  }
150  else
151 #endif
152 #if (IPV6_SUPPORT == ENABLED)
153  //IPv6 address?
154  if(addr->sa_family == AF_INET6 &&
155  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
156  {
157  //Point to the IPv6 address information
158  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
159 
160  //Get port number
161  port = ntohs(sa->sin6_port);
162 
163  //Copy IPv6 address
165  {
166  ipAddr.length = 0;
167  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
168  }
169  else
170  {
171  ipAddr.length = sizeof(Ipv6Addr);
172  ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr);
173  }
174  }
175  else
176 #endif
177  //Invalid address?
178  {
179  //Report an error
180  socketSetErrnoCode(sock, EINVAL);
181  return SOCKET_ERROR;
182  }
183 
184  //Associate the local address with the socket
185  error = socketBind(sock, &ipAddr, port);
186 
187  //Any error to report?
188  if(error)
189  {
190  socketTranslateErrorCode(sock, error);
191  return SOCKET_ERROR;
192  }
193 
194  //Successful processing
195  return SOCKET_SUCCESS;
196 }
197 
198 
199 /**
200  * @brief Establish a connection to a specified socket
201  * @param[in] s Descriptor identifying an unconnected socket
202  * @param[in] addr Address to which the connection should be established
203  * @param[in] addrlen Length in bytes of the address
204  * @return If no error occurs, connect returns SOCKET_SUCCESS.
205  * Otherwise, it returns SOCKET_ERROR
206  **/
207 
208 int_t connect(int_t s, const struct sockaddr *addr, socklen_t addrlen)
209 {
210  error_t error;
211  uint16_t port;
212  IpAddr ipAddr;
213  NetContext *context;
214  Socket *sock;
215 
216  //Point to the TCP/IP stack context
217  context = netGetDefaultContext();
218 
219  //Make sure the socket descriptor is valid
220  if(s < 0 || s >= SOCKET_MAX_COUNT)
221  {
222  return SOCKET_ERROR;
223  }
224 
225  //Point to the socket structure
226  sock = &context->socketTable[s];
227 
228  //Check the length of the address
229  if(addrlen < (socklen_t) sizeof(SOCKADDR))
230  {
231  socketSetErrnoCode(sock, EINVAL);
232  return SOCKET_ERROR;
233  }
234 
235 #if (IPV4_SUPPORT == ENABLED)
236  //IPv4 address?
237  if(addr->sa_family == AF_INET &&
238  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
239  {
240  //Point to the IPv4 address information
241  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
242 
243  //Get port number
244  port = ntohs(sa->sin_port);
245 
246  //Copy IPv4 address
247  ipAddr.length = sizeof(Ipv4Addr);
248  ipAddr.ipv4Addr = sa->sin_addr.s_addr;
249  }
250  else
251 #endif
252 #if (IPV6_SUPPORT == ENABLED)
253  //IPv6 address?
254  if(addr->sa_family == AF_INET6 &&
255  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
256  {
257  //Point to the IPv6 address information
258  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
259 
260  //Get port number
261  port = ntohs(sa->sin6_port);
262 
263  //Copy IPv6 address
265  {
266  ipAddr.length = 0;
267  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
268  }
269  else
270  {
271  ipAddr.length = sizeof(Ipv6Addr);
272  ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr);
273  }
274  }
275  else
276 #endif
277  //Invalid address?
278  {
279  //Report an error
280  socketSetErrnoCode(sock, EINVAL);
281  return SOCKET_ERROR;
282  }
283 
284  //Establish connection
285  error = socketConnect(sock, &ipAddr, port);
286 
287  //Check status code
288  if(error == NO_ERROR)
289  {
290  //Successful processing
291  return SOCKET_SUCCESS;
292  }
293  else if(error == ERROR_TIMEOUT)
294  {
295  //Non-blocking socket?
296  if(sock->timeout == 0)
297  {
298  //The connection cannot be completed immediately
300  }
301  else
302  {
303  //Timeout while attempting connection
305  }
306 
307  //Report an error
308  return SOCKET_ERROR;
309  }
310  else
311  {
312  //Report an error
313  socketTranslateErrorCode(sock, error);
314  return SOCKET_ERROR;
315  }
316 }
317 
318 
319 /**
320  * @brief Place a socket in the listening state
321  *
322  * Place a socket in a state in which it is listening for an incoming connection
323  *
324  * @param[in] s Descriptor identifying a bound, unconnected socket
325  * @param[in] backlog Maximum length of the queue of pending connections
326  * @return If no error occurs, listen returns SOCKET_SUCCESS.
327  * Otherwise, it returns SOCKET_ERROR
328  **/
329 
331 {
332  error_t error;
333  NetContext *context;
334  Socket *sock;
335 
336  //Point to the TCP/IP stack context
337  context = netGetDefaultContext();
338 
339  //Make sure the socket descriptor is valid
340  if(s < 0 || s >= SOCKET_MAX_COUNT)
341  {
342  return SOCKET_ERROR;
343  }
344 
345  //Point to the socket structure
346  sock = &context->socketTable[s];
347 
348  //Place the socket in the listening state
349  error = socketListen(sock, backlog);
350 
351  //Any error to report?
352  if(error)
353  {
354  socketTranslateErrorCode(sock, error);
355  return SOCKET_ERROR;
356  }
357 
358  //Successful processing
359  return SOCKET_SUCCESS;
360 }
361 
362 
363 /**
364  * @brief Permit an incoming connection attempt on a socket
365  * @param[in] s Descriptor that identifies a socket in the listening state
366  * @param[out] addr Address of the connecting entity (optional)
367  * @param[in,out] addrlen Length in bytes of the address (optional)
368  * @return If no error occurs, accept returns a descriptor for the new socket.
369  * Otherwise, it returns SOCKET_ERROR
370  **/
371 
372 int_t accept(int_t s, struct sockaddr *addr, socklen_t *addrlen)
373 {
374  uint16_t port;
375  IpAddr ipAddr;
376  NetContext *context;
377  Socket *sock;
378  Socket *newSock;
379 
380  //Point to the TCP/IP stack context
381  context = netGetDefaultContext();
382 
383  //Make sure the socket descriptor is valid
384  if(s < 0 || s >= SOCKET_MAX_COUNT)
385  {
386  return SOCKET_ERROR;
387  }
388 
389  //Point to the socket structure
390  sock = &context->socketTable[s];
391 
392  //Permit an incoming connection attempt on a socket
393  newSock = socketAccept(sock, &ipAddr, &port);
394 
395  //No connection request is pending in the SYN queue?
396  if(newSock == NULL)
397  {
398  //Report an error
400  return SOCKET_ERROR;
401  }
402 
403  //The address parameter is optional
404  if(addr != NULL && addrlen != NULL)
405  {
406 #if (IPV4_SUPPORT == ENABLED)
407  //IPv4 address?
408  if(ipAddr.length == sizeof(Ipv4Addr) &&
409  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
410  {
411  //Point to the IPv4 address information
412  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
413 
414  //Set address family and port number
415  sa->sin_family = AF_INET;
416  sa->sin_port = htons(port);
417 
418  //Copy IPv4 address
419  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
420 
421  //Return the actual length of the address
422  *addrlen = sizeof(SOCKADDR_IN);
423  }
424  else
425 #endif
426 #if (IPV6_SUPPORT == ENABLED)
427  //IPv6 address?
428  if(ipAddr.length == sizeof(Ipv6Addr) &&
429  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
430  {
431  //Point to the IPv6 address information
432  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
433 
434  //Set address family and port number
435  sa->sin6_family = AF_INET6;
436  sa->sin6_port = htons(port);
437  sa->sin6_flowinfo = 0;
438  sa->sin6_scope_id = 0;
439 
440  //Copy IPv6 address
441  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
442 
443  //Return the actual length of the address
444  *addrlen = sizeof(SOCKADDR_IN6);
445  }
446  else
447 #endif
448  //Invalid address?
449  {
450  //Close socket
451  socketClose(newSock);
452 
453  //Report an error
454  socketSetErrnoCode(sock, EINVAL);
455  return SOCKET_ERROR;
456  }
457  }
458 
459  //Return the descriptor to the new socket
460  return newSock->descriptor;
461 }
462 
463 
464 /**
465  * @brief Send data to a connected socket
466  * @param[in] s Descriptor that identifies a connected socket
467  * @param[in] data Pointer to a buffer containing the data to be transmitted
468  * @param[in] length Number of bytes to be transmitted
469  * @param[in] flags Set of flags that influences the behavior of this function
470  * @return If no error occurs, send returns the total number of bytes sent,
471  * which can be less than the number requested to be sent in the
472  * length parameter. Otherwise, a value of SOCKET_ERROR is returned
473  **/
474 
475 int_t send(int_t s, const void *data, size_t length, int_t flags)
476 {
477  error_t error;
478  size_t written;
479  uint_t socketFlags;
480  NetContext *context;
481  Socket *sock;
482 
483  //Point to the TCP/IP stack context
484  context = netGetDefaultContext();
485 
486  //Make sure the socket descriptor is valid
487  if(s < 0 || s >= SOCKET_MAX_COUNT)
488  {
489  return SOCKET_ERROR;
490  }
491 
492  //Point to the socket structure
493  sock = &context->socketTable[s];
494 
495  //The flags parameter can be used to influence the behavior of the function
496  socketFlags = 0;
497 
498  //The MSG_DONTROUTE flag specifies that the data should not be subject
499  //to routing
500  if((flags & MSG_DONTROUTE) != 0)
501  {
502  socketFlags |= SOCKET_FLAG_DONT_ROUTE;
503  }
504 
505  //The TCP_NODELAY option disables the Nagle algorithm for TCP sockets
506  if((sock->options & SOCKET_OPTION_TCP_NO_DELAY) != 0)
507  {
508  socketFlags |= SOCKET_FLAG_NO_DELAY;
509  }
510 
511  //Send data
512  error = socketSend(sock, data, length, &written, socketFlags);
513 
514  //Any error to report?
515  if(error == ERROR_TIMEOUT)
516  {
517  //Check whether some data has been written
518  if(written > 0)
519  {
520  //If a timeout error occurs and some data has been written, the
521  //count of bytes transferred so far is returned...
522  }
523  else
524  {
525  //If no data has been written, a value of SOCKET_ERROR is returned
526  socketTranslateErrorCode(sock, error);
527  return SOCKET_ERROR;
528  }
529  }
530  else if(error != NO_ERROR)
531  {
532  //Otherwise, a value of SOCKET_ERROR is returned
533  socketTranslateErrorCode(sock, error);
534  return SOCKET_ERROR;
535  }
536 
537  //Return the number of bytes transferred so far
538  return written;
539 }
540 
541 
542 /**
543  * @brief Send a datagram to a specific destination
544  * @param[in] s Descriptor that identifies a socket
545  * @param[in] data Pointer to a buffer containing the data to be transmitted
546  * @param[in] length Number of bytes to be transmitted
547  * @param[in] flags Set of flags that influences the behavior of this function
548  * @param[in] addr Destination address
549  * @param[in] addrlen Length in bytes of the destination address
550  * @return If no error occurs, sendto returns the total number of bytes sent,
551  * which can be less than the number requested to be sent in the
552  * length parameter. Otherwise, a value of SOCKET_ERROR is returned
553  **/
554 
555 int_t sendto(int_t s, const void *data, size_t length, int_t flags,
556  const struct sockaddr *addr, socklen_t addrlen)
557 {
558  error_t error;
559  size_t written;
560  uint_t socketFlags;
561  uint16_t port;
562  IpAddr ipAddr;
563  NetContext *context;
564  Socket *sock;
565 
566  //Point to the TCP/IP stack context
567  context = netGetDefaultContext();
568 
569  //Make sure the socket descriptor is valid
570  if(s < 0 || s >= SOCKET_MAX_COUNT)
571  {
572  return SOCKET_ERROR;
573  }
574 
575  //Point to the socket structure
576  sock = &context->socketTable[s];
577 
578  //The flags parameter can be used to influence the behavior of the function
579  socketFlags = 0;
580 
581  //The MSG_DONTROUTE flag specifies that the data should not be subject
582  //to routing
583  if((flags & MSG_DONTROUTE) != 0)
584  {
585  socketFlags |= SOCKET_FLAG_DONT_ROUTE;
586  }
587 
588  //The TCP_NODELAY option disables the Nagle algorithm for TCP sockets
589  if((sock->options & SOCKET_OPTION_TCP_NO_DELAY) != 0)
590  {
591  socketFlags |= SOCKET_FLAG_NO_DELAY;
592  }
593 
594  //Check the length of the address
595  if(addrlen < (socklen_t) sizeof(SOCKADDR))
596  {
597  //Report an error
598  socketSetErrnoCode(sock, EINVAL);
599  return SOCKET_ERROR;
600  }
601 
602 #if (IPV4_SUPPORT == ENABLED)
603  //IPv4 address?
604  if(addr->sa_family == AF_INET &&
605  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
606  {
607  //Point to the IPv4 address information
608  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
609 
610  //Get port number
611  port = ntohs(sa->sin_port);
612 
613  //Copy IPv4 address
614  ipAddr.length = sizeof(Ipv4Addr);
615  ipAddr.ipv4Addr = sa->sin_addr.s_addr;
616  }
617  else
618 #endif
619 #if (IPV6_SUPPORT == ENABLED)
620  //IPv6 address?
621  if(addr->sa_family == AF_INET6 &&
622  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
623  {
624  //Point to the IPv6 address information
625  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
626 
627  //Get port number
628  port = ntohs(sa->sin6_port);
629 
630  //Copy IPv6 address
631  ipAddr.length = sizeof(Ipv6Addr);
632  ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr);
633  }
634  else
635 #endif
636  //Invalid address?
637  {
638  //Report an error
639  socketSetErrnoCode(sock, EINVAL);
640  return SOCKET_ERROR;
641  }
642 
643  //Send data
644  error = socketSendTo(sock, &ipAddr, port, data, length, &written,
645  socketFlags);
646 
647  //Any error to report?
648  if(error == ERROR_TIMEOUT)
649  {
650  //Check whether some data has been written
651  if(written > 0)
652  {
653  //If a timeout error occurs and some data has been written, the
654  //count of bytes transferred so far is returned...
655  }
656  else
657  {
658  //If no data has been written, a value of SOCKET_ERROR is returned
659  socketTranslateErrorCode(sock, error);
660  return SOCKET_ERROR;
661  }
662  }
663  else if(error != NO_ERROR)
664  {
665  //Otherwise, a value of SOCKET_ERROR is returned
666  socketTranslateErrorCode(sock, error);
667  return SOCKET_ERROR;
668  }
669 
670  //Return the number of bytes transferred so far
671  return written;
672 }
673 
674 
675 /**
676  * @brief Send a message
677  * @param[in] s Descriptor that identifies a socket
678  * @param[in] msg Pointer to the structure describing the message
679  * @param[in] flags Set of flags that influences the behavior of this function
680  * @return If no error occurs, sendmsg returns the total number of bytes sent,
681  * which can be less than the number requested to be sent in the
682  * length parameter. Otherwise, a value of SOCKET_ERROR is returned
683  **/
684 
686 {
687  error_t error;
688  uint_t socketFlags;
689  NetContext *context;
690  Socket *sock;
692  SOCKADDR *addr;
693 
694  //Point to the TCP/IP stack context
695  context = netGetDefaultContext();
696 
697  //Make sure the socket descriptor is valid
698  if(s < 0 || s >= SOCKET_MAX_COUNT)
699  {
700  return SOCKET_ERROR;
701  }
702 
703  //Point to the socket structure
704  sock = &context->socketTable[s];
705 
706  //Check parameters
707  if(msg == NULL || msg->msg_iov == NULL || msg->msg_iovlen != 1)
708  {
709  socketSetErrnoCode(sock, EINVAL);
710  return SOCKET_ERROR;
711  }
712 
713  //Point to the message to be transmitted
715  message.data = msg->msg_iov[0].iov_base;
716  message.length = msg->msg_iov[0].iov_len;
717 
718  //Check the length of the address
719  if(msg->msg_namelen < (socklen_t) sizeof(SOCKADDR))
720  {
721  //Report an error
722  socketSetErrnoCode(sock, EINVAL);
723  return SOCKET_ERROR;
724  }
725 
726  //Point to the destination address
727  addr = (SOCKADDR *) msg->msg_name;
728 
729 #if (IPV4_SUPPORT == ENABLED)
730  //IPv4 address?
731  if(addr->sa_family == AF_INET &&
732  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN))
733  {
734  //Point to the IPv4 address information
735  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
736 
737  //Get port number
738  message.destPort = ntohs(sa->sin_port);
739 
740  //Copy IPv4 address
741  message.destIpAddr.length = sizeof(Ipv4Addr);
742  message.destIpAddr.ipv4Addr = sa->sin_addr.s_addr;
743  }
744  else
745 #endif
746 #if (IPV6_SUPPORT == ENABLED)
747  //IPv6 address?
748  if(addr->sa_family == AF_INET6 &&
749  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN6))
750  {
751  //Point to the IPv6 address information
752  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
753 
754  //Get port number
755  message.destPort = ntohs(sa->sin6_port);
756 
757  //Copy IPv6 address
758  message.destIpAddr.length = sizeof(Ipv6Addr);
759  ipv6CopyAddr(&message.destIpAddr.ipv6Addr, sa->sin6_addr.s6_addr);
760  }
761  else
762 #endif
763  //Invalid address?
764  {
765  //Report an error
766  socketSetErrnoCode(sock, EINVAL);
767  return SOCKET_ERROR;
768  }
769 
770  //The ancillary data buffer parameter is optional
771  if(msg->msg_control != NULL)
772  {
773  uint_t n;
774  int_t *val;
775  CMSGHDR *cmsg;
776 
777  //Point to the first control message
778  n = 0;
779 
780  //Loop through control messages
781  while((n + sizeof(CMSGHDR)) <= msg->msg_controllen)
782  {
783  //Point to the ancillary data header
784  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
785 
786  //Check the length of the control message
787  if(cmsg->cmsg_len >= sizeof(CMSGHDR) &&
788  cmsg->cmsg_len <= (msg->msg_controllen - n))
789  {
790 #if (IPV4_SUPPORT == ENABLED)
791  //IPv4 protocol?
792  if(addr->sa_family == AF_INET && cmsg->cmsg_level == IPPROTO_IP)
793  {
794  //Check control message type
795  if(cmsg->cmsg_type == IP_PKTINFO &&
796  cmsg->cmsg_len >= CMSG_LEN(sizeof(IN_PKTINFO)))
797  {
798  //Point to the ancillary data value
799  IN_PKTINFO *pktInfo = (IN_PKTINFO *) CMSG_DATA(cmsg);
800 
801  //Specify source IPv4 address
802  message.srcIpAddr.length = sizeof(Ipv4Addr);
803  message.srcIpAddr.ipv4Addr = pktInfo->ipi_addr.s_addr;
804  }
805  else if(cmsg->cmsg_type == IP_TOS &&
806  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
807  {
808  //Point to the ancillary data value
809  val = (int_t *) CMSG_DATA(cmsg);
810  //Specify ToS value
811  message.tos = (uint8_t) *val;
812  }
813  else if(cmsg->cmsg_type == IP_TTL &&
814  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
815  {
816  //Point to the ancillary data value
817  val = (int_t *) CMSG_DATA(cmsg);
818  //Specify TTL value
819  message.ttl = (uint8_t) *val;
820  }
821  else if(cmsg->cmsg_type == IP_DONTFRAG &&
822  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
823  {
824  //Point to the ancillary data value
825  val = (int_t *) CMSG_DATA(cmsg);
826 
827  //This option can be used to set the "don't fragment" flag
828  //on IP packets
829  message.dontFrag = (*val != 0) ? TRUE : FALSE;
830  }
831  else
832  {
833  //Unknown control message type
834  }
835  }
836  else
837 #endif
838 #if (IPV6_SUPPORT == ENABLED)
839  //IPv6 protocol?
840  if(addr->sa_family == AF_INET6 && cmsg->cmsg_level == IPPROTO_IPV6)
841  {
842  //Check control message type
843  if(cmsg->cmsg_type == IPV6_PKTINFO &&
844  cmsg->cmsg_len >= CMSG_LEN(sizeof(IN_PKTINFO)))
845  {
846  //Point to the ancillary data value
847  IN6_PKTINFO *pktInfo = (IN6_PKTINFO *) CMSG_DATA(cmsg);
848 
849  //Specify source IPv6 address
850  message.srcIpAddr.length = sizeof(Ipv6Addr);
851  ipv6CopyAddr(&message.srcIpAddr.ipv6Addr, pktInfo->ipi6_addr.s6_addr);
852  }
853  else if(cmsg->cmsg_type == IPV6_TCLASS &&
854  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
855  {
856  //Point to the ancillary data value
857  val = (int_t *) CMSG_DATA(cmsg);
858  //Specify Traffic Class value
859  message.tos = (uint8_t) *val;
860  }
861  else if(cmsg->cmsg_type == IPV6_HOPLIMIT &&
862  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
863  {
864  //Point to the ancillary data value
865  val = (int_t *) CMSG_DATA(cmsg);
866  //Specify Hop Limit value
867  message.ttl = (uint8_t) *val;
868  }
869  else if(cmsg->cmsg_type == IPV6_DONTFRAG &&
870  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
871  {
872  //Point to the ancillary data value
873  val = (int_t *) CMSG_DATA(cmsg);
874 
875  //This option be used to turn off the automatic inserting
876  //of a fragment header for UDP and raw sockets
877  message.dontFrag = (*val != 0) ? TRUE : FALSE;
878  }
879  else
880  {
881  //Unknown control message type
882  }
883  }
884  //Unknown protocol?
885  else
886 #endif
887  {
888  //Discard control message
889  }
890 
891  //Next control message
892  n += cmsg->cmsg_len;
893  }
894  else
895  {
896  //Malformed control message
897  break;
898  }
899  }
900  }
901 
902  //The flags parameter can be used to influence the behavior of the function
903  socketFlags = 0;
904 
905  //The MSG_DONTROUTE flag specifies that the data should not be subject
906  //to routing
907  if((flags & MSG_DONTROUTE) != 0)
908  {
909  socketFlags |= SOCKET_FLAG_DONT_ROUTE;
910  }
911 
912  //The TCP_NODELAY option disables the Nagle algorithm for TCP sockets
913  if((sock->options & SOCKET_OPTION_TCP_NO_DELAY) != 0)
914  {
915  socketFlags |= SOCKET_FLAG_NO_DELAY;
916  }
917 
918  //Send message
919  error = socketSendMsg(sock, &message, socketFlags);
920 
921  //Any error to report?
922  if(error != NO_ERROR)
923  {
924  //Otherwise, a value of SOCKET_ERROR is returned
925  socketTranslateErrorCode(sock, error);
926  return SOCKET_ERROR;
927  }
928 
929  //Return the number of bytes transferred so far
930  return message.length;
931 }
932 
933 
934 /**
935  * @brief Receive data from a connected socket
936  * @param[in] s Descriptor that identifies a connected socket
937  * @param[out] data Buffer where to store the incoming data
938  * @param[in] size Maximum number of bytes that can be received
939  * @param[in] flags Set of flags that influences the behavior of this function
940  * @return If no error occurs, recv returns the number of bytes received. If the
941  * connection has been gracefully closed, the return value is zero.
942  * Otherwise, a value of SOCKET_ERROR is returned
943  **/
944 
945 int_t recv(int_t s, void *data, size_t size, int_t flags)
946 {
947  error_t error;
948  size_t received;
949  uint_t socketFlags;
950  NetContext *context;
951  Socket *sock;
952 
953  //Point to the TCP/IP stack context
954  context = netGetDefaultContext();
955 
956  //Make sure the socket descriptor is valid
957  if(s < 0 || s >= SOCKET_MAX_COUNT)
958  {
959  return SOCKET_ERROR;
960  }
961 
962  //Point to the socket structure
963  sock = &context->socketTable[s];
964 
965  //The flags parameter can be used to influence the behavior of the function
966  socketFlags = 0;
967 
968  //When the MSG_PEEK flag is specified, the data is copied into the buffer,
969  //but is not removed from the input queue
970  if((flags & MSG_PEEK) != 0)
971  {
972  socketFlags |= SOCKET_FLAG_PEEK;
973  }
974 
975  //When the MSG_WAITALL flag is specified, the receive request will complete
976  //when the buffer supplied by the caller is completely full
977  if((flags & MSG_WAITALL) != 0)
978  {
979  socketFlags |= SOCKET_FLAG_WAIT_ALL;
980  }
981 
982  //The MSG_DONTWAIT flag enables non-blocking operation
983  if((flags & MSG_DONTWAIT) != 0)
984  {
985  socketFlags |= SOCKET_FLAG_DONT_WAIT;
986  }
987 
988  //Receive data
989  error = socketReceive(sock, data, size, &received, socketFlags);
990 
991  //Any error to report?
992  if(error == ERROR_END_OF_STREAM)
993  {
994  //If the connection has been gracefully closed, the return value is zero
995  return 0;
996  }
997  else if(error != NO_ERROR)
998  {
999  //Otherwise, a value of SOCKET_ERROR is returned
1000  socketTranslateErrorCode(sock, error);
1001  return SOCKET_ERROR;
1002  }
1003 
1004  //Return the number of bytes received
1005  return received;
1006 }
1007 
1008 
1009 /**
1010  * @brief Receive a datagram
1011  * @param[in] s Descriptor that identifies a socket
1012  * @param[out] data Buffer where to store the incoming data
1013  * @param[in] size Maximum number of bytes that can be received
1014  * @param[in] flags Set of flags that influences the behavior of this function
1015  * @param[out] addr Source address upon return (optional)
1016  * @param[in,out] addrlen Length in bytes of the address (optional)
1017  * @return If no error occurs, recvfrom returns the number of bytes received.
1018  * Otherwise, a value of SOCKET_ERROR is returned
1019  **/
1020 
1021 int_t recvfrom(int_t s, void *data, size_t size, int_t flags,
1022  struct sockaddr *addr, socklen_t *addrlen)
1023 {
1024  error_t error;
1025  size_t received;
1026  uint_t socketFlags;
1027  uint16_t port;
1028  IpAddr ipAddr;
1029  NetContext *context;
1030  Socket *sock;
1031 
1032  //Point to the TCP/IP stack context
1033  context = netGetDefaultContext();
1034 
1035  //Make sure the socket descriptor is valid
1036  if(s < 0 || s >= SOCKET_MAX_COUNT)
1037  {
1038  return SOCKET_ERROR;
1039  }
1040 
1041  //Point to the socket structure
1042  sock = &context->socketTable[s];
1043 
1044  //The flags parameter can be used to influence the behavior of the function
1045  socketFlags = 0;
1046 
1047  //When the MSG_PEEK flag is specified, the data is copied into the buffer,
1048  //but is not removed from the input queue
1049  if((flags & MSG_PEEK) != 0)
1050  {
1051  socketFlags |= SOCKET_FLAG_PEEK;
1052  }
1053 
1054  //When the MSG_WAITALL flag is specified, the receive request will complete
1055  //when the buffer supplied by the caller is completely full
1056  if((flags & MSG_WAITALL) != 0)
1057  {
1058  socketFlags |= SOCKET_FLAG_WAIT_ALL;
1059  }
1060 
1061  //The MSG_DONTWAIT flag enables non-blocking operation
1062  if((flags & MSG_DONTWAIT) != 0)
1063  {
1064  socketFlags |= SOCKET_FLAG_DONT_WAIT;
1065  }
1066 
1067  //Receive data
1068  error = socketReceiveFrom(sock, &ipAddr, &port, data, size, &received,
1069  socketFlags);
1070 
1071  //Any error to report?
1072  if(error == ERROR_END_OF_STREAM)
1073  {
1074  //If the connection has been gracefully closed, the return value is zero
1075  return 0;
1076  }
1077  else if(error != NO_ERROR)
1078  {
1079  //Otherwise, a value of SOCKET_ERROR is returned
1080  socketTranslateErrorCode(sock, error);
1081  return SOCKET_ERROR;
1082  }
1083 
1084  //The address parameter is optional
1085  if(addr != NULL && addrlen != NULL)
1086  {
1087 #if (IPV4_SUPPORT == ENABLED)
1088  //IPv4 address?
1089  if(ipAddr.length == sizeof(Ipv4Addr) &&
1090  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1091  {
1092  //Point to the IPv4 address information
1093  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1094 
1095  //Set address family and port number
1096  sa->sin_family = AF_INET;
1097  sa->sin_port = htons(port);
1098 
1099  //Copy IPv4 address
1100  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
1101 
1102  //Return the actual length of the address
1103  *addrlen = sizeof(SOCKADDR_IN);
1104  }
1105  else
1106 #endif
1107 #if (IPV6_SUPPORT == ENABLED)
1108  //IPv6 address?
1109  if(ipAddr.length == sizeof(Ipv6Addr) &&
1110  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1111  {
1112  //Point to the IPv6 address information
1113  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1114 
1115  //Set address family and port number
1116  sa->sin6_family = AF_INET6;
1117  sa->sin6_port = htons(port);
1118  sa->sin6_flowinfo = 0;
1119  sa->sin6_scope_id = 0;
1120 
1121  //Copy IPv6 address
1122  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
1123 
1124  //Return the actual length of the address
1125  *addrlen = sizeof(SOCKADDR_IN6);
1126  }
1127  else
1128 #endif
1129  //Invalid address?
1130  {
1131  //Report an error
1132  socketSetErrnoCode(sock, EINVAL);
1133  return SOCKET_ERROR;
1134  }
1135  }
1136 
1137  //Return the number of bytes received
1138  return received;
1139 }
1140 
1141 
1142 /**
1143  * @brief Receive a message
1144  * @param[in] s Descriptor that identifies a socket
1145  * @param[in,out] msg Pointer to the structure describing the message
1146  * @param[in] flags Set of flags that influences the behavior of this function
1147  * @return If no error occurs, recvmsg returns the number of bytes received.
1148  * Otherwise, a value of SOCKET_ERROR is returned
1149  **/
1150 
1152 {
1153  error_t error;
1154  size_t n;
1155  uint_t socketFlags;
1156  NetContext *context;
1157  Socket *sock;
1159 
1160  //Point to the TCP/IP stack context
1161  context = netGetDefaultContext();
1162 
1163  //Make sure the socket descriptor is valid
1164  if(s < 0 || s >= SOCKET_MAX_COUNT)
1165  {
1166  return SOCKET_ERROR;
1167  }
1168 
1169  //Point to the socket structure
1170  sock = &context->socketTable[s];
1171 
1172  //Check parameters
1173  if(msg == NULL || msg->msg_iov == NULL || msg->msg_iovlen != 1)
1174  {
1175  socketSetErrnoCode(sock, EINVAL);
1176  return SOCKET_ERROR;
1177  }
1178 
1179  //Point to the receive buffer
1181  message.data = msg->msg_iov[0].iov_base;
1182  message.size = msg->msg_iov[0].iov_len;
1183 
1184  //The flags parameter can be used to influence the behavior of the function
1185  socketFlags = 0;
1186 
1187  //When the MSG_PEEK flag is specified, the data is copied into the buffer,
1188  //but is not removed from the input queue
1189  if((flags & MSG_PEEK) != 0)
1190  {
1191  socketFlags |= SOCKET_FLAG_PEEK;
1192  }
1193 
1194  //When the MSG_WAITALL flag is specified, the receive request will complete
1195  //when the buffer supplied by the caller is completely full
1196  if((flags & MSG_WAITALL) != 0)
1197  {
1198  socketFlags |= SOCKET_FLAG_WAIT_ALL;
1199  }
1200 
1201  //The MSG_DONTWAIT flag enables non-blocking operation
1202  if((flags & MSG_DONTWAIT) != 0)
1203  {
1204  socketFlags |= SOCKET_FLAG_DONT_WAIT;
1205  }
1206 
1207  //Receive message
1208  error = socketReceiveMsg(sock, &message, socketFlags);
1209 
1210  //Any error to report?
1211  if(error)
1212  {
1213  socketTranslateErrorCode(sock, error);
1214  return SOCKET_ERROR;
1215  }
1216 
1217  //The source address parameter is optional
1218  if(msg->msg_name != NULL)
1219  {
1220 #if (IPV4_SUPPORT == ENABLED)
1221  //IPv4 address?
1222  if(message.srcIpAddr.length == sizeof(Ipv4Addr) &&
1223  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN))
1224  {
1225  //Point to the IPv4 address information
1226  SOCKADDR_IN *sa = (SOCKADDR_IN *) msg->msg_name;
1227 
1228  //Set address family and port number
1229  sa->sin_family = AF_INET;
1230  sa->sin_port = htons(message.srcPort);
1231 
1232  //Copy IPv4 address
1233  sa->sin_addr.s_addr = message.srcIpAddr.ipv4Addr;
1234 
1235  //Return the actual length of the address
1236  msg->msg_namelen = sizeof(SOCKADDR_IN);
1237  }
1238  else
1239 #endif
1240 #if (IPV6_SUPPORT == ENABLED)
1241  //IPv6 address?
1242  if(message.srcIpAddr.length == sizeof(Ipv6Addr) &&
1243  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN6))
1244  {
1245  //Point to the IPv6 address information
1246  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) msg->msg_name;
1247 
1248  //Set address family and port number
1249  sa->sin6_family = AF_INET6;
1250  sa->sin6_port = htons(message.srcPort);
1251  sa->sin6_flowinfo = 0;
1252  sa->sin6_scope_id = 0;
1253 
1254  //Copy IPv6 address
1255  ipv6CopyAddr(sa->sin6_addr.s6_addr, &message.srcIpAddr.ipv6Addr);
1256 
1257  //Return the actual length of the address
1258  msg->msg_namelen = sizeof(SOCKADDR_IN6);
1259  }
1260  else
1261 #endif
1262  //Invalid address?
1263  {
1264  //Report an error
1265  socketSetErrnoCode(sock, EINVAL);
1266  return SOCKET_ERROR;
1267  }
1268  }
1269  else
1270  {
1271  msg->msg_namelen = 0;
1272  }
1273 
1274  //Clear flags
1275  msg->msg_flags = 0;
1276 
1277  //Length of the ancillary data buffer
1278  n = 0;
1279 
1280  //The ancillary data buffer parameter is optional
1281  if(msg->msg_control != NULL)
1282  {
1283 #if (IPV4_SUPPORT == ENABLED)
1284  //IPv4 address?
1285  if(message.destIpAddr.length == sizeof(Ipv4Addr))
1286  {
1287  int_t *val;
1288  CMSGHDR *cmsg;
1289  IN_PKTINFO *pktInfo;
1290 
1291  //The IP_PKTINFO option allows an application to enable or disable
1292  //the return of IPv4 packet information
1293  if((sock->options & SOCKET_OPTION_IPV4_PKT_INFO) != 0)
1294  {
1295  //Make sure there is enough room to add the control message
1296  if((n + CMSG_SPACE(sizeof(IN_PKTINFO))) <= msg->msg_controllen)
1297  {
1298  //Point to the ancillary data header
1299  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1300 
1301  //Format ancillary data header
1302  cmsg->cmsg_len = CMSG_LEN(sizeof(IN_PKTINFO));
1303  cmsg->cmsg_level = IPPROTO_IP;
1304  cmsg->cmsg_type = IP_PKTINFO;
1305 
1306  //Point to the ancillary data value
1307  pktInfo = (IN_PKTINFO *) CMSG_DATA(cmsg);
1308 
1309  //Format packet information
1310  pktInfo->ipi_ifindex = message.interface->index + 1;
1311  pktInfo->ipi_addr.s_addr = message.destIpAddr.ipv4Addr;
1312 
1313  //Adjust the actual length of the ancillary data buffer
1314  n += CMSG_SPACE(sizeof(IN_PKTINFO));
1315  }
1316  else
1317  {
1318  //When the control message buffer is too short to store all
1319  //messages, the MSG_CTRUNC flag must be set
1320  msg->msg_flags |= MSG_CTRUNC;
1321  }
1322  }
1323 
1324  //The IP_RECVTOS option allows an application to enable or disable
1325  //the return of ToS header field on received datagrams
1326  if((sock->options & SOCKET_OPTION_IPV4_RECV_TOS) != 0)
1327  {
1328  //Make sure there is enough room to add the control message
1329  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1330  {
1331  //Point to the ancillary data header
1332  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1333 
1334  //Format ancillary data header
1335  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1336  cmsg->cmsg_level = IPPROTO_IP;
1337  cmsg->cmsg_type = IP_TOS;
1338 
1339  //Point to the ancillary data value
1340  val = (int_t *) CMSG_DATA(cmsg);
1341  //Set ancillary data value
1342  *val = message.tos;
1343 
1344  //Adjust the actual length of the ancillary data buffer
1345  n += CMSG_SPACE(sizeof(int_t));
1346  }
1347  else
1348  {
1349  //When the control message buffer is too short to store all
1350  //messages, the MSG_CTRUNC flag must be set
1351  msg->msg_flags |= MSG_CTRUNC;
1352  }
1353  }
1354 
1355  //The IP_RECVTTL option allows an application to enable or disable
1356  //the return of TTL header field on received datagrams
1357  if((sock->options & SOCKET_OPTION_IPV4_RECV_TTL) != 0)
1358  {
1359  //Make sure there is enough room to add the control message
1360  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1361  {
1362  //Point to the ancillary data header
1363  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1364 
1365  //Format ancillary data header
1366  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1367  cmsg->cmsg_level = IPPROTO_IP;
1368  cmsg->cmsg_type = IP_TTL;
1369 
1370  //Point to the ancillary data value
1371  val = (int_t *) CMSG_DATA(cmsg);
1372  //Set ancillary data value
1373  *val = message.ttl;
1374 
1375  //Adjust the actual length of the ancillary data buffer
1376  n += CMSG_SPACE(sizeof(int_t));
1377  }
1378  else
1379  {
1380  //When the control message buffer is too short to store all
1381  //messages, the MSG_CTRUNC flag must be set
1382  msg->msg_flags |= MSG_CTRUNC;
1383  }
1384  }
1385  }
1386  else
1387 #endif
1388 #if (IPV6_SUPPORT == ENABLED)
1389  //IPv6 address?
1390  if(message.destIpAddr.length == sizeof(Ipv6Addr))
1391  {
1392  int_t *val;
1393  CMSGHDR *cmsg;
1394  IN6_PKTINFO *pktInfo;
1395 
1396  //The IPV6_PKTINFO option allows an application to enable or disable
1397  //the return of IPv6 packet information
1398  if((sock->options & SOCKET_OPTION_IPV6_PKT_INFO) != 0)
1399  {
1400  //Make sure there is enough room to add the control message
1401  if((n + CMSG_SPACE(sizeof(IN6_PKTINFO))) <= msg->msg_controllen)
1402  {
1403  //Point to the ancillary data header
1404  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1405 
1406  //Format ancillary data header
1407  cmsg->cmsg_len = CMSG_LEN(sizeof(IN6_PKTINFO));
1408  cmsg->cmsg_level = IPPROTO_IPV6;
1409  cmsg->cmsg_type = IPV6_PKTINFO;
1410 
1411  //Point to the ancillary data value
1412  pktInfo = (IN6_PKTINFO *) CMSG_DATA(cmsg);
1413 
1414  //Format packet information
1415  pktInfo->ipi6_ifindex = message.interface->index + 1;
1416  ipv6CopyAddr(pktInfo->ipi6_addr.s6_addr, &message.destIpAddr.ipv6Addr);
1417 
1418  //Adjust the actual length of the ancillary data buffer
1419  n += CMSG_SPACE(sizeof(IN6_PKTINFO));
1420  }
1421  else
1422  {
1423  //When the control message buffer is too short to store all
1424  //messages, the MSG_CTRUNC flag must be set
1425  msg->msg_flags |= MSG_CTRUNC;
1426  }
1427  }
1428 
1429  //The IPV6_RECVTCLASS option allows an application to enable or disable
1430  //the return of Traffic Class header field on received datagrams
1431  if((sock->options & SOCKET_OPTION_IPV6_RECV_TRAFFIC_CLASS) != 0)
1432  {
1433  //Make sure there is enough room to add the control message
1434  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1435  {
1436  //Point to the ancillary data header
1437  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1438 
1439  //Format ancillary data header
1440  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1441  cmsg->cmsg_level = IPPROTO_IPV6;
1442  cmsg->cmsg_type = IPV6_TCLASS;
1443 
1444  //Point to the ancillary data value
1445  val = (int_t *) CMSG_DATA(cmsg);
1446  //Set ancillary data value
1447  *val = message.tos;
1448 
1449  //Adjust the actual length of the ancillary data buffer
1450  n += CMSG_SPACE(sizeof(int_t));
1451  }
1452  else
1453  {
1454  //When the control message buffer is too short to store all
1455  //messages, the MSG_CTRUNC flag must be set
1456  msg->msg_flags |= MSG_CTRUNC;
1457  }
1458  }
1459 
1460  //The IPV6_RECVHOPLIMIT option allows an application to enable or
1461  //disable the return of Hop Limit header field on received datagrams
1462  if((sock->options & SOCKET_OPTION_IPV6_RECV_HOP_LIMIT) != 0)
1463  {
1464  //Make sure there is enough room to add the control message
1465  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1466  {
1467  //Point to the ancillary data header
1468  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1469 
1470  //Format ancillary data header
1471  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1472  cmsg->cmsg_level = IPPROTO_IPV6;
1473  cmsg->cmsg_type = IPV6_HOPLIMIT;
1474 
1475  //Point to the ancillary data value
1476  val = (int_t *) CMSG_DATA(cmsg);
1477  //Set ancillary data value
1478  *val = message.ttl;
1479 
1480  //Adjust the actual length of the ancillary data buffer
1481  n += CMSG_SPACE(sizeof(int_t));
1482  }
1483  else
1484  {
1485  //When the control message buffer is too short to store all
1486  //messages, the MSG_CTRUNC flag must be set
1487  msg->msg_flags |= MSG_CTRUNC;
1488  }
1489  }
1490  }
1491  else
1492 #endif
1493  //Invalid address?
1494  {
1495  //Just for sanity
1496  }
1497  }
1498 
1499  //Length of the actual length of the ancillary data buffer
1500  msg->msg_controllen = n;
1501 
1502  //Return the number of bytes received
1503  return message.length;
1504 }
1505 
1506 
1507 /**
1508  * @brief Retrieves the local name for a socket
1509  * @param[in] s Descriptor identifying a socket
1510  * @param[out] addr Address of the socket
1511  * @param[in,out] addrlen Length in bytes of the address
1512  * @return If no error occurs, getsockname returns SOCKET_SUCCESS
1513  * Otherwise, it returns SOCKET_ERROR
1514  **/
1515 
1517 {
1518  int_t ret;
1519  NetContext *context;
1520  Socket *sock;
1521 
1522  //Point to the TCP/IP stack context
1523  context = netGetDefaultContext();
1524 
1525  //Make sure the socket descriptor is valid
1526  if(s < 0 || s >= SOCKET_MAX_COUNT)
1527  {
1528  return SOCKET_ERROR;
1529  }
1530 
1531  //Point to the socket structure
1532  sock = &context->socketTable[s];
1533 
1534  //Get exclusive access
1535  netLock(sock->netContext);
1536 
1537  //Check whether the socket has been bound to an address
1538  if(sock->localIpAddr.length != 0)
1539  {
1540 #if (IPV4_SUPPORT == ENABLED)
1541  //IPv4 address?
1542  if(sock->localIpAddr.length == sizeof(Ipv4Addr) &&
1543  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1544  {
1545  //Point to the IPv4 address information
1546  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1547 
1548  //Set address family and port number
1549  sa->sin_family = AF_INET;
1550  sa->sin_port = htons(sock->localPort);
1551 
1552  //Copy IPv4 address
1553  sa->sin_addr.s_addr = sock->localIpAddr.ipv4Addr;
1554 
1555  //Return the actual length of the address
1556  *addrlen = sizeof(SOCKADDR_IN);
1557  //Successful processing
1558  ret = SOCKET_SUCCESS;
1559  }
1560  else
1561 #endif
1562 #if (IPV6_SUPPORT == ENABLED)
1563  //IPv6 address?
1564  if(sock->localIpAddr.length == sizeof(Ipv6Addr) &&
1565  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1566  {
1567  //Point to the IPv6 address information
1568  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1569 
1570  //Set address family and port number
1571  sa->sin6_family = AF_INET6;
1572  sa->sin6_port = htons(sock->localPort);
1573  sa->sin6_flowinfo = 0;
1574  sa->sin6_scope_id = 0;
1575 
1576  //Copy IPv6 address
1577  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->localIpAddr.ipv6Addr);
1578 
1579  //Return the actual length of the address
1580  *addrlen = sizeof(SOCKADDR_IN6);
1581  //Successful processing
1582  ret = SOCKET_SUCCESS;
1583  }
1584  else
1585 #endif
1586  {
1587  //The specified length is not valid
1588  socketSetErrnoCode(sock, EINVAL);
1589  ret = SOCKET_ERROR;
1590  }
1591  }
1592  else if(sock->remoteIpAddr.length != 0)
1593  {
1594 #if (IPV4_SUPPORT == ENABLED)
1595  //IPv4 address?
1596  if(sock->remoteIpAddr.length == sizeof(Ipv4Addr) &&
1597  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1598  {
1599  //Point to the IPv4 address information
1600  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1601 
1602  //Set address family and port number
1603  sa->sin_family = AF_INET;
1604  sa->sin_port = htons(sock->localPort);
1605 
1606  //The socket is not bound to any address
1607  sa->sin_addr.s_addr = INADDR_ANY;
1608 
1609  //Return the actual length of the address
1610  *addrlen = sizeof(SOCKADDR_IN);
1611  //Successful processing
1612  ret = SOCKET_SUCCESS;
1613  }
1614  else
1615 #endif
1616 #if (IPV6_SUPPORT == ENABLED)
1617  //IPv6 address?
1618  if(sock->remoteIpAddr.length == sizeof(Ipv6Addr) &&
1619  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1620  {
1621  //Point to the IPv6 address information
1622  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1623 
1624  //Set address family and port number
1625  sa->sin6_family = AF_INET6;
1626  sa->sin6_port = htons(sock->localPort);
1627  sa->sin6_flowinfo = 0;
1628  sa->sin6_scope_id = 0;
1629 
1630  //The socket is not bound to any address
1632 
1633  //Return the actual length of the address
1634  *addrlen = sizeof(SOCKADDR_IN6);
1635  //Successful processing
1636  ret = SOCKET_SUCCESS;
1637  }
1638  else
1639 #endif
1640  {
1641  //The specified length is not valid
1642  socketSetErrnoCode(sock, EINVAL);
1643  ret = SOCKET_ERROR;
1644  }
1645  }
1646  else
1647  {
1648  //The socket is not bound to any address
1650  ret = SOCKET_ERROR;
1651  }
1652 
1653  //Release exclusive access
1654  netUnlock(sock->netContext);
1655 
1656  //return status code
1657  return ret;
1658 }
1659 
1660 
1661 /**
1662  * @brief Retrieves the address of the peer to which a socket is connected
1663  * @param[in] s Descriptor identifying a socket
1664  * @param[out] addr Address of the peer
1665  * @param[in,out] addrlen Length in bytes of the address
1666  * @return If no error occurs, getpeername returns SOCKET_SUCCESS
1667  * Otherwise, it returns SOCKET_ERROR
1668  **/
1669 
1671 {
1672  int_t ret;
1673  NetContext *context;
1674  Socket *sock;
1675 
1676  //Point to the TCP/IP stack context
1677  context = netGetDefaultContext();
1678 
1679  //Make sure the socket descriptor is valid
1680  if(s < 0 || s >= SOCKET_MAX_COUNT)
1681  {
1682  return SOCKET_ERROR;
1683  }
1684 
1685  //Point to the socket structure
1686  sock = &context->socketTable[s];
1687 
1688  //Get exclusive access
1689  netLock(sock->netContext);
1690 
1691  //Check whether the socket is connected to a peer
1692  if(sock->remoteIpAddr.length != 0)
1693  {
1694 #if (IPV4_SUPPORT == ENABLED)
1695  //IPv4 address?
1696  if(sock->remoteIpAddr.length == sizeof(Ipv4Addr) &&
1697  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1698  {
1699  //Point to the IPv4 address information
1700  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1701 
1702  //Set address family and port number
1703  sa->sin_family = AF_INET;
1704  sa->sin_port = htons(sock->remotePort);
1705 
1706  //Copy IPv4 address
1707  sa->sin_addr.s_addr = sock->remoteIpAddr.ipv4Addr;
1708 
1709  //Return the actual length of the address
1710  *addrlen = sizeof(SOCKADDR_IN);
1711  //Successful processing
1712  ret = SOCKET_SUCCESS;
1713  }
1714  else
1715 #endif
1716 #if (IPV6_SUPPORT == ENABLED)
1717  //IPv6 address?
1718  if(sock->remoteIpAddr.length == sizeof(Ipv6Addr) &&
1719  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1720  {
1721  //Point to the IPv6 address information
1722  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1723 
1724  //Set address family and port number
1725  sa->sin6_family = AF_INET6;
1726  sa->sin6_port = htons(sock->remotePort);
1727  sa->sin6_flowinfo = 0;
1728  sa->sin6_scope_id = 0;
1729 
1730  //Copy IPv6 address
1731  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->remoteIpAddr.ipv6Addr);
1732 
1733  //Return the actual length of the address
1734  *addrlen = sizeof(SOCKADDR_IN6);
1735  //Successful processing
1736  ret = SOCKET_SUCCESS;
1737  }
1738  else
1739 #endif
1740  {
1741  //The specified length is not valid
1742  socketSetErrnoCode(sock, EINVAL);
1743  ret = SOCKET_ERROR;
1744  }
1745  }
1746  else
1747  {
1748  //The socket is not connected to any peer
1750  ret = SOCKET_ERROR;
1751  }
1752 
1753  //Release exclusive access
1754  netUnlock(sock->netContext);
1755 
1756  //return status code
1757  return ret;
1758 }
1759 
1760 
1761 /**
1762  * @brief The setsockopt function sets a socket option
1763  * @param[in] s Descriptor that identifies a socket
1764  * @param[in] level The level at which the option is defined
1765  * @param[in] optname The socket option for which the value is to be set
1766  * @param[in] optval A pointer to the buffer in which the value for the
1767  * requested option is specified
1768  * @param[in] optlen The size, in bytes, of the buffer pointed to by the optval
1769  * parameter
1770  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
1771  * Otherwise, it returns SOCKET_ERROR
1772  **/
1773 
1774 int_t setsockopt(int_t s, int_t level, int_t optname, const void *optval,
1775  socklen_t optlen)
1776 {
1777  int_t ret;
1778  NetContext *context;
1779  Socket *sock;
1780 
1781  //Point to the TCP/IP stack context
1782  context = netGetDefaultContext();
1783 
1784  //Make sure the socket descriptor is valid
1785  if(s < 0 || s >= SOCKET_MAX_COUNT)
1786  {
1787  return SOCKET_ERROR;
1788  }
1789 
1790  //Point to the socket structure
1791  sock = &context->socketTable[s];
1792 
1793  //Make sure the option is valid
1794  if(optval != NULL)
1795  {
1796  //Check option level
1797  if(level == SOL_SOCKET)
1798  {
1799  //Check option type
1800  if(optname == SO_REUSEADDR)
1801  {
1802  //Set SO_REUSEADDR option
1803  ret = socketSetSoReuseAddrOption(sock, optval, optlen);
1804  }
1805  else if(optname == SO_BROADCAST)
1806  {
1807  //Set SO_BROADCAST option
1808  ret = socketSetSoBroadcastOption(sock, optval, optlen);
1809  }
1810  else if(optname == SO_SNDTIMEO)
1811  {
1812  //Set SO_SNDTIMEO option
1813  ret = socketSetSoSndTimeoOption(sock, optval, optlen);
1814  }
1815  else if(optname == SO_RCVTIMEO)
1816  {
1817  //Set SO_RCVTIMEO option
1818  ret = socketSetSoRcvTimeoOption(sock, optval, optlen);
1819  }
1820  else if(optname == SO_SNDBUF)
1821  {
1822  //Set SO_SNDBUF option
1823  ret = socketSetSoSndBufOption(sock, optval, optlen);
1824  }
1825  else if(optname == SO_RCVBUF)
1826  {
1827  //Set SO_RCVBUF option
1828  ret = socketSetSoRcvBufOption(sock, optval, optlen);
1829  }
1830  else if(optname == SO_KEEPALIVE)
1831  {
1832  //Set SO_KEEPALIVE option
1833  ret = socketSetSoKeepAliveOption(sock, optval, optlen);
1834  }
1835  else if(optname == SO_NO_CHECK)
1836  {
1837  //Set SO_NO_CHECK option
1838  ret = socketSetSoNoCheckOption(sock, optval, optlen);
1839  }
1840  else if(optname == SO_BINDTODEVICE)
1841  {
1842  //Set SO_BINDTODEVICE option
1843  ret = socketSetSoBindToDeviceOption(sock, optval, optlen);
1844  }
1845  else
1846  {
1847  //Unknown option
1849  //Report an error
1850  ret = SOCKET_ERROR;
1851  }
1852  }
1853  else if(level == IPPROTO_IP)
1854  {
1855  //Check option type
1856  if(optname == IP_TOS)
1857  {
1858  //Set IP_TOS option
1859  ret = socketSetIpTosOption(sock, optval, optlen);
1860  }
1861  else if(optname == IP_TTL)
1862  {
1863  //Set IP_TTL option
1864  ret = socketSetIpTtlOption(sock, optval, optlen);
1865  }
1866  else if(optname == IP_MULTICAST_IF)
1867  {
1868  //Set IP_MULTICAST_IF option
1869  ret = socketSetIpMulticastIfOption(sock, optval, optlen);
1870  }
1871  else if(optname == IP_MULTICAST_TTL)
1872  {
1873  //Set IP_MULTICAST_TTL option
1874  ret = socketSetIpMulticastTtlOption(sock, optval, optlen);
1875  }
1876  else if(optname == IP_MULTICAST_LOOP)
1877  {
1878  //Set IP_MULTICAST_LOOP option
1879  ret = socketSetIpMulticastLoopOption(sock, optval, optlen);
1880  }
1881  else if(optname == IP_ADD_MEMBERSHIP)
1882  {
1883  //Set IP_ADD_MEMBERSHIP option
1884  ret = socketSetIpAddMembershipOption(sock, optval, optlen);
1885  }
1886  else if(optname == IP_DROP_MEMBERSHIP)
1887  {
1888  //Set IP_DROP_MEMBERSHIP option
1889  ret = socketSetIpDropMembershipOption(sock, optval, optlen);
1890  }
1891  else if(optname == IP_BLOCK_SOURCE)
1892  {
1893  //Set IP_BLOCK_SOURCE option
1894  ret = socketSetIpBlockSourceOption(sock, optval, optlen);
1895  }
1896  else if(optname == IP_UNBLOCK_SOURCE)
1897  {
1898  //Set IP_UNBLOCK_SOURCE option
1899  ret = socketSetIpUnblockSourceOption(sock, optval, optlen);
1900  }
1901  else if(optname == IP_ADD_SOURCE_MEMBERSHIP)
1902  {
1903  //Set IP_ADD_SOURCE_MEMBERSHIP option
1904  ret = socketSetIpAddSourceMembershipOption(sock, optval, optlen);
1905  }
1906  else if(optname == IP_DROP_SOURCE_MEMBERSHIP)
1907  {
1908  //Set IP_DROP_SOURCE_MEMBERSHIP option
1909  ret = socketSetIpDropSourceMembershipOption(sock, optval, optlen);
1910  }
1911  else if(optname == MCAST_JOIN_GROUP)
1912  {
1913  //Set MCAST_JOIN_GROUP option
1914  ret = socketSetMcastJoinGroupOption(sock, optval, optlen);
1915  }
1916  else if(optname == MCAST_LEAVE_GROUP)
1917  {
1918  //Set MCAST_LEAVE_GROUP option
1919  ret = socketSetMcastLeaveGroupOption(sock, optval, optlen);
1920  }
1921  else if(optname == MCAST_BLOCK_SOURCE)
1922  {
1923  //Set MCAST_BLOCK_SOURCE option
1924  ret = socketSetMcastBlockSourceOption(sock, optval, optlen);
1925  }
1926  else if(optname == MCAST_UNBLOCK_SOURCE)
1927  {
1928  //Set MCAST_UNBLOCK_SOURCE option
1929  ret = socketSetMcastUnblockSourceOption(sock, optval, optlen);
1930  }
1931  else if(optname == MCAST_JOIN_SOURCE_GROUP)
1932  {
1933  //Set MCAST_JOIN_SOURCE_GROUP option
1934  ret = socketSetMcastJoinSourceGroupOption(sock, optval, optlen);
1935  }
1936  else if(optname == MCAST_LEAVE_SOURCE_GROUP)
1937  {
1938  //Set MCAST_LEAVE_SOURCE_GROUP option
1939  ret = socketSetMcastLeaveSourceGroupOption(sock, optval, optlen);
1940  }
1941  else if(optname == IP_DONTFRAG)
1942  {
1943  //Set IP_DONTFRAG option
1944  ret = socketSetIpDontFragOption(sock, optval, optlen);
1945  }
1946  else if(optname == IP_PKTINFO)
1947  {
1948  //Set IP_PKTINFO option
1949  ret = socketSetIpPktInfoOption(sock, optval, optlen);
1950  }
1951  else if(optname == IP_RECVTOS)
1952  {
1953  //Set IP_RECVTOS option
1954  ret = socketSetIpRecvTosOption(sock, optval, optlen);
1955  }
1956  else if(optname == IP_RECVTTL)
1957  {
1958  //Set IP_RECVTTL option
1959  ret = socketSetIpRecvTtlOption(sock, optval, optlen);
1960  }
1961  else
1962  {
1963  //Unknown option
1965  ret = SOCKET_ERROR;
1966  }
1967  }
1968  else if(level == IPPROTO_IPV6)
1969  {
1970  //Check option type
1971  if(optname == IPV6_TCLASS)
1972  {
1973  //Set IPV6_TCLASS option
1974  ret = socketSetIpv6TrafficClassOption(sock, optval, optlen);
1975  }
1976  else if(optname == IPV6_UNICAST_HOPS)
1977  {
1978  //Set IPV6_UNICAST_HOPS option
1979  ret = socketSetIpv6UnicastHopsOption(sock, optval, optlen);
1980  }
1981  else if(optname == IPV6_MULTICAST_IF)
1982  {
1983  //Set IPV6_MULTICAST_IF option
1984  ret = socketSetIpv6MulticastIfOption(sock, optval, optlen);
1985  }
1986  else if(optname == IPV6_MULTICAST_HOPS)
1987  {
1988  //Set IPV6_MULTICAST_HOPS option
1989  ret = socketSetIpv6MulticastHopsOption(sock, optval, optlen);
1990  }
1991  else if(optname == IPV6_MULTICAST_LOOP)
1992  {
1993  //Set IPV6_MULTICAST_LOOP option
1994  ret = socketSetIpv6MulticastLoopOption(sock, optval, optlen);
1995  }
1996  else if(optname == IPV6_ADD_MEMBERSHIP)
1997  {
1998  //Set IPV6_ADD_MEMBERSHIP option
1999  ret = socketSetIpv6AddMembershipOption(sock, optval, optlen);
2000  }
2001  else if(optname == IPV6_DROP_MEMBERSHIP)
2002  {
2003  //Set IPV6_DROP_MEMBERSHIP option
2004  ret = socketSetIpv6DropMembershipOption(sock, optval, optlen);
2005  }
2006  else if(optname == MCAST_JOIN_GROUP)
2007  {
2008  //Set MCAST_JOIN_GROUP option
2009  ret = socketSetMcastJoinGroupOption(sock, optval, optlen);
2010  }
2011  else if(optname == MCAST_LEAVE_GROUP)
2012  {
2013  //Set MCAST_LEAVE_GROUP option
2014  ret = socketSetMcastLeaveGroupOption(sock, optval, optlen);
2015  }
2016  else if(optname == MCAST_BLOCK_SOURCE)
2017  {
2018  //Set MCAST_BLOCK_SOURCE option
2019  ret = socketSetMcastBlockSourceOption(sock, optval, optlen);
2020  }
2021  else if(optname == MCAST_UNBLOCK_SOURCE)
2022  {
2023  //Set MCAST_UNBLOCK_SOURCE option
2024  ret = socketSetMcastUnblockSourceOption(sock, optval, optlen);
2025  }
2026  else if(optname == MCAST_JOIN_SOURCE_GROUP)
2027  {
2028  //Set MCAST_JOIN_SOURCE_GROUP option
2029  ret = socketSetMcastJoinSourceGroupOption(sock, optval, optlen);
2030  }
2031  else if(optname == MCAST_LEAVE_SOURCE_GROUP)
2032  {
2033  //Set MCAST_LEAVE_SOURCE_GROUP option
2034  ret = socketSetMcastLeaveSourceGroupOption(sock, optval, optlen);
2035  }
2036  else if(optname == IPV6_V6ONLY)
2037  {
2038  //Set IPV6_V6ONLY option
2039  ret = socketSetIpv6OnlyOption(sock, optval, optlen);
2040  }
2041  else if(optname == IPV6_DONTFRAG)
2042  {
2043  //Set IPV6_DONTFRAG option
2044  ret = socketSetIpv6DontFragOption(sock, optval, optlen);
2045  }
2046  else if(optname == IPV6_PKTINFO)
2047  {
2048  //Set IPV6_PKTINFO option
2049  ret = socketSetIpv6PktInfoOption(sock, optval, optlen);
2050  }
2051  else if(optname == IPV6_RECVTCLASS)
2052  {
2053  //Set IPV6_RECVTCLASS option
2054  ret = socketSetIpv6RecvTrafficClassOption(sock, optval, optlen);
2055  }
2056  else if(optname == IPV6_RECVHOPLIMIT)
2057  {
2058  //Set IPV6_RECVHOPLIMIT option
2059  ret = socketSetIpv6RecvHopLimitOption(sock, optval, optlen);
2060  }
2061  else
2062  {
2063  //Unknown option
2065  ret = SOCKET_ERROR;
2066  }
2067  }
2068  else if(level == IPPROTO_TCP)
2069  {
2070  //Check option type
2071  if(optname == TCP_NODELAY)
2072  {
2073  //Set TCP_NODELAY option
2074  ret = socketSetTcpNoDelayOption(sock, optval, optlen);
2075  }
2076  else if(optname == TCP_MAXSEG)
2077  {
2078  //Set TCP_MAXSEG option
2079  ret = socketSetTcpMaxSegOption(sock, optval, optlen);
2080  }
2081  else if(optname == TCP_KEEPIDLE)
2082  {
2083  //Set TCP_KEEPIDLE option
2084  ret = socketSetTcpKeepIdleOption(sock, optval, optlen);
2085  }
2086  else if(optname == TCP_KEEPINTVL)
2087  {
2088  //Set TCP_KEEPINTVL option
2089  ret = socketSetTcpKeepIntvlOption(sock, optval, optlen);
2090  }
2091  else if(optname == TCP_KEEPCNT)
2092  {
2093  //Set TCP_KEEPCNT option
2094  ret = socketSetTcpKeepCntOption(sock, optval, optlen);
2095  }
2096  else
2097  {
2098  //Unknown option
2100  ret = SOCKET_ERROR;
2101  }
2102  }
2103  else
2104  {
2105  //The specified level is not valid
2106  socketSetErrnoCode(sock, EINVAL);
2107  ret = SOCKET_ERROR;
2108  }
2109  }
2110  else
2111  {
2112  //The option is not valid
2113  socketSetErrnoCode(sock, EFAULT);
2114  ret = SOCKET_ERROR;
2115  }
2116 
2117  //return status code
2118  return ret;
2119 }
2120 
2121 
2122 /**
2123  * @brief The getsockopt function retrieves a socket option
2124  * @param[in] s Descriptor that identifies a socket
2125  * @param[in] level The level at which the option is defined
2126  * @param[in] optname The socket option for which the value is to be retrieved
2127  * @param[out] optval A pointer to the buffer in which the value for the
2128  * requested option is to be returned
2129  * @param[in,out] optlen The size, in bytes, of the buffer pointed to by the
2130  * optval parameter
2131  * @return If no error occurs, getsockopt returns SOCKET_SUCCESS
2132  * Otherwise, it returns SOCKET_ERROR
2133  **/
2134 
2135 int_t getsockopt(int_t s, int_t level, int_t optname, void *optval,
2136  socklen_t *optlen)
2137 {
2138  int_t ret;
2139  NetContext *context;
2140  Socket *sock;
2141 
2142  //Point to the TCP/IP stack context
2143  context = netGetDefaultContext();
2144 
2145  //Make sure the socket descriptor is valid
2146  if(s < 0 || s >= SOCKET_MAX_COUNT)
2147  {
2148  return SOCKET_ERROR;
2149  }
2150 
2151  //Point to the socket structure
2152  sock = &context->socketTable[s];
2153 
2154  //Get exclusive access
2155  netLock(sock->netContext);
2156 
2157  //Make sure the option is valid
2158  if(optval != NULL)
2159  {
2160  //Check option level
2161  if(level == SOL_SOCKET)
2162  {
2163  //Check option type
2164  if(optname == SO_REUSEADDR)
2165  {
2166  //Get SO_REUSEADDR option
2167  ret = socketGetSoReuseAddrOption(sock, optval, optlen);
2168  }
2169  else if(optname == SO_TYPE)
2170  {
2171  //Get SO_TYPE option
2172  ret = socketGetSoTypeOption(sock, optval, optlen);
2173  }
2174  else if(optname == SO_ERROR)
2175  {
2176  //Get SO_ERROR option
2177  ret = socketGetSoErrorOption(sock, optval, optlen);
2178  }
2179  else if(optname == SO_BROADCAST)
2180  {
2181  //Get SO_BROADCAST option
2182  ret = socketGetSoBroadcastOption(sock, optval, optlen);
2183  }
2184  else if(optname == SO_SNDTIMEO)
2185  {
2186  //Get SO_SNDTIMEO option
2187  ret = socketGetSoSndTimeoOption(sock, optval, optlen);
2188  }
2189  else if(optname == SO_RCVTIMEO)
2190  {
2191  //Get SO_RCVTIMEO option
2192  ret = socketGetSoRcvTimeoOption(sock, optval, optlen);
2193  }
2194  else if(optname == SO_SNDBUF)
2195  {
2196  //Get SO_SNDBUF option
2197  ret = socketGetSoSndBufOption(sock, optval, optlen);
2198  }
2199  else if(optname == SO_RCVBUF)
2200  {
2201  //Get SO_RCVBUF option
2202  ret = socketGetSoRcvBufOption(sock, optval, optlen);
2203  }
2204  else if(optname == SO_KEEPALIVE)
2205  {
2206  //Get SO_KEEPALIVE option
2207  ret = socketGetSoKeepAliveOption(sock, optval, optlen);
2208  }
2209  else if(optname == SO_NO_CHECK)
2210  {
2211  //Get SO_NO_CHECK option
2212  ret = socketGetSoNoCheckOption(sock, optval, optlen);
2213  }
2214  else
2215  {
2216  //Unknown option
2218  ret = SOCKET_ERROR;
2219  }
2220  }
2221  else if(level == IPPROTO_IP)
2222  {
2223  //Check option type
2224  if(optname == IP_TOS)
2225  {
2226  //Get IP_TOS option
2227  ret = socketGetIpTosOption(sock, optval, optlen);
2228  }
2229  else if(optname == IP_TTL)
2230  {
2231  //Get IP_TTL option
2232  ret = socketGetIpTtlOption(sock, optval, optlen);
2233  }
2234  else if(optname == IP_MULTICAST_TTL)
2235  {
2236  //Get IP_MULTICAST_TTL option
2237  ret = socketGetIpMulticastTtlOption(sock, optval, optlen);
2238  }
2239  else if(optname == IP_MULTICAST_LOOP)
2240  {
2241  //Get IP_MULTICAST_LOOP option
2242  ret = socketGetIpMulticastLoopOption(sock, optval, optlen);
2243  }
2244  else if(optname == IP_ADD_MEMBERSHIP ||
2245  optname == IP_DROP_MEMBERSHIP ||
2246  optname == IP_BLOCK_SOURCE ||
2247  optname == IP_UNBLOCK_SOURCE ||
2248  optname == IP_ADD_SOURCE_MEMBERSHIP ||
2249  optname == IP_DROP_SOURCE_MEMBERSHIP ||
2250  optname == MCAST_JOIN_GROUP ||
2251  optname == MCAST_LEAVE_GROUP ||
2252  optname == MCAST_BLOCK_SOURCE ||
2253  optname == MCAST_UNBLOCK_SOURCE ||
2254  optname == MCAST_JOIN_SOURCE_GROUP ||
2255  optname == MCAST_LEAVE_SOURCE_GROUP)
2256  {
2257  //When any of these options are used with getsockopt, the error
2258  //generated is EOPNOTSUPP (refer to RFC 3678, section 4.1.3)
2260  ret = SOCKET_ERROR;
2261  }
2262  else if(optname == IP_DONTFRAG)
2263  {
2264  //Get IP_DONTFRAG option
2265  ret = socketGetIpDontFragOption(sock, optval, optlen);
2266  }
2267  else if(optname == IP_PKTINFO)
2268  {
2269  //Get IP_PKTINFO option
2270  ret = socketGetIpPktInfoOption(sock, optval, optlen);
2271  }
2272  else if(optname == IP_RECVTOS)
2273  {
2274  //Get IP_RECVTOS option
2275  ret = socketGetIpRecvTosOption(sock, optval, optlen);
2276  }
2277  else if(optname == IP_RECVTTL)
2278  {
2279  //Get IP_RECVTTL option
2280  ret = socketGetIpRecvTtlOption(sock, optval, optlen);
2281  }
2282  else
2283  {
2284  //Unknown option
2286  ret = SOCKET_ERROR;
2287  }
2288  }
2289  else if(level == IPPROTO_IPV6)
2290  {
2291  //Check option type
2292  if(optname == IPV6_TCLASS)
2293  {
2294  //Get IPV6_TCLASS option
2295  ret = socketGetIpv6TrafficClassOption(sock, optval, optlen);
2296  }
2297  else if(optname == IPV6_UNICAST_HOPS)
2298  {
2299  //Get IPV6_UNICAST_HOPS option
2300  ret = socketGetIpv6UnicastHopsOption(sock, optval, optlen);
2301  }
2302  else if(optname == IPV6_MULTICAST_HOPS)
2303  {
2304  //Get IPV6_MULTICAST_HOPS option
2305  ret = socketGetIpv6MulticastHopsOption(sock, optval, optlen);
2306  }
2307  else if(optname == IPV6_MULTICAST_LOOP)
2308  {
2309  //Get IPV6_MULTICAST_LOOP option
2310  ret = socketGetIpv6MulticastLoopOption(sock, optval, optlen);
2311  }
2312  else if(optname == IPV6_ADD_MEMBERSHIP ||
2313  optname == IPV6_DROP_MEMBERSHIP ||
2314  optname == MCAST_JOIN_GROUP ||
2315  optname == MCAST_LEAVE_GROUP ||
2316  optname == MCAST_BLOCK_SOURCE ||
2317  optname == MCAST_UNBLOCK_SOURCE ||
2318  optname == MCAST_JOIN_SOURCE_GROUP ||
2319  optname == MCAST_LEAVE_SOURCE_GROUP)
2320  {
2321  //When any of these options are used with getsockopt, the error
2322  //generated is EOPNOTSUPP
2324  ret = SOCKET_ERROR;
2325  }
2326  else if(optname == IPV6_V6ONLY)
2327  {
2328  //Get IPV6_V6ONLY option
2329  ret = socketGetIpv6OnlyOption(sock, optval, optlen);
2330  }
2331  else if(optname == IPV6_DONTFRAG)
2332  {
2333  //Get IPV6_DONTFRAG option
2334  ret = socketGetIpv6DontFragOption(sock, optval, optlen);
2335  }
2336  else if(optname == IPV6_PKTINFO)
2337  {
2338  //Get IPV6_PKTINFO option
2339  ret = socketGetIpv6PktInfoOption(sock, optval, optlen);
2340  }
2341  else if(optname == IPV6_RECVTCLASS)
2342  {
2343  //Get IPV6_RECVTCLASS option
2344  ret = socketGetIpv6RecvTrafficClassOption(sock, optval, optlen);
2345  }
2346  else if(optname == IPV6_RECVHOPLIMIT)
2347  {
2348  //Get IPV6_RECVHOPLIMIT option
2349  ret = socketGetIpv6RecvHopLimitOption(sock, optval, optlen);
2350  }
2351  else
2352  {
2353  //Unknown option
2355  ret = SOCKET_ERROR;
2356  }
2357  }
2358  else if(level == IPPROTO_TCP)
2359  {
2360  //Check option type
2361  if(optname == TCP_NODELAY)
2362  {
2363  //Get TCP_NODELAY option
2364  ret = socketGetTcpNoDelayOption(sock, optval, optlen);
2365  }
2366  else if(optname == TCP_MAXSEG)
2367  {
2368  //Get TCP_MAXSEG option
2369  ret = socketGetTcpMaxSegOption(sock, optval, optlen);
2370  }
2371  else if(optname == TCP_KEEPIDLE)
2372  {
2373  //Get TCP_KEEPIDLE option
2374  ret = socketGetTcpKeepIdleOption(sock, optval, optlen);
2375  }
2376  else if(optname == TCP_KEEPINTVL)
2377  {
2378  //Get TCP_KEEPINTVL option
2379  ret = socketGetTcpKeepIntvlOption(sock, optval, optlen);
2380  }
2381  else if(optname == TCP_KEEPCNT)
2382  {
2383  //Get TCP_KEEPCNT option
2384  ret = socketGetTcpKeepCntOption(sock, optval, optlen);
2385  }
2386  else
2387  {
2388  //Unknown option
2390  ret = SOCKET_ERROR;
2391  }
2392  }
2393  else
2394  {
2395  //The specified level is not valid
2396  socketSetErrnoCode(sock, EINVAL);
2397  ret = SOCKET_ERROR;
2398  }
2399  }
2400  else
2401  {
2402  //The option is not valid
2403  socketSetErrnoCode(sock, EFAULT);
2404  ret = SOCKET_ERROR;
2405  }
2406 
2407  //Release exclusive access
2408  netUnlock(sock->netContext);
2409 
2410  //return status code
2411  return ret;
2412 }
2413 
2414 
2415 /**
2416  * @brief Set multicast source filter (IPv4 only)
2417  * @param[in] s Descriptor that identifies a socket
2418  * @param[in] interface Local IP address of the interface
2419  * @param[in] group IP multicast address of the group
2420  * @param[in] fmode Multicast filter mode (MCAST_INCLUDE or MCAST_EXCLUDE)
2421  * @param[in] numsrc Number of source addresses in the slist array
2422  * @param[in] slist Array of IP addresses of sources to include or exclude
2423  * depending on the filter mode
2424  * @return If no error occurs, setipv4sourcefilter returns SOCKET_SUCCESS
2425  * Otherwise, it returns SOCKET_ERROR
2426  **/
2427 
2428 int_t setipv4sourcefilter(int_t s, struct in_addr interface, struct in_addr group,
2429  uint32_t fmode, uint_t numsrc, struct in_addr *slist)
2430 {
2431 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
2432  error_t error;
2433  uint_t i;
2434  Socket *sock;
2435  IpFilterMode filterMode;
2436  IpAddr groupAddr;
2438 
2439  //Make sure the socket descriptor is valid
2440  if(s < 0 || s >= SOCKET_MAX_COUNT)
2441  {
2442  return SOCKET_ERROR;
2443  }
2444 
2445  //Point to the socket structure
2446  sock = &socketTable[s];
2447 
2448  //Copy group address
2449  groupAddr.length = sizeof(Ipv4Addr);
2450  groupAddr.ipv4Addr = group.s_addr;
2451 
2452  //Check filter mode
2453  if(fmode == MCAST_INCLUDE)
2454  {
2455  //Select source-specific filter mode
2456  filterMode = IP_FILTER_MODE_INCLUDE;
2457  }
2458  else if(fmode == MCAST_INCLUDE)
2459  {
2460  //Select any-source filter mode
2461  filterMode = IP_FILTER_MODE_EXCLUDE;
2462  }
2463  else
2464  {
2465  //Report an error
2466  socketSetErrnoCode(sock, EINVAL);
2467  return SOCKET_ERROR;
2468  }
2469 
2470  //If the implementation imposes a limit on the maximum number of sources
2471  //in a source filter, ENOBUFS is generated when the operation would exceed
2472  //the maximum (refer to RFC3678, section 4.2.1)
2473  if(numsrc > SOCKET_MAX_MULTICAST_SOURCES)
2474  {
2475  socketSetErrnoCode(sock, ENOBUFS);
2476  return SOCKET_ERROR;
2477  }
2478 
2479  //If numsrc is 0, a NULL pointer may be supplied
2480  if(numsrc > 0 && slist == NULL)
2481  {
2482  socketSetErrnoCode(sock, EINVAL);
2483  return SOCKET_ERROR;
2484  }
2485 
2486  //Copy the list of source addresses to include or exclude
2487  for(i = 0; i < numsrc; i++)
2488  {
2489  sources[i].length = sizeof(Ipv4Addr);
2490  sources[i].ipv4Addr = slist[i].s_addr;
2491  }
2492 
2493  //Set multicast source filter
2494  error = socketSetMulticastSourceFilter(sock, &groupAddr, filterMode,
2495  sources, numsrc);
2496 
2497  //Any error to report?
2498  if(error)
2499  {
2500  socketTranslateErrorCode(sock, error);
2501  return SOCKET_ERROR;
2502  }
2503 
2504  //Successful processing
2505  return SOCKET_SUCCESS;
2506 #else
2507  //Not implemented
2508  return SOCKET_ERROR;
2509 #endif
2510 }
2511 
2512 
2513 /**
2514  * @brief Get multicast source filter (IPv4 only)
2515  * @param[in] s Descriptor that identifies a socket
2516  * @param[in] interface Local IP address of the interface
2517  * @param[in] group IP multicast address of the group
2518  * @param[out] fmode Multicast filter mode (MCAST_INCLUDE or MCAST_EXCLUDE)
2519  * @param[out] numsrc On input, the numsrc argument holds the number of source
2520  * addresses that will fit in the slist array. On output, the numsrc argument
2521  * will hold the total number of sources in the filter
2522  * @param[out] slist Buffer into which an array of IP addresses of included or
2523  * excluded (depending on the filter mode) sources will be written. If numsrc
2524  * was 0 on input, a NULL pointer may be supplied
2525  * @return If no error occurs, setipv4sourcefilter returns SOCKET_SUCCESS
2526  * Otherwise, it returns SOCKET_ERROR
2527  **/
2528 
2529 int_t getipv4sourcefilter(int_t s, struct in_addr interface, struct in_addr group,
2530  uint32_t *fmode, uint_t *numsrc, struct in_addr *slist)
2531 {
2532 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
2533  error_t error;
2534  uint_t i;
2535  uint_t numSources;
2536  Socket *sock;
2537  IpFilterMode filterMode;
2538  IpAddr groupAddr;
2540 
2541  //Make sure the socket descriptor is valid
2542  if(s < 0 || s >= SOCKET_MAX_COUNT)
2543  {
2544  return SOCKET_ERROR;
2545  }
2546 
2547  //Point to the socket structure
2548  sock = &socketTable[s];
2549 
2550  //Check parameters
2551  if(fmode == NULL || numsrc == NULL)
2552  {
2553  socketSetErrnoCode(sock, EINVAL);
2554  return SOCKET_ERROR;
2555  }
2556 
2557  //If numsrc was 0 on input, a NULL pointer may be supplied
2558  if(*numsrc > 0 && slist == NULL)
2559  {
2560  socketSetErrnoCode(sock, EINVAL);
2561  return SOCKET_ERROR;
2562  }
2563 
2564  //Copy group address
2565  groupAddr.length = sizeof(Ipv4Addr);
2566  groupAddr.ipv4Addr = group.s_addr;
2567 
2568  //Set multicast source filter
2569  error = socketGetMulticastSourceFilter(sock, &groupAddr, &filterMode,
2570  sources, &numSources);
2571 
2572  //Any error to report?
2573  if(error)
2574  {
2575  socketTranslateErrorCode(sock, error);
2576  return SOCKET_ERROR;
2577  }
2578 
2579  //Filter mode
2580  if(filterMode == IP_FILTER_MODE_INCLUDE)
2581  {
2582  *fmode = MCAST_INCLUDE;
2583  }
2584  else
2585  {
2586  *fmode = MCAST_EXCLUDE;
2587  }
2588 
2589  //The slist parameter will hold as many source addresses as fit, up to the
2590  //minimum of the array size passed in as the original numsrc value and the
2591  //total number of sources in the filter (refer to RFC3678, section 4.2.2)
2592  for(i = 0; i < *numsrc && i < numSources; i++)
2593  {
2594  slist[i].s_addr = sources[i].ipv4Addr;
2595  }
2596 
2597  //On return, numsrc is always updated to be the total number of sources in
2598  //the filter
2599  *numsrc = numSources;
2600 
2601  //Successful processing
2602  return SOCKET_SUCCESS;
2603 #else
2604  //Not implemented
2605  return SOCKET_ERROR;
2606 #endif
2607 }
2608 
2609 
2610 /**
2611  * @brief Set multicast source filter
2612  * @param[in] s Descriptor that identifies a socket
2613  * @param[in] interface Local IP address of the interface
2614  * @param[in] group IP multicast address of the group
2615  * @param[in] grouplen Length in bytes of the group
2616  * @param[in] fmode Multicast filter mode (MCAST_INCLUDE or MCAST_EXCLUDE)
2617  * @param[in] numsrc Number of source addresses in the slist array
2618  * @param[in] slist Array of IP addresses of sources to include or exclude
2619  * depending on the filter mode
2620  * @return If no error occurs, setipv4sourcefilter returns SOCKET_SUCCESS
2621  * Otherwise, it returns SOCKET_ERROR
2622  **/
2623 
2624 int_t setsourcefilter(int_t s, uint32_t interface, struct sockaddr *group,
2625  socklen_t grouplen, uint32_t fmode, uint_t numsrc,
2626  struct sockaddr_storage *slist)
2627 {
2628 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
2629  error_t error;
2630  uint_t i;
2631  Socket *sock;
2632  IpFilterMode filterMode;
2633  IpAddr groupAddr;
2635 
2636  //Make sure the socket descriptor is valid
2637  if(s < 0 || s >= SOCKET_MAX_COUNT)
2638  {
2639  return SOCKET_ERROR;
2640  }
2641 
2642  //Point to the socket structure
2643  sock = &socketTable[s];
2644 
2645 #if (IPV4_SUPPORT == ENABLED)
2646  //IPv4 group address?
2647  if(group->sa_family == AF_INET &&
2648  grouplen >= (socklen_t) sizeof(SOCKADDR_IN))
2649  {
2650  //Point to the IPv4 address information
2651  SOCKADDR_IN *sa = (SOCKADDR_IN *) group;
2652 
2653  //Copy IPv4 address
2654  groupAddr.length = sizeof(Ipv4Addr);
2655  groupAddr.ipv4Addr = sa->sin_addr.s_addr;
2656  }
2657  else
2658 #endif
2659 #if (IPV6_SUPPORT == ENABLED)
2660  //IPv6 group address?
2661  if(group->sa_family == AF_INET6 &&
2662  grouplen >= (socklen_t) sizeof(SOCKADDR_IN6))
2663  {
2664  //Point to the IPv6 address information
2665  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) group;
2666 
2667  //Copy IPv6 address
2668  groupAddr.length = sizeof(Ipv6Addr);
2669  ipv6CopyAddr(&groupAddr.ipv6Addr, sa->sin6_addr.s6_addr);
2670  }
2671  else
2672 #endif
2673  //Invalid group address?
2674  {
2675  //Report an error
2676  socketSetErrnoCode(sock, EINVAL);
2677  return SOCKET_ERROR;
2678  }
2679 
2680  //Check filter mode
2681  if(fmode == MCAST_INCLUDE)
2682  {
2683  //Select source-specific filter mode
2684  filterMode = IP_FILTER_MODE_INCLUDE;
2685  }
2686  else if(fmode == MCAST_INCLUDE)
2687  {
2688  //Select any-source filter mode
2689  filterMode = IP_FILTER_MODE_EXCLUDE;
2690  }
2691  else
2692  {
2693  //Report an error
2694  socketSetErrnoCode(sock, EINVAL);
2695  return SOCKET_ERROR;
2696  }
2697 
2698  //If the implementation imposes a limit on the maximum number of sources
2699  //in a source filter, ENOBUFS is generated when the operation would exceed
2700  //the maximum (refer to RFC3678, section 5.2.1)
2701  if(numsrc > SOCKET_MAX_MULTICAST_SOURCES)
2702  {
2703  socketSetErrnoCode(sock, ENOBUFS);
2704  return SOCKET_ERROR;
2705  }
2706 
2707  //If numsrc is 0, a NULL pointer may be supplied
2708  if(numsrc > 0 && slist == NULL)
2709  {
2710  socketSetErrnoCode(sock, EINVAL);
2711  return SOCKET_ERROR;
2712  }
2713 
2714  //Copy the list of source addresses to include or exclude
2715  for(i = 0; i < numsrc; i++)
2716  {
2717 #if (IPV4_SUPPORT == ENABLED)
2718  //IPv4 source address?
2719  if(slist[i].ss_family == AF_INET &&
2720  slist[i].ss_family == group->sa_family)
2721  {
2722  //Point to the IPv4 address information
2723  SOCKADDR_IN *sa = (SOCKADDR_IN *) &slist[i];
2724 
2725  //Copy IPv4 address
2726  sources[i].length = sizeof(Ipv4Addr);
2727  sources[i].ipv4Addr = sa->sin_addr.s_addr;
2728  }
2729  else
2730 #endif
2731 #if (IPV6_SUPPORT == ENABLED)
2732  //IPv6 source address?
2733  if(slist[i].ss_family == AF_INET6 &&
2734  slist[i].ss_family == group->sa_family)
2735  {
2736  //Point to the IPv6 address information
2737  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) &slist[i];
2738 
2739  //Copy IPv6 address
2740  sources[i].length = sizeof(Ipv6Addr);
2741  ipv6CopyAddr(&sources[i].ipv6Addr, sa->sin6_addr.s6_addr);
2742  }
2743  else
2744 #endif
2745  //Invalid source address?
2746  {
2747  //Report an error
2748  socketSetErrnoCode(sock, EINVAL);
2749  return SOCKET_ERROR;
2750  }
2751  }
2752 
2753  //Set multicast source filter
2754  error = socketSetMulticastSourceFilter(sock, &groupAddr, filterMode,
2755  sources, numsrc);
2756 
2757  //Any error to report?
2758  if(error)
2759  {
2760  socketTranslateErrorCode(sock, error);
2761  return SOCKET_ERROR;
2762  }
2763 
2764  //Successful processing
2765  return SOCKET_SUCCESS;
2766 #else
2767  //Not implemented
2768  return SOCKET_ERROR;
2769 #endif
2770 }
2771 
2772 
2773 /**
2774  * @brief Get multicast source filter
2775  * @param[in] s Descriptor that identifies a socket
2776  * @param[in] interface Local IP address of the interface
2777  * @param[in] group IP multicast address of the group
2778  * @param[in] grouplen Length in bytes of the group
2779  * @param[out] fmode Multicast filter mode (MCAST_INCLUDE or MCAST_EXCLUDE)
2780  * @param[out] numsrc On input, the numsrc argument holds the number of source
2781  * addresses that will fit in the slist array. On output, the numsrc argument
2782  * will hold the total number of sources in the filter
2783  * @param[out] slist Buffer into which an array of IP addresses of included or
2784  * excluded (depending on the filter mode) sources will be written. If numsrc
2785  * was 0 on input, a NULL pointer may be supplied
2786  * @return If no error occurs, setipv4sourcefilter returns SOCKET_SUCCESS
2787  * Otherwise, it returns SOCKET_ERROR
2788  **/
2789 
2790 int_t getsourcefilter(int_t s, uint32_t interface, struct sockaddr *group,
2791  socklen_t grouplen, uint32_t *fmode, uint_t *numsrc,
2792  struct sockaddr_storage *slist)
2793 {
2794 #if (SOCKET_MAX_MULTICAST_SOURCES > 0)
2795  error_t error;
2796  uint_t i;
2797  uint_t numSources;
2798  Socket *sock;
2799  IpFilterMode filterMode;
2800  IpAddr groupAddr;
2802 
2803  //Make sure the socket descriptor is valid
2804  if(s < 0 || s >= SOCKET_MAX_COUNT)
2805  {
2806  return SOCKET_ERROR;
2807  }
2808 
2809  //Point to the socket structure
2810  sock = &socketTable[s];
2811 
2812  //Check parameters
2813  if(fmode == NULL || numsrc == NULL)
2814  {
2815  socketSetErrnoCode(sock, EINVAL);
2816  return SOCKET_ERROR;
2817  }
2818 
2819  //If numsrc was 0 on input, a NULL pointer may be supplied
2820  if(*numsrc > 0 && slist == NULL)
2821  {
2822  socketSetErrnoCode(sock, EINVAL);
2823  return SOCKET_ERROR;
2824  }
2825 
2826 #if (IPV4_SUPPORT == ENABLED)
2827  //IPv4 group address?
2828  if(group->sa_family == AF_INET &&
2829  grouplen >= (socklen_t) sizeof(SOCKADDR_IN))
2830  {
2831  //Point to the IPv4 address information
2832  SOCKADDR_IN *sa = (SOCKADDR_IN *) group;
2833 
2834  //Copy IPv4 address
2835  groupAddr.length = sizeof(Ipv4Addr);
2836  groupAddr.ipv4Addr = sa->sin_addr.s_addr;
2837  }
2838  else
2839 #endif
2840 #if (IPV6_SUPPORT == ENABLED)
2841  //IPv6 group address?
2842  if(group->sa_family == AF_INET6 &&
2843  grouplen >= (socklen_t) sizeof(SOCKADDR_IN6))
2844  {
2845  //Point to the IPv6 address information
2846  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) group;
2847 
2848  //Copy IPv6 address
2849  groupAddr.length = sizeof(Ipv6Addr);
2850  ipv6CopyAddr(&groupAddr.ipv6Addr, sa->sin6_addr.s6_addr);
2851  }
2852  else
2853 #endif
2854  //Invalid group address?
2855  {
2856  //Report an error
2857  socketSetErrnoCode(sock, EINVAL);
2858  return SOCKET_ERROR;
2859  }
2860 
2861  //Set multicast source filter
2862  error = socketGetMulticastSourceFilter(sock, &groupAddr, &filterMode,
2863  sources, &numSources);
2864 
2865  //Any error to report?
2866  if(error)
2867  {
2868  socketTranslateErrorCode(sock, error);
2869  return SOCKET_ERROR;
2870  }
2871 
2872  //Filter mode
2873  if(filterMode == IP_FILTER_MODE_INCLUDE)
2874  {
2875  *fmode = MCAST_INCLUDE;
2876  }
2877  else
2878  {
2879  *fmode = MCAST_EXCLUDE;
2880  }
2881 
2882  //The slist parameter will hold as many source addresses as fit, up to the
2883  //minimum of the array size passed in as the original numsrc value and the
2884  //total number of sources in the filter (refer to RFC3678, section 5.2.2)
2885  for(i = 0; i < *numsrc && i < numSources; i++)
2886  {
2887 #if (IPV4_SUPPORT == ENABLED)
2888  //IPv4 source address?
2889  if(sock->localIpAddr.length == sizeof(Ipv4Addr))
2890  {
2891  //Point to the IPv4 address information
2892  SOCKADDR_IN *sa = (SOCKADDR_IN *) &slist[i];
2893 
2894  //Set address family and port number
2895  sa->sin_family = AF_INET;
2896  sa->sin_port = 0;
2897 
2898  //Copy IPv4 address
2899  sa->sin_addr.s_addr = sources[i].ipv4Addr;
2900  }
2901  else
2902 #endif
2903 #if (IPV6_SUPPORT == ENABLED)
2904  //IPv6 source address?
2905  if(sock->localIpAddr.length == sizeof(Ipv6Addr))
2906  {
2907  //Point to the IPv4 address information
2908  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) &slist[i];
2909 
2910  //Set address family and port number
2911  sa->sin6_family = AF_INET6;
2912  sa->sin6_port = 0;
2913  sa->sin6_flowinfo = 0;
2914  sa->sin6_scope_id = 0;
2915 
2916  //Copy IPv6 address
2917  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sources[i].ipv6Addr);
2918  }
2919  else
2920 #endif
2921  //Invalid source address?
2922  {
2923  //Just for sanity
2924  osMemset(&slist[i], 0, sizeof(SOCKADDR_STORAGE));
2925  }
2926  }
2927 
2928  //On return, numsrc is always updated to be the total number of sources in
2929  //the filter
2930  *numsrc = numSources;
2931 
2932  //Successful processing
2933  return SOCKET_SUCCESS;
2934 #else
2935  //Not implemented
2936  return SOCKET_ERROR;
2937 #endif
2938 }
2939 
2940 
2941 /**
2942  * @brief Control the I/O mode of a socket
2943  * @param[in] s Descriptor that identifies a socket
2944  * @param[in] cmd A command to perform on the socket
2945  * @param[in,out] arg A pointer to a parameter
2946  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
2947  * Otherwise, it returns SOCKET_ERROR
2948  **/
2949 
2950 int_t ioctlsocket(int_t s, uint32_t cmd, void *arg)
2951 {
2952  int_t ret;
2953  uint_t *val;
2954  NetContext *context;
2955  Socket *sock;
2956 
2957  //Point to the TCP/IP stack context
2958  context = netGetDefaultContext();
2959 
2960  //Make sure the socket descriptor is valid
2961  if(s < 0 || s >= SOCKET_MAX_COUNT)
2962  {
2963  return SOCKET_ERROR;
2964  }
2965 
2966  //Point to the socket structure
2967  sock = &context->socketTable[s];
2968 
2969  //Get exclusive access
2970  netLock(sock->netContext);
2971 
2972  //Make sure the parameter is valid
2973  if(arg != NULL)
2974  {
2975  //Check command type
2976  switch(cmd)
2977  {
2978  //Enable or disable non-blocking mode
2979  case FIONBIO:
2980  //Cast the parameter to the relevant type
2981  val = (uint_t *) arg;
2982  //Enable blocking or non-blocking operation
2983  sock->timeout = (*val != 0) ? 0 : INFINITE_DELAY;
2984  //Successful processing
2985  ret = SOCKET_SUCCESS;
2986  break;
2987 
2988 #if (TCP_SUPPORT == ENABLED)
2989  //Get the number of bytes that are immediately available for reading
2990  case FIONREAD:
2991  //Cast the parameter to the relevant type
2992  val = (uint_t *) arg;
2993  //Return the actual value
2994  *val = sock->rcvUser;
2995  //Successful processing
2996  ret = SOCKET_SUCCESS;
2997  break;
2998 
2999  //Get the number of bytes written to the send queue but not yet
3000  //acknowledged by the other side of the connection
3001  case FIONWRITE:
3002  //Cast the parameter to the relevant type
3003  val = (uint_t *) arg;
3004  //Return the actual value
3005  *val = sock->sndUser + sock->sndNxt - sock->sndUna;
3006  //Successful processing
3007  ret = SOCKET_SUCCESS;
3008  break;
3009 
3010  //Get the free space in the send queue
3011  case FIONSPACE:
3012  //Cast the parameter to the relevant type
3013  val = (uint_t *) arg;
3014  //Return the actual value
3015  *val = sock->txBufferSize - (sock->sndUser + sock->sndNxt -
3016  sock->sndUna);
3017  //Successful processing
3018  ret = SOCKET_SUCCESS;
3019  break;
3020 #endif
3021 
3022  //Unknown command?
3023  default:
3024  //Report an error
3025  socketSetErrnoCode(sock, EINVAL);
3026  ret = SOCKET_ERROR;
3027  break;
3028  }
3029  }
3030  else
3031  {
3032  //The parameter is not valid
3033  socketSetErrnoCode(sock, EFAULT);
3034  ret = SOCKET_ERROR;
3035  }
3036 
3037  //Release exclusive access
3038  netUnlock(sock->netContext);
3039 
3040  //return status code
3041  return ret;
3042 }
3043 
3044 
3045 /**
3046  * @brief Perform specific operation
3047  * @param[in] s Descriptor that identifies a socket
3048  * @param[in] cmd A command to perform on the socket
3049  * @param[in] arg Argument value
3050  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
3051  * Otherwise, it returns SOCKET_ERROR
3052  **/
3053 
3055 {
3056  int_t ret;
3057  NetContext *context;
3058  Socket *sock;
3059 
3060  //Point to the TCP/IP stack context
3061  context = netGetDefaultContext();
3062 
3063  //Make sure the socket descriptor is valid
3064  if(s < 0 || s >= SOCKET_MAX_COUNT)
3065  {
3066  return SOCKET_ERROR;
3067  }
3068 
3069  //Point to the socket structure
3070  sock = &context->socketTable[s];
3071 
3072  //Get exclusive access
3073  netLock(sock->netContext);
3074 
3075  //Check command type
3076  switch(cmd)
3077  {
3078  //Get the file status flags?
3079  case F_GETFL:
3080  //Return (as the function result) the file descriptor flags
3081  ret = (sock->timeout == 0) ? O_NONBLOCK : 0;
3082  break;
3083 
3084  //Set the file status flags?
3085  case F_SETFL:
3086  //Enable blocking or non-blocking operation
3087  sock->timeout = ((arg & O_NONBLOCK) != 0) ? 0 : INFINITE_DELAY;
3088  //Successful processing
3089  ret = SOCKET_SUCCESS;
3090  break;
3091 
3092  //Unknown command?
3093  default:
3094  //Report an error
3095  socketSetErrnoCode(sock, EINVAL);
3096  ret = SOCKET_ERROR;
3097  break;
3098  }
3099 
3100  //Release exclusive access
3101  netUnlock(sock->netContext);
3102 
3103  //return status code
3104  return ret;
3105 }
3106 
3107 
3108 /**
3109  * @brief The shutdown function disables sends or receives on a socket
3110  * @param[in] s Descriptor that identifies a socket
3111  * @param[in] how A flag that describes what types of operation will no longer be allowed
3112  * @return If no error occurs, shutdown returns SOCKET_SUCCESS
3113  * Otherwise, it returns SOCKET_ERROR
3114  **/
3115 
3117 {
3118  error_t error;
3119  NetContext *context;
3120  Socket *sock;
3121 
3122  //Point to the TCP/IP stack context
3123  context = netGetDefaultContext();
3124 
3125  //Make sure the socket descriptor is valid
3126  if(s < 0 || s >= SOCKET_MAX_COUNT)
3127  {
3128  return SOCKET_ERROR;
3129  }
3130 
3131  //Point to the socket structure
3132  sock = &context->socketTable[s];
3133 
3134  //Shut down socket
3135  error = socketShutdown(sock, how);
3136 
3137  //Any error to report?
3138  if(error)
3139  {
3140  socketTranslateErrorCode(sock, error);
3141  return SOCKET_ERROR;
3142  }
3143 
3144  //Successful processing
3145  return SOCKET_SUCCESS;
3146 }
3147 
3148 
3149 /**
3150  * @brief The closesocket function closes an existing socket
3151  * @param[in] s Descriptor that identifies a socket
3152  * @return If no error occurs, closesocket returns SOCKET_SUCCESS
3153  * Otherwise, it returns SOCKET_ERROR
3154  **/
3155 
3157 {
3158  NetContext *context;
3159  Socket *sock;
3160 
3161  //Point to the TCP/IP stack context
3162  context = netGetDefaultContext();
3163 
3164  //Make sure the socket descriptor is valid
3165  if(s < 0 || s >= SOCKET_MAX_COUNT)
3166  {
3167  return SOCKET_ERROR;
3168  }
3169 
3170  //Point to the socket structure
3171  sock = &context->socketTable[s];
3172 
3173  //Close socket
3174  socketClose(sock);
3175 
3176  //Successful processing
3177  return SOCKET_SUCCESS;
3178 }
3179 
3180 
3181 /**
3182  * @brief Determine the status of one or more sockets
3183  *
3184  * The select function determines the status of one or more sockets,
3185  * waiting if necessary, to perform synchronous I/O
3186  *
3187  * @param[in] nfds Unused parameter included only for compatibility with
3188  * Berkeley socket
3189  * @param[in,out] readfds An optional pointer to a set of sockets to be
3190  * checked for readability
3191  * @param[in,out] writefds An optional pointer to a set of sockets to be
3192  * checked for writability
3193  * @param[in,out] exceptfds An optional pointer to a set of sockets to be
3194  * checked for errors
3195  * @param[in] timeout The maximum time for select to wait. Set the timeout
3196  * parameter to null for blocking operations
3197  * @return The select function returns the total number of socket handles that
3198  * are ready and contained in the fd_set structures, zero if the time limit
3199  * expired, or SOCKET_ERROR if an error occurred
3200  **/
3201 
3202 int_t select(int_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
3203  const struct timeval *timeout)
3204 {
3205  int_t i;
3206  int_t j;
3207  int_t n;
3208  int_t s;
3209  systime_t time;
3210  uint_t eventMask;
3211  uint_t eventFlags;
3212  OsEvent event;
3213  fd_set *fds;
3214  NetContext *context;
3215 
3216  //Point to the TCP/IP stack context
3217  context = netGetDefaultContext();
3218 
3219  //Parse all the descriptor sets
3220  for(i = 0; i < 3; i++)
3221  {
3222  //Select the suitable descriptor set
3223  switch(i)
3224  {
3225  case 0:
3226  //Set of sockets to be checked for readability
3227  fds = readfds;
3228  break;
3229 
3230  case 1:
3231  //Set of sockets to be checked for writability
3232  fds = writefds;
3233  break;
3234 
3235  default:
3236  //Set of sockets to be checked for errors
3237  fds = exceptfds;
3238  break;
3239  }
3240 
3241  //Each descriptor is optional and may be omitted
3242  if(fds != NULL)
3243  {
3244  //Parse the current set of sockets
3245  for(j = 0; j < fds->fd_count; j++)
3246  {
3247  //Invalid socket descriptor?
3248  if(fds->fd_array[j] < 0 || fds->fd_array[j] >= SOCKET_MAX_COUNT)
3249  {
3250  //Report an error
3251  return SOCKET_ERROR;
3252  }
3253  }
3254  }
3255  }
3256 
3257  //Create an event object to get notified of socket events
3258  if(!osCreateEvent(&event))
3259  {
3260  //Failed to create event
3261  return SOCKET_ERROR;
3262  }
3263 
3264  //Parse all the descriptor sets
3265  for(i = 0; i < 3; i++)
3266  {
3267  //Select the suitable descriptor set
3268  switch(i)
3269  {
3270  case 0:
3271  //Set of sockets to be checked for readability
3272  fds = readfds;
3273  eventMask = SOCKET_EVENT_RX_READY;
3274  break;
3275 
3276  case 1:
3277  //Set of sockets to be checked for writability
3278  fds = writefds;
3279  eventMask = SOCKET_EVENT_TX_READY;
3280  break;
3281 
3282  default:
3283  //Set of sockets to be checked for errors
3284  fds = exceptfds;
3285  eventMask = SOCKET_EVENT_CLOSED;
3286  break;
3287  }
3288 
3289  //Each descriptor is optional and may be omitted
3290  if(fds != NULL)
3291  {
3292  //Parse the current set of sockets
3293  for(j = 0; j < fds->fd_count; j++)
3294  {
3295  //Get the descriptor associated with the current entry
3296  s = fds->fd_array[j];
3297  //Subscribe to the requested events
3298  socketRegisterEvents(&context->socketTable[s], &event, eventMask);
3299  }
3300  }
3301  }
3302 
3303  //Retrieve timeout value
3304  if(timeout != NULL)
3305  {
3306  time = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
3307  }
3308  else
3309  {
3310  time = INFINITE_DELAY;
3311  }
3312 
3313  //Block the current task until an event occurs
3314  osWaitForEvent(&event, time);
3315 
3316  //Count the number of events in the signaled state
3317  n = 0;
3318 
3319  //Parse all the descriptor sets
3320  for(i = 0; i < 3; i++)
3321  {
3322  //Select the suitable descriptor set
3323  switch(i)
3324  {
3325  case 0:
3326  //Set of sockets to be checked for readability
3327  fds = readfds;
3328  eventMask = SOCKET_EVENT_RX_READY;
3329  break;
3330 
3331  case 1:
3332  //Set of sockets to be checked for writability
3333  fds = writefds;
3334  eventMask = SOCKET_EVENT_TX_READY;
3335  break;
3336 
3337  default:
3338  //Set of sockets to be checked for errors
3339  fds = exceptfds;
3340  eventMask = SOCKET_EVENT_CLOSED;
3341  break;
3342  }
3343 
3344  //Each descriptor is optional and may be omitted
3345  if(fds != NULL)
3346  {
3347  //Parse the current set of sockets
3348  for(j = 0; j < fds->fd_count; )
3349  {
3350  //Get the descriptor associated with the current entry
3351  s = fds->fd_array[j];
3352  //Retrieve event flags for the current socket
3353  eventFlags = socketGetEvents(&context->socketTable[s]);
3354  //Unsubscribe previously registered events
3355  socketUnregisterEvents(&context->socketTable[s]);
3356 
3357  //Event flag is set?
3358  if(eventFlags & eventMask)
3359  {
3360  //Track the number of events in the signaled state
3361  n++;
3362  //Jump to the next socket descriptor
3363  j++;
3364  }
3365  else
3366  {
3367  //Remove descriptor from the current set
3368  socketFdClr(fds, s);
3369  }
3370  }
3371  }
3372  }
3373 
3374  //Delete event object
3375  osDeleteEvent(&event);
3376  //Return the number of events in the signaled state
3377  return n;
3378 }
3379 
3380 
3381 /**
3382  * @brief Get system host name
3383  * @param[out] name Output buffer where to store the system host name
3384  * @param[in] len Length of the buffer, in bytes
3385  * @return On success, zero is returned. On error, -1 is returned
3386  **/
3387 
3389 {
3390  size_t n;
3391  NetInterface *interface;
3392 
3393  //Check parameter
3394  if(name == NULL)
3395  {
3396  //Report an error
3398  return -1;
3399  }
3400 
3401  //Select the default network interface
3402  interface = netGetDefaultInterface(NULL);
3403 
3404  //Retrieve the length of the host name
3405  n = osStrlen(interface->hostname);
3406 
3407  //Make sure the buffer is large enough to hold the string
3408  if(len <= n)
3409  {
3410  //Report an error
3412  return -1;
3413  }
3414 
3415  //Copy the host name
3416  osStrcpy(name, interface->hostname);
3417 
3418  //Successful processing
3419  return 0;
3420 }
3421 
3422 
3423 /**
3424  * @brief Host name resolution
3425  * @param[in] name Name of the host to resolve
3426  * @return Pointer to the hostent structure or a NULL if an error occurs
3427  **/
3428 
3430 {
3431  int_t herrno;
3432  static HOSTENT result;
3433 
3434  //The hostent structure returned by the function resides in static
3435  //memory area
3436  return gethostbyname_r(name, &result, NULL, 0, &herrno);
3437 }
3438 
3439 
3440 /**
3441  * @brief Host name resolution (reentrant version)
3442  * @param[in] name Name of the host to resolve
3443  * @param[in] result Pointer to a hostent structure where the function can
3444  * store the host entry
3445  * @param[out] buf Pointer to a temporary work buffer
3446  * @param[in] buflen Length of the temporary work buffer
3447  * @param[out] h_errnop Pointer to a location where the function can store an
3448  * h_errno value if an error occurs
3449  * @return Pointer to the hostent structure or a NULL if an error occurs
3450  **/
3451 
3452 struct hostent *gethostbyname_r(const char_t *name, struct hostent *result,
3453  char_t *buf, size_t buflen, int_t *h_errnop)
3454 {
3455  error_t error;
3456  IpAddr ipAddr;
3457 
3458  //Check input parameters
3459  if(name == NULL || result == NULL)
3460  {
3461  //Report an error
3462  *h_errnop = NO_RECOVERY;
3463  return NULL;
3464  }
3465 
3466  //Resolve host address
3467  error = getHostByName(NULL, name, &ipAddr, 0);
3468  //Address resolution failed?
3469  if(error)
3470  {
3471  //Report an error
3472  *h_errnop = HOST_NOT_FOUND;
3473  return NULL;
3474  }
3475 
3476 #if (IPV4_SUPPORT == ENABLED)
3477  //IPv4 address?
3478  if(ipAddr.length == sizeof(Ipv4Addr))
3479  {
3480  //Set address family
3481  result->h_addrtype = AF_INET;
3482  result->h_length = sizeof(Ipv4Addr);
3483 
3484  //Copy IPv4 address
3485  ipv4CopyAddr(result->h_addr, &ipAddr.ipv4Addr);
3486  }
3487  else
3488 #endif
3489 #if (IPV6_SUPPORT == ENABLED)
3490  //IPv6 address?
3491  if(ipAddr.length == sizeof(Ipv6Addr))
3492  {
3493  //Set address family
3494  result->h_addrtype = AF_INET6;
3495  result->h_length = sizeof(Ipv6Addr);
3496 
3497  //Copy IPv6 address
3498  ipv6CopyAddr(result->h_addr, &ipAddr.ipv6Addr);
3499  }
3500  else
3501 #endif
3502  //Invalid address?
3503  {
3504  //Report an error
3505  *h_errnop = NO_ADDRESS;
3506  return NULL;
3507  }
3508 
3509  //Successful host name resolution
3510  *h_errnop = NETDB_SUCCESS;
3511 
3512  //Return a pointer to the hostent structure
3513  return result;
3514 }
3515 
3516 
3517 /**
3518  * @brief Convert host and service names to socket address
3519  * @param[in] node Host name or numerical network address
3520  * @param[in] service Service name or decimal number
3521  * @param[in] hints Criteria for selecting the socket address structures
3522  * @param[out] res Dynamically allocated list of socket address structures
3523  * @return On success, zero is returned. On error, a non-zero value is returned
3524  **/
3525 
3526 int_t getaddrinfo(const char_t *node, const char_t *service,
3527  const struct addrinfo *hints, struct addrinfo **res)
3528 {
3529  error_t error;
3530  size_t n;
3531  char_t *p;
3532  uint_t flags;
3533  uint32_t port;
3534  IpAddr ipAddr;
3535  ADDRINFO h;
3536  ADDRINFO *ai;
3537 
3538  //Check whether both node and service name are NULL
3539  if(node == NULL && service == NULL)
3540  return EAI_NONAME;
3541 
3542  //The hints argument is optional
3543  if(hints != NULL)
3544  {
3545  //If hints is not NULL, it points to an addrinfo structure that specifies
3546  //criteria that limit the set of socket addresses that will be returned
3547  h = *hints;
3548  }
3549  else
3550  {
3551  //If hints is NULL, then default criteria are used
3552  osMemset(&h, 0, sizeof(ADDRINFO));
3553  h.ai_family = AF_UNSPEC;
3554  h.ai_socktype = 0;
3555  h.ai_protocol = 0;
3556  h.ai_flags = 0;
3557  }
3558 
3559  //The user may provide a hint to choose between IPv4 and IPv6
3560  if(h.ai_family == AF_UNSPEC)
3561  {
3562  //The value AF_UNSPEC indicates that function should return socket
3563  //addresses for any address family (either IPv4 or IPv6)
3564  flags = 0;
3565  }
3566 #if (IPV4_SUPPORT == ENABLED)
3567  else if(h.ai_family == AF_INET)
3568  {
3569  //The value AF_INET indicates that the function should return an IPv4
3570  //address
3572  }
3573 #endif
3574 #if (IPV6_SUPPORT == ENABLED)
3575  else if(h.ai_family == AF_INET6)
3576  {
3577  //The value AF_INET6 indicates that the function should return an IPv6
3578  //address
3580  }
3581 #endif
3582  else
3583  {
3584  //The requested address family is not supported
3585  return EAI_FAMILY;
3586  }
3587 
3588  //Check whether a host name or numerical network address is specified
3589  if(node != NULL)
3590  {
3591  //If the AI_NUMERICHOST flag, then node must be a numerical network
3592  //address
3593  if((h.ai_flags & AI_NUMERICHOST) != 0)
3594  {
3595  //Convert the string representation to a binary IP address
3596  error = ipStringToAddr(node, &ipAddr);
3597  }
3598  else
3599  {
3600  //Resolve host address
3601  error = getHostByName(NULL, node, &ipAddr, flags);
3602  }
3603 
3604  //Check status code
3605  if(error == NO_ERROR)
3606  {
3607  //Successful host name resolution
3608  }
3609  else if(error == ERROR_IN_PROGRESS)
3610  {
3611  //Host name resolution is in progress
3612  return EAI_AGAIN;
3613  }
3614  else
3615  {
3616  //Permanent failure indication
3617  return EAI_FAIL;
3618  }
3619  }
3620  else
3621  {
3622  //Check flags
3623  if((h.ai_flags & AI_PASSIVE) != 0)
3624  {
3625 #if (IPV4_SUPPORT == ENABLED)
3626  //IPv4 address family?
3627  if(h.ai_family == AF_INET || h.ai_family == AF_UNSPEC)
3628  {
3629  ipAddr.length = sizeof(Ipv4Addr);
3630  ipAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR;
3631  }
3632  else
3633 #endif
3634 #if (IPV6_SUPPORT == ENABLED)
3635  //IPv6 address family?
3636  if(h.ai_family == AF_INET6 || h.ai_family == AF_UNSPEC)
3637  {
3638  ipAddr.length = sizeof(Ipv6Addr);
3639  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
3640  }
3641  else
3642 #endif
3643  //Unknown address family?
3644  {
3645  //Report an error
3646  return EAI_ADDRFAMILY;
3647  }
3648  }
3649  else
3650  {
3651  //Invalid flags
3652  return EAI_BADFLAGS;
3653  }
3654  }
3655 
3656  //Only service names containing a numeric port number are supported
3657  port = osStrtoul(service, &p, 10);
3658  //Invalid service name?
3659  if(*p != '\0')
3660  {
3661  //The requested service is not available
3662  return EAI_SERVICE;
3663  }
3664 
3665 #if (IPV4_SUPPORT == ENABLED)
3666  //IPv4 address?
3667  if(ipAddr.length == sizeof(Ipv4Addr))
3668  {
3669  //Select the relevant socket family
3670  h.ai_family = AF_INET;
3671  //Get the length of the corresponding socket address
3672  n = sizeof(SOCKADDR_IN);
3673  }
3674  else
3675 #endif
3676 #if (IPV6_SUPPORT == ENABLED)
3677  //IPv6 address?
3678  if(ipAddr.length == sizeof(Ipv6Addr))
3679  {
3680  //Select the relevant socket family
3681  h.ai_family = AF_INET6;
3682  //Get the length of the corresponding socket address
3683  n = sizeof(SOCKADDR_IN6);
3684  }
3685  else
3686 #endif
3687  //Unknown address?
3688  {
3689  //Report an error
3690  return EAI_ADDRFAMILY;
3691  }
3692 
3693  //Allocate a memory buffer to hold the address information structure
3694  ai = osAllocMem(sizeof(ADDRINFO) + n);
3695  //Failed to allocate memory?
3696  if(ai == NULL)
3697  {
3698  //Out of memory
3699  return EAI_MEMORY;
3700  }
3701 
3702  //Initialize address information structure
3703  osMemset(ai, 0, sizeof(ADDRINFO) + n);
3704  ai->ai_family = h.ai_family;
3705  ai->ai_socktype = h.ai_socktype;
3706  ai->ai_protocol = h.ai_protocol;
3707  ai->ai_addr = (SOCKADDR *) ((uint8_t *) ai + sizeof(ADDRINFO));
3708  ai->ai_addrlen = n;
3709  ai->ai_next = NULL;
3710 
3711 #if (IPV4_SUPPORT == ENABLED)
3712  //IPv4 address?
3713  if(ipAddr.length == sizeof(Ipv4Addr))
3714  {
3715  //Point to the IPv4 address information
3716  SOCKADDR_IN *sa = (SOCKADDR_IN *) ai->ai_addr;
3717 
3718  //Set address family and port number
3719  sa->sin_family = AF_INET;
3720  sa->sin_port = htons(port);
3721 
3722  //Copy IPv4 address
3723  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
3724  }
3725  else
3726 #endif
3727 #if (IPV6_SUPPORT == ENABLED)
3728  //IPv6 address?
3729  if(ipAddr.length == sizeof(Ipv6Addr))
3730  {
3731  //Point to the IPv6 address information
3732  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) ai->ai_addr;
3733 
3734  //Set address family and port number
3735  sa->sin6_family = AF_INET6;
3736  sa->sin6_port = htons(port);
3737  sa->sin6_flowinfo = 0;
3738  sa->sin6_scope_id = 0;
3739 
3740  //Copy IPv6 address
3741  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
3742  }
3743  else
3744 #endif
3745  //Unknown address?
3746  {
3747  //Clean up side effects
3748  osFreeMem(ai);
3749  //Report an error
3750  return EAI_ADDRFAMILY;
3751  }
3752 
3753  //Return a pointer to the allocated address information
3754  *res = ai;
3755 
3756  //Successful processing
3757  return 0;
3758 }
3759 
3760 
3761 /**
3762  * @brief Free socket address structures
3763  * @param[in] res Dynamically allocated list of socket address structures
3764  **/
3765 
3767 {
3768  ADDRINFO *next;
3769 
3770  //Free the list of socket address structures
3771  while(res != NULL)
3772  {
3773  //Get next entry
3774  next = res->ai_next;
3775  //Free current socket address structure
3776  osFreeMem(res);
3777  //Point to the next entry
3778  res = next;
3779  }
3780 }
3781 
3782 
3783 /**
3784  * @brief Convert a socket address to a corresponding host and service
3785  * @param[in] addr Generic socket address structure
3786  * @param[in] addrlen Length in bytes of the address
3787  * @param[out] host Output buffer where to store the host name
3788  * @param[in] hostlen Length of the host name buffer, in bytes
3789  * @param[out] serv Output buffer where to store the service name
3790  * @param[in] servlen Length of the service name buffer, in bytes
3791  * @param[in] flags Set of flags that influences the behavior of this function
3792  * @return On success, zero is returned. On error, a non-zero value is returned
3793  **/
3794 
3795 int_t getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
3796  char_t *host, size_t hostlen, char_t *serv, size_t servlen, int flags)
3797 {
3798  uint16_t port;
3799 
3800  //At least one of host name or service name must be requested
3801  if(host == NULL && serv == NULL)
3802  return EAI_NONAME;
3803 
3804 #if (IPV4_SUPPORT == ENABLED)
3805  //IPv4 address?
3806  if(addr->sa_family == AF_INET &&
3807  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
3808  {
3809  SOCKADDR_IN *sa;
3810  Ipv4Addr ipv4Addr;
3811 
3812  //Point to the IPv4 address information
3813  sa = (SOCKADDR_IN *) addr;
3814 
3815  //The caller can specify that no host name is required
3816  if(host != NULL)
3817  {
3818  //Make sure the buffer is large enough to hold the host name
3819  if(hostlen < 16)
3820  return EAI_OVERFLOW;
3821 
3822  //Copy the binary representation of the IPv4 address
3823  ipv4CopyAddr(&ipv4Addr, &sa->sin_addr.s_addr);
3824  //Convert the IPv4 address to dot-decimal notation
3825  ipv4AddrToString(ipv4Addr, host);
3826  }
3827 
3828  //Retrieve port number
3829  port = ntohs(sa->sin_port);
3830  }
3831  else
3832 #endif
3833 #if (IPV6_SUPPORT == ENABLED)
3834  //IPv6 address?
3835  if(addr->sa_family == AF_INET6 &&
3836  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
3837  {
3838  SOCKADDR_IN6 *sa;
3839  Ipv6Addr ipv6Addr;
3840 
3841  //Point to the IPv6 address information
3842  sa = (SOCKADDR_IN6 *) addr;
3843 
3844  //The caller can specify that no host name is required
3845  if(host != NULL)
3846  {
3847  //Make sure the buffer is large enough to hold the host name
3848  if(hostlen < 40)
3849  return EAI_OVERFLOW;
3850 
3851  //Copy the binary representation of the IPv6 address
3852  ipv6CopyAddr(&ipv6Addr, sa->sin6_addr.s6_addr);
3853  //Convert the IPv6 address to string representation
3854  ipv6AddrToString(&ipv6Addr, host);
3855  }
3856 
3857  //Retrieve port number
3858  port = ntohs(sa->sin6_port);
3859  }
3860  else
3861 #endif
3862  //Invalid address?
3863  {
3864  //The address family was not recognized, or the address length was
3865  //invalid for the specified family
3866  return EAI_FAMILY;
3867  }
3868 
3869  //The caller can specify that no service name is required
3870  if(serv != NULL)
3871  {
3872  //Make sure the buffer is large enough to hold the service name
3873  if(servlen < 6)
3874  return EAI_OVERFLOW;
3875 
3876  //Convert the port number to string representation
3877  osSprintf(serv, "%" PRIu16, ntohs(port));
3878  }
3879 
3880  //Successful processing
3881  return 0;
3882 }
3883 
3884 
3885 /**
3886  * @brief Map an interface name into its corresponding index
3887  * @param[in] ifname Name of the interface
3888  * @return If ifname is the name of an interface, then the function returns the
3889  * interface index corresponding to name ifname. Otherwise, the function
3890  * returns zero
3891  **/
3892 
3894 {
3895  uint_t i;
3896  uint_t index;
3897  NetContext *context;
3898 
3899  //Initialize interface index
3900  index = 0;
3901 
3902  //Valid parameter?
3903  if(ifname != NULL)
3904  {
3905  //Point to the TCP/IP stack context
3906  context = netGetDefaultContext();
3907 
3908  //Loop through network interfaces
3909  for(i = 0; i < context->numInterfaces; i++)
3910  {
3911  //Matching interface name?
3912  if(osStrcmp(context->interfaces[i].name, ifname) == 0)
3913  {
3914  //Save the interface index
3915  index = context->interfaces[i].index + 1;
3916  //We are done
3917  break;
3918  }
3919  }
3920  }
3921 
3922  //Return the index corresponding to interface name
3923  return index;
3924 }
3925 
3926 
3927 /**
3928  * @brief Map an interface index into its corresponding name
3929  * @param[in] ifindex Interface index
3930  * @param[in] ifname Buffer of at least IF_NAMESIZE bytes
3931  * @return If ifindex is an interface index, then the function returns the value
3932  * supplied in ifname, which points to a buffer now containing the interface
3933  * name. Otherwise, the function returns a NULL pointer
3934  **/
3935 
3937 {
3938  uint_t i;
3939  char_t *name;
3940  NetContext *context;
3941 
3942  //Initialize interface name
3943  name = NULL;
3944 
3945  //Valid parameters?
3946  if(ifindex != 0 && ifname != NULL)
3947  {
3948  //Point to the TCP/IP stack context
3949  context = netGetDefaultContext();
3950 
3951  //Loop through network interfaces
3952  for(i = 0; i < context->numInterfaces; i++)
3953  {
3954  //Matching interface index?
3955  if((context->interfaces[i].index + 1) == ifindex)
3956  {
3957  //Copy the name of the interface
3958  osStrcpy(ifname, context->interfaces[i].name);
3959  name = ifname;
3960 
3961  //We are done
3962  break;
3963  }
3964  }
3965  }
3966 
3967  //Return the name of the interface
3968  return name;
3969 }
3970 
3971 
3972 /**
3973  * @brief Convert a dot-decimal string into binary data in network byte order
3974  * @param[in] cp NULL-terminated string representing the IPv4 address
3975  * @return Binary data in network byte order
3976  **/
3977 
3979 {
3980 #if (IPV4_SUPPORT == ENABLED)
3981  error_t error;
3982  Ipv4Addr ipv4Addr;
3983 
3984  //Convert a dot-decimal string to a binary IPv4 address
3985  error = ipv4StringToAddr(cp, &ipv4Addr);
3986 
3987  //Check status code
3988  if(error)
3989  {
3990  //The input is invalid
3991  return INADDR_NONE;
3992  }
3993  else
3994  {
3995  //Return the binary representation
3996  return ipv4Addr;
3997  }
3998 #else
3999  //IPv4 is not implemented
4000  return INADDR_NONE;
4001 #endif
4002 }
4003 
4004 
4005 /**
4006  * @brief Convert a dot-decimal string into binary form
4007  * @param[in] cp NULL-terminated string representing the IPv4 address
4008  * @param[out] inp Binary data in network byte order
4009  * @return The function returns non-zero if the address is valid, zero if not
4010  **/
4011 
4012 int_t inet_aton(const char_t *cp, struct in_addr *inp)
4013 {
4014 #if (IPV4_SUPPORT == ENABLED)
4015  error_t error;
4016  Ipv4Addr ipv4Addr;
4017 
4018  //Convert a dot-decimal string to a binary IPv4 address
4019  error = ipv4StringToAddr(cp, &ipv4Addr);
4020 
4021  //Check status code
4022  if(error)
4023  {
4024  //The input is invalid
4025  return 0;
4026  }
4027  else
4028  {
4029  //Copy the binary representation of the IPv4 address
4030  inp->s_addr = ipv4Addr;
4031  //The conversion succeeded
4032  return 1;
4033  }
4034 #else
4035  //IPv4 is not implemented
4036  return 0;
4037 #endif
4038 }
4039 
4040 
4041 /**
4042  * @brief Convert a binary IPv4 address to dot-decimal notation
4043  * @param[in] in Binary representation of the IPv4 address
4044  * @return Pointer to the formatted string
4045  **/
4046 
4047 const char_t *inet_ntoa(struct in_addr in)
4048 {
4049  static char_t buf[16];
4050 
4051  //The string returned by the function resides in static memory area
4052  return inet_ntoa_r(in, buf, sizeof(buf));
4053 }
4054 
4055 
4056 /**
4057  * @brief Convert a binary IPv4 address to dot-decimal notation (reentrant version)
4058  * @param[in] in Binary representation of the IPv4 address
4059  * @param[out] buf Pointer to the buffer where to format the string
4060  * @param[in] buflen Number of bytes available in the buffer
4061  * @return Pointer to the formatted string
4062  **/
4063 
4064 const char_t *inet_ntoa_r(struct in_addr in, char_t *buf, socklen_t buflen)
4065 {
4066  //Properly terminate the string
4067  buf[0] = '\0';
4068 
4069 #if (IPV4_SUPPORT == ENABLED)
4070  //Check the length of the buffer
4071  if(buflen >= 16)
4072  {
4073  //Convert the binary IPv4 address to dot-decimal notation
4074  ipv4AddrToString(in.s_addr, buf);
4075  }
4076 #endif
4077 
4078  //Return a pointer to the formatted string
4079  return buf;
4080 }
4081 
4082 
4083 /**
4084  * @brief Convert an IPv4 or IPv6 address from text to binary form
4085  * @param[in] af Address family
4086  * @param[in] src NULL-terminated string representing the IP address
4087  * @param[out] dst Binary representation of the IP address
4088  * @return The function returns 1 on success. 0 is returned if the address
4089  * is not valid. If the address family is not valid, -1 is returned
4090  **/
4091 
4092 int_t inet_pton(int_t af, const char_t *src, void *dst)
4093 {
4094  error_t error;
4095 
4096 #if (IPV4_SUPPORT == ENABLED)
4097  //IPv4 address?
4098  if(af == AF_INET)
4099  {
4100  Ipv4Addr ipv4Addr;
4101 
4102  //Convert the IPv4 address from text to binary form
4103  error = ipv4StringToAddr(src, &ipv4Addr);
4104 
4105  //Check status code
4106  if(error)
4107  {
4108  //The input is invalid
4109  return 0;
4110  }
4111  else
4112  {
4113  //Copy the binary representation of the IPv4 address
4114  ipv4CopyAddr(dst, &ipv4Addr);
4115  //The conversion succeeded
4116  return 1;
4117  }
4118  }
4119  else
4120 #endif
4121 #if (IPV6_SUPPORT == ENABLED)
4122  //IPv6 address?
4123  if(af == AF_INET6)
4124  {
4125  Ipv6Addr ipv6Addr;
4126 
4127  //Convert the IPv6 address from text to binary form
4128  error = ipv6StringToAddr(src, &ipv6Addr);
4129 
4130  //Check status code
4131  if(error)
4132  {
4133  //The input is invalid
4134  return 0;
4135  }
4136  else
4137  {
4138  //Copy the binary representation of the IPv6 address
4139  ipv6CopyAddr(dst, &ipv6Addr);
4140  //The conversion succeeded
4141  return 1;
4142  }
4143  }
4144  else
4145 #endif
4146  //Invalid address family?
4147  {
4148  //Report an error
4149  return -1;
4150  }
4151 }
4152 
4153 
4154 /**
4155  * @brief Convert an IPv4 or IPv6 address from binary to text
4156  * @param[in] af Address family
4157  * @param[in] src Binary representation of the IP address
4158  * @param[out] dst NULL-terminated string representing the IP address
4159  * @param[in] size Number of bytes available in the buffer
4160  * @return On success, the function returns a pointer to the formatted string.
4161  * NULL is returned if there was an error
4162  **/
4163 
4164 const char_t *inet_ntop(int_t af, const void *src, char_t *dst, socklen_t size)
4165 {
4166 #if (IPV4_SUPPORT == ENABLED)
4167  //IPv4 address?
4168  if(af == AF_INET && size >= INET_ADDRSTRLEN)
4169  {
4170  Ipv4Addr ipv4Addr;
4171 
4172  //Copy the binary representation of the IPv4 address
4173  ipv4CopyAddr(&ipv4Addr, src);
4174 
4175  //Convert the IPv4 address to dot-decimal notation
4176  return ipv4AddrToString(ipv4Addr, dst);
4177  }
4178  else
4179 #endif
4180 #if (IPV6_SUPPORT == ENABLED)
4181  //IPv6 address?
4182  if(af == AF_INET6 && size >= INET6_ADDRSTRLEN)
4183  {
4184  Ipv6Addr ipv6Addr;
4185 
4186  //Copy the binary representation of the IPv6 address
4187  ipv6CopyAddr(&ipv6Addr, src);
4188 
4189  //Convert the IPv6 address to string representation
4190  return ipv6AddrToString(&ipv6Addr, dst);
4191  }
4192  else
4193 #endif
4194  //Invalid address family?
4195  {
4196  //Report an error
4197  return NULL;
4198  }
4199 }
4200 
4201 #endif
error_t socketSend(Socket *socket, const void *data, size_t length, size_t *written, uint_t flags)
Send data to a connected socket.
Definition: socket.c:1511
const struct in6_addr in6addr_any
Definition: bsd_socket.c:49
IpFilterMode
Multicast filter mode.
Definition: ip.h:71
#define F_GETFL
Definition: bsd_socket.h:214
int_t socketSetSoSndBufOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_SNDBUF option.
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2325
struct hostent * gethostbyname(const char_t *name)
Host name resolution.
Definition: bsd_socket.c:3429
#define htons(value)
Definition: cpu_endian.h:413
struct sockaddr * ai_addr
Definition: bsd_socket.h:559
#define IP_BLOCK_SOURCE
Definition: bsd_socket.h:165
int_t socketGetTcpMaxSegOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_MAXSEG option.
int_t socklen_t
Length type.
Definition: bsd_socket.h:303
int_t socketSetTcpKeepIdleOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_KEEPIDLE option.
int_t inet_pton(int_t af, const char_t *src, void *dst)
Convert an IPv4 or IPv6 address from text to binary form.
Definition: bsd_socket.c:4092
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:1341
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
#define AF_INET6
Definition: bsd_socket.h:80
Ancillary data header.
Definition: bsd_socket.h:496
#define NetContext
Definition: net.h:36
uint32_t in_addr_t
IPv4 address.
Definition: bsd_socket.h:324
#define IPV6_HOPLIMIT
Definition: bsd_socket.h:186
#define CMSG_DATA(cmsg)
Definition: bsd_socket.h:585
@ SOCKET_OPTION_IPV4_RECV_TOS
Definition: socket.h:197
int_t socketGetTcpKeepIntvlOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_KEEPINTVL option.
int_t getsourcefilter(int_t s, uint32_t interface, struct sockaddr *group, socklen_t grouplen, uint32_t *fmode, uint_t *numsrc, struct sockaddr_storage *slist)
Get multicast source filter.
Definition: bsd_socket.c:2790
int_t socketSetSoRcvBufOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_RCVBUF option.
int_t socketSetSoNoCheckOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_NO_CHECK option.
int_t connect(int_t s, const struct sockaddr *addr, socklen_t addrlen)
Establish a connection to a specified socket.
Definition: bsd_socket.c:208
#define ENOPROTOOPT
Definition: bsd_socket.h:264
int_t recvmsg(int_t s, struct msghdr *msg, int_t flags)
Receive a message.
Definition: bsd_socket.c:1151
@ SOCKET_FLAG_WAIT_ALL
Definition: socket.h:138
int_t setsockopt(int_t s, int_t level, int_t optname, const void *optval, socklen_t optlen)
The setsockopt function sets a socket option.
Definition: bsd_socket.c:1774
Helper function for BSD socket API.
#define EAI_BADFLAGS
Definition: bsd_socket.h:243
int_t socketSetMcastLeaveGroupOption(Socket *socket, const struct group_req *optval, socklen_t optlen)
Set MCAST_LEAVE_GROUP option.
#define IP_TOS
Definition: bsd_socket.h:153
uint8_t protocol
Definition: ipv4.h:353
#define EINPROGRESS
Definition: bsd_socket.h:260
int_t socketGetSoRcvBufOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_RCVBUF option.
int_t socketSetSoBindToDeviceOption(Socket *socket, const char_t *optval, socklen_t optlen)
Set SO_BINDTODEVICE option.
uint32_t sin6_flowinfo
Definition: bsd_socket.h:390
signed int int_t
Definition: compiler_port.h:56
int_t socketGetIpv6RecvHopLimitOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_RECVHOPLIMIT option.
void * iov_base
Definition: bsd_socket.h:470
int_t socketSetIpv6TrafficClassOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_TCLASS option.
IP network address.
Definition: ip.h:94
int_t socketSetTcpMaxSegOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_MAXSEG option.
in_port_t sin6_port
Definition: bsd_socket.h:389
#define IP_UNBLOCK_SOURCE
Definition: bsd_socket.h:164
size_t iov_len
Definition: bsd_socket.h:471
int_t socketGetSoErrorOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_ERROR option.
const char_t * inet_ntoa(struct in_addr in)
Convert a binary IPv4 address to dot-decimal notation.
Definition: bsd_socket.c:4047
int_t socketSetMcastLeaveSourceGroupOption(Socket *socket, const struct group_source_req *optval, socklen_t optlen)
Set MCAST_LEAVE_SOURCE_GROUP option.
int_t socketGetIpv6MulticastHopsOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_MULTICAST_HOPS option.
int_t shutdown(int_t s, int_t how)
The shutdown function disables sends or receives on a socket.
Definition: bsd_socket.c:3116
#define ETIMEDOUT
Definition: bsd_socket.h:261
uint8_t p
Definition: ndp.h:300
#define INADDR_ANY
Definition: bsd_socket.h:115
#define SOCKET_ERROR
Definition: bsd_socket.h:238
@ SOCKET_FLAG_DONT_ROUTE
Definition: socket.h:137
#define NO_RECOVERY
Definition: bsd_socket.h:278
uint8_t message[]
Definition: chap.h:154
int_t recv(int_t s, void *data, size_t size, int_t flags)
Receive data from a connected socket.
Definition: bsd_socket.c:945
#define EAI_ADDRFAMILY
Definition: bsd_socket.h:241
Set of sockets.
Definition: bsd_socket.h:530
#define SO_RCVTIMEO
Definition: bsd_socket.h:148
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
Message and ancillary data.
Definition: socket.h:241
int_t socketSetIpv6MulticastHopsOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_MULTICAST_HOPS option.
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:2057
Event object.
#define IP_RECVTOS
Definition: bsd_socket.h:158
socklen_t msg_namelen
Definition: bsd_socket.h:482
in_port_t sin_port
Definition: bsd_socket.h:366
struct in6_addr sin6_addr
Definition: bsd_socket.h:391
#define AF_INET
Definition: bsd_socket.h:79
void * msg_control
Definition: bsd_socket.h:485
#define INADDR_NONE
Definition: bsd_socket.h:282
#define IP_MULTICAST_LOOP
Definition: bsd_socket.h:161
#define SO_BINDTODEVICE
Definition: bsd_socket.h:149
Ipv6Addr
Definition: ipv6.h:282
int_t gethostname(char_t *name, size_t len)
Get system host name.
Definition: bsd_socket.c:3388
@ IP_FILTER_MODE_EXCLUDE
Definition: ip.h:72
error_t socketSetMulticastSourceFilter(Socket *socket, const IpAddr *groupAddr, IpFilterMode filterMode, const IpAddr *sources, uint_t numSources)
Set multicast source filter (full-state API)
Definition: socket.c:580
int_t socketGetSoRcvTimeoOption(Socket *socket, struct timeval *optval, socklen_t *optlen)
Get SO_RCVTIMEO option.
uint8_t type
Definition: coap_common.h:176
struct sockaddr_in6 SOCKADDR_IN6
IPv6 address information.
#define SO_SNDBUF
Definition: bsd_socket.h:142
Socket address storage.
Definition: bsd_socket.h:343
#define IPV6_UNICAST_HOPS
Definition: bsd_socket.h:177
int_t socketGetIpTosOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_TOS option.
const char_t * inet_ntop(int_t af, const void *src, char_t *dst, socklen_t size)
Convert an IPv4 or IPv6 address from binary to text.
Definition: bsd_socket.c:4164
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:136
char_t name[]
#define EAI_FAIL
Definition: bsd_socket.h:244
#define osStrcmp(s1, s2)
Definition: os_port.h:177
sa_family_t sin6_family
Definition: bsd_socket.h:388
#define FIONREAD
Definition: bsd_socket.h:209
int_t listen(int_t s, int_t backlog)
Place a socket in the listening state.
Definition: bsd_socket.c:330
#define EINVAL
Definition: bsd_socket.h:259
#define osStrlen(s)
Definition: os_port.h:171
#define MSG_DONTROUTE
Definition: bsd_socket.h:121
#define IPV4_SUPPORT
Definition: ipv4.h:49
#define IPV6_RECVTCLASS
Definition: bsd_socket.h:188
@ ERROR_END_OF_STREAM
Definition: error.h:211
int_t socketSetIpv6MulticastLoopOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_MULTICAST_LOOP option.
const uint8_t res[]
IPv4 address information.
Definition: bsd_socket.h:364
const char_t * inet_ntoa_r(struct in_addr in, char_t *buf, socklen_t buflen)
Convert a binary IPv4 address to dot-decimal notation (reentrant version)
Definition: bsd_socket.c:4064
#define BSD_SOCKET_SET_ERRNO(e)
Definition: bsd_socket.h:50
#define MSG_DONTWAIT
Definition: bsd_socket.h:123
#define MCAST_UNBLOCK_SOURCE
Definition: bsd_socket.h:170
#define EWOULDBLOCK
Definition: bsd_socket.h:257
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:324
int_t socketGetIpRecvTtlOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_RECVTTL option.
int_t cmsg_level
Definition: bsd_socket.h:498
int_t socketGetTcpKeepIdleOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_KEEPIDLE option.
void socketFdClr(fd_set *fds, int_t s)
Remove a descriptor from an existing set.
#define TCP_MAXSEG
Definition: bsd_socket.h:193
#define IP_MULTICAST_IF
Definition: bsd_socket.h:159
uint_t if_nametoindex(const char_t *ifname)
Map an interface name into its corresponding index.
Definition: bsd_socket.c:3893
@ SOCKET_OPTION_IPV6_RECV_TRAFFIC_CLASS
Definition: socket.h:203
IPv6 packet information.
Definition: bsd_socket.h:519
#define IPV6_V6ONLY
Definition: bsd_socket.h:183
void * msg_name
Definition: bsd_socket.h:481
@ SOCKET_FLAG_PEEK
Definition: socket.h:136
int_t socketSetIpRecvTtlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_RECVTTL option.
int_t socketSetIpv6UnicastHopsOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_UNICAST_HOPS option.
#define MCAST_EXCLUDE
Definition: bsd_socket.h:204
uint8_t h_addr[16]
Definition: bsd_socket.h:544
void freeaddrinfo(struct addrinfo *res)
Free socket address structures.
Definition: bsd_socket.c:3766
#define AF_PACKET
Definition: bsd_socket.h:81
int_t socketSetIpDropSourceMembershipOption(Socket *socket, const struct ip_mreq_source *optval, socklen_t optlen)
Set IP_DROP_SOURCE_MEMBERSHIP option.
@ HOST_TYPE_IPV6
Definition: socket.h:218
#define NO_ADDRESS
Definition: bsd_socket.h:279
int_t socketGetTcpKeepCntOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_KEEPCNT option.
@ SOCKET_OPTION_IPV4_RECV_TTL
Definition: socket.h:198
int_t socketSetSoKeepAliveOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_KEEPALIVE option.
int_t socketGetIpv6MulticastLoopOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_MULTICAST_LOOP option.
Structure that represents an IPv6 address.
Definition: bsd_socket.h:377
#define IP_ADD_SOURCE_MEMBERSHIP
Definition: bsd_socket.h:166
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
error_t ipStringToAddr(const char_t *str, IpAddr *ipAddr)
Convert a string representation of an IP address to a binary IP address.
Definition: ip.c:766
#define SO_RCVBUF
Definition: bsd_socket.h:143
int_t socketSetIpv6OnlyOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_V6ONLY option.
int_t socketSetIpDontFragOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_DONTFRAG option.
#define EAI_NONAME
Definition: bsd_socket.h:248
@ ERROR_IN_PROGRESS
Definition: error.h:214
error_t socketSendMsg(Socket *socket, const SocketMsg *message, uint_t flags)
Send a message to a connectionless socket.
Definition: socket.c:1664
#define TCP_KEEPCNT
Definition: bsd_socket.h:196
char_t * if_indextoname(uint_t ifindex, char_t *ifname)
Map an interface index into its corresponding name.
Definition: bsd_socket.c:3936
#define TCP_NODELAY
Definition: bsd_socket.h:192
#define FALSE
Definition: os_port.h:46
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:49
int32_t tv_sec
Definition: bsd_socket.h:573
uint8_t h
Definition: ndp.h:302
int ipi_ifindex
Definition: bsd_socket.h:509
void socketTranslateErrorCode(Socket *socket, error_t errorCode)
Translate error code.
int_t fd_count
Definition: bsd_socket.h:531
int_t socketSetMcastJoinSourceGroupOption(Socket *socket, const struct group_source_req *optval, socklen_t optlen)
Set MCAST_JOIN_SOURCE_GROUP option.
#define IPPROTO_IP
Definition: bsd_socket.h:95
#define AI_NUMERICHOST
Definition: bsd_socket.h:223
int_t socketSetIpv6DontFragOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_DONTFRAG option.
Socket address.
Definition: bsd_socket.h:332
int_t socketGetSoReuseAddrOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_REUSEADDR option.
error_t
Error codes.
Definition: error.h:43
int_t ai_protocol
Definition: bsd_socket.h:557
int_t socketSetMcastUnblockSourceOption(Socket *socket, const struct group_source_req *optval, socklen_t optlen)
Set MCAST_UNBLOCK_SOURCE option.
IPv6 address information.
Definition: bsd_socket.h:387
#define osSprintf(dest,...)
Definition: os_port.h:237
#define AI_PASSIVE
Definition: bsd_socket.h:221
error_t socketReceive(Socket *socket, void *data, size_t size, size_t *received, uint_t flags)
Receive data from a connected socket.
Definition: socket.c:1722
int_t socketGetIpv6RecvTrafficClassOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_RECVTCLASS option.
Structure that represents an IPv4 address.
Definition: bsd_socket.h:354
@ SOCKET_OPTION_IPV6_RECV_HOP_LIMIT
Definition: socket.h:204
uint16_t h_length
Definition: bsd_socket.h:543
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
int_t socketGetIpv6DontFragOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_DONTFRAG option.
int_t socket(int_t family, int_t type, int_t protocol)
Create a socket that is bound to a specific transport service provider.
Definition: bsd_socket.c:65
#define MSG_WAITALL
Definition: bsd_socket.h:124
@ SOCKET_EVENT_TX_READY
Definition: socket.h:175
#define EAI_SERVICE
Definition: bsd_socket.h:249
#define EAI_OVERFLOW
Definition: bsd_socket.h:252
void socketSetErrnoCode(Socket *socket, uint_t errnoCode)
Set BSD error code.
int_t socketGetIpPktInfoOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_PKTINFO option.
struct sockaddr_in SOCKADDR_IN
IPv4 address information.
int_t socketGetIpv6UnicastHopsOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_UNICAST_HOPS option.
sa_family_t sin_family
Definition: bsd_socket.h:365
int_t getsockname(int_t s, struct sockaddr *addr, socklen_t *addrlen)
Retrieves the local name for a socket.
Definition: bsd_socket.c:1516
struct hostent * gethostbyname_r(const char_t *name, struct hostent *result, char_t *buf, size_t buflen, int_t *h_errnop)
Host name resolution (reentrant version)
Definition: bsd_socket.c:3452
void osDeleteEvent(OsEvent *event)
Delete an event object.
#define NetInterface
Definition: net.h:40
int ipi6_ifindex
Definition: bsd_socket.h:520
#define ENOTCONN
Definition: bsd_socket.h:270
#define SO_REUSEADDR
Definition: bsd_socket.h:137
int_t fcntl(int_t s, int_t cmd, int_t arg)
Perform specific operation.
Definition: bsd_socket.c:3054
#define SO_BROADCAST
Definition: bsd_socket.h:141
BSD socket API.
int_t socketGetIpv6OnlyOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_V6ONLY option.
error_t socketReceiveFrom(Socket *socket, IpAddr *srcIpAddr, uint16_t *srcPort, void *data, size_t size, size_t *received, uint_t flags)
Receive a datagram from a connectionless socket.
Definition: socket.c:1743
int_t socketSetIpRecvTosOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_RECVTOS option.
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1889
int_t socketSetIpTtlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_TTL option.
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
#define IP_MULTICAST_TTL
Definition: bsd_socket.h:160
error_t getHostByName(NetInterface *interface, const char_t *name, IpAddr *ipAddr, uint_t flags)
Resolve a host name into an IP address.
Definition: socket.c:2270
int_t msg_iovlen
Definition: bsd_socket.h:484
#define SOCKET_SUCCESS
Definition: bsd_socket.h:237
#define IP_PKTINFO
Definition: bsd_socket.h:156
int_t socketSetIpAddSourceMembershipOption(Socket *socket, const struct ip_mreq_source *optval, socklen_t optlen)
Set IP_ADD_SOURCE_MEMBERSHIP option.
int_t socketSetIpAddMembershipOption(Socket *socket, const struct ip_mreq *optval, socklen_t optlen)
Set IP_ADD_MEMBERSHIP option.
int_t socketSetTcpKeepCntOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_KEEPCNT option.
Message header.
Definition: bsd_socket.h:480
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:1374
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
int_t socketGetSoNoCheckOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_NO_CHECK option.
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:2015
#define IPV6_MULTICAST_HOPS
Definition: bsd_socket.h:179
int_t fd_array[FD_SETSIZE]
Definition: bsd_socket.h:532
int_t socketSetIpPktInfoOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_PKTINFO option.
#define IPPROTO_TCP
Definition: bsd_socket.h:98
uint8_t length
Definition: tcp.h:375
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket.
Definition: socket.c:123
#define SO_SNDTIMEO
Definition: bsd_socket.h:147
in_addr_t inet_addr(const char_t *cp)
Convert a dot-decimal string into binary data in network byte order.
Definition: bsd_socket.c:3978
int_t socketSetIpDropMembershipOption(Socket *socket, const struct ip_mreq *optval, socklen_t optlen)
Set IP_DROP_MEMBERSHIP option.
#define ENAMETOOLONG
Definition: bsd_socket.h:262
#define MCAST_JOIN_GROUP
Definition: bsd_socket.h:168
int32_t tv_usec
Definition: bsd_socket.h:574
size_t length
Definition: ip.h:95
int_t socketSetIpv6RecvHopLimitOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_RECVHOPLIMIT option.
socklen_t ai_addrlen
Definition: bsd_socket.h:558
@ HOST_TYPE_IPV4
Definition: socket.h:217
struct addrinfo ADDRINFO
Information about address of a service provider.
#define HOST_NOT_FOUND
Definition: bsd_socket.h:276
uint32_t sin6_scope_id
Definition: bsd_socket.h:392
#define ENABLED
Definition: os_port.h:37
#define IP_DROP_SOURCE_MEMBERSHIP
Definition: bsd_socket.h:167
int_t socketSetIpv6AddMembershipOption(Socket *socket, const struct ipv6_mreq *optval, socklen_t optlen)
Set IPV6_ADD_MEMBERSHIP option.
int_t socketGetIpMulticastLoopOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_MULTICAST_LOOP option.
int_t socketGetIpTtlOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_TTL option.
int_t socketSetIpTosOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_TOS option.
#define MCAST_BLOCK_SOURCE
Definition: bsd_socket.h:169
int_t recvfrom(int_t s, void *data, size_t size, int_t flags, struct sockaddr *addr, socklen_t *addrlen)
Receive a datagram.
Definition: bsd_socket.c:1021
#define FIONSPACE
Definition: bsd_socket.h:211
#define MSG_CTRUNC
Definition: bsd_socket.h:122
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:1476
int_t ioctlsocket(int_t s, uint32_t cmd, void *arg)
Control the I/O mode of a socket.
Definition: bsd_socket.c:2950
int_t socketGetIpv6TrafficClassOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_TCLASS option.
#define IP_RECVTTL
Definition: bsd_socket.h:157
uint32_t systime_t
System time.
#define IPV6_DONTFRAG
Definition: bsd_socket.h:187
uint16_t port
Definition: dns_common.h:272
#define ntohs(value)
Definition: cpu_endian.h:421
int_t socketSetTcpKeepIntvlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_KEEPINTVL option.
int_t socketGetSoTypeOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_TYPE option.
in_addr_t s_addr
Definition: bsd_socket.h:355
#define osStrtoul(s, endptr, base)
Definition: os_port.h:261
#define SO_NO_CHECK
Definition: bsd_socket.h:145
int_t bind(int_t s, const struct sockaddr *addr, socklen_t addrlen)
Associate a local address with a socket.
Definition: bsd_socket.c:107
#define EFAULT
Definition: bsd_socket.h:258
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:55
void socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask)
Subscribe to the specified socket events.
Definition: socket_misc.c:200
Ipv4Addr ipv4Addr
Definition: ip.h:99
int_t socketGetSoSndTimeoOption(Socket *socket, struct timeval *optval, socklen_t *optlen)
Get SO_SNDTIMEO option.
struct in_addr ipi_addr
Definition: bsd_socket.h:510
error_t socketGetMulticastSourceFilter(Socket *socket, const IpAddr *groupAddr, IpFilterMode *filterMode, IpAddr *sources, uint_t *numSources)
Get multicast source filter.
Definition: socket.c:697
#define SO_TYPE
Definition: bsd_socket.h:138
Information about a given host.
Definition: bsd_socket.h:541
#define F_SETFL
Definition: bsd_socket.h:215
BSD socket options.
int_t socketGetSoBroadcastOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_BROADCAST option.
uint32_t time
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:132
int_t select(int_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout)
Determine the status of one or more sockets.
Definition: bsd_socket.c:3202
#define FIONBIO
Definition: bsd_socket.h:208
Helper functions for sockets.
size_t cmsg_len
Definition: bsd_socket.h:497
#define FIONWRITE
Definition: bsd_socket.h:210
@ SOCKET_FLAG_NO_DELAY
Definition: socket.h:143
@ SOCKET_EVENT_RX_READY
Definition: socket.h:179
uint8_t n
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
#define MCAST_LEAVE_SOURCE_GROUP
Definition: bsd_socket.h:173
#define INET_ADDRSTRLEN
Definition: bsd_socket.h:285
int_t setipv4sourcefilter(int_t s, struct in_addr interface, struct in_addr group, uint32_t fmode, uint_t numsrc, struct in_addr *slist)
Set multicast source filter (IPv4 only)
Definition: bsd_socket.c:2428
Timeout structure.
Definition: bsd_socket.h:572
#define IPV6_MULTICAST_LOOP
Definition: bsd_socket.h:180
struct in6_addr ipi6_addr
Definition: bsd_socket.h:521
#define IP_DONTFRAG
Definition: bsd_socket.h:174
int_t socketSetIpUnblockSourceOption(Socket *socket, const struct ip_mreq_source *optval, socklen_t optlen)
Set IP_UNBLOCK_SOURCE option.
Ipv4Addr groupAddr
Definition: igmp_common.h:214
int_t socketSetIpv6DropMembershipOption(Socket *socket, const struct ipv6_mreq *optval, socklen_t optlen)
Set IPV6_DROP_MEMBERSHIP option.
struct in_addr sin_addr
Definition: bsd_socket.h:367
int_t getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char_t *host, size_t hostlen, char_t *serv, size_t servlen, int flags)
Convert a socket address to a corresponding host and service.
Definition: bsd_socket.c:3795
#define Socket
Definition: socket.h:36
int_t socketSetSoSndTimeoOption(Socket *socket, const struct timeval *optval, socklen_t optlen)
Set SO_SNDTIMEO option.
#define CMSG_SPACE(len)
Definition: bsd_socket.h:587
int_t socketSetSoBroadcastOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_BROADCAST option.
@ IP_FILTER_MODE_INCLUDE
Definition: ip.h:73
int_t ai_socktype
Definition: bsd_socket.h:556
#define MCAST_INCLUDE
Definition: bsd_socket.h:205
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define SOCKET_MAX_MULTICAST_SOURCES
Definition: socket.h:60
#define IPV6_PKTINFO
Definition: bsd_socket.h:184
#define INET6_ADDRSTRLEN
Definition: bsd_socket.h:288
#define SOL_SOCKET
Definition: bsd_socket.h:112
@ SOCKET_OPTION_IPV6_PKT_INFO
Definition: socket.h:202
#define EAI_AGAIN
Definition: bsd_socket.h:242
int_t getipv4sourcefilter(int_t s, struct in_addr interface, struct in_addr group, uint32_t *fmode, uint_t *numsrc, struct in_addr *slist)
Get multicast source filter (IPv4 only)
Definition: bsd_socket.c:2529
#define CMSG_LEN(len)
Definition: bsd_socket.h:588
const struct in6_addr in6addr_loopback
Definition: bsd_socket.c:52
#define EAI_FAMILY
Definition: bsd_socket.h:245
#define IPV6_RECVHOPLIMIT
Definition: bsd_socket.h:185
int_t accept(int_t s, struct sockaddr *addr, socklen_t *addrlen)
Permit an incoming connection attempt on a socket.
Definition: bsd_socket.c:372
sa_family_t sa_family
Definition: bsd_socket.h:333
int_t socketGetIpRecvTosOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_RECVTOS option.
int_t socketSetSoRcvTimeoOption(Socket *socket, const struct timeval *optval, socklen_t optlen)
Set SO_RCVTIMEO option.
Socket API.
#define EOPNOTSUPP
Definition: bsd_socket.h:265
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:1532
#define MCAST_JOIN_SOURCE_GROUP
Definition: bsd_socket.h:172
int_t socketGetSoKeepAliveOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_KEEPALIVE option.
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:95
int_t getsockopt(int_t s, int_t level, int_t optname, void *optval, socklen_t *optlen)
The getsockopt function retrieves a socket option.
Definition: bsd_socket.c:2135
int_t socketGetIpDontFragOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_DONTFRAG option.
#define AF_UNSPEC
Definition: bsd_socket.h:78
int_t getpeername(int_t s, struct sockaddr *addr, socklen_t *addrlen)
Retrieves the address of the peer to which a socket is connected.
Definition: bsd_socket.c:1670
int_t socketSetIpMulticastTtlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_MULTICAST_TTL option.
uint8_t s
Definition: igmp_common.h:234
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:167
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1427
Ipv4Addr ipAddr
Definition: ipcp.h:105
#define MSG_PEEK
Definition: bsd_socket.h:120
struct iovec * msg_iov
Definition: bsd_socket.h:483
#define NETDB_SUCCESS
Definition: bsd_socket.h:275
int_t setsourcefilter(int_t s, uint32_t interface, struct sockaddr *group, socklen_t grouplen, uint32_t fmode, uint_t numsrc, struct sockaddr_storage *slist)
Set multicast source filter.
Definition: bsd_socket.c:2624
int_t sendto(int_t s, const void *data, size_t length, int_t flags, const struct sockaddr *addr, socklen_t addrlen)
Send a datagram to a specific destination.
Definition: bsd_socket.c:555
int_t socketSetIpMulticastLoopOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_MULTICAST_LOOP option.
error_t ipv6StringToAddr(const char_t *str, Ipv6Addr *ipAddr)
Convert a string representation of an IPv6 address to a binary IPv6 address.
Definition: ipv6.c:2170
#define SO_KEEPALIVE
Definition: bsd_socket.h:144
#define IP_ADD_MEMBERSHIP
Definition: bsd_socket.h:162
#define O_NONBLOCK
Definition: bsd_socket.h:218
Ipv4Addr addr
Definition: nbns_common.h:141
#define EAI_MEMORY
Definition: bsd_socket.h:246
int_t socketSetSoReuseAddrOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_REUSEADDR option.
int_t socketSetTcpNoDelayOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_NODELAY option.
int_t socketSetIpv6MulticastIfOption(Socket *socket, const struct in_addr *optval, socklen_t optlen)
Set IPV6_MULTICAST_IF option.
#define IP_TTL
Definition: bsd_socket.h:154
#define IPV6_MULTICAST_IF
Definition: bsd_socket.h:178
int_t cmsg_type
Definition: bsd_socket.h:499
#define ENOBUFS
Definition: bsd_socket.h:268
uint8_t flags
Definition: tcp.h:358
Ipv6Addr ipv6Addr
Definition: ip.h:102
int_t socketSetIpv6RecvTrafficClassOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_RECVTCLASS option.
#define IPPROTO_IPV6
Definition: bsd_socket.h:100
int_t ai_family
Definition: bsd_socket.h:555
int_t getaddrinfo(const char_t *node, const char_t *service, const struct addrinfo *hints, struct addrinfo **res)
Convert host and service names to socket address.
Definition: bsd_socket.c:3526
unsigned int uint_t
Definition: compiler_port.h:57
size_t msg_controllen
Definition: bsd_socket.h:486
@ SOCKET_FLAG_DONT_WAIT
Definition: socket.h:139
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:255
#define osMemset(p, value, length)
Definition: os_port.h:141
TCP/IP stack core.
int_t socketSetMcastBlockSourceOption(Socket *socket, const struct group_source_req *optval, socklen_t optlen)
Set MCAST_BLOCK_SOURCE option.
@ SOCKET_EVENT_CLOSED
Definition: socket.h:174
int_t socketSetIpv6PktInfoOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_PKTINFO option.
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1516
#define IPV6_TCLASS
Definition: bsd_socket.h:189
int_t socketGetSoSndBufOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_SNDBUF option.
int_t socketGetIpv6PktInfoOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_PKTINFO option.
#define SOCKET_MAX_COUNT
Definition: socket.h:46
int_t inet_aton(const char_t *cp, struct in_addr *inp)
Convert a dot-decimal string into binary form.
Definition: bsd_socket.c:4012
#define IPV6_DROP_MEMBERSHIP
Definition: bsd_socket.h:182
int_t socketGetTcpNoDelayOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_NODELAY option.
#define osStrcpy(s1, s2)
Definition: os_port.h:213
#define TCP_KEEPINTVL
Definition: bsd_socket.h:195
int_t send(int_t s, const void *data, size_t length, int_t flags)
Send data to a connected socket.
Definition: bsd_socket.c:475
int_t socketGetIpMulticastTtlOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_MULTICAST_TTL option.
#define MCAST_LEAVE_GROUP
Definition: bsd_socket.h:171
uint16_t next
Definition: ipv4_frag.h:106
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket_misc.c:278
#define TCP_KEEPIDLE
Definition: bsd_socket.h:194
int_t socketSetMcastJoinGroupOption(Socket *socket, const struct group_req *optval, socklen_t optlen)
Set MCAST_JOIN_GROUP option.
int_t socketSetIpMulticastIfOption(Socket *socket, const struct in_addr *optval, socklen_t optlen)
Set IP_MULTICAST_IF option.
Information about address of a service provider.
Definition: bsd_socket.h:553
int_t msg_flags
Definition: bsd_socket.h:487
#define IPV6_ADD_MEMBERSHIP
Definition: bsd_socket.h:181
int_t socketSetIpBlockSourceOption(Socket *socket, const struct ip_mreq_source *optval, socklen_t optlen)
Set IP_BLOCK_SOURCE option.
@ NO_ERROR
Success.
Definition: error.h:44
#define IP_DROP_MEMBERSHIP
Definition: bsd_socket.h:163
Debugging facilities.
@ SOCKET_OPTION_TCP_NO_DELAY
Definition: socket.h:205
uint8_t s6_addr[16]
Definition: bsd_socket.h:378
#define INFINITE_DELAY
Definition: os_port.h:75
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:129
@ SOCKET_OPTION_IPV4_PKT_INFO
Definition: socket.h:196
int_t sendmsg(int_t s, struct msghdr *msg, int_t flags)
Send a message.
Definition: bsd_socket.c:685
int_t closesocket(int_t s)
The closesocket function closes an existing socket.
Definition: bsd_socket.c:3156
uint16_t h_addrtype
Definition: bsd_socket.h:542
struct addrinfo * ai_next
Definition: bsd_socket.h:561
IPv4 packet information.
Definition: bsd_socket.h:508
#define SO_ERROR
Definition: bsd_socket.h:139
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:1438