Update to new avl/list iteration macros
[olsrd.git] / lib / nameservice / src / mapwrite.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
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
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50
51 #include "defs.h"
52 #include "scheduler.h"
53 #include "nameservice.h"
54 #include "mid_set.h"
55 #include "tc_set.h"
56 #include "ipcalc.h"
57 #include "lq_plugin.h"
58 #include "olsr_logging.h"
59
60 #include "mapwrite.h"
61
62 static char my_latlon_str[48];
63 static struct olsr_timer_info *map_poll_timer_info;
64
65 /**
66  * lookup a nodes position
67  */
68 static char *
69 lookup_position_latlon(union olsr_ip_addr *ip)
70 {
71   int hash;
72   struct db_entry *entry;
73   struct list_entity *list_head;
74
75   if (olsr_ipcmp(ip, &olsr_cnf->router_id) == 0) {
76     return my_latlon_str;
77   }
78
79   for (hash = 0; hash < HASHSIZE; hash++) {
80     list_head = &latlon_list[hash];
81
82     list_for_each_element(list_head, entry, db_list) {
83       if (entry->names && olsr_ipcmp(&entry->originator, ip) == 0) {
84         return entry->names->name;
85       }
86     }
87   }
88   return NULL;
89 }
90
91 /**
92  * write latlon positions to a file
93  */
94 void
95 mapwrite_work(FILE * fmap)
96 {
97   int hash;
98   struct olsr_if_config *ifs;
99   union olsr_ip_addr ip;
100   struct ipaddr_str strbuf1, strbuf2;
101   struct tc_entry *tc, *tc_iterator;
102   struct tc_edge_entry *tc_edge, *edge_iterator;
103
104   if (!my_names || !fmap)
105     return;
106
107   for (ifs = olsr_cnf->if_configs; ifs; ifs = ifs->next) {
108     if (0 != ifs->interf) {
109       if (olsr_cnf->ip_version == AF_INET) {
110         if (ip4cmp(&olsr_cnf->router_id.v4, &ifs->interf->int_src.v4.sin_addr) != 0) {
111           if (0 > fprintf(fmap, "Mid('%s','%s');\n",
112                           olsr_ip_to_string(&strbuf1, &olsr_cnf->router_id),
113                           olsr_sockaddr_to_string(&strbuf2, &ifs->interf->int_src))) {
114             return;
115           }
116         }
117       } else if (ip6cmp(&olsr_cnf->router_id.v6, &ifs->interf->int_src.v6.sin6_addr) != 0) {
118         if (0 > fprintf(fmap, "Mid('%s','%s');\n",
119                         olsr_ip_to_string(&strbuf1, &olsr_cnf->router_id),
120                         olsr_sockaddr_to_string(&strbuf2, &ifs->interf->int_src))) {
121           return;
122         }
123       }
124     }
125   }
126
127   OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
128     struct mid_entry *alias, *alias_iterator;
129     OLSR_FOR_ALL_TC_MID_ENTRIES(tc, alias, alias_iterator) {
130       if (0 > fprintf(fmap, "Mid('%s','%s');\n",
131                       olsr_ip_to_string(&strbuf1, &tc->addr), olsr_ip_to_string(&strbuf2, &alias->mid_alias_addr))) {
132         return;
133       }
134     }
135   }
136
137   lookup_defhna_latlon(&ip);
138   sprintf(my_latlon_str, "%f,%f,%d", my_lat, my_lon, get_isdefhna_latlon());
139   if (0 > fprintf(fmap, "Self('%s',%s,'%s','%s');\n",
140                   olsr_ip_to_string(&strbuf1, &olsr_cnf->router_id), my_latlon_str,
141                   olsr_ip_to_string(&strbuf2, &ip), my_names->name)) {
142     return;
143   }
144   for (hash = 0; hash < HASHSIZE; hash++) {
145     struct db_entry *entry;
146     struct list_entity *list_head;
147
148     list_head = &latlon_list[hash];
149     list_for_each_element(list_head, entry, db_list) {
150       if (NULL != entry->names) {
151         if (0 > fprintf(fmap, "Node('%s',%s,'%s','%s');\n",
152                         olsr_ip_to_string(&strbuf1, &entry->originator),
153                         entry->names->name, olsr_ip_to_string(&strbuf2, &entry->names->ip),
154                         lookup_name_latlon(&entry->originator))) {
155           return;
156         }
157       }
158     }
159   }
160
161   OLSR_FOR_ALL_TC_ENTRIES(tc, tc_iterator) {
162     OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge, edge_iterator) {
163       char *lla = lookup_position_latlon(&tc->addr);
164       char *llb = lookup_position_latlon(&tc_edge->T_dest_addr);
165       if (NULL != lla && NULL != llb) {
166         char lqbuffer[LQTEXT_MAXLENGTH];
167
168         /*
169          * To speed up processing, Links with both positions are named PLink()
170          */
171         if (0 > fprintf(fmap, "PLink('%s','%s',%s,%s,%s);\n",
172                         olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
173                         olsr_ip_to_string(&strbuf2, &tc->addr),
174                         olsr_get_linkcost_text(tc_edge->cost, false, lqbuffer, sizeof(lqbuffer)), lla, llb)) {
175           return;
176         }
177       } else {
178         char lqbuffer[LQTEXT_MAXLENGTH];
179
180         /*
181          * If one link end pos is unkown, only send Link()
182          */
183         if (0 > fprintf(fmap, "Link('%s','%s',%s);\n",
184                         olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
185                         olsr_ip_to_string(&strbuf2, &tc->addr),
186                         olsr_get_linkcost_text(tc_edge->cost, false, lqbuffer, sizeof(lqbuffer)))) {
187           return;
188         }
189       }
190     }
191   }
192 }
193
194 #ifndef WIN32
195
196 /*
197  * Windows doesn't know fifo's AFAIK. We better write
198  * to a file (done in nameservice.c, see #ifdef WIN32)
199  */
200
201 static const char *the_fifoname = 0;
202
203 static void
204 mapwrite_poll(void *context __attribute__ ((unused)))
205 {
206   FILE *fout;
207   /* Non-blocking means: fail open if no pipe reader */
208   int fd = open(the_fifoname, O_WRONLY | O_NONBLOCK);
209   if (0 <= fd) {
210     /*
211      * Change to blocking, otherwhise expect fprintf errors
212      */
213     fcntl(fd, F_SETFL, O_WRONLY);
214     fout = fdopen(fd, "w");
215     if (0 != fout) {
216       mapwrite_work(fout);
217       fclose(fout);
218       /* Give pipe reader cpu slot to detect EOF */
219       usleep(1);
220     } else {
221       close(fd);
222     }
223   }
224 }
225
226 int
227 mapwrite_init(const char *fifoname)
228 {
229   the_fifoname = fifoname;
230   if (0 != fifoname && 0 != *fifoname) {
231     unlink(fifoname);
232     if (0 > mkfifo(fifoname, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) {
233       OLSR_WARN(LOG_PLUGINS, "mkfifo(%s): %s", fifoname, strerror(errno));
234       return false;
235     } else {
236       map_poll_timer_info = olsr_alloc_timerinfo("Nameservice: mapwrite", &mapwrite_poll, true);
237       olsr_start_timer(800, 5, NULL, map_poll_timer_info);
238     }
239   }
240   return true;
241 }
242
243 void
244 mapwrite_exit(void)
245 {
246   if (0 != the_fifoname) {
247     unlink(the_fifoname);
248     /* Ignore any Error */
249     the_fifoname = 0;
250   }
251 }
252 #endif
253
254 /*
255  * Local Variables:
256  * c-basic-offset: 2
257  * indent-tabs-mode: nil
258  * End:
259  */