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