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