Various headerfile inclusion cleanups
[olsrd.git] / src / ipc_frontend.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: ipc_frontend.c,v 1.26 2005/02/27 18:39:43 kattemat Exp $
40  */
41
42 /*
43  *
44  *IPC - interprocess communication
45  *for the OLSRD - GUI front-end
46  *
47  */
48
49 #include "ipc_frontend.h"
50 #include "link_set.h"
51 #include "olsr.h"
52 #include "log.h"
53 #include "parser.h"
54 #include "socket_parser.h"
55 #include "local_hna_set.h"
56
57 #ifdef WIN32
58 #define close(x) closesocket(x)
59 #define perror(x) WinSockPError(x)
60 void 
61 WinSockPError(char *);
62 #endif
63
64 #ifndef linux
65 #define MSG_NOSIGNAL 0
66 #endif
67
68 /**
69  *Create the socket to use for IPC to the
70  *GUI front-end
71  *
72  *@return the socket FD
73  */
74 int
75 ipc_init()
76 {
77   //int flags;
78   struct   sockaddr_in sin;
79   int yes = 1;
80
81   /* Add parser function */
82   olsr_parser_add_function(&frontend_msgparser, PROMISCUOUS, 0);
83
84   /* get an internet domain socket */
85   if ((ipc_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
86     {
87       perror("IPC socket");
88       olsr_exit("IPC socket", EXIT_FAILURE);
89     }
90
91   if(setsockopt(ipc_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) 
92     {
93       perror("SO_REUSEADDR failed");
94       return 0;
95     }
96
97   /* complete the socket structure */
98   memset(&sin, 0, sizeof(sin));
99   sin.sin_family = AF_INET;
100   sin.sin_addr.s_addr = INADDR_ANY;
101   sin.sin_port = htons(IPC_PORT);
102
103   /* bind the socket to the port number */
104   if(bind(ipc_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
105     {
106       perror("IPC bind");
107       OLSR_PRINTF(1, "Will retry in 10 seconds...\n")
108       sleep(10);
109       if(bind(ipc_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
110         {
111           perror("IPC bind");
112           olsr_exit("IPC bind", EXIT_FAILURE);
113         }
114       OLSR_PRINTF(1, "OK\n")
115     }
116
117   /* show that we are willing to listen */
118   if(listen(ipc_sock, olsr_cnf->ipc_connections) == -1) 
119     {
120       perror("IPC listen");
121       olsr_exit("IPC listen", EXIT_FAILURE);
122     }
123
124   /* Register the socket with the socket parser */
125   add_olsr_socket(ipc_sock, &ipc_accept);
126
127   return ipc_sock;
128 }
129
130
131 void
132 ipc_accept(int fd)
133 {
134   int                addrlen;
135   struct sockaddr_in pin;
136   char *addr;  
137
138
139   addrlen = sizeof (struct sockaddr_in);
140   
141   if ((ipc_connection = accept(ipc_sock, (struct sockaddr *)  &pin, &addrlen)) == -1)
142     {
143       perror("IPC accept");
144       olsr_exit("IPC accept", EXIT_FAILURE);
145     }
146   else
147     {
148       OLSR_PRINTF(1, "Front end connected\n")
149       addr = inet_ntoa(pin.sin_addr);
150       if(ipc_check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr))
151         {
152           ipc_active = OLSR_TRUE;
153           ipc_send_net_info();
154           ipc_send_all_routes();
155           OLSR_PRINTF(1, "Connection from %s\n",addr)
156         }
157       else
158         {
159           OLSR_PRINTF(1, "Front end-connection from foregin host(%s) not allowed!\n", addr)
160           olsr_syslog(OLSR_LOG_ERR, "OLSR: Front end-connection from foregin host(%s) not allowed!\n", addr);
161           close(ipc_connection);
162         }
163     }
164
165 }
166
167 olsr_bool
168 ipc_check_allowed_ip(union olsr_ip_addr *addr)
169 {
170   struct ipc_host *ipch = olsr_cnf->ipc_hosts;
171   struct ipc_net *ipcn = olsr_cnf->ipc_nets;
172
173   if(addr->v4 == ntohl(INADDR_LOOPBACK))
174     return OLSR_TRUE;
175
176   /* check hosts */
177   while(ipch)
178     {
179       if(addr->v4 == ipch->host.v4)
180         return OLSR_TRUE;
181       ipch = ipch->next;
182     }
183
184   /* check nets */
185   while(ipcn)
186     {
187       if((addr->v4 & ipcn->mask.v4) == (ipcn->net.v4 & ipcn->mask.v4))
188         return OLSR_TRUE;
189       ipcn = ipcn->next;
190     }
191
192   return OLSR_FALSE;
193 }
194
195 /**
196  *Read input from the IPC socket. Not in use.
197  *
198  *@todo for future use
199  *@param sock the IPC socket
200  *@return 1
201  */
202 int
203 ipc_input(int sock)
204 {
205   /*
206   union 
207   {
208     char        buf[MAXPACKETSIZE+1];
209     struct      olsr olsr;
210   } inbuf;
211
212
213   if (recv(sock, dir, sizeof(dir), 0) == -1) 
214     {
215       perror("recv");
216       exit(1);
217     }
218 */
219   return 1;
220 }
221
222
223 /**
224  *Sends a olsr packet on the IPC socket.
225  *
226  *@param olsr the olsr struct representing the packet
227  *
228  *@return negative on error
229  */
230 void
231 frontend_msgparser(union olsr_message *msg, struct interface *in_if, union olsr_ip_addr *from_addr)
232 {
233   int size;
234
235   if(!ipc_active)
236     return;
237   
238   if(olsr_cnf->ip_version == AF_INET)
239     size = ntohs(msg->v4.olsr_msgsize);
240   else
241     size = ntohs(msg->v6.olsr_msgsize);
242   
243   if (send(ipc_connection, (void *)msg, size, MSG_NOSIGNAL) < 0) 
244     {
245       OLSR_PRINTF(1, "(OUTPUT)IPC connection lost!\n")
246       close(ipc_connection);
247       //olsr_cnf->open_ipc = 0;
248       ipc_active = OLSR_FALSE;
249       return;
250     }
251   
252   return;
253 }
254
255
256 /**
257  *Send a route table update to the front-end.
258  *
259  *@param kernel_route a rtentry describing the route update
260  *@param add 1 if the route is to be added 0 if it is to be deleted
261  *@param int_name the name of the interface the route is set to go by
262  *
263  *@return negative on error
264  */
265 int
266 ipc_route_send_rtentry(union olsr_ip_addr *dst, union olsr_ip_addr *gw, int met, int add, char *int_name)
267 {
268   struct ipcmsg packet;
269   //int i, x;
270   char *tmp;
271
272   if(!ipc_active)
273     return 0;
274
275   memset(&packet, 0, sizeof(struct ipcmsg));
276   packet.size = htons(IPC_PACK_SIZE);
277   packet.msgtype = ROUTE_IPC;
278
279   COPY_IP(&packet.target_addr, dst);
280
281   packet.add = add;
282   if(add && gw)
283     {
284       packet.metric = met;
285       COPY_IP(&packet.gateway_addr, gw);
286     }
287
288   if(int_name != NULL)
289     memcpy(&packet.device[0], int_name, 4);
290   else
291     memset(&packet.device[0], 0, 4);
292
293
294   tmp = (char *) &packet;
295   /*
296   x = 0;
297   for(i = 0; i < IPC_PACK_SIZE;i++)
298     {
299       if(x == 4)
300         {
301           x = 0;
302           printf("\n\t");
303         }
304       x++;
305       printf(" %03i", (u_char) tmp[i]);
306     }
307   
308   printf("\n");
309   */
310   
311   if (send(ipc_connection, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
312     {
313       OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n")
314       close(ipc_connection);
315       //olsr_cnf->open_ipc = 0;
316       ipc_active = OLSR_FALSE;
317       return -1;
318     }
319
320   return 1;
321 }
322
323
324
325 int
326 ipc_send_all_routes()
327 {
328   struct rt_entry  *destination;
329   struct interface *ifn;
330   olsr_u8_t        index;
331   struct ipcmsg packet;
332   char *tmp;
333   
334
335   if(!ipc_active)
336     return 0;
337   
338   for(index=0;index<HASHSIZE;index++)
339     {
340       for(destination = routingtable[index].next;
341           destination != &routingtable[index];
342           destination = destination->next)
343         {
344           ifn = destination->rt_if;
345           
346
347           memset(&packet, 0, sizeof(struct ipcmsg));
348           packet.size = htons(IPC_PACK_SIZE);
349           packet.msgtype = ROUTE_IPC;
350           
351           COPY_IP(&packet.target_addr, &destination->rt_dst);
352           
353           packet.add = 1;
354
355           if(olsr_cnf->ip_version == AF_INET)
356             {
357               packet.metric = (olsr_u8_t)(destination->rt_metric - 1);
358             }
359           else
360             {
361               packet.metric = (olsr_u8_t)destination->rt_metric;
362             }
363           COPY_IP(&packet.gateway_addr, &destination->rt_router);
364
365           if(ifn)
366             memcpy(&packet.device[0], ifn->int_name, 4);
367           else
368             memset(&packet.device[0], 0, 4);
369
370
371           tmp = (char *) &packet;
372   
373           if (send(ipc_connection, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
374             {
375               OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n")
376               close(ipc_connection);
377               //olsr_cnf->open_ipc = 0;
378               ipc_active = OLSR_FALSE;
379               return -1;
380             }
381
382         }
383     }
384
385   for(index=0;index<HASHSIZE;index++)
386     {
387       for(destination = hna_routes[index].next;
388           destination != &hna_routes[index];
389           destination = destination->next)
390         {
391           ifn = destination->rt_if;
392
393           packet.size = htons(IPC_PACK_SIZE);
394           packet.msgtype = ROUTE_IPC;
395           
396           COPY_IP(&packet.target_addr, &destination->rt_dst);
397           
398           packet.add = 1;
399
400           if(olsr_cnf->ip_version == AF_INET)
401             {
402               packet.metric = (olsr_u8_t)(destination->rt_metric - 1);
403             }
404           else
405             {
406               packet.metric = (olsr_u8_t)destination->rt_metric;
407             }
408           COPY_IP(&packet.gateway_addr, &destination->rt_router);
409
410           if(ifn)
411             memcpy(&packet.device[0], ifn->int_name, 4);
412           else
413             memset(&packet.device[0], 0, 4);
414
415
416           tmp = (char *) &packet;
417   
418           if (send(ipc_connection, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) // MSG_NOSIGNAL to avoid sigpipe
419             {
420               OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n")
421               close(ipc_connection);
422               //olsr_cnf->open_ipc = 0;
423               ipc_active = OLSR_FALSE;
424               return -1;
425             }
426
427         }
428     }
429
430
431   return 1;
432 }
433
434
435
436 /**
437  *Sends OLSR info to the front-end. This info consists of
438  *the different time intervals and holding times, number
439  *of interfaces, HNA routes and main address.
440  *
441  *@return negative on error
442  */
443 int
444 ipc_send_net_info()
445 {
446   struct ipc_net_msg *net_msg;
447   //int x, i;
448   char *msg;
449   
450
451   net_msg = olsr_malloc(sizeof(struct ipc_net_msg), "send net info");
452
453   msg = (char *)net_msg;
454
455   OLSR_PRINTF(1, "Sending net-info to front end...\n")
456   
457   memset(net_msg, 0, sizeof(struct ipc_net_msg));
458   
459   /* Message size */
460   net_msg->size = htons(sizeof(struct ipc_net_msg));
461   /* Message type */
462   net_msg->msgtype = NET_IPC;
463   
464   /* MIDs */
465   /* XXX fix IPC MIDcnt */
466   net_msg->mids = (ifnet != NULL && ifnet->int_next != NULL) ? 1 : 0;
467   
468   /* HNAs */
469   if(olsr_cnf->ip_version == AF_INET6)
470     {
471       if(olsr_cnf->hna6_entries == NULL)
472         net_msg->hnas = 0;
473       else
474         net_msg->hnas = 1;
475     }
476
477   if(olsr_cnf->ip_version == AF_INET)
478     {
479       if(olsr_cnf->hna4_entries == NULL)
480         net_msg->hnas = 0;
481       else
482         net_msg->hnas = 1;
483     }
484
485   /* Different values */
486   /* Temporary fixes */
487   /* XXX fix IPC intervals */
488   net_msg->hello_int = 0;//htons((olsr_u16_t)hello_int);
489   net_msg->hello_lan_int = 0;//htons((olsr_u16_t)hello_int_nw);
490   net_msg->tc_int = 0;//htons((olsr_u16_t)tc_int);
491   net_msg->neigh_hold = 0;//htons((olsr_u16_t)neighbor_hold_time);
492   net_msg->topology_hold = 0;//htons((olsr_u16_t)topology_hold_time);
493
494   if(olsr_cnf->ip_version == AF_INET)
495     net_msg->ipv6 = 0;
496   else
497     net_msg->ipv6 = 1;
498  
499   /* Main addr */
500   COPY_IP(&net_msg->main_addr, &main_addr);
501
502
503   /*
504   printf("\t");
505   x = 0;
506   for(i = 0; i < sizeof(struct ipc_net_msg);i++)
507     {
508       if(x == 4)
509         {
510           x = 0;
511           printf("\n\t");
512         }
513       x++;
514       printf(" %03i", (u_char) msg[i]);
515     }
516   
517   printf("\n");
518   */
519
520
521   if (send(ipc_connection, (char *)net_msg, sizeof(struct ipc_net_msg), MSG_NOSIGNAL) < 0) 
522     {
523       OLSR_PRINTF(1, "(NETINFO)IPC connection lost!\n")
524       close(ipc_connection);
525       //olsr_cnf->open_ipc = 0;
526       return -1;
527     }
528
529   free(net_msg);
530   return 0;
531 }
532
533
534
535 int
536 shutdown_ipc()
537 {
538   OLSR_PRINTF(1, "Shutting down IPC...\n")
539   close(ipc_sock);
540   close(ipc_connection);
541   
542   return 1;
543 }