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;
|
||||
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*/
|
||||
len = sizeof(*opt) + 4;
|
||||
len = 4;
|
||||
len += (ecs->source_prefix / 8);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -1468,9 +1469,20 @@ static int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(context->ptr, dns_opt->data, dns_opt->length);
|
||||
context->ptr += dns_opt->length;
|
||||
|
||||
switch (dns_opt->code) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1756,21 +1768,21 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
|
||||
return -1;
|
||||
}
|
||||
} break;
|
||||
// case DNS_T_OPT: {
|
||||
// unsigned char *opt_start = context->ptr;
|
||||
// ret = _dns_decode_opt(context, type, ttl, rr_len);
|
||||
// if (ret < 0) {
|
||||
// tlog(TLOG_ERROR, "decode opt failed, %s", domain);
|
||||
// return -1;
|
||||
// }
|
||||
case DNS_T_OPT: {
|
||||
unsigned char *opt_start = context->ptr;
|
||||
ret = _dns_decode_opt(context, type, ttl, rr_len);
|
||||
if (ret < 0) {
|
||||
tlog(TLOG_ERROR, "decode opt failed, %s", domain);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// if (context->ptr - opt_start != rr_len) {
|
||||
// tlog(TLOG_ERROR, "opt length mismatch, %s\n", domain);
|
||||
// return -1;
|
||||
// }
|
||||
if (context->ptr - opt_start != rr_len) {
|
||||
tlog(TLOG_ERROR, "opt length mismatch, %s\n", domain);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// dns_set_OPT_payload_size(packet, qclass);
|
||||
// } break;
|
||||
dns_set_OPT_payload_size(packet, qclass);
|
||||
} break;
|
||||
default: {
|
||||
unsigned char raw_data[1024];
|
||||
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 scope_prefix;
|
||||
unsigned char addr[DNS_RR_AAAA_LEN];
|
||||
};
|
||||
} __attribute__((packed));;
|
||||
|
||||
/* OPT COOLIE */
|
||||
struct dns_opt_cookie {
|
||||
|
||||
@@ -3273,6 +3273,34 @@ static void *_dns_client_work(void *arg)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1257,7 +1257,7 @@ static int _conf_edns_client_subnet(void *data, int argc, char *argv[])
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
|
||||
if (argc <= 1 || data == NULL) {
|
||||
if (argc <= 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user