1 /* "net_db.c" network database support
2 * Copyright (C) 1995, 1996, 1997, 1998, 1999 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. Some systems do declare it, as a
76 #endif /* STDC_HEADERS */
78 extern int inet_aton ();
80 SCM_PROC (s_inet_aton
, "inet-aton", 1, 0, 0, scm_inet_aton
);
83 scm_inet_aton (address
)
88 SCM_ASSERT (SCM_NIMP (address
) && SCM_ROSTRINGP (address
), address
, SCM_ARG1
, s_inet_aton
);
89 if (SCM_SUBSTRP (address
))
90 address
= scm_makfromstr (SCM_ROCHARS (address
), SCM_ROLENGTH (address
), 0);
91 if (inet_aton (SCM_ROCHARS (address
), &soka
) == 0)
92 scm_syserror (s_inet_aton
);
93 return scm_ulong2num (ntohl (soka
.s_addr
));
97 SCM_PROC (s_inet_ntoa
, "inet-ntoa", 1, 0, 0, scm_inet_ntoa
);
100 scm_inet_ntoa (inetid
)
106 addr
.s_addr
= htonl (scm_num2ulong (inetid
, (char *) SCM_ARG1
, s_inet_ntoa
));
107 s
= inet_ntoa (addr
);
108 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
))
177 #ifdef HAVE_GETHOSTENT
178 entry
= gethostent ();
184 /* As far as I can tell, there's no good way to tell whether
185 zero means an error or end-of-file. The trick of
186 clearing errno before calling gethostent and checking it
187 afterwards doesn't cut it, because, on Linux, it seems to
188 try to contact some other server (YP?) and fails, which
189 is a benign failure. */
193 else if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
195 SCM_COERCE_SUBSTR (name
);
196 entry
= gethostbyname (SCM_ROCHARS (name
));
200 inad
.s_addr
= htonl (scm_num2ulong (name
, (char *) SCM_ARG1
, s_gethost
));
201 entry
= gethostbyaddr ((char *) &inad
, sizeof (inad
), AF_INET
);
207 args
= scm_listify (name
, SCM_UNDEFINED
);
210 case HOST_NOT_FOUND
: errmsg
= "host %s not found"; break;
211 case TRY_AGAIN
: errmsg
= "nameserver failure (try later)"; break;
212 case NO_RECOVERY
: errmsg
= "non-recoverable error"; break;
213 case NO_DATA
: errmsg
= "no address associated with %s"; break;
214 default: errmsg
= "undefined error"; break;
216 scm_syserror_msg (s_gethost
, errmsg
, args
, h_errno
);
218 ve
[0] = scm_makfromstr (entry
->h_name
, (scm_sizet
) strlen (entry
->h_name
), 0);
219 ve
[1] = scm_makfromstrs (-1, entry
->h_aliases
);
220 ve
[2] = SCM_MAKINUM (entry
->h_addrtype
+ 0L);
221 ve
[3] = SCM_MAKINUM (entry
->h_length
+ 0L);
222 if (sizeof (struct in_addr
) != entry
->h_length
)
227 for (argv
= entry
->h_addr_list
; argv
[i
]; i
++);
230 inad
= *(struct in_addr
*) argv
[i
];
231 lst
= scm_cons (scm_ulong2num (ntohl (inad
.s_addr
)), lst
);
238 /* In all subsequent getMUMBLE functions, when we're called with no
239 arguments, we're supposed to traverse the tables entry by entry.
240 However, there doesn't seem to be any documented way to distinguish
241 between end-of-table and an error; in both cases the functions
242 return zero. Gotta love Unix. For the time being, we clear errno,
243 and if we get a zero and errno is set, we signal an error. This
244 doesn't seem quite right (what if errno gets set as part of healthy
245 operation?), but it seems to work okay. We'll see. */
247 #if defined(HAVE_GETNETENT) && defined(HAVE_GETNETBYNAME) && defined(HAVE_GETNETBYADDR)
248 SCM_PROC (s_getnet
, "getnet", 0, 1, 0, scm_getnet
);
256 struct netent
*entry
;
258 ans
= scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED
);
259 ve
= SCM_VELTS (ans
);
260 if (SCM_UNBNDP (name
))
263 entry
= getnetent ();
267 scm_syserror (s_getnet
);
272 else if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
274 SCM_COERCE_SUBSTR (name
);
275 entry
= getnetbyname (SCM_ROCHARS (name
));
279 unsigned long netnum
;
280 netnum
= scm_num2ulong (name
, (char *) SCM_ARG1
, s_getnet
);
281 entry
= getnetbyaddr (netnum
, AF_INET
);
284 scm_syserror_msg (s_getnet
, "no such network %s",
285 scm_listify (name
, SCM_UNDEFINED
), errno
);
286 ve
[0] = scm_makfromstr (entry
->n_name
, (scm_sizet
) strlen (entry
->n_name
), 0);
287 ve
[1] = scm_makfromstrs (-1, entry
->n_aliases
);
288 ve
[2] = SCM_MAKINUM (entry
->n_addrtype
+ 0L);
289 ve
[3] = scm_ulong2num (entry
->n_net
+ 0L);
294 #ifdef HAVE_GETPROTOENT
295 SCM_PROC (s_getproto
, "getproto", 0, 1, 0, scm_getproto
);
303 struct protoent
*entry
;
305 ans
= scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED
);
306 ve
= SCM_VELTS (ans
);
307 if (SCM_UNBNDP (name
))
310 entry
= getprotoent ();
314 scm_syserror (s_getproto
);
319 else if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
321 SCM_COERCE_SUBSTR (name
);
322 entry
= getprotobyname (SCM_ROCHARS (name
));
326 unsigned long protonum
;
327 protonum
= scm_num2ulong (name
, (char *) SCM_ARG1
, s_getproto
);
328 entry
= getprotobynumber (protonum
);
331 scm_syserror_msg (s_getproto
, "no such protocol %s",
332 scm_listify (name
, SCM_UNDEFINED
), errno
);
333 ve
[0] = scm_makfromstr (entry
->p_name
, (scm_sizet
) strlen (entry
->p_name
), 0);
334 ve
[1] = scm_makfromstrs (-1, entry
->p_aliases
);
335 ve
[2] = SCM_MAKINUM (entry
->p_proto
+ 0L);
340 static SCM scm_return_entry
SCM_P ((struct servent
*entry
));
343 scm_return_entry (entry
)
344 struct servent
*entry
;
349 ans
= scm_make_vector (SCM_MAKINUM (4), SCM_UNSPECIFIED
);
350 ve
= SCM_VELTS (ans
);
351 ve
[0] = scm_makfromstr (entry
->s_name
, (scm_sizet
) strlen (entry
->s_name
), 0);
352 ve
[1] = scm_makfromstrs (-1, entry
->s_aliases
);
353 ve
[2] = SCM_MAKINUM (ntohs (entry
->s_port
) + 0L);
354 ve
[3] = scm_makfromstr (entry
->s_proto
, (scm_sizet
) strlen (entry
->s_proto
), 0);
358 #ifdef HAVE_GETSERVENT
359 SCM_PROC (s_getserv
, "getserv", 0, 2, 0, scm_getserv
);
362 scm_getserv (name
, proto
)
366 struct servent
*entry
;
367 if (SCM_UNBNDP (name
))
370 entry
= getservent ();
374 scm_syserror (s_getserv
);
378 return scm_return_entry (entry
);
380 SCM_ASSERT (SCM_NIMP (proto
) && SCM_ROSTRINGP (proto
), proto
, SCM_ARG2
, s_getserv
);
381 SCM_COERCE_SUBSTR (proto
);
382 if (SCM_NIMP (name
) && SCM_ROSTRINGP (name
))
384 SCM_COERCE_SUBSTR (name
);
385 entry
= getservbyname (SCM_ROCHARS (name
), SCM_ROCHARS (proto
));
389 SCM_ASSERT (SCM_INUMP (name
), name
, SCM_ARG1
, s_getserv
);
390 entry
= getservbyport (htons (SCM_INUM (name
)), SCM_ROCHARS (proto
));
393 scm_syserror_msg (s_getserv
, "no such service %s",
394 scm_listify (name
, SCM_UNDEFINED
), errno
);
395 return scm_return_entry (entry
);
399 #if defined(HAVE_SETHOSTENT) && defined(HAVE_ENDHOSTENT)
400 SCM_PROC (s_sethost
, "sethost", 0, 1, 0, scm_sethost
);
406 if (SCM_UNBNDP (arg
))
409 sethostent (SCM_NFALSEP (arg
));
410 return SCM_UNSPECIFIED
;
414 #if defined(HAVE_SETNETENT) && defined(HAVE_ENDNETENT)
415 SCM_PROC (s_setnet
, "setnet", 0, 1, 0, scm_setnet
);
421 if (SCM_UNBNDP (arg
))
424 setnetent (SCM_NFALSEP (arg
));
425 return SCM_UNSPECIFIED
;
429 #if defined(HAVE_SETPROTOENT) && defined(HAVE_ENDPROTOENT)
430 SCM_PROC (s_setproto
, "setproto", 0, 1, 0, scm_setproto
);
436 if (SCM_UNBNDP (arg
))
439 setprotoent (SCM_NFALSEP (arg
));
440 return SCM_UNSPECIFIED
;
444 #if defined(HAVE_SETSERVENT) && defined(HAVE_ENDSERVENT)
445 SCM_PROC (s_setserv
, "setserv", 0, 1, 0, scm_setserv
);
451 if (SCM_UNBNDP (arg
))
454 setservent (SCM_NFALSEP (arg
));
455 return SCM_UNSPECIFIED
;
464 scm_sysintern ("INADDR_ANY", scm_ulong2num (INADDR_ANY
));
466 #ifdef INADDR_BROADCAST
467 scm_sysintern ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST
));
470 scm_sysintern ("INADDR_NONE", scm_ulong2num (INADDR_NONE
));
472 #ifdef INADDR_LOOPBACK
473 scm_sysintern ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK
));
476 scm_add_feature ("net-db");