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
3a237152
Commit
3a237152
authored
Dec 12, 2013
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit to allow master merge.
parent
65c9b489
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
209 additions
and
52 deletions
+209
-52
src/dnsmasq.c
src/dnsmasq.c
+3
-3
src/dnsmasq.h
src/dnsmasq.h
+27
-7
src/dnssec.c
src/dnssec.c
+7
-7
src/forward.c
src/forward.c
+143
-22
src/option.c
src/option.c
+1
-1
src/rfc1035.c
src/rfc1035.c
+28
-12
No files found.
src/dnsmasq.c
View file @
3a237152
...
...
@@ -81,10 +81,10 @@ int main (int argc, char **argv)
umask
(
022
);
/* known umask, create leases and pid files as 0644 */
read_opts
(
argc
,
argv
,
compile_opts
);
if
(
option_bool
(
OPT_DNSSEC_VALID
ATE
))
if
(
option_bool
(
OPT_DNSSEC_VALID
))
if
(
daemon
->
doctors
)
exit
(
1
);
/* TODO */
if
(
daemon
->
edns_pktsz
<
PACKETSZ
)
daemon
->
edns_pktsz
=
option_bool
(
OPT_DNSSEC_VALID
ATE
)
?
EDNS_PKTSZ
:
PACKETSZ
;
daemon
->
edns_pktsz
=
option_bool
(
OPT_DNSSEC_VALID
)
?
EDNS_PKTSZ
:
PACKETSZ
;
daemon
->
packet_buff_sz
=
daemon
->
edns_pktsz
>
DNSMASQ_PACKETSZ
?
daemon
->
edns_pktsz
:
DNSMASQ_PACKETSZ
;
daemon
->
packet
=
safe_malloc
(
daemon
->
packet_buff_sz
);
...
...
@@ -1302,7 +1302,7 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
/* will we be able to get memory? */
if
(
daemon
->
port
!=
0
)
get_new_frec
(
now
,
&
wait
);
get_new_frec
(
now
,
&
wait
,
0
);
for
(
serverfdp
=
daemon
->
sfds
;
serverfdp
;
serverfdp
=
serverfdp
->
next
)
{
...
...
src/dnsmasq.h
View file @
3a237152
...
...
@@ -228,7 +228,7 @@ struct event_desc {
#define OPT_QUIET_DHCP 42
#define OPT_QUIET_DHCP6 43
#define OPT_QUIET_RA 44
#define OPT_DNSSEC_VALID
ATE
45
#define OPT_DNSSEC_VALID
45
#define OPT_LAST 46
/* extra flags for my_syslog, we use a couple of facilities since they are known
...
...
@@ -352,7 +352,7 @@ struct crec {
int
uid
;
/* -1 if union is interface-name */
}
cname
;
struct
{
struct
key
data
*
keydata
;
struct
block
data
*
keydata
;
unsigned
char
algo
;
unsigned
char
digest
;
/* DS only */
unsigned
short
keytag
;
...
...
@@ -499,9 +499,20 @@ struct hostsfile {
int
index
;
/* matches to cache entries for logging */
};
/* DNSSEC status values. */
#define STAT_SECURE 1
#define STAT_INSECURE 2
#define STAT_BOGUS 3
#define STAT_NEED_DS 4
#define STAT_NEED_KEY 5
#define FREC_NOREBIND 1
#define FREC_CHECKING_DISABLED 2
#define FREC_HAS_SUBNET 4
#define FREC_DNSSEC_QUERY 8
#define FREC_DNSKEY_QUERY 16
#define FREC_DS_QUERY 32
struct
frec
{
union
mysockaddr
source
;
...
...
@@ -516,6 +527,12 @@ struct frec {
int
fd
,
forwardall
,
flags
;
unsigned
int
crc
;
time_t
time
;
#ifdef HAVE_DNSSEC
struct
blockdata
*
stash
;
/* Saved reply, whilst we validate */
size_t
stash_len
;
struct
frec
*
dependent
;
/* Query awaiting internally-generated DNSKEY or DS query */
struct
frec
*
blocking_query
;
/* Query which is blocking us. */
#endif
struct
frec
*
next
;
};
...
...
@@ -954,9 +971,9 @@ char *cache_get_name(struct crec *crecp);
char
*
cache_get_cname_target
(
struct
crec
*
crecp
);
struct
crec
*
cache_enumerate
(
int
init
);
#ifdef HAVE_DNSSEC
struct
keydata
*
key
data_alloc
(
char
*
data
,
size_t
len
);
size_t
keydata_walk
(
struct
key
data
**
key
,
unsigned
char
**
p
,
size_t
cnt
);
void
keydata_free
(
struct
key
data
*
blocks
);
struct
blockdata
*
block
data_alloc
(
char
*
data
,
size_t
len
);
size_t
blockdata_walk
(
struct
block
data
**
key
,
unsigned
char
**
p
,
size_t
cnt
);
void
blockdata_free
(
struct
block
data
*
blocks
);
#endif
/* domain.c */
...
...
@@ -992,6 +1009,9 @@ size_t resize_packet(struct dns_header *header, size_t plen,
unsigned
char
*
pheader
,
size_t
hlen
);
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
nameoffset
,
unsigned
char
**
pp
,
unsigned
long
ttl
,
...
...
@@ -1010,7 +1030,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* dnssec.c */
int
dnssec_validate
(
struct
dns_header
*
header
,
size_t
plen
);
int
dnssec_validate
(
int
flags
,
struct
dns_header
*
header
,
size_t
plen
);
/* util.c */
void
rand_init
(
void
);
...
...
@@ -1072,7 +1092,7 @@ void receive_query(struct listener *listen, time_t now);
unsigned
char
*
tcp_request
(
int
confd
,
time_t
now
,
union
mysockaddr
*
local_addr
,
struct
in_addr
netmask
,
int
auth_dns
);
void
server_gone
(
struct
server
*
server
);
struct
frec
*
get_new_frec
(
time_t
now
,
int
*
wait
);
struct
frec
*
get_new_frec
(
time_t
now
,
int
*
wait
,
int
force
);
int
send_from
(
int
fd
,
int
nowild
,
char
*
packet
,
size_t
len
,
union
mysockaddr
*
to
,
struct
all_addr
*
source
,
unsigned
int
iface
);
...
...
src/dnssec.c
View file @
3a237152
...
...
@@ -713,7 +713,7 @@ int dnssec_parsekey(struct dns_header *header, size_t pktlen, char *owner, unsig
int
rdlen
,
unsigned
char
*
rdata
)
{
int
flags
,
proto
,
alg
;
struct
key
data
*
key
;
struct
crec
*
crecp
;
struct
block
data
*
key
;
struct
crec
*
crecp
;
unsigned
char
*
ordata
=
rdata
;
int
ordlen
=
rdlen
;
CHECKED_GETSHORT
(
flags
,
rdata
,
rdlen
);
...
...
@@ -726,7 +726,7 @@ int dnssec_parsekey(struct dns_header *header, size_t pktlen, char *owner, unsig
if
(
!
(
flags
&
0x100
))
return
0
;
key
=
key
data_alloc
((
char
*
)
rdata
,
rdlen
);
key
=
block
data_alloc
((
char
*
)
rdata
,
rdlen
);
/* TODO: time(0) is correct here? */
crecp
=
cache_insert
(
owner
,
NULL
,
time
(
0
),
ttl
,
F_FORWARD
|
F_DNSKEY
);
...
...
@@ -741,7 +741,7 @@ int dnssec_parsekey(struct dns_header *header, size_t pktlen, char *owner, unsig
}
else
{
key
data_free
(
key
);
block
data_free
(
key
);
/* TODO: if insertion really might fail, verify we don't depend on cache
insertion success for validation workflow correctness */
printf
(
"DNSKEY: cache insertion failure
\n
"
);
...
...
@@ -754,7 +754,7 @@ int dnssec_parseds(struct dns_header *header, size_t pktlen, char *owner, unsign
int
rdlen
,
unsigned
char
*
rdata
)
{
int
keytag
,
algo
,
dig
;
struct
key
data
*
key
;
struct
crec
*
crec_ds
,
*
crec_key
;
struct
block
data
*
key
;
struct
crec
*
crec_ds
,
*
crec_key
;
CHECKED_GETSHORT
(
keytag
,
rdata
,
rdlen
);
CHECKED_GETCHAR
(
algo
,
rdata
,
rdlen
);
...
...
@@ -763,13 +763,13 @@ int dnssec_parseds(struct dns_header *header, size_t pktlen, char *owner, unsign
if
(
!
digestalg_supported
(
dig
))
return
0
;
key
=
key
data_alloc
((
char
*
)
rdata
,
rdlen
);
key
=
block
data_alloc
((
char
*
)
rdata
,
rdlen
);
/* TODO: time(0) is correct here? */
crec_ds
=
cache_insert
(
owner
,
NULL
,
time
(
0
),
ttl
,
F_FORWARD
|
F_DS
);
if
(
!
crec_ds
)
{
key
data_free
(
key
);
block
data_free
(
key
);
/* TODO: if insertion really might fail, verify we don't depend on cache
insertion success for validation workflow correctness */
printf
(
"DS: cache insertion failure
\n
"
);
...
...
@@ -800,7 +800,7 @@ int dnssec_parseds(struct dns_header *header, size_t pktlen, char *owner, unsign
return
0
;
}
int
dnssec_validate
(
struct
dns_header
*
header
,
size_t
pktlen
)
int
dnssec
1
_validate
(
struct
dns_header
*
header
,
size_t
pktlen
)
{
unsigned
char
*
p
,
*
reply
;
char
*
owner
=
daemon
->
namebuff
;
...
...
src/forward.c
View file @
3a237152
...
...
@@ -270,7 +270,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if
(
gotname
)
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
);
if
(
!
flags
&&
!
(
forward
=
get_new_frec
(
now
,
NULL
)))
if
(
!
flags
&&
!
(
forward
=
get_new_frec
(
now
,
NULL
,
0
)))
/* table full - server failure. */
flags
=
F_NEG
;
...
...
@@ -342,6 +342,11 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
}
#ifdef HAVE_DNSSEC
if
(
option_bool
(
OPT_DNSSEC_VALID
))
plen
=
add_do_bit
(
header
,
plen
,
((
char
*
)
header
)
+
PACKETSZ
);
#endif
while
(
1
)
{
/* only send to servers dealing with our domain.
...
...
@@ -447,12 +452,13 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
static
size_t
process_reply
(
struct
dns_header
*
header
,
time_t
now
,
struct
server
*
server
,
size_t
n
,
int
check_rebind
,
int
checking_disabled
,
int
check_subnet
,
union
mysockaddr
*
query_source
)
int
no_cache
,
int
cache_secure
,
int
check_subnet
,
union
mysockaddr
*
query_source
)
{
unsigned
char
*
pheader
,
*
sizep
;
char
**
sets
=
0
;
int
munged
=
0
,
is_sign
;
size_t
plen
;
int
squash_ad
=
0
;
#ifdef HAVE_IPSET
/* Similar algorithm to search_servers. */
...
...
@@ -495,11 +501,21 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
}
}
/* RFC 4035 sect 4.6 para 3 */
if
(
!
is_sign
&&
!
option_bool
(
OPT_DNSSEC_PROXY
))
header
->
hb4
&=
~
HB4_AD
;
squash_ad
=
1
;
#ifdef HAVE_DNSSEC
if
(
option_bool
(
OPT_DNSSEC_VALID
))
squash_ad
=
no_cache
;
if
(
cache_secure
)
header
->
hb4
|=
HB4_AD
;
#endif
if
(
squash_ad
)
header
->
hb4
&=
~
HB4_AD
;
if
(
OPCODE
(
header
)
!=
QUERY
||
(
RCODE
(
header
)
!=
NOERROR
&&
RCODE
(
header
)
!=
NXDOMAIN
))
return
n
;
...
...
@@ -513,11 +529,6 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
server
->
flags
|=
SERV_WARNED_RECURSIVE
;
}
#ifdef HAVE_DNSSEC
printf
(
"validate
\n
"
);
dnssec_validate
(
header
,
n
);
#endif
if
(
daemon
->
bogus_addr
&&
RCODE
(
header
)
!=
NXDOMAIN
&&
check_for_bogus_wildcard
(
header
,
n
,
daemon
->
namebuff
,
daemon
->
bogus_addr
,
now
))
{
...
...
@@ -539,7 +550,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
SET_RCODE
(
header
,
NOERROR
);
}
if
(
extract_addresses
(
header
,
n
,
daemon
->
namebuff
,
now
,
sets
,
is_sign
,
check_rebind
,
checking_disabled
))
if
(
extract_addresses
(
header
,
n
,
daemon
->
namebuff
,
now
,
sets
,
is_sign
,
check_rebind
,
no_cache
))
{
my_syslog
(
LOG_WARNING
,
_
(
"possible DNS-rebind attack detected: %s"
),
daemon
->
namebuff
);
munged
=
1
;
...
...
@@ -597,9 +608,7 @@ void reply_query(int fd, int family, time_t now)
n
<
(
int
)
sizeof
(
struct
dns_header
)
||
!
(
header
->
hb3
&
HB3_QR
)
||
!
(
forward
=
lookup_frec
(
ntohs
(
header
->
id
),
questions_crc
(
header
,
n
,
daemon
->
namebuff
))))
return
;
server
=
forward
->
sentto
;
if
((
RCODE
(
header
)
==
SERVFAIL
||
RCODE
(
header
)
==
REFUSED
)
&&
!
option_bool
(
OPT_ORDER
)
&&
forward
->
forwardall
==
0
)
...
...
@@ -624,6 +633,8 @@ void reply_query(int fd, int family, time_t now)
}
}
}
server
=
forward
->
sentto
;
if
((
forward
->
sentto
->
flags
&
SERV_TYPE
)
==
0
)
{
...
...
@@ -645,7 +656,7 @@ void reply_query(int fd, int family, time_t now)
if
(
!
option_bool
(
OPT_ALL_SERVERS
))
daemon
->
last_server
=
server
;
}
/* If the answer is an error, keep the forward record in place in case
we get a good reply from another server. Kill it when we've
had replies from all to avoid filling the forwarding table when
...
...
@@ -653,12 +664,106 @@ void reply_query(int fd, int family, time_t now)
if
(
forward
->
forwardall
==
0
||
--
forward
->
forwardall
==
1
||
(
RCODE
(
header
)
!=
REFUSED
&&
RCODE
(
header
)
!=
SERVFAIL
))
{
int
check_rebind
=
!
(
forward
->
flags
&
FREC_NOREBIND
);
int
check_rebind
=
0
,
no_cache_dnssec
=
0
,
cache_secure
=
0
;
if
(
option_bool
(
OPT_NO_REBIND
))
check_rebind
=
!
(
forward
->
flags
&
FREC_NOREBIND
);
/* Don't cache replies where DNSSEC validation was turned off, either
the upstream server told us so, or the original query specified it. */
if
((
header
->
hb4
&
HB4_CD
)
||
(
forward
->
flags
&
FREC_CHECKING_DISABLED
))
no_cache_dnssec
=
1
;
#ifdef HAVE_DNSSEC
if
(
option_bool
(
OPT_DNSSEC_VALID
)
&&
!
(
forward
->
flags
&
FREC_CHECKING_DISABLED
))
{
int
status
=
dnssec_validate
(
forward
->
flags
,
header
,
n
);
/* Can't validate, as we're missing key data. Put this
answer aside, whilst we get that. */
if
(
status
==
STAT_NEED_DS
||
status
==
STAT_NEED_KEY
)
{
struct
frec
*
new
;
if
((
forward
->
stash
=
blockdata_alloc
((
char
*
)
header
,
n
)))
{
forward
->
stash_len
=
n
;
/* Now formulate a query for the missing data. */
nn
=
dnssec_generate_query
(
header
,
status
);
new
=
get_new_frec
(
now
,
NULL
,
1
);
if
(
new
)
{
int
fd
;
if
(
!
option_bool
(
OPT_NO_REBIND
))
check_rebind
=
0
;
new
=
forward
;
/* copy everything, then overwrite */
new
->
dependent
=
forward
;
/* to find query awaiting new one. */
forward
->
blocking_query
=
new
;
/* for garbage cleaning */
new
->
flags
|=
FREC_DNSSEC_QUERY
;
if
(
status
==
STAT_NEED_KEY
)
new
->
flags
|=
FREC_DNSKEY_QUERY
;
/* So we verify differently */
else
if
(
status
==
STAT_NEED_DS
)
new
->
flags
|=
FREC_DS_QUERY
;
new
->
crc
=
questions_crc
(
header
,
nn
,
daemon
->
namebuff
);
new
->
new_id
=
get_id
(
new
->
crc
);
/* Don't resend this. */
daemon
->
srv_save
=
NULL
;
if
(
server
->
sfd
)
fd
=
server
->
sfd
->
fd
;
else
#ifdef HAVE_IPV6
/* Note that we use the same random port for the DNSSEC stuff */
if
(
server
->
addr
.
sa
.
sa_family
==
AF_INET6
)
{
fd
=
new
->
rfd6
->
fd
;
new
->
rfd6
->
refcount
++
;
}
else
#endif
{
fd
=
new
->
rfd4
->
fd
;
new
->
rfd4
->
refcount
++
;
}
/* Send DNSSEC query to same server as original query */
while
(
sendto
(
fd
,
(
char
*
)
header
,
nn
,
0
,
&
server
->
addr
.
sa
,
sa_len
(
&
server
->
addr
))
==
-
1
&&
retry_send
());
}
}
return
;
}
/* Ok, we reached far enough up the chain-of-trust that we can validate something.
Now wind back down, pulling back answers which wouldn't previously validate
and validate them with the new data. Failure to find needed data here is an internal error.
Once we get to the original answer (FREC_DNSSEC_QUERY not set) and it validates,
return it to the original requestor. */
while
(
forward
->
flags
&
FREC_DNSSEC_QUERY
)
{
if
(
status
==
STAT_SECURE
)
extract_dnssec_replies
();
free_frec
(
forward
);
forward
=
forward
->
dependent
;
blockdata_retrieve_and_free
(
forward
->
stash
,
forward
->
stash_len
,
(
void
*
)
header
);
n
=
forward
->
stash_len
;
if
(
status
==
STAT_SECURE
)
{
status
=
dnssec_validate
(
forward
->
flags
,
header
,
n
);
if
(
status
==
STAT_NEED_DS
||
status
==
STAT_NEED_KEY
)
my_syslog
(
LOG_ERR
,
_
(
"Unexpected missing data for DNSSEC validation"
));
}
}
if
(
status
==
STAT_SECURE
)
cache_secure
=
1
;
/* TODO return SERVFAIL here */
else
if
(
status
==
STAT_BOGUS
)
no_cache_dnssec
=
1
;
}
#endif
if
((
nn
=
process_reply
(
header
,
now
,
server
,
(
size_t
)
n
,
check_rebind
,
forward
->
flags
&
FREC_CHECKING_DISABLED
,
if
((
nn
=
process_reply
(
header
,
now
,
server
,
(
size_t
)
n
,
check_rebind
,
no_cache_dnssec
,
cache_secure
,
forward
->
flags
&
FREC_HAS_SUBNET
,
&
forward
->
source
)))
{
header
->
id
=
htons
(
forward
->
orig_id
);
...
...
@@ -1129,7 +1234,7 @@ unsigned char *tcp_request(int confd, time_t now,
if
(
crc
==
questions_crc
(
header
,
(
unsigned
int
)
m
,
daemon
->
namebuff
))
m
=
process_reply
(
header
,
now
,
last_server
,
(
unsigned
int
)
m
,
option_bool
(
OPT_NO_REBIND
)
&&
!
norebind
,
checking_disabled
,
check_subnet
,
&
peer_addr
);
0
,
check_subnet
,
&
peer_addr
);
/* TODO - cache secure */
break
;
}
...
...
@@ -1163,6 +1268,9 @@ static struct frec *allocate_frec(time_t now)
f
->
flags
=
0
;
#ifdef HAVE_IPV6
f
->
rfd6
=
NULL
;
#endif
#ifdef HAVE_DNSSEC
f
->
blocking_query
=
NULL
;
#endif
daemon
->
frec_list
=
f
;
}
...
...
@@ -1221,13 +1329,26 @@ static void free_frec(struct frec *f)
f
->
rfd6
=
NULL
;
#endif
#ifdef HAVE_DNSSEC
if
(
f
->
stash
)
blockdata_free
(
f
->
stash
);
/* Anything we're waiting on is pointless now, too */
if
(
f
->
blocking_query
)
free_frec
(
f
->
blocking_query
);
f
->
blocking_query
=
NULL
;
#endif
}
/* if wait==NULL return a free or older than TIMEOUT record.
else return *wait zero if one available, or *wait is delay to
when the oldest in-use record will expire. Impose an absolute
limit of 4*TIMEOUT before we wipe things (for random sockets) */
struct
frec
*
get_new_frec
(
time_t
now
,
int
*
wait
)
limit of 4*TIMEOUT before we wipe things (for random sockets).
If force is set, always return a result, even if we have
to allocate above the limit. */
struct
frec
*
get_new_frec
(
time_t
now
,
int
*
wait
,
int
force
)
{
struct
frec
*
f
,
*
oldest
,
*
target
;
int
count
;
...
...
@@ -1276,7 +1397,7 @@ struct frec *get_new_frec(time_t now, int *wait)
}
/* none available, calculate time 'till oldest record expires */
if
(
count
>
daemon
->
ftabsize
)
if
(
!
force
&&
count
>
daemon
->
ftabsize
)
{
static
time_t
last_log
=
0
;
...
...
src/option.c
View file @
3a237152
...
...
@@ -427,7 +427,7 @@ static struct {
{
LOPT_IPSET
,
ARG_DUP
,
"/<domain>/<ipset>[,<ipset>...]"
,
gettext_noop
(
"Specify ipsets to which matching domains should be added"
),
NULL
},
{
LOPT_SYNTH
,
ARG_DUP
,
"<domain>,<range>,[<prefix>]"
,
gettext_noop
(
"Specify a domain and address range for synthesised names"
),
NULL
},
#ifdef HAVE_DNSSEC
{
LOPT_SEC_VALID
,
OPT_DNSSEC_VALID
ATE
,
NULL
,
gettext_noop
(
"Activate DNSSEC validation"
),
NULL
},
{
LOPT_SEC_VALID
,
OPT_DNSSEC_VALID
,
NULL
,
gettext_noop
(
"Activate DNSSEC validation"
),
NULL
},
#endif
#ifdef OPTION6_PREFIX_CLASS
{
LOPT_PREF_CLSS
,
ARG_DUP
,
"set:tag,<class>"
,
gettext_noop
(
"Specify DHCPv6 prefix class"
),
NULL
},
...
...
src/rfc1035.c
View file @
3a237152
...
...
@@ -515,7 +515,7 @@ struct macparm {
};
static
size_t
add_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
limit
,
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
)
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
,
int
set_do
)
{
unsigned
char
*
lenp
,
*
datap
,
*
p
;
int
rdlen
;
...
...
@@ -531,7 +531,8 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
*
p
++
=
0
;
/* empty name */
PUTSHORT
(
T_OPT
,
p
);
PUTSHORT
(
daemon
->
edns_pktsz
,
p
);
/* max packet length */
PUTLONG
(
0
,
p
);
/* extended RCODE */
PUTSHORT
(
0
,
p
);
/* extended RCODE and version */
PUTSHORT
(
set_do
?
0x8000
:
0
,
p
);
/* DO flag */
lenp
=
p
;
PUTSHORT
(
0
,
p
);
/* RDLEN */
rdlen
=
0
;
...
...
@@ -543,7 +544,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
else
{
int
i
,
is_sign
;
unsigned
short
code
,
len
;
unsigned
short
code
,
len
,
flags
;
if
(
ntohs
(
header
->
arcount
)
!=
1
||
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
))
||
...
...
@@ -551,14 +552,24 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
return
plen
;
p
+=
8
;
/* skip UDP length and RCODE */
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
)
{
...
...
@@ -602,7 +613,7 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
if
(
!
match
)
return
1
;
/* continue */
parm
->
plen
=
add_pseudoheader
(
parm
->
header
,
parm
->
plen
,
parm
->
limit
,
EDNS0_OPTION_MAC
,
(
unsigned
char
*
)
mac
,
maclen
);
parm
->
plen
=
add_pseudoheader
(
parm
->
header
,
parm
->
plen
,
parm
->
limit
,
EDNS0_OPTION_MAC
,
(
unsigned
char
*
)
mac
,
maclen
,
0
);
return
0
;
/* done */
}
...
...
@@ -681,9 +692,16 @@ size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, unio
struct
subnet_opt
opt
;
len
=
calc_subnet_opt
(
&
opt
,
source
);
return
add_pseudoheader
(
header
,
plen
,
(
unsigned
char
*
)
limit
,
EDNS0_OPTION_CLIENT_SUBNET
,
(
unsigned
char
*
)
&
opt
,
len
);
return
add_pseudoheader
(
header
,
plen
,
(
unsigned
char
*
)
limit
,
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
,
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. */
...
...
@@ -878,7 +896,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name)
expired and cleaned out that way.
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
int
extract_addresses
(
struct
dns_header
*
header
,
size_t
qlen
,
char
*
name
,
time_t
now
,
char
**
ipsets
,
int
is_sign
,
int
check_rebind
,
int
checking_disabled
)
char
**
ipsets
,
int
is_sign
,
int
check_rebind
,
int
no_cache_dnssec
)
{
unsigned
char
*
p
,
*
p1
,
*
endrr
,
*
namep
;
int
i
,
j
,
qtype
,
qclass
,
aqtype
,
aqclass
,
ardlen
,
res
,
searched_soa
=
0
;
...
...
@@ -1118,15 +1136,13 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
}
/* Don't put stuff from a truncated packet into the cache.
Don't cache replies where DNSSEC validation was turned off, either
the upstream server told us so, or the original query specified it.
Don't cache replies from non-recursive nameservers, since we may get a
reply containing a CNAME but not its target, even though the target
does exist. */
if
(
!
(
header
->
hb3
&
HB3_TC
)
&&
!
(
header
->
hb4
&
HB4_CD
)
&&
(
header
->
hb4
&
HB4_RA
)
&&
!
checking_disabled
)
!
no_cache_dnssec
)
cache_end_insert
();
return
0
;
...
...
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