/***************************************************************************
posadisrc.cpp - routines for reading the posadisrc
-------------------
begin : do sep 4 2003
copyright : (C) 2003 by Meilof
email : meilof@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "posadisrc.h"
#include "configuration.h"
#include "lib.h"
/* ----- configuration helper functions ------------------------------------ */
void set_setting(setting_fn fn, void *u1, void *u2, const char *_ptr) {
char *ptr = (char *)_ptr;
bool more;
stl_string i2;
while (1) {
try {
i2 = read_entry(ptr);
} catch (PException p) { throw PException(true, "Expected value: %s!", p.message); break; }
if (i2[i2.size() - 1] == ',') {
i2[i2.size() - 1] = 0;
more = true;
} else {
more = false;
}
fn(u1, u2, i2.c_str());
if (!more) {
char *po = ptr;
try {
skip_whitespace(ptr, ptr);
read_entry(ptr);
} catch (PException p) {
break;
}
throw PException(true, "Unexpected text at end of line: %s", po);
break;
}
}
}
void zone_set(Zone *z, char *setting, const char *value) {
z->feed_setting(setting, value);
}
void cachens_set(domainname *znroot, void *dat2, const char *value) {
char dom[256];
char dat[17];
domainname di, d3;
ZoneDomain *domn;
char *ptr = strchr(value, '@');
if (ptr) {
if (ptr - value + 1 > (signed)sizeof(dom)) throw PException("Domain name too long");
memcpy(dom, value, ptr - value);
dom[ptr - value] = 0;
ptr++;
di = dom;
if (strchr(ptr, ':') != 0) { dat[0] = '6'; txt_to_ipv6(dat + 1, ptr); }
else { dat[0] = '4'; txt_to_ip(dat + 1, ptr); }
} else {
di = value;
dat[0] = '0';
}
d3 = "";
domn = create_domainname(cache_root_domain, d3, *znroot, ZF_DONOTREMOVE);
domn->create_rrset(DNS_TYPE_NS)->add_rr(518400, di.len(), di.c_str());
switch (dat[0]) {
case '4':
domn = create_domainname(cache_root_domain, d3, di, ZF_DONOTREMOVE);
domn->create_rrset(DNS_TYPE_A)->add_rr(3600000, 4, dat + 1);
break;
case '6':
domn = create_domainname(cache_root_domain, d3, di, ZF_DONOTREMOVE);
domn->create_rrset(DNS_TYPE_AAAA)->add_rr(3600000, 16, dat + 1);
break;
}
}
void cachefw_set(CacheZone *z, void *dat2, const char *value) {
_addr a;
txt_to_addr(&a, value);
z->forwarders->push_front(a);
}
void conf_set(const char *optname, void *u2, const char *value) {
if (!feed_setting(optname, value))
throw PException(true, "Unknown setting %s", optname);
}
/* ----- main posadisrc reading function ----------------------------------- */
void read_posadisrc(const char *fname) {
FILE *f = try_fopen_r(fname);
char buff[1024];
stl_string item;
char *ptr;
Zone *z;
domainname dom, d2, d3;
char command[32];
int linenum_new = 1, linenum;
if (!f) throw PException(true, "Failed to open configuration file %s!", fname);
try {
while (!feof(f)) {
read_line(buff, f, &linenum_new, &linenum);
handle_config_line:
ptr = buff;
if (buff[0] == 0) continue;
if (buff[0] == '\t' || buff[0] == ' ') {
/* what is this, whitespace? */
read_entry(ptr);
if (buff[0] != '\0') throw PException(true, "posadisrc:%d: Line should not begin with whitespace", linenum);
}
item = read_entry(ptr);
if (item == "") {
if (ptr && ptr[0]) throw PException(true, "posadisrc:%d: No whitespace expected at beginning of line", linenum);
else continue;
}
if (strlen(item.c_str()) + 1 > 31) throw PException(true, "posadisrc:%d: Command name %s too long", linenum, item.c_str());
strcpy(command, item.c_str());
if (strcmpi(command, "zone") == 0) {
/* zone statement */
try {
z = create_zone(read_entry(ptr).c_str());
dom = read_entry(ptr).c_str();
add_authoritative_zone(dom, z);
while (!feof(f)) {
read_line(buff, f, &linenum_new, &linenum);
if (!buff[0]) continue;
if (!is_whitespace(buff[0])) break;
skip_whitespace(buff, ptr);
if (*ptr == '\0') continue;
item = read_entry(ptr); /* setting name */
try {
set_setting((setting_fn)zone_set, z, (void *)item.c_str(), ptr);
} catch (PException p) {
throw PException(true, "Error in setting \"%s\": %s", item.c_str(), p.message);
}
}
if (!feof(f)) goto handle_config_line;
} catch (PException p) {
throw PException("Error creating zone: ", p);
}
} else if (strcmpi(command, "cache-ns") == 0) {
dom = read_entry(ptr).c_str();
while (!feof(f)) {
read_line(buff, f, &linenum_new, &linenum);
if (!buff[0]) continue;
if (!is_whitespace(buff[0])) goto handle_config_line;
skip_whitespace(buff, ptr);
if (*ptr == '\0') continue;
try {
set_setting((setting_fn)cachens_set, &dom, NULL, ptr);
} catch (PException p) {
throw PException("Error in cache NS list: ", p);
}
}
} else if (strcmpi(command, "cache-forward") == 0) {
z = NULL;
try {
dom = read_entry(ptr).c_str();
if (dom == "") {
z = (Zone *)cache_root_zone;
if (!((CacheZone *)z)->forwarders)
((CacheZone *)z)->forwarders = new stl_slist(_addr);
} else {
z = NULL;
try {
z = (Zone *)new CacheZone();
((CacheZone *)z)->forwarders = new stl_slist(_addr);
add_cache_zone(dom, (CacheZone *)z);
} catch (PException p) { delete z; throw p; }
}
while (!feof(f)) {
read_line(buff, f, &linenum_new, &linenum);
if (!buff[0]) continue;
if (!is_whitespace(buff[0])) goto handle_config_line;
skip_whitespace(buff, ptr);
if (*ptr == '\0') continue;
try {
set_setting((setting_fn)cachefw_set, z, NULL, ptr);
} catch (PException p) {
throw PException(true, "Could not set cache forward data: %s", p.message);
}
}
} catch (PException p) {
throw PException("Could not set forwarding info: ", p);
}
} else {
try {
set_setting((setting_fn)conf_set, (void *)item.c_str(), NULL, ptr);
} catch (PException p) {
throw PException(true, "setting %s: %s", command, p.message);
}
}
}
} catch (PException p) {
fclose(f);
throw PException(true, "error: posadisrc:%d: %s", linenum, p.message);
}
fclose(f);
}
void posadisrc_finalize() {
try {
end_setting();
/* now, call end_setting for all zones recursively */
recursive_zone_end_setting(NULL, "", auth_root_zone);
} catch (PException p) {
throw PException("Error finalizing configuration settings: ", p);
}
}
syntax highlighted by Code2HTML, v. 0.9.1