2001-05-30 Martin Grabmueller <mgrabmue@cs.tu-berlin.de>
[bpt/guile.git] / libguile / socket.c
index ae799d9..685d932 100644 (file)
@@ -1,4 +1,4 @@
-/*     Copyright (C) 1996,1997,1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1996,1997,1998,2000,2001 Free Software Foundation, Inc.
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 
 \f
 
 
 \f
 
-#include <stdio.h>
+#include <errno.h>
 
 #include "libguile/_scm.h"
 #include "libguile/unif.h"
 
 #include "libguile/_scm.h"
 #include "libguile/unif.h"
 #include <netdb.h>
 #include <arpa/inet.h>
 
 #include <netdb.h>
 #include <arpa/inet.h>
 
+#if defined (HAVE_UNIX_DOMAIN_SOCKETS) && !defined (SUN_LEN)
+#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+                     + strlen ((ptr)->sun_path))
+#endif
+
+#if !defined (HAVE_UINT32_T)
+#if SIZEOF_INT == 4
+typedef unsigned int uint32_t;
+#elif SIZEOF_LONG == 4
+typedef unsigned long uint32_t;
+#else
+#error can not define uint32_t
+#endif
+#endif
+
+/* we are not currently using socklen_t.  it's not defined on all systems,
+   so would need to be checked by configure.  in the meantime, plain
+   int is the best alternative.  */
+
 \f
 
 SCM_DEFINE (scm_htons, "htons", 1, 0, 0, 
 \f
 
 SCM_DEFINE (scm_htons, "htons", 1, 0, 0, 
-            (SCM in),
-           "Returns a new integer from @var{value} by converting from host to\n"
-           "network order. @var{value} must be within the range of a C unsigned\n"
-           "short integer.")
+            (SCM value),
+           "Convert a 16 bit quantity from host to network byte ordering.\n"
+           "@var{value} is packed into 2 bytes, which are then converted\n"
+           "and returned as a new integer.")
 #define FUNC_NAME s_scm_htons
 {
   unsigned short c_in;
 
 #define FUNC_NAME s_scm_htons
 {
   unsigned short c_in;
 
-  SCM_VALIDATE_INUM_COPY (1,in,c_in);
-  if (c_in != SCM_INUM (in))
-    SCM_OUT_OF_RANGE (1,in);
+  SCM_VALIDATE_INUM_COPY (1, value, c_in);
+  if (c_in != SCM_INUM (value))
+    SCM_OUT_OF_RANGE (1, value);
 
   return SCM_MAKINUM (htons (c_in));
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_ntohs, "ntohs", 1, 0, 0, 
 
   return SCM_MAKINUM (htons (c_in));
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_ntohs, "ntohs", 1, 0, 0, 
-            (SCM in),
-           "Returns a new integer from @var{value} by converting from network to\n"
-           "host order.  @var{value} must be within the range of a C unsigned short\n"
-           "integer.")
+            (SCM value),
+           "Convert a 16 bit quantity from network to host byte ordering.\n"
+           "@var{value} is packed into 2 bytes, which are then converted\n"
+           "and returned as a new integer.")
 #define FUNC_NAME s_scm_ntohs
 {
   unsigned short c_in;
 
 #define FUNC_NAME s_scm_ntohs
 {
   unsigned short c_in;
 
-  SCM_VALIDATE_INUM_COPY (1,in,c_in);
-  if (c_in != SCM_INUM (in))
-    SCM_OUT_OF_RANGE (1,in);
+  SCM_VALIDATE_INUM_COPY (1, value, c_in);
+  if (c_in != SCM_INUM (value))
+    SCM_OUT_OF_RANGE (1, value);
 
   return SCM_MAKINUM (ntohs (c_in));
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_htonl, "htonl", 1, 0, 0, 
 
   return SCM_MAKINUM (ntohs (c_in));
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_htonl, "htonl", 1, 0, 0, 
-            (SCM in),
-           "Returns a new integer from @var{value} by converting from host to\n"
-           "network order. @var{value} must be within the range of a C unsigned\n"
-           "long integer.")
+            (SCM value),
+           "Convert a 32 bit quantity from host to network byte ordering.\n"
+           "@var{value} is packed into 4 bytes, which are then converted\n"
+           "and returned as a new integer.")
 #define FUNC_NAME s_scm_htonl
 {
 #define FUNC_NAME s_scm_htonl
 {
-  unsigned long c_in = SCM_NUM2ULONG (1,in);
+  uint32_t c_in = SCM_NUM2ULONG (1, value);
+
   return scm_ulong2num (htonl (c_in));
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_ntohl, "ntohl", 1, 0, 0, 
   return scm_ulong2num (htonl (c_in));
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_ntohl, "ntohl", 1, 0, 0, 
-            (SCM in),
-           "Returns a new integer from @var{value} by converting from network to\n"
-           "host order. @var{value} must be within the range of a C unsigned\n"
-           "long integer.")
+            (SCM value),
+           "Convert a 32 bit quantity from network to host byte ordering.\n"
+           "@var{value} is packed into 4 bytes, which are then converted\n"
+           "and returned as a new integer.")
 #define FUNC_NAME s_scm_ntohl
 {
 #define FUNC_NAME s_scm_ntohl
 {
-  unsigned long c_in = SCM_NUM2ULONG (1,in);
+  uint32_t c_in = SCM_NUM2ULONG (1, value);
+
   return scm_ulong2num (ntohl (c_in));
 }
 #undef FUNC_NAME
 
   return scm_ulong2num (ntohl (c_in));
 }
 #undef FUNC_NAME
 
