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