diff --git a/bin/tests/db_test.c b/bin/tests/db_test.c index d16b016679..7c9eebfa21 100644 --- a/bin/tests/db_test.c +++ b/bin/tests/db_test.c @@ -144,7 +144,7 @@ select_db(char *origintext) { } static void -dump(dbinfo *dbi) { +list(dbinfo *dbi) { dns_fixedname_t fname; dns_name_t *name; dns_dbnode_t *node; @@ -586,7 +586,13 @@ main(int argc, char *argv[]) { continue; } else if (strcmp(s, "!LS") == 0) { DBI_CHECK(dbi); - dump(dbi); + list(dbi); + continue; + } else if (strstr(s, "!DU ") == s) { + DBI_CHECK(dbi); + result = dns_db_dump(dbi->db, dbi->version, s+4); + if (result != DNS_R_SUCCESS) + printf("\n%s\n", dns_result_totext(result)); continue; } else if (strstr(s, "!P") == s) { DBI_CHECK(dbi); diff --git a/bin/tests/master/t_master.c b/bin/tests/master/t_master.c index 796d2da1bd..510e941a6f 100644 --- a/bin/tests/master/t_master.c +++ b/bin/tests/master/t_master.c @@ -100,6 +100,7 @@ test_master(char *testfile, char *origin, dns_result_t exp_result) { &dns_origin, &dns_origin, 1, + ISC_FALSE, &soacount, &nscount, &callbacks, diff --git a/bin/tests/master_test.c b/bin/tests/master_test.c index 7720037a3a..6a36cd4254 100644 --- a/bin/tests/master_test.c +++ b/bin/tests/master_test.c @@ -90,8 +90,8 @@ main(int argc, char *argv[]) { dns_rdatacallbacks_init(&callbacks); callbacks.commit = print_dataset; - result = dns_master_load(argv[1], &origin, &origin, 1, - &soacount, &nscount, + result = dns_master_load(argv[1], &origin, &origin, 1, ISC_FALSE, + &soacount, &nscount, &callbacks, mctx); fprintf(stdout, "dns_master_load: %s\n", dns_result_totext(result)); diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index 716abbce3d..be97bb8d74 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -36,12 +36,12 @@ LIBS = @LIBS@ OBJS = callbacks.o compress.o db.o dbiterator.o dbtable.o \ master.o message.o name.o rbt.o rbtdb.o rbtdb64.o \ rdata.o rdatalist.o rdataset.o rdatasetiter.o rdataslab.o \ - result.o version.o + result.o version.o masterdump.o time.o ttl.o OSRC = callbacks.c compress.c db.c dbiterator.c dbtable.c \ master.c name.c rbt.c rbtdb.c rbtdb64.c \ rdata.c rdatalist.c rdataset.c rdatasetiter.c rdataslab.c \ - result.c version.c + result.c version.c masterdump.c time.c ttl.c SUBDIRS = include TARGETS = include/dns/enumtype.h include/dns/enumclass.h \ diff --git a/lib/dns/db.c b/lib/dns/db.c index 0dfb7b6db0..10baf97cf9 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -180,6 +180,17 @@ dns_db_load(dns_db_t *db, char *filename) { return (db->methods->load(db, filename)); } +dns_result_t +dns_db_dump(dns_db_t *db, dns_dbversion_t *version, char *filename) { + /* + * Dump 'db' into master file 'filename'. + */ + + REQUIRE(DNS_DB_VALID(db)); + + return (db->methods->dump(db, version, filename)); +} + /*** *** Version Methods ***/ diff --git a/lib/dns/gen.c b/lib/dns/gen.c index 810303cda4..7004cb9619 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: gen.c,v 1.19 1999/05/07 03:24:04 marka Exp $ */ + /* $Id: gen.c,v 1.20 1999/06/08 10:35:04 gson Exp $ */ #include @@ -35,8 +35,8 @@ #define FROMTEXTTYPE "type" #define FROMTEXTDEF "use_default = ISC_TRUE" -#define TOTEXTDECL "dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target" -#define TOTEXTARGS "rdata, origin, target" +#define TOTEXTDECL "dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target" +#define TOTEXTARGS "rdata, tctx, target" #define TOTEXTCLASS "rdata->class" #define TOTEXTTYPE "rdata->type" #define TOTEXTDEF "use_default = ISC_TRUE" diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index f4b92ad6d7..1dc29ec8e9 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -74,6 +74,8 @@ typedef struct dns_dbmethods { void (*attach)(dns_db_t *source, dns_db_t **targetp); void (*detach)(dns_db_t **dbp); dns_result_t (*load)(dns_db_t *db, char *filename); + dns_result_t (*dump)(dns_db_t *db, dns_dbversion_t *version, + char *filename); void (*currentversion)(dns_db_t *db, dns_dbversion_t **versionp); dns_result_t (*newversion)(dns_db_t *db, @@ -320,6 +322,26 @@ dns_db_load(dns_db_t *db, char *filename); * implementation used, syntax errors in the master file, etc. */ +dns_result_t +dns_db_dump(dns_db_t *db, dns_dbversion_t *version, char *filename); +/* + * Dump version 'version' of 'db' to master file 'filename'. + * + * Requires: + * + * 'db' is a valid database. + * + * 'version' is a valid version. + * + * Returns: + * + * DNS_R_SUCCESS + * DNS_R_NOMEMORY + * + * Other results are possible, depending upon the database + * implementation used, OS file errors, etc. + */ + /*** *** Version Methods ***/ diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h index bc9daa2cbe..a3803ba3c7 100644 --- a/lib/dns/include/dns/master.h +++ b/lib/dns/include/dns/master.h @@ -41,7 +41,8 @@ ISC_LANG_BEGINDECLS dns_result_t dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, - dns_rdataclass_t class, + dns_rdataclass_t zclass, + isc_boolean_t age_ttl, int *soacount, int *nscount, dns_rdatacallbacks_t *callbacks, @@ -54,6 +55,9 @@ dns_result_t dns_master_load(char *master_file, * completes. dns_load_master will abort if callbacks->commit returns * any value other than DNS_R_SUCCESS. * + * If 'age_ttl' is ISC_TRUE and the master file contains one or more + * $DATE directives, the TTLs of the data will be aged accordingly. + * * 'callbacks->commit' is assumed to call 'callbacks->error' or * 'callbacks->warn' to generate any error messages required. * diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h new file mode 100644 index 0000000000..a08dde6c04 --- /dev/null +++ b/lib/dns/include/dns/masterdump.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DNS_MASTERDUMP_H +#define DNS_MASTERDUMP_H 1 + +/*** + *** Imports + ***/ + +#include + +#include +#include + +#include +#include +#include +#include + +/*** + *** Types + ***/ + +/* + * Style options for masterfile dumps. This struct is currently + * opaque, so applications cannot define their own style but have + * to choose a predefined style. A more flexible interface may + * be exported in the future. + */ + +typedef struct dns_master_style dns_master_style_t; + +ISC_LANG_BEGINDECLS + +/*** + *** Constants + ***/ + +/* + * The default masterfile style. + */ +extern const dns_master_style_t dns_master_style_default; + + +/*** + *** Functions + ***/ + +dns_result_t +dns_master_dump(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, char *filename); +/* + * Dump the database 'db' to the file 'filename' in RFC1035 master + * file format, in the style defined by 'style' + * (e.g., &dns_default_master_style_default) + * + * Temporary dynamic memory may be allocated from 'mctx'. + * + * Returns: + * DNS_R_SUCCESS + * DNS_R_NOMEMORY + * Any database or rrset iterator error. + * Any dns_rdata_totext() error code. + */ + +ISC_LANG_ENDDECLS + +#endif /* DNS_MASTERDUMP_H */ diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h index 775c6d9e9e..ae7a15900e 100644 --- a/lib/dns/include/dns/rdata.h +++ b/lib/dns/include/dns/rdata.h @@ -126,6 +126,30 @@ struct dns_rdata { ISC_LINK(dns_rdata_t) link; }; +/* + * Context structure for dns_rdata_totext(). Defines + * the way the rdata part of a master file lines is + * formatted. + */ +typedef struct dns_rdata_textctx { + dns_name_t *origin; /* Current origin, or NULL. */ + unsigned int flags; /* DNS_STYLEFLAG_* */ + unsigned int width; /* Width of rdata column. */ + char *linebreak; /* Line break string. */ +} dns_rdata_textctx_t; + +/* + * Flags affecting rdata formatting. Flags 0xFFFF0000 + * are used by masterfile-level formatting and defined elsewhere. + */ + +/* Split the rdata into multiple lines to try to keep it + within the "width". */ +#define DNS_STYLEFLAG_MULTILINE 0x00000001U + +/* Output explanatory comments. */ +#define DNS_STYLEFLAG_COMMENT 0x00000002U + /*** *** Initialization ***/ @@ -299,7 +323,7 @@ dns_result_t dns_rdata_fromtext(dns_rdata_t *rdata, * Resource Limit: Not enough space */ -dns_result_t dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, +dns_result_t dns_rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target); /* * Convert 'rdata' into text format, storing the result in 'target'. diff --git a/lib/dns/include/dns/time.h b/lib/dns/include/dns/time.h new file mode 100644 index 0000000000..1126c55715 --- /dev/null +++ b/lib/dns/include/dns/time.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DNS_TIME_H +#define DNS_TIME_H 1 + +/*** + *** Imports + ***/ + +#include +#include +#include + +ISC_LANG_BEGINDECLS + +/*** + *** Functions + ***/ + +dns_result_t dns_time64_fromtext(char *source, isc_int64_t *target); +/* + * Convert a date and time in YYYYMMDDHHMMSS text format at 'source' + * into to a 64-bit count of seconds since Jan 1 1970 0:00 GMT. + * Store the count at 'target'. + */ + +dns_result_t dns_time32_fromtext(char *source, isc_uint32_t *target); +/* + * Like dns_time64_fromtext, but returns the second count modulo 2^32 + * as per RFC2535. + */ + + +dns_result_t dns_time64_totext(isc_int64_t value, isc_buffer_t *target); +/* + * Convert a 64-bit count of seconds since Jan 1 1970 0:00 GMT into + * a YYYYMMDDHHMMSS text representation and append it to 'target'. + */ + +dns_result_t dns_time32_totext(isc_uint32_t value, isc_buffer_t *target); +/* + * Like dns_time64_totext, but for a 32-bit cyclic time value. + * Of those dates whose counts of seconds since Jan 1 1970 0:00 GMT + * are congruent with 'value' modulo 2^32, the one closest to the + * current date is chosen. + */ + +ISC_LANG_ENDDECLS + +#endif /* DNS_TIME_H */ diff --git a/lib/dns/include/dns/ttl.h b/lib/dns/include/dns/ttl.h new file mode 100644 index 0000000000..5e1f9beae1 --- /dev/null +++ b/lib/dns/include/dns/ttl.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifndef DNS_TTL_H +#define DNS_TTL_H 1 + +/*** + *** Imports + ***/ + +#include +#include + +ISC_LANG_BEGINDECLS + +/*** + *** Functions + ***/ + +dns_result_t +dns_ttl_totext(isc_uint32_t src, isc_boolean_t verbose, + isc_buffer_t *target); +/* + * Output a TTL or other time interval in a human-readable form. + * The time interval is given as a count of seconds in 'src'. + * The text representation is appended to 'target'. + * + * If 'verbose' is ISC_FALSE, use the terse BIND 8 style, like "1w2d3h4m5s". + * + * If 'verbose' is ISC_TRUE, use a verbose style like the SOA comments + * in "dig", like "1 week 2 days 3 hours 4 minutes 5 seconds". + * + * Returns: + * DNS_R_SUCCESS + * DNS_R_NOSPACE + */ + +ISC_LANG_ENDDECLS + +#endif /* DNS_MASTER_H */ diff --git a/lib/dns/master.c b/lib/dns/master.c index c8c6b49e5a..cd32e6d69d 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: master.c,v 1.17 1999/04/25 22:18:11 marka Exp $ */ + /* $Id: master.c,v 1.18 1999/06/08 10:35:04 gson Exp $ */ #include @@ -23,12 +23,14 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -38,6 +40,7 @@ #include #include #include +#include /* * Grow the number of dns_rdatalist_t (RDLSZ) and dns_rdata_t (RDSZ) structures @@ -132,13 +135,15 @@ gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, dns_result_t dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, - dns_rdataclass_t zclass, int *soacount, int *nscount, - dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx) + dns_rdataclass_t zclass, isc_boolean_t age_ttl, + int *soacount, int *nscount, dns_rdatacallbacks_t *callbacks, + isc_mem_t *mctx) { dns_rdataclass_t rdclass; dns_rdatatype_t type; isc_uint32_t ttl = 0; isc_uint32_t default_ttl = 0; + isc_uint32_t ttl_offset = 0; dns_name_t current_name; dns_name_t glue_name; dns_name_t new_name; @@ -316,6 +321,14 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, continue; } else if (strcasecmp(token.value.as_pointer, "$INCLUDE") == 0) { + if (ttl_offset != 0) { + (callbacks->error)(callbacks, + "dns_load_master: %s:%d: $INCLUDE " + "may not be used with $DATE", + master_file, + isc_lex_getsourceline(lex)); + goto cleanup; + } GETTOKEN(lex, 0, &token, ISC_FALSE); if (include_file != NULL) isc_mem_free(mctx, include_file); @@ -332,6 +345,7 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, top, &origin_name, zclass, + age_ttl, soacount, nscount, callbacks, @@ -343,6 +357,34 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, } read_till_eol = ISC_TRUE; finish_include = ISC_TRUE; + } else if (strcasecmp(token.value.as_pointer, + "$DATE") == 0) { + isc_uint64_t dump_time64; + isc_stdtime_t dump_time, current_time; + GETTOKEN(lex, 0, &token, ISC_FALSE); + iresult = isc_stdtime_get(¤t_time); + result = dns_time64_fromtext(token.value. + as_pointer, &dump_time64); + dump_time = dump_time64; + if (dump_time != dump_time64) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "dns_master_load: %s:%d: " + "$DATE outside epoch", + master_file, + isc_lex_getsourceline(lex)); + goto cleanup; + } + if (dump_time > current_time) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "dns_master_load: %s:%d: " + "$DATE in future, using current date", + master_file, + isc_lex_getsourceline(lex)); + dump_time = current_time; + } + ttl_offset = current_time - dump_time; + read_till_eol = ISC_TRUE; + continue; } /* @@ -386,6 +428,7 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, top, &new_name, zclass, + age_ttl, soacount, nscount, callbacks, @@ -597,6 +640,20 @@ dns_master_load(char *master_file, dns_name_t *top, dns_name_t *origin, if (type == dns_rdatatype_ns && !in_glue) current_has_delegation = ISC_TRUE; + if (age_ttl) { + /* + * Adjust the TTL for $DATE. If the RR has already + * expired, ignore it without even parsing the rdata + * part (good for performance, bad for catching + * syntax errors). + */ + if (ttl < ttl_offset) { + read_till_eol = ISC_TRUE; + continue; + } + ttl -= ttl_offset; + } + /* * Find type in rdatalist. * If it does not exit create new one and prepend to list diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c new file mode 100644 index 0000000000..8637cf76a2 --- /dev/null +++ b/lib/dns/masterdump.c @@ -0,0 +1,777 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RETERR(x) do { \ + dns_result_t __r = (x); \ + if (__r != DNS_R_SUCCESS) \ + return (__r); \ + } while (0) + +struct dns_master_style { + unsigned int flags; /* DNS_STYLEFLAG_* */ + unsigned int ttl_column; + unsigned int class_column; + unsigned int type_column; + unsigned int rdata_column; + unsigned int line_length; + unsigned int tab_width; +}; + +/* + * Flags affecting master file formatting. Flags 0x0000FFFF + * define the formatting of the rdata part and are defined in + * rdata.h. + */ + +/* Omit the owner name when possible. */ +#define DNS_STYLEFLAG_OMIT_OWNER 0x00010000U + +/* + * Omit the TTL when possible. If DNS_STYLEFLAG_TTL is + * also set, this means no TTLs are ever printed + * because $TTL directives are generated before every + * change in the TTL. In this case, no columns need to + * be reserved for the TTL. Master files generated with + * these options will be rejected by BIND 4.x because it + * does not recognize the $TTL directive. + * + * If DNS_STYLEFLAG_TTL is not also set, the TTL will be + * omitted when it is equal to the previous TTL. + * This is correct according to RFC1035, but the + * TTLs may be silently misinterpreted by older + * versions of BIND which use the SOA MINTTL as a + * default TTL value. + */ +#define DNS_STYLEFLAG_OMIT_TTL 0x00020000U + +/* Omit the class when possible. */ +#define DNS_STYLEFLAG_OMIT_CLASS 0x00040000U + +/* Output $TTL directives. */ +#define DNS_STYLEFLAG_TTL 0x00080000U + +/* + * Output $ORIGIN directives and print owner names relative to + * the origin when possible. + */ +#define DNS_STYLEFLAG_REL_OWNER 0x00100000U + +/* Print domain names in RR data in relative form when possible. + For this to take effect, DNS_STYLEFLAG_REL_OWNER must also be set. */ +#define DNS_STYLEFLAG_REL_DATA 0x00200000U + + +/* + * The maximum length of the newline+indentation that is output + * when inserting a line break in an RR. This effectively puts an + * upper limits on the value of "rdata_column", because if it is + * very large, the tabs and spaces needed to reach it will not fit. + */ +#define DNS_TOTEXT_LINEBREAK_MAXLEN 100 + +/* + * Context structure for a masterfile dump in progress. + */ +typedef struct dns_totext_ctx { + dns_master_style_t style; + dns_rdata_textctx_t rdata_ctx; + isc_boolean_t class_printed; + char linebreak[DNS_TOTEXT_LINEBREAK_MAXLEN]; + dns_fixedname_t origin_fixname; + isc_uint32_t current_ttl; + isc_boolean_t current_ttl_valid; +} dns_totext_ctx_t; + +/* + * The default master file style. + * + * Because the TTL is always omitted, and the class is almost always + * omitted, neither is allocated any columns. + */ +dns_master_style_t +dns_master_style_default = { + DNS_STYLEFLAG_OMIT_OWNER | + DNS_STYLEFLAG_OMIT_CLASS | + DNS_STYLEFLAG_REL_OWNER | + DNS_STYLEFLAG_REL_DATA | + DNS_STYLEFLAG_OMIT_TTL | + DNS_STYLEFLAG_TTL | + DNS_STYLEFLAG_COMMENT | + DNS_STYLEFLAG_MULTILINE, + 24, 24, 24, 32, 80, 8 +}; + +/* + * A style suitable for dns_rdataset_totext(). + */ +dns_master_style_t +dns_masterfile_style_debug = { + DNS_STYLEFLAG_REL_OWNER, + 24, 32, 40, 48, 80, 8 +}; + + +#define N_SPACES 10 +char spaces[N_SPACES] = " "; + +#define N_TABS 10 +char tabs[N_TABS] = "\t\t\t\t\t\t\t\t\t\t"; + +/* + * Output tabs and spaces to go from column '*current' to + * column 'to', and update '*current' to reflect the new + * current column. + */ +static dns_result_t +indent(int *current, int to, int tabwidth, isc_buffer_t *target) { + isc_region_t r; + unsigned char *p; + int from, ntabs, nspaces, t; + + from = *current; + + if (to < from + 1) + to = from + 1; + + ntabs = to / tabwidth - from / tabwidth; + if (ntabs < 0) + ntabs = 0; + + if (ntabs > 0) { + isc_buffer_available(target, &r); + if (r.length < (unsigned) ntabs) + return (DNS_R_NOSPACE); + p = r.base; + + t = ntabs; + while (t) { + int n = t; + if (n > N_TABS) + n = N_TABS; + memcpy(p, tabs, n); + p += n; + t -= n; + } + isc_buffer_add(target, ntabs); + from = (to / tabwidth) * tabwidth; + } + + nspaces = to - from; + INSIST(nspaces >= 0); + + isc_buffer_available(target, &r); + if (r.length < (unsigned) nspaces) + return (DNS_R_NOSPACE); + p = r.base; + + t = nspaces; + while (t) { + int n = t; + if (n > N_SPACES) + n = N_SPACES; + memcpy(p, spaces, n); + p += n; + t -= n; + } + isc_buffer_add(target, nspaces); + + *current = to; + return (DNS_R_SUCCESS); +} + +static dns_result_t +totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) +{ + dns_result_t result; + + ctx->style = *style; + REQUIRE(style->tab_width != 0); + dns_fixedname_init(&ctx->origin_fixname); + + /* Set up the line break string. */ + if ((ctx->style.flags & DNS_STYLEFLAG_MULTILINE) != 0) { + isc_buffer_t buf; + isc_region_t r; + int col = 0; + + isc_buffer_init(&buf, ctx->linebreak, sizeof(ctx->linebreak), + ISC_BUFFERTYPE_TEXT); + + isc_buffer_available(&buf, &r); + if (r.length < 1) + return (DNS_R_TEXTTOLONG); + r.base[0] = '\n'; + isc_buffer_add(&buf, 1); + + result = indent(&col, ctx->style.rdata_column, + ctx->style.tab_width, &buf); + /* + * Do not return DNS_R_NOSPACE if the line break string + * buffer is too small, because that would just make + * dump_rdataset() retry indenfinitely with ever + * bigger target buffers. That's a different buffer, + * so it won't help. Use DNS_R_TEXTTOLONG as a substitute. + */ + if (result == DNS_R_NOSPACE) + return (DNS_R_TEXTTOLONG); + if (result != DNS_R_SUCCESS) + return (result); + + isc_buffer_available(&buf, &r); + if (r.length < 1) + return (DNS_R_TEXTTOLONG); + r.base[0] = '\0'; + isc_buffer_add(&buf, 1); + } else { + /* + * Single-line output. Use a single space where + * a line break would otherwise be used. + */ + INSIST(sizeof(ctx->linebreak) >= 2); + ctx->linebreak[0] = ' '; + ctx->linebreak[1] = '\0'; + } + + ctx->class_printed = ISC_FALSE; + + ctx->rdata_ctx.origin = NULL; + ctx->rdata_ctx.width = ctx->style.line_length - ctx->style.rdata_column; + ctx->rdata_ctx.linebreak = ctx->linebreak; + ctx->rdata_ctx.flags = ctx->style.flags; + + return (DNS_R_SUCCESS); +} + +#define INDENT_TO(col) \ + do { \ + if ((result = indent(&column, ctx->style.col, \ + ctx->style.tab_width, target)) \ + != DNS_R_SUCCESS) \ + return (result); \ + } while (0) + + +/* + * Convert 'rdataset' to master file text format according to 'ctx', + * storing the result in 'target'. If 'owner_name' is NULL, it + * is omitted; otherwise 'owner_name' must be valid and have at least + * one label. + */ + +static dns_result_t +rdataset_totext(dns_rdataset_t *rdataset, + dns_name_t *owner_name, + dns_totext_ctx_t *ctx, + isc_boolean_t omit_final_dot, + isc_buffer_t *target) +{ + dns_result_t result; + unsigned int column; + isc_boolean_t first = ISC_TRUE; + isc_uint32_t current_ttl; + isc_boolean_t current_ttl_valid; + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + + result = dns_rdataset_first(rdataset); + REQUIRE(result == DNS_R_SUCCESS); + + current_ttl = ctx->current_ttl; + current_ttl_valid = ctx->current_ttl_valid; + + do { + column = 0; + + /* Owner name. */ + if (owner_name != NULL && + ! ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0 && ! first)) + { + unsigned int name_start = target->used; + RETERR(dns_name_totext(owner_name, + omit_final_dot, + target)); + column += target->used - name_start; + } + + /* TTL. */ + if (! ((ctx->style.flags & DNS_STYLEFLAG_OMIT_TTL) != 0 && + current_ttl_valid && + rdataset->ttl == current_ttl)) + { + char ttlbuf[64]; + isc_region_t r; + unsigned int length; + + INDENT_TO(ttl_column); + length = sprintf(ttlbuf, "%u", rdataset->ttl); + INSIST(length <= sizeof ttlbuf); + isc_buffer_available(target, &r); + if (r.length < length) + return (DNS_R_NOSPACE); + memcpy(r.base, ttlbuf, length); + isc_buffer_add(target, length); + column += length; + + /* + * If the $TTL directive is not in use, the TTL we + * just printed becomes the default for subsequent RRs. + */ + if ((ctx->style.flags & DNS_STYLEFLAG_TTL) == 0) { + current_ttl = rdataset->ttl; + current_ttl_valid = ISC_TRUE; + } + } + + /* Class. */ + if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_CLASS) == 0 || + ctx->class_printed == ISC_FALSE) + { + unsigned int class_start; + INDENT_TO(class_column); + class_start = target->used; + result = dns_rdataclass_totext(rdataset->rdclass, target); + if (result != DNS_R_SUCCESS) + return (result); + column += (target->used - class_start); + } + + /* Type. */ + { + unsigned int type_start; + INDENT_TO(type_column); + type_start = target->used; + result = dns_rdatatype_totext(rdataset->type, target); + if (result != DNS_R_SUCCESS) + return (result); + column += (target->used - type_start); + } + + /* Rdata. */ + { + dns_rdata_t rdata; + isc_region_t r; + + INDENT_TO(rdata_column); + dns_rdataset_current(rdataset, &rdata); + + RETERR(dns_rdata_totext(&rdata, &ctx->rdata_ctx, target)); + + isc_buffer_available(target, &r); + if (r.length < 1) + return (DNS_R_NOSPACE); + r.base[0] = '\n'; + isc_buffer_add(target, 1); + } + + first = ISC_FALSE; + result = dns_rdataset_next(rdataset); + } while (result == DNS_R_SUCCESS); + + if (result != DNS_R_NOMORE) + return (result); + + /* + * Update the ctx state to reflect what we just printed. + * This is done last, only when we are sure we will return + * success, because this function may be called multiple + * times with increasing buffer sizes until it succeeds, + * and failed attempts must not update the state prematurely. + */ + ctx->class_printed = ISC_TRUE; + ctx->current_ttl= current_ttl; + ctx->current_ttl_valid = current_ttl_valid; + + return (DNS_R_SUCCESS); +} + +/* + * Print the name, type, and class of an empty rdataset, + * such as those used to represent the question section + * of a DNS message. + */ +static dns_result_t +question_totext(dns_rdataset_t *rdataset, + dns_name_t *owner_name, + dns_totext_ctx_t *ctx, + isc_boolean_t omit_final_dot, + isc_buffer_t *target) +{ + unsigned int column; + dns_result_t result; + + REQUIRE(DNS_RDATASET_VALID(rdataset)); + result = dns_rdataset_first(rdataset); + REQUIRE(result == DNS_R_NOMORE); + + column = 0; + + /* Owner name */ + { + unsigned int name_start = target->used; + RETERR(dns_name_totext(owner_name, + omit_final_dot, + target)); + column += target->used - name_start; + } + + /* Class */ + { + unsigned int class_start; + INDENT_TO(class_column); + class_start = target->used; + result = dns_rdataclass_totext(rdataset->rdclass, target); + if (result != DNS_R_SUCCESS) + return (result); + column += (target->used - class_start); + } + + /* Type */ + { + unsigned int type_start; + INDENT_TO(type_column); + type_start = target->used; + result = dns_rdatatype_totext(rdataset->type, target); + if (result != DNS_R_SUCCESS) + return (result); + column += (target->used - type_start); + } + return (DNS_R_SUCCESS); +} + +/* + * Provide a backwards compatible interface for printing a + * single rdataset or question section. This is now used + * only by wire_test.c. + */ +dns_result_t +dns_rdataset_totext(dns_rdataset_t *rdataset, + dns_name_t *owner_name, + isc_boolean_t omit_final_dot, + isc_boolean_t no_rdata_or_ttl, + isc_buffer_t *target) +{ + dns_totext_ctx_t ctx; + dns_result_t result; + result = totext_ctx_init(&dns_masterfile_style_debug, &ctx); + if (result != DNS_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "could not set master file style"); + return (DNS_R_UNEXPECTED); + } + + /* + * The caller might want to give us an empty owner + * name (e.g. if they are outputting into a master + * file and this rdataset has the same name as the + * previous one.) + */ + if (dns_name_countlabels(owner_name) == 0) + owner_name = NULL; + + if (no_rdata_or_ttl) + return (question_totext(rdataset, owner_name, &ctx, + omit_final_dot, target)); + else + return (rdataset_totext(rdataset, owner_name, &ctx, + omit_final_dot, target)); +} + +/* + * Print an rdataset. 'buffer' is a scratch buffer, which must have been + * dynamically allocated by the caller. It must be large enough to + * hold the result from dns_ttl_totext(). If more than that is needed, + * the buffer will be grown automatically. + */ + +static dns_result_t +dump_rdataset(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset, + dns_totext_ctx_t *ctx, + isc_buffer_t *buffer, FILE *f) +{ + isc_region_t r; + dns_result_t result; + size_t nwritten; + + REQUIRE(buffer->length > 0); + + /* Output a $TTL directive if needed. */ + + if ((ctx->style.flags & DNS_STYLEFLAG_TTL) != 0) { + if (ctx->current_ttl_valid == ISC_FALSE || + ctx->current_ttl != rdataset->ttl) + { + if ((ctx->style.flags & DNS_STYLEFLAG_COMMENT) != 0) + { + isc_buffer_clear(buffer); + result = dns_ttl_totext(rdataset->ttl, + ISC_TRUE, buffer); + INSIST(result == DNS_R_SUCCESS); + isc_buffer_used(buffer, &r); + fprintf(f, "$TTL %u\t; %.*s\n", rdataset->ttl, + (int) r.length, (char *) r.base); + } else { + fprintf(f, "$TTL %u\n", rdataset->ttl); + } + ctx->current_ttl = rdataset->ttl; + ctx->current_ttl_valid = ISC_TRUE; + } + } + + isc_buffer_clear(buffer); + + /* + * Generate the text representation of the rdataset into + * the buffer. If the buffer is too small, grow it. + */ + for (;;) { + int newlength; + void *newmem; + result = rdataset_totext(rdataset, name, ctx, + ISC_FALSE, buffer); + if (result != DNS_R_NOSPACE) + break; + + isc_mem_put(mctx, buffer->base, buffer->length); + newlength = buffer->length * 2; + newmem = isc_mem_get(mctx, newlength); + if (newmem == NULL) + return (DNS_R_NOMEMORY); + isc_buffer_init(buffer, newmem, newlength, + ISC_BUFFERTYPE_TEXT); + } + if (result != DNS_R_SUCCESS) + return (result); + + /* Write the buffer contents to the master file. */ + isc_buffer_used(buffer, &r); + nwritten = fwrite(r.base, 1, (size_t) r.length, f); + + if (nwritten != (size_t) r.length) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "master file write failed: %s\n", + strerror(errno)); + return (DNS_R_UNEXPECTED); + } + + return (DNS_R_SUCCESS); +} + +/* + * Dump all the rdatasets of a domain name to a master file. + */ +static dns_result_t +dump_rdatasets(isc_mem_t *mctx, dns_name_t *name, dns_rdatasetiter_t *rdsiter, + dns_totext_ctx_t *ctx, + isc_buffer_t *buffer, FILE *f) +{ + dns_result_t result; + dns_rdataset_t rdataset; + + dns_rdataset_init(&rdataset); + result = dns_rdatasetiter_first(rdsiter); + while (result == DNS_R_SUCCESS) { + dns_rdatasetiter_current(rdsiter, &rdataset); + result = dump_rdataset(mctx, name, &rdataset, ctx, buffer, f); + dns_rdataset_disassociate(&rdataset); + if (result != DNS_R_SUCCESS) + return (result); + result = dns_rdatasetiter_next(rdsiter); + if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0) + name = NULL; + } + if (result != DNS_R_NOMORE) + return (result); + return (DNS_R_SUCCESS); +} + + +/* + * Initial size of text conversion buffer. The buffer is used + * for several purposes: converting origin names, rdatasets, + * $DATE timestamps, and comment strings for $TTL directives. + * + * When converting rdatasets, it is dynamically resized, but + * when converting origins, timestamps, etc it is not. Therefore, + * the initial size must large enough to hold the longest possible + * text representation of any domain name (for $ORIGIN). + */ +const int initial_buffer_length = 1200; + +/* + * Dump an entire database into a master file. + */ +static dns_result_t +dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db, + dns_dbversion_t *version, + const dns_master_style_t *style, + FILE *f) +{ + dns_fixedname_t fixname; + dns_name_t *name; + dns_dbiterator_t *dbiter = NULL; + dns_result_t result; + isc_buffer_t buffer; + char *bufmem; + isc_stdtime_t now; + isc_region_t r; + dns_totext_ctx_t ctx; + + result = totext_ctx_init(style, &ctx); + if (result != DNS_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "could not set master file style"); + return (DNS_R_UNEXPECTED); + } + + dns_fixedname_init(&fixname); + name = dns_fixedname_name(&fixname); + + if (isc_stdtime_get(&now) != ISC_R_SUCCESS) + return (DNS_R_UNEXPECTED); + + bufmem = isc_mem_get(mctx, initial_buffer_length); + if (bufmem == NULL) + return (DNS_R_NOMEMORY); + + isc_buffer_init(&buffer, bufmem, initial_buffer_length, + ISC_BUFFERTYPE_TEXT); + + /* + * If the database has cache semantics, output an RFC2540 + * $DATE directive so that the TTLs can be adjusted when + * it is reloaded. For zones it is not really needed, and + * it would make the file incompatible with pre-RFC2540 + * software, so we omit it in the zone case. + */ + if (dns_db_iscache(db)) { + result = dns_time32_totext(now, &buffer); + RUNTIME_CHECK(result == DNS_R_SUCCESS); + isc_buffer_used(&buffer, &r); + fprintf(f, "$DATE %.*s\n", (int) r.length, (char *) r.base); + } + + result = dns_db_createiterator(db, + ((ctx.style.flags & DNS_STYLEFLAG_REL_OWNER) != 0) ? + ISC_TRUE : ISC_FALSE, + &dbiter); + if (result != DNS_R_SUCCESS) + goto create_iter_failure; + + result = dns_dbiterator_first(dbiter); + + while (result == DNS_R_SUCCESS) { + dns_rdatasetiter_t *rdsiter = NULL; + dns_dbnode_t *node = NULL; + result = dns_dbiterator_current(dbiter, &node, name); + if (result != DNS_R_SUCCESS && result != DNS_R_NEWORIGIN) + break; + if (result == DNS_R_NEWORIGIN) { + dns_name_t *origin = dns_fixedname_name(&ctx.origin_fixname); + result = dns_dbiterator_origin(dbiter, origin); + RUNTIME_CHECK(result == DNS_R_SUCCESS); + isc_buffer_clear(&buffer); + result = dns_name_totext(origin, ISC_FALSE, &buffer); + RUNTIME_CHECK(result == DNS_R_SUCCESS); + isc_buffer_used(&buffer, &r); + fprintf(f, "$ORIGIN %.*s\n", (int) r.length, + (char *) r.base); + if (ctx.style.flags & DNS_STYLEFLAG_REL_DATA) + ctx.rdata_ctx.origin = origin; + } + result = dns_db_allrdatasets(db, node, version, now, &rdsiter); + if (result != DNS_R_SUCCESS) { + dns_db_detachnode(db, &node); + goto iter_failure; + } + result = dump_rdatasets(mctx, name, rdsiter, &ctx, + &buffer, f); + if (result != DNS_R_SUCCESS) { + dns_db_detachnode(db, &node); + goto iter_failure; + } + dns_rdatasetiter_destroy(&rdsiter); + dns_db_detachnode(db, &node); + result = dns_dbiterator_next(dbiter); + } + if (result != DNS_R_NOMORE) + goto iter_failure; + + result = DNS_R_SUCCESS; + + iter_failure: + dns_dbiterator_destroy(&dbiter); + + create_iter_failure: + isc_mem_put(mctx, buffer.base, buffer.length); + return (result); +} + + +dns_result_t +dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version, + const dns_master_style_t *style, char *filename) +{ + FILE *f; + dns_result_t result; + + f = fopen(filename, "w"); + if (f == NULL) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "could not open %s", + filename); + return (DNS_R_UNEXPECTED); + } + + result = dns_master_dumptostream(mctx, db, version, style, f); + + if (fclose(f) != 0) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "error closing %s", + filename); + return (DNS_R_UNEXPECTED); + } + + return (result); +} diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index dbfd3de80b..d73e7662f1 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef DNS_RBTDB_VERSION64 #include "rbtdb64.h" @@ -2550,23 +2551,21 @@ load(dns_db_t *db, char *filename) { dns_rdatacallbacks_t callbacks; dns_result_t result; dns_name_t name; - + isc_boolean_t age_ttl; + rbtdb = (dns_rbtdb_t *)db; REQUIRE(VALID_RBTDB(rbtdb)); loadctx.rbtdb = rbtdb; if ((rbtdb->common.attributes & DNS_DBATTR_CACHE) != 0) { - /* - * XXXRTH This is not quite right. We should probably - * use the last file modification time or perhaps the value - * of an new master file option (e.g. $TIME) as the 'now' - * time. - */ if (isc_stdtime_get(&loadctx.now) != DNS_R_SUCCESS) return (DNS_R_UNEXPECTED); - } else + age_ttl = ISC_TRUE; + } else { loadctx.now = 0; + age_ttl = ISC_FALSE; + } LOCK(&rbtdb->lock); @@ -2613,10 +2612,23 @@ load(dns_db_t *db, char *filename) { return (dns_master_load(filename, &rbtdb->common.origin, &rbtdb->common.origin, rbtdb->common.rdclass, - &soacount, &nscount, &callbacks, + age_ttl, &soacount, &nscount, &callbacks, rbtdb->common.mctx)); } +static dns_result_t +dump(dns_db_t *db, dns_dbversion_t *version, char *filename) { + dns_rbtdb_t *rbtdb; + + rbtdb = (dns_rbtdb_t *)db; + + REQUIRE(VALID_RBTDB(rbtdb)); + + return (dns_master_dump(rbtdb->common.mctx, db, version, + &dns_master_style_default, + filename)); +} + static void delete_callback(void *data, void *arg) { dns_rbtdb_t *rbtdb = arg; @@ -2632,6 +2644,7 @@ static dns_dbmethods_t zone_methods = { attach, detach, load, + dump, currentversion, newversion, attachversion, @@ -2653,6 +2666,7 @@ static dns_dbmethods_t cache_methods = { attach, detach, load, + dump, currentversion, newversion, attachversion, diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index e4aa2e6ba2..8f89788f1d 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -15,13 +15,12 @@ * SOFTWARE. */ - /* $Id: rdata.c,v 1.47 1999/05/27 18:03:40 gson Exp $ */ + /* $Id: rdata.c,v 1.48 1999/06/08 10:35:06 gson Exp $ */ #include #include #include -#include #include #include @@ -40,6 +39,8 @@ #include #include #include +#include +#include #define RETERR(x) do { \ dns_result_t __r = (x); \ @@ -73,9 +74,6 @@ static dns_result_t mem_tobuffer(isc_buffer_t *target, void *base, static int compare_region(isc_region_t *r1, isc_region_t *r2); static int hexvalue(char value); static int decvalue(char value); -static dns_result_t time_totext(unsigned long value, - isc_buffer_t *target); -static dns_result_t time_tobuffer(char *source, isc_buffer_t *target); static dns_result_t btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target); static dns_result_t atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target); @@ -415,7 +413,7 @@ dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t class, } dns_result_t -dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, +dns_rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target) { dns_result_t result = DNS_R_NOTIMPLEMENTED; @@ -423,8 +421,8 @@ dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, REQUIRE(rdata != NULL); REQUIRE(isc_buffer_type(target) == ISC_BUFFERTYPE_TEXT); - if (origin != NULL) - REQUIRE(dns_name_isabsolute(origin) == ISC_TRUE); + if (tctx->origin != NULL) + REQUIRE(dns_name_isabsolute(tctx->origin) == ISC_TRUE); TOTEXTSWITCH @@ -983,105 +981,6 @@ decvalue(char value) { return (s - decdigits); } -static int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -static dns_result_t -time_totext(unsigned long value, isc_buffer_t *target) { - isc_int64_t start; - isc_int64_t base; - isc_int64_t t; - struct tm tm; - char buf[sizeof "YYYYMMDDHHMMSS"]; - int secs; - - /* find the right epoch */ - start = time(NULL); - start -= 0x7fffffff; - base = 0; - while ((t = (base + value)) < start) { - base += 0x80000000; - base += 0x80000000; - } - -#define is_leap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) -#define year_secs(y) ((is_leap(y) ? 366 : 365 ) * 86400) -#define month_secs(m, y) ((days[m] + ((m == 1 && is_leap(y)) ? 1 : 0 )) * 86400) - - - tm.tm_year = 70; - while ((secs = year_secs(tm.tm_year + 1900)) <= t) { - t -= secs; - tm.tm_year++; - } - tm.tm_mon = 0; - while ((secs = month_secs(tm.tm_mon, tm.tm_year + 1900)) <= t) { - t -= secs; - tm.tm_mon++; - } - tm.tm_mday = 1; - while (86400 <= t) { - t -= 86400; - tm.tm_mday++; - } - tm.tm_hour = 0; - while (3600 <= t) { - t -= 3600; - tm.tm_hour++; - } - tm.tm_min = 0; - while (60 <= t) { - t -= 60; - tm.tm_min++; - } - tm.tm_sec = t; - /* yy mm dd HH MM SS */ - sprintf(buf, "%04d%02d%02d%02d%02d%02d", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - return (str_totext(buf, target)); -} - -static dns_result_t -time_tobuffer(char *source, isc_buffer_t *target) { - int year, month, day, hour, minute, second; - unsigned long value; - int secs; - int i; - -#define RANGE(min, max, value) \ - do { \ - if (value < (min) || value > (max)) \ - return (DNS_R_RANGE); \ - } while (0) - - if (strlen(source) != 14) - return (DNS_R_SYNTAX); - if (sscanf(source, "%4d%2d%2d%2d%2d%2d", - &year, &month, &day, &hour, &minute, &second) != 6) - return (DNS_R_SYNTAX); - - RANGE(1970, 9999, year); - RANGE(1, 12, month); - RANGE(1, days[month - 1] + - ((month == 2 && is_leap(year)) ? 1 : 0), day); - RANGE(0, 23, hour); - RANGE(0, 59, minute); - RANGE(0, 60, second); /* leap second */ - - /* calulate seconds since epoch */ - value = second + (60 * minute) + (3600 * hour) + ((day - 1) * 86400); - for (i = 0; i < (month - 1) ; i++) - value += days[i] * 86400; - if (is_leap(year) && month > 2) - value += 86400; - for (i = 1970; i < year; i++) { - secs = (is_leap(i) ? 366 : 365) * 86400; - value += secs; - } - - return (uint32_tobuffer(value, target)); -} - static const char atob_digits[86] = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu"; /* @@ -1382,3 +1281,4 @@ fromtext_error(void (*callback)(dns_rdatacallbacks_t *, char *, ...), name, line, dns_result_totext(result)); } } + diff --git a/lib/dns/rdata/any_255/tsig_250.c b/lib/dns/rdata/any_255/tsig_250.c index adc0bdf190..cd307362c0 100644 --- a/lib/dns/rdata/any_255/tsig_250.c +++ b/lib/dns/rdata/any_255/tsig_250.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: tsig_250.c,v 1.10 1999/05/18 17:46:59 bwelling Exp $ */ + /* $Id: tsig_250.c,v 1.11 1999/06/08 10:35:08 gson Exp $ */ /* draft-ietf-dnsind-tsig-07.txt */ @@ -93,7 +93,9 @@ fromtext_any_tsig(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_any_tsig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_any_tsig(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; isc_region_t sigr; char buf[sizeof "281474976710655 "]; @@ -112,7 +114,7 @@ totext_any_tsig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_init(&name, NULL); dns_name_init(&prefix, NULL); dns_name_fromregion(&name, &sr); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); isc_region_consume(&sr, name_length(&name)); @@ -149,8 +151,11 @@ totext_any_tsig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(n <= sr.length); sigr = sr; sigr.length = n; - RETERR(isc_base64_totext(&sigr, target)); - RETERR(str_totext(" ", target)); + RETERR(str_totext("(", target)); + RETERR(str_totext(tctx->linebreak, target)); + RETERR(isc_base64_totext(&sigr, tctx->width - 2, + tctx->linebreak, target)); + RETERR(str_totext(" ) ", target)); isc_region_consume(&sr, n); /* Original ID */ @@ -172,7 +177,7 @@ totext_any_tsig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { RETERR(str_totext(buf, target)); /* Other */ - return (isc_base64_totext(&sr, target)); + return (isc_base64_totext(&sr, 60, " ", target)); } static dns_result_t diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c index a2969685ed..569718d57f 100644 --- a/lib/dns/rdata/generic/afsdb_18.c +++ b/lib/dns/rdata/generic/afsdb_18.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: afsdb_18.c,v 1.7 1999/05/07 03:24:05 marka Exp $ */ + /* $Id: afsdb_18.c,v 1.8 1999/06/08 10:35:09 gson Exp $ */ /* RFC 1183 */ @@ -49,7 +49,9 @@ fromtext_afsdb(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_afsdb(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_afsdb(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ dns_name_t name; dns_name_t prefix; isc_region_t region; @@ -69,7 +71,7 @@ totext_afsdb(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { sprintf(buf, "%u ", num); RETERR(str_totext(buf, target)); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c index 64d6f26463..11517629f9 100644 --- a/lib/dns/rdata/generic/cert_37.c +++ b/lib/dns/rdata/generic/cert_37.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: cert_37.c,v 1.8 1999/05/18 17:46:59 bwelling Exp $ */ + /* $Id: cert_37.c,v 1.9 1999/06/08 10:35:09 gson Exp $ */ /* draft-ietf-dnssec-certs-04.txt */ @@ -74,14 +74,16 @@ fromtext_cert(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_cert(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_cert(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; char buf[sizeof "64000 "]; unsigned int n; REQUIRE(rdata->type == 37); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, &sr); @@ -103,7 +105,12 @@ totext_cert(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { isc_region_consume(&sr, 1); /* cert */ - return (isc_base64_totext(&sr, target)); + RETERR(str_totext("(", target)); + RETERR(str_totext(tctx->linebreak, target)); + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + RETERR(str_totext(" )", target)); + return (DNS_R_SUCCESS); } static dns_result_t diff --git a/lib/dns/rdata/generic/cname_5.c b/lib/dns/rdata/generic/cname_5.c index cfa8a65419..436dcd9c42 100644 --- a/lib/dns/rdata/generic/cname_5.c +++ b/lib/dns/rdata/generic/cname_5.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: cname_5.c,v 1.13 1999/05/07 03:24:06 marka Exp $ */ + /* $Id: cname_5.c,v 1.14 1999/06/08 10:35:09 gson Exp $ */ #ifndef RDATA_GENERIC_CNAME_5_C #define RDATA_GENERIC_CNAME_5_C @@ -43,7 +43,9 @@ fromtext_cname(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_cname(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_cname(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -57,7 +59,7 @@ totext_cname(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/dname_39.c b/lib/dns/rdata/generic/dname_39.c index 44075456b9..3f0931fab2 100644 --- a/lib/dns/rdata/generic/dname_39.c +++ b/lib/dns/rdata/generic/dname_39.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: dname_39.c,v 1.6 1999/05/07 03:24:06 marka Exp $ */ + /* $Id: dname_39.c,v 1.7 1999/06/08 10:35:09 gson Exp $ */ /* draft-ietf-dnsind-dname-02.txt */ @@ -44,7 +44,9 @@ fromtext_dname(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_dname(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_dname(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -58,7 +60,7 @@ totext_dname(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c index afa90cbaf3..76ed4b048c 100644 --- a/lib/dns/rdata/generic/gpos_27.c +++ b/lib/dns/rdata/generic/gpos_27.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: gpos_27.c,v 1.4 1999/05/07 03:24:06 marka Exp $ */ + /* $Id: gpos_27.c,v 1.5 1999/06/08 10:35:10 gson Exp $ */ /* RFC 1712 */ @@ -45,13 +45,15 @@ fromtext_gpos(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_gpos(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_gpos(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; int i; REQUIRE(rdata->type == 27); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, ®ion); diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c index 33c46fcc07..b87c12fcfb 100644 --- a/lib/dns/rdata/generic/hinfo_13.c +++ b/lib/dns/rdata/generic/hinfo_13.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: hinfo_13.c,v 1.12 1999/05/07 03:24:07 marka Exp $ */ + /* $Id: hinfo_13.c,v 1.13 1999/06/08 10:35:10 gson Exp $ */ #ifndef RDATA_GENERIC_HINFO_13_C #define RDATA_GENERIC_HINFO_13_C @@ -43,12 +43,14 @@ fromtext_hinfo(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_hinfo(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_hinfo(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; REQUIRE(rdata->type == 13); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, ®ion); RETERR(txt_totext(®ion, target)); diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c index a11b1ad766..0d6130e408 100644 --- a/lib/dns/rdata/generic/isdn_20.c +++ b/lib/dns/rdata/generic/isdn_20.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: isdn_20.c,v 1.5 1999/05/19 09:14:58 gson Exp $ */ + /* $Id: isdn_20.c,v 1.6 1999/06/08 10:35:10 gson Exp $ */ /* RFC 1183 */ @@ -50,12 +50,14 @@ fromtext_isdn(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_isdn(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_isdn(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; REQUIRE(rdata->type == 20); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, ®ion); RETERR(txt_totext(®ion, target)); diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c index cab21b1ca1..05d7053dc5 100644 --- a/lib/dns/rdata/generic/key_25.c +++ b/lib/dns/rdata/generic/key_25.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: key_25.c,v 1.6 1999/05/18 17:46:59 bwelling Exp $ */ + /* $Id: key_25.c,v 1.7 1999/06/08 10:35:11 gson Exp $ */ /* RFC 2065 */ @@ -63,14 +63,16 @@ fromtext_key(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_key(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_key(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; char buf[sizeof "64000"]; unsigned int flags; REQUIRE(rdata->type == 25); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, &sr); @@ -97,8 +99,13 @@ totext_key(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { return (DNS_R_SUCCESS); /* key */ - RETERR(str_totext(" ", target)); - return (isc_base64_totext(&sr, target)); + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + RETERR(str_totext(" )", target)); + + return DNS_R_SUCCESS; } static dns_result_t diff --git a/lib/dns/rdata/generic/loc_29.c b/lib/dns/rdata/generic/loc_29.c index 578532f550..061a9802e6 100644 --- a/lib/dns/rdata/generic/loc_29.c +++ b/lib/dns/rdata/generic/loc_29.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: loc_29.c,v 1.4 1999/05/07 03:24:07 marka Exp $ */ + /* $Id: loc_29.c,v 1.5 1999/06/08 10:35:11 gson Exp $ */ /* RFC 1876 */ @@ -376,7 +376,9 @@ fromtext_loc(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_loc(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_loc(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ int d1, m1, s1, fs1; int d2, m2, s2, fs2; unsigned long latitude; @@ -397,7 +399,7 @@ totext_loc(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(rdata->type == 29); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, &sr); diff --git a/lib/dns/rdata/generic/mb_7.c b/lib/dns/rdata/generic/mb_7.c index b22d9061e1..8cb25fc6c4 100644 --- a/lib/dns/rdata/generic/mb_7.c +++ b/lib/dns/rdata/generic/mb_7.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: mb_7.c,v 1.13 1999/05/07 03:24:08 marka Exp $ */ + /* $Id: mb_7.c,v 1.14 1999/06/08 10:35:11 gson Exp $ */ #ifndef RDATA_GENERIC_MB_7_C #define RDATA_GENERIC_MB_7_C @@ -43,7 +43,9 @@ fromtext_mb(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_mb(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_mb(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -57,7 +59,7 @@ totext_mb(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/md_3.c b/lib/dns/rdata/generic/md_3.c index 086aa4b071..75f08cabf7 100644 --- a/lib/dns/rdata/generic/md_3.c +++ b/lib/dns/rdata/generic/md_3.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: md_3.c,v 1.13 1999/05/07 03:24:08 marka Exp $ */ + /* $Id: md_3.c,v 1.14 1999/06/08 10:35:11 gson Exp $ */ #ifndef RDATA_GENERIC_MD_3_C #define RDATA_GENERIC_MD_3_C @@ -43,7 +43,9 @@ fromtext_md(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_md(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_md(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -52,10 +54,12 @@ totext_md(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(rdata->type == 3); dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/mf_4.c b/lib/dns/rdata/generic/mf_4.c index 736c453332..609fa340b4 100644 --- a/lib/dns/rdata/generic/mf_4.c +++ b/lib/dns/rdata/generic/mf_4.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: mf_4.c,v 1.12 1999/05/07 03:24:08 marka Exp $ */ + /* $Id: mf_4.c,v 1.13 1999/06/08 10:35:11 gson Exp $ */ #ifndef RDATA_GENERIC_MF_4_C #define RDATA_GENERIC_MF_4_C @@ -43,7 +43,9 @@ fromtext_mf(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_mf(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_mf(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -52,10 +54,12 @@ totext_mf(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(rdata->type == 4); dns_name_init(&name, NULL); + dns_name_init(&prefix, NULL); + dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/mg_8.c b/lib/dns/rdata/generic/mg_8.c index 538f6dba4a..c9fd10911a 100644 --- a/lib/dns/rdata/generic/mg_8.c +++ b/lib/dns/rdata/generic/mg_8.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: mg_8.c,v 1.12 1999/05/07 03:24:08 marka Exp $ */ + /* $Id: mg_8.c,v 1.13 1999/06/08 10:35:11 gson Exp $ */ #ifndef RDATA_GENERIC_MG_8_C #define RDATA_GENERIC_MG_8_C @@ -43,7 +43,9 @@ fromtext_mg(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_mg(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_mg(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -57,7 +59,7 @@ totext_mg(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/minfo_14.c b/lib/dns/rdata/generic/minfo_14.c index 3cb780c677..1b4d435b2c 100644 --- a/lib/dns/rdata/generic/minfo_14.c +++ b/lib/dns/rdata/generic/minfo_14.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: minfo_14.c,v 1.13 1999/05/07 03:24:09 marka Exp $ */ + /* $Id: minfo_14.c,v 1.14 1999/06/08 10:35:12 gson Exp $ */ #ifndef RDATA_GENERIC_MINFO_14_C #define RDATA_GENERIC_MINFO_14_C @@ -48,7 +48,9 @@ fromtext_minfo(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_minfo(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_minfo(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t rmail; dns_name_t email; @@ -69,13 +71,13 @@ totext_minfo(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_fromregion(&email, ®ion); isc_region_consume(®ion, email.length); - sub = name_prefix(&rmail, origin, &prefix); + sub = name_prefix(&rmail, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); - sub = name_prefix(&email, origin, &prefix); + sub = name_prefix(&email, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/mr_9.c b/lib/dns/rdata/generic/mr_9.c index b9123ea893..a955fb3d19 100644 --- a/lib/dns/rdata/generic/mr_9.c +++ b/lib/dns/rdata/generic/mr_9.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: mr_9.c,v 1.12 1999/05/07 03:24:09 marka Exp $ */ + /* $Id: mr_9.c,v 1.13 1999/06/08 10:35:12 gson Exp $ */ #ifndef RDATA_GENERIC_MR_9_C #define RDATA_GENERIC_MR_9_C @@ -43,7 +43,9 @@ fromtext_mr(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_mr(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_mr(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -57,7 +59,7 @@ totext_mr(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/mx_15.c b/lib/dns/rdata/generic/mx_15.c index b3ad6e16fa..b39d3361a4 100644 --- a/lib/dns/rdata/generic/mx_15.c +++ b/lib/dns/rdata/generic/mx_15.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: mx_15.c,v 1.15 1999/05/07 03:24:09 marka Exp $ */ + /* $Id: mx_15.c,v 1.16 1999/06/08 10:35:12 gson Exp $ */ #ifndef RDATA_GENERIC_MX_15_C #define RDATA_GENERIC_MX_15_C @@ -47,7 +47,9 @@ fromtext_mx(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_mx(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_mx(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -67,7 +69,7 @@ totext_mx(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/ns_2.c b/lib/dns/rdata/generic/ns_2.c index 24ada6a4f7..f13ace16a3 100644 --- a/lib/dns/rdata/generic/ns_2.c +++ b/lib/dns/rdata/generic/ns_2.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: ns_2.c,v 1.12 1999/05/07 03:24:09 marka Exp $ */ + /* $Id: ns_2.c,v 1.13 1999/06/08 10:35:14 gson Exp $ */ #ifndef RDATA_GENERIC_NS_2_C #define RDATA_GENERIC_NS_2_C @@ -43,7 +43,9 @@ fromtext_ns(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_ns(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_ns(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -57,7 +59,7 @@ totext_ns(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/null_10.c b/lib/dns/rdata/generic/null_10.c index 18deaf7d26..eca25e5042 100644 --- a/lib/dns/rdata/generic/null_10.c +++ b/lib/dns/rdata/generic/null_10.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: null_10.c,v 1.9 1999/05/07 03:24:10 marka Exp $ */ + /* $Id: null_10.c,v 1.10 1999/06/08 10:35:18 gson Exp $ */ #ifndef RDATA_GENERIC_NULL_10_C #define RDATA_GENERIC_NULL_10_C @@ -39,13 +39,15 @@ fromtext_null(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_null(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_null(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ REQUIRE(rdata->type == 10); REQUIRE(rdata->length == 0); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ target = target; /*unused*/ return (DNS_R_SUCCESS); diff --git a/lib/dns/rdata/generic/nxt_30.c b/lib/dns/rdata/generic/nxt_30.c index d518767d61..f8172eff15 100644 --- a/lib/dns/rdata/generic/nxt_30.c +++ b/lib/dns/rdata/generic/nxt_30.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: nxt_30.c,v 1.9 1999/05/07 03:24:10 marka Exp $ */ + /* $Id: nxt_30.c,v 1.10 1999/06/08 10:35:18 gson Exp $ */ /* RFC 2065 */ @@ -74,7 +74,9 @@ fromtext_nxt(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_nxt(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_nxt(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; char buf[sizeof "65535"]; unsigned int i, j; @@ -90,7 +92,7 @@ totext_nxt(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, &sr); dns_name_fromregion(&name, &sr); isc_region_consume(&sr, name_length(&name)); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ( ", target)); diff --git a/lib/dns/rdata/generic/proforma.c b/lib/dns/rdata/generic/proforma.c index 699e7f6efa..6bfa1abfc9 100644 --- a/lib/dns/rdata/generic/proforma.c +++ b/lib/dns/rdata/generic/proforma.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: proforma.c,v 1.10 1999/05/07 03:24:10 marka Exp $ */ + /* $Id: proforma.c,v 1.11 1999/06/08 10:35:19 gson Exp $ */ #ifndef RDATA_GENERIC_#_#_C #define RDATA_GENERIC_#_#_C @@ -35,7 +35,9 @@ fromtext_#(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_#(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_#(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ REQUIRE(rdata->type == #); REQUIRE(rdata->class == #); diff --git a/lib/dns/rdata/generic/ptr_12.c b/lib/dns/rdata/generic/ptr_12.c index a880394105..8ea8361485 100644 --- a/lib/dns/rdata/generic/ptr_12.c +++ b/lib/dns/rdata/generic/ptr_12.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: ptr_12.c,v 1.13 1999/05/07 03:24:10 marka Exp $ */ + /* $Id: ptr_12.c,v 1.14 1999/06/08 10:35:19 gson Exp $ */ #ifndef RDATA_GENERIC_PTR_12_C #define RDATA_GENERIC_PTR_12_C @@ -43,7 +43,9 @@ fromtext_ptr(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_ptr(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_ptr(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -57,7 +59,7 @@ totext_ptr(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/rp_17.c b/lib/dns/rdata/generic/rp_17.c index 866f577b75..a6644b03d3 100644 --- a/lib/dns/rdata/generic/rp_17.c +++ b/lib/dns/rdata/generic/rp_17.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: rp_17.c,v 1.7 1999/05/07 03:24:11 marka Exp $ */ + /* $Id: rp_17.c,v 1.8 1999/06/08 10:35:19 gson Exp $ */ /* RFC 1183 */ @@ -50,7 +50,9 @@ fromtext_rp(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_rp(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_rp(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t rmail; dns_name_t email; @@ -71,13 +73,13 @@ totext_rp(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_fromregion(&email, ®ion); isc_region_consume(®ion, email.length); - sub = name_prefix(&rmail, origin, &prefix); + sub = name_prefix(&rmail, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); - sub = name_prefix(&email, origin, &prefix); + sub = name_prefix(&email, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c index a382a6ca64..b14fef7249 100644 --- a/lib/dns/rdata/generic/rt_21.c +++ b/lib/dns/rdata/generic/rt_21.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: rt_21.c,v 1.7 1999/05/07 03:24:11 marka Exp $ */ + /* $Id: rt_21.c,v 1.8 1999/06/08 10:35:19 gson Exp $ */ /* RFC 1183 */ @@ -49,7 +49,9 @@ fromtext_rt(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_rt(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_rt(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -69,7 +71,7 @@ totext_rt(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { RETERR(str_totext(buf, target)); RETERR(str_totext(" ", target)); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c index f60c42d1b8..0cff734f2e 100644 --- a/lib/dns/rdata/generic/sig_24.c +++ b/lib/dns/rdata/generic/sig_24.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: sig_24.c,v 1.12 1999/05/18 17:46:59 bwelling Exp $ */ + /* $Id: sig_24.c,v 1.13 1999/06/08 10:35:19 gson Exp $ */ /* RFC 2065 */ @@ -35,6 +35,7 @@ fromtext_sig(dns_rdataclass_t class, dns_rdatatype_t type, dns_result_t result; dns_name_t name; isc_buffer_t buffer; + isc_uint32_t time_signed, time_expire; REQUIRE(type == 24); @@ -73,11 +74,13 @@ fromtext_sig(dns_rdataclass_t class, dns_rdatatype_t type, /* signature expiration */ RETERR(gettoken(lexer, &token, isc_tokentype_string, ISC_FALSE)); - RETERR(time_tobuffer(token.value.as_pointer, target)); + RETERR(dns_time32_fromtext(token.value.as_pointer, &time_expire)); + RETERR(uint32_tobuffer(time_expire, target)); /* time signed */ RETERR(gettoken(lexer, &token, isc_tokentype_string, ISC_FALSE)); - RETERR(time_tobuffer(token.value.as_pointer, target)); + RETERR(dns_time32_fromtext(token.value.as_pointer, &time_signed)); + RETERR(uint32_tobuffer(time_signed, target)); /* key footprint */ RETERR(gettoken(lexer, &token, isc_tokentype_number, ISC_FALSE)); @@ -96,7 +99,9 @@ fromtext_sig(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_sig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_sig(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; char buf[sizeof "4294967295"]; dns_rdatatype_t covered; @@ -110,7 +115,7 @@ totext_sig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(rdata->type == 24); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, &sr); @@ -142,13 +147,16 @@ totext_sig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { /* sig exp */ exp = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(time_totext(exp, target)); + RETERR(dns_time32_totext(exp, target)); RETERR(str_totext(" ", target)); + RETERR(str_totext("(", target)); + RETERR(str_totext(tctx->linebreak, target)); + /* time signed */ when = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(time_totext(when, target)); + RETERR(dns_time32_totext(when, target)); RETERR(str_totext(" ", target)); /* footprint */ @@ -163,12 +171,16 @@ totext_sig(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_init(&prefix, NULL); dns_name_fromregion(&name, &sr); isc_region_consume(&sr, name_length(&name)); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); - RETERR(str_totext(" ", target)); /* sig */ - return (isc_base64_totext(&sr, target)); + RETERR(str_totext(tctx->linebreak, target)); + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + RETERR(str_totext(" )", target)); + + return DNS_R_SUCCESS; } static dns_result_t diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c index bbbfda3f21..4f1d444d6d 100644 --- a/lib/dns/rdata/generic/soa_6.c +++ b/lib/dns/rdata/generic/soa_6.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: soa_6.c,v 1.17 1999/05/07 03:24:11 marka Exp $ */ + /* $Id: soa_6.c,v 1.18 1999/06/08 10:35:19 gson Exp $ */ #ifndef RDATA_GENERIC_SOA_6_C #define RDATA_GENERIC_SOA_6_C @@ -51,11 +51,18 @@ fromtext_soa(dns_rdataclass_t class, dns_rdatatype_t type, ISC_FALSE)); RETERR(uint32_tobuffer(token.value.as_ulong, target)); } + return (DNS_R_SUCCESS); } +static char *soa_fieldnames[5] = { + "serial", "refresh", "retry", "expire", "minimum" +} ; + static dns_result_t -totext_soa(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_soa(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t dregion; dns_name_t mname; dns_name_t rname; @@ -77,25 +84,47 @@ totext_soa(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_fromregion(&rname, &dregion); isc_region_consume(&dregion, name_length(&rname)); - sub = name_prefix(&mname, origin, &prefix); + sub = name_prefix(&mname, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); - sub = name_prefix(&rname, origin, &prefix); + sub = name_prefix(&rname, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); + RETERR(str_totext(" (" , target)); + RETERR(str_totext(tctx->linebreak, target)); + for (i = 0; i < 5 ; i++) { char buf[sizeof "2147483647"]; unsigned long num; - - RETERR(str_totext(" ", target)); - + unsigned int numlen; num = uint32_fromregion(&dregion); isc_region_consume(&dregion, 4); - sprintf(buf, "%lu", num); + numlen = sprintf(buf, "%lu", num); + INSIST(numlen > 0 && numlen < sizeof "2147483647"); RETERR(str_totext(buf, target)); + if ((tctx->flags & (DNS_STYLEFLAG_MULTILINE | + DNS_STYLEFLAG_COMMENT)) == + (DNS_STYLEFLAG_MULTILINE | + DNS_STYLEFLAG_COMMENT)) + { + RETERR(str_totext(" ; " + numlen, target)); + RETERR(str_totext(soa_fieldnames[i], target)); + /* Print times in week/day/hour/minute/second form */ + if (i >= 1) { + RETERR(str_totext(" (", target)); + RETERR(dns_ttl_totext(num, ISC_TRUE, target)); + RETERR(str_totext(")", target)); + } + RETERR(str_totext(tctx->linebreak, target)); + } else { + RETERR(str_totext(" ", target)); + } } + + RETERR(str_totext(")", target)); + return (DNS_R_SUCCESS); } diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c index 48e85f2b1a..cf52f95542 100644 --- a/lib/dns/rdata/generic/tkey_249.c +++ b/lib/dns/rdata/generic/tkey_249.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: tkey_249.c,v 1.10 1999/05/18 17:46:59 bwelling Exp $ */ + /* $Id: tkey_249.c,v 1.11 1999/06/08 10:35:20 gson Exp $ */ /* draft-ietf-dnssec-tkey-01.txt */ @@ -93,7 +93,9 @@ fromtext_tkey(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_tkey(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_tkey(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; isc_region_t sigr; char buf[sizeof "4294967295 "]; @@ -110,7 +112,7 @@ totext_tkey(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_init(&name, NULL); dns_name_init(&prefix, NULL); dns_name_fromregion(&name, &sr); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); isc_region_consume(&sr, name_length(&name)); @@ -153,8 +155,11 @@ totext_tkey(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(n <= sr.length); sigr = sr; sigr.length = n; - RETERR(isc_base64_totext(&sigr, target)); - RETERR(str_totext(" ", target)); + RETERR(str_totext("(", target)); + RETERR(str_totext(tctx->linebreak, target)); + RETERR(isc_base64_totext(&sigr, tctx->width - 2, + tctx->linebreak, target)); + RETERR(str_totext(" ) ", target)); isc_region_consume(&sr, n); /* Other Size */ @@ -164,7 +169,7 @@ totext_tkey(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { RETERR(str_totext(buf, target)); /* Other */ - return (isc_base64_totext(&sr, target)); + return (isc_base64_totext(&sr, 60, " ", target)); } static dns_result_t diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c index a91e2f4f90..04a255a709 100644 --- a/lib/dns/rdata/generic/txt_16.c +++ b/lib/dns/rdata/generic/txt_16.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: txt_16.c,v 1.11 1999/05/07 03:24:12 marka Exp $ */ + /* $Id: txt_16.c,v 1.12 1999/06/08 10:35:20 gson Exp $ */ #ifndef RDATA_GENERIC_TXT_16_C #define RDATA_GENERIC_TXT_16_C @@ -47,12 +47,14 @@ fromtext_txt(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_txt(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_txt(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; REQUIRE(rdata->type == 16); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, ®ion); diff --git a/lib/dns/rdata/generic/unspec_103.c b/lib/dns/rdata/generic/unspec_103.c index 82eb735db4..0d9f61215f 100644 --- a/lib/dns/rdata/generic/unspec_103.c +++ b/lib/dns/rdata/generic/unspec_103.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: unspec_103.c,v 1.4 1999/05/07 03:24:12 marka Exp $ */ + /* $Id: unspec_103.c,v 1.5 1999/06/08 10:35:20 gson Exp $ */ #ifndef RDATA_GENERIC_UNSPEC_103_C #define RDATA_GENERIC_UNSPEC_103_C @@ -36,12 +36,14 @@ fromtext_unspec(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_unspec(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_unspec(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ REQUIRE(rdata->type == 103); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ return (btoa_totext(rdata->data, rdata->length, target)); } diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c index d725270c38..e0568708dc 100644 --- a/lib/dns/rdata/generic/x25_19.c +++ b/lib/dns/rdata/generic/x25_19.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: x25_19.c,v 1.4 1999/05/07 03:24:12 marka Exp $ */ + /* $Id: x25_19.c,v 1.5 1999/06/08 10:35:21 gson Exp $ */ /* RFC 1183 */ @@ -38,7 +38,7 @@ fromtext_x25(dns_rdataclass_t class, dns_rdatatype_t type, origin = origin; /*unused*/ downcase = downcase; /*unused*/ - RETERR(gettoken(lexer, &token, isc_tokentype_string, ISC_FALSE)); + RETERR(gettoken(lexer, &token, isc_tokentype_qstring, ISC_FALSE)); for (i = 0; i < token.value.as_textregion.length; i++) if (!isascii(token.value.as_textregion.base[i]&0xff) || !isdigit(token.value.as_textregion.base[i]&0xff)) @@ -47,12 +47,14 @@ fromtext_x25(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_x25(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_x25(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; REQUIRE(rdata->type == 19); - origin = origin; /*unused*/ + tctx = tctx; /*unused*/ dns_rdata_toregion(rdata, ®ion); return (txt_totext(®ion, target)); diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c index 20c60ae68a..5ca2fe9cce 100644 --- a/lib/dns/rdata/in_1/a6_38.c +++ b/lib/dns/rdata/in_1/a6_38.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: a6_38.c,v 1.9 1999/05/07 03:24:13 marka Exp $ */ + /* $Id: a6_38.c,v 1.10 1999/06/08 10:35:21 gson Exp $ */ /* draft-ietf-ipngwg-dns-lookups-03.txt */ @@ -86,7 +86,9 @@ fromtext_in_a6(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_a6(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_a6(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t tr; isc_region_t sr; unsigned char addr[16]; @@ -131,7 +133,7 @@ totext_in_a6(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { dns_name_init(&name, NULL); dns_name_init(&prefix, NULL); dns_name_fromregion(&name, &sr); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c index 8246614797..2d0914ac73 100644 --- a/lib/dns/rdata/in_1/a_1.c +++ b/lib/dns/rdata/in_1/a_1.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: a_1.c,v 1.14 1999/05/07 03:24:13 marka Exp $ */ + /* $Id: a_1.c,v 1.15 1999/06/08 10:35:21 gson Exp $ */ #ifndef RDATA_IN_1_A_1_C #define RDATA_IN_1_A_1_C @@ -58,14 +58,16 @@ fromtext_in_a(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_a(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_a(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; REQUIRE(rdata->type == 1); REQUIRE(rdata->class == 1); REQUIRE(rdata->length == 4); - origin = origin; /* unused */ + tctx = tctx; /* unused */ isc_buffer_available(target, ®ion); if (isc_inet_ntop(AF_INET, rdata->data, diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c index 99c5f16d1c..9d90a5d4d6 100644 --- a/lib/dns/rdata/in_1/aaaa_28.c +++ b/lib/dns/rdata/in_1/aaaa_28.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: aaaa_28.c,v 1.8 1999/05/07 03:24:13 marka Exp $ */ + /* $Id: aaaa_28.c,v 1.9 1999/06/08 10:35:21 gson Exp $ */ /* RFC 1886 */ @@ -60,14 +60,16 @@ fromtext_in_aaaa(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_aaaa(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_aaaa(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; REQUIRE(rdata->type == 28); REQUIRE(rdata->class == 1); REQUIRE(rdata->length == 16); - origin = origin; /* unused */ + tctx = tctx; /* unused */ isc_buffer_available(target, ®ion); if (isc_inet_ntop(AF_INET6, rdata->data, diff --git a/lib/dns/rdata/in_1/kx_36.c b/lib/dns/rdata/in_1/kx_36.c index ec3558015c..037da8eea6 100644 --- a/lib/dns/rdata/in_1/kx_36.c +++ b/lib/dns/rdata/in_1/kx_36.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: kx_36.c,v 1.7 1999/05/07 03:24:14 marka Exp $ */ + /* $Id: kx_36.c,v 1.8 1999/06/08 10:35:21 gson Exp $ */ /* RFC 2230 */ @@ -46,7 +46,9 @@ fromtext_in_kx(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_kx(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_kx(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -68,7 +70,7 @@ totext_in_kx(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { RETERR(str_totext(" ", target)); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/in_1/naptr_35.c b/lib/dns/rdata/in_1/naptr_35.c index e31bb2f3a9..d383b4abdf 100644 --- a/lib/dns/rdata/in_1/naptr_35.c +++ b/lib/dns/rdata/in_1/naptr_35.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: naptr_35.c,v 1.7 1999/05/07 03:24:14 marka Exp $ */ + /* $Id: naptr_35.c,v 1.8 1999/06/08 10:35:21 gson Exp $ */ /* RFC 2168 */ @@ -64,7 +64,9 @@ fromtext_in_naptr(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_naptr(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_naptr(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -107,7 +109,7 @@ totext_in_naptr(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { /* replacement */ dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.c b/lib/dns/rdata/in_1/nsap-ptr_23.c index 443c33a727..9f6f275668 100644 --- a/lib/dns/rdata/in_1/nsap-ptr_23.c +++ b/lib/dns/rdata/in_1/nsap-ptr_23.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: nsap-ptr_23.c,v 1.6 1999/05/07 03:24:14 marka Exp $ */ + /* $Id: nsap-ptr_23.c,v 1.7 1999/06/08 10:35:22 gson Exp $ */ /* RFC 1348 */ @@ -44,7 +44,7 @@ fromtext_in_nsap_ptr(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_nsap_ptr(dns_rdata_t *rdata, dns_name_t *origin, +totext_in_nsap_ptr(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, isc_buffer_t *target) { isc_region_t region; @@ -61,7 +61,7 @@ totext_in_nsap_ptr(dns_rdata_t *rdata, dns_name_t *origin, dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return (dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/in_1/nsap_22.c b/lib/dns/rdata/in_1/nsap_22.c index 409a4510a0..11004dbbf0 100644 --- a/lib/dns/rdata/in_1/nsap_22.c +++ b/lib/dns/rdata/in_1/nsap_22.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: nsap_22.c,v 1.5 1999/05/19 09:15:52 gson Exp $ */ + /* $Id: nsap_22.c,v 1.6 1999/06/08 10:35:22 gson Exp $ */ /* RFC 1706 */ @@ -72,14 +72,16 @@ fromtext_in_nsap(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_nsap(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_nsap(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; char buf[sizeof "xx"]; REQUIRE(rdata->type == 22); REQUIRE(rdata->class == 1); - origin = origin; /* unused */ + tctx = tctx; /* unused */ dns_rdata_toregion(rdata, ®ion); RETERR(str_totext("0x", target)); diff --git a/lib/dns/rdata/in_1/px_26.c b/lib/dns/rdata/in_1/px_26.c index 4b5036dc5b..64d916bea2 100644 --- a/lib/dns/rdata/in_1/px_26.c +++ b/lib/dns/rdata/in_1/px_26.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: px_26.c,v 1.6 1999/05/07 03:24:15 marka Exp $ */ + /* $Id: px_26.c,v 1.7 1999/06/08 10:35:22 gson Exp $ */ /* RFC 2163 */ @@ -56,7 +56,9 @@ fromtext_in_px(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_px(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_px(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -80,14 +82,14 @@ totext_in_px(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { /* MAP822 */ dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); isc_region_consume(®ion, name_length(&name)); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); /* MAPX400 */ dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/in_1/srv_33.c b/lib/dns/rdata/in_1/srv_33.c index 84f2445523..7d87798e7a 100644 --- a/lib/dns/rdata/in_1/srv_33.c +++ b/lib/dns/rdata/in_1/srv_33.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: srv_33.c,v 1.6 1999/05/07 03:24:15 marka Exp $ */ + /* $Id: srv_33.c,v 1.7 1999/06/08 10:35:23 gson Exp $ */ /* RFC 2052 bis */ @@ -56,7 +56,9 @@ fromtext_in_srv(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_srv(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_srv(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t region; dns_name_t name; dns_name_t prefix; @@ -94,7 +96,7 @@ totext_in_srv(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { /* target */ dns_name_fromregion(&name, ®ion); - sub = name_prefix(&name, origin, &prefix); + sub = name_prefix(&name, tctx->origin, &prefix); return(dns_name_totext(&prefix, sub, target)); } diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c index dd36710af9..ffa5e4d0b3 100644 --- a/lib/dns/rdata/in_1/wks_11.c +++ b/lib/dns/rdata/in_1/wks_11.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: wks_11.c,v 1.10 1999/05/07 03:24:15 marka Exp $ */ + /* $Id: wks_11.c,v 1.11 1999/06/08 10:35:23 gson Exp $ */ #ifndef RDATA_IN_1_WKS_11_C #define RDATA_IN_1_WKS_11_C @@ -113,7 +113,9 @@ fromtext_in_wks(dns_rdataclass_t class, dns_rdatatype_t type, } static dns_result_t -totext_in_wks(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { +totext_in_wks(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, + isc_buffer_t *target) +{ isc_region_t sr; isc_region_t tr; unsigned short proto; @@ -123,7 +125,7 @@ totext_in_wks(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target) { REQUIRE(rdata->type == 11); REQUIRE(rdata->class == 1); - origin = origin; + tctx = tctx; dns_rdata_toregion(rdata, &sr); isc_buffer_available(target, &tr); if (isc_inet_ntop(AF_INET, sr.base, (char *)tr.base, tr.length) diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index 8647b38c25..fe25c40a68 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -137,149 +137,6 @@ dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) { (rdataset->methods->current)(rdataset, rdata); } -static char *tabs = "\t\t\t\t\t\t\t\t\t\t"; - -static inline int -tabs_needed(unsigned int current_offset, unsigned int desired_offset) { - unsigned int needed; - unsigned int spaces; - - /* - * Assumes tabs are 8 characters. - */ - - if (current_offset >= desired_offset) - return (1); - spaces = desired_offset - current_offset; - needed = spaces / 8; - if (spaces % 8 != 0) - needed++; - if (needed > 10) - needed = 10; - return (needed); -} - -dns_result_t -dns_rdataset_totext(dns_rdataset_t *rdataset, - dns_name_t *owner_name, - isc_boolean_t omit_final_dot, - isc_boolean_t no_rdata_or_ttl, - isc_buffer_t *target) -{ - dns_result_t result; - unsigned int common_start, common_length, length, ntabs, ttabs; - char *common; - dns_rdata_t rdata; - isc_boolean_t first = ISC_TRUE; - isc_region_t r; - char ttl[64]; - - /* - * Convert 'rdataset' to text format, storing the result in 'target'. - */ - - REQUIRE(DNS_RDATASET_VALID(rdataset)); - result = dns_rdataset_first(rdataset); - if (no_rdata_or_ttl) { - REQUIRE(result == DNS_R_NOMORE); - } else { - REQUIRE(result == DNS_R_SUCCESS); - } - - /* - * XXX Explicit buffer structure references here. Improve buffer - * API. - */ - common_start = target->used; - /* - * The caller might want to give us an empty owner - * name (e.g. if they are outputting into a master - * file and this rdataset has the same name as the - * previous one.) - */ - if (dns_name_countlabels(owner_name) != 0) { - result = dns_name_totext(owner_name, - omit_final_dot, - target); - if (result != DNS_R_SUCCESS) - return (result); - } - common = (char *)target->base + common_start; - common_length = target->used - common_start; - ntabs = tabs_needed(common_length, 24); - ttabs = ntabs; - isc_buffer_available(target, &r); - if (r.length < ntabs) - return (DNS_R_NOSPACE); - memcpy(r.base, tabs, ntabs); - isc_buffer_add(target, ntabs); - /* - * XXX The following sprintf() is safe, but it - * would still be good to use snprintf if we had it. - */ - if (!no_rdata_or_ttl) { - length = sprintf(ttl, "%u ", rdataset->ttl); - INSIST(length <= sizeof ttl); - isc_buffer_available(target, &r); - if (r.length < length) - return (DNS_R_NOSPACE); - memcpy(r.base, ttl, length); - isc_buffer_add(target, length); - } - result = dns_rdataclass_totext(rdataset->rdclass, target); - if (result != DNS_R_SUCCESS) - return (result); - isc_buffer_available(target, &r); - if (r.length == 0) - return (DNS_R_NOSPACE); - *r.base = ' '; - isc_buffer_add(target, 1); - result = dns_rdatatype_totext(rdataset->type, target); - if (result != DNS_R_SUCCESS) - return (result); - common_length = target->used - common_start; - ntabs = tabs_needed(common_length + ttabs * 7, 40); - ttabs += ntabs; - - isc_buffer_available(target, &r); - if (r.length < ntabs) - return (DNS_R_NOSPACE); - memcpy(r.base, tabs, ntabs); - isc_buffer_add(target, ntabs); - common_length = target->used - common_start; - - if (no_rdata_or_ttl) - return (DNS_R_SUCCESS); - - do { - if (!first) { - isc_buffer_available(target, &r); - if (r.length < common_length) - return (DNS_R_NOSPACE); - memcpy(r.base, common, common_length); - isc_buffer_add(target, common_length); - } else - first = ISC_FALSE; - - dns_rdataset_current(rdataset, &rdata); - result = dns_rdata_totext(&rdata, NULL, target); - if (result != DNS_R_SUCCESS) - return (result); - isc_buffer_available(target, &r); - if (r.length < 1) - return (DNS_R_NOSPACE); - memcpy(r.base, "\n", 1); - isc_buffer_add(target, 1); - - result = dns_rdataset_next(rdataset); - } while (result == DNS_R_SUCCESS); - - if (result != DNS_R_NOMORE) - return (result); - - return (DNS_R_SUCCESS); -} - dns_result_t dns_rdataset_towire(dns_rdataset_t *rdataset, dns_name_t *owner_name, diff --git a/lib/dns/time.c b/lib/dns/time.c new file mode 100644 index 0000000000..f3d4903c9e --- /dev/null +++ b/lib/dns/time.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 1998, 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + + /* $Id: time.c,v 1.1 1999/06/08 10:35:06 gson Exp $ */ + +#include + +#include +#include + +#include + +#include +#include +#include + +static int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +dns_result_t +dns_time64_totext(isc_int64_t t, isc_buffer_t *target) { + struct tm tm; + char buf[sizeof "YYYYMMDDHHMMSS"]; + int secs; + unsigned int l; + isc_region_t region; + + REQUIRE(t >= 0); + +#define is_leap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) +#define year_secs(y) ((is_leap(y) ? 366 : 365 ) * 86400) +#define month_secs(m, y) ((days[m] + ((m == 1 && is_leap(y)) ? 1 : 0 )) * 86400) + + tm.tm_year = 70; + while ((secs = year_secs(tm.tm_year + 1900)) <= t) { + t -= secs; + tm.tm_year++; + if (tm.tm_year + 1900 > 9999) + return DNS_R_RANGE; + } + tm.tm_mon = 0; + while ((secs = month_secs(tm.tm_mon, tm.tm_year + 1900)) <= t) { + t -= secs; + tm.tm_mon++; + } + tm.tm_mday = 1; + while (86400 <= t) { + t -= 86400; + tm.tm_mday++; + } + tm.tm_hour = 0; + while (3600 <= t) { + t -= 3600; + tm.tm_hour++; + } + tm.tm_min = 0; + while (60 <= t) { + t -= 60; + tm.tm_min++; + } + tm.tm_sec = t; + /* yy mm dd HH MM SS */ + sprintf(buf, "%04d%02d%02d%02d%02d%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + isc_buffer_available(target, ®ion); + l = strlen(buf); + + if (l > region.length) + return (DNS_R_NOSPACE); + + memcpy(region.base, buf, l); + isc_buffer_add(target, l); + return (DNS_R_SUCCESS); +} + +dns_result_t +dns_time32_totext(isc_uint32_t value, isc_buffer_t *target) { + isc_int64_t start; + isc_int64_t base; + isc_int64_t t; + + /* Find the right epoch. */ + start = time(NULL); + start -= 0x7fffffff; + base = 0; + while ((t = (base + value)) < start) { + base += 0x80000000; + base += 0x80000000; + } + return (dns_time64_totext(t, target)); +} + +dns_result_t +dns_time64_fromtext(char *source, isc_int64_t *target) { + int year, month, day, hour, minute, second; + isc_int64_t value; + int secs; + int i; + +#define RANGE(min, max, value) \ + do { \ + if (value < (min) || value > (max)) \ + return (DNS_R_RANGE); \ + } while (0) + + if (strlen(source) != 14) + return (DNS_R_SYNTAX); + if (sscanf(source, "%4d%2d%2d%2d%2d%2d", + &year, &month, &day, &hour, &minute, &second) != 6) + return (DNS_R_SYNTAX); + + RANGE(1970, 9999, year); + RANGE(1, 12, month); + RANGE(1, days[month - 1] + + ((month == 2 && is_leap(year)) ? 1 : 0), day); + RANGE(0, 23, hour); + RANGE(0, 59, minute); + RANGE(0, 60, second); /* leap second */ + + /* Calulate seconds since epoch. */ + value = second + (60 * minute) + (3600 * hour) + ((day - 1) * 86400); + for (i = 0; i < (month - 1) ; i++) + value += days[i] * 86400; + if (is_leap(year) && month > 2) + value += 86400; + for (i = 1970; i < year; i++) { + secs = (is_leap(i) ? 366 : 365) * 86400; + value += secs; + } + + *target = value; + return (DNS_R_SUCCESS); +} + +dns_result_t +dns_time32_fromtext(char *source, isc_uint32_t *target) { + isc_int64_t value64; + isc_int64_t value32; + dns_result_t result; + result = dns_time64_fromtext(source, &value64); + if (result != DNS_R_SUCCESS) + return (result); + value32 = (isc_uint32_t) value64; + if (value32 != value64) + return DNS_R_RANGE; + *target = value32; + + return DNS_R_SUCCESS; +} diff --git a/lib/dns/ttl.c b/lib/dns/ttl.c new file mode 100644 index 0000000000..5d6d0da3d4 --- /dev/null +++ b/lib/dns/ttl.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) 1999 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define RETERR(x) do { \ + dns_result_t __r = (x); \ + if (__r != DNS_R_SUCCESS) \ + return (__r); \ + } while (0) + + +/* Helper for dns_ttl_totext(). */ + +static dns_result_t +ttlfmt(unsigned int t, char *s, isc_boolean_t verbose, + isc_boolean_t space, isc_buffer_t *target) +{ + char tmp[60]; + size_t len; + isc_region_t region; + if (verbose) + len = sprintf(tmp, "%s%u %s%s", + space ? " " : "", + t, s, + t == 1 ? "" : "s"); + else + len = sprintf(tmp, "%u%c", t, s[0]); + INSIST(len + 1 <= sizeof tmp); + isc_buffer_available(target, ®ion); + if (len > region.length) + return (DNS_R_NOSPACE); + memcpy(region.base, tmp, len); + isc_buffer_add(target, len); + return (DNS_R_SUCCESS); +} + +/* Derived from bind8 ns_format_ttl(). */ + +dns_result_t +dns_ttl_totext(isc_uint32_t src, isc_boolean_t verbose, + isc_buffer_t *target) +{ + unsigned secs, mins, hours, days, weeks, x; + + secs = src % 60; src /= 60; + mins = src % 60; src /= 60; + hours = src % 24; src /= 24; + days = src % 7; src /= 7; + weeks = src; src = 0; + + x = 0; + if (weeks != 0) { + RETERR(ttlfmt(weeks, "week", verbose, (x > 0), target)); + x++; + } + if (days != 0) { + RETERR(ttlfmt(days, "day", verbose, (x > 0), target)); + x++; + } + if (hours != 0) { + RETERR(ttlfmt(hours, "hour", verbose, (x > 0), target)); + x++; + } + if (mins != 0) { + RETERR(ttlfmt(mins, "minute", verbose, (x > 0), target)); + x++; + } + if (secs != 0 || (weeks == 0 && days == 0 && hours == 0 && mins == 0)) { + RETERR(ttlfmt(secs, "second", verbose, (x > 0), target)); + x++; + } + INSIST (x > 0); + /* + * If only a single unit letter is printed, print it + * in upper case. (Why? Because BIND 8 does that. + * Presumably it has a reason.) + */ + if (x == 1 && !verbose) { + isc_region_t region; + /* + * The unit letter is the last character in the + * used region of the buffer. + */ + isc_buffer_used(target, ®ion); + region.base[region.length - 1] = + toupper(region.base[region.length - 1]); + } + return (DNS_R_SUCCESS); +} + diff --git a/lib/isc/base64.c b/lib/isc/base64.c index 97b0ecca10..a36081924a 100644 --- a/lib/isc/base64.c +++ b/lib/isc/base64.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: base64.c,v 1.2 1999/05/19 01:17:14 marka Exp $ */ + /* $Id: base64.c,v 1.3 1999/06/08 10:35:23 gson Exp $ */ #include @@ -51,12 +51,16 @@ static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; isc_result_t -isc_base64_totext(isc_region_t *source, isc_buffer_t *target) { +isc_base64_totext(isc_region_t *source, int wordlength, + char *wordbreak, isc_buffer_t *target) +{ char buf[5]; - int loops = 0; + unsigned int loops = 0; + + if (wordlength < 4) + wordlength = 4; memset(buf, 0, sizeof buf); - RETERR(str_totext("( " /*)*/, target)); while (source->length > 2) { buf[0] = base64[(source->base[0]>>2)&0x3f]; buf[1] = base64[((source->base[0]<<4)&0x30)| @@ -66,9 +70,13 @@ isc_base64_totext(isc_region_t *source, isc_buffer_t *target) { buf[3] = base64[source->base[2]&0x3f]; RETERR(str_totext(buf, target)); isc_region_consume(source, 3); - if (source->length != 0 && ++loops == 15) { + + loops++; + if (source->length != 0 && + (int)((loops + 1) * 4) >= wordlength) + { loops = 0; - RETERR(str_totext(" ", target)); + RETERR(str_totext(wordbreak, target)); } } if (source->length == 2) { @@ -84,7 +92,6 @@ isc_base64_totext(isc_region_t *source, isc_buffer_t *target) { buf[2] = buf[3] = '='; RETERR(str_totext(buf, target)); } - RETERR(str_totext(" )", target)); return (ISC_R_SUCCESS); } diff --git a/lib/isc/include/isc/base64.h b/lib/isc/include/isc/base64.h index 7953252e78..ef0772ead4 100644 --- a/lib/isc/include/isc/base64.h +++ b/lib/isc/include/isc/base64.h @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: base64.h,v 1.1 1999/05/18 17:46:59 bwelling Exp $ */ + /* $Id: base64.h,v 1.2 1999/06/08 10:35:23 gson Exp $ */ #ifndef ISC_BASE64_H #define ISC_BASE64_H 1 @@ -34,10 +34,18 @@ ISC_LANG_BEGINDECLS ***/ /* Convert data into base64 encoded text. + * + * Notes: + * The base64 encoded text in "target" will be divided into + * words of at most "wordlength" characters, separated by + * the "wordbreak" string. No parentheses will surround + * the text. * * Requires: * "source" is a region containing binary data * "target" is a text buffer containing available space + * "wordbreak" points to a null-terminated string of + * zero or more whitespace characters * * Ensures: * target will contain the base64 encoded version of the data @@ -45,7 +53,8 @@ ISC_LANG_BEGINDECLS * necessary. */ isc_result_t -isc_base64_totext(isc_region_t *source, isc_buffer_t *target); +isc_base64_totext(isc_region_t *source, int wordlength, + char *wordbreak, isc_buffer_t *target); /* Convert base64 encoded text into data. *