64e9f0503cb3435079ce8ecd486d0803db54fac9
[olsrd.git] / lib / pgraph / src / olsrd_pgraph.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  *                     includes code by Bruno Randolf
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  * Dynamic linked library for the olsr.org olsr daemon
44  */
45
46 #include "olsrd_pgraph.h"
47 #include "ipcalc.h"
48 #include "socket_parser.h"
49 #include "olsrd_plugin.h"
50 #include "plugin_util.h"
51 #include "net_olsr.h"
52
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <errno.h>
58 #ifdef WIN32
59 #define close(x) closesocket(x)
60 #endif
61
62 #define PLUGIN_NAME    "OLSRD pgraph plugin"
63 #define PLUGIN_VERSION "0.1"
64 #define PLUGIN_AUTHOR   "Richard Gopaul"
65 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
66 #define PLUGIN_INTERFACE_VERSION 5
67
68 static union olsr_ip_addr ipc_accept_ip;
69 static int ipc_port;
70
71 static int ipc_socket;
72 static int ipc_connection;
73
74 void my_init(void) __attribute__((constructor));
75
76 void my_fini(void) __attribute__((destructor));
77
78 /*
79  * Defines the version of the plugin interface that is used
80  * THIS IS NOT THE VERSION OF YOUR PLUGIN!
81  * Do not alter unless you know what you are doing!
82  */
83 int 
84 olsrd_plugin_interface_version(void)
85 {
86    return PLUGIN_INTERFACE_VERSION;
87 }
88
89
90 /**
91  *Constructor
92  */
93 void
94 my_init(void)
95 {
96   /* Print plugin info to stdout */
97   printf("%s\n", MOD_DESC);
98
99   /* defaults for parameters */
100   ipc_port = 2004;
101   if (olsr_cnf->ip_version == AF_INET) {
102     ipc_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
103   } else {
104     ipc_accept_ip.v6 = in6addr_loopback;
105   }
106   ipc_socket = -1;
107   ipc_connection = -1;
108 }
109
110 /**
111  *Destructor
112  */
113 void
114 my_fini(void)
115 {
116   if(ipc_socket >= 0) {
117     close(ipc_socket);
118     ipc_socket = -1;
119   }
120   if(ipc_connection >= 0) {
121     close(ipc_connection);
122     ipc_connection = -1;
123   }
124
125 }
126
127 static const struct olsrd_plugin_parameters plugin_parameters[] = {
128     { .name = "port",   .set_plugin_parameter = &set_plugin_port,      .data = &ipc_port },
129     { .name = "accept", .set_plugin_parameter = &set_plugin_ipaddress, .data = &ipc_accept_ip },
130 };
131
132 void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
133 {
134     *params = plugin_parameters;
135     *size = sizeof(plugin_parameters)/sizeof(*plugin_parameters);
136 }
137
138 /* Event function to register with the sceduler */
139 static int pcf_event(int, int, int);
140
141 static void ipc_action(int);
142
143 static void ipc_print_neigh_link(struct neighbor_entry *neighbor);
144
145 static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry);
146
147 static int ipc_send(const char *, int);
148
149 static void ipc_print_neigh_link(struct neighbor_entry *);
150
151 static int plugin_ipc_init(void);
152
153
154 static void ipc_print_neigh_link(struct neighbor_entry *neighbor)
155 {
156   char buf[256];
157   int len;
158   struct ipaddr_str main_adr, adr;
159 //  double etx=0.0;
160 //  char* style = "solid";
161 //  struct link_entry* link;
162
163   len = sprintf(buf,
164                 "add link %s %s\n",
165                 olsr_ip_to_string(&main_adr, &olsr_cnf->main_addr),
166                 olsr_ip_to_string(&adr, &neighbor->neighbor_main_addr));
167   ipc_send(buf, len);
168   
169 //  if (neighbor->status == 0) { // non SYM
170 //      style = "dashed";
171 //  }
172 //  else {
173     /* find best link to neighbor for the ETX */
174     //? why cant i just get it one time at fetch_olsrd_data??? (br1)
175 //    if(olsr_plugin_io(GETD__LINK_SET, &link, sizeof(link)) && link)
176 //    {
177 //      link_set = link; // for olsr_neighbor_best_link    
178 //      link = olsr_neighbor_best_link(&neighbor->neighbor_main_addr);
179 //      if (link) {
180 //        etx = olsr_calc_etx(link);
181 //      }
182 //    }
183 //  }
184     
185   //len = sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
186   //len = sprintf( buf, "%s\n", adr );
187   //ipc_send(buf, len);
188   
189    //if (neighbor->is_mpr) {
190    //   len = sprintf( buf, "\"%s\"[shape=box];\n", adr );
191    //   ipc_send(buf, len);
192    //}
193 }
194
195 /**
196  *Do initialization here
197  *
198  *This function is called by the my_init
199  *function in uolsrd_plugin.c
200  */
201 int olsrd_plugin_init(void)
202 {
203
204   /* Initial IPC value */
205   ipc_socket = -1;
206
207   /* Register the "ProcessChanges" function */
208   register_pcf(&pcf_event);
209
210   return 1;
211 }
212
213 static int plugin_ipc_init(void)
214 {
215   struct sockaddr_in sin;
216   olsr_u32_t yes = 1;
217
218   /* Init ipc socket */
219   if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
220     {
221       olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
222       return 0;
223     }
224   else
225     {
226       if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
227       {
228         perror("SO_REUSEADDR failed");
229         return 0;
230       }
231
232 #ifdef __FreeBSD__
233       if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) 
234       {
235         perror("SO_NOSIGPIPE failed");
236         return 0;
237       }
238 #endif
239
240       /* Bind the socket */
241       
242       /* complete the socket structure */
243       memset(&sin, 0, sizeof(sin));
244       sin.sin_family = AF_INET;
245       sin.sin_addr.s_addr = INADDR_ANY;
246       sin.sin_port = htons(ipc_port);
247       
248       /* bind the socket to the port number */
249       if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
250         {
251           olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
252           return 0;
253         }
254       
255       /* show that we are willing to listen */
256       if (listen(ipc_socket, 1) == -1) 
257         {
258           olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
259           return 0;
260         }
261
262
263       /* Register with olsrd */
264       add_olsr_socket(ipc_socket, &ipc_action);
265     }
266
267   return 1;
268 }
269
270 static void ipc_action(int fd __attribute__((unused)))
271 {
272   struct sockaddr_in pin;
273   socklen_t addrlen;
274   char *addr;  
275   char buf[256] ;
276   int len ;
277    
278   addrlen = sizeof(struct sockaddr_in);
279
280   if ((ipc_connection = accept(ipc_socket, (struct sockaddr *)  &pin, &addrlen)) == -1)
281     {
282       olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
283       exit(1);
284     }
285   else
286     {
287       struct ipaddr_str main_addr;
288       addr = inet_ntoa(pin.sin_addr);
289 /*
290       if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
291         {
292           olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
293           close(ipc_connection);
294           return;
295         }
296       else
297         {
298 */
299           olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n",addr);
300           len = sprintf(buf, "add node %s\n", olsr_ip_to_string(&main_addr, &olsr_cnf->main_addr));
301           ipc_send(buf, len);
302           pcf_event(1, 1, 1);
303 //      }
304     }
305
306 }
307
308 /**
309  *Scheduled event
310  */
311 static int pcf_event(int changes_neighborhood,
312                      int changes_topology,
313                      int changes_hna __attribute__((unused)))
314 {
315   int res;
316   struct neighbor_entry *neighbor_table_tmp;
317   struct tc_entry *tc;
318   struct tc_edge_entry *tc_edge;
319
320   res = 0;
321
322   if (changes_neighborhood || changes_topology) {
323     /* Print tables to IPC socket */
324
325     //ipc_send("start ", strlen("start "));
326
327     /* Neighbors */
328     OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp) {
329       ipc_print_neigh_link( neighbor_table_tmp );
330     } OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor_table_tmp);
331
332     /* Topology */  
333     OLSR_FOR_ALL_TC_ENTRIES(tc) {
334       OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
335         ipc_print_tc_link(tc, tc_edge);
336       } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
337     } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
338
339     ipc_send(" end ", strlen(" end "));
340
341     /* HNA entries */
342 //      for(index=0;index<HASHSIZE;index++)
343 //      {
344 //        tmp_hna = hna_set[index].next;
345 //        /* Check all entrys */
346 //        while(tmp_hna != &hna_set[index])
347 //          {
348 //            /* Check all networks */
349 //            tmp_net = tmp_hna->networks.next;
350 //            
351 //            while(tmp_net != &tmp_hna->networks)
352 //              {
353 //                ipc_print_net(&tmp_hna->A_gateway_addr, 
354 //                              &tmp_net->A_network_addr, 
355 //                              &tmp_net->A_netmask);
356 //                tmp_net = tmp_net->next;
357 //              }
358 //            
359 //            tmp_hna = tmp_hna->next;
360 //          }
361 //      }
362
363 //      ipc_send("}\n\n", strlen("}\n\n"));
364
365     res = 1;
366   }
367
368   if (ipc_socket == -1) {
369     plugin_ipc_init();
370   }
371
372   return res;
373 }
374
375 static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry)
376 {
377   char buf[256];
378   int len;
379   struct ipaddr_str main_adr, adr;
380 //  double etx = olsr_calc_tc_etx(dst_entry);
381
382   len = sprintf( buf, "add link %s %s\n",
383                  olsr_ip_to_string(&main_adr, &entry->addr),
384                  olsr_ip_to_string(&adr, &dst_entry->T_dest_addr));
385   ipc_send(buf, len);
386 }
387
388 static int ipc_send(const char *data, int size)
389 {
390   if(ipc_connection == -1)
391     return 0;
392
393 #if defined __FreeBSD__ || defined __MacOSX__
394 #define FLAG 0
395 #else
396 #define FLAG MSG_NOSIGNAL
397 #endif
398   if (send(ipc_connection, data, size, FLAG) < 0) 
399     {
400       olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
401       close(ipc_connection);
402       ipc_connection = -1;
403       return -1;
404     }
405
406   return 1;
407 }
408
409 /*
410  * Local Variables:
411  * c-basic-offset: 2
412  * End:
413  */