Developer Area

root/tools/iphone-sdk/trunk/ldns_sources/update.c @ 81

Revision 32, 7.2 kB (checked in by kjaleel, 6 years ago)

unzipped the DotTel?.zip and moved it into trunk

Line 
1/* update.c
2 *
3 * Functions for RFC 2136 Dynamic Update
4 *
5 * Copyright (c) 2005-2008, NLnet Labs. All rights reserved.
6 *
7 * See LICENSE for the license.
8 */
9
10#include "ldns/config.h"
11
12#include "ldns.h"
13
14#include <strings.h>
15#include <stdlib.h>
16#include <limits.h>
17
18/*
19 * RFC 2136 sections mapped to RFC 1035:
20 *              zone/ZO -- QD/question
21 *     prerequisites/PR -- AN/answers
22 *           updates/UP -- NS/authority records
23 *   additional data/AD -- AR/additional records
24 */
25
26ldns_pkt *
27ldns_update_pkt_new(ldns_rdf *zone_rdf, ldns_rr_class class,
28    ldns_rr_list *pr_rrlist, ldns_rr_list *up_rrlist, ldns_rr_list *ad_rrlist)
29{
30        ldns_pkt *p;
31
32        if (!zone_rdf || !up_rrlist) {
33                return NULL;
34        }
35
36        if (class == 0) { 
37                class = LDNS_RR_CLASS_IN;
38        }
39
40        /* Create packet, fill in Zone Section. */
41        p = ldns_pkt_query_new(zone_rdf, LDNS_RR_TYPE_SOA, class, LDNS_RD);
42        if (!p) {
43                return NULL;
44        }
45        zone_rdf = NULL; /* No longer safe to use. */
46
47        ldns_pkt_set_opcode(p, LDNS_PACKET_UPDATE);
48
49        ldns_rr_list_deep_free(p->_authority);
50
51        ldns_pkt_set_authority(p, ldns_rr_list_clone(up_rrlist));
52
53        ldns_update_set_upcount(p, ldns_rr_list_rr_count(up_rrlist));
54
55        if (pr_rrlist) {
56                ldns_rr_list_deep_free(p->_answer); /*XXX access function */
57                ldns_pkt_set_answer(p, ldns_rr_list_clone(pr_rrlist));
58                ldns_update_set_prcount(p, ldns_rr_list_rr_count(pr_rrlist));
59        }
60
61        if (ad_rrlist) {
62                ldns_rr_list_deep_free(p->_additional);
63                ldns_pkt_set_additional(p, ldns_rr_list_clone(ad_rrlist));
64                ldns_update_set_adcount(p, ldns_rr_list_rr_count(ad_rrlist));
65        }
66        return p;
67}
68
69ldns_status
70ldns_update_pkt_tsig_add(ldns_pkt *p, ldns_resolver *r)
71{
72#ifdef HAVE_SSL
73        uint16_t fudge = 300; /* Recommended fudge. [RFC2845 6.4]  */
74        if (ldns_resolver_tsig_keyname(r) && ldns_resolver_tsig_keydata(r))
75                return ldns_pkt_tsig_sign(p, ldns_resolver_tsig_keyname(r),
76                    ldns_resolver_tsig_keydata(r), fudge,
77                    ldns_resolver_tsig_algorithm(r), NULL);
78#else
79        /* do nothing */
80        (void)p;
81        (void)r;
82#endif /* HAVE_SSL */
83        /* No TSIG to do. */
84        return LDNS_STATUS_OK;
85}
86
87/* Move to higher.c or similar? */
88/* XXX doc */
89ldns_status
90ldns_update_soa_mname(ldns_rdf *zone, ldns_resolver *r,
91    ldns_rr_class class, ldns_rdf **mname)
92{
93        ldns_rr         *soa_rr;
94        ldns_pkt        *query, *resp;
95
96        /* Nondestructive, so clone 'zone' here */
97        query = ldns_pkt_query_new(ldns_rdf_clone(zone), LDNS_RR_TYPE_SOA,
98            class, LDNS_RD);
99        if (!query) {
100                return LDNS_STATUS_ERR;
101        }
102
103        ldns_pkt_set_random_id(query);
104        if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
105                ldns_pkt_free(query);
106                return LDNS_STATUS_ERR;
107        }
108        ldns_pkt_free(query);
109        if (!resp) {
110                return LDNS_STATUS_ERR;
111        }
112
113        /* Expect a SOA answer. */
114        *mname = NULL;
115        while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp)))) {
116                if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA)
117                        continue;
118                /* [RFC1035 3.3.13] */
119                *mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
120                break;
121        }
122        ldns_pkt_free(resp);
123
124        return *mname ? LDNS_STATUS_OK : LDNS_STATUS_ERR;
125}
126
127/* Try to get zone and MNAME from SOA queries. */
128ldns_status
129ldns_update_soa_zone_mname(const char *fqdn, ldns_resolver *r,
130    ldns_rr_class class, ldns_rdf **zone_rdf, ldns_rdf **mname_rdf)
131{
132        ldns_rr         *soa_rr, *rr;
133        ldns_rdf        *soa_zone = NULL, *soa_mname = NULL;
134        ldns_rdf        *ipaddr, *fqdn_rdf, *tmp;
135        ldns_rdf        **nslist;
136        ldns_pkt        *query, *resp;
137        size_t          i;
138
139        /*
140         * XXX Ok, this cannot be the best way to find this...?
141         * XXX (I run into weird cache-related stuff here)
142         */
143
144        /* Step 1 - first find a nameserver that should know *something* */
145        fqdn_rdf = ldns_dname_new_frm_str(fqdn);
146        query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, class, LDNS_RD);
147        if (!query) {
148                return LDNS_STATUS_ERR;
149        }
150        fqdn_rdf = NULL;
151
152        ldns_pkt_set_random_id(query);
153        if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
154                ldns_pkt_free(query);
155                return LDNS_STATUS_ERR;
156        }
157        ldns_pkt_free(query);
158        if (!resp) {
159                return LDNS_STATUS_ERR;
160        }
161
162        /* XXX Is it safe to only look in authority section here? */
163        while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) {
164                if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA)
165                        continue;
166                /* [RFC1035 3.3.13] */
167                soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
168                break;
169        }
170        ldns_pkt_free(resp);
171        if (!soa_rr) {
172                return LDNS_STATUS_ERR;
173        }
174
175        /* Step 2 - find SOA MNAME IP address, add to resolver */
176        query = ldns_pkt_query_new(soa_mname, LDNS_RR_TYPE_A, class, LDNS_RD);
177        if (!query) {
178                return LDNS_STATUS_ERR;
179        }
180        soa_mname = NULL;
181
182        ldns_pkt_set_random_id(query);
183        if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
184                ldns_pkt_free(query);
185                return LDNS_STATUS_ERR;
186        }
187        ldns_pkt_free(query);
188        if (!resp) {
189                return LDNS_STATUS_ERR;
190        }
191
192        if (ldns_pkt_ancount(resp) == 0) {
193                ldns_pkt_free(resp);
194                return LDNS_STATUS_ERR;
195        }
196
197        /* XXX There may be more than one answer RR here. */
198        rr = ldns_rr_list_pop_rr(ldns_pkt_answer(resp));
199        ipaddr = ldns_rr_rdf(rr, 0);
200
201        /* Put the SOA mname IP first in the nameserver list. */
202        nslist = ldns_resolver_nameservers(r);
203        for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
204                if (ldns_rdf_compare(ipaddr, nslist[i]) == 0) {
205                        if (i) {
206                                tmp = nslist[0];
207                                nslist[0] = nslist[i];
208                                nslist[i] = tmp;
209                        }
210                        break;
211                }
212        }
213        if (i >= ldns_resolver_nameserver_count(r)) {
214                /* SOA mname was not part of the resolver so add it first. */
215                (void) ldns_resolver_push_nameserver(r, ipaddr);
216                nslist = ldns_resolver_nameservers(r);
217                i = ldns_resolver_nameserver_count(r) - 1;
218                tmp = nslist[0];
219                nslist[0] = nslist[i];
220                nslist[i] = tmp;
221        }
222        ldns_pkt_free(resp);
223
224        /* Make sure to ask the first in the list, i.e SOA mname */
225        ldns_resolver_set_random(r, false);
226
227        /* Step 3 - Redo SOA query, sending to SOA MNAME directly. */
228        fqdn_rdf = ldns_dname_new_frm_str(fqdn);
229        query = ldns_pkt_query_new(fqdn_rdf, LDNS_RR_TYPE_SOA, class, LDNS_RD);
230        if (!query) {
231                return LDNS_STATUS_ERR;
232        }
233        fqdn_rdf = NULL;
234
235        ldns_pkt_set_random_id(query);
236        if (ldns_resolver_send_pkt(&resp, r, query) != LDNS_STATUS_OK) {
237                ldns_pkt_free(query);
238                return LDNS_STATUS_ERR;
239        }
240        ldns_pkt_free(query);
241        if (!resp) {
242                return LDNS_STATUS_ERR;
243        }
244
245        /* XXX Is it safe to only look in authority section here, too? */
246        while ((soa_rr = ldns_rr_list_pop_rr(ldns_pkt_authority(resp)))) {
247                if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA)
248                        continue;
249                /* [RFC1035 3.3.13] */
250                soa_mname = ldns_rdf_clone(ldns_rr_rdf(soa_rr, 0));
251                soa_zone = ldns_rdf_clone(ldns_rr_owner(soa_rr));
252                break;
253        }
254        ldns_pkt_free(resp);
255        if (!soa_rr) {
256                return LDNS_STATUS_ERR;
257        }
258
259        /* That seems to have worked, pass results to caller. */
260        *zone_rdf = soa_zone;
261        *mname_rdf = soa_mname;
262        return LDNS_STATUS_OK;
263}       
264
265/*
266 * ldns_update_{get,set}_{zo,pr,up,ad}count
267 */
268
269uint16_t
270ldns_update_zocount(const ldns_pkt *p)
271{
272        return ldns_pkt_qdcount(p);
273}
274
275uint16_t
276ldns_update_prcount(const ldns_pkt *p)
277{
278        return ldns_pkt_ancount(p);
279}
280
281uint16_t
282ldns_update_upcount(const ldns_pkt *p)
283{
284        return ldns_pkt_nscount(p);
285}
286
287uint16_t
288ldns_update_ad(const ldns_pkt *p)
289{
290        return ldns_pkt_arcount(p);
291}
292
293void
294ldns_update_set_zo(ldns_pkt *p, uint16_t v)
295{
296        ldns_pkt_set_qdcount(p, v);
297}
298
299void
300ldns_update_set_prcount(ldns_pkt *p, uint16_t v)
301{
302        ldns_pkt_set_ancount(p, v);
303}
304
305void
306ldns_update_set_upcount(ldns_pkt *p, uint16_t v)
307{
308        ldns_pkt_set_nscount(p, v);
309}
310
311void
312ldns_update_set_adcount(ldns_pkt *p, uint16_t v)
313{
314        ldns_pkt_set_arcount(p, v);
315}
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us