86915
|
1 ;;; dns.el --- Domain Name Service lookups
|
|
2
|
100908
|
3 ;; Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
86917
|
4 ;; Free Software Foundation, Inc.
|
86915
|
5
|
|
6 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
|
|
7 ;; Keywords: network
|
|
8
|
|
9 ;; This file is part of GNU Emacs.
|
|
10
|
94677
|
11 ;; GNU Emacs is free software: you can redistribute it and/or modify
|
86915
|
12 ;; it under the terms of the GNU General Public License as published by
|
94677
|
13 ;; the Free Software Foundation, either version 3 of the License, or
|
|
14 ;; (at your option) any later version.
|
86915
|
15
|
|
16 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
94677
|
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
86915
|
19 ;; GNU General Public License for more details.
|
|
20
|
|
21 ;; You should have received a copy of the GNU General Public License
|
94677
|
22 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
86915
|
23
|
|
24 ;;; Commentary:
|
|
25
|
|
26 ;;; Code:
|
|
27
|
|
28 (defvar dns-timeout 5
|
|
29 "How many seconds to wait when doing DNS queries.")
|
|
30
|
|
31 (defvar dns-servers nil
|
100993
|
32 "List of DNS servers to query.
|
|
33 If nil, /etc/resolv.conf and nslookup will be consulted.")
|
86915
|
34
|
|
35 ;;; Internal code:
|
|
36
|
|
37 (defvar dns-query-types
|
|
38 '((A 1)
|
|
39 (NS 2)
|
|
40 (MD 3)
|
|
41 (MF 4)
|
|
42 (CNAME 5)
|
|
43 (SOA 6)
|
|
44 (MB 7)
|
|
45 (MG 8)
|
|
46 (MR 9)
|
|
47 (NULL 10)
|
|
48 (WKS 11)
|
|
49 (PTR 12)
|
|
50 (HINFO 13)
|
|
51 (MINFO 14)
|
|
52 (MX 15)
|
|
53 (TXT 16)
|
|
54 (AAAA 28) ; RFC3596
|
|
55 (SRV 33) ; RFC2782
|
|
56 (AXFR 252)
|
|
57 (MAILB 253)
|
|
58 (MAILA 254)
|
|
59 (* 255))
|
|
60 "Names of query types and their values.")
|
|
61
|
|
62 (defvar dns-classes
|
|
63 '((IN 1)
|
|
64 (CS 2)
|
|
65 (CH 3)
|
|
66 (HS 4))
|
|
67 "Classes of queries.")
|
|
68
|
|
69 (defun dns-write-bytes (value &optional length)
|
|
70 (let (bytes)
|
|
71 (dotimes (i (or length 1))
|
|
72 (push (% value 256) bytes)
|
|
73 (setq value (/ value 256)))
|
|
74 (dolist (byte bytes)
|
|
75 (insert byte))))
|
|
76
|
|
77 (defun dns-read-bytes (length)
|
|
78 (let ((value 0))
|
|
79 (dotimes (i length)
|
|
80 (setq value (logior (* value 256) (following-char)))
|
|
81 (forward-char 1))
|
|
82 value))
|
|
83
|
|
84 (defun dns-get (type spec)
|
|
85 (cadr (assq type spec)))
|
|
86
|
|
87 (defun dns-inverse-get (value spec)
|
|
88 (let ((found nil))
|
|
89 (while (and (not found)
|
|
90 spec)
|
|
91 (if (eq value (cadr (car spec)))
|
|
92 (setq found (caar spec))
|
|
93 (pop spec)))
|
|
94 found))
|
|
95
|
|
96 (defun dns-write-name (name)
|
|
97 (dolist (part (split-string name "\\."))
|
|
98 (dns-write-bytes (length part))
|
|
99 (insert part))
|
|
100 (dns-write-bytes 0))
|
|
101
|
|
102 (defun dns-read-string-name (string buffer)
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
103 (with-temp-buffer
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
104 (set-buffer-multibyte nil)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
105 (insert string)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
106 (goto-char (point-min))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
107 (dns-read-name buffer)))
|
86915
|
108
|
|
109 (defun dns-read-name (&optional buffer)
|
|
110 (let ((ended nil)
|
|
111 (name nil)
|
|
112 length)
|
|
113 (while (not ended)
|
|
114 (setq length (dns-read-bytes 1))
|
|
115 (if (= 192 (logand length (lsh 3 6)))
|
|
116 (let ((offset (+ (* (logand 63 length) 256)
|
|
117 (dns-read-bytes 1))))
|
|
118 (save-excursion
|
|
119 (when buffer
|
|
120 (set-buffer buffer))
|
|
121 (goto-char (1+ offset))
|
|
122 (setq ended (dns-read-name buffer))))
|
|
123 (if (zerop length)
|
|
124 (setq ended t)
|
|
125 (push (buffer-substring (point)
|
|
126 (progn (forward-char length) (point)))
|
|
127 name))))
|
|
128 (if (stringp ended)
|
|
129 (if (null name)
|
|
130 ended
|
|
131 (concat (mapconcat 'identity (nreverse name) ".") "." ended))
|
|
132 (mapconcat 'identity (nreverse name) "."))))
|
|
133
|
|
134 (defun dns-write (spec &optional tcp-p)
|
|
135 "Write a DNS packet according to SPEC.
|
|
136 If TCP-P, the first two bytes of the package with be the length field."
|
|
137 (with-temp-buffer
|
93364
|
138 (set-buffer-multibyte nil)
|
86915
|
139 (dns-write-bytes (dns-get 'id spec) 2)
|
|
140 (dns-write-bytes
|
|
141 (logior
|
|
142 (lsh (if (dns-get 'response-p spec) 1 0) -7)
|
|
143 (lsh
|
|
144 (cond
|
|
145 ((eq (dns-get 'opcode spec) 'query) 0)
|
|
146 ((eq (dns-get 'opcode spec) 'inverse-query) 1)
|
|
147 ((eq (dns-get 'opcode spec) 'status) 2)
|
|
148 (t (error "No such opcode: %s" (dns-get 'opcode spec))))
|
|
149 -3)
|
|
150 (lsh (if (dns-get 'authoritative-p spec) 1 0) -2)
|
|
151 (lsh (if (dns-get 'truncated-p spec) 1 0) -1)
|
|
152 (lsh (if (dns-get 'recursion-desired-p spec) 1 0) 0)))
|
|
153 (dns-write-bytes
|
|
154 (cond
|
|
155 ((eq (dns-get 'response-code spec) 'no-error) 0)
|
|
156 ((eq (dns-get 'response-code spec) 'format-error) 1)
|
|
157 ((eq (dns-get 'response-code spec) 'server-failure) 2)
|
|
158 ((eq (dns-get 'response-code spec) 'name-error) 3)
|
|
159 ((eq (dns-get 'response-code spec) 'not-implemented) 4)
|
|
160 ((eq (dns-get 'response-code spec) 'refused) 5)
|
|
161 (t 0)))
|
|
162 (dns-write-bytes (length (dns-get 'queries spec)) 2)
|
|
163 (dns-write-bytes (length (dns-get 'answers spec)) 2)
|
|
164 (dns-write-bytes (length (dns-get 'authorities spec)) 2)
|
|
165 (dns-write-bytes (length (dns-get 'additionals spec)) 2)
|
|
166 (dolist (query (dns-get 'queries spec))
|
|
167 (dns-write-name (car query))
|
|
168 (dns-write-bytes (cadr (assq (or (dns-get 'type query) 'A)
|
|
169 dns-query-types)) 2)
|
|
170 (dns-write-bytes (cadr (assq (or (dns-get 'class query) 'IN)
|
|
171 dns-classes)) 2))
|
|
172 (dolist (slot '(answers authorities additionals))
|
|
173 (dolist (resource (dns-get slot spec))
|
|
174 (dns-write-name (car resource))
|
|
175 (dns-write-bytes (cadr (assq (dns-get 'type resource) dns-query-types))
|
|
176 2)
|
|
177 (dns-write-bytes (cadr (assq (dns-get 'class resource) dns-classes))
|
|
178 2)
|
|
179 (dns-write-bytes (dns-get 'ttl resource) 4)
|
|
180 (dns-write-bytes (length (dns-get 'data resource)) 2)
|
|
181 (insert (dns-get 'data resource))))
|
|
182 (when tcp-p
|
|
183 (goto-char (point-min))
|
|
184 (dns-write-bytes (buffer-size) 2))
|
|
185 (buffer-string)))
|
|
186
|
|
187 (defun dns-read (packet)
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
188 (with-temp-buffer
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
189 (set-buffer-multibyte nil)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
190 (let ((spec nil)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
191 queries answers authorities additionals)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
192 (insert packet)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
193 (goto-char (point-min))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
194 (push (list 'id (dns-read-bytes 2)) spec)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
195 (let ((byte (dns-read-bytes 1)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
196 (push (list 'response-p (if (zerop (logand byte (lsh 1 7))) nil t))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
197 spec)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
198 (let ((opcode (logand byte (lsh 7 3))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
199 (push (list 'opcode
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
200 (cond ((eq opcode 0) 'query)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
201 ((eq opcode 1) 'inverse-query)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
202 ((eq opcode 2) 'status)))
|
86917
|
203 spec))
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
204 (push (list 'authoritative-p (if (zerop (logand byte (lsh 1 2)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
205 nil t)) spec)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
206 (push (list 'truncated-p (if (zerop (logand byte (lsh 1 2))) nil t))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
207 spec)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
208 (push (list 'recursion-desired-p
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
209 (if (zerop (logand byte (lsh 1 0))) nil t)) spec))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
210 (let ((rc (logand (dns-read-bytes 1) 15)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
211 (push (list 'response-code
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
212 (cond
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
213 ((eq rc 0) 'no-error)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
214 ((eq rc 1) 'format-error)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
215 ((eq rc 2) 'server-failure)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
216 ((eq rc 3) 'name-error)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
217 ((eq rc 4) 'not-implemented)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
218 ((eq rc 5) 'refused)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
219 spec))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
220 (setq queries (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
221 (setq answers (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
222 (setq authorities (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
223 (setq additionals (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
224 (let ((qs nil))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
225 (dotimes (i queries)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
226 (push (list (dns-read-name)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
227 (list 'type (dns-inverse-get (dns-read-bytes 2)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
228 dns-query-types))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
229 (list 'class (dns-inverse-get (dns-read-bytes 2)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
230 dns-classes)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
231 qs))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
232 (push (list 'queries qs) spec))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
233 (dolist (slot '(answers authorities additionals))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
234 (let ((qs nil)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
235 type)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
236 (dotimes (i (symbol-value slot))
|
86917
|
237 (push (list (dns-read-name)
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
238 (list 'type
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
239 (setq type (dns-inverse-get (dns-read-bytes 2)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
240 dns-query-types)))
|
86917
|
241 (list 'class (dns-inverse-get (dns-read-bytes 2)
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
242 dns-classes))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
243 (list 'ttl (dns-read-bytes 4))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
244 (let ((length (dns-read-bytes 2)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
245 (list 'data
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
246 (dns-read-type
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
247 (buffer-substring
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
248 (point)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
249 (progn (forward-char length) (point)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
250 type))))
|
86917
|
251 qs))
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
252 (push (list slot qs) spec)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
253 (nreverse spec))))
|
86915
|
254
|
|
255 (defun dns-read-int32 ()
|
|
256 ;; Full 32 bit Integers can't be handled by Emacs. If we use
|
|
257 ;; floats, it works.
|
|
258 (format "%.0f" (+ (* (dns-read-bytes 1) 16777216.0)
|
|
259 (dns-read-bytes 3))))
|
|
260
|
|
261 (defun dns-read-type (string type)
|
|
262 (let ((buffer (current-buffer))
|
|
263 (point (point)))
|
|
264 (prog1
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
265 (with-temp-buffer
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
266 (set-buffer-multibyte nil)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
267 (insert string)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
268 (goto-char (point-min))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
269 (cond
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
270 ((eq type 'A)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
271 (let ((bytes nil))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
272 (dotimes (i 4)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
273 (push (dns-read-bytes 1) bytes))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
274 (mapconcat 'number-to-string (nreverse bytes) ".")))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
275 ((eq type 'AAAA)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
276 (let (hextets)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
277 (dotimes (i 8)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
278 (push (dns-read-bytes 2) hextets))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
279 (mapconcat (lambda (n) (format "%x" n))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
280 (nreverse hextets) ":")))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
281 ((eq type 'SOA)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
282 (list (list 'mname (dns-read-name buffer))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
283 (list 'rname (dns-read-name buffer))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
284 (list 'serial (dns-read-int32))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
285 (list 'refresh (dns-read-int32))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
286 (list 'retry (dns-read-int32))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
287 (list 'expire (dns-read-int32))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
288 (list 'minimum (dns-read-int32))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
289 ((eq type 'SRV)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
290 (list (list 'priority (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
291 (list 'weight (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
292 (list 'port (dns-read-bytes 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
293 (list 'target (dns-read-name buffer))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
294 ((eq type 'MX)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
295 (cons (dns-read-bytes 2) (dns-read-name buffer)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
296 ((or (eq type 'CNAME) (eq type 'NS) (eq type 'PTR))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
297 (dns-read-string-name string buffer))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
298 (t string)))
|
86915
|
299 (goto-char point))))
|
|
300
|
100993
|
301 (defun dns-set-servers ()
|
|
302 "Set `dns-servers' to a list of DNS servers or nil if none are found.
|
|
303 Parses \"/etc/resolv.conf\" or calls \"nslookup\"."
|
|
304 (or (when (file-exists-p "/etc/resolv.conf")
|
|
305 (setq dns-servers nil)
|
|
306 (with-temp-buffer
|
|
307 (insert-file-contents "/etc/resolv.conf")
|
|
308 (goto-char (point-min))
|
|
309 (while (re-search-forward "^nameserver[\t ]+\\([^ \t\n]+\\)" nil t)
|
|
310 (push (match-string 1) dns-servers))
|
|
311 (setq dns-servers (nreverse dns-servers))))
|
|
312 (when (executable-find "nslookup")
|
|
313 (with-temp-buffer
|
|
314 (call-process "nslookup" nil t nil "localhost")
|
|
315 (goto-char (point-min))
|
|
316 (re-search-forward
|
|
317 "^Address:[ \t]*\\([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\\)" nil t)
|
|
318 (setq dns-servers (list (match-string 1)))))))
|
86915
|
319
|
|
320 (defun dns-read-txt (string)
|
|
321 (if (> (length string) 1)
|
|
322 (substring string 1)
|
|
323 string))
|
|
324
|
|
325 (defun dns-get-txt-answer (answers)
|
|
326 (let ((result "")
|
|
327 (do-next nil))
|
|
328 (dolist (answer answers)
|
|
329 (dolist (elem answer)
|
|
330 (when (consp elem)
|
|
331 (cond
|
|
332 ((eq (car elem) 'type)
|
|
333 (setq do-next (eq (cadr elem) 'TXT)))
|
|
334 ((eq (car elem) 'data)
|
|
335 (when do-next
|
|
336 (setq result (concat result (dns-read-txt (cadr elem))))))))))
|
|
337 result))
|
|
338
|
|
339 ;;; Interface functions.
|
|
340 (defmacro dns-make-network-process (server)
|
|
341 (if (featurep 'xemacs)
|
|
342 `(let ((coding-system-for-read 'binary)
|
|
343 (coding-system-for-write 'binary))
|
|
344 (open-network-stream "dns" (current-buffer)
|
|
345 ,server "domain" 'udp))
|
|
346 `(let ((server ,server)
|
|
347 (coding-system-for-read 'binary)
|
|
348 (coding-system-for-write 'binary))
|
|
349 (if (fboundp 'make-network-process)
|
|
350 (make-network-process
|
|
351 :name "dns"
|
|
352 :coding 'binary
|
|
353 :buffer (current-buffer)
|
|
354 :host server
|
|
355 :service "domain"
|
|
356 :type 'datagram)
|
|
357 ;; Older versions of Emacs doesn't have
|
|
358 ;; `make-network-process', so we fall back on opening a TCP
|
|
359 ;; connection to the DNS server.
|
|
360 (open-network-stream "dns" (current-buffer) server "domain")))))
|
|
361
|
|
362 (defvar dns-cache (make-vector 4096 0))
|
|
363
|
100993
|
364 (defun dns-query-cached (name &optional type fullp reversep)
|
86915
|
365 (let* ((key (format "%s:%s:%s:%s" name type fullp reversep))
|
|
366 (sym (intern-soft key dns-cache)))
|
|
367 (if (and sym
|
|
368 (boundp sym))
|
|
369 (symbol-value sym)
|
100993
|
370 (let ((result (dns-query name type fullp reversep)))
|
86915
|
371 (set (intern key dns-cache) result)
|
|
372 result))))
|
|
373
|
100993
|
374 ;; The old names `query-dns' and `query-dns-cached' weren't used in Emacs 23
|
|
375 ;; yet, so no alias are provided. --rsteib
|
|
376
|
|
377 (defun dns-query (name &optional type fullp reversep)
|
86915
|
378 "Query a DNS server for NAME of TYPE.
|
|
379 If FULLP, return the entire record returned.
|
|
380 If REVERSEP, look up an IP address."
|
|
381 (setq type (or type 'A))
|
|
382 (unless dns-servers
|
100993
|
383 (dns-set-servers))
|
86915
|
384
|
|
385 (when reversep
|
|
386 (setq name (concat
|
|
387 (mapconcat 'identity (nreverse (split-string name "\\.")) ".")
|
|
388 ".in-addr.arpa")
|
|
389 type 'PTR))
|
|
390
|
|
391 (if (not dns-servers)
|
|
392 (message "No DNS server configuration found")
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
393 (with-temp-buffer
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
394 (set-buffer-multibyte nil)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
395 (let ((process (condition-case ()
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
396 (dns-make-network-process (car dns-servers))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
397 (error
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
398 (message
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
399 "dns: Got an error while trying to talk to %s"
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
400 (car dns-servers))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
401 nil)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
402 (tcp-p (and (not (fboundp 'make-network-process))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
403 (not (featurep 'xemacs))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
404 (step 100)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
405 (times (* dns-timeout 1000))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
406 (id (random 65000)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
407 (when process
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
408 (process-send-string
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
409 process
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
410 (dns-write `((id ,id)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
411 (opcode query)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
412 (queries ((,name (type ,type))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
413 (recursion-desired-p t))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
414 tcp-p))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
415 (while (and (zerop (buffer-size))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
416 (> times 0))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
417 (sit-for (/ step 1000.0))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
418 (accept-process-output process 0 step)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
419 (setq times (- times step)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
420 (condition-case nil
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
421 (delete-process process)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
422 (error nil))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
423 (when (and tcp-p
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
424 (>= (buffer-size) 2))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
425 (goto-char (point-min))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
426 (delete-region (point) (+ (point) 2)))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
427 (when (and (>= (buffer-size) 2)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
428 ;; We had a time-out.
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
429 (> times 0))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
430 (let ((result (dns-read (buffer-string))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
431 (if fullp
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
432 result
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
433 (let ((answer (car (dns-get 'answers result))))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
434 (when (eq type (dns-get 'type answer))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
435 (if (eq type 'TXT)
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
436 (dns-get-txt-answer (dns-get 'answers result))
|
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
437 (dns-get 'data answer))))))))))))
|
86915
|
438
|
|
439 (provide 'dns)
|
|
440
|
92781
f231a5d1706d
(dns-read-string-name, dns-read, dns-read-type, query-dns):
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
441 ;; arch-tag: d0edd0c4-4cce-4538-ae92-06c3356ee80a
|
86915
|
442 ;;; dns.el ends here
|