tsnoopy: add support for DNS packets - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 7e36b43bba16df64a08c13358ba2a70ae9001770
 (DIR) parent 6f61477d2607eb7df816aae3e2e94fb1697554c8
 (HTM) Author: Russ Cox <rsc@swtch.com>
       Date:   Thu, 24 Jul 2008 08:03:42 -0700
       
       snoopy: add support for DNS packets
       
       Diffstat:
         A src/cmd/ip/snoopy/dns.c             |     429 +++++++++++++++++++++++++++++++
       
       1 file changed, 429 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/ip/snoopy/dns.c b/src/cmd/ip/snoopy/dns.c
       t@@ -0,0 +1,429 @@
       +#include <u.h>
       +#include <libc.h>
       +#include <ip.h>
       +#include "dat.h"
       +#include "protos.h"
       +
       +enum
       +{
       +        /* RR types */
       +        Ta=        1,
       +        Tns=        2,
       +        Tmd=        3,
       +        Tmf=        4,
       +        Tcname=        5,
       +        Tsoa=        6,
       +        Tmb=        7,
       +        Tmg=        8,
       +        Tmr=        9,
       +        Tnull=        10,
       +        Twks=        11,
       +        Tptr=        12,
       +        Thinfo=        13,
       +        Tminfo=        14,
       +        Tmx=        15,
       +        Ttxt=        16,
       +        Trp=        17,
       +        Tsig=        24,
       +        Tkey=        25,
       +        Taaaa=        28,
       +        Tcert=        37,
       +
       +        /* query types (all RR types are also queries) */
       +        Tixfr=        251,        /* incremental zone transfer */
       +        Taxfr=        252,        /* zone transfer */
       +        Tmailb=        253,        /* { Tmb, Tmg, Tmr } */        
       +        Tall=        255,        /* all records */
       +
       +        /* classes */
       +        Csym=        0,        /* internal symbols */
       +        Cin=        1,        /* internet */
       +        Ccs,                /* CSNET (obsolete) */
       +        Cch,                /* Chaos net */
       +        Chs,                /* Hesiod (?) */
       +
       +        /* class queries (all class types are also queries) */
       +        Call=        255,        /* all classes */
       +
       +        /* opcodes */
       +        Oquery=                0<<11,                /* normal query */
       +        Oinverse=        1<<11,                /* inverse query */
       +        Ostatus=        2<<11,                /* status request */
       +        Onotify=        4<<11,                /* notify slaves of updates */
       +        Omask=                0xf<<11,        /* mask for opcode */
       +
       +        /* response codes */
       +        Rok=                0,
       +        Rformat=        1,        /* format error */
       +        Rserver=        2,        /* server failure (e.g. no answer from something) */
       +        Rname=                3,        /* bad name */
       +        Runimplimented=        4,        /* unimplemented */
       +        Rrefused=        5,        /* we don't like you */
       +        Rmask=                0xf,        /* mask for response */
       +        Rtimeout=        0x10,        /* timeout sending (for internal use only) */
       +
       +        /* bits in flag word (other than opcode and response) */
       +        Fresp=                1<<15,        /* message is a response */
       +        Fauth=                1<<10,        /* true if an authoritative response */
       +        Ftrunc=                1<<9,        /* truncated message */
       +        Frecurse=        1<<8,        /* request recursion */
       +        Fcanrec=        1<<7,        /* server can recurse */
       +};
       +
       +typedef struct Hdr        Hdr;
       +struct Hdr
       +{
       +        uchar        id[2];
       +        uchar        flags[2];
       +        uchar        qdcount[2];
       +        uchar        ancount[2];
       +        uchar        nscount[2];
       +        uchar        arcount[2];
       +};
       +
       +
       +static char*
       +getstr(uchar **pp, int *len, uchar *ep)
       +{
       +        uchar *p;
       +        int n;
       +        
       +        p = *pp;
       +        n = *p++;
       +        if(p+n > ep)
       +                return nil;
       +        *len = n;
       +        *pp = p+n;
       +        return (char*)p;
       +}
       +
       +static char*
       +getname(uchar **pp, uchar *bp, uchar *ep)
       +{
       +        static char buf[2][512];
       +        static int toggle;
       +        char *tostart, *to;
       +        char *toend;
       +        int len, off, pointer, n;
       +        uchar *p;
       +
       +        to = buf[toggle^=1];
       +        toend = to+sizeof buf[0];
       +        tostart = to;
       +        p = *pp;
       +        len = 0;
       +        pointer = 0;
       +        while(p < ep && *p){
       +                if((*p & 0xc0) == 0xc0){
       +                        /* pointer to another spot in message */
       +                        if(pointer == 0)
       +                                *pp = p + 2;
       +                        if(pointer++ > 10)
       +                                return nil;
       +                        off = ((p[0]<<8) + p[1]) & 0x3ff;
       +                        p = bp + off;
       +                        if(p >= ep)
       +                                return nil;
       +                        n = 0;
       +                        continue;
       +                }
       +                n = *p++;
       +                if(to+n >= toend || p+n > ep)
       +                        return nil;
       +                memmove(to, p, n);
       +                to += n;
       +                p += n;
       +                if(*p){
       +                        if(to >= toend)
       +                                return nil;
       +                        *to++ = '.';
       +                }
       +        }
       +        if(to >= toend || p >= ep)
       +                return nil;
       +        *to = 0;
       +        if(!pointer)
       +                *pp = ++p;
       +        return tostart;
       +}
       +
       +static char*
       +tname(int type)
       +{
       +        static char buf[20];
       +
       +        switch(type){
       +        case Ta:
       +                return "a";
       +        case Tns:
       +                return "ns";
       +        case Tmd:
       +                return "md";
       +        case Tmf:
       +                return "mf";
       +        case Tcname:
       +                return "cname";
       +        case Tsoa:
       +                return "soa";
       +        case Tmb:
       +                return "mb";
       +        case Tmg:
       +                return "mg";
       +        case Tmr:
       +                return "mr";
       +        case Tnull:
       +                return "null";
       +        case Twks:
       +                return "wks";
       +        case Tptr:
       +                return "ptr";
       +        case Thinfo:
       +                return "hinfo";
       +        case Tminfo:
       +                return "minfo";
       +        case Tmx:
       +                return "mx";
       +        case Ttxt:
       +                return "txt";
       +        case Trp:
       +                return "rp";
       +        case Tsig:
       +                return "sig";
       +        case Tkey:
       +                return "key";
       +        case Taaaa:
       +                return "aaaa";
       +        case Tcert:
       +                return "cert";
       +        case Tixfr:
       +                return "ixfr";
       +        case Taxfr:
       +                return "axfr";
       +        case Tmailb:
       +                return "mailb";
       +        case Tall:
       +                return "all";
       +        }
       +        snprint(buf, sizeof buf, "%d", type);
       +        return buf;
       +}
       +
       +static char*
       +cname(int class)
       +{
       +        static char buf[40];
       +
       +        if(class == Cin)
       +                return "";
       +        
       +        snprint(buf, sizeof buf, "class=%d", class);
       +        return buf;
       +}
       +
       +#define PR(name, len) utfnlen(name, len), name
       +
       +extern int sflag;
       +
       +static int
       +p_seprint(Msg *m)
       +{
       +        int i, pref;
       +        Hdr *h;
       +        uchar *p, *ep;
       +        int an, ns, ar, rlen;
       +        char *name, *prefix;
       +        int len1, len2;
       +        char *sym1, *sym2, *sep;
       +        int type;
       +        static int first = 1;
       +        
       +        if(first){
       +                first = 0;
       +                quotefmtinstall();
       +        }
       +
       +        if(m->pe - m->ps < sizeof(Hdr))
       +                return -1;
       +        h = (Hdr*)m->ps;
       +        m->pr = nil;
       +
       +        m->p = seprint(m->p, m->e, "id=%d flags=%04ux %d/%d/%d/%d",
       +                        NetS(h->id), NetS(h->flags),
       +                        NetS(h->qdcount), NetS(h->ancount),
       +                        NetS(h->nscount), NetS(h->arcount));
       +        sep = ")\n\t";
       +        if(sflag)
       +                sep = ") ";
       +        p = m->ps + sizeof(Hdr);
       +        for(i=0; i<NetS(h->qdcount); i++){
       +                name = getname(&p, m->ps, m->pe);
       +                if(name == nil || p+4 > m->pe)
       +                        goto error;
       +                m->p = seprint(m->p, m->e, "%sq=(%q %s%s",
       +                        sep, name, tname(NetS(p)), cname(NetS(p+2)));
       +                p += 4;
       +        }
       +
       +        an = NetS(h->ancount);
       +        ns = NetS(h->nscount);
       +        ar = NetS(h->arcount);
       +        while(an+ns+ar > 0){
       +                if(an > 0){
       +                        prefix = "an";
       +                        an--;
       +                }else if(ns > 0){
       +                        prefix = "ns";
       +                        ns--;
       +                }else{
       +                        prefix = "ar";
       +                        ar--;
       +                }
       +                name = getname(&p, m->ps, m->pe);
       +                if(name == nil || p+10 > m->pe)
       +                        goto error;
       +                type = NetS(p);
       +                rlen = NetS(p+8);
       +                ep = p+10+rlen;
       +                if(ep > m->pe)
       +                        goto error;
       +                m->p = seprint(m->p, m->e, "%s%s=(%q %s%s | ttl=%lud",
       +                        sep, prefix, name, tname(type), cname(NetS(p+2)), NetL(p+4), rlen);
       +                p += 10;
       +                switch(type){
       +                default:
       +                        p = ep;
       +                        break;
       +                case Thinfo:
       +                        sym1 = getstr(&p, &len1, ep);
       +                        if(sym1 == nil)
       +                                goto error;
       +                        sym2 = getstr(&p, &len2, ep);
       +                        if(sym2 == nil)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " cpu=%.*s os=%.*s",
       +                                PR(sym1, len1),
       +                                PR(sym2, len2));
       +                        break;
       +                case Tcname:
       +                case Tmb:
       +                case Tmd:
       +                case Tmf:
       +                case Tns:
       +                case Tmg:
       +                case Tmr:
       +                case Tptr:
       +                        sym1 = getname(&p, m->ps, m->pe);
       +                        if(sym1 == nil)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " %q", sym1);
       +                        break;
       +                case Tminfo:
       +                        sym1 = getname(&p, m->ps, m->pe);
       +                        if(sym1 == nil)
       +                                goto error;
       +                        sym2 = getname(&p, m->ps, m->pe);
       +                        if(sym2 == nil)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " %q %q", sym1, sym2);
       +                        break;
       +                case Tmx:
       +                        if(p+2 >= ep)
       +                                goto error;
       +                        pref = NetS(p);
       +                        p += 2;
       +                        sym1 = getname(&p, m->ps, m->pe);
       +                        if(sym1 == nil)
       +                                goto error;
       +                        break;
       +                case Ta:
       +                        if(p+4 > ep)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " %V", p);
       +                        p += 4;
       +                        break;
       +                case Taaaa:
       +                        if(p+16 > ep)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " %I", p);
       +                        p += 16;
       +                        break;
       +                case Tsoa:
       +                        sym1 = getname(&p, m->ps, m->pe);
       +                        if(sym1 == nil)
       +                                goto error;
       +                        sym2 = getname(&p, m->ps, m->pe);
       +                        if(sym2 == nil)
       +                                goto error;
       +                        if(p+20 > ep)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " host=%q rmb=%q serial=%lud refresh=%lud retry=%lud expire=%lud minttl=%lud",
       +                                sym1, sym2, NetL(p), NetL(p+4),
       +                                NetL(p+8), NetL(p+12), NetL(p+16));
       +                        break;
       +                case Ttxt:
       +                        while(p < ep){
       +                                sym1 = getstr(&p, &len1, ep);
       +                                if(sym1 == nil)
       +                                        goto error;
       +                                m->p = seprint(m->p, m->e, " %.*q", PR(sym1, len1));
       +                        }
       +                        break;
       +                case Tnull:
       +                        m->p = seprint(m->p, m->e, " %.*H", rlen, p);
       +                        p += rlen;
       +                        break;
       +                case Trp:
       +                        sym1 = getname(&p, m->ps, m->pe);
       +                        if(sym1 == nil)
       +                                goto error;
       +                        sym2 = getname(&p, m->ps, m->pe);
       +                        if(sym2 == nil)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " rmb=%q rp=%q", sym1, sym2);
       +                        break;
       +                case Tkey:
       +                        if(rlen < 4)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " flags=%04ux proto=%d alg=%d %.*H",
       +                                NetS(p), p[3], p[4], rlen-4, p+4);
       +                        p += rlen;
       +                        break;
       + 
       +                case Tsig:
       +                        if(rlen < 18)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d %.*H",
       +                                NetS(p), p[3], p[4], NetL(p+4), NetL(p+8), NetL(p+12), NetS(p+16),
       +                                rlen-18, p+18);
       +                        p += rlen;
       +                        break;
       +
       +                case Tcert:
       +                        if(rlen < 5)
       +                                goto error;
       +                        m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d %.*H",
       +                                NetS(p), NetS(p+2), p[4], rlen-5, p+5);
       +                        p += rlen;
       +                        break;
       +                }
       +                if(p != ep)
       +                        goto error;
       +        }        
       +        return 0;
       +
       +error:
       +        m->p = seprint(m->p, m->e, " packet error!");
       +        return 0;
       +}
       +
       +Proto dns =
       +{
       +        "dns",
       +        nil,
       +        nil,
       +        p_seprint,
       +        nil,
       +        nil,
       +        nil,
       +        defaultframer
       +};