Add --dns-rr option.

This commit is contained in:
Simon Kelley
2012-05-28 21:39:57 +01:00
parent 97c83bb05b
commit 9f7f3b1216
6 changed files with 89 additions and 8 deletions

View File

@@ -16,6 +16,8 @@ version 2.62
router-advertisement configured, but DHCPv6 not router-advertisement configured, but DHCPv6 not
configured. Thanks to Marien Zwart for the patch. configured. Thanks to Marien Zwart for the patch.
Add --dns-rr, to allow arbitrary DNS resource records.
version 2.61 version 2.61
Re-write interface discovery code on *BSD to use Re-write interface discovery code on *BSD to use

View File

@@ -454,6 +454,12 @@ hosts files) or from DHCP. If the target does not satisfy this
criteria, the whole cname is ignored. The cname must be unique, but it criteria, the whole cname is ignored. The cname must be unique, but it
is permissable to have more than one cname pointing to the same target. is permissable to have more than one cname pointing to the same target.
.TP .TP
.B --dns-rr=<name>,<RR-number>,[<hex data>]
Return an arbitrary DNS Resource Record. The number is the type of the
record (which is always in the C_IN class). The value of the record is
given by the hex data, which may be of the for 01:23:45 or 01 23 45 or
012345 or any mixture of these.
.TP
.B --interface-name=<name>,<interface> .B --interface-name=<name>,<interface>
Return a DNS record associating the name with the primary address on Return a DNS record associating the name with the primary address on
the given interface. This flag specifies an A record for the given the given interface. This flag specifies an A record for the given

View File

@@ -732,7 +732,7 @@ extern struct daemon {
time_t last_resolv; time_t last_resolv;
struct mx_srv_record *mxnames; struct mx_srv_record *mxnames;
struct naptr *naptr; struct naptr *naptr;
struct txt_record *txt; struct txt_record *txt, *rr;
struct ptr_record *ptr; struct ptr_record *ptr;
struct host_record *host_records, *host_records_tail; struct host_record *host_records, *host_records_tail;
struct cname *cnames; struct cname *cnames;

View File

@@ -118,6 +118,7 @@ struct myoption {
#define LOPT_DUID 307 #define LOPT_DUID 307
#define LOPT_HOST_REC 308 #define LOPT_HOST_REC 308
#define LOPT_TFTP_LC 309 #define LOPT_TFTP_LC 309
#define LOPT_RR 310
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -181,6 +182,7 @@ static const struct myoption opts[] =
{ "srv-host", 1, 0, 'W' }, { "srv-host", 1, 0, 'W' },
{ "localise-queries", 0, 0, 'y' }, { "localise-queries", 0, 0, 'y' },
{ "txt-record", 1, 0, 'Y' }, { "txt-record", 1, 0, 'Y' },
{ "dns-rr", 1, 0, LOPT_RR },
{ "enable-dbus", 0, 0, '1' }, { "enable-dbus", 0, 0, '1' },
{ "bootp-dynamic", 2, 0, '3' }, { "bootp-dynamic", 2, 0, '3' },
{ "dhcp-mac", 1, 0, '4' }, { "dhcp-mac", 1, 0, '4' },
@@ -371,6 +373,7 @@ static struct {
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL }, { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL }, { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL }, { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
@@ -2214,6 +2217,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
if (len == -1) if (len == -1)
problem = _("bad hex constant"); problem = _("bad hex constant");
else if ((new->clid = opt_malloc(len))) else if ((new->clid = opt_malloc(len)))
{ {
@@ -2932,6 +2936,41 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
break; break;
} }
case LOPT_RR: /* dns-rr */
{
struct txt_record *new;
size_t len;
char *data;
int val;
comma = split(arg);
data = split(comma);
new = opt_malloc(sizeof(struct txt_record));
new->next = daemon->rr;
daemon->rr = new;
if (!atoi_check(comma, &val) ||
!(new->name = canonicalise_opt(arg)) ||
(data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1))
{
problem = _("bad RR record");
break;
}
new->class = val;
new->len = 0;
if (data)
{
new->txt=opt_malloc(len);
new->len = len;
memcpy(new->txt, data, len);
}
break;
}
case 'Y': /* --txt-record */ case 'Y': /* --txt-record */
{ {
struct txt_record *new; struct txt_record *new;

View File

@@ -1250,7 +1250,8 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
case 't': case 't':
usval = va_arg(ap, int); usval = va_arg(ap, int);
sval = va_arg(ap, char *); sval = va_arg(ap, char *);
memcpy(p, sval, usval); if (usval != 0)
memcpy(p, sval, usval);
p += usval; p += usval;
break; break;
@@ -1393,6 +1394,22 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
if (qclass == C_IN) if (qclass == C_IN)
{ {
struct txt_record *t;
for (t = daemon->rr; t; t = t->next)
if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
{
ans = 1;
if (!dryrun)
{
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->local_ttl, NULL,
t->class, C_IN, "t", t->len, t->txt))
anscount ++;
}
}
if (qtype == T_PTR || qtype == T_ANY) if (qtype == T_PTR || qtype == T_ANY)
{ {
/* see if it's w.z.y.z.in-addr.arpa format */ /* see if it's w.z.y.z.in-addr.arpa format */

View File

@@ -426,7 +426,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
while (maxlen == -1 || i < maxlen) while (maxlen == -1 || i < maxlen)
{ {
for (r = in; *r != 0 && *r != ':' && *r != '-'; r++) for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
if (*r != '*' && !isxdigit((unsigned char)*r)) if (*r != '*' && !isxdigit((unsigned char)*r))
return -1; return -1;
@@ -444,12 +444,29 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
else else
{ {
*r = 0; *r = 0;
mask = mask << 1;
if (strcmp(in, "*") == 0) if (strcmp(in, "*") == 0)
mask |= 1; {
mask = (mask << 1) | 1;
i++;
}
else else
out[i] = strtol(in, NULL, 16); {
i++; int j, bytes = (1 + (r - in))/2;
for (j = 0; j < bytes; j++)
{
char sav;
if (j < bytes - 1)
{
sav = in[(j+1)*2];
in[(j+1)*2] = 0;
}
out[i] = strtol(&in[j*2], NULL, 16);
mask = mask << 1;
i++;
if (j < bytes - 1)
in[(j+1)*2] = sav;
}
}
} }
} }
in = r+1; in = r+1;