Hi.

On Mon, 2013-06-24 at 15:20 +0800, Chun Tian (binghe) wrote:

> 4. Write patches for SBCL and CCL to support IPv6 directly on their exist 
> network interfaces. The purpose is to make unmodified SBCL/CCL working 
> directly with my patches to get the ability to support IPv6 with their exist 
> interfaces. Platforms with such modifications should have :usocket-ipv6 in 
> their *features*.

I once started to write the attached patch for SBCL but then heard some
talk about replacing SBCL's stream machinery with iolib and stopped
working on that (not sure whether I remember "hearing" that correctly).

But anyway, maybe you have some use for the patch. I managed creating
IPv6 connections with it, but the patch is obviously far from finished.
It may contain little code fragments from iolib.

Kind regards,
Jan
>From 437e45f8d084d7c05dd5c6ed83f1bf6ebf4eb747 Mon Sep 17 00:00:00 2001
From: Jan Moringen <jmori...@techfak.uni-bielefeld.de>
Date: Sun, 3 Mar 2013 20:14:47 +0100
Subject: [PATCH] TODO temp commit

---
 contrib/sb-bsd-sockets/constants.lisp     |   14 ++++
 contrib/sb-bsd-sockets/inet6.lisp         |  103 +++++++++++++++++++++++++++++
 contrib/sb-bsd-sockets/sb-bsd-sockets.asd |    1 +
 contrib/sb-bsd-sockets/sockets.lisp       |   10 +--
 4 files changed, 123 insertions(+), 5 deletions(-)
 create mode 100644 contrib/sb-bsd-sockets/inet6.lisp

diff --git a/contrib/sb-bsd-sockets/constants.lisp b/contrib/sb-bsd-sockets/constants.lisp
index eeabd11..e149c49 100644
--- a/contrib/sb-bsd-sockets/constants.lisp
+++ b/contrib/sb-bsd-sockets/constants.lisp
@@ -165,6 +165,20 @@
                           ;; of the old sb-grovel scheme.
                           ((array (unsigned 8)) port "u_int16_t" "sin_port")
                           ((array (unsigned 8)) addr "struct in_addr" "sin_addr")))
+ (:structure in6-addr ("struct in6_addr"
+                       ((array (unsigned 8)) addr "unsigned char" "s6_addr[16]")))
+ (:structure sockaddr-in6 ("struct sockaddr_in6"
+                          #+darwin ((unsigned 8) len "__uint8_t" "sin_len")
+                          (integer family "sa_family_t" "sin6_family")
+                          ;; These two could be in-port-t and
+                          ;; in-addr-t, but then we'd throw away the
+                          ;; convenience (and byte-order agnosticism)
+                          ;; of the old sb-grovel scheme.
+                          ((array (unsigned 8)) port "u_int16_t" "sin6_port")
+                          ((array (unsigned 8)) flowinfo "u_int32_t" "sin6_flowinfo")
+
+                          ((array (unsigned 8)) addr "struct in_addr6" "sin6_addr")
+                          ((array (unsigned 8)) scope-id "u_int32_t" "sin6_scope_id")))
  (:structure sockaddr-un ("struct sockaddr_un"
                           (integer family "sa_family_t" "sun_family")
                           (c-string path "char" "sun_path")))
