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