* random.c (scm_c_random_bignum): use SCM_CHAR_BIT.
[bpt/guile.git] / libguile / socket.c
CommitLineData
aca23b65 1/* Copyright (C) 1996,1997,1998,2000,2001, 2002 Free Software Foundation, Inc.
86667910 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
86667910 7 *
73be1d9e
MV
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
86667910 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
1bbd0b84 17
1bbd0b84 18
0f2d19dd
JB
19\f
20
eccde741
RB
21#if HAVE_CONFIG_H
22# include <config.h>
23#endif
24
e6e2e95a 25#include <errno.h>
69d49ac8 26#include <gmp.h>
e6e2e95a 27
a0599745
MD
28#include "libguile/_scm.h"
29#include "libguile/unif.h"
30#include "libguile/feature.h"
31#include "libguile/fports.h"
32#include "libguile/strings.h"
33#include "libguile/vectors.h"
20e6290e 34
a0599745
MD
35#include "libguile/validate.h"
36#include "libguile/socket.h"
95b88819 37
b4e15479
SJ
38#ifdef __MINGW32__
39#include "win32-socket.h"
40#endif
41
af68e5e5
SJ
42#ifdef HAVE_STDINT_H
43#include <stdint.h>
44#endif
95b88819
GH
45#ifdef HAVE_STRING_H
46#include <string.h>
47#endif
370312ae
GH
48#ifdef HAVE_UNISTD_H
49#include <unistd.h>
50#endif
0f2d19dd 51#include <sys/types.h>
f87c105a 52#ifdef HAVE_WINSOCK2_H
82893676
MG
53#include <winsock2.h>
54#else
0f2d19dd 55#include <sys/socket.h>
1ba8c23a 56#ifdef HAVE_UNIX_DOMAIN_SOCKETS
0f2d19dd 57#include <sys/un.h>
0e958795 58#endif
0f2d19dd
JB
59#include <netinet/in.h>
60#include <netdb.h>
61#include <arpa/inet.h>
82893676 62#endif
0f2d19dd 63
97d0e20b
GH
64#if defined (HAVE_UNIX_DOMAIN_SOCKETS) && !defined (SUN_LEN)
65#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
66 + strlen ((ptr)->sun_path))
67#endif
68
439006bf
GH
69/* we are not currently using socklen_t. it's not defined on all systems,
70 so would need to be checked by configure. in the meantime, plain
71 int is the best alternative. */
72
0f2d19dd
JB
73\f
74
a1ec6916 75SCM_DEFINE (scm_htons, "htons", 1, 0, 0,
eefae538
GH
76 (SCM value),
77 "Convert a 16 bit quantity from host to network byte ordering.\n"
78 "@var{value} is packed into 2 bytes, which are then converted\n"
79 "and returned as a new integer.")
1bbd0b84 80#define FUNC_NAME s_scm_htons
5c11cc9d
GH
81{
82 unsigned short c_in;
83
eefae538
GH
84 SCM_VALIDATE_INUM_COPY (1, value, c_in);
85 if (c_in != SCM_INUM (value))
86 SCM_OUT_OF_RANGE (1, value);
5c11cc9d
GH
87
88 return SCM_MAKINUM (htons (c_in));
89}
1bbd0b84 90#undef FUNC_NAME
5c11cc9d 91
a1ec6916 92SCM_DEFINE (scm_ntohs, "ntohs", 1, 0, 0,
eefae538
GH
93 (SCM value),
94 "Convert a 16 bit quantity from network to host byte ordering.\n"
95 "@var{value} is packed into 2 bytes, which are then converted\n"
96 "and returned as a new integer.")
1bbd0b84 97#define FUNC_NAME s_scm_ntohs
5c11cc9d
GH
98{
99 unsigned short c_in;
100
eefae538
GH
101 SCM_VALIDATE_INUM_COPY (1, value, c_in);
102 if (c_in != SCM_INUM (value))
103 SCM_OUT_OF_RANGE (1, value);
5c11cc9d
GH
104
105 return SCM_MAKINUM (ntohs (c_in));
106}
1bbd0b84 107#undef FUNC_NAME
5c11cc9d 108
a1ec6916 109SCM_DEFINE (scm_htonl, "htonl", 1, 0, 0,
eefae538
GH
110 (SCM value),
111 "Convert a 32 bit quantity from host to network byte ordering.\n"
112 "@var{value} is packed into 4 bytes, which are then converted\n"
113 "and returned as a new integer.")
1bbd0b84 114#define FUNC_NAME s_scm_htonl
5c11cc9d 115{
eccde741 116 scm_t_uint32 c_in = SCM_NUM2ULONG (1, value);
66c73b76 117
5c11cc9d
GH
118 return scm_ulong2num (htonl (c_in));
119}
1bbd0b84 120#undef FUNC_NAME
5c11cc9d 121
a1ec6916 122SCM_DEFINE (scm_ntohl, "ntohl", 1, 0, 0,
eefae538
GH
123 (SCM value),
124 "Convert a 32 bit quantity from network to host byte ordering.\n"
125 "@var{value} is packed into 4 bytes, which are then converted\n"
126 "and returned as a new integer.")
1bbd0b84 127#define FUNC_NAME s_scm_ntohl
5c11cc9d 128{
eccde741 129 scm_t_uint32 c_in = SCM_NUM2ULONG (1, value);
66c73b76 130
5c11cc9d
GH
131 return scm_ulong2num (ntohl (c_in));
132}
1bbd0b84 133#undef FUNC_NAME
5c11cc9d 134
66c73b76
GH
135#ifndef HAVE_INET_ATON
136/* for our definition in inet_aton.c, not usually needed. */
137extern int inet_aton ();
138#endif
139
140SCM_DEFINE (scm_inet_aton, "inet-aton", 1, 0, 0,
141 (SCM address),
eefae538
GH
142 "Convert an IPv4 Internet address from printable string\n"
143 "(dotted decimal notation) to an integer. E.g.,\n\n"
66c73b76
GH
144 "@lisp\n"
145 "(inet-aton \"127.0.0.1\") @result{} 2130706433\n"
146 "@end lisp")
147#define FUNC_NAME s_scm_inet_aton
148{
149 struct in_addr soka;
150
151 SCM_VALIDATE_STRING (1, address);
66c73b76
GH
152 if (inet_aton (SCM_STRING_CHARS (address), &soka) == 0)
153 SCM_MISC_ERROR ("bad address", SCM_EOL);
154 return scm_ulong2num (ntohl (soka.s_addr));
155}
156#undef FUNC_NAME
157
158
159SCM_DEFINE (scm_inet_ntoa, "inet-ntoa", 1, 0, 0,
160 (SCM inetid),
eefae538
GH
161 "Convert an IPv4 Internet address to a printable\n"
162 "(dotted decimal notation) string. E.g.,\n\n"
66c73b76
GH
163 "@lisp\n"
164 "(inet-ntoa 2130706433) @result{} \"127.0.0.1\"\n"
165 "@end lisp")
166#define FUNC_NAME s_scm_inet_ntoa
167{
168 struct in_addr addr;
169 char *s;
170 SCM answer;
171 addr.s_addr = htonl (SCM_NUM2ULONG (1, inetid));
172 s = inet_ntoa (addr);
36284627 173 answer = scm_mem2string (s, strlen (s));
66c73b76
GH
174 return answer;
175}
176#undef FUNC_NAME
177
178#ifdef HAVE_INET_NETOF
179SCM_DEFINE (scm_inet_netof, "inet-netof", 1, 0, 0,
180 (SCM address),
eefae538
GH
181 "Return the network number part of the given IPv4\n"
182 "Internet address. E.g.,\n\n"
66c73b76
GH
183 "@lisp\n"
184 "(inet-netof 2130706433) @result{} 127\n"
185 "@end lisp")
186#define FUNC_NAME s_scm_inet_netof
187{
188 struct in_addr addr;
189 addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
190 return scm_ulong2num ((unsigned long) inet_netof (addr));
191}
192#undef FUNC_NAME
193#endif
194
195#ifdef HAVE_INET_LNAOF
196SCM_DEFINE (scm_lnaof, "inet-lnaof", 1, 0, 0,
197 (SCM address),
198 "Return the local-address-with-network part of the given\n"
eefae538
GH
199 "IPv4 Internet address, using the obsolete class A/B/C system.\n"
200 "E.g.,\n\n"
66c73b76
GH
201 "@lisp\n"
202 "(inet-lnaof 2130706433) @result{} 1\n"
203 "@end lisp")
204#define FUNC_NAME s_scm_lnaof
205{
206 struct in_addr addr;
207 addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
208 return scm_ulong2num ((unsigned long) inet_lnaof (addr));
209}
210#undef FUNC_NAME
211#endif
212
213#ifdef HAVE_INET_MAKEADDR
214SCM_DEFINE (scm_inet_makeaddr, "inet-makeaddr", 2, 0, 0,
215 (SCM net, SCM lna),
eefae538 216 "Make an IPv4 Internet address by combining the network number\n"
66c73b76 217 "@var{net} with the local-address-within-network number\n"
eefae538 218 "@var{lna}. E.g.,\n\n"
66c73b76
GH
219 "@lisp\n"
220 "(inet-makeaddr 127 1) @result{} 2130706433\n"
221 "@end lisp")
222#define FUNC_NAME s_scm_inet_makeaddr
223{
224 struct in_addr addr;
225 unsigned long netnum;
226 unsigned long lnanum;
227
228 netnum = SCM_NUM2ULONG (1, net);
229 lnanum = SCM_NUM2ULONG (2, lna);
230 addr = inet_makeaddr (netnum, lnanum);
231 return scm_ulong2num (ntohl (addr.s_addr));
232}
233#undef FUNC_NAME
234#endif
235
a57a0b1e 236#ifdef HAVE_IPV6
eefae538 237
66c73b76
GH
238/* flip a 128 bit IPv6 address between host and network order. */
239#ifdef WORDS_BIGENDIAN
240#define FLIP_NET_HOST_128(addr)
241#else
242#define FLIP_NET_HOST_128(addr)\
243{\
244 int i;\
245 \
246 for (i = 0; i < 8; i++)\
247 {\
2de4f939 248 scm_t_uint8 c = (addr)[i];\
66c73b76
GH
249 \
250 (addr)[i] = (addr)[15 - i];\
251 (addr)[15 - i] = c;\
252 }\
253}
254#endif
255
2de4f939
RB
256#ifdef WORDS_BIGENDIAN
257#define FLIPCPY_NET_HOST_128(dest, src) memcpy (dest, src, 16)
258#else
259#define FLIPCPY_NET_HOST_128(dest, src) \
260{ \
261 const scm_t_uint8 *tmp_srcp = (src) + 15; \
262 scm_t_uint8 *tmp_destp = (dest); \
263 \
264 do { \
265 *tmp_destp++ = *tmp_srcp--; \
266 } while (tmp_srcp != (src)); \
267}
268#endif
269
270
271#if (SIZEOF_SCM_T_BITS * 8) > 128
272#error "Assumption that scm_t_bits <= 128 bits has been violated."
273#endif
274
275#if (SIZEOF_UNSIGNED_LONG * 8) > 128
276#error "Assumption that unsigned long <= 128 bits has been violated."
277#endif
278
279#if (SIZEOF_UNSIGNED_LONG_LONG * 8) > 128
280#error "Assumption that unsigned long long <= 128 bits has been violated."
281#endif
282
66c73b76
GH
283/* convert a 128 bit IPv6 address in network order to a host ordered
284 SCM integer. */
2de4f939 285static SCM ipv6_net_to_num (const scm_t_uint8 *src)
66c73b76 286{
2de4f939
RB
287 int i = 0;
288 const scm_t_uint8 *ptr = src;
289 int num_zero_bytes = 0;
290 scm_t_uint8 addr[16];
66c73b76 291
2de4f939
RB
292 /* count leading zeros (since we know it's bigendian, they'll be first) */
293 while (i < 16)
66c73b76 294 {
2de4f939
RB
295 if (*ptr) break;
296 num_zero_bytes++;
297 i++;
298 }
66c73b76 299
2de4f939
RB
300 if (SCM_SIZEOF_UNSIGNED_LONG_LONG != 0) /* compiler should optimize this */
301 {
302 if ((16 - num_zero_bytes) <= sizeof (unsigned long long))
303 {
304 /* it fits */
305 unsigned long long x;
306
307 FLIPCPY_NET_HOST_128(addr, src);
308#ifdef WORDS_BIGENDIAN
309 memcpy (&x, addr + (16 - sizeof (x)), sizeof (x));
310#else
311 memcpy (&x, addr, sizeof (x));
312#endif
313 return scm_ulong_long2num (x);
314 }
66c73b76
GH
315 }
316 else
317 {
2de4f939
RB
318 if ((16 - num_zero_bytes) <= sizeof (unsigned long))
319 {
320 /* this is just so that we use INUM where possible. */
321 unsigned long x;
322
323 FLIPCPY_NET_HOST_128(addr, src);
324#ifdef WORDS_BIGENDIAN
325 memcpy (&x, addr + (16 - sizeof (x)), sizeof (x));
326#else
327 memcpy (&x, addr, sizeof (x));
328#endif
329 return scm_ulong2num (x);
330 }
66c73b76 331 }
2de4f939
RB
332 /* otherwise get the big hammer */
333 {
334 SCM result = scm_i_mkbig ();
335
336 mpz_import (SCM_I_BIG_MPZ (result),
337 1, /* chunk */
338 1, /* big-endian chunk ordering */
339 16, /* chunks are 16 bytes long */
340 1, /* big-endian byte ordering */
341 0, /* "nails" -- leading unused bits per chunk */
342 src);
343 return scm_i_normbig (result);
344 }
66c73b76
GH
345}
346
347/* convert a host ordered SCM integer to a 128 bit IPv6 address in
348 network order. */
2de4f939 349static void ipv6_num_to_net (SCM src, scm_t_uint8 *dst)
66c73b76 350{
2de4f939 351 /* This code presumes that src has already been checked for range. */
66c73b76
GH
352 if (SCM_INUMP (src))
353 {
2de4f939
RB
354 scm_t_signed_bits n = SCM_INUM (src);
355#ifdef WORDS_BIGENDIAN
356 memset (dst, 0, 16 - sizeof (scm_t_signed_bits));
357 memcpy (dst + (16 - sizeof (scm_t_signed_bits)),
358 &n,
359 sizeof (scm_t_signed_bits));
360#else
361 memset (dst + sizeof (scm_t_signed_bits),
362 0,
363 16 - sizeof (scm_t_signed_bits));
364 /* FIXME: this pair of ops is kinda wasteful -- should rewrite as
365 a single loop perhaps, similar to the handling of bignums. */
366 memcpy (dst, &n, sizeof (scm_t_signed_bits));
367 FLIP_NET_HOST_128 (dst);
368#endif
66c73b76
GH
369 }
370 else
371 {
2de4f939
RB
372 /* Presumes src has already been checked for fit -- see above. */
373 size_t count;
66c73b76 374 memset (dst, 0, 16);
2de4f939
RB
375 mpz_export (dst,
376 &count,
377 1, /* big-endian chunk ordering */
378 16, /* chunks are 16 bytes long */
379 1, /* big-endian byte ordering */
380 0, /* "nails" -- leading unused bits per chunk */
381 SCM_I_BIG_MPZ (src));
382 scm_remember_upto_here_1 (src);
66c73b76
GH
383 }
384}
385
2de4f939
RB
386static int
387bignum_in_ipv6_range_p (SCM address)
388{
389 int result;
390 int sgn = mpz_sgn (SCM_I_BIG_MPZ (address));
391
392 if (sgn < 0)
393 result = 0;
394 else
395 {
396 int size = mpz_sizeinbase (SCM_I_BIG_MPZ (address), 2);
397 if (size > 128) result = 0;
398 else result = 1;
399 }
400 scm_remember_upto_here_1 (address);
401 return result;
402}
403
66c73b76
GH
404/* check that an SCM variable contains an IPv6 integer address. */
405#define VALIDATE_INET6(which_arg, address)\
406 if (SCM_INUMP (address))\
407 SCM_ASSERT_RANGE (which_arg, address, SCM_INUM (address) >= 0);\
408 else\
409 {\
410 SCM_VALIDATE_BIGINT (which_arg, address);\
2de4f939 411 SCM_ASSERT_RANGE (which_arg, address, bignum_in_ipv6_range_p);\
66c73b76
GH
412 }
413
414#ifdef HAVE_INET_PTON
415SCM_DEFINE (scm_inet_pton, "inet-pton", 2, 0, 0,
416 (SCM family, SCM address),
eefae538
GH
417 "Convert a string containing a printable network address to\n"
418 "an integer address. Note that unlike the C version of this\n"
419 "function,\n"
66c73b76 420 "the result is an integer with normal host byte ordering.\n"
eefae538 421 "@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g.,\n\n"
66c73b76 422 "@lisp\n"
dd85ce47
ML
423 "(inet-pton AF_INET \"127.0.0.1\") @result{} 2130706433\n"
424 "(inet-pton AF_INET6 \"::1\") @result{} 1\n"
66c73b76
GH
425 "@end lisp")
426#define FUNC_NAME s_scm_inet_pton
427{
428 int af;
429 char *src;
430 char dst[16];
431 int rv;
432
433 SCM_VALIDATE_INUM_COPY (1, family, af);
434 SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
435 SCM_VALIDATE_STRING_COPY (2, address, src);
436 rv = inet_pton (af, src, dst);
437 if (rv == -1)
438 SCM_SYSERROR;
439 else if (rv == 0)
440 SCM_MISC_ERROR ("Bad address", SCM_EOL);
441 if (af == AF_INET)
eccde741 442 return scm_ulong2num (ntohl (*(scm_t_uint32 *) dst));
66c73b76
GH
443 else
444 return ipv6_net_to_num ((char *) dst);
445}
446#undef FUNC_NAME
447#endif
448
449#ifdef HAVE_INET_NTOP
450SCM_DEFINE (scm_inet_ntop, "inet-ntop", 2, 0, 0,
451 (SCM family, SCM address),
eefae538 452 "Convert a network address into a printable string.\n"
66c73b76
GH
453 "Note that unlike the C version of this function,\n"
454 "the input is an integer with normal host byte ordering.\n"
eefae538 455 "@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g.,\n\n"
66c73b76 456 "@lisp\n"
dd85ce47 457 "(inet-ntop AF_INET 2130706433) @result{} \"127.0.0.1\"\n"
66c73b76
GH
458 "(inet-ntop AF_INET6 (- (expt 2 128) 1)) @result{}\n"
459 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\n"
460 "@end lisp")
461#define FUNC_NAME s_scm_inet_ntop
462{
463 int af;
464#ifdef INET6_ADDRSTRLEN
465 char dst[INET6_ADDRSTRLEN];
466#else
467 char dst[46];
468#endif
469 char addr6[16];
470
471 SCM_VALIDATE_INUM_COPY (1, family, af);
472 SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
473 if (af == AF_INET)
eccde741 474 *(scm_t_uint32 *) addr6 = htonl (SCM_NUM2ULONG (2, address));
66c73b76
GH
475 else
476 {
477 VALIDATE_INET6 (2, address);
478 ipv6_num_to_net (address, addr6);
479 }
480 if (inet_ntop (af, &addr6, dst, sizeof dst) == NULL)
481 SCM_SYSERROR;
482 return scm_makfrom0str (dst);
483}
484#undef FUNC_NAME
485#endif
486
a57a0b1e 487#endif /* HAVE_IPV6 */
eefae538 488
bc45012d 489SCM_SYMBOL (sym_socket, "socket");
82ddea4e 490
439006bf 491#define SCM_SOCK_FD_TO_PORT(fd) scm_fdes_to_port (fd, "r+0", sym_socket)
1bbd0b84 492
a1ec6916 493SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
1bbd0b84 494 (SCM family, SCM style, SCM proto),
1e6808ea 495 "Return a new socket port of the type specified by @var{family},\n"
eefae538 496 "@var{style} and @var{proto}. All three parameters are\n"
3453619b
GH
497 "integers. Supported values for @var{family} are\n"
498 "@code{AF_UNIX}, @code{AF_INET} and @code{AF_INET6}.\n"
499 "Typical values for @var{style} are @code{SOCK_STREAM},\n"
eefae538
GH
500 "@code{SOCK_DGRAM} and @code{SOCK_RAW}.\n\n"
501 "@var{proto} can be obtained from a protocol name using\n"
1e6808ea 502 "@code{getprotobyname}. A value of zero specifies the default\n"
eefae538 503 "protocol, which is usually right.\n\n"
1e6808ea
MG
504 "A single socket port cannot by used for communication until it\n"
505 "has been connected to another socket.")
1bbd0b84 506#define FUNC_NAME s_scm_socket
0f2d19dd 507{
370312ae 508 int fd;
370312ae 509
439006bf
GH
510 SCM_VALIDATE_INUM (1, family);
511 SCM_VALIDATE_INUM (2, style);
512 SCM_VALIDATE_INUM (3, proto);
370312ae 513 fd = socket (SCM_INUM (family), SCM_INUM (style), SCM_INUM (proto));
439006bf
GH
514 if (fd == -1)
515 SCM_SYSERROR;
516 return SCM_SOCK_FD_TO_PORT (fd);
0f2d19dd 517}
1bbd0b84 518#undef FUNC_NAME
0f2d19dd 519
0e958795 520#ifdef HAVE_SOCKETPAIR
a1ec6916 521SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
1bbd0b84 522 (SCM family, SCM style, SCM proto),
1e6808ea 523 "Return a pair of connected (but unnamed) socket ports of the\n"
eefae538 524 "type specified by @var{family}, @var{style} and @var{proto}.\n"
1e6808ea
MG
525 "Many systems support only socket pairs of the @code{AF_UNIX}\n"
526 "family. Zero is likely to be the only meaningful value for\n"
eefae538 527 "@var{proto}.")
1bbd0b84 528#define FUNC_NAME s_scm_socketpair
0f2d19dd 529{
370312ae
GH
530 int fam;
531 int fd[2];
370312ae 532
34d19ef6
HWN
533 SCM_VALIDATE_INUM (1, family);
534 SCM_VALIDATE_INUM (2, style);
535 SCM_VALIDATE_INUM (3, proto);
370312ae
GH
536
537 fam = SCM_INUM (family);
538
370312ae 539 if (socketpair (fam, SCM_INUM (style), SCM_INUM (proto), fd) == -1)
1bbd0b84 540 SCM_SYSERROR;
370312ae 541
439006bf 542 return scm_cons (SCM_SOCK_FD_TO_PORT (fd[0]), SCM_SOCK_FD_TO_PORT (fd[1]));
0f2d19dd 543}
1bbd0b84 544#undef FUNC_NAME
0e958795 545#endif
0f2d19dd 546
a1ec6916 547SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
1bbd0b84 548 (SCM sock, SCM level, SCM optname),
1e6808ea 549 "Return the value of a particular socket option for the socket\n"
eefae538 550 "port @var{sock}. @var{level} is an integer code for type of\n"
1e6808ea
MG
551 "option being requested, e.g., @code{SOL_SOCKET} for\n"
552 "socket-level options. @var{optname} is an integer code for the\n"
553 "option required and should be specified using one of the\n"
eefae538 554 "symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n\n"
1e6808ea
MG
555 "The returned value is typically an integer but @code{SO_LINGER}\n"
556 "returns a pair of integers.")
1bbd0b84 557#define FUNC_NAME s_scm_getsockopt
0f2d19dd 558{
370312ae 559 int fd;
439006bf 560 /* size of optval is the largest supported option. */
370312ae
GH
561#ifdef HAVE_STRUCT_LINGER
562 char optval[sizeof (struct linger)];
439006bf 563 int optlen = sizeof (struct linger);
370312ae 564#else
1be6b49c
ML
565 char optval[sizeof (size_t)];
566 int optlen = sizeof (size_t);
370312ae
GH
567#endif
568 int ilevel;
569 int ioptname;
0f2d19dd 570
78446828 571 sock = SCM_COERCE_OUTPORT (sock);
2cf6d014
MD
572 SCM_VALIDATE_OPFPORT (1, sock);
573 SCM_VALIDATE_INUM_COPY (2, level, ilevel);
574 SCM_VALIDATE_INUM_COPY (3, optname, ioptname);
0f2d19dd 575
ee149d03 576 fd = SCM_FPORT_FDES (sock);
370312ae 577 if (getsockopt (fd, ilevel, ioptname, (void *) optval, &optlen) == -1)
1bbd0b84 578 SCM_SYSERROR;
1cc91f1b 579
439006bf 580 if (ilevel == SOL_SOCKET)
0f2d19dd 581 {
439006bf
GH
582#ifdef SO_LINGER
583 if (ioptname == SO_LINGER)
584 {
370312ae 585#ifdef HAVE_STRUCT_LINGER
439006bf
GH
586 struct linger *ling = (struct linger *) optval;
587
588 return scm_cons (scm_long2num (ling->l_onoff),
589 scm_long2num (ling->l_linger));
370312ae 590#else
82893676 591 return scm_cons (scm_long2num (*(int *) optval),
439006bf 592 SCM_MAKINUM (0));
0f2d19dd 593#endif
439006bf
GH
594 }
595 else
370312ae 596#endif
439006bf 597 if (0
370312ae 598#ifdef SO_SNDBUF
439006bf 599 || ioptname == SO_SNDBUF
370312ae
GH
600#endif
601#ifdef SO_RCVBUF
439006bf 602 || ioptname == SO_RCVBUF
370312ae 603#endif
439006bf
GH
604 )
605 {
1be6b49c 606 return scm_long2num (*(size_t *) optval);
439006bf
GH
607 }
608 }
609 return scm_long2num (*(int *) optval);
0f2d19dd 610}
1bbd0b84 611#undef FUNC_NAME
0f2d19dd 612
a1ec6916 613SCM_DEFINE (scm_setsockopt, "setsockopt", 4, 0, 0,
1bbd0b84 614 (SCM sock, SCM level, SCM optname, SCM value),
eefae538
GH
615 "Set the value of a particular socket option for the socket\n"
616 "port @var{sock}. @var{level} is an integer code for type of option\n"
b380b885
MD
617 "being set, e.g., @code{SOL_SOCKET} for socket-level options.\n"
618 "@var{optname} is an\n"
619 "integer code for the option to set and should be specified using one of\n"
620 "the symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n"
621 "@var{value} is the value to which the option should be set. For\n"
622 "most options this must be an integer, but for @code{SO_LINGER} it must\n"
623 "be a pair.\n\n"
624 "The return value is unspecified.")
1bbd0b84 625#define FUNC_NAME s_scm_setsockopt
0f2d19dd 626{
370312ae 627 int fd;
439006bf
GH
628 int optlen = -1;
629 /* size of optval is the largest supported option. */
370312ae 630#ifdef HAVE_STRUCT_LINGER
439006bf 631 char optval[sizeof (struct linger)];
370312ae 632#else
1be6b49c 633 char optval[sizeof (size_t)];
370312ae
GH
634#endif
635 int ilevel, ioptname;
439006bf 636
78446828 637 sock = SCM_COERCE_OUTPORT (sock);
439006bf
GH
638
639 SCM_VALIDATE_OPFPORT (1, sock);
640 SCM_VALIDATE_INUM_COPY (2, level, ilevel);
641 SCM_VALIDATE_INUM_COPY (3, optname, ioptname);
642
ee149d03 643 fd = SCM_FPORT_FDES (sock);
439006bf
GH
644
645 if (ilevel == SOL_SOCKET)
370312ae 646 {
439006bf
GH
647#ifdef SO_LINGER
648 if (ioptname == SO_LINGER)
649 {
370312ae 650#ifdef HAVE_STRUCT_LINGER
439006bf
GH
651 struct linger ling;
652 long lv;
653
654 SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
655 lv = SCM_NUM2LONG (4, SCM_CAR (value));
656 ling.l_onoff = (int) lv;
657 SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_onoff == lv);
658 lv = SCM_NUM2LONG (4, SCM_CDR (value));
659 ling.l_linger = (int) lv;
660 SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_linger == lv);
661 optlen = (int) sizeof (struct linger);
662 memcpy (optval, (void *) &ling, optlen);
370312ae 663#else
439006bf
GH
664 int ling;
665 long lv;
666
667 SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
668 /* timeout is ignored, but may as well validate it. */
669 lv = SCM_NUM2LONG (4, SCM_CDR (value));
670 ling = (int) lv;
671 SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
672 lv = SCM_NUM2LONG (4, SCM_CAR (value));
673 ling = (int) lv;
674 SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
675 optlen = (int) sizeof (int);
676 (*(int *) optval) = ling;
677#endif
678 }
679 else
680#endif
681 if (0
370312ae 682#ifdef SO_SNDBUF
439006bf 683 || ioptname == SO_SNDBUF
370312ae
GH
684#endif
685#ifdef SO_RCVBUF
439006bf 686 || ioptname == SO_RCVBUF
370312ae 687#endif
439006bf
GH
688 )
689 {
690 long lv = SCM_NUM2LONG (4, value);
691
1be6b49c
ML
692 optlen = (int) sizeof (size_t);
693 (*(size_t *) optval) = (size_t) lv;
439006bf
GH
694 }
695 }
696 if (optlen == -1)
0f2d19dd 697 {
439006bf
GH
698 /* Most options take an int. */
699 long lv = SCM_NUM2LONG (4, value);
700 int val = (int) lv;
701
702 SCM_ASSERT_RANGE (SCM_ARG4, value, val == lv);
370312ae 703 optlen = (int) sizeof (int);
439006bf 704 (*(int *) optval) = val;
0f2d19dd 705 }
370312ae 706 if (setsockopt (fd, ilevel, ioptname, (void *) optval, optlen) == -1)
1bbd0b84 707 SCM_SYSERROR;
370312ae 708 return SCM_UNSPECIFIED;
0f2d19dd 709}
1bbd0b84 710#undef FUNC_NAME
0f2d19dd 711
a1ec6916 712SCM_DEFINE (scm_shutdown, "shutdown", 2, 0, 0,
1bbd0b84 713 (SCM sock, SCM how),
b380b885 714 "Sockets can be closed simply by using @code{close-port}. The\n"
bb2c02f2 715 "@code{shutdown} procedure allows reception or transmission on a\n"
b380b885
MD
716 "connection to be shut down individually, according to the parameter\n"
717 "@var{how}:\n\n"
718 "@table @asis\n"
719 "@item 0\n"
720 "Stop receiving data for this socket. If further data arrives, reject it.\n"
721 "@item 1\n"
722 "Stop trying to transmit data from this socket. Discard any\n"
723 "data waiting to be sent. Stop looking for acknowledgement of\n"
724 "data already sent; don't retransmit it if it is lost.\n"
725 "@item 2\n"
726 "Stop both reception and transmission.\n"
727 "@end table\n\n"
728 "The return value is unspecified.")
1bbd0b84 729#define FUNC_NAME s_scm_shutdown
0f2d19dd 730{
370312ae 731 int fd;
78446828 732 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6
HWN
733 SCM_VALIDATE_OPFPORT (1, sock);
734 SCM_VALIDATE_INUM (2, how);
735 SCM_ASSERT_RANGE(2, how,0 <= SCM_INUM (how) && 2 >= SCM_INUM (how));
ee149d03 736 fd = SCM_FPORT_FDES (sock);
370312ae 737 if (shutdown (fd, SCM_INUM (how)) == -1)
1bbd0b84 738 SCM_SYSERROR;
370312ae
GH
739 return SCM_UNSPECIFIED;
740}
1bbd0b84 741#undef FUNC_NAME
0f2d19dd 742
370312ae
GH
743/* convert fam/address/args into a sockaddr of the appropriate type.
744 args is modified by removing the arguments actually used.
745 which_arg and proc are used when reporting errors:
746 which_arg is the position of address in the original argument list.
747 proc is the name of the original procedure.
748 size returns the size of the structure allocated. */
749
370312ae 750static struct sockaddr *
439006bf
GH
751scm_fill_sockaddr (int fam, SCM address, SCM *args, int which_arg,
752 const char *proc, int *size)
3453619b 753#define FUNC_NAME proc
370312ae
GH
754{
755 switch (fam)
0f2d19dd 756 {
370312ae
GH
757 case AF_INET:
758 {
370312ae 759 struct sockaddr_in *soka;
3453619b
GH
760 unsigned long addr;
761 int port;
370312ae 762
3453619b
GH
763 SCM_VALIDATE_ULONG_COPY (which_arg, address, addr);
764 SCM_VALIDATE_CONS (which_arg + 1, *args);
765 SCM_VALIDATE_INUM_COPY (which_arg + 1, SCM_CAR (*args), port);
766 *args = SCM_CDR (*args);
67329a9e 767 soka = (struct sockaddr_in *) scm_malloc (sizeof (struct sockaddr_in));
439006bf
GH
768 if (!soka)
769 scm_memory_error (proc);
3453619b
GH
770 /* 4.4BSD-style interface includes sin_len member and defines SIN_LEN,
771 4.3BSD does not. */
772#ifdef SIN_LEN
773 soka->sin_len = sizeof (struct sockaddr_in);
774#endif
370312ae 775 soka->sin_family = AF_INET;
3453619b
GH
776 soka->sin_addr.s_addr = htonl (addr);
777 soka->sin_port = htons (port);
370312ae
GH
778 *size = sizeof (struct sockaddr_in);
779 return (struct sockaddr *) soka;
780 }
a57a0b1e 781#ifdef HAVE_IPV6
3453619b
GH
782 case AF_INET6:
783 {
784 /* see RFC2553. */
785 int port;
786 struct sockaddr_in6 *soka;
787 unsigned long flowinfo = 0;
788 unsigned long scope_id = 0;
789
66c73b76 790 VALIDATE_INET6 (which_arg, address);
3453619b
GH
791 SCM_VALIDATE_CONS (which_arg + 1, *args);
792 SCM_VALIDATE_INUM_COPY (which_arg + 1, SCM_CAR (*args), port);
793 *args = SCM_CDR (*args);
794 if (SCM_CONSP (*args))
795 {
796 SCM_VALIDATE_ULONG_COPY (which_arg + 2, SCM_CAR (*args), flowinfo);
797 *args = SCM_CDR (*args);
798 if (SCM_CONSP (*args))
799 {
800 SCM_VALIDATE_ULONG_COPY (which_arg + 3, SCM_CAR (*args),
801 scope_id);
802 *args = SCM_CDR (*args);
803 }
804 }
67329a9e 805 soka = (struct sockaddr_in6 *) scm_malloc (sizeof (struct sockaddr_in6));
3453619b
GH
806 if (!soka)
807 scm_memory_error (proc);
808#ifdef SIN_LEN6
809 soka->sin6_len = sizeof (struct sockaddr_in6);
810#endif
811 soka->sin6_family = AF_INET6;
66c73b76 812 ipv6_num_to_net (address, soka->sin6_addr.s6_addr);
5a525b84 813 soka->sin6_port = htons (port);
3453619b 814 soka->sin6_flowinfo = flowinfo;
5a525b84 815#ifdef HAVE_SIN6_SCOPE_ID
3453619b 816 soka->sin6_scope_id = scope_id;
5a525b84 817#endif
3453619b
GH
818 *size = sizeof (struct sockaddr_in6);
819 return (struct sockaddr *) soka;
820 }
821#endif
1ba8c23a 822#ifdef HAVE_UNIX_DOMAIN_SOCKETS
370312ae
GH
823 case AF_UNIX:
824 {
825 struct sockaddr_un *soka;
439006bf 826 int addr_size;
370312ae 827
a6d9e5ab 828 SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
439006bf
GH
829 /* the static buffer size in sockaddr_un seems to be arbitrary
830 and not necessarily a hard limit. e.g., the glibc manual
831 suggests it may be possible to declare it size 0. let's
832 ignore it. if the O/S doesn't like the size it will cause
833 connect/bind etc., to fail. sun_path is always the last
834 member of the structure. */
835 addr_size = sizeof (struct sockaddr_un)
836 + max (0, SCM_STRING_LENGTH (address) + 1 - (sizeof soka->sun_path));
67329a9e 837 soka = (struct sockaddr_un *) scm_malloc (addr_size);
439006bf
GH
838 if (!soka)
839 scm_memory_error (proc);
840 memset (soka, 0, addr_size); /* for sun_len: see sin_len above. */
841 soka->sun_family = AF_UNIX;
34f0f2b8 842 memcpy (soka->sun_path, SCM_STRING_CHARS (address),
439006bf
GH
843 SCM_STRING_LENGTH (address));
844 *size = SUN_LEN (soka);
370312ae
GH
845 return (struct sockaddr *) soka;
846 }
0e958795 847#endif
370312ae
GH
848 default:
849 scm_out_of_range (proc, SCM_MAKINUM (fam));
0f2d19dd 850 }
0f2d19dd 851}
3453619b 852#undef FUNC_NAME
370312ae 853
a1ec6916 854SCM_DEFINE (scm_connect, "connect", 3, 0, 1,
1bbd0b84 855 (SCM sock, SCM fam, SCM address, SCM args),
eefae538 856 "Initiate a connection from a socket using a specified address\n"
3453619b
GH
857 "family to the address\n"
858 "specified by @var{address} and possibly @var{args}.\n"
859 "The format required for @var{address}\n"
860 "and @var{args} depends on the family of the socket.\n\n"
b380b885 861 "For a socket of family @code{AF_UNIX},\n"
3453619b 862 "only @var{address} is specified and must be a string with the\n"
b380b885
MD
863 "filename where the socket is to be created.\n\n"
864 "For a socket of family @code{AF_INET},\n"
3453619b
GH
865 "@var{address} must be an integer IPv4 host address and\n"
866 "@var{args} must be a single integer port number.\n\n"
867 "For a socket of family @code{AF_INET6},\n"
868 "@var{address} must be an integer IPv6 host address and\n"
869 "@var{args} may be up to three integers:\n"
870 "port [flowinfo] [scope_id],\n"
871 "where flowinfo and scope_id default to zero.\n\n"
b380b885 872 "The return value is unspecified.")
1bbd0b84 873#define FUNC_NAME s_scm_connect
0f2d19dd 874{
370312ae
GH
875 int fd;
876 struct sockaddr *soka;
439006bf 877 int size;
0f2d19dd 878
78446828 879 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6
HWN
880 SCM_VALIDATE_OPFPORT (1, sock);
881 SCM_VALIDATE_INUM (2, fam);
ee149d03 882 fd = SCM_FPORT_FDES (sock);
439006bf
GH
883 soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME,
884 &size);
370312ae 885 if (connect (fd, soka, size) == -1)
439006bf
GH
886 {
887 int save_errno = errno;
888
889 free (soka);
890 errno = save_errno;
891 SCM_SYSERROR;
892 }
893 free (soka);
370312ae 894 return SCM_UNSPECIFIED;
0f2d19dd 895}
1bbd0b84 896#undef FUNC_NAME
0f2d19dd 897
a1ec6916 898SCM_DEFINE (scm_bind, "bind", 3, 0, 1,
1bbd0b84 899 (SCM sock, SCM fam, SCM address, SCM args),
eefae538 900 "Assign an address to the socket port @var{sock}.\n"
b380b885
MD
901 "Generally this only needs to be done for server sockets,\n"
902 "so they know where to look for incoming connections. A socket\n"
903 "without an address will be assigned one automatically when it\n"
904 "starts communicating.\n\n"
eefae538
GH
905 "The format of @var{address} and @var{args} depends\n"
906 "on the family of the socket.\n\n"
b380b885 907 "For a socket of family @code{AF_UNIX}, only @var{address}\n"
eefae538
GH
908 "is specified and must be a string with the filename where\n"
909 "the socket is to be created.\n\n"
910 "For a socket of family @code{AF_INET}, @var{address}\n"
911 "must be an integer IPv4 address and @var{args}\n"
912 "must be a single integer port number.\n\n"
913 "The values of the following variables can also be used for\n"
914 "@var{address}:\n\n"
b380b885
MD
915 "@defvar INADDR_ANY\n"
916 "Allow connections from any address.\n"
917 "@end defvar\n\n"
918 "@defvar INADDR_LOOPBACK\n"
919 "The address of the local host using the loopback device.\n"
920 "@end defvar\n\n"
921 "@defvar INADDR_BROADCAST\n"
922 "The broadcast address on the local network.\n"
923 "@end defvar\n\n"
924 "@defvar INADDR_NONE\n"
925 "No address.\n"
926 "@end defvar\n\n"
eefae538
GH
927 "For a socket of family @code{AF_INET6}, @var{address}\n"
928 "must be an integer IPv6 address and @var{args}\n"
929 "may be up to three integers:\n"
930 "port [flowinfo] [scope_id],\n"
931 "where flowinfo and scope_id default to zero.\n\n"
b380b885 932 "The return value is unspecified.")
1bbd0b84 933#define FUNC_NAME s_scm_bind
370312ae 934{
370312ae 935 struct sockaddr *soka;
439006bf 936 int size;
370312ae
GH
937 int fd;
938
78446828 939 sock = SCM_COERCE_OUTPORT (sock);
439006bf
GH
940 SCM_VALIDATE_OPFPORT (1, sock);
941 SCM_VALIDATE_INUM (2, fam);
942 soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME,
943 &size);
ee149d03 944 fd = SCM_FPORT_FDES (sock);
439006bf
GH
945 if (bind (fd, soka, size) == -1)
946 {
947 int save_errno = errno;
948
949 free (soka);
950 errno = save_errno;
1bbd0b84 951 SCM_SYSERROR;
439006bf
GH
952 }
953 free (soka);
370312ae
GH
954 return SCM_UNSPECIFIED;
955}
1bbd0b84 956#undef FUNC_NAME
370312ae 957
a1ec6916 958SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
1bbd0b84 959 (SCM sock, SCM backlog),
eefae538 960 "Enable @var{sock} to accept connection\n"
b380b885
MD
961 "requests. @var{backlog} is an integer specifying\n"
962 "the maximum length of the queue for pending connections.\n"
eefae538
GH
963 "If the queue fills, new clients will fail to connect until\n"
964 "the server calls @code{accept} to accept a connection from\n"
965 "the queue.\n\n"
b380b885 966 "The return value is unspecified.")
1bbd0b84 967#define FUNC_NAME s_scm_listen
370312ae
GH
968{
969 int fd;
78446828 970 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6
HWN
971 SCM_VALIDATE_OPFPORT (1, sock);
972 SCM_VALIDATE_INUM (2, backlog);
ee149d03 973 fd = SCM_FPORT_FDES (sock);
370312ae 974 if (listen (fd, SCM_INUM (backlog)) == -1)
1bbd0b84 975 SCM_SYSERROR;
370312ae
GH
976 return SCM_UNSPECIFIED;
977}
1bbd0b84 978#undef FUNC_NAME
370312ae
GH
979
980/* Put the components of a sockaddr into a new SCM vector. */
370312ae 981static SCM
aca23b65
MV
982scm_addr_vector (const struct sockaddr *address, int addr_size,
983 const char *proc)
0f2d19dd 984{
370312ae 985 short int fam = address->sa_family;
1d1559ce 986 SCM result =SCM_EOL;
34d19ef6 987
439006bf 988
5a525b84 989 switch (fam)
0f2d19dd 990 {
5a525b84
GH
991 case AF_INET:
992 {
e1368a8d 993 const struct sockaddr_in *nad = (struct sockaddr_in *) address;
439006bf 994
1d1559ce 995 result = scm_c_make_vector (3, SCM_UNSPECIFIED);
34d19ef6 996
1d1559ce
HWN
997 SCM_VECTOR_SET(result, 0, scm_ulong2num ((unsigned long) fam));
998 SCM_VECTOR_SET(result, 1, scm_ulong2num (ntohl (nad->sin_addr.s_addr)));
999 SCM_VECTOR_SET(result, 2, scm_ulong2num ((unsigned long) ntohs (nad->sin_port)));
5a525b84
GH
1000 }
1001 break;
a57a0b1e 1002#ifdef HAVE_IPV6
5a525b84
GH
1003 case AF_INET6:
1004 {
e1368a8d 1005 const struct sockaddr_in6 *nad = (struct sockaddr_in6 *) address;
5a525b84 1006
1d1559ce
HWN
1007 result = scm_c_make_vector (5, SCM_UNSPECIFIED);
1008 SCM_VECTOR_SET(result, 0, scm_ulong2num ((unsigned long) fam));
1009 SCM_VECTOR_SET(result, 1, ipv6_net_to_num (nad->sin6_addr.s6_addr));
1010 SCM_VECTOR_SET(result, 2, scm_ulong2num ((unsigned long) ntohs (nad->sin6_port)));
1011 SCM_VECTOR_SET(result, 3, scm_ulong2num ((unsigned long) nad->sin6_flowinfo));
5a525b84 1012#ifdef HAVE_SIN6_SCOPE_ID
1d1559ce 1013 SCM_VECTOR_SET(result, 4, scm_ulong2num ((unsigned long) nad->sin6_scope_id));
5a525b84 1014#else
1d1559ce 1015 SCM_VECTOR_SET(result, 4, SCM_INUM0);
0e958795 1016#endif
5a525b84
GH
1017 }
1018 break;
1019#endif
1020#ifdef HAVE_UNIX_DOMAIN_SOCKETS
1021 case AF_UNIX:
1022 {
e1368a8d 1023 const struct sockaddr_un *nad = (struct sockaddr_un *) address;
439006bf 1024
1d1559ce 1025 result = scm_c_make_vector (2, SCM_UNSPECIFIED);
34d19ef6 1026
1d1559ce 1027 SCM_VECTOR_SET(result, 0, scm_ulong2num ((unsigned long) fam));
aca23b65
MV
1028 /* When addr_size is not enough to cover sun_path, do not try
1029 to access it. */
1030 if (addr_size <= offsetof (struct sockaddr_un, sun_path))
1031 SCM_VECTOR_SET(result, 1, SCM_BOOL_F);
1032 else
1033 SCM_VECTOR_SET(result, 1, scm_mem2string (nad->sun_path,
1034 strlen (nad->sun_path)));
5a525b84
GH
1035 }
1036 break;
1037#endif
1038 default:
1039 scm_misc_error (proc, "Unrecognised address family: ~A",
1afff620 1040 scm_list_1 (SCM_MAKINUM (fam)));
0f2d19dd 1041 }
1d1559ce 1042 return result;
370312ae
GH
1043}
1044
439006bf
GH
1045/* calculate the size of a buffer large enough to hold any supported
1046 sockaddr type. if the buffer isn't large enough, certain system
1047 calls will return a truncated address. */
370312ae 1048
439006bf
GH
1049#if defined (HAVE_UNIX_DOMAIN_SOCKETS)
1050#define MAX_SIZE_UN sizeof (struct sockaddr_un)
0e958795 1051#else
439006bf 1052#define MAX_SIZE_UN 0
0e958795 1053#endif
439006bf 1054
a57a0b1e 1055#if defined (HAVE_IPV6)
5a525b84
GH
1056#define MAX_SIZE_IN6 sizeof (struct sockaddr_in6)
1057#else
1058#define MAX_SIZE_IN6 0
1059#endif
1060
1061#define MAX_ADDR_SIZE max (max (sizeof (struct sockaddr_in), MAX_SIZE_IN6),\
1062 MAX_SIZE_UN)
0f2d19dd 1063
a1ec6916 1064SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
1bbd0b84 1065 (SCM sock),
eefae538
GH
1066 "Accept a connection on a bound, listening socket.\n"
1067 "If there\n"
1068 "are no pending connections in the queue, wait until\n"
1069 "one is available unless the non-blocking option has been\n"
1070 "set on the socket.\n\n"
b380b885 1071 "The return value is a\n"
eefae538
GH
1072 "pair in which the @emph{car} is a new socket port for the\n"
1073 "connection and\n"
1074 "the @emph{cdr} is an object with address information about the\n"
1075 "client which initiated the connection.\n\n"
1076 "@var{sock} does not become part of the\n"
b380b885 1077 "connection and will continue to accept new requests.")
1bbd0b84 1078#define FUNC_NAME s_scm_accept
0f2d19dd 1079{
370312ae
GH
1080 int fd;
1081 int newfd;
1082 SCM address;
1083 SCM newsock;
439006bf
GH
1084 int addr_size = MAX_ADDR_SIZE;
1085 char max_addr[MAX_ADDR_SIZE];
1086 struct sockaddr *addr = (struct sockaddr *) max_addr;
370312ae 1087
78446828 1088 sock = SCM_COERCE_OUTPORT (sock);
439006bf 1089 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1090 fd = SCM_FPORT_FDES (sock);
439006bf
GH
1091 newfd = accept (fd, addr, &addr_size);
1092 if (newfd == -1)
1093 SCM_SYSERROR;
1094 newsock = SCM_SOCK_FD_TO_PORT (newfd);
aca23b65 1095 address = scm_addr_vector (addr, addr_size, FUNC_NAME);
370312ae 1096 return scm_cons (newsock, address);
0f2d19dd 1097}
1bbd0b84 1098#undef FUNC_NAME
0f2d19dd 1099
a1ec6916 1100SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0,
1bbd0b84 1101 (SCM sock),
eefae538 1102 "Return the address of @var{sock}, in the same form as the\n"
1e6808ea
MG
1103 "object returned by @code{accept}. On many systems the address\n"
1104 "of a socket in the @code{AF_FILE} namespace cannot be read.")
1bbd0b84 1105#define FUNC_NAME s_scm_getsockname
0f2d19dd 1106{
370312ae 1107 int fd;
439006bf
GH
1108 int addr_size = MAX_ADDR_SIZE;
1109 char max_addr[MAX_ADDR_SIZE];
1110 struct sockaddr *addr = (struct sockaddr *) max_addr;
1111
78446828 1112 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1113 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1114 fd = SCM_FPORT_FDES (sock);
439006bf 1115 if (getsockname (fd, addr, &addr_size) == -1)
1bbd0b84 1116 SCM_SYSERROR;
aca23b65 1117 return scm_addr_vector (addr, addr_size, FUNC_NAME);
0f2d19dd 1118}
1bbd0b84 1119#undef FUNC_NAME
0f2d19dd 1120
a1ec6916 1121SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0,
1bbd0b84 1122 (SCM sock),
eefae538 1123 "Return the address that @var{sock}\n"
1e6808ea
MG
1124 "is connected to, in the same form as the object returned by\n"
1125 "@code{accept}. On many systems the address of a socket in the\n"
1126 "@code{AF_FILE} namespace cannot be read.")
1bbd0b84 1127#define FUNC_NAME s_scm_getpeername
0f2d19dd 1128{
370312ae 1129 int fd;
439006bf
GH
1130 int addr_size = MAX_ADDR_SIZE;
1131 char max_addr[MAX_ADDR_SIZE];
1132 struct sockaddr *addr = (struct sockaddr *) max_addr;
1133
78446828 1134 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1135 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1136 fd = SCM_FPORT_FDES (sock);
439006bf 1137 if (getpeername (fd, addr, &addr_size) == -1)
1bbd0b84 1138 SCM_SYSERROR;
aca23b65 1139 return scm_addr_vector (addr, addr_size, FUNC_NAME);
0f2d19dd 1140}
1bbd0b84 1141#undef FUNC_NAME
0f2d19dd 1142
a1ec6916 1143SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
1bbd0b84 1144 (SCM sock, SCM buf, SCM flags),
eefae538
GH
1145 "Receive data from a socket port.\n"
1146 "@var{sock} must already\n"
b380b885
MD
1147 "be bound to the address from which data is to be received.\n"
1148 "@var{buf} is a string into which\n"
eefae538
GH
1149 "the data will be written. The size of @var{buf} limits\n"
1150 "the amount of\n"
b380b885 1151 "data which can be received: in the case of packet\n"
eefae538
GH
1152 "protocols, if a packet larger than this limit is encountered\n"
1153 "then some data\n"
b380b885
MD
1154 "will be irrevocably lost.\n\n"
1155 "The optional @var{flags} argument is a value or\n"
1156 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1157 "The value returned is the number of bytes read from the\n"
1158 "socket.\n\n"
1159 "Note that the data is read directly from the socket file\n"
1160 "descriptor:\n"
09831f94 1161 "any unread buffered port data is ignored.")
1bbd0b84 1162#define FUNC_NAME s_scm_recv
0f2d19dd 1163{
370312ae
GH
1164 int rv;
1165 int fd;
1166 int flg;
370312ae 1167
34d19ef6
HWN
1168 SCM_VALIDATE_OPFPORT (1, sock);
1169 SCM_VALIDATE_STRING (2, buf);
1170 SCM_VALIDATE_INUM_DEF_COPY (3, flags,0, flg);
ee149d03 1171 fd = SCM_FPORT_FDES (sock);
370312ae 1172
bfa974f0 1173 SCM_SYSCALL (rv = recv (fd, SCM_STRING_CHARS (buf), SCM_STRING_LENGTH (buf), flg));
370312ae 1174 if (rv == -1)
1bbd0b84 1175 SCM_SYSERROR;
370312ae 1176
1146b6cd 1177 return SCM_MAKINUM (rv);
370312ae 1178}
1bbd0b84 1179#undef FUNC_NAME
370312ae 1180
a1ec6916 1181SCM_DEFINE (scm_send, "send", 2, 1, 0,
1bbd0b84 1182 (SCM sock, SCM message, SCM flags),
eefae538
GH
1183 "Transmit the string @var{message} on a socket port @var{sock}.\n"
1184 "@var{sock} must already be bound to a destination address. The\n"
1185 "value returned is the number of bytes transmitted --\n"
1186 "it's possible for\n"
1187 "this to be less than the length of @var{message}\n"
1188 "if the socket is\n"
1189 "set to be non-blocking. The optional @var{flags} argument\n"
1190 "is a value or\n"
b380b885 1191 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1192 "Note that the data is written directly to the socket\n"
1193 "file descriptor:\n"
b380b885 1194 "any unflushed buffered port data is ignored.")
1bbd0b84 1195#define FUNC_NAME s_scm_send
370312ae
GH
1196{
1197 int rv;
1198 int fd;
1199 int flg;
1200
78446828 1201 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1202 SCM_VALIDATE_OPFPORT (1, sock);
a6d9e5ab 1203 SCM_VALIDATE_STRING (2, message);
34d19ef6 1204 SCM_VALIDATE_INUM_DEF_COPY (3, flags,0, flg);
ee149d03 1205 fd = SCM_FPORT_FDES (sock);
370312ae 1206
34f0f2b8 1207 SCM_SYSCALL (rv = send (fd, SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message), flg));
370312ae 1208 if (rv == -1)
1bbd0b84 1209 SCM_SYSERROR;
370312ae
GH
1210 return SCM_MAKINUM (rv);
1211}
1bbd0b84 1212#undef FUNC_NAME
370312ae 1213
a1ec6916 1214SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
60d02d09 1215 (SCM sock, SCM str, SCM flags, SCM start, SCM end),
eefae538 1216 "Return data from the socket port @var{sock} and also\n"
1e6808ea 1217 "information about where the data was received from.\n"
eefae538 1218 "@var{sock} must already be bound to the address from which\n"
1e6808ea
MG
1219 "data is to be received. @code{str}, is a string into which the\n"
1220 "data will be written. The size of @var{str} limits the amount\n"
1221 "of data which can be received: in the case of packet protocols,\n"
1222 "if a packet larger than this limit is encountered then some\n"
eefae538 1223 "data will be irrevocably lost.\n\n"
1e6808ea 1224 "The optional @var{flags} argument is a value or bitwise OR of\n"
eefae538 1225 "@code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc.\n\n"
1e6808ea
MG
1226 "The value returned is a pair: the @emph{car} is the number of\n"
1227 "bytes read from the socket and the @emph{cdr} an address object\n"
eefae538
GH
1228 "in the same form as returned by @code{accept}. The address\n"
1229 "will given as @code{#f} if not available, as is usually the\n"
1230 "case for stream sockets.\n\n"
1e6808ea 1231 "The @var{start} and @var{end} arguments specify a substring of\n"
eefae538 1232 "@var{str} to which the data should be written.\n\n"
1e6808ea
MG
1233 "Note that the data is read directly from the socket file\n"
1234 "descriptor: any unread buffered port data is ignored.")
1bbd0b84 1235#define FUNC_NAME s_scm_recvfrom
370312ae
GH
1236{
1237 int rv;
1238 int fd;
1239 int flg;
60d02d09
GH
1240 char *buf;
1241 int offset;
1146b6cd 1242 int cend;
370312ae 1243 SCM address;
439006bf
GH
1244 int addr_size = MAX_ADDR_SIZE;
1245 char max_addr[MAX_ADDR_SIZE];
1246 struct sockaddr *addr = (struct sockaddr *) max_addr;
370312ae 1247
34d19ef6 1248 SCM_VALIDATE_OPFPORT (1, sock);
60d02d09
GH
1249 fd = SCM_FPORT_FDES (sock);
1250 SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, str, buf, 4, start, offset,
1251 5, end, cend);
1146b6cd
GH
1252 if (SCM_UNBNDP (flags))
1253 flg = 0;
370312ae 1254 else
60d02d09 1255 SCM_VALIDATE_ULONG_COPY (3, flags, flg);
370312ae 1256
97d0e20b
GH
1257 /* recvfrom will not necessarily return an address. usually nothing
1258 is returned for stream sockets. */
439006bf 1259 addr->sa_family = AF_UNSPEC;
60d02d09 1260 SCM_SYSCALL (rv = recvfrom (fd, buf + offset,
1146b6cd 1261 cend - offset, flg,
439006bf 1262 addr, &addr_size));
370312ae 1263 if (rv == -1)
1bbd0b84 1264 SCM_SYSERROR;
eefae538 1265 if (addr->sa_family != AF_UNSPEC)
aca23b65 1266 address = scm_addr_vector (addr, addr_size, FUNC_NAME);
370312ae
GH
1267 else
1268 address = SCM_BOOL_F;
1269
1146b6cd 1270 return scm_cons (SCM_MAKINUM (rv), address);
0f2d19dd 1271}
1bbd0b84 1272#undef FUNC_NAME
0f2d19dd 1273
a1ec6916 1274SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
1bbd0b84 1275 (SCM sock, SCM message, SCM fam, SCM address, SCM args_and_flags),
eefae538
GH
1276 "Transmit the string @var{message} on the socket port\n"
1277 "@var{sock}. The\n"
1278 "destination address is specified using the @var{fam},\n"
1279 "@var{address} and\n"
1280 "@var{args_and_flags} arguments, in a similar way to the\n"
1281 "@code{connect} procedure. @var{args_and_flags} contains\n"
1282 "the usual connection arguments optionally followed by\n"
1283 "a flags argument, which is a value or\n"
b380b885 1284 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1285 "The value returned is the number of bytes transmitted --\n"
1286 "it's possible for\n"
1287 "this to be less than the length of @var{message} if the\n"
1288 "socket is\n"
1289 "set to be non-blocking.\n"
1290 "Note that the data is written directly to the socket\n"
1291 "file descriptor:\n"
b380b885 1292 "any unflushed buffered port data is ignored.")
1bbd0b84 1293#define FUNC_NAME s_scm_sendto
370312ae
GH
1294{
1295 int rv;
1296 int fd;
1297 int flg;
1298 struct sockaddr *soka;
439006bf 1299 int size;
370312ae 1300
78446828 1301 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1302 SCM_VALIDATE_FPORT (1, sock);
a6d9e5ab 1303 SCM_VALIDATE_STRING (2, message);
34d19ef6 1304 SCM_VALIDATE_INUM (3, fam);
ee149d03 1305 fd = SCM_FPORT_FDES (sock);
370312ae 1306 soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args_and_flags, 4,
1bbd0b84 1307 FUNC_NAME, &size);
370312ae
GH
1308 if (SCM_NULLP (args_and_flags))
1309 flg = 0;
1310 else
1311 {
34d19ef6 1312 SCM_VALIDATE_CONS (5, args_and_flags);
e4b265d8 1313 flg = SCM_NUM2ULONG (5, SCM_CAR (args_and_flags));
370312ae 1314 }
439006bf
GH
1315 SCM_SYSCALL (rv = sendto (fd, SCM_STRING_CHARS (message),
1316 SCM_STRING_LENGTH (message),
ae2fa5bc 1317 flg, soka, size));
370312ae 1318 if (rv == -1)
439006bf
GH
1319 {
1320 int save_errno = errno;
1321 free (soka);
1322 errno = save_errno;
1323 SCM_SYSERROR;
1324 }
1325 free (soka);
370312ae
GH
1326 return SCM_MAKINUM (rv);
1327}
1bbd0b84 1328#undef FUNC_NAME
370312ae
GH
1329\f
1330
1331
1332void
0f2d19dd 1333scm_init_socket ()
0f2d19dd 1334{
370312ae
GH
1335 /* protocol families. */
1336#ifdef AF_UNSPEC
86d31dfe 1337 scm_c_define ("AF_UNSPEC", SCM_MAKINUM (AF_UNSPEC));
370312ae
GH
1338#endif
1339#ifdef AF_UNIX
86d31dfe 1340 scm_c_define ("AF_UNIX", SCM_MAKINUM (AF_UNIX));
370312ae
GH
1341#endif
1342#ifdef AF_INET
86d31dfe 1343 scm_c_define ("AF_INET", SCM_MAKINUM (AF_INET));
370312ae 1344#endif
3453619b 1345#ifdef AF_INET6
86d31dfe 1346 scm_c_define ("AF_INET6", SCM_MAKINUM (AF_INET6));
3453619b 1347#endif
370312ae
GH
1348
1349#ifdef PF_UNSPEC
86d31dfe 1350 scm_c_define ("PF_UNSPEC", SCM_MAKINUM (PF_UNSPEC));
370312ae
GH
1351#endif
1352#ifdef PF_UNIX
86d31dfe 1353 scm_c_define ("PF_UNIX", SCM_MAKINUM (PF_UNIX));
370312ae
GH
1354#endif
1355#ifdef PF_INET
86d31dfe 1356 scm_c_define ("PF_INET", SCM_MAKINUM (PF_INET));
370312ae 1357#endif
3453619b 1358#ifdef PF_INET6
86d31dfe 1359 scm_c_define ("PF_INET6", SCM_MAKINUM (PF_INET6));
3453619b 1360#endif
370312ae 1361
66c73b76
GH
1362 /* standard addresses. */
1363#ifdef INADDR_ANY
86d31dfe 1364 scm_c_define ("INADDR_ANY", scm_ulong2num (INADDR_ANY));
66c73b76
GH
1365#endif
1366#ifdef INADDR_BROADCAST
86d31dfe 1367 scm_c_define ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST));
66c73b76
GH
1368#endif
1369#ifdef INADDR_NONE
86d31dfe 1370 scm_c_define ("INADDR_NONE", scm_ulong2num (INADDR_NONE));
66c73b76
GH
1371#endif
1372#ifdef INADDR_LOOPBACK
86d31dfe 1373 scm_c_define ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK));
66c73b76
GH
1374#endif
1375
370312ae
GH
1376 /* socket types. */
1377#ifdef SOCK_STREAM
86d31dfe 1378 scm_c_define ("SOCK_STREAM", SCM_MAKINUM (SOCK_STREAM));
370312ae
GH
1379#endif
1380#ifdef SOCK_DGRAM
86d31dfe 1381 scm_c_define ("SOCK_DGRAM", SCM_MAKINUM (SOCK_DGRAM));
370312ae
GH
1382#endif
1383#ifdef SOCK_RAW
86d31dfe 1384 scm_c_define ("SOCK_RAW", SCM_MAKINUM (SOCK_RAW));
370312ae
GH
1385#endif
1386
1387 /* setsockopt level. */
1388#ifdef SOL_SOCKET
86d31dfe 1389 scm_c_define ("SOL_SOCKET", SCM_MAKINUM (SOL_SOCKET));
370312ae
GH
1390#endif
1391#ifdef SOL_IP
86d31dfe 1392 scm_c_define ("SOL_IP", SCM_MAKINUM (SOL_IP));
370312ae
GH
1393#endif
1394#ifdef SOL_TCP
86d31dfe 1395 scm_c_define ("SOL_TCP", SCM_MAKINUM (SOL_TCP));
370312ae
GH
1396#endif
1397#ifdef SOL_UDP
86d31dfe 1398 scm_c_define ("SOL_UDP", SCM_MAKINUM (SOL_UDP));
370312ae
GH
1399#endif
1400
1401 /* setsockopt names. */
1402#ifdef SO_DEBUG
86d31dfe 1403 scm_c_define ("SO_DEBUG", SCM_MAKINUM (SO_DEBUG));
370312ae
GH
1404#endif
1405#ifdef SO_REUSEADDR
86d31dfe 1406 scm_c_define ("SO_REUSEADDR", SCM_MAKINUM (SO_REUSEADDR));
370312ae
GH
1407#endif
1408#ifdef SO_STYLE
86d31dfe 1409 scm_c_define ("SO_STYLE", SCM_MAKINUM (SO_STYLE));
370312ae
GH
1410#endif
1411#ifdef SO_TYPE
86d31dfe 1412 scm_c_define ("SO_TYPE", SCM_MAKINUM (SO_TYPE));
370312ae
GH
1413#endif
1414#ifdef SO_ERROR
86d31dfe 1415 scm_c_define ("SO_ERROR", SCM_MAKINUM (SO_ERROR));
370312ae
GH
1416#endif
1417#ifdef SO_DONTROUTE
86d31dfe 1418 scm_c_define ("SO_DONTROUTE", SCM_MAKINUM (SO_DONTROUTE));
370312ae
GH
1419#endif
1420#ifdef SO_BROADCAST
86d31dfe 1421 scm_c_define ("SO_BROADCAST", SCM_MAKINUM (SO_BROADCAST));
370312ae
GH
1422#endif
1423#ifdef SO_SNDBUF
86d31dfe 1424 scm_c_define ("SO_SNDBUF", SCM_MAKINUM (SO_SNDBUF));
370312ae
GH
1425#endif
1426#ifdef SO_RCVBUF
86d31dfe 1427 scm_c_define ("SO_RCVBUF", SCM_MAKINUM (SO_RCVBUF));
370312ae
GH
1428#endif
1429#ifdef SO_KEEPALIVE
86d31dfe 1430 scm_c_define ("SO_KEEPALIVE", SCM_MAKINUM (SO_KEEPALIVE));
370312ae
GH
1431#endif
1432#ifdef SO_OOBINLINE
86d31dfe 1433 scm_c_define ("SO_OOBINLINE", SCM_MAKINUM (SO_OOBINLINE));
370312ae
GH
1434#endif
1435#ifdef SO_NO_CHECK
86d31dfe 1436 scm_c_define ("SO_NO_CHECK", SCM_MAKINUM (SO_NO_CHECK));
370312ae
GH
1437#endif
1438#ifdef SO_PRIORITY
86d31dfe 1439 scm_c_define ("SO_PRIORITY", SCM_MAKINUM (SO_PRIORITY));
370312ae
GH
1440#endif
1441#ifdef SO_LINGER
86d31dfe 1442 scm_c_define ("SO_LINGER", SCM_MAKINUM (SO_LINGER));
370312ae
GH
1443#endif
1444
1445 /* recv/send options. */
1446#ifdef MSG_OOB
86d31dfe 1447 scm_c_define ("MSG_OOB", SCM_MAKINUM (MSG_OOB));
370312ae
GH
1448#endif
1449#ifdef MSG_PEEK
86d31dfe 1450 scm_c_define ("MSG_PEEK", SCM_MAKINUM (MSG_PEEK));
370312ae
GH
1451#endif
1452#ifdef MSG_DONTROUTE
86d31dfe 1453 scm_c_define ("MSG_DONTROUTE", SCM_MAKINUM (MSG_DONTROUTE));
370312ae
GH
1454#endif
1455
b4e15479
SJ
1456#ifdef __MINGW32__
1457 scm_i_init_socket_Win32 ();
1458#endif
1459
0f2d19dd 1460 scm_add_feature ("socket");
370312ae 1461
a0599745 1462#include "libguile/socket.x"
0f2d19dd
JB
1463}
1464
89e00824
ML
1465
1466/*
1467 Local Variables:
1468 c-file-style: "gnu"
1469 End:
1470*/