85ec6e1cf8039681ab876722cef37eabfd5e8a67
[olsrd.git] / gui / linux-gtk / src / ipc.c
1
2 /*
3  * OLSR ad-hoc routing table management protocol GUI front-end
4  * Copyright (C) 2003 Andreas Tonnesen (andreto@ifi.uio.no)
5  *
6  * This file is part of olsr.org.
7  *
8  * uolsrGUI is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * uolsrGUI is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with olsr.org; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "common.h"
25 #include "ipc.h"
26 #include "packet.h"
27 #include "routes.h"
28
29 #ifdef _WIN32
30 #define close(x) closesocket(x)
31 #undef errno
32 #define errno WSAGetLastError()
33 #undef strerror
34 #define strerror(x) StrError(x)
35 #define perror(x) WinSockPError(x)
36 #endif /* _WIN32 */
37
38 int ipc_socket = 0;
39 int connected;
40
41 int
42 ipc_close(void)
43 {
44
45   if (close(ipc_socket))
46     return 1;
47
48   return 0;
49 }
50
51 int
52 ipc_connect(struct sockaddr_in *pin)
53 {
54 #ifdef _WIN32
55   int On = 1;
56   unsigned long Len;
57 #else /* _WIN32 */
58   int flags;
59 #endif /* _WIN32 */
60
61   connected = 0;
62
63   if (!ipc_socket)
64     if ((ipc_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
65       perror("socket");
66       exit(EXIT_FAILURE);
67     }
68
69   printf("Attempting connect...");
70
71   /* connect to PORT on HOST */
72   if (connect(ipc_socket, (struct sockaddr *)pin, sizeof(*pin)) < 0) {
73     fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
74     set_net_info_offline();
75     printf("connection refused\n");
76   } else {
77     set_net_info((gchar *)"Connected!", FALSE);
78     printf("Connected!!\n");
79
80     /* Setting socket non-blocking */
81
82 #ifdef _WIN32
83     if (WSAIoctl(ipc_socket, FIONBIO, &On, sizeof(On), NULL, 0, &Len, NULL, NULL) < 0) {
84       fprintf(stderr, "Error while making socket non-blocking!\n");
85       exit(EXIT_FAILURE);
86     }
87 #else /* _WIN32 */
88     if ((flags = fcntl(ipc_socket, F_GETFL, 0)) < 0) {
89       fprintf(stderr, "Error getting socket flags!\n");
90       exit(EXIT_FAILURE);
91     }
92
93     if (fcntl(ipc_socket, F_SETFL, flags | O_NONBLOCK) < 0) {
94       fprintf(stderr, "Error setting socket flags!\n");
95       exit(EXIT_FAILURE);
96     }
97 #endif /* _WIN32 */
98     connected = 1;
99
100     return 1;
101   }
102
103   return 0;
104
105 }
106
107 int
108 ipc_read(void)
109 {
110   //int x, i;
111   int bytes, tmp_len;
112   char *tmp;
113   union olsr_message *msg;
114   union {
115     char buf[BUFFSIZE + 1];
116     union olsr_message olsr_msg;
117   } inbuf;
118   //char buf[BUFFSIZE+1];
119
120   //printf(".");fflush(stdout);
121   memset(&inbuf, 0, sizeof(inbuf));
122   //buf[0] = '\0';
123
124   if (connected) {
125     bytes = recv(ipc_socket, (char *)&inbuf, BUFFSIZE, 0);
126     if (bytes == 0) {
127       shutdown(ipc_socket, SHUT_RDWR);
128       set_net_info((gchar *)"Disconnected from server...", TRUE);
129       connected = 0;
130       close(ipc_socket);
131     }
132
133     if (bytes > 0) {
134
135       tmp = (char *)&inbuf.olsr_msg;
136
137       /*
138          x = 0;
139          printf("\n\t");
140          for(i = 0; i < bytes;i++)
141          {
142          if(x == 4)
143          {
144          x = 0;
145          printf("\n\t");
146          }
147          x++;
148          printf(" %03i", (u_char) tmp[i]);
149          }
150
151          printf("\n\nBytes read: %d - msg_size: %d\n", bytes, ntohs(inbuf.olsr.v4.olsr_packlen));
152        */
153
154       msg = &inbuf.olsr_msg;
155
156       /* There can be(there probably are!) several packets in the buffer */
157
158       /* Should be the same for v4 and v6 */
159       if (ntohs(inbuf.olsr_msg.v4.olsr_msgsize) < bytes) {
160         //printf("chomping...\n");
161         while (ntohs(msg->v4.olsr_msgsize) < bytes) {
162           ipc_evaluate_message(msg);
163
164           tmp_len = ntohs(msg->v4.olsr_msgsize);
165           msg = (union olsr_message *)&tmp[tmp_len];
166           tmp = &tmp[tmp_len];
167           if (tmp_len == 0)
168             break;
169           bytes = bytes - tmp_len;
170
171           tmp_len = ntohs(msg->v4.olsr_msgsize);
172
173           //printf("%d/%d ", tmp_len, bytes);
174           /* Copy to start of buffer */
175           if (tmp_len > bytes) {
176             /* Copy the buffer */
177             //printf("READING END OF MESSAGE. %d bytes\n", tmp_len-bytes);
178             //printf("\tCopying %d bytes\n", bytes);
179             memcpy(&inbuf, tmp, bytes);
180             //printf("\tReceiving %d bytes to buffer[%d]\n", tmp_len-bytes, bytes);
181             bytes = recv(ipc_socket, (char *)&inbuf.buf[bytes], tmp_len - bytes, 0);
182             //printf("\tBytes: %d Size: %d\n", bytes, ntohs(msgs->v4.olsr_packlen));
183             tmp = (char *)&inbuf.olsr_msg;
184             msg = (union olsr_message *)tmp;
185           }
186         }
187         //printf("\n");
188       }
189
190       /* Only one (or the last) message */
191       ipc_evaluate_message(msg);
192
193     }
194
195   }
196
197   return 1;
198 }
199
200 int
201 ipc_send(void)
202 {
203
204   return 1;
205 }
206
207 int
208 ipc_evaluate_message(union olsr_message *olsr_in)
209 {
210   int ipc_pack = 0;
211   olsr_u8_t type;
212   int msgsize;
213   char itoa_buf[10];
214   olsr_u8_t vtime;
215   union olsr_ip_addr *originator;
216
217   /* Find size, vtime, originator and type - same for IPv4 and 6 */
218   type = olsr_in->v4.olsr_msgtype;
219   msgsize = ntohs(olsr_in->v4.olsr_msgsize);
220   vtime = olsr_in->v4.olsr_vtime;
221   originator = (union olsr_ip_addr *)&olsr_in->v4.originator;
222
223   gui_itoa(msgsize, itoa_buf);
224
225   switch (type) {
226   case HELLO_MESSAGE:
227     //printf("Received HELLO packet\n");
228     if (!freeze_packets)
229       packet_list_add((char *)"HELLO", ip_to_string(originator), itoa_buf);
230
231     if (ipversion == AF_INET) {
232       process_hello(msgsize, vtime, originator, (union hello_message *)&olsr_in->v4.message.hello);
233     } else {
234       process_hello(msgsize, vtime, originator, (union hello_message *)&olsr_in->v6.message.hello);
235     }
236     break;
237
238   case TC_MESSAGE:
239     if (!freeze_packets)
240       packet_list_add((char *)"TC", ip_to_string(originator), itoa_buf);
241
242     if (ipversion == AF_INET) {
243       process_tc(msgsize, vtime, originator, (union tc_message *)&olsr_in->v4.message.tc);
244       //printf("Received TC packet from %s\n", ip_to_string(&m->olsr_tc->tc_origaddr));
245     } else {
246       process_tc(msgsize, vtime, originator, (union tc_message *)&olsr_in->v6.message.tc);
247       //printf("Received TC packet from %s\n", ip_to_string(&m->olsr_tc->tc_origaddr));
248     }
249     break;
250
251   case MID_MESSAGE:
252     if (!freeze_packets)
253       packet_list_add((char *)"MID", ip_to_string(originator), itoa_buf);
254     if (ipversion == AF_INET) {
255       process_mid(msgsize, vtime, originator, (union mid_message *)&olsr_in->v4.message.mid);
256       //printf("Received MID packet from %s\n", ip_to_string(&m->olsr_mid->mid_origaddr));
257     } else {
258       process_mid(msgsize, vtime, originator, (union mid_message *)&olsr_in->v6.message.mid);
259       //printf("Received MID packet from %s\n", ip_to_string(&m->olsr_mid->mid_origaddr));
260     }
261
262     break;
263
264   case HNA_MESSAGE:
265
266     if (!freeze_packets)
267       packet_list_add((char *)"HNA", ip_to_string(originator), itoa_buf);
268     if (ipversion == AF_INET) {
269       process_hna(msgsize, vtime, originator, (union hna_message *)&olsr_in->v4.message.hna);
270       //printf("Received HNA packet\n");
271     } else {
272       process_hna(msgsize, vtime, originator, (union hna_message *)&olsr_in->v6.message.hna);
273       //printf("Received HNA packet\n");
274     }
275
276     break;
277
278   case IPC_MESSAGE:
279     //printf("Received IPC packet\n");
280     ipc_pack = 1;               /* Don't add to buffer */
281     ipc_eval_route_packet((struct routemsg *)olsr_in);
282     break;
283   case IPC_NET:
284     //printf("Received IPC packet\n");
285     ipc_pack = 1;               /* Don't add to buffer */
286     ipc_eval_net_info((struct netmsg *)olsr_in);
287     break;
288   default:
289     if (!freeze_packets) {
290       char unk_label[8];
291       sprintf(unk_label, "%d", type);
292       packet_list_add(unk_label, ip_to_string(originator), itoa_buf);
293     }
294     printf("Unknown packet type %d\n", type);
295     break;
296   }
297
298   if (!freeze_packets && !ipc_pack) {
299     add_packet_to_buffer(olsr_in, msgsize);
300   }
301
302   return 1;
303 }
304
305 int
306 ipc_eval_net_info(struct netmsg *msg)
307 {
308   char info[256];
309   printf("Evaluating NET info...\n");
310
311   /*
312      printf("\tMain address: %s\n", ip_to_string(&msg->main_addr));
313      printf("\tMid addresses: %d\n", msg->mids);
314      printf("\tHna addresses: %d\n", msg->hnas);
315      printf("\tHELLO interval: %f\n", (float)(ntohs(msg->hello_int)));
316      printf("\tHELLO LAN interval: %f\n", (float)(ntohs(msg->hello_lan_int)));
317      printf("\tTC interval: %d\n", ntohs(msg->tc_int));
318      printf("\tNeighbor hold time: %d\n", ntohs(msg->neigh_hold));
319      printf("\tTopology hold: %d\n", ntohs(msg->topology_hold));
320    */
321   if (msg->ipv6 == 0) {
322     ipversion = AF_INET;
323     ipsize = sizeof(struct in_addr);
324     sprintf(&info[0],
325             "IP version 4\nMain address: %s\nMid addresses: %d\nHna addresses: %d\nHELLO interval: %d\nHELLO LAN interval: %d\nTC interval: %d\nNeighbor hold time: %d\nTopology hold: %d\n",
326             ip_to_string(&msg->main_addr), msg->mids, msg->hnas, ntohs(msg->hello_int), ntohs(msg->hello_lan_int),
327             ntohs(msg->tc_int), ntohs(msg->neigh_hold), ntohs(msg->topology_hold));
328   } else {
329     ipversion = AF_INET6;
330     ipsize = sizeof(struct in6_addr);
331     sprintf(&info[0],
332             "IP version 6\nMain address: %s\nMid addresses: %d\nHna addresses: %d\nHELLO interval: %d\nHELLO LAN interval: %d\nTC interval: %d\nNeighbor hold time: %d\nTopology hold: %d\n",
333             ip_to_string(&msg->main_addr), msg->mids, msg->hnas, ntohs(msg->hello_int), ntohs(msg->hello_lan_int),
334             ntohs(msg->tc_int), ntohs(msg->neigh_hold), ntohs(msg->topology_hold));
335   }
336
337   memcpy(&main_addr, &msg->main_addr, ipsize);
338
339   set_net_info(&info[0], 0);
340
341   return 0;
342 }
343
344 int
345 ipc_eval_route_packet(struct routemsg *msg)
346 {
347   struct route_entry rt_ent;
348   char dev[5];
349   char gw[16];
350   char itoa_buf[10];
351   dev[4] = '\0';
352   memset(&gw[0], 0, 16);
353
354   printf("Processing route packet\n");
355
356   memset(rt_ent.if_name, 0, MAX_IF_NAMESIZ);
357
358   /* Fill struct */
359
360   memcpy(&rt_ent.gw, &msg->gateway_addr, ipsize);
361   memcpy(&rt_ent.dst, &msg->target_addr, ipsize);
362   memcpy(rt_ent.if_name, msg->device, 4);
363   rt_ent.hopcnt = msg->metric;
364
365   if (msg->add) {
366     memcpy(&dev[0], &msg->device[0], 4);
367
368     /*Add node to node list */
369     memcpy(&gw[0], ip_to_string(&msg->gateway_addr), 16);
370
371     gui_itoa(msg->metric, itoa_buf);
372
373     route_list_add(ip_to_string(&msg->target_addr), gw, dev, itoa_buf);
374
375     printf("\tRoute to %s(hc %d) added\n", ip_to_string(&msg->target_addr), rt_ent.hopcnt);
376
377     /*
378        printf("\tRoute to %s added\n", ip_to_string(&msg->target_addr));
379        printf("\tGateway %s\n", gw);
380        printf("\tInterface %s\n", msg->device);
381        printf("\tMetric %d\n", msg->metric);
382      */
383   } else {
384
385     if (route_list_del(ip_to_string(&msg->target_addr)) < 1)
386       printf("COULD NOT FIND ROUTE TO DELETE!\n\n");
387
388     printf("\tRoute to %s deleted\n", ip_to_string(&msg->target_addr));
389   }
390   return 1;
391 }
392
393 int
394 process_hello(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union hello_message *m)
395 {
396   struct hellinfo *neigh;
397   struct hellinfo6 *neigh6;
398   int i;
399   int nsize;
400   int type;
401   //int link;
402
403   printf("Processing HELLO from %s size = %d\n", ip_to_string(originator), size);
404
405   if (!update_timer_node(originator, vtime))
406     add_node(originator, vtime);
407
408   /* Add neighbors if any */
409   size = size - 4 - 8 - ipsize; /* size of neighbors(size - olsrheder- helloheader) */
410
411   if (!size)
412     return 0;
413
414   /* Get the neighbortype-blocks start */
415   neigh = m->v4.hell_info;
416   neigh6 = m->v6.hell_info;
417
418   //printf("HELLO Size: %d\n", size);
419
420   while (size > 0) {
421
422     //printf("\tNEIGH: 0x%x\n", (int)neigh);
423     if (ipversion == AF_INET) {
424       nsize = ntohs(neigh->size);
425       type = EXTRACT_STATUS(ntohs(neigh->link_code));
426       //link = EXTRACT_LINK(ntohs(neigh->link_code));
427       //printf("TYPE: %d\n", neigh->link_code);
428     } else {
429       nsize = ntohs(neigh6->size);
430       type = EXTRACT_STATUS(ntohs(neigh6->link_code));
431       //link = EXTRACT_LINK(ntohs(neigh6->link_code));
432     }
433
434     size -= nsize;
435
436     nsize = nsize - 4;          /* - hellinfo header */
437     //printf("Size left: %d Current hellinfo: %d\n", size, nsize);
438     i = 0;
439     while (nsize > 0) {
440       //printf("Adding neighbor %s...\n", ip_to_string((union olsr_ip_addr *)&neigh->neigh_addr[i]));
441       /*
442          if(MPR)
443          update_timer_mpr((union olsr_ip_addr *)&mprsinfo->addr, originator);
444        */
445
446       if (ipversion == AF_INET) {       /* Update MPRs */
447         if (type == MPR_NEIGH) {
448           //printf("MPR from HELLO\n");
449           update_timer_mpr((union olsr_ip_addr *)&neigh->neigh_addr[i], originator, vtime);
450         }
451         add_node((union olsr_ip_addr *)&neigh->neigh_addr[i++], vtime);
452       } else {
453         if (type == MPR_NEIGH) {        /* Update MPRs */
454           //printf("MPR from HELLO\n");
455           update_timer_mpr((union olsr_ip_addr *)&neigh6->neigh_addr[i], originator, vtime);
456         }
457         add_node((union olsr_ip_addr *)&neigh6->neigh_addr[i++], vtime);
458       }
459
460       nsize = nsize - ipsize;
461       //printf("Nsize: %d\n", nsize);
462     }
463
464     neigh = (struct hellinfo *)&neigh->neigh_addr[i];
465     neigh6 = (struct hellinfo6 *)&neigh6->neigh_addr[i];
466
467   }
468   //printf("DONE\n");
469
470   return 0;
471 }
472
473 int
474 process_tc(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union tc_message *m)
475 {
476
477   struct neigh_info *mprsinfo = NULL;
478   struct neigh_info6 *mprsinfo6 = NULL;
479
480   printf("Processing TC from %s size = %d\n", ip_to_string(originator), size);
481
482   /* Updating timer */
483   if (!update_timer_node(originator, vtime))
484     add_node(originator, vtime);
485
486   /* Calculate size of the mprsinfo */
487   size = size - 4 - 8 - ipsize;
488
489   //printf("TC Size: %d\n", size);
490
491   if (ipversion == AF_INET)
492     mprsinfo = &m->v4.neigh[0];
493   else
494     mprsinfo6 = &m->v6.neigh[0];
495
496   while (size > 0) {
497     if (ipversion == AF_INET) {
498       //printf("\tprocessing TC: %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo->addr));
499       add_node((union olsr_ip_addr *)&mprsinfo->addr, vtime);
500       update_timer_mpr((union olsr_ip_addr *)&mprsinfo->addr, originator, vtime);
501       mprsinfo++;
502     } else {
503       //printf("\tprocessing TC: %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo6->addr));
504       //printf("TC: add node %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo6->addr));
505       add_node((union olsr_ip_addr *)&mprsinfo6->addr, vtime);
506       update_timer_mpr((union olsr_ip_addr *)&mprsinfo6->addr, originator, vtime);
507       mprsinfo6++;
508     }
509     size = size - ipsize;
510     //printf("\tsize: %d\n", size);
511   }
512   //printf("DONE\n");
513
514   return 0;
515 }
516
517 int
518 process_mid(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union mid_message *m)
519 {
520   struct midaddr *midaddr = NULL;
521   struct midaddr6 *midaddr6 = NULL;
522
523   printf("Processing MID from %s size = %d\n", ip_to_string(originator), size);
524
525   /* Calculate size of the midinfo */
526   size = size - 4 - 4 - ipsize;
527
528   if (ipversion == AF_INET)
529     midaddr = &m->v4.mid_addr[0];
530   else
531     midaddr6 = &m->v6.mid_addr[0];
532
533   //printf("MID size: %d\n", size);
534
535   while (size > 0) {
536     if (ipversion == AF_INET) {
537       //printf("MID: add node %s\n", ip_to_string((union olsr_ip_addr *)&midaddr->addr));
538       add_mid_node(originator, (union olsr_ip_addr *)&midaddr->addr, vtime);
539       midaddr++;
540     } else {
541       add_mid_node(originator, (union olsr_ip_addr *)&midaddr6->addr, vtime);
542       //printf("MID: add node %s\n", ip_to_string((union olsr_ip_addr *)&midaddr6->addr));
543       midaddr6++;
544     }
545     size = size - ipsize;
546   }
547
548   //printf("DONE\n");
549   return 0;
550 }
551
552 int
553 process_hna(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union hna_message *m)
554 {
555   struct hnapair *hnapairs = NULL;
556   struct hnapair6 *hnapairs6 = NULL;
557
558   printf("Processing HNA size = %d\n", size);
559
560   /* Calculate size of the hnainfo */
561   size = size - 4 - 4 - ipsize;
562
563   if (ipversion == AF_INET)
564     hnapairs = &m->v4.hna_net[0];
565   else
566     hnapairs6 = &m->v6.hna_net[0];
567
568   while (size > 0) {
569     if (ipversion == AF_INET) {
570       //printf("\tHNA:%s\n", ip_to_string((union olsr_ip_addr *)&hnapairs->addr));
571       add_hna_node(originator, (union olsr_ip_addr *)&hnapairs->addr, (union olsr_ip_addr *)&hnapairs->netmask, vtime);
572       hnapairs++;
573     } else {
574       add_hna_node(originator, (union olsr_ip_addr *)&hnapairs6->addr, (union olsr_ip_addr *)&hnapairs6->netmask, vtime);
575       hnapairs6++;
576     }
577
578     size = size - ipsize - ipsize;
579   }
580
581   return 0;
582 }
583
584 char *
585 ip_to_string(union olsr_ip_addr *addr)
586 {
587   char *ret;
588   struct in_addr in;
589
590   if (ipversion == AF_INET) {
591     in = addr->v4;
592     ret = inet_ntoa(in);
593   } else {
594     /* IPv6 */
595     ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
596   }
597
598   return ret;
599
600 }
601
602 int
603 gui_itoa(int i, char *buf)
604 {
605   char tmp[10];
606
607   if (snprintf(buf, sizeof(tmp), "%hd", i)) {
608     /* This shitty string needs to be converted to UTF-8 */
609     snprintf(tmp, sizeof(tmp), "%s", g_locale_to_utf8(buf, -1, NULL, NULL, NULL));
610     strcpy(buf, tmp);
611     return 1;
612     //return ret;
613   }
614   return 0;
615 }
616
617 /*
618  * Local Variables:
619  * c-basic-offset: 2
620  * indent-tabs-mode: nil
621  * End:
622  */