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