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