/*
* 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: packet.c,v 1.23 2007/08/02 22:07:19 bernd67 Exp $
*/
#include "defs.h"
#include "link_set.h"
#include "mpr_selector_set.h"
#include "mpr.h"
#include "olsr.h"
#include "neighbor_table.h"
#include "build_msg.h"
static olsr_bool sending_tc = OLSR_FALSE;
/**
*Free the memory allocated for a HELLO packet.
*
*@param message the pointer to the packet to erase
*
*@return nada
*/
void
olsr_free_hello_packet(struct hello_message *message)
{
struct hello_neighbor *nb, *prev_nb;
if(!message)
return;
nb = message->neighbors;
while (nb)
{
prev_nb = nb;
nb = nb->next;
free(prev_nb);
}
}
/**
*Build an internal HELLO package for this
*node. This MUST be done for each interface.
*
*@param message the hello_message struct to fill with info
*@param outif the interface to send the message on - messages
*are created individually for each interface!
*@return 0
*/
int
olsr_build_hello_packet(struct hello_message *message, struct interface *outif)
{
struct hello_neighbor *message_neighbor, *tmp_neigh;
struct link_entry *links;
struct neighbor_entry *neighbor;
int idx;
#ifdef DEBUG
OLSR_PRINTF(3, "\tBuilding HELLO on interface %d\n", outif->if_nr);
#endif
message->neighbors=NULL;
message->packet_seq_number=0;
//message->mpr_seq_number=neighbortable.neighbor_mpr_seq;
/* Set willingness */
message->willingness = olsr_cnf->willingness;
#ifdef DEBUG
OLSR_PRINTF(3, "Willingness: %d\n", olsr_cnf->willingness);
#endif
/* Set TTL */
message->ttl = 1;
COPY_IP(&message->source_addr, &olsr_cnf->main_addr);
#ifdef DEBUG
OLSR_PRINTF(5, "On link:\n");
#endif
/* Get the links of this interface */
links = get_link_set();
while(links != NULL)
{
int lnk = lookup_link_status(links);
/* Update the status */
/* Check if this link tuple is registered on the outgoing interface */
if(!COMP_IP(&links->local_iface_addr, &outif->ip_addr))
{
links = links->next;
continue;
}
message_neighbor = olsr_malloc(sizeof(struct hello_neighbor), "Build HELLO");
/* Find the link status */
message_neighbor->link = lnk;
/*
* Calculate neighbor status
*/
/*
* 2.1 If the main address, corresponding to
* L_neighbor_iface_addr, is included in the MPR set:
*
* Neighbor Type = MPR_NEIGH
*/
if(links->neighbor->is_mpr)
{
message_neighbor->status = MPR_NEIGH;
}
/*
* 2.2 Otherwise, if the main address, corresponding to
* L_neighbor_iface_addr, is included in the neighbor set:
*/
/* NOTE:
* It is garanteed to be included when come this far
* due to the extentions made in the link sensing
* regarding main addresses.
*/
else
{
/*
* 2.2.1
* if N_status == SYM
*
* Neighbor Type = SYM_NEIGH
*/
if(links->neighbor->status == SYM)
{
message_neighbor->status = SYM_NEIGH;
}
/*
* 2.2.2
* Otherwise, if N_status == NOT_SYM
* Neighbor Type = NOT_NEIGH
*/
else
if(links->neighbor->status == NOT_SYM)
{
message_neighbor->status = NOT_NEIGH;
}
}
/* Set the remote interface address */
COPY_IP(&message_neighbor->address, &links->neighbor_iface_addr);
/* Set the main address */
COPY_IP(&message_neighbor->main_address, &links->neighbor->neighbor_main_addr);
#ifdef DEBUG
OLSR_PRINTF(5, "Added: %s - ", olsr_ip_to_string(&message_neighbor->address));
OLSR_PRINTF(5, " status %d\n", message_neighbor->status);
#endif
message_neighbor->next=message->neighbors;
message->neighbors=message_neighbor;
links = links->next;
}
/* Add the links */
#ifdef DEBUG
OLSR_PRINTF(5, "Not on link:\n");
#endif
/* Add the rest of the neighbors if running on multiple interfaces */
if(ifnet != NULL && ifnet->int_next != NULL)
for(idx=0;idx<HASHSIZE;idx++)
{
for(neighbor = neighbortable[idx].next;
neighbor != &neighbortable[idx];
neighbor=neighbor->next)
{
/* Check that the neighbor is not added yet */
tmp_neigh = message->neighbors;
//printf("Checking that the neighbor is not yet added\n");
while(tmp_neigh)
{
if(COMP_IP(&tmp_neigh->main_address, &neighbor->neighbor_main_addr))
{
//printf("Not adding duplicate neighbor %s\n", olsr_ip_to_string(&neighbor->neighbor_main_addr));
break;
}
tmp_neigh = tmp_neigh->next;
}
if(tmp_neigh)
continue;
message_neighbor = olsr_malloc(sizeof(struct hello_neighbor), "Build HELLO 2");
message_neighbor->link = UNSPEC_LINK;
/*
* Calculate neighbor status
*/
/*
* 2.1 If the main address, corresponding to
* L_neighbor_iface_addr, is included in the MPR set:
*
* Neighbor Type = MPR_NEIGH
*/
if(neighbor->is_mpr)
{
message_neighbor->status = MPR_NEIGH;
}
/*
* 2.2 Otherwise, if the main address, corresponding to
* L_neighbor_iface_addr, is included in the neighbor set:
*/
/* NOTE:
* It is garanteed to be included when come this far
* due to the extentions made in the link sensing
* regarding main addresses.
*/
else
{
/*
* 2.2.1
* if N_status == SYM
*
* Neighbor Type = SYM_NEIGH
*/
if(neighbor->status == SYM)
{
message_neighbor->status = SYM_NEIGH;
}
/*
* 2.2.2
* Otherwise, if N_status == NOT_SYM
* Neighbor Type = NOT_NEIGH
*/
else
if(neighbor->status == NOT_SYM)
{
message_neighbor->status = NOT_NEIGH;
}
}
COPY_IP(&message_neighbor->address, &neighbor->neighbor_main_addr);
COPY_IP(&message_neighbor->main_address, &neighbor->neighbor_main_addr);
#ifdef DEBUG
OLSR_PRINTF(5, "Added: %s - ", olsr_ip_to_string(&message_neighbor->address));
OLSR_PRINTF(5, " status %d\n", message_neighbor->status);
#endif
message_neighbor->next=message->neighbors;
message->neighbors=message_neighbor;
}
}
return 0;
}
/**
*Free the memory allocated for a TC packet.
*
*@param message the pointer to the packet to erase
*
*@return nada
*/
void
olsr_free_tc_packet(struct tc_message *message)
{
struct tc_mpr_addr *mprs, *prev_mprs;
if(!message)
return;
mprs = message->multipoint_relay_selector_address;
while (mprs)
{
prev_mprs = mprs;
mprs = mprs->next;
free(prev_mprs);
}
}
/**
*Build an internal TC package for this
*node.
*
*@param message the tc_message struct to fill with info
*@return 0
*/
int
olsr_build_tc_packet(struct tc_message *message)
{
struct tc_mpr_addr *message_mpr;
//struct mpr_selector *mprs;
int idx;
struct neighbor_entry *entry;
//struct mpr_selector_hash *mprs_hash;
olsr_bool entry_added = OLSR_FALSE;
message->multipoint_relay_selector_address=NULL;
message->packet_seq_number=0;
message->hop_count = 0;
message->ttl = MAX_TTL;
message->ansn = get_local_ansn();
COPY_IP(&message->originator, &olsr_cnf->main_addr);
COPY_IP(&message->source_addr, &olsr_cnf->main_addr);
/* Loop trough all neighbors */
for(idx=0;idx<HASHSIZE;idx++)
{
for(entry = neighbortable[idx].next;
entry != &neighbortable[idx];
entry = entry->next)
{
if(entry->status != SYM)
continue;
switch(olsr_cnf->tc_redundancy)
{
case(2):
{
/* 2 = Add all neighbors */
//printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC");
COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
message_mpr->next = message->multipoint_relay_selector_address;
message->multipoint_relay_selector_address = message_mpr;
entry_added = OLSR_TRUE;
break;
}
case(1):
{
/* 1 = Add all MPR selectors and selected MPRs */
if((entry->is_mpr) ||
(olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL))
{
//printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC 2");
COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
message_mpr->next = message->multipoint_relay_selector_address;
message->multipoint_relay_selector_address = message_mpr;
entry_added = OLSR_TRUE;
}
break;
}
default:
{
/* 0 = Add only MPR selectors(default) */
if(olsr_lookup_mprs_set(&entry->neighbor_main_addr) != NULL)
{
//printf("\t%s\n", olsr_ip_to_string(&mprs->mpr_selector_addr));
message_mpr = olsr_malloc(sizeof(struct tc_mpr_addr), "Build TC 3");
COPY_IP(&message_mpr->address, &entry->neighbor_main_addr);
message_mpr->next = message->multipoint_relay_selector_address;
message->multipoint_relay_selector_address = message_mpr;
entry_added = OLSR_TRUE;
}
break;
}
} /* Switch */
} /* For */
} /* For idx */
if(entry_added)
{
sending_tc = OLSR_TRUE;
}
else
{
if(sending_tc)
{
/* Send empty TC */
OLSR_PRINTF(3, "No more MPR selectors - will send empty TCs\n");
set_empty_tc_timer(GET_TIMESTAMP((olsr_cnf->max_tc_vtime*3)*1000));
sending_tc = OLSR_FALSE;
}
}
return 0;
}
/**
*Free the memory allocated for a HNA packet.
*
*@param message the pointer to the packet to erase
*
*@return nada
*/
void
olsr_free_hna_packet(struct hna_message *message)
{
struct hna_net_addr *hna_tmp, *hna_tmp2;
hna_tmp = message->hna_net;
while(hna_tmp)
{
hna_tmp2 = hna_tmp;
hna_tmp = hna_tmp->next;
free(hna_tmp2);
}
}
/**
*Free the memory allocated for a MID packet.
*
*@param message the pointer to the packet to erase
*
*@return nada
*/
void
olsr_free_mid_packet(struct mid_message *message)
{
struct mid_alias *tmp_adr, *tmp_adr2;
tmp_adr = message->mid_addr;
while(tmp_adr)
{
tmp_adr2 = tmp_adr;
tmp_adr = tmp_adr->next;
free(tmp_adr2);
}
}
syntax highlighted by Code2HTML, v. 0.9.1