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