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