Compare commits

...
10 Commits
Author SHA1 Message Date
Simon Kelley e426c2d3bc Add --conf-script 2022-02-08 12:10:27 +00:00
Simon Kelley 6279d9eaf3 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-04 22:28:53 +00:00
Simon Kelley 12949aa0c0 Ask netlink for new address events unconditionally.
The circumstances under which actions occur depending on
configuration is now controlled only by newaddress() in network.c
2022-02-04 22:24:00 +00:00
Simon Kelley 84f3357dd9 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-04 21:00:16 +00:00
Johnny S. Lee via Dnsmasq-discuss 4333d5d93a Fix FTBFS on BSD platforms.
Bug introduced in fc664d114d
2022-02-03 23:42:00 +00:00
Simon Kelley fa580ad3eb Handle changing interface indexes when binding DHCP sockets. 2022-02-03 17:26:28 +00:00
Simon Kelley 292dfa653e Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2022-02-02 18:31:22 +00:00
Simon Kelley bf1fc6c6fd Tidy iface_check(). 2022-01-21 15:47:09 +00:00
Olaf Hering b18e9c8c61 fix dnsmasq typo in man page
Fixes commit 27ce754b3d

Signed-off-by: Olaf Hering <olaf@aepfle.de>
2022-01-21 12:18:08 +00:00
Simon Kelley a3293bb242 Fix indentation in Umbrella option code. 2022-01-21 12:07:42 +00:00
9 changed files with 183 additions and 85 deletions

No files matched your search

