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
ed4c0767
Commit
ed4c0767
authored
Oct 08, 2013
by
Simon Kelley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
--add-subnet option.
parent
043c271f
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
234 additions
and
59 deletions
+234
-59
CHANGELOG
CHANGELOG
+3
-0
man/dnsmasq.8
man/dnsmasq.8
+14
-1
src/config.h
src/config.h
+0
-1
src/dns-protocol.h
src/dns-protocol.h
+4
-0
src/dnsmasq.h
src/dnsmasq.h
+7
-1
src/forward.c
src/forward.c
+48
-13
src/option.c
src/option.c
+14
-0
src/rfc1035.c
src/rfc1035.c
+144
-43
No files found.
CHANGELOG
View file @
ed4c0767
...
@@ -132,6 +132,9 @@ version 2.67
...
@@ -132,6 +132,9 @@ version 2.67
Update Spanish transalation. Thanks to Vicente Soriano.
Update Spanish transalation. Thanks to Vicente Soriano.
Add --add-subnet configuration, to tell upstream DNS
servers where the original client is.
version 2.66
version 2.66
Add the ability to act as an authoritative DNS
Add the ability to act as an authoritative DNS
...
...
man/dnsmasq.8
View file @
ed4c0767
...
@@ -543,7 +543,20 @@ server. The MAC address can only be added if the requestor is on the same
...
@@ -543,7 +543,20 @@ server. The MAC address can only be added if the requestor is on the same
subnet as the dnsmasq server. Note that the mechanism used to achieve this (an EDNS0 option)
subnet as the dnsmasq server. Note that the mechanism used to achieve this (an EDNS0 option)
is not yet standardised, so this should be considered
is not yet standardised, so this should be considered
experimental. Also note that exposing MAC addresses in this way may
experimental. Also note that exposing MAC addresses in this way may
have security and privacy implications.
have security and privacy implications. The warning about caching
given for --add-subnet applies to --add-mac too.
.TP
.B --add-subnet[[=<IPv4 prefix length>],<IPv6 prefix length>]
Add the subnet address of the requestor to the DNS queries which are
forwarded upstream. The amount of the address forwarded depends on the
prefix length parameter: 32 (128 for IPv6) forwards the whole address,
zero forwards none of it but still marks the request so that no
upstream nameserver will add client address information either. The
default is zero for both IPv4 and IPv6. Note that upstream nameservers
may be configured to return different results based on this
information, but the dnsmasq cache does not take account. If a dnsmasq
instance is configured such that different results may be encountered,
caching should be disabled.
.TP
.TP
.B \-c, --cache-size=<cachesize>
.B \-c, --cache-size=<cachesize>
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
...
...
src/config.h
View file @
ed4c0767
...
@@ -39,7 +39,6 @@
...
@@ -39,7 +39,6 @@
#define TFTP_MAX_CONNECTIONS 50
/* max simultaneous connections */
#define TFTP_MAX_CONNECTIONS 50
/* max simultaneous connections */
#define LOG_MAX 5
/* log-queue length */
#define LOG_MAX 5
/* log-queue length */
#define RANDFILE "/dev/urandom"
#define RANDFILE "/dev/urandom"
#define EDNS0_OPTION_MAC 5
/* dyndns.org temporary assignment */
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
/* Default - may be overridden by config */
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq"
/* Default - may be overridden by config */
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
#define AUTH_TTL 600
/* default TTL for auth DNS */
#define AUTH_TTL 600
/* default TTL for auth DNS */
...
...
src/dns-protocol.h
View file @
ed4c0767
...
@@ -56,6 +56,10 @@
...
@@ -56,6 +56,10 @@
#define T_MAILB 253
#define T_MAILB 253
#define T_ANY 255
#define T_ANY 255
#define EDNS0_OPTION_MAC 65001
/* dyndns.org temporary assignment */
#define EDNS0_OPTION_CLIENT_SUBNET 5
/* IANA */
struct
dns_header
{
struct
dns_header
{
u16
id
;
u16
id
;
u8
hb3
,
hb4
;
u8
hb3
,
hb4
;
...
...
src/dnsmasq.h
View file @
ed4c0767
...
@@ -222,7 +222,8 @@ struct event_desc {
...
@@ -222,7 +222,8 @@ struct event_desc {
#define OPT_CLEVERBIND 39
#define OPT_CLEVERBIND 39
#define OPT_TFTP 40
#define OPT_TFTP 40
#define OPT_FAST_RA 41
#define OPT_FAST_RA 41
#define OPT_LAST 42
#define OPT_CLIENT_SUBNET 42
#define OPT_LAST 43
/* extra flags for my_syslog, we use a couple of facilities since they are known
/* extra flags for my_syslog, we use a couple of facilities since they are known
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
...
@@ -487,6 +488,7 @@ struct hostsfile {
...
@@ -487,6 +488,7 @@ struct hostsfile {
#define FREC_NOREBIND 1
#define FREC_NOREBIND 1
#define FREC_CHECKING_DISABLED 2
#define FREC_CHECKING_DISABLED 2
#define FREC_HAS_SUBNET 4
struct
frec
{
struct
frec
{
union
mysockaddr
source
;
union
mysockaddr
source
;
...
@@ -802,6 +804,8 @@ extern struct daemon {
...
@@ -802,6 +804,8 @@ extern struct daemon {
struct
auth_zone
*
auth_zones
;
struct
auth_zone
*
auth_zones
;
struct
interface_name
*
int_names
;
struct
interface_name
*
int_names
;
char
*
mxtarget
;
char
*
mxtarget
;
int
addr4_netmask
;
int
addr6_netmask
;
char
*
lease_file
;
char
*
lease_file
;
char
*
username
,
*
groupname
,
*
scriptuser
;
char
*
username
,
*
groupname
,
*
scriptuser
;
char
*
luascript
;
char
*
luascript
;
...
@@ -962,6 +966,8 @@ unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
...
@@ -962,6 +966,8 @@ 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_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
);
size_t
add_source_addr
(
struct
dns_header
*
header
,
size_t
plen
,
char
*
limit
,
union
mysockaddr
*
source
);
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
,
...);
...
...
src/forward.c
View file @
ed4c0767
...
@@ -284,6 +284,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
...
@@ -284,6 +284,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
forward
->
fd
=
udpfd
;
forward
->
fd
=
udpfd
;
forward
->
crc
=
crc
;
forward
->
crc
=
crc
;
forward
->
forwardall
=
0
;
forward
->
forwardall
=
0
;
forward
->
flags
=
0
;
if
(
norebind
)
if
(
norebind
)
forward
->
flags
|=
FREC_NOREBIND
;
forward
->
flags
|=
FREC_NOREBIND
;
if
(
header
->
hb4
&
HB4_CD
)
if
(
header
->
hb4
&
HB4_CD
)
...
@@ -331,6 +332,16 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
...
@@ -331,6 +332,16 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if
(
option_bool
(
OPT_ADD_MAC
))
if
(
option_bool
(
OPT_ADD_MAC
))
plen
=
add_mac
(
header
,
plen
,
((
char
*
)
header
)
+
PACKETSZ
,
&
forward
->
source
);
plen
=
add_mac
(
header
,
plen
,
((
char
*
)
header
)
+
PACKETSZ
,
&
forward
->
source
);
if
(
option_bool
(
OPT_CLIENT_SUBNET
))
{
size_t
new
=
add_source_addr
(
header
,
plen
,
((
char
*
)
header
)
+
PACKETSZ
,
&
forward
->
source
);
if
(
new
!=
plen
)
{
plen
=
new
;
forward
->
flags
|=
FREC_HAS_SUBNET
;
}
}
while
(
1
)
while
(
1
)
{
{
/* only send to servers dealing with our domain.
/* only send to servers dealing with our domain.
...
@@ -435,8 +446,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
...
@@ -435,8 +446,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
return
0
;
return
0
;
}
}
static
size_t
process_reply
(
struct
dns_header
*
header
,
time_t
now
,
static
size_t
process_reply
(
struct
dns_header
*
header
,
time_t
now
,
struct
server
*
server
,
size_t
n
,
int
check_rebind
,
struct
server
*
server
,
size_t
n
,
int
check_rebind
,
int
checking_disabled
)
int
checking_disabled
,
int
check_subnet
,
union
mysockaddr
*
query_source
)
{
{
unsigned
char
*
pheader
,
*
sizep
;
unsigned
char
*
pheader
,
*
sizep
;
char
**
sets
=
0
;
char
**
sets
=
0
;
...
@@ -465,19 +476,29 @@ static size_t process_reply(struct dns_header *header, time_t now,
...
@@ -465,19 +476,29 @@ static size_t process_reply(struct dns_header *header, time_t now,
than we allow, trim it so that we don't get overlarge
than we allow, trim it so that we don't get overlarge
requests for the client. We can't do this for signed packets. */
requests for the client. We can't do this for signed packets. */
if
((
pheader
=
find_pseudoheader
(
header
,
n
,
&
plen
,
&
sizep
,
&
is_sign
))
&&
!
is_sign
)
if
((
pheader
=
find_pseudoheader
(
header
,
n
,
&
plen
,
&
sizep
,
&
is_sign
)))
{
{
unsigned
short
udpsz
;
if
(
!
is_sign
)
unsigned
char
*
psave
=
sizep
;
{
unsigned
short
udpsz
;
unsigned
char
*
psave
=
sizep
;
GETSHORT
(
udpsz
,
sizep
);
if
(
udpsz
>
daemon
->
edns_pktsz
)
PUTSHORT
(
daemon
->
edns_pktsz
,
psave
);
}
GETSHORT
(
udpsz
,
sizep
);
if
(
check_subnet
&&
!
check_source
(
header
,
plen
,
pheader
,
query_source
))
if
(
udpsz
>
daemon
->
edns_pktsz
)
{
PUTSHORT
(
daemon
->
edns_pktsz
,
psave
);
my_syslog
(
LOG_WARNING
,
_
(
"discarding DNS reply: subnet option mismatch"
));
return
0
;
}
}
}
/* RFC 4035 sect 4.6 para 3 */
/* RFC 4035 sect 4.6 para 3 */
if
(
!
is_sign
&&
!
option_bool
(
OPT_DNSSEC
))
if
(
!
is_sign
&&
!
option_bool
(
OPT_DNSSEC
))
header
->
hb4
&=
~
HB4_AD
;
header
->
hb4
&=
~
HB4_AD
;
if
(
OPCODE
(
header
)
!=
QUERY
||
(
RCODE
(
header
)
!=
NOERROR
&&
RCODE
(
header
)
!=
NXDOMAIN
))
if
(
OPCODE
(
header
)
!=
QUERY
||
(
RCODE
(
header
)
!=
NOERROR
&&
RCODE
(
header
)
!=
NXDOMAIN
))
return
n
;
return
n
;
...
@@ -632,7 +653,8 @@ void reply_query(int fd, int family, time_t now)
...
@@ -632,7 +653,8 @@ void reply_query(int fd, int family, time_t now)
if
(
!
option_bool
(
OPT_NO_REBIND
))
if
(
!
option_bool
(
OPT_NO_REBIND
))
check_rebind
=
0
;
check_rebind
=
0
;
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
,
forward
->
flags
&
FREC_CHECKING_DISABLED
,
forward
->
flags
&
FREC_HAS_SUBNET
,
&
forward
->
source
)))
{
{
header
->
id
=
htons
(
forward
->
orig_id
);
header
->
id
=
htons
(
forward
->
orig_id
);
header
->
hb4
|=
HB4_RA
;
/* recursion if available */
header
->
hb4
|=
HB4_RA
;
/* recursion if available */
...
@@ -876,7 +898,7 @@ unsigned char *tcp_request(int confd, time_t now,
...
@@ -876,7 +898,7 @@ unsigned char *tcp_request(int confd, time_t now,
{
{
size_t
size
=
0
;
size_t
size
=
0
;
int
norebind
=
0
;
int
norebind
=
0
;
int
checking_disabled
;
int
checking_disabled
,
check_subnet
;
size_t
m
;
size_t
m
;
unsigned
short
qtype
;
unsigned
short
qtype
;
unsigned
int
gotname
;
unsigned
int
gotname
;
...
@@ -906,6 +928,8 @@ unsigned char *tcp_request(int confd, time_t now,
...
@@ -906,6 +928,8 @@ unsigned char *tcp_request(int confd, time_t now,
if
(
size
<
(
int
)
sizeof
(
struct
dns_header
))
if
(
size
<
(
int
)
sizeof
(
struct
dns_header
))
continue
;
continue
;
check_subnet
=
0
;
/* save state of "cd" flag in query */
/* save state of "cd" flag in query */
checking_disabled
=
header
->
hb4
&
HB4_CD
;
checking_disabled
=
header
->
hb4
&
HB4_CD
;
...
@@ -955,7 +979,17 @@ unsigned char *tcp_request(int confd, time_t now,
...
@@ -955,7 +979,17 @@ unsigned char *tcp_request(int confd, time_t now,
if
(
option_bool
(
OPT_ADD_MAC
))
if
(
option_bool
(
OPT_ADD_MAC
))
size
=
add_mac
(
header
,
size
,
((
char
*
)
header
)
+
65536
,
&
peer_addr
);
size
=
add_mac
(
header
,
size
,
((
char
*
)
header
)
+
65536
,
&
peer_addr
);
if
(
option_bool
(
OPT_CLIENT_SUBNET
))
{
size_t
new
=
add_source_addr
(
header
,
size
,
((
char
*
)
header
)
+
65536
,
&
peer_addr
);
if
(
size
!=
new
)
{
size
=
new
;
check_subnet
=
1
;
}
}
if
(
gotname
)
if
(
gotname
)
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
);
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
);
...
@@ -1056,7 +1090,8 @@ unsigned char *tcp_request(int confd, time_t now,
...
@@ -1056,7 +1090,8 @@ unsigned char *tcp_request(int confd, time_t now,
sending replies containing questions and bogus answers. */
sending replies containing questions and bogus answers. */
if
(
crc
==
questions_crc
(
header
,
(
unsigned
int
)
m
,
daemon
->
namebuff
))
if
(
crc
==
questions_crc
(
header
,
(
unsigned
int
)
m
,
daemon
->
namebuff
))
m
=
process_reply
(
header
,
now
,
last_server
,
(
unsigned
int
)
m
,
m
=
process_reply
(
header
,
now
,
last_server
,
(
unsigned
int
)
m
,
option_bool
(
OPT_NO_REBIND
)
&&
!
norebind
,
checking_disabled
);
option_bool
(
OPT_NO_REBIND
)
&&
!
norebind
,
checking_disabled
,
check_subnet
,
&
peer_addr
);
break
;
break
;
}
}
...
...
src/option.c
View file @
ed4c0767
...
@@ -134,6 +134,7 @@ struct myoption {
...
@@ -134,6 +134,7 @@ struct myoption {
#endif
#endif
#define LOPT_FAST_RA 322
#define LOPT_FAST_RA 322
#define LOPT_RELAY 323
#define LOPT_RELAY 323
#define LOPT_ADD_SBNET 324
#ifdef HAVE_GETOPT_LONG
#ifdef HAVE_GETOPT_LONG
static
const
struct
option
opts
[]
=
static
const
struct
option
opts
[]
=
...
@@ -251,6 +252,7 @@ static const struct myoption opts[] =
...
@@ -251,6 +252,7 @@ static const struct myoption opts[] =
{
"dhcp-generate-names"
,
2
,
0
,
LOPT_GEN_NAMES
},
{
"dhcp-generate-names"
,
2
,
0
,
LOPT_GEN_NAMES
},
{
"rebind-localhost-ok"
,
0
,
0
,
LOPT_LOC_REBND
},
{
"rebind-localhost-ok"
,
0
,
0
,
LOPT_LOC_REBND
},
{
"add-mac"
,
0
,
0
,
LOPT_ADD_MAC
},
{
"add-mac"
,
0
,
0
,
LOPT_ADD_MAC
},
{
"add-subnet"
,
2
,
0
,
LOPT_ADD_SBNET
},
{
"proxy-dnssec"
,
0
,
0
,
LOPT_DNSSEC
},
{
"proxy-dnssec"
,
0
,
0
,
LOPT_DNSSEC
},
{
"dhcp-sequential-ip"
,
0
,
0
,
LOPT_INCR_ADDR
},
{
"dhcp-sequential-ip"
,
0
,
0
,
LOPT_INCR_ADDR
},
{
"conntrack"
,
0
,
0
,
LOPT_CONNTRACK
},
{
"conntrack"
,
0
,
0
,
LOPT_CONNTRACK
},
...
@@ -397,6 +399,7 @@ static struct {
...
@@ -397,6 +399,7 @@ static struct {
{
LOPT_PXE_SERV
,
ARG_DUP
,
"<service>"
,
gettext_noop
(
"Boot service for PXE menu."
),
NULL
},
{
LOPT_PXE_SERV
,
ARG_DUP
,
"<service>"
,
gettext_noop
(
"Boot service for PXE menu."
),
NULL
},
{
LOPT_TEST
,
0
,
NULL
,
gettext_noop
(
"Check configuration syntax."
),
NULL
},
{
LOPT_TEST
,
0
,
NULL
,
gettext_noop
(
"Check configuration syntax."
),
NULL
},
{
LOPT_ADD_MAC
,
OPT_ADD_MAC
,
NULL
,
gettext_noop
(
"Add requestor's MAC address to forwarded DNS queries."
),
NULL
},
{
LOPT_ADD_MAC
,
OPT_ADD_MAC
,
NULL
,
gettext_noop
(
"Add requestor's MAC address to forwarded DNS queries."
),
NULL
},
{
LOPT_ADD_SBNET
,
ARG_ONE
,
"<v4 pref>[,<v6 pref>]"
,
gettext_noop
(
"Add requestor's IP subnet to forwarded DNS queries."
),
NULL
},
{
LOPT_DNSSEC
,
OPT_DNSSEC
,
NULL
,
gettext_noop
(
"Proxy DNSSEC validation results from upstream nameservers."
),
NULL
},
{
LOPT_DNSSEC
,
OPT_DNSSEC
,
NULL
,
gettext_noop
(
"Proxy DNSSEC validation results from upstream nameservers."
),
NULL
},
{
LOPT_INCR_ADDR
,
OPT_CONSEC_ADDR
,
NULL
,
gettext_noop
(
"Attempt to allocate sequential IP addresses to DHCP clients."
),
NULL
},
{
LOPT_INCR_ADDR
,
OPT_CONSEC_ADDR
,
NULL
,
gettext_noop
(
"Attempt to allocate sequential IP addresses to DHCP clients."
),
NULL
},
{
LOPT_CONNTRACK
,
OPT_CONNTRACK
,
NULL
,
gettext_noop
(
"Copy connection-track mark from queries to upstream connections."
),
NULL
},
{
LOPT_CONNTRACK
,
OPT_CONNTRACK
,
NULL
,
gettext_noop
(
"Copy connection-track mark from queries to upstream connections."
),
NULL
},
...
@@ -1424,6 +1427,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
...
@@ -1424,6 +1427,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
break
;
break
;
}
}
case
LOPT_ADD_SBNET
:
/* --add-subnet */
set_option_bool
(
OPT_CLIENT_SUBNET
);
if
(
arg
)
{
comma
=
split
(
arg
);
if
(
!
atoi_check
(
arg
,
&
daemon
->
addr4_netmask
)
||
(
comma
&&
!
atoi_check
(
comma
,
&
daemon
->
addr6_netmask
)))
ret_err
(
gen_err
);
}
break
;
case
'1'
:
/* --enable-dbus */
case
'1'
:
/* --enable-dbus */
set_option_bool
(
OPT_DBUS
);
set_option_bool
(
OPT_DBUS
);
if
(
arg
)
if
(
arg
)
...
...
src/rfc1035.c
View file @
ed4c0767
...
@@ -513,46 +513,30 @@ struct macparm {
...
@@ -513,46 +513,30 @@ struct macparm {
size_t
plen
;
size_t
plen
;
union
mysockaddr
*
l3
;
union
mysockaddr
*
l3
;
};
};
static
int
filter_mac
(
int
family
,
char
*
addrp
,
char
*
mac
,
size_t
maclen
,
void
*
parmv
)
{
struct
macparm
*
parm
=
parmv
;
int
match
=
0
;
unsigned
short
rdlen
;
struct
dns_header
*
header
=
parm
->
header
;
unsigned
char
*
lenp
,
*
datap
,
*
p
;
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
)
static
size_t
add_pseudoheader
(
struct
dns_header
*
header
,
size_t
plen
,
unsigned
char
*
limit
,
return
1
;
/* continue */
int
optno
,
unsigned
char
*
opt
,
size_t
optlen
)
{
unsigned
char
*
lenp
,
*
datap
,
*
p
;
int
rdlen
;
if
(
ntohs
(
header
->
arcount
)
==
0
)
if
(
ntohs
(
header
->
arcount
)
==
0
)
{
{
/* We are adding the pseudoheader */
/* We are adding the pseudoheader */
if
(
!
(
p
=
skip_questions
(
header
,
p
arm
->
p
len
))
||
if
(
!
(
p
=
skip_questions
(
header
,
plen
))
||
!
(
p
=
skip_section
(
p
,
!
(
p
=
skip_section
(
p
,
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
),
ntohs
(
header
->
ancount
)
+
ntohs
(
header
->
nscount
),
header
,
p
arm
->
p
len
)))
header
,
plen
)))
return
0
;
return
plen
;
*
p
++
=
0
;
/* empty name */
*
p
++
=
0
;
/* empty name */
PUTSHORT
(
T_OPT
,
p
);
PUTSHORT
(
T_OPT
,
p
);
PUTSHORT
(
PACKETSZ
,
p
);
/* max packet length - is 512 suitable default for non-EDNS0 resolvers?
*/
PUTSHORT
(
daemon
->
edns_pktsz
,
p
);
/* max packet length
*/
PUTLONG
(
0
,
p
);
/* extended RCODE */
PUTLONG
(
0
,
p
);
/* extended RCODE */
lenp
=
p
;
lenp
=
p
;
PUTSHORT
(
0
,
p
);
/* RDLEN */
PUTSHORT
(
0
,
p
);
/* RDLEN */
rdlen
=
0
;
rdlen
=
0
;
if
(((
ssize_t
)
maclen
)
>
(
parm
->
limit
-
(
p
+
4
)))
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
0
;
/* Too big */
return
plen
;
/* Too big */
header
->
arcount
=
htons
(
1
);
header
->
arcount
=
htons
(
1
);
datap
=
p
;
datap
=
p
;
}
}
...
@@ -562,17 +546,17 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
...
@@ -562,17 +546,17 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
unsigned
short
code
,
len
;
unsigned
short
code
,
len
;
if
(
ntohs
(
header
->
arcount
)
!=
1
||
if
(
ntohs
(
header
->
arcount
)
!=
1
||
!
(
p
=
find_pseudoheader
(
header
,
p
arm
->
p
len
,
NULL
,
NULL
,
&
is_sign
))
||
!
(
p
=
find_pseudoheader
(
header
,
plen
,
NULL
,
NULL
,
&
is_sign
))
||
is_sign
||
is_sign
||
(
!
(
p
=
skip_name
(
p
,
header
,
p
arm
->
p
len
,
10
))))
(
!
(
p
=
skip_name
(
p
,
header
,
plen
,
10
))))
return
0
;
return
plen
;
p
+=
8
;
/* skip UDP length and RCODE */
p
+=
8
;
/* skip UDP length and RCODE */
lenp
=
p
;
lenp
=
p
;
GETSHORT
(
rdlen
,
p
);
GETSHORT
(
rdlen
,
p
);
if
(
!
CHECK_LEN
(
header
,
p
,
p
arm
->
p
len
,
rdlen
))
if
(
!
CHECK_LEN
(
header
,
p
,
plen
,
rdlen
))
return
0
;
/* bad packet */
return
plen
;
/* bad packet */
datap
=
p
;
datap
=
p
;
/* check if option already there */
/* check if option already there */
...
@@ -580,27 +564,49 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
...
@@ -580,27 +564,49 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
{
{
GETSHORT
(
code
,
p
);
GETSHORT
(
code
,
p
);
GETSHORT
(
len
,
p
);
GETSHORT
(
len
,
p
);
if
(
code
==
EDNS0_OPTION_MAC
)
if
(
code
==
optno
)
return
0
;
return
plen
;
p
+=
len
;
p
+=
len
;
}
}
if
(((
ssize_t
)
maclen
)
>
(
parm
->
limit
-
(
p
+
4
)))
if
(((
ssize_t
)
optlen
)
>
(
limit
-
(
p
+
4
)))
return
0
;
/* Too big */
return
plen
;
/* Too big */
}
}
PUTSHORT
(
EDNS0_OPTION_MAC
,
p
);
PUTSHORT
(
optno
,
p
);
PUTSHORT
(
mac
len
,
p
);
PUTSHORT
(
opt
len
,
p
);
memcpy
(
p
,
mac
,
mac
len
);
memcpy
(
p
,
opt
,
opt
len
);
p
+=
mac
len
;
p
+=
opt
len
;
PUTSHORT
(
p
-
datap
,
lenp
);
PUTSHORT
(
p
-
datap
,
lenp
);
parm
->
plen
=
p
-
(
unsigned
char
*
)
header
;
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
,
EDNS0_OPTION_MAC
,
(
unsigned
char
*
)
mac
,
maclen
);
return
0
;
/* done */
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
;
struct
macparm
parm
;
...
@@ -621,7 +627,102 @@ size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysock
...
@@ -621,7 +627,102 @@ size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysock
return
parm
.
plen
;
return
parm
.
plen
;
}
}
struct
subnet_opt
{
u16
family
;
u8
source_netmask
,
scope_netmask
;
#ifdef HAVE_IPV6
u8
addr
[
IN6ADDRSZ
];
#else
u8
addr
[
INADDRSZ
];
#endif
};
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
;
if
(
source
->
sa
.
sa_family
==
AF_INET
)
{
opt
->
family
=
htons
(
1
);
opt
->
source_netmask
=
daemon
->
addr4_netmask
;
addrp
=
&
source
->
in
.
sin_addr
;
}
#ifdef HAVE_IPV6
else
{
opt
->
family
=
htons
(
2
);
opt
->
source_netmask
=
daemon
->
addr6_netmask
;
addrp
=
&
source
->
in6
.
sin6_addr
;
}
#endif
opt
->
scope_netmask
=
0
;
len
=
0
;
if
(
opt
->
source_netmask
!=
0
)
{
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
,
EDNS0_OPTION_CLIENT_SUBNET
,
(
unsigned
char
*
)
&
opt
,
len
);
}
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? */
static
int
private_net
(
struct
in_addr
addr
,
int
ban_localhost
)
static
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