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
c4cd95df
Commit
c4cd95df
authored
Oct 10, 2013
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add --ra-param and remove --force-fast-ra
parent
043c271f
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
147 additions
and
37 deletions
+147
-37
CHANGELOG
CHANGELOG
+3
-2
man/dnsmasq.8
man/dnsmasq.8
+13
-5
src/dnsmasq.h
src/dnsmasq.h
+8
-2
src/option.c
src/option.c
+28
-3
src/radv.c
src/radv.c
+95
-25
No files found.
CHANGELOG
View file @
c4cd95df
...
...
@@ -90,8 +90,6 @@ version 2.67
smallest valid dhcp-range is sent. Thanks to Uwe Schindler
for suggesting this.
Add --force-fast-ra option. Another thanks to Uwe Schindler.
Make --listen-address higher priority than --except-interface
in all circumstances. Thanks to Thomas Hood for the bugreport.
...
...
@@ -132,6 +130,9 @@ version 2.67
Update Spanish transalation. Thanks to Vicente Soriano.
Add --ra-param option. Thanks to Vladislav Grishenko for
inspiration on this.
version 2.66
Add the ability to act as an authoritative DNS
...
...
man/dnsmasq.8
View file @
c4cd95df
...
...
@@ -1525,11 +1525,19 @@ the relevant link-local address of the machine running dnsmasq is sent
as recursive DNS server. If provided, the DHCPv6 options dns-server and
domain-search are used for RDNSS and DNSSL.
.TP
.B --force-fast-ra
Normally, dnsmasq advertises a new IPv6 prefix frequently (every 10 seconds or so) for the first minute, and then
drops back to sending "maintenance" advertisements every 10 minutes or so. This option forces dnsmasq to be always in
frequent RA mode. It's a bug workaround for mobile devices which go deaf to RAs during sleep and therefore
lose conectivity; with frequent RAs they recover in a reasonable time after wakeup.
.B --ra-param=<interface>,[high|low],[[<ra-interval>],<router lifetime>]
Set non-default values for router advertisements sent via an
interface. The priority field for the router may be altered from the
default of medium with eg
.B --ra-param=eth0,high.
The interval between router advertisements may be set (in seconds) with
.B --ra-param=eth0,60.
The lifetime of the route may be changed or set to zero, which allows
a router to advertise prefixes but not a route via itself.
.B --ra-parm=eth0,0,0
(A value of zero for the interval means the default value.) All three parameters may be set at once.
.B --ra-param=low,60,1200
The interface field may include a wildcard.
.TP
.B --enable-tftp[=<interface>[,<interface>]]
Enable the TFTP server function. This is deliberately limited to that
...
...
src/dnsmasq.h
View file @
c4cd95df
...
...
@@ -221,8 +221,7 @@ struct event_desc {
#define OPT_TFTP_LC 38
#define OPT_CLEVERBIND 39
#define OPT_TFTP 40
#define OPT_FAST_RA 41
#define OPT_LAST 42
#define OPT_LAST 41
/* 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. */
...
...
@@ -701,6 +700,12 @@ struct prefix_class {
};
#endif
struct
ra_interface
{
char
*
name
;
int
interval
,
lifetime
,
prio
;
struct
ra_interface
*
next
;
};
struct
dhcp_context
{
unsigned
int
lease_time
,
addr_epoch
;
struct
in_addr
netmask
,
broadcast
;
...
...
@@ -825,6 +830,7 @@ extern struct daemon {
unsigned
long
local_ttl
,
neg_ttl
,
max_ttl
,
max_cache_ttl
,
auth_ttl
;
struct
hostsfile
*
addn_hosts
;
struct
dhcp_context
*
dhcp
,
*
dhcp6
;
struct
ra_interface
*
ra_interfaces
;
struct
dhcp_config
*
dhcp_conf
;
struct
dhcp_opt
*
dhcp_opts
,
*
dhcp_match
,
*
dhcp_opts6
,
*
dhcp_match6
;
struct
dhcp_vendor
*
dhcp_vendors
;
...
...
src/option.c
View file @
c4cd95df
...
...
@@ -132,8 +132,8 @@ struct myoption {
#ifdef OPTION6_PREFIX_CLASS
#define LOPT_PREF_CLSS 321
#endif
#define LOPT_FAST_RA 322
#define LOPT_RELAY 323
#define LOPT_RA_PARAM 324
#ifdef HAVE_GETOPT_LONG
static
const
struct
option
opts
[]
=
...
...
@@ -271,8 +271,8 @@ static const struct myoption opts[] =
#ifdef OPTION6_PREFIX_CLASS
{
"dhcp-prefix-class"
,
1
,
0
,
LOPT_PREF_CLSS
},
#endif
{
"force-fast-ra"
,
0
,
0
,
LOPT_FAST_RA
},
{
"dhcp-relay"
,
1
,
0
,
LOPT_RELAY
},
{
"ra-param"
,
1
,
0
,
LOPT_RA_PARAM
},
{
NULL
,
0
,
0
,
0
}
};
...
...
@@ -402,7 +402,6 @@ static struct {
{
LOPT_CONNTRACK
,
OPT_CONNTRACK
,
NULL
,
gettext_noop
(
"Copy connection-track mark from queries to upstream connections."
),
NULL
},
{
LOPT_FQDN
,
OPT_FQDN_UPDATE
,
NULL
,
gettext_noop
(
"Allow DHCP clients to do their own DDNS updates."
),
NULL
},
{
LOPT_RA
,
OPT_RA
,
NULL
,
gettext_noop
(
"Send router-advertisements for interfaces doing DHCPv6"
),
NULL
},
{
LOPT_FAST_RA
,
OPT_FAST_RA
,
NULL
,
gettext_noop
(
"Always send frequent router-advertisements"
),
NULL
},
{
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
},
...
...
@@ -418,6 +417,7 @@ static struct {
#ifdef OPTION6_PREFIX_CLASS
{
LOPT_PREF_CLSS
,
ARG_DUP
,
"set:tag,<class>"
,
gettext_noop
(
"Specify DHCPv6 prefix class"
),
NULL
},
#endif
{
LOPT_RA_PARAM
,
ARG_DUP
,
"<interface>,[high,|low,]<interval>[,<lifetime>]"
,
gettext_noop
(
"Set priority, resend-interval and router-lifetime"
),
NULL
},
{
0
,
0
,
NULL
,
NULL
,
NULL
}
};
...
...
@@ -3215,6 +3215,31 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
#endif
#ifdef HAVE_DHCP6
case
LOPT_RA_PARAM
:
/* --ra-param */
if
((
comma
=
split
(
arg
)))
{
struct
ra_interface
*
new
=
opt_malloc
(
sizeof
(
struct
ra_interface
));
new
->
lifetime
=
-
1
;
new
->
prio
=
0
;
new
->
name
=
opt_string_alloc
(
arg
);
if
(
strcasestr
(
comma
,
"high"
)
==
comma
||
strcasestr
(
comma
,
"low"
)
==
comma
)
{
if
(
*
comma
==
'l'
||
*
comma
==
'L'
)
new
->
prio
=
0x18
;
else
new
->
prio
=
0x08
;
comma
=
split
(
comma
);
}
arg
=
split
(
comma
);
if
(
!
atoi_check
(
comma
,
&
new
->
interval
)
||
(
arg
&&
!
atoi_check
(
arg
,
&
new
->
lifetime
)))
ret_err
(
_
(
"bad RA-params"
));
new
->
next
=
daemon
->
ra_interfaces
;
daemon
->
ra_interfaces
=
new
;
}
break
;
case
LOPT_DUID
:
/* --dhcp-duid */
if
(
!
(
comma
=
split
(
arg
))
||
!
atoi_check
(
arg
,
(
int
*
)
&
daemon
->
duid_enterprise
))
ret_err
(
_
(
"bad DUID"
));
...
...
src/radv.c
View file @
c4cd95df
...
...
@@ -32,11 +32,12 @@ struct ra_param {
char
*
if_name
;
struct
dhcp_netid
*
tags
;
struct
in6_addr
link_local
,
link_global
;
unsigned
int
pref_time
;
unsigned
int
pref_time
,
adv_interval
;
};
struct
search_param
{
time_t
now
;
int
iface
;
char
name
[
IF_NAMESIZE
+
1
];
};
static
void
send_ra
(
time_t
now
,
int
iface
,
char
*
iface_name
,
struct
in6_addr
*
dest
);
...
...
@@ -47,7 +48,11 @@ static int iface_search(struct in6_addr *local, int prefix,
int
scope
,
int
if_index
,
int
flags
,
int
prefered
,
int
valid
,
void
*
vparam
);
static
int
add_lla
(
int
index
,
unsigned
int
type
,
char
*
mac
,
size_t
maclen
,
void
*
parm
);
static
void
new_timeout
(
struct
dhcp_context
*
context
,
time_t
now
);
static
void
new_timeout
(
struct
dhcp_context
*
context
,
char
*
iface_name
,
time_t
now
);
static
unsigned
int
calc_lifetime
(
struct
ra_interface
*
ra
);
static
unsigned
int
calc_interval
(
struct
ra_interface
*
ra
);
static
unsigned
int
calc_prio
(
struct
ra_interface
*
ra
);
static
struct
ra_interface
*
find_iface_param
(
char
*
iface
);
static
int
hop_limit
;
...
...
@@ -198,19 +203,20 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
struct
dhcp_context
*
context
,
*
tmp
,
**
up
;
struct
dhcp_netid
iface_id
;
struct
dhcp_opt
*
opt_cfg
;
struct
ra_interface
*
ra_param
=
find_iface_param
(
iface_name
);
int
done_dns
=
0
;
#ifdef HAVE_LINUX_NETWORK
FILE
*
f
;
#endif
save_counter
(
0
);
ra
=
expand
(
sizeof
(
struct
ra_packet
));
ra
->
type
=
ND_ROUTER_ADVERT
;
ra
->
code
=
0
;
ra
->
hop_limit
=
hop_limit
;
ra
->
flags
=
0x00
;
ra
->
lifetime
=
htons
(
RA_INTERVAL
*
3
);
/* AdvDefaultLifetime * 3 */
ra
->
flags
=
calc_prio
(
ra_param
)
;
ra
->
lifetime
=
htons
(
calc_lifetime
(
ra_param
));
ra
->
reachable_time
=
0
;
ra
->
retrans_time
=
0
;
...
...
@@ -222,6 +228,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
parm
.
first
=
1
;
parm
.
now
=
now
;
parm
.
pref_time
=
0
;
parm
.
adv_interval
=
calc_interval
(
ra_param
);
/* set tag with name == interface */
iface_id
.
net
=
iface_name
;
...
...
@@ -335,7 +342,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
put_opt6_char
(
ICMP6_OPT_RDNSS
);
put_opt6_char
((
opt_cfg
->
len
/
8
)
+
1
);
put_opt6_short
(
0
);
put_opt6_long
(
RA_INTERVAL
*
2
);
/* lifetime - twice RA retransmit */
put_opt6_long
(
parm
.
adv_interval
*
2
);
/* lifetime - twice RA retransmit */
/* zero means "self" */
for
(
i
=
0
;
i
<
opt_cfg
->
len
;
i
+=
IN6ADDRSZ
,
a
++
)
if
(
IN6_IS_ADDR_UNSPECIFIED
(
a
))
...
...
@@ -351,7 +358,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
put_opt6_char
(
ICMP6_OPT_DNSSL
);
put_opt6_char
(
len
+
1
);
put_opt6_short
(
0
);
put_opt6_long
(
RA_INTERVAL
*
2
);
/* lifetime - twice RA retransmit */
put_opt6_long
(
parm
.
adv_interval
*
2
);
/* lifetime - twice RA retransmit */
put_opt6
(
opt_cfg
->
val
,
opt_cfg
->
len
);
/* pad */
...
...
@@ -366,7 +373,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
put_opt6_char
(
ICMP6_OPT_RDNSS
);
put_opt6_char
(
3
);
put_opt6_short
(
0
);
put_opt6_long
(
RA_INTERVAL
*
2
);
/* lifetime - twice RA retransmit */
put_opt6_long
(
parm
.
adv_interval
*
2
);
/* lifetime - twice RA retransmit */
put_opt6
(
&
parm
.
link_global
,
IN6ADDRSZ
);
}
...
...
@@ -455,8 +462,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
if
(
time
>
context
->
lease_time
)
{
time
=
context
->
lease_time
;
if
(
time
<
((
unsigned
int
)(
3
*
RA_INTERVAL
)))
time
=
3
*
RA_INTERVAL
;
if
(
time
<
((
unsigned
int
)(
3
*
param
->
adv_interval
)))
time
=
3
*
param
->
adv_interval
;
}
if
(
context
->
flags
&
CONTEXT_DEPRECATE
)
...
...
@@ -564,8 +571,7 @@ time_t periodic_ra(time_t now)
struct
search_param
param
;
struct
dhcp_context
*
context
;
time_t
next_event
;
char
interface
[
IF_NAMESIZE
+
1
];
param
.
now
=
now
;
param
.
iface
=
0
;
...
...
@@ -586,13 +592,15 @@ time_t periodic_ra(time_t now)
if
(
!
context
)
break
;
if
((
context
->
flags
&
CONTEXT_OLD
)
&&
context
->
if_index
!=
0
)
if
((
context
->
flags
&
CONTEXT_OLD
)
&&
context
->
if_index
!=
0
&&
indextoname
(
daemon
->
icmp6fd
,
param
.
iface
,
param
.
name
))
{
/* A context for an old address. We'll not find the interface by
looking for addresses, but we know it anyway,
as long as we
sent at least one RA whilst the address was current.
*/
looking for addresses, but we know it anyway,
since the context is
constructed
*/
param
.
iface
=
context
->
if_index
;
new_timeout
(
context
,
now
);
new_timeout
(
context
,
param
.
name
,
now
);
}
else
if
(
iface_enumerate
(
AF_INET6
,
&
param
,
iface_search
))
/* There's a context overdue, but we can't find an interface
...
...
@@ -603,15 +611,14 @@ time_t periodic_ra(time_t now)
context
->
ra_time
=
0
;
if
(
param
.
iface
!=
0
&&
indextoname
(
daemon
->
icmp6fd
,
param
.
iface
,
interface
)
&&
iface_check
(
AF_LOCAL
,
NULL
,
interface
,
NULL
))
iface_check
(
AF_LOCAL
,
NULL
,
param
.
name
,
NULL
))
{
struct
iname
*
tmp
;
for
(
tmp
=
daemon
->
dhcp_except
;
tmp
;
tmp
=
tmp
->
next
)
if
(
tmp
->
name
&&
wildcard_match
(
tmp
->
name
,
interfac
e
))
if
(
tmp
->
name
&&
wildcard_match
(
tmp
->
name
,
param
.
nam
e
))
break
;
if
(
!
tmp
)
send_ra
(
now
,
param
.
iface
,
interfac
e
,
NULL
);
send_ra
(
now
,
param
.
iface
,
param
.
nam
e
,
NULL
);
}
}
return
next_event
;
...
...
@@ -643,7 +650,14 @@ static int iface_search(struct in6_addr *local, int prefix,
if
(
!
(
flags
&
IFACE_TENTATIVE
))
param
->
iface
=
if_index
;
new_timeout
(
context
,
param
->
now
);
/* should never fail */
if
(
!
indextoname
(
daemon
->
icmp6fd
,
if_index
,
param
->
name
))
{
param
->
iface
=
0
;
return
0
;
}
new_timeout
(
context
,
param
->
name
,
param
->
now
);
/* zero timers for other contexts on the same subnet, so they don't timeout
independently */
...
...
@@ -659,14 +673,70 @@ static int iface_search(struct in6_addr *local, int prefix,
return
1
;
/* keep searching */
}
static
void
new_timeout
(
struct
dhcp_context
*
context
,
time_t
now
)
static
void
new_timeout
(
struct
dhcp_context
*
context
,
char
*
iface_name
,
time_t
now
)
{
if
(
difftime
(
now
,
context
->
ra_short_period_start
)
<
60
.
0
||
option_bool
(
OPT_FAST_RA
)
)
if
(
difftime
(
now
,
context
->
ra_short_period_start
)
<
60
.
0
)
/* range 5 - 20 */
context
->
ra_time
=
now
+
5
+
(
rand16
()
/
4400
);
else
/* range 3/4 - 1 times RA_INTERVAL */
context
->
ra_time
=
now
+
(
3
*
RA_INTERVAL
)
/
4
+
((
RA_INTERVAL
*
(
unsigned
int
)
rand16
())
>>
18
);
{
/* range 3/4 - 1 times MaxRtrAdvInterval */
unsigned
int
adv_interval
=
calc_interval
(
find_iface_param
(
iface_name
));
context
->
ra_time
=
now
+
(
3
*
adv_interval
)
/
4
+
((
adv_interval
*
(
unsigned
int
)
rand16
())
>>
18
);
}
}
static
struct
ra_interface
*
find_iface_param
(
char
*
iface
)
{
struct
ra_interface
*
ra
;
for
(
ra
=
daemon
->
ra_interfaces
;
ra
;
ra
=
ra
->
next
)
if
(
wildcard_match
(
ra
->
name
,
iface
))
return
ra
;
return
NULL
;
}
static
unsigned
int
calc_interval
(
struct
ra_interface
*
ra
)
{
int
interval
=
600
;
if
(
ra
&&
ra
->
interval
!=
0
)
{
interval
=
ra
->
interval
;
if
(
interval
>
1800
)
interval
=
1800
;
else
if
(
interval
<
4
)
interval
=
4
;
}
return
(
unsigned
int
)
interval
;
}
static
unsigned
int
calc_lifetime
(
struct
ra_interface
*
ra
)
{
int
lifetime
,
interval
=
(
int
)
calc_interval
(
ra
);
if
(
!
ra
||
ra
->
lifetime
==
-
1
)
/* not specified */
lifetime
=
3
*
interval
;
else
{
lifetime
=
ra
->
lifetime
;
if
(
lifetime
<
interval
&&
lifetime
!=
0
)
lifetime
=
interval
;
else
if
(
lifetime
>
9000
)
lifetime
=
9000
;
}
return
(
unsigned
int
)
lifetime
;
}
static
unsigned
int
calc_prio
(
struct
ra_interface
*
ra
)
{
if
(
ra
)
return
ra
->
prio
;
return
0
;
}
#endif
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