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