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