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