* more fixups for the generated .c file
[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.23 2007/02/10 17:36:51 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   struct link_entry *link;
154   static int ttl_list[] = { 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, MAX_TTL-1, 0};
155
156   // remember that we have generated an LQ TC message; this is
157   // checked in net_output()
158
159   lq_tc_pending = OLSR_TRUE;
160
161   // initialize the static fields
162
163   lq_tc->comm.type = LQ_TC_MESSAGE;
164   lq_tc->comm.vtime = ME_TO_DOUBLE(outif->valtimes.tc);
165   lq_tc->comm.size = 0;
166
167   COPY_IP(&lq_tc->comm.orig, &olsr_cnf->main_addr);
168
169   if (olsr_cnf->lq_fish > 0)
170   {
171     // Sven-Ola: Too lazy to find the different iface inits. This will do it too.
172     if (outif->ttl_index >= (int)(sizeof(ttl_list) / sizeof(ttl_list[0])))
173       outif->ttl_index = 0;
174     
175     if (ttl_list[outif->ttl_index] == 0)
176       outif->ttl_index = 0;
177   
178     lq_tc->comm.ttl = ttl_list[outif->ttl_index++];
179
180     OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
181   }
182
183   else
184     lq_tc->comm.ttl = MAX_TTL;
185
186   lq_tc->comm.hops = 0;
187   lq_tc->comm.seqno = get_msg_seqno();
188
189   COPY_IP(&lq_tc->from, &olsr_cnf->main_addr);
190
191   lq_tc->ansn = get_local_ansn();
192
193   lq_tc->neigh = NULL;
194  
195   // loop through all neighbours
196   
197   for(i = 0; i < HASHSIZE; i++)
198     {
199       for(walker = neighbortable[i].next; walker != &neighbortable[i];
200           walker = walker->next)
201         {
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           link = get_best_link_to_neighbor(&neigh->main);
230
231           if (link) {
232             neigh->link_quality = link->loss_link_quality;
233             neigh->neigh_link_quality = link->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, j;
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       for(j = 0; j <= MAX_LINK; j++)
364         {
365           if(j == HIDE_LINK)
366             continue;
367
368           is_first = 1;
369
370           // loop through neighbors
371
372           for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
373             {  
374               if (neigh->neigh_type != i || neigh->link_type != j)
375                 continue;
376
377               // we need space for an IP address plus link quality
378               // information
379
380               req = olsr_cnf->ipsize + 4;
381
382               // no, we also need space for an info header, as this is the
383               // first neighbor with the current neighor type and link type
384
385               if (is_first != 0)
386                 req += sizeof (struct lq_hello_info_header);
387
388               // we do not have enough space left
389
390               // force signed comparison
391
392               if ((int)(size + req) > rem)
393                 {
394                   // finalize the OLSR header
395
396                   lq_hello->comm.size = size + off;
397
398                   serialize_common((struct olsr_common *)lq_hello);
399
400                   // finalize the info header
401
402                   info_head->size =
403                     ntohs(buff + size - (unsigned char *)info_head);
404                               
405                   // output packet
406
407                   net_outbuffer_push(outif, msg_buffer, size + off);
408
409                   net_output(outif);
410
411                   // move to the beginning of the buffer
412
413                   size = 0;
414                   rem = net_outbuffer_bytes_left(outif) - off;
415
416                   // we need a new info header
417
418                   is_first = 1;
419                 }
420
421               // create a new info header
422
423               if (is_first != 0)
424                 {
425                   info_head = (struct lq_hello_info_header *)(buff + size);
426                   size += sizeof (struct lq_hello_info_header);
427
428                   info_head->reserved = 0;
429                   info_head->link_code = CREATE_LINK_CODE(i, j);
430                 }
431
432               // add the current neighbor's IP address
433
434               COPY_IP(buff + size, &neigh->addr);
435               size += olsr_cnf->ipsize;
436
437               // add the corresponding link quality
438
439               buff[size++] = (unsigned char)(neigh->link_quality * 255);
440               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
441
442               // pad
443
444               buff[size++] = 0;
445               buff[size++] = 0;
446
447               is_first = 0;
448             }
449
450           // finalize the info header, if there are any neighbors with the
451           // current neighbor type and link type
452
453           if (is_first == 0)
454             info_head->size = ntohs(buff + size - (unsigned char *)info_head);
455         }
456     }
457
458   // finalize the OLSR header
459
460   lq_hello->comm.size = size + off;
461
462   serialize_common((struct olsr_common *)lq_hello);
463
464   // move the message to the output buffer
465
466   net_outbuffer_push(outif, msg_buffer, size + off);
467 }
468
469 static void
470 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
471 {
472   int off, rem, size;
473   struct lq_tc_header *head;
474   struct lq_tc_neighbor *neigh;
475   unsigned char *buff;
476
477   if (lq_tc == NULL || outif == NULL)
478     return;
479
480   // leave space for the OLSR header
481
482   off = common_size();
483
484   // initialize the LQ_TC header
485
486   head = (struct lq_tc_header *)(msg_buffer + off);
487
488   head->ansn = htons(lq_tc->ansn);
489   head->reserved = 0;
490
491   // 'off' is the offset of the byte following the LQ_TC header
492
493   off += sizeof (struct lq_tc_header);
494
495   // our work buffer starts at 'off'...
496
497   buff = msg_buffer + off;
498
499   // ... that's why we start with a 'size' of 0 and subtract 'off' from
500   // the remaining bytes in the output buffer
501
502   size = 0;
503   rem = net_outbuffer_bytes_left(outif) - off;
504
505   // initially, we want to put at least an IP address and the corresponding
506   // link quality into the message
507
508   // force signed comparison
509
510   if (rem < (int)(olsr_cnf->ipsize + 4))
511   {
512     net_output(outif);
513
514     rem = net_outbuffer_bytes_left(outif) - off;
515   }
516
517   // loop through neighbors
518
519   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
520     {  
521       // we need space for an IP address plus link quality
522       // information
523
524       // force signed comparison
525
526       if ((int)(size + olsr_cnf->ipsize + 4) > rem)
527         {
528           // finalize the OLSR header
529
530           lq_tc->comm.size = size + off;
531
532           serialize_common((struct olsr_common *)lq_tc);
533
534           // output packet
535
536           net_outbuffer_push(outif, msg_buffer, size + off);
537
538           net_output(outif);
539
540           // move to the beginning of the buffer
541
542           size = 0;
543           rem = net_outbuffer_bytes_left(outif) - off;
544         }
545
546       // add the current neighbor's IP address
547
548       COPY_IP(buff + size, &neigh->main);
549       size += olsr_cnf->ipsize;
550
551       // add the corresponding link quality
552
553       buff[size++] = (unsigned char)(neigh->link_quality * 255);
554       buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
555
556       // pad
557
558       buff[size++] = 0;
559       buff[size++] = 0;
560     }
561
562   // finalize the OLSR header
563
564   lq_tc->comm.size = size + off;
565
566   serialize_common((struct olsr_common *)lq_tc);
567
568   net_outbuffer_push(outif, msg_buffer, size + off);
569 }
570
571 static void *deserialize_common(struct olsr_common *comm, void *ser)
572 {
573   struct olsr_header_v4 *olsr_head_v4;
574   struct olsr_header_v6 *olsr_head_v6;
575
576   // deserialize an IPv4 OLSR message header
577
578   if (olsr_cnf->ip_version == AF_INET)
579     {
580       olsr_head_v4 = (struct olsr_header_v4 *)ser;
581
582       comm->type = olsr_head_v4->type;
583       comm->vtime = ME_TO_DOUBLE(olsr_head_v4->vtime);
584       comm->size = ntohs(olsr_head_v4->size);
585
586       COPY_IP(&comm->orig, &olsr_head_v4->orig);
587
588       comm->ttl = olsr_head_v4->ttl;
589       comm->hops = olsr_head_v4->hops;
590       comm->seqno = ntohs(olsr_head_v4->seqno);
591
592       return (void *)(olsr_head_v4 + 1);
593     }
594
595   // deserialize an IPv6 OLSR message header
596
597   olsr_head_v6 = (struct olsr_header_v6 *)ser;
598
599   comm->type = olsr_head_v6->type;
600   comm->vtime = ME_TO_DOUBLE(olsr_head_v6->vtime);
601   comm->size = ntohs(olsr_head_v6->size);
602
603   COPY_IP(&comm->orig, &olsr_head_v6->orig);
604
605   comm->ttl = olsr_head_v6->ttl;
606   comm->hops = olsr_head_v6->hops;
607   comm->seqno = ntohs(olsr_head_v6->seqno);
608
609   return (void *)(olsr_head_v6 + 1);
610 }
611
612 static void
613 deserialize_lq_hello(struct lq_hello_message *lq_hello, void *ser)
614 {
615   struct lq_hello_header *head;
616   struct lq_hello_info_header *info_head;
617   unsigned char *curr, *limit, *limit2;
618   struct lq_hello_neighbor *neigh;
619   
620   lq_hello->neigh = NULL;
621
622   if (ser == NULL)
623     return;
624
625   head = (struct lq_hello_header *)
626     deserialize_common((struct olsr_common *)lq_hello, ser);
627
628   if (lq_hello->comm.type != LQ_HELLO_MESSAGE)
629     return;
630
631   limit = ((unsigned char *)ser) + lq_hello->comm.size;
632
633   lq_hello->htime = ME_TO_DOUBLE(head->htime);
634   lq_hello->will = head->will;
635
636   lq_hello->neigh = NULL;
637
638   curr = (unsigned char *)(head + 1);
639
640   while (curr < limit)
641     {
642       info_head = (struct lq_hello_info_header *)curr;
643
644       limit2 = curr + ntohs(info_head->size);
645
646       curr = (unsigned char *)(info_head + 1);
647       
648       while (curr < limit2)
649         {
650           neigh = olsr_malloc(sizeof (struct lq_hello_neighbor),
651                               "LQ_HELLO deserialization");
652
653           COPY_IP(&neigh->addr, curr);
654           curr += olsr_cnf->ipsize;
655
656           neigh->link_quality = (double)*curr++ / 255.0;
657           neigh->neigh_link_quality = (double)*curr++ / 255.0;
658
659           curr += 2;
660
661           neigh->link_type = EXTRACT_LINK(info_head->link_code);
662           neigh->neigh_type = EXTRACT_STATUS(info_head->link_code);
663
664           neigh->next = lq_hello->neigh;
665           lq_hello->neigh = neigh;
666         }
667     }
668 }
669
670 static void
671 deserialize_lq_tc(struct lq_tc_message *lq_tc, void *ser,
672                   union olsr_ip_addr *from)
673 {
674   struct lq_tc_header *head;
675   union olsr_ip_addr *addr;
676   unsigned char *curr, *limit;
677   struct lq_tc_neighbor *neigh;
678
679   lq_tc->neigh = NULL;
680
681   if (ser == NULL)
682     return;
683
684   head = (struct lq_tc_header *)
685     deserialize_common((struct olsr_common *)lq_tc, ser);
686
687   if (lq_tc->comm.type != LQ_TC_MESSAGE)
688     return;
689
690   limit = ((unsigned char *)ser) + lq_tc->comm.size;
691
692   addr = mid_lookup_main_addr(from);
693
694   if (addr == 0)
695     COPY_IP(&lq_tc->from, from);
696
697   else
698     COPY_IP(&lq_tc->from, addr);
699
700   lq_tc->ansn =  ntohs(head->ansn);
701
702   lq_tc->neigh = NULL;
703
704   curr = (unsigned char *)(head + 1);
705
706   while (curr < limit)
707     {
708       neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
709                           "LQ_TC deserialization");
710
711       COPY_IP(&neigh->main, curr);
712       curr += olsr_cnf->ipsize;
713
714       neigh->link_quality = (double)*curr++ / 255.0;
715       neigh->neigh_link_quality = (double)*curr++ / 255.0;
716
717       curr += 2;
718
719       neigh->next = lq_tc->neigh;
720       lq_tc->neigh = neigh;
721     }
722 }
723
724 void
725 olsr_output_lq_hello(void *para)
726 {
727   struct lq_hello_message lq_hello;
728   struct interface *outif = (struct interface *)para;
729
730   // create LQ_HELLO in internal format
731
732   create_lq_hello(&lq_hello, outif);
733
734   // convert internal format into transmission format, send it
735
736   serialize_lq_hello(&lq_hello, outif);
737
738   // destroy internal format
739
740   destroy_lq_hello(&lq_hello);
741
742   if(net_output_pending(outif))
743     net_output(outif);
744 }
745
746 void
747 olsr_output_lq_tc(void *para)
748 {
749   static int prev_empty = 1;
750   struct lq_tc_message lq_tc;
751   struct interface *outif = (struct interface *)para;
752
753   // create LQ_TC in internal format
754
755   create_lq_tc(&lq_tc, outif);
756
757   // a) the message is not empty
758
759   if (lq_tc.neigh != NULL)
760     {
761       prev_empty = 0;
762
763       // convert internal format into transmission format, send it
764
765       serialize_lq_tc(&lq_tc, outif);
766     }
767
768   // b) this is the first empty message
769
770   else if (prev_empty == 0)
771     {
772       // initialize timer
773
774       set_empty_tc_timer(GET_TIMESTAMP((olsr_cnf->max_tc_vtime * 3) * 1000));
775
776       prev_empty = 1;
777
778       // convert internal format into transmission format, send it
779
780       serialize_lq_tc(&lq_tc, outif);
781     }
782
783   // c) this is not the first empty message, send if timer hasn't fired
784
785   else if (!TIMED_OUT(get_empty_tc_timer()))
786     serialize_lq_tc(&lq_tc, outif);
787
788   // destroy internal format
789
790   destroy_lq_tc(&lq_tc);
791
792   if(net_output_pending(outif) && TIMED_OUT(outif->fwdtimer))
793     set_buffer_timer(outif);
794 }
795
796 static void
797 process_lq_hello(struct lq_hello_message *lq_hello, struct interface *inif,
798                  union olsr_ip_addr *from)
799 {
800   struct hello_message hello;
801   struct lq_hello_neighbor *neigh;
802   struct hello_neighbor *new_neigh;
803
804   // Sven-Ola: Check the message source addr
805   if(!olsr_validate_address(&lq_hello->comm.orig))
806     {
807       return;
808     }
809
810   // XXX - translation is ugly; everybody should use lq_hello_message :-)
811
812   // move the static fields from LQ_HELLO to HELLO
813
814   hello.vtime = lq_hello->comm.vtime;
815   hello.htime = lq_hello->htime;
816
817   COPY_IP(&hello.source_addr, &lq_hello->comm.orig);
818
819   hello.packet_seq_number = lq_hello->comm.seqno;
820   hello.hop_count = lq_hello->comm.hops;
821   hello.ttl = lq_hello->comm.ttl;
822   hello.willingness = lq_hello->will;
823
824   hello.neighbors = NULL;
825
826   // move all LQ_HELLO neighbours to HELLO
827
828   for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
829     {
830       // Sven-Ola: Also check the neighbours
831       if(!olsr_validate_address(&neigh->addr)) continue;
832       
833       // allocate HELLO neighbour
834
835       new_neigh = olsr_malloc(sizeof (struct hello_neighbor),
836                               "LQ_HELLO translation");
837
838       // copy fields
839
840       new_neigh->status = neigh->neigh_type;
841       new_neigh->link = neigh->link_type;
842       new_neigh->link_quality = neigh->link_quality;
843       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
844
845       COPY_IP(&new_neigh->address, &neigh->addr);
846
847       // queue HELLO neighbour
848
849       new_neigh->next = hello.neighbors;
850       hello.neighbors = new_neigh;
851     }
852
853   olsr_hello_tap(&hello, inif, from);
854 }
855
856 static void
857 process_lq_tc(struct lq_tc_message *lq_tc, struct interface *inif,
858               union olsr_ip_addr *from, union olsr_message *ser)
859 {
860   struct tc_message tc;
861   struct lq_tc_neighbor *neigh;
862   struct tc_mpr_addr *new_neigh;
863
864   // Sven-Ola: Check the message source addr
865   if(!olsr_validate_address(&lq_tc->from)||!olsr_validate_address(&lq_tc->comm.orig))
866     {
867       return;
868     }
869
870   // XXX - translation is ugly; everybody should use lq_tc_message :-)
871
872   // move the static fields from LQ_TC to TC
873
874   tc.vtime = lq_tc->comm.vtime;
875
876   COPY_IP(&tc.source_addr, &lq_tc->from);
877   COPY_IP(&tc.originator, &lq_tc->comm.orig);
878
879   tc.packet_seq_number = lq_tc->comm.seqno;
880   tc.hop_count = lq_tc->comm.hops;
881   tc.ttl = lq_tc->comm.ttl;
882   tc.ansn = lq_tc->ansn;
883
884   tc.multipoint_relay_selector_address = NULL;
885
886   // move all LQ_TC neighbours to TC
887
888   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
889     {
890       // Sven-Ola: Also check the neighbours
891       if(!olsr_validate_address(&neigh->main)) continue;
892       
893       // allocate TC neighbour
894
895       new_neigh = olsr_malloc(sizeof (struct tc_mpr_addr),
896                               "LQ_TC translation");
897
898       // copy fields
899
900       new_neigh->link_quality = neigh->link_quality;
901       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
902
903       COPY_IP(&new_neigh->address, &neigh->main);
904
905       // queue TC neighbour
906
907       new_neigh->next = tc.multipoint_relay_selector_address;
908       tc.multipoint_relay_selector_address = new_neigh;
909     }
910
911   olsr_tc_tap(&tc, inif, from, ser);
912 }
913
914 void
915 olsr_input_lq_hello(union olsr_message *ser,
916                     struct interface *inif,
917                     union olsr_ip_addr *from)
918 {
919   struct lq_hello_message lq_hello;
920
921   // convert received packet from transmission format into internal format
922
923   deserialize_lq_hello(&lq_hello, ser);
924
925   // process internal format
926
927   process_lq_hello(&lq_hello, inif, from);
928
929   // destroy internal format
930
931   destroy_lq_hello(&lq_hello);
932 }
933
934 void
935 olsr_input_lq_tc(union olsr_message *ser, struct interface *inif,
936                  union olsr_ip_addr *from)
937 {
938   struct lq_tc_message lq_tc;
939   
940   // convert received packet from transmission format into internal format
941
942   deserialize_lq_tc(&lq_tc, ser, from);
943
944   // process internal format
945
946   process_lq_tc(&lq_tc, inif, from, ser);
947
948   // destroy internal format
949
950   destroy_lq_tc(&lq_tc);
951 }