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