]> git.meshlink.io Git - catta/blob - rr.c
* add cache management
[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, gconstpointer data, guint16 size, guint32 ttl) {
49     flxRecord *r;
50     
51     g_assert(k);
52     g_assert(data);
53     g_assert(size > 0);
54     g_assert(ttl > 0);
55
56     r = g_new(flxRecord, 1);
57     r->ref = 1;
58     r->key = flx_key_ref(k);
59     r->data = g_memdup(data, size);
60     r->size = size;
61     r->ttl = ttl;
62
63     return r;
64 }
65
66 flxRecord *flx_record_new_full(const gchar *name, guint16 class, guint16 type, gconstpointer data, guint16 size, guint32 ttl) {
67     flxRecord *r;
68     flxKey *k;
69     
70     k = flx_key_new(name, class, type);
71     r = flx_record_new(k, data, size, ttl);
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         flx_key_unref(r->key);
91         g_free(r->data);
92         g_free(r);
93     }
94 }
95
96 const gchar *flx_dns_class_to_string(guint16 class) {
97     if (class == FLX_DNS_CLASS_IN)
98         return "IN";
99
100     return NULL;
101 }
102
103 const gchar *flx_dns_type_to_string(guint16 type) {
104     switch (type) {
105         case FLX_DNS_TYPE_CNAME:
106             return "CNAME";
107         case FLX_DNS_TYPE_A:
108             return "A";
109         case FLX_DNS_TYPE_AAAA:
110             return "AAAA";
111         case FLX_DNS_TYPE_PTR:
112             return "PTR";
113         case FLX_DNS_TYPE_HINFO:
114             return "HINFO";
115         case FLX_DNS_TYPE_TXT:
116             return "TXT";
117         case FLX_DNS_TYPE_SRV:
118             return "SRV";
119         default:
120             return NULL;
121     }
122 }
123
124
125 gchar *flx_key_to_string(flxKey *k) {
126     return g_strdup_printf("%s\t%s\t%s",
127                            k->name,
128                            flx_dns_class_to_string(k->class),
129                            flx_dns_type_to_string(k->type));
130 }
131
132 gchar *flx_record_to_string(flxRecord *r) {
133     gchar *p, *s;
134     char t[257] = "<unparsable>";
135
136     switch (r->key->type) {
137         case FLX_DNS_TYPE_A:
138             inet_ntop(AF_INET, r->data, t, sizeof(t));
139             break;
140             
141         case FLX_DNS_TYPE_AAAA:
142             inet_ntop(AF_INET6, r->data, t, sizeof(t));
143             break;
144             
145         case FLX_DNS_TYPE_PTR:
146         case FLX_DNS_TYPE_TXT: {
147             size_t l;
148         
149             l = r->size;
150             if (l > sizeof(t)-1)
151                 l = sizeof(t)-1;
152             
153             memcpy(t, r->data, l);
154             t[l] = 0;
155             break;
156         }
157
158         case FLX_DNS_TYPE_HINFO: {
159             char *s2;
160             
161             if ((s2 = memchr(r->data, 0, r->size))) {
162                 s2++;
163                 if (memchr(s2, 0, r->size - ((char*) s2 - (char*) r->data)))
164                     snprintf(t, sizeof(t), "'%s' '%s'", (char*) r->data, s2);
165             }
166
167             break;
168         }
169
170         case FLX_DNS_TYPE_SRV: {
171             char k[257];
172             size_t l;
173
174             l = r->size-6;
175             if (l > sizeof(k)-1)
176                 l = sizeof(k)-1;
177             
178             memcpy(k, r->data+6, l);
179             k[l] = 0;
180             
181             snprintf(t, sizeof(t), "%u %u %u %s",
182                      ntohs(((guint16*) r->data)[0]),
183                      ntohs(((guint16*) r->data)[1]),
184                      ntohs(((guint16*) r->data)[2]),
185                      k);
186         }
187     }
188
189     p = flx_key_to_string(r->key);
190     s = g_strdup_printf("%s %s ; ttl=%u", p, t, r->ttl);
191     g_free(p);
192     
193     return s;
194 }
195
196 gboolean flx_key_equal(const flxKey *a, const flxKey *b) {
197     g_assert(a);
198     g_assert(b);
199
200 /*     g_message("equal: %p %p", a, b); */
201     
202     return strcmp(a->name, b->name) == 0 && a->type == b->type && a->class == b->class;
203 }
204
205 guint flx_key_hash(const flxKey *k) {
206     g_assert(k);
207
208     return g_str_hash(k->name) + k->type + k->class;
209 }
210
211 gboolean flx_record_equal(const flxRecord *a, const flxRecord *b) {
212     g_assert(a);
213     g_assert(b);
214
215     return flx_key_equal(a->key, b->key) &&
216         a->ttl == b->ttl &&
217         a->size == b->size &&
218         memcmp(a->data, b->data, a->size) == 0;
219 }