Skip to content

Commit

Permalink
DNS working
Browse files Browse the repository at this point in the history
  • Loading branch information
konect-V committed Apr 1, 2024
1 parent c746709 commit 435b762
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 0 deletions.
15 changes: 15 additions & 0 deletions sources/core/modules/net/source/dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,20 @@ int get_dhcp_info(net_device_t* net_device){
fill_dhcp_output(net_device, &dhcp);
fill_dhcp_discovery_options(&dhcp);
generate_udp_packet(net_device, 0xffffffff, 67, 68, sizeof(struct dhcp_packet), &dhcp);

/* test dns */
net_device_internal_t* internal = (net_device_internal_t*)net_device->external_data;
while(internal->dns_ip == 0){
sleep_us(1000);
}

uint32_t address;
uint32_t ttl;
uint8_t error;
if(!dns_resolve_ip(net_device, "wikipedia.com", &address, &ttl, &error)){
log_info("DNS resolve IP: %d.%d.%d.%d, TTL : %d seconds, with error code : 0x%x\n",
((uint8_t*)&address)[3], ((uint8_t*)&address)[2], ((uint8_t*)&address)[1], ((uint8_t*)&address)[0], ttl, error);
}

return 0;
}
165 changes: 165 additions & 0 deletions sources/core/modules/net/source/dns.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include <main.h>

struct dns_request{
uint32_t address;
uint32_t ttl;
uint8_t error;
bool have_response;
};

vector_t* dns_requests = NULL;

void receive_dns_info(void* external_data, net_device_t* net_device, struct udphdr* udp_header, size_t size){
void* buffer_data = (void*)((uintptr_t)udp_header + (uintptr_t)sizeof(struct udphdr));
struct dns_packet* dns_packet = (struct dns_packet*)buffer_data;

uint32_t ttl = 0;
uint32_t address = 0;

if( dns_packet->header.qr == QR_RESPONSE &&
dns_packet->header.opcode == OPCODE_QUERY &&
dns_packet->header.tc == 0 &&
dns_packet->header.rcode == 0 &&
dns_packet->header.ancount == __bswap_16(1)){
size_t current_index_data = 0;

/* ignore name */
if(dns_packet->data[current_index_data] & 0xc0){ /* pointer */
current_index_data += 2;
}else{
while(dns_packet->data[current_index_data] != 0){
current_index_data += dns_packet->data[current_index_data] + 1;
}
current_index_data++;
}

/* ignore question */
current_index_data += sizeof(uint16_t) * 2;

/* ignore name */
if(dns_packet->data[current_index_data] & 0xc0){ /* pointer */
current_index_data += 2;
}else{
while(dns_packet->data[current_index_data] != 0){
current_index_data += dns_packet->data[current_index_data] + 1;
}
}

if(*(uint16_t*)&dns_packet->data[current_index_data] == __bswap_16(1)){ // Answer is a Type A query (host address)
current_index_data += sizeof(uint16_t);
if(*(uint16_t*)&dns_packet->data[current_index_data] == __bswap_16(1)){ // Answer is class IN (Internet address)
current_index_data += sizeof(uint16_t);
ttl = __bswap_32(*(uint32_t*)&dns_packet->data[current_index_data]); // Response is valid for x seconds
current_index_data += sizeof(uint32_t);
if(*(uint16_t*)&dns_packet->data[current_index_data] == __bswap_16(4)){ // Address is  bytes long
current_index_data += sizeof(uint16_t);
address = __bswap_32(*(uint32_t*)&dns_packet->data[current_index_data]);
}
}
}

}
struct dns_request* request = vector_get(dns_requests, dns_packet->header.id);
if(request != NULL){
request->address = address;
request->ttl = ttl;
request->error = dns_packet->header.rcode;
request->have_response = true;
}
}

int init_dns(void){
dns_requests = vector_create();

udp_listen_port(DNS_PORT, &receive_dns_info, NULL);
return 0;
}

