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