|
@@ -100,8 +100,7 @@ fmtrr(Msg *m, RR **rrp, int quest)
|
|
|
default:
|
|
|
break;
|
|
|
case Thinfo:
|
|
|
- m->p = seprint(m->p, m->e, " cpu=%s os=%s",
|
|
|
- rr->cpu->name, rr->os->name);
|
|
|
+ m->p = seprint(m->p, m->e, " cpu=%s os=%s", rr->cpu->name, rr->os->name);
|
|
|
break;
|
|
|
case Tcname:
|
|
|
case Tmb:
|
|
@@ -143,29 +142,23 @@ fmtrr(Msg *m, RR **rrp, int quest)
|
|
|
m->p = seprint(m->p, m->e, " txt=%q", t->p);
|
|
|
break;
|
|
|
case Tnull:
|
|
|
- m->p = seprint(m->p, m->e, " null=%.*H",
|
|
|
- rr->null->dlen, rr->null->data);
|
|
|
+ m->p = seprint(m->p, m->e, " null=%.*H", rr->null->dlen, rr->null->data);
|
|
|
break;
|
|
|
case Trp:
|
|
|
m->p = seprint(m->p, m->e, " rmb=%s", rr->rmb->name);
|
|
|
m->p = seprint(m->p, m->e, " rp=%s", rr->rp->name);
|
|
|
break;
|
|
|
case Tkey:
|
|
|
- m->p = seprint(m->p, m->e, " flags=%d proto=%d alg=%d data=%.*H",
|
|
|
- rr->key->flags, rr->key->proto, rr->key->alg,
|
|
|
- rr->key->dlen, rr->key->data);
|
|
|
+ m->p = seprint(m->p, m->e, " flags=%d proto=%d alg=%d data=%.*H", rr->key->flags, rr->key->proto, rr->key->alg, rr->key->dlen, rr->key->data);
|
|
|
break;
|
|
|
case Tsig:
|
|
|
- m->p = seprint(m->p, m->e,
|
|
|
-" type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s data=%.*H",
|
|
|
+ m->p = seprint(m->p, m->e, " type=%d alg=%d labels=%d ttl=%lud exp=%lud incep=%lud tag=%d signer=%s data=%.*H",
|
|
|
rr->sig->type, rr->sig->alg, rr->sig->labels,
|
|
|
rr->sig->ttl, rr->sig->exp, rr->sig->incep, rr->sig->tag,
|
|
|
rr->sig->signer->name, rr->sig->dlen, rr->sig->data);
|
|
|
break;
|
|
|
case Tcert:
|
|
|
- m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d data=%.*H",
|
|
|
- rr->cert->type, rr->cert->tag, rr->cert->alg,
|
|
|
- rr->cert->dlen, rr->cert->data);
|
|
|
+ m->p = seprint(m->p, m->e, " type=%d tag=%d alg=%d data=%.*H", rr->cert->type, rr->cert->tag, rr->cert->alg, rr->cert->dlen, rr->cert->data);
|
|
|
break;
|
|
|
}
|
|
|
rrfree(rr);
|
|
@@ -182,7 +175,7 @@ p_seprint(Msg *m)
|
|
|
{
|
|
|
char *e;
|
|
|
|
|
|
- if((e = convM2DNS(m->ps, m->pe-m->ps, &dm, nil)) != nil){
|
|
|
+ if((e = convM2DNS(m->ps, m->pe-m->ps, &dm)) != nil){
|
|
|
m->p = seprint(m->p, m->e, "error: %s", e);
|
|
|
return 0;
|
|
|
}
|
|
@@ -351,30 +344,13 @@ freealldn(void)
|
|
|
}
|
|
|
|
|
|
|
|
|
-ulong now = 0;
|
|
|
+#define now 0
|
|
|
|
|
|
/*************************************************
|
|
|
- * Everything below here is copied from /sys/src/cmd/ndb/dn.c
|
|
|
- * without modification and can be recopied to update.
|
|
|
- */
|
|
|
-
|
|
|
-/*
|
|
|
- * convert an integer RR type to it's ascii name
|
|
|
- */
|
|
|
-char*
|
|
|
-rrname(int type, char *buf, int len)
|
|
|
-{
|
|
|
- char *t;
|
|
|
-
|
|
|
- t = nil;
|
|
|
- if(type >= 0 && type <= Tall)
|
|
|
- t = rrtname[type];
|
|
|
- if(t==nil){
|
|
|
- snprint(buf, len, "%d", type);
|
|
|
- t = buf;
|
|
|
- }
|
|
|
- return t;
|
|
|
-}
|
|
|
+ Everything below here is copied from /sys/src/cmd/ndb
|
|
|
+ without modification and can be recopied to update.
|
|
|
+ First parts from dn.c, then all of convM2DNS.c.
|
|
|
+*/
|
|
|
|
|
|
/*
|
|
|
* free a list of resource records and any related structs
|
|
@@ -490,3 +466,457 @@ rrfree(RR *rp)
|
|
|
rp->magic = ~rp->magic;
|
|
|
free(rp);
|
|
|
}
|
|
|
+
|
|
|
+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;
|
|
|
+}
|