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