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