add localhost to /etc/hosts file
[olsrd.git] / lib / nameservice / src / nameservice.c
1 /*
2  * Copyright (c) 2005, Bruno Randolf <bruno.randolf@4g-systems.biz>
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto-at-olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, 
11  *   this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright notice, 
13  *   this list of conditions and the following disclaimer in the documentation 
14  *   and/or other materials provided with the distribution.
15  * * Neither the name of the UniK olsr daemon nor the names of its contributors 
16  *   may be used to endorse or promote products derived from this software 
17  *   without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
22  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31
32 /* $Id: nameservice.c,v 1.12 2005/04/28 12:46:32 br1 Exp $ */
33
34 /*
35  * Dynamic linked library for UniK OLSRd
36  */
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include "nameservice.h"
43 #include "olsrd_copy.h"
44
45 #include "routing_table.h"
46
47 /* send buffer: huge */
48 static char buffer[10240];
49
50 /* config parameters */
51 static char my_hosts_file[MAX_FILE + 1];
52 static char my_add_hosts[MAX_FILE + 1];
53 static char my_suffix[MAX_SUFFIX];
54 static int my_interval = EMISSION_INTERVAL;
55 static double my_timeout = NAME_VALID_TIME;
56 static olsr_bool have_dns_server = OLSR_FALSE;
57 static union olsr_ip_addr my_dns_server;
58 static char my_resolv_file[MAX_FILE +1];
59
60 /* the database (using hashing) */
61 struct db_entry* list[HASHSIZE];
62 struct name_entry *my_names = NULL;
63 olsr_bool name_table_changed = OLSR_TRUE;
64
65
66 /**
67  * do initialization
68  */
69 void
70 name_constructor() 
71 {
72         int i;
73         
74 #ifdef WIN32
75         int len;
76
77         GetWindowsDirectory(my_hosts_file, MAX_FILE - 12);
78
79         len = strlen(my_hosts_file);
80  
81         if (my_hosts_file[len - 1] != '\\')
82                 my_hosts_file[len++] = '\\';
83  
84         strcpy(my_hosts_file + len, "hosts_olsr");
85 #else
86         strcpy(my_hosts_file, "/var/run/hosts_olsr");
87 #endif
88
89         my_suffix[0] = '\0';
90         my_add_hosts[0] = '\0';
91         my_resolv_file[0] = '\0';
92         
93         /* init list */
94         for(i = 0; i < HASHSIZE; i++) {
95                 list[i] = NULL;
96         }
97         
98         memset(&my_dns_server, 0, sizeof(my_dns_server));
99 }
100
101
102 /**
103  * called for all plugin parameters
104  */
105 int
106 register_olsr_param(char *key, char *value)
107 {
108         if(!strcmp(key, "interval")) {
109                 my_interval = atoi(value);
110                 printf("\nNAME PLUGIN: parameter interval: %d\n", my_interval);
111         }
112         else if(!strcmp(key, "timeout")) {
113                 my_timeout = atof(value);
114                 printf("\nNAME PLUGIN: parameter timeout: %f\n", my_timeout);
115         } 
116         else if(!strcmp(key, "hosts-file")) {
117                 strncpy( my_hosts_file, value, MAX_FILE );
118                 printf("\nNAME PLUGIN: parameter filename: %s\n", my_hosts_file);
119         }
120         else if(!strcmp(key, "resolv-file")) {
121                 strncpy(my_resolv_file, value, MAX_FILE);
122                 printf("\nNAME PLUGIN: parameter resolv file: %s\n", my_resolv_file);
123         }
124         else if(!strcmp(key, "suffix")) {
125                 strncpy(my_suffix, value, MAX_SUFFIX);
126                 printf("\nNAME PLUGIN: parameter suffix: %s\n", my_suffix);
127         }
128         else if(!strcmp(key, "add-hosts")) {
129                 strncpy(my_add_hosts, value, MAX_FILE);
130                 printf("\nNAME PLUGIN: parameter additional host: %s\n", my_add_hosts);
131         }
132         else if(!strcmp(key, "dns-server")) {
133                 struct in_addr ip;
134                 if (strlen(value) == 0) {
135                         // set dns server ip to main address
136                         // which is not known yet
137                         have_dns_server = OLSR_TRUE;
138                 }
139                 else if (inet_aton(value, &ip)) {
140                         my_dns_server.v4 = ip.s_addr;
141                         have_dns_server = OLSR_TRUE;
142                 }
143                 else {
144                         printf("\nNAME PLUGIN: invalid dns-server IP %s\n", value);
145                 }
146         }
147         else if(!strcmp(key, "name")) {
148                 // name for main address
149                 struct name_entry *tmp;
150                 tmp = malloc(sizeof(struct name_entry));
151                 tmp->name = strndup( value, MAX_NAME );
152                 tmp->len = strlen( tmp->name );
153                 tmp->type = NAME_HOST;
154                 // will be set to main_addr later
155                 memset(&tmp->ip, 0, sizeof(tmp->ip));
156                 tmp->next = my_names;
157                 my_names = tmp;
158                 
159                 printf("\nNAME PLUGIN: parameter name: %s (main address)\n", tmp->name);
160         }
161         else {
162                 // assume this is an IP address and hostname
163                 struct in_addr ip;
164                 
165                 if (inet_aton(key, &ip)) {
166                         // the IP is validated later
167                         struct name_entry *tmp;
168                         tmp = malloc(sizeof(struct name_entry));
169                         tmp->name = strndup( value, MAX_NAME );
170                         tmp->len = strlen( tmp->name );
171                         tmp->type = NAME_HOST;
172                         tmp->ip.v4 = ip.s_addr;
173                         tmp->next = my_names;
174                         my_names = tmp;
175                         printf("\nNAME PLUGIN: parameter %s (%s)\n", tmp->name,
176                                 olsr_ip_to_string(&tmp->ip));
177                 } 
178                 else {
179                         printf("\nNAME PLUGIN: invalid IP %s for name %s!\n", key, value);
180                 }
181         }
182
183         return 1;
184 }
185
186
187 /**
188  * last initialization
189  *
190  * we have to do this here because some things like main_addr 
191  * are not known before
192  *
193  * this is beause of the order in which the plugin is initzalized 
194  * by the plugin loader:
195  *   - first the parameters are sent
196  *   - then register_olsr_data() from olsrd_plugin.c is called
197  *     which sets up main_addr and some other variables
198  *   - register_olsr_data() then then finally calls this function
199  */
200 int
201 olsr_plugin_init()
202 {
203         struct name_entry *name;
204         struct name_entry *prev=NULL;
205
206         /* fixup names and IP addresses */
207         for (name = my_names; name != NULL; name = name->next) {
208                 if (name->ip.v4 == 0) {
209                         // insert main_addr
210                         memcpy(&name->ip, main_addr, ipsize);
211                         prev = name;
212                 } else {
213                         // IP from config file
214                         // check if we are allowed to announce a name for this IP
215                         // we can only do this if we also announce the IP        
216                         if (!allowed_ip(&name->ip)) {
217                                 olsr_printf(1, "NAME PLUGIN: name for unknown IP %s not allowed, fix your config!\n", 
218                                         olsr_ip_to_string(&name->ip));
219                                 if (prev!=NULL) {
220                                         prev->next = name->next;
221                                         free(name->name);
222                                         free(name);
223                                 }
224                         }
225                         else {
226                                 prev = name;
227                         }
228                 }
229         }
230                 
231         if (have_dns_server) {
232                 if (my_dns_server.v4 == 0) {
233                         memcpy(&my_dns_server, main_addr, ipsize);
234                         printf("\nNAME PLUGIN: announcing upstream DNS server: %s\n", 
235                                 olsr_ip_to_string(&my_dns_server));
236                 }
237                 else if (!allowed_ip(&my_dns_server)) {
238                         printf("NAME PLUGIN: announcing DNS server on unknown IP %s is not allowed, fix your config!\n", 
239                                 olsr_ip_to_string(&my_dns_server));
240                         memset(&my_dns_server, 0, sizeof(my_dns_server));
241                         have_dns_server = OLSR_FALSE;
242                 }
243                 else {
244                         printf("\nNAME PLUGIN: announcing upstream DNS server: %s\n", 
245                                 olsr_ip_to_string(&my_dns_server));
246                 }
247         }
248         
249         /* register functions with olsrd */
250         olsr_parser_add_function(&olsr_parser, PARSER_TYPE, 1);
251         olsr_register_timeout_function(&olsr_timeout);
252         olsr_register_scheduler_event(&olsr_event, NULL, my_interval, 0, NULL);
253
254         return 1;
255 }
256
257
258 /**
259  * called at unload: free everything
260  */
261 void
262 olsr_plugin_exit()
263 {
264         int i;
265         struct db_entry **tmp;
266         struct db_entry *to_delete;
267         
268         olsr_printf(2, "NAME PLUGIN: exit. cleaning up...\n");
269         
270         free_name_entry_list(&my_names);
271         
272         /* free list entries */
273         for(i = 0; i < HASHSIZE; i++)
274         {
275                 tmp = &list[i];
276                 while(*tmp != NULL)
277                 {
278                         to_delete = *tmp;
279                         *tmp = (*tmp)->next;
280                         free_name_entry_list(&to_delete->names);
281                         free(to_delete);
282                         to_delete = NULL;
283                 }
284         }
285 }
286
287
288 /**
289  * A timeout function called every time
290  * the scheduler is polled: time out old list entries
291  * and write changes to file
292  */
293 void
294 olsr_timeout()
295 {
296         struct db_entry **tmp;
297         struct db_entry *to_delete;
298         int index;
299
300         for(index=0;index<HASHSIZE;index++)
301         {
302                 for (tmp = &list[index]; *tmp != NULL; )
303                 {
304                         /* check if the entry is timed out */
305                         if (olsr_timed_out(&(*tmp)->timer))
306                         {
307                                 to_delete = *tmp;
308                                 *tmp = (*tmp)->next;
309                                 
310                                 olsr_printf(2, "NAME PLUGIN: %s timed out... deleting\n", 
311                                         olsr_ip_to_string(&to_delete->originator));
312         
313                                 /* Delete */
314                                 free_name_entry_list(&to_delete->names);
315                                 free(to_delete);
316                                 name_table_changed = OLSR_TRUE;
317                         } else {
318                                 tmp = &(*tmp)->next;
319                         }
320                 }
321         }
322         write_resolv_file();
323         write_hosts_file();
324 }
325
326
327 /**
328  * Scheduled event: generate and send NAME packet
329  */
330 void
331 olsr_event(void *foo)
332 {
333         union olsr_message *message = (union olsr_message*)buffer;
334         struct interface *ifn;
335         int namesize;
336   
337         /* looping trough interfaces */
338         for (ifn = ifs; ifn ; ifn = ifn->int_next) 
339         {
340                 olsr_printf(3, "NAME PLUGIN: Generating packet - [%s]\n", ifn->int_name);
341
342                 /* fill message */
343                 if(ipversion == AF_INET)
344                 {
345                         /* IPv4 */
346                         message->v4.olsr_msgtype = MESSAGE_TYPE;
347                         message->v4.olsr_vtime = double_to_me(my_timeout);
348                         memcpy(&message->v4.originator, main_addr, ipsize);
349                         message->v4.ttl = MAX_TTL;
350                         message->v4.hopcnt = 0;
351                         message->v4.seqno = htons(get_msg_seqno());
352                         
353                         namesize = encap_namemsg((struct namemsg*)&message->v4.message);
354                         namesize = namesize + sizeof(struct olsrmsg);
355                         
356                         message->v4.olsr_msgsize = htons(namesize);
357                 }
358                 else
359                 {
360                         /* IPv6 */
361                         message->v6.olsr_msgtype = MESSAGE_TYPE;
362                         message->v6.olsr_vtime = double_to_me(my_timeout);
363                         memcpy(&message->v6.originator, main_addr, ipsize);
364                         message->v6.ttl = MAX_TTL;
365                         message->v6.hopcnt = 0;
366                         message->v6.seqno = htons(get_msg_seqno());
367                         
368                         namesize = encap_namemsg((struct namemsg*)&message->v6.message);
369                         namesize = namesize + sizeof(struct olsrmsg6);
370                         
371                         message->v6.olsr_msgsize = htons(namesize);
372                 }
373                 
374                 if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
375                         /* send data and try again */
376                         net_output(ifn);
377                         if(net_outbuffer_push(ifn, (olsr_u8_t *)message, namesize) != namesize ) {
378                                 olsr_printf(1, "NAME PLUGIN: could not send on interface: %s\n", ifn->int_name);
379                         }
380                 }
381         }
382 }
383
384
385 /**
386  * Parse name olsr message of NAME type
387  */
388 void
389 olsr_parser(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *in_addr)
390 {
391         struct namemsg *namemessage;
392         union olsr_ip_addr originator;
393         double vtime;
394         int size;
395
396         /* Fetch the originator of the messsage */
397         memcpy(&originator, &m->v4.originator, ipsize);
398                 
399         /* Fetch the message based on IP version */
400         if(ipversion == AF_INET) {
401                 vtime = me_to_double(m->v4.olsr_vtime);
402                 size = ntohs(m->v4.olsr_msgsize);
403                 namemessage = (struct namemsg*)&m->v4.message;
404         }
405         else {
406                 vtime = me_to_double(m->v6.olsr_vtime);
407                 size = ntohs(m->v6.olsr_msgsize);
408                 namemessage = (struct namemsg*)&m->v4.message;
409         }
410
411         /* Check if message originated from this node. 
412         If so - back off */
413         if(memcmp(&originator, main_addr, ipsize) == 0)
414                 return;
415
416         /* Check that the neighbor this message was received from is symmetric. 
417         If not - back off*/
418         if(check_neighbor_link(in_addr) != SYM_LINK) {
419                 olsr_printf(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(in_addr));
420                 return;
421         }
422
423         /* Check if this message has been processed before
424         * Remeber that this also registeres the message as
425         * processed if nessecary
426         */
427         if(!check_dup_proc(&originator, ntohs(m->v4.seqno))) {
428                 /* If so - do not process */
429                 goto forward;
430         }
431
432         update_name_entry(&originator, namemessage, size, vtime);
433
434 forward:
435         /* Forward the message if nessecary
436         * default_fwd does all the work for us! */
437         default_fwd(m, &originator, ntohs(m->v4.seqno), in_if, in_addr);
438 }
439
440
441 /**
442  * Encapsulate a name message into a packet. 
443  *
444  * It assumed that there is enough space in the buffer to do this!
445  *
446  * Returns: the length of the message that was appended
447  */
448 int
449 encap_namemsg(struct namemsg* msg)
450 {
451         struct name_entry *my_name = my_names;
452         struct name* to_packet;
453         char* pos = (char*)msg + sizeof(struct namemsg);
454         short i=0;
455         int k;
456         
457         // upstream dns server
458         if (have_dns_server) {
459                 olsr_printf(3, "NAME PLUGIN: Announcing DNS server (%s)\n", 
460                         olsr_ip_to_string(&my_dns_server));
461                 to_packet = (struct name*)pos;
462                 to_packet->type = htons(NAME_FORWARDER);
463                 to_packet->len = htons(0);
464                 memcpy(&to_packet->ip, &my_dns_server, ipsize);
465                 pos += sizeof(struct name);
466                 i++;
467         }
468
469         // names
470         for (my_name = my_names; my_name!=NULL; my_name = my_name->next)
471         {
472                 olsr_printf(3, "NAME PLUGIN: Announcing name %s (%s) %d\n", 
473                         my_name->name, olsr_ip_to_string(&my_name->ip), my_name->len);
474                         
475                 to_packet = (struct name*)pos;
476                 to_packet->type = htons(my_name->type);
477                 to_packet->len = htons(my_name->len);
478                 memcpy(&to_packet->ip, &my_name->ip, ipsize);
479                 pos += sizeof(struct name);
480                 strncpy(pos, my_name->name, my_name->len);
481                 pos += my_name->len;
482                 // padding to 4 byte boundaries
483                 for (k = my_name->len; (k & 3) != 0; k++)
484                         *pos++ = '\0';
485                 i++;
486         }
487         msg->nr_names = htons(i);
488         msg->version = htons(NAME_PROTOCOL_VERSION);
489         return pos - (char*)msg; //length
490 }
491
492
493 /**
494  * decapsulate a name message and update name_entries if necessary
495  */
496 void
497 decap_namemsg( struct namemsg *msg, int size, struct name_entry **to )
498 {
499         char *pos, *end_pos;
500         struct name_entry *tmp;
501         struct name *from_packet; 
502         int i;
503         
504         olsr_printf(4, "NAME PLUGIN: decapsulating name msg (size %d)\n", size);
505         
506         if (ntohs(msg->version) != NAME_PROTOCOL_VERSION) {
507                 olsr_printf(3, "NAME PLUGIN: ignoring wrong version %d\n", msg->version);
508                 return;
509         }
510         
511         // for now ist easier to just delete everything, than
512         // to update selectively
513         free_name_entry_list(to);
514         name_table_changed = OLSR_TRUE;
515         
516         /* now add the names from the message */
517         pos = (char*)msg + sizeof(struct namemsg);
518         end_pos = pos + size - sizeof(struct name*); // at least one struct name has to be left
519         
520         for (i=ntohs(msg->nr_names); i > 0 && pos<end_pos; i--) 
521         {
522                 from_packet = (struct name*)pos;
523                 
524                 tmp = olsr_malloc(sizeof(struct name_entry), "new name_entry");         
525                 tmp->type = ntohs(from_packet->type);
526                 tmp->len = ntohs(from_packet->len) > MAX_NAME ? MAX_NAME : ntohs(from_packet->len);
527                 tmp->name = olsr_malloc(tmp->len+1, "new name_entry name");
528                 memcpy(&tmp->ip, &from_packet->ip, ipsize);
529                 pos += sizeof(struct name);
530                 strncpy(tmp->name, pos, tmp->len);
531                 tmp->name[tmp->len] = '\0';
532
533                 olsr_printf(3, "NAME PLUGIN: New name %s (%s) %d %d\n", 
534                         tmp->name, olsr_ip_to_string(&tmp->ip), tmp->len, tmp->type);
535
536                 // queue to front
537                 tmp->next = *to;
538                 *to = tmp;
539
540                 // name + padding
541                 pos += 1 + ((tmp->len - 1) | 3);
542         }
543         if (i!=0)
544                 olsr_printf(4, "NAME PLUGIN: Lost %d names due to length inconsistency\n", i);
545 }
546
547
548 /**
549  * Update or register a new name entry
550  */
551 void
552 update_name_entry(union olsr_ip_addr *originator, struct namemsg *msg, int msg_size, double vtime)
553 {
554         int hash;
555         struct db_entry *entry;
556
557         olsr_printf(3, "NAME PLUGIN: Received Name Message from %s\n", 
558                 olsr_ip_to_string(originator));
559
560         hash = olsr_hashing(originator);
561
562         /* find the entry for originator */
563         for (entry = list[hash]; entry != NULL; entry = entry->next)
564         {
565                 if (memcmp(originator, &entry->originator, ipsize) == 0) {
566                         // found
567                         olsr_printf(4, "NAME PLUGIN: %s found\n", 
568                                 olsr_ip_to_string(originator));
569                 
570                         decap_namemsg(msg, msg_size, &entry->names);
571                         
572                         olsr_get_timestamp(vtime * 1000, &entry->timer);
573                         
574                         return;
575                 }
576         }
577
578         olsr_printf(3, "NAME PLUGIN: New entry %s\n", 
579                 olsr_ip_to_string(originator));
580                 
581         /* insert a new entry */
582         entry = olsr_malloc(sizeof(struct db_entry), "new db_entry");
583         memcpy(&entry->originator, originator, ipsize);
584         olsr_get_timestamp(vtime * 1000, &entry->timer);
585         entry->names = NULL;
586         // queue to front
587         entry->next = list[hash];
588         list[hash] = entry;
589         
590         decap_namemsg(msg, msg_size, &entry->names);
591
592         name_table_changed = OLSR_TRUE;
593 }
594
595
596 /**
597  * write names to a file in /etc/hosts compatible format
598  */
599 void
600 write_hosts_file()
601 {
602         int hash;
603         struct name_entry *name;
604         struct db_entry *entry;
605         FILE* hosts;
606         FILE* add_hosts;
607         int c=0;
608         time_t currtime;
609   
610         if (!name_table_changed)
611                 return;
612
613         olsr_printf(2, "NAME PLUGIN: writing hosts file\n");
614                       
615         hosts = fopen( my_hosts_file, "w" );
616         if (hosts == NULL) {
617                 olsr_printf(2, "NAME PLUGIN: cant write hosts file\n");
618                 return;
619         }
620         
621         fprintf(hosts, "### this /etc/hosts file is overwritten regularly by olsrd\n");
622         fprintf(hosts, "### do not edit\n\n");
623
624         fprintf(hosts, "127.0.0.1\tlocalhost\n\n");
625         
626         // copy content from additional hosts filename
627         if (my_add_hosts[0] != '\0') {
628                 add_hosts = fopen( my_add_hosts, "r" );
629                 if (add_hosts == NULL) {
630                         olsr_printf(2, "NAME PLUGIN: cant open additional hosts file\n");
631                 }
632                 else {
633                         fprintf(hosts, "### contents from '%s' ###\n\n", my_add_hosts);
634                         while ((c = getc(add_hosts)) != EOF)
635                                 putc(c, hosts);
636                 }
637                 fclose(add_hosts);              
638                 fprintf(hosts, "\n### olsr names ###\n\n");
639         }
640         
641         // write own names
642         for (name = my_names; name != NULL; name = name->next) {
643                 fprintf(hosts, "%s\t%s%s\t# myself\n", olsr_ip_to_string(&name->ip),
644                         name->name, my_suffix );
645         }
646         
647         // write received names
648         for (hash = 0; hash < HASHSIZE; hash++) 
649         {
650                 for(entry = list[hash]; entry != NULL; entry = entry->next)
651                 {
652                         for (name = entry->names; name != NULL; name = name->next) 
653                         {
654                                 if (name->type == NAME_HOST) {
655                                         olsr_printf(6, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
656                                         olsr_printf(6, "\t#%s\n", olsr_ip_to_string(&entry->originator));
657                                         
658                                         fprintf(hosts, "%s\t%s%s", olsr_ip_to_string(&name->ip), name->name, my_suffix);
659                                         fprintf(hosts, "\t# %s\n", olsr_ip_to_string(&entry->originator));
660                                 }
661                         }
662                 }
663         }
664
665         if (time(&currtime)) {
666                 fprintf(hosts, "\n### written by olsrd at %s", ctime(&currtime));
667         }
668           
669         fclose(hosts);
670         name_table_changed = OLSR_FALSE;
671 }
672
673
674 /**
675  * write upstream DNS servers to resolv.conf file
676  */
677 void
678 write_resolv_file()
679 {
680         int hash;
681         struct name_entry *name;
682         struct db_entry *entry;
683         struct rt_entry *best_routes = NULL;
684         struct rt_entry *route, *tmp, *last;
685         FILE* resolv;
686         int i=0;
687         
688         if (my_resolv_file[0] == '\0')
689                 return;
690         
691         if (!name_table_changed)
692                 return;
693
694         olsr_printf(2, "NAME PLUGIN: writing resolv file\n");
695
696         for (hash = 0; hash < HASHSIZE; hash++) 
697         {
698                 for(entry = list[hash]; entry != NULL; entry = entry->next)
699                 {
700                         for (name = entry->names; name != NULL; name = name->next) 
701                         {
702                                 if (name->type != NAME_FORWARDER)
703                                         continue;
704                                 
705                                 /* find the nearest one */
706                                 route = olsr_lookup_routing_table(&name->ip);
707                                 if (route==NULL) // it's possible that route is not present yet
708                                         continue;
709                                 
710                                 if (best_routes == NULL || route->rt_etx < best_routes->rt_etx) {
711                                         olsr_printf(6, "NAME PLUGIN: best nameserver %s\n",
712                                                 olsr_ip_to_string(&route->rt_dst));
713                                         if (best_routes!=NULL)
714                                                 olsr_printf(6, "NAME PLUGIN: better than %f (%s)\n",
715                                                         best_routes->rt_etx,
716                                                         olsr_ip_to_string(&best_routes->rt_dst));
717                                         
718                                         tmp = olsr_malloc(sizeof(struct rt_entry), "new rt_entry");
719                                         memcpy(&tmp->rt_dst, &route->rt_dst, ipsize);
720                                         tmp->rt_etx = route->rt_etx;
721                                         tmp->next = best_routes;
722                                         best_routes = tmp;
723                                 } else {
724                                         // queue in etx order
725                                         last = best_routes;
726                                         while ( last->next!=NULL && i<3 ) {
727                                                 if (last->next->rt_etx > route->rt_etx)
728                                                         break;
729                                                 last = last->next;
730                                                 i++;
731                                         }
732                                         if (i<3) {
733                                                 olsr_printf(6, "NAME PLUGIN: queue %f (%s)",
734                                                         route->rt_etx,
735                                                         olsr_ip_to_string(&route->rt_dst));
736                                                 olsr_printf(6, " after %f (%s)\n", 
737                                                         last->rt_etx, olsr_ip_to_string(&last->rt_dst));
738                                                 
739                                                 tmp = olsr_malloc(sizeof(struct rt_entry), "new rt_entry");
740                                                 memcpy(&tmp->rt_dst, &route->rt_dst, ipsize);
741                                                 tmp->rt_etx = route->rt_etx;
742                                                 tmp->next = last->next;
743                                                 last->next = tmp;
744                                         } else {
745                                                 olsr_printf(6, "NAME PLUGIN: don't need more than 3 nameservers\n");
746                                         }
747                                 }
748                         }
749                 }
750         }
751         if (best_routes==NULL)
752                 return;
753                  
754         /* write to file */
755         resolv = fopen( my_resolv_file, "w" );
756         if (resolv == NULL) {
757                 olsr_printf(2, "NAME PLUGIN: can't write resolv file\n");
758                 return;
759         }
760         i=0;
761         for (tmp=best_routes; tmp!=NULL && i<3; tmp=tmp->next) {
762                 olsr_printf(6, "NAME PLUGIN: nameserver %s\n", olsr_ip_to_string(&tmp->rt_dst));
763                 fprintf(resolv, "nameserver %s\n", olsr_ip_to_string(&tmp->rt_dst));
764                 i++;
765         }
766         fclose(resolv);
767 }
768
769
770 /**
771  * completely free a list of name_entries
772  */
773 void 
774 free_name_entry_list(struct name_entry **list) 
775 {
776         struct name_entry **tmp = list;
777         struct name_entry *to_delete;
778         while (*tmp != NULL) {
779                 to_delete = *tmp;
780                 *tmp = (*tmp)->next;
781                 free( to_delete->name );
782                 free( to_delete );
783                 to_delete = NULL;
784         }
785 }
786
787
788 /**
789  * we only allow names for IP addresses which we are
790  * responsible for: 
791  * so the IP must either be from one of the interfaces
792  * or inside a HNA which we have configured 
793  */
794 olsr_bool
795 allowed_ip(union olsr_ip_addr *addr)
796 {
797         struct hna4_entry *hna4;
798         struct interface *iface;
799         
800         olsr_printf(6, "checking %s\n", olsr_ip_to_string(addr));
801         
802         for(iface = ifs; iface; iface = iface->int_next)
803         {
804                 olsr_printf(6, "interface %s\n", olsr_ip_to_string(&iface->ip_addr));
805                 if (COMP_IP(&iface->ip_addr, addr)) {
806                         olsr_printf(6, "MATCHED\n");
807                         return OLSR_TRUE;
808                 }
809         }
810         
811         for (hna4 = cfg->hna4_entries; hna4; hna4 = hna4->next)
812         {
813                 olsr_printf(6, "HNA %s/%s\n", 
814                         olsr_ip_to_string(&hna4->net),
815                         olsr_ip_to_string(&hna4->netmask));
816         
817                 if ( hna4->netmask.v4 != 0 && (addr->v4 & hna4->netmask.v4) == hna4->net.v4 ) {
818                         olsr_printf(6, "MATCHED\n");
819                         return OLSR_TRUE;
820                 }
821         }
822         return OLSR_FALSE;
823 }