Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

preparing for a real 0.0.1 release

  • Loading branch information...
commit d2ababf0ae41a38c2d63fe1eaf108f5576413229 1 parent 37c5fb1
Bryan Weber authored
Showing with 144 additions and 91 deletions.
  1. +124 −79 docs/uberdoc.html
  2. +20 −12 src/clj_dns/core.clj
View
203 docs/uberdoc.html
@@ -3029,50 +3029,100 @@
};
})(SyntaxHighlighter);
</script><title>com.brweber2/clj-dns -- Marginalia</title></head><body><table><tr><td class="docs"><div class="header"><h1 class="project-name">com.brweber2/clj-dns</h1><h2 class="project-version">0.0.1-SNAPSHOT</h2><br /><p>Clojure wrapper library for <a href="http://www.xbill.org/dnsjava">dnsjava</a></p>
-</div><div class="dependencies"><h3>dependencies</h3><table><tr><td class="dep-name">org.clojure/clojure</td><td class="dotted"><hr /></td><td class="dep-version">1.4.0</td></tr><tr><td class="dep-name">dnsjava/dnsjava</td><td class="dotted"><hr /></td><td class="dep-version">2.1.1</td></tr></table></div><div class="dependencies"><h3>dev dependencies</h3><table><tr><td class="dep-name">lein-marginalia</td><td class="dotted"><hr /></td><td class="dep-version">0.7.0</td></tr></table></div></td><td class="codes" style="text-align: center; vertical-align: middle;color: #666;padding-right:20px"><br /><br /><br />(this space intentionally left almost blank)</td></tr><tr><td class="docs"><div class="toc"><a name="toc"><h3>namespaces</h3></a><ul><li><a href="#clj-dns.core">clj-dns.core</a></li></ul></div></td><td class="codes">&nbsp;</td></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#clj-dns.core" name="clj-dns.core"><h1 class="project-name">clj-dns.core</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
+</div><div class="dependencies"><h3>dependencies</h3><table><tr><td class="dep-name">org.clojure/clojure</td><td class="dotted"><hr /></td><td class="dep-version">1.3.0</td></tr><tr><td class="dep-name">dnsjava/dnsjava</td><td class="dotted"><hr /></td><td class="dep-version">2.1.1</td></tr></table></div><div class="dependencies"><h3>dev dependencies</h3><table><tr><td class="dep-name">lein-marginalia</td><td class="dotted"><hr /></td><td class="dep-version">0.7.0</td></tr></table></div></td><td class="codes" style="text-align: center; vertical-align: middle;color: #666;padding-right:20px"><br /><br /><br />(this space intentionally left almost blank)</td></tr><tr><td class="docs"><div class="toc"><a name="toc"><h3>namespaces</h3></a><ul><li><a href="#clj-dns.core">clj-dns.core</a></li></ul></div></td><td class="codes">&nbsp;</td></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#clj-dns.core" name="clj-dns.core"><h1 class="project-name">clj-dns.core</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns clj-dns.core
(:import (org.xbill.DNS Name Zone Record Type Master DClass Address SOARecord NSRecord DSRecord CNAMERecord TXTRecord ARecord AAAARecord MXRecord PTRRecord))
(:import lookup)
(:import dig)
(:import java.io.File)
(:import java.util.List)
- (:import clojure.lang.ISeq))</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn todo [] (throw (RuntimeException. &quot;Not yet implemented!&quot;)))
-(declare to-name)
-(declare to-filename-string)
-(declare to-inet-address)
-(declare rr-has?)
-(declare to-list)
-(declare dummy-soa)
-(declare dummy-ns)
-(declare add-rrs)
-(declare rrs-from-zone)</pre></td></tr><tr><td class="docs"><h3>Default values</h3>
-</td><td class="codes"><pre class="brush: clojure">(def soa-defaults {})
-(def default-ttl 86400)
-(def default-dclass DClass/IN)
-(def rr-defaults {:ttl default-ttl :dclass default-dclass})</pre></td></tr><tr><td class="docs"><h2>Common DNS tasks</h2>
-</td><td class="codes"></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn dns-lookup [&amp; to-lookups] (lookup/main (into-array String to-lookups)))
-(defn dns-lookup-by-type [rr-type &amp; to-lookups] (lookup/main (into-array String (into [&quot;-t&quot; rr-type] to-lookups))))</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn convert-dig-options
+ (:import clojure.lang.ISeq))</pre></td></tr><tr><td class="docs"><h2>Default values (used for creating resource records)</h2>
+</td><td class="codes"></td></tr><tr><td class="docs"><p>special defaults for SOA records</p>
+</td><td class="codes"><pre class="brush: clojure">(def soa-defaults {
+ :refresh 1800 ; 30 minutes
+ :retry 900 ; 15 minutes
+ :expire 691200 ; 1 week 1 day
+ :minimum 10800 ; 3 hours
+ })</pre></td></tr><tr><td class="docs"><p>TTL is time-to-live</p>
+</td><td class="codes"><pre class="brush: clojure">(def dflt-ttl 86400) ; 1 day</pre></td></tr><tr><td class="docs"><p>IN is for Internet. I can almost guarantee this is what you want :)</p>
+</td><td class="codes"><pre class="brush: clojure">(def dflt-dclass DClass/IN)</pre></td></tr><tr><td class="docs"><p>Map of default values for resource record creation (making these optional parameters essentially)</p>
+</td><td class="codes"><pre class="brush: clojure">(def rr-defaults {:ttl dflt-ttl :dclass dflt-dclass})</pre></td></tr><tr><td class="docs"><h2>Helper functions (todo protocol better for the instance? cases...?)</h2>
+</td><td class="codes"></td></tr><tr><td class="docs"><p>Convert a string, keyword or symbol to a java.net.InetAddress</p>
+</td><td class="codes"><pre class="brush: clojure">(defn to-inet-address [a] (Address/getByName (name a)))</pre></td></tr><tr><td class="docs"><p>Convert a single element, clojure.lang.ISeq or java.util.List to a java.util.List</p>
+</td><td class="codes"><pre class="brush: clojure">(defn to-list [x] (condp instance? x String (apply list (flatten [x])) List x ISeq (apply list x)))</pre></td></tr><tr><td class="docs"><p>Convert a File to its aboslute path, otherwise assume the string value is a path</p>
+</td><td class="codes"><pre class="brush: clojure">(defn to-filename-string [f] (if (instance? File f) (.getAbsolutePath f) (str f)))</pre></td></tr><tr><td class="docs"><p>Stick a trailing '.' on the end of the string (keyword or symbol) if one is not already present</p>
+</td><td class="codes"><pre class="brush: clojure">(defn ensure-trailing-period [a] (let [s (name a)](if-not (.endsWith s &quot;.&quot;) (str s &quot;.&quot;) s)))</pre></td></tr><tr><td class="docs"><p>Convert the value passed in to a org.xbill.DNS.Name (prefer calling the to-name function below)</p>
+</td><td class="codes"><pre class="brush: clojure">(defn dns-name [s] (Name. (ensure-trailing-period s)))</pre></td></tr><tr><td class="docs"><p>Conver the value passed in to a org.xbill.DNS.Name if it is not one already</p>
+</td><td class="codes"><pre class="brush: clojure">(defn to-name [n] (if (instance? Name n) n (dns-name n)))</pre></td></tr><tr><td class="docs"><p>Given two org.xbill.DNS.Name instances, check if b is a subdomain of a</p>
+</td><td class="codes"><pre class="brush: clojure">(defn sub-domain? [a b] (.subdomain (to-name a) (to-name b)))</pre></td></tr><tr><td class="docs"><p>Predicate that checks if any resource record in the rrs seq has the provided resource record type
+The rr-type is an int, but there are constants for the values on org.xbill.DNS.Type (e.g. Type/NS)</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rr-has? [rr-type &amp; rrs] (some #(= rr-type (.getType %)) rrs))</pre></td></tr><tr><td class="docs"><p>converts a map of options for dig to a seq of strings
+e.g. {:tcp true} will return '("-t")
+and {:ignore-trunction true :print-query true} will return '("-i" "-p")</p>
+</td><td class="codes"><pre class="brush: clojure">(defn- convert-dig-options
[options-map]
- (filter seq [(when (:tcp options-map) &quot;-t&quot;) (when (:ignore-trunction options-map) &quot;-i&quot;) (when (:print-query options-map) &quot;-p&quot;)]))</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn all-or-none
+ (filter seq [(when (:tcp options-map) &quot;-t&quot;) (when (:ignore-trunction options-map) &quot;-i&quot;) (when (:print-query options-map) &quot;-p&quot;)]))</pre></td></tr><tr><td class="docs"><p>given a map and a sequence of keys, it verifies that either all the keys from the sequence are present in the map or none of them are.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn- all-or-none
[m s] ; map m must contain each keyword from s or none of them
(or (every? #(contains? m %) s)
- (not-any? #(contains? m %) s)))</pre></td></tr><tr><td class="docs"><p>dig [@server] name [<type>] [<class>] [<options>]</p>
+ (not-any? #(contains? m %) s)))</pre></td></tr><tr><td class="docs"><h2>Resource Records</h2>
+
+<p>Functions for creating new instances of common resource record types.
+If you aren't familiar with a particular resource record type, then I suggest you read some RFCs or wikipedia :)
+It should be noted that there are many more resource record types, I've just chosen what I believe to be the most common.
+More might be added later.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rr-ns [{:keys [zone dclass ttl the-ns] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (NSRecord. (to-name zone) (int dclass) (long ttl) (to-name the-ns)))</pre></td></tr><tr><td class="docs"><p>key-tag is called footprint in the Java DNS library</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rr-ds [{:keys [zone dclass ttl key-tag algorithm digest-type digest] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (DSRecord. (to-name zone) (int dclass) (long ttl) key-tag algorithm digest-type digest))</pre></td></tr><tr><td class="docs"><p>The serial is commonly in the following format <date in yyyymmdd><run-of-the-day> &lt;20120420>&lt;01> or 2012042001
+What generally really matters is that each serial number is numerically larger than the previous ones issued.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rr-soa [{:keys [zone dclass ttl host admin serial refresh retry expire minimum] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults) refresh (:refresh soa-defaults) retry (:retry soa-defaults) expire (:expire soa-defaults) minimum (:minimum soa-defaults)}}]
+ (SOARecord. (to-name zone) (int dclass) (long ttl) (to-name host) (to-name admin) (long serial) (long refresh) (long retry) (long expire) (long minimum)))
+(defn rr-txt [{:keys [zone dclass ttl lines] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (TXTRecord. (to-name zone) (int dclass) (long ttl) (to-list lines)))
+(defn rr-mx [{:keys [zone dclass ttl priority target] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}] ; todo add default priority?
+ (MXRecord. (to-name zone) (int dclass) (long ttl) (int priority) (to-name target)))
+(defn rr-cname [{:keys [zone dclass ttl alias] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (CNAMERecord. (to-name zone) (int dclass) (long ttl) (to-name alias)))
+(defn rr-ptr [{:keys [zone dclass ttl target] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (PTRRecord. (to-name zone) (int dclass) (long ttl) (to-name target)))
+(defn rr-a [{:keys [zone dclass ttl address] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (ARecord. (to-name zone) (int dclass) (long ttl) (to-inet-address address)))
+(defn rr-aaaa [{:keys [zone dclass ttl address] :or {ttl (:ttl rr-defaults) dclass (:dclass rr-defaults)}}]
+ (ARecord. (to-name zone) (int dclass) (long ttl) (to-inet-address address)))</pre></td></tr><tr><td class="docs"><h3>Dummy functions (part of the hack to create an empty zone)</h3>
+</td><td class="codes"><pre class="brush: clojure">(defn- dummy-soa [zone-name] (rr-soa {:zone zone-name :dclass dflt-dclass :ttl dflt-ttl :host zone-name :admin zone-name :serial 0 :refresh 0 :retry 0 :expire 0 :minimum 0}))
+(defn- dummy-ns [zone-name] (rr-ns {:zone zone-name :dclass dflt-dclass :ttl dflt-ttl :the-ns zone-name}))</pre></td></tr><tr><td class="docs"><h2>Common DNS tasks</h2>
+
+<p>These are helpful from a REPL for example, but not generally in a program because they print results to standard out.</p>
+</td><td class="codes"></td></tr><tr><td class="docs"><p>Lookup hostname(s). This prints the result to stdout, it does not return a seq of the data.
+This can be used like so:
+(dns-lookup "www.google.com")
+or with multiple values:
+(dns-lookup "www.google.com" "www.bing.com")
+or if you have a seq of things to look up:
+(apply dns-lookup ["www.google.com" "www.bing.com"])</p>
+</td><td class="codes"><pre class="brush: clojure">(defn dns-lookup [&amp; to-lookups] (lookup/main (into-array String to-lookups)))</pre></td></tr><tr><td class="docs"><p>Lookup hostname(s) by resource record type. This prints the result to stdout, it does not return a seq of the data.
+example:
+(dns-loookup-by-type Type/PTR "www.google.com" "www.bing.com")</p>
+</td><td class="codes"><pre class="brush: clojure">(defn dns-lookup-by-type [rr-type &amp; to-lookups] (lookup/main (into-array String (into [&quot;-t&quot; (Type/string rr-type)] to-lookups))))</pre></td></tr><tr><td class="docs"><p>todo - add function for reverse lookup</p>
+</td><td class="codes"></td></tr><tr><td class="docs"><p>dig is a DNS utility that provides a great deal more detail than a simple lookup. It contains all the DNS information in the UDP packets.
+dig's options look something like:
+dig [@server] name [<type>] [<class>] [<options>]</p>
<pre><code>
-type defaults to A and class defaults to IN
-we might not want type A, but we're always going to default to class IN
+The type defaults to A and dclass defaults to IN
+A simple example:
+(dns-dig {:name "www.google.com"})
+Again, this prints the result to standard out.
use -x <name> for "name" to get a reverse lookup
here are the supported options...
-p <port>
-b <address>
--t -- use TCP instead of UDP
+-t -- use TCP instead of UDP (DNS uses UDP)
-i -- ignore truncation
-q -- print the query
-(example-dig-options {:tcp true :ignore-trunction true :print-query true})
+example
+(dns-dig {:tcp true :ignore-trunction true :print-query true})
and options I decided not to support
-k <TSIG> -- not supported here
-e <edns> -- not supported here
@@ -3082,70 +3132,65 @@
[{the-server :server the-name :name the-type :type options-map :options the-class :dclass :as the-args :or {:dclass DClass/IN}}]
{:pre [(all-or-none the-args [:server :type :dclass])]} ; if :server is present, :class and :type must be as well (for all permutations...)
(dig/main (into-array String (filter seq (into [the-server the-name the-type the-class] (convert-dig-options options-map))))))</pre></td></tr><tr><td class="docs"><h2>Ways to get a zone (generally prefer a Zone over a Master)</h2>
-</td><td class="codes"></td></tr><tr><td class="docs"><p>Read the zone from a file. It can be a java.io.File object or a String file path.</p>
-</td><td class="codes"><pre class="brush: clojure">(defn new-zone [zone-name zone-file]
- (Zone. (to-name zone-name) (to-filename-string zone-file)))</pre></td></tr><tr><td class="docs"><p>A zone must be seeded with a SOA and at least one NS record</p>
+</td><td class="codes"></td></tr><tr><td class="docs"><p>Read the zone from a file. It can be a java.io.File object or a String file path.
+Example:
+(read-zone-from-file "6.0.2.ip6.arpa." "/zones/6.0.2.ip6.arpa")</p>
+</td><td class="codes"><pre class="brush: clojure">(defn read-zone-from-file [zone-name zone-file]
+ (Zone. (to-name zone-name) (to-filename-string zone-file)))</pre></td></tr><tr><td class="docs"><p>A zone must be seeded with a SOA and at least one NS record. Additional resource records can be passed along with the NS record.
+Example
+(new-zone "6.0.2.ip6.arpa"
+ (rr-soa {:zone "6.0.2.ip6.arpa" :host "foo.com." :admin "dns.foo.com." :serial 1400 :refresh 1500 :retry 1600 :expire 1700 :minimum 1800})
+ (rr-ns {:zone "a.6.0.2.ip6.arpa" :the-ns "ns1.foo.com"})
+ (rr-txt {:zone "b.6.0.2.ip6.arpa" :lines "clojure is fun"}))</p>
</td><td class="codes"><pre class="brush: clojure">(defn new-zone [zone-name ^SOARecord the-soa &amp; rrs]
{:pre [(rr-has? Type/NS rrs)]}
(Zone. (to-name zone-name) (into-array Record (conj the-soa rrs))))</pre></td></tr><tr><td class="docs"><p>DNS Java requires a SOA and at least one NS record. We'll put placeholders in there and then
remove them, thus creating an empty zone. This allows zonelets (or fragments) to be created
and later stitched together to form a complete zone.</p>
-</td><td class="codes"><pre class="brush: clojure">(defn empty-zone
+</td><td class="codes"><pre class="brush: clojure">(defn zone-fragment
[zone-name]
(let [placeholder-soa (dummy-soa zone-name) placeholder-ns (dummy-ns zone-name)]
- (doto (Zone. (to-name zone-name) (into-array Record [placeholder-soa placeholder-ns]))
- (.removeRecord placeholder-soa)
- (.removeRecord placeholder-ns))))</pre></td></tr><tr><td class="docs"><p>zone passed in can be a File or InputStream</p>
+ (doto (Zone. (to-name zone-name) (into-array Record [placeholder-soa placeholder-ns]))
+ (.removeRecord placeholder-soa)
+ (.removeRecord placeholder-ns))))</pre></td></tr><tr><td class="docs"><p>Creates a completely empty zone. The idea is that you can build up pieces of a zone from these empty zones and merge them with merge-zones.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn empty-zone [] (zone-fragment &quot;.&quot;))</pre></td></tr><tr><td class="docs"><p>zone passed in can be a File or InputStream</p>
</td><td class="codes"><pre class="brush: clojure">(defn parse-master [zone]
- (Master. zone))</pre></td></tr><tr><td class="docs"><h2>Things you can do with a zone</h2>
+ (Master. zone))</pre></td></tr><tr><td class="docs"><h2>Things you can do with a RRSet</h2>
+
+<p>Generally, prefer to get a seq of resource records, but Java DNS has these RRSet objects, so we expose them as an intermediate abstraction.</p>
+</td><td class="codes"></td></tr><tr><td class="docs">
+</td><td class="codes"><pre class="brush: clojure">(defn rrs-from-rrset [rrset]
+ (iterator-seq (.rrs rrset)))</pre></td></tr><tr><td class="docs"><h2>Things you can do with a zone</h2>
</td><td class="codes"></td></tr><tr><td class="docs"><p>Print the zone as a string</p>
</td><td class="codes"><pre class="brush: clojure">(defn zone-to-str [zone]
- (.toMasterFile zone))</pre></td></tr><tr><td class="docs"><p>merge resource records from b into a</p>
-</td><td class="codes"><pre class="brush: clojure">(defn rrs-into [a b]
- (add-rrs a (rrs-from-zone b)))</pre></td></tr><tr><td class="docs"><p>Merge zonelets (or fragments) into a single zone</p>
+ (.toMasterFile zone))</pre></td></tr><tr><td class="docs"><p>Adds all the resource records passed in to the zone</p>
+</td><td class="codes"><pre class="brush: clojure">(defn add-rrs [zone &amp; rrs]
+ (do
+ (doseq [rr rrs] (.addRecord zone rr))
+ zone))</pre></td></tr><tr><td class="docs"><p>Get a seq of the rrsets from a zone. Prefer rrs-from-zone which gets a seq of the resource records in this seq of RRSet's</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rrsets-from-zone [zone]
+ (try
+ (iterator-seq (.iterator zone))
+ (catch ArrayIndexOutOfBoundsException e [])))</pre></td></tr><tr><td class="docs"><p>Get the resource records from a zone.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rrs-from-zone [zone]
+ (flatten (map rrs-from-rrset (rrsets-from-zone zone))))</pre></td></tr><tr><td class="docs"><p>merge resource records from b into a</p>
+</td><td class="codes"><pre class="brush: clojure">(defn rrs-into [zone-a zone-b]
+ (apply add-rrs zone-a (rrs-from-zone zone-b)))</pre></td></tr><tr><td class="docs"><p>Merge zonelets (or fragments) into a single zone</p>
</td><td class="codes"><pre class="brush: clojure">(defn merge-zones [&amp; zones]
- (let [new-zone (empty-zone)]
- (doseq [] (map (partial rrs-into new-zone) zones))))</pre></td></tr><tr><td class="docs"><p>todo need to introduce a protocol here to get the rrs from a master/zone
-Get the resource records from a master file. Note that this closes the master input stream.</p>
+ (let [the-new-zone (empty-zone)]
+ (doseq [z zones] (rrs-into the-new-zone z))
+ the-new-zone))</pre></td></tr><tr><td class="docs"><p>Removes all the resource records passed in from the zone</p>
+</td><td class="codes"><pre class="brush: clojure">(defn remove-rrs [zone &amp; rrs]
+ (doseq [rr rrs] (.removeRecord zone rr)))</pre></td></tr><tr><td class="docs"><p>This returns a seq of RRSet's from a zone.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn find-rrsets [zone zone-name zone-type]
+ (seq (.answers (.findRecords zone (to-name zone-name) (int zone-type)))))</pre></td></tr><tr><td class="docs"><p>This returns a seq of all the resource records from a zone.</p>
+</td><td class="codes"><pre class="brush: clojure">(defn find-records [zone zone-name zone-type]
+ (doall (map #(rrs-from-rrset %) (find-rrsets zone zone-name zone-type))))</pre></td></tr><tr><td class="docs"><h2>Master files</h2>
+</td><td class="codes"></td></tr><tr><td class="docs"><p>Prefer a zone to a master file
+todo need to introduce a protocol here to get the rrs from a master/zone?
+Get the resource records from a master file. Note that this closes the master input stream. </p>
</td><td class="codes"><pre class="brush: clojure">(defn rrs-from-master [master]
(let [v (.nextRecord master)]
(when-not (nil? v)
- (lazy-seq (cons v (rrs-from-master master))))))</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn rrs-from-zone [zone]
- (iterator-seq (.iterator zone)))</pre></td></tr><tr><td class="docs"><p>Adds all the resource records passed in to the zone</p>
-</td><td class="codes"><pre class="brush: clojure">(defn add-rrs [zone &amp; rrs]
- (doseq [] (map #(.addRecord zone %) rrs)))</pre></td></tr><tr><td class="docs"><p>Removes all the resource records passed in from the zone</p>
-</td><td class="codes"><pre class="brush: clojure">(defn remove-rrs [zone &amp; rrs]
- (doseq [] (map #(.removeRecord zone %) rrs)))</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn find-records [zone zone-name zone-type]
- (.findRecords zone (to-name zone-name) (int zone-type)))</pre></td></tr><tr><td class="docs"><h2>Resource Records</h2>
-</td><td class="codes"><pre class="brush: clojure">(defn rr-ns [{zone-name :zone ttl :ttl the-ns :ns dclass :dclass :or rr-defaults}]
- (NSRecord. (to-name zone-name) dclass (long ttl) (to-name the-ns)))
-(defn rr-ds [{:keys [zone dclass ttl key-tag algorithm digest-type digest] :or rr-defaults}]
- (DSRecord. (to-name zone) dclass (long ttl) key-tag algorithm digest-type digest)) ; key-tag is called footprint in the Java DNS library</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn rr-soa [{:keys [zone dclass ttl host admin serial refresh retry expire minimum] :or rr-defaults}]
- (SOARecord. (to-name zone) dclass (long ttl) (to-name host) (to-name admin) (long serial) (long refresh) (long retry) (long expire) (long minimum)))
-(defn rr-txt [{:keys [zone dclass ttl lines] :or rr-defaults}]
- (TXTRecord. (to-name zone) dclass (long ttl) (to-list lines)))
-(defn rr-mx [{:keys [zone dclass ttl priority target] :or rr-defaults}] ; todo add default priority?
- (MXRecord. (to-name zone) dclass (long ttl) (int priority) (to-name target)))
-(defn rr-cname [{:keys [zone dclass ttl alias] :or rr-defaults}]
- (CNAMERecord. (to-name zone) dclass (long ttl) (to-name alias)))
-(defn rr-ptr [{:keys [zone dclass ttl target] :or rr-defaults}]
- (PTRRecord. (to-name zone) dclass (long ttl) (to-name target)))
-(defn rr-a [{:keys [zone dclass ttl address] :or rr-defaults}]
- (ARecord. (to-name zone) dclass (long ttl) (to-inet-address address)))
-(defn rr-aaaa [{:keys [zone dclass ttl address] :or rr-defaults}]
- (ARecord. (to-name zone) dclass (long ttl) (to-inet-address address)))</pre></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn dummy-soa [zone-name] (rr-soa {:zone zone-name :dclass default-dclass :ttl default-ttl :host zone-name :admin zone-name :serial 0 :refresh 0 :retry 0 :expire 0 :minimum 0}))
-(defn dummy-ns [zone-name] (rr-ns {:zone zone-name :dclass default-dclass :ttl default-ttl :ns zone-name}))</pre></td></tr><tr><td class="docs"><h2>Helper functions (todo protocol better for the instance? cases...?)</h2>
-</td><td class="codes"></td></tr><tr><td class="docs">
-</td><td class="codes"><pre class="brush: clojure">(defn to-inet-address [a] (Address/getByName (name a)))</pre></td></tr><tr><td class="docs"><p>could have a single element, seq or java.util.List</p>
-</td><td class="codes"><pre class="brush: clojure">(defn to-list [x] (condp instance? x String (apply list (flatten [x])) List x ISeq (apply list x)))
-(defn to-filename-string [f] (if (instance? File f) (.getAbsolutePath f) (str f)))
-(defn ensure-trailing-period [a] (let [s (name a)](if-not (.endsWith s &quot;.&quot;) (str s &quot;.&quot;) s)))
-(defn dns-name [s] (Name. (ensure-trailing-period s)))
-(defn to-name [n] (if (instance? Name n) n (dns-name n)))
-(defn sub-domain? [a b] (.subdomain (to-name a) (to-name b)))
-(defn rr-has? [rr-type &amp; rrs] (some #(= rr-type (.getType %)) rrs))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/fogus/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
+ (lazy-seq (cons v (rrs-from-master master))))))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/fogus/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.all()</script></body></html>
View
32 src/clj_dns/core.clj
@@ -158,12 +158,19 @@
(.removeRecord placeholder-soa)
(.removeRecord placeholder-ns))))
+;; Creates a completely empty zone. The idea is that you can build up pieces of a zone from these empty zones and merge them with merge-zones.
(defn empty-zone [] (zone-fragment "."))
;; zone passed in can be a File or InputStream
(defn parse-master [zone]
(Master. zone))
+;; ## Things you can do with a RRSet
+;; Generally, prefer to get a seq of resource records, but Java DNS has these RRSet objects, so we expose them as an intermediate abstraction.
+
+(defn rrs-from-rrset [rrset]
+ (iterator-seq (.rrs rrset)))
+
;; ## Things you can do with a zone
;; Print the zone as a string
@@ -176,21 +183,19 @@
(doseq [rr rrs] (.addRecord zone rr))
zone))
+;; Get a seq of the rrsets from a zone. Prefer rrs-from-zone which gets a seq of the resource records in this seq of RRSet's
(defn rrsets-from-zone [zone]
(try
(iterator-seq (.iterator zone))
(catch ArrayIndexOutOfBoundsException e [])))
-(defn rrs-from-rrset [rrset]
- (iterator-seq (.rrs rrset)))
-
;; Get the resource records from a zone.
(defn rrs-from-zone [zone]
(flatten (map rrs-from-rrset (rrsets-from-zone zone))))
;; merge resource records from b into a
-(defn rrs-into [a b]
- (apply add-rrs a (rrs-from-zone b)))
+(defn rrs-into [zone-a zone-b]
+ (apply add-rrs zone-a (rrs-from-zone zone-b)))
;; Merge zonelets (or fragments) into a single zone
(defn merge-zones [& zones]
@@ -198,13 +203,6 @@
(doseq [z zones] (rrs-into the-new-zone z))
the-new-zone))
-;; todo need to introduce a protocol here to get the rrs from a master/zone
-;; Get the resource records from a master file. Note that this closes the master input stream.
-(defn rrs-from-master [master]
- (let [v (.nextRecord master)]
- (when-not (nil? v)
- (lazy-seq (cons v (rrs-from-master master))))))
-
;; Removes all the resource records passed in from the zone
(defn remove-rrs [zone & rrs]
(doseq [rr rrs] (.removeRecord zone rr)))
@@ -216,3 +214,13 @@
;; This returns a seq of all the resource records from a zone.
(defn find-records [zone zone-name zone-type]
(doall (map #(rrs-from-rrset %) (find-rrsets zone zone-name zone-type))))
+
+;; ## Master files
+
+;; Prefer a zone to a master file
+;; todo need to introduce a protocol here to get the rrs from a master/zone?
+;; Get the resource records from a master file. Note that this closes the master input stream.
+(defn rrs-from-master [master]
+ (let [v (.nextRecord master)]
+ (when-not (nil? v)
+ (lazy-seq (cons v (rrs-from-master master))))))
Please sign in to comment.
Something went wrong with that request. Please try again.