1/* 2 * Copyright (C) 2004, 2007, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 2000, 2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20/* 21 * A simple database driver that enables the server to return the 22 * current time in a DNS record. 23 */ 24 25#include <config.h> 26 27#include <string.h> 28#include <stdio.h> 29#include <time.h> 30 31#include <isc/print.h> 32#include <isc/result.h> 33#include <isc/util.h> 34 35#include <dns/sdb.h> 36 37#include <named/globals.h> 38 39#include "timedb.h" 40 41static dns_sdbimplementation_t *timedb = NULL; 42 43/* 44 * This database operates on relative names. 45 * 46 * "time" and "@" return the time in a TXT record. 47 * "clock" is a CNAME to "time" 48 * "current" is a DNAME to "@" (try time.current.time) 49 */ 50static isc_result_t 51timedb_lookup(const char *zone, const char *name, void *dbdata, 52 dns_sdblookup_t *lookup) 53{ 54 isc_result_t result; 55 56 UNUSED(zone); 57 UNUSED(dbdata); 58 59 if (strcmp(name, "@") == 0 || strcmp(name, "time") == 0) { 60 time_t now = time(NULL); 61 char buf[100]; 62 int n; 63 64 /* 65 * Call ctime to create the string, put it in quotes, and 66 * remove the trailing newline. 67 */ 68 n = snprintf(buf, sizeof(buf), "\"%s", ctime(&now)); 69 if (n < 0) 70 return (ISC_R_FAILURE); 71 buf[n - 1] = '\"'; 72 result = dns_sdb_putrr(lookup, "txt", 1, buf); 73 if (result != ISC_R_SUCCESS) 74 return (ISC_R_FAILURE); 75 } else if (strcmp(name, "clock") == 0) { 76 result = dns_sdb_putrr(lookup, "cname", 1, "time"); 77 if (result != ISC_R_SUCCESS) 78 return (ISC_R_FAILURE); 79 } else if (strcmp(name, "current") == 0) { 80 result = dns_sdb_putrr(lookup, "dname", 1, "@"); 81 if (result != ISC_R_SUCCESS) 82 return (ISC_R_FAILURE); 83 } else 84 return (ISC_R_NOTFOUND); 85 86 return (ISC_R_SUCCESS); 87} 88 89/* 90 * lookup() does not return SOA or NS records, so authority() must be defined. 91 */ 92static isc_result_t 93timedb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) { 94 isc_result_t result; 95 96 UNUSED(zone); 97 UNUSED(dbdata); 98 99 result = dns_sdb_putsoa(lookup, "localhost.", "root.localhost.", 0); 100 if (result != ISC_R_SUCCESS) 101 return (ISC_R_FAILURE); 102 103 result = dns_sdb_putrr(lookup, "ns", 86400, "ns1.localdomain."); 104 if (result != ISC_R_SUCCESS) 105 return (ISC_R_FAILURE); 106 result = dns_sdb_putrr(lookup, "ns", 86400, "ns2.localdomain."); 107 if (result != ISC_R_SUCCESS) 108 return (ISC_R_FAILURE); 109 110 return (ISC_R_SUCCESS); 111} 112 113/* 114 * This zone does not support zone transfer, so allnodes() is NULL. There 115 * is no database specific data, so create() and destroy() are NULL. 116 */ 117static dns_sdbmethods_t timedb_methods = { 118 timedb_lookup, 119 timedb_authority, 120 NULL, /* allnodes */ 121 NULL, /* create */ 122 NULL /* destroy */ 123}; 124 125/* 126 * Wrapper around dns_sdb_register(). 127 */ 128isc_result_t 129timedb_init(void) { 130 unsigned int flags; 131 flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA; 132 return (dns_sdb_register("time", &timedb_methods, NULL, flags, 133 ns_g_mctx, &timedb)); 134} 135 136/* 137 * Wrapper around dns_sdb_unregister(). 138 */ 139void 140timedb_clear(void) { 141 if (timedb != NULL) 142 dns_sdb_unregister(&timedb); 143} 144