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
353ae4d2
Commit
353ae4d2
authored
Mar 19, 2012
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Check assumed SLAAC addresses by pinging them.
parent
e759d426
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
414 additions
and
177 deletions
+414
-177
Makefile
Makefile
+1
-1
bld/Android.mk
bld/Android.mk
+1
-1
src/dhcp.c
src/dhcp.c
+1
-1
src/dhcp6.c
src/dhcp6.c
+1
-1
src/dnsmasq.c
src/dnsmasq.c
+21
-10
src/dnsmasq.h
src/dnsmasq.h
+25
-14
src/lease.c
src/lease.c
+70
-54
src/netlink.c
src/netlink.c
+3
-2
src/radv-protocol.h
src/radv-protocol.h
+7
-3
src/radv.c
src/radv.c
+34
-83
src/rfc2131.c
src/rfc2131.c
+5
-5
src/rfc3315.c
src/rfc3315.c
+2
-2
src/slaac.c
src/slaac.c
+243
-0
No files found.
Makefile
View file @
353ae4d2
...
...
@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
objs
=
cache.o rfc1035.o util.o option.o forward.o network.o
\
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o
\
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o
\
dhcp-common.o outpacket.o radv.o
dhcp-common.o outpacket.o radv.o
slaac.o
hdrs
=
dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h
\
dns-protocol.h radv-protocol.h
...
...
bld/Android.mk
View file @
353ae4d2
...
...
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
netlink.c network.c option.c rfc1035.c
\
rfc2131.c tftp.c util.c conntrack.c
\
dhcp6.c rfc3315.c dhcp-common.c outpacket.c
\
radv.c
radv.c
slaac.c
LOCAL_MODULE
:=
dnsmasq
...
...
src/dhcp.c
View file @
353ae4d2
...
...
@@ -299,7 +299,7 @@ void dhcp_packet(time_t now, int pxe_fd)
iov
.
iov_len
=
dhcp_reply
(
parm
.
current
,
ifr
.
ifr_name
,
iface_index
,
(
size_t
)
sz
,
now
,
unicast_dest
,
&
is_inform
,
pxe_fd
,
iface_addr
);
lease_update_file
(
now
);
lease_update_dns
();
lease_update_dns
(
0
);
if
(
iov
.
iov_len
==
0
)
return
;
...
...
src/dhcp6.c
View file @
353ae4d2
...
...
@@ -139,7 +139,7 @@ void dhcp6_packet(time_t now)
sz
,
IN6_IS_ADDR_MULTICAST
(
&
from
.
sin6_addr
),
now
);
lease_update_file
(
now
);
lease_update_dns
();
lease_update_dns
(
0
);
/* The port in the source address of the original request should
be correct, but at least once client sends from the server port,
...
...
src/dnsmasq.c
View file @
353ae4d2
...
...
@@ -23,6 +23,7 @@ struct daemon *daemon;
static
volatile
pid_t
pid
=
0
;
static
volatile
int
pipewrite
;
static
int
alarm_queued
=
0
;
static
int
set_dns_listeners
(
time_t
now
,
fd_set
*
set
,
int
*
maxfdp
);
static
void
check_dns_listeners
(
fd_set
*
set
,
time_t
now
);
...
...
@@ -864,9 +865,23 @@ static void sig_handler(int sig)
}
}
void
send_alarm
(
void
)
/* now == 0 -> queue immediate callback */
void
send_alarm
(
time_t
event
,
time_t
now
)
{
send_event
(
pipewrite
,
EVENT_ALARM
,
0
,
NULL
);
if
(
now
!=
0
&&
event
==
0
)
return
;
if
((
now
==
0
||
difftime
(
event
,
now
)
<=
0
.
0
))
{
if
(
!
alarm_queued
)
{
send_event
(
pipewrite
,
EVENT_ALARM
,
0
,
NULL
);
alarm_queued
=
1
;
}
}
else
alarm
((
unsigned
)
difftime
(
event
,
now
));
}
void
send_event
(
int
fd
,
int
event
,
int
data
,
char
*
msg
)
...
...
@@ -980,6 +995,7 @@ static void async_event(int pipe, time_t now)
break
;
case
EVENT_ALARM
:
alarm_queued
=
0
;
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
{
...
...
@@ -988,13 +1004,8 @@ static void async_event(int pipe, time_t now)
}
#ifdef HAVE_DHCP6
else
if
(
daemon
->
ra_contexts
)
{
/* Not doing DHCP, so no lease system, manage
alarms for ra only */
time_t
next_event
=
periodic_ra
(
now
);
if
(
next_event
!=
0
)
alarm
((
unsigned
)
difftime
(
next_event
,
now
));
}
/* Not doing DHCP, so no lease system, manage alarms for ra only */
send_alarm
(
periodic_ra
(
now
),
now
);
#endif
#endif
break
;
...
...
@@ -1158,7 +1169,7 @@ void clear_cache_and_reload(time_t now)
check_dhcp_hosts
(
0
);
lease_update_from_configs
();
lease_update_file
(
now
);
lease_update_dns
();
lease_update_dns
(
1
);
}
#ifdef HAVE_DHCP6
else
if
(
daemon
->
ra_contexts
)
...
...
src/dnsmasq.h
View file @
353ae4d2
...
...
@@ -466,6 +466,7 @@ struct frec {
#define LEASE_USED 16
/* used this DHCPv6 transaction */
#define LEASE_NA 32
/* IPv6 no-temporary lease */
#define LEASE_TA 64
/* IPv6 temporary lease */
#define LEASE_HAVE_HWADDR 128
/* Have set hwaddress */
struct
dhcp_lease
{
int
clid_len
;
/* length of client identifier */
...
...
@@ -483,6 +484,14 @@ struct dhcp_lease {
unsigned
char
*
extradata
;
unsigned
int
extradata_len
,
extradata_size
;
int
last_interface
;
#ifdef HAVE_DHCP6
struct
slaac_address
{
struct
in6_addr
addr
,
local
;
time_t
ping_time
;
int
backoff
;
/* zero -> confirmed */
struct
slaac_address
*
next
;
}
*
slaac_address
;
#endif
struct
dhcp_lease
*
next
;
};
...
...
@@ -627,7 +636,7 @@ struct dhcp_context {
#ifdef HAVE_DHCP6
struct
in6_addr
start6
,
end6
;
/* range of available addresses */
struct
in6_addr
local6
;
int
prefix
;
int
prefix
,
if_index
;
time_t
ra_time
;
#endif
int
flags
;
...
...
@@ -651,13 +660,6 @@ struct ping_result {
struct
ping_result
*
next
;
};
struct
subnet_map
{
int
iface
;
struct
in6_addr
subnet
;
struct
subnet_map
*
next
;
};
struct
tftp_file
{
int
refcount
,
fd
;
off_t
size
;
...
...
@@ -957,7 +959,7 @@ char *host_from_dns(struct in_addr addr);
/* lease.c */
#ifdef HAVE_DHCP
void
lease_update_file
(
time_t
now
);
void
lease_update_dns
();
void
lease_update_dns
(
int
force
);
void
lease_init
(
time_t
now
);
struct
dhcp_lease
*
lease4_allocate
(
struct
in_addr
addr
);
#ifdef HAVE_DHCP6
...
...
@@ -966,12 +968,13 @@ struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
int
lease_type
,
int
iaid
,
struct
in6_addr
*
addr
);
struct
dhcp_lease
*
lease6_find_by_addr
(
struct
in6_addr
*
net
,
int
prefix
,
u64
addr
);
u64
lease_find_max_addr6
(
struct
dhcp_context
*
context
);
void
lease_ping_reply
(
struct
in6_addr
*
sender
,
unsigned
char
*
packet
,
char
*
interface
);
#endif
void
lease_set_hwaddr
(
struct
dhcp_lease
*
lease
,
unsigned
char
*
hwaddr
,
unsigned
char
*
clid
,
int
hw_len
,
int
hw_type
,
int
clid_len
);
unsigned
char
*
clid
,
int
hw_len
,
int
hw_type
,
int
clid_len
,
time_t
now
);
void
lease_set_hostname
(
struct
dhcp_lease
*
lease
,
char
*
name
,
int
auth
,
char
*
domain
,
char
*
config_domain
);
void
lease_set_expires
(
struct
dhcp_lease
*
lease
,
unsigned
int
len
,
time_t
now
);
void
lease_set_interface
(
struct
dhcp_lease
*
lease
,
int
interface
);
void
lease_set_interface
(
struct
dhcp_lease
*
lease
,
int
interface
,
time_t
now
);
struct
dhcp_lease
*
lease_find_by_client
(
unsigned
char
*
hwaddr
,
int
hw_len
,
int
hw_type
,
unsigned
char
*
clid
,
int
clid_len
);
struct
dhcp_lease
*
lease_find_by_addr
(
struct
in_addr
addr
);
...
...
@@ -1000,7 +1003,7 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int
make_icmp_sock
(
void
);
int
icmp_ping
(
struct
in_addr
addr
);
#endif
void
send_alarm
(
void
);
void
send_alarm
(
time_t
event
,
time_t
now
);
void
send_event
(
int
fd
,
int
event
,
int
data
,
char
*
msg
);
void
clear_cache_and_reload
(
time_t
now
);
void
poll_resolv
(
int
force
,
int
do_reload
,
time_t
now
);
...
...
@@ -1121,6 +1124,14 @@ void put_opt6_string(char *s);
void
ra_init
(
time_t
now
);
void
icmp6_packet
(
void
);
time_t
periodic_ra
(
time_t
now
);
void
ra_start_unsolicted
(
time_t
now
);
struct
subnet_map
*
build_subnet_map
(
void
);
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
);
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 @
353ae4d2
...
...
@@ -97,7 +97,8 @@ void lease_init(time_t now)
if
(
hw_type
==
0
&&
hw_len
!=
0
)
hw_type
=
ARPHRD_ETHER
;
lease_set_hwaddr
(
lease
,
(
unsigned
char
*
)
daemon
->
dhcp_buff2
,
(
unsigned
char
*
)
daemon
->
packet
,
hw_len
,
hw_type
,
clid_len
);
lease_set_hwaddr
(
lease
,
(
unsigned
char
*
)
daemon
->
dhcp_buff2
,
(
unsigned
char
*
)
daemon
->
packet
,
hw_len
,
hw_type
,
clid_len
,
now
);
if
(
strcmp
(
daemon
->
dhcp_buff
,
"*"
)
!=
0
)
lease_set_hostname
(
lease
,
daemon
->
dhcp_buff
,
0
,
get_domain
(
lease
->
addr
),
NULL
);
...
...
@@ -118,7 +119,7 @@ void lease_init(time_t now)
if
((
lease
=
lease6_allocate
(
&
addr
.
addr
.
addr6
,
lease_type
)))
{
lease_set_hwaddr
(
lease
,
NULL
,
(
unsigned
char
*
)
daemon
->
packet
,
0
,
hw_type
,
clid_len
);
lease_set_hwaddr
(
lease
,
NULL
,
(
unsigned
char
*
)
daemon
->
packet
,
0
,
hw_type
,
clid_len
,
now
);
if
(
strcmp
(
daemon
->
dhcp_buff
,
"*"
)
!=
0
)
lease_set_hostname
(
lease
,
daemon
->
dhcp_buff
,
0
,
get_domain6
((
struct
in6_addr
*
)
lease
->
hwaddr
),
NULL
);
...
...
@@ -306,9 +307,16 @@ void lease_update_file(time_t now)
next_event
=
0
;
#ifdef HAVE_DHCP6
/* do timed RAs and determine when the next is */
/* do timed RAs and determine when the next is
, also pings to potential SLAAC addresses
*/
if
(
daemon
->
ra_contexts
)
next_event
=
periodic_ra
(
now
);
{
time_t
ra_event
=
periodic_slaac
(
now
,
leases
);
next_event
=
periodic_ra
(
now
);
if
(
next_event
==
0
||
difftime
(
next_event
,
ra_event
)
>
0
.
0
)
next_event
=
ra_event
;
}
#endif
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
...
...
@@ -326,8 +334,7 @@ void lease_update_file(time_t now)
(
unsigned
int
)
difftime
(
next_event
,
now
));
}
if
(
next_event
!=
0
)
alarm
((
unsigned
)
difftime
(
next_event
,
now
));
send_alarm
(
next_event
,
now
);
}
...
...
@@ -342,7 +349,7 @@ static int find_interface_v4(struct in_addr local, int if_index,
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
if
(
!
(
lease
->
flags
&
(
LEASE_TA
|
LEASE_NA
)))
if
(
is_same_net
(
local
,
lease
->
addr
,
netmask
))
lease
->
last_interface
=
if_index
;
lease
_set_interface
(
lease
,
if_index
,
*
((
time_t
*
)
vparam
))
;
return
1
;
}
...
...
@@ -353,17 +360,22 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
{
struct
dhcp_lease
*
lease
;
(
void
)
scope
;
(
void
)
vparam
;
(
void
)
scope
;
(
void
)
dad
;
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
if
((
lease
->
flags
&
(
LEASE_TA
|
LEASE_NA
)))
if
(
is_same_net6
(
local
,
(
struct
in6_addr
*
)
&
lease
->
hwaddr
,
prefix
))
lease
->
last_interface
=
if_index
;
lease
_set_interface
(
lease
,
if_index
,
*
((
time_t
*
)
vparam
))
;
return
1
;
}
void
lease_ping_reply
(
struct
in6_addr
*
sender
,
unsigned
char
*
packet
,
char
*
interface
)
{
slaac_ping_reply
(
sender
,
packet
,
interface
,
leases
);
}
#endif
...
...
@@ -373,9 +385,13 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
start-time. */
void
lease_find_interfaces
(
time_t
now
)
{
iface_enumerate
(
AF_INET
,
NULL
,
find_interface_v4
);
#ifdef HAVE_DHCP6
iface_enumerate
(
AF_INET6
,
NULL
,
find_interface_v6
);
build_subnet_map
();
#endif
iface_enumerate
(
AF_INET
,
&
now
,
find_interface_v4
);
#ifdef HAVE_DHCP6
iface_enumerate
(
AF_INET6
,
&
now
,
find_interface_v6
);
/* If we're not doing DHCPv6, and there are not v6 leases, don't add the DUID to the database */
if
(
!
daemon
->
duid
&&
daemon
->
dhcp6
)
...
...
@@ -388,16 +404,12 @@ void lease_find_interfaces(time_t now)
void
lease_update_dns
(
void
)
void
lease_update_dns
(
int
force
)
{
struct
dhcp_lease
*
lease
;
if
(
daemon
->
port
!=
0
&&
dns_dirty
)
if
(
daemon
->
port
!=
0
&&
(
dns_dirty
||
force
)
)
{
#ifdef HAVE_DHCP6
struct
subnet_map
*
subnets
=
build_subnet_map
();
#endif
cache_unhash_dhcp
();
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
...
...
@@ -409,41 +421,15 @@ void lease_update_dns(void)
prot
=
AF_INET6
;
else
if
(
lease
->
hostname
||
lease
->
fqdn
)
{
struct
subnet_map
*
map
;
for
(
map
=
subnets
;
map
;
map
=
map
->
next
)
if
(
lease
->
last_interface
==
map
->
iface
)
struct
slaac_address
*
slaac
;
for
(
slaac
=
lease
->
slaac_address
;
slaac
;
slaac
=
slaac
->
next
)
if
(
slaac
->
backoff
==
0
)
{
struct
in6_addr
addr
=
map
->
subnet
;
if
(
lease
->
hwaddr_len
==
6
&&
(
lease
->
hwaddr_type
==
ARPHRD_ETHER
||
lease
->
hwaddr_type
==
ARPHRD_IEEE802
))
{
/* convert MAC address to EUI-64 */
memcpy
(
&
addr
.
s6_addr
[
8
],
lease
->
hwaddr
,
3
);
memcpy
(
&
addr
.
s6_addr
[
13
],
&
lease
->
hwaddr
[
3
],
3
);
addr
.
s6_addr
[
11
]
=
0xff
;
addr
.
s6_addr
[
12
]
=
0xfe
;
}
#if defined(ARPHRD_EUI64)
else
if
(
lease
->
hwaddr_len
==
8
&&
lease
->
hwaddr_type
==
ARPHRD_EUI64
)
memcpy
(
&
addr
.
s6_addr
[
8
],
lease
->
hwaddr
,
8
);
#endif
#if defined(ARPHRD_IEEE1394) && defined(ARPHRD_EUI64)
else
if
(
lease
->
clid_len
==
9
&&
lease
->
clid
[
0
]
==
ARPHRD_EUI64
&&
lease
->
hwaddr_type
==
ARPHRD_IEEE1394
)
/* firewire has EUI-64 identifier as clid */
memcpy
(
&
addr
.
s6_addr
[
8
],
&
lease
->
clid
[
1
],
8
);
#endif
else
continue
;
addr
.
s6_addr
[
8
]
^=
0x02
;
if
(
lease
->
fqdn
)
cache_add_dhcp_entry
(
lease
->
fqdn
,
AF_INET6
,
(
struct
all_addr
*
)
&
addr
,
lease
->
expires
);
cache_add_dhcp_entry
(
lease
->
fqdn
,
AF_INET6
,
(
struct
all_addr
*
)
&
slaac
->
addr
,
lease
->
expires
);
if
(
!
option_bool
(
OPT_DHCP_FQDN
)
&&
lease
->
hostname
)
cache_add_dhcp_entry
(
lease
->
hostname
,
AF_INET6
,
(
struct
all_addr
*
)
&
addr
,
lease
->
expires
);
cache_add_dhcp_entry
(
lease
->
hostname
,
AF_INET6
,
(
struct
all_addr
*
)
&
slaac
->
addr
,
lease
->
expires
);
}
}
#endif
...
...
@@ -713,8 +699,13 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
}
void
lease_set_hwaddr
(
struct
dhcp_lease
*
lease
,
unsigned
char
*
hwaddr
,
unsigned
char
*
clid
,
int
hw_len
,
int
hw_type
,
int
clid_len
)
unsigned
char
*
clid
,
int
hw_len
,
int
hw_type
,
int
clid_len
,
time_t
now
)
{
#ifdef HAVE_DHCP6
int
change
=
0
;
lease
->
flags
|=
LEASE_HAVE_HWADDR
;
#endif
if
(
hw_len
!=
lease
->
hwaddr_len
||
hw_type
!=
lease
->
hwaddr_type
||
(
hw_len
!=
0
&&
memcmp
(
lease
->
hwaddr
,
hwaddr
,
hw_len
)
!=
0
))
...
...
@@ -725,6 +716,9 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
lease
->
hwaddr_type
=
hw_type
;
lease
->
flags
|=
LEASE_CHANGED
;
file_dirty
=
1
;
/* run script on change */
#ifdef HAVE_DHCP6
change
=
1
;
#endif
}
/* only update clid when one is available, stops packets
...
...
@@ -742,17 +736,27 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
free
(
lease
->
clid
);
if
(
!
(
lease
->
clid
=
whine_malloc
(
clid_len
)))
return
;
#ifdef HAVE_DHCP6
change
=
1
;
#endif
}
else
if
(
memcmp
(
lease
->
clid
,
clid
,
clid_len
)
!=
0
)
{
lease
->
flags
|=
LEASE_AUX_CHANGED
;
file_dirty
=
1
;
#ifdef HAVE_DHCP6
change
=
1
;
#endif
}
lease
->
clid_len
=
clid_len
;
memcpy
(
lease
->
clid
,
clid
,
clid_len
);
}
#ifdef HAVE_DHCP6
if
(
change
)
slaac_add_addrs
(
lease
,
now
);
#endif
}
static
void
kill_name
(
struct
dhcp_lease
*
lease
)
...
...
@@ -870,13 +874,17 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *do
lease
->
flags
|=
LEASE_CHANGED
;
/* run script on change */
}
void
lease_set_interface
(
struct
dhcp_lease
*
lease
,
int
interface
)
void
lease_set_interface
(
struct
dhcp_lease
*
lease
,
int
interface
,
time_t
now
)
{
if
(
lease
->
last_interface
==
interface
)
return
;
lease
->
last_interface
=
interface
;
lease
->
flags
|=
LEASE_CHANGED
;
#ifdef HAVE_DHCP6
slaac_add_addrs
(
lease
,
now
);
#endif
}
void
rerun_scripts
(
void
)
...
...
@@ -919,6 +927,14 @@ int do_script_run(time_t now)
}
else
{
#ifdef HAVE_DHCP6
struct
slaac_address
*
slaac
,
*
tmp
;
for
(
slaac
=
lease
->
slaac_address
;
slaac
;
slaac
=
tmp
)
{
tmp
=
slaac
->
next
;
free
(
slaac
);
}
#endif
kill_name
(
lease
);
#ifdef HAVE_SCRIPT
queue_script
(
ACTION_DEL
,
lease
,
lease
->
old_hostname
,
now
);
...
...
src/netlink.c
View file @
353ae4d2
...
...
@@ -345,10 +345,11 @@ static void nl_routechange(struct nlmsghdr *h)
/* force RAs to sync new network and pick up new interfaces. */
if
(
daemon
->
ra_contexts
)
{
ra_start_unsolicted
(
dnsmasq_time
());
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
();
send_alarm
(
0
,
0
);
}
#endif
...
...
src/radv-protocol.h
View file @
353ae4d2
...
...
@@ -17,6 +17,13 @@
#define ALL_HOSTS "FF02::1"
#define ALL_ROUTERS "FF02::2"
struct
ping_packet
{
u8
type
,
code
;
u16
checksum
;
u16
identifier
;
u16
sequence_no
;
};
struct
ra_packet
{
u8
type
,
code
;
u16
checksum
;
...
...
@@ -32,9 +39,6 @@ struct prefix_opt {
struct
in6_addr
prefix
;
};
#define ICMP6_ROUTER_SOLICIT 133
#define ICMP6_ROUTER_ADVERT 134
#define ICMP6_OPT_SOURCE_MAC 1
#define ICMP6_OPT_PREFIX 3
#define ICMP6_OPT_MTU 5
...
...
src/radv.c
View file @
353ae4d2
...
...
@@ -55,13 +55,20 @@ void ra_init(time_t now)
#endif
int
val
=
255
;
/* radvd uses this value */
socklen_t
len
=
sizeof
(
int
);
struct
dhcp_context
*
context
;
/* ensure this is around even if we're not doing DHCPv6 */
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
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
))
break
;
ICMP6_FILTER_SETBLOCKALL
(
&
filter
);
ICMP6_FILTER_SETPASS
(
ND_ROUTER_SOLICIT
,
&
filter
);
ICMP6_FILTER_SETPASS
(
ND_ROUTER_ADVERT
,
&
filter
);
if
(
context
)
ICMP6_FILTER_SETPASS
(
ICMP6_ECHO_REPLY
,
&
filter
);
if
((
fd
=
socket
(
PF_INET6
,
SOCK_RAW
,
IPPROTO_ICMPV6
))
==
-
1
||
getsockopt
(
fd
,
IPPROTO_IPV6
,
IPV6_UNICAST_HOPS
,
&
hop_limit
,
&
len
)
||
...
...
@@ -77,21 +84,21 @@ void ra_init(time_t now)
daemon
->
icmp6fd
=
fd
;
ra_start_unsolicted
(
now
);
ra_start_unsolicted
(
now
,
NULL
);
}
void
ra_start_unsolicted
(
time_t
now
)
void
ra_start_unsolicted
(
time_t
now
,
struct
dhcp_context
*
context
)
{
struct
dhcp_context
*
context
;
/* init timers so that we do ra's for all soon. some ra_times will end up zeroed
/* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
if it's not appropriate to advertise those contexts.
This gets re-called on a netlink route-change to re-do the advertisement
and pick up new interfaces */
/* range 0 - 5 */
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
context
->
ra_time
=
now
+
(
rand16
()
/
13000
);
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 */
/* re-do frequently for a minute or so, in case the first gets lost. */
ra_short_period_start
=
now
;
...
...
@@ -158,7 +165,19 @@ void icmp6_packet(void)
p
=
(
unsigned
char
*
)
daemon
->
outpacket
.
iov_base
;
if
(
p
[
0
]
!=
ICMP6_ROUTER_SOLICIT
||
p
[
1
]
!=
0
)
if
(
p
[
1
]
!=
0
)
return
;
if
(
p
[
0
]
==
ICMP6_ECHO_REPLY
)
{
/* We may be doing RA but not DHCPv4, in which case the lease
database may not exist and we have nothing to do anyway */
if
(
daemon
->
dhcp
)
lease_ping_reply
(
&
from
.
sin6_addr
,
p
,
interface
);
return
;
}
if
(
p
[
0
]
!=
ND_ROUTER_SOLICIT
)
return
;
/* look for link-layer address option for logging */
...
...
@@ -184,7 +203,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
save_counter
(
0
);
ra
=
expand
(
sizeof
(
struct
ra_packet
));
ra
->
type
=
ICMP6
_ROUTER_ADVERT
;
ra
->
type
=
ND
_ROUTER_ADVERT
;
ra
->
code
=
0
;
ra
->
hop_limit
=
hop_limit
;
ra
->
flags
=
0
;
...
...
@@ -238,7 +257,7 @@ static void send_ra(int iface, char *iface_name, struct in6_addr *dest)
addr
.
sin6_port
=
htons
(
IPPROTO_ICMPV6
);
if
(
dest
)
{
memcpy
(
&
addr
.
sin6_addr
,
dest
,
sizeof
(
struct
in6_addr
))
;
addr
.
sin6_addr
=
*
dest
;
if
(
IN6_IS_ADDR_LINKLOCAL
(
dest
)
||
IN6_IS_ADDR_MC_LINKLOCAL
(
dest
))
addr
.
sin6_scope_id
=
iface
;
...
...
@@ -406,7 +425,7 @@ static int iface_search(struct in6_addr *local, int prefix,
if
(
prefix
==
context
->
prefix
&&
is_same_net6
(
local
,
&
context
->
start6
,
prefix
)
&&
is_same_net6
(
local
,
&
context
->
end6
,
prefix
))
if
(
context
->
ra_time
!=
0
&&
difftime
(
context
->
ra_time
,
param
->
now
)
<
0
.
0
)
if
(
context
->
ra_time
!=
0
&&
difftime
(
context
->
ra_time
,
param
->
now
)
<
=
0
.
0
)
{
/* found an interface that's overdue for RA determine new
timeout value and zap other contexts on the same interface
...
...
@@ -426,73 +445,5 @@ static int iface_search(struct in6_addr *local, int prefix,
return
1
;
/* keep searching */
}
static
int
add_subnet
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
{
struct
dhcp_context
*
context
;
struct
subnet_map
**
subnets
=
vparam
;
struct
subnet_map
*
map
;
(
void
)
scope
;
(
void
)
dad
;
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
))
{
for
(
map
=
*
subnets
;
map
;
map
=
map
->
next
)
if
(
map
->
iface
==
0
||
(
map
->
iface
==
if_index
&&
is_same_net6
(
local
,
&
map
->
subnet
,
prefix
)))
break
;
/* It's there already */
if
(
map
&&
map
->
iface
!=
0
)
continue
;
if
(
!
map
&&
(
map
=
whine_malloc
(
sizeof
(
struct
subnet_map
))))
{
map
->
next
=
*
subnets
;
*
subnets
=
map
;
}
if
(
map
)
{
map
->
iface
=
if_index
;
map
->
subnet
=
*
local
;
}
}
return
1
;
}
/* 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.
*/
struct
subnet_map
*
build_subnet_map
(
void
)
{
struct
subnet_map
*
map
;
struct
dhcp_context
*
context
;
static
struct
subnet_map
*
subnets
=
NULL
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
))
break
;
/* no ra-names, no need to go further. */
if
(
!
context
)
return
NULL
;
/* mark unused */
for
(
map
=
subnets
;
map
;
map
=
map
->
next
)
map
->
iface
=
0
;
if
(
iface_enumerate
(
AF_INET6
,
&
subnets
,
add_subnet
))
return
subnets
;
return
NULL
;
}
#endif
src/rfc2131.c
View file @
353ae4d2
...
...
@@ -483,14 +483,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
{
logaddr
=
&
mess
->
yiaddr
;
lease_set_hwaddr
(
lease
,
mess
->
chaddr
,
NULL
,
mess
->
hlen
,
mess
->
htype
,
0
);
lease_set_hwaddr
(
lease
,
mess
->
chaddr
,
NULL
,
mess
->
hlen
,
mess
->
htype
,
0
,
now
);
if
(
hostname
)
lease_set_hostname
(
lease
,
hostname
,
1
,
get_domain
(
lease
->
addr
),
domain
);
/* infinite lease unless nailed in dhcp-host line. */
lease_set_expires
(
lease
,
have_config
(
config
,
CONFIG_TIME
)
?
config
->
lease_time
:
0xffffffff
,
now
);
lease_set_interface
(
lease
,
int_index
);
lease_set_interface
(
lease
,
int_index
,
now
);
clear_packet
(
mess
,
end
);
do_options
(
context
,
mess
,
end
,
NULL
,
hostname
,
get_domain
(
mess
->
yiaddr
),
...
...
@@ -1276,7 +1276,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
time
=
calc_time
(
context
,
config
,
option_find
(
mess
,
sz
,
OPTION_LEASE_TIME
,
4
));
lease_set_hwaddr
(
lease
,
mess
->
chaddr
,
clid
,
mess
->
hlen
,
mess
->
htype
,
clid_len
);
lease_set_hwaddr
(
lease
,
mess
->
chaddr
,
clid
,
mess
->
hlen
,
mess
->
htype
,
clid_len
,
now
);
/* if all the netids in the ignore_name list are present, ignore client-supplied name */
if
(
!
hostname_auth
)
...
...
@@ -1310,7 +1310,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease_set_hostname
(
lease
,
hostname
,
hostname_auth
,
get_domain
(
lease
->
addr
),
domain
);
lease_set_expires
(
lease
,
time
,
now
);
lease_set_interface
(
lease
,
int_index
);
lease_set_interface
(
lease
,
int_index
,
now
);
if
(
override
.
s_addr
!=
0
)
lease
->
override
=
override
;
...
...
@@ -1387,7 +1387,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
time
=
(
unsigned
int
)
difftime
(
lease
->
expires
,
now
);
option_put
(
mess
,
end
,
OPTION_LEASE_TIME
,
4
,
time
);
lease_set_interface
(
lease
,
int_index
);
lease_set_interface
(
lease
,
int_index
,
now
);
}
do_options
(
context
,
mess
,
end
,
req_options
,
hostname
,
get_domain
(
mess
->
ciaddr
),
...
...
src/rfc3315.c
View file @
353ae4d2
...
...
@@ -637,8 +637,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
if
(
lease
)
{
lease_set_expires
(
lease
,
lease_time
,
now
);
lease_set_hwaddr
(
lease
,
NULL
,
clid
,
0
,
iaid
,
clid_len
);
lease_set_interface
(
lease
,
interface
);
lease_set_hwaddr
(
lease
,
NULL
,
clid
,
0
,
iaid
,
clid_len
,
now
);
lease_set_interface
(
lease
,
interface
,
now
);
if
(
hostname
&&
ia_type
==
OPTION6_IA_NA
)
{
char
*
addr_domain
=
get_domain6
(
addrp
);
...
...
src/slaac.c
0 → 100644
View file @
353ae4d2
/* dnsmasq is Copyright (c) 2000-2012 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
#ifdef HAVE_DHCP6
#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
)
{
struct
slaac_address
*
slaac
,
*
old
,
**
up
;
struct
dhcp_context
*
context
;
if
(
!
(
lease
->
flags
&
LEASE_HAVE_HWADDR
)
||
lease
->
last_interface
==
0
||
!
lease
->
hostname
)
return
;
old
=
lease
->
slaac_address
;
lease
->
slaac_address
=
NULL
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
)
&&
lease
->
last_interface
==
context
->
if_index
)
{
struct
in6_addr
addr
=
context
->
start6
;
if
(
lease
->
hwaddr_len
==
6
&&
(
lease
->
hwaddr_type
==
ARPHRD_ETHER
||
lease
->
hwaddr_type
==
ARPHRD_IEEE802
))
{
/* convert MAC address to EUI-64 */
memcpy
(
&
addr
.
s6_addr
[
8
],
lease
->
hwaddr
,
3
);
memcpy
(
&
addr
.
s6_addr
[
13
],
&
lease
->
hwaddr
[
3
],
3
);
addr
.
s6_addr
[
11
]
=
0xff
;
addr
.
s6_addr
[
12
]
=
0xfe
;
}
#if defined(ARPHRD_EUI64)
else
if
(
lease
->
hwaddr_len
==
8
&&
lease
->
hwaddr_type
==
ARPHRD_EUI64
)
memcpy
(
&
addr
.
s6_addr
[
8
],
lease
->
hwaddr
,
8
);
#endif
#if defined(ARPHRD_IEEE1394) && defined(ARPHRD_EUI64)
else
if
(
lease
->
clid_len
==
9
&&
lease
->
clid
[
0
]
==
ARPHRD_EUI64
&&
lease
->
hwaddr_type
==
ARPHRD_IEEE1394
)
/* firewire has EUI-64 identifier as clid */
memcpy
(
&
addr
.
s6_addr
[
8
],
&
lease
->
clid
[
1
],
8
);
#endif
else
continue
;
addr
.
s6_addr
[
8
]
^=
0x02
;
/* check if we already have this one */
for
(
up
=
&
old
,
slaac
=
old
;
slaac
;
slaac
=
slaac
->
next
)
{
if
(
IN6_ARE_ADDR_EQUAL
(
&
addr
,
&
slaac
->
addr
))
{
*
up
=
slaac
->
next
;
break
;
}
up
=
&
slaac
->
next
;
}
/* No, make new one */
if
(
!
slaac
&&
(
slaac
=
whine_malloc
(
sizeof
(
struct
slaac_address
))))
{
slaac
->
ping_time
=
now
;
slaac
->
backoff
=
1
;
slaac
->
addr
=
addr
;
slaac
->
local
=
context
->
local6
;
/* Do RA's to prod it */
ra_start_unsolicted
(
now
,
context
);
}
if
(
slaac
)
{
slaac
->
next
=
lease
->
slaac_address
;
lease
->
slaac_address
=
slaac
;
}
}
/* Free any no reused */
for
(;
old
;
old
=
slaac
)
{
slaac
=
old
->
next
;
free
(
old
);
}
}
time_t
periodic_slaac
(
time_t
now
,
struct
dhcp_lease
*
leases
)
{
struct
dhcp_context
*
context
;
struct
dhcp_lease
*
lease
;
struct
slaac_address
*
slaac
;
time_t
next_event
=
0
;
for
(
context
=
daemon
->
ra_contexts
;
context
;
context
=
context
->
next
)
if
((
context
->
flags
&
CONTEXT_RA_NAME
))
break
;
/* nothing configured */
if
(
!
context
)
return
0
;
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
)
{
/* confirmed? */
if
(
slaac
->
backoff
==
0
)
continue
;
if
(
difftime
(
slaac
->
ping_time
,
now
)
<=
0
.
0
)
{
struct
ping_packet
*
ping
;
struct
sockaddr_in6
addr
;
save_counter
(
0
);
ping
=
expand
(
sizeof
(
struct
ping_packet
));
ping
->
type
=
ICMP6_ECHO_REQUEST
;
ping
->
code
=
0
;
ping
->
identifier
=
ping_id
;
ping
->
sequence_no
=
slaac
->
backoff
;
memset
(
&
addr
,
0
,
sizeof
(
addr
));
#ifdef HAVE_SOCKADDR_SA_LEN
addr
.
sin6_len
=
sizeof
(
struct
sockaddr_in6
);
#endif
addr
.
sin6_family
=
AF_INET6
;
addr
.
sin6_port
=
htons
(
IPPROTO_ICMPV6
);
addr
.
sin6_addr
=
slaac
->
addr
;
send_from
(
daemon
->
icmp6fd
,
0
,
daemon
->
outpacket
.
iov_base
,
save_counter
(
0
),
(
union
mysockaddr
*
)
&
addr
,
(
struct
all_addr
*
)
&
slaac
->
local
,
lease
->
last_interface
);
slaac
->
ping_time
+=
(
1
<<
(
slaac
->
backoff
-
1
))
+
(
rand16
()
/
21785
);
/* 0 - 3 */
if
(
slaac
->
backoff
>
4
)
slaac
->
ping_time
+=
rand16
()
/
4000
;
/* 0 - 15 */
slaac
->
backoff
++
;
}
if
(
next_event
==
0
||
difftime
(
next_event
,
slaac
->
ping_time
)
>=
0
.
0
)
next_event
=
slaac
->
ping_time
;
}
return
next_event
;
}
void
slaac_ping_reply
(
struct
in6_addr
*
sender
,
unsigned
char
*
packet
,
char
*
interface
,
struct
dhcp_lease
*
leases
)
{
struct
dhcp_lease
*
lease
;
struct
slaac_address
*
slaac
;
struct
ping_packet
*
ping
=
(
struct
ping_packet
*
)
packet
;
int
gotone
=
0
;
if
(
ping
->
identifier
==
ping_id
)
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
for
(
slaac
=
lease
->
slaac_address
;
slaac
;
slaac
=
slaac
->
next
)
if
(
slaac
->
backoff
!=
0
&&
IN6_ARE_ADDR_EQUAL
(
sender
,
&
slaac
->
addr
))
{
slaac
->
backoff
=
0
;
gotone
=
1
;
inet_ntop
(
AF_INET6
,
sender
,
daemon
->
addrbuff
,
ADDRSTRLEN
);
my_syslog
(
MS_DHCP
|
LOG_INFO
,
"SLAAC-CONFIRM(%s) %s %s"
,
interface
,
daemon
->
addrbuff
,
lease
->
hostname
);
}
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