igmp_router_receive.c

来自「路由器协议平台igmp协议设计实现源码。」· C语言 代码 · 共 206 行

C
206
字号
/*
 $Log:: /OEM Source Code/igmp/igmp_router_receive.c                                                $
 * 
 * 1     4/23/98 9:53p Release Engineer
 * Initial release
 * IGMP v4.1.0
 */
/************************************************************************/
/*  Copyright (C) 1997-1998 RouterWare, Inc.                            */
/*  Unpublished - rights reserved under the Copyright Laws of the       */
/*  United States.  Use, duplication, or disclosure by the              */
/*  Government is subject to restrictions as set forth in               */
/*  subparagraph (c)(1)(ii) of the Rights in Technical Data and         */
/*  Computer Software clause at 252.227-7013.                           */
/*  RouterWare, Inc., 3961 MacArthur Blvd. Suite 212, Newport Beach, CA */
/************************************************************************/
#include "igmp.h"
/********************************************************************************************/
static void igmp_router_process_membership_query_message (IGMP_MESSAGE *sptr_igmp_message);
static enum BOOLEAN igmp_received_a_wrong_version_query (IGMP_MESSAGE *sptr_igmp_message);
static enum TEST igmp_set_ip_address_of_last_reporter (UINT port, ULONG group_ip_address, ULONG ip_address_of_last_reporter);
/********************************************************************************************/
void igmp_router_process_received_message (IGMP_MESSAGE *sptr_igmp_message)
{
	UINT port;

	port = sptr_igmp_message->receiving_port;

	switch (sptr_igmp_message->type)
		{
		case IGMP_MEMBERSHIP_QUERY:
			igmp_router_process_membership_query_message (sptr_igmp_message);

			break;

		case IGMP_V1_MEMBERSHIP_REPORT:
			if (igmp_set_ip_address_of_last_reporter (port, sptr_igmp_message->group_ip_address, sptr_igmp_message->source_ip_address) == FAIL)
				{
				/* we were unable to locate/add the group over the port */
				return;
				}
				
			igmp_process_router_group_state_transition (port, sptr_igmp_message->group_ip_address, IGMP_ROUTER_GROUP_V1_REPORT_RECEIVED_EVENT);

			break;

		case IGMP_V2_MEMBERSHIP_REPORT:
			if (igmp.port_table[port].version == IGMP_VERSION_2)
				{
				if (igmp_set_ip_address_of_last_reporter (port, sptr_igmp_message->group_ip_address, sptr_igmp_message->source_ip_address) == FAIL)
					{
					/* we were unable to locate/add the group over the port */
					return;
					}

				igmp_process_router_group_state_transition (port, sptr_igmp_message->group_ip_address, IGMP_ROUTER_GROUP_V2_REPORT_RECEIVED_EVENT);
				}
			else if (igmp.port_table[port].version == IGMP_VERSION_1)
				{
				IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Router: IGNORING received VERSION 2 report on port %u configured for VERSION 1.\n",
						port);
				}
			
			break;

		case IGMP_LEAVE_GROUP:
			if (igmp.port_table[port].version == IGMP_VERSION_2)
				{
				igmp_process_router_group_state_transition (port, sptr_igmp_message->group_ip_address, IGMP_ROUTER_GROUP_LEAVE_MESSAGE_RECEIVED_EVENT);
				}
			else
				{
				IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Router: IGNORING received Leave Group Message on port %u configured for VERSION 1.\n",
						port);
				}
				
			break;
	
		default:
			IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Router: Received UNKNOWN message type on port %u.\n", port);

			break;
		}
}
/********************************************************************************************/
static void igmp_router_process_membership_query_message (IGMP_MESSAGE *sptr_igmp_message)
{
	IGMP_GROUP_CLASS *sptr_matching_group_node;
	UINT port;

	port = sptr_igmp_message->receiving_port;

	/* check for wrong version queries */
	/* the most important issue here is whether we stop processing	this message or should we continue?
		the author of this code	believes that we must STOP processing this message and expect
		an administrative router port version reconfiguration.
	*/
	if (igmp_received_a_wrong_version_query (sptr_igmp_message) == TRUE)
		{
		return;
		}
		
	if (sptr_igmp_message->max_response_time == 0)
		{
		/* this query was generated by a v1 router */
		igmp.port_table[port].max_response_time_from_most_recent_query = IGMP_DEFAULT_GENERAL_QUERY_MAX_RESPONSE_INTERVAL;
		}
	else
		{
		igmp.port_table[port].max_response_time_from_most_recent_query = sptr_igmp_message->max_response_time / IGMP_HOST_RESPONSE_TIME_DIVIDER ; /* seconds */
		}

	/* now, whatever the query be, check if the sender of this query should be the querier */
	if (sptr_igmp_message->source_ip_address < igmp.port_table[port].ip_address_of_port)
		{
		/* igmp v2 draft specifies that there should be no querier to non-querier state transition when the router has heard
			a leave group message. para 7, section 3.
		*/
		if (igmp.port_table[port].router_port.state == IGMP_ROUTER_PORT_QUERIER_STATE)
			{
			for (sptr_matching_group_node = (IGMP_GROUP_CLASS *) get_pointer_to_first_entry_in_list ((LINK *) &igmp.port_table[port].active_group_list);
				sptr_matching_group_node != NULL;
				sptr_matching_group_node = (IGMP_GROUP_CLASS *) get_pointer_to_next_entry_in_list ((LINK *) &sptr_matching_group_node->links))
				{
				if (sptr_matching_group_node->router_group.state == IGMP_ROUTER_GROUP_CHECKING_MEMBERSHIP_STATE)
					{
					return;
					}
				}
			}

		igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceQuerier = sptr_igmp_message->source_ip_address;

		igmp_process_router_port_state_transition (port, sptr_igmp_message->group_ip_address, IGMP_ROUTER_PORT_QUERY_RECEIVED_FROM_ROUTER_WITH_LOWER_IP_ADDRESS_EVENT);
		}

	/* group specific queries are meaningful only when the port is in non-querier state */
	if (sptr_igmp_message->group_ip_address != 0x00000000L) /* a group specific query */
		{
		if (igmp.port_table[port].router_port.state == IGMP_ROUTER_PORT_NON_QUERIER_STATE)
			{
			igmp_process_router_group_state_transition (port, sptr_igmp_message->group_ip_address, IGMP_ROUTER_GROUP_SPECIFIC_QUERY_RECEIVED_EVENT);
			}
		}
}
/********************************************************************************************/
static enum BOOLEAN igmp_received_a_wrong_version_query (IGMP_MESSAGE *sptr_igmp_message)
{
	UINT port;

