Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
D
Dnsmasq
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Dnsmasq
Commits
5f4dc5c6
Commit
5f4dc5c6
authored
Jan 20, 2015
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add --dhcp-hostsdir config option.
parent
2ae195f5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
177 additions
and
21 deletions
+177
-21
CHANGELOG
CHANGELOG
+5
-0
man/dnsmasq.8
man/dnsmasq.8
+9
-0
src/dnsmasq.c
src/dnsmasq.c
+20
-8
src/dnsmasq.h
src/dnsmasq.h
+11
-4
src/inotify.c
src/inotify.c
+113
-6
src/option.c
src/option.c
+19
-3
No files found.
CHANGELOG
View file @
5f4dc5c6
...
...
@@ -53,6 +53,11 @@ version 2.73
Cope with multiple interfaces with the same link-local
address. (IPv6 addresses are scoped, so this is allowed.)
Thanks to Cory Benfield for help with this.
Add --dhcp-hostsdir. This allows addition of new host
configurations to a running dnsmasq instance much more
cheaply than having dnsmasq re-read all its existing
configuration each time.
version 2.72
...
...
man/dnsmasq.8
View file @
5f4dc5c6
...
...
@@ -977,6 +977,15 @@ is given, then read all the files contained in that directory. The advantage of
using this option is the same as for --dhcp-hostsfile: the
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a
.TP
.B --dhcp-hostsdir=<path>
This is exactly equivalent to dhcp-hostfile, except for the following. The path MUST be a
directory, and not an individual file. Changed or new files within
the directory are read automatically, without the need to send SIGHUP.
If a file is deleted for changed after it has been read by dnsmasq, then the
host record it contained will remain until dnsmasq recieves a SIGHUP, or
is restarted; ie host records are only added dynamically.
.TP
.B --dhcp-boot
flag as DHCP options, using the options names bootfile-name,
server-ip-address and tftp-server. This allows these to be included
...
...
src/dnsmasq.c
View file @
5f4dc5c6
...
...
@@ -142,6 +142,9 @@ int main (int argc, char **argv)
set_option_bool
(
OPT_NOWILD
);
reset_option_bool
(
OPT_CLEVERBIND
);
}
if
(
daemon
->
inotify_hosts
)
die
(
_
(
"dhcp-hostsdir not supported on this platform"
),
NULL
,
EC_BADCONF
);
#endif
if
(
option_bool
(
OPT_DNSSEC_VALID
))
...
...
@@ -316,13 +319,16 @@ int main (int argc, char **argv)
#ifdef HAVE_DNSSEC
blockdata_init
();
#endif
}
#ifdef HAVE_LINUX_NETWORK
if
(
!
option_bool
(
OPT_NO_POLL
))
inotify_dnsmasq_init
();
if
((
!
option_bool
(
OPT_NO_POLL
)
&&
daemon
->
port
!=
0
)
||
daemon
->
dhcp
||
daemon
->
doing_dhcp6
)
inotify_dnsmasq_init
();
else
daemon
->
inotifyfd
=
-
1
;
#endif
}
if
(
option_bool
(
OPT_DBUS
))
#ifdef HAVE_DBUS
{
...
...
@@ -745,7 +751,7 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_TFTP
if
(
option_bool
(
OPT_TFTP
))
if
(
option_bool
(
OPT_TFTP
))
{
#ifdef FD_SETSIZE
if
(
FD_SETSIZE
<
(
unsigned
)
max_fd
)
...
...
@@ -870,7 +876,7 @@ int main (int argc, char **argv)
#if defined(HAVE_LINUX_NETWORK)
FD_SET
(
daemon
->
netlinkfd
,
&
rset
);
bump_maxfd
(
daemon
->
netlinkfd
,
&
maxfd
);
if
(
daemon
->
port
!=
0
&&
!
option_bool
(
OPT_NO_POLL
)
)
if
(
daemon
->
inotifyfd
!=
-
1
)
{
FD_SET
(
daemon
->
inotifyfd
,
&
rset
);
bump_maxfd
(
daemon
->
inotifyfd
,
&
maxfd
);
...
...
@@ -943,8 +949,11 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_LINUX_NETWORK
if
(
daemon
->
port
!=
0
&&
!
option_bool
(
OPT_NO_POLL
)
&&
FD_ISSET
(
daemon
->
inotifyfd
,
&
rset
)
&&
inotify_check
())
poll_resolv
(
1
,
1
,
now
);
if
(
daemon
->
inotifyfd
!=
-
1
&&
FD_ISSET
(
daemon
->
inotifyfd
,
&
rset
)
&&
inotify_check
(
now
))
{
if
(
daemon
->
port
!=
0
&&
!
option_bool
(
OPT_NO_POLL
))
poll_resolv
(
1
,
1
,
now
);
}
#else
/* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */
...
...
@@ -1385,6 +1394,9 @@ void clear_cache_and_reload(time_t now)
if
(
option_bool
(
OPT_ETHERS
))
dhcp_read_ethers
();
reread_dhcp
();
#ifdef HAVE_LINUX_NETWORK
set_dhcp_inotify
();
#endif
dhcp_update_configs
(
daemon
->
dhcp_conf
);
lease_update_from_configs
();
lease_update_file
(
now
);
...
...
src/dnsmasq.h
View file @
5f4dc5c6
...
...
@@ -550,13 +550,17 @@ struct resolvc {
#endif
};
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile
and dhcp-hostsdir
*/
#define AH_DIR 1
#define AH_INACTIVE 2
#define AH_WD_DONE 4
struct
hostsfile
{
struct
hostsfile
*
next
;
int
flags
;
char
*
fname
;
#ifdef HAVE_LINUX_NETWORK
int
wd
;
/* inotify watch descriptor */
#endif
unsigned
int
index
;
/* matches to cache entries for logging */
};
...
...
@@ -961,7 +965,7 @@ extern struct daemon {
int
doing_ra
,
doing_dhcp6
;
struct
dhcp_netid_list
*
dhcp_ignore
,
*
dhcp_ignore_names
,
*
dhcp_gen_names
;
struct
dhcp_netid_list
*
force_broadcast
,
*
bootp_dynamic
;
struct
hostsfile
*
dhcp_hosts_file
,
*
dhcp_opts_file
;
struct
hostsfile
*
dhcp_hosts_file
,
*
dhcp_opts_file
,
*
inotify_hosts
;
int
dhcp_max
,
tftp_max
;
int
dhcp_server_port
,
dhcp_client_port
;
int
start_tftp_port
,
end_tftp_port
;
...
...
@@ -1197,7 +1201,7 @@ void reset_option_bool(unsigned int opt);
struct
hostsfile
*
expand_filelist
(
struct
hostsfile
*
list
);
char
*
parse_server
(
char
*
arg
,
union
mysockaddr
*
addr
,
union
mysockaddr
*
source_addr
,
char
*
interface
,
int
*
flags
);
int
option_read_hostsfile
(
char
*
file
);
/* forward.c */
void
reply_query
(
int
fd
,
int
family
,
time_t
now
);
void
receive_query
(
struct
listener
*
listen
,
time_t
now
);
...
...
@@ -1486,5 +1490,8 @@ int detect_loop(char *query, int type);
/* inotify.c */
#ifdef HAVE_LINUX_NETWORK
void
inotify_dnsmasq_init
();
int
inotify_check
(
void
);
int
inotify_check
(
time_t
now
);
# ifdef HAVE_DHCP
void
set_dhcp_inotify
(
void
);
# endif
#endif
src/inotify.c
View file @
5f4dc5c6
...
...
@@ -19,6 +19,11 @@
#include <sys/inotify.h>
#ifdef HAVE_DHCP
static
void
check_for_dhcp_inotify
(
struct
inotify_event
*
in
,
time_t
now
);
#endif
/* the strategy is to set a inotify on the directories containing
resolv files, for any files in the directory which are close-write
or moved into the directory.
...
...
@@ -40,8 +45,6 @@ void inotify_dnsmasq_init()
struct
resolvc
*
res
;
inotify_buffer
=
safe_malloc
(
INOTIFY_SZ
);
daemon
->
inotifyfd
=
inotify_init1
(
IN_NONBLOCK
|
IN_CLOEXEC
);
if
(
daemon
->
inotifyfd
==
-
1
)
...
...
@@ -66,6 +69,7 @@ void inotify_dnsmasq_init()
{
*
d
=
0
;
/* make path just directory */
res
->
wd
=
inotify_add_watch
(
daemon
->
inotifyfd
,
path
,
IN_CLOSE_WRITE
|
IN_MOVED_TO
);
res
->
file
=
d
+
1
;
/* pointer to filename */
*
d
=
'/'
;
...
...
@@ -78,7 +82,7 @@ void inotify_dnsmasq_init()
}
}
int
inotify_check
(
void
)
int
inotify_check
(
time_t
now
)
{
int
hit
=
0
;
...
...
@@ -101,13 +105,116 @@ int inotify_check(void)
for
(
res
=
daemon
->
resolv_files
;
res
;
res
=
res
->
next
)
if
(
res
->
wd
==
in
->
wd
&&
in
->
len
!=
0
&&
strcmp
(
res
->
file
,
in
->
name
)
==
0
)
hit
=
1
;
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
||
daemon
->
doing_dhcp6
)
check_for_dhcp_inotify
(
in
,
now
);
#endif
}
}
return
hit
;
}
#endif
#ifdef HAVE_DHCP
/* initialisation for dhcp-hostdir. Set inotify watch for each directory, and read pre-existing files */
void
set_dhcp_inotify
(
void
)
{
struct
hostsfile
*
ah
;
for
(
ah
=
daemon
->
inotify_hosts
;
ah
;
ah
=
ah
->
next
)
{
DIR
*
dir_stream
=
NULL
;
struct
dirent
*
ent
;
struct
stat
buf
;
if
(
stat
(
ah
->
fname
,
&
buf
)
==
-
1
||
!
(
S_ISDIR
(
buf
.
st_mode
)))
{
my_syslog
(
LOG_ERR
,
_
(
"bad directory in dhcp-hostsdir %s"
),
ah
->
fname
);
continue
;
}
if
(
!
(
ah
->
flags
&
AH_WD_DONE
))
{
ah
->
wd
=
inotify_add_watch
(
daemon
->
inotifyfd
,
ah
->
fname
,
IN_CLOSE_WRITE
|
IN_MOVED_TO
);
ah
->
flags
|=
AH_WD_DONE
;
}
/* Read contents of dir _after_ calling add_watch, in the ho[e of avoiding
a race which misses files being added as we start */
if
(
ah
->
wd
==
-
1
||
!
(
dir_stream
=
opendir
(
ah
->
fname
)))
{
my_syslog
(
LOG_ERR
,
_
(
"failed to create inotify for %s"
),
ah
->
fname
);
continue
;
}
while
((
ent
=
readdir
(
dir_stream
)))
{
size_t
lendir
=
strlen
(
ah
->
fname
);
size_t
lenfile
=
strlen
(
ent
->
d_name
);
char
*
path
;
/* ignore emacs backups and dotfiles */
if
(
lenfile
==
0
||
ent
->
d_name
[
lenfile
-
1
]
==
'~'
||
(
ent
->
d_name
[
0
]
==
'#'
&&
ent
->
d_name
[
lenfile
-
1
]
==
'#'
)
||
ent
->
d_name
[
0
]
==
'.'
)
continue
;
if
((
path
=
whine_malloc
(
lendir
+
lenfile
+
2
)))
{
strcpy
(
path
,
ah
->
fname
);
strcat
(
path
,
"/"
);
strcat
(
path
,
ent
->
d_name
);
/* ignore non-regular files */
if
(
stat
(
path
,
&
buf
)
!=
-
1
&&
S_ISREG
(
buf
.
st_mode
))
option_read_hostsfile
(
path
);
free
(
path
);
}
}
}
}
static
void
check_for_dhcp_inotify
(
struct
inotify_event
*
in
,
time_t
now
)
{
struct
hostsfile
*
ah
;
/* ignore emacs backups and dotfiles */
if
(
in
->
len
==
0
||
in
->
name
[
in
->
len
-
1
]
==
'~'
||
(
in
->
name
[
0
]
==
'#'
&&
in
->
name
[
in
->
len
-
1
]
==
'#'
)
||
in
->
name
[
0
]
==
'.'
)
return
;
for
(
ah
=
daemon
->
inotify_hosts
;
ah
;
ah
=
ah
->
next
)
if
(
ah
->
wd
==
in
->
wd
)
{
size_t
lendir
=
strlen
(
ah
->
fname
);
char
*
path
;
if
((
path
=
whine_malloc
(
lendir
+
in
->
len
+
2
)))
{
strcpy
(
path
,
ah
->
fname
);
strcat
(
path
,
"/"
);
strcat
(
path
,
in
->
name
);
if
(
option_read_hostsfile
(
path
))
{
/* Propogate the consequences of loading a new dhcp-host */
dhcp_update_configs
(
daemon
->
dhcp_conf
);
lease_update_from_configs
();
lease_update_file
(
now
);
lease_update_dns
(
1
);
}
free
(
path
);
}
return
;
}
}
#endif
/* DHCP */
#endif
/* LINUX_NETWORK */
src/option.c
View file @
5f4dc5c6
...
...
@@ -149,7 +149,7 @@ struct myoption {
#define LOPT_LOOP_DETECT 337
#define LOPT_IGNORE_ADDR 338
#define LOPT_MINCTTL 339
#define LOPT_DHCP_INOTIFY 340
#ifdef HAVE_GETOPT_LONG
static
const
struct
option
opts
[]
=
...
...
@@ -248,6 +248,7 @@ static const struct myoption opts[] =
{
"interface-name"
,
1
,
0
,
LOPT_INTNAME
},
{
"dhcp-hostsfile"
,
1
,
0
,
LOPT_DHCP_HOST
},
{
"dhcp-optsfile"
,
1
,
0
,
LOPT_DHCP_OPTS
},
{
"dhcp-hostsdir"
,
1
,
0
,
LOPT_DHCP_INOTIFY
},
{
"dhcp-no-override"
,
0
,
0
,
LOPT_OVERRIDE
},
{
"tftp-port-range"
,
1
,
0
,
LOPT_TFTPPORTS
},
{
"stop-dns-rebind"
,
0
,
0
,
LOPT_REBIND
},
...
...
@@ -336,6 +337,7 @@ static struct {
{
'G'
,
ARG_DUP
,
"<hostspec>"
,
gettext_noop
(
"Set address or hostname for a specified machine."
),
NULL
},
{
LOPT_DHCP_HOST
,
ARG_DUP
,
"<path>"
,
gettext_noop
(
"Read DHCP host specs from file."
),
NULL
},
{
LOPT_DHCP_OPTS
,
ARG_DUP
,
"<path>"
,
gettext_noop
(
"Read DHCP option specs from file."
),
NULL
},
{
LOPT_DHCP_INOTIFY
,
ARG_DUP
,
"<path>"
,
gettext_noop
(
"Read DHCP host specs from a directory."
),
NULL
},
{
LOPT_TAG_IF
,
ARG_DUP
,
"tag-expression"
,
gettext_noop
(
"Evaluate conditional tag expression."
),
NULL
},
{
'h'
,
OPT_NO_HOSTS
,
NULL
,
gettext_noop
(
"Do NOT load %s file."
),
HOSTSFILE
},
{
'H'
,
ARG_DUP
,
"<path>"
,
gettext_noop
(
"Specify a hosts file to be read in addition to %s."
),
HOSTSFILE
},
...
...
@@ -1710,8 +1712,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break
;
#endif
/* HAVE_DHCP */
case
LOPT_DHCP_HOST
:
/* --dhcp-hostfile */
case
LOPT_DHCP_HOST
:
/* --dhcp-host
s
file */
case
LOPT_DHCP_OPTS
:
/* --dhcp-optsfile */
case
LOPT_DHCP_INOTIFY
:
/* dhcp-hostsdir */
case
'H'
:
/* --addn-hosts */
{
struct
hostsfile
*
new
=
opt_malloc
(
sizeof
(
struct
hostsfile
));
...
...
@@ -1734,6 +1737,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new
->
next
=
daemon
->
dhcp_opts_file
;
daemon
->
dhcp_opts_file
=
new
;
}
else
if
(
option
==
LOPT_DHCP_INOTIFY
)
{
new
->
next
=
daemon
->
inotify_hosts
;
daemon
->
inotify_hosts
=
new
;
}
break
;
}
...
...
@@ -4042,6 +4051,13 @@ static void read_file(char *file, FILE *f, int hard_opt)
fclose
(
f
);
}
#ifdef HAVE_DHCP
int
option_read_hostsfile
(
char
*
file
)
{
return
one_file
(
file
,
LOPT_BANK
);
}
#endif
static
int
one_file
(
char
*
file
,
int
hard_opt
)
{
FILE
*
f
;
...
...
@@ -4139,7 +4155,7 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
/* don't read this as a file */
ah
->
flags
|=
AH_INACTIVE
;
if
(
!
(
dir_stream
=
opendir
(
ah
->
fname
)))
my_syslog
(
LOG_ERR
,
_
(
"cannot access directory %s: %s"
),
ah
->
fname
,
strerror
(
errno
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment