aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/socket.c')
-rw-r--r--gcc/ada/socket.c167
1 files changed, 160 insertions, 7 deletions
diff --git a/gcc/ada/socket.c b/gcc/ada/socket.c
index ed5b8df..7f2b5ff 100644
--- a/gcc/ada/socket.c
+++ b/gcc/ada/socket.c
@@ -90,10 +90,27 @@ extern int __gnat_hostent_h_addrtype (struct hostent *);
extern int __gnat_hostent_h_length (struct hostent *);
extern char * __gnat_hostent_h_addr (struct hostent *, int);
+extern int __gnat_getaddrinfo(
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+int __gnat_getnameinfo(
+ const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags);
+extern void __gnat_freeaddrinfo(struct addrinfo *res);
+extern const char * __gnat_gai_strerror(int errcode);
+
#ifndef HAVE_INET_PTON
extern int __gnat_inet_pton (int, const char *, void *);
#endif
-
+
+#ifndef HAVE_INET_NTOP
+extern const char *
+__gnat_inet_ntop(int, const void *, char *, socklen_t);
+#endif
+
/* Disable the sending of SIGPIPE for writes on a broken stream */
void
@@ -112,7 +129,7 @@ __gnat_disable_all_sigpipes (void)
(void) signal (SIGPIPE, SIG_IGN);
#endif
}
-
+
#if defined (_WIN32) || defined (__vxworks)
/*
* Signalling FDs operations are implemented in Ada for these platforms
@@ -128,7 +145,7 @@ int
__gnat_create_signalling_fds (int *fds) {
return pipe (fds);
}
-
+
/*
* Read one byte of data from rsig, the read end of a pair of signalling fds
* created by __gnat_create_signalling_fds.
@@ -138,7 +155,7 @@ __gnat_read_signalling_fd (int rsig) {
char c;
return read (rsig, &c, 1);
}
-
+
/*
* Write one byte of data to wsig, the write end of a pair of signalling fds
* created by __gnat_create_signalling_fds.
@@ -148,7 +165,7 @@ __gnat_write_signalling_fd (int wsig) {
char c = 0;
return write (wsig, &c, 1);
}
-
+
/*
* Close one end of a pair of signalling fds
*/
@@ -157,7 +174,7 @@ __gnat_close_signalling_fd (int sig) {
(void) close (sig);
}
#endif
-
+
/*
* Handling of gethostbyname, gethostbyaddr, getservbyname and getservbyport
* =========================================================================
@@ -369,7 +386,7 @@ __gnat_getservbyport (int port, const char *proto,
return 0;
}
#endif
-
+
/* Find the largest socket in the socket set SET. This is needed for
`select'. LAST is the maximum value for the largest socket. This hint is
used to avoid scanning very large socket sets. On return, LAST is the
@@ -572,6 +589,41 @@ __gnat_inet_pton (int af, const char *src, void *dst) {
}
#endif
+#ifndef HAVE_INET_NTOP
+
+const char *
+__gnat_inet_ntop(int af, const void *src, char *dst, socklen_t size)
+{
+#ifdef _WIN32
+ struct sockaddr_storage ss;
+ int sslen = sizeof ss;
+ memset(&ss, 0, sslen);
+ ss.ss_family = af;
+
+ switch (af) {
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
+ break;
+ case AF_INET:
+ ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ DWORD sz = size;
+
+ if (WSAAddressToStringA((struct sockaddr*)&ss, sslen, 0, dst, &sz) != 0) {
+ return NULL;
+ }
+ return dst;
+#else
+ return NULL;
+#endif
+}
+#endif
+
/*
* Accessor functions for struct hostent.
*/
@@ -650,4 +702,105 @@ __gnat_servent_s_proto (struct servent * s)
return s->s_proto;
}
+#if defined(AF_INET6) && !defined(__rtems__)
+
+#if defined (__vxworks)
+#define getaddrinfo ipcom_getaddrinfo
+#define getnameinfo ipcom_getnameinfo
+#define freeaddrinfo ipcom_freeaddrinfo
+#endif
+
+int __gnat_getaddrinfo(
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ return getaddrinfo(node, service, hints, res);
+}
+
+int __gnat_getnameinfo(
+ const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+
+void __gnat_freeaddrinfo(struct addrinfo *res) {
+ freeaddrinfo(res);
+}
+
+const char * __gnat_gai_strerror(int errcode) {
+#if defined(_WIN32) || defined(__vxworks)
+ // gai_strerror thread usafe on Windows and is not available on some vxWorks
+ // versions
+
+ switch (errcode) {
+ case EAI_AGAIN:
+ return "Temporary failure in name resolution.";
+ case EAI_BADFLAGS:
+ return "Invalid value for ai_flags.";
+ case EAI_FAIL:
+ return "Nonrecoverable failure in name resolution.";
+ case EAI_FAMILY:
+ return "The ai_family member is not supported.";
+ case EAI_MEMORY:
+ return "Memory allocation failure.";
+#ifdef EAI_NODATA
+ // Could be not defined under the vxWorks
+ case EAI_NODATA:
+ return "No address associated with nodename.";
+#endif
+#if EAI_NODATA != EAI_NONAME
+ /* with mingw64 runtime EAI_NODATA and EAI_NONAME have the same value.
+ This applies to both win32 and win64 */
+ case EAI_NONAME:
+ return "Neither nodename nor servname provided, or not known.";
+#endif
+ case EAI_SERVICE:
+ return "The servname parameter is not supported for ai_socktype.";
+ case EAI_SOCKTYPE:
+ return "The ai_socktype member is not supported.";
+#ifdef EAI_SYSTEM
+ // Could be not defined, at least on Windows
+ case EAI_SYSTEM:
+ return "System error returned in errno";
+#endif
+ default:
+ return "Unknown error.";
+ }
+#else
+ return gai_strerror(errcode);
+#endif
+}
+
+#else
+
+int __gnat_getaddrinfo(
+ const char *node,
+ const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ return -1;
+}
+
+int __gnat_getnameinfo(
+ const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen, int flags)
+{
+ return -1;
+}
+
+void __gnat_freeaddrinfo(struct addrinfo *res) {
+}
+
+const char * __gnat_gai_strerror(int errcode) {
+ return "getaddinfo functions family is not supported";
+}
+
+#endif
+
#endif /* defined(HAVE_SOCKETS) */