diff --git a/src/dns_client.c b/src/dns_client.c index 410371e..ec55d35 100644 --- a/src/dns_client.c +++ b/src/dns_client.c @@ -50,6 +50,8 @@ #define DNS_MAX_EVENTS 64 #define DNS_HOSTNAME_LEN 128 #define DNS_TCP_BUFFER (32 * 1024) +#define DNS_TCP_IDLE_TIMEOUT (60 * 10) +#define DNS_TCP_CONNECT_TIMEOUT (5) #ifndef TCP_FASTOPEN_CONNECT #define TCP_FASTOPEN_CONNECT 30 @@ -109,6 +111,7 @@ struct dns_server_info { /* server ping handle */ struct ping_host_struct *ping_host; + char ip[DNS_HOSTNAME_LEN]; /* server type */ dns_server_type_t type; @@ -242,7 +245,7 @@ void _dns_client_server_update_ttl(struct ping_host_struct *ping_host, const cha } double rtt = tv->tv_sec * 1000.0 + tv->tv_usec / 1000.0; - tlog(TLOG_DEBUG, "from %15s: seq=%d ttl=%d time=%.3f\n", host, seqno, ttl, rtt); + tlog(TLOG_DEBUG, "from %s: seq=%d ttl=%d time=%.3f\n", host, seqno, ttl, rtt); server_info->ttl = ttl; } @@ -265,6 +268,7 @@ int _dns_client_server_add(char *server_ip, struct addrinfo *gai, dns_server_typ } memset(server_info, 0, sizeof(*server_info)); + strncpy(server_info->ip, server_ip, sizeof(server_info->ip)); server_info->ai_family = gai->ai_family; server_info->ai_addrlen = gai->ai_addrlen; server_info->type = server_type; @@ -341,6 +345,9 @@ static void _dns_client_close_socket(struct dns_server_info *server_info) server_info->fd = -1; server_info->status = DNS_SERVER_STATUS_DISCONNECTED; + time(&server_info->last_send); + time(&server_info->last_recv); + tlog(TLOG_DEBUG, "server %s closed.", server_info->ip); } static void _dns_client_server_close(struct dns_server_info *server_info) @@ -553,10 +560,72 @@ void _dns_client_query_remove_all(void) return; } +void _dns_client_check_udp_nat(void) +{ + struct dns_server_info *server_info; + /* For udp nat case. + * when router reconnect to internet, udp port may always marked as UNREPLIED. + * dns query will timeout, and cannot reconnect again, + * create a new socket to communicate. + */ + pthread_mutex_lock(&client.server_list_lock); + list_for_each_entry(server_info, &client.dns_server_list, list) + { + if (server_info->type != DNS_SERVER_UDP) { + continue; + } + + if (server_info->last_send - 5 > server_info->last_recv) { + server_info->recv_buff.len = 0; + server_info->send_buff.len = 0; + tlog(TLOG_DEBUG, "query server %s timeout.", server_info->ip); + _dns_client_close_socket(server_info); + } + } + pthread_mutex_unlock(&client.server_list_lock); +} + +void _dns_client_check_tcp(void) +{ + struct dns_server_info *server_info; + time_t now; + + time(&now); + + pthread_mutex_lock(&client.server_list_lock); + list_for_each_entry(server_info, &client.dns_server_list, list) + { + if (server_info->type == DNS_SERVER_UDP) { + continue; + } + + if (server_info->status == DNS_SERVER_STATUS_CONNECTING) { + if (server_info->last_send + DNS_TCP_CONNECT_TIMEOUT < now) { + tlog(TLOG_DEBUG, "server %s connect timeout.", server_info->ip); + _dns_client_close_socket(server_info); + } + } else if (server_info->status == DNS_SERVER_STATUS_CONNECTED) { + if (server_info->last_recv + DNS_TCP_IDLE_TIMEOUT < now) { + server_info->recv_buff.len = 0; + server_info->send_buff.len = 0; + _dns_client_close_socket(server_info); + } + } + } + pthread_mutex_unlock(&client.server_list_lock); +} + +void _dns_client_period_run_second(void) +{ + _dns_client_check_tcp(); +} + void _dns_client_period_run(void) { struct dns_query_struct *query, *tmp; - struct dns_server_info *server_info; + static unsigned int msec = 0; + msec++; + LIST_HEAD(check_list); unsigned long now = get_tick_count(); @@ -579,21 +648,12 @@ void _dns_client_period_run(void) _dns_client_query_remove(query); _dns_client_query_release(query); - /* For udp nat case. - * when router reconnect to internet, udp port may always marked as UNREPLIED. - * dns query will timeout, and cannot reconnect again, - * create a new socket to communicate. - */ - pthread_mutex_lock(&client.server_list_lock); - list_for_each_entry(server_info, &client.dns_server_list, list) - { - if (server_info->last_send - 5 > server_info->last_recv) { - server_info->recv_buff.len = 0; - server_info->send_buff.len = 0; - _dns_client_close_socket(server_info); - } - } - pthread_mutex_unlock(&client.server_list_lock); + _dns_client_check_udp_nat(); + } + + + if (msec % 10 == 0) { + _dns_client_period_run_second(); } return; @@ -825,6 +885,8 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info) server_info->fd = fd; server_info->status = DNS_SERVER_STATUS_CONNECTING; + tlog(TLOG_DEBUG, "tcp server %s connecting.\n", server_info->ip); + return 0; errout: if (fd > 0) { @@ -898,7 +960,7 @@ static int _DNS_client_create_socket_tls(struct dns_server_info *server_info) server_info->ssl = ssl; server_info->status = DNS_SERVER_STATUS_CONNECTING; - tlog(TLOG_DEBUG, "TLS server connecting.\n"); + tlog(TLOG_DEBUG, "tls server %s connecting.\n", server_info->ip); return 0; errout: @@ -979,7 +1041,7 @@ static int _dns_client_process_udp(struct dns_server_info *server_info, struct e } } - tlog(TLOG_DEBUG, "recv udp, from %s, len: %d, ttl: %d", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len), len, ttl); + tlog(TLOG_DEBUG, "recv udp packet from %s, len: %d, ttl: %d", gethost_by_addr(from_host, (struct sockaddr *)&from, from_len), len, ttl); if ((ttl != server_info->ttl) && (server_info->ttl > 0) && (server_info->result_flag & DNSSERVER_FLAG_CHECK_TTL)) { if ((ttl < server_info->ttl - server_info->ttl_range) || (ttl > server_info->ttl + server_info->ttl_range)) { @@ -1141,7 +1203,6 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e int len; int ret = -1; unsigned char *inpacket_data = server_info->recv_buff.data; - char from_host[DNS_MAX_CNAME_LEN]; if (event->events & EPOLLIN) { /* receive from tcp */ @@ -1173,7 +1234,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e ret = 0; } pthread_mutex_unlock(&client.server_list_lock); - tlog(TLOG_DEBUG, "peer close, left = %d", server_info->send_buff.len); + tlog(TLOG_DEBUG, "peer close, %s", server_info->ip); return ret; } @@ -1202,7 +1263,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e } inpacket_data = server_info->recv_buff.data + 2; - tlog(TLOG_DEBUG, "recv tcp from %s, len = %d", gethost_by_addr(from_host, (struct sockaddr *)&server_info->addr, server_info->ai_addrlen), len); + tlog(TLOG_DEBUG, "recv tcp packet from %s, len = %d", server_info->ip, len); /* process result */ if (_dns_client_recv(server_info, inpacket_data, len, &server_info->addr, server_info->ai_addrlen) != 0) { @@ -1226,7 +1287,7 @@ static int _dns_client_process_tcp(struct dns_server_info *server_info, struct e if (server_info->status == DNS_SERVER_STATUS_CONNECTING) { server_info->status = DNS_SERVER_STATUS_CONNECTED; - tlog(TLOG_DEBUG, "tcp connected"); + tlog(TLOG_DEBUG, "tcp server %s connected", server_info->ip); } if (server_info->status != DNS_SERVER_STATUS_CONNECTED) { @@ -1361,7 +1422,7 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e return 0; } - tlog(TLOG_DEBUG, "TLS server connected.\n"); + tlog(TLOG_DEBUG, "tls server %s connected.\n", server_info->ip); /* Was the stored session reused? */ if (SSL_session_reused(server_info->ssl)) { tlog(TLOG_DEBUG, "reused session"); @@ -1371,14 +1432,15 @@ static int _dns_client_process_tls(struct dns_server_info *server_info, struct e SSL_SESSION_free(server_info->ssl_session); server_info->ssl_session = NULL; } + + if (_dns_client_tls_verify(server_info) != 0) { + tlog(TLOG_WARN, "peer verify failed."); + goto errout; + } + server_info->ssl_session = SSL_get1_session(server_info->ssl); } - if (_dns_client_tls_verify(server_info) != 0) { - tlog(TLOG_WARN, "peer verify failed."); - goto errout; - } - server_info->status = DNS_SERVER_STATUS_CONNECTED; memset(&fd_event, 0, sizeof(fd_event)); fd_event.events = EPOLLIN | EPOLLOUT; diff --git a/src/dns_server.c b/src/dns_server.c index f1cd8c6..47bea67 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -761,9 +761,9 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos } if (result == PING_RESULT_RESPONSE) { request->has_ping_result = 1; - tlog(TLOG_DEBUG, "from %15s: seq=%d time=%d\n", host, seqno, rtt); + tlog(TLOG_DEBUG, "from %s: seq=%d time=%d\n", host, seqno, rtt); } else { - tlog(TLOG_DEBUG, "from %15s: seq=%d timeout\n", host, seqno); + tlog(TLOG_DEBUG, "from %s: seq=%d timeout\n", host, seqno); } if (rtt < threshold) { @@ -1416,6 +1416,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac _dns_server_client_get(client); + tlog(TLOG_DEBUG, "recv query packet from %s, len = %d", gethost_by_addr(name, (struct sockaddr *)from, from_len), inpacket_len); decode_len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len); if (decode_len < 0) { tlog(TLOG_ERROR, "decode failed.\n"); @@ -1507,7 +1508,7 @@ static int _dns_server_recv(struct dns_server_conn *client, unsigned char *inpac goto clean_exit; } - tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, gethost_by_addr(name, (struct sockaddr *)from, from_len), qtype); + tlog(TLOG_INFO, "query server %s from %s, qtype = %d\n", request->domain, name, qtype); _dns_server_request_get(request); pthread_mutex_lock(&server.request_list_lock);