Cleanups of message generation code
[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.25 2005/02/02 19:59:17 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           olsr_printf(1, "TC: Sending empty package\n");
679
680           m->v4.olsr_msgsize = htons(curr_size);
681           m->v4.seqno = htons(get_msg_seqno());
682
683           net_outbuffer_push(ifp, msg_buffer, curr_size);
684
685           found = OLSR_TRUE;
686         }
687     }
688
689   return found; 
690 }
691
692
693
694 /**
695  *IP version 6
696  *
697  *@param message the tc_message struct containing the info
698  *to send
699  *@param ifp the interface to send the message on
700  *
701  *@return nada
702  */
703
704 static olsr_bool
705 serialize_tc6(struct tc_message *message, struct interface *ifp)           
706 {
707
708   int remainsize, curr_size;
709   struct tc_mpr_addr *mprs;
710   union olsr_message *m;
711   struct tcmsg6 *tc6;
712   struct neigh_info6 *mprsaddr6; 
713   olsr_bool found = OLSR_FALSE, partial_sent = OLSR_FALSE;
714
715   if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
716     return OLSR_FALSE;
717
718   remainsize = net_outbuffer_bytes_left(ifp);
719
720   m = (union olsr_message *)msg_buffer;
721
722   tc6 = &m->v6.message.tc;
723
724   mprsaddr6 = tc6->neigh;
725   curr_size = OLSR_TC_IPV6_HDRSIZE;
726
727   /* Send pending packet if not room in buffer */
728   if(curr_size > remainsize)
729     {
730       net_output(ifp);
731       remainsize = net_outbuffer_bytes_left(ifp);
732     }
733   check_buffspace(curr_size, remainsize, "TC");
734
735   /* Fill header */
736   m->v6.olsr_vtime = ifp->valtimes.tc;
737   m->v6.olsr_msgtype = TC_MESSAGE;
738   m->v6.hopcnt = message->hop_count;
739   m->v6.ttl = message->ttl;
740   COPY_IP(&m->v6.originator, &message->originator);
741
742   /* Fill TC header */
743   tc6->ansn = htons(message->ansn);
744   tc6->reserved = 0;
745   
746
747   /*Looping trough MPR selectors */
748   for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) 
749     {
750             
751       /*If packet is to be chomped */
752       if((curr_size + ipsize) > remainsize)
753         {
754           /* Only add TC message if it contains data */
755           if(curr_size > OLSR_TC_IPV6_HDRSIZE)
756             {
757 #ifdef DEBUG
758               olsr_printf(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
759 #endif
760               m->v6.olsr_msgsize = htons(curr_size);
761               m->v6.seqno = htons(get_msg_seqno());
762
763               net_outbuffer_push(ifp, msg_buffer, curr_size);
764               mprsaddr6 = tc6->neigh;
765               curr_size = OLSR_TC_IPV6_HDRSIZE;
766               found = OLSR_FALSE;
767               partial_sent = OLSR_TRUE;
768             }
769           net_output(ifp);
770           remainsize = net_outbuffer_bytes_left(ifp);
771           check_buffspace(curr_size + ipsize, remainsize, "TC2");
772
773         }
774       found = OLSR_TRUE;
775 #ifdef DEBUG
776           olsr_printf(BMSG_DBGLVL, "\t%s\n", 
777                       olsr_ip_to_string(&mprs->address));
778 #endif
779       COPY_IP(&mprsaddr6->addr, &mprs->address);
780       curr_size += ipsize;
781
782       mprsaddr6++;
783     }
784         
785   if (found)
786     {
787       m->v6.olsr_msgsize = htons(curr_size);
788       m->v6.seqno = htons(get_msg_seqno());
789
790       net_outbuffer_push(ifp, msg_buffer, curr_size);
791
792     }
793   else
794     {
795       if((!partial_sent) && (!TIMED_OUT(send_empty_tc)))
796         {
797           olsr_printf(1, "TC: Sending empty package\n");
798             
799           m->v6.olsr_msgsize = htons(curr_size);
800           m->v6.seqno = htons(get_msg_seqno());
801
802           net_outbuffer_push(ifp, msg_buffer, curr_size);
803
804           found = OLSR_TRUE;
805         }
806     }
807
808   return found; 
809 }
810
811
812
813
814 /**
815  *IP version 4
816  *
817  *<b>NO INTERNAL BUFFER</b>
818  *@param ifp use this interfaces address as main address
819  *@return 1 on success
820  */
821
822 static olsr_bool
823 serialize_mid4(struct interface *ifp)
824 {
825   int remainsize, curr_size;
826   /* preserve existing data in output buffer */
827   union olsr_message *m;
828   struct midaddr *addrs;
829   struct interface *ifs;  
830
831   if((olsr_cnf->ip_version != AF_INET) || (!ifp) || (ifnet == NULL || ifnet->int_next == NULL))
832     return OLSR_FALSE;
833
834
835   remainsize = net_outbuffer_bytes_left(ifp);
836
837   m = (union olsr_message *)msg_buffer;
838
839   curr_size = OLSR_MID_IPV4_HDRSIZE;
840
841   /* Send pending packet if not room in buffer */
842   if(curr_size > remainsize)
843     {
844       net_output(ifp);
845       remainsize = net_outbuffer_bytes_left(ifp);
846     }
847   check_buffspace(curr_size, remainsize, "MID");
848
849   /* Fill header */
850   m->v4.hopcnt = 0;
851   m->v4.ttl = MAX_TTL;
852   /* Set main(first) address */
853   COPY_IP(&m->v4.originator, &main_addr);
854   m->v4.olsr_msgtype = MID_MESSAGE;
855   m->v4.olsr_vtime = ifp->valtimes.mid;
856  
857   addrs = m->v4.message.mid.mid_addr;
858
859   /* Don't add the main address... it's already there */
860   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
861     {
862       if(!COMP_IP(&main_addr, &ifs->ip_addr))
863         {
864
865           if((curr_size + ipsize) > remainsize)
866             {
867               /* Only add MID message if it contains data */
868               if(curr_size > OLSR_MID_IPV4_HDRSIZE)
869                 {
870 #ifdef DEBUG
871                   olsr_printf(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
872 #endif
873                   /* set size */
874                   m->v4.olsr_msgsize = htons(curr_size);
875                   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
876                   
877                   net_outbuffer_push(ifp, msg_buffer, curr_size);
878                   curr_size = OLSR_MID_IPV4_HDRSIZE;
879                   addrs = m->v4.message.mid.mid_addr;
880                 }
881               net_output(ifp);
882               remainsize = net_outbuffer_bytes_left(ifp);
883               check_buffspace(curr_size, remainsize, "MID2");
884             }
885 #ifdef DEBUG
886           olsr_printf(BMSG_DBGLVL, "\t%s(%s)\n", 
887                       olsr_ip_to_string(&ifs->ip_addr), 
888                       ifs->int_name);
889 #endif
890           
891           COPY_IP(&addrs->addr, &ifs->ip_addr);
892           addrs++;
893           curr_size += ipsize;
894         }
895     }
896
897
898   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
899   m->v4.olsr_msgsize = htons(curr_size);
900
901   //printf("Sending MID (%d bytes)...\n", outputsize);
902   net_outbuffer_push(ifp, msg_buffer, curr_size);
903
904
905   return OLSR_TRUE;
906 }
907
908
909
910 /**
911  *IP version 6
912  *
913  *<b>NO INTERNAL BUFFER</b>
914  *@param ifp use this interfaces address as main address
915  *@return 1 on success
916  */
917
918 static olsr_bool
919 serialize_mid6(struct interface *ifp)
920 {
921   int remainsize, curr_size;
922   /* preserve existing data in output buffer */
923   union olsr_message *m;
924   struct midaddr6 *addrs6;
925   struct interface *ifs;
926
927   //printf("\t\tGenerating mid on %s\n", ifn->int_name);
928
929
930   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL || ifnet->int_next == NULL))
931     return OLSR_FALSE;
932
933   remainsize = net_outbuffer_bytes_left(ifp);
934
935   curr_size = OLSR_MID_IPV6_HDRSIZE;
936
937   /* Send pending packet if not room in buffer */
938   if(curr_size > remainsize)
939     {
940       net_output(ifp);
941       remainsize = net_outbuffer_bytes_left(ifp);
942     }
943   check_buffspace(curr_size + ipsize, remainsize, "MID");
944
945   m = (union olsr_message *)msg_buffer;
946     
947   /* Build header */
948   m->v6.hopcnt = 0;
949   m->v6.ttl = MAX_TTL;      
950   m->v6.olsr_msgtype = MID_MESSAGE;
951   m->v6.olsr_vtime = ifp->valtimes.mid;
952   /* Set main(first) address */
953   COPY_IP(&m->v6.originator, &main_addr);
954    
955
956   addrs6 = m->v6.message.mid.mid_addr;
957
958   /* Don't add the main address... it's already there */
959   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
960     {
961       if(!COMP_IP(&main_addr, &ifs->ip_addr))
962         {
963           if((curr_size + ipsize) > remainsize)
964             {
965               /* Only add MID message if it contains data */
966               if(curr_size > OLSR_MID_IPV6_HDRSIZE)
967                 {
968 #ifdef DEBUG
969                   olsr_printf(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
970 #endif
971                   /* set size */
972                   m->v6.olsr_msgsize = htons(curr_size);
973                   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
974                   
975                   net_outbuffer_push(ifp, msg_buffer, curr_size);
976                   curr_size = OLSR_MID_IPV6_HDRSIZE;
977                   addrs6 = m->v6.message.mid.mid_addr;
978                 }
979               net_output(ifp);
980               remainsize = net_outbuffer_bytes_left(ifp);
981               check_buffspace(curr_size + ipsize, remainsize, "MID2");
982             }
983 #ifdef DEBUG
984                   olsr_printf(BMSG_DBGLVL, "\t%s(%s)\n", 
985                               olsr_ip_to_string(&ifs->ip_addr), 
986                               ifs->int_name);
987 #endif
988
989           COPY_IP(&addrs6->addr, &ifs->ip_addr);
990           addrs6++;
991           curr_size += ipsize;
992         }
993     }
994
995   m->v6.olsr_msgsize = htons(curr_size);
996   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
997
998   //printf("Sending MID (%d bytes)...\n", outputsize);
999   net_outbuffer_push(ifp, msg_buffer, curr_size);
1000
1001   return OLSR_TRUE;
1002 }
1003
1004
1005
1006
1007 /**
1008  *IP version 4
1009  *
1010  *@param ifp the interface to send on
1011  *@return nada
1012  */
1013 static olsr_bool
1014 serialize_hna4(struct interface *ifp)
1015 {
1016   int remainsize, curr_size;
1017   /* preserve existing data in output buffer */
1018   union olsr_message *m;
1019   struct hnapair *pair;
1020   struct hna4_entry *h = olsr_cnf->hna4_entries;
1021
1022   /* No hna nets */
1023   if((olsr_cnf->ip_version != AF_INET) || (!ifp) || h == NULL)
1024     return OLSR_FALSE;
1025     
1026   remainsize = net_outbuffer_bytes_left(ifp);
1027   
1028   curr_size = OLSR_HNA_IPV4_HDRSIZE;
1029   
1030   /* Send pending packet if not room in buffer */
1031   if(curr_size > remainsize)
1032     {
1033       net_output(ifp);
1034       remainsize = net_outbuffer_bytes_left(ifp);
1035     }
1036   check_buffspace(curr_size, remainsize, "HNA");
1037
1038   m = (union olsr_message *)msg_buffer;
1039   
1040   
1041   /* Fill header */
1042   COPY_IP(&m->v4.originator, &main_addr);
1043   m->v4.hopcnt = 0;
1044   m->v4.ttl = MAX_TTL;
1045   m->v4.olsr_msgtype = HNA_MESSAGE;
1046   m->v4.olsr_vtime = ifp->valtimes.hna;
1047   
1048
1049   pair = m->v4.message.hna.hna_net;
1050   
1051   while(h)
1052     {
1053       if((curr_size + (2 * ipsize)) > remainsize)
1054         {
1055           /* Only add HNA message if it contains data */
1056           if(curr_size > OLSR_HNA_IPV4_HDRSIZE)
1057             {
1058 #ifdef DEBUG
1059               olsr_printf(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
1060 #endif
1061               m->v4.seqno = htons(get_msg_seqno());
1062               m->v4.olsr_msgsize = htons(curr_size);
1063               net_outbuffer_push(ifp, msg_buffer, curr_size);
1064               curr_size = OLSR_HNA_IPV4_HDRSIZE;
1065               pair = m->v4.message.hna.hna_net;
1066             }
1067           net_output(ifp);
1068           remainsize = net_outbuffer_bytes_left(ifp);
1069           check_buffspace(curr_size + (2 * ipsize), remainsize, "HNA2");
1070         }
1071 #ifdef DEBUG
1072       olsr_printf(BMSG_DBGLVL, "\tNet: %s/%s\n", 
1073                   olsr_ip_to_string(&h->net),
1074                   olsr_ip_to_string(&h->netmask));
1075 #endif
1076       COPY_IP(&pair->addr, &h->net);
1077       COPY_IP(&pair->netmask, &h->netmask);
1078       pair++;
1079       curr_size += (2 * ipsize);
1080       h = h->next;
1081     }
1082
1083   m->v4.seqno = htons(get_msg_seqno());
1084   m->v4.olsr_msgsize = htons(curr_size);
1085
1086   net_outbuffer_push(ifp, msg_buffer, curr_size);
1087
1088   //printf("Sending HNA (%d bytes)...\n", outputsize);
1089   return OLSR_FALSE;
1090 }
1091
1092
1093
1094
1095
1096 /**
1097  *IP version 6
1098  *
1099  *@param ifp the interface to send on
1100  *@return nada
1101  */
1102 static olsr_bool
1103 serialize_hna6(struct interface *ifp)
1104 {
1105   int remainsize, curr_size;
1106   /* preserve existing data in output buffer */
1107   union olsr_message *m;
1108   struct hnapair6 *pair6;
1109   union olsr_ip_addr tmp_netmask;
1110   struct hna6_entry *h = olsr_cnf->hna6_entries;
1111   
1112   /* No hna nets */
1113   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || h == NULL)
1114     return OLSR_FALSE;
1115
1116     
1117   remainsize = net_outbuffer_bytes_left(ifp);
1118
1119   curr_size = OLSR_HNA_IPV6_HDRSIZE;
1120
1121   /* Send pending packet if not room in buffer */
1122   if(curr_size > remainsize)
1123     {
1124       net_output(ifp);
1125       remainsize = net_outbuffer_bytes_left(ifp);
1126     }
1127   check_buffspace(curr_size, remainsize, "HNA");
1128
1129   m = (union olsr_message *)msg_buffer;   
1130
1131   /* Fill header */
1132   COPY_IP(&m->v6.originator, &main_addr);
1133   m->v6.hopcnt = 0;
1134   m->v6.ttl = MAX_TTL;
1135   m->v6.olsr_msgtype = HNA_MESSAGE;
1136   m->v6.olsr_vtime = ifp->valtimes.hna;
1137
1138   pair6 = m->v6.message.hna.hna_net;
1139
1140
1141   while(h)
1142     {
1143       if((curr_size + (2 * ipsize)) > remainsize)
1144         {
1145           /* Only add HNA message if it contains data */
1146           if(curr_size > OLSR_HNA_IPV6_HDRSIZE)
1147             {
1148 #ifdef DEBUG
1149               olsr_printf(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
1150 #endif
1151               m->v6.seqno = htons(get_msg_seqno());
1152               m->v6.olsr_msgsize = htons(curr_size);
1153               net_outbuffer_push(ifp, msg_buffer, curr_size);
1154               curr_size = OLSR_HNA_IPV6_HDRSIZE;
1155               pair6 = m->v6.message.hna.hna_net;
1156             }
1157           net_output(ifp);
1158           remainsize = net_outbuffer_bytes_left(ifp);
1159           check_buffspace(curr_size + (2 * ipsize), remainsize, "HNA2");
1160         }
1161 #ifdef DEBUG
1162       olsr_printf(BMSG_DBGLVL, "\tNet: %s/%d\n", 
1163                   olsr_ip_to_string(&h->net),
1164                   h->prefix_len);
1165 #endif
1166       COPY_IP(&pair6->addr, &h->net);
1167       olsr_prefix_to_netmask(&tmp_netmask, h->prefix_len);
1168       COPY_IP(&pair6->netmask, &tmp_netmask);
1169       pair6++;
1170       curr_size += (2 * ipsize);
1171       h = h->next;
1172     }
1173   
1174   m->v6.olsr_msgsize = htons(curr_size);
1175   m->v6.seqno = htons(get_msg_seqno());
1176   
1177   net_outbuffer_push(ifp, msg_buffer, curr_size);
1178   
1179   //printf("Sending HNA (%d bytes)...\n", outputsize);
1180   return OLSR_FALSE;
1181
1182 }