~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/libaddns/dnsrecord.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
26
DNS_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;
 
31
        struct dns_question *q;
 
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
 
 
60
DNS_ERROR dns_create_update( TALLOC_CTX *mem_ctx, const char *name,
 
61
                             struct dns_update_request **preq )
 
62
{
 
63
        struct dns_update_request *req;
 
64
        struct dns_zone *z;
 
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
 
 
93
DNS_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;
 
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
 
 
121
DNS_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
 
 
150
DNS_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
 
 
163
DNS_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
 
 
171
DNS_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
 
 
178
DNS_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;
 
185
        struct dns_domain_name *algorithm;
 
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
 
 
217
DNS_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;
 
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
 
 
265
DNS_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;
 
273
        struct dns_domain_name *algorithm;
 
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
 
 
306
DNS_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
 
 
329
DNS_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;
 
335
        struct dns_rrec *rec;
 
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
                           
 
365
DNS_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;
 
373
        struct dns_rrec *rec;
 
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
}