URI:
       tdns.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tdns.c (7924B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <ip.h>
            4 #include "dat.h"
            5 #include "protos.h"
            6 
            7 enum
            8 {
            9         /* RR types */
           10         Ta=        1,
           11         Tns=        2,
           12         Tmd=        3,
           13         Tmf=        4,
           14         Tcname=        5,
           15         Tsoa=        6,
           16         Tmb=        7,
           17         Tmg=        8,
           18         Tmr=        9,
           19         Tnull=        10,
           20         Twks=        11,
           21         Tptr=        12,
           22         Thinfo=        13,
           23         Tminfo=        14,
           24         Tmx=        15,
           25         Ttxt=        16,
           26         Trp=        17,
           27         Tsig=        24,
           28         Tkey=        25,
           29         Taaaa=        28,
           30         Tcert=        37,
           31 
           32         /* query types (all RR types are also queries) */
           33         Tixfr=        251,        /* incremental zone transfer */
           34         Taxfr=        252,        /* zone transfer */
           35         Tmailb=        253,        /* { Tmb, Tmg, Tmr } */
           36         Tall=        255,        /* all records */
           37 
           38         /* classes */
           39         Csym=        0,        /* internal symbols */
           40         Cin=        1,        /* internet */
           41         Ccs,                /* CSNET (obsolete) */
           42         Cch,                /* Chaos net */
           43         Chs,                /* Hesiod (?) */
           44 
           45         /* class queries (all class types are also queries) */
           46         Call=        255,        /* all classes */
           47 
           48         /* opcodes */
           49         Oquery=                0<<11,                /* normal query */
           50         Oinverse=        1<<11,                /* inverse query */
           51         Ostatus=        2<<11,                /* status request */
           52         Onotify=        4<<11,                /* notify slaves of updates */
           53         Omask=                0xf<<11,        /* mask for opcode */
           54 
           55         /* response codes */
           56         Rok=                0,
           57         Rformat=        1,        /* format error */
           58         Rserver=        2,        /* server failure (e.g. no answer from something) */
           59         Rname=                3,        /* bad name */
           60         Runimplimented=        4,        /* unimplemented */
           61         Rrefused=        5,        /* we don't like you */
           62         Rmask=                0xf,        /* mask for response */
           63         Rtimeout=        0x10,        /* timeout sending (for internal use only) */
           64 
           65         /* bits in flag word (other than opcode and response) */
           66         Fresp=                1<<15,        /* message is a response */
           67         Fauth=                1<<10,        /* true if an authoritative response */
           68         Ftrunc=                1<<9,        /* truncated message */
           69         Frecurse=        1<<8,        /* request recursion */
           70         Fcanrec=        1<<7,        /* server can recurse */
           71 };
           72 
           73 typedef struct Hdr        Hdr;
           74 struct Hdr
           75 {
           76         uchar        id[2];
           77         uchar        flags[2];
           78         uchar        qdcount[2];
           79         uchar        ancount[2];
           80         uchar        nscount[2];
           81         uchar        arcount[2];
           82 };
           83 
           84 
           85 static char*
           86 getstr(uchar **pp, int *len, uchar *ep)
           87 {
           88         uchar *p;
           89         int n;
           90 
           91         p = *pp;
           92         n = *p++;
           93         if(p+n > ep)
           94                 return nil;
           95         *len = n;
           96         *pp = p+n;
           97         return (char*)p;
           98 }
           99 
          100 static char*
          101 getname(uchar **pp, uchar *bp, uchar *ep)
          102 {
          103         static char buf[2][512];
          104         static int toggle;
          105         char *tostart, *to;
          106         char *toend;
          107         int len, off, pointer, n;
          108         uchar *p;
          109 
          110         to = buf[toggle^=1];
          111         toend = to+sizeof buf[0];
          112         tostart = to;
          113         p = *pp;
          114         len = 0;
          115         pointer = 0;
          116         while(p < ep && *p){
          117                 if((*p & 0xc0) == 0xc0){
          118                         /* pointer to another spot in message */
          119                         if(pointer == 0)
          120                                 *pp = p + 2;
          121                         if(pointer++ > 10)
          122                                 return nil;
          123                         off = ((p[0]<<8) + p[1]) & 0x3ff;
          124                         p = bp + off;
          125                         if(p >= ep)
          126                                 return nil;
          127                         n = 0;
          128                         continue;
          129                 }
          130                 n = *p++;
          131                 if(to+n >= toend || p+n > ep)
          132                         return nil;
          133                 memmove(to, p, n);
          134                 to += n;
          135                 p += n;
          136                 if(*p){
          137                         if(to >= toend)
          138                                 return nil;
          139                         *to++ = '.';
          140                 }
          141         }
          142         if(to >= toend || p >= ep)
          143                 return nil;
          144         *to = 0;
          145         if(!pointer)
          146                 *pp = ++p;
          147         return tostart;
          148 }
          149 
          150 static char*
          151 tname(int type)
          152 {
          153         static char buf[20];
          154 
          155         switch(type){
          156         case Ta:
          157                 return "a";
          158         case Tns:
          159                 return "ns";
          160         case Tmd:
          161                 return "md";
          162         case Tmf:
          163                 return "mf";
          164         case Tcname:
          165                 return "cname";
          166         case Tsoa:
          167                 return "soa";
          168         case Tmb:
          169                 return "mb";
          170         case Tmg:
          171                 return "mg";
          172         case Tmr:
          173                 return "mr";
          174         case Tnull:
          175                 return "null";
          176         case Twks:
          177                 return "wks";
          178         case Tptr:
          179                 return "ptr";
          180         case Thinfo:
          181                 return "hinfo";
          182         case Tminfo:
          183                 return "minfo";
          184         case Tmx:
          185                 return "mx";
          186         case Ttxt:
          187                 return "txt";
          188         case Trp:
          189                 return "rp";
          190         case Tsig:
          191                 return "sig";
          192         case Tkey:
          193                 return "key";
          194         case Taaaa:
          195                 return "aaaa";
          196         case Tcert:
          197                 return "cert";
          198         case Tixfr:
          199                 return "ixfr";
          200         case Taxfr:
          201                 return "axfr";
          202         case Tmailb:
          203                 return "mailb";
          204         case Tall:
          205                 return "all";
          206         }
          207         snprint(buf, sizeof buf, "%d", type);
          208         return buf;
          209 }
          210 
          211 static char*
          212 cname(int class)
          213 {
          214         static char buf[40];
          215 
          216         if(class == Cin)
          217                 return "";
          218 
          219         snprint(buf, sizeof buf, "class=%d", class);
          220         return buf;
          221 }
          222 
          223 #define PR(name, len) utfnlen(name, len), name
          224 
          225 extern int sflag;
          226 
          227 static int
          228 p_seprint(Msg *m)
          229 {
          230         int i, pref;
          231         Hdr *h;
          232         uchar *p, *ep;
          233         int an, ns, ar, rlen;
          234         char *name, *prefix;
          235         int len1, len2;
          236         char *sym1, *sym2, *sep;
          237         int type;
          238         static int first = 1;
          239 
          240         if(first){
          241                 first = 0;
          242                 quotefmtinstall();
          243         }
          244 
          245         if(m->pe - m->ps < sizeof(Hdr))
          246                 return -1;
          247         h = (Hdr*)m->ps;
          248         m->pr = nil;
          249 
          250         m->p = seprint(m->p, m->e, "id=%d flags=%04ux %d/%d/%d/%d",
          251                         NetS(h->id), NetS(h->flags),
          252                         NetS(h->qdcount), NetS(h->ancount),
          253                         NetS(h->nscount), NetS(h->arcount));
          254         sep = ")\n\t";
          255         if(sflag)
          256                 sep = ") ";
          257         p = m->ps + sizeof(Hdr);
          258         for(i=0; i<NetS(h->qdcount); i++){
          259                 name = getname(&p, m->ps, m->pe);
          260                 if(name == nil || p+4 > m->pe)
          261                         goto error;
          262                 m->p = seprint(m->p, m->e, "%sq=(%q %s%s",
          263                         sep, name, tname(NetS(p)), cname(NetS(p+2)));
          264                 p += 4;
          265         }
          266 
          267         an = NetS(h->ancount);
          268         ns = NetS(h->nscount);
          269         ar = NetS(h->arcount);
          270         while(an+ns+ar > 0){
          271                 if(an > 0){
          272                         prefix = "an";
          273                         an--;
          274                 }else if(ns > 0){
          275                         prefix = "ns";
          276                         ns--;
          277                 }else{
          278                         prefix = "ar";
          279                         ar--;
          280                 }
          281                 name = getname(&p, m->ps, m->pe);
          282                 if(name == nil || p+10 > m->pe)
          283                         goto error;
          284                 type = NetS(p);
          285                 rlen = NetS(p+8);
          286                 ep = p+10+rlen;
          287                 if(ep > m->pe)
          288                         goto error;
          289                 m->p = seprint(m->p, m->e, "%s%s=(%q %s%s | ttl=%lud",
          290                         sep, prefix, name, tname(type), cname(NetS(p+2)), NetL(p+4), rlen);
          291                 p += 10;
          292                 switch(type){
          293                 default:
          294                         p = ep;
          295                         break;
          296                 case Thinfo:
          297                         sym1 = getstr(&p, &len1, ep);
          298                         if(sym1 == nil)
          299                                 goto error;
          300                         sym2 = getstr(&p, &len2, ep);
          301                         if(sym2 == nil)
          302                                 goto error;
          303                         m->p = seprint(m->p, m->e, " cpu=%.*s os=%.*s",
          304                                 PR(sym1, len1),
          305                                 PR(sym2, len2));
          306                         break;
          307                 case Tcname:
          308                 case Tmb:
          309                 case Tmd:
          310                 case Tmf:
          311                 case Tns:
          312                 case Tmg:
          313                 case Tmr:
          314                 case Tptr:
          315                         sym1 = getname(&p, m->ps, m->pe);
          316                         if(sym1 == nil)
          317                                 goto error;
          318                         m->p = seprint(m->p, m->e, " %q", sym1);
          319                         break;
          320                 case Tminfo:
          321                         sym1 = getname(&p, m->ps, m->pe);
          322                         if(sym1 == nil)
          323                                 goto error;
          324                         sym2 = getname(&p, m->ps, m->pe);
          325                         if(sym2 == nil)
          326                                 goto error;
          327                         m->p = seprint(m->p, m->e, " %q %q", sym1, sym2);
          328                         break;
          329                 case Tmx:
          330                         if(p+2 >= ep)
          331                                 goto error;
          332                         pref = NetS(p);
          333                         p += 2;
          334                         sym1 = getname(&p, m->ps, m->pe);
          335                         if(sym1 == nil)
          336                                 goto error;
          337                         break;
          338                 case Ta:
          339                         if(p+4 > ep)
          340                                 goto error;
          341                         m->p = seprint(m->p, m->e, " %V", p);
          342                         p += 4;
          343                         break;
          344                 case Taaaa:
          345                         if(p+16 > ep)
          346                                 goto error;
          347                         m->p = seprint(m->p, m->e, " %I", p);
          348                         p += 16;
          349                         break;
          350                 case Tsoa:
          351                         sym1 = getname(&p, m->ps, m->pe);
          352                         if(sym1 == nil)
          353                                 goto error;
          354                         sym2 = getname(&p, m->ps, m->pe);
          355                         if(sym2 == nil)
          356                                 goto error;
          357                         if(p+20 > ep)
          358                                 goto error;
          359                         m->p = seprint(m->p, m->e, " host=%q rmb=%q serial=%lud refresh=%lud retry=%lud expire=%lud minttl=%lud",
          360                                 sym1, sym2, NetL(p), NetL(p+4),
          361                                 NetL(p+8), NetL(p+12), NetL(p+16));
          362                         break;
          363                 case Ttxt:
          364                         while(p < ep){
          365                                 sym1 = getstr(&p, &len1, ep);
          366                                 if(sym1 == nil)
          367                                         goto error;
          368                                 m->p = seprint(m->p, m->e, " %.*q", PR(sym1, len1));
          369                         }
          370                         break;
          371                 case Tnull:
          372                         m->p = seprint(m->p, m->e, " %.*H", rlen, p);
          373                         p += rlen;
          374                         break;
          375                 case Trp:
          376                         sym1 = getname(&p, m->ps, m->pe);
          377                         if(sym1 == nil)
          378                                 goto error;
          379                         sym2 = getname(&p, m->ps, m->pe);
          380                         if(sym2 == nil)
          381                                 goto error;
          382                         m->p = seprint(m->p, m->e, " rmb=%q rp=%q", sym1, sym2);
          383                         break;
          384                 case Tkey:
          385                         if(rlen < 4)
          386                                 goto error;
          387                         m->p = seprint(m->p, m->e, " flags=%04ux proto=%d alg=%d %.*H",
          388                                 NetS(p), p[3], p[4], rlen-4, p+4);
          389                         p += rlen;
          390                         break;
          391 
          392                 case Tsig:
          393                         if(rlen < 18)
          394                                 goto error;
          395                         m->p = seprint(m->p, m->e, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d %.*H",
          396                                 NetS(p), p[3], p[4], NetL(p+4), NetL(p+8), NetL(p+12), NetS(p+16),
          397                                 rlen-18, p+18);
          398                         p += rlen;
          399                         break;
          400 
          401                 case Tcert:
          402                         if(rlen < 5)
          403                                 goto error;
          404                         m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d %.*H",
          405                                 NetS(p), NetS(p+2), p[4], rlen-5, p+5);
          406                         p += rlen;
          407                         break;
          408                 }
          409                 if(p != ep)
          410                         goto error;
          411         }
          412         return 0;
          413 
          414 error:
          415         m->p = seprint(m->p, m->e, " packet error!");
          416         return 0;
          417 }
          418 
          419 Proto dns =
          420 {
          421         "dns",
          422         nil,
          423         nil,
          424         p_seprint,
          425         nil,
          426         nil,
          427         nil,
          428         defaultframer
          429 };