int dns_resolve_ip(net_device_t* net_device, char* name, uint32_t* address, uint32_t* ttl, uint8_t* error){
assert(dns_requests);

net_device_internal_t* internal = (net_device_internal_t*)net_device->external_data;

size_t dot_count = 1;
size_t name_length = strlen(name);
for(size_t i = 0; i < name_length; i++){
if(name[i] == '.'){
dot_count++;
}
}

volatile struct dns_request request;
request.have_response = false;

uint64_t request_index = vector_push(dns_requests, (void*)&request);

if(request_index > UINT16_MAX){
vector_remove(dns_requests, request_index);
return -1;
}

size_t dns_packet_size = sizeof(struct dns_packet) + dot_count * sizeof(uint8_t) + name_length + 1 + sizeof(uint16_t) + sizeof(uint16_t);
struct dns_packet* dns_packet = (struct dns_packet*)malloc(dns_packet_size);
dns_packet->header.id = request_index;
dns_packet->header.qr = QR_QUERY;
dns_packet->header.opcode = OPCODE_QUERY;
dns_packet->header.aa = AA_NONAUTHORITY;
dns_packet->header.tc = 0;
dns_packet->header.rd = 1;
dns_packet->header.ra = 1;
dns_packet->header.z = 0;
dns_packet->header.rcode = 0;
dns_packet->header.qdcount = __bswap_16(1);
dns_packet->header.ancount = __bswap_16(0);
dns_packet->header.nscount = __bswap_16(0);
dns_packet->header.arcount = __bswap_16(0);

size_t current_index_data = 0;

char* token = (char*)name;
while(token != NULL){
char* next_dot = strchr(token, '.');
char* current_dot = token;
if(next_dot){
*next_dot = '\0';
token = next_dot + sizeof(char);
}else{
token = NULL;
}

size_t token_length = strlen(current_dot);
dns_packet->data[current_index_data] = token_length;
current_index_data++;
memcpy(&dns_packet->data[current_index_data], current_dot, token_length);
current_index_data += token_length;
}

dns_packet->data[current_index_data] = 0;
current_index_data++;

*(uint16_t*)&dns_packet->data[current_index_data] = __bswap_16(1);
current_index_data += sizeof(uint16_t);
*(uint16_t*)&dns_packet->data[current_index_data] = __bswap_16(1);

generate_udp_packet(net_device, internal->dns_ip, DNS_PORT, DNS_PORT, dns_packet_size, dns_packet);

int64_t timeout = 1000; // in ms
while(!request.have_response && timeout > 0){
timeout--;
sleep_us(1000);
}

if(timeout == 0){
*address = 0;
*ttl = 0;
*error = 6; // we add our error code : timeout
}else{
*address = request.address;
*ttl = request.ttl;
*error = request.error;
}

vector_remove(dns_requests, request_index);

return 0;
}
12 changes: 12 additions & 0 deletions sources/core/modules/net/source/dns.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef _MODULE_NET_DNS_H
#define _MODULE_NET_DNS_H

#include <dns_header.h>
#include <global/modules.h>

int init_dns(void);

int dns_resolve_ip(net_device_t* net_device, char* name, uint32_t* address, uint32_t* ttl, uint8_t* error);


#endif // _MODULE_NET_DNS_H
38 changes: 38 additions & 0 deletions sources/core/modules/net/source/dns_header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#define DNS_PORT 53

#define QR_QUERY 0
#define QR_RESPONSE 1

#define OPCODE_QUERY 0
#define OPCODE_IQUERY 1
#define OPCODE_STATUS 2

#define AA_NONAUTHORITY 0
#define AA_AUTHORITY 1

struct dns_header{
uint16_t id;

uint8_t rd:1;
uint8_t tc:1;
uint8_t aa:1;
uint8_t opcode:4;
uint8_t qr:1;

uint8_t rcode:4;
uint8_t cd:1;
uint8_t ad:1;
uint8_t z:1;
uint8_t ra:1;

uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};


struct dns_packet{
struct dns_header header;
uint8_t data[];
};
2 changes: 2 additions & 0 deletions sources/core/modules/net/source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <ip.c>
#include <arp.c>
#include <dns.c>
#include <tcp.c>
#include <udp.c>
#include <dhcp.c>
Expand All @@ -17,6 +18,7 @@ int init(int argc, char* args[]){
assert(!init_arp());
assert(!init_udp());
assert(!init_tcp());
assert(!init_dns());
assert(!init_dhcp());
assert(!init_ethernet());
assert(!interface_init());
Expand Down
2 changes: 2 additions & 0 deletions sources/core/modules/net/source/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <ip.h>
#include <arp.h>
#include <dns.h>
#include <tcp.h>
#include <udp.h>
#include <dhcp.h>
Expand All @@ -15,6 +16,7 @@
#include <lib/vector.h>
#include <lib/assert.h>
#include <lib/memory.h>
#include <lib/string.h>
#include <global/heap.h>
#include <global/modules.h>

Expand Down

0 comments on commit 435b762

Please sign in to comment.