mirror of
https://github.com/isc-projects/bind9.git
synced 2026-03-30 22:35:38 -04:00
This commit was manufactured by cvs2git to create branch 'v9_3'.
This commit is contained in:
commit
79df9ecfdd
7 changed files with 7748 additions and 0 deletions
453
bin/named/config.c
Normal file
453
bin/named/config.c
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* Copyright (C) 2001, 2002 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: config.c,v 1.11.2.4 2002/03/20 20:32:41 marka Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/log.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/region.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <isccfg/cfg.h>
|
||||
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdataclass.h>
|
||||
#include <dns/tsig.h>
|
||||
#include <dns/zone.h>
|
||||
|
||||
#include <named/config.h>
|
||||
#include <named/globals.h>
|
||||
|
||||
static char defaultconf[] = "\
|
||||
options {\n\
|
||||
# blackhole {none;};\n\
|
||||
coresize default;\n\
|
||||
datasize default;\n\
|
||||
deallocate-on-exit true;\n\
|
||||
# directory <none>\n\
|
||||
dump-file \"named_dump.db\";\n\
|
||||
fake-iquery no;\n\
|
||||
files default;\n\
|
||||
has-old-clients false;\n\
|
||||
heartbeat-interval 60;\n\
|
||||
host-statistics no;\n\
|
||||
interface-interval 60;\n\
|
||||
listen-on {any;};\n\
|
||||
listen-on-v6 {none;};\n\
|
||||
match-mapped-addresses no;\n\
|
||||
memstatistics-file \"named.memstats\";\n\
|
||||
multiple-cnames no;\n\
|
||||
# named-xfer <obsolete>;\n\
|
||||
# pid-file \"" NS_LOCALSTATEDIR "/named.pid\"; /* or /lwresd.pid */\n\
|
||||
port 53;\n\
|
||||
"
|
||||
#ifdef PATH_RANDOMDEV
|
||||
"\
|
||||
random-device \"" PATH_RANDOMDEV "\";\n\
|
||||
"
|
||||
#endif
|
||||
"\
|
||||
recursive-clients 1000;\n\
|
||||
rrset-order {order cyclic;};\n\
|
||||
serial-queries 20;\n\
|
||||
serial-query-rate 20;\n\
|
||||
stacksize default;\n\
|
||||
statistics-file \"named.stats\";\n\
|
||||
statistics-interval 60;\n\
|
||||
tcp-clients 100;\n\
|
||||
# tkey-dhkey <none>\n\
|
||||
# tkey-gssapi-credential <none>\n\
|
||||
# tkey-domain <none>\n\
|
||||
transfers-per-ns 2;\n\
|
||||
transfers-in 10;\n\
|
||||
transfers-out 10;\n\
|
||||
treat-cr-as-space true;\n\
|
||||
use-id-pool true;\n\
|
||||
use-ixfr true;\n\
|
||||
version \""VERSION"\";\n\
|
||||
\n\
|
||||
/* view */\n\
|
||||
allow-notify {none;};\n\
|
||||
allow-update-forwarding {none;};\n\
|
||||
allow-recursion {any;};\n\
|
||||
allow-v6-synthesis {none;};\n\
|
||||
# sortlist <none>\n\
|
||||
# topology <none>\n\
|
||||
auth-nxdomain false;\n\
|
||||
minimal-responses false;\n\
|
||||
recursion true;\n\
|
||||
provide-ixfr true;\n\
|
||||
request-ixfr true;\n\
|
||||
fetch-glue no;\n\
|
||||
rfc2308-type1 no;\n\
|
||||
additional-from-auth true;\n\
|
||||
additional-from-cache true;\n\
|
||||
query-source address *;\n\
|
||||
query-source-v6 address *;\n\
|
||||
notify-source *;\n\
|
||||
notify-source-v6 *;\n\
|
||||
cleaning-interval 60;\n\
|
||||
min-roots 2;\n\
|
||||
lame-ttl 600;\n\
|
||||
max-ncache-ttl 10800; /* 3 hours */\n\
|
||||
max-cache-ttl 604800; /* 1 week */\n\
|
||||
transfer-format many-answers;\n\
|
||||
max-cache-size 0;\n\
|
||||
check-names master ignore;\n\
|
||||
check-names slave ignore;\n\
|
||||
check-names response ignore;\n\
|
||||
\n\
|
||||
/* zone */\n\
|
||||
allow-query {any;};\n\
|
||||
allow-transfer {any;};\n\
|
||||
notify yes;\n\
|
||||
# also-notify <none>\n\
|
||||
dialup no;\n\
|
||||
# forward <none>\n\
|
||||
# forwarders <none>\n\
|
||||
maintain-ixfr-base no;\n\
|
||||
# max-ixfr-log-size <obsolete>\n\
|
||||
transfer-source *;\n\
|
||||
transfer-source-v6 *;\n\
|
||||
max-transfer-time-in 120;\n\
|
||||
max-transfer-time-out 120;\n\
|
||||
max-transfer-idle-in 60;\n\
|
||||
max-transfer-idle-out 60;\n\
|
||||
max-retry-time 1209600; /* 2 weeks */\n\
|
||||
min-retry-time 500;\n\
|
||||
max-refresh-time 2419200; /* 4 weeks */\n\
|
||||
min-refresh-time 300;\n\
|
||||
sig-validity-interval 30; /* days */\n\
|
||||
zone-statistics false;\n\
|
||||
};";
|
||||
|
||||
isc_result_t
|
||||
ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
|
||||
isc_buffer_t b;
|
||||
|
||||
isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
|
||||
isc_buffer_add(&b, sizeof(defaultconf) - 1);
|
||||
return (cfg_parse_buffer(parser, &b, &cfg_type_namedconf, conf));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_get(cfg_obj_t **maps, const char* name, cfg_obj_t **obj) {
|
||||
int i;
|
||||
|
||||
for (i = 0; ; i++) {
|
||||
if (maps[i] == NULL)
|
||||
return (ISC_R_NOTFOUND);
|
||||
if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ns_config_listcount(cfg_obj_t *list) {
|
||||
cfg_listelt_t *e;
|
||||
int i = 0;
|
||||
|
||||
for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e))
|
||||
i++;
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_getclass(cfg_obj_t *classobj, dns_rdataclass_t defclass,
|
||||
dns_rdataclass_t *classp) {
|
||||
char *str;
|
||||
isc_textregion_t r;
|
||||
isc_result_t result;
|
||||
|
||||
if (!cfg_obj_isstring(classobj)) {
|
||||
*classp = defclass;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
str = cfg_obj_asstring(classobj);
|
||||
r.base = str;
|
||||
r.length = strlen(str);
|
||||
result = dns_rdataclass_fromtext(classp, &r);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"unknown class '%s'", str);
|
||||
return (result);
|
||||
}
|
||||
|
||||
dns_zonetype_t
|
||||
ns_config_getzonetype(cfg_obj_t *zonetypeobj) {
|
||||
dns_zonetype_t ztype = dns_zone_none;
|
||||
char *str;
|
||||
|
||||
str = cfg_obj_asstring(zonetypeobj);
|
||||
if (strcasecmp(str, "master") == 0)
|
||||
ztype = dns_zone_master;
|
||||
else if (strcasecmp(str, "slave") == 0)
|
||||
ztype = dns_zone_slave;
|
||||
else if (strcasecmp(str, "stub") == 0)
|
||||
ztype = dns_zone_stub;
|
||||
else
|
||||
INSIST(0);
|
||||
return (ztype);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_getiplist(cfg_obj_t *config, cfg_obj_t *list,
|
||||
in_port_t defport, isc_mem_t *mctx,
|
||||
isc_sockaddr_t **addrsp, isc_uint32_t *countp)
|
||||
{
|
||||
int count, i = 0;
|
||||
cfg_obj_t *addrlist;
|
||||
cfg_obj_t *portobj;
|
||||
cfg_listelt_t *element;
|
||||
isc_sockaddr_t *addrs;
|
||||
in_port_t port;
|
||||
isc_result_t result;
|
||||
|
||||
INSIST(addrsp != NULL && *addrsp == NULL);
|
||||
|
||||
addrlist = cfg_tuple_get(list, "addresses");
|
||||
count = ns_config_listcount(addrlist);
|
||||
|
||||
portobj = cfg_tuple_get(list, "port");
|
||||
if (cfg_obj_isuint32(portobj)) {
|
||||
isc_uint32_t val = cfg_obj_asuint32(portobj);
|
||||
if (val > ISC_UINT16_MAX) {
|
||||
cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"port '%u' out of range", val);
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
port = (in_port_t) val;
|
||||
} else if (defport != 0)
|
||||
port = defport;
|
||||
else {
|
||||
result = ns_config_getport(config, &port);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
|
||||
if (addrs == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
|
||||
for (element = cfg_list_first(addrlist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element), i++)
|
||||
{
|
||||
INSIST(i < count);
|
||||
addrs[i] = *cfg_obj_assockaddr(cfg_listelt_value(element));
|
||||
if (isc_sockaddr_getport(&addrs[i]) == 0)
|
||||
isc_sockaddr_setport(&addrs[i], port);
|
||||
}
|
||||
INSIST(i == count);
|
||||
|
||||
*addrsp = addrs;
|
||||
*countp = count;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
isc_uint32_t count)
|
||||
{
|
||||
INSIST(addrsp != NULL && *addrsp != NULL);
|
||||
|
||||
isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
|
||||
*addrsp = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
|
||||
isc_sockaddr_t **addrsp, dns_name_t ***keysp,
|
||||
isc_uint32_t *countp)
|
||||
{
|
||||
isc_uint32_t count, i = 0;
|
||||
isc_result_t result;
|
||||
cfg_listelt_t *element;
|
||||
cfg_obj_t *addrlist;
|
||||
cfg_obj_t *portobj;
|
||||
in_port_t port;
|
||||
dns_fixedname_t fname;
|
||||
isc_sockaddr_t *addrs = NULL;
|
||||
dns_name_t **keys = NULL;
|
||||
|
||||
INSIST(addrsp != NULL && *addrsp == NULL);
|
||||
|
||||
addrlist = cfg_tuple_get(list, "addresses");
|
||||
count = ns_config_listcount(addrlist);
|
||||
|
||||
portobj = cfg_tuple_get(list, "port");
|
||||
if (cfg_obj_isuint32(portobj)) {
|
||||
isc_uint32_t val = cfg_obj_asuint32(portobj);
|
||||
if (val > ISC_UINT16_MAX) {
|
||||
cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"port '%u' out of range", val);
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
port = (in_port_t) val;
|
||||
} else {
|
||||
result = ns_config_getport(config, &port);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
}
|
||||
|
||||
result = ISC_R_NOMEMORY;
|
||||
|
||||
addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
|
||||
if (addrs == NULL)
|
||||
goto cleanup;
|
||||
|
||||
keys = isc_mem_get(mctx, count * sizeof(dns_name_t *));
|
||||
if (keys == NULL)
|
||||
goto cleanup;
|
||||
|
||||
for (element = cfg_list_first(addrlist);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element), i++)
|
||||
{
|
||||
cfg_obj_t *addr;
|
||||
cfg_obj_t *key;
|
||||
char *keystr;
|
||||
isc_buffer_t b;
|
||||
|
||||
INSIST(i < count);
|
||||
|
||||
addr = cfg_tuple_get(cfg_listelt_value(element), "sockaddr");
|
||||
key = cfg_tuple_get(cfg_listelt_value(element), "key");
|
||||
|
||||
addrs[i] = *cfg_obj_assockaddr(addr);
|
||||
if (isc_sockaddr_getport(&addrs[i]) == 0)
|
||||
isc_sockaddr_setport(&addrs[i], port);
|
||||
|
||||
keys[i] = NULL;
|
||||
if (!cfg_obj_isstring(key))
|
||||
continue;
|
||||
keys[i] = isc_mem_get(mctx, sizeof(dns_name_t));
|
||||
if (keys[i] == NULL)
|
||||
goto cleanup;
|
||||
dns_name_init(keys[i], NULL);
|
||||
|
||||
keystr = cfg_obj_asstring(key);
|
||||
isc_buffer_init(&b, keystr, strlen(keystr));
|
||||
isc_buffer_add(&b, strlen(keystr));
|
||||
dns_fixedname_init(&fname);
|
||||
result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
|
||||
dns_rootname, ISC_FALSE, NULL);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
result = dns_name_dup(dns_fixedname_name(&fname), mctx,
|
||||
keys[i]);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
}
|
||||
INSIST(i == count);
|
||||
|
||||
*addrsp = addrs;
|
||||
*keysp = keys;
|
||||
*countp = count;
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
if (addrs != NULL)
|
||||
isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
|
||||
if (keys != NULL) {
|
||||
unsigned int j;
|
||||
for (j = 0 ; j <= i; j++) {
|
||||
if (keys[j] == NULL)
|
||||
continue;
|
||||
if (dns_name_dynamic(keys[j]))
|
||||
dns_name_free(keys[j], mctx);
|
||||
isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
|
||||
}
|
||||
isc_mem_put(mctx, keys, count * sizeof(dns_name_t *));
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
|
||||
dns_name_t ***keysp, isc_uint32_t count)
|
||||
{
|
||||
unsigned int i;
|
||||
dns_name_t **keys = *keysp;
|
||||
|
||||
INSIST(addrsp != NULL && *addrsp != NULL);
|
||||
|
||||
isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
|
||||
for (i = 0; i < count; i++) {
|
||||
if (keys[i] == NULL)
|
||||
continue;
|
||||
if (dns_name_dynamic(keys[i]))
|
||||
dns_name_free(keys[i], mctx);
|
||||
isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
|
||||
}
|
||||
isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
|
||||
*addrsp = NULL;
|
||||
*keysp = NULL;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_getport(cfg_obj_t *config, in_port_t *portp) {
|
||||
cfg_obj_t *maps[3];
|
||||
cfg_obj_t *options = NULL;
|
||||
cfg_obj_t *portobj = NULL;
|
||||
isc_result_t result;
|
||||
int i;
|
||||
|
||||
cfg_map_get(config, "options", &options);
|
||||
i = 0;
|
||||
if (options != NULL)
|
||||
maps[i++] = options;
|
||||
maps[i++] = ns_g_defaults;
|
||||
maps[i] = NULL;
|
||||
|
||||
result = ns_config_get(maps, "port", &portobj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
|
||||
cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"port '%u' out of range",
|
||||
cfg_obj_asuint32(portobj));
|
||||
return (ISC_R_RANGE);
|
||||
}
|
||||
*portp = (in_port_t)cfg_obj_asuint32(portobj);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_config_getkeyalgorithm(const char *str, dns_name_t **name)
|
||||
{
|
||||
if (strcasecmp(str, "hmac-md5") == 0 ||
|
||||
strcasecmp(str, "hmac-md5.sig-alg.reg.int") == 0 ||
|
||||
strcasecmp(str, "hmac-md5.sig-alg.reg.int.") == 0)
|
||||
{
|
||||
if (name != NULL)
|
||||
*name = dns_tsig_hmacmd5_name;
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
608
bin/named/zoneconf.c
Normal file
608
bin/named/zoneconf.c
Normal file
|
|
@ -0,0 +1,608 @@
|
|||
/*
|
||||
* Copyright (C) 1999-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zoneconf.c,v 1.87.2.4 2001/11/13 01:15:33 gson Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/acl.h>
|
||||
#include <dns/fixedname.h>
|
||||
#include <dns/log.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdatatype.h>
|
||||
#include <dns/ssu.h>
|
||||
#include <dns/zone.h>
|
||||
|
||||
#include <named/config.h>
|
||||
#include <named/globals.h>
|
||||
#include <named/log.h>
|
||||
#include <named/zoneconf.h>
|
||||
|
||||
/*
|
||||
* These are BIND9 server defaults, not necessarily identical to the
|
||||
* library defaults defined in zone.c.
|
||||
*/
|
||||
#define RETERR(x) do { \
|
||||
isc_result_t _r = (x); \
|
||||
if (_r != ISC_R_SUCCESS) \
|
||||
return (_r); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Convenience function for configuring a single zone ACL.
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_zone_acl(cfg_obj_t *zconfig, cfg_obj_t *vconfig, cfg_obj_t *config,
|
||||
const char *aclname, ns_aclconfctx_t *actx,
|
||||
dns_zone_t *zone,
|
||||
void (*setzacl)(dns_zone_t *, dns_acl_t *),
|
||||
void (*clearzacl)(dns_zone_t *))
|
||||
{
|
||||
isc_result_t result;
|
||||
cfg_obj_t *maps[4];
|
||||
cfg_obj_t *aclobj = NULL;
|
||||
int i = 0;
|
||||
dns_acl_t *dacl = NULL;
|
||||
|
||||
if (zconfig != NULL)
|
||||
maps[i++] = cfg_tuple_get(zconfig, "options");
|
||||
if (vconfig != NULL)
|
||||
maps[i++] = cfg_tuple_get(vconfig, "options");
|
||||
if (config != NULL) {
|
||||
cfg_obj_t *options = NULL;
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL)
|
||||
maps[i++] = options;
|
||||
}
|
||||
maps[i] = NULL;
|
||||
|
||||
result = ns_config_get(maps, aclname, &aclobj);
|
||||
if (aclobj == NULL) {
|
||||
(*clearzacl)(zone);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
result = ns_acl_fromconfig(aclobj, config, actx,
|
||||
dns_zone_getmctx(zone), &dacl);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
(*setzacl)(zone, dacl);
|
||||
dns_acl_detach(&dacl);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the zone update-policy statement.
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_zone_ssutable(cfg_obj_t *zconfig, dns_zone_t *zone) {
|
||||
cfg_obj_t *updatepolicy = NULL;
|
||||
cfg_listelt_t *element, *element2;
|
||||
dns_ssutable_t *table = NULL;
|
||||
isc_mem_t *mctx = dns_zone_getmctx(zone);
|
||||
isc_result_t result;
|
||||
|
||||
(void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
|
||||
if (updatepolicy == NULL)
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
result = dns_ssutable_create(mctx, &table);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
for (element = cfg_list_first(updatepolicy);
|
||||
element != NULL;
|
||||
element = cfg_list_next(element))
|
||||
{
|
||||
cfg_obj_t *stmt = cfg_listelt_value(element);
|
||||
cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
|
||||
cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
|
||||
cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
|
||||
cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
|
||||
cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
|
||||
char *str;
|
||||
isc_boolean_t grant = ISC_FALSE;
|
||||
unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
|
||||
dns_fixedname_t fname, fident;
|
||||
isc_buffer_t b;
|
||||
dns_rdatatype_t *types;
|
||||
unsigned int i, n;
|
||||
|
||||
str = cfg_obj_asstring(mode);
|
||||
if (strcasecmp(str, "grant") == 0)
|
||||
grant = ISC_TRUE;
|
||||
else if (strcasecmp(str, "deny") == 0)
|
||||
grant = ISC_FALSE;
|
||||
else
|
||||
INSIST(0);
|
||||
|
||||
str = cfg_obj_asstring(matchtype);
|
||||
if (strcasecmp(str, "name") == 0)
|
||||
mtype = DNS_SSUMATCHTYPE_NAME;
|
||||
else if (strcasecmp(str, "subdomain") == 0)
|
||||
mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
|
||||
else if (strcasecmp(str, "wildcard") == 0)
|
||||
mtype = DNS_SSUMATCHTYPE_WILDCARD;
|
||||
else if (strcasecmp(str, "self") == 0)
|
||||
mtype = DNS_SSUMATCHTYPE_SELF;
|
||||
else
|
||||
INSIST(0);
|
||||
|
||||
dns_fixedname_init(&fident);
|
||||
str = cfg_obj_asstring(identity);
|
||||
isc_buffer_init(&b, str, strlen(str));
|
||||
isc_buffer_add(&b, strlen(str));
|
||||
result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
|
||||
dns_rootname, ISC_FALSE, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"'%s' is not a valid name", str);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dns_fixedname_init(&fname);
|
||||
str = cfg_obj_asstring(dname);
|
||||
isc_buffer_init(&b, str, strlen(str));
|
||||
isc_buffer_add(&b, strlen(str));
|
||||
result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
|
||||
dns_rootname, ISC_FALSE, NULL);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"'%s' is not a valid name", str);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
n = ns_config_listcount(typelist);
|
||||
if (n == 0)
|
||||
types = NULL;
|
||||
else {
|
||||
types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
|
||||
if (types == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (element2 = cfg_list_first(typelist);
|
||||
element2 != NULL;
|
||||
element2 = cfg_list_next(element2))
|
||||
{
|
||||
cfg_obj_t *typeobj;
|
||||
isc_textregion_t r;
|
||||
|
||||
INSIST(i < n);
|
||||
|
||||
typeobj = cfg_listelt_value(element2);
|
||||
str = cfg_obj_asstring(typeobj);
|
||||
r.base = str;
|
||||
r.length = strlen(str);
|
||||
|
||||
result = dns_rdatatype_fromtext(&types[i++], &r);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
|
||||
"'%s' is not a valid type", str);
|
||||
isc_mem_put(mctx, types,
|
||||
n * sizeof(dns_rdatatype_t));
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
INSIST(i == n);
|
||||
|
||||
result = dns_ssutable_addrule(table, grant,
|
||||
dns_fixedname_name(&fident),
|
||||
mtype,
|
||||
dns_fixedname_name(&fname),
|
||||
n, types);
|
||||
if (types != NULL)
|
||||
isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result = ISC_R_SUCCESS;
|
||||
dns_zone_setssutable(zone, table);
|
||||
|
||||
cleanup:
|
||||
dns_ssutable_detach(&table);
|
||||
return (result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a config file zone type into a server zone type.
|
||||
*/
|
||||
static inline dns_zonetype_t
|
||||
zonetype_fromconfig(cfg_obj_t *map) {
|
||||
cfg_obj_t *obj = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
result = cfg_map_get(map, "type", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
return (ns_config_getzonetype(obj));
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for strtoargv(). Pardon the gratuitous recursion.
|
||||
*/
|
||||
static isc_result_t
|
||||
strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
|
||||
char ***argvp, unsigned int n)
|
||||
{
|
||||
isc_result_t result;
|
||||
|
||||
/* Discard leading whitespace. */
|
||||
while (*s == ' ' || *s == '\t')
|
||||
s++;
|
||||
|
||||
if (*s == '\0') {
|
||||
/* We have reached the end of the string. */
|
||||
*argcp = n;
|
||||
*argvp = isc_mem_get(mctx, n * sizeof(char *));
|
||||
if (*argvp == NULL)
|
||||
return (ISC_R_NOMEMORY);
|
||||
} else {
|
||||
char *p = s;
|
||||
while (*p != ' ' && *p != '\t' && *p != '\0')
|
||||
p++;
|
||||
if (*p != '\0')
|
||||
*p++ = '\0';
|
||||
|
||||
result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
(*argvp)[n] = s;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenize the string "s" into whitespace-separated words,
|
||||
* return the number of words in '*argcp' and an array
|
||||
* of pointers to the words in '*argvp'. The caller
|
||||
* must free the array using isc_mem_put(). The string
|
||||
* is modified in-place.
|
||||
*/
|
||||
static isc_result_t
|
||||
strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
|
||||
return (strtoargvsub(mctx, s, argcp, argvp, 0));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
ns_zone_configure(cfg_obj_t *config, cfg_obj_t *vconfig, cfg_obj_t *zconfig,
|
||||
ns_aclconfctx_t *ac, dns_zone_t *zone)
|
||||
{
|
||||
isc_result_t result;
|
||||
char *zname;
|
||||
dns_rdataclass_t zclass;
|
||||
dns_rdataclass_t vclass;
|
||||
cfg_obj_t *maps[5];
|
||||
cfg_obj_t *zoptions = NULL;
|
||||
cfg_obj_t *options = NULL;
|
||||
cfg_obj_t *obj;
|
||||
const char *filename = NULL;
|
||||
dns_notifytype_t notifytype = dns_notifytype_yes;
|
||||
isc_sockaddr_t *addrs;
|
||||
dns_name_t **keynames;
|
||||
isc_uint32_t count;
|
||||
char *cpval;
|
||||
unsigned int dbargc;
|
||||
char **dbargv;
|
||||
static char default_dbtype[] = "rbt";
|
||||
isc_mem_t *mctx = dns_zone_getmctx(zone);
|
||||
dns_dialuptype_t dialup = dns_dialuptype_no;
|
||||
dns_zonetype_t ztype;
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
if (zconfig != NULL) {
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
maps[i++] = zoptions;
|
||||
}
|
||||
if (vconfig != NULL)
|
||||
maps[i++] = cfg_tuple_get(vconfig, "options");
|
||||
if (config != NULL) {
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL)
|
||||
maps[i++] = options;
|
||||
}
|
||||
maps[i++] = ns_g_defaults;
|
||||
maps[i++] = NULL;
|
||||
|
||||
if (vconfig != NULL)
|
||||
RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
|
||||
dns_rdataclass_in, &vclass));
|
||||
else
|
||||
vclass = dns_rdataclass_in;
|
||||
|
||||
/*
|
||||
* Configure values common to all zone types.
|
||||
*/
|
||||
|
||||
zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
|
||||
|
||||
RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
|
||||
vclass, &zclass));
|
||||
dns_zone_setclass(zone, zclass);
|
||||
|
||||
ztype = zonetype_fromconfig(zoptions);
|
||||
dns_zone_settype(zone, ztype);
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "database", &obj);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
cpval = cfg_obj_asstring(obj);
|
||||
else
|
||||
cpval = default_dbtype;
|
||||
RETERR(strtoargv(mctx, cpval, &dbargc, &dbargv));
|
||||
/*
|
||||
* ANSI C is strange here. There is no logical reason why (char **)
|
||||
* cannot be promoted automatically to (const char * const *) by the
|
||||
* compiler w/o generating a warning.
|
||||
*/
|
||||
RETERR(dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv));
|
||||
isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "file", &obj);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
filename = cfg_obj_asstring(obj);
|
||||
RETERR(dns_zone_setfile(zone, filename));
|
||||
|
||||
if (ztype == dns_zone_slave)
|
||||
RETERR(configure_zone_acl(zconfig, vconfig, config,
|
||||
"allow-notify", ac, zone,
|
||||
dns_zone_setnotifyacl,
|
||||
dns_zone_clearnotifyacl));
|
||||
/*
|
||||
* XXXAG This probably does not make sense for stubs.
|
||||
*/
|
||||
RETERR(configure_zone_acl(zconfig, vconfig, config,
|
||||
"allow-query", ac, zone,
|
||||
dns_zone_setqueryacl,
|
||||
dns_zone_clearqueryacl));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "dialup", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
if (cfg_obj_isboolean(obj)) {
|
||||
if (cfg_obj_asboolean(obj))
|
||||
dialup = dns_dialuptype_yes;
|
||||
else
|
||||
dialup = dns_dialuptype_no;
|
||||
} else {
|
||||
char *dialupstr = cfg_obj_asstring(obj);
|
||||
if (strcasecmp(dialupstr, "notify") == 0)
|
||||
dialup = dns_dialuptype_notify;
|
||||
else if (strcasecmp(dialupstr, "notify-passive") == 0)
|
||||
dialup = dns_dialuptype_notifypassive;
|
||||
else if (strcasecmp(dialupstr, "refresh") == 0)
|
||||
dialup = dns_dialuptype_refresh;
|
||||
else if (strcasecmp(dialupstr, "passive") == 0)
|
||||
dialup = dns_dialuptype_passive;
|
||||
else
|
||||
INSIST(0);
|
||||
}
|
||||
dns_zone_setdialup(zone, dialup);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "zone-statistics", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setstatistics(zone, cfg_obj_asboolean(obj));
|
||||
|
||||
/*
|
||||
* Configure master functionality. This applies
|
||||
* to primary masters (type "master") and slaves
|
||||
* acting as masters (type "slave"), but not to stubs.
|
||||
*/
|
||||
if (ztype != dns_zone_stub) {
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "notify", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
if (cfg_obj_isboolean(obj)) {
|
||||
if (cfg_obj_asboolean(obj))
|
||||
notifytype = dns_notifytype_yes;
|
||||
else
|
||||
notifytype = dns_notifytype_no;
|
||||
} else {
|
||||
char *notifystr = cfg_obj_asstring(obj);
|
||||
if (strcasecmp(notifystr, "explicit") == 0)
|
||||
notifytype = dns_notifytype_explicit;
|
||||
else
|
||||
INSIST(0);
|
||||
}
|
||||
dns_zone_setnotifytype(zone, notifytype);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "also-notify", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
isc_sockaddr_t *addrs = NULL;
|
||||
isc_uint32_t addrcount;
|
||||
result = ns_config_getiplist(config, obj, 0, mctx,
|
||||
&addrs, &addrcount);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
result = dns_zone_setalsonotify(zone, addrs,
|
||||
addrcount);
|
||||
ns_config_putiplist(mctx, &addrs, addrcount);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
} else
|
||||
RETERR(dns_zone_setalsonotify(zone, NULL, 0));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "notify-source", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "notify-source-v6", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj));
|
||||
|
||||
RETERR(configure_zone_acl(zconfig, vconfig, config,
|
||||
"allow-transfer", ac, zone,
|
||||
dns_zone_setxfracl,
|
||||
dns_zone_clearxfracl));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "max-transfer-time-out", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "max-transfer-idle-out", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure update-related options. These apply to
|
||||
* primary masters only.
|
||||
*/
|
||||
if (ztype == dns_zone_master) {
|
||||
dns_acl_t *updateacl;
|
||||
RETERR(configure_zone_acl(zconfig, vconfig, config,
|
||||
"allow-update", ac, zone,
|
||||
dns_zone_setupdateacl,
|
||||
dns_zone_clearupdateacl));
|
||||
|
||||
updateacl = dns_zone_getupdateacl(zone);
|
||||
if (updateacl != NULL && dns_acl_isinsecure(updateacl))
|
||||
isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
|
||||
NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
|
||||
"zone '%s' allows updates by IP "
|
||||
"address, which is insecure",
|
||||
zname);
|
||||
|
||||
RETERR(configure_zone_ssutable(zoptions, zone));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "sig-validity-interval", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setsigvalidityinterval(zone,
|
||||
cfg_obj_asuint32(obj) * 86400);
|
||||
} else if (ztype == dns_zone_slave) {
|
||||
RETERR(configure_zone_acl(zconfig, vconfig, config,
|
||||
"allow-update-forwarding", ac, zone,
|
||||
dns_zone_setforwardacl,
|
||||
dns_zone_clearforwardacl));
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure slave functionality.
|
||||
*/
|
||||
switch (ztype) {
|
||||
case dns_zone_slave:
|
||||
case dns_zone_stub:
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "masters", &obj);
|
||||
if (obj != NULL) {
|
||||
addrs = NULL;
|
||||
keynames = NULL;
|
||||
RETERR(ns_config_getipandkeylist(config, obj, mctx,
|
||||
&addrs, &keynames,
|
||||
&count));
|
||||
result = dns_zone_setmasterswithkeys(zone, addrs,
|
||||
keynames, count);
|
||||
ns_config_putipandkeylist(mctx, &addrs, &keynames,
|
||||
count);
|
||||
} else
|
||||
result = dns_zone_setmasters(zone, NULL, 0);
|
||||
RETERR(result);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "max-transfer-time-in", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "max-transfer-idle-in", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60);
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "max-refresh-time", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "min-refresh-time", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "max-retry-time", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "min-retry-time", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "transfer-source", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = ns_config_get(maps, "transfer-source-v6", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
ns_zone_reusable(dns_zone_t *zone, cfg_obj_t *zconfig) {
|
||||
cfg_obj_t *zoptions = NULL;
|
||||
cfg_obj_t *obj = NULL;
|
||||
const char *cfilename;
|
||||
const char *zfilename;
|
||||
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
|
||||
if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone))
|
||||
return (ISC_FALSE);
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "file", &obj);
|
||||
if (obj != NULL)
|
||||
cfilename = cfg_obj_asstring(obj);
|
||||
else
|
||||
cfilename = NULL;
|
||||
zfilename = dns_zone_getfile(zone);
|
||||
if (!((cfilename == NULL && zfilename == NULL) ||
|
||||
(cfilename != NULL && zfilename != NULL &&
|
||||
strcmp(cfilename, zfilename) == 0)))
|
||||
return (ISC_FALSE);
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
263
lib/dns/include/dns/journal.h
Normal file
263
lib/dns/include/dns/journal.h
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (C) 1999-2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: journal.h,v 1.23 2001/05/21 23:56:33 gson Exp $ */
|
||||
|
||||
#ifndef DNS_JOURNAL_H
|
||||
#define DNS_JOURNAL_H 1
|
||||
|
||||
/*****
|
||||
***** Module Info
|
||||
*****/
|
||||
|
||||
/*
|
||||
* Database journalling.
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Imports
|
||||
***/
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/magic.h>
|
||||
|
||||
#include <dns/name.h>
|
||||
#include <dns/diff.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
/***
|
||||
*** Types
|
||||
***/
|
||||
|
||||
/*
|
||||
* A dns_journal_t represents an open journal file. This is an opaque type.
|
||||
*
|
||||
* A particular dns_journal_t object may be opened for writing, in which case
|
||||
* it can be used for writing transactions to a journal file, or it can be
|
||||
* opened for reading, in which case it can be used for reading transactions
|
||||
* from (iterating over) a journal file. A single dns_journal_t object may
|
||||
* not be used for both purposes.
|
||||
*/
|
||||
typedef struct dns_journal dns_journal_t;
|
||||
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
isc_result_t
|
||||
dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
|
||||
dns_diffop_t op, dns_difftuple_t **tp);
|
||||
/*
|
||||
* Create a diff tuple for the current database SOA.
|
||||
* XXX this probably belongs somewhere else.
|
||||
*/
|
||||
|
||||
|
||||
#define DNS_SERIAL_GT(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) > 0)
|
||||
#define DNS_SERIAL_GE(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) >= 0)
|
||||
/*
|
||||
* Compare SOA serial numbers. DNS_SERIAL_GT(a, b) returns true iff
|
||||
* a is "greater than" b where "greater than" is as defined in RFC1982.
|
||||
* DNS_SERIAL_GE(a, b) returns true iff a is "greater than or equal to" b.
|
||||
*/
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
* Journal object creation and destruction.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
|
||||
dns_journal_t **journalp);
|
||||
/*
|
||||
* Open the journal file 'filename' and create a dns_journal_t object for it.
|
||||
*
|
||||
* If 'write' is ISC_TRUE, the journal is open for writing. If it does
|
||||
* not exist, it is created.
|
||||
*
|
||||
* If 'write' is ISC_FALSE, the journal is open for reading. If it does
|
||||
* not exist, ISC_R_NOTFOUND is returned.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_journal_destroy(dns_journal_t **journalp);
|
||||
/*
|
||||
* Destroy a dns_journal_t, closing any open files and freeing its memory.
|
||||
*/
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
* Writing transactions to journals.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_begin_transaction(dns_journal_t *j);
|
||||
/*
|
||||
* Prepare to write a new transaction to the open journal file 'j'.
|
||||
*
|
||||
* Requires:
|
||||
* 'j' is open for writing.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_writediff(dns_journal_t *j, dns_diff_t *diff);
|
||||
/*
|
||||
* Write 'diff' to the current transaction of journal file 'j'.
|
||||
*
|
||||
* Requires:
|
||||
* 'j' is open for writing and dns_journal_begin_transaction()
|
||||
* has been called.
|
||||
*
|
||||
* 'diff' is a full or partial, correctly ordered IXFR
|
||||
* difference sequence.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_commit(dns_journal_t *j);
|
||||
/*
|
||||
* Commit the current transaction of journal file 'j'.
|
||||
*
|
||||
* Requires:
|
||||
* 'j' is open for writing and dns_journal_begin_transaction()
|
||||
* has been called.
|
||||
*
|
||||
* dns_journal_writediff() has been called one or more times
|
||||
* to form a complete, correctly ordered IXFR difference
|
||||
* sequence.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_write_transaction(dns_journal_t *j, dns_diff_t *diff);
|
||||
/*
|
||||
* Write a complete transaction at once to a journal file,
|
||||
* sorting it if necessary, and commit it. Equivalent to calling
|
||||
* dns_diff_sort(), dns_journal_begin_transaction(),
|
||||
* dns_journal_writediff(), and dns_journal_commit().
|
||||
*
|
||||
* Requires:
|
||||
* 'j' is open for writing.
|
||||
*
|
||||
* 'diff' contains exactly one SOA deletion, one SOA addition
|
||||
* with a greater serial number, and possibly other changes,
|
||||
* in arbitrary order.
|
||||
*/
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
* Reading transactions from journals.
|
||||
*/
|
||||
|
||||
isc_uint32_t
|
||||
dns_journal_first_serial(dns_journal_t *j);
|
||||
isc_uint32_t
|
||||
dns_journal_last_serial(dns_journal_t *j);
|
||||
/*
|
||||
* Get the first and last addressable serial number in the journal.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_iter_init(dns_journal_t *j,
|
||||
isc_uint32_t begin_serial, isc_uint32_t end_serial);
|
||||
/*
|
||||
* Prepare to iterate over the transactions that will bring the database
|
||||
* from SOA serial number 'begin_serial' to 'end_serial'.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS
|
||||
* ISC_R_RANGE begin_serial is outside the addressable range.
|
||||
* ISC_R_NOTFOUND begin_serial is within the range of adressable
|
||||
* serial numbers covered by the journal, but
|
||||
* this particular serial number does not exist.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_first_rr(dns_journal_t *j);
|
||||
isc_result_t
|
||||
dns_journal_next_rr(dns_journal_t *j);
|
||||
/*
|
||||
* Position the iterator at the first/next RR in a journal
|
||||
* transaction sequence established using dns_journal_iter_init().
|
||||
*
|
||||
* Requires:
|
||||
* dns_journal_iter_init() has been called.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl,
|
||||
dns_rdata_t **rdata);
|
||||
/*
|
||||
* Get the name, ttl, and rdata of the current journal RR.
|
||||
*
|
||||
* Requires:
|
||||
* The last call to dns_journal_first_rr() or dns_journal_next_rr()
|
||||
* returned ISC_R_SUCCESS.
|
||||
*/
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
* Database roll-forward.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, const char *filename);
|
||||
/*
|
||||
* Roll forward (play back) the journal file "filename" into the
|
||||
* database "db". This should be called when the server starts
|
||||
* after a shutdown or crash.
|
||||
*
|
||||
* Requires:
|
||||
* 'mctx' is a valid memory context.
|
||||
* 'db' is a valid database which does not have a version
|
||||
* open for writing.
|
||||
* 'filename' is the name of the journal file belonging to 'db'.
|
||||
*
|
||||
* Returns:
|
||||
* DNS_R_NOJOURNAL when journal does not exist.
|
||||
* ISC_R_NOTFOUND when current serial in not in journal.
|
||||
* ISC_R_RANGE when current serial in not in journals range.
|
||||
* ISC_R_SUCCESS journal has been applied successfully to database.
|
||||
* others
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file);
|
||||
/* For debugging not general use */
|
||||
|
||||
isc_result_t
|
||||
dns_db_diff(isc_mem_t *mctx,
|
||||
dns_db_t *dba, dns_dbversion_t *dbvera,
|
||||
dns_db_t *dbb, dns_dbversion_t *dbverb,
|
||||
const char *journal_filename);
|
||||
/*
|
||||
* Compare the databases 'dba' and 'dbb' and generate a journal
|
||||
* entry containing the changes to make 'dba' from 'dbb' (note
|
||||
* the order). This journal entry will consist of a single,
|
||||
* possibly very large transaction. Append the journal
|
||||
* entry to the journal file specified by 'journal_filename'.
|
||||
*/
|
||||
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_JOURNAL_H */
|
||||
1908
lib/dns/journal.c
Normal file
1908
lib/dns/journal.c
Normal file
File diff suppressed because it is too large
Load diff
246
lib/isc/include/isc/file.h
Normal file
246
lib/isc/include/isc/file.h
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: file.h,v 1.24 2001/07/16 18:33:00 gson Exp $ */
|
||||
|
||||
#ifndef ISC_FILE_H
|
||||
#define ISC_FILE_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/types.h>
|
||||
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
isc_result_t
|
||||
isc_file_settime(const char *file, isc_time_t *time);
|
||||
|
||||
isc_result_t
|
||||
isc_file_getmodtime(const char *file, isc_time_t *time);
|
||||
/*
|
||||
* Get the time of last modication of a file.
|
||||
*
|
||||
* Notes:
|
||||
* The time that is set is relative to the (OS-specific) epoch, as are
|
||||
* all isc_time_t structures.
|
||||
*
|
||||
* Requires:
|
||||
* file != NULL.
|
||||
* time != NULL.
|
||||
*
|
||||
* Ensures:
|
||||
* If the file could not be accessed, 'time' is unchanged.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS
|
||||
* Success.
|
||||
* ISC_R_NOTFOUND
|
||||
* No such file exists.
|
||||
* ISC_R_INVALIDFILE
|
||||
* The path specified was not usable by the operating system.
|
||||
* ISC_R_NOPERM
|
||||
* The file's metainformation could not be retrieved because
|
||||
* permission was denied to some part of the file's path.
|
||||
* ISC_R_EIO
|
||||
* Hardware error interacting with the filesystem.
|
||||
* ISC_R_UNEXPECTED
|
||||
* Something totally unexpected happened.
|
||||
*
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_mktemplate(const char *path, char *buf, size_t buflen);
|
||||
/*
|
||||
* Generate a template string suitable for use with isc_file_openunique.
|
||||
*
|
||||
* Notes:
|
||||
* This function is intended to make creating temporary files
|
||||
* portable between different operating systems.
|
||||
*
|
||||
* The path is prepended to an implementation-defined string and
|
||||
* placed into buf. The string has no path characters in it,
|
||||
* and its maximum length is 14 characters plus a NUL. Thus
|
||||
* buflen should be at least strlen(path) + 15 characters or
|
||||
* an error will be returned.
|
||||
*
|
||||
* Requires:
|
||||
* buf != NULL.
|
||||
*
|
||||
* Ensures:
|
||||
* If result == ISC_R_SUCCESS:
|
||||
* buf contains a string suitable for use as the template argument
|
||||
* to isc_file_openunique.
|
||||
*
|
||||
* If result != ISC_R_SUCCESS:
|
||||
* buf is unchanged.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS Success.
|
||||
* ISC_R_NOSPACE buflen indicates buf is too small for the catenation
|
||||
* of the path with the internal template string.
|
||||
*/
|
||||
|
||||
|
||||
isc_result_t
|
||||
isc_file_openunique(char *templet, FILE **fp);
|
||||
/*
|
||||
* Create and open a file with a unique name based on 'templet'.
|
||||
*
|
||||
* Notes:
|
||||
* 'template' is a reserved work in C++. If you want to complain
|
||||
* about the spelling of 'templet', first look it up in the
|
||||
* Merriam-Webster English dictionary. (http://www.m-w.com/)
|
||||
*
|
||||
* This function works by using the template to generate file names.
|
||||
* The template must be a writable string, as it is modified in place.
|
||||
* Trailing X characters in the file name (full file name on Unix,
|
||||
* basename on Win32 -- eg, tmp-XXXXXX vs XXXXXX.tmp, respectively)
|
||||
* are replaced with ASCII characters until a non-existent filename
|
||||
* is found. If the template does not include pathname information,
|
||||
* the files in the working directory of the program are searched.
|
||||
*
|
||||
* isc_file_mktemplate is a good, portable way to get a template.
|
||||
*
|
||||
* Requires:
|
||||
* 'fp' is non-NULL and '*fp' is NULL.
|
||||
*
|
||||
* 'template' is non-NULL, and of a form suitable for use by
|
||||
* the system as described above.
|
||||
*
|
||||
* Ensures:
|
||||
* If result is ISC_R_SUCCESS:
|
||||
* *fp points to an stream opening in stdio's "w+" mode.
|
||||
*
|
||||
* If result is not ISC_R_SUCCESS:
|
||||
* *fp is NULL.
|
||||
*
|
||||
* No file is open. Even if one was created (but unable
|
||||
* to be reopened as a stdio FILE pointer) then it has been
|
||||
* removed.
|
||||
*
|
||||
* This function does *not* ensure that the template string has not been
|
||||
* modified, even if the operation was unsuccessful.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS
|
||||
* Success.
|
||||
* ISC_R_EXISTS
|
||||
* No file with a unique name could be created based on the
|
||||
* template.
|
||||
* ISC_R_INVALIDFILE
|
||||
* The path specified was not usable by the operating system.
|
||||
* ISC_R_NOPERM
|
||||
* The file could not be created because permission was denied
|
||||
* to some part of the file's path.
|
||||
* ISC_R_EIO
|
||||
* Hardware error interacting with the filesystem.
|
||||
* ISC_R_UNEXPECTED
|
||||
* Something totally unexpected happened.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_remove(const char *filename);
|
||||
/*
|
||||
* Remove the file named by 'filename'.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_rename(const char *oldname, const char *newname);
|
||||
/*
|
||||
* Rename the file 'oldname' to 'newname'.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_exists(const char *pathname);
|
||||
/*
|
||||
* Return ISC_TRUE iff the calling process can tell that the given file exists.
|
||||
* Will not return true if the calling process has insufficient privileges
|
||||
* to search the entire path.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_isabsolute(const char *filename);
|
||||
/*
|
||||
* Return ISC_TRUE iff the given file name is absolute.
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_iscurrentdir(const char *filename);
|
||||
/*
|
||||
* Return ISC_TRUE iff the given file name is the current directory (".").
|
||||
*/
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_ischdiridempotent(const char *filename);
|
||||
/*
|
||||
* Return ISC_TRUE if calling chdir(filename) multiple times will give
|
||||
* the same result as calling it once.
|
||||
*/
|
||||
|
||||
const char *
|
||||
isc_file_basename(const char *filename);
|
||||
/*
|
||||
* Return the final component of the path in the file name.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_progname(const char *filename, char *buf, size_t buflen);
|
||||
/*
|
||||
* Given an operating system specific file name "filename"
|
||||
* referring to a program, return the canonical program name.
|
||||
* Any directory prefix or executable file name extension (if
|
||||
* used on the OS in case) is stripped. On systems where program
|
||||
* names are case insensitive, the name is canonicalized to all
|
||||
* lower case. The name is written to 'buf', an array of 'buflen'
|
||||
* chars, and null terminated.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS
|
||||
* ISC_R_NOSPACE The name did not fit in 'buf'.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_template(const char *path, const char *templet, char *buf,
|
||||
size_t buflen);
|
||||
/*
|
||||
* Create an OS specific template using 'path' to define the directory
|
||||
* 'templet' to describe the filename and store the result in 'buf'
|
||||
* such that path can be renamed to buf atomically.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_renameunique(const char *file, char *templet);
|
||||
/*
|
||||
* Rename 'file' using 'templet' as a template for the new file name.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_file_absolutepath(const char *filename, char *path, size_t pathlen);
|
||||
/*
|
||||
* Given a file name, return the fully qualified path to the file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX We should also have a isc_file_writeeopen() function
|
||||
* for safely open a file in a publicly writable directory
|
||||
* (see write_open() in BIND 8's ns_config.c).
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* ISC_FILE_H */
|
||||
315
lib/isc/unix/file.c
Normal file
315
lib/isc/unix/file.c
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* Copyright (C) 2000, 2001 Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
|
||||
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
|
||||
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
||||
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: file.c,v 1.38 2001/07/16 18:33:01 gson Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h> /* Required for utimes on some platforms. */
|
||||
#include <unistd.h> /* Required for mkstemp on NetBSD. */
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <isc/dir.h>
|
||||
#include <isc/file.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/time.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "errno2result.h"
|
||||
|
||||
/*
|
||||
* XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
|
||||
* it might be good to provide a mechanism that allows for the results
|
||||
* of a previous stat() to be used again without having to do another stat,
|
||||
* such as perl's mechanism of using "_" in place of a file name to indicate
|
||||
* that the results of the last stat should be used. But then you get into
|
||||
* annoying MP issues. BTW, Win32 has stat().
|
||||
*/
|
||||
static isc_result_t
|
||||
file_stats(const char *file, struct stat *stats) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(file != NULL);
|
||||
REQUIRE(stats != NULL);
|
||||
|
||||
if (stat(file, stats) != 0)
|
||||
result = isc__errno2result(errno);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_getmodtime(const char *file, isc_time_t *time) {
|
||||
isc_result_t result;
|
||||
struct stat stats;
|
||||
|
||||
REQUIRE(file != NULL);
|
||||
REQUIRE(time != NULL);
|
||||
|
||||
result = file_stats(file, &stats);
|
||||
|
||||
if (result == ISC_R_SUCCESS)
|
||||
/*
|
||||
* XXXDCL some operating systems provide nanoseconds, too,
|
||||
* such as BSD/OS via st_mtimespec.
|
||||
*/
|
||||
isc_time_set(time, stats.st_mtime, 0);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_settime(const char *file, isc_time_t *time) {
|
||||
struct timeval times[2];
|
||||
|
||||
REQUIRE(file != NULL && time != NULL);
|
||||
|
||||
/*
|
||||
* tv_sec is at least a 32 bit quantity on all platforms we're
|
||||
* dealing with, but it is signed on most (all?) of them,
|
||||
* so we need to make sure the high bit isn't set. This unfortunately
|
||||
* loses when either:
|
||||
* * tv_sec becomes a signed 64 bit integer but long is 32 bits
|
||||
* and isc_time_seconds > LONG_MAX, or
|
||||
* * isc_time_seconds is changed to be > 32 bits but long is 32 bits
|
||||
* and isc_time_seconds has at least 33 significant bits.
|
||||
*/
|
||||
times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time);
|
||||
|
||||
/*
|
||||
* Here is the real check for the high bit being set.
|
||||
*/
|
||||
if ((times[0].tv_sec &
|
||||
(1ULL << (sizeof(times[0].tv_sec) * CHAR_BIT - 1))) != 0)
|
||||
return (ISC_R_RANGE);
|
||||
|
||||
/*
|
||||
* isc_time_nanoseconds guarantees a value that divided by 1000 will
|
||||
* fit into the minimum possible size tv_usec field. Unfortunately,
|
||||
* we don't know what that type is so can't cast directly ... but
|
||||
* we can at least cast to signed so the IRIX compiler shuts up.
|
||||
*/
|
||||
times[0].tv_usec = times[1].tv_usec =
|
||||
(isc_int32_t)(isc_time_nanoseconds(time) / 1000);
|
||||
|
||||
if (utimes(file, times) < 0)
|
||||
return (isc__errno2result(errno));
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
#undef TEMPLATE
|
||||
#define TEMPLATE "tmp-XXXXXXXXXX" /* 14 characters. */
|
||||
|
||||
isc_result_t
|
||||
isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
|
||||
return (isc_file_template(path, TEMPLATE, buf, buflen));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_template(const char *path, const char *templet, char *buf,
|
||||
size_t buflen) {
|
||||
char *s;
|
||||
|
||||
REQUIRE(path != NULL);
|
||||
REQUIRE(templet != NULL);
|
||||
REQUIRE(buf != NULL);
|
||||
|
||||
s = strrchr(templet, '/');
|
||||
if (s != NULL)
|
||||
templet = s + 1;
|
||||
|
||||
s = strrchr(path, '/');
|
||||
|
||||
if (s != NULL) {
|
||||
if ((s - path + 1 + strlen(templet) + 1) > buflen)
|
||||
return (ISC_R_NOSPACE);
|
||||
|
||||
strncpy(buf, path, s - path + 1);
|
||||
buf[s - path + 1] = '\0';
|
||||
strcat(buf, templet);
|
||||
} else {
|
||||
if ((strlen(templet) + 1) > buflen)
|
||||
return (ISC_R_NOSPACE);
|
||||
|
||||
strcpy(buf, templet);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_renameunique(const char *file, char *templet) {
|
||||
int fd = -1;
|
||||
int res = 0;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(file != NULL);
|
||||
REQUIRE(templet != NULL);
|
||||
|
||||
fd = mkstemp(templet);
|
||||
if (fd == -1) {
|
||||
result = isc__errno2result(errno);
|
||||
}
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
res = rename(file, templet);
|
||||
if (res != 0) {
|
||||
result = isc__errno2result(errno);
|
||||
(void)unlink(templet);
|
||||
}
|
||||
}
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_openunique(char *templet, FILE **fp) {
|
||||
int fd;
|
||||
FILE *f;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
|
||||
REQUIRE(templet != NULL);
|
||||
REQUIRE(fp != NULL && *fp == NULL);
|
||||
|
||||
/*
|
||||
* Win32 does not have mkstemp.
|
||||
*/
|
||||
fd = mkstemp(templet);
|
||||
|
||||
if (fd == -1)
|
||||
result = isc__errno2result(errno);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
f = fdopen(fd, "w+");
|
||||
if (f == NULL) {
|
||||
result = isc__errno2result(errno);
|
||||
(void)remove(templet);
|
||||
(void)close(fd);
|
||||
|
||||
} else
|
||||
*fp = f;
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_remove(const char *filename) {
|
||||
int r;
|
||||
|
||||
REQUIRE(filename != NULL);
|
||||
|
||||
r = unlink(filename);
|
||||
if (r == 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
else
|
||||
return (isc__errno2result(errno));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_rename(const char *oldname, const char *newname) {
|
||||
int r;
|
||||
|
||||
REQUIRE(oldname != NULL);
|
||||
REQUIRE(newname != NULL);
|
||||
|
||||
r = rename(oldname, newname);
|
||||
if (r == 0)
|
||||
return (ISC_R_SUCCESS);
|
||||
else
|
||||
return (isc__errno2result(errno));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_exists(const char *pathname) {
|
||||
struct stat stats;
|
||||
|
||||
REQUIRE(pathname != NULL);
|
||||
|
||||
return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_isabsolute(const char *filename) {
|
||||
REQUIRE(filename != NULL);
|
||||
return (ISC_TF(filename[0] == '/'));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_iscurrentdir(const char *filename) {
|
||||
REQUIRE(filename != NULL);
|
||||
return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
|
||||
}
|
||||
|
||||
isc_boolean_t
|
||||
isc_file_ischdiridempotent(const char *filename) {
|
||||
REQUIRE(filename != NULL);
|
||||
if (isc_file_isabsolute(filename))
|
||||
return (ISC_TRUE);
|
||||
if (isc_file_iscurrentdir(filename))
|
||||
return (ISC_TRUE);
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
const char *
|
||||
isc_file_basename(const char *filename) {
|
||||
char *s;
|
||||
|
||||
REQUIRE(filename != NULL);
|
||||
|
||||
s = strrchr(filename, '/');
|
||||
if (s == NULL)
|
||||
return (filename);
|
||||
|
||||
return (s + 1);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_progname(const char *filename, char *buf, size_t buflen) {
|
||||
const char *base;
|
||||
size_t len;
|
||||
|
||||
REQUIRE(filename != NULL);
|
||||
REQUIRE(buf != NULL);
|
||||
|
||||
base = isc_file_basename(filename);
|
||||
len = strlen(base) + 1;
|
||||
|
||||
if (len > buflen)
|
||||
return (ISC_R_NOSPACE);
|
||||
memcpy(buf, base, len);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
|
||||
isc_result_t result;
|
||||
result = isc_dir_current(path, pathlen, ISC_TRUE);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
if (strlen(path) + strlen(filename) + 1 > pathlen)
|
||||
return (ISC_R_NOSPACE);
|
||||
strcat(path, filename);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
3955
lib/isccfg/parser.c
Normal file
3955
lib/isccfg/parser.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue