]> git.meshlink.io Git - catta/blob - rr.c
assorted work:
[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     gchar *t;
245     g_assert(a);
246     g_assert(b);
247     g_assert(a->key->type == b->key->type);
248
249     t = flx_record_to_string(a);
250     g_message("comparing %s", t);
251     g_free(t);
252
253     t = flx_record_to_string(b);
254     g_message("and %s", t);
255     g_free(t);
256
257     
258     switch (a->key->type) {
259         case FLX_DNS_TYPE_SRV:
260             return
261                 a->data.srv.priority == b->data.srv.priority &&
262                 a->data.srv.weight == b->data.srv.weight &&
263                 a->data.srv.port == b->data.srv.port &&
264                 !strcmp(a->data.srv.name, b->data.srv.name);
265
266         case FLX_DNS_TYPE_PTR:
267         case FLX_DNS_TYPE_CNAME:
268             return !strcmp(a->data.ptr.name, b->data.ptr.name);
269
270         case FLX_DNS_TYPE_HINFO:
271             return
272                 !strcmp(a->data.hinfo.cpu, b->data.hinfo.cpu) &&
273                 !strcmp(a->data.hinfo.os, b->data.hinfo.os);
274
275         case FLX_DNS_TYPE_TXT:
276             return flx_string_list_equal(a->data.txt.string_list, b->data.txt.string_list);
277
278         case FLX_DNS_TYPE_A:
279             return memcmp(&a->data.a.address, &b->data.a.address, sizeof(flxIPv4Address)) == 0;
280
281         case FLX_DNS_TYPE_AAAA:
282             return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(flxIPv6Address)) == 0;
283
284         default:
285             return a->data.generic.size == b->data.generic.size &&
286                 (a->data.generic.size == 0 || memcmp(a->data.generic.data, b->data.generic.data, a->data.generic.size) == 0);
287     }
288     
289 }
290
291 gboolean flx_record_equal_no_ttl(const flxRecord *a, const flxRecord *b) {
292     g_assert(a);
293     g_assert(b);
294
295     return
296         flx_key_equal(a->key, b->key) &&
297         rdata_equal(a, b);
298 }
299
300
301 flxRecord *flx_record_copy(flxRecord *r) {
302     flxRecord *copy;
303
304     copy = g_new(flxRecord, 1);
305     copy->ref = 1;
306     copy->key = flx_key_ref(r->key);
307     copy->ttl = r->ttl;
308
309     switch (r->key->type) {
310         case FLX_DNS_TYPE_PTR:
311         case FLX_DNS_TYPE_CNAME:
312             copy->data.ptr.name = g_strdup(r->data.ptr.name);
313             break;
314
315         case FLX_DNS_TYPE_SRV:
316             copy->data.srv.priority = r->data.srv.priority;
317             copy->data.srv.weight = r->data.srv.weight;
318             copy->data.srv.port = r->data.srv.port;
319             copy->data.srv.name = g_strdup(r->data.srv.name);
320             break;
321
322         case FLX_DNS_TYPE_HINFO:
323             copy->data.hinfo.os = g_strdup(r->data.hinfo.os);
324             copy->data.hinfo.cpu = g_strdup(r->data.hinfo.cpu);
325             break;
326
327         case FLX_DNS_TYPE_TXT:
328             copy->data.txt.string_list = flx_string_list_copy(r->data.txt.string_list);
329             break;
330
331         case FLX_DNS_TYPE_A:
332             copy->data.a.address = r->data.a.address;
333             break;
334
335         case FLX_DNS_TYPE_AAAA:
336             copy->data.aaaa.address = r->data.aaaa.address;
337             break;
338
339         default:
340             copy->data.generic.data = g_memdup(r->data.generic.data, r->data.generic.size);
341             copy->data.generic.size = r->data.generic.size;
342             break;
343                 
344     }
345
346     return copy;
347 }