1ee65b806SJan Lentfer /*
2ee65b806SJan Lentfer * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
3ee65b806SJan Lentfer * Copyright (c) 1996-1999 by Internet Software Consortium.
4ee65b806SJan Lentfer *
5ee65b806SJan Lentfer * Permission to use, copy, modify, and distribute this software for any
6ee65b806SJan Lentfer * purpose with or without fee is hereby granted, provided that the above
7ee65b806SJan Lentfer * copyright notice and this permission notice appear in all copies.
8ee65b806SJan Lentfer *
9ee65b806SJan Lentfer * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10ee65b806SJan Lentfer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11ee65b806SJan Lentfer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12ee65b806SJan Lentfer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13ee65b806SJan Lentfer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14ee65b806SJan Lentfer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15ee65b806SJan Lentfer * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*fbfb85d2SSascha Wildner *
17*fbfb85d2SSascha Wildner * $Id: ns_print.c,v 1.10 2005/04/27 04:56:40 sra Exp $
18ee65b806SJan Lentfer */
19ee65b806SJan Lentfer
20ee65b806SJan Lentfer /* Import. */
21ee65b806SJan Lentfer
22ee65b806SJan Lentfer #include "port_before.h"
23ee65b806SJan Lentfer
24ee65b806SJan Lentfer #include <sys/types.h>
25ee65b806SJan Lentfer #include <sys/socket.h>
26ee65b806SJan Lentfer
27ee65b806SJan Lentfer #include <netinet/in.h>
28ee65b806SJan Lentfer #include <arpa/nameser.h>
29ee65b806SJan Lentfer #include <arpa/inet.h>
30ee65b806SJan Lentfer
31ee65b806SJan Lentfer #ifdef _LIBC
32ee65b806SJan Lentfer #include <assert.h>
33ee65b806SJan Lentfer #define INSIST(cond) assert(cond)
34ee65b806SJan Lentfer #else
35ee65b806SJan Lentfer #include <isc/assertions.h>
36ee65b806SJan Lentfer #include <isc/dst.h>
37ee65b806SJan Lentfer #endif
38ee65b806SJan Lentfer #include <errno.h>
39ee65b806SJan Lentfer #include <resolv.h>
40ee65b806SJan Lentfer #include <string.h>
41ee65b806SJan Lentfer #include <ctype.h>
42ee65b806SJan Lentfer
43ee65b806SJan Lentfer #include "port_after.h"
44ee65b806SJan Lentfer
45ee65b806SJan Lentfer #ifdef SPRINTF_CHAR
46ee65b806SJan Lentfer # define SPRINTF(x) strlen(sprintf/**/x)
47ee65b806SJan Lentfer #else
48ee65b806SJan Lentfer # define SPRINTF(x) ((size_t)sprintf x)
49ee65b806SJan Lentfer #endif
50ee65b806SJan Lentfer
51ee65b806SJan Lentfer /* Forward. */
52ee65b806SJan Lentfer
53ee65b806SJan Lentfer static size_t prune_origin(const char *name, const char *origin);
54ee65b806SJan Lentfer static int charstr(const u_char *rdata, const u_char *edata,
55ee65b806SJan Lentfer char **buf, size_t *buflen);
56ee65b806SJan Lentfer static int addname(const u_char *msg, size_t msglen,
57ee65b806SJan Lentfer const u_char **p, const char *origin,
58ee65b806SJan Lentfer char **buf, size_t *buflen);
59ee65b806SJan Lentfer static void addlen(size_t len, char **buf, size_t *buflen);
60ee65b806SJan Lentfer static int addstr(const char *src, size_t len,
61ee65b806SJan Lentfer char **buf, size_t *buflen);
62ee65b806SJan Lentfer static int addtab(size_t len, size_t target, int spaced,
63ee65b806SJan Lentfer char **buf, size_t *buflen);
64ee65b806SJan Lentfer
65ee65b806SJan Lentfer /* Macros. */
66ee65b806SJan Lentfer
67ee65b806SJan Lentfer #define T(x) \
68ee65b806SJan Lentfer do { \
69ee65b806SJan Lentfer if ((x) < 0) \
70ee65b806SJan Lentfer return (-1); \
71ee65b806SJan Lentfer } while (0)
72ee65b806SJan Lentfer
73ee65b806SJan Lentfer /* Public. */
74ee65b806SJan Lentfer
75ee65b806SJan Lentfer /*%
76ee65b806SJan Lentfer * Convert an RR to presentation format.
77ee65b806SJan Lentfer *
78ee65b806SJan Lentfer * return:
79ee65b806SJan Lentfer *\li Number of characters written to buf, or -1 (check errno).
80ee65b806SJan Lentfer */
81ee65b806SJan Lentfer int
ns_sprintrr(const ns_msg * handle,const ns_rr * rr,const char * name_ctx,const char * origin,char * buf,size_t buflen)82ee65b806SJan Lentfer ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
83ee65b806SJan Lentfer const char *name_ctx, const char *origin,
84ee65b806SJan Lentfer char *buf, size_t buflen)
85ee65b806SJan Lentfer {
86ee65b806SJan Lentfer int n;
87ee65b806SJan Lentfer
88ee65b806SJan Lentfer n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
89ee65b806SJan Lentfer ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
90ee65b806SJan Lentfer ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
91ee65b806SJan Lentfer name_ctx, origin, buf, buflen);
92ee65b806SJan Lentfer return (n);
93ee65b806SJan Lentfer }
94ee65b806SJan Lentfer
95ee65b806SJan Lentfer /*%
96ee65b806SJan Lentfer * Convert the fields of an RR into presentation format.
97ee65b806SJan Lentfer *
98ee65b806SJan Lentfer * return:
99ee65b806SJan Lentfer *\li Number of characters written to buf, or -1 (check errno).
100ee65b806SJan Lentfer */
101ee65b806SJan Lentfer 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)102ee65b806SJan Lentfer ns_sprintrrf(const u_char *msg, size_t msglen,
103ee65b806SJan Lentfer const char *name, ns_class class, ns_type type,
104ee65b806SJan Lentfer u_long ttl, const u_char *rdata, size_t rdlen,
105ee65b806SJan Lentfer const char *name_ctx, const char *origin,
106ee65b806SJan Lentfer char *buf, size_t buflen)
107ee65b806SJan Lentfer {
108ee65b806SJan Lentfer const char *obuf = buf;
109ee65b806SJan Lentfer const u_char *edata = rdata + rdlen;
110ee65b806SJan Lentfer int spaced = 0;
111ee65b806SJan Lentfer
112ee65b806SJan Lentfer const char *comment;
113ee65b806SJan Lentfer char tmp[100];
114ee65b806SJan Lentfer int len, x;
115ee65b806SJan Lentfer
116ee65b806SJan Lentfer /*
117ee65b806SJan Lentfer * Owner.
118ee65b806SJan Lentfer */
119ee65b806SJan Lentfer if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
120ee65b806SJan Lentfer T(addstr("\t\t\t", 3, &buf, &buflen));
121ee65b806SJan Lentfer } else {
122ee65b806SJan Lentfer len = prune_origin(name, origin);
123ee65b806SJan Lentfer if (*name == '\0') {
124ee65b806SJan Lentfer goto root;
125ee65b806SJan Lentfer } else if (len == 0) {
126ee65b806SJan Lentfer T(addstr("@\t\t\t", 4, &buf, &buflen));
127ee65b806SJan Lentfer } else {
128ee65b806SJan Lentfer T(addstr(name, len, &buf, &buflen));
129ee65b806SJan Lentfer /* Origin not used or not root, and no trailing dot? */
130ee65b806SJan Lentfer if (((origin == NULL || origin[0] == '\0') ||
131ee65b806SJan Lentfer (origin[0] != '.' && origin[1] != '\0' &&
132ee65b806SJan Lentfer name[len] == '\0')) && name[len - 1] != '.') {
133ee65b806SJan Lentfer root:
134ee65b806SJan Lentfer T(addstr(".", 1, &buf, &buflen));
135ee65b806SJan Lentfer len++;
136ee65b806SJan Lentfer }
137ee65b806SJan Lentfer T(spaced = addtab(len, 24, spaced, &buf, &buflen));
138ee65b806SJan Lentfer }
139ee65b806SJan Lentfer }
140ee65b806SJan Lentfer
141ee65b806SJan Lentfer /*
142ee65b806SJan Lentfer * TTL, Class, Type.
143ee65b806SJan Lentfer */
144ee65b806SJan Lentfer T(x = ns_format_ttl(ttl, buf, buflen));
145ee65b806SJan Lentfer addlen(x, &buf, &buflen);
146ee65b806SJan Lentfer len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
147ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
148ee65b806SJan Lentfer T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
149ee65b806SJan Lentfer
150ee65b806SJan Lentfer /*
151ee65b806SJan Lentfer * RData.
152ee65b806SJan Lentfer */
153ee65b806SJan Lentfer switch (type) {
154ee65b806SJan Lentfer case ns_t_a:
155ee65b806SJan Lentfer if (rdlen != (size_t)NS_INADDRSZ)
156ee65b806SJan Lentfer goto formerr;
157ee65b806SJan Lentfer (void) inet_ntop(AF_INET, rdata, buf, buflen);
158ee65b806SJan Lentfer addlen(strlen(buf), &buf, &buflen);
159ee65b806SJan Lentfer break;
160ee65b806SJan Lentfer
161ee65b806SJan Lentfer case ns_t_cname:
162ee65b806SJan Lentfer case ns_t_mb:
163ee65b806SJan Lentfer case ns_t_mg:
164ee65b806SJan Lentfer case ns_t_mr:
165ee65b806SJan Lentfer case ns_t_ns:
166ee65b806SJan Lentfer case ns_t_ptr:
167ee65b806SJan Lentfer case ns_t_dname:
168ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
169ee65b806SJan Lentfer break;
170ee65b806SJan Lentfer
171ee65b806SJan Lentfer case ns_t_hinfo:
172ee65b806SJan Lentfer case ns_t_isdn:
173ee65b806SJan Lentfer /* First word. */
174ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
175ee65b806SJan Lentfer if (len == 0)
176ee65b806SJan Lentfer goto formerr;
177ee65b806SJan Lentfer rdata += len;
178ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
179ee65b806SJan Lentfer
180ee65b806SJan Lentfer
181ee65b806SJan Lentfer /* Second word, optional in ISDN records. */
182ee65b806SJan Lentfer if (type == ns_t_isdn && rdata == edata)
183ee65b806SJan Lentfer break;
184ee65b806SJan Lentfer
185ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
186ee65b806SJan Lentfer if (len == 0)
187ee65b806SJan Lentfer goto formerr;
188ee65b806SJan Lentfer rdata += len;
189ee65b806SJan Lentfer break;
190ee65b806SJan Lentfer
191ee65b806SJan Lentfer case ns_t_soa: {
192ee65b806SJan Lentfer u_long t;
193ee65b806SJan Lentfer
194ee65b806SJan Lentfer /* Server name. */
195ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
196ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
197ee65b806SJan Lentfer
198ee65b806SJan Lentfer /* Administrator name. */
199ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
200ee65b806SJan Lentfer T(addstr(" (\n", 3, &buf, &buflen));
201ee65b806SJan Lentfer spaced = 0;
202ee65b806SJan Lentfer
203ee65b806SJan Lentfer if ((edata - rdata) != 5*NS_INT32SZ)
204ee65b806SJan Lentfer goto formerr;
205ee65b806SJan Lentfer
206ee65b806SJan Lentfer /* Serial number. */
207ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
208ee65b806SJan Lentfer T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
209ee65b806SJan Lentfer len = SPRINTF((tmp, "%lu", t));
210ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
211ee65b806SJan Lentfer T(spaced = addtab(len, 16, spaced, &buf, &buflen));
212ee65b806SJan Lentfer T(addstr("; serial\n", 9, &buf, &buflen));
213ee65b806SJan Lentfer spaced = 0;
214ee65b806SJan Lentfer
215ee65b806SJan Lentfer /* Refresh interval. */
216ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
217ee65b806SJan Lentfer T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
218ee65b806SJan Lentfer T(len = ns_format_ttl(t, buf, buflen));
219ee65b806SJan Lentfer addlen(len, &buf, &buflen);
220ee65b806SJan Lentfer T(spaced = addtab(len, 16, spaced, &buf, &buflen));
221ee65b806SJan Lentfer T(addstr("; refresh\n", 10, &buf, &buflen));
222ee65b806SJan Lentfer spaced = 0;
223ee65b806SJan Lentfer
224ee65b806SJan Lentfer /* Retry interval. */
225ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
226ee65b806SJan Lentfer T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
227ee65b806SJan Lentfer T(len = ns_format_ttl(t, buf, buflen));
228ee65b806SJan Lentfer addlen(len, &buf, &buflen);
229ee65b806SJan Lentfer T(spaced = addtab(len, 16, spaced, &buf, &buflen));
230ee65b806SJan Lentfer T(addstr("; retry\n", 8, &buf, &buflen));
231ee65b806SJan Lentfer spaced = 0;
232ee65b806SJan Lentfer
233ee65b806SJan Lentfer /* Expiry. */
234ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
235ee65b806SJan Lentfer T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
236ee65b806SJan Lentfer T(len = ns_format_ttl(t, buf, buflen));
237ee65b806SJan Lentfer addlen(len, &buf, &buflen);
238ee65b806SJan Lentfer T(spaced = addtab(len, 16, spaced, &buf, &buflen));
239ee65b806SJan Lentfer T(addstr("; expiry\n", 9, &buf, &buflen));
240ee65b806SJan Lentfer spaced = 0;
241ee65b806SJan Lentfer
242ee65b806SJan Lentfer /* Minimum TTL. */
243ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
244ee65b806SJan Lentfer T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
245ee65b806SJan Lentfer T(len = ns_format_ttl(t, buf, buflen));
246ee65b806SJan Lentfer addlen(len, &buf, &buflen);
247ee65b806SJan Lentfer T(addstr(" )", 2, &buf, &buflen));
248ee65b806SJan Lentfer T(spaced = addtab(len, 16, spaced, &buf, &buflen));
249ee65b806SJan Lentfer T(addstr("; minimum\n", 10, &buf, &buflen));
250ee65b806SJan Lentfer
251ee65b806SJan Lentfer break;
252ee65b806SJan Lentfer }
253ee65b806SJan Lentfer
254ee65b806SJan Lentfer case ns_t_mx:
255ee65b806SJan Lentfer case ns_t_afsdb:
256ee65b806SJan Lentfer case ns_t_rt: {
257ee65b806SJan Lentfer u_int t;
258ee65b806SJan Lentfer
259ee65b806SJan Lentfer if (rdlen < (size_t)NS_INT16SZ)
260ee65b806SJan Lentfer goto formerr;
261ee65b806SJan Lentfer
262ee65b806SJan Lentfer /* Priority. */
263ee65b806SJan Lentfer t = ns_get16(rdata);
264ee65b806SJan Lentfer rdata += NS_INT16SZ;
265ee65b806SJan Lentfer len = SPRINTF((tmp, "%u ", t));
266ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
267ee65b806SJan Lentfer
268ee65b806SJan Lentfer /* Target. */
269ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
270ee65b806SJan Lentfer
271ee65b806SJan Lentfer break;
272ee65b806SJan Lentfer }
273ee65b806SJan Lentfer
274ee65b806SJan Lentfer case ns_t_px: {
275ee65b806SJan Lentfer u_int t;
276ee65b806SJan Lentfer
277ee65b806SJan Lentfer if (rdlen < (size_t)NS_INT16SZ)
278ee65b806SJan Lentfer goto formerr;
279ee65b806SJan Lentfer
280ee65b806SJan Lentfer /* Priority. */
281ee65b806SJan Lentfer t = ns_get16(rdata);
282ee65b806SJan Lentfer rdata += NS_INT16SZ;
283ee65b806SJan Lentfer len = SPRINTF((tmp, "%u ", t));
284ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
285ee65b806SJan Lentfer
286ee65b806SJan Lentfer /* Name1. */
287ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
288ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
289ee65b806SJan Lentfer
290ee65b806SJan Lentfer /* Name2. */
291ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
292ee65b806SJan Lentfer
293ee65b806SJan Lentfer break;
294ee65b806SJan Lentfer }
295ee65b806SJan Lentfer
296ee65b806SJan Lentfer case ns_t_x25:
297ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
298ee65b806SJan Lentfer if (len == 0)
299ee65b806SJan Lentfer goto formerr;
300ee65b806SJan Lentfer rdata += len;
301ee65b806SJan Lentfer break;
302ee65b806SJan Lentfer
303ee65b806SJan Lentfer case ns_t_txt:
304ee65b806SJan Lentfer while (rdata < edata) {
305ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
306ee65b806SJan Lentfer if (len == 0)
307ee65b806SJan Lentfer goto formerr;
308ee65b806SJan Lentfer rdata += len;
309ee65b806SJan Lentfer if (rdata < edata)
310ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
311ee65b806SJan Lentfer }
312ee65b806SJan Lentfer break;
313ee65b806SJan Lentfer
314ee65b806SJan Lentfer case ns_t_nsap: {
315ee65b806SJan Lentfer char t[2+255*3];
316ee65b806SJan Lentfer
317ee65b806SJan Lentfer (void) inet_nsap_ntoa(rdlen, rdata, t);
318ee65b806SJan Lentfer T(addstr(t, strlen(t), &buf, &buflen));
319ee65b806SJan Lentfer break;
320ee65b806SJan Lentfer }
321ee65b806SJan Lentfer
322ee65b806SJan Lentfer case ns_t_aaaa:
323ee65b806SJan Lentfer if (rdlen != (size_t)NS_IN6ADDRSZ)
324ee65b806SJan Lentfer goto formerr;
325ee65b806SJan Lentfer (void) inet_ntop(AF_INET6, rdata, buf, buflen);
326ee65b806SJan Lentfer addlen(strlen(buf), &buf, &buflen);
327ee65b806SJan Lentfer break;
328ee65b806SJan Lentfer
329ee65b806SJan Lentfer case ns_t_loc: {
330ee65b806SJan Lentfer char t[255];
331ee65b806SJan Lentfer
332ee65b806SJan Lentfer /* XXX protocol format checking? */
333ee65b806SJan Lentfer (void) loc_ntoa(rdata, t);
334ee65b806SJan Lentfer T(addstr(t, strlen(t), &buf, &buflen));
335ee65b806SJan Lentfer break;
336ee65b806SJan Lentfer }
337ee65b806SJan Lentfer
338ee65b806SJan Lentfer case ns_t_naptr: {
339ee65b806SJan Lentfer u_int order, preference;
340ee65b806SJan Lentfer char t[50];
341ee65b806SJan Lentfer
342ee65b806SJan Lentfer if (rdlen < 2U*NS_INT16SZ)
343ee65b806SJan Lentfer goto formerr;
344ee65b806SJan Lentfer
345ee65b806SJan Lentfer /* Order, Precedence. */
346ee65b806SJan Lentfer order = ns_get16(rdata); rdata += NS_INT16SZ;
347ee65b806SJan Lentfer preference = ns_get16(rdata); rdata += NS_INT16SZ;
348ee65b806SJan Lentfer len = SPRINTF((t, "%u %u ", order, preference));
349ee65b806SJan Lentfer T(addstr(t, len, &buf, &buflen));
350ee65b806SJan Lentfer
351ee65b806SJan Lentfer /* Flags. */
352ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
353ee65b806SJan Lentfer if (len == 0)
354ee65b806SJan Lentfer goto formerr;
355ee65b806SJan Lentfer rdata += len;
356ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
357ee65b806SJan Lentfer
358ee65b806SJan Lentfer /* Service. */
359ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
360ee65b806SJan Lentfer if (len == 0)
361ee65b806SJan Lentfer goto formerr;
362ee65b806SJan Lentfer rdata += len;
363ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
364ee65b806SJan Lentfer
365ee65b806SJan Lentfer /* Regexp. */
366ee65b806SJan Lentfer T(len = charstr(rdata, edata, &buf, &buflen));
367ee65b806SJan Lentfer if (len < 0)
368ee65b806SJan Lentfer return (-1);
369ee65b806SJan Lentfer if (len == 0)
370ee65b806SJan Lentfer goto formerr;
371ee65b806SJan Lentfer rdata += len;
372ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
373ee65b806SJan Lentfer
374ee65b806SJan Lentfer /* Server. */
375ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
376ee65b806SJan Lentfer break;
377ee65b806SJan Lentfer }
378ee65b806SJan Lentfer
379ee65b806SJan Lentfer case ns_t_srv: {
380ee65b806SJan Lentfer u_int priority, weight, port;
381ee65b806SJan Lentfer char t[50];
382ee65b806SJan Lentfer
383ee65b806SJan Lentfer if (rdlen < 3U*NS_INT16SZ)
384ee65b806SJan Lentfer goto formerr;
385ee65b806SJan Lentfer
386ee65b806SJan Lentfer /* Priority, Weight, Port. */
387ee65b806SJan Lentfer priority = ns_get16(rdata); rdata += NS_INT16SZ;
388ee65b806SJan Lentfer weight = ns_get16(rdata); rdata += NS_INT16SZ;
389ee65b806SJan Lentfer port = ns_get16(rdata); rdata += NS_INT16SZ;
390ee65b806SJan Lentfer len = SPRINTF((t, "%u %u %u ", priority, weight, port));
391ee65b806SJan Lentfer T(addstr(t, len, &buf, &buflen));
392ee65b806SJan Lentfer
393ee65b806SJan Lentfer /* Server. */
394ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
395ee65b806SJan Lentfer break;
396ee65b806SJan Lentfer }
397ee65b806SJan Lentfer
398ee65b806SJan Lentfer case ns_t_minfo:
399ee65b806SJan Lentfer case ns_t_rp:
400ee65b806SJan Lentfer /* Name1. */
401ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
402ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
403ee65b806SJan Lentfer
404ee65b806SJan Lentfer /* Name2. */
405ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
406ee65b806SJan Lentfer
407ee65b806SJan Lentfer break;
408ee65b806SJan Lentfer
409ee65b806SJan Lentfer case ns_t_wks: {
410ee65b806SJan Lentfer int n, lcnt;
411ee65b806SJan Lentfer
412ee65b806SJan Lentfer if (rdlen < 1U + NS_INT32SZ)
413ee65b806SJan Lentfer goto formerr;
414ee65b806SJan Lentfer
415ee65b806SJan Lentfer /* Address. */
416ee65b806SJan Lentfer (void) inet_ntop(AF_INET, rdata, buf, buflen);
417ee65b806SJan Lentfer addlen(strlen(buf), &buf, &buflen);
418ee65b806SJan Lentfer rdata += NS_INADDRSZ;
419ee65b806SJan Lentfer
420ee65b806SJan Lentfer /* Protocol. */
421ee65b806SJan Lentfer len = SPRINTF((tmp, " %u ( ", *rdata));
422ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
423ee65b806SJan Lentfer rdata += NS_INT8SZ;
424ee65b806SJan Lentfer
425ee65b806SJan Lentfer /* Bit map. */
426ee65b806SJan Lentfer n = 0;
427ee65b806SJan Lentfer lcnt = 0;
428ee65b806SJan Lentfer while (rdata < edata) {
429ee65b806SJan Lentfer u_int c = *rdata++;
430ee65b806SJan Lentfer do {
431ee65b806SJan Lentfer if (c & 0200) {
432ee65b806SJan Lentfer if (lcnt == 0) {
433ee65b806SJan Lentfer T(addstr("\n\t\t\t\t", 5,
434ee65b806SJan Lentfer &buf, &buflen));
435ee65b806SJan Lentfer lcnt = 10;
436ee65b806SJan Lentfer spaced = 0;
437ee65b806SJan Lentfer }
438ee65b806SJan Lentfer len = SPRINTF((tmp, "%d ", n));
439ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
440ee65b806SJan Lentfer lcnt--;
441ee65b806SJan Lentfer }
442ee65b806SJan Lentfer c <<= 1;
443ee65b806SJan Lentfer } while (++n & 07);
444ee65b806SJan Lentfer }
445ee65b806SJan Lentfer T(addstr(")", 1, &buf, &buflen));
446ee65b806SJan Lentfer
447ee65b806SJan Lentfer break;
448ee65b806SJan Lentfer }
449ee65b806SJan Lentfer
450ee65b806SJan Lentfer case ns_t_key: {
451ee65b806SJan Lentfer char base64_key[NS_MD5RSA_MAX_BASE64];
452ee65b806SJan Lentfer u_int keyflags, protocol, algorithm, key_id;
453ee65b806SJan Lentfer const char *leader;
454ee65b806SJan Lentfer int n;
455ee65b806SJan Lentfer
456ee65b806SJan Lentfer if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
457ee65b806SJan Lentfer goto formerr;
458ee65b806SJan Lentfer
459ee65b806SJan Lentfer /* Key flags, Protocol, Algorithm. */
460ee65b806SJan Lentfer #ifndef _LIBC
461ee65b806SJan Lentfer key_id = dst_s_dns_key_id(rdata, edata-rdata);
462ee65b806SJan Lentfer #else
463ee65b806SJan Lentfer key_id = 0;
464ee65b806SJan Lentfer #endif
465ee65b806SJan Lentfer keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
466ee65b806SJan Lentfer protocol = *rdata++;
467ee65b806SJan Lentfer algorithm = *rdata++;
468ee65b806SJan Lentfer len = SPRINTF((tmp, "0x%04x %u %u",
469ee65b806SJan Lentfer keyflags, protocol, algorithm));
470ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
471ee65b806SJan Lentfer
472ee65b806SJan Lentfer /* Public key data. */
473ee65b806SJan Lentfer len = b64_ntop(rdata, edata - rdata,
474ee65b806SJan Lentfer base64_key, sizeof base64_key);
475ee65b806SJan Lentfer if (len < 0)
476ee65b806SJan Lentfer goto formerr;
477ee65b806SJan Lentfer if (len > 15) {
478ee65b806SJan Lentfer T(addstr(" (", 2, &buf, &buflen));
479ee65b806SJan Lentfer leader = "\n\t\t";
480ee65b806SJan Lentfer spaced = 0;
481ee65b806SJan Lentfer } else
482ee65b806SJan Lentfer leader = " ";
483ee65b806SJan Lentfer for (n = 0; n < len; n += 48) {
484ee65b806SJan Lentfer T(addstr(leader, strlen(leader), &buf, &buflen));
485ee65b806SJan Lentfer T(addstr(base64_key + n, MIN(len - n, 48),
486ee65b806SJan Lentfer &buf, &buflen));
487ee65b806SJan Lentfer }
488ee65b806SJan Lentfer if (len > 15)
489ee65b806SJan Lentfer T(addstr(" )", 2, &buf, &buflen));
490ee65b806SJan Lentfer n = SPRINTF((tmp, " ; key_tag= %u", key_id));
491ee65b806SJan Lentfer T(addstr(tmp, n, &buf, &buflen));
492ee65b806SJan Lentfer
493ee65b806SJan Lentfer break;
494ee65b806SJan Lentfer }
495ee65b806SJan Lentfer
496ee65b806SJan Lentfer case ns_t_sig: {
497ee65b806SJan Lentfer char base64_key[NS_MD5RSA_MAX_BASE64];
498ee65b806SJan Lentfer u_int type, algorithm, labels, footprint;
499ee65b806SJan Lentfer const char *leader;
500ee65b806SJan Lentfer u_long t;
501ee65b806SJan Lentfer int n;
502ee65b806SJan Lentfer
503ee65b806SJan Lentfer if (rdlen < 22U)
504ee65b806SJan Lentfer goto formerr;
505ee65b806SJan Lentfer
506ee65b806SJan Lentfer /* Type covered, Algorithm, Label count, Original TTL. */
507ee65b806SJan Lentfer type = ns_get16(rdata); rdata += NS_INT16SZ;
508ee65b806SJan Lentfer algorithm = *rdata++;
509ee65b806SJan Lentfer labels = *rdata++;
510ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
511ee65b806SJan Lentfer len = SPRINTF((tmp, "%s %d %d %lu ",
512ee65b806SJan Lentfer p_type(type), algorithm, labels, t));
513ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
514ee65b806SJan Lentfer if (labels > (u_int)dn_count_labels(name))
515ee65b806SJan Lentfer goto formerr;
516ee65b806SJan Lentfer
517ee65b806SJan Lentfer /* Signature expiry. */
518ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
519ee65b806SJan Lentfer len = SPRINTF((tmp, "%s ", p_secstodate(t)));
520ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
521ee65b806SJan Lentfer
522ee65b806SJan Lentfer /* Time signed. */
523ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
524ee65b806SJan Lentfer len = SPRINTF((tmp, "%s ", p_secstodate(t)));
525ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
526ee65b806SJan Lentfer
527ee65b806SJan Lentfer /* Signature Footprint. */
528ee65b806SJan Lentfer footprint = ns_get16(rdata); rdata += NS_INT16SZ;
529ee65b806SJan Lentfer len = SPRINTF((tmp, "%u ", footprint));
530ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
531ee65b806SJan Lentfer
532ee65b806SJan Lentfer /* Signer's name. */
533ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
534ee65b806SJan Lentfer
535ee65b806SJan Lentfer /* Signature. */
536ee65b806SJan Lentfer len = b64_ntop(rdata, edata - rdata,
537ee65b806SJan Lentfer base64_key, sizeof base64_key);
538ee65b806SJan Lentfer if (len > 15) {
539ee65b806SJan Lentfer T(addstr(" (", 2, &buf, &buflen));
540ee65b806SJan Lentfer leader = "\n\t\t";
541ee65b806SJan Lentfer spaced = 0;
542ee65b806SJan Lentfer } else
543ee65b806SJan Lentfer leader = " ";
544ee65b806SJan Lentfer if (len < 0)
545ee65b806SJan Lentfer goto formerr;
546ee65b806SJan Lentfer for (n = 0; n < len; n += 48) {
547ee65b806SJan Lentfer T(addstr(leader, strlen(leader), &buf, &buflen));
548ee65b806SJan Lentfer T(addstr(base64_key + n, MIN(len - n, 48),
549ee65b806SJan Lentfer &buf, &buflen));
550ee65b806SJan Lentfer }
551ee65b806SJan Lentfer if (len > 15)
552ee65b806SJan Lentfer T(addstr(" )", 2, &buf, &buflen));
553ee65b806SJan Lentfer break;
554ee65b806SJan Lentfer }
555ee65b806SJan Lentfer
556ee65b806SJan Lentfer case ns_t_nxt: {
557ee65b806SJan Lentfer int n, c;
558ee65b806SJan Lentfer
559ee65b806SJan Lentfer /* Next domain name. */
560ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
561ee65b806SJan Lentfer
562ee65b806SJan Lentfer /* Type bit map. */
563ee65b806SJan Lentfer n = edata - rdata;
564ee65b806SJan Lentfer for (c = 0; c < n*8; c++)
565ee65b806SJan Lentfer if (NS_NXT_BIT_ISSET(c, rdata)) {
566ee65b806SJan Lentfer len = SPRINTF((tmp, " %s", p_type(c)));
567ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
568ee65b806SJan Lentfer }
569ee65b806SJan Lentfer break;
570ee65b806SJan Lentfer }
571ee65b806SJan Lentfer
572ee65b806SJan Lentfer case ns_t_cert: {
573ee65b806SJan Lentfer u_int c_type, key_tag, alg;
574ee65b806SJan Lentfer int n;
575ee65b806SJan Lentfer unsigned int siz;
576ee65b806SJan Lentfer char base64_cert[8192], tmp[40];
577ee65b806SJan Lentfer const char *leader;
578ee65b806SJan Lentfer
579ee65b806SJan Lentfer c_type = ns_get16(rdata); rdata += NS_INT16SZ;
580ee65b806SJan Lentfer key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
581ee65b806SJan Lentfer alg = (u_int) *rdata++;
582ee65b806SJan Lentfer
583ee65b806SJan Lentfer len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
584ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
585ee65b806SJan Lentfer siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
586ee65b806SJan Lentfer if (siz > sizeof(base64_cert) * 3/4) {
587ee65b806SJan Lentfer const char *str = "record too long to print";
588ee65b806SJan Lentfer T(addstr(str, strlen(str), &buf, &buflen));
589ee65b806SJan Lentfer }
590ee65b806SJan Lentfer else {
591ee65b806SJan Lentfer len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
592ee65b806SJan Lentfer
593ee65b806SJan Lentfer if (len < 0)
594ee65b806SJan Lentfer goto formerr;
595ee65b806SJan Lentfer else if (len > 15) {
596ee65b806SJan Lentfer T(addstr(" (", 2, &buf, &buflen));
597ee65b806SJan Lentfer leader = "\n\t\t";
598ee65b806SJan Lentfer spaced = 0;
599ee65b806SJan Lentfer }
600ee65b806SJan Lentfer else
601ee65b806SJan Lentfer leader = " ";
602ee65b806SJan Lentfer
603ee65b806SJan Lentfer for (n = 0; n < len; n += 48) {
604ee65b806SJan Lentfer T(addstr(leader, strlen(leader),
605ee65b806SJan Lentfer &buf, &buflen));
606ee65b806SJan Lentfer T(addstr(base64_cert + n, MIN(len - n, 48),
607ee65b806SJan Lentfer &buf, &buflen));
608ee65b806SJan Lentfer }
609ee65b806SJan Lentfer if (len > 15)
610ee65b806SJan Lentfer T(addstr(" )", 2, &buf, &buflen));
611ee65b806SJan Lentfer }
612ee65b806SJan Lentfer break;
613ee65b806SJan Lentfer }
614ee65b806SJan Lentfer
615ee65b806SJan Lentfer case ns_t_tkey: {
616ee65b806SJan Lentfer /* KJD - need to complete this */
617ee65b806SJan Lentfer u_long t;
618ee65b806SJan Lentfer int mode, err, keysize;
619ee65b806SJan Lentfer
620ee65b806SJan Lentfer /* Algorithm name. */
621ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
622ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
623ee65b806SJan Lentfer
624ee65b806SJan Lentfer /* Inception. */
625ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
626ee65b806SJan Lentfer len = SPRINTF((tmp, "%s ", p_secstodate(t)));
627ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
628ee65b806SJan Lentfer
629ee65b806SJan Lentfer /* Experation. */
630ee65b806SJan Lentfer t = ns_get32(rdata); rdata += NS_INT32SZ;
631ee65b806SJan Lentfer len = SPRINTF((tmp, "%s ", p_secstodate(t)));
632ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
633ee65b806SJan Lentfer
634ee65b806SJan Lentfer /* Mode , Error, Key Size. */
635ee65b806SJan Lentfer /* Priority, Weight, Port. */
636ee65b806SJan Lentfer mode = ns_get16(rdata); rdata += NS_INT16SZ;
637ee65b806SJan Lentfer err = ns_get16(rdata); rdata += NS_INT16SZ;
638ee65b806SJan Lentfer keysize = ns_get16(rdata); rdata += NS_INT16SZ;
639ee65b806SJan Lentfer len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
640ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
641ee65b806SJan Lentfer
642ee65b806SJan Lentfer /* XXX need to dump key, print otherdata length & other data */
643ee65b806SJan Lentfer break;
644ee65b806SJan Lentfer }
645ee65b806SJan Lentfer
646ee65b806SJan Lentfer case ns_t_tsig: {
647ee65b806SJan Lentfer /* BEW - need to complete this */
648ee65b806SJan Lentfer int n;
649ee65b806SJan Lentfer
650ee65b806SJan Lentfer T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
651ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
652ee65b806SJan Lentfer rdata += 8; /*%< time */
653ee65b806SJan Lentfer n = ns_get16(rdata); rdata += INT16SZ;
654ee65b806SJan Lentfer rdata += n; /*%< sig */
655ee65b806SJan Lentfer n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
656ee65b806SJan Lentfer sprintf(buf, "%d", ns_get16(rdata));
657ee65b806SJan Lentfer rdata += INT16SZ;
658ee65b806SJan Lentfer addlen(strlen(buf), &buf, &buflen);
659ee65b806SJan Lentfer break;
660ee65b806SJan Lentfer }
661ee65b806SJan Lentfer
662ee65b806SJan Lentfer case ns_t_a6: {
663ee65b806SJan Lentfer struct in6_addr a;
664ee65b806SJan Lentfer int pbyte, pbit;
665ee65b806SJan Lentfer
666ee65b806SJan Lentfer /* prefix length */
667ee65b806SJan Lentfer if (rdlen == 0U) goto formerr;
668ee65b806SJan Lentfer len = SPRINTF((tmp, "%d ", *rdata));
669ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
670ee65b806SJan Lentfer pbit = *rdata;
671ee65b806SJan Lentfer if (pbit > 128) goto formerr;
672ee65b806SJan Lentfer pbyte = (pbit & ~7) / 8;
673ee65b806SJan Lentfer rdata++;
674ee65b806SJan Lentfer
675ee65b806SJan Lentfer /* address suffix: provided only when prefix len != 128 */
676ee65b806SJan Lentfer if (pbit < 128) {
677ee65b806SJan Lentfer if (rdata + pbyte >= edata) goto formerr;
678ee65b806SJan Lentfer memset(&a, 0, sizeof(a));
679ee65b806SJan Lentfer memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
680ee65b806SJan Lentfer (void) inet_ntop(AF_INET6, &a, buf, buflen);
681ee65b806SJan Lentfer addlen(strlen(buf), &buf, &buflen);
682ee65b806SJan Lentfer rdata += sizeof(a) - pbyte;
683ee65b806SJan Lentfer }
684ee65b806SJan Lentfer
685ee65b806SJan Lentfer /* prefix name: provided only when prefix len > 0 */
686ee65b806SJan Lentfer if (pbit == 0)
687ee65b806SJan Lentfer break;
688ee65b806SJan Lentfer if (rdata >= edata) goto formerr;
689ee65b806SJan Lentfer T(addstr(" ", 1, &buf, &buflen));
690ee65b806SJan Lentfer T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
691ee65b806SJan Lentfer
692ee65b806SJan Lentfer break;
693ee65b806SJan Lentfer }
694ee65b806SJan Lentfer
695ee65b806SJan Lentfer case ns_t_opt: {
696ee65b806SJan Lentfer len = SPRINTF((tmp, "%u bytes", class));
697ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
698ee65b806SJan Lentfer break;
699ee65b806SJan Lentfer }
700ee65b806SJan Lentfer
701ee65b806SJan Lentfer default:
702ee65b806SJan Lentfer comment = "unknown RR type";
703ee65b806SJan Lentfer goto hexify;
704ee65b806SJan Lentfer }
705ee65b806SJan Lentfer return (buf - obuf);
706ee65b806SJan Lentfer formerr:
707ee65b806SJan Lentfer comment = "RR format error";
708ee65b806SJan Lentfer hexify: {
709ee65b806SJan Lentfer int n, m;
710ee65b806SJan Lentfer char *p;
711ee65b806SJan Lentfer
712ee65b806SJan Lentfer len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
713ee65b806SJan Lentfer rdlen != 0U ? " (" : "", comment));
714ee65b806SJan Lentfer T(addstr(tmp, len, &buf, &buflen));
715ee65b806SJan Lentfer while (rdata < edata) {
716ee65b806SJan Lentfer p = tmp;
717ee65b806SJan Lentfer p += SPRINTF((p, "\n\t"));
718ee65b806SJan Lentfer spaced = 0;
719ee65b806SJan Lentfer n = MIN(16, edata - rdata);
720ee65b806SJan Lentfer for (m = 0; m < n; m++)
721ee65b806SJan Lentfer p += SPRINTF((p, "%02x ", rdata[m]));
722ee65b806SJan Lentfer T(addstr(tmp, p - tmp, &buf, &buflen));
723ee65b806SJan Lentfer if (n < 16) {
724ee65b806SJan Lentfer T(addstr(")", 1, &buf, &buflen));
725ee65b806SJan Lentfer T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
726ee65b806SJan Lentfer }
727ee65b806SJan Lentfer p = tmp;
728ee65b806SJan Lentfer p += SPRINTF((p, "; "));
729ee65b806SJan Lentfer for (m = 0; m < n; m++)
730ee65b806SJan Lentfer *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
731ee65b806SJan Lentfer ? rdata[m]
732ee65b806SJan Lentfer : '.';
733ee65b806SJan Lentfer T(addstr(tmp, p - tmp, &buf, &buflen));
734ee65b806SJan Lentfer rdata += n;
735ee65b806SJan Lentfer }
736ee65b806SJan Lentfer return (buf - obuf);
737ee65b806SJan Lentfer }
738ee65b806SJan Lentfer }
739ee65b806SJan Lentfer
740ee65b806SJan Lentfer /* Private. */
741ee65b806SJan Lentfer
742ee65b806SJan Lentfer /*%
743ee65b806SJan Lentfer * size_t
744ee65b806SJan Lentfer * prune_origin(name, origin)
745ee65b806SJan Lentfer * Find out if the name is at or under the current origin.
746ee65b806SJan Lentfer * return:
747ee65b806SJan Lentfer * Number of characters in name before start of origin,
748ee65b806SJan Lentfer * or length of name if origin does not match.
749ee65b806SJan Lentfer * notes:
750ee65b806SJan Lentfer * This function should share code with samedomain().
751ee65b806SJan Lentfer */
752ee65b806SJan Lentfer static size_t
prune_origin(const char * name,const char * origin)753ee65b806SJan Lentfer prune_origin(const char *name, const char *origin) {
754ee65b806SJan Lentfer const char *oname = name;
755ee65b806SJan Lentfer
756ee65b806SJan Lentfer while (*name != '\0') {
757ee65b806SJan Lentfer if (origin != NULL && ns_samename(name, origin) == 1)
758ee65b806SJan Lentfer return (name - oname - (name > oname));
759ee65b806SJan Lentfer while (*name != '\0') {
760ee65b806SJan Lentfer if (*name == '\\') {
761ee65b806SJan Lentfer name++;
762ee65b806SJan Lentfer /* XXX need to handle \nnn form. */
763ee65b806SJan Lentfer if (*name == '\0')
764ee65b806SJan Lentfer break;
765ee65b806SJan Lentfer } else if (*name == '.') {
766ee65b806SJan Lentfer name++;
767ee65b806SJan Lentfer break;
768ee65b806SJan Lentfer }
769ee65b806SJan Lentfer name++;
770ee65b806SJan Lentfer }
771ee65b806SJan Lentfer }
772ee65b806SJan Lentfer return (name - oname);
773ee65b806SJan Lentfer }
774ee65b806SJan Lentfer
775ee65b806SJan Lentfer /*%
776ee65b806SJan Lentfer * int
777ee65b806SJan Lentfer * charstr(rdata, edata, buf, buflen)
778ee65b806SJan Lentfer * Format a <character-string> into the presentation buffer.
779ee65b806SJan Lentfer * return:
780ee65b806SJan Lentfer * Number of rdata octets consumed
781ee65b806SJan Lentfer * 0 for protocol format error
782ee65b806SJan Lentfer * -1 for output buffer error
783ee65b806SJan Lentfer * side effects:
784ee65b806SJan Lentfer * buffer is advanced on success.
785ee65b806SJan Lentfer */
786ee65b806SJan Lentfer static int
charstr(const u_char * rdata,const u_char * edata,char ** buf,size_t * buflen)787ee65b806SJan Lentfer charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
788ee65b806SJan Lentfer const u_char *odata = rdata;
789ee65b806SJan Lentfer size_t save_buflen = *buflen;
790ee65b806SJan Lentfer char *save_buf = *buf;
791ee65b806SJan Lentfer
792ee65b806SJan Lentfer if (addstr("\"", 1, buf, buflen) < 0)
793ee65b806SJan Lentfer goto enospc;
794ee65b806SJan Lentfer if (rdata < edata) {
795ee65b806SJan Lentfer int n = *rdata;
796ee65b806SJan Lentfer
797ee65b806SJan Lentfer if (rdata + 1 + n <= edata) {
798ee65b806SJan Lentfer rdata++;
799ee65b806SJan Lentfer while (n-- > 0) {
800ee65b806SJan Lentfer if (strchr("\n\"\\", *rdata) != NULL)
801ee65b806SJan Lentfer if (addstr("\\", 1, buf, buflen) < 0)
802ee65b806SJan Lentfer goto enospc;
803ee65b806SJan Lentfer if (addstr((const char *)rdata, 1,
804ee65b806SJan Lentfer buf, buflen) < 0)
805ee65b806SJan Lentfer goto enospc;
806ee65b806SJan Lentfer rdata++;
807ee65b806SJan Lentfer }
808ee65b806SJan Lentfer }
809ee65b806SJan Lentfer }
810ee65b806SJan Lentfer if (addstr("\"", 1, buf, buflen) < 0)
811ee65b806SJan Lentfer goto enospc;
812ee65b806SJan Lentfer return (rdata - odata);
813ee65b806SJan Lentfer enospc:
814ee65b806SJan Lentfer errno = ENOSPC;
815ee65b806SJan Lentfer *buf = save_buf;
816ee65b806SJan Lentfer *buflen = save_buflen;
817ee65b806SJan Lentfer return (-1);
818ee65b806SJan Lentfer }
819ee65b806SJan Lentfer
820ee65b806SJan Lentfer static int
addname(const u_char * msg,size_t msglen,const u_char ** pp,const char * origin,char ** buf,size_t * buflen)821ee65b806SJan Lentfer addname(const u_char *msg, size_t msglen,
822ee65b806SJan Lentfer const u_char **pp, const char *origin,
823ee65b806SJan Lentfer char **buf, size_t *buflen)
824ee65b806SJan Lentfer {
825ee65b806SJan Lentfer size_t newlen, save_buflen = *buflen;
826ee65b806SJan Lentfer char *save_buf = *buf;
827ee65b806SJan Lentfer int n;
828ee65b806SJan Lentfer
829ee65b806SJan Lentfer n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
830ee65b806SJan Lentfer if (n < 0)
831ee65b806SJan Lentfer goto enospc; /*%< Guess. */
832ee65b806SJan Lentfer newlen = prune_origin(*buf, origin);
833ee65b806SJan Lentfer if (**buf == '\0') {
834ee65b806SJan Lentfer goto root;
835ee65b806SJan Lentfer } else if (newlen == 0U) {
836ee65b806SJan Lentfer /* Use "@" instead of name. */
837ee65b806SJan Lentfer if (newlen + 2 > *buflen)
838ee65b806SJan Lentfer goto enospc; /* No room for "@\0". */
839ee65b806SJan Lentfer (*buf)[newlen++] = '@';
840ee65b806SJan Lentfer (*buf)[newlen] = '\0';
841ee65b806SJan Lentfer } else {
842ee65b806SJan Lentfer if (((origin == NULL || origin[0] == '\0') ||
843ee65b806SJan Lentfer (origin[0] != '.' && origin[1] != '\0' &&
844ee65b806SJan Lentfer (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
845ee65b806SJan Lentfer /* No trailing dot. */
846ee65b806SJan Lentfer root:
847ee65b806SJan Lentfer if (newlen + 2 > *buflen)
848ee65b806SJan Lentfer goto enospc; /* No room for ".\0". */
849ee65b806SJan Lentfer (*buf)[newlen++] = '.';
850ee65b806SJan Lentfer (*buf)[newlen] = '\0';
851ee65b806SJan Lentfer }
852ee65b806SJan Lentfer }
853ee65b806SJan Lentfer *pp += n;
854ee65b806SJan Lentfer addlen(newlen, buf, buflen);
855ee65b806SJan Lentfer **buf = '\0';
856ee65b806SJan Lentfer return (newlen);
857ee65b806SJan Lentfer enospc:
858ee65b806SJan Lentfer errno = ENOSPC;
859ee65b806SJan Lentfer *buf = save_buf;
860ee65b806SJan Lentfer *buflen = save_buflen;
861ee65b806SJan Lentfer return (-1);
862ee65b806SJan Lentfer }
863ee65b806SJan Lentfer
864ee65b806SJan Lentfer static void
addlen(size_t len,char ** buf,size_t * buflen)865ee65b806SJan Lentfer addlen(size_t len, char **buf, size_t *buflen) {
866ee65b806SJan Lentfer INSIST(len <= *buflen);
867ee65b806SJan Lentfer *buf += len;
868ee65b806SJan Lentfer *buflen -= len;
869ee65b806SJan Lentfer }
870ee65b806SJan Lentfer
871ee65b806SJan Lentfer static int
addstr(const char * src,size_t len,char ** buf,size_t * buflen)872ee65b806SJan Lentfer addstr(const char *src, size_t len, char **buf, size_t *buflen) {
873ee65b806SJan Lentfer if (len >= *buflen) {
874ee65b806SJan Lentfer errno = ENOSPC;
875ee65b806SJan Lentfer return (-1);
876ee65b806SJan Lentfer }
877ee65b806SJan Lentfer memcpy(*buf, src, len);
878ee65b806SJan Lentfer addlen(len, buf, buflen);
879ee65b806SJan Lentfer **buf = '\0';
880ee65b806SJan Lentfer return (0);
881ee65b806SJan Lentfer }
882ee65b806SJan Lentfer
883ee65b806SJan Lentfer static int
addtab(size_t len,size_t target,int spaced,char ** buf,size_t * buflen)884ee65b806SJan Lentfer addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
885ee65b806SJan Lentfer size_t save_buflen = *buflen;
886ee65b806SJan Lentfer char *save_buf = *buf;
887ee65b806SJan Lentfer int t;
888ee65b806SJan Lentfer
889ee65b806SJan Lentfer if (spaced || len >= target - 1) {
890ee65b806SJan Lentfer T(addstr(" ", 2, buf, buflen));
891ee65b806SJan Lentfer spaced = 1;
892ee65b806SJan Lentfer } else {
893ee65b806SJan Lentfer for (t = (target - len - 1) / 8; t >= 0; t--)
894ee65b806SJan Lentfer if (addstr("\t", 1, buf, buflen) < 0) {
895ee65b806SJan Lentfer *buflen = save_buflen;
896ee65b806SJan Lentfer *buf = save_buf;
897ee65b806SJan Lentfer return (-1);
898ee65b806SJan Lentfer }
899ee65b806SJan Lentfer spaced = 0;
900ee65b806SJan Lentfer }
901ee65b806SJan Lentfer return (spaced);
902ee65b806SJan Lentfer }
903ee65b806SJan Lentfer
904ee65b806SJan Lentfer /*! \file */
905