summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2016-02-29 20:54:34 -0800
committerKaz Kylheku <kaz@kylheku.com>2016-02-29 20:54:34 -0800
commit26a58a0d7fc48b9e609808593c830d74b15750b5 (patch)
tree9102f9c0b0175da784e62ee8cdadb56b7cf906a6 /share
parentd50725ab1a9055fd3f0c83c90c9fb71bfd16c205 (diff)
downloadtxr-26a58a0d7fc48b9e609808593c830d74b15750b5.tar.gz
txr-26a58a0d7fc48b9e609808593c830d74b15750b5.tar.bz2
txr-26a58a0d7fc48b9e609808593c830d74b15750b5.zip
Functions for address prefixes to slash notation.
* lisplib.c (sock_set_entries): Autload entries for str-inaddr-net and str-in6addr-net. * share/txr/stdlib/socket.tl (str-inaddr-net, str-in6addr-net): New functions. * txr.1: Documented str-inaddr, str-in6-addr, str-inaddr-net and str-in6addr-net.
Diffstat (limited to 'share')
-rw-r--r--share/txr/stdlib/socket.tl60
1 files changed, 60 insertions, 0 deletions
diff --git a/share/txr/stdlib/socket.tl b/share/txr/stdlib/socket.tl
index cb9fd23d..0898a491 100644
--- a/share/txr/stdlib/socket.tl
+++ b/share/txr/stdlib/socket.tl
@@ -82,3 +82,63 @@
(if port
`[@str]:@port`
str)))
+
+(defun sys:str-inaddr-net-impl (addr wextra)
+ (let ((mask addr))
+ (set mask (logior mask (ash mask 1)))
+ (set mask (logior mask (ash mask 2)))
+ (set mask (logior mask (ash mask 4)))
+ (set mask (logior mask (ash mask 8)))
+ (set mask (logior mask (ash mask 16)))
+ (let ((w (+ (- 32 (width (lognot mask 32))) wextra))
+ (d (logand addr #xFF))
+ (c (logand (ash addr -8) #xFF))
+ (b (logand (ash addr -16) #xFF))
+ (a (ash addr -24)))
+ (cond
+ ((or (> a 255) (minusp a))
+ (throwf 'eval-error "str-inaddr-net: ~a out of range for IPv4 address"
+ addr))
+ ((> w 24) `@a.@b.@c.@d/@w`)
+ ((> w 16) `@a.@b.@c/@w`)
+ ((> w 8) `@a.@b/@w`)
+ (t `@a/@w`)))))
+
+(defun str-inaddr-net (addr)
+ (sys:str-inaddr-net-impl addr 0))
+
+(defun str-in6addr-net (addr)
+ (if (and (<= (width addr) 48)
+ (= (ash addr -32) #xFFFF))
+ `::ffff:@(sys:str-inaddr-net-impl (logtrunc addr 32) 96)`
+ (let ((mask addr))
+ (set mask (logior mask (ash mask 1)))
+ (set mask (logior mask (ash mask 2)))
+ (set mask (logior mask (ash mask 4)))
+ (set mask (logior mask (ash mask 8)))
+ (set mask (logior mask (ash mask 16)))
+ (set mask (logior mask (ash mask 32)))
+ (set mask (logior mask (ash mask 64)))
+ (let* ((w (- 128 (width (lognot mask 128))))
+ (pieces (let ((count 8))
+ (nexpand-left (lambda (val)
+ (if (minusp (dec count))
+ (unless (zerop val)
+ (throwf 'eval-error
+ "str-in6addr-net: \
+ \ ~a out of range \
+ \ for IPv6 address"
+ addr))
+ (cons (logand val #xFFFF)
+ (ash val -16))))
+ addr)))
+ (cand-prefix [pieces 0..(trunc (+ w 15) 16)])
+ (prefix (if (search cand-prefix '(0 0)) pieces cand-prefix))
+ (notyet t)
+ (texts (append-each ((chunk [partition-by zerop prefix]))
+ (cond
+ ((and notyet (zerop (car chunk)) (cdr chunk))
+ (zap notyet)
+ '(":"))
+ (t (mapcar (op format nil "~x") chunk))))))
+ `@{texts ":"}/@w`))))