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