Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: DNS Question

  1. #1
    Senior Member frpeter's Avatar
    Join Date
    Dec 2004
    Posts
    131

    Post DNS Question

    Hello,

    I have been trying to determine the differences between res_query and res_search. From the standpint of programming and results given by both, thus far I am not seeing a difference.

    Can someone illuminate the differences? ie: which is faster, more robust (fault tolerant), and so on.

    Thank you in advance.

  2. #2

  3. #3
    Senior Member frpeter's Avatar
    Join Date
    Dec 2004
    Posts
    131
    Hello,

    I've read the man pages multiple times, but still not getting the significance of RES_DEFNAMES and RES_DNSRCH options in the practical context of resolving an ip address or domain name. For this context which is better to use?

    Thank you in advance.

  4. #4
    Senior Member
    Join Date
    Mar 2004
    Posts
    557
    Hi

    res_search is a bit more powerful than res_query, although they
    do in principle the same job. All you can resolve with res_query
    you can with res_search, but not the other way around.

    In order to answer the question, of which one to use, you have
    to include performance/restrictions/simplicity into your equation.


    Res_query makes a query for
    Code:
    testmachine.test.com
    , able to handle "full" requests like these only.


    Res_search in addition is able to handle queries like
    Code:
    testmachine
    This testmachine can be interpreted as an alias (search_aliases)
    or, if RES_DEFNAMES is set, the default DNS suffix (local setting)
    is appended, like

    Code:
    testmachine.test.com
    Based on some specific order, the query is resolved.

    Cheers!
    If the only tool you have is a hammer, you tend to see every problem as a nail.
    (Abraham Maslow, Psychologist, 1908-70)

  5. #5
    Senior Member frpeter's Avatar
    Join Date
    Dec 2004
    Posts
    131
    Hello,

    Thank you for explaining the suddleties. Does res_search incur a speed penalty versus res_query for large number of resolutions, say in the order of a thousand? Which would yielf the best performance in a high demand situation?

    Thank you in advance.

  6. #6
    Leftie Linux Lover the_JinX's Avatar
    Join Date
    Nov 2001
    Location
    Beverwijk Netherlands
    Posts
    2,534
    that seems to depend on the implementation.

    As sec_ware suggested the search has a different function then the query..

    If you know the full domain and don't want to use it to get the info about lan machines without a .doman.tld part going with query would have to give less overhead..
    ASCII stupid question, get a stupid ANSI.
    When in Russia, pet a PETSCII.

    Get your ass over to SLAYRadio the best station for C64 Remixes !

  7. #7
    Senior Member frpeter's Avatar
    Join Date
    Dec 2004
    Posts
    131
    Hello,

    Prehaps the implementation would help refine the choice. I am the author of BullDog Firewall. A large aspect of its operations is rapid doman scans and updates. All data to be looked up are IP addresses only. I am emulating a recursive reverse dif methodology that does use donain name lookups. The system processes thousans of ip addresses and domains per hour.

    I will demonstrate this with two dig commands that yield the data I am interested in:

    $ dig -t any -x 129.250.159.173

    ; <<>> DiG 9.2.2 <<>> -t any -x 129.250.159.173
    ;; global options: printcmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40174
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

    ;; QUESTION SECTION:
    ;173.159.250.129.in-addr.arpa. IN ANY

    ;; ANSWER SECTION:
    173.159.250.129.in-addr.arpa. 86375 IN CNAME 173.128-26.159.250.129.in-addr.arpa.

    ;; Query time: 5 msec
    ;; SERVER: 127.0.0.1#53(127.0.0.1)
    ;; WHEN: Sun Feb 6 22:40:31 2005
    ;; MSG SIZE rcvd: 71


    $ dig -t any 173.128-26.159.250.129.in-addr.arpa

    ; <<>> DiG 9.2.2 <<>> -t any 173.128-26.159.250.129.in-addr.arpa
    ;; global options: printcmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10311
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

    ;; QUESTION SECTION:
    ;173.128-26.159.250.129.in-addr.arpa. IN ANY

    ;; ANSWER SECTION:
    173.128-26.159.250.129.in-addr.arpa. 604757 IN PTR tournaments.playsite.com.

    ;; Query time: 1 msec
    ;; SERVER: 127.0.0.1#53(127.0.0.1)
    ;; WHEN: Sun Feb 6 22:40:59 2005
    ;; MSG SIZE rcvd: 91


    From this, my result is derived as 129.250.159.173 is resolved to tournaments.playsite.com.

    It took 2 lookup for this one IP address. I have some IP addresses that require hundreds on lookup to produce the complete result.

    Hopefully this will narrow the scope a bit.

    Thank you in advance.

  8. #8
    Senior Member
    Join Date
    Mar 2004
    Posts
    557
    Hi

    The performance depends, as the_JinX said, on the implementation,
    and furthermore, on the task to perform.

    If HOSTALIASES are set, getenv(), which is used by res_search,
    is obviously faster than a query to a name server.

    Otherwise: res_search usually performs a call to res_query in the end.
    Hence, in addition to the actual query, there are some string manipulations
    and additional function calls. In some implementations, several
    res_query'ies are performed by res_search before the final decision,
    if I recall correctly.

    If this is really somewhat crucial, I'd perform a serious benchmark and/or
    a profiling (gprof, ...) based on the "average" query. If you do so, please keep
    us updated.

    Cheers.
    If the only tool you have is a hammer, you tend to see every problem as a nail.
    (Abraham Maslow, Psychologist, 1908-70)

  9. #9
    Senior Member frpeter's Avatar
    Join Date
    Dec 2004
    Posts
    131
    Hello,

    I did the testing and found the results (under a thousand IP's or so) to be very close, in some cases too close to make a distinction. 1000+ ips though clearly show (in my tests run) the res_query has a slight adavtage or res_search. A lot of the advantage seems to depend on the domain server being called. In one case, 256 IP addresses where scanned in approximately 5 minutes. Worse case took 1 hour 57 minutes.

    I am putting my code here for others to test and evaluate. the C code is similar to what I am using in my research. It probably could use optimization...

    First is the script I used to generate the IP addresses:

    --- [ start

    #!/bin/bash
    ip=$1

    let ip4=0
    while [ $ip4 -lt 256 ] ; do
    echo $ip.$ip4
    let ip4=ip4+1
    done

    --- [ end

    The next message will have the C code.

    I compiled with

    gcc -o Resolver Resolver.c -static -lresolv

    Expect warnings. It runs on my machine quite well.

  10. #10
    Senior Member frpeter's Avatar
    Join Date
    Dec 2004
    Posts
    131
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <netinet/in.h>
    #include <arpa/nameser.h>
    #include <resolv.h>

    /* Common headers to simplify typing */

    #define C unsigned char
    #define D double
    #define F float
    #define I int
    #define L long
    #define UL2 unsigned long long
    #define L2 long long
    #define LD long double
    #define S struct
    #define SC signed char
    #define SI int
    #define STR string
    #define STR2 longstring
    #define STR3 string16384
    #define TEXT textline
    #define U union
    #define UC unsigned char
    #define UI unsigned int
    #define UL unsigned long
    #define US unsigned short
    #define V void

    /* for conditionals */

    #ifndef FALSE
    #define FALSE 0
    #endif

    #ifndef TRUE
    #define TRUE 1
    #endif

    /* type defs */

    typedef unsigned char string[256];
    typedef unsigned char longstring[65536];

    // DNSRES should be either res_search or res_query

    #define DNSRES res_query

    // Need a large buffer

    #define DNS_MAX_ANSWER_LEN 65536

    typedef struct queue_node Queue;

    struct queue_node
    {
    char *item;
    Queue *next;
    };

    typedef S _DNSRESOLVER
    {
    I SavedNS; // Number of save DNS entries from original list
    S in_addr sns[MAXNS]; // Original DNS entries
    Queue *DNSListH, *DNSListT; // List of valid DNS resolvers to use, should be in in_addr
    Queue *DNSListC; // Current DNSList ptr;
    } DNSRESOLVER;

    DNSRESOLVER DNSResolver;

    // Common routines

    US dstrcmp(C *s1, C *s2);
    C *dstrcopy(C *d, C *s);
    UL dstrlen(C *s);
    C *trim(C *d, C *s);
    I IsIP(C *sp);

    // DNS Digging

    V InitializeResolver(V);
    V RotateDNS(V);
    C *Resolver(C *d, C *sp);

    Queue *BindResolver(C *ipn, Queue *head);

    // Queue

    Queue *AddQueue(V *str, I size, Queue *q);
    Queue *DelQueue(Queue *h, Queue *q);

    // Global variables

    Queue *reslist=NULL;

    I ResolverInitialized=FALSE;

    I main(I argc, C *argv[])
    {
    time_t start, progstart,now;
    STR line;
    C *d;
    I ipcount=0;

    progstart=time(NULL);

    d=malloc(DNS_MAX_ANSWER_LEN+1);

    while(fgets(line,sizeof(line),stdin)!=NULL)
    {
    memset(d,'\0',DNS_MAX_ANSWER_LEN);
    line[dstrlen(line)-1]='\0';
    trim(line,line);

    start=time(NULL);
    Resolver(d,line);

    now=time(NULL);
    printf("%8i %8i %-16s %s\n",now-progstart,now-start,line,d);
    ipcount++;
    }

    reslist=DelQueue(reslist,reslist);

    free(d);

    printf("Total run time for %i ip addresses: %i seconds\n",ipcount,time(NULL)-progstart);

    return(0);
    }

    // Advanced resolver routines

    // Initialize our resolver and save initial information

    V InitializeResolver(V)
    {
    Queue *ptr;
    STR d1;
    I i;

    if(ResolverInitialized==FALSE) // Only Initialize once
    {
    res_init();

    // Set up resolver to basic defaults

    _res.retry=3;
    _res.options=RES_DNSRCH|RES_RECURSE|RES_DEFNAMES;

    DNSResolver.SavedNS=_res.nscount;
    DNSResolver.DNSListH=NULL;
    DNSResolver.DNSListT=NULL;

    for(i=0;i<DNSResolver.SavedNS;i++)
    {
    DNSResolver.sns[i]=_res.nsaddr_list[i].sin_addr;

    DNSResolver.DNSListT=AddQueue((V *)&_res.nsaddr_list[i].sin_addr,sizeof(S in_addr)+1,DNSResolver.DNSListT);

    if(DNSResolver.DNSListH==NULL)
    DNSResolver.DNSListH=DNSResolver.DNSListT;
    }
    DNSResolver.DNSListC=DNSResolver.DNSListH; // Set the Current DNS ptr to the list head

    dstrcopy(d1,"QueueTracer");
    reslist=AddQueue((V *)d1,dstrlen(d1)+1,reslist);
    ResolverInitialized=TRUE;
    }
    else // Reset the resolver list to first entry
    {
    DNSResolver.DNSListC=DNSResolver.DNSListH;
    ptr=DNSResolver.DNSListC;

    for(i=0;i<DNSResolver.SavedNS;i++)
    {
    memcpy(&_res.nsaddr_list[i].sin_addr,ptr->item,sizeof(_res.nsaddr_list[i].sin_addr));

    if(ptr->next!=NULL)
    ptr=ptr->next;
    else
    ptr=DNSResolver.DNSListH;
    }
    }
    }

    // Rotate the Current DNS Entries

    V RotateDNS(V)
    {
    Queue *ptr;
    I i;

    ptr=DNSResolver.DNSListC;

    for(i=0;i<DNSResolver.SavedNS;i++)
    {
    memcpy(&_res.nsaddr_list[i].sin_addr,ptr->item,sizeof(_res.nsaddr_list[i].sin_addr));

    if(ptr->next!=NULL)
    ptr=ptr->next;
    else
    ptr=DNSResolver.DNSListH;
    }

    if(DNSResolver.DNSListC->next!=NULL)
    DNSResolver.DNSListC=DNSResolver.DNSListC->next;
    else
    DNSResolver.DNSListC=DNSResolver.DNSListH;
    }

    // Emulate dig -x ip.ad.re.ss -t any

    C *Resolver(C *d, C *sp)
    {
    Queue *rptr, *rtmp;
    STR ipn;
    I ip1, ip2, ip3, ip4;

    if(sp[0]=='\0')
    return("\0");

    if(IsIP(sp)==FALSE)
    return("\0");

    InitializeResolver();

    sscanf(sp,"%d.%d.%d.%d",&ip1, &ip2, &ip3, &ip4);
    sprintf(ipn,"%i.%i.%i.%i.in-addr.arpa.",ip4,ip3,ip2,ip1);

    reslist=BindResolver(ipn,reslist);

    rptr=reslist->next; // Tracer is first entry in list

    while(rptr)
    {
    if(rptr->item[0]!='\\')
    {
    if(IsIP(rptr->item)==FALSE)
    {
    strcat(d,rptr->item);
    strcat(d," ");
    }
    }
    rtmp=rptr;
    rptr=rptr->next;

    if(rtmp->item)
    free(rtmp->item);

    if(rtmp)
    free(rtmp);
    }

    reslist->next=NULL;

    trim(d,d);

    if(d[0]=='.' || d[0]==' ')
    d[0]='\0';

    return(d);
    }

    // Advanced recursive Dig resolver - REQUIRES libbind if compiled shared,
    // libbind may require libpthread

    Queue *BindResolver(C *ipn, Queue *head)
    {
    Queue *tail;
    C *buffer;
    ns_msg handle;
    I r, retry=_res.retry;

    I InList(C *s, Queue *head)
    {
    Queue *ptr;
    I done=FALSE;

    ptr=head;
    while(ptr!=NULL && done==FALSE)
    {
    done=dstrcmp(s,ptr->item);
    ptr=ptr->next;
    }
    return(done);
    }

    Queue *scan_rr(ns_sect sect, Queue *head)
    {
    ns_rr rr;
    C d1[2048];
    I i;

    for(i=0;i<ns_msg_count(handle, sect);i++)
    {
    ns_parserr(&handle, sect, i, &rr);
    if(ns_rr_type(rr)==ns_t_ns || ns_rr_type(rr)==ns_t_ptr
    || ns_rr_type(rr)==ns_t_cname || ns_rr_type(rr)==ns_t_mx
    || ns_rr_type(rr)==ns_t_a)
    {
    if(ns_rr_type(rr)==ns_t_a)
    dstrcopy(d1,(C *)inet_ntoa(*((struct in_addr *)rr.rdata)));
    else
    {
    if(ns_rr_type(rr)!=ns_t_mx)
    ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr), d1, sizeof(d1));
    else
    ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr)+2, d1, sizeof(d1));
    }
    trim(d1,d1);
    if(d1[dstrlen(d1)-1]=='.')
    d1[dstrlen(d1)-1]='\0';

    if(d1[0]!='\0')
    {
    if(InList(d1,head)==FALSE)
    {
    tail=head;
    if(head)
    {
    while(tail->next!=NULL)
    tail=tail->next;
    }
    tail=AddQueue((V *)d1,dstrlen(d1)+1,tail);
    strcat(d1,".");

    head=BindResolver(d1,head);
    }
    }
    }
    }
    return(head);
    }

    if(dstrcmp(ipn,".")==TRUE) // Root sever flaw, avoid
    return(head);

    buffer=malloc(DNS_MAX_ANSWER_LEN+1);
    memset(buffer,'\0',DNS_MAX_ANSWER_LEN);

    do {
    r=DNSRES(ipn,C_IN,T_ANY,buffer,DNS_MAX_ANSWER_LEN);
    if(r>0)
    {
    retry=-1;
    ns_initparse(buffer, r, &handle);

    head=scan_rr(ns_s_an,head);
    head=scan_rr(ns_s_ns,head);
    head=scan_rr(ns_s_ar,head);
    }
    else
    {
    RotateDNS();
    retry--;
    }
    } while(retry>0);

    free(buffer);

    return(head);
    }

    I IsIP(C *sp)
    {
    I ip1, ip2, ip3, ip4;
    STR d1;

    I ChkIP(I ip)
    {
    if(ip<0 || ip>255)
    return(FALSE);
    return(TRUE);
    }

    if(!sp)
    return(FALSE);

    sscanf(sp,"%d.%d.%d.%d",&ip1, &ip2, &ip3, &ip4);

    if(ChkIP(ip1)==FALSE || ChkIP(ip2)==FALSE
    || ChkIP(ip3)==FALSE || ChkIP(ip4)==FALSE)
    return(FALSE);

    sprintf(d1,"%i.%i.%i.%i",ip1, ip2, ip3, ip4);
    if(dstrcmp(d1,sp)==FALSE)
    return(FALSE);

    return(TRUE);
    }

    Queue *AddQueue(V *str, I size, Queue *q)
    {
    Queue *n;

    n=malloc(sizeof(Queue));
    n->item=malloc(size+1);

    n->next=NULL;

    memset(n->item,'\0',size);
    memcpy(n->item,str,size);

    if(q==NULL)
    return(n);

    q->next=n;
    q=q->next;

    return(q);
    }

    Queue *DelQueue(Queue *h, Queue *q)
    {
    Queue *tmp=h;

    if(q==NULL)
    return(q);

    if(q!=h)
    {
    while(tmp->next!=q)
    tmp=tmp->next;
    }
    else
    h=h->next;

    tmp->next=q->next;

    if(q->item!=NULL)
    free(q->item);

    if(q!=NULL)
    free(q);

    return(h);
    }

    /* Copy a string to a new variable */

    C *dstrcopy(C *d, C *s)
    {
    UL l;

    if(!*s)
    {
    d[0]='\0';
    return(d);
    }

    for(l=0;s[l]!='\0';l++)
    d[l]=s[l];
    d[l]='\0';

    return(d);
    }

    /* Compare w/ no case */

    US dstrcmp(C *s1, C *s2)
    {
    UL i, l;
    C d1, d2;

    if(!*s1)
    return(FALSE);
    if(!*s2)
    return(FALSE);

    if(dstrlen(s1)!=dstrlen(s2))
    return(FALSE);

    l=dstrlen(s1);

    for(i=0;i<l;i++)
    {
    d1=s1[i];
    if((d1>='a')&&(d1<='z'))
    d1-=32;

    d2=s2[i];
    if((d2>='a')&&(d2<='z'))
    d2-=32;

    if(d1!=d2)
    return(FALSE);
    }

    return(TRUE);
    }

    /* Trim leading and trailing spaces */

    C *trim(C *d, C *s)
    {
    UL i=0, j, l;

    if(!*s)
    return(d=s);

    for(i=0; (s[i]==' ' || s[i]=='\t') && s[i]!='\0'; i++);

    if(s[i]=='\0')
    {
    d[0]='\0';
    return(d);
    }

    for(j=0;s[i]!='\0';j++,i++)
    d[j]=s[i];
    d[j]='\0';

    l=dstrlen(d);

    for(i=l-1; (d[i]==' ' || d[i]=='\t') && i>0; i--);
    d[i+1]='\0';

    return(d);
    }

    /* Return the length of a string */

    UL dstrlen(C *s)
    {
    UL i=0;

    for(i=0; s[i]!='\0'; i++);

    return(i);
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •