/* * Copyright (C) Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * See the COPYRIGHT file distributed with this work for additional * information regarding copyright ownership. */ /* * A simple database driver that enables the server to return the * current time in a DNS record. */ #include #include #include #include #include #include #include #include #include #include "timedb.h" static dns_sdbimplementation_t *timedb = NULL; /* * This database operates on relative names. * * "time" and "@" return the time in a TXT record. * "clock" is a CNAME to "time" * "current" is a DNAME to "@" (try time.current.time) */ #ifdef DNS_CLIENTINFO_VERSION static isc_result_t timedb_lookup(const char *zone, const char *name, void *dbdata, dns_sdblookup_t *lookup, dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo) #else static isc_result_t timedb_lookup(const char *zone, const char *name, void *dbdata, dns_sdblookup_t *lookup) #endif /* DNS_CLIENTINFO_VERSION */ { isc_result_t result; UNUSED(zone); UNUSED(dbdata); #ifdef DNS_CLIENTINFO_VERSION UNUSED(methods); UNUSED(clientinfo); #endif /* DNS_CLIENTINFO_VERSION */ if (strcmp(name, "@") == 0 || strcmp(name, "time") == 0) { time_t now = time(NULL); char buf[100]; int n; /* * Call ctime to create the string, put it in quotes, and * remove the trailing newline. */ n = snprintf(buf, sizeof(buf), "\"%s", ctime(&now)); if (n < 0) return (ISC_R_FAILURE); buf[n - 1] = '\"'; result = dns_sdb_putrr(lookup, "txt", 1, buf); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); } else if (strcmp(name, "clock") == 0) { result = dns_sdb_putrr(lookup, "cname", 1, "time"); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); } else if (strcmp(name, "current") == 0) { result = dns_sdb_putrr(lookup, "dname", 1, "@"); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); } else return (ISC_R_NOTFOUND); return (ISC_R_SUCCESS); } /* * lookup() does not return SOA or NS records, so authority() must be defined. */ static isc_result_t timedb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) { isc_result_t result; UNUSED(zone); UNUSED(dbdata); result = dns_sdb_putsoa(lookup, "localhost.", "root.localhost.", 0); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); result = dns_sdb_putrr(lookup, "ns", 86400, "ns1.localdomain."); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); result = dns_sdb_putrr(lookup, "ns", 86400, "ns2.localdomain."); if (result != ISC_R_SUCCESS) return (ISC_R_FAILURE); return (ISC_R_SUCCESS); } /* * This zone does not support zone transfer, so allnodes() is NULL. There * is no database specific data, so create() and destroy() are NULL. */ static dns_sdbmethods_t timedb_methods = { timedb_lookup, timedb_authority, NULL, /* allnodes */ NULL, /* create */ NULL, /* destroy */ NULL /* lookup2 */ }; /* * Wrapper around dns_sdb_register(). */ isc_result_t timedb_init(void) { unsigned int flags; flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA; return (dns_sdb_register("time", &timedb_methods, NULL, flags, ns_g_mctx, &timedb)); } /* * Wrapper around dns_sdb_unregister(). */ void timedb_clear(void) { if (timedb != NULL) dns_sdb_unregister(&timedb); }