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
1d03016b
Commit
1d03016b
authored
Dec 21, 2015
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split EDNS0 stuff into its own source file.
parent
ce5732e8
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
362 additions
and
344 deletions
+362
-344
Makefile
Makefile
+1
-1
bld/Android.mk
bld/Android.mk
+1
-1
src/dnsmasq.h
src/dnsmasq.h
+9
-8
src/edns0.c
src/edns0.c
+351
-0
src/rfc1035.c
src/rfc1035.c
+0
-334
No files found.
Makefile
View file @
1d03016b
...
@@ -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
poll.o rrfilter.o
edns0.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 @
1d03016b
...
@@ -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
loop.c inotify.c poll.c rrfilter.c
edns0.c
LOCAL_MODULE
:=
dnsmasq
LOCAL_MODULE
:=
dnsmasq
...
...
src/dnsmasq.h
View file @
1d03016b
...
@@ -1123,14 +1123,6 @@ int check_for_local_domain(char *name, time_t now);
...
@@ -1123,14 +1123,6 @@ int check_for_local_domain(char *name, time_t now);
unsigned
int
questions_crc
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
buff
);
unsigned
int
questions_crc
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
buff
);
size_t
resize_packet
(
struct
dns_header
*
header
,
size_t
plen
,
size_t
resize_packet
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pheader
,
size_t
hlen
);
unsigned
char
*
pheader
,
size_t
hlen
);
size_t
add_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
limit
,
unsigned
short
udp_sz
,
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
);
size_t
add_mac
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
l3
);
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
);
#ifdef HAVE_DNSSEC
size_t
add_do_bit
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
);
#endif
int
check_source
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pseudoheader
,
union
mysockaddr
*
peer
);
int
add_resource_record
(
struct
dns_header
*
header
,
char
*
limit
,
int
*
truncp
,
int
add_resource_record
(
struct
dns_header
*
header
,
char
*
limit
,
int
*
truncp
,
int
nameoffset
,
unsigned
char
**
pp
,
unsigned
long
ttl
,
int
nameoffset
,
unsigned
char
**
pp
,
unsigned
long
ttl
,
int
*
offset
,
unsigned
short
type
,
unsigned
short
class
,
char
*
format
,
...);
int
*
offset
,
unsigned
short
type
,
unsigned
short
class
,
char
*
format
,
...);
...
@@ -1521,3 +1513,12 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode);
...
@@ -1521,3 +1513,12 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode);
u16
*
rrfilter_desc
(
int
type
);
u16
*
rrfilter_desc
(
int
type
);
int
expand_workspace
(
unsigned
char
***
wkspc
,
int
*
szp
,
int
new
);
int
expand_workspace
(
unsigned
char
***
wkspc
,
int
*
szp
,
int
new
);
/* edns0.c */
size_t
add_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
limit
,
unsigned
short
udp_sz
,
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
);
size_t
add_mac
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
l3
);
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
);
#ifdef HAVE_DNSSEC
size_t
add_do_bit
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
);
#endif
int
check_source
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pseudoheader
,
union
mysockaddr
*
peer
);
src/edns0.c
0 → 100644
View file @
1d03016b
/* 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"
unsigned
char
*
find_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
size_t
*
len
,
unsigned
char
**
p
,
int
*
is_sign
)
{
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
also return length of pseudoheader in *len and pointer to the UDP size in *p
Finally, check to see if a packet is signed. If it is we cannot change a single bit before
forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
int
i
,
arcount
=
ntohs
(
header
->
arcount
);
unsigned
char
*
ansp
=
(
unsigned
char
*
)(
header
+
1
);
unsigned
short
rdlen
,
type
,
class
;
unsigned
char
*
ret
=
NULL
;
if
(
is_sign
)
{
*
is_sign
=
0
;
if
(
OPCODE
(
header
)
==
QUERY
)
{
for
(
i
=
ntohs
(
header
->
qdcount
);
i
!=
0
;
i
--
)
{
if
(
!
(
ansp
=
skip_name
(
ansp
,
header
,
plen
,
4
)))
return
NULL
;
GETSHORT
(
type
,
ansp
);
GETSHORT
(
class
,
ansp
);
if
(
class
==
C_IN
&&
type
==
T_TKEY
)
*
is_sign
=
1
;
}
}
}
else
{
if
(
!
(
ansp
=
skip_questions
(
header
,
plen
)))
return
NULL
;
}
if
(
arcount
==
0
)
return
NULL
;
if
(
!
(
ansp
=
skip_section
(
ansp
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
),
header
,
plen
)))
return
NULL
;
for
(
i
=
0
;
i
<
arcount
;
i
++
)
{
unsigned
char
*
save
,
*
start
=
ansp
;
if
(
!
(
ansp
=
skip_name
(
ansp
,
header
,
plen
,
10
)))
return
NULL
;
GETSHORT
(
type
,
ansp
);
save
=
ansp
;
GETSHORT
(
class
,
ansp
);
ansp
+=
4
;
/* TTL */
GETSHORT
(
rdlen
,
ansp
);
if
(
!
ADD_RDLEN
(
header
,
ansp
,
plen
,
rdlen
))
return
NULL
;
if
(
type
==
T_OPT
)
{
if
(
len
)
*
len
=
ansp
-
start
;
if
(
p
)
*
p
=
save
;
ret
=
start
;
}
else
if
(
is_sign
&&
i
==
arcount
-
1
&&
class
==
C_ANY
&&
type
==
T_TSIG
)
*
is_sign
=
1
;
}
return
ret
;
}
struct
macparm
{
unsigned
char
*
limit
;
struct
dns_header
*
header
;
size_t
plen
;
union
mysockaddr
*
l3
;
};
size_t
add_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
limit
,
unsigned
short
udp_sz
,
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
)
{
unsigned
char
*
lenp
,
*
datap
,
*
p
;
int
rdlen
,
is_sign
;
if
(
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
)))
{
if
(
is_sign
)
return
plen
;
/* We are adding the pseudoheader */
if
(
!
(
p
=
skip_questions
(
header
,
plen
))
||
!
(
p
=
skip_section
(
p
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
)
+
ntohs
(
header
->
arcount
),
header
,
plen
)))
return
plen
;
*
p
++
=
0
;
/* empty name */
PUTSHORT
(
T_OPT
,
p
);
PUTSHORT
(
udp_sz
,
p
);
/* max packet length, 512 if not given in EDNS0 header */
PUTSHORT
(
0
,
p
);
/* extended RCODE and version */
PUTSHORT
(
set_do
?
0x8000
:
0
,
p
);
/* DO flag */
lenp
=
p
;
PUTSHORT
(
0
,
p
);
/* RDLEN */
rdlen
=
0
;
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
plen
;
/* Too big */
header
->
arcount
=
htons
(
ntohs
(
header
->
arcount
)
+
1
);
datap
=
p
;
}
else
{
int
i
;
unsigned
short
code
,
len
,
flags
;
/* Must be at the end, if exists */
if
(
ntohs
(
header
->
arcount
)
!=
1
||
is_sign
||
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
return
plen
;
p
+=
6
;
/* skip UDP length and RCODE */
GETSHORT
(
flags
,
p
);
if
(
set_do
)
{
p
-=
2
;
PUTSHORT
(
flags
|
0x8000
,
p
);
}
lenp
=
p
;
GETSHORT
(
rdlen
,
p
);
if
(
!
CHECK_LEN
(
header
,
p
,
plen
,
rdlen
))
return
plen
;
/* bad packet */
datap
=
p
;
/* no option to add */
if
(
optno
==
0
)
return
plen
;
/* check if option already there */
for
(
i
=
0
;
i
+
4
<
rdlen
;
i
+=
len
+
4
)
{
GETSHORT
(
code
,
p
);
GETSHORT
(
len
,
p
);
if
(
code
==
optno
)
return
plen
;
p
+=
len
;
}
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
plen
;
/* Too big */
}
if
(
optno
!=
0
)
{
PUTSHORT
(
optno
,
p
);
PUTSHORT
(
optlen
,
p
);
memcpy
(
p
,
opt
,
optlen
);
p
+=
optlen
;
}
PUTSHORT
(
p
-
datap
,
lenp
);
return
p
-
(
unsigned
char
*
)
header
;
}
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
)
{
struct
macparm
parm
;
parm
.
header
=
header
;
parm
.
limit
=
(
unsigned
char
*
)
limit
;
parm
.
plen
=
plen
;
parm
.
l3
=
l3
;
iface_enumerate
(
AF_UNSPEC
,
&
parm
,
filter_mac
);
return
parm
.
plen
;
}
struct
subnet_opt
{
u16
family
;
u8
source_netmask
,
scope_netmask
;
#ifdef HAVE_IPV6
u8
addr
[
IN6ADDRSZ
];
#else
u8
addr
[
INADDRSZ
];
#endif
};
static
void
*
get_addrp
(
union
mysockaddr
*
addr
,
const
short
family
)
{
#ifdef HAVE_IPV6
if
(
family
==
AF_INET6
)
return
&
addr
->
in6
.
sin6_addr
;
#endif
return
&
addr
->
in
.
sin_addr
;
}
static
size_t
calc_subnet_opt
(
struct
subnet_opt
*
opt
,
union
mysockaddr
*
source
)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int
len
;
void
*
addrp
;
int
sa_family
=
source
->
sa
.
sa_family
;
#ifdef HAVE_IPV6
if
(
source
->
sa
.
sa_family
==
AF_INET6
)
{
opt
->
source_netmask
=
daemon
->
add_subnet6
->
mask
;
if
(
daemon
->
add_subnet6
->
addr_used
)
{
sa_family
=
daemon
->
add_subnet6
->
addr
.
sa
.
sa_family
;
addrp
=
get_addrp
(
&
daemon
->
add_subnet6
->
addr
,
sa_family
);
}
else
addrp
=
&
source
->
in6
.
sin6_addr
;
}
else
#endif
{
opt
->
source_netmask
=
daemon
->
add_subnet4
->
mask
;
if
(
daemon
->
add_subnet4
->
addr_used
)
{
sa_family
=
daemon
->
add_subnet4
->
addr
.
sa
.
sa_family
;
addrp
=
get_addrp
(
&
daemon
->
add_subnet4
->
addr
,
sa_family
);
}
else
addrp
=
&
source
->
in
.
sin_addr
;
}
opt
->
scope_netmask
=
0
;
len
=
0
;
if
(
opt
->
source_netmask
!=
0
)
{
#ifdef HAVE_IPV6
opt
->
family
=
htons
(
sa_family
==
AF_INET6
?
2
:
1
);
#else
opt
->
family
=
htons
(
1
);
#endif
len
=
((
opt
->
source_netmask
-
1
)
>>
3
)
+
1
;
memcpy
(
opt
->
addr
,
addrp
,
len
);
if
(
opt
->
source_netmask
&
7
)
opt
->
addr
[
len
-
1
]
&=
0xff
<<
(
8
-
(
opt
->
source_netmask
&
7
));
}
return
len
+
4
;
}
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int
len
;
struct
subnet_opt
opt
;
len
=
calc_subnet_opt
(
&
opt
,
source
);
return
add_pseudoheader
(
header
,
plen
,
(
unsigned
char
*
)
limit
,
PACKETSZ
,
EDNS0_OPTION_CLIENT_SUBNET
,
(
unsigned
char
*
)
&
opt
,
len
,
0
);
}
#ifdef HAVE_DNSSEC
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
);
}
#endif
int
check_source
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pseudoheader
,
union
mysockaddr
*
peer
)
{
/* Section 9.2, Check that subnet option in reply matches. */
int
len
,
calc_len
;
struct
subnet_opt
opt
;
unsigned
char
*
p
;
int
code
,
i
,
rdlen
;
calc_len
=
calc_subnet_opt
(
&
opt
,
peer
);
if
(
!
(
p
=
skip_name
(
pseudoheader
,
header
,
plen
,
10
)))
return
1
;
p
+=
8
;
/* skip UDP length and RCODE */
GETSHORT
(
rdlen
,
p
);
if
(
!
CHECK_LEN
(
header
,
p
,
plen
,
rdlen
))
return
1
;
/* bad packet */
/* check if option there */
for
(
i
=
0
;
i
+
4
<
rdlen
;
i
+=
len
+
4
)
{
GETSHORT
(
code
,
p
);
GETSHORT
(
len
,
p
);
if
(
code
==
EDNS0_OPTION_CLIENT_SUBNET
)
{
/* make sure this doesn't mismatch. */
opt
.
scope_netmask
=
p
[
3
];
if
(
len
!=
calc_len
||
memcmp
(
p
,
&
opt
,
len
)
!=
0
)
return
0
;
}
p
+=
len
;
}
return
1
;
}
src/rfc1035.c
View file @
1d03016b
...
@@ -408,340 +408,6 @@ size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *phea
...
@@ -408,340 +408,6 @@ size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *phea
return
ansp
-
(
unsigned
char
*
)
header
;
return
ansp
-
(
unsigned
char
*
)
header
;
}
}
unsigned
char
*
find_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
size_t
*
len
,
unsigned
char
**
p
,
int
*
is_sign
)
{
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
also return length of pseudoheader in *len and pointer to the UDP size in *p
Finally, check to see if a packet is signed. If it is we cannot change a single bit before
forwarding. We look for SIG and TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
int
i
,
arcount
=
ntohs
(
header
->
arcount
);
unsigned
char
*
ansp
=
(
unsigned
char
*
)(
header
+
1
);
unsigned
short
rdlen
,
type
,
class
;
unsigned
char
*
ret
=
NULL
;
if
(
is_sign
)
{
*
is_sign
=
0
;
if
(
OPCODE
(
header
)
==
QUERY
)
{
for
(
i
=
ntohs
(
header
->
qdcount
);
i
!=
0
;
i
--
)
{
if
(
!
(
ansp
=
skip_name
(
ansp
,
header
,
plen
,
4
)))
return
NULL
;
GETSHORT
(
type
,
ansp
);
GETSHORT
(
class
,
ansp
);
if
(
class
==
C_IN
&&
type
==
T_TKEY
)
*
is_sign
=
1
;
}
}
}
else
{
if
(
!
(
ansp
=
skip_questions
(
header
,
plen
)))
return
NULL
;
}
if
(
arcount
==
0
)
return
NULL
;
if
(
!
(
ansp
=
skip_section
(
ansp
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
),
header
,
plen
)))
return
NULL
;
for
(
i
=
0
;
i
<
arcount
;
i
++
)
{
unsigned
char
*
save
,
*
start
=
ansp
;
if
(
!
(
ansp
=
skip_name
(
ansp
,
header
,
plen
,
10
)))
return
NULL
;
GETSHORT
(
type
,
ansp
);
save
=
ansp
;
GETSHORT
(
class
,
ansp
);
ansp
+=
4
;
/* TTL */
GETSHORT
(
rdlen
,
ansp
);
if
(
!
ADD_RDLEN
(
header
,
ansp
,
plen
,
rdlen
))
return
NULL
;
if
(
type
==
T_OPT
)
{
if
(
len
)
*
len
=
ansp
-
start
;
if
(
p
)
*
p
=
save
;
ret
=
start
;
}
else
if
(
is_sign
&&
i
==
arcount
-
1
&&
class
==
C_ANY
&&
type
==
T_TSIG
)
*
is_sign
=
1
;
}
return
ret
;
}
struct
macparm
{
unsigned
char
*
limit
;
struct
dns_header
*
header
;
size_t
plen
;
union
mysockaddr
*
l3
;
};
size_t
add_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
limit
,
unsigned
short
udp_sz
,
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
)
{
unsigned
char
*
lenp
,
*
datap
,
*
p
;
int
rdlen
,
is_sign
;
if
(
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
)))
{
if
(
is_sign
)
return
plen
;
/* We are adding the pseudoheader */
if
(
!
(
p
=
skip_questions
(
header
,
plen
))
||
!
(
p
=
skip_section
(
p
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
)
+
ntohs
(
header
->
arcount
),
header
,
plen
)))
return
plen
;
*
p
++
=
0
;
/* empty name */
PUTSHORT
(
T_OPT
,
p
);
PUTSHORT
(
udp_sz
,
p
);
/* max packet length, 512 if not given in EDNS0 header */
PUTSHORT
(
0
,
p
);
/* extended RCODE and version */
PUTSHORT
(
set_do
?
0x8000
:
0
,
p
);
/* DO flag */
lenp
=
p
;
PUTSHORT
(
0
,
p
);
/* RDLEN */
rdlen
=
0
;
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
plen
;
/* Too big */
header
->
arcount
=
htons
(
ntohs
(
header
->
arcount
)
+
1
);
datap
=
p
;
}
else
{
int
i
;
unsigned
short
code
,
len
,
flags
;
/* Must be at the end, if exists */
if
(
ntohs
(
header
->
arcount
)
!=
1
||
is_sign
||
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
return
plen
;
p
+=
6
;
/* skip UDP length and RCODE */
GETSHORT
(
flags
,
p
);
if
(
set_do
)
{
p
-=
2
;
PUTSHORT
(
flags
|
0x8000
,
p
);
}
lenp
=
p
;
GETSHORT
(
rdlen
,
p
);
if
(
!
CHECK_LEN
(
header
,
p
,
plen
,
rdlen
))
return
plen
;
/* bad packet */
datap
=
p
;
/* no option to add */
if
(
optno
==
0
)
return
plen
;
/* check if option already there */
for
(
i
=
0
;
i
+
4
<
rdlen
;
i
+=
len
+
4
)
{
GETSHORT
(
code
,
p
);
GETSHORT
(
len
,
p
);
if
(
code
==
optno
)
return
plen
;
p
+=
len
;
}
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
plen
;
/* Too big */
}
if
(
optno
!=
0
)
{
PUTSHORT
(
optno
,
p
);
PUTSHORT
(
optlen
,
p
);
memcpy
(
p
,
opt
,
optlen
);
p
+=
optlen
;
}
PUTSHORT
(
p
-
datap
,
lenp
);
return
p
-
(
unsigned
char
*
)
header
;
}
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
)
{
struct
macparm
parm
;
parm
.
header
=
header
;
parm
.
limit
=
(
unsigned
char
*
)
limit
;
parm
.
plen
=
plen
;
parm
.
l3
=
l3
;
iface_enumerate
(
AF_UNSPEC
,
&
parm
,
filter_mac
);
return
parm
.
plen
;
}
struct
subnet_opt
{
u16
family
;
u8
source_netmask
,
scope_netmask
;
#ifdef HAVE_IPV6
u8
addr
[
IN6ADDRSZ
];
#else
u8
addr
[
INADDRSZ
];
#endif
};
static
void
*
get_addrp
(
union
mysockaddr
*
addr
,
const
short
family
)
{
#ifdef HAVE_IPV6
if
(
family
==
AF_INET6
)
return
&
addr
->
in6
.
sin6_addr
;
#endif
return
&
addr
->
in
.
sin_addr
;
}
static
size_t
calc_subnet_opt
(
struct
subnet_opt
*
opt
,
union
mysockaddr
*
source
)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int
len
;
void
*
addrp
;
int
sa_family
=
source
->
sa
.
sa_family
;
#ifdef HAVE_IPV6
if
(
source
->
sa
.
sa_family
==
AF_INET6
)
{
opt
->
source_netmask
=
daemon
->
add_subnet6
->
mask
;
if
(
daemon
->
add_subnet6
->
addr_used
)
{
sa_family
=
daemon
->
add_subnet6
->
addr
.
sa
.
sa_family
;
addrp
=
get_addrp
(
&
daemon
->
add_subnet6
->
addr
,
sa_family
);
}
else
addrp
=
&
source
->
in6
.
sin6_addr
;
}
else
#endif
{
opt
->
source_netmask
=
daemon
->
add_subnet4
->
mask
;
if
(
daemon
->
add_subnet4
->
addr_used
)
{
sa_family
=
daemon
->
add_subnet4
->
addr
.
sa
.
sa_family
;
addrp
=
get_addrp
(
&
daemon
->
add_subnet4
->
addr
,
sa_family
);
}
else
addrp
=
&
source
->
in
.
sin_addr
;
}
opt
->
scope_netmask
=
0
;
len
=
0
;
if
(
opt
->
source_netmask
!=
0
)
{
#ifdef HAVE_IPV6
opt
->
family
=
htons
(
sa_family
==
AF_INET6
?
2
:
1
);
#else
opt
->
family
=
htons
(
1
);
#endif
len
=
((
opt
->
source_netmask
-
1
)
>>
3
)
+
1
;
memcpy
(
opt
->
addr
,
addrp
,
len
);
if
(
opt
->
source_netmask
&
7
)
opt
->
addr
[
len
-
1
]
&=
0xff
<<
(
8
-
(
opt
->
source_netmask
&
7
));
}
return
len
+
4
;
}
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int
len
;
struct
subnet_opt
opt
;
len
=
calc_subnet_opt
(
&
opt
,
source
);
return
add_pseudoheader
(
header
,
plen
,
(
unsigned
char
*
)
limit
,
PACKETSZ
,
EDNS0_OPTION_CLIENT_SUBNET
,
(
unsigned
char
*
)
&
opt
,
len
,
0
);
}
#ifdef HAVE_DNSSEC
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
);
}
#endif
int
check_source
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
pseudoheader
,
union
mysockaddr
*
peer
)
{
/* Section 9.2, Check that subnet option in reply matches. */
int
len
,
calc_len
;
struct
subnet_opt
opt
;
unsigned
char
*
p
;
int
code
,
i
,
rdlen
;
calc_len
=
calc_subnet_opt
(
&
opt
,
peer
);
if
(
!
(
p
=
skip_name
(
pseudoheader
,
header
,
plen
,
10
)))
return
1
;
p
+=
8
;
/* skip UDP length and RCODE */
GETSHORT
(
rdlen
,
p
);
if
(
!
CHECK_LEN
(
header
,
p
,
plen
,
rdlen
))
return
1
;
/* bad packet */
/* check if option there */
for
(
i
=
0
;
i
+
4
<
rdlen
;
i
+=
len
+
4
)
{
GETSHORT
(
code
,
p
);
GETSHORT
(
len
,
p
);
if
(
code
==
EDNS0_OPTION_CLIENT_SUBNET
)
{
/* make sure this doesn't mismatch. */
opt
.
scope_netmask
=
p
[
3
];
if
(
len
!=
calc_len
||
memcmp
(
p
,
&
opt
,
len
)
!=
0
)
return
0
;
}
p
+=
len
;
}
return
1
;
}
/* is addr in the non-globally-routed IP space? */
/* is addr in the non-globally-routed IP space? */
int
private_net
(
struct
in_addr
addr
,
int
ban_localhost
)
int
private_net
(
struct
in_addr
addr
,
int
ban_localhost
)
{
{
...
...
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