initial
This commit is contained in:
commit
2b6118268c
10
Android.mk
Normal file
10
Android.mk
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
LOCAL_PATH := $(call my-dir)
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
LOCAL_CFLAGS = -O2 -pie -Wall
|
||||||
|
LOCAL_LDFLAGS = -O2 -pie -Wall
|
||||||
|
LOCAL_ARM_MODE = arm
|
||||||
|
LOCAL_MODULE = httpdns
|
||||||
|
LOCAL_MODULE_FILENAME = httpdns
|
||||||
|
c_src_files = $(wildcard $(LOCAL_PATH)/*.c)
|
||||||
|
LOCAL_SRC_FILES = $(c_src_files:$(LOCAL_PATH)/%=%)
|
||||||
|
include $(BUILD_EXECUTABLE)
|
2
Application.mk
Normal file
2
Application.mk
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
APP_ABI = arm64-v8a armeabi-v7a
|
||||||
|
APP_PLATFORM = android-29
|
28
Makefile
Normal file
28
Makefile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
CROSS_COMPILE ?=
|
||||||
|
CC := $(CROSS_COMPILE)gcc
|
||||||
|
STRIP := $(CROSS_COMPILE)strip
|
||||||
|
NDK_BUILD := /usr/lib/android-ndk/ndk-build
|
||||||
|
OBJ := httpdns
|
||||||
|
|
||||||
|
#如果是安卓编译
|
||||||
|
ifeq ($(ANDROID_DATA),/data)
|
||||||
|
CFLAGS := -O2 -pie
|
||||||
|
SHELL := /system/bin/sh
|
||||||
|
else
|
||||||
|
CFLAGS := -O2 -pthread -Wall -static
|
||||||
|
endif
|
||||||
|
|
||||||
|
all : main.o common.o httpdns.o conf.o
|
||||||
|
$(CC) $(CFLAGS) $(DEFS) -o $(OBJ) $^
|
||||||
|
$(STRIP) $(OBJ)
|
||||||
|
-chmod 777 $(OBJ) 2>&-
|
||||||
|
|
||||||
|
.c.o :
|
||||||
|
$(CC) $(CFLAGS) $(DEFS) -c $<
|
||||||
|
|
||||||
|
clean :
|
||||||
|
rm -f *.o
|
||||||
|
rm $(OBJ)
|
||||||
|
|
||||||
|
android:
|
||||||
|
$(NDK_BUILD) NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk APP_BUILD_SCRIPT=Android.mk
|
33
README.md
Normal file
33
README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# HttpDNS
|
||||||
|
|
||||||
|
提取 [mmmdbybyd](https://github.com/mmmdbybyd) CProxy 中 httpdns 核心功能用于Android
|
||||||
|
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Linux编译:
|
||||||
|
make clean; make
|
||||||
|
|
||||||
|
windows 10子系统交叉编译:
|
||||||
|
apt-get install gcc-aarch64-linux-gnu
|
||||||
|
make clean; CROSS_COMPILE=aarch64-linux-gnu- make
|
||||||
|
|
||||||
|
Android NDK 编译:
|
||||||
|
make android
|
||||||
|
或
|
||||||
|
ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=Application.mk APP_BUILD_SCRIPT=Android.mk
|
||||||
|
|
||||||
|
## Help Information
|
||||||
|
|
||||||
|
HttpDNS(2.0.1)
|
||||||
|
Author: aixiao@aixiao.me
|
||||||
|
|
||||||
|
启动命令:
|
||||||
|
httpdns httpdns.conf
|
||||||
|
结束命令:
|
||||||
|
httpdns stop
|
||||||
|
检测命令:
|
||||||
|
httpdns status
|
||||||
|
重启命令:
|
||||||
|
httpdns restart httpdns.conf
|
||||||
|
|
99
common.c
Normal file
99
common.c
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
//有些头文件不声明memmem
|
||||||
|
void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
|
||||||
|
|
||||||
|
void error(const char *error_info)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n\n", error_info);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t copy_new_mem(char *src, int src_len, char **dest)
|
||||||
|
{
|
||||||
|
*dest = (char *)malloc(src_len + 1);
|
||||||
|
if (*dest == NULL)
|
||||||
|
return 1;
|
||||||
|
memcpy(*dest, src, src_len);
|
||||||
|
*((*dest) + src_len) = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 字符串替换,replace_memory为可以用free释放的指针 */
|
||||||
|
char *replace(char *replace_memory, int *replace_memory_len, const char *src, const int src_len, const char *dest, const int dest_len)
|
||||||
|
{
|
||||||
|
if (!replace_memory || !src || !dest)
|
||||||
|
return replace_memory;
|
||||||
|
|
||||||
|
char *p;
|
||||||
|
int diff;
|
||||||
|
|
||||||
|
if (src_len == dest_len) {
|
||||||
|
for (p = memmem(replace_memory, *replace_memory_len, src, src_len); p; p = memmem(p, *replace_memory_len - (p - replace_memory), src, src_len)) {
|
||||||
|
memcpy(p, dest, dest_len);
|
||||||
|
p += dest_len;
|
||||||
|
}
|
||||||
|
} else if (src_len < dest_len) {
|
||||||
|
int before_len;
|
||||||
|
char *before_end, *new_replace_memory;
|
||||||
|
|
||||||
|
diff = dest_len - src_len;
|
||||||
|
for (p = memmem(replace_memory, *replace_memory_len, src, src_len); p; p = memmem(p, *replace_memory_len - (p - replace_memory), src, src_len)) {
|
||||||
|
*replace_memory_len += diff;
|
||||||
|
before_len = p - replace_memory;
|
||||||
|
new_replace_memory = (char *)realloc(replace_memory, *replace_memory_len + 1);
|
||||||
|
if (new_replace_memory == NULL) {
|
||||||
|
free(replace_memory);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
replace_memory = new_replace_memory;
|
||||||
|
before_end = replace_memory + before_len;
|
||||||
|
p = before_end + dest_len;
|
||||||
|
memmove(p, p - diff, *replace_memory_len - (p - replace_memory));
|
||||||
|
memcpy(before_end, dest, dest_len);
|
||||||
|
}
|
||||||
|
} else if (src_len > dest_len) {
|
||||||
|
diff = src_len - dest_len;
|
||||||
|
for (p = memmem(replace_memory, *replace_memory_len, src, src_len); p; p = memmem(p, *replace_memory_len - (p - replace_memory), src, src_len)) {
|
||||||
|
*replace_memory_len -= diff;
|
||||||
|
memcpy(p, dest, dest_len);
|
||||||
|
p += dest_len;
|
||||||
|
memmove(p, p + diff, *replace_memory_len - (p - replace_memory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
replace_memory[*replace_memory_len] = '\0';
|
||||||
|
return replace_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 对数据进行编码 */
|
||||||
|
void dataEncode(char *data, int data_len, unsigned code)
|
||||||
|
{
|
||||||
|
while (data_len-- > 0)
|
||||||
|
data[data_len] ^= code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 监听一个UDP接口 */
|
||||||
|
int udp_listen(char *ip, int port)
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
int fd, opt = 1;
|
||||||
|
|
||||||
|
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
perror("udp socket");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &opt, sizeof(opt));
|
||||||
|
setsockopt(fd, SOL_IP, IP_RECVORIGDSTADDR, &opt, sizeof(opt));
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_addr.s_addr = inet_addr(ip);
|
||||||
|
addr.sin_port = htons(port);
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
|
||||||
|
perror("udp bind");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
24
common.h
Normal file
24
common.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#define VERSION "2.0.1" //"beta" " " __DATE__ " " __TIME__
|
||||||
|
|
||||||
|
extern char *replace(char *str, int *str_len, const char *src, const int src_len, const char *dest, const int dest_len);
|
||||||
|
extern void error(const char *msg);
|
||||||
|
extern int udp_listen(char *ip, int port);
|
||||||
|
extern void dataEncode(char *data, int data_len, unsigned code);
|
||||||
|
extern int8_t copy_new_mem(char *src, int src_len, char **dest);
|
||||||
|
|
||||||
|
#endif
|
BIN
common.o
Normal file
BIN
common.o
Normal file
Binary file not shown.
221
conf.c
Normal file
221
conf.c
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
/* 字符串预处理,设置转义字符 */
|
||||||
|
static void string_pretreatment(char *str, int *len)
|
||||||
|
{
|
||||||
|
char *lf, *p, *ori_strs[] = { "\\r", "\\n", "\\b", "\\v", "\\f", "\\t", "\\a", "\\b", "\\0" }, to_chrs[] = { '\r', '\n', '\b', '\v', '\f', '\t', '\a', '\b', '\0' };
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while ((lf = strchr(str, '\n')) != NULL) {
|
||||||
|
for (p = lf + 1; *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'; p++)
|
||||||
|
*len -= 1;
|
||||||
|
strcpy(lf, p);
|
||||||
|
*len -= 1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < sizeof(to_chrs); i++) {
|
||||||
|
for (p = strstr(str, ori_strs[i]); p; p = strstr(p, ori_strs[i])) {
|
||||||
|
//支持\\r
|
||||||
|
*(p - 1) == '\\' ? (*p--) : (*p = to_chrs[i]);
|
||||||
|
memmove(p + 1, p + 2, strlen(p + 2));
|
||||||
|
(*len)--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */
|
||||||
|
static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end)
|
||||||
|
{
|
||||||
|
char *p, *pn, *lineEnd;
|
||||||
|
;
|
||||||
|
int val_len;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (content == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (; *content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++) ;
|
||||||
|
if (*content == '\0')
|
||||||
|
return NULL;
|
||||||
|
*var = content;
|
||||||
|
pn = strchr(content, '\n');
|
||||||
|
p = strchr(content, '=');
|
||||||
|
if (p == NULL) {
|
||||||
|
if (pn) {
|
||||||
|
content = pn + 1;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
content = p;
|
||||||
|
//将变量以\0结束
|
||||||
|
for (p--; *p == ' ' || *p == '\t'; p--) ;
|
||||||
|
*(p + 1) = '\0';
|
||||||
|
//值的首地址
|
||||||
|
for (content++; *content == ' ' || *content == '\t'; content++) ;
|
||||||
|
if (*content == '\0')
|
||||||
|
return NULL;
|
||||||
|
//双引号引起来的值支持换行
|
||||||
|
if (*content == '"') {
|
||||||
|
*val_begin = content + 1;
|
||||||
|
*val_end = strstr(*val_begin, "\";");
|
||||||
|
if (*val_end != NULL)
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
*val_begin = content;
|
||||||
|
*val_end = strchr(content, ';');
|
||||||
|
if (pn && *val_end > pn) {
|
||||||
|
content = pn + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*val_end) {
|
||||||
|
**val_end = '\0';
|
||||||
|
val_len = *val_end - *val_begin;
|
||||||
|
lineEnd = *val_end;
|
||||||
|
} else {
|
||||||
|
val_len = strlen(*val_begin);
|
||||||
|
*val_end = lineEnd = *val_begin + val_len;
|
||||||
|
}
|
||||||
|
string_pretreatment(*val_begin, &val_len);
|
||||||
|
*val_end = *val_begin + val_len;
|
||||||
|
//printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin);
|
||||||
|
return lineEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 在buff中读取模块(global http https httpdns httpudp)内容 */
|
||||||
|
static char *read_module(char *buff, const char *module_name)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *p, *p0;
|
||||||
|
|
||||||
|
len = strlen(module_name);
|
||||||
|
p = buff;
|
||||||
|
while (1) {
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||||
|
p++;
|
||||||
|
if (strncasecmp(p, module_name, len) == 0) {
|
||||||
|
p += len;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||||
|
p++;
|
||||||
|
if (*p == '{')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((p = strchr(p, '\n')) == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((p0 = strchr(++p, '}')) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
//printf("%s\n%s", module_name, content);
|
||||||
|
return strndup(p, p0 - p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_global_module(char *content)
|
||||||
|
{
|
||||||
|
char *var, *val_begin, *val_end, *lineEnd, *p;
|
||||||
|
|
||||||
|
while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) {
|
||||||
|
if (strcasecmp(var, "mode") == 0) {
|
||||||
|
if (strcasecmp(val_begin, "wap_connect") == 0)
|
||||||
|
global.mode = WAP_CONNECT;
|
||||||
|
else if (strcasecmp(val_begin, "wap") == 0)
|
||||||
|
global.mode = WAP;
|
||||||
|
else if (strcasecmp(val_begin, "net_connect") == 0)
|
||||||
|
global.mode = NET_CONNECT;
|
||||||
|
else if (strcasecmp(val_begin, "net_proxy") == 0)
|
||||||
|
global.mode = NET_PROXY;
|
||||||
|
} else if (strcasecmp(var, "uid") == 0) {
|
||||||
|
global.uid = atoi(val_begin);
|
||||||
|
} else if (strcasecmp(var, "procs") == 0) {
|
||||||
|
global.procs = atol(val_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcasecmp(var, "dns_listen") == 0) {
|
||||||
|
if ((p = strchr(val_begin, ':')) != NULL && p - val_begin <= 15) {
|
||||||
|
*p = '\0';
|
||||||
|
global.dns_listen_fd = udp_listen(val_begin, atoi(p + 1));
|
||||||
|
} else
|
||||||
|
global.dns_listen_fd = udp_listen((char *)"127.0.0.1", atoi(val_begin));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcasecmp(var, "strict") == 0 && strcasecmp(val_begin, "on") == 0) {
|
||||||
|
global.strict_modify = 1;
|
||||||
|
} else if (strcasecmp(var, "timeout") == 0) {
|
||||||
|
global.timeout_m = atoi(val_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
content = strchr(lineEnd + 1, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 读取HTTPDNS模块 */
|
||||||
|
static int8_t parse_httpdns_module(char *content)
|
||||||
|
{
|
||||||
|
char *var, *val_begin, *val_end, *lineEnd, *p;
|
||||||
|
|
||||||
|
while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) {
|
||||||
|
if (strcasecmp(var, "addr") == 0) {
|
||||||
|
if ((p = strchr(val_begin, ':')) != NULL && p - val_begin <= 15) {
|
||||||
|
*p = '\0';
|
||||||
|
httpdns.dst.sin_port = htons(atoi(p + 1));
|
||||||
|
} else {
|
||||||
|
httpdns.dst.sin_port = htons(80);
|
||||||
|
}
|
||||||
|
httpdns.dst.sin_addr.s_addr = inet_addr(val_begin);
|
||||||
|
} else if (strcasecmp(var, "mode") == 0 && strcasecmp(val_begin, "tcpDNS") == 0) {
|
||||||
|
httpdns.tcpDNS_mode = 1;
|
||||||
|
} else if (strcasecmp(var, "http_req") == 0) {
|
||||||
|
httpdns.http_req_len = val_end - val_begin;
|
||||||
|
if (copy_new_mem(val_begin, httpdns.http_req_len, &httpdns.http_req) != 0)
|
||||||
|
return 1;
|
||||||
|
} else if (strcasecmp(var, "cachePath") == 0) {
|
||||||
|
httpdns.cachePath = strdup(val_begin);
|
||||||
|
if (httpdns.cachePath == NULL || read_cache_file() != 0)
|
||||||
|
return 1;
|
||||||
|
} else if (strcasecmp(var, "cacheLimit") == 0) {
|
||||||
|
httpdns.cacheLimit = atoi(val_begin);
|
||||||
|
} else if (strcasecmp(var, "encode") == 0) {
|
||||||
|
httpdns.encodeCode = (unsigned)atoi(val_begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
content = strchr(lineEnd + 1, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_conf(char *path)
|
||||||
|
{
|
||||||
|
char *buff, *global_content, *httpdns_content;
|
||||||
|
FILE *file;
|
||||||
|
long file_size;
|
||||||
|
|
||||||
|
/* 读取配置文件到缓冲区 */
|
||||||
|
file = fopen(path, "r");
|
||||||
|
if (file == NULL)
|
||||||
|
error("cannot open config file.");
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
file_size = ftell(file);
|
||||||
|
buff = (char *)alloca(file_size + 1);
|
||||||
|
if (buff == NULL)
|
||||||
|
error("out of memory.");
|
||||||
|
rewind(file);
|
||||||
|
fread(buff, file_size, 1, file);
|
||||||
|
fclose(file);
|
||||||
|
buff[file_size] = '\0';
|
||||||
|
/* 读取global模块内容 */
|
||||||
|
if ((global_content = read_module(buff, "global")) == NULL)
|
||||||
|
error("read global module error");
|
||||||
|
parse_global_module(global_content);
|
||||||
|
free(global_content);
|
||||||
|
|
||||||
|
/* 读取httpdns模块 */
|
||||||
|
if (global.dns_listen_fd >= 0) {
|
||||||
|
if ((httpdns_content = read_module(buff, "httpdns")) == NULL || parse_httpdns_module(httpdns_content) != 0)
|
||||||
|
error("read httpdns module error");
|
||||||
|
free(httpdns_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
10
conf.h
Normal file
10
conf.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef CONF_H
|
||||||
|
#define CONF_H
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
extern void read_conf(char *path);
|
||||||
|
|
||||||
|
#endif
|
BIN
conf.o
Normal file
BIN
conf.o
Normal file
Binary file not shown.
BIN
httpdns
Normal file
BIN
httpdns
Normal file
Binary file not shown.
633
httpdns.c
Normal file
633
httpdns.c
Normal file
@ -0,0 +1,633 @@
|
|||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "httpdns.h"
|
||||||
|
|
||||||
|
#define DNS_MAX_CONCURRENT 512
|
||||||
|
#define DNS_REQUEST_MAX_SIZE 512+2 //2是TCPDNS头部用于指定dns的长度
|
||||||
|
#define HTTP_RSP_SIZE 2048
|
||||||
|
/*
|
||||||
|
缓存结构: (dns查询请求长度-2)(2字节) + dns原查询请求(删除2字节的dnsID) + dns回应长度(2字节) + dns回应
|
||||||
|
*/
|
||||||
|
struct dns_cache {
|
||||||
|
char *dns_cache;
|
||||||
|
struct dns_cache *next;
|
||||||
|
};
|
||||||
|
typedef struct dns_connection {
|
||||||
|
char dns_req[DNS_REQUEST_MAX_SIZE + 1];
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
char *out_request;
|
||||||
|
char *host;
|
||||||
|
int out_request_len, fd, timer;
|
||||||
|
/*
|
||||||
|
sent_CONNECT_len:
|
||||||
|
在使用SSL代理的情况下,与httpDNS的CONNECT请求长度对比
|
||||||
|
小于表示需要发送CONNECT请求,并且还没有发送完成
|
||||||
|
等于表示已经完成CONNECT连接
|
||||||
|
大于表示已发送完成CONNECT连接,但是没有读取CONNECT的回应包
|
||||||
|
*/
|
||||||
|
int sent_CONNECT_len;
|
||||||
|
uint16_t dns_req_len;
|
||||||
|
char query_type;
|
||||||
|
unsigned host_len:7;
|
||||||
|
} dns_t;
|
||||||
|
|
||||||
|
static dns_t dns_list[DNS_MAX_CONCURRENT];
|
||||||
|
static struct epoll_event dns_evs[DNS_MAX_CONCURRENT + 1], dns_ev;
|
||||||
|
struct httpdns httpdns;
|
||||||
|
static int dns_efd;
|
||||||
|
/* 缓存变量 */
|
||||||
|
FILE *cfp = NULL;
|
||||||
|
static struct dns_cache *cache = NULL;
|
||||||
|
static int cache_using;
|
||||||
|
//子进程先写入缓存,再到父进程写入,否则可能导致缓存文件错乱
|
||||||
|
pid_t child_pid = 0;
|
||||||
|
|
||||||
|
/* 读取缓存文件 */
|
||||||
|
int8_t read_cache_file()
|
||||||
|
{
|
||||||
|
char *buff, *cache_ptr;
|
||||||
|
struct dns_cache *cache_temp;
|
||||||
|
long file_size;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
cache_temp = NULL;
|
||||||
|
cache_using = 0;
|
||||||
|
if ((cfp = fopen(httpdns.cachePath, "r+")) == NULL) {
|
||||||
|
//创建文件并设置权限
|
||||||
|
if ((cfp = fopen(httpdns.cachePath, "w")) != NULL) {
|
||||||
|
chmod(httpdns.cachePath, S_IWOTH | S_IROTH | S_IWGRP | S_IRGRP | S_IWUSR | S_IRUSR);
|
||||||
|
fclose(cfp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//读取文件内容
|
||||||
|
fseek(cfp, 0, SEEK_END);
|
||||||
|
file_size = ftell(cfp);
|
||||||
|
if ((buff = (char *)alloca(file_size)) == NULL)
|
||||||
|
return 1;
|
||||||
|
rewind(cfp);
|
||||||
|
fread(buff, file_size, 1, cfp);
|
||||||
|
fclose(cfp);
|
||||||
|
|
||||||
|
for (cache_ptr = buff; cache_ptr - buff < file_size; cache_ptr += len) {
|
||||||
|
cache_temp = (struct dns_cache *)malloc(sizeof(struct dns_cache));
|
||||||
|
if (cache_temp == NULL)
|
||||||
|
return 1;
|
||||||
|
cache_temp->next = cache;
|
||||||
|
cache = cache_temp;
|
||||||
|
cache_using++;
|
||||||
|
len = *(uint16_t *) cache_ptr + *(uint16_t *) (cache_ptr + *(uint16_t *) cache_ptr + 2) + 4;
|
||||||
|
copy_new_mem(cache_ptr, len, &cache->dns_cache);
|
||||||
|
if (cache->dns_cache == NULL)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* 删除重复记录 */
|
||||||
|
struct dns_cache *before, *after;
|
||||||
|
for (; cache_temp; cache_temp = cache_temp->next) {
|
||||||
|
for (before = cache_temp; before && (after = before->next) != NULL; before = before->next) {
|
||||||
|
if (*(uint16_t *) after->dns_cache == *(uint16_t *) cache_temp->dns_cache && memcmp(after->dns_cache + 2, cache_temp->dns_cache + 2, *(uint16_t *) after->dns_cache) == 0) {
|
||||||
|
before->next = after->next;
|
||||||
|
free(after->dns_cache);
|
||||||
|
free(after);
|
||||||
|
cache_using--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chmod(httpdns.cachePath, S_IWOTH | S_IROTH | S_IWGRP | S_IRGRP | S_IWUSR | S_IRUSR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 程序结束时将缓存写入文件 */
|
||||||
|
static void write_dns_cache(int sig)
|
||||||
|
{
|
||||||
|
//子进程先写入缓存
|
||||||
|
if (child_pid) {
|
||||||
|
wait(NULL);
|
||||||
|
cfp = fopen(httpdns.cachePath, "a");
|
||||||
|
} else {
|
||||||
|
cfp = fopen(httpdns.cachePath, "w");
|
||||||
|
}
|
||||||
|
while (cache) {
|
||||||
|
fwrite(cache->dns_cache, *(uint16_t *) cache->dns_cache + *(uint16_t *) (cache->dns_cache + *(uint16_t *) cache->dns_cache + 2) + 4, 1, cfp);
|
||||||
|
cache = cache->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dnsProxyStop(dns_t * dns)
|
||||||
|
{
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_DEL, dns->fd, NULL);
|
||||||
|
close(dns->fd);
|
||||||
|
if (httpdns.tcpDNS_mode == 0)
|
||||||
|
free(dns->out_request);
|
||||||
|
memset(((char *)dns) + DNS_REQUEST_MAX_SIZE + sizeof(struct sockaddr_in), 0, sizeof(dns_t) - DNS_REQUEST_MAX_SIZE + -sizeof(struct sockaddr_in));
|
||||||
|
dns->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 查询缓存 */
|
||||||
|
static uint8_t cache_lookup(dns_t * dns)
|
||||||
|
{
|
||||||
|
struct dns_cache *c;
|
||||||
|
char *rsp;
|
||||||
|
|
||||||
|
for (c = cache; c; c = c->next) {
|
||||||
|
//不匹配dnsID
|
||||||
|
if (dns->dns_req_len - 2 == *(uint16_t *) c->dns_cache && memcmp(dns->dns_req + 2, c->dns_cache + 2, dns->dns_req_len - 2) == 0) {
|
||||||
|
rsp = c->dns_cache + *(uint16_t *) c->dns_cache + 2;
|
||||||
|
*(uint16_t *) (rsp + 2) = *(uint16_t *) dns->dns_req; //设置dns id
|
||||||
|
sendto(global.dns_listen_fd, rsp + 2, *(uint16_t *) rsp, 0, (struct sockaddr *)&dns->src_addr, sizeof(struct sockaddr_in));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 记录缓存 */
|
||||||
|
static void cache_record(char *request, uint16_t request_len, char *response, uint16_t response_len)
|
||||||
|
{
|
||||||
|
struct dns_cache *cache_temp;
|
||||||
|
|
||||||
|
cache_temp = (struct dns_cache *)malloc(sizeof(struct dns_cache));
|
||||||
|
if (cache_temp == NULL)
|
||||||
|
return;
|
||||||
|
cache_temp->dns_cache = (char *)malloc(request_len + response_len + 2);
|
||||||
|
if (cache_temp->dns_cache == NULL) {
|
||||||
|
free(cache_temp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cache_temp->next = cache;
|
||||||
|
cache = cache_temp;
|
||||||
|
//不缓存dnsid
|
||||||
|
request += 2;
|
||||||
|
request_len -= 2;
|
||||||
|
memcpy(cache_temp->dns_cache, &request_len, 2);
|
||||||
|
memcpy(cache_temp->dns_cache + 2, request, request_len);
|
||||||
|
memcpy(cache_temp->dns_cache + request_len + 2, &response_len, 2);
|
||||||
|
memcpy(cache_temp->dns_cache + request_len + 4, response, response_len);
|
||||||
|
if (httpdns.cacheLimit) {
|
||||||
|
//到达缓存记录条目限制则释放前一半缓存
|
||||||
|
if (cache_using >= httpdns.cacheLimit) {
|
||||||
|
struct dns_cache *free_c;
|
||||||
|
int i;
|
||||||
|
for (i = cache_using = httpdns.cacheLimit >> 1; i--; cache_temp = cache_temp->next) ;
|
||||||
|
for (free_c = cache_temp->next, cache_temp->next = NULL; free_c; free_c = cache_temp) {
|
||||||
|
cache_temp = free_c->next;
|
||||||
|
free(free_c->dns_cache);
|
||||||
|
free(free_c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache_using++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 分析DNS请求 */
|
||||||
|
static int8_t parse_dns_request(char *dns_req, dns_t * dns)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
dns_req += 13; //跳到域名部分
|
||||||
|
dns->host_len = strlen(dns_req);
|
||||||
|
dns->query_type = *(dns_req + 2 + dns->host_len);
|
||||||
|
//tcpdns不需要解析域名
|
||||||
|
if (httpdns.tcpDNS_mode == 1)
|
||||||
|
return 0;
|
||||||
|
//httpdns只支持域名查询ipv4
|
||||||
|
if (dns->query_type != 1 || (dns->host = strdup(dns_req)) == NULL)
|
||||||
|
return 1;
|
||||||
|
for (len = *(--dns_req); dns_req[len + 1] != 0; len += dns_req[len]) {
|
||||||
|
//防止数组越界
|
||||||
|
if (len > dns->host_len) {
|
||||||
|
free(dns->host);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
dns->host[len++] = '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 回应dns客户端 */
|
||||||
|
static int8_t httpDNS_respond_client(dns_t * dns, char *rspIp)
|
||||||
|
{
|
||||||
|
static char rsp[DNS_REQUEST_MAX_SIZE + 16];
|
||||||
|
char *p;
|
||||||
|
int rsp_len;
|
||||||
|
|
||||||
|
//18: 查询资源的前(12字节)后(6字节)部分
|
||||||
|
rsp_len = 18 + dns->host_len + (rspIp ? 16 : 0);
|
||||||
|
//判断是否超出缓冲大小
|
||||||
|
if (rsp_len > DNS_REQUEST_MAX_SIZE) {
|
||||||
|
dns->query_type = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* dns ID */
|
||||||
|
memcpy(rsp, dns->dns_req, 2);
|
||||||
|
/* 问题数 */
|
||||||
|
rsp[4] = 0;
|
||||||
|
rsp[5] = 1;
|
||||||
|
/* 资源记录数 */
|
||||||
|
rsp[6] = 0;
|
||||||
|
rsp[7] = 0;
|
||||||
|
/* 授权资源记录数 */
|
||||||
|
rsp[8] = 0;
|
||||||
|
rsp[9] = 0;
|
||||||
|
/* 额外资源记录数 */
|
||||||
|
rsp[10] = 0;
|
||||||
|
rsp[11] = 0;
|
||||||
|
memcpy(rsp + 12, dns->dns_req + 12, dns->host_len + 6);
|
||||||
|
/* 如果有回应内容(资源记录) */
|
||||||
|
if (rspIp) {
|
||||||
|
p = rsp + 18 + dns->host_len;
|
||||||
|
/* 资源记录数+1 */
|
||||||
|
rsp[7]++;
|
||||||
|
/* 成功标志 */
|
||||||
|
rsp[2] = (char)133;
|
||||||
|
rsp[3] = (char)128;
|
||||||
|
/* 指向主机域名 */
|
||||||
|
p[0] = (char)192;
|
||||||
|
p[1] = 12;
|
||||||
|
/* 回应类型 */
|
||||||
|
p[2] = 0;
|
||||||
|
p[3] = dns->query_type;
|
||||||
|
/* 区域类别 */
|
||||||
|
p[4] = 0;
|
||||||
|
p[5] = 1;
|
||||||
|
/* 生存时间 (1 ora) */
|
||||||
|
p[6] = 0;
|
||||||
|
p[7] = 0;
|
||||||
|
p[8] = 14;
|
||||||
|
p[9] = 16;
|
||||||
|
/* 回应长度 */
|
||||||
|
p[10] = 0;
|
||||||
|
p[11] = 4;
|
||||||
|
memcpy(p + 12, rspIp, 4);
|
||||||
|
} else {
|
||||||
|
/* 失败标志 */
|
||||||
|
rsp[2] = (char)129;
|
||||||
|
rsp[3] = (char)130;
|
||||||
|
}
|
||||||
|
|
||||||
|
//因为UDP是无连接协议,所以不做返回值判断
|
||||||
|
sendto(global.dns_listen_fd, rsp, rsp_len, 0, (struct sockaddr *)&dns->src_addr, sizeof(struct sockaddr_in));
|
||||||
|
printf("receive from %s\n", inet_ntoa(dns->src_addr.sin_addr));
|
||||||
|
dns->query_type = 0; //表示结构体空闲
|
||||||
|
if (cfp && rspIp)
|
||||||
|
cache_record(dns->dns_req, dns->dns_req_len, rsp, rsp_len);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dns_timeout_check()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < DNS_MAX_CONCURRENT; i++) {
|
||||||
|
if (dns_list[i].fd > -1) {
|
||||||
|
if (dns_list[i].timer >= global.timeout_m) {
|
||||||
|
dnsProxyStop(dns_list + i);
|
||||||
|
} else {
|
||||||
|
dns_list[i].timer++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void http_out(dns_t * out)
|
||||||
|
{
|
||||||
|
int write_len;
|
||||||
|
|
||||||
|
out->timer = 0;
|
||||||
|
if (httpdns.connect_request && out->sent_CONNECT_len < httpdns.connect_request_len) {
|
||||||
|
write_len = write(out->fd, httpdns.connect_request + out->sent_CONNECT_len, httpdns.connect_request_len - out->sent_CONNECT_len);
|
||||||
|
if (write_len == -1) {
|
||||||
|
dnsProxyStop(out);
|
||||||
|
} else {
|
||||||
|
out->sent_CONNECT_len += write_len;
|
||||||
|
if (out->sent_CONNECT_len == httpdns.connect_request_len) {
|
||||||
|
out->sent_CONNECT_len++; //表示已完全发送CONNECT请求,等待HTTP回应
|
||||||
|
dns_ev.events = EPOLLIN | EPOLLET;
|
||||||
|
dns_ev.data.ptr = out;
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_MOD, out->fd, &dns_ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_len = write(out->fd, out->out_request, out->out_request_len);
|
||||||
|
if (write_len == out->out_request_len) {
|
||||||
|
dns_ev.events = EPOLLIN | EPOLLET;
|
||||||
|
dns_ev.data.ptr = out;
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_MOD, out->fd, &dns_ev);
|
||||||
|
} else if (write_len > 0) {
|
||||||
|
out->out_request_len -= write_len;
|
||||||
|
memmove(out->out_request, out->out_request + write_len, out->out_request_len);
|
||||||
|
} else {
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_DEL, out->fd, NULL);
|
||||||
|
close(out->fd);
|
||||||
|
out->query_type = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_httpDNS_rsp(dns_t * dns, char *rsp, int rsp_len)
|
||||||
|
{
|
||||||
|
char *ip_ptr, *p, ip[4];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = strstr(rsp, "\n\r");
|
||||||
|
if (p) {
|
||||||
|
p += 3;
|
||||||
|
rsp_len -= p - rsp;
|
||||||
|
//部分代理服务器使用长连接,第二次读取数据才读到域名的IP
|
||||||
|
if (rsp_len <= 0)
|
||||||
|
return;
|
||||||
|
rsp = p;
|
||||||
|
}
|
||||||
|
printf("%s\n", rsp);
|
||||||
|
if (httpdns.encodeCode)
|
||||||
|
dataEncode(rsp, rsp_len, httpdns.encodeCode);
|
||||||
|
do {
|
||||||
|
if (*rsp == '\n')
|
||||||
|
rsp++;
|
||||||
|
/* 匹配IP */
|
||||||
|
while ((*rsp > 57 || *rsp < 49) && *rsp != '\0')
|
||||||
|
rsp++;
|
||||||
|
for (i = 0, ip_ptr = rsp, rsp = strchr(ip_ptr, '.');; ip_ptr = rsp + 1, rsp = strchr(ip_ptr, '.')) {
|
||||||
|
if (i < 3) {
|
||||||
|
if (rsp == NULL) {
|
||||||
|
printf("111111111111111111111111111111111111111111111111111111111111111111111111111\n");
|
||||||
|
httpDNS_respond_client(dns, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//查找下一行
|
||||||
|
if (rsp - ip_ptr > 3)
|
||||||
|
break;
|
||||||
|
ip[i++] = atoi(ip_ptr);
|
||||||
|
} else {
|
||||||
|
printf("22222222222222222222222222222222222222222222222222222222222222222222222222222222222222\n");
|
||||||
|
ip[3] = atoi(ip_ptr);
|
||||||
|
httpDNS_respond_client(dns, ip);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((rsp = strchr(rsp, '\n')) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_tcpDNS_rsp(dns_t * dns, char *rsp, int rsp_len)
|
||||||
|
{
|
||||||
|
/* 转换为UDPdns请求(为什么不做长度判断?因为懒) */
|
||||||
|
rsp += 2;
|
||||||
|
rsp_len -= 2;
|
||||||
|
//回应客户端
|
||||||
|
sendto(global.dns_listen_fd, rsp, rsp_len, 0, (struct sockaddr *)&dns->src_addr, sizeof(struct sockaddr_in));
|
||||||
|
if (cfp && (unsigned char)rsp[3] == 128) {
|
||||||
|
//如果使用编码,则需要还原dns请求
|
||||||
|
if (httpdns.httpsProxy_encodeCode)
|
||||||
|
dataEncode(dns->dns_req + 2 /* 换成TCPDNS请求时原本请求后移动了2字节 */ , dns->dns_req_len, httpdns.httpsProxy_encodeCode);
|
||||||
|
cache_record(dns->dns_req + 2, dns->dns_req_len, rsp, (uint16_t) rsp_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void http_in(dns_t * in)
|
||||||
|
{
|
||||||
|
static char http_rsp[HTTP_RSP_SIZE + 1];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
in->timer = 0;
|
||||||
|
if (httpdns.connect_request && in->sent_CONNECT_len > httpdns.connect_request_len) {
|
||||||
|
in->sent_CONNECT_len--;
|
||||||
|
do {
|
||||||
|
len = read(in->fd, http_rsp, HTTP_RSP_SIZE);
|
||||||
|
//没有数据读取,CONNECT代理连接完成
|
||||||
|
if (len < 0 && errno == EAGAIN)
|
||||||
|
break;
|
||||||
|
if (len <= 0) {
|
||||||
|
dnsProxyStop(in);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while (len == HTTP_RSP_SIZE);
|
||||||
|
dns_ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
|
||||||
|
dns_ev.data.ptr = in;
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_MOD, in->fd, &dns_ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
len = read(in->fd, http_rsp, HTTP_RSP_SIZE);
|
||||||
|
if (len <= 0) {
|
||||||
|
if (len == 0 || errno != EAGAIN)
|
||||||
|
dnsProxyStop(in);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
http_rsp[len] = '\0';
|
||||||
|
if (httpdns.httpsProxy_encodeCode)
|
||||||
|
dataEncode(http_rsp, len, httpdns.httpsProxy_encodeCode);
|
||||||
|
if (httpdns.tcpDNS_mode == 1) {
|
||||||
|
handle_tcpDNS_rsp(in, http_rsp, len);
|
||||||
|
} else {
|
||||||
|
handle_httpDNS_rsp(in, http_rsp, len);
|
||||||
|
}
|
||||||
|
dnsProxyStop(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t create_outRequest(dns_t * dns)
|
||||||
|
{
|
||||||
|
if (parse_dns_request(dns->dns_req, dns) != 0) {
|
||||||
|
dns->out_request = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (httpdns.tcpDNS_mode == 1) {
|
||||||
|
memmove(dns->dns_req + 2, dns->dns_req, dns->dns_req_len);
|
||||||
|
dns->dns_req[0] = *((char *)(&dns->dns_req_len) + 1);
|
||||||
|
dns->dns_req[1] = *((char *)&dns->dns_req_len);
|
||||||
|
dns->out_request = dns->dns_req;
|
||||||
|
dns->out_request_len = dns->dns_req_len + 2;
|
||||||
|
dns->host = NULL;
|
||||||
|
/*
|
||||||
|
//调试用
|
||||||
|
int i;
|
||||||
|
printf("(");
|
||||||
|
for (i=0;i<dns->out_request_len;i++)
|
||||||
|
printf("%u ", dns->out_request[i]);
|
||||||
|
puts(")");
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
if (httpdns.encodeCode)
|
||||||
|
dataEncode(dns->host, dns->host_len, httpdns.encodeCode);
|
||||||
|
dns->out_request_len = httpdns.http_req_len;
|
||||||
|
copy_new_mem(httpdns.http_req, httpdns.http_req_len, &dns->out_request);
|
||||||
|
dns->out_request = replace(dns->out_request, &dns->out_request_len, "[D]", 3, dns->host, dns->host_len);
|
||||||
|
printf("%s", dns->out_request);
|
||||||
|
free(dns->host);
|
||||||
|
if (dns->out_request == NULL)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (httpdns.httpsProxy_encodeCode)
|
||||||
|
dataEncode(dns->out_request, dns->out_request_len, httpdns.httpsProxy_encodeCode);
|
||||||
|
dns->sent_CONNECT_len = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 连接到dns服务器 */
|
||||||
|
static int connectToDnsServer(dns_t * dns)
|
||||||
|
{
|
||||||
|
dns->fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
if (dns->fd < 0)
|
||||||
|
return 1;
|
||||||
|
dns->timer = 0; //超时计时器设为0
|
||||||
|
fcntl(dns->fd, F_SETFL, O_NONBLOCK);
|
||||||
|
dns_ev.events = EPOLLERR | EPOLLOUT | EPOLLET;
|
||||||
|
dns_ev.data.ptr = dns;
|
||||||
|
if (epoll_ctl(dns_efd, EPOLL_CTL_ADD, dns->fd, &dns_ev) != 0) {
|
||||||
|
close(dns->fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (connect(dns->fd, (struct sockaddr *)&httpdns.dst, sizeof(httpdns.dst)) != 0 && errno != EINPROGRESS) {
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_DEL, dns->fd, NULL);
|
||||||
|
close(dns->fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void new_client()
|
||||||
|
{
|
||||||
|
dns_t *dns;
|
||||||
|
socklen_t addr_len = sizeof(struct sockaddr_in);
|
||||||
|
int i, len;
|
||||||
|
|
||||||
|
for (i = 0; i < DNS_MAX_CONCURRENT; i++) {
|
||||||
|
if (dns_list[i].query_type == 0) {
|
||||||
|
dns = &dns_list[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == DNS_MAX_CONCURRENT)
|
||||||
|
return;
|
||||||
|
len = recvfrom(global.dns_listen_fd, dns->dns_req, DNS_REQUEST_MAX_SIZE - 2, 0, (struct sockaddr *)&dns->src_addr, &addr_len);
|
||||||
|
//dns请求必须大于18
|
||||||
|
if (len <= 18)
|
||||||
|
return;
|
||||||
|
dns->dns_req_len = (uint16_t) len;
|
||||||
|
/* 查询缓存 */
|
||||||
|
if (cfp && cache_lookup(dns) == 0)
|
||||||
|
return;
|
||||||
|
if (create_outRequest(dns) != 0 || connectToDnsServer(dns) != 0) {
|
||||||
|
printf("33333333333333333333333333333333333333333333333333\n");
|
||||||
|
if (dns->out_request != dns->dns_req)
|
||||||
|
free(dns->out_request);
|
||||||
|
httpDNS_respond_client(dns, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void httpRequest_init()
|
||||||
|
{
|
||||||
|
char dest[22];
|
||||||
|
uint16_t port;
|
||||||
|
|
||||||
|
port = ntohs(httpdns.dst.sin_port);
|
||||||
|
sprintf(dest, "%s:%u", inet_ntoa(httpdns.dst.sin_addr), port);
|
||||||
|
|
||||||
|
//如果设置http_req = "";则不创建请求头
|
||||||
|
if (httpdns.http_req_len > 0) {
|
||||||
|
printf("333333333333333333333333333333333333\n");
|
||||||
|
httpdns.http_req_len = strlen(httpdns.http_req);
|
||||||
|
httpdns.http_req_len += 2;
|
||||||
|
httpdns.http_req = (char *)realloc(httpdns.http_req, httpdns.http_req_len + 1);
|
||||||
|
if (httpdns.http_req == NULL)
|
||||||
|
error("out of memory.");
|
||||||
|
strcat(httpdns.http_req, "\r\n");
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[V]", 3, "HTTP/1.1", 8);
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[H]", 3, dest, strlen(dest));
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "\\0", 2, "\0", 1);
|
||||||
|
if (httpdns.tcpDNS_mode == 0) {
|
||||||
|
printf("666666666666666666666666666666666666666666\n");
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[M]", 3, "GET", 3);
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[url]", 5, "/d?dn=[D]", 9);
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[U]", 3, "/d?dn=[D]", 9);
|
||||||
|
if (httpdns.http_req == NULL)
|
||||||
|
error("out of memory.");
|
||||||
|
} else {
|
||||||
|
printf("77777777777777777777777777777777777777777777777\n");
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[M]", 3, "CONNECT", 7);
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[url]", 5, "/", 1);
|
||||||
|
httpdns.http_req = replace(httpdns.http_req, &httpdns.http_req_len, "[U]", 3, "/", 1);
|
||||||
|
if (httpdns.http_req == NULL)
|
||||||
|
error("out of memory.");
|
||||||
|
httpdns.connect_request = httpdns.http_req;
|
||||||
|
httpdns.connect_request_len = httpdns.http_req_len;
|
||||||
|
httpdns.http_req = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// 保存原始请求,配合use_hdr语法
|
||||||
|
if (saveHdrs)
|
||||||
|
{
|
||||||
|
if (httpdns.http_req_len > 0)
|
||||||
|
{
|
||||||
|
printf("9999999999999999999999999999999999999\n");
|
||||||
|
if (copy_new_mem(httpdns.http_req, httpdns.http_req_len, &httpdns.original_http_req) != 0)
|
||||||
|
error("out of memory.");
|
||||||
|
httpdns.original_http_req_len = httpdns.http_req_len;
|
||||||
|
}
|
||||||
|
if (httpdns.connect_request)
|
||||||
|
{
|
||||||
|
printf("00000000000000000000000000000000000000000\n");
|
||||||
|
if (copy_new_mem(httpdns.connect_request, httpdns.connect_request_len, &httpdns.original_connect_request) != 0)
|
||||||
|
error("out of memory.");
|
||||||
|
httpdns.original_connect_request_len = httpdns.connect_request_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void dns_init()
|
||||||
|
{
|
||||||
|
httpRequest_init();
|
||||||
|
dns_efd = epoll_create(DNS_MAX_CONCURRENT + 1);
|
||||||
|
if (dns_efd < 0) {
|
||||||
|
perror("epoll_create");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fcntl(global.dns_listen_fd, F_SETFL, O_NONBLOCK);
|
||||||
|
dns_ev.data.fd = global.dns_listen_fd;
|
||||||
|
dns_ev.events = EPOLLIN;
|
||||||
|
epoll_ctl(dns_efd, EPOLL_CTL_ADD, global.dns_listen_fd, &dns_ev);
|
||||||
|
memset(dns_list, 0, sizeof(dns_list));
|
||||||
|
//程序关闭时写入dns缓存
|
||||||
|
if (cfp) {
|
||||||
|
signal(SIGTERM, write_dns_cache);
|
||||||
|
signal(SIGHUP, write_dns_cache);
|
||||||
|
signal(SIGINT, write_dns_cache);
|
||||||
|
signal(SIGABRT, write_dns_cache);
|
||||||
|
signal(SIGILL, write_dns_cache);
|
||||||
|
signal(SIGSEGV, write_dns_cache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *dns_loop(void *nullPtr)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
n = epoll_wait(dns_efd, dns_evs, DNS_MAX_CONCURRENT + 1, -1);
|
||||||
|
|
||||||
|
while (n-- > 0) {
|
||||||
|
if (dns_evs[n].data.fd == global.dns_listen_fd) {
|
||||||
|
new_client();
|
||||||
|
} else {
|
||||||
|
if (dns_evs[n].events & EPOLLIN) {
|
||||||
|
http_in((dns_t *) dns_evs[n].data.ptr);
|
||||||
|
}
|
||||||
|
if (dns_evs[n].events & EPOLLOUT) {
|
||||||
|
http_out((dns_t *) dns_evs[n].data.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; //消除编译警告
|
||||||
|
}
|
9
httpdns.conf
Normal file
9
httpdns.conf
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
global {
|
||||||
|
uid = 3004;
|
||||||
|
dns_listen = 126;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpdns {
|
||||||
|
addr = 119.29.29.29;
|
||||||
|
http_req = "[M] [U] [V]\r\nHost: [H]\r\n";
|
||||||
|
}
|
26
httpdns.h
Normal file
26
httpdns.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef HTTPDNS_H
|
||||||
|
#define HTTPDNS_H
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#define HTTPDNS_REQUEST "GET /d?dn=[D] HTTP/1.0\r\nHost: [H]\r\n\r\n"
|
||||||
|
|
||||||
|
struct httpdns {
|
||||||
|
struct sockaddr_in dst;
|
||||||
|
char *http_req, *original_http_req, *connect_request, *original_connect_request, *cachePath, *ssl_request; //original_http_req, original_connect_request为初始化生成的请求头,用来配合use_hdr语法
|
||||||
|
int http_req_len, original_http_req_len, connect_request_len, original_connect_request_len, cacheLimit, ssl_request_len;
|
||||||
|
unsigned encodeCode, //Host编码传输
|
||||||
|
httpsProxy_encodeCode, //CONNECT代理编码
|
||||||
|
tcpDNS_mode:1; //判断是否开启TCPDNS
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void dns_timeout_check();
|
||||||
|
extern void *dns_loop(void *nullPtr);
|
||||||
|
extern int8_t read_cache_file();
|
||||||
|
extern void dns_init();
|
||||||
|
|
||||||
|
extern struct httpdns httpdns;
|
||||||
|
extern pid_t child_pid;
|
||||||
|
extern FILE *cfp;
|
||||||
|
|
||||||
|
#endif
|
BIN
httpdns.o
Normal file
BIN
httpdns.o
Normal file
Binary file not shown.
BIN
libs/arm64-v8a/httpdns
Normal file
BIN
libs/arm64-v8a/httpdns
Normal file
Binary file not shown.
BIN
libs/armeabi-v7a/httpdns
Normal file
BIN
libs/armeabi-v7a/httpdns
Normal file
Binary file not shown.
167
main.c
Normal file
167
main.c
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include <dirent.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#define SERVICE_TYPE_STOP 1
|
||||||
|
#define SERVICE_TYPE_STATUS 2
|
||||||
|
#define SERVICE_TYPE_STATUS_NOT_PRINT 3
|
||||||
|
|
||||||
|
struct global global;
|
||||||
|
uint16_t tcp_listen_port;
|
||||||
|
struct httpudp udp;
|
||||||
|
|
||||||
|
static char *get_proc_name(char *path)
|
||||||
|
{
|
||||||
|
char proc_name[257];
|
||||||
|
FILE *fp;
|
||||||
|
int readsize;
|
||||||
|
|
||||||
|
fp = fopen(path, "r");
|
||||||
|
if (fp == NULL)
|
||||||
|
return NULL;
|
||||||
|
readsize = fread(proc_name, 1, 256, fp);
|
||||||
|
fclose(fp);
|
||||||
|
return strndup(proc_name, readsize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t additional_service(char *self_name, uint8_t service_type)
|
||||||
|
{
|
||||||
|
char commpath[270];
|
||||||
|
DIR *DP;
|
||||||
|
struct dirent *dp;
|
||||||
|
char *proc_name;
|
||||||
|
pid_t self_pid;
|
||||||
|
|
||||||
|
DP = opendir("/proc");
|
||||||
|
if (DP == NULL)
|
||||||
|
return 1;
|
||||||
|
proc_name = strrchr(self_name, '/');
|
||||||
|
if (proc_name)
|
||||||
|
self_name = proc_name + 1;
|
||||||
|
self_pid = getpid();
|
||||||
|
while ((dp = readdir(DP)) != NULL) {
|
||||||
|
if (dp->d_type != DT_DIR)
|
||||||
|
continue;
|
||||||
|
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0 || atoi(dp->d_name) == self_pid)
|
||||||
|
continue;
|
||||||
|
sprintf(commpath, "/proc/%s/comm", dp->d_name);
|
||||||
|
proc_name = get_proc_name(commpath);
|
||||||
|
if (proc_name == NULL)
|
||||||
|
continue;
|
||||||
|
if (strcmp(proc_name, self_name) == 0) {
|
||||||
|
if (service_type == SERVICE_TYPE_STOP)
|
||||||
|
kill(atoi(dp->d_name), SIGTERM);
|
||||||
|
else {
|
||||||
|
free(proc_name);
|
||||||
|
closedir(DP);
|
||||||
|
if (service_type != SERVICE_TYPE_STATUS_NOT_PRINT)
|
||||||
|
LOG(RED "%s(" VERSION ") 正在运行\n" NONE, self_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(proc_name);
|
||||||
|
}
|
||||||
|
closedir(DP);
|
||||||
|
|
||||||
|
if (service_type == SERVICE_TYPE_STATUS)
|
||||||
|
LOG(RED "%s(" VERSION ") 没有运行\n" NONE, self_name);
|
||||||
|
else if (service_type == SERVICE_TYPE_STATUS_NOT_PRINT)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *timeout_check(void *nullPtr)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
sleep(60);
|
||||||
|
if (global.dns_listen_fd >= 0)
|
||||||
|
dns_timeout_check();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 初始化变量 */
|
||||||
|
static void initVariable()
|
||||||
|
{
|
||||||
|
memset(&global, 0, sizeof(global));
|
||||||
|
memset(&httpdns, 0, sizeof(httpdns));
|
||||||
|
|
||||||
|
//saveHdrs = NULL;
|
||||||
|
httpdns.dst.sin_family = AF_INET;
|
||||||
|
//http.dst.sin_family = https.dst.sin_family = httpdns.dst.sin_family = AF_INET;
|
||||||
|
global.tcp_listen_fd = global.dns_listen_fd = global.udp_listen_fd = global.uid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_cmd(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* 命令行选项 */
|
||||||
|
if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
|
||||||
|
printf(RED "HttpDNS(" VERSION ")\n"
|
||||||
|
"Author: aixiao@aixiao.me, mmmdbybyd.\n"
|
||||||
|
"\n"
|
||||||
|
"启动命令:\n httpdns httpdns.conf\n"
|
||||||
|
"结束命令:\n httpdns stop\n"
|
||||||
|
"检测命令:\n httpdns status\n"
|
||||||
|
"重启命令:\n httpdns restart httpdns.conf\n"
|
||||||
|
"\n" NONE);
|
||||||
|
exit(argc < 2 ? 1 : 0);
|
||||||
|
}
|
||||||
|
if (strcasecmp(argv[1], "stop") == 0)
|
||||||
|
exit(additional_service(argv[0], SERVICE_TYPE_STOP));
|
||||||
|
else if (strcasecmp(argv[1], "status") == 0)
|
||||||
|
exit(additional_service(argv[0], SERVICE_TYPE_STATUS));
|
||||||
|
else if (strcasecmp(argv[1], "restart") == 0) {
|
||||||
|
additional_service(argv[0], SERVICE_TYPE_STOP);
|
||||||
|
while (additional_service(argv[0], SERVICE_TYPE_STATUS_NOT_PRINT) == 0) ;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
read_conf(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void server_init()
|
||||||
|
{
|
||||||
|
/* 忽略PIPE信号 */
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
//不能用setgid和setuid,这两个函数不能切换回root,可能导致HTTPUDP代理失败
|
||||||
|
if (global.uid > -1 && (setegid(global.uid) == -1 || seteuid(global.uid) == -1)) {
|
||||||
|
perror("setegid(or seteuid)");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#ifndef DEBUG
|
||||||
|
if (daemon(1, 1) == -1) {
|
||||||
|
perror("daemon");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
一个进程只开一个子进程,
|
||||||
|
程序结束时子进程先写入dns缓存,
|
||||||
|
之后主进程再写入,
|
||||||
|
否则可能导致缓存文件格式错误
|
||||||
|
*/
|
||||||
|
while (global.procs-- > 1 && (child_pid = fork()) == 0) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void start_server_loop()
|
||||||
|
{
|
||||||
|
pthread_t thread_id;
|
||||||
|
|
||||||
|
if (global.timeout_m)
|
||||||
|
pthread_create(&thread_id, NULL, &timeout_check, NULL);
|
||||||
|
|
||||||
|
if (global.dns_listen_fd >= 0) {
|
||||||
|
dns_init();
|
||||||
|
dns_loop(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
initVariable();
|
||||||
|
handle_cmd(argc, argv);
|
||||||
|
server_init();
|
||||||
|
start_server_loop();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
73
main.h
Normal file
73
main.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include "common.h"
|
||||||
|
#include "httpdns.h"
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
// 字体颜色
|
||||||
|
#define NONE "\033[m"
|
||||||
|
#define RED "\033[0;32;31m"
|
||||||
|
#define LIGHT_RED "\033[1;31m"
|
||||||
|
#define GREEN "\033[0;32;32m"
|
||||||
|
#define LIGHT_GREEN "\033[1;32m"
|
||||||
|
#define BLUE "\033[0;32;34m"
|
||||||
|
#define LIGHT_BLUE "\033[1;34m"
|
||||||
|
#define DARY_GRAY "\033[1;30m"
|
||||||
|
#define CYAN "\033[0;36m"
|
||||||
|
#define LIGHT_CYAN "\033[1;36m"
|
||||||
|
#define PURPLE "\033[0;35m"
|
||||||
|
#define LIGHT_PURPLE "\033[1;35m"
|
||||||
|
#define BROWN "\033[0;33m"
|
||||||
|
#define YELLOW "\033[1;33m"
|
||||||
|
#define LIGHT_GRAY "\033[0;37m"
|
||||||
|
#define WHITE "\033[1;37m"
|
||||||
|
|
||||||
|
#define LOG(fmt...) do { fprintf(stderr, ##fmt); } while(0)
|
||||||
|
|
||||||
|
/* 数据类型 */
|
||||||
|
#define OTHER 1
|
||||||
|
#define HTTP 2
|
||||||
|
#define HTTP_OTHERS 3
|
||||||
|
#define HTTP_CONNECT 4
|
||||||
|
/* 处理TCP请求模式 */
|
||||||
|
#define WAP 1
|
||||||
|
#define WAP_CONNECT 2
|
||||||
|
#define NET_CONNECT 3
|
||||||
|
#define NET_PROXY 4
|
||||||
|
|
||||||
|
struct httpudp {
|
||||||
|
struct sockaddr_in dst;
|
||||||
|
char *http_request, *original_http_request; //original_http_request为初始化生成的请求头,用来配合use_hdr语法
|
||||||
|
int http_request_len, original_http_request_len;
|
||||||
|
unsigned encodeCode, //数据编码传输
|
||||||
|
httpsProxy_encodeCode; //CONNECT代理编码
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct connection {
|
||||||
|
struct sockaddr_in original_dst;
|
||||||
|
char *ready_data; //已就绪的数据,可以发送
|
||||||
|
char *incomplete_data; //存放不是完整的请求头
|
||||||
|
char *host;
|
||||||
|
char *connect; //存放CONNECT请求
|
||||||
|
int connect_len; //CONNECT请求的长度
|
||||||
|
int incomplete_data_len, ready_data_len, sent_len, fd, timer;
|
||||||
|
uint16_t original_port;
|
||||||
|
unsigned reqType:3, //请求类型
|
||||||
|
first_connection:1, //发送客户端数据前是否首先进行CONNECT连接
|
||||||
|
is_httpsProxy:1; //如果真 则表示连接是走HTTPS模块
|
||||||
|
} tcp_t;
|
||||||
|
|
||||||
|
struct global {
|
||||||
|
int tcp_listen_fd, dns_listen_fd, udp_listen_fd, uid, procs, timeout_m;
|
||||||
|
unsigned mode:3, strict_modify:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct global global;
|
||||||
|
|
||||||
|
extern uint16_t tcp_listen_port;
|
||||||
|
extern struct httpudp udp;
|
||||||
|
|
||||||
|
#endif
|
BIN
main.o
Normal file
BIN
main.o
Normal file
Binary file not shown.
BIN
obj/local/arm64-v8a/httpdns
Normal file
BIN
obj/local/arm64-v8a/httpdns
Normal file
Binary file not shown.
BIN
obj/local/arm64-v8a/objs/httpdns/common.o
Normal file
BIN
obj/local/arm64-v8a/objs/httpdns/common.o
Normal file
Binary file not shown.
10
obj/local/arm64-v8a/objs/httpdns/common.o.d
Normal file
10
obj/local/arm64-v8a/objs/httpdns/common.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/arm64-v8a/objs/httpdns/common.o: common.c common.h main.h \
|
||||||
|
httpdns.h conf.h
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
httpdns.h:
|
||||||
|
|
||||||
|
conf.h:
|
BIN
obj/local/arm64-v8a/objs/httpdns/conf.o
Normal file
BIN
obj/local/arm64-v8a/objs/httpdns/conf.o
Normal file
Binary file not shown.
10
obj/local/arm64-v8a/objs/httpdns/conf.o.d
Normal file
10
obj/local/arm64-v8a/objs/httpdns/conf.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/arm64-v8a/objs/httpdns/conf.o: conf.c conf.h main.h common.h \
|
||||||
|
httpdns.h
|
||||||
|
|
||||||
|
conf.h:
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
httpdns.h:
|
BIN
obj/local/arm64-v8a/objs/httpdns/httpdns.o
Normal file
BIN
obj/local/arm64-v8a/objs/httpdns/httpdns.o
Normal file
Binary file not shown.
10
obj/local/arm64-v8a/objs/httpdns/httpdns.o.d
Normal file
10
obj/local/arm64-v8a/objs/httpdns/httpdns.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/arm64-v8a/objs/httpdns/httpdns.o: httpdns.c httpdns.h main.h \
|
||||||
|
common.h conf.h
|
||||||
|
|
||||||
|
httpdns.h:
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
conf.h:
|
BIN
obj/local/arm64-v8a/objs/httpdns/main.o
Normal file
BIN
obj/local/arm64-v8a/objs/httpdns/main.o
Normal file
Binary file not shown.
10
obj/local/arm64-v8a/objs/httpdns/main.o.d
Normal file
10
obj/local/arm64-v8a/objs/httpdns/main.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/arm64-v8a/objs/httpdns/main.o: main.c main.h common.h \
|
||||||
|
httpdns.h conf.h
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
httpdns.h:
|
||||||
|
|
||||||
|
conf.h:
|
BIN
obj/local/armeabi-v7a/httpdns
Normal file
BIN
obj/local/armeabi-v7a/httpdns
Normal file
Binary file not shown.
BIN
obj/local/armeabi-v7a/objs/httpdns/common.o
Normal file
BIN
obj/local/armeabi-v7a/objs/httpdns/common.o
Normal file
Binary file not shown.
10
obj/local/armeabi-v7a/objs/httpdns/common.o.d
Normal file
10
obj/local/armeabi-v7a/objs/httpdns/common.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/armeabi-v7a/objs/httpdns/common.o: common.c common.h main.h \
|
||||||
|
httpdns.h conf.h
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
httpdns.h:
|
||||||
|
|
||||||
|
conf.h:
|
BIN
obj/local/armeabi-v7a/objs/httpdns/conf.o
Normal file
BIN
obj/local/armeabi-v7a/objs/httpdns/conf.o
Normal file
Binary file not shown.
10
obj/local/armeabi-v7a/objs/httpdns/conf.o.d
Normal file
10
obj/local/armeabi-v7a/objs/httpdns/conf.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/armeabi-v7a/objs/httpdns/conf.o: conf.c conf.h main.h \
|
||||||
|
common.h httpdns.h
|
||||||
|
|
||||||
|
conf.h:
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
httpdns.h:
|
BIN
obj/local/armeabi-v7a/objs/httpdns/httpdns.o
Normal file
BIN
obj/local/armeabi-v7a/objs/httpdns/httpdns.o
Normal file
Binary file not shown.
10
obj/local/armeabi-v7a/objs/httpdns/httpdns.o.d
Normal file
10
obj/local/armeabi-v7a/objs/httpdns/httpdns.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/armeabi-v7a/objs/httpdns/httpdns.o: httpdns.c httpdns.h \
|
||||||
|
main.h common.h conf.h
|
||||||
|
|
||||||
|
httpdns.h:
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
conf.h:
|
BIN
obj/local/armeabi-v7a/objs/httpdns/main.o
Normal file
BIN
obj/local/armeabi-v7a/objs/httpdns/main.o
Normal file
Binary file not shown.
10
obj/local/armeabi-v7a/objs/httpdns/main.o.d
Normal file
10
obj/local/armeabi-v7a/objs/httpdns/main.o.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
./obj/local/armeabi-v7a/objs/httpdns/main.o: main.c main.h common.h \
|
||||||
|
httpdns.h conf.h
|
||||||
|
|
||||||
|
main.h:
|
||||||
|
|
||||||
|
common.h:
|
||||||
|
|
||||||
|
httpdns.h:
|
||||||
|
|
||||||
|
conf.h:
|
Loading…
x
Reference in New Issue
Block a user