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

📄 plugs.c

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

	next_plug:
		plug++;
		} // for (i), each plug

#if PLUGS_TCP
	// |
	// | If it was a tcp packet to this IP address, and
	// | nobody handled it, reply with an incisive RST
	// |
	if(sub_protocol[ne_plugs_tcp].header
			&& ip_address_equal(ip_packet->destination_ip_address,a->settings.ip_address)
			&& !got_tcp)
		{
		int tcp_flags;
		ns_plugs_tcp_packet *tcp_packet;
		// |
		// | Make sure we have the ethernet address
		// | for this packet before we try to send
		// |

		tcp_packet = sub_protocol[ne_plugs_tcp].header;
		tcp_flags = nr_n2h16(tcp_packet->header_length_flags);

		if(!(tcp_flags & ne_plugs_flag_tcp_rst))
			{
			// |
			// | But, don't respond to rst with rst!
			// |
			r_add_to_arp_cache_from_ip_packet(a,packet);
			r_tcp_send(0,0,
					ne_plugs_flag_tcp_rst | ne_plugs_flag_tcp_ack,
					sub_protocol,0);
			}
		}
//MR #endif PLUGS_TCP
#endif

	// If any plug_bitmask, and queing enabled, queue the packet
//HB Removed to get rid of warning message go_home:

	g->in_dispatch--;

	return 0;
	}

int nr_plugs_create(int *plugHandleOut,
		int protocol,
		host_16 port,
		nr_plugs_receive_callback_proc callback,
		void *callback_context,
		long flags)
	{
	s_plugs_globals *g = &ng_plugs_globals;
	int i;
	s_plugs_plug *plug;

	if(!g->running)
		return ne_plugs_error_not_initialized; // uninitialized error

	port = nr_h2n16(port);

	// port number zero means "give me a fresh port number"
	if(port == 0)
		port = get_port_number(g);


	plug = g->plug;

	for(i = 0; i < PLUGS_PLUG_COUNT; i++)
		{
		if(plug->protocol == 0)
			{
			//
			// We found an unused plug, lets use it.
			// (??? how to mark it until its connected?)
			//

			// zero out all fields?

			plug->protocol = protocol;
			plug->local_port = port;
			plug->callback_proc = callback;
			plug->callback_context = callback_context;
			plug->flags = flags;

#if PLUGS_TCP
			plug->tcp_state = e_plugs_tcp_inert;
#endif

			*plugHandleOut = i + nk_plugs_plug_number_base;

			return 0;
			}

		plug++;
		}

	return ne_plugs_error_too_many_plugs;
	}

int nr_plugs_destroy(int plug_handle)
	{
//	s_plugs_globals *g = &ng_plugs_globals;
	s_plugs_plug *plug = r_plug_from_handle(plug_handle);

	// | "Destroying" a plug is easy: just
	// | mark it as unused, and everyone
	// | will ignore it.

	plug->protocol = 0;
	return 0;
	}


//
// nr_plugs_connect
//
// Some kinds of port _must_ be connected
// before they can send or receive packets.

int nr_plugs_connect(int plug_handle,
		char *remote_name,
		host_32 remote_ip_address,
		host_16 remote_port)
	{
	s_plugs_globals *g = &ng_plugs_globals;
	s_plugs_plug *plug;
	int result = 0;

	plug = r_plug_from_handle(plug_handle);

	if(remote_name)
		{
		result = nr_plugs_name_to_ip(remote_name,&remote_ip_address);
		if(result)
			goto go_home;
		remote_ip_address = nr_n2h32(remote_ip_address);
		}

#if PLUGS_TCP
	// |
	// | Any existing TCP connection?
	// | Close it. We do a partial
	// | close: we send a FIN and pretend
	// | we're completely done. When they
	// | send their ACK and FIN, we'll just
	// | slam them with a RST. This is
	// | impolite, but happens to be what
	// | Windows NT does, too, so I don't
	// | feel too bad, actually. -- dvb
	// |
	if((plug->protocol == ne_plugs_tcp)
			&& (plug->tcp_state > e_plugs_tcp_listening))
		{
		result = r_tcp_send
				(
				plug_handle,
				plug,
				ne_plugs_flag_tcp_ack | ne_plugs_flag_tcp_fin,
				0,
				0
				);
		if(result)
			goto go_home;
		plug->tcp_state = e_plugs_tcp_inert;
		}
#endif // PLUGS_TCP

	plug->remote_ip_address = nr_h2n32(remote_ip_address);
	plug->remote_port = nm_h2n16(remote_port);

#if PLUGS_TCP
	// |
	// | Open a new connection?
	// | They may have said connect to 0.0.0.0/0,
	// | which just means "hang up and forget it."
	// | If not, well, initiate connection.
	// |

	if((plug->protocol == ne_plugs_tcp) && plug->remote_ip_address)
		{
		int retry_count;
		long t0;

		plug->tcp_sn_local = nr_h2n32(get_port_number(g));

		for(retry_count = 0; retry_count < nk_plugs_tcp_retry_count; retry_count++)
			{
			t0 = nr_timer_milliseconds();

			result = r_tcp_send(plug_handle,plug,ne_plugs_flag_tcp_syn,0,0);
			if(result)
				goto go_home;
			plug->tcp_state = e_plugs_tcp_connecting;

			while(nr_timer_milliseconds() - t0 < nk_plugs_tcp_retry_interval)
				{
				nr_plugs_idle();
				if(plug->tcp_state == e_plugs_tcp_connected)
					goto done_trying_to_connect;
				if(plug->tcp_state == e_plugs_tcp_inert)
					{
					result = ne_plugs_error_tcp_connection_refused;
					goto done_trying_to_connect;
					}

				}
			}
		result = ne_plugs_error_tcp_timed_out;
done_trying_to_connect:
		;
		}
#endif // PLUGS_TCP


go_home:
	return result;
	}

