addr-family-ipv6.lisp (ipaddr-string): Use IPv4 notation if appropriate.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 22 Apr 2014 13:12:48 +0000 (14:12 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 22 Apr 2014 13:35:21 +0000 (14:35 +0100)
This supports the v4-mapped range ::ffff:0.0.0.0/96, and the deprecated
v4-compatible range ::0.0.0.0/96 (with an exception for ::0/112 so that
the magic addresses ::1 and :: still comes out OK).  The output
behaviour here seems to match Linux's inet_ntop(3).

addr-family-ipv6.lisp

index 4bec06c..e9dd1aa 100644 (file)
 
     ;; Third step: output the two parts of the address either side of the
     ;; longest zero run.  If there are no zero words in the address, just
-    ;; write the whole thing.
+    ;; write the whole thing.  There's a special case here for the
+    ;; IPv6-mapped IPv4 address space ::ffff:0.0.0.0/96.
     (with-output-to-string (out)
       (flet ((chunk (start end)
               (when (< start end)
                     (write-char #\: out))))))
        (cond ((null best-start)
               (chunk 0 8))
+             ((and (= best-start 0)
+                   (or (and (= best-length 5)
+                            (= (aref words 5) #xffff))
+                       (= best-length 6)))
+              (let ((v4addr (make-instance 'ip4addr
+                                           :addr (ldb (byte 32 0) addr))))
+                (write-string "::" out)
+                (when (= best-length 5)
+                  (chunk 5 6)
+                  (write-char #\: out))
+                (write-string (ipaddr-string v4addr) out)))
              (t
               (chunk 0 best-start)
               (write-string "::" out)