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

📄 plugs.c

📁 altera epxa1的例子程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	}

//
// Accept ip match, or filter = -1 gets everything
int ip_address_equal(net_32 packet_ip_address,net_32 filter_ip_address)
	{
	return (filter_ip_address == 0xffffffff) || (packet_ip_address == filter_ip_address);
	}

//
// Accept ip match, or filter = -1 gets everything
int port_number_equal(net_16 packet_port,net_16 filter_port)
	{
	return (filter_port == 0xffff) || (packet_port == filter_port);
	}

// debug routine: get_protocol_name
#if PLUGS_DEBUG
char *get_protocol_name(int protocol)
	{
	switch(protocol)
		{
		case ne_plugs_ethernet:
					return "ethernet";
		case ne_plugs_arp:
					return "arp";
		case ne_plugs_ip:
					return "ip";
		case ne_plugs_icmp:
					return "icmp";
		case ne_plugs_udp:
					return "udp";
		case ne_plugs_tcp_raw:
		case ne_plugs_tcp:
					return "tcp";
		default:
					return "unknown";
		}
	}
#endif

// nr_plugs_dispatch_packet
//
// Examine an ethernet packet and find out what protocol
// it is.
// Then loop through every plug and see which ones should
// receive this packet.
//
// This routine is called by an adapters polling proc.
//
int nr_plugs_dispatch_packet(void *pp,int packet_length,void *context)
	{
	ns_plugs_ethernet_packet *packet = pp;	// only one link_layer_type today.
	s_plugs_globals *g = &ng_plugs_globals;
	//int is_protocol[ne_plugs_last_protocol];
	ns_plugs_packet sub_protocol[ne_plugs_last_protocol];
	int i;
	s_plugs_plug *plug;
	int p;
	long plug_bitmask;
	int got_tcp = 0; // so only one tcp plug gets a tcp packet
	s_plugs_adapter_entry *a = context;

	// | since most interesting packets are ip-derivative,
	// | we figure out the sizes &c and put them in these vars
	// |

	ns_plugs_ip_packet *ip_packet; // if incoming packet is ip or better...
	void *past_ip_packet; // if incoming packet is ip or better
	int ip_payload_length;

	// | Not running? go home now.
	// |

	if(!g->running)
		return ne_plugs_error_not_initialized; // | plugs not initialized

	g->in_dispatch++;

	// |
	// | Start with no protocol set

	for(i = 0; i < ne_plugs_last_protocol; i++)
		{
		sub_protocol[i].header = 0;
		sub_protocol[i].length = 0;
		}

	// |
	// | Every packet is "ethernet"

	sub_protocol[ne_plugs_ethernet].header = (void *)packet;
	sub_protocol[ne_plugs_ethernet].length = packet_length;

	// |
	// | Check progressive layers of protocol numbers

	p = nm_n2h16(packet->type);

   	if(p == ne_plugs_ethernet_arp)
		{
//MR		sub_protocol[ne_plugs_arp].header = &packet->payload;
		sub_protocol[ne_plugs_arp].header = (void *)&packet->payload;
		sub_protocol[ne_plugs_arp].length = 28;
		}
	else if(p == ne_plugs_ethernet_ip)
		{
		//
		// | It's an IP packet! but what kind?

		ip_packet = (ns_plugs_ip_packet *)packet->payload;

#if PLUGS_DEBUG
	if (ip_packet->flags_fragment & nm_h2n16(0xbfff))
		printf("   [plugs] | Ignored fragmented IP packet (0x%04x)\n",ip_packet->flags_fragment);
//MR #endif PLUGS_DEBUG
#endif

		if
				(
				((ip_packet->version_header_length & 0x00f0) == 0x0040)	// ipv4 only
				&&
				((ip_packet->flags_fragment & nm_h2n16(0xbfff)) == 0)	// ignore fragments!
				)
			{
			int ip_packet_length;
			void *ip_payload;

			// | stash the common ip packet info
			// |

			ip_packet_length = nr_n2h16(ip_packet->length);
			sub_protocol[ne_plugs_ip].header = (void *)ip_packet;
			sub_protocol[ne_plugs_ip].length = ip_packet_length;

			// temporarily put header-length into this ip_payload_length variable
			ip_payload_length = (ip_packet->version_header_length & 0x0f) * 4;
			past_ip_packet = (void *)((int)ip_packet + ip_payload_length);

//mr
//			ip_payload = ((void *)ip_packet) + ip_payload_length;
			ip_payload = ((char *)ip_packet) + ip_payload_length;

			// And now put the actual payload length into it
			ip_payload_length = ip_packet_length - ip_payload_length;

			if(ip_packet->protocol == ne_plugs_ip_icmp)
				{
				sub_protocol[ne_plugs_icmp].header = ip_payload;
				sub_protocol[ne_plugs_icmp].length = ip_payload_length;
				}
			else if(ip_packet->protocol == ne_plugs_ip_udp)
				{
				sub_protocol[ne_plugs_udp].header = ip_payload;
				sub_protocol[ne_plugs_udp].length = ip_payload_length;
				}
			else if(ip_packet->protocol == ne_plugs_ip_tcp)
				{
				sub_protocol[ne_plugs_tcp_raw].header = ip_payload;
				sub_protocol[ne_plugs_tcp_raw].length = ip_payload_length;
				sub_protocol[ne_plugs_tcp].header = ip_payload;
				sub_protocol[ne_plugs_tcp].length = ip_payload_length;
				}
			}
		}

	// |
	// | The array sub_protocol now shows what protocol(s)
	// | this packet is.

	// | Loop through the plugs and call any
	// | plug that has a receiver-proc and wants this packet.
	// |

	plug_bitmask = 0;				// start with no plug-recipients
	got_tcp = 0; // at most one tcp plug gets each tcp packet

	plug = g->plug;
	for(i = 0; i < PLUGS_PLUG_COUNT; i++)
		{
		// |
		// | Each plug is associated with a particular adapter.
		// | We only look at plugs for the adapter that got
		// | this packet, else skip along.
		// |

		if(a != &g->adapter[plug->flags & ne_plugs_flag_adapter_index_mask])
			goto next_plug;

#if PLUGS_DEBUG
		if(plug->flags & ne_plugs_flag_debug_rx)
			{
			int j;

			// Dont print the "ignores" messages unless debug level 2
			if( sub_protocol[plug->protocol].header || (PLUGS_DEBUG & 2) )
				{
				for(j = ne_plugs_last_protocol - 1; j > 0; j--)
					if(sub_protocol[j].header)
						break;
				printf("   [plugs] +-----------------------\n");
				printf("   [plugs] | plug %d (%s): %s a %d byte %s packet\n",i,
					get_protocol_name(plug->protocol),
					sub_protocol[plug->protocol].header ? "examines" : "ignores",
					packet_length,
					get_protocol_name(j));
				}
			}
#endif
		if(sub_protocol[plug->protocol].header)
			{
			void *payload;
			int payload_length;
			int for_the_plug = 0;		// well check this later
			int ip_address_match;
			int ethernet_address_match;
			int port_match = 0;

			// First things first:
			// Do we even care the slightest bit about
			// this ethernet packet?
			// The hardware may or may not already
			// be in promiscuous mode, but regardless,
			// if the packet gets to this routine, we
			// should verify that we want it.

			ethernet_address_match =
					((plug->flags & ne_plugs_flag_ethernet_all) != 0)
					||
						(
						((plug->flags & ne_plugs_flag_ethernet_broadcast) != 0)
						&&
						(packet->destination_address.u32 == 0xffffFFFF)
						&&
						(packet->destination_address.l16 == 0xffff)
						)
					||
						ethernet_address_equal
								(&packet->destination_address,
								&a->settings.ethernet_address
								);

			//
			// Since ip, icmp, udp, and tcp all rely on
			// matching source & destination ip addresses,
			// we check those once out here, if the
			// packet is ip flavored.

			ip_address_match =
					ethernet_address_match
					&&
					(packet->type == nm_h2n16(ne_plugs_ethernet_ip))
					&&
					ip_address_equal
							(
							ip_packet->destination_ip_address,
							a->settings.ip_address
							)
					&&
					ip_address_equal
							(ip_packet->source_ip_address,
							plug->remote_ip_address
							);

			//
			// Since udp & tcp rely on port matching, we'll do that here, too
			// udp & tcp have port info in same position (thankyou!)

			if(sub_protocol[ne_plugs_udp].header || sub_protocol[ne_plugs_tcp_raw].header)
				{
				// |
				// | Get port number from udp or tcp header -- first bytes
				// | are port numbers in either case, so cast as udp header.
				// |

				ns_plugs_udp_packet *udpp = sub_protocol[ne_plugs_udp].header;
				if(!udpp)
					udpp = sub_protocol[ne_plugs_tcp_raw].header;
				port_match =
						ip_address_match
						&&
						port_number_equal
								(
								udpp->destination_port,
								plug->local_port
								)
						&&
						port_number_equal
								(
								udpp->source_port,
								plug->remote_port
								);
				}

#if PLUGS_DEBUG
			if(plug->flags & ne_plugs_flag_debug_rx)
				{
				printf("   [plugs] | ");
				if(sub_protocol[ne_plugs_udp].header || sub_protocol[ne_plugs_tcp_raw].header)
					printf("port_match = %d, ",port_match);
				if(sub_protocol[ne_plugs_ip].header)
					printf("ip_address_match = %d, ",ip_address_match);
				printf("ethernet_address_match = %d\n",ethernet_address_match);
				if(sub_protocol[ne_plugs_ip].header && !ip_address_match)
					{
					printf("   [plugs] |      packet source ip address: ");
					nr_plugs_print_ip_address(ip_packet->source_ip_address);
					printf("\n   [plugs] | packet destination ip address: ");
					nr_plugs_print_ip_address(ip_packet->destination_ip_address);
					printf("\n   [plugs] |              local ip address: ");
					nr_plugs_print_ip_address(a->settings.ip_address);
					printf("\n");
					}
				if(!ethernet_address_match)
					{
					printf("   [plugs] |      packet source ethernet address: ");
					nr_plugs_print_ethernet_address(&packet->source_address);
					printf("\n   [plugs] | packet destination ethernet address: ");
					nr_plugs_print_ethernet_address(&packet->destination_address);
					printf("\n   [plugs] |              local ethernet address: ");
					nr_plugs_print_ethernet_address(&a->settings.ethernet_address);
					printf("\n");
					}
				}
#endif
			//
			// The packet is a type this plug listens to.
			// Check out other filtration (ethernet address,
			// port numbers, &c.)

			switch(plug->protocol)
				{
				case ne_plugs_ethernet:		// Ethernet proc gets whole packet
					//
					// Filter by ethernet address

					if(ethernet_address_match)
						{
//MR						payload = packet;
						payload = (void *)packet;
						payload_length = packet_length;
						for_the_plug = 1;
						}
					break;

				case ne_plugs_arp:		// ARP proc gets ARP header
					//
					// Filter by ethernet address

					if(ethernet_address_match)
						{
//MR						payload = packet->payload;
						payload = (void *)packet->payload;
//MR						payload_length = sizeof(ns_plugs_arp_packet);
						payload_length = sizeof(ns_plugs_arp_packet) - 1;
						for_the_plug = 1;
						}
					break;

				case ne_plugs_icmp:	// ICMP proc gets ICMP header, IP gets own payload
				case ne_plugs_ip:
					if(ip_address_match)
						{
						payload = past_ip_packet;
						payload_length = ip_payload_length;
						for_the_plug = 1;
						}
					break;

				case ne_plugs_udp:
					if(port_match)
						{
//MR						payload = ((ns_plugs_udp_packet *)past_ip_packet)->payload;
						payload = (void *)(((ns_plugs_udp_packet *)past_ip_packet)->payload);
//MR						payload_length = ip_payload_length - sizeof(ns_plugs_udp_packet);
						payload_length = ip_payload_length - sizeof(ns_plugs_udp_packet) - 1;
						for_the_plug = 1;
						}
					break;

				case ne_plugs_tcp_raw:
#if PLUGS_TCP
				case ne_plugs_tcp:
//MR #endif PLUGS_TCP
#endif
					if(port_match && !got_tcp)
						{
						payload = past_ip_packet;
						payload = (void *)((int)payload
								+ (nr_n2h16(((ns_plugs_tcp_packet *)past_ip_packet)->header_length_flags) >> 12) * 4);
						payload_length = nr_n2h16(ip_packet->length)
								- ((int)payload - (int)ip_packet);

#if PLUGS_TCP
						if(plug->protocol == ne_plugs_tcp)
							{
							// | Handle specially elsewhere

							int r;

							r = r_tcp_dispatch(
									a,
									i + nk_plugs_plug_number_base,
									plug,
									sub_protocol,
									payload,
									payload_length);

							// | only one tcp plug can get each
							// | tcp packet to us.
							if(!r)
								got_tcp = 1;

							}
						else
//MR #endif PLUGS_TCP
#endif
							{
							for_the_plug = 1;
							got_tcp = 1;
							}
			// The interaction between tcp and tcp_raw is
			// tricky. A tcp_raw plug *could* steal your
			// regular tcp packet, after all! best not to
			// mix them, you know?
						}
					break;

				} // switch

			//
			// If we've determined that this packet should
			// be received by this plug, then either
			// call the plug's callback proc right now,
			// or mark the packet to be received on demand
			// by the plug.

			if(for_the_plug)
				{
#if PLUGS_DEBUG
				if(plug->flags & ne_plugs_flag_debug_rx)
					{
					printf("   [plugs] | packet accepted for plug\n");
					nr_plugs_print_ethernet_packet(packet,packet_length,"   [plugs] | ");
					}
//MR #endif PLUGS_DEBUG
#endif

				// We know *some* plug wants it.
				// If it happens to be in IP packet
				// of any kind, let's just make sure
				// that we have the originator in
				// our ARP cache. Easy info!

				if(sub_protocol[ne_plugs_ip].header)
					r_add_to_arp_cache_from_ip_packet(a,packet);

				if(plug->callback_proc)
					{
#if PLUGS_DEBUG
					if(plug->flags & ne_plugs_flag_debug_rx)
						printf("   [plugs] | packet dispatched to callback proc %08x\n",
								(int)plug->callback_proc);
//MR #endif PLUGS_DEBUG
#endif
					(plug->callback_proc)
							(i + nk_plugs_plug_number_base,
							plug->callback_context,
							sub_protocol,
							payload,
							payload_length);
					}
				else
					plug_bitmask |= 1 << i;
				}

#if PLUGS_DEBUG
			else
				{
				if((plug->flags & ne_plugs_flag_debug_rx)
						&& !got_tcp)
					{
					printf("   [plugs] | packet not sent to plug\n");
					}
				}
//MR #endif PLUGS_DEBUG
#endif

			} // packet protocol include plug protocol

⌨️ 快捷键说明

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