Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#if !defined(_LIBC) && !defined(lint)
static const char rcsid[] = "$BINDId: ns_print.c,v 8.18 2000/02/29 05:48:12 vixie Exp $";
#endif
/* Import. */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <resolv.h>
#include <string.h>
#include <ctype.h>
#define SPRINTF(x) ((size_t)sprintf x)
/* Forward. */
static size_t prune_origin(const char *name, const char *origin);
static int charstr(const u_char *rdata, const u_char *edata,
char **buf, size_t *buflen);
static int addname(const u_char *msg, size_t msglen,
const u_char **p, const char *origin,
char **buf, size_t *buflen);
static void addlen(size_t len, char **buf, size_t *buflen);
static int addstr(const char *src, size_t len,
char **buf, size_t *buflen);
static int addtab(size_t len, size_t target, int spaced,
char **buf, size_t *buflen);
static u_int16_t dst_s_dns_key_id(const u_char *, const int);
/* Macros. */
#define T(x) \
do { \
if ((x) < 0) \
return (-1); \
} while (0)
/* Public. */
/*%
* Convert an RR to presentation format.
*
* return:
*\li Number of characters written to buf, or -1 (check errno).
*/
int
ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
const char *name_ctx, const char *origin,
char *buf, size_t buflen)
{
int n;
n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
name_ctx, origin, buf, buflen);
return (n);
}
libresolv_hidden_def (ns_sprintrr)
/*%
* Convert the fields of an RR into presentation format.
*
* return:
*\li Number of characters written to buf, or -1 (check errno).
*/
int
ns_sprintrrf(const u_char *msg, size_t msglen,
const char *name, ns_class class, ns_type type,
u_long ttl, const u_char *rdata, size_t rdlen,
const char *name_ctx, const char *origin,
char *buf, size_t buflen)
{
const char *obuf = buf;
const u_char *edata = rdata + rdlen;
int spaced = 0;
const char *comment;
char tmp[100];
char errbuf[40];
int len, x;
/*
* Owner.
*/
if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
T(addstr("\t\t\t", 3, &buf, &buflen));
} else {
len = prune_origin(name, origin);
if (*name == '\0') {
goto root;
} else if (len == 0) {
T(addstr("@\t\t\t", 4, &buf, &buflen));
} else {
T(addstr(name, len, &buf, &buflen));
/* Origin not used or not root, and no trailing dot? */
if (((origin == NULL || origin[0] == '\0') ||
(origin[0] != '.' && origin[1] != '\0' &&
name[len] == '\0')) && name[len - 1] != '.') {
root:
T(addstr(".", 1, &buf, &buflen));
len++;
}
T(spaced = addtab(len, 24, spaced, &buf, &buflen));
}
}
/*
* TTL, Class, Type.
*/
T(x = ns_format_ttl(ttl, buf, buflen));
addlen(x, &buf, &buflen);
len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
T(addstr(tmp, len, &buf, &buflen));
T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
/*
* RData.
*/
switch (type) {
case ns_t_a:
if (rdlen != (size_t)NS_INADDRSZ)
goto formerr;
(void) inet_ntop(AF_INET, rdata, buf, buflen);
addlen(strlen(buf), &buf, &buflen);
break;
case ns_t_cname:
case ns_t_mb:
case ns_t_mg:
case ns_t_mr:
case ns_t_ns:
case ns_t_ptr:
case ns_t_dname:
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
case ns_t_hinfo:
case ns_t_isdn:
/* First word. */
T(len = charstr(rdata, edata, &buf, &buflen));
if (len == 0)
goto formerr;
rdata += len;
T(addstr(" ", 1, &buf, &buflen));
/* Second word, optional in ISDN records. */
if (type == ns_t_isdn && rdata == edata)
break;
T(len = charstr(rdata, edata, &buf, &buflen));
if (len == 0)
goto formerr;
rdata += len;
break;
case ns_t_soa: {
u_long t;
/* Server name. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
T(addstr(" ", 1, &buf, &buflen));
/* Administrator name. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
T(addstr(" (\n", 3, &buf, &buflen));
spaced = 0;
if ((edata - rdata) != 5*NS_INT32SZ)
goto formerr;
/* Serial number. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
len = SPRINTF((tmp, "%lu", t));
T(addstr(tmp, len, &buf, &buflen));
T(spaced = addtab(len, 16, spaced, &buf, &buflen));
T(addstr("; serial\n", 9, &buf, &buflen));
spaced = 0;
/* Refresh interval. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
T(len = ns_format_ttl(t, buf, buflen));
addlen(len, &buf, &buflen);
T(spaced = addtab(len, 16, spaced, &buf, &buflen));
T(addstr("; refresh\n", 10, &buf, &buflen));
spaced = 0;
/* Retry interval. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
T(len = ns_format_ttl(t, buf, buflen));
addlen(len, &buf, &buflen);
T(spaced = addtab(len, 16, spaced, &buf, &buflen));
T(addstr("; retry\n", 8, &buf, &buflen));
spaced = 0;
/* Expiry. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
T(len = ns_format_ttl(t, buf, buflen));
addlen(len, &buf, &buflen);
T(spaced = addtab(len, 16, spaced, &buf, &buflen));
T(addstr("; expiry\n", 9, &buf, &buflen));
spaced = 0;
/* Minimum TTL. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
T(len = ns_format_ttl(t, buf, buflen));
addlen(len, &buf, &buflen);
T(addstr(" )", 2, &buf, &buflen));
T(spaced = addtab(len, 16, spaced, &buf, &buflen));
T(addstr("; minimum\n", 10, &buf, &buflen));
break;
}
case ns_t_mx:
case ns_t_afsdb:
case ns_t_rt: {
u_int t;
if (rdlen < (size_t)NS_INT16SZ)
goto formerr;
/* Priority. */
t = ns_get16(rdata);
rdata += NS_INT16SZ;
len = SPRINTF((tmp, "%u ", t));
T(addstr(tmp, len, &buf, &buflen));
/* Target. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
}
case ns_t_px: {
u_int t;
if (rdlen < (size_t)NS_INT16SZ)
goto formerr;
/* Priority. */
t = ns_get16(rdata);
rdata += NS_INT16SZ;
len = SPRINTF((tmp, "%u ", t));
T(addstr(tmp, len, &buf, &buflen));
/* Name1. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
T(addstr(" ", 1, &buf, &buflen));
/* Name2. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
}
case ns_t_x25:
T(len = charstr(rdata, edata, &buf, &buflen));
if (len == 0)
goto formerr;
rdata += len;
break;
case ns_t_txt:
while (rdata < edata) {
T(len = charstr(rdata, edata, &buf, &buflen));
if (len == 0)
goto formerr;
rdata += len;
if (rdata < edata)
T(addstr(" ", 1, &buf, &buflen));
}
break;
case ns_t_nsap: {
char t[2+255*3];
(void) inet_nsap_ntoa(rdlen, rdata, t);
T(addstr(t, strlen(t), &buf, &buflen));
break;
}
case ns_t_aaaa:
if (rdlen != (size_t)NS_IN6ADDRSZ)
goto formerr;
(void) inet_ntop(AF_INET6, rdata, buf, buflen);
addlen(strlen(buf), &buf, &buflen);
break;
case ns_t_loc: {
char t[255];
/* XXX protocol format checking? */
(void) loc_ntoa(rdata, t);
T(addstr(t, strlen(t), &buf, &buflen));
break;
}
case ns_t_naptr: {
u_int order, preference;
char t[50];
if (rdlen < 2U*NS_INT16SZ)
goto formerr;
/* Order, Precedence. */
order = ns_get16(rdata); rdata += NS_INT16SZ;
preference = ns_get16(rdata); rdata += NS_INT16SZ;
len = SPRINTF((t, "%u %u ", order, preference));
T(addstr(t, len, &buf, &buflen));
/* Flags. */
T(len = charstr(rdata, edata, &buf, &buflen));
if (len == 0)
goto formerr;
rdata += len;
T(addstr(" ", 1, &buf, &buflen));
/* Service. */
T(len = charstr(rdata, edata, &buf, &buflen));
if (len == 0)
goto formerr;
rdata += len;
T(addstr(" ", 1, &buf, &buflen));
/* Regexp. */
T(len = charstr(rdata, edata, &buf, &buflen));
if (len < 0)
return (-1);
if (len == 0)
goto formerr;
rdata += len;
T(addstr(" ", 1, &buf, &buflen));
/* Server. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
}
case ns_t_srv: {
u_int priority, weight, port;
char t[50];
if (rdlen < 3U*NS_INT16SZ)
goto formerr;
/* Priority, Weight, Port. */
priority = ns_get16(rdata); rdata += NS_INT16SZ;
weight = ns_get16(rdata); rdata += NS_INT16SZ;
port = ns_get16(rdata); rdata += NS_INT16SZ;
len = SPRINTF((t, "%u %u %u ", priority, weight, port));
T(addstr(t, len, &buf, &buflen));
/* Server. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
}
case ns_t_minfo:
case ns_t_rp:
/* Name1. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
T(addstr(" ", 1, &buf, &buflen));
/* Name2. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
case ns_t_wks: {
int n, lcnt;
if (rdlen < 1U + NS_INT32SZ)
goto formerr;
/* Address. */
(void) inet_ntop(AF_INET, rdata, buf, buflen);
addlen(strlen(buf), &buf, &buflen);
rdata += NS_INADDRSZ;
/* Protocol. */
len = SPRINTF((tmp, " %u ( ", *rdata));
T(addstr(tmp, len, &buf, &buflen));
rdata += NS_INT8SZ;
/* Bit map. */
n = 0;
lcnt = 0;
while (rdata < edata) {
u_int c = *rdata++;
do {
if (c & 0200) {
if (lcnt == 0) {
T(addstr("\n\t\t\t\t", 5,
&buf, &buflen));
lcnt = 10;
spaced = 0;
}
len = SPRINTF((tmp, "%d ", n));
T(addstr(tmp, len, &buf, &buflen));
lcnt--;
}
c <<= 1;
} while (++n & 07);
}
T(addstr(")", 1, &buf, &buflen));
break;
}
case ns_t_key: {
char base64_key[NS_MD5RSA_MAX_BASE64];
u_int keyflags, protocol, algorithm, key_id;
const char *leader;
int n;
if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
goto formerr;
/* Key flags, Protocol, Algorithm. */
key_id = dst_s_dns_key_id(rdata, edata-rdata);
keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
protocol = *rdata++;
algorithm = *rdata++;
len = SPRINTF((tmp, "0x%04x %u %u",
keyflags, protocol, algorithm));
T(addstr(tmp, len, &buf, &buflen));
/* Public key data. */
len = b64_ntop(rdata, edata - rdata,
base64_key, sizeof base64_key);
if (len < 0)
goto formerr;
if (len > 15) {
T(addstr(" (", 2, &buf, &buflen));
leader = "\n\t\t";
spaced = 0;
} else
leader = " ";
for (n = 0; n < len; n += 48) {
T(addstr(leader, strlen(leader), &buf, &buflen));
T(addstr(base64_key + n, MIN(len - n, 48),
&buf, &buflen));
}
if (len > 15)
T(addstr(" )", 2, &buf, &buflen));
n = SPRINTF((tmp, " ; key_tag= %u", key_id));
T(addstr(tmp, n, &buf, &buflen));
break;
}
case ns_t_sig: {
char base64_key[NS_MD5RSA_MAX_BASE64];
u_int type, algorithm, labels, footprint;
const char *leader;
u_long t;
int n;
if (rdlen < 22U)
goto formerr;
/* Type covered, Algorithm, Label count, Original TTL. */
type = ns_get16(rdata); rdata += NS_INT16SZ;
algorithm = *rdata++;
labels = *rdata++;
t = ns_get32(rdata); rdata += NS_INT32SZ;
len = SPRINTF((tmp, "%s %d %d %lu ",
p_type(type), algorithm, labels, t));
T(addstr(tmp, len, &buf, &buflen));
if (labels > (u_int)dn_count_labels(name))
goto formerr;
/* Signature expiry. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
len = SPRINTF((tmp, "%s ", p_secstodate(t)));
T(addstr(tmp, len, &buf, &buflen));
/* Time signed. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
len = SPRINTF((tmp, "%s ", p_secstodate(t)));
T(addstr(tmp, len, &buf, &buflen));
/* Signature Footprint. */
footprint = ns_get16(rdata); rdata += NS_INT16SZ;
len = SPRINTF((tmp, "%u ", footprint));
T(addstr(tmp, len, &buf, &buflen));
/* Signer's name. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
/* Signature. */
len = b64_ntop(rdata, edata - rdata,
base64_key, sizeof base64_key);
if (len > 15) {
T(addstr(" (", 2, &buf, &buflen));
leader = "\n\t\t";
spaced = 0;
} else
leader = " ";
if (len < 0)
goto formerr;
for (n = 0; n < len; n += 48) {
T(addstr(leader, strlen(leader), &buf, &buflen));
T(addstr(base64_key + n, MIN(len - n, 48),
&buf, &buflen));
}
if (len > 15)
T(addstr(" )", 2, &buf, &buflen));
break;
}
case ns_t_nxt: {
int n, c;
/* Next domain name. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
/* Type bit map. */
n = edata - rdata;
for (c = 0; c < n*8; c++)
if (NS_NXT_BIT_ISSET(c, rdata)) {
len = SPRINTF((tmp, " %s", p_type(c)));
T(addstr(tmp, len, &buf, &buflen));
}
break;
}
case ns_t_cert: {
u_int c_type, key_tag, alg;
int n;
unsigned int siz;
char base64_cert[8192], tmp[40];
const char *leader;
c_type = ns_get16(rdata); rdata += NS_INT16SZ;
key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
alg = (u_int) *rdata++;
len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
T(addstr(tmp, len, &buf, &buflen));
siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
if (siz > sizeof(base64_cert) * 3/4) {
const char *str = "record too long to print";
T(addstr(str, strlen(str), &buf, &buflen));
}
else {
len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
if (len < 0)
goto formerr;
else if (len > 15) {
T(addstr(" (", 2, &buf, &buflen));
leader = "\n\t\t";
spaced = 0;
}
else
leader = " ";
for (n = 0; n < len; n += 48) {
T(addstr(leader, strlen(leader),
&buf, &buflen));
T(addstr(base64_cert + n, MIN(len - n, 48),
&buf, &buflen));
}
if (len > 15)
T(addstr(" )", 2, &buf, &buflen));
}
break;
}
case ns_t_tkey: {
/* KJD - need to complete this */
u_long t;
int mode, err, keysize;
/* Algorithm name. */
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
T(addstr(" ", 1, &buf, &buflen));
/* Inception. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
len = SPRINTF((tmp, "%s ", p_secstodate(t)));
T(addstr(tmp, len, &buf, &buflen));
/* Experation. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
len = SPRINTF((tmp, "%s ", p_secstodate(t)));
T(addstr(tmp, len, &buf, &buflen));
/* Mode , Error, Key Size. */
/* Priority, Weight, Port. */
mode = ns_get16(rdata); rdata += NS_INT16SZ;
err = ns_get16(rdata); rdata += NS_INT16SZ;
keysize = ns_get16(rdata); rdata += NS_INT16SZ;
len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
T(addstr(tmp, len, &buf, &buflen));
/* XXX need to dump key, print otherdata length & other data */
break;
}
case ns_t_tsig: {
/* BEW - need to complete this */
int n;
T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
T(addstr(" ", 1, &buf, &buflen));
rdata += 8; /*%< time */
n = ns_get16(rdata); rdata += INT16SZ;
rdata += n; /*%< sig */
n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
sprintf(buf, "%d", ns_get16(rdata));
rdata += INT16SZ;
addlen(strlen(buf), &buf, &buflen);
break;
}
case ns_t_a6: {
struct in6_addr a;
int pbyte, pbit;
/* prefix length */
if (rdlen == 0U) goto formerr;
len = SPRINTF((tmp, "%d ", *rdata));
T(addstr(tmp, len, &buf, &buflen));
pbit = *rdata;
if (pbit > 128) goto formerr;
pbyte = (pbit & ~7) / 8;
rdata++;
/* address suffix: provided only when prefix len != 128 */
if (pbit < 128) {
if (rdata + pbyte >= edata) goto formerr;
memset(&a, 0, sizeof(a));
memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
(void) inet_ntop(AF_INET6, &a, buf, buflen);
addlen(strlen(buf), &buf, &buflen);
rdata += sizeof(a) - pbyte;
}
/* prefix name: provided only when prefix len > 0 */
if (pbit == 0)
break;
if (rdata >= edata) goto formerr;
T(addstr(" ", 1, &buf, &buflen));
T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
break;
}
case ns_t_opt: {
len = SPRINTF((tmp, "%u bytes", class));
T(addstr(tmp, len, &buf, &buflen));
break;
}
default:
snprintf (errbuf, sizeof (errbuf), "unknown RR type %d", type);
comment = errbuf;
goto hexify;
}
return (buf - obuf);
formerr:
comment = "RR format error";
hexify: {
int n, m;
char *p;
len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
rdlen != 0U ? " (" : "", comment));
T(addstr(tmp, len, &buf, &buflen));
while (rdata < edata) {
p = tmp;
p += SPRINTF((p, "\n\t"));
spaced = 0;
n = MIN(16, edata - rdata);
for (m = 0; m < n; m++)
p += SPRINTF((p, "%02x ", rdata[m]));
T(addstr(tmp, p - tmp, &buf, &buflen));
if (n < 16) {
T(addstr(")", 1, &buf, &buflen));
T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
}
p = tmp;
p += SPRINTF((p, "; "));
for (m = 0; m < n; m++)
*p++ = (isascii(rdata[m]) && isprint(rdata[m]))
? rdata[m]
: '.';
T(addstr(tmp, p - tmp, &buf, &buflen));
rdata += n;
}
return (buf - obuf);
}
}
libresolv_hidden_def (ns_sprintrrf)
/* Private. */
/*%
* size_t
* prune_origin(name, origin)
* Find out if the name is at or under the current origin.
* return:
* Number of characters in name before start of origin,
* or length of name if origin does not match.
* notes:
* This function should share code with samedomain().
*/
static size_t
prune_origin(const char *name, const char *origin) {
const char *oname = name;
while (*name != '\0') {
if (origin != NULL && ns_samename(name, origin) == 1)
return (name - oname - (name > oname));
while (*name != '\0') {
if (*name == '\\') {
name++;
/* XXX need to handle \nnn form. */
if (*name == '\0')
break;
} else if (*name == '.') {
name++;
break;
}
name++;
}
}
return (name - oname);
}
/*%
* int
* charstr(rdata, edata, buf, buflen)
* Format a <character-string> into the presentation buffer.
* return:
* Number of rdata octets consumed
* 0 for protocol format error
* -1 for output buffer error
* side effects:
* buffer is advanced on success.
*/
static int
charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
const u_char *odata = rdata;
size_t save_buflen = *buflen;
char *save_buf = *buf;
if (addstr("\"", 1, buf, buflen) < 0)
goto enospc;
if (rdata < edata) {
int n = *rdata;
if (rdata + 1 + n <= edata) {
rdata++;
while (n-- > 0) {
if (strchr("\n\"\\", *rdata) != NULL)
if (addstr("\\", 1, buf, buflen) < 0)
goto enospc;
if (addstr((const char *)rdata, 1,
buf, buflen) < 0)
goto enospc;
rdata++;
}
}
}
if (addstr("\"", 1, buf, buflen) < 0)
goto enospc;
return (rdata - odata);
enospc:
__set_errno (ENOSPC);
*buf = save_buf;
*buflen = save_buflen;
return (-1);
}
static int
addname(const u_char *msg, size_t msglen,
const u_char **pp, const char *origin,
char **buf, size_t *buflen)
{
size_t newlen, save_buflen = *buflen;
char *save_buf = *buf;
int n;
n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
if (n < 0)
goto enospc; /*%< Guess. */
newlen = prune_origin(*buf, origin);
if (**buf == '\0') {
goto root;
} else if (newlen == 0U) {
/* Use "@" instead of name. */
if (newlen + 2 > *buflen)
goto enospc; /* No room for "@\0". */
(*buf)[newlen++] = '@';
(*buf)[newlen] = '\0';
} else {
if (((origin == NULL || origin[0] == '\0') ||
(origin[0] != '.' && origin[1] != '\0' &&
(*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
/* No trailing dot. */
root:
if (newlen + 2 > *buflen)
goto enospc; /* No room for ".\0". */
(*buf)[newlen++] = '.';
(*buf)[newlen] = '\0';
}
}
*pp += n;
addlen(newlen, buf, buflen);
**buf = '\0';
return (newlen);
enospc:
__set_errno (ENOSPC);
*buf = save_buf;
*buflen = save_buflen;
return (-1);
}
static void
addlen(size_t len, char **buf, size_t *buflen) {
assert(len <= *buflen);
*buf += len;
*buflen -= len;
}
static int
addstr(const char *src, size_t len, char **buf, size_t *buflen) {
if (len >= *buflen) {
__set_errno (ENOSPC);
return (-1);
}
memcpy(*buf, src, len);
addlen(len, buf, buflen);
**buf = '\0';
return (0);
}
static int
addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
size_t save_buflen = *buflen;
char *save_buf = *buf;
int t;
if (spaced || len >= target - 1) {
T(addstr(" ", 2, buf, buflen));
spaced = 1;
} else {
for (t = (target - len - 1) / 8; t >= 0; t--)
if (addstr("\t", 1, buf, buflen) < 0) {
*buflen = save_buflen;
*buf = save_buf;
return (-1);
}
spaced = 0;
}
return (spaced);
}
/* DST algorithm codes */
#define KEY_RSA 1
#define KEY_HMAC_MD5 157
/*%
* calculates a checksum used in dst for an id.
* takes an array of bytes and a length.
* returns a 16 bit checksum.
*/
static u_int16_t
dst_s_id_calc(const u_char *key, const int keysize)
{
u_int32_t ac;
const u_char *kp = key;
int size = keysize;
if (!key || (keysize <= 0))
return (0xffffU);
for (ac = 0; size > 1; size -= 2, kp += 2)
ac += ((*kp) << 8) + *(kp + 1);
if (size > 0)
ac += ((*kp) << 8);
ac += (ac >> 16) & 0xffff;
return (ac & 0xffff);
}
/*%
* dst_s_get_int16
* This routine extracts a 16 bit integer from a two byte character
* string. The character string is assumed to be in network byte
* order and may be unaligned. The number returned is in host order.
* Parameter
* buf A two byte character string.
* Return
* The converted integer value.
*/
static u_int16_t
dst_s_get_int16(const u_char *buf)
{
u_int16_t a = 0;
a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
return (a);
}
/*%
* dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record
* rdata
* Input:
* dns_key_rdata: the raw data in wire format
* rdata_len: the size of the input data
* Output:
* the key footprint/id calculated from the key data
*/
static u_int16_t
dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
{
if (!dns_key_rdata)
return 0;
/* compute id */
if (dns_key_rdata[3] == KEY_RSA) /*%< Algorithm RSA */
return dst_s_get_int16((const u_char *)
&dns_key_rdata[rdata_len - 3]);
else if (dns_key_rdata[3] == KEY_HMAC_MD5)
/* compatibility */
return 0;
else
/* compute a checksum on the key part of the key rr */
return dst_s_id_calc(dns_key_rdata, rdata_len);
}
/*! \file */