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