source: vendor/current/lib/addns/dnsrecord.c@ 746

Last change on this file since 746 was 746, checked in by Silvan Scherrer, 12 years ago

Samba Server: updated vendor to 3.6.9

File size: 11.1 KB
Line 
1/*
2 Linux DNS client library implementation
3 Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
4 Copyright (C) 2006 Gerald Carter <jerry@samba.org>
5
6 ** NOTE! The following LGPL license applies to the libaddns
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2.1 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
22*/
23
24#include "dns.h"
25
26DNS_ERROR dns_create_query( TALLOC_CTX *mem_ctx, const char *name,
27 uint16 q_type, uint16 q_class,
28 struct dns_request **preq )
29{
30 struct dns_request *req = NULL;
31 struct dns_question *q = NULL;
32 DNS_ERROR err;
33
34 if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_request)) ||
35 !(req->questions = TALLOC_ARRAY(req, struct dns_question *, 1)) ||
36 !(req->questions[0] = talloc(req->questions,
37 struct dns_question))) {
38 TALLOC_FREE(req);
39 return ERROR_DNS_NO_MEMORY;
40 }
41
42 req->id = random();
43
44 req->num_questions = 1;
45 q = req->questions[0];
46
47 err = dns_domain_name_from_string(q, name, &q->name);
48 if (!ERR_DNS_IS_OK(err)) {
49 TALLOC_FREE(req);
50 return err;
51 }
52
53 q->q_type = q_type;
54 q->q_class = q_class;
55
56 *preq = req;
57 return ERROR_DNS_SUCCESS;
58}
59
60DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
61 struct dns_update_request **preq )
62{
63 struct dns_update_request *req = NULL;
64 struct dns_zone *z = NULL;
65 DNS_ERROR err;
66
67 if (!(req = TALLOC_ZERO_P(mem_ctx, struct dns_update_request)) ||
68 !(req->zones = TALLOC_ARRAY(req, struct dns_zone *, 1)) ||
69 !(req->zones[0] = talloc(req->zones, struct dns_zone))) {
70 TALLOC_FREE(req);
71 return ERROR_DNS_NO_MEMORY;
72 }
73
74 req->id = random();
75 req->flags = 0x2800; /* Dynamic update */
76
77 req->num_zones = 1;
78 z = req->zones[0];
79
80 err = dns_domain_name_from_string(z, name, &z->name);
81 if (!ERR_DNS_IS_OK(err)) {
82 TALLOC_FREE(req);
83 return err;
84 }
85
86 z->z_type = QTYPE_SOA;
87 z->z_class = DNS_CLASS_IN;
88
89 *preq = req;
90 return ERROR_DNS_SUCCESS;
91}
92
93DNS_ERROR dns_create_rrec(TALLOC_CTX *mem_ctx, const char *name,
94 uint16 type, uint16 r_class, uint32 ttl,
95 uint16 data_length, uint8 *data,
96 struct dns_rrec **prec)
97{
98 struct dns_rrec *rec = NULL;
99 DNS_ERROR err;
100
101 if (!(rec = talloc(mem_ctx, struct dns_rrec))) {
102 return ERROR_DNS_NO_MEMORY;
103 }
104
105 err = dns_domain_name_from_string(rec, name, &rec->name);
106 if (!(ERR_DNS_IS_OK(err))) {
107 TALLOC_FREE(rec);
108 return err;
109 }
110
111 rec->type = type;
112 rec->r_class = r_class;
113 rec->ttl = ttl;
114 rec->data_length = data_length;
115 rec->data = talloc_move(rec, &data);
116
117 *prec = rec;
118 return ERROR_DNS_SUCCESS;
119}
120
121DNS_ERROR dns_create_a_record(TALLOC_CTX *mem_ctx, const char *host,
122 uint32 ttl, const struct sockaddr_storage *pss,
123 struct dns_rrec **prec)
124{
125 uint8 *data;
126 DNS_ERROR err;
127 struct in_addr ip;
128
129 if (pss->ss_family != AF_INET) {
130 /* Silently ignore this. */
131 return ERROR_DNS_SUCCESS;
132 }
133
134 ip = ((struct sockaddr_in *)pss)->sin_addr;
135 if (!(data = (uint8 *)TALLOC_MEMDUP(mem_ctx, (const void *)&ip.s_addr,
136 sizeof(ip.s_addr)))) {
137 return ERROR_DNS_NO_MEMORY;
138 }
139
140 err = dns_create_rrec(mem_ctx, host, QTYPE_A, DNS_CLASS_IN, ttl,
141 sizeof(ip.s_addr), data, prec);
142
143 if (!ERR_DNS_IS_OK(err)) {
144 TALLOC_FREE(data);
145 }
146
147 return err;
148}
149
150DNS_ERROR dns_create_name_in_use_record(TALLOC_CTX *mem_ctx,
151 const char *name,
152 const struct sockaddr_storage *ss,
153 struct dns_rrec **prec)
154{
155 if (ss != NULL) {
156 return dns_create_a_record(mem_ctx, name, 0, ss, prec);
157 }
158
159 return dns_create_rrec(mem_ctx, name, QTYPE_ANY, DNS_CLASS_IN, 0, 0,
160 NULL, prec);
161}
162
163DNS_ERROR dns_create_name_not_in_use_record(TALLOC_CTX *mem_ctx,
164 const char *name, uint32 type,
165 struct dns_rrec **prec)
166{
167 return dns_create_rrec(mem_ctx, name, type, DNS_CLASS_NONE, 0,
168 0, NULL, prec);
169}
170
171DNS_ERROR dns_create_delete_record(TALLOC_CTX *mem_ctx, const char *name,
172 uint16 type, uint16 r_class,
173 struct dns_rrec **prec)
174{
175 return dns_create_rrec(mem_ctx, name, type, r_class, 0, 0, NULL, prec);
176}
177
178DNS_ERROR dns_create_tkey_record(TALLOC_CTX *mem_ctx, const char *keyname,
179 const char *algorithm_name, time_t inception,
180 time_t expiration, uint16 mode, uint16 error,
181 uint16 key_length, const uint8 *key,
182 struct dns_rrec **prec)
183{
184 struct dns_buffer *buf = NULL;
185 struct dns_domain_name *algorithm = NULL;
186 DNS_ERROR err;
187
188 if (!(buf = dns_create_buffer(mem_ctx))) {
189 return ERROR_DNS_NO_MEMORY;
190 }
191
192 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
193 if (!ERR_DNS_IS_OK(err)) goto error;
194
195 dns_marshall_domain_name(buf, algorithm);
196 dns_marshall_uint32(buf, inception);
197 dns_marshall_uint32(buf, expiration);
198 dns_marshall_uint16(buf, mode);
199 dns_marshall_uint16(buf, error);
200 dns_marshall_uint16(buf, key_length);
201 dns_marshall_buffer(buf, key, key_length);
202 dns_marshall_uint16(buf, 0); /* Other Size */
203
204 if (!ERR_DNS_IS_OK(buf->error)) {
205 err = buf->error;
206 goto error;
207 }
208
209 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TKEY, DNS_CLASS_ANY, 0,
210 buf->offset, buf->data, prec);
211
212 error:
213 TALLOC_FREE(buf);
214 return err;
215}
216
217DNS_ERROR dns_unmarshall_tkey_record(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
218 struct dns_tkey_record **ptkey)
219{
220 struct dns_tkey_record *tkey = NULL;
221 struct dns_buffer buf;
222 uint32 tmp_inception, tmp_expiration;
223
224 if (!(tkey = talloc(mem_ctx, struct dns_tkey_record))) {
225 return ERROR_DNS_NO_MEMORY;
226 }
227
228 buf.data = rec->data;
229 buf.size = rec->data_length;
230 buf.offset = 0;
231 buf.error = ERROR_DNS_SUCCESS;
232
233 dns_unmarshall_domain_name(tkey, &buf, &tkey->algorithm);
234 dns_unmarshall_uint32(&buf, &tmp_inception);
235 dns_unmarshall_uint32(&buf, &tmp_expiration);
236 dns_unmarshall_uint16(&buf, &tkey->mode);
237 dns_unmarshall_uint16(&buf, &tkey->error);
238 dns_unmarshall_uint16(&buf, &tkey->key_length);
239
240 if (!ERR_DNS_IS_OK(buf.error)) goto error;
241
242 if (tkey->key_length) {
243 if (!(tkey->key = TALLOC_ARRAY(tkey, uint8, tkey->key_length))) {
244 buf.error = ERROR_DNS_NO_MEMORY;
245 goto error;
246 }
247 } else {
248 tkey->key = NULL;
249 }
250
251 dns_unmarshall_buffer(&buf, tkey->key, tkey->key_length);
252 if (!ERR_DNS_IS_OK(buf.error)) goto error;
253
254 tkey->inception = (time_t)tmp_inception;
255 tkey->expiration = (time_t)tmp_expiration;
256
257 *ptkey = tkey;
258 return ERROR_DNS_SUCCESS;
259
260 error:
261 TALLOC_FREE(tkey);
262 return buf.error;
263}
264
265DNS_ERROR dns_create_tsig_record(TALLOC_CTX *mem_ctx, const char *keyname,
266 const char *algorithm_name,
267 time_t time_signed, uint16 fudge,
268 uint16 mac_length, const uint8 *mac,
269 uint16 original_id, uint16 error,
270 struct dns_rrec **prec)
271{
272 struct dns_buffer *buf = NULL;
273 struct dns_domain_name *algorithm = NULL;
274 DNS_ERROR err;
275
276 if (!(buf = dns_create_buffer(mem_ctx))) {
277 return ERROR_DNS_NO_MEMORY;
278 }
279
280 err = dns_domain_name_from_string(buf, algorithm_name, &algorithm);
281 if (!ERR_DNS_IS_OK(err)) goto error;
282
283 dns_marshall_domain_name(buf, algorithm);
284 dns_marshall_uint16(buf, 0); /* time prefix */
285 dns_marshall_uint32(buf, time_signed);
286 dns_marshall_uint16(buf, fudge);
287 dns_marshall_uint16(buf, mac_length);
288 dns_marshall_buffer(buf, mac, mac_length);
289 dns_marshall_uint16(buf, original_id);
290 dns_marshall_uint16(buf, error);
291 dns_marshall_uint16(buf, 0); /* Other Size */
292
293 if (!ERR_DNS_IS_OK(buf->error)) {
294 err = buf->error;
295 goto error;
296 }
297
298 err = dns_create_rrec(mem_ctx, keyname, QTYPE_TSIG, DNS_CLASS_ANY, 0,
299 buf->offset, buf->data, prec);
300
301 error:
302 TALLOC_FREE(buf);
303 return err;
304}
305
306DNS_ERROR dns_add_rrec(TALLOC_CTX *mem_ctx, struct dns_rrec *rec,
307 uint16 *num_records, struct dns_rrec ***records)
308{
309 struct dns_rrec **new_records;
310
311 if (!(new_records = TALLOC_REALLOC_ARRAY(mem_ctx, *records,
312 struct dns_rrec *,
313 (*num_records)+1))) {
314 return ERROR_DNS_NO_MEMORY;
315 }
316
317 new_records[*num_records] = talloc_move(new_records, &rec);
318
319 *num_records += 1;
320 *records = new_records;
321 return ERROR_DNS_SUCCESS;
322}
323
324/*
325 * Create a request that probes a server whether the list of IP addresses
326 * provides meets our expectations
327 */
328
329DNS_ERROR dns_create_probe(TALLOC_CTX *mem_ctx, const char *zone,
330 const char *host, int num_ips,
331 const struct sockaddr_storage *sslist,
332 struct dns_update_request **preq)
333{
334 struct dns_update_request *req = NULL;
335 struct dns_rrec *rec = NULL;
336 DNS_ERROR err;
337 uint16 i;
338
339 err = dns_create_update(mem_ctx, zone, &req);
340 if (!ERR_DNS_IS_OK(err)) goto error;
341
342 err = dns_create_name_not_in_use_record(req, host, QTYPE_CNAME, &rec);
343 if (!ERR_DNS_IS_OK(err)) goto error;
344
345 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
346 if (!ERR_DNS_IS_OK(err)) goto error;
347
348 for (i=0; i<num_ips; i++) {
349 err = dns_create_name_in_use_record(req, host,
350 &sslist[i], &rec);
351 if (!ERR_DNS_IS_OK(err)) goto error;
352
353 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
354 if (!ERR_DNS_IS_OK(err)) goto error;
355 }
356
357 *preq = req;
358 return ERROR_DNS_SUCCESS;
359
360 error:
361 TALLOC_FREE(req);
362 return err;
363}
364
365DNS_ERROR dns_create_update_request(TALLOC_CTX *mem_ctx,
366 const char *domainname,
367 const char *hostname,
368 const struct sockaddr_storage *ss_addrs,
369 size_t num_addrs,
370 struct dns_update_request **preq)
371{
372 struct dns_update_request *req = NULL;
373 struct dns_rrec *rec = NULL;
374 DNS_ERROR err;
375 size_t i;
376
377 err = dns_create_update(mem_ctx, domainname, &req);
378 if (!ERR_DNS_IS_OK(err)) return err;
379
380 /*
381 * Use the same prereq as WinXP -- No CNAME records for this host.
382 */
383
384 err = dns_create_rrec(req, hostname, QTYPE_CNAME, DNS_CLASS_NONE,
385 0, 0, NULL, &rec);
386 if (!ERR_DNS_IS_OK(err)) goto error;
387
388 err = dns_add_rrec(req, rec, &req->num_preqs, &req->preqs);
389 if (!ERR_DNS_IS_OK(err)) goto error;
390
391 /*
392 * Delete any existing A records
393 */
394
395 err = dns_create_delete_record(req, hostname, QTYPE_A, DNS_CLASS_ANY,
396 &rec);
397 if (!ERR_DNS_IS_OK(err)) goto error;
398
399 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
400 if (!ERR_DNS_IS_OK(err)) goto error;
401
402 /*
403 * .. and add our IPs
404 */
405
406 for ( i=0; i<num_addrs; i++ ) {
407 err = dns_create_a_record(req, hostname, 3600, &ss_addrs[i], &rec);
408 if (!ERR_DNS_IS_OK(err))
409 goto error;
410
411 err = dns_add_rrec(req, rec, &req->num_updates, &req->updates);
412 if (!ERR_DNS_IS_OK(err))
413 goto error;
414 }
415
416 *preq = req;
417 return ERROR_DNS_SUCCESS;
418
419 error:
420 TALLOC_FREE(req);
421 return err;
422}
Note: See TracBrowser for help on using the repository browser.