+ rr-X -> resource-record-X

+ removed separate cache mapping IPs to FQDNs
This commit is contained in:
mainzelm 2003-02-10 08:04:17 +00:00
parent a4f7e6f337
commit e2697605f6
1 changed files with 278 additions and 289 deletions

View File

@ -377,14 +377,14 @@
;; filters types in a list of rrs
(define (filter-type list type)
(filter (lambda (rr)
(eq? (rr-type rr) type))
(eq? (resource-record-type rr) type))
list))
;; sorts a mx-rr-list by preference. needed for dns-lookup-mail-exchanger.
;; sorts a mx-resource-record-list by preference. needed for dns-lookup-mail-exchanger.
(define (sort-by-preference mx-list)
(sort-list mx-list
(lambda (a b)
(< (rr-data-mx-preference (rr-data a)) (rr-data-mx-preference (rr-data b))))))
(< (resource-record-data-mx-preference (resource-record-data a)) (resource-record-data-mx-preference (resource-record-data b))))))
;; returns a IP if available (additonal type-a processing)
@ -422,16 +422,17 @@
;; makes a query-message (header and question only)
;; TODO does this really work for several questions as well?
(define (make-query-dns-message header . questions)
(make-message header questions '() '() '()
(apply
append
(header->octets header)
(map question->octets questions))))
(define (make-query-message header question . questions)
(let ((questions (cons question questions)))
(make-message header questions '() '() '()
(apply
append
(header->octets header)
(map question->octets questions)))))
(define (make-simple-query-dns-message id name type class)
(make-query-dns-message (make-std-query-header id 1)
(make-question name type class)))
(define (make-simple-query-message name type class)
(make-query-message (make-std-query-header (random 256) 1)
(make-question name type class)))
;; makes a resource record for ans, nss, ars (name, type, class, ttl, data)
(define (make-octet-rr name type class ttl rdata)
@ -566,15 +567,15 @@
(message-class-number (question-class q)))))
(append qname qtype qclass)))
;;type rr
(define-record-type rr :rr
(make-rr name type class ttl data)
rr?
(name rr-name)
(type rr-type)
(class rr-class)
(ttl rr-ttl)
(data rr-data))
;;type resource-record
(define-record-type resource-record :resource-record
(make-resource-record name type class ttl data)
resource-record?
(name resource-record-name)
(type resource-record-type)
(class resource-record-class)
(ttl resource-record-ttl)
(data resource-record-data))
;; cache
(define-record-type cache :cache
@ -654,94 +655,94 @@
(start start)
(accum '()))
(if (zero? len)
(values (make-rr name type class ttl (parse-rr-data type class (reverse! accum) message)) start)
(values (make-resource-record name type class ttl (parse-resource-record-data type class (reverse! accum) message)) start)
(loop (- len 1)
(cdr start)
(cons (car start) accum)))))))))))
;;; -- rr-data-type records
;;; -- resource-record-data-type records
(define-record-type rr-data-a :rr-data-a
(make-rr-data-a ip)
rr-data-a?
(ip rr-data-a-ip))
(define-record-type resource-record-data-a :resource-record-data-a
(make-resource-record-data-a ip)
resource-record-data-a?
(ip resource-record-data-a-ip))
(define-record-type rr-data-ns :rr-data-ns
(make-rr-data-ns name)
rr-data-ns?
(name rr-data-ns-name))
(define-record-type resource-record-data-ns :resource-record-data-ns
(make-resource-record-data-ns name)
resource-record-data-ns?
(name resource-record-data-ns-name))
(define-record-type rr-data-cname :rr-data-cname
(make-rr-data-cname name)
rr-data-cname?
(name rr-data-cname-name))
(define-record-type resource-record-data-cname :resource-record-data-cname
(make-resource-record-data-cname name)
resource-record-data-cname?
(name resource-record-data-cname-name))
;; ###
;; hinfo not correctly implemented, trying to find examples
(define-record-type rr-data-hinfo :rr-data-hinfo
(make-rr-data-hinfo data)
rr-data-hinfo?
(data rr-data-hinfo-data))
(define-record-type resource-record-data-hinfo :resource-record-data-hinfo
(make-resource-record-data-hinfo data)
resource-record-data-hinfo?
(data resource-record-data-hinfo-data))
(define-record-type rr-data-mx :rr-data-mx
(make-rr-data-mx preference exchanger)
rr-data-mx?
(preference rr-data-mx-preference)
(exchanger rr-data-mx-exchanger))
(define-record-type resource-record-data-mx :resource-record-data-mx
(make-resource-record-data-mx preference exchanger)
resource-record-data-mx?
(preference resource-record-data-mx-preference)
(exchanger resource-record-data-mx-exchanger))
(define-record-type rr-data-ptr :rr-data-ptr
(make-rr-data-ptr name)
rr-data-ptr?
(name rr-data-ptr-name))
(define-record-type resource-record-data-ptr :resource-record-data-ptr
(make-resource-record-data-ptr name)
resource-record-data-ptr?
(name resource-record-data-ptr-name))
(define-record-type rr-data-soa :rr-data-soa
(make-rr-data-soa mname rname serial refresh retry expire minimum)
rr-data-soa?
(mname rr-data-soa-mname)
(rname rr-data-soa-rname)
(serial rr-data-soa-serial)
(refresh rr-data-soa-refresh)
(retry rr-data-soa-retry)
(expire rr-data-soa-expire)
(minimum rr-data-soa-minimum))
(define-record-type resource-record-data-soa :resource-record-data-soa
(make-resource-record-data-soa mname rname serial refresh retry expire minimum)
resource-record-data-soa?
(mname resource-record-data-soa-mname)
(rname resource-record-data-soa-rname)
(serial resource-record-data-soa-serial)
(refresh resource-record-data-soa-refresh)
(retry resource-record-data-soa-retry)
(expire resource-record-data-soa-expire)
(minimum resource-record-data-soa-minimum))
;; ### same as hinfo
(define-record-type rr-data-txt :rr-data-txt
(make-rr-data-txt text)
rr-data-txt?
(text rr-data-txt-text))
(define-record-type resource-record-data-txt :resource-record-data-txt
(make-resource-record-data-txt text)
resource-record-data-txt?
(text resource-record-data-txt-text))
;; ### same as hinfo and txt
(define-record-type rr-data-wks :rr-data-wks
(make-rr-data-wks data)
rr-data-wks?
(data rr-data-wks-data))
(define-record-type resource-record-data-wks :resource-record-data-wks
(make-resource-record-data-wks data)
resource-record-data-wks?
(data resource-record-data-wks-data))
;;
(define (parse-rr-data type class data message)
(define (parse-resource-record-data type class data message)
(cond
((eq? type (message-type a))
(make-rr-data-a (octet-ip->address32 data)))
(make-resource-record-data-a (octet-ip->address32 data)))
((eq? type (message-type ns))
(make-rr-data-ns (call-with-values
(make-resource-record-data-ns (call-with-values
(lambda () (parse-name data message))
(lambda (name rest) name))))
((eq? type (message-type cname))
(make-rr-data-cname (call-with-values
(make-resource-record-data-cname (call-with-values
(lambda () (parse-name data message))
(lambda (name rest) name))))
((eq? type (message-type mx))
(make-rr-data-mx (octet-pair->number (car data) (cadr data))
(make-resource-record-data-mx (octet-pair->number (car data) (cadr data))
(call-with-values
(lambda ()(parse-name (cddr data) message))
(lambda (name rest) name))))
((eq? type (message-type ptr))
(make-rr-data-ptr (call-with-values
(make-resource-record-data-ptr (call-with-values
(lambda () (parse-name data message))
(lambda (name rest) name))))
@ -762,16 +763,16 @@
(rest (cddddr rest)))
(let ((minimum (octet-quad->number (car rest) (cadr rest) (caddr rest) (cadddr rest)))
(rest (cddddr rest)))
(make-rr-data-soa mname rname serial refresh retry expire minimum)))))))))))
(make-resource-record-data-soa mname rname serial refresh retry expire minimum)))))))))))
((eq? type (message-type hinfo))
(make-rr-data-hinfo (list->string data)))
(make-resource-record-data-hinfo (list->string data)))
((eq? type (message-type txt))
(make-rr-data-txt (list->string data)))
(make-resource-record-data-txt (list->string data)))
((eq? type (message-type wks))
(make-rr-data-wks data))
(make-resource-record-data-wks data))
(else (list data))))
@ -875,10 +876,10 @@
(sock (cdr (assoc w wport-socket-alist))))
(if (not (connect-socket-successful? sock))
(dns-error 'bad-nameserver hit-ns))
(let ((query-string
(add-size-tag (list->string (message-source query))))
(let ((query-string
(list->string (add-size-tag (message-source query))))
(r (socket:inport sock)))
(display (list->string query-string) w)
(display query-string w)
(force-output w)
(let ((a (read-char r))
(b (read-char r)))
@ -960,12 +961,12 @@
(for-each (lambda (x) (find-shortest-ttl-1 x)) (message-nameservers dns-msg))
(for-each (lambda (x) (find-shortest-ttl-1 x)) (message-additionals dns-msg))
minimum)
((rr? dns-msg)
((resource-record? dns-msg)
(cond
((not minimum) (set! minimum (rr-ttl dns-msg)))
((not minimum) (set! minimum (resource-record-ttl dns-msg)))
(else
(if (and (not minimum) (> minimum (rr-ttl dns-msg)))
(set! minimum (rr-ttl dns-msg))))))))))
(if (and (not minimum) (> minimum (resource-record-ttl dns-msg)))
(set! minimum (resource-record-ttl dns-msg))))))))))
(find-shortest-ttl-1 dns-msg)))
@ -1022,10 +1023,17 @@
nameservers)))
(else (lp (cdr ns))))))))
(define-enumerated-type network-protocol :network-protocol
network-protocol?
network-protocols
network-protocol-name
network-protocol-index
(udp tcp))
(define (send-receive-message nameservers query protocol)
((cond
((eq? protocol 'tcp) send-receive-message-tcp)
((eq? protocol 'udp) send-receive-message-udp))
((eq? protocol (network-protocol tcp)) send-receive-message-tcp)
((eq? protocol (network-protocol udp)) send-receive-message-udp))
nameservers query))
;; makes a dns-query. optional cache-check.
@ -1042,28 +1050,29 @@
;; this feature is technically optional (RFC 1035).
;; dns-get-information implements the resovler-side recursion.
;; it returns a dns-message
(define (dns-get-information query use-cache? protocol nameservers check-answer)
(let lp ((tried '()) (nss nameservers))
(if (null? nss)
(dns-error 'bad-address)
(receive (dns-msg hit-ns nss-with-no-reply)
(dns-query/cache query use-cache? protocol nss tried)
(if (check-answer dns-msg)
dns-msg
(let ((auth? (flags-authoritative? (header-flags
(message-header
(dns-message-reply dns-msg))))))
(if auth?
(dns-error 'bad-address)
;; other nameservers names are found in the nameserver-part,
;; but their ip-adresses are found in the additonal-rrs
(let ((other-nameservers
(filter (lambda (elem) (eq? (rr-type elem) (message-type a)))
(message-additionals (dns-message-reply dns-msg)))))
(lp (if (not (member hit-ns tried)) (cons hit-ns tried) tried)
(lset-union equal?
nss-with-no-reply
(lset-difference equal? other-nameservers tried)))))))))))
(define (dns-get-information query protocol check-answer . args)
(receive (nameservers use-cache?) (lookup-optional-args args)
(let lp ((tried '()) (nss nameservers))
(if (null? nss)
(dns-error 'bad-address)
(receive (dns-msg hit-ns nss-with-no-reply)
(dns-query/cache query use-cache? protocol nss tried)
(if (check-answer dns-msg)
dns-msg
(let ((auth? (flags-authoritative? (header-flags
(message-header
(dns-message-reply dns-msg))))))
(if auth?
(dns-error 'bad-address)
;; other nameservers names are found in the nameserver-part,
;; but their ip-adresses are found in the additonal-rrs
(let ((other-nameservers
(filter (lambda (elem) (eq? (resource-record-type elem) (message-type a)))
(message-additionals (dns-message-reply dns-msg)))))
(lp (if (not (member hit-ns tried)) (cons hit-ns tried) tried)
(lset-union equal?
nss-with-no-reply
(lset-difference equal? other-nameservers tried))))))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Parsing of /etc/resolv.conf
@ -1241,147 +1250,147 @@
(car ns))))
;; checks the nameservers argument of the lookup functions.
;; computes the nameservers argument of the lookup functions.
;; if a nameserver-name is given and not a nameserver-ip
;; (dns-lookup-name nameserver) is called.
(define (check-args args)
;; use-cache? defaults to #t
(define (lookup-optional-args args)
(if (null? args)
(map ip-string->address32 (dns-find-nameserver-list))
(map (lambda (nameserver)
(cond
((address32? nameserver) nameserver)
((ip-string? nameserver) (ip-string->address32 nameserver))
(else (map (dns-lookup-name nameserver (dns-find-nameserver-list))))))
(car args))))
(values (map ip-string->address32 (dns-find-nameserver-list)) #t)
(values
(map (lambda (nameserver)
(cond
((address32? nameserver) nameserver)
((ip-string? nameserver) (ip-string->address32 nameserver))
(else (map (dns-lookup-name nameserver (dns-find-nameserver-list))))))
(car args))
(if (null? (cdr args))
#t
(cadr args)))))
;; dns-lookup with more options than dns-lookup-*
(define (dns-lookup name type . nameservers)
(let* ((maybe-ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(make-simple-query-dns-message
(random 256) maybe-ip-string type (message-class in))
(make-simple-query-dns-message (random 256) name type (message-class in))))
(use-cache? #t)
(protocol 'udp)
(nameservers (check-args nameservers))
(check-answer (lambda (dns-msg) #t))
(dns-msg (dns-get-information query use-cache? protocol nameservers check-answer))
(answers (message-answers (dns-message-reply dns-msg))))
dns-msg))
(define (dns-lookup name type . args)
(receive (nameservers use-cache?) (lookup-optional-args args)
(let* ((maybe-ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(make-simple-query-message
maybe-ip-string type (message-class in))
(make-simple-query-message name type (message-class in))))
(protocol (network-protocol udp))
(check-answer (lambda (dns-msg) #t))
(dns-msg (dns-get-information query protocol check-answer nameservers use-cache?))
(answers (message-answers (dns-message-reply dns-msg))))
dns-msg)))
;; looks up a hostname, returns an ip.
;; (dns-lookup-name <name> nameservers)
(define (dns-lookup-name name . nameservers)
(let* ((maybe-ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(dns-error 'not-a-hostname)
(make-simple-query-dns-message (random 256) name (message-type a) (message-class in))))
(use-cache? #t)
(protocol 'udp)
(nameservers (check-args nameservers))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply)))
(not (null? (filter-type answers (message-type a)))))))
(dns-msg (dns-get-information query use-cache? protocol nameservers check-answer))
(answers (filter-type (message-answers (dns-message-reply dns-msg)) (message-type a))))
(rr-data-a-ip (rr-data (car answers)))))
(define (dns-lookup-name name . args)
(receive (nameservers use-cache?) (lookup-optional-args args)
(let* ((maybe-ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(dns-error 'not-a-hostname)
(make-simple-query-message name (message-type a) (message-class in))))
(protocol (network-protocol udp))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply)))
(not (null? (filter-type answers (message-type a)))))))
(dns-msg (dns-get-information query protocol check-answer nameservers use-cache?))
(answers (filter-type (message-answers (dns-message-reply dns-msg)) (message-type a))))
(resource-record-data-a-ip (resource-record-data (car answers))))))
;; looks up an ip, returns a hostname
;; (dns-inverse-lookup <name> [nameserver])
(define (dns-lookup-ip ip . nameservers)
(let* ((maybe-ip-string (if (address32? ip)
(ip-string->in-addr-arpa (address32->ip-string ip))
(ip-string->in-addr-arpa ip)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(make-simple-query-dns-message (random 256) maybe-ip-string (message-type ptr) (message-class in))
(dns-error 'not-a-ip)))
(use-cache? #t)
(protocol 'udp)
(nameservers (check-args nameservers))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply)))
(not (null? (filter-type answers (message-type ptr)))))))
(dns-msg (dns-get-information query use-cache? protocol nameservers check-answer))
(answers (filter-type (message-answers (dns-message-reply dns-msg)) (message-type ptr))))
(rr-data-ptr-name (rr-data (car answers)))))
(define (dns-lookup-ip ip . args)
(receive (nameservers use-cache?) (lookup-optional-args args)
(let* ((maybe-ip-string (if (address32? ip)
(ip-string->in-addr-arpa (address32->ip-string ip))
(ip-string->in-addr-arpa ip)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(make-simple-query-message maybe-ip-string (message-type ptr) (message-class in))
(dns-error 'not-a-ip)))
(protocol (network-protocol udp))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply)))
(not (null? (filter-type answers (message-type ptr)))))))
(dns-msg (dns-get-information query protocol check-answer nameservers use-cache?))
(answers (filter-type (message-answers (dns-message-reply dns-msg)) (message-type ptr))))
(resource-record-data-ptr-name (resource-record-data (car answers))))))
(define dns-inverse-lookup dns-lookup-ip)
;; looks up an authoritative nameserver for a hostname
;; returns a list of nameservers
;; (dns-lookup-nameserver <name> [nameserver])
(define (dns-lookup-nameserver name . nameservers)
(let* ((maybe-ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(dns-error 'not-a-hostname)
(make-simple-query-dns-message
(random 256) name (message-type ns) (message-class in))))
(use-cache? #t)
(protocol 'udp)
(nameservers (check-args nameservers))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply))
(nameservers (message-nameservers reply)))
(or (not (null? (filter-type nameservers (message-type soa))))
(not (null? (filter-type answers (message-type ns))))))))
(dns-msg (dns-get-information query use-cache? protocol nameservers check-answer))
(reply (dns-message-reply dns-msg))
(soa (filter-type (message-nameservers reply) (message-type soa)))
(nss (filter-type (message-answers reply) (message-type ns)))
(add (filter-type (message-additionals reply) (message-type a))))
(if (null? nss)
(list (dns-lookup-name (rr-data-soa-mname (rr-data (car soa)))))
(map (lambda (elem) (rr-data-a-ip (rr-data elem))) add))))
(define (dns-lookup-nameserver name . args)
(receive (nameservers use-cache?) (lookup-optional-args args)
(let* ((maybe-ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if maybe-ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(dns-error 'not-a-hostname)
(make-simple-query-message
name (message-type ns) (message-class in))))
(protocol (network-protocol udp))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply))
(nameservers (message-nameservers reply)))
(or (not (null? (filter-type nameservers (message-type soa))))
(not (null? (filter-type answers (message-type ns))))))))
(dns-msg (dns-get-information query protocol check-answer nameservers use-cache?))
(reply (dns-message-reply dns-msg))
(soa (filter-type (message-nameservers reply) (message-type soa)))
(nss (filter-type (message-answers reply) (message-type ns)))
(add (filter-type (message-additionals reply) (message-type a))))
(if (null? nss)
(list (dns-lookup-name (resource-record-data-soa-mname (resource-record-data (car soa)))))
(map (lambda (elem) (resource-record-data-a-ip (resource-record-data elem))) add)))))
;; looks up a mail-exchanger for a hostname.
;; returns a list of mail-exchanger, sorted by their preference
;; if there are no mx-records in the answer-section,
;; implementation based on RFC2821
;; (dns-lookup-mail-exchanger <name> [nameserver])
(define (dns-lookup-mail-exchanger name . nameservers)
(let* ((ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(dns-error 'not-a-hostname)
(make-simple-query-dns-message
(random 256) name (message-type mx) (message-class in))))
(use-cache? #t)
(protocol 'tcp)
(nameservers (check-args nameservers))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply))
(nameservers (message-nameservers reply)))
(or (not (null? (filter-type answers (message-type mx))))
(not (null? (filter-type answers (message-type cname))))
(not (null? (filter-type answers (message-type a))))))))
(dns-msg (dns-get-information query use-cache? protocol nameservers check-answer))
(reply (dns-message-reply dns-msg))
(mx (filter-type (message-answers reply) (message-type mx)))
(soa (filter-type (message-nameservers reply)(message-type soa)))
(cname (filter-type (message-answers reply) (message-type cname)))
(a (filter-type (message-answers reply) (message-type a))))
(define (dns-lookup-mail-exchanger name . args)
(receive (nameservers use-cache?) (lookup-optional-args args)
(let* ((ip-string (if (address32? name)
(ip-string->in-addr-arpa (address32->ip-string name))
(ip-string->in-addr-arpa name)))
(query (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
(dns-error 'not-a-hostname)
(make-simple-query-message
name (message-type mx) (message-class in))))
(protocol (network-protocol tcp))
(check-answer (lambda (dns-msg)
(let* ((reply (dns-message-reply dns-msg))
(answers (message-answers reply))
(nameservers (message-nameservers reply)))
(or (not (null? (filter-type answers (message-type mx))))
(not (null? (filter-type answers (message-type cname))))
(not (null? (filter-type answers (message-type a))))))))
(dns-msg (dns-get-information query protocol check-answer nameservers use-cache?))
(reply (dns-message-reply dns-msg))
(mx (filter-type (message-answers reply) (message-type mx)))
(soa (filter-type (message-nameservers reply)(message-type soa)))
(cname (filter-type (message-answers reply) (message-type cname)))
(a (filter-type (message-answers reply) (message-type a))))
(cond
((not (null? a))
(list (rr-data-a-ip (rr-data (car a)))))
((not (null? cname))
(dns-lookup-mail-exchanger (rr-data-cname-name (rr-data (car cname)))))
((null? mx)
(list (rr-data-soa-rname (rr-data (car soa)))))
(else
(map (lambda (elem) (rr-data-mx-exchanger (rr-data elem))) (sort-by-preference mx))))))
(cond
((not (null? a))
(list (resource-record-data-a-ip (resource-record-data (car a)))))
((not (null? cname))
(dns-lookup-mail-exchanger (resource-record-data-cname-name (resource-record-data (car cname)))))
((null? mx)
(list (resource-record-data-soa-rname (resource-record-data (car soa)))))
(else
(map (lambda (elem) (resource-record-data-mx-exchanger (resource-record-data elem))) (sort-by-preference mx)))))))
;;; pretty-prints a dns-msg
(define (pretty-print-dns-message dns-msg . maybe-port)
@ -1413,8 +1422,8 @@
"not found in cache"))
(d 1 "PROTOCOL" (let ((protocol (dns-message-protocol dns-msg)))
(cond
((eq? protocol 'tcp) "TCP")
((eq? protocol 'udp) "UDP"))))
((eq? protocol (network-protocol tcp)) "TCP")
((eq? protocol (network-protocol udp)) "UDP"))))
(d 1 "TRIED-NAMESERVERS" (if (> (length (dns-message-tried-nameservers dns-msg)) 1)
(begin
(display " had perform recursion: ")
@ -1453,73 +1462,52 @@
(d 4 "name " (question-name dns-msg))
(d 4 "type " (message-type-name (question-type dns-msg)))
(d 4 "class" (message-class-name (question-class dns-msg)))))
((rr? dns-msg)
((resource-record? dns-msg)
(begin
(d 4 "name " (rr-name dns-msg))
(d 4 "type "(message-type-name (rr-type dns-msg)))
(d 4 "class" (message-class-name (rr-class dns-msg)))
(d 4 "ttl " (rr-ttl dns-msg))
(d 4 "data " "") (show-dns-message (rr-data dns-msg))))
((rr-data-a? dns-msg)
(d 5 "ip " (rr-data-a-ip dns-msg)))
((rr-data-ns? dns-msg)
(d 5 "name " (rr-data-ns-name dns-msg)))
((rr-data-cname? dns-msg)
(d 5 "name " (rr-data-cname-name dns-msg)))
((rr-data-mx? dns-msg)
(d 4 "name " (resource-record-name dns-msg))
(d 4 "type "(message-type-name (resource-record-type dns-msg)))
(d 4 "class" (message-class-name (resource-record-class dns-msg)))
(d 4 "ttl " (resource-record-ttl dns-msg))
(d 4 "data " "") (show-dns-message (resource-record-data dns-msg))))
((resource-record-data-a? dns-msg)
(d 5 "ip " (resource-record-data-a-ip dns-msg)))
((resource-record-data-ns? dns-msg)
(d 5 "name " (resource-record-data-ns-name dns-msg)))
((resource-record-data-cname? dns-msg)
(d 5 "name " (resource-record-data-cname-name dns-msg)))
((resource-record-data-mx? dns-msg)
(begin
(d 5 "preference " (rr-data-mx-preference dns-msg))
(d 5 "exchanger " (rr-data-mx-exchanger dns-msg))))
((rr-data-ptr? dns-msg)
(d 5 "name " (rr-data-ptr-name dns-msg)))
((rr-data-soa? dns-msg)
(d 5 "preference " (resource-record-data-mx-preference dns-msg))
(d 5 "exchanger " (resource-record-data-mx-exchanger dns-msg))))
((resource-record-data-ptr? dns-msg)
(d 5 "name " (resource-record-data-ptr-name dns-msg)))
((resource-record-data-soa? dns-msg)
(begin
(d 5 "mname " (rr-data-soa-mname dns-msg))
(d 5 "rname " (rr-data-soa-rname dns-msg))
(d 5 "serial " (rr-data-soa-serial dns-msg))
(d 5 "refresh " (rr-data-soa-refresh dns-msg))
(d 5 "expire " (rr-data-soa-expire dns-msg))
(d 5 "minimum " (rr-data-soa-expire dns-msg))))
(d 5 "mname " (resource-record-data-soa-mname dns-msg))
(d 5 "rname " (resource-record-data-soa-rname dns-msg))
(d 5 "serial " (resource-record-data-soa-serial dns-msg))
(d 5 "refresh " (resource-record-data-soa-refresh dns-msg))
(d 5 "expire " (resource-record-data-soa-expire dns-msg))
(d 5 "minimum " (resource-record-data-soa-expire dns-msg))))
;; ###
((rr-data-hinfo? dns-msg)
(d 5 "data " (rr-data-hinfo-data dns-msg)))
((rr-data-txt? dns-msg)
(d 5 "text " (rr-data-txt-text dns-msg)))
((rr-data-wks? dns-msg)
(d 5 "data " (rr-data-wks-data dns-msg)))
((resource-record-data-hinfo? dns-msg)
(d 5 "data " (resource-record-data-hinfo-data dns-msg)))
((resource-record-data-txt? dns-msg)
(d 5 "text " (resource-record-data-txt-text dns-msg)))
((resource-record-data-wks? dns-msg)
(d 5 "data " (resource-record-data-wks-data dns-msg)))
))
(show-dns-message dns-msg)))))
(define *fqdn-lock* (make-lock))
(define *fqdn-cache* '())
(define (socket-address->fqdn addr cache?)
(define (socket-address->fqdn addr . args)
(receive (ip32 port)
(socket-address->internet-address addr)
(internet-address->fqdn ip32 cache?)))
(apply dns-lookup-ip ip32 args)))
(define (internet-address->fqdn ip32 cache?)
(if cache?
(begin
(obtain-lock *fqdn-lock*)
(cond
((assv ip32 *fqdn-cache*) =>
(lambda (pair)
(release-lock *fqdn-lock*)
(cdr pair)))
(else
(release-lock *fqdn-lock*)
(let ((fqdn (dns-lookup-ip ip32)))
(set! *fqdn-cache*
(cons (cons ip32 fqdn) *fqdn-cache*))
fqdn))))
(dns-lookup-ip ip32)))
(define (is-fqdn? name)
(define (fqdn? name)
(regexp-search? (rx #\.) name))
(define (maybe-dns-lookup-name name)
(define (maybe-dns-lookup-name name . args)
(call-with-current-continuation
(lambda (k)
(with-handler (lambda (cond more)
@ -1527,9 +1515,9 @@
(k #f)
(more)))
(lambda ()
(dns-lookup-name name))))))
(dns-lookup-name name args))))))
(define (maybe-dns-lookup-ip ip-addr)
(define (maybe-dns-lookup-ip ip-addr . args)
(call-with-current-continuation
(lambda (k)
(with-handler (lambda (cond more)
@ -1537,7 +1525,7 @@
(k #f)
(more)))
(lambda ()
(dns-lookup-ip ip-addr))))))
(apply dns-lookup-ip ip-addr args))))))
(define (domains-for-search)
(cond ((assoc 'domain (resolv.conf))
@ -1548,20 +1536,21 @@
(cdr pair)))
(else '())))
(define (host-fqdn name-or-socket-address)
(define (host-fqdn name-or-socket-address . args)
(if (socket-address? name-or-socket-address)
(socket-address->fqdn name-or-socket-address #f)
(apply socket-address->fqdn name-or-socket-address args)
(let ((name name-or-socket-address))
(if (is-fqdn? name)
name
(let lp ((domains (domains-for-search)))
(if (null? domains)
#f
(cond ((maybe-dns-lookup-name (string-append name "." (car domains)))
(cond ((apply maybe-dns-lookup-name
(string-append name "." (car domains)) args)
=> (lambda (ip)
(dns-lookup-ip ip)))
(apply dns-lookup-ip ip args)))
(else (lp (cdr domains))))))))))
(define (system-fqdn)
(host-fqdn (system-name)))
(define (system-fqdn . args)
(apply host-fqdn (system-name) args))