dns-debug: support record fail packet for debugging
This commit is contained in:
42
src/dns.c
42
src/dns.c
@@ -1785,7 +1785,7 @@ static int _dns_decode_an(struct dns_context *context, dns_rr_type type)
|
||||
}
|
||||
|
||||
if (context->ptr - opt_start != rr_len) {
|
||||
tlog(TLOG_ERROR, "opt length mismatch, %s\n", domain);
|
||||
tlog(TLOG_DEBUG, "opt length mismatch, %s\n", domain);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -2223,43 +2223,3 @@ int dns_packet_update(unsigned char *data, int size, struct dns_update_param *pa
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void dns_debug(void)
|
||||
{
|
||||
unsigned char data[1024];
|
||||
ssize_t len;
|
||||
char buff[4096];
|
||||
|
||||
int fd = open("dns.bin", O_RDWR);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
len = read(fd, data, 1024);
|
||||
close(fd);
|
||||
if (len < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct dns_packet *packet = (struct dns_packet *)buff;
|
||||
if (dns_decode(packet, 4096, data, len) != 0) {
|
||||
tlog(TLOG_ERROR, "decode failed.\n");
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
len = dns_encode(data, 1024, packet);
|
||||
if (len < 0) {
|
||||
tlog(TLOG_ERROR, "encode failed.");
|
||||
}
|
||||
|
||||
fd = open("dns-cmp.bin", O_CREAT | O_TRUNC | O_RDWR, 0660);
|
||||
write(fd, data, len);
|
||||
close(fd);
|
||||
|
||||
packet = (struct dns_packet *)buff;
|
||||
if (dns_decode(packet, 4096, data, len) != 0) {
|
||||
tlog(TLOG_ERROR, "decode failed.\n");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -574,7 +574,8 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _dns_client_add_to_pending_group(const char *group_name, char *server_ip, int port, dns_server_type_t server_type)
|
||||
static int _dns_client_add_to_pending_group(const char *group_name, char *server_ip, int port,
|
||||
dns_server_type_t server_type)
|
||||
{
|
||||
struct dns_server_pending *item = NULL;
|
||||
struct dns_server_pending *tmp = NULL;
|
||||
@@ -621,8 +622,8 @@ errout:
|
||||
}
|
||||
|
||||
/* add server to group */
|
||||
static int _dns_client_add_to_group_pending(const char *group_name, char *server_ip, int port, dns_server_type_t server_type,
|
||||
int ispending)
|
||||
static int _dns_client_add_to_group_pending(const char *group_name, char *server_ip, int port,
|
||||
dns_server_type_t server_type, int ispending)
|
||||
{
|
||||
struct dns_server_info *server_info = NULL;
|
||||
|
||||
@@ -1591,8 +1592,11 @@ static int _dns_client_recv(struct dns_server_info *server_info, unsigned char *
|
||||
len = dns_decode(packet, DNS_PACKSIZE, inpacket, inpacket_len);
|
||||
if (len != 0) {
|
||||
char host_name[DNS_MAX_CNAME_LEN];
|
||||
tlog(TLOG_WARN, "decode failed, packet len = %d, tc = %d, id = %d, from = %s\n", inpacket_len, packet->head.tc,
|
||||
tlog(TLOG_INFO, "decode failed, packet len = %d, tc = %d, id = %d, from = %s\n", inpacket_len, packet->head.tc,
|
||||
packet->head.id, gethost_by_addr(host_name, sizeof(host_name), from));
|
||||
if (dns_save_fail_packet) {
|
||||
dns_packet_save(dns_save_fail_packet_dir, "client", host_name, inpacket, inpacket_len);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1721,7 +1725,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
|
||||
|
||||
fd = socket(server_info->ai_family, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
tlog(TLOG_ERROR, "create socket failed.");
|
||||
tlog(TLOG_ERROR, "create socket failed, %s", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
@@ -1732,7 +1736,7 @@ static int _DNS_client_create_socket_tcp(struct dns_server_info *server_info)
|
||||
|
||||
/* enable tcp fast open */
|
||||
if (setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, &yes, sizeof(yes)) != 0) {
|
||||
tlog(TLOG_DEBUG, "enable TCP fast open failed.");
|
||||
tlog(TLOG_DEBUG, "enable TCP fast open failed, %s", strerror(errno));
|
||||
}
|
||||
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes));
|
||||
|
||||
@@ -130,6 +130,9 @@ int dns_conf_ipset_timeout_enable;
|
||||
|
||||
char dns_conf_user[DNS_CONF_USRNAME_LEN];
|
||||
|
||||
int dns_save_fail_packet;
|
||||
char dns_save_fail_packet_dir[DNS_MAX_PATH];
|
||||
|
||||
/* ECS */
|
||||
struct dns_edns_client_subnet dns_conf_ipv4_ecs;
|
||||
struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
||||
@@ -1920,6 +1923,8 @@ static struct config_item _config_item[] = {
|
||||
CONF_STRING("ca-file", (char *)&dns_conf_ca_file, DNS_MAX_PATH),
|
||||
CONF_STRING("ca-path", (char *)&dns_conf_ca_path, DNS_MAX_PATH),
|
||||
CONF_STRING("user", (char *)&dns_conf_user, sizeof(dns_conf_user)),
|
||||
CONF_YESNO("debug-save-fail-packet", &dns_save_fail_packet),
|
||||
CONF_STRING("debug-save-fail-packet-dir", (char *)&dns_save_fail_packet_dir, sizeof(dns_save_fail_packet_dir)),
|
||||
CONF_CUSTOM("conf-file", config_addtional_file, NULL),
|
||||
CONF_END(),
|
||||
};
|
||||
@@ -2068,6 +2073,8 @@ static int _dns_conf_load_pre(void)
|
||||
|
||||
_dns_ping_cap_check();
|
||||
|
||||
safe_strncpy(dns_save_fail_packet_dir, SMARTDNS_DEBUG_DIR, sizeof(dns_save_fail_packet_dir));
|
||||
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
|
||||
@@ -52,6 +52,7 @@ extern "C" {
|
||||
#define SMARTDNS_LOG_FILE "/var/log/smartdns/smartdns.log"
|
||||
#define SMARTDNS_AUDIT_FILE "/var/log/smartdns/smartdns-audit.log"
|
||||
#define SMARTDNS_CACHE_FILE "/tmp/smartdns.cache"
|
||||
#define SMARTDNS_DEBUG_DIR "/tmp/smartdns"
|
||||
|
||||
enum domain_rule {
|
||||
DOMAIN_RULE_FLAGS = 0,
|
||||
@@ -321,6 +322,9 @@ extern struct dns_edns_client_subnet dns_conf_ipv6_ecs;
|
||||
|
||||
extern char dns_conf_sni_proxy_ip[DNS_MAX_IPLEN];
|
||||
|
||||
extern int dns_save_fail_packet;
|
||||
extern char dns_save_fail_packet_dir[DNS_MAX_PATH];
|
||||
|
||||
void dns_server_load_exit(void);
|
||||
|
||||
int dns_server_load_conf(const char *file);
|
||||
|
||||
@@ -557,8 +557,8 @@ static void _dns_server_audit_log(struct dns_server_post_context *context)
|
||||
tm.min, tm.sec, tm.usec / 1000);
|
||||
|
||||
tlog_printf(dns_audit, "%s %s query %s, type %d, time %lums, speed: %.1fms, result %s\n", req_time, req_host,
|
||||
request->domain, request->qtype, get_tick_count() - request->send_tick, ((float)request->ping_time) / 10,
|
||||
req_result);
|
||||
request->domain, request->qtype, get_tick_count() - request->send_tick,
|
||||
((float)request->ping_time) / 10, req_result);
|
||||
}
|
||||
|
||||
static void _dns_rrs_result_log(struct dns_server_post_context *context, struct dns_ip_address *addr_map)
|
||||
@@ -3533,6 +3533,7 @@ static int _dns_server_process_cache_packet(struct dns_request *request, struct
|
||||
request->ping_time = dns_cache->info.speed;
|
||||
|
||||
if (dns_decode(context.packet, context.packet_maxlen, cache_packet->data, cache_packet->head.size) != 0) {
|
||||
tlog(TLOG_ERROR, "decode cache failed, %d, %d", context.packet_maxlen, context.inpacket_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4159,6 +4160,9 @@ static int _dns_server_recv(struct dns_server_conn_head *conn, unsigned char *in
|
||||
if (decode_len < 0) {
|
||||
tlog(TLOG_DEBUG, "decode failed.\n");
|
||||
ret = RECV_ERROR_INVALID_PACKET;
|
||||
if (dns_save_fail_packet) {
|
||||
dns_packet_save(dns_save_fail_packet_dir, "server", name, inpacket, inpacket_len);
|
||||
}
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
||||
@@ -524,7 +524,7 @@ int main(int argc, char *argv[])
|
||||
sigemptyset(&empty_sigblock);
|
||||
sigprocmask(SIG_SETMASK, &empty_sigblock, NULL);
|
||||
|
||||
while ((opt = getopt(argc, argv, "fhc:p:Svx")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "fhc:p:SvxN:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
is_forground = 1;
|
||||
@@ -545,6 +545,10 @@ int main(int argc, char *argv[])
|
||||
_show_version();
|
||||
return 0;
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case 'N':
|
||||
return dns_packet_debug(optarg);
|
||||
#endif
|
||||
case 'h':
|
||||
_help();
|
||||
return 1;
|
||||
|
||||
43
src/tlog.c
43
src/tlog.c
@@ -79,6 +79,7 @@ struct tlog_log {
|
||||
int zip_pid;
|
||||
int multi_log;
|
||||
int logscreen;
|
||||
int no_write_log;
|
||||
int segment_log;
|
||||
int max_line_size;
|
||||
|
||||
@@ -216,7 +217,6 @@ static int _tlog_mkdir(const char *path)
|
||||
}
|
||||
|
||||
if (mkdir(path_c, 0750) != 0) {
|
||||
fprintf(stderr, "create directory %s failed, %s\n", path_c, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1130,6 +1130,10 @@ static int _tlog_write(struct tlog_log *log, const char *buff, int bufflen)
|
||||
unused = write(STDOUT_FILENO, buff, bufflen);
|
||||
}
|
||||
|
||||
if (log->no_write_log) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if log file size exceeds threshold, start to compress */
|
||||
if (log->multi_log && log->fd > 0) {
|
||||
log->filesize = lseek(log->fd, 0, SEEK_END);
|
||||
@@ -1160,7 +1164,15 @@ static int _tlog_write(struct tlog_log *log, const char *buff, int bufflen)
|
||||
|
||||
char logfile[PATH_MAX * 2];
|
||||
if (_tlog_mkdir(log->logdir) != 0) {
|
||||
fprintf(stderr, "create log dir %s failed.\n", log->logdir);
|
||||
if (print_errmsg == 0) {
|
||||
return -1;
|
||||
}
|
||||
print_errmsg = 0;
|
||||
fprintf(stderr, "create log dir %s failed, %s\n", log->logdir, strerror(errno));
|
||||
if (errno == EACCES && log->logscreen == 0) {
|
||||
fprintf(stderr, "no permission to write log file, output log to console\n");
|
||||
tlog_logscreen_only(log, 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
snprintf(logfile, sizeof(logfile), "%s/%s", log->logdir, log->logname);
|
||||
@@ -1574,11 +1586,26 @@ static void _tlog_log_setlogscreen(struct tlog_log *log, int enable)
|
||||
log->logscreen = (enable != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void _tlog_log_setlogscreen_only(struct tlog_log *log, int enable)
|
||||
{
|
||||
if (log == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
log->logscreen = (enable != 0) ? 1 : 0;
|
||||
log->no_write_log = (enable != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void tlog_setlogscreen(int enable)
|
||||
{
|
||||
_tlog_log_setlogscreen(tlog.root, enable);
|
||||
}
|
||||
|
||||
void tlog_setlogscreen_only(int enable)
|
||||
{
|
||||
_tlog_log_setlogscreen_only(tlog.root, enable);
|
||||
}
|
||||
|
||||
int tlog_write_log(char *buff, int bufflen)
|
||||
{
|
||||
if (unlikely(tlog.root == NULL)) {
|
||||
@@ -1597,6 +1624,15 @@ void tlog_logscreen(tlog_log *log, int enable)
|
||||
_tlog_log_setlogscreen(log, enable);
|
||||
}
|
||||
|
||||
void tlog_logscreen_only(tlog_log *log, int enable)
|
||||
{
|
||||
if (log == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
_tlog_log_setlogscreen_only(log, enable);
|
||||
}
|
||||
|
||||
int tlog_reg_output_func(tlog_log *log, tlog_output_func output)
|
||||
{
|
||||
if (log == NULL) {
|
||||
@@ -1830,13 +1866,13 @@ int tlog_init(const char *logfile, int maxlogsize, int maxlogcount, int buffsize
|
||||
}
|
||||
tlog_reg_output_func(log, _tlog_root_write_log);
|
||||
|
||||
tlog.root = log;
|
||||
ret = pthread_create(&tlog.tid, &attr, _tlog_work, NULL);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "create tlog work thread failed, %s\n", strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
tlog.root = log;
|
||||
if (flag & TLOG_SUPPORT_FORK) {
|
||||
pthread_atfork(&tlog_fork_prepare, &tlog_fork_parent, &tlog_fork_child);
|
||||
}
|
||||
@@ -1852,6 +1888,7 @@ errout:
|
||||
pthread_cond_destroy(&tlog.cond);
|
||||
pthread_mutex_destroy(&tlog.lock);
|
||||
tlog.run = 0;
|
||||
tlog.root = NULL;
|
||||
|
||||
_tlog_close(log, 1);
|
||||
|
||||
|
||||
@@ -104,6 +104,9 @@ extern void tlog_set_logfile(const char *logfile);
|
||||
/* enalbe log to screen */
|
||||
extern void tlog_setlogscreen(int enable);
|
||||
|
||||
/* output log to screen only */
|
||||
extern void tlog_setlogscreen_only(int enable);
|
||||
|
||||
/* enalbe early log to screen */
|
||||
extern void tlog_set_early_printf(int enable);
|
||||
|
||||
@@ -184,6 +187,9 @@ extern int tlog_vprintf(tlog_log *log, const char *format, va_list ap);
|
||||
/* enalbe log to screen */
|
||||
extern void tlog_logscreen(tlog_log *log, int enable);
|
||||
|
||||
/* enalbe log to screen only*/
|
||||
extern void tlog_logscreen_only(tlog_log *log, int enable);
|
||||
|
||||
/* register output callback */
|
||||
typedef int (*tlog_output_func)(struct tlog_log *log, const char *buff, int bufflen);
|
||||
extern int tlog_reg_output_func(tlog_log *log, tlog_output_func output);
|
||||
|
||||
283
src/util.c
283
src/util.c
@@ -34,12 +34,13 @@
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
@@ -79,6 +80,8 @@
|
||||
#define NETLINK_ALIGN(len) (((len) + 3) & ~(3))
|
||||
|
||||
#define BUFF_SZ 1024
|
||||
#define PACKET_BUF_SIZE 8192
|
||||
#define PACKET_MAGIC 0X11040918
|
||||
|
||||
struct ipset_netlink_attr {
|
||||
unsigned short len;
|
||||
@@ -641,7 +644,7 @@ unsigned char *SSL_SHA256(const unsigned char *d, size_t n, unsigned char *md)
|
||||
md = m;
|
||||
}
|
||||
|
||||
EVP_MD_CTX* ctx = EVP_MD_CTX_create();
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -1159,7 +1162,7 @@ void bug_ext(const char *file, int line, const char *func, const char *errfmt, .
|
||||
|
||||
int write_file(const char *filename, void *data, int data_len)
|
||||
{
|
||||
int fd = open(filename, O_WRONLY|O_CREAT, 0644);
|
||||
int fd = open(filename, O_WRONLY | O_CREAT, 0644);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -1178,3 +1181,277 @@ errout:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dns_packet_save(const char *dir, const char *type, const char *from, const void *packet, int packet_len)
|
||||
{
|
||||
char *data = NULL;
|
||||
int data_len = 0;
|
||||
char filename[BUFF_SZ];
|
||||
char time_s[BUFF_SZ];
|
||||
int ret = -1;
|
||||
|
||||
struct tm *ptm;
|
||||
struct tm tm;
|
||||
struct timeval tmval;
|
||||
struct stat sb;
|
||||
|
||||
if (stat(dir, &sb) != 0) {
|
||||
mkdir(dir, 0750);
|
||||
}
|
||||
|
||||
if (gettimeofday(&tmval, NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ptm = localtime_r(&tmval.tv_sec, &tm);
|
||||
if (ptm == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = snprintf(time_s, sizeof(time_s) - 1, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.3d", ptm->tm_year + 1900,
|
||||
ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, (int)(tmval.tv_usec / 1000));
|
||||
ret = snprintf(filename, sizeof(filename) - 1, "%s/%s-%.4d%.2d%.2d-%.2d%.2d%.2d%.1d.packet", dir, type,
|
||||
ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec,
|
||||
(int)(tmval.tv_usec / 100000));
|
||||
|
||||
data = malloc(PACKET_BUF_SIZE);
|
||||
if (data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data_len = snprintf(data, PACKET_BUF_SIZE,
|
||||
"type: %s\n"
|
||||
"from: %s\n"
|
||||
"time: %s\n"
|
||||
"packet-len: %d\n",
|
||||
type, from, time_s, packet_len);
|
||||
if (data_len <= 0 || data_len >= PACKET_BUF_SIZE) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
data[data_len] = 0;
|
||||
data_len++;
|
||||
uint32_t magic = htonl(PACKET_MAGIC);
|
||||
memcpy(data + data_len, &magic, sizeof(magic));
|
||||
data_len += sizeof(magic);
|
||||
int len_in_h = htonl(packet_len);
|
||||
memcpy(data + data_len, &len_in_h, sizeof(len_in_h));
|
||||
data_len += 4;
|
||||
memcpy(data + data_len, packet, packet_len);
|
||||
data_len += packet_len;
|
||||
|
||||
ret = write_file(filename, data, data_len);
|
||||
if (ret != 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (data) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
struct _dns_read_packet_info {
|
||||
int data_len;
|
||||
int message_len;
|
||||
char *message;
|
||||
int packet_len;
|
||||
uint8_t *packet;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
static struct _dns_read_packet_info *_dns_read_packet_file(const char *packet_file)
|
||||
{
|
||||
struct _dns_read_packet_info *info = NULL;
|
||||
int fd = 0;
|
||||
int len = 0;
|
||||
int message_len = 0;
|
||||
uint8_t *ptr = NULL;
|
||||
|
||||
info = malloc(sizeof(struct _dns_read_packet_info) + PACKET_BUF_SIZE);
|
||||
fd = open(packet_file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
printf("open file %s failed, %s\n", packet_file, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
len = read(fd, info->data, PACKET_BUF_SIZE);
|
||||
if (len < 0) {
|
||||
printf("read file %s failed, %s\n", packet_file, strerror(errno));
|
||||
goto errout;
|
||||
}
|
||||
|
||||
message_len = strnlen((char *)info->data, PACKET_BUF_SIZE);
|
||||
if (message_len >= 512 || message_len >= len) {
|
||||
printf("invalid packet file, bad message len\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
info->message_len = message_len;
|
||||
info->message = (char *)info->data;
|
||||
|
||||
ptr = info->data + message_len + 1;
|
||||
uint32_t magic = 0;
|
||||
if (ptr - (uint8_t *)info + sizeof(magic) >= (size_t)len) {
|
||||
printf("invalid packet file, magic length is invalid.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
memcpy(&magic, ptr, sizeof(magic));
|
||||
if (magic != htonl(PACKET_MAGIC)) {
|
||||
printf("invalid packet file, bad magic\n");
|
||||
goto errout;
|
||||
}
|
||||
ptr += sizeof(magic);
|
||||
|
||||
uint32_t packet_len = 0;
|
||||
if (ptr - info->data + sizeof(packet_len) >= (size_t)len) {
|
||||
printf("invalid packet file, packet length is invalid.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
memcpy(&packet_len, ptr, sizeof(packet_len));
|
||||
packet_len = ntohl(packet_len);
|
||||
ptr += sizeof(packet_len);
|
||||
if (packet_len != (size_t)len - (ptr - info->data)) {
|
||||
printf("invalid packet file, packet length is invalid\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
info->packet_len = packet_len;
|
||||
info->packet = ptr;
|
||||
|
||||
close(fd);
|
||||
return info;
|
||||
errout:
|
||||
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (info) {
|
||||
free(info);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _dns_debug_display(struct dns_packet *packet)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int ttl = 0;
|
||||
struct dns_rrs *rrs = NULL;
|
||||
int rr_count = 0;
|
||||
char req_host[MAX_IP_LEN];
|
||||
|
||||
for (j = 1; j < DNS_RRS_END; j++) {
|
||||
rrs = dns_get_rrs_start(packet, j, &rr_count);
|
||||
printf("section: %d\n", j);
|
||||
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];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
/* get A result */
|
||||
dns_get_A(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
req_host[0] = '\0';
|
||||
inet_ntop(AF_INET, addr, req_host, sizeof(req_host));
|
||||
printf("domain: %s A: %s TTL: %d\n", name, req_host, ttl);
|
||||
} break;
|
||||
case DNS_T_AAAA: {
|
||||
unsigned char addr[16];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
dns_get_AAAA(rrs, name, DNS_MAX_CNAME_LEN, &ttl, addr);
|
||||
req_host[0] = '\0';
|
||||
inet_ntop(AF_INET6, addr, req_host, sizeof(req_host));
|
||||
printf("domain: %s AAAA: %s TTL:%d\n", name, req_host, ttl);
|
||||
} break;
|
||||
case DNS_T_NS: {
|
||||
char cname[DNS_MAX_CNAME_LEN];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
|
||||
printf("domain: %s TTL: %d NS: %s\n", name, ttl, cname);
|
||||
} break;
|
||||
case DNS_T_CNAME: {
|
||||
char cname[DNS_MAX_CNAME_LEN];
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
if (dns_conf_force_no_cname) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dns_get_CNAME(rrs, name, DNS_MAX_CNAME_LEN, &ttl, cname, DNS_MAX_CNAME_LEN);
|
||||
printf("domain: %s TTL: %d CNAME: %s\n", name, ttl, cname);
|
||||
} break;
|
||||
case DNS_T_SOA: {
|
||||
char name[DNS_MAX_CNAME_LEN] = {0};
|
||||
struct dns_soa soa;
|
||||
dns_get_SOA(rrs, name, 128, &ttl, &soa);
|
||||
printf("domain: %s SOA: mname: %s, rname: %s, serial: %d, refresh: %d, retry: %d, expire: "
|
||||
"%d, minimum: %d",
|
||||
name, soa.mname, soa.rname, soa.serial, soa.refresh, soa.retry, soa.expire, soa.minimum);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_packet_debug(const char *packet_file)
|
||||
{
|
||||
struct _dns_read_packet_info *info = NULL;
|
||||
char buff[DNS_PACKSIZE];
|
||||
|
||||
tlog_setlogscreen_only(1);
|
||||
tlog_setlevel(TLOG_DEBUG);
|
||||
|
||||
info = _dns_read_packet_file(packet_file);
|
||||
if (info == NULL) {
|
||||
goto errout;
|
||||
}
|
||||
|
||||
const char *send_env = getenv("SMARTDNS_DEBUG_SEND");
|
||||
if (send_env != NULL) {
|
||||
char ip[32];
|
||||
int port = 53;
|
||||
if (parse_ip(send_env, ip, &port) == 0) {
|
||||
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd > 0) {
|
||||
struct sockaddr_in server;
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
server.sin_addr.s_addr = inet_addr(ip);
|
||||
sendto(sockfd, info->packet, info->packet_len, 0, (struct sockaddr *)&server, sizeof(server));
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct dns_packet *packet = (struct dns_packet *)buff;
|
||||
if (dns_decode(packet, DNS_PACKSIZE, info->packet, info->packet_len) != 0) {
|
||||
printf("decode failed.\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
_dns_debug_display(packet);
|
||||
|
||||
free(info);
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
if (info) {
|
||||
free(info);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -126,6 +126,10 @@ void print_stack(void);
|
||||
|
||||
int write_file(const char *filename, void *data, int data_len);
|
||||
|
||||
int dns_packet_save(const char *dir, const char *type, const char *from, const void *packet, int packet_len);
|
||||
|
||||
int dns_packet_debug(const char *packet_file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus */
|
||||
|
||||
Reference in New Issue
Block a user