Another big cleanup (brewing hereover):
[olsrd.git] / src / lq_packet.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2003, Andreas T√łnnesen (andreto@olsr.org)
4  *               2004, Thomas Lopatic (thomas@lopatic.de)
5  *               2006, for some fixups, sven-ola(gmx.de)
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions 
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright 
13  *   notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright 
15  *   notice, this list of conditions and the following disclaimer in 
16  *   the documentation and/or other materials provided with the 
17  *   distribution.
18  * * Neither the name of olsr.org, olsrd nor the names of its 
19  *   contributors may be used to endorse or promote products derived 
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Visit http://www.olsr.org for more information.
36  *
37  * If you find this software useful feel free to make a donation
38  * to the project. For more information see the website or contact
39  * the copyright holders.
40  *
41  * $Id: lq_packet.c,v 1.27 2007/08/29 22:57:17 bernd67 Exp $
42  */
43
44 #include "olsr_protocol.h"
45 #include "defs.h"
46 #include "lq_packet.h"
47 #include "interfaces.h"
48 #include "link_set.h"
49 #include "neighbor_table.h"
50 #include "mpr_selector_set.h"
51 #include "mid_set.h"
52 #include "mantissa.h"
53 #include "process_package.h" // XXX - remove
54 #include "two_hop_neighbor_table.h"
55 #include "hysteresis.h"
56 #include "olsr.h"
57 #include "build_msg.h"
58
59
60 olsr_bool lq_tc_pending = OLSR_FALSE;
61
62 static unsigned char msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE];
63
64 static inline void        pkt_get_u8(const uint8_t **p, olsr_u8_t  *var)         { *var =       *(olsr_u8_t *)(*p);   *p += sizeof(olsr_u8_t); }
65 static inline void       pkt_get_u16(const uint8_t **p, olsr_u16_t *var)         { *var = ntohs(*(olsr_u16_t *)(*p)); *p += sizeof(olsr_u16_t); }
66 static inline void       pkt_get_u32(const uint8_t **p, olsr_u32_t *var)         { *var = ntohl(*(olsr_u32_t *)(p));  *p += sizeof(olsr_u32_t); }
67 static inline void        pkt_get_s8(const uint8_t **p, olsr_8_t  *var)          { *var =       *(olsr_8_t *)(*p);    *p += sizeof(olsr_8_t); }
68 static inline void       pkt_get_s16(const uint8_t **p, olsr_16_t *var)          { *var = ntohs(*(olsr_16_t *)(*p));  *p += sizeof(olsr_16_t); }
69 static inline void       pkt_get_s32(const uint8_t **p, olsr_32_t *var)          { *var = ntohl(*(olsr_32_t *)(*p));  *p += sizeof(olsr_32_t); }
70 static inline void    pkt_get_double(const uint8_t **p, double *var)             { *var = me_to_double(**p);          *p += sizeof(olsr_u8_t); }
71 static inline void pkt_get_ipaddress(const uint8_t **p, union olsr_ip_addr *var) { COPY_IP(var, *p);                  *p += olsr_cnf->ipsize; }
72 static inline void        pkt_get_lq(const uint8_t **p, double *var)             { *var = (double)**p / 255.0;        *p += sizeof(olsr_u8_t); }
73
74 static inline void        pkt_ignore_u8(const uint8_t **p) { *p += sizeof(olsr_u8_t); }
75 static inline void       pkt_ignore_u16(const uint8_t **p) { *p += sizeof(olsr_u16_t); }
76 static inline void       pkt_ignore_u32(const uint8_t **p) { *p += sizeof(olsr_u32_t); }
77 static inline void        pkt_ignore_s8(const uint8_t **p) { *p += sizeof(olsr_8_t); }
78 static inline void       pkt_ignore_s16(const uint8_t **p) { *p += sizeof(olsr_16_t); }
79 static inline void       pkt_ignore_s32(const uint8_t **p) { *p += sizeof(olsr_32_t); }
80 static inline void pkt_ignore_ipaddress(const uint8_t **p) { *p += olsr_cnf->ipsize; }
81
82 static inline void        pkt_put_u8(uint8_t **p, const olsr_u8_t  var)         { *(olsr_u8_t *)(*p)  = var;        *p += sizeof(olsr_u8_t); }
83 static inline void       pkt_put_u16(uint8_t **p, const olsr_u16_t var)         { *(olsr_u16_t *)(*p) = htons(var); *p += sizeof(olsr_u16_t); }
84 static inline void       pkt_put_u32(uint8_t **p, const olsr_u32_t var)         { *(olsr_u32_t *)(*p) = htonl(var); *p += sizeof(olsr_u32_t); }
85 static inline void        pkt_put_s8(uint8_t **p, const olsr_8_t  var)          { *(olsr_8_t *)(*p)   = var;        *p += sizeof(olsr_8_t); }
86 static inline void       pkt_put_s16(uint8_t **p, const olsr_16_t var)          { *(olsr_16_t *)(*p)  = htons(var); *p += sizeof(olsr_16_t); }
87 static inline void       pkt_put_s32(uint8_t **p, const olsr_32_t var)          { *(olsr_32_t *)(*p)  = htonl(var); *p += sizeof(olsr_32_t); }
88 static inline void    pkt_put_double(uint8_t **p, const double var)             { **p = double_to_me(var);          *p += sizeof(olsr_u8_t); }
89 static inline void pkt_put_ipaddress(uint8_t **p, const union olsr_ip_addr var) { COPY_IP(*p, &var);                *p += olsr_cnf->ipsize; }
90 static inline void        pkt_put_lq(uint8_t **p, const double var)             { **p  = var * 255.0;               *p += sizeof(olsr_u8_t); }
91
92
93
94 static void
95 create_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
96 {
97   struct link_entry *walker;
98
99   // initialize the static fields
100
101   lq_hello->comm.type = LQ_HELLO_MESSAGE;
102   lq_hello->comm.vtime = me_to_double(outif->valtimes.hello);
103   lq_hello->comm.size = 0;
104
105   COPY_IP(&lq_hello->comm.orig, &olsr_cnf->main_addr);
106
107   lq_hello->comm.ttl = 1;
108   lq_hello->comm.hops = 0;
109   lq_hello->comm.seqno = get_msg_seqno();
110
111   lq_hello->htime = outif->hello_etime;
112   lq_hello->will = olsr_cnf->willingness;
113
114   lq_hello->neigh = NULL;
115   
116   // loop through the link set
117
118   for (walker = get_link_set(); walker != NULL; walker = walker->next)
119     {
120       // allocate a neighbour entry
121       struct lq_hello_neighbor *neigh = olsr_malloc(sizeof (struct lq_hello_neighbor), "Build LQ_HELLO");
122
123       // a) this neighbor interface IS NOT visible via the output interface
124       if(!COMP_IP(&walker->local_iface_addr, &outif->ip_addr))
125         neigh->link_type = UNSPEC_LINK;
126       
127       // b) this neighbor interface IS visible via the output interface
128
129       else
130         neigh->link_type = lookup_link_status(walker);
131
132       // set the entry's link quality
133
134       neigh->link_quality = walker->loss_link_quality;
135       neigh->neigh_link_quality = walker->neigh_link_quality;
136
137       // set the entry's neighbour type
138
139       if(walker->neighbor->is_mpr)
140         neigh->neigh_type = MPR_NEIGH;
141
142       else if (walker->neighbor->status == SYM)
143         neigh->neigh_type = SYM_NEIGH;
144
145       else if (walker->neighbor->status == NOT_SYM)
146         neigh->neigh_type = NOT_NEIGH;
147   
148       // set the entry's neighbour interface address
149
150       COPY_IP(&neigh->addr, &walker->neighbor_iface_addr);
151       
152       // queue the neighbour entry
153
154       neigh->next = lq_hello->neigh;
155       lq_hello->neigh = neigh;
156     }
157 }
158
159 static void
160 destroy_lq_hello(struct lq_hello_message *lq_hello)
161 {
162   struct lq_hello_neighbor *walker, *aux;
163
164   // loop through the queued neighbour entries and free them
165
166   for (walker = lq_hello->neigh; walker != NULL; walker = aux)
167     {
168       aux = walker->next;
169       free(walker);
170     }
171
172   lq_hello->neigh = NULL;
173 }
174
175 static void
176 create_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
177 {
178   int i;
179   static int ttl_list[] = { 1, 2, 1, 4, 1, 2, 1, 8, 1, 2, 1, 4, 1, 2, 1, MAX_TTL-1, 0};
180
181   // remember that we have generated an LQ TC message; this is
182   // checked in net_output()
183
184   lq_tc_pending = OLSR_TRUE;
185
186   // initialize the static fields
187
188   lq_tc->comm.type = LQ_TC_MESSAGE;
189   lq_tc->comm.vtime = me_to_double(outif->valtimes.tc);
190   lq_tc->comm.size = 0;
191
192   COPY_IP(&lq_tc->comm.orig, &olsr_cnf->main_addr);
193
194   if (olsr_cnf->lq_fish > 0)
195   {
196     // Sven-Ola: Too lazy to find the different iface inits. This will do it too.
197     if (outif->ttl_index >= (int)(sizeof(ttl_list) / sizeof(ttl_list[0])))
198       outif->ttl_index = 0;
199     
200     if (ttl_list[outif->ttl_index] == 0)
201       outif->ttl_index = 0;
202   
203     lq_tc->comm.ttl = ttl_list[outif->ttl_index++];
204
205     OLSR_PRINTF(3, "Creating LQ TC with TTL %d.\n", lq_tc->comm.ttl);
206   }
207
208   else
209     lq_tc->comm.ttl = MAX_TTL;
210
211   lq_tc->comm.hops = 0;
212   lq_tc->comm.seqno = get_msg_seqno();
213
214   COPY_IP(&lq_tc->from, &olsr_cnf->main_addr);
215
216   lq_tc->ansn = get_local_ansn();
217
218   lq_tc->neigh = NULL;
219  
220   // loop through all neighbours
221   
222   for(i = 0; i < HASHSIZE; i++)
223     {
224       struct neighbor_entry *walker;
225       struct tc_mpr_addr    *neigh;
226       for(walker = neighbortable[i].next; walker != &neighbortable[i];
227           walker = walker->next)
228         {
229           struct link_entry *lnk;
230           // only consider symmetric neighbours
231
232           if(walker->status != SYM)
233             continue;
234
235           // TC redundancy == 1: only consider MPRs and MPR selectors
236
237           if (olsr_cnf->tc_redundancy == 1 && !walker->is_mpr &&
238               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
239             continue;
240
241           // TC redundancy == 0: only consider MPR selectors
242           if (olsr_cnf->tc_redundancy == 0 &&
243               olsr_lookup_mprs_set(&walker->neighbor_main_addr) == NULL)
244             continue;
245
246           // allocate a neighbour entry          
247           neigh = olsr_malloc(sizeof (struct tc_mpr_addr), "Build LQ_TC");
248
249           // set the entry's main address
250
251           COPY_IP(&neigh->address, &walker->neighbor_main_addr);
252
253           // set the entry's link quality
254           lnk = get_best_link_to_neighbor(&neigh->address);
255
256           if (lnk) {
257             neigh->link_quality = lnk->loss_link_quality;
258             neigh->neigh_link_quality = lnk->neigh_link_quality;
259           }
260
261           // queue the neighbour entry
262
263           neigh->next = lq_tc->neigh;
264           lq_tc->neigh = neigh;
265         }
266     }
267 }
268
269 static void
270 destroy_lq_tc(struct lq_tc_message *lq_tc)
271 {
272   struct tc_mpr_addr *walker, *aux;
273
274   // loop through the queued neighbour entries and free them
275
276   for (walker = lq_tc->neigh; walker != NULL; walker = aux)
277     {
278       aux = walker->next;
279       free(walker);
280     }
281 }
282
283 static int common_size(void)
284 {
285   // return the size of the header shared by all OLSR messages
286
287   return (olsr_cnf->ip_version == AF_INET) ?
288     sizeof (struct olsr_header_v4) : sizeof (struct olsr_header_v6);
289 }
290
291 static void serialize_common(struct olsr_common *comm)
292 {
293   if (olsr_cnf->ip_version == AF_INET)
294     {
295       // serialize an IPv4 OLSR message header
296       struct olsr_header_v4 *olsr_head_v4 = (struct olsr_header_v4 *)msg_buffer;
297
298       olsr_head_v4->type = comm->type;
299       olsr_head_v4->vtime = double_to_me(comm->vtime);
300       olsr_head_v4->size = htons(comm->size);
301
302       COPY_IP(&olsr_head_v4->orig, &comm->orig);
303
304       olsr_head_v4->ttl = comm->ttl;
305       olsr_head_v4->hops = comm->hops;
306       olsr_head_v4->seqno = htons(comm->seqno);
307     }
308   else
309     {
310       // serialize an IPv6 OLSR message header
311       struct olsr_header_v6 *olsr_head_v6 = (struct olsr_header_v6 *)msg_buffer;
312
313       olsr_head_v6->type = comm->type;
314       olsr_head_v6->vtime = double_to_me(comm->vtime);
315       olsr_head_v6->size = htons(comm->size);
316
317       COPY_IP(&olsr_head_v6->orig, &comm->orig);
318
319       olsr_head_v6->ttl = comm->ttl;
320       olsr_head_v6->hops = comm->hops;
321       olsr_head_v6->seqno = htons(comm->seqno);
322     }
323 }
324
325 static void
326 serialize_lq_hello(struct lq_hello_message *lq_hello, struct interface *outif)
327 {
328   int rem, size, req;
329   struct lq_hello_info_header *info_head;
330   struct lq_hello_neighbor *neigh;
331   unsigned char *buff;
332   int is_first;
333   int i;
334
335   // leave space for the OLSR header
336   int off = common_size();
337
338   // initialize the LQ_HELLO header
339
340   struct lq_hello_header *head = (struct lq_hello_header *)(msg_buffer + off);
341
342   head->reserved = 0;
343   head->htime = double_to_me(lq_hello->htime);
344   head->will = lq_hello->will; 
345
346   // 'off' is the offset of the byte following the LQ_HELLO header
347
348   off += sizeof (struct lq_hello_header);
349
350   // our work buffer starts at 'off'...
351
352   buff = msg_buffer + off;
353
354   // ... that's why we start with a 'size' of 0 and subtract 'off' from
355   // the remaining bytes in the output buffer
356
357   size = 0;
358   rem = net_outbuffer_bytes_left(outif) - off;
359
360   // initially, we want to put at least an info header, an IP address,
361   // and the corresponding link quality into the message
362
363   // force signed comparison
364
365   if (rem < (int)(sizeof (struct lq_hello_info_header) + olsr_cnf->ipsize + 4))
366   {
367     net_output(outif);
368
369     rem = net_outbuffer_bytes_left(outif) - off;
370   }
371
372   info_head = NULL;
373
374   // iterate through all neighbor types ('i') and all link types ('j')
375
376   for (i = 0; i <= MAX_NEIGH; i++) 
377     {
378       static const int LINK_ORDER[] = {SYM_LINK, UNSPEC_LINK, ASYM_LINK, LOST_LINK};
379       unsigned int j;
380       for(j = 0; j < sizeof(LINK_ORDER) / sizeof(LINK_ORDER[0]); j++)
381         {
382           is_first = 1;
383
384           // loop through neighbors
385
386           for (neigh = lq_hello->neigh; neigh != NULL; neigh = neigh->next)
387             {  
388               if (neigh->neigh_type != i || neigh->link_type != LINK_ORDER[j])
389                 continue;
390
391               // we need space for an IP address plus link quality
392               // information
393
394               req = olsr_cnf->ipsize + 4;
395
396               // no, we also need space for an info header, as this is the
397               // first neighbor with the current neighor type and link type
398
399               if (is_first != 0)
400                 req += sizeof (struct lq_hello_info_header);
401
402               // we do not have enough space left
403
404               // force signed comparison
405
406               if ((int)(size + req) > rem)
407                 {
408                   // finalize the OLSR header
409
410                   lq_hello->comm.size = size + off;
411
412                   serialize_common(&lq_hello->comm);
413
414                   // finalize the info header
415
416                   info_head->size =
417                     ntohs(buff + size - (unsigned char *)info_head);
418                               
419                   // output packet
420
421                   net_outbuffer_push(outif, msg_buffer, size + off);
422
423                   net_output(outif);
424
425                   // move to the beginning of the buffer
426
427                   size = 0;
428                   rem = net_outbuffer_bytes_left(outif) - off;
429
430                   // we need a new info header
431
432                   is_first = 1;
433                 }
434
435               // create a new info header
436
437               if (is_first != 0)
438                 {
439                   info_head = (struct lq_hello_info_header *)(buff + size);
440                   size += sizeof (struct lq_hello_info_header);
441
442                   info_head->reserved = 0;
443                   info_head->link_code = CREATE_LINK_CODE(i, LINK_ORDER[j]);
444                 }
445
446               // add the current neighbor's IP address
447
448               COPY_IP(buff + size, &neigh->addr);
449               size += olsr_cnf->ipsize;
450
451               // add the corresponding link quality
452
453               buff[size++] = (unsigned char)(neigh->link_quality * 255);
454               buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
455
456               // pad
457
458               buff[size++] = 0;
459               buff[size++] = 0;
460
461               is_first = 0;
462             }
463
464           // finalize the info header, if there are any neighbors with the
465           // current neighbor type and link type
466
467           if (is_first == 0)
468             info_head->size = ntohs(buff + size - (unsigned char *)info_head);
469         }
470     }
471
472   // finalize the OLSR header
473
474   lq_hello->comm.size = size + off;
475
476   serialize_common((struct olsr_common *)lq_hello);
477
478   // move the message to the output buffer
479
480   net_outbuffer_push(outif, msg_buffer, size + off);
481 }
482
483 static void
484 serialize_lq_tc(struct lq_tc_message *lq_tc, struct interface *outif)
485 {
486   int off, rem, size;
487   struct lq_tc_header *head;
488   struct tc_mpr_addr *neigh;
489   unsigned char *buff;
490
491   // leave space for the OLSR header
492
493   off = common_size();
494
495   // initialize the LQ_TC header
496
497   head = (struct lq_tc_header *)(msg_buffer + off);
498
499   head->ansn = htons(lq_tc->ansn);
500   head->reserved = 0;
501
502   // 'off' is the offset of the byte following the LQ_TC header
503
504   off += sizeof (struct lq_tc_header);
505
506   // our work buffer starts at 'off'...
507
508   buff = msg_buffer + off;
509
510   // ... that's why we start with a 'size' of 0 and subtract 'off' from
511   // the remaining bytes in the output buffer
512
513   size = 0;
514   rem = net_outbuffer_bytes_left(outif) - off;
515
516   // initially, we want to put at least an IP address and the corresponding
517   // link quality into the message
518
519   // force signed comparison
520
521   if (rem < (int)(olsr_cnf->ipsize + 4))
522   {
523     net_output(outif);
524
525     rem = net_outbuffer_bytes_left(outif) - off;
526   }
527
528   // loop through neighbors
529
530   for (neigh = lq_tc->neigh; neigh != NULL; neigh = neigh->next)
531     {  
532       // we need space for an IP address plus link quality
533       // information
534
535       // force signed comparison
536
537       if ((int)(size + olsr_cnf->ipsize + 4) > rem)
538         {
539           // finalize the OLSR header
540
541           lq_tc->comm.size = size + off;
542
543           serialize_common((struct olsr_common *)lq_tc);
544
545           // output packet
546
547           net_outbuffer_push(outif, msg_buffer, size + off);
548
549           net_output(outif);
550
551           // move to the beginning of the buffer
552
553           size = 0;
554           rem = net_outbuffer_bytes_left(outif) - off;
555         }
556
557       // add the current neighbor's IP address
558       COPY_IP(buff + size, &neigh->address);
559       size += olsr_cnf->ipsize;
560
561       // add the corresponding link quality
562       buff[size++] = (unsigned char)(neigh->link_quality * 255);
563       buff[size++] = (unsigned char)(neigh->neigh_link_quality * 255);
564
565       // pad
566       buff[size++] = 0;
567       buff[size++] = 0;
568     }
569
570   // finalize the OLSR header
571
572   lq_tc->comm.size = size + off;
573
574   serialize_common((struct olsr_common *)lq_tc);
575
576   net_outbuffer_push(outif, msg_buffer, size + off);
577 }
578
579
580 static int
581 deserialize_lq_hello(struct hello_message *hello,
582                      const void *ser)
583 {
584     const unsigned char *limit;
585     olsr_u8_t type;
586     olsr_u16_t size;
587   
588     const unsigned char *curr = ser;
589     pkt_get_u8(&curr, &type);
590     if (type != LQ_HELLO_MESSAGE) {
591         /* No need to do anything more */
592         return 1;
593     }
594     pkt_get_double(&curr, &hello->vtime);
595     pkt_get_u16(&curr, &size);
596
597     // Sven-Ola: Check the message source addr
598     if (!olsr_validate_address((const union olsr_ip_addr *)curr)) {
599         /* No need to do anything more */
600         return 1;
601     }
602     pkt_get_ipaddress(&curr, &hello->source_addr);
603
604     pkt_get_u8(&curr, &hello->ttl);
605     pkt_get_u8(&curr, &hello->hop_count);
606     pkt_get_u16(&curr, &hello->packet_seq_number);
607     pkt_ignore_u16(&curr);
608
609     pkt_get_double(&curr, &hello->htime);
610     pkt_get_u8(&curr, &hello->willingness);
611
612     hello->neighbors = NULL;
613     limit = ser + size;
614     while (curr < limit) {
615         struct lq_hello_info_header *info_head = (struct lq_hello_info_header *)curr;
616         const unsigned char *limit2 = curr + ntohs(info_head->size);
617
618         curr = (unsigned char *)(info_head + 1);      
619         while (curr < limit2) {
620             struct hello_neighbor *neigh = olsr_malloc(sizeof (struct hello_neighbor),
621                                                        "LQ_HELLO deserialization");
622             pkt_get_ipaddress(&curr, &neigh->address);
623
624             pkt_get_lq(&curr, &neigh->link_quality);
625             pkt_get_lq(&curr, &neigh->neigh_link_quality);
626             pkt_ignore_u16(&curr);
627
628             neigh->link   = EXTRACT_LINK(info_head->link_code);
629             neigh->status = EXTRACT_STATUS(info_head->link_code);
630
631             neigh->next = hello->neighbors;
632             hello->neighbors = neigh;
633         }
634     }
635     return 0;
636 }
637
638 static int
639 deserialize_lq_tc(struct tc_message *tc,
640                   const void *ser,
641                   union olsr_ip_addr *from)
642 {
643     const union olsr_ip_addr *addr;
644     olsr_u8_t type;
645     olsr_u16_t size;
646     const unsigned char *limit;
647
648     // convert received packet from transmission format into internal format
649     const unsigned char *curr = ser;
650     pkt_get_u8(&curr, &type);
651     if (type != LQ_TC_MESSAGE) {
652         /* No need to do anything more */
653         return 1;
654     }
655     pkt_get_double(&curr, &tc->vtime);
656     pkt_get_u16(&curr, &size);
657     // Sven-Ola: Check the message source addr
658     if (!olsr_validate_address((const union olsr_ip_addr *)curr)) {
659         /* No need to do anything more */
660         return 1;
661     }
662     pkt_get_ipaddress(&curr, &tc->originator);
663
664     addr = mid_lookup_main_addr(from);
665     if (addr == NULL) {
666         addr = from;
667     }
668     // Sven-Ola: Check the message source addr
669     if (!olsr_validate_address(addr)) {
670         return 1;
671     }
672     COPY_IP(&tc->source_addr, addr);
673
674     pkt_get_u8(&curr, &tc->ttl);
675     pkt_get_u8(&curr, &tc->hop_count);
676     pkt_get_u16(&curr, &tc->packet_seq_number);
677     pkt_get_u16(&curr, &tc->ansn);
678     pkt_ignore_u16(&curr);
679
680     tc->multipoint_relay_selector_address = NULL;
681     limit = ser + size;
682     while (curr < limit) {
683         struct tc_mpr_addr *neigh;
684
685         if (!olsr_validate_address((const union olsr_ip_addr *)curr)) {
686             /* Ignore the same amount as below  */
687             pkt_ignore_ipaddress(&curr);
688             pkt_ignore_u8(&curr);
689             pkt_ignore_u8(&curr);
690             pkt_ignore_u16(&curr);
691             continue;
692         }
693
694         neigh = olsr_malloc(sizeof (struct tc_mpr_addr), "LQ_TC deserialization");
695
696         pkt_get_ipaddress(&curr, &neigh->address);
697
698         pkt_get_lq(&curr, &neigh->link_quality);
699         pkt_get_lq(&curr, &neigh->neigh_link_quality);
700         pkt_ignore_u16(&curr);
701
702         neigh->next = tc->multipoint_relay_selector_address;
703         tc->multipoint_relay_selector_address = neigh;
704     }
705     return 0;
706 }
707
708 void
709 olsr_output_lq_hello(void *para)
710 {
711   struct lq_hello_message lq_hello;
712   struct interface *outif = para;
713
714   if (outif == NULL) {
715     return;
716   }
717
718   // create LQ_HELLO in internal format
719   create_lq_hello(&lq_hello, outif);
720
721   // convert internal format into transmission format, send it
722   serialize_lq_hello(&lq_hello, outif);
723
724   // destroy internal format
725   destroy_lq_hello(&lq_hello);
726
727   if(net_output_pending(outif)) {
728     net_output(outif);
729   }
730 }
731
732 void
733 olsr_output_lq_tc(void *para)
734 {
735   static int prev_empty = 1;
736   struct lq_tc_message lq_tc;
737   struct interface *outif = para;
738
739   if (outif == NULL) {
740     return;
741   }
742   // create LQ_TC in internal format
743
744   create_lq_tc(&lq_tc, outif);
745
746   // a) the message is not empty
747
748   if (lq_tc.neigh != NULL) {
749       prev_empty = 0;
750       
751       // convert internal format into transmission format, send it
752       serialize_lq_tc(&lq_tc, outif);
753
754   // b) this is the first empty message
755   } else if (prev_empty == 0) {
756       // initialize timer
757
758       set_empty_tc_timer(GET_TIMESTAMP(olsr_cnf->max_tc_vtime * 3 * 1000));
759
760       prev_empty = 1;
761
762       // convert internal format into transmission format, send it
763
764       serialize_lq_tc(&lq_tc, outif);
765
766   // c) this is not the first empty message, send if timer hasn't fired
767   } else if (!TIMED_OUT(get_empty_tc_timer())) {
768       serialize_lq_tc(&lq_tc, outif);
769   }
770   // destroy internal format
771
772   destroy_lq_tc(&lq_tc);
773
774   if(net_output_pending(outif) && TIMED_OUT(outif->fwdtimer)) {
775     set_buffer_timer(outif);
776   }
777 }
778
779 void
780 olsr_input_lq_hello(union olsr_message *ser,
781                     struct interface *inif,
782                     union olsr_ip_addr *from)
783 {
784   struct hello_message hello;
785
786   if (ser == NULL) {
787     return;
788   }
789   if (deserialize_lq_hello(&hello, ser) != 0) {
790     return;
791   }
792   olsr_hello_tap(&hello, inif, from);
793 }
794
795 void
796 olsr_input_lq_tc(union olsr_message *ser,
797                  struct interface *inif,
798                  union olsr_ip_addr *from)
799 {
800   struct tc_message tc;
801
802   if (ser == NULL) {
803     return;
804   }
805   if (deserialize_lq_tc(&tc, ser, from) != 0) {
806     return;
807   }
808   olsr_tc_tap(&tc, inif, from, ser);
809 }