OpenDNSSEC-enforcer 2.1.13
keystate_ds.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 Stichting NLnet Labs
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28#include "config.h"
29
30#include <sys/stat.h>
31#include <getopt.h>
32
33#include "cmdhandler.h"
34#include "daemon/engine.h"
36#include "file.h"
37#include "log.h"
38#include "str.h"
39#include "clientpipe.h"
40#include "longgetopt.h"
41#include "duration.h"
42#include "db/key_data.h"
43#include "db/zone_db.h"
44#include "db/db_error.h"
45#include "db/hsm_key.h"
46#include "libhsm.h"
47#include "libhsmdns.h"
48
50
51static const char *module_str = "keystate_ds_x_cmd";
52
59static ldns_rr *
60get_dnskey(const char *id, const char *zone, int alg, uint32_t ttl)
61{
62 libhsm_key_t *key;
63 hsm_sign_params_t *sign_params;
64 ldns_rr *dnskey_rr;
65 /* Code to output the DNSKEY record (stolen from hsmutil) */
66 hsm_ctx_t *hsm_ctx = hsm_create_context();
67 if (!hsm_ctx) {
68 ods_log_error("[%s] Could not connect to HSM", module_str);
69 return NULL;
70 }
71 if (!(key = hsm_find_key_by_id(hsm_ctx, id))) {
72 hsm_destroy_context(hsm_ctx);
73 return NULL;
74 }
75
76 /* Sign params only need to be kept around
77 * for the hsm_get_dnskey() call. */
78 sign_params = hsm_sign_params_new();
79 sign_params->owner = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, zone);
80 sign_params->algorithm = (ldns_algorithm) alg;
81 sign_params->flags = LDNS_KEY_ZONE_KEY | LDNS_KEY_SEP_KEY;
82
83 /* Get the DNSKEY record */
84 dnskey_rr = hsm_get_dnskey(hsm_ctx, key, sign_params);
85
86 libhsm_key_free(key);
87 hsm_sign_params_free(sign_params);
88 hsm_destroy_context(hsm_ctx);
89
90 /* Override the TTL in the dnskey rr */
91 if (ttl) ldns_rr_set_ttl(dnskey_rr, ttl);
92
93 return dnskey_rr;
94}
95
97static int
98exec_dnskey_by_id(int sockfd, key_data_t *key, const char* ds_command,
99 const char* action)
100{
101 ldns_rr *dnskey_rr;
102 int ttl = 0, status, i;
103 const char *locator;
104 char *rrstr, *chrptr;
105 zone_db_t* zone;
106 struct stat stat_ret;
107 int cka = 0;
108 char *pos = NULL;
109
110 assert(key);
111
112 zone = key_data_get_zone(key);
113 if(key_data_cache_hsm_key(key) != DB_OK) {
114 ods_log_error_and_printf(sockfd, module_str,
115 "Error fetching from database");
116 zone_db_free(zone);
117 return 1;
118 }
119 locator = hsm_key_locator(key_data_hsm_key(key));
120 if (!locator) {
121 zone_db_free(zone);
122 return 1;
123 }
124 /* This fetches the states from the DB, I'm only assuming they get
125 * cleaned up when 'key' is cleaned(?) */
126 if (key_data_cache_key_states(key) != DB_OK) {
127 zone_db_free(zone);
128 return 1;
129 }
130
132
133 dnskey_rr = get_dnskey(locator, zone_db_name(zone), key_data_algorithm(key), ttl);
134 zone_db_free(zone);
135 if (!dnskey_rr) return 2;
136
137 rrstr = ldns_rr2str(dnskey_rr);
138
139 /* Replace tab with white-space */
140 for (i = 0; rrstr[i]; ++i) {
141 if (rrstr[i] == '\t') rrstr[i] = ' ';
142 }
143
144 /* We need to strip off trailing comments before we send
145 to any clients that might be listening */
146 if ((chrptr = strchr(rrstr, ';'))) {
147 chrptr[0] = '\n';
148 chrptr[1] = '\0';
149 }
150
151 if (!ds_command || ds_command[0] == '\0') {
152 ods_log_error_and_printf(sockfd, module_str,
153 "No \"DelegationSigner%sCommand\" "
154 "configured.", action);
155 status = 1;
156 } else {
157 pos = strstr(ds_command, " --cka_id");
158 if (pos){
159 cka = 1;
160 *pos = '\0';
161 rrstr[strlen(rrstr)-1] = '\0';
162 pos = NULL;
163 }
164
165 if (stat(ds_command, &stat_ret) != 0) {
166 ods_log_error_and_printf(sockfd, module_str,
167 "Cannot stat file %s: %s", ds_command,
168 strerror(errno));
169 status = 2;
170 } else if (S_ISREG(stat_ret.st_mode) &&
171 !(stat_ret.st_mode & S_IXUSR ||
172 stat_ret.st_mode & S_IXGRP ||
173 stat_ret.st_mode & S_IXOTH)) {
174 /* Then see if it is a regular file, then if usr, grp or
175 * all have execute set */
176 status = 3;
177 ods_log_error_and_printf(sockfd, module_str,
178 "File %s is not executable", ds_command);
179 } else {
180 /* send records to the configured command */
181 FILE *fp = popen(ds_command, "w");
182 if (fp == NULL) {
183 status = 4;
184 ods_log_error_and_printf(sockfd, module_str,
185 "failed to run command: %s: %s",ds_command,
186 strerror(errno));
187 } else {
188 int bytes_written;
189 if (cka)
190 bytes_written = fprintf(fp, "%s; {cka_id = %s}\n", rrstr, locator);
191 else
192 bytes_written = fprintf(fp, "%s", rrstr);
193 if (bytes_written < 0) {
194 status = 5;
195 ods_log_error_and_printf(sockfd, module_str,
196 "Failed to write to %s: %s", ds_command,
197 strerror(errno));
198 } else if (pclose(fp) == -1) {
199 status = 6;
200 ods_log_error_and_printf(sockfd, module_str,
201 "failed to close %s: %s", ds_command,
202 strerror(errno));
203 } else {
204 client_printf(sockfd, "key %sed to %s\n",
205 action, ds_command);
206 status = 0;
207 }
208 }
209 }
210 }
211 LDNS_FREE(rrstr);
212 ldns_rr_free(dnskey_rr);
213 return status;
214}
215
216static int
217submit_dnskey_by_id(int sockfd, key_data_t *key, engine_type* engine)
218{
219 const char* ds_submit_command;
220 ds_submit_command = engine->config->delegation_signer_submit_command;
221 return exec_dnskey_by_id(sockfd, key, ds_submit_command, "submit");
222}
223
224static int
225retract_dnskey_by_id(int sockfd, key_data_t *key, engine_type* engine)
226{
227 const char* ds_retract_command;
228 ds_retract_command = engine->config->delegation_signer_retract_command;
229 return exec_dnskey_by_id(sockfd, key, ds_retract_command, "retract");
230}
231
232static int
233ds_list_keys(db_connection_t *dbconn, int sockfd,
235{
236 const char *fmth = "%-31s %-13s %-13s %-40s\n";
237 const char *fmtl = "%-31s %-13s %-13u %-40s\n";
238
239 key_data_list_t *key_list;
240 const key_data_t *key;
241 zone_db_t *zone = NULL;
242 hsm_key_t* hsmkey = NULL;
243 db_clause_list_t* clause_list;
244 db_clause_t* clause;
245
246 if (!(key_list = key_data_list_new(dbconn))
247 || !(clause_list = db_clause_list_new()))
248 {
249 key_data_list_free(key_list);
250 return 10;
251 }
252 if (!(clause = key_data_role_clause(clause_list, KEY_DATA_ROLE_ZSK))
254 || !(clause = key_data_ds_at_parent_clause(clause_list, state))
256 {
257 key_data_list_free(key_list);
258 db_clause_list_free(clause_list);
259 return 11;
260 }
261 if (key_data_list_get_by_clauses(key_list, clause_list)) {
262 key_data_list_free(key_list);
263 db_clause_list_free(clause_list);
264 return 12;
265 }
266 db_clause_list_free(clause_list);
267
268 client_printf(sockfd, fmth, "Zone:", "Key role:", "Keytag:", "Id:");
269
270 for (key = key_data_list_next(key_list); key;
271 key = key_data_list_next(key_list))
272 {
273 zone = key_data_get_zone(key);
274 hsmkey = key_data_get_hsm_key(key);
275 client_printf(sockfd, fmtl,
276 (zone ? zone_db_name(zone) : "NOT_FOUND"),
278 (hsmkey ? hsm_key_locator(hsmkey) : "NOT_FOUND")
279 );
280 zone_db_free(zone);
281 hsm_key_free(hsmkey);
282 }
283 key_data_list_free(key_list);
284 return 0;
285}
286
287static int
288push_clauses(db_clause_list_t *clause_list, zone_db_t *zone,
289 key_data_ds_at_parent_t state_from, const hsm_key_t* hsmkey, int keytag)
290{
291 db_clause_t* clause;
292
293 if (!key_data_zone_id_clause(clause_list, zone_db_id(zone)))
294 return 1;
295 if (!(clause = key_data_role_clause(clause_list, KEY_DATA_ROLE_ZSK)) ||
297 return 1;
298 if (!key_data_ds_at_parent_clause(clause_list, state_from))
299 return 1;
300
301 /* filter in id and or keytag conditionally. */
302 if (hsmkey) {
303 if (hsmkey && !key_data_hsm_key_id_clause(clause_list, hsm_key_id(hsmkey)))
304 return 1;
305 }
306 if (keytag > 0) {
307 if (!key_data_keytag_clause(clause_list, keytag))
308 return 1;
309 }
310 return 0;
311}
312
314static int
315ds_changed(key_data_t *key)
316{
317 key_state_list_t* keystatelist;
318 key_state_t* keystate;
319
320 if(key_data_retrieve_key_state_list(key)) return 1;
321 keystatelist = key_data_key_state_list(key);
322 keystate = key_state_list_get_begin(keystatelist);
323 if (!keystate) return 1;
324
325 while (keystate) {
326 key_state_t* keystate_next;
327 if (keystate->type == KEY_STATE_TYPE_DS) {
328 keystate->last_change = time_now();
329 if(key_state_update(keystate)) {
330 key_state_free(keystate);
331 return 1;
332 }
333 key_state_free(keystate);
334 return 0;
335 }
336 keystate_next = key_state_list_get_next(keystatelist);
337 key_state_free(keystate);
338 keystate = keystate_next;
339 }
340 return 1;
341}
342
343/* Change DS state, when zonename not given do it for all zones!
344 */
345int
347 const char *zonename, const hsm_key_t* hsmkey, int keytag,
349 engine_type *engine)
350{
351 key_data_list_t *key_list = NULL;
352 key_data_t *key;
353 zone_db_t *zone = NULL;
354 int status = 0, key_match = 0, key_mod = 0;
355 db_clause_list_t* clause_list = NULL;
356 db_clause_t* clause = NULL;
357 char *tmp_zone_name;
358
359 if (zonename) {
360 if (!(key_list = key_data_list_new(dbconn)) ||
361 !(clause_list = db_clause_list_new()) ||
362 !(zone = zone_db_new_get_by_name(dbconn, zonename)) ||
363 push_clauses(clause_list, zone, state_from, hsmkey, keytag) ||
364 key_data_list_get_by_clauses(key_list, clause_list))
365 {
366 key_data_list_free(key_list);
367 db_clause_list_free(clause_list);
368 zone_db_free(zone);
369 client_printf_err(sockfd, "Could not find ksk for zone %s, "
370 "does zone exist?\n", zonename);
371 ods_log_error("[%s] Error fetching from database", module_str);
372 return 10;
373 }
374 db_clause_list_free(clause_list);
375 } else {
376 /* Select all KSKs */
377 if (!(clause_list = db_clause_list_new()) ||
378 !key_data_ds_at_parent_clause(clause_list, state_from) ||
379 !(clause = key_data_role_clause(clause_list, KEY_DATA_ROLE_ZSK)) ||
381 !(key_list = key_data_list_new_get_by_clauses(dbconn, clause_list)))
382 {
383 key_data_list_free(key_list);
384 db_clause_list_free(clause_list);
385 ods_log_error("[%s] Error fetching from database", module_str);
386 return 14;
387 }
388 db_clause_list_free(clause_list);
389 }
390 while ((key = key_data_list_get_next(key_list))) {
391 key_match++;
392 /* if from is submit also exec dsSubmit command? */
393 if (state_from == KEY_DATA_DS_AT_PARENT_SUBMIT &&
395 {
396 (void)submit_dnskey_by_id(sockfd, key, engine);
397 } else if (state_from == KEY_DATA_DS_AT_PARENT_RETRACT &&
399 {
400 (void)retract_dnskey_by_id(sockfd, key, engine);
401 }
402
403 if (key_data_set_ds_at_parent(key, state_to) ||
404 key_data_update(key) || ds_changed(key) )
405 {
406 key_data_free(key);
407 ods_log_error("[%s] Error writing to database", module_str);
408 client_printf(sockfd, "[%s] Error writing to database", module_str);
409 status = 12;
410 break;
411 }
412 key_mod++;
413 /* We need to schedule enforce for owner of key. */
414 tmp_zone_name = zone_db_ext_zonename_from_id(dbconn, &key->zone_id);
415 if (tmp_zone_name)
416 enforce_task_flush_zone(engine, tmp_zone_name);
417 free(tmp_zone_name);
418 key_data_free(key);
419 }
420 key_data_list_free(key_list);
421
422 client_printf(sockfd, "%d KSK matches found.\n", key_match);
423 if (!key_match) status = 11;
424 client_printf(sockfd, "%d KSKs changed.\n", key_mod);
425 if (zone && key_mod > 0) {
426 zone->next_change = 0; /* asap */
427 (void)zone_db_update(zone);
428 }
429 zone_db_free(zone);
430 return status;
431}
432
433int
434run_ds_cmd(cmdhandler_ctx_type* context, int argc, char* argv[],
435 db_connection_t *dbconn, key_data_ds_at_parent_t state_from,
436 key_data_ds_at_parent_t state_to, engine_type *engine)
437{
438 int sockfd = context->sockfd;
439 struct longgetopt optctx;
440 const char *zonename = NULL, *cka_id = NULL, *keytag_s = NULL;
441 int keytag = -1;
442 hsm_key_t* hsmkey = NULL;
443 int ret;
444 char buf[ODS_SE_MAXLINE];
445 zone_db_t* zone = NULL;
446 int all = 0;
447 int long_index = 0, opt = 0;
448
449 static struct option long_options[] = {
450 {"zone", required_argument, 0, 'z'},
451 {"cka_id", required_argument, 0, 'k'},
452 {"keytag", required_argument, 0, 'x'},
453 {"all", no_argument, 0, 'a'},
454 {0, 0, 0, 0}
455 };
456
457 for(opt = longgetopt(argc, argv, "z:k:x:a", long_options, &long_index, &optctx); opt != -1;
458 opt = longgetopt(argc, argv, NULL, long_options, &long_index, &optctx)) {
459 switch (opt) {
460 case 'z':
461 zonename = optctx.optarg;
462 break;
463 case 'k':
464 cka_id = optctx.optarg;
465 break;
466 case 'x':
467 keytag_s = optctx.optarg;
468 break;
469 case 'a':
470 all = 1;
471 break;
472 default:
473 client_printf_err(sockfd, "unknown arguments\n");
474 ods_log_error("[%s] unknown arguments for %s command",
475 module_str, argv[0]);
476 return -1;
477 }
478 }
479
480 if (!all && !zonename && !cka_id && !keytag_s) {
481 return ds_list_keys(dbconn, sockfd, state_from);
482 }
483
484 if (keytag_s) {
485 keytag = atoi(keytag_s);
486 if (keytag < 0 || keytag >= 65536) {
487 ods_log_warning("[%s] value \"%d\" for --keytag is invalid",
488 module_str, keytag);
489 client_printf_err(sockfd, "value \"%d\" for --keytag is invalid\n",
490 keytag);
491
492 return 1;
493 }
494 }
495
496 if (all && zonename) {
497 ods_log_warning ("[%s] Error: Unable to use --zone and --all together", module_str);
498 client_printf_err(sockfd, "Error: Unable to use --zone and --all together\n");
499 return -1;
500 }
501
502 if (zonename && (!(zone = zone_db_new(dbconn)) || zone_db_get_by_name(zone, zonename))) {
503 ods_log_warning ("[%s] Error: Unable to find a zone named \"%s\" in database\n", module_str, zonename);
504 client_printf_err(sockfd, "Error: Unable to find a zone named \"%s\" in database\n", zonename);
505 zone_db_free(zone);
506 zone = NULL;
507 return -1;
508 }
509 zone_db_free(zone);
510 zone = NULL;
511 if (!zonename && (keytag != -1 || cka_id)) {
512 ods_log_warning ("[%s] Error: expected --zone <zone>", module_str);
513 client_printf_err(sockfd, "Error: expected --zone <zone>\n");
514 return -1;
515 }
516
517 if (!(zonename && ((cka_id && keytag == -1) || (!cka_id && keytag != -1))) && !all)
518 {
519 ods_log_warning("[%s] expected --zone and either --cka_id or "
520 "--keytag option or expected --all", module_str);
521 client_printf_err(sockfd, "expected --zone and either --cka_id or "
522 "--keytag option or expected --all.\n");
523 return -1;
524 }
525
526 if (cka_id && !(hsmkey = hsm_key_new_get_by_locator(dbconn, cka_id))) {
527 client_printf_err(sockfd, "CKA_ID %s can not be found!\n", cka_id);
528 return -1;
529 }
530 ret = change_keys_from_to(dbconn, sockfd, zonename, hsmkey, keytag,
531 state_from, state_to, engine);
532 hsm_key_free(hsmkey);
533 return ret;
534}
db_clause_list_t * db_clause_list_new(void)
Definition db_clause.c:202
void db_clause_list_free(db_clause_list_t *clause_list)
Definition db_clause.c:209
int db_clause_set_type(db_clause_t *clause, db_clause_type_t type)
Definition db_clause.c:130
@ DB_CLAUSE_NOT_EQUAL
Definition db_clause.h:48
@ DB_CLAUSE_EQUAL
Definition db_clause.h:44
#define DB_OK
Definition db_error.h:36
void enforce_task_flush_zone(engine_type *engine, char const *zonename)
void hsm_key_free(hsm_key_t *hsm_key)
Definition hsm_key.c:286
const char * hsm_key_locator(const hsm_key_t *hsm_key)
Definition hsm_key.c:520
hsm_key_t * hsm_key_new_get_by_locator(const db_connection_t *connection, const char *locator)
Definition hsm_key.c:1205
const db_value_t * hsm_key_id(const hsm_key_t *hsm_key)
Definition hsm_key.c:504
zone_db_t * key_data_get_zone(const key_data_t *key_data)
Definition key_data.c:569
db_clause_t * key_data_keytag_clause(db_clause_list_t *clause_list, unsigned int keytag)
Definition key_data.c:1072
int key_data_update(key_data_t *key_data)
Definition key_data.c:1349
void key_data_free(key_data_t *key_data)
Definition key_data.c:304
const hsm_key_t * key_data_hsm_key(const key_data_t *key_data)
Definition key_data.c:638
db_clause_t * key_data_hsm_key_id_clause(db_clause_list_t *clause_list, const db_value_t *hsm_key_id)
Definition key_data.c:1003
hsm_key_t * key_data_get_hsm_key(const key_data_t *key_data)
Definition key_data.c:649
key_data_list_t * key_data_list_new_get_by_clauses(const db_connection_t *connection, const db_clause_list_t *clause_list)
Definition key_data.c:2161
int key_data_list_get_by_clauses(key_data_list_t *key_data_list, const db_clause_list_t *clause_list)
Definition key_data.c:2119
unsigned int key_data_keytag(const key_data_t *key_data)
Definition key_data.c:767
const char * key_data_role_text(const key_data_t *key_data)
Definition key_data.c:711
void key_data_list_free(key_data_list_t *key_data_list)
Definition key_data.c:1694
key_data_t * key_data_list_get_next(key_data_list_t *key_data_list)
Definition key_data.c:2425
int key_data_cache_hsm_key(key_data_t *key_data)
Definition key_data.c:615
db_clause_t * key_data_ds_at_parent_clause(db_clause_list_t *clause_list, key_data_ds_at_parent_t ds_at_parent)
Definition key_data.c:1051
key_data_list_t * key_data_list_new(const db_connection_t *connection)
Definition key_data.c:1651
db_clause_t * key_data_role_clause(db_clause_list_t *clause_list, key_data_role_t role)
Definition key_data.c:1030
int key_data_set_ds_at_parent(key_data_t *key_data, key_data_ds_at_parent_t ds_at_parent)
Definition key_data.c:943
int key_data_retrieve_key_state_list(key_data_t *key_data)
Definition key_data.c:801
key_state_list_t * key_data_key_state_list(key_data_t *key_data)
Definition key_data.c:783
const key_data_t * key_data_list_next(key_data_list_t *key_data_list)
Definition key_data.c:2359
unsigned int key_data_algorithm(const key_data_t *key_data)
Definition key_data.c:687
db_clause_t * key_data_zone_id_clause(db_clause_list_t *clause_list, const db_value_t *zone_id)
Definition key_data.c:976
@ KEY_DATA_ROLE_ZSK
Definition key_data.h:43
enum key_data_ds_at_parent key_data_ds_at_parent_t
@ KEY_DATA_DS_AT_PARENT_SUBMITTED
Definition key_data.h:54
@ KEY_DATA_DS_AT_PARENT_RETRACT
Definition key_data.h:56
@ KEY_DATA_DS_AT_PARENT_SUBMIT
Definition key_data.h:53
@ KEY_DATA_DS_AT_PARENT_RETRACTED
Definition key_data.h:57
int key_data_cache_key_states(key_data_t *key_data)
const key_state_t * key_data_cached_dnskey(key_data_t *key_data)
key_state_t * key_state_list_get_next(key_state_list_t *key_state_list)
Definition key_state.c:1398
key_state_t * key_state_list_get_begin(key_state_list_t *key_state_list)
Definition key_state.c:1296
unsigned int key_state_ttl(const key_state_t *key_state)
Definition key_state.c:409
void key_state_free(key_state_t *key_state)
Definition key_state.c:214
int key_state_update(key_state_t *key_state)
Definition key_state.c:684
@ KEY_STATE_TYPE_DS
Definition key_state.h:42
int run_ds_cmd(cmdhandler_ctx_type *context, int argc, char *argv[], db_connection_t *dbconn, key_data_ds_at_parent_t state_from, key_data_ds_at_parent_t state_to, engine_type *engine)
int change_keys_from_to(db_connection_t *dbconn, int sockfd, const char *zonename, const hsm_key_t *hsmkey, int keytag, key_data_ds_at_parent_t state_from, key_data_ds_at_parent_t state_to, engine_type *engine)
engineconfig_type * config
Definition engine.h:48
const char * delegation_signer_submit_command
Definition cfg.h:61
const char * delegation_signer_retract_command
Definition cfg.h:62
db_value_t zone_id
Definition key_data.h:72
key_state_type_t type
Definition key_state.h:72
unsigned int last_change
Definition key_state.h:74
int next_change
Definition zone_db.h:56
void zone_db_free(zone_db_t *zone)
Definition zone_db.c:325
const char * zone_db_name(const zone_db_t *zone)
Definition zone_db.c:782
int zone_db_update(zone_db_t *zone)
Definition zone_db.c:1589
zone_db_t * zone_db_new(const db_connection_t *connection)
Definition zone_db.c:287
const db_value_t * zone_db_id(const zone_db_t *zone)
Definition zone_db.c:728
int zone_db_get_by_name(zone_db_t *zone, const char *name)
Definition zone_db.c:1519
zone_db_t * zone_db_new_get_by_name(const db_connection_t *connection, const char *name)
Definition zone_db.c:1569
char * zone_db_ext_zonename_from_id(const db_connection_t *connection, const db_value_t *id)
Definition zone_db_ext.c:39