X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/zone/blobdiff_plain/9c44003b8aa3a1a03d6f92c16ec782b13e61249a..d41530734b268fb5396c5bf9b39f141408922026:/zone.lisp diff --git a/zone.lisp b/zone.lisp index 91f2386..35e6f80 100644 --- a/zone.lisp +++ b/zone.lisp @@ -27,7 +27,7 @@ ;;; Packaging. (defpackage #:zone - (:use #:common-lisp #:mdw.base #:mdw.str #:mdw.collect #:safely #:net) + (:use #:common-lisp #:mdw.base #:mdw.str #:collect #:safely #:net) (:export #:soa #:mx #:zone #:zone-record #:zone-subdomain #:*default-zone-source* #:*default-zone-refresh* #:*default-zone-retry* #:*default-zone-expire* @@ -49,7 +49,7 @@ (defun to-integer (x) (defun from-mixed-base (base val) "BASE is a list of the ranges for the `digits' of a mixed-base -representation. Convert VAL, a list of digits, into an integer." + representation. Convert VAL, a list of digits, into an integer." (do ((base base (cdr base)) (val (cdr val) (cdr val)) (a (car val) (+ (* a (car base)) (car val)))) @@ -57,7 +57,7 @@ (defun from-mixed-base (base val) (defun to-mixed-base (base val) "BASE is a list of the ranges for the `digits' of a mixed-base -representation. Convert VAL, an integer, into a list of digits." + representation. Convert VAL, an integer, into a list of digits." (let ((base (reverse base)) (a nil)) (loop @@ -70,8 +70,8 @@ (defun to-mixed-base (base val) (defun timespec-seconds (ts) "Convert a timespec TS to seconds. A timespec may be a real count of -seconds, or a list (COUNT UNIT): UNIT may be any of a number of obvious time -units." + seconds, or a list (COUNT UNIT): UNIT may be any of a number of obvious + time units." (cond ((null ts) 0) ((realp ts) (floor ts)) ((atom ts) @@ -99,9 +99,9 @@ (defun hash-table-keys (ht) (defun iso-date (&optional time &key datep timep (sep #\ )) "Construct a textual date or time in ISO format. The TIME is the universal -time to convert, which defaults to now; DATEP is whether to emit the date; -TIMEP is whether to emit the time, and SEP (default is space) is how to -separate the two." + time to convert, which defaults to now; DATEP is whether to emit the date; + TIMEP is whether to emit the time, and SEP (default is space) is how to + separate the two." (multiple-value-bind (sec min hr day mon yr dow dstp tz) (decode-universal-time (if (or (null time) (eq time :now)) @@ -175,7 +175,7 @@ (defvar *default-mx-priority* 50 (defun make-zone-serial (name) "Given a zone NAME, come up with a new serial number. This will (very -carefully) update a file ZONE.serial in the current directory." + carefully) update a file ZONE.serial in the current directory." (let* ((file (format nil "~(~A~).serial" name)) (last (with-open-file (in file :direction :input @@ -223,7 +223,7 @@ (defsubp nil) (defstruct (zone-subdomain (:conc-name zs-)) "A subdomain. Slightly weird. Used internally by zone-process-records -below, and shouldn't escape." + below, and shouldn't escape." name ttl records) @@ -233,7 +233,7 @@ (defstruct (zone-subdomain (:conc-name zs-)) (defun zone-process-records (rec ttl func) "Sort out the list of records in REC, calling FUNC for each one. TTL is -the default time-to-live for records which don't specify one." + the default time-to-live for records which don't specify one." (labels ((sift (rec ttl) (collecting (top sub) (loop @@ -283,7 +283,7 @@ (defun zone-process-records (rec ttl func) (defun zone-parse-host (f zname) "Parse a host name F: if F ends in a dot then it's considered absolute; -otherwise it's relative to ZNAME." + otherwise it's relative to ZNAME." (setf f (stringify f)) (cond ((string= f "@") (stringify zname)) ((and (plusp (length f)) @@ -293,7 +293,7 @@ (defun zone-parse-host (f zname) (stringify zname)))))) (defun default-rev-zone (base bytes) "Return the default reverse-zone name for the given BASE address and number -of fixed leading BYTES." + of fixed leading BYTES." (join-strings #\. (collecting () (loop for i from (- 3 bytes) downto 0 do (collect (ipaddr-byte base i))) @@ -301,7 +301,7 @@ (defun default-rev-zone (base bytes) (defun zone-name-from-net (net &optional bytes) "Given a NET, and maybe the BYTES to use, convert to the appropriate -subdomain of in-addr.arpa." + subdomain of in-addr.arpa." (let ((ipn (net-get-as-ipnet net))) (with-ipnet (net mask) ipn (unless bytes @@ -341,8 +341,8 @@ (defun zone-net-from-name (name) (defun zone-reverse-records (records net list bytes dom) "Construct a reverse zone given a forward zone's RECORDS list, the NET that -the reverse zone is to serve, a LIST to collect the records into, how -many BYTES of data need to end up in the zone, and the DOM-ain suffix." + the reverse zone is to serve, a LIST to collect the records into, how many + BYTES of data need to end up in the zone, and the DOM-ain suffix." (dolist (zr records) (when (and (eq (zr-type zr) :a) (not (zr-defsubp zr)) @@ -363,7 +363,7 @@ (defun zone-reverse-records (records net list bytes dom) (defun zone-reverse (data name list) "Process a :reverse record's DATA, for a domain called NAME, and add the -records to the LIST." + records to the LIST." (destructuring-bind (net &key bytes zones) (listify data) @@ -378,15 +378,15 @@ (defun zone-reverse (data name list) name)))) (defun zone-parse-net (net name) - "Given a NET, and the NAME of a domain to guess from if NET is null, -return the ipnet for the network." + "Given a NET, and the NAME of a domain to guess from if NET is null, return + the ipnet for the network." (if net (net-get-as-ipnet net) (zone-net-from-name name))) (defun zone-cidr-delg-default-name (ipn bytes) "Given a delegated net IPN and the parent's number of changing BYTES, -return the default deletate zone prefix." + return the default deletate zone prefix." (with-ipnet (net mask) ipn (join-strings #\. (reverse @@ -397,7 +397,7 @@ (defun zone-cidr-delg-default-name (ipn bytes) (defun zone-cidr-delegation (data name ttl list) "Given :cidr-delegation info DATA, for a record called NAME and the current -TTL, write lots of CNAME records to LIST." + TTL, write lots of CNAME records to LIST." (destructuring-bind (net &key bytes) (listify (car data)) @@ -444,8 +444,8 @@ (defun zone-parse-head (head) (NAME &key :source :admin :refresh :retry :expire :min-ttl :ttl :serial) -though a singleton NAME needn't be a list. Returns the default TTL and an -soa structure representing the zone head." + though a singleton NAME needn't be a list. Returns the default TTL and an + soa structure representing the zone head." (destructuring-bind (zname &key @@ -475,52 +475,56 @@ (defmacro defzoneparse (types (name data list (defsubp (gensym "DEFSUBP"))) &body body) "Define a new zone record type (or TYPES -- a list of synonyms is -permitted). The arguments are as follows: + permitted). The arguments are as follows: -NAME The name of the record to be added. + NAME The name of the record to be added. -DATA The content of the record to be added (a single object, unevaluated). + DATA The content of the record to be added (a single object, + unevaluated). -LIST A function to add a record to the zone. See below. + LIST A function to add a record to the zone. See below. -ZNAME The name of the zone being constructed. + ZNAME The name of the zone being constructed. -TTL The TTL for this record. + TTL The TTL for this record. -DEFSUBP Whether this is the default subdomain for this entry. + DEFSUBP Whether this is the default subdomain for this entry. -You get to choose your own names for these. ZNAME, TTL and DEFSUBP are -optional: you don't have to accept them if you're not interested. + You get to choose your own names for these. ZNAME, TTL and DEFSUBP are + optional: you don't have to accept them if you're not interested. -The LIST argument names a function to be bound in the body to add a new -low-level record to the zone. It has the prototype + The LIST argument names a function to be bound in the body to add a new + low-level record to the zone. It has the prototype - (LIST &key :name :type :data :ttl :defsubp) + (LIST &key :name :type :data :ttl :defsubp) -Except for defsubp, these default to the above arguments (even if you didn't -accept the arguments)." + Except for defsubp, these default to the above arguments (even if you + didn't accept the arguments)." (setf types (listify types)) (let* ((type (car types)) (func (intern (format nil "ZONE-PARSE/~:@(~A~)" type)))) - (with-gensyms (col tname ttype tttl tdata tdefsubp i) - `(progn - (dolist (,i ',types) - (setf (get ,i 'zone-parse) ',func)) - (defun ,func (,name ,data ,ttl ,col ,zname ,defsubp) - (declare (ignorable ,zname ,defsubp)) - (flet ((,list (&key ((:name ,tname) ,name) - ((:type ,ttype) ,type) - ((:data ,tdata) ,data) - ((:ttl ,tttl) ,ttl) - ((:defsubp ,tdefsubp) nil)) - (collect (make-zone-record :name ,tname - :type ,ttype - :data ,tdata - :ttl ,tttl - :defsubp ,tdefsubp) - ,col))) - ,@body)) - ',type)))) + (multiple-value-bind (doc decls body) (parse-body body) + (with-gensyms (col tname ttype tttl tdata tdefsubp i) + `(progn + (dolist (,i ',types) + (setf (get ,i 'zone-parse) ',func)) + (defun ,func (,name ,data ,ttl ,col ,zname ,defsubp) + ,@doc + ,@decls + (declare (ignorable ,zname ,defsubp)) + (flet ((,list (&key ((:name ,tname) ,name) + ((:type ,ttype) ,type) + ((:data ,tdata) ,data) + ((:ttl ,tttl) ,ttl) + ((:defsubp ,tdefsubp) nil)) + (collect (make-zone-record :name ,tname + :type ,ttype + :data ,tdata + :ttl ,tttl + :defsubp ,tdefsubp) + ,col))) + ,@body)) + ',type))))) (defun zone-parse-records (zone records) (let ((zname (zone-name zone))) @@ -554,12 +558,12 @@ (defun zone-parse-records (zone records) (defun zone-parse (zf) "Parse a ZONE form. The syntax of a zone form is as follows: -ZONE-FORM: - ZONE-HEAD ZONE-RECORD* + ZONE-FORM: + ZONE-HEAD ZONE-RECORD* -ZONE-RECORD: - ((NAME*) ZONE-RECORD*) -| SYM ARGS" + ZONE-RECORD: + ((NAME*) ZONE-RECORD*) + | SYM ARGS" (multiple-value-bind (zname ttl soa) (zone-parse-head (car zf)) (let ((zone (make-zone :name zname :default-ttl ttl @@ -570,7 +574,7 @@ (defun zone-parse (zf) (defun zone-create (zf) "Zone construction function. Given a zone form ZF, construct the zone and -add it to the table." + add it to the table." (let* ((zone (zone-parse zf)) (name (zone-name zone))) (setf (zone-find name) zone) @@ -792,7 +796,7 @@ (defun zone-write (zone &optional (stream *standard-output*)) (defun zone-save (zones) "Write the named ZONES to files. If no zones are given, write all the -zones." + zones." (unless zones (setf zones (hash-table-keys *zones*))) (safely (safe)