- Made a function from the ME_TO_DOUBLE() macro (in src/mantissa.h).
[olsrd.git] / src / lq_packet.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2003, Andreas T√łnnesen (andreto@olsr.org)
4  *               2004, Thomas Lopatic (thomas@lopatic.de)
5  *               2006, for some fixups, sven-ola(gmx.de)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions 
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright 
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright 
15  *   notice, this list of conditions and the following disclaimer in 
16  *   the documentation and/or other materials provided with the 
17  *   distribution.
18  * * Neither the name of olsr.org, olsrd nor the names of its 
19  *   contributors may be used to endorse or promote products derived 
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Visit http://www.olsr.org for more information.
36  *
37  * If you find this software useful feel free to make a donation
38  * to the project. For more information see the website or contact
39  * the copyright holders.
40  *
41  * $Id: lq_packet.c,v 1.26 2007/08/28 20:45:17 bernd67 Exp $
42  */
43
44 #include "olsr_protocol.h"
45 #include "defs.h"
46 #include "lq_packet.h"
47 #include "interfaces.h"
48 #include "link_set.h"
49 #include "neighbor_table.h"
50 #include "mpr_selector_set.h"
51 #include "mid_set.h"
52 #include "mantissa.h"
53 #include "process_package.h" // XXX - remove
54 #include "two_hop_neighbor_table.h"
55 #include "hysteresis.h"
56 #include "olsr.h"
57 #include "build_msg.h"
58
59 olsr_bool lq_tc_pending = OLSR_FALSE;
60
61 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
62
63 static void
64 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
65 {
66   struct lq_hello_neighbor *neigh;
67   struct link_entry *walker;
68
69   // initialize the static fields
70
71   lq_hello->comm.type = LQ_HELLO_MESSAGE;
72   lq_hello->comm.vtime = me_to_double(outif->valtimes.hello);
73   lq_hello->comm.size = 0;
74
75   COPY_IP(&lq_hello->comm.orig, &olsr_cnf->main_addr);
76
77   lq_hello->comm.ttl = 1;
78   lq_hello->comm.hops = 0;
79   lq_hello->comm.seqno = get_msg_seqno();
80
81   lq_hello->htime = outif->hello_etime;
82   lq_hello->will = olsr_cnf->willingness;
83
84   lq_hello->neigh = NULL;
85   
86   // loop through the link set
87
88   for (walker = get_link_set(); walker != NULL; walker = walker->next)
89     {
90       // allocate a neighbour entry
91
92       neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
93       
94       // a) this neighbor interface IS NOT visible via the output interface
95
96       if(!COMP_IP(&walker->local_iface_addr, &outif->ip_addr))
97         neigh->link_type = UNSPEC_LINK;
98       
99       // b) this neighbor interface IS visible via the output interface
100
101       else
102         neigh->link_type = lookup_link_status(walker);
103
104       // set the entry's link quality
105
106       neigh->link_quality = walker->loss_link_quality;
107       neigh->neigh_link_quality = walker->neigh_link_quality;
108
109       // set the entry's neighbour type
110
111       if(walker->neighbor->is_mpr)
112         neigh->neigh_type = MPR_NEIGH;
113
114       else if (walker->neighbor->status == SYM)
115         neigh->neigh_type = SYM_NEIGH;
116
117       else if (walker->neighbor->status == NOT_SYM)
118         neigh->neigh_type = NOT_NEIGH;
119   
120       // set the entry's neighbour interface address
121
122       COPY_IP(&neigh->addr, &walker->neighbor_iface_addr);
123       
124       // queue the neighbour entry
125
126       neigh->next = lq_hello->neigh;
127       lq_hello->neigh = neigh;
128     }
129 }
130
131 static void
132 destroy_lq_hello(struct lq_hello_message *lq_hello)
133 {
134   struct lq_hello_neighbor *walker, *aux;
135
136   // loop through the queued neighbour entries and free them
137
138   for (walker = lq_hello->neigh; walker != NULL; walker = aux)
139     {
140       aux = walker->next;
141       free(walker);
142     }
143
144   lq_hello->neigh = NULL;
145 }
146
147 static void
148 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
149 {
150   struct lq_tc_neighbor *neigh;
151   int i;
152   struct neighbor_entry *walker;
153   static int ttl_list[] = { 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, MAX_TTL-1, 0};
154
155   // remember that we have generated an LQ TC message; this is
156   // checked in net_output()
157
158   lq_tc_pending = OLSR_TRUE;
159
160   // initialize the static fields
161
162   lq_tc->comm.type = LQ_TC_MESSAGE;
163   lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
164   lq_tc->comm.size = 0;
165
166   COPY_IP(&lq_tc->comm.orig, &olsr_cnf->main_addr);
167
168   if (olsr_cnf->lq_fish > 0)
169   {
170     // Sven-Ola: Too lazy to find the different iface inits. This will do it too.
171     if (outif->ttl_index >= (int)(sizeof(ttl_list) / sizeof(ttl_list[0])))
172       outif->ttl_index = 0;
173     
174     if (ttl_list[outif->ttl_index] == 0)
175       outif->ttl_index = 0;
176   
177     lq_tc->comm.ttl = ttl_list[outif->ttl_index++];
178
179     OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
180   }
181
182   else
183     lq_tc->comm.ttl = MAX_TTL;
184
185   lq_tc->comm.hops = 0;
186   lq_tc->comm.seqno = get_msg_seqno();
187
188   COPY_IP(&lq_tc->from, &olsr_cnf->main_addr);
189
190   lq_tc->ansn = get_local_ansn();
191
192   lq_tc->neigh = NULL;
193  
194   // loop through all neighbours
195   
196   for(i = 0; i < HASHSIZE; i++)
197     {
198       for(walker = neighbortable[i].next; walker != &neighbortable[i];
199           walker = walker->next)
200         {
201           struct link_entry *lnk;
202           // only consider symmetric neighbours
203
204           if(walker->status != SYM)
205             continue;
206
207           // TC redundancy == 1: only consider MPRs and MPR selectors
208
209           if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
210               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
211             continue;
212
213           // TC redundancy == 0: only consider MPR selectors
214
215           else if (olsr_cnf->tc_redundancy == 0 &&
216                    olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
217             continue;
218
219           // allocate a neighbour entry
220           
221           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor), "Build LQ_TC");
222                 
223           // set the entry's main address
224
225           COPY_IP(&neigh->main, &walker->neighbor_main_addr);
226
227           // set the entry's link quality
228
229           lnk = get_best_link_to_neighbor(&neigh->main);
230
231           if (lnk) {
232             neigh->link_quality = lnk->loss_link_quality;
233             neigh->neigh_link_quality = lnk->neigh_link_quality;
234           }
235
236           // queue the neighbour entry
237
238           neigh->next = lq_tc->neigh;
239           lq_tc->neigh = neigh;
240         }
241     }
242 }
243
244 static void
245 destroy_lq_tc(struct lq_tc_message *lq_tc)
246 {
247   struct lq_tc_neighbor *walker, *aux;
248
249   // loop through the queued neighbour entries and free them
250
251   for (walker = lq_tc->neigh; walker != NULL; walker = aux)
252     {
253       aux = walker->next;
254       free(walker);
255     }
256 }
257
258 static int common_size(void)
259 {
260   // return the size of the header shared by all OLSR messages
261
262   return (olsr_cnf->ip_version == AF_INET) ?
263     sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
264 }
265
266 static void serialize_common(struct olsr_common *comm)
267 {
268   struct olsr_header_v4 *olsr_head_v4;
269   struct olsr_header_v6 *olsr_head_v6;
270
271   // serialize an IPv4 OLSR message header
272
273   if (olsr_cnf->ip_version == AF_INET)
274     {
275       olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
276
277       olsr_head_v4->type = comm->type;
278       olsr_head_v4->vtime = double_to_me(comm->vtime);
279       olsr_head_v4->size = htons(comm->size);
280
281       COPY_IP(&olsr_head_v4->orig, &comm->orig);
282
283       olsr_head_v4->ttl = comm->ttl;
284       olsr_head_v4->hops = comm->hops;
285       olsr_head_v4->seqno = htons(comm->seqno);
286
287       return;
288     }
289
290   // serialize an IPv6 OLSR message header
291
292   olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
293
294   olsr_head_v6->type = comm->type;
295   olsr_head_v6->vtime = double_to_me(comm->vtime);
296   olsr_head_v6->size = htons(comm->size);
297
298   COPY_IP(&olsr_head_v6->orig, &comm->orig);
299
300   olsr_head_v6->ttl = comm->ttl;
301   olsr_head_v6->hops = comm->hops;
302   olsr_head_v6->seqno = htons(comm->seqno);
303 }
304
305 static void
306 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
307 {
308   int off, rem, size, req;
309   struct lq_hello_header *head;
310   struct lq_hello_info_header *info_head;
311   struct lq_hello_neighbor *neigh;
312   unsigned char *buff;
313   int is_first;
314   int i;
315
316   if (lq_hello == NULL || outif == NULL)
317     return;
318
319   // leave space for the OLSR header
320
321   off = common_size();
322
323   // initialize the LQ_HELLO header
324
325   head = (struct lq_hello_header *)(msg_buffer + off);
326
327   head->reserved = 0;
328   head->htime = double_to_me(lq_hello->htime);
329   head->will = lq_hello->will; 
330
331   // 'off' is the offset of the byte following the LQ_HELLO header
332
333   off += sizeof (struct lq_hello_header);
334
335   // our work buffer starts at 'off'...
336
337   buff = msg_buffer + off;
338
339   // ... that's why we start with a 'size' of 0 and subtract 'off' from
340   // the remaining bytes in the output buffer
341
342   size = 0;
343   rem = net_outbuffer_bytes_left(outif) - off;
344
345   // initially, we want to put at least an info header, an IP address,
346   // and the corresponding link quality into the message
347
348   // force signed comparison
349
350   if (rem < (int)(sizeof (struct lq_hello_info_header) + olsr_cnf->ipsize + 4))
351   {
352     net_output(outif);
353
354     rem = net_outbuffer_bytes_left(outif) - off;
355   }
356
357   info_head = NULL;
358
359   // iterate through all neighbor types ('i') and all link types ('j')
360
361   for (i = 0; i <= MAX_NEIGH; i++) 
362     {
363       static const int LINK_ORDER[] = {SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK};
364       unsigned int j;
365       for(j = 0; j < sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0]); j++)
366         {
367           is_first = 1;
368
369           // loop through neighbors
370
371           for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
372             {  
373               if (neigh->neigh_type != i || neigh->link_type != LINK_ORDER[j])
374                 continue;
375
376               // we need space for an IP address plus link quality
377               // information
378
379               req = olsr_cnf->ipsize + 4;
380
381               // no, we also need space for an info header, as this is the
382               // first neighbor with the current neighor type and link type
383
384               if (is_first != 0)
385                 req += sizeof (struct lq_hello_info_header);
386
387               // we do not have enough space left
388
389               // force signed comparison
390
391               if ((int)(size + req) > rem)
392                 {
393                   // finalize the OLSR header
394
395                   lq_hello->comm.size = size + off;
396
397                   serialize_common((struct olsr_common *)lq_hello);
398
399                   // finalize the info header
400
401                   info_head->size =
402                     ntohs(buff + size - (unsigned char *)info_head);
403                               
404                   // output packet
405
406                   net_outbuffer_push(outif, msg_buffer, size + off);
407
408                   net_output(outif);
409
410                   // move to the beginning of the buffer
411
412                   size = 0;
413                   rem = net_outbuffer_bytes_left(outif) - off;
414
415                   // we need a new info header
416
417                   is_first = 1;
418                 }
419
420               // create a new info header
421
422               if (is_first != 0)
423                 {
424                   info_head = (struct lq_hello_info_header *)(buff + size);
425                   size += sizeof (struct lq_hello_info_header);
426
427                   info_head->reserved = 0;
428                   info_head->link_code = CREATE_LINK_CODE(i, LINK_ORDER[j]);
429                 }
430
431               // add the current neighbor's IP address
432
433               COPY_IP(buff + size, &neigh->addr);
434               size += olsr_cnf->ipsize;
435
436               // add the corresponding link quality
437
438               buff[size++] = (unsigned char)(neigh->link_quality * 255);
439               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
440
441               // pad
442
443               buff[size++] = 0;
444               buff[size++] = 0;
445
446               is_first = 0;
447             }
448
449           // finalize the info header, if there are any neighbors with the
450           // current neighbor type and link type
451
452           if (is_first == 0)
453             info_head->size = ntohs(buff + size - (unsigned char *)info_head);
454         }
455     }
456
457   // finalize the OLSR header
458
459   lq_hello->comm.size = size + off;
460
461   serialize_common((struct olsr_common *)lq_hello);
462
463   // move the message to the output buffer
464
465   net_outbuffer_push(outif, msg_buffer, size + off);
466 }
467
468 static void
469 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
470 {
471   int off, rem, size;
472   struct lq_tc_header *head;
473   struct lq_tc_neighbor *neigh;
474   unsigned char *buff;
475
476   if (lq_tc == NULL || outif == NULL)
477     return;
478
479   // leave space for the OLSR header
480
481   off = common_size();
482
483   // initialize the LQ_TC header
484
485   head = (struct lq_tc_header *)(msg_buffer + off);
486
487   head->ansn = htons(lq_tc->ansn);
488   head->reserved = 0;
489
490   // 'off' is the offset of the byte following the LQ_TC header
491
492   off += sizeof (struct lq_tc_header);
493
494   // our work buffer starts at 'off'...
495
496   buff = msg_buffer + off;
497
498   // ... that's why we start with a 'size' of 0 and subtract 'off' from
499   // the remaining bytes in the output buffer
500
501   size = 0;
502   rem = net_outbuffer_bytes_left(outif) - off;
503
504   // initially, we want to put at least an IP address and the corresponding
505   // link quality into the message
506
507   // force signed comparison
508
509   if (rem < (int)(olsr_cnf->ipsize + 4))
510   {
511     net_output(outif);
512
513     rem = net_outbuffer_bytes_left(outif) - off;
514   }
515
516   // loop through neighbors
517
518   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
519     {  
520       // we need space for an IP address plus link quality
521       // information
522
523       // force signed comparison
524
525       if ((int)(size + olsr_cnf->ipsize + 4) > rem)
526         {
527           // finalize the OLSR header
528
529           lq_tc->comm.size = size + off;
530
531           serialize_common((struct olsr_common *)lq_tc);
532
533           // output packet
534
535           net_outbuffer_push(outif, msg_buffer, size + off);
536
537           net_output(outif);
538
539           // move to the beginning of the buffer
540
541           size = 0;
542           rem = net_outbuffer_bytes_left(outif) - off;
543         }
544
545       // add the current neighbor's IP address
546
547       COPY_IP(buff + size, &neigh->main);
548       size += olsr_cnf->ipsize;
549
550       // add the corresponding link quality
551
552       buff[size++] = (unsigned char)(neigh->link_quality * 255);
553       buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
554
555       // pad
556
557       buff[size++] = 0;
558       buff[size++] = 0;
559     }
560
561   // finalize the OLSR header
562
563   lq_tc->comm.size = size + off;
564
565   serialize_common((struct olsr_common *)lq_tc);
566
567   net_outbuffer_push(outif, msg_buffer, size + off);
568 }
569
570 static void *deserialize_common(struct olsr_common *comm, void *ser)
571 {
572   struct olsr_header_v4 *olsr_head_v4;
573   struct olsr_header_v6 *olsr_head_v6;
574
575   // deserialize an IPv4 OLSR message header
576
577   if (olsr_cnf->ip_version == AF_INET)
578     {
579       olsr_head_v4 = (struct olsr_header_v4 *)ser;
580
581       comm->type = olsr_head_v4->type;
582       comm->vtime = me_to_double(olsr_head_v4->vtime);
583       comm->size = ntohs(olsr_head_v4->size);
584
585       COPY_IP(&comm->orig, &olsr_head_v4->orig);
586
587       comm->ttl = olsr_head_v4->ttl;
588       comm->hops = olsr_head_v4->hops;
589       comm->seqno = ntohs(olsr_head_v4->seqno);
590
591       return (void *)(olsr_head_v4 + 1);
592     }
593
594   // deserialize an IPv6 OLSR message header
595
596   olsr_head_v6 = (struct olsr_header_v6 *)ser;
597
598   comm->type = olsr_head_v6->type;
599   comm->vtime = me_to_double(olsr_head_v6->vtime);
600   comm->size = ntohs(olsr_head_v6->size);
601
602   COPY_IP(&comm->orig, &olsr_head_v6->orig);
603
604   comm->ttl = olsr_head_v6->ttl;
605   comm->hops = olsr_head_v6->hops;
606   comm->seqno = ntohs(olsr_head_v6->seqno);
607
608   return (void *)(olsr_head_v6 + 1);
609 }
610
611 static void
612 deserialize_lq_hello(struct lq_hello_message *lq_hello, void *ser)
613 {
614   struct lq_hello_header *head;
615   struct lq_hello_info_header *info_head;
616   unsigned char *curr, *limit, *limit2;
617   struct lq_hello_neighbor *neigh;
618   
619   lq_hello->neigh = NULL;
620
621   if (ser == NULL)
622     return;
623
624   head = (struct lq_hello_header *)
625     deserialize_common((struct olsr_common *)lq_hello, ser);
626
627   if (lq_hello->comm.type != LQ_HELLO_MESSAGE)
628     return;
629
630   limit = ((unsigned char *)ser) + lq_hello->comm.size;
631
632   lq_hello->htime = me_to_double(head->htime);
633   lq_hello->will = head->will;
634
635   lq_hello->neigh = NULL;
636
637   curr = (unsigned char *)(head + 1);
638
639   while (curr < limit)
640     {
641       info_head = (struct lq_hello_info_header *)curr;
642
643       limit2 = curr + ntohs(info_head->size);
644
645       curr = (unsigned char *)(info_head + 1);
646       
647       while (curr < limit2)
648         {
649           neigh = olsr_malloc(sizeof (struct lq_hello_neighbor),
650                               "LQ_HELLO deserialization");
651
652           COPY_IP(&neigh->addr, curr);
653           curr += olsr_cnf->ipsize;
654
655           neigh->link_quality = (double)*curr++ / 255.0;
656           neigh->neigh_link_quality = (double)*curr++ / 255.0;
657
658           curr += 2;
659
660           neigh->link_type = EXTRACT_LINK(info_head->link_code);
661           neigh->neigh_type = EXTRACT_STATUS(info_head->link_code);
662
663           neigh->next = lq_hello->neigh;
664           lq_hello->neigh = neigh;
665         }
666     }
667 }
668
669 static void
670 deserialize_lq_tc(struct lq_tc_message *lq_tc, void *ser,
671                   union olsr_ip_addr *from)
672 {
673   struct lq_tc_header *head;
674   union olsr_ip_addr *addr;
675   unsigned char *curr, *limit;
676   struct lq_tc_neighbor *neigh;
677
678   lq_tc->neigh = NULL;
679
680   if (ser == NULL)
681     return;
682
683   head = (struct lq_tc_header *)
684     deserialize_common((struct olsr_common *)lq_tc, ser);
685
686   if (lq_tc->comm.type != LQ_TC_MESSAGE)
687     return;
688
689   limit = ((unsigned char *)ser) + lq_tc->comm.size;
690
691   addr = mid_lookup_main_addr(from);
692
693   if (addr == 0)
694     COPY_IP(&lq_tc->from, from);
695
696   else
697     COPY_IP(&lq_tc->from, addr);
698
699   lq_tc->ansn =  ntohs(head->ansn);
700
701   lq_tc->neigh = NULL;
702
703   curr = (unsigned char *)(head + 1);
704
705   while (curr < limit)
706     {
707       neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
708                           "LQ_TC deserialization");
709
710       COPY_IP(&neigh->main, curr);
711       curr += olsr_cnf->ipsize;
712
713       neigh->link_quality = (double)*curr++ / 255.0;
714       neigh->neigh_link_quality = (double)*curr++ / 255.0;
715
716       curr += 2;
717
718       neigh->next = lq_tc->neigh;
719       lq_tc->neigh = neigh;
720     }
721 }
722
723 void
724 olsr_output_lq_hello(void *para)
725 {
726   struct lq_hello_message lq_hello;
727   struct interface *outif = (struct interface *)para;
728
729   // create LQ_HELLO in internal format
730
731   create_lq_hello(&lq_hello, outif);
732
733   // convert internal format into transmission format, send it
734
735   serialize_lq_hello(&lq_hello, outif);
736
737   // destroy internal format
738
739   destroy_lq_hello(&lq_hello);
740
741   if(net_output_pending(outif))
742     net_output(outif);
743 }
744
745 void
746 olsr_output_lq_tc(void *para)
747 {
748   static int prev_empty = 1;
749   struct lq_tc_message lq_tc;
750   struct interface *outif = (struct interface *)para;
751
752   // create LQ_TC in internal format
753
754   create_lq_tc(&lq_tc, outif);
755
756   // a) the message is not empty
757
758   if (lq_tc.neigh != NULL)
759     {
760       prev_empty = 0;
761
762       // convert internal format into transmission format, send it
763
764       serialize_lq_tc(&lq_tc, outif);
765     }
766
767   // b) this is the first empty message
768
769   else if (prev_empty == 0)
770     {
771       // initialize timer
772
773       set_empty_tc_timer(GET_TIMESTAMP((olsr_cnf->max_tc_vtime * 3) * 1000));
774
775       prev_empty = 1;
776
777       // convert internal format into transmission format, send it
778
779       serialize_lq_tc(&lq_tc, outif);
780     }
781
782   // c) this is not the first empty message, send if timer hasn't fired
783
784   else if (!TIMED_OUT(get_empty_tc_timer()))
785     serialize_lq_tc(&lq_tc, outif);
786
787   // destroy internal format
788
789   destroy_lq_tc(&lq_tc);
790
791   if(net_output_pending(outif) && TIMED_OUT(outif->fwdtimer))
792     set_buffer_timer(outif);
793 }
794
795 static void
796 process_lq_hello(struct lq_hello_message *lq_hello, struct interface *inif,
797                  union olsr_ip_addr *from)
798 {
799   struct hello_message hello;
800   struct lq_hello_neighbor *neigh;
801   struct hello_neighbor *new_neigh;
802
803   // Sven-Ola: Check the message source addr
804   if(!olsr_validate_address(&lq_hello->comm.orig))
805     {
806       return;
807     }
808
809   // XXX - translation is ugly; everybody should use lq_hello_message :-)
810
811   // move the static fields from LQ_HELLO to HELLO
812
813   hello.vtime = lq_hello->comm.vtime;
814   hello.htime = lq_hello->htime;
815
816   COPY_IP(&hello.source_addr, &lq_hello->comm.orig);
817
818   hello.packet_seq_number = lq_hello->comm.seqno;
819   hello.hop_count = lq_hello->comm.hops;
820   hello.ttl = lq_hello->comm.ttl;
821   hello.willingness = lq_hello->will;
822
823   hello.neighbors = NULL;
824
825   // move all LQ_HELLO neighbours to HELLO
826
827   for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
828     {
829       // Sven-Ola: Also check the neighbours
830       if(!olsr_validate_address(&neigh->addr)) continue;
831       
832       // allocate HELLO neighbour
833
834       new_neigh = olsr_malloc(sizeof (struct hello_neighbor),
835                               "LQ_HELLO translation");
836
837       // copy fields
838
839       new_neigh->status = neigh->neigh_type;
840       new_neigh->link = neigh->link_type;
841       new_neigh->link_quality = neigh->link_quality;
842       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
843
844       COPY_IP(&new_neigh->address, &neigh->addr);
845
846       // queue HELLO neighbour
847
848       new_neigh->next = hello.neighbors;
849       hello.neighbors = new_neigh;
850     }
851
852   olsr_hello_tap(&hello, inif, from);
853 }
854
855 static void
856 process_lq_tc(struct lq_tc_message *lq_tc, struct interface *inif,
857               union olsr_ip_addr *from, union olsr_message *ser)
858 {
859   struct tc_message tc;
860   struct lq_tc_neighbor *neigh;
861   struct tc_mpr_addr *new_neigh;
862
863   // Sven-Ola: Check the message source addr
864   if(!olsr_validate_address(&lq_tc->from)||!olsr_validate_address(&lq_tc->comm.orig))
865     {
866       return;
867     }
868
869   // XXX - translation is ugly; everybody should use lq_tc_message :-)
870
871   // move the static fields from LQ_TC to TC
872
873   tc.vtime = lq_tc->comm.vtime;
874
875   COPY_IP(&tc.source_addr, &lq_tc->from);
876   COPY_IP(&tc.originator, &lq_tc->comm.orig);
877
878   tc.packet_seq_number = lq_tc->comm.seqno;
879   tc.hop_count = lq_tc->comm.hops;
880   tc.ttl = lq_tc->comm.ttl;
881   tc.ansn = lq_tc->ansn;
882
883   tc.multipoint_relay_selector_address = NULL;
884
885   // move all LQ_TC neighbours to TC
886
887   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
888     {
889       // Sven-Ola: Also check the neighbours
890       if(!olsr_validate_address(&neigh->main)) continue;
891       
892       // allocate TC neighbour
893
894       new_neigh = olsr_malloc(sizeof (struct tc_mpr_addr),
895                               "LQ_TC translation");
896
897       // copy fields
898
899       new_neigh->link_quality = neigh->link_quality;
900       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
901
902       COPY_IP(&new_neigh->address, &neigh->main);
903
904       // queue TC neighbour
905
906       new_neigh->next = tc.multipoint_relay_selector_address;
907       tc.multipoint_relay_selector_address = new_neigh;
908     }
909
910   olsr_tc_tap(&tc, inif, from, ser);
911 }
912
913 void
914 olsr_input_lq_hello(union olsr_message *ser,
915                     struct interface *inif,
916                     union olsr_ip_addr *from)
917 {
918   struct lq_hello_message lq_hello;
919
920   // convert received packet from transmission format into internal format
921
922   deserialize_lq_hello(&lq_hello, ser);
923
924   // process internal format
925
926   process_lq_hello(&lq_hello, inif, from);
927
928   // destroy internal format
929
930   destroy_lq_hello(&lq_hello);
931 }
932
933 void
934 olsr_input_lq_tc(union olsr_message *ser, struct interface *inif,
935                  union olsr_ip_addr *from)
936 {
937   struct lq_tc_message lq_tc;
938   
939   // convert received packet from transmission format into internal format
940
941   deserialize_lq_tc(&lq_tc, ser, from);
942
943   // process internal format
944
945   process_lq_tc(&lq_tc, inif, from, ser);
946
947   // destroy internal format
948
949   destroy_lq_tc(&lq_tc);
950 }