summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/res_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/res_debug.c')
-rw-r--r--src/lib/libc/net/res_debug.c1432
1 files changed, 1039 insertions, 393 deletions
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
index d841293f18..246fefef3c 100644
--- a/src/lib/libc/net/res_debug.c
+++ b/src/lib/libc/net/res_debug.c
@@ -1,9 +1,11 @@
1/* $NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $ */ 1/* $OpenBSD: res_debug.c,v 1.22 2007/10/11 18:36:41 jakob Exp $ */
2 2
3/*- 3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
4 * Copyright (c) 1985, 1990, 1993 6 * Copyright (c) 1985, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
6 * 8 *
7 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
9 * are met: 11 * are met:
@@ -12,11 +14,7 @@
12 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 19 * without specific prior written permission.
22 * 20 *
@@ -50,174 +48,179 @@
50 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 48 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
51 * SOFTWARE. 49 * SOFTWARE.
52 * - 50 * -
51 * Portions Copyright (c) 1995 by International Business Machines, Inc.
52 *
53 * International Business Machines, Inc. (hereinafter called IBM) grants
54 * permission under its copyrights to use, copy, modify, and distribute this
55 * Software with or without fee, provided that the above copyright notice and
56 * all paragraphs of this notice appear in all copies, and that the name of IBM
57 * not be used in connection with the marketing of any product incorporating
58 * the Software or modifications thereof, without specific, written prior
59 * permission.
60 *
61 * To the extent it has a right to do so, IBM grants an immunity from suit
62 * under its patents, if any, for the use, sale or manufacture of products to
63 * the extent that such products are used for performing Domain Name System
64 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
65 * granted for any product per se or for any other function of any product.
66 *
67 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
68 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
69 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
70 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
71 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
72 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
53 * --Copyright-- 73 * --Copyright--
54 */ 74 */
55 75
56#if defined(LIBC_SCCS) && !defined(lint)
57#if 0
58static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
59#else
60static char rcsid[] = "$NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $";
61#endif
62#endif /* LIBC_SCCS and not lint */
63
64#include <sys/param.h> 76#include <sys/param.h>
77#include <sys/types.h>
78#include <sys/socket.h>
65#include <netinet/in.h> 79#include <netinet/in.h>
66#include <arpa/inet.h> 80#include <arpa/inet.h>
67#include <arpa/nameser.h> 81#include <arpa/nameser.h>
82
83#include <ctype.h>
84#include <netdb.h>
68#include <resolv.h> 85#include <resolv.h>
69#include <stdio.h> 86#include <stdio.h>
87#include <time.h>
88
89#include <stdlib.h>
70#include <string.h> 90#include <string.h>
71 91
72void __fp_query(); 92#include "thread_private.h"
73char *__p_class(), *__p_time(), *__p_type(); 93
74char *p_cdname(), *p_fqname(), *p_rr(); 94extern const char *_res_opcodes[];
75static char *p_option __P((u_int32_t)); 95extern const char *_res_resultcodes[];
76 96
77char *_res_opcodes[] = { 97static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
78 "QUERY", 98
79 "IQUERY", 99/* XXX: we should use getservbyport() instead. */
80 "CQUERYM", 100static const char *
81 "CQUERYU", 101dewks(int wks)
82 "4",
83 "5",
84 "6",
85 "7",
86 "8",
87 "UPDATEA",
88 "UPDATED",
89 "UPDATEDA",
90 "UPDATEM",
91 "UPDATEMA",
92 "ZONEINIT",
93 "ZONEREF",
94};
95
96char *_res_resultcodes[] = {
97 "NOERROR",
98 "FORMERR",
99 "SERVFAIL",
100 "NXDOMAIN",
101 "NOTIMP",
102 "REFUSED",
103 "6",
104 "7",
105 "8",
106 "9",
107 "10",
108 "11",
109 "12",
110 "13",
111 "14",
112 "NOCHANGE",
113};
114
115static char retbuf[16];
116
117static char *
118dewks(wks)
119 int wks;
120{ 102{
103 static char nbuf[20];
104
121 switch (wks) { 105 switch (wks) {
122 case 5: return("rje"); 106 case 5: return "rje";
123 case 7: return("echo"); 107 case 7: return "echo";
124 case 9: return("discard"); 108 case 9: return "discard";
125 case 11: return("systat"); 109 case 11: return "systat";
126 case 13: return("daytime"); 110 case 13: return "daytime";
127 case 15: return("netstat"); 111 case 15: return "netstat";
128 case 17: return("qotd"); 112 case 17: return "qotd";
129 case 19: return("chargen"); 113 case 19: return "chargen";
130 case 20: return("ftp-data"); 114 case 20: return "ftp-data";
131 case 21: return("ftp"); 115 case 21: return "ftp";
132 case 23: return("telnet"); 116 case 23: return "telnet";
133 case 25: return("smtp"); 117 case 25: return "smtp";
134 case 37: return("time"); 118 case 37: return "time";
135 case 39: return("rlp"); 119 case 39: return "rlp";
136 case 42: return("name"); 120 case 42: return "name";
137 case 43: return("whois"); 121 case 43: return "whois";
138 case 53: return("domain"); 122 case 53: return "domain";
139 case 57: return("apts"); 123 case 57: return "apts";
140 case 59: return("apfs"); 124 case 59: return "apfs";
141 case 67: return("bootps"); 125 case 67: return "bootps";
142 case 68: return("bootpc"); 126 case 68: return "bootpc";
143 case 69: return("tftp"); 127 case 69: return "tftp";
144 case 77: return("rje"); 128 case 77: return "rje";
145 case 79: return("finger"); 129 case 79: return "finger";
146 case 87: return("link"); 130 case 87: return "link";
147 case 95: return("supdup"); 131 case 95: return "supdup";
148 case 100: return("newacct"); 132 case 100: return "newacct";
149 case 101: return("hostnames"); 133 case 101: return "hostnames";
150 case 102: return("iso-tsap"); 134 case 102: return "iso-tsap";
151 case 103: return("x400"); 135 case 103: return "x400";
152 case 104: return("x400-snd"); 136 case 104: return "x400-snd";
153 case 105: return("csnet-ns"); 137 case 105: return "csnet-ns";
154 case 109: return("pop-2"); 138 case 109: return "pop-2";
155 case 111: return("sunrpc"); 139 case 111: return "sunrpc";
156 case 113: return("auth"); 140 case 113: return "auth";
157 case 115: return("sftp"); 141 case 115: return "sftp";
158 case 117: return("uucp-path"); 142 case 117: return "uucp-path";
159 case 119: return("nntp"); 143 case 119: return "nntp";
160 case 121: return("erpc"); 144 case 121: return "erpc";
161 case 123: return("ntp"); 145 case 123: return "ntp";
162 case 133: return("statsrv"); 146 case 133: return "statsrv";
163 case 136: return("profile"); 147 case 136: return "profile";
164 case 144: return("NeWS"); 148 case 144: return "NeWS";
165 case 161: return("snmp"); 149 case 161: return "snmp";
166 case 162: return("snmp-trap"); 150 case 162: return "snmp-trap";
167 case 170: return("print-srv"); 151 case 170: return "print-srv";
168 default: (void) sprintf(retbuf, "%d", wks); return(retbuf); 152 default:
153 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
154 return (nbuf);
169 } 155 }
170} 156}
171 157
172static char * 158/* XXX: we should use getprotobynumber() instead. */
173deproto(protonum) 159static const char *
174 int protonum; 160deproto(int protonum)
175{ 161{
162 static char nbuf[20];
163
176 switch (protonum) { 164 switch (protonum) {
177 case 1: return("icmp"); 165 case 1: return "icmp";
178 case 2: return("igmp"); 166 case 2: return "igmp";
179 case 3: return("ggp"); 167 case 3: return "ggp";
180 case 5: return("st"); 168 case 5: return "st";
181 case 6: return("tcp"); 169 case 6: return "tcp";
182 case 7: return("ucl"); 170 case 7: return "ucl";
183 case 8: return("egp"); 171 case 8: return "egp";
184 case 9: return("igp"); 172 case 9: return "igp";
185 case 11: return("nvp-II"); 173 case 11: return "nvp-II";
186 case 12: return("pup"); 174 case 12: return "pup";
187 case 16: return("chaos"); 175 case 16: return "chaos";
188 case 17: return("udp"); 176 case 17: return "udp";
189 default: (void) sprintf(retbuf, "%d", protonum); return(retbuf); 177 default:
178 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
179 return (nbuf);
190 } 180 }
191} 181}
192 182
193static char * 183static const u_char *
194do_rrset(msg, cp, cnt, pflag, file, hs) 184do_rrset(const u_char *msg, int len, const u_char *cp, int cnt, int pflag,
195 int cnt, pflag; 185 FILE *file, const char *hs)
196 char *cp,*msg, *hs;
197 FILE *file;
198{ 186{
187 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
199 int n; 188 int n;
200 int sflag; 189 int sflag;
190
201 /* 191 /*
202 * Print answer records 192 * Print answer records.
203 */ 193 */
204 sflag = (_res.pfcode & pflag); 194 sflag = (_resp->pfcode & pflag);
205 if (n = ntohs(cnt)) { 195 if ((n = ntohs(cnt))) {
206 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 196 if ((!_resp->pfcode) ||
207 fprintf(file, hs); 197 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
198 fprintf(file, "%s", hs);
208 while (--n >= 0) { 199 while (--n >= 0) {
209 cp = p_rr(cp, msg, file); 200 if ((!_resp->pfcode) || sflag) {
210 if ((cp-msg) > PACKETSZ) 201 cp = p_rr(cp, msg, file);
202 } else {
203 unsigned int dlen;
204 cp += __dn_skipname(cp, cp + MAXCDNAME);
205 cp += INT16SZ;
206 cp += INT16SZ;
207 cp += INT32SZ;
208 dlen = _getshort((u_char*)cp);
209 cp += INT16SZ;
210 cp += dlen;
211 }
212 if ((cp - msg) > len)
211 return (NULL); 213 return (NULL);
212 } 214 }
213 if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) 215 if ((!_resp->pfcode) ||
216 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
214 putc('\n', file); 217 putc('\n', file);
215 } 218 }
216 return(cp); 219 return (cp);
217} 220}
218 221
219__p_query(msg) 222void
220 char *msg; 223__p_query(const u_char *msg)
221{ 224{
222 __fp_query(msg, stdout); 225 __fp_query(msg, stdout);
223} 226}
@@ -227,19 +230,16 @@ __p_query(msg)
227 * This is intended to be primarily a debugging routine. 230 * This is intended to be primarily a debugging routine.
228 */ 231 */
229void 232void
230__fp_resstat(statp, file) 233__fp_resstat(struct __res_state *statp, FILE *file)
231 struct __res_state *statp;
232 FILE *file;
233{ 234{
234 int bit; 235 u_long mask;
235 236
236 fprintf(file, ";; res options:"); 237 fprintf(file, ";; res options:");
237 if (!statp) 238 if (!statp)
238 statp = &_res; 239 statp = &_res;
239 for (bit = 0; bit < 32; bit++) { /* XXX 32 - bad assumption! */ 240 for (mask = 1; mask != 0; mask <<= 1)
240 if (statp->options & (1<<bit)) 241 if (statp->options & mask)
241 fprintf(file, " %s", p_option(1<<bit)); 242 fprintf(file, " %s", p_option(mask));
242 }
243 putc('\n', file); 243 putc('\n', file);
244} 244}
245 245
@@ -248,109 +248,144 @@ __fp_resstat(statp, file)
248 * This is intended to be primarily a debugging routine. 248 * This is intended to be primarily a debugging routine.
249 */ 249 */
250void 250void
251__fp_query(msg,file) 251__fp_nquery(const u_char *msg, int len, FILE *file)
252 char *msg;
253 FILE *file;
254{ 252{
255 register char *cp; 253 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
256 register HEADER *hp; 254 const u_char *cp, *endMark;
257 register int n; 255 const HEADER *hp;
256 int n;
257
258 if (_res_init(0) == -1)
259 return;
260
261#define TruncTest(x) if (x > endMark) goto trunc
262#define ErrorTest(x) if (x == NULL) goto error
258 263
259 /* 264 /*
260 * Print header fields. 265 * Print header fields.
261 */ 266 */
262 hp = (HEADER *)msg; 267 hp = (HEADER *)msg;
263 cp = msg + sizeof(HEADER); 268 cp = msg + HFIXEDSZ;
264 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { 269 endMark = msg + len;
265 fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d", 270 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
271 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
266 _res_opcodes[hp->opcode], 272 _res_opcodes[hp->opcode],
267 _res_resultcodes[hp->rcode], 273 _res_resultcodes[hp->rcode],
268 ntohs(hp->id)); 274 ntohs(hp->id));
269 putc('\n', file); 275 putc('\n', file);
270 } 276 }
271 putc(';', file); 277 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
272 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { 278 putc(';', file);
273 fprintf(file,"; flags:"); 279 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
280 fprintf(file, "; flags:");
274 if (hp->qr) 281 if (hp->qr)
275 fprintf(file," qr"); 282 fprintf(file, " qr");
276 if (hp->aa) 283 if (hp->aa)
277 fprintf(file," aa"); 284 fprintf(file, " aa");
278 if (hp->tc) 285 if (hp->tc)
279 fprintf(file," tc"); 286 fprintf(file, " tc");
280 if (hp->rd) 287 if (hp->rd)
281 fprintf(file," rd"); 288 fprintf(file, " rd");
282 if (hp->ra) 289 if (hp->ra)
283 fprintf(file," ra"); 290 fprintf(file, " ra");
284 if (hp->pr) 291 if (hp->unused)
285 fprintf(file," pr"); 292 fprintf(file, " UNUSED-BIT-ON");
293 if (hp->ad)
294 fprintf(file, " ad");
295 if (hp->cd)
296 fprintf(file, " cd");
286 } 297 }
287 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { 298 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
288 fprintf(file,"; Ques: %d", ntohs(hp->qdcount)); 299 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
289 fprintf(file,", Ans: %d", ntohs(hp->ancount)); 300 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
290 fprintf(file,", Auth: %d", ntohs(hp->nscount)); 301 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
291 fprintf(file,", Addit: %d\n", ntohs(hp->arcount)); 302 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
292 } 303 }
293#if 0 304 if ((!_resp->pfcode) || (_resp->pfcode &
294 if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) { 305 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
295 putc('\n',file); 306 putc('\n',file);
296 } 307 }
297#endif
298 /* 308 /*
299 * Print question records. 309 * Print question records.
300 */ 310 */
301 if (n = ntohs(hp->qdcount)) { 311 if ((n = ntohs(hp->qdcount))) {
302 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 312 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
303 fprintf(file,";; QUESTIONS:\n"); 313 fprintf(file, ";; QUESTIONS:\n");
304 while (--n >= 0) { 314 while (--n >= 0) {
305 fprintf(file,";;\t"); 315 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
306 cp = p_cdname(cp, msg, file); 316 fprintf(file, ";;\t");
307 if (cp == NULL) 317 TruncTest(cp);
308 return; 318 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
309 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 319 cp = p_cdnname(cp, msg, len, file);
320 else {
321 int n;
322 char name[MAXDNAME];
323
324 if ((n = dn_expand(msg, msg+len, cp, name,
325 sizeof name)) < 0)
326 cp = NULL;
327 else
328 cp += n;
329 }
330 ErrorTest(cp);
331 TruncTest(cp);
332 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
310 fprintf(file, ", type = %s", 333 fprintf(file, ", type = %s",
311 __p_type(_getshort(cp))); 334 __p_type(_getshort((u_char*)cp)));
312 cp += sizeof(u_int16_t); 335 cp += INT16SZ;
313 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) 336 TruncTest(cp);
314 fprintf(file, ", class = %s\n\n", 337 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
315 __p_class(_getshort(cp))); 338 fprintf(file, ", class = %s\n",
316 cp += sizeof(u_int16_t); 339 __p_class(_getshort((u_char*)cp)));
340 cp += INT16SZ;
341 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
342 putc('\n', file);
317 } 343 }
318 } 344 }
319 /* 345 /*
320 * Print authoritative answer records 346 * Print authoritative answer records
321 */ 347 */
322 cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, 348 TruncTest(cp);
349 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
323 ";; ANSWERS:\n"); 350 ";; ANSWERS:\n");
324 if (cp == NULL) 351 ErrorTest(cp);
325 return;
326 352
327 /* 353 /*
328 * print name server records 354 * print name server records
329 */ 355 */
330 cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, 356 TruncTest(cp);
357 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
331 ";; AUTHORITY RECORDS:\n"); 358 ";; AUTHORITY RECORDS:\n");
332 if (!cp) 359 ErrorTest(cp);
333 return;
334 360
361 TruncTest(cp);
335 /* 362 /*
336 * print additional records 363 * print additional records
337 */ 364 */
338 cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file, 365 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
339 ";; ADDITIONAL RECORDS:\n"); 366 ";; ADDITIONAL RECORDS:\n");
340 if (!cp) 367 ErrorTest(cp);
341 return; 368 return;
369 trunc:
370 fprintf(file, "\n;; ...truncated\n");
371 return;
372 error:
373 fprintf(file, "\n;; ...malformed\n");
342} 374}
343 375
344char * 376void
345p_cdname(cp, msg, file) 377__fp_query(const u_char *msg, FILE *file)
346 char *cp, *msg; 378{
347 FILE *file; 379 fp_nquery(msg, PACKETSZ, file);
380}
381
382const u_char *
383__p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file)
348{ 384{
349 char name[MAXDNAME]; 385 char name[MAXDNAME];
350 int n; 386 int n;
351 387
352 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 388 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
353 (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
354 return (NULL); 389 return (NULL);
355 if (name[0] == '\0') 390 if (name[0] == '\0')
356 putc('.', file); 391 putc('.', file);
@@ -359,55 +394,86 @@ p_cdname(cp, msg, file)
359 return (cp + n); 394 return (cp + n);
360} 395}
361 396
362char * 397const u_char *
363p_fqname(cp, msg, file) 398__p_cdname(const u_char *cp, const u_char *msg, FILE *file)
364 char *cp, *msg;
365 FILE *file;
366{ 399{
367 char name[MAXDNAME]; 400 return (p_cdnname(cp, msg, PACKETSZ, file));
368 int n, len; 401}
402
403
404/* Return a fully-qualified domain name from a compressed name (with
405 length supplied). */
406
407const u_char *
408__p_fqnname(const u_char *cp, const u_char *msg, int msglen, char *name, int namelen)
409{
410 int n, newlen;
369 411
370 if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, 412 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
371 (u_char *)cp, (u_char *)name, sizeof(name))) < 0)
372 return (NULL); 413 return (NULL);
373 if (name[0] == '\0') { 414 newlen = strlen(name);
374 putc('.', file); 415 if (newlen == 0 || name[newlen - 1] != '.') {
375 } else { 416 if (newlen + 1 >= namelen) /* Lack space for final dot */
376 fputs(name, file); 417 return (NULL);
377 if (name[strlen(name) - 1] != '.') 418 else
378 putc('.', file); 419 strlcpy(name + newlen, ".", namelen - newlen);
379 } 420 }
380 return (cp + n); 421 return (cp + n);
381} 422}
382 423
424/* XXX: the rest of these functions need to become length-limited, too. (vix)
425 */
426
427const u_char *
428__p_fqname(const u_char *cp, const u_char *msg, FILE *file)
429{
430 char name[MAXDNAME];
431 const u_char *n;
432
433 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
434 if (n == NULL)
435 return (NULL);
436 fputs(name, file);
437 return (n);
438}
439
383/* 440/*
384 * Print resource record fields in human readable form. 441 * Print resource record fields in human readable form.
385 */ 442 */
386char * 443const u_char *
387p_rr(cp, msg, file) 444__p_rr(const u_char *cp, const u_char *msg, FILE *file)
388 char *cp, *msg;
389 FILE *file;
390{ 445{
446 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
391 int type, class, dlen, n, c; 447 int type, class, dlen, n, c;
392 struct in_addr inaddr; 448 struct in_addr inaddr;
393 char *cp1, *cp2; 449 const u_char *cp1, *cp2;
394 u_int32_t tmpttl, t; 450 u_int32_t tmpttl, t;
395 int lcnt; 451 int lcnt;
452 u_int16_t keyflags;
453 char rrname[MAXDNAME]; /* The fqdn of this RR */
454 char base64_key[MAX_KEY_BASE64];
396 455
397 if ((cp = p_fqname(cp, msg, file)) == NULL) 456 if (_res_init(0) == -1) {
457 h_errno = NETDB_INTERNAL;
458 return (NULL);
459 }
460 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
461 if (!cp)
398 return (NULL); /* compression error */ 462 return (NULL); /* compression error */
399 type = _getshort(cp); 463 fputs(rrname, file);
400 cp += sizeof(u_int16_t); 464
401 class = _getshort(cp); 465 type = _getshort((u_char*)cp);
402 cp += sizeof(u_int16_t); 466 cp += INT16SZ;
403 tmpttl = _getlong(cp); 467 class = _getshort((u_char*)cp);
404 cp += sizeof(u_int32_t); 468 cp += INT16SZ;
405 dlen = _getshort(cp); 469 tmpttl = _getlong((u_char*)cp);
406 cp += sizeof(u_int16_t); 470 cp += INT32SZ;
471 dlen = _getshort((u_char*)cp);
472 cp += INT16SZ;
407 cp1 = cp; 473 cp1 = cp;
408 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) 474 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
409 fprintf(file, "\t%lu", tmpttl); 475 fprintf(file, "\t%lu", (u_long)tmpttl);
410 if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) 476 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
411 fprintf(file, "\t%s", __p_class(class)); 477 fprintf(file, "\t%s", __p_class(class));
412 fprintf(file, "\t%s", __p_type(type)); 478 fprintf(file, "\t%s", __p_type(type));
413 /* 479 /*
@@ -418,22 +484,22 @@ p_rr(cp, msg, file)
418 switch (class) { 484 switch (class) {
419 case C_IN: 485 case C_IN:
420 case C_HS: 486 case C_HS:
421 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 487 bcopy(cp, (char *)&inaddr, INADDRSZ);
422 if (dlen == 4) { 488 if (dlen == 4) {
423 fprintf(file,"\t%s", inet_ntoa(inaddr)); 489 fprintf(file, "\t%s", inet_ntoa(inaddr));
424 cp += dlen; 490 cp += dlen;
425 } else if (dlen == 7) { 491 } else if (dlen == 7) {
426 char *address; 492 char *address;
427 u_char protocol; 493 u_char protocol;
428 u_short port; 494 in_port_t port;
429 495
430 address = inet_ntoa(inaddr); 496 address = inet_ntoa(inaddr);
431 cp += sizeof(inaddr); 497 cp += INADDRSZ;
432 protocol = *(u_char*)cp; 498 protocol = *(u_char*)cp;
433 cp += sizeof(u_char); 499 cp += sizeof (u_char);
434 port = _getshort(cp); 500 port = _getshort((u_char*)cp);
435 cp += sizeof(u_int16_t); 501 cp += INT16SZ;
436 fprintf(file, "\t%s\t; proto %d, port %d", 502 fprintf(file, "\t%s\t; proto %u, port %u",
437 address, protocol, port); 503 address, protocol, port);
438 } 504 }
439 break; 505 break;
@@ -448,98 +514,205 @@ p_rr(cp, msg, file)
448 case T_NS: 514 case T_NS:
449 case T_PTR: 515 case T_PTR:
450 putc('\t', file); 516 putc('\t', file);
451 cp = p_fqname(cp, msg, file); 517 if ((cp = p_fqname(cp, msg, file)) == NULL)
518 return (NULL);
452 break; 519 break;
453 520
454 case T_HINFO: 521 case T_HINFO:
455 if (n = *cp++) { 522 case T_ISDN:
456 fprintf(file,"\t%.*s", n, cp); 523 cp2 = cp + dlen;
457 cp += n; 524 (void) fputs("\t\"", file);
525 if ((n = (unsigned char) *cp++) != 0) {
526 for (c = n; c > 0 && cp < cp2; c--) {
527 if (strchr("\n\"\\", *cp))
528 (void) putc('\\', file);
529 (void) putc(*cp++, file);
530 }
458 } 531 }
459 if (n = *cp++) { 532 putc('"', file);
460 fprintf(file,"\t%.*s", n, cp); 533 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
461 cp += n; 534 (void) fputs ("\t\"", file);
535 for (c = n; c > 0 && cp < cp2; c--) {
536 if (strchr("\n\"\\", *cp))
537 (void) putc('\\', file);
538 (void) putc(*cp++, file);
539 }
540 putc('"', file);
541 } else if (type == T_HINFO) {
542 (void) fputs("\"?\"", file);
543 fprintf(file, "\n;; *** Warning *** OS-type missing");
462 } 544 }
463 break; 545 break;
464 546
465 case T_SOA: 547 case T_SOA:
466 putc('\t', file); 548 putc('\t', file);
467 cp = p_fqname(cp, msg, file); /* origin */ 549 if ((cp = p_fqname(cp, msg, file)) == NULL)
550 return (NULL);
468 putc(' ', file); 551 putc(' ', file);
469 cp = p_fqname(cp, msg, file); /* mail addr */ 552 if ((cp = p_fqname(cp, msg, file)) == NULL)
553 return (NULL);
470 fputs(" (\n", file); 554 fputs(" (\n", file);
471 t = _getlong(cp); cp += sizeof(u_int32_t); 555 t = _getlong((u_char*)cp); cp += INT32SZ;
472 fprintf(file,"\t\t\t%lu\t; serial\n", t); 556 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
473 t = _getlong(cp); cp += sizeof(u_int32_t); 557 t = _getlong((u_char*)cp); cp += INT32SZ;
474 fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); 558 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
475 t = _getlong(cp); cp += sizeof(u_int32_t); 559 (u_long)t, __p_time(t));
476 fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); 560 t = _getlong((u_char*)cp); cp += INT32SZ;
477 t = _getlong(cp); cp += sizeof(u_int32_t); 561 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
478 fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t)); 562 (u_long)t, __p_time(t));
479 t = _getlong(cp); cp += sizeof(u_int32_t); 563 t = _getlong((u_char*)cp); cp += INT32SZ;
480 fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t)); 564 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
565 (u_long)t, __p_time(t));
566 t = _getlong((u_char*)cp); cp += INT32SZ;
567 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
568 (u_long)t, __p_time(t));
481 break; 569 break;
482 570
483 case T_MX: 571 case T_MX:
484 case T_AFSDB: 572 case T_AFSDB:
485 fprintf(file,"\t%d ", _getshort(cp)); 573 case T_RT:
486 cp += sizeof(u_int16_t); 574 fprintf(file, "\t%u ", _getshort((u_char*)cp));
487 cp = p_fqname(cp, msg, file); 575 cp += INT16SZ;
576 if ((cp = p_fqname(cp, msg, file)) == NULL)
577 return (NULL);
488 break; 578 break;
489 579
490 case T_TXT: 580 case T_PX:
581 fprintf(file, "\t%u ", _getshort((u_char*)cp));
582 cp += INT16SZ;
583 if ((cp = p_fqname(cp, msg, file)) == NULL)
584 return (NULL);
585 putc(' ', file);
586 if ((cp = p_fqname(cp, msg, file)) == NULL)
587 return (NULL);
588 break;
589
590 case T_X25:
591 cp2 = cp + dlen;
491 (void) fputs("\t\"", file); 592 (void) fputs("\t\"", file);
593 if ((n = (unsigned char) *cp++) != 0) {
594 for (c = n; c > 0 && cp < cp2; c--) {
595 if (strchr("\n\"\\", *cp))
596 (void) putc('\\', file);
597 (void) putc(*cp++, file);
598 }
599 }
600 putc('"', file);
601 break;
602
603 case T_TXT:
604 (void) putc('\t', file);
492 cp2 = cp1 + dlen; 605 cp2 = cp1 + dlen;
493 while (cp < cp2) { 606 while (cp < cp2) {
494 if (n = (unsigned char) *cp++) { 607 putc('"', file);
495 for (c = n; c > 0 && cp < cp2; c--) 608 if ((n = (unsigned char) *cp++)) {
496 if (*cp == '\n') { 609 for (c = n; c > 0 && cp < cp2; c--) {
497 (void) putc('\\', file); 610 if (strchr("\n\"\\", *cp))
498 (void) putc(*cp++, file); 611 (void) putc('\\', file);
499 } else 612 (void) putc(*cp++, file);
500 (void) putc(*cp++, file); 613 }
501 } 614 }
615 putc('"', file);
616 if (cp < cp2)
617 putc(' ', file);
502 } 618 }
503 putc('"', file); 619 break;
504 break; 620
621 case T_NSAP:
622 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
623 cp += dlen;
624 break;
625
626 case T_AAAA: {
627 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
628
629 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
630 cp += dlen;
631 break;
632 }
633
634 case T_LOC: {
635 char t[255];
636
637 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
638 cp += dlen;
639 break;
640 }
641
642 case T_NAPTR: {
643 u_int order, preference;
644
645 order = _getshort(cp); cp += INT16SZ;
646 preference = _getshort(cp); cp += INT16SZ;
647 fprintf(file, "\t%u %u ",order, preference);
648 /* Flags */
649 n = *cp++;
650 fprintf(file,"\"%.*s\" ", (int)n, cp);
651 cp += n;
652 /* Service */
653 n = *cp++;
654 fprintf(file,"\"%.*s\" ", (int)n, cp);
655 cp += n;
656 /* Regexp */
657 n = *cp++;
658 fprintf(file,"\"%.*s\" ", (int)n, cp);
659 cp += n;
660 if ((cp = p_fqname(cp, msg, file)) == NULL)
661 return (NULL);
662 break;
663 }
664
665 case T_SRV: {
666 u_int priority, weight, port;
667
668 priority = _getshort(cp); cp += INT16SZ;
669 weight = _getshort(cp); cp += INT16SZ;
670 port = _getshort(cp); cp += INT16SZ;
671 fprintf(file, "\t%u %u %u ", priority, weight, port);
672 if ((cp = p_fqname(cp, msg, file)) == NULL)
673 return (NULL);
674 break;
675 }
505 676
506 case T_MINFO: 677 case T_MINFO:
507 case T_RP: 678 case T_RP:
508 putc('\t', file); 679 putc('\t', file);
509 cp = p_fqname(cp, msg, file); 680 if ((cp = p_fqname(cp, msg, file)) == NULL)
681 return (NULL);
510 putc(' ', file); 682 putc(' ', file);
511 cp = p_fqname(cp, msg, file); 683 if ((cp = p_fqname(cp, msg, file)) == NULL)
684 return (NULL);
512 break; 685 break;
513 686
514 case T_UINFO: 687 case T_UINFO:
515 putc('\t', file); 688 putc('\t', file);
516 fputs(cp, file); 689 fputs((char *)cp, file);
517 cp += dlen; 690 cp += dlen;
518 break; 691 break;
519 692
520 case T_UID: 693 case T_UID:
521 case T_GID: 694 case T_GID:
522 if (dlen == 4) { 695 if (dlen == 4) {
523 fprintf(file,"\t%u", _getlong(cp)); 696 fprintf(file, "\t%u", _getlong((u_char*)cp));
524 cp += sizeof(int32_t); 697 cp += INT32SZ;
525 } 698 }
526 break; 699 break;
527 700
528 case T_WKS: 701 case T_WKS:
529 if (dlen < sizeof(u_int32_t) + 1) 702 if (dlen < INT32SZ + 1)
530 break; 703 break;
531 bcopy(cp, (char *)&inaddr, sizeof(inaddr)); 704 bcopy(cp, (char *)&inaddr, INADDRSZ);
532 cp += sizeof(u_int32_t); 705 cp += INT32SZ;
533 fprintf(file, "\t%s %s ( ", 706 fprintf(file, "\t%s %s ( ",
534 inet_ntoa(inaddr), 707 inet_ntoa(inaddr),
535 deproto((int) *cp)); 708 deproto((int) *cp));
536 cp += sizeof(u_char); 709 cp += sizeof (u_char);
537 n = 0; 710 n = 0;
538 lcnt = 0; 711 lcnt = 0;
539 while (cp < cp1 + dlen) { 712 while (cp < cp1 + dlen) {
540 c = *cp++; 713 c = *cp++;
541 do { 714 do {
542 if (c & 0200) { 715 if (c & 0200) {
543 if (lcnt == 0) { 716 if (lcnt == 0) {
544 fputs("\n\t\t\t", file); 717 fputs("\n\t\t\t", file);
545 lcnt = 5; 718 lcnt = 5;
@@ -548,17 +721,84 @@ p_rr(cp, msg, file)
548 putc(' ', file); 721 putc(' ', file);
549 lcnt--; 722 lcnt--;
550 } 723 }
551 c <<= 1; 724 c <<= 1;
552 } while (++n & 07); 725 } while (++n & 07);
553 } 726 }
554 putc(')', file); 727 putc(')', file);
555 break; 728 break;
556 729
730 case T_KEY:
731 putc('\t', file);
732 keyflags = _getshort(cp);
733 cp += 2;
734 fprintf(file,"0x%04x", keyflags ); /* flags */
735 fprintf(file," %u", *cp++); /* protocol */
736 fprintf(file," %u (", *cp++); /* algorithm */
737
738 n = b64_ntop(cp, (cp1 + dlen) - cp,
739 base64_key, sizeof base64_key);
740 for (c = 0; c < n; ++c) {
741 if (0 == (c & 0x3F))
742 fprintf(file, "\n\t");
743 putc(base64_key[c], file); /* public key data */
744 }
745
746 fprintf(file, " )");
747 if (n < 0)
748 fprintf(file, "\t; BAD BASE64");
749 fflush(file);
750 cp = cp1 + dlen;
751 break;
752
753 case T_SIG:
754 case T_RRSIG:
755 type = _getshort((u_char*)cp);
756 cp += INT16SZ;
757 fprintf(file, " %s", p_type(type));
758 fprintf(file, "\t%u", *cp++); /* algorithm */
759 /* Check label value and print error if wrong. */
760 n = *cp++;
761 c = dn_count_labels (rrname);
762 if (n != c)
763 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
764 n, c);
765 /* orig ttl */
766 n = _getlong((u_char*)cp);
767 if (n != tmpttl)
768 fprintf(file, " %u", n);
769 cp += INT32SZ;
770 /* sig expire */
771 fprintf(file, " (\n\t%s",
772 __p_secstodate(_getlong((u_char*)cp)));
773 cp += INT32SZ;
774 /* time signed */
775 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
776 cp += INT32SZ;
777 /* sig footprint */
778 fprintf(file," %u ", _getshort((u_char*)cp));
779 cp += INT16SZ;
780 /* signer's name */
781 cp = p_fqname(cp, msg, file);
782 n = b64_ntop(cp, (cp1 + dlen) - cp,
783 base64_key, sizeof base64_key);
784 for (c = 0; c < n; c++) {
785 if (0 == (c & 0x3F))
786 fprintf (file, "\n\t");
787 putc(base64_key[c], file); /* signature */
788 }
789 /* Clean up... */
790 fprintf(file, " )");
791 if (n < 0)
792 fprintf(file, "\t; BAD BASE64");
793 fflush(file);
794 cp = cp1+dlen;
795 break;
796
557#ifdef ALLOW_T_UNSPEC 797#ifdef ALLOW_T_UNSPEC
558 case T_UNSPEC: 798 case T_UNSPEC:
559 { 799 {
560 int NumBytes = 8; 800 int NumBytes = 8;
561 char *DataPtr; 801 u_char *DataPtr;
562 int i; 802 int i;
563 803
564 if (dlen < NumBytes) NumBytes = dlen; 804 if (dlen < NumBytes) NumBytes = dlen;
@@ -572,7 +812,7 @@ p_rr(cp, msg, file)
572#endif /* ALLOW_T_UNSPEC */ 812#endif /* ALLOW_T_UNSPEC */
573 813
574 default: 814 default:
575 fprintf(file,"\t?%d?", type); 815 fprintf(file, "\t?%d?", type);
576 cp += dlen; 816 cp += dlen;
577 } 817 }
578#if 0 818#if 0
@@ -581,136 +821,91 @@ p_rr(cp, msg, file)
581 putc('\n', file); 821 putc('\n', file);
582#endif 822#endif
583 if (cp - cp1 != dlen) { 823 if (cp - cp1 != dlen) {
584 fprintf(file,";; packet size error (found %d, dlen was %d)\n", 824 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
585 cp - cp1, dlen); 825 (long)(cp - cp1), dlen);
586 cp = NULL; 826 cp = NULL;
587 } 827 }
588 return (cp); 828 return (cp);
589} 829}
590 830
591static char nbuf[40]; 831int
592 832__sym_ston(const struct res_sym *syms, char *name, int *success)
593/*
594 * Return a string for the type
595 */
596char *
597__p_type(type)
598 int type;
599{ 833{
600 switch (type) { 834 for (; syms->name != 0; syms++) {
601 case T_A: 835 if (strcasecmp (name, syms->name) == 0) {
602 return("A"); 836 if (success)
603 case T_NS: /* authoritative server */ 837 *success = 1;
604 return("NS"); 838 return (syms->number);
605 case T_CNAME: /* canonical name */ 839 }
606 return("CNAME");
607 case T_SOA: /* start of authority zone */
608 return("SOA");
609 case T_MB: /* mailbox domain name */
610 return("MB");
611 case T_MG: /* mail group member */
612 return("MG");
613 case T_MR: /* mail rename name */
614 return("MR");
615 case T_NULL: /* null resource record */
616 return("NULL");
617 case T_WKS: /* well known service */
618 return("WKS");
619 case T_PTR: /* domain name pointer */
620 return("PTR");
621 case T_HINFO: /* host information */
622 return("HINFO");
623 case T_MINFO: /* mailbox information */
624 return("MINFO");
625 case T_MX: /* mail routing info */
626 return("MX");
627 case T_TXT: /* text */
628 return("TXT");
629 case T_RP: /* responsible person */
630 return("RP");
631 case T_AFSDB: /* AFS cell database */
632 return("AFSDB");
633 case T_AXFR: /* zone transfer */
634 return("AXFR");
635 case T_MAILB: /* mail box */
636 return("MAILB");
637 case T_MAILA: /* mail address */
638 return("MAILA");
639 case T_ANY: /* matches any type */
640 return("ANY");
641 case T_UINFO:
642 return("UINFO");
643 case T_UID:
644 return("UID");
645 case T_GID:
646 return("GID");
647#ifdef ALLOW_T_UNSPEC
648 case T_UNSPEC:
649 return("UNSPEC");
650#endif /* ALLOW_T_UNSPEC */
651
652 default:
653 (void)sprintf(nbuf, "%d", type);
654 return(nbuf);
655 } 840 }
841 if (success)
842 *success = 0;
843 return (syms->number); /* The default value. */
656} 844}
657 845
658/* 846
659 * Return a mnemonic for class 847const char *
660 */ 848__sym_ntop(const struct res_sym *syms, int number, int *success)
661char *
662__p_class(class)
663 int class;
664{ 849{
850 static char unname[20];
665 851
666 switch (class) { 852 for (; syms->name != 0; syms++) {
667 case C_IN: /* internet class */ 853 if (number == syms->number) {
668 return("IN"); 854 if (success)
669 case C_HS: /* hesiod class */ 855 *success = 1;
670 return("HS"); 856 return (syms->humanname);
671 case C_ANY: /* matches any class */ 857 }
672 return("ANY");
673 default:
674 (void)sprintf(nbuf, "%d", class);
675 return(nbuf);
676 } 858 }
859 snprintf(unname, sizeof unname, "%d", number);
860 if (success)
861 *success = 0;
862 return (unname);
677} 863}
678 864
679/* 865/*
680 * Return a mnemonic for an option 866 * Return a mnemonic for an option
681 */ 867 */
682static char * 868const char *
683p_option(option) 869__p_option(u_long option)
684 u_int32_t option;
685{ 870{
871 static char nbuf[40];
872
686 switch (option) { 873 switch (option) {
687 case RES_INIT: return "init"; 874 case RES_INIT: return "init";
688 case RES_DEBUG: return "debug"; 875 case RES_DEBUG: return "debug";
689 case RES_AAONLY: return "aaonly"; 876 case RES_AAONLY: return "aaonly(unimpl)";
690 case RES_USEVC: return "usevc"; 877 case RES_USEVC: return "usevc";
691 case RES_PRIMARY: return "primry"; 878 case RES_PRIMARY: return "primry(unimpl)";
692 case RES_IGNTC: return "igntc"; 879 case RES_IGNTC: return "igntc";
693 case RES_RECURSE: return "recurs"; 880 case RES_RECURSE: return "recurs";
694 case RES_DEFNAMES: return "defnam"; 881 case RES_DEFNAMES: return "defnam";
695 case RES_STAYOPEN: return "styopn"; 882 case RES_STAYOPEN: return "styopn";
696 case RES_DNSRCH: return "dnsrch"; 883 case RES_DNSRCH: return "dnsrch";
697 default: sprintf(nbuf, "?0x%x?", option); return nbuf; 884 case RES_INSECURE1: return "insecure1";
885 case RES_INSECURE2: return "insecure2";
886 case RES_USE_INET6: return "inet6";
887 case RES_USE_EDNS0: return "edns0";
888 default:
889 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
890 return (nbuf);
698 } 891 }
699} 892}
700 893
701/* 894/*
702 * Return a mnemonic for a time to live 895 * Return a mnemonic for a time to live
703 */ 896 */
704char * 897const char *
705__p_time(value) 898p_time(u_int32_t value)
706 u_int32_t value;
707{ 899{
900 static char nbuf[40];
901 char *ebuf;
708 int secs, mins, hours, days; 902 int secs, mins, hours, days;
709 register char *p; 903 char *p;
904 int tmp;
710 905
711 if (value == 0) { 906 if (value == 0) {
712 strcpy(nbuf, "0 secs"); 907 strlcpy(nbuf, "0 secs", sizeof nbuf);
713 return(nbuf); 908 return (nbuf);
714 } 909 }
715 910
716 secs = value % 60; 911 secs = value % 60;
@@ -724,26 +919,477 @@ __p_time(value)
724 919
725#define PLURALIZE(x) x, (x == 1) ? "" : "s" 920#define PLURALIZE(x) x, (x == 1) ? "" : "s"
726 p = nbuf; 921 p = nbuf;
922 ebuf = nbuf + sizeof(nbuf);
727 if (days) { 923 if (days) {
728 (void)sprintf(p, "%d day%s", PLURALIZE(days)); 924 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
729 while (*++p); 925 PLURALIZE(days))) >= ebuf - p || tmp < 0)
926 goto full;
927 p += tmp;
730 } 928 }
731 if (hours) { 929 if (hours) {
732 if (days) 930 if (days)
733 *p++ = ' '; 931 *p++ = ' ';
734 (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); 932 if (p >= ebuf)
735 while (*++p); 933 goto full;
934 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
935 PLURALIZE(hours))) >= ebuf - p || tmp < 0)
936 goto full;
937 p += tmp;
736 } 938 }
737 if (mins) { 939 if (mins) {
738 if (days || hours) 940 if (days || hours)
739 *p++ = ' '; 941 *p++ = ' ';
740 (void)sprintf(p, "%d min%s", PLURALIZE(mins)); 942 if (p >= ebuf)
741 while (*++p); 943 goto full;
944 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
945 PLURALIZE(mins))) >= ebuf - p || tmp < 0)
946 goto full;
947 p += tmp;
742 } 948 }
743 if (secs || ! (days || hours || mins)) { 949 if (secs || ! (days || hours || mins)) {
744 if (days || hours || mins) 950 if (days || hours || mins)
745 *p++ = ' '; 951 *p++ = ' ';
746 (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); 952 if (p >= ebuf)
953 goto full;
954 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
955 PLURALIZE(secs))) >= ebuf - p || tmp < 0)
956 goto full;
747 } 957 }
748 return(nbuf); 958 return (nbuf);
959full:
960 p = nbuf + sizeof(nbuf) - 4;
961 *p++ = '.';
962 *p++ = '.';
963 *p++ = '.';
964 *p++ = '\0';
965 return (nbuf);
966}
967
968/*
969 * routines to convert between on-the-wire RR format and zone file format.
970 * Does not contain conversion to/from decimal degrees; divide or multiply
971 * by 60*60*1000 for that.
972 */
973
974static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
975 1000000,10000000,100000000,1000000000};
976
977/* takes an XeY precision/size value, returns a string representation. */
978static const char *
979precsize_ntoa(u_int8_t prec)
980{
981 static char retbuf[sizeof "90000000.00"];
982 unsigned long val;
983 int mantissa, exponent;
984
985 mantissa = (int)((prec >> 4) & 0x0f) % 10;
986 exponent = (int)((prec >> 0) & 0x0f) % 10;
987
988 val = mantissa * poweroften[exponent];
989
990 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
991 return (retbuf);
992}
993
994/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
995static u_int8_t
996precsize_aton(char **strptr)
997{
998 unsigned int mval = 0, cmval = 0;
999 u_int8_t retval = 0;
1000 char *cp;
1001 int exponent;
1002 int mantissa;
1003
1004 cp = *strptr;
1005
1006 while (isdigit(*cp))
1007 mval = mval * 10 + (*cp++ - '0');
1008
1009 if (*cp == '.') { /* centimeters */
1010 cp++;
1011 if (isdigit(*cp)) {
1012 cmval = (*cp++ - '0') * 10;
1013 if (isdigit(*cp)) {
1014 cmval += (*cp++ - '0');
1015 }
1016 }
1017 }
1018 cmval = (mval * 100) + cmval;
1019
1020 for (exponent = 0; exponent < 9; exponent++)
1021 if (cmval < poweroften[exponent+1])
1022 break;
1023
1024 mantissa = cmval / poweroften[exponent];
1025 if (mantissa > 9)
1026 mantissa = 9;
1027
1028 retval = (mantissa << 4) | exponent;
1029
1030 *strptr = cp;
1031
1032 return (retval);
1033}
1034
1035/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1036static u_int32_t
1037latlon2ul(char **latlonstrptr, int *which)
1038{
1039 char *cp;
1040 u_int32_t retval;
1041 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1042
1043 cp = *latlonstrptr;
1044
1045 while (isdigit(*cp))
1046 deg = deg * 10 + (*cp++ - '0');
1047
1048 while (isspace(*cp))
1049 cp++;
1050
1051 if (!(isdigit(*cp)))
1052 goto fndhemi;
1053
1054 while (isdigit(*cp))
1055 min = min * 10 + (*cp++ - '0');
1056
1057 while (isspace(*cp))
1058 cp++;
1059
1060 if (!(isdigit(*cp)))
1061 goto fndhemi;
1062
1063 while (isdigit(*cp))
1064 secs = secs * 10 + (*cp++ - '0');
1065
1066 if (*cp == '.') { /* decimal seconds */
1067 cp++;
1068 if (isdigit(*cp)) {
1069 secsfrac = (*cp++ - '0') * 100;
1070 if (isdigit(*cp)) {
1071 secsfrac += (*cp++ - '0') * 10;
1072 if (isdigit(*cp)) {
1073 secsfrac += (*cp++ - '0');
1074 }
1075 }
1076 }
1077 }
1078
1079 while (!isspace(*cp)) /* if any trailing garbage */
1080 cp++;
1081
1082 while (isspace(*cp))
1083 cp++;
1084
1085 fndhemi:
1086 switch (*cp) {
1087 case 'N': case 'n':
1088 case 'E': case 'e':
1089 retval = ((unsigned)1<<31)
1090 + (((((deg * 60) + min) * 60) + secs) * 1000)
1091 + secsfrac;
1092 break;
1093 case 'S': case 's':
1094 case 'W': case 'w':
1095 retval = ((unsigned)1<<31)
1096 - (((((deg * 60) + min) * 60) + secs) * 1000)
1097 - secsfrac;
1098 break;
1099 default:
1100 retval = 0; /* invalid value -- indicates error */
1101 break;
1102 }
1103
1104 switch (*cp) {
1105 case 'N': case 'n':
1106 case 'S': case 's':
1107 *which = 1; /* latitude */
1108 break;
1109 case 'E': case 'e':
1110 case 'W': case 'w':
1111 *which = 2; /* longitude */
1112 break;
1113 default:
1114 *which = 0; /* error */
1115 break;
1116 }
1117
1118 cp++; /* skip the hemisphere */
1119
1120 while (!isspace(*cp)) /* if any trailing garbage */
1121 cp++;
1122
1123 while (isspace(*cp)) /* move to next field */
1124 cp++;
1125
1126 *latlonstrptr = cp;
1127
1128 return (retval);
1129}
1130
1131/* converts a zone file representation in a string to an RDATA on-the-wire
1132 * representation. */
1133int
1134loc_aton(const char *ascii, u_char *binary)
1135{
1136 const char *maxcp;
1137 u_char *bcp;
1138 char *cp;
1139
1140 u_int32_t latit = 0, longit = 0, alt = 0;
1141 u_int32_t lltemp1 = 0, lltemp2 = 0;
1142 int altmeters = 0, altfrac = 0, altsign = 1;
1143 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1144 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1145 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1146 int which1 = 0, which2 = 0;
1147
1148 cp = (char *)ascii;
1149 maxcp = cp + strlen(ascii);
1150
1151 lltemp1 = latlon2ul(&cp, &which1);
1152
1153 lltemp2 = latlon2ul(&cp, &which2);
1154
1155 switch (which1 + which2) {
1156 case 3: /* 1 + 2, the only valid combination */
1157 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1158 latit = lltemp1;
1159 longit = lltemp2;
1160 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1161 longit = lltemp1;
1162 latit = lltemp2;
1163 } else { /* some kind of brokenness */
1164 return (0);
1165 }
1166 break;
1167 default: /* we didn't get one of each */
1168 return (0);
1169 }
1170
1171 /* altitude */
1172 if (*cp == '-') {
1173 altsign = -1;
1174 cp++;
1175 }
1176
1177 if (*cp == '+')
1178 cp++;
1179
1180 while (isdigit(*cp))
1181 altmeters = altmeters * 10 + (*cp++ - '0');
1182
1183 if (*cp == '.') { /* decimal meters */
1184 cp++;
1185 if (isdigit(*cp)) {
1186 altfrac = (*cp++ - '0') * 10;
1187 if (isdigit(*cp)) {
1188 altfrac += (*cp++ - '0');
1189 }
1190 }
1191 }
1192
1193 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1194
1195 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1196 cp++;
1197
1198 while (isspace(*cp) && (cp < maxcp))
1199 cp++;
1200
1201 if (cp >= maxcp)
1202 goto defaults;
1203
1204 siz = precsize_aton(&cp);
1205
1206 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1207 cp++;
1208
1209 while (isspace(*cp) && (cp < maxcp))
1210 cp++;
1211
1212 if (cp >= maxcp)
1213 goto defaults;
1214
1215 hp = precsize_aton(&cp);
1216
1217 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1218 cp++;
1219
1220 while (isspace(*cp) && (cp < maxcp))
1221 cp++;
1222
1223 if (cp >= maxcp)
1224 goto defaults;
1225
1226 vp = precsize_aton(&cp);
1227
1228 defaults:
1229
1230 bcp = binary;
1231 *bcp++ = (u_int8_t) 0; /* version byte */
1232 *bcp++ = siz;
1233 *bcp++ = hp;
1234 *bcp++ = vp;
1235 PUTLONG(latit,bcp);
1236 PUTLONG(longit,bcp);
1237 PUTLONG(alt,bcp);
1238
1239 return (16); /* size of RR in octets */
1240}
1241
1242const char *
1243loc_ntoa(const u_char *binary, char *ascii)
1244{
1245 return loc_ntoal(binary, ascii, 255);
1246}
1247
1248/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1249static const char *
1250loc_ntoal(const u_char *binary, char *ascii, int ascii_len)
1251{
1252 static char *error = "?";
1253 const u_char *cp = binary;
1254
1255 int latdeg, latmin, latsec, latsecfrac;
1256 int longdeg, longmin, longsec, longsecfrac;
1257 char northsouth, eastwest;
1258 int altmeters, altfrac, altsign;
1259
1260 const int referencealt = 100000 * 100;
1261
1262 int32_t latval, longval, altval;
1263 u_int32_t templ;
1264 u_int8_t sizeval, hpval, vpval, versionval;
1265
1266 char *sizestr, *hpstr, *vpstr;
1267
1268 versionval = *cp++;
1269
1270 if (versionval) {
1271 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1272 return (ascii);
1273 }
1274
1275 sizeval = *cp++;
1276
1277 hpval = *cp++;
1278 vpval = *cp++;
1279
1280 GETLONG(templ, cp);
1281 latval = (templ - ((unsigned)1<<31));
1282
1283 GETLONG(templ, cp);
1284 longval = (templ - ((unsigned)1<<31));
1285
1286 GETLONG(templ, cp);
1287 if (templ < referencealt) { /* below WGS 84 spheroid */
1288 altval = referencealt - templ;
1289 altsign = -1;
1290 } else {
1291 altval = templ - referencealt;
1292 altsign = 1;
1293 }
1294
1295 if (latval < 0) {
1296 northsouth = 'S';
1297 latval = -latval;
1298 } else
1299 northsouth = 'N';
1300
1301 latsecfrac = latval % 1000;
1302 latval = latval / 1000;
1303 latsec = latval % 60;
1304 latval = latval / 60;
1305 latmin = latval % 60;
1306 latval = latval / 60;
1307 latdeg = latval;
1308
1309 if (longval < 0) {
1310 eastwest = 'W';
1311 longval = -longval;
1312 } else
1313 eastwest = 'E';
1314
1315 longsecfrac = longval % 1000;
1316 longval = longval / 1000;
1317 longsec = longval % 60;
1318 longval = longval / 60;
1319 longmin = longval % 60;
1320 longval = longval / 60;
1321 longdeg = longval;
1322
1323 altfrac = altval % 100;
1324 altmeters = (altval / 100) * altsign;
1325
1326 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1327 sizestr = error;
1328 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1329 hpstr = error;
1330 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1331 vpstr = error;
1332
1333 snprintf(ascii, ascii_len,
1334 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1335 latdeg, latmin, latsec, latsecfrac, northsouth,
1336 longdeg, longmin, longsec, longsecfrac, eastwest,
1337 altmeters, altfrac, sizestr, hpstr, vpstr);
1338
1339 if (sizestr != error)
1340 free(sizestr);
1341 if (hpstr != error)
1342 free(hpstr);
1343 if (vpstr != error)
1344 free(vpstr);
1345
1346 return (ascii);
1347}
1348
1349
1350/* Return the number of DNS hierarchy levels in the name. */
1351int
1352__dn_count_labels(char *name)
1353{
1354 int i, len, count;
1355
1356 len = strlen(name);
1357
1358 for(i = 0, count = 0; i < len; i++) {
1359 if (name[i] == '.')
1360 count++;
1361 }
1362
1363 /* don't count initial wildcard */
1364 if (name[0] == '*')
1365 if (count)
1366 count--;
1367
1368 /* don't count the null label for root. */
1369 /* if terminating '.' not found, must adjust */
1370 /* count to include last label */
1371 if (len > 0 && name[len-1] != '.')
1372 count++;
1373 return (count);
1374}
1375
1376
1377/*
1378 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1379 * SIG records are required to be printed like this, by the Secure DNS RFC.
1380 */
1381char *
1382__p_secstodate (long unsigned int secs)
1383{
1384 static char output[15]; /* YYYYMMDDHHMMSS and null */
1385 time_t clock = secs;
1386 struct tm *time;
1387
1388 time = gmtime(&clock);
1389 time->tm_year += 1900;
1390 time->tm_mon += 1;
1391 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1392 time->tm_year, time->tm_mon, time->tm_mday,
1393 time->tm_hour, time->tm_min, time->tm_sec);
1394 return (output);
749} 1395}