remove MID entries only after their validity time (this is a mostly RFC conform handl...
[olsrd.git] / src / build_msg.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
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  */
41
42 #include "build_msg.h"
43 #include "ipcalc.h"
44 #include "olsr.h"
45 #include "log.h"
46 #include "mantissa.h"
47 #include "net_olsr.h"
48
49 #define BMSG_DBGLVL 5
50
51 #define OLSR_IPV4_HDRSIZE          12
52 #define OLSR_IPV6_HDRSIZE          24
53
54 #define OLSR_HELLO_IPV4_HDRSIZE    (OLSR_IPV4_HDRSIZE + 4)
55 #define OLSR_HELLO_IPV6_HDRSIZE    (OLSR_IPV6_HDRSIZE + 4)
56 #define OLSR_TC_IPV4_HDRSIZE       (OLSR_IPV4_HDRSIZE + 4)
57 #define OLSR_TC_IPV6_HDRSIZE       (OLSR_IPV6_HDRSIZE + 4)
58 #define OLSR_MID_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
59 #define OLSR_MID_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
60 #define OLSR_HNA_IPV4_HDRSIZE      OLSR_IPV4_HDRSIZE
61 #define OLSR_HNA_IPV6_HDRSIZE      OLSR_IPV6_HDRSIZE
62
63 static void check_buffspace(int msgsize, int buffsize, const char *type);
64
65 /* All these functions share this buffer */
66
67 static uint32_t msg_buffer_align[(MAXMESSAGESIZE - OLSR_HEADERSIZE)/sizeof(uint32_t) + 1];
68 static uint8_t *msg_buffer = (uint8_t *)msg_buffer_align;
69
70 static uint32_t send_empty_tc;          /* TC empty message sending */
71
72 /* Prototypes for internal functions */
73
74 /* IPv4 */
75
76 static bool serialize_hello4(struct hello_message *, struct interface *);
77
78 static bool serialize_tc4(struct tc_message *, struct interface *);
79
80 static bool serialize_mid4(struct interface *);
81
82 static bool serialize_hna4(struct interface *);
83
84 /* IPv6 */
85
86 static bool serialize_hello6(struct hello_message *, struct interface *);
87
88 static bool serialize_tc6(struct tc_message *, struct interface *);
89
90 static bool serialize_mid6(struct interface *);
91
92 static bool serialize_hna6(struct interface *);
93
94 /**
95  * Set the timer that controls the generation of
96  * empty TC messages
97  */
98 void
99 set_empty_tc_timer(uint32_t empty_tc_new)
100 {
101   send_empty_tc = empty_tc_new;
102 }
103
104 /**
105  * Get the timer that controls the generation of
106  * empty TC messages
107  */
108 uint32_t
109 get_empty_tc_timer(void)
110 {
111   return send_empty_tc;
112 }
113
114 /**
115  * Generate HELLO packet with the contents of the parameter "message".
116  * If this won't fit in one packet, chop it up into several.
117  * Send the packet if the size of the data contained in the output buffer
118  * reach maxmessagesize. Can generate an empty HELLO packet if the
119  * neighbor table is empty.
120  *
121  *
122  *@param message the hello_message struct containing the info
123  *to build the hello message from.
124  *@param ifp the interface to send the message on
125  *
126  *@return nada
127  */
128
129 bool
130 queue_hello(struct hello_message * message, struct interface * ifp)
131 {
132 #ifdef DEBUG
133   OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name);
134 #endif
135
136   switch (olsr_cnf->ip_version) {
137   case (AF_INET):
138     return serialize_hello4(message, ifp);
139   case (AF_INET6):
140     return serialize_hello6(message, ifp);
141   }
142   return false;
143 }
144
145 /*
146  * Generate TC packet with the contents of the parameter "message".
147  * If this won't fit in one packet, chop it up into several.
148  * Send the packet if the size of the data contained in the output buffer
149  * reach maxmessagesize.
150  *
151  *@param message the tc_message struct containing the info
152  *to send
153  *@param ifp the interface to send the message on
154  *
155  *@return nada
156  */
157
158 bool
159 queue_tc(struct tc_message * message, struct interface * ifp)
160 {
161 #ifdef DEBUG
162   OLSR_PRINTF(BMSG_DBGLVL, "Building TC on %s\n-------------------\n", ifp->int_name);
163 #endif
164
165   switch (olsr_cnf->ip_version) {
166   case (AF_INET):
167     return serialize_tc4(message, ifp);
168   case (AF_INET6):
169     return serialize_tc6(message, ifp);
170   }
171   return false;
172 }
173
174 /**
175  *Build a MID message to the outputbuffer
176  *
177  *<b>NO INTERNAL BUFFER</b>
178  *@param ifn use this interfaces address as main address
179  *@return 1 on success
180  */
181
182 bool
183 queue_mid(struct interface * ifp)
184 {
185 #ifdef DEBUG
186   OLSR_PRINTF(BMSG_DBGLVL, "Building MID on %s\n-------------------\n", ifp->int_name);
187 #endif
188
189   switch (olsr_cnf->ip_version) {
190   case (AF_INET):
191     return serialize_mid4(ifp);
192   case (AF_INET6):
193     return serialize_mid6(ifp);
194   }
195   return false;
196 }
197
198 /**
199  *Builds a HNA message in the outputbuffer
200  *<b>NB! Not internal packetformat!</b>
201  *
202  *@param ifp the interface to send on
203  *@return nada
204  */
205 bool
206 queue_hna(struct interface * ifp)
207 {
208 #ifdef DEBUG
209   OLSR_PRINTF(BMSG_DBGLVL, "Building HNA on %s\n-------------------\n", ifp->int_name);
210 #endif
211
212   switch (olsr_cnf->ip_version) {
213   case (AF_INET):
214     return serialize_hna4(ifp);
215   case (AF_INET6):
216     return serialize_hna6(ifp);
217   }
218   return false;
219 }
220
221 /*
222  * Protocol specific versions
223  */
224
225 static void
226 check_buffspace(int msgsize, int buffsize, const char *type)
227 {
228   if (msgsize > buffsize) {
229     OLSR_PRINTF(1, "%s build, outputbuffer to small(%d/%u)!\n", type, msgsize, buffsize);
230     olsr_syslog(OLSR_LOG_ERR, "%s build, outputbuffer to small(%d/%u)!\n", type, msgsize, buffsize);
231     olsr_exit(__func__, EXIT_FAILURE);
232   }
233 }
234
235 /**
236  * IP version 4
237  *
238  *@param message the hello_message struct containing the info
239  *to build the hello message from.
240  *@param ifp the interface to send the message on
241  *
242  *@return nada
243  */
244
245 static bool
246 serialize_hello4(struct hello_message *message, struct interface *ifp)
247 {
248   uint16_t remainsize, curr_size;
249   struct hello_neighbor *nb;
250   union olsr_message *m;
251   struct hellomsg *h;
252   struct hellinfo *hinfo;
253   union olsr_ip_addr *haddr;
254   int i, j;
255   bool first_entry;
256
257   if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
258     return false;
259
260   remainsize = net_outbuffer_bytes_left(ifp);
261
262   m = (union olsr_message *)msg_buffer;
263
264   curr_size = OLSR_HELLO_IPV4_HDRSIZE;
265
266   /* Send pending packet if not room in buffer */
267   if (curr_size > remainsize) {
268     net_output(ifp);
269     remainsize = net_outbuffer_bytes_left(ifp);
270   }
271   /* Sanity check */
272   check_buffspace(curr_size, remainsize, "HELLO");
273
274   h = &m->v4.message.hello;
275   hinfo = h->hell_info;
276   haddr = (union olsr_ip_addr *)hinfo->neigh_addr;
277
278   /* Fill message header */
279   m->v4.ttl = message->ttl;
280   m->v4.hopcnt = 0;
281   m->v4.olsr_msgtype = HELLO_MESSAGE;
282   /* Set source(main) addr */
283   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
284
285   m->v4.olsr_vtime = ifp->valtimes.hello;
286
287   /* Fill HELLO header */
288   h->willingness = message->willingness;
289   h->htime = reltime_to_me(ifp->hello_etime);
290
291   memset(&h->reserved, 0, sizeof(uint16_t));
292
293   /*
294    *Loops trough all possible neighbor statuses
295    *The negbor list is grouped by status
296    *
297    */
298   /* Nighbor statuses */
299   for (i = 0; i <= MAX_NEIGH; i++) {
300     /* Link statuses */
301     for (j = 0; j <= MAX_LINK; j++) {
302 #ifdef DEBUG
303       struct ipaddr_str buf;
304 #endif
305
306       /* HYSTERESIS - Not adding neighbors with link type HIDE */
307
308       if (j == HIDE_LINK)
309         continue;
310
311       first_entry = true;
312
313       /* Looping trough neighbors */
314       for (nb = message->neighbors; nb != NULL; nb = nb->next) {
315         if ((nb->status != i) || (nb->link != j))
316           continue;
317
318 #ifdef DEBUG
319         OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&buf, &nb->address));
320         OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i);
321 #endif
322         /*
323          * If there is not enough room left
324          * for the data in the outputbuffer
325          * we must send a partial HELLO and
326          * continue building the rest of the
327          * data in a new HELLO message
328          *
329          * If this is the first neighbor in
330          * a group, we must check for an extra
331          * 4 bytes
332          */
333         if ((curr_size + olsr_cnf->ipsize + (first_entry ? 4 : 0)) > remainsize) {
334           /* Only send partial HELLO if it contains data */
335           if (curr_size > OLSR_HELLO_IPV4_HDRSIZE) {
336 #ifdef DEBUG
337             OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
338 #endif
339             /* Complete the headers */
340             m->v4.seqno = htons(get_msg_seqno());
341             m->v4.olsr_msgsize = htons(curr_size);
342
343             hinfo->size = htons((char *)haddr - (char *)hinfo);
344
345             /* Send partial packet */
346             net_outbuffer_push(ifp, msg_buffer, curr_size);
347
348             curr_size = OLSR_HELLO_IPV4_HDRSIZE;
349
350             h = &m->v4.message.hello;
351             hinfo = h->hell_info;
352             haddr = (union olsr_ip_addr *)hinfo->neigh_addr;
353             /* Make sure typeheader is added */
354             first_entry = true;
355           }
356
357           net_output(ifp);
358           /* Reset size and pointers */
359           remainsize = net_outbuffer_bytes_left(ifp);
360
361           /* Sanity check */
362           check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2");
363         }
364
365         if (first_entry) {
366           memset(&hinfo->reserved, 0, sizeof(uint8_t));
367           /* Set link and status for this group of neighbors (this is the first) */
368           hinfo->link_code = CREATE_LINK_CODE(i, j);
369           curr_size += 4;       /* HELLO type section header */
370         }
371
372         *haddr = nb->address;
373
374         /* Point to next address */
375         haddr += sizeof(haddr->v4);
376         curr_size += olsr_cnf->ipsize;  /* IP address added */
377
378         first_entry = false;
379       }
380
381       if (!first_entry) {
382         hinfo->size = htons((char *)haddr - (char *)hinfo);
383         hinfo = (struct hellinfo *)((char *)haddr);
384         haddr = (union olsr_ip_addr *)&hinfo->neigh_addr;
385       }
386     }                           /* for j */
387   }                             /* for i */
388
389   m->v4.seqno = htons(get_msg_seqno());
390   m->v4.olsr_msgsize = htons(curr_size);
391
392   net_outbuffer_push(ifp, msg_buffer, curr_size);
393
394   /* HELLO will always be generated */
395   return true;
396 }
397
398 /**
399  * IP version 6
400  *
401  *@param message the hello_message struct containing the info
402  *to build the hello message from.
403  *@param ifp the interface to send the message on
404  *
405  *@return nada
406  */
407
408 static bool
409 serialize_hello6(struct hello_message *message, struct interface *ifp)
410 {
411   uint16_t remainsize, curr_size;
412   struct hello_neighbor *nb;
413   union olsr_message *m;
414   struct hellomsg6 *h6;
415   struct hellinfo6 *hinfo6;
416   union olsr_ip_addr *haddr;
417   int i, j;
418   bool first_entry;
419
420   if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
421     return false;
422
423   remainsize = net_outbuffer_bytes_left(ifp);
424   m = (union olsr_message *)msg_buffer;
425
426   curr_size = OLSR_HELLO_IPV6_HDRSIZE;  /* OLSR message header */
427
428   /* Send pending packet if not room in buffer */
429   if (curr_size > remainsize) {
430     net_output(ifp);
431     remainsize = net_outbuffer_bytes_left(ifp);
432   }
433   check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO");
434
435   h6 = &m->v6.message.hello;
436   hinfo6 = h6->hell_info;
437   haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
438
439   /* Fill message header */
440   m->v6.ttl = message->ttl;
441   m->v6.hopcnt = 0;
442   /* Set source(main) addr */
443   m->v6.originator = olsr_cnf->main_addr.v6;
444   m->v6.olsr_msgtype = HELLO_MESSAGE;
445
446   m->v6.olsr_vtime = ifp->valtimes.hello;
447
448   /* Fill packet header */
449   h6->willingness = message->willingness;
450   h6->htime = reltime_to_me(ifp->hello_etime);
451   memset(&h6->reserved, 0, sizeof(uint16_t));
452
453   /*
454    *Loops trough all possible neighbor statuses
455    *The negbor list is grouped by status
456    */
457
458   for (i = 0; i <= MAX_NEIGH; i++) {
459     for (j = 0; j <= MAX_LINK; j++) {
460 #ifdef DEBUG
461       struct ipaddr_str buf;
462 #endif
463       first_entry = true;
464
465       /*
466        *Looping trough neighbors
467        */
468       for (nb = message->neighbors; nb != NULL; nb = nb->next) {
469         if ((nb->status != i) || (nb->link != j))
470           continue;
471
472 #ifdef DEBUG
473         OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&buf, &nb->address));
474         OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i);
475 #endif
476
477         /*
478          * If there is not enough room left
479          * for the data in the outputbuffer
480          * we must send a partial HELLO and
481          * continue building the rest of the
482          * data in a new HELLO message
483          *
484          * If this is the first neighbor in
485          * a group, we must check for an extra
486          * 4 bytes
487          */
488         if ((curr_size + olsr_cnf->ipsize + (first_entry ? 4 : 0)) > remainsize) {
489           /* Only send partial HELLO if it contains data */
490           if (curr_size > OLSR_HELLO_IPV6_HDRSIZE) {
491 #ifdef DEBUG
492             OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
493 #endif
494             /* Complete the headers */
495             m->v6.seqno = htons(get_msg_seqno());
496             m->v6.olsr_msgsize = htons(curr_size);
497
498             hinfo6->size = (char *)haddr - (char *)hinfo6;
499             hinfo6->size = htons(hinfo6->size);
500
501             /* Send partial packet */
502             net_outbuffer_push(ifp, msg_buffer, curr_size);
503             curr_size = OLSR_HELLO_IPV6_HDRSIZE;
504
505             h6 = &m->v6.message.hello;
506             hinfo6 = h6->hell_info;
507             haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
508             /* Make sure typeheader is added */
509             first_entry = true;
510           }
511           net_output(ifp);
512           /* Reset size and pointers */
513           remainsize = net_outbuffer_bytes_left(ifp);
514
515           check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2");
516
517         }
518
519         if (first_entry) {
520           memset(&hinfo6->reserved, 0, sizeof(uint8_t));
521           /* Set link and status for this group of neighbors (this is the first) */
522           hinfo6->link_code = CREATE_LINK_CODE(i, j);
523           curr_size += 4;       /* HELLO type section header */
524         }
525
526         *haddr = nb->address;
527
528         /* Point to next address */
529         haddr++;
530         curr_size += olsr_cnf->ipsize;  /* IP address added */
531
532         first_entry = false;
533       }                         /* looping trough neighbors */
534
535       if (!first_entry) {
536         hinfo6->size = htons((char *)haddr - (char *)hinfo6);
537         hinfo6 = (struct hellinfo6 *)((char *)haddr);
538         haddr = (union olsr_ip_addr *)&hinfo6->neigh_addr;
539       }
540
541     }                           /* for j */
542   }                             /* for i */
543
544   m->v6.seqno = htons(get_msg_seqno());
545   m->v6.olsr_msgsize = htons(curr_size);
546
547   net_outbuffer_push(ifp, msg_buffer, curr_size);
548
549   /* HELLO is always buildt */
550   return true;
551 }
552
553 /**
554  *IP version 4
555  *
556  *@param message the tc_message struct containing the info
557  *to send
558  *@param ifp the interface to send the message on
559  *
560  *@return nada
561  */
562
563 static bool
564 serialize_tc4(struct tc_message *message, struct interface *ifp)
565 {
566 #ifdef DEBUG
567   struct ipaddr_str buf;
568 #endif
569   uint16_t remainsize, curr_size;
570   struct tc_mpr_addr *mprs;
571   union olsr_message *m;
572   struct olsr_tcmsg *tc;
573   struct neigh_info *mprsaddr;
574   bool found = false, partial_sent = false;
575
576   if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
577     return false;
578
579   remainsize = net_outbuffer_bytes_left(ifp);
580
581   m = (union olsr_message *)msg_buffer;
582
583   tc = &m->v4.message.tc;
584
585   mprsaddr = tc->neigh;
586   curr_size = OLSR_TC_IPV4_HDRSIZE;
587
588   /* Send pending packet if not room in buffer */
589   if (curr_size > remainsize) {
590     net_output(ifp);
591     remainsize = net_outbuffer_bytes_left(ifp);
592   }
593   check_buffspace(curr_size, remainsize, "TC");
594
595   /* Fill header */
596   m->v4.olsr_vtime = ifp->valtimes.tc;
597   m->v4.olsr_msgtype = TC_MESSAGE;
598   m->v4.hopcnt = message->hop_count;
599   m->v4.ttl = message->ttl;
600   m->v4.originator = message->originator.v4.s_addr;
601
602   /* Fill TC header */
603   tc->ansn = htons(message->ansn);
604   tc->reserved = 0;
605
606   /*Looping trough MPR selectors */
607   for (mprs = message->multipoint_relay_selector_address; mprs != NULL; mprs = mprs->next) {
608     /*If packet is to be chomped */
609     if ((curr_size + olsr_cnf->ipsize) > remainsize) {
610
611       /* Only add TC message if it contains data */
612       if (curr_size > OLSR_TC_IPV4_HDRSIZE) {
613 #ifdef DEBUG
614         OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
615 #endif
616
617         m->v4.olsr_msgsize = htons(curr_size);
618         m->v4.seqno = htons(get_msg_seqno());
619
620         net_outbuffer_push(ifp, msg_buffer, curr_size);
621
622         /* Reset stuff */
623         mprsaddr = tc->neigh;
624         curr_size = OLSR_TC_IPV4_HDRSIZE;
625         found = false;
626         partial_sent = true;
627       }
628
629       net_output(ifp);
630       remainsize = net_outbuffer_bytes_left(ifp);
631       check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2");
632
633     }
634     found = true;
635 #ifdef DEBUG
636     OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&buf, &mprs->address));
637 #endif
638     mprsaddr->addr = mprs->address.v4.s_addr;
639     curr_size += olsr_cnf->ipsize;
640     mprsaddr++;
641   }
642
643   if (found) {
644
645     m->v4.olsr_msgsize = htons(curr_size);
646     m->v4.seqno = htons(get_msg_seqno());
647
648     net_outbuffer_push(ifp, msg_buffer, curr_size);
649
650   } else {
651     if ((!partial_sent) && (!TIMED_OUT(send_empty_tc))) {
652       if (!TIMED_OUT(send_empty_tc))
653         OLSR_PRINTF(1, "TC: Sending empty package - (%d/%d/%d/%d)\n", partial_sent, (int)send_empty_tc, (int)now_times,
654                     (int)((send_empty_tc) - now_times));
655
656       m->v4.olsr_msgsize = htons(curr_size);
657       m->v4.seqno = htons(get_msg_seqno());
658
659       net_outbuffer_push(ifp, msg_buffer, curr_size);
660
661       found = true;
662     }
663   }
664
665   return found;
666 }
667
668 /**
669  *IP version 6
670  *
671  *@param message the tc_message struct containing the info
672  *to send
673  *@param ifp the interface to send the message on
674  *
675  *@return nada
676  */
677
678 static bool
679 serialize_tc6(struct tc_message *message, struct interface *ifp)
680 {
681 #ifdef DEBUG
682   struct ipaddr_str buf;
683 #endif
684   uint16_t remainsize, curr_size;
685   struct tc_mpr_addr *mprs;
686   union olsr_message *m;
687   struct olsr_tcmsg6 *tc6;
688   struct neigh_info6 *mprsaddr6;
689   bool found = false, partial_sent = false;
690
691   if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
692     return false;
693
694   remainsize = net_outbuffer_bytes_left(ifp);
695
696   m = (union olsr_message *)msg_buffer;
697
698   tc6 = &m->v6.message.tc;
699
700   mprsaddr6 = tc6->neigh;
701   curr_size = OLSR_TC_IPV6_HDRSIZE;
702
703   /* Send pending packet if not room in buffer */
704   if (curr_size > remainsize) {
705     net_output(ifp);
706     remainsize = net_outbuffer_bytes_left(ifp);
707   }
708   check_buffspace(curr_size, remainsize, "TC");
709
710   /* Fill header */
711   m->v6.olsr_vtime = ifp->valtimes.tc;
712   m->v6.olsr_msgtype = TC_MESSAGE;
713   m->v6.hopcnt = message->hop_count;
714   m->v6.ttl = message->ttl;
715   m->v6.originator = message->originator.v6;
716
717   /* Fill TC header */
718   tc6->ansn = htons(message->ansn);
719   tc6->reserved = 0;
720
721   /*Looping trough MPR selectors */
722   for (mprs = message->multipoint_relay_selector_address; mprs != NULL; mprs = mprs->next) {
723
724     /*If packet is to be chomped */
725     if ((curr_size + olsr_cnf->ipsize) > remainsize) {
726       /* Only add TC message if it contains data */
727       if (curr_size > OLSR_TC_IPV6_HDRSIZE) {
728 #ifdef DEBUG
729         OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
730 #endif
731         m->v6.olsr_msgsize = htons(curr_size);
732         m->v6.seqno = htons(get_msg_seqno());
733
734         net_outbuffer_push(ifp, msg_buffer, curr_size);
735         mprsaddr6 = tc6->neigh;
736         curr_size = OLSR_TC_IPV6_HDRSIZE;
737         found = false;
738         partial_sent = true;
739       }
740       net_output(ifp);
741       remainsize = net_outbuffer_bytes_left(ifp);
742       check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2");
743
744     }
745     found = true;
746 #ifdef DEBUG
747     OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&buf, &mprs->address));
748 #endif
749     mprsaddr6->addr = mprs->address.v6;
750     curr_size += olsr_cnf->ipsize;
751
752     mprsaddr6++;
753   }
754
755   if (found) {
756     m->v6.olsr_msgsize = htons(curr_size);
757     m->v6.seqno = htons(get_msg_seqno());
758
759     net_outbuffer_push(ifp, msg_buffer, curr_size);
760
761   } else {
762     if ((!partial_sent) && (!TIMED_OUT(send_empty_tc))) {
763       OLSR_PRINTF(1, "TC: Sending empty package\n");
764
765       m->v6.olsr_msgsize = htons(curr_size);
766       m->v6.seqno = htons(get_msg_seqno());
767
768       net_outbuffer_push(ifp, msg_buffer, curr_size);
769
770       found = true;
771     }
772   }
773
774   return found;
775 }
776
777 /**
778  *IP version 4
779  *
780  *<b>NO INTERNAL BUFFER</b>
781  *@param ifp use this interfaces address as main address
782  *@return 1 on success
783  */
784
785 static bool
786 serialize_mid4(struct interface *ifp)
787 {
788   uint16_t remainsize, curr_size;
789   /* preserve existing data in output buffer */
790   union olsr_message *m;
791   struct midaddr *addrs;
792   struct interface *ifs;
793
794   if ((olsr_cnf->ip_version != AF_INET) || (!ifp) || (ifnet == NULL) || ((ifnet->int_next == NULL) && (ipequal(&olsr_cnf->main_addr, &ifnet->ip_addr))))
795     return false;
796
797   remainsize = net_outbuffer_bytes_left(ifp);
798
799   m = (union olsr_message *)msg_buffer;
800
801   curr_size = OLSR_MID_IPV4_HDRSIZE;
802
803   /* Send pending packet if not room in buffer */
804   if (curr_size > remainsize) {
805     net_output(ifp);
806     remainsize = net_outbuffer_bytes_left(ifp);
807   }
808   check_buffspace(curr_size, remainsize, "MID");
809
810   /* Fill header */
811   m->v4.hopcnt = 0;
812   m->v4.ttl = MAX_TTL;
813   /* Set main(first) address */
814   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
815   m->v4.olsr_msgtype = MID_MESSAGE;
816   m->v4.olsr_vtime = ifp->valtimes.mid;
817
818   addrs = m->v4.message.mid.mid_addr;
819
820   /* Don't add the main address... it's already there */
821   for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
822     if (!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr)) {
823 #ifdef DEBUG
824       struct ipaddr_str buf;
825 #endif
826
827       if ((curr_size + olsr_cnf->ipsize) > remainsize) {
828         /* Only add MID message if it contains data */
829         if (curr_size > OLSR_MID_IPV4_HDRSIZE) {
830 #ifdef DEBUG
831           OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
832 #endif
833           /* set size */
834           m->v4.olsr_msgsize = htons(curr_size);
835           m->v4.seqno = htons(get_msg_seqno()); /* seqnumber */
836
837           net_outbuffer_push(ifp, msg_buffer, curr_size);
838           curr_size = OLSR_MID_IPV4_HDRSIZE;
839           addrs = m->v4.message.mid.mid_addr;
840         }
841         net_output(ifp);
842         remainsize = net_outbuffer_bytes_left(ifp);
843         check_buffspace(curr_size, remainsize, "MID2");
844       }
845 #ifdef DEBUG
846       OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name);
847 #endif
848
849       addrs->addr = ifs->ip_addr.v4.s_addr;
850       addrs++;
851       curr_size += olsr_cnf->ipsize;
852     }
853   }
854
855   m->v4.seqno = htons(get_msg_seqno()); /* seqnumber */
856   m->v4.olsr_msgsize = htons(curr_size);
857
858   //printf("Sending MID (%d bytes)...\n", outputsize);
859   if (curr_size > OLSR_MID_IPV4_HDRSIZE)
860     net_outbuffer_push(ifp, msg_buffer, curr_size);
861
862   return true;
863 }
864
865 /**
866  *IP version 6
867  *
868  *<b>NO INTERNAL BUFFER</b>
869  *@param ifp use this interfaces address as main address
870  *@return 1 on success
871  */
872
873 static bool
874 serialize_mid6(struct interface *ifp)
875 {
876   uint16_t remainsize, curr_size;
877   /* preserve existing data in output buffer */
878   union olsr_message *m;
879   struct midaddr6 *addrs6;
880   struct interface *ifs;
881
882   //printf("\t\tGenerating mid on %s\n", ifn->int_name);
883
884   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL) || ((ifnet->int_next == NULL) && (ipequal(&olsr_cnf->main_addr, &ifnet->ip_addr))))
885     return false;
886
887   remainsize = net_outbuffer_bytes_left(ifp);
888
889   curr_size = OLSR_MID_IPV6_HDRSIZE;
890
891   /* Send pending packet if not room in buffer */
892   if (curr_size > remainsize) {
893     net_output(ifp);
894     remainsize = net_outbuffer_bytes_left(ifp);
895   }
896   check_buffspace(curr_size, remainsize, "MID");
897
898   m = (union olsr_message *)msg_buffer;
899
900   /* Build header */
901   m->v6.hopcnt = 0;
902   m->v6.ttl = MAX_TTL;
903   m->v6.olsr_msgtype = MID_MESSAGE;
904   m->v6.olsr_vtime = ifp->valtimes.mid;
905   /* Set main(first) address */
906   m->v6.originator = olsr_cnf->main_addr.v6;
907
908   addrs6 = m->v6.message.mid.mid_addr;
909
910   /* Don't add the main address... it's already there */
911   for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
912     if (!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr)) {
913 #ifdef DEBUG
914       struct ipaddr_str buf;
915 #endif
916       if ((curr_size + olsr_cnf->ipsize) > remainsize) {
917         /* Only add MID message if it contains data */
918         if (curr_size > OLSR_MID_IPV6_HDRSIZE) {
919 #ifdef DEBUG
920           OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
921 #endif
922           /* set size */
923           m->v6.olsr_msgsize = htons(curr_size);
924           m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */
925
926           net_outbuffer_push(ifp, msg_buffer, curr_size);
927           curr_size = OLSR_MID_IPV6_HDRSIZE;
928           addrs6 = m->v6.message.mid.mid_addr;
929         }
930         net_output(ifp);
931         remainsize = net_outbuffer_bytes_left(ifp);
932         check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
933       }
934 #ifdef DEBUG
935       OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name);
936 #endif
937
938       addrs6->addr = ifs->ip_addr.v6;
939       addrs6++;
940       curr_size += olsr_cnf->ipsize;
941     }
942   }
943
944   m->v6.olsr_msgsize = htons(curr_size);
945   m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */
946
947   //printf("Sending MID (%d bytes)...\n", outputsize);
948   if (curr_size > OLSR_MID_IPV6_HDRSIZE)
949     net_outbuffer_push(ifp, msg_buffer, curr_size);
950
951   return true;
952 }
953
954 /**
955  *IP version 4
956  *
957  *@param ifp the interface to send on
958  *@return nada
959  */
960 static bool
961 serialize_hna4(struct interface *ifp)
962 {
963   uint16_t remainsize, curr_size;
964   /* preserve existing data in output buffer */
965   union olsr_message *m;
966   struct hnapair *pair;
967   struct ip_prefix_list *h;
968
969   /* No hna nets */
970   if (ifp == NULL) {
971     return false;
972   }
973   if (olsr_cnf->ip_version != AF_INET) {
974     return false;
975   }
976   h = olsr_cnf->hna_entries;
977   if (h == NULL) {
978     return false;
979   }
980
981   remainsize = net_outbuffer_bytes_left(ifp);
982
983   curr_size = OLSR_HNA_IPV4_HDRSIZE;
984
985   /* Send pending packet if not room in buffer */
986   if (curr_size > remainsize) {
987     net_output(ifp);
988     remainsize = net_outbuffer_bytes_left(ifp);
989   }
990   check_buffspace(curr_size, remainsize, "HNA");
991
992   m = (union olsr_message *)msg_buffer;
993
994   /* Fill header */
995   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
996   m->v4.hopcnt = 0;
997   m->v4.ttl = MAX_TTL;
998   m->v4.olsr_msgtype = HNA_MESSAGE;
999   m->v4.olsr_vtime = ifp->valtimes.hna;
1000
1001   pair = m->v4.message.hna.hna_net;
1002
1003   for (; h != NULL; h = h->next) {
1004     union olsr_ip_addr ip_addr;
1005     if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) {
1006       /* Only add HNA message if it contains data */
1007       if (curr_size > OLSR_HNA_IPV4_HDRSIZE) {
1008 #ifdef DEBUG
1009         OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
1010 #endif
1011         m->v4.seqno = htons(get_msg_seqno());
1012         m->v4.olsr_msgsize = htons(curr_size);
1013         net_outbuffer_push(ifp, msg_buffer, curr_size);
1014         curr_size = OLSR_HNA_IPV4_HDRSIZE;
1015         pair = m->v4.message.hna.hna_net;
1016       }
1017       net_output(ifp);
1018       remainsize = net_outbuffer_bytes_left(ifp);
1019       check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
1020     }
1021 #ifdef DEBUG
1022     OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1023 #endif
1024     pair->addr = h->net.prefix.v4.s_addr;
1025     olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
1026     pair->netmask = ip_addr.v4.s_addr;
1027     pair++;
1028     curr_size += (2 * olsr_cnf->ipsize);
1029   }
1030
1031   m->v4.seqno = htons(get_msg_seqno());
1032   m->v4.olsr_msgsize = htons(curr_size);
1033
1034   net_outbuffer_push(ifp, msg_buffer, curr_size);
1035
1036   //printf("Sending HNA (%d bytes)...\n", outputsize);
1037   return false;
1038 }
1039
1040 /**
1041  *IP version 6
1042  *
1043  *@param ifp the interface to send on
1044  *@return nada
1045  */
1046 static bool
1047 serialize_hna6(struct interface *ifp)
1048 {
1049   uint16_t remainsize, curr_size;
1050   /* preserve existing data in output buffer */
1051   union olsr_message *m;
1052   struct hnapair6 *pair6;
1053   union olsr_ip_addr tmp_netmask;
1054   struct ip_prefix_list *h = olsr_cnf->hna_entries;
1055
1056   /* No hna nets */
1057   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || h == NULL)
1058     return false;
1059
1060   remainsize = net_outbuffer_bytes_left(ifp);
1061
1062   curr_size = OLSR_HNA_IPV6_HDRSIZE;
1063
1064   /* Send pending packet if not room in buffer */
1065   if (curr_size > remainsize) {
1066     net_output(ifp);
1067     remainsize = net_outbuffer_bytes_left(ifp);
1068   }
1069   check_buffspace(curr_size, remainsize, "HNA");
1070
1071   m = (union olsr_message *)msg_buffer;
1072
1073   /* Fill header */
1074   m->v6.originator = olsr_cnf->main_addr.v6;
1075   m->v6.hopcnt = 0;
1076   m->v6.ttl = MAX_TTL;
1077   m->v6.olsr_msgtype = HNA_MESSAGE;
1078   m->v6.olsr_vtime = ifp->valtimes.hna;
1079
1080   pair6 = m->v6.message.hna.hna_net;
1081
1082   while (h) {
1083     if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) {
1084       /* Only add HNA message if it contains data */
1085       if (curr_size > OLSR_HNA_IPV6_HDRSIZE) {
1086 #ifdef DEBUG
1087         OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
1088 #endif
1089         m->v6.seqno = htons(get_msg_seqno());
1090         m->v6.olsr_msgsize = htons(curr_size);
1091         net_outbuffer_push(ifp, msg_buffer, curr_size);
1092         curr_size = OLSR_HNA_IPV6_HDRSIZE;
1093         pair6 = m->v6.message.hna.hna_net;
1094       }
1095       net_output(ifp);
1096       remainsize = net_outbuffer_bytes_left(ifp);
1097       check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
1098     }
1099 #ifdef DEBUG
1100     OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1101 #endif
1102     pair6->addr = h->net.prefix.v6;
1103     olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
1104     pair6->netmask = tmp_netmask.v6;
1105     pair6++;
1106     curr_size += (2 * olsr_cnf->ipsize);
1107     h = h->next;
1108   }
1109
1110   m->v6.olsr_msgsize = htons(curr_size);
1111   m->v6.seqno = htons(get_msg_seqno());
1112
1113   net_outbuffer_push(ifp, msg_buffer, curr_size);
1114 #if 0
1115   printf("Sending HNA (%d bytes)...\n", outputsize);
1116 #endif
1117   return false;
1118
1119 }
1120
1121 /*
1122  * Local Variables:
1123  * c-basic-offset: 2
1124  * indent-tabs-mode: nil
1125  * End:
1126  */