1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup dnsdbzone Zone related functions
36  *  @ingroup dnsdb
37  *  @brief Functions used to iterate through the labels of a zone
38  *
39  * @{
40  */
41 
42 #include "dnsdb/dnsdb-config.h"
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <dnsdb/avl.h>
46 
47 #include "dnscore/logger.h"
48 #include "dnsdb/zdb_types.h"
49 #include "dnsdb/nsec3_item.h"
50 #include "dnsdb/zdb_rr_label.h"
51 #include "dnsdb/zdb_zone_label_iterator_ex.h"
52 #include "dnsdb/zdb_zone_label_iterator.h"
53 
54 extern logger_handle* g_database_logger;
55 #define MODULE_MSG_HANDLE g_database_logger
56 
57 /**
58  * @brief Initializes a zone label iterator
59  *
60  * Initializes a zone label iterator (iterates zdb_rr_label)
61  *
62  * @param[in] zone The zone to explore
63  * @param[in] iter a pointer to the iterator to initialize
64  *
65  */
66 
67 
68 #define ZLI_DEBUG 0
69 
70 void
zdb_zone_label_iterator_ex_init(zdb_zone_label_iterator_ex * iter,const zdb_zone * zone)71 zdb_zone_label_iterator_ex_init(zdb_zone_label_iterator_ex* iter, const zdb_zone* zone)
72 {
73     memset(iter, 0, sizeof(zdb_zone_label_iterator_ex));
74 
75     //iter->mode = ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS; // set by the memset
76     iter->min_ttl = zone->min_ttl;
77     iter->zone = zone;
78     iter->n3 = zone->nsec.nsec3;
79     iter->pool = &iter->pool_buffer[0];
80     //iter->nsec3_owner = NULL;
81 
82     //iter->nsec3_label.next = NULL;
83     //iter->nsec3_label.sub.count = 0;
84 
85     iter->nsec3_label.resource_record_set = &iter->nsec3_label_nsec3;
86 
87     iter->nsec3_label_nsec3.hash = TYPE_NSEC3;
88     iter->nsec3_label_rrsig.hash = TYPE_RRSIG;
89 
90     zdb_zone_label_iterator_init(&iter->iter.label_iter, zone);
91 }
92 
93 /**
94  * @brief Checks if there is still data available from an iterator
95  *
96  * Checks if there is still data available from an iterator
97  *
98  * @param[in] iter a pointer to the iterator
99  *
100  * @return TRUE if data is available, FALSE otherwise.
101  *
102  */
103 
104 bool
zdb_zone_label_iterator_ex_hasnext(zdb_zone_label_iterator_ex * iter)105 zdb_zone_label_iterator_ex_hasnext(zdb_zone_label_iterator_ex* iter)
106 {
107     bool ret;
108     switch(iter->mode)
109     {
110         case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS:
111         {
112             ret = zdb_zone_label_iterator_hasnext(&iter->iter.label_iter);
113             if(ret)
114             {
115                 return ret;
116             }
117 
118             // end of the labels, prepare the NSEC3 if any
119 
120             if(iter->n3 == NULL)
121             {
122                 return FALSE;
123             }
124 
125             nsec3_iterator_init(&iter->n3->items, &iter->iter.nsec3_iter);
126 
127             iter->mode = ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN; // falls through on purpose
128 
129             FALLTHROUGH // fallthrough
130         }
131         case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN:
132         {
133             ret = nsec3_iterator_hasnext(&iter->iter.nsec3_iter);
134 
135             if(ret)
136             {
137                 iter->pool = &iter->pool_buffer[0];
138                 // get the record and convert it to an zdb_rr_label
139 
140                 nsec3_node *nsec3_node = nsec3_iterator_next_node(&iter->iter.nsec3_iter);
141 
142                 nsec3_zone_item_to_new_zdb_packed_ttlrdata_parm nsec3_parms =
143                     {
144                         iter->n3,
145                         nsec3_node,         /// note:  in an iterator, if used properly, the returned node cannot be NULL
146                         iter->zone->origin,
147                         &iter->pool,
148                         iter->min_ttl
149                     };
150 
151                 nsec3_zone_item_to_new_zdb_packed_ttlrdata(
152                     &nsec3_parms,
153                     &iter->nsec3_owner,
154                     (zdb_packed_ttlrdata**)&iter->nsec3_label_nsec3.data,
155                     (const zdb_packed_ttlrdata**)&iter->nsec3_label_rrsig.data);
156 
157                 // craft an zdb_rr_label that suits our needs
158 
159                 if(iter->nsec3_label_rrsig.data != NULL)
160                 {
161                     iter->nsec3_label_nsec3.balance = -1;
162                     iter->nsec3_label_nsec3.children.lr.left = &iter->nsec3_label_rrsig;
163                 }
164                 else
165                 {
166                     iter->nsec3_label_nsec3.balance = 0;
167                     iter->nsec3_label_nsec3.children.lr.left = NULL;
168                 }
169 
170                 return TRUE;
171             }
172             else
173             {
174                 iter->mode = ZDB_ZONE_LABEL_ITERATOR_END_OF_ITERATION;
175             }
176 
177             // FALLTHROUGH // fallthrough
178             break;
179         }
180     }
181 
182     return FALSE;
183 }
184 
185 /**
186  * @brief Copies the full name of the next label returned by the "next" call.
187  *
188  * Copies the full name of the next label returned by the "next" call.
189  *
190  * @param[in] iter a pointer to the iterator
191  * @param[in] buffer256 a pointer to a buffer that will hold the full dns name
192  *
193  * @return the size of the dns name
194  *
195  */
196 
197 u32
zdb_zone_label_iterator_ex_nextname_to_cstr(zdb_zone_label_iterator_ex * iter,char * buffer256)198 zdb_zone_label_iterator_ex_nextname_to_cstr(zdb_zone_label_iterator_ex* iter, char* buffer256)
199 {
200     u32 ret;
201 
202     switch(iter->mode)
203     {
204         case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS:
205         {
206             ret = zdb_zone_label_iterator_nextname_to_cstr(&iter->iter.label_iter, buffer256);
207             return ret;
208         }
209         case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN:
210         {
211             ret = dnsname_to_cstr(buffer256, iter->nsec3_owner);
212             return ret;
213         }
214     }
215 
216     return 0;
217 }
218 
219 u32
zdb_zone_label_iterator_ex_nextname(zdb_zone_label_iterator_ex * iter,u8 * buffer256)220 zdb_zone_label_iterator_ex_nextname(zdb_zone_label_iterator_ex* iter, u8* buffer256)
221 { /* TOP-DOWN stack */
222     u32 ret;
223 
224     switch(iter->mode)
225     {
226         case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS:
227         {
228             ret = zdb_zone_label_iterator_nextname(&iter->iter.label_iter, buffer256);
229             return ret;
230         }
231         case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN:
232         {
233             ret = dnsname_copy(buffer256, iter->nsec3_owner);
234             return ret;
235         }
236     }
237 
238     return 0;
239 }
240 
241 /**
242  * @brief Returns the next data available from an iterator
243  *
244  * Returns the next data available from an iterator
245  *
246  * @param[in] iter a pointer to the iterator
247  *
248  * @return a pointer to the next label
249  *
250  */
251 
252 zdb_rr_label*
zdb_zone_label_iterator_ex_next(zdb_zone_label_iterator_ex * iter)253 zdb_zone_label_iterator_ex_next(zdb_zone_label_iterator_ex* iter)
254 {
255     zdb_rr_label *ret;
256 
257     switch(iter->mode)
258     {
259         case ZDB_ZONE_LABEL_ITERATOR_ZONE_RECORDS:
260         {
261             ret = zdb_zone_label_iterator_next(&iter->iter.label_iter);
262             return ret;
263         }
264         case ZDB_ZONE_LABEL_ITERATOR_NSEC3_CHAIN:
265         {
266             ret = &iter->nsec3_label;
267 
268             return ret;
269         }
270     }
271 
272     return NULL;
273 }
274 
275 /** @} */
276