⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.c

📁 wifi 无线网络路由协议OLSR linux下C代码
💻 C
字号:
/* * The olsr.org Optimized Link-State Routing daemon(olsrd) * Copyright (c) 2004, Andreas T鴑nesen(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: parser.c,v 1.35 2007/05/08 23:34:52 bernd67 Exp $ */#include "parser.h"#include "defs.h"#include "process_package.h"#include "mantissa.h"#include "hysteresis.h"#include "duplicate_set.h"#include "mid_set.h"#include "olsr.h"#include "rebuild_packet.h"#include "net_os.h"#include "log.h"#include "print_packet.h"#ifdef WIN32#undef EWOULDBLOCK#define EWOULDBLOCK WSAEWOULDBLOCK#undef errno#define errno WSAGetLastError()#undef strerror#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;voidparser_set_disp_pack_in(olsr_bool val){  disp_pack_in = val;}/** *Initialize the parser.  * *@return nada */voidolsr_init_parser(void){  OLSR_PRINTF(3, "Initializing parser...\n");  /* Initialize the packet functions */  olsr_init_package_process();}voidolsr_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);   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");  new_entry->function = function;  new_entry->type = type;  new_entry->caller_forwarding = forwarding;  /* Queue */  new_entry->next = parse_functions;  parse_functions = new_entry;  OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type);}intolsr_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;  entry = parse_functions;  prev = NULL;  while(entry)    {      if((entry->function == function) &&	 (entry->type == type) &&	 (entry->caller_forwarding == forwarding))	{	  if(entry == parse_functions)	    {	      parse_functions = entry->next;	    }	  else	    {	      prev->next = entry->next;	    }	  free(entry);	  return 1;	}      prev = entry;      entry = entry->next;    }  return 0;}/** *Process a newly received OLSR packet. Checks the type *and to the neccessary convertions and call the *corresponding functions to handle the information. *@param from the sockaddr struct describing the sender *@param olsr the olsr struct containing the message *@param size the size of the message *@return nada */voidparse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr){  union olsr_message *m = (union olsr_message *)olsr->olsr_msg;  struct unknown_message unkpacket;  int count;  int msgsize;  int processed;  struct parse_function_entry *entry;  count = size - ((char *)m - (char *)olsr);  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_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",	     olsr_ip_to_string(from_addr));      return;    }  //printf("Message from %s\n\n", olsr_ip_to_string(from_addr));         /* Display packet */  if(disp_pack_in)    print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);  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(olsr_cnf->use_hysteresis)    {      if(olsr_cnf->ip_version == AF_INET)	{	  /* IPv4 */	  update_hysteresis_incoming(from_addr, 				     in_if,				     ntohs(olsr->olsr_seqno));	}      else	{	  /* IPv6 */	  update_hysteresis_incoming(from_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 < MIN_PACKET_SIZE(olsr_cnf->ip_version))	break;            if(olsr_cnf->ip_version == AF_INET)	msgsize = ntohs(m->v4.olsr_msgsize);      else	msgsize = ntohs(m->v6.olsr_msgsize);            count -= 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_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",		 olsr_ip_to_string(from_addr));	  break;	}      /* Treat TTL hopcnt */      if(olsr_cnf->ip_version == AF_INET)	{	  /* IPv4 */	  if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)	    {	      OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n", 			  m->v4.olsr_msgtype,			  olsr_ip_to_string(from_addr));	      continue;	    }	}      else	{	  /* IPv6 */	  if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0) 	    {	      OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n", 			  m->v4.olsr_msgtype,			  olsr_ip_to_string(from_addr));	      continue;	    }	}      /*RFC 3626 section 3.4:       *  2    If the time to live of the message is less than or equal to       *  '0' (zero), or if the message was sent by the receiving node       *  (i.e., the Originator Address of the message is the main       *  address of the receiving node): the message MUST silently be       *  dropped.       */      /* Should be the same for IPv4 and IPv6 */      if(COMP_IP(&m->v4.originator, &olsr_cnf->main_addr))	{#ifdef DEBUG	  OLSR_PRINTF(3, "Not processing message originating from us!\n");#endif	  continue;	}      //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);      entry = parse_functions;      while(entry)	{	  /* Should be the same for IPv4 and IPv6 */	  /* Promiscuous or exact match */	  if((entry->type == PROMISCUOUS) || 	     (entry->type == m->v4.olsr_msgtype))	    {	      entry->function(m, in_if, from_addr);	      if(entry->caller_forwarding)		processed = 1;	    }	  entry = entry->next;	}      /* UNKNOWN PACKETTYPE */      if(processed == 0)	{	  unk_chgestruct(&unkpacket, m);	  	  OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",		      m->v4.olsr_msgtype,		      size,		      olsr_ip_to_string(&unkpacket.originator));	  /* Forward message */	  if(!COMP_IP(&unkpacket.originator, &olsr_cnf->main_addr))	    {	      	      /* Forward */	      olsr_forward_message(m, 				   &unkpacket.originator, 				   unkpacket.seqno, 				   in_if,				   from_addr);	    }	}    } /* for olsr_msg */ }/** *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 */voidolsr_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 */voidolsr_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, (void *)&pcklen, 2, MSG_PEEK)) != 2) /* Win needs a cast */    {      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)	{          const char * const err_msg = strerror(errno);	  OLSR_PRINTF(1, "error recvfrom: %s", err_msg);          olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %s", err_msg);	}      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);  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -