// File: /workspace/github_c_makefile_star2_O2/bloomsource[P]dns_update/dns.c
// Function: proc_dns_query
void proc_dns_query( char* data, int len, char* ip, int port )
{
    dns_hdr req, rsp;
    char domain[MAX_DOMAIN+1];
    char buf[1024];
    int write_len;
    int qry_len;
    int qry_type, qry_class;
    int offset = 0;
    unsigned short slen;
    unsigned int   ilen;
    unsigned char bin_ip[4];
    int find;
    dns_node *node;
    
    //write_log( "recv dns data from %s:%d", ip, port );
    //write_log_hex( data, len );
    
    if( len < sizeof(dns_hdr) )
    {
        write_log( "recv dns data from %s:%d", ip, port );
        write_log_hex( data, len );
        write_log( "[WRN] dns pack size small, query abandon." );
        return;
    }
    
    memcpy( &req, data, sizeof(req) );
    req.flags   = ntohs( req.flags );
    req.qry_cnt = ntohs( req.qry_cnt );
    req.ans_cnt = ntohs( req.ans_cnt );
    req.auth_cnt= ntohs( req.auth_cnt );
    req.add_cnt = ntohs( req.add_cnt );
    
    if( req.flags & 0x8000 )
    {
        write_log( "recv dns data from %s:%d", ip, port );
        write_log_hex( data, len );
        write_log( "[WRN] dns query flag is not 1, query abandon." );
        return;
    }
    
    if( req.qry_cnt != 1 )
    {
        write_log( "recv dns data from %s:%d", ip, port );
        write_log_hex( data, len );
        write_log( "[WRN] dns query req cnt is not 1, query abandon." );
        return;
    }
    
    if( req.ans_cnt )
    {
        write_log( "recv dns data from %s:%d", ip, port );
        write_log_hex( data, len );
        write_log( "[WRN] dns ans_cnt not 0, query abandon." );
        return;
    }
    
    memset( domain, 0, sizeof(domain) );
    if( dns_resove_query( data + sizeof(req), len - sizeof(req), domain, &qry_type, &qry_class, &qry_len ) )
    {
        write_log( "recv dns data from %s:%d", ip, port );
        write_log_hex( data, len );
        write_log( "[WRN] dns query resolve domain failed, query abandon." );
        return ;
    }
    strlower( domain );
    
    write_log( "recv dns query from %-15s domain: %-20s type: %-3d class: %-3d", ip, domain, qry_type, qry_class );
    

    
    node = (dns_node*)rbtree_find( &domains, domain );
    if( node )
        find = 1;
    else
        find = 0;
    
    if( find == 0 )
    {
        write_log( "[WRN] domain %s not exist!", domain );
        return;
    }

    if( qry_type != 1 || qry_class != 1 ) //ipv4 only
    {
        write_log( "[WRN] dns query type/class not support." );
        find = 0;
    }
    
    

    rsp.id = req.id;
    rsp.flags = 0;
    rsp.flags |= 0x8000;
    if( !find )
        rsp.flags |= 0x03;
        
    rsp.flags = htons( rsp.flags );
    rsp.qry_cnt = htons( 1 );
    rsp.ans_cnt = find ? htons( 1 ) : 0;
    rsp.auth_cnt = 0;
    rsp.add_cnt = 0;
    
    /*------------ write response header ---------------*/
    memcpy( buf+offset, &rsp, sizeof(rsp) );
    offset+= sizeof(rsp );


    //-------------- write query ------------------------
    //write domain
    if( dns_write_domain( buf+offset, sizeof(buf)-sizeof(rsp), domain, &write_len ) )
        return;
    offset+= write_len;
    
    
    // write type
    slen = htons( qry_type );
    memcpy( buf + offset, &slen, sizeof(slen) );
    offset += sizeof(slen);
    
    //write class
    slen = htons( qry_class );
    memcpy( buf + offset, &slen, sizeof(slen) );
    offset += sizeof(slen);
    

    //--------------- write answer ------------------------
    if( !find )
        goto send_rsp;
        
    //answer name
    slen = htons( 0xc00c );
    memcpy( buf + offset, &slen, sizeof(slen) );
    offset += sizeof(slen);
    
    // write type
    slen = htons( 1 );
    memcpy( buf + offset, &slen, sizeof(slen) );
    offset += sizeof(slen);
    
    //write class
    slen = htons( 1 );
    memcpy( buf + offset, &slen, sizeof(slen) );
    offset += sizeof(slen);
    
    //write ttl
    ilen = htonl( 300 );
    memcpy( buf + offset, &ilen, sizeof(ilen) );
    offset += sizeof(ilen);
    
    //write address len
    slen = htons( 4 );
    memcpy( buf + offset, &slen, sizeof(slen) );
    offset += sizeof(slen);
    
    //write ip
    fill_binary_ip( bin_ip, node->ip );
    memcpy( buf + offset, bin_ip, 4 );
    offset += 4;
    
    
    send_rsp:
    //write_log( "dns response data:" );
    //write_log_hex( buf, offset );
    
    udp_send( dns_fd, ip, port, buf, offset );
    
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x528, %rsp            # imm = 0x528
movl %ecx, %ebx
movq %rdx, %r14
movl %esi, %r15d
movq %rdi, %r12
cmpl $0xb, %esi
ja 0x27ea
leaq 0x6936(%rip), %rdi      # 0x90fd
movq %r14, %rsi
movl %ebx, %edx
xorl %eax, %eax
callq 0x3281
movq %r12, %rdi
movl %r15d, %esi
callq 0x33ab
leaq 0x6931(%rip), %rdi      # 0x9116
jmp 0x287c
testb $-0x80, 0x2(%r12)
jne 0x2830
cmpw $0x100, 0x4(%r12)       # imm = 0x100
jne 0x2857
cmpw $0x0, 0x6(%r12)
je 0x2894
leaq 0x68ed(%rip), %rdi      # 0x90fd
movq %r14, %rsi
movl %ebx, %edx
xorl %eax, %eax
callq 0x3281
movq %r12, %rdi
movl %r15d, %esi
callq 0x33ab
leaq 0x6971(%rip), %rdi      # 0x919f
jmp 0x287c
leaq 0x68c6(%rip), %rdi      # 0x90fd
movq %r14, %rsi
movl %ebx, %edx
xorl %eax, %eax
callq 0x3281
movq %r12, %rdi
movl %r15d, %esi
callq 0x33ab
leaq 0x68eb(%rip), %rdi      # 0x9140
jmp 0x287c
leaq 0x689f(%rip), %rdi      # 0x90fd
movq %r14, %rsi
movl %ebx, %edx
xorl %eax, %eax
callq 0x3281
movq %r12, %rdi
movl %r15d, %esi
callq 0x33ab
leaq 0x68f2(%rip), %rdi      # 0x916e
xorl %eax, %eax
addq $0x528, %rsp            # imm = 0x528
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3281
movzwl (%r12), %ebp
leaq 0x20(%rsp), %r13
movl $0x100, %edx            # imm = 0x100
movq %r13, %rdi
xorl %esi, %esi
callq 0x2140
leaq 0xc(%r12), %rdi
leal -0xc(%r15), %esi
leaq 0x10(%rsp), %rcx
leaq 0xc(%rsp), %r8
leaq 0x1c(%rsp), %r9
movq %r13, %rdx
callq 0x2e43
testl %eax, %eax
je 0x28f8
leaq 0x6825(%rip), %rdi      # 0x90fd
movq %r14, %rsi
movl %ebx, %edx
xorl %eax, %eax
callq 0x3281
movq %r12, %rdi
movl %r15d, %esi
callq 0x33ab
leaq 0x68d1(%rip), %rdi      # 0x91c7
jmp 0x287c
movw %bp, 0xa(%rsp)
leaq 0x20(%rsp), %r15
movq %r15, %rdi
callq 0x3647
movl 0x10(%rsp), %r12d
movl 0xc(%rsp), %ebp
leaq 0x68e3(%rip), %rdi      # 0x91fd
movq %r14, %rsi
movq %r15, %rdx
movl %r12d, %ecx
movl %ebp, %r8d
xorl %eax, %eax
callq 0x3281
leaq 0xf89c(%rip), %rdi      # 0x121d0
movq %r15, %rsi
callq 0x6a00
testq %rax, %rax
je 0x296f
movq %rax, %r15
movl %r12d, %eax
xorl $0x1, %eax
movl %ebp, %ecx
xorl $0x1, %ecx
orl %eax, %ecx
setne 0x9(%rsp)
je 0x2987
leaq 0x68f8(%rip), %rdi      # 0x9257
xorl %r13d, %r13d
xorl %eax, %eax
callq 0x3281
movw $0x380, %ax             # imm = 0x380
jmp 0x2990
leaq 0x68c6(%rip), %rdi      # 0x923c
leaq 0x20(%rsp), %rsi
xorl %eax, %eax
callq 0x3281
jmp 0x2a7a
movw $0x100, %r13w           # imm = 0x100
movw $0x80, %ax
leaq 0x12c(%rsp), %rdi
movzwl 0xa(%rsp), %ecx
movw %cx, -0xc(%rdi)
movw %ax, -0xa(%rdi)
movw $0x100, -0x8(%rdi)      # imm = 0x100
movw %r13w, -0x6(%rdi)
andl $0x0, -0x4(%rdi)
leaq 0x20(%rsp), %rdx
leaq 0x14(%rsp), %rcx
movl $0x3f4, %esi            # imm = 0x3F4
callq 0x2fa2
testl %eax, %eax
jne 0x2a7a
movslq 0x14(%rsp), %r13
rolw $0x8, %r12w
movw %r12w, 0x12c(%rsp,%r13)
leal 0xe(%r13), %eax
rolw $0x8, %bp
cltq
movw %bp, 0x120(%rsp,%rax)
leal 0x10(%r13), %r8d
cmpb $0x0, 0x9(%rsp)
jne 0x2a62
movslq %r8d, %rax
movw $0xcc0, 0x120(%rsp,%rax) # imm = 0xCC0
leal 0x12(%r13), %eax
cltq
movabsq $0x2c01000001000100, %rcx # imm = 0x2C01000001000100
movq %rcx, 0x120(%rsp,%rax)
leal 0x1a(%r13), %eax
cltq
movw $0x400, 0x120(%rsp,%rax) # imm = 0x400
leal 0x1c(%r13), %ebp
addq $0x120, %r15            # imm = 0x120
leaq 0x18(%rsp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x2db2
movslq %ebp, %rax
movl (%r12), %ecx
movl %ecx, 0x120(%rsp,%rax)
leal 0x20(%r13), %r8d
movl 0xf760(%rip), %edi      # 0x121c8
leaq 0x120(%rsp), %rcx
movq %r14, %rsi
movl %ebx, %edx
callq 0x317e
addq $0x528, %rsp            # imm = 0x528
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq