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