commit 2b6118268c60540c2c771630c41d1224a06cd42b Author: aixiao Date: Sat Jun 12 09:50:56 2021 +0800 initial diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..e8816f6 --- /dev/null +++ b/Android.mk @@ -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) diff --git a/Application.mk b/Application.mk new file mode 100644 index 0000000..75d4de5 --- /dev/null +++ b/Application.mk @@ -0,0 +1,2 @@ +APP_ABI = arm64-v8a armeabi-v7a +APP_PLATFORM = android-29 \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9d78f79 --- /dev/null +++ b/Makefile @@ -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 \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb4c4e6 --- /dev/null +++ b/README.md @@ -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 + diff --git a/common.c b/common.c new file mode 100644 index 0000000..5b32013 --- /dev/null +++ b/common.c @@ -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; +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..ad5af9d --- /dev/null +++ b/common.h @@ -0,0 +1,24 @@ +#ifndef COMMON_H +#define COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 diff --git a/common.o b/common.o new file mode 100644 index 0000000..3d290e6 Binary files /dev/null and b/common.o differ diff --git a/conf.c b/conf.c new file mode 100644 index 0000000..025f769 --- /dev/null +++ b/conf.c @@ -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); + } + +} diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..d1cc8ba --- /dev/null +++ b/conf.h @@ -0,0 +1,10 @@ +#ifndef CONF_H +#define CONF_H + +#include +#include +#include "main.h" + +extern void read_conf(char *path); + +#endif diff --git a/conf.o b/conf.o new file mode 100644 index 0000000..6638085 Binary files /dev/null and b/conf.o differ diff --git a/httpdns b/httpdns new file mode 100644 index 0000000..f550f43 Binary files /dev/null and b/httpdns differ diff --git a/httpdns.c b/httpdns.c new file mode 100644 index 0000000..967219a --- /dev/null +++ b/httpdns.c @@ -0,0 +1,633 @@ +#include +#include +#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;iout_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; //消除编译警告 +} diff --git a/httpdns.conf b/httpdns.conf new file mode 100644 index 0000000..10c9d5d --- /dev/null +++ b/httpdns.conf @@ -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"; +} diff --git a/httpdns.h b/httpdns.h new file mode 100644 index 0000000..7c3962b --- /dev/null +++ b/httpdns.h @@ -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 diff --git a/httpdns.o b/httpdns.o new file mode 100644 index 0000000..9a6de37 Binary files /dev/null and b/httpdns.o differ diff --git a/libs/arm64-v8a/httpdns b/libs/arm64-v8a/httpdns new file mode 100644 index 0000000..da79592 Binary files /dev/null and b/libs/arm64-v8a/httpdns differ diff --git a/libs/armeabi-v7a/httpdns b/libs/armeabi-v7a/httpdns new file mode 100644 index 0000000..b403418 Binary files /dev/null and b/libs/armeabi-v7a/httpdns differ diff --git a/main.c b/main.c new file mode 100644 index 0000000..fe89d3c --- /dev/null +++ b/main.c @@ -0,0 +1,167 @@ +#include +#include +#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; +} diff --git a/main.h b/main.h new file mode 100644 index 0000000..1532819 --- /dev/null +++ b/main.h @@ -0,0 +1,73 @@ +#ifndef MAIN_H +#define MAIN_H + +#include +#include +#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 diff --git a/main.o b/main.o new file mode 100644 index 0000000..d4906d4 Binary files /dev/null and b/main.o differ diff --git a/obj/local/arm64-v8a/httpdns b/obj/local/arm64-v8a/httpdns new file mode 100644 index 0000000..6107a9b Binary files /dev/null and b/obj/local/arm64-v8a/httpdns differ diff --git a/obj/local/arm64-v8a/objs/httpdns/common.o b/obj/local/arm64-v8a/objs/httpdns/common.o new file mode 100644 index 0000000..998bbb2 Binary files /dev/null and b/obj/local/arm64-v8a/objs/httpdns/common.o differ diff --git a/obj/local/arm64-v8a/objs/httpdns/common.o.d b/obj/local/arm64-v8a/objs/httpdns/common.o.d new file mode 100644 index 0000000..7b0a93d --- /dev/null +++ b/obj/local/arm64-v8a/objs/httpdns/common.o.d @@ -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: diff --git a/obj/local/arm64-v8a/objs/httpdns/conf.o b/obj/local/arm64-v8a/objs/httpdns/conf.o new file mode 100644 index 0000000..6ebac57 Binary files /dev/null and b/obj/local/arm64-v8a/objs/httpdns/conf.o differ diff --git a/obj/local/arm64-v8a/objs/httpdns/conf.o.d b/obj/local/arm64-v8a/objs/httpdns/conf.o.d new file mode 100644 index 0000000..ef77f5d --- /dev/null +++ b/obj/local/arm64-v8a/objs/httpdns/conf.o.d @@ -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: diff --git a/obj/local/arm64-v8a/objs/httpdns/httpdns.o b/obj/local/arm64-v8a/objs/httpdns/httpdns.o new file mode 100644 index 0000000..d145b32 Binary files /dev/null and b/obj/local/arm64-v8a/objs/httpdns/httpdns.o differ diff --git a/obj/local/arm64-v8a/objs/httpdns/httpdns.o.d b/obj/local/arm64-v8a/objs/httpdns/httpdns.o.d new file mode 100644 index 0000000..565b8d1 --- /dev/null +++ b/obj/local/arm64-v8a/objs/httpdns/httpdns.o.d @@ -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: diff --git a/obj/local/arm64-v8a/objs/httpdns/main.o b/obj/local/arm64-v8a/objs/httpdns/main.o new file mode 100644 index 0000000..9b2ad3a Binary files /dev/null and b/obj/local/arm64-v8a/objs/httpdns/main.o differ diff --git a/obj/local/arm64-v8a/objs/httpdns/main.o.d b/obj/local/arm64-v8a/objs/httpdns/main.o.d new file mode 100644 index 0000000..bdd0b23 --- /dev/null +++ b/obj/local/arm64-v8a/objs/httpdns/main.o.d @@ -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: diff --git a/obj/local/armeabi-v7a/httpdns b/obj/local/armeabi-v7a/httpdns new file mode 100644 index 0000000..8383240 Binary files /dev/null and b/obj/local/armeabi-v7a/httpdns differ diff --git a/obj/local/armeabi-v7a/objs/httpdns/common.o b/obj/local/armeabi-v7a/objs/httpdns/common.o new file mode 100644 index 0000000..1df25b5 Binary files /dev/null and b/obj/local/armeabi-v7a/objs/httpdns/common.o differ diff --git a/obj/local/armeabi-v7a/objs/httpdns/common.o.d b/obj/local/armeabi-v7a/objs/httpdns/common.o.d new file mode 100644 index 0000000..fce9324 --- /dev/null +++ b/obj/local/armeabi-v7a/objs/httpdns/common.o.d @@ -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: diff --git a/obj/local/armeabi-v7a/objs/httpdns/conf.o b/obj/local/armeabi-v7a/objs/httpdns/conf.o new file mode 100644 index 0000000..c856001 Binary files /dev/null and b/obj/local/armeabi-v7a/objs/httpdns/conf.o differ diff --git a/obj/local/armeabi-v7a/objs/httpdns/conf.o.d b/obj/local/armeabi-v7a/objs/httpdns/conf.o.d new file mode 100644 index 0000000..4bf84ac --- /dev/null +++ b/obj/local/armeabi-v7a/objs/httpdns/conf.o.d @@ -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: diff --git a/obj/local/armeabi-v7a/objs/httpdns/httpdns.o b/obj/local/armeabi-v7a/objs/httpdns/httpdns.o new file mode 100644 index 0000000..aee8ed0 Binary files /dev/null and b/obj/local/armeabi-v7a/objs/httpdns/httpdns.o differ diff --git a/obj/local/armeabi-v7a/objs/httpdns/httpdns.o.d b/obj/local/armeabi-v7a/objs/httpdns/httpdns.o.d new file mode 100644 index 0000000..ab34d17 --- /dev/null +++ b/obj/local/armeabi-v7a/objs/httpdns/httpdns.o.d @@ -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: diff --git a/obj/local/armeabi-v7a/objs/httpdns/main.o b/obj/local/armeabi-v7a/objs/httpdns/main.o new file mode 100644 index 0000000..fa649a9 Binary files /dev/null and b/obj/local/armeabi-v7a/objs/httpdns/main.o differ diff --git a/obj/local/armeabi-v7a/objs/httpdns/main.o.d b/obj/local/armeabi-v7a/objs/httpdns/main.o.d new file mode 100644 index 0000000..690e3e7 --- /dev/null +++ b/obj/local/armeabi-v7a/objs/httpdns/main.o.d @@ -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: