add dns
This commit is contained in:
parent
cff43a06f2
commit
3e0d8fb3ea
15 changed files with 7047 additions and 0 deletions
380
src/cmd/ndb/convDNS2M.c
Executable file
380
src/cmd/ndb/convDNS2M.c
Executable file
|
|
@ -0,0 +1,380 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ip.h>
|
||||
#include <bio.h>
|
||||
#include <ndb.h>
|
||||
#include "dns.h"
|
||||
|
||||
/*
|
||||
* a dictionary of domain names for packing messages
|
||||
*/
|
||||
enum
|
||||
{
|
||||
Ndict= 64,
|
||||
};
|
||||
typedef struct Dict Dict;
|
||||
struct Dict
|
||||
{
|
||||
struct {
|
||||
ushort offset; /* pointer to packed name in message */
|
||||
char *name; /* pointer to unpacked name in buf */
|
||||
} x[Ndict];
|
||||
int n; /* size of dictionary */
|
||||
uchar *start; /* start of packed message */
|
||||
char buf[4*1024]; /* buffer for unpacked names */
|
||||
char *ep; /* first free char in buf */
|
||||
};
|
||||
|
||||
#define NAME(x) p = pname(p, ep, x, dp)
|
||||
#define SYMBOL(x) p = psym(p, ep, x)
|
||||
#define STRING(x) p = pstr(p, ep, x)
|
||||
#define BYTES(x, n) p = pbytes(p, ep, x, n)
|
||||
#define USHORT(x) p = pushort(p, ep, x)
|
||||
#define UCHAR(x) p = puchar(p, ep, x)
|
||||
#define ULONG(x) p = pulong(p, ep, x)
|
||||
#define V4ADDR(x) p = pv4addr(p, ep, x)
|
||||
#define V6ADDR(x) p = pv6addr(p, ep, x)
|
||||
|
||||
static uchar*
|
||||
psym(uchar *p, uchar *ep, char *np)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = strlen(np);
|
||||
if(n >= Strlen) /* DNS maximum length string */
|
||||
n = Strlen - 1;
|
||||
if(ep - p < n+1) /* see if it fits in the buffer */
|
||||
return ep+1;
|
||||
*p++ = n;
|
||||
memcpy(p, np, n);
|
||||
return p + n;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pstr(uchar *p, uchar *ep, char *np)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = strlen(np);
|
||||
if(n >= Strlen) /* DNS maximum length string */
|
||||
n = Strlen - 1;
|
||||
if(ep - p < n+1) /* see if it fits in the buffer */
|
||||
return ep+1;
|
||||
*p++ = n;
|
||||
memcpy(p, np, n);
|
||||
return p + n;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pbytes(uchar *p, uchar *ep, uchar *np, int n)
|
||||
{
|
||||
if(ep - p < n)
|
||||
return ep+1;
|
||||
memcpy(p, np, n);
|
||||
return p + n;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
puchar(uchar *p, uchar *ep, int val)
|
||||
{
|
||||
if(ep - p < 1)
|
||||
return ep+1;
|
||||
*p++ = val;
|
||||
return p;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pushort(uchar *p, uchar *ep, int val)
|
||||
{
|
||||
if(ep - p < 2)
|
||||
return ep+1;
|
||||
*p++ = val>>8;
|
||||
*p++ = val;
|
||||
return p;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pulong(uchar *p, uchar *ep, int val)
|
||||
{
|
||||
if(ep - p < 4)
|
||||
return ep+1;
|
||||
*p++ = val>>24;
|
||||
*p++ = val>>16;
|
||||
*p++ = val>>8;
|
||||
*p++ = val;
|
||||
return p;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pv4addr(uchar *p, uchar *ep, char *name)
|
||||
{
|
||||
uchar ip[IPaddrlen];
|
||||
|
||||
if(ep - p < 4)
|
||||
return ep+1;
|
||||
parseip(ip, name);
|
||||
v6tov4(p, ip);
|
||||
return p + 4;
|
||||
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pv6addr(uchar *p, uchar *ep, char *name)
|
||||
{
|
||||
if(ep - p < IPaddrlen)
|
||||
return ep+1;
|
||||
parseip(p, name);
|
||||
return p + IPaddrlen;
|
||||
|
||||
}
|
||||
|
||||
static uchar*
|
||||
pname(uchar *p, uchar *ep, char *np, Dict *dp)
|
||||
{
|
||||
char *cp;
|
||||
int i;
|
||||
char *last; /* last component packed */
|
||||
|
||||
if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
|
||||
return ep+1;
|
||||
|
||||
last = 0;
|
||||
while(*np){
|
||||
/* look through every component in the dictionary for a match */
|
||||
for(i = 0; i < dp->n; i++){
|
||||
if(strcmp(np, dp->x[i].name) == 0){
|
||||
if(ep - p < 2)
|
||||
return ep+1;
|
||||
*p++ = (dp->x[i].offset>>8) | 0xc0;
|
||||
*p++ = dp->x[i].offset;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/* if there's room, enter this name in dictionary */
|
||||
if(dp->n < Ndict){
|
||||
if(last){
|
||||
/* the whole name is already in dp->buf */
|
||||
last = strchr(last, '.') + 1;
|
||||
dp->x[dp->n].name = last;
|
||||
dp->x[dp->n].offset = p - dp->start;
|
||||
dp->n++;
|
||||
} else {
|
||||
/* add to dp->buf */
|
||||
i = strlen(np);
|
||||
if(dp->ep + i + 1 < &dp->buf[sizeof(dp->buf)]){
|
||||
strcpy(dp->ep, np);
|
||||
dp->x[dp->n].name = dp->ep;
|
||||
last = dp->ep;
|
||||
dp->x[dp->n].offset = p - dp->start;
|
||||
dp->ep += i + 1;
|
||||
dp->n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* put next component into message */
|
||||
cp = strchr(np, '.');
|
||||
if(cp == 0){
|
||||
i = strlen(np);
|
||||
cp = np + i; /* point to null terminator */
|
||||
} else {
|
||||
i = cp - np;
|
||||
cp++; /* point past '.' */
|
||||
}
|
||||
if(ep-p < i+1)
|
||||
return ep+1;
|
||||
*p++ = i; /* count of chars in label */
|
||||
memcpy(p, np, i);
|
||||
np = cp;
|
||||
p += i;
|
||||
}
|
||||
|
||||
if(p >= ep)
|
||||
return ep+1;
|
||||
*p++ = 0; /* add top level domain */
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
|
||||
{
|
||||
uchar *lp, *data;
|
||||
int len, ttl;
|
||||
Txt *t;
|
||||
|
||||
NAME(rp->owner->name);
|
||||
USHORT(rp->type);
|
||||
USHORT(rp->owner->class);
|
||||
|
||||
/* egregious overuse of ttl (it's absolute time in the cache) */
|
||||
if(rp->db)
|
||||
ttl = rp->ttl;
|
||||
else
|
||||
ttl = rp->ttl - now;
|
||||
if(ttl < 0)
|
||||
ttl = 0;
|
||||
ULONG(ttl);
|
||||
|
||||
lp = p; /* leave room for the rdata length */
|
||||
p += 2;
|
||||
data = p;
|
||||
|
||||
if(data >= ep)
|
||||
return p+1;
|
||||
|
||||
switch(rp->type){
|
||||
case Thinfo:
|
||||
SYMBOL(rp->cpu->name);
|
||||
SYMBOL(rp->os->name);
|
||||
break;
|
||||
case Tcname:
|
||||
case Tmb:
|
||||
case Tmd:
|
||||
case Tmf:
|
||||
case Tns:
|
||||
NAME(rp->host->name);
|
||||
break;
|
||||
case Tmg:
|
||||
case Tmr:
|
||||
NAME(rp->mb->name);
|
||||
break;
|
||||
case Tminfo:
|
||||
NAME(rp->rmb->name);
|
||||
NAME(rp->mb->name);
|
||||
break;
|
||||
case Tmx:
|
||||
USHORT(rp->pref);
|
||||
NAME(rp->host->name);
|
||||
break;
|
||||
case Ta:
|
||||
V4ADDR(rp->ip->name);
|
||||
break;
|
||||
case Taaaa:
|
||||
V6ADDR(rp->ip->name);
|
||||
break;
|
||||
case Tptr:
|
||||
NAME(rp->ptr->name);
|
||||
break;
|
||||
case Tsoa:
|
||||
NAME(rp->host->name);
|
||||
NAME(rp->rmb->name);
|
||||
ULONG(rp->soa->serial);
|
||||
ULONG(rp->soa->refresh);
|
||||
ULONG(rp->soa->retry);
|
||||
ULONG(rp->soa->expire);
|
||||
ULONG(rp->soa->minttl);
|
||||
break;
|
||||
case Ttxt:
|
||||
for(t = rp->txt; t != nil; t = t->next)
|
||||
STRING(t->p);
|
||||
break;
|
||||
case Tnull:
|
||||
BYTES(rp->null->data, rp->null->dlen);
|
||||
break;
|
||||
case Trp:
|
||||
NAME(rp->rmb->name);
|
||||
NAME(rp->rp->name);
|
||||
break;
|
||||
case Tkey:
|
||||
USHORT(rp->key->flags);
|
||||
UCHAR(rp->key->proto);
|
||||
UCHAR(rp->key->alg);
|
||||
BYTES(rp->key->data, rp->key->dlen);
|
||||
break;
|
||||
case Tsig:
|
||||
USHORT(rp->sig->type);
|
||||
UCHAR(rp->sig->alg);
|
||||
UCHAR(rp->sig->labels);
|
||||
ULONG(rp->sig->ttl);
|
||||
ULONG(rp->sig->exp);
|
||||
ULONG(rp->sig->incep);
|
||||
USHORT(rp->sig->tag);
|
||||
NAME(rp->sig->signer->name);
|
||||
BYTES(rp->sig->data, rp->sig->dlen);
|
||||
break;
|
||||
case Tcert:
|
||||
USHORT(rp->cert->type);
|
||||
USHORT(rp->cert->tag);
|
||||
UCHAR(rp->cert->alg);
|
||||
BYTES(rp->cert->data, rp->cert->dlen);
|
||||
break;
|
||||
}
|
||||
|
||||
/* stuff in the rdata section length */
|
||||
len = p - data;
|
||||
*lp++ = len >> 8;
|
||||
*lp = len;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
|
||||
{
|
||||
NAME(rp->owner->name);
|
||||
USHORT(rp->type);
|
||||
USHORT(rp->owner->class);
|
||||
return p;
|
||||
}
|
||||
|
||||
static uchar*
|
||||
rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
|
||||
{
|
||||
uchar *np;
|
||||
|
||||
*countp = 0;
|
||||
for(; rp && p < ep; rp = rp->next){
|
||||
if(quest)
|
||||
np = convQ2M(rp, p, ep, dp);
|
||||
else
|
||||
np = convRR2M(rp, p, ep, dp);
|
||||
if(np > ep)
|
||||
break;
|
||||
p = np;
|
||||
(*countp)++;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* convert into a message
|
||||
*/
|
||||
int
|
||||
convDNS2M(DNSmsg *m, uchar *buf, int len)
|
||||
{
|
||||
uchar *p, *ep, *np;
|
||||
Dict d;
|
||||
|
||||
d.n = 0;
|
||||
d.start = buf;
|
||||
d.ep = d.buf;
|
||||
memset(buf, 0, len);
|
||||
m->qdcount = m->ancount = m->nscount = m->arcount = 0;
|
||||
|
||||
/* first pack in the RR's so we can get real counts */
|
||||
p = buf + 12;
|
||||
ep = buf + len;
|
||||
p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
|
||||
p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
|
||||
p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
|
||||
p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
|
||||
if(p > ep)
|
||||
return -1;
|
||||
|
||||
/* now pack the rest */
|
||||
np = p;
|
||||
p = buf;
|
||||
ep = buf + len;
|
||||
USHORT(m->id);
|
||||
USHORT(m->flags);
|
||||
USHORT(m->qdcount);
|
||||
USHORT(m->ancount);
|
||||
USHORT(m->nscount);
|
||||
USHORT(m->arcount);
|
||||
if(p > ep)
|
||||
return -1;
|
||||
|
||||
return np - buf;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue