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-2023 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.3.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
794  {
795  //Unknown control message type
796  }
797  }
798  else
799 #endif
800 #if (IPV6_SUPPORT == ENABLED)
801  //IPv6 protocol?
802  if(addr->sa_family == AF_INET6 && cmsg->cmsg_level == IPPROTO_IPV6)
803  {
804  //Check control message type
805  if(cmsg->cmsg_type == IPV6_PKTINFO &&
806  cmsg->cmsg_len >= CMSG_LEN(sizeof(IN_PKTINFO)))
807  {
808  //Point to the ancillary data value
809  IN6_PKTINFO *pktInfo = (IN6_PKTINFO *) CMSG_DATA(cmsg);
810 
811  //Specify source IPv6 address
812  message.srcIpAddr.length = sizeof(Ipv6Addr);
813  ipv6CopyAddr(&message.srcIpAddr.ipv6Addr, pktInfo->ipi6_addr.s6_addr);
814  }
815  else if(cmsg->cmsg_type == IPV6_TCLASS &&
816  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
817  {
818  //Point to the ancillary data value
819  val = (int_t *) CMSG_DATA(cmsg);
820  //Specify Traffic Class value
821  message.tos = (uint8_t) *val;
822  }
823  else if(cmsg->cmsg_type == IPV6_HOPLIMIT &&
824  cmsg->cmsg_len >= CMSG_LEN(sizeof(int_t)))
825  {
826  //Point to the ancillary data value
827  val = (int_t *) CMSG_DATA(cmsg);
828  //Specify Hop Limit value
829  message.ttl = (uint8_t) *val;
830  }
831  else
832  {
833  //Unknown control message type
834  }
835  }
836  //Unknown protocol?
837  else
838 #endif
839  {
840  //Discard control message
841  }
842 
843  //Next control message
844  n += cmsg->cmsg_len;
845  }
846  else
847  {
848  //Malformed control message
849  break;
850  }
851  }
852  }
853 
854  //The flags parameter can be used to influence the behavior of the function
855  socketFlags = 0;
856 
857  //The MSG_DONTROUTE flag specifies that the data should not be subject
858  //to routing
859  if((flags & MSG_DONTROUTE) != 0)
860  {
861  socketFlags |= SOCKET_FLAG_DONT_ROUTE;
862  }
863 
864  //The TCP_NODELAY option disables the Nagle algorithm for TCP sockets
865  if((sock->options & SOCKET_OPTION_TCP_NO_DELAY) != 0)
866  {
867  socketFlags |= SOCKET_FLAG_NO_DELAY;
868  }
869 
870  //Send message
871  error = socketSendMsg(sock, &message, socketFlags);
872 
873  //Any error to report?
874  if(error != NO_ERROR)
875  {
876  //Otherwise, a value of SOCKET_ERROR is returned
877  socketTranslateErrorCode(sock, error);
878  return SOCKET_ERROR;
879  }
880 
881  //Return the number of bytes transferred so far
882  return message.length;
883 }
884 
885 
886 /**
887  * @brief Receive data from a connected socket
888  * @param[in] s Descriptor that identifies a connected socket
889  * @param[out] data Buffer where to store the incoming data
890  * @param[in] size Maximum number of bytes that can be received
891  * @param[in] flags Set of flags that influences the behavior of this function
892  * @return If no error occurs, recv returns the number of bytes received. If the
893  * connection has been gracefully closed, the return value is zero.
894  * Otherwise, a value of SOCKET_ERROR is returned
895  **/
896 
897 int_t recv(int_t s, void *data, size_t size, int_t flags)
898 {
899  error_t error;
900  size_t received;
901  uint_t socketFlags;
902  Socket *sock;
903 
904  //Make sure the socket descriptor is valid
905  if(s < 0 || s >= SOCKET_MAX_COUNT)
906  {
907  return SOCKET_ERROR;
908  }
909 
910  //Point to the socket structure
911  sock = &socketTable[s];
912 
913  //The flags parameter can be used to influence the behavior of the function
914  socketFlags = 0;
915 
916  //When the MSG_PEEK flag is specified, the data is copied into the buffer,
917  //but is not removed from the input queue
918  if((flags & MSG_PEEK) != 0)
919  {
920  socketFlags |= SOCKET_FLAG_PEEK;
921  }
922 
923  //When the MSG_WAITALL flag is specified, the receive request will complete
924  //when the buffer supplied by the caller is completely full
925  if((flags & MSG_WAITALL) != 0)
926  {
927  socketFlags |= SOCKET_FLAG_WAIT_ALL;
928  }
929 
930  //The MSG_DONTWAIT flag enables non-blocking operation
931  if((flags & MSG_DONTWAIT) != 0)
932  {
933  socketFlags |= SOCKET_FLAG_DONT_WAIT;
934  }
935 
936  //Receive data
937  error = socketReceive(sock, data, size, &received, socketFlags);
938 
939  //Any error to report?
940  if(error == ERROR_END_OF_STREAM)
941  {
942  //If the connection has been gracefully closed, the return value is zero
943  return 0;
944  }
945  else if(error != NO_ERROR)
946  {
947  //Otherwise, a value of SOCKET_ERROR is returned
948  socketTranslateErrorCode(sock, error);
949  return SOCKET_ERROR;
950  }
951 
952  //Return the number of bytes received
953  return received;
954 }
955 
956 
957 /**
958  * @brief Receive a datagram
959  * @param[in] s Descriptor that identifies a socket
960  * @param[out] data Buffer where to store the incoming data
961  * @param[in] size Maximum number of bytes that can be received
962  * @param[in] flags Set of flags that influences the behavior of this function
963  * @param[out] addr Source address upon return (optional)
964  * @param[in,out] addrlen Length in bytes of the address (optional)
965  * @return If no error occurs, recvfrom returns the number of bytes received.
966  * Otherwise, a value of SOCKET_ERROR is returned
967  **/
968 
969 int_t recvfrom(int_t s, void *data, size_t size, int_t flags,
970  struct sockaddr *addr, socklen_t *addrlen)
971 {
972  error_t error;
973  size_t received;
974  uint_t socketFlags;
975  uint16_t port;
976  IpAddr ipAddr;
977  Socket *sock;
978 
979  //Make sure the socket descriptor is valid
980  if(s < 0 || s >= SOCKET_MAX_COUNT)
981  {
982  return SOCKET_ERROR;
983  }
984 
985  //Point to the socket structure
986  sock = &socketTable[s];
987 
988  //The flags parameter can be used to influence the behavior of the function
989  socketFlags = 0;
990 
991  //When the MSG_PEEK flag is specified, the data is copied into the buffer,
992  //but is not removed from the input queue
993  if((flags & MSG_PEEK) != 0)
994  {
995  socketFlags |= SOCKET_FLAG_PEEK;
996  }
997 
998  //When the MSG_WAITALL flag is specified, the receive request will complete
999  //when the buffer supplied by the caller is completely full
1000  if((flags & MSG_WAITALL) != 0)
1001  {
1002  socketFlags |= SOCKET_FLAG_WAIT_ALL;
1003  }
1004 
1005  //The MSG_DONTWAIT flag enables non-blocking operation
1006  if((flags & MSG_DONTWAIT) != 0)
1007  {
1008  socketFlags |= SOCKET_FLAG_DONT_WAIT;
1009  }
1010 
1011  //Receive data
1012  error = socketReceiveFrom(sock, &ipAddr, &port, data, size, &received,
1013  socketFlags);
1014 
1015  //Any error to report?
1016  if(error == ERROR_END_OF_STREAM)
1017  {
1018  //If the connection has been gracefully closed, the return value is zero
1019  return 0;
1020  }
1021  else if(error != NO_ERROR)
1022  {
1023  //Otherwise, a value of SOCKET_ERROR is returned
1024  socketTranslateErrorCode(sock, error);
1025  return SOCKET_ERROR;
1026  }
1027 
1028  //The address parameter is optional
1029  if(addr != NULL && addrlen != NULL)
1030  {
1031 #if (IPV4_SUPPORT == ENABLED)
1032  //IPv4 address?
1033  if(ipAddr.length == sizeof(Ipv4Addr) &&
1034  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1035  {
1036  //Point to the IPv4 address information
1037  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1038 
1039  //Set address family and port number
1040  sa->sin_family = AF_INET;
1041  sa->sin_port = htons(port);
1042 
1043  //Copy IPv4 address
1044  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
1045 
1046  //Return the actual length of the address
1047  *addrlen = sizeof(SOCKADDR_IN);
1048  }
1049  else
1050 #endif
1051 #if (IPV6_SUPPORT == ENABLED)
1052  //IPv6 address?
1053  if(ipAddr.length == sizeof(Ipv6Addr) &&
1054  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1055  {
1056  //Point to the IPv6 address information
1057  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1058 
1059  //Set address family and port number
1060  sa->sin6_family = AF_INET6;
1061  sa->sin6_port = htons(port);
1062  sa->sin6_flowinfo = 0;
1063  sa->sin6_scope_id = 0;
1064 
1065  //Copy IPv6 address
1066  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
1067 
1068  //Return the actual length of the address
1069  *addrlen = sizeof(SOCKADDR_IN6);
1070  }
1071  else
1072 #endif
1073  //Invalid address?
1074  {
1075  //Report an error
1076  socketSetErrnoCode(sock, EINVAL);
1077  return SOCKET_ERROR;
1078  }
1079  }
1080 
1081  //Return the number of bytes received
1082  return received;
1083 }
1084 
1085 
1086 /**
1087  * @brief Receive a message
1088  * @param[in] s Descriptor that identifies a socket
1089  * @param[in,out] msg Pointer to the structure describing the message
1090  * @param[in] flags Set of flags that influences the behavior of this function
1091  * @return If no error occurs, recvmsg returns the number of bytes received.
1092  * Otherwise, a value of SOCKET_ERROR is returned
1093  **/
1094 
1096 {
1097  error_t error;
1098  size_t n;
1099  uint_t socketFlags;
1100  Socket *sock;
1102 
1103  //Make sure the socket descriptor is valid
1104  if(s < 0 || s >= SOCKET_MAX_COUNT)
1105  {
1106  return SOCKET_ERROR;
1107  }
1108 
1109  //Point to the socket structure
1110  sock = &socketTable[s];
1111 
1112  //Check parameters
1113  if(msg == NULL || msg->msg_iov == NULL || msg->msg_iovlen != 1)
1114  {
1115  socketSetErrnoCode(sock, EINVAL);
1116  return SOCKET_ERROR;
1117  }
1118 
1119  //Point to the receive buffer
1121  message.data = msg->msg_iov[0].iov_base;
1122  message.size = msg->msg_iov[0].iov_len;
1123 
1124  //The flags parameter can be used to influence the behavior of the function
1125  socketFlags = 0;
1126 
1127  //When the MSG_PEEK flag is specified, the data is copied into the buffer,
1128  //but is not removed from the input queue
1129  if((flags & MSG_PEEK) != 0)
1130  {
1131  socketFlags |= SOCKET_FLAG_PEEK;
1132  }
1133 
1134  //When the MSG_WAITALL flag is specified, the receive request will complete
1135  //when the buffer supplied by the caller is completely full
1136  if((flags & MSG_WAITALL) != 0)
1137  {
1138  socketFlags |= SOCKET_FLAG_WAIT_ALL;
1139  }
1140 
1141  //The MSG_DONTWAIT flag enables non-blocking operation
1142  if((flags & MSG_DONTWAIT) != 0)
1143  {
1144  socketFlags |= SOCKET_FLAG_DONT_WAIT;
1145  }
1146 
1147  //Receive message
1148  error = socketReceiveMsg(sock, &message, socketFlags);
1149 
1150  //Any error to report?
1151  if(error)
1152  {
1153  socketTranslateErrorCode(sock, error);
1154  return SOCKET_ERROR;
1155  }
1156 
1157  //The source address parameter is optional
1158  if(msg->msg_name != NULL)
1159  {
1160 #if (IPV4_SUPPORT == ENABLED)
1161  //IPv4 address?
1162  if(message.srcIpAddr.length == sizeof(Ipv4Addr) &&
1163  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN))
1164  {
1165  //Point to the IPv4 address information
1166  SOCKADDR_IN *sa = (SOCKADDR_IN *) msg->msg_name;
1167 
1168  //Set address family and port number
1169  sa->sin_family = AF_INET;
1170  sa->sin_port = htons(message.srcPort);
1171 
1172  //Copy IPv4 address
1173  sa->sin_addr.s_addr = message.srcIpAddr.ipv4Addr;
1174 
1175  //Return the actual length of the address
1176  msg->msg_namelen = sizeof(SOCKADDR_IN);
1177  }
1178  else
1179 #endif
1180 #if (IPV6_SUPPORT == ENABLED)
1181  //IPv6 address?
1182  if(message.srcIpAddr.length == sizeof(Ipv6Addr) &&
1183  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN6))
1184  {
1185  //Point to the IPv6 address information
1186  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) msg->msg_name;
1187 
1188  //Set address family and port number
1189  sa->sin6_family = AF_INET6;
1190  sa->sin6_port = htons(message.srcPort);
1191  sa->sin6_flowinfo = 0;
1192  sa->sin6_scope_id = 0;
1193 
1194  //Copy IPv6 address
1195  ipv6CopyAddr(sa->sin6_addr.s6_addr, &message.srcIpAddr.ipv6Addr);
1196 
1197  //Return the actual length of the address
1198  msg->msg_namelen = sizeof(SOCKADDR_IN6);
1199  }
1200  else
1201 #endif
1202  //Invalid address?
1203  {
1204  //Report an error
1205  socketSetErrnoCode(sock, EINVAL);
1206  return SOCKET_ERROR;
1207  }
1208  }
1209  else
1210  {
1211  msg->msg_namelen = 0;
1212  }
1213 
1214  //Clear flags
1215  msg->msg_flags = 0;
1216 
1217  //Length of the ancillary data buffer
1218  n = 0;
1219 
1220  //The ancillary data buffer parameter is optional
1221  if(msg->msg_control != NULL)
1222  {
1223 #if (IPV4_SUPPORT == ENABLED)
1224  //IPv4 address?
1225  if(message.destIpAddr.length == sizeof(Ipv4Addr))
1226  {
1227  int_t *val;
1228  CMSGHDR *cmsg;
1229  IN_PKTINFO *pktInfo;
1230 
1231  //The IP_PKTINFO option allows an application to enable or disable
1232  //the return of IPv4 packet information
1233  if((sock->options & SOCKET_OPTION_IPV4_PKT_INFO) != 0)
1234  {
1235  //Make sure there is enough room to add the control message
1236  if((n + CMSG_SPACE(sizeof(IN_PKTINFO))) <= msg->msg_controllen)
1237  {
1238  //Point to the ancillary data header
1239  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1240 
1241  //Format ancillary data header
1242  cmsg->cmsg_len = CMSG_LEN(sizeof(IN_PKTINFO));
1243  cmsg->cmsg_level = IPPROTO_IP;
1244  cmsg->cmsg_type = IP_PKTINFO;
1245 
1246  //Point to the ancillary data value
1247  pktInfo = (IN_PKTINFO *) CMSG_DATA(cmsg);
1248 
1249  //Format packet information
1250  pktInfo->ipi_ifindex = message.interface->index;
1251  pktInfo->ipi_addr.s_addr = message.destIpAddr.ipv4Addr;
1252 
1253  //Adjust the actual length of the ancillary data buffer
1254  n += CMSG_SPACE(sizeof(IN_PKTINFO));
1255  }
1256  else
1257  {
1258  //When the control message buffer is too short to store all
1259  //messages, the MSG_CTRUNC flag must be set
1260  msg->msg_flags |= MSG_CTRUNC;
1261  }
1262  }
1263 
1264  //The IP_RECVTOS option allows an application to enable or disable
1265  //the return of ToS header field on received datagrams
1266  if((sock->options & SOCKET_OPTION_IPV4_RECV_TOS) != 0)
1267  {
1268  //Make sure there is enough room to add the control message
1269  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1270  {
1271  //Point to the ancillary data header
1272  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1273 
1274  //Format ancillary data header
1275  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1276  cmsg->cmsg_level = IPPROTO_IP;
1277  cmsg->cmsg_type = IP_TOS;
1278 
1279  //Point to the ancillary data value
1280  val = (int_t *) CMSG_DATA(cmsg);
1281  //Set ancillary data value
1282  *val = message.tos;
1283 
1284  //Adjust the actual length of the ancillary data buffer
1285  n += CMSG_SPACE(sizeof(int_t));
1286  }
1287  else
1288  {
1289  //When the control message buffer is too short to store all
1290  //messages, the MSG_CTRUNC flag must be set
1291  msg->msg_flags |= MSG_CTRUNC;
1292  }
1293  }
1294 
1295  //The IP_RECVTTL option allows an application to enable or disable
1296  //the return of TTL header field on received datagrams
1297  if((sock->options & SOCKET_OPTION_IPV4_RECV_TTL) != 0)
1298  {
1299  //Make sure there is enough room to add the control message
1300  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1301  {
1302  //Point to the ancillary data header
1303  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1304 
1305  //Format ancillary data header
1306  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1307  cmsg->cmsg_level = IPPROTO_IP;
1308  cmsg->cmsg_type = IP_TTL;
1309 
1310  //Point to the ancillary data value
1311  val = (int_t *) CMSG_DATA(cmsg);
1312  //Set ancillary data value
1313  *val = message.ttl;
1314 
1315  //Adjust the actual length of the ancillary data buffer
1316  n += CMSG_SPACE(sizeof(int_t));
1317  }
1318  else
1319  {
1320  //When the control message buffer is too short to store all
1321  //messages, the MSG_CTRUNC flag must be set
1322  msg->msg_flags |= MSG_CTRUNC;
1323  }
1324  }
1325  }
1326  else
1327 #endif
1328 #if (IPV6_SUPPORT == ENABLED)
1329  //IPv6 address?
1330  if(message.destIpAddr.length == sizeof(Ipv6Addr))
1331  {
1332  int_t *val;
1333  CMSGHDR *cmsg;
1334  IN6_PKTINFO *pktInfo;
1335 
1336  //The IPV6_PKTINFO option allows an application to enable or disable
1337  //the return of IPv6 packet information
1338  if((sock->options & SOCKET_OPTION_IPV6_PKT_INFO) != 0)
1339  {
1340  //Make sure there is enough room to add the control message
1341  if((n + CMSG_SPACE(sizeof(IN6_PKTINFO))) <= msg->msg_controllen)
1342  {
1343  //Point to the ancillary data header
1344  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1345 
1346  //Format ancillary data header
1347  cmsg->cmsg_len = CMSG_LEN(sizeof(IN6_PKTINFO));
1348  cmsg->cmsg_level = IPPROTO_IPV6;
1349  cmsg->cmsg_type = IPV6_PKTINFO;
1350 
1351  //Point to the ancillary data value
1352  pktInfo = (IN6_PKTINFO *) CMSG_DATA(cmsg);
1353 
1354  //Format packet information
1355  pktInfo->ipi6_ifindex = message.interface->index;
1356  ipv6CopyAddr(pktInfo->ipi6_addr.s6_addr, &message.destIpAddr.ipv6Addr);
1357 
1358  //Adjust the actual length of the ancillary data buffer
1359  n += CMSG_SPACE(sizeof(IN6_PKTINFO));
1360  }
1361  else
1362  {
1363  //When the control message buffer is too short to store all
1364  //messages, the MSG_CTRUNC flag must be set
1365  msg->msg_flags |= MSG_CTRUNC;
1366  }
1367  }
1368 
1369  //The IPV6_RECVTCLASS option allows an application to enable or disable
1370  //the return of Traffic Class header field on received datagrams
1371  if((sock->options & SOCKET_OPTION_IPV6_RECV_TRAFFIC_CLASS) != 0)
1372  {
1373  //Make sure there is enough room to add the control message
1374  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1375  {
1376  //Point to the ancillary data header
1377  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1378 
1379  //Format ancillary data header
1380  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1381  cmsg->cmsg_level = IPPROTO_IPV6;
1382  cmsg->cmsg_type = IPV6_TCLASS;
1383 
1384  //Point to the ancillary data value
1385  val = (int_t *) CMSG_DATA(cmsg);
1386  //Set ancillary data value
1387  *val = message.tos;
1388 
1389  //Adjust the actual length of the ancillary data buffer
1390  n += CMSG_SPACE(sizeof(int_t));
1391  }
1392  else
1393  {
1394  //When the control message buffer is too short to store all
1395  //messages, the MSG_CTRUNC flag must be set
1396  msg->msg_flags |= MSG_CTRUNC;
1397  }
1398  }
1399 
1400  //The IPV6_RECVHOPLIMIT option allows an application to enable or
1401  //disable the return of Hop Limit header field on received datagrams
1402  if((sock->options & SOCKET_OPTION_IPV6_RECV_HOP_LIMIT) != 0)
1403  {
1404  //Make sure there is enough room to add the control message
1405  if((n + CMSG_SPACE(sizeof(int_t))) <= msg->msg_controllen)
1406  {
1407  //Point to the ancillary data header
1408  cmsg = (CMSGHDR *) ((uint8_t *) msg->msg_control + n);
1409 
1410  //Format ancillary data header
1411  cmsg->cmsg_len = CMSG_LEN(sizeof(int_t));
1412  cmsg->cmsg_level = IPPROTO_IPV6;
1413  cmsg->cmsg_type = IPV6_HOPLIMIT;
1414 
1415  //Point to the ancillary data value
1416  val = (int_t *) CMSG_DATA(cmsg);
1417  //Set ancillary data value
1418  *val = message.ttl;
1419 
1420  //Adjust the actual length of the ancillary data buffer
1421  n += CMSG_SPACE(sizeof(int_t));
1422  }
1423  else
1424  {
1425  //When the control message buffer is too short to store all
1426  //messages, the MSG_CTRUNC flag must be set
1427  msg->msg_flags |= MSG_CTRUNC;
1428  }
1429  }
1430  }
1431  else
1432 #endif
1433  //Invalid address?
1434  {
1435  //Just for sanity
1436  }
1437  }
1438 
1439  //Length of the actual length of the ancillary data buffer
1440  msg->msg_controllen = n;
1441 
1442  //Return the number of bytes received
1443  return message.length;
1444 }
1445 
1446 
1447 /**
1448  * @brief Retrieves the local name for a socket
1449  * @param[in] s Descriptor identifying a socket
1450  * @param[out] addr Address of the socket
1451  * @param[in,out] addrlen Length in bytes of the address
1452  * @return If no error occurs, getsockname returns SOCKET_SUCCESS
1453  * Otherwise, it returns SOCKET_ERROR
1454  **/
1455 
1457 {
1458  int_t ret;
1459  Socket *sock;
1460 
1461  //Make sure the socket descriptor is valid
1462  if(s < 0 || s >= SOCKET_MAX_COUNT)
1463  {
1464  return SOCKET_ERROR;
1465  }
1466 
1467  //Point to the socket structure
1468  sock = &socketTable[s];
1469 
1470  //Get exclusive access
1472 
1473  //Check whether the socket has been bound to an address
1474  if(sock->localIpAddr.length != 0)
1475  {
1476 #if (IPV4_SUPPORT == ENABLED)
1477  //IPv4 address?
1478  if(sock->localIpAddr.length == sizeof(Ipv4Addr) &&
1479  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1480  {
1481  //Point to the IPv4 address information
1482  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1483 
1484  //Set address family and port number
1485  sa->sin_family = AF_INET;
1486  sa->sin_port = htons(sock->localPort);
1487 
1488  //Copy IPv4 address
1489  sa->sin_addr.s_addr = sock->localIpAddr.ipv4Addr;
1490 
1491  //Return the actual length of the address
1492  *addrlen = sizeof(SOCKADDR_IN);
1493  //Successful processing
1494  ret = SOCKET_SUCCESS;
1495  }
1496  else
1497 #endif
1498 #if (IPV6_SUPPORT == ENABLED)
1499  //IPv6 address?
1500  if(sock->localIpAddr.length == sizeof(Ipv6Addr) &&
1501  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1502  {
1503  //Point to the IPv6 address information
1504  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1505 
1506  //Set address family and port number
1507  sa->sin6_family = AF_INET6;
1508  sa->sin6_port = htons(sock->localPort);
1509  sa->sin6_flowinfo = 0;
1510  sa->sin6_scope_id = 0;
1511 
1512  //Copy IPv6 address
1513  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->localIpAddr.ipv6Addr);
1514 
1515  //Return the actual length of the address
1516  *addrlen = sizeof(SOCKADDR_IN6);
1517  //Successful processing
1518  ret = SOCKET_SUCCESS;
1519  }
1520  else
1521 #endif
1522  {
1523  //The specified length is not valid
1524  socketSetErrnoCode(sock, EINVAL);
1525  ret = SOCKET_ERROR;
1526  }
1527  }
1528  else
1529  {
1530  //The socket is not bound to any address
1532  ret = SOCKET_ERROR;
1533  }
1534 
1535  //Release exclusive access
1537 
1538  //return status code
1539  return ret;
1540 }
1541 
1542 
1543 /**
1544  * @brief Retrieves the address of the peer to which a socket is connected
1545  * @param[in] s Descriptor identifying a socket
1546  * @param[out] addr Address of the peer
1547  * @param[in,out] addrlen Length in bytes of the address
1548  * @return If no error occurs, getpeername returns SOCKET_SUCCESS
1549  * Otherwise, it returns SOCKET_ERROR
1550  **/
1551 
1553 {
1554  int_t ret;
1555  Socket *sock;
1556 
1557  //Make sure the socket descriptor is valid
1558  if(s < 0 || s >= SOCKET_MAX_COUNT)
1559  {
1560  return SOCKET_ERROR;
1561  }
1562 
1563  //Point to the socket structure
1564  sock = &socketTable[s];
1565 
1566  //Get exclusive access
1568 
1569  //Check whether the socket is connected to a peer
1570  if(sock->remoteIpAddr.length != 0)
1571  {
1572 #if (IPV4_SUPPORT == ENABLED)
1573  //IPv4 address?
1574  if(sock->remoteIpAddr.length == sizeof(Ipv4Addr) &&
1575  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1576  {
1577  //Point to the IPv4 address information
1578  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1579 
1580  //Set address family and port number
1581  sa->sin_family = AF_INET;
1582  sa->sin_port = htons(sock->remotePort);
1583 
1584  //Copy IPv4 address
1585  sa->sin_addr.s_addr = sock->remoteIpAddr.ipv4Addr;
1586 
1587  //Return the actual length of the address
1588  *addrlen = sizeof(SOCKADDR_IN);
1589  //Successful processing
1590  ret = SOCKET_SUCCESS;
1591  }
1592  else
1593 #endif
1594 #if (IPV6_SUPPORT == ENABLED)
1595  //IPv6 address?
1596  if(sock->remoteIpAddr.length == sizeof(Ipv6Addr) &&
1597  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1598  {
1599  //Point to the IPv6 address information
1600  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1601 
1602  //Set address family and port number
1603  sa->sin6_family = AF_INET6;
1604  sa->sin6_port = htons(sock->remotePort);
1605  sa->sin6_flowinfo = 0;
1606  sa->sin6_scope_id = 0;
1607 
1608  //Copy IPv6 address
1609  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->remoteIpAddr.ipv6Addr);
1610 
1611  //Return the actual length of the address
1612  *addrlen = sizeof(SOCKADDR_IN6);
1613  //Successful processing
1614  ret = SOCKET_SUCCESS;
1615  }
1616  else
1617 #endif
1618  {
1619  //The specified length is not valid
1620  socketSetErrnoCode(sock, EINVAL);
1621  ret = SOCKET_ERROR;
1622  }
1623  }
1624  else
1625  {
1626  //The socket is not connected to any peer
1628  ret = SOCKET_ERROR;
1629  }
1630 
1631  //Release exclusive access
1633 
1634  //return status code
1635  return ret;
1636 }
1637 
1638 
1639 /**
1640  * @brief The setsockopt function sets a socket option
1641  * @param[in] s Descriptor that identifies a socket
1642  * @param[in] level The level at which the option is defined
1643  * @param[in] optname The socket option for which the value is to be set
1644  * @param[in] optval A pointer to the buffer in which the value for the
1645  * requested option is specified
1646  * @param[in] optlen The size, in bytes, of the buffer pointed to by the optval
1647  * parameter
1648  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
1649  * Otherwise, it returns SOCKET_ERROR
1650  **/
1651 
1652 int_t setsockopt(int_t s, int_t level, int_t optname, const void *optval,
1653  socklen_t optlen)
1654 {
1655  int_t ret;
1656  Socket *sock;
1657 
1658  //Make sure the socket descriptor is valid
1659  if(s < 0 || s >= SOCKET_MAX_COUNT)
1660  {
1661  return SOCKET_ERROR;
1662  }
1663 
1664  //Point to the socket structure
1665  sock = &socketTable[s];
1666 
1667  //Make sure the option is valid
1668  if(optval != NULL)
1669  {
1670  //Check option level
1671  if(level == SOL_SOCKET)
1672  {
1673  //Check option type
1674  if(optname == SO_REUSEADDR)
1675  {
1676  //Set SO_REUSEADDR option
1677  ret = socketSetSoReuseAddrOption(sock, optval, optlen);
1678  }
1679  else if(optname == SO_BROADCAST)
1680  {
1681  //Set SO_BROADCAST option
1682  ret = socketSetSoBroadcastOption(sock, optval, optlen);
1683  }
1684  else if(optname == SO_SNDTIMEO)
1685  {
1686  //Set SO_SNDTIMEO option
1687  ret = socketSetSoSndTimeoOption(sock, optval, optlen);
1688  }
1689  else if(optname == SO_RCVTIMEO)
1690  {
1691  //Set SO_RCVTIMEO option
1692  ret = socketSetSoRcvTimeoOption(sock, optval, optlen);
1693  }
1694  else if(optname == SO_SNDBUF)
1695  {
1696  //Set SO_SNDBUF option
1697  ret = socketSetSoSndBufOption(sock, optval, optlen);
1698  }
1699  else if(optname == SO_RCVBUF)
1700  {
1701  //Set SO_RCVBUF option
1702  ret = socketSetSoRcvBufOption(sock, optval, optlen);
1703  }
1704  else if(optname == SO_KEEPALIVE)
1705  {
1706  //Set SO_KEEPALIVE option
1707  ret = socketSetSoKeepAliveOption(sock, optval, optlen);
1708  }
1709  else
1710  {
1711  //Unknown option
1713  //Report an error
1714  ret = SOCKET_ERROR;
1715  }
1716  }
1717  else if(level == IPPROTO_IP)
1718  {
1719  //Check option type
1720  if(optname == IP_TOS)
1721  {
1722  //Set IP_TOS option
1723  ret = socketSetIpTosOption(sock, optval, optlen);
1724  }
1725  else if(optname == IP_TTL)
1726  {
1727  //Set IP_TTL option
1728  ret = socketSetIpTtlOption(sock, optval, optlen);
1729  }
1730  else if(optname == IP_MULTICAST_IF)
1731  {
1732  //Set IP_MULTICAST_IF option
1733  ret = socketSetIpMulticastIfOption(sock, optval, optlen);
1734  }
1735  else if(optname == IP_MULTICAST_TTL)
1736  {
1737  //Set IP_MULTICAST_TTL option
1738  ret = socketSetIpMulticastTtlOption(sock, optval, optlen);
1739  }
1740  else if(optname == IP_MULTICAST_LOOP)
1741  {
1742  //Set IP_MULTICAST_LOOP option
1743  ret = socketSetIpMulticastLoopOption(sock, optval, optlen);
1744  }
1745  else if(optname == IP_ADD_MEMBERSHIP)
1746  {
1747  //Set IP_ADD_MEMBERSHIP option
1748  ret = socketSetIpAddMembershipOption(sock, optval, optlen);
1749  }
1750  else if(optname == IP_DROP_MEMBERSHIP)
1751  {
1752  //Set IP_DROP_MEMBERSHIP option
1753  ret = socketSetIpDropMembershipOption(sock, optval, optlen);
1754  }
1755  else if(optname == IP_PKTINFO)
1756  {
1757  //Set IP_PKTINFO option
1758  ret = socketSetIpPktInfoOption(sock, optval, optlen);
1759  }
1760  else if(optname == IP_RECVTOS)
1761  {
1762  //Set IP_RECVTOS option
1763  ret = socketSetIpRecvTosOption(sock, optval, optlen);
1764  }
1765  else if(optname == IP_RECVTTL)
1766  {
1767  //Set IP_RECVTTL option
1768  ret = socketSetIpRecvTtlOption(sock, optval, optlen);
1769  }
1770  else
1771  {
1772  //Unknown option
1774  ret = SOCKET_ERROR;
1775  }
1776  }
1777  else if(level == IPPROTO_IPV6)
1778  {
1779  //Check option type
1780  if(optname == IPV6_TCLASS)
1781  {
1782  //Set IPV6_TCLASS option
1783  ret = socketSetIpv6TrafficClassOption(sock, optval, optlen);
1784  }
1785  else if(optname == IPV6_UNICAST_HOPS)
1786  {
1787  //Set IPV6_UNICAST_HOPS option
1788  ret = socketSetIpv6UnicastHopsOption(sock, optval, optlen);
1789  }
1790  else if(optname == IPV6_MULTICAST_IF)
1791  {
1792  //Set IPV6_MULTICAST_IF option
1793  ret = socketSetIpv6MulticastIfOption(sock, optval, optlen);
1794  }
1795  else if(optname == IPV6_MULTICAST_HOPS)
1796  {
1797  //Set IPV6_MULTICAST_HOPS option
1798  ret = socketSetIpv6MulticastHopsOption(sock, optval, optlen);
1799  }
1800  else if(optname == IPV6_MULTICAST_LOOP)
1801  {
1802  //Set IPV6_MULTICAST_LOOP option
1803  ret = socketSetIpv6MulticastLoopOption(sock, optval, optlen);
1804  }
1805  else if(optname == IPV6_ADD_MEMBERSHIP)
1806  {
1807  //Set IPV6_ADD_MEMBERSHIP option
1808  ret = socketSetIpv6AddMembershipOption(sock, optval, optlen);
1809  }
1810  else if(optname == IPV6_DROP_MEMBERSHIP)
1811  {
1812  //Set IPV6_DROP_MEMBERSHIP option
1813  ret = socketSetIpv6DropMembershipOption(sock, optval, optlen);
1814  }
1815  else if(optname == IPV6_V6ONLY)
1816  {
1817  //Set IPV6_V6ONLY option
1818  ret = socketSetIpv6OnlyOption(sock, optval, optlen);
1819  }
1820  else if(optname == IPV6_PKTINFO)
1821  {
1822  //Set IPV6_PKTINFO option
1823  ret = socketSetIpv6PktInfoOption(sock, optval, optlen);
1824  }
1825  else if(optname == IPV6_RECVTCLASS)
1826  {
1827  //Set IPV6_RECVTCLASS option
1828  ret = socketSetIpv6RecvTrafficClassOption(sock, optval, optlen);
1829  }
1830  else if(optname == IPV6_RECVHOPLIMIT)
1831  {
1832  //Set IPV6_RECVHOPLIMIT option
1833  ret = socketSetIpv6RecvHopLimitOption(sock, optval, optlen);
1834  }
1835  else
1836  {
1837  //Unknown option
1839  ret = SOCKET_ERROR;
1840  }
1841  }
1842  else if(level == IPPROTO_TCP)
1843  {
1844  //Check option type
1845  if(optname == TCP_NODELAY)
1846  {
1847  //Set TCP_NODELAY option
1848  ret = socketSetTcpNoDelayOption(sock, optval, optlen);
1849  }
1850  else if(optname == TCP_MAXSEG)
1851  {
1852  //Set TCP_MAXSEG option
1853  ret = socketSetTcpMaxSegOption(sock, optval, optlen);
1854  }
1855  else if(optname == TCP_KEEPIDLE)
1856  {
1857  //Set TCP_KEEPIDLE option
1858  ret = socketSetTcpKeepIdleOption(sock, optval, optlen);
1859  }
1860  else if(optname == TCP_KEEPINTVL)
1861  {
1862  //Set TCP_KEEPINTVL option
1863  ret = socketSetTcpKeepIntvlOption(sock, optval, optlen);
1864  }
1865  else if(optname == TCP_KEEPCNT)
1866  {
1867  //Set TCP_KEEPCNT option
1868  ret = socketSetTcpKeepCntOption(sock, optval, optlen);
1869  }
1870  else
1871  {
1872  //Unknown option
1874  ret = SOCKET_ERROR;
1875  }
1876  }
1877  else
1878  {
1879  //The specified level is not valid
1880  socketSetErrnoCode(sock, EINVAL);
1881  ret = SOCKET_ERROR;
1882  }
1883  }
1884  else
1885  {
1886  //The option is not valid
1887  socketSetErrnoCode(sock, EFAULT);
1888  ret = SOCKET_ERROR;
1889  }
1890 
1891  //return status code
1892  return ret;
1893 }
1894 
1895 
1896 /**
1897  * @brief The getsockopt function retrieves a socket option
1898  * @param[in] s Descriptor that identifies a socket
1899  * @param[in] level The level at which the option is defined
1900  * @param[in] optname The socket option for which the value is to be retrieved
1901  * @param[out] optval A pointer to the buffer in which the value for the
1902  * requested option is to be returned
1903  * @param[in,out] optlen The size, in bytes, of the buffer pointed to by the
1904  * optval parameter
1905  * @return If no error occurs, getsockopt returns SOCKET_SUCCESS
1906  * Otherwise, it returns SOCKET_ERROR
1907  **/
1908 
1909 int_t getsockopt(int_t s, int_t level, int_t optname, void *optval,
1910  socklen_t *optlen)
1911 {
1912  int_t ret;
1913  Socket *sock;
1914 
1915  //Make sure the socket descriptor is valid
1916  if(s < 0 || s >= SOCKET_MAX_COUNT)
1917  {
1918  return SOCKET_ERROR;
1919  }
1920 
1921  //Point to the socket structure
1922  sock = &socketTable[s];
1923 
1924  //Get exclusive access
1926 
1927  //Make sure the option is valid
1928  if(optval != NULL)
1929  {
1930  //Check option level
1931  if(level == SOL_SOCKET)
1932  {
1933  //Check option type
1934  if(optname == SO_REUSEADDR)
1935  {
1936  //Get SO_REUSEADDR option
1937  ret = socketGetSoReuseAddrOption(sock, optval, optlen);
1938  }
1939  else if(optname == SO_BROADCAST)
1940  {
1941  //Get SO_BROADCAST option
1942  ret = socketGetSoBroadcastOption(sock, optval, optlen);
1943  }
1944  else if(optname == SO_SNDTIMEO)
1945  {
1946  //Get SO_SNDTIMEO option
1947  ret = socketGetSoSndTimeoOption(sock, optval, optlen);
1948  }
1949  else if(optname == SO_RCVTIMEO)
1950  {
1951  //Get SO_RCVTIMEO option
1952  ret = socketGetSoRcvTimeoOption(sock, optval, optlen);
1953  }
1954  else if(optname == SO_SNDBUF)
1955  {
1956  //Get SO_SNDBUF option
1957  ret = socketGetSoSndBufOption(sock, optval, optlen);
1958  }
1959  else if(optname == SO_RCVBUF)
1960  {
1961  //Get SO_RCVBUF option
1962  ret = socketGetSoRcvBufOption(sock, optval, optlen);
1963  }
1964  else if(optname == SO_KEEPALIVE)
1965  {
1966  //Get SO_KEEPALIVE option
1967  ret = socketGetSoKeepAliveOption(sock, optval, optlen);
1968  }
1969  else if(optname == SO_ERROR)
1970  {
1971  //Get SO_ERROR option
1972  ret = socketGetSoErrorOption(sock, optval, optlen);
1973  }
1974  else
1975  {
1976  //Unknown option
1978  ret = SOCKET_ERROR;
1979  }
1980  }
1981  else if(level == IPPROTO_IP)
1982  {
1983  //Check option type
1984  if(optname == IP_TOS)
1985  {
1986  //Get IP_TOS option
1987  ret = socketGetIpTosOption(sock, optval, optlen);
1988  }
1989  else if(optname == IP_TTL)
1990  {
1991  //Get IP_TTL option
1992  ret = socketGetIpTtlOption(sock, optval, optlen);
1993  }
1994  else if(optname == IP_MULTICAST_TTL)
1995  {
1996  //Get IP_MULTICAST_TTL option
1997  ret = socketGetIpMulticastTtlOption(sock, optval, optlen);
1998  }
1999  else if(optname == IP_MULTICAST_LOOP)
2000  {
2001  //Get IP_MULTICAST_LOOP option
2002  ret = socketGetIpMulticastLoopOption(sock, optval, optlen);
2003  }
2004  else if(optname == IP_PKTINFO)
2005  {
2006  //Get IP_PKTINFO option
2007  ret = socketGetIpPktInfoOption(sock, optval, optlen);
2008  }
2009  else if(optname == IP_RECVTOS)
2010  {
2011  //Get IP_RECVTOS option
2012  ret = socketGetIpRecvTosOption(sock, optval, optlen);
2013  }
2014  else if(optname == IP_RECVTTL)
2015  {
2016  //Get IP_RECVTTL option
2017  ret = socketGetIpRecvTtlOption(sock, optval, optlen);
2018  }
2019  else
2020  {
2021  //Unknown option
2023  ret = SOCKET_ERROR;
2024  }
2025  }
2026  else if(level == IPPROTO_IPV6)
2027  {
2028  //Check option type
2029  if(optname == IPV6_TCLASS)
2030  {
2031  //Get IPV6_TCLASS option
2032  ret = socketGetIpv6TrafficClassOption(sock, optval, optlen);
2033  }
2034  else if(optname == IPV6_UNICAST_HOPS)
2035  {
2036  //Get IPV6_UNICAST_HOPS option
2037  ret = socketGetIpv6UnicastHopsOption(sock, optval, optlen);
2038  }
2039  else if(optname == IPV6_MULTICAST_HOPS)
2040  {
2041  //Get IPV6_MULTICAST_HOPS option
2042  ret = socketGetIpv6MulticastHopsOption(sock, optval, optlen);
2043  }
2044  else if(optname == IPV6_MULTICAST_LOOP)
2045  {
2046  //Get IPV6_MULTICAST_LOOP option
2047  ret = socketGetIpv6MulticastLoopOption(sock, optval, optlen);
2048  }
2049  else if(optname == IPV6_V6ONLY)
2050  {
2051  //Get IPV6_V6ONLY option
2052  ret = socketGetIpv6OnlyOption(sock, optval, optlen);
2053  }
2054  else if(optname == IPV6_PKTINFO)
2055  {
2056  //Get IPV6_PKTINFO option
2057  ret = socketGetIpv6PktInfoOption(sock, optval, optlen);
2058  }
2059  else if(optname == IPV6_RECVTCLASS)
2060  {
2061  //Get IPV6_RECVTCLASS option
2062  ret = socketGetIpv6RecvTrafficClassOption(sock, optval, optlen);
2063  }
2064  else if(optname == IPV6_RECVHOPLIMIT)
2065  {
2066  //Get IPV6_RECVHOPLIMIT option
2067  ret = socketGetIpv6RecvHopLimitOption(sock, optval, optlen);
2068  }
2069  else
2070  {
2071  //Unknown option
2073  ret = SOCKET_ERROR;
2074  }
2075  }
2076  else if(level == IPPROTO_TCP)
2077  {
2078  //Check option type
2079  if(optname == TCP_NODELAY)
2080  {
2081  //Get TCP_NODELAY option
2082  ret = socketGetTcpNoDelayOption(sock, optval, optlen);
2083  }
2084  else if(optname == TCP_MAXSEG)
2085  {
2086  //Get TCP_MAXSEG option
2087  ret = socketGetTcpMaxSegOption(sock, optval, optlen);
2088  }
2089  else if(optname == TCP_KEEPIDLE)
2090  {
2091  //Get TCP_KEEPIDLE option
2092  ret = socketGetTcpKeepIdleOption(sock, optval, optlen);
2093  }
2094  else if(optname == TCP_KEEPINTVL)
2095  {
2096  //Get TCP_KEEPINTVL option
2097  ret = socketGetTcpKeepIntvlOption(sock, optval, optlen);
2098  }
2099  else if(optname == TCP_KEEPCNT)
2100  {
2101  //Get TCP_KEEPCNT option
2102  ret = socketGetTcpKeepCntOption(sock, optval, optlen);
2103  }
2104  else
2105  {
2106  //Unknown option
2108  ret = SOCKET_ERROR;
2109  }
2110  }
2111  else
2112  {
2113  //The specified level is not valid
2114  socketSetErrnoCode(sock, EINVAL);
2115  ret = SOCKET_ERROR;
2116  }
2117  }
2118  else
2119  {
2120  //The option is not valid
2121  socketSetErrnoCode(sock, EFAULT);
2122  ret = SOCKET_ERROR;
2123  }
2124 
2125  //Release exclusive access
2127 
2128  //return status code
2129  return ret;
2130 }
2131 
2132 
2133 /**
2134  * @brief Control the I/O mode of a socket
2135  * @param[in] s Descriptor that identifies a socket
2136  * @param[in] cmd A command to perform on the socket
2137  * @param[in,out] arg A pointer to a parameter
2138  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
2139  * Otherwise, it returns SOCKET_ERROR
2140  **/
2141 
2142 int_t ioctlsocket(int_t s, uint32_t cmd, void *arg)
2143 {
2144  int_t ret;
2145  uint_t *val;
2146  Socket *sock;
2147 
2148  //Make sure the socket descriptor is valid
2149  if(s < 0 || s >= SOCKET_MAX_COUNT)
2150  {
2151  return SOCKET_ERROR;
2152  }
2153 
2154  //Point to the socket structure
2155  sock = &socketTable[s];
2156 
2157  //Get exclusive access
2159 
2160  //Make sure the parameter is valid
2161  if(arg != NULL)
2162  {
2163  //Check command type
2164  switch(cmd)
2165  {
2166  //Enable or disable non-blocking mode
2167  case FIONBIO:
2168  //Cast the parameter to the relevant type
2169  val = (uint_t *) arg;
2170  //Enable blocking or non-blocking operation
2171  sock->timeout = (*val != 0) ? 0 : INFINITE_DELAY;
2172  //Successful processing
2173  ret = SOCKET_SUCCESS;
2174  break;
2175 
2176 #if (TCP_SUPPORT == ENABLED)
2177  //Get the number of bytes that are immediately available for reading
2178  case FIONREAD:
2179  //Cast the parameter to the relevant type
2180  val = (uint_t *) arg;
2181  //Return the actual value
2182  *val = sock->rcvUser;
2183  //Successful processing
2184  ret = SOCKET_SUCCESS;
2185  break;
2186 
2187  //Get the number of bytes written to the send queue but not yet
2188  //acknowledged by the other side of the connection
2189  case FIONWRITE:
2190  //Cast the parameter to the relevant type
2191  val = (uint_t *) arg;
2192  //Return the actual value
2193  *val = sock->sndUser + sock->sndNxt - sock->sndUna;
2194  //Successful processing
2195  ret = SOCKET_SUCCESS;
2196  break;
2197 
2198  //Get the free space in the send queue
2199  case FIONSPACE:
2200  //Cast the parameter to the relevant type
2201  val = (uint_t *) arg;
2202  //Return the actual value
2203  *val = sock->txBufferSize - (sock->sndUser + sock->sndNxt -
2204  sock->sndUna);
2205  //Successful processing
2206  ret = SOCKET_SUCCESS;
2207  break;
2208 #endif
2209 
2210  //Unknown command?
2211  default:
2212  //Report an error
2213  socketSetErrnoCode(sock, EINVAL);
2214  ret = SOCKET_ERROR;
2215  break;
2216  }
2217  }
2218  else
2219  {
2220  //The parameter is not valid
2221  socketSetErrnoCode(sock, EFAULT);
2222  ret = SOCKET_ERROR;
2223  }
2224 
2225  //Release exclusive access
2227 
2228  //return status code
2229  return ret;
2230 }
2231 
2232 
2233 /**
2234  * @brief Perform specific operation
2235  * @param[in] s Descriptor that identifies a socket
2236  * @param[in] cmd A command to perform on the socket
2237  * @param[in,out] arg A pointer to a parameter
2238  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
2239  * Otherwise, it returns SOCKET_ERROR
2240  **/
2241 
2242 int_t fcntl(int_t s, int_t cmd, void *arg)
2243 {
2244  int_t ret;
2245  int_t *flags;
2246  Socket *sock;
2247 
2248  //Make sure the socket descriptor is valid
2249  if(s < 0 || s >= SOCKET_MAX_COUNT)
2250  {
2251  return SOCKET_ERROR;
2252  }
2253 
2254  //Point to the socket structure
2255  sock = &socketTable[s];
2256 
2257  //Get exclusive access
2259 
2260  //Make sure the parameter is valid
2261  if(arg != NULL)
2262  {
2263  //Check command type
2264  switch(cmd)
2265  {
2266  //Get the file status flags?
2267  case F_GETFL:
2268  //Cast the parameter to the relevant type
2269  flags = (int_t *) arg;
2270  //Check whether non-blocking mode is currently enabled
2271  *flags = (sock->timeout == 0) ? O_NONBLOCK : 0;
2272  //Successful processing
2273  ret = SOCKET_SUCCESS;
2274  break;
2275 
2276  //Set the file status flags?
2277  case F_SETFL:
2278  //Cast the parameter to the relevant type
2279  flags = (int_t *) arg;
2280  //Enable blocking or non-blocking operation
2281  sock->timeout = (*flags & O_NONBLOCK) ? 0 : INFINITE_DELAY;
2282  //Successful processing
2283  ret = SOCKET_SUCCESS;
2284  break;
2285 
2286  //Unknown command?
2287  default:
2288  //Report an error
2289  socketSetErrnoCode(sock, EINVAL);
2290  ret = SOCKET_ERROR;
2291  break;
2292  }
2293  }
2294  else
2295  {
2296  //Report an error
2297  socketSetErrnoCode(sock, EFAULT);
2298  ret = SOCKET_ERROR;
2299  }
2300 
2301  //Release exclusive access
2303 
2304  //return status code
2305  return ret;
2306 }
2307 
2308 
2309 /**
2310  * @brief The shutdown function disables sends or receives on a socket
2311  * @param[in] s Descriptor that identifies a socket
2312  * @param[in] how A flag that describes what types of operation will no longer be allowed
2313  * @return If no error occurs, shutdown returns SOCKET_SUCCESS
2314  * Otherwise, it returns SOCKET_ERROR
2315  **/
2316 
2318 {
2319  error_t error;
2320  Socket *sock;
2321 
2322  //Make sure the socket descriptor is valid
2323  if(s < 0 || s >= SOCKET_MAX_COUNT)
2324  {
2325  return SOCKET_ERROR;
2326  }
2327 
2328  //Point to the socket structure
2329  sock = &socketTable[s];
2330 
2331  //Shut down socket
2332  error = socketShutdown(sock, how);
2333 
2334  //Any error to report?
2335  if(error)
2336  {
2337  socketTranslateErrorCode(sock, error);
2338  return SOCKET_ERROR;
2339  }
2340 
2341  //Successful processing
2342  return SOCKET_SUCCESS;
2343 }
2344 
2345 
2346 /**
2347  * @brief The closesocket function closes an existing socket
2348  * @param[in] s Descriptor that identifies a socket
2349  * @return If no error occurs, closesocket returns SOCKET_SUCCESS
2350  * Otherwise, it returns SOCKET_ERROR
2351  **/
2352 
2354 {
2355  Socket *sock;
2356 
2357  //Make sure the socket descriptor is valid
2358  if(s < 0 || s >= SOCKET_MAX_COUNT)
2359  {
2360  return SOCKET_ERROR;
2361  }
2362 
2363  //Point to the socket structure
2364  sock = &socketTable[s];
2365 
2366  //Close socket
2367  socketClose(sock);
2368 
2369  //Successful processing
2370  return SOCKET_SUCCESS;
2371 }
2372 
2373 
2374 /**
2375  * @brief Determine the status of one or more sockets
2376  *
2377  * The select function determines the status of one or more sockets,
2378  * waiting if necessary, to perform synchronous I/O
2379  *
2380  * @param[in] nfds Unused parameter included only for compatibility with
2381  * Berkeley socket
2382  * @param[in,out] readfds An optional pointer to a set of sockets to be
2383  * checked for readability
2384  * @param[in,out] writefds An optional pointer to a set of sockets to be
2385  * checked for writability
2386  * @param[in,out] exceptfds An optional pointer to a set of sockets to be
2387  * checked for errors
2388  * @param[in] timeout The maximum time for select to wait. Set the timeout
2389  * parameter to null for blocking operations
2390  * @return The select function returns the total number of socket handles that
2391  * are ready and contained in the fd_set structures, zero if the time limit
2392  * expired, or SOCKET_ERROR if an error occurred
2393  **/
2394 
2395 int_t select(int_t nfds, fd_set *readfds, fd_set *writefds,
2396  fd_set *exceptfds, const struct timeval *timeout)
2397 {
2398  int_t i;
2399  int_t j;
2400  int_t n;
2401  int_t s;
2402  systime_t time;
2403  uint_t eventMask;
2404  uint_t eventFlags;
2405  OsEvent event;
2406  fd_set *fds;
2407 
2408  //Parse all the descriptor sets
2409  for(i = 0; i < 3; i++)
2410  {
2411  //Select the suitable descriptor set
2412  switch(i)
2413  {
2414  case 0:
2415  //Set of sockets to be checked for readability
2416  fds = readfds;
2417  break;
2418  case 1:
2419  //Set of sockets to be checked for writability
2420  fds = writefds;
2421  break;
2422  default:
2423  //Set of sockets to be checked for errors
2424  fds = exceptfds;
2425  break;
2426  }
2427 
2428  //Each descriptor is optional and may be omitted
2429  if(fds != NULL)
2430  {
2431  //Parse the current set of sockets
2432  for(j = 0; j < fds->fd_count; j++)
2433  {
2434  //Invalid socket descriptor?
2435  if(fds->fd_array[j] < 0 || fds->fd_array[j] >= SOCKET_MAX_COUNT)
2436  {
2437  //Report an error
2438  return SOCKET_ERROR;
2439  }
2440  }
2441  }
2442  }
2443 
2444  //Create an event object to get notified of socket events
2445  if(!osCreateEvent(&event))
2446  {
2447  //Failed to create event
2448  return SOCKET_ERROR;
2449  }
2450 
2451  //Parse all the descriptor sets
2452  for(i = 0; i < 3; i++)
2453  {
2454  //Select the suitable descriptor set
2455  switch(i)
2456  {
2457  case 0:
2458  //Set of sockets to be checked for readability
2459  fds = readfds;
2460  eventMask = SOCKET_EVENT_RX_READY;
2461  break;
2462  case 1:
2463  //Set of sockets to be checked for writability
2464  fds = writefds;
2465  eventMask = SOCKET_EVENT_TX_READY;
2466  break;
2467  default:
2468  //Set of sockets to be checked for errors
2469  fds = exceptfds;
2470  eventMask = SOCKET_EVENT_CLOSED;
2471  break;
2472  }
2473 
2474  //Each descriptor is optional and may be omitted
2475  if(fds != NULL)
2476  {
2477  //Parse the current set of sockets
2478  for(j = 0; j < fds->fd_count; j++)
2479  {
2480  //Get the descriptor associated with the current entry
2481  s = fds->fd_array[j];
2482  //Subscribe to the requested events
2483  socketRegisterEvents(&socketTable[s], &event, eventMask);
2484  }
2485  }
2486  }
2487 
2488  //Retrieve timeout value
2489  if(timeout != NULL)
2490  {
2491  time = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
2492  }
2493  else
2494  {
2495  time = INFINITE_DELAY;
2496  }
2497 
2498  //Block the current task until an event occurs
2499  osWaitForEvent(&event, time);
2500 
2501  //Count the number of events in the signaled state
2502  n = 0;
2503 
2504  //Parse all the descriptor sets
2505  for(i = 0; i < 3; i++)
2506  {
2507  //Select the suitable descriptor set
2508  switch(i)
2509  {
2510  case 0:
2511  //Set of sockets to be checked for readability
2512  fds = readfds;
2513  eventMask = SOCKET_EVENT_RX_READY;
2514  break;
2515  case 1:
2516  //Set of sockets to be checked for writability
2517  fds = writefds;
2518  eventMask = SOCKET_EVENT_TX_READY;
2519  break;
2520  default:
2521  //Set of sockets to be checked for errors
2522  fds = exceptfds;
2523  eventMask = SOCKET_EVENT_CLOSED;
2524  break;
2525  }
2526 
2527  //Each descriptor is optional and may be omitted
2528  if(fds != NULL)
2529  {
2530  //Parse the current set of sockets
2531  for(j = 0; j < fds->fd_count; )
2532  {
2533  //Get the descriptor associated with the current entry
2534  s = fds->fd_array[j];
2535  //Retrieve event flags for the current socket
2536  eventFlags = socketGetEvents(&socketTable[s]);
2537  //Unsubscribe previously registered events
2539 
2540  //Event flag is set?
2541  if(eventFlags & eventMask)
2542  {
2543  //Track the number of events in the signaled state
2544  n++;
2545  //Jump to the next socket descriptor
2546  j++;
2547  }
2548  else
2549  {
2550  //Remove descriptor from the current set
2551  socketFdClr(fds, s);
2552  }
2553  }
2554  }
2555  }
2556 
2557  //Delete event object
2558  osDeleteEvent(&event);
2559  //Return the number of events in the signaled state
2560  return n;
2561 }
2562 
2563 
2564 /**
2565  * @brief Get system host name
2566  * @param[out] name Output buffer where to store the system host name
2567  * @param[in] len Length of the buffer, in bytes
2568  * @return On success, zero is returned. On error, -1 is returned
2569  **/
2570 
2572 {
2573  size_t n;
2574  NetInterface *interface;
2575 
2576  //Check parameter
2577  if(name == NULL)
2578  {
2579  //Report an error
2581  return -1;
2582  }
2583 
2584  //Select the default network interface
2585  interface = netGetDefaultInterface();
2586 
2587  //Retrieve the length of the host name
2588  n = osStrlen(interface->hostname);
2589 
2590  //Make sure the buffer is large enough to hold the string
2591  if(len <= n)
2592  {
2593  //Report an error
2595  return -1;
2596  }
2597 
2598  //Copy the host name
2599  osStrcpy(name, interface->hostname);
2600 
2601  //Successful processing
2602  return 0;
2603 }
2604 
2605 
2606 /**
2607  * @brief Host name resolution
2608  * @param[in] name Name of the host to resolve
2609  * @return Pointer to the hostent structure or a NULL if an error occurs
2610  **/
2611 
2613 {
2614  int_t herrno;
2615  static HOSTENT result;
2616 
2617  //The hostent structure returned by the function resides in static
2618  //memory area
2619  return gethostbyname_r(name, &result, NULL, 0, &herrno);
2620 }
2621 
2622 
2623 /**
2624  * @brief Host name resolution (reentrant version)
2625  * @param[in] name Name of the host to resolve
2626  * @param[in] result Pointer to a hostent structure where the function can
2627  * store the host entry
2628  * @param[out] buf Pointer to a temporary work buffer
2629  * @param[in] buflen Length of the temporary work buffer
2630  * @param[out] h_errnop Pointer to a location where the function can store an
2631  * h_errno value if an error occurs
2632  * @return Pointer to the hostent structure or a NULL if an error occurs
2633  **/
2634 
2635 struct hostent *gethostbyname_r(const char_t *name, struct hostent *result,
2636  char_t *buf, size_t buflen, int_t *h_errnop)
2637 {
2638  error_t error;
2639  IpAddr ipAddr;
2640 
2641  //Check input parameters
2642  if(name == NULL || result == NULL)
2643  {
2644  //Report an error
2645  *h_errnop = NO_RECOVERY;
2646  return NULL;
2647  }
2648 
2649  //Resolve host address
2650  error = getHostByName(NULL, name, &ipAddr, 0);
2651  //Address resolution failed?
2652  if(error)
2653  {
2654  //Report an error
2655  *h_errnop = HOST_NOT_FOUND;
2656  return NULL;
2657  }
2658 
2659 #if (IPV4_SUPPORT == ENABLED)
2660  //IPv4 address?
2661  if(ipAddr.length == sizeof(Ipv4Addr))
2662  {
2663  //Set address family
2664  result->h_addrtype = AF_INET;
2665  result->h_length = sizeof(Ipv4Addr);
2666 
2667  //Copy IPv4 address
2668  ipv4CopyAddr(result->h_addr, &ipAddr.ipv4Addr);
2669  }
2670  else
2671 #endif
2672 #if (IPV6_SUPPORT == ENABLED)
2673  //IPv6 address?
2674  if(ipAddr.length == sizeof(Ipv6Addr))
2675  {
2676  //Set address family
2677  result->h_addrtype = AF_INET6;
2678  result->h_length = sizeof(Ipv6Addr);
2679 
2680  //Copy IPv6 address
2681  ipv6CopyAddr(result->h_addr, &ipAddr.ipv6Addr);
2682  }
2683  else
2684 #endif
2685  //Invalid address?
2686  {
2687  //Report an error
2688  *h_errnop = NO_ADDRESS;
2689  return NULL;
2690  }
2691 
2692  //Successful host name resolution
2693  *h_errnop = NETDB_SUCCESS;
2694 
2695  //Return a pointer to the hostent structure
2696  return result;
2697 }
2698 
2699 
2700 /**
2701  * @brief Convert host and service names to socket address
2702  * @param[in] node Host name or numerical network address
2703  * @param[in] service Service name or decimal number
2704  * @param[in] hints Criteria for selecting the socket address structures
2705  * @param[out] res Dynamically allocated list of socket address structures
2706  * @return On success, zero is returned. On error, a non-zero value is returned
2707  **/
2708 
2709 int_t getaddrinfo(const char_t *node, const char_t *service,
2710  const struct addrinfo *hints, struct addrinfo **res)
2711 {
2712  error_t error;
2713  size_t n;
2714  char_t *p;
2715  uint_t flags;
2716  uint32_t port;
2717  IpAddr ipAddr;
2718  ADDRINFO h;
2719  ADDRINFO *ai;
2720 
2721  //Check whether both node and service name are NULL
2722  if(node == NULL && service == NULL)
2723  return EAI_NONAME;
2724 
2725  //The hints argument is optional
2726  if(hints != NULL)
2727  {
2728  //If hints is not NULL, it points to an addrinfo structure that specifies
2729  //criteria that limit the set of socket addresses that will be returned
2730  h = *hints;
2731  }
2732  else
2733  {
2734  //If hints is NULL, then default criteria are used
2735  osMemset(&h, 0, sizeof(ADDRINFO));
2736  h.ai_family = AF_UNSPEC;
2737  h.ai_socktype = 0;
2738  h.ai_protocol = 0;
2739  h.ai_flags = 0;
2740  }
2741 
2742  //The user may provide a hint to choose between IPv4 and IPv6
2743  if(h.ai_family == AF_UNSPEC)
2744  {
2745  //The value AF_UNSPEC indicates that function should return socket
2746  //addresses for any address family (either IPv4 or IPv6)
2747  flags = 0;
2748  }
2749 #if (IPV4_SUPPORT == ENABLED)
2750  else if(h.ai_family == AF_INET)
2751  {
2752  //The value AF_INET indicates that the function should return an IPv4
2753  //address
2755  }
2756 #endif
2757 #if (IPV6_SUPPORT == ENABLED)
2758  else if(h.ai_family == AF_INET6)
2759  {
2760  //The value AF_INET6 indicates that the function should return an IPv6
2761  //address
2763  }
2764 #endif
2765  else
2766  {
2767  //The requested address family is not supported
2768  return EAI_FAMILY;
2769  }
2770 
2771  //Check whether a host name or numerical network address is specified
2772  if(node != NULL)
2773  {
2774  //If the AI_NUMERICHOST flag, then node must be a numerical network
2775  //address
2776  if((h.ai_flags & AI_NUMERICHOST) != 0)
2777  {
2778  //Convert the string representation to a binary IP address
2779  error = ipStringToAddr(node, &ipAddr);
2780  }
2781  else
2782  {
2783  //Resolve host address
2784  error = getHostByName(NULL, node, &ipAddr, flags);
2785  }
2786 
2787  //Check status code
2788  if(error == NO_ERROR)
2789  {
2790  //Successful host name resolution
2791  }
2792  else if(error == ERROR_IN_PROGRESS)
2793  {
2794  //Host name resolution is in progress
2795  return EAI_AGAIN;
2796  }
2797  else
2798  {
2799  //Permanent failure indication
2800  return EAI_FAIL;
2801  }
2802  }
2803  else
2804  {
2805  //Check flags
2806  if((h.ai_flags & AI_PASSIVE) != 0)
2807  {
2808 #if (IPV4_SUPPORT == ENABLED)
2809  //IPv4 address family?
2810  if(h.ai_family == AF_INET || h.ai_family == AF_UNSPEC)
2811  {
2812  ipAddr.length = sizeof(Ipv4Addr);
2813  ipAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR;
2814  }
2815  else
2816 #endif
2817 #if (IPV6_SUPPORT == ENABLED)
2818  //IPv6 address family?
2819  if(h.ai_family == AF_INET6 || h.ai_family == AF_UNSPEC)
2820  {
2821  ipAddr.length = sizeof(Ipv6Addr);
2822  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
2823  }
2824  else
2825 #endif
2826  //Unknown address family?
2827  {
2828  //Report an error
2829  return EAI_ADDRFAMILY;
2830  }
2831  }
2832  else
2833  {
2834  //Invalid flags
2835  return EAI_BADFLAGS;
2836  }
2837  }
2838 
2839  //Only service names containing a numeric port number are supported
2840  port = osStrtoul(service, &p, 10);
2841  //Invalid service name?
2842  if(*p != '\0')
2843  {
2844  //The requested service is not available
2845  return EAI_SERVICE;
2846  }
2847 
2848 #if (IPV4_SUPPORT == ENABLED)
2849  //IPv4 address?
2850  if(ipAddr.length == sizeof(Ipv4Addr))
2851  {
2852  //Select the relevant socket family
2853  h.ai_family = AF_INET;
2854  //Get the length of the corresponding socket address
2855  n = sizeof(SOCKADDR_IN);
2856  }
2857  else
2858 #endif
2859 #if (IPV6_SUPPORT == ENABLED)
2860  //IPv6 address?
2861  if(ipAddr.length == sizeof(Ipv6Addr))
2862  {
2863  //Select the relevant socket family
2864  h.ai_family = AF_INET6;
2865  //Get the length of the corresponding socket address
2866  n = sizeof(SOCKADDR_IN6);
2867  }
2868  else
2869 #endif
2870  //Unknown address?
2871  {
2872  //Report an error
2873  return EAI_ADDRFAMILY;
2874  }
2875 
2876  //Allocate a memory buffer to hold the address information structure
2877  ai = osAllocMem(sizeof(ADDRINFO) + n);
2878  //Failed to allocate memory?
2879  if(ai == NULL)
2880  {
2881  //Out of memory
2882  return EAI_MEMORY;
2883  }
2884 
2885  //Initialize address information structure
2886  osMemset(ai, 0, sizeof(ADDRINFO) + n);
2887  ai->ai_family = h.ai_family;
2888  ai->ai_socktype = h.ai_socktype;
2889  ai->ai_protocol = h.ai_protocol;
2890  ai->ai_addr = (SOCKADDR *) ((uint8_t *) ai + sizeof(ADDRINFO));
2891  ai->ai_addrlen = n;
2892  ai->ai_next = NULL;
2893 
2894 #if (IPV4_SUPPORT == ENABLED)
2895  //IPv4 address?
2896  if(ipAddr.length == sizeof(Ipv4Addr))
2897  {
2898  //Point to the IPv4 address information
2899  SOCKADDR_IN *sa = (SOCKADDR_IN *) ai->ai_addr;
2900 
2901  //Set address family and port number
2902  sa->sin_family = AF_INET;
2903  sa->sin_port = htons(port);
2904 
2905  //Copy IPv4 address
2906  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
2907  }
2908  else
2909 #endif
2910 #if (IPV6_SUPPORT == ENABLED)
2911  //IPv6 address?
2912  if(ipAddr.length == sizeof(Ipv6Addr))
2913  {
2914  //Point to the IPv6 address information
2915  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) ai->ai_addr;
2916 
2917  //Set address family and port number
2918  sa->sin6_family = AF_INET6;
2919  sa->sin6_port = htons(port);
2920  sa->sin6_flowinfo = 0;
2921  sa->sin6_scope_id = 0;
2922 
2923  //Copy IPv6 address
2924  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
2925  }
2926  else
2927 #endif
2928  //Unknown address?
2929  {
2930  //Clean up side effects
2931  osFreeMem(ai);
2932  //Report an error
2933  return EAI_ADDRFAMILY;
2934  }
2935 
2936  //Return a pointer to the allocated address information
2937  *res = ai;
2938 
2939  //Successful processing
2940  return 0;
2941 }
2942 
2943 
2944 /**
2945  * @brief Free socket address structures
2946  * @param[in] res Dynamically allocated list of socket address structures
2947  **/
2948 
2950 {
2951  ADDRINFO *next;
2952 
2953  //Free the list of socket address structures
2954  while(res != NULL)
2955  {
2956  //Get next entry
2957  next = res->ai_next;
2958  //Free current socket address structure
2959  osFreeMem(res);
2960  //Point to the next entry
2961  res = next;
2962  }
2963 }
2964 
2965 
2966 /**
2967  * @brief Convert a socket address to a corresponding host and service
2968  * @param[in] addr Generic socket address structure
2969  * @param[in] addrlen Length in bytes of the address
2970  * @param[out] host Output buffer where to store the host name
2971  * @param[in] hostlen Length of the host name buffer, in bytes
2972  * @param[out] serv Output buffer where to store the service name
2973  * @param[in] servlen Length of the service name buffer, in bytes
2974  * @param[in] flags Set of flags that influences the behavior of this function
2975  * @return On success, zero is returned. On error, a non-zero value is returned
2976  **/
2977 
2978 int_t getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
2979  char_t *host, size_t hostlen, char_t *serv, size_t servlen, int flags)
2980 {
2981  uint16_t port;
2982 
2983  //At least one of hostname or service name must be requested
2984  if(host == NULL && serv == NULL)
2985  return EAI_NONAME;
2986 
2987 #if (IPV4_SUPPORT == ENABLED)
2988  //IPv4 address?
2989  if(addr->sa_family == AF_INET &&
2990  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
2991  {
2992  SOCKADDR_IN *sa;
2993  Ipv4Addr ipv4Addr;
2994 
2995  //Point to the IPv4 address information
2996  sa = (SOCKADDR_IN *) addr;
2997 
2998  //The caller can specify that no host name is required
2999  if(host != NULL)
3000  {
3001  //Make sure the buffer is large enough to hold the host name
3002  if(hostlen < 16)
3003  return EAI_OVERFLOW;
3004 
3005  //Copy the binary representation of the IPv4 address
3006  ipv4CopyAddr(&ipv4Addr, &sa->sin_addr.s_addr);
3007  //Convert the IPv4 address to dot-decimal notation
3008  ipv4AddrToString(ipv4Addr, host);
3009  }
3010 
3011  //Retrieve port number
3012  port = ntohs(sa->sin_port);
3013  }
3014  else
3015 #endif
3016 #if (IPV6_SUPPORT == ENABLED)
3017  //IPv6 address?
3018  if(addr->sa_family == AF_INET6 &&
3019  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
3020  {
3021  SOCKADDR_IN6 *sa;
3022  Ipv6Addr ipv6Addr;
3023 
3024  //Point to the IPv6 address information
3025  sa = (SOCKADDR_IN6 *) addr;
3026 
3027  //The caller can specify that no host name is required
3028  if(host != NULL)
3029  {
3030  //Make sure the buffer is large enough to hold the host name
3031  if(hostlen < 40)
3032  return EAI_OVERFLOW;
3033 
3034  //Copy the binary representation of the IPv6 address
3035  ipv6CopyAddr(&ipv6Addr, sa->sin6_addr.s6_addr);
3036  //Convert the IPv6 address to string representation
3037  ipv6AddrToString(&ipv6Addr, host);
3038  }
3039 
3040  //Retrieve port number
3041  port = ntohs(sa->sin6_port);
3042  }
3043  else
3044 #endif
3045  //Invalid address?
3046  {
3047  //The address family was not recognized, or the address length was
3048  //invalid for the specified family
3049  return EAI_FAMILY;
3050  }
3051 
3052  //The caller can specify that no service name is required
3053  if(serv != NULL)
3054  {
3055  //Make sure the buffer is large enough to hold the service name
3056  if(servlen < 6)
3057  return EAI_OVERFLOW;
3058 
3059  //Convert the port number to string representation
3060  osSprintf(serv, "%" PRIu16, ntohs(port));
3061  }
3062 
3063  //Successful processing
3064  return 0;
3065 }
3066 
3067 
3068 /**
3069  * @brief Convert a dot-decimal string into binary data in network byte order
3070  * @param[in] cp NULL-terminated string representing the IPv4 address
3071  * @return Binary data in network byte order
3072  **/
3073 
3075 {
3076 #if (IPV4_SUPPORT == ENABLED)
3077  error_t error;
3078  Ipv4Addr ipv4Addr;
3079 
3080  //Convert a dot-decimal string to a binary IPv4 address
3081  error = ipv4StringToAddr(cp, &ipv4Addr);
3082 
3083  //Check status code
3084  if(error)
3085  {
3086  //The input is invalid
3087  return INADDR_NONE;
3088  }
3089  else
3090  {
3091  //Return the binary representation
3092  return ipv4Addr;
3093  }
3094 #else
3095  //IPv4 is not implemented
3096  return INADDR_NONE;
3097 #endif
3098 }
3099 
3100 
3101 /**
3102  * @brief Convert a dot-decimal string into binary form
3103  * @param[in] cp NULL-terminated string representing the IPv4 address
3104  * @param[out] inp Binary data in network byte order
3105  * @return The function returns non-zero if the address is valid, zero if not
3106  **/
3107 
3108 int_t inet_aton(const char_t *cp, struct in_addr *inp)
3109 {
3110 #if (IPV4_SUPPORT == ENABLED)
3111  error_t error;
3112  Ipv4Addr ipv4Addr;
3113 
3114  //Convert a dot-decimal string to a binary IPv4 address
3115  error = ipv4StringToAddr(cp, &ipv4Addr);
3116 
3117  //Check status code
3118  if(error)
3119  {
3120  //The input is invalid
3121  return 0;
3122  }
3123  else
3124  {
3125  //Copy the binary representation of the IPv4 address
3126  inp->s_addr = ipv4Addr;
3127  //The conversion succeeded
3128  return 1;
3129  }
3130 #else
3131  //IPv4 is not implemented
3132  return 0;
3133 #endif
3134 }
3135 
3136 
3137 /**
3138  * @brief Convert a binary IPv4 address to dot-decimal notation
3139  * @param[in] in Binary representation of the IPv4 address
3140  * @return Pointer to the formatted string
3141  **/
3142 
3143 const char_t *inet_ntoa(struct in_addr in)
3144 {
3145  static char_t buf[16];
3146 
3147  //The string returned by the function resides in static memory area
3148  return inet_ntoa_r(in, buf, sizeof(buf));
3149 }
3150 
3151 
3152 /**
3153  * @brief Convert a binary IPv4 address to dot-decimal notation (reentrant version)
3154  * @param[in] in Binary representation of the IPv4 address
3155  * @param[out] buf Pointer to the buffer where to format the string
3156  * @param[in] buflen Number of bytes available in the buffer
3157  * @return Pointer to the formatted string
3158  **/
3159 
3160 const char_t *inet_ntoa_r(struct in_addr in, char_t *buf, socklen_t buflen)
3161 {
3162  //Properly terminate the string
3163  buf[0] = '\0';
3164 
3165 #if (IPV4_SUPPORT == ENABLED)
3166  //Check the length of the buffer
3167  if(buflen >= 16)
3168  {
3169  //Convert the binary IPv4 address to dot-decimal notation
3170  ipv4AddrToString(in.s_addr, buf);
3171  }
3172 #endif
3173 
3174  //Return a pointer to the formatted string
3175  return buf;
3176 }
3177 
3178 
3179 /**
3180  * @brief Convert an IPv4 or IPv6 address from text to binary form
3181  * @param[in] af Address family
3182  * @param[in] src NULL-terminated string representing the IP address
3183  * @param[out] dst Binary representation of the IP address
3184  * @return The function returns 1 on success. 0 is returned if the address
3185  * is not valid. If the address family is not valid, -1 is returned
3186  **/
3187 
3188 int_t inet_pton(int_t af, const char_t *src, void *dst)
3189 {
3190  error_t error;
3191 
3192 #if (IPV4_SUPPORT == ENABLED)
3193  //IPv4 address?
3194  if(af == AF_INET)
3195  {
3196  Ipv4Addr ipv4Addr;
3197 
3198  //Convert the IPv4 address from text to binary form
3199  error = ipv4StringToAddr(src, &ipv4Addr);
3200 
3201  //Check status code
3202  if(error)
3203  {
3204  //The input is invalid
3205  return 0;
3206  }
3207  else
3208  {
3209  //Copy the binary representation of the IPv4 address
3210  ipv4CopyAddr(dst, &ipv4Addr);
3211  //The conversion succeeded
3212  return 1;
3213  }
3214  }
3215  else
3216 #endif
3217 #if (IPV6_SUPPORT == ENABLED)
3218  //IPv6 address?
3219  if(af == AF_INET6)
3220  {
3221  Ipv6Addr ipv6Addr;
3222 
3223  //Convert the IPv6 address from text to binary form
3224  error = ipv6StringToAddr(src, &ipv6Addr);
3225 
3226  //Check status code
3227  if(error)
3228  {
3229  //The input is invalid
3230  return 0;
3231  }
3232  else
3233  {
3234  //Copy the binary representation of the IPv6 address
3235  ipv6CopyAddr(dst, &ipv6Addr);
3236  //The conversion succeeded
3237  return 1;
3238  }
3239  }
3240  else
3241 #endif
3242  //Invalid address family?
3243  {
3244  //Report an error
3245  return -1;
3246  }
3247 }
3248 
3249 
3250 /**
3251  * @brief Convert an IPv4 or IPv6 address from binary to text
3252  * @param[in] af Address family
3253  * @param[in] src Binary representation of the IP address
3254  * @param[out] dst NULL-terminated string representing the IP address
3255  * @param[in] size Number of bytes available in the buffer
3256  * @return On success, the function returns a pointer to the formatted string.
3257  * NULL is returned if there was an error
3258  **/
3259 
3260 const char_t *inet_ntop(int_t af, const void *src, char_t *dst, socklen_t size)
3261 {
3262 #if (IPV4_SUPPORT == ENABLED)
3263  //IPv4 address?
3264  if(af == AF_INET && size >= INET_ADDRSTRLEN)
3265  {
3266  Ipv4Addr ipv4Addr;
3267 
3268  //Copy the binary representation of the IPv4 address
3269  ipv4CopyAddr(&ipv4Addr, src);
3270 
3271  //Convert the IPv4 address to dot-decimal notation
3272  return ipv4AddrToString(ipv4Addr, dst);
3273  }
3274  else
3275 #endif
3276 #if (IPV6_SUPPORT == ENABLED)
3277  //IPv6 address?
3278  if(af == AF_INET6 && size >= INET6_ADDRSTRLEN)
3279  {
3280  Ipv6Addr ipv6Addr;
3281 
3282  //Copy the binary representation of the IPv6 address
3283  ipv6CopyAddr(&ipv6Addr, src);
3284 
3285  //Convert the IPv6 address to string representation
3286  return ipv6AddrToString(&ipv6Addr, dst);
3287  }
3288  else
3289 #endif
3290  //Invalid address family?
3291  {
3292  //Report an error
3293  return NULL;
3294  }
3295 }
3296 
3297 #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:941
const struct in6_addr in6addr_any
Definition: bsd_socket.c:49
#define F_GETFL
Definition: bsd_socket.h:197
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:2364
struct hostent * gethostbyname(const char_t *name)
Host name resolution.
Definition: bsd_socket.c:2612
#define htons(value)
Definition: cpu_endian.h:413
struct sockaddr * ai_addr
Definition: bsd_socket.h:486
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:279
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:3188
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:777
#define AF_INET6
Definition: bsd_socket.h:80
Ancillary data header.
Definition: bsd_socket.h:423
uint32_t in_addr_t
IPv4 address.
Definition: bsd_socket.h:286
#define IPV6_HOPLIMIT
Definition: bsd_socket.h:174
#define CMSG_DATA(cmsg)
Definition: bsd_socket.h:512
@ SOCKET_OPTION_IPV4_RECV_TOS
Definition: socket.h:186
int_t socketGetTcpKeepIntvlOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_KEEPINTVL option.
int_t socketSetSoRcvBufOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_RCVBUF 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:246
int_t recvmsg(int_t s, struct msghdr *msg, int_t flags)
Receive a message.
Definition: bsd_socket.c:1095
@ SOCKET_FLAG_WAIT_ALL
Definition: socket.h:128
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:1652
Helper function for BSD socket API.
#define EAI_BADFLAGS
Definition: bsd_socket.h:226
#define IP_TOS
Definition: bsd_socket.h:152
uint8_t protocol
Definition: ipv4.h:294
#define EINPROGRESS
Definition: bsd_socket.h:243
int_t socketGetSoRcvBufOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_RCVBUF option.
uint32_t sin6_flowinfo
Definition: bsd_socket.h:352
signed int int_t
Definition: compiler_port.h:49
#define netMutex
Definition: net_legacy.h:195
int_t socketGetIpv6RecvHopLimitOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_RECVHOPLIMIT option.
void * iov_base
Definition: bsd_socket.h:397
int_t socketSetIpv6TrafficClassOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_TCLASS option.
IP network address.
Definition: ip.h:72
int_t socketSetTcpMaxSegOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_MAXSEG option.
uint16_t sin_family
Definition: bsd_socket.h:327
size_t iov_len
Definition: bsd_socket.h:398
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:3143
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:2317
#define ETIMEDOUT
Definition: bsd_socket.h:244
uint8_t p
Definition: ndp.h:298
#define SOCKET_ERROR
Definition: bsd_socket.h:221
@ SOCKET_FLAG_DONT_ROUTE
Definition: socket.h:127
#define NO_RECOVERY
Definition: bsd_socket.h:257
uint8_t message[]
Definition: chap.h:152
int_t recv(int_t s, void *data, size_t size, int_t flags)
Receive data from a connected socket.
Definition: bsd_socket.c:897
#define EAI_ADDRFAMILY
Definition: bsd_socket.h:224
Set of sockets.
Definition: bsd_socket.h:457
#define SO_RCVTIMEO
Definition: bsd_socket.h:145
uint8_t data[]
Definition: ethernet.h:220
Message and ancillary data.
Definition: socket.h:228
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:1512
Event object.
#define IP_RECVTOS
Definition: bsd_socket.h:157
socklen_t msg_namelen
Definition: bsd_socket.h:409
struct in6_addr sin6_addr
Definition: bsd_socket.h:353
#define AF_INET
Definition: bsd_socket.h:79
void * msg_control
Definition: bsd_socket.h:412
#define INADDR_NONE
Definition: bsd_socket.h:261
#define IP_MULTICAST_LOOP
Definition: bsd_socket.h:160
Ipv6Addr
Definition: ipv6.h:249
int_t gethostname(char_t *name, size_t len)
Get system host name.
Definition: bsd_socket.c:2571
int_t socketGetSoRcvTimeoOption(Socket *socket, struct timeval *optval, socklen_t *optlen)
Get SO_RCVTIMEO option.
struct sockaddr_in6 SOCKADDR_IN6
IPv6 address information.
#define SO_SNDBUF
Definition: bsd_socket.h:142
#define IPV6_UNICAST_HOPS
Definition: bsd_socket.h:165
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:3260
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:120
char_t name[]
#define EAI_FAIL
Definition: bsd_socket.h:227
#define FIONREAD
Definition: bsd_socket.h:192
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:242
#define osStrlen(s)
Definition: os_port.h:167
#define MSG_DONTROUTE
Definition: bsd_socket.h:121
#define IPV4_SUPPORT
Definition: ipv4.h:48
#define IPV6_RECVTCLASS
Definition: bsd_socket.h:175
@ ERROR_END_OF_STREAM
Definition: error.h:210
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:326
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:3160
#define BSD_SOCKET_SET_ERRNO(e)
Definition: bsd_socket.h:50
#define MSG_DONTWAIT
Definition: bsd_socket.h:123
#define EWOULDBLOCK
Definition: bsd_socket.h:240
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
int_t socketGetIpRecvTtlOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IP_RECVTTL option.
int_t cmsg_level
Definition: bsd_socket.h:425
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:180
#define IP_MULTICAST_IF
Definition: bsd_socket.h:158
@ SOCKET_OPTION_IPV6_RECV_TRAFFIC_CLASS
Definition: socket.h:191
IPv6 packet information.
Definition: bsd_socket.h:446
#define IPV6_V6ONLY
Definition: bsd_socket.h:171
void * msg_name
Definition: bsd_socket.h:408
@ SOCKET_FLAG_PEEK
Definition: socket.h:126
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.
uint8_t h_addr[16]
Definition: bsd_socket.h:471
void freeaddrinfo(struct addrinfo *res)
Free socket address structures.
Definition: bsd_socket.c:2949
#define AF_PACKET
Definition: bsd_socket.h:81
@ HOST_TYPE_IPV6
Definition: socket.h:205
#define NO_ADDRESS
Definition: bsd_socket.h:258
int_t socketGetTcpKeepCntOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_KEEPCNT option.
@ SOCKET_OPTION_IPV4_RECV_TTL
Definition: socket.h:187
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:339
__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.
#define EAI_NONAME
Definition: bsd_socket.h:231
@ ERROR_IN_PROGRESS
Definition: error.h:213
error_t socketSendMsg(Socket *socket, const SocketMsg *message, uint_t flags)
Send a message to a connectionless socket.
Definition: socket.c:1089
#define TCP_KEEPCNT
Definition: bsd_socket.h:183
#define TCP_NODELAY
Definition: bsd_socket.h:179
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:52
int32_t tv_sec
Definition: bsd_socket.h:500
uint8_t h
Definition: ndp.h:300
int ipi_ifindex
Definition: bsd_socket.h:436
void socketTranslateErrorCode(Socket *socket, error_t errorCode)
Translate error code.
int_t fd_count
Definition: bsd_socket.h:458
#define IPPROTO_IP
Definition: bsd_socket.h:95
#define AI_NUMERICHOST
Definition: bsd_socket.h:206
Socket address.
Definition: bsd_socket.h:294
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:484
IPv6 address information.
Definition: bsd_socket.h:349
#define osSprintf(dest,...)
Definition: os_port.h:233
#define AI_PASSIVE
Definition: bsd_socket.h:204
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:1147
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:316
@ SOCKET_OPTION_IPV6_RECV_HOP_LIMIT
Definition: socket.h:192
uint16_t h_length
Definition: bsd_socket.h:470
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
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:165
#define EAI_SERVICE
Definition: bsd_socket.h:232
#define EAI_OVERFLOW
Definition: bsd_socket.h:235
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.
int_t getsockname(int_t s, struct sockaddr *addr, socklen_t *addrlen)
Retrieves the local name for a socket.
Definition: bsd_socket.c:1456
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:2635
void osDeleteEvent(OsEvent *event)
Delete an event object.
#define NetInterface
Definition: net.h:36
int ipi6_ifindex
Definition: bsd_socket.h:447
#define ENOTCONN
Definition: bsd_socket.h:249
#define SO_REUSEADDR
Definition: bsd_socket.h:137
#define SO_BROADCAST
Definition: bsd_socket.h:140
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:414
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:1169
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:1349
int_t socketSetIpTtlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_TTL option.
#define IP_MULTICAST_TTL
Definition: bsd_socket.h:159
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:1712
int_t msg_iovlen
Definition: bsd_socket.h:411
#define SOCKET_SUCCESS
Definition: bsd_socket.h:220
#define IP_PKTINFO
Definition: bsd_socket.h:155
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:407
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:806
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:65
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:1475
#define IPV6_MULTICAST_HOPS
Definition: bsd_socket.h:167
int_t fd_array[FD_SETSIZE]
Definition: bsd_socket.h:459
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:366
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:124
#define SO_SNDTIMEO
Definition: bsd_socket.h:144
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:3074
int_t socketSetIpDropMembershipOption(Socket *socket, const struct ip_mreq *optval, socklen_t optlen)
Set IP_DROP_MEMBERSHIP option.
uint16_t sin6_family
Definition: bsd_socket.h:350
#define ENAMETOOLONG
Definition: bsd_socket.h:245
int32_t tv_usec
Definition: bsd_socket.h:501
int_t socketSetIpv6RecvHopLimitOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IPV6_RECVHOPLIMIT option.
socklen_t ai_addrlen
Definition: bsd_socket.h:485
@ HOST_TYPE_IPV4
Definition: socket.h:204
struct addrinfo ADDRINFO
Information about address of a service provider.
#define HOST_NOT_FOUND
Definition: bsd_socket.h:255
uint32_t sin6_scope_id
Definition: bsd_socket.h:354
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:49
#define ENABLED
Definition: os_port.h:37
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.
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:969
#define FIONSPACE
Definition: bsd_socket.h:194
#define MSG_CTRUNC
Definition: bsd_socket.h:122
uint8_t type
Definition: coap_common.h:174
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:907
int_t ioctlsocket(int_t s, uint32_t cmd, void *arg)
Control the I/O mode of a socket.
Definition: bsd_socket.c:2142
int_t socketGetIpv6TrafficClassOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get IPV6_TCLASS option.
#define IP_RECVTTL
Definition: bsd_socket.h:156
uint32_t systime_t
System time.
uint16_t port
Definition: dns_common.h:265
#define ntohs(value)
Definition: cpu_endian.h:421
int_t socketSetTcpKeepIntvlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set TCP_KEEPINTVL option.
in_addr_t s_addr
Definition: bsd_socket.h:317
#define osStrtoul(s, endptr, base)
Definition: os_port.h:251
uint8_t flags
Definition: tcp.h:349
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:241
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:48
void socketRegisterEvents(Socket *socket, OsEvent *event, uint_t eventMask)
Subscribe to the specified socket events.
Definition: socket_misc.c:197
int_t socketGetSoSndTimeoOption(Socket *socket, struct timeval *optval, socklen_t *optlen)
Get SO_SNDTIMEO option.
struct in_addr ipi_addr
Definition: bsd_socket.h:437
Information about a given host.
Definition: bsd_socket.h:468
#define F_SETFL
Definition: bsd_socket.h:198
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:116
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:2395
#define FIONBIO
Definition: bsd_socket.h:191
Helper functions for sockets.
size_t cmsg_len
Definition: bsd_socket.h:424
#define FIONWRITE
Definition: bsd_socket.h:193
@ SOCKET_FLAG_NO_DELAY
Definition: socket.h:133
@ SOCKET_EVENT_RX_READY
Definition: socket.h:169
uint8_t n
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
#define INET_ADDRSTRLEN
Definition: bsd_socket.h:264
Timeout structure.
Definition: bsd_socket.h:499
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
#define IPV6_MULTICAST_LOOP
Definition: bsd_socket.h:168
struct in6_addr ipi6_addr
Definition: bsd_socket.h:448
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
uint16_t sin_port
Definition: bsd_socket.h:328
int_t socketSetIpv6DropMembershipOption(Socket *socket, const struct ipv6_mreq *optval, socklen_t optlen)
Set IPV6_DROP_MEMBERSHIP option.
uint16_t sin6_port
Definition: bsd_socket.h:351
struct in_addr sin_addr
Definition: bsd_socket.h:329
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:2978
#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:514
int_t socketSetSoBroadcastOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set SO_BROADCAST option.
int_t ai_socktype
Definition: bsd_socket.h:483
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define IPV6_PKTINFO
Definition: bsd_socket.h:172
#define INET6_ADDRSTRLEN
Definition: bsd_socket.h:267
#define SOL_SOCKET
Definition: bsd_socket.h:112
@ SOCKET_OPTION_IPV6_PKT_INFO
Definition: socket.h:190
#define EAI_AGAIN
Definition: bsd_socket.h:225
#define CMSG_LEN(len)
Definition: bsd_socket.h:515
const struct in6_addr in6addr_loopback
Definition: bsd_socket.c:52
#define EAI_FAMILY
Definition: bsd_socket.h:228
#define IPV6_RECVHOPLIMIT
Definition: bsd_socket.h:173
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
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.
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:962
int_t socketGetSoKeepAliveOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get SO_KEEPALIVE option.
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:88
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:1909
#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:1552
int_t socketSetIpMulticastTtlOption(Socket *socket, const int_t *optval, socklen_t optlen)
Set IP_MULTICAST_TTL option.
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:148
uint8_t s
Definition: ndp.h:343
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1530
Ipv4Addr ipAddr
Definition: ipcp.h:103
#define MSG_PEEK
Definition: bsd_socket.h:120
struct iovec * msg_iov
Definition: bsd_socket.h:410
#define NETDB_SUCCESS
Definition: bsd_socket.h:254
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:2213
#define SO_KEEPALIVE
Definition: bsd_socket.h:138
#define IP_ADD_MEMBERSHIP
Definition: bsd_socket.h:161
#define O_NONBLOCK
Definition: bsd_socket.h:201
Ipv4Addr addr
Definition: nbns_common.h:121
#define EAI_MEMORY
Definition: bsd_socket.h:229
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:153
#define IPV6_MULTICAST_IF
Definition: bsd_socket.h:166
int_t cmsg_type
Definition: bsd_socket.h:426
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:482
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:2709
unsigned int uint_t
Definition: compiler_port.h:50
size_t msg_controllen
Definition: bsd_socket.h:413
@ SOCKET_FLAG_DONT_WAIT
Definition: socket.h:129
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:252
#define osMemset(p, value, length)
Definition: os_port.h:137
TCP/IP stack core.
int_t fcntl(int_t s, int_t cmd, void *arg)
Perform specific operation.
Definition: bsd_socket.c:2242
@ SOCKET_EVENT_CLOSED
Definition: socket.h:164
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:1617
#define IPV6_TCLASS
Definition: bsd_socket.h:176
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:3108
#define IPV6_DROP_MEMBERSHIP
Definition: bsd_socket.h:170
int_t socketGetTcpNoDelayOption(Socket *socket, int_t *optval, socklen_t *optlen)
Get TCP_NODELAY option.
#define osStrcpy(s1, s2)
Definition: os_port.h:209
#define TCP_KEEPINTVL
Definition: bsd_socket.h:182
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.
uint16_t next
Definition: ipv4_frag.h:104
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket_misc.c:275
#define TCP_KEEPIDLE
Definition: bsd_socket.h:181
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:480
int_t msg_flags
Definition: bsd_socket.h:414
#define IPV6_ADD_MEMBERSHIP
Definition: bsd_socket.h:169
@ NO_ERROR
Success.
Definition: error.h:44
#define IP_DROP_MEMBERSHIP
Definition: bsd_socket.h:162
Debugging facilities.
@ SOCKET_OPTION_TCP_NO_DELAY
Definition: socket.h:193
uint8_t s6_addr[16]
Definition: bsd_socket.h:340
#define INFINITE_DELAY
Definition: os_port.h:77
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
@ SOCKET_OPTION_IPV4_PKT_INFO
Definition: socket.h:185
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:2353
uint16_t h_addrtype
Definition: bsd_socket.h:469
struct addrinfo * ai_next
Definition: bsd_socket.h:488
IPv4 packet information.
Definition: bsd_socket.h:435
#define SO_ERROR
Definition: bsd_socket.h:146
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:870