Make the ipset working as expected when the domain passthrough

This commit is contained in:
Kevin Zhou
2020-08-21 10:14:14 +08:00
committed by Nick Peng
parent 69ba3f8789
commit cb73eadf01

View File

@@ -1712,6 +1712,14 @@ static int _dns_server_get_answer(struct dns_request *request, struct dns_packet
static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns_packet *packet,
unsigned char *inpacket, int inpacket_len)
{
int ttl;
char name[DNS_MAX_CNAME_LEN] = {0};
int rr_count;
int i = 0;
int j = 0;
struct dns_rrs *rrs = NULL;
struct dns_ipset_rule *ipset_rule = NULL;
struct dns_rule_flags *rule_flags = NULL;
int ret = 0;
if (atomic_inc_return(&request->notified) != 1) {
@@ -1731,6 +1739,74 @@ static int _dns_server_reply_passthrouth(struct dns_request *request, struct dns
dns_server_update_reply_packet_id(request, inpacket, inpacket_len);
ret = _dns_reply_inpacket(request, inpacket, inpacket_len);
if (packet->head.rcode != DNS_RC_NOERROR && packet->head.rcode != DNS_RC_NXDOMAIN) {
return ret;
}
if (_dns_server_has_bind_flag(request, BIND_FLAG_NO_RULE_IPSET) == 0) {
return ret;
}
/* check ipset rule */
rule_flags = request->domain_rule.rules[DOMAIN_RULE_FLAGS];
if (rule_flags) {
if (rule_flags->flags & DOMAIN_FLAG_IPSET_IGNORE) {
return ret;
}
}
ipset_rule = request->domain_rule.rules[DOMAIN_RULE_IPSET];
if (ipset_rule == NULL) {
return ret;
}
for (j = 1; j < DNS_RRS_END; j++) {
rrs = dns_get_rrs_start(packet, j, &rr_count);
for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
switch (rrs->type) {
case DNS_T_A: {
unsigned char addr[4];
if (request->qtype != DNS_T_A) {
/* ignore non-matched query type */
if (request->dualstack_selection == 0) {
break;
}
}
/* get A result */
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
/* add IPV4 to ipset */
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %d.%d.%d.%d",
request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3]);
} break;
case DNS_T_AAAA: {
unsigned char addr[16];
if (request->qtype != DNS_T_AAAA) {
/* ignore non-matched query type */
break;
}
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
/* add IPV6 to ipset */
if (request->has_ipv6) {
if (request->has_ipv4) {
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_A_LEN, request->ttl_v4 * 2);
}
ipset_add(ipset_rule->ipsetname, addr, DNS_RR_AAAA_LEN, request->ttl_v6 * 2);
}
tlog(TLOG_DEBUG, "IPSET-MATCH-PASSTHROUTH: domain: %s, ipset: %s, IP: %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x",
request->domain, ipset_rule->ipsetname, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], addr[8],
addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
} break;
default:
break;
}
}
}
return ret;
}