Added CVS Id to all C and haeder files
[olsrd.git] / lib / dot_draw / src / olsrd_dot_draw.c
1 /*
2  * OLSR plugin
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@olsr.org)
4  *
5  * This file is part of the olsrd dynamic gateway detection.
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This plugin is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsrd-unik; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: olsrd_dot_draw.c,v 1.5 2004/09/21 19:08:57 kattemat Exp $
23  *
24  */
25
26 /*
27  * Dynamic linked library for UniK OLSRd
28  */
29
30 #include "olsrd_dot_draw.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #ifdef WIN32
37 #define close(x) closesocket(x)
38 #endif
39
40 int ipc_socket;
41 int ipc_open;
42 int ipc_connection;
43 int ipc_socket_up;
44
45 /**
46  *Do initialization here
47  *
48  *This function is called by the my_init
49  *function in uolsrd_plugin.c
50  */
51 int
52 olsr_plugin_init()
53 {
54
55   /* Initial IPC value */
56   ipc_open = 0;
57   ipc_socket_up = 0;
58
59   /* Register the "ProcessChanges" function */
60   register_pcf(&pcf_event);
61
62   return 1;
63 }
64
65 int
66 plugin_ipc_init()
67 {
68   struct sockaddr_in sin;
69   olsr_u32_t yes = 1;
70
71   /* Init ipc socket */
72   if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
73     {
74       olsr_printf(1, "(DOT DRAW)IPC socket %s\n", strerror(errno));
75       return 0;
76     }
77   else
78     {
79       if (setsockopt(ipc_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
80       {
81         perror("SO_REUSEADDR failed");
82         return 0;
83       }
84
85       /* Bind the socket */
86       
87       /* complete the socket structure */
88       memset(&sin, 0, sizeof(sin));
89       sin.sin_family = AF_INET;
90       sin.sin_addr.s_addr = INADDR_ANY;
91       sin.sin_port = htons(2004);
92       
93       /* bind the socket to the port number */
94       if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
95         {
96           olsr_printf(1, "(DOT DRAW)IPC bind %s\n", strerror(errno));
97           return 0;
98         }
99       
100       /* show that we are willing to listen */
101       if (listen(ipc_socket, 1) == -1) 
102         {
103           olsr_printf(1, "(DOT DRAW)IPC listen %s\n", strerror(errno));
104           return 0;
105         }
106
107
108       /* Register with olsrd */
109       add_olsr_socket(ipc_socket, &ipc_action);
110       ipc_socket_up = 1;
111     }
112
113   return 1;
114 }
115
116 void
117 ipc_action(int fd)
118 {
119   struct sockaddr_in pin;
120   socklen_t addrlen;
121   char *addr;  
122
123   addrlen = sizeof(struct sockaddr_in);
124
125   if ((ipc_connection = accept(ipc_socket, (struct sockaddr *)  &pin, &addrlen)) == -1)
126     {
127       olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
128       exit(1);
129     }
130   else
131     {
132       addr = inet_ntoa(pin.sin_addr);
133       if(ntohl(pin.sin_addr.s_addr) != INADDR_LOOPBACK)
134         {
135           olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
136           close(ipc_connection);
137           return;
138         }
139       else
140         {
141           ipc_open = 1;
142           olsr_printf(1, "(DOT DRAW)IPC: Connection from %s\n",addr);
143         }
144     }
145
146 }
147
148 /*
149  * destructor - called at unload
150  */
151 void
152 olsr_plugin_exit()
153 {
154   if(ipc_open)
155     close(ipc_socket);
156 }
157
158
159
160 /* Mulitpurpose funtion */
161 int
162 plugin_io(int cmd, void *data, size_t size)
163 {
164
165   switch(cmd)
166     {
167     default:
168       return 0;
169     }
170   
171   return 1;
172 }
173
174
175
176
177 /**
178  *Scheduled event
179  */
180 int
181 pcf_event(int changes_neighborhood,
182           int changes_topology,
183           int changes_hna)
184 {
185   int res;
186   olsr_u8_t index;
187   struct neighbor_entry *neighbor_table_tmp;
188   struct neighbor_2_list_entry *list_2;
189   struct tc_entry *entry;
190   struct topo_dst *dst_entry;
191   struct hna_entry *tmp_hna;
192   struct hna_net *tmp_net;
193
194   res = 0;
195
196   if(changes_neighborhood || changes_topology || changes_hna)
197     {
198       /* Print tables to IPC socket */
199
200       ipc_send("digraph topology\n{\n", strlen("digraph topology\n{\n"));
201
202       /* Neighbors */
203       for(index=0;index<HASHSIZE;index++)
204         {
205           
206           for(neighbor_table_tmp = neighbortable[index].next;
207               neighbor_table_tmp != &neighbortable[index];
208               neighbor_table_tmp = neighbor_table_tmp->next)
209             {
210               if(neighbor_table_tmp->is_mpr)
211                 {
212                   ipc_print_mpr_link(main_addr, &neighbor_table_tmp->neighbor_main_addr);                 
213                   ipc_print_mpr_link(&neighbor_table_tmp->neighbor_main_addr, main_addr);
214                 }
215               else
216                 {
217                   ipc_print_neigh_link(main_addr, &neighbor_table_tmp->neighbor_main_addr);               
218                   ipc_print_neigh_link(&neighbor_table_tmp->neighbor_main_addr, main_addr);
219                 }
220
221               for(list_2 = neighbor_table_tmp->neighbor_2_list.next;
222                   list_2 != &neighbor_table_tmp->neighbor_2_list;
223                   list_2 = list_2->next)
224                 {
225                   ipc_print_2h_link(&neighbor_table_tmp->neighbor_main_addr, 
226                                     &list_2->neighbor_2->neighbor_2_addr);
227                 }
228               
229             }
230         }
231
232       /* Topology */  
233       for(index=0;index<HASHSIZE;index++)
234         {
235           /* For all TC entries */
236           entry = tc_table[index].next;
237           while(entry != &tc_table[index])
238             {
239               /* For all destination entries of that TC entry */
240               dst_entry = entry->destinations.next;
241               while(dst_entry != &entry->destinations)
242                 {
243                   ipc_print_tc_link(&entry->T_last_addr, &dst_entry->T_dest_addr);
244                   dst_entry = dst_entry->next;
245                 }
246               entry = entry->next;
247             }
248           
249         }
250
251       /* HNA entries */
252       for(index=0;index<HASHSIZE;index++)
253         {
254           tmp_hna = hna_set[index].next;
255           /* Check all entrys */
256           while(tmp_hna != &hna_set[index])
257             {
258               /* Check all networks */
259               tmp_net = tmp_hna->networks.next;
260               
261               while(tmp_net != &tmp_hna->networks)
262                 {
263                   ipc_print_net(&tmp_hna->A_gateway_addr, 
264                                 &tmp_net->A_network_addr, 
265                                 &tmp_net->A_netmask);
266                   tmp_net = tmp_net->next;
267                 }
268               
269               tmp_hna = tmp_hna->next;
270             }
271         }
272
273
274       ipc_send("}\n\n", strlen("}\n\n"));
275
276       res = 1;
277     }
278
279
280   if(!ipc_socket_up)
281     plugin_ipc_init();
282
283   return res;
284 }
285
286
287
288
289 static void inline
290 ipc_print_neigh_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
291 {
292   char *adr;
293
294   adr = olsr_ip_to_string(from);
295   ipc_send("\"", 1);
296   ipc_send(adr, strlen(adr));
297   ipc_send("\" -> \"", strlen("\" -> \""));
298   adr = olsr_ip_to_string(to);
299   ipc_send(adr, strlen(adr));
300   ipc_send("\"[label=\"neigh\", style=dashed];\n", strlen("\"[label=\"neigh\", style=dashed];\n"));
301
302 }
303
304 static void inline
305 ipc_print_2h_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
306 {
307   char *adr;
308
309   adr = olsr_ip_to_string(from);
310   ipc_send("\"", 1);
311   ipc_send(adr, strlen(adr));
312   ipc_send("\" -> \"", strlen("\" -> \""));
313   adr = olsr_ip_to_string(to);
314   ipc_send(adr, strlen(adr));
315   ipc_send("\"[label=\"2 hop\"];\n", strlen("\"[label=\"2 hop\"];\n"));
316
317 }
318
319 static void inline
320 ipc_print_mpr_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
321 {
322   char *adr;
323
324   adr = olsr_ip_to_string(from);
325   ipc_send("\"", 1);
326   ipc_send(adr, strlen(adr));
327   ipc_send("\" -> \"", strlen("\" -> \""));
328   adr = olsr_ip_to_string(to);
329   ipc_send(adr, strlen(adr));
330   ipc_send("\"[label=\"MPR\", style=dashed];\n", strlen("\"[label=\"MPR\", style=dashed]];\n"));
331
332 }
333
334 static void inline
335 ipc_print_tc_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
336 {
337   char *adr;
338
339   adr = olsr_ip_to_string(from);
340   ipc_send("\"", 1);
341   ipc_send(adr, strlen(adr));
342   ipc_send("\" -> \"", strlen("\" -> \""));
343   adr = olsr_ip_to_string(to);
344   ipc_send(adr, strlen(adr));
345   ipc_send("\"[label=\"TC\"];\n", strlen("\"[label=\"TC\"];\n"));
346
347 }
348
349 static void inline
350 ipc_print_net(union olsr_ip_addr *gw, union olsr_ip_addr *net, union hna_netmask *mask)
351 {
352   char *adr;
353
354   adr = olsr_ip_to_string(gw);
355   ipc_send("\"", 1);
356   ipc_send(adr, strlen(adr));
357   ipc_send("\" -> \"", strlen("\" -> \""));
358   adr = olsr_ip_to_string(net);
359   ipc_send(adr, strlen(adr));
360   ipc_send("/", 1);
361   adr = olsr_netmask_to_string(mask);
362   ipc_send(adr, strlen(adr));
363   ipc_send("\"[label=\"HNA\"];\n", strlen("\"[label=\"HNA\"];\n"));
364   ipc_send("\"", 1);
365   adr = olsr_ip_to_string(net);
366   ipc_send(adr, strlen(adr));
367   ipc_send("/", 1);
368   adr = olsr_netmask_to_string(mask);
369   ipc_send(adr, strlen(adr));
370   ipc_send("\"", 1);
371   ipc_send("[shape=diamond];\n", strlen("[shape=diamond];\n"));
372 }
373
374
375
376 int
377 ipc_send(char *data, int size)
378 {
379   if(!ipc_open)
380     return 0;
381
382   if (send(ipc_connection, data, size, MSG_NOSIGNAL) < 0) 
383     {
384       olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
385       close(ipc_connection);
386       ipc_open = 0;
387       return -1;
388     }
389
390   return 1;
391 }
392
393
394
395
396
397 /**
398  *Converts a olsr_ip_addr to a string
399  *Goes for both IPv4 and IPv6
400  *
401  *NON REENTRANT! If you need to use this
402  *function twice in e.g. the same printf
403  *it will not work.
404  *You must use it in different calls e.g.
405  *two different printfs
406  *
407  *@param the IP to convert
408  *@return a pointer to a static string buffer
409  *representing the address in "dots and numbers"
410  *
411  */
412 char *
413 olsr_ip_to_string(union olsr_ip_addr *addr)
414 {
415
416   char *ret;
417   struct in_addr in;
418   
419   if(ipversion == AF_INET)
420     {
421       in.s_addr=addr->v4;
422       ret = inet_ntoa(in);
423     }
424   else
425     {
426       /* IPv6 */
427       ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
428     }
429
430   return ret;
431 }
432
433
434
435
436 /**
437  *This function is just as bad as the previous one :-(
438  */
439 char *
440 olsr_netmask_to_string(union hna_netmask *mask)
441 {
442   char *ret;
443   struct in_addr in;
444   
445   if(ipversion == AF_INET)
446     {
447       in.s_addr = mask->v4;
448       ret = inet_ntoa(in);
449       return ret;
450
451     }
452   else
453     {
454       /* IPv6 */
455       sprintf(netmask, "%d", mask->v6);
456       return netmask;
457     }
458
459   return ret;
460 }
461
462