25f6a4ca93be7558e4319480fa18ffbc0704c1cb
[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) {
976   union olsr_ip_addr ip_addr;
977
978   if ((*curr_size + (2 * olsr_cnf->ipsize)) > *remainsize) {
979     /* Only add HNA message if it contains data */
980     if (*curr_size > OLSR_HNA_IPV4_HDRSIZE) {
981 #ifdef DEBUG
982       OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", *curr_size, *remainsize);
983 #endif /* DEBUG */
984       m->v4.olsr_msgsize = htons(*curr_size);
985       m->v4.seqno = htons(get_msg_seqno());
986       net_outbuffer_push(ifp, msg_buffer, *curr_size);
987       *curr_size = OLSR_HNA_IPV4_HDRSIZE;
988       *pair = m->v4.message.hna.hna_net;
989     }
990     net_output(ifp);
991     *remainsize = net_outbuffer_bytes_left(ifp);
992     check_buffspace(*curr_size + (2 * olsr_cnf->ipsize), *remainsize, "HNA2");
993   }
994 #ifdef DEBUG
995   OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
996 #endif /* DEBUG */
997
998   olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
999 #ifdef __linux__
1000   if (olsr_cnf->smart_gw_active && is_prefix_inetgw(&h->net)) {
1001     /* this is the default route, overwrite it with the smart gateway */
1002     olsr_modifiy_inetgw_netmask(&ip_addr, h->net.prefix_len);
1003   }
1004 #endif /* __linux__ */
1005   (*pair)->addr = h->net.prefix.v4.s_addr;
1006   (*pair)->netmask = ip_addr.v4.s_addr;
1007   *pair = &(*pair)[1];
1008   *curr_size += (2 * olsr_cnf->ipsize);
1009 }
1010
1011 /**
1012  *IP version 4
1013  *
1014  *@param ifp the interface to send on
1015  *@return nada
1016  */
1017 static bool
1018 serialize_hna4(struct interface_olsr *ifp)
1019 {
1020   uint16_t remainsize, curr_size, needsize;
1021   /* preserve existing data in output buffer */
1022   union olsr_message *m;
1023   struct hnapair *pair;
1024   struct ip_prefix_list *h;
1025
1026   /* No hna nets */
1027   if (ifp == NULL) {
1028     return false;
1029   }
1030   if (olsr_cnf->ip_version != AF_INET) {
1031     return false;
1032   }
1033   h = olsr_cnf->hna_entries;
1034   if (h == NULL) {
1035     return false;
1036   }
1037
1038   remainsize = net_outbuffer_bytes_left(ifp);
1039
1040   curr_size = OLSR_HNA_IPV4_HDRSIZE;
1041
1042   /* calculate size needed for HNA */
1043   needsize = curr_size;
1044   while (h) {
1045     needsize += olsr_cnf->ipsize*2;
1046     h = h->next;
1047   }
1048
1049   h = olsr_cnf->hna_entries;
1050
1051   /* Send pending packet if not room in buffer */
1052   if (needsize > remainsize) {
1053     net_output(ifp);
1054     remainsize = net_outbuffer_bytes_left(ifp);
1055   }
1056   check_buffspace(curr_size, remainsize, "HNA");
1057
1058   m = (union olsr_message *)msg_buffer;
1059
1060   /* Fill header */
1061   m->v4.olsr_msgtype = HNA_MESSAGE;
1062   m->v4.olsr_vtime = ifp->valtimes.hna;
1063   // olsr_msgsize
1064   m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
1065   m->v4.ttl = MAX_TTL;
1066   m->v4.hopcnt = 0;
1067   // seqno
1068
1069   pair = m->v4.message.hna.hna_net;
1070
1071   for (; h != NULL; h = h->next) {
1072     appendHNAEntry(ifp, h, &remainsize, &curr_size, m, &pair);
1073   }
1074
1075   m->v4.olsr_msgsize = htons(curr_size);
1076   m->v4.seqno = htons(get_msg_seqno());
1077
1078   net_outbuffer_push(ifp, msg_buffer, curr_size);
1079
1080   //printf("Sending HNA (%d bytes)...\n", outputsize);
1081   return false;
1082 }
1083
1084 static void appendHNA6Entry(struct interface_olsr *ifp, struct ip_prefix_list *h, uint16_t * remainsize, uint16_t * curr_size,
1085     union olsr_message *m, struct hnapair6 **pair) {
1086   union olsr_ip_addr ip_addr;
1087
1088   if ((*curr_size + (2 * olsr_cnf->ipsize)) > *remainsize) {
1089     /* Only add HNA message if it contains data */
1090     if (*curr_size > OLSR_HNA_IPV6_HDRSIZE) {
1091 #ifdef DEBUG
1092       OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", *curr_size, *remainsize);
1093 #endif /* DEBUG */
1094       m->v6.olsr_msgsize = htons(*curr_size);
1095       m->v6.seqno = htons(get_msg_seqno());
1096       net_outbuffer_push(ifp, msg_buffer, *curr_size);
1097       *curr_size = OLSR_HNA_IPV6_HDRSIZE;
1098       *pair = m->v6.message.hna.hna_net;
1099     }
1100     net_output(ifp);
1101     *remainsize = net_outbuffer_bytes_left(ifp);
1102     check_buffspace(*curr_size + (2 * olsr_cnf->ipsize), *remainsize, "HNA2");
1103   }
1104 #ifdef DEBUG
1105   OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1106 #endif /* DEBUG */
1107
1108   olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
1109 #ifdef __linux__
1110   if (olsr_cnf->smart_gw_active && is_prefix_inetgw(&h->net)) {
1111     /* this is the default gateway, so overwrite it with the smart one */
1112     olsr_modifiy_inetgw_netmask(&ip_addr, h->net.prefix_len);
1113   }
1114 #endif /* __linux__ */
1115   (*pair)->addr = h->net.prefix.v6;
1116   (*pair)->netmask = ip_addr.v6;
1117   *pair = &(*pair)[1];
1118   *curr_size += (2 * olsr_cnf->ipsize);
1119 }
1120
1121 /**
1122  *IP version 6
1123  *
1124  *@param ifp the interface to send on
1125  *@return nada
1126  */
1127 static bool
1128 serialize_hna6(struct interface_olsr *ifp)
1129 {
1130   uint16_t remainsize, curr_size, needsize;
1131   /* preserve existing data in output buffer */
1132   union olsr_message *m;
1133   struct hnapair6 *pair6;
1134   struct ip_prefix_list *h = olsr_cnf->hna_entries;
1135
1136   /* No hna nets */
1137   if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || h == NULL)
1138     return false;
1139
1140   remainsize = net_outbuffer_bytes_left(ifp);
1141
1142   curr_size = OLSR_HNA_IPV6_HDRSIZE;
1143
1144   /* calculate size needed for HNA */
1145   needsize = curr_size;
1146   while (h) {
1147     needsize += olsr_cnf->ipsize*2;
1148     h = h->next;
1149   }
1150
1151   h = olsr_cnf->hna_entries;
1152
1153   /* Send pending packet if not room in buffer */
1154   if (needsize > remainsize) {
1155     net_output(ifp);
1156     remainsize = net_outbuffer_bytes_left(ifp);
1157   }
1158   check_buffspace(curr_size, remainsize, "HNA");
1159
1160   m = (union olsr_message *)msg_buffer;
1161
1162   /* Fill header */
1163   m->v6.olsr_msgtype = HNA_MESSAGE;
1164   m->v6.olsr_vtime = ifp->valtimes.hna;
1165   // olsr_msgsize
1166   m->v6.originator = olsr_cnf->main_addr.v6;
1167   m->v6.ttl = MAX_TTL;
1168   m->v6.hopcnt = 0;
1169   // seqno
1170
1171   pair6 = m->v6.message.hna.hna_net;
1172
1173   for (; h != NULL; h = h->next) {
1174     appendHNA6Entry(ifp, h, &remainsize, &curr_size, m, &pair6);
1175   }
1176
1177   m->v6.olsr_msgsize = htons(curr_size);
1178   m->v6.seqno = htons(get_msg_seqno());
1179
1180   net_outbuffer_push(ifp, msg_buffer, curr_size);
1181   return false;
1182 }
1183
1184 /*
1185  * Local Variables:
1186  * c-basic-offset: 2
1187  * indent-tabs-mode: nil
1188  * End:
1189  */