新版本采用libipset库操作ipset集合,采用libpcap、libcap抓包获取源IP
This commit is contained in:
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"alibaba-cloud.tongyi-lingma"
|
||||
]
|
||||
}
|
||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -1,13 +1,9 @@
|
||||
{
|
||||
"C_Cpp.errorSquiggles": "disabled",
|
||||
"files.associations": {
|
||||
"string.h": "c",
|
||||
"stdlib.h": "c",
|
||||
"ip2region.h": "c",
|
||||
"common.h": "c",
|
||||
"prctl.h": "c",
|
||||
"resource.h": "c",
|
||||
"wait.h": "c",
|
||||
"stdio.h": "c"
|
||||
"algorithm": "c",
|
||||
"cstdlib": "c"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -5,18 +5,22 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IPInfo struct {
|
||||
Code string `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data struct {
|
||||
Continent string `json:"continent"`
|
||||
Country string `json:"country"`
|
||||
} `json:"data"`
|
||||
IP string `json:"ip"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
func isValidIP(ip string) bool {
|
||||
return net.ParseIP(ip) != nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -24,16 +28,29 @@ func main() {
|
||||
log.Fatalf("用法: %s <IP>", os.Args[0])
|
||||
}
|
||||
|
||||
ip := os.Args[1]
|
||||
if !isValidIP(ip) {
|
||||
log.Fatalf("无效的 IP 地址: %s", ip)
|
||||
}
|
||||
|
||||
// 目标 URL
|
||||
url := "https://qifu.baidu.com/ip/geo/v1/district?ip=" + os.Args[1]
|
||||
url := "https://qifu.baidu.com/ip/geo/v1/district?ip=" + ip
|
||||
|
||||
// 创建 HTTP 客户端并设置超时时间
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
|
||||
// 发送 GET 请求
|
||||
resp, err := http.Get(url)
|
||||
resp, err := client.Get(url)
|
||||
if err != nil {
|
||||
log.Fatalf("发送 GET 请求时出错: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查 HTTP 响应状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Fatalf("HTTP 请求失败,状态码: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 读取响应体
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
|
||||
17
Makefile
17
Makefile
@@ -1,21 +1,26 @@
|
||||
CROSS_COMPILE ?=
|
||||
CC := $(CROSS_COMPILE)gcc
|
||||
STRIP := $(CROSS_COMPILE)strip
|
||||
CFLAGS += -g -Os -Wall -Iip2region -Iqqwry
|
||||
LIBS = -lm -static
|
||||
BIN := denyip
|
||||
CFLAGS += -g -Wall -Iip2region
|
||||
LIBS =
|
||||
BIN := a.out
|
||||
|
||||
# 使用shell命令获取库的链接选项
|
||||
LIBPCAP := $(shell pkg-config --libs --static libpcap)
|
||||
LIBCAP := $(shell pkg-config --libs --static libcap)
|
||||
LIBIPSET := $(shell pkg-config --libs --static libipset)
|
||||
|
||||
all: $(BIN) # 默认目标
|
||||
|
||||
ipquery: # Go 构建目标
|
||||
cd IP_region_query && CGO_ENABLED=0 go build -ldflags '-w -s'
|
||||
|
||||
$(BIN): main.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o qqwry/qqwry.o
|
||||
$(CC) $(CFLAGS) -o $(BIN) $^ $(LIBS)
|
||||
$(BIN): cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o
|
||||
$(CC) $(CFLAGS) -o $(BIN) $^ $(LIBPCAP) $(LIBCAP) $(LIBIPSET) $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(BIN) ipquery
|
||||
rm -rf main.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o qqwry/qqwry.o
|
||||
rm -rf cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o
|
||||
|
||||
50
README.md
50
README.md
@@ -8,17 +8,17 @@
|
||||
# Debian System
|
||||
apt install build-essential
|
||||
apt install golang
|
||||
apt install tcpdump procps iptables ipset
|
||||
apt install libpcap-dev libcap-dev libsystemd-dev
|
||||
|
||||
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP# make clean; make
|
||||
rm -rf denyip ipquery
|
||||
rm -rf main.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o qqwry/qqwry.o
|
||||
gcc -g -Os -Wall -Iip2region -Iqqwry -c main.c -o main.o
|
||||
gcc -g -Os -Wall -Iip2region -Iqqwry -c common.c -o common.o
|
||||
gcc -g -Os -Wall -Iip2region -Iqqwry -c ip2region/ip2region.c -o ip2region/ip2region.o
|
||||
gcc -g -Os -Wall -Iip2region -Iqqwry -c ip2region/xdb_searcher.c -o ip2region/xdb_searcher.o
|
||||
gcc -g -Os -Wall -Iip2region -Iqqwry -c qqwry/qqwry.c -o qqwry/qqwry.o
|
||||
gcc -g -Os -Wall -Iip2region -Iqqwry -o denyip main.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o qqwry/qqwry.o -lm -static
|
||||
rm -rf a.out ipquery
|
||||
rm -rf cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o
|
||||
gcc -g -Wall -Iip2region -c cap.c -o cap.o
|
||||
gcc -g -Wall -Iip2region -c common.c -o common.o
|
||||
gcc -g -Wall -Iip2region -c ip2region/ip2region.c -o ip2region/ip2region.o
|
||||
gcc -g -Wall -Iip2region -c ip2region/xdb_searcher.c -o ip2region/xdb_searcher.o
|
||||
gcc -g -Wall -Iip2region -c libipset.c -o libipset.o
|
||||
gcc -g -Wall -Iip2region -o a.out cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o -lpcap -ldbus-1 -lsystemd -L/usr/lib64 -lcap -lipset -lmnl
|
||||
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP#
|
||||
~~~
|
||||
|
||||
@@ -26,22 +26,22 @@ root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP#
|
||||
|
||||
~~~bash
|
||||
|
||||
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP# ./denyip -h
|
||||
DenyIp
|
||||
Linux system firewall, reject non-Chinese IP
|
||||
Email: aixiao@aixiao.me
|
||||
Version: 0.1
|
||||
Usage: ./denyip [-i eth0|-h|-?] [start|stop]
|
||||
Options:
|
||||
stop Enable firewall rules
|
||||
start Disable firewall rules
|
||||
Parameters:
|
||||
-h|? Help info
|
||||
-i interface name
|
||||
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP# ./a.out -h
|
||||
DenyIP version 0.2
|
||||
拒绝Linux服务器非大陆IP工具
|
||||
MAIL: aixiao@aixiao.me
|
||||
Date: 20241024
|
||||
Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]
|
||||
-d Daemon mode
|
||||
-i interface (default eth0)
|
||||
-s regular signal (default start|stop)
|
||||
start Enable Iptables rule
|
||||
stop Disable Iptables rule
|
||||
-h|-? Help Information
|
||||
|
||||
|
||||
root@niuyuling:~/DenyIP# killall denyip # 关闭
|
||||
root@niuyuling:~/DenyIP# ./denyip -i eth0 # 启动
|
||||
root@niuyuling:~/DenyIP# ./denyip start # Iptables 规则打开
|
||||
root@niuyuling:~/DenyIP# ./denyip stop # Iptables 规则关闭
|
||||
root@niuyuling:~/DenyIP# killall -15 denyip # 关闭
|
||||
root@niuyuling:~/DenyIP# ./denyip -i eth0 # 启动
|
||||
root@niuyuling:~/DenyIP# ./denyip -s start # Iptables 规则打开
|
||||
root@niuyuling:~/DenyIP# ./denyip -s stop # Iptables 规则关闭
|
||||
~~~
|
||||
|
||||
439
cap.c
Normal file
439
cap.c
Normal file
@@ -0,0 +1,439 @@
|
||||
#include "cap.h"
|
||||
#include "common.h"
|
||||
#include "libipset.h"
|
||||
|
||||
#define CACHE_TTL 600 // 设定缓存的存活时间为 600 秒 (10 分钟)
|
||||
#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址
|
||||
|
||||
struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点
|
||||
int cache_size = 0; // 当前缓存中的 IP 数量
|
||||
|
||||
pid_t pid = -1;
|
||||
|
||||
#define SHM_SIZE 1024 // 共享内存大小
|
||||
#define SHM_KEY 1234 // 共享内存键值
|
||||
int shmid = -1;
|
||||
int RULE_NAME_NUMBER = 0;
|
||||
char *RULE_NAME = NULL;
|
||||
|
||||
char *ip2region_area = NULL; // ip2region 解析结果
|
||||
char *command_result = NULL; // 执行命令的结果
|
||||
|
||||
// 定义链表结构,用于缓存 IP 地址
|
||||
struct ip_cache_node {
|
||||
char ip[INET_ADDRSTRLEN]; // 存储 IP 地址
|
||||
time_t timestamp; // 记录缓存时间
|
||||
struct ip_cache_node *next; // 指向下一个节点
|
||||
};
|
||||
|
||||
// 检查 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)
|
||||
{
|
||||
// 如果缓存大小超过限制,移除最早的 IP
|
||||
if (cache_size >= MAX_CACHE_SIZE) {
|
||||
struct ip_cache_node *current = ip_cache_head;
|
||||
struct ip_cache_node *prev = NULL;
|
||||
|
||||
// 找到链表的最后一个节点
|
||||
while (current->next != NULL) {
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
// 移除最后一个节点(最早的 IP)
|
||||
if (prev != NULL) {
|
||||
prev->next = NULL;
|
||||
} else {
|
||||
ip_cache_head = NULL;
|
||||
}
|
||||
free(current);
|
||||
cache_size--;
|
||||
}
|
||||
|
||||
// 创建新的缓存节点并添加到链表头部
|
||||
struct ip_cache_node *new_node = (struct ip_cache_node *)malloc(sizeof(struct ip_cache_node));
|
||||
if (new_node == NULL) {
|
||||
perror("malloc");
|
||||
return;
|
||||
}
|
||||
strncpy(new_node->ip, ip, INET_ADDRSTRLEN);
|
||||
new_node->timestamp = time(NULL); // 记录当前时间
|
||||
new_node->next = ip_cache_head;
|
||||
ip_cache_head = new_node;
|
||||
cache_size++;
|
||||
}
|
||||
|
||||
// 清理缓存链表,释放所有节点的内存
|
||||
void free_ip_cache()
|
||||
{
|
||||
struct ip_cache_node *current = ip_cache_head;
|
||||
while (current != NULL) {
|
||||
struct ip_cache_node *next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
ip_cache_head = NULL;
|
||||
cache_size = 0;
|
||||
}
|
||||
|
||||
// 回调函数,在捕获到每个数据包时调用
|
||||
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
{
|
||||
int ethernet_header_len = 14;
|
||||
struct ip *ip_header = (struct ip *)(packet + ethernet_header_len);
|
||||
char src_ip[INET_ADDRSTRLEN] = { 0 };
|
||||
|
||||
// 地域白名单
|
||||
char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||
char _REGION_LIST[BUFFER] = { 0 };
|
||||
const char *REGION_ENV = NULL;
|
||||
|
||||
int r = 0;
|
||||
//char *t = _time();
|
||||
|
||||
inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN);
|
||||
//_printf("%s\n", src_ip);
|
||||
|
||||
|
||||
// 如果 IP 地址已在缓存中且未过期,则跳过查询
|
||||
if (is_ip_in_cache(src_ip)) {
|
||||
printf(RED "IP:%s 已在缓存中,跳过查询\n" REDEND, src_ip);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 执行查询并添加到缓存
|
||||
ip2region_area = ip2region("ip2region/ip2region.xdb", src_ip);
|
||||
if (ip2region_area == NULL) {
|
||||
printf(RED "ip2region 解析地域错误\n" REDEND);
|
||||
return;
|
||||
}
|
||||
// 取环境变量
|
||||
REGION_ENV = getenv("REGION");
|
||||
if (REGION_ENV != NULL) {
|
||||
printf("REGION: %s\n", REGION_ENV);
|
||||
strcpy(_REGION_LIST, REGION_ENV);
|
||||
} else {
|
||||
strcpy(_REGION_LIST, "局域网 内网 中国 ");
|
||||
}
|
||||
|
||||
split_string(_REGION_LIST, " ", _region_list);
|
||||
if (isregion(ip2region_area, _region_list) == 1) { // 返回1表示在白名单列表
|
||||
;
|
||||
} else {
|
||||
//puts(ip2region_area);
|
||||
|
||||
char ip_query_command[256] = { 0 };
|
||||
snprintf(ip_query_command, sizeof(ip_query_command), "./IP_region_query/ipquery %s", src_ip);
|
||||
if (cache_size < MAX_CACHE_SIZE) // 缓存IP数不够预备设定值
|
||||
{
|
||||
sleep(1);
|
||||
printf("缓存IP数 %d\n", cache_size);
|
||||
}
|
||||
command_result = _execute_command(ip_query_command);
|
||||
if (command_result != NULL) {
|
||||
add_ip_to_cache(src_ip); // 添加 IP 到缓存
|
||||
|
||||
char *p = strstr(command_result, "中国");
|
||||
if (p == NULL) {
|
||||
printf(RED "%s %s\n" REDEND, src_ip, command_result);
|
||||
r = add_ip_to_ipset(RULE_NAME, src_ip);
|
||||
printf("add_ip_to_ipset %d\n", r);
|
||||
}
|
||||
|
||||
free(command_result);
|
||||
command_result = NULL;
|
||||
} else {
|
||||
;
|
||||
}
|
||||
|
||||
if (command_result != NULL)
|
||||
free(command_result);
|
||||
}
|
||||
|
||||
if (ip2region_area != NULL)
|
||||
{
|
||||
free(ip2region_area);
|
||||
ip2region_area = NULL;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
printf("DenyIP version %s\n", _VERSION);
|
||||
puts("拒绝Linux服务器非大陆IP工具");
|
||||
puts("MAIL: aixiao@aixiao.me");
|
||||
puts("Date: 20241024");
|
||||
puts(" Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]");
|
||||
puts(" -d Daemon mode");
|
||||
puts(" -i interface (default eth0)");
|
||||
puts(" -s regular signal (default start|stop) ");
|
||||
puts(" start Enable Iptables rule");
|
||||
puts(" stop Disable Iptables rule");
|
||||
puts(" -h|-? Help Information");
|
||||
puts("");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
pcap_if_t *alldevs, *device;
|
||||
pcap_t *handle; // 会话句柄
|
||||
struct bpf_program fp; // 编译后的过滤器
|
||||
|
||||
void cleanup_(int signum)
|
||||
{
|
||||
|
||||
printf("Received signal %d, cleaning up...\n", signum);
|
||||
|
||||
// 释放共享内存
|
||||
if (RULE_NAME != NULL) {
|
||||
shmdt(RULE_NAME);
|
||||
shmctl(shmid, IPC_RMID, NULL);
|
||||
}
|
||||
|
||||
// 在程序结束时,清理缓存链表
|
||||
free_ip_cache();
|
||||
if (ip2region_area != NULL) {
|
||||
free(ip2region_area);
|
||||
ip2region_area = NULL;
|
||||
}
|
||||
if (command_result != NULL) {
|
||||
free(command_result);
|
||||
command_result = NULL;
|
||||
}
|
||||
|
||||
// 清理
|
||||
pcap_freecode(&fp);
|
||||
pcap_freealldevs(alldevs); // 释放设备列表
|
||||
pcap_close(handle); // 关闭会话句柄
|
||||
|
||||
// 终止子进程
|
||||
if (pid > 0) {
|
||||
kill(pid, SIGTERM);
|
||||
}
|
||||
|
||||
// 退出主进程
|
||||
exit(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// 注册 SIGTERM 信号处理函数
|
||||
signal(SIGTERM, cleanup_);
|
||||
|
||||
|
||||
int opt;
|
||||
char errbuf[PCAP_ERRBUF_SIZE]; // 错误缓冲区
|
||||
|
||||
|
||||
char protocol[] = "tcp";
|
||||
|
||||
char interface[256] = "{ 0 }";
|
||||
strcpy(interface, "eth0");
|
||||
|
||||
memset(&alldevs, 0, sizeof(alldevs));
|
||||
memset(&device, 0, sizeof(device));
|
||||
memset(errbuf, 0, PCAP_ERRBUF_SIZE);
|
||||
|
||||
char Ipset_Command[BUFFER];
|
||||
|
||||
while ((opt = getopt(argc, argv, "di:s:h?")) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
if (daemon(1, 1)) {
|
||||
perror("daemon");
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
strcpy(interface, optarg);
|
||||
break;
|
||||
case 's':
|
||||
if (strcmp(optarg, "start") == 0) {
|
||||
memset(Ipset_Command, 0, BUFFER);
|
||||
// 将 MAXIPSET_RULT_NAME_NUM 替换为实际值
|
||||
snprintf(Ipset_Command, sizeof(Ipset_Command),
|
||||
"for n in $(seq 0 %d); do iptables -A INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done",
|
||||
MAXIPSET_RULT_NAME_NUM);
|
||||
system(Ipset_Command);
|
||||
|
||||
//system("for n in $(seq 0 MAXIPSET_RULT_NAME_NUM); do iptables -A INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done");
|
||||
exit(0);
|
||||
} else if (strcmp(optarg, "stop") == 0) {
|
||||
memset(Ipset_Command, 0, BUFFER);
|
||||
// 将 MAXIPSET_RULT_NAME_NUM 替换为实际值
|
||||
snprintf(Ipset_Command, sizeof(Ipset_Command),
|
||||
"for n in $(seq 0 %d); do iptables -D INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done",
|
||||
MAXIPSET_RULT_NAME_NUM);
|
||||
system(Ipset_Command);
|
||||
|
||||
//system("for n in $(seq 0 MAXIPSET_RULT_NAME_NUM); do iptables -D INPUT -p tcp -m set --match-set root$n src -j DROP 2> /dev/null; done");
|
||||
exit(0);
|
||||
} else {
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
usage();
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 创建共享内存
|
||||
shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666);
|
||||
if (shmid < 0) {
|
||||
perror("shmget");
|
||||
exit(1);
|
||||
}
|
||||
// 连接共享内存到进程地址空间
|
||||
RULE_NAME = (char *)shmat(shmid, NULL, 0);
|
||||
if (RULE_NAME == (char *)-1) {
|
||||
perror("shmat");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pid = fork(); // 创建子进程
|
||||
if (pid == 0) // 子进程
|
||||
{
|
||||
|
||||
int count = 0;
|
||||
snprintf(RULE_NAME, BUFFER, "root%d", RULE_NAME_NUMBER);
|
||||
|
||||
if (create_ipset(RULE_NAME) != 0) {
|
||||
fprintf(stderr, "创建 IPSet %s 失败\n", RULE_NAME);
|
||||
}
|
||||
while (1) {
|
||||
|
||||
printf("子进程当前Ipset Rule 名 %s\n", RULE_NAME);
|
||||
|
||||
count = get_ip_count_in_ipset(RULE_NAME);
|
||||
if (count >= 0) {
|
||||
printf("IPSet %s 中的 IP 数量: %d\n", RULE_NAME, count);
|
||||
if (count >= MAXIPSET && RULE_NAME_NUMBER <= MAXIPSET_RULT_NAME_NUM) // RULE_中的IP数量不超过MAXIPSET,并且集合不能超过 MAXIPSET_RULT_NAME_NUM 个
|
||||
{
|
||||
RULE_NAME_NUMBER++;
|
||||
|
||||
snprintf(RULE_NAME, BUFFER, "root%d", RULE_NAME_NUMBER); // 更新规则名称
|
||||
// 创建新的 IPSet
|
||||
if (create_ipset(RULE_NAME) != 0) {
|
||||
printf("创建 IPSet %s 失败\n", RULE_NAME);
|
||||
} else {
|
||||
char iptables_command[256];
|
||||
sprintf(iptables_command, "iptables -I INPUT -m set --match-set %s src -j DROP", RULE_NAME);
|
||||
system(iptables_command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (RULE_NAME_NUMBER == MAXIPSET_RULT_NAME_NUM) {
|
||||
printf("已达到最大规则数限制,停止创建新规则。\n");
|
||||
printf("请手动清理Ipset规则\n");
|
||||
}
|
||||
}
|
||||
|
||||
sleep(3); // 每 3 秒检查一次
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 查找可用的网络设备
|
||||
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
|
||||
fprintf(stderr, "无法找到设备: %s\n", errbuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 打印可用设备列表
|
||||
printf("可用的设备:\n");
|
||||
for (device = alldevs; device != NULL; device = device->next) {
|
||||
printf("设备: %s\n", device->name);
|
||||
}
|
||||
|
||||
// 打开设备以进行数据包捕获
|
||||
handle = pcap_open_live(interface, BUFSIZ, 1, 1000, errbuf);
|
||||
if (handle == NULL) {
|
||||
fprintf(stderr, "无法打开设备 %s: %s\n", interface, errbuf);
|
||||
pcap_freealldevs(alldevs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 编译过滤器
|
||||
if (pcap_compile(handle, &fp, protocol, 0, PCAP_NETMASK_UNKNOWN) == -1) {
|
||||
fprintf(stderr, "无法编译过滤器 %s: %s\n", protocol, pcap_geterr(handle));
|
||||
pcap_close(handle);
|
||||
pcap_freealldevs(alldevs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 设置过滤器
|
||||
if (pcap_setfilter(handle, &fp) == -1) {
|
||||
fprintf(stderr, "无法设置过滤器 %s: %s\n", protocol, pcap_geterr(handle));
|
||||
pcap_freecode(&fp);
|
||||
pcap_close(handle);
|
||||
pcap_freealldevs(alldevs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// 开始捕获数据包
|
||||
if (pcap_loop(handle, 0, packet_handler, NULL) < 0) {
|
||||
fprintf(stderr, "捕获数据包时出错: %s\n", pcap_geterr(handle));
|
||||
pcap_freecode(&fp);
|
||||
pcap_close(handle);
|
||||
pcap_freealldevs(alldevs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 在程序结束时,清理缓存链表
|
||||
free_ip_cache();
|
||||
|
||||
// 清理
|
||||
pcap_freecode(&fp);
|
||||
pcap_freealldevs(alldevs); // 释放设备列表
|
||||
pcap_close(handle); // 关闭会话句柄
|
||||
|
||||
return 0;
|
||||
}
|
||||
31
cap.h
Normal file
31
cap.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef CAP_H
|
||||
#define CAP_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pcap.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ip.h> // IP header
|
||||
#include <netinet/tcp.h> // TCP header
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ip2region/ip2region.h"
|
||||
#include "qqwry/qqwry.h"
|
||||
|
||||
#define RED "\033[31m"
|
||||
#define REDEND "\033[0m"
|
||||
|
||||
#define MAXIPSET 65535
|
||||
#define MAXIPSET_RULT_NAME_NUM 26
|
||||
|
||||
#define _VERSION "0.2"
|
||||
|
||||
#endif
|
||||
59
common.c
59
common.c
@@ -17,7 +17,7 @@ int _strlen(char *str)
|
||||
}
|
||||
|
||||
// 自定义 printf 函数
|
||||
void my_printf(const char *format, ...)
|
||||
void _printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
@@ -51,6 +51,7 @@ void my_printf(const char *format, ...)
|
||||
perror("Unable to open log file");
|
||||
}
|
||||
|
||||
|
||||
va_end(args); // 结束对变参列表的处理
|
||||
}
|
||||
|
||||
@@ -117,7 +118,7 @@ int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM])
|
||||
return 0; // 没有匹配,返回0
|
||||
}
|
||||
|
||||
int8_t copy_new_mem(char *src, int src_len, char **dest)
|
||||
int8_t _copy_new_mem(char *src, int src_len, char **dest)
|
||||
{
|
||||
*dest = (char *)malloc(src_len + 1);
|
||||
if (*dest == NULL)
|
||||
@@ -152,7 +153,7 @@ int is_valid_ip(const char *ip)
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
int nice_(int increment)
|
||||
int _nice(int increment)
|
||||
{
|
||||
int oldprio = getpriority(PRIO_PROCESS, getpid());
|
||||
printf("%d\n", oldprio);
|
||||
@@ -161,7 +162,7 @@ int nice_(int increment)
|
||||
}
|
||||
|
||||
// 判断命令是否存在
|
||||
int command_exists(const char *command)
|
||||
int _command_exists(const char *command)
|
||||
{
|
||||
char buffer[BUFFER];
|
||||
snprintf(buffer, sizeof(buffer), "%s > /dev/null 2>&1", command);
|
||||
@@ -169,3 +170,53 @@ int command_exists(const char *command)
|
||||
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
// 定义一个函数,执行命令并返回输出
|
||||
char *_execute_command(const char *command) {
|
||||
FILE *fp;
|
||||
char buffer[1024];
|
||||
char *output = NULL;
|
||||
size_t output_size = 0;
|
||||
size_t total_read = 0;
|
||||
|
||||
// 打开管道,执行命令
|
||||
fp = popen(command, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 读取命令的输出
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
size_t len = strlen(buffer);
|
||||
if (total_read + len + 1 > output_size) {
|
||||
output_size = output_size == 0 ? 128 : output_size * 2;
|
||||
char *new_output = realloc(output, output_size);
|
||||
if (new_output == NULL) {
|
||||
perror("realloc");
|
||||
free(output); // 释放已分配的内存
|
||||
pclose(fp); // 关闭管道
|
||||
return NULL;
|
||||
}
|
||||
output = new_output;
|
||||
}
|
||||
// 复制内容并增加总计读取的长度
|
||||
strcpy(output + total_read, buffer);
|
||||
total_read += len;
|
||||
}
|
||||
|
||||
// 确保输出以 null 结尾
|
||||
if (output_size > 0) {
|
||||
output[total_read] = '\0';
|
||||
}
|
||||
|
||||
// 关闭管道
|
||||
if (pclose(fp) == -1) {
|
||||
perror("pclose");
|
||||
free(output); // pclose 失败时释放内存
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
15
common.h
15
common.h
@@ -22,21 +22,24 @@
|
||||
#include <signal.h>
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#define PRINT_LOG_FILE "Gateway.log"
|
||||
#define PRINT_LOG_FILE "denyip.log"
|
||||
#define BUFFER 1024
|
||||
#define WHITELIST_IP_NUM 1024
|
||||
|
||||
|
||||
extern char *_time();
|
||||
extern int _strlen(char *str);
|
||||
extern void my_printf(const char *format, ...);
|
||||
extern void _printf(const char *format, ...);
|
||||
extern int _nice(int increment);
|
||||
|
||||
extern void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]);
|
||||
extern int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM]);
|
||||
extern char *_time();
|
||||
extern int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM]);
|
||||
|
||||
extern int8_t copy_new_mem(char *src, int src_len, char **dest);
|
||||
extern int8_t _copy_new_mem(char *src, int src_len, char **dest);
|
||||
|
||||
extern int is_valid_ip(const char *ip);
|
||||
extern int nice_(int increment);
|
||||
extern int command_exists(const char *command);
|
||||
extern int _command_exists(const char *command);
|
||||
extern char *_execute_command(const char *command);
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
20
ip2region/main.c
Normal file
20
ip2region/main.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "ip2region.h"
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
// 执行查询并添加到缓存
|
||||
char *area = ip2region("ip2region.xdb", "1.1.1.1");
|
||||
if (area == NULL) {
|
||||
return -1;
|
||||
}
|
||||
puts(area);
|
||||
|
||||
|
||||
free(area);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Binary file not shown.
246
libipset.c
Normal file
246
libipset.c
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "libipset.h"
|
||||
|
||||
// 自定义输出处理函数
|
||||
int custom_output_handler(struct ipset_session *session, void *p, const char *msg, ...)
|
||||
{
|
||||
int *ip_count = (int *)p;
|
||||
char buffer[BUFFER];
|
||||
|
||||
// 格式化输出消息
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
vsnprintf(buffer, sizeof(buffer), msg, args);
|
||||
va_end(args);
|
||||
|
||||
// 输出调试信息
|
||||
//printf("Buffer: %s\n", buffer); // 调试输出
|
||||
|
||||
if (strlen(buffer) > 1) {
|
||||
char temp[BUFFER];
|
||||
char *p1 = strstr(buffer, "Number of entries:");
|
||||
if (p1 != NULL) {
|
||||
char *p2 = strstr(p1, "\n");
|
||||
if (p2 != NULL) {
|
||||
size_t len = p2 - p1; // 计算长度
|
||||
if (len < BUFFER) {
|
||||
strncpy(temp, p1, len);
|
||||
temp[len] = '\0'; // 确保字符串结束
|
||||
//puts(temp);
|
||||
|
||||
// 查找冒号并提取数量
|
||||
char *p3 = strstr(temp, ":");
|
||||
if (p3 != NULL) {
|
||||
// 提取数字
|
||||
int count = atoi(p3 + 1); // 从冒号后面开始转换
|
||||
*ip_count += count; // 更新计数
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int custom_output_handler_(struct ipset_session *session, void *p, const char *msg, ...)
|
||||
{
|
||||
char buffer[BUFFER];
|
||||
|
||||
// 格式化输出消息
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
vsnprintf(buffer, sizeof(buffer), msg, args);
|
||||
va_end(args);
|
||||
|
||||
// 输出调试信息
|
||||
//printf("Buffer: %s\n", buffer); // 调试输出
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 自定义错误处理函数
|
||||
int custom_error_handler(struct ipset *ipset, void *p, int errnum, const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
fprintf(stderr, "自定义错误: ");
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
return 0; // 返回0表示处理成功
|
||||
}
|
||||
|
||||
// 创建 IPSet,如果它不存在
|
||||
int create_ipset(char *set_name)
|
||||
{
|
||||
struct ipset *ipset = ipset_init();
|
||||
if (!ipset) {
|
||||
fprintf(stderr, "Failed to initialize IPSet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipset_load_types();
|
||||
|
||||
struct ipset_session *session = ipset_session(ipset);
|
||||
if (!session) {
|
||||
fprintf(stderr, "Failed to create IPSet session\n");
|
||||
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) {
|
||||
ipset_fini(ipset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ipset_fini(ipset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 向指定的 ipset 添加 IP
|
||||
int add_ip_to_ipset(char *set_name, char *ip)
|
||||
{
|
||||
struct ipset *ipset = NULL;
|
||||
struct ipset_session *session = NULL;
|
||||
|
||||
// 初始化 ipset 和 session
|
||||
ipset = ipset_init();
|
||||
if (!ipset) {
|
||||
fprintf(stderr, "初始化 IPSet 失败\n");
|
||||
return -1; // 返回 -1,但不退出
|
||||
}
|
||||
|
||||
ipset_load_types();
|
||||
|
||||
session = ipset_session(ipset);
|
||||
if (!session) {
|
||||
fprintf(stderr, "创建 IPSet 会话失败\n");
|
||||
ipset_fini(ipset);
|
||||
return -1; // 返回 -1,但不退出
|
||||
}
|
||||
// 设置 IPSet 名称
|
||||
if (ipset_session_data_set(session, IPSET_SETNAME, set_name) != 0) {
|
||||
fprintf(stderr, "设置 IPSet 名称失败\n");
|
||||
ipset_session_fini(session);
|
||||
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) {
|
||||
ipset_fini(ipset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ipset_fini(ipset);
|
||||
|
||||
return 0; // 始终返回 0,表示执行成功
|
||||
}
|
||||
|
||||
// 定义一个函数来清空指定名称的 ipset 集合
|
||||
int flush_ipset(char *set_name)
|
||||
{
|
||||
struct ipset *ipset = ipset_init();
|
||||
if (!ipset) {
|
||||
fprintf(stderr, "Failed to initialize IPSet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipset_load_types();
|
||||
|
||||
// 设置自定义错误和输出处理函数
|
||||
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", "flush", set_name, NULL };
|
||||
if (ipset_parse_argv(ipset, 3, args) != 0) {
|
||||
ipset_fini(ipset);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("IPSet %s flushed successfully\n", set_name);
|
||||
ipset_fini(ipset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 获取指定 IPSet 中的 IP 数量
|
||||
int get_ip_count_in_ipset(char *set_name)
|
||||
{
|
||||
int ip_count = 0;
|
||||
struct ipset *ipset = ipset_init();
|
||||
if (!ipset) {
|
||||
fprintf(stderr, "初始化 ipset 失败。\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipset_load_types();
|
||||
|
||||
// 设置自定义错误和输出处理函数
|
||||
if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler, &ip_count) != 0) {
|
||||
fprintf(stderr, "设置自定义打印函数失败。\n");
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
int main()
|
||||
{
|
||||
int r;
|
||||
char *set_name = "root";
|
||||
char *ip = "1.1.1.2";
|
||||
|
||||
// 确保 IPSet 已存在
|
||||
r = create_ipset(set_name);
|
||||
printf("create_ipset %d\n", r);
|
||||
|
||||
r = flush_ipset(set_name);
|
||||
printf("flush_ipset %d\n", r);
|
||||
|
||||
// 尝试添加 IP
|
||||
r = add_ip_to_ipset(set_name, ip);
|
||||
printf("add_ip_to_ipset %d\n", r);
|
||||
|
||||
// 获取并打印 IPSet 中的 IP 数量
|
||||
int count = get_ip_count_in_ipset(set_name);
|
||||
if (count >= 0) {
|
||||
printf("IPSet %s 中的 IP 数量: %d\n", set_name, count);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
17
libipset.h
Normal file
17
libipset.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef LIBIPSET_H
|
||||
#define LIBIPSET_H
|
||||
|
||||
#include "common.h"
|
||||
#include <libipset/ipset.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <arpa/inet.h> // 包含 inet_pton 函数
|
||||
|
||||
#define BUFFER 1024
|
||||
#define MAX_CMD_LENGTH 256 // 或者根据需要调整
|
||||
|
||||
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);
|
||||
|
||||
#endif
|
||||
BIN
libipset.o
Normal file
BIN
libipset.o
Normal file
Binary file not shown.
2
main.c
2
main.c
@@ -1,5 +1,6 @@
|
||||
#include "main.h"
|
||||
|
||||
char IPSET_LIST[256] = {0};
|
||||
|
||||
void denyip_help()
|
||||
{
|
||||
@@ -171,6 +172,7 @@ int main(int argc, char *argv[])
|
||||
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) {
|
||||
|
||||
1
main.h
1
main.h
@@ -20,6 +20,7 @@
|
||||
#define WHITELIST_IP_NUM 1024
|
||||
#define MAXIPSET 65534
|
||||
|
||||
|
||||
char *xdb_path = "ip2region.xdb";
|
||||
pid_t pid1, pid2; // 保存子进程的 PID
|
||||
|
||||
|
||||
18
qqwry/main.c
Normal file
18
qqwry/main.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
#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;
|
||||
|
||||
|
||||
}
|
||||
@@ -52,7 +52,8 @@ int qqwry_match(char *pattern, char *subject)
|
||||
return ret;
|
||||
}
|
||||
|
||||
iconv_t initialize_iconv(const char *target, const char *src) {
|
||||
iconv_t initialize_iconv(const char *target, const char *src)
|
||||
{
|
||||
// 创建转换描述符
|
||||
iconv_t iconvDesc = iconv_open(target, src);
|
||||
|
||||
@@ -60,9 +61,8 @@ iconv_t initialize_iconv(const char *target, const char *src) {
|
||||
if (iconvDesc == (iconv_t) - 1) {
|
||||
// 如果失败,打印错误信息并返回 NULL
|
||||
fprintf(stderr, "Error: Conversion from '%s' to '%s' is not available.\n", src, target);
|
||||
return (iconv_t)NULL;
|
||||
return (iconv_t) NULL;
|
||||
}
|
||||
|
||||
// 成功时返回 iconv_t 描述符
|
||||
return iconvDesc;
|
||||
}
|
||||
@@ -165,8 +165,8 @@ void qqwry_back(unsigned int byte)
|
||||
qqwry_seek(currPos - byte);
|
||||
}
|
||||
|
||||
|
||||
char *long2ip(int ip) {
|
||||
char *long2ip(int ip)
|
||||
{
|
||||
// 分配16字节内存用于存储IP字符串
|
||||
char *ip_str = malloc(16 * sizeof(char));
|
||||
|
||||
@@ -175,13 +175,8 @@ char *long2ip(int ip) {
|
||||
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);
|
||||
snprintf(ip_str, 16, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF);
|
||||
|
||||
return ip_str;
|
||||
}
|
||||
@@ -341,24 +336,15 @@ int get_location(char *ip)
|
||||
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
|
||||
readvalue(3, (int *)(&tmp_offset)); // the offset pointing to the data
|
||||
get_data(tmp_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *qqwry_(char *ip)
|
||||
char *qqwry_(char *dat, char *ip)
|
||||
{
|
||||
char *qqdb_path = "qqwry.dat";
|
||||
if (access(qqdb_path, F_OK) == -1) { // 判断 ip2region 地址定位库是否存在
|
||||
qqdb_path = "qqwry/qqwry.dat";
|
||||
if (access(qqdb_path, F_OK) == -1) {
|
||||
printf("qqwry.dat DOESN'T EXIST!\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
qqwry_init(qqdb_path);
|
||||
|
||||
qqwry_init(dat);
|
||||
|
||||
get_location(ip);
|
||||
//printf("%s-%s %d\n", ip_defaults.parent_data, ip_defaults.child_data, ip_defaults.isp);
|
||||
|
||||
@@ -28,4 +28,4 @@ void qqwry_back(unsigned int byte);
|
||||
int get_location(char *ip);
|
||||
int gbk2utf8(char *utf8_str, char *gbk_str);
|
||||
|
||||
extern char *qqwry_(char *ip);
|
||||
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