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