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
352d236d
Commit
352d236d
authored
Feb 04, 2015
by
Chen Wei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
--server mod build successfully
parent
c2a3d340
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
294 additions
and
248 deletions
+294
-248
src/dict.c
src/dict.c
+60
-11
src/dnsmasq.c
src/dnsmasq.c
+3
-0
src/dnsmasq.h
src/dnsmasq.h
+13
-2
src/forward.c
src/forward.c
+115
-169
src/option.c
src/option.c
+103
-66
No files found.
src/dict.c
View file @
352d236d
...
...
@@ -25,8 +25,10 @@
#define FNV_32_PRIME ((uint32_t)0x01000193)
#define max(A, B) ((A) > (B) ? (A) : (B))
static
char
buf
[
MAXDNAME
];
/* prototypes */
static
struct
dict_node
*
add_or_
replace
_dictnode
(
struct
dict_node
*
node
,
char
*
label
);
static
struct
dict_node
*
add_or_
lookup
_dictnode
(
struct
dict_node
*
node
,
char
*
label
);
static
struct
dict_node
*
lookup_dictnode
(
struct
dict_node
*
node
,
char
*
label
);
static
void
add_dicttree
(
struct
dict_node
*
node
,
struct
dict_node
*
sub
);
static
void
upsize_dicttree
(
struct
dict_node
*
np
);
...
...
@@ -205,7 +207,7 @@ static void add_dicttree (struct dict_node *node, struct dict_node *sub)
/* add a new subnode to node, or update the attr of the subnode with same
* label
* return the subnode */
static
struct
dict_node
*
add_or_
replace
_dictnode
(
struct
dict_node
*
node
,
static
struct
dict_node
*
add_or_
lookup
_dictnode
(
struct
dict_node
*
node
,
char
*
label
)
{
struct
dict_node
*
np
;
...
...
@@ -254,13 +256,11 @@ static struct dict_node *lookup_dictnode (struct dict_node *node, char *label)
return
NULL
;
}
/* look up the whole domain pattern by step over DNS name hierarchy top down.
* for example, if the pattern is cn.debian.org, the lookup will start with
* org, then debian, then cn */
struct
dict_node
*
match_domain
_ipsets
(
struct
dict_node
*
root
,
char
*
domain
)
struct
dict_node
*
match_domain
(
struct
dict_node
*
root
,
char
*
domain
)
{
char
buf
[
MAXDNAME
];
char
*
labels
[
MAXLABELS
];
int
i
,
label_num
;
int
len
=
strlen
(
domain
);
...
...
@@ -307,8 +307,8 @@ struct dict_node * match_domain_ipsets (struct dict_node *root, char *domain)
res
=
node
;
}
if
(
res
==
NULL
)
return
NULL
;
if
(
res
==
NULL
)
return
NULL
;
return
res
;
}
...
...
@@ -318,7 +318,6 @@ struct dict_node * match_domain_ipsets (struct dict_node *root, char *domain)
* com, then google, then cache */
struct
dict_node
*
lookup_domain
(
struct
dict_node
*
root
,
char
*
domain
)
{
char
buf
[
MAXDNAME
];
char
*
labels
[
MAXLABELS
];
int
i
,
label_num
;
int
len
=
strlen
(
domain
);
...
...
@@ -354,9 +353,8 @@ struct dict_node * lookup_domain (struct dict_node *root, char *domain)
/* add a domain pattern in the form of google.com to root
* return the node with lowest hierarchy */
struct
dict_node
*
add_domain
(
struct
dict_node
*
root
,
char
*
domain
)
struct
dict_node
*
add_
or_lookup_
domain
(
struct
dict_node
*
root
,
char
*
domain
)
{
char
buf
[
MAXDNAME
];
char
*
labels
[
MAXLABELS
];
int
i
,
label_num
;
int
len
=
strlen
(
domain
);
...
...
@@ -383,7 +381,7 @@ struct dict_node *add_domain (struct dict_node *root, char *domain)
node
=
root
;
for
(
i
=
label_num
-
1
;
i
>=
0
;
i
--
)
{
node
=
add_or_
replace
_dictnode
(
node
,
labels
[
i
]);
node
=
add_or_
lookup
_dictnode
(
node
,
labels
[
i
]);
}
return
node
;
...
...
@@ -416,3 +414,54 @@ void free_dicttree (struct dict_node *node)
free
(
node
);
}
/* temp area * */
/* only compare addr, source_addr, interface, and flags */
static
inline
int
is_same_server
(
struct
server
*
s1
,
struct
server
*
s2
)
{
if
(
memcmp
(
&
s1
->
addr
,
&
s2
->
addr
,
sizeof
(
union
mysockaddr
))
!=
0
)
return
-
1
;
if
(
strncmp
(
s1
->
interface
,
s2
->
interface
,
IF_NAMESIZE
+
1
)
!=
0
)
return
-
1
;
if
(
s1
->
flags
!=
s2
->
flags
)
return
-
1
;
return
0
;
}
/* duplicate a struct server, but only copy addr, source_addr, interfaces, and
* flags
* return the allocated pointer */
static
inline
struct
server
*
serverdup
(
struct
server
*
src
)
{
struct
server
*
dst
;
dst
=
safe_malloc
(
sizeof
(
struct
server
));
memcpy
(
dst
,
src
,
sizeof
(
struct
server
));
return
dst
;
}
struct
server
*
lookup_or_install_new_server
(
struct
server
*
serv
)
{
struct
server
*
res
;
res
=
NULL
;
for
(
res
=
daemon
->
servers
;
res
!=
NULL
;
res
=
res
->
next
)
{
if
(
is_same_server
(
res
,
serv
))
break
;
}
if
(
res
==
NULL
)
{
res
=
serverdup
(
serv
);
res
->
next
=
daemon
->
servers
;
daemon
->
servers
=
res
;
}
return
res
;
}
src/dnsmasq.c
View file @
352d236d
...
...
@@ -254,6 +254,9 @@ int main (int argc, char **argv)
ipset_init
();
#endif
if
(
daemon
->
dh_special_domains
==
NULL
)
daemon
->
dh_special_domains
=
new_dictnode
(
NULL
,
0
);
#if defined(HAVE_LINUX_NETWORK)
netlink_init
();
#elif defined(HAVE_BSD_NETWORK)
...
...
src/dnsmasq.h
View file @
352d236d
...
...
@@ -534,6 +534,13 @@ struct dict_node {
struct
dict_node
**
sub
;
};
struct
special_domain
{
struct
server
*
server
;
union
mysockaddr
addr
;
int
domain_flags
;
};
struct
ipsets_names
{
char
**
sets
;
/* ipsets names end with NULL ptr */
int
count
;
...
...
@@ -965,8 +972,11 @@ extern struct daemon {
struct
bogus_addr
*
bogus_addr
,
*
ignore_addr
;
struct
server
*
servers
;
struct
ipsets
*
ipsets
;
struct
dict_node
*
dh_ipsets
;
struct
dict_node
*
dh_ipsets_names
;
struct
dict_node
*
dh_special_domains
;
int
log_fac
;
/* log facility */
char
*
log_file
;
/* optional log file */
int
max_logs
;
/* queue limit */
...
...
@@ -1392,8 +1402,9 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags,
/* dict.c */
struct
dict_node
*
new_dictnode
(
char
*
label
,
int
len
);
struct
dict_node
*
lookup_domain
(
struct
dict_node
*
root
,
char
*
domain
);
struct
dict_node
*
match_domain_ipsets
(
struct
dict_node
*
root
,
char
*
domain
);
struct
dict_node
*
add_domain
(
struct
dict_node
*
root
,
char
*
domain
);
struct
dict_node
*
match_domain
(
struct
dict_node
*
root
,
char
*
domain
);
struct
dict_node
*
add_or_lookup_domain
(
struct
dict_node
*
root
,
char
*
domain
);
struct
server
*
lookup_or_install_new_server
(
struct
server
*
serv
);
void
free_dicttree
(
struct
dict_node
*
node
);
/* helper.c */
...
...
src/forward.c
View file @
352d236d
...
...
@@ -120,102 +120,63 @@ int send_from(int fd, int nowild, char *packet, size_t len,
}
static
unsigned
int
search_servers
(
time_t
now
,
struct
all_addr
**
addrpp
,
unsigned
int
qtype
,
char
*
qdomain
,
int
*
type
,
char
**
domain
,
int
*
norebind
)
unsigned
int
qtype
,
char
*
qdomain
,
int
*
type
,
char
**
domain
,
int
*
norebind
,
struct
server
**
fwdserv
)
{
/* If the query ends in the domain in one of our servers, set
domain to point to that name. We find the largest match to allow both
domain.org and sub.domain.org to exist. */
unsigned
int
namelen
=
strlen
(
qdomain
);
unsigned
int
matchlen
=
0
;
struct
server
*
serv
;
unsigned
int
flags
=
0
;
for
(
serv
=
daemon
->
servers
;
serv
;
serv
=
serv
->
next
)
/* domain matches take priority over NODOTS matches */
if
((
serv
->
flags
&
SERV_FOR_NODOTS
)
&&
*
type
!=
SERV_HAS_DOMAIN
&&
!
strchr
(
qdomain
,
'.'
)
&&
namelen
!=
0
)
unsigned
int
namelen
=
strlen
(
qdomain
);
struct
server
*
serv
;
unsigned
int
flags
=
0
;
unsigned
int
sflag
;
struct
dict_node
*
np
;
struct
special_domain
*
obj
;
np
=
match_domain
(
daemon
->
dh_special_domains
,
qdomain
);
if
(
np
!=
NULL
)
{
unsigned
int
sflag
=
serv
->
addr
.
sa
.
sa_family
==
AF_INET
?
F_IPV4
:
F_IPV6
;
*
type
=
SERV_FOR_NODOTS
;
if
(
serv
->
flags
&
SERV_NO_ADDR
)
flags
=
F_NXDOMAIN
;
else
if
(
serv
->
flags
&
SERV_LITERAL_ADDRESS
)
{
if
(
sflag
&
qtype
)
{
flags
=
sflag
;
if
(
serv
->
addr
.
sa
.
sa_family
==
AF_INET
)
*
addrpp
=
(
struct
all_addr
*
)
&
serv
->
addr
.
in
.
sin_addr
;
obj
=
(
struct
special_domain
*
)
np
->
obj
;
serv
=
obj
->
server
;
*
type
=
serv
->
flags
&
(
SERV_HAS_DOMAIN
|
SERV_USE_RESOLV
|
SERV_NO_REBIND
);
if
(
obj
->
domain_flags
&
SERV_NO_REBIND
)
*
norebind
=
1
;
// no server, domain is local only
if
(
obj
->
domain_flags
&
SERV_NO_ADDR
)
{
flags
=
F_NXDOMAIN
;
}
else
if
(
obj
->
domain_flags
==
SERV_LITERAL_ADDRESS
)
{
// --address and AF matches
sflag
=
obj
->
addr
.
sa
.
sa_family
==
AF_INET
?
F_IPV4
:
F_IPV6
;
if
(
sflag
&
qtype
)
{
flags
=
sflag
;
if
(
serv
->
addr
.
sa
.
sa_family
==
AF_INET
)
*
addrpp
=
(
struct
all_addr
*
)
&
serv
->
addr
.
in
.
sin_addr
;
#ifdef HAVE_IPV6
else
*
addrpp
=
(
struct
all_addr
*
)
&
serv
->
addr
.
in6
.
sin6_addr
;
#endif
}
else
if
(
!
flags
||
(
flags
&
F_NXDOMAIN
))
flags
=
F_NOERR
;
}
else
*
addrpp
=
(
struct
all_addr
*
)
&
serv
->
addr
.
in6
.
sin6_addr
;
#endif
}
}
else
{
*
fwdserv
=
obj
->
server
;
flags
=
0
;
}
}
//TODO add fast hash lookup
else
if
(
serv
->
flags
&
SERV_HAS_DOMAIN
)
else
{
unsigned
int
domainlen
=
strlen
(
serv
->
domain
);
char
*
matchstart
=
qdomain
+
namelen
-
domainlen
;
if
(
namelen
>=
domainlen
&&
hostname_isequal
(
matchstart
,
serv
->
domain
)
&&
(
domainlen
==
0
||
namelen
==
domainlen
||
*
(
matchstart
-
1
)
==
'.'
))
{
if
(
serv
->
flags
&
SERV_NO_REBIND
)
*
norebind
=
1
;
else
{
unsigned
int
sflag
=
serv
->
addr
.
sa
.
sa_family
==
AF_INET
?
F_IPV4
:
F_IPV6
;
/* implement priority rules for --address and --server for same domain.
--address wins if the address is for the correct AF
--server wins otherwise. */
if
(
domainlen
!=
0
&&
domainlen
==
matchlen
)
{
if
((
serv
->
flags
&
SERV_LITERAL_ADDRESS
))
{
if
(
!
(
sflag
&
qtype
)
&&
flags
==
0
)
continue
;
}
else
{
if
(
flags
&
(
F_IPV4
|
F_IPV6
))
continue
;
}
}
if
(
domainlen
>=
matchlen
)
{
*
type
=
serv
->
flags
&
(
SERV_HAS_DOMAIN
|
SERV_USE_RESOLV
|
SERV_NO_REBIND
);
*
domain
=
serv
->
domain
;
matchlen
=
domainlen
;
if
(
serv
->
flags
&
SERV_NO_ADDR
)
flags
=
F_NXDOMAIN
;
else
if
(
serv
->
flags
&
SERV_LITERAL_ADDRESS
)
{
if
(
sflag
&
qtype
)
{
flags
=
sflag
;
if
(
serv
->
addr
.
sa
.
sa_family
==
AF_INET
)
*
addrpp
=
(
struct
all_addr
*
)
&
serv
->
addr
.
in
.
sin_addr
;
#ifdef HAVE_IPV6
else
*
addrpp
=
(
struct
all_addr
*
)
&
serv
->
addr
.
in6
.
sin6_addr
;
#endif
}
else
if
(
!
flags
||
(
flags
&
F_NXDOMAIN
))
flags
=
F_NOERR
;
}
else
flags
=
0
;
}
}
}
*
type
=
0
;
// use normal server
*
fwdserv
=
NULL
;
}
/* have go through all servers in chain, now let's see what flag survive */
if
(
flags
==
0
&&
!
(
qtype
&
F_QUERY
)
&&
option_bool
(
OPT_NODOTS_LOCAL
)
&&
!
strchr
(
qdomain
,
'.'
)
&&
namelen
!=
0
)
/* don't forward A or AAAA queries for simple names, except the empty name */
...
...
@@ -241,6 +202,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
return
flags
;
}
//forward_query(-1, NULL, NULL, 0, header, nn, now, forward, 0, 0);
static
int
forward_query
(
int
udpfd
,
union
mysockaddr
*
udpaddr
,
struct
all_addr
*
dst_addr
,
unsigned
int
dst_iface
,
struct
dns_header
*
header
,
size_t
plen
,
time_t
now
,
...
...
@@ -251,6 +213,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
struct
all_addr
*
addrp
=
NULL
;
unsigned
int
flags
=
0
;
struct
server
*
start
=
NULL
;
struct
server
*
fwdserv
=
NULL
;
#ifdef HAVE_DNSSEC
void
*
hash
=
hash_questions
(
header
,
plen
,
daemon
->
namebuff
);
#else
...
...
@@ -322,7 +285,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
else
{
if
(
gotname
)
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
);
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
,
&
fwdserv
);
if
(
!
flags
&&
!
(
forward
=
get_new_frec
(
now
,
NULL
,
0
)))
/* table full - server failure. */
...
...
@@ -387,7 +350,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if
(
!
flags
&&
forward
)
{
struct
server
*
firstsentto
=
start
;
int
forwarded
=
0
;
/* If a query is retried, use the log_id for the retry when logging the answer. */
...
...
@@ -423,92 +385,75 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
#endif
while
(
1
)
{
/* only send to servers dealing with our domain.
domain may be NULL, in which case server->domain
must be NULL also. */
if
(
type
==
(
start
->
flags
&
SERV_TYPE
)
&&
(
type
!=
SERV_HAS_DOMAIN
||
hostname_isequal
(
domain
,
start
->
domain
))
&&
!
(
start
->
flags
&
(
SERV_LITERAL_ADDRESS
|
SERV_LOOP
)))
{
int
fd
;
// we have the server for our domain by lookup daemon->dh_special_domains
int
fd
;
/* find server socket to use, may need to get random one. */
if
(
start
->
sfd
)
fd
=
start
->
sfd
->
fd
;
else
{
/* find server socket to use, may need to get random one. */
if
(
fwdserv
->
sfd
)
fd
=
fwdserv
->
sfd
->
fd
;
else
{
#ifdef HAVE_IPV6
if
(
start
->
addr
.
sa
.
sa_family
==
AF_INET6
)
{
if
(
!
forward
->
rfd6
&&
!
(
forward
->
rfd6
=
allocate_rfd
(
AF_INET6
)))
break
;
daemon
->
rfd_save
=
forward
->
rfd6
;
fd
=
forward
->
rfd6
->
fd
;
}
else
if
(
fwdserv
->
addr
.
sa
.
sa_family
==
AF_INET6
)
{
if
(
forward
->
rfd6
==
NULL
)
forward
->
rfd6
=
allocate_rfd
(
AF_INET6
);
daemon
->
rfd_save
=
forward
->
rfd6
;
fd
=
forward
->
rfd6
->
fd
;
}
else
#endif
{
if
(
!
forward
->
rfd4
&&
!
(
forward
->
rfd4
=
allocate_rfd
(
AF_INET
)))
break
;
daemon
->
rfd_save
=
forward
->
rfd4
;
fd
=
forward
->
rfd4
->
fd
;
}
{
if
(
forward
->
rfd4
==
NULL
)
forward
->
rfd4
=
allocate_rfd
(
AF_INET
);
daemon
->
rfd_save
=
forward
->
rfd4
;
fd
=
forward
->
rfd4
->
fd
;
}
#ifdef HAVE_CONNTRACK
/* Copy connection mark of incoming query to outgoing connection. */
if
(
option_bool
(
OPT_CONNTRACK
))
{
unsigned
int
mark
;
if
(
get_incoming_mark
(
&
forward
->
source
,
&
forward
->
dest
,
0
,
&
mark
))
setsockopt
(
fd
,
SOL_SOCKET
,
SO_MARK
,
&
mark
,
sizeof
(
unsigned
int
));
}
/* Copy connection mark of incoming query to outgoing connection. */
if
(
option_bool
(
OPT_CONNTRACK
))
{
unsigned
int
mark
;
if
(
get_incoming_mark
(
&
forward
->
source
,
&
forward
->
dest
,
0
,
&
mark
))
setsockopt
(
fd
,
SOL_SOCKET
,
SO_MARK
,
&
mark
,
sizeof
(
unsigned
int
));
}
#endif
}
if
(
sendto
(
fd
,
(
char
*
)
header
,
plen
,
0
,
&
start
->
addr
.
sa
,
sa_len
(
&
start
->
addr
))
==
-
1
)
{
if
(
retry_send
())
continue
;
}
else
{
/* Keep info in case we want to re-send this packet */
daemon
->
srv_save
=
start
;
daemon
->
packet_len
=
plen
;
if
(
!
gotname
)
strcpy
(
daemon
->
namebuff
,
"query"
);
if
(
start
->
addr
.
sa
.
sa_family
==
AF_INET
)
log_query
(
F_SERVER
|
F_IPV4
|
F_FORWARD
,
daemon
->
namebuff
,
(
struct
all_addr
*
)
&
start
->
addr
.
in
.
sin_addr
,
NULL
);
}
if
(
sendto
(
fd
,
(
char
*
)
header
,
plen
,
0
,
&
fwdserv
->
addr
.
sa
,
sa_len
(
&
fwdserv
->
addr
))
==
-
1
)
{
retry_send
();
}
else
{
/* Keep info in case we want to re-send this packet */
daemon
->
srv_save
=
fwdserv
;
daemon
->
packet_len
=
plen
;
if
(
!
gotname
)
strcpy
(
daemon
->
namebuff
,
"query"
);
if
(
fwdserv
->
addr
.
sa
.
sa_family
==
AF_INET
)
log_query
(
F_SERVER
|
F_IPV4
|
F_FORWARD
,
daemon
->
namebuff
,
(
struct
all_addr
*
)
&
fwdserv
->
addr
.
in
.
sin_addr
,
NULL
);
#ifdef HAVE_IPV6
else
log_query
(
F_SERVER
|
F_IPV6
|
F_FORWARD
,
daemon
->
namebuff
,
(
struct
all_addr
*
)
&
start
->
addr
.
in6
.
sin6_addr
,
NULL
);
else
log_query
(
F_SERVER
|
F_IPV6
|
F_FORWARD
,
daemon
->
namebuff
,
(
struct
all_addr
*
)
&
fwdserv
->
addr
.
in6
.
sin6_addr
,
NULL
);
#endif
start
->
queries
++
;
forwarded
=
1
;
forward
->
sentto
=
start
;
if
(
!
forward
->
forwardall
)
break
;
forward
->
forwardall
++
;
}
}
if
(
!
(
start
=
start
->
next
))
start
=
daemon
->
servers
;
if
(
start
==
firstsentto
)
break
;
}
fwdserv
->
queries
++
;
forwarded
=
1
;
forward
->
sentto
=
fwdserv
;
if
(
forward
->
forwardall
)
forward
->
forwardall
++
;
}
if
(
forwarded
)
return
1
;
...
...
@@ -543,7 +488,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
#ifdef HAVE_IPSET
if
(
daemon
->
dh_ipsets
&&
extract_request
(
header
,
n
,
daemon
->
namebuff
,
NULL
))
{
np
=
match_domain
_ipsets
(
daemon
->
dh_ipsets
,
daemon
->
namebuff
);
np
=
match_domain
(
daemon
->
dh_ipsets
,
daemon
->
namebuff
);
if
(
np
!=
NULL
)
{
obj
=
(
struct
ipsets_names
*
)
np
->
obj
;
...
...
@@ -707,6 +652,7 @@ void reply_query(int fd, int family, time_t now)
if
(
!
(
server
->
flags
&
(
SERV_LITERAL_ADDRESS
|
SERV_NO_ADDR
))
&&
sockaddr_isequal
(
&
server
->
addr
,
&
serveraddr
))
break
;
/* TODO server may also come from the list for special domains */
if
(
!
server
)
return
;
...
...
@@ -1677,7 +1623,7 @@ unsigned char *tcp_request(int confd, time_t now,
/* largest field in header is 16-bits, so this is still sufficiently aligned */
struct
dns_header
*
header
=
(
struct
dns_header
*
)
payload
;
u16
*
length
=
(
u16
*
)
packet
;
struct
server
*
last_server
;
struct
server
*
last_server
,
*
fwdserv
;
struct
in_addr
dst_addr_4
;
union
mysockaddr
peer_addr
;
socklen_t
peer_len
=
sizeof
(
union
mysockaddr
);
...
...
@@ -1810,7 +1756,7 @@ unsigned char *tcp_request(int confd, time_t now,
}
if
(
gotname
)
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
);
flags
=
search_servers
(
now
,
&
addrp
,
gotname
,
daemon
->
namebuff
,
&
type
,
&
domain
,
&
norebind
,
&
fwdserv
);
if
(
type
!=
0
||
option_bool
(
OPT_ORDER
)
||
!
daemon
->
last_server
)
last_server
=
daemon
->
servers
;
...
...
src/option.c
View file @
352d236d
...
...
@@ -2210,11 +2210,74 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case
LOPT_NO_REBIND
:
/* --rebind-domain-ok */
//TODO fast hash lookup
{
struct
server
*
serv
,
*
newlist
=
NULL
;
unhide_metas
(
arg
);
char
*
start_addr
;
char
*
err
;
struct
server
newlist
;
struct
dict_node
*
np
;
struct
special_domain
*
obj
;
memset
(
&
newlist
,
0
,
sizeof
(
struct
server
));
#ifdef HAVE_LOOP
newlist
.
uid
=
rand32
();
#endif
if
(
arg
==
NULL
)
break
;
// scan the address part first
// --xxxx=/example.org/ample.com/temple.net/address-of-server
// ^
start_addr
=
NULL
;
if
(
strchr
(
arg
,
'/'
)
==
NULL
)
{
// --xxxx=example.org (only availabe for --rebind-domain-ok)
if
(
option
==
LOPT_NO_REBIND
)
newlist
.
flags
|=
SERV_NO_REBIND
;
else
if
(
option
==
'S'
)
// --server=8.8.8.8
start_addr
=
arg
;
}
else
{
for
(
start_addr
=
arg
;
(
start_addr
=
strchr
(
start_addr
,
'/'
))
!=
NULL
;
)
;
start_addr
++
;
}
/* --xxxx=/example.org/# , here "#" means use standard server*/
if
(
start_addr
!=
NULL
)
{
if
(
*
start_addr
==
'#'
)
{
newlist
.
flags
|=
SERV_USE_RESOLV
;
/* --xxxx=/example.org/here-is-empty */
}
else
if
(
*
start_addr
==
'\0'
)
{
if
(
!
(
newlist
.
flags
&
SERV_NO_REBIND
))
newlist
.
flags
|=
SERV_NO_ADDR
;
/* no server */
}
else
{
/* --xxxx=/example.org/8.8.8.8#53@source-ip|interface#port */
err
=
parse_server
(
arg
,
&
newlist
.
addr
,
&
newlist
.
source_addr
,
newlist
.
interface
,
&
newlist
.
flags
);
if
(
err
)
ret_err
(
err
);
}
}
// --server
if
(
servers_only
&&
option
==
'S'
)
newlist
.
flags
|=
SERV_FROM_FILE
;
if
(
arg
&&
(
*
arg
==
'/'
||
option
==
LOPT_NO_REBIND
))
// --rebind-domain-ok
if
(
option
==
LOPT_NO_REBIND
)
newlist
.
flags
|=
SERV_NO_REBIND
;
// --address will be handled inside the domain dict_node
// the arg pattern can be
// --xxxx=example.org (only availabe for --rebind-domain-ok) or
// --xxxx=/example.org/ or
// --xxxx=/example.org/ample.com/temple.net/
if
(
*
arg
==
'/'
||
option
==
LOPT_NO_REBIND
)
{
int
rebind
=
!
(
*
arg
==
'/'
);
char
*
end
=
NULL
;
...
...
@@ -2230,75 +2293,49 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
domain
=
""
;
else
if
(
strlen
(
arg
)
!=
0
&&
!
(
domain
=
canonicalise_opt
(
arg
)))
option
=
'?'
;
serv
=
opt_malloc
(
sizeof
(
struct
server
));
memset
(
serv
,
0
,
sizeof
(
struct
server
));
serv
->
next
=
newlist
;
newlist
=
serv
;
serv
->
domain
=
domain
;
serv
->
flags
=
domain
?
SERV_HAS_DOMAIN
:
SERV_FOR_NODOTS
;
np
=
add_or_lookup_domain
(
daemon
->
dh_special_domains
,
domain
);
if
(
np
->
obj
==
NULL
)
{
obj
=
opt_malloc
(
sizeof
(
struct
special_domain
));
memset
(
obj
,
0
,
sizeof
(
struct
special_domain
));
obj
->
domain_flags
=
0
;
}
else
{
obj
=
(
struct
special_domain
*
)
np
->
obj
;
}
if
(
option
==
'A'
)
{
obj
->
server
=
NULL
;
obj
->
domain_flags
=
SERV_LITERAL_ADDRESS
;
memcpy
(
&
obj
->
addr
,
&
newlist
.
addr
,
sizeof
(
union
mysockaddr
));
}
else
if
(
option
==
'S'
)
{
// pointer to one of servers in daemon->servers link list,
// no memory is leaked if obj->server been overwritten
obj
->
server
=
lookup_or_install_new_server
(
&
newlist
);
}
if
(
option
==
LOPT_NO_REBIND
)
{
// the rebind flag here instead of the one in struct server
// will be used by forward
obj
->
domain_flags
|=
SERV_NO_REBIND
;
}
if
(
option
==
LOPT_LOCAL
)
{
obj
->
domain_flags
|=
SERV_NO_ADDR
;
}
//newlist.flags |= domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
np
->
obj
=
(
void
*
)
obj
;
arg
=
end
;
if
(
rebind
)
break
;
}
if
(
!
newlist
)
ret_err
(
gen_err
);
}
else
{
newlist
=
opt_malloc
(
sizeof
(
struct
server
));
memset
(
newlist
,
0
,
sizeof
(
struct
server
));
#ifdef HAVE_LOOP
newlist
->
uid
=
rand32
();
#endif
}
if
(
servers_only
&&
option
==
'S'
)
newlist
->
flags
|=
SERV_FROM_FILE
;
if
(
option
==
'A'
)
{
newlist
->
flags
|=
SERV_LITERAL_ADDRESS
;
if
(
!
(
newlist
->
flags
&
SERV_TYPE
))
ret_err
(
gen_err
);
}
else
if
(
option
==
LOPT_NO_REBIND
)
newlist
->
flags
|=
SERV_NO_REBIND
;
if
(
!
arg
||
!*
arg
)
{
if
(
!
(
newlist
->
flags
&
SERV_NO_REBIND
))
newlist
->
flags
|=
SERV_NO_ADDR
;
/* no server */
if
(
newlist
->
flags
&
SERV_LITERAL_ADDRESS
)
ret_err
(
gen_err
);
}
else
if
(
strcmp
(
arg
,
"#"
)
==
0
)
{
newlist
->
flags
|=
SERV_USE_RESOLV
;
/* treat in ordinary way */
if
(
newlist
->
flags
&
SERV_LITERAL_ADDRESS
)
ret_err
(
gen_err
);
}
else
{
char
*
err
=
parse_server
(
arg
,
&
newlist
->
addr
,
&
newlist
->
source_addr
,
newlist
->
interface
,
&
newlist
->
flags
);
if
(
err
)
ret_err
(
err
);
}
serv
=
newlist
;
while
(
serv
->
next
)
{
serv
->
next
->
flags
=
serv
->
flags
;
serv
->
next
->
addr
=
serv
->
addr
;
serv
->
next
->
source_addr
=
serv
->
source_addr
;
strcpy
(
serv
->
next
->
interface
,
serv
->
interface
);
serv
=
serv
->
next
;
}
serv
->
next
=
daemon
->
servers
;
daemon
->
servers
=
newlist
;
break
;
break
;
}
case
LOPT_REV_SERV
:
/* --rev-server */
{
char
*
string
;
...
...
@@ -2368,7 +2405,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
option
=
'?'
;
if
(
domain
!=
NULL
)
np
=
add_domain
(
daemon
->
dh_ipsets
,
domain
);
np
=
add_
or_lookup_
domain
(
daemon
->
dh_ipsets
,
domain
);
arg
=
end
;
}
...
...
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