// +--------
// | Bracketing the tcp-specific routines...

#if PLUGS_TCP

// +---------------------------------------
// | Listen -- let a tcp port wait for a connection

int nr_plugs_listen(
		int plug_handle,
		nr_plugs_listen_callback_proc listen_proc,
		void *listen_proc_context
		)
	{
//HB  Removed to get rid of warning message	s_plugs_globals *g = &ng_plugs_globals;
	s_plugs_plug *plug;

	plug = r_plug_from_handle(plug_handle);

	if(plug->tcp_state != e_plugs_tcp_inert)
		nr_plugs_connect(plug_handle,0,0,0);

		//return ne_plugs_error;

	plug->tcp_listen_proc = listen_proc;
	plug->tcp_listen_proc_context = listen_proc_context;
	plug->tcp_state = e_plugs_tcp_listening;

	plug->remote_ip_address = -1;
	plug->remote_port = -1; // accept from anyone...

	return 0;
	}

// +--------------------------------------------
// | Utility routine for composing and sending
// | tcp packets. Mostly it can figure out
// | what to do just from the flags.
// |
// | Exceptions:
// |     if plug is 0, then payload is actually the
// |     sub_protocol array.
// |

int r_tcp_send(int plug_handle,s_plugs_plug *plug,int tcp_flags,void *payload,long payload_length)
	{
	int result;

	unsigned char x[1500];
	ns_plugs_tcp_packet *tcp_reply; // reply
	net_32 destination_ip_address;
	int send_to_flags = 0;

	tcp_reply = (ns_plugs_tcp_packet *)x;
//MR	nr_zerorange((char *)tcp_reply,sizeof(ns_plugs_tcp_packet));
	nr_zerorange((char *)tcp_reply,sizeof(ns_plugs_tcp_packet) - 1);

	if(!plug)
		{
		// |
		// | If plug is 0, the *only* thing we can
		// | do is send an RST to the sender, presumed
		// | to be the source of an ip_packet overloading
		// | the input parameter "payload"
		// |

		ns_plugs_packet *sub_protocol = payload;
		ns_plugs_ip_packet *ipp = sub_protocol[ne_plugs_ip].header; // what we reply to
		ns_plugs_tcp_packet *tcpp = sub_protocol[ne_plugs_tcp].header;

		destination_ip_address = ipp->source_ip_address;

		tcp_reply->source_port = tcpp->destination_port;
		tcp_reply->destination_port = tcpp->source_port;
		tcp_reply->sequence_number = tcpp->acknowledgement_number;
		tcp_reply->acknowledgement_number = nr_h2n32(nr_n2h32(tcpp->sequence_number) + 1);

		tcp_reply->header_length_flags =
				nr_h2n16(0x5000 | ne_plugs_flag_tcp_rst | ne_plugs_flag_tcp_ack);
		payload = 0;
		payload_length = 0;
		send_to_flags = nk_plugs_default_debug;
		}
	else
		{
		destination_ip_address = plug->remote_ip_address;

		tcp_reply->source_port = plug->local_port;
		tcp_reply->destination_port = plug->remote_port;
		tcp_reply->window_size = nm_h2n16(1024);	// always room for another packet!

		// | Always send ack & seq numbers...

		tcp_reply->acknowledgement_number = nr_h2n32(plug->tcp_sn_remote);
		tcp_reply->sequence_number = nr_h2n32(plug->tcp_sn_local);
		tcp_reply->header_length_flags =
				nr_h2n16(0x5000 | (tcp_flags & ne_plugs_flag_tcp_mask));

		// | If SYN or FIN, bump our local seq by 1,
		// | else, if PSH, put payload bump local seq by payload size

		if(tcp_flags & (ne_plugs_flag_tcp_syn | ne_plugs_flag_tcp_fin))
			plug->tcp_sn_local++;
		else if(tcp_flags & ne_plugs_flag_tcp_psh)
			{
			// |
			// | Copy (byte by byte) the payload)
			// |

			int i;

			plug->tcp_sn_local += payload_length;
			for(i = 0; i < payload_length; i++)
				tcp_reply->payload[i] = ((char *)payload)[i];
			}

		if(tcp_flags & ne_plugs_flag_tcp_rst) // reset? window is zero, thank you.
			tcp_reply->window_size = 0;
		}

	// |
	// | Use the overload-feature of nr_plugs_send, and treat
	// | our carefully constructed packet as an ip packet,
	// | since we're giving it the payload already all
	// | put together.
	// |

	// | (payload_length now includes tcp header + tcp payload)

//MR	payload_length += sizeof(ns_plugs_tcp_packet);
	payload_length += sizeof(ns_plugs_tcp_packet) - 1;
//MR	result = nr_plugs_send_to(ne_plugs_ip,tcp_reply,payload_length,
	result = nr_plugs_send_to(ne_plugs_ip,(void *)tcp_reply,payload_length,
			ne_plugs_flag_tcp_checksum | send_to_flags,
			destination_ip_address,tcp_reply->destination_port);

	return result;
	}

