* applied patches from the most recent FreiFunkFirmware (and fixed compile errors...
[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  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without 
8  * modification, are permitted provided that the following conditions 
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright 
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright 
14  *   notice, this list of conditions and the following disclaimer in 
15  *   the documentation and/or other materials provided with the 
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its 
18  *   contributors may be used to endorse or promote products derived 
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  * $Id: lq_packet.c,v 1.22 2007/01/31 12:36:50 bernd67 Exp $
41  */
42
43 #include "olsr_protocol.h"
44 #include "defs.h"
45 #include "lq_packet.h"
46 #include "interfaces.h"
47 #include "link_set.h"
48 #include "neighbor_table.h"
49 #include "mpr_selector_set.h"
50 #include "mid_set.h"
51 #include "mantissa.h"
52 #include "process_package.h" // XXX - remove
53 #include "two_hop_neighbor_table.h"
54 #include "hysteresis.h"
55 #include "olsr.h"
56 #include "build_msg.h"
57
58 olsr_bool lq_tc_pending = OLSR_FALSE;
59
60 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
61
62 static void
63 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
64 {
65   struct lq_hello_neighbor *neigh;
66   struct link_entry *walker;
67
68   // initialize the static fields
69
70   lq_hello->comm.type = LQ_HELLO_MESSAGE;
71   lq_hello->comm.vtime = ME_TO_DOUBLE(outif->valtimes.hello);
72   lq_hello->comm.size = 0;
73
74   COPY_IP(&lq_hello->comm.orig, &olsr_cnf->main_addr);
75
76   lq_hello->comm.ttl = 1;
77   lq_hello->comm.hops = 0;
78   lq_hello->comm.seqno = get_msg_seqno();
79
80   lq_hello->htime = outif->hello_etime;
81   lq_hello->will = olsr_cnf->willingness;
82
83   lq_hello->neigh = NULL;
84   
85   // loop through the link set
86
87   for (walker = get_link_set(); walker != NULL; walker = walker->next)
88     {
89       // allocate a neighbour entry
90
91       neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
92       
93       // a) this neighbor interface IS NOT visible via the output interface
94
95       if(!COMP_IP(&walker->local_iface_addr, &outif->ip_addr))
96         neigh->link_type = UNSPEC_LINK;
97       
98       // b) this neighbor interface IS visible via the output interface
99
100       else
101         neigh->link_type = lookup_link_status(walker);
102
103       // set the entry's link quality
104
105       neigh->link_quality = walker->loss_link_quality;
106       neigh->neigh_link_quality = walker->neigh_link_quality;
107
108       // set the entry's neighbour type
109
110       if(walker->neighbor->is_mpr)
111         neigh->neigh_type = MPR_NEIGH;
112
113       else if (walker->neighbor->status == SYM)
114         neigh->neigh_type = SYM_NEIGH;
115
116       else if (walker->neighbor->status == NOT_SYM)
117         neigh->neigh_type = NOT_NEIGH;
118   
119       // set the entry's neighbour interface address
120
121       COPY_IP(&neigh->addr, &walker->neighbor_iface_addr);
122       
123       // queue the neighbour entry
124
125       neigh->next = lq_hello->neigh;
126       lq_hello->neigh = neigh;
127     }
128 }
129
130 static void
131 destroy_lq_hello(struct lq_hello_message *lq_hello)
132 {
133   struct lq_hello_neighbor *walker, *aux;
134
135   // loop through the queued neighbour entries and free them
136
137   for (walker = lq_hello->neigh; walker != NULL; walker = aux)
138     {
139       aux = walker->next;
140       free(walker);
141     }
142
143   lq_hello->neigh = NULL;
144 }
145
146 static void
147 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
148 {
149   struct lq_tc_neighbor *neigh;
150   int i;
151   struct neighbor_entry *walker;
152   struct link_entry *link;
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           // only consider symmetric neighbours
202
203           if(walker->status != SYM)
204             continue;
205
206           // TC redundancy == 1: only consider MPRs and MPR selectors
207
208           if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
209               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
210             continue;
211
212           // TC redundancy == 0: only consider MPR selectors
213
214           else if (olsr_cnf->tc_redundancy == 0 &&
215                    olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
216             continue;
217
218           // allocate a neighbour entry
219           
220           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor), "Build LQ_TC");
221                 
222           // set the entry's main address
223
224           COPY_IP(&neigh->main, &walker->neighbor_main_addr);
225
226           // set the entry's link quality
227
228           link = get_best_link_to_neighbor(&neigh->main);
229
230           if (link) {
231             neigh->link_quality = link->loss_link_quality;
232             neigh->neigh_link_quality = link->neigh_link_quality;
233           }
234
235           // queue the neighbour entry
236
237           neigh->next = lq_tc->neigh;
238           lq_tc->neigh = neigh;
239         }
240     }
241 }
242
243 static void
244 destroy_lq_tc(struct lq_tc_message *lq_tc)
245 {
246   struct lq_tc_neighbor *walker, *aux;
247
248   // loop through the queued neighbour entries and free them
249
250   for (walker = lq_tc->neigh; walker != NULL; walker = aux)
251     {
252       aux = walker->next;
253       free(walker);
254     }
255 }
256
257 static int common_size(void)
258 {
259   // return the size of the header shared by all OLSR messages
260
261   return (olsr_cnf->ip_version == AF_INET) ?
262     sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
263 }
264
265 static void serialize_common(struct olsr_common *comm)
266 {
267   struct olsr_header_v4 *olsr_head_v4;
268   struct olsr_header_v6 *olsr_head_v6;
269
270   // serialize an IPv4 OLSR message header
271
272   if (olsr_cnf->ip_version == AF_INET)
273     {
274       olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
275
276       olsr_head_v4->type = comm->type;
277       olsr_head_v4->vtime = double_to_me(comm->vtime);
278       olsr_head_v4->size = htons(comm->size);
279
280       COPY_IP(&olsr_head_v4->orig, &comm->orig);
281
282       olsr_head_v4->ttl = comm->ttl;
283       olsr_head_v4->hops = comm->hops;
284       olsr_head_v4->seqno = htons(comm->seqno);
285
286       return;
287     }
288
289   // serialize an IPv6 OLSR message header
290
291   olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
292
293   olsr_head_v6->type = comm->type;
294   olsr_head_v6->vtime = double_to_me(comm->vtime);
295   olsr_head_v6->size = htons(comm->size);
296
297   COPY_IP(&olsr_head_v6->orig, &comm->orig);
298
299   olsr_head_v6->ttl = comm->ttl;
300   olsr_head_v6->hops = comm->hops;
301   olsr_head_v6->seqno = htons(comm->seqno);
302 }
303
304 static void
305 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
306 {
307   int off, rem, size, req;
308   struct lq_hello_header *head;
309   struct lq_hello_info_header *info_head;
310   struct lq_hello_neighbor *neigh;
311   unsigned char *buff;
312   int is_first;
313   int i, j;
314
315   if (lq_hello == NULL || outif == NULL)
316     return;
317
318   // leave space for the OLSR header
319
320   off = common_size();
321
322   // initialize the LQ_HELLO header
323
324   head = (struct lq_hello_header *)(msg_buffer + off);
325
326   head->reserved = 0;
327   head->htime = double_to_me(lq_hello->htime);
328   head->will = lq_hello->will; 
329
330   // 'off' is the offset of the byte following the LQ_HELLO header
331
332   off += sizeof (struct lq_hello_header);
333
334   // our work buffer starts at 'off'...
335
336   buff = msg_buffer + off;
337
338   // ... that's why we start with a 'size' of 0 and subtract 'off' from
339   // the remaining bytes in the output buffer
340
341   size = 0;
342   rem = net_outbuffer_bytes_left(outif) - off;
343
344   // initially, we want to put at least an info header, an IP address,
345   // and the corresponding link quality into the message
346
347   // force signed comparison
348
349   if (rem < (int)(sizeof (struct lq_hello_info_header) + olsr_cnf->ipsize + 4))
350   {
351     net_output(outif);
352
353     rem = net_outbuffer_bytes_left(outif) - off;
354   }
355
356   info_head = NULL;
357
358   // iterate through all neighbor types ('i') and all link types ('j')
359
360   for (i = 0; i <= MAX_NEIGH; i++) 
361     {
362       for(j = 0; j <= MAX_LINK; j++)
363         {
364           if(j == HIDE_LINK)
365             continue;
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 != 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, 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 }