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