OSDN Git Service

PR ada/53766
[pf3gnuchains/gcc-fork.git] / gcc / ada / socket.c
1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                               S O C K E T                                *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *          Copyright (C) 2003-2010, Free Software Foundation, Inc.         *
10  *                                                                          *
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.                                     *
17  *                                                                          *
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.               *
21  *                                                                          *
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/>.                                          *
26  *                                                                          *
27  * GNAT was originally developed  by the GNAT team at  New York University. *
28  * Extensive contributions were provided by Ada Core Technologies Inc.      *
29  *                                                                          *
30  ****************************************************************************/
31
32 /*  This file provides a portable binding to the sockets API                */
33
34 #include "gsocket.h"
35
36 #ifdef VMS
37 /*
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.
42  */
43 # include "s-oscons.h"
44
45 /*
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.
50  */
51 typedef char *__netdb_char_ptr __attribute__ (( mode (SI) ));
52 typedef __netdb_char_ptr *__netdb_char_ptr_ptr __attribute__ (( mode (SI) ));
53
54 struct hostent {
55   __netdb_char_ptr     h_name;
56   __netdb_char_ptr_ptr h_aliases;
57   int                  h_addrtype;
58   int                  h_length;
59   __netdb_char_ptr_ptr h_addr_list;
60 };
61
62 struct servent {
63   __netdb_char_ptr     s_name;
64   __netdb_char_ptr_ptr s_aliases;
65   int                  s_port;
66   __netdb_char_ptr     s_proto;
67 };
68 #endif
69
70 #if defined(HAVE_SOCKETS)
71
72 /* Include all the necessary system-specific headers and define the
73  * necessary macros (shared with gen-oscons).
74  */
75
76 #if !defined(SO_NOSIGPIPE) && !defined (MSG_NOSIGNAL)
77 #include <signal.h>
78 #endif
79 /* Required if we will be calling signal() in __gnat_disable_all_sigpipes() */
80
81 #include "raise.h"
82 /* Required for __gnat_malloc() */
83
84 #include <string.h>
85 /* Required for memcpy() */
86
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 *);
102
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 *);
107
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);
113
114 #ifndef HAVE_INET_PTON
115 extern int  __gnat_inet_pton (int, const char *, void *);
116 #endif
117 \f
118 /* Disable the sending of SIGPIPE for writes on a broken stream */
119
120 void
121 __gnat_disable_sigpipe (int fd)
122 {
123 #ifdef SO_NOSIGPIPE
124   int val = 1;
125   (void) setsockopt (fd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof val);
126 #endif
127 }
128
129 void
130 __gnat_disable_all_sigpipes (void)
131 {
132 #if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL) && defined(SIGPIPE)
133   (void) signal (SIGPIPE, SIG_IGN);
134 #endif
135 }
136 \f
137 #if defined (_WIN32) || defined (__vxworks) || defined (VMS)
138 /*
139  * Signalling FDs operations are implemented in Ada for these platforms
140  * (see subunit GNAT.Sockets.Thin.Signalling_Fds).
141  */
142 #else
143 /*
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
146  * write end.
147  */
148 int
149 __gnat_create_signalling_fds (int *fds) {
150   return pipe (fds);
151 }
152 \f
153 /*
154  * Read one byte of data from rsig, the read end of a pair of signalling fds
155  * created by __gnat_create_signalling_fds.
156  */
157 int
158 __gnat_read_signalling_fd (int rsig) {
159   char c;
160   return read (rsig, &c, 1);
161 }
162 \f
163 /*
164  * Write one byte of data to wsig, the write end of a pair of signalling fds
165  * created by __gnat_create_signalling_fds.
166  */
167 int
168 __gnat_write_signalling_fd (int wsig) {
169   char c = 0;
170   return write (wsig, &c, 1);
171 }
172 \f
173 /*
174  * Close one end of a pair of signalling fds
175  */
176 void
177 __gnat_close_signalling_fd (int sig) {
178   (void) close (sig);
179 }
180 #endif
181 \f
182 /*
183  * Handling of gethostbyname, gethostbyaddr, getservbyname and getservbyport
184  * =========================================================================
185  *
186  * This module exposes __gnat_getXXXbyYYY operations with the same signature
187  * as the reentrant variant getXXXbyYYY_r.
188  *
189  * On platforms where getXXXbyYYY is intrinsically reentrant, the provided user
190  * buffer argument is ignored.
191  *
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).
195  *
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
199  * exclusion.
200  */
201
202 #ifdef HAVE_GETxxxBYyyy_R
203 int
204 __gnat_gethostbyname (const char *name,
205   struct hostent *ret, char *buf, size_t buflen,
206   int *h_errnop)
207 {
208   struct hostent *rh;
209   int ri;
210
211 #if defined(__linux__) || defined(__GLIBC__)
212   (void) gethostbyname_r (name, ret, buf, buflen, &rh, h_errnop);
213 #else
214   rh = gethostbyname_r (name, ret, buf, buflen, h_errnop);
215 #endif
216   ri = (rh == NULL) ? -1 : 0;
217   return ri;
218 }
219
220 int
221 __gnat_gethostbyaddr (const char *addr, int len, int type,
222   struct hostent *ret, char *buf, size_t buflen,
223   int *h_errnop)
224 {
225   struct hostent *rh;
226   int ri;
227
228 #if defined(__linux__) || defined(__GLIBC__)
229   (void) gethostbyaddr_r (addr, len, type, ret, buf, buflen, &rh, h_errnop);
230 #else
231   rh = gethostbyaddr_r (addr, len, type, ret, buf, buflen, h_errnop);
232 #endif
233   ri = (rh == NULL) ? -1 : 0;
234   return ri;
235 }
236
237 int
238 __gnat_getservbyname (const char *name, const char *proto,
239   struct servent *ret, char *buf, size_t buflen)
240 {
241   struct servent *rh;
242   int ri;
243
244 #if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
245   (void) getservbyname_r (name, proto, ret, buf, buflen, &rh);
246 #else
247   rh = getservbyname_r (name, proto, ret, buf, buflen);
248 #endif
249   ri = (rh == NULL) ? -1 : 0;
250   return ri;
251 }
252
253 int
254 __gnat_getservbyport (int port, const char *proto,
255   struct servent *ret, char *buf, size_t buflen)
256 {
257   struct servent *rh;
258   int ri;
259
260 #if defined(__linux__) || defined(__GLIBC__) || defined(__rtems__)
261   (void) getservbyport_r (port, proto, ret, buf, buflen, &rh);
262 #else
263   rh = getservbyport_r (port, proto, ret, buf, buflen);
264 #endif
265   ri = (rh == NULL) ? -1 : 0;
266   return ri;
267 }
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 };
273
274 int
275 __gnat_gethostbyname (const char *name,
276   struct hostent *ret, char *buf, size_t buflen,
277   int *h_errnop)
278 {
279   vxw_h_addr = hostGetByName (name);
280   if (vxw_h_addr == ERROR) {
281     *h_errnop = __gnat_get_h_errno ();
282     return -1;
283   }
284   ret->h_name      = name;
285   ret->h_aliases   = &vxw_h_aliases;
286   ret->h_addrtype  = AF_INET;
287   ret->h_length    = 4;
288   ret->h_addr_list = &vxw_h_addr_list;
289   return 0;
290 }
291
292 int
293 __gnat_gethostbyaddr (const char *addr, int len, int type,
294   struct hostent *ret, char *buf, size_t buflen,
295   int *h_errnop)
296 {
297   if (type != AF_INET) {
298     *h_errnop = EAFNOSUPPORT;
299     return -1;
300   }
301
302   if (addr == NULL || len != 4) {
303     *h_errnop = EINVAL;
304     return -1;
305   }
306
307   if (hostGetByAddr (*(int*)addr, &vxw_h_name) != OK) {
308     *h_errnop = __gnat_get_h_errno ();
309     return -1;
310   }
311
312   vxw_h_addr       = addr;
313
314   ret->h_name      = &vxw_h_name;
315   ret->h_aliases   = &vxw_h_aliases;
316   ret->h_addrtype  = AF_INET;
317   ret->h_length    = 4;
318   ret->h_addr_list = &vxw_h_addr_list;
319 }
320
321 int
322 __gnat_getservbyname (const char *name, const char *proto,
323   struct servent *ret, char *buf, size_t buflen)
324 {
325   /* Not available under VxWorks */
326   return -1;
327 }
328
329 int
330 __gnat_getservbyport (int port, const char *proto,
331   struct servent *ret, char *buf, size_t buflen)
332 {
333   /* Not available under VxWorks */
334   return -1;
335 }
336 #else
337 int
338 __gnat_gethostbyname (const char *name,
339   struct hostent *ret, char *buf, size_t buflen,
340   int *h_errnop)
341 {
342   struct hostent *rh;
343   rh = gethostbyname (name);
344   if (rh == NULL) {
345     *h_errnop = __gnat_get_h_errno ();
346     return -1;
347   }
348   *ret = *rh;
349   *h_errnop = 0;
350   return 0;
351 }
352
353 int
354 __gnat_gethostbyaddr (const char *addr, int len, int type,
355   struct hostent *ret, char *buf, size_t buflen,
356   int *h_errnop)
357 {
358   struct hostent *rh;
359   rh = gethostbyaddr (addr, len, type);
360   if (rh == NULL) {
361     *h_errnop = __gnat_get_h_errno ();
362     return -1;
363   }
364   *ret = *rh;
365   *h_errnop = 0;
366   return 0;
367 }
368
369 int
370 __gnat_getservbyname (const char *name, const char *proto,
371   struct servent *ret, char *buf, size_t buflen)
372 {
373   struct servent *rh;
374   rh = getservbyname (name, proto);
375   if (rh == NULL)
376     return -1;
377   *ret = *rh;
378   return 0;
379 }
380
381 int
382 __gnat_getservbyport (int port, const char *proto,
383   struct servent *ret, char *buf, size_t buflen)
384 {
385   struct servent *rh;
386   rh = getservbyport (port, proto);
387   if (rh == NULL)
388     return -1;
389   *ret = *rh;
390   return 0;
391 }
392 #endif
393 \f
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. */
398
399 void
400 __gnat_last_socket_in_set (fd_set *set, int *last)
401 {
402   int s;
403   int l;
404   l = -1;
405
406 #ifdef _WIN32
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];
411
412 #else
413
414   for (s = *last; s != -1; s--)
415     if (FD_ISSET (s, set))
416       {
417         l = s;
418         break;
419       }
420 #endif
421
422   *last = l;
423 }
424
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. */
429
430 void
431 __gnat_get_socket_from_set (fd_set *set, int *last, int *socket)
432 {
433   *socket = *last;
434   FD_CLR (*socket, set);
435   __gnat_last_socket_in_set (set, last);
436 }
437
438 /* Insert SOCKET in the socket set SET. */
439
440 void
441 __gnat_insert_socket_in_set (fd_set *set, int socket)
442 {
443   FD_SET (socket, set);
444 }
445
446 /* Check whether a given SOCKET is in the socket set SET. */
447
448 int
449 __gnat_is_socket_in_set (fd_set *set, int socket)
450 {
451   return FD_ISSET (socket, set);
452 }
453
454 /* Remove SOCKET from the socket set SET. */
455
456 void
457 __gnat_remove_socket_from_set (fd_set *set, int socket)
458 {
459   FD_CLR (socket, set);
460 }
461
462 /* Reset SET */
463 void
464 __gnat_reset_socket_set (fd_set *set)
465 {
466   FD_ZERO (set);
467 }
468
469 /* Get the value of the last host error */
470
471 int
472 __gnat_get_h_errno (void) {
473 #ifdef __vxworks
474   int vxw_errno = errno;
475
476   switch (vxw_errno) {
477     case 0:
478       return 0;
479
480 #ifdef S_hostLib_HOST_NOT_FOUND
481     case S_hostLib_HOST_NOT_FOUND:
482 #endif
483     case S_hostLib_UNKNOWN_HOST:
484       return HOST_NOT_FOUND;
485
486 #ifdef S_hostLib_TRY_AGAIN
487     case S_hostLib_TRY_AGAIN:
488       return TRY_AGAIN;
489 #endif
490
491 #ifdef S_hostLib_NO_RECOVERY
492     case S_hostLib_NO_RECOVERY:
493 #endif
494 #ifdef S_hostLib_NETDB_INTERNAL
495     case S_hostLib_NETDB_INTERNAL:
496 #endif
497     case S_hostLib_INVALID_PARAMETER:
498       return NO_RECOVERY;
499
500     default:
501       return -1;
502   }
503
504 #elif defined (VMS)
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.
509    */
510   extern int *decc$h_errno_get_addr ();
511   return *decc$h_errno_get_addr ();
512
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.
517    */
518   extern int h_errno;
519   return h_errno;
520
521 #else
522   return h_errno;
523 #endif
524 }
525
526 /* Wrapper for ioctl(2), which is a variadic function */
527
528 int
529 __gnat_socket_ioctl (int fd, int req, int *arg) {
530 #if defined (_WIN32)
531   return ioctlsocket (fd, req, arg);
532 #elif defined (__APPLE__)
533   /*
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.
536    */
537   return ioctl (fd, (unsigned int) req, arg);
538 #else
539   return ioctl (fd, req, arg);
540 #endif
541 }
542
543 #ifndef HAVE_INET_PTON
544
545 #ifdef VMS
546 # define in_addr_t int
547 # define inet_addr decc$inet_addr
548 #endif
549
550 int
551 __gnat_inet_pton (int af, const char *src, void *dst) {
552   switch (af) {
553 #if defined (_WIN32) && defined (AF_INET6)
554     case AF_INET6:
555 #endif
556     case AF_INET:
557       break;
558     default:
559       errno = EAFNOSUPPORT;
560       return -1;
561   }
562
563 #if defined (__vxworks)
564   return (inet_aton (src, dst) == OK);
565
566 #elif defined (_WIN32)
567   struct sockaddr_storage ss;
568   int sslen = sizeof ss;
569   int rc;
570
571   ss.ss_family = af;
572   rc = WSAStringToAddressA (src, af, NULL, (struct sockaddr *)&ss, &sslen);
573   if (rc == 0) {
574     switch (af) {
575       case AF_INET:
576         *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
577         break;
578 #ifdef AF_INET6
579       case AF_INET6:
580         *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
581         break;
582 #endif
583     }
584   }
585   return (rc == 0);
586
587 #elif defined (__hpux__) || defined (VMS)
588   in_addr_t addr;
589   int rc = -1;
590
591   if (src == NULL || dst == NULL) {
592     errno = EINVAL;
593
594   } else if (!strcmp (src, "255.255.255.255")) {
595     addr = 0xffffffff;
596     rc = 1;
597
598   } else {
599     addr = inet_addr (src);
600     rc = (addr != 0xffffffff);
601   }
602   if (rc == 1) {
603     *(in_addr_t *)dst = addr;
604   }
605   return rc;
606 #endif
607 }
608 #endif
609
610 /*
611  * Accessor functions for struct hostent.
612  */
613
614 char * __gnat_hostent_h_name (struct hostent * h) {
615   return h->h_name;
616 }
617
618 char * __gnat_hostent_h_alias (struct hostent * h, int index) {
619   return h->h_aliases[index];
620 }
621
622 int __gnat_hostent_h_addrtype (struct hostent * h) {
623   return h->h_addrtype;
624 }
625
626 int __gnat_hostent_h_length (struct hostent * h) {
627   return h->h_length;
628 }
629
630 char * __gnat_hostent_h_addr (struct hostent * h, int index) {
631   return h->h_addr_list[index];
632 }
633
634 /*
635  * Accessor functions for struct servent.
636  *
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):
640  *
641  *   struct servent
642  *   {
643  *     char *s_name;
644  *     char **s_aliases;
645  *     int s_port;
646  *     char *s_proto;
647  *   };
648  *
649  * and on Windows (see mingw's socket.h):
650  *
651  *   struct servent {
652  *     char *s_name;
653  *     char **s_aliases;
654  *   #ifdef _WIN64
655  *     char *s_proto;
656  *     short s_port;
657  *   #else
658  *     short s_port;
659  *     char *s_proto;
660  *   #endif
661  *   };
662  */
663
664 char *
665 __gnat_servent_s_name (struct servent * s)
666 {
667   return s->s_name;
668 }
669
670 char *
671 __gnat_servent_s_alias (struct servent * s, int index)
672 {
673   return s->s_aliases[index];
674 }
675
676 unsigned short
677 __gnat_servent_s_port (struct servent * s)
678 {
679   return s->s_port;
680 }
681
682 char *
683 __gnat_servent_s_proto (struct servent * s)
684 {
685   return s->s_proto;
686 }
687
688 #else
689 # warning Sockets are not supported on this platform
690 #endif /* defined(HAVE_SOCKETS) */