/*
* 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
*
*<b>NO INTERNAL BUFFER</b>
*@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
*<b>NB! Not internal packetformat!</b>
*
*@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
*
*<b>NO INTERNAL BUFFER</b>
*@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
*
*<b>NO INTERNAL BUFFER</b>
*@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;
}
syntax highlighted by Code2HTML, v. 0.9.1