--- guile-core-20040808/libguile/socket.c	Fri Mar 15 10:23:19 2002
+++ guile-core-mod/libguile/socket.c	Tue Aug 10 20:23:56 2004
@@ -71,6 +71,9 @@
 #include <netinet/in.h>
 #include <netdb.h>
 #include <arpa/inet.h>
+#ifdef HAVE_NETINET_SCTP_H
+#include <netinet/sctp.h>
+#endif
 #endif
 
 #if defined (HAVE_UNIX_DOMAIN_SOCKETS) && !defined (SUN_LEN)
@@ -706,6 +709,7 @@
 	  scm_memory_error (proc);
 	/* 4.4BSD-style interface includes sin_len member and defines SIN_LEN,
 	   4.3BSD  does not.  */
+	memset((void *)soka, 0, sizeof(struct sockaddr_in));
 #ifdef SIN_LEN
 	soka->sin_len = sizeof (struct sockaddr_in);
 #endif
@@ -742,6 +746,7 @@
 	soka = (struct sockaddr_in6 *) malloc (sizeof (struct sockaddr_in6));
 	if (!soka)
 	  scm_memory_error (proc);
+	memset((void *)soka, 0, sizeof(struct sockaddr_in6));
 #ifdef SIN_LEN6
 	soka->sin6_len = sizeof (struct sockaddr_in6);
 #endif
@@ -1202,6 +1207,72 @@
 }
 #undef FUNC_NAME
 
