📄 plugs.c
字号:
present_but_unresolved:
// We put entries in the cache with ethernet_address == 0
// to signify that we want it. The ARP handler only fills
// in mac addr's that already have an entry for the ip.
// Not found in cache
// If we're already in dispatch, we cannot conduct a
// transaction, so just fail
if(g->in_dispatch)
{
result = ne_plugs_error_arp;
goto go_home;
}
//
// Should we send an ARP request?
t1 = nr_timer_milliseconds();
if(t1 - ti < nk_plugs_arp_retry_interval)
goto scan_cache;
ti = t1; // retry timer shall go again from here...
if(retry_count >= nk_plugs_arp_retry_count)
{
result = ne_plugs_error_arp_timed_out;
goto go_home;
}
retry_count++;
// Not in the cache, & is time to send out a request, and wait...
// If we wait too long, well, report an error then.
{
ns_plugs_arp_packet request;
request.hardware_type = nm_h2n16(1);
request.protocol_type = nm_h2n16(0x0800);
request.hardware_size = 6; // 6 for ethernet
request.protocol_size = 4; // 4 for IP
request.op = nm_h2n16(1); // request
request.sender_ethernet_address = a->settings.ethernet_address;
request.sender_ip_address = a->settings.ip_address;
request.target_ethernet_address.u32 = 0;
request.target_ethernet_address.l16 = 0;
request.target_ip_address = ip_address;
#if PLUGS_DEBUG
if(flags & ne_plugs_flag_debug_tx)
{
printf(" [plugs] | sending arp request for ");
nr_plugs_print_ip_address(request.target_ip_address);
printf("\n");
}
#endif
//MR result = nr_plugs_send(a->arp_plug,&request,28,0);
result = nr_plugs_send(a->arp_plug,(void *)&request,28,0);
if(result)
goto go_home;
}
goto scan_cache;
go_home:
return result;
}
void packet_append_bytes(char **dst,void *src, int length)
{
char *src_c = (char *)src;
char *w = *dst;
while(length--)
*w++ = *src_c++;
*dst = w;
}
void packet_append_n16(char **dst,net_16 x)
{
packet_append_bytes(dst,&x,2);
}
// Send must construct an entire ethernet packet
// for whatever protocol it is sending.
// The address can be deduced from the packet
// Note -- the adapter's send routine
// is not reentrant, so it should disable
// interrupts until it has made its
// best attempt to send.
// Note -- In the case of an ip packet,
// this routine can end up recursively
// calling itself as part of the ARP exchange.
// (The nr_plugs_ip_to_ethernet routine will need
// to send an arp request the first time an
// ip address is encountered.) (If the adapter
// requires mac address.) Usually we'll have
// the address in cache already, though, from the
// incoming ip message.
// plug_handle -- if this is a small integer,
// then it is presumed to be just a protocol
// number. This is so we can send a packet
// without a plug allocated, in some cases.
// Specifically, this lets us send tcp rst
// messages in response to spurious packets.
// If used like this, the adapter index must
// be coded into the low flags bits.
int nr_plugs_send_to(int plug_handle,
void *payload,
int payload_length,
long flags,
net_32 ip_address,
net_16 port)
{
s_plugs_globals *g = &ng_plugs_globals;
int result = 0;
ns_plugs_ethernet_packet *ep;
char ep_contents[1500]; // this should be supplied by each adapter
char *ep_w; // progressive walk along the packet...
int plug_protocol;
net_16 plug_local_port;
int adapter_index;
s_plugs_adapter_entry *a;
// |
// | Extract the protocol, flags, and source port
// | either from the plug pointer, or inferentially
// | from the (fake) plug_handle
// |
if(plug_handle < ne_plugs_last_protocol) // not a plug handle!
{
plug_protocol = plug_handle;
plug_local_port = 0;
#if PLUGS_DEBUG
plug_handle = -1; // so debug printing reveals the fake plug-ness
adapter_index = flags & ne_plugs_flag_adapter_index_mask;
#endif
}
else
{
s_plugs_plug *plug;
plug_handle -= nk_plugs_plug_number_base;
plug = &g->plug[plug_handle];
plug_protocol = plug->protocol;
plug_local_port = plug->local_port;
flags |= plug->flags;
adapter_index = plug->flags & ne_plugs_flag_adapter_index_mask;
}
a = &g->adapter[adapter_index];
#if PLUGS_DEBUG
if(flags & ne_plugs_flag_debug_tx)
{
printf(" [plugs] +-----------------------\n");
printf(" [plugs] | plug %d (%s): sends %d byte payload\n",
plug_handle,
get_protocol_name(plug_protocol),
payload_length);
}
#endif
ep = (ns_plugs_ethernet_packet *)ep_contents;
ep_w = (char *)ep_contents;
if(plug_protocol == ne_plugs_ethernet)
{
// ethernet protocol means your "payload" is, in fact,
// the whole ethernet packet. 1st 14 bytes is the header.
packet_append_bytes(&ep_w,payload,payload_length);
}
else if(plug_protocol == ne_plugs_arp)
{
// arp protocol: payload is presumed to be
// a 28-byte arp packet. We don't even
// check the length.
ns_plugs_arp_packet *arp_packet;
net_48 broadcast_ethernet_address;
arp_packet = (ns_plugs_arp_packet *)payload;
// ethernet header
broadcast_ethernet_address.u32 = 0xffffFFFF;
broadcast_ethernet_address.l16 = 0xffff;
packet_append_bytes(&ep_w,
(flags & ne_plugs_flag_ethernet_broadcast)
//MR ? &broadcast_ethernet_address
? (void *)&broadcast_ethernet_address
//MR : &arp_packet->target_ethernet_address,
: (void *)&arp_packet->target_ethernet_address,
6);
//MR packet_append_bytes(&ep_w,&a->settings.ethernet_address,6);
packet_append_bytes(&ep_w,(void *)&a->settings.ethernet_address,6);
packet_append_n16(&ep_w,nm_h2n16(ne_plugs_ethernet_arp));
// arp packet as delivered to us
packet_append_bytes(&ep_w,payload,28);
}
else if
(
plug_protocol == ne_plugs_ip
|| plug_protocol == ne_plugs_icmp
|| plug_protocol == ne_plugs_udp
|| plug_protocol == ne_plugs_tcp_raw
)
{
// | icmp, udp, tcp: payload is just the data to be
// | sent to the port and address specified in
// | the nr_plugs_connect call.
ns_plugs_ip_packet *ip_packet;
net_48 ep_ethernet_address;
// | look up ethernet destination
result = nr_plugs_ip_to_ethernet
(
adapter_index,
ip_address,
&ep_ethernet_address,flags
);
if(result)
goto go_home;
// |
// | ethernet header
//MR packet_append_bytes(&ep_w,&ep_ethernet_address,6);
packet_append_bytes(&ep_w,(void *)&ep_ethernet_address,6);
//MR packet_append_bytes(&ep_w,&a->settings.ethernet_address,6);
packet_append_bytes(&ep_w,(void *)&a->settings.ethernet_address,6);
packet_append_n16(&ep_w,nm_h2n16(ne_plugs_ethernet_ip));
// |
// | construct ip header in place (not appending)
ip_packet = (ns_plugs_ip_packet *)ep_w;
//MR ep_w += sizeof(ns_plugs_ip_packet);
ep_w += sizeof(ns_plugs_ip_packet) - 1;
ip_packet->version_header_length = 0x45; // 0x45 for no options
ip_packet->tos = 0; // zero
//MR ip_packet->length = nr_h2n16(sizeof(ns_plugs_ip_packet) + payload_length
ip_packet->length = nr_h2n16(sizeof(ns_plugs_ip_packet) - 1 + payload_length
+ ((plug_protocol == ne_plugs_udp)
//MR ? sizeof(ns_plugs_udp_packet) : 0)); // header + payload length
? sizeof(ns_plugs_udp_packet) - 1: 0)); // header + payload length
ip_packet->identifier = nr_h2n16(g->ip_identifier++); // bump for each packet
ip_packet->flags_fragment = nm_h2n16(0); // fragment miscellany
ip_packet->time_to_live = 128; // some typical value
ip_packet->protocol = (plug_protocol == ne_plugs_icmp) ? ne_plugs_ip_icmp :
(plug_protocol == ne_plugs_udp) ? ne_plugs_ip_udp :
ne_plugs_ip_tcp;
ip_packet->header_checksum = 0;
ip_packet->source_ip_address = a->settings.ip_address;
ip_packet->destination_ip_address = ip_address;
// |
// | maybe append udp header
if(plug_protocol == ne_plugs_udp)
{
//MR int udp_packet_length = sizeof(ns_plugs_udp_packet) + payload_length;
int udp_packet_length = sizeof(ns_plugs_udp_packet) - 1 + payload_length;
packet_append_n16(&ep_w,plug_local_port);
packet_append_n16(&ep_w,port);
packet_append_n16(&ep_w,nr_n2h16(udp_packet_length));
packet_append_n16(&ep_w,0); // no stinking checksum
}
// |
// | append the payload
packet_append_bytes(&ep_w,payload,payload_length);
// |
// | After the whole packet is together,
// | work backwards out and do the checksums.
// | maybe calculate icmp checksum, so courteously!
if(plug_protocol == ne_plugs_icmp)
{
ns_plugs_icmp_packet *icmp_packet;
icmp_packet = (ns_plugs_icmp_packet *)ip_packet->payload;
// | clear checksum, first
icmp_packet->checksum = 0;
//MR icmp_packet->checksum = r_calculate_checksum(ip_packet->payload,payload_length,0,0);
icmp_packet->checksum = r_calculate_checksum((void *)ip_packet->payload,payload_length,0,0);
}
else if(plug_protocol == ne_plugs_udp)
{
ns_plugs_udp_packet *udp_packet = (ns_plugs_udp_packet *)ip_packet->payload;
//MR int udp_packet_length = sizeof(ns_plugs_udp_packet) + payload_length;
int udp_packet_length = sizeof(ns_plugs_udp_packet) - 1 + payload_length;
udp_packet->checksum = r_calculate_checksum(
//MR udp_packet,
(void *)udp_packet,
udp_packet_length,
ip_packet,
udp_packet_length);
}
else if(plug_protocol == ne_plugs_tcp_raw
|| (flags & ne_plugs_flag_tcp_checksum))
{
ns_plugs_tcp_packet *tcp_packet = (ns_plugs_tcp_packet *)ip_packet->payload;
tcp_packet->checksum = 0;
tcp_packet->checksum = r_calculate_checksum(
//MR tcp_packet,
(void *)tcp_packet,
payload_length,
ip_packet,
payload_length);
}
//MR ip_packet->header_checksum = r_calculate_checksum(ip_packet,
ip_packet->header_checksum = r_calculate_checksum((void *)ip_packet,
//MR sizeof(ns_plugs_ip_packet),0,0);
sizeof(ns_plugs_ip_packet) - 1,0,0);
}
#if PLUGS_DEBUG
else
printf(" [plugs] | nr_plugs_send: unknown plug %d protocol %d\n",
plug_handle,plug_protocol);
#endif
#if PLUGS_DEBUG
if(flags & ne_plugs_flag_debug_tx)
nr_plugs_print_ethernet_packet(ep,ep_w - ep_contents," [plugs] | ");
#endif
// |
// | Send the packet to the hardware adapter
// |
result = a->adapter_description->tx_frame_proc
(
a->adapter_address,
ep_contents,
ep_w - ep_contents
);
go_home:
#if PLUGS_DEBUG
if(result)
{
if(flags & ne_plugs_flag_debug_tx)
printf(" [plugs] | ERROR nr_plugs_send_to result = %d\n",result);
}
#endif
return result;
}
int nr_plugs_send(int plug_handle,
void *payload,
int payload_length,
long flags)
{
//HB Removed to get rid of warning message s_plugs_globals *g = &ng_plugs_globals;
s_plugs_plug *plug;
//HB Removed to get rid of warning message int plugIndex;
int result;
//printf("*** nr_plugs_send() 1 plug_handle=%08x ***\n",plug_handle);
plug = r_plug_from_handle(plug_handle);
//printf("*** nr_plugs_send() 2 plug=%x ***\n",plug);
// |
// | For a tcp connection, shunt it through
// | r_tcp_send (which eventually
// | calls through to nr_plugs_send_to,
// | after building the tcp packet &c.)
// |
#if PLUGS_TCP
if(plug->protocol == ne_plugs_tcp)
{
//printf("*** nr_plugs_send() 3 ***\n");
result = r_tcp_send
(
plug_handle,
plug,
ne_plugs_flag_tcp_ack | ne_plugs_flag_tcp_psh,
payload,
payload_length
);
//printf("*** nr_plugs_send() 4 ***\n");
}
else
#endif
{
//printf("*** nr_plugs_send() 5 ***\n");
result = nr_plugs_send_to(plug_handle,payload,payload_length,flags,
plug->remote_ip_address,
plug->remote_port);
//printf("*** nr_plugs_send() 6 ***\n");
}
//printf("*** nr_plugs_send() 7 ***\n");
return result;
}
// +------------------------
// | Mundane stuff, like setting
// | the LED and such
int nr_plugs_set_mac_led(int adapter_index,int led_onoff)
{
s_plugs_globals *g = &ng_plugs_globals;
s_plugs_adapter_entry *a = &g->adapter[adapter_index];
return a->adapter_description->set_led_proc
(
a->adapter_address,
led_onoff
);
}
int nr_plugs_set_mac_loopback(int adapter_index,int loopback_onoff)
{
s_plugs_globals *g = &ng_plugs_globals;
s_plugs_adapter_entry *a = &g->adapter[adapter_index];
return a->adapter_description->set_loopback_proc
(
a->adapter_address,
loopback_onoff
);
}
// +-----------------------------------
// | nr_plugs_idle
// | Poll for events and other interesting things.
//
int nr_plugs_idle(void)
{
s_plugs_globals *g = &ng_plugs_globals;
int adapter_index;
s_plugs_adapter_entry *a;
if(!g->running)
return ne_plugs_error_not_initialized; // | plugs not initialized
if(g->in_idle)
return ne_plugs_error;
// +--------------------
// | Can't call more than one deep for check_for_events, thank you.
// |
g->in_idle++;
a = g->adapter;
for(adapter_index = 0; adapter_index < g->adapter_count; adapter_index++)
{
a->adapter_description->check_for_events_proc
(
a->adapter_address,
nr_plugs_dispatch_packet,
a // context is adapter pointer
);
a++;
}
g->in_idle--;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -