3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 * Visit http://www.olsr.org for more information.
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.
42 #include "build_msg.h"
52 #define OLSR_IPV4_HDRSIZE 12
53 #define OLSR_IPV6_HDRSIZE 24
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
64 static void check_buffspace(int msgsize, int buffsize, const char *type);
66 /* All these functions share this buffer */
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;
71 static uint32_t send_empty_tc; /* TC empty message sending */
73 /* Prototypes for internal functions */
77 static bool serialize_hello4(struct hello_message *, struct interface_olsr *);
79 static bool serialize_tc4(struct tc_message *, struct interface_olsr *);
81 static bool serialize_mid4(struct interface_olsr *);
83 static bool serialize_hna4(struct ip_prefix_list *h, struct interface_olsr *, bool is_zero_bw);
87 static bool serialize_hello6(struct hello_message *, struct interface_olsr *);
89 static bool serialize_tc6(struct tc_message *, struct interface_olsr *);
91 static bool serialize_mid6(struct interface_olsr *);
93 static bool serialize_hna6(struct ip_prefix_list *h, struct interface_olsr *, bool is_zero_bw);
96 * Set the timer that controls the generation of
100 set_empty_tc_timer(uint32_t empty_tc_new)
102 send_empty_tc = empty_tc_new;
106 * Get the timer that controls the generation of
110 get_empty_tc_timer(void)
112 return send_empty_tc;
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.
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
131 queue_hello(struct hello_message * message, struct interface_olsr * ifp)
134 OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name);
137 switch (olsr_cnf->ip_version) {
139 return serialize_hello6(message, ifp);
142 return serialize_hello4(message, ifp);
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.
153 *@param message the tc_message struct containing the info
155 *@param ifp the interface to send the message on
161 queue_tc(struct tc_message * message, struct interface_olsr * ifp)
164 OLSR_PRINTF(BMSG_DBGLVL, "Building TC on %s\n-------------------\n", ifp->int_name);
167 switch (olsr_cnf->ip_version) {
169 return serialize_tc6(message, ifp);
172 return serialize_tc4(message, ifp);
178 *Build a MID message to the outputbuffer
180 *<b>NO INTERNAL BUFFER</b>
181 *@param ifp a pointer to the interface with the main address
182 *@return 1 on success
186 queue_mid(struct interface_olsr * ifp)
189 OLSR_PRINTF(BMSG_DBGLVL, "Building MID on %s\n-------------------\n", ifp->int_name);
192 switch (olsr_cnf->ip_version) {
194 return serialize_mid6(ifp);
197 return serialize_mid4(ifp);
203 *Builds a HNA message in the outputbuffer
204 *<b>NB! Not internal packetformat!</b>
206 *@param ifp the interface to send on
210 queue_hna(struct interface_olsr * ifp)
213 OLSR_PRINTF(BMSG_DBGLVL, "Building HNA on %s\n-------------------\n", ifp->int_name);
216 switch (olsr_cnf->ip_version) {
218 return serialize_hna6(olsr_cnf->hna_entries, ifp, false);
221 return serialize_hna4(olsr_cnf->hna_entries, ifp, false);
227 * Protocol specific versions
231 check_buffspace(int msgsize, int buffsize, const char *type)
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);
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
251 serialize_hello4(struct hello_message *message, struct interface_olsr *ifp)
253 uint16_t remainsize, curr_size;
254 struct hello_neighbor *nb;
255 union olsr_message *m;
257 struct hellinfo *hinfo;
262 if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
265 remainsize = net_outbuffer_bytes_left(ifp);
267 m = (union olsr_message *)msg_buffer;
269 curr_size = OLSR_HELLO_IPV4_HDRSIZE;
271 /* Send pending packet if not room in buffer */
272 if (curr_size > remainsize) {
274 remainsize = net_outbuffer_bytes_left(ifp);
277 check_buffspace(curr_size, remainsize, "HELLO");
279 h = &m->v4.message.hello;
280 hinfo = h->hell_info;
281 haddr = (char *)hinfo->neigh_addr;
283 /* Fill message header */
284 m->v4.ttl = message->ttl;
286 m->v4.olsr_msgtype = HELLO_MESSAGE;
287 /* Set source(main) addr */
288 m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
290 m->v4.olsr_vtime = ifp->valtimes.hello;
292 /* Fill HELLO header */
293 h->willingness = message->willingness;
294 h->htime = reltime_to_me(ifp->hello_etime);
296 memset(&h->reserved, 0, sizeof(uint16_t));
299 *Loops trough all possible neighbor statuses
300 *The neighbor list is grouped by status
303 /* Neighbor statuses */
304 for (i = 0; i <= MAX_NEIGH; i++) {
306 for (j = 0; j <= MAX_LINK; j++) {
308 struct ipaddr_str buf;
311 /* HYSTERESIS - Not adding neighbors with link type HIDE */
318 /* Looping trough neighbors */
319 for (nb = message->neighbors; nb != NULL; nb = nb->next) {
320 if ((nb->status != i) || (nb->link != j))
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);
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
335 * If this is the first neighbor in
336 * a group, we must check for an extra
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) {
343 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
345 /* Complete the headers */
346 m->v4.seqno = htons(get_msg_seqno());
347 m->v4.olsr_msgsize = htons(curr_size);
349 hinfo->size = htons((char *)haddr - (char *)hinfo);
351 /* Send partial packet */
352 net_outbuffer_push(ifp, msg_buffer, curr_size);
354 curr_size = OLSR_HELLO_IPV4_HDRSIZE;
356 h = &m->v4.message.hello;
357 hinfo = h->hell_info;
358 haddr = (char *)hinfo->neigh_addr;
359 /* Make sure typeheader is added */
364 /* Reset size and pointers */
365 remainsize = net_outbuffer_bytes_left(ifp);
368 check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2");
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 */
378 memcpy(haddr, &nb->address, sizeof(union olsr_ip_addr));
380 /* Point to next address */
381 haddr += olsr_cnf->ipsize;
382 curr_size += olsr_cnf->ipsize; /* IP address added */
388 hinfo->size = htons((char *)haddr - (char *)hinfo);
390 hinfo = (struct hellinfo *)((char *)haddr);
391 haddr = (char *)hinfo->neigh_addr;
397 m->v4.seqno = htons(get_msg_seqno());
398 m->v4.olsr_msgsize = htons(curr_size);
400 net_outbuffer_push(ifp, msg_buffer, curr_size);
402 /* HELLO will always be generated */
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
417 serialize_hello6(struct hello_message *message, struct interface_olsr *ifp)
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;
428 if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
431 remainsize = net_outbuffer_bytes_left(ifp);
432 m = (union olsr_message *)msg_buffer;
434 curr_size = OLSR_HELLO_IPV6_HDRSIZE; /* OLSR message header */
436 /* Send pending packet if not room in buffer */
437 if (curr_size > remainsize) {
439 remainsize = net_outbuffer_bytes_left(ifp);
441 check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO");
443 h6 = &m->v6.message.hello;
444 hinfo6 = h6->hell_info;
445 haddr = (union olsr_ip_addr *)hinfo6->neigh_addr;
447 /* Fill message header */
448 m->v6.ttl = message->ttl;
450 /* Set source(main) addr */
451 m->v6.originator = olsr_cnf->main_addr.v6;
452 m->v6.olsr_msgtype = HELLO_MESSAGE;
454 m->v6.olsr_vtime = ifp->valtimes.hello;
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));
462 *Loops trough all possible neighbor statuses
463 *The negbor list is grouped by status
466 for (i = 0; i <= MAX_NEIGH; i++) {
467 for (j = 0; j <= MAX_LINK; j++) {
469 struct ipaddr_str buf;
474 *Looping trough neighbors
476 for (nb = message->neighbors; nb != NULL; nb = nb->next) {
477 if ((nb->status != i) || (nb->link != j))
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);
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
492 * If this is the first neighbor in
493 * a group, we must check for an extra
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) {
500 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
502 /* Complete the headers */
503 m->v6.seqno = htons(get_msg_seqno());
504 m->v6.olsr_msgsize = htons(curr_size);
506 hinfo6->size = (char *)haddr - (char *)hinfo6;
507 hinfo6->size = htons(hinfo6->size);
509 /* Send partial packet */
510 net_outbuffer_push(ifp, msg_buffer, curr_size);
511 curr_size = OLSR_HELLO_IPV6_HDRSIZE;
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 */
520 /* Reset size and pointers */
521 remainsize = net_outbuffer_bytes_left(ifp);
523 check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2");
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 */
534 *haddr = nb->address;
536 /* Point to next address */
538 curr_size += olsr_cnf->ipsize; /* IP address added */
541 } /* looping trough neighbors */
544 hinfo6->size = htons((char *)haddr - (char *)hinfo6);
545 hinfo6 = (struct hellinfo6 *)((char *)haddr);
546 haddr = (union olsr_ip_addr *)&hinfo6->neigh_addr;
552 m->v6.seqno = htons(get_msg_seqno());
553 m->v6.olsr_msgsize = htons(curr_size);
555 net_outbuffer_push(ifp, msg_buffer, curr_size);
557 /* HELLO is always buildt */
564 *@param message the tc_message struct containing the info
566 *@param ifp the interface to send the message on
572 serialize_tc4(struct tc_message *message, struct interface_olsr *ifp)
575 struct ipaddr_str buf;
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;
584 if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET))
587 remainsize = net_outbuffer_bytes_left(ifp);
589 m = (union olsr_message *)msg_buffer;
591 tc = &m->v4.message.tc;
593 mprsaddr = tc->neigh;
594 curr_size = OLSR_TC_IPV4_HDRSIZE;
596 /* Send pending packet if not room in buffer */
597 if (curr_size > remainsize) {
599 remainsize = net_outbuffer_bytes_left(ifp);
601 check_buffspace(curr_size, remainsize, "TC");
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;
611 tc->ansn = htons(message->ansn);
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) {
619 /* Only add TC message if it contains data */
620 if (curr_size > OLSR_TC_IPV4_HDRSIZE) {
622 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
625 m->v4.olsr_msgsize = htons(curr_size);
626 m->v4.seqno = htons(get_msg_seqno());
628 net_outbuffer_push(ifp, msg_buffer, curr_size);
631 mprsaddr = tc->neigh;
632 curr_size = OLSR_TC_IPV4_HDRSIZE;
638 remainsize = net_outbuffer_bytes_left(ifp);
639 check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2");
644 OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&buf, &mprs->address));
646 mprsaddr->addr = mprs->address.v4.s_addr;
647 curr_size += olsr_cnf->ipsize;
653 m->v4.olsr_msgsize = htons(curr_size);
654 m->v4.seqno = htons(get_msg_seqno());
656 net_outbuffer_push(ifp, msg_buffer, curr_size);
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));
664 m->v4.olsr_msgsize = htons(curr_size);
665 m->v4.seqno = htons(get_msg_seqno());
667 net_outbuffer_push(ifp, msg_buffer, curr_size);
679 *@param message the tc_message struct containing the info
681 *@param ifp the interface to send the message on
687 serialize_tc6(struct tc_message *message, struct interface_olsr *ifp)
690 struct ipaddr_str buf;
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;
699 if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6))
702 remainsize = net_outbuffer_bytes_left(ifp);
704 m = (union olsr_message *)msg_buffer;
706 tc6 = &m->v6.message.tc;
708 mprsaddr6 = tc6->neigh;
709 curr_size = OLSR_TC_IPV6_HDRSIZE;
711 /* Send pending packet if not room in buffer */
712 if (curr_size > remainsize) {
714 remainsize = net_outbuffer_bytes_left(ifp);
716 check_buffspace(curr_size, remainsize, "TC");
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;
726 tc6->ansn = htons(message->ansn);
729 /*Looping trough MPR selectors */
730 for (mprs = message->multipoint_relay_selector_address; mprs != NULL; mprs = mprs->next) {
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) {
737 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
739 m->v6.olsr_msgsize = htons(curr_size);
740 m->v6.seqno = htons(get_msg_seqno());
742 net_outbuffer_push(ifp, msg_buffer, curr_size);
743 mprsaddr6 = tc6->neigh;
744 curr_size = OLSR_TC_IPV6_HDRSIZE;
749 remainsize = net_outbuffer_bytes_left(ifp);
750 check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2");
755 OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&buf, &mprs->address));
757 mprsaddr6->addr = mprs->address.v6;
758 curr_size += olsr_cnf->ipsize;
764 m->v6.olsr_msgsize = htons(curr_size);
765 m->v6.seqno = htons(get_msg_seqno());
767 net_outbuffer_push(ifp, msg_buffer, curr_size);
770 if ((!partial_sent) && (!TIMED_OUT(send_empty_tc))) {
771 OLSR_PRINTF(1, "TC: Sending empty package\n");
773 m->v6.olsr_msgsize = htons(curr_size);
774 m->v6.seqno = htons(get_msg_seqno());
776 net_outbuffer_push(ifp, msg_buffer, curr_size);
788 *<b>NO INTERNAL BUFFER</b>
789 *@param ifp use this interfaces address as main address
790 *@return 1 on success
794 serialize_mid4(struct interface_olsr *ifp)
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;
802 if ((olsr_cnf->ip_version != AF_INET) || (!ifp) || (ifnet == NULL) || ((ifnet->int_next == NULL) && (ipequal(&olsr_cnf->main_addr, &ifnet->ip_addr))))
805 remainsize = net_outbuffer_bytes_left(ifp);
807 m = (union olsr_message *)msg_buffer;
809 curr_size = OLSR_MID_IPV4_HDRSIZE;
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;
817 /* Send pending packet if not room in buffer */
818 if (needsize > remainsize) {
820 remainsize = net_outbuffer_bytes_left(ifp);
822 check_buffspace(curr_size, remainsize, "MID");
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;
832 addrs = m->v4.message.mid.mid_addr;
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)) {
838 struct ipaddr_str buf;
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) {
845 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
848 m->v4.olsr_msgsize = htons(curr_size);
849 m->v4.seqno = htons(get_msg_seqno()); /* seqnumber */
851 net_outbuffer_push(ifp, msg_buffer, curr_size);
852 curr_size = OLSR_MID_IPV4_HDRSIZE;
853 addrs = m->v4.message.mid.mid_addr;
856 remainsize = net_outbuffer_bytes_left(ifp);
857 check_buffspace(curr_size, remainsize, "MID2");
860 OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name);
863 addrs->addr = ifs->ip_addr.v4.s_addr;
865 curr_size += olsr_cnf->ipsize;
869 m->v4.seqno = htons(get_msg_seqno()); /* seqnumber */
870 m->v4.olsr_msgsize = htons(curr_size);
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);
882 *<b>NO INTERNAL BUFFER</b>
883 *@param ifp use this interfaces address as main address
884 *@return 1 on success
888 serialize_mid6(struct interface_olsr *ifp)
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;
896 //printf("\t\tGenerating mid on %s\n", ifn->int_name);
898 if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL) || ((ifnet->int_next == NULL) && (ipequal(&olsr_cnf->main_addr, &ifnet->ip_addr))))
901 remainsize = net_outbuffer_bytes_left(ifp);
903 curr_size = OLSR_MID_IPV6_HDRSIZE;
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;
911 /* Send pending packet if not room in buffer */
912 if (needsize > remainsize) {
914 remainsize = net_outbuffer_bytes_left(ifp);
916 check_buffspace(curr_size, remainsize, "MID");
918 m = (union olsr_message *)msg_buffer;
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;
928 addrs6 = m->v6.message.mid.mid_addr;
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)) {
934 struct ipaddr_str buf;
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) {
940 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize);
943 m->v6.olsr_msgsize = htons(curr_size);
944 m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */
946 net_outbuffer_push(ifp, msg_buffer, curr_size);
947 curr_size = OLSR_MID_IPV6_HDRSIZE;
948 addrs6 = m->v6.message.mid.mid_addr;
951 remainsize = net_outbuffer_bytes_left(ifp);
952 check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2");
955 OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name);
958 addrs6->addr = ifs->ip_addr.v6;
960 curr_size += olsr_cnf->ipsize;
964 m->v6.olsr_msgsize = htons(curr_size);
965 m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */
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);
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
977 __attribute__((unused))
981 __attribute__((unused))
984 union olsr_ip_addr ip_addr;
986 bool is_def_route = is_prefix_inetgw(&h->net);
989 if ((*curr_size + (2 * olsr_cnf->ipsize)) > *remainsize) {
990 /* Only add HNA message if it contains data */
991 if (*curr_size > OLSR_HNA_IPV4_HDRSIZE) {
993 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", *curr_size, *remainsize);
995 m->v4.olsr_msgsize = htons(*curr_size);
996 m->v4.seqno = htons(get_msg_seqno());
997 net_outbuffer_push(ifp, msg_buffer, *curr_size);
998 *curr_size = OLSR_HNA_IPV4_HDRSIZE;
999 *pair = m->v4.message.hna.hna_net;
1002 *remainsize = net_outbuffer_bytes_left(ifp);
1003 check_buffspace(*curr_size + (2 * olsr_cnf->ipsize), *remainsize, "HNA2");
1006 OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1009 olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
1011 if (olsr_cnf->smart_gw_active && is_def_route) {
1012 /* this is the default route, overwrite it with the smart gateway */
1013 olsr_modifiy_inetgw_netmask(&ip_addr, h->net.prefix_len, zero);
1016 #endif /* __linux__ */
1017 (*pair)->addr = h->net.prefix.v4.s_addr;
1018 (*pair)->netmask = ip_addr.v4.s_addr;
1019 *pair = &(*pair)[1];
1020 *curr_size += (2 * olsr_cnf->ipsize);
1026 *@param ifp the interface to send on
1030 serialize_hna4(struct ip_prefix_list *h, struct interface_olsr *ifp, bool is_zero_bw)
1032 uint16_t remainsize, curr_size, needsize;
1033 /* preserve existing data in output buffer */
1034 union olsr_message *m;
1035 struct hnapair *pair;
1037 bool sgw_set = false;
1043 if (olsr_cnf->ip_version != AF_INET) {
1047 if (h_empty && !ifp->sgw_sgw_zero_bw_timeout) {
1051 remainsize = net_outbuffer_bytes_left(ifp);
1053 curr_size = OLSR_HNA_IPV4_HDRSIZE;
1055 needsize = curr_size;
1058 /* calculate size needed for HNA */
1059 struct ip_prefix_list *h_tmp = h;
1061 needsize += olsr_cnf->ipsize*2;
1062 h_tmp = h_tmp->next;
1065 /* Send pending packet if not room in buffer */
1066 if (needsize > remainsize) {
1068 remainsize = net_outbuffer_bytes_left(ifp);
1070 check_buffspace(curr_size, remainsize, "HNA");
1072 m = (union olsr_message *)msg_buffer;
1075 m->v4.olsr_msgtype = HNA_MESSAGE;
1076 m->v4.olsr_vtime = is_zero_bw ? reltime_to_me(ifp->sgw_sgw_zero_bw_timeout) : ifp->valtimes.hna;
1078 m->v4.originator = olsr_cnf->main_addr.v4.s_addr;
1079 m->v4.ttl = MAX_TTL;
1083 pair = m->v4.message.hna.hna_net;
1085 for (; h != NULL; h = h->next) {
1086 appendHNAEntry(ifp, h, &remainsize, &curr_size, m, &pair, is_zero_bw, &sgw_set);
1089 m->v4.olsr_msgsize = htons(curr_size);
1090 m->v4.seqno = htons(get_msg_seqno());
1092 net_outbuffer_push(ifp, msg_buffer, curr_size);
1095 if (sgw_set && !is_zero_bw) {
1096 /* (re)set zero bandwidth sgw HNAs timeout */
1097 ifp->sgw_sgw_zero_bw_timeout = ifp->valtimes.hna_reltime;
1103 if (olsr_cnf->smart_gw_active /* sgw is active */
1104 && (h_empty || !sgw_set) /* there are no HNAs at all or no sgw HNA */
1105 && ifp->sgw_sgw_zero_bw_timeout /* the zero bandwidth sgw HNA window is still valid */
1106 && !is_zero_bw /* prevent infinite recursion */
1108 struct ip_prefix_list h_zero;
1110 memset(&h_zero, 0, sizeof(h_zero));
1111 serialize_hna4(&h_zero, ifp, true);
1113 /* decrement the window validity time */
1115 unsigned int hna_period = ifp->hna_gen_timer->timer_period;
1116 if (ifp->sgw_sgw_zero_bw_timeout <= hna_period) {
1117 ifp->sgw_sgw_zero_bw_timeout = 0;
1119 ifp->sgw_sgw_zero_bw_timeout -= hna_period;
1123 #endif /* __linux__ */
1125 //printf("Sending HNA (%d bytes)...\n", outputsize);
1129 static void appendHNA6Entry(struct interface_olsr *ifp, struct ip_prefix_list *h, uint16_t * remainsize, uint16_t * curr_size,
1130 union olsr_message *m, struct hnapair6 **pair, bool zero
1132 __attribute__((unused))
1136 __attribute__((unused))
1139 union olsr_ip_addr ip_addr;
1141 bool is_def_route = is_prefix_inetgw(&h->net);
1144 if ((*curr_size + (2 * olsr_cnf->ipsize)) > *remainsize) {
1145 /* Only add HNA message if it contains data */
1146 if (*curr_size > OLSR_HNA_IPV6_HDRSIZE) {
1148 OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", *curr_size, *remainsize);
1150 m->v6.olsr_msgsize = htons(*curr_size);
1151 m->v6.seqno = htons(get_msg_seqno());
1152 net_outbuffer_push(ifp, msg_buffer, *curr_size);
1153 *curr_size = OLSR_HNA_IPV6_HDRSIZE;
1154 *pair = m->v6.message.hna.hna_net;
1157 *remainsize = net_outbuffer_bytes_left(ifp);
1158 check_buffspace(*curr_size + (2 * olsr_cnf->ipsize), *remainsize, "HNA2");
1161 OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s\n", olsr_ip_prefix_to_string(&h->net));
1164 olsr_prefix_to_netmask(&ip_addr, h->net.prefix_len);
1166 if (olsr_cnf->smart_gw_active && is_def_route) {
1167 /* this is the default route, overwrite it with the smart gateway */
1168 olsr_modifiy_inetgw_netmask(&ip_addr, h->net.prefix_len, zero);
1171 #endif /* __linux__ */
1172 (*pair)->addr = h->net.prefix.v6;
1173 (*pair)->netmask = ip_addr.v6;
1174 *pair = &(*pair)[1];
1175 *curr_size += (2 * olsr_cnf->ipsize);
1181 *@param ifp the interface to send on
1185 serialize_hna6(struct ip_prefix_list *h, struct interface_olsr *ifp, bool is_zero_bw)
1187 uint16_t remainsize, curr_size, needsize;
1188 /* preserve existing data in output buffer */
1189 union olsr_message *m;
1190 struct hnapair6 *pair;
1192 bool sgw_set = false;
1198 if (olsr_cnf->ip_version != AF_INET6) {
1202 if (h_empty && !ifp->sgw_sgw_zero_bw_timeout) {
1206 remainsize = net_outbuffer_bytes_left(ifp);
1208 curr_size = OLSR_HNA_IPV6_HDRSIZE;
1210 needsize = curr_size;
1213 /* calculate size needed for HNA */
1214 struct ip_prefix_list *h_tmp = h;
1216 needsize += olsr_cnf->ipsize*2;
1217 h_tmp = h_tmp->next;
1220 /* Send pending packet if not room in buffer */
1221 if (needsize > remainsize) {
1223 remainsize = net_outbuffer_bytes_left(ifp);
1225 check_buffspace(curr_size, remainsize, "HNA");
1227 m = (union olsr_message *)msg_buffer;
1230 m->v6.olsr_msgtype = HNA_MESSAGE;
1231 m->v6.olsr_vtime = is_zero_bw ? reltime_to_me(ifp->sgw_sgw_zero_bw_timeout) : ifp->valtimes.hna;
1233 m->v6.originator = olsr_cnf->main_addr.v6;
1234 m->v6.ttl = MAX_TTL;
1238 pair = m->v6.message.hna.hna_net;
1240 for (; h != NULL; h = h->next) {
1241 appendHNA6Entry(ifp, h, &remainsize, &curr_size, m, &pair, is_zero_bw, &sgw_set);
1244 m->v6.olsr_msgsize = htons(curr_size);
1245 m->v6.seqno = htons(get_msg_seqno());
1247 net_outbuffer_push(ifp, msg_buffer, curr_size);
1250 if (sgw_set && !is_zero_bw) {
1251 /* (re)set zero bandwidth sgw HNAs timeout */
1252 ifp->sgw_sgw_zero_bw_timeout = ifp->valtimes.hna_reltime;
1258 if (olsr_cnf->smart_gw_active /* sgw is active */
1259 && (h_empty || !sgw_set) /* there are no HNAs at all or no sgw HNA */
1260 && ifp->sgw_sgw_zero_bw_timeout /* the zero bandwidth sgw HNA window is still valid */
1261 && !is_zero_bw /* prevent infinite recursion */
1263 struct ip_prefix_list h_zero;
1265 memset(&h_zero, 0, sizeof(h_zero));
1266 serialize_hna6(&h_zero, ifp, true);
1268 /* decrement the window validity time */
1270 unsigned int hna_period = ifp->hna_gen_timer->timer_period;
1271 if (ifp->sgw_sgw_zero_bw_timeout <= hna_period) {
1272 ifp->sgw_sgw_zero_bw_timeout = 0;
1274 ifp->sgw_sgw_zero_bw_timeout -= hna_period;
1278 #endif /* __linux__ */
1280 //printf("Sending HNA (%d bytes)...\n", outputsize);
1287 * indent-tabs-mode: nil