diff --git a/contrib/sb-bsd-sockets/inet6.lisp b/contrib/sb-bsd-sockets/inet6.lisp
new file mode 100644
index 0000000..a31a877
--- /dev/null
+++ b/contrib/sb-bsd-sockets/inet6.lisp
@@ -0,0 +1,103 @@
+(in-package :sb-bsd-sockets)
+
+;;; Our class and constructor
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (defclass inet6-socket (socket)
+    ((family :initform sockint::AF-INET6))
+    (:documentation "Class representing TCP and UDP over IPv6 sockets.
+
+Examples:
+
+ (make-instance 'inet-socket6 :type :stream :protocol :tcp)
+
+ (make-instance 'inet-socket6 :type :datagram :protocol :udp)
+")))
+
+;;; XXX should we *...* this?
+(defparameter inet6-address-any (vector 0 0 0 0))
+
+(defmethod socket-namestring ((socket inet6-socket))
+  (ignore-errors
+   (multiple-value-bind (addr port) (socket-name socket)
+     (let ((numbers
+             (loop for i from 0 below 8 by 2
+                   collect
+                      (let ((number (+ (* 256 (aref addr i))
+                                       (aref addr (1+ i)))))
+                        (unless (zerop number)
+                          number)))))
+       (format nil "~{~@[~(~X~)~]~^:~}:~A" numbers port)))))
+
+(defmethod socket-peerstring ((socket inet6-socket))
+  (ignore-errors
+   (multiple-value-bind (addr port) (socket-peername socket)
+     (let ((numbers
+             (loop for i from 0 below 8 by 2
+                   collect
+                      (let ((number (+ (* 256 (aref addr i))
+                                       (aref addr (1+ i)))))
+                        (unless (zerop number)
+                          number)))))
+       (format nil "~{~@[~(~X~)~]~^:~}:~A" numbers port)))))
+
+;;; binding a socket to an address and port.  Doubt that anyone's
+;;; actually using this much, to be honest.
+
+(defun make-inet6-address (colon-separated-integers)
+  "Return a vector of octets given a TODO. Signals an error if the string is malformed."
+  (declare (type string colon-separated-integers))
+  (let ((address (make-array 16 :element-type '(unsigned-byte 8)))
+        (i 0))
+    (dolist (component (split colon-separated-integers 8 '(#\:)))
+      (multiple-value-bind (high low)
+          (floor (parse-integer component :radix 16) 256)
+        (check-type high (unsigned-byte 8) #+maybe octet)
+        (check-type low  (unsigned-byte 8) #+maybe octet)
+        (setf (aref address i)      high
+              (aref address (1+ i)) low)
+        (incf i 2)))
+    address))
+
+;;; our protocol provides make-sockaddr-for, size-of-sockaddr,
+;;; bits-of-sockaddr
+
+(defmethod make-sockaddr-for ((socket inet6-socket) &optional sockaddr &rest address &aux (host (first address)) (port (second address)))
+  (let ((sockaddr (or sockaddr (sockint::allocate-sockaddr-in6))))
+    (when (and host port)
+      (setf host (coerce host '(simple-array (unsigned-byte 8) (16))))
+      ;; port and host are represented in C as "network-endian" unsigned
+      ;; integers of various lengths.  This is stupid.  The value of the
+      ;; integer doesn't matter (and will change depending on your
+      ;; machine's endianness); what the bind(2) call is interested in
+      ;; is the pattern of bytes within that integer.
+
+      ;; We have no truck with such dreadful type punning.  Octets to
+      ;; octets, dust to dust.
+
+      (setf (sockint::sockaddr-in6-family sockaddr) sockint::af-inet6)
+      (setf (sb-alien:deref (sockint::sockaddr-in6-port sockaddr) 0) (ldb (byte 8 8) port))
+      (setf (sb-alien:deref (sockint::sockaddr-in6-port sockaddr) 1) (ldb (byte 8 0) port))
+      (dotimes (i 4)
+        (setf (sb-alien:deref (sockint::sockaddr-in6-flowinfo sockaddr) i) 0))
+
+      (dotimes (i 16)
+        (setf (sb-alien:deref (sockint::sockaddr-in6-addr sockaddr) i) (elt host i)))
+      (dotimes (i 4)
+        (setf (sb-alien:deref (sockint::sockaddr-in6-scope-id sockaddr) i) 0)))
+    sockaddr))
+
+(defmethod free-sockaddr-for ((socket inet6-socket) sockaddr)
+  (sockint::free-sockaddr-in6 sockaddr))
+
+(defmethod size-of-sockaddr ((socket inet6-socket))
+  sockint::size-of-sockaddr-in6)
+
+(defmethod bits-of-sockaddr ((socket inet6-socket) sockaddr)
+  "Returns address and port of SOCKADDR as multiple values"
+  (values
+   (coerce (loop for i from 0 below 16
+                 collect (sb-alien:deref (sockint::sockaddr-in6-addr sockaddr) i))
+           '(vector (unsigned-byte 8) 16))
+   (+ (* 256 (sb-alien:deref (sockint::sockaddr-in6-port sockaddr) 0))
+      (sb-alien:deref (sockint::sockaddr-in6-port sockaddr) 1))))
diff --git a/contrib/sb-bsd-sockets/sb-bsd-sockets.asd b/contrib/sb-bsd-sockets/sb-bsd-sockets.asd
index e17fc63..69c39c4 100644
--- a/contrib/sb-bsd-sockets/sb-bsd-sockets.asd
+++ b/contrib/sb-bsd-sockets/sb-bsd-sockets.asd
@@ -30,6 +30,7 @@
                                     #+win32 ("win32-sockets"))
                  (:file "sockopt" :depends-on ("sockets"))
                  (:file "inet" :depends-on ("sockets" "split"))
+                 (:file "inet6" :depends-on ("sockets" "split"))
                  (:file "local" :depends-on ("sockets" "split"))
                  (:file "name-service" :depends-on ("sockets"))
                  (:file "misc" :depends-on ("sockets"))
diff --git a/contrib/sb-bsd-sockets/sockets.lisp b/contrib/sb-bsd-sockets/sockets.lisp
index 146d32b..fc6fe63 100644
--- a/contrib/sb-bsd-sockets/sockets.lisp
+++ b/contrib/sb-bsd-sockets/sockets.lisp
@@ -137,11 +137,11 @@ values"))
 
 (defmethod socket-connect ((socket socket) &rest peer)
   (with-sockaddr-for (socket sockaddr peer)
-    (if (= (sockint::connect (socket-file-descriptor socket)
-                             sockaddr
-                             (size-of-sockaddr socket))
-           -1)
-        (socket-error "connect"))))
+    (when (= (sockint::connect (socket-file-descriptor socket)
+                               sockaddr
+                               (size-of-sockaddr socket))
+             -1)
+      (socket-error "connect"))))
 
 (defgeneric socket-peername (socket)
   (:documentation "Return the socket's peer; depending on the address
-- 
1.7.10.4

Reply via email to