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