chiark / gitweb /
net.lisp, sys.lisp: Merge packages.
[zone] / net.lisp
index 64c796dde7defe7bd15e5c96555b7ddaeb1ffad5..e764581e9780d96ee7fe9fdb5d5e249a2eecad8b 100644 (file)
--- a/net.lisp
+++ b/net.lisp
@@ -1,7 +1,5 @@
 ;;; -*-lisp-*-
 ;;;
 ;;; -*-lisp-*-
 ;;;
-;;; $Id$
-;;;
 ;;; Network (numbering) tools
 ;;;
 ;;; (c) 2006 Straylight/Edgeware
 ;;; Network (numbering) tools
 ;;;
 ;;; (c) 2006 Straylight/Edgeware
 ;;; it under the terms of the GNU General Public License as published by
 ;;; the Free Software Foundation; either version 2 of the License, or
 ;;; (at your option) any later version.
 ;;; it under the terms of the GNU General Public License as published by
 ;;; the Free Software Foundation; either version 2 of the License, or
 ;;; (at your option) any later version.
-;;; 
+;;;
 ;;; This program is distributed in the hope that it will be useful,
 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;;; GNU General Public License for more details.
 ;;; This program is distributed in the hope that it will be useful,
 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;;; GNU General Public License for more details.
-;;; 
+;;;
 ;;; You should have received a copy of the GNU General Public License
 ;;; along with this program; if not, write to the Free Software Foundation,
 ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 ;;; You should have received a copy of the GNU General Public License
 ;;; along with this program; if not, write to the Free Software Foundation,
 ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-;;;--------------------------------------------------------------------------
