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