New configfile parser and configuration scheme integrated
[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.14 2004/10/18 13:13:36 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(olsr_cnf->ip_version)
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(olsr_cnf->ip_version)
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(olsr_cnf->ip_version)
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(olsr_cnf->ip_version)
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) || (olsr_cnf->ip_version != AF_INET))
232     return;
233
234   remainsize = net_outbuffer_bytes_left(ifp);
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(ifp);
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->valtimes.hello;
264
265   /* Fill HELLO header */
266   h->willingness = message->willingness; 
267   h->htime = ifp->hello_etime;
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                           /* Only send partial HELLO if it contains data */
319                           if(curr_size > (12 + 4))
320                             {
321                               /* Complete the headers */
322                               m->v4.seqno = htons(get_msg_seqno());
323                               m->v4.olsr_msgsize = htons(curr_size);
324                               
325                               hinfo->size = (char *)haddr - (char *)hinfo;
326                               hinfo->size = ntohs(hinfo->size);
327                               
328                               /* Send partial packet */
329                               net_outbuffer_push(ifp, msg_buffer, curr_size);
330
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
339                           net_output(ifp);                        
340                           /* Reset size and pointers */
341                           remainsize = net_outbuffer_bytes_left(ifp);
342                         }
343                       memset(&hinfo->reserved, 0, sizeof(olsr_u8_t));
344                       /* Set link and status for this group of neighbors (this is the first) */
345                       hinfo->link_code = CREATE_LINK_CODE(i, j);//j | (i<<2);
346                       //printf("(2)Setting neighbor link status: %x\n", hinfo->link_code);
347                       curr_size += 4; /* HELLO type section header */
348                     }
349
350 #ifdef DEBUG
351                   olsr_printf(5, "\tLink status of %s: ", olsr_ip_to_string(&nb->address));
352                   olsr_printf(5, "%d\n", nb->link);
353 #endif
354                   
355                   /*
356                    * If there is not enough room left 
357                    * for the data in tho outputbuffer
358                    * we must send a partial HELLO and
359                    * continue building the rest of the
360                    * data in a new HELLO message
361                    */
362                   if((curr_size + ipsize) > remainsize)
363                     {
364                       /* If we get here the message contains data
365                        * - no need to check 
366                        */
367                       /* Complete the headers */
368                       m->v4.seqno = htons(get_msg_seqno());
369                       m->v4.olsr_msgsize = htons(curr_size);
370                       
371                       hinfo->size = (char *)haddr - (char *)hinfo;
372                       hinfo->size = ntohs(hinfo->size);
373                       
374                       /* Send partial packet */
375                       net_outbuffer_push(ifp, msg_buffer, curr_size);
376                       net_output(ifp);
377                       
378                       /* Reset size and pointers */
379                       remainsize = net_outbuffer_bytes_left(ifp);
380                       curr_size = 12; /* OLSR message header */
381                       curr_size += 4; /* Hello header */
382                       
383                       h = &m->v4.message.hello;
384                       hinfo = h->hell_info;
385                       haddr = (union olsr_ip_addr *)hinfo->neigh_addr;
386                       
387                       /* Rebuild TYPE header */
388                       memset(&hinfo->reserved, 0, sizeof(olsr_u8_t));
389                       /* Set link and status for this group of neighbors (this is the first) */
390                       hinfo->link_code = CREATE_LINK_CODE(i, j);//j | (i<<2);
391                       //printf("(2)Setting neighbor link status: %x\n", hinfo->link_code);
392                       curr_size += 4; /* HELLO type section header */
393                       
394                     }
395
396                   COPY_IP(haddr, &nb->address);
397
398                   //printf("\n\n1: %d\n", (char *)haddr - packet);
399                   /*
400                    *Point to next address
401                    */
402                   haddr = (union olsr_ip_addr *)&haddr->v6.s6_addr[4];
403                   curr_size += ipsize; /* IP address added */
404
405                   //printf("\n2: %d\n\n", (char *)haddr - packet); 
406                   //printf("Ipsize: %d\n", ipsize);
407
408                   //printf("Adding neighbor %s\n", olsr_ip_to_string(&nb->address));
409    
410                 }
411     
412             }/* looping trough neighbors */
413             
414
415           if (sametype && sametype > lastpacket)
416             {
417               hinfo->size = (char *)haddr - (char *)hinfo;
418               hinfo->size = ntohs(hinfo->size);
419               hinfo = (struct hellinfo *)((char *)haddr);
420               haddr = (union olsr_ip_addr *)&hinfo->neigh_addr;
421               
422             }
423         } /* for j */
424     } /* for i*/
425      
426   m->v4.seqno = htons(get_msg_seqno());
427   m->v4.olsr_msgsize = htons(curr_size);
428   
429   net_outbuffer_push(ifp, msg_buffer, curr_size);
430
431   /*
432    * Delete the list of neighbor messages.
433    */
434      
435   nb = message->neighbors;
436      
437   while (nb)
438     {
439       prev_nb = nb;
440       nb = nb->next;
441       free(prev_nb);
442     }
443
444 }
445
446
447
448
449 /**
450  * IP version 6
451  *
452  *@param message the hello_message struct containing the info
453  *to build the hello message from.
454  *@param ifp the interface to send the message on
455  *
456  *@return nada
457  */
458
459
460 static void
461 hello_build6(struct hello_message *message, struct interface *ifp)
462 {
463   int remainsize, curr_size;
464   struct hello_neighbor *nb, *prev_nb;
465   union olsr_message *m;
466   struct hellomsg6 *h6;
467   struct hellinfo6 *hinfo6;
468   union olsr_ip_addr *haddr;
469
470   int i, j, sametype;
471   int lastpacket = 0; /* number of neighbors with the same
472                          greater link status in the last packet */
473   if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
474     return;
475
476
477   remainsize = net_outbuffer_bytes_left(ifp);
478
479   //printf("HELLO build outputsize: %d\n", outputsize);
480
481   m = (union olsr_message *)msg_buffer;
482
483   curr_size = 24; /* OLSR message header */
484   curr_size += 4; /* Hello header */
485
486   /* Send pending packet if not room in buffer */
487   if(curr_size > remainsize)
488     {
489       net_output(ifp);
490       remainsize = net_outbuffer_bytes_left(ifp);
491     }
492
493   //printf("HELLO build outputsize: %d\n", outputsize);
494   h6 = &m->v6.message.hello;
495   hinfo6 = h6->hell_info;
496   haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
497
498
499   /* Fill message header */
500   m->v6.ttl = message->ttl;
501   m->v6.hopcnt = 0;
502   /* Set source(main) addr */
503   COPY_IP(&m->v6.originator, &main_addr);
504   m->v6.olsr_msgtype = HELLO_MESSAGE;
505
506   m->v6.olsr_vtime = ifp->valtimes.hello;
507   
508   /* Fill packet header */
509   h6->willingness = message->willingness; 
510
511   h6->htime = ifp->hello_etime;
512
513   memset(&h6->reserved, 0, sizeof(olsr_u16_t));
514   
515   
516
517   /*
518    *Loops trough all possible neighbor statuses
519    *The negbor list is grouped by status
520    */
521
522   for (i = 0; i <= MAX_NEIGH; i++) 
523     {
524       for(j = 0; j <= MAX_LINK; j++)
525         {
526           
527           
528           lastpacket = sametype = 0;
529           
530           
531           //printf("Neighbortype %d outputsize %d\n", i, outputsize);
532                   
533           /*
534            *Looping trough neighbors
535            */
536           for (nb = message->neighbors; nb != NULL; nb = nb->next) 
537             {         
538               if ((nb->status == i) && (nb->link == j))
539                 {             
540                   sametype++;
541                   if (sametype == 1)
542                     {
543                       /* Check if there is room for header + one address */
544                       if((curr_size + 4 + ipsize) > remainsize)
545                         {
546                           /* Only send partial HELLO if it contains data */
547                           if(curr_size > (24 + 4))
548                             {
549                               /* Complete the headers */
550                               m->v6.seqno = htons(get_msg_seqno());
551                               m->v6.olsr_msgsize = htons(curr_size);
552                               
553                               hinfo6->size = (char *)haddr - (char *)hinfo6;
554                               hinfo6->size = ntohs(hinfo6->size);
555                               
556                               /* Send partial packet */
557                               net_outbuffer_push(ifp, msg_buffer, curr_size);
558                               curr_size = 24; /* OLSR message header */
559                               curr_size += 4; /* Hello header */
560                               
561                               h6 = &m->v6.message.hello;
562                               hinfo6 = h6->hell_info;
563                               haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
564                             }
565                           net_output(ifp);
566                           /* Reset size and pointers */
567                           remainsize = net_outbuffer_bytes_left(ifp);
568                         }
569                       memset(&hinfo6->reserved, 0, sizeof(olsr_u8_t));
570                       /* Set link and status for this group of neighbors (this is the first) */
571                       hinfo6->link_code = CREATE_LINK_CODE(i, j);//j | (i<<2);
572                       //printf("(2)Setting neighbor link status: %x\n", hinfo->link_code);
573                       curr_size += 4; /* HELLO type section header */
574                     }
575
576 #ifdef DEBUG
577                   olsr_printf(5, "\tLink status of %s: ", olsr_ip_to_string(&nb->address));
578                   olsr_printf(5, "%d\n", nb->link);
579 #endif
580
581                   /*
582                    * If there is not enough room left 
583                    * for the data in the outputbuffer
584                    * we must send a partial HELLO and
585                    * continue building the rest of the
586                    * data in a new HELLO message
587                    */
588                   if((curr_size + ipsize) > remainsize)
589                     {
590                       /* If we get here the message contains data
591                        * - no need to check 
592                        */
593                       /* Complete the headers */
594                       m->v6.seqno = htons(get_msg_seqno());
595                       m->v6.olsr_msgsize = htons(curr_size);
596                       
597                       hinfo6->size = (char *)haddr - (char *)hinfo6;
598                       hinfo6->size = ntohs(hinfo6->size);
599                       
600                       /* Send partial packet */
601                           net_outbuffer_push(ifp, msg_buffer, curr_size);
602                       curr_size = 24; /* OLSR message header */
603                       curr_size += 4; /* Hello header */
604                       
605                       h6 = &m->v6.message.hello;
606                       hinfo6 = h6->hell_info;
607                       haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
608                       
609                       /* Rebuild TYPE header */
610                       memset(&hinfo6->reserved, 0, sizeof(olsr_u8_t));
611                       /* Set link and status for this group of neighbors (this is the first) */
612                       hinfo6->link_code = CREATE_LINK_CODE(i, j);//j | (i<<2);
613                       //printf("(2)Setting neighbor link status: %x\n", hinfo->link_code);
614                       curr_size += 4; /* HELLO type section header */
615
616                       net_output(ifp);                
617                       /* Reset size */
618                       remainsize = net_outbuffer_bytes_left(ifp);
619                       
620                     }
621
622                   COPY_IP(haddr, &nb->address);
623                   
624                   //printf("\n\n1: %d\n", (char *)haddr - packet);
625                   /*
626                    *Point to next address
627                    */
628                   haddr++;
629                   curr_size += ipsize; /* IP address added */ 
630                   //printf("\n2: %d\n\n", (char *)haddr - packet); 
631                   //printf("Ipsize: %d\n", ipsize);
632                   
633                   //printf("Adding neighbor %s\n", olsr_ip_to_string(&nb->address));
634                   
635                 }
636               
637             }/* looping trough neighbors */
638             
639           
640           if (sametype && sametype > lastpacket)
641             {
642               hinfo6->size = (char *)haddr - (char *)hinfo6;
643               hinfo6->size = ntohs(hinfo6->size);
644               hinfo6 = (struct hellinfo6 *)((char *)haddr);
645               haddr = (union olsr_ip_addr *)&hinfo6->neigh_addr;
646             }
647           
648         } /* for j */
649     } /* for i */
650
651   m->v6.seqno = htons(get_msg_seqno());
652   m->v6.olsr_msgsize = htons(curr_size);
653
654   net_outbuffer_push(ifp, msg_buffer, curr_size);
655
656   /*
657    * Delete the list of neighbor messages.
658    */
659      
660   nb = message->neighbors;
661      
662   while (nb)
663     {
664       prev_nb = nb;
665       nb = nb->next;
666       free(prev_nb);
667     }
668
669 }
670
671
672
673
674
675 /**
676  *IP version 4
677  *
678  *@param message the tc_message struct containing the info
679  *to send
680  *@param ifp the interface to send the message on
681  *
682  *@return nada
683  */
684
685 static void
686 tc_build4(struct tc_message *message, struct interface *ifp)           
687 {
688
689   int remainsize, curr_size;;
690   struct tc_mpr_addr *mprs, *prev_mprs;
691   union olsr_message *m;
692   struct tcmsg *tc;
693   struct neigh_info *mprsaddr; 
694   int found = 0, partial_sent = 0;
695
696   if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
697     return;
698
699   remainsize = net_outbuffer_bytes_left(ifp);
700
701   m = (union olsr_message *)msg_buffer;
702
703   tc = &m->v4.message.tc;
704
705
706   mprsaddr = tc->neigh;
707   curr_size = 12; /* OLSR message header */
708   curr_size += 4; /* TC header */
709
710   /* Send pending packet if not room in buffer */
711   if(curr_size > remainsize)
712     {
713       net_output(ifp);
714       remainsize = net_outbuffer_bytes_left(ifp);
715     }
716
717   /* Fill header */
718   m->v4.olsr_vtime = ifp->valtimes.tc;
719   m->v4.olsr_msgtype = TC_MESSAGE;
720   m->v4.hopcnt = message->hop_count;
721   m->v4.ttl = message->ttl;
722   COPY_IP(&m->v4.originator, &message->originator);
723
724   /* Fill TC header */
725   tc->ansn = htons(message->ansn);
726   tc->reserved = 0;
727   
728
729   /*Looping trough MPR selectors */
730   for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) 
731     {
732       /*If packet is to be chomped */
733       if((curr_size + ipsize) > remainsize)
734         {
735
736           /* Only add TC message if it contains data */
737           if(curr_size > (12 + 4 ))
738             {
739               m->v4.olsr_msgsize = htons(curr_size);
740               m->v4.seqno = htons(get_msg_seqno());
741
742               net_outbuffer_push(ifp, msg_buffer, curr_size);
743               
744               /* Reset stuff */
745               mprsaddr = tc->neigh;
746               curr_size = 12; /* OLSR message header */
747               curr_size += 4; /* TC header */
748               found = 0;
749               partial_sent = 1;
750             }
751
752           net_output(ifp);
753           remainsize = net_outbuffer_bytes_left(ifp);
754
755         }
756       found = 1;
757       
758       COPY_IP(&mprsaddr->addr, &mprs->address);
759
760       curr_size += ipsize;
761       mprsaddr++;
762     }
763
764   if (found)
765     {
766             
767       m->v4.olsr_msgsize = htons(curr_size);
768       m->v4.seqno = htons(get_msg_seqno());
769       
770       net_outbuffer_push(ifp, msg_buffer, curr_size);
771
772     }
773   else
774     {
775       if((!partial_sent) && (!TIMED_OUT(&send_empty_tc)))
776         {
777           olsr_printf(1, "TC: Sending empty package\n");
778
779           m->v4.olsr_msgsize = htons(curr_size);
780           m->v4.seqno = htons(get_msg_seqno());
781
782           net_outbuffer_push(ifp, msg_buffer, curr_size);
783
784         }
785     }
786
787
788   /*
789    * Delete the list of mprs messages
790    */
791         
792   mprs = message->multipoint_relay_selector_address;
793         
794   while (mprs)
795     {
796       prev_mprs = mprs;
797       mprs = mprs->next;
798       free(prev_mprs);
799     }
800         
801         
802 }
803
804
805
806
807 /**
808  *IP version 6
809  *
810  *@param message the tc_message struct containing the info
811  *to send
812  *@param ifp the interface to send the message on
813  *
814  *@return nada
815  */
816
817 static void
818 tc_build6(struct tc_message *message, struct interface *ifp)           
819 {
820
821   int remainsize, curr_size;;
822   struct tc_mpr_addr *mprs, *prev_mprs;
823   union olsr_message *m;
824   struct tcmsg6 *tc6;
825   struct neigh_info6 *mprsaddr6; 
826   int found = 0, partial_sent = 0;
827
828   if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
829     return;
830
831   remainsize = net_outbuffer_bytes_left(ifp);
832
833   m = (union olsr_message *)msg_buffer;
834
835   tc6 = &m->v6.message.tc;
836
837   mprsaddr6 = tc6->neigh;
838   curr_size = 24; /* OLSR message header */
839   curr_size += 4; /* TC header */
840
841   /* Send pending packet if not room in buffer */
842   if(curr_size > remainsize)
843     {
844       net_output(ifp);
845       remainsize = net_outbuffer_bytes_left(ifp);
846     }
847
848   /* Fill header */
849   m->v6.olsr_vtime = ifp->valtimes.tc;
850   m->v6.olsr_msgtype = TC_MESSAGE;
851   m->v6.hopcnt = message->hop_count;
852   m->v6.ttl = message->ttl;
853   COPY_IP(&m->v6.originator, &message->originator);
854
855   /* Fill TC header */
856   tc6->ansn = htons(message->ansn);
857   tc6->reserved = 0;
858   
859
860   /*Looping trough MPR selectors */
861   for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) 
862     {
863             
864       /*If packet is to be chomped */
865       if((curr_size + ipsize) > remainsize)
866         {
867           /* Only add TC message if it contains data */
868           if(curr_size > (24 + 4 ))
869             {
870               m->v6.olsr_msgsize = htons(curr_size);
871               m->v6.seqno = htons(get_msg_seqno());
872
873               net_outbuffer_push(ifp, msg_buffer, curr_size);
874               mprsaddr6 = tc6->neigh;
875               curr_size = 24; /* OLSR message header */
876               curr_size += 4; /* TC header */
877               found = 0;
878               partial_sent = 1;
879             }
880           net_output(ifp);
881           remainsize = net_outbuffer_bytes_left(ifp);
882                 
883
884         }
885       found = 1;
886
887       //printf("mprsaddr6 is %x\n", (char *)mprsaddr6 - packet);
888       //printf("Adding MPR-selector: %s\n", olsr_ip_to_string(&mprs->address));fflush(stdout);      
889       COPY_IP(&mprsaddr6->addr, &mprs->address);
890       curr_size += ipsize;
891
892       mprsaddr6++;
893     }
894         
895   if (found)
896     {
897       m->v6.olsr_msgsize = htons(curr_size);
898       m->v6.seqno = htons(get_msg_seqno());
899
900       net_outbuffer_push(ifp, msg_buffer, curr_size);
901
902     }
903   else
904     {
905       if((!partial_sent) && (!TIMED_OUT(&send_empty_tc)))
906         {
907           olsr_printf(1, "TC: Sending empty package\n");
908             
909           m->v6.olsr_msgsize = htons(curr_size);
910           m->v6.seqno = htons(get_msg_seqno());
911
912           net_outbuffer_push(ifp, msg_buffer, curr_size);
913         }
914     }
915
916   /*
917    * Delete the list of mprs messages
918    */
919         
920   mprs = message->multipoint_relay_selector_address;
921         
922   while (mprs)
923     {
924       prev_mprs = mprs;
925       mprs = mprs->next;
926       free(prev_mprs);
927     }
928         
929         
930 }
931
932
933
934
935 /**
936  *IP version 4
937  *
938  *<b>NO INTERNAL BUFFER</b>
939  *@param ifp use this interfaces address as main address
940  *@return 1 on success
941  */
942
943 static void
944 mid_build4(struct interface *ifp)
945 {
946   int remainsize, curr_size;
947   /* preserve existing data in output buffer */
948   union olsr_message *m;
949   struct midaddr *addrs;
950   struct interface *ifs;  
951
952   if((olsr_cnf->ip_version != AF_INET) || (!ifp) || (nbinterf <= 1))
953     return;
954
955
956   remainsize = net_outbuffer_bytes_left(ifp);
957
958   m = (union olsr_message *)msg_buffer;
959
960   curr_size = 12; /* OLSR message header */
961
962   /* Send pending packet if not room in buffer */
963   if(curr_size > remainsize)
964     {
965       net_output(ifp);
966       remainsize = net_outbuffer_bytes_left(ifp);
967     }
968
969   /* Fill header */
970   m->v4.hopcnt = 0;
971   m->v4.ttl = MAX_TTL;
972   /* Set main(first) address */
973   COPY_IP(&m->v4.originator, &main_addr);
974   m->v4.olsr_msgtype = MID_MESSAGE;
975   m->v4.olsr_vtime = ifp->valtimes.mid;
976  
977   addrs = m->v4.message.mid.mid_addr;
978
979   /* Don't add the main address... it's already there */
980   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
981     {
982       if(!COMP_IP(&main_addr, &ifs->ip_addr))
983         {
984
985           if((curr_size + ipsize) > remainsize)
986             {
987               /* Only add MID message if it contains data */
988               if(curr_size > 12)
989                 {
990                   /* set size */
991                   m->v4.olsr_msgsize = htons(curr_size);
992                   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
993                   
994                   net_outbuffer_push(ifp, msg_buffer, curr_size);
995                   curr_size = 12; /* OLSR message header */
996                   addrs = m->v4.message.mid.mid_addr;
997                 }
998               net_output(ifp);
999               remainsize = net_outbuffer_bytes_left(ifp);
1000             }
1001           
1002           COPY_IP(&addrs->addr, &ifs->ip_addr);
1003           addrs++;
1004           curr_size += ipsize;
1005         }
1006     }
1007
1008
1009   m->v4.seqno = htons(get_msg_seqno());/* seqnumber */
1010   m->v4.olsr_msgsize = htons(curr_size);
1011
1012   //printf("Sending MID (%d bytes)...\n", outputsize);
1013   net_outbuffer_push(ifp, msg_buffer, curr_size);
1014
1015
1016   return;
1017 }
1018
1019
1020
1021 /**
1022  *IP version 6
1023  *
1024  *<b>NO INTERNAL BUFFER</b>
1025  *@param ifp use this interfaces address as main address
1026  *@return 1 on success
1027  */
1028
1029 static void
1030 mid_build6(struct interface *ifp)
1031 {
1032   int remainsize, curr_size;
1033   /* preserve existing data in output buffer */
1034   union olsr_message *m;
1035   struct midaddr6 *addrs6;
1036   struct interface *ifs;
1037
1038   //printf("\t\tGenerating mid on %s\n", ifn->int_name);
1039
1040
1041   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (nbinterf <= 1))
1042     return;
1043
1044   remainsize = net_outbuffer_bytes_left(ifp);
1045
1046   curr_size = 24; /* OLSR message header */
1047
1048   /* Send pending packet if not room in buffer */
1049   if(curr_size > remainsize)
1050     {
1051       net_output(ifp);
1052       remainsize = net_outbuffer_bytes_left(ifp);
1053     }
1054
1055   m = (union olsr_message *)msg_buffer;
1056     
1057   /* Build header */
1058   m->v6.hopcnt = 0;
1059   m->v6.ttl = MAX_TTL;      
1060   m->v6.olsr_msgtype = MID_MESSAGE;
1061   m->v6.olsr_vtime = ifp->valtimes.mid;
1062   /* Set main(first) address */
1063   COPY_IP(&m->v6.originator, &main_addr);
1064    
1065
1066   addrs6 = m->v6.message.mid.mid_addr;
1067
1068   /* Don't add the main address... it's already there */
1069   for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next)
1070     {
1071       if(!COMP_IP(&main_addr, &ifs->ip_addr))
1072         {
1073           if((curr_size + ipsize) > remainsize)
1074             {
1075               /* Only add MID message if it contains data */
1076               if(curr_size > 24)
1077                 {
1078                   /* set size */
1079                   m->v6.olsr_msgsize = htons(curr_size);
1080                   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
1081                   
1082                   net_outbuffer_push(ifp, msg_buffer, curr_size);
1083                   curr_size = 24; /* OLSR message header */
1084                   addrs6 = m->v6.message.mid.mid_addr;
1085                 }
1086               net_output(ifp);
1087               remainsize = net_outbuffer_bytes_left(ifp);
1088             }
1089
1090           COPY_IP(&addrs6->addr, &ifs->ip_addr);
1091           addrs6++;
1092           curr_size += ipsize;
1093         }
1094     }
1095
1096   m->v6.olsr_msgsize = htons(curr_size);
1097   m->v6.seqno = htons(get_msg_seqno());/* seqnumber */
1098
1099   //printf("Sending MID (%d bytes)...\n", outputsize);
1100   net_outbuffer_push(ifp, msg_buffer, curr_size);
1101
1102   return;
1103 }
1104
1105
1106
1107
1108 /**
1109  *IP version 4
1110  *
1111  *@param ifp the interface to send on
1112  *@return nada
1113  */
1114 static void
1115 hna_build4(struct interface *ifp)
1116 {
1117   int remainsize, curr_size;
1118   /* preserve existing data in output buffer */
1119   union olsr_message *m;
1120   struct hnapair *pair;
1121   struct local_hna_entry *h;
1122
1123   /* No hna nets */
1124   if((olsr_cnf->ip_version != AF_INET) || (!ifp) || (local_hna4_set.next == &local_hna4_set))
1125     return;
1126     
1127   remainsize = net_outbuffer_bytes_left(ifp);
1128
1129   curr_size = 12; /* OLSR message header */
1130
1131   /* Send pending packet if not room in buffer */
1132   if(curr_size > remainsize)
1133     {
1134       net_output(ifp);
1135       remainsize = net_outbuffer_bytes_left(ifp);
1136     }
1137
1138   m = (union olsr_message *)msg_buffer;
1139     
1140
1141   /* Fill header */
1142   COPY_IP(&m->v4.originator, &main_addr);
1143   m->v4.hopcnt = 0;
1144   m->v4.ttl = MAX_TTL;
1145   m->v4.olsr_msgtype = HNA_MESSAGE;
1146   m->v4.olsr_vtime = ifp->valtimes.hna;
1147
1148
1149   pair = m->v4.message.hna.hna_net;
1150
1151   for(h = local_hna4_set.next;
1152       h != &local_hna4_set;
1153       h = h->next)
1154     {
1155       if((curr_size + (2 * ipsize)) > remainsize)
1156         {
1157           /* Only add HNA message if it contains data */
1158           if(curr_size > 12)
1159             {
1160               m->v4.seqno = htons(get_msg_seqno());
1161               m->v4.olsr_msgsize = htons(curr_size);
1162               net_outbuffer_push(ifp, msg_buffer, curr_size);
1163               curr_size = 12; /* OLSR message header */
1164               pair = m->v4.message.hna.hna_net;
1165             }
1166           net_output(ifp);
1167           remainsize = net_outbuffer_bytes_left(ifp);
1168         }
1169       COPY_IP(&pair->addr, &h->A_network_addr);
1170       COPY_IP(&pair->netmask, &h->A_netmask);
1171       pair++;
1172       curr_size += (2 * ipsize);
1173     }
1174
1175   m->v4.seqno = htons(get_msg_seqno());
1176   m->v4.olsr_msgsize = htons(curr_size);
1177
1178   net_outbuffer_push(ifp, msg_buffer, curr_size);
1179
1180   //printf("Sending HNA (%d bytes)...\n", outputsize);
1181   return;
1182 }
1183
1184
1185
1186
1187
1188 /**
1189  *IP version 6
1190  *
1191  *@param ifp the interface to send on
1192  *@return nada
1193  */
1194 static void
1195 hna_build6(struct interface *ifp)
1196 {
1197   int remainsize, curr_size;
1198   /* preserve existing data in output buffer */
1199   union olsr_message *m;
1200   struct hnapair6 *pair6;
1201   union olsr_ip_addr tmp_netmask;
1202   struct local_hna_entry *h;
1203   
1204   /* No hna nets */
1205   if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (local_hna6_set.next == &local_hna6_set))
1206     return;
1207
1208     
1209   remainsize = net_outbuffer_bytes_left(ifp);
1210
1211   curr_size = 24; /* OLSR message header */
1212
1213   /* Send pending packet if not room in buffer */
1214   if(curr_size > remainsize)
1215     {
1216       net_output(ifp);
1217       remainsize = net_outbuffer_bytes_left(ifp);
1218     }
1219
1220   m = (union olsr_message *)msg_buffer;   
1221
1222   /* Fill header */
1223   COPY_IP(&m->v6.originator, &main_addr);
1224   m->v6.hopcnt = 0;
1225   m->v6.ttl = MAX_TTL;
1226   m->v6.olsr_msgtype = HNA_MESSAGE;
1227   m->v6.olsr_vtime = ifp->valtimes.hna;
1228
1229   pair6 = m->v6.message.hna.hna_net;
1230
1231
1232   for(h = local_hna6_set.next;
1233       h != &local_hna6_set;
1234       h = h->next)
1235     {
1236       if((curr_size + (2 * ipsize)) > remainsize)
1237         {
1238           /* Only add HNA message if it contains data */
1239           if(curr_size > 24)
1240             {
1241               m->v6.seqno = htons(get_msg_seqno());
1242               m->v6.olsr_msgsize = htons(curr_size);
1243               net_outbuffer_push(ifp, msg_buffer, curr_size);
1244               curr_size = 24; /* OLSR message header */
1245               pair6 = m->v6.message.hna.hna_net;
1246             }
1247           net_output(ifp);
1248           remainsize = net_outbuffer_bytes_left(ifp);
1249         }
1250
1251       //printf("Adding %s\n", olsr_ip_to_string(&h->hna_net.addr));
1252       COPY_IP(&pair6->addr, &h->A_network_addr);
1253       olsr_prefix_to_netmask(&tmp_netmask, h->A_netmask.v6);
1254       COPY_IP(&pair6->netmask, &tmp_netmask);
1255       pair6++;
1256       curr_size += (2 * ipsize);
1257     }
1258   
1259   m->v6.olsr_msgsize = htons(curr_size);
1260   m->v6.seqno = htons(get_msg_seqno());
1261
1262   net_outbuffer_push(ifp, msg_buffer, curr_size);
1263   
1264   //printf("Sending HNA (%d bytes)...\n", outputsize);
1265   return;
1266
1267 }
1268