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
8939c95f
Commit
8939c95f
authored
Sep 25, 2013
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Don't extract MAC address from ND table when DHCPv6 request is from a relay.
parent
408c368f
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
84 additions
and
75 deletions
+84
-75
src/dhcp6.c
src/dhcp6.c
+52
-50
src/dnsmasq.h
src/dnsmasq.h
+5
-5
src/rfc3315.c
src/rfc3315.c
+27
-20
No files found.
src/dhcp6.c
View file @
8939c95f
...
...
@@ -29,7 +29,7 @@ struct iface_param {
struct
mac_param
{
struct
in6_addr
*
target
;
unsigned
char
mac
[
DHCP_CHADDR_MAX
]
;
unsigned
char
*
mac
;
unsigned
int
maclen
;
};
...
...
@@ -99,7 +99,6 @@ void dhcp6_packet(time_t now)
struct
dhcp_context
*
context
;
struct
dhcp_relay
*
relay
;
struct
iface_param
parm
;
struct
mac_param
mac_param
;
struct
cmsghdr
*
cmptr
;
struct
msghdr
msg
;
int
if_index
=
0
;
...
...
@@ -145,8 +144,6 @@ void dhcp6_packet(time_t now)
if
((
port
=
relay_reply6
(
&
from
,
sz
,
ifr
.
ifr_name
))
==
0
)
{
int
i
;
for
(
tmp
=
daemon
->
if_except
;
tmp
;
tmp
=
tmp
->
next
)
if
(
tmp
->
name
&&
wildcard_match
(
tmp
->
name
,
ifr
.
ifr_name
))
return
;
...
...
@@ -182,48 +179,6 @@ void dhcp6_packet(time_t now)
if
(
!
iface_enumerate
(
AF_INET6
,
&
parm
,
complete_context6
))
return
;
/* Recieving a packet from a host does not populate the neighbour
cache, so we send a neighbour discovery request if we can't
find the sender. Repeat a few times in case of packet loss. */
for
(
i
=
0
;
i
<
5
;
i
++
)
{
struct
timespec
ts
;
struct
neigh_packet
*
neigh
;
struct
sockaddr_in6
addr
;
mac_param
.
target
=
&
from
.
sin6_addr
;
mac_param
.
maclen
=
0
;
iface_enumerate
(
AF_UNSPEC
,
&
mac_param
,
find_mac
);
if
(
mac_param
.
maclen
!=
0
)
break
;
save_counter
(
0
);
neigh
=
expand
(
sizeof
(
struct
neigh_packet
));
neigh
->
type
=
ND_NEIGHBOR_SOLICIT
;
neigh
->
code
=
0
;
neigh
->
reserved
=
0
;
neigh
->
target
=
from
.
sin6_addr
;
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
=
from
.
sin6_addr
;
addr
.
sin6_scope_id
=
from
.
sin6_scope_id
;
sendto
(
daemon
->
icmp6fd
,
daemon
->
outpacket
.
iov_base
,
save_counter
(
0
),
0
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
ts
.
tv_sec
=
0
;
ts
.
tv_nsec
=
100000000
;
/* 100ms */
nanosleep
(
&
ts
,
NULL
);
}
if
(
daemon
->
if_names
||
daemon
->
if_addrs
)
{
...
...
@@ -244,8 +199,7 @@ void dhcp6_packet(time_t now)
inet_pton
(
AF_INET6
,
ALL_SERVERS
,
&
all_servers
);
if
(
!
IN6_ARE_ADDR_EQUAL
(
&
dst_addr
,
&
all_servers
))
relay_upstream6
(
parm
.
relay
,
sz
,
&
from
.
sin6_addr
,
from
.
sin6_scope_id
,
mac_param
.
maclen
==
0
?
NULL
:
&
mac_param
.
mac
[
0
],
mac_param
.
maclen
,
ARPHRD_ETHER
);
relay_upstream6
(
parm
.
relay
,
sz
,
&
from
.
sin6_addr
,
from
.
sin6_scope_id
);
return
;
}
...
...
@@ -256,8 +210,7 @@ void dhcp6_packet(time_t now)
lease_prune
(
NULL
,
now
);
/* lose any expired leases */
port
=
dhcp6_reply
(
parm
.
current
,
if_index
,
ifr
.
ifr_name
,
&
parm
.
fallback
,
sz
,
IN6_IS_ADDR_MULTICAST
(
&
from
.
sin6_addr
),
now
,
mac_param
.
maclen
==
0
?
NULL
:
&
mac_param
.
mac
[
0
],
mac_param
.
maclen
,
ARPHRD_ETHER
);
sz
,
&
from
.
sin6_addr
,
now
);
lease_update_file
(
now
);
lease_update_dns
(
0
);
...
...
@@ -276,6 +229,55 @@ void dhcp6_packet(time_t now)
}
}
void
get_client_mac
(
struct
in6_addr
*
client
,
int
iface
,
unsigned
char
*
mac
,
unsigned
int
*
maclenp
,
unsigned
int
*
mactypep
)
{
/* Recieving a packet from a host does not populate the neighbour
cache, so we send a neighbour discovery request if we can't
find the sender. Repeat a few times in case of packet loss. */
struct
neigh_packet
neigh
;
struct
sockaddr_in6
addr
;
struct
mac_param
mac_param
;
int
i
;
neigh
.
type
=
ND_NEIGHBOR_SOLICIT
;
neigh
.
code
=
0
;
neigh
.
reserved
=
0
;
neigh
.
target
=
*
client
;
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
=
*
client
;
addr
.
sin6_scope_id
=
iface
;
mac_param
.
target
=
client
;
mac_param
.
maclen
=
0
;
mac_param
.
mac
=
mac
;
for
(
i
=
0
;
i
<
5
;
i
++
)
{
struct
timespec
ts
;
iface_enumerate
(
AF_UNSPEC
,
&
mac_param
,
find_mac
);
if
(
mac_param
.
maclen
!=
0
)
break
;
sendto
(
daemon
->
icmp6fd
,
&
neigh
,
sizeof
(
neigh
),
0
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
ts
.
tv_sec
=
0
;
ts
.
tv_nsec
=
100000000
;
/* 100ms */
nanosleep
(
&
ts
,
NULL
);
}
*
maclenp
=
mac_param
.
maclen
;
*
mactypep
=
ARPHRD_ETHER
;
}
static
int
find_mac
(
int
family
,
char
*
addrp
,
char
*
mac
,
size_t
maclen
,
void
*
parmv
)
{
struct
mac_param
*
parm
=
parmv
;
...
...
src/dnsmasq.h
View file @
8939c95f
...
...
@@ -1212,15 +1212,15 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
int
prefix
,
u64
addr
);
void
make_duid
(
time_t
now
);
void
dhcp_construct_contexts
(
time_t
now
);
void
get_client_mac
(
struct
in6_addr
*
client
,
int
iface
,
unsigned
char
*
mac
,
unsigned
int
*
maclenp
,
unsigned
int
*
mactypep
);
#endif
/* rfc3315.c */
#ifdef HAVE_DHCP6
unsigned
short
dhcp6_reply
(
struct
dhcp_context
*
context
,
int
interface
,
char
*
iface_name
,
struct
in6_addr
*
fallback
,
size_t
sz
,
int
is_multicast
,
time_t
now
,
unsigned
char
*
mac
,
unsigned
int
mac_len
,
unsigned
int
mac_type
);
void
relay_upstream6
(
struct
dhcp_relay
*
relay
,
ssize_t
sz
,
struct
in6_addr
*
peer_address
,
u32
scope_id
,
unsigned
char
*
mac
,
unsigned
int
mac_len
,
unsigned
int
mac_type
);
struct
in6_addr
*
fallback
,
size_t
sz
,
struct
in6_addr
*
client_addr
,
time_t
now
);
void
relay_upstream6
(
struct
dhcp_relay
*
relay
,
ssize_t
sz
,
struct
in6_addr
*
peer_address
,
u32
scope_id
);
unsigned
short
relay_reply6
(
struct
sockaddr_in6
*
peer
,
ssize_t
sz
,
char
*
arrival_interface
);
#endif
...
...
src/rfc3315.c
View file @
8939c95f
...
...
@@ -29,14 +29,15 @@ struct state {
char
*
iface_name
;
void
*
packet_options
,
*
end
;
struct
dhcp_netid
*
tags
,
*
context_tags
;
unsigned
char
*
mac
;
unsigned
char
mac
[
DHCP_CHADDR_MAX
]
;
unsigned
int
mac_len
,
mac_type
;
#ifdef OPTION6_PREFIX_CLASS
struct
prefix_class
*
send_prefix_class
;
#endif
};
static
int
dhcp6_maybe_relay
(
struct
state
*
state
,
void
*
inbuff
,
size_t
sz
,
int
is_unicast
,
time_t
now
);
static
int
dhcp6_maybe_relay
(
struct
state
*
state
,
void
*
inbuff
,
size_t
sz
,
struct
in6_addr
*
client_addr
,
int
is_unicast
,
time_t
now
);
static
int
dhcp6_no_relay
(
struct
state
*
state
,
int
msg_type
,
void
*
inbuff
,
size_t
sz
,
int
is_unicast
,
time_t
now
);
static
void
log6_opts
(
int
nest
,
unsigned
int
xid
,
void
*
start_opts
,
void
*
end_opts
);
static
void
log6_packet
(
struct
state
*
state
,
char
*
type
,
struct
in6_addr
*
addr
,
char
*
string
);
...
...
@@ -67,8 +68,7 @@ static void calculate_times(struct dhcp_context *context, unsigned int *min_time
unsigned
short
dhcp6_reply
(
struct
dhcp_context
*
context
,
int
interface
,
char
*
iface_name
,
struct
in6_addr
*
fallback
,
size_t
sz
,
int
is_unicast
,
time_t
now
,
unsigned
char
*
mac
,
unsigned
int
mac_len
,
unsigned
int
mac_type
)
struct
in6_addr
*
fallback
,
size_t
sz
,
struct
in6_addr
*
client_addr
,
time_t
now
)
{
struct
dhcp_vendor
*
vendor
;
int
msg_type
;
...
...
@@ -88,20 +88,20 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
state
.
interface
=
interface
;
state
.
iface_name
=
iface_name
;
state
.
fallback
=
fallback
;
state
.
mac
=
mac
;
state
.
mac_len
=
mac_len
;
state
.
mac_type
=
mac_type
;
state
.
mac_len
=
0
;
state
.
tags
=
NULL
;
state
.
link_address
=
NULL
;
if
(
dhcp6_maybe_relay
(
&
state
,
daemon
->
dhcp_packet
.
iov_base
,
sz
,
is_unicast
,
now
))
if
(
dhcp6_maybe_relay
(
&
state
,
daemon
->
dhcp_packet
.
iov_base
,
sz
,
client_addr
,
IN6_IS_ADDR_MULTICAST
(
client_addr
),
now
))
return
msg_type
==
DHCP6RELAYFORW
?
DHCPV6_SERVER_PORT
:
DHCPV6_CLIENT_PORT
;
return
0
;
}
/* This cost me blood to write, it will probably cost you blood to understand - srk. */
static
int
dhcp6_maybe_relay
(
struct
state
*
state
,
void
*
inbuff
,
size_t
sz
,
int
is_unicast
,
time_t
now
)
static
int
dhcp6_maybe_relay
(
struct
state
*
state
,
void
*
inbuff
,
size_t
sz
,
struct
in6_addr
*
client_addr
,
int
is_unicast
,
time_t
now
)
{
void
*
end
=
inbuff
+
sz
;
void
*
opts
=
inbuff
+
34
;
...
...
@@ -116,9 +116,14 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, int i
/* if link_address != NULL if points to the link address field of the
innermost nested RELAYFORW message, which is where we find the
address of the network on which we can allocate an address.
Recalculate the available contexts using that information. */
Recalculate the available contexts using that information.
link_address == NULL means there's no relay in use, so we try and find the client's
MAC address from the local ND cache. */
if
(
state
->
link_address
)
if
(
!
state
->
link_address
)
get_client_mac
(
client_addr
,
state
->
interface
,
state
->
mac
,
&
state
->
mac_len
,
&
state
->
mac_type
);
else
{
struct
dhcp_context
*
c
;
state
->
context
=
NULL
;
...
...
@@ -146,7 +151,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, int i
return
0
;
}
}
if
(
!
state
->
context
)
{
my_syslog
(
MS_DHCP
|
LOG_WARNING
,
...
...
@@ -193,9 +198,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, int i
/* RFC-6939 */
if
((
opt
=
opt6_find
(
opts
,
end
,
OPTION6_CLIENT_MAC
,
3
)))
{
state
->
mac
=
opt6_ptr
(
opt
,
2
);
state
->
mac_type
=
opt6_uint
(
opt
,
0
,
2
);
state
->
mac_len
=
opt6_len
(
opt
)
-
2
;
memcpy
(
&
state
->
mac
[
0
],
opt6_ptr
(
opt
,
2
),
state
->
mac_len
);
}
for
(
opt
=
opts
;
opt
;
opt
=
opt6_next
(
opt
,
end
))
...
...
@@ -209,7 +214,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, int i
state
->
link_address
=
&
align
;
/* zero is_unicast since that is now known to refer to the
relayed packet, not the original sent by the client */
if
(
!
dhcp6_maybe_relay
(
state
,
opt6_ptr
(
opt
,
0
),
opt6_len
(
opt
),
0
,
now
))
if
(
!
dhcp6_maybe_relay
(
state
,
opt6_ptr
(
opt
,
0
),
opt6_len
(
opt
),
client_addr
,
0
,
now
))
return
0
;
}
else
if
(
opt6_type
(
opt
)
!=
OPTION6_CLIENT_MAC
)
...
...
@@ -1961,8 +1966,7 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
return
ret
;
}
void
relay_upstream6
(
struct
dhcp_relay
*
relay
,
ssize_t
sz
,
struct
in6_addr
*
peer_address
,
u32
scope_id
,
unsigned
char
*
mac
,
unsigned
int
mac_len
,
unsigned
int
mac_type
)
void
relay_upstream6
(
struct
dhcp_relay
*
relay
,
ssize_t
sz
,
struct
in6_addr
*
peer_address
,
u32
scope_id
)
{
/* ->local is same value for all relays on ->current chain */
...
...
@@ -1972,9 +1976,12 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
int
msg_type
=
*
inbuff
;
int
hopcount
;
struct
in6_addr
multicast
;
unsigned
int
maclen
,
mactype
;
unsigned
char
mac
[
DHCP_CHADDR_MAX
];
inet_pton
(
AF_INET6
,
ALL_SERVERS
,
&
multicast
);
get_client_mac
(
peer_address
,
scope_id
,
mac
,
&
maclen
,
&
mactype
);
/* source address == relay address */
from
.
addr
.
addr6
=
relay
->
local
.
addr
.
addr6
;
...
...
@@ -2000,11 +2007,11 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
memcpy
(
&
header
[
18
],
peer_address
,
IN6ADDRSZ
);
/* RFC-6939 */
if
(
mac
)
if
(
mac
len
!=
0
)
{
o
=
new_opt6
(
OPTION6_CLIENT_MAC
);
put_opt6_short
(
mac
_
type
);
put_opt6
(
mac
,
mac
_
len
);
put_opt6_short
(
mactype
);
put_opt6
(
mac
,
maclen
);
end_opt6
(
o
);
}
...
...
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