Browse Source

dns_server: support TCP keepalive timeout EDNS

Nick Peng 1 year ago
parent
commit
9a83df46e0
7 changed files with 161 additions and 70 deletions
  1. 38 7
      src/dns.c
  2. 2 3
      src/dns.h
  3. 16 2
      src/dns_cache.c
  4. 6 2
      src/dns_client.c
  5. 88 45
      src/dns_server.c
  6. 2 2
      src/util.c
  7. 9 9
      test/cases/test-subnet.cc

+ 38 - 7
src/dns.c

@@ -738,14 +738,14 @@ static int _dns_add_opt_RAW(struct dns_packet *packet, dns_opt_code_t opt_rrtype
 	struct dns_opt *opt = (struct dns_opt *)opt_data;
 	int len = 0;
 
-	opt->code = DNS_OPT_T_TCP_KEEPALIVE;
+	opt->code = opt_rrtype;
 	opt->length = sizeof(unsigned short);
 
 	memcpy(opt->data, raw, raw_len);
 	len += raw_len;
 	len += sizeof(*opt);
 
-	return _dns_add_RAW(packet, DNS_RRS_OPT, (dns_type_t)DNS_OPT_T_TCP_KEEPALIVE, "", 0, opt_data, len);
+	return _dns_add_RAW(packet, DNS_RRS_OPT, (dns_type_t)opt_rrtype, "", 0, opt_data, len);
 }
 
 static int _dns_get_opt_RAW(struct dns_rrs *rrs, char *domain, int maxsize, int *ttl, struct dns_opt *dns_opt,
@@ -1030,7 +1030,7 @@ int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs)
 	return _dns_add_RAW(packet, DNS_RRS_OPT, (dns_type_t)DNS_OPT_T_ECS, "", 0, opt_data, len);
 }
 
-int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs)
+int dns_get_OPT_ECS(struct dns_rrs *rrs, struct dns_opt_ecs *ecs)
 {
 	unsigned char opt_data[DNS_MAX_OPT_LEN];
 	char domain[DNS_MAX_CNAME_LEN] = {0};
@@ -1067,16 +1067,16 @@ int dns_add_OPT_TCP_KEEPALIVE(struct dns_packet *packet, unsigned short timeout)
 	return _dns_add_opt_RAW(packet, DNS_OPT_T_TCP_KEEPALIVE, &timeout_net, data_len);
 }
 
