// File: davidgfnet[P]tadns/tadns.cc
// Function: DNSResolver::send_dns_packet(Query*, sockaddr*)
void DNSResolver::send_dns_packet(Query *query, struct sockaddr * dnss) {
    struct dns_packet outp;

    /* Prepare DNS packet header */
    outp.header.tid      = getNewTid();
    outp.header.flags    = 0x100;        /* Haha. guess what it is */
    outp.header.nqueries = 1;            /* Just one query */
    outp.header.nanswers = 0;
    outp.header.nauth    = 0;
    outp.header.nother   = 0;

    struct dns_question q;
    q.qtype = query->qtype;
    q.qclass = 0x0001;
    q.name = query->name;
    outp.questions.push_back(q);

    uint8_t pkt[DNS_PACKET_LEN];
    unsigned psize = serialize_udp_packet(&outp, pkt);
    assert(psize < sizeof(pkt));

    /* FIXME Add some queueing mechanism for packets? */
    if (dnss)
        pkts_auth_servers++;
    else
        pkts_dns_servers++;

    /* Pick a server to send query to */
    struct sockaddr * serv = dnss ? dnss : getNextServer();
    int ssock = serv->sa_family == AF_INET ? sock4 : sock6;
    int addrl = serv->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);

    if (sendto(ssock, pkt, psize, 0, serv, addrl) != psize) {
        call_user_rec(query, DNS_NET_ERROR);
        delete query;
    } else {
        auto lookup = std::make_pair(query->name, query->qtype);
        active.emplace(outp.header.tid, query);
        ongoing[lookup] = query;
        assert(active.size() == ongoing.size());
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x950, %rsp            # imm = 0x950
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x8f0(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x4150
movq -0x8f0(%rbp), %rdi
callq 0x9180
movw %ax, -0x8e2(%rbp)
jmp 0x9230
movw -0x8e2(%rbp), %ax
movw %ax, -0x58(%rbp)
movw $0x100, -0x56(%rbp)     # imm = 0x100
movw $0x1, -0x54(%rbp)
movw $0x0, -0x52(%rbp)
movw $0x0, -0x50(%rbp)
movw $0x0, -0x4e(%rbp)
leaq -0x90(%rbp), %rdi
callq 0xb1d0
movq -0x10(%rbp), %rax
movw 0xc(%rax), %ax
movw %ax, -0x90(%rbp)
movw $0x1, -0x8e(%rbp)
movq -0x10(%rbp), %rsi
addq $0x10, %rsi
leaq -0x88(%rbp), %rdi
callq 0x3040
jmp 0x9293
leaq -0x48(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x40b0
jmp 0x92a5
leaq -0x58(%rbp), %rdi
leaq -0x890(%rbp), %rsi
callq 0x17df0
movl %eax, -0x8f4(%rbp)
jmp 0x92bd
movl -0x8f4(%rbp), %eax
movl %eax, -0x894(%rbp)
movl -0x894(%rbp), %eax
cmpq $0x800, %rax            # imm = 0x800
jae 0x92d9
jmp 0x931a
leaq 0xff48(%rip), %rdi      # 0x19228
leaq 0xfdc1(%rip), %rsi      # 0x190a8
movl $0x2c9, %edx            # imm = 0x2C9
leaq 0xff49(%rip), %rcx      # 0x1923c
callq 0x3210
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x95b8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x95ac
cmpq $0x0, -0x18(%rbp)
je 0x9333
movq -0x8f0(%rbp), %rax
movl 0x18(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x18(%rax)
jmp 0x9343
movq -0x8f0(%rbp), %rax
movl 0x14(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x14(%rax)
cmpq $0x0, -0x18(%rbp)
je 0x9357
movq -0x18(%rbp), %rax
movq %rax, -0x900(%rbp)
jmp 0x937c
movq -0x8f0(%rbp), %rdi
callq 0x6230
movq %rax, -0x908(%rbp)
jmp 0x936c
movq -0x908(%rbp), %rax
movq %rax, -0x900(%rbp)
jmp 0x937c
movq -0x900(%rbp), %rax
movq %rax, -0x8a0(%rbp)
movq -0x8a0(%rbp), %rax
movzwl (%rax), %eax
cmpl $0x2, %eax
jne 0x93ab
movq -0x8f0(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x90c(%rbp)
jmp 0x93bb
movq -0x8f0(%rbp), %rax
movl 0xc(%rax), %eax
movl %eax, -0x90c(%rbp)
movl -0x90c(%rbp), %eax
movl %eax, -0x8a4(%rbp)
movq -0x8a0(%rbp), %rax
movw (%rax), %ax
subw $0x2, %ax
movl $0x10, %ecx
movl $0x1c, %eax
cmovel %ecx, %eax
movl %eax, -0x8a8(%rbp)
movl -0x8a4(%rbp), %edi
movl -0x894(%rbp), %eax
movl %eax, %edx
movq -0x8a0(%rbp), %r8
movl -0x8a8(%rbp), %r9d
leaq -0x890(%rbp), %rsi
xorl %ecx, %ecx
callq 0x3080
movq %rax, -0x918(%rbp)
jmp 0x941b
movq -0x918(%rbp), %rax
movl -0x894(%rbp), %ecx
cmpq %rcx, %rax
je 0x9477
movq -0x8f0(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x4, %edx
callq 0x7090
jmp 0x9444
movq -0x10(%rbp), %rax
movq %rax, -0x920(%rbp)
cmpq $0x0, %rax
je 0x9472
movq -0x920(%rbp), %rdi
callq 0x9cc0
movq -0x920(%rbp), %rdi
movl $0x78, %esi
callq 0x3360
jmp 0x958e
movq -0x10(%rbp), %rdx
movq %rdx, %rsi
addq $0x10, %rsi
addq $0xc, %rdx
leaq -0x8d0(%rbp), %rdi
callq 0x9c80
jmp 0x9494
movq -0x8f0(%rbp), %rdi
addq $0x38, %rdi
leaq -0x58(%rbp), %rsi
leaq -0x10(%rbp), %rdx
callq 0xb1f0
movb %dl, -0x929(%rbp)
movq %rax, -0x928(%rbp)
jmp 0x94bb
movq -0x8f0(%rbp), %rdi
movb -0x929(%rbp), %al
movq -0x928(%rbp), %rcx
movq %rcx, -0x8e0(%rbp)
movb %al, -0x8d8(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x940(%rbp)
addq $0x70, %rdi
leaq -0x8d0(%rbp), %rsi
callq 0xb240
movq %rax, -0x938(%rbp)
jmp 0x9500
movq -0x8f0(%rbp), %rdi
movq -0x938(%rbp), %rax
movq -0x940(%rbp), %rcx
movq %rcx, (%rax)
addq $0x38, %rdi
callq 0x9e40
movq -0x8f0(%rbp), %rdi
movq %rax, -0x948(%rbp)
addq $0x70, %rdi
callq 0x9e60
movq %rax, %rcx
movq -0x948(%rbp), %rax
cmpq %rcx, %rax
jne 0x9549
jmp 0x9582
leaq 0xfb38(%rip), %rdi      # 0x19088
leaq 0xfb51(%rip), %rsi      # 0x190a8
movl $0x2dd, %edx            # imm = 0x2DD
leaq 0xfcd9(%rip), %rcx      # 0x1923c
callq 0x3210
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x8d0(%rbp), %rdi
callq 0x9ab0
jmp 0x95ac
leaq -0x8d0(%rbp), %rdi
callq 0x9ab0
leaq -0x90(%rbp), %rdi
callq 0x4750
leaq -0x58(%rbp), %rdi
callq 0x4120
addq $0x950, %rsp            # imm = 0x950
popq %rbp
retq
leaq -0x90(%rbp), %rdi
callq 0x4750
leaq -0x58(%rbp), %rdi
callq 0x4120
movq -0x60(%rbp), %rdi
callq 0x3530
nopw (%rax,%rax)