SpecialProxy/dns.c

142 lines
3.2 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "dns.h"
#include "http.h"
struct dns dns_list[MAX_CONNECTION >> 1]; //一个客户端 + 一个服务端 占用一个dns结构体
int dnsFd;
void read_dns_rsp()
{
static char rsp_data[512], *ip, *p;
struct dns *dns;
conn_t *client;
int16_t len, dns_id;
while ((len = read(dnsFd, rsp_data, 512)) > 11)
{
memcpy(&dns_id, rsp_data, 2);
dns = dns_list + dns_id;
client = cts + (dns_id << 1);
//判断是否是正常DNS回应是否已关闭连接
if (dns_id > MAX_CONNECTION >> 1 || client->fd < 0)
continue;
if (dns->request_len + 12 > len || (unsigned char)rsp_data[3] != 128) //char只有7位可用则正数最高为127
{
close_connection(client);
continue;
}
/* get domain ip */
p = rsp_data + dns->request_len + 11;
ip = NULL;
while (p - rsp_data + 4 <= len)
{
//type
if (*(p - 8) != 1)
{
p += *p + 12;
continue;
}
ip = p + 1;
break;
}
if (ip == NULL || connectionToServer(*(in_addr_t *)ip, client + 1) != 0)
{
close_connection(client);
continue;
}
}
}
/* 完全发送返回0发送部分返回1出错返回-1 */
static int8_t send_dns_req(struct dns *dns)
{
int write_len;
write_len = write(dnsFd, dns->request, dns->request_len);
if (write_len == dns->request_len - dns->sent_len)
{
dns->sent_len = dns->request_len;
return 0;
}
else if (write_len > 0)
{
return 1;
}
else
{
return -1;
}
}
void dns_query()
{
int16_t i, ret;
for (i = 0; i < MAX_CONNECTION >> 1; i++)
{
if (dns_list[i].request_len != dns_list[i].sent_len)
{
ret = send_dns_req(dns_list + i);
if (ret == 1)
break;
else if (ret == -1)
close_connection(cts + (i << 1));
}
}
//dnsFd的缓冲区以满
if (i < MAX_CONNECTION >> 1)
{
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
ev.data.fd = dnsFd;
epoll_ctl(efd, EPOLL_CTL_MOD, dnsFd, &ev);
}
}
int8_t build_dns_req(struct dns *dns, char *domain)
{
char *p, *_p;
int8_t domain_size;
domain_size = strlen(domain);
p = dns->request + 12;
memcpy(p+1, domain, domain_size + 1);
while ((_p = strchr(p+1, '.')) != NULL)
{
*p = _p - p - 1;
p = _p;
}
*p = strlen(p+1);
p = dns->request + 14 + domain_size;
*p++ = 0;
*p++ = 1;
*p++ = 0;
*p++ = 1;
dns->request_len = p - dns->request;
switch (send_dns_req(dns))
{
case 0:
return 0;
case 1:
ev.data.fd = dnsFd;
ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
epoll_ctl(efd, EPOLL_CTL_MOD, dnsFd, &ev);
return 1;
default:
return -1;
}
}
void dns_connect(struct sockaddr_in *dnsAddr)
{
dnsFd = socket(AF_INET, SOCK_DGRAM, 0);
if (dnsFd < 0)
{
perror("socket");
exit(1);
}
connect(dnsFd, (struct sockaddr *)dnsAddr, sizeof(struct sockaddr_in));
fcntl(dnsFd, F_SETFL, O_NONBLOCK);
}