* merged it also and fixed lots of stuff by hand
[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  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without 
8  * modification, are permitted provided that the following conditions 
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, 
12  *   this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright notice, 
14  *   this list of conditions and the following disclaimer in the documentation 
15  *   and/or other materials provided with the distribution.
16  * * Neither the name of the UniK olsr daemon nor the names of its contributors 
17  *   may be used to endorse or promote products derived from this software 
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
23  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
27  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32
33 /* $Id: nameservice.c,v 1.17 2007/02/04 21:11:48 bernd67 Exp $ */
34
35 /*
36  * Dynamic linked library for UniK OLSRd
37  */
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <ctype.h>
44 #include <sys/types.h>
45 #include <regex.h>
46
47 #include "olsr.h"
48 #include "net_olsr.h"
49 #include "routing_table.h"
50 #include "mantissa.h"
51 #include "scheduler.h"
52 #include "parser.h"
53 #include "duplicate_set.h"
54 #include "link_set.h"
55
56 #include "nameservice.h"
57 #include "olsrd_copy.h"
58 #include "compat.h"
59
60
61 /* send buffer: huge */
62 static char buffer[10240];
63
64 /* config parameters */
65 static char my_hosts_file[MAX_FILE + 1];
66 static char my_add_hosts[MAX_FILE + 1];
67 static char my_suffix[MAX_SUFFIX];
68 static int my_interval = EMISSION_INTERVAL;
69 static double my_timeout = NAME_VALID_TIME;
70 static char my_resolv_file[MAX_FILE +1];
71 static char my_services_file[MAX_FILE + 1];
72
73 /* the databases (using hashing)
74  * for hostnames, service_lines and dns-servers
75  *
76  * my own hostnames, service_lines and dns-servers
77  * are store in a linked list (without hashing)
78  * */
79 struct db_entry* list[HASHSIZE];
80 struct name_entry *my_names = NULL;
81 olsr_bool name_table_changed = OLSR_TRUE;
82
83 struct db_entry* service_list[HASHSIZE];
84 struct name_entry *my_services = NULL;
85 olsr_bool service_table_changed = OLSR_TRUE;
86
87 struct db_entry* forwarder_list[HASHSIZE];
88 struct name_entry *my_forwarders = NULL;
89 olsr_bool forwarder_table_changed = OLSR_TRUE;
90
91 /* regualar expression to be matched by valid hostnames, compiled in name_init() */
92 regex_t regex_t_name;
93 regmatch_t regmatch_t_name;
94
95 /* regualar expression to be matched by valid service_lines, compiled in name_init() */
96 regex_t regex_t_service;
97 int pmatch_service = 10;
98 regmatch_t regmatch_t_service[10];
99  
100 static void free_routing_table_list(struct rt_entry **list) ;
101 static struct rt_entry *host_lookup_routing_table(union olsr_ip_addr *);
102
103 /**
104  * do initialization
105  */
106 void
107 name_constructor() 
108 {
109         int i;
110         
111 #ifdef WIN32
112         int len;
113
114         GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
115         GetWindowsDirectory(my_services_file, MAX_FILE - 12);
116
117         len = strlen(my_hosts_file);
118         if (my_hosts_file[len - 1] != '\\')
119                 my_hosts_file[len++] = '\\';
120         strcpy(my_hosts_file + len, "hosts_olsr");
121         
122     len = strlen(my_services_file);
123         if (my_services_file[len - 1] != '\\')
124                 my_services_file[len++] = '\\';
125         strcpy(my_services_file + len, "services_olsr");
126
127     len = strlen(my_resolv_file);
128         if (my_resolv_file[len - 1] != '\\')
129                 my_resolv_file[len++] = '\\';
130         strcpy(my_resolv_file + len, "resolvconf_olsr");
131 #else
132         strcpy(my_hosts_file, "/var/run/hosts_olsr");
133         strcpy(my_services_file, "/var/run/services_olsr");
134         strcpy(my_resolv_file, "/var/run/resolvconf_olsr");
135 #endif
136
137         my_suffix[0] = '\0';
138         my_add_hosts[0] = '\0';
139         
140         /* init lists */
141         for(i = 0; i < HASHSIZE; i++) {
142                 list[i] = NULL;
143                 forwarder_list[i] = NULL;
144         service_list[i] = NULL;
145         }
146         
147
148 }
149
150
151 /**
152  * called for all plugin parameters
153  */
154 int
155 olsrd_plugin_register_param(char *key, char *value)
156 {
157         if(!strcmp(key, "interval")) {
158                 my_interval = atoi(value);
159                 olsr_printf(1, "\nNAME PLUGIN: parameter interval: %d\n", my_interval);
160         }
161         else if(!strcmp(key, "timeout")) {
162                 my_timeout = atof(value);
163                 olsr_printf(1, "\nNAME PLUGIN: parameter timeout: %f\n", my_timeout);
164         } 
165         else if(!strcmp(key, "hosts-file")) {
166                 strncpy( my_hosts_file, value, MAX_FILE );
167                 olsr_printf(1, "\nNAME PLUGIN: parameter filename: %s\n", my_hosts_file);
168         }
169         else if(!strcmp(key, "resolv-file")) {
170                 strncpy(my_resolv_file, value, MAX_FILE);
171                 olsr_printf(1, "\nNAME PLUGIN: parameter resolv file: %s\n", my_resolv_file);
172         }
173         else if(!strcmp(key, "suffix")) {
174                 strncpy(my_suffix, value, MAX_SUFFIX);
175                 olsr_printf(1, "\nNAME PLUGIN: parameter suffix: %s\n", my_suffix);
176         }
177         else if(!strcmp(key, "add-hosts")) {
178                 strncpy(my_add_hosts, value, MAX_FILE);
179                 olsr_printf(1, "\nNAME PLUGIN: parameter additional host: %s\n", my_add_hosts);
180         }
181         else if(!strcmp(key, "services-file")) {
182                 strncpy(my_services_file, value, MAX_FILE);
183                 olsr_printf(1,"\nNAME PLUGIN: parameter services-file: %s", my_services_file);
184         }
185         else if(!strcmp(key, "dns-server")) {
186                 struct in_addr ip;
187                 if (strlen(value) == 0) {
188             my_forwarders = add_name_to_list(my_forwarders, "", NAME_FORWARDER, NULL);
189             olsr_printf(1,"\nNAME PLUGIN: parameter dns-server: (main address)");
190         } else if (inet_aton(value, &ip)) {
191             my_forwarders = add_name_to_list(my_forwarders, "", NAME_FORWARDER, &ip);
192             olsr_printf(1,"\nNAME PLUGIN: parameter dns-server: (%s)", value);
193         } else {
194             olsr_printf(1,"\nNAME PLUGIN: invalid parameter dns-server: %s ", value);
195         }
196         }
197         else if(!strcmp(key, "name")) {
198                 // name for main address
199         my_names = add_name_to_list(my_names, value, NAME_HOST, NULL);
200         olsr_printf(1,"\nNAME PLUGIN: parameter name: %s (main address)", value);
201         }
202         else if(!strcmp(key, "service")) {
203                 // name for main address
204         my_services = add_name_to_list(my_services, value, NAME_SERVICE, NULL);
205         olsr_printf(1,"\nNAME PLUGIN: parameter service: %s (main address)", value);
206         }
207         else {
208                 // assume this is an IP address and hostname
209                 struct in_addr ip;
210                 
211                 if (inet_pton(olsr_cnf->ip_version, key, &ip) == 1) {
212                         // the IP is validated later
213             my_names = add_name_to_list(my_names, value, NAME_HOST, &ip);
214                         olsr_printf(1,"\nNAME PLUGIN: parameter name %s (%s)", value, key);
215                 } 
216                 else {
217                         olsr_printf(1, "\nNAME PLUGIN: invalid IP %s for name %s!\n", key, value);
218                 }
219         }
220
221         return 1;
222 }
223
224
225 /**
226  * queue the name/forwarder/service given in value
227  * to the front of my_list
228  */
229 struct name_entry* 
230 add_name_to_list(struct name_entry *my_list, char *value, int type, struct in_addr *ip) 
231 {
232                 struct name_entry *tmp;
233                 tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry add_name_to_list");
234         tmp->name = strndup( value, MAX_NAME );
235         tmp->len = strlen( tmp->name );
236         tmp->type = type;
237         // all IPs with value 0 will be set to main_addr later
238         if (ip==NULL) 
239             memset(&tmp->ip, 0, sizeof(tmp->ip));
240         else
241             tmp->ip.v4 = ip->s_addr;
242         tmp->next = my_list;
243         return tmp;
244 }
245
246
247 /**
248  * last initialization
249  *
250  * we have to do this here because some things like main_addr 
251  * or the dns suffix (for validation) are not known before
252  *
253  * this is beause of the order in which the plugin is initialized 
254  * by the plugin loader:
255  *   - first the parameters are sent
256  *   - then register_olsr_data() from olsrd_plugin.c is called
257  *     which sets up main_addr and some other variables
258  *   - register_olsr_data() then then finally calls this function
259  */
260 int
261 name_init()
262 {
263         struct name_entry *name;
264         union olsr_ip_addr ipz;
265
266         memset(&ipz, 0, sizeof(ipz));
267
268     int ret;
269     //regex string for validating the hostnames
270     char *regex_name = "^[[:alnum:]_.-]+$";
271     //regex string for the service line
272     char *regex_service = olsr_malloc(256*sizeof(char) + strlen(my_suffix), "new *char from name_init for regex_service");
273
274     //compile the regex from the string
275         if ((ret = regcomp(&regex_t_name, regex_name , REG_EXTENDED)) != 0)
276     {
277                 /* #2: call regerror() if regcomp failed 
278          * commented out, because only for debuggin needed
279          *
280         int errmsgsz = regerror(ret, &regex_t_name, NULL, 0);
281         char *errmsg = malloc(errmsgsz);
282         regerror(ret, &regex_t_name, errmsg, errmsgsz);
283         fprintf(stderr, "regcomp: %s", errmsg);
284         free(errmsg);
285         regfree(&regex_t_name);
286          * */
287         olsr_printf(0, "compilation of regex \"%s\" for hostname failed", regex_name);
288         }
289                   
290   // a service line is something like prot://hostname.suffix:port|tcp|my little description about this service
291   //                  for example     http://router.olsr:80|tcp|my homepage
292   //                     prot     ://  (hostname.suffix     OR         ip)
293   //regex_service = "^[[:alnum:]]+://(([[:alnum:]_.-]+.olsr)|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}))
294   //                 :    port              /path      |(tcp OR udp) |short description
295   //                 :[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$";
296   strcat (strcat (strcat(regex_service, "^[[:alnum:]]+://(([[:alnum:]_.-]+"),
297                   my_suffix),
298           ")|([[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3}\\.[[:digit:]]{1,3})):[[:digit:]]+[[:alnum:]/?._=#-]*\\|(tcp|udp)\\|[^|[:cntrl:]]+$");
299
300         /* #1: call regcomp() to compile the regex */
301         if ((ret = regcomp(&regex_t_service, regex_service , REG_EXTENDED )) != 0)
302     {
303                 /* #2: call regerror() if regcomp failed 
304          * commented out, because only for debuggin needed
305          *
306                 int errmsgsz = regerror(ret, &regex_t_service, NULL, 0);
307                 char *errmsg = malloc(errmsgsz);
308                 regerror(ret, &regex_t_service, errmsg, errmsgsz);
309                 fprintf(stderr, "regcomp: %s", errmsg);
310                 free(errmsg);
311                 regfree(&regex_t_service);
312          * */
313         olsr_printf(0, "compilation of regex \"%s\" for hostname failed", regex_name);
314         }
315     free(regex_service);
316     regex_service = NULL;
317
318     //fill in main addr for all entries with ip==0
319     //this does not matter for service, because the ip does not matter
320     //for service
321
322         for (name = my_names; name != NULL; name = name->next) {
323         if (memcmp(&name->ip, &ipz, olsr_cnf->ipsize) == 0) {
324             olsr_printf(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
325                         memcpy(&name->ip, &olsr_cnf->main_addr, olsr_cnf->ipsize);
326         }
327     }
328         for (name = my_forwarders; name != NULL; name = name->next) {
329         if (name->ip.v4 == 0) {
330             olsr_printf(2, "NAME PLUGIN: insert main addr for name %s \n", name->name);
331                         memcpy(&name->ip, &olsr_cnf->main_addr, olsr_cnf->ipsize);
332         }
333     }
334
335     //check if entries I want to announce myself are valid and allowed
336     my_names = remove_nonvalid_names_from_list(my_names, NAME_HOST);
337     my_forwarders = remove_nonvalid_names_from_list(my_forwarders, NAME_FORWARDER);
338     my_services = remove_nonvalid_names_from_list(my_services, NAME_SERVICE);
339
340
341         /* register functions with olsrd */
342         olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
343         olsr_register_timeout_function(&olsr_timeout);
344         olsr_register_scheduler_event(&olsr_event, NULL, my_interval, 0, NULL);
345
346         return 1;
347 }
348
349
350 struct name_entry*
351 remove_nonvalid_names_from_list(struct name_entry *my_list, int type) 
352 {
353     struct name_entry *next = my_list;
354     olsr_bool valid = OLSR_FALSE;
355     if (my_list == NULL) {
356         return NULL;
357     } 
358
359     switch (type) {
360         case NAME_HOST:
361             valid = is_name_wellformed(my_list->name) && allowed_ip(&my_list->ip); 
362             break;
363         case NAME_FORWARDER:
364             valid = allowed_ip(&my_list->ip);
365             break;
366         case NAME_SERVICE:
367             valid = allowed_service(my_list->name);
368             break;
369     }
370     
371     if ( !valid  ) {
372         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));
373         next = my_list->next;
374         free(my_list->name);
375         my_list->name = NULL;
376         free(my_list);
377         my_list = NULL;
378         return remove_nonvalid_names_from_list(next, type);
379     } else {
380         olsr_printf(2, "NAME PLUGIN: validate parameter %s (%s) -> OK\n", my_list->name, olsr_ip_to_string(&my_list->ip));
381         my_list->next = remove_nonvalid_names_from_list(my_list->next, type);
382         return my_list;    
383     }
384 }
385
386
387
388 /**
389  * called at unload: free everything
390  *
391  * XXX: should I delete the hosts/services/resolv.conf files on exit?
392  */
393 void
394 name_destructor()
395 {
396         olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
397         
398         free_name_entry_list(&my_names);
399         free_name_entry_list(&my_services);
400         free_name_entry_list(&my_forwarders);
401
402     free_all_list_entries(list);
403     free_all_list_entries(service_list);
404     free_all_list_entries(forwarder_list);
405
406     regfree(&regex_t_name);
407     regfree(&regex_t_service);
408         
409 }
410
411 /* free all list entries */
412 void 
413 free_all_list_entries(struct db_entry **this_db_list) 
414 {
415         int i;
416         struct db_entry **tmp;
417         struct db_entry *to_delete;
418         
419         for(i = 0; i < HASHSIZE; i++)
420         {
421                 tmp = &list[i];
422                 while(*tmp != NULL)
423                 {
424                         to_delete = *tmp;
425                         *tmp = (*tmp)->next;
426                         free_name_entry_list(&to_delete->names);
427                         free(to_delete);
428                         to_delete = NULL;
429                 }
430         }
431 }
432
433
434 /**
435  * A timeout function called every time
436  *
437  * XXX:the scheduler is polled (by default 10 times a sec,
438  * which is far too often):
439  *
440  * time out old list entries
441  * and write changes to file
442  */
443 void
444 olsr_timeout()
445 {
446     timeout_old_names(list, &name_table_changed);
447     timeout_old_names(forwarder_list, &forwarder_table_changed);
448     timeout_old_names(service_list, &service_table_changed);
449      
450         write_resolv_file();
451         write_hosts_file();
452         write_services_file();
453 }
454
455 void
456 timeout_old_names(struct db_entry **this_list, olsr_bool *this_table_changed)
457 {
458         struct db_entry **tmp;
459         struct db_entry *to_delete;
460         int index;
461
462         for(index=0;index<HASHSIZE;index++)
463         {
464                 for (tmp = &this_list[index]; *tmp != NULL; )
465                 {
466                         /* check if the entry for this ip is timed out */
467                         if (olsr_timed_out(&(*tmp)->timer))
468                         {
469                                 to_delete = *tmp;
470                 /* update the pointer in the linked list */
471                                 *tmp = (*tmp)->next;
472                                 
473                                 olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n", 
474                                         olsr_ip_to_string(&to_delete->originator));
475         
476                                 /* Delete */
477                                 free_name_entry_list(&to_delete->names);
478                                 free(to_delete);
479                                 *this_table_changed = OLSR_TRUE;
480                         } else {
481                                 tmp = &(*tmp)->next;
482                         }
483                 }
484         }
485 }
486
487
488 /**
489  * Scheduled event: generate and send NAME packet
490  */
491 void
492 olsr_event(void *foo)
493 {
494         union olsr_message *message = (union olsr_message*)buffer;
495         struct interface *ifn;
496         int namesize;
497   
498         /* looping trough interfaces */
499         for (ifn = ifnet; ifn ; ifn = ifn->int_next) 
500         {
501                 olsr_printf(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
502
503                 /* fill message */
504                 if(olsr_cnf->ip_version == AF_INET)
505                 {
506                         /* IPv4 */
507                         message->v4.olsr_msgtype = MESSAGE_TYPE;
508                         message->v4.olsr_vtime = double_to_me(my_timeout);
509                         memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
510                         message->v4.ttl = MAX_TTL;
511                         message->v4.hopcnt = 0;
512                         message->v4.seqno = htons(get_msg_seqno());
513                         
514                         namesize = encap_namemsg((struct namemsg*)&message->v4.message);
515                         namesize = namesize + sizeof(struct olsrmsg);
516                         
517                         message->v4.olsr_msgsize = htons(namesize);
518                 }
519                 else
520                 {
521                         /* IPv6 */
522                         message->v6.olsr_msgtype = MESSAGE_TYPE;
523                         message->v6.olsr_vtime = double_to_me(my_timeout);
524                         memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
525                         message->v6.ttl = MAX_TTL;
526                         message->v6.hopcnt = 0;
527                         message->v6.seqno = htons(get_msg_seqno());
528                         
529                         namesize = encap_namemsg((struct namemsg*)&message->v6.message);
530                         namesize = namesize + sizeof(struct olsrmsg6);
531                         
532                         message->v6.olsr_msgsize = htons(namesize);
533                 }
534                 
535                 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
536                         /* send data and try again */
537                         net_output(ifn);
538                         if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
539                                 olsr_printf(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
540                         }
541                 }
542         }
543 }
544
545
546 /**
547  * Parse name olsr message of NAME type
548  */
549 void
550 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *in_addr)
551 {
552         struct namemsg *namemessage;
553         union olsr_ip_addr originator;
554         double vtime;
555         int size;
556         olsr_u16_t seqno;
557
558         /* Fetch the originator of the messsage */
559         if(olsr_cnf->ip_version == AF_INET) {
560                 memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
561                 seqno = ntohs(m->v4.seqno);
562         } else {
563                 memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
564                 seqno = ntohs(m->v6.seqno);
565         }
566                 
567         /* Fetch the message based on IP version */
568         if(olsr_cnf->ip_version == AF_INET) {
569                 vtime = ME_TO_DOUBLE(m->v4.olsr_vtime);
570                 size = ntohs(m->v4.olsr_msgsize);
571                 namemessage = (struct namemsg*)&m->v4.message;
572         }
573         else {
574                 vtime = ME_TO_DOUBLE(m->v6.olsr_vtime);
575                 size = ntohs(m->v6.olsr_msgsize);
576                 namemessage = (struct namemsg*)&m->v6.message;
577         }
578
579         /* Check if message originated from this node. 
580         If so - back off */
581         if(memcmp(&originator, &olsr_cnf->main_addr, olsr_cnf->ipsize) == 0)
582                 return;
583
584         /* Check that the neighbor this message was received from is symmetric. 
585         If not - back off*/
586         if(check_neighbor_link(in_addr) != SYM_LINK) {
587                 olsr_printf(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(in_addr));
588                 return;
589         }
590
591         /* Check if this message has been processed before
592         * Remeber that this also registeres the message as
593         * processed if nessecary
594         */
595         if(!olsr_check_dup_table_proc(&originator, seqno)) {
596                 /* If so - do not process */
597                 goto forward;
598         }
599
600         update_name_entry(&originator, namemessage, size, vtime);
601
602 forward:
603         /* Forward the message if nessecary
604         * default_fwd does all the work for us! */
605         olsr_forward_message(m, &originator, seqno, in_if, in_addr);
606 }
607
608
609 /**
610  * Encapsulate a name message into a packet. 
611  *
612  * It assumed that there is enough space in the buffer to do this!
613  *
614  * Returns: the length of the message that was appended
615  */
616 int
617 encap_namemsg(struct namemsg* msg)
618 {
619         struct name_entry *my_name;
620         struct name_entry *my_service;
621
622     // add the hostname, service and forwarder entries after the namemsg header
623         char* pos = (char*)msg + sizeof(struct namemsg);
624         short i=0;
625
626         // names
627         for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
628         {
629         pos = create_packet( (struct name*) pos, my_name);
630                 i++;
631         }
632         // forwarders
633         for (my_name = my_forwarders; my_name!=NULL; my_name = my_name->next)
634         {
635         pos = create_packet( (struct name*) pos, my_name);
636                 i++;
637         }
638         // services
639         for (my_service = my_services; my_service!=NULL; my_service = my_service->next)
640         {
641         pos = create_packet( (struct name*) pos, my_service);
642                 i++;
643         }
644     
645     // write the namemsg header with the number of announced entries and the protocol version
646         msg->nr_names = htons(i);
647         msg->version = htons(NAME_PROTOCOL_VERSION);
648
649         return pos - (char*)msg; //length
650 }
651
652
653 /**
654  * convert each of my to be announced name_entries into network
655  * compatible format
656  *
657  * return the length of the name packet
658  */
659 char*  
660 create_packet(struct name* to, struct name_entry *from)
661 {
662     char *pos = (char*) to;
663     int k;
664     olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
665         from->name, olsr_ip_to_string(&from->ip), from->len);
666     to->type = htons(from->type);
667     to->len = htons(from->len);
668     memcpy(&to->ip, &from->ip, olsr_cnf->ipsize);
669     pos += sizeof(struct name);
670     strncpy(pos, from->name, from->len);
671     pos += from->len;
672     for (k = from->len; (k & 3) != 0; k++)
673         *pos++ = '\0';
674     return pos;
675 }
676
677 /**
678  * decapsulate a received name, service or forwarder and update the corresponding hash table if necessary
679  */
680 void
681 decap_namemsg(struct name *from_packet, struct name_entry **to, olsr_bool *this_table_changed )
682 {
683         struct name_entry *tmp;
684         struct name_entry *already_saved_name_entries;
685     char *name = (char*)from_packet + sizeof(struct name);
686         olsr_printf(4, "\nNAME PLUGIN: decapsulating received name, service or forwarder \n");
687     int type_of_from_packet = ntohs(from_packet->type);
688     unsigned int len_of_name = ntohs(from_packet->len);
689     
690     // don't insert the received entry again, if it has already been inserted in the hash table. 
691     // Instead only the validity time is set in insert_new_name_in_list function, which calls this one
692     for (already_saved_name_entries = (*to); already_saved_name_entries != NULL ; already_saved_name_entries = already_saved_name_entries->next)
693     {
694         if ( (type_of_from_packet==NAME_HOST || type_of_from_packet==NAME_SERVICE) && strncmp(already_saved_name_entries->name, name, len_of_name) == 0 ) {
695             olsr_printf(4, "\nNAME PLUGIN: received name or service entry %s (%s) already in hash table\n", name, olsr_ip_to_string(&already_saved_name_entries->ip));
696             return;
697         } else  if (type_of_from_packet==NAME_FORWARDER && COMP_IP(&already_saved_name_entries->ip, &from_packet->ip) ) {
698             olsr_printf(4, "\nNAME PLUGIN: received forwarder entry %s (%s) already in hash table\n", name, olsr_ip_to_string(&already_saved_name_entries->ip));
699             return;
700         }
701     }
702
703     //XXX: should I check the from_packet->ip here? If so, why not also check the ip fro HOST and SERVICE?
704     if( (type_of_from_packet==NAME_HOST && !is_name_wellformed(name))  ||  (type_of_from_packet==NAME_SERVICE && !is_service_wellformed(name)) ) {
705         olsr_printf(4, "\nNAME PLUGIN: invalid name [%s] received, skipping.\n", name );
706         return;
707     }
708
709     //ignore all packets with a too long name
710     //or a spoofed len of its included name string
711     if (len_of_name > MAX_NAME || strlen(name) != len_of_name) {
712         olsr_printf(4, "\nNAME PLUGIN: from_packet->len %d > MAX_NAME %d or from_packet->len %d !0 strlen(name [%s] in packet)\n", 
713                 len_of_name, MAX_NAME, len_of_name, name );
714         return;
715     }
716
717     //if not yet known entry 
718     tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");             
719     tmp->type = ntohs(from_packet->type);
720     tmp->len = len_of_name > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
721     tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
722     memcpy(&tmp->ip, &from_packet->ip, olsr_cnf->ipsize);
723     strncpy(tmp->name, name, tmp->len);
724     tmp->name[tmp->len] = '\0';
725
726     olsr_printf(3, "\nNAME PLUGIN: create new name/service/forwarder entry %s (%s) [len=%d] [type=%d] in linked list\n", 
727         tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
728
729     *this_table_changed = OLSR_TRUE;
730
731     // queue to front
732     tmp->next = *to;
733     *to = tmp;
734 }
735
736
737 /**
738  * unpack the received message and delegate to the decapsilation function for each
739  * name/service/forwarder entry in the message
740  */
741 void
742 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
743 {
744         char *pos, *end_pos;
745         struct name *from_packet; 
746         int i;
747
748         olsr_printf(3, "NAME PLUGIN: Received Message from %s\n", 
749                 olsr_ip_to_string(originator));
750         
751         if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
752                 olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
753                 return;
754         }
755         
756         /* now add the names from the message */
757         pos = (char*)msg + sizeof(struct namemsg);
758         end_pos = pos + msg_size - sizeof(struct name*); // at least one struct name has to be left     
759
760         for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
761         {
762                 from_packet = (struct name*)pos;
763                 
764         switch (ntohs(from_packet->type)) {
765             case NAME_HOST: 
766                 insert_new_name_in_list(originator, list, from_packet, &name_table_changed, vtime); 
767                 break;
768             case NAME_FORWARDER:
769                 insert_new_name_in_list(originator, forwarder_list, from_packet, &forwarder_table_changed, vtime); 
770                 break;
771             case NAME_SERVICE:
772                 insert_new_name_in_list(originator, service_list, from_packet, &service_table_changed, vtime); 
773                 break;
774             default:
775                 olsr_printf(3, "NAME PLUGIN: Received Message of unknown type [%d] from (%s)\n", from_packet->type, olsr_ip_to_string(originator));
776                 break;
777         }
778
779                 pos += sizeof(struct name);
780                 pos += 1 + (( ntohs(from_packet->len) - 1) | 3);
781     }
782         if (i!=0)
783                 olsr_printf(4, "NAME PLUGIN: Lost %d entries in received packet due to length inconsistency (%s)\n", i, olsr_ip_to_string(originator));
784 }
785
786
787 /**
788  * insert all the new names,services and forwarders from a received packet into the
789  * corresponding entry for this ip in the corresponding hash table
790  */
791 void
792 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)
793 {
794         int hash;
795         struct db_entry *entry;
796
797     olsr_bool entry_found = OLSR_FALSE;
798
799         hash = olsr_hashing(originator);
800
801             /* find the entry for originator, if there is already one */
802             for (entry = this_list[hash]; entry != NULL; entry = entry->next)
803             {
804                 if (memcmp(originator, &entry->originator, olsr_cnf->ipsize) == 0) {
805                     // found
806                     olsr_printf(4, "NAME PLUGIN: found entry for (%s) in its hash table\n", olsr_ip_to_string(originator));
807                 
808                     //delegate to function for parsing the packet and linking it to entry->names
809                     decap_namemsg(from_packet, &entry->names, this_table_changed);
810                     
811                     olsr_get_timestamp(vtime * 1000, &entry->timer);
812                    
813                     entry_found = OLSR_TRUE;
814                 }
815             }
816             if (! entry_found)
817             {
818                 olsr_printf(3, "NAME PLUGIN: create new db entry for ip (%s) in hash table\n", olsr_ip_to_string(originator));
819                     
820                 /* insert a new entry */
821                 entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
822                 
823                 memcpy(&entry->originator, originator, olsr_cnf->ipsize);
824                 olsr_get_timestamp(vtime * 1000, &entry->timer);
825                 entry->names = NULL;
826
827                 // queue to front
828                 entry->next = this_list[hash];
829                 this_list[hash] = entry;
830                 
831                 //delegate to function for parsing the packet and linking it to entry->names
832                 decap_namemsg(from_packet, &entry->names, this_table_changed);
833             }
834 }
835
836 /**
837  * write names to a file in /etc/hosts compatible format
838  */
839 void
840 write_hosts_file()
841 {
842         int hash;
843         struct name_entry *name;
844         struct db_entry *entry;
845         FILE* hosts;
846         FILE* add_hosts;
847         int c=0;
848         time_t currtime;
849   
850         if (!name_table_changed)
851                 return;
852
853         olsr_printf(2, "NAME PLUGIN: writing hosts file\n");
854                       
855         hosts = fopen( my_hosts_file, "w" );
856         if (hosts == NULL) {
857                 olsr_printf(2, "NAME PLUGIN: cant write hosts file\n");
858                 return;
859         }
860         
861         fprintf(hosts, "### this /etc/hosts file is overwritten regularly by olsrd\n");
862         fprintf(hosts, "### do not edit\n\n");
863
864         fprintf(hosts, "127.0.0.1\tlocalhost\n");
865         fprintf(hosts, "::1\t\tlocalhost\n\n");
866         
867         // copy content from additional hosts filename
868         if (my_add_hosts[0] != '\0') {
869                 add_hosts = fopen( my_add_hosts, "r" );
870                 if (add_hosts == NULL) {
871                         olsr_printf(2, "NAME PLUGIN: cant open additional hosts file\n");
872                 }
873                 else {
874                         fprintf(hosts, "### contents from '%s' ###\n\n", my_add_hosts);
875                         while ((c = getc(add_hosts)) != EOF)
876                                 putc(c, hosts);
877                 }
878                 fclose(add_hosts);              
879                 fprintf(hosts, "\n### olsr names ###\n\n");
880         }
881         
882         // write own names
883         for (name = my_names; name != NULL; name = name->next) {
884         fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip), name->name, my_suffix );
885         }
886         
887         // write received names
888         for (hash = 0; hash < HASHSIZE; hash++) 
889         {
890                 for(entry = list[hash]; entry != NULL; entry = entry->next)
891                 {
892                         for (name = entry->names; name != NULL; name = name->next) 
893                         {
894                 olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
895                 olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
896                 
897                 fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
898                 fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
899                         }
900                 }
901         }
902
903         if (time(&currtime)) {
904                 fprintf(hosts, "\n### written by olsrd at %s", ctime(&currtime));
905         }
906           
907         fclose(hosts);
908         name_table_changed = OLSR_FALSE;
909 }
910
911
912 /**
913  * write services to a file in the format:
914  * service  #originator ip
915  *
916  * since service has a special format
917  * each line will look similar to e.g.
918  * http://me.olsr:80|tcp|my little homepage
919  */
920 void
921 write_services_file()
922 {
923         int hash;
924         struct name_entry *name;
925         struct db_entry *entry;
926         FILE* services_file;
927         time_t currtime;
928   
929   
930         if (!service_table_changed)
931                 return;
932
933         olsr_printf(2, "NAME PLUGIN: writing services file\n");
934                       
935         services_file = fopen( my_services_file, "w" );
936         if (services_file == NULL) {
937                 olsr_printf(2, "NAME PLUGIN: cant write services_file file\n");
938                 return;
939         }
940         
941         fprintf(services_file, "### this file is overwritten regularly by olsrd\n");
942         fprintf(services_file, "### do not edit\n\n");
943
944         
945         // write own services
946         for (name = my_services; name != NULL; name = name->next) {
947         fprintf(services_file, "%s\t# my own service\n", name->name);
948         }
949         
950         // write received services
951         for (hash = 0; hash < HASHSIZE; hash++) 
952         {
953                 for(entry = service_list[hash]; entry != NULL; entry = entry->next)
954                 {
955                         for (name = entry->names; name != NULL; name = name->next) 
956                         {
957                 olsr_printf(6, "%s\t",  name->name);
958                 olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
959                 
960                 fprintf(services_file, "%s\t", name->name );
961                 fprintf(services_file, "\t#%s\n", olsr_ip_to_string(&entry->originator));
962                         }
963                 }
964         }
965
966         if (time(&currtime)) {
967                 fprintf(services_file, "\n### written by olsrd at %s", ctime(&currtime));
968         }
969           
970         fclose(services_file);
971         service_table_changed = OLSR_FALSE;
972 }
973
974 /**
975  * write the 3 best upstream DNS servers to resolv.conf file
976  * best means the 3 with the best etx value in routing table
977  */
978 void
979 write_resolv_file()
980 {
981         int hash;
982         struct name_entry *name, *tmp_dns, *last_dns, *dnslist = NULL;
983         struct db_entry *entry;
984         struct rt_entry *best_routes = NULL;
985         struct rt_entry *route, *tmp = NULL, *last;
986         FILE* resolv;
987         int i=0;
988         time_t currtime;
989         
990         if (!forwarder_table_changed || my_forwarders != NULL || my_resolv_file[0] == '\0')
991                 return;
992
993         for (hash = 0; hash < HASHSIZE; hash++) 
994         {
995                 for(entry = forwarder_list[hash]; entry != NULL; entry = entry->next)
996                 {
997                         for (name = entry->names; name != NULL; name = name->next) 
998                         {
999                                 
1000                                 /* find the nearest one */
1001                                 route = host_lookup_routing_table(&name->ip);
1002                                 if (route==NULL) // it's possible that route is not present yet
1003                                         continue;
1004                                 
1005                                 if (best_routes == NULL || route->rt_etx < best_routes->rt_etx) {
1006                                         olsr_printf(6, "NAME PLUGIN: best nameserver %s\n",
1007                                                 olsr_ip_to_string(&name->ip));
1008                                         if (best_routes!=NULL)
1009                                                 olsr_printf(6, "NAME PLUGIN: better than %f (%s)\n",
1010                                                         best_routes->rt_etx,
1011                                                         olsr_ip_to_string(&best_routes->rt_dst));
1012                                         
1013                                         tmp = olsr_malloc(sizeof(struct rt_entry), "new rt_entry");
1014                                         memcpy(&tmp->rt_dst, &route->rt_dst, olsr_cnf->ipsize);
1015                                         tmp->rt_etx = route->rt_etx;
1016                                         tmp->next = best_routes;
1017                                         best_routes = tmp;
1018                                         tmp_dns = olsr_malloc(sizeof(struct name_entry), "write_resolv name_entry");
1019                                         COPY_IP(&tmp_dns->ip, &name->ip);
1020                                         tmp_dns->type = name->type;
1021                                         tmp_dns->len = 0;
1022                                         tmp_dns->name = NULL;
1023                                         tmp_dns->next = dnslist;
1024                                         dnslist = tmp_dns;
1025                                 } else {
1026                                         // queue in etx order
1027                                         last = best_routes;
1028                                         last_dns = dnslist;
1029                                         while ( last->next!=NULL && i<3 ) {
1030                                                 if (last->next->rt_etx > route->rt_etx)
1031                                                         break;
1032                                                 last = last->next;
1033                                                 last_dns = last_dns->next;
1034                                                 i++;
1035                                         }
1036                                         if (i<3) {
1037                                                 olsr_printf(6, "NAME PLUGIN: queue %f (%s)",
1038                                                         route->rt_etx,
1039                                                         olsr_ip_to_string(&name->ip));
1040                                                 olsr_printf(6, " after %f (%s)\n", 
1041                                                         last->rt_etx, olsr_ip_to_string(&last_dns->ip));
1042                                                 
1043                                                 tmp = olsr_malloc(sizeof(struct rt_entry), "new rt_entry");
1044                                                 memcpy(&tmp->rt_dst, &route->rt_dst, olsr_cnf->ipsize);
1045                                                 tmp->rt_etx = route->rt_etx;
1046                                                 tmp->next = last->next;
1047                                                 last->next = tmp;
1048
1049                                                 tmp_dns = olsr_malloc(sizeof(struct name_entry), "write_resolv name_entry");
1050                                                 COPY_IP(&tmp_dns->ip, &name->ip);
1051                                                 tmp_dns->type = name->type;
1052                                                 tmp_dns->len = 0;
1053                                                 tmp_dns->name = NULL;
1054                                                 tmp_dns->next = last_dns->next;
1055                                                 last_dns->next = tmp_dns;
1056                                         } else {
1057                                                 olsr_printf(6, "NAME PLUGIN: don't need more than 3 nameservers\n");
1058                                         }
1059                                 }
1060                         }
1061                 }
1062         }
1063         if (best_routes==NULL)
1064                 return;
1065                  
1066         /* write to file */
1067     olsr_printf(2, "NAME PLUGIN: try to write to resolv file\n");
1068         resolv = fopen( my_resolv_file, "w" );
1069         if (resolv == NULL) {
1070                 olsr_printf(2, "NAME PLUGIN: can't write resolv file\n");
1071                 return;
1072         }
1073         fprintf(resolv, "### this file is overwritten regularly by olsrd\n");
1074         fprintf(resolv, "### do not edit\n\n");
1075         i=0;
1076         for (tmp_dns=dnslist; tmp_dns!=NULL && i<3; tmp_dns=tmp_dns->next) {
1077                 olsr_printf(6, "NAME PLUGIN: nameserver %s\n", olsr_ip_to_string(&tmp_dns->ip));
1078                 fprintf(resolv, "nameserver %s\n", olsr_ip_to_string(&tmp_dns->ip));
1079                 i++;
1080         }
1081         free_name_entry_list(&dnslist);
1082         if(tmp != NULL) {
1083             free_routing_table_list(&tmp);
1084         }
1085         if (time(&currtime)) {
1086                 fprintf(resolv, "\n### written by olsrd at %s", ctime(&currtime));
1087         }
1088         fclose(resolv);
1089         forwarder_table_changed = OLSR_FALSE;
1090 }
1091
1092
1093 /**
1094  * completely free a list of name_entries
1095  */
1096 void 
1097 free_name_entry_list(struct name_entry **list) 
1098 {
1099         struct name_entry **tmp = list;
1100         struct name_entry *to_delete;
1101         while (*tmp != NULL) {
1102                 to_delete = *tmp;
1103                 *tmp = (*tmp)->next;
1104                 free( to_delete->name );
1105                 to_delete->name = NULL;
1106                 free( to_delete );
1107                 to_delete = NULL;
1108         }
1109 }
1110
1111
1112 /**
1113  * completely free a list of rt_entries
1114  */
1115 static void 
1116 free_routing_table_list(struct rt_entry **list) 
1117 {
1118         struct rt_entry **tmp = list;
1119         struct rt_entry *to_delete;
1120         while (*tmp != NULL) {
1121                 to_delete = *tmp;
1122                 *tmp = (*tmp)->next;
1123                 free( to_delete );
1124                 to_delete = NULL;
1125         }
1126 }
1127
1128
1129 /**
1130  * we only allow names for IP addresses which we are
1131  * responsible for: 
1132  * so the IP must either be from one of the interfaces
1133  * or inside a HNA which we have configured 
1134  */
1135 olsr_bool
1136 allowed_ip(union olsr_ip_addr *addr)
1137 {
1138         struct hna4_entry *hna4;
1139         struct hna6_entry *hna6;
1140         struct interface *iface;
1141         union olsr_ip_addr tmp_ip, tmp_msk;
1142         
1143         olsr_printf(6, "checking %s\n", olsr_ip_to_string(addr));
1144         
1145         for(iface = ifnet; iface; iface = iface->int_next)
1146         {
1147                 olsr_printf(6, "interface %s\n", olsr_ip_to_string(&iface->ip_addr));
1148                 if (COMP_IP(&iface->ip_addr, addr)) {
1149                         olsr_printf(6, "MATCHED\n");
1150                         return OLSR_TRUE;
1151                 }
1152         }
1153         
1154         if (olsr_cnf->ip_version == AF_INET) {
1155                 for (hna4 = olsr_cnf->hna4_entries; hna4; hna4 = hna4->next)
1156                 {
1157                         olsr_printf(6, "HNA %s/%s\n", 
1158                                 olsr_ip_to_string(&hna4->net),
1159                                 olsr_ip_to_string(&hna4->netmask));
1160         
1161                         if ( hna4->netmask.v4 != 0 &&
1162                             (addr->v4 & hna4->netmask.v4) == hna4->net.v4 ) {
1163                                 olsr_printf(6, "MATCHED\n");
1164                                 return OLSR_TRUE;
1165                         }
1166                 }
1167         } else {
1168                 int i;
1169
1170                 for (hna6 = olsr_cnf->hna6_entries; hna6; hna6 = hna6->next)
1171                 {
1172                         olsr_printf(6, "HNA %s/%d\n", 
1173                                 olsr_ip_to_string(&hna6->net),
1174                                 hna6->prefix_len);
1175                         if ( hna6->prefix_len == 0 )
1176                                 continue;
1177                         olsr_prefix_to_netmask(&tmp_msk, hna6->prefix_len);
1178                         for (i = 0; i < 16; i++) {
1179                                 tmp_ip.v6.s6_addr[i] = addr->v6.s6_addr[i] &
1180                                         tmp_msk.v6.s6_addr[i];
1181                         }
1182                         if (COMP_IP(&tmp_ip, &hna6->net)) {
1183                                 olsr_printf(6, "MATCHED\n");
1184                                 return OLSR_TRUE;
1185                         }
1186                 }
1187         }
1188         return OLSR_FALSE;
1189 }
1190
1191 static struct rt_entry *
1192 host_lookup_routing_table(union olsr_ip_addr *dst)
1193 {
1194         olsr_u32_t index;
1195         union olsr_ip_addr tmp_ip, tmp_msk;
1196         struct rt_entry *walker;
1197   
1198         walker = olsr_lookup_routing_table(dst);
1199         if (walker != NULL)
1200                 return walker;
1201
1202         for (index = 0; index < HASHSIZE; index++) {
1203                 for (walker = hna_routes[index].next;
1204                     walker != &hna_routes[index]; walker = walker->next) {
1205                         if (COMP_IP(&walker->rt_dst, dst))
1206                                 return walker;
1207                         if (olsr_cnf->ip_version == AF_INET) {
1208                                 if ( walker->rt_mask.v4 != 0 &&
1209                                     (dst->v4 & walker->rt_mask.v4) ==
1210                                     walker->rt_dst.v4 ) {
1211                                         olsr_printf(6, "MATCHED\n");
1212                                         return walker;
1213                                 }
1214                         } else {
1215                                 int i;
1216
1217                                 if ( walker->rt_mask.v6 == 0 )
1218                                         continue;
1219                                 olsr_prefix_to_netmask(&tmp_msk,
1220                                     walker->rt_mask.v6);
1221                                 for (i = 0; i < 16; i++) {
1222                                         tmp_ip.v6.s6_addr[i] =
1223                                             dst->v6.s6_addr[i] &
1224                                             tmp_msk.v6.s6_addr[i];
1225                                 }
1226                                 if (COMP_IP(&tmp_ip, &walker->rt_dst)) {
1227                                         olsr_printf(6, "MATCHED\n");
1228                                         return walker;
1229                                 }
1230                         }
1231                 }
1232         }
1233         return NULL;
1234 }
1235
1236 /** check if name has the right syntax, i.e. it must adhere to a special regex 
1237  * stored in regex_t_name
1238  * necessary to avaid names like "0.0.0.0 google.de\n etc"
1239  */
1240 olsr_bool
1241 is_name_wellformed(char *name) {
1242     return regexec(&regex_t_name, name, 1, &regmatch_t_name, 0) == 0 ;
1243 }
1244
1245
1246 /**
1247  * check if the service is in the right syntax and also that the hostname 
1248  * or ip whithin the service is allowed
1249  */
1250 olsr_bool
1251 allowed_service(char *service_line)
1252 {
1253     /* the call of is_service_wellformed generates the submatches stored in regmatch_t_service
1254      * these are then used by allowed_hostname_or_ip_in_service
1255      * see regexec(3) for more infos */
1256     if (!is_service_wellformed(service_line)) {
1257         return OLSR_FALSE;
1258     } else if (!allowed_hostname_or_ip_in_service(service_line, &(regmatch_t_service[1]))) {
1259         return OLSR_FALSE;
1260     } 
1261
1262    return OLSR_TRUE;
1263 }
1264
1265 olsr_bool
1266 allowed_hostname_or_ip_in_service(char *service_line, regmatch_t *hostname_or_ip_match) 
1267 {
1268     char *hostname_or_ip;
1269     struct in_addr ip;
1270     union olsr_ip_addr olsr_ip;
1271     struct name_entry *name;
1272     if (hostname_or_ip_match->rm_so < 0 || hostname_or_ip_match->rm_eo < 0) {
1273           return OLSR_FALSE;
1274     } 
1275
1276     hostname_or_ip = strndup(&service_line[hostname_or_ip_match->rm_so], hostname_or_ip_match->rm_eo - hostname_or_ip_match->rm_so);
1277     //hostname is one of the names, that I announce (i.e. one that i am allowed to announce)
1278     for (name = my_names; name != NULL; name = name->next) {
1279         if (strncmp(name->name, hostname_or_ip, name->len - strlen(my_suffix)) == 0 ) {
1280             olsr_printf(4, "NAME PLUGIN: hostname %s in service %s is OK\n", hostname_or_ip, service_line);
1281             free(hostname_or_ip);
1282             hostname_or_ip = NULL;
1283             return OLSR_TRUE;
1284         }
1285     }
1286     
1287     //ip in service-line is allowed 
1288     if (inet_aton(hostname_or_ip, &ip)) {
1289         olsr_ip.v4 = ip.s_addr;
1290         if (allowed_ip(&olsr_ip)) {
1291             olsr_printf(2, "NAME PLUGIN: ip %s in service %s is OK\n", olsr_ip_to_string(&olsr_ip), service_line);
1292             free(hostname_or_ip);
1293             hostname_or_ip = NULL;
1294             return OLSR_TRUE;
1295         }
1296     }
1297
1298     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);
1299     free(hostname_or_ip);
1300     hostname_or_ip = NULL;
1301
1302     return OLSR_FALSE;
1303 }
1304
1305 /**
1306  * check if the service matches the syntax 
1307  * of "protocol://host:port/path|tcp_or_udp|a short description", 
1308  * which is given in the regex regex_t_service
1309  */
1310 olsr_bool
1311 is_service_wellformed(char *service_line)
1312 {
1313     return regexec(&regex_t_service, service_line, pmatch_service, regmatch_t_service, 0) == 0;
1314 }
1315
1316 /*
1317  * Local Variables:
1318  * mode: c
1319  * c-indent-tabs-mode: t
1320  * c-basic-offset: 4
1321  * tab-width: 4
1322  * End:
1323  */