mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-26 07:20:32 +00:00
Network stack in functional state
Many TODOs and still a good bit of tidying up to do PCNet Direct Init wasn't working so added Shrine/OSDev Initialization Block code, need to do renames and comments for clarity Added UDPRep and ARPRep as early network Rep functions. UDPRep to see all bound sockets still needs to be made To get the network stack running, #include NetStart.CC
This commit is contained in:
parent
31d3760e34
commit
20484c6ada
19 changed files with 1227 additions and 164 deletions
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
#include "PCNet"
|
||||
#include "Ethernet"
|
||||
//#include "PCNet"
|
||||
//#include "Ethernet"
|
||||
|
||||
#define ARP_HASHTABLE_SIZE 1024
|
||||
|
||||
|
@ -56,6 +56,7 @@ I64 ARPSend(U16 operation,
|
|||
|
||||
U8 *ethernet_frame;
|
||||
CARPHeader *header;
|
||||
|
||||
I64 de_index = EthernetFrameAllocate(ðernet_frame,
|
||||
send_mac_address,
|
||||
dest_mac_address,
|
||||
|
@ -85,10 +86,14 @@ I64 ARPSend(U16 operation,
|
|||
|
||||
CARPHash *ARPCacheFindByIP(U32 ip_address)
|
||||
{
|
||||
U8 *ip_string = MStrPrint("%d", ip_address);
|
||||
U8 *ip_string = MStrPrint("%X", ip_address);
|
||||
CARPHash *entry = HashFind(ip_string, arp_cache, HTT_ARP);
|
||||
|
||||
if (entry == NULL)
|
||||
ZenithErr("Could not find an IP in ARP cache.");
|
||||
{
|
||||
ZenithWarn("ARP CACHE FIND BY IP: Could not find an IP in ARP cache.\n");
|
||||
// CallerRep;
|
||||
}
|
||||
|
||||
Free(ip_string);
|
||||
return entry;
|
||||
|
@ -96,19 +101,24 @@ CARPHash *ARPCacheFindByIP(U32 ip_address)
|
|||
|
||||
CARPHash *ARPCachePut(U32 ip_address, U8 *mac_address)
|
||||
{
|
||||
ZenithLog("ARP CACHE PUT: Attempting to look for entry in ARP Cache.\n");
|
||||
CARPHash *entry = ARPCacheFindByIP(ip_address);
|
||||
//Free(entry); // something seems wrong about this...
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
entry = CAlloc(sizeof(CARPHash));
|
||||
entry->str = MStrPrint("%d", ip_address);
|
||||
ZenithLog("ARP CACHE PUT: Attempting add to cache: addr, mac: \n");
|
||||
ZenithLog(" 0x%0X, 0x%0X 0x%0X 0x%0X 0x%0X 0x%0X 0x%0X\n",
|
||||
ip_address, mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5]);
|
||||
entry->str = MStrPrint("%X", ip_address);
|
||||
entry->type = HTT_ARP;
|
||||
MemCopy(entry->mac_address, mac_address, 6);
|
||||
|
||||
HashAdd(entry, arp_cache);
|
||||
}
|
||||
else
|
||||
ZenithWarn("ARP Cache Put attempted but entry was already found in Cache. TODO: overwrite?\n");
|
||||
ZenithWarn("ARP CACHE Put: Entry was already found in Cache. TODO: overwrite?\n");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -139,16 +149,18 @@ U0 ARPSetIPV4Address(U32 ip_address)
|
|||
//the NetQueueHandler
|
||||
I64 ARPHandler(CEthernetFrame *ethernet_frame)
|
||||
{
|
||||
ZenithLog("ARP HANDLER: Entering ARP Handler.\n");
|
||||
|
||||
// shrine checks if frame ethertype is ARP and ensures length is not less than CARPHeader
|
||||
// since revising Shrine implement, will do same checks for now ..
|
||||
if (ethernet_frame->ethertype != ETHERTYPE_ARP)
|
||||
{
|
||||
ZenithErr("ARP Handler caught wrong frame ethertype.");
|
||||
ZenithErr("ARP HANDLER: Caught wrong frame ethertype.\n");
|
||||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
if (ethernet_frame->length < sizeof(CARPHeader))
|
||||
{
|
||||
ZenithErr("ARP Handler caught wrong frame length.");
|
||||
ZenithErr("ARP HANDLER: Caught wrong frame length.\n");
|
||||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
|
||||
|
@ -161,22 +173,22 @@ I64 ARPHandler(CEthernetFrame *ethernet_frame)
|
|||
// hlen(?) != 6(?), and that plen(?) == 4 (?)
|
||||
if (EndianU16(header->hardware_type) != HTYPE_ETHERNET)
|
||||
{
|
||||
ZenithErr("ARP Handler caught wrong frame hardware type.");
|
||||
ZenithErr("ARP HANDLER: Caught wrong frame hardware type.\n");
|
||||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
if (EndianU16(header->protocol_type) != ETHERTYPE_IPV4)
|
||||
{
|
||||
ZenithErr("ARP Handler caught wrong frame protocol type.");
|
||||
ZenithErr("ARP HANDLER: Caught wrong frame protocol type.\n");
|
||||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
if (header->hardware_addr_len != HLEN_ETHERNET)
|
||||
{
|
||||
ZenithErr("ARP Handler caught wrong frame hardware address length.");
|
||||
ZenithErr("ARP HANDLER: Caught wrong frame hardware address length.\n");
|
||||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
if (header->protocol_addr_len != PLEN_IPV4)
|
||||
{
|
||||
ZenithErr("ARP Handler caught wrong frame protocol address length.");
|
||||
ZenithErr("ARP HANDLER: Caught wrong frame protocol address length.\n");
|
||||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
|
||||
|
@ -197,4 +209,26 @@ I64 ARPHandler(CEthernetFrame *ethernet_frame)
|
|||
}
|
||||
}
|
||||
|
||||
U0 ARPRep()
|
||||
{ // TODO: primitive, needs refine.
|
||||
I64 i;
|
||||
CARPHash *temp_hash;
|
||||
|
||||
"\n";
|
||||
Who(, arp_cache);
|
||||
"\n";
|
||||
|
||||
for (i = 0; i <= arp_cache->mask; i++)
|
||||
{
|
||||
temp_hash = arp_cache->body[i];
|
||||
|
||||
while (temp_hash)
|
||||
{
|
||||
ClassRep(temp_hash);
|
||||
temp_hash = temp_hash->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ARPCacheInit;
|
534
src/Home/Net/DHCP.CC
Executable file
534
src/Home/Net/DHCP.CC
Executable file
|
@ -0,0 +1,534 @@
|
|||
//www.networksorcery.com/enp/protocol/dhcp.htm
|
||||
|
||||
//#include "DNS";
|
||||
|
||||
#define DHCP_OPCODE_BOOTREQUEST 0x01
|
||||
|
||||
#define DHCP_OPTION_SUBNET_MASK 1
|
||||
#define DHCP_OPTION_ROUTER 3
|
||||
#define DHCP_OPTION_DNS 6
|
||||
#define DHCP_OPTION_DOMAIN_NAME 15
|
||||
|
||||
#define DHCP_OPTION_REQUESTED_IP 50
|
||||
#define DHCP_OPTION_MESSAGETYPE 53
|
||||
#define DHCP_OPTION_SERVER_ID 54
|
||||
#define DHCP_OPTION_PARAMLIST 55
|
||||
|
||||
#define DHCP_MESSAGETYPE_DISCOVER 0x01
|
||||
#define DHCP_MESSAGETYPE_OFFER 0x02
|
||||
#define DHCP_MESSAGETYPE_REQUEST 0x03
|
||||
#define DHCP_MESSAGETYPE_ACK 0x05
|
||||
|
||||
#define DHCP_COOKIE 0x63825363
|
||||
|
||||
#define DHCP_STATE_CLIENT_START 0
|
||||
#define DHCP_STATE_CLIENT_DISCOVER 1
|
||||
#define DHCP_STATE_CLIENT_REQUEST 2
|
||||
#define DHCP_STATE_CLIENT_REQ_ACCEPTED 3
|
||||
|
||||
#define DHCP_TIMEOUT 3000
|
||||
#define DHCP_MAX_RETRIES 5 // shrine has 3, why not 5 :^)
|
||||
|
||||
class CDHCPHeader
|
||||
{
|
||||
U8 opcode; // Opcode
|
||||
U8 hw_type; // Hardware Type
|
||||
U8 hw_addr_len; // Hardware Address Length
|
||||
U8 hops; // Hop Count
|
||||
U32 xid; // Transaction ID
|
||||
U16 seconds; // Elapsed time in seconds since client began address acquisition or renewal process
|
||||
U16 flags; // Flags
|
||||
U32 client_ip; // Client IP Address
|
||||
U32 your_ip; // Your IP Address
|
||||
U32 server_ip; // Server IP Address
|
||||
U32 gateway_ip; // Gateway IP Address
|
||||
U8 client_hw_addr[16]; // Client Hardware Address
|
||||
U8 server_name[64]; // Server Hostname
|
||||
U8 boot_file[128]; // Boot Filename
|
||||
};
|
||||
|
||||
class CDHCPDiscoverOptions
|
||||
{
|
||||
U32 cookie;
|
||||
U8 message_type;
|
||||
U8 message_length;
|
||||
U8 message; // dmt
|
||||
U8 param_req_list_type;
|
||||
U8 param_req_list_length;
|
||||
U8 param_req_list[4];
|
||||
U8 end;
|
||||
};
|
||||
|
||||
class CDHCPRequestOptions
|
||||
{
|
||||
U32 cookie;
|
||||
U8 message_type;
|
||||
U8 message_length;
|
||||
U8 message; // dmt
|
||||
U8 requested_ip_type;
|
||||
U8 requested_ip_length;
|
||||
U32 requested_ip;
|
||||
U8 server_id_type;
|
||||
U8 server_id_length;
|
||||
U32 server_id;
|
||||
U8 end;
|
||||
};
|
||||
|
||||
U32 DHCPBeginTransaction()
|
||||
{
|
||||
return RandU32();
|
||||
}
|
||||
|
||||
I64 DHCPSendDiscover(U32 xid)
|
||||
{
|
||||
U8 *ethernet_frame;
|
||||
I64 de_index;
|
||||
CDHCPHeader *dhcp;
|
||||
CDHCPDiscoverOptions *opts;
|
||||
|
||||
|
||||
de_index = UDPPacketAllocate(ðernet_frame,
|
||||
0x00000000,
|
||||
68,
|
||||
0xFFFFFFFF,
|
||||
67,
|
||||
sizeof(CDHCPHeader) + sizeof(CDHCPDiscoverOptions));
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithErr("DHCP SEND DISCOVER: Failed, UDP Packet Allocate error.\n");
|
||||
return de_index;
|
||||
}
|
||||
|
||||
dhcp = ethernet_frame;
|
||||
MemSet(dhcp, 0, sizeof(CDHCPHeader));
|
||||
|
||||
dhcp->opcode = DHCP_OPCODE_BOOTREQUEST;
|
||||
dhcp->hw_type = HTYPE_ETHERNET;
|
||||
dhcp->hw_addr_len = HLEN_ETHERNET;
|
||||
dhcp->hops = 0;
|
||||
dhcp->xid = EndianU32(xid);
|
||||
dhcp->seconds = 0;
|
||||
dhcp->flags = EndianU16(0x8000); // TODO: what is this
|
||||
dhcp->client_ip = 0;
|
||||
dhcp->your_ip = 0;
|
||||
dhcp->server_ip = 0;
|
||||
dhcp->gateway_ip = 0;
|
||||
MemCopy(dhcp->client_hw_addr, EthernetGetMAC(), MAC_ADDRESS_LENGTH);
|
||||
// "DHCP Send Discover\n";
|
||||
// ClassRep(dhcp);
|
||||
|
||||
opts = ethernet_frame + sizeof(CDHCPHeader);
|
||||
|
||||
opts->cookie = EndianU32(DHCP_COOKIE);
|
||||
opts->message_type = DHCP_OPTION_MESSAGETYPE;
|
||||
opts->message_length = 1;
|
||||
opts->message = DHCP_MESSAGETYPE_DISCOVER;
|
||||
opts->param_req_list_type = DHCP_OPTION_PARAMLIST;
|
||||
opts->param_req_list_length = 4;
|
||||
opts->param_req_list[0] = DHCP_OPTION_SUBNET_MASK;
|
||||
opts->param_req_list[1] = DHCP_OPTION_ROUTER;
|
||||
opts->param_req_list[2] = DHCP_OPTION_DNS;
|
||||
opts->param_req_list[3] = DHCP_OPTION_DOMAIN_NAME;
|
||||
opts->end = 0xFF; // ??
|
||||
// ClassRep(opts);
|
||||
|
||||
UDPPacketFinish(de_index);
|
||||
return de_index;
|
||||
}
|
||||
|
||||
I64 DHCPSendRequest(U32 xid, U32 requested_ip, U32 server_ip)
|
||||
{
|
||||
U8 *ethernet_frame;
|
||||
I64 de_index;
|
||||
CDHCPHeader *dhcp;
|
||||
CDHCPRequestOptions *opts;
|
||||
|
||||
de_index = UDPPacketAllocate(ðernet_frame,
|
||||
0x00000000,
|
||||
68,
|
||||
0xFFFFFFFF,
|
||||
67,
|
||||
sizeof(CDHCPHeader) + sizeof(CDHCPRequestOptions));
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithErr("DHCP SEND REQUEST: Failed, UDP Packet Allocate error.\n");
|
||||
}
|
||||
|
||||
dhcp = ethernet_frame;
|
||||
MemSet(dhcp, 0, sizeof(CDHCPHeader));
|
||||
|
||||
dhcp->opcode = DHCP_OPCODE_BOOTREQUEST;
|
||||
dhcp->hw_type = HTYPE_ETHERNET;
|
||||
dhcp->hw_addr_len = HLEN_ETHERNET;
|
||||
dhcp->hops = 0;
|
||||
dhcp->xid = EndianU32(xid);
|
||||
dhcp->seconds = 0;
|
||||
dhcp->flags = EndianU16(0x0000); // seems redundant ...
|
||||
dhcp->client_ip = 0;
|
||||
dhcp->your_ip = 0;
|
||||
dhcp->server_ip = EndianU32(server_ip);
|
||||
dhcp->gateway_ip = 0;
|
||||
MemCopy(dhcp->client_hw_addr, EthernetGetMAC(), MAC_ADDRESS_LENGTH);
|
||||
|
||||
opts = ethernet_frame + sizeof(CDHCPHeader);
|
||||
|
||||
opts->cookie = EndianU32(DHCP_COOKIE);
|
||||
opts->message_type = DHCP_OPTION_MESSAGETYPE;
|
||||
opts->message_length = 1;
|
||||
opts->message = DHCP_MESSAGETYPE_REQUEST;
|
||||
opts->requested_ip_type = DHCP_OPTION_REQUESTED_IP;
|
||||
opts->requested_ip_length = 4;
|
||||
opts->requested_ip = EndianU32(requested_ip);
|
||||
opts->server_id_type = DHCP_OPTION_SERVER_ID;
|
||||
opts->server_id_length = 4;
|
||||
opts->server_id = EndianU32(server_ip);
|
||||
opts->end = 0xFF;
|
||||
|
||||
// ClassRep(opts);
|
||||
UDPPacketFinish(de_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
I64 DHCPParseBegin(U8 **data_inout, I64 *length_inout, CDHCPHeader **header_out)
|
||||
{
|
||||
U8 *data = *data_inout;
|
||||
I64 length = *length_inout;
|
||||
U32 *cookie;
|
||||
|
||||
if (length < sizeof(CDHCPHeader) + 4) // + 4?
|
||||
{
|
||||
ZenithErr("DHCP PARSE BEGIN: Failed, length too short.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cookie = data + sizeof(CDHCPHeader);
|
||||
|
||||
if (EndianU32(*cookie) != DHCP_COOKIE)
|
||||
{
|
||||
ZenithErr("DHCP PARSE BEGIN: Failed, cookie doesn't match DHCP-cookie.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*header_out = data;
|
||||
*data_inout = data + sizeof(CDHCPHeader) + 4; // ?
|
||||
*length_inout = length - sizeof(CDHCPHeader) + 4; // ?..
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
I64 DHCPParseOption(U8 **data_inout, I64 *length_inout, U8 *type_out, U8 *value_length_out, U8 **value_out)
|
||||
{
|
||||
U8 *data = *data_inout;
|
||||
I64 length = *length_inout;
|
||||
|
||||
if (length < 2 || length < 2 + data[1]) // ??? what is the 1
|
||||
{
|
||||
ZenithErr("DHCP PARSE OPTION: Failed, length too short.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data[0] == 0xFF) // ahead, data[0] is type_out, so data[0] is perhaps usually type?
|
||||
{
|
||||
ZenithLog("DHCP PARSE OPTION: Saw 0xFF, returning 0.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*type_out = data[0];
|
||||
*value_length_out = data[1];
|
||||
*value_out = data + 2;
|
||||
|
||||
*data_inout = data + 2 + *value_length_out;
|
||||
*length_inout = length - 2 + *value_length_out;
|
||||
|
||||
return data[0]; // returns ... type?
|
||||
}
|
||||
|
||||
I64 DHCPParseOffer(U32 xid, U8 *data, I64 length,
|
||||
U32 *your_ip_out,
|
||||
U32 *dns_ip_out,
|
||||
U32 *router_ip_out,
|
||||
U32 *subnet_mask_out)
|
||||
{
|
||||
CDHCPHeader *header;
|
||||
I64 error = DHCPParseBegin(&data, &length, &header);
|
||||
Bool have_type = FALSE;
|
||||
Bool have_dns = FALSE;
|
||||
Bool have_router = FALSE;
|
||||
Bool have_subnet = FALSE;
|
||||
U8 type;
|
||||
U8 value_length;
|
||||
U8 *value;
|
||||
|
||||
|
||||
if (EndianU32(header->xid) != xid)
|
||||
{
|
||||
ZenithErr("DHCP PARSE OFFER: Failed, parsed and parameter Transaction IDs do not match.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (length)
|
||||
{
|
||||
error = DHCPParseOption(&data, &length, &type, &value_length, &value);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("DHCP PARSE OFFER: Failed at DHCP Parse Option.\n");
|
||||
return error;
|
||||
}
|
||||
if (error == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DHCP_OPTION_MESSAGETYPE:
|
||||
ZenithLog("DHCP PARSE OFFER: Parsed Option, Type MESSAGETYPE.\n");
|
||||
if (value_length == 1 && value[0] == DHCP_MESSAGETYPE_OFFER)
|
||||
have_type = TRUE;
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_DNS:
|
||||
ZenithLog("DHCP PARSE OFFER: Parsed Option, Type DNS.\n");
|
||||
if (value_length == 4)
|
||||
{
|
||||
*dns_ip_out = EndianU32(*(value(U32 *))); // TODO: this syntax used on last 3 cases is gross, alter it
|
||||
have_dns = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_ROUTER:
|
||||
ZenithLog("DHCP PARSE OFFER: Parsed Option, Type ROUTER.\n");
|
||||
if (value_length == 4)
|
||||
{
|
||||
*router_ip_out = EndianU32(*(value(U32 *))); //
|
||||
have_router = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DHCP_OPTION_SUBNET_MASK:
|
||||
ZenithLog("DHCP PARSE OFFER: Parsed Option, Type SUBNET MASK.\n");
|
||||
if (value_length == 4)
|
||||
{
|
||||
*subnet_mask_out = EndianU32(*(value(U32 *))); //
|
||||
have_subnet = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_type && have_dns && have_subnet && have_router)
|
||||
{
|
||||
*your_ip_out = EndianU32(header->your_ip);
|
||||
ZenithLog("DHCP PARSE OFFER: Success, got your-ip from DHCP Header.\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithErr("DHCP PARSE OFFER: Failed, did not have needed Options.\n");
|
||||
ZenithErr(" have_type: %Z\n", have_type, "ST_FALSE_TRUE");
|
||||
ZenithErr(" have_dns: %Z\n", have_dns, "ST_FALSE_TRUE");
|
||||
ZenithErr(" have_router: %Z\n", have_router, "ST_FALSE_TRUE");
|
||||
ZenithErr(" have_subnet: %Z\n", have_subnet, "ST_FALSE_TRUE");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
I64 DHCPParseAck(U32 xid, U8 *data, I64 length)
|
||||
{
|
||||
CDHCPHeader *header;
|
||||
I64 error = DHCPParseBegin(&data, &length, &header);
|
||||
U8 type;
|
||||
U8 value_length;
|
||||
U8 *value;
|
||||
|
||||
if (EndianU32(header->xid) != xid)
|
||||
{
|
||||
ZenithErr("DHCP PARSE ACK: Failed, parsed and parameter Transaction IDs do not match.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (length)
|
||||
{
|
||||
error = DHCPParseOption(&data, &length, &type, &value_length, &value);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("DHCP PARSE ACK: Failed at DHCP Parse Option.\n");
|
||||
return error;
|
||||
}
|
||||
if (error == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case DHCP_OPTION_MESSAGETYPE:
|
||||
if (value_length == 1 && value[0] == DHCP_MESSAGETYPE_ACK)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ZenithErr("DHCP PARSE ACK: Failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
I64 DHCPConfigureInner(CUDPSocket *udp_socket,
|
||||
U32 *your_ip_out,
|
||||
U32 *dns_ip_out,
|
||||
U32 *router_ip_out,
|
||||
U32 *subnet_mask_out)
|
||||
{
|
||||
I64 state = DHCP_STATE_CLIENT_START;
|
||||
I64 retries = 0;
|
||||
I64 timeout = DHCP_TIMEOUT;
|
||||
I64 error = 0;
|
||||
U32 xid;
|
||||
U32 dhcp_addr;
|
||||
U8 buffer[2048];
|
||||
I64 count;
|
||||
|
||||
CSocketAddressIPV4 ipv4_addr;
|
||||
CSocketAddressIPV4 ipv4_addr_in;
|
||||
|
||||
//Shrine: setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO_MS, &timeout, sizeof(timeout)))
|
||||
udp_socket->receive_timeout_ms = timeout;
|
||||
|
||||
ipv4_addr.family = AF_INET;
|
||||
ipv4_addr.port = EndianU16(68);
|
||||
ipv4_addr.address.address = INADDR_ANY;
|
||||
|
||||
if (UDPSocketBind(udp_socket, &ipv4_addr) < 0)
|
||||
{
|
||||
ZenithErr("DHCP CONFIGURE INNER: Failed to Bind UDP Socket.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
xid = DHCPBeginTransaction();
|
||||
|
||||
while (state != DHCP_STATE_CLIENT_REQ_ACCEPTED)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case DHCP_STATE_CLIENT_START:
|
||||
state = DHCP_STATE_CLIENT_DISCOVER;
|
||||
retries = 0;
|
||||
|
||||
break;
|
||||
|
||||
case DHCP_STATE_CLIENT_DISCOVER:
|
||||
ZenithLog("DHCP CONFIGURE INNER: Trying Discover.\n");
|
||||
error = DHCPSendDiscover(xid);
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("DHCP CONFIGURE INNER: Failed, DHCP Send Discover error.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
count = UDPSocketReceiveFrom(udp_socket, buffer, sizeof(buffer), &ipv4_addr_in);
|
||||
|
||||
if (count > 0)
|
||||
{ // 'Try a parse offer'
|
||||
ZenithLog("DHCP CONFIGURE INNER: Trying Parse Offer.\n");
|
||||
error = DHCPParseOffer(xid, buffer, count, your_ip_out, dns_ip_out, router_ip_out, subnet_mask_out);
|
||||
|
||||
if (error < 0)
|
||||
ZenithWarn("DHCP CONFIGURE INNER: Unsuccessful DHCP Parse Offer.\n");
|
||||
}
|
||||
|
||||
if (count > 0 && error >= 0) // TODO: >= ? can DHCPSendDiscover or DHCPParseOffer return greater than zero?
|
||||
{
|
||||
dhcp_addr = EndianU32(ipv4_addr_in.address.address);
|
||||
state = DHCP_STATE_CLIENT_REQUEST;
|
||||
retries = 0;
|
||||
}
|
||||
else if (++retries == DHCP_MAX_RETRIES)
|
||||
{
|
||||
ZenithErr("DHCP CONFIGURE INNER: Failed, hit max retries in DHCP DISCOVER state.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DHCP_STATE_CLIENT_REQUEST:
|
||||
ZenithLog("DHCP CONFIGURE INNER: Trying Send Request.\n");
|
||||
error = DHCPSendRequest(xid, *your_ip_out, dhcp_addr);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("DHCP CONFIGURE INNER: Failed, unsuccessful DHCP Send Request.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
count = UDPSocketReceiveFrom(udp_socket, buffer, sizeof(buffer), &ipv4_addr_in);
|
||||
|
||||
if (count > 0)
|
||||
{ // 'Try parse Ack'
|
||||
error = DHCPParseAck(xid, buffer, count);
|
||||
|
||||
if (error < 0)
|
||||
ZenithWarn("DHCP CONFIGURE INNER: Unsuccessful DHCP Parse Ack.\n");
|
||||
}
|
||||
|
||||
if (count > 0 && error >= 0) // see above TODO
|
||||
{
|
||||
dhcp_addr = EndianU32(ipv4_addr_in.address.address);
|
||||
state = DHCP_STATE_CLIENT_REQ_ACCEPTED;
|
||||
}
|
||||
else if (++retries == DHCP_MAX_RETRIES)
|
||||
{
|
||||
ZenithErr("DHCP CONFIGURE INNER: Failed, hit max retries in DHCP REQUEST state.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
I64 DHCPConfigure()
|
||||
{
|
||||
CUDPSocket *udp_socket = UDPSocket(AF_INET);
|
||||
CIPV4Address address;
|
||||
U32 your_ip;
|
||||
U32 dns_ip;
|
||||
U32 router_ip;
|
||||
U32 subnet_mask;
|
||||
I64 state = DHCPConfigureInner(udp_socket, &your_ip, &dns_ip, &router_ip, &subnet_mask);
|
||||
|
||||
UDPSocketClose(udp_socket);
|
||||
|
||||
if (state == DHCP_STATE_CLIENT_REQ_ACCEPTED)
|
||||
{
|
||||
address.address = EndianU32(your_ip);
|
||||
ZenithLog("$$FG,2$$DHCP CONFIGURE: Obtained IPV4 Address! : %s $$FG$$\n", NetworkToPresentation(AF_INET, &address));
|
||||
|
||||
IPV4SetAddress(your_ip);
|
||||
IPV4SetSubnet(router_ip, subnet_mask);
|
||||
DNSSetResolverIPV4(dns_ip);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithErr("$$FG,4$$DHCP CONFIGURE: Failed, incorrect state.$$FG$$\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
U0 NetConfigure()
|
||||
{
|
||||
I64 error;
|
||||
|
||||
ZenithLog("==== Configuring Network. ====\n");
|
||||
error = DHCPConfigure();
|
||||
|
||||
if (error < 0)
|
||||
ZenithLog("$$FG,4$$==== Network Configure Failed ====$$FG$$\n");
|
||||
else
|
||||
ZenithLog("$$FG,2$$==== Network Configure Success ====$$FG$$\n");
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
#include "UDP";
|
||||
//#include "UDP";
|
||||
|
||||
// https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf
|
||||
// https://en.wikipedia.org/wiki/Domain_Name_System
|
||||
|
@ -17,6 +17,9 @@
|
|||
#define DNS_CLASS_IN 1
|
||||
|
||||
#define DNS_TIMEOUT 5000
|
||||
|
||||
#define DNS_MAX_RETRIES 5 // Shrine has 3, why not 5? :^)
|
||||
|
||||
class CDNSHash:CHash
|
||||
{ // store U8 *hostname as CHash->str U8 *
|
||||
CAddressInfo info;
|
||||
|
@ -82,25 +85,30 @@ CDNSHash *DNSCacheFind(U8 *hostname)
|
|||
CDNSHash *entry = HashFind(hostname, dns_cache, HTT_DNS);
|
||||
|
||||
if (entry == NULL)
|
||||
ZenithErr("Could not find a hostname in the DNS Cache.\n");
|
||||
ZenithWarn("DNS CACHE FIND: Could not find a hostname in the DNS Cache.\n");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
CDNSHash *DNSCachePut(U8 *hostname, CAddressInfo *info)
|
||||
{
|
||||
ZenithLog("DNS CACHE PUT: Attempting Find DNS Entry in Cache: hostname: %s\n", hostname);
|
||||
/* "==\n";ClassRep(info);
|
||||
ClassRep(info->address(CSocketAddressIPV4 *));"==\n";*/
|
||||
CDNSHash *entry = DNSCacheFind(hostname);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
entry = CAlloc(sizeof(CDNSHash));
|
||||
entry->str = StrNew(hostname);
|
||||
entry->type = HTT_DNS;
|
||||
|
||||
AddressInfoCopy(&entry->info, info);
|
||||
|
||||
HashAdd(entry, dns_cache);
|
||||
}
|
||||
else
|
||||
ZenithWarn("DNS Cache Put attempted but entry was already found in Cache. TODO: overwrite?");
|
||||
ZenithWarn("DNS CACHE PUT: Entry was already found in Cache. TODO: overwrite?");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -150,18 +158,22 @@ I64 DNSSendQuestion(U16 id, U16 local_port, CDNSQuestion *q)
|
|||
switch (dns_globals.addr_family)
|
||||
{
|
||||
case AF_UNSPEC: // 0, global dns ip not set
|
||||
ZenithErr("DNS SEND QUESTION: Failed, global dns addr family was AF_UNSPEC.\n");
|
||||
return -1;
|
||||
|
||||
case AF_INET6:
|
||||
ZenithErr("IPV6 not supported yet in DNS.\n");
|
||||
ZenithErr("DNS SEND QUESTION: Failed, IPV6 not supported yet in DNS.\n");
|
||||
throw('DNS');
|
||||
|
||||
case AF_INET:
|
||||
ipv4_addr = &dns_globals.dns_ip;
|
||||
|
||||
if (!*ipv4_addr)
|
||||
{
|
||||
ZenithErr("DNS SEND QUESTION: Failed, ipv4_addr had no value set.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// UDPPacketAllocate currently only accepts IPV4 ...
|
||||
de_index = UDPPacketAllocate(&frame,
|
||||
|
@ -171,7 +183,10 @@ I64 DNSSendQuestion(U16 id, U16 local_port, CDNSQuestion *q)
|
|||
53,
|
||||
sizeof(CDNSHeader) + DNSCalculateQuestionSize(q));
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithErr("DNS SEND QUESTION: Failed, UDPPacketAllocate returned error.\n");
|
||||
return de_index;
|
||||
}
|
||||
|
||||
flags = (DNS_OP_QUERY << 11) | DNS_FLAG_RD;
|
||||
|
||||
|
@ -202,7 +217,7 @@ I64 DNSParseDomainName(U8 *packet_data, I64 packet_length, U8 **data_inout, I64
|
|||
|
||||
if (length < 1)
|
||||
{
|
||||
ZenithErr("DNS parsed domain name, hit length of 0 or less\n");
|
||||
ZenithErr("DNS PARSE DOMAIN NAME: Length less than one.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -228,7 +243,7 @@ I64 DNSParseDomainName(U8 *packet_data, I64 packet_length, U8 **data_inout, I64
|
|||
*data_inout = data + 1;
|
||||
*length_inout = length - 1;
|
||||
jump_taken = TRUE;
|
||||
ZenithLog("UDP parsed domain name, jump taken\n");
|
||||
ZenithLog("DNS PARSE DOMAIN NAME: Jump taken\n");
|
||||
}
|
||||
|
||||
data = packet_data + ((label_len << 8) | *data);
|
||||
|
@ -317,7 +332,7 @@ I64 DNSParseRR(U8 *packet_data, I64 packet_length, U8 **data_inout, I64 *length_
|
|||
return 0;
|
||||
}
|
||||
|
||||
I64 DNSParseResponse(U16 id, U8 *data, I64 len, CDNSHeader **header_out, CDNSQuestion **questions_out, CDNSRR **answers_out)
|
||||
I64 DNSParseResponse(U16 id, U8 *data, I64 length, CDNSHeader **header_out, CDNSQuestion **questions_out, CDNSRR **answers_out)
|
||||
{
|
||||
CDNSHeader *header;
|
||||
CDNSQuestion *question;
|
||||
|
@ -328,7 +343,7 @@ I64 DNSParseResponse(U16 id, U8 *data, I64 len, CDNSHeader **header_out, CDNSQue
|
|||
|
||||
if (length < sizeof(CDNSHeader))
|
||||
{
|
||||
ZenithErr("DNS Response Parsed, length too short.\n");
|
||||
ZenithErr("DNS PARSE RESPONSE: Length too short.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -337,7 +352,7 @@ I64 DNSParseResponse(U16 id, U8 *data, I64 len, CDNSHeader **header_out, CDNSQue
|
|||
|
||||
if (id != 0 && EndianU16(header->id) != id)
|
||||
{
|
||||
ZenithErr("DNS Response Parsed, header id mismatch.\n");
|
||||
ZenithErr("DNS PARSE RESPONSE: Header ID mismatch.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -399,7 +414,7 @@ U0 DNSFreeQuestion(CDNSQuestion *q)
|
|||
Free(q->q_name.labels[0]);
|
||||
}
|
||||
|
||||
U0 DNSFreeRR(CDNSRR *r)
|
||||
U0 DNSFreeRR(CDNSRR *rr)
|
||||
{
|
||||
Free(rr->name.labels[0]);
|
||||
}
|
||||
|
@ -430,17 +445,18 @@ U0 DNSFreeRRChain(CDNSRR *rrs)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
I64 DNSRunQuery(CUDPSocket *udp_socket, U8 *name, U16 port, CAddressInfo **result_out)
|
||||
{ // IPV4-UDP-based
|
||||
{ // IPV4-UDP-based, TODO: take good look at this method to ensure no floating pointers after.
|
||||
// note: UDP Socket created in this method is not closed in this method, gets closed e.g. in DNSGetAddressInfo
|
||||
I64 retries = 0;
|
||||
I64 timeout = DNS_TIMEOUT;
|
||||
U16 local_port = RandU16;
|
||||
U16 local_port = RandU16; // TODO: is rand needed? would a local port 0 work? (would improve lookup speed)
|
||||
U16 id = RandU16;
|
||||
I64 error = 0;
|
||||
U8 *buffer;
|
||||
U8 buffer[2048];
|
||||
I64 count;
|
||||
Bool have;
|
||||
Bool have; // ??
|
||||
|
||||
CDNSQuestion q;
|
||||
CDNSHeader *header;
|
||||
|
@ -450,24 +466,214 @@ I64 DNSRunQuery(CUDPSocket *udp_socket, U8 *name, U16 port, CAddressInfo **resul
|
|||
|
||||
CSocketAddressIPV4 ipv4_addr;
|
||||
CSocketAddressIPV4 ipv4_addr_in; // ?
|
||||
CSocketAddressIPV4 *ipv4_addr_temp;
|
||||
CAddressInfo *res;
|
||||
|
||||
//setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO_MS, &timeout, sizeof(timeout))
|
||||
udp_socket->receive_timeout_ms = timeout;
|
||||
|
||||
ipv4_addr.family = AF_INET;
|
||||
ipv4_addr.port = EndianU16(local_port);
|
||||
ipv4_addr.address.address = INADDR_ANY;
|
||||
|
||||
|
||||
// UDPSocketBind will be attempted on the udp_socket param, method expects a UDPSocket() result to be made already
|
||||
if (UDPSocketBind(udp_socket, &ipv4_addr)) // expected return value is 0
|
||||
{
|
||||
ZenithErr("DNS RUN QUERY: Failed to bind UDP socket.\n");
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
I64 DNSRunQuery(socket?, U8 *name, U16 port, CAddressInfo **result_out)
|
||||
DNSBuildQuestion(&q, name);
|
||||
|
||||
I64 DNSGetAddressInfo(U8 *node, U8 *service, CAddressInfo *hints, CAddressInfo **result)
|
||||
while (TRUE) // Shrine uses while (1) infinite loop, need to be careful not to lock
|
||||
{
|
||||
error = DNSSendQuestion(id, local_port, &q);
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("DNS RUN QUERY: Failed to Send Question.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
U0 DNSSetResolverIPV4(U32 ip) // funny enough he explicitly labeled IPV4.........
|
||||
count = UDPSocketReceiveFrom(udp_socket, buffer, sizeof(buffer), &ipv4_addr_in);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
ZenithLog("DNS RUN QUERY: Trying Parse Response.\n");
|
||||
|
||||
header = NULL;
|
||||
questions = NULL;
|
||||
answers = NULL;
|
||||
|
||||
error = DNSParseResponse(id, buffer, count, &header, &questions, &answers);
|
||||
|
||||
if (error == 0) // Shrine has (error >= 0), but DNSParseResponse can only return 0 or 1 ..
|
||||
{
|
||||
have = FALSE;
|
||||
|
||||
a = answers;
|
||||
while (a)
|
||||
{
|
||||
// Shrine has TODO: if multiple acceptable answers, pick one at random, not just first one.
|
||||
// perhaps we could use r_count in header for that ?
|
||||
|
||||
if (EndianU16(a->type) == DNS_TYPE_A &&
|
||||
EndianU16(a->rr_class) == DNS_CLASS_IN &&
|
||||
EndianU16(a->rd_length) == 4)
|
||||
{
|
||||
res = CAlloc(sizeof(CAddressInfo));
|
||||
|
||||
res->flags = 0;
|
||||
res->family = AF_INET;
|
||||
res->socket_type = 0; // ??
|
||||
res->protocol = 0; // ??
|
||||
res->address_length = sizeof(CSocketAddressIPV4);
|
||||
res->address = CAlloc(sizeof(CSocketAddressIPV4));
|
||||
res->canonical_name = 0;
|
||||
res->next = NULL;
|
||||
|
||||
ipv4_addr_temp = res->address;
|
||||
|
||||
ipv4_addr_temp->family = AF_INET;
|
||||
ipv4_addr_temp->port = port;
|
||||
MemCopy(&ipv4_addr_temp->address.address, answers->r_data, 4);
|
||||
|
||||
DNSCachePut(name, res);
|
||||
*result_out = res;
|
||||
have = TRUE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
a = a->next;
|
||||
}
|
||||
|
||||
DNSFreeQuestionChain(questions);
|
||||
DNSFreeRRChain(answers);
|
||||
|
||||
if (have)
|
||||
break;
|
||||
|
||||
// Shrine comment: 'at this point, we could try iterative resolution,
|
||||
// but all end-user DNS servers would have tried that already'
|
||||
|
||||
ZenithErr("DNS RUN QUERY: Failed to find suitable answer in reply.\n");
|
||||
error = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithErr("DNS RUN QUERY: Failed a DNS Parse Response.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (++retries == DNS_MAX_RETRIES)
|
||||
{
|
||||
ZenithErr("DNS RUN QUERY: Failed, max retries reached.\n");
|
||||
error = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DNSFreeQuestion(&q);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Shrine has port arg as U8 *service with a no_warn and says it should be parsed as port, allowing that here
|
||||
// Also has CAddressInfo *hints with a no_warn, omitting that for now
|
||||
I64 DNSGetAddressInfo(U8 *node_name, U16 port, CAddressInfo **result)
|
||||
{
|
||||
I64 error;
|
||||
CUDPSocket *udp_socket;
|
||||
CDNSHash *cached_entry = DNSCacheFind(node_name);
|
||||
|
||||
if (cached_entry)
|
||||
{
|
||||
*result = CAlloc(sizeof(CAddressInfo));
|
||||
AddressInfoCopy(*result, &cached_entry->info);
|
||||
//(*res)->flags |= AI_CACHED; // TODO: add AI_CACHED define (maybe a better name?) not used anywhere i don't think..
|
||||
return 0;
|
||||
}
|
||||
|
||||
udp_socket = UDPSocket(AF_INET);
|
||||
error = 0;
|
||||
|
||||
if (udp_socket)
|
||||
{
|
||||
error = DNSRunQuery(udp_socket, node_name, port, result);
|
||||
|
||||
UDPSocketClose(udp_socket);
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithErr("DNS GET ADDRESS INFO: Failed to make UDP Socket.\n");
|
||||
error = -1;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
U0 DNSSetResolverIPV4(U32 ip)
|
||||
{
|
||||
CIPV4Address *address = &dns_globals.dns_ip;
|
||||
|
||||
dns_globals.addr_family = AF_INET;
|
||||
address->address = ip;
|
||||
}
|
||||
|
||||
U0 Host(U8 *hostname)
|
||||
{ // getaddrinfo() for whole system in Shrine ends up as pointer to DNSGetAddressInfo.. should we do something similar?
|
||||
CAddressInfo *current;
|
||||
CAddressInfo *result = NULL;
|
||||
I64 error = DNSGetAddressInfo(hostname, NULL, &result);
|
||||
I64 i = 0;
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("HOST(): Failed at DNS Get Address Info.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
"Host() Results:\n\n";
|
||||
current = result;
|
||||
while (current)
|
||||
{
|
||||
"Result %d:\n", ++i;
|
||||
|
||||
" flags: %04Xh \n", current->flags;
|
||||
" family: %d \n", current->family;
|
||||
" socket type: %d \n", current->socket_type;
|
||||
" protocol: %d \n", current->protocol;
|
||||
" address length: %d \n", current->address_length;
|
||||
" address: %s \n", NetworkToPresentation(AF_INET, ¤t->address(CSocketAddressIPV4 *)->address);
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
AddressInfoFree(result);
|
||||
}
|
||||
|
||||
U0 DNSRep()
|
||||
{ // TODO: primitive, needs refine. switch() on Socket Address types for NetworkToPresentation, etc
|
||||
I64 i;
|
||||
CDNSHash *temp_hash;
|
||||
|
||||
"\n";
|
||||
Who(, dns_cache);
|
||||
"\n";
|
||||
|
||||
for (i = 0; i <= dns_cache->mask; i++)
|
||||
{
|
||||
temp_hash = dns_cache->body[i];
|
||||
|
||||
while (temp_hash)
|
||||
{
|
||||
ClassRep(temp_hash,, 5);
|
||||
temp_hash = temp_hash->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
U0 DNSInit()
|
||||
|
||||
|
|
Binary file not shown.
|
@ -36,6 +36,8 @@ U0 EthernetFrameParse(CEthernetFrame *frame_out, U8 *frame, U16 length)
|
|||
//of the current system should be done with less extra allocation
|
||||
//altogether, more passing.
|
||||
|
||||
ZenithLog("ETHERNET FRAME PARSE: Parsing frame, copying out to frame_out param.\n");
|
||||
|
||||
MemCopy(frame_out->destination_address, frame, MAC_ADDRESS_LENGTH);
|
||||
|
||||
MemCopy(frame_out->source_address, frame + MAC_ADDRESS_LENGTH, MAC_ADDRESS_LENGTH);
|
||||
|
@ -44,7 +46,7 @@ U0 EthernetFrameParse(CEthernetFrame *frame_out, U8 *frame, U16 length)
|
|||
|
||||
frame_out->data = frame + ETHERNET_DATA_OFFSET;
|
||||
|
||||
frame_out->length = length - ETHERNET_MAC_HEADER_LENGTH + 4; // He has a comment literally just saying "??".
|
||||
frame_out->length = length - ETHERNET_MAC_HEADER_LENGTH - 4; // He has a comment literally just saying "??". + or - 4?
|
||||
}
|
||||
|
||||
EthernetInitGlobals;
|
|
@ -1,4 +1,4 @@
|
|||
#include "IPV4"
|
||||
//#include "IPV4"
|
||||
|
||||
#define ICMP_TYPE_ECHO_REPLY 0
|
||||
#define ICMP_TYPE_ECHO_REQUEST 8
|
||||
|
@ -32,7 +32,7 @@ I64 ICMPSendReply(U32 destination_ip_address,
|
|||
sizeof(CICMPHeader) + length);
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithLog("ICMP Send Reply failed to allocate IPV4 packet.\n");
|
||||
ZenithErr("ICMP SEND REPLY: Failed to allocate IPV4 packet.\n");
|
||||
return de_index;
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ I64 ICMPHandler(CIPV4Packet *packet)
|
|||
|
||||
if (packet->length < sizeof(CICMPHeader))
|
||||
{
|
||||
ZenithLog("ICMP Handler caught wrong IPV4 length.\n");
|
||||
ZenithErr("ICMP HANDLER: Caught wrong IPV4 length.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "ARP"
|
||||
//#include "ARP"
|
||||
|
||||
#define IPV4_ERR_ADDR_INVALID -200001
|
||||
#define IPV4_ERR_HOST_UNREACHABLE -200002
|
||||
|
@ -42,7 +42,7 @@ class CIPV4Header
|
|||
|
||||
U32 source_ip_address;
|
||||
U32 destination_ip_address;
|
||||
}
|
||||
};
|
||||
|
||||
class CIPV4Globals
|
||||
{ // _be indicates Big Endian
|
||||
|
@ -60,7 +60,7 @@ U0 InitIPV4Globals()
|
|||
ipv4_globals.local_ip_be = 0;
|
||||
ipv4_globals.ipv4_router_address = 0;
|
||||
ipv4_globals.ipv4_subnet_mask = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// For now, trusting Shrine's implement
|
||||
// of checksum. Shrine links back to
|
||||
|
@ -96,25 +96,26 @@ I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
|||
CARPHash *entry;
|
||||
I64 retries;
|
||||
I64 attempt;
|
||||
/*
|
||||
switch (ip_address)
|
||||
{
|
||||
case 0:
|
||||
return IPV4_ERR_ADDR_INVALID;
|
||||
case 0xFFFFFFFF:
|
||||
*mac_out = ethernet_globals.ethernet_broadcast;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (ip_address == 0)
|
||||
{
|
||||
ZenithLog("Get MAC for IP failed. Address = 0\n");
|
||||
ZenithErr("GET MAC FOR IP: Failed. Address = 0\n");
|
||||
return IPV4_ERR_ADDR_INVALID;
|
||||
}
|
||||
if (ip_address == 0xFFFFFFFF)
|
||||
{
|
||||
ZenithLog("Get MAC for IP requested and returning ethernet broadcast\n");
|
||||
ZenithLog("GET MAC FOR IP: Returning ethernet broadcast\n");
|
||||
*mac_out = ethernet_globals.ethernet_broadcast;
|
||||
|
||||
/* I64 i;
|
||||
"\nEthernet Global Broadcast\n";
|
||||
for (i = 0; i < 6; i++)
|
||||
" %X", ethernet_globals.ethernet_broadcast[i];
|
||||
"\nMac Out\n";
|
||||
for (i = 0; i < 6; i++)
|
||||
" %X", (*mac_out)[i];
|
||||
"\n";
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -122,9 +123,12 @@ I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
|||
if ((ip_address & ipv4_globals.ipv4_subnet_mask) != (ipv4_globals.local_ip & ipv4_globals.ipv4_subnet_mask))
|
||||
{
|
||||
// TODO: Shrine recurses here... and says FIXME infinite loop if mis-configured...
|
||||
ZenithWarn("GET MAC FOR IP: TODO: Doing GetMACAddressForIP recursion, could infinite loop and overflow stack.");
|
||||
return GetMACAddressForIP(ipv4_globals.ipv4_router_address, mac_out);
|
||||
}
|
||||
else // "local network"
|
||||
{
|
||||
ZenithLog("GET MAC FOR IP: Attempting ARP Find by IP for address: %d.\n", ip_address);
|
||||
entry = ARPCacheFindByIP(ip_address);
|
||||
|
||||
if (entry)
|
||||
|
@ -138,6 +142,13 @@ I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
|||
retries = 4;
|
||||
while (retries)
|
||||
{
|
||||
ARPSend(ARP_REQUEST,
|
||||
ethernet_globals.ethernet_broadcast,
|
||||
EthernetGetMAC,
|
||||
ipv4_globals.local_ip_be,
|
||||
ethernet_globals.ethernet_null,
|
||||
EndianU32(ip_address));
|
||||
|
||||
attempt = 0;
|
||||
for (attempt = 0; attempt < 50; attempt++)
|
||||
{
|
||||
|
@ -157,7 +168,7 @@ I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
|||
}
|
||||
|
||||
//Shrine does some in_addr mess to log error
|
||||
ZenithLog("Failed to resolve address %d", ip_address);
|
||||
ZenithErr("GET MAC FOR IP: Failed to resolve address %d\n", ip_address);
|
||||
return IPV4_ERR_HOST_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +190,7 @@ I64 IPV4PacketAllocate(U8 **frame_out,
|
|||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithLog("IPV4 Packet Allocate failed to get MAC for destination.\n");
|
||||
ZenithLog("IPV4 PACKET ALLOCATE: Failed to get MAC for destination.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -190,7 +201,7 @@ I64 IPV4PacketAllocate(U8 **frame_out,
|
|||
sizeof(CIPV4Header) + length);
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithLog("IPV4 Ethernet Frame Allocate failed.\n");
|
||||
ZenithLog("IPV4 PACKET ALLOCATE: Ethernet Frame Allocate failed.\n");
|
||||
return de_index;
|
||||
}
|
||||
|
||||
|
@ -208,7 +219,7 @@ I64 IPV4PacketAllocate(U8 **frame_out,
|
|||
header->header_checksum = 0; // why is 0 ok?
|
||||
header->source_ip_address = EndianU32(source_ip_address);
|
||||
header->destination_ip_address = EndianU32(destination_ip_address);
|
||||
header->header_checksum = IPV4Checksum(header, internet_header_length + 4);//why the 4's...
|
||||
header->header_checksum = IPV4Checksum(header, internet_header_length * 4);//why the 4's...
|
||||
|
||||
*frame_out = ethernet_frame + sizeof(CIPV4Header);
|
||||
return de_index;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
/* Ethernet Frame Size.
|
||||
Linux uses 1544, OSDev and Shrine use 1548. Based on IEEE 802.3as, max frame size was agreed upon as 2000 bytes. */
|
||||
#define ETHERNET_FRAME_SIZE 2000
|
||||
#define ETHERNET_FRAME_SIZE 2048//2000
|
||||
|
||||
#define HTYPE_ETHERNET 1
|
||||
#define HLEN_ETHERNET 6
|
||||
|
|
|
@ -9,13 +9,13 @@ U0 IPV4Handler(CEthernetFrame *ethernet_frame)
|
|||
switch (packet.protocol)
|
||||
{
|
||||
case IP_PROTOCOL_ICMP:
|
||||
ZenithLog("IPV4 Handler: ICMP.\n");
|
||||
ZenithLog("IPV4 HANDLER: ICMP.\n");
|
||||
ICMPHandler(&packet);
|
||||
break;
|
||||
case IP_PROTOCOL_TCP:
|
||||
break;
|
||||
case IP_PROTOCOL_UDP:
|
||||
ZenithLog("IPV4 Handler: UDP.\n");
|
||||
ZenithLog("IPV4 HANDLER: UDP.\n");
|
||||
UDPHandler(&packet);
|
||||
break;
|
||||
}
|
||||
|
@ -30,9 +30,11 @@ U0 HandleNetQueueEntry(CNetQueueEntry *entry)
|
|||
switch (ethernet_frame.ethertype)
|
||||
{
|
||||
case ETHERTYPE_ARP:
|
||||
ZenithLog("HANDLE NETQUEUE ENTRY: ARP.\n");
|
||||
ARPHandler(ðernet_frame);
|
||||
break;
|
||||
case ETHERTYPE_IPV4:
|
||||
ZenithLog("HANDLE NETQUEUE ENTRY: IPV4.\n");
|
||||
IPV4Handler(ðernet_frame);
|
||||
break;
|
||||
}
|
||||
|
@ -42,10 +44,11 @@ U0 NetHandlerTask(I64)
|
|||
{
|
||||
while (TRUE)
|
||||
{
|
||||
CNetQueueEntry *entry = NetQueuePull;
|
||||
CNetQueueEntry *entry = NetQueuePull();
|
||||
|
||||
if (entry)
|
||||
{
|
||||
ZenithLog("NET HANDLER TASK: Caught NetQueue Entry, handling.\n");
|
||||
HandleNetQueueEntry(entry);
|
||||
}
|
||||
else
|
||||
|
@ -56,6 +59,8 @@ U0 NetHandlerTask(I64)
|
|||
}
|
||||
|
||||
}
|
||||
ZenithErr("Net Handler Task exit! Debug!\n"); // shouldn't ever reach this
|
||||
}
|
||||
|
||||
net_handler_task = Spawn(&NetHandlerTask, NULL, "NetQueueHandler",,);
|
||||
net_handler_task = Spawn(&NetHandlerTask, NULL, "NetQueueHandler");
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ class CNetQueueEntry:CQueue
|
|||
U8 frame[ETHERNET_FRAME_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/* global variable, holds pointer of Ethernet Queue.
|
||||
This acts as the Head of the Queue, Entries act
|
||||
as the Tail of the Queue.
|
||||
|
@ -21,11 +22,14 @@ class CNetQueueEntry:CQueue
|
|||
|
||||
CQueue *net_queue; // no QueueRemove the Head! only Entries!
|
||||
|
||||
|
||||
/* Net Handler Task is set idle and active depending
|
||||
on if entries in Net Queue. See $LK,"NetHandlerTask",A="FF:C:/Home/Net/NetHandlerTask.CC,net_handler_task"$ */
|
||||
|
||||
CTask *net_handler_task = NULL;
|
||||
|
||||
|
||||
|
||||
U0 NetQueueInit()
|
||||
{
|
||||
net_queue = CAlloc(sizeof(CQueue));
|
||||
|
@ -35,11 +39,14 @@ U0 NetQueueInit()
|
|||
CNetQueueEntry *NetQueuePull()
|
||||
{/* Returns a pointer to a CNetQueueEntry,
|
||||
or NULL pointer if Net Queue is empty. */
|
||||
|
||||
CNetQueueEntry *entry;
|
||||
|
||||
if (net_queue->next != net_queue)
|
||||
{
|
||||
entry = net_queue->next;
|
||||
|
||||
ZenithLog("NETQUEUE PULL: Removing entry from queue.\n");
|
||||
QueueRemove(entry);
|
||||
}
|
||||
else // Queue is empty if head->next is head itself.
|
||||
|
@ -55,19 +62,20 @@ U0 NetQueuePushCopy(U8 *data, I64 length)
|
|||
into the Net Queue. The NetQueueEntry is inserted
|
||||
after the last entry of net_queue to keep new
|
||||
items in the back of the Queue, old in front. */
|
||||
|
||||
CNetQueueEntry *entry = CAlloc(sizeof(CNetQueueEntry));
|
||||
|
||||
entry->length = length;
|
||||
|
||||
MemCopy(entry->frame, data, length);
|
||||
|
||||
QueueInsert(entry, net_queue->last);
|
||||
|
||||
//Set Net Handler Task active.
|
||||
ZenithLog("ACTIVE: NetHandler\n");
|
||||
ZenithLog("NETQUEUE PUSH COPY: Setting NetHandler ACTIVE.\n");
|
||||
if (net_handler_task)
|
||||
LBtr(&net_handler_task->task_flags, TASKf_IDLE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
NetQueueInit;
|
28
src/Home/Net/NetStart.CC
Executable file
28
src/Home/Net/NetStart.CC
Executable file
|
@ -0,0 +1,28 @@
|
|||
#include "C:/Home/Net/Net.HH"
|
||||
|
||||
#include "C:/Home/Net/NetQueue"
|
||||
#include "C:/Home/Net/PCNet"
|
||||
#include "C:/Home/Net/Ethernet"
|
||||
|
||||
#include "C:/Home/Net/ARP"
|
||||
#include "C:/Home/Net/IPV4"
|
||||
#include "C:/Home/Net/ICMP"
|
||||
|
||||
#include "C:/Home/Net/Sockets"
|
||||
|
||||
#include "C:/Home/Net/UDP"
|
||||
|
||||
#include "C:/Home/Net/DNS"
|
||||
#include "C:/Home/Net/DHCP"
|
||||
|
||||
#include "C:/Home/Net/NetHandlerTask" // needs IPV4, UDP, ICMP
|
||||
|
||||
|
||||
|
||||
XTalk(Fs, "NetConfigure;\n");
|
||||
|
||||
XTalk(Fs, "Host(\"zenithos.org\");\n");
|
||||
|
||||
XTalk(Fs, "DNSRep;\n");
|
||||
|
||||
XTalk(Fs, "ARPRep;\n");
|
|
@ -13,8 +13,8 @@
|
|||
- Clear documentation.
|
||||
*/
|
||||
|
||||
#include "Net.HH"
|
||||
#include "NetQueue"
|
||||
//#include "Net.HH"
|
||||
//#include "NetQueue"
|
||||
|
||||
#define PCNET_DEVICE_ID 0x2000
|
||||
#define PCNET_VENDOR_ID 0x1022
|
||||
|
@ -53,7 +53,9 @@
|
|||
#define PCNET_CSR_RXRINGLEN 76
|
||||
#define PCNET_CSR_TXRINGLEN 78
|
||||
|
||||
#define PCNET_SWSTYLE_SELECTION 2 // AMD PCNet datasheet p. 1-968
|
||||
#define PCNET_SWSTYLE_SELECTION 2 // (value, not bit) AMD PCNet datasheet p. 1-968
|
||||
|
||||
#define PCNET_SWSTYLE_SSIZE32 8 // Bit 8 of SWSTYLE
|
||||
|
||||
// Refer to AMD PCNet datasheet p. 1-954, 1-956, 1-957 for Interrupt Mask details.
|
||||
#define PCNET_INT_BSWP 2 // Byte Swap (Big-Endian / Little-Endian)
|
||||
|
@ -110,9 +112,21 @@ class CPCNetDescriptorEntry
|
|||
U32 reserved;
|
||||
};
|
||||
|
||||
class CPCNetBufferSetup
|
||||
{
|
||||
U16 mode;
|
||||
U8 rlen;
|
||||
U8 tlen;
|
||||
U8 mac[6];
|
||||
U16 reserved;
|
||||
U8 ladr[8];
|
||||
U32 rxbuf;
|
||||
U32 txbuf;
|
||||
};
|
||||
|
||||
CPCIDev *PCNetPCIDevFind()
|
||||
{// Find and return PCNetII card as a CPCIDev pointer.
|
||||
|
||||
return PCIDevFind(,, PCNET_VENDOR_ID, PCNET_DEVICE_ID);
|
||||
}
|
||||
|
||||
|
@ -121,6 +135,7 @@ U32 PCNetGetIOBase()
|
|||
of PCNet card. Bits 0-4 are not
|
||||
for the IO base, so an AND with
|
||||
~0x1F ignores those bits. */
|
||||
|
||||
U32 io_base = pcnet.pci->base[0] & ~0x1F;
|
||||
return io_base;
|
||||
}
|
||||
|
@ -129,8 +144,9 @@ U0 PCNetReset()
|
|||
{/* Reads the 32- and 16-bit RESET registers,
|
||||
which, regardless of which mode the card is in,
|
||||
will reset it back to 16-bit mode. */
|
||||
InU32(PCNetGetIOBase + PCNET_DW_RESET);
|
||||
InU16(PCNetGetIOBase + PCNET_WD_RESET);
|
||||
|
||||
InU32(PCNetGetIOBase() + PCNET_DW_RESET);
|
||||
InU16(PCNetGetIOBase() + PCNET_WD_RESET);
|
||||
Busy(5); // OSDev says minimum 1 æS
|
||||
}
|
||||
|
||||
|
@ -139,8 +155,8 @@ U0 PCNetEnter32BitMode()
|
|||
Summary: A 32-bit write (while in 16-bit mode)
|
||||
to RDP will cause 16-bit mode exit
|
||||
and immediate enter into 32-bit mode. */
|
||||
OutU32(PCNetGetIOBase + PCNET_DW_RDP, 0);
|
||||
|
||||
OutU32(PCNetGetIOBase() + PCNET_DW_RDP, 0);
|
||||
}
|
||||
|
||||
U0 PCNetWriteRAP(U32 value)
|
||||
|
@ -148,7 +164,8 @@ U0 PCNetWriteRAP(U32 value)
|
|||
Summary: Register Address Pointer register
|
||||
value will indicate which CSR / BCR register
|
||||
we want to access in RDP / BDP. */
|
||||
OutU32(PCNetGetIOBase + PCNET_DW_RAP, value);
|
||||
|
||||
OutU32(PCNetGetIOBase() + PCNET_DW_RAP, value);
|
||||
}
|
||||
|
||||
U0 PCNetWriteCSR(U32 csr, U32 value)
|
||||
|
@ -157,8 +174,9 @@ U0 PCNetWriteCSR(U32 csr, U32 value)
|
|||
accessed via the RDP (Register Data Port).
|
||||
Which CSR is selected is based on the value
|
||||
in the RAP. */
|
||||
|
||||
PCNetWriteRAP(csr);
|
||||
OutU32(PCNetGetIOBase + PCNET_DW_RDP, value);
|
||||
OutU32(PCNetGetIOBase() + PCNET_DW_RDP, value);
|
||||
}
|
||||
|
||||
U32 PCNetReadCSR(U32 csr)
|
||||
|
@ -167,8 +185,9 @@ U32 PCNetReadCSR(U32 csr)
|
|||
accessed via the RDP (Register Data Port).
|
||||
Which CSR is selected is based on the value
|
||||
in the RAP. */
|
||||
|
||||
PCNetWriteRAP(csr);
|
||||
return InU32(PCNetGetIOBase + PCNET_DW_RDP);
|
||||
return InU32(PCNetGetIOBase() + PCNET_DW_RDP);
|
||||
}
|
||||
|
||||
U0 PCNetSetSWStyle()
|
||||
|
@ -179,10 +198,13 @@ U0 PCNetSetSWStyle()
|
|||
initialization block. In PCINet-PCI mode, CSR4 bits
|
||||
function as defined in the datasheet , and TMD1[29]
|
||||
functions as ADD_FCS. */
|
||||
|
||||
U32 csr = PCNetReadCSR(PCNET_CSR_SOFTWARESTYLE);
|
||||
|
||||
csr &= ~0xFF; // clears first 8 bits: SWSTYLE 8-bit register.
|
||||
// csr &= ~0xFF; // clears first 8 bits: SWSTYLE 8-bit register.
|
||||
csr &= 0xFFF0;
|
||||
csr |= PCNET_SWSTYLE_SELECTION; // set SWSTYLE to PCNet-PCI mode.
|
||||
Bts(&csr, PCNET_SWSTYLE_SSIZE32); // set SSIZE32 bit 1
|
||||
|
||||
PCNetWriteCSR(PCNET_CSR_SOFTWARESTYLE, csr);
|
||||
}
|
||||
|
@ -192,11 +214,16 @@ U0 PCNetGetMAC()
|
|||
MAC address stored at first 6 bytes of PCNet EEPROM.
|
||||
EEPROM addresses shadow-copied to APROM at hardware init.
|
||||
APROM accessible at first 16 bytes of PCI IO space. */
|
||||
|
||||
I64 i;
|
||||
ZenithLog("PCNET GET MAC: Getting VM MAC.\n");
|
||||
ZenithLog(" ");
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
pcnet.mac_address[i] = InU8(PCNetGetIOBase + i);
|
||||
pcnet.mac_address[i] = InU8(PCNetGetIOBase() + i);
|
||||
ZenithLog(" %02X", pcnet.mac_address[i]);
|
||||
}
|
||||
ZenithLog("\n");
|
||||
}
|
||||
|
||||
U0 PCNetInitDescriptorEntry(CPCNetDescriptorEntry *entry, U32 buffer_address, I64 is_rx)
|
||||
|
@ -208,6 +235,7 @@ U0 PCNetInitDescriptorEntry(CPCNetDescriptorEntry *entry, U32 buffer_address, I6
|
|||
12 bits of 2s-complement of desired length.
|
||||
Bits 0-11 of a DE are for the buffer byte count (BCNT),
|
||||
and bits 12-15 of a DE must be written all ones (ONES) */
|
||||
|
||||
U16 buffer_byte_count = -ETHERNET_FRAME_SIZE; // Sets up as 2s complement of the desired length.
|
||||
buffer_byte_count &= 0x0FFF; // Masks 0 over everything except bits 0-11.
|
||||
|
||||
|
@ -217,8 +245,8 @@ U0 PCNetInitDescriptorEntry(CPCNetDescriptorEntry *entry, U32 buffer_address, I6
|
|||
//if this is a Receive DE, give ownership to the card so the PCNet can fill them.
|
||||
if (is_rx)
|
||||
Bts(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
||||
ClassRep(entry);
|
||||
|
||||
// ClassRep(entry);
|
||||
}
|
||||
|
||||
U0 PCNetAllocateBuffers()
|
||||
|
@ -228,6 +256,7 @@ U0 PCNetAllocateBuffers()
|
|||
/* AMD PCNet datasheet p.1-913, p.1-990
|
||||
When SSIZE32=1, Descriptor Ring Entry Base Address
|
||||
must be on 16-byte boundary. (TDRA[3:0]=0, RDRA[3:0]=0) */
|
||||
|
||||
pcnet.rx_de_buffer_phys = CAllocAligned(sizeof(CPCNetDescriptorEntry) * PCNET_RX_BUFF_COUNT,
|
||||
16,
|
||||
Fs->code_heap);
|
||||
|
@ -253,17 +282,23 @@ U0 PCNetAllocateBuffers()
|
|||
CPCNetDescriptorEntry *entry = pcnet.rx_de_buffer;
|
||||
for (de_index = 0; de_index < PCNET_RX_BUFF_COUNT; de_index++)
|
||||
{
|
||||
PCNetInitDescriptorEntry(&entry[de_index], pcnet.rx_buffer_addr, TRUE); // TRUE for is_rx.
|
||||
//PCNetInitDescriptorEntry(&entry[de_index], pcnet.rx_buffer_addr, TRUE); // TRUE for is_rx.
|
||||
PCNetInitDescriptorEntry(&entry[de_index],
|
||||
pcnet.rx_buffer_addr + de_index * ETHERNET_FRAME_SIZE,
|
||||
TRUE); // TRUE for is_rx.
|
||||
}
|
||||
|
||||
entry = pcnet.tx_de_buffer;
|
||||
for (de_index = 0; de_index < PCNET_TX_BUFF_COUNT; de_index++)
|
||||
{
|
||||
PCNetInitDescriptorEntry(&entry[de_index], pcnet.tx_buffer_addr, FALSE); // FALSE for is_rx.
|
||||
}
|
||||
|
||||
//PCNetInitDescriptorEntry(&entry[de_index], pcnet.tx_buffer_addr, FALSE); // FALSE for is_rx.
|
||||
PCNetInitDescriptorEntry(&entry[de_index],
|
||||
pcnet.tx_buffer_addr + de_index * ETHERNET_FRAME_SIZE,
|
||||
FALSE); // FALSE for is_rx.
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
U0 PCNetDirectInit()
|
||||
{/* AMD PCNet datasheet p. 1-1021
|
||||
Instead of setting up initialization block,
|
||||
|
@ -288,8 +323,11 @@ U0 PCNetDirectInit()
|
|||
The OR and bit-shift of 8 allows writing
|
||||
separate U8 values in the correct locations
|
||||
of the CSR. */
|
||||
ZenithLog("PCNetDirectInit: Write MAC to CSR: 0x%X \n", pcnet.mac_address[0] | (pcnet.mac_address[1] << 8));
|
||||
PCNetWriteCSR(PCNET_CSR_PADR0, pcnet.mac_address[0] | (pcnet.mac_address[1] << 8));
|
||||
ZenithLog("PCNetDirectInit: Write MAC to CSR: 0x%X \n", pcnet.mac_address[2] | (pcnet.mac_address[3] << 8));
|
||||
PCNetWriteCSR(PCNET_CSR_PADR1, pcnet.mac_address[2] | (pcnet.mac_address[3] << 8));
|
||||
ZenithLog("PCNetDirectInit: Write MAC to CSR: 0x%X \n", pcnet.mac_address[4] | (pcnet.mac_address[5] << 8));
|
||||
PCNetWriteCSR(PCNET_CSR_PADR2, pcnet.mac_address[4] | (pcnet.mac_address[5] << 8));
|
||||
|
||||
/* AMD PCNet datasheet p.1-961, 1-962, 1-963
|
||||
|
@ -333,8 +371,29 @@ U0 PCNetDirectInit()
|
|||
as zeroes read undefined. */
|
||||
PCNetWriteCSR(PCNET_CSR_RXRINGLEN, -PCNET_RX_BUFF_COUNT & 0xFFFF);
|
||||
PCNetWriteCSR(PCNET_CSR_TXRINGLEN, -PCNET_TX_BUFF_COUNT & 0xFFFF);
|
||||
}
|
||||
*/
|
||||
|
||||
U8 *PCNetInitBlockSetup()
|
||||
{
|
||||
U8 *setup = CAlloc(sizeof(CPCNetBufferSetup), Fs->code_heap);
|
||||
CPCNetBufferSetup *u_setup = setup + dev.uncached_alias;
|
||||
U32 p_setup;
|
||||
|
||||
u_setup->mode = 0;
|
||||
u_setup->rlen = 5 << 4;
|
||||
u_setup->tlen = 3 << 4;
|
||||
MemCopy(u_setup->mac, pcnet.mac_address, 6);
|
||||
u_setup->reserved = 0;
|
||||
MemSet(u_setup->ladr, 0, 8);
|
||||
u_setup->rxbuf = pcnet.rx_de_buffer_phys;
|
||||
u_setup->txbuf = pcnet.tx_de_buffer_phys;
|
||||
|
||||
p_setup = setup;
|
||||
PCNetWriteCSR(1, p_setup & 0xFFFF);
|
||||
PCNetWriteCSR(2, p_setup >> 16);
|
||||
|
||||
return setup;
|
||||
}
|
||||
|
||||
U0 PCNetSetInterruptCSR()
|
||||
|
@ -344,6 +403,7 @@ U0 PCNetSetInterruptCSR()
|
|||
We set Big-Endian disabled, RX interrupts
|
||||
enabled, Init Done interrupt disabled, and TX interrupt
|
||||
disabled. */
|
||||
|
||||
U32 csr = PCNetReadCSR(PCNET_CSR_INTERRUPTS);
|
||||
|
||||
Btr(&csr, PCNET_INT_BSWP);
|
||||
|
@ -360,12 +420,12 @@ U0 PCNetEnableTXAutoPad()
|
|||
Setting bit 11 (Auto Pad Transmit) allows
|
||||
shoft transmit frames to be automatically
|
||||
extended to 64 bytes. */
|
||||
|
||||
U32 csr = PCNetReadCSR(PCNET_CSR_FEATURECTRL);
|
||||
|
||||
Bts(&csr, PCNET_FEATURE_APADXMT);
|
||||
|
||||
PCNetWriteCSR(PCNET_CSR_FEATURECTRL, csr);
|
||||
|
||||
}
|
||||
|
||||
U0 PCNetExitConfigMode()
|
||||
|
@ -375,6 +435,7 @@ U0 PCNetExitConfigMode()
|
|||
and STOP are cleared and START bit
|
||||
is set, in Status and Control Register
|
||||
(CSR0). */
|
||||
|
||||
U32 csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS);
|
||||
|
||||
Btr(&csr, PCNET_CTRL_INIT);
|
||||
|
@ -382,14 +443,15 @@ U0 PCNetExitConfigMode()
|
|||
|
||||
Bts(&csr, PCNET_CTRL_STRT);
|
||||
|
||||
PCNetWriteCSR(PCNET_CSR_CTRLSTATUS, csr);
|
||||
}
|
||||
|
||||
I64 PCNetDriverOwns(CPCNetDescriptorEntry* entry)
|
||||
{/* Returns whether the value of the OWN bit of the
|
||||
Descriptor Entry is zero. If 0, driver owns,
|
||||
if 1, PCNet card owns it. */
|
||||
return !Bt(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
||||
|
||||
return !Bt(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
||||
}
|
||||
|
||||
I64 PCNetAllocateTransmitPacket(U8 **packet_buffer_out, I64 length)
|
||||
|
@ -405,18 +467,22 @@ I64 PCNetAllocateTransmitPacket(U8 **packet_buffer_out, I64 length)
|
|||
|
||||
if (length > 0xFFF)
|
||||
{ // Max packet length must fit into BCNT 12-bit register.
|
||||
ZenithErr("Invalid TX Packet Length");
|
||||
ZenithErr("PCNET ALLOCATE TX PACKET: Invalid TX Packet Length\n");
|
||||
throw('PCNet');
|
||||
}
|
||||
|
||||
|
||||
CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index];
|
||||
// CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index];
|
||||
CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index * sizeof(CPCNetDescriptorEntry)];
|
||||
|
||||
if (!PCNetDriverOwns(entry))
|
||||
{
|
||||
ZenithErr("TX FIFO Full");
|
||||
ZenithErr("PCNET ALLOCATE TX PACKET: TX FIFO Full\n");
|
||||
return -1; // Positive value expected. Functions calling this must factor this in.
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithLog("PCNET ALLOCATE TX PACKET: Driver owns TX DE at index %d.\n", de_index);
|
||||
}
|
||||
|
||||
Bts(&entry->status1, PCNET_DESCRIPTORf_STP);
|
||||
|
||||
|
@ -437,16 +503,21 @@ I64 PCNetAllocateTransmitPacket(U8 **packet_buffer_out, I64 length)
|
|||
|
||||
*packet_buffer_out = pcnet.tx_buffer_addr + (de_index * ETHERNET_FRAME_SIZE);
|
||||
|
||||
ZenithLog("PCNET ALLOCATE TX PACKET: de_index: %X.\n", de_index);
|
||||
return de_index;
|
||||
|
||||
}
|
||||
|
||||
U0 PCNetFinishTransmitPacket(I64 de_index)
|
||||
{/* Release ownership of the packet to the PCNet card
|
||||
by setting the OWN bit to 1. */
|
||||
CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index];
|
||||
|
||||
// CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index];
|
||||
CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index * sizeof(CPCNetDescriptorEntry)];
|
||||
|
||||
Bts(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
||||
ZenithLog("PCNet FINISH TX PACKET: TX DE index: %X, OWN bit of entry at entry: %b.\n",
|
||||
de_index, Bt(&entry->status1, PCNET_DESCRIPTORf_OWN));
|
||||
// CallerRep;
|
||||
|
||||
}
|
||||
|
||||
|
@ -465,10 +536,12 @@ I64 PCNetReceivePacket(U8 **packet_buffer_out, U16 *packet_length_out)
|
|||
The increment of the current RX DE index is done by assigning it the
|
||||
value of incrementing it AND the max DE index-1. This will increment it
|
||||
as well as wrap back to 0 if we hit the max DE index. */
|
||||
ZenithErr("PCNet received packet. %X , %X",packet_buffer_out,packet_length_out);
|
||||
|
||||
ZenithLog("PCNET RECEIVE PACKET: PCNet received packet. %X , %X \n", packet_buffer_out, packet_length_out);
|
||||
I64 de_index = pcnet.current_rx_de_index;
|
||||
|
||||
CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index];
|
||||
// CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index];
|
||||
CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index * sizeof(CPCNetDescriptorEntry)];
|
||||
|
||||
U16 packet_length = entry->status2 & 0xFFFF;
|
||||
|
||||
|
@ -477,15 +550,16 @@ I64 PCNetReceivePacket(U8 **packet_buffer_out, U16 *packet_length_out)
|
|||
|
||||
*packet_buffer_out = pcnet.rx_buffer_addr + (de_index * ETHERNET_FRAME_SIZE);
|
||||
*packet_length_out = packet_length;
|
||||
|
||||
return de_index;
|
||||
|
||||
|
||||
}
|
||||
|
||||
U0 PCNetReleaseReceivePacket(I64 de_index)
|
||||
{/* Release ownership of the packet to the PCNet card
|
||||
by setting the OWN bit to 1. */
|
||||
CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index];
|
||||
|
||||
// CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index];
|
||||
CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index * sizeof(CPCNetDescriptorEntry)];
|
||||
|
||||
Bts(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
||||
}
|
||||
|
@ -498,18 +572,19 @@ interrupt U0 PCNetIRQ()
|
|||
I64 de_index;
|
||||
|
||||
U32 csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS);
|
||||
//"Interrupt Reason: %X , %b\n",csr,csr;
|
||||
// "Interrupt Reason: %X , %b\n",csr,csr;Debug;
|
||||
|
||||
CPCNetDescriptorEntry *entry = pcnet.rx_de_buffer;
|
||||
|
||||
while (PCNetDriverOwns(&entry[pcnet.current_rx_de_index]))
|
||||
{
|
||||
"%X", pcnet.current_rx_de_index;
|
||||
ZenithLog("PCNET IRQ: Saw owned RX DE index %d.\n", pcnet.current_rx_de_index);
|
||||
|
||||
de_index = PCNetReceivePacket(&packet_buffer, &packet_length);
|
||||
|
||||
if (de_index >= 0) // necessary? check increment logic in PCNetReceivePacket.
|
||||
{
|
||||
ZenithErr("Pushing copy into Net Queue, Releasing Receive Packet");
|
||||
ZenithLog("PCNET IRQ: Pushing copy into Net Queue, Releasing Receive Packet\n");
|
||||
NetQueuePushCopy(packet_buffer, packet_length);
|
||||
PCNetReleaseReceivePacket(de_index);
|
||||
}
|
||||
|
@ -567,6 +642,13 @@ U0 PCNetInit()
|
|||
|
||||
PCNetEnter32BitMode;
|
||||
|
||||
U32 csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS);
|
||||
ZenithLog("PCNET INIT START: what is INIT ?: %d\n", Bt(&csr, PCNET_CTRL_INIT));
|
||||
ZenithLog("PCNET INIT START: what is STRT ?: %d\n", Bt(&csr, PCNET_CTRL_STRT));
|
||||
ZenithLog("PCNET INIT START: what is STOP ?: %d\n", Bt(&csr, PCNET_CTRL_STOP));
|
||||
ZenithLog("PCNET INIT START: what is RINT ?: %d\n", Bt(&csr, PCNET_CTRL_RINT));
|
||||
|
||||
|
||||
PCNetSetSWStyle;
|
||||
|
||||
PCNetGetMAC;
|
||||
|
@ -574,26 +656,49 @@ U0 PCNetInit()
|
|||
|
||||
PCNetAllocateBuffers;
|
||||
|
||||
PCNetDirectInit;
|
||||
// PCNetDirectInit;
|
||||
U8 *setup = PCNetInitBlockSetup();
|
||||
|
||||
PCNetSetInterruptCSR;
|
||||
|
||||
PCNetEnableTXAutoPad;
|
||||
|
||||
PCNetWriteCSR(0, PCNetReadCSR(0) | 1 | (1<<6));
|
||||
// Bt(&(csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS)), 8);
|
||||
csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS);
|
||||
ZenithLog("PCNET INIT UPLOAD: what is INIT ?: %d\n", Bt(&csr, PCNET_CTRL_INIT));
|
||||
ZenithLog("PCNET INIT UPLOAD: what is STRT ?: %d\n", Bt(&csr, PCNET_CTRL_STRT));
|
||||
ZenithLog("PCNET INIT UPLOAD: what is STOP ?: %d\n", Bt(&csr, PCNET_CTRL_STOP));
|
||||
ZenithLog("PCNET INIT UPLOAD: what is RINT ?: %d\n", Bt(&csr, PCNET_CTRL_RINT));
|
||||
|
||||
while (!(PCNetReadCSR(0) & (1<<8)))
|
||||
Yield;
|
||||
|
||||
PCNetExitConfigMode;
|
||||
|
||||
PCNetSetupInterrupts;
|
||||
|
||||
|
||||
Sleep(100);//? necessary?
|
||||
ClassRep(&pcnet);
|
||||
/* ClassRep(&pcnet);
|
||||
|
||||
"pcnet->rx_de_buffer: %X\n", pcnet.rx_de_buffer;
|
||||
"pcnet->tx_de_buffer: %X\n", pcnet.tx_de_buffer;
|
||||
"pcnet->rx_de_buffer_phys: %X\n", pcnet.rx_de_buffer_phys;
|
||||
"pcnet->rx_de_buffer_phys: %X\n", pcnet.tx_de_buffer_phys;
|
||||
*/
|
||||
csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS);
|
||||
ZenithLog("PCNET INIT END: what is INIT ?: %d\n", Bt(&csr, PCNET_CTRL_INIT));
|
||||
ZenithLog("PCNET INIT END: what is STRT ?: %d\n", Bt(&csr, PCNET_CTRL_STRT));
|
||||
ZenithLog("PCNET INIT END: what is STOP ?: %d\n", Bt(&csr, PCNET_CTRL_STOP));
|
||||
ZenithLog("PCNET INIT END: what is RINT ?: %d\n", Bt(&csr, PCNET_CTRL_RINT));
|
||||
ZenithLog("PCNET INIT END: what is TXON ?: %d\n", Bt(&csr, 4));
|
||||
ZenithLog("PCNET INIT END: what is RXON ?: %d\n", Bt(&csr, 5));
|
||||
|
||||
csr = PCNetReadCSR(PCNET_CSR_POLLINT);
|
||||
ZenithLog("PCNET INIT END: what is POLLINT ?: %d\n", Bt(&csr, PCNET_CTRL_RINT));
|
||||
|
||||
Free(setup);
|
||||
}
|
||||
|
||||
I64 EthernetFrameAllocate(U8 **packet_buffer_out,
|
||||
|
@ -613,20 +718,23 @@ I64 EthernetFrameAllocate(U8 **packet_buffer_out,
|
|||
|
||||
//need to see if 3 years later VirtualBox supports APAD_XMT!
|
||||
if (packet_length < ETHERNET_MIN_FRAME_SIZE)
|
||||
{
|
||||
ZenithWarn("ETHERNET FRAME ALLOCATE: PCNET APAD XMT TRUNCATE ? ...\n");
|
||||
packet_length = ETHERNET_MIN_FRAME_SIZE;
|
||||
}
|
||||
|
||||
de_index = PCNetAllocateTransmitPacket(ðernet_frame, ETHERNET_MAC_HEADER_LENGTH + packet_length);
|
||||
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithErr("Ethernet Frame Allocate failure");
|
||||
ZenithErr("ETHERNET FRAME ALLOCATE: Failure\n");
|
||||
return -1; // Positive value expected. Functions calling this must factor this in.
|
||||
}
|
||||
|
||||
MemCopy(ethernet_frame, destination_address, MAC_ADDRESS_LENGTH);
|
||||
MemCopy(ethernet_frame + MAC_ADDRESS_LENGTH, source_address, MAC_ADDRESS_LENGTH);
|
||||
|
||||
ethernet_frame[ETHERNET_ETHERTYPE_OFFSET] = ethertype << 8;
|
||||
ethernet_frame[ETHERNET_ETHERTYPE_OFFSET] = ethertype >> 8; // << or >> ? Shrine has >>
|
||||
ethernet_frame[ETHERNET_ETHERTYPE_OFFSET + 1] = ethertype & 0xFF;
|
||||
|
||||
*packet_buffer_out = ethernet_frame + ETHERNET_MAC_HEADER_LENGTH;
|
||||
|
@ -639,5 +747,5 @@ U8 *EthernetGetMAC()
|
|||
return pcnet.mac_address;
|
||||
}
|
||||
|
||||
PCNetInit;
|
||||
|
||||
PCNetInit;
|
|
@ -35,6 +35,8 @@
|
|||
#define AF_INET 2
|
||||
#define AF_INET6 10
|
||||
|
||||
#define INADDR_ANY 0
|
||||
|
||||
#define INET_ADDRSTRLEN 16 //pubs.opengroup.com netinit/in.h
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
|
||||
|
@ -70,7 +72,8 @@ class CIPAddressStorage
|
|||
|
||||
class CSocketAddressIPV4
|
||||
{
|
||||
I16 family; // 'AF_INET'
|
||||
// I16 family; // 'AF_INET'
|
||||
U16 family; // 'AF_INET'
|
||||
U16 port; // 'in Network Byte order' ... Big Endian
|
||||
CIPV4Address address;
|
||||
U8 zeroes[8]; // 'same size as socket address'
|
||||
|
@ -130,6 +133,22 @@ U0 AddressInfoCopy(CAddressInfo *out, CAddressInfo *in)
|
|||
}
|
||||
}
|
||||
|
||||
U0 AddressInfoFree(CAddressInfo *info)
|
||||
{
|
||||
CAddressInfo *next;
|
||||
|
||||
while (info)
|
||||
{
|
||||
next = info->next;
|
||||
|
||||
Free(info->address);
|
||||
Free(info->canonical_name);
|
||||
Free(info);
|
||||
|
||||
info = next;
|
||||
}
|
||||
}
|
||||
|
||||
Bool IPV4AddressParse(U8 *string, U32 *destination)
|
||||
{
|
||||
// U8* lexable_string;
|
||||
|
@ -159,12 +178,12 @@ Bool IPV4AddressParse(U8 *string, U32 *destination)
|
|||
case TK_I64:
|
||||
if (cc->cur_i64 > 255 || cc->cur_i64 < 0)
|
||||
{
|
||||
ZenithErr("Invalid value, must be 0 - 255.\n");
|
||||
ZenithErr("IPV4 ADDRESS PARSE: Invalid value, must be 0 - 255.\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (current_section > 3)
|
||||
{
|
||||
ZenithErr("IP Address can only have 4 sections.\n");
|
||||
ZenithErr("IPV4 ADDRESS PARSE: IP Address can only have 4 sections.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -176,7 +195,7 @@ Bool IPV4AddressParse(U8 *string, U32 *destination)
|
|||
break;
|
||||
|
||||
default:
|
||||
ZenithErr("Expected decimal. \n");
|
||||
ZenithErr("IPV4 ADDRESS PARSE: Expected decimal. \n");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -189,7 +208,7 @@ Bool IPV4AddressParse(U8 *string, U32 *destination)
|
|||
break;
|
||||
|
||||
default:
|
||||
ZenithErr("Expected dot. \n");
|
||||
ZenithErr("IPV4 ADDRESS PARSE: Expected dot. \n");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
@ -275,11 +294,17 @@ U8 *NetworkToPresentation(I64 address_family, CIPAddressStorage *source)
|
|||
|
||||
ipv4_source = source;
|
||||
|
||||
StrPrint(ip_string, "%d.%d.%d.%d",
|
||||
/* StrPrint(ip_string, "%d.%d.%d.%d",
|
||||
ipv4_source->address.u8[3],
|
||||
ipv4_source->address.u8[2],
|
||||
ipv4_source->address.u8[1],
|
||||
ipv4_source->address.u8[0]);
|
||||
ipv4_source->address.u8[0]);*/
|
||||
|
||||
StrPrint(ip_string, "%d.%d.%d.%d",
|
||||
ipv4_source->address.u8[0],
|
||||
ipv4_source->address.u8[1],
|
||||
ipv4_source->address.u8[2],
|
||||
ipv4_source->address.u8[3]);
|
||||
break;
|
||||
case AF_INET6:
|
||||
|
||||
|
|
4
src/Home/Net/Tests/DHCPTest1.CC
Executable file
4
src/Home/Net/Tests/DHCPTest1.CC
Executable file
|
@ -0,0 +1,4 @@
|
|||
#include "C:/Home/Net/DHCP"
|
||||
#include "C:/Home/Net/NetHandlerTask"
|
||||
|
||||
NetConfigure;
|
16
src/Home/Net/Tests/DNSTest1.CC
Executable file
16
src/Home/Net/Tests/DNSTest1.CC
Executable file
|
@ -0,0 +1,16 @@
|
|||
|
||||
#include "../DNS"
|
||||
#include "../NetHandlerTask"
|
||||
|
||||
/*
|
||||
"Manually setting DNS Resolver IP.\n";
|
||||
|
||||
CIPV4Address *addr = CAlloc(sizeof(CIPV4Address));
|
||||
PresentationToNetwork(AF_INET, "192.168.1.254", addr);
|
||||
|
||||
DNSSetResolverIPV4(addr->address);
|
||||
*/
|
||||
"Trying Host() at \"google.com\".\n";
|
||||
Host("google.com");
|
||||
|
||||
Free(addr);
|
33
src/Home/Net/Tests/MakeBreakDown.CC
Executable file
33
src/Home/Net/Tests/MakeBreakDown.CC
Executable file
|
@ -0,0 +1,33 @@
|
|||
#include "C:/Home/Net/Net.HH"
|
||||
|
||||
#include "C:/Home/Net/NetQueue"
|
||||
#include "C:/Home/Net/PCNet"
|
||||
#include "C:/Home/Net/Ethernet"
|
||||
|
||||
Sleep(300);
|
||||
|
||||
#include "C:/Home/Net/ARP"
|
||||
#include "C:/Home/Net/IPV4"
|
||||
#include "C:/Home/Net/ICMP"
|
||||
|
||||
#include "C:/Home/Net/Sockets"
|
||||
|
||||
#include "C:/Home/Net/UDP"
|
||||
|
||||
#include "C:/Home/Net/DNS"
|
||||
#include "C:/Home/Net/DHCP"
|
||||
|
||||
|
||||
Sleep(300);
|
||||
|
||||
#include "C:/Home/Net/NetHandlerTask" // needs IPV4, UDP, ICMP
|
||||
|
||||
NetConfigure;
|
||||
|
||||
//ClassRep(&pcnet);
|
||||
Sleep(1000);
|
||||
|
||||
XTalk(Fs, "Host(\"google.com\");\n");
|
||||
|
||||
Dir;
|
||||
|
21
src/Home/Net/Tests/UDPSendTrash.CC
Executable file
21
src/Home/Net/Tests/UDPSendTrash.CC
Executable file
|
@ -0,0 +1,21 @@
|
|||
CAddressInfo *result = NULL;
|
||||
I64 error = DNSGetAddressInfo("zenithos.org", NULL, &result);
|
||||
I64 i = 0;
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("failed at DNS Get Address Info.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
CUDPSocket *u = UDPSocket(AF_INET);
|
||||
CSocketAddressIPV4 *ipv4_addr = result->address;
|
||||
|
||||
ipv4_addr->port = EndianU16(80);
|
||||
U8 *b = CAlloc(4);
|
||||
b[0] = 0xDE;
|
||||
b[1] = 0xAD;
|
||||
b[2] = 0xBE;
|
||||
b[3] = 0xEF;
|
||||
UDPSocketSendTo(u, b, 4, ipv4_addr);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
//#include "IPV4"
|
||||
#include "ICMP" // this is wrong and only doing this because we're just in dev right now. probably need approach like Shrine, MakeNet, idk.
|
||||
#include "Sockets"
|
||||
//#include "ICMP" // this is wrong and only doing this because we're just in dev right now. probably need approach like Shrine, MakeNet, idk.
|
||||
//#include "Sockets"
|
||||
|
||||
#define UDP_MAX_PORT 65535
|
||||
|
||||
|
@ -21,6 +21,9 @@ class CUDPSocket
|
|||
I64 receive_len;
|
||||
CSocketAddressStorage receive_address; // based on ->family, cast or assign to a var as IPV4/IPV6 CSocketAddress
|
||||
U16 bound_to; // represents the currently bound port
|
||||
|
||||
CSocketAddressStorage from_address; // when UDP Handler sees UDP packet, this is filled with where the packet came from.
|
||||
// recvfrom uses this to fill its address_out parameter.
|
||||
};
|
||||
|
||||
/***************************************************
|
||||
|
@ -237,34 +240,35 @@ CUDPTreeQueue *UDPTreeNodeQueueSocketFind(CUDPSocket *socket, CUDPTreeNode *node
|
|||
|
||||
CUDPTreeQueue *UDPTreeNodeQueueIPV4Find(U32 address, CUDPTreeNode *node)
|
||||
{ // address should be pulled from an instance of CIPV4Address (TODO... double check what bit order we're in ?)
|
||||
// TODO: should INADDR_ANY entries be stored and looped, or keep current returning ASAP at INNADDR_ANY ?
|
||||
|
||||
CUDPTreeQueue *temp_queue;
|
||||
CUDPTreeQueue *temp_queue = node->queue;
|
||||
CSocketAddressIPV4 *temp_ip;
|
||||
|
||||
if (node->queue)
|
||||
if (temp_queue)
|
||||
{
|
||||
if (node->queue->socket->receive_address.family == AF_INET)
|
||||
{
|
||||
temp_ip = &node->queue->socket->receive_address;
|
||||
if (temp_ip->address == address)
|
||||
return node->queue;
|
||||
}
|
||||
|
||||
temp_queue = node->queue->next;
|
||||
while (temp_queue != node->queue)
|
||||
do
|
||||
{
|
||||
if (temp_queue->socket->receive_address.family == AF_INET)
|
||||
{
|
||||
temp_ip = &temp_queue->socket->receive_address;
|
||||
if (temp_ip->address == address)
|
||||
ZenithLog("UDPTreeNodeQueueIPV4Find: addr, nodequeue addr: %08X, %08X\n",
|
||||
address, temp_ip->address.address);
|
||||
|
||||
if (temp_ip->address.address == address || temp_ip->address.address == INADDR_ANY)
|
||||
{
|
||||
ZenithLog("UDPTreeNodeQueueIPV4Find: Address match: addr, nodequeue: %08X, %08X \n",
|
||||
address, temp_ip->address.address);
|
||||
return temp_queue;
|
||||
}
|
||||
}
|
||||
|
||||
temp_queue = temp_queue->next;
|
||||
}
|
||||
while (temp_queue != node->queue);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CUDPTreeQueue *UDPTreeNodeQueueSocketSinglePop(CUDPSocket *socket, CUDPTreeNode *node)
|
||||
|
@ -342,7 +346,7 @@ I64 UDPPacketAllocate(U8 **frame_out,
|
|||
sizeof(CUDPHeader) + length);
|
||||
if (de_index < 0)
|
||||
{
|
||||
ZenithLog("UDP Ethernet Frame Allocate failed.\n");
|
||||
ZenithLog("UDP PACKET ALLOCATE: Ethernet Frame Allocate failed.\n");
|
||||
return de_index;
|
||||
}
|
||||
|
||||
|
@ -353,8 +357,11 @@ I64 UDPPacketAllocate(U8 **frame_out,
|
|||
header->length = EndianU16(sizeof(CUDPHeader) + length);
|
||||
header->checksum = 0;
|
||||
|
||||
// ClassRep(header);
|
||||
|
||||
*frame_out = ethernet_frame + sizeof(CUDPHeader);
|
||||
|
||||
return de_index;
|
||||
}
|
||||
|
||||
U0 UDPPacketFinish(I64 de_index)
|
||||
|
@ -414,13 +421,13 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
break;
|
||||
|
||||
default:
|
||||
ZenithErr("Unsuccessful UDP Socket Bind: Socket state-machine must be in READY state.\n");
|
||||
ZenithErr("UDP SOCKET BIND: Failed, Socket state-machine must be in READY state.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (udp_socket->bound_to)
|
||||
{
|
||||
ZenithErr("Attempted UDP Socket Bind while UDP socket currently bound.");
|
||||
ZenithErr("UDP SOCKET BIND: UDP Socket currently Bound.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -430,7 +437,7 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
|
||||
if (udp_socket->receive_address.family == AF_INET6)
|
||||
{
|
||||
ZenithErr("Attempted UDP Socket Bind with incompatible Address type.\n");
|
||||
ZenithErr("UDP SOCKET BIND: Incompatible Address type.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -448,7 +455,7 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
|
||||
if (udp_socket->receive_address.family == AF_INET)
|
||||
{
|
||||
ZenithErr("Attempted UDP Socket Bind with incompatible Address type.\n");
|
||||
ZenithErr("UDP SOCKET BIND: Incompatible Address type.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -464,7 +471,7 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
break;
|
||||
|
||||
case AF_UNSPEC:
|
||||
Debug("TODO: AF_UNSPEC UDP BIND");
|
||||
Debug("TODO: AF_UNSPEC UDP BIND -- param family");
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -481,9 +488,10 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
switch (address_source->family)
|
||||
{
|
||||
case AF_INET:
|
||||
// TODO: will any INADDR_ANY sockets bound at the port break this?
|
||||
if (UDPTreeNodeQueueIPV4Find(ipv4_receive->address.address, temp_node))
|
||||
{
|
||||
ZenithErr("Attempted UDP Socket Bind at an address already in Bound Socket Tree !\n");
|
||||
ZenithErr("UDP SOCKET BIND: Address already in Bound Socket Tree !\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
|
@ -496,7 +504,7 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
break;
|
||||
|
||||
case AF_UNSPEC:
|
||||
Debug("TODO: AF_UNSPEC UDP BIND");
|
||||
Debug("TODO: AF_UNSPEC UDP BIND -- found in bound tree");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -524,7 +532,7 @@ I64 UDPSocketBind(CUDPSocket *udp_socket, CSocketAddressStorage *address_source)
|
|||
break;
|
||||
|
||||
default:
|
||||
ZenithErr("Unsuccessful UDP Socket Bind: Misconfigured Socket state-machine.\n");
|
||||
ZenithErr("UDP SOCKET BIND: Failed, Misconfigured Socket state-machine.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -585,7 +593,7 @@ I64 UDPSocketReceiveFrom(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAdd
|
|||
break;
|
||||
|
||||
default:
|
||||
ZenithErr("Unsuccessful UDP Socket Receive From: Socket state-machine must be in OPEN or BOUND state.\n");
|
||||
ZenithErr("UDP SOCKET RECEIVE FROM: Socket state-machine must be in OPEN or BOUND state.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -595,11 +603,14 @@ I64 UDPSocketReceiveFrom(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAdd
|
|||
if (udp_socket->receive_timeout_ms != 0)
|
||||
udp_socket->receive_max_timeout = counts.jiffies + udp_socket->receive_timeout_ms * JIFFY_FREQ / 1000;
|
||||
|
||||
// ClassRep(udp_socket);
|
||||
ZenithLog("UDP SOCKET RECEIVE FROM: udp_socket->receive_buffer: 0x%0X.\n", udp_socket->receive_buffer);
|
||||
while (udp_socket->receive_buffer != NULL)
|
||||
{ // 'Check for timeout'
|
||||
if (udp_socket->receive_timeout_ms != 0 && counts.jiffies > udp_socket->receive_max_timeout)
|
||||
{ // Shrine has TODO: 'seterror(EWOULDBLOCK)' investigate this
|
||||
udp_socket->receive_len = -1; // ?
|
||||
ZenithErr("UDP SOCKET RECEIVE FROM: Timed out.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -608,15 +619,18 @@ I64 UDPSocketReceiveFrom(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAdd
|
|||
|
||||
if (address_out)
|
||||
{
|
||||
switch (udp_socket->receive_address.family)
|
||||
// switch (udp_socket->receive_address.family)
|
||||
switch (udp_socket->from_address.family)
|
||||
{
|
||||
case AF_INET:
|
||||
ipv4_socket_addr = address_out;
|
||||
MemCopy(ipv4_socket_addr, &udp_socket->receive_address, sizeof(CSocketAddressIPV4));
|
||||
// MemCopy(ipv4_socket_addr, &udp_socket->receive_address, sizeof(CSocketAddressIPV4));
|
||||
MemCopy(ipv4_socket_addr, &udp_socket->from_address, sizeof(CSocketAddressIPV4));
|
||||
break;
|
||||
case AF_INET6:
|
||||
ipv6_socket_addr = address_out;
|
||||
MemCopy(ipv6_socket_addr, &udp_socket->receive_address, sizeof(CSocketAddressIPV6));
|
||||
// MemCopy(ipv6_socket_addr, &udp_socket->receive_address, sizeof(CSocketAddressIPV6));
|
||||
MemCopy(ipv6_socket_addr, &udp_socket->from_address, sizeof(CSocketAddressIPV6));
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
Debug("TODO: UDP Receive From Error AF_UNSPEC UDPSocket Address Family\n");
|
||||
|
@ -645,13 +659,13 @@ I64 UDPSocketSendTo(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAddressS
|
|||
break; // and use stored address as send address.
|
||||
|
||||
case SOCKET_STATE_READY: // If socket state is initial, attempt to bind it to destination.
|
||||
ZenithLog("UDP Socket Send To but Socket unbound. Attempting Bind at address parameter.\n");
|
||||
ZenithLog("UDP SOCKET SEND TO: Socket unbound. Attempting Bind at address parameter.\n");
|
||||
UDPSocketBind(udp_socket, destination_addr);
|
||||
dest = destination_addr;
|
||||
break;
|
||||
|
||||
default:
|
||||
ZenithErr("Unsuccessful UDP Socket Receive From: Socket state-machine must be in OPEN, BOUND or READY state.\n");
|
||||
ZenithErr("UDP SOCKET SEND TO: Socket state-machine must be in OPEN, BOUND or READY state.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -699,11 +713,19 @@ I64 UDPHandler(CIPV4Packet *packet)
|
|||
CSocketAddressIPV4 *ipv4_addr;
|
||||
I64 num_receive;
|
||||
|
||||
ZenithLog("UDP HANDLER: Beginning handling UDP Packet.\n");
|
||||
/* ZenithWarn("UDP HANDLER: Yielding for a little bit as a debug.\n");
|
||||
ZenithWarn("UDP HANDLER: ...\n");
|
||||
I64 c = counts.jiffies;
|
||||
while (counts.jiffies < c + 1000)
|
||||
Yield;
|
||||
ZenithWarn("UDP HANDLER: ...\n");*/
|
||||
|
||||
I64 error = UDPParsePacket(&source_port, &destination_port, &data, &length, packet);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithErr("UDP Handler Packet Parse Error.\n");
|
||||
ZenithErr("UDP HANDLER: Packet Parse Error.\n");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -712,41 +734,44 @@ I64 UDPHandler(CIPV4Packet *packet)
|
|||
node = UDPTreeNodeFind(destination_port, udp_globals.bound_socket_tree);
|
||||
if (node)
|
||||
{
|
||||
// TODO: implement check for INADDR_ANY in socket queue
|
||||
queue = UDPTreeNodeQueueIPV4Find(packet->destination_ip_address, node); // TODO: make sure bit order is correct here!!
|
||||
if (queue)
|
||||
{
|
||||
udp_socket = queue->socket;
|
||||
ZenithLog("Handled UDP packet, port and address are in bound tree.\n");
|
||||
ZenithLog("UDP HANDLER: Port and Address are in bound tree.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithWarn("Handled UDP packet, found node for port, but address is not in node queue.\n");
|
||||
ZenithWarn("UDP HANDLER: Found node for port, but address is not in node queue.\n");
|
||||
ZenithWarn(" UDP packet dest ip: 0x%0X.\n", packet->destination_ip_address);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithWarn("Handled UDP packet but node for port is not in tree.\n");
|
||||
ZenithWarn("UDP HANDLER: Node for Port is not in tree.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ZenithWarn("Handled UDP packet but socket tree is currently empty.\n");
|
||||
ZenithWarn("UDP HANDLER: Socket tree is currently empty.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZenithLog("UDP HANDLER: Checking if UDP Socket's Receive-Buffer exists. UDPSocket at: 0x%0X \n", udp_socket);
|
||||
ZenithLog(" It probably exists, wtf going on ? udp_socket->receive_buffer: 0x%0X.\n", udp_socket->receive_buffer);
|
||||
// at this point, udp_socket is set, otherwise has already returned -1.
|
||||
|
||||
if (udp_socket->receive_buffer)
|
||||
{
|
||||
ZenithLog("UDP HANDLER: Saw UDP Socket receive buffer exists, about to copy data into it.\n");
|
||||
num_receive = udp_socket->receive_len;
|
||||
|
||||
if (num_receive > length)
|
||||
{
|
||||
ZenithWarn("UDP HANDLER: Truncating UDP socket receive length. num_receive , len : %d, %d\n",
|
||||
num_receive, length);
|
||||
num_receive = length;
|
||||
ZenithWarn("UDP Handler: Truncating UDP socket receive length.\n");
|
||||
}
|
||||
|
||||
MemCopy(udp_socket->receive_buffer, data, num_receive);
|
||||
|
@ -759,10 +784,13 @@ I64 UDPHandler(CIPV4Packet *packet)
|
|||
udp_socket->receive_buffer = NULL;
|
||||
udp_socket->receive_len = num_receive;
|
||||
|
||||
ipv4_addr = &udp_socket->receive_address;
|
||||
// ipv4_addr = &udp_socket->receive_address;
|
||||
ipv4_addr = &udp_socket->from_address;
|
||||
|
||||
ipv4_addr->family = AF_INET;
|
||||
ipv4_addr->port = EndianU16(source_port);
|
||||
ipv4_addr->address.address = EndianU32(packet->source_ip_address);
|
||||
ZenithLog("UDP HANDLER: Copying packet source IP (BE) to FROM_ADDRESS of UDP Socket: %08X \n", ipv4_addr->address.address);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
|
Loading…
Reference in a new issue