-SCM_SYMBOL (sym_socket, "socket");
+#ifndef HAVE_INET_ATON
+/* for our definition in inet_aton.c, not usually needed.  */
+extern int inet_aton ();
+#endif
 
 
-static SCM
-scm_sock_fd_to_port (int fd, const char *proc)
+SCM_DEFINE (scm_inet_aton, "inet-aton", 1, 0, 0, 
+            (SCM address),
+           "Convert an IPv4 Internet address from printable string\n"
+           "(dotted decimal notation) to an integer.  E.g.,\n\n"
+           "@lisp\n"
+           "(inet-aton \"127.0.0.1\") @result{} 2130706433\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_inet_aton
+{
+  struct in_addr soka;
+
+  SCM_VALIDATE_STRING (1, address);
+  SCM_STRING_COERCE_0TERMINATION_X (address);
+  if (inet_aton (SCM_STRING_CHARS (address), &soka) == 0)
+    SCM_MISC_ERROR ("bad address", SCM_EOL);
+  return scm_ulong2num (ntohl (soka.s_addr));
+}
+#undef FUNC_NAME
+
+
+SCM_DEFINE (scm_inet_ntoa, "inet-ntoa", 1, 0, 0, 
+            (SCM inetid),
+           "Convert an IPv4 Internet address to a printable\n"
+           "(dotted decimal notation) string.  E.g.,\n\n"
+           "@lisp\n"
+           "(inet-ntoa 2130706433) @result{} \"127.0.0.1\"\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_inet_ntoa
+{
+  struct in_addr addr;
+  char *s;
+  SCM answer;
+  addr.s_addr = htonl (SCM_NUM2ULONG (1, inetid));
+  s = inet_ntoa (addr);
+  answer = scm_makfromstr (s, strlen (s), 0);
+  return answer;
+}
+#undef FUNC_NAME
+
+#ifdef HAVE_INET_NETOF
+SCM_DEFINE (scm_inet_netof, "inet-netof", 1, 0, 0, 
+            (SCM address),
+           "Return the network number part of the given IPv4\n"
+           "Internet address.  E.g.,\n\n"
+           "@lisp\n"
+           "(inet-netof 2130706433) @result{} 127\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_inet_netof
 {
 {
+  struct in_addr addr;
+  addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
+  return scm_ulong2num ((unsigned long) inet_netof (addr));
+}
+#undef FUNC_NAME
+#endif
+
+#ifdef HAVE_INET_LNAOF
+SCM_DEFINE (scm_lnaof, "inet-lnaof", 1, 0, 0, 
+            (SCM address),
+           "Return the local-address-with-network part of the given\n"
+           "IPv4 Internet address, using the obsolete class A/B/C system.\n"
+           "E.g.,\n\n"
+           "@lisp\n"
+           "(inet-lnaof 2130706433) @result{} 1\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_lnaof
+{
+  struct in_addr addr;
+  addr.s_addr = htonl (SCM_NUM2ULONG (1, address));
+  return scm_ulong2num ((unsigned long) inet_lnaof (addr));
+}
+#undef FUNC_NAME
+#endif
+
+#ifdef HAVE_INET_MAKEADDR
+SCM_DEFINE (scm_inet_makeaddr, "inet-makeaddr", 2, 0, 0,
+            (SCM net, SCM lna),
+           "Make an IPv4 Internet address by combining the network number\n"
+           "@var{net} with the local-address-within-network number\n"
+           "@var{lna}.  E.g.,\n\n"
+           "@lisp\n"
+           "(inet-makeaddr 127 1) @result{} 2130706433\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_inet_makeaddr
+{
+  struct in_addr addr;
+  unsigned long netnum;
+  unsigned long lnanum;
+
+  netnum = SCM_NUM2ULONG (1, net);
+  lnanum = SCM_NUM2ULONG (2, lna);
+  addr = inet_makeaddr (netnum, lnanum);
+  return scm_ulong2num (ntohl (addr.s_addr));
+}
+#undef FUNC_NAME
+#endif
+
+#ifdef HAVE_IPV6
+
+/* flip a 128 bit IPv6 address between host and network order.  */
+#ifdef WORDS_BIGENDIAN
+#define FLIP_NET_HOST_128(addr)
+#else
+#define FLIP_NET_HOST_128(addr)\
+{\
+  int i;\
+  \
+  for (i = 0; i < 8; i++)\
+    {\
+      char c = (addr)[i];\
+      \
+      (addr)[i] = (addr)[15 - i];\
+      (addr)[15 - i] = c;\
+    }\
+}
+#endif
+
+/* convert a 128 bit IPv6 address in network order to a host ordered
+   SCM integer.  */
+static SCM ipv6_net_to_num (const char *src)
+{
+  int big_digits = 128 / SCM_BITSPERDIG;
+  const int bytes_per_dig = SCM_BITSPERDIG / 8;
+  char addr[16];
+  char *ptr = addr;
   SCM result;
   SCM result;
-  if (fd == -1)
-    scm_syserror (proc);
-  result = scm_fdes_to_port (fd, "r+0", sym_socket);
+
+  memcpy (addr, src, 16);
+  /* get rid of leading zeros.  */ 
+  while (big_digits > 0)
+    {
+      long test = 0;
+
+      memcpy (&test, ptr, bytes_per_dig);
+      if (test != 0)
+       break;
+      ptr += bytes_per_dig;
+      big_digits--;
+    }
+  FLIP_NET_HOST_128 (addr);
+  if (big_digits * bytes_per_dig <= sizeof (unsigned long))
+    {
+      /* this is just so that we use INUM where possible.  */
+      unsigned long l_addr;
+
+      memcpy (&l_addr, addr, sizeof (unsigned long));
+      result = scm_ulong2num (l_addr);
+    }
+  else
+    {
+      result = scm_i_mkbig (big_digits, 0);
+      memcpy (SCM_BDIGITS (result), addr, big_digits * bytes_per_dig);
+    }
   return result;
   return result;
+}  
+
+/* convert a host ordered SCM integer to a 128 bit IPv6 address in
+   network order.  */
+static void ipv6_num_to_net (SCM src, char *dst)
+{
+  if (SCM_INUMP (src))
+    {
+      uint32_t addr = htonl (SCM_INUM (src));
+
+      memset (dst, 0, 12);
+      memcpy (dst + 12, &addr, 4);
+    }
+  else
+    {
+      memset (dst, 0, 16);
+      memcpy (dst, SCM_BDIGITS (src),
+             SCM_NUMDIGS (src) * (SCM_BITSPERDIG / 8));
+      FLIP_NET_HOST_128 (dst);
+    }
 }
 
 }
 
+/* check that an SCM variable contains an IPv6 integer address.  */
+#define VALIDATE_INET6(which_arg, address)\
+   if (SCM_INUMP (address))\
+      SCM_ASSERT_RANGE (which_arg, address, SCM_INUM (address) >= 0);\
+   else\
+   {\
+      SCM_VALIDATE_BIGINT (which_arg, address);\
+      SCM_ASSERT_RANGE (which_arg, address,\
+                       !SCM_BIGSIGN (address)\
+                       && (SCM_BITSPERDIG\
+                           * SCM_NUMDIGS (address) <= 128));\
+   }
+
+#ifdef HAVE_INET_PTON
+SCM_DEFINE (scm_inet_pton, "inet-pton", 2, 0, 0,
+            (SCM family, SCM address),
+           "Convert a string containing a printable network address to\n"
+           "an integer address.  Note that unlike the C version of this\n"
+           "function,\n"
+           "the result is an integer with normal host byte ordering.\n"
+           "@var{family} can be @code{AF_INET} or @code{AF_INET6}.  E.g.,\n\n"
+           "@lisp\n"
+           "(inet-pton AF_INET \"127.0.0.1\") @result{} 2130706433\n"
+           "(inet-pton AF_INET6 \"::1\") @result{} 1\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_inet_pton
+{
+  int af;
+  char *src;
+  char dst[16];
+  int rv;
 
 
-#define SCM_SOCK_FD_TO_PORT(fd) (scm_sock_fd_to_port((fd),FUNC_NAME))
+  SCM_VALIDATE_INUM_COPY (1, family, af);
+  SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
+  SCM_VALIDATE_STRING_COPY (2, address, src);
+  rv = inet_pton (af, src, dst);
+  if (rv == -1)
+    SCM_SYSERROR;
+  else if (rv == 0)
+    SCM_MISC_ERROR ("Bad address", SCM_EOL);
+  if (af == AF_INET)
+    return scm_ulong2num (ntohl (*(uint32_t *) dst));
+  else
+    return ipv6_net_to_num ((char *) dst);
+}
+#undef FUNC_NAME
+#endif
+
+#ifdef HAVE_INET_NTOP
+SCM_DEFINE (scm_inet_ntop, "inet-ntop", 2, 0, 0,
+            (SCM family, SCM address),
+           "Convert a network address into a printable string.\n"
+           "Note that unlike the C version of this function,\n"
+           "the input is an integer with normal host byte ordering.\n"
+           "@var{family} can be @code{AF_INET} or @code{AF_INET6}.  E.g.,\n\n"
+           "@lisp\n"
+           "(inet-ntop AF_INET 2130706433) @result{} \"127.0.0.1\"\n"
+           "(inet-ntop AF_INET6 (- (expt 2 128) 1)) @result{}\n"
+           "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff\n"
+           "@end lisp")
+#define FUNC_NAME s_scm_inet_ntop
+{
+  int af;
+#ifdef INET6_ADDRSTRLEN
+  char dst[INET6_ADDRSTRLEN];
+#else
+  char dst[46];
+#endif
+  char addr6[16];
+
+  SCM_VALIDATE_INUM_COPY (1, family, af);
+  SCM_ASSERT_RANGE (1, family, af == AF_INET || af == AF_INET6);
+  if (af == AF_INET)
+    *(uint32_t *) addr6 = htonl (SCM_NUM2ULONG (2, address));
+  else
+    {
+      VALIDATE_INET6 (2, address);
+      ipv6_num_to_net (address, addr6);
+    }
+  if (inet_ntop (af, &addr6, dst, sizeof dst) == NULL)
+    SCM_SYSERROR;
+  return scm_makfrom0str (dst);
+}
+#undef FUNC_NAME
+#endif
+
+#endif  /* HAVE_IPV6 */
+
+SCM_SYMBOL (sym_socket, "socket");
+
+#define SCM_SOCK_FD_TO_PORT(fd) scm_fdes_to_port (fd, "r+0", sym_socket)
 
 SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
             (SCM family, SCM style, SCM proto),
 
 SCM_DEFINE (scm_socket, "socket", 3, 0, 0,
             (SCM family, SCM style, SCM proto),
-           "Returns a new socket port of the type specified by @var{family}, @var{style}\n"
-           "and @var{protocol}.  All three parameters are integers.  Typical values\n"
-           "for @var{family} are the values of @code{AF_UNIX}\n"
-           "and @code{AF_INET}.  Typical values for @var{style} are\n"
-           "the values of @code{SOCK_STREAM}, @code{SOCK_DGRAM} and @code{SOCK_RAW}.\n\n"
-           "@var{protocol} can be obtained from a protocol name using\n"
-           "@code{getprotobyname}.  A value of\n"
-           "zero specifies the default protocol, which is usually right.\n\n"
-           "A single socket port cannot by used for communication until\n"
-           "it has been connected to another socket.")
+           "Return a new socket port of the type specified by @var{family},\n"
+           "@var{style} and @var{proto}.  All three parameters are\n"
+           "integers.  Supported values for @var{family} are\n"
+           "@code{AF_UNIX}, @code{AF_INET} and @code{AF_INET6}.\n"
+           "Typical values for @var{style} are @code{SOCK_STREAM},\n"
+           "@code{SOCK_DGRAM} and @code{SOCK_RAW}.\n\n"
+           "@var{proto} can be obtained from a protocol name using\n"
+           "@code{getprotobyname}.  A value of zero specifies the default\n"
+           "protocol, which is usually right.\n\n"
+           "A single socket port cannot by used for communication until it\n"
+           "has been connected to another socket.")
 #define FUNC_NAME s_scm_socket
 {
   int fd;
 #define FUNC_NAME s_scm_socket
 {
   int fd;
-  SCM result;
 
 
-  SCM_VALIDATE_INUM (1,family);
-  SCM_VALIDATE_INUM (2,style);
-  SCM_VALIDATE_INUM (3,proto);
+  SCM_VALIDATE_INUM (1, family);
+  SCM_VALIDATE_INUM (2, style);
+  SCM_VALIDATE_INUM (3, proto);
   fd = socket (SCM_INUM (family), SCM_INUM (style), SCM_INUM (proto));
   fd = socket (SCM_INUM (family), SCM_INUM (style), SCM_INUM (proto));
-  result = SCM_SOCK_FD_TO_PORT (fd);
-  return result;
+  if (fd == -1)
+    SCM_SYSERROR;
+  return SCM_SOCK_FD_TO_PORT (fd);
 }
 #undef FUNC_NAME
 
 }
 #undef FUNC_NAME
 
-
-
 #ifdef HAVE_SOCKETPAIR
 SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
             (SCM family, SCM style, SCM proto),
 #ifdef HAVE_SOCKETPAIR
 SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
             (SCM family, SCM style, SCM proto),
-           "Returns a pair of connected (but unnamed) socket ports of the type specified\n"
-           "by @var{family}, @var{style} and @var{protocol}.\n"
-           "Many systems support only\n"
-           "socket pairs of the @code{AF_UNIX} family.  Zero is likely to be\n"
-           "the only meaningful value for @var{protocol}.")
+           "Return a pair of connected (but unnamed) socket ports of the\n"
+           "type specified by @var{family}, @var{style} and @var{proto}.\n"
+           "Many systems support only socket pairs of the @code{AF_UNIX}\n"
+           "family.  Zero is likely to be the only meaningful value for\n"
+           "@var{proto}.")
 #define FUNC_NAME s_scm_socketpair
 {
   int fam;
   int fd[2];
 #define FUNC_NAME s_scm_socketpair
 {
   int fam;
   int fd[2];
-  SCM a;
-  SCM b;
 
   SCM_VALIDATE_INUM (1,family);
   SCM_VALIDATE_INUM (2,style);
 
   SCM_VALIDATE_INUM (1,family);
   SCM_VALIDATE_INUM (2,style);
@@ -198,41 +474,35 @@ SCM_DEFINE (scm_socketpair, "socketpair", 3, 0, 0,
   if (socketpair (fam, SCM_INUM (style), SCM_INUM (proto), fd) == -1)
     SCM_SYSERROR;
 
   if (socketpair (fam, SCM_INUM (style), SCM_INUM (proto), fd) == -1)
     SCM_SYSERROR;
 
-  a = SCM_SOCK_FD_TO_PORT(fd[0]);
-  b = SCM_SOCK_FD_TO_PORT(fd[1]);
-  return scm_cons (a, b);
+  return scm_cons (SCM_SOCK_FD_TO_PORT (fd[0]), SCM_SOCK_FD_TO_PORT (fd[1]));
 }
 #undef FUNC_NAME
 #endif
 
 SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
             (SCM sock, SCM level, SCM optname),
 }
 #undef FUNC_NAME
 #endif
 
 SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
             (SCM sock, SCM level, SCM optname),
-           "Returns the value of a particular socket option for the socket\n"
-           "port @var{socket}.  @var{level} is an integer code for type of option\n"
-           "being requested, e.g., @code{SOL_SOCKET} for socket-level options.\n"
-           "@var{optname} is an\n"
-           "integer code for the option required and should be specified using one of\n"
-           "the symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n\n"
-           "The returned value is typically an integer but @code{SO_LINGER} returns a\n"
-           "pair of integers.")
+           "Return the value of a particular socket option for the socket\n"
+           "port @var{sock}.  @var{level} is an integer code for type of\n"
+           "option being requested, e.g., @code{SOL_SOCKET} for\n"
+           "socket-level options.  @var{optname} is an integer code for the\n"
+           "option required and should be specified using one of the\n"
+           "symbols @code{SO_DEBUG}, @code{SO_REUSEADDR} etc.\n\n"
+           "The returned value is typically an integer but @code{SO_LINGER}\n"
+           "returns a pair of integers.")
 #define FUNC_NAME s_scm_getsockopt
 {
   int fd;
 #define FUNC_NAME s_scm_getsockopt
 {
   int fd;
-  size_t optlen;
+  /* size of optval is the largest supported option.  */
 #ifdef HAVE_STRUCT_LINGER
   char optval[sizeof (struct linger)];
 #ifdef HAVE_STRUCT_LINGER
   char optval[sizeof (struct linger)];
+  int optlen = sizeof (struct linger);
 #else
 #else
-  char optval[sizeof (scm_sizet)];
+  char optval[sizeof (size_t)];
+  int optlen = sizeof (size_t);
 #endif
   int ilevel;
   int ioptname;
 
 #endif
   int ilevel;
   int ioptname;
 
-#ifdef HAVE_STRUCT_LINGER
-  optlen = sizeof (struct linger);
-#else
-  optlen = sizeof (size_t);
-#endif
-
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1, sock);
   SCM_VALIDATE_INUM_COPY (2, level, ilevel);
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1, sock);
   SCM_VALIDATE_INUM_COPY (2, level, ilevel);
@@ -242,42 +512,43 @@ SCM_DEFINE (scm_getsockopt, "getsockopt", 3, 0, 0,
   if (getsockopt (fd, ilevel, ioptname, (void *) optval, &optlen) == -1)
     SCM_SYSERROR;
 
   if (getsockopt (fd, ilevel, ioptname, (void *) optval, &optlen) == -1)
     SCM_SYSERROR;
 
-#ifdef SO_LINGER
-  if (ilevel == SOL_SOCKET && ioptname == SO_LINGER)
+  if (ilevel == SOL_SOCKET)
     {
     {
+#ifdef SO_LINGER
+      if (ioptname == SO_LINGER)
+       {
 #ifdef HAVE_STRUCT_LINGER
 #ifdef HAVE_STRUCT_LINGER
-      struct linger *ling = (struct linger *) optval;
-      return scm_cons (SCM_MAKINUM (ling->l_onoff),
-                      SCM_MAKINUM (ling->l_linger));
+         struct linger *ling = (struct linger *) optval;
+
+         return scm_cons (scm_long2num (ling->l_onoff),
+                          scm_long2num (ling->l_linger));
 #else
 #else
-      scm_sizet *ling = (scm_sizet *) optval;
-      return scm_cons (SCM_MAKINUM (*ling),
-                      SCM_MAKINUM (0));
+         return scm_cons (scm_long2num (*(int *) optval)
+                          SCM_MAKINUM (0));
 #endif
 #endif
-    }
+       }
+      else
 #endif
 #endif
+       if (0
 #ifdef SO_SNDBUF
 #ifdef SO_SNDBUF
-  if (ilevel == SOL_SOCKET && ioptname == SO_SNDBUF)
-    {
-      scm_sizet *bufsize = (scm_sizet *) optval;
-      return SCM_MAKINUM (*bufsize);
-    }
+           || ioptname == SO_SNDBUF
 #endif
 #ifdef SO_RCVBUF
 #endif
 #ifdef SO_RCVBUF
-  if (ilevel == SOL_SOCKET && ioptname == SO_RCVBUF)
-    {
-      scm_sizet *bufsize = (scm_sizet *) optval;
-      return SCM_MAKINUM (*bufsize);
-    }
+           || ioptname == SO_RCVBUF
 #endif
 #endif
-  return SCM_MAKINUM (*(int *) optval);
+           )
+         {
+           return scm_long2num (*(size_t *) optval);
+         }
+    }
+  return scm_long2num (*(int *) optval);
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_setsockopt, "setsockopt", 4, 0, 0,
             (SCM sock, SCM level, SCM optname, SCM value),
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_setsockopt, "setsockopt", 4, 0, 0,
             (SCM sock, SCM level, SCM optname, SCM value),
-           "Sets the value of a particular socket option for the socket\n"
-           "port @var{socket}.  @var{level} is an integer code for type of option\n"
+           "Set the value of a particular socket option for the socket\n"
+           "port @var{sock}.  @var{level} is an integer code for type of option\n"
            "being set, e.g., @code{SOL_SOCKET} for socket-level options.\n"
            "@var{optname} is an\n"
            "integer code for the option to set and should be specified using one of\n"
            "being set, e.g., @code{SOL_SOCKET} for socket-level options.\n"
            "@var{optname} is an\n"
            "integer code for the option to set and should be specified using one of\n"
@@ -289,66 +560,83 @@ SCM_DEFINE (scm_setsockopt, "setsockopt", 4, 0, 0,
 #define FUNC_NAME s_scm_setsockopt
 {
   int fd;
 #define FUNC_NAME s_scm_setsockopt
 {
   int fd;
-  int optlen;
+  int optlen = -1;
+  /* size of optval is the largest supported option.  */
 #ifdef HAVE_STRUCT_LINGER
 #ifdef HAVE_STRUCT_LINGER
-  char optval[sizeof (struct linger)]; /* Biggest option :-(  */
+  char optval[sizeof (struct linger)];
 #else
 #else
-  char optval[sizeof (scm_sizet)];
+  char optval[sizeof (size_t)];
 #endif
   int ilevel, ioptname;
 #endif
   int ilevel, ioptname;
+
   sock = SCM_COERCE_OUTPORT (sock);
   sock = SCM_COERCE_OUTPORT (sock);
-  SCM_VALIDATE_OPFPORT (1,sock);
-  SCM_VALIDATE_INUM_COPY (2,level,ilevel);
-  SCM_VALIDATE_INUM_COPY (3,optname,ioptname);
+
+  SCM_VALIDATE_OPFPORT (1, sock);
+  SCM_VALIDATE_INUM_COPY (2, level, ilevel);
+  SCM_VALIDATE_INUM_COPY (3, optname, ioptname);
+
   fd = SCM_FPORT_FDES (sock);
   fd = SCM_FPORT_FDES (sock);
-  if (0);
-#ifdef SO_LINGER
-  else if (ilevel == SOL_SOCKET && ioptname == SO_LINGER)
+
+  if (ilevel == SOL_SOCKET)
     {
     {
+#ifdef SO_LINGER
+      if (ioptname == SO_LINGER)
+       {
 #ifdef HAVE_STRUCT_LINGER
 #ifdef HAVE_STRUCT_LINGER
-      struct linger ling;
-      SCM_ASSERT (SCM_CONSP (value)
-                 && SCM_INUMP (SCM_CAR (value))
-                 &&  SCM_INUMP (SCM_CDR (value)),
-                 value, SCM_ARG4, FUNC_NAME);
-      ling.l_onoff = SCM_INUM (SCM_CAR (value));
-      ling.l_linger = SCM_INUM (SCM_CDR (value));
-      optlen = (int) sizeof (struct linger);
-      memcpy (optval, (void *) &ling, optlen);
+         struct linger ling;
+         long lv;
+
+         SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
+         lv = SCM_NUM2LONG (4, SCM_CAR (value));
+         ling.l_onoff = (int) lv;
+         SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_onoff == lv);
+         lv = SCM_NUM2LONG (4, SCM_CDR (value));
+         ling.l_linger = (int) lv;
+         SCM_ASSERT_RANGE (SCM_ARG4, value, ling.l_linger == lv);
+         optlen = (int) sizeof (struct linger);
+         memcpy (optval, (void *) &ling, optlen);
 #else
 #else
-      scm_sizet ling;
-      SCM_ASSERT (SCM_CONSP (value)
-                 && SCM_INUMP (SCM_CAR (value))
-                 &&  SCM_INUMP (SCM_CDR (value)),
-                 value, SCM_ARG4, FUNC_NAME);
-      ling = SCM_INUM (SCM_CAR (value));
-      optlen = (int) sizeof (scm_sizet);
-      (*(scm_sizet *) optval) = (scm_sizet) SCM_INUM (value);
+         int ling;
+         long lv;
+
+         SCM_ASSERT (SCM_CONSP (value), value, SCM_ARG4, FUNC_NAME);
+         /* timeout is ignored, but may as well validate it.  */
+         lv = SCM_NUM2LONG (4, SCM_CDR (value));
+         ling = (int) lv;
+         SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
+         lv = SCM_NUM2LONG (4, SCM_CAR (value));
+         ling = (int) lv;
+         SCM_ASSERT_RANGE (SCM_ARG4, value, ling == lv);
+         optlen = (int) sizeof (int);
+         (*(int *) optval) = ling;
 #endif
 #endif
-    }
+       }
+      else
 #endif
 #endif
+       if (0
 #ifdef SO_SNDBUF
 #ifdef SO_SNDBUF
-  else if (ilevel == SOL_SOCKET && ioptname == SO_SNDBUF)
-    {
-      SCM_VALIDATE_INUM (4,value);
-      optlen = (int) sizeof (scm_sizet);
-      (*(scm_sizet *) optval) = (scm_sizet) SCM_INUM (value);
-    }
+           || ioptname == SO_SNDBUF
 #endif
 #ifdef SO_RCVBUF
 #endif
 #ifdef SO_RCVBUF
-  else if (ilevel == SOL_SOCKET && ioptname == SO_RCVBUF)
-    {
-      SCM_VALIDATE_INUM (4,value);
-      optlen = (int) sizeof (scm_sizet);
-      (*(scm_sizet *) optval) = (scm_sizet) SCM_INUM (value);
-    }
+           || ioptname == SO_RCVBUF
 #endif
 #endif
-  else
+           )
+         {
+           long lv = SCM_NUM2LONG (4, value);
+
+           optlen = (int) sizeof (size_t);
+           (*(size_t *) optval) = (size_t) lv;
+         }
+    }
+  if (optlen == -1)
     {
     {
-      /* Most options just take an int.  */
-      SCM_VALIDATE_INUM (4,value);
+      /* Most options take an int.  */
+      long lv = SCM_NUM2LONG (4, value);
+      int val = (int) lv;
+
+      SCM_ASSERT_RANGE (SCM_ARG4, value, val == lv);
       optlen = (int) sizeof (int);
       optlen = (int) sizeof (int);
-      (*(int *) optval) = (int) SCM_INUM (value);
+      (*(int *) optval) = val;
     }
   if (setsockopt (fd, ilevel, ioptname, (void *) optval, optlen) == -1)
     SCM_SYSERROR;
     }
   if (setsockopt (fd, ilevel, ioptname, (void *) optval, optlen) == -1)
     SCM_SYSERROR;
@@ -394,46 +682,101 @@ SCM_DEFINE (scm_shutdown, "shutdown", 2, 0, 0,
    proc is the name of the original procedure.
    size returns the size of the structure allocated.  */
 
    proc is the name of the original procedure.
    size returns the size of the structure allocated.  */
 
-
 static struct sockaddr *
 static struct sockaddr *
-scm_fill_sockaddr (int fam,SCM address,SCM *args,int which_arg,const char *proc,scm_sizet *size)
+scm_fill_sockaddr (int fam, SCM address, SCM *args, int which_arg,
+                  const char *proc, int *size)
+#define FUNC_NAME proc
 {
   switch (fam)
     {
     case AF_INET:
       {
 {
   switch (fam)
     {
     case AF_INET:
       {
-       SCM isport;
        struct sockaddr_in *soka;
        struct sockaddr_in *soka;
+       unsigned long addr;
+       int port;
 
 
-       soka = (struct sockaddr_in *)
-         scm_must_malloc (sizeof (struct sockaddr_in), proc);
-       /* e.g., for BSDs which don't like invalid sin_len.  */
-       memset (soka, 0, sizeof (struct sockaddr_in));
-       soka->sin_family = AF_INET;
-       soka->sin_addr.s_addr =
-         htonl (scm_num2ulong (address, (char *) which_arg, proc));
-       SCM_ASSERT (SCM_CONSP (*args), *args, 
-                   which_arg + 1, proc);
-       isport = SCM_CAR (*args);
+       SCM_VALIDATE_ULONG_COPY (which_arg, address, addr);
+       SCM_VALIDATE_CONS (which_arg + 1, *args);
+       SCM_VALIDATE_INUM_COPY (which_arg + 1, SCM_CAR (*args), port);
        *args = SCM_CDR (*args);
        *args = SCM_CDR (*args);
-       SCM_ASSERT (SCM_INUMP (isport), isport, which_arg + 1, proc);
-       soka->sin_port = htons (SCM_INUM (isport));
+       soka = (struct sockaddr_in *) malloc (sizeof (struct sockaddr_in));
+       if (!soka)
+         scm_memory_error (proc);
+       /* 4.4BSD-style interface includes sin_len member and defines SIN_LEN,
+          4.3BSD  does not.  */
+#ifdef SIN_LEN
+       soka->sin_len = sizeof (struct sockaddr_in);
+#endif
+       soka->sin_family = AF_INET;
+       soka->sin_addr.s_addr = htonl (addr);
+       soka->sin_port = htons (port);
        *size = sizeof (struct sockaddr_in);
        return (struct sockaddr *) soka;
       }
        *size = sizeof (struct sockaddr_in);
        return (struct sockaddr *) soka;
       }
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      {
+       /* see RFC2553.  */
+       int port;
+       struct sockaddr_in6 *soka;
+       unsigned long flowinfo = 0;
+       unsigned long scope_id = 0;
+
+       VALIDATE_INET6 (which_arg, address);
+       SCM_VALIDATE_CONS (which_arg + 1, *args);
+       SCM_VALIDATE_INUM_COPY (which_arg + 1, SCM_CAR (*args), port);
+       *args = SCM_CDR (*args);
+       if (SCM_CONSP (*args))
+         {
+           SCM_VALIDATE_ULONG_COPY (which_arg + 2, SCM_CAR (*args), flowinfo);
+           *args = SCM_CDR (*args);
+           if (SCM_CONSP (*args))
+             {
+               SCM_VALIDATE_ULONG_COPY (which_arg + 3, SCM_CAR (*args),
+                                        scope_id);
+               *args = SCM_CDR (*args);
+             }
+         }
+       soka = (struct sockaddr_in6 *) malloc (sizeof (struct sockaddr_in6));
+       if (!soka)
+         scm_memory_error (proc);
+#ifdef SIN_LEN6
+       soka->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+       soka->sin6_family = AF_INET6;
+       ipv6_num_to_net (address, soka->sin6_addr.s6_addr);
+       soka->sin6_port = htons (port);
+       soka->sin6_flowinfo = flowinfo;
+#ifdef HAVE_SIN6_SCOPE_ID
+       soka->sin6_scope_id = scope_id;
+#endif
+       *size = sizeof (struct sockaddr_in6);
+       return (struct sockaddr *) soka;
+      }
+#endif
 #ifdef HAVE_UNIX_DOMAIN_SOCKETS
     case AF_UNIX:
       {
        struct sockaddr_un *soka;
 #ifdef HAVE_UNIX_DOMAIN_SOCKETS
     case AF_UNIX:
       {
        struct sockaddr_un *soka;
+       int addr_size;
 
 
-       soka = (struct sockaddr_un *)
-         scm_must_malloc (sizeof (struct sockaddr_un), proc);
-       memset (soka, 0, sizeof (struct sockaddr_un));
-       soka->sun_family = AF_UNIX;
        SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
        SCM_ASSERT (SCM_STRINGP (address), address, which_arg, proc);
-       memcpy (soka->sun_path, SCM_ROCHARS (address),
-               1 + SCM_STRING_LENGTH (address));
-       *size = sizeof (struct sockaddr_un);
+       /* the static buffer size in sockaddr_un seems to be arbitrary
+          and not necessarily a hard limit.  e.g., the glibc manual
+          suggests it may be possible to declare it size 0.  let's
+          ignore it.  if the O/S doesn't like the size it will cause
+          connect/bind etc., to fail.  sun_path is always the last
+          member of the structure.  */
+       addr_size = sizeof (struct sockaddr_un)
+         + max (0, SCM_STRING_LENGTH (address) + 1 - (sizeof soka->sun_path));
+       soka = (struct sockaddr_un *) malloc (addr_size);
+       if (!soka)
+         scm_memory_error (proc);
+       memset (soka, 0, addr_size);  /* for sun_len: see sin_len above. */
+       soka->sun_family = AF_UNIX;
+       memcpy (soka->sun_path, SCM_STRING_CHARS (address),
+               SCM_STRING_LENGTH (address));
+       *size = SUN_LEN (soka);
        return (struct sockaddr *) soka;
       }
 #endif
        return (struct sockaddr *) soka;
       }
 #endif
@@ -441,54 +784,69 @@ scm_fill_sockaddr (int fam,SCM address,SCM *args,int which_arg,const char *proc,
       scm_out_of_range (proc, SCM_MAKINUM (fam));
     }
 }
       scm_out_of_range (proc, SCM_MAKINUM (fam));
     }
 }
+#undef FUNC_NAME
   
 SCM_DEFINE (scm_connect, "connect", 3, 0, 1,
             (SCM sock, SCM fam, SCM address, SCM args),
   
 SCM_DEFINE (scm_connect, "connect", 3, 0, 1,
             (SCM sock, SCM fam, SCM address, SCM args),
-           "Initiates a connection from @var{socket} to the address\n"
-           "specified by @var{address} and possibly @var{arg @dots{}}.  The format\n"
-           "required for @var{address}\n"
-           "and @var{arg} @dots{} depends on the family of the socket.\n\n"
+           "Initiate a connection from a socket using a specified address\n"
+           "family to the address\n"
+           "specified by @var{address} and possibly @var{args}.\n"
+           "The format required for @var{address}\n"
+           "and @var{args} depends on the family of the socket.\n\n"
            "For a socket of family @code{AF_UNIX},\n"
            "For a socket of family @code{AF_UNIX},\n"
-           "only @code{address} is specified and must be a string with the\n"
+           "only @var{address} is specified and must be a string with the\n"
            "filename where the socket is to be created.\n\n"
            "For a socket of family @code{AF_INET},\n"
            "filename where the socket is to be created.\n\n"
            "For a socket of family @code{AF_INET},\n"
-           "@code{address} must be an integer Internet host address and @var{arg} @dots{}\n"
-           "must be a single integer port number.\n\n"
+           "@var{address} must be an integer IPv4 host address and\n"
+           "@var{args} must be a single integer port number.\n\n"
+           "For a socket of family @code{AF_INET6},\n"
+           "@var{address} must be an integer IPv6 host address and\n"
+           "@var{args} may be up to three integers:\n"
+           "port [flowinfo] [scope_id],\n"
+           "where flowinfo and scope_id default to zero.\n\n"
            "The return value is unspecified.")
 #define FUNC_NAME s_scm_connect
 {
   int fd;
   struct sockaddr *soka;
            "The return value is unspecified.")
 #define FUNC_NAME s_scm_connect
 {
   int fd;
   struct sockaddr *soka;
-  scm_sizet size;
+  int size;
 
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1,sock);
   SCM_VALIDATE_INUM (2,fam);
   fd = SCM_FPORT_FDES (sock);
 
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1,sock);
   SCM_VALIDATE_INUM (2,fam);
   fd = SCM_FPORT_FDES (sock);
-  soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME, &size);
+  soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME,
+                           &size);
   if (connect (fd, soka, size) == -1)
   if (connect (fd, soka, size) == -1)
-    SCM_SYSERROR;
-  scm_must_free ((char *) soka);
+    {
+      int save_errno = errno;
+      
+      free (soka);
+      errno = save_errno;
+      SCM_SYSERROR;
+    }
+  free (soka);
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_bind, "bind", 3, 0, 1,
             (SCM sock, SCM fam, SCM address, SCM args),
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_bind, "bind", 3, 0, 1,
             (SCM sock, SCM fam, SCM address, SCM args),
-           "Assigns an address to the socket port @var{socket}.\n"
+           "Assign an address to the socket port @var{sock}.\n"
            "Generally this only needs to be done for server sockets,\n"
            "so they know where to look for incoming connections.  A socket\n"
            "without an address will be assigned one automatically when it\n"
            "starts communicating.\n\n"
            "Generally this only needs to be done for server sockets,\n"
            "so they know where to look for incoming connections.  A socket\n"
            "without an address will be assigned one automatically when it\n"
            "starts communicating.\n\n"
-           "The format of @var{address} and @var{ARG} @dots{} depends on the family\n"
-           "of the socket.\n\n"
+           "The format of @var{address} and @var{args} depends\n"
+           "on the family of the socket.\n\n"
            "For a socket of family @code{AF_UNIX}, only @var{address}\n"
            "For a socket of family @code{AF_UNIX}, only @var{address}\n"
-           "is specified and must \n"
-           "be a string with the filename where the socket is to be created.\n\n"
-           "For a socket of family @code{AF_INET}, @var{address} must be an integer\n"
-           "Internet host address and @var{arg} @dots{} must be a single integer\n"
-           "port number.\n\n"
-           "The values of the following variables can also be used for @var{address}:\n\n"
+           "is specified and must be a string with the filename where\n"
+           "the socket is to be created.\n\n"
+           "For a socket of family @code{AF_INET}, @var{address}\n"
+           "must be an integer IPv4 address and @var{args}\n"
+           "must be a single integer port number.\n\n"
+           "The values of the following variables can also be used for\n"
+           "@var{address}:\n\n"
            "@defvar INADDR_ANY\n"
            "Allow connections from any address.\n"
            "@end defvar\n\n"
            "@defvar INADDR_ANY\n"
            "Allow connections from any address.\n"
            "@end defvar\n\n"
@@ -501,34 +859,45 @@ SCM_DEFINE (scm_bind, "bind", 3, 0, 1,
            "@defvar INADDR_NONE\n"
            "No address.\n"
            "@end defvar\n\n"
            "@defvar INADDR_NONE\n"
            "No address.\n"
            "@end defvar\n\n"
+           "For a socket of family @code{AF_INET6}, @var{address}\n"
+           "must be an integer IPv6 address and @var{args}\n"
+           "may be up to three integers:\n"
+           "port [flowinfo] [scope_id],\n"
+           "where flowinfo and scope_id default to zero.\n\n"
            "The return value is unspecified.")
 #define FUNC_NAME s_scm_bind
 {
            "The return value is unspecified.")
 #define FUNC_NAME s_scm_bind
 {
-  int rv;
   struct sockaddr *soka;
   struct sockaddr *soka;
-  scm_sizet size;
+  int size;
   int fd;
 
   sock = SCM_COERCE_OUTPORT (sock);
   int fd;
 
   sock = SCM_COERCE_OUTPORT (sock);
-  SCM_VALIDATE_OPFPORT (1,sock);
-  SCM_VALIDATE_INUM (2,fam);
-  soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME, &size);
+  SCM_VALIDATE_OPFPORT (1, sock);
+  SCM_VALIDATE_INUM (2, fam);
+  soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args, 3, FUNC_NAME,
+                           &size);
   fd = SCM_FPORT_FDES (sock);
   fd = SCM_FPORT_FDES (sock);
-  rv = bind (fd, soka, size);
-  if (rv == -1)
+  if (bind (fd, soka, size) == -1)
+  {
+    int save_errno = errno;
+      
+    free (soka);
+    errno = save_errno;
     SCM_SYSERROR;
     SCM_SYSERROR;
-  scm_must_free ((char *) soka);
+  }
+  free (soka);
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
             (SCM sock, SCM backlog),
   return SCM_UNSPECIFIED;
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
             (SCM sock, SCM backlog),
-           "This procedure enables @var{socket} to accept connection\n"
+           "Enable @var{sock} to accept connection\n"
            "requests.  @var{backlog} is an integer specifying\n"
            "the maximum length of the queue for pending connections.\n"
            "requests.  @var{backlog} is an integer specifying\n"
            "the maximum length of the queue for pending connections.\n"
-           "If the queue fills, new clients will fail to connect until the\n"
-           "server calls @code{accept} to accept a connection from the queue.\n\n"
+           "If the queue fills, new clients will fail to connect until\n"
+           "the server calls @code{accept} to accept a connection from\n"
+           "the queue.\n\n"
            "The return value is unspecified.")
 #define FUNC_NAME s_scm_listen
 {
            "The return value is unspecified.")
 #define FUNC_NAME s_scm_listen
 {
@@ -544,72 +913,97 @@ SCM_DEFINE (scm_listen, "listen", 2, 0, 0,
 #undef FUNC_NAME
 
 /* Put the components of a sockaddr into a new SCM vector.  */
 #undef FUNC_NAME
 
 /* Put the components of a sockaddr into a new SCM vector.  */
-
 static SCM
 static SCM
-scm_addr_vector (struct sockaddr *address,const char *proc)
+scm_addr_vector (const struct sockaddr *address, const char *proc)
 {
   short int fam = address->sa_family;
   SCM result;
   SCM *ve;
 {
   short int fam = address->sa_family;
   SCM result;
   SCM *ve;
-#ifdef HAVE_UNIX_DOMAIN_SOCKETS
-  if (fam == AF_UNIX)
+
+  switch (fam)
     {
     {
-      struct sockaddr_un *nad = (struct sockaddr_un *) address;
-      result = scm_make_vector (SCM_MAKINUM (2), SCM_UNSPECIFIED);
-      ve = SCM_VELTS (result);
-      ve[0] = scm_ulong2num ((unsigned long) fam);
-      ve[1] = scm_makfromstr (nad->sun_path,
-                             (scm_sizet) strlen (nad->sun_path), 0);
-    }
-  else 
+    case AF_INET:
+      {
+       const struct sockaddr_in *nad = (struct sockaddr_in *) address;
+
+       result = scm_c_make_vector (3, SCM_UNSPECIFIED);
+       ve = SCM_VELTS (result);
+       ve[0] = scm_ulong2num ((unsigned long) fam);
+       ve[1] = scm_ulong2num (ntohl (nad->sin_addr.s_addr));
+       ve[2] = scm_ulong2num ((unsigned long) ntohs (nad->sin_port));
+      }
+      break;
+#ifdef HAVE_IPV6
+    case AF_INET6:
+      {
+       const struct sockaddr_in6 *nad = (struct sockaddr_in6 *) address;
+
+       result = scm_c_make_vector (5, SCM_UNSPECIFIED);
+       ve = SCM_VELTS (result);
+       ve[0] = scm_ulong2num ((unsigned long) fam);
+       ve[1] = ipv6_net_to_num (nad->sin6_addr.s6_addr);
+       ve[2] = scm_ulong2num ((unsigned long) ntohs (nad->sin6_port));
+       ve[3] = scm_ulong2num ((unsigned long) nad->sin6_flowinfo);
+#ifdef HAVE_SIN6_SCOPE_ID
+       ve[4] = scm_ulong2num ((unsigned long) nad->sin6_scope_id);
+#else
+       ve[4] = SCM_INUM0;
 #endif
 #endif
-  if (fam == AF_INET)
-    {
-      struct sockaddr_in *nad = (struct sockaddr_in *) address;
-      result = scm_make_vector (SCM_MAKINUM (3), SCM_UNSPECIFIED);
-      ve = SCM_VELTS (result);
-      ve[0] = scm_ulong2num ((unsigned long) fam);
-      ve[1] = scm_ulong2num (ntohl (nad->sin_addr.s_addr));
-      ve[2] = scm_ulong2num ((unsigned long) ntohs (nad->sin_port));
-    }
-  else
-    scm_misc_error (proc, "Unrecognised address family: ~A",
-                   scm_listify (SCM_MAKINUM (fam), SCM_UNDEFINED));
+      }
+      break;
+#endif
+#ifdef HAVE_UNIX_DOMAIN_SOCKETS
+    case AF_UNIX:
+      {
+       const struct sockaddr_un *nad = (struct sockaddr_un *) address;
 
 
+       result = scm_c_make_vector (2, SCM_UNSPECIFIED);
+       ve = SCM_VELTS (result);
+       ve[0] = scm_ulong2num ((unsigned long) fam);
+       ve[1] = scm_makfromstr (nad->sun_path,
+                               (size_t) strlen (nad->sun_path), 0);
+      }
+      break;
+#endif
+    default:
+      scm_misc_error (proc, "Unrecognised address family: ~A",
+                     SCM_LIST1 (SCM_MAKINUM (fam)));
+    }
   return result;
 }
 
   return result;
 }
 
-/* Allocate a buffer large enough to hold any sockaddr type.  */
-static char *scm_addr_buffer;
-static size_t scm_addr_buffer_size;
+/* calculate the size of a buffer large enough to hold any supported
+   sockaddr type.  if the buffer isn't large enough, certain system
+   calls will return a truncated address.  */
 
 
-static void
-scm_init_addr_buffer (void)
-{
-  scm_addr_buffer_size =
-#ifdef HAVE_UNIX_DOMAIN_SOCKETS
-  sizeof (struct sockaddr_un)
+#if defined (HAVE_UNIX_DOMAIN_SOCKETS)
+#define MAX_SIZE_UN sizeof (struct sockaddr_un)
 #else
 #else
-  0
+#define MAX_SIZE_UN 0
+#endif
+
+#if defined (HAVE_IPV6)
+#define MAX_SIZE_IN6 sizeof (struct sockaddr_in6)
+#else
+#define MAX_SIZE_IN6 0
 #endif
 #endif
-  ;
-  if (sizeof (struct sockaddr_in) > scm_addr_buffer_size)
-    scm_addr_buffer_size = sizeof (struct sockaddr_in);
-  scm_addr_buffer = scm_must_malloc (scm_addr_buffer_size, "address buffer");
-}
+
+#define MAX_ADDR_SIZE max (max (sizeof (struct sockaddr_in), MAX_SIZE_IN6),\
+                           MAX_SIZE_UN)
 
 SCM_DEFINE (scm_accept, "accept", 1, 0, 0, 
             (SCM sock),
 
 SCM_DEFINE (scm_accept, "accept", 1, 0, 0, 
             (SCM sock),
-           "Accepts a connection on a bound, listening socket @var{socket}.  If there\n"
-           "are no pending connections in the queue, it waits until\n"
-           "one is available unless the non-blocking option has been set on the\n"
-           "socket.\n\n"
+           "Accept a connection on a bound, listening socket.\n"
+           "If there\n"
+           "are no pending connections in the queue, wait until\n"
+           "one is available unless the non-blocking option has been\n"
+           "set on the socket.\n\n"
            "The return value is a\n"
            "The return value is a\n"
-           "pair in which the CAR is a new socket port for the connection and\n"
-           "the CDR is an object with address information about the client which\n"
-           "initiated the connection.\n\n"
-           "If the address is not available then the CDR will be an empty vector.\n\n"
-           "@var{socket} does not become part of the\n"
+           "pair in which the @emph{car} is a new socket port for the\n"
+           "connection and\n"
+           "the @emph{cdr} is an object with address information about the\n"
+           "client which initiated the connection.\n\n"
+           "@var{sock} does not become part of the\n"
            "connection and will continue to accept new requests.")
 #define FUNC_NAME s_scm_accept
 {
            "connection and will continue to accept new requests.")
 #define FUNC_NAME s_scm_accept
 {
@@ -617,85 +1011,83 @@ SCM_DEFINE (scm_accept, "accept", 1, 0, 0,
   int newfd;
   SCM address;
   SCM newsock;
   int newfd;
   SCM address;
   SCM newsock;
+  int addr_size = MAX_ADDR_SIZE;
+  char max_addr[MAX_ADDR_SIZE];
+  struct sockaddr *addr = (struct sockaddr *) max_addr;
 
 
-  size_t tmp_size;
   sock = SCM_COERCE_OUTPORT (sock);
   sock = SCM_COERCE_OUTPORT (sock);
-  SCM_VALIDATE_OPFPORT (1,sock);
+  SCM_VALIDATE_OPFPORT (1, sock);
   fd = SCM_FPORT_FDES (sock);
   fd = SCM_FPORT_FDES (sock);
-  tmp_size = scm_addr_buffer_size;
-  newfd = accept (fd, (struct sockaddr *) scm_addr_buffer, &tmp_size);
-  newsock = scm_sock_fd_to_port (newfd, FUNC_NAME);
-  if (tmp_size > 0)
-    address = scm_addr_vector ((struct sockaddr *) scm_addr_buffer, FUNC_NAME);
-  else
-    address = SCM_BOOL_F;
-  
+  newfd = accept (fd, addr, &addr_size);
+  if (newfd == -1)
+    SCM_SYSERROR;
+  newsock = SCM_SOCK_FD_TO_PORT (newfd);
+  address = scm_addr_vector (addr, FUNC_NAME);
   return scm_cons (newsock, address);
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0, 
             (SCM sock),
   return scm_cons (newsock, address);
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_getsockname, "getsockname", 1, 0, 0, 
             (SCM sock),
-           "Returns the address of @var{socket}, in the same form as the object\n"
-           "returned by @code{accept}.  On many systems the address of a socket\n"
-           "in the @code{AF_FILE} namespace cannot be read.")
+           "Return the address of @var{sock}, in the same form as the\n"
+           "object returned by @code{accept}.  On many systems the address\n"
+           "of a socket in the @code{AF_FILE} namespace cannot be read.")
 #define FUNC_NAME s_scm_getsockname
 {
 #define FUNC_NAME s_scm_getsockname
 {
-  size_t tmp_size;
   int fd;
   int fd;
-  SCM result;
+  int addr_size = MAX_ADDR_SIZE;
+  char max_addr[MAX_ADDR_SIZE];
+  struct sockaddr *addr = (struct sockaddr *) max_addr;
+
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1,sock);
   fd = SCM_FPORT_FDES (sock);
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1,sock);
   fd = SCM_FPORT_FDES (sock);
-  tmp_size = scm_addr_buffer_size;
-  if (getsockname (fd, (struct sockaddr *) scm_addr_buffer, &tmp_size) == -1)
+  if (getsockname (fd, addr, &addr_size) == -1)
     SCM_SYSERROR;
     SCM_SYSERROR;
-  if (tmp_size > 0)
-    result = scm_addr_vector ((struct sockaddr *) scm_addr_buffer, FUNC_NAME);
-  else
-    result = SCM_BOOL_F;
-  return result;
+  return scm_addr_vector (addr, FUNC_NAME);
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0, 
             (SCM sock),
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_getpeername, "getpeername", 1, 0, 0, 
             (SCM sock),
-           "Returns the address of the socket that the socket @var{socket} is connected to,\n"
-           "in the same form as the object\n"
-           "returned by @code{accept}.  On many systems the address of a socket\n"
-           "in the @code{AF_FILE} namespace cannot be read.")
+           "Return the address that @var{sock}\n"
+           "is connected to, in the same form as the object returned by\n"
+           "@code{accept}.  On many systems the address of a socket in the\n"
+           "@code{AF_FILE} namespace cannot be read.")
 #define FUNC_NAME s_scm_getpeername
 {
 #define FUNC_NAME s_scm_getpeername
 {
-  size_t tmp_size;
   int fd;
   int fd;
-  SCM result;
+  int addr_size = MAX_ADDR_SIZE;
+  char max_addr[MAX_ADDR_SIZE];
+  struct sockaddr *addr = (struct sockaddr *) max_addr;
+
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1,sock);
   fd = SCM_FPORT_FDES (sock);
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_OPFPORT (1,sock);
   fd = SCM_FPORT_FDES (sock);
-  tmp_size = scm_addr_buffer_size;
-  if (getpeername (fd, (struct sockaddr *) scm_addr_buffer, &tmp_size) == -1)
+  if (getpeername (fd, addr, &addr_size) == -1)
     SCM_SYSERROR;
     SCM_SYSERROR;
-  if (tmp_size > 0)
-    result = scm_addr_vector ((struct sockaddr *) scm_addr_buffer, FUNC_NAME);
-  else
-    result = SCM_BOOL_F;
-  return result;
+  return scm_addr_vector (addr, FUNC_NAME);
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
             (SCM sock, SCM buf, SCM flags),
 }
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
             (SCM sock, SCM buf, SCM flags),
-           "Receives data from the socket port @var{socket}.  @var{socket} must already\n"
+           "Receive data from a socket port.\n"
+           "@var{sock} must already\n"
            "be bound to the address from which data is to be received.\n"
            "@var{buf} is a string into which\n"
            "be bound to the address from which data is to be received.\n"
            "@var{buf} is a string into which\n"
-           "the data will be written.  The size of @var{buf} limits the amount of\n"
+           "the data will be written.  The size of @var{buf} limits\n"
+           "the amount of\n"
            "data which can be received: in the case of packet\n"
            "data which can be received: in the case of packet\n"
-           "protocols, if a packet larger than this limit is encountered then some data\n"
+           "protocols, if a packet larger than this limit is encountered\n"
+           "then some data\n"
            "will be irrevocably lost.\n\n"
            "The optional @var{flags} argument is a value or\n"
            "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
            "will be irrevocably lost.\n\n"
            "The optional @var{flags} argument is a value or\n"
            "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
-           "The value returned is the number of bytes read from the socket.\n\n"
-           "Note that the data is read directly from the socket file descriptor:\n"
+           "The value returned is the number of bytes read from the\n"
+           "socket.\n\n"
+           "Note that the data is read directly from the socket file\n"
+           "descriptor:\n"
            "any unread buffered port data is ignored.")
 #define FUNC_NAME s_scm_recv
 {
            "any unread buffered port data is ignored.")
 #define FUNC_NAME s_scm_recv
 {
@@ -718,13 +1110,17 @@ SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
 
 SCM_DEFINE (scm_send, "send", 2, 1, 0,
             (SCM sock, SCM message, SCM flags),
 
 SCM_DEFINE (scm_send, "send", 2, 1, 0,
             (SCM sock, SCM message, SCM flags),
-           "Transmits the string @var{message} on the socket port @var{socket}. \n"
-           "@var{socket} must already be bound to a destination address.  The\n"
-           "value returned is the number of bytes transmitted -- it's possible for\n"
-           "this to be less than the length of @var{message} if the socket is\n"
-           "set to be non-blocking.  The optional @var{flags} argument is a value or\n"
+           "Transmit the string @var{message} on a socket port @var{sock}.\n"
+           "@var{sock} must already be bound to a destination address.  The\n"
+           "value returned is the number of bytes transmitted --\n"
+           "it's possible for\n"
+           "this to be less than the length of @var{message}\n"
+           "if the socket is\n"
+           "set to be non-blocking.  The optional @var{flags} argument\n"
+           "is a value or\n"
            "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
            "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
-           "Note that the data is written directly to the socket file descriptor:\n"
+           "Note that the data is written directly to the socket\n"
+           "file descriptor:\n"
            "any unflushed buffered port data is ignored.")
 #define FUNC_NAME s_scm_send
 {
            "any unflushed buffered port data is ignored.")
 #define FUNC_NAME s_scm_send
 {
@@ -738,7 +1134,7 @@ SCM_DEFINE (scm_send, "send", 2, 1, 0,
   SCM_VALIDATE_INUM_DEF_COPY (3,flags,0,flg);
   fd = SCM_FPORT_FDES (sock);
 
   SCM_VALIDATE_INUM_DEF_COPY (3,flags,0,flg);
   fd = SCM_FPORT_FDES (sock);
 
-  SCM_SYSCALL (rv = send (fd, SCM_ROCHARS (message), SCM_STRING_LENGTH (message), flg));
+  SCM_SYSCALL (rv = send (fd, SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message), flg));
   if (rv == -1)
     SCM_SYSERROR;
   return SCM_MAKINUM (rv);
   if (rv == -1)
     SCM_SYSERROR;
   return SCM_MAKINUM (rv);
@@ -746,74 +1142,58 @@ SCM_DEFINE (scm_send, "send", 2, 1, 0,
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
 #undef FUNC_NAME
 
 SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
-            (SCM sock, SCM buf, SCM flags, SCM start, SCM end),
-           "Returns data from the socket port @var{socket} and also information about\n"
-           "where the data was received from.  @var{socket} must already\n"
-           "be bound to the address from which data is to be received.\n"
-           "@code{buf}, is a string into which\n"
-           "the data will be written.  The size of @var{buf} limits the amount of\n"
-           "data which can be received: in the case of packet\n"
-           "protocols, if a packet larger than this limit is encountered then some data\n"
-           "will be irrevocably lost.\n\n"
-           "The optional @var{flags} argument is a value or\n"
-           "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
-           "The value returned is a pair: the CAR is the number of bytes read from\n"
-           "the socket and the CDR an address object in the same form as returned by\n"
-           "@code{accept}.\n\n"
-           "The @var{start} and @var{end} arguments specify a substring of @var{buf}\n"
-           "to which the data should be written.\n\n"
-           "Note that the data is read directly from the socket file descriptor:\n"
-           "any unread buffered port data is ignored.")
+            (SCM sock, SCM str, SCM flags, SCM start, SCM end),
+           "Return data from the socket port @var{sock} and also\n"
+           "information about where the data was received from.\n"
+           "@var{sock} must already be bound to the address from which\n"
+           "data is to be received.  @code{str}, is a string into which the\n"
+           "data will be written.  The size of @var{str} limits the amount\n"
+           "of data which can be received: in the case of packet protocols,\n"
+           "if a packet larger than this limit is encountered then some\n"
+           "data will be irrevocably lost.\n\n"
+           "The optional @var{flags} argument is a value or bitwise OR of\n"
+           "@code{MSG_OOB}, @code{MSG_PEEK}, @code{MSG_DONTROUTE} etc.\n\n"
+           "The value returned is a pair: the @emph{car} is the number of\n"
+           "bytes read from the socket and the @emph{cdr} an address object\n"
+           "in the same form as returned by @code{accept}.  The address\n"
+           "will given as @code{#f} if not available, as is usually the\n"
+           "case for stream sockets.\n\n"
+           "The @var{start} and @var{end} arguments specify a substring of\n"
+           "@var{str} to which the data should be written.\n\n"
+           "Note that the data is read directly from the socket file\n"
+           "descriptor: any unread buffered port data is ignored.")
 #define FUNC_NAME s_scm_recvfrom
 {
   int rv;
   int fd;
   int flg;
 #define FUNC_NAME s_scm_recvfrom
 {
   int rv;
   int fd;
   int flg;
-  int offset = 0;
+  char *buf;
+  int offset;
   int cend;
   int cend;
-  size_t tmp_size;
   SCM address;
   SCM address;
+  int addr_size = MAX_ADDR_SIZE;
+  char max_addr[MAX_ADDR_SIZE];
+  struct sockaddr *addr = (struct sockaddr *) max_addr;
 
   SCM_VALIDATE_OPFPORT (1,sock);
 
   SCM_VALIDATE_OPFPORT (1,sock);
-  SCM_VALIDATE_STRING (2,buf);
-  cend = SCM_STRING_LENGTH (buf);
-  
+  fd = SCM_FPORT_FDES (sock);
+  SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, str, buf, 4, start, offset,
+                                   5, end, cend);
   if (SCM_UNBNDP (flags))
     flg = 0;
   else
   if (SCM_UNBNDP (flags))
     flg = 0;
   else
-    {
-      flg = SCM_NUM2ULONG (3,flags);
+    SCM_VALIDATE_ULONG_COPY (3, flags, flg);
 
 
-      if (!SCM_UNBNDP (start))
-       {
-         offset = (int) SCM_NUM2LONG (4,start);
-         
-         if (offset < 0 || offset >= cend)
-           SCM_OUT_OF_RANGE (4, start);
-
-         if (!SCM_UNBNDP (end))
-           {
-             int tend = (int) SCM_NUM2LONG (5,end);
-      
-             if (tend <= offset || tend > cend)
-               SCM_OUT_OF_RANGE (5, end);
-
-             cend = tend;
-           }
-       }
-    }
-
-  fd = SCM_FPORT_FDES (sock);
-
-  tmp_size = scm_addr_buffer_size;
-  SCM_SYSCALL (rv = recvfrom (fd, SCM_STRING_CHARS (buf) + offset,
+  /* recvfrom will not necessarily return an address.  usually nothing
+     is returned for stream sockets.  */
+  addr->sa_family = AF_UNSPEC;
+  SCM_SYSCALL (rv = recvfrom (fd, buf + offset,
                              cend - offset, flg,
                              cend - offset, flg,
-                             (struct sockaddr *) scm_addr_buffer,
-                             &tmp_size));
+                             addr, &addr_size));
   if (rv == -1)
     SCM_SYSERROR;
   if (rv == -1)
     SCM_SYSERROR;
-  if (tmp_size > 0)
-    address = scm_addr_vector ((struct sockaddr *) scm_addr_buffer, FUNC_NAME);
+  if (addr->sa_family != AF_UNSPEC)
+    address = scm_addr_vector (addr, FUNC_NAME);
   else
     address = SCM_BOOL_F;
 
   else
     address = SCM_BOOL_F;
 
@@ -823,15 +1203,22 @@ SCM_DEFINE (scm_recvfrom, "recvfrom!", 2, 3, 0,
 
 SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
             (SCM sock, SCM message, SCM fam, SCM address, SCM args_and_flags),
 
 SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
             (SCM sock, SCM message, SCM fam, SCM address, SCM args_and_flags),
-           "Transmits the string @var{message} on the socket port @var{socket}.  The\n"
-           "destination address is specified using the @var{family}, @var{address} and\n"
-           "@var{arg} arguments, in a similar way to the @code{connect}\n"
-           "procedure.  The\n"
-           "value returned is the number of bytes transmitted -- it's possible for\n"
-           "this to be less than the length of @var{message} if the socket is\n"
-           "set to be non-blocking.  The optional @var{flags} argument is a value or\n"
+           "Transmit the string @var{message} on the socket port\n"
+           "@var{sock}.  The\n"
+           "destination address is specified using the @var{fam},\n"
+           "@var{address} and\n"
+           "@var{args_and_flags} arguments, in a similar way to the\n"
+           "@code{connect} procedure.  @var{args_and_flags} contains\n"
+           "the usual connection arguments optionally followed by\n"
+           "a flags argument, which is a value or\n"
            "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
            "bitwise OR of MSG_OOB, MSG_PEEK, MSG_DONTROUTE etc.\n\n"
-           "Note that the data is written directly to the socket file descriptor:\n"
+           "The value returned is the number of bytes transmitted --\n"
+           "it's possible for\n"
+           "this to be less than the length of @var{message} if the\n"
+           "socket is\n"
+           "set to be non-blocking.\n"
+           "Note that the data is written directly to the socket\n"
+           "file descriptor:\n"
            "any unflushed buffered port data is ignored.")
 #define FUNC_NAME s_scm_sendto
 {
            "any unflushed buffered port data is ignored.")
 #define FUNC_NAME s_scm_sendto
 {
@@ -839,8 +1226,7 @@ SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
   int fd;
   int flg;
   struct sockaddr *soka;
   int fd;
   int flg;
   struct sockaddr *soka;
-  scm_sizet size;
-  int save_err;
+  int size;
 
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_FPORT (1,sock);
 
   sock = SCM_COERCE_OUTPORT (sock);
   SCM_VALIDATE_FPORT (1,sock);
@@ -854,15 +1240,19 @@ SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
   else
     {
       SCM_VALIDATE_CONS (5,args_and_flags);
   else
     {
       SCM_VALIDATE_CONS (5,args_and_flags);
-      flg = SCM_NUM2ULONG (5,SCM_CAR (args_and_flags));
+      flg = SCM_NUM2ULONG (5, SCM_CAR (args_and_flags));
     }
     }
-  SCM_SYSCALL (rv = sendto (fd, SCM_ROCHARS (message), SCM_STRING_LENGTH (message),
+  SCM_SYSCALL (rv = sendto (fd, SCM_STRING_CHARS (message),
+                           SCM_STRING_LENGTH (message),
                            flg, soka, size));
                            flg, soka, size));
-  save_err = errno;
-  scm_must_free ((char *) soka);
-  errno = save_err;
   if (rv == -1)
   if (rv == -1)
-    SCM_SYSERROR;
+    {
+      int save_errno = errno;
+      free (soka);
+      errno = save_errno;
+      SCM_SYSERROR;
+    }
+  free (soka);
   return SCM_MAKINUM (rv);
 }
 #undef FUNC_NAME
   return SCM_MAKINUM (rv);
 }
 #undef FUNC_NAME
@@ -874,109 +1264,130 @@ scm_init_socket ()
 {
   /* protocol families.  */
 #ifdef AF_UNSPEC
 {
   /* protocol families.  */
 #ifdef AF_UNSPEC
-  scm_sysintern ("AF_UNSPEC", SCM_MAKINUM (AF_UNSPEC));
+  scm_c_define ("AF_UNSPEC", SCM_MAKINUM (AF_UNSPEC));
 #endif
 #ifdef AF_UNIX
 #endif
 #ifdef AF_UNIX
-  scm_sysintern ("AF_UNIX", SCM_MAKINUM (AF_UNIX));
+  scm_c_define ("AF_UNIX", SCM_MAKINUM (AF_UNIX));
 #endif
 #ifdef AF_INET
 #endif
 #ifdef AF_INET
-  scm_sysintern ("AF_INET", SCM_MAKINUM (AF_INET));
+  scm_c_define ("AF_INET", SCM_MAKINUM (AF_INET));
+#endif
+#ifdef AF_INET6
+  scm_c_define ("AF_INET6", SCM_MAKINUM (AF_INET6));
 #endif
 
 #ifdef PF_UNSPEC
 #endif
 
 #ifdef PF_UNSPEC
-  scm_sysintern ("PF_UNSPEC", SCM_MAKINUM (PF_UNSPEC));
+  scm_c_define ("PF_UNSPEC", SCM_MAKINUM (PF_UNSPEC));
 #endif
 #ifdef PF_UNIX
 #endif
 #ifdef PF_UNIX
-  scm_sysintern ("PF_UNIX", SCM_MAKINUM (PF_UNIX));
+  scm_c_define ("PF_UNIX", SCM_MAKINUM (PF_UNIX));
 #endif
 #ifdef PF_INET
 #endif
 #ifdef PF_INET
-  scm_sysintern ("PF_INET", SCM_MAKINUM (PF_INET));
+  scm_c_define ("PF_INET", SCM_MAKINUM (PF_INET));
+#endif
+#ifdef PF_INET6
+  scm_c_define ("PF_INET6", SCM_MAKINUM (PF_INET6));
+#endif
+
+  /* standard addresses.  */
+#ifdef INADDR_ANY
+  scm_c_define ("INADDR_ANY", scm_ulong2num (INADDR_ANY));
+#endif
+#ifdef INADDR_BROADCAST
+  scm_c_define ("INADDR_BROADCAST", scm_ulong2num (INADDR_BROADCAST));
+#endif
+#ifdef INADDR_NONE
+  scm_c_define ("INADDR_NONE", scm_ulong2num (INADDR_NONE));
+#endif
+#ifdef INADDR_LOOPBACK
+  scm_c_define ("INADDR_LOOPBACK", scm_ulong2num (INADDR_LOOPBACK));
 #endif
 
   /* socket types.  */
 #ifdef SOCK_STREAM
 #endif
 
   /* socket types.  */
 #ifdef SOCK_STREAM
-  scm_sysintern ("SOCK_STREAM", SCM_MAKINUM (SOCK_STREAM));
+  scm_c_define ("SOCK_STREAM", SCM_MAKINUM (SOCK_STREAM));
 #endif
 #ifdef SOCK_DGRAM
 #endif
 #ifdef SOCK_DGRAM
-  scm_sysintern ("SOCK_DGRAM", SCM_MAKINUM (SOCK_DGRAM));
+  scm_c_define ("SOCK_DGRAM", SCM_MAKINUM (SOCK_DGRAM));
 #endif
 #ifdef SOCK_RAW
 #endif
 #ifdef SOCK_RAW
-  scm_sysintern ("SOCK_RAW", SCM_MAKINUM (SOCK_RAW));
+  scm_c_define ("SOCK_RAW", SCM_MAKINUM (SOCK_RAW));
 #endif
 
   /* setsockopt level.  */
 #ifdef SOL_SOCKET
 #endif
 
   /* setsockopt level.  */
 #ifdef SOL_SOCKET
-  scm_sysintern ("SOL_SOCKET", SCM_MAKINUM (SOL_SOCKET));
+  scm_c_define ("SOL_SOCKET", SCM_MAKINUM (SOL_SOCKET));
 #endif
 #ifdef SOL_IP
 #endif
 #ifdef SOL_IP
-  scm_sysintern ("SOL_IP", SCM_MAKINUM (SOL_IP));
+  scm_c_define ("SOL_IP", SCM_MAKINUM (SOL_IP));
 #endif
 #ifdef SOL_TCP
 #endif
 #ifdef SOL_TCP
-  scm_sysintern ("SOL_TCP", SCM_MAKINUM (SOL_TCP));
+  scm_c_define ("SOL_TCP", SCM_MAKINUM (SOL_TCP));
 #endif
 #ifdef SOL_UDP
 #endif
 #ifdef SOL_UDP
-  scm_sysintern ("SOL_UDP", SCM_MAKINUM (SOL_UDP));
+  scm_c_define ("SOL_UDP", SCM_MAKINUM (SOL_UDP));
 #endif
 
   /* setsockopt names.  */
 #ifdef SO_DEBUG
 #endif
 
   /* setsockopt names.  */
 #ifdef SO_DEBUG
-  scm_sysintern ("SO_DEBUG", SCM_MAKINUM (SO_DEBUG));
+  scm_c_define ("SO_DEBUG", SCM_MAKINUM (SO_DEBUG));
 #endif
 #ifdef SO_REUSEADDR
 #endif
 #ifdef SO_REUSEADDR
-  scm_sysintern ("SO_REUSEADDR", SCM_MAKINUM (SO_REUSEADDR));
+  scm_c_define ("SO_REUSEADDR", SCM_MAKINUM (SO_REUSEADDR));
 #endif
 #ifdef SO_STYLE
 #endif
 #ifdef SO_STYLE
-  scm_sysintern ("SO_STYLE", SCM_MAKINUM (SO_STYLE));
+  scm_c_define ("SO_STYLE", SCM_MAKINUM (SO_STYLE));
 #endif
 #ifdef SO_TYPE
 #endif
 #ifdef SO_TYPE
-  scm_sysintern ("SO_TYPE", SCM_MAKINUM (SO_TYPE));
+  scm_c_define ("SO_TYPE", SCM_MAKINUM (SO_TYPE));
 #endif
 #ifdef SO_ERROR
 #endif
 #ifdef SO_ERROR
-  scm_sysintern ("SO_ERROR", SCM_MAKINUM (SO_ERROR));
+  scm_c_define ("SO_ERROR", SCM_MAKINUM (SO_ERROR));
 #endif
 #ifdef SO_DONTROUTE
 #endif
 #ifdef SO_DONTROUTE
-  scm_sysintern ("SO_DONTROUTE", SCM_MAKINUM (SO_DONTROUTE));
+  scm_c_define ("SO_DONTROUTE", SCM_MAKINUM (SO_DONTROUTE));
 #endif
 #ifdef SO_BROADCAST
 #endif
 #ifdef SO_BROADCAST
-  scm_sysintern ("SO_BROADCAST", SCM_MAKINUM (SO_BROADCAST));
+  scm_c_define ("SO_BROADCAST", SCM_MAKINUM (SO_BROADCAST));
 #endif
 #ifdef SO_SNDBUF
 #endif
 #ifdef SO_SNDBUF
-  scm_sysintern ("SO_SNDBUF", SCM_MAKINUM (SO_SNDBUF));
+  scm_c_define ("SO_SNDBUF", SCM_MAKINUM (SO_SNDBUF));
 #endif
 #ifdef SO_RCVBUF
 #endif
 #ifdef SO_RCVBUF
-  scm_sysintern ("SO_RCVBUF", SCM_MAKINUM (SO_RCVBUF));
+  scm_c_define ("SO_RCVBUF", SCM_MAKINUM (SO_RCVBUF));
 #endif
 #ifdef SO_KEEPALIVE
 #endif
 #ifdef SO_KEEPALIVE
-  scm_sysintern ("SO_KEEPALIVE", SCM_MAKINUM (SO_KEEPALIVE));
+  scm_c_define ("SO_KEEPALIVE", SCM_MAKINUM (SO_KEEPALIVE));
 #endif
 #ifdef SO_OOBINLINE
 #endif
 #ifdef SO_OOBINLINE
-  scm_sysintern ("SO_OOBINLINE", SCM_MAKINUM (SO_OOBINLINE));
+  scm_c_define ("SO_OOBINLINE", SCM_MAKINUM (SO_OOBINLINE));
 #endif
 #ifdef SO_NO_CHECK
 #endif
 #ifdef SO_NO_CHECK
-  scm_sysintern ("SO_NO_CHECK", SCM_MAKINUM (SO_NO_CHECK));
+  scm_c_define ("SO_NO_CHECK", SCM_MAKINUM (SO_NO_CHECK));
 #endif
 #ifdef SO_PRIORITY
 #endif
 #ifdef SO_PRIORITY
-  scm_sysintern ("SO_PRIORITY", SCM_MAKINUM (SO_PRIORITY));
+  scm_c_define ("SO_PRIORITY", SCM_MAKINUM (SO_PRIORITY));
 #endif
 #ifdef SO_LINGER
 #endif
 #ifdef SO_LINGER
-  scm_sysintern ("SO_LINGER", SCM_MAKINUM (SO_LINGER));
+  scm_c_define ("SO_LINGER", SCM_MAKINUM (SO_LINGER));
 #endif
 
   /* recv/send options.  */
 #ifdef MSG_OOB
 #endif
 
   /* recv/send options.  */
 #ifdef MSG_OOB
-  scm_sysintern ("MSG_OOB", SCM_MAKINUM (MSG_OOB));
+  scm_c_define ("MSG_OOB", SCM_MAKINUM (MSG_OOB));
 #endif
 #ifdef MSG_PEEK
 #endif
 #ifdef MSG_PEEK
-  scm_sysintern ("MSG_PEEK", SCM_MAKINUM (MSG_PEEK));
+  scm_c_define ("MSG_PEEK", SCM_MAKINUM (MSG_PEEK));
 #endif
 #ifdef MSG_DONTROUTE
 #endif
 #ifdef MSG_DONTROUTE
-  scm_sysintern ("MSG_DONTROUTE", SCM_MAKINUM (MSG_DONTROUTE));
+  scm_c_define ("MSG_DONTROUTE", SCM_MAKINUM (MSG_DONTROUTE));
 #endif
 
   scm_add_feature ("socket");
 #endif
 
   scm_add_feature ("socket");
-  scm_init_addr_buffer ();
 
 
+#ifndef SCM_MAGIC_SNARFER
 #include "libguile/socket.x"
 #include "libguile/socket.x"
+#endif
 }
 
 
 }