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