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