1 #include <sys/socket.h>
8 flxServer *flx_server_new(GMainContext *c) {
9 flxServer *s = g_new(flxServer, 1);
12 g_main_context_ref(c);
15 s->context = g_main_context_default();
18 s->rrset_by_id = g_hash_table_new(g_int_hash, g_int_equal);
19 s->rrset_by_name = g_hash_table_new(g_str_hash, g_str_equal);
22 s->monitor = flx_interface_monitor_new(s->context);
27 void flx_server_free(flxServer* s) {
30 flx_interface_monitor_free(s->monitor);
32 flx_server_remove(s, 0);
34 g_hash_table_destroy(s->rrset_by_id);
35 g_hash_table_destroy(s->rrset_by_name);
36 g_main_context_unref(s->context);
40 gint flx_server_get_next_id(flxServer *s) {
43 return s->current_id++;
46 void flx_server_add_rr(flxServer *s, gint id, gint interface, const flxRecord *rr) {
54 e = g_new(flxEntry, 1);
55 flx_record_copy_normalize(&e->rr, rr);
57 e->interface = interface;
59 /* Insert into linked list */
61 if ((e->next = s->entries))
65 /* Insert into hash table indexed by id */
67 if ((e->next_by_id = g_hash_table_lookup(s->rrset_by_id, &id)))
68 e->next_by_id->prev = e;
69 g_hash_table_replace(s->rrset_by_id, &e->id, e);
71 /* Insert into hash table indexed by name */
72 e->prev_by_name = NULL;
73 if ((e->next_by_name = g_hash_table_lookup(s->rrset_by_name, e->rr.name)))
74 e->next_by_name->prev = e;
75 g_hash_table_replace(s->rrset_by_name, e->rr.name, e);
78 void flx_server_add(flxServer *s, gint id, gint interface, const gchar *name, guint16 type, gconstpointer data, guint size) {
85 rr.name = (gchar*) name;
87 rr.class = FLX_DNS_CLASS_IN;
88 rr.data = (gpointer) data;
90 rr.ttl = FLX_DEFAULT_TTL;
91 flx_server_add_rr(s, id, interface, &rr);
94 const flxRecord *flx_server_iterate(flxServer *s, gint id, void **state) {
95 flxEntry **e = (flxEntry**) state;
100 *e = id > 0 ? (*e)->next_by_id : (*e)->next;
102 *e = id > 0 ? g_hash_table_lookup(s->rrset_by_id, &id) : s->entries;
110 static void free_entry(flxServer*s, flxEntry *e) {
113 /* Remove from linked list */
115 e->prev->next = e->next;
117 s->entries = e->next;
120 e->next->prev = e->prev;
122 /* Remove from hash table indexed by id */
124 e->prev_by_id = e->next_by_id;
127 g_hash_table_replace(s->rrset_by_id, &e->next_by_id->id, e->next_by_id);
129 g_hash_table_remove(s->rrset_by_id, &e->id);
133 e->next_by_id->prev_by_id = e->prev_by_id;
135 /* Remove from hash table indexed by name */
137 e->prev_by_name = e->next_by_name;
140 g_hash_table_replace(s->rrset_by_name, &e->next_by_name->rr.name, e->next_by_name);
142 g_hash_table_remove(s->rrset_by_name, &e->rr.name);
146 e->next_by_name->prev_by_name = e->prev_by_name;
149 void flx_server_remove(flxServer *s, gint id) {
154 free_entry(s, s->entries);
158 while ((e = g_hash_table_lookup(s->rrset_by_id, &id)))
163 flxRecord *flx_record_copy_normalize(flxRecord *ret_dest, const flxRecord*src) {
168 ret_dest->name = flx_normalize_name(src->name);
169 ret_dest->data = g_memdup(src->data, src->size);
174 static const gchar *dns_class_to_string(guint16 class) {
175 if (class == FLX_DNS_CLASS_IN)
181 static const gchar *dns_type_to_string(guint16 type) {
185 case FLX_DNS_TYPE_AAAA:
187 case FLX_DNS_TYPE_PTR:
189 case FLX_DNS_TYPE_HINFO:
191 case FLX_DNS_TYPE_TXT:
198 void flx_server_dump(flxServer *s, FILE *f) {
203 for (e = s->entries; e; e = e->next) {
205 fprintf(f, "%i: %-40s %-8s %-8s ", e->interface, e->rr.name, dns_class_to_string(e->rr.class), dns_type_to_string(e->rr.type));
209 if (e->rr.class == FLX_DNS_CLASS_IN) {
210 if (e->rr.type == FLX_DNS_TYPE_A)
211 inet_ntop(AF_INET, e->rr.data, t, sizeof(t));
212 else if (e->rr.type == FLX_DNS_TYPE_AAAA)
213 inet_ntop(AF_INET6, e->rr.data, t, sizeof(t));
214 else if (e->rr.type == FLX_DNS_TYPE_PTR)
215 g_strlcpy(t, e->rr.data, sizeof(t));
216 else if (e->rr.type == FLX_DNS_TYPE_HINFO) {
219 if ((s2 = memchr(e->rr.data, 0, e->rr.size))) {
221 if (memchr(s2, 0, e->rr.size - ((char*) s2 - (char*) e->rr.data)))
222 snprintf(t, sizeof(t), "'%s' '%s'", (char*) e->rr.data, s2);
228 fprintf(f, "%s\n", t);
232 void flx_server_add_address(flxServer *s, gint id, gint interface, const gchar *name, flxAddress *a) {
238 n = flx_normalize_name(name);
240 if (a->family == AF_INET) {
243 flx_server_add(s, id, interface, n, FLX_DNS_TYPE_A, &a->ipv4, sizeof(a->ipv4));
245 r = flx_reverse_lookup_name_ipv4(&a->ipv4);
247 flx_server_add(s, id, interface, r, FLX_DNS_TYPE_PTR, n, strlen(n)+1);
253 flx_server_add(s, id, interface, n, FLX_DNS_TYPE_AAAA, &a->ipv6, sizeof(a->ipv6));
255 r = flx_reverse_lookup_name_ipv6_arpa(&a->ipv6);
257 flx_server_add(s, id, interface, r, FLX_DNS_TYPE_PTR, n, strlen(n)+1);
260 r = flx_reverse_lookup_name_ipv6_int(&a->ipv6);
262 flx_server_add(s, id, interface, r, FLX_DNS_TYPE_PTR, n, strlen(n)+1);