p2pd: show Git SHA and no version in plugin constructor
[olsrd.git] / lib / pgraph / src / olsrd_pgraph.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
5  *                     includes code by Bruno Randolf
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  * * Neither the name of olsr.org, olsrd nor the names of its
19  *   contributors may be used to endorse or promote products derived
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Visit http://www.olsr.org for more information.
36  *
37  * If you find this software useful feel free to make a donation
38  * to the project. For more information see the website or contact
39  * the copyright holders.
40  *
41  */
42
43 /*
44  * Dynamic linked library for the olsr.org olsr daemon
45  */
46
47 #include "olsrd_pgraph.h"
48 #include "ipcalc.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 #include <signal.h>
59 #ifdef _WIN32
60 #define close(x) closesocket(x)
61 #endif /* _WIN32 */
62
63 #define PLUGIN_NAME    "OLSRD pgraph plugin"
64 #define PLUGIN_VERSION "0.1"
65 #define PLUGIN_AUTHOR   "Richard Gopaul"
66 #define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION " by " PLUGIN_AUTHOR
67 #define PLUGIN_INTERFACE_VERSION 5
68
69 static union olsr_ip_addr ipc_accept_ip;
70 static int ipc_port;
71
72 static int ipc_socket;
73 static int ipc_connection;
74
75 void my_init(void) __attribute__ ((constructor));
76
77 void my_fini(void) __attribute__ ((destructor));
78
79 /*
80  * Defines the version of the plugin interface that is used
81  * THIS IS NOT THE VERSION OF YOUR PLUGIN!
82  * Do not alter unless you know what you are doing!
83  */
84 int
85 olsrd_plugin_interface_version(void)
86 {
87   return PLUGIN_INTERFACE_VERSION;
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
133 olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
134 {
135   *params = plugin_parameters;
136   *size = sizeof(plugin_parameters) / sizeof(*plugin_parameters);
137 }
138
139 /* Event function to register with the sceduler */
140 static int pcf_event(int, int, int);
141
142 static void ipc_action(int, void *, unsigned int);
143
144 static void ipc_print_neigh_link(struct neighbor_entry *neighbor);
145
146 static void ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry);
147
148 static int ipc_send(const char *, int);
149
150 static void ipc_print_neigh_link(struct neighbor_entry *);
151
152 static int plugin_ipc_init(void);
153
154 static void
155 ipc_print_neigh_link(struct neighbor_entry *neighbor)
156 {
157   char buf[256];
158   int len;
159   struct ipaddr_str main_adr, adr;
160 //  double etx=0.0;
161 //  char* style = "solid";
162 //  struct link_entry* link;
163
164   len =
165     sprintf(buf, "add link %s %s\n", 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
202 olsrd_plugin_init(void)
203 {
204
205   /* Initial IPC value */
206   ipc_socket = -1;
207
208   /* Register the "ProcessChanges" function */
209   register_pcf(&pcf_event);
210
211   return 1;
212 }
213
214 static int
215 plugin_ipc_init(void)
216 {
217   struct sockaddr_in sin;
218   uint32_t yes = 1;
219
220   /* Init ipc socket */
221   if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
222     olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
223     return 0;
224   } else {
225     if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
226       perror("SO_REUSEADDR failed");
227       return 0;
228     }
229 #if defined __FreeBSD__
230     if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) {
231       perror("SO_NOSIGPIPE failed");
232       return 0;
233     }
234 #endif /* defined __FreeBSD__ */
235
236     /* Bind the socket */
237
238     /* complete the socket structure */
239     memset(&sin, 0, sizeof(sin));
240     sin.sin_family = AF_INET;
241     sin.sin_addr.s_addr = INADDR_ANY;
242     sin.sin_port = htons(ipc_port);
243
244     /* bind the socket to the port number */
245     if (bind(ipc_socket, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
246       olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
247       return 0;
248     }
249
250     /* show that we are willing to listen */
251     if (listen(ipc_socket, 1) == -1) {
252       olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
253       return 0;
254     }
255
256     /* Register with olsrd */
257     add_olsr_socket(ipc_socket, &ipc_action, NULL, NULL, SP_PR_READ);
258   }
259
260   return 1;
261 }
262
263 static void
264 ipc_action(int fd __attribute__ ((unused)), void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
265 {
266   struct sockaddr_in pin;
267   socklen_t addrlen;
268   char *addr;
269   char buf[256];
270   int len;
271
272   addrlen = sizeof(struct sockaddr_in);
273
274   if ((ipc_connection = accept(ipc_socket, (struct sockaddr *)&pin, &addrlen)) == -1) {
275     char buf2[1024];
276     snprintf(buf2, sizeof(buf2), "(DOT DRAW)IPC accept error: %s", strerror(errno));
277     olsr_exit(buf2, EXIT_FAILURE);
278   } else {
279     struct ipaddr_str main_addr;
280     addr = inet_ntoa(pin.sin_addr);
281
282 /*
283       if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
284         {
285           olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
286           close(ipc_connection);
287           return;
288         }
289       else
290         {
291 */
292     olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n", addr);
293     len = sprintf(buf, "add node %s\n", olsr_ip_to_string(&main_addr, &olsr_cnf->main_addr));
294     ipc_send(buf, len);
295     pcf_event(1, 1, 1);
296 //      }
297   }
298
299 }
300
301 /**
302  *Scheduled event
303  */
304 static int
305 pcf_event(int my_changes_neighborhood, int my_changes_topology, int my_changes_hna __attribute__ ((unused)))
306 {
307   int res;
308   struct neighbor_entry *neighbor_table_tmp;
309   struct tc_entry *tc;
310   struct tc_edge_entry *tc_edge;
311
312   res = 0;
313
314   if (my_changes_neighborhood || my_changes_topology) {
315     /* Print tables to IPC socket */
316
317     //ipc_send("start ", strlen("start "));
318
319     /* Neighbors */
320     OLSR_FOR_ALL_NBR_ENTRIES(neighbor_table_tmp) {
321       ipc_print_neigh_link(neighbor_table_tmp);
322     }
323     OLSR_FOR_ALL_NBR_ENTRIES_END(neighbor_table_tmp);
324
325     /* Topology */
326     OLSR_FOR_ALL_TC_ENTRIES(tc) {
327       OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
328         ipc_print_tc_link(tc, tc_edge);
329       }
330       OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
331     }
332     OLSR_FOR_ALL_TC_ENTRIES_END(tc);
333
334     ipc_send(" end ", strlen(" end "));
335
336     /* HNA entries */
337 //      for(index=0;index<HASHSIZE;index++)
338 //      {
339 //        tmp_hna = hna_set[index].next;
340 //        /* Check all entrys */
341 //        while(tmp_hna != &hna_set[index])
342 //          {
343 //            /* Check all networks */
344 //            tmp_net = tmp_hna->networks.next;
345 //
346 //            while(tmp_net != &tmp_hna->networks)
347 //              {
348 //                ipc_print_net(&tmp_hna->A_gateway_addr,
349 //                              &tmp_net->A_network_addr,
350 //                              &tmp_net->A_netmask);
351 //                tmp_net = tmp_net->next;
352 //              }
353 //
354 //            tmp_hna = tmp_hna->next;
355 //          }
356 //      }
357
358 //      ipc_send("}\n\n", strlen("}\n\n"));
359
360     res = 1;
361   }
362
363   if (ipc_socket == -1) {
364     plugin_ipc_init();
365   }
366
367   return res;
368 }
369
370 static void
371 ipc_print_tc_link(struct tc_entry *entry, struct tc_edge_entry *dst_entry)
372 {
373   char buf[256];
374   int len;
375   struct ipaddr_str main_adr, adr;
376 //  double etx = olsr_calc_tc_etx(dst_entry);
377
378   len =
379     sprintf(buf, "add link %s %s\n", olsr_ip_to_string(&main_adr, &entry->addr), olsr_ip_to_string(&adr, &dst_entry->T_dest_addr));
380   ipc_send(buf, len);
381 }
382
383 static int
384 ipc_send(const char *data, int size)
385 {
386   if (ipc_connection == -1)
387     return 0;
388
389 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __OpenBSD__
390 #define FLAG 0
391 #else /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __OpenBSD__ */
392 #define FLAG MSG_NOSIGNAL
393 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __OpenBSD__ */
394   if (send(ipc_connection, data, size, FLAG) < 0) {
395     olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
396     close(ipc_connection);
397     ipc_connection = -1;
398     return -1;
399   }
400
401   return 1;
402 }
403
404 /*
405  * Local Variables:
406  * c-basic-offset: 2
407  * indent-tabs-mode: nil
408  * End:
409  */