degenerate let forms
[bpt/guile.git] / libguile / socket.c
CommitLineData
d21a1dc8 1/* Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
b9b88351 2 * 2006, 2007, 2009, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
d21a1dc8 3 *
73be1d9e 4 * This library is free software; you can redistribute it and/or
53befeb7
NJ
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation; either version 3 of
7 * the License, or (at your option) any later version.
86667910 8 *
53befeb7
NJ
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
73be1d9e
MV
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
86667910 13 *
73be1d9e
MV
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
53befeb7
NJ
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
73be1d9e 18 */
1bbd0b84 19
1bbd0b84 20
0f2d19dd
JB
21\f
22
dbb605f5 23#ifdef HAVE_CONFIG_H
eccde741
RB
24# include <config.h>
25#endif
26
e6e2e95a 27#include <errno.h>
cc948107 28#include <verify.h>
e6e2e95a 29
af68e5e5
SJ
30#ifdef HAVE_STDINT_H
31#include <stdint.h>
32#endif
95b88819
GH
33#ifdef HAVE_STRING_H
34#include <string.h>
35#endif
370312ae 36#include <unistd.h>
0f2d19dd
JB
37#include <sys/types.h>
38#include <sys/socket.h>
1ba8c23a 39#ifdef HAVE_UNIX_DOMAIN_SOCKETS
0f2d19dd 40#include <sys/un.h>
0e958795 41#endif
0f2d19dd
JB
42#include <netinet/in.h>
43#include <netdb.h>
44#include <arpa/inet.h>
09b204d3 45
b0dbbacb
AW
46#include <gmp.h>
47
48#include "libguile/_scm.h"
49#include "libguile/arrays.h"
50#include "libguile/feature.h"
51#include "libguile/fports.h"
52#include "libguile/strings.h"
53#include "libguile/vectors.h"
54#include "libguile/dynwind.h"
55#include "libguile/srfi-13.h"
56
57#include "libguile/validate.h"
58#include "libguile/socket.h"
59
60#if SCM_ENABLE_DEPRECATED == 1
61# include "libguile/deprecation.h"
82893676 62#endif
0f2d19dd 63
b0dbbacb 64
0f2d19dd 65
97d0e20b 66#if defined (HAVE_UNIX_DOMAIN_SOCKETS) && !defined (SUN_LEN)
9fcee9da 67#define SUN_LEN(ptr) (offsetof (struct sockaddr_un, sun_path) \
97d0e20b
GH
68 + strlen ((ptr)->sun_path))
69#endif
70
f43f3620
LC
71/* The largest possible socket address. Wrapping it in a union guarantees
72 that the compiler will make it suitably aligned. */
73typedef union
74{
75 struct sockaddr sockaddr;
76 struct sockaddr_in sockaddr_in;
77
78#ifdef HAVE_UNIX_DOMAIN_SOCKETS
79 struct sockaddr_un sockaddr_un;
80#endif
81#ifdef HAVE_IPV6
82 struct sockaddr_in6 sockaddr_in6;
83#endif
84} scm_t_max_sockaddr;
85
86
87/* Maximum size of a socket address. */
88#define MAX_ADDR_SIZE (sizeof (scm_t_max_sockaddr))
89
90
0f2d19dd
JB
91\f
92
66c73b76
GH
93#ifdef HAVE_INET_NETOF
94SCM_DEFINE (scm_inet_netof, "inet-netof", 1, 0, 0,
95 (SCM address),
eefae538
GH
96 "Return the network number part of the given IPv4\n"
97 "Internet address. E.g.,\n\n"
66c73b76
GH
98 "@lisp\n"
99 "(inet-netof 2130706433) @result{} 127\n"
100 "@end lisp")
101#define FUNC_NAME s_scm_inet_netof
102{
103 struct in_addr addr;
104 addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
b9bd8526 105 return scm_from_ulong (inet_netof (addr));
66c73b76
GH
106}
107#undef FUNC_NAME
108#endif
109
110#ifdef HAVE_INET_LNAOF
111SCM_DEFINE (scm_lnaof, "inet-lnaof", 1, 0, 0,
112 (SCM address),
113 "Return the local-address-with-network part of the given\n"
eefae538
GH
114 "IPv4 Internet address, using the obsolete class A/B/C system.\n"
115 "E.g.,\n\n"
66c73b76
GH
116 "@lisp\n"
117 "(inet-lnaof 2130706433) @result{} 1\n"
118 "@end lisp")
119#define FUNC_NAME s_scm_lnaof
120{
121 struct in_addr addr;
122 addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
b9bd8526 123 return scm_from_ulong (inet_lnaof (addr));
66c73b76
GH
124}
125#undef FUNC_NAME
126#endif
127
128#ifdef HAVE_INET_MAKEADDR
129SCM_DEFINE (scm_inet_makeaddr, "inet-makeaddr", 2, 0, 0,
130 (SCM net, SCM lna),
eefae538 131 "Make an IPv4 Internet address by combining the network number\n"
66c73b76 132 "@var{net} with the local-address-within-network number\n"
eefae538 133 "@var{lna}. E.g.,\n\n"
66c73b76
GH
134 "@lisp\n"
135 "(inet-makeaddr 127 1) @result{} 2130706433\n"
136 "@end lisp")
137#define FUNC_NAME s_scm_inet_makeaddr
138{
139 struct in_addr addr;
140 unsigned long netnum;
141 unsigned long lnanum;
142
143 netnum = SCM_NUM2ULONG (1, net);
144 lnanum = SCM_NUM2ULONG (2, lna);
145 addr = inet_makeaddr (netnum, lnanum);
b9bd8526 146 return scm_from_ulong (ntohl (addr.s_addr));
66c73b76
GH
147}
148#undef FUNC_NAME
149#endif
150
a57a0b1e 151#ifdef HAVE_IPV6
eefae538 152
66c73b76
GH
153/* flip a 128 bit IPv6 address between host and network order. */
154#ifdef WORDS_BIGENDIAN
155#define FLIP_NET_HOST_128(addr)
156#else
157#define FLIP_NET_HOST_128(addr)\
158{\
159 int i;\
160 \
161 for (i = 0; i < 8; i++)\
162 {\
2de4f939 163 scm_t_uint8 c = (addr)[i];\
66c73b76
GH
164 \
165 (addr)[i] = (addr)[15 - i];\
166 (addr)[15 - i] = c;\
167 }\
168}
169#endif
170
2de4f939
RB
171#ifdef WORDS_BIGENDIAN
172#define FLIPCPY_NET_HOST_128(dest, src) memcpy (dest, src, 16)
173#else
174#define FLIPCPY_NET_HOST_128(dest, src) \
175{ \
176 const scm_t_uint8 *tmp_srcp = (src) + 15; \
177 scm_t_uint8 *tmp_destp = (dest); \
178 \
179 do { \
180 *tmp_destp++ = *tmp_srcp--; \
181 } while (tmp_srcp != (src)); \
182}
183#endif
184
185
7310ad0c 186#if (SIZEOF_SCM_T_BITS * SCM_CHAR_BIT) > 128
2de4f939
RB
187#error "Assumption that scm_t_bits <= 128 bits has been violated."
188#endif
189
7310ad0c 190#if (SIZEOF_UNSIGNED_LONG * SCM_CHAR_BIT) > 128
2de4f939
RB
191#error "Assumption that unsigned long <= 128 bits has been violated."
192#endif
193
7310ad0c 194#if (SIZEOF_UNSIGNED_LONG_LONG * SCM_CHAR_BIT) > 128
2de4f939
RB
195#error "Assumption that unsigned long long <= 128 bits has been violated."
196#endif
197
66c73b76
GH
198/* convert a 128 bit IPv6 address in network order to a host ordered
199 SCM integer. */
7cee5b31
MV
200static SCM
201scm_from_ipv6 (const scm_t_uint8 *src)
66c73b76 202{
2b4d1547
KR
203 SCM result = scm_i_mkbig ();
204 mpz_import (SCM_I_BIG_MPZ (result),
205 1, /* chunk */
206 1, /* big-endian chunk ordering */
207 16, /* chunks are 16 bytes long */
208 1, /* big-endian byte ordering */
209 0, /* "nails" -- leading unused bits per chunk */
210 src);
211 return scm_i_normbig (result);
212}
66c73b76
GH
213
214/* convert a host ordered SCM integer to a 128 bit IPv6 address in
215 network order. */
7cee5b31
MV
216static void
217scm_to_ipv6 (scm_t_uint8 dst[16], SCM src)
66c73b76 218{
e11e83f3 219 if (SCM_I_INUMP (src))
66c73b76 220 {
e11e83f3 221 scm_t_signed_bits n = SCM_I_INUM (src);
7cee5b31
MV
222 if (n < 0)
223 scm_out_of_range (NULL, src);
2de4f939
RB
224#ifdef WORDS_BIGENDIAN
225 memset (dst, 0, 16 - sizeof (scm_t_signed_bits));
226 memcpy (dst + (16 - sizeof (scm_t_signed_bits)),
227 &n,
228 sizeof (scm_t_signed_bits));
229#else
230 memset (dst + sizeof (scm_t_signed_bits),
231 0,
232 16 - sizeof (scm_t_signed_bits));
233 /* FIXME: this pair of ops is kinda wasteful -- should rewrite as
234 a single loop perhaps, similar to the handling of bignums. */
235 memcpy (dst, &n, sizeof (scm_t_signed_bits));
236 FLIP_NET_HOST_128 (dst);
237#endif
66c73b76 238 }
7cee5b31 239 else if (SCM_BIGP (src))
66c73b76 240 {
2de4f939 241 size_t count;
7cee5b31
MV
242
243 if ((mpz_sgn (SCM_I_BIG_MPZ (src)) < 0)
244 || mpz_sizeinbase (SCM_I_BIG_MPZ (src), 2) > 128)
245 scm_out_of_range (NULL, src);
246
66c73b76 247 memset (dst, 0, 16);
2de4f939
RB
248 mpz_export (dst,
249 &count,
250 1, /* big-endian chunk ordering */
251 16, /* chunks are 16 bytes long */
252 1, /* big-endian byte ordering */
253 0, /* "nails" -- leading unused bits per chunk */
254 SCM_I_BIG_MPZ (src));
255 scm_remember_upto_here_1 (src);
66c73b76 256 }
2de4f939 257 else
1ff4da65 258 scm_wrong_type_arg_msg ("scm_to_ipv6", 0, src, "integer");
2de4f939
RB
259}
260
e91f21dc 261#endif /* HAVE_IPV6 */
66c73b76 262
e91f21dc 263\f
66c73b76 264
66c73b76
GH
265SCM_DEFINE (scm_inet_ntop, "inet-ntop", 2, 0, 0,
266 (SCM family, SCM address),
eefae538 267 "Convert a network address into a printable string.\n"
66c73b76
GH
268 "Note that unlike the C version of this function,\n"
269 "the input is an integer with normal host byte ordering.\n"
eefae538 270 "@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g.,\n\n"
66c73b76 271 "@lisp\n"
dd85ce47 272 "(inet-ntop AF_INET 2130706433) @result{} \"127.0.0.1\"\n"
187a4390
NJ
273 "(inet-ntop AF_INET6 (- (expt 2 128) 1))\n"
274 " @result{} \"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\"\n"
66c73b76
GH
275 "@end lisp")
276#define FUNC_NAME s_scm_inet_ntop
277{
278 int af;
279#ifdef INET6_ADDRSTRLEN
280 char dst[INET6_ADDRSTRLEN];
281#else
282 char dst[46];
283#endif
7a5fb796 284 const char *result;
66c73b76 285
7cee5b31 286 af = scm_to_int (family);
e91f21dc
LC
287 SCM_ASSERT_RANGE (1, family,
288 af == AF_INET
289#ifdef HAVE_IPV6
290 || af == AF_INET6
291#endif
292 );
66c73b76 293 if (af == AF_INET)
7a5fb796
LC
294 {
295 scm_t_uint32 addr4;
296
297 addr4 = htonl (SCM_NUM2ULONG (2, address));
298 result = inet_ntop (af, &addr4, dst, sizeof (dst));
299 }
e91f21dc
LC
300#ifdef HAVE_IPV6
301 else if (af == AF_INET6)
7a5fb796
LC
302 {
303 char addr6[16];
304
305 scm_to_ipv6 ((scm_t_uint8 *) addr6, address);
306 result = inet_ntop (af, &addr6, dst, sizeof (dst));
307 }
e91f21dc
LC
308#endif
309 else
310 SCM_MISC_ERROR ("unsupported address family", family);
7a5fb796
LC
311
312 if (result == NULL)
66c73b76 313 SCM_SYSERROR;
7a5fb796 314
cc95e00a 315 return scm_from_locale_string (dst);
66c73b76
GH
316}
317#undef FUNC_NAME
66c73b76 318
e91f21dc
LC
319SCM_DEFINE (scm_inet_pton, "inet-pton", 2, 0, 0,
320 (SCM family, SCM address),
321 "Convert a string containing a printable network address to\n"
322 "an integer address. Note that unlike the C version of this\n"
323 "function,\n"
324 "the result is an integer with normal host byte ordering.\n"
325 "@var{family} can be @code{AF_INET} or @code{AF_INET6}. E.g.,\n\n"
326 "@lisp\n"
327 "(inet-pton AF_INET \"127.0.0.1\") @result{} 2130706433\n"
328 "(inet-pton AF_INET6 \"::1\") @result{} 1\n"
329 "@end lisp")
330#define FUNC_NAME s_scm_inet_pton
331{
332 int af;
333 char *src;
334 scm_t_uint32 dst[4];
335 int rv, eno;
336
337 af = scm_to_int (family);
338 SCM_ASSERT_RANGE (1, family,
339 af == AF_INET
340#ifdef HAVE_IPV6
341 || af == AF_INET6
342#endif
343 );
eefae538 344
e91f21dc
LC
345 src = scm_to_locale_string (address);
346 rv = inet_pton (af, src, dst);
347 eno = errno;
348 free (src);
349 errno = eno;
350
351 if (rv == -1)
352 SCM_SYSERROR;
353 else if (rv == 0)
354 SCM_MISC_ERROR ("Bad address", SCM_EOL);
355 if (af == AF_INET)
356 return scm_from_ulong (ntohl (*dst));
357#ifdef HAVE_IPV6
358 else if (af == AF_INET6)
359 return scm_from_ipv6 ((scm_t_uint8 *) dst);
360#endif
361 else
362 SCM_MISC_ERROR ("unsupported address family", family);
363}
364#undef FUNC_NAME
365
366\f
bc45012d 367SCM_SYMBOL (sym_socket, "socket");
82ddea4e 368
439006bf 369#define SCM_SOCK_FD_TO_PORT(fd) scm_fdes_to_port (fd, "r+0", sym_socket)
1bbd0b84 370
a1ec6916 371SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
1bbd0b84 372 (SCM family, SCM style, SCM proto),
1e6808ea 373 "Return a new socket port of the type specified by @var{family},\n"
eefae538 374 "@var{style} and @var{proto}. All three parameters are\n"
3453619b
GH
375 "integers. Supported values for @var{family} are\n"
376 "@code{AF_UNIX}, @code{AF_INET} and @code{AF_INET6}.\n"
377 "Typical values for @var{style} are @code{SOCK_STREAM},\n"
eefae538
GH
378 "@code{SOCK_DGRAM} and @code{SOCK_RAW}.\n\n"
379 "@var{proto} can be obtained from a protocol name using\n"
1e6808ea 380 "@code{getprotobyname}. A value of zero specifies the default\n"
eefae538 381 "protocol, which is usually right.\n\n"
1e6808ea
MG
382 "A single socket port cannot by used for communication until it\n"
383 "has been connected to another socket.")
1bbd0b84 384#define FUNC_NAME s_scm_socket
0f2d19dd 385{
370312ae 386 int fd;
370312ae 387
7cee5b31
MV
388 fd = socket (scm_to_int (family),
389 scm_to_int (style),
390 scm_to_int (proto));
439006bf
GH
391 if (fd == -1)
392 SCM_SYSERROR;
393 return SCM_SOCK_FD_TO_PORT (fd);
0f2d19dd 394}
1bbd0b84 395#undef FUNC_NAME
0f2d19dd 396
0e958795 397#ifdef HAVE_SOCKETPAIR
a1ec6916 398SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
1bbd0b84 399 (SCM family, SCM style, SCM proto),
1e6808ea 400 "Return a pair of connected (but unnamed) socket ports of the\n"
eefae538 401 "type specified by @var{family}, @var{style} and @var{proto}.\n"
1e6808ea
MG
402 "Many systems support only socket pairs of the @code{AF_UNIX}\n"
403 "family. Zero is likely to be the only meaningful value for\n"
eefae538 404 "@var{proto}.")
1bbd0b84 405#define FUNC_NAME s_scm_socketpair
0f2d19dd 406{
370312ae
GH
407 int fam;
408 int fd[2];
370312ae 409
7cee5b31 410 fam = scm_to_int (family);
370312ae 411
7cee5b31 412 if (socketpair (fam, scm_to_int (style), scm_to_int (proto), fd) == -1)
1bbd0b84 413 SCM_SYSERROR;
370312ae 414
439006bf 415 return scm_cons (SCM_SOCK_FD_TO_PORT (fd[0]), SCM_SOCK_FD_TO_PORT (fd[1]));
0f2d19dd 416}
1bbd0b84 417#undef FUNC_NAME
0e958795 418#endif
0f2d19dd 419
f43f3620
LC
420/* Possible results for `getsockopt ()'. Wrapping it into a union guarantees
421 suitable alignment. */
422typedef union
423{
424#ifdef HAVE_STRUCT_LINGER
425 struct linger linger;
426#endif
427 size_t size;
428 int integer;
429} scm_t_getsockopt_result;
430
a1ec6916 431SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
1bbd0b84 432 (SCM sock, SCM level, SCM optname),
72e3dae1
KR
433 "Return an option value from socket port @var{sock}.\n"
434 "\n"
435 "@var{level} is an integer specifying a protocol layer, either\n"
436 "@code{SOL_SOCKET} for socket level options, or a protocol\n"
437 "number from the @code{IPPROTO} constants or @code{getprotoent}\n"
438 "(@pxref{Network Databases}).\n"
439 "\n"
440 "@defvar SOL_SOCKET\n"
441 "@defvarx IPPROTO_IP\n"
442 "@defvarx IPPROTO_TCP\n"
443 "@defvarx IPPROTO_UDP\n"
444 "@end defvar\n"
445 "\n"
446 "@var{optname} is an integer specifying an option within the\n"
447 "protocol layer.\n"
448 "\n"
449 "For @code{SOL_SOCKET} level the following @var{optname}s are\n"
450 "defined (when provided by the system). For their meaning see\n"
451 "@ref{Socket-Level Options,,, libc, The GNU C Library Reference\n"
452 "Manual}, or @command{man 7 socket}.\n"
453 "\n"
454 "@defvar SO_DEBUG\n"
455 "@defvarx SO_REUSEADDR\n"
456 "@defvarx SO_STYLE\n"
457 "@defvarx SO_TYPE\n"
458 "@defvarx SO_ERROR\n"
459 "@defvarx SO_DONTROUTE\n"
460 "@defvarx SO_BROADCAST\n"
461 "@defvarx SO_SNDBUF\n"
462 "@defvarx SO_RCVBUF\n"
463 "@defvarx SO_KEEPALIVE\n"
464 "@defvarx SO_OOBINLINE\n"
465 "@defvarx SO_NO_CHECK\n"
466 "@defvarx SO_PRIORITY\n"
5f24f1b5 467 "@defvarx SO_REUSEPORT\n"
72e3dae1
KR
468 "The value returned is an integer.\n"
469 "@end defvar\n"
470 "\n"
471 "@defvar SO_LINGER\n"
b7e64f8b
BT
472 "The value returned is a pair of integers\n"
473 "@code{(@var{enable} . @var{timeout})}. On old systems without\n"
72e3dae1 474 "timeout support (ie.@: without @code{struct linger}), only\n"
b7e64f8b 475 "@var{enable} has an effect but the value in Guile is always a\n"
72e3dae1
KR
476 "pair.\n"
477 "@end defvar")
1bbd0b84 478#define FUNC_NAME s_scm_getsockopt
0f2d19dd 479{
370312ae 480 int fd;
439006bf 481 /* size of optval is the largest supported option. */
f43f3620
LC
482 scm_t_getsockopt_result optval;
483 socklen_t optlen = sizeof (optval);
370312ae
GH
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);
f43f3620 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
f43f3620 502 struct linger *ling = (struct linger *) &optval;
439006bf 503
b9bd8526
MV
504 return scm_cons (scm_from_long (ling->l_onoff),
505 scm_from_long (ling->l_linger));
370312ae 506#else
f43f3620 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 {
f43f3620 522 return scm_from_size_t (*(size_t *) &optval);
439006bf
GH
523 }
524 }
f43f3620 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),
72e3dae1
KR
531 "Set an option on socket port @var{sock}. The return value is\n"
532 "unspecified.\n"
533 "\n"
534 "@var{level} is an integer specifying a protocol layer, either\n"
535 "@code{SOL_SOCKET} for socket level options, or a protocol\n"
536 "number from the @code{IPPROTO} constants or @code{getprotoent}\n"
537 "(@pxref{Network Databases}).\n"
538 "\n"
539 "@defvar SOL_SOCKET\n"
540 "@defvarx IPPROTO_IP\n"
541 "@defvarx IPPROTO_TCP\n"
542 "@defvarx IPPROTO_UDP\n"
543 "@end defvar\n"
544 "\n"
545 "@var{optname} is an integer specifying an option within the\n"
546 "protocol layer.\n"
547 "\n"
548 "For @code{SOL_SOCKET} level the following @var{optname}s are\n"
549 "defined (when provided by the system). For their meaning see\n"
550 "@ref{Socket-Level Options,,, libc, The GNU C Library Reference\n"
551 "Manual}, or @command{man 7 socket}.\n"
552 "\n"
553 "@defvar SO_DEBUG\n"
554 "@defvarx SO_REUSEADDR\n"
555 "@defvarx SO_STYLE\n"
556 "@defvarx SO_TYPE\n"
557 "@defvarx SO_ERROR\n"
558 "@defvarx SO_DONTROUTE\n"
559 "@defvarx SO_BROADCAST\n"
560 "@defvarx SO_SNDBUF\n"
561 "@defvarx SO_RCVBUF\n"
562 "@defvarx SO_KEEPALIVE\n"
563 "@defvarx SO_OOBINLINE\n"
564 "@defvarx SO_NO_CHECK\n"
565 "@defvarx SO_PRIORITY\n"
5f24f1b5 566 "@defvarx SO_REUSEPORT\n"
72e3dae1
KR
567 "@var{value} is an integer.\n"
568 "@end defvar\n"
569 "\n"
570 "@defvar SO_LINGER\n"
571 "@var{value} is a pair of integers @code{(@var{ENABLE}\n"
572 ". @var{TIMEOUT})}. On old systems without timeout support\n"
573 "(ie.@: without @code{struct linger}), only @var{ENABLE} has an\n"
574 "effect but the value in Guile is always a pair.\n"
575 "@end defvar\n"
576 "\n"
577 "@c Note that we refer only to ``man ip'' here. On GNU/Linux it's\n"
578 "@c ``man 7 ip'' but on NetBSD it's ``man 4 ip''.\n"
579 "@c \n"
580 "For IP level (@code{IPPROTO_IP}) the following @var{optname}s\n"
581 "are defined (when provided by the system). See @command{man\n"
582 "ip} for what they mean.\n"
583 "\n"
511246a1
TCM
584 "@defvar IP_MULTICAST_IF\n"
585 "This sets the source interface used by multicast traffic.\n"
586 "@end defvar\n"
587 "\n"
588 "@defvar IP_MULTICAST_TTL\n"
589 "This sets the default TTL for multicast traffic. This defaults \n"
590 "to 1 and should be increased to allow traffic to pass beyond the\n"
591 "local network.\n"
592 "@end defvar\n"
593 "\n"
72e3dae1
KR
594 "@defvar IP_ADD_MEMBERSHIP\n"
595 "@defvarx IP_DROP_MEMBERSHIP\n"
596 "These can be used only with @code{setsockopt}, not\n"
597 "@code{getsockopt}. @var{value} is a pair\n"
598 "@code{(@var{MULTIADDR} . @var{INTERFACEADDR})} of IPv4\n"
599 "addresses (@pxref{Network Address Conversion}).\n"
600 "@var{MULTIADDR} is a multicast address to be added to or\n"
601 "dropped from the interface @var{INTERFACEADDR}.\n"
602 "@var{INTERFACEADDR} can be @code{INADDR_ANY} to have the system\n"
603 "select the interface. @var{INTERFACEADDR} can also be an\n"
f1b7209b
KR
604 "interface index number, on systems supporting that.\n"
605 "@end defvar")
1bbd0b84 606#define FUNC_NAME s_scm_setsockopt
0f2d19dd 607{
370312ae 608 int fd;
1c80707c
MV
609
610 int opt_int;
370312ae 611#ifdef HAVE_STRUCT_LINGER
1c80707c 612 struct linger opt_linger;
370312ae 613#endif
ecc9f40f 614
56a3dcd4 615#ifdef HAVE_STRUCT_IP_MREQ
1c80707c 616 struct ip_mreq opt_mreq;
ecc9f40f 617#endif
1c80707c
MV
618
619 const void *optval = NULL;
620 socklen_t optlen = 0;
621
370312ae 622 int ilevel, ioptname;
439006bf 623
78446828 624 sock = SCM_COERCE_OUTPORT (sock);
439006bf
GH
625
626 SCM_VALIDATE_OPFPORT (1, sock);
7cee5b31
MV
627 ilevel = scm_to_int (level);
628 ioptname = scm_to_int (optname);
439006bf 629
ee149d03 630 fd = SCM_FPORT_FDES (sock);
1c80707c 631
439006bf 632 if (ilevel == SOL_SOCKET)
370312ae 633 {
439006bf
GH
634#ifdef SO_LINGER
635 if (ioptname == SO_LINGER)
636 {
370312ae 637#ifdef HAVE_STRUCT_LINGER
d2e53ed6 638 SCM_ASSERT (scm_is_pair (value), value, SCM_ARG4, FUNC_NAME);
1c80707c
MV
639 opt_linger.l_onoff = scm_to_int (SCM_CAR (value));
640 opt_linger.l_linger = scm_to_int (SCM_CDR (value));
641 optlen = sizeof (struct linger);
642 optval = &opt_linger;
370312ae 643#else
d2e53ed6 644 SCM_ASSERT (scm_is_pair (value), value, SCM_ARG4, FUNC_NAME);
1c80707c 645 opt_int = scm_to_int (SCM_CAR (value));
439006bf 646 /* timeout is ignored, but may as well validate it. */
1c80707c
MV
647 scm_to_int (SCM_CDR (value));
648 optlen = sizeof (int);
649 optval = &opt_int;
439006bf
GH
650#endif
651 }
652 else
653#endif
654 if (0
370312ae 655#ifdef SO_SNDBUF
439006bf 656 || ioptname == SO_SNDBUF
370312ae
GH
657#endif
658#ifdef SO_RCVBUF
439006bf 659 || ioptname == SO_RCVBUF
370312ae 660#endif
439006bf
GH
661 )
662 {
1c80707c
MV
663 opt_int = scm_to_int (value);
664 optlen = sizeof (size_t);
665 optval = &opt_int;
439006bf
GH
666 }
667 }
1c80707c 668
56a3dcd4 669#ifdef HAVE_STRUCT_IP_MREQ
1c80707c
MV
670 if (ilevel == IPPROTO_IP &&
671 (ioptname == IP_ADD_MEMBERSHIP || ioptname == IP_DROP_MEMBERSHIP))
0f2d19dd 672 {
1c80707c
MV
673 /* Fourth argument must be a pair of addresses. */
674 SCM_ASSERT (scm_is_pair (value), value, SCM_ARG4, FUNC_NAME);
675 opt_mreq.imr_multiaddr.s_addr = htonl (scm_to_ulong (SCM_CAR (value)));
676 opt_mreq.imr_interface.s_addr = htonl (scm_to_ulong (SCM_CDR (value)));
677 optlen = sizeof (opt_mreq);
678 optval = &opt_mreq;
679 }
ecc9f40f 680#endif
439006bf 681
1c80707c
MV
682 if (optval == NULL)
683 {
684 /* Most options take an int. */
685 opt_int = scm_to_int (value);
686 optlen = sizeof (int);
687 optval = &opt_int;
0f2d19dd 688 }
1c80707c
MV
689
690 if (setsockopt (fd, ilevel, ioptname, optval, optlen) == -1)
1bbd0b84 691 SCM_SYSERROR;
370312ae 692 return SCM_UNSPECIFIED;
0f2d19dd 693}
1bbd0b84 694#undef FUNC_NAME
0f2d19dd 695
cc948107
LC
696/* Our documentation hard-codes this mapping, so make sure it holds. */
697verify (SHUT_RD == 0);
698verify (SHUT_WR == 1);
699verify (SHUT_RDWR == 2);
700
a1ec6916 701SCM_DEFINE (scm_shutdown, "shutdown", 2, 0, 0,
1bbd0b84 702 (SCM sock, SCM how),
b380b885 703 "Sockets can be closed simply by using @code{close-port}. The\n"
bb2c02f2 704 "@code{shutdown} procedure allows reception or transmission on a\n"
b380b885
MD
705 "connection to be shut down individually, according to the parameter\n"
706 "@var{how}:\n\n"
707 "@table @asis\n"
708 "@item 0\n"
709 "Stop receiving data for this socket. If further data arrives, reject it.\n"
710 "@item 1\n"
711 "Stop trying to transmit data from this socket. Discard any\n"
712 "data waiting to be sent. Stop looking for acknowledgement of\n"
713 "data already sent; don't retransmit it if it is lost.\n"
714 "@item 2\n"
715 "Stop both reception and transmission.\n"
716 "@end table\n\n"
717 "The return value is unspecified.")
1bbd0b84 718#define FUNC_NAME s_scm_shutdown
0f2d19dd 719{
370312ae 720 int fd;
78446828 721 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 722 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 723 fd = SCM_FPORT_FDES (sock);
7cee5b31 724 if (shutdown (fd, scm_to_signed_integer (how, 0, 2)) == -1)
1bbd0b84 725 SCM_SYSERROR;
370312ae
GH
726 return SCM_UNSPECIFIED;
727}
1bbd0b84 728#undef FUNC_NAME
0f2d19dd 729
370312ae
GH
730/* convert fam/address/args into a sockaddr of the appropriate type.
731 args is modified by removing the arguments actually used.
732 which_arg and proc are used when reporting errors:
733 which_arg is the position of address in the original argument list.
734 proc is the name of the original procedure.
735 size returns the size of the structure allocated. */
736
bc732342 737static struct sockaddr *
439006bf 738scm_fill_sockaddr (int fam, SCM address, SCM *args, int which_arg,
9c0129ac 739 const char *proc, size_t *size)
3453619b 740#define FUNC_NAME proc
370312ae
GH
741{
742 switch (fam)
0f2d19dd 743 {
370312ae
GH
744 case AF_INET:
745 {
370312ae 746 struct sockaddr_in *soka;
3453619b
GH
747 unsigned long addr;
748 int port;
370312ae 749
3453619b
GH
750 SCM_VALIDATE_ULONG_COPY (which_arg, address, addr);
751 SCM_VALIDATE_CONS (which_arg + 1, *args);
7cee5b31 752 port = scm_to_int (SCM_CAR (*args));
3453619b 753 *args = SCM_CDR (*args);
67329a9e 754 soka = (struct sockaddr_in *) scm_malloc (sizeof (struct sockaddr_in));
333a81cc 755 memset (soka, '\0', sizeof (struct sockaddr_in));
9c0129ac 756
482d311b 757#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
3453619b
GH
758 soka->sin_len = sizeof (struct sockaddr_in);
759#endif
370312ae 760 soka->sin_family = AF_INET;
3453619b
GH
761 soka->sin_addr.s_addr = htonl (addr);
762 soka->sin_port = htons (port);
370312ae
GH
763 *size = sizeof (struct sockaddr_in);
764 return (struct sockaddr *) soka;
765 }
a57a0b1e 766#ifdef HAVE_IPV6
3453619b
GH
767 case AF_INET6:
768 {
769 /* see RFC2553. */
770 int port;
771 struct sockaddr_in6 *soka;
772 unsigned long flowinfo = 0;
773 unsigned long scope_id = 0;
774
3453619b 775 SCM_VALIDATE_CONS (which_arg + 1, *args);
7cee5b31 776 port = scm_to_int (SCM_CAR (*args));
3453619b 777 *args = SCM_CDR (*args);
d2e53ed6 778 if (scm_is_pair (*args))
3453619b
GH
779 {
780 SCM_VALIDATE_ULONG_COPY (which_arg + 2, SCM_CAR (*args), flowinfo);
781 *args = SCM_CDR (*args);
d2e53ed6 782 if (scm_is_pair (*args))
3453619b
GH
783 {
784 SCM_VALIDATE_ULONG_COPY (which_arg + 3, SCM_CAR (*args),
785 scope_id);
786 *args = SCM_CDR (*args);
787 }
788 }
67329a9e 789 soka = (struct sockaddr_in6 *) scm_malloc (sizeof (struct sockaddr_in6));
9c0129ac 790
56a3dcd4 791#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
3453619b
GH
792 soka->sin6_len = sizeof (struct sockaddr_in6);
793#endif
794 soka->sin6_family = AF_INET6;
7cee5b31 795 scm_to_ipv6 (soka->sin6_addr.s6_addr, address);
5a525b84 796 soka->sin6_port = htons (port);
3453619b 797 soka->sin6_flowinfo = flowinfo;
5a525b84 798#ifdef HAVE_SIN6_SCOPE_ID
3453619b 799 soka->sin6_scope_id = scope_id;
5a525b84 800#endif
3453619b
GH
801 *size = sizeof (struct sockaddr_in6);
802 return (struct sockaddr *) soka;
803 }
804#endif
1ba8c23a 805#ifdef HAVE_UNIX_DOMAIN_SOCKETS
370312ae
GH
806 case AF_UNIX:
807 {
808 struct sockaddr_un *soka;
439006bf 809 int addr_size;
7f9994d9
MV
810 char *c_address;
811
661ae7ab 812 scm_dynwind_begin (0);
7f9994d9
MV
813
814 c_address = scm_to_locale_string (address);
661ae7ab 815 scm_dynwind_free (c_address);
370312ae 816
439006bf
GH
817 /* the static buffer size in sockaddr_un seems to be arbitrary
818 and not necessarily a hard limit. e.g., the glibc manual
819 suggests it may be possible to declare it size 0. let's
820 ignore it. if the O/S doesn't like the size it will cause
821 connect/bind etc., to fail. sun_path is always the last
822 member of the structure. */
823 addr_size = sizeof (struct sockaddr_un)
7f9994d9 824 + max (0, strlen (c_address) + 1 - (sizeof soka->sun_path));
67329a9e 825 soka = (struct sockaddr_un *) scm_malloc (addr_size);
439006bf
GH
826 memset (soka, 0, addr_size); /* for sun_len: see sin_len above. */
827 soka->sun_family = AF_UNIX;
7f9994d9 828 strcpy (soka->sun_path, c_address);
439006bf 829 *size = SUN_LEN (soka);
7f9994d9 830
661ae7ab 831 scm_dynwind_end ();
370312ae
GH
832 return (struct sockaddr *) soka;
833 }
0e958795 834#endif
370312ae 835 default:
e11e83f3 836 scm_out_of_range (proc, scm_from_int (fam));
0f2d19dd 837 }
0f2d19dd 838}
3453619b 839#undef FUNC_NAME
9c0129ac
KR
840
841SCM_DEFINE (scm_connect, "connect", 2, 1, 1,
842 (SCM sock, SCM fam_or_sockaddr, SCM address, SCM args),
eefae538 843 "Initiate a connection from a socket using a specified address\n"
3453619b
GH
844 "family to the address\n"
845 "specified by @var{address} and possibly @var{args}.\n"
846 "The format required for @var{address}\n"
847 "and @var{args} depends on the family of the socket.\n\n"
b380b885 848 "For a socket of family @code{AF_UNIX},\n"
3453619b 849 "only @var{address} is specified and must be a string with the\n"
b380b885
MD
850 "filename where the socket is to be created.\n\n"
851 "For a socket of family @code{AF_INET},\n"
3453619b
GH
852 "@var{address} must be an integer IPv4 host address and\n"
853 "@var{args} must be a single integer port number.\n\n"
854 "For a socket of family @code{AF_INET6},\n"
855 "@var{address} must be an integer IPv6 host address and\n"
856 "@var{args} may be up to three integers:\n"
857 "port [flowinfo] [scope_id],\n"
858 "where flowinfo and scope_id default to zero.\n\n"
9c0129ac
KR
859 "Alternatively, the second argument can be a socket address object "
860 "as returned by @code{make-socket-address}, in which case the "
861 "no additional arguments should be passed.\n\n"
b380b885 862 "The return value is unspecified.")
1bbd0b84 863#define FUNC_NAME s_scm_connect
0f2d19dd 864{
370312ae
GH
865 int fd;
866 struct sockaddr *soka;
9c0129ac 867 size_t size;
0f2d19dd 868
78446828 869 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 870 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 871 fd = SCM_FPORT_FDES (sock);
9c0129ac 872
d223c3fc 873 if (scm_is_eq (address, SCM_UNDEFINED))
9c0129ac
KR
874 /* No third argument was passed to FAM_OR_SOCKADDR must actually be a
875 `socket address' object. */
876 soka = scm_to_sockaddr (fam_or_sockaddr, &size);
877 else
878 soka = scm_fill_sockaddr (scm_to_int (fam_or_sockaddr), address,
879 &args, 3, FUNC_NAME, &size);
880
370312ae 881 if (connect (fd, soka, size) == -1)
439006bf
GH
882 {
883 int save_errno = errno;
9c0129ac 884
439006bf
GH
885 free (soka);
886 errno = save_errno;
887 SCM_SYSERROR;
888 }
889 free (soka);
370312ae 890 return SCM_UNSPECIFIED;
0f2d19dd 891}
1bbd0b84 892#undef FUNC_NAME
0f2d19dd 893
9c0129ac
KR
894SCM_DEFINE (scm_bind, "bind", 2, 1, 1,
895 (SCM sock, SCM fam_or_sockaddr, SCM address, SCM args),
eefae538 896 "Assign an address to the socket port @var{sock}.\n"
b380b885
MD
897 "Generally this only needs to be done for server sockets,\n"
898 "so they know where to look for incoming connections. A socket\n"
899 "without an address will be assigned one automatically when it\n"
900 "starts communicating.\n\n"
eefae538
GH
901 "The format of @var{address} and @var{args} depends\n"
902 "on the family of the socket.\n\n"
b380b885 903 "For a socket of family @code{AF_UNIX}, only @var{address}\n"
eefae538
GH
904 "is specified and must be a string with the filename where\n"
905 "the socket is to be created.\n\n"
906 "For a socket of family @code{AF_INET}, @var{address}\n"
907 "must be an integer IPv4 address and @var{args}\n"
908 "must be a single integer port number.\n\n"
909 "The values of the following variables can also be used for\n"
910 "@var{address}:\n\n"
b380b885
MD
911 "@defvar INADDR_ANY\n"
912 "Allow connections from any address.\n"
913 "@end defvar\n\n"
914 "@defvar INADDR_LOOPBACK\n"
915 "The address of the local host using the loopback device.\n"
916 "@end defvar\n\n"
917 "@defvar INADDR_BROADCAST\n"
918 "The broadcast address on the local network.\n"
919 "@end defvar\n\n"
920 "@defvar INADDR_NONE\n"
921 "No address.\n"
922 "@end defvar\n\n"
eefae538
GH
923 "For a socket of family @code{AF_INET6}, @var{address}\n"
924 "must be an integer IPv6 address and @var{args}\n"
925 "may be up to three integers:\n"
926 "port [flowinfo] [scope_id],\n"
927 "where flowinfo and scope_id default to zero.\n\n"
9c0129ac
KR
928 "Alternatively, the second argument can be a socket address object "
929 "as returned by @code{make-socket-address}, in which case the "
930 "no additional arguments should be passed.\n\n"
b380b885 931 "The return value is unspecified.")
1bbd0b84 932#define FUNC_NAME s_scm_bind
370312ae 933{
370312ae 934 struct sockaddr *soka;
9c0129ac 935 size_t size;
370312ae
GH
936 int fd;
937
78446828 938 sock = SCM_COERCE_OUTPORT (sock);
439006bf 939 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 940 fd = SCM_FPORT_FDES (sock);
9c0129ac 941
d223c3fc 942 if (scm_is_eq (address, SCM_UNDEFINED))
9c0129ac
KR
943 /* No third argument was passed to FAM_OR_SOCKADDR must actually be a
944 `socket address' object. */
945 soka = scm_to_sockaddr (fam_or_sockaddr, &size);
946 else
947 soka = scm_fill_sockaddr (scm_to_int (fam_or_sockaddr), address,
948 &args, 3, FUNC_NAME, &size);
949
950
439006bf
GH
951 if (bind (fd, soka, size) == -1)
952 {
953 int save_errno = errno;
9c0129ac 954
439006bf
GH
955 free (soka);
956 errno = save_errno;
1bbd0b84 957 SCM_SYSERROR;
439006bf
GH
958 }
959 free (soka);
370312ae
GH
960 return SCM_UNSPECIFIED;
961}
1bbd0b84 962#undef FUNC_NAME
370312ae 963
a1ec6916 964SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
1bbd0b84 965 (SCM sock, SCM backlog),
eefae538 966 "Enable @var{sock} to accept connection\n"
b380b885
MD
967 "requests. @var{backlog} is an integer specifying\n"
968 "the maximum length of the queue for pending connections.\n"
eefae538
GH
969 "If the queue fills, new clients will fail to connect until\n"
970 "the server calls @code{accept} to accept a connection from\n"
971 "the queue.\n\n"
b380b885 972 "The return value is unspecified.")
1bbd0b84 973#define FUNC_NAME s_scm_listen
370312ae
GH
974{
975 int fd;
78446828 976 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 977 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 978 fd = SCM_FPORT_FDES (sock);
7cee5b31 979 if (listen (fd, scm_to_int (backlog)) == -1)
1bbd0b84 980 SCM_SYSERROR;
370312ae
GH
981 return SCM_UNSPECIFIED;
982}
1bbd0b84 983#undef FUNC_NAME
370312ae
GH
984
985/* Put the components of a sockaddr into a new SCM vector. */
9c0129ac 986static SCM_C_INLINE_KEYWORD SCM
f43f3620
LC
987_scm_from_sockaddr (const scm_t_max_sockaddr *address, unsigned addr_size,
988 const char *proc)
0f2d19dd 989{
f43f3620
LC
990 SCM result = SCM_EOL;
991 short int fam = ((struct sockaddr *) address)->sa_family;
439006bf 992
5a525b84 993 switch (fam)
0f2d19dd 994 {
5a525b84
GH
995 case AF_INET:
996 {
e1368a8d 997 const struct sockaddr_in *nad = (struct sockaddr_in *) address;
439006bf 998
1d1559ce 999 result = scm_c_make_vector (3, SCM_UNSPECIFIED);
34d19ef6 1000
4057a3e0
MV
1001 SCM_SIMPLE_VECTOR_SET(result, 0,
1002 scm_from_short (fam));
1003 SCM_SIMPLE_VECTOR_SET(result, 1,
1004 scm_from_ulong (ntohl (nad->sin_addr.s_addr)));
1005 SCM_SIMPLE_VECTOR_SET(result, 2,
1006 scm_from_ushort (ntohs (nad->sin_port)));
5a525b84
GH
1007 }
1008 break;
a57a0b1e 1009#ifdef HAVE_IPV6
5a525b84
GH
1010 case AF_INET6:
1011 {
e1368a8d 1012 const struct sockaddr_in6 *nad = (struct sockaddr_in6 *) address;
5a525b84 1013
1d1559ce 1014 result = scm_c_make_vector (5, SCM_UNSPECIFIED);
4057a3e0
MV
1015 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_short (fam));
1016 SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_ipv6 (nad->sin6_addr.s6_addr));
1017 SCM_SIMPLE_VECTOR_SET(result, 2, scm_from_ushort (ntohs (nad->sin6_port)));
1018 SCM_SIMPLE_VECTOR_SET(result, 3, scm_from_uint32 (nad->sin6_flowinfo));
5a525b84 1019#ifdef HAVE_SIN6_SCOPE_ID
4057a3e0 1020 SCM_SIMPLE_VECTOR_SET(result, 4, scm_from_ulong (nad->sin6_scope_id));
5a525b84 1021#else
4057a3e0 1022 SCM_SIMPLE_VECTOR_SET(result, 4, SCM_INUM0);
0e958795 1023#endif
5a525b84
GH
1024 }
1025 break;
1026#endif
1027#ifdef HAVE_UNIX_DOMAIN_SOCKETS
1028 case AF_UNIX:
1029 {
e1368a8d 1030 const struct sockaddr_un *nad = (struct sockaddr_un *) address;
439006bf 1031
1d1559ce 1032 result = scm_c_make_vector (2, SCM_UNSPECIFIED);
34d19ef6 1033
4057a3e0 1034 SCM_SIMPLE_VECTOR_SET(result, 0, scm_from_short (fam));
aca23b65
MV
1035 /* When addr_size is not enough to cover sun_path, do not try
1036 to access it. */
1037 if (addr_size <= offsetof (struct sockaddr_un, sun_path))
4057a3e0 1038 SCM_SIMPLE_VECTOR_SET(result, 1, SCM_BOOL_F);
aca23b65 1039 else
4057a3e0 1040 SCM_SIMPLE_VECTOR_SET(result, 1, scm_from_locale_string (nad->sun_path));
5a525b84
GH
1041 }
1042 break;
1043#endif
1044 default:
9c0129ac
KR
1045 result = SCM_UNSPECIFIED;
1046 scm_misc_error (proc, "unrecognised address family: ~A",
e11e83f3 1047 scm_list_1 (scm_from_int (fam)));
9c0129ac 1048
0f2d19dd 1049 }
1d1559ce 1050 return result;
370312ae
GH
1051}
1052
9c0129ac
KR
1053/* The publicly-visible function. Return a Scheme object representing
1054 ADDRESS, an address of ADDR_SIZE bytes. */
1055SCM
1056scm_from_sockaddr (const struct sockaddr *address, unsigned addr_size)
1057{
f43f3620
LC
1058 return (_scm_from_sockaddr ((scm_t_max_sockaddr *) address,
1059 addr_size, "scm_from_sockaddr"));
9c0129ac
KR
1060}
1061
1062/* Convert ADDRESS, an address object returned by either
1063 `scm_from_sockaddr ()' or `scm_make_socket_address ()', into its C
1064 representation. On success, a non-NULL pointer is returned and
1065 ADDRESS_SIZE is updated to the actual size (in bytes) of the returned
1066 address. The result must eventually be freed using `free ()'. */
1067struct sockaddr *
1068scm_to_sockaddr (SCM address, size_t *address_size)
1069#define FUNC_NAME "scm_to_sockaddr"
1070{
1071 short int family;
1072 struct sockaddr *c_address = NULL;
1073
1074 SCM_VALIDATE_VECTOR (1, address);
1075
1076 *address_size = 0;
1077 family = scm_to_short (SCM_SIMPLE_VECTOR_REF (address, 0));
1078
1079 switch (family)
1080 {
1081 case AF_INET:
1082 {
1083 if (SCM_SIMPLE_VECTOR_LENGTH (address) != 3)
1084 scm_misc_error (FUNC_NAME,
1085 "invalid inet address representation: ~A",
1086 scm_list_1 (address));
1087 else
1088 {
1089 struct sockaddr_in c_inet;
1090
333a81cc
NL
1091 memset (&c_inet, '\0', sizeof (struct sockaddr_in));
1092
482d311b
NL
1093#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
1094 c_inet.sin_len = sizeof (struct sockaddr_in);
1095#endif
1096
9c0129ac
KR
1097 c_inet.sin_addr.s_addr =
1098 htonl (scm_to_ulong (SCM_SIMPLE_VECTOR_REF (address, 1)));
1099 c_inet.sin_port =
1100 htons (scm_to_ushort (SCM_SIMPLE_VECTOR_REF (address, 2)));
1101 c_inet.sin_family = AF_INET;
1102
1103 *address_size = sizeof (c_inet);
1104 c_address = scm_malloc (sizeof (c_inet));
1105 memcpy (c_address, &c_inet, sizeof (c_inet));
1106 }
1107
1108 break;
1109 }
1110
1111#ifdef HAVE_IPV6
1112 case AF_INET6:
1113 {
1114 if (SCM_SIMPLE_VECTOR_LENGTH (address) != 5)
1115 scm_misc_error (FUNC_NAME, "invalid inet6 address representation: ~A",
1116 scm_list_1 (address));
1117 else
1118 {
1119 struct sockaddr_in6 c_inet6;
1120
1ff4da65
NJ
1121 scm_to_ipv6 (c_inet6.sin6_addr.s6_addr,
1122 SCM_SIMPLE_VECTOR_REF (address, 1));
9c0129ac
KR
1123 c_inet6.sin6_port =
1124 htons (scm_to_ushort (SCM_SIMPLE_VECTOR_REF (address, 2)));
1125 c_inet6.sin6_flowinfo =
1126 scm_to_uint32 (SCM_SIMPLE_VECTOR_REF (address, 3));
1127#ifdef HAVE_SIN6_SCOPE_ID
1128 c_inet6.sin6_scope_id =
1129 scm_to_ulong (SCM_SIMPLE_VECTOR_REF (address, 4));
1130#endif
1131
1132 c_inet6.sin6_family = AF_INET6;
1133
1134 *address_size = sizeof (c_inet6);
1135 c_address = scm_malloc (sizeof (c_inet6));
1136 memcpy (c_address, &c_inet6, sizeof (c_inet6));
1137 }
1138
1139 break;
1140 }
1141#endif
1142
1143#ifdef HAVE_UNIX_DOMAIN_SOCKETS
1144 case AF_UNIX:
1145 {
1146 if (SCM_SIMPLE_VECTOR_LENGTH (address) != 2)
1147 scm_misc_error (FUNC_NAME, "invalid unix address representation: ~A",
1148 scm_list_1 (address));
1149 else
1150 {
1151 SCM path;
1152 size_t path_len = 0;
1153
1154 path = SCM_SIMPLE_VECTOR_REF (address, 1);
393baa8a 1155 if (!scm_is_string (path) && !scm_is_false (path))
9c0129ac
KR
1156 scm_misc_error (FUNC_NAME, "invalid unix address "
1157 "path: ~A", scm_list_1 (path));
1158 else
1159 {
1160 struct sockaddr_un c_unix;
1161
393baa8a 1162 if (scm_is_false (path))
9c0129ac
KR
1163 path_len = 0;
1164 else
1165 path_len = scm_c_string_length (path);
1166
1167#ifdef UNIX_PATH_MAX
1168 if (path_len >= UNIX_PATH_MAX)
1169#else
1170/* We can hope that this limit will eventually vanish, at least on GNU.
1171 However, currently, while glibc doesn't define `UNIX_PATH_MAX', it
1172 documents it has being limited to 108 bytes. */
1173 if (path_len >= sizeof (c_unix.sun_path))
1174#endif
1175 scm_misc_error (FUNC_NAME, "unix address path "
1176 "too long: ~A", scm_list_1 (path));
1177 else
1178 {
1179 if (path_len)
1180 {
1181 scm_to_locale_stringbuf (path, c_unix.sun_path,
1182#ifdef UNIX_PATH_MAX
1183 UNIX_PATH_MAX);
1184#else
1185 sizeof (c_unix.sun_path));
1186#endif
1187 c_unix.sun_path[path_len] = '\0';
1188
1189 /* Sanity check. */
1190 if (strlen (c_unix.sun_path) != path_len)
1191 scm_misc_error (FUNC_NAME, "unix address path "
1192 "contains nul characters: ~A",
1193 scm_list_1 (path));
1194 }
1195 else
1196 c_unix.sun_path[0] = '\0';
1197
1198 c_unix.sun_family = AF_UNIX;
1199
1200 *address_size = SUN_LEN (&c_unix);
1201 c_address = scm_malloc (sizeof (c_unix));
1202 memcpy (c_address, &c_unix, sizeof (c_unix));
1203 }
1204 }
1205 }
1206
1207 break;
1208 }
1209#endif
1210
1211 default:
1212 scm_misc_error (FUNC_NAME, "unrecognised address family: ~A",
1213 scm_list_1 (scm_from_ushort (family)));
1214 }
1215
1216 return c_address;
1217}
1218#undef FUNC_NAME
1219
1220
1221/* Return a newly-allocated `sockaddr' structure that reflects ADDRESS, being
1222 an address of family FAMILY, with the family-specific parameters ARGS (see
1223 the description of `connect' for details). The returned structure may be
1224 freed using `free ()'. */
1225struct sockaddr *
1226scm_c_make_socket_address (SCM family, SCM address, SCM args,
1227 size_t *address_size)
1228{
9c0129ac
KR
1229 struct sockaddr *soka;
1230
1231 soka = scm_fill_sockaddr (scm_to_ushort (family), address, &args, 1,
d7c6575f 1232 "scm_c_make_socket_address", address_size);
9c0129ac
KR
1233
1234 return soka;
1235}
1236
1237SCM_DEFINE (scm_make_socket_address, "make-socket-address", 2, 0, 1,
1238 (SCM family, SCM address, SCM args),
1239 "Return a Scheme address object that reflects @var{address}, "
1240 "being an address of family @var{family}, with the "
1241 "family-specific parameters @var{args} (see the description of "
1242 "@code{connect} for details).")
1243#define FUNC_NAME s_scm_make_socket_address
1244{
1ac5fb45 1245 SCM result = SCM_BOOL_F;
9c0129ac
KR
1246 struct sockaddr *c_address;
1247 size_t c_address_size;
1248
1249 c_address = scm_c_make_socket_address (family, address, args,
1250 &c_address_size);
1ac5fb45
LC
1251 if (c_address != NULL)
1252 {
1253 result = scm_from_sockaddr (c_address, c_address_size);
1254 free (c_address);
1255 }
9c0129ac 1256
1ac5fb45 1257 return result;
9c0129ac
KR
1258}
1259#undef FUNC_NAME
1260
1261\f
a1ec6916 1262SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
1bbd0b84 1263 (SCM sock),
eefae538
GH
1264 "Accept a connection on a bound, listening socket.\n"
1265 "If there\n"
1266 "are no pending connections in the queue, wait until\n"
1267 "one is available unless the non-blocking option has been\n"
1268 "set on the socket.\n\n"
b380b885 1269 "The return value is a\n"
eefae538
GH
1270 "pair in which the @emph{car} is a new socket port for the\n"
1271 "connection and\n"
1272 "the @emph{cdr} is an object with address information about the\n"
1273 "client which initiated the connection.\n\n"
1274 "@var{sock} does not become part of the\n"
b380b885 1275 "connection and will continue to accept new requests.")
1bbd0b84 1276#define FUNC_NAME s_scm_accept
0f2d19dd 1277{
e68e0369 1278 int fd;
370312ae
GH
1279 int newfd;
1280 SCM address;
1281 SCM newsock;
5ee417fc 1282 socklen_t addr_size = MAX_ADDR_SIZE;
f43f3620 1283 scm_t_max_sockaddr addr;
370312ae 1284
78446828 1285 sock = SCM_COERCE_OUTPORT (sock);
439006bf 1286 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1287 fd = SCM_FPORT_FDES (sock);
032a16fc 1288 SCM_SYSCALL (newfd = accept (fd, (struct sockaddr *) &addr, &addr_size));
439006bf
GH
1289 if (newfd == -1)
1290 SCM_SYSERROR;
1291 newsock = SCM_SOCK_FD_TO_PORT (newfd);
f43f3620
LC
1292 address = _scm_from_sockaddr (&addr, addr_size,
1293 FUNC_NAME);
1294
370312ae 1295 return scm_cons (newsock, address);
0f2d19dd 1296}
1bbd0b84 1297#undef FUNC_NAME
0f2d19dd 1298
a1ec6916 1299SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0,
1bbd0b84 1300 (SCM sock),
eefae538 1301 "Return the address of @var{sock}, in the same form as the\n"
1e6808ea
MG
1302 "object returned by @code{accept}. On many systems the address\n"
1303 "of a socket in the @code{AF_FILE} namespace cannot be read.")
1bbd0b84 1304#define FUNC_NAME s_scm_getsockname
0f2d19dd 1305{
370312ae 1306 int fd;
5ee417fc 1307 socklen_t addr_size = MAX_ADDR_SIZE;
f43f3620 1308 scm_t_max_sockaddr addr;
439006bf 1309
78446828 1310 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1311 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1312 fd = SCM_FPORT_FDES (sock);
f43f3620 1313 if (getsockname (fd, (struct sockaddr *) &addr, &addr_size) == -1)
1bbd0b84 1314 SCM_SYSERROR;
f43f3620
LC
1315
1316 return _scm_from_sockaddr (&addr, addr_size, FUNC_NAME);
0f2d19dd 1317}
1bbd0b84 1318#undef FUNC_NAME
0f2d19dd 1319
a1ec6916 1320SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0,
1bbd0b84 1321 (SCM sock),
eefae538 1322 "Return the address that @var{sock}\n"
1e6808ea
MG
1323 "is connected to, in the same form as the object returned by\n"
1324 "@code{accept}. On many systems the address of a socket in the\n"
1325 "@code{AF_FILE} namespace cannot be read.")
1bbd0b84 1326#define FUNC_NAME s_scm_getpeername
0f2d19dd 1327{
370312ae 1328 int fd;
5ee417fc 1329 socklen_t addr_size = MAX_ADDR_SIZE;
f43f3620 1330 scm_t_max_sockaddr addr;
439006bf 1331
78446828 1332 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1333 SCM_VALIDATE_OPFPORT (1, sock);
ee149d03 1334 fd = SCM_FPORT_FDES (sock);
f43f3620 1335 if (getpeername (fd, (struct sockaddr *) &addr, &addr_size) == -1)
1bbd0b84 1336 SCM_SYSERROR;
f43f3620
LC
1337
1338 return _scm_from_sockaddr (&addr, addr_size, FUNC_NAME);
0f2d19dd 1339}
1bbd0b84 1340#undef FUNC_NAME
0f2d19dd 1341
a1ec6916 1342SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
1bbd0b84 1343 (SCM sock, SCM buf, SCM flags),
eefae538
GH
1344 "Receive data from a socket port.\n"
1345 "@var{sock} must already\n"
b380b885 1346 "be bound to the address from which data is to be received.\n"
d21a1dc8 1347 "@var{buf} is a bytevector into which\n"
eefae538
GH
1348 "the data will be written. The size of @var{buf} limits\n"
1349 "the amount of\n"
b380b885 1350 "data which can be received: in the case of packet\n"
eefae538
GH
1351 "protocols, if a packet larger than this limit is encountered\n"
1352 "then some data\n"
b380b885
MD
1353 "will be irrevocably lost.\n\n"
1354 "The optional @var{flags} argument is a value or\n"
1355 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1356 "The value returned is the number of bytes read from the\n"
1357 "socket.\n\n"
1358 "Note that the data is read directly from the socket file\n"
1359 "descriptor:\n"
09831f94 1360 "any unread buffered port data is ignored.")
1bbd0b84 1361#define FUNC_NAME s_scm_recv
0f2d19dd 1362{
d21a1dc8 1363 int rv, fd, flg;
370312ae 1364
34d19ef6 1365 SCM_VALIDATE_OPFPORT (1, sock);
d21a1dc8 1366
7cee5b31
MV
1367 if (SCM_UNBNDP (flags))
1368 flg = 0;
1369 else
1370 flg = scm_to_int (flags);
ee149d03 1371 fd = SCM_FPORT_FDES (sock);
370312ae 1372
fc7bd367 1373 SCM_VALIDATE_BYTEVECTOR (1, buf);
d21a1dc8 1374
fc7bd367
AW
1375 SCM_SYSCALL (rv = recv (fd,
1376 SCM_BYTEVECTOR_CONTENTS (buf),
1377 SCM_BYTEVECTOR_LENGTH (buf),
1378 flg));
cc95e00a 1379
d21a1dc8 1380 if (SCM_UNLIKELY (rv == -1))
1bbd0b84 1381 SCM_SYSERROR;
370312ae 1382
d21a1dc8 1383 scm_remember_upto_here (buf);
7cee5b31 1384 return scm_from_int (rv);
370312ae 1385}
1bbd0b84 1386#undef FUNC_NAME
370312ae 1387
a1ec6916 1388SCM_DEFINE (scm_send, "send", 2, 1, 0,
1bbd0b84 1389 (SCM sock, SCM message, SCM flags),
d21a1dc8 1390 "Transmit bytevector @var{message} on socket port @var{sock}.\n"
eefae538
GH
1391 "@var{sock} must already be bound to a destination address. The\n"
1392 "value returned is the number of bytes transmitted --\n"
1393 "it's possible for\n"
1394 "this to be less than the length of @var{message}\n"
1395 "if the socket is\n"
1396 "set to be non-blocking. The optional @var{flags} argument\n"
1397 "is a value or\n"
b380b885 1398 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1399 "Note that the data is written directly to the socket\n"
1400 "file descriptor:\n"
587a3355
MG
1401 "any unflushed buffered port data is ignored.\n\n"
1402 "This operation is defined only for strings containing codepoints\n"
1403 "zero to 255.")
1bbd0b84 1404#define FUNC_NAME s_scm_send
370312ae 1405{
d21a1dc8 1406 int rv, fd, flg;
370312ae 1407
78446828 1408 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1409 SCM_VALIDATE_OPFPORT (1, sock);
587a3355 1410
7cee5b31
MV
1411 if (SCM_UNBNDP (flags))
1412 flg = 0;
1413 else
1414 flg = scm_to_int (flags);
d21a1dc8 1415
ee149d03 1416 fd = SCM_FPORT_FDES (sock);
370312ae 1417
fc7bd367 1418 SCM_VALIDATE_BYTEVECTOR (1, message);
d21a1dc8 1419
fc7bd367
AW
1420 SCM_SYSCALL (rv = send (fd,
1421 SCM_BYTEVECTOR_CONTENTS (message),
1422 SCM_BYTEVECTOR_LENGTH (message),
1423 flg));
cc95e00a 1424
370312ae 1425 if (rv == -1)
1bbd0b84 1426 SCM_SYSERROR;
396e5506
MV
1427
1428 scm_remember_upto_here_1 (message);
7cee5b31 1429 return scm_from_int (rv);
370312ae 1430}
1bbd0b84 1431#undef FUNC_NAME
370312ae 1432
a1ec6916 1433SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
d21a1dc8 1434 (SCM sock, SCM buf, SCM flags, SCM start, SCM end),
8ab3d8a0
KR
1435 "Receive data from socket port @var{sock} (which must be already\n"
1436 "bound), returning the originating address as well as the data.\n"
1437 "This is usually for use on datagram sockets, but can be used on\n"
1438 "stream-oriented sockets too.\n"
1439 "\n"
d21a1dc8
LC
1440 "The data received is stored in bytevector @var{buf}, using\n"
1441 "either the whole bytevector or just the region between the optional\n"
1442 "@var{start} and @var{end} positions. The size of @var{buf}\n"
1443 "limits the amount of data that can be received. For datagram\n"
8ab3d8a0
KR
1444 "protocols, if a packet larger than this is received then excess\n"
1445 "bytes are irrevocably lost.\n"
1446 "\n"
1447 "The return value is a pair. The @code{car} is the number of\n"
1448 "bytes read. The @code{cdr} is a socket address object which is\n"
d21a1dc8 1449 "where the data came from, or @code{#f} if the origin is\n"
8ab3d8a0
KR
1450 "unknown.\n"
1451 "\n"
1452 "The optional @var{flags} argument is a or bitwise OR\n"
1453 "(@code{logior}) of @code{MSG_OOB}, @code{MSG_PEEK},\n"
1454 "@code{MSG_DONTROUTE} etc.\n"
1455 "\n"
1456 "Data is read directly from the socket file descriptor, any\n"
1457 "buffered port data is ignored.\n"
1458 "\n"
1459 "On a GNU/Linux system @code{recvfrom!} is not multi-threading,\n"
1460 "all threads stop while a @code{recvfrom!} call is in progress.\n"
1461 "An application may need to use @code{select}, @code{O_NONBLOCK}\n"
1462 "or @code{MSG_DONTWAIT} to avoid this.")
1bbd0b84 1463#define FUNC_NAME s_scm_recvfrom
370312ae 1464{
d21a1dc8 1465 int rv, fd, flg;
370312ae 1466 SCM address;
d21a1dc8 1467 size_t offset, cend;
5ee417fc 1468 socklen_t addr_size = MAX_ADDR_SIZE;
f43f3620 1469 scm_t_max_sockaddr addr;
370312ae 1470
34d19ef6 1471 SCM_VALIDATE_OPFPORT (1, sock);
60d02d09 1472 fd = SCM_FPORT_FDES (sock);
396e5506 1473
1146b6cd
GH
1474 if (SCM_UNBNDP (flags))
1475 flg = 0;
370312ae 1476 else
60d02d09 1477 SCM_VALIDATE_ULONG_COPY (3, flags, flg);
370312ae 1478
f43f3620 1479 ((struct sockaddr *) &addr)->sa_family = AF_UNSPEC;
d21a1dc8 1480
fc7bd367 1481 SCM_VALIDATE_BYTEVECTOR (1, buf);
d21a1dc8 1482
fc7bd367
AW
1483 if (SCM_UNBNDP (start))
1484 offset = 0;
1485 else
1486 offset = scm_to_size_t (start);
d21a1dc8 1487
fc7bd367
AW
1488 if (SCM_UNBNDP (end))
1489 cend = SCM_BYTEVECTOR_LENGTH (buf);
d21a1dc8 1490 else
d21a1dc8 1491 {
fc7bd367
AW
1492 cend = scm_to_size_t (end);
1493 if (SCM_UNLIKELY (cend >= SCM_BYTEVECTOR_LENGTH (buf)
1494 || cend < offset))
1495 scm_out_of_range (FUNC_NAME, end);
d21a1dc8 1496 }
cc95e00a 1497
fc7bd367
AW
1498 SCM_SYSCALL (rv = recvfrom (fd,
1499 SCM_BYTEVECTOR_CONTENTS (buf) + offset,
1500 cend - offset, flg,
1501 (struct sockaddr *) &addr, &addr_size));
1502
370312ae 1503 if (rv == -1)
1bbd0b84 1504 SCM_SYSERROR;
d21a1dc8
LC
1505
1506 /* `recvfrom' does not necessarily return an address. Usually nothing
1507 is returned for stream sockets. */
f43f3620
LC
1508 if (((struct sockaddr *) &addr)->sa_family != AF_UNSPEC)
1509 address = _scm_from_sockaddr (&addr, addr_size, FUNC_NAME);
370312ae
GH
1510 else
1511 address = SCM_BOOL_F;
1512
d21a1dc8 1513 scm_remember_upto_here_1 (buf);
f43f3620 1514
e11e83f3 1515 return scm_cons (scm_from_int (rv), address);
0f2d19dd 1516}
1bbd0b84 1517#undef FUNC_NAME
0f2d19dd 1518
9c0129ac
KR
1519SCM_DEFINE (scm_sendto, "sendto", 3, 1, 1,
1520 (SCM sock, SCM message, SCM fam_or_sockaddr, SCM address, SCM args_and_flags),
d21a1dc8 1521 "Transmit bytevector @var{message} on socket port\n"
eefae538 1522 "@var{sock}. The\n"
b7e64f8b 1523 "destination address is specified using the @var{fam_or_sockaddr},\n"
eefae538 1524 "@var{address} and\n"
9c0129ac
KR
1525 "@var{args_and_flags} arguments, or just a socket address object "
1526 "returned by @code{make-socket-address}, in a similar way to the\n"
eefae538
GH
1527 "@code{connect} procedure. @var{args_and_flags} contains\n"
1528 "the usual connection arguments optionally followed by\n"
1529 "a flags argument, which is a value or\n"
b380b885 1530 "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
eefae538
GH
1531 "The value returned is the number of bytes transmitted --\n"
1532 "it's possible for\n"
1533 "this to be less than the length of @var{message} if the\n"
1534 "socket is\n"
1535 "set to be non-blocking.\n"
1536 "Note that the data is written directly to the socket\n"
1537 "file descriptor:\n"
587a3355
MG
1538 "any unflushed buffered port data is ignored.\n"
1539 "This operation is defined only for strings containing codepoints\n"
1540 "zero to 255.")
1bbd0b84 1541#define FUNC_NAME s_scm_sendto
370312ae 1542{
d21a1dc8 1543 int rv, fd, flg;
370312ae 1544 struct sockaddr *soka;
9c0129ac 1545 size_t size;
370312ae 1546
78446828 1547 sock = SCM_COERCE_OUTPORT (sock);
34d19ef6 1548 SCM_VALIDATE_FPORT (1, sock);
ee149d03 1549 fd = SCM_FPORT_FDES (sock);
9c0129ac
KR
1550
1551 if (!scm_is_number (fam_or_sockaddr))
1552 {
1553 /* FAM_OR_SOCKADDR must actually be a `socket address' object. This
1554 means that the following arguments, i.e. ADDRESS and those listed in
1555 ARGS_AND_FLAGS, are the `MSG_' flags. */
1556 soka = scm_to_sockaddr (fam_or_sockaddr, &size);
d223c3fc 1557 if (!scm_is_eq (address, SCM_UNDEFINED))
9c0129ac
KR
1558 args_and_flags = scm_cons (address, args_and_flags);
1559 }
1560 else
1561 soka = scm_fill_sockaddr (scm_to_int (fam_or_sockaddr), address,
1562 &args_and_flags, 3, FUNC_NAME, &size);
1563
d2e53ed6 1564 if (scm_is_null (args_and_flags))
370312ae
GH
1565 flg = 0;
1566 else
1567 {
34d19ef6 1568 SCM_VALIDATE_CONS (5, args_and_flags);
e4b265d8 1569 flg = SCM_NUM2ULONG (5, SCM_CAR (args_and_flags));
370312ae 1570 }
d21a1dc8 1571
fc7bd367 1572 SCM_VALIDATE_BYTEVECTOR (1, message);
d21a1dc8 1573
fc7bd367
AW
1574 SCM_SYSCALL (rv = sendto (fd,
1575 SCM_BYTEVECTOR_CONTENTS (message),
1576 SCM_BYTEVECTOR_LENGTH (message),
1577 flg, soka, size));
d21a1dc8 1578
370312ae 1579 if (rv == -1)
439006bf
GH
1580 {
1581 int save_errno = errno;
1582 free (soka);
1583 errno = save_errno;
1584 SCM_SYSERROR;
1585 }
1586 free (soka);
396e5506
MV
1587
1588 scm_remember_upto_here_1 (message);
e11e83f3 1589 return scm_from_int (rv);
370312ae 1590}
1bbd0b84 1591#undef FUNC_NAME
370312ae
GH
1592\f
1593
1594
1595void
0f2d19dd 1596scm_init_socket ()
0f2d19dd 1597{
370312ae
GH
1598 /* protocol families. */
1599#ifdef AF_UNSPEC
e11e83f3 1600 scm_c_define ("AF_UNSPEC", scm_from_int (AF_UNSPEC));
370312ae 1601#endif
dba6f4e2 1602#if defined HAVE_UNIX_DOMAIN_SOCKETS && defined AF_UNIX
e11e83f3 1603 scm_c_define ("AF_UNIX", scm_from_int (AF_UNIX));
370312ae
GH
1604#endif
1605#ifdef AF_INET
e11e83f3 1606 scm_c_define ("AF_INET", scm_from_int (AF_INET));
370312ae 1607#endif
3453619b 1608#ifdef AF_INET6
e11e83f3 1609 scm_c_define ("AF_INET6", scm_from_int (AF_INET6));
3453619b 1610#endif
370312ae
GH
1611
1612#ifdef PF_UNSPEC
e11e83f3 1613 scm_c_define ("PF_UNSPEC", scm_from_int (PF_UNSPEC));
370312ae
GH
1614#endif
1615#ifdef PF_UNIX
e11e83f3 1616 scm_c_define ("PF_UNIX", scm_from_int (PF_UNIX));
370312ae
GH
1617#endif
1618#ifdef PF_INET
e11e83f3 1619 scm_c_define ("PF_INET", scm_from_int (PF_INET));
370312ae 1620#endif
3453619b 1621#ifdef PF_INET6
e11e83f3 1622 scm_c_define ("PF_INET6", scm_from_int (PF_INET6));
3453619b 1623#endif
370312ae 1624
66c73b76
GH
1625 /* standard addresses. */
1626#ifdef INADDR_ANY
b9bd8526 1627 scm_c_define ("INADDR_ANY", scm_from_ulong (INADDR_ANY));
66c73b76
GH
1628#endif
1629#ifdef INADDR_BROADCAST
b9bd8526 1630 scm_c_define ("INADDR_BROADCAST", scm_from_ulong (INADDR_BROADCAST));
66c73b76
GH
1631#endif
1632#ifdef INADDR_NONE
b9bd8526 1633 scm_c_define ("INADDR_NONE", scm_from_ulong (INADDR_NONE));
66c73b76
GH
1634#endif
1635#ifdef INADDR_LOOPBACK
b9bd8526 1636 scm_c_define ("INADDR_LOOPBACK", scm_from_ulong (INADDR_LOOPBACK));
66c73b76
GH
1637#endif
1638
6f637a1b
KR
1639 /* socket types.
1640
1641 SOCK_PACKET is deliberately omitted, the GNU/Linux socket(2) and
1642 packet(7) advise that it's obsolete and strongly deprecated. */
1643
370312ae 1644#ifdef SOCK_STREAM
e11e83f3 1645 scm_c_define ("SOCK_STREAM", scm_from_int (SOCK_STREAM));
370312ae
GH
1646#endif
1647#ifdef SOCK_DGRAM
e11e83f3 1648 scm_c_define ("SOCK_DGRAM", scm_from_int (SOCK_DGRAM));
370312ae 1649#endif
6f637a1b
KR
1650#ifdef SOCK_SEQPACKET
1651 scm_c_define ("SOCK_SEQPACKET", scm_from_int (SOCK_SEQPACKET));
1652#endif
370312ae 1653#ifdef SOCK_RAW
e11e83f3 1654 scm_c_define ("SOCK_RAW", scm_from_int (SOCK_RAW));
370312ae 1655#endif
6f637a1b
KR
1656#ifdef SOCK_RDM
1657 scm_c_define ("SOCK_RDM", scm_from_int (SOCK_RDM));
1658#endif
370312ae 1659
8fae2bf4
KR
1660 /* setsockopt level.
1661
1662 SOL_IP, SOL_TCP and SOL_UDP are defined on gnu/linux, but not on for
1663 instance NetBSD. We define IPPROTOs because that's what the posix spec
1664 shows in its example at
1665
1666 http://www.opengroup.org/onlinepubs/007904975/functions/getsockopt.html
1667 */
370312ae 1668#ifdef SOL_SOCKET
e11e83f3 1669 scm_c_define ("SOL_SOCKET", scm_from_int (SOL_SOCKET));
370312ae 1670#endif
8fae2bf4
KR
1671#ifdef IPPROTO_IP
1672 scm_c_define ("IPPROTO_IP", scm_from_int (IPPROTO_IP));
370312ae 1673#endif
8fae2bf4
KR
1674#ifdef IPPROTO_TCP
1675 scm_c_define ("IPPROTO_TCP", scm_from_int (IPPROTO_TCP));
370312ae 1676#endif
8fae2bf4
KR
1677#ifdef IPPROTO_UDP
1678 scm_c_define ("IPPROTO_UDP", scm_from_int (IPPROTO_UDP));
370312ae
GH
1679#endif
1680
1681 /* setsockopt names. */
1682#ifdef SO_DEBUG
e11e83f3 1683 scm_c_define ("SO_DEBUG", scm_from_int (SO_DEBUG));
370312ae
GH
1684#endif
1685#ifdef SO_REUSEADDR
e11e83f3 1686 scm_c_define ("SO_REUSEADDR", scm_from_int (SO_REUSEADDR));
370312ae
GH
1687#endif
1688#ifdef SO_STYLE
e11e83f3 1689 scm_c_define ("SO_STYLE", scm_from_int (SO_STYLE));
370312ae
GH
1690#endif
1691#ifdef SO_TYPE
e11e83f3 1692 scm_c_define ("SO_TYPE", scm_from_int (SO_TYPE));
370312ae
GH
1693#endif
1694#ifdef SO_ERROR
e11e83f3 1695 scm_c_define ("SO_ERROR", scm_from_int (SO_ERROR));
370312ae
GH
1696#endif
1697#ifdef SO_DONTROUTE
e11e83f3 1698 scm_c_define ("SO_DONTROUTE", scm_from_int (SO_DONTROUTE));
370312ae
GH
1699#endif
1700#ifdef SO_BROADCAST
e11e83f3 1701 scm_c_define ("SO_BROADCAST", scm_from_int (SO_BROADCAST));
370312ae
GH
1702#endif
1703#ifdef SO_SNDBUF
e11e83f3 1704 scm_c_define ("SO_SNDBUF", scm_from_int (SO_SNDBUF));
370312ae
GH
1705#endif
1706#ifdef SO_RCVBUF
e11e83f3 1707 scm_c_define ("SO_RCVBUF", scm_from_int (SO_RCVBUF));
370312ae
GH
1708#endif
1709#ifdef SO_KEEPALIVE
e11e83f3 1710 scm_c_define ("SO_KEEPALIVE", scm_from_int (SO_KEEPALIVE));
370312ae
GH
1711#endif
1712#ifdef SO_OOBINLINE
e11e83f3 1713 scm_c_define ("SO_OOBINLINE", scm_from_int (SO_OOBINLINE));
370312ae
GH
1714#endif
1715#ifdef SO_NO_CHECK
e11e83f3 1716 scm_c_define ("SO_NO_CHECK", scm_from_int (SO_NO_CHECK));
370312ae
GH
1717#endif
1718#ifdef SO_PRIORITY
e11e83f3 1719 scm_c_define ("SO_PRIORITY", scm_from_int (SO_PRIORITY));
370312ae
GH
1720#endif
1721#ifdef SO_LINGER
e11e83f3 1722 scm_c_define ("SO_LINGER", scm_from_int (SO_LINGER));
370312ae 1723#endif
5f24f1b5
LC
1724#ifdef SO_REUSEPORT /* new in Linux 3.9 */
1725 scm_c_define ("SO_REUSEPORT", scm_from_int (SO_REUSEPORT));
1726#endif
370312ae
GH
1727
1728 /* recv/send options. */
8ab3d8a0
KR
1729#ifdef MSG_DONTWAIT
1730 scm_c_define ("MSG_DONTWAIT", scm_from_int (MSG_DONTWAIT));
1731#endif
370312ae 1732#ifdef MSG_OOB
e11e83f3 1733 scm_c_define ("MSG_OOB", scm_from_int (MSG_OOB));
370312ae
GH
1734#endif
1735#ifdef MSG_PEEK
e11e83f3 1736 scm_c_define ("MSG_PEEK", scm_from_int (MSG_PEEK));
370312ae
GH
1737#endif
1738#ifdef MSG_DONTROUTE
e11e83f3 1739 scm_c_define ("MSG_DONTROUTE", scm_from_int (MSG_DONTROUTE));
370312ae
GH
1740#endif
1741
1c80707c
MV
1742#ifdef IP_ADD_MEMBERSHIP
1743 scm_c_define ("IP_ADD_MEMBERSHIP", scm_from_int (IP_ADD_MEMBERSHIP));
1744 scm_c_define ("IP_DROP_MEMBERSHIP", scm_from_int (IP_DROP_MEMBERSHIP));
1745#endif
1746
511246a1
TCM
1747#ifdef IP_MULTICAST_TTL
1748 scm_c_define ("IP_MULTICAST_TTL", scm_from_int ( IP_MULTICAST_TTL));
1749#endif
1750
1751#ifdef IP_MULTICAST_IF
1752 scm_c_define ("IP_MULTICAST_IF", scm_from_int ( IP_MULTICAST_IF));
1753#endif
1754
0f2d19dd 1755 scm_add_feature ("socket");
370312ae 1756
a0599745 1757#include "libguile/socket.x"
0f2d19dd
JB
1758}
1759
89e00824
ML
1760
1761/*
1762 Local Variables:
1763 c-file-style: "gnu"
1764 End:
1765*/