nameservice plugin: unlink before freeing db_entries, kill all timers upon termination
[olsrd.git] / lib / nameservice / src / nameservice.c
1 /*
2  * Copyright (c) 2006, Jens Nachtigall <nachtigall@web.de>
3  * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
4  * Copyright (c) 2004, Andreas T√łnnesen(andreto-at-olsr.org)
5  * Copyright (c) 2007, Sven-Ola <sven-ola@gmx.de>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions 
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright notice, 
13  *   this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright notice, 
15  *   this list of conditions and the following disclaimer in the documentation 
16  *   and/or other materials provided with the distribution.
17  * * Neither the name of the UniK olsr daemon nor the names of its contributors 
18  *   may be used to endorse or promote products derived from this software 
19  *   without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
24  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
29  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
30  * OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  */
33
34
35 /*
36  * Dynamic linked library for UniK OLSRd
37  */
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <ctype.h>
44 #include <sys/types.h>
45 #include <regex.h>
46
47 #include "olsr.h"
48 #include "ipcalc.h"
49 #include "net_olsr.h"
50 #include "routing_table.h"
51 #include "mantissa.h"
52 #include "scheduler.h"
53 #include "parser.h"
54 #include "duplicate_set.h"
55 #include "tc_set.h"
56 #include "hna_set.h"
57 #include "mid_set.h"
58 #include "link_set.h"
59
60 #include "plugin_util.h"
61 #include "nameservice.h"
62 #include "mapwrite.h"
63 #include "compat.h"
64
65
66 /* config parameters */
67 static char my_hosts_file[MAX_FILE + 1];
68 static char my_add_hosts[MAX_FILE + 1];
69 static char my_suffix[MAX_SUFFIX];
70 static int my_interval = EMISSION_INTERVAL;
71 static double my_timeout = NAME_VALID_TIME;
72 static char my_resolv_file[MAX_FILE +1];
73 static char my_services_file[MAX_FILE + 1];
74 static char latlon_in_file[MAX_FILE + 1];
75 static char my_latlon_file[MAX_FILE + 1];
76 float my_lat = 0.0, my_lon = 0.0;
77
78 /* the databases (using hashing)
79  * for hostnames, service_lines and dns-servers
80  *
81  * my own hostnames, service_lines and dns-servers
82  * are store in a linked list (without hashing)
83  * */
84 static struct list_node list[HASHSIZE];
85 struct name_entry *my_names = NULL;
86 struct timer_entry *name_table_write = NULL;
87 static olsr_bool name_table_changed = OLSR_TRUE;
88
89 static struct list_node service_list[HASHSIZE];
90 static struct name_entry *my_services = NULL;
91 static olsr_bool service_table_changed = OLSR_TRUE;
92
93 static struct list_node forwarder_list[HASHSIZE];
94 static struct name_entry *my_forwarders = NULL;
95 static olsr_bool forwarder_table_changed = OLSR_TRUE;
96
97 struct list_node latlon_list[HASHSIZE];
98 static olsr_bool latlon_table_changed = OLSR_TRUE;
99
100 /* backoff timer for writing changes into a file */
101 struct timer_entry *write_file_timer = NULL;
102
103 /* periodic message generation */
104 struct timer_entry *msg_gen_timer = NULL;
105
106 /* regular expression to be matched by valid hostnames, compiled in name_init() */
107 static regex_t regex_t_name;
108 static regmatch_t regmatch_t_name;
109
110 /* regular expression to be matched by valid service_lines, compiled in name_init() */
111 static regex_t regex_t_service;
112 static int pmatch_service = 10;
113 static regmatch_t regmatch_t_service[10];
114
115 /**
116  * do initialization
117  */
118 void
119 name_constructor(void) 
120 {
121         int i;
122         
123 #ifdef WIN32
124         int len;
125
126         GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
127         GetWindowsDirectory(my_services_file, MAX_FILE - 12);
128         GetWindowsDirectory(my_resolv_file, MAX_FILE - 12);
129
130         len = strlen(my_hosts_file);
131         if (my_hosts_file[len - 1] != '\\')
132                 my_hosts_file[len++] = '\\';
133         strcpy(my_hosts_file + len, "hosts_olsr");
134         
135         len = strlen(my_services_file);
136         if (my_services_file[len - 1] != '\\')
137                 my_services_file[len++] = '\\';
138         strcpy(my_services_file + len, "services_olsr");
139
140         len = strlen(my_resolv_file);
141         if (my_resolv_file[len - 1] != '\\')
142                 my_resolv_file[len++] = '\\';
143         strcpy(my_resolv_file + len, "resolvconf_olsr");
144 #else
145         strcpy(my_hosts_file, "/var/run/hosts_olsr");
146         strcpy(my_services_file, "/var/run/services_olsr");
147         strcpy(my_resolv_file, "/var/run/resolvconf_olsr");
148 #endif
149
150         my_suffix[0] = '\0';
151         my_add_hosts[0] = '\0';
152         my_latlon_file[0] = '\0';
153         latlon_in_file[0] = '\0';
154         
155         /* init the lists heads */
156         for(i = 0; i < HASHSIZE; i++) {
157                 list_head_init(&list[i]);
158                 list_head_init(&forwarder_list[i]);
159                 list_head_init(&service_list[i]);
160                 list_head_init(&latlon_list[i]);
161         }
162         
163
164 }
165
166
167 static int set_nameservice_server(const char *value, void *data, set_plugin_parameter_addon addon)
168 {
169         union olsr_ip_addr ip;
170         struct name_entry **v = data;
171         if (0 == strlen(value))
172         {
173                 *v = add_name_to_list(*v, "", addon.ui, NULL);
174                 OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value);
175                 return 0;
176         }
177         else if (0 < inet_pton(olsr_cnf->ip_version, value, &ip))
178         {
179                 *v = add_name_to_list(*v, "", addon.ui, &ip);
180                 OLSR_PRINTF(1, "%s got %s\n", "Got", value);
181                 return 0;
182         }
183         else
184         {
185                 OLSR_PRINTF(0, "Illegal IP address \"%s\"", value);
186         }
187         return 1;
188 }
189
190 static int set_nameservice_name(const char *value, void *data, set_plugin_parameter_addon addon)
191 {
192         struct name_entry **v = data;
193         if (0 < strlen(value))
194         {
195                 *v = add_name_to_list(*v, value, addon.ui, NULL);
196                 OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value);
197                 return 0;
198         }
199         else
200         {
201                 OLSR_PRINTF(0, "Illegal name \"%s\"", value);
202         }
203         return 1;
204 }
205
206 static int set_nameservice_host(const char *value, void *data, set_plugin_parameter_addon addon)
207 {
208         union olsr_ip_addr ip;
209         struct name_entry **v = data;
210         if (0 < inet_pton(olsr_cnf->ip_version, addon.pc, &ip))
211         {
212                 // the IP is validated later
213                 *v = add_name_to_list(*v, value, NAME_HOST, &ip);
214                 OLSR_PRINTF(1, "%s: %s got %s\n", "Got", addon.pc, value);
215                 return 0;
216         }
217         else
218         {
219                 OLSR_PRINTF(0, "%s: Illegal IP address \"%s\"", addon.pc, value);
220         }
221         return 1;
222 }
223
224 static int set_nameservice_float(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused)))
225 {
226         const float thefloat = atof(value);
227         if (data != NULL)
228         {
229                 float *v = data;
230                 *v = thefloat;
231                 OLSR_PRINTF(1, "%s float %f\n", "Got", thefloat);
232         }
233         else
234         {
235                 OLSR_PRINTF(0, "%s float %f\n", "Ignored", thefloat);
236         }
237         return 0;
238 }
239
240 static const struct olsrd_plugin_parameters plugin_parameters[] = {
241     { .name = "interval",      .set_plugin_parameter = &set_plugin_int,         .data = &my_interval },
242     { .name = "timeout",       .set_plugin_parameter = &set_nameservice_float,  .data = &my_timeout },
243     { .name = "hosts-file",    .set_plugin_parameter = &set_plugin_string,      .data = &my_hosts_file,    .addon = {sizeof(my_hosts_file)} },
244     { .name = "resolv-file",   .set_plugin_parameter = &set_plugin_string,      .data = &my_resolv_file,   .addon = {sizeof(my_resolv_file)} },
245     { .name = "suffix",        .set_plugin_parameter = &set_plugin_string,      .data = &my_suffix,        .addon = {sizeof(my_suffix)} },
246     { .name = "add-hosts",     .set_plugin_parameter = &set_plugin_string,      .data = &my_add_hosts,     .addon = {sizeof(my_add_hosts)} },
247     { .name = "services-file", .set_plugin_parameter = &set_plugin_string,      .data = &my_services_file, .addon = {sizeof(my_services_file)} },
248     { .name = "lat",           .set_plugin_parameter = &set_nameservice_float,  .data = &my_lat },
249     { .name = "lon",           .set_plugin_parameter = &set_nameservice_float,  .data = &my_lon },
250     { .name = "latlon-file",   .set_plugin_parameter = &set_plugin_string,      .data = &my_latlon_file,   .addon = {sizeof(my_latlon_file)} },
251     { .name = "latlon-infile", .set_plugin_parameter = &set_plugin_string,      .data = &latlon_in_file,   .addon = {sizeof(latlon_in_file)} },
252     { .name = "dns-server",    .set_plugin_parameter = &set_nameservice_server, .data = &my_forwarders,    .addon = {NAME_FORWARDER} },
253     { .name = "name",          .set_plugin_parameter = &set_nameservice_name,   .data = &my_names,         .addon = {NAME_HOST} },
254     { .name = "service",       .set_plugin_parameter = &set_nameservice_name,   .data = &my_services,      .addon = {NAME_SERVICE} },
255     { .name = "",              .set_plugin_parameter = &set_nameservice_host,   .data = &my_names },
256 };
257
258 void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
259 {
260         *params = plugin_parameters;
261         *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
262 }
263
264
265 /**
266  * queue the name/forwarder/service given in value
267  * to the front of my_list
268  */
269 struct name_entry* 
270 add_name_to_list(struct name_entry *my_list, const char *value, int type, const union olsr_ip_addr *ip) 
271 {
272         struct name_entry *tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry add_name_to_list");
273         tmp->name = strndup( value, MAX_NAME );
274         tmp->len = strlen( tmp->name );
275         tmp->type = type;
276         // all IPs with value 0 will be set to main_addr later
277         if (ip==NULL) 
278                 memset(&tmp->ip, 0, sizeof(tmp->ip));
279         else
280                 tmp->ip = *ip;
281         tmp->next = my_list;
282         return tmp;
283 }
284
285
286 /**
287  * last initialization
288  *
289  * we have to do this here because some things like main_addr 
290  * or the dns suffix (for validation) are not known before
291  *
292  * this is beause of the order in which the plugin is initialized 
293  * by the plugin loader:
294  *   - first the parameters are sent
295  *   - then register_olsr_data() from olsrd_plugin.c is called
296  *     which sets up main_addr and some other variables
297  *   - register_olsr_data() then then finally calls this function
298  */
299 int
300 name_init(void)
301 {
302         struct name_entry *name;
303         union olsr_ip_addr ipz;
304         int ret;
305
306         //regex string for validating the hostnames
307         const char *regex_name = "^[[:alnum:]_.-]+$";
308         //regex string for the service line
309         char *regex_service = olsr_malloc(256*sizeof(char) + strlen(my_suffix), "new *char from name_init for regex_service");
310         memset(&ipz, 0, sizeof(ipz));
311
312         //compile the regex from the string
313         if ((ret = regcomp(&regex_t_name, regex_name , REG_EXTENDED)) != 0)
314         {
315                 /* #2: call regerror() if regcomp failed 
316                  * commented out, because only for debuggin needed
317                  *
318                 int errmsgsz = regerror(ret, &regex_t_name, NULL, 0);
319                 char *errmsg = malloc(errmsgsz);
320                 regerror(ret, &regex_t_name, errmsg, errmsgsz);
321                 fprintf(stderr, "regcomp: %s", errmsg);
322                 free(errmsg);
323                 regfree(&regex_t_name);
324                 * */
325                 OLSR_PRINTF(0, "compilation of regex \"%s\" for hostname failed", regex_name);
326         }
327
328         // a service line is something like prot://hostname.suffix:port|tcp|my little description about this service
329         //                  for example     http://router.olsr:80|tcp|my homepage
330         //                     prot     ://  (hostname.suffix     OR         ip)
331         //regex_service = "^[[:alnum:]]+://(([[:alnum:]_.-]+.olsr)|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}))
332         //                 :    port              /path      |(tcp OR udp) |short description
333         //                 :[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$";
334     strcpy(regex_service, "^[[:alnum:]]+://(([[:alnum:]_.-]+");
335     strcat(regex_service, my_suffix);
336         strcat(regex_service, ")|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3})):[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$");
337
338         /* #1: call regcomp() to compile the regex */
339         if ((ret = regcomp(&regex_t_service, regex_service , REG_EXTENDED )) != 0)
340         {
341                 /* #2: call regerror() if regcomp failed 
342                  * commented out, because only for debuggin needed
343                  *
344                 int errmsgsz = regerror(ret, &regex_t_service, NULL, 0);
345                 char *errmsg = malloc(errmsgsz);
346                 regerror(ret, &regex_t_service, errmsg, errmsgsz);
347                 fprintf(stderr, "regcomp: %s", errmsg);
348                 free(errmsg);
349                 regfree(&regex_t_service);
350                 * */
351                 OLSR_PRINTF(0, "compilation of regex \"%s\" for hostname failed", regex_name);
352         }
353         free(regex_service);
354         regex_service = NULL;
355
356         //fill in main addr for all entries with ip==0
357         //this does not matter for service, because the ip does not matter
358         //for service
359
360         for (name = my_names; name != NULL; name = name->next) {
361                 if (ipequal(&name->ip, &ipz)) {
362                         OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
363                         name->ip = olsr_cnf->main_addr;
364                 }
365         }
366         for (name = my_forwarders; name != NULL; name = name->next) {
367                 if (name->ip.v4.s_addr == 0) {
368                         OLSR_PRINTF(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
369                         name->ip = olsr_cnf->main_addr;
370                 }
371         }
372
373         //check if entries I want to announce myself are valid and allowed
374         my_names = remove_nonvalid_names_from_list(my_names, NAME_HOST);
375         my_forwarders = remove_nonvalid_names_from_list(my_forwarders, NAME_FORWARDER);
376         my_services = remove_nonvalid_names_from_list(my_services, NAME_SERVICE);
377
378
379         /* register functions with olsrd */
380         olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
381
382         /* periodic message generation */
383         msg_gen_timer = olsr_start_timer(my_interval * MSEC_PER_SEC, EMISSION_JITTER,
384                                                                          OLSR_TIMER_PERIODIC, &olsr_namesvc_gen,
385                                                                          NULL, 0);
386
387         mapwrite_init(my_latlon_file);
388
389         return 1;
390 }
391
392
393 struct name_entry*
394 remove_nonvalid_names_from_list(struct name_entry *my_list, int type) 
395 {
396         struct name_entry *next = my_list;
397         olsr_bool valid = OLSR_FALSE;
398         if (my_list == NULL) {
399                 return NULL;
400         } 
401
402         switch (type) {
403                 case NAME_HOST:
404                         valid = is_name_wellformed(my_list->name) && allowed_ip(&my_list->ip); 
405                         break;
406                 case NAME_FORWARDER:
407                         valid = allowed_ip(&my_list->ip);
408                         break;
409                 case NAME_SERVICE:
410                         valid = allowed_service(my_list->name);
411                         break;
412                 case NAME_LATLON:
413                         valid = is_latlon_wellformed(my_list->name);
414                         break;
415         }
416
417         if ( !valid  ) {
418 #ifndef NODEBUG
419                 struct ipaddr_str strbuf;
420 #endif
421                 OLSR_PRINTF(1, "NAME PLUGIN: invalid or malformed parameter %s (%s), fix your config!\n", my_list->name, olsr_ip_to_string(&strbuf, &my_list->ip));
422                 next = my_list->next;
423                 free(my_list->name);
424                 my_list->name = NULL;
425                 free(my_list);
426                 my_list = NULL;
427                 return remove_nonvalid_names_from_list(next, type);
428         } else {
429 #ifndef NODEBUG
430                 struct ipaddr_str strbuf;
431 #endif
432                 OLSR_PRINTF(2, "NAME PLUGIN: validate parameter %s (%s) -> OK\n", my_list->name, olsr_ip_to_string(&strbuf, &my_list->ip));
433                 my_list->next = remove_nonvalid_names_from_list(my_list->next, type);
434                 return my_list;
435         }
436 }
437
438
439
440 /**
441  * called at unload: free everything
442  *
443  * XXX: should I delete the hosts/services/resolv.conf files on exit?
444  */
445 void
446 name_destructor(void)
447 {
448         OLSR_PRINTF(2, "NAME PLUGIN: exit. cleaning up...\n");
449         
450         free_name_entry_list(&my_names);
451         free_name_entry_list(&my_services);
452         free_name_entry_list(&my_forwarders);
453
454         free_all_list_entries(list);
455         free_all_list_entries(service_list);
456         free_all_list_entries(forwarder_list);
457         free_all_list_entries(latlon_list);
458
459         olsr_stop_timer(write_file_timer);
460         olsr_stop_timer(msg_gen_timer);
461
462         regfree(&regex_t_name);
463         regfree(&regex_t_service);
464         mapwrite_exit();
465 }
466
467 /* free all list entries */
468 void 
469 free_all_list_entries(struct list_node *this_db_list) 
470 {
471         struct db_entry *db;
472         struct list_node *list_head, *list_node, *list_node_next;
473
474         int i;
475         
476         for (i = 0; i < HASHSIZE; i++) {
477
478                 list_head = &this_db_list[i];
479
480                 for (list_node = list_head->next;
481                          list_node != list_head;
482                          list_node = list_node_next) {
483
484                         /* prefetch next node before loosing context */
485                         list_node_next = list_node->next;
486
487                         db = list2db(list_node);
488                         olsr_namesvc_delete_db_entry(db);
489                 }
490         }
491 }
492
493
494 /**
495  * The write file timer has fired.
496  */
497 void
498 olsr_expire_write_file_timer(void *context __attribute__((unused)))
499 {
500         write_file_timer = NULL;
501
502         write_resolv_file();   /* if forwarder_table_changed */
503         write_hosts_file();    /* if name_table_changed */
504         write_services_file(); /* if service_table_changed */
505 #ifdef WIN32
506         write_latlon_file();   /* if latlon_table_changed */
507 #endif
508 }
509
510
511 /*
512  * Kick a timer to write everything into a file.
513  * This also paces things a bit.
514  */
515 static void
516 olsr_start_write_file_timer(void)
517 {
518         if (write_file_timer) {
519                 return;
520         }
521
522         write_file_timer = olsr_start_timer(5 * MSEC_PER_SEC, 5, OLSR_TIMER_ONESHOT,
523                                                                                 olsr_expire_write_file_timer, NULL, 0);
524 }
525
526 /*
527  * Delete and unlink db_entry.
528  */
529 void
530 olsr_namesvc_delete_db_entry(struct db_entry *db)
531 {
532 #ifndef NODEBUG
533         struct ipaddr_str strbuf;
534 #endif
535         OLSR_PRINTF(2, "NAME PLUGIN: %s timed out... deleting\n", 
536                                 olsr_ip_to_string(&strbuf, &db->originator));
537
538         olsr_start_write_file_timer();
539         olsr_stop_timer(db->db_timer); /* stop timer if running */
540         
541         /* Delete */
542         free_name_entry_list(&db->names);
543         list_remove(&db->db_list);
544         free(db);
545 }
546
547 /**
548  * Callback for the db validity timer.
549  */
550 static void
551 olsr_nameservice_expire_db_timer(void *context)
552 {
553   struct db_entry *db;
554
555   db = (struct db_entry *)context;
556   db->db_timer = NULL; /* be pedandic */
557
558   olsr_namesvc_delete_db_entry(db);
559 }
560
561 /**
562  * Scheduled event: generate and send NAME packet
563  */
564 void
565 olsr_namesvc_gen(void *foo __attribute__((unused)))
566 {
567         /* send buffer: huge */
568         char buffer[10240];
569         union olsr_message *message = (union olsr_message *)buffer;
570         struct interface *ifn;
571         int namesize;
572
573         /* fill message */
574         if(olsr_cnf->ip_version == AF_INET)
575         {
576                 /* IPv4 */
577                 message->v4.olsr_msgtype = MESSAGE_TYPE;
578                 message->v4.olsr_vtime = double_to_me(my_timeout);
579                 memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
580                 message->v4.ttl = MAX_TTL;
581                 message->v4.hopcnt = 0;
582                 message->v4.seqno = htons(get_msg_seqno());
583
584                 namesize = encap_namemsg((struct namemsg*)&message->v4.message);
585                 namesize = namesize + sizeof(struct olsrmsg);
586
587                 message->v4.olsr_msgsize = htons(namesize);
588         }
589         else
590         {
591                 /* IPv6 */
592                 message->v6.olsr_msgtype = MESSAGE_TYPE;
593                 message->v6.olsr_vtime = double_to_me(my_timeout);
594                 memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
595                 message->v6.ttl = MAX_TTL;
596                 message->v6.hopcnt = 0;
597                 message->v6.seqno = htons(get_msg_seqno());
598
599                 namesize = encap_namemsg((struct namemsg*)&message->v6.message);
600                 namesize = namesize + sizeof(struct olsrmsg6);
601                 
602                 message->v6.olsr_msgsize = htons(namesize);
603         }
604
605         /* looping trough interfaces */
606         for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
607         {
608                 OLSR_PRINTF(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
609
610                 if(net_outbuffer_push(ifn, message, namesize) != namesize ) {
611                         /* send data and try again */
612                         net_output(ifn);
613                         if(net_outbuffer_push(ifn, message, namesize) != namesize ) {
614                                 OLSR_PRINTF(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
615                         }
616                 }
617         }
618 }
619
620
621 /**
622  * Parse name olsr message of NAME type
623  */
624 void
625 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *ipaddr)
626 {
627         struct namemsg *namemessage;
628         union olsr_ip_addr originator;
629         double vtime;
630         int size;
631         olsr_u16_t seqno;
632
633         /* Fetch the originator of the messsage */
634         if(olsr_cnf->ip_version == AF_INET) {
635                 memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
636                 seqno = ntohs(m->v4.seqno);
637         } else {
638                 memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
639                 seqno = ntohs(m->v6.seqno);
640         }
641                 
642         /* Fetch the message based on IP version */
643         if(olsr_cnf->ip_version == AF_INET) {
644                 vtime = me_to_double(m->v4.olsr_vtime);
645                 size = ntohs(m->v4.olsr_msgsize);
646                 namemessage = (struct namemsg*)&m->v4.message;
647         }
648         else {
649                 vtime = me_to_double(m->v6.olsr_vtime);
650                 size = ntohs(m->v6.olsr_msgsize);
651                 namemessage = (struct namemsg*)&m->v6.message;
652         }
653
654         /* Check if message originated from this node. 
655         If so - back off */
656         if(ipequal(&originator, &olsr_cnf->main_addr))
657                 return;
658
659         /* Check that the neighbor this message was received from is symmetric. 
660         If not - back off*/
661         if(check_neighbor_link(ipaddr) != SYM_LINK) {
662 #ifndef NODEBUG
663                 struct ipaddr_str strbuf;
664 #endif
665                 OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr));
666                 return;
667         }
668
669         /* Check if this message has been processed before
670         * Remeber that this also registeres the message as
671         * processed if nessecary
672         */
673         if(olsr_check_dup_table_proc(&originator, seqno)) {
674                 /* If not so - process */
675                 update_name_entry(&originator, namemessage, size, vtime);
676         }
677
678         /* Forward the message if nessecary
679         * default_fwd does all the work for us! */
680         olsr_forward_message(m, &originator, seqno, in_if, ipaddr);
681 }
682
683 /**
684  * Encapsulate a name message into a packet. 
685  *
686  * It assumed that there is enough space in the buffer to do this!
687  *
688  * Returns: the length of the message that was appended
689  */
690 int
691 encap_namemsg(struct namemsg* msg)
692 {
693         struct name_entry *my_name;
694         struct name_entry *my_service;
695
696         // add the hostname, service and forwarder entries after the namemsg header
697         char* pos = (char*)msg + sizeof(struct namemsg);
698         short i=0;
699
700         // names
701         for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
702         {
703                 pos = create_packet( (struct name*) pos, my_name);
704                 i++;
705         }
706         // forwarders
707         for (my_name = my_forwarders; my_name!=NULL; my_name = my_name->next)
708         {
709                 pos = create_packet( (struct name*) pos, my_name);
710                 i++;
711         }
712         // services
713         for (my_service = my_services; my_service!=NULL; my_service = my_service->next)
714         {
715                 pos = create_packet( (struct name*) pos, my_service);
716                 i++;
717         }
718         // latlon
719         if ('\0' != latlon_in_file[0])
720         {
721                 FILE* in = fopen( latlon_in_file, "r" );
722                 if (in != NULL) {
723                         fscanf(in, "%f,%f", &my_lat, &my_lon);
724                         fclose(in);
725                 }
726                 else
727                 {
728                         OLSR_PRINTF(0, "NAME PLUGIN: cant read latlon in file %s\n", latlon_in_file);
729                 }
730         }
731         if (0.0 != my_lat && 0.0 != my_lon)
732         {
733                 char s[64];
734                 struct name_entry e;
735                 memset(&e, 0, sizeof(e));
736                 sprintf(s, "%f,%f,%d", my_lat, my_lon, get_isdefhna_latlon());
737                 e.len = strlen(s);
738                 e.type = NAME_LATLON;
739                 e.name = s;
740                 lookup_defhna_latlon(&e.ip);
741                 pos = create_packet( (struct name*) pos, &e);
742                 i++;
743         }
744
745         // write the namemsg header with the number of announced entries and the protocol version
746         msg->nr_names = htons(i);
747         msg->version = htons(NAME_PROTOCOL_VERSION);
748
749         return pos - (char*)msg; //length
750 }
751
752
753 /**
754  * convert each of my to be announced name_entries into network
755  * compatible format
756  *
757  * return the length of the name packet
758  */
759 char*  
760 create_packet(struct name* to, struct name_entry *from)
761 {
762         char *pos = (char*) to;
763         int k;
764 #ifndef NODEBUG
765         struct ipaddr_str strbuf;
766 #endif
767         OLSR_PRINTF(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
768                 from->name, olsr_ip_to_string(&strbuf, &from->ip), from->len);
769         to->type = htons(from->type);
770         to->len = htons(from->len);
771         to->ip = from->ip;
772         pos += sizeof(struct name);
773         strncpy(pos, from->name, from->len);
774         pos += from->len;
775         for (k = from->len; (k & 3) != 0; k++)
776                 *pos++ = '\0';
777         return pos;
778 }
779
780 /**
781  * decapsulate a received name, service or forwarder and update the corresponding hash table if necessary
782  */
783 void
784 decap_namemsg(struct name *from_packet, struct name_entry **to, olsr_bool *this_table_changed )
785 {
786 #ifndef NODEBUG
787         struct ipaddr_str strbuf;
788 #endif
789         struct name_entry *tmp;
790         struct name_entry *already_saved_name_entries;
791         char *name = (char*)from_packet + sizeof(struct name);
792         int type_of_from_packet = ntohs(from_packet->type);
793         unsigned int len_of_name = ntohs(from_packet->len);
794         OLSR_PRINTF(4, "NAME PLUGIN: decap type=%d, len=%d, name=%s\n",
795                 type_of_from_packet, len_of_name, name);
796
797         //XXX: should I check the from_packet->ip here? If so, why not also check the ip from HOST and SERVICE?
798         if( (type_of_from_packet==NAME_HOST && !is_name_wellformed(name)) ||
799                 (type_of_from_packet==NAME_SERVICE && !is_service_wellformed(name)) ||
800                 (type_of_from_packet==NAME_LATLON && !is_latlon_wellformed(name)))
801         {
802                 OLSR_PRINTF(4, "NAME PLUGIN: invalid name [%s] received, skipping.\n", name );
803                 return;
804         }
805
806         //ignore all packets with a too long name
807         //or a spoofed len of its included name string
808         if (len_of_name > MAX_NAME || strlen(name) != len_of_name || NULL != strchr(name, '\\') || NULL != strchr(name, '\'')) {
809                 OLSR_PRINTF(4, "NAME PLUGIN: from_packet->len %d > MAX_NAME %d or from_packet->len %d !0 strlen(name [%s] in packet)\n",
810                         len_of_name, MAX_NAME, len_of_name, name );
811                 return;
812         }
813
814         // don't insert the received entry again, if it has already been inserted in the hash table. 
815         // Instead only the validity time is set in insert_new_name_in_list function, which calls this one
816         for (already_saved_name_entries = (*to); already_saved_name_entries != NULL ; already_saved_name_entries = already_saved_name_entries->next)
817         {
818                 if ( (type_of_from_packet==NAME_HOST || type_of_from_packet==NAME_SERVICE) && strncmp(already_saved_name_entries->name, name, len_of_name) == 0 ) {
819                         OLSR_PRINTF(4, "NAME PLUGIN: received name or service entry %s (%s) already in hash table\n",
820                                 name, olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
821                         return;
822                 } else if (type_of_from_packet==NAME_FORWARDER && ipequal(&already_saved_name_entries->ip, &from_packet->ip) ) {
823                         OLSR_PRINTF(4, "NAME PLUGIN: received forwarder entry %s (%s) already in hash table\n",
824                                 name, olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
825                         return;
826                 } else if (type_of_from_packet==NAME_LATLON ) {
827                         if (0 != strncmp(already_saved_name_entries->name, name, len_of_name))
828                         {
829                                 OLSR_PRINTF(4, "NAME PLUGIN: updating name %s -> %s (%s)\n",
830                                         already_saved_name_entries->name, name,
831                                         olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
832                                 free(already_saved_name_entries->name);
833                                 already_saved_name_entries->name = olsr_malloc(len_of_name + 1, "upd name_entry name");
834                                 strncpy(already_saved_name_entries->name, name, len_of_name);
835
836                                 *this_table_changed = OLSR_TRUE;
837                                 olsr_start_write_file_timer();
838                         }
839                         if (!ipequal(&already_saved_name_entries->ip, &from_packet->ip))
840                         {
841 #ifndef NODEBUG
842                                 struct ipaddr_str strbuf2, strbuf3;
843 #endif
844                                 OLSR_PRINTF(4, "NAME PLUGIN: updating ip %s -> %s (%s)\n",
845                                         olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip),
846                                         olsr_ip_to_string(&strbuf2, &from_packet->ip),
847                                         olsr_ip_to_string(&strbuf3, &already_saved_name_entries->ip));
848                                 already_saved_name_entries->ip = from_packet->ip;
849
850                                 *this_table_changed = OLSR_TRUE;
851                                 olsr_start_write_file_timer();
852                         }
853                         if (!*this_table_changed)
854                         {
855                                 OLSR_PRINTF(4, "NAME PLUGIN: received latlon entry %s (%s) already in hash table\n",
856                                         name, olsr_ip_to_string(&strbuf, &already_saved_name_entries->ip));
857                         }
858                         return;
859                 }
860         }
861
862         //if not yet known entry 
863         tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");         
864         tmp->type = ntohs(from_packet->type);
865         tmp->len = len_of_name > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
866         tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
867         tmp->ip = from_packet->ip;
868         strncpy(tmp->name, name, tmp->len);
869         tmp->name[tmp->len] = '\0';
870
871         OLSR_PRINTF(3, "\nNAME PLUGIN: create new name/service/forwarder entry %s (%s) [len=%d] [type=%d] in linked list\n", 
872                 tmp->name, olsr_ip_to_string(&strbuf, &tmp->ip), tmp->len, tmp->type);
873
874         *this_table_changed = OLSR_TRUE;
875         olsr_start_write_file_timer();
876
877         // queue to front
878         tmp->next = *to;
879         *to = tmp;
880 }
881
882
883 /**
884  * unpack the received message and delegate to the decapsulation function for each
885  * name/service/forwarder entry in the message
886  */
887 void
888 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
889 {
890 #ifndef NODEBUG
891         struct ipaddr_str strbuf;
892 #endif
893         char *pos, *end_pos;
894         struct name *from_packet; 
895         int i;
896
897         OLSR_PRINTF(3, "NAME PLUGIN: Received Message from %s\n", 
898                                 olsr_ip_to_string(&strbuf, originator));
899         
900         if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
901                 OLSR_PRINTF(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
902                 return;
903         }
904         
905         /* now add the names from the message */
906         pos = (char*)msg + sizeof(struct namemsg);
907         end_pos = pos + msg_size - sizeof(struct name*); // at least one struct name has to be left     
908
909         for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
910         {
911                 from_packet = (struct name*)pos;
912                 
913                 switch (ntohs(from_packet->type)) {
914                         case NAME_HOST: 
915                                 insert_new_name_in_list(originator, list, from_packet,
916                                                                                 &name_table_changed, vtime); 
917                                 break;
918                         case NAME_FORWARDER:
919                                 insert_new_name_in_list(originator, forwarder_list, from_packet,
920                                                                                 &forwarder_table_changed, vtime); 
921                                 break;
922                         case NAME_SERVICE:
923                                 insert_new_name_in_list(originator, service_list, from_packet,
924                                                                                 &service_table_changed, vtime); 
925                                 break;
926                         case NAME_LATLON:
927                                 insert_new_name_in_list(originator, latlon_list, from_packet,
928                                                                                 &latlon_table_changed, vtime);
929                                 break;
930                         default:
931                                 OLSR_PRINTF(3, "NAME PLUGIN: Received Message of unknown type [%d] from (%s)\n",
932                                                         from_packet->type, olsr_ip_to_string(&strbuf, originator));
933                                 break;
934                 }
935
936                 pos += sizeof(struct name);
937                 pos += 1 + (( ntohs(from_packet->len) - 1) | 3);
938         }
939         if (i!=0)
940                 OLSR_PRINTF(4, "NAME PLUGIN: Lost %d entries in received packet due to length inconsistency (%s)\n", i, olsr_ip_to_string(&strbuf, originator));
941 }
942
943
944 /**
945  * insert all the new names,services and forwarders from a received packet into the
946  * corresponding entry for this ip in the corresponding hash table
947  */
948 void
949 insert_new_name_in_list(union olsr_ip_addr *originator,
950                                                 struct list_node *this_list,
951                                                 struct name *from_packet, olsr_bool *this_table_changed,
952                                                 double vtime)
953 {
954         int hash;
955         struct db_entry *entry;
956         struct list_node *list_head, *list_node;
957
958         olsr_bool entry_found = OLSR_FALSE;
959
960         hash = olsr_ip_hashing(originator);
961
962         /* find the entry for originator, if there is already one */
963         list_head = &this_list[hash];
964         for (list_node = list_head->next; list_node != list_head;
965                  list_node = list_node->next) {
966
967                 entry = list2db(list_node);
968
969                 if (ipequal(originator, &entry->originator)) {
970 #ifndef NODEBUG
971                         struct ipaddr_str strbuf;
972 #endif
973                         // found
974                         OLSR_PRINTF(4, "NAME PLUGIN: found entry for (%s) in its hash table\n",
975                                                 olsr_ip_to_string(&strbuf, originator));
976
977                         //delegate to function for parsing the packet and linking it to entry->names
978                         decap_namemsg(from_packet, &entry->names, this_table_changed);
979
980                         olsr_set_timer(&entry->db_timer, vtime * MSEC_PER_SEC,
981                                                    OLSR_NAMESVC_DB_JITTER, OLSR_TIMER_ONESHOT,
982                                                    &olsr_nameservice_expire_db_timer, entry, 0);
983
984                         entry_found = OLSR_TRUE;
985                 }
986         }
987
988         if (! entry_found)
989         {
990 #ifndef NODEBUG
991                 struct ipaddr_str strbuf;
992 #endif
993                 OLSR_PRINTF(3, "NAME PLUGIN: create new db entry for ip (%s) in hash table\n",
994                                         olsr_ip_to_string(&strbuf, originator));
995
996                 /* insert a new entry */
997                 entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
998                 memset(entry, 0, sizeof(struct db_entry));
999
1000                 entry->originator = *originator;
1001
1002                 olsr_set_timer(&entry->db_timer, vtime * MSEC_PER_SEC,
1003                                            OLSR_LINK_LOSS_JITTER, OLSR_TIMER_ONESHOT,
1004                                            &olsr_nameservice_expire_db_timer, entry, 0);
1005
1006                 entry->names = NULL;
1007
1008                 /* insert to the list */
1009                 list_add_before(&this_list[hash], &entry->db_list);
1010                 
1011                 //delegate to function for parsing the packet and linking it to entry->names
1012                 decap_namemsg(from_packet, &entry->names, this_table_changed);
1013         }
1014 }
1015
1016 /**
1017  * write names to a file in /etc/hosts compatible format
1018  */
1019 void
1020 write_hosts_file(void)
1021 {
1022         int hash;
1023         struct name_entry *name;
1024         struct db_entry *entry;
1025         struct list_node *list_head, *list_node;
1026         FILE* hosts;
1027         FILE* add_hosts;
1028         int c=0;
1029         time_t currtime;
1030
1031 #ifdef MID_ENTRIES
1032         struct mid_address *alias;
1033 #endif
1034
1035         if (!name_table_changed)
1036                 return;
1037
1038         OLSR_PRINTF(2, "NAME PLUGIN: writing hosts file\n");
1039
1040         hosts = fopen( my_hosts_file, "w" );
1041         if (hosts == NULL) {
1042                 OLSR_PRINTF(2, "NAME PLUGIN: cant write hosts file\n");
1043                 return;
1044         }
1045         
1046         fprintf(hosts, "### this /etc/hosts file is overwritten regularly by olsrd\n");
1047         fprintf(hosts, "### do not edit\n\n");
1048
1049         fprintf(hosts, "127.0.0.1\tlocalhost\n");
1050         fprintf(hosts, "::1\t\tlocalhost\n\n");
1051         
1052         // copy content from additional hosts filename
1053         if (my_add_hosts[0] != '\0') {
1054                 add_hosts = fopen( my_add_hosts, "r" );
1055                 if (add_hosts == NULL) {
1056                         OLSR_PRINTF(2, "NAME PLUGIN: cant open additional hosts file\n");
1057                 }
1058                 else {
1059                         fprintf(hosts, "### contents from '%s' ###\n\n", my_add_hosts);
1060                         while ((c = getc(add_hosts)) != EOF)
1061                                 putc(c, hosts);
1062                 }
1063                 fclose(add_hosts);              
1064                 fprintf(hosts, "\n### olsr names ###\n\n");
1065         }
1066         
1067         // write own names
1068         for (name = my_names; name != NULL; name = name->next) {
1069                 struct ipaddr_str strbuf;
1070                 fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&strbuf, &name->ip), name->name, my_suffix );
1071         }
1072         
1073         // write received names
1074         for (hash = 0; hash < HASHSIZE; hash++) {
1075                 list_head = &list[hash];
1076                 for (list_node = list_head->next; list_node != list_head;
1077                          list_node = list_node->next) {
1078
1079                         entry = list2db(list_node);
1080
1081                         for (name = entry->names; name != NULL; name = name->next) {
1082                                 struct ipaddr_str strbuf;
1083                                 OLSR_PRINTF(
1084                                         6, "%s\t%s%s\t#%s\n",
1085                                         olsr_ip_to_string( &strbuf, &name->ip ), name->name, my_suffix,
1086                                         olsr_ip_to_string( &strbuf, &entry->originator )
1087                                         );
1088
1089                                 fprintf(
1090                                         hosts, "%s\t%s%s\t# %s\n",
1091                                         olsr_ip_to_string( &strbuf, &name->ip ), name->name, my_suffix,
1092                                         olsr_ip_to_string( &strbuf, &entry->originator )
1093                                         );
1094
1095 #ifdef MID_ENTRIES
1096                                 // write mid entries
1097                                 if( ( alias = mid_lookup_aliases( &name->ip ) ) != NULL )
1098                                 {
1099                                         unsigned short mid_num = 1;
1100                                         char       mid_prefix[MID_MAXLEN];
1101
1102                                         while( alias != NULL )
1103                                         {
1104                                                 struct ipaddr_str midbuf;
1105
1106                                                 // generate mid prefix
1107                                                 sprintf( mid_prefix, MID_PREFIX, mid_num );
1108
1109                                                 OLSR_PRINTF(
1110                                                         6, "%s\t%s%s%s\t# %s (mid #%i)\n",
1111                                                         olsr_ip_to_string( &midbuf, &alias->alias ),
1112                                                         mid_prefix, name->name, my_suffix,
1113                                                         olsr_ip_to_string( &strbuf, &entry->originator ),
1114                                                         mid_num
1115                                                         );
1116
1117                                                 fprintf(
1118                                                         hosts, "%s\t%s%s%s\t# %s (mid #%i)\n",
1119                                                         olsr_ip_to_string( &midbuf, &alias->alias ),
1120                                                         mid_prefix, name->name, my_suffix,
1121                                                         olsr_ip_to_string( &strbuf, &entry->originator ),
1122                                                         mid_num
1123                                                         );
1124
1125                                                 alias = alias->next_alias;
1126                                                 mid_num++;
1127                                         }
1128                                 }
1129 #endif
1130                         }
1131                 }
1132         }
1133
1134         if (time(&currtime)) {
1135                 fprintf(hosts, "\n### written by olsrd at %s", ctime(&currtime));
1136         }
1137           
1138         fclose(hosts);
1139         name_table_changed = OLSR_FALSE;
1140 }
1141
1142
1143 /**
1144  * write services to a file in the format:
1145  * service  #originator ip
1146  *
1147  * since service has a special format
1148  * each line will look similar to e.g.
1149  * http://me.olsr:80|tcp|my little homepage
1150  */
1151 void
1152 write_services_file(void)
1153 {
1154         int hash;
1155         struct name_entry *name;
1156         struct db_entry *entry;
1157         struct list_node *list_head, *list_node;
1158         FILE* services_file;
1159         time_t currtime;
1160
1161
1162         if (!service_table_changed)
1163                 return;
1164
1165         OLSR_PRINTF(2, "NAME PLUGIN: writing services file\n");
1166
1167         services_file = fopen( my_services_file, "w" );
1168         if (services_file == NULL) {
1169                 OLSR_PRINTF(2, "NAME PLUGIN: cant write services_file file\n");
1170                 return;
1171         }
1172         
1173         fprintf(services_file, "### this file is overwritten regularly by olsrd\n");
1174         fprintf(services_file, "### do not edit\n\n");
1175
1176         
1177         // write own services
1178         for (name = my_services; name != NULL; name = name->next) {
1179                 fprintf(services_file, "%s\t# my own service\n", name->name);
1180         }
1181         
1182         // write received services
1183         for (hash = 0; hash < HASHSIZE; hash++) {
1184                 list_head = &list[hash];
1185                 for (list_node = list_head->next; list_node != list_head;
1186                          list_node = list_node->next) {
1187
1188                         entry = list2db(list_node);
1189
1190                         for (name = entry->names; name != NULL; name = name->next) {
1191                                 struct ipaddr_str strbuf;
1192                                 OLSR_PRINTF(6, "%s\t",  name->name);
1193                                 OLSR_PRINTF(6, "\t#%s\n",
1194                                                         olsr_ip_to_string(&strbuf, &entry->originator));
1195
1196                                 fprintf(services_file, "%s\t", name->name );
1197                                 fprintf(services_file, "\t#%s\n",
1198                                                 olsr_ip_to_string(&strbuf, &entry->originator));
1199                         }
1200                 }
1201         }
1202
1203         if (time(&currtime)) {
1204                 fprintf(services_file, "\n### written by olsrd at %s", ctime(&currtime));
1205         }
1206           
1207         fclose(services_file);
1208         service_table_changed = OLSR_FALSE;
1209 }
1210
1211 /**
1212  * Sort the nameserver pointer array.
1213  *
1214  * fresh entries are at the beginning of the array and
1215  * the best entry is at the end of the array.
1216  */
1217 static void
1218 select_best_nameserver(struct rt_entry **rt)
1219 {
1220         int nameserver_idx;
1221         struct rt_entry *rt1, *rt2;
1222
1223         for (nameserver_idx = 0;
1224                  nameserver_idx < NAMESERVER_COUNT;
1225                  nameserver_idx++) {
1226
1227                 rt1 = rt[nameserver_idx];
1228                 rt2 = rt[nameserver_idx+1];
1229
1230                 /*
1231                  * compare the next two pointers in the array.
1232                  * if the second pointer is NULL then percolate it up.
1233                  */
1234                 if (!rt2 || olsr_cmp_rt(rt1, rt2)) {
1235 #ifndef NODEBUG
1236                         struct ipaddr_str strbuf;
1237 #endif
1238                         /*
1239                          * first is better, swap the pointers.
1240                          */
1241                         OLSR_PRINTF(6, "NAME PLUGIN: nameserver %s, etx %s\n",
1242                                                 olsr_ip_to_string(&strbuf, &rt1->rt_dst.prefix),
1243                                                 etxtoa(rt1->rt_best->rtp_metric.etx));
1244
1245                         rt[nameserver_idx] = rt2;
1246                         rt[nameserver_idx+1] = rt1;
1247                 }
1248         }
1249 }
1250
1251 /**
1252  * write the 3 best upstream DNS servers to resolv.conf file
1253  * best means the 3 with the best etx value in routing table
1254  */
1255 void
1256 write_resolv_file(void)
1257 {
1258         int hash;
1259         struct name_entry *name;
1260         struct db_entry *entry;
1261         struct list_node *list_head, *list_node;
1262         struct rt_entry *route;
1263         static struct rt_entry *nameserver_routes[NAMESERVER_COUNT+1];
1264         FILE* resolv;
1265         int i=0;
1266         time_t currtime;
1267
1268         if (!forwarder_table_changed || my_forwarders != NULL || my_resolv_file[0] == '\0')
1269                 return;
1270
1271         /* clear the array of 3+1 nameserver routes */
1272         memset(nameserver_routes, 0, sizeof(nameserver_routes));
1273
1274         for (hash = 0; hash < HASHSIZE; hash++) {
1275                 list_head = &list[hash];
1276                 for (list_node = list_head->next; list_node != list_head;
1277                          list_node = list_node->next) {
1278
1279                         entry = list2db(list_node);
1280
1281                         for (name = entry->names; name != NULL; name = name->next) {
1282 #ifndef NODEBUG
1283                                 struct ipaddr_str strbuf;
1284 #endif
1285                                 route = olsr_lookup_routing_table(&name->ip);
1286
1287                                 OLSR_PRINTF(6, "NAME PLUGIN: check route for nameserver %s %s",
1288                                                         olsr_ip_to_string(&strbuf, &name->ip),
1289                                                         route ? "suceeded" : "failed");
1290
1291                                 if (route==NULL) // it's possible that route is not present yet
1292                                         continue;
1293
1294                                 /* enqueue it on the head of list */
1295                                 *nameserver_routes = route;
1296                                 OLSR_PRINTF(6, "NAME PLUGIN: found nameserver %s, etx %s",
1297                                                         olsr_ip_to_string(&strbuf, &name->ip),
1298                                                         etxtoa(route->rt_best->rtp_metric.etx));
1299
1300                                 /* find the closet one */
1301                                 select_best_nameserver(nameserver_routes);
1302                         }
1303                 }
1304         }
1305
1306         /* if there is no best route we are done */
1307         if (nameserver_routes[NAMESERVER_COUNT]==NULL)
1308                 return;
1309                  
1310         /* write to file */
1311         OLSR_PRINTF(2, "NAME PLUGIN: try to write to resolv file\n");
1312         resolv = fopen( my_resolv_file, "w" );
1313         if (resolv == NULL) {
1314                 OLSR_PRINTF(2, "NAME PLUGIN: can't write resolv file\n");
1315                 return;
1316         }
1317         fprintf(resolv, "### this file is overwritten regularly by olsrd\n");
1318         fprintf(resolv, "### do not edit\n\n");
1319
1320         for (i = NAMESERVER_COUNT; i >= 0; i--) {
1321                 struct ipaddr_str strbuf;
1322
1323                 route = nameserver_routes[i];
1324
1325                 OLSR_PRINTF(2, "NAME PLUGIN: nameserver_routes #%d %p\n", i, route);
1326
1327                 if (!route) {
1328                         continue;
1329                 }
1330
1331                 OLSR_PRINTF(2, "NAME PLUGIN: nameserver %s\n",
1332                                         olsr_ip_to_string(&strbuf, &route->rt_dst.prefix));
1333                 fprintf(resolv, "nameserver %s\n",
1334                                 olsr_ip_to_string(&strbuf, &route->rt_dst.prefix));
1335         }
1336         if (time(&currtime)) {
1337                 fprintf(resolv, "\n### written by olsrd at %s", ctime(&currtime));
1338         }
1339         fclose(resolv);
1340         forwarder_table_changed = OLSR_FALSE;
1341 }
1342
1343
1344 /**
1345  * completely free a list of name_entries
1346  */
1347 void 
1348 free_name_entry_list(struct name_entry **list) 
1349 {
1350         struct name_entry **tmp = list;
1351         struct name_entry *to_delete;
1352         while (*tmp != NULL) {
1353                 to_delete = *tmp;
1354                 *tmp = (*tmp)->next;
1355
1356                 /* flag changes */
1357                 switch (to_delete->type) {
1358                 case NAME_HOST:
1359                         name_table_changed = OLSR_TRUE;
1360                         break;
1361                 case NAME_FORWARDER:
1362                         forwarder_table_changed = OLSR_TRUE;
1363                         break;
1364                 case NAME_SERVICE:
1365                         service_table_changed = OLSR_TRUE;
1366                         break;
1367                 case NAME_LATLON:
1368                         latlon_table_changed = OLSR_TRUE;
1369                         break;
1370                 default:
1371                         break;
1372                 }
1373
1374                 free( to_delete->name );
1375                 to_delete->name = NULL;
1376                 free( to_delete );
1377                 to_delete = NULL;
1378         }
1379 }
1380
1381
1382 /**
1383  * we only allow names for IP addresses which we are
1384  * responsible for: 
1385  * so the IP must either be from one of the interfaces
1386  * or inside a HNA which we have configured 
1387  */
1388 olsr_bool
1389 allowed_ip(const union olsr_ip_addr *addr)
1390 {
1391         struct ip_prefix_list *hna;
1392         struct interface *iface;
1393         union olsr_ip_addr tmp_ip, tmp_msk;
1394 #ifndef NODEBUG
1395         struct ipaddr_str strbuf;
1396 #endif
1397         
1398         OLSR_PRINTF(6, "checking %s\n", olsr_ip_to_string(&strbuf, addr));
1399         
1400         for(iface = ifnet; iface; iface = iface->int_next)
1401         {
1402                 OLSR_PRINTF(6, "interface %s\n", olsr_ip_to_string(&strbuf, &iface->ip_addr));
1403                 if (ipequal(&iface->ip_addr, addr)) {
1404                         OLSR_PRINTF(6, "MATCHED\n");
1405                         return OLSR_TRUE;
1406                 }
1407         }
1408         
1409         if (olsr_cnf->ip_version == AF_INET) {
1410                 for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next) {
1411                         union olsr_ip_addr netmask;
1412                         OLSR_PRINTF(6, "HNA %s/%d\n", 
1413                                                 olsr_ip_to_string(&strbuf, &hna->net.prefix),
1414                                                 hna->net.prefix_len);
1415                         if (hna->net.prefix_len == 0) {
1416                                 continue;
1417                         }
1418                         olsr_prefix_to_netmask(&netmask, hna->net.prefix_len);
1419                         if ((addr->v4.s_addr & netmask.v4.s_addr) == hna->net.prefix.v4.s_addr) {
1420                                 OLSR_PRINTF(6, "MATCHED\n");
1421                                 return OLSR_TRUE;
1422                         }
1423                 }
1424         } else {
1425                 for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next)
1426                 {
1427                         unsigned int i;
1428                         OLSR_PRINTF(6, "HNA %s/%d\n", 
1429                                 olsr_ip_to_string(&strbuf, &hna->net.prefix),
1430                                 hna->net.prefix_len);
1431                         if ( hna->net.prefix_len == 0 )
1432                                 continue;
1433                         olsr_prefix_to_netmask(&tmp_msk, hna->net.prefix_len);
1434                         for (i = 0; i < sizeof(tmp_ip.v6.s6_addr); i++) {
1435                                 tmp_ip.v6.s6_addr[i] = addr->v6.s6_addr[i] & tmp_msk.v6.s6_addr[i];
1436                         }
1437                         if (ipequal(&tmp_ip, &hna->net.prefix)) {
1438                                 OLSR_PRINTF(6, "MATCHED\n");
1439                                 return OLSR_TRUE;
1440                         }
1441                 }
1442         }
1443         return OLSR_FALSE;
1444 }
1445
1446 /** check if name has the right syntax, i.e. it must adhere to a special regex 
1447  * stored in regex_t_name
1448  * necessary to avaid names like "0.0.0.0 google.de\n etc"
1449  */
1450 olsr_bool
1451 is_name_wellformed(const char *name) {
1452         return regexec(&regex_t_name, name, 1, &regmatch_t_name, 0) == 0 ;
1453 }
1454
1455
1456 /**
1457  * check if the service is in the right syntax and also that the hostname 
1458  * or ip whithin the service is allowed
1459  */
1460 olsr_bool
1461 allowed_service(const char *service_line)
1462 {
1463         /* the call of is_service_wellformed generates the submatches stored in regmatch_t_service
1464          * these are then used by allowed_hostname_or_ip_in_service
1465          * see regexec(3) for more infos */
1466         if (!is_service_wellformed(service_line)) {
1467                 return OLSR_FALSE;
1468         } else if (!allowed_hostname_or_ip_in_service(service_line, &(regmatch_t_service[1]))) {
1469                 return OLSR_FALSE;
1470         } 
1471
1472         return OLSR_TRUE;
1473 }
1474
1475 olsr_bool
1476 allowed_hostname_or_ip_in_service(const char *service_line, const regmatch_t *hostname_or_ip_match) 
1477 {
1478         char *hostname_or_ip;
1479         union olsr_ip_addr olsr_ip;
1480         struct name_entry *name;
1481         if (hostname_or_ip_match->rm_so < 0 || hostname_or_ip_match->rm_eo < 0) {
1482                 return OLSR_FALSE;
1483         } 
1484
1485         hostname_or_ip = strndup(&service_line[hostname_or_ip_match->rm_so], hostname_or_ip_match->rm_eo - hostname_or_ip_match->rm_so);
1486         //hostname is one of the names, that I announce (i.e. one that i am allowed to announce)
1487         for (name = my_names; name != NULL; name = name->next) {
1488                 if (strncmp(name->name, hostname_or_ip, name->len - strlen(my_suffix)) == 0 ) {
1489                         OLSR_PRINTF(4, "NAME PLUGIN: hostname %s in service %s is OK\n", hostname_or_ip, service_line);
1490                         free(hostname_or_ip);
1491                         hostname_or_ip = NULL;
1492                         return OLSR_TRUE;
1493                 }
1494         }
1495
1496         //ip in service-line is allowed 
1497         if (inet_pton(olsr_cnf->ip_version, hostname_or_ip, &olsr_ip) > 0) {
1498                 if (allowed_ip(&olsr_ip)) {
1499 #ifndef NODEBUG
1500                         struct ipaddr_str strbuf;
1501 #endif
1502                         OLSR_PRINTF(2, "NAME PLUGIN: ip %s in service %s is OK\n", olsr_ip_to_string(&strbuf, &olsr_ip), service_line);
1503                         free(hostname_or_ip);
1504                         hostname_or_ip = NULL;
1505                         return OLSR_TRUE;
1506                 }
1507         }
1508
1509         OLSR_PRINTF(1, "NAME PLUGIN: ip or hostname %s in service %s is NOT allowed (does not belong to you)\n", hostname_or_ip, service_line);
1510         free(hostname_or_ip);
1511         hostname_or_ip = NULL;
1512
1513         return OLSR_FALSE;
1514 }
1515
1516 /**
1517  * check if the service matches the syntax 
1518  * of "protocol://host:port/path|tcp_or_udp|a short description", 
1519  * which is given in the regex regex_t_service
1520  */
1521 olsr_bool
1522 is_service_wellformed(const char *service_line)
1523 {
1524         return regexec(&regex_t_service, service_line, pmatch_service, regmatch_t_service, 0) == 0;
1525 }
1526
1527 /**
1528  * check if the latlot matches the syntax 
1529  */
1530 olsr_bool
1531 is_latlon_wellformed(const char *latlon_line)
1532 {
1533         int hna = -1;
1534         float a = 0.0, b = 0.0;
1535         sscanf(latlon_line, "%f,%f,%d", &a, &b, &hna);
1536         return (a != 0.0 && b != 0.0 && -1 != hna);
1537 }
1538
1539 /**
1540  * Returns 1 if this olsrd announces inet
1541  */
1542 olsr_bool get_isdefhna_latlon(void)
1543 {
1544         struct ip_prefix_list *hna;
1545         for (hna = olsr_cnf->hna_entries; hna != NULL; hna = hna->next){
1546                 if (hna->net.prefix_len == 0) {
1547                         return OLSR_TRUE;
1548                 }
1549         }
1550         return OLSR_FALSE;
1551 }
1552
1553 /**
1554  * Grabs the current HNA selected default route
1555  */
1556 void lookup_defhna_latlon(union olsr_ip_addr *ip)
1557 {
1558   struct avl_node *rt_tree_node;
1559   struct olsr_ip_prefix prefix;
1560
1561   memset(ip, 0, sizeof(ip));
1562   memset(&prefix, 0, sizeof(prefix));
1563
1564   if (NULL != (rt_tree_node = avl_find(&routingtree, &prefix)))
1565   {
1566     *ip = ((struct rt_entry *)rt_tree_node->data)->rt_best->rtp_nexthop.gateway;
1567   }
1568 }
1569
1570 /**
1571  * lookup a nodes name
1572  */
1573 const char*
1574 lookup_name_latlon(union olsr_ip_addr *ip)
1575 {
1576         int hash;
1577         struct db_entry *entry;
1578         struct list_node *list_head, *list_node;
1579         struct name_entry *name;
1580
1581         for (hash = 0; hash < HASHSIZE; hash++) {
1582                 list_head = &list[hash];
1583                 for (list_node = list_head->next; list_node != list_head;
1584                          list_node = list_node->next) {
1585
1586                         entry = list2db(list_node);
1587
1588                         for (name = entry->names; name != NULL; name = name->next) {
1589                                 if (ipequal(&name->ip, ip)) return name->name;
1590                         }
1591                 }
1592         }
1593         return "";
1594 }
1595
1596 #ifdef WIN32
1597 /**
1598  * write latlon positions to a javascript file
1599  */
1600 void
1601 write_latlon_file(void)
1602 {
1603   FILE* fmap;
1604   
1605   if (!my_names || !latlon_table_changed) return;
1606   
1607   OLSR_PRINTF(2, "NAME PLUGIN: writing latlon file\n");
1608
1609   if (NULL == (fmap = fopen(my_latlon_file, "w"))) {
1610     OLSR_PRINTF(0, "NAME PLUGIN: cant write latlon file\n");
1611     return;
1612   }
1613   fprintf(fmap, "/* This file is overwritten regularly by olsrd */\n");
1614   mapwrite_work(fmap);  
1615   fclose(fmap);
1616   latlon_table_changed = OLSR_FALSE;
1617 }
1618 #endif
1619
1620 /*
1621  * Local Variables:
1622  * mode: c
1623  * c-indent-tabs-mode: t
1624  * indent-tabs-mode: t
1625  * c-basic-offset: 4
1626  * tab-width: 4
1627  * End:
1628  */