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
1f776932
Commit
1f776932
authored
Dec 16, 2012
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First checkin of interface-address constructor mode for DHCPv6 and RA.
parent
4820dce9
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
479 additions
and
339 deletions
+479
-339
src/bpf.c
src/bpf.c
+1
-1
src/dhcp-common.c
src/dhcp-common.c
+71
-77
src/dhcp6.c
src/dhcp6.c
+212
-2
src/dnsmasq.c
src/dnsmasq.c
+59
-120
src/dnsmasq.h
src/dnsmasq.h
+15
-7
src/lease.c
src/lease.c
+5
-6
src/netlink.c
src/netlink.c
+36
-27
src/network.c
src/network.c
+4
-1
src/option.c
src/option.c
+21
-20
src/radv.c
src/radv.c
+53
-22
src/slaac.c
src/slaac.c
+2
-56
No files found.
src/bpf.c
View file @
1f776932
...
...
@@ -147,7 +147,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
addr
->
s6_addr
[
3
]
=
0
;
}
if
(
!
((
*
callback
)(
addr
,
prefix
,
scope_id
,
iface_index
,
0
,
parm
)))
if
(
!
((
*
callback
)(
addr
,
prefix
,
scope_id
,
iface_index
,
0
,
0
,
0
,
parm
)))
goto
err
;
}
#endif
...
...
src/dhcp-common.c
View file @
1f776932
...
...
@@ -333,83 +333,6 @@ void dhcp_update_configs(struct dhcp_config *configs)
}
#ifdef HAVE_DHCP6
static
int
join_multicast_worker
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
{
char
ifrn_name
[
IFNAMSIZ
];
struct
ipv6_mreq
mreq
;
int
fd
,
i
,
max
=
*
((
int
*
)
vparam
);
struct
iname
*
tmp
;
(
void
)
prefix
;
(
void
)
scope
;
(
void
)
dad
;
/* record which interfaces we join on, so that we do it at most one per
interface, even when they have multiple addresses. Use outpacket
as an array of int, since it's always allocated here and easy
to expand for theoretical vast numbers of interfaces. */
for
(
i
=
0
;
i
<
max
;
i
++
)
if
(
if_index
==
((
int
*
)
daemon
->
outpacket
.
iov_base
)[
i
])
return
1
;
if
((
fd
=
socket
(
PF_INET6
,
SOCK_DGRAM
,
0
))
==
-
1
)
return
0
;
if
(
!
indextoname
(
fd
,
if_index
,
ifrn_name
))
{
close
(
fd
);
return
0
;
}
close
(
fd
);
/* Are we doing DHCP on this interface? */
if
(
!
iface_check
(
AF_INET6
,
(
struct
all_addr
*
)
local
,
ifrn_name
,
NULL
))
return
1
;
for
(
tmp
=
daemon
->
dhcp_except
;
tmp
;
tmp
=
tmp
->
next
)
if
(
tmp
->
name
&&
(
strcmp
(
tmp
->
name
,
ifrn_name
)
==
0
))
return
1
;
mreq
.
ipv6mr_interface
=
if_index
;
inet_pton
(
AF_INET6
,
ALL_RELAY_AGENTS_AND_SERVERS
,
&
mreq
.
ipv6mr_multiaddr
);
if
(
daemon
->
dhcp6
&&
setsockopt
(
daemon
->
dhcp6fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
inet_pton
(
AF_INET6
,
ALL_SERVERS
,
&
mreq
.
ipv6mr_multiaddr
);
if
(
daemon
->
dhcp6
&&
setsockopt
(
daemon
->
dhcp6fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
inet_pton
(
AF_INET6
,
ALL_ROUTERS
,
&
mreq
.
ipv6mr_multiaddr
);
if
(
daemon
->
ra_contexts
&&
setsockopt
(
daemon
->
icmp6fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
expand_buf
(
&
daemon
->
outpacket
,
(
max
+
1
)
*
sizeof
(
int
));
((
int
*
)
daemon
->
outpacket
.
iov_base
)[
max
++
]
=
if_index
;
*
((
int
*
)
vparam
)
=
max
;
return
1
;
}
void
join_multicast
(
void
)
{
int
count
=
0
;
if
(
!
iface_enumerate
(
AF_INET6
,
&
count
,
join_multicast_worker
))
die
(
_
(
"failed to join DHCPv6 multicast group: %s"
),
NULL
,
EC_BADNET
);
}
#endif
#ifdef HAVE_LINUX_NETWORK
void
bindtodevice
(
int
fd
)
{
...
...
@@ -750,4 +673,75 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
}
void
log_context
(
int
family
,
struct
dhcp_context
*
context
)
{
/* Cannot use dhcp_buff* for RA contexts */
void
*
start
=
&
context
->
start
;
void
*
end
=
&
context
->
end
;
#ifdef HAVE_DHCP6
if
(
family
==
AF_INET6
)
{
struct
in6_addr
subnet
=
context
->
start6
;
if
(
!
(
context
->
flags
&
CONTEXT_TEMPLATE
))
setaddr6part
(
&
subnet
,
0
);
inet_ntop
(
AF_INET6
,
&
subnet
,
daemon
->
addrbuff
,
ADDRSTRLEN
);
start
=
&
context
->
start6
;
end
=
&
context
->
end6
;
}
#endif
if
(
context
->
flags
&
CONTEXT_CONSTRUCTED
)
sprintf
(
daemon
->
namebuff
,
"constructed for %s"
,
context
->
template_interface
);
else
if
(
context
->
flags
&
CONTEXT_TEMPLATE
)
sprintf
(
daemon
->
namebuff
,
"template for %s"
,
context
->
template_interface
);
else
{
if
(
family
!=
AF_INET
&&
(
context
->
flags
&
CONTEXT_DEPRECATE
))
strcpy
(
daemon
->
namebuff
,
_
(
"prefix deprecated"
));
else
{
char
*
p
=
daemon
->
namebuff
;
p
+=
sprintf
(
p
,
_
(
"lease time "
));
prettyprint_time
(
p
,
context
->
lease_time
);
}
}
if
((
context
->
flags
&
CONTEXT_DHCP
)
||
family
==
AF_INET
)
{
inet_ntop
(
family
,
start
,
daemon
->
dhcp_buff
,
256
);
inet_ntop
(
family
,
end
,
daemon
->
dhcp_buff3
,
256
);
my_syslog
(
MS_DHCP
|
LOG_INFO
,
(
context
->
flags
&
CONTEXT_RA_STATELESS
)
?
_
(
"%s stateless on %s%.0s%.0s"
)
:
(
context
->
flags
&
CONTEXT_STATIC
)
?
_
(
"%s, static leases only on %.0s%s, %s"
)
:
(
context
->
flags
&
CONTEXT_PROXY
)
?
_
(
"%s, proxy on subnet %.0s%s%.0s"
)
:
_
(
"%s, IP range %s -- %s, %s"
),
(
family
!=
AF_INET
)
?
"DHCPv6"
:
"DHCP"
,
daemon
->
dhcp_buff
,
daemon
->
dhcp_buff3
,
daemon
->
namebuff
);
}
if
(
context
->
flags
&
CONTEXT_RA_NAME
)
my_syslog
(
MS_DHCP
|
LOG_INFO
,
_
(
"DHCPv4-derived IPv6 names on %s"
),
daemon
->
addrbuff
);
if
(
context
->
flags
&
(
CONTEXT_RA_ONLY
|
CONTEXT_RA_NAME
|
CONTEXT_RA_STATELESS
))
{
if
(
!
(
context
->
flags
&
(
CONTEXT_DEPRECATE
|
CONTEXT_CONSTRUCTED
|
CONTEXT_TEMPLATE
)))
{
char
*
p
=
daemon
->
namebuff
;
p
+=
sprintf
(
p
,
_
(
"prefix valid "
));
prettyprint_time
(
p
,
context
->
lease_time
>
7200
?
context
->
lease_time
:
7200
);
}
my_syslog
(
MS_DHCP
|
LOG_INFO
,
_
(
"router advertisement on %s %s"
),
daemon
->
addrbuff
,
daemon
->
namebuff
);
}
}
#endif
src/dhcp6.c
View file @
1f776932
...
...
@@ -25,7 +25,8 @@ struct iface_param {
};
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
);
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
);
static
int
make_duid1
(
int
index
,
unsigned
int
type
,
char
*
mac
,
size_t
maclen
,
void
*
parm
);
...
...
@@ -181,7 +182,8 @@ void dhcp6_packet(time_t now)
}
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
struct
dhcp_context
*
context
;
struct
iface_param
*
param
=
vparam
;
...
...
@@ -189,6 +191,8 @@ static int complete_context6(struct in6_addr *local, int prefix,
(
void
)
scope
;
/* warning */
(
void
)
dad
;
(
void
)
preferred
;
(
void
)
valid
;
if
(
if_index
==
param
->
ind
&&
!
IN6_IS_ADDR_LOOPBACK
(
local
)
&&
...
...
@@ -467,6 +471,212 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo
return
0
;
}
struct
cparam
{
time_t
now
;
int
newone
;
};
static
int
construct_worker
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
char
ifrn_name
[
IFNAMSIZ
];
struct
in6_addr
start6
,
end6
;
struct
dhcp_context
*
template
,
*
context
;
(
void
)
scope
;
(
void
)
dad
;
struct
cparam
*
param
=
vparam
;
if
(
IN6_IS_ADDR_LOOPBACK
(
local
)
||
IN6_IS_ADDR_LINKLOCAL
(
local
)
||
IN6_IS_ADDR_MULTICAST
(
local
))
return
1
;
if
(
!
indextoname
(
daemon
->
doing_dhcp6
?
daemon
->
dhcp6fd
:
daemon
->
icmp6fd
,
if_index
,
ifrn_name
))
return
0
;
for
(
template
=
daemon
->
dhcp6
;
template
;
template
=
template
->
next
)
if
(
!
(
template
->
flags
&
CONTEXT_TEMPLATE
))
{
/* non-template entries, just fill in interface and local addresses */
if
(
prefix
==
template
->
prefix
&&
is_same_net6
(
local
,
&
template
->
start6
,
prefix
)
&&
is_same_net6
(
local
,
&
template
->
end6
,
prefix
))
{
template
->
if_index
=
if_index
;
template
->
local6
=
*
local
;
}
}
else
if
(
strcmp
(
ifrn_name
,
template
->
template_interface
)
==
0
&&
addr6part
(
local
)
==
addr6part
(
&
template
->
start6
))
{
start6
=
*
local
;
setaddr6part
(
&
start6
,
addr6part
(
&
template
->
start6
));
end6
=
*
local
;
setaddr6part
(
&
end6
,
addr6part
(
&
template
->
end6
));
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_CONSTRUCTED
)
&&
IN6_ARE_ADDR_EQUAL
(
&
start6
,
&
context
->
start6
)
&&
IN6_ARE_ADDR_EQUAL
(
&
end6
,
&
context
->
end6
))
{
context
->
flags
&=
~
CONTEXT_GC
;
break
;
}
if
(
!
context
&&
(
context
=
whine_malloc
(
sizeof
(
struct
dhcp_context
))))
{
*
context
=
*
template
;
context
->
start6
=
start6
;
context
->
end6
=
end6
;
context
->
flags
&=
~
CONTEXT_TEMPLATE
;
context
->
flags
|=
CONTEXT_CONSTRUCTED
;
context
->
if_index
=
if_index
;
context
->
local6
=
*
local
;
context
->
lease_time
=
param
->
now
+
valid
;
context
->
next
=
daemon
->
dhcp6
;
daemon
->
dhcp6
=
context
;
ra_start_unsolicted
(
dnsmasq_time
(),
context
);
/* we created a new one, need to call
lease_update_file to get periodic functions called */
param
->
newone
=
1
;
log_context
(
AF_INET6
,
context
);
}
if
(
context
)
{
if
(
valid
==
-
1
)
context
->
valid
=
valid
;
else
context
->
valid
=
valid
+
param
->
now
;
if
(
preferred
==
-
1
)
context
->
preferred
=
preferred
;
else
context
->
preferred
=
preferred
+
param
->
now
;
}
}
return
1
;
}
void
dhcp_construct_contexts
(
time_t
now
)
{
struct
dhcp_context
*
tmp
,
*
context
,
**
up
;
struct
cparam
param
;
param
.
newone
=
0
;
param
.
now
=
now
;
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
(
context
->
flags
&
CONTEXT_CONSTRUCTED
)
context
->
flags
|=
CONTEXT_GC
;
iface_enumerate
(
AF_INET6
,
&
param
,
construct_worker
);
for
(
up
=
&
daemon
->
dhcp6
,
context
=
daemon
->
dhcp6
;
context
;
context
=
tmp
)
{
tmp
=
context
->
next
;
if
(
context
->
flags
&
CONTEXT_GC
)
{
if
(
daemon
->
dhcp6
==
context
)
daemon
->
dhcp6
=
context
->
next
;
*
up
=
context
->
next
;
free
(
context
);
}
else
up
=
&
context
->
next
;
}
if
(
param
.
newone
)
lease_update_file
(
now
);
}
static
int
join_multicast_worker
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
char
ifrn_name
[
IFNAMSIZ
];
struct
ipv6_mreq
mreq
;
int
fd
,
i
,
max
=
*
((
int
*
)
vparam
);
struct
iname
*
tmp
;
(
void
)
prefix
;
(
void
)
scope
;
(
void
)
dad
;
(
void
)
preferred
;
(
void
)
valid
;
/* record which interfaces we join on, so that we do it at most one per
interface, even when they have multiple addresses. Use outpacket
as an array of int, since it's always allocated here and easy
to expand for theoretical vast numbers of interfaces. */
for
(
i
=
0
;
i
<
max
;
i
++
)
if
(
if_index
==
((
int
*
)
daemon
->
outpacket
.
iov_base
)[
i
])
return
1
;
if
((
fd
=
socket
(
PF_INET6
,
SOCK_DGRAM
,
0
))
==
-
1
)
return
0
;
if
(
!
indextoname
(
fd
,
if_index
,
ifrn_name
))
{
close
(
fd
);
return
0
;
}
close
(
fd
);
/* Are we doing DHCP on this interface? */
if
(
!
iface_check
(
AF_INET6
,
(
struct
all_addr
*
)
local
,
ifrn_name
,
NULL
))
return
1
;
for
(
tmp
=
daemon
->
dhcp_except
;
tmp
;
tmp
=
tmp
->
next
)
if
(
tmp
->
name
&&
(
strcmp
(
tmp
->
name
,
ifrn_name
)
==
0
))
return
1
;
mreq
.
ipv6mr_interface
=
if_index
;
inet_pton
(
AF_INET6
,
ALL_RELAY_AGENTS_AND_SERVERS
,
&
mreq
.
ipv6mr_multiaddr
);
if
(
daemon
->
doing_dhcp6
&&
setsockopt
(
daemon
->
dhcp6fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
inet_pton
(
AF_INET6
,
ALL_SERVERS
,
&
mreq
.
ipv6mr_multiaddr
);
if
(
daemon
->
doing_dhcp6
&&
setsockopt
(
daemon
->
dhcp6fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
inet_pton
(
AF_INET6
,
ALL_ROUTERS
,
&
mreq
.
ipv6mr_multiaddr
);
if
(
daemon
->
doing_ra
&&
setsockopt
(
daemon
->
icmp6fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
expand_buf
(
&
daemon
->
outpacket
,
(
max
+
1
)
*
sizeof
(
int
));
((
int
*
)
daemon
->
outpacket
.
iov_base
)[
max
++
]
=
if_index
;
*
((
int
*
)
vparam
)
=
max
;
return
1
;
}
void
join_multicast
(
void
)
{
int
count
=
0
;
if
(
!
iface_enumerate
(
AF_INET6
,
&
count
,
join_multicast_worker
))
die
(
_
(
"failed to join DHCPv6 multicast group: %s"
),
NULL
,
EC_BADNET
);
}
#endif
src/dnsmasq.c
View file @
1f776932
...
...
@@ -51,6 +51,7 @@ int main (int argc, char **argv)
cap_user_header_t
hdr
=
NULL
;
cap_user_data_t
data
=
NULL
;
#endif
struct
dhcp_context
*
context
;
#ifdef LOCALEDIR
setlocale
(
LC_ALL
,
""
);
...
...
@@ -167,40 +168,44 @@ int main (int argc, char **argv)
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
{
{
# ifdef HAVE_DHCP6
if
(
daemon
->
dhcp6
)
{
daemon
->
doing_ra
=
option_bool
(
OPT_RA
);
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
{
if
(
context
->
flags
&
CONTEXT_DHCP
)
daemon
->
doing_dhcp6
=
1
;
if
(
context
->
flags
&
(
CONTEXT_RA_ONLY
|
CONTEXT_RA_NAME
|
CONTEXT_RA_STATELESS
))
daemon
->
doing_ra
=
1
;
}
}
# endif
/* Note that order matters here, we must call lease_init before
creating any file descriptors which shouldn't be leaked
to the lease-script init process. We need to call common_init
before lease_init to allocate buffers it uses.*/
dhcp_common_init
();
lease_init
(
now
);
if
(
daemon
->
dhcp
||
daemon
->
doing_dhcp6
)
{
dhcp_common_init
();
lease_init
(
now
);
}
if
(
daemon
->
dhcp
)
dhcp_init
();
}
# ifdef HAVE_DHCP6
/* Start RA subsystem if --enable-ra OR dhcp-range=<subnet>, ra-only */
if
(
daemon
->
ra_contexts
||
option_bool
(
OPT_RA
))
{
/* link the DHCP6 contexts to the ra-only ones so we can traverse them all
from ->ra_contexts, but only the non-ra-onlies from ->dhcp6 */
struct
dhcp_context
*
context
;
if
(
daemon
->
doing_ra
)
ra_init
(
now
);
if
(
!
daemon
->
ra_contexts
)
daemon
->
ra_contexts
=
daemon
->
dhcp6
;
else
{
for
(
context
=
daemon
->
ra_contexts
;
context
->
next
;
context
=
context
->
next
);
context
->
next
=
daemon
->
dhcp6
;
}
ra_init
(
now
);
}
if
(
daemon
->
dhcp6
)
dhcp6_init
();
if
(
daemon
->
doing_dhcp6
)
dhcp6_init
();
# endif
}
#endif
...
...
@@ -214,13 +219,13 @@ int main (int argc, char **argv)
#ifdef HAVE_DHCP6
/* after netlink_init */
if
(
daemon
->
ra_contexts
||
daemon
->
dhcp6
)
if
(
daemon
->
doing_dhcp6
||
daemon
->
doing_ra
)
join_multicast
();
#endif
#ifdef HAVE_DHCP
/* after netlink_init */
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
if
(
daemon
->
dhcp
||
daemon
->
d
oing_d
hcp6
)
lease_find_interfaces
(
now
);
#endif
...
...
@@ -628,90 +633,24 @@ int main (int argc, char **argv)
if
(
daemon
->
max_logs
!=
0
)
my_syslog
(
LOG_INFO
,
_
(
"asynchronous logging enabled, queue limit is %d messages"
),
daemon
->
max_logs
);
if
(
daemon
->
ra_contexts
)
my_syslog
(
MS_DHCP
|
LOG_INFO
,
_
(
"IPv6 router advertisement enabled"
));
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
||
daemon
->
ra_contexts
)
{
struct
dhcp_context
*
dhcp_tmp
;
int
family
=
AF_INET
;
dhcp_tmp
=
daemon
->
dhcp
;
#ifdef HAVE_DHCP6
again:
#endif
for
(;
dhcp_tmp
;
dhcp_tmp
=
dhcp_tmp
->
next
)
{
void
*
start
=
&
dhcp_tmp
->
start
;
void
*
end
=
&
dhcp_tmp
->
end
;
#ifdef HAVE_DHCP6
if
(
family
==
AF_INET6
)
{
start
=
&
dhcp_tmp
->
start6
;
end
=
&
dhcp_tmp
->
end6
;
struct
in6_addr
subnet
=
dhcp_tmp
->
start6
;
setaddr6part
(
&
subnet
,
0
);
inet_ntop
(
AF_INET6
,
&
subnet
,
daemon
->
dhcp_buff2
,
256
);
}
#endif
if
(
family
!=
AF_INET
&&
(
dhcp_tmp
->
flags
&
CONTEXT_DEPRECATE
))
strcpy
(
daemon
->
namebuff
,
_
(
"prefix deprecated"
));
else
{
char
*
p
=
daemon
->
namebuff
;
p
+=
sprintf
(
p
,
_
(
"lease time "
));
prettyprint_time
(
p
,
dhcp_tmp
->
lease_time
);
}
inet_ntop
(
family
,
start
,
daemon
->
dhcp_buff
,
256
);
inet_ntop
(
family
,
end
,
daemon
->
dhcp_buff3
,
256
);
if
((
dhcp_tmp
->
flags
&
CONTEXT_DHCP
)
||
family
==
AF_INET
)
my_syslog
(
MS_DHCP
|
LOG_INFO
,
(
dhcp_tmp
->
flags
&
CONTEXT_RA_STATELESS
)
?
_
(
"%s stateless on %s%.0s%.0s"
)
:
(
dhcp_tmp
->
flags
&
CONTEXT_STATIC
)
?
_
(
"%s, static leases only on %.0s%s, %s"
)
:
(
dhcp_tmp
->
flags
&
CONTEXT_PROXY
)
?
_
(
"%s, proxy on subnet %.0s%s%.0s"
)
:
_
(
"%s, IP range %s -- %s, %s"
),
(
family
!=
AF_INET
)
?
"DHCPv6"
:
"DHCP"
,
daemon
->
dhcp_buff
,
daemon
->
dhcp_buff3
,
daemon
->
namebuff
);
if
(
dhcp_tmp
->
flags
&
CONTEXT_RA_NAME
)
my_syslog
(
MS_DHCP
|
LOG_INFO
,
_
(
"DHCPv4-derived IPv6 names on %s"
),
daemon
->
dhcp_buff2
);
if
(
dhcp_tmp
->
flags
&
(
CONTEXT_RA_ONLY
|
CONTEXT_RA_NAME
|
CONTEXT_RA_STATELESS
))
{
if
(
!
(
dhcp_tmp
->
flags
&
CONTEXT_DEPRECATE
))
{
char
*
p
=
daemon
->
namebuff
;
p
+=
sprintf
(
p
,
_
(
"prefix valid "
));
prettyprint_time
(
p
,
dhcp_tmp
->
lease_time
>
7200
?
dhcp_tmp
->
lease_time
:
7200
);
}
my_syslog
(
MS_DHCP
|
LOG_INFO
,
_
(
"SLAAC on %s %s"
),
daemon
->
dhcp_buff2
,
daemon
->
namebuff
);
}
}
#ifdef HAVE_DHCP6
if
(
family
==
AF_INET
)
{
family
=
AF_INET6
;
if
(
daemon
->
ra_contexts
)
dhcp_tmp
=
daemon
->
ra_contexts
;
else
dhcp_tmp
=
daemon
->
dhcp6
;
goto
again
;
}
#endif
for
(
context
=
daemon
->
dhcp
;
context
;
context
=
context
->
next
)
log_context
(
AF_INET
,
context
);
}
#endif
# ifdef HAVE_DHCP6
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
log_context
(
AF_INET6
,
context
);
if
(
daemon
->
doing_dhcp6
||
daemon
->
doing_ra
)
dhcp_construct_contexts
(
now
);
if
(
option_bool
(
OPT_RA
))
my_syslog
(
MS_DHCP
|
LOG_INFO
,
_
(
"IPv6 router advertisement enabled"
));
# endif
#endif
#ifdef HAVE_TFTP
if
(
option_bool
(
OPT_TFTP
))
...
...
@@ -818,13 +757,13 @@ int main (int argc, char **argv)
#endif
#ifdef HAVE_DHCP6
if
(
daemon
->
dhcp6
)
if
(
daemon
->
d
oing_d
hcp6
)
{
FD_SET
(
daemon
->
dhcp6fd
,
&
rset
);
bump_maxfd
(
daemon
->
dhcp6fd
,
&
maxfd
);
}
if
(
daemon
->
ra_contexts
)
if
(
daemon
->
doing_ra
)
{
FD_SET
(
daemon
->
icmp6fd
,
&
rset
);
bump_maxfd
(
daemon
->
icmp6fd
,
&
maxfd
);
...
...
@@ -888,7 +827,7 @@ int main (int argc, char **argv)
#ifdef HAVE_LINUX_NETWORK
if
(
FD_ISSET
(
daemon
->
netlinkfd
,
&
rset
))
netlink_multicast
();
netlink_multicast
(
now
);
#endif
/* Check for changes to resolv files once per second max. */
...
...
@@ -936,11 +875,11 @@ int main (int argc, char **argv)
}
#ifdef HAVE_DHCP6
if
(
daemon
->
dhcp6
&&
FD_ISSET
(
daemon
->
dhcp6fd
,
&
rset
))
if
(
daemon
->
d
oing_d
hcp6
&&
FD_ISSET
(
daemon
->
dhcp6fd
,
&
rset
))
dhcp6_packet
(
now
);
if
(
daemon
->
ra_contexts
&&
FD_ISSET
(
daemon
->
icmp6fd
,
&
rset
))
icmp6_packet
();
if
(
daemon
->
doing_ra
&&
FD_ISSET
(
daemon
->
icmp6fd
,
&
rset
))
icmp6_packet
(
now
);
#endif
# ifdef HAVE_SCRIPT
...
...
@@ -1120,13 +1059,13 @@ static void async_event(int pipe, time_t now)
case
EVENT_ALARM
:
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
if
(
daemon
->
dhcp
||
daemon
->
d
oing_d
hcp6
)
{
lease_prune
(
NULL
,
now
);
lease_update_file
(
now
);
}
#ifdef HAVE_DHCP6
else
if
(
daemon
->
ra_contexts
)
else
if
(
daemon
->
doing_ra
)
/* Not doing DHCP, so no lease system, manage alarms for ra only */
send_alarm
(
periodic_ra
(
now
),
now
);
#endif
...
...
@@ -1283,7 +1222,7 @@ void clear_cache_and_reload(time_t now)
cache_reload
();
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
if
(
daemon
->
dhcp
||
daemon
->
d
oing_d
hcp6
)
{
if
(
option_bool
(
OPT_ETHERS
))
dhcp_read_ethers
();
...
...
@@ -1294,7 +1233,7 @@ void clear_cache_and_reload(time_t now)
lease_update_dns
(
1
);
}
#ifdef HAVE_DHCP6
else
if
(
daemon
->
ra_contexts
)
else
if
(
daemon
->
doing_ra
)
/* Not doing DHCP, so no lease system, manage
alarms for ra only */
send_alarm
(
periodic_ra
(
now
),
now
);
...
...
@@ -1597,7 +1536,7 @@ int icmp_ping(struct in_addr addr)
set_log_writer
(
&
wset
,
&
maxfd
);
#ifdef HAVE_DHCP6
if
(
daemon
->
ra_contexts
)
if
(
daemon
->
doing_ra
)
{
FD_SET
(
daemon
->
icmp6fd
,
&
rset
);
bump_maxfd
(
daemon
->
icmp6fd
,
&
maxfd
);
...
...
@@ -1616,8 +1555,8 @@ int icmp_ping(struct in_addr addr)
check_dns_listeners
(
&
rset
,
now
);
#ifdef HAVE_DHCP6
if
(
daemon
->
ra_contexts
&&
FD_ISSET
(
daemon
->
icmp6fd
,
&
rset
))
icmp6_packet
();
if
(
daemon
->
doing_ra
&&
FD_ISSET
(
daemon
->
icmp6fd
,
&
rset
))
icmp6_packet
(
now
);
#endif
#ifdef HAVE_TFTP
...
...
src/dnsmasq.h
View file @
1f776932
...
...
@@ -667,7 +667,7 @@ struct cond_domain {
#endif
int
is6
;
struct
cond_domain
*
next
;
};
};
struct
dhcp_context
{
unsigned
int
lease_time
,
addr_epoch
;
...
...
@@ -679,6 +679,8 @@ struct dhcp_context {
struct
in6_addr
local6
;
int
prefix
,
if_index
;
time_t
ra_time
;
char
*
template_interface
;
int
valid
,
preferred
;
/* times from address for constructed contexts */
#endif
int
flags
;
struct
dhcp_netid
netid
,
*
filter
;
...
...
@@ -695,6 +697,11 @@ struct dhcp_context {
#define CONTEXT_RA_STATELESS 128
#define CONTEXT_DHCP 256
#define CONTEXT_DEPRECATE 512
#define CONTEXT_TEMPLATE 1024
/* create contexts using addresses */
#define CONTEXT_CONSTRUCTED 2048
#define CONTEXT_GC 4096
#define CONTEXT_RA 8192
struct
ping_result
{
struct
in_addr
addr
;
...
...
@@ -773,7 +780,7 @@ extern struct daemon {
int
port
,
query_port
,
min_port
;
unsigned
long
local_ttl
,
neg_ttl
,
max_ttl
,
max_cache_ttl
,
auth_ttl
;
struct
hostsfile
*
addn_hosts
;
struct
dhcp_context
*
dhcp
,
*
dhcp6
,
*
ra_contexts
;
struct
dhcp_context
*
dhcp
,
*
dhcp6
;
struct
dhcp_config
*
dhcp_conf
;
struct
dhcp_opt
*
dhcp_opts
,
*
dhcp_match
,
*
dhcp_opts6
,
*
dhcp_match6
;
struct
dhcp_vendor
*
dhcp_vendors
;
...
...
@@ -784,6 +791,7 @@ extern struct daemon {
struct
addr_list
*
override_relays
;
int
override
;
int
enable_pxe
;
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
;
...
...
@@ -1074,7 +1082,7 @@ void poll_resolv(int force, int do_reload, time_t now);
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
void
netlink_init
(
void
);
void
netlink_multicast
(
void
);
void
netlink_multicast
(
time_t
now
);
#endif
/* bpf.c */
...
...
@@ -1142,6 +1150,8 @@ struct dhcp_config *find_config6(struct dhcp_config *configs,
struct
dhcp_config
*
config_find_by_address6
(
struct
dhcp_config
*
configs
,
struct
in6_addr
*
net
,
int
prefix
,
u64
addr
);
void
make_duid
(
time_t
now
);
void
dhcp_construct_contexts
(
time_t
now
);
void
join_multicast
(
void
);
#endif
/* rfc3315.c */
...
...
@@ -1172,8 +1182,8 @@ void bindtodevice(int fd);
#endif
# ifdef HAVE_DHCP6
void
display_opts6
(
void
);
void
join_multicast
(
void
);
# endif
void
log_context
(
int
family
,
struct
dhcp_context
*
context
);
#endif
/* outpacket.c */
...
...
@@ -1192,16 +1202,14 @@ void put_opt6_string(char *s);
/* radv.c */
#ifdef HAVE_DHCP6
void
ra_init
(
time_t
now
);
void
icmp6_packet
(
void
);
void
icmp6_packet
(
time_t
now
);
time_t
periodic_ra
(
time_t
now
);
void
ra_start_unsolicted
(
time_t
now
,
struct
dhcp_context
*
context
);
#endif
/* slaac.c */
#ifdef HAVE_DHCP6
void
build_subnet_map
(
void
);
void
slaac_add_addrs
(
struct
dhcp_lease
*
lease
,
time_t
now
,
int
force
);
time_t
periodic_slaac
(
time_t
now
,
struct
dhcp_lease
*
leases
);
void
slaac_ping_reply
(
struct
in6_addr
*
sender
,
unsigned
char
*
packet
,
char
*
interface
,
struct
dhcp_lease
*
leases
);
void
schedule_subnet_map
(
void
);
#endif
src/lease.c
View file @
1f776932
...
...
@@ -308,7 +308,7 @@ void lease_update_file(time_t now)
#ifdef HAVE_DHCP6
/* do timed RAs and determine when the next is, also pings to potential SLAAC addresses */
if
(
daemon
->
ra_contexts
)
if
(
daemon
->
doing_ra
)
{
time_t
event
;
...
...
@@ -363,12 +363,15 @@ static int find_interface_v4(struct in_addr local, int if_index,
#ifdef HAVE_DHCP6
static
int
find_interface_v6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
struct
dhcp_lease
*
lease
;
(
void
)
scope
;
(
void
)
dad
;
(
void
)
preferred
;
(
void
)
valid
;
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
if
((
lease
->
flags
&
(
LEASE_TA
|
LEASE_NA
)))
...
...
@@ -395,10 +398,6 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
start-time. */
void
lease_find_interfaces
(
time_t
now
)
{
#ifdef HAVE_DHCP6
build_subnet_map
();
#endif
iface_enumerate
(
AF_INET
,
&
now
,
find_interface_v4
);
#ifdef HAVE_DHCP6
iface_enumerate
(
AF_INET6
,
&
now
,
find_interface_v6
);
...
...
src/netlink.c
View file @
1f776932
...
...
@@ -50,10 +50,14 @@ void netlink_init(void)
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
;
#ifdef HAVE_IPV6
addr
.
nl_groups
|=
RTMGRP_IPV6_ROUTE
;
if
(
daemon
->
ra_contexts
||
option_bool
(
OPT_CLEVERBIND
))
if
(
option_bool
(
OPT_CLEVERBIND
))
addr
.
nl_groups
|=
RTMGRP_IPV6_IFADDR
;
#endif
#ifdef HAVE_DHCP6
if
(
daemon
->
doing_ra
||
daemon
->
doing_dhcp6
)
addr
.
nl_groups
|=
RTMGRP_IPV6_IFADDR
;
#endif
...
...
@@ -187,7 +191,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
if
(
h
->
nlmsg_seq
!=
seq
||
h
->
nlmsg_pid
!=
netlink_pid
||
h
->
nlmsg_type
==
NLMSG_ERROR
)
{
/* May be multicast arriving async */
if
(
nl_async
(
h
)
&&
option_bool
(
OPT_CLEVERBIND
)
)
if
(
nl_async
(
h
))
newaddr
=
1
;
}
else
if
(
h
->
nlmsg_type
==
NLMSG_DONE
)
...
...
@@ -196,10 +200,15 @@ int iface_enumerate(int family, void *parm, int (*callback)())
after we complete as we're not re-entrant */
if
(
newaddr
)
{
enumerate_interfaces
();
create_bound_listeners
(
0
);
if
(
option_bool
(
OPT_CLEVERBIND
))
{
enumerate_interfaces
();
create_bound_listeners
(
0
);
}
#ifdef HAVE_DHCP6
dhcp_construct_contexts
(
dnsmasq_time
());
#endif
}
return
callback_ok
;
}
else
if
(
h
->
nlmsg_type
==
RTM_NEWADDR
&&
family
!=
AF_UNSPEC
&&
family
!=
AF_LOCAL
)
...
...
@@ -236,17 +245,24 @@ int iface_enumerate(int family, void *parm, int (*callback)())
else
if
(
ifa
->
ifa_family
==
AF_INET6
)
{
struct
in6_addr
*
addrp
=
NULL
;
u32
valid
=
0
,
preferred
=
0
;
while
(
RTA_OK
(
rta
,
len1
))
{
if
(
rta
->
rta_type
==
IFA_ADDRESS
)
addrp
=
((
struct
in6_addr
*
)(
rta
+
1
));
else
if
(
rta
->
rta_type
==
IFA_CACHEINFO
)
{
struct
ifa_cacheinfo
*
ifc
=
(
struct
ifa_cacheinfo
*
)(
rta
+
1
);
preferred
=
ifc
->
ifa_prefered
;
valid
=
ifc
->
ifa_valid
;
}
rta
=
RTA_NEXT
(
rta
,
len1
);
}
if
(
addrp
&&
callback_ok
)
if
(
!
((
*
callback
)(
addrp
,
(
int
)(
ifa
->
ifa_prefixlen
),
(
int
)(
ifa
->
ifa_scope
),
(
int
)(
ifa
->
ifa_index
),
(
int
)(
ifa
->
ifa_flags
&
IFA_F_TENTATIVE
),
parm
)))
(
int
)(
ifa
->
ifa_index
),
(
int
)(
ifa
->
ifa_flags
&
IFA_F_TENTATIVE
),
(
int
)
preferred
,
(
int
)
valid
,
parm
)))
callback_ok
=
0
;
}
#endif
...
...
@@ -305,7 +321,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
}
void
netlink_multicast
(
void
)
void
netlink_multicast
(
time_t
now
)
{
ssize_t
len
;
struct
nlmsghdr
*
h
;
...
...
@@ -318,7 +334,7 @@ void netlink_multicast(void)
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
)
&&
option_bool
(
OPT_CLEVERBIND
)
)
if
(
nl_async
(
h
))
newaddr
=
1
;
/* restore non-blocking status */
...
...
@@ -326,8 +342,14 @@ void netlink_multicast(void)
if
(
newaddr
)
{
enumerate_interfaces
();
create_bound_listeners
(
0
);
if
(
option_bool
(
OPT_CLEVERBIND
))
{
enumerate_interfaces
();
create_bound_listeners
(
0
);
}
#ifdef HAVE_DHCP6
dhcp_construct_contexts
(
now
);
#endif
}
}
...
...
@@ -371,21 +393,8 @@ static int nl_async(struct nlmsghdr *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
);
}
#endif
return
1
;
/* clever bind mode - rescan */
}
else
if
(
h
->
nlmsg_type
==
RTM_NEWADDR
||
h
->
nlmsg_type
==
RTM_DELADDR
)
return
1
;
/* clever bind mode - rescan */
return
0
;
}
...
...
src/network.c
View file @
1f776932
...
...
@@ -289,7 +289,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
#ifdef HAVE_IPV6
static
int
iface_allowed_v6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
union
mysockaddr
addr
;
struct
in_addr
netmask
;
/* dummy */
...
...
@@ -297,6 +298,8 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
(
void
)
prefix
;
/* warning */
(
void
)
scope
;
/* warning */
(
void
)
preferred
;
(
void
)
valid
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
#ifdef HAVE_SOCKADDR_SA_LEN
...
...
src/option.c
View file @
1f776932
...
...
@@ -2180,7 +2180,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case
'F'
:
/* --dhcp-range */
{
int
k
,
leasepos
=
2
;
char
*
cp
,
*
a
[
7
]
=
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
char
*
cp
,
*
a
[
8
]
=
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
struct
dhcp_context
*
new
=
opt_malloc
(
sizeof
(
struct
dhcp_context
));
memset
(
new
,
0
,
sizeof
(
*
new
));
...
...
@@ -2227,7 +2227,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
}
for
(
k
=
1
;
k
<
7
;
k
++
)
for
(
k
=
1
;
k
<
8
;
k
++
)
if
(
!
(
a
[
k
]
=
split
(
a
[
k
-
1
])))
break
;
...
...
@@ -2284,28 +2284,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if
(
strcmp
(
a
[
leasepos
],
"static"
)
==
0
)
new
->
flags
|=
CONTEXT_STATIC
|
CONTEXT_DHCP
;
else
if
(
strcmp
(
a
[
leasepos
],
"ra-only"
)
==
0
||
strcmp
(
a
[
leasepos
],
"slaac"
)
==
0
)
new
->
flags
|=
CONTEXT_RA_ONLY
;
new
->
flags
|=
CONTEXT_RA_ONLY
|
CONTEXT_RA
;
else
if
(
strcmp
(
a
[
leasepos
],
"ra-names"
)
==
0
)
new
->
flags
|=
CONTEXT_RA_NAME
;
new
->
flags
|=
CONTEXT_RA_NAME
|
CONTEXT_RA
;
else
if
(
strcmp
(
a
[
leasepos
],
"ra-stateless"
)
==
0
)
new
->
flags
|=
CONTEXT_RA_STATELESS
|
CONTEXT_DHCP
;
new
->
flags
|=
CONTEXT_RA_STATELESS
|
CONTEXT_DHCP
|
CONTEXT_RA
;
else
if
(
leasepos
==
1
&&
inet_pton
(
AF_INET6
,
a
[
leasepos
],
&
new
->
end6
))
new
->
flags
|=
CONTEXT_DHCP
;
else
if
(
strstr
(
a
[
leasepos
],
"constructor:"
)
==
a
[
leasepos
])
{
new
->
template_interface
=
opt_string_alloc
(
a
[
leasepos
]
+
12
);
new
->
flags
|=
CONTEXT_TEMPLATE
;
}
else
break
;
}
if
(
new
->
flags
&
CONTEXT_DHCP
)
{
new
->
next
=
daemon
->
dhcp6
;
daemon
->
dhcp6
=
new
;
}
else
{
new
->
next
=
daemon
->
ra_contexts
;
daemon
->
ra_contexts
=
new
;
}
new
->
next
=
daemon
->
dhcp6
;
daemon
->
dhcp6
=
new
;
/* bare integer < 128 is prefix value */
if
(
leasepos
<
k
)
{
...
...
@@ -2317,10 +2314,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
new
->
prefix
=
pref
;
leasepos
++
;
if
((
new
->
flags
&
(
CONTEXT_RA_ONLY
|
CONTEXT_RA_NAME
|
CONTEXT_RA_STATELESS
))
&&
new
->
prefix
!=
64
)
ret_err
(
_
(
"prefix must be exactly 64 for RA subnets"
));
else
if
(
new
->
prefix
<
64
)
if
(
new
->
prefix
!=
64
)
{
if
((
new
->
flags
&
(
CONTEXT_RA_ONLY
|
CONTEXT_RA_NAME
|
CONTEXT_RA_STATELESS
)))
ret_err
(
_
(
"prefix must be exactly 64 for RA subnets"
));
else
if
(
new
->
template_interface
)
ret_err
(
_
(
"prefix must be exactly 64 for subnet constructors"
));
}
if
(
new
->
prefix
<
64
)
ret_err
(
_
(
"prefix must be at least 64"
));
}
}
...
...
src/radv.c
View file @
1f776932
...
...
@@ -27,6 +27,7 @@
#include <netinet/icmp6.h>
struct
ra_param
{
time_t
now
;
int
ind
,
managed
,
other
,
found_context
,
first
;
char
*
if_name
;
struct
dhcp_netid
*
tags
;
...
...
@@ -37,11 +38,13 @@ struct search_param {
time_t
now
;
int
iface
;
};
static
void
send_ra
(
int
iface
,
char
*
iface_name
,
struct
in6_addr
*
dest
);
static
void
send_ra
(
time_t
now
,
int
iface
,
char
*
iface_name
,
struct
in6_addr
*
dest
);
static
int
add_prefixes
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
);
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
);
static
int
iface_search
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
);
int
scope
,
int
if_index
,
int
dad
,
int
prefered
,
int
valid
,
void
*
vparam
);
static
int
add_lla
(
int
index
,
unsigned
int
type
,
char
*
mac
,
size_t
maclen
,
void
*
parm
);
static
int
hop_limit
;
...
...
@@ -62,7 +65,7 @@ void ra_init(time_t now)
expand_buf
(
&
daemon
->
outpacket
,
sizeof
(
struct
dhcp_packet
));
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
))
break
;
...
...
@@ -98,14 +101,17 @@ void ra_start_unsolicted(time_t now, struct dhcp_context *context)
if
(
context
)
context
->
ra_time
=
now
;
else
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
context
->
ra_time
=
now
+
(
rand16
()
/
13000
);
/* range 0 - 5 */
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
(
context
->
flags
&
CONTEXT_RA
)
context
->
ra_time
=
now
+
(
rand16
()
/
13000
);
/* range 0 - 5 */
else
context
->
ra_time
=
0
;
/* re-do frequently for a minute or so, in case the first gets lost. */
ra_short_period_start
=
now
;
}
void
icmp6_packet
(
void
)
void
icmp6_packet
(
time_t
now
)
{
char
interface
[
IF_NAMESIZE
+
1
];
ssize_t
sz
;
...
...
@@ -174,11 +180,11 @@ void icmp6_packet(void)
my_syslog
(
MS_DHCP
|
LOG_INFO
,
"RTR-SOLICIT(%s) %s"
,
interface
,
mac
);
/* source address may not be valid in solicit request. */
send_ra
(
if_index
,
interface
,
!
IN6_IS_ADDR_UNSPECIFIED
(
&
from
.
sin6_addr
)
?
&
from
.
sin6_addr
:
NULL
);
send_ra
(
now
,
if_index
,
interface
,
!
IN6_IS_ADDR_UNSPECIFIED
(
&
from
.
sin6_addr
)
?
&
from
.
sin6_addr
:
NULL
);
}
}
static
void
send_ra
(
int
iface
,
char
*
iface_name
,
struct
in6_addr
*
dest
)
static
void
send_ra
(
time_t
now
,
int
iface
,
char
*
iface_name
,
struct
in6_addr
*
dest
)
{
struct
ra_packet
*
ra
;
struct
ra_param
parm
;
...
...
@@ -206,13 +212,14 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
parm
.
found_context
=
0
;
parm
.
if_name
=
iface_name
;
parm
.
first
=
1
;
parm
.
now
=
now
;
/* set tag with name == interface */
iface_id
.
net
=
iface_name
;
iface_id
.
next
=
NULL
;
parm
.
tags
=
&
iface_id
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
{
context
->
flags
&=
~
CONTEXT_RA_DONE
;
context
->
netid
.
next
=
&
context
->
netid
;
...
...
@@ -320,28 +327,32 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
}
static
int
add_prefixes
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
struct
ra_param
*
param
=
vparam
;
(
void
)
scope
;
/* warning */
(
void
)
dad
;
(
void
)
preferred
;
(
void
)
valid
;
if
(
if_index
==
param
->
ind
)
{
if
(
IN6_IS_ADDR_LINKLOCAL
(
local
))
param
->
link_local
=
*
local
;
else
if
(
!
IN6_IS_ADDR_LOOPBACK
(
local
)
&&
!
IN6_IS_ADDR_LINKLOCAL
(
local
)
&&
!
IN6_IS_ADDR_MULTICAST
(
local
))
{
int
do_prefix
=
0
;
int
do_slaac
=
0
;
int
deprecate
=
0
;
int
found_constructed
=
0
;
unsigned
int
time
=
0xffffffff
;
int
calc_valid
=
0
,
calc_preferred
=
0
;
struct
dhcp_context
*
context
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
(
prefix
==
context
->
prefix
&&
is_same_net6
(
local
,
&
context
->
start6
,
prefix
)
&&
is_same_net6
(
local
,
&
context
->
end6
,
prefix
))
...
...
@@ -365,7 +376,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param
->
managed
=
1
;
param
->
other
=
1
;
}
if
(
context
->
flags
&
CONTEXT_CONSTRUCTED
)
{
found_constructed
=
1
;
calc_valid
=
context
->
valid
;
calc_preferred
=
context
->
preferred
;
if
(
context
->
valid
!=
-
1
)
calc_valid
-=
(
int
)
param
->
now
;
if
(
context
->
preferred
!=
-
1
)
calc_preferred
-=
(
int
)
param
->
now
;
}
/* find floor time */
if
(
time
>
context
->
lease_time
)
time
=
context
->
lease_time
;
...
...
@@ -395,6 +417,12 @@ static int add_prefixes(struct in6_addr *local, int prefix,
param
->
first
=
0
;
param
->
found_context
=
1
;
}
if
(
!
found_constructed
)
{
calc_valid
=
time
;
calc_preferred
=
deprecate
?
0
:
time
;
}
if
(
do_prefix
)
{
...
...
@@ -414,8 +442,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
opt
->
prefix_len
=
prefix
;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt
->
flags
=
do_slaac
?
0xC0
:
0x80
;
opt
->
valid_lifetime
=
htonl
(
time
);
opt
->
preferred_lifetime
=
htonl
(
deprecate
?
0
:
time
);
opt
->
valid_lifetime
=
htonl
(
calc_valid
);
opt
->
preferred_lifetime
=
htonl
(
calc_preferred
);
opt
->
reserved
=
0
;
opt
->
prefix
=
*
local
;
...
...
@@ -462,7 +490,7 @@ time_t periodic_ra(time_t now)
while
(
1
)
{
/* find overdue events, and time of first future event */
for
(
next_event
=
0
,
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
next_event
=
0
,
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
(
context
->
ra_time
!=
0
)
{
if
(
difftime
(
context
->
ra_time
,
now
)
<=
0
.
0
)
...
...
@@ -492,22 +520,25 @@ time_t periodic_ra(time_t now)
if
(
tmp
->
name
&&
(
strcmp
(
tmp
->
name
,
interface
)
==
0
))
break
;
if
(
!
tmp
)
send_ra
(
param
.
iface
,
interface
,
NULL
);
send_ra
(
now
,
param
.
iface
,
interface
,
NULL
);
}
}
return
next_event
;
}
static
int
iface_search
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
int
preferred
,
int
valid
,
void
*
vparam
)
{
struct
search_param
*
param
=
vparam
;
struct
dhcp_context
*
context
;
(
void
)
scope
;
(
void
)
dad
;
(
void
)
preferred
;
(
void
)
valid
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
(
prefix
==
context
->
prefix
&&
is_same_net6
(
local
,
&
context
->
start6
,
prefix
)
&&
is_same_net6
(
local
,
&
context
->
end6
,
prefix
))
...
...
src/slaac.c
View file @
1f776932
...
...
@@ -20,7 +20,6 @@
#include <netinet/icmp6.h>
static
int
map_rebuild
=
0
;
static
int
ping_id
=
0
;
void
slaac_add_addrs
(
struct
dhcp_lease
*
lease
,
time_t
now
,
int
force
)
...
...
@@ -38,7 +37,7 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
old
=
lease
->
slaac_address
;
lease
->
slaac_address
=
NULL
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
)
&&
lease
->
last_interface
==
context
->
if_index
)
{
struct
in6_addr
addr
=
context
->
start6
;
...
...
@@ -123,7 +122,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
struct
slaac_address
*
slaac
;
time_t
next_event
=
0
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
))
break
;
...
...
@@ -134,12 +133,6 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
while
(
ping_id
==
0
)
ping_id
=
rand16
();
if
(
map_rebuild
)
{
map_rebuild
=
0
;
build_subnet_map
();
}
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
for
(
slaac
=
lease
->
slaac_address
;
slaac
;
slaac
=
slaac
->
next
)
{
...
...
@@ -211,51 +204,4 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
lease_update_dns
(
gotone
);
}
/* Build a map from ra-names subnets to corresponding interfaces. This
is used to go from DHCPv4 leases to SLAAC addresses,
interface->IPv6-subnet, IPv6-subnet + MAC address -> SLAAC.
*/
static
int
add_subnet
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
{
struct
dhcp_context
*
context
;
(
void
)
scope
;
(
void
)
dad
;
(
void
)
vparam
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
)
&&
prefix
==
context
->
prefix
&&
is_same_net6
(
local
,
&
context
->
start6
,
prefix
)
&&
is_same_net6
(
local
,
&
context
->
end6
,
prefix
))
{
context
->
if_index
=
if_index
;
context
->
local6
=
*
local
;
}
return
1
;
}
void
build_subnet_map
(
void
)
{
struct
dhcp_context
*
context
;
int
ok
=
0
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
{
context
->
if_index
=
0
;
if
((
context
->
flags
&
CONTEXT_RA_NAME
))
ok
=
1
;
}
/* ra-names configured */
if
(
ok
)
iface_enumerate
(
AF_INET6
,
NULL
,
add_subnet
);
}
void
schedule_subnet_map
(
void
)
{
map_rebuild
=
1
;
}
#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