+10
View File
@@ -39,6 +39,16 @@ version 2.87
a local NODATA answer. The pre-2.86 behaviour is still available,
by configuring --address=/example.com/1.2.3.4 --local=/example.com/
Fix problem with binding DHCP sockets to an individual interface.
Despite the fact that the system call tales the interface _name_ as
a parameter, it actually, binds the socket to interface _index_.
Deleting the interface and creating a new one with the same name
leaves the socket bound to the old index. (Creating new sockets
always allocates a fresh index, they are not reused). We now
take this behaviour into account and keep up with changing indexes.
Add --conf-script configuration option.
version 2.86
Handle DHCPREBIND requests in the DHCPv6 server code.
+21 -2
View File
@@ -777,7 +777,7 @@ will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
.TP
.B --strip-subnet
Remove any subnet address already present in a downstream query before forwarding it upstream. If --add-subnet is set this also
ensures that any downstream-provided subnet is replaced by the one added by dnsmasq. Otherwise, dnsmaaq will NOT replace an
ensures that any downstream-provided subnet is replaced by the one added by dnsmasq. Otherwise, dnsmasq will NOT replace an
existing subnet in the query.
.TP
.B --umbrella[=[deviceid:<deviceid>][,orgid:<orgid>][,assetid:<id>]]
@@ -2141,6 +2141,23 @@ A special case of
which differs in two respects. Firstly, only \fB--server\fP and \fB--rev-server\fP are allowed
in the configuration file included. Secondly, the file is re-read and the configuration
therein is updated when dnsmasq receives SIGHUP.
.TP
.B \--conf-script=<file>[ <arg]
Execute <file>, and treat what it emits to stdout as the contents of a configuration file.
If the script exits with a non-zero exit code, dnsmasq treats this as a fatal error.
The script can be passed arguments, space seperated from the filename and each other so, for instance
.B --conf-dir="/etc/dnsmasq-uncompress-ads /share/ads-domains.gz"
with /etc/dnsmasq-uncompress-ads containing
set -e
zcat ${1} | sed -e "s:^:address=/:" -e "s:$:/:"
exit 0
and /share/ads-domains.gz containing a compressed
list of ad server domains will save disk space with large ad-server blocklists.
.SH CONFIG FILE
At startup, dnsmasq reads
.I /etc/dnsmasq.conf,
@@ -2537,7 +2554,9 @@ file/directory, permissions).
5 - Other miscellaneous problem.
.PP
11 or greater - a non zero return code was received from the
lease-script process "init" call. The exit code from dnsmasq is the
lease-script process "init" call or a
.B \--conf-script
file. The exit code from dnsmasq is the
script's exit code with 10 added.
.SH LIMITS
+34 -4
View File
@@ -566,12 +566,16 @@ char *whichdevice(void)
}
if (found)
return found->name;
{
char *ret = safe_malloc(strlen(found->name)+1);
strcpy(ret, found->name);
return ret;
}
return NULL;
}
void bindtodevice(char *device, int fd)
static int bindtodevice(char *device, int fd)
{
size_t len = strlen(device)+1;
if (len > IFNAMSIZ)
@@ -579,7 +583,33 @@ void bindtodevice(char *device, int fd)
/* only allowed by root. */
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
errno != EPERM)
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
return 2;
return 1;
}
int bind_dhcp_devices(char *bound_device)
{
int ret = 0;
if (bound_device)
{
if (daemon->dhcp)
{
if (!daemon->relay4)
ret |= bindtodevice(bound_device, daemon->dhcpfd);
if (daemon->enable_pxe && daemon->pxefd != -1)
ret |= bindtodevice(bound_device, daemon->pxefd);
}
#if defined(HAVE_DHCP6)
if (daemon->doing_dhcp6 && !daemon->relay6)
ret |= bindtodevice(bound_device, daemon->dhcp6fd);
#endif
}
return ret;
}
#endif
+5 -2
View File
@@ -458,9 +458,12 @@ void dhcp_packet(time_t now, int pxe_fd)
else
{
#ifdef HAVE_DUMPFILE
dest.sin_addr.s_addr = (ntohs(mess->flags) & 0x8000) ? INADDR_BROADCAST : mess->yiaddr;
if (ntohs(mess->flags) & 0x8000)
dest.sin_addr.s_addr = INADDR_BROADCAST;
else
dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(daemon->dhcp_client_port);
dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
(union mysockaddr *)&dest, daemon->dhcp_server_port);
#endif
+13 -21
View File
@@ -387,28 +387,9 @@ int main (int argc, char **argv)
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
/* after enumerate_interfaces() */
bound_device = whichdevice();
if (daemon->dhcp)
{
if (!daemon->relay4 && bound_device)
{
bindtodevice(bound_device, daemon->dhcpfd);
did_bind = 1;
}
if (daemon->enable_pxe && bound_device && daemon->pxefd != -1)
{
bindtodevice(bound_device, daemon->pxefd);
did_bind = 1;
}
}
#endif
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
{
bindtodevice(bound_device, daemon->dhcp6fd);
did_bind = 1;
}
if ((did_bind = bind_dhcp_devices(bound_device)) & 2)
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
#endif
}
else
@@ -1100,6 +1081,17 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_DHCP
# if defined(HAVE_LINUX_NETWORK)
if (bind_dhcp_devices(bound_device) & 2)
{
static int warned = 0;
if (!warned)
{
my_syslog(LOG_ERR, _("error binding DHCP socket to device %s"), bound_device);
warned = 1;
}
}
# endif
if (daemon->dhcp || daemon->relay4)
{
poll_listen(daemon->dhcpfd, POLLIN);
+1 -1
View File
@@ -1715,7 +1715,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
#ifdef HAVE_LINUX_NETWORK
char *whichdevice(void);
void bindtodevice(char *device, int fd);
int bind_dhcp_devices(char *bound_device);
#endif
# ifdef HAVE_DHCP6
void display_opts6(void);
+2 -9
View File
@@ -66,17 +66,10 @@ char *netlink_init(void)
addr.nl_pad = 0;
addr.nl_pid = 0; /* autobind */
addr.nl_groups = RTMGRP_IPV4_ROUTE;
if (option_bool(OPT_CLEVERBIND))
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
if (option_bool(OPT_CLEVERBIND))
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
#ifdef HAVE_DHCP6
if (daemon->doing_ra || daemon->doing_dhcp6)
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
#endif
/* May not be able to have permission to set multicast groups don't die in that case */
if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1)
{
+24 -25
View File
@@ -114,13 +114,8 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
struct iname *tmp;
int ret = 1, match_addr = 0;
/* Note: have to check all and not bail out early, so that we set the
"used" flags.
May be called with family == AF_LOCALto check interface by name only. */
if (auth)
*auth = 0;
/* Note: have to check all and not bail out early, so that we set the "used" flags.
May be called with family == AF_LOCAL to check interface by name only. */
if (daemon->if_names || daemon->if_addrs)
{
@@ -149,25 +144,29 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
if (tmp->name && wildcard_match(tmp->name, name))
ret = 0;
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
if (tmp->name)
{
if (strcmp(tmp->name, name) == 0 &&
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
break;
}
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
break;
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
break;
if (tmp && auth)
if (auth)
{
*auth = 1;
ret = 1;
*auth = 0;
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
if (tmp->name)
{
if (strcmp(tmp->name, name) == 0 &&
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
break;
}
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
break;
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
break;
if (tmp)
{
*auth = 1;
ret = 1;
}
}
return ret;
+73 -21
View File
@@ -179,6 +179,8 @@ struct myoption {
#define LOPT_FILTER_AAAA 370
#define LOPT_STRIP_SBNET 371
#define LOPT_STRIP_MAC 372
#define LOPT_CONF_OPT 373
#define LOPT_CONF_SCRIPT 374
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -225,6 +227,7 @@ static const struct myoption opts[] =
{ "local", 1, 0, LOPT_LOCAL },
{ "address", 1, 0, 'A' },
{ "conf-file", 2, 0, 'C' },
{ "conf-script", 1, 0, LOPT_CONF_SCRIPT },
{ "no-resolv", 0, 0, 'R' },
{ "expand-hosts", 0, 0, 'E' },
{ "localmx", 0, 0, 'L' },
@@ -467,6 +470,7 @@ static struct {
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
{ LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL },
{ '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
{ LOPT_CONF_SCRIPT, ARG_DUP, "<path>", gettext_noop("Execute file and read configuration from stdin."), NULL },
{ '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
{ '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
@@ -1810,6 +1814,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break;
}
case LOPT_CONF_SCRIPT: /* --conf-script */
{
char *file = opt_string_alloc(arg);
if (file)
{
one_file(file, LOPT_CONF_SCRIPT);
free(file);
}
break;
}
case '7': /* --conf-dir */
{
DIR *dir_stream;
@@ -2537,13 +2552,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
arg += 9;
if (strlen(arg) != 16)
ret_err(gen_err);
for (p = arg; *p; p++)
if (!isxdigit((int)*p))
ret_err(gen_err);
set_option_bool(OPT_UMBRELLA_DEVID);
for (i = 0; i < (int)sizeof(daemon->umbrella_device); i++, arg+=2)
{
memcpy(word, &(arg[0]), 2);
@@ -2555,13 +2570,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (!strtoul_check(arg+6, &daemon->umbrella_org))
ret_err(gen_err);
}
else if (strstr(arg, "assetid:"))
{
if (!strtoul_check(arg+8, &daemon->umbrella_asset))
ret_err(gen_err);
}
else
ret_err(gen_err);
else if (strstr(arg, "assetid:"))
{
if (!strtoul_check(arg+8, &daemon->umbrella_asset))
ret_err(gen_err);
}
else
ret_err(gen_err);
arg = comma;
}
@@ -4966,11 +4981,19 @@ static void read_file(char *file, FILE *f, int hard_opt)
while (fgets(buff, MAXDNAME, f))
{
int white, i;
volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
int white, i, script = 0;
volatile int option;
char *errmess, *p, *arg, *start;
size_t len;
if (hard_opt == LOPT_CONF_SCRIPT)
{
hard_opt = 0;
script = 1;
}
option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
/* Memory allocation failure longjmps here if mem_recover == 1 */
if (option != 0 || hard_opt == LOPT_REV_SERV)
{
@@ -5084,7 +5107,11 @@ static void read_file(char *file, FILE *f, int hard_opt)
if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
{
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (script)
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" in output from %s"), file);
else
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
if (hard_opt != 0)
my_syslog(LOG_ERR, "%s", daemon->namebuff);
else
@@ -5093,7 +5120,6 @@ static void read_file(char *file, FILE *f, int hard_opt)
}
mem_recover = 0;
fclose(f);
}
#if defined(HAVE_DHCP) && defined(HAVE_INOTIFY)
@@ -5113,7 +5139,7 @@ int option_read_dynfile(char *file, int flags)
static int one_file(char *file, int hard_opt)
{
FILE *f;
int nofile_ok = 0;
int nofile_ok = 0, do_popen = 0;
static int read_stdin = 0;
static struct fileread {
dev_t dev;
@@ -5121,13 +5147,13 @@ static int one_file(char *file, int hard_opt)
struct fileread *next;
} *filesread = NULL;
if (hard_opt == '7')
if (hard_opt == LOPT_CONF_OPT)
{
/* default conf-file reading */
hard_opt = 0;
nofile_ok = 1;
}
if (hard_opt == 0 && strcmp(file, "-") == 0)
{
if (read_stdin == 1)
@@ -5141,6 +5167,12 @@ static int one_file(char *file, int hard_opt)
/* ignore repeated files. */
struct stat statbuf;
if (hard_opt == LOPT_CONF_SCRIPT)
{
hard_opt = 0;
do_popen = 1;
}
if (hard_opt == 0 && stat(file, &statbuf) == 0)
{
struct fileread *r;
@@ -5155,8 +5187,13 @@ static int one_file(char *file, int hard_opt)
r->dev = statbuf.st_dev;
r->ino = statbuf.st_ino;
}
if (!(f = fopen(file, "r")))
if (do_popen)
{
if (!(f = popen(file, "r")))
die(_("cannot execute %s: %s"), file, EC_FILE);
}
else if (!(f = fopen(file, "r")))
{
if (errno == ENOENT && nofile_ok)
return 1; /* No conffile, all done. */
@@ -5174,7 +5211,21 @@ static int one_file(char *file, int hard_opt)
}
}
read_file(file, f, hard_opt);
read_file(file, f, do_popen ? LOPT_CONF_SCRIPT : hard_opt);
if (do_popen)
{
int rc;
if ((rc = pclose(f)) == -1)
die(_("error executing %s: %s"), file, EC_MISC);
if (rc != 0)
die(_("%s returns non-zero error code"), file, rc+10);
}
else
fclose(f);
return 1;
}
@@ -5315,6 +5366,7 @@ void read_servers_file(void)
mark_servers(SERV_FROM_FILE);
read_file(daemon->servers_file, f, LOPT_REV_SERV);
fclose(f);
cleanup_servers();
check_servers(0);
}
@@ -5540,7 +5592,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
free(conffile);
}
else
one_file(CONFFILE, '7');
one_file(CONFFILE, LOPT_CONF_OPT);
/* port might not be known when the address is parsed - fill in here */
if (daemon->servers)