Enhance --domain to accept, interface names for the address range.

This allows hosts get a domain which relects the interface they
are attached to in a way which doesn't require hard-coding addresses.

Thanks to Sten Spans for the idea.
This commit is contained in:
Simon Kelley
2022-03-05 18:07:07 +00:00
parent 4458d87289
commit 3ab6dd1c37
6 changed files with 92 additions and 11 deletions

View File

@@ -975,6 +975,8 @@ struct dhcp_bridge {
struct cond_domain {
char *domain, *prefix; /* prefix is text-prefix on domain name */
char *interface; /* These two set when domain comes from interface. */
struct addrlist *al;
struct in_addr start, end;
struct in6_addr start6, end6;
int is6, indexed, prefixlen;

View File

@@ -230,9 +230,17 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
static int match_domain(struct in_addr addr, struct cond_domain *c)
{
if (!c->is6 &&
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
if (c->interface)
{
struct addrlist *al;
for (al = c->al; al; al = al->next)
if (!(al->flags & ADDRLIST_IPV6) &&
is_same_net_prefix(addr, al->addr.addr4, al->prefixlen))
return 1;
}
else if (!c->is6 &&
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return 1;
return 0;
@@ -259,12 +267,21 @@ char *get_domain(struct in_addr addr)
static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
{
u64 addrpart = addr6part(addr);
if (c->is6)
/* subnet from interface address. */
if (c->interface)
{
struct addrlist *al;
for (al = c->al; al; al = al->next)
if (al->flags & ADDRLIST_IPV6 &&
is_same_net6(addr, &al->addr.addr6, al->prefixlen))
return 1;
}
else if (c->is6)
{
if (c->prefixlen >= 64)
{
u64 addrpart = addr6part(addr);
if (is_same_net6(addr, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
@@ -273,7 +290,7 @@ static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
else if (is_same_net6(addr, &c->start6, c->prefixlen))
return 1;
}
return 0;
}

View File

@@ -231,6 +231,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
{
struct irec *iface;
struct cond_domain *cond;
int loopback;
struct ifreq ifr;
int tftp_ok = !!option_bool(OPT_TFTP);
@@ -453,7 +454,37 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
}
}
}
/* Update addresses for domain=<domain>,<interface> */
for (cond = daemon->cond_domain; cond; cond = cond->next)
if (cond->interface && strncmp(label, cond->interface, IF_NAMESIZE) == 0)
{
struct addrlist *al;
if (param->spare)
{
al = param->spare;
param->spare = al->next;
}
else
al = whine_malloc(sizeof(struct addrlist));
if (addr->sa.sa_family == AF_INET)
{
al->addr.addr4 = addr->in.sin_addr;
al->flags = 0;
}
else
{
al->addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6;
}
al->prefixlen = prefixlen;
al->next = cond->al;
cond->al = al;
}
/* check whether the interface IP has been added already
we call this routine multiple times. */
for (iface = daemon->interfaces; iface; iface = iface->next)
@@ -691,6 +722,7 @@ int enumerate_interfaces(int reset)
int errsave, ret = 1;
struct addrlist *addr, *tmp;
struct interface_name *intname;
struct cond_domain *cond;
struct irec *iface;
#ifdef HAVE_AUTH
struct auth_zone *zone;
@@ -750,6 +782,19 @@ again:
intname->addr = NULL;
}
/* remove addresses stored against cond-domains. */
for (cond = daemon->cond_domain; cond; cond = cond->next)
{
for (addr = cond->al; addr; addr = tmp)
{
tmp = addr->next;
addr->next = spare;
spare = addr;
}
cond->al = NULL;
}
/* Remove list of addresses of local interfaces */
for (addr = daemon->interface_addrs; addr; addr = tmp)
{

View File

@@ -2492,9 +2492,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else if (!inet_pton(AF_INET6, arg, &new->end6))
ret_err_free(gen_err, new);
}
else
else if (option == 's')
{
/* subnet from interface. */
new->interface = opt_string_alloc(comma);
new->al = NULL;
}
else
ret_err_free(gen_err, new);
if (option != 's' && prefstr)
{
if (!(new->prefix = canonicalise_opt(prefstr)) ||