// File: davidgfnet[P]tadns/tadns.cc
// Function: DNSResolver::getNSipaddr(unsigned int, unsigned int, std::vector<dns_record, std::allocator<dns_record>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, void*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, dns_record_type, void (*)(dns_cb_data*))
std::string
DNSResolver::getNSipaddr(unsigned level, unsigned niter, std::vector<struct dns_record> recs,
                         std::string dom, void *ctx, std::string name,
                         enum dns_record_type qtype, dns_callback_t callback) {

    // Filter all the NS records
    std::vector<std::string> nsrecs;
    std::unordered_map<std::string, std::string> arecs;
    for (const auto & e: recs) {
        if (e.name == dom && e.rtype == DNS_NS_RECORD)
            nsrecs.push_back(e.addr);
        if (e.rtype == DNS_A_RECORD)
            arecs[e.name] = e.addr;
    }

    // If we have no NS servers, it gets a bit more interesting.
    // According to rfc7816 (Qname minimization) we should need to go one level up
    // trying the same server
    if (!nsrecs.size())
        return "-";   // Hack, shame on me

    // Get a random permutation to avoid banging the same server
    std::random_shuffle(nsrecs.begin(), nsrecs.end());

    // Now go and check whether we have the A adress for them (in response)
    for (const auto & e: nsrecs)
        if (arecs.count(e))
            return arecs.at(e);

    // Seems like we don't have it in the packet, check the query cache
    std::vector<std::string> ipaddrs;
    int totry = -1;
    //for (const auto & e: nsrecs) {
    for (unsigned i = 0; i < nsrecs.size(); i++) {
        struct cache_entry *nsentry = find_cached_query(DNS_A_RECORD, nsrecs[i]);
        if (nsentry != NULL) {
            // Get any valid IP address (random)
            for (const auto & aent: nsentry->replies)
                if (aent.name == nsrecs[i] && aent.rtype == DNS_A_RECORD)
                    ipaddrs.push_back(aent.addr);
        }
        else
            totry = i;
    }
    // Pick a random one if any, a bit biased here
    if (ipaddrs.size())
        return ipaddrs[std::rand() % ipaddrs.size()];

    // Now, packet was useless, cache too, issue a request for ips
    // Prefetch all of them for better balancing and stuff
    #ifdef DO_DNS_PREFETCH
    if (level <= DO_DNS_PREFETCH) {
        for (const auto & e: nsrecs)
            this->queue(niter, e, NULL, DNS_A_RECORD, NULL);
    }
    #endif

    if (totry >= 0) {
        Query * oq = createQuery(niter, ctx, name, qtype, callback);
        this->queue(niter, nsrecs[totry], oq, DNS_A_RECORD, NULL);
        return "";
    }
    else {
        // None of the NS servers are really up for this!
        call_user(this, name, qtype, NULL, callback, ctx, DNS_DOES_NOT_EXIST);
    }
    return "";
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2d0, %rsp            # imm = 0x2D0
movq %r9, -0x230(%rbp)
movq %r8, -0x208(%rbp)
movq %rdi, -0x228(%rbp)
movq %rdi, %rax
movq %rax, -0x220(%rbp)
movq 0x28(%rbp), %rax
movl 0x20(%rbp), %eax
movq 0x18(%rbp), %rax
movq %rax, -0x218(%rbp)
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %ecx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movq %r9, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x210(%rbp)
leaq -0x40(%rbp), %rdi
callq 0xa710
leaq -0x78(%rbp), %rdi
callq 0xa9d0
movq -0x208(%rbp), %r8
movq %r8, -0x80(%rbp)
movq -0x80(%rbp), %rdi
callq 0x3cf0
movq %rax, -0x88(%rbp)
movq -0x80(%rbp), %rdi
callq 0x3d20
movq %rax, -0x90(%rbp)
leaq -0x88(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x3d50
testb $0x1, %al
jne 0x808a
jmp 0x8156
leaq -0x88(%rbp), %rdi
callq 0x3d90
movq -0x230(%rbp), %rsi
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rdi
addq $0x8, %rdi
callq 0xa9f0
testb $0x1, %al
jne 0x80ba
jmp 0x80f5
movq -0x98(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x80f5
movq -0x98(%rbp), %rsi
addq $0x28, %rsi
leaq -0x40(%rbp), %rdi
callq 0xa760
jmp 0x80dc
jmp 0x80f5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x88df
movq -0x98(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x8143
movq -0x98(%rbp), %rsi
movq %rsi, %rax
addq $0x28, %rax
movq %rax, -0x240(%rbp)
addq $0x8, %rsi
leaq -0x78(%rbp), %rdi
callq 0xaa80
movq %rax, -0x238(%rbp)
jmp 0x812c
movq -0x240(%rbp), %rsi
movq -0x238(%rbp), %rdi
callq 0x3040
jmp 0x8141
jmp 0x8143
jmp 0x8145
leaq -0x88(%rbp), %rdi
callq 0x3db0
jmp 0x806e
leaq -0x40(%rbp), %rdi
callq 0xa7d0
cmpq $0x0, %rax
jne 0x81d2
leaq -0xa5(%rbp), %rdi
movq %rdi, -0x248(%rbp)
callq 0x3540
movq -0x228(%rbp), %rdi
movq -0x248(%rbp), %rdx
leaq 0x10fad(%rip), %rsi     # 0x1913a
callq 0xaab0
jmp 0x8194
leaq -0xa5(%rbp), %rdi
callq 0x33b0
movl $0x1, -0xac(%rbp)
jmp 0x88bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0xa5(%rbp), %rdi
callq 0x33b0
jmp 0x88df
leaq -0x40(%rbp), %rdi
movq %rdi, -0x250(%rbp)
callq 0xac30
movq -0x250(%rbp), %rdi
movq %rax, -0xb8(%rbp)
callq 0xac60
movq %rax, -0xc0(%rbp)
movq -0xb8(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0xab60
jmp 0x8211
leaq -0x40(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rdi
callq 0xac30
movq %rax, -0xd0(%rbp)
movq -0xc8(%rbp), %rdi
callq 0xac60
movq %rax, -0xd8(%rbp)
leaq -0xd0(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0xac90
testb $0x1, %al
jne 0x825e
jmp 0x82e7
leaq -0xd0(%rbp), %rdi
callq 0xacd0
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rsi
leaq -0x78(%rbp), %rdi
callq 0xacf0
movq %rax, -0x258(%rbp)
jmp 0x828a
movq -0x258(%rbp), %rax
cmpq $0x0, %rax
je 0x82d4
movq -0xe0(%rbp), %rsi
leaq -0x78(%rbp), %rdi
callq 0xad20
movq %rax, -0x260(%rbp)
jmp 0x82b0
movq -0x260(%rbp), %rsi
movq -0x228(%rbp), %rdi
callq 0x3160
jmp 0x82c5
movl $0x1, -0xac(%rbp)
jmp 0x88bd
jmp 0x82d6
leaq -0xd0(%rbp), %rdi
callq 0xad50
jmp 0x8242
leaq -0xf8(%rbp), %rdi
callq 0xa710
movl $0xffffffff, -0xfc(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x100(%rbp)
movl -0x100(%rbp), %eax
movq %rax, -0x268(%rbp)
leaq -0x40(%rbp), %rdi
callq 0xa7d0
movq %rax, %rcx
movq -0x268(%rbp), %rax
cmpq %rcx, %rax
jae 0x84ce
movl -0x100(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0xad70
movq %rax, %rsi
leaq -0x128(%rbp), %rdi
callq 0x3160
jmp 0x8352
movq -0x210(%rbp), %rdi
movl $0x1, %esi
leaq -0x128(%rbp), %rdx
callq 0x62a0
movq %rax, -0x270(%rbp)
jmp 0x8373
leaq -0x128(%rbp), %rdi
callq 0x3200
movq -0x270(%rbp), %rax
movq %rax, -0x108(%rbp)
cmpq $0x0, -0x108(%rbp)
je 0x84ac
movq -0x108(%rbp), %rax
movq %rax, -0x130(%rbp)
movq -0x130(%rbp), %rdi
callq 0x3cf0
movq %rax, -0x138(%rbp)
movq -0x130(%rbp), %rdi
callq 0x3d20
movq %rax, -0x140(%rbp)
leaq -0x138(%rbp), %rdi
leaq -0x140(%rbp), %rsi
callq 0x3d50
testb $0x1, %al
jne 0x83eb
jmp 0x84aa
leaq -0x138(%rbp), %rdi
callq 0x3d90
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x278(%rbp)
movl -0x100(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0xad70
movq -0x278(%rbp), %rdi
movq %rax, %rsi
callq 0xa9f0
testb $0x1, %al
jne 0x8436
jmp 0x8497
movq -0x148(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x8497
movq -0x148(%rbp), %rsi
addq $0x28, %rsi
leaq -0xf8(%rbp), %rdi
callq 0xa760
jmp 0x845b
jmp 0x8497
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x88af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x128(%rbp), %rdi
callq 0x3200
jmp 0x88af
jmp 0x8499
leaq -0x138(%rbp), %rdi
callq 0x3db0
jmp 0x83cf
jmp 0x84b8
movl -0x100(%rbp), %eax
movl %eax, -0xfc(%rbp)
jmp 0x84ba
movl -0x100(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x100(%rbp)
jmp 0x8307
leaq -0xf8(%rbp), %rdi
callq 0xa7d0
cmpq $0x0, %rax
je 0x853f
callq 0x3100
cltq
movq %rax, -0x280(%rbp)
leaq -0xf8(%rbp), %rdi
movq %rdi, -0x288(%rbp)
callq 0xa7d0
movq -0x288(%rbp), %rdi
movq %rax, %rcx
movq -0x280(%rbp), %rax
xorl %edx, %edx
divq %rcx
movq %rdx, %rsi
callq 0xad70
movq -0x228(%rbp), %rdi
movq %rax, %rsi
callq 0x3160
jmp 0x8530
movl $0x1, -0xac(%rbp)
jmp 0x88a1
cmpl $0x2, -0x14(%rbp)
ja 0x8632
leaq -0x40(%rbp), %rax
movq %rax, -0x150(%rbp)
movq -0x150(%rbp), %rdi
callq 0xac30
movq %rax, -0x158(%rbp)
movq -0x150(%rbp), %rdi
callq 0xac60
movq %rax, -0x160(%rbp)
leaq -0x158(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0xac90
testb $0x1, %al
jne 0x8596
jmp 0x8630
leaq -0x158(%rbp), %rdi
callq 0xacd0
movq %rax, -0x168(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x28c(%rbp)
movq -0x168(%rbp), %rsi
leaq -0x188(%rbp), %rdi
callq 0x3160
jmp 0x85c7
movl -0x28c(%rbp), %esi
movq -0x210(%rbp), %rdi
xorl %eax, %eax
movl %eax, %r9d
leaq -0x188(%rbp), %rdx
movl $0x1, %r8d
movq %r9, %rcx
callq 0x8900
jmp 0x85f0
leaq -0x188(%rbp), %rdi
callq 0x3200
leaq -0x158(%rbp), %rdi
callq 0xad50
jmp 0x857a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x188(%rbp), %rdi
callq 0x3200
jmp 0x88af
jmp 0x8632
cmpl $0x0, -0xfc(%rbp)
jl 0x87c9
movq -0x218(%rbp), %rsi
movl -0x18(%rbp), %eax
movl %eax, -0x29c(%rbp)
movq 0x10(%rbp), %rax
movq %rax, -0x298(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x3160
jmp 0x8668
movq -0x298(%rbp), %rdx
movl -0x29c(%rbp), %esi
movq -0x210(%rbp), %rdi
movl 0x20(%rbp), %r8d
movq 0x28(%rbp), %r9
leaq -0x1b0(%rbp), %rcx
callq 0x8d20
movq %rax, -0x2a8(%rbp)
jmp 0x8699
leaq -0x1b0(%rbp), %rdi
callq 0x3200
movq -0x2a8(%rbp), %rax
movq %rax, -0x190(%rbp)
movl -0x18(%rbp), %eax
movl %eax, -0x2ac(%rbp)
movslq -0xfc(%rbp), %rsi
leaq -0x40(%rbp), %rdi
callq 0xad70
movq %rax, %rsi
leaq -0x1d0(%rbp), %rdi
callq 0x3160
jmp 0x86dd
movl -0x2ac(%rbp), %esi
movq -0x210(%rbp), %rdi
movq -0x190(%rbp), %rcx
xorl %eax, %eax
movl %eax, %r9d
leaq -0x1d0(%rbp), %rdx
movl $0x1, %r8d
callq 0x8900
jmp 0x870a
leaq -0x1d0(%rbp), %rdi
callq 0x3200
leaq -0x1d1(%rbp), %rdi
movq %rdi, -0x2b8(%rbp)
callq 0x3540
movq -0x228(%rbp), %rdi
movq -0x2b8(%rbp), %rdx
leaq 0x108fa(%rip), %rsi     # 0x19038
callq 0xaab0
jmp 0x8745
leaq -0x1d1(%rbp), %rdi
callq 0x33b0
movl $0x1, -0xac(%rbp)
jmp 0x88a1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x3200
jmp 0x88af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x3200
jmp 0x88af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x1d1(%rbp), %rdi
callq 0x33b0
jmp 0x88af
movq -0x218(%rbp), %rsi
leaq -0x1f8(%rbp), %rdi
callq 0x3160
jmp 0x87de
movq -0x210(%rbp), %rdi
movzwl 0x20(%rbp), %edx
movq 0x28(%rbp), %r8
movq 0x10(%rbp), %r9
movq %rsp, %rax
movl $0x1, (%rax)
xorl %eax, %eax
movl %eax, %ecx
leaq -0x1f8(%rbp), %rsi
callq 0x7190
jmp 0x880c
leaq -0x1f8(%rbp), %rdi
callq 0x3200
jmp 0x883a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x1f8(%rbp), %rdi
callq 0x3200
jmp 0x88af
leaq -0x1f9(%rbp), %rdi
movq %rdi, -0x2c0(%rbp)
callq 0x3540
movq -0x228(%rbp), %rdi
movq -0x2c0(%rbp), %rdx
leaq 0x107d6(%rip), %rsi     # 0x19038
callq 0xaab0
jmp 0x8869
leaq -0x1f9(%rbp), %rdi
callq 0x33b0
movl $0x1, -0xac(%rbp)
jmp 0x88a1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0x1f9(%rbp), %rdi
callq 0x33b0
jmp 0x88af
leaq -0xf8(%rbp), %rdi
callq 0xa970
jmp 0x88bd
leaq -0xf8(%rbp), %rdi
callq 0xa970
jmp 0x88df
leaq -0x78(%rbp), %rdi
callq 0xad90
leaq -0x40(%rbp), %rdi
callq 0xa970
movq -0x220(%rbp), %rax
addq $0x2d0, %rsp            # imm = 0x2D0
popq %rbp
retq
leaq -0x78(%rbp), %rdi
callq 0xad90
leaq -0x40(%rbp), %rdi
callq 0xa970
movq -0xa0(%rbp), %rdi
callq 0x3530
nopl (%rax)