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