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