IPs are now 32bit integer internet addresses,

changed the API for concurrent-lookup,
revised the documentation
This commit is contained in:
cresh 2002-07-07 17:43:32 +00:00
parent 27ff0f4326
commit 470c2fbab3
2 changed files with 129 additions and 55 deletions

View File

@ -14,31 +14,40 @@
; --- ; ---
; sample usage & documentation: ; sample usage & documentation:
; ;
; <name>, <ip-string> and <nameserver> are strings. ; <ip-address32> is a 32bit integer internet->address, shortly address32.
; <ip-string> is a string in standard dot notation "xxx.xxx.xxx.xxx".
; <name> is a string
; ;
; <nameserver> can either be a domainname or a ip. ; <nameserver> can either be a domainname, an ip-string or an ip-address32.
; if it is a domainname, its ip is looked up on a nameserver listed in ; if it is a domainname, its ip is looked up on a nameserver listed in
; /etc/resolv.conf. ; /etc/resolv.conf.
; ;
; (dns-find-nameserver) --> <ip-string> ; (dns-find-nameserver) --> <ip-address32>
; this parses the /etc/resolv.conf file and returns the first found ; this parses the /etc/resolv.conf file and returns the first found
; nameserver. ; nameserver in address32 format.
; ;
; ;
; ;
; (dns-lookup-name <name> [nameserver]) --> <ip-string> ; (dns-lookup-name <name> [nameserver]) --> <ip-address32>
; (dns-lookup-ip <ip-string> [nameserver]) --> <name> ; (dns-lookup-ip <ip-string | ip-address32> [nameserver]) --> <name>
; (dns-lookup-nameserver <name> [nameserver]) ; (dns-lookup-nameserver <name> [nameserver])
; --> <list of ip-strings of authoritative nameservers> ; --> <list of ip-address32s of authoritative nameservers>
; (dns-lookup-mail-exchanger <name> [nameserver]) ; (dns-lookup-mail-exchanger <name> [nameserver])
; --> <list of names of mail-exchangers> ; --> <list of names of mail-exchangers>
; ;
; dns-lookup-name, dns-lookup-ip, dns-lookup-nameserver and ; dns-lookup-name, dns-lookup-ip, dns-lookup-nameserver and
; dns-lookup-mail-exchanger are "simple lookup functions", ; dns-lookup-mail-exchanger are "simple lookup functions",
; they return the wanted information or #f. ; they return the wanted information or #f.
; dns-lookup-ip can either be given an ip-string or an ip-address32.
;
; concurrent dns lookup:
; a concurrent lookup to all nameservers in /etc/resolv.conf is started,
; if the variable dns-concurrent-lookup is given as optional <nameserver>
; argument.
; ;
; ;
; (dns-lookup <name/ip-string> <type> [nameserver]) --> <dns-message> ; (dns-lookup <name | ip-string | ip-address32> <type> [nameserver])
; --> <dns-message>
; (show-dns-message <dns-message) --> the whole message, human readable ; (show-dns-message <dns-message) --> the whole message, human readable
; ;
; a <dns-message> is a record, with several entries, which holds the whole ; a <dns-message> is a record, with several entries, which holds the whole
@ -49,18 +58,20 @@
; only useful in very special cases. ; only useful in very special cases.
; ;
; ;
; (concurrent-lookup <simple lookup function> <name>)
; starts a concurrent lookup to all nameservers in /etc/resolv.conf.
; the simple lookup function defines the lookup type.
;
;
; some lookups return a hostname (e.g. mx). ; some lookups return a hostname (e.g. mx).
; many applications need instead of a hostname a ip address. ; many applications need instead of a hostname a ip address.
; force-ip and force-ip-list guarantee that a ip address is ; force-ip and force-ip-list guarantee that a ip address is
; returned. ; returned.
; ;
; (force-ip <name>) --> <ip-string> ; (force-ip <name>) --> <ip>
; (force-ip-list <list of names>) --> <list of ips> ; (force-ip-list <list of names>) --> <list of ips>
;
;
; useful converters:
;
; (address32->ip-string <ip-address32>) -> <ip-string>
; (ip-string->address32 <ip-string>) -> <ip-address32>
@ -151,6 +162,8 @@
(else (more)))) (else (more))))
;; concurrent-flag
(define dns-concurrent-lookup 'dns-concurrent-lookup)
;;; -- globals and types ;;; -- globals and types
@ -254,9 +267,40 @@
(if *debug* (display "add-size-tag\n")) (if *debug* (display "add-size-tag\n"))
(append (number->octet-pair (length m)) m)) (append (number->octet-pair (length m)) m))
;; converts an octeted-ip to a 32bit integer internet-address
(define (octet-ip->address32 ip)
(if *debug* (display "octet-ip->address32\n"))
(+ (arithmetic-shift (char->ascii (list-ref ip 0)) 24)
(arithmetic-shift (char->ascii (list-ref ip 1)) 16)
(arithmetic-shift (char->ascii (list-ref ip 2)) 8)
(char->ascii (list-ref ip 3))))
;; converts a 32 bit integer internet-address to an octeted-ip
(define (address32->octet-ip ip)
(if *debug* (display "number->octet-quad\n"))
(list (arithmetic-shift ip -24)
(modulo (arithmetic-shift ip -16) 256)
(modulo (arithmetic-shift ip -8) 256)
(modulo ip 256)))
;; converts an ip-string to an 32bit integer internet-address
(define (ip-string->address32 ip)
(if *debug* (display "ip-string->address32\n"))
(octet-ip->address32 (string->octet-ip ip)))
;; converts an ip-string to an 32bit integer internet-address
(define (address32->ip-string ip)
; (if *debug* (display "address32->ip-string\n"))
(format #f
"~a.~a.~a.~a"
(arithmetic-shift ip -24)
(modulo (arithmetic-shift ip -16) 256)
(modulo (arithmetic-shift ip -8) 256)
(modulo ip 256)))
;; converts an octeted-ip to an human readable ip-string ;; converts an octeted-ip to an human readable ip-string
(define (ip->string s) (define (octet-ip->string s)
(if *debug* (display "ip->string\n")) (if *debug* (display "octet-ip->string\n"))
(format #f (format #f
"~a.~a.~a.~a" "~a.~a.~a.~a"
(char->ascii (list-ref s 0)) (char->ascii (list-ref s 0))
@ -265,8 +309,8 @@
(char->ascii (list-ref s 3)))) (char->ascii (list-ref s 3))))
;; converts an ip-string to octets ;; converts an ip-string to octets
(define (string->ip s) (define (string->octet-ip s)
(if *debug* (display "string->ip\n")) (if *debug* (display "string->octet-ip\n"))
(let loop ((s s) (let loop ((s s)
(result '())) (result '()))
(cond (cond
@ -285,7 +329,7 @@
314159265)))) 314159265))))
;; checks if a string is a ip ;; checks if a string is a ip
(define (ip? s) (define (ip-string? s)
(if *debug* (display "ip-string->in-addr\n")) (if *debug* (display "ip-string->in-addr\n"))
(let loop ((s s) (let loop ((s s)
(count 0)) (count 0))
@ -304,6 +348,10 @@
(= count 3) (= count 3)
#t)))))) #t))))))
;; checks if v is a address32
(define (address32? v)
(and (number? v)
(<= 0 v #xffffffff)))
;; returns a in-addr.arpa name-string or #f (needed to resolve hostname by ip) ;; returns a in-addr.arpa name-string or #f (needed to resolve hostname by ip)
(define (ip-string->in-addr s) (define (ip-string->in-addr s)
@ -343,7 +391,7 @@
;; returns a IP if available (additonal type-a processing) ;; returns a IP if available (additonal type-a processing)
(define (force-ip name) (define (force-ip name)
(let loop ((result (dns-lookup-name name))) (let loop ((result (dns-lookup-name name)))
(if (ip? result) (if (ip-string? result)
result result
(loop (dns-lookup-name result))))) (loop (dns-lookup-name result)))))
@ -612,7 +660,7 @@
(if *debug* (display "parse-rr-data\n")) (if *debug* (display "parse-rr-data\n"))
(cond (cond
((eq? type 'a) ((eq? type 'a)
(make-rr-data-a (ip->string data))) (make-rr-data-a (octet-ip->address32 data)))
((eq? type 'ns) ((eq? type 'ns)
(make-rr-data-ns (call-with-values (make-rr-data-ns (call-with-values
@ -932,7 +980,7 @@
ns)) ns))
((regexp-search (posix-string->regexp "nameserver[ ]+([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)") l) ((regexp-search (posix-string->regexp "nameserver[ ]+([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)") l)
=> (lambda (match) => (lambda (match)
(loop (append ns (list (match:substring match 1)))))) (loop (append ns (list (ip-string->address32 (match:substring match 1)))))))
(else (else
(loop ns)))))))) (loop ns))))))))
@ -960,12 +1008,12 @@
(for-each (lambda (nameserver) (for-each (lambda (nameserver)
(spawn (spawn
(lambda () (lambda ()
(display "query sent to ")(display nameserver)(display " \n") ;(display "query sent to ")(display nameserver)(display " \n")
(let* ((result (apply lookup (list name nameserver)))) (let* ((result (apply lookup (list name nameserver))))
(enqueue! queue result) (enqueue! queue result)
(display "received reply from ")(display nameserver)(display ": ")(display result)(newline) ;(display "received reply from ")(display nameserver)(display ": ")(display result)(newline)
(release-lock lock))))) (release-lock lock)))))
(dns-find-nameserver-list)))) (map (lambda (adr32) (address32->ip-string adr32)) (dns-find-nameserver-list)))))
(let loop ((count (length nameserver-list))) (let loop ((count (length nameserver-list)))
(obtain-lock lock) (obtain-lock lock)
@ -974,16 +1022,17 @@
result result
(loop (- count 1))))))) (loop (- count 1)))))))
;; checks the arguments of the dns-lookup-* functions. ;; checks the arguments of the simple lookup functions.
;; if a nameserver-name is given and not a nameserver-ip ;; if a nameserver-name is given and not a nameserver-ip
;; (dns-lookup-name nameserver) is called. ;; (dns-lookup-name nameserver) is called.
(define (check-args args) (define (check-args args)
(if (null? args) (if (null? args)
(dns-find-nameserver) (address32->ip-string (dns-find-nameserver) )
(let ((nameserver (car args))) (let ((nameserver (car args)))
(if (ip? nameserver) (cond
nameserver ((ip-string? nameserver) nameserver)
(dns-lookup-name nameserver))))) ((address32? nameserver) (address32->ip-string nameserver))
(else (address32->ip-string (dns-lookup-name nameserver)))))))
;; dns-lookup with more options than dns-lookup-* ;; dns-lookup with more options than dns-lookup-*
@ -996,7 +1045,9 @@
(dns-error-messages condition more) (dns-error-messages condition more)
(exit #f)) (exit #f))
(lambda () (lambda ()
(let* ((ip-string (ip-string->in-addr name)) (let* ((ip-string (if (address32? name)
(ip-string->in-addr (address32->ip-string name))
(ip-string->in-addr name)))
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address (question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(make-octet-query-message (random 256) ip-string type 'in) (make-octet-query-message (random 256) ip-string type 'in)
(make-octet-query-message (random 256) name type 'in))) (make-octet-query-message (random 256) name type 'in)))
@ -1012,10 +1063,18 @@
dns-msg)))))) dns-msg))))))
;; returns a lookup-function with concurrent-flag
(define (make-lookup-function simple-lookup-function)
(lambda (name . args)
(if (null? args)
(simple-lookup-function name)
(if (eq? (car args) dns-concurrent-lookup)
(concurrent-lookup simple-lookup-function name)
(simple-lookup-function name (car args))))))
;; looks up a hostname, returns an ip. ;; looks up a hostname, returns an ip.
;; (dns-lookup-name <name> [nameserver]) ;; (dns-lookup-name <name> [nameserver])
(define (dns-lookup-name name . args) (define (dns-simple-lookup-name name . args)
(call-with-current-continuation (call-with-current-continuation
(lambda (exit) (lambda (exit)
(with-handler (with-handler
@ -1023,7 +1082,9 @@
(dns-error-messages condition more) (dns-error-messages condition more)
(exit #f)) (exit #f))
(lambda () (lambda ()
(let* ((ip-string (ip-string->in-addr name)) (let* ((ip-string (if (address32? name)
(ip-string->in-addr (address32->ip-string name))
(ip-string->in-addr name)))
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address (question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(signal 'not-a-hostname) (signal 'not-a-hostname)
(make-octet-query-message (random 256) name 'a 'in))) (make-octet-query-message (random 256) name 'a 'in)))
@ -1038,10 +1099,11 @@
(answers (filter-type (message:answers (dns-message:reply dns-msg)) 'a))) (answers (filter-type (message:answers (dns-message:reply dns-msg)) 'a)))
(rr-data-a:ip (rr:data (car answers))))))))) (rr-data-a:ip (rr:data (car answers)))))))))
(define dns-lookup-name (make-lookup-function dns-simple-lookup-name))
;; looks up an ip, returns a hostname ;; looks up an ip, returns a hostname
;; (dns-inverse-lookup <name> [nameserver]) ;; (dns-inverse-lookup <name> [nameserver])
(define (dns-inverse-lookup ip . args) (define (dns-simple-lookup-ip ip . args)
(call-with-current-continuation (call-with-current-continuation
(lambda (exit) (lambda (exit)
(with-handler (with-handler
@ -1049,7 +1111,9 @@
(dns-error-messages condition more) (dns-error-messages condition more)
(exit #f)) (exit #f))
(lambda () (lambda ()
(let* ((ip-string (ip-string->in-addr ip)) (let* ((ip-string (if (address32? ip)
(ip-string->in-addr (address32->ip-string ip))
(ip-string->in-addr ip)))
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address (question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(make-octet-query-message (random 256) ip-string 'ptr 'in) (make-octet-query-message (random 256) ip-string 'ptr 'in)
(signal 'not-a-ip))) (signal 'not-a-ip)))
@ -1064,13 +1128,15 @@
(answers (filter-type (message:answers (dns-message:reply dns-msg)) 'ptr))) (answers (filter-type (message:answers (dns-message:reply dns-msg)) 'ptr)))
(rr-data-ptr:name (rr:data (car answers))))))))) (rr-data-ptr:name (rr:data (car answers)))))))))
(define dns-lookup-ip dns-inverse-lookup) (define dns-lookup-ip (make-lookup-function dns-simple-lookup-ip))
(define dns-inverse-lookup dns-lookup-ip)
;; looks up an authoritative nameserver for a hostname ;; looks up an authoritative nameserver for a hostname
;; returns a list of nameservers ;; returns a list of nameservers
;; (dns-lookup-nameserver <name> [nameserver]) ;; (dns-lookup-nameserver <name> [nameserver])
(define (dns-lookup-nameserver name . args) (define (dns-simple-lookup-nameserver name . args)
(call-with-current-continuation (call-with-current-continuation
(lambda (exit) (lambda (exit)
(with-handler (with-handler
@ -1078,7 +1144,9 @@
(dns-error-messages condition more) (dns-error-messages condition more)
(exit #f)) (exit #f))
(lambda () (lambda ()
(let* ((ip-string (ip-string->in-addr name)) (let* ((ip-string (if (address32? name)
(ip-string->in-addr (address32->ip-string name))
(ip-string->in-addr name)))
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address (question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(signal 'not-a-hostname) (signal 'not-a-hostname)
(make-octet-query-message (random 256) name 'ns 'in))) (make-octet-query-message (random 256) name 'ns 'in)))
@ -1100,13 +1168,15 @@
(list (dns-lookup-name (rr-data-soa:mname (rr:data (car soa))))) (list (dns-lookup-name (rr-data-soa:mname (rr:data (car soa)))))
(map (lambda (elem) (rr-data-a:ip (rr:data elem))) add)))))))) (map (lambda (elem) (rr-data-a:ip (rr:data elem))) add))))))))
(define dns-lookup-nameserver (make-lookup-function dns-simple-lookup-nameserver))
;; looks up a mail-exchanger for a hostname. ;; looks up a mail-exchanger for a hostname.
;; returns a list of mail-exchanger, sorted by their preference ;; returns a list of mail-exchanger, sorted by their preference
;; if there are no mx-records in the answer-section, ;; if there are no mx-records in the answer-section,
;; implementation based on RFC2821 ;; implementation based on RFC2821
;; (dns-lookup-mail-exchanger <name> [nameserver]) ;; (dns-lookup-mail-exchanger <name> [nameserver])
(define (dns-lookup-mail-exchanger name . args) (define (dns-simple-lookup-mail-exchanger name . args)
(call-with-current-continuation (call-with-current-continuation
(lambda (exit) (lambda (exit)
(with-handler (with-handler
@ -1114,7 +1184,9 @@
(dns-error-messages condition more) (dns-error-messages condition more)
(exit #f)) (exit #f))
(lambda () (lambda ()
(let* ((ip-string (ip-string->in-addr name)) (let* ((ip-string (if (address32? name)
(ip-string->in-addr (address32->ip-string name))
(ip-string->in-addr name)))
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address (question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(signal 'not-a-hostname) (signal 'not-a-hostname)
(make-octet-query-message (random 256) name 'mx 'in))) (make-octet-query-message (random 256) name 'mx 'in)))
@ -1145,7 +1217,7 @@
(else (else
(map (lambda (elem) (rr-data-mx:exchanger (rr:data elem))) (sort-by-preference mx)))))))))) (map (lambda (elem) (rr-data-mx:exchanger (rr:data elem))) (sort-by-preference mx))))))))))
(define dns-lookup-mail-exchanger (make-lookup-function dns-simple-lookup-mail-exchanger))
;;; pretty-prints a dns-msg ;;; pretty-prints a dns-msg

