Add --no-dhcpv4-interface and --no-dhcpv6-interface options.

This commit is contained in:
Simon Kelley
2023-04-12 22:55:14 +01:00
parent 597378cdf5
commit aaba66efbd
10 changed files with 51 additions and 15 deletions

View File

@@ -15,6 +15,9 @@ version 2.90
for IPv6. It's still possible to override this with
--edns-packet-max for special circumstances.
Add --no-dhcpv4-interface and --no-dhcpv6-interface for
better control over which inetrfaces are providing DHCP service.
version 2.89
Fix bug introduced in 2.88 (commit fe91134b) which can result

View File

@@ -279,7 +279,14 @@ a default on installation, to allow unconfigured installations to be
useful but also safe from being used for DNS amplification attacks.
.TP
.B \-2, --no-dhcp-interface=<interface name>
Do not provide DHCP or TFTP on the specified interface, but do provide DNS service.
Do not provide DHCP, TFTP or router advertisement on the specified interface, but do provide DNS service.
.TP
.B --no-dhcpv4-interface=<interface name>
Disable only IPv4 DHCP on the specified interface.
.TP
.B
--no-dhcpv6-interface=<interface name>
Disable IPv6 DHCP and router advertisement on the specified interface.
.TP
.B \-a, --listen-address=<ipaddr>
Listen on the given IP address(es). Both

View File

@@ -557,7 +557,7 @@ char *whichdevice(void)
return NULL;
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
if (iface->dhcp_ok)
if (iface->dhcp4_ok || iface->dhcp6_ok)
{
if (!found)
found = iface;

View File

@@ -297,7 +297,7 @@ void dhcp_packet(time_t now, int pxe_fd)
}
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
if (tmp->name && (tmp->flags & INAME_4) && wildcard_match(tmp->name, ifr.ifr_name))
return;
/* unlinked contexts/relays are marked by context->current == context */

View File

@@ -159,7 +159,8 @@ void dhcp6_packet(time_t now)
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
if (tmp->name && (tmp->flags & INAME_6) &&
wildcard_match(tmp->name, ifr.ifr_name))
return;
parm.current = NULL;

View File

