aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ndb/convM2DNS.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-12-27 04:30:05 +0000
committerrsc <devnull@localhost>2005-12-27 04:30:05 +0000
commit3e0d8fb3ea83b2b65a6425c65beda887140f9349 (patch)
treece1579f6999c0e4adad35b75c498ddc714b40c1e /src/cmd/ndb/convM2DNS.c
parentcff43a06f21a674b2b16e72f8853aac5fd24f48d (diff)
downloadplan9port-3e0d8fb3ea83b2b65a6425c65beda887140f9349.tar.gz
plan9port-3e0d8fb3ea83b2b65a6425c65beda887140f9349.tar.bz2
plan9port-3e0d8fb3ea83b2b65a6425c65beda887140f9349.zip
add dns
Diffstat (limited to 'src/cmd/ndb/convM2DNS.c')
-rwxr-xr-xsrc/cmd/ndb/convM2DNS.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/src/cmd/ndb/convM2DNS.c b/src/cmd/ndb/convM2DNS.c
new file mode 100755
index 00000000..47b35616
--- /dev/null
+++ b/src/cmd/ndb/convM2DNS.c
@@ -0,0 +1,460 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <bio.h>
+#include <ndb.h>
+#include "dns.h"
+
+typedef struct Scan Scan;
+struct Scan
+{
+ uchar *base;
+ uchar *p;
+ uchar *ep;
+ char *err;
+};
+
+#define NAME(x) gname(x, sp)
+#define SYMBOL(x) (x = gsym(sp))
+#define STRING(x) (x = gstr(sp))
+#define USHORT(x) (x = gshort(sp))
+#define ULONG(x) (x = glong(sp))
+#define UCHAR(x) (x = gchar(sp))
+#define V4ADDR(x) (x = gv4addr(sp))
+#define V6ADDR(x) (x = gv6addr(sp))
+#define BYTES(x, y) (y = gbytes(sp, &x, len - (sp->p - data)))
+
+static char *toolong = "too long";
+
+/*
+ * get a ushort/ulong
+ */
+static ushort
+gchar(Scan *sp)
+{
+ ushort x;
+
+ if(sp->err)
+ return 0;
+ if(sp->ep - sp->p < 1){
+ sp->err = toolong;
+ return 0;
+ }
+ x = sp->p[0];
+ sp->p += 1;
+ return x;
+}
+static ushort
+gshort(Scan *sp)
+{
+ ushort x;
+
+ if(sp->err)
+ return 0;
+ if(sp->ep - sp->p < 2){
+ sp->err = toolong;
+ return 0;
+ }
+ x = (sp->p[0]<<8) | sp->p[1];
+ sp->p += 2;
+ return x;
+}
+static ulong
+glong(Scan *sp)
+{
+ ulong x;
+
+ if(sp->err)
+ return 0;
+ if(sp->ep - sp->p < 4){
+ sp->err = toolong;
+ return 0;
+ }
+ x = (sp->p[0]<<24) | (sp->p[1]<<16) | (sp->p[2]<<8) | sp->p[3];
+ sp->p += 4;
+ return x;
+}
+
+/*
+ * get an ip address
+ */
+static DN*
+gv4addr(Scan *sp)
+{
+ char addr[32];
+
+ if(sp->err)
+ return 0;
+ if(sp->ep - sp->p < 4){
+ sp->err = toolong;
+ return 0;
+ }
+ snprint(addr, sizeof(addr), "%V", sp->p);
+ sp->p += 4;
+
+ return dnlookup(addr, Cin, 1);
+}
+static DN*
+gv6addr(Scan *sp)
+{
+ char addr[64];
+
+ if(sp->err)
+ return 0;
+ if(sp->ep - sp->p < IPaddrlen){
+ sp->err = toolong;
+ return 0;
+ }
+ snprint(addr, sizeof(addr), "%I", sp->p);
+ sp->p += IPaddrlen;
+
+ return dnlookup(addr, Cin, 1);
+}
+
+/*
+ * get a string. make it an internal symbol.
+ */
+static DN*
+gsym(Scan *sp)
+{
+ int n;
+ char sym[Strlen+1];
+
+ if(sp->err)
+ return 0;
+ n = *(sp->p++);
+ if(sp->p+n > sp->ep){
+ sp->err = toolong;
+ return 0;
+ }
+
+ if(n > Strlen){
+ sp->err = "illegal string";
+ return 0;
+ }
+ strncpy(sym, (char*)sp->p, n);
+ sym[n] = 0;
+ sp->p += n;
+
+ return dnlookup(sym, Csym, 1);
+}
+
+/*
+ * get a string. don't make it an internal symbol.
+ */
+static Txt*
+gstr(Scan *sp)
+{
+ int n;
+ char sym[Strlen+1];
+ Txt *t;
+
+ if(sp->err)
+ return 0;
+ n = *(sp->p++);
+ if(sp->p+n > sp->ep){
+ sp->err = toolong;
+ return 0;
+ }
+
+ if(n > Strlen){
+ sp->err = "illegal string";
+ return 0;
+ }
+ strncpy(sym, (char*)sp->p, n);
+ sym[n] = 0;
+ sp->p += n;
+
+ t = emalloc(sizeof(*t));
+ t->next = nil;
+ t->p = estrdup(sym);
+ return t;
+}
+
+/*
+ * get a sequence of bytes
+ */
+static int
+gbytes(Scan *sp, uchar **p, int n)
+{
+ if(sp->err)
+ return 0;
+ if(sp->p+n > sp->ep || n < 0){
+ sp->err = toolong;
+ return 0;
+ }
+ *p = emalloc(n);
+ memmove(*p, sp->p, n);
+ sp->p += n;
+
+ return n;
+}
+
+/*
+ * get a domain name. 'to' must point to a buffer at least Domlen+1 long.
+ */
+static char*
+gname(char *to, Scan *sp)
+{
+ int len, off;
+ int pointer;
+ int n;
+ char *tostart;
+ char *toend;
+ uchar *p;
+
+ tostart = to;
+ if(sp->err)
+ goto err;
+ pointer = 0;
+ p = sp->p;
+ toend = to + Domlen;
+ for(len = 0; *p; len += pointer ? 0 : (n+1)){
+ if((*p & 0xc0) == 0xc0){
+ /* pointer to other spot in message */
+ if(pointer++ > 10){
+ sp->err = "pointer loop";
+ goto err;
+ }
+ off = ((p[0]<<8) + p[1]) & 0x3ff;
+ p = sp->base + off;
+ if(p >= sp->ep){
+ sp->err = "bad pointer";
+ goto err;
+ }
+ n = 0;
+ continue;
+ }
+ n = *p++;
+ if(len + n < Domlen - 1){
+ if(to + n > toend){
+ sp->err = toolong;
+ goto err;
+ }
+ memmove(to, p, n);
+ to += n;
+ }
+ p += n;
+ if(*p){
+ if(to >= toend){
+ sp->err = toolong;
+ goto err;
+ }
+ *to++ = '.';
+ }
+ }
+ *to = 0;
+ if(pointer)
+ sp->p += len + 2; /* + 2 for pointer */
+ else
+ sp->p += len + 1; /* + 1 for the null domain */
+ return tostart;
+err:
+ *tostart = 0;
+ return tostart;
+}
+
+/*
+ * convert the next RR from a message
+ */
+static RR*
+convM2RR(Scan *sp)
+{
+ RR *rp;
+ int type;
+ int class;
+ uchar *data;
+ int len;
+ char dname[Domlen+1];
+ Txt *t, **l;
+
+retry:
+ NAME(dname);
+ USHORT(type);
+ USHORT(class);
+
+ rp = rralloc(type);
+ rp->owner = dnlookup(dname, class, 1);
+ rp->type = type;
+
+ ULONG(rp->ttl);
+ rp->ttl += now;
+ USHORT(len);
+ data = sp->p;
+
+ if(sp->p + len > sp->ep)
+ sp->err = toolong;
+ if(sp->err){
+ rrfree(rp);
+ return 0;
+ }
+
+ switch(type){
+ default:
+ /* unknown type, just ignore it */
+ sp->p = data + len;
+ rrfree(rp);
+ goto retry;
+ case Thinfo:
+ SYMBOL(rp->cpu);
+ SYMBOL(rp->os);
+ break;
+ case Tcname:
+ case Tmb:
+ case Tmd:
+ case Tmf:
+ case Tns:
+ rp->host = dnlookup(NAME(dname), Cin, 1);
+ break;
+ case Tmg:
+ case Tmr:
+ rp->mb = dnlookup(NAME(dname), Cin, 1);
+ break;
+ case Tminfo:
+ rp->rmb = dnlookup(NAME(dname), Cin, 1);
+ rp->mb = dnlookup(NAME(dname), Cin, 1);
+ break;
+ case Tmx:
+ USHORT(rp->pref);
+ rp->host = dnlookup(NAME(dname), Cin, 1);
+ break;
+ case Ta:
+ V4ADDR(rp->ip);
+ break;
+ case Taaaa:
+ V6ADDR(rp->ip);
+ break;
+ case Tptr:
+ rp->ptr = dnlookup(NAME(dname), Cin, 1);
+ break;
+ case Tsoa:
+ rp->host = dnlookup(NAME(dname), Cin, 1);
+ rp->rmb = dnlookup(NAME(dname), Cin, 1);
+ ULONG(rp->soa->serial);
+ ULONG(rp->soa->refresh);
+ ULONG(rp->soa->retry);
+ ULONG(rp->soa->expire);
+ ULONG(rp->soa->minttl);
+ break;
+ case Ttxt:
+ l = &rp->txt;
+ *l = nil;
+ while(sp->p-data < len){
+ STRING(t);
+ *l = t;
+ l = &t->next;
+ }
+ break;
+ case Tnull:
+ BYTES(rp->null->data, rp->null->dlen);
+ break;
+ case Trp:
+ rp->rmb = dnlookup(NAME(dname), Cin, 1);
+ rp->rp = dnlookup(NAME(dname), Cin, 1);
+ 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);
+ rp->sig->signer = dnlookup(NAME(dname), Cin, 1);
+ 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;
+ }
+ if(sp->p - data != len)
+ sp->err = "bad RR len";
+ return rp;
+}
+
+/*
+ * convert the next question from a message
+ */
+static RR*
+convM2Q(Scan *sp)
+{
+ char dname[Domlen+1];
+ int type;
+ int class;
+ RR *rp;
+
+ NAME(dname);
+ USHORT(type);
+ USHORT(class);
+ if(sp->err)
+ return 0;
+
+ rp = rralloc(type);
+ rp->owner = dnlookup(dname, class, 1);
+
+ return rp;
+}
+
+static RR*
+rrloop(Scan *sp, int count, int quest)
+{
+ int i;
+ static char errbuf[64];
+ RR *first, *rp, **l;
+
+ if(sp->err)
+ return 0;
+ l = &first;
+ first = 0;
+ for(i = 0; i < count; i++){
+ rp = quest ? convM2Q(sp) : convM2RR(sp);
+ if(rp == 0)
+ break;
+ if(sp->err){
+ rrfree(rp);
+ break;
+ }
+ *l = rp;
+ l = &rp->next;
+ }
+ return first;
+}
+
+/*
+ * convert the next DNS from a message stream
+ */
+char*
+convM2DNS(uchar *buf, int len, DNSmsg *m)
+{
+ Scan scan;
+ Scan *sp;
+ char *err;
+
+ scan.base = buf;
+ scan.p = buf;
+ scan.ep = buf + len;
+ scan.err = 0;
+ sp = &scan;
+ memset(m, 0, sizeof(DNSmsg));
+ USHORT(m->id);
+ USHORT(m->flags);
+ USHORT(m->qdcount);
+ USHORT(m->ancount);
+ USHORT(m->nscount);
+ USHORT(m->arcount);
+ m->qd = rrloop(sp, m->qdcount, 1);
+ m->an = rrloop(sp, m->ancount, 0);
+ m->ns = rrloop(sp, m->nscount, 0);
+ err = scan.err; /* live with bad ar's */
+ m->ar = rrloop(sp, m->arcount, 0);
+ return err;
+}