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