-int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
-							  unsigned short *timeout)
+int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *timeout)
 {
 	unsigned char opt_data[DNS_MAX_OPT_LEN];
+	char domain[DNS_MAX_CNAME_LEN] = {0};
 	struct dns_opt *opt = (struct dns_opt *)opt_data;
 	int len = DNS_MAX_OPT_LEN;
 	int ttl = 0;
 	unsigned char *data = NULL;
 
-	if (_dns_get_opt_RAW(rrs, NULL, 0, &ttl, opt, &len) != 0) {
+	if (_dns_get_opt_RAW(rrs, domain, DNS_MAX_CNAME_LEN, &ttl, opt, &len) != 0) {
 		return -1;
 	}
 
@@ -1757,6 +1757,23 @@ static int _dns_decode_opt_cookie(struct dns_context *context, struct dns_opt_co
 	return 0;
 }
 
+static int _dns_decode_opt_tcp_keepalive(struct dns_context *context, unsigned short *timeout, int opt_len)
+{
+	if (opt_len == 0) {
+		*timeout = 0;
+		return 0;
+	}
+
+	if (opt_len < (int)sizeof(unsigned short)) {
+		return -1;
+	}
+
+	*timeout = _dns_read_short(&context->ptr);
+
+	tlog(TLOG_DEBUG, "OPT TCP KEEPALIVE %u", *timeout);
+	return 0;
+}
+
 static int _dns_encode_OPT(struct dns_context *context, struct dns_rrs *rrs)
 {
 	int ret = 0;
@@ -1875,7 +1892,7 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
 	unsigned short opt_code = 0;
 	unsigned short opt_len = 0;
 	unsigned short errcode = (ttl >> 16) & 0xFFFF;
-	unsigned short ever = (ttl)&0xFFFF;
+	unsigned short ever = (ttl) & 0xFFFF;
 	unsigned char *start = context->ptr;
 	struct dns_packet *packet = context->packet;
 	int ret = 0;
@@ -1960,6 +1977,20 @@ static int _dns_decode_opt(struct dns_context *context, dns_rr_type type, unsign
 				return -1;
 			}
 		} break;
+		case DNS_OPT_T_TCP_KEEPALIVE: {
+			unsigned short timeout = 0;
+			ret = _dns_decode_opt_tcp_keepalive(context, &timeout, opt_len);
+			if (ret != 0) {
+				tlog(TLOG_ERROR, "decode tcp keepalive failed.");
+				return -1;
+			}
+
+			ret = dns_add_OPT_TCP_KEEPALIVE(packet, timeout);
+			if (ret != 0) {
+				tlog(TLOG_ERROR, "add tcp keepalive failed.");
+				return -1;
+			}
+		} break;
 		case DNS_OPT_T_PADDING:
 			context->ptr += opt_len;
 			break;

+ 2 - 3
src/dns.h

@@ -280,11 +280,10 @@ int dns_set_OPT_payload_size(struct dns_packet *packet, int payload_size);
 int dns_get_OPT_payload_size(struct dns_packet *packet);
 
 int dns_add_OPT_ECS(struct dns_packet *packet, struct dns_opt_ecs *ecs);
-int dns_get_OPT_ECS(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len, struct dns_opt_ecs *ecs);
+int dns_get_OPT_ECS(struct dns_rrs *rrs, struct dns_opt_ecs *ecs);
 
 int dns_add_OPT_TCP_KEEPALIVE(struct dns_packet *packet, unsigned short timeout);
-int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *opt_code, unsigned short *opt_len,
-							  unsigned short *timeout);
+int dns_get_OPT_TCP_KEEPALIVE(struct dns_rrs *rrs, unsigned short *timeout);
 
 /* the key must be added in orders, or dig will report FORMERR */
 int dns_add_HTTPS_start(struct dns_rr_nested *svcparam_buffer, struct dns_packet *packet, dns_rr_type type,

+ 16 - 2
src/dns_cache.c

@@ -32,6 +32,7 @@
 #define DNS_CACHE_HITNUM_STEP 3
 #define DNS_CACHE_HITNUM_STEP_MAX 6
 #define DNS_CACHE_READ_TIMEOUT 60
+#define EXPIRED_DOMAIN_PREFETCH_TIME (3600 * 8)
 
 struct dns_cache_head {
 	struct hash_table cache_hash;
@@ -508,12 +509,25 @@ static int _dns_cache_read_to_cache(struct dns_cache_record *cache_record, struc
 	struct list_head *head = NULL;
 	head = &dns_cache_head.cache_list;
 	struct dns_cache_info *info = &cache_record->info;
+	int expired_time = 0;
 
 	time_t now = time(NULL);
+	if (now < info->replace_time) {
+		info->replace_time = now;
+	}
+
+	expired_time = dns_conf_serve_expired_prefetch_time;
+	if (expired_time == 0) {
+		expired_time = dns_conf_serve_expired_ttl / 2;
+		if (expired_time == 0 || expired_time > EXPIRED_DOMAIN_PREFETCH_TIME) {
+			expired_time = EXPIRED_DOMAIN_PREFETCH_TIME;
+		}
+	}
+
 	int passed_time = now - info->replace_time;
 	int timeout = info->timeout - passed_time;
-	if ((timeout > dns_conf_serve_expired_ttl + info->ttl) && dns_conf_serve_expired_ttl >= 0) {
-		timeout = dns_conf_serve_expired_ttl + info->ttl;
+	if ((timeout > expired_time + info->ttl) && expired_time >= 0) {
+		timeout = expired_time + info->ttl;
 	}
 
 	if (timeout < DNS_CACHE_READ_TIMEOUT * 2) {

+ 6 - 2
src/dns_client.c

@@ -3416,7 +3416,11 @@ static int _dns_client_setup_server_packet(struct dns_server_info *server_info,
 	}
 
 	dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
-	/* dns_add_OPT_TCP_KEEPALIVE(packet, 600); */
+
+	if (server_info->type != DNS_SERVER_UDP) {
+		dns_add_OPT_TCP_KEEPALIVE(packet, 6000);
+	}
+
 	if ((query->qtype == DNS_T_A && server_info->ecs_ipv4.enable)) {
 		dns_add_OPT_ECS(packet, &server_info->ecs_ipv4.ecs);
 	} else if ((query->qtype == DNS_T_AAAA && server_info->ecs_ipv6.enable)) {
@@ -3628,7 +3632,7 @@ static int _dns_client_send_query(struct dns_query_struct *query)
 	}
 
 	dns_set_OPT_payload_size(packet, DNS_IN_PACKSIZE);
-	/* dns_add_OPT_TCP_KEEPALIVE(packet, 600); */
+	dns_add_OPT_TCP_KEEPALIVE(packet, 1200);
 	if (_dns_client_dns_add_ecs(query, packet) != 0) {
 		tlog(TLOG_ERROR, "add ecs failed.");
 		return -1;

+ 88 - 45
src/dns_server.c

@@ -181,20 +181,12 @@ struct dns_server_conn_tcp_client {
 	socklen_t localaddr_len;
 	struct sockaddr_storage localaddr;
 
+	int conn_idle_timeout;
 	dns_server_client_status status;
 };
 
 struct dns_server_conn_tls_client {
-	struct dns_server_conn_head head;
-	struct dns_conn_buf recvbuff;
-	struct dns_conn_buf sndbuff;
-	socklen_t addr_len;
-	struct sockaddr_storage addr;
-
-	socklen_t localaddr_len;
-	struct sockaddr_storage localaddr;
-	dns_server_client_status status;
-
+	struct dns_server_conn_tcp_client tcp;
 	SSL *ssl;
 	pthread_mutex_t ssl_lock;
 };
@@ -369,6 +361,7 @@ static int _dns_server_reply_all_pending_list(struct dns_request *request, struc
 static void *_dns_server_get_dns_rule(struct dns_request *request, enum domain_rule rule);
 static const char *_dns_server_get_request_groupname(struct dns_request *request);
 static int _dns_server_tcp_socket_send(struct dns_server_conn_tcp_client *tcp_client, void *data, int data_len);
+static int _dns_server_update_request_connection_timeout(struct dns_server_conn_head *conn, int timeout);
 static int _dns_server_cache_save(int check_lock);
 
 int dns_is_ipv6_ready(void)
@@ -5638,12 +5631,26 @@ static int _dns_server_parser_request(struct dns_request *request, struct dns_pa
 	}
 
 	for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(packet, rrs)) {
-		ret = dns_get_OPT_ECS(rrs, NULL, NULL, &request->ecs);
-		if (ret != 0) {
-			continue;
+		switch (rrs->type) {
+		case DNS_OPT_T_TCP_KEEPALIVE: {
+			unsigned short idle_timeout = 0;
+			ret = dns_get_OPT_TCP_KEEPALIVE(rrs, &idle_timeout);
+			if (idle_timeout == 0) {
+				continue;
+			}
+
+			tlog(TLOG_DEBUG, "set tcp connection timeout to %u", idle_timeout);
+			_dns_server_update_request_connection_timeout(request->conn, idle_timeout / 10);
+		} break;
+		case DNS_OPT_T_ECS:
+			ret = dns_get_OPT_ECS(rrs, &request->ecs);
+			if (ret != 0) {
+				continue;
+			}
+			request->has_ecs = 1;
+		default:
+			break;
 		}
-		request->has_ecs = 1;
-		break;
 	}
 
 	return 0;
@@ -5891,6 +5898,33 @@ static int _dns_server_client_close(struct dns_server_conn_head *conn)
 	return 0;
 }
 
+static int _dns_server_update_request_connection_timeout(struct dns_server_conn_head *conn, int timeout)
+{
+	if (conn == NULL) {
+		return -1;
+	}
+
+	if (timeout == 0) {
+		return 0;
+	}
+
+	switch (conn->type) {
+	case DNS_CONN_TYPE_TCP_CLIENT: {
+		struct dns_server_conn_tcp_client *tcpclient = (struct dns_server_conn_tcp_client *)conn;
+		tcpclient->conn_idle_timeout = timeout;
+	} break;
+	case DNS_CONN_TYPE_TLS_CLIENT:
+	case DNS_CONN_TYPE_HTTPS_CLIENT: {
+		struct dns_server_conn_tls_client *tlsclient = (struct dns_server_conn_tls_client *)conn;
+		tlsclient->tcp.conn_idle_timeout = timeout;
+	} break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 static int _dns_server_tcp_accept(struct dns_server_conn_tcp_server *tcpserver, struct epoll_event *event,
 								  unsigned long now)
 {
@@ -5917,6 +5951,7 @@ static int _dns_server_tcp_accept(struct dns_server_conn_tcp_server *tcpserver,
 	tcpclient->head.server_flags = tcpserver->head.server_flags;
 	tcpclient->head.dns_group = tcpserver->head.dns_group;
 	tcpclient->head.ipset_nftset_rule = tcpserver->head.ipset_nftset_rule;
+	tcpclient->conn_idle_timeout = dns_conf_tcp_idle_time;
 
 	atomic_set(&tcpclient->head.refcnt, 0);
 	memcpy(&tcpclient->addr, &addr, addr_len);
@@ -5937,6 +5972,8 @@ static int _dns_server_tcp_accept(struct dns_server_conn_tcp_server *tcpserver,
 	list_add(&tcpclient->head.list, &server.conn_list);
 	_dns_server_conn_get(&tcpclient->head);
 
+	set_sock_keepalive(fd, 15, 3, 4);
+
 	return 0;
 errout:
 	if (fd > 0) {
@@ -6411,30 +6448,31 @@ static int _dns_server_tls_accept(struct dns_server_conn_tls_server *tls_server,
 	}
 	memset(tls_client, 0, sizeof(*tls_client));
 
-	tls_client->head.fd = fd;
+	tls_client->tcp.head.fd = fd;
 	if (tls_server->head.type == DNS_CONN_TYPE_TLS_SERVER) {
-		tls_client->head.type = DNS_CONN_TYPE_TLS_CLIENT;
+		tls_client->tcp.head.type = DNS_CONN_TYPE_TLS_CLIENT;
 	} else if (tls_server->head.type == DNS_CONN_TYPE_HTTPS_SERVER) {
-		tls_client->head.type = DNS_CONN_TYPE_HTTPS_CLIENT;
+		tls_client->tcp.head.type = DNS_CONN_TYPE_HTTPS_CLIENT;
 	} else {
 		tlog(TLOG_ERROR, "invalid http server type.");
 		goto errout;
 	}
-	tls_client->head.server_flags = tls_server->head.server_flags;
-	tls_client->head.dns_group = tls_server->head.dns_group;
-	tls_client->head.ipset_nftset_rule = tls_server->head.ipset_nftset_rule;
+	tls_client->tcp.head.server_flags = tls_server->head.server_flags;
+	tls_client->tcp.head.dns_group = tls_server->head.dns_group;
+	tls_client->tcp.head.ipset_nftset_rule = tls_server->head.ipset_nftset_rule;
+	tls_client->tcp.conn_idle_timeout = dns_conf_tcp_idle_time;
 
-	atomic_set(&tls_client->head.refcnt, 0);
-	memcpy(&tls_client->addr, &addr, addr_len);
-	tls_client->addr_len = addr_len;
-	tls_client->localaddr_len = sizeof(struct sockaddr_storage);
-	if (_dns_server_epoll_ctl(&tls_client->head, EPOLL_CTL_ADD, EPOLLIN) != 0) {
+	atomic_set(&tls_client->tcp.head.refcnt, 0);
+	memcpy(&tls_client->tcp.addr, &addr, addr_len);
+	tls_client->tcp.addr_len = addr_len;
+	tls_client->tcp.localaddr_len = sizeof(struct sockaddr_storage);
+	if (_dns_server_epoll_ctl(&tls_client->tcp.head, EPOLL_CTL_ADD, EPOLLIN) != 0) {
 		tlog(TLOG_ERROR, "epoll ctl failed.");
 		return -1;
 	}
 
-	if (getsocket_inet(tls_client->head.fd, (struct sockaddr *)&tls_client->localaddr, &tls_client->localaddr_len) !=
-		0) {
+	if (getsocket_inet(tls_client->tcp.head.fd, (struct sockaddr *)&tls_client->tcp.localaddr,
+					   &tls_client->tcp.localaddr_len) != 0) {
 		tlog(TLOG_ERROR, "get local addr failed, %s", strerror(errno));
 		goto errout;
 	}
@@ -6451,12 +6489,14 @@ static int _dns_server_tls_accept(struct dns_server_conn_tls_server *tls_server,
 	}
 
 	tls_client->ssl = ssl;
-	tls_client->status = DNS_SERVER_CLIENT_STATUS_CONNECTING;
+	tls_client->tcp.status = DNS_SERVER_CLIENT_STATUS_CONNECTING;
 	pthread_mutex_init(&tls_client->ssl_lock, NULL);
-	_dns_server_client_touch(&tls_client->head);
+	_dns_server_client_touch(&tls_client->tcp.head);
 
-	list_add(&tls_client->head.list, &server.conn_list);
-	_dns_server_conn_get(&tls_client->head);
+	list_add(&tls_client->tcp.head.list, &server.conn_list);
+	_dns_server_conn_get(&tls_client->tcp.head);
+
+	set_sock_keepalive(fd, 15, 3, 4);
 
 	return 0;
 errout:
@@ -6481,7 +6521,7 @@ static int _dns_server_process_tls(struct dns_server_conn_tls_client *tls_client
 	int ssl_ret = 0;
 	struct epoll_event fd_event;
 
-	if (tls_client->status == DNS_SERVER_CLIENT_STATUS_CONNECTING) {
+	if (tls_client->tcp.status == DNS_SERVER_CLIENT_STATUS_CONNECTING) {
 		/* do SSL hand shake */
 		ret = _ssl_do_accept(tls_client);
 		if (ret <= 0) {
@@ -6498,14 +6538,14 @@ static int _dns_server_process_tls(struct dns_server_conn_tls_client *tls_client
 				int ssl_reason = ERR_GET_REASON(ssl_err);
 				char name[DNS_MAX_CNAME_LEN];
 				tlog(TLOG_DEBUG, "Handshake with %s failed, error no: %s(%d, %d, %d)\n",
-					 get_host_by_addr(name, sizeof(name), (struct sockaddr *)&tls_client->addr),
+					 get_host_by_addr(name, sizeof(name), (struct sockaddr *)&tls_client->tcp.addr),
 					 ERR_reason_error_string(ssl_err), ret, ssl_ret, ssl_reason);
 				ret = 0;
 				goto errout;
 			}
 
 			fd_event.data.ptr = tls_client;
-			if (epoll_ctl(server.epoll_fd, EPOLL_CTL_MOD, tls_client->head.fd, &fd_event) != 0) {
+			if (epoll_ctl(server.epoll_fd, EPOLL_CTL_MOD, tls_client->tcp.head.fd, &fd_event) != 0) {
 				tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
 				goto errout;
 			}
@@ -6513,11 +6553,11 @@ static int _dns_server_process_tls(struct dns_server_conn_tls_client *tls_client
 			return 0;
 		}
 
-		tls_client->status = DNS_SERVER_CLIENT_STATUS_CONNECTED;
+		tls_client->tcp.status = DNS_SERVER_CLIENT_STATUS_CONNECTED;
 		memset(&fd_event, 0, sizeof(fd_event));
 		fd_event.events = EPOLLIN | EPOLLOUT;
 		fd_event.data.ptr = tls_client;
-		if (epoll_ctl(server.epoll_fd, EPOLL_CTL_MOD, tls_client->head.fd, &fd_event) != 0) {
+		if (epoll_ctl(server.epoll_fd, EPOLL_CTL_MOD, tls_client->tcp.head.fd, &fd_event) != 0) {
 			tlog(TLOG_ERROR, "epoll ctl failed, %s", strerror(errno));
 			goto errout;
 		}
@@ -6525,7 +6565,7 @@ static int _dns_server_process_tls(struct dns_server_conn_tls_client *tls_client
 
 	return _dns_server_process_tcp((struct dns_server_conn_tcp_client *)tls_client, event, now);
 errout:
-	_dns_server_client_close(&tls_client->head);
+	_dns_server_client_close(&tls_client->tcp.head);
 	return ret;
 }
 
@@ -6557,7 +6597,7 @@ static int _dns_server_process(struct dns_server_conn_head *conn, struct epoll_e
 		if (ret != 0) {
 			char name[DNS_MAX_CNAME_LEN];
 			tlog(TLOG_DEBUG, "process TLS packet from %s failed.",
-				 get_host_by_addr(name, sizeof(name), (struct sockaddr *)&tls_client->addr));
+				 get_host_by_addr(name, sizeof(name), (struct sockaddr *)&tls_client->tcp.addr));
 		}
 	} else {
 		tlog(TLOG_ERROR, "unsupported dns server type %d", conn->type);
@@ -6692,18 +6732,21 @@ static void _dns_server_tcp_idle_check(void)
 	struct dns_server_conn_head *tmp = NULL;
 	time_t now = 0;
 
-	if (dns_conf_tcp_idle_time <= 0) {
-		return;
-	}
-
 	time(&now);
 	list_for_each_entry_safe(conn, tmp, &server.conn_list, list)
 	{
-		if (conn->type != DNS_CONN_TYPE_TCP_CLIENT && conn->type != DNS_CONN_TYPE_TLS_CLIENT) {
+		if (conn->type != DNS_CONN_TYPE_TCP_CLIENT && conn->type != DNS_CONN_TYPE_TLS_CLIENT &&
+			conn->type != DNS_CONN_TYPE_HTTPS_CLIENT) {
+			continue;
+		}
+
+		struct dns_server_conn_tcp_client *tcpclient = (struct dns_server_conn_tcp_client *)conn;
+
+		if (tcpclient->conn_idle_timeout <= 0) {
 			continue;
 		}
 
-		if (conn->last_request_time > now - dns_conf_tcp_idle_time) {
+		if (conn->last_request_time > now - tcpclient->conn_idle_timeout) {
 			continue;
 		}
 

+ 2 - 2
src/util.c

@@ -1386,8 +1386,8 @@ int set_sock_keepalive(int fd, int keepidle, int keepinterval, int keepcnt)
 	}
 
 	setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
-	setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepinterval, sizeof(keepinterval));
-	setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepcnt, sizeof(keepcnt));
+	setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepinterval, sizeof(keepinterval));
+	setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
 
 	return 0;
 }

+ 9 - 9
test/cases/test-subnet.cc

@@ -55,7 +55,7 @@ TEST_F(SubNet, pass_subnet)
 
 		for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 			memset(&ecs, 0, sizeof(ecs));
-			ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+			ret = dns_get_OPT_ECS(rrs, &ecs);
 			if (ret != 0) {
 				continue;
 			}
@@ -125,7 +125,7 @@ TEST_F(SubNet, conf)
 
 		for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 			memset(&ecs, 0, sizeof(ecs));
-			ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+			ret = dns_get_OPT_ECS(rrs, &ecs);
 			if (ret != 0) {
 				continue;
 			}
@@ -196,7 +196,7 @@ TEST_F(SubNet, conf_v6)
 
 		for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 			memset(&ecs, 0, sizeof(ecs));
-			ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+			ret = dns_get_OPT_ECS(rrs, &ecs);
 			if (ret != 0) {
 				continue;
 			}
@@ -269,7 +269,7 @@ TEST_F(SubNet, v4_server_subnet_txt)
 
 		for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 			memset(&ecs, 0, sizeof(ecs));
-			ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+			ret = dns_get_OPT_ECS(rrs, &ecs);
 			if (ret != 0) {
 				continue;
 			}
@@ -340,7 +340,7 @@ TEST_F(SubNet, v6_default_subnet_txt)
 
 		for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 			memset(&ecs, 0, sizeof(ecs));
-			ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+			ret = dns_get_OPT_ECS(rrs, &ecs);
 			if (ret != 0) {
 				continue;
 			}
@@ -410,7 +410,7 @@ TEST_F(SubNet, per_server)
 
 			for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 				memset(&ecs, 0, sizeof(ecs));
-				ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+				ret = dns_get_OPT_ECS(rrs, &ecs);
 				if (ret != 0) {
 					continue;
 				}
@@ -442,7 +442,7 @@ TEST_F(SubNet, per_server)
 
 			for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 				memset(&ecs, 0, sizeof(ecs));
-				ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+				ret = dns_get_OPT_ECS(rrs, &ecs);
 				if (ret != 0) {
 					continue;
 				}
@@ -479,7 +479,7 @@ TEST_F(SubNet, per_server)
 
 			for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 				memset(&ecs, 0, sizeof(ecs));
-				ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+				ret = dns_get_OPT_ECS(rrs, &ecs);
 				if (ret != 0) {
 					continue;
 				}
@@ -524,7 +524,7 @@ TEST_F(SubNet, per_server)
 
 			for (i = 0; i < rr_count && rrs; i++, rrs = dns_get_rrs_next(request->packet, rrs)) {
 				memset(&ecs, 0, sizeof(ecs));
-				ret = dns_get_OPT_ECS(rrs, NULL, NULL, &ecs);
+				ret = dns_get_OPT_ECS(rrs, &ecs);
 				if (ret != 0) {
 					continue;
 				}