+#ifdef HAVE_SCTP_RECVMSG
+
+SCM_DEFINE (scm_sctp_recvmsg, "sctp-recvmsg!", 2, 2, 0,
+            (SCM sock, SCM str, 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 value returned is a list containing:\n"
+	    "- the number of bytes read from the socket\n"
+	    "- an address object in the same form as returned by @code{accept}\n"
+	    "- the flags returned by the sctp_recvmsg call\n"
+	    "- a list containing the SID, SSN, PPID, TSN and CUM_TSN\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_sctp_recvmsg
+{
+  int rv;
+  int fd;
+  int flg;
+  char *buf;
+  int offset;
+  int cend;
+  SCM address, s_sinfo;
+  int addr_size = MAX_ADDR_SIZE;
+  char max_addr[MAX_ADDR_SIZE];
+  struct sockaddr *addr = (struct sockaddr *) max_addr;
+  struct sctp_sndrcvinfo sinfo;
+  
+  SCM_VALIDATE_OPFPORT (1, sock);
+  fd = SCM_FPORT_FDES (sock);
+  SCM_VALIDATE_SUBSTRING_SPEC_COPY (2, str, buf, 3, start, offset,
+				    4, end, cend);
+
+  addr->sa_family = AF_UNSPEC;
+  flg = 0;
+  SCM_SYSCALL (rv = sctp_recvmsg (fd, buf + offset,
+			          cend - offset,
+			          addr, &addr_size,
+			          &sinfo,
+			          &flg));
+  if (rv == -1)
+    SCM_SYSERROR;
+  if (addr->sa_family != AF_UNSPEC)
+    address = scm_addr_vector (addr, FUNC_NAME);
+  else
+    address = SCM_BOOL_F;
+
+  s_sinfo = scm_list_5(scm_ushort2num(sinfo.sinfo_stream),
+                       scm_ushort2num(sinfo.sinfo_ssn),
+                       scm_uint2num(ntohl(sinfo.sinfo_ppid)),
+                       scm_uint2num(sinfo.sinfo_tsn),
+                       scm_uint2num(sinfo.sinfo_cumtsn));
+                       
+  return scm_list_4 (SCM_MAKINUM (rv), address, SCM_MAKINUM (flg), s_sinfo); 
+}
+#undef FUNC_NAME
+
+#endif
+
 SCM_DEFINE (scm_sendto, "sendto", 4, 0, 1,
             (SCM sock, SCM message, SCM fam, SCM address, SCM args_and_flags),
 	    "Transmit the string @var{message} on the socket port\n"
@@ -1257,7 +1328,70 @@
   return SCM_MAKINUM (rv);
 }
 #undef FUNC_NAME
-
+
+#ifdef HAVE_SCTP_SENDMSG
+SCM_DEFINE (scm_sctp_sendmsg, "sctp-sendmsg", 8, 0, 1,
+            (SCM sock, SCM message, SCM ppid, SCM stream_no, SCM ttl, SCM context, SCM fam, SCM address, SCM args_and_flags),
+	    "Transmit the string @var{message} on the socket port\n"
+	    "@var{sock}.  The\n"
+	    "parameters @var{ppid}, @var{stream_no}, @var{ttl} and  @var{context}\n"
+	    "are the corresponding SCTP parameters. 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_UNORDERED, MSG_ABORT, MSG_EOF etc.\n\n"
+	    "The value returned is the number of bytes transmitted\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_sctp_sendmsg
+{
+  int rv;
+  int fd;
+  int flg;
+  struct sockaddr *soka;
+  int size;
+  uint16_t c_stream_no;
+  uint32_t c_ppid, c_ttl, c_context;
+
+  sock = SCM_COERCE_OUTPORT (sock);
+  SCM_VALIDATE_FPORT (1, sock);
+  SCM_VALIDATE_STRING (2, message);
+  c_ppid      = htonl(SCM_NUM2ULONG(3, ppid));
+  c_stream_no = SCM_NUM2USHORT(4, stream_no);
+  c_ttl       = SCM_NUM2ULONG(5, ttl);
+  c_context   = SCM_NUM2ULONG(6, context);
+  SCM_VALIDATE_INUM (7, fam);
+  fd = SCM_FPORT_FDES (sock);
+  soka = scm_fill_sockaddr (SCM_INUM (fam), address, &args_and_flags, 8, FUNC_NAME, &size);
+  if (SCM_NULLP (args_and_flags))
+    flg = 0;
+  else {
+      SCM_VALIDATE_CONS (9,args_and_flags);
+      flg = SCM_NUM2ULONG (9, SCM_CAR (args_and_flags));
+    }
+
+  SCM_SYSCALL (rv = sctp_sendmsg (fd,  SCM_STRING_CHARS (message), SCM_STRING_LENGTH (message),
+			          soka, size,
+				  c_ppid,
+				  flg,
+				  c_stream_no,
+				  c_ttl,
+				  c_context));
+  if (rv == -1) {
+      int save_errno = errno;
+      free (soka);
+      errno = save_errno;
+      SCM_SYSERROR;
+  }
+  free (soka);
+  return SCM_MAKINUM (rv);
+}
+#undef FUNC_NAME
+#endif
 
 
 void
@@ -1311,10 +1445,26 @@
 #ifdef SOCK_DGRAM
   scm_c_define ("SOCK_DGRAM", SCM_MAKINUM (SOCK_DGRAM));
 #endif
+#ifdef SOCK_SEQPACKET
+  scm_c_define ("SOCK_SEQPACKET", SCM_MAKINUM (SOCK_SEQPACKET));
+#endif
 #ifdef SOCK_RAW
   scm_c_define ("SOCK_RAW", SCM_MAKINUM (SOCK_RAW));
 #endif
 
+  /* protocol numbers */
+#ifdef IPPROTO_SCTP
+  scm_c_define ("IPPROTO_SCTP", SCM_MAKINUM (IPPROTO_SCTP));
+#endif
+
+#ifdef IPPROTO_TCP
+  scm_c_define ("IPPROTO_TCP", SCM_MAKINUM (IPPROTO_TCP));
+#endif
+
+#ifdef IPPROTO_UDP
+  scm_c_define ("IPPROTO_UDP", SCM_MAKINUM (IPPROTO_UDP));
+#endif
+
   /* setsockopt level.  */
 #ifdef SOL_SOCKET
   scm_c_define ("SOL_SOCKET", SCM_MAKINUM (SOL_SOCKET));
@@ -1382,6 +1532,30 @@
 #endif
 #ifdef MSG_DONTROUTE
   scm_c_define ("MSG_DONTROUTE", SCM_MAKINUM (MSG_DONTROUTE));
+#endif
+#ifdef MSG_UNORDERED
+  scm_c_define ("MSG_UNORDERED", SCM_MAKINUM (MSG_UNORDERED));
+#endif
+#ifdef MSG_ADDR_OVER
+  scm_c_define ("MSG_ADDR_OVER", SCM_MAKINUM (MSG_ADDR_OVER));
+#endif
+#ifdef MSG_ABORT
+  scm_c_define("MSG_ABORT", SCM_MAKINUM (MSG_ABORT));
+#endif
+#ifdef MSG_EOF
+  scm_c_define ("MSG_EOF", SCM_MAKINUM (MSG_EOF));
+#endif
+#ifdef MSG_EOR
+  scm_c_define ("MSG_EOR", SCM_MAKINUM (MSG_EOR));
+#endif
+#ifdef MSG_NOTIFICATION
+  scm_c_define ("MSG_NOTIFICATION", SCM_MAKINUM (MSG_NOTIFICATION));
+#endif
+#ifdef MSG_PR_SCTP_TTL
+  scm_c_define ("MSG_PR_SCTP_TTL", SCM_MAKINUM (MSG_PR_SCTP_TTL));
+#endif
+#ifdef MSG_PR_SCTP_BUF
+  scm_c_define ("MSG_PR_SCTP_BUF", SCM_MAKINUM (MSG_PR_SCTP_BUF));
 #endif
 
   scm_add_feature ("socket");