View File

@ -182,19 +182,21 @@
net:daytime)) net:daytime))
(define-interface dns-interface (define-interface dns-interface
(export dns-clear-cache (export dns-clear-cache ; clears the cache
dns-lookup dns-lookup ; complex lookup function
dns-lookup-name dns-lookup-name ; simple lookup function
dns-inverse-lookup dns-inverse-lookup ; obsolete, use dns-lookup-ip
dns-lookup-ip dns-lookup-ip ; simple lookup function
dns-lookup-nameserver dns-lookup-nameserver ; simple lookup function
dns-lookup-mail-exchanger dns-lookup-mail-exchanger ; simple lookpu function
concurrent-lookup dns-concurrent-lookup ; the concurrent lookup variable
show-dns-message show-dns-message ; prints a human readable dns-msg
force-ip force-ip ; reruns a lookup until a ip is resolved
force-ip-list force-ip-list ; reruns a lookup until a list of ips is resolved
dns-find-nameserver address32->ip-string ; converts a address32 in an ip-string
dns-find-nameserver-list)) ip-string->address32 ; converts a ip-string in an address32
dns-find-nameserver ; returns a nameserver
dns-find-nameserver-list)) ; returns a list of nameservers
(define-interface cgi-script-interface (define-interface cgi-script-interface
(export cgi-form-query)) (export cgi-form-query))