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