mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
--host-record support
This commit is contained in:
@@ -21,6 +21,9 @@ version 2.61
|
|||||||
|
|
||||||
Better logging of DHCPv6 options.
|
Better logging of DHCPv6 options.
|
||||||
|
|
||||||
|
Add --host-record. Thanks to Rob Zwissler for the
|
||||||
|
suggestion.
|
||||||
|
|
||||||
|
|
||||||
version 2.60
|
version 2.60
|
||||||
Fix compilation problem in Mac OS X Lion. Thanks to Olaf
|
Fix compilation problem in Mac OS X Lion. Thanks to Olaf
|
||||||
|
|||||||
@@ -416,6 +416,22 @@ zone files: the port, weight and priority numbers are in a different
|
|||||||
order. More than one SRV record for a given service/domain is allowed,
|
order. More than one SRV record for a given service/domain is allowed,
|
||||||
all that match are returned.
|
all that match are returned.
|
||||||
.TP
|
.TP
|
||||||
|
.B --host-record=<name>[,<name>....][<IPv4-address>],[IPv6-address]
|
||||||
|
Add A, AAAA and PTR records to the DNS. This adds one or more names to
|
||||||
|
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
|
||||||
|
appear in more than one
|
||||||
|
.B host-record
|
||||||
|
and therefore be assigned more than one address. Only the first
|
||||||
|
address creates a PTR record linking the address to the name. This is
|
||||||
|
the same rule as is used reading hosts-files.
|
||||||
|
.B host-record
|
||||||
|
options are considered to be read before host-files, so a name
|
||||||
|
appearing there inhibits PTR-record creation if it appears in
|
||||||
|
hosts-file also. Unlike host-files, names are not expanded, even when
|
||||||
|
.B expand-hosts
|
||||||
|
is in effect. Short and long names may appear in the same
|
||||||
|
.B host-record, eg. --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
|
||||||
|
.TP
|
||||||
.B \-Y, --txt-record=<name>[[,<text>],<text>]
|
.B \-Y, --txt-record=<name>[[,<text>],<text>]
|
||||||
Return a TXT DNS record. The value of TXT record is a set of strings,
|
Return a TXT DNS record. The value of TXT record is a set of strings,
|
||||||
so any number may be included, delimited by commas; use quotes to put
|
so any number may be included, delimited by commas; use quotes to put
|
||||||
|
|||||||
63
src/cache.c
63
src/cache.c
@@ -634,10 +634,11 @@ struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
||||||
unsigned short flags, int index, struct crec **rhash, int hashsz)
|
int index, struct crec **rhash, int hashsz)
|
||||||
{
|
{
|
||||||
struct crec *lookup = cache_find_by_name(NULL, cache->name.sname, 0, flags & (F_IPV4 | F_IPV6));
|
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
||||||
int i, nameexists = 0;
|
int i, nameexists = 0;
|
||||||
struct cname *a;
|
struct cname *a;
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
@@ -670,10 +671,10 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
|||||||
j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
|
j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
|
||||||
|
|
||||||
for (lookup = rhash[j]; lookup; lookup = lookup->next)
|
for (lookup = rhash[j]; lookup; lookup = lookup->next)
|
||||||
if ((lookup->flags & flags & (F_IPV4 | F_IPV6)) &&
|
if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
|
||||||
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
||||||
{
|
{
|
||||||
flags &= ~F_REVERSE;
|
cache->flags &= ~F_REVERSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,7 +685,6 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
|||||||
rhash[j] = cache;
|
rhash[j] = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache->flags = flags;
|
|
||||||
cache->uid = index;
|
cache->uid = index;
|
||||||
memcpy(&cache->addr.addr, addr, addrlen);
|
memcpy(&cache->addr.addr, addr, addrlen);
|
||||||
cache_hash(cache);
|
cache_hash(cache);
|
||||||
@@ -692,7 +692,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
|||||||
/* don't need to do alias stuff for second and subsequent addresses. */
|
/* don't need to do alias stuff for second and subsequent addresses. */
|
||||||
if (!nameexists)
|
if (!nameexists)
|
||||||
for (a = daemon->cnames; a; a = a->next)
|
for (a = daemon->cnames; a; a = a->next)
|
||||||
if (hostname_isequal(cache->name.sname, a->target) &&
|
if (hostname_isequal(cache_get_name(cache), a->target) &&
|
||||||
(lookup = whine_malloc(sizeof(struct crec))))
|
(lookup = whine_malloc(sizeof(struct crec))))
|
||||||
{
|
{
|
||||||
lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
lookup->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_HOSTS | F_CNAME;
|
||||||
@@ -771,26 +771,19 @@ static int read_hostsfile(char *filename, int index, int cache_size, struct crec
|
|||||||
{
|
{
|
||||||
lineno++;
|
lineno++;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (inet_pton(AF_INET, token, &addr) > 0)
|
if (inet_pton(AF_INET, token, &addr) > 0)
|
||||||
{
|
{
|
||||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
|
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
|
||||||
addrlen = INADDRSZ;
|
addrlen = INADDRSZ;
|
||||||
domain_suffix = get_domain(addr.addr.addr4);
|
domain_suffix = get_domain(addr.addr.addr4);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
else if (inet_pton(AF_INET6, token, &addr) > 0)
|
else if (inet_pton(AF_INET6, token, &addr) > 0)
|
||||||
{
|
{
|
||||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
|
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6;
|
||||||
addrlen = IN6ADDRSZ;
|
addrlen = IN6ADDRSZ;
|
||||||
domain_suffix = get_domain6(&addr.addr.addr6);
|
domain_suffix = get_domain6(&addr.addr.addr6);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if ((addr.addr.addr4.s_addr = inet_addr(token)) != (in_addr_t) -1)
|
|
||||||
{
|
|
||||||
flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4;
|
|
||||||
addrlen = INADDRSZ;
|
|
||||||
domain_suffix = get_domain(addr.addr.addr4);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -830,13 +823,15 @@ static int read_hostsfile(char *filename, int index, int cache_size, struct crec
|
|||||||
strcpy(cache->name.sname, canon);
|
strcpy(cache->name.sname, canon);
|
||||||
strcat(cache->name.sname, ".");
|
strcat(cache->name.sname, ".");
|
||||||
strcat(cache->name.sname, domain_suffix);
|
strcat(cache->name.sname, domain_suffix);
|
||||||
add_hosts_entry(cache, &addr, addrlen, flags, index, rhash, hashsz);
|
cache->flags = flags;
|
||||||
|
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
|
||||||
name_count++;
|
name_count++;
|
||||||
}
|
}
|
||||||
if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
|
if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
|
||||||
{
|
{
|
||||||
strcpy(cache->name.sname, canon);
|
strcpy(cache->name.sname, canon);
|
||||||
add_hosts_entry(cache, &addr, addrlen, flags, index, rhash, hashsz);
|
cache->flags = flags;
|
||||||
|
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
|
||||||
name_count++;
|
name_count++;
|
||||||
}
|
}
|
||||||
free(canon);
|
free(canon);
|
||||||
@@ -860,6 +855,8 @@ void cache_reload(void)
|
|||||||
struct crec *cache, **up, *tmp;
|
struct crec *cache, **up, *tmp;
|
||||||
int revhashsz, i, total_size = daemon->cachesize;
|
int revhashsz, i, total_size = daemon->cachesize;
|
||||||
struct hostsfile *ah;
|
struct hostsfile *ah;
|
||||||
|
struct host_record *hr;
|
||||||
|
struct name_list *nl;
|
||||||
|
|
||||||
cache_inserted = cache_live_freed = 0;
|
cache_inserted = cache_live_freed = 0;
|
||||||
|
|
||||||
@@ -886,6 +883,34 @@ void cache_reload(void)
|
|||||||
up = &cache->hash_next;
|
up = &cache->hash_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* borrow the packet buffer for a temporary by-address hash */
|
||||||
|
memset(daemon->packet, 0, daemon->packet_buff_sz);
|
||||||
|
revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
|
||||||
|
/* we overwrote the buffer... */
|
||||||
|
daemon->srv_save = NULL;
|
||||||
|
|
||||||
|
/* Do host_records in config. */
|
||||||
|
for (hr = daemon->host_records; hr; hr = hr->next)
|
||||||
|
for (nl = hr->names; nl; nl = nl->next)
|
||||||
|
{
|
||||||
|
if (hr->addr.s_addr != 0 &&
|
||||||
|
(cache = whine_malloc(sizeof(struct crec))))
|
||||||
|
{
|
||||||
|
cache->name.namep = nl->name;
|
||||||
|
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
|
||||||
|
add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, 0, (struct crec **)daemon->packet, revhashsz);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
|
||||||
|
(cache = whine_malloc(sizeof(struct crec))))
|
||||||
|
{
|
||||||
|
cache->name.namep = nl->name;
|
||||||
|
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
|
||||||
|
add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, 0, (struct crec **)daemon->packet, revhashsz);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
|
if (option_bool(OPT_NO_HOSTS) && !daemon->addn_hosts)
|
||||||
{
|
{
|
||||||
if (daemon->cachesize > 0)
|
if (daemon->cachesize > 0)
|
||||||
@@ -893,12 +918,6 @@ void cache_reload(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* borrow the packet buffer for a temporary by-address hash */
|
|
||||||
memset(daemon->packet, 0, daemon->packet_buff_sz);
|
|
||||||
revhashsz = daemon->packet_buff_sz / sizeof(struct crec *);
|
|
||||||
/* we overwrote the buffer... */
|
|
||||||
daemon->srv_save = NULL;
|
|
||||||
|
|
||||||
if (!option_bool(OPT_NO_HOSTS))
|
if (!option_bool(OPT_NO_HOSTS))
|
||||||
total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz);
|
total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz);
|
||||||
|
|
||||||
|
|||||||
@@ -274,6 +274,18 @@ struct cname {
|
|||||||
struct cname *next;
|
struct cname *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct host_record {
|
||||||
|
struct name_list {
|
||||||
|
char *name;
|
||||||
|
struct name_list *next;
|
||||||
|
} *names;
|
||||||
|
struct in_addr addr;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
struct in6_addr addr6;
|
||||||
|
#endif
|
||||||
|
struct host_record *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct interface_name {
|
struct interface_name {
|
||||||
char *name; /* domain name */
|
char *name; /* domain name */
|
||||||
char *intr; /* interface name */
|
char *intr; /* interface name */
|
||||||
@@ -695,6 +707,7 @@ extern struct daemon {
|
|||||||
struct naptr *naptr;
|
struct naptr *naptr;
|
||||||
struct txt_record *txt;
|
struct txt_record *txt;
|
||||||
struct ptr_record *ptr;
|
struct ptr_record *ptr;
|
||||||
|
struct host_record *host_records, *host_records_tail;
|
||||||
struct cname *cnames;
|
struct cname *cnames;
|
||||||
struct interface_name *int_names;
|
struct interface_name *int_names;
|
||||||
char *mxtarget;
|
char *mxtarget;
|
||||||
|
|||||||
56
src/option.c
56
src/option.c
@@ -116,6 +116,7 @@ struct myoption {
|
|||||||
#define LOPT_LUASCRIPT 305
|
#define LOPT_LUASCRIPT 305
|
||||||
#define LOPT_RA 306
|
#define LOPT_RA 306
|
||||||
#define LOPT_DUID 307
|
#define LOPT_DUID 307
|
||||||
|
#define LOPT_HOST_REC 308
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
static const struct option opts[] =
|
static const struct option opts[] =
|
||||||
@@ -237,6 +238,7 @@ static const struct myoption opts[] =
|
|||||||
{ "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
|
{ "dhcp-luascript", 1, 0, LOPT_LUASCRIPT },
|
||||||
{ "enable-ra", 0, 0, LOPT_RA },
|
{ "enable-ra", 0, 0, LOPT_RA },
|
||||||
{ "dhcp-duid", 1, 0, LOPT_DUID },
|
{ "dhcp-duid", 1, 0, LOPT_DUID },
|
||||||
|
{ "host-record", 1, 0, LOPT_HOST_REC },
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -365,6 +367,7 @@ static struct {
|
|||||||
{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
|
{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
|
||||||
{ 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 },
|
||||||
{ 0, 0, NULL, NULL, NULL }
|
{ 0, 0, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3030,6 +3033,59 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LOPT_HOST_REC: /* --host-record */
|
||||||
|
{
|
||||||
|
struct host_record *new = opt_malloc(sizeof(struct host_record));
|
||||||
|
memset(new, 0, sizeof(struct host_record));
|
||||||
|
|
||||||
|
if (!arg || !(comma = split(arg)))
|
||||||
|
problem = _("Bad host-record");
|
||||||
|
else
|
||||||
|
while (arg)
|
||||||
|
{
|
||||||
|
struct all_addr addr;
|
||||||
|
if (inet_pton(AF_INET, arg, &addr))
|
||||||
|
new->addr = addr.addr.addr4;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (inet_pton(AF_INET6, arg, &addr))
|
||||||
|
new->addr6 = addr.addr.addr6;
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int nomem;
|
||||||
|
char *canon = canonicalise(arg, &nomem);
|
||||||
|
struct name_list *nl = opt_malloc(sizeof(struct name_list));
|
||||||
|
if (!canon)
|
||||||
|
{
|
||||||
|
problem = _("Bad name in host-record");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nl->name = canon;
|
||||||
|
/* keep order, so that PTR record goes to first name */
|
||||||
|
nl->next = NULL;
|
||||||
|
if (!new->names)
|
||||||
|
new->names = nl;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct name_list *tmp;
|
||||||
|
for (tmp = new->names; tmp->next; tmp = tmp->next);
|
||||||
|
tmp->next = nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg = comma;
|
||||||
|
comma = split(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep list order */
|
||||||
|
if (!daemon->host_records_tail)
|
||||||
|
daemon->host_records = new;
|
||||||
|
else
|
||||||
|
daemon->host_records_tail->next = new;
|
||||||
|
new->next = NULL;
|
||||||
|
daemon->host_records_tail = new;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
|
return _("unsupported option (check that dnsmasq was compiled with DHCP/TFTP/DBus support)");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user