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