// File: davidgfnet[P]tadns/tadns.cc
// Function: DNSResolver::parse_udp(unsigned char const*, int)
void DNSResolver::parse_udp(const unsigned char *pkt, int len) {
    Query *q;
    struct header *header = (struct header *) pkt;

    /* Return if we did not send that query */
    if ((q = find_active_query(ntohs(header->tid))) == NULL)
        return;

    /* Actually parse the packet */
    auto dnsp = parse_udp_packet(pkt, len);

    std::vector< std::tuple<unsigned, void*, std::string, enum dns_record_type, dns_callback_t> > deferred;
    if (ntohs(header->nqueries) != 1)
        /* We sent 1 query. We want to see more that 1 answer. */
        call_user_rec(q, DNS_ERROR);
    else if ((header->nanswers | header->nauth | header->nother) == 0)
        /* Received 0 answers */
        call_user_rec(q, DNS_DOES_NOT_EXIST);
    else if (dnsp.questions.size() == 0 || dnsp.questions[0].name != q->name)
        /* Check whether the query matches at all! */
        call_user_rec(q, DNS_ERROR);
    else {
        struct cache_entry entry;
        entry.hits = 0;
        entry.expire = std::numeric_limits<time_t>::max();
        entry.replies = dnsp.answers;

        for (const auto &e: dnsp.answers)
            entry.expire = std::min(time(NULL) + (time_t)e.ttl, entry.expire);

        // Detected some 0 TTL answers, that's an issue cause we rely on the cache as an intermediate
        // structure. That works as long as ttls are significantly bigger than DNS response latency
        entry.expire = std::max(time(NULL) + MIN_TTL_TIME, entry.expire);

        // Insert finding in the cache
        auto cacheentry = std::make_pair(q->name, q->qtype);
        cached.erase(cacheentry);
        auto res = cached.emplace(cacheentry, entry);

        /* If query has a dependant, do not notify the user but re-schedule it */
        if (q->deps.size())
            for (auto de: q->deps)
                deferred.push_back(std::make_tuple(q->niter, de->ctx, de->name, (enum dns_record_type)de->qtype, de->callback));
        else
            call_user(this, q->name, q->qtype, &res.first->second, q->callback, q->ctx, DNS_OK);
    }

    // Delete from active queries and cleanup
    active.erase(dnsp.header.tid);
    ongoing.erase(std::make_pair(q->name, q->qtype));
    assert(active.size() == ongoing.size());

    // Remove the query from the deps list
    delete q;

    // Retry deferred queries
    for (auto df: deferred)
        resolveInt(std::get<0>(df), std::get<1>(df), std::get<2>(df), std::get<3>(df), std::get<4>(df));

    purgeCache();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2d0, %rsp            # imm = 0x2D0
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x260(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movzwl (%rax), %edi
callq 0x3570
movq -0x260(%rbp), %rdi
movzwl %ax, %esi
callq 0xa0f0
movq %rax, -0x20(%rbp)
cmpq $0x0, %rax
jne 0x68d3
jmp 0x705f
movq -0x10(%rbp), %rsi
movl -0x14(%rbp), %edx
leaq -0x68(%rbp), %rdi
callq 0x17660
leaq -0x80(%rbp), %rdi
callq 0xa150
movq -0x28(%rbp), %rax
movzwl 0x4(%rax), %edi
callq 0x3570
movzwl %ax, %eax
cmpl $0x1, %eax
je 0x6934
movq -0x260(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x3, %edx
callq 0x7090
jmp 0x6918
jmp 0x6dbd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x7068
movq -0x28(%rbp), %rax
movzwl 0x6(%rax), %eax
movq -0x28(%rbp), %rcx
movzwl 0x8(%rcx), %ecx
orl %ecx, %eax
movq -0x28(%rbp), %rcx
movzwl 0xa(%rcx), %ecx
orl %ecx, %eax
cmpl $0x0, %eax
jne 0x6971
movq -0x260(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x1, %edx
callq 0x7090
jmp 0x696c
jmp 0x6dbb
leaq -0x68(%rbp), %rdi
addq $0x10, %rdi
callq 0x4040
cmpq $0x0, %rax
je 0x69af
leaq -0x68(%rbp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x4070
movq %rax, %rdi
addq $0x8, %rdi
movq -0x20(%rbp), %rsi
addq $0x10, %rsi
callq 0xa170
testb $0x1, %al
jne 0x69af
jmp 0x69cb
movq -0x260(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x3, %edx
callq 0x7090
jmp 0x69c6
jmp 0x6db9
leaq -0xb8(%rbp), %rdi
movq %rdi, -0x268(%rbp)
callq 0xa1a0
movl $0x0, -0x98(%rbp)
callq 0xa1c0
movq -0x268(%rbp), %rdi
movq %rax, -0xa0(%rbp)
leaq -0x40(%rbp), %rsi
callq 0x3dd0
jmp 0x6a06
leaq -0x68(%rbp), %rax
addq $0x28, %rax
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rdi
callq 0x3cf0
movq %rax, -0xc8(%rbp)
movq -0xc0(%rbp), %rdi
callq 0x3d20
movq %rax, -0xd0(%rbp)
leaq -0xc8(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x3d50
testb $0x1, %al
jne 0x6a57
jmp 0x6adc
leaq -0xc8(%rbp), %rdi
callq 0x3d90
movq %rax, -0xd8(%rbp)
xorl %eax, %eax
movl %eax, %edi
callq 0x3310
movq -0xd8(%rbp), %rcx
movl 0x48(%rcx), %ecx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
leaq -0xa0(%rbp), %rsi
leaq -0xe0(%rbp), %rdi
callq 0xa1d0
movq %rax, -0x270(%rbp)
jmp 0x6aa3
movq -0x270(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xa0(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x3db0
jmp 0x6a3b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x6da8
xorl %eax, %eax
movl %eax, %edi
callq 0x3310
addq $0x3c, %rax
movq %rax, -0xe8(%rbp)
leaq -0xa0(%rbp), %rsi
leaq -0xe8(%rbp), %rdi
callq 0xa210
movq %rax, -0x278(%rbp)
jmp 0x6b0c
movq -0x278(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xa0(%rbp)
movq -0x20(%rbp), %rdx
movq %rdx, %rsi
addq $0x10, %rsi
addq $0xc, %rdx
leaq -0x110(%rbp), %rdi
callq 0x9c80
jmp 0x6b3a
movq -0x260(%rbp), %rdi
addq $0xa0, %rdi
leaq -0x110(%rbp), %rsi
callq 0xa010
jmp 0x6b56
movq -0x260(%rbp), %rdi
addq $0xa0, %rdi
leaq -0x110(%rbp), %rsi
leaq -0xb8(%rbp), %rdx
callq 0xa250
movb %dl, -0x281(%rbp)
movq %rax, -0x280(%rbp)
jmp 0x6b86
movb -0x281(%rbp), %al
movq -0x280(%rbp), %rcx
movq %rcx, -0x130(%rbp)
movb %al, -0x128(%rbp)
movq -0x130(%rbp), %rax
movq %rax, -0x120(%rbp)
movb -0x128(%rbp), %al
movb %al, -0x118(%rbp)
movq -0x20(%rbp), %rdi
addq $0x40, %rdi
callq 0xa2a0
cmpq $0x0, %rax
je 0x6ced
movq -0x20(%rbp), %rax
addq $0x40, %rax
movq %rax, -0x138(%rbp)
movq -0x138(%rbp), %rdi
callq 0xa2c0
movq %rax, -0x140(%rbp)
movq -0x138(%rbp), %rdi
callq 0xa2f0
movq %rax, -0x148(%rbp)
leaq -0x140(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0xa320
testb $0x1, %al
jne 0x6c22
jmp 0x6ce8
leaq -0x140(%rbp), %rdi
callq 0xa350
movq (%rax), %rax
movq %rax, -0x150(%rbp)
movq -0x20(%rbp), %rsi
addq $0x8, %rsi
movq -0x150(%rbp), %rax
movq %rax, %rdx
addq $0x30, %rdx
movq %rax, %rcx
addq $0x10, %rcx
movzwl 0xc(%rax), %eax
movl %eax, -0x194(%rbp)
movq -0x150(%rbp), %r9
addq $0x38, %r9
leaq -0x190(%rbp), %rdi
leaq -0x194(%rbp), %r8
callq 0xa3a0
jmp 0x6c7f
leaq -0x80(%rbp), %rdi
leaq -0x190(%rbp), %rsi
callq 0xa370
jmp 0x6c91
leaq -0x190(%rbp), %rdi
callq 0xa3f0
leaq -0x140(%rbp), %rdi
callq 0xa410
jmp 0x6c06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x6d9c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x190(%rbp), %rdi
callq 0xa3f0
jmp 0x6d9c
jmp 0x6d82
movq -0x20(%rbp), %rsi
addq $0x10, %rsi
leaq -0x1b8(%rbp), %rdi
callq 0x3160
jmp 0x6d03
movq -0x20(%rbp), %rax
movzwl 0xc(%rax), %eax
movl %eax, -0x288(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x9f20
movq -0x260(%rbp), %rdi
movl -0x288(%rbp), %edx
movq %rax, %rcx
addq $0x28, %rcx
movq -0x20(%rbp), %rax
movq 0x30(%rax), %r9
movq 0x38(%rax), %r8
movq %rsp, %rax
movl $0x0, (%rax)
leaq -0x1b8(%rbp), %rsi
callq 0x7190
jmp 0x6d54
leaq -0x1b8(%rbp), %rdi
callq 0x3200
jmp 0x6d82
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x1b8(%rbp), %rdi
callq 0x3200
jmp 0x6d9c
leaq -0x110(%rbp), %rdi
callq 0x9ab0
leaq -0xb8(%rbp), %rdi
callq 0xa440
jmp 0x6db9
leaq -0x110(%rbp), %rdi
callq 0x9ab0
leaq -0xb8(%rbp), %rdi
callq 0xa440
jmp 0x7068
jmp 0x6dbb
jmp 0x6dbd
movq -0x260(%rbp), %rdi
addq $0x38, %rdi
leaq -0x68(%rbp), %rsi
callq 0x9e10
jmp 0x6dd3
movq -0x260(%rbp), %rax
addq $0x70, %rax
movq %rax, -0x290(%rbp)
movq -0x20(%rbp), %rdx
movq %rdx, %rsi
addq $0x10, %rsi
addq $0xc, %rdx
leaq -0x1e0(%rbp), %rdi
callq 0x9c80
jmp 0x6e02
movq -0x290(%rbp), %rdi
leaq -0x1e0(%rbp), %rsi
callq 0x9c50
jmp 0x6e17
leaq -0x1e0(%rbp), %rdi
callq 0x9ab0
movq -0x260(%rbp), %rdi
addq $0x38, %rdi
callq 0x9e40
movq -0x260(%rbp), %rdi
movq %rax, -0x298(%rbp)
addq $0x70, %rdi
callq 0x9e60
movq %rax, %rcx
movq -0x298(%rbp), %rax
cmpq %rcx, %rax
jne 0x6e5b
jmp 0x6e9d
leaq 0x12226(%rip), %rdi     # 0x19088
leaq 0x1223f(%rip), %rsi     # 0x190a8
movl $0x186, %edx            # imm = 0x186
leaq 0x1226b(%rip), %rcx     # 0x190e0
callq 0x3210
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x9ab0
jmp 0x7068
movq -0x20(%rbp), %rax
movq %rax, -0x2a0(%rbp)
cmpq $0x0, %rax
je 0x6ecb
movq -0x2a0(%rbp), %rdi
callq 0x9cc0
movq -0x2a0(%rbp), %rdi
movl $0x78, %esi
callq 0x3360
leaq -0x80(%rbp), %rax
movq %rax, -0x1e8(%rbp)
movq -0x1e8(%rbp), %rdi
callq 0xa460
movq %rax, -0x1f0(%rbp)
movq -0x1e8(%rbp), %rdi
callq 0xa490
movq %rax, -0x1f8(%rbp)
leaq -0x1f0(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0xa4c0
testb $0x1, %al
jne 0x6f18
jmp 0x703f
leaq -0x1f0(%rbp), %rdi
callq 0xa500
movq %rax, %rsi
leaq -0x238(%rbp), %rdi
callq 0xa520
jmp 0x6f35
leaq -0x238(%rbp), %rdi
movq %rdi, -0x2b0(%rbp)
callq 0xa550
movq -0x2b0(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x2b4(%rbp)
callq 0xa570
movq -0x2b0(%rbp), %rdi
movq (%rax), %rax
movq %rax, -0x2a8(%rbp)
callq 0xa590
movq %rax, %rsi
leaq -0x258(%rbp), %rdi
callq 0x3160
jmp 0x6f83
leaq -0x238(%rbp), %rdi
movq %rdi, -0x2c0(%rbp)
callq 0xa5b0
movq -0x2c0(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x2b8(%rbp)
callq 0xa5d0
movq -0x260(%rbp), %rdi
movl -0x2b4(%rbp), %esi
movq -0x2a8(%rbp), %rdx
movl -0x2b8(%rbp), %r8d
movq (%rax), %r9
leaq -0x258(%rbp), %rcx
callq 0x7260
jmp 0x6fd6
leaq -0x258(%rbp), %rdi
callq 0x3200
leaq -0x238(%rbp), %rdi
callq 0xa3f0
leaq -0x1f0(%rbp), %rdi
callq 0xa5f0
jmp 0x6efc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
jmp 0x7031
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x88(%rbp)
movl %eax, -0x8c(%rbp)
leaq -0x258(%rbp), %rdi
callq 0x3200
leaq -0x238(%rbp), %rdi
callq 0xa3f0
jmp 0x7068
movq -0x260(%rbp), %rdi
callq 0x6640
jmp 0x704d
leaq -0x80(%rbp), %rdi
callq 0xa610
leaq -0x68(%rbp), %rdi
callq 0x4120
addq $0x2d0, %rsp            # imm = 0x2D0
popq %rbp
retq
leaq -0x80(%rbp), %rdi
callq 0xa610
leaq -0x68(%rbp), %rdi
callq 0x4120
movq -0x88(%rbp), %rdi
callq 0x3530
nopw %cs:(%rax,%rax)