diff --git a/.vscode/settings.json b/.vscode/settings.json index c10cf8a..310ff0b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,7 @@ "cache.h": "c", "errno.h": "c", "stdlib.h": "c", - "string.h": "c" + "string.h": "c", + "stat.h": "c" } } \ No newline at end of file diff --git a/cache.c b/cache.c index 06263b9..fc52782 100644 --- a/cache.c +++ b/cache.c @@ -1,6 +1,5 @@ #include "cache.h" - struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点 int cache_size = 0; // 当前缓存中的 IP 数量 @@ -27,7 +26,6 @@ void add_ip_to_cache(const char *ip) free(current); cache_size--; } - // 创建新的缓存节点并添加到链表头部 struct ip_cache_node *new_node = (struct ip_cache_node *)malloc(sizeof(struct ip_cache_node)); if (new_node == NULL) { @@ -48,7 +46,8 @@ int is_ip_in_cache(const char *ip) struct ip_cache_node *current = ip_cache_head; struct ip_cache_node *prev = NULL; - if (ip_cache_head == NULL) return 0; // 如果 ip_cache_head == NULL,current->next 可能导致段错误 (Segmentation Fault)。 + if (ip_cache_head == NULL) + return 0; // 如果 ip_cache_head == NULL,current->next 可能导致段错误 (Segmentation Fault)。 while (current != NULL) { // 如果 IP 匹配并且未过期 @@ -89,8 +88,6 @@ void free_ip_cache() cache_size = 0; } - - char cn_ip[MAXIPSET_][MAXIPLEN] = { 0 }; // 添加一个 IP 到集合(如果已存在则不添加) @@ -133,20 +130,38 @@ int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *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; } +int truncate_file(const char *path) +{ + int fd; + + // 以只写模式打开文件并截断到0字节 + fd = open(path, O_WRONLY | O_TRUNC); + if (fd == -1) { + perror("truncate_file: Failed to open file"); + return -1; + } + // 关闭文件描述符(此时文件已被截断) + close(fd); + return 0; +} + // 安全的清理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); } diff --git a/cache.h b/cache.h index 514f128..42854d0 100644 --- a/cache.h +++ b/cache.h @@ -18,6 +18,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -25,7 +29,7 @@ #include #include -#define MAXIPSET_ 10240 +#define MAXIPSET_ 65535 #define MAXIPLEN 32 #define CACHE_TTL 180 // 设定缓存的存活时间为 600 秒 (10 分钟) @@ -54,5 +58,6 @@ 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); +extern int truncate_file(const char *path); #endif diff --git a/cap.c b/cap.c index 638421e..32c7b90 100644 --- a/cap.c +++ b/cap.c @@ -4,26 +4,22 @@ #include "libcurl.h" #include "cache.h" - -pcap_if_t *alldevs, *device; -pcap_t *handle; // 会话句柄 +pcap_if_t *alldevs, *device; +pcap_t *handle; // 会话句柄 struct bpf_program fp; // 编译后的过滤器 pid_t pid = -1; // 子进程全局PID #define SHM_SIZE 1024 // 共享内存大小 #define SHM_KEY 0124 // 共享内存键值 -int shmid = -1; -int RULE_NAME_NUMBER = 0; // ipset 集合集合数 -char *RULE_NAME = NULL; // 共享内存 - - -char *ip2region_area = NULL; // ip2region 解析结果 -char *command_result = NULL; // 执行命令的结果 +int shmid = -1; +int RULE_NAME_NUMBER = 0; // ipset 集合集合数 +char *RULE_NAME = NULL; // 共享内存 +char *ip2region_area = NULL; // ip2region 解析结果 +char *command_result = NULL; // 执行命令的结果 void Processing_IP_addresses(char *src_ip) { - // 地域白名单 char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } }; char _REGION_LIST[BUFFER] = { 0 }; @@ -53,8 +49,9 @@ void Processing_IP_addresses(char *src_ip) printf("%s ", cn_ip[i]); } } - if (cn_ip_len(cn_ip) >= 1024) { // 清理集合 + if (cn_ip_len(cn_ip) >= 10240) { // 清理集合 clear_ip_set(cn_ip); + truncate_file("cn.txt"); // 清空文件 } printf("cn_ip_len(cn_ip): %d\n", cn_ip_len(cn_ip)); @@ -97,8 +94,10 @@ void Processing_IP_addresses(char *src_ip) if (NULL == strstr(response.continent_country, "中国")) { // 这时是国外IP _printf(RED "CurlGetIpArea(): %s %s\n" REDEND, src_ip, response.continent_country); add_ip_to_ipset(RULE_NAME, src_ip); - } else { // 这时是国内IP - add_cn_ip(cn_ip, src_ip); // 添加国内IP到缓存 + } else { // 这时是国内IP + if (-1 == add_cn_ip(cn_ip, src_ip)) { // 添加国内IP到缓存 + _printf(RED "add_cn_ip() Error!!! 错误:集合已满\n" REDEND); + } _printf("IP: %s 离线库为国外, API 判断为国内, 标记为已处理!!!\n", src_ip); if (append_string_to_file("cn.txt", src_ip) != 0) { @@ -119,7 +118,7 @@ void Processing_IP_addresses(char *src_ip) ip2region_area = NULL; } - return ; + return; } // 回调函数,在捕获到每个数据包时调用 @@ -128,12 +127,11 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char int ethernet_header_len = 14; //struct ip *ip_header = (struct ip *)(packet + ethernet_header_len); struct ip *ip_header = (struct ip *)(packet + ethernet_header_len); - if (ip_header->ip_v != 4) return; // 只处理 IPv4 + if (ip_header->ip_v != 4) + return; // 只处理 IPv4 char src_ip[INET_ADDRSTRLEN] = { 0 }; - - inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN); Processing_IP_addresses(src_ip); diff --git a/cap.h b/cap.h index 352a1ef..121155b 100644 --- a/cap.h +++ b/cap.h @@ -28,7 +28,4 @@ #define _VERSION "0.2" - - - #endif diff --git a/common.c b/common.c index d17b26a..90ea0e6 100644 --- a/common.c +++ b/common.c @@ -1,7 +1,8 @@ #include "common.h" // 计算字符串长度 -int _strlen(const char *str) { +int _strlen(const char *str) +{ if (str == NULL) return 0; @@ -9,7 +10,6 @@ int _strlen(const char *str) { return _p - str; } - // 自定义 printf 函数 void _printf(const char *format, ...) { @@ -20,13 +20,13 @@ void _printf(const char *format, ...) time_t now = time(NULL); struct tm local_time; localtime_r(&now, &local_time); - char time_str[20]; // YYYY-MM-DD HH:MM:SS 格式 + char time_str[20]; // YYYY-MM-DD HH:MM:SS 格式 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &local_time); // 打印时间戳到控制台 printf("[%s] ", time_str); - vprintf(format, args); // 打印内容到控制台 - va_end(args); // 结束对变参列表的处理 + vprintf(format, args); // 打印内容到控制台 + va_end(args); // 结束对变参列表的处理 // 重新启动变参列表 va_start(args, format); @@ -46,24 +46,23 @@ void _printf(const char *format, ...) perror("Unable to open log file"); } - va_end(args); // 结束对变参列表的处理 + va_end(args); // 结束对变参列表的处理 } void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]) { int i = 0; char *result = NULL; - char temp[WHITELIST_IP_NUM]; // 创建一个足够大的副本缓冲区 + char temp[WHITELIST_IP_NUM]; // 创建一个足够大的副本缓冲区 // 复制原始字符串到副本 strncpy(temp, string, sizeof(temp) - 1); - temp[sizeof(temp) - 1] = '\0'; // 确保字符串以 '\0' 结尾 + temp[sizeof(temp) - 1] = '\0'; // 确保字符串以 '\0' 结尾 - result = strtok(temp, delims); // 使用副本进行拆分 - while (result != NULL && i < WHITELIST_IP_NUM) - { + result = strtok(temp, delims); // 使用副本进行拆分 + while (result != NULL && i < WHITELIST_IP_NUM) { strncpy(whitelist_ip[i], result, WHITELIST_IP_NUM - 1); - whitelist_ip[i][WHITELIST_IP_NUM - 1] = '\0'; // 确保每个元素以 '\0' 结尾 + whitelist_ip[i][WHITELIST_IP_NUM - 1] = '\0'; // 确保每个元素以 '\0' 结尾 i++; result = strtok(NULL, delims); } @@ -74,19 +73,18 @@ int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM]) { int i; - for (i = 0; i < WHITELIST_IP_NUM; i++) { // 从 i = 0 开始 + for (i = 0; i < WHITELIST_IP_NUM; i++) { // 从 i = 0 开始 // 如果白名单 IP 是空字符串,跳出循环 if (whitelist_ip[i][0] == '\0') { break; } - // 对比 client_ip 的前缀是否与白名单中的IP段匹配 if (strncmp(client_ip, whitelist_ip[i], strlen(whitelist_ip[i])) == 0) { - return 1; // 匹配成功 + return 1; // 匹配成功 } } - return 0; // 未找到匹配 + return 0; // 未找到匹配 } // 地域段白名单对比 @@ -100,15 +98,14 @@ int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM]) if (region_list[i][0] == '\0') { break; } - // 在str中查找 region_list[i] p = strstr(str, region_list[i]); if (p != NULL) { - return 1; // 匹配成功,返回1 + return 1; // 匹配成功,返回1 } } - return 0; // 没有匹配,返回0 + return 0; // 没有匹配,返回0 } int8_t _copy_new_mem(char *src, int src_len, char **dest) @@ -123,7 +120,8 @@ int8_t _copy_new_mem(char *src, int src_len, char **dest) } // 返回的时间字符串存储在静态缓冲区中 -char *_time() { +char *_time() +{ static char temp[BUFFER]; const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; time_t t = time(NULL); @@ -134,11 +132,9 @@ char *_time() { return NULL; } - snprintf(temp, sizeof(temp), "[%d/%02d/%02d %s %02d:%02d:%02d]", - 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, - wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec); + snprintf(temp, sizeof(temp), "[%d/%02d/%02d %s %02d:%02d:%02d]", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec); - return temp; // 返回静态缓冲区地址 + return temp; // 返回静态缓冲区地址 } // 将字符串转换为IPv4地址 @@ -152,7 +148,8 @@ int is_valid_ip(const char *ip) } // 修改进程优先级 -int _nice(int increment) { +int _nice(int increment) +{ // 获取当前优先级 int oldprio = getpriority(PRIO_PROCESS, getpid()); if (oldprio == -1 && errno != 0) { @@ -163,12 +160,10 @@ int _nice(int increment) { printf("Current priority: %d\n", oldprio); // 检查是否溢出 - if ((increment > 0 && oldprio > INT_MAX - increment) || - (increment < 0 && oldprio < INT_MIN - increment)) { + if ((increment > 0 && oldprio > INT_MAX - increment) || (increment < 0 && oldprio < INT_MIN - increment)) { fprintf(stderr, "Priority overflow error\n"); return -1; } - // 计算新的优先级 int newprio = oldprio + increment; @@ -177,7 +172,6 @@ int _nice(int increment) { fprintf(stderr, "New priority out of range: %d (valid range is %d to %d)\n", newprio, PRIO_MIN, PRIO_MAX); return -1; } - // 设置新的优先级 if (setpriority(PRIO_PROCESS, getpid(), newprio) == -1) { perror("setpriority failed"); @@ -189,13 +183,14 @@ 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 不存在,返回不存在 + return 0; // 如果 PATH 不存在,返回不存在 } - char filepath[1024]; // 缓冲区大小 + char filepath[1024]; // 缓冲区大小 const char *dir = path_env; while (dir && *dir) { @@ -205,24 +200,23 @@ int _command_exists(const char *command) { // 构建路径并检查长度 if (snprintf(filepath, sizeof(filepath), "%.*s/%s", (int)len, dir, command) >= (int)sizeof(filepath)) { - return 0; // 缓冲区溢出,返回不存在 + return 0; // 缓冲区溢出,返回不存在 } - // 检查文件是否存在且可执行 if (access(filepath, X_OK) == 0) { puts(filepath); - return 1; // 命令存在 + return 1; // 命令存在 } - // 更新 dir 指针 dir = end ? end + 1 : NULL; } - return 0; // 命令不存在 + return 0; // 命令不存在 } // 执行命令并返回输出 -char *_execute_command(const char *command) { +char *_execute_command(const char *command) +{ FILE *fp; char buffer[1024]; char *output = NULL; @@ -235,7 +229,6 @@ char *_execute_command(const char *command) { perror("popen"); return NULL; } - // 读取命令的输出 while (fgets(buffer, sizeof(buffer), fp) != NULL) { size_t len = strlen(buffer); @@ -244,7 +237,7 @@ char *_execute_command(const char *command) { char *new_output = realloc(output, output_size); if (new_output == NULL) { perror("realloc"); - free(output); // 释放已分配的内存 + free(output); // 释放已分配的内存 pclose(fp); // 关闭管道 return NULL; } @@ -259,11 +252,10 @@ char *_execute_command(const char *command) { if (output_size > 0) { output[total_read] = '\0'; } - // 关闭管道 if (pclose(fp) == -1) { perror("pclose"); - free(output); // pclose 失败时释放内存 + free(output); // pclose 失败时释放内存 return NULL; } @@ -281,4 +273,3 @@ void remove_char(char *str, char c) } str[j] = '\0'; } - diff --git a/common.h b/common.h index 5a05c4e..dab8a99 100644 --- a/common.h +++ b/common.h @@ -27,7 +27,6 @@ #define BUFFER 1024 #define WHITELIST_IP_NUM 1024 - extern char *_time(); extern int _strlen(const char *str); extern void _printf(const char *format, ...); diff --git a/libcurl.c b/libcurl.c index 38bb650..dc4bcfe 100644 --- a/libcurl.c +++ b/libcurl.c @@ -1,6 +1,5 @@ #include "libcurl.h" - struct MemoryStruct { char *memory; size_t size; @@ -28,7 +27,7 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, voi } char *GetLocalAddr(char *url) -{ +{ CURL *curl_handle; CURLcode res; @@ -100,8 +99,7 @@ char *CurlGetIpArea(char *ip) { char url[256] = { 0 }; snprintf(url, sizeof(url), "https://qifu.baidu.com/ip/geo/v1/district?ip=%s", ip); - - + CURL *curl_handle; CURLcode res; @@ -169,13 +167,14 @@ char *CurlGetIpArea(char *ip) } // 函数用于从 cJSON 对象提取字段内容 -void parse_string_field(cJSON *parent, const char *field_name, char *output, size_t max_len) { +void parse_string_field(cJSON *parent, const char *field_name, char *output, size_t max_len) +{ cJSON *item = cJSON_GetObjectItemCaseSensitive(parent, field_name); if (cJSON_IsString(item) && item->valuestring) { strncpy(output, item->valuestring, max_len - 1); output[max_len - 1] = '\0'; // 确保字符串以 '\0' 结尾 } else { - output[0] = '\0'; // 如果字段不存在或不是字符串,设置为空字符串 + output[0] = '\0'; // 如果字段不存在或不是字符串,设置为空字符串 } } @@ -186,7 +185,6 @@ int parse_json_to_struct(const char *json_string, Response *response) fprintf(stderr, "Invalid input parameters!\n"); return -1; } - // 初始化结构体 memset(response, 0, sizeof(Response)); @@ -196,7 +194,6 @@ int parse_json_to_struct(const char *json_string, Response *response) fprintf(stderr, "Error parsing JSON: %s\n", cJSON_GetErrorPtr()); return -1; } - // 解析字段 parse_string_field(root, "code", response->code, sizeof(response->code)); parse_string_field(root, "ip", response->ip, sizeof(response->ip)); @@ -207,7 +204,6 @@ int parse_json_to_struct(const char *json_string, Response *response) cJSON_Delete(root); return -1; } - // 解析 data 对象 cJSON *data_item = cJSON_GetObjectItemCaseSensitive(root, "data"); if (cJSON_IsObject(data_item)) { @@ -222,20 +218,17 @@ int parse_json_to_struct(const char *json_string, Response *response) parse_string_field(data_item, "district", response->data.district, sizeof(response->data.district)); parse_string_field(data_item, "region", response->data.region, sizeof(response->data.region)); } - // ----------- 拼接 continent_country --------------- if (snprintf(response->continent_country, sizeof(response->continent_country), "%s%s", response->data.continent, response->data.country) >= sizeof(response->continent_country)) { fprintf(stderr, "continent_country truncated!\n"); } - //snprintf(response->continent_country, 256, "%s%s", response->data.continent, response->data.country); - + // 清理 JSON 对象 cJSON_Delete(root); return 0; } - /* int main(int argc, char *argv[]) { diff --git a/libcurl.h b/libcurl.h index 5cf0f2e..f1eab02 100644 --- a/libcurl.h +++ b/libcurl.h @@ -42,11 +42,8 @@ typedef struct { char continent_country[256]; } Response; - extern char *CurlGetIpArea(char *ip); extern char *GetLocalAddr(char *url); -extern int parse_json_to_struct(const char *json_string, Response *response); +extern int parse_json_to_struct(const char *json_string, Response * response); - - -#endif \ No newline at end of file +#endif diff --git a/libipset.c b/libipset.c index 22e7686..ed3895a 100644 --- a/libipset.c +++ b/libipset.c @@ -86,14 +86,12 @@ int create_ipset(char *set_name) ipset_fini(ipset); return -1; } - // 设置自定义错误和输出处理函数 if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) { fprintf(stderr, "设置自定义打印函数失败。\n"); ipset_fini(ipset); return -1; } - // 创建集合 char *args[] = { "ipset", "create", set_name, "hash:ip", NULL }; if (ipset_parse_argv(ipset, 4, args) != 0) { @@ -101,7 +99,6 @@ int create_ipset(char *set_name) return -1; } - ipset_fini(ipset); return 0; @@ -135,14 +132,12 @@ int add_ip_to_ipset(char *set_name, char *ip) ipset_fini(ipset); return -1; // 返回 -1,但不退出 } - // 设置自定义错误和输出处理函数 if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) { fprintf(stderr, "设置自定义打印函数失败。\n"); ipset_fini(ipset); return -1; } - // 将ip添加到集合 char *args[] = { "ipset", "add", set_name, ip, NULL }; if (ipset_parse_argv(ipset, 4, args) != 0) { @@ -150,7 +145,6 @@ int add_ip_to_ipset(char *set_name, char *ip) return -1; } - ipset_fini(ipset); return 0; // 始终返回 0,表示执行成功 @@ -173,7 +167,6 @@ int flush_ipset(char *set_name) ipset_fini(ipset); return -1; } - // 清空集合 char *args[] = { "ipset", "flush", set_name, NULL }; if (ipset_parse_argv(ipset, 3, args) != 0) { @@ -204,14 +197,12 @@ int get_ip_count_in_ipset(char *set_name) ipset_fini(ipset); return -1; } - // 列出集合 char *args[] = { "ipset", "list", set_name, NULL }; if (ipset_parse_argv(ipset, 3, args) != 0) { ipset_fini(ipset); return -1; } - // 释放资源 ipset_fini(ipset); return ip_count; diff --git a/libipset.h b/libipset.h index a05d001..c55cec5 100644 --- a/libipset.h +++ b/libipset.h @@ -5,12 +5,12 @@ #include #include #include -#include // 包含 inet_pton 函数 +#include // 包含 inet_pton 函数 #define BUFFER 1024 -#define MAX_CMD_LENGTH 256 // 或者根据需要调整 +#define MAX_CMD_LENGTH 256 // 或者根据需要调整 -extern int create_ipset( char *set_name); +extern int create_ipset(char *set_name); extern int add_ip_to_ipset(char *set_name, char *ip); extern int get_ip_count_in_ipset(char *set_name);