net_db.c 24 KB

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