删除不必要文件
This commit is contained in:
4
Makefile
4
Makefile
@@ -2,8 +2,8 @@ CROSS_COMPILE ?=
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
CFLAGS += -g -Wall -Iip2region
|
||||
LIBS =
|
||||
BIN := a.out
|
||||
LIBS = -static
|
||||
BIN := denyip
|
||||
|
||||
# 使用shell命令获取库的链接选项
|
||||
LIBPCAP := $(shell pkg-config --libs --static libpcap)
|
||||
|
||||
1
cap.h
1
cap.h
@@ -18,7 +18,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "ip2region/ip2region.h"
|
||||
#include "qqwry/qqwry.h"
|
||||
|
||||
#define RED "\033[31m"
|
||||
#define REDEND "\033[0m"
|
||||
|
||||
317
main.c
317
main.c
@@ -1,317 +0,0 @@
|
||||
#include "main.h"
|
||||
|
||||
char IPSET_LIST[256] = {0};
|
||||
|
||||
void denyip_help()
|
||||
{
|
||||
puts(" DenyIp");
|
||||
puts("Linux system firewall, reject non-Chinese IP");
|
||||
puts("Email: aixiao@aixiao.me");
|
||||
puts("Version: 0.1");
|
||||
puts("Usage: ./denyip [-i eth0|-h|-?] [start|stop] ");
|
||||
puts("Options:");
|
||||
puts(" stop Enable firewall rules");
|
||||
puts(" start Disable firewall rules");
|
||||
|
||||
puts("Parameters:");
|
||||
puts(" -h|? Help info ");
|
||||
puts(" -i interface name");
|
||||
puts("");
|
||||
puts("");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* 处理僵尸进程 */
|
||||
void sigchld_handler(int signal)
|
||||
{
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0) ;
|
||||
}
|
||||
|
||||
void kill_tcpdump_processes()
|
||||
{
|
||||
int result = system("pkill tcpdump"); // 用 pkill 命令终止所有 tcpdump 进程
|
||||
if (result == -1) {
|
||||
perror("Failed to kill tcpdump processes");
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// 进程重启功能
|
||||
void restart_process(pid_t pid1, pid_t pid2, char *argv[])
|
||||
{
|
||||
// 发送 SIGTERM 信号终止两个子进程
|
||||
kill(pid1, SIGTERM);
|
||||
kill(pid2, SIGTERM);
|
||||
|
||||
// 等待子进程完全退出
|
||||
waitpid(pid1, NULL, 0);
|
||||
waitpid(pid2, NULL, 0);
|
||||
|
||||
// 终止 tcpdump 进程
|
||||
kill_tcpdump_processes();
|
||||
|
||||
// 使用 execvp 重新启动程序自身
|
||||
printf("重启进程...\n");
|
||||
execvp(argv[0], argv); // 重新启动程序
|
||||
perror("execvp failed"); // 如果 execvp 出错
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void cleanup_(int signum)
|
||||
{
|
||||
int r;
|
||||
printf("Received signal %d, cleaning up...\n", signum);
|
||||
|
||||
// 终止子进程
|
||||
if (pid1 > 0) {
|
||||
kill(pid1, SIGTERM);
|
||||
}
|
||||
if (pid2 > 0) {
|
||||
kill(pid2, SIGTERM);
|
||||
}
|
||||
|
||||
// 终止所有 tcpdump 进程
|
||||
r = system("pkill tcpdump");
|
||||
if (r == 0) {
|
||||
puts("pkill tcpdump");
|
||||
}
|
||||
|
||||
// 退出主进程
|
||||
exit(0);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
signal(SIGCHLD, sigchld_handler); // 防止子进程变成僵尸进程
|
||||
|
||||
// 主进程设置
|
||||
//prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||
|
||||
// 注册 SIGTERM 信号处理函数
|
||||
signal(SIGTERM, cleanup_);
|
||||
|
||||
char interface[BUFFER] = { 0 };
|
||||
strcpy(interface, "eth0");
|
||||
|
||||
int r;
|
||||
|
||||
// 参数处理
|
||||
if (argc == 2) {
|
||||
if (0 == strcmp(argv[1], "start")) {
|
||||
if ((r = system("iptables -A INPUT -p tcp -m set --match-set root src -j DROP")) == -1) {
|
||||
puts("\"iptables -A INPUT -p tcp -m set --match-set root src -j DROP\" Error!");
|
||||
}
|
||||
exit(0);
|
||||
} else if (0 == strcmp(argv[1], "stop")) {
|
||||
if ((r = system("iptables -D INPUT -p tcp -m set --match-set root src -j DROP")) == -1) {
|
||||
puts("\"iptables -D INPUT -p tcp -m set --match-set root src -j DROP\" Error!");
|
||||
}
|
||||
exit(0);
|
||||
} else if (0 == strcmp(argv[1], "-h")) {
|
||||
denyip_help();
|
||||
} else if (0 == strcmp(argv[1], "-?")) {
|
||||
denyip_help();
|
||||
}
|
||||
}
|
||||
if (argc == 3) {
|
||||
if (0 == strcmp(argv[1], "-i")) {
|
||||
strcpy(interface, argv[2]);
|
||||
}
|
||||
}
|
||||
// 判断运行用户禁止非root用户运行
|
||||
if (geteuid() == 0) {
|
||||
;
|
||||
} else {
|
||||
printf("This process is not running as root.\n");
|
||||
printf("\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// 判断网卡是否存在
|
||||
char command_ifconfig[BUFFER + 20] = { 0 };
|
||||
snprintf(command_ifconfig, BUFFER + 20, "ifconfig %s", interface);
|
||||
// 判断必要命令是否存在
|
||||
if (command_exists(command_ifconfig)) {
|
||||
;
|
||||
} else {
|
||||
puts("The network card does not exist!");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// 后台运行
|
||||
if (daemon(1, 1)) {
|
||||
perror("daemon");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 进程优先级
|
||||
if (-1 == (nice_(-20)))
|
||||
perror("nice_");
|
||||
|
||||
// 哈希集合
|
||||
if ((r = system("ipset create root hash:ip > /dev/null 2>&1")) != -1) {
|
||||
;
|
||||
}
|
||||
|
||||
// 判断必要命令是否存在
|
||||
if (command_exists("which tcpdump")) {
|
||||
;
|
||||
} else {
|
||||
r = system("yum -y install tcpdump > /dev/null 2>&1");
|
||||
r = system("apt -y install tcpdump > /dev/null 2>&1");
|
||||
}
|
||||
|
||||
|
||||
// 子进程
|
||||
pid1 = fork(); // 创建子进程
|
||||
if (pid1 == 0) {
|
||||
while (1) {
|
||||
|
||||
FILE *fp = popen("ipset list root | grep \"Number of entries\" | cut -d : -f 2 | xargs", "r");
|
||||
char line[BUFFER] = { 0 };
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
line[strcspn(line, "\n")] = '\0';
|
||||
}
|
||||
|
||||
if (atoi(line) >= MAXIPSET) {
|
||||
r = system("ipset flush root");
|
||||
}
|
||||
|
||||
printf("%s\n", line);
|
||||
pclose(fp);
|
||||
sleep(3);
|
||||
}
|
||||
}
|
||||
|
||||
// 子进程
|
||||
pid2 = fork(); // 创建子进程
|
||||
if (pid2 == 0) {
|
||||
// 缓冲区用于存储每行的输出
|
||||
char line[BUFFER];
|
||||
// 要执行的命令
|
||||
char command_tcpdump[BUFFER + 256] = { 0 };
|
||||
snprintf(command_tcpdump, BUFFER + 256, "tcpdump -i %s -n 'tcp' | awk '{print $3}' | cut -d '.' -f 1-4", interface);
|
||||
|
||||
// 地域白名单
|
||||
char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||
char qqwry_region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||
char _REGION_LIST_COPY[BUFFER] = { 0 };
|
||||
char QQWRY_REGION_LIST_COPY[BUFFER] = { 0 };
|
||||
|
||||
if (access(xdb_path, F_OK) == -1) { // 判断 ip2region 地址定位库是否存在
|
||||
xdb_path = "ip2region/ip2region.xdb";
|
||||
if (access(xdb_path, F_OK) == -1) {
|
||||
printf("ip2region.xdb DOESN'T EXIST!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// 打开管道来执行命令
|
||||
FILE *fp = popen(command_tcpdump, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 逐行读取命令输出
|
||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||
line[strcspn(line, "\n")] = '\0';
|
||||
|
||||
if (is_valid_ip(line)) {
|
||||
|
||||
char *qqwry_region = qqwry_(line);
|
||||
if (qqwry_region == NULL) {
|
||||
printf("qqwry 解析地域错误\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
char *area = ip2region(xdb_path, line);
|
||||
if (area == NULL) {
|
||||
printf("ip2region 解析地域错误\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 取环境变量
|
||||
const char *REGION_ENV = getenv("REGION");
|
||||
if (REGION_ENV != NULL) {
|
||||
printf("REGION: %s\n", REGION_ENV);
|
||||
strcpy(_REGION_LIST_COPY, REGION_ENV);
|
||||
strcpy(QQWRY_REGION_LIST_COPY, REGION_ENV);
|
||||
} else {
|
||||
strcpy(_REGION_LIST_COPY, "局域网 内网 中国 ");
|
||||
strcpy(QQWRY_REGION_LIST_COPY, "局域网 内网 中国 ");
|
||||
}
|
||||
//printf("REGION_LIST : %s\n", _REGION_LIST_COPY);
|
||||
|
||||
split_string(QQWRY_REGION_LIST_COPY, " ", qqwry_region_list); // 分割后存储在 qqwry_region_list
|
||||
if (isregion(qqwry_region, qqwry_region_list) == 1) { // 返回1表示在白名单列表
|
||||
;
|
||||
} else {
|
||||
split_string(_REGION_LIST_COPY, " ", _region_list);
|
||||
if (isregion(area, _region_list) == 1) { // 返回1表示在白名单列表
|
||||
;
|
||||
} else {
|
||||
char ipquery_command[BUFFER + 100] = { 0 };
|
||||
snprintf(ipquery_command, BUFFER + 100, "./IP_region_query/ipquery %s", line);
|
||||
FILE *fp = popen(ipquery_command, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 创建足够大的缓冲区来存储命令输出
|
||||
char buffer[1024 * 2]; // 2KB 缓冲区
|
||||
size_t bytesRead = fread(buffer, 1, sizeof(buffer) - 1, fp);
|
||||
buffer[bytesRead] = '\0';
|
||||
|
||||
pclose(fp);
|
||||
sleep(1);
|
||||
|
||||
char *p = strstr(buffer, "中国");
|
||||
if (p == NULL) {
|
||||
printf("%s %s", line, buffer);
|
||||
|
||||
char command_ipset[BUFFER + 256] = { 0 };
|
||||
snprintf(command_ipset, sizeof(command_ipset), "ipset add root %s > /dev/null 2>&1", line);
|
||||
int r = system(command_ipset);
|
||||
if (r == -1) {
|
||||
perror("system command failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(qqwry_region);
|
||||
free(area);
|
||||
|
||||
} else { // 是正确IP
|
||||
printf("%s is not a valid IPv4 address.\n", line);
|
||||
}
|
||||
} // while
|
||||
|
||||
// 关闭管道
|
||||
pclose(fp);
|
||||
}
|
||||
|
||||
|
||||
// 父进程 主进程循环,检查子进程运行情况
|
||||
int iteration = 0;
|
||||
while (1) {
|
||||
iteration++;
|
||||
|
||||
if (iteration >= 3600*3) {
|
||||
iteration = 0;
|
||||
printf("准备重启进程...\n");
|
||||
restart_process(pid1, pid2, argv);
|
||||
}
|
||||
|
||||
sleep(1); // 每次检查间隔1秒
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
27
main.h
27
main.h
@@ -1,27 +0,0 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/resource.h>
|
||||
#include <signal.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include "ip2region.h"
|
||||
#include "qqwry.h"
|
||||
#include "common.h"
|
||||
|
||||
#define RED "\033[31m"
|
||||
#define RESET "\033[0m"
|
||||
#define WHITELIST_IP_NUM 1024
|
||||
#define MAXIPSET 65534
|
||||
|
||||
|
||||
char *xdb_path = "ip2region.xdb";
|
||||
pid_t pid1, pid2; // 保存子进程的 PID
|
||||
|
||||
#endif
|
||||
18
qqwry/main.c
18
qqwry/main.c
@@ -1,18 +0,0 @@
|
||||
#
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "qqwry.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
char *qqwry_region = qqwry_("qqwry.dat", "1.1.1.1");
|
||||
if (qqwry_region == NULL) {
|
||||
printf("qqwry 解析地域错误\n");
|
||||
}
|
||||
puts(qqwry_region);
|
||||
|
||||
free(qqwry_region);
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
367
qqwry/qqwry.c
367
qqwry/qqwry.c
@@ -1,367 +0,0 @@
|
||||
|
||||
#include "qqwry.h"
|
||||
|
||||
ip_data ip_defaults = {.parent_data = NULL,.child_data = NULL,.index_size = 7,.isp = 1 };
|
||||
|
||||
int qqwry_init(char *file)
|
||||
{
|
||||
int buff;
|
||||
|
||||
ip_defaults.fp = fopen(file, "r");
|
||||
if (ip_defaults.fp == NULL) {
|
||||
fprintf(stderr, "failed to open %s\n", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
readvalue(4, &buff); //first 4 bytes represents the offset of first index
|
||||
ip_defaults.first_item = buff;
|
||||
readvalue(4, &buff);
|
||||
ip_defaults.last_item = buff;
|
||||
ip_defaults.item_number = (ip_defaults.last_item - ip_defaults.first_item) / ip_defaults.index_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qqwry_match(char *pattern, char *subject)
|
||||
{
|
||||
regex_t regex;
|
||||
int reti, ret;
|
||||
char msgbuf[100];
|
||||
|
||||
/* Compile regular expression */
|
||||
reti = regcomp(®ex, pattern, 0);
|
||||
if (reti) {
|
||||
fprintf(stderr, "Could not compile regex\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Execute regular expression */
|
||||
reti = regexec(®ex, subject, 0, NULL, 0);
|
||||
if (!reti) {
|
||||
ret = 1;
|
||||
} else if (reti == REG_NOMATCH) {
|
||||
ret = 0;
|
||||
} else {
|
||||
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
|
||||
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* Free memory allocated to the pattern buffer by regcomp() */
|
||||
regfree(®ex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
iconv_t initialize_iconv(const char *target, const char *src)
|
||||
{
|
||||
// 创建转换描述符
|
||||
iconv_t iconvDesc = iconv_open(target, src);
|
||||
|
||||
// 检查 iconv_open 是否成功
|
||||
if (iconvDesc == (iconv_t) - 1) {
|
||||
// 如果失败,打印错误信息并返回 NULL
|
||||
fprintf(stderr, "Error: Conversion from '%s' to '%s' is not available.\n", src, target);
|
||||
return (iconv_t) NULL;
|
||||
}
|
||||
// 成功时返回 iconv_t 描述符
|
||||
return iconvDesc;
|
||||
}
|
||||
|
||||
int gbk2utf8(char *utf8_str, char *gbk_str)
|
||||
{
|
||||
iconv_t iconvDesc = initialize_iconv("UTF-8//TRANSLIT//IGNORE", "GBK");
|
||||
size_t iconv_value, len, utf8len;
|
||||
//int len_start;
|
||||
|
||||
len = strlen(gbk_str) + 1;
|
||||
if (!len) {
|
||||
fprintf(stderr, "iconvISO2UTF8: input String is empty.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Assign enough space to put the UTF-8. */
|
||||
utf8len = 3 * len;
|
||||
if (!utf8_str) {
|
||||
fprintf(stderr, "iconvISO2UTF8: Calloc failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iconv_value = iconv(iconvDesc, &gbk_str, &len, &utf8_str, &utf8len);
|
||||
/* Handle failures. */
|
||||
if (iconv_value == (size_t)-1) {
|
||||
switch (errno) {
|
||||
/* See "man 3 iconv" for an explanation. */
|
||||
case EILSEQ:
|
||||
fprintf(stderr, "iconv failed: Invalid multibyte sequence, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "iconv failed: Incomplete multibyte sequence, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
|
||||
break;
|
||||
case E2BIG:
|
||||
fprintf(stderr, "iconv failed: No more room, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "iconv failed, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iconv_close(iconvDesc) != 0) {
|
||||
fprintf(stderr, "libicon close failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return utf8len;
|
||||
}
|
||||
|
||||
int readbyte(int size, int offset, int *buff)
|
||||
{
|
||||
int count;
|
||||
int nbytes = 1;
|
||||
*buff = 0;
|
||||
if (ip_defaults.fp != NULL) {
|
||||
//if offset is negative,keep the current offset unchanged
|
||||
if (offset >= 0) {
|
||||
qqwry_seek(offset);
|
||||
} else {
|
||||
int curr_pos = ftell(ip_defaults.fp);
|
||||
fseek(ip_defaults.fp, curr_pos, SEEK_SET);
|
||||
}
|
||||
|
||||
if ((count = fread(buff, nbytes, size, ip_defaults.fp)) != size) {
|
||||
return -1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int readvalue(unsigned int size, int *buff)
|
||||
{
|
||||
return readbyte(size, -1, buff);
|
||||
}
|
||||
|
||||
void set_ip_range(unsigned int offset)
|
||||
{
|
||||
readbyte(4, offset, (int *)(&ip_defaults.startip));
|
||||
//skip 3 bytes to read the next ip
|
||||
qqwry_forward(3);
|
||||
readvalue(4, (int *)(&ip_defaults.endip));
|
||||
}
|
||||
|
||||
void qqwry_seek(int offset)
|
||||
{
|
||||
fseek(ip_defaults.fp, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
void qqwry_forward(unsigned int byte)
|
||||
{
|
||||
fseek(ip_defaults.fp, byte, SEEK_CUR);
|
||||
}
|
||||
|
||||
void qqwry_back(unsigned int byte)
|
||||
{
|
||||
int currPos = ftell(ip_defaults.fp);
|
||||
qqwry_seek(currPos - byte);
|
||||
}
|
||||
|
||||
char *long2ip(int ip)
|
||||
{
|
||||
// 分配16字节内存用于存储IP字符串
|
||||
char *ip_str = malloc(16 * sizeof(char));
|
||||
|
||||
if (ip_str == NULL) {
|
||||
// 如果内存分配失败,返回NULL
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
return NULL;
|
||||
}
|
||||
// 将IP转换为字符串
|
||||
snprintf(ip_str, 16, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
|
||||
|
||||
return ip_str;
|
||||
}
|
||||
|
||||
unsigned int ip2long(char *ip)
|
||||
{
|
||||
int nip = 0, tmp = 0, step = 24;
|
||||
char *copy = strdup(ip);
|
||||
char *token = strtok(copy, ".");
|
||||
|
||||
while (token) {
|
||||
tmp = (unsigned int)atoi(token);
|
||||
tmp <<= step;
|
||||
nip += tmp;
|
||||
step -= 8;
|
||||
token = strtok(NULL, ".");
|
||||
}
|
||||
free(copy);
|
||||
return nip;
|
||||
}
|
||||
|
||||
int search_record(char *ip)
|
||||
{
|
||||
int numeric_ip = ip2long(ip);
|
||||
int low = 0;
|
||||
int high = ip_defaults.item_number;
|
||||
return binary_search(low, high, numeric_ip);
|
||||
}
|
||||
|
||||
int binary_search(int low, int high, int ip)
|
||||
{
|
||||
unsigned int mid, offset, startip, endip;
|
||||
|
||||
if (low <= high) {
|
||||
mid = low + (high - low) / 2;
|
||||
offset = round(ip_defaults.first_item + mid * ip_defaults.index_size);
|
||||
set_ip_range(offset);
|
||||
startip = ip_defaults.startip;
|
||||
endip = ip_defaults.endip;
|
||||
if (ip >= startip && ip <= endip) {
|
||||
return offset;
|
||||
}
|
||||
//if ip is below the lower limit, decrease the upper limit
|
||||
if (ip < startip) {
|
||||
return binary_search(low, mid - 1, ip);
|
||||
}
|
||||
//if ip is above the lower limit, increase the lower limit
|
||||
return binary_search(mid + 1, high, ip);
|
||||
}
|
||||
return ip_defaults.last_item;
|
||||
}
|
||||
|
||||
static char *get_string()
|
||||
{
|
||||
unsigned int buff = 0;
|
||||
char *str = realloc(NULL, sizeof(char));
|
||||
char *tmp;
|
||||
int i = 0, c = 0;
|
||||
|
||||
if ((c = readvalue(1, (int *)(&buff))) != 1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; buff != 0; i++) {
|
||||
str[i] = buff;
|
||||
tmp = realloc(str, (sizeof(char)) * (i + 2));
|
||||
str = tmp;
|
||||
readvalue(1, (int *)(&buff));
|
||||
}
|
||||
str[i] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *get_child_data()
|
||||
{
|
||||
unsigned int flag, offset;
|
||||
readvalue(1, (int *)(&flag));
|
||||
if (flag == 0) { //no child data
|
||||
return 0;
|
||||
} else if (flag == 1 || flag == 2) { // redirection for child data
|
||||
readvalue(3, (int *)(&offset));
|
||||
qqwry_seek(offset);
|
||||
return get_string();
|
||||
}
|
||||
// no redirection for child data
|
||||
qqwry_back(1);
|
||||
return get_string();
|
||||
}
|
||||
|
||||
int convert_data(char *parent_data, char *child_data)
|
||||
{
|
||||
ip_defaults.parent_data = malloc(strlen(parent_data) * 3); //in utf8,one chinese character could consume up to 3 bytes
|
||||
gbk2utf8(ip_defaults.parent_data, parent_data);
|
||||
ip_defaults.child_data = malloc(strlen(child_data) * 3);
|
||||
gbk2utf8(ip_defaults.child_data, child_data);
|
||||
|
||||
if (qqwry_match("移动", ip_defaults.child_data)) {
|
||||
ip_defaults.isp = 0x03;
|
||||
} else if (qqwry_match("联通", ip_defaults.child_data)) {
|
||||
ip_defaults.isp = 0x02;
|
||||
} else {
|
||||
ip_defaults.isp = 0x01;
|
||||
}
|
||||
free(parent_data);
|
||||
free(child_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qqwry_redirect(int bytes)
|
||||
{
|
||||
int redirect_offset;
|
||||
readvalue(bytes, &redirect_offset);
|
||||
qqwry_seek(redirect_offset);
|
||||
return redirect_offset;
|
||||
}
|
||||
|
||||
int get_data(int offset)
|
||||
{ //get record data
|
||||
int flag, redirect_offset;
|
||||
char *parent_data, *child_data;
|
||||
readbyte(1, offset + 4, &flag); //get the flag value to see if the data is stored elsewhere
|
||||
|
||||
if (flag == 1) { //this means we should look elsewhere for both
|
||||
redirect_offset = qqwry_redirect(3); //read 3 bytes to get a new offset and redirect there
|
||||
readvalue(1, &flag);
|
||||
if (flag == 2) {
|
||||
// child data is elsewhere
|
||||
qqwry_redirect(3);
|
||||
parent_data = get_string();
|
||||
qqwry_seek(redirect_offset + 4);
|
||||
child_data = get_child_data();
|
||||
} else { // no redirection for parent data
|
||||
qqwry_back(1);
|
||||
parent_data = get_string();
|
||||
child_data = get_child_data();
|
||||
}
|
||||
} else if (flag == 2) { //redirection for only parent
|
||||
qqwry_redirect(3);
|
||||
parent_data = get_string();
|
||||
qqwry_seek(offset + 8);
|
||||
child_data = get_child_data();
|
||||
} else { // no redirection for both parent and child
|
||||
qqwry_back(1);
|
||||
parent_data = get_string();
|
||||
child_data = get_string();
|
||||
}
|
||||
|
||||
convert_data(parent_data, child_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_location(char *ip)
|
||||
{
|
||||
//offset is the address where the ip is found. first 4 bytes is the start ip address of the ip range and the following 3 bytes is the offset pointing to the actual record data;
|
||||
unsigned int offset = search_record(ip);
|
||||
unsigned int tmp_offset;
|
||||
qqwry_seek(offset + 4); // skip 4 byte to get the offset value pointing to record data
|
||||
readvalue(3, (int *)(&tmp_offset)); // the offset pointing to the data
|
||||
get_data(tmp_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *qqwry_(char *dat, char *ip)
|
||||
{
|
||||
qqwry_init(dat);
|
||||
|
||||
get_location(ip);
|
||||
//printf("%s-%s %d\n", ip_defaults.parent_data, ip_defaults.child_data, ip_defaults.isp);
|
||||
//printf("QQWRY %s %s-%s\n", ip, ip_defaults.parent_data, ip_defaults.child_data);
|
||||
|
||||
// 计算拼接后的字符串所需的长度
|
||||
size_t len = strlen(ip_defaults.parent_data) + strlen(ip_defaults.child_data) + 2; // +2 for the hyphen and null terminator
|
||||
char *result = malloc(len);
|
||||
|
||||
if (result) {
|
||||
// 拼接字符串,格式为 "parent_data-child_data"
|
||||
snprintf(result, len, "%s-%s", ip_defaults.parent_data, ip_defaults.child_data);
|
||||
}
|
||||
|
||||
free(ip_defaults.parent_data);
|
||||
free(ip_defaults.child_data);
|
||||
fclose(ip_defaults.fp);
|
||||
|
||||
return result;
|
||||
}
|
||||
BIN
qqwry/qqwry.dat
BIN
qqwry/qqwry.dat
Binary file not shown.
@@ -1,31 +0,0 @@
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <iconv.h>
|
||||
#include <errno.h>
|
||||
#include <regex.h>
|
||||
|
||||
typedef struct {
|
||||
FILE *fp;
|
||||
unsigned int index_size;
|
||||
unsigned int first_item, last_item;
|
||||
unsigned int item_number, startip, endip, curr_data_offset;
|
||||
char *parent_data, *child_data;
|
||||
int isp;
|
||||
} ip_data;
|
||||
|
||||
int search_record(char *ip);
|
||||
int binary_search(int low, int high, int ip);
|
||||
int readbyte(int size, int offset, int *buff);
|
||||
int readvalue(unsigned int size, int *buff);
|
||||
void qqwry_seek(int offset);
|
||||
void qqwry_forward(unsigned int byte);
|
||||
void qqwry_back(unsigned int byte);
|
||||
int get_location(char *ip);
|
||||
int gbk2utf8(char *utf8_str, char *gbk_str);
|
||||
|
||||
extern char *qqwry_(char *dat, char *ip);
|
||||
BIN
qqwry/qqwry.o
BIN
qqwry/qqwry.o
Binary file not shown.
Reference in New Issue
Block a user