📄 plugs.c
字号:
}
//
// 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 + -