diff --git a/Zenith-latest-2020-07-31-13_42_17.iso b/Zenith-latest-2020-08-07-02_32_46.iso similarity index 99% rename from Zenith-latest-2020-07-31-13_42_17.iso rename to Zenith-latest-2020-08-07-02_32_46.iso index 21d60204..302a7aab 100755 Binary files a/Zenith-latest-2020-07-31-13_42_17.iso and b/Zenith-latest-2020-08-07-02_32_46.iso differ diff --git a/src/Home/Net/ARP.CC b/src/Home/Net/ARP.CC index b24a829f..76d39c43 100755 --- a/src/Home/Net/ARP.CC +++ b/src/Home/Net/ARP.CC @@ -1,5 +1,5 @@ -#include "PCNet" -#include "Ethernet" +//#include "PCNet" +//#include "Ethernet" #define ARP_HASHTABLE_SIZE 1024 @@ -54,8 +54,9 @@ I64 ARPSend(U16 operation, U32 target_ip) {//method currently assumes send_ and target_ip EndianU16 already... - U8 *ethernet_frame; - CARPHeader *header; + 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); - CARPHash *entry = HashFind(ip_string, arp_cache, HTT_ARP); + 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; \ No newline at end of file diff --git a/src/Home/Net/DHCP.CC b/src/Home/Net/DHCP.CC new file mode 100755 index 00000000..318ad14c --- /dev/null +++ b/src/Home/Net/DHCP.CC @@ -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"); +} diff --git a/src/Home/Net/DNS.CC b/src/Home/Net/DNS.CC index 6fb6d86d..a73bab0e 100755 --- a/src/Home/Net/DNS.CC +++ b/src/Home/Net/DNS.CC @@ -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->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,17 +158,21 @@ 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 ... @@ -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; + } + + DNSBuildQuestion(&q, name); + + 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; + } + + 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; } -*/ -/* -I64 DNSRunQuery(socket?, U8 *name, U16 port, CAddressInfo **result_out) +// 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); -I64 DNSGetAddressInfo(U8 *node, U8 *service, CAddressInfo *hints, CAddressInfo **result) + 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; + } -U0 DNSSetResolverIPV4(U32 ip) // funny enough he explicitly labeled IPV4......... + 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() diff --git a/src/Home/Net/Docs/ZenithStackNotes.DD b/src/Home/Net/Docs/ZenithStackNotes.DD index f4f4a4f4..91b82a8b 100755 Binary files a/src/Home/Net/Docs/ZenithStackNotes.DD and b/src/Home/Net/Docs/ZenithStackNotes.DD differ diff --git a/src/Home/Net/Ethernet.CC b/src/Home/Net/Ethernet.CC index bd24e620..ce63381b 100755 --- a/src/Home/Net/Ethernet.CC +++ b/src/Home/Net/Ethernet.CC @@ -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; \ No newline at end of file diff --git a/src/Home/Net/ICMP.CC b/src/Home/Net/ICMP.CC index a9496179..99b87248 100755 --- a/src/Home/Net/ICMP.CC +++ b/src/Home/Net/ICMP.CC @@ -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; } diff --git a/src/Home/Net/IPV4.CC b/src/Home/Net/IPV4.CC index 35dbcf85..70f03071 100755 --- a/src/Home/Net/IPV4.CC +++ b/src/Home/Net/IPV4.CC @@ -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; diff --git a/src/Home/Net/Net.HH b/src/Home/Net/Net.HH index 8b0e6af6..23700426 100755 --- a/src/Home/Net/Net.HH +++ b/src/Home/Net/Net.HH @@ -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 diff --git a/src/Home/Net/NetHandlerTask.CC b/src/Home/Net/NetHandlerTask.CC index 16267c47..e8eab401 100755 --- a/src/Home/Net/NetHandlerTask.CC +++ b/src/Home/Net/NetHandlerTask.CC @@ -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",,); \ No newline at end of file +net_handler_task = Spawn(&NetHandlerTask, NULL, "NetQueueHandler"); + diff --git a/src/Home/Net/NetQueue.CC b/src/Home/Net/NetQueue.CC index a9eaea81..3c05ede7 100755 --- a/src/Home/Net/NetQueue.CC +++ b/src/Home/Net/NetQueue.CC @@ -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; \ No newline at end of file diff --git a/src/Home/Net/NetStart.CC b/src/Home/Net/NetStart.CC new file mode 100755 index 00000000..cf44f72b --- /dev/null +++ b/src/Home/Net/NetStart.CC @@ -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"); diff --git a/src/Home/Net/PCNet.CC b/src/Home/Net/PCNet.CC index 56cfd478..717f1b26 100755 --- a/src/Home/Net/PCNet.CC +++ b/src/Home/Net/PCNet.CC @@ -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; - + 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); } @@ -524,8 +599,8 @@ interrupt U0 PCNetIRQ() U0 PCIRerouteInterrupts(I64 base) { // todo: comments explaining process, maybe better var names - I64 i; - U8 *da = dev.uncached_alias + IOAPIC_REG; + I64 i; + U8 *da = dev.uncached_alias + IOAPIC_REG; U32 *_d = dev.uncached_alias + IOAPIC_DATA; for (i = 0; i < 4; i++) @@ -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; \ No newline at end of file diff --git a/src/Home/Net/Sockets.CC b/src/Home/Net/Sockets.CC index 64259c90..fb3978f0 100755 --- a/src/Home/Net/Sockets.CC +++ b/src/Home/Net/Sockets.CC @@ -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: diff --git a/src/Home/Net/Tests/DHCPTest1.CC b/src/Home/Net/Tests/DHCPTest1.CC new file mode 100755 index 00000000..9d649f92 --- /dev/null +++ b/src/Home/Net/Tests/DHCPTest1.CC @@ -0,0 +1,4 @@ +#include "C:/Home/Net/DHCP" +#include "C:/Home/Net/NetHandlerTask" + +NetConfigure; \ No newline at end of file diff --git a/src/Home/Net/Tests/DNSTest1.CC b/src/Home/Net/Tests/DNSTest1.CC new file mode 100755 index 00000000..662e3fe9 --- /dev/null +++ b/src/Home/Net/Tests/DNSTest1.CC @@ -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); \ No newline at end of file diff --git a/src/Home/Net/Tests/MakeBreakDown.CC b/src/Home/Net/Tests/MakeBreakDown.CC new file mode 100755 index 00000000..71b07a73 --- /dev/null +++ b/src/Home/Net/Tests/MakeBreakDown.CC @@ -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; + diff --git a/src/Home/Net/Tests/UDPSendTrash.CC b/src/Home/Net/Tests/UDPSendTrash.CC new file mode 100755 index 00000000..2b70cbbe --- /dev/null +++ b/src/Home/Net/Tests/UDPSendTrash.CC @@ -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); +} diff --git a/src/Home/Net/UDP.CC b/src/Home/Net/UDP.CC index e60eafac..91a38fe7 100755 --- a/src/Home/Net/UDP.CC +++ b/src/Home/Net/UDP.CC @@ -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. }; /*************************************************** @@ -236,35 +239,36 @@ 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 ?) +{ // 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; - CSocketAddressIPV4 *temp_ip; + 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; } @@ -689,21 +703,29 @@ I64 UDPSocketSendTo(CUDPSocket *udp_socket, U8 *buffer, I64 len, CSocketAddressS I64 UDPHandler(CIPV4Packet *packet) { // TODO: Need either two UDP handlers for IPv4/IPv6, or logic changes if IPV6 is desired. - U16 source_port; - U16 destination_port; - U8 *data; - I64 length; - CUDPTreeNode *node; - CUDPTreeQueue *queue; - CUDPSocket *udp_socket; - CSocketAddressIPV4 *ipv4_addr; - I64 num_receive; + U16 source_port; + U16 destination_port; + U8 *data; + I64 length; + CUDPTreeNode *node; + CUDPTreeQueue *queue; + CUDPSocket *udp_socket; + 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;