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
|
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
|
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
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
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…
Reference in New Issue
Block a user