Fixed signed/unsigned comparison.
[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.15 2005/03/09 23:06:30 tlopatic 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
57 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
58
59 static void
60 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
61 {
62   struct lq_hello_neighbor *neigh;
63   struct link_entry *walker;
64
65   // initialize the static fields
66
67   lq_hello->comm.type = LQ_HELLO_MESSAGE;
68   lq_hello->comm.vtime = me_to_double(outif->valtimes.hello);
69   lq_hello->comm.size = 0;
70
71   COPY_IP(&lq_hello->comm.orig, &main_addr);
72
73   lq_hello->comm.ttl = 1;
74   lq_hello->comm.hops = 0;
75   lq_hello->comm.seqno = get_msg_seqno();
76
77   lq_hello->htime = me_to_double(outif->hello_etime);
78   lq_hello->will = olsr_cnf->willingness;
79
80   lq_hello->neigh = NULL;
81   
82   // loop through the link set
83
84   for (walker = get_link_set(); walker != NULL; walker = walker->next)
85     {
86       // allocate a neighbour entry
87
88       neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
89       
90       // a) this neighbor interface IS NOT visible via the output interface
91
92       if(!COMP_IP(&walker->local_iface_addr, &outif->ip_addr))
93         neigh->link_type = UNSPEC_LINK;
94       
95       // b) this neighbor interface IS visible via the output interface
96
97       else
98         neigh->link_type = lookup_link_status(walker);
99
100       // set the entry's link quality
101
102       neigh->link_quality = walker->loss_link_quality;
103       neigh->neigh_link_quality = walker->neigh_link_quality;
104
105       // set the entry's neighbour type
106
107       if(walker->neighbor->is_mpr)
108         neigh->neigh_type = MPR_NEIGH;
109
110       else if (walker->neighbor->status == SYM)
111         neigh->neigh_type = SYM_NEIGH;
112
113       else if (walker->neighbor->status == NOT_SYM)
114         neigh->neigh_type = NOT_NEIGH;
115   
116       // set the entry's neighbour interface address
117
118       COPY_IP(&neigh->addr, &walker->neighbor_iface_addr);
119       
120       // queue the neighbour entry
121
122       neigh->next = lq_hello->neigh;
123       lq_hello->neigh = neigh;
124     }
125 }
126
127 static void
128 destroy_lq_hello(struct lq_hello_message *lq_hello)
129 {
130   struct lq_hello_neighbor *walker, *aux;
131
132   // loop through the queued neighbour entries and free them
133
134   for (walker = lq_hello->neigh; walker != NULL; walker = aux)
135     {
136       aux = walker->next;
137       free(walker);
138     }
139
140   lq_hello->neigh = NULL;
141 }
142
143 static void
144 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
145 {
146   struct lq_tc_neighbor *neigh;
147   int i;
148   struct neighbor_entry *walker;
149   struct link_entry *link;
150
151   // initialize the static fields
152
153   lq_tc->comm.type = LQ_TC_MESSAGE;
154   lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
155   lq_tc->comm.size = 0;
156
157   COPY_IP(&lq_tc->comm.orig, &main_addr);
158
159   lq_tc->comm.ttl = MAX_TTL;
160   lq_tc->comm.hops = 0;
161   lq_tc->comm.seqno = get_msg_seqno();
162
163   COPY_IP(&lq_tc->from, &main_addr);
164
165   lq_tc->ansn = get_local_ansn();
166
167   lq_tc->neigh = NULL;
168  
169   // loop through all neighbours
170   
171   for(i = 0; i < HASHSIZE; i++)
172     {
173       for(walker = neighbortable[i].next; walker != &neighbortable[i];
174           walker = walker->next)
175         {
176           // only consider symmetric neighbours
177
178           if(walker->status != SYM)
179             continue;
180
181           // TC redundancy == 1: only consider MPRs and MPR selectors
182
183           if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
184               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
185             continue;
186
187           // TC redundancy == 0: only consider MPR selectors
188
189           else if (olsr_cnf->tc_redundancy == 0 &&
190                    olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
191             continue;
192
193           // allocate a neighbour entry
194           
195           neigh = olsr_malloc(sizeof (struct lq_tc_neighbor), "Build LQ_TC");
196                 
197           // set the entry's main address
198
199           COPY_IP(&neigh->main, &walker->neighbor_main_addr);
200
201           // set the entry's link quality
202
203           link = get_best_link_to_neighbor(&neigh->main);
204
205           neigh->link_quality = link->loss_link_quality;
206           neigh->neigh_link_quality = link->neigh_link_quality;
207
208           // queue the neighbour entry
209
210           neigh->next = lq_tc->neigh;
211           lq_tc->neigh = neigh;
212         }
213     }
214 }
215
216 static void
217 destroy_lq_tc(struct lq_tc_message *lq_tc)
218 {
219   struct lq_tc_neighbor *walker, *aux;
220
221   // loop through the queued neighbour entries and free them
222
223   for (walker = lq_tc->neigh; walker != NULL; walker = aux)
224     {
225       aux = walker->next;
226       free(walker);
227     }
228 }
229
230 static int common_size(void)
231 {
232   // return the size of the header shared by all OLSR messages
233
234   return (olsr_cnf->ip_version == AF_INET) ?
235     sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
236 }
237
238 static void serialize_common(struct olsr_common *comm)
239 {
240   struct olsr_header_v4 *olsr_head_v4;
241   struct olsr_header_v6 *olsr_head_v6;
242
243   // serialize an IPv4 OLSR message header
244
245   if (olsr_cnf->ip_version == AF_INET)
246     {
247       olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
248
249       olsr_head_v4->type = comm->type;
250       olsr_head_v4->vtime = double_to_me(comm->vtime);
251       olsr_head_v4->size = htons(comm->size);
252
253       COPY_IP(&olsr_head_v4->orig, &comm->orig);
254
255       olsr_head_v4->ttl = comm->ttl;
256       olsr_head_v4->hops = comm->hops;
257       olsr_head_v4->seqno = htons(comm->seqno);
258
259       return;
260     }
261
262   // serialize an IPv6 OLSR message header
263
264   olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
265
266   olsr_head_v6->type = comm->type;
267   olsr_head_v6->vtime = double_to_me(comm->vtime);
268   olsr_head_v6->size = htons(comm->size);
269
270   COPY_IP(&olsr_head_v6->orig, &comm->orig);
271
272   olsr_head_v6->ttl = comm->ttl;
273   olsr_head_v6->hops = comm->hops;
274   olsr_head_v6->seqno = htons(comm->seqno);
275 }
276
277 static void
278 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
279 {
280   int off, rem, size, req;
281   struct lq_hello_header *head;
282   struct lq_hello_info_header *info_head;
283   struct lq_hello_neighbor *neigh;
284   unsigned char *buff;
285   int is_first;
286   int i, j;
287
288   if (lq_hello == NULL || outif == NULL)
289     return;
290
291   // leave space for the OLSR header
292
293   off = common_size();
294
295   // initialize the LQ_HELLO header
296
297   head = (struct lq_hello_header *)(msg_buffer + off);
298
299   head->reserved = 0;
300   head->htime = double_to_me(lq_hello->htime);
301   head->will = lq_hello->will; 
302
303   // 'off' is the offset of the byte following the LQ_HELLO header
304
305   off += sizeof (struct lq_hello_header);
306
307   // our work buffer starts at 'off'...
308
309   buff = msg_buffer + off;
310
311   // ... that's why we start with a 'size' of 0 and subtract 'off' from
312   // the remaining bytes in the output buffer
313
314   size = 0;
315   rem = net_outbuffer_bytes_left(outif) - off;
316
317   // initially, we want to put at least an info header, an IP address,
318   // and the corresponding link quality into the message
319
320   // force signed comparison
321
322   if (rem < (int)(sizeof (struct lq_hello_info_header) + ipsize + 4))
323   {
324     net_output(outif);
325
326     rem = net_outbuffer_bytes_left(outif) - off;
327   }
328
329   info_head = NULL;
330
331   // iterate through all neighbor types ('i') and all link types ('j')
332
333   for (i = 0; i <= MAX_NEIGH; i++) 
334     {
335       for(j = 0; j <= MAX_LINK; j++)
336         {
337           if(j == HIDE_LINK)
338             continue;
339
340           is_first = 1;
341
342           // loop through neighbors
343
344           for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
345             {  
346               if (neigh->neigh_type != i || neigh->link_type != j)
347                 continue;
348
349               // we need space for an IP address plus link quality
350               // information
351
352               req = ipsize + 4;
353
354               // no, we also need space for an info header, as this is the
355               // first neighbor with the current neighor type and link type
356
357               if (is_first != 0)
358                 req += sizeof (struct lq_hello_info_header);
359
360               // we do not have enough space left
361
362               // force signed comparison
363
364               if ((int)(size + req) > rem)
365                 {
366                   // finalize the OLSR header
367
368                   lq_hello->comm.size = size + off;
369
370                   serialize_common((struct olsr_common *)lq_hello);
371
372                   // finalize the info header
373
374                   info_head->size =
375                     ntohs(buff + size - (unsigned char *)info_head);
376                               
377                   // output packet
378
379                   net_outbuffer_push(outif, msg_buffer, size + off);
380
381                   net_output(outif);
382
383                   // move to the beginning of the buffer
384
385                   size = 0;
386                   rem = net_outbuffer_bytes_left(outif) - off;
387
388                   // we need a new info header
389
390                   is_first = 1;
391                 }
392
393               // create a new info header
394
395               if (is_first != 0)
396                 {
397                   info_head = (struct lq_hello_info_header *)(buff + size);
398                   size += sizeof (struct lq_hello_info_header);
399
400                   info_head->reserved = 0;
401                   info_head->link_code = CREATE_LINK_CODE(i, j);
402                 }
403
404               // add the current neighbor's IP address
405
406               COPY_IP(buff + size, &neigh->addr);
407               size += ipsize;
408
409               // add the corresponding link quality
410
411               buff[size++] = (unsigned char)(neigh->link_quality * 255);
412               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
413
414               // pad
415
416               buff[size++] = 0;
417               buff[size++] = 0;
418
419               is_first = 0;
420             }
421
422           // finalize the info header, if there are any neighbors with the
423           // current neighbor type and link type
424
425           if (is_first == 0)
426             info_head->size = ntohs(buff + size - (unsigned char *)info_head);
427         }
428     }
429
430   // finalize the OLSR header
431
432   lq_hello->comm.size = size + off;
433
434   serialize_common((struct olsr_common *)lq_hello);
435
436   // move the message to the output buffer
437
438   net_outbuffer_push(outif, msg_buffer, size + off);
439 }
440
441 static void
442 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
443 {
444   int off, rem, size;
445   struct lq_tc_header *head;
446   struct lq_tc_neighbor *neigh;
447   unsigned char *buff;
448
449   if (lq_tc == NULL || outif == NULL)
450     return;
451
452   // leave space for the OLSR header
453
454   off = common_size();
455
456   // initialize the LQ_TC header
457
458   head = (struct lq_tc_header *)(msg_buffer + off);
459
460   head->ansn = htons(lq_tc->ansn);
461   head->reserved = 0;
462
463   // 'off' is the offset of the byte following the LQ_TC header
464
465   off += sizeof (struct lq_tc_header);
466
467   // our work buffer starts at 'off'...
468
469   buff = msg_buffer + off;
470
471   // ... that's why we start with a 'size' of 0 and subtract 'off' from
472   // the remaining bytes in the output buffer
473
474   size = 0;
475   rem = net_outbuffer_bytes_left(outif) - off;
476
477   // initially, we want to put at least an IP address and the corresponding
478   // link quality into the message
479
480   // force signed comparison
481
482   if (rem < (int)(ipsize + 4))
483   {
484     net_output(outif);
485
486     rem = net_outbuffer_bytes_left(outif) - off;
487   }
488
489   // loop through neighbors
490
491   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
492     {  
493       // we need space for an IP address plus link quality
494       // information
495
496       // force signed comparison
497
498       if ((int)(size + ipsize + 4) > rem)
499         {
500           // finalize the OLSR header
501
502           lq_tc->comm.size = size + off;
503
504           serialize_common((struct olsr_common *)lq_tc);
505
506           // output packet
507
508           net_outbuffer_push(outif, msg_buffer, size + off);
509
510           net_output(outif);
511
512           // move to the beginning of the buffer
513
514           size = 0;
515           rem = net_outbuffer_bytes_left(outif) - off;
516         }
517
518       // add the current neighbor's IP address
519
520       COPY_IP(buff + size, &neigh->main);
521       size += ipsize;
522
523       // add the corresponding link quality
524
525       buff[size++] = (unsigned char)(neigh->link_quality * 255);
526       buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
527
528       // pad
529
530       buff[size++] = 0;
531       buff[size++] = 0;
532     }
533
534   // finalize the OLSR header
535
536   lq_tc->comm.size = size + off;
537
538   serialize_common((struct olsr_common *)lq_tc);
539
540   net_outbuffer_push(outif, msg_buffer, size + off);
541 }
542
543 static void *deserialize_common(struct olsr_common *comm, void *ser)
544 {
545   struct olsr_header_v4 *olsr_head_v4;
546   struct olsr_header_v6 *olsr_head_v6;
547
548   // deserialize an IPv4 OLSR message header
549
550   if (olsr_cnf->ip_version == AF_INET)
551     {
552       olsr_head_v4 = (struct olsr_header_v4 *)ser;
553
554       comm->type = olsr_head_v4->type;
555       comm->vtime = me_to_double(olsr_head_v4->vtime);
556       comm->size = ntohs(olsr_head_v4->size);
557
558       COPY_IP(&comm->orig, &olsr_head_v4->orig);
559
560       comm->ttl = olsr_head_v4->ttl;
561       comm->hops = olsr_head_v4->hops;
562       comm->seqno = ntohs(olsr_head_v4->seqno);
563
564       return (void *)(olsr_head_v4 + 1);
565     }
566
567   // deserialize an IPv6 OLSR message header
568
569   olsr_head_v6 = (struct olsr_header_v6 *)ser;
570
571   comm->type = olsr_head_v6->type;
572   comm->vtime = me_to_double(olsr_head_v6->vtime);
573   comm->size = ntohs(olsr_head_v6->size);
574
575   COPY_IP(&comm->orig, &olsr_head_v6->orig);
576
577   comm->ttl = olsr_head_v6->ttl;
578   comm->hops = olsr_head_v6->hops;
579   comm->seqno = ntohs(olsr_head_v6->seqno);
580
581   return (void *)(olsr_head_v6 + 1);
582 }
583
584 static void
585 deserialize_lq_hello(struct lq_hello_message *lq_hello, void *ser)
586 {
587   struct lq_hello_header *head;
588   struct lq_hello_info_header *info_head;
589   unsigned char *curr, *limit, *limit2;
590   struct lq_hello_neighbor *neigh;
591   
592   lq_hello->neigh = NULL;
593
594   if (ser == NULL)
595     return;
596
597   head = (struct lq_hello_header *)
598     deserialize_common((struct olsr_common *)lq_hello, ser);
599
600   if (lq_hello->comm.type != LQ_HELLO_MESSAGE)
601     return;
602
603   limit = ((unsigned char *)ser) + lq_hello->comm.size;
604
605   lq_hello->htime = me_to_double(head->htime);
606   lq_hello->will = head->will;
607
608   lq_hello->neigh = NULL;
609
610   curr = (unsigned char *)(head + 1);
611
612   while (curr < limit)
613     {
614       info_head = (struct lq_hello_info_header *)curr;
615
616       limit2 = curr + ntohs(info_head->size);
617
618       curr = (unsigned char *)(info_head + 1);
619       
620       while (curr < limit2)
621         {
622           neigh = olsr_malloc(sizeof (struct lq_hello_neighbor),
623                               "LQ_HELLO deserialization");
624
625           COPY_IP(&neigh->addr, curr);
626           curr += ipsize;
627
628           neigh->link_quality = (double)*curr++ / 255.0;
629           neigh->neigh_link_quality = (double)*curr++ / 255.0;
630
631           curr += 2;
632
633           neigh->link_type = EXTRACT_LINK(info_head->link_code);
634           neigh->neigh_type = EXTRACT_STATUS(info_head->link_code);
635
636           neigh->next = lq_hello->neigh;
637           lq_hello->neigh = neigh;
638         }
639     }
640 }
641
642 static void
643 deserialize_lq_tc(struct lq_tc_message *lq_tc, void *ser,
644                   union olsr_ip_addr *from)
645 {
646   struct lq_tc_header *head;
647   union olsr_ip_addr *addr;
648   unsigned char *curr, *limit;
649   struct lq_tc_neighbor *neigh;
650
651   lq_tc->neigh = NULL;
652
653   if (ser == NULL)
654     return;
655
656   head = (struct lq_tc_header *)
657     deserialize_common((struct olsr_common *)lq_tc, ser);
658
659   if (lq_tc->comm.type != LQ_TC_MESSAGE)
660     return;
661
662   limit = ((unsigned char *)ser) + lq_tc->comm.size;
663
664   addr = mid_lookup_main_addr(from);
665
666   if (addr == 0)
667     COPY_IP(&lq_tc->from, from);
668
669   else
670     COPY_IP(&lq_tc->from, addr);
671
672   lq_tc->ansn =  ntohs(head->ansn);
673
674   lq_tc->neigh = NULL;
675
676   curr = (unsigned char *)(head + 1);
677
678   while (curr < limit)
679     {
680       neigh = olsr_malloc(sizeof (struct lq_tc_neighbor),
681                           "LQ_TC deserialization");
682
683       COPY_IP(&neigh->main, curr);
684       curr += ipsize;
685
686       neigh->link_quality = (double)*curr++ / 255.0;
687       neigh->neigh_link_quality = (double)*curr++ / 255.0;
688
689       curr += 2;
690
691       neigh->next = lq_tc->neigh;
692       lq_tc->neigh = neigh;
693     }
694 }
695
696 void
697 olsr_output_lq_hello(void *para)
698 {
699   struct lq_hello_message lq_hello;
700   struct interface *outif = (struct interface *)para;
701
702   // create LQ_HELLO in internal format
703
704   create_lq_hello(&lq_hello, outif);
705
706   // convert internal format into transmission format, send it
707
708   serialize_lq_hello(&lq_hello, outif);
709
710   // destroy internal format
711
712   destroy_lq_hello(&lq_hello);
713
714   if(net_output_pending(outif))
715     net_output(outif);
716 }
717
718 void
719 olsr_output_lq_tc(void *para)
720 {
721   static int prev_empty = 1;
722   struct lq_tc_message lq_tc;
723   struct interface *outif = (struct interface *)para;
724
725   // create LQ_TC in internal format
726
727   create_lq_tc(&lq_tc, outif);
728
729   // a) the message is not empty
730
731   if (lq_tc.neigh != NULL)
732     {
733       prev_empty = 0;
734
735       // convert internal format into transmission format, send it
736
737       serialize_lq_tc(&lq_tc, outif);
738     }
739
740   // b) this is the first empty message
741
742   else if (prev_empty == 0)
743     {
744       // initialize timer
745
746       send_empty_tc = GET_TIMESTAMP((max_tc_vtime * 3) * 1000);
747
748       prev_empty = 1;
749
750       // convert internal format into transmission format, send it
751
752       serialize_lq_tc(&lq_tc, outif);
753     }
754
755   // c) this is not the first empty message, send if timer hasn't fired
756
757   else if (!TIMED_OUT(send_empty_tc))
758     serialize_lq_tc(&lq_tc, outif);
759
760   // destroy internal format
761
762   destroy_lq_tc(&lq_tc);
763
764   if(net_output_pending(outif) && TIMED_OUT(fwdtimer[outif->if_nr]))
765     set_buffer_timer(outif);
766 }
767
768 static void
769 process_lq_hello(struct lq_hello_message *lq_hello, struct interface *inif,
770                  union olsr_ip_addr *from)
771 {
772   struct hello_message hello;
773   struct lq_hello_neighbor *neigh;
774   struct hello_neighbor *new_neigh;
775
776   // XXX - translation is ugly; everybody should use lq_hello_message :-)
777
778   // move the static fields from LQ_HELLO to HELLO
779
780   hello.vtime = lq_hello->comm.vtime;
781   hello.htime = lq_hello->htime;
782
783   COPY_IP(&hello.source_addr, &lq_hello->comm.orig);
784
785   hello.packet_seq_number = lq_hello->comm.seqno;
786   hello.hop_count = lq_hello->comm.hops;
787   hello.ttl = lq_hello->comm.ttl;
788   hello.willingness = lq_hello->will;
789
790   hello.neighbors = NULL;
791
792   // move all LQ_HELLO neighbours to HELLO
793
794   for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
795     {
796       // allocate HELLO neighbour
797
798       new_neigh = olsr_malloc(sizeof (struct hello_neighbor),
799                               "LQ_HELLO translation");
800
801       // copy fields
802
803       new_neigh->status = neigh->neigh_type;
804       new_neigh->link = neigh->link_type;
805       new_neigh->link_quality = neigh->link_quality;
806       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
807
808       COPY_IP(&new_neigh->address, &neigh->addr);
809
810       // queue HELLO neighbour
811
812       new_neigh->next = hello.neighbors;
813       hello.neighbors = new_neigh;
814     }
815
816   olsr_hello_tap(&hello, inif, from);
817 }
818
819 static void
820 process_lq_tc(struct lq_tc_message *lq_tc, struct interface *inif,
821               union olsr_ip_addr *from, union olsr_message *ser)
822 {
823   struct tc_message tc;
824   struct lq_tc_neighbor *neigh;
825   struct tc_mpr_addr *new_neigh;
826
827   // XXX - translation is ugly; everybody should use lq_tc_message :-)
828
829   // move the static fields from LQ_TC to TC
830
831   tc.vtime = lq_tc->comm.vtime;
832
833   COPY_IP(&tc.source_addr, &lq_tc->from);
834   COPY_IP(&tc.originator, &lq_tc->comm.orig);
835
836   tc.packet_seq_number = lq_tc->comm.seqno;
837   tc.hop_count = lq_tc->comm.hops;
838   tc.ttl = lq_tc->comm.ttl;
839   tc.ansn = lq_tc->ansn;
840
841   tc.multipoint_relay_selector_address = NULL;
842
843   // move all LQ_TC neighbours to TC
844
845   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
846     {
847       // allocate TC neighbour
848
849       new_neigh = olsr_malloc(sizeof (struct tc_mpr_addr),
850                               "LQ_TC translation");
851
852       // copy fields
853
854       new_neigh->link_quality = neigh->link_quality;
855       new_neigh->neigh_link_quality = neigh->neigh_link_quality;
856
857       COPY_IP(&new_neigh->address, &neigh->main);
858
859       // queue TC neighbour
860
861       new_neigh->next = tc.multipoint_relay_selector_address;
862       tc.multipoint_relay_selector_address = new_neigh;
863     }
864
865   olsr_tc_tap(&tc, inif, from, ser);
866 }
867
868 void
869 olsr_input_lq_hello(union olsr_message *ser,
870                     struct interface *inif,
871                     union olsr_ip_addr *from)
872 {
873   struct lq_hello_message lq_hello;
874
875   // convert received packet from transmission format into internal format
876
877   deserialize_lq_hello(&lq_hello, ser);
878
879   // process internal format
880
881   process_lq_hello(&lq_hello, inif, from);
882
883   // destroy internal format
884
885   destroy_lq_hello(&lq_hello);
886 }
887
888 void
889 olsr_input_lq_tc(union olsr_message *ser, struct interface *inif,
890                  union olsr_ip_addr *from)
891 {
892   struct lq_tc_message lq_tc;
893   
894   // convert received packet from transmission format into internal format
895
896   deserialize_lq_tc(&lq_tc, ser, from);
897
898   // process internal format
899
900   process_lq_tc(&lq_tc, inif, from, ser);
901
902   // destroy internal format
903
904   destroy_lq_tc(&lq_tc);
905 }