diff --git a/sys/src/cmd/ndb/convDNS2M.c b/sys/src/cmd/ndb/convDNS2M.c index 49ca68f56..1e45310b6 100644 --- a/sys/src/cmd/ndb/convDNS2M.c +++ b/sys/src/cmd/ndb/convDNS2M.c @@ -26,7 +26,7 @@ struct Dict #define NAME(x) p = pname(p, ep, x, dp) #define LABEL(x) p = pname(p, ep, x, nil) #define SYMBOL(x) p = psym(p, ep, x) -#define STRING(x) p = pstr(p, ep, x) +#define STRING(x, n) p = pstr(p, ep, x, n) #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) @@ -35,24 +35,21 @@ struct Dict #define V6ADDR(x) p = pv6addr(p, ep, x) static uchar* -psym(uchar *p, uchar *ep, char *np) +pstr(uchar *p, uchar *ep, uchar *s, int n) { - int n; - - n = strlen(np); if(n >= Strlen) /* DNS maximum length string */ - n = Strlen - 1; + n = Strlen-1; if(ep - p < n+1) /* see if it fits in the buffer */ return ep+1; *p++ = n; - memmove(p, np, n); + memmove(p, s, n); return p + n; } static uchar* -pstr(uchar *p, uchar *ep, char *np) +psym(uchar *p, uchar *ep, char *np) { - return psym(p, ep, np); + return pstr(p, ep, (uchar*)np, strlen(np)); } static uchar* @@ -266,7 +263,7 @@ convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp) break; case Ttxt: for(t = rp->txt; t != nil; t = t->next) - STRING(t->p); + STRING(t->data, t->dlen); break; case Tnull: BYTES(rp->null->data, rp->null->dlen); diff --git a/sys/src/cmd/ndb/convM2DNS.c b/sys/src/cmd/ndb/convM2DNS.c index 585cb8d30..c3b81a745 100644 --- a/sys/src/cmd/ndb/convM2DNS.c +++ b/sys/src/cmd/ndb/convM2DNS.c @@ -103,7 +103,7 @@ gv4addr(RR *rp, Scan *sp) char addr[32]; if(sp->err) - return 0; + return nil; if(sp->ep - sp->p < 4) return (DN*)errtoolong(rp, sp, sp->ep - sp->p, 4, "gv4addr"); snprint(addr, sizeof addr, "%V", sp->p); @@ -117,7 +117,7 @@ gv6addr(RR *rp, Scan *sp) char addr[64]; if(sp->err) - return 0; + return nil; if(sp->ep - sp->p < IPaddrlen) return (DN*)errtoolong(rp, sp, sp->ep - sp->p, IPaddrlen, "gv6addr"); @@ -133,20 +133,20 @@ gv6addr(RR *rp, Scan *sp) static DN* gsym(RR *rp, Scan *sp) { + char sym[Strlen]; int n; - char sym[Strlen+1]; if(sp->err) - return 0; + return nil; n = 0; if (sp->p < sp->ep) n = *(sp->p++); if(sp->ep - sp->p < n) return (DN*)errtoolong(rp, sp, sp->ep - sp->p, n, "gsym"); - if(n > Strlen){ + if(n >= Strlen){ sp->err = "illegal string (symbol)"; - return 0; + return nil; } strncpy(sym, (char*)sp->p, n); sym[n] = 0; @@ -164,30 +164,28 @@ static Txt* gstr(RR *rp, Scan *sp) { int n; - char sym[Strlen+1]; Txt *t; if(sp->err) - return 0; + return nil; n = 0; if (sp->p < sp->ep) n = *(sp->p++); if(sp->ep - sp->p < n) return (Txt*)errtoolong(rp, sp, sp->ep - sp->p, n, "gstr"); - if(n > Strlen){ + if(n >= Strlen){ sp->err = "illegal string"; - return 0; + return nil; } - strncpy(sym, (char*)sp->p, n); - sym[n] = 0; - if (strlen(sym) != n) - sp->err = "string shorter than declared length"; - sp->p += n; t = emalloc(sizeof(*t)); t->next = nil; - t->p = estrdup(sym); + t->dlen = n; + t->data = emalloc(n); + memmove(t->data, sp->p, n); + sp->p += n; + return t; } diff --git a/sys/src/cmd/ndb/dblookup.c b/sys/src/cmd/ndb/dblookup.c index aabb0ab71..0d5458778 100644 --- a/sys/src/cmd/ndb/dblookup.c +++ b/sys/src/cmd/ndb/dblookup.c @@ -36,7 +36,6 @@ static RR* doaxfr(Ndb*, char*); static Ndbtuple*look(Ndbtuple*, Ndbtuple*, char*); static RR* mxrr(Ndbtuple*, Ndbtuple*); static RR* nsrr(Ndbtuple*, Ndbtuple*); -static RR* nullrr(Ndbtuple*, Ndbtuple*); static RR* ptrrr(Ndbtuple*, Ndbtuple*); static RR* soarr(Ndbtuple*, Ndbtuple*); static RR* srvrr(Ndbtuple*, Ndbtuple*); @@ -50,7 +49,6 @@ static int implemented[] = [Tcname] 1, [Tmx] 1, [Tns] 1, - [Tnull] 1, [Tptr] 1, [Tsoa] 1, [Tsrv] 1, @@ -228,10 +226,6 @@ dblookup1(char *name, int type, int auth, int ttl) attr2 = "ipv6"; f = addr6rr; break; - case Tnull: - attr = "nullrr"; - f = nullrr; - break; case Tns: attr = "ns"; f = nsrr; @@ -246,7 +240,7 @@ dblookup1(char *name, int type, int auth, int ttl) break; case Ttxt: attr = "txt"; - attr2 = "txtrr"; /* undocumented */ + attr2 = "txtrr"; /* obsolete */ f = txtrr; break; case Tmx: @@ -435,27 +429,17 @@ addrrr(Ndbtuple*, Ndbtuple *pair) return rp; } -static RR* -nullrr(Ndbtuple*, Ndbtuple *pair) -{ - RR *rp; - - rp = rralloc(Tnull); - rp->null->data = (uchar*)estrdup(pair->val); - rp->null->dlen = strlen((char*)rp->null->data); - return rp; -} /* - * txt rr strings are at most 255 bytes long. one + * txt rr strings are at most Strlen-1 bytes long. one * can represent longer strings by multiple concatenated - * <= 255 byte ones. + * < Strlen byte ones. */ static RR* txtrr(Ndbtuple*, Ndbtuple *pair) { RR *rp; Txt *t, **l; - int i, len, sofar; + int i, n, len, sofar; rp = rralloc(Ttxt); l = &rp->txt; @@ -466,14 +450,26 @@ txtrr(Ndbtuple*, Ndbtuple *pair) t = emalloc(sizeof(*t)); t->next = nil; - i = len-sofar; - if(i > 255) - i = 255; + n = len-sofar; + if(n >= Strlen) + n = Strlen-1; + t->data = emalloc(n); - t->p = emalloc(i+1); - memmove(t->p, pair->val+sofar, i); - t->p[i] = 0; - sofar += i; + /* see bslashfmt() */ + for(i = 0; i < n && sofar < len; i++){ + uint c = pair->val[sofar++]; + if(c == '\\' && sofar < len){ + if(pair->val[sofar] >= '0' && pair->val[sofar] <= '7'){ + c = pair->val[sofar++] - '0'; + while(pair->val[sofar] >= '0' && pair->val[sofar] <= '7') + c = (c << 3) | (pair->val[sofar++] - '0'); + } else { + c = pair->val[sofar++]; + } + } + t->data[i] = c; + } + t->dlen = i; *l = t; l = &t->next; @@ -672,9 +668,7 @@ dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair) rp = srvrr(entry, pair); else if(strcmp(pair->attr, "cname") == 0) rp = cnamerr(entry, pair); - else if(strcmp(pair->attr, "nullrr") == 0) - rp = nullrr(entry, pair); - else if(strcmp(pair->attr, "txtrr") == 0) /* undocumented */ + else if(strcmp(pair->attr, "txtrr") == 0) /* obsolete */ rp = txtrr(entry, pair); else if(strcmp(pair->attr, "txt") == 0) rp = txtrr(entry, pair); diff --git a/sys/src/cmd/ndb/dn.c b/sys/src/cmd/ndb/dn.c index 4c3c7f352..377fdd987 100644 --- a/sys/src/cmd/ndb/dn.c +++ b/sys/src/cmd/ndb/dn.c @@ -139,7 +139,6 @@ Lock dnlock; static ulong agefreq = Defagefreq; static int rrequiv(RR *r1, RR *r2); -static int sencodefmt(Fmt*); static void ding(void*, char *msg) @@ -157,9 +156,10 @@ dninit(void) fmtinstall('E', eipfmt); fmtinstall('I', eipfmt); fmtinstall('V', eipfmt); + fmtinstall('\\', bslashfmt); fmtinstall('R', rrfmt); fmtinstall('Q', rravfmt); - fmtinstall('H', sencodefmt); + fmtinstall('H', encodefmt); dnvars.oldest = maxage; dnvars.names = 0; @@ -944,7 +944,9 @@ rrcopy(RR *rp, RR **last) *l = nil; for(t = rp->txt; t != nil; t = t->next){ nt = emalloc(sizeof(*nt)); - nt->p = estrdup(t->p); + nt->dlen = t->dlen; + nt->data = emalloc(t->dlen); + memmove(nt->data, t->data, t->dlen); nt->next = nil; *l = nt; l = &nt->next; @@ -1194,6 +1196,47 @@ idnname(DN *dn, char *buf, int nbuf) return name; } +/* + * txt rr strings can contain binary data such as + * control characters and double quotes (") which would + * collide with ndb(6) format. + * escape special characters by encoding them as: \DDD + * where D is a octal digit. backslash (\) is escaped + * by doubling. valid utf8 is encoded verbatim. + */ +int +bslashfmt(Fmt *f) +{ + int len, out, n, c; + uchar *data; + + out = 0; + len = f->prec; + f->prec = 0; + f->flags &= ~FmtPrec; + data = va_arg(f->args, uchar*); + for(; len > 0; data += n, len -= n){ + if(*data >= Runeself && fullrune((char*)data, len)){ + Rune r; + + n = chartorune(&r, (char*)data); + if(r != Runeerror){ + out += fmtprint(f, "%C", r); + continue; + } + } + c = *data; + if(c < ' ' || c == '"' || c > '~') + out += fmtprint(f, "\\%.3o", c); + else if(c == '\\') + out += fmtprint(f, "\\\\"); + else + out += fmtprint(f, "%c", c); + n = 1; + } + return out; +} + /* * print conversion for rr records */ @@ -1280,7 +1323,7 @@ rrfmt(Fmt *f) case Ttxt: fmtprint(&fstr, "\t"); for(t = rp->txt; t != nil; t = t->next) - fmtprint(&fstr, "%s", t->p); + fmtprint(&fstr, "%.*\\", t->dlen, t->data); break; case Trp: fmtprint(&fstr, "\t%s %s", dnname(rp->rmb), dnname(rp->rp)); @@ -1314,9 +1357,9 @@ rrfmt(Fmt *f) if (rp->caa == nil) fmtprint(&fstr, "\t "); else - fmtprint(&fstr, "\t%d %s %.*s", + fmtprint(&fstr, "\t%d %s %.*\\", rp->caa->flags, dnname(rp->caa->tag), - rp->caa->dlen, (char*)rp->caa->data); + rp->caa->dlen, rp->caa->data); break; } out: @@ -1416,7 +1459,7 @@ rravfmt(Fmt *f) case Ttxt: fmtprint(&fstr, " txt=\""); for(t = rp->txt; t != nil; t = t->next) - fmtprint(&fstr, "%s", t->p); + fmtprint(&fstr, "%.*\\", t->dlen, t->data); fmtprint(&fstr, "\""); break; case Trp: @@ -1453,9 +1496,9 @@ rravfmt(Fmt *f) if (rp->caa == nil) fmtprint(&fstr, " flags= tag= caa="); else - fmtprint(&fstr, " flags=%d tag=%s caa=\"%.*s\"", + fmtprint(&fstr, " flags=%d tag=%s caa=\"%.*\\\"", rp->caa->flags, dnname(rp->caa->tag), - rp->caa->dlen, (char*)rp->caa->data); + rp->caa->dlen, rp->caa->data); break; } out: @@ -1574,14 +1617,14 @@ certequiv(Cert *a, Cert *b) static int txtequiv(Txt *a, Txt *b) { - char *ap, *ae, *bp, *be; + uchar *ap, *ae, *bp, *be; int n; for(ap = ae = bp = be = nil;;ap += n, bp += n){ - while(a != nil && (ap == nil || (ap == ae && (a = a->next) != nil))) - ap = a->p, ae = ap + strlen(ap); - while(b != nil && (bp == nil || (bp == be && (b = b->next) != nil))) - bp = b->p, be = bp + strlen(bp); + while(a != nil && (ap == nil || (ap >= ae && (a = a->next) != nil))) + ap = a->data, ae = ap + a->dlen; + while(b != nil && (bp == nil || (bp >= be && (b = b->next) != nil))) + bp = b->data, be = bp + b->dlen; if(a == b || a == nil || b == nil) break; n = ae - ap; @@ -1709,61 +1752,6 @@ randomize(RR *rp) return first; } -static int -sencodefmt(Fmt *f) -{ - int i, len, ilen, rv; - char *out, *buf; - uchar *b; - char obuf[64]; /* rsc optimization */ - - if(!(f->flags&FmtPrec) || f->prec < 1) - goto error; - - b = va_arg(f->args, uchar*); - if(b == nil) - goto error; - - /* if it's a printable, go for it */ - len = f->prec; - for(i = 0; i < len; i++) - if(!isprint(b[i])) - break; - if(i == len){ - if(len >= sizeof obuf) - len = sizeof(obuf)-1; - memmove(obuf, b, len); - obuf[len] = 0; - fmtstrcpy(f, obuf); - return 0; - } - - ilen = f->prec; - f->prec = 0; - f->flags &= ~FmtPrec; - len = 2*ilen + 1; - if(len > sizeof(obuf)){ - buf = malloc(len); - if(buf == nil) - goto error; - } else - buf = obuf; - - /* convert */ - out = buf; - rv = enc16(out, len, b, ilen); - if(rv < 0) - goto error; - - fmtstrcpy(f, buf); - if(buf != obuf) - free(buf); - return 0; - -error: - return fmtstrcpy(f, ""); -} - void* emalloc(int size) { @@ -2048,7 +2036,7 @@ rrfree(RR *rp) case Ttxt: while(t = rp->txt){ rp->txt = t->next; - free(t->p); + free(t->data); memset(t, 0, sizeof *t); /* cause trouble */ free(t); } diff --git a/sys/src/cmd/ndb/dns.h b/sys/src/cmd/ndb/dns.h index c3d3efcbc..3944c604e 100644 --- a/sys/src/cmd/ndb/dns.h +++ b/sys/src/cmd/ndb/dns.h @@ -251,7 +251,7 @@ struct Null struct Txt { Txt *next; - char *p; + Block; }; /* @@ -436,6 +436,7 @@ extern char *trace; extern int traceactivity; extern char *zonerefreshprogram; +#pragma varargck type "\\" uchar* #pragma varargck type "R" RR* #pragma varargck type "Q" RR* @@ -448,6 +449,7 @@ extern Lock dnlock; void abort(); /* char*, ... */; void addserver(Server**, char*); +int bslashfmt(Fmt*); Server* copyserverlist(Server*); void db2cache(int); void dnage(DN*);