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 manipulate a zone
38  *
39  *  Functions used to manipulate a zone
40  *
41  * @{
42  */
43 
44 #pragma once
45 
46 #include <dnscore/sys_types.h>
47 #include <dnscore/rfc.h>
48 
49 #ifdef	__cplusplus
50 extern "C"
51 {
52 #endif
53 
54 #define ZONEFILE_ERROR_BASE                       0x800a0000
55 #define ZONEFILE_ERROR_CODE(code_)                ((s32)(ZONEFILE_ERROR_BASE+(code_)))
56 
57 #define ZONEFILE_FEATURE_NOT_SUPPORTED            ZONEFILE_ERROR_CODE(0x0001)
58 #define ZONEFILE_EXPECTED_FILE_PATH               ZONEFILE_ERROR_CODE(0x0002)
59 #define ZONEFILE_SOA_WITHOUT_CLASS                ZONEFILE_ERROR_CODE(0x0003)
60 #define ZONEFILE_SALT_TOO_BIG                     ZONEFILE_ERROR_CODE(0x0011)
61 #define ZONEFILE_TEXT_TOO_BIG                     ZONEFILE_ERROR_CODE(0x0012)
62 #define ZONEFILE_FLAGS_TOO_BIG                    ZONEFILE_ERROR_CODE(0x0013)
63 #define ZONEFILE_SERVICE_TOO_BIG                  ZONEFILE_ERROR_CODE(0x0014)
64 #define ZONEFILE_REGEX_TOO_BIG                    ZONEFILE_ERROR_CODE(0x0015)
65 #define ZONEFILE_RDATA_PARSE_ERROR                ZONEFILE_ERROR_CODE(0x0016)
66 #define ZONEFILE_RDATA_BUFFER_TOO_SMALL           ZONEFILE_ERROR_CODE(0x0017)
67 #define ZONEFILE_RDATA_SIZE_MISMATCH              ZONEFILE_ERROR_CODE(0x0018)
68 
69 /**
70  * Structure used to describe a resource record from a zone.
71  *
72  * Meant to be used by the zone reader modules :
73  *
74  * TEXT FILE
75  * AXFR FILE
76  *
77  */
78 
79 #define DNSRR_TAG 0x5252534e44
80 
81 typedef struct resource_record resource_record;
82 struct resource_record
83 {
84     /* Next resource record */
85     resource_record                                                  *next;
86 
87     s32                                                                ttl;
88     /* Contains one of the RR TYPE codes */
89     u16                                                               type;
90     /* Contains one of the RR CLASS codes */
91     u16                                                              class; /* should be renamed to something else */
92 
93     u16                                                         rdata_size;
94 
95     /* The name of the node to which this resource record pertains */
96     u8                                              name[MAX_DOMAIN_LENGTH];
97 
98     u8                                              rdata[RDATA_MAX_LENGTH];
99 };
100 
101 #if MAX_DOMAIN_LENGTH < 255
102 #error "MAX_DOMAIN_LENGTH must be 255 at least"
103 #endif
104 
105 
resource_record_init(resource_record * entry)106 static inline void resource_record_init(resource_record* entry)
107 {
108     memset(entry, 0, (offsetof(resource_record, name) + 7) & ~7);
109     /*
110     entry->next    = NULL;
111     entry->ttl     = 0;
112     entry->type    = 0;
113     entry->class   = 0;
114 
115     entry->rdata_size = 0;
116 
117     entry->name[0] = 0;
118     entry->name[1] = 0;
119      */
120 }
121 
resource_record_copy(resource_record * entry,const resource_record * source)122 static inline void resource_record_copy(resource_record* entry, const resource_record* source)
123 {
124     memcpy(entry, source, offsetof(resource_record, name));
125     dnsname_copy(entry->name, source->name);
126     memcpy(entry->rdata, source->rdata, source->rdata_size);
127 }
128 
resource_record_equals(resource_record * entry,const resource_record * source)129 static inline bool resource_record_equals(resource_record* entry, const resource_record* source)
130 {
131     if(memcmp(entry, source, offsetof(resource_record, name)) == 0)
132     {
133         if(dnsname_equals(entry->name, source->name))
134         {
135             if(memcmp(entry->rdata, source->rdata, source->rdata_size) == 0)
136             {
137                 return TRUE;
138             }
139         }
140     }
141 
142     return FALSE;
143 }
144 
resource_record_init_from(resource_record * entry,const resource_record * source)145 static inline void resource_record_init_from(resource_record* entry, const resource_record* source)
146 {
147     resource_record_copy(entry, source);
148     entry->next = NULL;
149 }
150 
resource_record_freecontent(resource_record * entry)151 static inline void resource_record_freecontent(resource_record* entry)
152 {
153     yassert(entry != NULL);
154     (void)entry;
155 }
156 
resource_record_resetcontent(resource_record * entry)157 static inline void resource_record_resetcontent(resource_record* entry)
158 {
159     yassert(entry != NULL);
160 
161     /* Resets the RDATA output stream so we can fill it again */
162 
163     entry->rdata_size = 0;
164 }
165 
resource_record_size(resource_record * entry)166 static inline s32 resource_record_size(resource_record* entry)
167 {
168     return entry->rdata_size + 10 + dnsname_len(entry->name);
169 }
170 
171 struct zone_reader_vtbl;
172 
173 typedef struct zone_reader zone_reader;
174 struct zone_reader
175 {
176     void *data;
177     const struct zone_reader_vtbl *vtbl;
178 };
179 
180 typedef ya_result zone_reader_read_record_method(zone_reader *, resource_record *);
181 typedef ya_result zone_reader_unread_record_method(zone_reader *, resource_record *);
182 typedef ya_result zone_reader_free_record_method(zone_reader *, resource_record *);
183 typedef void zone_reader_close_method(zone_reader *);
184 typedef void zone_reader_handle_error_method(zone_reader *zr, ya_result error_code); // used for cleaning up after an error (AXFR feedback)
185 typedef const char* zone_reader_get_last_error_message_method(zone_reader *zr);
186 typedef bool zone_reader_canwriteback_method(zone_reader *);
187 
188 typedef struct zone_reader_vtbl zone_reader_vtbl;
189 struct zone_reader_vtbl
190 {
191     zone_reader_read_record_method *read_record;
192     zone_reader_unread_record_method *unread_record;
193     zone_reader_free_record_method *free_record;
194     zone_reader_close_method *close;
195     zone_reader_handle_error_method *handle_error;
196     zone_reader_canwriteback_method *can_write_back;
197     zone_reader_get_last_error_message_method *get_last_error_message;
198     const char* __class__;
199 };
200 
201 #define zone_reader_read_record(zr__,rr__) (zr__)->vtbl->read_record((zr__),(rr__))
202 #define zone_reader_free_record(zr__,rr__) (zr__)->vtbl->free_record((zr__),(rr__))
203 #define zone_reader_handle_error(zr__,rr__) (zr__)->vtbl->handle_error((zr__),(rr__))
204 #define zone_reader_close(zr__) (zr__)->vtbl->close((zr__))
205 #define zone_reader_canwriteback(zr__) (zr__)->vtbl->can_write_back((zr__))
206 #define zone_reader_get_last_error_message(zr__) (zr__)->vtbl->get_last_error_message((zr__))
207 #define zone_reader_unread_record(zr__,rr__) (zr__)->vtbl->unread_record((zr__),(rr__))
208 
209 #define zone_reader_rdata(zr__)      ((zr__).rdata)
210 #define zone_reader_rdata_size(zr__) ((zr__).rdata_size)
211 
212 #ifdef	__cplusplus
213 }
214 #endif
215 
216 /** @} */
217