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