-;;; Packaging.
-
-(defpackage #:net
-  (:use #:common-lisp #:mdw.base #:mdw.str #:collect)
-  (:export #:ipaddr #:string-ipaddr #:ipaddr-byte #:ipaddr-string #:ipaddrp
-          #:integer-netmask #:ipmask #:ipmask-cidl-slash #:make-ipnet
-            #:string-ipnet #:ipnet #:ipnet-net #:ipnet-mask #:with-ipnet
-            #:ipnet-pretty #:ipnet-string #:ipnet-broadcast #:ipnet-hosts
-            #:ipnet-host #:ipaddr-networkp #:ipnet-subnetp
-            #:ipnet-changeable-bytes
-          #:host-find# #:host-create #:defhost #:parse-ipaddr
-            #:resolve-hostname #:canonify-hostname
-            #:net #:net-find #:net-get-as-ipnet #:net-create #:defnet
-            #:net-next-host #:net-host))
-
 (in-package #:net)
 
 ;;;--------------------------------------------------------------------------
 (in-package #:net)
 
 ;;;--------------------------------------------------------------------------
@@ -52,6 +34,7 @@ (deftype u32 ()
   "The type of unsigned 32-bit values."
   '(unsigned-byte 32))
 
   "The type of unsigned 32-bit values."
   '(unsigned-byte 32))
 
+(export 'ipaddr)
 (deftype ipaddr ()
   "The type of IP (version 4) addresses."
   'u32)
 (deftype ipaddr ()
   "The type of IP (version 4) addresses."
   'u32)
@@ -69,14 +52,14 @@ (defun count-low-zero-bits (n)
 ;;;--------------------------------------------------------------------------
 ;;; Simple messing with IP addresses.
 
 ;;;--------------------------------------------------------------------------
 ;;; Simple messing with IP addresses.
 
+(export 'string-ipaddr)
 (defun string-ipaddr (str &key (start 0) (end nil))
   "Parse STR as an IP address in dotted-quad form and return the integer
    equivalent.  STR may be anything at all: it's converted as if by
    `stringify'.  The START and END arguments may be used to parse out a
    substring."
   (setf str (stringify str))
 (defun string-ipaddr (str &key (start 0) (end nil))
   "Parse STR as an IP address in dotted-quad form and return the integer
    equivalent.  STR may be anything at all: it's converted as if by
    `stringify'.  The START and END arguments may be used to parse out a
    substring."
   (setf str (stringify str))
-  (unless end
-    (setf end (length str)))
+  (setf-default end (length str))
   (let ((addr 0) (noct 0))
     (loop
       (let* ((pos (position #\. str :start start :end end))
   (let ((addr 0) (noct 0))
     (loop
       (let* ((pos (position #\. str :start start :end end))
@@ -92,11 +75,13 @@ (defun string-ipaddr (str &key (start 0) (end nil))
       (error "Wrong number of octets in IP address"))
     addr))
 
       (error "Wrong number of octets in IP address"))
     addr))
 
+(export 'ipaddr-byte)
 (defun ipaddr-byte (ip n)
   "Return byte N (from most significant downwards) of an IP address."
   (assert (<= 0 n 3))
   (logand #xff (ash ip (* -8 (- 3 n)))))
 
 (defun ipaddr-byte (ip n)
   "Return byte N (from most significant downwards) of an IP address."
   (assert (<= 0 n 3))
   (logand #xff (ash ip (* -8 (- 3 n)))))
 
+(export 'ipaddr-string)
 (defun ipaddr-string (ip)
   "Transform the address IP into a string in dotted-quad form."
   (check-type ip ipaddr)
 (defun ipaddr-string (ip)
   "Transform the address IP into a string in dotted-quad form."
   (check-type ip ipaddr)
@@ -104,6 +89,7 @@ (defun ipaddr-string (ip)
                      (dotimes (i 4)
                        (collect (ipaddr-byte ip i))))))
 
                      (dotimes (i 4)
                        (collect (ipaddr-byte ip i))))))
 
+(export 'ipaddrp)
 (defun ipaddrp (ip)
   "Answer true if IP is a valid IP address in integer form."
   (typep ip 'ipaddr))
 (defun ipaddrp (ip)
   "Answer true if IP is a valid IP address in integer form."
   (typep ip 'ipaddr))
@@ -118,10 +104,12 @@ (defun ipaddr (ip)
 ;;;--------------------------------------------------------------------------
 ;;; Netmasks.
 
 ;;;--------------------------------------------------------------------------
 ;;; Netmasks.
 
+(export 'integer-netmask)
 (defun integer-netmask (i)
   "Given an integer I, return a netmask with its I top bits set."
   (- (ash 1 32) (ash 1 (- 32 i))))
 
 (defun integer-netmask (i)
   "Given an integer I, return a netmask with its I top bits set."
   (- (ash 1 32) (ash 1 (- 32 i))))
 
+(export 'ipmask)
 (defun ipmask (ip)
   "Transform IP into a netmask.  If it's a small integer then it's converted
    by `integer-netmask'; if nil, then all-bits-set; otherwise convert using
 (defun ipmask (ip)
   "Transform IP into a netmask.  If it's a small integer then it's converted
    by `integer-netmask'; if nil, then all-bits-set; otherwise convert using
@@ -131,6 +119,7 @@ (defun ipmask (ip)
     ((integer 0 32) (integer-netmask ip))
     (t (ipaddr ip))))
 
     ((integer 0 32) (integer-netmask ip))
     (t (ipaddr ip))))
 
+(export 'ipmask-cidl-slash)
 (defun ipmask-cidl-slash (mask)
   "Given a netmask MASK, return an integer N such that (integer-netmask N) =
    MASK, or nil if this is impossible."
 (defun ipmask-cidl-slash (mask)
   "Given a netmask MASK, return an integer N such that (integer-netmask N) =
    MASK, or nil if this is impossible."
@@ -141,6 +130,7 @@ (defun ipmask-cidl-slash (mask)
 ;;;--------------------------------------------------------------------------
 ;;; Networks: pairing an address and netmask.
 
 ;;;--------------------------------------------------------------------------
 ;;; Networks: pairing an address and netmask.
 
+(export 'make-ipnet)
 (defun make-ipnet (net mask)
   "Construct an IP-network object given the NET and MASK; these are
    transformed as though by `ipaddr' and `ipmask'."
 (defun make-ipnet (net mask)
   "Construct an IP-network object given the NET and MASK; these are
    transformed as though by `ipaddr' and `ipmask'."
@@ -148,10 +138,11 @@ (defun make-ipnet (net mask)
        (mask (ipmask mask)))
     (cons (logand net mask) mask)))
 
        (mask (ipmask mask)))
     (cons (logand net mask) mask)))
 
+(export 'string-ipnet)
 (defun string-ipnet (str &key (start 0) (end nil))
   "Parse an IP-network from the string STR."
   (setf str (stringify str))
 (defun string-ipnet (str &key (start 0) (end nil))
   "Parse an IP-network from the string STR."
   (setf str (stringify str))
-  (unless end (setf end (length str)))
+  (setf-default end (length str))
   (let ((sl (position #\/ str :start start :end end)))
     (if sl
        (make-ipnet (parse-ipaddr (subseq str start sl))
   (let ((sl (position #\/ str :start start :end end)))
     (if sl
        (make-ipnet (parse-ipaddr (subseq str start sl))
@@ -163,6 +154,7 @@ (defun string-ipnet (str &key (start 0) (end nil))
        (make-ipnet (parse-ipaddr (subseq str start end))
                    (integer-netmask 32)))))
 
        (make-ipnet (parse-ipaddr (subseq str start end))
                    (integer-netmask 32)))))
 
+(export 'ipnet)
 (defun ipnet (net)
   "Construct an IP-network object from the given argument.  A number of forms
    are acceptable:
 (defun ipnet (net)
   "Construct an IP-network object from the given argument.  A number of forms
    are acceptable:
@@ -174,14 +166,17 @@ (defun ipnet (net)
   (cond ((or (stringp net) (symbolp net)) (string-ipnet net))
        (t (apply #'make-ipnet (pairify net 32)))))
 
   (cond ((or (stringp net) (symbolp net)) (string-ipnet net))
        (t (apply #'make-ipnet (pairify net 32)))))
 
+(export 'ipnet-net)
 (defun ipnet-net (ipn)
   "Return the base network address of IPN."
   (car ipn))
 
 (defun ipnet-net (ipn)
   "Return the base network address of IPN."
   (car ipn))
 
+(export 'ipnet-mask)
 (defun ipnet-mask (ipn)
   "Return the netmask of IPN."
   (cdr ipn))
 
 (defun ipnet-mask (ipn)
   "Return the netmask of IPN."
   (cdr ipn))
 
+(export 'with-ipnet)
 (defmacro with-ipnet ((net mask) ipn &body body)
   "Evaluate BODY with NET and MASK bound to the base address and netmask of
    IPN.  Either NET or MASK (or, less usefully, both) may be nil if not
 (defmacro with-ipnet ((net mask) ipn &body body)
   "Evaluate BODY with NET and MASK bound to the base address and netmask of
    IPN.  Either NET or MASK (or, less usefully, both) may be nil if not
@@ -192,12 +187,14 @@ (defmacro with-ipnet ((net mask) ipn &body body)
             ,@(and mask `((,mask (ipnet-mask ,tmp)))))
         ,@body))))
 
             ,@(and mask `((,mask (ipnet-mask ,tmp)))))
         ,@body))))
 
+(export 'ipnet-pretty)
 (defun ipnet-pretty (ipn)
   "Convert IPN to a pretty cons-cell form."
   (with-ipnet (net mask) ipn
     (cons (ipaddr-string net)
          (or (ipmask-cidl-slash mask) (ipaddr-string mask)))))
 
 (defun ipnet-pretty (ipn)
   "Convert IPN to a pretty cons-cell form."
   (with-ipnet (net mask) ipn
     (cons (ipaddr-string net)
          (or (ipmask-cidl-slash mask) (ipaddr-string mask)))))
 
+(export 'ipnet-string)
 (defun ipnet-string (ipn)
   "Convert IPN to a string."
   (with-ipnet (net mask) ipn
 (defun ipnet-string (ipn)
   "Convert IPN to a string."
   (with-ipnet (net mask) ipn
@@ -205,15 +202,18 @@ (defun ipnet-string (ipn)
            (ipaddr-string net)
            (or (ipmask-cidl-slash mask) (ipaddr-string mask)))))
 
            (ipaddr-string net)
            (or (ipmask-cidl-slash mask) (ipaddr-string mask)))))
 
+(export 'ipnet-broadcast)
 (defun ipnet-broadcast (ipn)
   "Return the broadcast address for the network IPN."
   (with-ipnet (net mask) ipn
     (logior net (logxor (mask 32) mask))))
 
 (defun ipnet-broadcast (ipn)
   "Return the broadcast address for the network IPN."
   (with-ipnet (net mask) ipn
     (logior net (logxor (mask 32) mask))))
 
+(export 'ipnet-hosts)
 (defun ipnet-hosts (ipn)
   "Return the number of available addresses in network IPN."
   (ash 1 (- 32 (logcount (ipnet-mask ipn)))))
 
 (defun ipnet-hosts (ipn)
   "Return the number of available addresses in network IPN."
   (ash 1 (- 32 (logcount (ipnet-mask ipn)))))
 
+(export 'ipnet-host)
 (defun ipnet-host (ipn host)
   "Return the address of the given HOST in network IPN.  This works even with
    a non-contiguous netmask."
 (defun ipnet-host (ipn host)
   "Return the address of the given HOST in network IPN.  This works even with
    a non-contiguous netmask."
@@ -234,11 +234,13 @@ (defun ipnet-host (ipn host)
        (setf m (ash m 1))
        (incf i)))))
 
        (setf m (ash m 1))
        (incf i)))))
 
+(export 'ipaddr-networkp)
 (defun ipaddr-networkp (ip ipn)
   "Returns true if address IP is within network IPN."
   (with-ipnet (net mask) ipn
     (= net (logand ip mask))))
 
 (defun ipaddr-networkp (ip ipn)
   "Returns true if address IP is within network IPN."
   (with-ipnet (net mask) ipn
     (= net (logand ip mask))))
 
+(export 'ipnet-subnetp)
 (defun ipnet-subnetp (ipn subn)
   "Returns true if SUBN is a (non-strict) subnet of IPN."
   (with-ipnet (net mask) ipn
 (defun ipnet-subnetp (ipn subn)
   "Returns true if SUBN is a (non-strict) subnet of IPN."
   (with-ipnet (net mask) ipn
@@ -246,6 +248,7 @@ (defun ipnet-subnetp (ipn subn)
       (and (= net (logand subnet mask))
           (= submask (logior mask submask))))))
 
       (and (= net (logand subnet mask))
           (= submask (logior mask submask))))))
 
+(export 'ipnet-changeable-bytes)
 (defun ipnet-changeable-bytes (mask)
   "Answers how many low-order bytes of MASK are (entirely or partially)
    changeable.  This is used when constructing reverse zones."
 (defun ipnet-changeable-bytes (mask)
   "Answers how many low-order bytes of MASK are (entirely or partially)
    changeable.  This is used when constructing reverse zones."
@@ -253,30 +256,10 @@ (defun ipnet-changeable-bytes (mask)
     (when (/= (ipaddr-byte mask i) 255)
       (return (- 4 i)))))
 
     (when (/= (ipaddr-byte mask i) 255)
       (return (- 4 i)))))
 
-;;;--------------------------------------------------------------------------
-;;; Name resolution.
-
-(defun resolve-hostname (name)
-  "Resolve a hostname to an IP address using the DNS, or return nil."
-  #+cmu (let ((he (ext:lookup-host-entry name)))
-         (and he (ext:host-entry-addr he)))
-  #+clisp (let ((he (ext:resolve-host-ipaddr name)))
-           (and he (string-ipaddr (car (ext:hostent-addr-list he)))))
-  #+ecl (nth-value 2 (ext:lookup-host-entry name))
-  #-(or cmu clisp ecl) nil)
-
-(defun canonify-hostname (name)
-  "Resolve a hostname to canonical form using the DNS, or return nil."
-  #+cmu (let ((he (ext:lookup-host-entry name)))
-         (and he (ext:host-entry-name he)))
-  #+clisp (let ((he (ext:resolve-host-ipaddr name)))
-           (and he (ext:hostent-name he)))
-  #+ecl (nth-value 0 (ext:lookup-host-entry name))
-  #-(or cmu clisp ecl) name)
-
 ;;;--------------------------------------------------------------------------
 ;;; Host names and specifiers.
 
 ;;;--------------------------------------------------------------------------
 ;;; Host names and specifiers.
 
+(export 'parse-ipaddr)
 (defun parse-ipaddr (addr)
   "Convert the string ADDR into an IP address: tries all sorts of things:
 
 (defun parse-ipaddr (addr)
   "Convert the string ADDR into an IP address: tries all sorts of things:
 
@@ -311,18 +294,20 @@ (defun parse-ipaddr (addr)
 (defvar *hosts* (make-hash-table :test #'equal)
   "The table of known hostnames.")
 
 (defvar *hosts* (make-hash-table :test #'equal)
   "The table of known hostnames.")
 
+(export 'host-find)
 (defun host-find (name)
   "Find a host by NAME."
   (gethash (string-downcase (stringify name)) *hosts*))
 (defun host-find (name)
   "Find a host by NAME."
   (gethash (string-downcase (stringify name)) *hosts*))
-
 (defun (setf host-find) (addr name)
   "Make NAME map to ADDR (must be an ipaddr in integer form)."
   (setf (gethash (string-downcase (stringify name)) *hosts*) addr))
 
 (defun (setf host-find) (addr name)
   "Make NAME map to ADDR (must be an ipaddr in integer form)."
   (setf (gethash (string-downcase (stringify name)) *hosts*) addr))
 
+(export 'host-create)
 (defun host-create (name addr)
   "Make host NAME map to ADDR (anything acceptable to parse-ipaddr)."
   (setf (host-find name) (parse-ipaddr addr)))
 
 (defun host-create (name addr)
   "Make host NAME map to ADDR (anything acceptable to parse-ipaddr)."
   (setf (host-find name) (parse-ipaddr addr)))
 
+(export 'defhost)
 (defmacro defhost (name addr)
   "Main host definition macro.  Neither NAME nor ADDR is evaluated."
   `(progn
 (defmacro defhost (name addr)
   "Main host definition macro.  Neither NAME nor ADDR is evaluated."
   `(progn
@@ -332,6 +317,7 @@ (defmacro defhost (name addr)
 ;;;--------------------------------------------------------------------------
 ;;; Network names and specifiers.
 
 ;;;--------------------------------------------------------------------------
 ;;; Network names and specifiers.
 
+(export 'net)
 (defstruct (net (:predicate netp))
   "A network structure.  Slots:
 
 (defstruct (net (:predicate netp))
   "A network structure.  Slots:
 
@@ -347,14 +333,15 @@ (defstruct (net (:predicate netp))
 (defvar *networks* (make-hash-table :test #'equal)
   "The table of known networks.")
 
 (defvar *networks* (make-hash-table :test #'equal)
   "The table of known networks.")
 
+(export 'net-find)
 (defun net-find (name)
   "Find a network by NAME."
   (gethash (string-downcase (stringify name)) *networks*))
 (defun net-find (name)
   "Find a network by NAME."
   (gethash (string-downcase (stringify name)) *networks*))
-
 (defun (setf net-find) (net name)
   "Make NAME map to NET."
   (setf (gethash (string-downcase (stringify name)) *networks*) net))
 
 (defun (setf net-find) (net name)
   "Make NAME map to NET."
   (setf (gethash (string-downcase (stringify name)) *networks*) net))
 
+(export 'net-get-as-ipnet)
 (defun net-get-as-ipnet (form)
   "Transform FORM into an ipnet.  FORM may be a network name, or something
 acceptable to the ipnet function."
 (defun net-get-as-ipnet (form)
   "Transform FORM into an ipnet.  FORM may be a network name, or something
 acceptable to the ipnet function."
@@ -390,6 +377,7 @@ (defun process-net-form (root addr subnets)
        (cons (list root net mask)
              (frob subnets (+ net (ipnet-hosts ipn) 1) net))))))
 
        (cons (list root net mask)
              (frob subnets (+ net (ipnet-hosts ipn) 1) net))))))
 
+(export 'net-create)
 (defun net-create (name net)
   "Construct a new network called NAME and add it to the map.  The ARGS
    describe the new network, in a form acceptable to the ipnet function."
 (defun net-create (name net)
   "Construct a new network called NAME and add it to the map.  The ARGS
    describe the new network, in a form acceptable to the ipnet function."
@@ -400,6 +388,7 @@ (defun net-create (name net)
                    :hosts (ipnet-hosts ipn)
                    :next 1))))
 
                    :hosts (ipnet-hosts ipn)
                    :next 1))))
 
+(export 'defnet)
 (defmacro defnet (name net &rest subnets)
   "Main network definition macro.  None of the arguments is evaluated."
   `(progn
 (defmacro defnet (name net &rest subnets)
   "Main network definition macro.  None of the arguments is evaluated."
   `(progn
@@ -407,6 +396,7 @@ (defmacro defnet (name net &rest subnets)
            collect `(net-create ',name '(,addr . ,mask)))
     ',name))
 
            collect `(net-create ',name '(,addr . ,mask)))
     ',name))
 
+(export 'net-next-host)
 (defun net-next-host (net)
   "Given a NET, return the IP address (as integer) of the next available
    address in the network."
 (defun net-next-host (net)
   "Given a NET, return the IP address (as integer) of the next available
    address in the network."
@@ -416,6 +406,7 @@ (defun net-next-host (net)
     (incf (net-next net))
     (net-host net next)))
 
     (incf (net-next net))
     (net-host net next)))
 
+(export 'net-host)
 (defun net-host (net host)
   "Return the given HOST on the NEXT.  HOST may be an index (in range, of
    course), or one of the keywords:
 (defun net-host (net host)
   "Return the given HOST on the NEXT.  HOST may be an index (in range, of
    course), or one of the keywords: