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