@@ -648,7 +648,8 @@ struct allowlist {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
int tftp_ok, dhcp4_ok, dhcp6_ok, mtu, done, warned, dad;
int dns_auth, index, multicast_done, found, label;
char *name;
struct irec *next;
};
@@ -669,6 +670,8 @@ struct iname {
};
#define INAME_USED 1
#define INAME_4 2
#define INAME_6 4
struct rrlist {
unsigned short rr;

View File

@@ -244,7 +244,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
int loopback;
struct ifreq ifr;
int tftp_ok = !!option_bool(OPT_TFTP);
int dhcp_ok = 1;
int dhcp4_ok = 1;
int dhcp6_ok = 1;
int auth_dns = 0;
int is_label = 0;
#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
@@ -260,7 +261,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
loopback = ifr.ifr_flags & IFF_LOOPBACK;
if (loopback)
dhcp_ok = 0;
dhcp4_ok = dhcp6_ok = 0;
if (!label)
label = ifr.ifr_name;
@@ -532,14 +533,17 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
if (auth_dns)
{
tftp_ok = 0;
dhcp_ok = 0;
dhcp4_ok = dhcp6_ok = 0;
}
else
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
{
tftp_ok = 0;
dhcp_ok = 0;
if (tmp->flags & INAME_4)
dhcp4_ok = 0;
if (tmp->flags & INAME_6)
dhcp6_ok = 0;
}
#endif
@@ -566,7 +570,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
iface->addr = *addr;
iface->netmask = netmask;
iface->tftp_ok = tftp_ok;
iface->dhcp_ok = dhcp_ok;
iface->dhcp4_ok = dhcp4_ok;
iface->dhcp6_ok = dhcp6_ok;
iface->dns_auth = auth_dns;
iface->mtu = mtu;
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
@@ -1295,7 +1300,7 @@ void join_multicast(int dienow)
struct irec *iface, *tmp;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp6_ok && !iface->multicast_done)
{
/* There's an irec per address but we only want to join for multicast
once per interface. Weed out duplicates. */

View File

@@ -188,6 +188,8 @@ struct myoption {
#define LOPT_NO_IDENT 379
#define LOPT_CACHE_RR 380
#define LOPT_FILTER_RR 381
#define LOPT_NO_DHCP6 382
#define LOPT_NO_DHCP4 383
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -248,6 +250,8 @@ static const struct myoption opts[] =
{ "query-port", 1, 0, 'Q' },
{ "except-interface", 1, 0, 'I' },
{ "no-dhcp-interface", 1, 0, '2' },
{ "no-dhcpv4-interface", 1, 0, LOPT_NO_DHCP4 },
{ "no-dhcpv6-interface", 1, 0, LOPT_NO_DHCP6 },
{ "domain-needed", 0, 0, 'D' },
{ "dhcp-lease-max", 1, 0, 'X' },
{ "bind-interfaces", 0, 0, 'z' },
@@ -478,6 +482,8 @@ static struct {
{ '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
{ LOPT_UBUS, ARG_ONE, "[=<busname>]", gettext_noop("Enable the UBus interface."), NULL },
{ '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
{ LOPT_NO_DHCP6, ARG_DUP, "<interface>", gettext_noop("Do not provide DHCPv6 on this interface."), NULL },
{ LOPT_NO_DHCP4, ARG_DUP, "<interface>", gettext_noop("Do not provide DHCPv4 on this interface."), NULL },
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
{ LOPT_BRIDGE, ARG_DUP, "<iface>,<alias>..", gettext_noop("Treat DHCP requests on aliases as arriving from interface."), NULL },
@@ -2846,10 +2852,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case 'I': /* --except-interface */
case '2': /* --no-dhcp-interface */
case LOPT_NO_DHCP6: /* --no-dhcpv6-interface */
case LOPT_NO_DHCP4: /* --no-dhcpv4-interface */
do {
struct iname *new = opt_malloc(sizeof(struct iname));
comma = split(arg);
new->name = opt_string_alloc(arg);
new->flags = INAME_4 | INAME_6;
if (option == 'I')
{
new->next = daemon->if_except;
@@ -2862,6 +2871,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
else
{
if (option == LOPT_NO_DHCP6)
new->flags &= ~INAME_4;
if (option == LOPT_NO_DHCP4)
new->flags &= ~INAME_6;
new->next = daemon->dhcp_except;
daemon->dhcp_except = new;
}

View File

@@ -186,7 +186,8 @@ void icmp6_packet(time_t now)
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, interface))
if (tmp->name && (tmp->flags & INAME_6) &&
wildcard_match(tmp->name, interface))
return;
if (packet[1] != 0)
@@ -835,7 +836,8 @@ time_t periodic_ra(time_t now)
{
struct iname *tmp;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, param.name))
if (tmp->name && (tmp->flags & INAME_6) &&
wildcard_match(tmp->name, param.name))
break;
if (!tmp)
{
@@ -934,7 +936,8 @@ static int iface_search(struct in6_addr *local, int prefix,
return 1;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, param->name))
if (tmp->name && (tmp->flags & INAME_6) &&
wildcard_match(tmp->name, param->name))
return 1;
for (context = daemon->dhcp6; context; context = context->next)

View File

@@ -228,7 +228,8 @@ void tftp_request(struct listener *listen, time_t now)
#ifdef HAVE_DHCP
/* allowed interfaces are the same as for DHCP */
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, name))
if (tmp->name && (tmp->flags & (INAME_4 | INAME_6) == (INAME_4 | INAME_6)) &&
wildcard_match(tmp->name, name))
return;
#endif
}