ip_frontend: remove unused variable
[olsrd.git] / src / ipc_frontend.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
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 "scheduler.h"
55 #include "net_olsr.h"
56 #include "ipcalc.h"
57
58 #ifdef WIN32
59 #define close(x) closesocket(x)
60 #define perror(x) WinSockPError(x)
61 void WinSockPError(const char *);
62 #endif
63
64 #ifndef MSG_NOSIGNAL
65 #define MSG_NOSIGNAL 0
66 #endif
67
68 static int ipc_sock = -1;
69 static int ipc_conn = -1;
70 static int ipc_active = false;
71
72 static int ipc_send_all_routes(int fd);
73
74 static int ipc_send_net_info(int fd);
75
76 /**
77  *Create the socket to use for IPC to the
78  *GUI front-end
79  *
80  *@return the socket FD
81  */
82 int
83 ipc_init(void)
84 {
85   //int flags;
86   struct sockaddr_in sin;
87   int yes = 1;
88
89   /* Add parser function */
90   olsr_parser_add_function(&frontend_msgparser, PROMISCUOUS);
91
92   /* get an internet domain socket */
93   if ((ipc_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
94     perror("IPC socket");
95     olsr_exit("IPC socket", EXIT_FAILURE);
96   }
97
98   if (setsockopt(ipc_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
99     perror("SO_REUSEADDR failed");
100     return 0;
101   }
102
103   /* complete the socket structure */
104   memset(&sin, 0, sizeof(sin));
105   sin.sin_family = AF_INET;
106   sin.sin_addr.s_addr = INADDR_ANY;
107   sin.sin_port = htons(IPC_PORT);
108
109   /* bind the socket to the port number */
110   if (bind(ipc_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
111     perror("IPC bind");
112     OLSR_PRINTF(1, "Will retry in 10 seconds...\n");
113     sleep(10);
114     if (bind(ipc_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
115       perror("IPC bind");
116       olsr_exit("IPC bind", EXIT_FAILURE);
117     }
118     OLSR_PRINTF(1, "OK\n");
119   }
120
121   /* show that we are willing to listen */
122   if (listen(ipc_sock, olsr_cnf->ipc_connections) == -1) {
123     perror("IPC listen");
124     olsr_exit("IPC listen", EXIT_FAILURE);
125   }
126
127   /* Register the socket with the socket parser */
128   add_olsr_socket(ipc_sock, &ipc_accept, NULL, NULL, SP_PR_READ);
129
130   return ipc_sock;
131 }
132
133
134 void
135 ipc_accept(int fd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
136 {
137   socklen_t addrlen;
138   struct sockaddr_in pin;
139   char *addr;
140
141   addrlen = sizeof(struct sockaddr_in);
142
143   if ((ipc_conn = accept(fd, (struct sockaddr *)&pin, &addrlen)) == -1) {
144     perror("IPC accept");
145     olsr_exit("IPC accept", EXIT_FAILURE);
146   } else {
147     OLSR_PRINTF(1, "Front end connected\n");
148     addr = inet_ntoa(pin.sin_addr);
149     if (ipc_check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr)) {
150       ipc_active = true;
151       ipc_send_net_info(ipc_conn);
152       ipc_send_all_routes(ipc_conn);
153       OLSR_PRINTF(1, "Connection from %s\n", addr);
154     } else {
155       OLSR_PRINTF(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
156       olsr_syslog(OLSR_LOG_ERR, "OLSR: Front end-connection from foregin host(%s) not allowed!\n", addr);
157       CLOSE(ipc_conn);
158     }
159   }
160
161 }
162
163 bool
164 ipc_check_allowed_ip(const union olsr_ip_addr *addr)
165 {
166   struct ip_prefix_list *ipcn;
167
168   if (addr->v4.s_addr == ntohl(INADDR_LOOPBACK)) {
169     return true;
170   }
171
172   /* check nets */
173   for (ipcn = olsr_cnf->ipc_nets; ipcn != NULL; ipcn = ipcn->next) {
174     if (ip_in_net(addr, &ipcn->net)) {
175       return true;
176     }
177   }
178
179   return false;
180 }
181
182 #if 0
183
184 /**
185  *Read input from the IPC socket. Not in use.
186  *
187  *@todo for future use
188  *@param sock the IPC socket
189  *@return 1
190  */
191 int
192 ipc_input(int sock __attribute__ ((unused)))
193 {
194   union {
195     char buf[MAXPACKETSIZE + 1];
196     struct olsr olsr;
197   } inbuf;
198
199   if (recv(sock, dir, sizeof(dir), 0) == -1) {
200     perror("recv");
201     exit(1);
202   }
203   return 1;
204 }
205 #endif
206
207 /**
208  *Sends a olsr packet on the IPC socket.
209  *
210  *@param olsr the olsr struct representing the packet
211  *
212  *@return true for not preventing forwarding
213  */
214 bool
215 frontend_msgparser(union olsr_message * msg, struct interface * in_if __attribute__ ((unused)), union olsr_ip_addr * from_addr
216                    __attribute__ ((unused)))
217 {
218   int size;
219
220   if (!ipc_active)
221     return true;
222
223   if (olsr_cnf->ip_version == AF_INET)
224     size = ntohs(msg->v4.olsr_msgsize);
225   else
226     size = ntohs(msg->v6.olsr_msgsize);
227
228   if (send(ipc_conn, (void *)msg, size, MSG_NOSIGNAL) < 0) {
229     OLSR_PRINTF(1, "(OUTPUT)IPC connection lost!\n");
230     CLOSE(ipc_conn);
231     ipc_active = false;
232   }
233   return true;
234 }
235
236 /**
237  *Send a route table update to the front-end.
238  *
239  *@param kernel_route a rtentry describing the route update
240  *@param add 1 if the route is to be added 0 if it is to be deleted
241  *@param int_name the name of the interface the route is set to go by
242  *
243  *@return negative on error
244  */
245 int
246 ipc_route_send_rtentry(const union olsr_ip_addr *dst, const union olsr_ip_addr *gw, int met, int add, const char *int_name)
247 {
248   struct ipcmsg packet;
249   char *tmp;
250
251   if (olsr_cnf->ipc_connections <= 0) {
252     return -1;
253   }
254
255   if (!ipc_active) {
256     return 0;
257   }
258   memset(&packet, 0, sizeof(struct ipcmsg));
259   packet.size = htons(IPC_PACK_SIZE);
260   packet.msgtype = ROUTE_IPC;
261
262   packet.target_addr = *dst;
263
264   packet.add = add;
265   if (add && gw) {
266     packet.metric = met;
267     packet.gateway_addr = *gw;
268   }
269
270   if (int_name != NULL)
271     memcpy(&packet.device[0], int_name, 4);
272   else
273     memset(&packet.device[0], 0, 4);
274
275   tmp = (char *)&packet;
276   /*
277      x = 0;
278      for(i = 0; i < IPC_PACK_SIZE;i++)
279      {
280      if(x == 4)
281      {
282      x = 0;
283      printf("\n\t");
284      }
285      x++;
286      printf(" %03i", (u_char) tmp[i]);
287      }
288
289      printf("\n");
290    */
291
292   if (send(ipc_conn, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0)     // MSG_NOSIGNAL to avoid sigpipe
293   {
294     OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n");
295     CLOSE(ipc_conn);
296
297     ipc_active = false;
298     return -1;
299   }
300
301   return 1;
302 }
303
304 static int
305 ipc_send_all_routes(int fd)
306 {
307   struct rt_entry *rt;
308   struct ipcmsg packet;
309   char *tmp;
310
311   if (!ipc_active)
312     return 0;
313
314   OLSR_FOR_ALL_RT_ENTRIES(rt) {
315
316     memset(&packet, 0, sizeof(struct ipcmsg));
317     packet.size = htons(IPC_PACK_SIZE);
318     packet.msgtype = ROUTE_IPC;
319
320     packet.target_addr = rt->rt_dst.prefix;
321
322     packet.add = 1;
323     packet.metric = (uint8_t) (rt->rt_best->rtp_metric.hops);
324
325     packet.gateway_addr = rt->rt_nexthop.gateway;
326
327     memcpy(&packet.device[0], if_ifwithindex_name(rt->rt_nexthop.iif_index), 4);
328
329     tmp = (char *)&packet;
330
331     /* MSG_NOSIGNAL to avoid sigpipe */
332     if (send(fd, tmp, IPC_PACK_SIZE, MSG_NOSIGNAL) < 0) {
333       OLSR_PRINTF(1, "(RT_ENTRY)IPC connection lost!\n");
334       CLOSE(ipc_conn);
335       ipc_active = false;
336       return -1;
337     }
338   }
339   OLSR_FOR_ALL_RT_ENTRIES_END(rt);
340   return 1;
341 }
342
343 /**
344  *Sends OLSR info to the front-end. This info consists of
345  *the different time intervals and holding times, number
346  *of interfaces, HNA routes and main address.
347  *
348  *@return negative on error
349  */
350 static int
351 ipc_send_net_info(int fd)
352 {
353   struct ipc_net_msg *net_msg;
354
355   net_msg = olsr_malloc(sizeof(struct ipc_net_msg), "send net info");
356
357   OLSR_PRINTF(1, "Sending net-info to front end...\n");
358
359   memset(net_msg, 0, sizeof(struct ipc_net_msg));
360
361   /* Message size */
362   net_msg->size = htons(sizeof(struct ipc_net_msg));
363   /* Message type */
364   net_msg->msgtype = NET_IPC;
365
366   /* MIDs */
367   /* XXX fix IPC MIDcnt */
368   net_msg->mids = (ifnet != NULL && ifnet->int_next != NULL) ? 1 : 0;
369
370   /* HNAs */
371   net_msg->hnas = olsr_cnf->hna_entries == NULL ? 0 : 1;
372
373   /* Different values */
374   /* Temporary fixes */
375   /* XXX fix IPC intervals */
376   net_msg->hello_int = 0;       //htons((uint16_t)hello_int);
377   net_msg->hello_lan_int = 0;   //htons((uint16_t)hello_int_nw);
378   net_msg->tc_int = 0;          //htons((uint16_t)tc_int);
379   net_msg->neigh_hold = 0;      //htons((uint16_t)neighbor_hold_time);
380   net_msg->topology_hold = 0;   //htons((uint16_t)topology_hold_time);
381
382   net_msg->ipv6 = olsr_cnf->ip_version == AF_INET ? 0 : 1;
383
384   /* Main addr */
385   net_msg->main_addr = olsr_cnf->main_addr;
386
387   /*
388   {
389      unsigned int x, i;
390
391      printf("\t");
392      for(i = 0; i < sizeof(struct ipc_net_msg);i++)
393      {
394      if(x == 4)
395      {
396      x = 0;
397      printf("\n\t");
398      }
399      x++;
400      printf(" %03i", ((u_char *)net_msg)[i]);
401      }
402
403      printf("\n");
404   }
405   */
406
407   if (send(fd, (char *)net_msg, sizeof(struct ipc_net_msg), MSG_NOSIGNAL) < 0) {
408     OLSR_PRINTF(1, "(NETINFO)IPC connection lost!\n");
409     CLOSE(ipc_conn);
410     return -1;
411   }
412
413   free(net_msg);
414   return 0;
415 }
416
417 int
418 shutdown_ipc(void)
419 {
420   OLSR_PRINTF(1, "Shutting down IPC...\n");
421   CLOSE(ipc_sock);
422   CLOSE(ipc_conn);
423
424   return 1;
425 }
426
427 /*
428  * Local Variables:
429  * c-basic-offset: 2
430  * indent-tabs-mode: nil
431  * End:
432  */