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