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.2.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL BSD_SOCKET_TRACE_LEVEL
33 
34 //Dependencies
35 #include <string.h>
36 #include "core/net.h"
37 #include "core/bsd_socket.h"
38 #include "core/bsd_socket_misc.h"
39 #include "core/socket.h"
40 #include "core/socket_misc.h"
41 #include "debug.h"
42 
43 //Check TCP/IP stack configuration
44 #if (BSD_SOCKET_SUPPORT == ENABLED)
45 
46 //Common IPv6 addresses
47 const struct in6_addr in6addr_any =
48  {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
49 
50 const struct in6_addr in6addr_loopback =
51  {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
52 
53 
54 /**
55  * @brief Create a socket that is bound to a specific transport service provider
56  * @param[in] family Address family
57  * @param[in] type Type specification for the new socket
58  * @param[in] protocol Protocol to be used
59  * @return On success, a file descriptor for the new socket is returned.
60  * On failure, SOCKET_ERROR is returned
61  **/
62 
64 {
65  Socket *sock;
66 
67  //Check address family
68  if(family == AF_INET || family == AF_INET6)
69  {
70  //Create a socket
71  sock = socketOpen(type, protocol);
72  }
73  else if(family == AF_PACKET)
74  {
75  //Create a socket
77  }
78  else
79  {
80  //The address family is not valid
81  return SOCKET_ERROR;
82  }
83 
84  //Failed to create a new socket?
85  if(sock == NULL)
86  {
87  //Report an error
88  return SOCKET_ERROR;
89  }
90 
91  //Return the socket descriptor
92  return sock->descriptor;
93 }
94 
95 
96 /**
97  * @brief Associate a local address with a socket
98  * @param[in] s Descriptor identifying an unbound socket
99  * @param[in] addr Local address to assign to the bound socket
100  * @param[in] addrlen Length in bytes of the address
101  * @return If no error occurs, bind returns SOCKET_SUCCESS.
102  * Otherwise, it returns SOCKET_ERROR
103  **/
104 
105 int_t bind(int_t s, const struct sockaddr *addr, socklen_t addrlen)
106 {
107  error_t error;
108  uint16_t port;
109  IpAddr ipAddr;
110  Socket *sock;
111 
112  //Make sure the socket descriptor is valid
113  if(s < 0 || s >= SOCKET_MAX_COUNT)
114  {
115  return SOCKET_ERROR;
116  }
117 
118  //Point to the socket structure
119  sock = &socketTable[s];
120 
121  //Check the length of the address
122  if(addrlen < (socklen_t) sizeof(SOCKADDR))
123  {
124  //Report an error
125  socketSetErrnoCode(sock, EINVAL);
126  return SOCKET_ERROR;
127  }
128 
129 #if (IPV4_SUPPORT == ENABLED)
130  //IPv4 address?
131  if(addr->sa_family == AF_INET &&
132  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
133  {
134  //Point to the IPv4 address information
135  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
136  //Get port number
137  port = ntohs(sa->sin_port);
138 
139  //Copy IPv4 address
140  ipAddr.length = sizeof(Ipv4Addr);
141  ipAddr.ipv4Addr = sa->sin_addr.s_addr;
142  }
143  else
144 #endif
145 #if (IPV6_SUPPORT == ENABLED)
146  //IPv6 address?
147  if(addr->sa_family == AF_INET6 &&
148  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
149  {
150  //Point to the IPv6 address information
151  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
152  //Get port number
153  port = ntohs(sa->sin6_port);
154 
155  //Copy IPv6 address
157  {
158  ipAddr.length = 0;
159  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
160  }
161  else
162  {
163  ipAddr.length = sizeof(Ipv6Addr);
164  ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr);
165  }
166  }
167  else
168 #endif
169  //Invalid address?
170  {
171  //Report an error
172  socketSetErrnoCode(sock, EINVAL);
173  return SOCKET_ERROR;
174  }
175 
176  //Associate the local address with the socket
177  error = socketBind(sock, &ipAddr, port);
178 
179  //Any error to report?
180  if(error)
181  {
182  socketTranslateErrorCode(sock, error);
183  return SOCKET_ERROR;
184  }
185 
186  //Successful processing
187  return SOCKET_SUCCESS;
188 }
189 
190 
191 /**
192  * @brief Establish a connection to a specified socket
193  * @param[in] s Descriptor identifying an unconnected socket
194  * @param[in] addr Address to which the connection should be established
195  * @param[in] addrlen Length in bytes of the address
196  * @return If no error occurs, connect returns SOCKET_SUCCESS.
197  * Otherwise, it returns SOCKET_ERROR
198  **/
199 
200 int_t connect(int_t s, const struct sockaddr *addr, socklen_t addrlen)
201 {
202  error_t error;
203  uint16_t port;
204  IpAddr ipAddr;
205  Socket *sock;
206 
207  //Make sure the socket descriptor is valid
208  if(s < 0 || s >= SOCKET_MAX_COUNT)
209  {
210  return SOCKET_ERROR;
211  }
212 
213  //Point to the socket structure
214  sock = &socketTable[s];
215 
216  //Check the length of the address
217  if(addrlen < (socklen_t) sizeof(SOCKADDR))
218  {
219  socketSetErrnoCode(sock, EINVAL);
220  return SOCKET_ERROR;
221  }
222 
223 #if (IPV4_SUPPORT == ENABLED)
224  //IPv4 address?
225  if(addr->sa_family == AF_INET &&
226  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
227  {
228  //Point to the IPv4 address information
229  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
230  //Get port number
231  port = ntohs(sa->sin_port);
232 
233  //Copy IPv4 address
234  ipAddr.length = sizeof(Ipv4Addr);
235  ipAddr.ipv4Addr = sa->sin_addr.s_addr;
236  }
237  else
238 #endif
239 #if (IPV6_SUPPORT == ENABLED)
240  //IPv6 address?
241  if(addr->sa_family == AF_INET6 &&
242  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
243  {
244  //Point to the IPv6 address information
245  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
246  //Get port number
247  port = ntohs(sa->sin6_port);
248 
249  //Copy IPv6 address
251  {
252  ipAddr.length = 0;
253  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
254  }
255  else
256  {
257  ipAddr.length = sizeof(Ipv6Addr);
258  ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr);
259  }
260  }
261  else
262 #endif
263  //Invalid address?
264  {
265  //Report an error
266  socketSetErrnoCode(sock, EINVAL);
267  return SOCKET_ERROR;
268  }
269 
270  //Establish connection
271  error = socketConnect(sock, &ipAddr, port);
272 
273  //Check status code
274  if(error == NO_ERROR)
275  {
276  //Successful processing
277  return SOCKET_SUCCESS;
278  }
279  else if(error == ERROR_TIMEOUT)
280  {
281  //Non-blocking socket?
282  if(sock->timeout == 0)
283  {
284  //The connection cannot be completed immediately
286  }
287  else
288  {
289  //Timeout while attempting connection
291  }
292 
293  //Report an error
294  return SOCKET_ERROR;
295  }
296  else
297  {
298  //Report an error
299  socketTranslateErrorCode(sock, error);
300  return SOCKET_ERROR;
301  }
302 }
303 
304 
305 /**
306  * @brief Place a socket in the listening state
307  *
308  * Place a socket in a state in which it is listening for an incoming connection
309  *
310  * @param[in] s Descriptor identifying a bound, unconnected socket
311  * @param[in] backlog Maximum length of the queue of pending connections
312  * @return If no error occurs, listen returns SOCKET_SUCCESS.
313  * Otherwise, it returns SOCKET_ERROR
314  **/
315 
317 {
318  error_t error;
319  Socket *sock;
320 
321  //Make sure the socket descriptor is valid
322  if(s < 0 || s >= SOCKET_MAX_COUNT)
323  {
324  return SOCKET_ERROR;
325  }
326 
327  //Point to the socket structure
328  sock = &socketTable[s];
329 
330  //Place the socket in the listening state
331  error = socketListen(sock, backlog);
332 
333  //Any error to report?
334  if(error)
335  {
336  socketTranslateErrorCode(sock, error);
337  return SOCKET_ERROR;
338  }
339 
340  //Successful processing
341  return SOCKET_SUCCESS;
342 }
343 
344 
345 /**
346  * @brief Permit an incoming connection attempt on a socket
347  * @param[in] s Descriptor that identifies a socket in the listening state
348  * @param[out] addr Address of the connecting entity (optional)
349  * @param[in,out] addrlen Length in bytes of the address (optional)
350  * @return If no error occurs, accept returns a descriptor for the new socket.
351  * Otherwise, it returns SOCKET_ERROR
352  **/
353 
354 int_t accept(int_t s, struct sockaddr *addr, socklen_t *addrlen)
355 {
356  uint16_t port;
357  IpAddr ipAddr;
358  Socket *sock;
359  Socket *newSock;
360 
361  //Make sure the socket descriptor is valid
362  if(s < 0 || s >= SOCKET_MAX_COUNT)
363  {
364  return SOCKET_ERROR;
365  }
366 
367  //Point to the socket structure
368  sock = &socketTable[s];
369 
370  //Permit an incoming connection attempt on a socket
371  newSock = socketAccept(sock, &ipAddr, &port);
372 
373  //No connection request is pending in the SYN queue?
374  if(newSock == NULL)
375  {
376  //Report an error
378  return SOCKET_ERROR;
379  }
380 
381  //The address parameter is optional
382  if(addr != NULL && addrlen != NULL)
383  {
384 #if (IPV4_SUPPORT == ENABLED)
385  //IPv4 address?
386  if(ipAddr.length == sizeof(Ipv4Addr) &&
387  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
388  {
389  //Point to the IPv4 address information
390  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
391 
392  //Set address family and port number
393  sa->sin_family = AF_INET;
394  sa->sin_port = htons(port);
395 
396  //Copy IPv4 address
397  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
398 
399  //Return the actual length of the address
400  *addrlen = sizeof(SOCKADDR_IN);
401  }
402  else
403 #endif
404 #if (IPV6_SUPPORT == ENABLED)
405  //IPv6 address?
406  if(ipAddr.length == sizeof(Ipv6Addr) &&
407  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
408  {
409  //Point to the IPv6 address information
410  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
411 
412  //Set address family and port number
413  sa->sin6_family = AF_INET6;
414  sa->sin6_port = htons(port);
415 
416  //Copy IPv6 address
417  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
418 
419  //Return the actual length of the address
420  *addrlen = sizeof(SOCKADDR_IN6);
421  }
422  else
423 #endif
424  //Invalid address?
425  {
426  //Close socket
427  socketClose(newSock);
428 
429  //Report an error
430  socketSetErrnoCode(sock, EINVAL);
431  return SOCKET_ERROR;
432  }
433  }
434 
435  //Return the descriptor to the new socket
436  return newSock->descriptor;
437 }
438 
439 
440 /**
441  * @brief Send data to a connected socket
442  * @param[in] s Descriptor that identifies a connected socket
443  * @param[in] data Pointer to a buffer containing the data to be transmitted
444  * @param[in] length Number of bytes to be transmitted
445  * @param[in] flags Set of flags that influences the behavior of this function
446  * @return If no error occurs, send returns the total number of bytes sent,
447  * which can be less than the number requested to be sent in the
448  * length parameter. Otherwise, a value of SOCKET_ERROR is returned
449  **/
450 
451 int_t send(int_t s, const void *data, size_t length, int_t flags)
452 {
453  error_t error;
454  size_t written;
455  Socket *sock;
456 
457  //Make sure the socket descriptor is valid
458  if(s < 0 || s >= SOCKET_MAX_COUNT)
459  {
460  return SOCKET_ERROR;
461  }
462 
463  //Point to the socket structure
464  sock = &socketTable[s];
465 
466  //Send data
467  error = socketSend(sock, data, length, &written, flags << 8);
468 
469  //Any error to report?
470  if(error == ERROR_TIMEOUT)
471  {
472  //Check whether some data has been written
473  if(written > 0)
474  {
475  //If a timeout error occurs and some data has been written, the
476  //count of bytes transferred so far is returned...
477  }
478  else
479  {
480  //If no data has been written, a value of SOCKET_ERROR is returned
481  socketTranslateErrorCode(sock, error);
482  return SOCKET_ERROR;
483  }
484  }
485  else if(error != NO_ERROR)
486  {
487  //Otherwise, a value of SOCKET_ERROR is returned
488  socketTranslateErrorCode(sock, error);
489  return SOCKET_ERROR;
490  }
491 
492  //Return the number of bytes transferred so far
493  return written;
494 }
495 
496 
497 /**
498  * @brief Send a datagram to a specific destination
499  * @param[in] s Descriptor that identifies a socket
500  * @param[in] data Pointer to a buffer containing the data to be transmitted
501  * @param[in] length Number of bytes to be transmitted
502  * @param[in] flags Set of flags that influences the behavior of this function
503  * @param[in] addr Destination address
504  * @param[in] addrlen Length in bytes of the destination address
505  * @return If no error occurs, sendto returns the total number of bytes sent,
506  * which can be less than the number requested to be sent in the
507  * length parameter. Otherwise, a value of SOCKET_ERROR is returned
508  **/
509 
510 int_t sendto(int_t s, const void *data, size_t length, int_t flags,
511  const struct sockaddr *addr, socklen_t addrlen)
512 {
513  error_t error;
514  size_t written;
515  uint16_t port;
516  IpAddr ipAddr;
517  Socket *sock;
518 
519  //Make sure the socket descriptor is valid
520  if(s < 0 || s >= SOCKET_MAX_COUNT)
521  {
522  return SOCKET_ERROR;
523  }
524 
525  //Point to the socket structure
526  sock = &socketTable[s];
527 
528  //Check the length of the address
529  if(addrlen < (socklen_t) sizeof(SOCKADDR))
530  {
531  //Report an error
532  socketSetErrnoCode(sock, EINVAL);
533  return SOCKET_ERROR;
534  }
535 
536 #if (IPV4_SUPPORT == ENABLED)
537  //IPv4 address?
538  if(addr->sa_family == AF_INET &&
539  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
540  {
541  //Point to the IPv4 address information
542  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
543 
544  //Get port number
545  port = ntohs(sa->sin_port);
546  //Copy IPv4 address
547  ipAddr.length = sizeof(Ipv4Addr);
548  ipAddr.ipv4Addr = sa->sin_addr.s_addr;
549  }
550  else
551 #endif
552 #if (IPV6_SUPPORT == ENABLED)
553  //IPv6 address?
554  if(addr->sa_family == AF_INET6 &&
555  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
556  {
557  //Point to the IPv6 address information
558  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
559 
560  //Get port number
561  port = ntohs(sa->sin6_port);
562  //Copy IPv6 address
563  ipAddr.length = sizeof(Ipv6Addr);
564  ipv6CopyAddr(&ipAddr.ipv6Addr, sa->sin6_addr.s6_addr);
565  }
566  else
567 #endif
568  //Invalid address?
569  {
570  //Report an error
571  socketSetErrnoCode(sock, EINVAL);
572  return SOCKET_ERROR;
573  }
574 
575  //Send data
576  error = socketSendTo(sock, &ipAddr, port, data, length, &written,
577  flags << 8);
578 
579  //Any error to report?
580  if(error == ERROR_TIMEOUT)
581  {
582  //Check whether some data has been written
583  if(written > 0)
584  {
585  //If a timeout error occurs and some data has been written, the
586  //count of bytes transferred so far is returned...
587  }
588  else
589  {
590  //If no data has been written, a value of SOCKET_ERROR is returned
591  socketTranslateErrorCode(sock, error);
592  return SOCKET_ERROR;
593  }
594  }
595  else if(error != NO_ERROR)
596  {
597  //Otherwise, a value of SOCKET_ERROR is returned
598  socketTranslateErrorCode(sock, error);
599  return SOCKET_ERROR;
600  }
601 
602  //Return the number of bytes transferred so far
603  return written;
604 }
605 
606 
607 /**
608  * @brief Receive data from a connected socket
609  * @param[in] s Descriptor that identifies a connected socket
610  * @param[out] data Buffer where to store the incoming data
611  * @param[in] size Maximum number of bytes that can be received
612  * @param[in] flags Set of flags that influences the behavior of this function
613  * @return If no error occurs, recv returns the number of bytes received. If the
614  * connection has been gracefully closed, the return value is zero.
615  * Otherwise, a value of SOCKET_ERROR is returned
616  **/
617 
618 int_t recv(int_t s, void *data, size_t size, int_t flags)
619 {
620  error_t error;
621  size_t received;
622  Socket *sock;
623 
624  //Make sure the socket descriptor is valid
625  if(s < 0 || s >= SOCKET_MAX_COUNT)
626  {
627  return SOCKET_ERROR;
628  }
629 
630  //Point to the socket structure
631  sock = &socketTable[s];
632 
633  //Receive data
634  error = socketReceive(sock, data, size, &received, flags << 8);
635 
636  //Any error to report?
637  if(error == ERROR_END_OF_STREAM)
638  {
639  //If the connection has been gracefully closed, the return value is zero
640  return 0;
641  }
642  else if(error != NO_ERROR)
643  {
644  //Otherwise, a value of SOCKET_ERROR is returned
645  socketTranslateErrorCode(sock, error);
646  return SOCKET_ERROR;
647  }
648 
649  //Return the number of bytes received
650  return received;
651 }
652 
653 
654 /**
655  * @brief Receive a datagram
656  * @param[in] s Descriptor that identifies a socket
657  * @param[out] data Buffer where to store the incoming data
658  * @param[in] size Maximum number of bytes that can be received
659  * @param[in] flags Set of flags that influences the behavior of this function
660  * @param[out] addr Source address upon return (optional)
661  * @param[in,out] addrlen Length in bytes of the address (optional)
662  * @return If no error occurs, recvfrom returns the number of bytes received.
663  * Otherwise, a value of SOCKET_ERROR is returned
664  **/
665 
666 int_t recvfrom(int_t s, void *data, size_t size, int_t flags,
667  struct sockaddr *addr, socklen_t *addrlen)
668 {
669  error_t error;
670  size_t received;
671  uint16_t port;
672  IpAddr ipAddr;
673  Socket *sock;
674 
675  //Make sure the socket descriptor is valid
676  if(s < 0 || s >= SOCKET_MAX_COUNT)
677  {
678  return SOCKET_ERROR;
679  }
680 
681  //Point to the socket structure
682  sock = &socketTable[s];
683 
684  //Receive data
685  error = socketReceiveFrom(sock, &ipAddr, &port, data, size, &received,
686  flags << 8);
687 
688  //Any error to report?
689  if(error == ERROR_END_OF_STREAM)
690  {
691  //If the connection has been gracefully closed, the return value is zero
692  return 0;
693  }
694  else if(error != NO_ERROR)
695  {
696  //Otherwise, a value of SOCKET_ERROR is returned
697  socketTranslateErrorCode(sock, error);
698  return SOCKET_ERROR;
699  }
700 
701  //The address parameter is optional
702  if(addr != NULL && addrlen != NULL)
703  {
704 #if (IPV4_SUPPORT == ENABLED)
705  //IPv4 address?
706  if(ipAddr.length == sizeof(Ipv4Addr) &&
707  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
708  {
709  //Point to the IPv4 address information
710  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
711 
712  //Set address family and port number
713  sa->sin_family = AF_INET;
714  sa->sin_port = htons(port);
715 
716  //Copy IPv4 address
717  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
718 
719  //Return the actual length of the address
720  *addrlen = sizeof(SOCKADDR_IN);
721  }
722  else
723 #endif
724 #if (IPV6_SUPPORT == ENABLED)
725  //IPv6 address?
726  if(ipAddr.length == sizeof(Ipv6Addr) &&
727  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
728  {
729  //Point to the IPv6 address information
730  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
731 
732  //Set address family and port number
733  sa->sin6_family = AF_INET6;
734  sa->sin6_port = htons(port);
735 
736  //Copy IPv6 address
737  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
738 
739  //Return the actual length of the address
740  *addrlen = sizeof(SOCKADDR_IN6);
741  }
742  else
743 #endif
744  //Invalid address?
745  {
746  //Report an error
747  socketSetErrnoCode(sock, EINVAL);
748  return SOCKET_ERROR;
749  }
750  }
751 
752  //Return the number of bytes received
753  return received;
754 }
755 
756 
757 /**
758  * @brief Receive a message
759  * @param[in] s Descriptor that identifies a socket
760  * @param[in,out] msg Pointer to the structure describing the message
761  * @param[in] flags Set of flags that influences the behavior of this function
762  * @return If no error occurs, recvfrom returns the number of bytes received.
763  * Otherwise, a value of SOCKET_ERROR is returned
764  **/
765 
767 {
768  error_t error;
769  size_t n;
770  Socket *sock;
772 
773  //Make sure the socket descriptor is valid
774  if(s < 0 || s >= SOCKET_MAX_COUNT)
775  {
776  return SOCKET_ERROR;
777  }
778 
779  //Point to the socket structure
780  sock = &socketTable[s];
781 
782  //Check parameters
783  if(msg == NULL || msg->msg_iov == NULL || msg->msg_iovlen != 1)
784  {
785  socketSetErrnoCode(sock, EINVAL);
786  return SOCKET_ERROR;
787  }
788 
789  //Point to the receive buffer
791  message.data = msg->msg_iov[0].iov_base;
792  message.size = msg->msg_iov[0].iov_len;
793 
794  //Receive message
795  error = socketReceiveMsg(sock, &message, flags << 8);
796 
797  //Any error to report?
798  if(error)
799  {
800  socketTranslateErrorCode(sock, error);
801  return SOCKET_ERROR;
802  }
803 
804  //The source address parameter is optional
805  if(msg->msg_name != NULL)
806  {
807 #if (IPV4_SUPPORT == ENABLED)
808  //IPv4 address?
809  if(message.srcIpAddr.length == sizeof(Ipv4Addr) &&
810  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN))
811  {
812  //Point to the IPv4 address information
813  SOCKADDR_IN *sa = (SOCKADDR_IN *) msg->msg_name;
814 
815  //Set address family and port number
816  sa->sin_family = AF_INET;
817  sa->sin_port = htons(message.srcPort);
818 
819  //Copy IPv4 address
820  sa->sin_addr.s_addr = message.srcIpAddr.ipv4Addr;
821 
822  //Return the actual length of the address
823  msg->msg_namelen = sizeof(SOCKADDR_IN);
824  }
825  else
826 #endif
827 #if (IPV6_SUPPORT == ENABLED)
828  //IPv6 address?
829  if(message.srcIpAddr.length == sizeof(Ipv6Addr) &&
830  msg->msg_namelen >= (socklen_t) sizeof(SOCKADDR_IN6))
831  {
832  //Point to the IPv6 address information
833  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) msg->msg_name;
834 
835  //Set address family and port number
836  sa->sin6_family = AF_INET6;
837  sa->sin6_port = htons(message.srcPort);
838 
839  //Copy IPv6 address
840  ipv6CopyAddr(sa->sin6_addr.s6_addr, &message.srcIpAddr.ipv6Addr);
841 
842  //Return the actual length of the address
843  msg->msg_namelen = sizeof(SOCKADDR_IN6);
844  }
845  else
846 #endif
847  //Invalid address?
848  {
849  //Report an error
850  socketSetErrnoCode(sock, EINVAL);
851  return SOCKET_ERROR;
852  }
853  }
854  else
855  {
856  msg->msg_namelen = 0;
857  }
858 
859  //Number of bytes required to store ancillary data
860  n = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo);
861 
862  //The ancillary data buffer parameter is optional
863  if(msg->msg_control != NULL && msg->msg_controllen >= n)
864  {
865  struct cmsghdr *cmsg;
866  struct in_pktinfo *pktInfo;
867 
868  //Point to the ancillary data header
869  cmsg = (struct cmsghdr *) msg->msg_control;
870 
871  //Point to the packet information
872  pktInfo = (struct in_pktinfo *) ((uint8_t *) msg->msg_control +
873  sizeof(struct cmsghdr));
874 
875 #if (IPV4_SUPPORT == ENABLED)
876  //IPv4 address?
877  if(message.destIpAddr.length == sizeof(Ipv4Addr))
878  {
879  //Format ancillary data header
880  cmsg->cmsg_len = n;
881  cmsg->cmsg_level = IPPROTO_IP;
882  cmsg->cmsg_type = IP_PKTINFO;
883 
884  //Save packet information
885  pktInfo->ipi_ifindex = message.interface->index;
886  pktInfo->ipi_addr.s_addr = message.destIpAddr.ipv4Addr;
887 
888  //Return the actual length of the ancillary data buffer
889  msg->msg_controllen = n;
890  }
891  else
892 #endif
893  {
894  msg->msg_controllen = 0;
895  }
896  }
897  else
898  {
899  msg->msg_controllen = 0;
900  }
901 
902  //Return the number of bytes received
903  return message.length;;
904 }
905 
906 
907 /**
908  * @brief Retrieves the local name for a socket
909  * @param[in] s Descriptor identifying a socket
910  * @param[out] addr Address of the socket
911  * @param[in,out] addrlen Length in bytes of the address
912  * @return If no error occurs, getsockname returns SOCKET_SUCCESS
913  * Otherwise, it returns SOCKET_ERROR
914  **/
915 
917 {
918  int_t ret;
919  Socket *sock;
920 
921  //Make sure the socket descriptor is valid
922  if(s < 0 || s >= SOCKET_MAX_COUNT)
923  {
924  return SOCKET_ERROR;
925  }
926 
927  //Point to the socket structure
928  sock = &socketTable[s];
929 
930  //Get exclusive access
932 
933  //Check whether the socket has been bound to an address
934  if(sock->localIpAddr.length != 0)
935  {
936 #if (IPV4_SUPPORT == ENABLED)
937  //IPv4 address?
938  if(sock->localIpAddr.length == sizeof(Ipv4Addr) &&
939  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
940  {
941  //Point to the IPv4 address information
942  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
943 
944  //Set address family and port number
945  sa->sin_family = AF_INET;
946  sa->sin_port = htons(sock->localPort);
947 
948  //Copy IPv4 address
949  sa->sin_addr.s_addr = sock->localIpAddr.ipv4Addr;
950 
951  //Return the actual length of the address
952  *addrlen = sizeof(SOCKADDR_IN);
953  //Successful processing
954  ret = SOCKET_SUCCESS;
955  }
956  else
957 #endif
958 #if (IPV6_SUPPORT == ENABLED)
959  //IPv6 address?
960  if(sock->localIpAddr.length == sizeof(Ipv6Addr) &&
961  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
962  {
963  //Point to the IPv6 address information
964  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
965 
966  //Set address family and port number
967  sa->sin6_family = AF_INET6;
968  sa->sin6_port = htons(sock->localPort);
969 
970  //Copy IPv6 address
971  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->localIpAddr.ipv6Addr);
972 
973  //Return the actual length of the address
974  *addrlen = sizeof(SOCKADDR_IN6);
975  //Successful processing
976  ret = SOCKET_SUCCESS;
977  }
978  else
979 #endif
980  {
981  //The specified length is not valid
982  socketSetErrnoCode(sock, EINVAL);
983  ret = SOCKET_ERROR;
984  }
985  }
986  else
987  {
988  //The socket is not bound to any address
990  ret = SOCKET_ERROR;
991  }
992 
993  //Release exclusive access
995 
996  //return status code
997  return ret;
998 }
999 
1000 
1001 /**
1002  * @brief Retrieves the address of the peer to which a socket is connected
1003  * @param[in] s Descriptor identifying a socket
1004  * @param[out] addr Address of the peer
1005  * @param[in,out] addrlen Length in bytes of the address
1006  * @return If no error occurs, getpeername returns SOCKET_SUCCESS
1007  * Otherwise, it returns SOCKET_ERROR
1008  **/
1009 
1011 {
1012  int_t ret;
1013  Socket *sock;
1014 
1015  //Make sure the socket descriptor is valid
1016  if(s < 0 || s >= SOCKET_MAX_COUNT)
1017  {
1018  return SOCKET_ERROR;
1019  }
1020 
1021  //Point to the socket structure
1022  sock = &socketTable[s];
1023 
1024  //Get exclusive access
1026 
1027  //Check whether the socket is connected to a peer
1028  if(sock->remoteIpAddr.length != 0)
1029  {
1030 #if (IPV4_SUPPORT == ENABLED)
1031  //IPv4 address?
1032  if(sock->remoteIpAddr.length == sizeof(Ipv4Addr) &&
1033  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
1034  {
1035  //Point to the IPv4 address information
1036  SOCKADDR_IN *sa = (SOCKADDR_IN *) addr;
1037 
1038  //Set address family and port number
1039  sa->sin_family = AF_INET;
1040  sa->sin_port = htons(sock->remotePort);
1041 
1042  //Copy IPv4 address
1043  sa->sin_addr.s_addr = sock->remoteIpAddr.ipv4Addr;
1044 
1045  //Return the actual length of the address
1046  *addrlen = sizeof(SOCKADDR_IN);
1047  //Successful processing
1048  ret = SOCKET_SUCCESS;
1049  }
1050  else
1051 #endif
1052 #if (IPV6_SUPPORT == ENABLED)
1053  //IPv6 address?
1054  if(sock->remoteIpAddr.length == sizeof(Ipv6Addr) &&
1055  *addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
1056  {
1057  //Point to the IPv6 address information
1058  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) addr;
1059 
1060  //Set address family and port number
1061  sa->sin6_family = AF_INET6;
1062  sa->sin6_port = htons(sock->remotePort);
1063 
1064  //Copy IPv6 address
1065  ipv6CopyAddr(sa->sin6_addr.s6_addr, &sock->remoteIpAddr.ipv6Addr);
1066 
1067  //Return the actual length of the address
1068  *addrlen = sizeof(SOCKADDR_IN6);
1069  //Successful processing
1070  ret = SOCKET_SUCCESS;
1071  }
1072  else
1073 #endif
1074  {
1075  //The specified length is not valid
1076  socketSetErrnoCode(sock, EINVAL);
1077  ret = SOCKET_ERROR;
1078  }
1079  }
1080  else
1081  {
1082  //The socket is not connected to any peer
1084  ret = SOCKET_ERROR;
1085  }
1086 
1087  //Release exclusive access
1089 
1090  //return status code
1091  return ret;
1092 }
1093 
1094 
1095 /**
1096  * @brief The setsockopt function sets a socket option
1097  * @param[in] s Descriptor that identifies a socket
1098  * @param[in] level The level at which the option is defined
1099  * @param[in] optname The socket option for which the value is to be set
1100  * @param[in] optval A pointer to the buffer in which the value for the requested option is specified
1101  * @param[in] optlen The size, in bytes, of the buffer pointed to by the optval parameter
1102  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
1103  * Otherwise, it returns SOCKET_ERROR
1104  **/
1105 
1106 int_t setsockopt(int_t s, int_t level, int_t optname, const void *optval,
1107  socklen_t optlen)
1108 {
1109  int_t ret;
1110  int_t *val;
1111  TIMEVAL *t;
1112  Socket *sock;
1113 
1114  //Make sure the socket descriptor is valid
1115  if(s < 0 || s >= SOCKET_MAX_COUNT)
1116  {
1117  return SOCKET_ERROR;
1118  }
1119 
1120  //Point to the socket structure
1121  sock = &socketTable[s];
1122 
1123  //Make sure the option is valid
1124  if(optval != NULL)
1125  {
1126  //Level at which the option is defined?
1127  if(level == SOL_SOCKET)
1128  {
1129  //Check option type
1130  if(optname == SO_REUSEADDR)
1131  {
1132  //The socket can be bound to an address which is already in use
1133  ret = SOCKET_SUCCESS;
1134  }
1135  else if(optname == SO_BROADCAST)
1136  {
1137  //Allow transmission and receipt of broadcast messages
1138  ret = SOCKET_SUCCESS;
1139  }
1140  else if(optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)
1141  {
1142  //Check the length of the option
1143  if(optlen >= (socklen_t) sizeof(TIMEVAL))
1144  {
1145  //Cast the option value to the relevant type
1146  t = (TIMEVAL *) optval;
1147 
1148  //If the specified value is of zero, I/O operations shall not
1149  //time out
1150  if(t->tv_sec == 0 && t->tv_usec == 0)
1151  {
1153  }
1154  else
1155  {
1156  socketSetTimeout(sock, t->tv_sec * 1000 + t->tv_usec / 1000);
1157  }
1158 
1159  //Successful processing
1160  ret = SOCKET_SUCCESS;
1161  }
1162  else
1163  {
1164  //The option length is not valid
1165  socketSetErrnoCode(sock, EFAULT);
1166  ret = SOCKET_ERROR;
1167  }
1168  }
1169 #if (TCP_SUPPORT == ENABLED)
1170  else if(optname == SO_SNDBUF)
1171  {
1172  //Check the length of the option
1173  if(optlen >= (socklen_t) sizeof(int_t))
1174  {
1175  //Cast the option value to the relevant type
1176  val = (int_t *) optval;
1177  //Adjust the size of the send buffer
1178  socketSetTxBufferSize(sock, *val);
1179  //Successful processing
1180  ret = SOCKET_SUCCESS;
1181  }
1182  else
1183  {
1184  //The option length is not valid
1185  socketSetErrnoCode(sock, EFAULT);
1186  ret = SOCKET_ERROR;
1187  }
1188  }
1189  else if(optname == SO_RCVBUF)
1190  {
1191  //Check the length of the option
1192  if(optlen >= (socklen_t) sizeof(int_t))
1193  {
1194  //Cast the option value to the relevant type
1195  val = (int_t *) optval;
1196  //Adjust the size of the receive buffer
1197  socketSetRxBufferSize(sock, *val);
1198  //Successful processing
1199  ret = SOCKET_SUCCESS;
1200  }
1201  else
1202  {
1203  //The option length is not valid
1204  socketSetErrnoCode(sock, EFAULT);
1205  ret = SOCKET_ERROR;
1206  }
1207  }
1208 #endif
1209 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
1210  else if(optname == SO_KEEPALIVE)
1211  {
1212  //Check the length of the option
1213  if(optlen >= (socklen_t) sizeof(int_t))
1214  {
1215  //Cast the option value to the relevant type
1216  val = (int_t *) optval;
1217  //This option specifies whether TCP keep-alive is enabled
1218  socketEnableKeepAlive(sock, *val);
1219  //Successful processing
1220  ret = SOCKET_SUCCESS;
1221  }
1222  else
1223  {
1224  //The option length is not valid
1225  socketSetErrnoCode(sock, EFAULT);
1226  ret = SOCKET_ERROR;
1227  }
1228  }
1229 #endif
1230  else
1231  {
1232  //Unknown option
1234  //Report an error
1235  ret = SOCKET_ERROR;
1236  }
1237  }
1238  else if(level == IPPROTO_IP)
1239  {
1240  //Check option type
1241  if(optname == IP_TTL)
1242  {
1243  //Check the length of the option
1244  if(optlen >= (socklen_t) sizeof(int_t))
1245  {
1246  //Cast the option value to the relevant type
1247  val = (int_t *) optval;
1248  //Save TTL value
1249  sock->ttl = *val;
1250  //Successful processing
1251  ret = SOCKET_SUCCESS;
1252  }
1253  else
1254  {
1255  //The option length is not valid
1256  socketSetErrnoCode(sock, EFAULT);
1257  ret = SOCKET_ERROR;
1258  }
1259  }
1260  else if(optname == IP_PKTINFO)
1261  {
1262  //Check the length of the option
1263  if(optlen >= (socklen_t) sizeof(int_t))
1264  {
1265  //Successful processing
1266  ret = SOCKET_SUCCESS;
1267  }
1268  else
1269  {
1270  //The option length is not valid
1271  socketSetErrnoCode(sock, EFAULT);
1272  ret = SOCKET_ERROR;
1273  }
1274  }
1275  else if(optname == IP_MULTICAST_TTL)
1276  {
1277  //Check the length of the option
1278  if(optlen >= (socklen_t) sizeof(int_t))
1279  {
1280  //Cast the option value to the relevant type
1281  val = (int_t *) optval;
1282  //Save TTL value for multicast packets
1283  sock->multicastTtl = *val;
1284  //Successful processing
1285  ret = SOCKET_SUCCESS;
1286  }
1287  else
1288  {
1289  //The option length is not valid
1290  socketSetErrnoCode(sock, EFAULT);
1291  ret = SOCKET_ERROR;
1292  }
1293  }
1294 #if (IP_DIFF_SERV_SUPPORT == ENABLED)
1295  else if(optname == IP_TOS)
1296  {
1297  //Check the length of the option
1298  if(optlen >= (socklen_t) sizeof(int_t))
1299  {
1300  //Cast the option value to the relevant type
1301  val = (int_t *) optval;
1302  //Save DSCP value
1303  sock->dscp = (*val & 0xFF) >> 2;
1304  //Successful processing
1305  ret = SOCKET_SUCCESS;
1306  }
1307  else
1308  {
1309  //The option length is not valid
1310  socketSetErrnoCode(sock, EFAULT);
1311  ret = SOCKET_ERROR;
1312  }
1313  }
1314 #endif
1315  else
1316  {
1317  //Unknown option
1319  ret = SOCKET_ERROR;
1320  }
1321  }
1322  else if(level == IPPROTO_TCP)
1323  {
1324  //Check option type
1325  if(optname == TCP_NODELAY)
1326  {
1327  //Disable Nagle algorithm
1328  ret = SOCKET_SUCCESS;
1329  }
1330 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
1331  else if(optname == TCP_KEEPIDLE)
1332  {
1333  //Check the length of the option
1334  if(optlen >= (socklen_t) sizeof(int_t))
1335  {
1336  //Cast the option value to the relevant type
1337  val = (int_t *) optval;
1338  //Convert the time interval to milliseconds
1339  sock->keepAliveIdle = *val * 1000;
1340  //Successful processing
1341  ret = SOCKET_SUCCESS;
1342  }
1343  else
1344  {
1345  //The option length is not valid
1346  socketSetErrnoCode(sock, EFAULT);
1347  ret = SOCKET_ERROR;
1348  }
1349  }
1350  else if(optname == TCP_KEEPINTVL)
1351  {
1352  //Check the length of the option
1353  if(optlen >= (socklen_t) sizeof(int_t))
1354  {
1355  //Cast the option value to the relevant type
1356  val = (int_t *) optval;
1357  //Convert the time interval to milliseconds
1358  sock->keepAliveInterval = *val * 1000;
1359  //Successful processing
1360  ret = SOCKET_SUCCESS;
1361  }
1362  else
1363  {
1364  //The option length is not valid
1365  socketSetErrnoCode(sock, EFAULT);
1366  ret = SOCKET_ERROR;
1367  }
1368  }
1369  else if(optname == TCP_KEEPCNT)
1370  {
1371  //Check the length of the option
1372  if(optlen >= (socklen_t) sizeof(int_t))
1373  {
1374  //Cast the option value to the relevant type
1375  val = (int_t *) optval;
1376  //Save parameter value
1377  sock->keepAliveMaxProbes = *val;
1378  //Successful processing
1379  ret = SOCKET_SUCCESS;
1380  }
1381  else
1382  {
1383  //The option length is not valid
1384  socketSetErrnoCode(sock, EFAULT);
1385  ret = SOCKET_ERROR;
1386  }
1387  }
1388 #endif
1389  else
1390  {
1391  //Unknown option
1393  ret = SOCKET_ERROR;
1394  }
1395  }
1396  else
1397  {
1398  //The specified level is not valid
1399  socketSetErrnoCode(sock, EINVAL);
1400  ret = SOCKET_ERROR;
1401  }
1402  }
1403  else
1404  {
1405  //The option is not valid
1406  socketSetErrnoCode(sock, EFAULT);
1407  ret = SOCKET_ERROR;
1408  }
1409 
1410  //return status code
1411  return ret;
1412 }
1413 
1414 
1415 /**
1416  * @brief The getsockopt function retrieves a socket option
1417  * @param[in] s Descriptor that identifies a socket
1418  * @param[in] level The level at which the option is defined
1419  * @param[in] optname The socket option for which the value is to be retrieved
1420  * @param[out] optval A pointer to the buffer in which the value for the requested option is to be returned
1421  * @param[in,out] optlen The size, in bytes, of the buffer pointed to by the optval parameter
1422  * @return If no error occurs, getsockopt returns SOCKET_SUCCESS
1423  * Otherwise, it returns SOCKET_ERROR
1424  **/
1425 
1426 int_t getsockopt(int_t s, int_t level, int_t optname, void *optval,
1427  socklen_t *optlen)
1428 {
1429  int_t ret;
1430  int_t *val;
1431  TIMEVAL *t;
1432  Socket *sock;
1433 
1434  //Make sure the socket descriptor is valid
1435  if(s < 0 || s >= SOCKET_MAX_COUNT)
1436  {
1437  return SOCKET_ERROR;
1438  }
1439 
1440  //Point to the socket structure
1441  sock = &socketTable[s];
1442 
1443  //Get exclusive access
1445 
1446  //Make sure the option is valid
1447  if(optval != NULL)
1448  {
1449  //Level at which the option is defined?
1450  if(level == SOL_SOCKET)
1451  {
1452  //Check option type
1453  if(optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)
1454  {
1455  //Check the length of the option
1456  if(*optlen >= (socklen_t) sizeof(TIMEVAL))
1457  {
1458  //Cast the option value to the relevant type
1459  t = (TIMEVAL *) optval;
1460 
1461  //Return the timeout value
1462  if(sock->timeout == INFINITE_DELAY)
1463  {
1464  t->tv_sec = 0;
1465  t->tv_usec = 0;
1466  }
1467  else
1468  {
1469  t->tv_sec = sock->timeout / 1000;
1470  t->tv_usec = (sock->timeout % 1000) * 1000;
1471  }
1472 
1473  //Return the actual length of the option
1474  *optlen = sizeof(TIMEVAL);
1475  //Successful processing
1476  ret = SOCKET_SUCCESS;
1477  }
1478  else
1479  {
1480  //The option length is not valid
1481  socketSetErrnoCode(sock, EFAULT);
1482  ret = SOCKET_ERROR;
1483  }
1484  }
1485 #if (TCP_SUPPORT == ENABLED)
1486  else if(optname == SO_SNDBUF)
1487  {
1488  //Check the length of the option
1489  if(*optlen >= (socklen_t) sizeof(int_t))
1490  {
1491  //Cast the option value to the relevant type
1492  val = (int_t *) optval;
1493  //Return the size of the send buffer
1494  *val = sock->txBufferSize;
1495  //Return the actual length of the option
1496  *optlen = sizeof(int_t);
1497  //Successful processing
1498  ret = SOCKET_SUCCESS;
1499  }
1500  else
1501  {
1502  //The option length is not valid
1503  socketSetErrnoCode(sock, EFAULT);
1504  ret = SOCKET_ERROR;
1505  }
1506  }
1507  else if(optname == SO_RCVBUF)
1508  {
1509  //Check the length of the option
1510  if(*optlen >= (socklen_t) sizeof(int_t))
1511  {
1512  //Cast the option value to the relevant type
1513  val = (int_t *) optval;
1514  //Return the size of the receive buffer
1515  *val = sock->rxBufferSize;
1516  //Return the actual length of the option
1517  *optlen = sizeof(int_t);
1518  //Successful processing
1519  ret = SOCKET_SUCCESS;
1520  }
1521  else
1522  {
1523  //The option length is not valid
1524  socketSetErrnoCode(sock, EFAULT);
1525  ret = SOCKET_ERROR;
1526  }
1527  }
1528 #endif
1529 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
1530  else if(optname == SO_KEEPALIVE)
1531  {
1532  //Check the length of the option
1533  if(*optlen >= (socklen_t) sizeof(TIMEVAL))
1534  {
1535  //Cast the option value to the relevant type
1536  val = (int_t *) optval;
1537  //This option specifies whether TCP keep-alive is enabled
1538  *val = sock->keepAliveEnabled;
1539  //Successful processing
1540  ret = SOCKET_SUCCESS;
1541  }
1542  else
1543  {
1544  //The option length is not valid
1545  socketSetErrnoCode(sock, EFAULT);
1546  ret = SOCKET_ERROR;
1547  }
1548  }
1549 #endif
1550  else if(optname == SO_ERROR)
1551  {
1552  //Check the length of the option
1553  if(*optlen >= (socklen_t) sizeof(int_t))
1554  {
1555  //Cast the option value to the relevant type
1556  val = (int_t *) optval;
1557  //Return the error code
1558  *val = sock->errnoCode;
1559  //Return the actual length of the option
1560  *optlen = sizeof(int_t);
1561 
1562  //Clear error status
1563  sock->errnoCode = 0;
1564 
1565  //Successful processing
1566  ret = SOCKET_SUCCESS;
1567  }
1568  else
1569  {
1570  //The option length is not valid
1571  socketSetErrnoCode(sock, EFAULT);
1572  ret = SOCKET_ERROR;
1573  }
1574  }
1575  else
1576  {
1577  //Unknown option
1579  ret = SOCKET_ERROR;
1580  }
1581  }
1582  else if(level == IPPROTO_IP)
1583  {
1584  //Check option type
1585  if(optname == IP_TTL)
1586  {
1587  //Check the length of the option
1588  if(*optlen >= (socklen_t) sizeof(int_t))
1589  {
1590  //Cast the option value to the relevant type
1591  val = (int_t *) optval;
1592  //Return TTL value
1593  *val = sock->ttl;
1594  //Return the actual length of the option
1595  *optlen = sizeof(int_t);
1596 
1597  //Successful processing
1598  ret = SOCKET_SUCCESS;
1599  }
1600  else
1601  {
1602  //The option length is not valid
1603  socketSetErrnoCode(sock, EFAULT);
1604  ret = SOCKET_ERROR;
1605  }
1606  }
1607  else if(optname == IP_MULTICAST_TTL)
1608  {
1609  //Check the length of the option
1610  if(*optlen >= (socklen_t) sizeof(int_t))
1611  {
1612  //Cast the option value to the relevant type
1613  val = (int_t *) optval;
1614  //Return TTL value for multicast packets
1615  *val = sock->multicastTtl;
1616  //Return the actual length of the option
1617  *optlen = sizeof(int_t);
1618 
1619  //Successful processing
1620  ret = SOCKET_SUCCESS;
1621  }
1622  else
1623  {
1624  //The option length is not valid
1625  socketSetErrnoCode(sock, EFAULT);
1626  ret = SOCKET_ERROR;
1627  }
1628  }
1629 #if (IP_DIFF_SERV_SUPPORT == ENABLED)
1630  else if(optname == IP_TOS)
1631  {
1632  //Check the length of the option
1633  if(*optlen >= (socklen_t) sizeof(int_t))
1634  {
1635  //Cast the option value to the relevant type
1636  val = (int_t *) optval;
1637  //Return DSCP value
1638  *val = sock->dscp << 2;
1639  //Return the actual length of the option
1640  *optlen = sizeof(int_t);
1641 
1642  //Successful processing
1643  ret = SOCKET_SUCCESS;
1644  }
1645  else
1646  {
1647  //The option length is not valid
1648  socketSetErrnoCode(sock, EFAULT);
1649  ret = SOCKET_ERROR;
1650  }
1651  }
1652 #endif
1653  else
1654  {
1655  //Unknown option
1657  ret = SOCKET_ERROR;
1658  }
1659  }
1660  else if(level == IPPROTO_TCP)
1661  {
1662 #if (TCP_SUPPORT == ENABLED && TCP_KEEP_ALIVE_SUPPORT == ENABLED)
1663  //Check option type
1664  if(optname == TCP_KEEPIDLE)
1665  {
1666  //Check the length of the option
1667  if(*optlen >= (socklen_t) sizeof(int_t))
1668  {
1669  //Cast the option value to the relevant type
1670  val = (int_t *) optval;
1671  //Convert the time interval to seconds
1672  *val = sock->keepAliveIdle / 1000;
1673  //Successful processing
1674  ret = SOCKET_SUCCESS;
1675  }
1676  else
1677  {
1678  //The option length is not valid
1679  socketSetErrnoCode(sock, EFAULT);
1680  ret = SOCKET_ERROR;
1681  }
1682  }
1683  else if(optname == TCP_KEEPINTVL)
1684  {
1685  //Check the length of the option
1686  if(*optlen >= (socklen_t) sizeof(int_t))
1687  {
1688  //Cast the option value to the relevant type
1689  val = (int_t *) optval;
1690  //Convert the time interval to seconds
1691  *val = sock->keepAliveInterval / 1000;
1692  //Successful processing
1693  ret = SOCKET_SUCCESS;
1694  }
1695  else
1696  {
1697  //The option length is not valid
1698  socketSetErrnoCode(sock, EFAULT);
1699  ret = SOCKET_ERROR;
1700  }
1701  }
1702  else if(optname == TCP_KEEPCNT)
1703  {
1704  //Check the length of the option
1705  if(*optlen >= (socklen_t) sizeof(int_t))
1706  {
1707  //Cast the option value to the relevant type
1708  val = (int_t *) optval;
1709  //Return parameter value
1710  *val = sock->keepAliveMaxProbes;
1711  //Successful processing
1712  ret = SOCKET_SUCCESS;
1713  }
1714  else
1715  {
1716  //The option length is not valid
1717  socketSetErrnoCode(sock, EFAULT);
1718  ret = SOCKET_ERROR;
1719  }
1720  }
1721  else
1722 #endif
1723  {
1724  //Unknown option
1726  ret = SOCKET_ERROR;
1727  }
1728  }
1729  else
1730  {
1731  //The specified level is not valid
1732  socketSetErrnoCode(sock, EINVAL);
1733  ret = SOCKET_ERROR;
1734  }
1735  }
1736  else
1737  {
1738  //The option is not valid
1739  socketSetErrnoCode(sock, EFAULT);
1740  ret = SOCKET_ERROR;
1741  }
1742 
1743  //Release exclusive access
1745 
1746  //return status code
1747  return ret;
1748 }
1749 
1750 
1751 /**
1752  * @brief Control the I/O mode of a socket
1753  * @param[in] s Descriptor that identifies a socket
1754  * @param[in] cmd A command to perform on the socket
1755  * @param[in,out] arg A pointer to a parameter
1756  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
1757  * Otherwise, it returns SOCKET_ERROR
1758  **/
1759 
1760 int_t ioctlsocket(int_t s, uint32_t cmd, void *arg)
1761 {
1762  int_t ret;
1763  uint_t *val;
1764  Socket *sock;
1765 
1766  //Make sure the socket descriptor is valid
1767  if(s < 0 || s >= SOCKET_MAX_COUNT)
1768  {
1769  return SOCKET_ERROR;
1770  }
1771 
1772  //Point to the socket structure
1773  sock = &socketTable[s];
1774 
1775  //Get exclusive access
1777 
1778  //Make sure the parameter is valid
1779  if(arg != NULL)
1780  {
1781  //Check command type
1782  switch(cmd)
1783  {
1784  //Enable or disable non-blocking mode
1785  case FIONBIO:
1786  //Cast the parameter to the relevant type
1787  val = (uint_t *) arg;
1788  //Enable blocking or non-blocking operation
1789  sock->timeout = (*val != 0) ? 0 : INFINITE_DELAY;
1790  //Successful processing
1791  ret = SOCKET_SUCCESS;
1792  break;
1793 
1794 #if (TCP_SUPPORT == ENABLED)
1795  //Get the number of bytes that are immediately available for reading
1796  case FIONREAD:
1797  //Cast the parameter to the relevant type
1798  val = (uint_t *) arg;
1799  //Return the actual value
1800  *val = sock->rcvUser;
1801  //Successful processing
1802  ret = SOCKET_SUCCESS;
1803  break;
1804 
1805  //Get the number of bytes written to the send queue but not yet
1806  //acknowledged by the other side of the connection
1807  case FIONWRITE:
1808  //Cast the parameter to the relevant type
1809  val = (uint_t *) arg;
1810  //Return the actual value
1811  *val = sock->sndUser + sock->sndNxt - sock->sndUna;
1812  //Successful processing
1813  ret = SOCKET_SUCCESS;
1814  break;
1815 
1816  //Get the free space in the send queue
1817  case FIONSPACE:
1818  //Cast the parameter to the relevant type
1819  val = (uint_t *) arg;
1820  //Return the actual value
1821  *val = sock->txBufferSize - (sock->sndUser + sock->sndNxt -
1822  sock->sndUna);
1823  //Successful processing
1824  ret = SOCKET_SUCCESS;
1825  break;
1826 #endif
1827 
1828  //Unknown command?
1829  default:
1830  //Report an error
1831  socketSetErrnoCode(sock, EINVAL);
1832  ret = SOCKET_ERROR;
1833  break;
1834  }
1835  }
1836  else
1837  {
1838  //The parameter is not valid
1839  socketSetErrnoCode(sock, EFAULT);
1840  ret = SOCKET_ERROR;
1841  }
1842 
1843  //Release exclusive access
1845 
1846  //return status code
1847  return ret;
1848 }
1849 
1850 
1851 /**
1852  * @brief Perform specific operation
1853  * @param[in] s Descriptor that identifies a socket
1854  * @param[in] cmd A command to perform on the socket
1855  * @param[in,out] arg A pointer to a parameter
1856  * @return If no error occurs, setsockopt returns SOCKET_SUCCESS
1857  * Otherwise, it returns SOCKET_ERROR
1858  **/
1859 
1860 int_t fcntl(int_t s, int_t cmd, void *arg)
1861 {
1862  int_t ret;
1863  int_t *flags;
1864  Socket *sock;
1865 
1866  //Make sure the socket descriptor is valid
1867  if(s < 0 || s >= SOCKET_MAX_COUNT)
1868  {
1869  return SOCKET_ERROR;
1870  }
1871 
1872  //Point to the socket structure
1873  sock = &socketTable[s];
1874 
1875  //Get exclusive access
1877 
1878  //Make sure the parameter is valid
1879  if(arg != NULL)
1880  {
1881  //Check command type
1882  switch(cmd)
1883  {
1884  //Get the file status flags?
1885  case F_GETFL:
1886  //Cast the parameter to the relevant type
1887  flags = (int_t *) arg;
1888  //Check whether non-blocking mode is currently enabled
1889  *flags = (sock->timeout == 0) ? O_NONBLOCK : 0;
1890  //Successful processing
1891  ret = SOCKET_SUCCESS;
1892  break;
1893 
1894  //Set the file status flags?
1895  case F_SETFL:
1896  //Cast the parameter to the relevant type
1897  flags = (int_t *) arg;
1898  //Enable blocking or non-blocking operation
1899  sock->timeout = (*flags & O_NONBLOCK) ? 0 : INFINITE_DELAY;
1900  //Successful processing
1901  ret = SOCKET_SUCCESS;
1902  break;
1903 
1904  //Unknown command?
1905  default:
1906  //Report an error
1907  socketSetErrnoCode(sock, EINVAL);
1908  ret = SOCKET_ERROR;
1909  break;
1910  }
1911  }
1912  else
1913  {
1914  //Report an error
1915  socketSetErrnoCode(sock, EFAULT);
1916  ret = SOCKET_ERROR;
1917  }
1918 
1919  //Release exclusive access
1921 
1922  //return status code
1923  return ret;
1924 }
1925 
1926 
1927 /**
1928  * @brief The shutdown function disables sends or receives on a socket
1929  * @param[in] s Descriptor that identifies a socket
1930  * @param[in] how A flag that describes what types of operation will no longer be allowed
1931  * @return If no error occurs, shutdown returns SOCKET_SUCCESS
1932  * Otherwise, it returns SOCKET_ERROR
1933  **/
1934 
1936 {
1937  error_t error;
1938  Socket *sock;
1939 
1940  //Make sure the socket descriptor is valid
1941  if(s < 0 || s >= SOCKET_MAX_COUNT)
1942  {
1943  return SOCKET_ERROR;
1944  }
1945 
1946  //Point to the socket structure
1947  sock = &socketTable[s];
1948 
1949  //Shut down socket
1950  error = socketShutdown(sock, how);
1951 
1952  //Any error to report?
1953  if(error)
1954  {
1955  socketTranslateErrorCode(sock, error);
1956  return SOCKET_ERROR;
1957  }
1958 
1959  //Successful processing
1960  return SOCKET_SUCCESS;
1961 }
1962 
1963 
1964 /**
1965  * @brief The closesocket function closes an existing socket
1966  * @param[in] s Descriptor that identifies a socket
1967  * @return If no error occurs, closesocket returns SOCKET_SUCCESS
1968  * Otherwise, it returns SOCKET_ERROR
1969  **/
1970 
1972 {
1973  Socket *sock;
1974 
1975  //Make sure the socket descriptor is valid
1976  if(s < 0 || s >= SOCKET_MAX_COUNT)
1977  {
1978  return SOCKET_ERROR;
1979  }
1980 
1981  //Point to the socket structure
1982  sock = &socketTable[s];
1983 
1984  //Close socket
1985  socketClose(sock);
1986 
1987  //Successful processing
1988  return SOCKET_SUCCESS;
1989 }
1990 
1991 
1992 /**
1993  * @brief Determine the status of one or more sockets
1994  *
1995  * The select function determines the status of one or more sockets,
1996  * waiting if necessary, to perform synchronous I/O
1997  *
1998  * @param[in] nfds Unused parameter included only for compatibility with
1999  * Berkeley socket
2000  * @param[in,out] readfds An optional pointer to a set of sockets to be
2001  * checked for readability
2002  * @param[in,out] writefds An optional pointer to a set of sockets to be
2003  * checked for writability
2004  * @param[in,out] exceptfds An optional pointer to a set of sockets to be
2005  * checked for errors
2006  * @param[in] timeout The maximum time for select to wait. Set the timeout
2007  * parameter to null for blocking operations
2008  * @return The select function returns the total number of socket handles that
2009  * are ready and contained in the fd_set structures, zero if the time limit
2010  * expired, or SOCKET_ERROR if an error occurred
2011  **/
2012 
2013 int_t select(int_t nfds, fd_set *readfds, fd_set *writefds,
2014  fd_set *exceptfds, const struct timeval *timeout)
2015 {
2016  int_t i;
2017  int_t j;
2018  int_t n;
2019  int_t s;
2020  systime_t time;
2021  uint_t eventMask;
2022  uint_t eventFlags;
2023  OsEvent event;
2024  fd_set *fds;
2025 
2026  //Parse all the descriptor sets
2027  for(i = 0; i < 3; i++)
2028  {
2029  //Select the suitable descriptor set
2030  switch(i)
2031  {
2032  case 0:
2033  //Set of sockets to be checked for readability
2034  fds = readfds;
2035  break;
2036  case 1:
2037  //Set of sockets to be checked for writability
2038  fds = writefds;
2039  break;
2040  default:
2041  //Set of sockets to be checked for errors
2042  fds = exceptfds;
2043  break;
2044  }
2045 
2046  //Each descriptor is optional and may be omitted
2047  if(fds != NULL)
2048  {
2049  //Parse the current set of sockets
2050  for(j = 0; j < fds->fd_count; j++)
2051  {
2052  //Invalid socket descriptor?
2053  if(fds->fd_array[j] < 0 || fds->fd_array[j] >= SOCKET_MAX_COUNT)
2054  {
2055  //Report an error
2056  return SOCKET_ERROR;
2057  }
2058  }
2059  }
2060  }
2061 
2062  //Create an event object to get notified of socket events
2063  if(!osCreateEvent(&event))
2064  {
2065  //Failed to create event
2066  return SOCKET_ERROR;
2067  }
2068 
2069  //Parse all the descriptor sets
2070  for(i = 0; i < 3; i++)
2071  {
2072  //Select the suitable descriptor set
2073  switch(i)
2074  {
2075  case 0:
2076  //Set of sockets to be checked for readability
2077  fds = readfds;
2078  eventMask = SOCKET_EVENT_RX_READY;
2079  break;
2080  case 1:
2081  //Set of sockets to be checked for writability
2082  fds = writefds;
2083  eventMask = SOCKET_EVENT_TX_READY;
2084  break;
2085  default:
2086  //Set of sockets to be checked for errors
2087  fds = exceptfds;
2088  eventMask = SOCKET_EVENT_CLOSED;
2089  break;
2090  }
2091 
2092  //Each descriptor is optional and may be omitted
2093  if(fds != NULL)
2094  {
2095  //Parse the current set of sockets
2096  for(j = 0; j < fds->fd_count; j++)
2097  {
2098  //Get the descriptor associated with the current entry
2099  s = fds->fd_array[j];
2100  //Subscribe to the requested events
2101  socketRegisterEvents(&socketTable[s], &event, eventMask);
2102  }
2103  }
2104  }
2105 
2106  //Retrieve timeout value
2107  if(timeout != NULL)
2108  {
2109  time = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
2110  }
2111  else
2112  {
2113  time = INFINITE_DELAY;
2114  }
2115 
2116  //Block the current task until an event occurs
2117  osWaitForEvent(&event, time);
2118 
2119  //Count the number of events in the signaled state
2120  n = 0;
2121 
2122  //Parse all the descriptor sets
2123  for(i = 0; i < 3; i++)
2124  {
2125  //Select the suitable descriptor set
2126  switch(i)
2127  {
2128  case 0:
2129  //Set of sockets to be checked for readability
2130  fds = readfds;
2131  eventMask = SOCKET_EVENT_RX_READY;
2132  break;
2133  case 1:
2134  //Set of sockets to be checked for writability
2135  fds = writefds;
2136  eventMask = SOCKET_EVENT_TX_READY;
2137  break;
2138  default:
2139  //Set of sockets to be checked for errors
2140  fds = exceptfds;
2141  eventMask = SOCKET_EVENT_CLOSED;
2142  break;
2143  }
2144 
2145  //Each descriptor is optional and may be omitted
2146  if(fds != NULL)
2147  {
2148  //Parse the current set of sockets
2149  for(j = 0; j < fds->fd_count; )
2150  {
2151  //Get the descriptor associated with the current entry
2152  s = fds->fd_array[j];
2153  //Retrieve event flags for the current socket
2154  eventFlags = socketGetEvents(&socketTable[s]);
2155  //Unsubscribe previously registered events
2157 
2158  //Event flag is set?
2159  if(eventFlags & eventMask)
2160  {
2161  //Track the number of events in the signaled state
2162  n++;
2163  //Jump to the next socket descriptor
2164  j++;
2165  }
2166  else
2167  {
2168  //Remove descriptor from the current set
2169  socketFdClr(fds, s);
2170  }
2171  }
2172  }
2173  }
2174 
2175  //Delete event object
2176  osDeleteEvent(&event);
2177  //Return the number of events in the signaled state
2178  return n;
2179 }
2180 
2181 
2182 /**
2183  * @brief Get system host name
2184  * @param[out] name Output buffer where to store the system host name
2185  * @param[in] len Length of the buffer, in bytes
2186  * @return On success, zero is returned. On error, -1 is returned
2187  **/
2188 
2190 {
2191  size_t n;
2192  NetInterface *interface;
2193 
2194  //Check parameter
2195  if(name == NULL)
2196  {
2197  //Report an error
2199  return -1;
2200  }
2201 
2202  //Select the default network interface
2203  interface = netGetDefaultInterface();
2204 
2205  //Retrieve the length of the host name
2206  n = osStrlen(interface->hostname);
2207 
2208  //Make sure the buffer is large enough to hold the string
2209  if(len <= n)
2210  {
2211  //Report an error
2213  return -1;
2214  }
2215 
2216  //Copy the host name
2217  osStrcpy(name, interface->hostname);
2218 
2219  //Successful processing
2220  return 0;
2221 }
2222 
2223 
2224 /**
2225  * @brief Host name resolution
2226  * @param[in] name Name of the host to resolve
2227  * @return Pointer to the hostent structure or a NULL if an error occurs
2228  **/
2229 
2231 {
2232  int_t herrno;
2233  static HOSTENT result;
2234 
2235  //The hostent structure returned by the function resides in static
2236  //memory area
2237  return gethostbyname_r(name, &result, NULL, 0, &herrno);
2238 }
2239 
2240 
2241 /**
2242  * @brief Host name resolution (reentrant version)
2243  * @param[in] name Name of the host to resolve
2244  * @param[in] result Pointer to a hostent structure where the function can
2245  * store the host entry
2246  * @param[out] buf Pointer to a temporary work buffer
2247  * @param[in] buflen Length of the temporary work buffer
2248  * @param[out] h_errnop Pointer to a location where the function can store an
2249  * h_errno value if an error occurs
2250  * @return Pointer to the hostent structure or a NULL if an error occurs
2251  **/
2252 
2253 struct hostent *gethostbyname_r(const char_t *name, struct hostent *result,
2254  char_t *buf, size_t buflen, int_t *h_errnop)
2255 {
2256  error_t error;
2257  IpAddr ipAddr;
2258 
2259  //Check input parameters
2260  if(name == NULL || result == NULL)
2261  {
2262  //Report an error
2263  *h_errnop = NO_RECOVERY;
2264  return NULL;
2265  }
2266 
2267  //Resolve host address
2268  error = getHostByName(NULL, name, &ipAddr, 0);
2269  //Address resolution failed?
2270  if(error)
2271  {
2272  //Report an error
2273  *h_errnop = HOST_NOT_FOUND;
2274  return NULL;
2275  }
2276 
2277 #if (IPV4_SUPPORT == ENABLED)
2278  //IPv4 address?
2279  if(ipAddr.length == sizeof(Ipv4Addr))
2280  {
2281  //Set address family
2282  result->h_addrtype = AF_INET;
2283  result->h_length = sizeof(Ipv4Addr);
2284 
2285  //Copy IPv4 address
2286  ipv4CopyAddr(result->h_addr, &ipAddr.ipv4Addr);
2287  }
2288  else
2289 #endif
2290 #if (IPV6_SUPPORT == ENABLED)
2291  //IPv6 address?
2292  if(ipAddr.length == sizeof(Ipv6Addr))
2293  {
2294  //Set address family
2295  result->h_addrtype = AF_INET6;
2296  result->h_length = sizeof(Ipv6Addr);
2297 
2298  //Copy IPv6 address
2299  ipv6CopyAddr(result->h_addr, &ipAddr.ipv6Addr);
2300  }
2301  else
2302 #endif
2303  //Invalid address?
2304  {
2305  //Report an error
2306  *h_errnop = NO_ADDRESS;
2307  return NULL;
2308  }
2309 
2310  //Successful host name resolution
2311  *h_errnop = NETDB_SUCCESS;
2312 
2313  //Return a pointer to the hostent structure
2314  return result;
2315 }
2316 
2317 
2318 /**
2319  * @brief Convert host and service names to socket address
2320  * @param[in] node Host name or numerical network address
2321  * @param[in] service Service name or decimal number
2322  * @param[in] hints Criteria for selecting the socket address structures
2323  * @param[out] res Dynamically allocated list of socket address structures
2324  * @return On success, zero is returned. On error, a non-zero value is returned
2325  **/
2326 
2327 int_t getaddrinfo(const char_t *node, const char_t *service,
2328  const struct addrinfo *hints, struct addrinfo **res)
2329 {
2330  error_t error;
2331  size_t n;
2332  char_t *p;
2333  uint_t flags;
2334  uint32_t port;
2335  IpAddr ipAddr;
2336  ADDRINFO h;
2337  ADDRINFO *ai;
2338 
2339  //Check whether both node and service name are NULL
2340  if(node == NULL && service == NULL)
2341  return EAI_NONAME;
2342 
2343  //The hints argument is optional
2344  if(hints != NULL)
2345  {
2346  //If hints is not NULL, it points to an addrinfo structure that specifies
2347  //criteria that limit the set of socket addresses that will be returned
2348  h = *hints;
2349  }
2350  else
2351  {
2352  //If hints is NULL, then default criteria are used
2353  osMemset(&h, 0, sizeof(ADDRINFO));
2354  h.ai_family = AF_UNSPEC;
2355  h.ai_socktype = 0;
2356  h.ai_protocol = 0;
2357  h.ai_flags = 0;
2358  }
2359 
2360  //The user may provide a hint to choose between IPv4 and IPv6
2361  if(h.ai_family == AF_UNSPEC)
2362  {
2363  //The value AF_UNSPEC indicates that function should return socket
2364  //addresses for any address family (either IPv4 or IPv6)
2365  flags = 0;
2366  }
2367 #if (IPV4_SUPPORT == ENABLED)
2368  else if(h.ai_family == AF_INET)
2369  {
2370  //The value AF_INET indicates that the function should return an IPv4
2371  //address
2373  }
2374 #endif
2375 #if (IPV6_SUPPORT == ENABLED)
2376  else if(h.ai_family == AF_INET6)
2377  {
2378  //The value AF_INET6 indicates that the function should return an IPv6
2379  //address
2381  }
2382 #endif
2383  else
2384  {
2385  //The requested address family is not supported
2386  return EAI_FAMILY;
2387  }
2388 
2389  //Check whether a host name or numerical network address is specified
2390  if(node != NULL)
2391  {
2392  //If the AI_NUMERICHOST flag, then node must be a numerical network
2393  //address
2394  if((h.ai_flags & AI_NUMERICHOST) != 0)
2395  {
2396  //Convert the string representation to a binary IP address
2397  error = ipStringToAddr(node, &ipAddr);
2398  }
2399  else
2400  {
2401  //Resolve host address
2402  error = getHostByName(NULL, node, &ipAddr, flags);
2403  }
2404 
2405  //Check status code
2406  if(error == NO_ERROR)
2407  {
2408  //Successful host name resolution
2409  }
2410  else if(error == ERROR_IN_PROGRESS)
2411  {
2412  //Host name resolution is in progress
2413  return EAI_AGAIN;
2414  }
2415  else
2416  {
2417  //Permanent failure indication
2418  return EAI_FAIL;
2419  }
2420  }
2421  else
2422  {
2423  //Check flags
2424  if((h.ai_flags & AI_PASSIVE) != 0)
2425  {
2426 #if (IPV4_SUPPORT == ENABLED)
2427  //IPv4 address family?
2428  if(h.ai_family == AF_INET || h.ai_family == AF_UNSPEC)
2429  {
2430  ipAddr.length = sizeof(Ipv4Addr);
2431  ipAddr.ipv4Addr = IPV4_UNSPECIFIED_ADDR;
2432  }
2433  else
2434 #endif
2435 #if (IPV6_SUPPORT == ENABLED)
2436  //IPv6 address family?
2437  if(h.ai_family == AF_INET6 || h.ai_family == AF_UNSPEC)
2438  {
2439  ipAddr.length = sizeof(Ipv6Addr);
2440  ipAddr.ipv6Addr = IPV6_UNSPECIFIED_ADDR;
2441  }
2442  else
2443 #endif
2444  //Unknown address family?
2445  {
2446  //Report an error
2447  return EAI_ADDRFAMILY;
2448  }
2449  }
2450  else
2451  {
2452  //Invalid flags
2453  return EAI_BADFLAGS;
2454  }
2455  }
2456 
2457  //Only service names containing a numeric port number are supported
2458  port = osStrtoul(service, &p, 10);
2459  //Invalid service name?
2460  if(*p != '\0')
2461  {
2462  //The requested service is not available
2463  return EAI_SERVICE;
2464  }
2465 
2466 #if (IPV4_SUPPORT == ENABLED)
2467  //IPv4 address?
2468  if(ipAddr.length == sizeof(Ipv4Addr))
2469  {
2470  //Select the relevant socket family
2471  h.ai_family = AF_INET;
2472  //Get the length of the corresponding socket address
2473  n = sizeof(SOCKADDR_IN);
2474  }
2475  else
2476 #endif
2477 #if (IPV6_SUPPORT == ENABLED)
2478  //IPv6 address?
2479  if(ipAddr.length == sizeof(Ipv6Addr))
2480  {
2481  //Select the relevant socket family
2482  h.ai_family = AF_INET6;
2483  //Get the length of the corresponding socket address
2484  n = sizeof(SOCKADDR_IN6);
2485  }
2486  else
2487 #endif
2488  //Unknown address?
2489  {
2490  //Report an error
2491  return EAI_ADDRFAMILY;
2492  }
2493 
2494  //Allocate a memory buffer to hold the address information structure
2495  ai = osAllocMem(sizeof(ADDRINFO) + n);
2496  //Failed to allocate memory?
2497  if(ai == NULL)
2498  {
2499  //Out of memory
2500  return EAI_MEMORY;
2501  }
2502 
2503  //Initialize address information structure
2504  osMemset(ai, 0, sizeof(ADDRINFO) + n);
2505  ai->ai_family = h.ai_family;
2506  ai->ai_socktype = h.ai_socktype;
2507  ai->ai_protocol = h.ai_protocol;
2508  ai->ai_addr = (SOCKADDR *) ((uint8_t *) ai + sizeof(ADDRINFO));
2509  ai->ai_addrlen = n;
2510  ai->ai_next = NULL;
2511 
2512 #if (IPV4_SUPPORT == ENABLED)
2513  //IPv4 address?
2514  if(ipAddr.length == sizeof(Ipv4Addr))
2515  {
2516  //Point to the IPv4 address information
2517  SOCKADDR_IN *sa = (SOCKADDR_IN *) ai->ai_addr;
2518 
2519  //Set address family and port number
2520  sa->sin_family = AF_INET;
2521  sa->sin_port = htons(port);
2522 
2523  //Copy IPv4 address
2524  sa->sin_addr.s_addr = ipAddr.ipv4Addr;
2525  }
2526  else
2527 #endif
2528 #if (IPV6_SUPPORT == ENABLED)
2529  //IPv6 address?
2530  if(ipAddr.length == sizeof(Ipv6Addr))
2531  {
2532  //Point to the IPv6 address information
2533  SOCKADDR_IN6 *sa = (SOCKADDR_IN6 *) ai->ai_addr;
2534 
2535  //Set address family and port number
2536  sa->sin6_family = AF_INET6;
2537  sa->sin6_port = htons(port);
2538 
2539  //Copy IPv6 address
2540  ipv6CopyAddr(sa->sin6_addr.s6_addr, &ipAddr.ipv6Addr);
2541  }
2542  else
2543 #endif
2544  //Unknown address?
2545  {
2546  //Clean up side effects
2547  osFreeMem(ai);
2548  //Report an error
2549  return EAI_ADDRFAMILY;
2550  }
2551 
2552  //Return a pointer to the allocated address information
2553  *res = ai;
2554 
2555  //Successful processing
2556  return 0;
2557 }
2558 
2559 
2560 /**
2561  * @brief Free socket address structures
2562  * @param[in] res Dynamically allocated list of socket address structures
2563  **/
2564 
2566 {
2567  ADDRINFO *next;
2568 
2569  //Free the list of socket address structures
2570  while(res != NULL)
2571  {
2572  //Get next entry
2573  next = res->ai_next;
2574  //Free current socket address structure
2575  osFreeMem(res);
2576  //Point to the next entry
2577  res = next;
2578  }
2579 }
2580 
2581 
2582 /**
2583  * @brief Convert a socket address to a corresponding host and service
2584  * @param[in] addr Generic socket address structure
2585  * @param[in] addrlen Length in bytes of the address
2586  * @param[out] host Output buffer where to store the host name
2587  * @param[in] hostlen Length of the host name buffer, in bytes
2588  * @param[out] serv Output buffer where to store the service name
2589  * @param[in] servlen Length of the service name buffer, in bytes
2590  * @param[in] flags Set of flags that influences the behavior of this function
2591  * @return On success, zero is returned. On error, a non-zero value is returned
2592  **/
2593 
2594 int_t getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
2595  char_t *host, size_t hostlen, char_t *serv, size_t servlen, int flags)
2596 {
2597  uint16_t port;
2598 
2599  //At least one of hostname or service name must be requested
2600  if(host == NULL && serv == NULL)
2601  return EAI_NONAME;
2602 
2603 #if (IPV4_SUPPORT == ENABLED)
2604  //IPv4 address?
2605  if(addr->sa_family == AF_INET &&
2606  addrlen >= (socklen_t) sizeof(SOCKADDR_IN))
2607  {
2608  SOCKADDR_IN *sa;
2609  Ipv4Addr ipv4Addr;
2610 
2611  //Point to the IPv4 address information
2612  sa = (SOCKADDR_IN *) addr;
2613 
2614  //The caller can specify that no host name is required
2615  if(host != NULL)
2616  {
2617  //Make sure the buffer is large enough to hold the host name
2618  if(hostlen < 16)
2619  return EAI_OVERFLOW;
2620 
2621  //Copy the binary representation of the IPv4 address
2622  ipv4CopyAddr(&ipv4Addr, &sa->sin_addr.s_addr);
2623  //Convert the IPv4 address to dot-decimal notation
2624  ipv4AddrToString(ipv4Addr, host);
2625  }
2626 
2627  //Retrieve port number
2628  port = ntohs(sa->sin_port);
2629  }
2630  else
2631 #endif
2632 #if (IPV6_SUPPORT == ENABLED)
2633  //IPv6 address?
2634  if(addr->sa_family == AF_INET6 &&
2635  addrlen >= (socklen_t) sizeof(SOCKADDR_IN6))
2636  {
2637  SOCKADDR_IN6 *sa;
2638  Ipv6Addr ipv6Addr;
2639 
2640  //Point to the IPv6 address information
2641  sa = (SOCKADDR_IN6 *) addr;
2642 
2643  //The caller can specify that no host name is required
2644  if(host != NULL)
2645  {
2646  //Make sure the buffer is large enough to hold the host name
2647  if(hostlen < 40)
2648  return EAI_OVERFLOW;
2649 
2650  //Copy the binary representation of the IPv6 address
2651  ipv6CopyAddr(&ipv6Addr, sa->sin6_addr.s6_addr);
2652  //Convert the IPv6 address to string representation
2653  ipv6AddrToString(&ipv6Addr, host);
2654  }
2655 
2656  //Retrieve port number
2657  port = ntohs(sa->sin6_port);
2658  }
2659  else
2660 #endif
2661  //Invalid address?
2662  {
2663  //The address family was not recognized, or the address length was
2664  //invalid for the specified family
2665  return EAI_FAMILY;
2666  }
2667 
2668  //The caller can specify that no service name is required
2669  if(serv != NULL)
2670  {
2671  //Make sure the buffer is large enough to hold the service name
2672  if(servlen < 6)
2673  return EAI_OVERFLOW;
2674 
2675  //Convert the port number to string representation
2676  osSprintf(serv, "%" PRIu16, ntohs(port));
2677  }
2678 
2679  //Successful processing
2680  return 0;
2681 }
2682 
2683 
2684 /**
2685  * @brief Convert a dot-decimal string into binary data in network byte order
2686  * @param[in] cp NULL-terminated string representing the IPv4 address
2687  * @return Binary data in network byte order
2688  **/
2689 
2691 {
2692 #if (IPV4_SUPPORT == ENABLED)
2693  error_t error;
2694  Ipv4Addr ipv4Addr;
2695 
2696  //Convert a dot-decimal string to a binary IPv4 address
2697  error = ipv4StringToAddr(cp, &ipv4Addr);
2698 
2699  //Check status code
2700  if(error)
2701  {
2702  //The input is invalid
2703  return INADDR_NONE;
2704  }
2705  else
2706  {
2707  //Return the binary representation
2708  return ipv4Addr;
2709  }
2710 #else
2711  //IPv4 is not implemented
2712  return INADDR_NONE;
2713 #endif
2714 }
2715 
2716 
2717 /**
2718  * @brief Convert a dot-decimal string into binary form
2719  * @param[in] cp NULL-terminated string representing the IPv4 address
2720  * @param[out] inp Binary data in network byte order
2721  * @return The function returns non-zero if the address is valid, zero if not
2722  **/
2723 
2724 int_t inet_aton(const char_t *cp, struct in_addr *inp)
2725 {
2726 #if (IPV4_SUPPORT == ENABLED)
2727  error_t error;
2728  Ipv4Addr ipv4Addr;
2729 
2730  //Convert a dot-decimal string to a binary IPv4 address
2731  error = ipv4StringToAddr(cp, &ipv4Addr);
2732 
2733  //Check status code
2734  if(error)
2735  {
2736  //The input is invalid
2737  return 0;
2738  }
2739  else
2740  {
2741  //Copy the binary representation of the IPv4 address
2742  inp->s_addr = ipv4Addr;
2743  //The conversion succeeded
2744  return 1;
2745  }
2746 #else
2747  //IPv4 is not implemented
2748  return 0;
2749 #endif
2750 }
2751 
2752 
2753 /**
2754  * @brief Convert a binary IPv4 address to dot-decimal notation
2755  * @param[in] in Binary representation of the IPv4 address
2756  * @return Pointer to the formatted string
2757  **/
2758 
2759 const char_t *inet_ntoa(struct in_addr in)
2760 {
2761  static char_t buf[16];
2762 
2763  //The string returned by the function resides in static memory area
2764  return inet_ntoa_r(in, buf, sizeof(buf));
2765 }
2766 
2767 
2768 /**
2769  * @brief Convert a binary IPv4 address to dot-decimal notation (reentrant version)
2770  * @param[in] in Binary representation of the IPv4 address
2771  * @param[out] buf Pointer to the buffer where to format the string
2772  * @param[in] buflen Number of bytes available in the buffer
2773  * @return Pointer to the formatted string
2774  **/
2775 
2776 const char_t *inet_ntoa_r(struct in_addr in, char_t *buf, socklen_t buflen)
2777 {
2778  //Properly terminate the string
2779  buf[0] = '\0';
2780 
2781 #if (IPV4_SUPPORT == ENABLED)
2782  //Check the length of the buffer
2783  if(buflen >= 16)
2784  {
2785  //Convert the binary IPv4 address to dot-decimal notation
2786  ipv4AddrToString(in.s_addr, buf);
2787  }
2788 #endif
2789 
2790  //Return a pointer to the formatted string
2791  return buf;
2792 }
2793 
2794 
2795 /**
2796  * @brief Convert an IPv4 or IPv6 address from text to binary form
2797  * @param[in] af Address family
2798  * @param[in] src NULL-terminated string representing the IP address
2799  * @param[out] dst Binary representation of the IP address
2800  * @return The function returns 1 on success. 0 is returned if the address
2801  * is not valid. If the address family is not valid, -1 is returned
2802  **/
2803 
2804 int_t inet_pton(int_t af, const char_t *src, void *dst)
2805 {
2806  error_t error;
2807 
2808 #if (IPV4_SUPPORT == ENABLED)
2809  //IPv4 address?
2810  if(af == AF_INET)
2811  {
2812  Ipv4Addr ipv4Addr;
2813 
2814  //Convert the IPv4 address from text to binary form
2815  error = ipv4StringToAddr(src, &ipv4Addr);
2816 
2817  //Check status code
2818  if(error)
2819  {
2820  //The input is invalid
2821  return 0;
2822  }
2823  else
2824  {
2825  //Copy the binary representation of the IPv4 address
2826  ipv4CopyAddr(dst, &ipv4Addr);
2827  //The conversion succeeded
2828  return 1;
2829  }
2830  }
2831  else
2832 #endif
2833 #if (IPV6_SUPPORT == ENABLED)
2834  //IPv6 address?
2835  if(af == AF_INET6)
2836  {
2837  Ipv6Addr ipv6Addr;
2838 
2839  //Convert the IPv6 address from text to binary form
2840  error = ipv6StringToAddr(src, &ipv6Addr);
2841 
2842  //Check status code
2843  if(error)
2844  {
2845  //The input is invalid
2846  return 0;
2847  }
2848  else
2849  {
2850  //Copy the binary representation of the IPv6 address
2851  ipv6CopyAddr(dst, &ipv6Addr);
2852  //The conversion succeeded
2853  return 1;
2854  }
2855  }
2856  else
2857 #endif
2858  //Invalid address family?
2859  {
2860  //Report an error
2861  return -1;
2862  }
2863 }
2864 
2865 
2866 /**
2867  * @brief Convert an IPv4 or IPv6 address from binary to text
2868  * @param[in] af Address family
2869  * @param[in] src Binary representation of the IP address
2870  * @param[out] dst NULL-terminated string representing the IP address
2871  * @param[in] size Number of bytes available in the buffer
2872  * @return On success, the function returns a pointer to the formatted string.
2873  * NULL is returned if there was an error
2874  **/
2875 
2876 const char_t *inet_ntop(int_t af, const void *src, char_t *dst, socklen_t size)
2877 {
2878 #if (IPV4_SUPPORT == ENABLED)
2879  //IPv4 address?
2880  if(af == AF_INET && size >= INET_ADDRSTRLEN)
2881  {
2882  Ipv4Addr ipv4Addr;
2883 
2884  //Copy the binary representation of the IPv4 address
2885  ipv4CopyAddr(&ipv4Addr, src);
2886 
2887  //Convert the IPv4 address to dot-decimal notation
2888  return ipv4AddrToString(ipv4Addr, dst);
2889  }
2890  else
2891 #endif
2892 #if (IPV6_SUPPORT == ENABLED)
2893  //IPv6 address?
2894  if(af == AF_INET6 && size >= INET6_ADDRSTRLEN)
2895  {
2896  Ipv6Addr ipv6Addr;
2897 
2898  //Copy the binary representation of the IPv6 address
2899  ipv6CopyAddr(&ipv6Addr, src);
2900 
2901  //Convert the IPv6 address to string representation
2902  return ipv6AddrToString(&ipv6Addr, dst);
2903  }
2904  else
2905 #endif
2906  //Invalid address family?
2907  {
2908  //Report an error
2909  return NULL;
2910  }
2911 }
2912 
2913 #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:760
const struct in6_addr in6addr_any
Definition: bsd_socket.c:47
#define F_GETFL
Definition: bsd_socket.h:172
uint8_t length
Definition: coap_common.h:193
char_t * ipv6AddrToString(const Ipv6Addr *ipAddr, char_t *str)
Convert a binary IPv6 address to a string representation.
Definition: ipv6.c:2334
struct hostent * gethostbyname(const char_t *name)
Host name resolution.
Definition: bsd_socket.c:2230
#define htons(value)
Definition: cpu_endian.h:413
struct sockaddr * ai_addr
Definition: bsd_socket.h:404
int_t socklen_t
Length type.
Definition: bsd_socket.h:254
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:2804
error_t socketBind(Socket *socket, const IpAddr *localIpAddr, uint16_t localPort)
Associate a local address with a socket.
Definition: socket.c:596
#define AF_INET6
Definition: bsd_socket.h:80
Ancillary data header.
Definition: bsd_socket.h:352
uint32_t in_addr_t
IPv4 address.
Definition: bsd_socket.h:261
int_t connect(int_t s, const struct sockaddr *addr, socklen_t addrlen)
Establish a connection to a specified socket.
Definition: bsd_socket.c:200
#define ENOPROTOOPT
Definition: bsd_socket.h:221
int_t recvmsg(int_t s, struct msghdr *msg, int_t flags)
Receive a message.
Definition: bsd_socket.c:766
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:1106
Helper function for BSD socket API.
#define EAI_BADFLAGS
Definition: bsd_socket.h:201
#define IP_TOS
Definition: bsd_socket.h:148
#define EINPROGRESS
Definition: bsd_socket.h:218
uint8_t data[]
Definition: ethernet.h:220
signed int int_t
Definition: compiler_port.h:49
#define netMutex
Definition: net_legacy.h:195
void * iov_base
Definition: bsd_socket.h:326
IP network address.
Definition: ip.h:79
uint16_t sin_family
Definition: bsd_socket.h:291
size_t iov_len
Definition: bsd_socket.h:327
const char_t * inet_ntoa(struct in_addr in)
Convert a binary IPv4 address to dot-decimal notation.
Definition: bsd_socket.c:2759
int_t shutdown(int_t s, int_t how)
The shutdown function disables sends or receives on a socket.
Definition: bsd_socket.c:1935
#define ETIMEDOUT
Definition: bsd_socket.h:219
uint8_t p
Definition: ndp.h:298
#define SOCKET_ERROR
Definition: bsd_socket.h:196
#define NO_RECOVERY
Definition: bsd_socket.h:232
int_t recv(int_t s, void *data, size_t size, int_t flags)
Receive data from a connected socket.
Definition: bsd_socket.c:618
uint8_t t
Definition: lldp_ext_med.h:210
#define EAI_ADDRFAMILY
Definition: bsd_socket.h:199
Set of sockets.
Definition: bsd_socket.h:375
#define SO_RCVTIMEO
Definition: bsd_socket.h:141
Message and ancillary data.
Definition: socket.h:200
void socketClose(Socket *socket)
Close an existing socket.
Definition: socket.c:1331
Event object.
socklen_t msg_namelen
Definition: bsd_socket.h:338
struct in6_addr sin6_addr
Definition: bsd_socket.h:316
#define AF_INET
Definition: bsd_socket.h:79
void * msg_control
Definition: bsd_socket.h:341
#define INADDR_NONE
Definition: bsd_socket.h:236
int_t gethostname(char_t *name, size_t len)
Get system host name.
Definition: bsd_socket.c:2189
struct sockaddr_in6 SOCKADDR_IN6
IPv6 address information.
#define SO_SNDBUF
Definition: bsd_socket.h:138
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:2876
#define ipv6CompAddr(ipAddr1, ipAddr2)
Definition: ipv6.h:121
char_t name[]
#define EAI_FAIL
Definition: bsd_socket.h:202
#define FIONREAD
Definition: bsd_socket.h:167
int_t listen(int_t s, int_t backlog)
Place a socket in the listening state.
Definition: bsd_socket.c:316
#define EINVAL
Definition: bsd_socket.h:217
#define osStrlen(s)
Definition: os_port.h:164
@ ERROR_END_OF_STREAM
Definition: error.h:210
const uint8_t res[]
IPv4 address information.
Definition: bsd_socket.h:290
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:2776
#define BSD_SOCKET_SET_ERRNO(e)
Definition: bsd_socket.h:50
#define EWOULDBLOCK
Definition: bsd_socket.h:215
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:268
int_t cmsg_level
Definition: bsd_socket.h:354
void socketFdClr(fd_set *fds, int_t s)
Remove a descriptor from an existing set.
void * msg_name
Definition: bsd_socket.h:337
error_t socketSetTxBufferSize(Socket *socket, size_t size)
Specify the size of the send buffer.
Definition: socket.c:485
uint8_t h_addr[16]
Definition: bsd_socket.h:389
void freeaddrinfo(struct addrinfo *res)
Free socket address structures.
Definition: bsd_socket.c:2565
#define AF_PACKET
Definition: bsd_socket.h:81
uint8_t level
Definition: tls.h:1800
@ HOST_TYPE_IPV6
Definition: socket.h:177
#define NO_ADDRESS
Definition: bsd_socket.h:233
Structure that represents an IPv6 address.
Definition: bsd_socket.h:303
__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:774
#define SO_RCVBUF
Definition: bsd_socket.h:139
#define EAI_NONAME
Definition: bsd_socket.h:206
struct timeval TIMEVAL
Timeout structure.
@ ERROR_IN_PROGRESS
Definition: error.h:213
#define TCP_KEEPCNT
Definition: bsd_socket.h:158
#define TCP_NODELAY
Definition: bsd_socket.h:154
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:53
int32_t tv_sec
Definition: bsd_socket.h:418
uint8_t h
Definition: ndp.h:300
int ipi_ifindex
Definition: bsd_socket.h:365
void socketTranslateErrorCode(Socket *socket, error_t errorCode)
Translate error code.
error_t socketSetRxBufferSize(Socket *socket, size_t size)
Specify the size of the receive buffer.
Definition: socket.c:519
int_t fd_count
Definition: bsd_socket.h:376
#define IPPROTO_IP
Definition: bsd_socket.h:95
#define AI_NUMERICHOST
Definition: bsd_socket.h:181
error_t socketEnableKeepAlive(Socket *socket, bool_t enabled)
Enable TCP keep-alive.
Definition: socket.c:394
Socket address.
Definition: bsd_socket.h:269
char_t type
error_t
Error codes.
Definition: error.h:43
int_t ai_protocol
Definition: bsd_socket.h:402
IPv6 address information.
Definition: bsd_socket.h:313
#define osSprintf(dest,...)
Definition: os_port.h:230
#define AI_PASSIVE
Definition: bsd_socket.h:179
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:966
uint8_t protocol
Structure that represents an IPv4 address.
Definition: bsd_socket.h:280
uint16_t h_length
Definition: bsd_socket.h:388
__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:63
@ SOCKET_EVENT_TX_READY
Definition: socket.h:158
#define EAI_SERVICE
Definition: bsd_socket.h:207
#define EAI_OVERFLOW
Definition: bsd_socket.h:210
void socketSetErrnoCode(Socket *socket, uint_t errnoCode)
Set BSD error code.
struct sockaddr_in SOCKADDR_IN
IPv4 address information.
int_t getsockname(int_t s, struct sockaddr *addr, socklen_t *addrlen)
Retrieves the local name for a socket.
Definition: bsd_socket.c:916
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:2253
void osDeleteEvent(OsEvent *event)
Delete an event object.
#define NetInterface
Definition: net.h:36
#define ENOTCONN
Definition: bsd_socket.h:224
#define SO_REUSEADDR
Definition: bsd_socket.h:133
#define SO_BROADCAST
Definition: bsd_socket.h:136
NetInterface * netGetDefaultInterface(void)
Get default network interface.
Definition: net.c:410
BSD socket API.
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:988
error_t socketReceiveMsg(Socket *socket, SocketMsg *message, uint_t flags)
Receive a message from a connectionless socket.
Definition: socket.c:1168
#define IP_MULTICAST_TTL
Definition: bsd_socket.h:151
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:1516
int_t msg_iovlen
Definition: bsd_socket.h:340
#define SOCKET_SUCCESS
Definition: bsd_socket.h:195
#define IP_PKTINFO
Definition: bsd_socket.h:150
Message header.
Definition: bsd_socket.h:336
error_t socketConnect(Socket *socket, const IpAddr *remoteIpAddr, uint16_t remotePort)
Establish a connection to a specified socket.
Definition: socket.c:625
const Ipv6Addr IPV6_UNSPECIFIED_ADDR
Definition: ipv6.c:66
error_t socketShutdown(Socket *socket, uint_t how)
Disable reception, transmission, or both.
Definition: socket.c:1294
int_t fd_array[FD_SETSIZE]
Definition: bsd_socket.h:377
#define IPPROTO_TCP
Definition: bsd_socket.h:98
Socket * socketOpen(uint_t type, uint_t protocol)
Create a socket (UDP or TCP)
Definition: socket.c:122
#define SO_SNDTIMEO
Definition: bsd_socket.h:140
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:2690
uint16_t sin6_family
Definition: bsd_socket.h:314
#define ENAMETOOLONG
Definition: bsd_socket.h:220
int32_t tv_usec
Definition: bsd_socket.h:419
socklen_t ai_addrlen
Definition: bsd_socket.h:403
@ HOST_TYPE_IPV4
Definition: socket.h:176
struct addrinfo ADDRINFO
Information about address of a service provider.
#define HOST_NOT_FOUND
Definition: bsd_socket.h:230
Socket socketTable[SOCKET_MAX_COUNT]
Definition: socket.c:50
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:666
#define FIONSPACE
Definition: bsd_socket.h:169
Socket * socketAccept(Socket *socket, IpAddr *clientIpAddr, uint16_t *clientPort)
Permit an incoming connection attempt on a socket.
Definition: socket.c:726
int_t ioctlsocket(int_t s, uint32_t cmd, void *arg)
Control the I/O mode of a socket.
Definition: bsd_socket.c:1760
uint32_t systime_t
System time.
uint16_t port
Definition: dns_common.h:251
#define ntohs(value)
Definition: cpu_endian.h:421
in_addr_t s_addr
Definition: bsd_socket.h:281
#define osStrtoul(s, endptr, base)
Definition: os_port.h:248
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:105
#define EFAULT
Definition: bsd_socket.h:216
@ 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:195
struct in_addr ipi_addr
Definition: bsd_socket.h:366
Information about a given host.
Definition: bsd_socket.h:386
#define F_SETFL
Definition: bsd_socket.h:173
uint32_t time
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:117
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:2013
#define FIONBIO
Definition: bsd_socket.h:166
Helper functions for sockets.
size_t cmsg_len
Definition: bsd_socket.h:353
#define FIONWRITE
Definition: bsd_socket.h:168
@ SOCKET_EVENT_RX_READY
Definition: socket.h:162
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:239
Timeout structure.
Definition: bsd_socket.h:417
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
uint16_t sin_port
Definition: bsd_socket.h:292
uint16_t sin6_port
Definition: bsd_socket.h:315
struct in_addr sin_addr
Definition: bsd_socket.h:293
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:2594
#define Socket
Definition: socket.h:36
int_t ai_socktype
Definition: bsd_socket.h:401
bool_t osCreateEvent(OsEvent *event)
Create an event object.
#define INET6_ADDRSTRLEN
Definition: bsd_socket.h:242
#define SOL_SOCKET
Definition: bsd_socket.h:109
#define EAI_AGAIN
Definition: bsd_socket.h:200
uint8_t s
uint8_t message[]
Definition: chap.h:152
const struct in6_addr in6addr_loopback
Definition: bsd_socket.c:50
#define EAI_FAMILY
Definition: bsd_socket.h:203
int_t accept(int_t s, struct sockaddr *addr, socklen_t *addrlen)
Permit an incoming connection attempt on a socket.
Definition: bsd_socket.c:354
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:781
@ SOCKET_TYPE_RAW_ETH
Definition: socket.h:81
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:1426
#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:1010
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:149
error_t ipv4StringToAddr(const char_t *str, Ipv4Addr *ipAddr)
Convert a dot-decimal string to a binary IPv4 address.
Definition: ipv4.c:1505
struct iovec * msg_iov
Definition: bsd_socket.h:339
#define NETDB_SUCCESS
Definition: bsd_socket.h:229
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:510
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:2188
#define SO_KEEPALIVE
Definition: bsd_socket.h:134
#define O_NONBLOCK
Definition: bsd_socket.h:176
Ipv4Addr addr
Definition: nbns_common.h:121
#define EAI_MEMORY
Definition: bsd_socket.h:204
#define IP_TTL
Definition: bsd_socket.h:149
int_t cmsg_type
Definition: bsd_socket.h:355
int_t ai_family
Definition: bsd_socket.h:400
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:2327
unsigned int uint_t
Definition: compiler_port.h:50
size_t msg_controllen
Definition: bsd_socket.h:342
void socketUnregisterEvents(Socket *socket)
Unsubscribe previously registered events.
Definition: socket_misc.c:250
#define osMemset(p, value, length)
Definition: os_port.h:134
TCP/IP stack core.
int_t fcntl(int_t s, int_t cmd, void *arg)
Perform specific operation.
Definition: bsd_socket.c:1860
@ SOCKET_EVENT_CLOSED
Definition: socket.h:157
char_t * ipv4AddrToString(Ipv4Addr ipAddr, char_t *str)
Convert a binary IPv4 address to dot-decimal notation.
Definition: ipv4.c:1592
#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:2724
#define osStrcpy(s1, s2)
Definition: os_port.h:206
#define TCP_KEEPINTVL
Definition: bsd_socket.h:157
error_t socketSetTimeout(Socket *socket, systime_t timeout)
Set timeout value for blocking operations.
Definition: socket.c:145
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:451
__start_packed struct @0 Ipv6Addr
IPv6 network address.
uint16_t next
Definition: ipv4_frag.h:97
uint_t socketGetEvents(Socket *socket)
Retrieve event flags for a specified socket.
Definition: socket_misc.c:273
#define TCP_KEEPIDLE
Definition: bsd_socket.h:156
Information about address of a service provider.
Definition: bsd_socket.h:398
uint8_t ipAddr[4]
Definition: mib_common.h:187
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
uint8_t s6_addr[16]
Definition: bsd_socket.h:304
#define INFINITE_DELAY
Definition: os_port.h:77
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:111
int_t closesocket(int_t s)
The closesocket function closes an existing socket.
Definition: bsd_socket.c:1971
uint16_t h_addrtype
Definition: bsd_socket.h:387
struct addrinfo * ai_next
Definition: bsd_socket.h:406
Packet information.
Definition: bsd_socket.h:364
#define SO_ERROR
Definition: bsd_socket.h:142
error_t socketListen(Socket *socket, uint_t backlog)
Place a socket in the listening state.
Definition: socket.c:689