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