/* * The olsr.org Optimized Link-State Routing daemon(olsrd) * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of olsr.org, olsrd nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Visit http://www.olsr.org for more information. * * If you find this software useful feel free to make a donation * to the project. For more information see the website or contact * the copyright holders. * * $Id: build_msg.c,v 1.36 2007/04/25 22:08:07 bernd67 Exp $ */ #include "defs.h" #include "olsr.h" #include "log.h" #include "build_msg.h" #include "local_hna_set.h" #include "mantissa.h" #define BMSG_DBGLVL 5 #define OLSR_IPV4_HDRSIZE 12 #define OLSR_IPV6_HDRSIZE 24 #define OLSR_HELLO_IPV4_HDRSIZE (OLSR_IPV4_HDRSIZE + 4) #define OLSR_HELLO_IPV6_HDRSIZE (OLSR_IPV6_HDRSIZE + 4) #define OLSR_TC_IPV4_HDRSIZE (OLSR_IPV4_HDRSIZE + 4) #define OLSR_TC_IPV6_HDRSIZE (OLSR_IPV6_HDRSIZE + 4) #define OLSR_MID_IPV4_HDRSIZE OLSR_IPV4_HDRSIZE #define OLSR_MID_IPV6_HDRSIZE OLSR_IPV6_HDRSIZE #define OLSR_HNA_IPV4_HDRSIZE OLSR_IPV4_HDRSIZE #define OLSR_HNA_IPV6_HDRSIZE OLSR_IPV6_HDRSIZE /* All these functions share this buffer */ static olsr_u8_t msg_buffer[MAXMESSAGESIZE - OLSR_HEADERSIZE]; static clock_t send_empty_tc; /* TC empty message sending */ /* Prototypes for internal functions */ /* IPv4 */ static olsr_bool serialize_hello4(struct hello_message *, struct interface *); static olsr_bool serialize_tc4(struct tc_message *, struct interface *); static olsr_bool serialize_mid4(struct interface *); static olsr_bool serialize_hna4(struct interface *); /* IPv6 */ static olsr_bool serialize_hello6(struct hello_message *, struct interface *); static olsr_bool serialize_tc6(struct tc_message *, struct interface *); static olsr_bool serialize_mid6(struct interface *); static olsr_bool serialize_hna6(struct interface *); /** * Set the timer that controls the generation of * empty TC messages */ void set_empty_tc_timer(clock_t empty_tc_new) { send_empty_tc = empty_tc_new; } /** * Get the timer that controls the generation of * empty TC messages */ clock_t get_empty_tc_timer(void) { return send_empty_tc; } /** * Generate HELLO packet with the contents of the parameter "message". * If this won't fit in one packet, chop it up into several. * Send the packet if the size of the data contained in the output buffer * reach maxmessagesize. Can generate an empty HELLO packet if the * neighbor table is empty. * * *@param message the hello_message struct containing the info *to build the hello message from. *@param ifp the interface to send the message on * *@return nada */ olsr_bool queue_hello(struct hello_message *message, struct interface *ifp) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Building HELLO on %s\n-------------------\n", ifp->int_name); #endif switch(olsr_cnf->ip_version) { case(AF_INET): return serialize_hello4(message, ifp); case(AF_INET6): return serialize_hello6(message, ifp); } return OLSR_FALSE; } /* * Generate TC packet with the contents of the parameter "message". * If this won't fit in one packet, chop it up into several. * Send the packet if the size of the data contained in the output buffer * reach maxmessagesize. * *@param message the tc_message struct containing the info *to send *@param ifp the interface to send the message on * *@return nada */ olsr_bool queue_tc(struct tc_message *message, struct interface *ifp) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Building TC on %s\n-------------------\n", ifp->int_name); #endif switch(olsr_cnf->ip_version) { case(AF_INET): return serialize_tc4(message, ifp); case(AF_INET6): return serialize_tc6(message, ifp); } return OLSR_FALSE; } /** *Build a MID message to the outputbuffer * *NO INTERNAL BUFFER *@param ifn use this interfaces address as main address *@return 1 on success */ olsr_bool queue_mid(struct interface *ifp) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Building MID on %s\n-------------------\n", ifp->int_name); #endif switch(olsr_cnf->ip_version) { case(AF_INET): return serialize_mid4(ifp); case(AF_INET6): return serialize_mid6(ifp); } return OLSR_FALSE; } /** *Builds a HNA message in the outputbuffer *NB! Not internal packetformat! * *@param ifp the interface to send on *@return nada */ olsr_bool queue_hna(struct interface *ifp) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Building HNA on %s\n-------------------\n", ifp->int_name); #endif switch(olsr_cnf->ip_version) { case(AF_INET): return serialize_hna4(ifp); case(AF_INET6): return serialize_hna6(ifp); } return OLSR_FALSE; } /* * Protocol specific versions */ static void check_buffspace(int msgsize, int buffsize, char *type) { if(msgsize > buffsize) { OLSR_PRINTF(1, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize); olsr_syslog(OLSR_LOG_ERR, "%s build, outputbuffer to small(%d/%d)!\n", type, msgsize, buffsize); olsr_exit(__func__, EXIT_FAILURE); } } /** * IP version 4 * *@param message the hello_message struct containing the info *to build the hello message from. *@param ifp the interface to send the message on * *@return nada */ static olsr_bool serialize_hello4(struct hello_message *message, struct interface *ifp) { olsr_u16_t remainsize, curr_size; struct hello_neighbor *nb; union olsr_message *m; struct hellomsg *h; struct hellinfo *hinfo; union olsr_ip_addr *haddr; int i, j; olsr_bool first_entry; if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET)) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); m = (union olsr_message *)msg_buffer; curr_size = OLSR_HELLO_IPV4_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } /* Sanity check */ check_buffspace(curr_size, remainsize, "HELLO"); h = &m->v4.message.hello; hinfo = h->hell_info; haddr = (union olsr_ip_addr *)hinfo->neigh_addr; /* Fill message header */ m->v4.ttl = message->ttl; m->v4.hopcnt = 0; m->v4.olsr_msgtype = HELLO_MESSAGE; /* Set source(main) addr */ COPY_IP(&m->v4.originator, &olsr_cnf->main_addr); m->v4.olsr_vtime = ifp->valtimes.hello; /* Fill HELLO header */ h->willingness = message->willingness; h->htime = double_to_me(ifp->hello_etime); memset(&h->reserved, 0, sizeof(olsr_u16_t)); /* *Loops trough all possible neighbor statuses *The negbor list is grouped by status * */ /* Nighbor statuses */ for (i = 0; i <= MAX_NEIGH; i++) { /* Link statuses */ for(j = 0; j <= MAX_LINK; j++) { /* HYSTERESIS - Not adding neighbors with link type HIDE */ if(j == HIDE_LINK) continue; first_entry = OLSR_TRUE; /* Looping trough neighbors */ for (nb = message->neighbors; nb != NULL; nb = nb->next) { if ((nb->status != i) || (nb->link != j)) continue; #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&nb->address)); OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i); #endif /* * If there is not enough room left * for the data in the outputbuffer * we must send a partial HELLO and * continue building the rest of the * data in a new HELLO message * * If this is the first neighbor in * a group, we must check for an extra * 4 bytes */ if((curr_size + olsr_cnf->ipsize + (first_entry ? 4 : 0)) > remainsize) { /* Only send partial HELLO if it contains data */ if(curr_size > OLSR_HELLO_IPV4_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif /* Complete the headers */ m->v4.seqno = htons(get_msg_seqno()); m->v4.olsr_msgsize = htons(curr_size); hinfo->size = htons((char *)haddr - (char *)hinfo); /* Send partial packet */ net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_HELLO_IPV4_HDRSIZE; h = &m->v4.message.hello; hinfo = h->hell_info; haddr = (union olsr_ip_addr *)hinfo->neigh_addr; /* Make sure typeheader is added */ first_entry = OLSR_TRUE; } net_output(ifp); /* Reset size and pointers */ remainsize = net_outbuffer_bytes_left(ifp); /* Sanity check */ check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2"); } if (first_entry) { memset(&hinfo->reserved, 0, sizeof(olsr_u8_t)); /* Set link and status for this group of neighbors (this is the first) */ hinfo->link_code = CREATE_LINK_CODE(i, j); curr_size += 4; /* HELLO type section header */ } COPY_IP(haddr, &nb->address); /* Point to next address */ haddr = (union olsr_ip_addr *)&haddr->v6.s6_addr[4]; curr_size += olsr_cnf->ipsize; /* IP address added */ first_entry = OLSR_FALSE; } if(!first_entry) { hinfo->size = htons((char *)haddr - (char *)hinfo); hinfo = (struct hellinfo *)((char *)haddr); haddr = (union olsr_ip_addr *)&hinfo->neigh_addr; } } /* for j */ } /* for i*/ m->v4.seqno = htons(get_msg_seqno()); m->v4.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); /* HELLO will always be generated */ return OLSR_TRUE; } /** * IP version 6 * *@param message the hello_message struct containing the info *to build the hello message from. *@param ifp the interface to send the message on * *@return nada */ static olsr_bool serialize_hello6(struct hello_message *message, struct interface *ifp) { olsr_u16_t remainsize, curr_size; struct hello_neighbor *nb; union olsr_message *m; struct hellomsg6 *h6; struct hellinfo6 *hinfo6; union olsr_ip_addr *haddr; int i, j; olsr_bool first_entry; if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6)) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); m = (union olsr_message *)msg_buffer; curr_size = OLSR_HELLO_IPV6_HDRSIZE; /* OLSR message header */ /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO"); h6 = &m->v6.message.hello; hinfo6 = h6->hell_info; haddr = (union olsr_ip_addr *)hinfo6->neigh_addr; /* Fill message header */ m->v6.ttl = message->ttl; m->v6.hopcnt = 0; /* Set source(main) addr */ COPY_IP(&m->v6.originator, &olsr_cnf->main_addr); m->v6.olsr_msgtype = HELLO_MESSAGE; m->v6.olsr_vtime = ifp->valtimes.hello; /* Fill packet header */ h6->willingness = message->willingness; h6->htime = double_to_me(ifp->hello_etime); memset(&h6->reserved, 0, sizeof(olsr_u16_t)); /* *Loops trough all possible neighbor statuses *The negbor list is grouped by status */ for (i = 0; i <= MAX_NEIGH; i++) { for(j = 0; j <= MAX_LINK; j++) { first_entry = OLSR_TRUE; /* *Looping trough neighbors */ for (nb = message->neighbors; nb != NULL; nb = nb->next) { if ((nb->status != i) || (nb->link != j)) continue; #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s - ", olsr_ip_to_string(&nb->address)); OLSR_PRINTF(BMSG_DBGLVL, "L:%d N:%d\n", j, i); #endif /* * If there is not enough room left * for the data in the outputbuffer * we must send a partial HELLO and * continue building the rest of the * data in a new HELLO message * * If this is the first neighbor in * a group, we must check for an extra * 4 bytes */ if((curr_size + olsr_cnf->ipsize + (first_entry ? 4 : 0)) > remainsize) { /* Only send partial HELLO if it contains data */ if(curr_size > OLSR_HELLO_IPV6_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif /* Complete the headers */ m->v6.seqno = htons(get_msg_seqno()); m->v6.olsr_msgsize = htons(curr_size); hinfo6->size = (char *)haddr - (char *)hinfo6; hinfo6->size = htons(hinfo6->size); /* Send partial packet */ net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_HELLO_IPV6_HDRSIZE; h6 = &m->v6.message.hello; hinfo6 = h6->hell_info; haddr = (union olsr_ip_addr *)hinfo6->neigh_addr; /* Make sure typeheader is added */ first_entry = OLSR_TRUE; } net_output(ifp); /* Reset size and pointers */ remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + olsr_cnf->ipsize + 4, remainsize, "HELLO2"); } if(first_entry) { memset(&hinfo6->reserved, 0, sizeof(olsr_u8_t)); /* Set link and status for this group of neighbors (this is the first) */ hinfo6->link_code = CREATE_LINK_CODE(i, j); curr_size += 4; /* HELLO type section header */ } COPY_IP(haddr, &nb->address); /* Point to next address */ haddr++; curr_size += olsr_cnf->ipsize; /* IP address added */ first_entry = OLSR_FALSE; }/* looping trough neighbors */ if (!first_entry) { hinfo6->size = htons((char *)haddr - (char *)hinfo6); hinfo6 = (struct hellinfo6 *)((char *)haddr); haddr = (union olsr_ip_addr *)&hinfo6->neigh_addr; } } /* for j */ } /* for i */ m->v6.seqno = htons(get_msg_seqno()); m->v6.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); /* HELLO is always buildt */ return OLSR_TRUE; } /** *IP version 4 * *@param message the tc_message struct containing the info *to send *@param ifp the interface to send the message on * *@return nada */ static olsr_bool serialize_tc4(struct tc_message *message, struct interface *ifp) { olsr_u16_t remainsize, curr_size; struct tc_mpr_addr *mprs; union olsr_message *m; struct olsr_tcmsg *tc; struct neigh_info *mprsaddr; olsr_bool found = OLSR_FALSE, partial_sent = OLSR_FALSE; if((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET)) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); m = (union olsr_message *)msg_buffer; tc = &m->v4.message.tc; mprsaddr = tc->neigh; curr_size = OLSR_TC_IPV4_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "TC"); /* Fill header */ m->v4.olsr_vtime = ifp->valtimes.tc; m->v4.olsr_msgtype = TC_MESSAGE; m->v4.hopcnt = message->hop_count; m->v4.ttl = message->ttl; COPY_IP(&m->v4.originator, &message->originator); /* Fill TC header */ tc->ansn = htons(message->ansn); tc->reserved = 0; /*Looping trough MPR selectors */ for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) { /*If packet is to be chomped */ if((curr_size + olsr_cnf->ipsize) > remainsize) { /* Only add TC message if it contains data */ if(curr_size > OLSR_TC_IPV4_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif m->v4.olsr_msgsize = htons(curr_size); m->v4.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); /* Reset stuff */ mprsaddr = tc->neigh; curr_size = OLSR_TC_IPV4_HDRSIZE; found = OLSR_FALSE; partial_sent = OLSR_TRUE; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2"); } found = OLSR_TRUE; #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&mprs->address)); #endif COPY_IP(&mprsaddr->addr, &mprs->address); curr_size += olsr_cnf->ipsize; mprsaddr++; } if (found) { m->v4.olsr_msgsize = htons(curr_size); m->v4.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); } else { if((!partial_sent) && (!TIMED_OUT(send_empty_tc))) { if(!TIMED_OUT(send_empty_tc)) OLSR_PRINTF(1, "TC: Sending empty package - (%d/%d/%d/%d)\n", partial_sent, (int)send_empty_tc, (int)now_times, (int)((send_empty_tc) - now_times)); m->v4.olsr_msgsize = htons(curr_size); m->v4.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); found = OLSR_TRUE; } } return found; } /** *IP version 6 * *@param message the tc_message struct containing the info *to send *@param ifp the interface to send the message on * *@return nada */ static olsr_bool serialize_tc6(struct tc_message *message, struct interface *ifp) { olsr_u16_t remainsize, curr_size; struct tc_mpr_addr *mprs; union olsr_message *m; struct olsr_tcmsg6 *tc6; struct neigh_info6 *mprsaddr6; olsr_bool found = OLSR_FALSE, partial_sent = OLSR_FALSE; if ((!message) || (!ifp) || (olsr_cnf->ip_version != AF_INET6)) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); m = (union olsr_message *)msg_buffer; tc6 = &m->v6.message.tc; mprsaddr6 = tc6->neigh; curr_size = OLSR_TC_IPV6_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "TC"); /* Fill header */ m->v6.olsr_vtime = ifp->valtimes.tc; m->v6.olsr_msgtype = TC_MESSAGE; m->v6.hopcnt = message->hop_count; m->v6.ttl = message->ttl; COPY_IP(&m->v6.originator, &message->originator); /* Fill TC header */ tc6->ansn = htons(message->ansn); tc6->reserved = 0; /*Looping trough MPR selectors */ for (mprs = message->multipoint_relay_selector_address; mprs != NULL;mprs = mprs->next) { /*If packet is to be chomped */ if((curr_size + olsr_cnf->ipsize) > remainsize) { /* Only add TC message if it contains data */ if(curr_size > OLSR_TC_IPV6_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); mprsaddr6 = tc6->neigh; curr_size = OLSR_TC_IPV6_HDRSIZE; found = OLSR_FALSE; partial_sent = OLSR_TRUE; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "TC2"); } found = OLSR_TRUE; #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s\n", olsr_ip_to_string(&mprs->address)); #endif COPY_IP(&mprsaddr6->addr, &mprs->address); curr_size += olsr_cnf->ipsize; mprsaddr6++; } if (found) { m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); } else { if((!partial_sent) && (!TIMED_OUT(send_empty_tc))) { OLSR_PRINTF(1, "TC: Sending empty package\n"); m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); found = OLSR_TRUE; } } return found; } /** *IP version 4 * *NO INTERNAL BUFFER *@param ifp use this interfaces address as main address *@return 1 on success */ static olsr_bool serialize_mid4(struct interface *ifp) { olsr_u16_t remainsize, curr_size; /* preserve existing data in output buffer */ union olsr_message *m; struct midaddr *addrs; struct interface *ifs; if((olsr_cnf->ip_version != AF_INET) || (!ifp) || (ifnet == NULL || ifnet->int_next == NULL)) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); m = (union olsr_message *)msg_buffer; curr_size = OLSR_MID_IPV4_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "MID"); /* Fill header */ m->v4.hopcnt = 0; m->v4.ttl = MAX_TTL; /* Set main(first) address */ COPY_IP(&m->v4.originator, &olsr_cnf->main_addr); m->v4.olsr_msgtype = MID_MESSAGE; m->v4.olsr_vtime = ifp->valtimes.mid; addrs = m->v4.message.mid.mid_addr; /* Don't add the main address... it's already there */ for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { if(!COMP_IP(&olsr_cnf->main_addr, &ifs->ip_addr)) { if((curr_size + olsr_cnf->ipsize) > remainsize) { /* Only add MID message if it contains data */ if(curr_size > OLSR_MID_IPV4_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif /* set size */ m->v4.olsr_msgsize = htons(curr_size); m->v4.seqno = htons(get_msg_seqno());/* seqnumber */ net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_MID_IPV4_HDRSIZE; addrs = m->v4.message.mid.mid_addr; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size, remainsize, "MID2"); } #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&ifs->ip_addr), ifs->int_name); #endif COPY_IP(&addrs->addr, &ifs->ip_addr); addrs++; curr_size += olsr_cnf->ipsize; } } m->v4.seqno = htons(get_msg_seqno());/* seqnumber */ m->v4.olsr_msgsize = htons(curr_size); //printf("Sending MID (%d bytes)...\n", outputsize); if(curr_size > OLSR_MID_IPV4_HDRSIZE) net_outbuffer_push(ifp, msg_buffer, curr_size); return OLSR_TRUE; } /** *IP version 6 * *NO INTERNAL BUFFER *@param ifp use this interfaces address as main address *@return 1 on success */ static olsr_bool serialize_mid6(struct interface *ifp) { olsr_u16_t remainsize, curr_size; /* preserve existing data in output buffer */ union olsr_message *m; struct midaddr6 *addrs6; struct interface *ifs; //printf("\t\tGenerating mid on %s\n", ifn->int_name); if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL || ifnet->int_next == NULL)) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); curr_size = OLSR_MID_IPV6_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID"); m = (union olsr_message *)msg_buffer; /* Build header */ m->v6.hopcnt = 0; m->v6.ttl = MAX_TTL; m->v6.olsr_msgtype = MID_MESSAGE; m->v6.olsr_vtime = ifp->valtimes.mid; /* Set main(first) address */ COPY_IP(&m->v6.originator, &olsr_cnf->main_addr); addrs6 = m->v6.message.mid.mid_addr; /* Don't add the main address... it's already there */ for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { if(!COMP_IP(&olsr_cnf->main_addr, &ifs->ip_addr)) { if((curr_size + olsr_cnf->ipsize) > remainsize) { /* Only add MID message if it contains data */ if(curr_size > OLSR_MID_IPV6_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif /* set size */ m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno());/* seqnumber */ net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_MID_IPV6_HDRSIZE; addrs6 = m->v6.message.mid.mid_addr; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2"); } #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&ifs->ip_addr), ifs->int_name); #endif COPY_IP(&addrs6->addr, &ifs->ip_addr); addrs6++; curr_size += olsr_cnf->ipsize; } } m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno());/* seqnumber */ //printf("Sending MID (%d bytes)...\n", outputsize); if(curr_size > OLSR_MID_IPV6_HDRSIZE) net_outbuffer_push(ifp, msg_buffer, curr_size); return OLSR_TRUE; } /** *IP version 4 * *@param ifp the interface to send on *@return nada */ static olsr_bool serialize_hna4(struct interface *ifp) { olsr_u16_t remainsize, curr_size; /* preserve existing data in output buffer */ union olsr_message *m; struct hnapair *pair; struct hna4_entry *h = olsr_cnf->hna4_entries; /* No hna nets */ if((olsr_cnf->ip_version != AF_INET) || (!ifp) || h == NULL) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); curr_size = OLSR_HNA_IPV4_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "HNA"); m = (union olsr_message *)msg_buffer; /* Fill header */ COPY_IP(&m->v4.originator, &olsr_cnf->main_addr); m->v4.hopcnt = 0; m->v4.ttl = MAX_TTL; m->v4.olsr_msgtype = HNA_MESSAGE; m->v4.olsr_vtime = ifp->valtimes.hna; pair = m->v4.message.hna.hna_net; while(h) { if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) { /* Only add HNA message if it contains data */ if(curr_size > OLSR_HNA_IPV4_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif m->v4.seqno = htons(get_msg_seqno()); m->v4.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_HNA_IPV4_HDRSIZE; pair = m->v4.message.hna.hna_net; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2"); } #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s/%s\n", olsr_ip_to_string(&h->net), olsr_ip_to_string(&h->netmask)); #endif COPY_IP(&pair->addr, &h->net); COPY_IP(&pair->netmask, &h->netmask); pair++; curr_size += (2 * olsr_cnf->ipsize); h = h->next; } m->v4.seqno = htons(get_msg_seqno()); m->v4.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); //printf("Sending HNA (%d bytes)...\n", outputsize); return OLSR_FALSE; } /** *IP version 6 * *@param ifp the interface to send on *@return nada */ static olsr_bool serialize_hna6(struct interface *ifp) { olsr_u16_t remainsize, curr_size; /* preserve existing data in output buffer */ union olsr_message *m; struct hnapair6 *pair6; union olsr_ip_addr tmp_netmask; struct hna6_entry *h = olsr_cnf->hna6_entries; /* No hna nets */ if((olsr_cnf->ip_version != AF_INET6) || (!ifp) || h == NULL) return OLSR_FALSE; remainsize = net_outbuffer_bytes_left(ifp); curr_size = OLSR_HNA_IPV6_HDRSIZE; /* Send pending packet if not room in buffer */ if(curr_size > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "HNA"); m = (union olsr_message *)msg_buffer; /* Fill header */ COPY_IP(&m->v6.originator, &olsr_cnf->main_addr); m->v6.hopcnt = 0; m->v6.ttl = MAX_TTL; m->v6.olsr_msgtype = HNA_MESSAGE; m->v6.olsr_vtime = ifp->valtimes.hna; pair6 = m->v6.message.hna.hna_net; while(h) { if((curr_size + (2 * olsr_cnf->ipsize)) > remainsize) { /* Only add HNA message if it contains data */ if(curr_size > OLSR_HNA_IPV6_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif m->v6.seqno = htons(get_msg_seqno()); m->v6.olsr_msgsize = htons(curr_size); net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_HNA_IPV6_HDRSIZE; pair6 = m->v6.message.hna.hna_net; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + (2 * olsr_cnf->ipsize), remainsize, "HNA2"); } #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\tNet: %s/%d\n", olsr_ip_to_string(&h->net), h->prefix_len); #endif COPY_IP(&pair6->addr, &h->net); olsr_prefix_to_netmask(&tmp_netmask, h->prefix_len); COPY_IP(&pair6->netmask, &tmp_netmask); pair6++; curr_size += (2 * olsr_cnf->ipsize); h = h->next; } m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); net_outbuffer_push(ifp, msg_buffer, curr_size); //printf("Sending HNA (%d bytes)...\n", outputsize); return OLSR_FALSE; }