;;; dns.el --- Domain Name Service lookups
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: network
;;; Code:
+(eval-when-compile (require 'cl))
+
(require 'mm-util)
(defvar dns-timeout 5
(MR 9)
(NULL 10)
(WKS 11)
- (PRT 12)
+ (PTR 12)
(HINFO 13)
(MINFO 14)
(MX 15)
(TXT 16)
+ (AAAA 28) ; RFC3596
(AXFR 252)
(MAILB 253)
(MAILA 254)
(push (list slot qs) spec)))
(nreverse spec))))
+(defun dns-read-int32 ()
+ ;; Full 32 bit Integers can't be handled by Emacs. If we use
+ ;; floats, it works.
+ (format "%.0f" (+ (* (dns-read-bytes 1) 16777216.0)
+ (dns-read-bytes 3))))
+
(defun dns-read-type (string type)
(let ((buffer (current-buffer))
(point (point)))
(dotimes (i 4)
(push (dns-read-bytes 1) bytes))
(mapconcat 'number-to-string (nreverse bytes) ".")))
- ((eq type 'NS)
- (dns-read-string-name string buffer))
- ((eq type 'CNAME)
+ ((eq type 'AAAA)
+ (let (hextets)
+ (dotimes (i 8)
+ (push (dns-read-bytes 2) hextets))
+ (mapconcat (lambda (n) (format "%x" n)) (nreverse hextets) ":")))
+ ((eq type 'SOA)
+ (list (list 'mname (dns-read-name buffer))
+ (list 'rname (dns-read-name buffer))
+ (list 'serial (dns-read-int32))
+ (list 'refresh (dns-read-int32))
+ (list 'retry (dns-read-int32))
+ (list 'expire (dns-read-int32))
+ (list 'minimum (dns-read-int32))))
+ ((eq type 'MX)
+ (cons (dns-read-bytes 2) (dns-read-name buffer)))
+ ((or (eq type 'CNAME) (eq type 'NS) (eq type 'PTR))
(dns-read-string-name string buffer))
(t string)))
(goto-char point))))
(setq dns-servers (nreverse dns-servers)))))
;;; Interface functions.
+(defmacro dns-make-network-process (server)
+ (if (featurep 'xemacs)
+ `(let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ (open-network-stream "dns" (current-buffer)
+ ,server "domain" 'udp))
+ `(let ((server ,server)
+ (coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ (if (fboundp 'make-network-process)
+ (make-network-process
+ :name "dns"
+ :coding 'binary
+ :buffer (current-buffer)
+ :host server
+ :service "domain"
+ :type 'datagram)
+ ;; Older versions of Emacs doesn't have
+ ;; `make-network-process', so we fall back on opening a TCP
+ ;; connection to the DNS server.
+ (open-network-stream "dns" (current-buffer) server "domain")))))
(defun query-dns (name &optional type fullp)
"Query a DNS server for NAME of TYPE.
If FULLP, return the entire record returned."
(setq type (or type 'A))
(unless dns-servers
- (dns-parse-resolv-conf)
- (unless dns-servers
- (error "No DNS server configuration found")))
- (mm-with-unibyte-buffer
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (tcp-p (and (not (fboundp 'open-network-stream))
- (not (featurep 'xemacs)))))
- (let ((process
- (cond
- ((featurep 'xemacs)
- (open-network-stream
- "dns" (current-buffer) (car dns-servers) "domain" 'udp))
- (tcp-p
- (open-network-stream
- "dns" (current-buffer) (car dns-servers) "domain"))
- (t
- (make-network-process
- :name "dns"
- :coding 'binary
- :buffer (current-buffer)
- :host (car dns-servers)
- :service "domain"
- :type 'datagram))))
+ (dns-parse-resolv-conf))
+
+ (if (not dns-servers)
+ (message "No DNS server configuration found")
+ (mm-with-unibyte-buffer
+ (let ((process (condition-case ()
+ (dns-make-network-process (car dns-servers))
+ (error
+ (message "dns: Got an error while trying to talk to %s"
+ (car dns-servers))
+ nil)))
+ (tcp-p (and (not (fboundp 'make-network-process))
+ (not (featurep 'xemacs))))
(step 100)
(times (* dns-timeout 1000))
(id (random 65000)))
- (process-send-string
- process
- (dns-write `((id ,id)
- (opcode query)
- (queries ((,name (type ,type))))
- (recursion-desired-p t))
- tcp-p))
- (while (and (zerop (buffer-size))
- (> times 0))
- (accept-process-output process 0 step)
- (decf times step))
- (ignore-errors
- (delete-process process))
- (when tcp-p
- (goto-char (point-min))
- (delete-region (point) (+ (point) 2)))
- (unless (zerop (buffer-size))
- (let ((result (dns-read (buffer-string))))
- (if fullp
- result
- (let ((answer (car (dns-get 'answers result))))
- (when (eq type (dns-get 'type answer))
- (dns-get 'data answer))))))))))
-
+ (when process
+ (process-send-string
+ process
+ (dns-write `((id ,id)
+ (opcode query)
+ (queries ((,name (type ,type))))
+ (recursion-desired-p t))
+ tcp-p))
+ (while (and (zerop (buffer-size))
+ (> times 0))
+ (accept-process-output process 0 step)
+ (decf times step))
+ (ignore-errors
+ (delete-process process))
+ (when tcp-p
+ (goto-char (point-min))
+ (delete-region (point) (+ (point) 2)))
+ (unless (zerop (buffer-size))
+ (let ((result (dns-read (buffer-string))))
+ (if fullp
+ result
+ (let ((answer (car (dns-get 'answers result))))
+ (when (eq type (dns-get 'type answer))
+ (dns-get 'data answer)))))))))))
+
(provide 'dns)
;;; dns.el ends here