mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
snoopy: add support for DNS packets
This commit is contained in:
parent
6f61477d26
commit
7e36b43bba
1 changed files with 429 additions and 0 deletions
429
src/cmd/ip/snoopy/dns.c
Normal file
429
src/cmd/ip/snoopy/dns.c
Normal file
|
@ -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
|
||||
};
|
Loading…
Reference in a new issue