1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 2003-2010, Free Software Foundation, Inc. *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 3, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
22 * You should have received a copy of the GNU General Public License and *
23 * a copy of the GCC Runtime Library Exception along with this program; *
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
25 * <http://www.gnu.org/licenses/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
32 /* This file provides a portable binding to the sockets API */
38 * For VMS, gsocket.h can't include sockets-related DEC C header files
39 * when building the runtime (because these files are in a DEC C text library
40 * (DECC$RTLDEF.TLB) not accessible to GCC). So, we generate a separate header
41 * file along with s-oscons.ads and include it here.
43 # include "s-oscons.h"
46 * We also need the declaration of struct hostent/servent, which s-oscons
47 * can't provide, so we copy it manually here. This needs to be kept in synch
48 * with the definition of that structure in the DEC C headers, which
49 * hopefully won't change frequently.
51 typedef char *__netdb_char_ptr
__attribute__ (( mode (SI
) ));
52 typedef __netdb_char_ptr
*__netdb_char_ptr_ptr
__attribute__ (( mode (SI
) ));
55 __netdb_char_ptr h_name
;
56 __netdb_char_ptr_ptr h_aliases
;
59 __netdb_char_ptr_ptr h_addr_list
;
63 __netdb_char_ptr s_name
;
64 __netdb_char_ptr_ptr s_aliases
;
66 __netdb_char_ptr s_proto
;
70 #if defined(HAVE_SOCKETS)
72 /* Include all the necessary system-specific headers and define the
73 * necessary macros (shared with gen-oscons).
76 #if !defined(SO_NOSIGPIPE) && !defined (MSG_NOSIGNAL)
79 /* Required if we will be calling signal() in __gnat_disable_all_sigpipes() */
82 /* Required for __gnat_malloc() */
85 /* Required for memcpy() */
87 extern void __gnat_disable_sigpipe (int fd
);
88 extern void __gnat_disable_all_sigpipes (void);
89 extern int __gnat_create_signalling_fds (int *fds
);
90 extern int __gnat_read_signalling_fd (int rsig
);
91 extern int __gnat_write_signalling_fd (int wsig
);
92 extern void __gnat_close_signalling_fd (int sig
);
93 extern void __gnat_last_socket_in_set (fd_set
*, int *);
94 extern void __gnat_get_socket_from_set (fd_set
*, int *, int *);
95 extern void __gnat_insert_socket_in_set (fd_set
*, int);
96 extern int __gnat_is_socket_in_set (fd_set
*, int);
97 extern fd_set
*__gnat_new_socket_set (fd_set
*);
98 extern void __gnat_remove_socket_from_set (fd_set
*, int);
99 extern void __gnat_reset_socket_set (fd_set
*);
100 extern int __gnat_get_h_errno (void);
101 extern int __gnat_socket_ioctl (int, int, int *);
103 extern char * __gnat_servent_s_name (struct servent
*);
104 extern char * __gnat_servent_s_alias (struct servent
*, int index
);
105 extern unsigned short __gnat_servent_s_port (struct servent
*);
106 extern char * __gnat_servent_s_proto (struct servent
*);
108 extern char * __gnat_hostent_h_name (struct hostent
*);
109 extern char * __gnat_hostent_h_alias (struct hostent
*, int);
110 extern int __gnat_hostent_h_addrtype (struct hostent
*);
111 extern int __gnat_hostent_h_length (struct hostent
*);
112 extern char * __gnat_hostent_h_addr (struct hostent
*, int);
114 #ifndef HAVE_INET_PTON
115 extern int __gnat_inet_pton (int, const char *, void *);
118 /* Disable the sending of SIGPIPE for writes on a broken stream */
121 __gnat_disable_sigpipe (int fd
)
125 (void) setsockopt (fd
, SOL_SOCKET
, SO_NOSIGPIPE
, &val
, sizeof val
);
130 __gnat_disable_all_sigpipes (void)
132 #if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) && defined(SIGPIPE)
133 (void) signal (SIGPIPE
, SIG_IGN
);
137 #if defined (_WIN32) || defined (__vxworks) || defined (VMS)
139 * Signalling FDs operations are implemented in Ada for these platforms
140 * (see subunit GNAT.Sockets.Thin.Signalling_Fds).
144 * Create a pair of connected file descriptors fds[0] and fds[1] used for
145 * signalling by a Selector object. fds[0] is the read end, and fds[1] the
149 __gnat_create_signalling_fds (int *fds
) {
154 * Read one byte of data from rsig, the read end of a pair of signalling fds
155 * created by __gnat_create_signalling_fds.
158 __gnat_read_signalling_fd (int rsig
) {
160 return read (rsig
, &c
, 1);
164 * Write one byte of data to wsig, the write end of a pair of signalling fds
165 * created by __gnat_create_signalling_fds.
168 __gnat_write_signalling_fd (int wsig
) {
170 return write (wsig
, &c
, 1);
174 * Close one end of a pair of signalling fds
177 __gnat_close_signalling_fd (int sig
) {
183 * Handling of gethostbyname, gethostbyaddr, getservbyname and getservbyport
184 * =========================================================================
186 * This module exposes __gnat_getXXXbyYYY operations with the same signature
187 * as the reentrant variant getXXXbyYYY_r.
189 * On platforms where getXXXbyYYY is intrinsically reentrant, the provided user
190 * buffer argument is ignored.
192 * When getXXXbyYYY is not reentrant but getXXXbyYYY_r exists, the latter is
193 * used, and the provided buffer argument must point to a valid, thread-local
194 * buffer (usually on the caller's stack).
196 * When getXXXbyYYY is not reentrant and no reentrant getXXXbyYYY_r variant
197 * is available, the non-reentrant getXXXbyYYY is called, the provided user
198 * buffer is ignored, and the caller is expected to take care of mutual
202 #ifdef HAVE_GETxxxBYyyy_R
204 __gnat_gethostbyname (const char *name
,
205 struct hostent
*ret
, char *buf
, size_t buflen
,
211 #if defined(__linux__) || defined(__GLIBC__)
212 (void) gethostbyname_r (name
, ret
, buf
, buflen
, &rh
, h_errnop
);
214 rh
= gethostbyname_r (name
, ret
, buf
, buflen
, h_errnop
);
216 ri
= (rh
== NULL
) ? -1 : 0;
221 __gnat_gethostbyaddr (const char *addr
, int len
, int type
,
222 struct hostent
*ret
, char *buf
, size_t buflen
,
228 #if defined(__linux__) || defined(__GLIBC__)
229 (void) gethostbyaddr_r (addr
, len
, type
, ret
, buf
, buflen
, &rh
, h_errnop
);
231 rh
= gethostbyaddr_r (addr
, len
, type
, ret
, buf
, buflen
, h_errnop
);
233 ri
= (rh
== NULL
) ? -1 : 0;
238 __gnat_getservbyname (const char *name
, const char *proto
,
239 struct servent
*ret
, char *buf
, size_t buflen
)
244 #if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
245 (void) getservbyname_r (name
, proto
, ret
, buf
, buflen
, &rh
);
247 rh
= getservbyname_r (name
, proto
, ret
, buf
, buflen
);
249 ri
= (rh
== NULL
) ? -1 : 0;
254 __gnat_getservbyport (int port
, const char *proto
,
255 struct servent
*ret
, char *buf
, size_t buflen
)
260 #if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
261 (void) getservbyport_r (port
, proto
, ret
, buf
, buflen
, &rh
);
263 rh
= getservbyport_r (port
, proto
, ret
, buf
, buflen
);
265 ri
= (rh
== NULL
) ? -1 : 0;
268 #elif defined (__vxworks)
269 static char vxw_h_name
[MAXHOSTNAMELEN
+ 1];
270 static char *vxw_h_aliases
[1] = { NULL
};
271 static int vxw_h_addr
;
272 static char *vxw_h_addr_list
[2] = { (char*) &vxw_h_addr
, NULL
};
275 __gnat_gethostbyname (const char *name
,
276 struct hostent
*ret
, char *buf
, size_t buflen
,
279 vxw_h_addr
= hostGetByName (name
);
280 if (vxw_h_addr
== ERROR
) {
281 *h_errnop
= __gnat_get_h_errno ();
285 ret
->h_aliases
= &vxw_h_aliases
;
286 ret
->h_addrtype
= AF_INET
;
288 ret
->h_addr_list
= &vxw_h_addr_list
;
293 __gnat_gethostbyaddr (const char *addr
, int len
, int type
,
294 struct hostent
*ret
, char *buf
, size_t buflen
,
297 if (type
!= AF_INET
) {
298 *h_errnop
= EAFNOSUPPORT
;
302 if (addr
== NULL
|| len
!= 4) {
307 if (hostGetByAddr (*(int*)addr
, &vxw_h_name
) != OK
) {
308 *h_errnop
= __gnat_get_h_errno ();
314 ret
->h_name
= &vxw_h_name
;
315 ret
->h_aliases
= &vxw_h_aliases
;
316 ret
->h_addrtype
= AF_INET
;
318 ret
->h_addr_list
= &vxw_h_addr_list
;
322 __gnat_getservbyname (const char *name
, const char *proto
,
323 struct servent
*ret
, char *buf
, size_t buflen
)
325 /* Not available under VxWorks */
330 __gnat_getservbyport (int port
, const char *proto
,
331 struct servent
*ret
, char *buf
, size_t buflen
)
333 /* Not available under VxWorks */
338 __gnat_gethostbyname (const char *name
,
339 struct hostent
*ret
, char *buf
, size_t buflen
,
343 rh
= gethostbyname (name
);
345 *h_errnop
= __gnat_get_h_errno ();
354 __gnat_gethostbyaddr (const char *addr
, int len
, int type
,
355 struct hostent
*ret
, char *buf
, size_t buflen
,
359 rh
= gethostbyaddr (addr
, len
, type
);
361 *h_errnop
= __gnat_get_h_errno ();
370 __gnat_getservbyname (const char *name
, const char *proto
,
371 struct servent
*ret
, char *buf
, size_t buflen
)
374 rh
= getservbyname (name
, proto
);
382 __gnat_getservbyport (int port
, const char *proto
,
383 struct servent
*ret
, char *buf
, size_t buflen
)
386 rh
= getservbyport (port
, proto
);
394 /* Find the largest socket in the socket set SET. This is needed for
395 `select'. LAST is the maximum value for the largest socket. This hint is
396 used to avoid scanning very large socket sets. On return, LAST is the
397 actual largest socket in the socket set. */
400 __gnat_last_socket_in_set (fd_set
*set
, int *last
)
407 /* More efficient method for NT. */
408 for (s
= 0; s
< set
->fd_count
; s
++)
409 if ((int) set
->fd_array
[s
] > l
)
410 l
= set
->fd_array
[s
];
414 for (s
= *last
; s
!= -1; s
--)
415 if (FD_ISSET (s
, set
))
425 /* Get last socket and remove it from the socket set SET. LAST is the
426 maximum value of the largest socket. This hint is used to avoid scanning
427 very large socket sets. On return, LAST is set to the actual largest
428 socket in the socket set. */
431 __gnat_get_socket_from_set (fd_set
*set
, int *last
, int *socket
)
434 FD_CLR (*socket
, set
);
435 __gnat_last_socket_in_set (set
, last
);
438 /* Insert SOCKET in the socket set SET. */
441 __gnat_insert_socket_in_set (fd_set
*set
, int socket
)
443 FD_SET (socket
, set
);
446 /* Check whether a given SOCKET is in the socket set SET. */
449 __gnat_is_socket_in_set (fd_set
*set
, int socket
)
451 return FD_ISSET (socket
, set
);
454 /* Remove SOCKET from the socket set SET. */
457 __gnat_remove_socket_from_set (fd_set
*set
, int socket
)
459 FD_CLR (socket
, set
);
464 __gnat_reset_socket_set (fd_set
*set
)
469 /* Get the value of the last host error */
472 __gnat_get_h_errno (void) {
474 int vxw_errno
= errno
;
480 #ifdef S_hostLib_HOST_NOT_FOUND
481 case S_hostLib_HOST_NOT_FOUND
:
483 case S_hostLib_UNKNOWN_HOST
:
484 return HOST_NOT_FOUND
;
486 #ifdef S_hostLib_TRY_AGAIN
487 case S_hostLib_TRY_AGAIN
:
491 #ifdef S_hostLib_NO_RECOVERY
492 case S_hostLib_NO_RECOVERY
:
494 #ifdef S_hostLib_NETDB_INTERNAL
495 case S_hostLib_NETDB_INTERNAL
:
497 case S_hostLib_INVALID_PARAMETER
:
505 /* h_errno is defined as follows in OpenVMS' version of <netdb.h>.
506 * However this header file is not available when building the GNAT
507 * runtime library using GCC, so we are hardcoding the definition
508 * directly. Note that the returned address is thread-specific.
510 extern int *decc$
h_errno_get_addr ();
511 return *decc$
h_errno_get_addr ();
513 #elif defined (__rtems__)
514 /* At this stage in the tool build, no networking .h files are available.
515 * Newlib does not provide networking .h files and RTEMS is not built yet.
516 * So we need to explicitly extern h_errno to access it.
526 /* Wrapper for ioctl(2), which is a variadic function */
529 __gnat_socket_ioctl (int fd
, int req
, int *arg
) {
531 return ioctlsocket (fd
, req
, arg
);
532 #elif defined (__APPLE__)
534 * On Darwin, req is an unsigned long, and we want to convert without sign
535 * extension to get the proper bit pattern in the case of a 64 bit kernel.
537 return ioctl (fd
, (unsigned int) req
, arg
);
539 return ioctl (fd
, req
, arg
);
543 #ifndef HAVE_INET_PTON
546 # define in_addr_t int
547 # define inet_addr decc$inet_addr
551 __gnat_inet_pton (int af
, const char *src
, void *dst
) {
553 #if defined (_WIN32) && defined (AF_INET6)
559 errno
= EAFNOSUPPORT
;
563 #if defined (__vxworks)
564 return (inet_aton (src
, dst
) == OK
);
566 #elif defined (_WIN32)
567 struct sockaddr_storage ss
;
568 int sslen
= sizeof ss
;
572 rc
= WSAStringToAddressA (src
, af
, NULL
, (struct sockaddr
*)&ss
, &sslen
);
576 *(struct in_addr
*)dst
= ((struct sockaddr_in
*)&ss
)->sin_addr
;
580 *(struct in6_addr
*)dst
= ((struct sockaddr_in6
*)&ss
)->sin6_addr
;
587 #elif defined (__hpux__) || defined (VMS)
591 if (src
== NULL
|| dst
== NULL
) {
594 } else if (!strcmp (src
, "255.255.255.255")) {
599 addr
= inet_addr (src
);
600 rc
= (addr
!= 0xffffffff);
603 *(in_addr_t
*)dst
= addr
;
611 * Accessor functions for struct hostent.
614 char * __gnat_hostent_h_name (struct hostent
* h
) {
618 char * __gnat_hostent_h_alias (struct hostent
* h
, int index
) {
619 return h
->h_aliases
[index
];
622 int __gnat_hostent_h_addrtype (struct hostent
* h
) {
623 return h
->h_addrtype
;
626 int __gnat_hostent_h_length (struct hostent
* h
) {
630 char * __gnat_hostent_h_addr (struct hostent
* h
, int index
) {
631 return h
->h_addr_list
[index
];
635 * Accessor functions for struct servent.
637 * These are needed because servent has different representations on different
638 * platforms, and we don't want to deal with that on the Ada side. For example,
639 * on Linux, we have (see /usr/include netdb.h):
649 * and on Windows (see mingw's socket.h):
665 __gnat_servent_s_name (struct servent
* s
)
671 __gnat_servent_s_alias (struct servent
* s
, int index
)
673 return s
->s_aliases
[index
];
677 __gnat_servent_s_port (struct servent
* s
)
683 __gnat_servent_s_proto (struct servent
* s
)
689 # warning Sockets are not supported on this platform
690 #endif /* defined(HAVE_SOCKETS) */