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