]> git.meshlink.io Git - catta/blob - rr.c
fix some memory corruption bugs
[catta] / rr.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <sys/socket.h>
5 #include <arpa/inet.h>
6
7 #include "util.h"
8 #include "rr.h"
9
10 flxKey *flx_key_new(const gchar *name, guint16 class, guint16 type) {
11     flxKey *k;
12     g_assert(name);
13
14     k = g_new(flxKey, 1);
15     k->ref = 1;
16     k->name = flx_normalize_name(name);    
17     k->class = class;
18     k->type = type;
19
20 /*     g_message("%p %% ref=1", k); */
21     
22     return k;
23 }
24
25 flxKey *flx_key_ref(flxKey *k) {
26     g_assert(k);
27     g_assert(k->ref >= 1);
28
29     k->ref++;
30
31 /*     g_message("%p ++ ref=%i", k, k->ref); */
32
33     return k;
34 }
35
36 void flx_key_unref(flxKey *k) {
37     g_assert(k);
38     g_assert(k->ref >= 1);
39
40 /*     g_message("%p -- ref=%i", k, k->ref-1); */
41     
42     if ((--k->ref) <= 0) {
43         g_free(k->name);
44         g_free(k);
45     }
46 }
47
48 flxRecord *flx_record_new(flxKey *k) {
49     flxRecord *r;
50     
51     g_assert(k);
52     
53     r = g_new(flxRecord, 1);
54     r->ref = 1;
55     r->key = flx_key_ref(k);
56
57     memset(&r->data, 0, sizeof(r->data));
58
59     r->ttl = FLX_DEFAULT_TTL;
60
61     return r;
62 }
63
64 flxRecord *flx_record_new_full(const gchar *name, guint16 class, guint16 type) {
65     flxRecord *r;
66     flxKey *k;
67
68     g_assert(name);
69     
70     k = flx_key_new(name, class, type);
71     r = flx_record_new(k);
72     flx_key_unref(k);
73
74     return r;
75 }
76
77 flxRecord *flx_record_ref(flxRecord *r) {
78     g_assert(r);
79     g_assert(r->ref >= 1);
80
81     r->ref++;
82     return r;
83 }
84
85 void flx_record_unref(flxRecord *r) {
86     g_assert(r);
87     g_assert(r->ref >= 1);
88
89     if ((--r->ref) <= 0) {
90         switch (r->key->type) {
91
92             case FLX_DNS_TYPE_SRV:
93                 g_free(r->data.srv.name);
94                 break;
95
96             case FLX_DNS_TYPE_PTR:
97             case FLX_DNS_TYPE_CNAME:
98                 g_free(r->data.ptr.name);
99                 break;
100
101             case FLX_DNS_TYPE_HINFO:
102                 g_free(r->data.hinfo.cpu);
103                 g_free(r->data.hinfo.os);
104                 break;
105
106             case FLX_DNS_TYPE_TXT:
107                 flx_string_list_free(r->data.txt.string_list);
108                 break;
109
110             case FLX_DNS_TYPE_A:
111             case FLX_DNS_TYPE_AAAA:
112                 break;
113             
114             default:
115                 g_free(r->data.generic.data);
116         }
117         
118         flx_key_unref(r->key);
119         g_free(r);
120     }
121 }
122
123 const gchar *flx_dns_class_to_string(guint16 class) {
124     if (class == FLX_DNS_CLASS_IN)
125         return "IN";
126
127     return NULL;
128 }
129
130 const gchar *flx_dns_type_to_string(guint16 type) {
131     switch (type) {
132         case FLX_DNS_TYPE_CNAME:
133             return "CNAME";
134         case FLX_DNS_TYPE_A:
135             return "A";
136         case FLX_DNS_TYPE_AAAA:
137             return "AAAA";
138         case FLX_DNS_TYPE_PTR:
139             return "PTR";
140         case FLX_DNS_TYPE_HINFO:
141             return "HINFO";
142         case FLX_DNS_TYPE_TXT:
143             return "TXT";
144         case FLX_DNS_TYPE_SRV:
145             return "SRV";
146         default:
147             return NULL;
148     }
149 }
150
151
152 gchar *flx_key_to_string(const flxKey *k) {
153     return g_strdup_printf("%s\t%s\t%s",
154                            k->name,
155                            flx_dns_class_to_string(k->class),
156                            flx_dns_type_to_string(k->type));
157 }
158
159 gchar *flx_record_to_string(const flxRecord *r) {
160     gchar *p, *s;
161     char buf[257], *t, *d = NULL;
162
163     switch (r->key->type) {
164         case FLX_DNS_TYPE_A:
165             inet_ntop(AF_INET, &r->data.a.address.address, t = buf, sizeof(buf));
166             break;
167             
168         case FLX_DNS_TYPE_AAAA:
169             inet_ntop(AF_INET6, &r->data.aaaa.address.address, t = buf, sizeof(buf));
170             break;
171             
172         case FLX_DNS_TYPE_PTR:
173         case FLX_DNS_TYPE_CNAME :
174
175             t = r->data.ptr.name;
176             break;
177
178         case FLX_DNS_TYPE_TXT:
179             t = d = flx_string_list_to_string(r->data.txt.string_list);
180             break;
181
182         case FLX_DNS_TYPE_HINFO:
183
184             snprintf(t = buf, sizeof(buf), "\"%s\" \"%s\"", r->data.hinfo.cpu, r->data.hinfo.os);
185             break;
186
187         case FLX_DNS_TYPE_SRV:
188
189             snprintf(t = buf, sizeof(buf), "%u %u %u %s",
190                      r->data.srv.priority,
191                      r->data.srv.weight,
192                      r->data.srv.port,
193                      r->data.srv.name);
194
195             break;
196     }
197
198     p = flx_key_to_string(r->key);
199     s = g_strdup_printf("%s %s ; ttl=%u", p, t ? t : "<unparsable>", r->ttl);
200     g_free(p);
201     g_free(d);
202     
203     return s;
204 }
205
206 gboolean flx_key_equal(const flxKey *a, const flxKey *b) {
207     g_assert(a);
208     g_assert(b);
209
210 /*     g_message("equal: %p %p", a, b); */
211     
212     return strcmp(a->name, b->name) == 0 &&
213         a->type == b->type &&
214         a->class == b->class;
215 }
216
217 gboolean flx_key_pattern_match(const flxKey *pattern, const flxKey *k) {
218     g_assert(pattern);
219     g_assert(k);
220
221 /*     g_message("equal: %p %p", a, b); */
222
223     g_assert(!flx_key_is_pattern(k));
224     
225     return strcmp(pattern->name, k->name) == 0 &&
226         (pattern->type == k->type || pattern->type == FLX_DNS_TYPE_ANY) &&
227         pattern->class == k->class;
228 }
229
230 gboolean flx_key_is_pattern(const flxKey *k) {
231     g_assert(k);
232
233     return k->type == FLX_DNS_TYPE_ANY;
234 }
235
236
237 guint flx_key_hash(const flxKey *k) {
238     g_assert(k);
239
240     return g_str_hash(k->name) + k->type + k->class;
241 }
242
243 static gboolean rdata_equal(const flxRecord *a, const flxRecord *b) {
244     g_assert(a);
245     g_assert(b);
246     g_assert(a->key->type == b->key->type);
247
248 /*     t = flx_record_to_string(a); */
249 /*     g_message("comparing %s", t); */
250 /*     g_free(t); */
251
252 /*     t = flx_record_to_string(b); */
253 /*     g_message("and %s", t); */
254 /*     g_free(t); */
255
256     
257     switch (a->key->type) {
258         case FLX_DNS_TYPE_SRV:
259             return
260                 a->data.srv.priority == b->data.srv.priority &&
261                 a->data.srv.weight == b->data.srv.weight &&
262                 a->data.srv.port == b->data.srv.port &&
263                 !strcmp(a->data.srv.name, b->data.srv.name);
264
265         case FLX_DNS_TYPE_PTR:
266         case FLX_DNS_TYPE_CNAME:
267             return !strcmp(a->data.ptr.name, b->data.ptr.name);
268
269         case FLX_DNS_TYPE_HINFO:
270             return
271                 !strcmp(a->data.hinfo.cpu, b->data.hinfo.cpu) &&
272                 !strcmp(a->data.hinfo.os, b->data.hinfo.os);
273
274         case FLX_DNS_TYPE_TXT:
275             return flx_string_list_equal(a->data.txt.string_list, b->data.txt.string_list);
276
277         case FLX_DNS_TYPE_A:
278             return memcmp(&a->data.a.address, &b->data.a.address, sizeof(flxIPv4Address)) == 0;
279
280         case FLX_DNS_TYPE_AAAA:
281             return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(flxIPv6Address)) == 0;
282
283         default:
284             return a->data.generic.size == b->data.generic.size &&
285                 (a->data.generic.size == 0 || memcmp(a->data.generic.data, b->data.generic.data, a->data.generic.size) == 0);
286     }
287     
288 }
289
290 gboolean flx_record_equal_no_ttl(const flxRecord *a, const flxRecord *b) {
291     g_assert(a);
292     g_assert(b);
293
294     return
295         flx_key_equal(a->key, b->key) &&
296         rdata_equal(a, b);
297 }
298
299
300 flxRecord *flx_record_copy(flxRecord *r) {
301     flxRecord *copy;
302
303     copy = g_new(flxRecord, 1);
304     copy->ref = 1;
305     copy->key = flx_key_ref(r->key);
306     copy->ttl = r->ttl;
307
308     switch (r->key->type) {
309         case FLX_DNS_TYPE_PTR:
310         case FLX_DNS_TYPE_CNAME:
311             copy->data.ptr.name = g_strdup(r->data.ptr.name);
312             break;
313
314         case FLX_DNS_TYPE_SRV:
315             copy->data.srv.priority = r->data.srv.priority;
316             copy->data.srv.weight = r->data.srv.weight;
317             copy->data.srv.port = r->data.srv.port;
318             copy->data.srv.name = g_strdup(r->data.srv.name);
319             break;
320
321         case FLX_DNS_TYPE_HINFO:
322             copy->data.hinfo.os = g_strdup(r->data.hinfo.os);
323             copy->data.hinfo.cpu = g_strdup(r->data.hinfo.cpu);
324             break;
325
326         case FLX_DNS_TYPE_TXT:
327             copy->data.txt.string_list = flx_string_list_copy(r->data.txt.string_list);
328             break;
329
330         case FLX_DNS_TYPE_A:
331             copy->data.a.address = r->data.a.address;
332             break;
333
334         case FLX_DNS_TYPE_AAAA:
335             copy->data.aaaa.address = r->data.aaaa.address;
336             break;
337
338         default:
339             copy->data.generic.data = g_memdup(r->data.generic.data, r->data.generic.size);
340             copy->data.generic.size = r->data.generic.size;
341             break;
342                 
343     }
344
345     return copy;
346 }