Replaced TRUE/FALSE with OLSR_TRUE/OLSR_FALSE
[olsrd.git] / src / ipc_frontend.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org 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  * olsr.org 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 olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: ipc_frontend.c,v 1.11 2004/11/05 11:52:55 kattemat Exp $
23  *
24  */
25
26 /*
27  *Andreas T√łnnesen (andreto@ifi.uio.no)
28  *
29  *IPC - interprocess communication
30  *for the OLSRD - GUI front-end
31  *
32  */
33
34 #include "ipc_frontend.h"
35 #include "link_set.h"
36 #include "olsr.h"
37 #include "parser.h"
38 #include "local_hna_set.h"
39
40 #ifdef WIN32
41 #define close(x) closesocket(x)
42 #define perror(x) WinSockPError(x)
43 #define MSG_NOSIGNAL 0
44 void 
45 WinSockPError(char *);
46 #elif defined __FreeBSD__
47 #define MSG_NOSIGNAL 0
48 #endif
49
50 pthread_t accept_thread;
51
52 /**
53  *Create the socket to use for IPC to the
54  *GUI front-end
55  *
56  *@return the socket FD
57  */
58 int
59 ipc_init()
60 {
61   //int flags;
62   struct   sockaddr_in sin;
63
64   /* Add parser function */
65   olsr_parser_add_function(&frontend_msgparser, PROMISCUOUS, 0);
66
67   /* get an internet domain socket */
68   if ((ipc_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
69     {
70       perror("IPC socket");
71       olsr_exit("IPC socket", EXIT_FAILURE);
72     }
73
74   /* complete the socket structure */
75   memset(&sin, 0, sizeof(sin));
76   sin.sin_family = AF_INET;
77   sin.sin_addr.s_addr = INADDR_ANY;
78   sin.sin_port = htons(IPC_PORT);
79
80   /* bind the socket to the port number */
81   if (bind(ipc_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
82     {
83       perror("IPC bind");
84       olsr_exit("IPC bind", EXIT_FAILURE);
85     }
86
87   /* show that we are willing to listen */
88   if (listen(ipc_sock, 5) == -1) 
89     {
90       perror("IPC listen");
91       olsr_exit("IPC listen", EXIT_FAILURE);
92     }
93
94
95   /* Start the accept thread */
96
97   pthread_create(&accept_thread, NULL, (void *)&ipc_accept_thread, NULL);
98
99   return ipc_sock;
100 }
101
102
103 /*
104  * XXX - the socket should just be registered with the socket parser.
105  * Should NOT spawn this listen thread!
106  */
107 void
108 ipc_accept_thread()
109 {
110   int                addrlen;
111   struct sockaddr_in pin;
112   char *addr;  
113
114   while(olsr_cnf->open_ipc)
115     {
116       olsr_printf(2, "\nFront-end accept thread initiated(socket %d)\n\n", ipc_sock);
117
118       addrlen = sizeof (struct sockaddr_in);
119
120       if ((ipc_connection = accept(ipc_sock, (struct sockaddr *)  &pin, &addrlen)) == -1)
121         {
122           perror("IPC accept");
123           olsr_exit("IPC accept", EXIT_FAILURE);
124         }
125       else
126         {
127           olsr_printf(1, "Front end connected\n");
128           addr = inet_ntoa(pin.sin_addr);
129           if(ntohl(pin.sin_addr.s_addr) != INADDR_LOOPBACK)
130             {
131               olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
132               olsr_syslog(OLSR_LOG_ERR, "OLSR: Front end-connection from foregin host(%s) not allowed!\n", addr);
133               close(ipc_connection);
134             }
135           else
136             {
137               ipc_active = OLSR_TRUE;
138               ipc_send_net_info();
139               ipc_send_all_routes();
140               olsr_printf(1, "Connection from %s\n",addr);
141             }
142         }
143
144       sleep(2);
145     }
146 }
147
148
149
150 /**
151  *Read input from the IPC socket. Not in use.
152  *
153  *@todo for future use
154  *@param sock the IPC socket
155  *@return 1
156  */
157 int
158 ipc_input(int sock)
159 {
160   /*
161   union 
162   {
163     char        buf[MAXPACKETSIZE+1];
164     struct      olsr olsr;
165   } inbuf;
166
167
168   if (recv(sock, dir, sizeof(dir), 0) == -1) 
169     {
170       perror("recv");
171       exit(1);
172     }
173 */
174   return 1;
175 }
176
177
178 /**
179  *Sends a olsr packet on the IPC socket.
180  *
181  *@param olsr the olsr struct representing the packet
182  *
183  *@return negative on error
184  */
185 void
186 frontend_msgparser(union olsr_message *msg, struct interface *in_if, union olsr_ip_addr *from_addr)
187 {
188   int size;
189
190   if(!ipc_active)
191     return;
192   
193   if(olsr_cnf->ip_version == AF_INET)
194     size = ntohs(msg->v4.olsr_msgsize);
195   else
196     size = ntohs(msg->v6.olsr_msgsize);
197   
198   if (send(ipc_connection, (void *)msg, size, MSG_NOSIGNAL) < 0) 
199     {
200       olsr_printf(1, "(OUTPUT)IPC connection lost!\n");
201       close(ipc_connection);
202       //olsr_cnf->open_ipc = 0;
203       ipc_active = OLSR_FALSE;
204       return;
205     }
206   
207   return;
208 }
209
210
211 /**
212  *Send a route table update to the front-end.
213  *
214  *@param kernel_route a rtentry describing the route update
215  *@param add 1 if the route is to be added 0 if it is to be deleted
216  *@param int_name the name of the interface the route is set to go by
217  *
218  *@return negative on error
219  */
220 int
221 ipc_route_send_rtentry(union olsr_kernel_route *kernel_route, int add, char *int_name)
222 {
223   struct ipcmsg packet;
224   //int i, x;
225   char *tmp;
226
227   if(!ipc_active)
228     return 0;
229
230   packet.size = htons(IPC_PACK_SIZE);
231   packet.msgtype = ROUTE_IPC;
232
233   if(olsr_cnf->ip_version == AF_INET)
234     COPY_IP(&packet.target_addr, &((struct sockaddr_in *)&kernel_route->v4.rt_dst)->sin_addr.s_addr);
235   else
236     COPY_IP(&packet.target_addr, &kernel_route->v6.rtmsg_dst);
237
238   packet.add = add;
239   if(add)
240     {
241       if(olsr_cnf->ip_version == AF_INET)
242         {
243           packet.metric = kernel_route->v4.rt_metric - 1;
244           COPY_IP(&packet.gateway_addr, &((struct sockaddr_in *)&kernel_route->v4.rt_gateway)->sin_addr.s_addr);
245         }
246       else
247         {
248           packet.metric = kernel_route->v6.rtmsg_metric;
249           COPY_IP(&packet.gateway_addr, &kernel_route->v6.rtmsg_gateway);
250         }
251
252       if(int_name != NULL)
253         memcpy(&packet.device[0], int_name, 4);
254       else
255         memset(&packet.device[0], 0, 4);
256     }
257   else
258     {
259       memset(&packet.metric, 0, 1);
260       memset(&packet.gateway_addr, 0, 4);
261       memset(&packet.device[0], 0, 4);
262     }
263
264
265   tmp = (char *) &packet;
266   /*
267   x = 0;
268   for(i = 0; i < IPC_PACK_SIZE;i++)
269     {
270       if(x == 4)
271         {
272           x = 0;
273           printf("\n\t");
274         }
275       x++;
276       printf(" %03i", (u_char) tmp[i]);
277     }
278   
279   printf("\n");
280   */
281   
282   if (send(ipc_connection, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
283     {
284       olsr_printf(1, "(RT_ENTRY)IPC connection lost!\n");
285       close(ipc_connection);
286       //olsr_cnf->open_ipc = 0;
287       ipc_active = OLSR_FALSE;
288       return -1;
289     }
290
291   return 1;
292 }
293
294
295
296 int
297 ipc_send_all_routes()
298 {
299   struct rt_entry  *destination;
300   struct interface *ifn;
301   olsr_u8_t        index;
302   struct ipcmsg packet;
303   char *tmp;
304   
305
306   if(!ipc_active)
307     return 0;
308   
309   for(index=0;index<HASHSIZE;index++)
310     {
311       for(destination = routingtable[index].next;
312           destination != &routingtable[index];
313           destination = destination->next)
314         {
315           ifn = get_interface_link_set(&destination->rt_router);
316           
317
318           
319           packet.size = htons(IPC_PACK_SIZE);
320           packet.msgtype = ROUTE_IPC;
321           
322           COPY_IP(&packet.target_addr, &destination->rt_dst);
323           
324           packet.add = 1;
325
326           if(olsr_cnf->ip_version == AF_INET)
327             {
328               packet.metric = (olsr_u8_t)(destination->rt_metric - 1);
329             }
330           else
331             {
332               packet.metric = (olsr_u8_t)destination->rt_metric;
333             }
334           COPY_IP(&packet.gateway_addr, &destination->rt_router);
335
336           if(ifn)
337             memcpy(&packet.device[0], ifn->int_name, 4);
338           else
339             memset(&packet.device[0], 0, 4);
340
341
342           tmp = (char *) &packet;
343   
344           if (send(ipc_connection, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
345             {
346               olsr_printf(1, "(RT_ENTRY)IPC connection lost!\n");
347               close(ipc_connection);
348               //olsr_cnf->open_ipc = 0;
349               ipc_active = OLSR_FALSE;
350               return -1;
351             }
352
353         }
354     }
355
356   for(index=0;index<HASHSIZE;index++)
357     {
358       for(destination = hna_routes[index].next;
359           destination != &hna_routes[index];
360           destination = destination->next)
361         {
362           ifn = get_interface_link_set(&destination->rt_router);
363
364           packet.size = htons(IPC_PACK_SIZE);
365           packet.msgtype = ROUTE_IPC;
366           
367           COPY_IP(&packet.target_addr, &destination->rt_dst);
368           
369           packet.add = 1;
370
371           if(olsr_cnf->ip_version == AF_INET)
372             {
373               packet.metric = (olsr_u8_t)(destination->rt_metric - 1);
374             }
375           else
376             {
377               packet.metric = (olsr_u8_t)destination->rt_metric;
378             }
379           COPY_IP(&packet.gateway_addr, &destination->rt_router);
380
381           if(ifn)
382             memcpy(&packet.device[0], ifn->int_name, 4);
383           else
384             memset(&packet.device[0], 0, 4);
385
386
387           tmp = (char *) &packet;
388   
389           if (send(ipc_connection, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
390             {
391               olsr_printf(1, "(RT_ENTRY)IPC connection lost!\n");
392               close(ipc_connection);
393               //olsr_cnf->open_ipc = 0;
394               ipc_active = OLSR_FALSE;
395               return -1;
396             }
397
398         }
399     }
400
401
402   return 1;
403 }
404
405
406
407 /**
408  *Sends OLSR info to the front-end. This info consists of
409  *the different time intervals and holding times, number
410  *of interfaces, HNA routes and main address.
411  *
412  *@return negative on error
413  */
414 int
415 ipc_send_net_info()
416 {
417   struct ipc_net_msg *net_msg;
418   //int x, i;
419   char *msg;
420   
421
422   net_msg = olsr_malloc(sizeof(struct ipc_net_msg), "send net info");
423
424   msg = (char *)net_msg;
425
426   olsr_printf(1, "Sending net-info to front end...\n");
427   
428   memset(net_msg, 0, sizeof(struct ipc_net_msg));
429   
430   /* Message size */
431   net_msg->size = htons(sizeof(struct ipc_net_msg));
432   /* Message type */
433   net_msg->msgtype = NET_IPC;
434   
435   /* MIDs */
436 #warning fix IPC MIDcnt
437   net_msg->mids = (ifnet != NULL && ifnet->int_next != NULL) ? 1 : 0;
438   
439   /* HNAs */
440   if(olsr_cnf->ip_version == AF_INET6)
441     {
442       if(olsr_cnf->hna6_entries == NULL)
443         net_msg->hnas = 0;
444       else
445         net_msg->hnas = 1;
446     }
447
448   if(olsr_cnf->ip_version == AF_INET)
449     {
450       if(olsr_cnf->hna4_entries == NULL)
451         net_msg->hnas = 0;
452       else
453         net_msg->hnas = 1;
454     }
455
456   /* Different values */
457   /* Temporary fixes */
458 #warning fix IPC intervals
459   net_msg->hello_int = 0;//htons((olsr_u16_t)hello_int);
460   net_msg->hello_lan_int = 0;//htons((olsr_u16_t)hello_int_nw);
461   net_msg->tc_int = 0;//htons((olsr_u16_t)tc_int);
462   net_msg->neigh_hold = 0;//htons((olsr_u16_t)neighbor_hold_time);
463   net_msg->topology_hold = 0;//htons((olsr_u16_t)topology_hold_time);
464
465   if(olsr_cnf->ip_version == AF_INET)
466     net_msg->ipv6 = 0;
467   else
468     net_msg->ipv6 = 1;
469  
470   /* Main addr */
471   COPY_IP(&net_msg->main_addr, &main_addr);
472
473
474   /*
475   printf("\t");
476   x = 0;
477   for(i = 0; i < sizeof(struct ipc_net_msg);i++)
478     {
479       if(x == 4)
480         {
481           x = 0;
482           printf("\n\t");
483         }
484       x++;
485       printf(" %03i", (u_char) msg[i]);
486     }
487   
488   printf("\n");
489   */
490
491
492   if (send(ipc_connection, (char *)net_msg, sizeof(struct ipc_net_msg), MSG_NOSIGNAL) < 0) 
493     {
494       olsr_printf(1, "(NETINFO)IPC connection lost!\n");
495       close(ipc_connection);
496       olsr_cnf->open_ipc = 0;
497       return -1;
498     }
499
500   free(net_msg);
501   return 0;
502 }
503
504
505
506 int
507 shutdown_ipc()
508 {
509
510   pthread_kill(accept_thread, SIGTERM);
511   close(ipc_sock);
512   
513   if(ipc_active)
514     close(ipc_connection);
515   
516   return 1;
517 }