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
11867dc2
Commit
11867dc2
authored
Dec 23, 2015
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cache access to the kernel's ARP table.
parent
d3a8b39c
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
223 additions
and
77 deletions
+223
-77
Makefile
Makefile
+1
-1
bld/Android.mk
bld/Android.mk
+1
-1
src/arp.c
src/arp.c
+201
-0
src/dhcp6.c
src/dhcp6.c
+11
-43
src/dnsmasq.h
src/dnsmasq.h
+4
-0
src/edns0.c
src/edns0.c
+5
-32
No files found.
Makefile
View file @
11867dc2
...
@@ -74,7 +74,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
...
@@ -74,7 +74,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o
\
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o
\
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
\
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o
\
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
\
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
\
poll.o rrfilter.o edns0.o
poll.o rrfilter.o edns0.o
arp.o
hdrs
=
dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h
\
hdrs
=
dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h
\
dns-protocol.h radv-protocol.h ip6addr.h
dns-protocol.h radv-protocol.h ip6addr.h
...
...
bld/Android.mk
View file @
11867dc2
...
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
...
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
dhcp6.c rfc3315.c dhcp-common.c outpacket.c
\
dhcp6.c rfc3315.c dhcp-common.c outpacket.c
\
radv.c slaac.c auth.c ipset.c domain.c
\
radv.c slaac.c auth.c ipset.c domain.c
\
dnssec.c dnssec-openssl.c blockdata.c tables.c
\
dnssec.c dnssec-openssl.c blockdata.c tables.c
\
loop.c inotify.c poll.c rrfilter.c edns0.c
loop.c inotify.c poll.c rrfilter.c edns0.c
arp.c
LOCAL_MODULE
:=
dnsmasq
LOCAL_MODULE
:=
dnsmasq
...
...
src/arp.c
0 → 100644
View file @
11867dc2
/* dnsmasq is Copyright (c) 2000-2015 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"
#define ARP_FREE 0
#define ARP_FOUND 1
#define ARP_NEW 2
#define ARP_EMPTY 3
struct
arp_record
{
short
hwlen
,
status
;
int
family
;
unsigned
char
hwaddr
[
DHCP_CHADDR_MAX
];
struct
all_addr
addr
;
struct
arp_record
*
next
;
};
static
struct
arp_record
*
arps
=
NULL
,
*
old
=
NULL
;
static
int
filter_mac
(
int
family
,
char
*
addrp
,
char
*
mac
,
size_t
maclen
,
void
*
parmv
)
{
int
match
=
0
;
struct
arp_record
*
arp
;
if
(
maclen
>
DHCP_CHADDR_MAX
)
return
1
;
/* Look for existing entry */
for
(
arp
=
arps
;
arp
;
arp
=
arp
->
next
)
{
if
(
family
!=
arp
->
family
||
arp
->
status
==
ARP_NEW
)
continue
;
if
(
family
==
AF_INET
)
{
if
(
arp
->
addr
.
addr
.
addr4
.
s_addr
!=
((
struct
in_addr
*
)
addrp
)
->
s_addr
)
continue
;
}
#ifdef HAVE_IPV6
else
{
if
(
!
IN6_ARE_ADDR_EQUAL
(
&
arp
->
addr
.
addr
.
addr6
,
(
struct
in6_addr
*
)
addrp
))
continue
;
}
#endif
if
(
arp
->
status
!=
ARP_EMPTY
&&
arp
->
hwlen
==
maclen
&&
memcmp
(
arp
->
hwaddr
,
mac
,
maclen
)
==
0
)
arp
->
status
=
ARP_FOUND
;
else
{
/* existing address, MAC changed or arrived new. */
arp
->
status
=
ARP_NEW
;
arp
->
hwlen
=
maclen
;
arp
->
family
=
family
;
memcpy
(
arp
->
hwaddr
,
mac
,
maclen
);
}
break
;
}
if
(
!
arp
)
{
/* New entry */
if
(
old
)
{
arp
=
old
;
old
=
old
->
next
;
}
else
if
(
!
(
arp
=
whine_malloc
(
sizeof
(
struct
arp_record
))))
return
1
;
arp
->
next
=
arps
;
arps
=
arp
;
arp
->
status
=
ARP_NEW
;
arp
->
hwlen
=
maclen
;
arp
->
family
=
family
;
memcpy
(
arp
->
hwaddr
,
mac
,
maclen
);
if
(
family
==
AF_INET
)
arp
->
addr
.
addr
.
addr4
.
s_addr
=
((
struct
in_addr
*
)
addrp
)
->
s_addr
;
#ifdef HAVE_IPV6
else
memcpy
(
&
arp
->
addr
.
addr
.
addr6
,
addrp
,
IN6ADDRSZ
);
#endif
}
return
1
;
}
/* If in lazy mode, we cache absence of ARP entries. */
int
find_mac
(
union
mysockaddr
*
addr
,
unsigned
char
*
mac
,
int
lazy
)
{
struct
arp_record
*
arp
,
**
up
;
int
updated
=
0
;
again:
for
(
arp
=
arps
;
arp
;
arp
=
arp
->
next
)
{
if
(
addr
->
sa
.
sa_family
==
arp
->
family
)
{
if
(
arp
->
addr
.
addr
.
addr4
.
s_addr
!=
addr
->
in
.
sin_addr
.
s_addr
)
continue
;
}
#ifdef HAVE_IPV6
else
{
if
(
!
IN6_ARE_ADDR_EQUAL
(
&
arp
->
addr
.
addr
.
addr6
,
&
addr
->
in6
.
sin6_addr
))
continue
;
}
#endif
/* Only accept poitive entries unless in lazy mode. */
if
(
arp
->
status
!=
ARP_EMPTY
||
lazy
||
updated
)
{
if
(
mac
&&
arp
->
hwlen
!=
0
)
memcpy
(
mac
,
arp
->
hwaddr
,
arp
->
hwlen
);
return
arp
->
hwlen
;
}
}
/* Not found, try the kernel */
if
(
!
updated
)
{
updated
=
1
;
/* Mark all non-negative entries */
for
(
arp
=
arps
,
up
=
&
arps
;
arp
;
arp
=
arp
->
next
)
if
(
arp
->
status
!=
ARP_EMPTY
)
arp
->
status
=
ARP_FREE
;
iface_enumerate
(
AF_UNSPEC
,
NULL
,
filter_mac
);
/* Remove all unconfirmed entries to old list, announce new ones. */
for
(
arp
=
arps
,
up
=
&
arps
;
arp
;
arp
=
arp
->
next
)
if
(
arp
->
status
==
ARP_FREE
)
{
*
up
=
arp
->
next
;
arp
->
next
=
old
;
old
=
arp
;
}
else
{
up
=
&
arp
->
next
;
if
(
arp
->
status
==
ARP_NEW
)
{
char
a
[
ADDRSTRLEN
],
m
[
ADDRSTRLEN
];
union
mysockaddr
pa
;
pa
.
sa
.
sa_family
=
arp
->
family
;
pa
.
in
.
sin_addr
.
s_addr
=
arp
->
addr
.
addr
.
addr4
.
s_addr
;
prettyprint_addr
(
&
pa
,
a
);
print_mac
(
m
,
arp
->
hwaddr
,
arp
->
hwlen
);
my_syslog
(
LOG_INFO
,
_
(
"new arp: %s %s"
),
a
,
m
);
}
}
goto
again
;
}
/* record failure, so we don't consult the kernel each time
we're asked for this address */
if
(
old
)
{
arp
=
old
;
old
=
old
->
next
;
}
else
arp
=
whine_malloc
(
sizeof
(
struct
arp_record
));
if
(
arp
)
{
arp
->
next
=
arps
;
arps
=
arp
;
arp
->
status
=
ARP_EMPTY
;
arp
->
family
=
addr
->
sa
.
sa_family
;
if
(
addr
->
sa
.
sa_family
==
AF_INET
)
arp
->
addr
.
addr
.
addr4
.
s_addr
=
addr
->
in
.
sin_addr
.
s_addr
;
#ifdef HAVE_IPV6
else
memcpy
(
&
arp
->
addr
.
addr
.
addr6
,
&
addr
->
in6
.
sin6_addr
,
IN6ADDRSZ
);
#endif
}
return
0
;
}
src/dhcp6.c
View file @
11867dc2
...
@@ -27,17 +27,10 @@ struct iface_param {
...
@@ -27,17 +27,10 @@ struct iface_param {
int
ind
,
addr_match
;
int
ind
,
addr_match
;
};
};
struct
mac_param
{
struct
in6_addr
*
target
;
unsigned
char
*
mac
;
unsigned
int
maclen
;
};
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
flags
,
int
scope
,
int
if_index
,
int
flags
,
unsigned
int
preferred
,
unsigned
int
valid
,
void
*
vparam
);
unsigned
int
preferred
,
unsigned
int
valid
,
void
*
vparam
);
static
int
find_mac
(
int
family
,
char
*
addrp
,
char
*
mac
,
size_t
maclen
,
void
*
parmv
);
static
int
make_duid1
(
int
index
,
unsigned
int
type
,
char
*
mac
,
size_t
maclen
,
void
*
parm
);
static
int
make_duid1
(
int
index
,
unsigned
int
type
,
char
*
mac
,
size_t
maclen
,
void
*
parm
);
void
dhcp6_init
(
void
)
void
dhcp6_init
(
void
)
...
@@ -264,9 +257,8 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
...
@@ -264,9 +257,8 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
find the sender. Repeat a few times in case of packet loss. */
find the sender. Repeat a few times in case of packet loss. */
struct
neigh_packet
neigh
;
struct
neigh_packet
neigh
;
struct
sockaddr_in6
addr
;
union
mysockaddr
addr
;
struct
mac_param
mac_param
;
int
i
,
maclen
;
int
i
;
neigh
.
type
=
ND_NEIGHBOR_SOLICIT
;
neigh
.
type
=
ND_NEIGHBOR_SOLICIT
;
neigh
.
code
=
0
;
neigh
.
code
=
0
;
...
@@ -277,55 +269,31 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
...
@@ -277,55 +269,31 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
memset
(
&
addr
,
0
,
sizeof
(
addr
));
memset
(
&
addr
,
0
,
sizeof
(
addr
));
#ifdef HAVE_SOCKADDR_SA_LEN
#ifdef HAVE_SOCKADDR_SA_LEN
addr
.
sin6_len
=
sizeof
(
struct
sockaddr_in6
);
addr
.
in6
.
sin6_len
=
sizeof
(
struct
sockaddr_in6
);
#endif
#endif
addr
.
sin6_family
=
AF_INET6
;
addr
.
in6
.
sin6_family
=
AF_INET6
;
addr
.
sin6_port
=
htons
(
IPPROTO_ICMPV6
);
addr
.
in6
.
sin6_port
=
htons
(
IPPROTO_ICMPV6
);
addr
.
sin6_addr
=
*
client
;
addr
.
in6
.
sin6_addr
=
*
client
;
addr
.
sin6_scope_id
=
iface
;
addr
.
in6
.
sin6_scope_id
=
iface
;
mac_param
.
target
=
client
;
mac_param
.
maclen
=
0
;
mac_param
.
mac
=
mac
;
for
(
i
=
0
;
i
<
5
;
i
++
)
for
(
i
=
0
;
i
<
5
;
i
++
)
{
{
struct
timespec
ts
;
struct
timespec
ts
;
iface_enumerate
(
AF_UNSPEC
,
&
mac_param
,
find_mac
);
if
((
maclen
=
find_mac
(
&
addr
,
mac
,
0
))
!=
0
)
if
(
mac_param
.
maclen
!=
0
)
break
;
break
;
sendto
(
daemon
->
icmp6fd
,
&
neigh
,
sizeof
(
neigh
),
0
,
(
struct
sockaddr
*
)
&
addr
,
sizeof
(
addr
));
sendto
(
daemon
->
icmp6fd
,
&
neigh
,
sizeof
(
neigh
),
0
,
&
addr
.
sa
,
sizeof
(
addr
));
ts
.
tv_sec
=
0
;
ts
.
tv_sec
=
0
;
ts
.
tv_nsec
=
100000000
;
/* 100ms */
ts
.
tv_nsec
=
100000000
;
/* 100ms */
nanosleep
(
&
ts
,
NULL
);
nanosleep
(
&
ts
,
NULL
);
}
}
*
maclenp
=
mac
_param
.
mac
len
;
*
maclenp
=
maclen
;
*
mactypep
=
ARPHRD_ETHER
;
*
mactypep
=
ARPHRD_ETHER
;
}
}
static
int
find_mac
(
int
family
,
char
*
addrp
,
char
*
mac
,
size_t
maclen
,
void
*
parmv
)
{
struct
mac_param
*
parm
=
parmv
;
if
(
family
==
AF_INET6
&&
IN6_ARE_ADDR_EQUAL
(
parm
->
target
,
(
struct
in6_addr
*
)
addrp
))
{
if
(
maclen
<=
DHCP_CHADDR_MAX
)
{
parm
->
maclen
=
maclen
;
memcpy
(
parm
->
mac
,
mac
,
maclen
);
}
return
0
;
/* found, abort */
}
return
1
;
}
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
int
flags
,
unsigned
int
preferred
,
int
scope
,
int
if_index
,
int
flags
,
unsigned
int
preferred
,
unsigned
int
valid
,
void
*
vparam
)
unsigned
int
valid
,
void
*
vparam
)
...
...
src/dnsmasq.h
View file @
11867dc2
...
@@ -1516,3 +1516,7 @@ size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysock
...
@@ -1516,3 +1516,7 @@ size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysock
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
);
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
);
size_t
add_do_bit
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
);
size_t
add_do_bit
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
);
int
check_source
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pseudoheader
,
union
mysockaddr
*
peer
);
int
check_source
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pseudoheader
,
union
mysockaddr
*
peer
);
/* arp.c */
int
find_mac
(
union
mysockaddr
*
addr
,
unsigned
char
*
mac
,
int
lazy
);
src/edns0.c
View file @
11867dc2
...
@@ -213,42 +213,15 @@ size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
...
@@ -213,42 +213,15 @@ size_t add_do_bit(struct dns_header *header, size_t plen, char *limit)
return
add_pseudoheader
(
header
,
plen
,
(
unsigned
char
*
)
limit
,
PACKETSZ
,
0
,
NULL
,
0
,
1
);
return
add_pseudoheader
(
header
,
plen
,
(
unsigned
char
*
)
limit
,
PACKETSZ
,
0
,
NULL
,
0
,
1
);
}
}
static
int
filter_mac
(
int
family
,
char
*
addrp
,
char
*
mac
,
size_t
maclen
,
void
*
parmv
)
{
struct
macparm
*
parm
=
parmv
;
int
match
=
0
;
if
(
family
==
parm
->
l3
->
sa
.
sa_family
)
{
if
(
family
==
AF_INET
&&
memcmp
(
&
parm
->
l3
->
in
.
sin_addr
,
addrp
,
INADDRSZ
)
==
0
)
match
=
1
;
#ifdef HAVE_IPV6
else
if
(
family
==
AF_INET6
&&
memcmp
(
&
parm
->
l3
->
in6
.
sin6_addr
,
addrp
,
IN6ADDRSZ
)
==
0
)
match
=
1
;
#endif
}
if
(
!
match
)
return
1
;
/* continue */
parm
->
plen
=
add_pseudoheader
(
parm
->
header
,
parm
->
plen
,
parm
->
limit
,
PACKETSZ
,
EDNS0_OPTION_MAC
,
(
unsigned
char
*
)
mac
,
maclen
,
0
);
return
0
;
/* done */
}
size_t
add_mac
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
l3
)
size_t
add_mac
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
l3
)
{
{
struct
macparm
parm
;
int
maclen
;
unsigned
char
mac
[
DHCP_CHADDR_MAX
];
parm
.
header
=
header
;
parm
.
limit
=
(
unsigned
char
*
)
limit
;
parm
.
plen
=
plen
;
parm
.
l3
=
l3
;
iface_enumerate
(
AF_UNSPEC
,
&
parm
,
filter_mac
);
if
((
maclen
=
find_mac
(
l3
,
mac
,
1
))
!=
0
)
plen
=
add_pseudoheader
(
header
,
plen
,
limit
,
PACKETSZ
,
EDNS0_OPTION_MAC
,
mac
,
maclen
,
0
);
return
p
arm
.
p
len
;
return
plen
;
}
}
struct
subnet_opt
{
struct
subnet_opt
{
...
...
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