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