summaryrefslogtreecommitdiffstats
path: root/contrib/sdb/time/timedb.c
blob: 11633caeb8a3673d1f2ad71eb19f659322c7e160 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * 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 <config.h>

#include <string.h>
#include <stdio.h>
#include <time.h>

#include <isc/print.h>
#include <isc/result.h>
#include <isc/util.h>

#include <dns/sdb.h>

#include <named/globals.h>

#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);
}