mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-04-18 05:38:36 +01:00
Small updates to Network Stack
Added DNS, not finished. Lots of cleaning up to do when converting Shrine code Formatting alterations to Net files, beginning restructuring and updating Docs & Tests
This commit is contained in:
parent
9e53a92859
commit
31d3760e34
28 changed files with 628 additions and 241 deletions
BIN
Zenith-latest-2020-07-28-02_40_22.iso → Zenith-latest-2020-07-31-13_42_17.iso
Normal file → Executable file
BIN
Zenith-latest-2020-07-28-02_40_22.iso → Zenith-latest-2020-07-31-13_42_17.iso
Normal file → Executable file
Binary file not shown.
|
@ -46,7 +46,6 @@ U0 ARPCacheInit()
|
|||
arp_globals.local_ipv4 = 0;
|
||||
}
|
||||
|
||||
|
||||
I64 ARPSend(U16 operation,
|
||||
U8 *dest_mac_address,
|
||||
U8 *send_mac_address,
|
||||
|
@ -68,13 +67,11 @@ I64 ARPSend(U16 operation,
|
|||
|
||||
header = ethernet_frame;
|
||||
|
||||
header->hardware_type = EndianU16(HTYPE_ETHERNET);
|
||||
header->protocol_type = EndianU16(ETHERTYPE_IPV4);
|
||||
|
||||
header->hardware_addr_len = MAC_ADDRESS_LENGTH;
|
||||
header->protocol_addr_len = IP_ADDRESS_LENGTH;
|
||||
|
||||
header->operation = EndianU16(operation);
|
||||
header->hardware_type = EndianU16(HTYPE_ETHERNET);
|
||||
header->protocol_type = EndianU16(ETHERTYPE_IPV4);
|
||||
header->hardware_addr_len = MAC_ADDRESS_LENGTH;
|
||||
header->protocol_addr_len = IP_ADDRESS_LENGTH;
|
||||
header->operation = EndianU16(operation);
|
||||
|
||||
MemCopy(header->sender_hardware_addr, send_mac_address, MAC_ADDRESS_LENGTH);
|
||||
header->sender_protocol_addr = send_ip;
|
||||
|
@ -86,9 +83,6 @@ I64 ARPSend(U16 operation,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CARPHash *ARPCacheFindByIP(U32 ip_address)
|
||||
{
|
||||
U8 *ip_string = MStrPrint("%d", ip_address);
|
||||
|
@ -103,11 +97,19 @@ CARPHash *ARPCacheFindByIP(U32 ip_address)
|
|||
CARPHash *ARPCachePut(U32 ip_address, U8 *mac_address)
|
||||
{
|
||||
CARPHash *entry = ARPCacheFindByIP(ip_address);
|
||||
Free(entry);
|
||||
//Free(entry); // something seems wrong about this...
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
entry = CAlloc(sizeof(CARPHash));
|
||||
entry->str = MStrPrint("%d", ip_address);
|
||||
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");
|
||||
|
||||
entry = CAlloc(sizeof(CARPHash));
|
||||
entry->str = MStrPrint("%d", ip_address);
|
||||
MemCopy(entry->mac_address, mac_address, 6);
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -123,8 +125,6 @@ U0 ARPSetIPV4Address(U32 ip_address)
|
|||
arp_globals.local_ipv4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//ARP Handler? Takes an eth_frame CEthFrame* ?
|
||||
//Seems like a weird way to do this,
|
||||
//and then it goes into a a RegisterL3Protocol
|
||||
|
@ -164,7 +164,6 @@ I64 ARPHandler(CEthernetFrame *ethernet_frame)
|
|||
ZenithErr("ARP Handler caught wrong frame hardware type.");
|
||||
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.");
|
||||
|
@ -181,8 +180,6 @@ I64 ARPHandler(CEthernetFrame *ethernet_frame)
|
|||
return -1; // External use of ARPHandler must account for -1 error codes
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case ARP_REQUEST:
|
||||
|
@ -200,43 +197,4 @@ I64 ARPHandler(CEthernetFrame *ethernet_frame)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ARPCacheInit;
|
476
src/Home/Net/DNS.CC
Executable file
476
src/Home/Net/DNS.CC
Executable file
|
@ -0,0 +1,476 @@
|
|||
#include "UDP";
|
||||
|
||||
// https://www2.cs.duke.edu/courses/fall16/compsci356/DNS/DNS-primer.pdf
|
||||
// https://en.wikipedia.org/wiki/Domain_Name_System
|
||||
|
||||
// DNS Cache is a HashTable, similar to ARP Cache
|
||||
|
||||
#define DNS_HASHTABLE_SIZE 2048 // 1024 might be fine, test it
|
||||
#define HTT_DNS 0x00100 // identical to HTT_DICT_WORD
|
||||
|
||||
#define DNS_FLAG_RD 0x0100
|
||||
|
||||
#define DNS_OP_QUERY 0
|
||||
|
||||
#define DNS_TYPE_A 1
|
||||
|
||||
#define DNS_CLASS_IN 1
|
||||
|
||||
#define DNS_TIMEOUT 5000
|
||||
class CDNSHash:CHash
|
||||
{ // store U8 *hostname as CHash->str U8 *
|
||||
CAddressInfo info;
|
||||
// Shrine has 'TODO: honor TTL' ...
|
||||
// Duke: 'TTL: the number of seconds the results can be cached'
|
||||
// perhaps have a separate task for removing cached results ?
|
||||
};
|
||||
|
||||
class CDNSDomainName
|
||||
{
|
||||
U8 **labels;
|
||||
I64 num_labels;
|
||||
};
|
||||
|
||||
class CDNSQuestion
|
||||
{
|
||||
CDNSQuestion *next;
|
||||
CDNSDomainName q_name;
|
||||
U16 q_type;
|
||||
U16 q_class;
|
||||
};
|
||||
|
||||
class CDNSHeader
|
||||
{
|
||||
U16 id;
|
||||
U16 flags;
|
||||
U16 q_count; // number of entries in question section
|
||||
U16 a_count; // number of resource records in answer section
|
||||
U16 ns_count; // number of name server resource records in authority records section
|
||||
U16 ar_count; // number of resource records in additional records section
|
||||
};
|
||||
|
||||
class CDNSRR
|
||||
{ // RR: Resource Record
|
||||
CDNSRR *next;
|
||||
CDNSDomainName name; // name of the node this record is for
|
||||
U16 type; // RR type, e.g. 44=SSHFP, 15=MX, 49=DHCID ...
|
||||
U16 rr_class; // class code
|
||||
U32 ttl; // count in seconds that RR stays valid (max = 2^31 - 1)
|
||||
U16 rd_length; // length of r_data member
|
||||
U8 *r_data; // additional RR-specific data
|
||||
};
|
||||
|
||||
class CDNSGlobals
|
||||
{
|
||||
U16 addr_family;
|
||||
CIPAddressStorage dns_ip;
|
||||
|
||||
} dns_globals;
|
||||
|
||||
CHashTable *dns_cache = NULL;
|
||||
|
||||
U0 DNSCacheInit()
|
||||
{
|
||||
dns_cache = HashTableNew(DNS_HASHTABLE_SIZE);
|
||||
|
||||
MemSet(&dns_globals.dns_ip, 0, sizeof(CIPAddressStorage));
|
||||
dns_globals.addr_family = 0;
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
CDNSHash *DNSCachePut(U8 *hostname, CAddressInfo *info)
|
||||
{
|
||||
CDNSHash *entry = DNSCacheFind(hostname);
|
||||
|
||||
if (!entry)
|
||||
{
|
||||
entry = CAlloc(sizeof(CDNSHash));
|
||||
entry->str = StrNew(hostname);
|
||||
AddressInfoCopy(&entry->info, info);
|
||||
|
||||
HashAdd(entry, dns_cache);
|
||||
}
|
||||
else
|
||||
ZenithWarn("DNS Cache Put attempted but entry was already found in Cache. TODO: overwrite?");
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
I64 DNSCalculateQuestionSize(CDNSQuestion *q)
|
||||
{ // ??
|
||||
I64 i, size = 0;
|
||||
|
||||
for (i = 0; i < q->q_name.num_labels; i++)
|
||||
{
|
||||
size += 1 + StrLen(q->q_name.labels[i]);
|
||||
}
|
||||
|
||||
return size + 1 + 4;
|
||||
}
|
||||
|
||||
U0 DNSSerializeQuestion(U8 *buffer, CDNSQuestion *q)
|
||||
{ // ??
|
||||
I64 i;
|
||||
U8 *label;
|
||||
|
||||
for (i = 0; i < q->q_name.num_labels; i++)
|
||||
{
|
||||
label = q->q_name.labels[i];
|
||||
|
||||
*(buffer++) = StrLen(label);
|
||||
|
||||
while (*label)
|
||||
*(buffer++) = *(label++);
|
||||
}
|
||||
|
||||
*(buffer++) = 0;
|
||||
*(buffer++) = q->q_type >> 8;
|
||||
*(buffer++) = q->q_type & 0xFF;
|
||||
*(buffer++) = q->q_class >> 8;
|
||||
*(buffer++) = q->q_class & 0xFF;
|
||||
}
|
||||
|
||||
I64 DNSSendQuestion(U16 id, U16 local_port, CDNSQuestion *q)
|
||||
{
|
||||
CIPV4Address* ipv4_addr;
|
||||
U8 *frame;
|
||||
U16 flags;
|
||||
CDNSHeader *header;
|
||||
I64 de_index;
|
||||
|
||||
switch (dns_globals.addr_family)
|
||||
{
|
||||
case AF_UNSPEC: // 0, global dns ip not set
|
||||
return -1;
|
||||
|
||||
case AF_INET6:
|
||||
ZenithErr("IPV6 not supported yet in DNS.\n");
|
||||
throw('DNS');
|
||||
|
||||
case AF_INET:
|
||||
ipv4_addr = &dns_globals.dns_ip;
|
||||
|
||||
if (!*ipv4_addr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// UDPPacketAllocate currently only accepts IPV4 ...
|
||||
de_index = UDPPacketAllocate(&frame,
|
||||
IPV4GetAddress(),
|
||||
local_port,
|
||||
*ipv4_addr,
|
||||
53,
|
||||
sizeof(CDNSHeader) + DNSCalculateQuestionSize(q));
|
||||
if (de_index < 0)
|
||||
return de_index;
|
||||
|
||||
flags = (DNS_OP_QUERY << 11) | DNS_FLAG_RD;
|
||||
|
||||
header = frame;
|
||||
|
||||
header->id = EndianU16(id);
|
||||
header->flags = EndianU16(flags);
|
||||
header->q_count = EndianU16(1);
|
||||
header->a_count = 0;
|
||||
header->ns_count = 0;
|
||||
header->ar_count = 0;
|
||||
|
||||
DNSSerializeQuestion(frame + sizeof(CDNSHeader), q);
|
||||
|
||||
UDPPacketFinish(de_index);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
I64 DNSParseDomainName(U8 *packet_data, I64 packet_length, U8 **data_inout, I64 *length_inout, CDNSDomainName *name_out)
|
||||
{ // these methods look not-so-good, ngl.
|
||||
U8 *data = *data_inout;
|
||||
U8 *name_buf;
|
||||
I64 length = *length_inout;
|
||||
I64 label_len;
|
||||
Bool jump_taken = FALSE;
|
||||
|
||||
if (length < 1)
|
||||
{
|
||||
ZenithErr("DNS parsed domain name, hit length of 0 or less\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
name_out->labels = CAlloc(16 * sizeof(U8 *));
|
||||
name_out->num_labels = 0;
|
||||
|
||||
name_buf = CAlloc(256); // ?..
|
||||
name_out->labels[0] = name_buf;
|
||||
|
||||
while (length)
|
||||
{
|
||||
label_len = *(data++);
|
||||
length--;
|
||||
|
||||
if (label_len == 0)
|
||||
break;
|
||||
else if (label_len >= 192)
|
||||
{
|
||||
label_len &= 0x3F; // ...
|
||||
|
||||
if (!jump_taken)
|
||||
{
|
||||
*data_inout = data + 1;
|
||||
*length_inout = length - 1;
|
||||
jump_taken = TRUE;
|
||||
ZenithLog("UDP parsed domain name, jump taken\n");
|
||||
}
|
||||
|
||||
data = packet_data + ((label_len << 8) | *data);
|
||||
length = packet_data + packet_length - data;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length < label_len)
|
||||
return -1; // ?
|
||||
|
||||
MemCopy(name_buf, data, label_len);
|
||||
data += label_len;
|
||||
length -= label_len;
|
||||
|
||||
name_buf[label_len] = 0;
|
||||
name_out->labels[name_out->num_labels++] = name_buf;
|
||||
|
||||
name_buf += label_len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!jump_taken)
|
||||
{
|
||||
*data_inout = data;
|
||||
*length_inout = length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
I64 DNSParseQuestion(U8 *packet_data, I64 packet_length, U8 **data_inout, I64 *length_inout, CDNSQuestion *q_out)
|
||||
{
|
||||
U8 *data;
|
||||
I64 length;
|
||||
I64 error = DNSParseDomainName(packet_data, packet_length, data_inout, length_inout, &q_out->q_name);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
data = *data_inout;
|
||||
length = *length_inout;
|
||||
|
||||
if (length < 4)
|
||||
return -1;
|
||||
|
||||
q_out->next = NULL;
|
||||
q_out->q_type = (data[1] << 8) | data[0];
|
||||
q_out->q_class = (data[3] << 8) | data[2];
|
||||
|
||||
*data_inout = data + 4;
|
||||
*length_inout = length - 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
I64 DNSParseRR(U8 *packet_data, I64 packet_length, U8 **data_inout, I64 *length_inout, CDNSRR *rr_out)
|
||||
{
|
||||
U8 *data;
|
||||
I64 length;
|
||||
I64 record_length;
|
||||
I64 error = DNSParseDomainName(packet_data, packet_length, data_inout, length_inout, &rr_out->name);
|
||||
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
data = *data_inout;
|
||||
length = *length_inout;
|
||||
|
||||
if (length < 10)
|
||||
return -1;
|
||||
|
||||
rr_out->next = NULL;
|
||||
MemCopy(&rr_out->type, data, 10); // ???
|
||||
|
||||
record_length = 10 + EndianU16(rr_out->rd_length);
|
||||
|
||||
if (length < record_length)
|
||||
return -1;
|
||||
|
||||
rr_out->r_data = data + 10; // ??
|
||||
|
||||
*data_inout = data + record_length;
|
||||
*length_inout = length - record_length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
I64 DNSParseResponse(U16 id, U8 *data, I64 len, CDNSHeader **header_out, CDNSQuestion **questions_out, CDNSRR **answers_out)
|
||||
{
|
||||
CDNSHeader *header;
|
||||
CDNSQuestion *question;
|
||||
CDNSRR *answer;
|
||||
I64 i;
|
||||
U8 *packet_data = data;
|
||||
I64 packet_length = length;
|
||||
|
||||
if (length < sizeof(CDNSHeader))
|
||||
{
|
||||
ZenithErr("DNS Response Parsed, length too short.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
header = data;
|
||||
data += sizeof(CDNSHeader);
|
||||
|
||||
if (id != 0 && EndianU16(header->id) != id)
|
||||
{
|
||||
ZenithErr("DNS Response Parsed, header id mismatch.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < EndianU16(header->q_count); i++)
|
||||
{
|
||||
question = CAlloc(sizeof(CDNSQuestion));
|
||||
if (DNSParseQuestion(packet_data, packet_length, &data, &length, question) < 0)
|
||||
return -1;
|
||||
|
||||
question->next = *questions_out;
|
||||
*questions_out = question;
|
||||
}
|
||||
|
||||
for (i = 0; i < EndianU16(header->a_count); i++)
|
||||
{
|
||||
answer = CAlloc(sizeof(CDNSRR));
|
||||
if (DNSParseRR(packet_data, packet_length, &data, &length, answer) < 0)
|
||||
return -1;
|
||||
|
||||
answer->next = *answers_out;
|
||||
*answers_out = answer;
|
||||
}
|
||||
|
||||
*header_out = header;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
U0 DNSBuildQuestion(CDNSQuestion *q, U8 *name)
|
||||
{
|
||||
U8 *copy = StrNew(name);
|
||||
U8 *dot;
|
||||
|
||||
q->next = NULL;
|
||||
q->q_name.labels = CAlloc(16 * sizeof(U8 *));
|
||||
q->q_name.labels[0] = 0;
|
||||
q->q_name.num_labels = 0;
|
||||
q->q_type = DNS_TYPE_A;
|
||||
q->q_class = DNS_CLASS_IN;
|
||||
|
||||
while (*copy)
|
||||
{
|
||||
q->q_name.labels[q->q_name.num_labels++] = copy;
|
||||
dot = StrFirstOcc(copy, ".");
|
||||
|
||||
if (dot)
|
||||
{
|
||||
*dot = 0;
|
||||
copy = dot + 1;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// these Free methods bother me a bit...
|
||||
U0 DNSFreeQuestion(CDNSQuestion *q)
|
||||
{
|
||||
Free(q->q_name.labels[0]);
|
||||
}
|
||||
|
||||
U0 DNSFreeRR(CDNSRR *r)
|
||||
{
|
||||
Free(rr->name.labels[0]);
|
||||
}
|
||||
|
||||
U0 DNSFreeQuestionChain(CDNSQuestion *questions)
|
||||
{
|
||||
CDNSQuestion *next;
|
||||
|
||||
while (questions)
|
||||
{
|
||||
next = questions->next;
|
||||
DNSFreeQuestion(questions);
|
||||
Free(questions);
|
||||
questions = next;
|
||||
}
|
||||
}
|
||||
|
||||
U0 DNSFreeRRChain(CDNSRR *rrs)
|
||||
{ // Shrine sets rrs->next to a CDNSQuestion when it would be a CDNSRR ... assuming it's wrong and fixing it here..
|
||||
CDNSRR *next;
|
||||
|
||||
while (rrs)
|
||||
{
|
||||
next = rrs->next;
|
||||
DNSFreeRR(rrs);
|
||||
Free(rrs);
|
||||
rrs = next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
I64 DNSRunQuery(CUDPSocket *udp_socket, U8 *name, U16 port, CAddressInfo **result_out)
|
||||
{ // IPV4-UDP-based
|
||||
I64 retries = 0;
|
||||
I64 timeout = DNS_TIMEOUT;
|
||||
U16 local_port = RandU16;
|
||||
U16 id = RandU16;
|
||||
I64 error = 0;
|
||||
U8 *buffer;
|
||||
I64 count;
|
||||
Bool have;
|
||||
|
||||
CDNSQuestion q;
|
||||
CDNSHeader *header;
|
||||
CDNSQuestion *questions;
|
||||
CDNSRR *answers;
|
||||
CDNSRR *a;
|
||||
|
||||
CSocketAddressIPV4 ipv4_addr;
|
||||
CSocketAddressIPV4 ipv4_addr_in; // ?
|
||||
CAddressInfo *res;
|
||||
|
||||
//setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO_MS, &timeout, sizeof(timeout))
|
||||
udp_socket->receive_timeout_ms = timeout;
|
||||
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
I64 DNSRunQuery(socket?, U8 *name, U16 port, CAddressInfo **result_out)
|
||||
|
||||
I64 DNSGetAddressInfo(U8 *node, U8 *service, CAddressInfo *hints, CAddressInfo **result)
|
||||
|
||||
U0 DNSSetResolverIPV4(U32 ip) // funny enough he explicitly labeled IPV4.........
|
||||
|
||||
U0 Host(U8 *hostname)
|
||||
|
||||
U0 DNSInit()
|
||||
|
||||
*/
|
||||
|
||||
DNSCacheInit;
|
|
@ -36,6 +36,7 @@ NetQueue
|
|||
|
||||
|
||||
Ethernet
|
||||
EthernetInitGlobals
|
||||
EthernetFrameParse (has a fixme)
|
||||
|
||||
|
||||
|
@ -46,10 +47,17 @@ ARP
|
|||
ARPCachePut
|
||||
ARPHandler
|
||||
ARPSetIPV4Address
|
||||
ARPHandler
|
||||
|
||||
|
||||
Sockets (just finite state modifiers.)
|
||||
AddressInfoCopy
|
||||
IPV4AddressParse
|
||||
PresentationToNetwork
|
||||
NetworkToPresentation
|
||||
|
||||
SocketStateErr
|
||||
Socket
|
||||
SocketAccept
|
||||
SocketClose
|
||||
SocketBind
|
||||
|
@ -61,6 +69,7 @@ Sockets (just finite state modifiers.)
|
|||
SocketSendTo
|
||||
|
||||
IPV4
|
||||
InitIPV4Globals (should change this to IPV4InitGlobals ...)
|
||||
IPV4Checksum
|
||||
GetMACAddressForIP
|
||||
IPV4PacketAllocate
|
||||
|
@ -78,14 +87,37 @@ TCP
|
|||
|
||||
|
||||
UDP
|
||||
UDPTreeNodeInit
|
||||
UDPTreeNodeAdd
|
||||
UDPTreeNodeParamAdd
|
||||
UDPTreeNodeParamInit
|
||||
UDPTreeNodeFind
|
||||
UDPTreeNodePop
|
||||
UDPTreeNodeSinglePop
|
||||
UDPTreeNodeQueueInit
|
||||
UDPTreeNodeQueueSocketFind
|
||||
UDPTreeNodeQueueIPV4Find
|
||||
UDPTreeNodeQueueSocketSinglePop
|
||||
|
||||
UDPGlobalsInit
|
||||
UDPPacketAllocate
|
||||
UDPPacketFinish
|
||||
UDPParsePacket
|
||||
|
||||
UDPSocket
|
||||
UDPSocketBind
|
||||
UDPSocketClose
|
||||
UDPSocketReceiveFrom
|
||||
UDPSocketSendTo
|
||||
|
||||
DNS
|
||||
|
||||
DNSCacheInit
|
||||
DNSCacheFind
|
||||
DNSCachePut
|
||||
|
||||
NetHandlerTask
|
||||
NetHandlerTask
|
||||
HandleNetQueueEntry (4 million context swaps per second!)
|
||||
HandleNetQueueEntry (TODO: investigate 4 million context swaps per second)
|
||||
IPV4Handler
|
||||
|
||||
NetConfig
|
Binary file not shown.
|
@ -4,6 +4,8 @@ Departures from Shrine:
|
|||
|
||||
ARP Cache is Hashtable. Keys are U32 ip addresses to "%d" string.
|
||||
|
||||
DNS Cache is Hashtable. Keys are U8 *hostname.
|
||||
|
||||
NetFIFO is NetQueue. If problems arise, maybe set a #define max
|
||||
for the length of the Queue.
|
||||
|
||||
|
@ -16,9 +18,9 @@ Departures from Shrine:
|
|||
Stack progress: (# done, ~ WIP, . N/A)
|
||||
|
||||
# PCNet-II Driver
|
||||
. Other Network Card Drivers? See $LK,"Roadmap",A="FF:C:/Home/Roadmap.DD,most common ethernet cards"$.
|
||||
|
||||
# NetQueue
|
||||
- no NetHandler currently
|
||||
|
||||
# Ethernet
|
||||
- double check.
|
||||
|
@ -34,6 +36,9 @@ Stack progress: (# done, ~ WIP, . N/A)
|
|||
socket state. Protocols will
|
||||
need to detect socket states
|
||||
and respond appropriately.
|
||||
- had to go back and alter low level
|
||||
logic recently, keep eyes on verifying
|
||||
socket logic sanity.
|
||||
|
||||
|
||||
# IPV4 (Internet Protocol version 4)
|
||||
|
@ -44,11 +49,12 @@ Stack progress: (# done, ~ WIP, . N/A)
|
|||
|
||||
. TCP (Transmission Control Protocol)
|
||||
|
||||
. UDP (User Datagram Protocol)
|
||||
~ UDP (User Datagram Protocol)
|
||||
- needs more testing. could use a UDPRep func to render bound tree.
|
||||
|
||||
. DNS (Domain Name System)
|
||||
~ DNS (Domain Name System)
|
||||
|
||||
. NetHandlerTask
|
||||
~ NetHandlerTask
|
||||
- thinking maybe for this, instead of using this whole
|
||||
handler function pointer nonsense, it can be done
|
||||
more seamlessly with a switch(ethertype). Shrine
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -44,7 +44,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; //TODO: He has a comment literally just saying "??".
|
||||
frame_out->length = length - ETHERNET_MAC_HEADER_LENGTH + 4; // He has a comment literally just saying "??".
|
||||
}
|
||||
|
||||
EthernetInitGlobals;
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
class CICMPHeader // Shrine's use of id and seq indicate this header is for Address Mask Reply/Request
|
||||
{
|
||||
U8 type;
|
||||
U8 code;
|
||||
U8 type;
|
||||
U8 code;
|
||||
U16 checksum;
|
||||
|
||||
U16 identifier;
|
||||
|
@ -38,16 +38,12 @@ I64 ICMPSendReply(U32 destination_ip_address,
|
|||
|
||||
header = frame;
|
||||
|
||||
|
||||
header->type = ICMP_TYPE_ECHO_REPLY;
|
||||
|
||||
header->code = 0; // why is 0 okay?
|
||||
|
||||
header->checksum = EndianU16(EndianU16(request_checksum) + 0x0800);// TODO: this is awful. Shrine says hack alert.
|
||||
|
||||
header->identifier = identifier;
|
||||
|
||||
header->sequence_number = sequence_number;
|
||||
header->type = ICMP_TYPE_ECHO_REPLY;
|
||||
header->code = 0; // why is 0 okay?
|
||||
header->checksum = EndianU16(EndianU16(request_checksum) + 0x0800);
|
||||
header->identifier = identifier;
|
||||
header->sequence_number = sequence_number;
|
||||
// TODO: header checksum is awful. Shrine says hack alert.
|
||||
|
||||
MemCopy(frame + sizeof(CICMPHeader), payload, length);
|
||||
|
||||
|
|
|
@ -11,39 +11,32 @@
|
|||
#define IP_PROTOCOL_TCP 0x06
|
||||
#define IP_PROTOCOL_UDP 0x11
|
||||
|
||||
|
||||
class CIPV4Packet
|
||||
{
|
||||
CEthernetFrame *ethernet_frame;
|
||||
CEthernetFrame *ethernet_frame;
|
||||
|
||||
U32 source_ip_address;
|
||||
U32 destination_ip_address;
|
||||
U32 source_ip_address;
|
||||
U32 destination_ip_address;
|
||||
|
||||
U8 protocol;
|
||||
U8 protocol;
|
||||
U8 padding[7];
|
||||
|
||||
U8 padding[7];
|
||||
|
||||
U8 *data;
|
||||
|
||||
I64 length;
|
||||
U8 *data;
|
||||
I64 length;
|
||||
};
|
||||
|
||||
class CIPV4Header
|
||||
{ // note: U4's in some U8s.
|
||||
U8 version_ihl; // Version for IPV4 is 4. IHL=Internet Header Length
|
||||
|
||||
U8 dscp_ecn; // DSCP=Differentiated Services Code Point. ECN=Explicit Congestion Notification
|
||||
U8 version_ihl; // Version for IPV4 is 4. IHL=Internet Header Length
|
||||
U8 dscp_ecn; // DSCP=Differentiated Services Code Point. ECN=Explicit Congestion Notification
|
||||
|
||||
U16 total_length; // min 20B max 65535
|
||||
|
||||
U16 identification;
|
||||
|
||||
U16 flags_fragment_offset; // flags first(?) 3 bits. fragment offset min 0 max 65528
|
||||
// flag: bit 0: reserved must be 0. bit 1: don't fragment. bit 2: more fragments
|
||||
// flag: bit 0: reserved must be 0. bit 1: don't fragment. bit 2: more fragments
|
||||
|
||||
U8 time_to_live; // specified in seconds, wikipedia says nowadays serves as a hop count
|
||||
|
||||
U8 protocol;
|
||||
U8 time_to_live; // specified in seconds, wikipedia says nowadays serves as a hop count
|
||||
U8 protocol;
|
||||
|
||||
U16 header_checksum;
|
||||
|
||||
|
@ -69,9 +62,8 @@ U0 InitIPV4Globals()
|
|||
ipv4_globals.ipv4_subnet_mask = 0;
|
||||
}
|
||||
|
||||
|
||||
// For now, trusting Shrine's implement
|
||||
// of this. Shrine links back to
|
||||
// of checksum. Shrine links back to
|
||||
// http://stackoverflow.com/q/26774761/2524350
|
||||
|
||||
U16 IPV4Checksum(U8* header, I64 length)
|
||||
|
@ -99,8 +91,6 @@ U16 IPV4Checksum(U8* header, I64 length)
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
||||
{
|
||||
CARPHash *entry;
|
||||
|
@ -116,7 +106,6 @@ I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
|||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (ip_address == 0)
|
||||
{
|
||||
ZenithLog("Get MAC for IP failed. Address = 0\n");
|
||||
|
@ -129,11 +118,10 @@ I64 GetMACAddressForIP(U32 ip_address, U8 **mac_out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// "outside this subnet; needs routing"
|
||||
if ((ip_address & ipv4_globals.ipv4_subnet_mask) != (ipv4_globals.local_ip & ipv4_globals.ipv4_subnet_mask))
|
||||
{
|
||||
// Shrine recurses here... and says FIXME infinite loop if mis-configured...
|
||||
// TODO: Shrine recurses here... and says FIXME infinite loop if mis-configured...
|
||||
}
|
||||
else // "local network"
|
||||
{
|
||||
|
@ -182,16 +170,13 @@ I64 IPV4PacketAllocate(U8 **frame_out,
|
|||
{
|
||||
U8 *ethernet_frame;
|
||||
U8 *destination_mac_address;
|
||||
|
||||
I64 error;
|
||||
I64 de_index;
|
||||
|
||||
I64 internet_header_length;
|
||||
|
||||
CIPV4Header *header;
|
||||
|
||||
|
||||
error = GetMACAddressForIP(destination_ip_address, &destination_mac_address);
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
ZenithLog("IPV4 Packet Allocate failed to get MAC for destination.\n");
|
||||
|
@ -211,10 +196,8 @@ I64 IPV4PacketAllocate(U8 **frame_out,
|
|||
|
||||
internet_header_length = 5;// ... why. need a #define
|
||||
|
||||
|
||||
header = ethernet_frame;
|
||||
|
||||
|
||||
header->version_ihl = internet_header_length | (4 << 4);// whaaat the fuck is this? #define!
|
||||
header->dscp_ecn = 0; // a clear define of what this actually means would be good
|
||||
header->total_length = EndianU16(internet_header_length * 4 + length); //...why?
|
||||
|
@ -278,32 +261,4 @@ U0 IPV4ParsePacket(CIPV4Packet *packet_out, CEthernetFrame *ethernet_frame)
|
|||
}
|
||||
|
||||
// IPV4 handler moved to NetHandlerTask file.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
InitIPV4Globals;
|
|
@ -2,28 +2,29 @@
|
|||
(in our case, Queues) for pending and
|
||||
empty frames. If logical to implement,
|
||||
perhaps Zenith NetQueue code should
|
||||
do something similar to that idea. */
|
||||
do something similar to that idea.
|
||||
|
||||
/* Each Ethernet Frame will be represented
|
||||
Each Ethernet Frame will be represented
|
||||
as an entry in a CQueue. */
|
||||
|
||||
class CNetQueueEntry:CQueue
|
||||
{
|
||||
I64 length; //todo: change to packet_length?
|
||||
U8 frame[ETHERNET_FRAME_SIZE];
|
||||
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.
|
||||
Upon QueueInit, ->next and ->last are set to
|
||||
itself, the Head. */
|
||||
|
||||
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 NetHandlerTask.CC */
|
||||
CTask *net_handler_task = NULL;
|
||||
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()
|
||||
{
|
||||
|
@ -31,7 +32,6 @@ U0 NetQueueInit()
|
|||
QueueInit(net_queue);
|
||||
}
|
||||
|
||||
|
||||
CNetQueueEntry *NetQueuePull()
|
||||
{/* Returns a pointer to a CNetQueueEntry,
|
||||
or NULL pointer if Net Queue is empty. */
|
||||
|
@ -50,8 +50,6 @@ CNetQueueEntry *NetQueuePull()
|
|||
return entry;
|
||||
}
|
||||
|
||||
|
||||
|
||||
U0 NetQueuePushCopy(U8 *data, I64 length)
|
||||
{/* Pushes a copy of the packet data and length
|
||||
into the Net Queue. The NetQueueEntry is inserted
|
||||
|
@ -72,27 +70,4 @@ U0 NetQueuePushCopy(U8 *data, I64 length)
|
|||
|
||||
}
|
||||
|
||||
NetQueueInit;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NetQueueInit;
|
|
@ -81,7 +81,8 @@
|
|||
class CPCNet
|
||||
{
|
||||
CPCIDev *pci;
|
||||
U8 mac_address[6]; // MAC address is first 6 bytes of PCNet EEPROM (page # ? )
|
||||
|
||||
U8 mac_address[6]; // MAC address is first 6 bytes of PCNet EEPROM (page # ? )
|
||||
|
||||
I64 current_rx_de_index; // Current Receive DE being processed. Gets incremented, wrapped to 0 at max of PCNET_RX_BUFF_COUNT.
|
||||
I64 current_tx_de_index; // Current Transmit DE being processed. Gets incremented, wrapped to 0 at max of PCNET_TX_BUFF_COUNT.
|
||||
|
@ -102,6 +103,7 @@ class CPCNetDescriptorEntry
|
|||
but have different registers and functions.
|
||||
The RX and TX DE buffers of the CPCNet class
|
||||
are allocated to a certain amount of these DEs. */
|
||||
|
||||
U32 buffer_addr;
|
||||
U32 status1;
|
||||
U32 status2;
|
||||
|
|
|
@ -45,14 +45,14 @@
|
|||
#define IP_PARSE_STATE_NUM 0
|
||||
#define IP_PARSE_STATE_DOT 1
|
||||
|
||||
|
||||
/*
|
||||
class CSocketAddress
|
||||
{
|
||||
U16 family; // 'address family, AF_xxx'
|
||||
|
||||
U8 data[14]; // '14 bytes of protocol address'
|
||||
};
|
||||
|
||||
*/
|
||||
class CIPV4Address
|
||||
{
|
||||
U32 address; // 'in Network Byte order' ... Big Endian
|
||||
|
@ -70,24 +70,19 @@ class CIPAddressStorage
|
|||
|
||||
class CSocketAddressIPV4
|
||||
{
|
||||
I16 family; // 'AF_INET'
|
||||
U16 port; // 'in Network Byte order' ... Big Endian
|
||||
|
||||
CIPV4Address address;
|
||||
|
||||
U8 zeroes[8]; // 'same size as socket address'
|
||||
I16 family; // 'AF_INET'
|
||||
U16 port; // 'in Network Byte order' ... Big Endian
|
||||
CIPV4Address address;
|
||||
U8 zeroes[8]; // 'same size as socket address'
|
||||
};
|
||||
|
||||
class CSocketAddressIPV6
|
||||
{
|
||||
U16 family; // 'AF_INET6'
|
||||
U16 port; // 'in Network Byte order'... Big Endian
|
||||
|
||||
U32 flow_info;
|
||||
|
||||
CIPV6Address address;
|
||||
|
||||
U32 scope_id;
|
||||
U16 family; // 'AF_INET6'
|
||||
U16 port; // 'in Network Byte order'... Big Endian
|
||||
U32 flow_info;
|
||||
CIPV6Address address;
|
||||
U32 scope_id;
|
||||
};
|
||||
|
||||
class CSocketAddressStorage
|
||||
|
@ -95,25 +90,20 @@ class CSocketAddressStorage
|
|||
hold both IPV4 and IPV6 structures.' */
|
||||
|
||||
U16 family;
|
||||
|
||||
U8 padding[26];
|
||||
U8 padding[26];
|
||||
|
||||
};
|
||||
|
||||
class CAddressInfo
|
||||
{
|
||||
I32 flags;
|
||||
I32 family;
|
||||
I32 socket_type;
|
||||
I32 protocol;
|
||||
|
||||
I64 address_length;
|
||||
|
||||
CSocketAddress *address;
|
||||
|
||||
U8 *canonical_name;
|
||||
|
||||
CAddressInfo *next;
|
||||
I32 flags;
|
||||
I32 family;
|
||||
I32 socket_type;
|
||||
I32 protocol;
|
||||
I64 address_length;
|
||||
CSocketAddressStorage *address;
|
||||
U8 *canonical_name;
|
||||
CAddressInfo *next;
|
||||
};
|
||||
|
||||
class CSocket
|
||||
|
@ -124,6 +114,22 @@ class CSocket
|
|||
U16 domain;
|
||||
};
|
||||
|
||||
U0 AddressInfoCopy(CAddressInfo *out, CAddressInfo *in)
|
||||
{ // assumes *out already exists
|
||||
MemCopy(out, in, sizeof(CAddressInfo));
|
||||
|
||||
if (in->address)
|
||||
{
|
||||
out->address = CAlloc(in->address_length);
|
||||
MemCopy(out->address, in->address, in->address_length);
|
||||
}
|
||||
|
||||
if (in->canonical_name)
|
||||
{
|
||||
out->canonical_name = StrNew(in->canonical_name);
|
||||
}
|
||||
}
|
||||
|
||||
Bool IPV4AddressParse(U8 *string, U32 *destination)
|
||||
{
|
||||
// U8* lexable_string;
|
||||
|
@ -339,9 +345,6 @@ U0 SocketStateErr(U8 *request, U8 state)
|
|||
ZenithErr("Socket attempted %s while in %s state.\n", request, state_string);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
U0 SocketAccept(CSocket *socket)
|
||||
{
|
||||
switch (socket->state)
|
||||
|
|
0
src/Home/Net/Test8.CC → src/Home/Net/Tests/Old/Test8.CC
Normal file → Executable file
0
src/Home/Net/Test8.CC → src/Home/Net/Tests/Old/Test8.CC
Normal file → Executable file
0
src/Home/Net/Test9.CC → src/Home/Net/Tests/Old/Test9.CC
Normal file → Executable file
0
src/Home/Net/Test9.CC → src/Home/Net/Tests/Old/Test9.CC
Normal file → Executable file
|
@ -8,48 +8,40 @@ class CUDPHeader
|
|||
{
|
||||
U16 source_port;
|
||||
U16 destination_port;
|
||||
|
||||
U16 length;
|
||||
U16 checksum;
|
||||
};
|
||||
|
||||
class CUDPSocket
|
||||
{
|
||||
CSocket *socket;
|
||||
|
||||
I64 receive_timeout_ms;
|
||||
I64 receive_max_timeout;
|
||||
|
||||
U8 *receive_buffer;
|
||||
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
|
||||
CSocket *socket;
|
||||
I64 receive_timeout_ms;
|
||||
I64 receive_max_timeout;
|
||||
U8 *receive_buffer;
|
||||
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
|
||||
};
|
||||
|
||||
/***************************************************
|
||||
|
||||
UDP Bound Socket Tree Classes & Functions
|
||||
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
// UDP Bound Socket Tree Classes & Functions
|
||||
***************************************************/
|
||||
|
||||
class CUDPTreeQueue
|
||||
{ // next, last for CQueue implementation.
|
||||
CUDPTreeQueue *next;
|
||||
CUDPTreeQueue *last;
|
||||
|
||||
CUDPSocket *socket;
|
||||
CUDPTreeQueue *next;
|
||||
CUDPTreeQueue *last;
|
||||
CUDPSocket *socket;
|
||||
};
|
||||
|
||||
class CUDPTreeNode
|
||||
{
|
||||
I64 port;
|
||||
|
||||
CUDPTreeNode *left;
|
||||
CUDPTreeNode *right;
|
||||
|
||||
CUDPTreeQueue *queue;
|
||||
I64 port;
|
||||
CUDPTreeNode *left;
|
||||
CUDPTreeNode *right;
|
||||
CUDPTreeQueue *queue;
|
||||
};
|
||||
|
||||
CUDPTreeNode *UDPTreeNodeInit()
|
||||
|
@ -316,16 +308,8 @@ CUDPTreeQueue *UDPTreeNodeQueueSinglePop(U32 address, CUDPTreeNode *node)
|
|||
return temp_queue; // if not found, NULL.
|
||||
}
|
||||
*/
|
||||
// end UDP Bound Socket functions & classes
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***************************************************/
|
||||
|
||||
class CUDPGlobals
|
||||
{
|
||||
|
@ -788,4 +772,4 @@ I64 UDPHandler(CIPV4Packet *packet)
|
|||
// ZenithErr and return fail vals if socket FSM improperly used.
|
||||
// Careful with Free()'s.
|
||||
|
||||
UDPGlobalsInit;
|
||||
UDPGlobalsInit;
|
Loading…
Reference in a new issue