summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2023-04-12 22:55:14 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2023-04-12 22:55:14 +0100
commitaaba66efbd3b4e7283993ca3718df47706a8549b (patch)
treee17877af52d9ae0e71c3294127ad46a642f813f3
parent597378cdf55b248a54b930fa31acbad7415aaefd (diff)
downloaddnsmasq-aaba66efbd3b4e7283993ca3718df47706a8549b.tar.gz
Add --no-dhcpv4-interface and --no-dhcpv6-interface options.
-rw-r--r--CHANGELOG3
-rw-r--r--man/dnsmasq.89
-rw-r--r--src/dhcp-common.c2
-rw-r--r--src/dhcp.c2
-rw-r--r--src/dhcp6.c3
-rw-r--r--src/dnsmasq.h5
-rw-r--r--src/network.c17
-rw-r--r--src/option.c13
-rw-r--r--src/radv.c9
-rw-r--r--src/tftp.c3
10 files changed, 51 insertions, 15 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 52d8678..c0694eb 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index 37aea60..30429df 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -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
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index 360cdc5..b004e40 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -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;
diff --git a/src/dhcp.c b/src/dhcp.c
index 7126b29..c7dd33b 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -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 */
diff --git a/src/dhcp6.c b/src/dhcp6.c
index 9ae92da..7eeef03 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -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;
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 2a57969..2f95c12 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -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;
diff --git a/src/network.c b/src/network.c
index 9c5c613..ca9fada 100644
--- a/src/network.c
+++ b/src/network.c
@@ -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. */
diff --git a/src/option.c b/src/option.c
index 94bc682..8322725 100644
--- a/src/option.c
+++ b/src/option.c
@@ -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;
}
diff --git a/src/radv.c b/src/radv.c
index 49b41d8..a4af344 100644
--- a/src/radv.c
+++ b/src/radv.c
@@ -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)
diff --git a/src/tftp.c b/src/tftp.c
index 8bbaea0..caf077f 100644
--- a/src/tftp.c
+++ b/src/tftp.c
@@ -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
}