start working on the dns resolver
This commit is contained in:
@@ -7,8 +7,8 @@ func main[] : i64
|
|||||||
while true
|
while true
|
||||||
let pkt: net.UDPPacket = net.udp_receive(s, 60000)
|
let pkt: net.UDPPacket = net.udp_receive(s, 60000)
|
||||||
if pkt->size <= 0
|
if pkt->size <= 0
|
||||||
net.udp_free_packet(pkt)
|
net.UDPPacket.free(pkt)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
net.udp_send_to(s, pkt->source_addr, pkt->buffer, pkt->size)
|
net.udp_send_to(s, pkt->source_addr, pkt->buffer, pkt->size)
|
||||||
net.udp_free_packet(pkt)
|
net.UDPPacket.free(pkt)
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ impl Analyzer {
|
|||||||
pub fn new() -> Analyzer {
|
pub fn new() -> Analyzer {
|
||||||
Analyzer {
|
Analyzer {
|
||||||
functions: HashMap::from([
|
functions: HashMap::from([
|
||||||
("_builtin_heap_head".into(), -1),
|
("_builtin_heap_head".into(), 0),
|
||||||
("_builtin_heap_tail".into(), -1),
|
("_builtin_heap_tail".into(), 0),
|
||||||
("_builtin_read64".into(), -1),
|
("_builtin_read64".into(), 1),
|
||||||
("_builtin_set64".into(), -1),
|
("_builtin_set64".into(), 2),
|
||||||
("_builtin_syscall".into(), -1),
|
("_builtin_syscall".into(), -1),
|
||||||
("io.printf".into(), -1),
|
("io.printf".into(), -1),
|
||||||
("_builtin_environ".into(), -1),
|
("_builtin_environ".into(), 0),
|
||||||
]),
|
]),
|
||||||
constants: HashMap::new(),
|
constants: HashMap::new(),
|
||||||
structs: HashMap::new(),
|
structs: HashMap::new(),
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ func net.udp_listen[packed_host: i64, port: i64] : net.UDPSocket
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0
|
if _builtin_syscall(SYS_bind, s->fd, s->addr, 16) < 0
|
||||||
net.udp_close_and_free(s)
|
net.UDPSocket.close_and_free(s)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
return s
|
return s
|
||||||
@@ -130,12 +130,95 @@ func net.udp_receive[s: net.UDPSocket, size: i64] : net.UDPPacket
|
|||||||
pkt->size = _builtin_syscall(SYS_recvfrom, s->fd, pkt->buffer, size, 0, pkt->source_addr, ^addrlen)
|
pkt->size = _builtin_syscall(SYS_recvfrom, s->fd, pkt->buffer, size, 0, pkt->source_addr, ^addrlen)
|
||||||
return pkt
|
return pkt
|
||||||
|
|
||||||
func net.udp_close_and_free[s: net.UDPSocket] : void
|
func net.UDPSocket.close_and_free[s: net.UDPSocket] : void
|
||||||
_builtin_syscall(SYS_close, s->fd)
|
_builtin_syscall(SYS_close, s->fd)
|
||||||
mem.free(s->addr)
|
mem.free(s->addr)
|
||||||
mem.free(s)
|
mem.free(s)
|
||||||
|
|
||||||
func net.udp_free_packet[pkt: net.UDPPacket] : void
|
func net.UDPPacket.free[pkt: net.UDPPacket] : void
|
||||||
mem.free(pkt->buffer)
|
mem.free(pkt->buffer)
|
||||||
mem.free(pkt->source_addr)
|
mem.free(pkt->source_addr)
|
||||||
mem.free(pkt)
|
mem.free(pkt)
|
||||||
|
|
||||||
|
// https://implement-dns.wizardzines.com/book/part_1
|
||||||
|
struct net.DNSHeader
|
||||||
|
id: i64
|
||||||
|
flags: i64
|
||||||
|
num_questions: i64
|
||||||
|
num_answers: i64
|
||||||
|
num_authorities: i64
|
||||||
|
num_additionals: i64
|
||||||
|
|
||||||
|
struct net.DNSQuestion
|
||||||
|
name: io.Buffer
|
||||||
|
type: i64
|
||||||
|
class: i64
|
||||||
|
|
||||||
|
func net.DNSHeader.to_bytes[h: net.DNSHeader] : io.Buffer
|
||||||
|
let buf: io.Buffer = io.Buffer.alloc(12)
|
||||||
|
mem.write16be(buf->data + 0, h->id)
|
||||||
|
mem.write16be(buf->data + 2, h->flags)
|
||||||
|
mem.write16be(buf->data + 4, h->num_questions)
|
||||||
|
mem.write16be(buf->data + 6, h->num_answers)
|
||||||
|
mem.write16be(buf->data + 8, h->num_authorities)
|
||||||
|
mem.write16be(buf->data + 10, h->num_additionals)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
func net.DNSQuestion.to_bytes[h: net.DNSQuestion] : io.Buffer
|
||||||
|
let name_buf: io.Buffer = h->name
|
||||||
|
let buf: io.Buffer = io.Buffer.alloc(name_buf->size + 4)
|
||||||
|
mem.copy(name_buf->data, buf->data, name_buf->size)
|
||||||
|
buf->data[name_buf->size + 0] = (h->type >> 8) & 0xff
|
||||||
|
buf->data[name_buf->size + 1] = h->type & 0xff
|
||||||
|
buf->data[name_buf->size + 2] = (h->class >> 8) & 0xff
|
||||||
|
buf->data[name_buf->size + 3] = h->class & 0xff
|
||||||
|
return buf
|
||||||
|
|
||||||
|
func net.encode_dns_name[domain: str] : io.Buffer
|
||||||
|
let domain_len: i64 = str.len(domain)
|
||||||
|
let buf: io.Buffer = io.Buffer.alloc(domain_len + 2)
|
||||||
|
let out_pos: i64 = 0
|
||||||
|
let part_start: i64 = 0
|
||||||
|
let i: i64 = 0
|
||||||
|
while i <= domain_len
|
||||||
|
if i == domain_len || domain[i] == '.'
|
||||||
|
let part_len: i64 = i - part_start
|
||||||
|
buf->data[out_pos] = part_len & 0xff
|
||||||
|
out_pos = out_pos + 1
|
||||||
|
mem.copy(domain + part_start, buf->data + out_pos, part_len)
|
||||||
|
out_pos = out_pos + part_len
|
||||||
|
part_start = i + 1
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
buf->data[out_pos] = 0
|
||||||
|
return buf
|
||||||
|
|
||||||
|
const DNS_TYPE_A = 1
|
||||||
|
const DNS_CLASS_IN = 1
|
||||||
|
const DNS_RECURSION_DESIRED = 256
|
||||||
|
|
||||||
|
func net.build_dns_query[domain_name: str, record_type: i64] : io.Buffer
|
||||||
|
let h: net.DNSHeader = new net.DNSHeader
|
||||||
|
h->id = math.abs(os.urandom_i64()) % 65535
|
||||||
|
h->num_questions = 1
|
||||||
|
h->flags = DNS_RECURSION_DESIRED
|
||||||
|
|
||||||
|
let q: net.DNSQuestion = new net.DNSQuestion
|
||||||
|
let name: io.Buffer = net.encode_dns_name(domain_name)
|
||||||
|
q->name = name
|
||||||
|
q->type = record_type
|
||||||
|
q->class = DNS_CLASS_IN
|
||||||
|
|
||||||
|
let hb: io.Buffer = net.DNSHeader.to_bytes(h)
|
||||||
|
let qb: io.Buffer = net.DNSQuestion.to_bytes(q)
|
||||||
|
|
||||||
|
let out: io.Buffer = io.Buffer.alloc(hb->size + qb->size)
|
||||||
|
mem.copy(hb->data, out->data, hb->size)
|
||||||
|
mem.copy(qb->data, out->data + hb->size, qb->size)
|
||||||
|
|
||||||
|
mem.free(hb->data)
|
||||||
|
mem.free(qb->data)
|
||||||
|
mem.free(name->data)
|
||||||
|
mem.free(q->data)
|
||||||
|
mem.free(h->data)
|
||||||
|
return out
|
||||||
|
|||||||
@@ -183,9 +183,18 @@ func mem.write32[x: ptr, d: i64] : void
|
|||||||
x[2] = (d >> 16) & 0xff
|
x[2] = (d >> 16) & 0xff
|
||||||
x[3] = (d >> 24) & 0xff
|
x[3] = (d >> 24) & 0xff
|
||||||
|
|
||||||
|
func mem.write16[x: ptr, d: i64] : void
|
||||||
|
x[0] = d & 0xff
|
||||||
|
x[1] = (d >> 8) & 0xff
|
||||||
|
|
||||||
|
func mem.write16be[x: ptr, d: i64] : void
|
||||||
|
x[0] = (d >> 8) & 0xff
|
||||||
|
x[1] = d & 0xff
|
||||||
|
|
||||||
func mem.write64[x: ptr, d: i64] : void
|
func mem.write64[x: ptr, d: i64] : void
|
||||||
_builtin_set64(x, d)
|
_builtin_set64(x, d)
|
||||||
|
|
||||||
|
// see emit_prologue for the io.printf wrapper
|
||||||
func io._printf_impl[s: str, args: ptr] : void
|
func io._printf_impl[s: str, args: ptr] : void
|
||||||
while s[0]
|
while s[0]
|
||||||
if s[0] == '%'
|
if s[0] == '%'
|
||||||
@@ -205,6 +214,8 @@ func io._printf_impl[s: str, args: ptr] : void
|
|||||||
args = args + 8
|
args = args + 8
|
||||||
else if s[0] == '%'
|
else if s[0] == '%'
|
||||||
io.print_char('%')
|
io.print_char('%')
|
||||||
|
else if s[0] == 0
|
||||||
|
break
|
||||||
else
|
else
|
||||||
io.print_char(s[0])
|
io.print_char(s[0])
|
||||||
s = s + 1
|
s = s + 1
|
||||||
@@ -279,6 +290,12 @@ struct io.Buffer
|
|||||||
data: ptr
|
data: ptr
|
||||||
size: i64
|
size: i64
|
||||||
|
|
||||||
|
func io.Buffer.alloc[size: i64] : io.Buffer
|
||||||
|
let buffer: io.Buffer = new io.Buffer
|
||||||
|
buffer->size = size
|
||||||
|
buffer->data = mem.alloc(size)
|
||||||
|
return buffer
|
||||||
|
|
||||||
func io.read_binary_file[path: str] : io.Buffer
|
func io.read_binary_file[path: str] : io.Buffer
|
||||||
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
let fd: i64 = _builtin_syscall(SYS_openat, -100, path, 0, 0)
|
||||||
if fd < 0
|
if fd < 0
|
||||||
|
|||||||
Reference in New Issue
Block a user