1 /* "net_db.c" network database support
2 * Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
9 * This program 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
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this software; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307 USA
19 * As a special exception, the Free Software Foundation gives permission
20 * for additional uses of the text contained in its release of GUILE.
22 * The exception is that, if you link the GUILE library with other files
23 * to produce an executable, this does not by itself cause the
24 * resulting executable to be covered by the GNU General Public License.
25 * Your use of that executable is in no way restricted on account of
26 * linking the GUILE library code into it.
28 * This exception does not however invalidate any other reasons why
29 * the executable file might be covered by the GNU General Public License.
31 * This exception applies only to the code released by the
32 * Free Software Foundation under the name GUILE. If you copy
33 * code from other Free Software Foundation releases into a copy of
34 * GUILE, as the General Public License permits, the exception does
35 * not apply to the code that you add in this way. To avoid misleading
36 * anyone as to the status of such modified files, you must delete
37 * this exception notice from them.
39 * If you write modifications of your own for GUILE, it is your choice
40 * whether to permit this exception to apply to your modifications.
41 * If you do not wish that, delete this exception notice. */
43 /* Written in 1994 by Aubrey Jaffer.
44 * Thanks to Hallvard.Tretteberg@si.sintef.no for inspiration and discussion.
45 * Rewritten by Gary Houston to be a closer interface to the C socket library.
46 * Split into net_db.c and socket.c.
60 #include <sys/types.h>
61 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
66 /* Some systems do not declare this. It seems unlikely to produce a
74 #endif /* STDC_HEADERS */
76 extern int inet_aton ();
78 SCM_PROC (s_inet_aton
, "inet-aton", 1, 0, 0, scm_inet_aton
);
81 scm_inet_aton (address
)
86 SCM_ASSERT (SCM_NIMP (address
) && SCM_ROSTRINGP (address
), address
, SCM_ARG1
, s_inet_aton
);
87 if (SCM_SUBSTRP (address
))
88 address
= scm_makfromstr (SCM_ROCHARS (address
), SCM_ROLENGTH (address
), 0);
89 if (inet_aton (SCM_ROCHARS (address
), &soka
) == 0)
90 scm_syserror (s_inet_aton
);
91 return scm_ulong2num (ntohl (soka
.s_addr
));
95 SCM_PROC (s_inet_ntoa
, "inet-ntoa", 1, 0, 0, scm_inet_ntoa
);
98 scm_inet_ntoa (inetid
)
104 addr
.s_addr
= htonl (scm_num2ulong (inetid
, (char *) SCM_ARG1
, s_inet_ntoa
));
106 s
= inet_ntoa (addr
);
107 answer
= scm_makfromstr (s
, strlen (s
), 0);
112 #ifdef HAVE_INET_NETOF
113 SCM_PROC (s_inet_netof
, "inet-netof", 1, 0, 0, scm_inet_netof
);
116 scm_inet_netof (address
)
120 addr
.s_addr
= htonl (scm_num2ulong (address
, (char *) SCM_ARG1
, s_inet_netof
));
121 return scm_ulong2num ((unsigned long) inet_netof (addr
));
125 #ifdef HAVE_INET_LNAOF
126 SCM_PROC (s_lnaof
, "inet-lnaof", 1, 0, 0, scm_lnaof
);
133 addr
.s_addr
= htonl (scm_num2ulong (address
, (char *) SCM_ARG1
, s_lnaof
));
134 return scm_ulong2num ((unsigned long) inet_lnaof (addr
));
138 #ifdef HAVE_INET_MAKEADDR
139 SCM_PROC (s_inet_makeaddr
, "inet-makeaddr", 2, 0, 0, scm_inet_makeaddr
);
142 scm_inet_makeaddr (net
, lna
)
147 unsigned long netnum
;
148 unsigned long lnanum
;
150 netnum
= scm_num2ulong (net
, (char *) SCM_ARG1
, s_inet_makeaddr
);
151 lnanum
= scm_num2ulong (lna
, (char *) SCM_ARG2
, s_inet_makeaddr
);
152 addr
= inet_makeaddr (netnum
, lnanum
);
153 return scm_ulong2num (ntohl (addr
.s_addr
));
158 /* !!! Doesn't take address format.
159 * Assumes hostent stream isn't reused.
162 SCM_PROC (s_gethost
, "gethost", 0, 1, 0, scm_gethost
);
168 SCM ans
= scm_make_vector (SCM_MAKINUM (5), SCM_UNSPECIFIED
);
169 SCM
*ve
= SCM_VELTS (ans
);
171 struct hostent
*entry
;
175 if (SCM_UNBNDP (name
))
178 #ifdef HAVE_GETHOSTENT
179 entry
= gethostent ();
185 /* As far as I can tell, there's no good way to tell whether
186 zero means an error or end-of-file. The trick of
187 clearing errno before calling gethostent and checking it
188 afterwards doesn't cut it, because, on Linux, it seems to
189 try to contact some other server (YP?) and fails, which
190 is a benign failure. */
195 else if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
197 SCM_COERCE_SUBSTR (name
);
199 entry
= gethostbyname (SCM_ROCHARS (name
));
203 inad
.s_addr
= htonl (scm_num2ulong (name
, (char *) SCM_ARG1
, s_gethost
));
205 entry
= gethostbyaddr ((char *) &inad
, sizeof (inad
), AF_INET
);
212 args
= scm_listify (name
, SCM_UNDEFINED
);
215 case HOST_NOT_FOUND
: errmsg
= "host %s not found"; break;
216 case TRY_AGAIN
: errmsg
= "nameserver failure (try later)"; break;
217 case NO_RECOVERY
: errmsg
= "non-recoverable error"; break;
218 case NO_DATA
: errmsg
= "no address associated with %s"; break;
219 default: errmsg
= "undefined error"; break;
221 scm_syserror_msg (s_gethost
, errmsg
, args
, h_errno
);
223 ve
[0] = scm_makfromstr (entry
->h_name
, (scm_sizet
) strlen (entry
->h_name
), 0);
224 ve
[1] = scm_makfromstrs (-1, entry
->h_aliases
);
225 ve
[2] = SCM_MAKINUM (entry
->h_addrtype
+ 0L);
226 ve
[3] = SCM_MAKINUM (entry
->h_length
+ 0L);
227 if (sizeof (struct in_addr
) != entry
->h_length
)
232 for (argv
= entry
->h_addr_list
; argv
[i
]; i
++);
235 inad
= *(struct in_addr
*) argv
[i
];
236 lst
= scm_cons (scm_ulong2num (ntohl (inad
.s_addr
)), lst
);
243 /* In all subsequent getMUMBLE functions, when we're called with no
244 arguments, we're supposed to traverse the tables entry by entry.
245 However, there doesn't seem to be any documented way to distinguish
246 between end-of-table and an error; in both cases the functions
247 return zero. Gotta love Unix. For the time being, we clear errno,
248 and if we get a zero and errno is set, we signal an error. This
249 doesn't seem quite right (what if errno gets set as part of healthy
250 operation?), but it seems to work okay. We'll see. */
252 #if defined(HAVE_GETNETENT) && defined(HAVE_GETNETBYNAME) && defined(HAVE_GETNETBYADDR)
253 SCM_PROC (s_getnet
, "getnet", 0, 1, 0, scm_getnet
);
261 struct netent
*entry
;
263 ans
= scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED
);
264 ve
= SCM_VELTS (ans
);
265 if (SCM_UNBNDP (name
))
269 entry
= getnetent ();
274 scm_syserror (s_getnet
);
279 else if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
281 SCM_COERCE_SUBSTR (name
);
283 entry
= getnetbyname (SCM_ROCHARS (name
));
287 unsigned long netnum
;
288 netnum
= scm_num2ulong (name
, (char *) SCM_ARG1
, s_getnet
);
290 entry
= getnetbyaddr (netnum
, AF_INET
);
294 scm_syserror_msg (s_getnet
, "no such network %s",
295 scm_listify (name
, SCM_UNDEFINED
), errno
);
296 ve
[0] = scm_makfromstr (entry
->n_name
, (scm_sizet
) strlen (entry
->n_name
), 0);
297 ve
[1] = scm_makfromstrs (-1, entry
->n_aliases
);
298 ve
[2] = SCM_MAKINUM (entry
->n_addrtype
+ 0L);
299 ve
[3] = scm_ulong2num (entry
->n_net
+ 0L);
304 #ifdef HAVE_GETPROTOENT
305 SCM_PROC (s_getproto
, "getproto", 0, 1, 0, scm_getproto
);
313 struct protoent
*entry
;
315 ans
= scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED
);
316 ve
= SCM_VELTS (ans
);
317 if (SCM_UNBNDP (name
))
321 entry
= getprotoent ();
326 scm_syserror (s_getproto
);
331 else if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
333 SCM_COERCE_SUBSTR (name
);
335 entry
= getprotobyname (SCM_ROCHARS (name
));
339 unsigned long protonum
;
340 protonum
= scm_num2ulong (name
, (char *) SCM_ARG1
, s_getproto
);
342 entry
= getprotobynumber (protonum
);
346 scm_syserror_msg (s_getproto
, "no such protocol %s",
347 scm_listify (name
, SCM_UNDEFINED
), errno
);
348 ve
[0] = scm_makfromstr (entry
->p_name
, (scm_sizet
) strlen (entry
->p_name
), 0);
349 ve
[1] = scm_makfromstrs (-1, entry
->p_aliases
);
350 ve
[2] = SCM_MAKINUM (entry
->p_proto
+ 0L);
355 static SCM scm_return_entry
SCM_P ((struct servent
*entry
));
358 scm_return_entry (entry
)
359 struct servent
*entry
;
364 ans
= scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED
);
365 ve
= SCM_VELTS (ans
);
366 ve
[0] = scm_makfromstr (entry
->s_name
, (scm_sizet
) strlen (entry
->s_name
), 0);
367 ve
[1] = scm_makfromstrs (-1, entry
->s_aliases
);
368 ve
[2] = SCM_MAKINUM (ntohs (entry
->s_port
) + 0L);
369 ve
[3] = scm_makfromstr (entry
->s_proto
, (scm_sizet
) strlen (entry
->s_proto
), 0);
374 #ifdef HAVE_GETSERVENT
375 SCM_PROC (s_getserv
, "getserv", 0, 2, 0, scm_getserv
);
378 scm_getserv (name
, proto
)
382 struct servent
*entry
;
383 if (SCM_UNBNDP (name
))
387 entry
= getservent ();
392 scm_syserror (s_getserv
);
396 return scm_return_entry (entry
);
398 SCM_ASSERT (SCM_NIMP (proto
) && SCM_ROSTRINGP (proto
), proto
, SCM_ARG2
, s_getserv
);
399 SCM_COERCE_SUBSTR (proto
);
400 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
402 SCM_COERCE_SUBSTR (name
);
404 entry
= getservbyname (SCM_ROCHARS (name
), SCM_ROCHARS (proto
));
408 SCM_ASSERT (SCM_INUMP (name
), name
, SCM_ARG1
, s_getserv
);
410 entry
= getservbyport (htons (SCM_INUM (name
)), SCM_ROCHARS (proto
));
413 scm_syserror_msg (s_getserv
, "no such service %s",
414 scm_listify (name
, SCM_UNDEFINED
), errno
);
416 return scm_return_entry (entry
);
420 #if defined(HAVE_SETHOSTENT) && defined(HAVE_ENDHOSTENT)
421 SCM_PROC (s_sethost
, "sethost", 0, 1, 0, scm_sethost
);
427 if (SCM_UNBNDP (arg
))
430 sethostent (SCM_NFALSEP (arg
));
431 return SCM_UNSPECIFIED
;
435 #if defined(HAVE_SETNETENT) && defined(HAVE_ENDNETENT)
436 SCM_PROC (s_setnet
, "setnet", 0, 1, 0, scm_setnet
);
442 if (SCM_UNBNDP (arg
))
445 setnetent (SCM_NFALSEP (arg
));
446 return SCM_UNSPECIFIED
;
450 #if defined(HAVE_SETPROTOENT) && defined(HAVE_ENDPROTOENT)
451 SCM_PROC (s_setproto
, "setproto", 0, 1, 0, scm_setproto
);
457 if (SCM_UNBNDP (arg
))
460 setprotoent (SCM_NFALSEP (arg
));
461 return SCM_UNSPECIFIED
;
465 #if defined(HAVE_SETSERVENT) && defined(HAVE_ENDSERVENT)
466 SCM_PROC (s_setserv
, "setserv", 0, 1, 0, scm_setserv
);
472 if (SCM_UNBNDP (arg
))
475 setservent (SCM_NFALSEP (arg
));
476 return SCM_UNSPECIFIED
;
485 scm_sysintern ("INADDR_ANY", scm_ulong2num (INADDR_ANY
));
487 #ifdef INADDR_BROADCAST
488 scm_sysintern ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST
));
491 scm_sysintern ("INADDR_NONE", scm_ulong2num (INADDR_NONE
));
493 #ifdef INADDR_LOOPBACK
494 scm_sysintern ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK
));
497 scm_add_feature ("net-db");