1 /* "net_db.c" network database support
2 * Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2006, 2009 Free Software Foundation, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 /* Written in 1994 by Aubrey Jaffer.
22 * Thanks to Hallvard.Tretteberg@si.sintef.no for inspiration and discussion.
23 * Rewritten by Gary Houston to be a closer interface to the C socket library.
24 * Split into net_db.c and socket.c.
34 #include "libguile/_scm.h"
35 #include "libguile/feature.h"
36 #include "libguile/strings.h"
37 #include "libguile/vectors.h"
38 #include "libguile/dynwind.h"
40 #include "libguile/validate.h"
41 #include "libguile/net_db.h"
47 #include <sys/types.h>
49 #ifdef HAVE_WINSOCK2_H
52 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <arpa/inet.h>
59 #include "win32-socket.h"
62 #if !defined (HAVE_H_ERRNO) && !defined (__MINGW32__) && !defined (__CYGWIN__)
63 /* h_errno not found in netdb.h, maybe this will help. */
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);
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");
80 static void scm_resolv_error (const char *subr, SCM bad_value)
83 if (h_errno == NETDB_INTERNAL)
85 /* errno supposedly contains a useful value. */
97 key = scm_host_not_found_key;
98 errmsg = "Unknown host";
101 key = scm_try_again_key;
102 errmsg = "Host name lookup failure";
105 key = scm_no_recovery_key;
106 errmsg = "Unknown server error";
109 key = scm_no_data_key;
110 errmsg = "No address associated with name";
113 scm_misc_error (subr, "Unknown resolver error", SCM_EOL);
117 #ifdef HAVE_HSTRERROR
118 errmsg = (const char *) hstrerror (h_errno);
120 scm_error (key, subr, errmsg, SCM_BOOL_F, SCM_EOL);
124 /* Should take an extra arg for address format (will be needed for IPv6).
125 Should use reentrant facilities if available.
128 SCM_DEFINE (scm_gethost, "gethost", 0, 1, 0,
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
143 SCM result = scm_c_make_vector (5, SCM_UNSPECIFIED);
145 struct hostent *entry;
150 if (SCM_UNBNDP (host))
152 #ifdef HAVE_GETHOSTENT
153 entry = gethostent ();
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. */
168 else if (scm_is_string (host))
170 char *str = scm_to_locale_string (host);
171 entry = gethostbyname (str);
176 inad.s_addr = htonl (scm_to_ulong (host));
177 entry = gethostbyaddr ((char *) &inad, sizeof (inad), AF_INET);
181 scm_resolv_error (FUNC_NAME, host);
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)
189 SCM_SIMPLE_VECTOR_SET(result, 4, SCM_BOOL_F);
192 for (argv = entry->h_addr_list; argv[i]; i++);
195 inad = *(struct in_addr *) argv[i];
196 lst = scm_cons (scm_from_ulong (ntohl (inad.s_addr)), lst);
198 SCM_SIMPLE_VECTOR_SET(result, 4, lst);
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. */
213 #if defined(HAVE_GETNETENT) && defined(HAVE_GETNETBYNAME) && defined(HAVE_GETNETBYADDR)
214 SCM_DEFINE (scm_getnet, "getnet", 0, 1, 0,
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"
223 #define FUNC_NAME s_scm_getnet
225 SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
226 struct netent *entry;
229 if (SCM_UNBNDP (net))
231 entry = getnetent ();
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'
240 else if (scm_is_string (net))
242 char *str = scm_to_locale_string (net);
243 entry = getnetbyname (str);
249 unsigned long netnum = scm_to_ulong (net);
250 entry = getnetbyaddr (netnum, AF_INET);
255 SCM_SYSERROR_MSG ("no such network ~A", scm_list_1 (net), eno);
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));
266 #if defined (HAVE_GETPROTOENT) || defined (__MINGW32__)
267 SCM_DEFINE (scm_getproto, "getproto", 0, 1, 0,
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
277 SCM result = scm_c_make_vector (3, SCM_UNSPECIFIED);
278 struct protoent *entry;
281 if (SCM_UNBNDP (protocol))
283 entry = getprotoent ();
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'
292 else if (scm_is_string (protocol))
294 char *str = scm_to_locale_string (protocol);
295 entry = getprotobyname (str);
301 unsigned long protonum = scm_to_ulong (protocol);
302 entry = getprotobynumber (protonum);
307 SCM_SYSERROR_MSG ("no such protocol ~A", scm_list_1 (protocol), eno);
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));
317 #if defined (HAVE_GETSERVENT) || defined (__MINGW32__)
319 scm_return_entry (struct servent *entry)
321 SCM result = scm_c_make_vector (4, SCM_UNSPECIFIED);
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));
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
343 struct servent *entry;
347 if (SCM_UNBNDP (name))
349 entry = getservent ();
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'
357 return scm_return_entry (entry);
360 scm_dynwind_begin (0);
362 protoname = scm_to_locale_string (protocol);
363 scm_dynwind_free (protoname);
365 if (scm_is_string (name))
367 char *str = scm_to_locale_string (name);
368 entry = getservbyname (str, protoname);
374 entry = getservbyport (htons (scm_to_int (name)), protoname);
379 SCM_SYSERROR_MSG("no such service ~A", scm_list_1 (name), eno);
382 return scm_return_entry (entry);
387 #if defined(HAVE_SETHOSTENT) && defined(HAVE_ENDHOSTENT)
388 SCM_DEFINE (scm_sethost, "sethost", 0, 1, 0,
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
394 if (SCM_UNBNDP (stayopen))
397 sethostent (scm_is_true (stayopen));
398 return SCM_UNSPECIFIED;
403 #if defined(HAVE_SETNETENT) && defined(HAVE_ENDNETENT)
404 SCM_DEFINE (scm_setnet, "setnet", 0, 1, 0,
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
410 if (SCM_UNBNDP (stayopen))
413 setnetent (scm_is_true (stayopen));
414 return SCM_UNSPECIFIED;
419 #if defined (HAVE_SETPROTOENT) && defined (HAVE_ENDPROTOENT) || defined (__MINGW32__)
420 SCM_DEFINE (scm_setproto, "setproto", 0, 1, 0,
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
426 if (SCM_UNBNDP (stayopen))
429 setprotoent (scm_is_true (stayopen));
430 return SCM_UNSPECIFIED;
435 #if defined (HAVE_SETSERVENT) && defined (HAVE_ENDSERVENT) || defined (__MINGW32__)
436 SCM_DEFINE (scm_setserv, "setserv", 0, 1, 0,
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
442 if (SCM_UNBNDP (stayopen))
445 setservent (scm_is_true (stayopen));
446 return SCM_UNSPECIFIED;
455 scm_add_feature ("net-db");
456 #include "libguile/net_db.x"