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