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