Back to index

glibc  2.9
ns_print.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (c) 1996-1999 by Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
00010  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00011  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
00012  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00013  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00014  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00015  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00016  * SOFTWARE.
00017  */
00018 
00019 #if !defined(_LIBC) && !defined(lint)
00020 static const char rcsid[] = "$BINDId: ns_print.c,v 8.18 2000/02/29 05:48:12 vixie Exp $";
00021 #endif
00022 
00023 /* Import. */
00024 
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 
00028 #include <netinet/in.h>
00029 #include <arpa/nameser.h>
00030 #include <arpa/inet.h>
00031 
00032 #include <assert.h>
00033 #include <errno.h>
00034 #include <resolv.h>
00035 #include <string.h>
00036 #include <ctype.h>
00037 
00038 #define SPRINTF(x) ((size_t)sprintf x)
00039 
00040 /* Forward. */
00041 
00042 static size_t prune_origin(const char *name, const char *origin);
00043 static int    charstr(const u_char *rdata, const u_char *edata,
00044                      char **buf, size_t *buflen);
00045 static int    addname(const u_char *msg, size_t msglen,
00046                      const u_char **p, const char *origin,
00047                      char **buf, size_t *buflen);
00048 static void   addlen(size_t len, char **buf, size_t *buflen);
00049 static int    addstr(const char *src, size_t len,
00050                      char **buf, size_t *buflen);
00051 static int    addtab(size_t len, size_t target, int spaced,
00052                      char **buf, size_t *buflen);
00053 
00054 static u_int16_t dst_s_dns_key_id(const u_char *, const int);
00055 
00056 /* Macros. */
00057 
00058 #define       T(x) \
00059        do { \
00060               if ((x) < 0) \
00061                      return (-1); \
00062        } while (0)
00063 
00064 /* Public. */
00065 
00066 /*%
00067  *     Convert an RR to presentation format.
00068  *
00069  * return:
00070  *\li  Number of characters written to buf, or -1 (check errno).
00071  */
00072 int
00073 ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
00074            const char *name_ctx, const char *origin,
00075            char *buf, size_t buflen)
00076 {
00077        int n;
00078 
00079        n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
00080                       ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
00081                       ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
00082                       name_ctx, origin, buf, buflen);
00083        return (n);
00084 }
00085 libresolv_hidden_def (ns_sprintrr)
00086 
00087 /*%
00088  *     Convert the fields of an RR into presentation format.
00089  *
00090  * return:
00091  *\li  Number of characters written to buf, or -1 (check errno).
00092  */
00093 int
00094 ns_sprintrrf(const u_char *msg, size_t msglen,
00095            const char *name, ns_class class, ns_type type,
00096            u_long ttl, const u_char *rdata, size_t rdlen,
00097            const char *name_ctx, const char *origin,
00098            char *buf, size_t buflen)
00099 {
00100        const char *obuf = buf;
00101        const u_char *edata = rdata + rdlen;
00102        int spaced = 0;
00103 
00104        const char *comment;
00105        char tmp[100];
00106        char errbuf[40];
00107        int len, x;
00108 
00109        /*
00110         * Owner.
00111         */
00112        if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
00113               T(addstr("\t\t\t", 3, &buf, &buflen));
00114        } else {
00115               len = prune_origin(name, origin);
00116               if (*name == '\0') {
00117                      goto root;
00118               } else if (len == 0) {
00119                      T(addstr("@\t\t\t", 4, &buf, &buflen));
00120               } else {
00121                      T(addstr(name, len, &buf, &buflen));
00122                      /* Origin not used or not root, and no trailing dot? */
00123                      if (((origin == NULL || origin[0] == '\0') ||
00124                           (origin[0] != '.' && origin[1] != '\0' &&
00125                            name[len] == '\0')) && name[len - 1] != '.') {
00126  root:
00127                             T(addstr(".", 1, &buf, &buflen));
00128                             len++;
00129                      }
00130                      T(spaced = addtab(len, 24, spaced, &buf, &buflen));
00131               }
00132        }
00133 
00134        /*
00135         * TTL, Class, Type.
00136         */
00137        T(x = ns_format_ttl(ttl, buf, buflen));
00138        addlen(x, &buf, &buflen);
00139        len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
00140        T(addstr(tmp, len, &buf, &buflen));
00141        T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
00142 
00143        /*
00144         * RData.
00145         */
00146        switch (type) {
00147        case ns_t_a:
00148          if (rdlen != (size_t)NS_INADDRSZ)
00149                      goto formerr;
00150               (void) inet_ntop(AF_INET, rdata, buf, buflen);
00151               addlen(strlen(buf), &buf, &buflen);
00152               break;
00153 
00154        case ns_t_cname:
00155        case ns_t_mb:
00156        case ns_t_mg:
00157        case ns_t_mr:
00158        case ns_t_ns:
00159        case ns_t_ptr:
00160        case ns_t_dname:
00161               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00162               break;
00163 
00164        case ns_t_hinfo:
00165        case ns_t_isdn:
00166               /* First word. */
00167               T(len = charstr(rdata, edata, &buf, &buflen));
00168               if (len == 0)
00169                      goto formerr;
00170               rdata += len;
00171               T(addstr(" ", 1, &buf, &buflen));
00172 
00173 
00174               /* Second word, optional in ISDN records. */
00175               if (type == ns_t_isdn && rdata == edata)
00176                      break;
00177 
00178               T(len = charstr(rdata, edata, &buf, &buflen));
00179               if (len == 0)
00180                      goto formerr;
00181               rdata += len;
00182               break;
00183 
00184        case ns_t_soa: {
00185               u_long t;
00186 
00187               /* Server name. */
00188               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00189               T(addstr(" ", 1, &buf, &buflen));
00190 
00191               /* Administrator name. */
00192               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00193               T(addstr(" (\n", 3, &buf, &buflen));
00194               spaced = 0;
00195 
00196               if ((edata - rdata) != 5*NS_INT32SZ)
00197                      goto formerr;
00198 
00199               /* Serial number. */
00200               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00201               T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
00202               len = SPRINTF((tmp, "%lu", t));
00203               T(addstr(tmp, len, &buf, &buflen));
00204               T(spaced = addtab(len, 16, spaced, &buf, &buflen));
00205               T(addstr("; serial\n", 9, &buf, &buflen));
00206               spaced = 0;
00207 
00208               /* Refresh interval. */
00209               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00210               T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
00211               T(len = ns_format_ttl(t, buf, buflen));
00212               addlen(len, &buf, &buflen);
00213               T(spaced = addtab(len, 16, spaced, &buf, &buflen));
00214               T(addstr("; refresh\n", 10, &buf, &buflen));
00215               spaced = 0;
00216 
00217               /* Retry interval. */
00218               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00219               T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
00220               T(len = ns_format_ttl(t, buf, buflen));
00221               addlen(len, &buf, &buflen);
00222               T(spaced = addtab(len, 16, spaced, &buf, &buflen));
00223               T(addstr("; retry\n", 8, &buf, &buflen));
00224               spaced = 0;
00225 
00226               /* Expiry. */
00227               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00228               T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
00229               T(len = ns_format_ttl(t, buf, buflen));
00230               addlen(len, &buf, &buflen);
00231               T(spaced = addtab(len, 16, spaced, &buf, &buflen));
00232               T(addstr("; expiry\n", 9, &buf, &buflen));
00233               spaced = 0;
00234 
00235               /* Minimum TTL. */
00236               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00237               T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
00238               T(len = ns_format_ttl(t, buf, buflen));
00239               addlen(len, &buf, &buflen);
00240               T(addstr(" )", 2, &buf, &buflen));
00241               T(spaced = addtab(len, 16, spaced, &buf, &buflen));
00242               T(addstr("; minimum\n", 10, &buf, &buflen));
00243 
00244               break;
00245            }
00246 
00247        case ns_t_mx:
00248        case ns_t_afsdb:
00249        case ns_t_rt: {
00250               u_int t;
00251 
00252               if (rdlen < (size_t)NS_INT16SZ)
00253                      goto formerr;
00254 
00255               /* Priority. */
00256               t = ns_get16(rdata);
00257               rdata += NS_INT16SZ;
00258               len = SPRINTF((tmp, "%u ", t));
00259               T(addstr(tmp, len, &buf, &buflen));
00260 
00261               /* Target. */
00262               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00263 
00264               break;
00265            }
00266 
00267        case ns_t_px: {
00268               u_int t;
00269 
00270               if (rdlen < (size_t)NS_INT16SZ)
00271                      goto formerr;
00272 
00273               /* Priority. */
00274               t = ns_get16(rdata);
00275               rdata += NS_INT16SZ;
00276               len = SPRINTF((tmp, "%u ", t));
00277               T(addstr(tmp, len, &buf, &buflen));
00278 
00279               /* Name1. */
00280               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00281               T(addstr(" ", 1, &buf, &buflen));
00282 
00283               /* Name2. */
00284               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00285 
00286               break;
00287            }
00288 
00289        case ns_t_x25:
00290               T(len = charstr(rdata, edata, &buf, &buflen));
00291               if (len == 0)
00292                      goto formerr;
00293               rdata += len;
00294               break;
00295 
00296        case ns_t_txt:
00297               while (rdata < edata) {
00298                      T(len = charstr(rdata, edata, &buf, &buflen));
00299                      if (len == 0)
00300                             goto formerr;
00301                      rdata += len;
00302                      if (rdata < edata)
00303                             T(addstr(" ", 1, &buf, &buflen));
00304               }
00305               break;
00306 
00307        case ns_t_nsap: {
00308               char t[2+255*3];
00309 
00310               (void) inet_nsap_ntoa(rdlen, rdata, t);
00311               T(addstr(t, strlen(t), &buf, &buflen));
00312               break;
00313            }
00314 
00315        case ns_t_aaaa:
00316          if (rdlen != (size_t)NS_IN6ADDRSZ)
00317                      goto formerr;
00318               (void) inet_ntop(AF_INET6, rdata, buf, buflen);
00319               addlen(strlen(buf), &buf, &buflen);
00320               break;
00321 
00322        case ns_t_loc: {
00323               char t[255];
00324 
00325               /* XXX protocol format checking? */
00326               (void) loc_ntoa(rdata, t);
00327               T(addstr(t, strlen(t), &buf, &buflen));
00328               break;
00329            }
00330 
00331        case ns_t_naptr: {
00332               u_int order, preference;
00333               char t[50];
00334 
00335               if (rdlen < 2U*NS_INT16SZ)
00336                      goto formerr;
00337 
00338               /* Order, Precedence. */
00339               order = ns_get16(rdata);    rdata += NS_INT16SZ;
00340               preference = ns_get16(rdata);      rdata += NS_INT16SZ;
00341               len = SPRINTF((t, "%u %u ", order, preference));
00342               T(addstr(t, len, &buf, &buflen));
00343 
00344               /* Flags. */
00345               T(len = charstr(rdata, edata, &buf, &buflen));
00346               if (len == 0)
00347                      goto formerr;
00348               rdata += len;
00349               T(addstr(" ", 1, &buf, &buflen));
00350 
00351               /* Service. */
00352               T(len = charstr(rdata, edata, &buf, &buflen));
00353               if (len == 0)
00354                      goto formerr;
00355               rdata += len;
00356               T(addstr(" ", 1, &buf, &buflen));
00357 
00358               /* Regexp. */
00359               T(len = charstr(rdata, edata, &buf, &buflen));
00360               if (len < 0)
00361                      return (-1);
00362               if (len == 0)
00363                      goto formerr;
00364               rdata += len;
00365               T(addstr(" ", 1, &buf, &buflen));
00366 
00367               /* Server. */
00368               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00369               break;
00370            }
00371 
00372        case ns_t_srv: {
00373               u_int priority, weight, port;
00374               char t[50];
00375 
00376               if (rdlen < 3U*NS_INT16SZ)
00377                      goto formerr;
00378 
00379               /* Priority, Weight, Port. */
00380               priority = ns_get16(rdata);  rdata += NS_INT16SZ;
00381               weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
00382               port     = ns_get16(rdata);  rdata += NS_INT16SZ;
00383               len = SPRINTF((t, "%u %u %u ", priority, weight, port));
00384               T(addstr(t, len, &buf, &buflen));
00385 
00386               /* Server. */
00387               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00388               break;
00389            }
00390 
00391        case ns_t_minfo:
00392        case ns_t_rp:
00393               /* Name1. */
00394               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00395               T(addstr(" ", 1, &buf, &buflen));
00396 
00397               /* Name2. */
00398               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00399 
00400               break;
00401 
00402        case ns_t_wks: {
00403               int n, lcnt;
00404 
00405               if (rdlen < 1U + NS_INT32SZ)
00406                      goto formerr;
00407 
00408               /* Address. */
00409               (void) inet_ntop(AF_INET, rdata, buf, buflen);
00410               addlen(strlen(buf), &buf, &buflen);
00411               rdata += NS_INADDRSZ;
00412 
00413               /* Protocol. */
00414               len = SPRINTF((tmp, " %u ( ", *rdata));
00415               T(addstr(tmp, len, &buf, &buflen));
00416               rdata += NS_INT8SZ;
00417 
00418               /* Bit map. */
00419               n = 0;
00420               lcnt = 0;
00421               while (rdata < edata) {
00422                      u_int c = *rdata++;
00423                      do {
00424                             if (c & 0200) {
00425                                    if (lcnt == 0) {
00426                                           T(addstr("\n\t\t\t\t", 5,
00427                                                   &buf, &buflen));
00428                                           lcnt = 10;
00429                                           spaced = 0;
00430                                    }
00431                                    len = SPRINTF((tmp, "%d ", n));
00432                                    T(addstr(tmp, len, &buf, &buflen));
00433                                    lcnt--;
00434                             }
00435                             c <<= 1;
00436                      } while (++n & 07);
00437               }
00438               T(addstr(")", 1, &buf, &buflen));
00439 
00440               break;
00441            }
00442 
00443        case ns_t_key: {
00444               char base64_key[NS_MD5RSA_MAX_BASE64];
00445               u_int keyflags, protocol, algorithm, key_id;
00446               const char *leader;
00447               int n;
00448 
00449               if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
00450                      goto formerr;
00451 
00452               /* Key flags, Protocol, Algorithm. */
00453               key_id = dst_s_dns_key_id(rdata, edata-rdata);
00454               keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
00455               protocol = *rdata++;
00456               algorithm = *rdata++;
00457               len = SPRINTF((tmp, "0x%04x %u %u",
00458                             keyflags, protocol, algorithm));
00459               T(addstr(tmp, len, &buf, &buflen));
00460 
00461               /* Public key data. */
00462               len = b64_ntop(rdata, edata - rdata,
00463                             base64_key, sizeof base64_key);
00464               if (len < 0)
00465                      goto formerr;
00466               if (len > 15) {
00467                      T(addstr(" (", 2, &buf, &buflen));
00468                      leader = "\n\t\t";
00469                      spaced = 0;
00470               } else
00471                      leader = " ";
00472               for (n = 0; n < len; n += 48) {
00473                      T(addstr(leader, strlen(leader), &buf, &buflen));
00474                      T(addstr(base64_key + n, MIN(len - n, 48),
00475                              &buf, &buflen));
00476               }
00477               if (len > 15)
00478                      T(addstr(" )", 2, &buf, &buflen));
00479               n = SPRINTF((tmp, " ; key_tag= %u", key_id));
00480               T(addstr(tmp, n, &buf, &buflen));
00481 
00482               break;
00483            }
00484 
00485        case ns_t_sig: {
00486               char base64_key[NS_MD5RSA_MAX_BASE64];
00487               u_int type, algorithm, labels, footprint;
00488               const char *leader;
00489               u_long t;
00490               int n;
00491 
00492               if (rdlen < 22U)
00493                      goto formerr;
00494 
00495               /* Type covered, Algorithm, Label count, Original TTL. */
00496                type = ns_get16(rdata);  rdata += NS_INT16SZ;
00497               algorithm = *rdata++;
00498               labels = *rdata++;
00499               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00500               len = SPRINTF((tmp, "%s %d %d %lu ",
00501                             p_type(type), algorithm, labels, t));
00502               T(addstr(tmp, len, &buf, &buflen));
00503               if (labels > (u_int)dn_count_labels(name))
00504                      goto formerr;
00505 
00506               /* Signature expiry. */
00507               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00508               len = SPRINTF((tmp, "%s ", p_secstodate(t)));
00509               T(addstr(tmp, len, &buf, &buflen));
00510 
00511               /* Time signed. */
00512               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00513               len = SPRINTF((tmp, "%s ", p_secstodate(t)));
00514               T(addstr(tmp, len, &buf, &buflen));
00515 
00516               /* Signature Footprint. */
00517               footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
00518               len = SPRINTF((tmp, "%u ", footprint));
00519               T(addstr(tmp, len, &buf, &buflen));
00520 
00521               /* Signer's name. */
00522               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00523 
00524               /* Signature. */
00525               len = b64_ntop(rdata, edata - rdata,
00526                             base64_key, sizeof base64_key);
00527               if (len > 15) {
00528                      T(addstr(" (", 2, &buf, &buflen));
00529                      leader = "\n\t\t";
00530                      spaced = 0;
00531               } else
00532                      leader = " ";
00533               if (len < 0)
00534                      goto formerr;
00535               for (n = 0; n < len; n += 48) {
00536                      T(addstr(leader, strlen(leader), &buf, &buflen));
00537                      T(addstr(base64_key + n, MIN(len - n, 48),
00538                              &buf, &buflen));
00539               }
00540               if (len > 15)
00541                      T(addstr(" )", 2, &buf, &buflen));
00542               break;
00543            }
00544 
00545        case ns_t_nxt: {
00546               int n, c;
00547 
00548               /* Next domain name. */
00549               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00550 
00551               /* Type bit map. */
00552               n = edata - rdata;
00553               for (c = 0; c < n*8; c++)
00554                      if (NS_NXT_BIT_ISSET(c, rdata)) {
00555                             len = SPRINTF((tmp, " %s", p_type(c)));
00556                             T(addstr(tmp, len, &buf, &buflen));
00557                      }
00558               break;
00559            }
00560 
00561        case ns_t_cert: {
00562               u_int c_type, key_tag, alg;
00563               int n;
00564               unsigned int siz;
00565               char base64_cert[8192], tmp[40];
00566               const char *leader;
00567 
00568               c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
00569               key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
00570               alg = (u_int) *rdata++;
00571 
00572               len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
00573               T(addstr(tmp, len, &buf, &buflen));
00574               siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
00575               if (siz > sizeof(base64_cert) * 3/4) {
00576                      const char *str = "record too long to print";
00577                      T(addstr(str, strlen(str), &buf, &buflen));
00578               }
00579               else {
00580                      len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
00581 
00582                      if (len < 0)
00583                             goto formerr;
00584                      else if (len > 15) {
00585                             T(addstr(" (", 2, &buf, &buflen));
00586                             leader = "\n\t\t";
00587                             spaced = 0;
00588                      }
00589                      else
00590                             leader = " ";
00591 
00592                      for (n = 0; n < len; n += 48) {
00593                             T(addstr(leader, strlen(leader),
00594                                     &buf, &buflen));
00595                             T(addstr(base64_cert + n, MIN(len - n, 48),
00596                                     &buf, &buflen));
00597                      }
00598                      if (len > 15)
00599                             T(addstr(" )", 2, &buf, &buflen));
00600               }
00601               break;
00602            }
00603 
00604        case ns_t_tkey: {
00605               /* KJD - need to complete this */
00606               u_long t;
00607               int mode, err, keysize;
00608 
00609               /* Algorithm name. */
00610               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00611               T(addstr(" ", 1, &buf, &buflen));
00612 
00613               /* Inception. */
00614               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00615               len = SPRINTF((tmp, "%s ", p_secstodate(t)));
00616               T(addstr(tmp, len, &buf, &buflen));
00617 
00618               /* Experation. */
00619               t = ns_get32(rdata);  rdata += NS_INT32SZ;
00620               len = SPRINTF((tmp, "%s ", p_secstodate(t)));
00621               T(addstr(tmp, len, &buf, &buflen));
00622 
00623               /* Mode , Error, Key Size. */
00624               /* Priority, Weight, Port. */
00625               mode = ns_get16(rdata);  rdata += NS_INT16SZ;
00626               err  = ns_get16(rdata);  rdata += NS_INT16SZ;
00627               keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
00628               len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
00629               T(addstr(tmp, len, &buf, &buflen));
00630 
00631               /* XXX need to dump key, print otherdata length & other data */
00632               break;
00633            }
00634 
00635        case ns_t_tsig: {
00636               /* BEW - need to complete this */
00637               int n;
00638 
00639               T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
00640               T(addstr(" ", 1, &buf, &buflen));
00641               rdata += 8; /*%< time */
00642               n = ns_get16(rdata); rdata += INT16SZ;
00643               rdata += n; /*%< sig */
00644               n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
00645               sprintf(buf, "%d", ns_get16(rdata));
00646               rdata += INT16SZ;
00647               addlen(strlen(buf), &buf, &buflen);
00648               break;
00649            }
00650 
00651        case ns_t_a6: {
00652               struct in6_addr a;
00653               int pbyte, pbit;
00654 
00655               /* prefix length */
00656               if (rdlen == 0U) goto formerr;
00657               len = SPRINTF((tmp, "%d ", *rdata));
00658               T(addstr(tmp, len, &buf, &buflen));
00659               pbit = *rdata;
00660               if (pbit > 128) goto formerr;
00661               pbyte = (pbit & ~7) / 8;
00662               rdata++;
00663 
00664               /* address suffix: provided only when prefix len != 128 */
00665               if (pbit < 128) {
00666                      if (rdata + pbyte >= edata) goto formerr;
00667                      memset(&a, 0, sizeof(a));
00668                      memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
00669                      (void) inet_ntop(AF_INET6, &a, buf, buflen);
00670                      addlen(strlen(buf), &buf, &buflen);
00671                      rdata += sizeof(a) - pbyte;
00672               }
00673 
00674               /* prefix name: provided only when prefix len > 0 */
00675               if (pbit == 0)
00676                      break;
00677               if (rdata >= edata) goto formerr;
00678               T(addstr(" ", 1, &buf, &buflen));
00679               T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
00680 
00681               break;
00682            }
00683 
00684        case ns_t_opt: {
00685               len = SPRINTF((tmp, "%u bytes", class));
00686               T(addstr(tmp, len, &buf, &buflen));
00687               break;
00688            }
00689 
00690        default:
00691               snprintf (errbuf, sizeof (errbuf), "unknown RR type %d", type);
00692               comment = errbuf;
00693               goto hexify;
00694        }
00695        return (buf - obuf);
00696  formerr:
00697        comment = "RR format error";
00698  hexify: {
00699        int n, m;
00700        char *p;
00701 
00702        len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
00703                      rdlen != 0U ? " (" : "", comment));
00704        T(addstr(tmp, len, &buf, &buflen));
00705        while (rdata < edata) {
00706               p = tmp;
00707               p += SPRINTF((p, "\n\t"));
00708               spaced = 0;
00709               n = MIN(16, edata - rdata);
00710               for (m = 0; m < n; m++)
00711                      p += SPRINTF((p, "%02x ", rdata[m]));
00712               T(addstr(tmp, p - tmp, &buf, &buflen));
00713               if (n < 16) {
00714                      T(addstr(")", 1, &buf, &buflen));
00715                      T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
00716               }
00717               p = tmp;
00718               p += SPRINTF((p, "; "));
00719               for (m = 0; m < n; m++)
00720                      *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
00721                             ? rdata[m]
00722                             : '.';
00723               T(addstr(tmp, p - tmp, &buf, &buflen));
00724               rdata += n;
00725        }
00726        return (buf - obuf);
00727     }
00728 }
00729 libresolv_hidden_def (ns_sprintrrf)
00730 
00731 /* Private. */
00732 
00733 /*%
00734  * size_t
00735  * prune_origin(name, origin)
00736  *     Find out if the name is at or under the current origin.
00737  * return:
00738  *     Number of characters in name before start of origin,
00739  *     or length of name if origin does not match.
00740  * notes:
00741  *     This function should share code with samedomain().
00742  */
00743 static size_t
00744 prune_origin(const char *name, const char *origin) {
00745        const char *oname = name;
00746 
00747        while (*name != '\0') {
00748               if (origin != NULL && ns_samename(name, origin) == 1)
00749                      return (name - oname - (name > oname));
00750               while (*name != '\0') {
00751                      if (*name == '\\') {
00752                             name++;
00753                             /* XXX need to handle \nnn form. */
00754                             if (*name == '\0')
00755                                    break;
00756                      } else if (*name == '.') {
00757                             name++;
00758                             break;
00759                      }
00760                      name++;
00761               }
00762        }
00763        return (name - oname);
00764 }
00765 
00766 /*%
00767  * int
00768  * charstr(rdata, edata, buf, buflen)
00769  *     Format a <character-string> into the presentation buffer.
00770  * return:
00771  *     Number of rdata octets consumed
00772  *     0 for protocol format error
00773  *     -1 for output buffer error
00774  * side effects:
00775  *     buffer is advanced on success.
00776  */
00777 static int
00778 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
00779        const u_char *odata = rdata;
00780        size_t save_buflen = *buflen;
00781        char *save_buf = *buf;
00782 
00783        if (addstr("\"", 1, buf, buflen) < 0)
00784               goto enospc;
00785        if (rdata < edata) {
00786               int n = *rdata;
00787 
00788               if (rdata + 1 + n <= edata) {
00789                      rdata++;
00790                      while (n-- > 0) {
00791                             if (strchr("\n\"\\", *rdata) != NULL)
00792                                    if (addstr("\\", 1, buf, buflen) < 0)
00793                                           goto enospc;
00794                             if (addstr((const char *)rdata, 1,
00795                                       buf, buflen) < 0)
00796                                    goto enospc;
00797                             rdata++;
00798                      }
00799               }
00800        }
00801        if (addstr("\"", 1, buf, buflen) < 0)
00802               goto enospc;
00803        return (rdata - odata);
00804  enospc:
00805        __set_errno (ENOSPC);
00806        *buf = save_buf;
00807        *buflen = save_buflen;
00808        return (-1);
00809 }
00810 
00811 static int
00812 addname(const u_char *msg, size_t msglen,
00813        const u_char **pp, const char *origin,
00814        char **buf, size_t *buflen)
00815 {
00816        size_t newlen, save_buflen = *buflen;
00817        char *save_buf = *buf;
00818        int n;
00819 
00820        n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
00821        if (n < 0)
00822               goto enospc;  /*%< Guess. */
00823        newlen = prune_origin(*buf, origin);
00824        if (**buf == '\0') {
00825               goto root;
00826        } else if (newlen == 0U) {
00827               /* Use "@" instead of name. */
00828               if (newlen + 2 > *buflen)
00829                      goto enospc;        /* No room for "@\0". */
00830               (*buf)[newlen++] = '@';
00831               (*buf)[newlen] = '\0';
00832        } else {
00833               if (((origin == NULL || origin[0] == '\0') ||
00834                   (origin[0] != '.' && origin[1] != '\0' &&
00835                   (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
00836                      /* No trailing dot. */
00837  root:
00838                      if (newlen + 2 > *buflen)
00839                             goto enospc;  /* No room for ".\0". */
00840                      (*buf)[newlen++] = '.';
00841                      (*buf)[newlen] = '\0';
00842               }
00843        }
00844        *pp += n;
00845        addlen(newlen, buf, buflen);
00846        **buf = '\0';
00847        return (newlen);
00848  enospc:
00849        __set_errno (ENOSPC);
00850        *buf = save_buf;
00851        *buflen = save_buflen;
00852        return (-1);
00853 }
00854 
00855 static void
00856 addlen(size_t len, char **buf, size_t *buflen) {
00857        assert(len <= *buflen);
00858        *buf += len;
00859        *buflen -= len;
00860 }
00861 
00862 static int
00863 addstr(const char *src, size_t len, char **buf, size_t *buflen) {
00864        if (len >= *buflen) {
00865               __set_errno (ENOSPC);
00866               return (-1);
00867        }
00868        memcpy(*buf, src, len);
00869        addlen(len, buf, buflen);
00870        **buf = '\0';
00871        return (0);
00872 }
00873 
00874 static int
00875 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
00876        size_t save_buflen = *buflen;
00877        char *save_buf = *buf;
00878        int t;
00879 
00880        if (spaced || len >= target - 1) {
00881               T(addstr("  ", 2, buf, buflen));
00882               spaced = 1;
00883        } else {
00884               for (t = (target - len - 1) / 8; t >= 0; t--)
00885                      if (addstr("\t", 1, buf, buflen) < 0) {
00886                             *buflen = save_buflen;
00887                             *buf = save_buf;
00888                             return (-1);
00889                      }
00890               spaced = 0;
00891        }
00892        return (spaced);
00893 }
00894 
00895 /* DST algorithm codes */
00896 #define KEY_RSA                    1
00897 #define KEY_HMAC_MD5        157
00898 
00899 /*%
00900  * calculates a checksum used in dst for an id.
00901  * takes an array of bytes and a length.
00902  * returns a 16  bit checksum.
00903  */
00904 static u_int16_t
00905 dst_s_id_calc(const u_char *key, const int keysize)
00906 {
00907        u_int32_t ac;
00908        const u_char *kp = key;
00909        int size = keysize;
00910 
00911        if (!key || (keysize <= 0))
00912               return (0xffffU);
00913 
00914        for (ac = 0; size > 1; size -= 2, kp += 2)
00915               ac += ((*kp) << 8) + *(kp + 1);
00916 
00917        if (size > 0)
00918               ac += ((*kp) << 8);
00919        ac += (ac >> 16) & 0xffff;
00920 
00921        return (ac & 0xffff);
00922 }
00923 
00924 /*%
00925  * dst_s_get_int16
00926  *     This routine extracts a 16 bit integer from a two byte character
00927  *     string.  The character string is assumed to be in network byte
00928  *     order and may be unaligned.  The number returned is in host order.
00929  * Parameter
00930  *     buf     A two byte character string.
00931  * Return
00932  *     The converted integer value.
00933  */
00934 
00935 static u_int16_t
00936 dst_s_get_int16(const u_char *buf)
00937 {
00938        register u_int16_t a = 0;
00939        a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
00940        return (a);
00941 }
00942 
00943 /*%
00944  * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record
00945  *   rdata
00946  * Input:
00947  *     dns_key_rdata: the raw data in wire format
00948  *      rdata_len: the size of the input data
00949  * Output:
00950  *      the key footprint/id calculated from the key data
00951  */
00952 static u_int16_t
00953 dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
00954 {
00955        if (!dns_key_rdata)
00956               return 0;
00957 
00958        /* compute id */
00959        if (dns_key_rdata[3] == KEY_RSA)   /*%< Algorithm RSA */
00960               return dst_s_get_int16((const u_char *)
00961                                    &dns_key_rdata[rdata_len - 3]);
00962        else if (dns_key_rdata[3] == KEY_HMAC_MD5)
00963               /* compatibility */
00964               return 0;
00965        else
00966               /* compute a checksum on the key part of the key rr */
00967               return dst_s_id_calc(dns_key_rdata, rdata_len);
00968 }
00969 
00970