// +-----------------------------------------
// | Routine for handling non-raw tcp connections
// | Return 0 if the packet is handled by this
// | port, else return -1. Whoever calls this
// | routine may decide to send a tcp RST to
// | the sender if no plug handles the tcp connection.

int r_tcp_dispatch(
		s_plugs_adapter_entry *a,
		int plug_handle,
		s_plugs_plug *plug,
		ns_plugs_packet *sub_protocol,
		void *payload,
		int payload_length)
	{
	int result = 0;
	host_32 seq;
	host_32 ack;
	host_16 tcp_flags;
	ns_plugs_ip_packet *ipp = sub_protocol[ne_plugs_ip].header;
	ns_plugs_tcp_packet *tcpp = sub_protocol[ne_plugs_tcp].header;

	// |
	// | Ensure that we can respond to this
	// | packet, mac-address-wise...
	// |

	r_add_to_arp_cache_from_ip_packet(a,sub_protocol[ne_plugs_ethernet].header);

	// |
	// | Extract some basic info from the incoming packet
	// |

	seq = nr_n2h32(tcpp->sequence_number);
	ack = nr_n2h32(tcpp->acknowledgement_number);
	tcp_flags = nr_n2h16(tcpp->header_length_flags);

	// |
	// | Handle the various tcp packet kinds in
	// | an exploded if{do and go home} list
	// |

	if(tcp_flags & ne_plugs_flag_tcp_syn) // | connection request or confirm
		{
		int x = nr_timer_milliseconds();

		if(plug->tcp_state == e_plugs_tcp_connecting)
			{
			// |
			// | We initiated a connection, and
			// | our remote target has, apparently,
			// | responded.
			// | Swell, we are connected.
			// |

			plug->tcp_sn_remote = seq + 1;
			result = r_tcp_send(plug_handle,plug,ne_plugs_flag_tcp_ack,0,0);
			if(!result)
				plug->tcp_state = e_plugs_tcp_connected;
			} // if connecting & got syn
		else if(plug->tcp_state == e_plugs_tcp_listening)
			{
			// |
			// | Listening -- call application acceptance routine
			// | (Really, it's an application rejection routine,
			// | since if there isn't one, we automatically accept.
			// |

			if(plug->tcp_listen_proc)
				{
				result = (plug->tcp_listen_proc)
						(plug_handle,
						plug->tcp_listen_proc_context,
						nr_n2h32(ipp->source_ip_address),
						nr_n2h16(tcpp->source_port));

				if(result)
					goto go_home;
				}

			plug->tcp_connection_time = x;

			plug->remote_ip_address = ipp->source_ip_address;
			plug->remote_port = tcpp->source_port;
			plug->tcp_sn_remote = seq + 1;

			// |
			// | Send ACK & SYN in return, to accept the connection
			// |

			result = r_tcp_send(plug_handle,plug,ne_plugs_flag_tcp_ack | ne_plugs_flag_tcp_syn,0,0);
			if(!result)
				plug->tcp_state = e_plugs_tcp_connected;

			} // if listening & got syn
		else
			{
			// |
			// | Not listening or connecting? Then
			// | a SYN has no business with us.
			// | Return an error code, we cannot accept.
			// |
	return_error:
			result = ne_plugs_error;
			}
		goto go_home;
		} // if syn

	// +---------------------------------
	// | If we're not connected, no other packet is interesting

	if(plug->tcp_state <= e_plugs_tcp_listening)
		{
		goto return_error;
		}

	// +-------------------------------------------
	// | If the packet has an ACK in it, we'll check
	// | it against our own numbers, and maybe resent
	// | an ack to get back into phase...
	// |
	// | We do this before checking the payload,
	// | because the remote count in the packet
	// | does not include the current payload.
	// |

	if(tcp_flags & ne_plugs_flag_tcp_ack)
		{
		// |
		// | Just sending us an ack?

⌨️ 快捷键说明

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