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