c93646af0eca8dbc95a23751eb500b59e1ee16c3
[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
37
38 int ipc_socket = 0;
39
40 int
41 ipc_close()
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
57   int flags;
58 #endif
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("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
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
97     connected = 1;
98
99     return 1;
100   }
101
102   return 0;
103
104 }
105
106 int
107 ipc_read()
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("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()
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("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("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("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("Receied 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("Receied 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("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("Receied HNA packet\n");
270     } else {
271       process_hna(msgsize, vtime, originator, (union hna_message *)&olsr_in->v6.message.hna);
272       //printf("Receied HNA packet\n");
273     }
274
275     break;
276
277   case IPC_MESSAGE:
278     //printf("Receied 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("Receied 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
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 adresses: %d\n", msg->mids);
313      printf("\tHna adresses: %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, link;
400
401   printf("Processing HELLO from %s size = %d\n", ip_to_string(originator), size);
402
403   if (!update_timer_node(originator, vtime))
404     add_node(originator, vtime);
405
406   /* Add neighbors if any */
407   size = size - 4 - 8 - ipsize; /* size of neighbors(size - olsrheder- helloheader) */
408
409   if (!size)
410     return 0;
411
412   /* Get the neighbortype-blocks start */
413   neigh = m->v4.hell_info;
414   neigh6 = m->v6.hell_info;
415
416   //printf("HELLO Size: %d\n", size);
417
418   while (size > 0) {
419
420     //printf("\tNEIGH: 0x%x\n", (int)neigh);
421     if (ipversion == AF_INET) {
422       nsize = ntohs(neigh->size);
423       type = EXTRACT_STATUS(ntohs(neigh->link_code));
424       link = EXTRACT_LINK(ntohs(neigh->link_code));
425       //printf("TYPE: %d\n", neigh->link_code);
426     } else {
427       nsize = ntohs(neigh6->size);
428       type = EXTRACT_STATUS(ntohs(neigh6->link_code));
429       link = EXTRACT_LINK(ntohs(neigh6->link_code));
430     }
431
432     size -= nsize;
433
434     nsize = nsize - 4;          /* - hellinfo header */
435     //printf("Size left: %d Current hellinfo: %d\n", size, nsize);
436     i = 0;
437     while (nsize > 0) {
438       //printf("Adding neighbor %s...\n", ip_to_string((union olsr_ip_addr *)&neigh->neigh_addr[i]));
439       /*
440          if(MPR)
441          update_timer_mpr((union olsr_ip_addr *)&mprsinfo->addr, originator);
442        */
443
444       if (ipversion == AF_INET) {       /* Update MPRs */
445         if (type == MPR_NEIGH) {
446           //printf("MPR from HELLO\n");
447           update_timer_mpr((union olsr_ip_addr *)&neigh->neigh_addr[i], originator, vtime);
448         }
449         add_node((union olsr_ip_addr *)&neigh->neigh_addr[i++], vtime);
450       } else {
451         if (type == MPR_NEIGH) {        /* Update MPRs */
452           //printf("MPR from HELLO\n");
453           update_timer_mpr((union olsr_ip_addr *)&neigh6->neigh_addr[i], originator, vtime);
454         }
455         add_node((union olsr_ip_addr *)&neigh6->neigh_addr[i++], vtime);
456       }
457
458       nsize = nsize - ipsize;
459       //printf("Nsize: %d\n", nsize);
460     }
461
462     neigh = (struct hellinfo *)&neigh->neigh_addr[i];
463     neigh6 = (struct hellinfo6 *)&neigh6->neigh_addr[i];
464
465   }
466   //printf("DONE\n");
467
468   return 0;
469 }
470
471 int
472 process_tc(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union tc_message *m)
473 {
474
475   struct neigh_info *mprsinfo;
476   struct neigh_info6 *mprsinfo6;
477
478   printf("Processing TC from %s size = %d\n", ip_to_string(originator), size);
479
480   /* Updating timer */
481   if (!update_timer_node(originator, vtime))
482     add_node(originator, vtime);
483
484   /* Calculate size of the mprsinfo */
485   size = size - 4 - 8 - ipsize;
486
487   //printf("TC Size: %d\n", size);
488
489   if (ipversion == AF_INET)
490     mprsinfo = &m->v4.neigh[0];
491   else
492     mprsinfo6 = &m->v6.neigh[0];
493
494   while (size > 0) {
495     if (ipversion == AF_INET) {
496       //printf("\tprocessing TC: %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo->addr));
497       add_node((union olsr_ip_addr *)&mprsinfo->addr, vtime);
498       update_timer_mpr((union olsr_ip_addr *)&mprsinfo->addr, originator, vtime);
499       mprsinfo++;
500     } else {
501       //printf("\tprocessing TC: %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo6->addr));
502       //printf("TC: add node %s\n", ip_to_string((union olsr_ip_addr *)&mprsinfo6->addr));
503       add_node((union olsr_ip_addr *)&mprsinfo6->addr, vtime);
504       update_timer_mpr((union olsr_ip_addr *)&mprsinfo6->addr, originator, vtime);
505       mprsinfo6++;
506     }
507     size = size - ipsize;
508     //printf("\tsize: %d\n", size);
509   }
510   //printf("DONE\n");
511
512   return 0;
513 }
514
515 int
516 process_mid(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union mid_message *m)
517 {
518   struct midaddr *midaddr;
519   struct midaddr6 *midaddr6;
520
521   printf("Processing MID from %s size = %d\n", ip_to_string(originator), size);
522
523   /* Calculate size of the midinfo */
524   size = size - 4 - 4 - ipsize;
525
526   if (ipversion == AF_INET)
527     midaddr = &m->v4.mid_addr[0];
528   else
529     midaddr6 = &m->v6.mid_addr[0];
530
531   //printf("MID size: %d\n", size);
532
533   while (size > 0) {
534     if (ipversion == AF_INET) {
535       //printf("MID: add node %s\n", ip_to_string((union olsr_ip_addr *)&midaddr->addr));
536       add_mid_node(originator, (union olsr_ip_addr *)&midaddr->addr, vtime);
537       midaddr++;
538     } else {
539       add_mid_node(originator, (union olsr_ip_addr *)&midaddr6->addr, vtime);
540       //printf("MID: add node %s\n", ip_to_string((union olsr_ip_addr *)&midaddr6->addr));
541       midaddr6++;
542     }
543     size = size - ipsize;
544   }
545
546   //printf("DONE\n");
547   return 0;
548 }
549
550 int
551 process_hna(int size, olsr_u8_t vtime, union olsr_ip_addr *originator, union hna_message *m)
552 {
553
554   printf("Processing HNA size = %d\n", size);
555   struct hnapair *hnapairs;
556   struct hnapair6 *hnapairs6;
557
558   /* Calculate size of the hnainfo */
559   size = size - 4 - 4 - ipsize;
560
561   if (ipversion == AF_INET)
562     hnapairs = &m->v4.hna_net[0];
563   else
564     hnapairs6 = &m->v6.hna_net[0];
565
566   while (size > 0) {
567     if (ipversion == AF_INET) {
568       //printf("\tHNA:%s\n", ip_to_string((union olsr_ip_addr *)&hnapairs->addr));
569       add_hna_node(originator, (union olsr_ip_addr *)&hnapairs->addr, (union olsr_ip_addr *)&hnapairs->netmask, vtime);
570       hnapairs++;
571     } else {
572       add_hna_node(originator, (union olsr_ip_addr *)&hnapairs6->addr, (union olsr_ip_addr *)&hnapairs6->netmask, vtime);
573       hnapairs6++;
574     }
575
576     size = size - ipsize - ipsize;
577   }
578
579   return 0;
580 }
581
582 char *
583 ip_to_string(union olsr_ip_addr *addr)
584 {
585   char *ret;
586   struct in_addr in;
587
588   if (ipversion == AF_INET) {
589     in.s_addr = addr->v4;
590     ret = inet_ntoa(in);
591   } else {
592     /* IPv6 */
593     ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
594   }
595
596   return ret;
597
598 }
599
600 int
601 gui_itoa(int i, char *buf)
602 {
603   char tmp[10];
604
605   if (sprintf(buf, "%hd", i)) {
606     /* This shitty string needs to be converted to UTF-8 */
607     strcpy(tmp, g_locale_to_utf8(buf, -1, NULL, NULL, NULL));
608     strcpy(buf, tmp);
609     return 1;
610     //return ret;
611   }
612   return 0;
613 }
614
615 /*
616  * Local Variables:
617  * c-basic-offset: 2
618  * indent-tabs-mode: nil
619  * End:
620  */