15185a700Sflorian /*
25185a700Sflorian * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian *
45185a700Sflorian * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian * copyright notice and this permission notice appear in all copies.
75185a700Sflorian *
85185a700Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian */
165185a700Sflorian
17*1fb015a8Sflorian /* $Id: ttl.c,v 1.6 2020/09/14 08:40:43 florian Exp $ */
185185a700Sflorian
195185a700Sflorian /*! \file */
205185a700Sflorian
215185a700Sflorian #include <ctype.h>
225185a700Sflorian #include <stdio.h>
234465bcfbSjsg #include <string.h>
245185a700Sflorian
255185a700Sflorian #include <isc/buffer.h>
265185a700Sflorian #include <isc/region.h>
275185a700Sflorian #include <isc/util.h>
285185a700Sflorian
295185a700Sflorian #include <dns/ttl.h>
305185a700Sflorian
315185a700Sflorian #define RETERR(x) do { \
325185a700Sflorian isc_result_t _r = (x); \
335185a700Sflorian if (_r != ISC_R_SUCCESS) \
345185a700Sflorian return (_r); \
355185a700Sflorian } while (0)
365185a700Sflorian
375185a700Sflorian /*
385185a700Sflorian * Helper for dns_ttl_totext().
395185a700Sflorian */
405185a700Sflorian static isc_result_t
ttlfmt(unsigned int t,const char * s,int verbose,int space,isc_buffer_t * target)41*1fb015a8Sflorian ttlfmt(unsigned int t, const char *s, int verbose,
42*1fb015a8Sflorian int space, isc_buffer_t *target)
435185a700Sflorian {
445185a700Sflorian char tmp[60];
455185a700Sflorian unsigned int len;
465185a700Sflorian isc_region_t region;
475185a700Sflorian
485185a700Sflorian if (verbose)
495185a700Sflorian len = snprintf(tmp, sizeof(tmp), "%s%u %s%s",
505185a700Sflorian space ? " " : "",
515185a700Sflorian t, s,
525185a700Sflorian t == 1 ? "" : "s");
535185a700Sflorian else
545185a700Sflorian len = snprintf(tmp, sizeof(tmp), "%u%c", t, s[0]);
555185a700Sflorian
565185a700Sflorian INSIST(len + 1 <= sizeof(tmp));
575185a700Sflorian isc_buffer_availableregion(target, ®ion);
585185a700Sflorian if (len > region.length)
595185a700Sflorian return (ISC_R_NOSPACE);
605185a700Sflorian memmove(region.base, tmp, len);
615185a700Sflorian isc_buffer_add(target, len);
625185a700Sflorian
635185a700Sflorian return (ISC_R_SUCCESS);
645185a700Sflorian }
655185a700Sflorian
665185a700Sflorian /*
675185a700Sflorian * Derived from bind8 ns_format_ttl().
685185a700Sflorian */
695185a700Sflorian isc_result_t
dns_ttl_totext(uint32_t src,int verbose,isc_buffer_t * target)70*1fb015a8Sflorian dns_ttl_totext(uint32_t src, int verbose, isc_buffer_t *target) {
715185a700Sflorian unsigned secs, mins, hours, days, weeks, x;
725185a700Sflorian
735185a700Sflorian secs = src % 60; src /= 60;
745185a700Sflorian mins = src % 60; src /= 60;
755185a700Sflorian hours = src % 24; src /= 24;
765185a700Sflorian days = src % 7; src /= 7;
775185a700Sflorian weeks = src; src = 0;
785185a700Sflorian POST(src);
795185a700Sflorian
805185a700Sflorian x = 0;
815185a700Sflorian if (weeks != 0) {
82*1fb015a8Sflorian RETERR(ttlfmt(weeks, "week", verbose, (x > 0), target));
835185a700Sflorian x++;
845185a700Sflorian }
855185a700Sflorian if (days != 0) {
86*1fb015a8Sflorian RETERR(ttlfmt(days, "day", verbose, (x > 0), target));
875185a700Sflorian x++;
885185a700Sflorian }
895185a700Sflorian if (hours != 0) {
90*1fb015a8Sflorian RETERR(ttlfmt(hours, "hour", verbose, (x > 0), target));
915185a700Sflorian x++;
925185a700Sflorian }
935185a700Sflorian if (mins != 0) {
94*1fb015a8Sflorian RETERR(ttlfmt(mins, "minute", verbose, (x > 0), target));
955185a700Sflorian x++;
965185a700Sflorian }
975185a700Sflorian if (secs != 0 ||
985185a700Sflorian (weeks == 0 && days == 0 && hours == 0 && mins == 0)) {
99*1fb015a8Sflorian RETERR(ttlfmt(secs, "second", verbose, (x > 0), target));
1005185a700Sflorian x++;
1015185a700Sflorian }
1025185a700Sflorian INSIST (x > 0);
1035185a700Sflorian /*
1045185a700Sflorian * If only a single unit letter is printed, print it
1055185a700Sflorian * in upper case. (Why? Because BIND 8 does that.
1065185a700Sflorian * Presumably it has a reason.)
1075185a700Sflorian */
1085185a700Sflorian if (x == 1 && !verbose) {
1095185a700Sflorian isc_region_t region;
1105185a700Sflorian /*
1115185a700Sflorian * The unit letter is the last character in the
1125185a700Sflorian * used region of the buffer.
1135185a700Sflorian *
1145185a700Sflorian * toupper() does not need its argument to be masked of cast
1155185a700Sflorian * here because region.base is type unsigned char *.
1165185a700Sflorian */
1175185a700Sflorian isc_buffer_usedregion(target, ®ion);
1185185a700Sflorian region.base[region.length - 1] =
1195185a700Sflorian toupper(region.base[region.length - 1]);
1205185a700Sflorian }
1215185a700Sflorian return (ISC_R_SUCCESS);
1225185a700Sflorian }
123