Merge branch 'stable' of http://olsr.org/git/olsrd into stable
[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, needsize;
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   /* calculate size needed for HNA */
804   needsize = curr_size;
805   for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
806     needsize += olsr_cnf->ipsize*2;
807   }
808
809   /* Send pending packet if not room in buffer */
810   if (needsize > remainsize) {
811     net_output(ifp);
812     remainsize = net_outbuffer_bytes_left(ifp);
813   }
814   check_buffspace(curr_size, remainsize, "MID");
815
816   /* Fill header */
817   m->v4.hopcnt = 0;
818   m->v4.ttl = MAX_TTL;
819   /* Set main(first) address */
820   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
821   m->v4.olsr_msgtype = MID_MESSAGE;
822   m->v4.olsr_vtime = ifp->valtimes.mid;
823
824   addrs = m->v4.message.mid.mid_addr;
825
826   /* Don't add the main address... it's already there */
827   for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
828     if (!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr)) {
829 #ifdef DEBUG
830       struct ipaddr_str buf;
831 #endif
832
833       if ((curr_size + olsr_cnf->ipsize) > remainsize) {
834         /* Only add MID message if it contains data */
835         if (curr_size > OLSR_MID_IPV4_HDRSIZE) {
836 #ifdef DEBUG
837           OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
838 #endif
839           /* set size */
840           m->v4.olsr_msgsize = htons(curr_size);
841           m->v4.seqno = htons(get_msg_seqno()); /* seqnumber */
842
843           net_outbuffer_push(ifp, msg_buffer, curr_size);
844           curr_size = OLSR_MID_IPV4_HDRSIZE;
845           addrs = m->v4.message.mid.mid_addr;
846         }
847         net_output(ifp);
848         remainsize = net_outbuffer_bytes_left(ifp);
849         check_buffspace(curr_size, remainsize, "MID2");
850       }
851 #ifdef DEBUG
852       OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name);
853 #endif
854
855       addrs->addr = ifs->ip_addr.v4.s_addr;
856       addrs++;
857       curr_size += olsr_cnf->ipsize;
858     }
859   }
860
861   m->v4.seqno = htons(get_msg_seqno()); /* seqnumber */
862   m->v4.olsr_msgsize = htons(curr_size);
863
864   //printf("Sending MID (%d bytes)...\n", outputsize);
865   if (curr_size > OLSR_MID_IPV4_HDRSIZE)
866     net_outbuffer_push(ifp, msg_buffer, curr_size);
867
868   return true;
869 }
870
871 /**
872  *IP version 6
873  *
874  *<b>NO INTERNAL BUFFER</b>
875  *@param ifp use this interfaces address as main address
876  *@return 1 on success
877  */
878
879 static bool
880 serialize_mid6(struct interface *ifp)
881 {
882   uint16_t remainsize, curr_size, needsize;
883   /* preserve existing data in output buffer */
884   union olsr_message *m;
885   struct midaddr6 *addrs6;
886   struct interface *ifs;
887
888   //printf("\t\tGenerating mid on %s\n", ifn->int_name);
889
890   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL) || ((ifnet->int_next == NULL) && (ipequal(&olsr_cnf->main_addr, &ifnet->ip_addr))))
891     return false;
892
893   remainsize = net_outbuffer_bytes_left(ifp);
894
895   curr_size = OLSR_MID_IPV6_HDRSIZE;
896
897   /* calculate size needed for HNA */
898   needsize = curr_size;
899   for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
900     needsize += olsr_cnf->ipsize*2;
901   }
902
903   /* Send pending packet if not room in buffer */
904   if (needsize > remainsize) {
905     net_output(ifp);
906     remainsize = net_outbuffer_bytes_left(ifp);
907   }
908   check_buffspace(curr_size, remainsize, "MID");
909
910   m = (union olsr_message *)msg_buffer;
911
912   /* Build header */
913   m->v6.hopcnt = 0;
914   m->v6.ttl = MAX_TTL;
915   m->v6.olsr_msgtype = MID_MESSAGE;
916   m->v6.olsr_vtime = ifp->valtimes.mid;
917   /* Set main(first) address */
918   m->v6.originator = olsr_cnf->main_addr.v6;
919
920   addrs6 = m->v6.message.mid.mid_addr;
921
922   /* Don't add the main address... it's already there */
923   for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) {
924     if (!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr)) {
925 #ifdef DEBUG
926       struct ipaddr_str buf;
927 #endif
928       if ((curr_size + olsr_cnf->ipsize) > remainsize) {
929         /* Only add MID message if it contains data */
930         if (curr_size > OLSR_MID_IPV6_HDRSIZE) {
931 #ifdef DEBUG
932           OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
933 #endif
934           /* set size */
935           m->v6.olsr_msgsize = htons(curr_size);
936           m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */
937
938           net_outbuffer_push(ifp, msg_buffer, curr_size);
939           curr_size = OLSR_MID_IPV6_HDRSIZE;
940           addrs6 = m->v6.message.mid.mid_addr;
941         }
942         net_output(ifp);
943         remainsize = net_outbuffer_bytes_left(ifp);
944         check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
945       }
946 #ifdef DEBUG
947       OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name);
948 #endif
949
950       addrs6->addr = ifs->ip_addr.v6;
951       addrs6++;
952       curr_size += olsr_cnf->ipsize;
953     }
954   }
955
956   m->v6.olsr_msgsize = htons(curr_size);
957   m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */
958
959   //printf("Sending MID (%d bytes)...\n", outputsize);
960   if (curr_size > OLSR_MID_IPV6_HDRSIZE)
961     net_outbuffer_push(ifp, msg_buffer, curr_size);
962
963   return true;
964 }
965
966 /**
967  *IP version 4
968  *
969  *@param ifp the interface to send on
970  *@return nada
971  */
972 static bool
973 serialize_hna4(struct interface *ifp)
974 {
975   uint16_t remainsize, curr_size, needsize;
976   /* preserve existing data in output buffer */
977   union olsr_message *m;
978   struct hnapair *pair;
979   struct ip_prefix_list *h;
980
981   /* No hna nets */
982   if (ifp == NULL) {
983     return false;
984   }
985   if (olsr_cnf->ip_version != AF_INET) {
986     return false;
987   }
988   h = olsr_cnf->hna_entries;
989   if (h == NULL) {
990     return false;
991   }
992
993   remainsize = net_outbuffer_bytes_left(ifp);
994
995   curr_size = OLSR_HNA_IPV4_HDRSIZE;
996
997   /* calculate size needed for HNA */
998   needsize = curr_size;
999   while (h) {
1000     needsize += olsr_cnf->ipsize*2;
1001     h = h->next;
1002   }
1003
1004   h = olsr_cnf->hna_entries;
1005
1006   /* Send pending packet if not room in buffer */
1007   if (needsize > remainsize) {
1008     net_output(ifp);
1009     remainsize = net_outbuffer_bytes_left(ifp);
1010   }
1011   check_buffspace(curr_size, remainsize, "HNA");
1012
1013   m = (union olsr_message *)msg_buffer;
1014
1015   /* Fill header */
1016   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
1017   m->v4.hopcnt = 0;
1018   m->v4.ttl = MAX_TTL;
1019   m->v4.olsr_msgtype = HNA_MESSAGE;
1020   m->v4.olsr_vtime = ifp->valtimes.hna;
1021
1022   pair = m->v4.message.hna.hna_net;
1023
1024   for (; h != NULL; h = h->next) {
1025     union olsr_ip_addr ip_addr;
1026     if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) {
1027       /* Only add HNA message if it contains data */
1028       if (curr_size > OLSR_HNA_IPV4_HDRSIZE) {
1029 #ifdef DEBUG
1030         OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
1031 #endif
1032         m->v4.seqno = htons(get_msg_seqno());
1033         m->v4.olsr_msgsize = htons(curr_size);
1034         net_outbuffer_push(ifp, msg_buffer, curr_size);
1035         curr_size = OLSR_HNA_IPV4_HDRSIZE;
1036         pair = m->v4.message.hna.hna_net;
1037       }
1038       net_output(ifp);
1039       remainsize = net_outbuffer_bytes_left(ifp);
1040       check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
1041     }
1042 #ifdef DEBUG
1043     OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1044 #endif
1045     pair->addr = h->net.prefix.v4.s_addr;
1046     olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
1047     pair->netmask = ip_addr.v4.s_addr;
1048     pair++;
1049     curr_size += (2 * olsr_cnf->ipsize);
1050   }
1051
1052   m->v4.seqno = htons(get_msg_seqno());
1053   m->v4.olsr_msgsize = htons(curr_size);
1054
1055   net_outbuffer_push(ifp, msg_buffer, curr_size);
1056
1057   //printf("Sending HNA (%d bytes)...\n", outputsize);
1058   return false;
1059 }
1060
1061 /**
1062  *IP version 6
1063  *
1064  *@param ifp the interface to send on
1065  *@return nada
1066  */
1067 static bool
1068 serialize_hna6(struct interface *ifp)
1069 {
1070   uint16_t remainsize, curr_size, needsize;
1071   /* preserve existing data in output buffer */
1072   union olsr_message *m;
1073   struct hnapair6 *pair6;
1074   union olsr_ip_addr tmp_netmask;
1075   struct ip_prefix_list *h = olsr_cnf->hna_entries;
1076
1077   /* No hna nets */
1078   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || h == NULL)
1079     return false;
1080
1081   remainsize = net_outbuffer_bytes_left(ifp);
1082
1083   curr_size = OLSR_HNA_IPV6_HDRSIZE;
1084
1085   /* calculate size needed for HNA */
1086   needsize = curr_size;
1087   while (h) {
1088     needsize += olsr_cnf->ipsize*2;
1089     h = h->next;
1090   }
1091
1092   h = olsr_cnf->hna_entries;
1093
1094   /* Send pending packet if not room in buffer */
1095   if (needsize > remainsize) {
1096     net_output(ifp);
1097     remainsize = net_outbuffer_bytes_left(ifp);
1098   }
1099   check_buffspace(curr_size, remainsize, "HNA");
1100
1101   m = (union olsr_message *)msg_buffer;
1102
1103   /* Fill header */
1104   m->v6.originator = olsr_cnf->main_addr.v6;
1105   m->v6.hopcnt = 0;
1106   m->v6.ttl = MAX_TTL;
1107   m->v6.olsr_msgtype = HNA_MESSAGE;
1108   m->v6.olsr_vtime = ifp->valtimes.hna;
1109
1110   pair6 = m->v6.message.hna.hna_net;
1111
1112   while (h) {
1113     if ((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) {
1114       /* Only add HNA message if it contains data */
1115       if (curr_size > OLSR_HNA_IPV6_HDRSIZE) {
1116 #ifdef DEBUG
1117         OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
1118 #endif
1119         m->v6.seqno = htons(get_msg_seqno());
1120         m->v6.olsr_msgsize = htons(curr_size);
1121         net_outbuffer_push(ifp, msg_buffer, curr_size);
1122         curr_size = OLSR_HNA_IPV6_HDRSIZE;
1123         pair6 = m->v6.message.hna.hna_net;
1124       }
1125       net_output(ifp);
1126       remainsize = net_outbuffer_bytes_left(ifp);
1127       check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2");
1128     }
1129 #ifdef DEBUG
1130     OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1131 #endif
1132     pair6->addr = h->net.prefix.v6;
1133     olsr_prefix_to_netmask(&tmp_netmask, h->net.prefix_len);
1134     pair6->netmask = tmp_netmask.v6;
1135     pair6++;
1136     curr_size += (2 * olsr_cnf->ipsize);
1137     h = h->next;
1138   }
1139
1140   m->v6.olsr_msgsize = htons(curr_size);
1141   m->v6.seqno = htons(get_msg_seqno());
1142
1143   net_outbuffer_push(ifp, msg_buffer, curr_size);
1144 #if 0
1145   printf("Sending HNA (%d bytes)...\n", outputsize);
1146 #endif
1147   return false;
1148
1149 }
1150
1151 /*
1152  * Local Variables:
1153  * c-basic-offset: 2
1154  * indent-tabs-mode: nil
1155  * End:
1156  */