📄 plugs.c
字号:
//
//
// Implementation of the plugs
// tcp/ip stack for embedded systems
//
//#define PLUGS_DEBUG 1
#include <stdio.h>
#include "nios_compatibility.h"
#include "plugs.h"
#include "plugs_private.h"
// +------------------------
// | Debug bit 4 means show debug on system plugs
// |
#if (PLUGS_DEBUG & 4)
#define nk_plugs_default_debug (ne_plugs_flag_debug_tx | ne_plugs_flag_debug_rx)
#else
#define nk_plugs_default_debug (0)
#endif
// +------------------------
// | Local Prototypes
static void r_add_to_arp_cache_from_ip_packet
(
s_plugs_adapter_entry *a,
ns_plugs_ethernet_packet *p
);
static void r_add_to_arp_cache
(
s_plugs_adapter_entry *a,
net_32 ip_address,
net_32 ethu32,net_16 ethl16
);
static int r_plugs_dns_proc
(
int plug_handle,
void *context,
ns_plugs_packet *p,
void *payload,
int payload_length
);
static 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
);
static int r_tcp_send
(
int plug_handle,
s_plugs_plug *plug,
int flags,
void *payload,
long payload_length
);
static s_plugs_plug *r_plug_from_handle(int plug_handle);
// ---------------------------
// Byte-swapping subroutines
host_16 nr_n2h16(net_16 n)
{
return nm_n2h16(n);
}
host_32 nr_n2h32(net_32 n)
{
return nm_n2h32(n);
}
static s_plugs_plug *r_plug_from_handle(int plug_handle)
{
s_plugs_plug *plug;
s_plugs_globals *g = &ng_plugs_globals;
plug_handle -= nk_plugs_plug_number_base;
plug = &g->plug[plug_handle];
return plug;
}
// --------------------
// r_calculate_checksum(base,byte_count,ip_header)
//
// Return complement of 1's-complement
// checksum of the specified range
// Return in network byte order.
//
// If ip_header pointer is included, add in
// the pseudo header as used by udp & tcp
// And possibly add in the (host-ordered)
// pseudo_length, too.
//
net_16 r_calculate_checksum(void *base,int byte_count,ns_plugs_ip_packet *ip_packet,host_16 pseudo_length)
{
net_16 *w = base;
host_32 x;
unsigned long result = 0;
while(byte_count > 0)
{
x = nr_n2h16(*w++);
if(byte_count == 1)
x &= 0xff00;
result += x;
byte_count -= 2;
}
// | Add in udp/tcp pseudo-header, maybe
if(ip_packet)
{
result += nr_n2h16(ip_packet->source_ip_address & 0x0000ffff);
result += nr_n2h16(ip_packet->source_ip_address >> 16);
result += nr_n2h16(ip_packet->destination_ip_address & 0x0000ffff);
result += nr_n2h16(ip_packet->destination_ip_address >> 16);
result += ip_packet->protocol;
result += pseudo_length;
}
// | strangely, tcp/ip checksums require
// | that the carry-bit be added back in.
// | And, do it twice, to account for the case
// | where adding the halves overflows. You
// | only need to do it twice at most. Really.
// |
result = (result & 0xffff) + (result >> 16);
result = (result & 0xffff) + (result >> 16);
// |
// | Never have checksum == 0
// |
if(result == 0)
result = 0xffff;
return ~(nr_h2n16((host_16)result));
}
#if PLUGS_PING
// --------------------------------------------------------
// ICMP Handler
//
// This handler only responds to one thing: a ping (echo request)
//
#define k_plugs_ping_reply_size 1536
static int r_plugs_icmp_proc
(
int plug_handle,
void *context,
ns_plugs_packet *p,
void *payload,
int payload_length
)
{
char response_b[k_plugs_ping_reply_size]; // (raw bytes) upper bound for ping we can reply to!
ns_plugs_icmp_packet *icmpp = payload;
ns_plugs_icmp_packet *response = (ns_plugs_icmp_packet *)response_b;
if(icmpp->type == ne_plugs_icmp_ping_request)
{
char *ws,*wd;
int i;
ns_plugs_ip_packet *ipp;
// | copy payload portion of ping request
ws = payload;
ws += 4;
wd = (char *)(response->payload);
if(payload_length >= k_plugs_ping_reply_size)
payload_length = k_plugs_ping_reply_size;
for(i = payload_length - 4; i > 0; i--)
*wd++ = *ws++;
response->type = ne_plugs_icmp_ping_reply;
response->code = 0;
// | Send the almost-identical packet on out
// | Use send_to to send it to the originator
ipp = p[ne_plugs_ip].header;
//MR nr_plugs_send_to(plug_handle,response,payload_length,0,ipp->source_ip_address,0);
nr_plugs_send_to(plug_handle,(void *)response,payload_length,0,ipp->source_ip_address,0);
}
return 0;
}
#endif
// ---------------------------------------------------------
// Arp Handler
//
// When we get an arp "reply" packet,
// we'll save its information into the
// cache IF there is an entry for it already
// there.
// When we get an arp "request" packet,
// we'll reply to it if its about us.
int r_plugs_arp_proc
(
int plug_handle,
void *context,
ns_plugs_packet *p,
void *payload,
int payload_length
)
{
ns_plugs_arp_packet *ap = payload;
ns_plugs_arp_packet response;
s_plugs_adapter_entry *a = context;
switch(ap->op)
{
case nm_h2n16(1): // arp request
if(a->settings.ip_address == ap->target_ip_address)
{
// | Request for us!
// | construct an answer and send it.
response.hardware_type = nm_h2n16(1);
response.protocol_type = nm_h2n16(0x0800);
response.hardware_size = 6; // 6 for ethernet
response.protocol_size = 4; // 4 for IP
response.op = nm_h2n16(2); // reply
response.sender_ethernet_address = a->settings.ethernet_address;
response.sender_ip_address = a->settings.ip_address;
response.target_ethernet_address = ap->sender_ethernet_address;
response.target_ip_address = ap->sender_ip_address;
nr_plugs_send
(
plug_handle,
//MR &response,
(void *)&response,
28,
ne_plugs_flag_ethernet_broadcast
);
}
break;
case nm_h2n16(2): // arp reply
//
// | walk through our arp cache, and see if we want this reply
{
s_plugs_arp_cache_entry *w;
int i;
w = a->arp_cache;
for(i = 0; i < nk_plugs_arp_cache_count; i++)
{
if(w->ip_address == ap->sender_ip_address)
w->ethernet_address = ap->sender_ethernet_address;
w++;
}
}
break;
} // switch
return 0;
}
// Nothing wrong with two plugs listening
// on the same port. No sir! Perfectly
// legal. But we wont let it happen
// accidentally.
#define nk_plugs_minimum_fresh_port_number 32769
net_16 get_port_number(s_plugs_globals *g)
{
int v;
s_plugs_plug *plug;
int i;
try_again:
v = g->port_number++; // will be zero the very first time...
if(v == 0)
v = g->port_number = nk_plugs_minimum_fresh_port_number;
v = nr_h2n16(v);
plug = g->plug;
for(i = 0; i < PLUGS_PLUG_COUNT; i++)
if(v == plug++->local_port)
goto try_again;
return v;
}
int nr_plugs_initialize
(
long flags,
ns_plugs_network_settings *network_settings,
void *adapter_address,
ns_plugs_adapter_description *adapter_description
)
{
s_plugs_globals *g = &ng_plugs_globals;
int result = 0;
s_plugs_adapter_entry *a;
// +---------------------------------
// | Initialize can be used to start up the plugs
// | stack from scratch, or to add one more adapter
// |
if(!(flags & ne_plugs_flag_add_adapter))
{
// +----------------------
// | clear and reset everything
// | Only the 1st adapter gets a DNS socket
// |
nr_zerorange((char *)g,sizeof(s_plugs_globals));
// +---------------
// | Mark the globals as Up And Running
g->running = 1;
#if PLUGS_DNS
// +------
// | Install a DNS handler
// | ONLY the first adapter installed gets
// | a DNS handler.
// |
result = nr_plugs_create
(
&g->dns_plug,
ne_plugs_udp,
0,
r_plugs_dns_proc,
0,
nk_plugs_default_debug);
result = nr_plugs_connect
(
g->dns_plug,
0,
nr_n2h32(network_settings->nameserver_ip_address),
ne_plugs_udp_dns
);
#endif
}
// +---------------
// | Install the adapter
// | Stash the adapter pointer
// |
a = &g->adapter[g->adapter_count];
a->adapter_address = adapter_address;
a->adapter_description = adapter_description;
// +-----------------
// | Install this adapter's network settings.
// | If there's a flash, maybe get settings from flash
// |
#ifdef nasys_plugs_persistent_network_settings
// | 0 means use the stored index,
if((int)network_settings == 0)
network_settings = &nasys_plugs_persistent_network_settings->settings
[
nasys_plugs_persistent_network_settings->settings_index
];
#endif
a->settings = *network_settings;
// +--------------------
// | Install this adapter's arp proc
// |
result = nr_plugs_create
(
&a->arp_plug,
ne_plugs_arp,
1,
r_plugs_arp_proc,
a, // | use context to hold "our adapter".
ne_plugs_flag_ethernet_broadcast + nk_plugs_default_debug
);
#if PLUGS_PING
// +------
// | Install this adapter's ICMP ping handler
// |
result = nr_plugs_create
(
&a->icmp_plug,
ne_plugs_icmp,
1,
r_plugs_icmp_proc,
0,
nk_plugs_default_debug
);
result = nr_plugs_connect
(a->icmp_plug, 0, -1,-1);
#endif
// +---------------
// | Reset the adapter
result = (a->adapter_description->reset_proc)
(
a->adapter_address,
network_settings
);
#if PLUGS_DEBUG
printf(" [plugs] +-----------------------\n");
printf(" [plugs] | initialized adapter %s at 0x%08x, ",
a->adapter_description->adapter_name,
(int)a->adapter_address);
nr_plugs_print_ip_address(network_settings->ip_address);
printf("\n");
//MR #endif PLUGS_DEBUG
#endif
g->adapter_count++;
return result;
}
int nr_plugs_terminate(void)
{
s_plugs_globals *g = &ng_plugs_globals;
int i;
for(i = 0; i < PLUGS_PLUG_COUNT; i++)
nr_plugs_destroy(i + nk_plugs_plug_number_base);
nr_zerorange((char *)g,sizeof(s_plugs_globals));
return 0;
}
int nr_plugs_get_settings
(
int adapter_index,
ns_plugs_network_settings *network_settings_out
)
{
s_plugs_globals *g = &ng_plugs_globals;
s_plugs_adapter_entry *a = &g->adapter[adapter_index];
*network_settings_out = a->settings;
return 0;
}
int ethernet_address_equal(net_48 *ea1,net_48 *ea2)
{
return ea1->u32 == ea2->u32
&& ea1->l16 == ea2->l16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -