client: support ECS
This commit is contained in:
54
src/dns.c
54
src/dns.c
@@ -871,15 +871,16 @@ int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
|
|||||||
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
struct dns_opt *opt = (struct dns_opt *)opt_data;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
opt->code = DNS_OPT_T_ECS;
|
|
||||||
opt->length = sizeof(*ecs);
|
|
||||||
memcpy(opt->data, ecs, sizeof(*ecs));
|
|
||||||
|
|
||||||
/* ecs size 4 + bit of address*/
|
/* ecs size 4 + bit of address*/
|
||||||
len = sizeof(*opt) + 4;
|
len = 4;
|
||||||
len += (ecs->source_prefix / 8);
|
len += (ecs->source_prefix / 8);
|
||||||
len += (ecs->source_prefix % 8 > 0) ? 1 : 0;
|
len += (ecs->source_prefix % 8 > 0) ? 1 : 0;
|
||||||
|
|
||||||
|
opt->length = len;
|
||||||
|
opt->code = DNS_OPT_T_ECS;
|
||||||
|
memcpy(opt->data, ecs, len);
|
||||||
|
len += sizeof(*opt);
|
||||||
|
|
||||||
return _dns_add_RAW(packet, DNS_RRS_OPT, DNS_OPT_T_ECS, "", 0, opt_data, len);
|
return _dns_add_RAW(packet, DNS_RRS_OPT, DNS_OPT_T_ECS, "", 0, opt_data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1468,9 +1469,20 @@ static int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(context->ptr, dns_opt->data, dns_opt->length);
|
switch (dns_opt->code) {
|
||||||
context->ptr += dns_opt->length;
|
case DNS_OPT_T_ECS: {
|
||||||
|
struct dns_opt_ecs *ecs = (struct dns_opt_ecs *)&(dns_opt->data);
|
||||||
|
_dns_write_short(&context->ptr, ecs->family);
|
||||||
|
_dns_write_char(&context->ptr, ecs->source_prefix);
|
||||||
|
_dns_write_char(&context->ptr, ecs->scope_prefix);
|
||||||
|
memcpy(context->ptr, ecs->addr, dns_opt->length - 4);
|
||||||
|
context->ptr += dns_opt->length - 4;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
memcpy(context->ptr, dns_opt->data, dns_opt->length);
|
||||||
|
context->ptr += dns_opt->length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1756,21 +1768,21 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
// case DNS_T_OPT: {
|
case DNS_T_OPT: {
|
||||||
// unsigned char *opt_start = context->ptr;
|
unsigned char *opt_start = context->ptr;
|
||||||
// ret = _dns_decode_opt(context, type, ttl, rr_len);
|
ret = _dns_decode_opt(context, type, ttl, rr_len);
|
||||||
// if (ret < 0) {
|
if (ret < 0) {
|
||||||
// tlog(TLOG_ERROR, "decode opt failed, %s", domain);
|
tlog(TLOG_ERROR, "decode opt failed, %s", domain);
|
||||||
// return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if (context->ptr - opt_start != rr_len) {
|
if (context->ptr - opt_start != rr_len) {
|
||||||
// tlog(TLOG_ERROR, "opt length mismatch, %s\n", domain);
|
tlog(TLOG_ERROR, "opt length mismatch, %s\n", domain);
|
||||||
// return -1;
|
return -1;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// dns_set_OPT_payload_size(packet, qclass);
|
dns_set_OPT_payload_size(packet, qclass);
|
||||||
// } break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
unsigned char raw_data[1024];
|
unsigned char raw_data[1024];
|
||||||
if (_dns_left_len(context) < rr_len || rr_len >= sizeof(raw_data)) {
|
if (_dns_left_len(context) < rr_len || rr_len >= sizeof(raw_data)) {
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ struct dns_opt_ecs {
|
|||||||
unsigned char source_prefix;
|
unsigned char source_prefix;
|
||||||
unsigned char scope_prefix;
|
unsigned char scope_prefix;
|
||||||
unsigned char addr[DNS_RR_AAAA_LEN];
|
unsigned char addr[DNS_RR_AAAA_LEN];
|
||||||
};
|
} __attribute__((packed));;
|
||||||
|
|
||||||
/* OPT COOLIE */
|
/* OPT COOLIE */
|
||||||
struct dns_opt_cookie {
|
struct dns_opt_cookie {
|
||||||
|
|||||||
@@ -3273,6 +3273,34 @@ static void *_dns_client_work(void *arg)
|
|||||||
|
|
||||||
int dns_client_set_ecs(char *ip, int subnet)
|
int dns_client_set_ecs(char *ip, int subnet)
|
||||||
{
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
getaddr_by_host(ip, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
|
||||||
|
switch (addr.ss_family) {
|
||||||
|
case AF_INET: {
|
||||||
|
struct sockaddr_in *addr_in;
|
||||||
|
addr_in = (struct sockaddr_in *)&addr;
|
||||||
|
memcpy(&client.ecs_ipv4.ipv4_addr, &addr_in->sin_addr.s_addr, 4);
|
||||||
|
client.ecs_ipv4.bitlen = subnet;
|
||||||
|
client.ecs_ipv4.enable = 1;
|
||||||
|
} break;
|
||||||
|
case AF_INET6: {
|
||||||
|
struct sockaddr_in6 *addr_in6;
|
||||||
|
addr_in6 = (struct sockaddr_in6 *)&addr;
|
||||||
|
if (IN6_IS_ADDR_V4MAPPED(&addr_in6->sin6_addr)) {
|
||||||
|
memcpy(&client.ecs_ipv4.ipv4_addr, addr_in6->sin6_addr.s6_addr + 12, 4);
|
||||||
|
client.ecs_ipv4.bitlen = subnet;
|
||||||
|
client.ecs_ipv4.enable = 1;
|
||||||
|
} else {
|
||||||
|
memcpy(&client.ecs_ipv6.ipv6_addr, addr_in6->sin6_addr.s6_addr, 16);
|
||||||
|
client.ecs_ipv6.bitlen = subnet;
|
||||||
|
client.ecs_ipv6.enable = 1;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1257,7 +1257,7 @@ static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
|
|||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addr_len = sizeof(addr);
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
if (argc <= 1 || data == NULL) {
|
if (argc <= 1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user