	port = sptr_igmp_message->receiving_port;

	if (igmp.port_table[port].version == IGMP_VERSION_1)
		{
		++igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceWrongVersionQueries;

		if (sptr_igmp_message->max_response_time != 0)
			{
			IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Router: Received a VERSION 2 Query on port %u configured for VERSION 1.\n",
					port);
			
			return (TRUE);
			}
		}

	if (igmp.port_table[port].version == IGMP_VERSION_2)
		{
		++igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceWrongVersionQueries;

		if (sptr_igmp_message->max_response_time == 0)
			{
			IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Router: Received a VERSION 1 Query on port %u configured for VERSION 2.\n",
					port);

			return (TRUE);
			}
		}

	return (FALSE);
}
/********************************************************************************************/
static enum TEST igmp_set_ip_address_of_last_reporter (UINT port, ULONG group_ip_address, ULONG ip_address_of_last_reporter)
{
	IGMP_GROUP_CLASS *sptr_igmp_group_node;
	char ip_address[IP_ADDRESS_PRINT_BUFFER_SIZE];

	sptr_igmp_group_node = igmp_get_matching_group_node_on_port (group_ip_address, port);

	if (sptr_igmp_group_node == NULL)
		{
		sptr_igmp_group_node = igmp_add_group_to_port (group_ip_address, port);

		if (sptr_igmp_group_node == NULL)
			{
			/* failed to locate and add the group node */
			IGMP_PROTOCOL_ALARM_TRACE (IGMP_ALARM_TRACE, "IGMP Router: Unable to add node for %s on port %u.\n",
					convert_ip_address_to_dot_format (&ip_address[0], group_ip_address), port);

			return (FAIL);
			}
		}

	sptr_igmp_group_node->ip_address_of_last_reporter = ip_address_of_last_reporter;

	return (PASS);
}

⌨️ 快捷键说明

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