Enhance --add-subnet to allow arbitary subnet addresses.

This commit is contained in:
Ed Bardsley
2015-08-05 21:17:18 +01:00
committed by Simon Kelley
parent d2aa7dfbb6
commit a7369bef8a
5 changed files with 121 additions and 26 deletions

View File

@@ -541,6 +541,13 @@ struct iname {
struct iname *next;
};
/* subnet parameters from command line */
struct mysubnet {
union mysockaddr addr;
int addr_used;
int mask;
};
/* resolv-file parms from command-line */
struct resolvc {
struct resolvc *next;
@@ -935,9 +942,9 @@ extern struct daemon {
struct auth_zone *auth_zones;
struct interface_name *int_names;
char *mxtarget;
int addr4_netmask;
int addr6_netmask;
char *lease_file;
struct mysubnet *add_subnet4;
struct mysubnet *add_subnet6;
char *lease_file;
char *username, *groupname, *scriptuser;
char *luascript;
char *authserver, *hostmaster;

View File

@@ -445,7 +445,7 @@ static struct {
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
{ LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL },
{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL },
{ LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
{ LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
@@ -722,6 +722,20 @@ static void do_usage(void)
#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
{
if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
addr->sa.sa_family = AF_INET;
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
addr->sa.sa_family = AF_INET6;
#endif
else
return _("bad address");
return NULL;
}
char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
{
int source_port = 0, serv_port = NAMESERVER_PORT;
@@ -1585,7 +1599,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
li = match_suffix->next;
free(match_suffix->suffix);
free(match_suffix);
}
}
break;
}
@@ -1593,10 +1607,45 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
set_option_bool(OPT_CLIENT_SUBNET);
if (arg)
{
char *err, *end;
comma = split(arg);
if (!atoi_check(arg, &daemon->addr4_netmask) ||
(comma && !atoi_check(comma, &daemon->addr6_netmask)))
ret_err(gen_err);
struct mysubnet* new = opt_malloc(sizeof(struct mysubnet));
if ((end = split_chr(arg, '/')))
{
/* has subnet+len */
err = parse_mysockaddr(arg, &new->addr);
if (err)
ret_err(err);
if (!atoi_check(end, &new->mask))
ret_err(gen_err);
new->addr_used = 1;
}
else if (!atoi_check(arg, &new->mask))
ret_err(gen_err);
daemon->add_subnet4 = new;
new = opt_malloc(sizeof(struct mysubnet));
if (comma)
{
if ((end = split_chr(comma, '/')))
{
/* has subnet+len */
err = parse_mysockaddr(comma, &new->addr);
if (err)
ret_err(err);
if (!atoi_check(end, &new->mask))
ret_err(gen_err);
new->addr_used = 1;
}
else
{
if (!atoi_check(comma, &new->mask))
ret_err(gen_err);
}
}
daemon->add_subnet6 = new;
}
break;

View File

@@ -629,26 +629,47 @@ struct subnet_opt {
#endif
};
static void *get_addrp(union mysockaddr *addr, const short family)
{
#ifdef HAVE_IPV6
if (family == AF_INET6)
return &addr->in6.sin6_addr;
#endif
return &addr->in.sin_addr;
}
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len;
void *addrp;
int sa_family = source->sa.sa_family;
#ifdef HAVE_IPV6
if (source->sa.sa_family == AF_INET6)
{
opt->family = htons(2);
opt->source_netmask = daemon->addr6_netmask;
addrp = &source->in6.sin6_addr;
opt->source_netmask = daemon->add_subnet6->mask;
if (daemon->add_subnet6->addr_used)
{
sa_family = daemon->add_subnet6->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
}
else
addrp = &source->in6.sin6_addr;
}
else
#endif
{
opt->family = htons(1);
opt->source_netmask = daemon->addr4_netmask;
addrp = &source->in.sin_addr;
opt->source_netmask = daemon->add_subnet4->mask;
if (daemon->add_subnet4->addr_used)
{
sa_family = daemon->add_subnet4->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
}
else
addrp = &source->in.sin_addr;
}
opt->scope_netmask = 0;
@@ -656,6 +677,11 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
if (opt->source_netmask != 0)
{
#ifdef HAVE_IPV6
opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
#else
opt->family = htons(1);
#endif
len = ((opt->source_netmask - 1) >> 3) + 1;
memcpy(opt->addr, addrp, len);
if (opt->source_netmask & 7)
@@ -2335,4 +2361,3 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
return len;
}