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
54dd393f
Commit
54dd393f
authored
Jun 20, 2012
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add --bind-dynamic
parent
4ce4f377
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
128 additions
and
74 deletions
+128
-74
CHANGELOG
CHANGELOG
+4
-0
man/dnsmasq.8
man/dnsmasq.8
+11
-0
src/dhcp.c
src/dhcp.c
+1
-1
src/dnsmasq.c
src/dnsmasq.c
+18
-10
src/dnsmasq.h
src/dnsmasq.h
+2
-1
src/forward.c
src/forward.c
+4
-4
src/netlink.c
src/netlink.c
+85
-58
src/option.c
src/option.c
+3
-0
No files found.
CHANGELOG
View file @
54dd393f
...
...
@@ -7,6 +7,10 @@ version 2.63
Allow more than one --tfp-root flag. The per-interface
stuff is pointless without that.
Add --bind-dynamic. A hybrid mode between the default and
--bind-interfaces which copes with dynamically created
interfaces.
version 2.62
Update German translation. Thanks to Conrad Kostecki.
...
...
man/dnsmasq.8
View file @
54dd393f
...
...
@@ -204,6 +204,17 @@ running another nameserver (or another instance of dnsmasq) on the
same machine. Setting this option also enables multiple instances of
dnsmasq which provide DHCP service to run in the same machine.
.TP
.B --bind-dynamic
Enable a network mode which is a hybrid between
.B --bind-interfaces
and the default. Dnsmasq binds the address of indivdual interfaces,
allowing multiple dnsmasq instances, but if new interfaces or
addresses appear, it automatically listens on those (subject to any
access-control configuration). This makes dynamically created
interfaces work in the same way as the default. Implementing this
option requires non-standard networking APIs and it is only availble
under Linux.
.TP
.B \-y, --localise-queries
Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
received. If a name in /etc/hosts has more than one address associated with
...
...
src/dhcp.c
View file @
54dd393f
...
...
@@ -66,7 +66,7 @@ static int make_fd(int port)
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 67. That's OK if they serve different networks.
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
if
(
option_bool
(
OPT_NOWILD
))
if
(
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
)
)
{
#ifdef SO_REUSEPORT
int
rc
=
setsockopt
(
fd
,
SOL_SOCKET
,
SO_REUSEPORT
,
&
oneopt
,
sizeof
(
oneopt
));
...
...
src/dnsmasq.c
View file @
54dd393f
...
...
@@ -114,6 +114,9 @@ int main (int argc, char **argv)
set_option_bool
(
OPT_NOWILD
);
}
# endif
if
(
option_bool
(
OPT_CLEVERBIND
))
die
(
_
(
"--bind-dynamic not available on this platform"
),
NULL
,
EC_BADCONF
);
#endif
#ifndef HAVE_TFTP
...
...
@@ -185,6 +188,9 @@ int main (int argc, char **argv)
#ifdef HAVE_LINUX_NETWORK
/* After lease_init */
netlink_init
();
if
(
option_bool
(
OPT_NOWILD
)
&&
option_bool
(
OPT_CLEVERBIND
))
die
(
_
(
"cannot set --bind-interfaces and --bind-dynamic"
),
NULL
,
EC_BADCONF
);
#endif
#ifdef HAVE_DHCP6
...
...
@@ -202,13 +208,14 @@ int main (int argc, char **argv)
if
(
!
enumerate_interfaces
())
die
(
_
(
"failed to find list of interfaces: %s"
),
NULL
,
EC_MISC
);
if
(
option_bool
(
OPT_NOWILD
))
if
(
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
)
)
{
create_bound_listeners
(
1
);
for
(
if_tmp
=
daemon
->
if_names
;
if_tmp
;
if_tmp
=
if_tmp
->
next
)
if
(
if_tmp
->
name
&&
!
if_tmp
->
used
)
die
(
_
(
"unknown interface %s"
),
if_tmp
->
name
,
EC_BADNET
);
if
(
!
option_bool
(
OPT_CLEVERBIND
))
for
(
if_tmp
=
daemon
->
if_names
;
if_tmp
;
if_tmp
=
if_tmp
->
next
)
if
(
if_tmp
->
name
&&
!
if_tmp
->
used
)
die
(
_
(
"unknown interface %s"
),
if_tmp
->
name
,
EC_BADNET
);
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
/* after enumerate_interfaces() */
...
...
@@ -425,8 +432,9 @@ int main (int argc, char **argv)
#if defined(HAVE_LINUX_NETWORK)
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
ports because of DAD, we need CAP_NET_BIND_SERVICE too. */
if
(
is_dad_listeners
())
ports because of DAD, or we're doing it dynamically,
we need CAP_NET_BIND_SERVICE too. */
if
(
is_dad_listeners
()
||
option_bool
(
OPT_CLEVERBIND
))
data
->
effective
=
data
->
permitted
=
data
->
inheritable
=
(
1
<<
CAP_NET_ADMIN
)
|
(
1
<<
CAP_NET_RAW
)
|
(
1
<<
CAP_SETUID
)
|
(
1
<<
CAP_NET_BIND_SERVICE
);
...
...
@@ -474,7 +482,7 @@ int main (int argc, char **argv)
}
#ifdef HAVE_LINUX_NETWORK
if
(
is_dad_listeners
(
))
if
(
is_dad_listeners
()
||
option_bool
(
OPT_CLEVERBIND
))
data
->
effective
=
data
->
permitted
=
(
1
<<
CAP_NET_ADMIN
)
|
(
1
<<
CAP_NET_RAW
)
|
(
1
<<
CAP_NET_BIND_SERVICE
);
else
...
...
@@ -1352,7 +1360,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
getsockname
(
confd
,
(
struct
sockaddr
*
)
&
tcp_addr
,
&
tcp_len
)
==
-
1
)
continue
;
if
(
option_bool
(
OPT_NOWILD
))
if
(
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
)
)
iface
=
listener
->
iface
;
/* May be NULL */
else
{
...
...
@@ -1369,7 +1377,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
break
;
}
if
(
!
iface
&&
!
option_bool
(
OPT_NOWILD
))
if
(
!
iface
&&
!
(
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
)
))
{
shutdown
(
confd
,
SHUT_RDWR
);
close
(
confd
);
...
...
src/dnsmasq.h
View file @
54dd393f
...
...
@@ -219,7 +219,8 @@ struct event_desc {
#define OPT_FQDN_UPDATE 36
#define OPT_RA 37
#define OPT_TFTP_LC 38
#define OPT_LAST 39
#define OPT_CLEVERBIND 39
#define OPT_LAST 40
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
...
...
src/forward.c
View file @
54dd393f
...
...
@@ -436,7 +436,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if
(
udpfd
!=
-
1
)
{
plen
=
setup_reply
(
header
,
plen
,
addrp
,
flags
,
daemon
->
local_ttl
);
send_from
(
udpfd
,
option_bool
(
OPT_NOWILD
),
(
char
*
)
header
,
plen
,
udpaddr
,
dst_addr
,
dst_iface
);
send_from
(
udpfd
,
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
)
,
(
char
*
)
header
,
plen
,
udpaddr
,
dst_addr
,
dst_iface
);
}
return
0
;
...
...
@@ -624,7 +624,7 @@ void reply_query(int fd, int family, time_t now)
{
header
->
id
=
htons
(
forward
->
orig_id
);
header
->
hb4
|=
HB4_RA
;
/* recursion if available */
send_from
(
forward
->
fd
,
option_bool
(
OPT_NOWILD
),
daemon
->
packet
,
nn
,
send_from
(
forward
->
fd
,
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
)
,
daemon
->
packet
,
nn
,
&
forward
->
source
,
&
forward
->
dest
,
forward
->
iface
);
}
free_frec
(
forward
);
/* cancel */
...
...
@@ -819,8 +819,8 @@ void receive_query(struct listener *listen, time_t now)
dst_addr_4
,
netmask
,
now
);
if
(
m
>=
1
)
{
send_from
(
listen
->
fd
,
option_bool
(
OPT_NOWILD
)
,
(
char
*
)
header
,
m
,
&
source_addr
,
&
dst_addr
,
if_index
);
send_from
(
listen
->
fd
,
option_bool
(
OPT_NOWILD
)
||
option_bool
(
OPT_CLEVERBIND
),
(
char
*
)
header
,
m
,
&
source_addr
,
&
dst_addr
,
if_index
);
daemon
->
local_answer
++
;
}
else
if
(
forward_query
(
listen
->
fd
,
&
source_addr
,
&
dst_addr
,
if_index
,
...
...
src/netlink.c
View file @
54dd393f
...
...
@@ -38,7 +38,7 @@
static
struct
iovec
iov
;
static
u32
netlink_pid
;
static
void
nl_err
(
struct
nlmsghdr
*
h
);
static
int
nl_async
(
struct
nlmsghdr
*
h
);
static
void
nl_routechange
(
struct
nlmsghdr
*
h
);
void
netlink_init
(
void
)
...
...
@@ -49,10 +49,13 @@ void netlink_init(void)
addr
.
nl_family
=
AF_NETLINK
;
addr
.
nl_pad
=
0
;
addr
.
nl_pid
=
0
;
/* autobind */
#ifdef HAVE_IPV6
addr
.
nl_groups
=
RTMGRP_IPV4_ROUTE
|
RTMGRP_IPV6_ROUTE
;
#else
addr
.
nl_groups
=
RTMGRP_IPV4_ROUTE
;
if
(
option_bool
(
OPT_CLEVERBIND
))
addr
.
nl_groups
|=
RTMGRP_IPV4_IFADDR
;
#ifdef HAVE_IPV6
addr
.
nl_groups
|=
RTMGRP_IPV6_ROUTE
;
if
(
daemon
->
ra_contexts
||
option_bool
(
OPT_CLEVERBIND
))
addr
.
nl_groups
|=
RTMGRP_IPV6_IFADDR
;
#endif
/* May not be able to have permission to set multicast groups don't die in that case */
...
...
@@ -136,7 +139,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
struct
nlmsghdr
*
h
;
ssize_t
len
;
static
unsigned
int
seq
=
0
;
int
callback_ok
=
1
;
int
callback_ok
=
1
,
newaddr
=
0
;
struct
{
struct
nlmsghdr
nlh
;
...
...
@@ -182,12 +185,24 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
for
(
h
=
(
struct
nlmsghdr
*
)
iov
.
iov_base
;
NLMSG_OK
(
h
,
(
size_t
)
len
);
h
=
NLMSG_NEXT
(
h
,
len
))
if
(
h
->
nlmsg_seq
!=
seq
||
h
->
nlmsg_pid
!=
netlink_pid
)
nl_routechange
(
h
);
/* May be multicast arriving async */
else
if
(
h
->
nlmsg_type
==
NLMSG_ERROR
)
nl_err
(
h
);
if
(
h
->
nlmsg_seq
!=
seq
||
h
->
nlmsg_pid
!=
netlink_pid
||
h
->
nlmsg_type
==
NLMSG_ERROR
)
{
/* May be multicast arriving async */
if
(
nl_async
(
h
))
newaddr
=
1
;
}
else
if
(
h
->
nlmsg_type
==
NLMSG_DONE
)
return
callback_ok
;
{
/* handle async new interface address arrivals, these have to be done
after we complete as we're not re-entrant */
if
(
newaddr
)
{
enumerate_interfaces
();
create_bound_listeners
(
0
);
}
return
callback_ok
;
}
else
if
(
h
->
nlmsg_type
==
RTM_NEWADDR
&&
family
!=
AF_UNSPEC
&&
family
!=
AF_LOCAL
)
{
struct
ifaddrmsg
*
ifa
=
NLMSG_DATA
(
h
);
...
...
@@ -295,7 +310,7 @@ void netlink_multicast(void)
{
ssize_t
len
;
struct
nlmsghdr
*
h
;
int
flags
;
int
flags
,
newaddr
=
0
;
/* don't risk blocking reading netlink messages here. */
if
((
flags
=
fcntl
(
daemon
->
netlinkfd
,
F_GETFL
))
==
-
1
||
...
...
@@ -303,71 +318,83 @@ void netlink_multicast(void)
return
;
if
((
len
=
netlink_recv
())
!=
-
1
)
for
(
h
=
(
struct
nlmsghdr
*
)
iov
.
iov_base
;
NLMSG_OK
(
h
,
(
size_t
)
len
);
h
=
NLMSG_NEXT
(
h
,
len
))
if
(
nl_async
(
h
))
newaddr
=
1
;
/* restore non-blocking status */
fcntl
(
daemon
->
netlinkfd
,
F_SETFL
,
flags
);
if
(
newaddr
)
{
for
(
h
=
(
struct
nlmsghdr
*
)
iov
.
iov_base
;
NLMSG_OK
(
h
,
(
size_t
)
len
);
h
=
NLMSG_NEXT
(
h
,
len
))
if
(
h
->
nlmsg_type
==
NLMSG_ERROR
)
nl_err
(
h
);
else
nl_routechange
(
h
);
enumerate_interfaces
();
create_bound_listeners
(
0
);
}
/* restore non-blocking status */
fcntl
(
daemon
->
netlinkfd
,
F_SETFL
,
flags
);
}
static
void
nl_err
(
struct
nlmsghdr
*
h
)
static
int
nl_async
(
struct
nlmsghdr
*
h
)
{
struct
nlmsgerr
*
err
=
NLMSG_DATA
(
h
);
if
(
err
->
error
!=
0
)
my_syslog
(
LOG_ERR
,
_
(
"netlink returns error: %s"
),
strerror
(
-
(
err
->
error
)));
}
if
(
h
->
nlmsg_type
==
NLMSG_ERROR
)
{
struct
nlmsgerr
*
err
=
NLMSG_DATA
(
h
);
my_syslog
(
LOG_ERR
,
_
(
"netlink returns error: %s"
),
strerror
(
-
(
err
->
error
)));
return
0
;
}
else
if
(
h
->
nlmsg_pid
==
0
&&
h
->
nlmsg_type
==
RTM_NEWROUTE
)
{
nl_routechange
(
h
);
return
0
;
}
else
if
(
h
->
nlmsg_type
==
RTM_NEWADDR
)
{
#ifdef HAVE_DHCP6
/* force RAs to sync new network and pick up new interfaces. */
if
(
daemon
->
ra_contexts
)
{
schedule_subnet_map
();
ra_start_unsolicted
(
dnsmasq_time
(),
NULL
);
/* cause lease_update_file to run after we return, in case we were called from
iface_enumerate and can't re-enter it now */
send_alarm
(
0
,
0
);
}
return
!!
option_bool
(
OPT_CLEVERBIND
);
/* clever bind mode - rescan */
}
#endif
return
0
;
}
/* We arrange to receive netlink multicast messages whenever the network route is added.
If this happens and we still have a DNS packet in the buffer, we re-send it.
This helps on DoD links, where frequently the packet which triggers dialling is
a DNS query, which then gets lost. By re-sending, we can avoid the lookup
failing.
Note that we only accept these messages from the kernel (pid == 0)
*/
failing. */
static
void
nl_routechange
(
struct
nlmsghdr
*
h
)
{
if
(
h
->
nlmsg_pid
==
0
&&
h
->
nlmsg_type
==
RTM_NEWROUTE
)
struct
rtmsg
*
rtm
=
NLMSG_DATA
(
h
);
int
fd
;
if
(
rtm
->
rtm_type
!=
RTN_UNICAST
||
rtm
->
rtm_scope
!=
RT_SCOPE_LINK
)
return
;
/* Force re-reading resolv file right now, for luck. */
daemon
->
last_resolv
=
0
;
if
(
daemon
->
srv_save
)
{
struct
rtmsg
*
rtm
=
NLMSG_DATA
(
h
);
int
fd
;
if
(
rtm
->
rtm_type
!=
RTN_UNICAST
||
rtm
->
rtm_scope
!=
RT_SCOPE_LINK
)
if
(
daemon
->
srv_save
->
sfd
)
fd
=
daemon
->
srv_save
->
sfd
->
fd
;
else
if
(
daemon
->
rfd_save
&&
daemon
->
rfd_save
->
refcount
!=
0
)
fd
=
daemon
->
rfd_save
->
fd
;
else
return
;
/* Force re-reading resolv file right now, for luck. */
daemon
->
last_resolv
=
0
;
#ifdef HAVE_DHCP6
/* force RAs to sync new network and pick up new interfaces. */
if
(
daemon
->
ra_contexts
)
{
schedule_subnet_map
();
ra_start_unsolicted
(
dnsmasq_time
(),
NULL
);
/* cause lease_update_file to run after we return, in case we were called from
iface_enumerate and can't re-enter it now */
send_alarm
(
0
,
0
);
}
#endif
if
(
daemon
->
srv_save
)
{
if
(
daemon
->
srv_save
->
sfd
)
fd
=
daemon
->
srv_save
->
sfd
->
fd
;
else
if
(
daemon
->
rfd_save
&&
daemon
->
rfd_save
->
refcount
!=
0
)
fd
=
daemon
->
rfd_save
->
fd
;
else
return
;
while
(
sendto
(
fd
,
daemon
->
packet
,
daemon
->
packet_len
,
0
,
&
daemon
->
srv_save
->
addr
.
sa
,
sa_len
(
&
daemon
->
srv_save
->
addr
))
==
-
1
&&
retry_send
());
}
while
(
sendto
(
fd
,
daemon
->
packet
,
daemon
->
packet_len
,
0
,
&
daemon
->
srv_save
->
addr
.
sa
,
sa_len
(
&
daemon
->
srv_save
->
addr
))
==
-
1
&&
retry_send
());
}
}
#endif
src/option.c
View file @
54dd393f
...
...
@@ -119,6 +119,7 @@ struct myoption {
#define LOPT_HOST_REC 308
#define LOPT_TFTP_LC 309
#define LOPT_RR 310
#define LOPT_CLVERBIND 311
#ifdef HAVE_GETOPT_LONG
static
const
struct
option
opts
[]
=
...
...
@@ -243,6 +244,7 @@ static const struct myoption opts[] =
{
"enable-ra"
,
0
,
0
,
LOPT_RA
},
{
"dhcp-duid"
,
1
,
0
,
LOPT_DUID
},
{
"host-record"
,
1
,
0
,
LOPT_HOST_REC
},
{
"bind-dynamic"
,
0
,
0
,
LOPT_CLVERBIND
},
{
NULL
,
0
,
0
,
0
}
};
...
...
@@ -374,6 +376,7 @@ static struct {
{
LOPT_DUID
,
ARG_ONE
,
"<enterprise>,<duid>"
,
gettext_noop
(
"Specify DUID_EN-type DHCPv6 server DUID"
),
NULL
},
{
LOPT_HOST_REC
,
ARG_DUP
,
"<name>,<address>"
,
gettext_noop
(
"Specify host (A/AAAA and PTR) records"
),
NULL
},
{
LOPT_RR
,
ARG_DUP
,
"<name>,<RR-number>,[<data>]"
,
gettext_noop
(
"Specify arbitrary DNS resource record"
),
NULL
},
{
LOPT_CLVERBIND
,
OPT_CLEVERBIND
,
NULL
,
gettext_noop
(
"Bind to interfaces in use - check for new interfaces"
),
NULL
},
{
0
,
0
,
NULL
,
NULL
,
NULL
}
};
...
...
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