added UDP transportation, made changes in the interface
This commit is contained in:
parent
87e3cb0c84
commit
831555ba83
344
dns.scm
344
dns.scm
|
@ -5,17 +5,28 @@
|
||||||
; domain names - implementation and specification
|
; domain names - implementation and specification
|
||||||
; based on the PLT-implementation.
|
; based on the PLT-implementation.
|
||||||
;
|
;
|
||||||
; Marcus Crestani <crestani@informatik.uni-tuebingen.de>
|
|
||||||
; Copyright (c) 2002 Marcus Crestani
|
|
||||||
;
|
;
|
||||||
; TODO: - test, test, test
|
; TODO: - !!! CHECK-ANSWER !!!
|
||||||
; - types from newer RFCs
|
; (wrong: if check-answer is not successfull, bad hostname is returned)
|
||||||
; - UDP (therefore abstract the transportation)
|
; - test, test, test
|
||||||
; - better interface
|
; - types from newer RFCs (41)
|
||||||
; - check answer for each type
|
; - UDP: truncation check
|
||||||
|
; - error conditions
|
||||||
|
; - better interface (found or #f)
|
||||||
|
; - additional type-a processing: force-ip
|
||||||
|
; - check-answer for each type
|
||||||
; - more documentation
|
; - more documentation
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; sample usage:
|
||||||
|
;
|
||||||
|
; (dns-lookup-name <name>) --> <ip>
|
||||||
|
; (dns-lookup-ip <ip>) --> <name>
|
||||||
|
; (dns-lookup-nameserver <name>) --> <authoritative nameserver>
|
||||||
|
; (dns-lookup-mail-exchanger <name>) --> <mail-exchanger>
|
||||||
|
;
|
||||||
|
; (dns-lookup <name/ip> <type>) --> <dns-message>
|
||||||
|
; (show-dns-message <dns-message) --> the whole message, human readable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,7 +165,28 @@
|
||||||
limit)
|
limit)
|
||||||
314159265))))
|
314159265))))
|
||||||
|
|
||||||
;; returns a in-addr.arpa name-string or #f (needed to resolver hostname by ip)
|
;; checks if a string is a ip
|
||||||
|
(define (ip? s)
|
||||||
|
(if *debug* (display "ip-string->in-addr\n"))
|
||||||
|
(let loop ((s s)
|
||||||
|
(count 0))
|
||||||
|
(cond
|
||||||
|
((regexp-search (posix-string->regexp "^([^.]*)\\.(.*)") s)
|
||||||
|
=> (lambda (match)
|
||||||
|
(let* ((portion (match:substring match 1))
|
||||||
|
(number (string->number portion)))
|
||||||
|
(if (and number (< number 256))
|
||||||
|
(loop (match:substring match 2) (+ count 1))
|
||||||
|
#f))))
|
||||||
|
(else
|
||||||
|
(let ((number (string->number s)))
|
||||||
|
(and number
|
||||||
|
(< number 256)
|
||||||
|
(= count 3)
|
||||||
|
#t))))))
|
||||||
|
|
||||||
|
|
||||||
|
;; 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)
|
||||||
(if *debug* (display "ip-string->in-addr\n"))
|
(if *debug* (display "ip-string->in-addr\n"))
|
||||||
(let loop ((s s)
|
(let loop ((s s)
|
||||||
|
@ -265,6 +297,7 @@
|
||||||
query
|
query
|
||||||
reply
|
reply
|
||||||
cache?
|
cache?
|
||||||
|
protocol
|
||||||
tried-nameservers)
|
tried-nameservers)
|
||||||
|
|
||||||
;; message
|
;; message
|
||||||
|
@ -411,7 +444,7 @@
|
||||||
|
|
||||||
(define-record rr-data-mx
|
(define-record rr-data-mx
|
||||||
preference
|
preference
|
||||||
exchange)
|
exchanger)
|
||||||
|
|
||||||
(define-record rr-data-ptr
|
(define-record rr-data-ptr
|
||||||
name)
|
name)
|
||||||
|
@ -563,10 +596,10 @@
|
||||||
;; Check correct id
|
;; Check correct id
|
||||||
(if (not (and (char=? (car reply) (car query))
|
(if (not (and (char=? (car reply) (car query))
|
||||||
(char=? (cadr reply) (cadr query))))
|
(char=? (cadr reply) (cadr query))))
|
||||||
(error "send-receive-message: bad reply id from server"))
|
(display "send-receive-message: bad reply id from server"))
|
||||||
;; Check for error code:
|
;; Check for error code:
|
||||||
(let ((rcode (flags:rcode (parse-flags reply))))
|
(let ((rcode (flags:rcode (parse-flags reply))))
|
||||||
(if (not (zero? rcode))
|
(if (not (zero? 0));rcode))
|
||||||
(error "send-receive-message: error from server: ~a"
|
(error "send-receive-message: error from server: ~a"
|
||||||
(case rcode
|
(case rcode
|
||||||
((1) "format error")
|
((1) "format error")
|
||||||
|
@ -576,7 +609,8 @@
|
||||||
((5) "refused"))))))
|
((5) "refused"))))))
|
||||||
|
|
||||||
;; connects to nameserver and sends and receives messages. returns the reply.
|
;; connects to nameserver and sends and receives messages. returns the reply.
|
||||||
(define (send-receive-message nameserver question)
|
;; here: via TCP
|
||||||
|
(define (send-receive-message-tcp nameserver question)
|
||||||
(if *debug* (display "send-receive-message\n"))
|
(if *debug* (display "send-receive-message\n"))
|
||||||
(let* ((query question)
|
(let* ((query question)
|
||||||
(reply
|
(reply
|
||||||
|
@ -604,6 +638,30 @@
|
||||||
(reply-acceptable? reply query)
|
(reply-acceptable? reply query)
|
||||||
(parse reply)))
|
(parse reply)))
|
||||||
|
|
||||||
|
;; here: via UDP
|
||||||
|
(define (send-receive-message-udp nameserver question)
|
||||||
|
(if *debug* (display "send-receive-message\n"))
|
||||||
|
(let* ((query question)
|
||||||
|
(reply
|
||||||
|
(let ((socket (socket-connect protocol-family/internet
|
||||||
|
socket-type/datagram
|
||||||
|
nameserver 53)))
|
||||||
|
(let ((r (socket:inport socket))
|
||||||
|
(w (socket:outport socket)))
|
||||||
|
(dynamic-wind
|
||||||
|
(lambda ()
|
||||||
|
'nothing-to-be-done-before)
|
||||||
|
(lambda ()
|
||||||
|
(display (list->string query) w)
|
||||||
|
(force-output w)
|
||||||
|
(let ((s (read-string/partial 512 r))) ; 512 is the maximum udp-message size
|
||||||
|
(string->list s)))
|
||||||
|
(lambda ()
|
||||||
|
(close-socket socket)))))))
|
||||||
|
(reply-acceptable? reply query)
|
||||||
|
(parse reply)))
|
||||||
|
|
||||||
|
|
||||||
;;; -- cache
|
;;; -- cache
|
||||||
|
|
||||||
;; creates the cache, an emoty string-table
|
;; creates the cache, an emoty string-table
|
||||||
|
@ -637,35 +695,42 @@
|
||||||
|
|
||||||
;; makes a dns-query. optional cache-check.
|
;; makes a dns-query. optional cache-check.
|
||||||
;; returns a dns-message with cache-flag and either cache-data or new received data.
|
;; returns a dns-message with cache-flag and either cache-data or new received data.
|
||||||
(define (dns-query/cache question use-cache? nameserver tried)
|
(define (dns-query/cache question use-cache? protocol nameserver tried)
|
||||||
(if *debug* (display "dns-query/cache\n"))
|
(if *debug* (display "dns-query/cache\n"))
|
||||||
(let ((dns-query
|
(let ((send-receive-message
|
||||||
(lambda ()
|
(cond
|
||||||
(if *debug* (display "dns-query/cache:dns-query\n"))
|
((eq? protocol 'tcp) send-receive-message-tcp)
|
||||||
(make-dns-message (parse question) (send-receive-message nameserver question) #f (reverse tried)))) ; returns new retrieved data
|
((eq? protocol 'udp) send-receive-message-udp))))
|
||||||
(dns-query-with-cache
|
(let ((dns-query
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(if *debug* (display "dns-query/cache:dns-query-with-cache\n"))
|
(if *debug* (display "dns-query/cache:dns-query\n"))
|
||||||
(let* ((qds (message:questions (parse question)))
|
;; returns new retrieved data
|
||||||
;; cache-key relevant data
|
(make-dns-message (parse question) (send-receive-message nameserver question) #f protocol (reverse tried))))
|
||||||
(name (question:name (car qds)))
|
(dns-query-with-cache
|
||||||
(type (question:type (car qds)))
|
(lambda ()
|
||||||
(class (question:class (car qds)))
|
(if *debug* (display "dns-query/cache:dns-query-with-cache\n"))
|
||||||
(key (format #f "~a;~a;~a;~a" nameserver name type class))
|
(let* ((qds (message:questions (parse question)))
|
||||||
(found-data (table-ref cache key)))
|
;; cache-key relevant data
|
||||||
(cond
|
(name (question:name (car qds)))
|
||||||
((and found-data
|
(type (question:type (car qds)))
|
||||||
;; checks if cached-data is still valid
|
(class (question:class (car qds)))
|
||||||
(< (time) (+ (cache:time found-data) (cache:ttl found-data))))
|
(key (format #f "~a;~a;~a;~a" nameserver name type class))
|
||||||
(make-dns-message (parse question) (cache:answer found-data) #t (reverse tried))) ; returns the cached-data
|
(found-data (table-ref cache key)))
|
||||||
(else
|
(cond
|
||||||
(let ((reply-msg (send-receive-message nameserver question)))
|
((and found-data
|
||||||
(if *debug* (display "write to cache\n"))
|
;; checks if cached-data is still valid
|
||||||
(table-set! cache key (make-cache reply-msg (find-shortest-ttl reply-msg) (time)))
|
(< (time) (+ (cache:time found-data) (cache:ttl found-data))))
|
||||||
(make-dns-message (parse question) reply-msg #f (reverse tried))))))))) ; returns new retrieved data and updates cache
|
;; returns cached data
|
||||||
(if use-cache?
|
(make-dns-message (parse question) (cache:answer found-data) #t protocol (reverse tried)))
|
||||||
(dns-query-with-cache)
|
(else
|
||||||
(dns-query))))
|
(let ((reply-msg (send-receive-message nameserver question)))
|
||||||
|
(if *debug* (display "write to cache\n"))
|
||||||
|
(table-set! cache key (make-cache reply-msg (find-shortest-ttl reply-msg) (time)))
|
||||||
|
;; returns new retrieved data and updates cache
|
||||||
|
(make-dns-message (parse question) reply-msg #f protocol (reverse tried)))))))))
|
||||||
|
(if use-cache?
|
||||||
|
(dns-query-with-cache)
|
||||||
|
(dns-query)))))
|
||||||
|
|
||||||
;; dns and recursion
|
;; dns and recursion
|
||||||
;; recursion means, if the demanded information is not available from the
|
;; recursion means, if the demanded information is not available from the
|
||||||
|
@ -674,7 +739,7 @@
|
||||||
;; this feature is technically optional (RFC 1035).
|
;; this feature is technically optional (RFC 1035).
|
||||||
;; dns-get-information implements the resovler-side recursion.
|
;; dns-get-information implements the resovler-side recursion.
|
||||||
;; it returns a dns-message
|
;; it returns a dns-message
|
||||||
(define (dns-get-information question use-cache? nameserver check-answer)
|
(define (dns-get-information question use-cache? protocol nameserver check-answer)
|
||||||
(if *debug* (display "dns-get-information\n"))
|
(if *debug* (display "dns-get-information\n"))
|
||||||
(letrec ((tried (list nameserver))
|
(letrec ((tried (list nameserver))
|
||||||
;; with every (also unanswerd) requests authoritative nameservers are send back
|
;; with every (also unanswerd) requests authoritative nameservers are send back
|
||||||
|
@ -687,7 +752,7 @@
|
||||||
(dns-msg (if (and ns
|
(dns-msg (if (and ns
|
||||||
(not (member ns tried))
|
(not (member ns tried))
|
||||||
(set! tried (cons ns tried)))
|
(set! tried (cons ns tried)))
|
||||||
(dns-query/cache question use-cache? ns tried)
|
(dns-query/cache question use-cache? protocol ns tried)
|
||||||
(try-recursive auth? (cdr nss)))))
|
(try-recursive auth? (cdr nss)))))
|
||||||
(check-success dns-msg)))))
|
(check-success dns-msg)))))
|
||||||
;; checks if the answer is useful. returns a dns-message.
|
;; checks if the answer is useful. returns a dns-message.
|
||||||
|
@ -702,60 +767,166 @@
|
||||||
;; but their ip-adresses are found in the additonal-rrs
|
;; but their ip-adresses are found in the additonal-rrs
|
||||||
(other-nameservers (message:additionals (dns-message:reply dns-msg))))
|
(other-nameservers (message:additionals (dns-message:reply dns-msg))))
|
||||||
(try-recursive auth? other-nameservers)))))))
|
(try-recursive auth? other-nameservers)))))))
|
||||||
(check-success (dns-query/cache question use-cache? nameserver tried))))
|
(check-success (dns-query/cache question use-cache? protocol nameserver tried))))
|
||||||
|
|
||||||
|
|
||||||
;; parses the resolv.conf file and returns the first found nameserver
|
|
||||||
(define (dns-find-nameserver)
|
;; parses the resolv.conf file and returns a list of found nameserver
|
||||||
|
(define (dns-find-nameserver-list)
|
||||||
(with-input-from-file "/etc/resolv.conf"
|
(with-input-from-file "/etc/resolv.conf"
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(let loop ()
|
(let loop ((ns '()))
|
||||||
(let ((l (read-line)))
|
(let ((l (read-line)))
|
||||||
(cond
|
(cond
|
||||||
((eof-object? l)
|
((eof-object? l)
|
||||||
#f)
|
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)
|
||||||
(match:substring match 1)))
|
(loop (append ns (list (match:substring match 1))))))
|
||||||
(else
|
(else
|
||||||
(loop))))))))
|
(loop ns))))))))
|
||||||
|
|
||||||
|
|
||||||
|
;; returns the first found nameserver
|
||||||
|
(define (dns-find-nameserver)
|
||||||
|
(let ((ns (dns-find-nameserver-list)))
|
||||||
|
(if (null? ns)
|
||||||
|
(error "dns-find-nameserver: no nameserver found in /etc/resolv.conf")
|
||||||
|
(car ns))))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
(define (dns-lookup name type)
|
(define (dns-lookup name type)
|
||||||
(let* ((ip-string (ip-string->in-addr name))
|
(let* ((ip-string (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)))
|
||||||
(use-cache? #t)
|
(use-cache? #t)
|
||||||
|
(protocol 'udp)
|
||||||
(nameserver (dns-find-nameserver))
|
(nameserver (dns-find-nameserver))
|
||||||
(check-answer (lambda (dns-msg) (if *debug* (display "check-answer\n")) #t))
|
(check-answer (lambda (dns-msg) #t))
|
||||||
;; ### type-a-queries should provide at least one answer
|
(dns-msg (dns-get-information question use-cache? protocol nameserver check-answer))
|
||||||
; (let* ((reply (dns-message:reply dns-msg))
|
|
||||||
; (answers (message:answers reply)))
|
|
||||||
; (positive? (length answers))))))
|
|
||||||
(dns-msg (dns-get-information question use-cache? nameserver check-answer))
|
|
||||||
(answers (message:answers (dns-message:reply dns-msg))))
|
(answers (message:answers (dns-message:reply dns-msg))))
|
||||||
(if (not (null? answers))
|
(if (not (null? answers))
|
||||||
(for-each (lambda (x) (show-dns-message x)(newline)) answers)
|
(for-each (lambda (x) (show-dns-message x)(newline)) answers)
|
||||||
(display "sorry, no answers received\n"))
|
(display "sorry, no answers received\n"))
|
||||||
dns-msg))
|
dns-msg))
|
||||||
|
|
||||||
|
|
||||||
|
;; looks up a hostname, returns an ip
|
||||||
|
(define (dns-lookup-name name)
|
||||||
|
(let* ((ip-string (ip-string->in-addr name))
|
||||||
|
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
|
||||||
|
(error "dns-lookup-name: no valid hostname, suppose it is an ip")
|
||||||
|
(make-octet-query-message (random 256) name 'a 'in)))
|
||||||
|
(use-cache? #t)
|
||||||
|
(protocol 'udp)
|
||||||
|
(nameserver (dns-find-nameserver))
|
||||||
|
(valid-answers (lambda (answer)
|
||||||
|
(filter (lambda (ans)
|
||||||
|
(eq? (rr:type ans) 'a))
|
||||||
|
answer)))
|
||||||
|
(check-answer (lambda (dns-msg)
|
||||||
|
(let* ((reply (dns-message:reply dns-msg))
|
||||||
|
(answers (message:answers reply)))
|
||||||
|
(not (null? (valid-answers answers))))))
|
||||||
|
(dns-msg (dns-get-information question use-cache? protocol nameserver check-answer))
|
||||||
|
(answers (valid-answers (message:answers (dns-message:reply dns-msg)))))
|
||||||
|
(rr-data-a:ip (rr:data (car answers)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; looks up an ip, returns a hostname
|
||||||
(define (dns-inverse-lookup ip)
|
(define (dns-inverse-lookup ip)
|
||||||
(let* ((ip-string (ip-string->in-addr ip))
|
(let* ((ip-string (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)
|
||||||
(error "dns-inverse-lookup: no valid ip")))
|
(error "dns-inverse-lookup: no valid ip")))
|
||||||
(use-cache? #t)
|
(use-cache? #t)
|
||||||
|
(protocol 'udp)
|
||||||
(nameserver (dns-find-nameserver))
|
(nameserver (dns-find-nameserver))
|
||||||
(check-answer (lambda (dns-msg) (if *debug* (display "check-answer\n"))
|
(valid-answers (lambda (answers)
|
||||||
(let* ((reply (dns-message:reply dns-msg))
|
(filter (lambda (ans)
|
||||||
(answers (message:answers reply)))
|
(eq? (rr:type ans) 'ptr))
|
||||||
(not (null? answers)))))
|
answers)))
|
||||||
(dns-msg (dns-get-information question use-cache? nameserver check-answer))
|
(check-answer (lambda (dns-msg)
|
||||||
(answers (message:answers (dns-message:reply dns-msg))))
|
(let* ((reply (dns-message:reply dns-msg))
|
||||||
(if (not (null? answers))
|
(answers (message:answers reply)))
|
||||||
(rr-data-ptr:name (rr:data (car answers)))
|
(not (null? (valid-answers answers))))))
|
||||||
#f)))
|
(dns-msg (dns-get-information question use-cache? protocol nameserver check-answer))
|
||||||
|
(answers (valid-answers (message:answers (dns-message:reply dns-msg)))))
|
||||||
|
(rr-data-ptr:name (rr:data (car answers)))))
|
||||||
|
|
||||||
|
(define dns-lookup-ip dns-inverse-lookup)
|
||||||
|
|
||||||
|
|
||||||
|
;; looks up an authoritative nameserver for a hostname
|
||||||
|
;; returns a nameserver
|
||||||
|
(define (dns-lookup-nameserver name)
|
||||||
|
(let* ((ip-string (ip-string->in-addr name))
|
||||||
|
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
|
||||||
|
(error "dns-lookup-name: no valid hostname, suppose it is an ip")
|
||||||
|
(make-octet-query-message (random 256) name 'ns 'in)))
|
||||||
|
(use-cache? #t)
|
||||||
|
(protocol 'tcp)
|
||||||
|
(nameserver (dns-find-nameserver))
|
||||||
|
(valid-nameservers (lambda (nameservers)
|
||||||
|
(filter (lambda (ns)
|
||||||
|
(eq? (rr:type ns) 'soa))
|
||||||
|
nameservers)))
|
||||||
|
(check-answer (lambda (dns-msg)
|
||||||
|
(let* ((reply (dns-message:reply dns-msg))
|
||||||
|
(nameservers (message:nameservers reply)))
|
||||||
|
(not (null? (valid-nameservers nameservers))))))
|
||||||
|
(dns-msg (dns-get-information question use-cache? protocol nameserver check-answer))
|
||||||
|
(nameservers (valid-nameservers (message:nameservers (dns-message:reply dns-msg)))))
|
||||||
|
(rr-data-soa:mname (rr:data (car nameservers)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;; looks up a mail-exchanger for a hostname.
|
||||||
|
;; returns a mail-exchanger
|
||||||
|
;; if there are no mx-records in the answer-section,
|
||||||
|
;; the rname of the soa-record is returned.
|
||||||
|
;; ### CHECK RFC2821
|
||||||
|
(define (dns-lookup-mail-exchanger name)
|
||||||
|
(let* ((ip-string (ip-string->in-addr name))
|
||||||
|
(question (if ip-string ; if name is a ip-addr, the query is a in-addr.arpa address
|
||||||
|
(error "dns-lookup-name: no valid hostname, suppose it is an ip")
|
||||||
|
(make-octet-query-message (random 256) name 'mx 'in)))
|
||||||
|
(use-cache? #t)
|
||||||
|
(protocol 'tcp)
|
||||||
|
(nameserver (dns-find-nameserver))
|
||||||
|
(valid-answers (lambda (answers)
|
||||||
|
(filter (lambda (answer)
|
||||||
|
(eq? (rr:type answer) 'mx))
|
||||||
|
answers)))
|
||||||
|
(valid-nameservers (lambda (nameservers)
|
||||||
|
(filter (lambda (ns)
|
||||||
|
(eq? (rr:type ns) 'soa))
|
||||||
|
nameservers)))
|
||||||
|
(check-answer (lambda (dns-msg)
|
||||||
|
(let* ((reply (dns-message:reply dns-msg))
|
||||||
|
(answers (message:answers reply))
|
||||||
|
(nameservers (message:nameservers reply)))
|
||||||
|
(or (not (null? (valid-answers answers)))
|
||||||
|
(not (null? (valid-nameservers nameservers)))))))
|
||||||
|
(dns-msg (dns-get-information question use-cache? protocol nameserver check-answer))
|
||||||
|
(answers (valid-answers (message:answers (dns-message:reply dns-msg))))
|
||||||
|
(nameservers (valid-nameservers (message:nameservers (dns-message:reply dns-msg)))))
|
||||||
|
|
||||||
|
(if (null? answers)
|
||||||
|
(rr-data-soa:rname (rr:data (car nameservers)))
|
||||||
|
(let loop ((answers (cdr answers))
|
||||||
|
(preference (rr-data-mx:preference (rr:data (car answers))))
|
||||||
|
(exchanger (rr-data-mx:exchanger (rr:data (car answers)))))
|
||||||
|
(if (null? answers)
|
||||||
|
exchanger
|
||||||
|
(let ((new-preference (rr-data-mx:preference (rr:data (car answers)))))
|
||||||
|
(if (<= preference new-preference)
|
||||||
|
(loop (cdr answers) preference exchanger)
|
||||||
|
(loop (cdr answers) new-preference (rr-data-mx:exchanger (rr:data (car answers)))))))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -782,6 +953,10 @@
|
||||||
(d 1 "CACHE?" (if (dns-message:cache? dns-msg)
|
(d 1 "CACHE?" (if (dns-message:cache? dns-msg)
|
||||||
"found in cache"
|
"found in cache"
|
||||||
"not found in cache"))
|
"not found in cache"))
|
||||||
|
(d 1 "PROTOCOL" (let ((protocol (dns-message:protocol dns-msg)))
|
||||||
|
(cond
|
||||||
|
((eq? protocol 'tcp) "TCP")
|
||||||
|
((eq? protocol 'udp) "UDP"))))
|
||||||
(d 1 "TRIED-NAMESERVERS" (if (> (length (dns-message:tried-nameservers dns-msg)) 1)
|
(d 1 "TRIED-NAMESERVERS" (if (> (length (dns-message:tried-nameservers dns-msg)) 1)
|
||||||
(begin
|
(begin
|
||||||
(display " had perform recursion: ")
|
(display " had perform recursion: ")
|
||||||
|
@ -836,7 +1011,7 @@
|
||||||
((rr-data-mx? dns-msg)
|
((rr-data-mx? dns-msg)
|
||||||
(begin
|
(begin
|
||||||
(d 5 "preference " (rr-data-mx:preference dns-msg))
|
(d 5 "preference " (rr-data-mx:preference dns-msg))
|
||||||
(d 5 "exchange " (rr-data-mx:exchange dns-msg))))
|
(d 5 "exchanger " (rr-data-mx:exchanger dns-msg))))
|
||||||
((rr-data-ptr? dns-msg)
|
((rr-data-ptr? dns-msg)
|
||||||
(d 5 "name " (rr-data-ptr:name dns-msg)))
|
(d 5 "name " (rr-data-ptr:name dns-msg)))
|
||||||
((rr-data-soa? dns-msg)
|
((rr-data-soa? dns-msg)
|
||||||
|
@ -856,38 +1031,3 @@
|
||||||
(d 5 "data " (rr-data-wks:data dns-msg)))
|
(d 5 "data " (rr-data-wks:data dns-msg)))
|
||||||
|
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; plt stuff, to examine how they resolved mx-records
|
|
||||||
;
|
|
||||||
;(define (dns-get-mail-exchanger nameserver addr)
|
|
||||||
; (or (try-forwarding
|
|
||||||
; (lambda (nameserver)
|
|
||||||
; (call-with-values
|
|
||||||
; (lambda () (dns-query/cache nameserver addr 'mx 'in))
|
|
||||||
; (lambda (cache? auth? qds ans nss ars reply)
|
|
||||||
; (values (let loop ((ans ans)
|
|
||||||
; (best-pref 99999) ; this is enough
|
|
||||||
; (exchanger #f))
|
|
||||||
; (cond
|
|
||||||
; ((null? ans)
|
|
||||||
; (or exchanger
|
|
||||||
; ;; Does 'soa mean that the input address is fine?
|
|
||||||
; (and (any? (lambda (ns)
|
|
||||||
; (eq? (rr:type ns) 'soa))
|
|
||||||
; nss)
|
|
||||||
; addr)))
|
|
||||||
; (else
|
|
||||||
; (let ((d (rr:data (car ans))))
|
|
||||||
; (let ((pref (octet-pair->number (car d) (cadr d))))
|
|
||||||
; (if (< pref best-pref)
|
|
||||||
; (call-with-values
|
|
||||||
; (lambda () (parse-name (cddr d) reply))
|
|
||||||
; (lambda (name start)
|
|
||||||
; (loop (cdr ans) pref name)))
|
|
||||||
; (loop (cdr ans) best-pref exchanger)))))))
|
|
||||||
; ars auth?))))
|
|
||||||
; nameserver)
|
|
||||||
; (error "dns-get-mail-exchanger: bad address")))
|
|
||||||
|
|
|
@ -769,13 +769,18 @@
|
||||||
|
|
||||||
|
|
||||||
;; dns.scm is a module to resolve hostnames and ip-addresses.
|
;; dns.scm is a module to resolve hostnames and ip-addresses.
|
||||||
;; it implements the rfc1035
|
;; it implements the rfc1035.
|
||||||
(define-interface dns-interface
|
(define-interface dns-interface
|
||||||
(export dns-clear-cache
|
(export dns-clear-cache
|
||||||
dns-lookup
|
dns-lookup
|
||||||
|
dns-lookup-name
|
||||||
dns-inverse-lookup
|
dns-inverse-lookup
|
||||||
|
dns-lookup-ip
|
||||||
|
dns-lookup-nameserver
|
||||||
|
dns-lookup-mail-exchanger
|
||||||
show-dns-message
|
show-dns-message
|
||||||
dns-find-nameserver))
|
dns-find-nameserver
|
||||||
|
dns-find-nameserver-list))
|
||||||
|
|
||||||
(define-structure dns dns-interface
|
(define-structure dns dns-interface
|
||||||
(open scheme
|
(open scheme
|
||||||
|
|
Loading…
Reference in New Issue