/*
- * OLSR ad-hoc routing table management protocol
- * Copyright (C) 2004 Andreas Tønnesen (andreto@ifi.uio.no)
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
+ * All rights reserved.
*
- * This file is part of the olsr.org OLSR daemon.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * olsr.org is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * * 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.
*
- * olsr.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * 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.
*
- * You should have received a copy of the GNU General Public License
- * along with olsr.org; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * $Id: parser.c,v 1.7 2004/09/21 19:08:57 kattemat Exp $
+ * 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: parser.c,v 1.32 2007/01/31 12:36:50 bernd67 Exp $
*/
#include "parser.h"
#include "mid_set.h"
#include "olsr.h"
#include "rebuild_packet.h"
+#include "net_os.h"
+#include "log.h"
+#include "print_packet.h"
-//union olsr_ip_addr tmp_addr;
#ifdef WIN32
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#define strerror(x) StrError(x)
#endif
+/* Sven-Ola: On very slow devices used in huge networks
+ * the amount of lq_tc messages is so high, that the
+ * recv() loop never ends. This is a small hack to end
+ * the loop in this cases
+ */
+
+unsigned int cpu_overload_exit = 0;
+
+struct parse_function_entry *parse_functions;
+
+static char inbuf[MAXMESSAGESIZE+1];
+
+static olsr_bool disp_pack_in = OLSR_FALSE;
+
+void
+parser_set_disp_pack_in(olsr_bool val)
+{
+ disp_pack_in = val;
+}
/**
*Initialize the parser.
void
olsr_init_parser()
{
- olsr_printf(3, "Initializing parser...\n");
-
- parse_functions = NULL;
+ OLSR_PRINTF(3, "Initializing parser...\n")
/* Initialize the packet functions */
olsr_init_package_process();
}
void
-olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
+olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), olsr_u32_t type, int forwarding)
{
struct parse_function_entry *new_entry;
- olsr_printf(3, "Parser: registering event for type %d\n", type);
+ OLSR_PRINTF(3, "Parser: registering event for type %d\n", type)
new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
new_entry->next = parse_functions;
parse_functions = new_entry;
- olsr_printf(3, "Register parse function: Added function for type %d\n", type);
+ OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type)
}
int
-olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
+olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), olsr_u32_t type, int forwarding)
{
struct parse_function_entry *entry, *prev;
}
-
-/**
- *Processing OLSR data from socket. Reading data, setting
- *wich interface recieved the message, Sends IPC(if used)
- *and passes the packet on to parse_packet().
- *
- *@param fd the filedescriptor that data should be read from.
- *@return nada
- */
-void
-olsr_input(int fd)
-{
- /* sockaddr_in6 is bigger than sockaddr !!!! */
- struct sockaddr_storage from;
- size_t fromlen;
- int cc;
- struct interface *olsr_in_if;
- union olsr_ip_addr from_addr;
- union
- {
- char buf[MAXMESSAGESIZE+1];
- struct olsr olsr;
- } inbuf;
-
-
- for (;;)
- {
- fromlen = sizeof(struct sockaddr_storage);
-
- cc = recvfrom(fd,
- (char *)&inbuf,
- sizeof (inbuf),
- 0,
- (struct sockaddr *)&from,
- &fromlen);
-
- if (cc <= 0)
- {
- if (cc < 0 && errno != EWOULDBLOCK)
- {
- olsr_printf(1, "error recvfrom: %s", strerror(errno));
- olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
- }
- break;
- }
-
- if(ipversion == AF_INET)
- {
- /* IPv4 sender address */
- COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
- }
- else
- {
- /* IPv6 sender address */
- COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
- }
-
- /* are we talking to ourselves? */
- if(if_ifwithaddr(&from_addr) != NULL)
- return;
-
-#ifdef DEBUG
- olsr_printf(5, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
-#endif
- //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
- if ((ipversion == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
- break;
- else if ((ipversion == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
- break;
-
- //printf("Recieved data on socket %d\n", socknr);
-
-
- if((olsr_in_if = if_ifwithsock(fd)) == NULL)
- {
- olsr_printf(1, "Could not find input interface for message from %s size %d\n",
- olsr_ip_to_string(&from_addr),
- cc);
- olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
- olsr_ip_to_string(&from_addr),
- cc);
- return ;
- }
-
- /*
- * &from - sender
- * &inbuf.olsr
- * cc - bytes read
- */
- parse_packet(&inbuf.olsr, cc, olsr_in_if, &from_addr);
-
- }
-}
-
-
-
-
/**
*Process a newly received OLSR packet. Checks the type
*and to the neccessary convertions and call the
int msgsize;
int processed;
struct parse_function_entry *entry;
- char *packet = (char*)olsr;
- int i;
- int x = 0;
count = size - ((char *)m - (char *)olsr);
- if (count < minsize)
+ if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
return;
-
if (ntohs(olsr->olsr_packlen) != size)
{
- olsr_printf(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
+ OLSR_PRINTF(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen))
olsr_syslog(OLSR_LOG_ERR, " packet length error in packet received from %s!",
olsr_ip_to_string(from_addr));
/* Display packet */
if(disp_pack_in)
- {
- printf("\n\tfrom: %s\n\tsize: %d\n\tcontent(decimal):\n\t", olsr_ip_to_string(from_addr), size);
-
- for(i = 0; i < size;i++)
- {
- if(x == 4)
- {
- x = 0;
- printf("\n\t");
- }
- x++;
- if(ipversion == AF_INET)
- printf(" %03i", (u_char) packet[i]);
- else
- printf(" %02x", (u_char) packet[i]);
- }
-
- printf("\n");
- }
+ print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
- if(ipversion == AF_INET)
+ if(olsr_cnf->ip_version == AF_INET)
msgsize = ntohs(m->v4.olsr_msgsize);
else
msgsize = ntohs(m->v6.olsr_msgsize);
/*
* Hysteresis update - for every OLSR package
*/
- if(use_hysteresis)
+ if(olsr_cnf->use_hysteresis)
{
- if(ipversion == AF_INET)
+ if(olsr_cnf->ip_version == AF_INET)
{
/* IPv4 */
update_hysteresis_incoming(from_addr,
- &in_if->ip_addr,
+ in_if,
ntohs(olsr->olsr_seqno));
}
else
{
/* IPv6 */
update_hysteresis_incoming(from_addr,
- &in_if->ip_addr,
+ in_if,
ntohs(olsr->olsr_seqno));
}
}
+ if (olsr_cnf->lq_level > 0)
+ {
+ olsr_update_packet_loss(from_addr, in_if,
+ ntohs(olsr->olsr_seqno));
+ }
for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
{
processed = 0;
- if (count < minsize)
+ if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
break;
- if(ipversion == AF_INET)
+ if(olsr_cnf->ip_version == AF_INET)
msgsize = ntohs(m->v4.olsr_msgsize);
else
msgsize = ntohs(m->v6.olsr_msgsize);
/* Check size of message */
if(count < 0)
{
- olsr_printf(1, "packet length error in packet received from %s!",
- olsr_ip_to_string(from_addr));
+ OLSR_PRINTF(1, "packet length error in packet received from %s!",
+ olsr_ip_to_string(from_addr))
olsr_syslog(OLSR_LOG_ERR, " packet length error in packet received from %s!",
olsr_ip_to_string(from_addr));
/* Treat TTL hopcnt */
- if(ipversion == AF_INET)
+ if(olsr_cnf->ip_version == AF_INET)
{
/* IPv4 */
- if (m->v4.ttl <= 0)
+ if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)
{
- olsr_printf(1, "Dropping packet type %d from neigh %s with TTL 0\n",
+ OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n",
m->v4.olsr_msgtype,
- olsr_ip_to_string(from_addr));
+ olsr_ip_to_string(from_addr))
continue;
}
}
else
{
/* IPv6 */
- if (m->v6.ttl <= 0)
+ if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0)
{
- olsr_printf(1, "Dropping packet type %d from %s with TTL 0\n",
+ OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n",
m->v4.olsr_msgtype,
- olsr_ip_to_string(from_addr));
+ olsr_ip_to_string(from_addr))
continue;
}
}
*/
/* Should be the same for IPv4 and IPv6 */
- if(COMP_IP(&m->v4.originator, &main_addr))
+ if(COMP_IP(&m->v4.originator, &olsr_cnf->main_addr))
{
#ifdef DEBUG
- olsr_printf(3, "Not processing message originating from us!\n");
+ OLSR_PRINTF(3, "Not processing message originating from us!\n")
#endif
continue;
}
{
unk_chgestruct(&unkpacket, m);
- olsr_printf(1, "Unknown type: %d, size %d, from %s\n",
+ OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",
m->v4.olsr_msgtype,
size,
- olsr_ip_to_string(&unkpacket.originator));
+ olsr_ip_to_string(&unkpacket.originator))
/* Forward message */
- if(!COMP_IP(&unkpacket.originator, &main_addr))
+ if(!COMP_IP(&unkpacket.originator, &olsr_cnf->main_addr))
{
/* Forward */
olsr_forward_message(m,
+/**
+ *Processing OLSR data from socket. Reading data, setting
+ *wich interface recieved the message, Sends IPC(if used)
+ *and passes the packet on to parse_packet().
+ *
+ *@param fd the filedescriptor that data should be read from.
+ *@return nada
+ */
+void
+olsr_input(int fd)
+{
+ /* sockaddr_in6 is bigger than sockaddr !!!! */
+ struct sockaddr_storage from;
+ socklen_t fromlen;
+ int cc;
+ struct interface *olsr_in_if;
+ union olsr_ip_addr from_addr;
+ cpu_overload_exit = 0;
+
+ for (;;)
+ {
+ if (32 < ++cpu_overload_exit)
+ {
+ OLSR_PRINTF(1, "CPU overload detected, ending olsr_input() loop\n")
+ break;
+ }
+
+ fromlen = sizeof(struct sockaddr_storage);
+
+ cc = olsr_recvfrom(fd,
+ inbuf,
+ sizeof (inbuf),
+ 0,
+ (struct sockaddr *)&from,
+ &fromlen);
+
+ if (cc <= 0)
+ {
+ if (cc < 0 && errno != EWOULDBLOCK)
+ {
+ OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno))
+ olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
+ }
+ break;
+ }
+
+ if(olsr_cnf->ip_version == AF_INET)
+ {
+ /* IPv4 sender address */
+ COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
+ }
+ else
+ {
+ /* IPv6 sender address */
+ COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
+ }
+
+
+#ifdef DEBUG
+ OLSR_PRINTF(5, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr))
+#endif
+
+ if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
+ break;
+ else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
+ break;
+
+ /* are we talking to ourselves? */
+ if(if_ifwithaddr(&from_addr) != NULL)
+ return;
+
+ if((olsr_in_if = if_ifwithsock(fd)) == NULL)
+ {
+ OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
+ olsr_ip_to_string(&from_addr),
+ cc)
+ olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
+ olsr_ip_to_string(&from_addr),
+ cc);
+ return ;
+ }
+
+ /*
+ * &from - sender
+ * &inbuf.olsr
+ * cc - bytes read
+ */
+ parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
+
+ }
+}
+
+
+
+
+/**
+ *Processing OLSR data from socket. Reading data, setting
+ *wich interface recieved the message, Sends IPC(if used)
+ *and passes the packet on to parse_packet().
+ *
+ *@param fd the filedescriptor that data should be read from.
+ *@return nada
+ */
+void
+olsr_input_hostemu(int fd)
+{
+ /* sockaddr_in6 is bigger than sockaddr !!!! */
+ struct sockaddr_storage from;
+ socklen_t fromlen;
+ int cc;
+ struct interface *olsr_in_if;
+ union olsr_ip_addr from_addr;
+ olsr_u16_t pcklen;
+
+ /* Host emulator receives IP address first to emulate
+ direct link */
+
+ if((cc = recv(fd, from_addr.v6.s6_addr, olsr_cnf->ipsize, 0)) != (int)olsr_cnf->ipsize)
+ {
+ fprintf(stderr, "Error receiving host-client IP hook(%d) %s!\n", cc, strerror(errno));
+ COPY_IP(&from_addr, &((struct olsr *)inbuf)->olsr_msg->originator);
+ }
+
+ /* are we talking to ourselves? */
+ if(if_ifwithaddr(&from_addr) != NULL)
+ return;
+
+ /* Extract size */
+ if((cc = recv(fd, &pcklen, 2, MSG_PEEK)) != 2)
+ {
+ if(cc <= 0)
+ {
+ fprintf(stderr, "Lost olsr_switch connection - exit!\n");
+ olsr_exit(__func__, EXIT_FAILURE);
+ }
+ fprintf(stderr, "[hust-emu] error extracting size(%d) %s!\n", cc, strerror(errno));
+ return;
+ }
+ else
+ {
+ pcklen = ntohs(pcklen);
+ }
+
+ fromlen = sizeof(struct sockaddr_storage);
+
+ cc = olsr_recvfrom(fd,
+ inbuf,
+ pcklen,
+ 0,
+ (struct sockaddr *)&from,
+ &fromlen);
+
+ if (cc <= 0)
+ {
+ if (cc < 0 && errno != EWOULDBLOCK)
+ {
+ OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno))
+ olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
+ }
+ return;
+ }
+
+ if(cc != pcklen)
+ {
+ printf("Could not read whole packet(size %d, read %d)\n", pcklen, cc);
+ return;
+ }
+
+ if((olsr_in_if = if_ifwithsock(fd)) == NULL)
+ {
+ OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
+ olsr_ip_to_string(&from_addr),
+ cc)
+ olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
+ olsr_ip_to_string(&from_addr),
+ cc);
+ return;
+ }
+
+ /*
+ * &from - sender
+ * &inbuf.olsr
+ * cc - bytes read
+ */
+ parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
+
+}
+
+