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