增加中国IP缓存
This commit is contained in:
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -5,6 +5,11 @@
|
||||
"prctl.h": "c",
|
||||
"algorithm": "c",
|
||||
"cstdlib": "c",
|
||||
"libipset.h": "c"
|
||||
"libipset.h": "c",
|
||||
"array": "c",
|
||||
"cache.h": "c",
|
||||
"errno.h": "c",
|
||||
"stdlib.h": "c",
|
||||
"string.h": "c"
|
||||
}
|
||||
}
|
||||
6
Makefile
6
Makefile
@@ -68,11 +68,11 @@ ipquery:
|
||||
cd IP_region_query && CGO_ENABLED=0 go build -ldflags '-w -s' && upx -9 ipquery
|
||||
|
||||
# 动态链接目标
|
||||
$(BIN): cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o
|
||||
$(BIN): cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o cache.o
|
||||
$(CC) $(CFLAGS) -o $(BIN) $^ -lpcap -lipset -lcurl -lcjson
|
||||
|
||||
# 静态链接目标
|
||||
static: cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o
|
||||
static: cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o cache.o
|
||||
$(CC) $(CFLAGS) $(CFLAGS_LIBCURL) $(CFLAGS_LIBCJSON) -o $(BIN) $^ $(LIBPCAP) $(LIBCAP) $(LIBIPSET) $(LIBCJSON) $(LIBCURL) $(LIBS) -static
|
||||
|
||||
%.o: %.c
|
||||
@@ -81,4 +81,4 @@ static: cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o
|
||||
# 清理目标
|
||||
clean:
|
||||
rm -rf $(BIN) IP_region_query/ipquery
|
||||
rm -rf cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o
|
||||
rm -rf cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o cache.o
|
||||
|
||||
150
cache.c
Normal file
150
cache.c
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "cache.h"
|
||||
|
||||
char cn_ip[MAXIPSET_][MAXIPLEN] = { 0 };
|
||||
|
||||
// 添加一个 IP 到集合(如果已存在则不添加)
|
||||
int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip)
|
||||
{
|
||||
if (ip == NULL || strlen(ip) >= MAXIPLEN) {
|
||||
return -1; // 错误:无效的 IP 地址或过长
|
||||
}
|
||||
// 检查是否已存在
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) {
|
||||
return 1; // IP 已存在,返回特殊代码
|
||||
}
|
||||
}
|
||||
// 查找空位并添加
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] == '\0') { // 检查是否为空
|
||||
strcpy(cn_ip[i], ip);
|
||||
return 0; // 成功添加
|
||||
}
|
||||
}
|
||||
return -1; // 错误:集合已满
|
||||
}
|
||||
|
||||
// 判断给定的IP地址是否在集合中
|
||||
int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip)
|
||||
{
|
||||
if (ip == NULL) {
|
||||
return 0; // 错误:无效的IP地址指针
|
||||
}
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) {
|
||||
return 1; // 找到匹配的IP地址
|
||||
}
|
||||
}
|
||||
return 0; // 没有找到匹配的IP地址
|
||||
}
|
||||
|
||||
// 计算集合中非空IP的数量
|
||||
int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN])
|
||||
{
|
||||
int count = 0; // 用于计数非空IP
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] != '\0') {
|
||||
count++; // 非空IP计数
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// 安全的清理IP地址集合,将所有位置置为空字符串
|
||||
void clear_ip_set(char cn_ip[MAXIPSET_][MAXIPLEN])
|
||||
{
|
||||
if (cn_ip == NULL) {
|
||||
return; // 如果指针无效,则直接返回
|
||||
}
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
memset(cn_ip[i], '\0', MAXIPLEN);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存字符串到文件
|
||||
int append_string_to_file(const char *filepath, const char *str)
|
||||
{
|
||||
// 检查输入是否为空
|
||||
if (filepath == NULL || str == NULL) {
|
||||
fprintf(stderr, "Invalid argument(s).\n");
|
||||
return -1;
|
||||
}
|
||||
// 打开文件以追加模式
|
||||
FILE *file = fopen(filepath, "a");
|
||||
if (file == NULL) {
|
||||
perror("Error opening file");
|
||||
return -1;
|
||||
}
|
||||
// 追加字符串到文件
|
||||
if (fprintf(file, "%s\n", str) < 0) {
|
||||
perror("Error writing to file");
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
// 刷新缓冲区确保数据写入磁盘
|
||||
if (fflush(file) != 0) {
|
||||
perror("Error flushing file");
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
// 关闭文件
|
||||
if (fclose(file) != 0) {
|
||||
perror("Error closing file");
|
||||
return -1;
|
||||
}
|
||||
// 成功返回
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_file_to_array(const char *filepath, char cn_ip[MAXIPSET_][MAXIPLEN], int *line_count)
|
||||
{
|
||||
// 参数校验
|
||||
if (filepath == NULL || cn_ip == NULL || line_count == NULL) {
|
||||
fprintf(stderr, "Invalid argument(s).\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
FILE *file = fopen(filepath, "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Error opening file '%s': %s\n", filepath, strerror(errno));
|
||||
return -2;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
while (fgets(cn_ip[count], MAXIPLEN, file)) {
|
||||
// 去掉行尾的换行符
|
||||
size_t len = strlen(cn_ip[count]);
|
||||
if (len > 0 && cn_ip[count][len - 1] == '\n') {
|
||||
cn_ip[count][len - 1] = '\0';
|
||||
}
|
||||
count++;
|
||||
if (count >= MAXIPSET_) {
|
||||
fprintf(stderr, "Exceeded maximum number of lines (%d).\n", MAXIPSET_);
|
||||
fclose(file);
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(file)) {
|
||||
fprintf(stderr, "Error reading file '%s'.\n", filepath);
|
||||
fclose(file);
|
||||
return -4;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
*line_count = count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 判断文件是否存在,返回 1 表示存在,0 表示不存在
|
||||
int file_exists_access(const char *filepath)
|
||||
{
|
||||
if (filepath == NULL) {
|
||||
fprintf(stderr, "Invalid argument.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return access(filepath, F_OK) == 0;
|
||||
}
|
||||
26
cache.h
Normal file
26
cache.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CACHE_H
|
||||
#define CACHE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define MAXIPSET_ 256
|
||||
#define MAXIPLEN 32
|
||||
|
||||
extern char cn_ip[MAXIPSET_][MAXIPLEN];
|
||||
|
||||
extern int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip);
|
||||
extern int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip);
|
||||
extern int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN]);
|
||||
extern void clear_ip_set(char cn_ip[MAXIPSET_][MAXIPLEN]);
|
||||
extern int is_ip_in_cache(const char *ip);
|
||||
|
||||
extern int append_string_to_file(const char *filepath, const char *str);
|
||||
extern int read_file_to_array(const char *filepath, char cn_ip[MAXIPSET_][MAXIPLEN], int *line_count);
|
||||
|
||||
extern int file_exists_access(const char *filepath);
|
||||
|
||||
#endif
|
||||
148
cap.c
148
cap.c
@@ -2,6 +2,8 @@
|
||||
#include "common.h"
|
||||
#include "libipset.h"
|
||||
#include "libcurl.h"
|
||||
#include "cache.h"
|
||||
|
||||
|
||||
pcap_if_t *alldevs, *device;
|
||||
pcap_t *handle; // 会话句柄
|
||||
@@ -29,100 +31,6 @@ struct ip_cache_node {
|
||||
struct ip_cache_node *next; // 指向下一个节点
|
||||
};
|
||||
|
||||
#define MAXIPSET_ 100
|
||||
#define MAXIPLEN 32
|
||||
char cn_ip[MAXIPSET_][MAXIPLEN] = { 0 };
|
||||
|
||||
// 添加一个 IP 到集合(如果已存在则不添加)
|
||||
int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip)
|
||||
{
|
||||
if (ip == NULL || strlen(ip) >= MAXIPLEN) {
|
||||
return -1; // 错误:无效的 IP 地址或过长
|
||||
}
|
||||
// 检查是否已存在
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) {
|
||||
return 1; // IP 已存在,返回特殊代码
|
||||
}
|
||||
}
|
||||
// 查找空位并添加
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] == '\0') { // 检查是否为空
|
||||
strcpy(cn_ip[i], ip);
|
||||
return 0; // 成功添加
|
||||
}
|
||||
}
|
||||
return -1; // 错误:集合已满
|
||||
}
|
||||
|
||||
// 判断给定的IP地址是否在集合中
|
||||
int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip)
|
||||
{
|
||||
if (ip == NULL) {
|
||||
return 0; // 错误:无效的IP地址指针
|
||||
}
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) {
|
||||
return 1; // 找到匹配的IP地址
|
||||
}
|
||||
}
|
||||
return 0; // 没有找到匹配的IP地址
|
||||
}
|
||||
|
||||
// 计算集合中非空IP的数量
|
||||
int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN])
|
||||
{
|
||||
int count = 0; // 用于计数非空IP
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
if (cn_ip[i][0] != '\0') {
|
||||
count++; // 非空IP计数
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// 安全的清理IP地址集合,将所有位置置为空字符串
|
||||
void clear_ip_set(char cn_ip[MAXIPSET_][MAXIPLEN])
|
||||
{
|
||||
if (cn_ip == NULL) {
|
||||
return; // 如果指针无效,则直接返回
|
||||
}
|
||||
for (int i = 0; i < MAXIPSET_; i++) {
|
||||
memset(cn_ip[i], '\0', MAXIPLEN);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查 IP 是否已在缓存中并是否过期
|
||||
int is_ip_in_cache(const char *ip)
|
||||
{
|
||||
time_t now = time(NULL); // 获取当前时间
|
||||
struct ip_cache_node *current = ip_cache_head;
|
||||
struct ip_cache_node *prev = NULL;
|
||||
|
||||
while (current != NULL) {
|
||||
// 如果 IP 匹配并且未过期
|
||||
if (strcmp(current->ip, ip) == 0) {
|
||||
if (now - current->timestamp <= CACHE_TTL) {
|
||||
return 1; // IP 在缓存中,且未过期
|
||||
} else {
|
||||
// 如果过期,从链表中移除这个节点
|
||||
if (prev == NULL) {
|
||||
ip_cache_head = current->next;
|
||||
} else {
|
||||
prev->next = current->next;
|
||||
}
|
||||
|
||||
free(current);
|
||||
cache_size--;
|
||||
return 0; // IP 过期,不再缓存
|
||||
}
|
||||
}
|
||||
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
return 0; // IP 不在缓存中
|
||||
}
|
||||
|
||||
// 将新 IP 添加到缓存,若缓存过大则移除最早的 IP
|
||||
void add_ip_to_cache(const char *ip)
|
||||
@@ -161,6 +69,38 @@ void add_ip_to_cache(const char *ip)
|
||||
cache_size++;
|
||||
}
|
||||
|
||||
// 检查 IP 是否已在缓存中并是否过期
|
||||
int is_ip_in_cache(const char *ip)
|
||||
{
|
||||
time_t now = time(NULL); // 获取当前时间
|
||||
struct ip_cache_node *current = ip_cache_head;
|
||||
struct ip_cache_node *prev = NULL;
|
||||
|
||||
while (current != NULL) {
|
||||
// 如果 IP 匹配并且未过期
|
||||
if (strcmp(current->ip, ip) == 0) {
|
||||
if (now - current->timestamp <= CACHE_TTL) {
|
||||
return 1; // IP 在缓存中,且未过期
|
||||
} else {
|
||||
// 如果过期,从链表中移除这个节点
|
||||
if (prev == NULL) {
|
||||
ip_cache_head = current->next;
|
||||
} else {
|
||||
prev->next = current->next;
|
||||
}
|
||||
|
||||
free(current);
|
||||
cache_size--;
|
||||
return 0; // IP 过期,不再缓存
|
||||
}
|
||||
}
|
||||
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
return 0; // IP 不在缓存中
|
||||
}
|
||||
|
||||
// 清理缓存链表,释放所有节点的内存
|
||||
void free_ip_cache()
|
||||
{
|
||||
@@ -175,6 +115,7 @@ void free_ip_cache()
|
||||
cache_size = 0;
|
||||
}
|
||||
|
||||
|
||||
// 回调函数,在捕获到每个数据包时调用
|
||||
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
{
|
||||
@@ -264,6 +205,10 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
|
||||
} else { // 这时是国内IP
|
||||
add_cn_ip(cn_ip, src_ip); // 添加国内IP到缓存
|
||||
_printf("IP: %s 离线库为国外, API 判断为国内, 标记为已处理!!!\n", src_ip);
|
||||
|
||||
if (append_string_to_file("cn.txt", src_ip) != 0) {
|
||||
_printf("append_string_to_file() Error!!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -427,6 +372,21 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 读取缓存
|
||||
if (1 == file_exists_access("cn.txt")) {
|
||||
int line_count = 0;
|
||||
int result = read_file_to_array("cn.txt", cn_ip, &line_count);
|
||||
if (result != 0) {
|
||||
fprintf(stderr, "Failed to read file with error code: %d\n", result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Read %d lines from file:\n", line_count);
|
||||
for (int i = 0; i < line_count; i++) {
|
||||
printf("Line %d: %s\n", i + 1, cn_ip[i]);
|
||||
}
|
||||
}
|
||||
|
||||
pid = fork(); // 创建子进程
|
||||
if (pid == 0) // 子进程
|
||||
{
|
||||
|
||||
4
common.c
4
common.c
@@ -189,7 +189,7 @@ int _nice(int increment) {
|
||||
}
|
||||
|
||||
// 判断命令是否存在
|
||||
int command_exists(const char *command) {
|
||||
int _command_exists(const char *command) {
|
||||
const char *path_env = getenv("PATH");
|
||||
if (!path_env) {
|
||||
return 0; // 如果 PATH 不存在,返回不存在
|
||||
@@ -221,7 +221,7 @@ int command_exists(const char *command) {
|
||||
return 0; // 命令不存在
|
||||
}
|
||||
|
||||
// 定义一个函数,执行命令并返回输出
|
||||
// 执行命令并返回输出
|
||||
char *_execute_command(const char *command) {
|
||||
FILE *fp;
|
||||
char buffer[1024];
|
||||
|
||||
Reference in New Issue
Block a user