net_db.c doesn't import winsock2.h
[bpt/guile.git] / libguile / net_db.c
1 /* "net_db.c" network database support
2 * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2006, 2009,
3 * 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7 * as published by the Free Software Foundation; either version 3 of
8 * the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
21
22
23 /* Written in 1994 by Aubrey Jaffer.
24 * Thanks to Hallvard.Tretteberg@si.sintef.no for inspiration and discussion.
25 * Rewritten by Gary Houston to be a closer interface to the C socket library.
26 * Split into net_db.c and socket.c.
27 */
28 \f
29
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33
34 #include <verify.h>
35 #include <errno.h>
36
37 #include "libguile/_scm.h"
38 #include "libguile/feature.h"
39 #include "libguile/strings.h"
40 #include "libguile/vectors.h"
41 #include "libguile/dynwind.h"
42
43 #include "libguile/validate.h"
44 #include "libguile/net_db.h"
45 #include "libguile/socket.h"
46
47 #ifdef HAVE_STRING_H
48 #include <string.h>
49 #endif
50
51 #include <sys/types.h>
52
53 #include <sys/socket.h>
54 #include <netdb.h>
55 #include <netinet/in.h>
56 #include <arpa/inet.h>
57
58 #ifdef __MINGW32__
59 #include "win32-socket.h"
60 #endif
61
62 #if !defined (HAVE_H_ERRNO) && !defined (__MINGW32__) && !defined (__CYGWIN__)
63 /* h_errno not found in netdb.h, maybe this will help. */
64 extern int h_errno;
65 #endif
66
67 #if defined HAVE_HSTRERROR && !HAVE_DECL_HSTRERROR \
68 && !defined __MINGW32__ && !defined __CYGWIN__
69 /* Some OSes, such as Tru64 5.1b, lack a declaration for hstrerror(3). */
70 extern const char *hstrerror (int);
71 #endif
72
73 \f
74
75 SCM_SYMBOL (scm_host_not_found_key, "host-not-found");
76 SCM_SYMBOL (scm_try_again_key, "try-again");
77 SCM_SYMBOL (scm_no_recovery_key, "no-recovery");
78 SCM_SYMBOL (scm_no_data_key, "no-data");
79
80 static void scm_resolv_error (const char *subr, SCM bad_value)
81 {
82 #ifdef NETDB_INTERNAL
83 if (h_errno == NETDB_INTERNAL)
84 {
85 /* errno supposedly contains a useful value. */
86 scm_syserror (subr);
87 }
88 else
89 #endif
90 {
91 SCM key;
92 const char *errmsg;
93
94 switch (h_errno)
95 {
96 case HOST_NOT_FOUND:
97 key = scm_host_not_found_key;
98 errmsg = "Unknown host";
99 break;
100 case TRY_AGAIN:
101 key = scm_try_again_key;
102 errmsg = "Host name lookup failure";
103 break;
104 case NO_RECOVERY:
105 key = scm_no_recovery_key;
106 errmsg = "Unknown server error";
107 break;
108 case NO_DATA:
109 key = scm_no_data_key;
110 errmsg = "No address associated with name";
111 break;
112 default:
113 scm_misc_error (subr, "Unknown resolver error", SCM_EOL);
114 errmsg = NULL;
115 }
116
117 #ifdef HAVE_HSTRERROR
118 errmsg = (const char *) hstrerror (h_errno);
119 #endif
120 scm_error (key, subr, errmsg, SCM_BOOL_F, SCM_EOL);
121 }
122 }
123
124 /* Should take an extra arg for address format (will be needed for IPv6).
125 Should use reentrant facilities if available.
126 */
127
128 SCM_DEFINE (scm_gethost, "gethost", 0, 1, 0,
129 (SCM host),
130 "@deffnx {Scheme Procedure} gethostbyname hostname\n"
131 "@deffnx {Scheme Procedure} gethostbyaddr address\n"
132 "Look up a host by name or address, returning a host object. The\n"
133 "@code{gethost} procedure will accept either a string name or an integer\n"
134 "address; if given no arguments, it behaves like @code{gethostent} (see\n"
135 "below). If a name or address is supplied but the address can not be\n"
136 "found, an error will be thrown to one of the keys:\n"
137 "@code{host-not-found}, @code{try-again}, @code{no-recovery} or\n"
138 "@code{no-data}, corresponding to the equivalent @code{h_error} values.\n"
139 "Unusual conditions may result in errors thrown to the\n"
140 "@code{system-error} or @code{misc_error} keys.")
141 #define FUNC_NAME s_scm_gethost
142 {
143 SCM result = scm_c_make_vector (5, SCM_UNSPECIFIED);
144 SCM lst = SCM_EOL;
145 struct hostent *entry;
146 struct in_addr inad;
147 char **argv;
148 int i = 0;
149
150 if (SCM_UNBNDP (host))
151 {
152 #ifdef HAVE_GETHOSTENT
153 entry = gethostent ();
154 #else
155 entry = NULL;
156 #endif
157 if (! entry)
158 {
159 /* As far as I can tell, there's no good way to tell whether
160 zero means an error or end-of-file. The trick of
161 clearing errno before calling gethostent and checking it
162 afterwards doesn't cut it, because, on Linux, it seems to
163 try to contact some other server (YP?) and fails, which
164 is a benign failure. */
165 return SCM_BOOL_F;
166 }
167 }
168 else if (scm_is_string (host))
169 {
170 char *str = scm_to_locale_string (host);
171 entry = gethostbyname (str);
172 free (str);
173 }
174 else
175 {
176 inad.s_addr = htonl (scm_to_ulong (host));
177 entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
178 }
179
180 if (!entry)
181 scm_resolv_error (FUNC_NAME, host);
182
183 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->h_name));
184 SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->h_aliases));
185 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_int (entry->h_addrtype));
186 SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_int (entry->h_length));
187 if (sizeof (struct in_addr) != entry->h_length)
188 {
189 SCM_SIMPLE_VECTOR_SET(result, 4, SCM_BOOL_F);
190 return result;
191 }
192 for (argv = entry->h_addr_list; argv[i]; i++);
193 while (i--)
194 {
195 inad = *(struct in_addr *) argv[i];
196 lst = scm_cons (scm_from_ulong (ntohl (inad.s_addr)), lst);
197 }
198 SCM_SIMPLE_VECTOR_SET(result, 4, lst);
199 return result;
200 }
201 #undef FUNC_NAME
202
203
204 /* In all subsequent getMUMBLE functions, when we're called with no
205 arguments, we're supposed to traverse the tables entry by entry.
206 However, there doesn't seem to be any documented way to distinguish
207 between end-of-table and an error; in both cases the functions
208 return zero. Gotta love Unix. For the time being, we clear errno,
209 and if we get a zero and errno is set, we signal an error. This
210 doesn't seem quite right (what if errno gets set as part of healthy
211 operation?), but it seems to work okay. We'll see. */
212
213 #if defined(HAVE_GETNETENT) && defined(HAVE_GETNETBYNAME) && defined(HAVE_GETNETBYADDR)
214 SCM_DEFINE (scm_getnet, "getnet", 0, 1, 0,
215 (SCM net),
216 "@deffnx {Scheme Procedure} getnetbyname net-name\n"
217 "@deffnx {Scheme Procedure} getnetbyaddr net-number\n"
218 "Look up a network by name or net number in the network database. The\n"
219 "@var{net-name} argument must be a string, and the @var{net-number}\n"
220 "argument must be an integer. @code{getnet} will accept either type of\n"
221 "argument, behaving like @code{getnetent} (see below) if no arguments are\n"
222 "given.")
223 #define FUNC_NAME s_scm_getnet
224 {
225 SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
226 struct netent *entry;
227 int eno;
228
229 if (SCM_UNBNDP (net))
230 {
231 entry = getnetent ();
232 if (! entry)
233 {
234 /* There's no good way to tell whether zero means an error
235 or end-of-file, so we always return #f. See `gethost'
236 for details. */
237 return SCM_BOOL_F;
238 }
239 }
240 else if (scm_is_string (net))
241 {
242 char *str = scm_to_locale_string (net);
243 entry = getnetbyname (str);
244 eno = errno;
245 free (str);
246 }
247 else
248 {
249 unsigned long netnum = scm_to_ulong (net);
250 entry = getnetbyaddr (netnum, AF_INET);
251 eno = errno;
252 }
253
254 if (!entry)
255 SCM_SYSERROR_MSG ("no such network ~A", scm_list_1 (net), eno);
256
257 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->n_name));
258 SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->n_aliases));
259 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_int (entry->n_addrtype));
260 SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_ulong (entry->n_net));
261 return result;
262 }
263 #undef FUNC_NAME
264 #endif
265
266 #if defined (HAVE_GETPROTOENT) || defined (__MINGW32__)
267 SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
268 (SCM protocol),
269 "@deffnx {Scheme Procedure} getprotobyname name\n"
270 "@deffnx {Scheme Procedure} getprotobynumber number\n"
271 "Look up a network protocol by name or by number. @code{getprotobyname}\n"
272 "takes a string argument, and @code{getprotobynumber} takes an integer\n"
273 "argument. @code{getproto} will accept either type, behaving like\n"
274 "@code{getprotoent} (see below) if no arguments are supplied.")
275 #define FUNC_NAME s_scm_getproto
276 {
277 SCM result = scm_c_make_vector (3, SCM_UNSPECIFIED);
278 struct protoent *entry;
279 int eno;
280
281 if (SCM_UNBNDP (protocol))
282 {
283 entry = getprotoent ();
284 if (! entry)
285 {
286 /* There's no good way to tell whether zero means an error
287 or end-of-file, so we always return #f. See `gethost'
288 for details. */
289 return SCM_BOOL_F;
290 }
291 }
292 else if (scm_is_string (protocol))
293 {
294 char *str = scm_to_locale_string (protocol);
295 entry = getprotobyname (str);
296 eno = errno;
297 free (str);
298 }
299 else
300 {
301 unsigned long protonum = scm_to_ulong (protocol);
302 entry = getprotobynumber (protonum);
303 eno = errno;
304 }
305
306 if (!entry)
307 SCM_SYSERROR_MSG ("no such protocol ~A", scm_list_1 (protocol), eno);
308
309 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->p_name));
310 SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->p_aliases));
311 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_int (entry->p_proto));
312 return result;
313 }
314 #undef FUNC_NAME
315 #endif
316
317 #if defined (HAVE_GETSERVENT) || defined (__MINGW32__)
318 static SCM
319 scm_return_entry (struct servent *entry)
320 {
321 SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
322
323 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_locale_string (entry->s_name));
324 SCM_SIMPLE_VECTOR_SET(result, 1, scm_makfromstrs (-1, entry->s_aliases));
325 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_uint16 (ntohs (entry->s_port)));
326 SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_locale_string (entry->s_proto));
327 return result;
328 }
329
330 SCM_DEFINE (scm_getserv, "getserv", 0, 2, 0,
331 (SCM name, SCM protocol),
332 "@deffnx {Scheme Procedure} getservbyname name protocol\n"
333 "@deffnx {Scheme Procedure} getservbyport port protocol\n"
334 "Look up a network service by name or by service number, and return a\n"
335 "network service object. The @var{protocol} argument specifies the name\n"
336 "of the desired protocol; if the protocol found in the network service\n"
337 "database does not match this name, a system error is signalled.\n\n"
338 "The @code{getserv} procedure will take either a service name or number\n"
339 "as its first argument; if given no arguments, it behaves like\n"
340 "@code{getservent} (see below).")
341 #define FUNC_NAME s_scm_getserv
342 {
343 struct servent *entry;
344 char *protoname;
345 int eno;
346
347 if (SCM_UNBNDP (name))
348 {
349 entry = getservent ();
350 if (!entry)
351 {
352 /* There's no good way to tell whether zero means an error
353 or end-of-file, so we always return #f. See `gethost'
354 for details. */
355 return SCM_BOOL_F;
356 }
357 return scm_return_entry (entry);
358 }
359
360 scm_dynwind_begin (0);
361
362 protoname = scm_to_locale_string (protocol);
363 scm_dynwind_free (protoname);
364
365 if (scm_is_string (name))
366 {
367 char *str = scm_to_locale_string (name);
368 entry = getservbyname (str, protoname);
369 eno = errno;
370 free (str);
371 }
372 else
373 {
374 entry = getservbyport (htons (scm_to_int (name)), protoname);
375 eno = errno;
376 }
377
378 if (!entry)
379 SCM_SYSERROR_MSG("no such service ~A", scm_list_1 (name), eno);
380
381 scm_dynwind_end ();
382 return scm_return_entry (entry);
383 }
384 #undef FUNC_NAME
385 #endif
386
387 #if defined(HAVE_SETHOSTENT) && defined(HAVE_ENDHOSTENT)
388 SCM_DEFINE (scm_sethost, "sethost", 0, 1, 0,
389 (SCM stayopen),
390 "If @var{stayopen} is omitted, this is equivalent to @code{endhostent}.\n"
391 "Otherwise it is equivalent to @code{sethostent stayopen}.")
392 #define FUNC_NAME s_scm_sethost
393 {
394 if (SCM_UNBNDP (stayopen))
395 endhostent ();
396 else
397 sethostent (scm_is_true (stayopen));
398 return SCM_UNSPECIFIED;
399 }
400 #undef FUNC_NAME
401 #endif
402
403 #if defined(HAVE_SETNETENT) && defined(HAVE_ENDNETENT)
404 SCM_DEFINE (scm_setnet, "setnet", 0, 1, 0,
405 (SCM stayopen),
406 "If @var{stayopen} is omitted, this is equivalent to @code{endnetent}.\n"
407 "Otherwise it is equivalent to @code{setnetent stayopen}.")
408 #define FUNC_NAME s_scm_setnet
409 {
410 if (SCM_UNBNDP (stayopen))
411 endnetent ();
412 else
413 setnetent (scm_is_true (stayopen));
414 return SCM_UNSPECIFIED;
415 }
416 #undef FUNC_NAME
417 #endif
418
419 #if defined (HAVE_SETPROTOENT) && defined (HAVE_ENDPROTOENT) || defined (__MINGW32__)
420 SCM_DEFINE (scm_setproto, "setproto", 0, 1, 0,
421 (SCM stayopen),
422 "If @var{stayopen} is omitted, this is equivalent to @code{endprotoent}.\n"
423 "Otherwise it is equivalent to @code{setprotoent stayopen}.")
424 #define FUNC_NAME s_scm_setproto
425 {
426 if (SCM_UNBNDP (stayopen))
427 endprotoent ();
428 else
429 setprotoent (scm_is_true (stayopen));
430 return SCM_UNSPECIFIED;
431 }
432 #undef FUNC_NAME
433 #endif
434
435 #if defined (HAVE_SETSERVENT) && defined (HAVE_ENDSERVENT) || defined (__MINGW32__)
436 SCM_DEFINE (scm_setserv, "setserv", 0, 1, 0,
437 (SCM stayopen),
438 "If @var{stayopen} is omitted, this is equivalent to @code{endservent}.\n"
439 "Otherwise it is equivalent to @code{setservent stayopen}.")
440 #define FUNC_NAME s_scm_setserv
441 {
442 if (SCM_UNBNDP (stayopen))
443 endservent ();
444 else
445 setservent (scm_is_true (stayopen));
446 return SCM_UNSPECIFIED;
447 }
448 #undef FUNC_NAME
449 #endif
450
451 \f
452 /* Protocol-independent name resolution with getaddrinfo(3) & co. */
453
454 SCM_SYMBOL (sym_getaddrinfo_error, "getaddrinfo-error");
455
456 /* Make sure the `AI_*' flags can be stored as INUMs. */
457 verify (AI_ALL < SCM_MOST_POSITIVE_FIXNUM);
458
459 /* Valid values for the `ai_flags' to `struct addrinfo'. */
460 SCM_VARIABLE_INIT (sym_ai_passive, "AI_PASSIVE",
461 SCM_I_MAKINUM (AI_PASSIVE));
462 SCM_VARIABLE_INIT (sym_ai_canonname, "AI_CANONNAME",
463 SCM_I_MAKINUM (AI_CANONNAME));
464 SCM_VARIABLE_INIT (sym_ai_numerichost, "AI_NUMERICHOST",
465 SCM_I_MAKINUM (AI_NUMERICHOST));
466 SCM_VARIABLE_INIT (sym_ai_numericserv, "AI_NUMERICSERV",
467 SCM_I_MAKINUM (AI_NUMERICSERV));
468 SCM_VARIABLE_INIT (sym_ai_v4mapped, "AI_V4MAPPED",
469 SCM_I_MAKINUM (AI_V4MAPPED));
470 SCM_VARIABLE_INIT (sym_ai_all, "AI_ALL",
471 SCM_I_MAKINUM (AI_ALL));
472 SCM_VARIABLE_INIT (sym_ai_addrconfig, "AI_ADDRCONFIG",
473 SCM_I_MAKINUM (AI_ADDRCONFIG));
474
475 /* Return a Scheme vector whose elements correspond to the fields of C_AI,
476 ignoring the `ai_next' field. This function is not exported because the
477 definition of `struct addrinfo' is provided by Gnulib. */
478 static SCM
479 scm_from_addrinfo (const struct addrinfo *c_ai)
480 {
481 SCM ai;
482
483 /* Note: The indices here must be kept synchronized with those used by the
484 `addrinfo:' procedures in `networking.scm'. */
485
486 ai = scm_c_make_vector (6, SCM_UNDEFINED);
487 SCM_SIMPLE_VECTOR_SET (ai, 0, scm_from_int (c_ai->ai_flags));
488 SCM_SIMPLE_VECTOR_SET (ai, 1, scm_from_int (c_ai->ai_family));
489 SCM_SIMPLE_VECTOR_SET (ai, 2, scm_from_int (c_ai->ai_socktype));
490 SCM_SIMPLE_VECTOR_SET (ai, 3, scm_from_int (c_ai->ai_protocol));
491 SCM_SIMPLE_VECTOR_SET (ai, 4,
492 scm_from_sockaddr (c_ai->ai_addr, c_ai->ai_addrlen));
493 SCM_SIMPLE_VECTOR_SET (ai, 5,
494 c_ai->ai_canonname != NULL
495 ? scm_from_locale_string (c_ai->ai_canonname)
496 : SCM_BOOL_F);
497
498 return ai;
499 }
500
501 SCM_DEFINE (scm_getaddrinfo, "getaddrinfo", 1, 5, 0,
502 (SCM name, SCM service, SCM hint_flags, SCM hint_family,
503 SCM hint_socktype, SCM hint_protocol),
504 "Return a list of @code{addrinfo} structures containing "
505 "a socket address and associated information for host @var{name} "
506 "and/or @var{service} to be used in creating a socket with "
507 "which to address the specified service.\n\n"
508 "@example\n"
509 "(let* ((ai (car (getaddrinfo \"www.gnu.org\" \"http\")))\n"
510 " (s (socket (addrinfo:fam ai) (addrinfo:socktype ai)\n"
511 " (addrinfo:protocol ai))))\n"
512 " (connect s (addrinfo:addr ai))\n"
513 " s)\n"
514 "@end example\n\n"
515 "When @var{service} is omitted or is @code{#f}, return "
516 "network-level addresses for @var{name}. When @var{name} "
517 "is @code{#f} @var{service} must be provided and service "
518 "locations local to the caller are returned.\n"
519 "\n"
520 "Additional hints can be provided. When specified, "
521 "@var{hint_flags} should be a bitwise-or of zero or more "
522 "constants among the following:\n\n"
523 "@table @code\n"
524 "@item AI_PASSIVE\n"
525 "Socket address is intended for @code{bind}.\n\n"
526 "@item AI_CANONNAME\n"
527 "Request for canonical host name, available via "
528 "@code{addrinfo:canonname}. This makes sense mainly when "
529 "DNS lookups are involved.\n\n"
530 "@item AI_NUMERICHOST\n"
531 "Specifies that @var{name} is a numeric host address string "
532 "(e.g., @code{\"127.0.0.1\"}), meaning that name resolution "
533 "will not be used.\n\n"
534 "@item AI_NUMERICSERV\n"
535 "Likewise, specifies that @var{service} is a numeric port "
536 "string (e.g., @code{\"80\"}).\n\n"
537 "@item AI_ADDRCONFIG\n"
538 "Return only addresses configured on the local system. It is "
539 "highly recommended to provide this flag when the returned "
540 "socket addresses are to be used to make connections; "
541 "otherwise, some of the returned addresses could be unreachable "
542 "or use a protocol that is not supported.\n\n"
543 "@item AI_V4MAPPED\n"
544 "When looking up IPv6 addresses, return mapped "
545 "IPv4 addresses if there is no IPv6 address available at all.\n\n"
546 "@item AI_ALL\n"
547 "If this flag is set along with @code{AI_V4MAPPED} when looking "
548 "up IPv6 addresses, return all IPv6 addresses "
549 "as well as all IPv4 addresses, the latter mapped to IPv6 "
550 "format.\n"
551 "@end table\n\n"
552 "When given, @var{hint_family} should specify the requested "
553 "address family, e.g., @code{AF_INET6}. Similarly, "
554 "@var{hint_socktype} should specify the requested socket type "
555 "(e.g., @code{SOCK_DGRAM}), and @var{hint_protocol} should "
556 "specify the requested protocol (its value is interpretered "
557 "as in calls to @code{socket}).\n"
558 "\n"
559 "On error, an exception with key @code{getaddrinfo-error} is "
560 "thrown, with an error code (an integer) as its argument:\n\n"
561 "@example\n"
562 "(catch 'getaddrinfo-error\n"
563 " (lambda ()\n"
564 " (getaddrinfo \"www.gnu.org\" \"gopher\"))\n"
565 " (lambda (key errcode)\n"
566 " (cond ((= errcode EAI_SERVICE)\n"
567 " (display \"doesn't know about Gopher!\\n\"))\n"
568 " ((= errcode EAI_NONAME)\n"
569 " (display \"www.gnu.org not found\\n\"))\n"
570 " (else\n"
571 " (format #t \"something wrong: ~a\\n\"\n"
572 " (gai-strerror errcode))))))\n"
573 "@end example\n"
574 "\n"
575 "Error codes are:\n\n"
576 "@table @code\n"
577 "@item EAI_AGAIN\n"
578 "The name or service could not be resolved at this time. Future "
579 "attempts may succeed.\n\n"
580 "@item EAI_BADFLAGS\n"
581 "@var{hint_flags} contains an invalid value.\n\n"
582 "@item EAI_FAIL\n"
583 "A non-recoverable error occurred when attempting to "
584 "resolve the name.\n\n"
585 "@item EAI_FAMILY\n"
586 "@var{hint_family} was not recognized.\n\n"
587 "@item EAI_NONAME\n"
588 "Either @var{name} does not resolve for the supplied parameters, "
589 "or neither @var{name} nor @var{service} were supplied.\n\n"
590
591 /* See `sysdeps/posix/getaddrinfo.c' in the GNU libc, and
592 <http://www.opensource.apple.com/source/Libinfo/Libinfo-324.1/lookup.subproj/netdb.h>,
593 for details on EAI_NODATA. */
594 "@item EAI_NODATA\n"
595 "This non-POSIX error code can be returned on some systems (GNU "
596 "and Darwin, at least), for example when @var{name} is known "
597 "but requests that were made turned out no data. Error handling\n"
598 "code should be prepared to handle it when it is defined.\n\n"
599 "@item EAI_SERVICE\n"
600 "@var{service} was not recognized for the specified socket type.\n\n"
601 "@item EAI_SOCKTYPE\n"
602 "@var{hint_socktype} was not recognized.\n\n"
603 "@item EAI_SYSTEM\n"
604 "A system error occurred; the error code can be found in "
605 "@code{errno}.\n"
606 "@end table\n"
607 "\n"
608 "Users are encouraged to read the "
609 "@url{http://www.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html,"
610 "POSIX specification} for more details.\n")
611 #define FUNC_NAME s_scm_getaddrinfo
612 {
613 int err;
614 char *c_name, *c_service;
615 struct addrinfo c_hints, *c_result;
616 SCM result = SCM_EOL;
617
618 if (scm_is_true (name))
619 SCM_VALIDATE_STRING (SCM_ARG1, name);
620
621 if (!SCM_UNBNDP (service) && scm_is_true (service))
622 SCM_VALIDATE_STRING (SCM_ARG2, service);
623
624 scm_dynwind_begin (0);
625
626 if (scm_is_string (name))
627 {
628 c_name = scm_to_locale_string (name);
629 scm_dynwind_free (c_name);
630 }
631 else
632 c_name = NULL;
633
634 if (scm_is_string (service))
635 {
636 c_service = scm_to_locale_string (service);
637 scm_dynwind_free (c_service);
638 }
639 else
640 c_service = NULL;
641
642 memset (&c_hints, 0, sizeof (c_hints));
643 if (!SCM_UNBNDP (hint_flags))
644 {
645 c_hints.ai_flags = scm_to_int (hint_flags);
646 if (!SCM_UNBNDP (hint_family))
647 {
648 c_hints.ai_family = scm_to_int (hint_family);
649 if (!SCM_UNBNDP (hint_socktype))
650 {
651 c_hints.ai_socktype = scm_to_int (hint_socktype);
652 if (!SCM_UNBNDP (hint_family))
653 c_hints.ai_family = scm_to_int (hint_family);
654 }
655 }
656 }
657
658 err = getaddrinfo (c_name, c_service, &c_hints, &c_result);
659 if (err == 0)
660 {
661 SCM *prev_addr;
662 struct addrinfo *a;
663
664 for (prev_addr = &result, a = c_result;
665 a != NULL;
666 a = a->ai_next, prev_addr = SCM_CDRLOC (*prev_addr))
667 *prev_addr = scm_list_1 (scm_from_addrinfo (a));
668
669 freeaddrinfo (c_result);
670 }
671 else
672 scm_throw (sym_getaddrinfo_error, scm_list_1 (scm_from_int (err)));
673
674 scm_dynwind_end ();
675
676 return result;
677 }
678 #undef FUNC_NAME
679
680 /* Make sure the `EAI_*' flags can be stored as INUMs. */
681 verify (EAI_BADFLAGS < SCM_MOST_POSITIVE_FIXNUM);
682
683 /* Error codes returned by `getaddrinfo'. */
684 SCM_VARIABLE_INIT (sym_eai_badflags, "EAI_BADFLAGS",
685 SCM_I_MAKINUM (EAI_BADFLAGS));
686 SCM_VARIABLE_INIT (sym_eai_noname, "EAI_NONAME",
687 SCM_I_MAKINUM (EAI_NONAME));
688 SCM_VARIABLE_INIT (sym_eai_again, "EAI_AGAIN",
689 SCM_I_MAKINUM (EAI_AGAIN));
690 SCM_VARIABLE_INIT (sym_eai_fail, "EAI_FAIL",
691 SCM_I_MAKINUM (EAI_FAIL));
692 SCM_VARIABLE_INIT (sym_eai_family, "EAI_FAMILY",
693 SCM_I_MAKINUM (EAI_FAMILY));
694 SCM_VARIABLE_INIT (sym_eai_socktype, "EAI_SOCKTYPE",
695 SCM_I_MAKINUM (EAI_SOCKTYPE));
696 SCM_VARIABLE_INIT (sym_eai_service, "EAI_SERVICE",
697 SCM_I_MAKINUM (EAI_SERVICE));
698 SCM_VARIABLE_INIT (sym_eai_memory, "EAI_MEMORY",
699 SCM_I_MAKINUM (EAI_MEMORY));
700 SCM_VARIABLE_INIT (sym_eai_system, "EAI_SYSTEM",
701 SCM_I_MAKINUM (EAI_SYSTEM));
702 SCM_VARIABLE_INIT (sym_eai_overflow, "EAI_OVERFLOW",
703 SCM_I_MAKINUM (EAI_OVERFLOW));
704
705 /* The following values are GNU extensions. */
706 #ifdef EAI_NODATA
707 SCM_VARIABLE_INIT (sym_eai_nodata, "EAI_NODATA",
708 SCM_I_MAKINUM (EAI_NODATA));
709 #endif
710 #ifdef EAI_ADDRFAMILY
711 SCM_VARIABLE_INIT (sym_eai_addrfamily, "EAI_ADDRFAMILY",
712 SCM_I_MAKINUM (EAI_ADDRFAMILY));
713 #endif
714 #ifdef EAI_INPROGRESS
715 SCM_VARIABLE_INIT (sym_eai_inprogress, "EAI_INPROGRESS",
716 SCM_I_MAKINUM (EAI_INPROGRESS));
717 #endif
718 #ifdef EAI_CANCELED
719 SCM_VARIABLE_INIT (sym_eai_canceled, "EAI_CANCELED",
720 SCM_I_MAKINUM (EAI_CANCELED));
721 #endif
722 #ifdef EAI_NOTCANCELED
723 SCM_VARIABLE_INIT (sym_eai_notcanceled, "EAI_NOTCANCELED",
724 SCM_I_MAKINUM (EAI_NOTCANCELED));
725 #endif
726 #ifdef EAI_ALLDONE
727 SCM_VARIABLE_INIT (sym_eai_alldone, "EAI_ALLDONE",
728 SCM_I_MAKINUM (EAI_ALLDONE));
729 #endif
730 #ifdef EAI_INTR
731 SCM_VARIABLE_INIT (sym_eai_intr, "EAI_INTR",
732 SCM_I_MAKINUM (EAI_INTR));
733 #endif
734 #ifdef EAI_IDN_ENCODE
735 SCM_VARIABLE_INIT (sym_eai_idn_encode, "EAI_IDN_ENCODE",
736 SCM_I_MAKINUM (EAI_IDN_ENCODE));
737 #endif
738
739 SCM_DEFINE (scm_gai_strerror, "gai-strerror", 1, 0, 0,
740 (SCM error),
741 "Return a string describing @var{error}, an integer error code "
742 "returned by @code{getaddrinfo}.")
743 #define FUNC_NAME s_scm_gai_strerror
744 {
745 return scm_from_locale_string (gai_strerror (scm_to_int (error)));
746 }
747 #undef FUNC_NAME
748
749 /* TODO: Add a getnameinfo(3) wrapper. */
750
751 \f
752 void
753 scm_init_net_db ()
754 {
755 scm_add_feature ("net-db");
756 #include "libguile/net_db.x"
757 }
758
759 /*
760 Local Variables:
761 c-file-style: "gnu"
762 End:
763 */