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