25 Commits
0.2 ... main

Author SHA1 Message Date
387ecea2d0 微小优化 2025-07-25 14:14:11 +08:00
9f84e29852 微小优化 2025-07-25 11:37:14 +08:00
c27df40923 增加白名单支持,还未大量测试 2025-07-24 15:05:03 +08:00
62013fbab9 优化 2025-07-23 15:50:53 +08:00
1361b15f79 优化 2025-07-23 15:00:23 +08:00
1440451f8a 修改百度API地址 2025-07-23 14:27:02 +08:00
bd21381806 20250515 2025-05-15 15:09:58 +08:00
6a4fb872f7 Add leak_detector_c 2025-04-24 10:01:18 +08:00
1c28d55681 20250423 2025-04-23 11:41:06 +08:00
1e00348e84 优化 2025-03-07 09:38:51 +08:00
5e441c068f 优化:
添加主要处理函数Processing_IP_addresses(src_ip);
数据处理放到cache.c
暂时未发现Bug
2025-02-17 12:59:02 +08:00
685b29a045 增加中国IP缓存 2025-01-21 17:06:12 +08:00
5028d24a32 优化 2025-01-20 09:46:18 +08:00
a3712fde22 优化 2025-01-16 16:32:39 +08:00
a79a59bd97 稍微优化 2025-01-15 15:30:12 +08:00
3b902877b5 新增加静态构建 2025-01-14 22:56:23 +08:00
e926ce3c0b 增加libcurl库调用百度API,与原来的的go命令执行调用API两种。libcurl涉及静态链接,考虑使用哪种? 2025-01-14 15:14:32 +08:00
b45c747ba4 优化 2025-01-07 18:04:33 +08:00
25a5790929 优化golang工具 2025-01-07 17:54:15 +08:00
22f3c339ce 规范Go变量 2025-01-07 12:45:18 +08:00
d25a3a257b 修改文档 2024-12-27 14:40:33 +08:00
0c02220245 修改文档 2024-12-09 16:12:32 +08:00
a5446848a1 增加客户端信息 2024-11-07 17:17:46 +08:00
8cff88a666 增加客户端信息 2024-11-07 10:03:14 +08:00
a568c3faa5 修改获取ipquery查询结果规则 2024-11-06 09:37:54 +08:00
61 changed files with 8456 additions and 291 deletions

View File

@@ -5,6 +5,13 @@
"prctl.h": "c", "prctl.h": "c",
"algorithm": "c", "algorithm": "c",
"cstdlib": "c", "cstdlib": "c",
"libipset.h": "c" "libipset.h": "c",
"array": "c",
"cache.h": "c",
"errno.h": "c",
"stdlib.h": "c",
"string.h": "c",
"stat.h": "c",
"leak_detector_c.h": "c"
} }
} }

Binary file not shown.

View File

@@ -11,62 +11,141 @@ import (
"time" "time"
) )
type IPInfo struct { // Response 结构体用于存储整个JSON响应
Msg string `json:"msg"` type JSON struct {
Data struct { Code string `json:"code"`
Continent string `json:"continent"` Data Data `json:"data"`
Country string `json:"country"` IP string `json:"ip"`
} `json:"data"` }
// Data 结构体用于存储"data"字段下的详细信息
type Data struct {
Continent string `json:"continent"`
Country string `json:"country"`
Zipcode string `json:"zipcode"`
Owner string `json:"owner"`
Isp string `json:"isp"`
Adcode string `json:"adcode"`
Prov string `json:"prov"`
City string `json:"city"`
District string `json:"district"`
} }
func isValidIP(ip string) bool { func isValidIP(ip string) bool {
return net.ParseIP(ip) != nil return net.ParseIP(ip) != nil
} }
func SaveBytesToFile(data []byte, filename string, syncToDisk bool) error {
if filename == "" {
return fmt.Errorf("filename cannot be empty")
}
file, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return fmt.Errorf("failed to open file %q: %w", filename, err)
}
defer file.Close()
_, err = file.Write(data)
if err != nil {
return fmt.Errorf("failed to write to file %q: %w", filename, err)
}
if syncToDisk {
err = file.Sync()
if err != nil {
return fmt.Errorf("failed to sync data to disk for file %q: %w", filename, err)
}
}
return nil
}
func main() { func main() {
var (
err error
IP_ADDR string
URL_ADDR string
HTTP_RESP *http.Response
HTTP_Request *http.Request
HTTP_BODY []byte
HTTP_CLIENT *http.Client
HTPP_JSON JSON
)
if len(os.Args) < 2 { if len(os.Args) < 2 {
log.Fatalf("用法: %s <IP>", os.Args[0]) log.Fatalf("用法: %s <IP>", os.Args[0])
} }
ip := os.Args[1] IP_ADDR = os.Args[1]
if !isValidIP(ip) { if !isValidIP(IP_ADDR) {
log.Fatalf("无效的 IP 地址: %s", ip) log.Fatalf("无效的 IP 地址: %s", IP_ADDR)
} }
// 目标 URL // 目标 URL
url := "https://qifu.baidu.com/ip/geo/v1/district?ip=" + ip URL_ADDR = "https://qifu.baidu.com/ip/geo/v1/district?ip=" + IP_ADDR
// 创建 HTTP 请求
HTTP_Request, err = http.NewRequest("GET", URL_ADDR, nil)
if err != nil {
log.Fatalf("创建请求时出错: %v", err)
}
// 设置请求头
HTTP_Request.Header.Set("User-Agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Mobile Safari/537.36")
HTTP_Request.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
HTTP_Request.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")
HTTP_Request.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
HTTP_Request.Header.Set("Cache-Control", "max-age=0")
HTTP_Request.Header.Set("Connection", "keep-alive")
HTTP_Request.Header.Set("Cookie", "BIDUPSID=04922F7E0DDC6A5B7E0BA15C33FD2176; PSTM=1722408897; BAIDUID=8313999060289847CAE0A6F34A9C4206:FG=1; Hm_lvt_edc762f9f8f5f525fad4770a32b5edda=1724987641; Hm_lvt_28a17f66627d87f1d046eae152a1c93d=1724987645; AGL_USER_ID=186badbd-dd36-4d39-89f4-8d2aa7a01414; BDUSS=1pvWmdhYThIelRSS1NuQkJESHNYV0REcG9teXMxOW9VaURTU2tyRlZTZ3Z4dmhtRVFBQUFBJCQAAAAAAAAAAAEAAADGRkRexaPT8cHrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC850WYvOdFmM")
HTTP_Request.Header.Set("Host", "qifu.baidu.com")
HTTP_Request.Header.Set("Sec-Ch-Ua", `"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"`)
HTTP_Request.Header.Set("Sec-Ch-Ua-Mobile", "?1")
HTTP_Request.Header.Set("Sec-Ch-Ua-Platform", `"Android"`)
HTTP_Request.Header.Set("Sec-Fetch-Dest", "document")
HTTP_Request.Header.Set("Sec-Fetch-Mode", "navigate")
HTTP_Request.Header.Set("Sec-Fetch-Site", "none")
HTTP_Request.Header.Set("Sec-Fetch-User", "?1")
HTTP_Request.Header.Set("Upgrade-Insecure-Requests", "1")
// 创建 HTTP 客户端并设置超时时间 // 创建 HTTP 客户端并设置超时时间
client := &http.Client{Timeout: 10 * time.Second} HTTP_CLIENT = &http.Client{Timeout: 10 * time.Second}
// 发送 GET 请求 // 发送请求
resp, err := client.Get(url) HTTP_RESP, err = HTTP_CLIENT.Do(HTTP_Request)
if err != nil { if err != nil {
log.Fatalf("发送 GET 请求时出错: %v", err) log.Fatalf("发送请求时出错: %v", err)
} }
defer resp.Body.Close() defer HTTP_RESP.Body.Close()
// 检查 HTTP 响应状态码 // 检查 HTTP 响应状态码
if resp.StatusCode != http.StatusOK { if HTTP_RESP.StatusCode != http.StatusOK {
log.Fatalf("HTTP 请求失败,状态码: %d", resp.StatusCode) log.Fatalf("HTTP 请求失败,状态码: %d", HTTP_RESP.StatusCode)
} }
// 读取响应体 // 读取响应体
body, err := io.ReadAll(resp.Body) HTTP_BODY, err = io.ReadAll(HTTP_RESP.Body)
if err != nil { if err != nil {
log.Fatalf("读取响应体时出错: %v", err) log.Fatalf("读取响应体时出错: %v", err)
} }
// 解析 JSON 数据 // 保存响应体到文件(可选)
var ipInfo IPInfo if err := SaveBytesToFile(append(HTTP_BODY, '\n'), "response.json", true); err != nil {
if err := json.Unmarshal(body, &ipInfo); err != nil { log.Printf("failed to save HTTP response to file: %v", err)
log.Fatalf("解析 JSON 时出错: %v", err)
} }
if ipInfo.Msg == "查询成功" { // 解析 JSON 数据
// 提取并打印 continent 和 country 字段 err = json.Unmarshal(HTTP_BODY, &HTPP_JSON)
fmt.Printf("%s%s\n", ipInfo.Data.Continent, ipInfo.Data.Country) if err != nil {
fmt.Println("Error parsing JSON:", err)
return
}
if HTPP_JSON.Code == "Success" {
fmt.Printf("%s%s\n", HTPP_JSON.Data.Continent, HTPP_JSON.Data.Country)
} else { } else {
fmt.Printf("查询失败\n") fmt.Printf("Error!\n")
} }
} }

View File

@@ -0,0 +1,9 @@
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.1"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.2"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.3"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.4"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.5"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.6"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.7"}
{"code":"Success","data":{"continent":"北美洲","country":"美国","zipcode":"","owner":"","isp":"Cloudflare, Inc.","adcode":"","prov":"","city":"","district":""},"ip":"1.1.1.8"}
{"code":"Success","data":{"continent":"亚洲","country":"中国","zipcode":"999077","owner":"Censys, Inc.","isp":"Censys, Inc.","adcode":"810000","prov":"中国香港","city":"中国香港","district":""},"ip":"199.45.154.152"}

View File

@@ -38,10 +38,16 @@ ifeq ($(OS), centos)
LIBS = LIBS =
else else
LIBPCAP := $(shell pkg-config --libs --static libpcap) LIBPCAP := $(shell pkg-config --libs --static libpcap)
endif endif
LIBCAP := $(shell pkg-config --libs --static libcap) LIBCAP := $(shell pkg-config --libs --static libcap)
LIBIPSET := $(shell pkg-config --libs --static libipset) LIBIPSET := $(shell pkg-config --libs --static libipset)
CFLAGS_LIBCURL += -DCURL_STATICLIB -I./libcurl/include
LIBCURL := -L./libcurl/lib -lcurl -lssh2 -lssh2 -lgpg-error -lssl -ldl -lcrypto -ldl -lz -lssl -lcrypto -lssl -ldl -pthread -lcrypto -ldl -pthread -lzstd -lz
CFLAGS_LIBCJSON += -I./libcjson/include/
LIBCJSON := ./libcjson/lib/libcjson.a
all: $(BIN) # 默认目标 all: $(BIN) # 默认目标
# 系统信息打印目标 # 系统信息打印目标
@@ -57,15 +63,22 @@ info:
@echo "LIBCAP: $(LIBCAP)" @echo "LIBCAP: $(LIBCAP)"
@echo "LIBIPSET: $(LIBIPSET)" @echo "LIBIPSET: $(LIBIPSET)"
ipquery: # Go 构建目标 # Go 构建目标
cd IP_region_query && CGO_ENABLED=0 go build -ldflags '-w -s' 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 # 动态链接目标
$(CC) $(CFLAGS) -o $(BIN) $^ $(LIBPCAP) $(LIBCAP) $(LIBIPSET) $(LIBS) $(BIN): cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o cache.o leak_detector_c/leak_detector_c.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 cache.o
$(CC) $(CFLAGS) $(CFLAGS_LIBCURL) $(CFLAGS_LIBCJSON) -o $(BIN) $^ $(LIBPCAP) $(LIBCAP) $(LIBIPSET) $(LIBCJSON) $(LIBCURL) $(LIBS) -static
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
# 清理目标
clean: clean:
rm -rf $(BIN) ipquery rm -rf $(BIN) IP_region_query/ipquery
rm -rf cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o rm -rf cap.o common.o ip2region/ip2region.o ip2region/xdb_searcher.o libipset.o libcurl.o cache.o leak_detector_c/leak_detector_c.o

View File

@@ -20,12 +20,14 @@
```bash ```bash
sudo apt update sudo apt update
sudo apt install build-essential golang libpcap-dev libcap-dev libipset-dev libsystemd-dev sudo apt install build-essential golang
sudo apt install libpcap-dev libcap-dev libipset-dev libsystemd-dev
``` ```
在 Centos 7 系统上安装所需的开发工具和库: 在 Centos 7 系统上安装所需的开发工具和库:
```bash ```bash
yum groupinstall "Development Tools" -y
yum install ipset-devel libattr-devel libpcap-devel libcap-devel yum install ipset-devel libattr-devel libpcap-devel libcap-devel
``` ```
@@ -43,7 +45,9 @@ cd DenyIP
编译项目: 编译项目:
```bash ```bash
cd DenyIP
make clean make clean
make ipquery
make make
``` ```
@@ -52,13 +56,21 @@ make
### 命令行选项 ### 命令行选项
```bash ```bash
Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?] root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP# ./denyip -h
-d Daemon mode DenyIP version 0.2
-i interface (default eth0) 拒绝Linux服务器非大陆IP工具
-s regular signal (default start|stop) MAIL: aixiao@aixiao.me
start Enable Iptables rule Date: 20241024
stop Disable Iptables rule Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]
-h|-? Help Information -d --daemon Daemon mode
-i --interface interface (default eth0)
-l print iptables rule
-s --signal regular signal (default start|stop)
start Enable Iptables rule
stop Disable Iptables rule
-h|-? Help Information
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP#
``` ```
### 示例命令 ### 示例命令
@@ -93,7 +105,6 @@ Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]
killall -15 denyip killall -15 denyip
``` ```
## 贡献 ## 贡献
欢迎贡献代码和提出改进建议!请通过 Pull Request 或 Issue 的方式提交。 欢迎贡献代码和提出改进建议!请通过 Pull Request 或 Issue 的方式提交。
@@ -109,4 +120,4 @@ Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]
--- ---
希望这个 `README.md` 文件能够帮助您更好地介绍和使用 `DenyIP` 项目。如果有任何其他需求或修改,请随时告知。 希望这个 `README.md` 文件能够帮助您更好地介绍和使用 `DenyIP` 项目。如果有任何其他需求或修改,请随时告知。

258
cache.c Normal file
View File

@@ -0,0 +1,258 @@
#include "cache.h"
struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点
int cache_size = 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++;
}
// 检查 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;
if (ip_cache_head == NULL)
return 0; // 如果 ip_cache_head == NULLcurrent->next 可能导致段错误 (Segmentation Fault)。
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()
{
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;
}
// 添加一个 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;
}
int truncate_file(const char *path)
{
// 以只写模式打开文件并截断到0字节
int 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);
}
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;
}

63
cache.h Normal file
View File

@@ -0,0 +1,63 @@
#ifndef CACHE_H
#define CACHE_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.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/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#define MAXIPSET_ 65535
#define MAXIPLEN 32
#define CACHE_TTL 180 // 设定缓存的存活时间为 600 秒 (10 分钟)
#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址
extern int cache_size; // 当前缓存中的 IP 数量
// 定义链表结构,用于缓存 IP 地址
struct ip_cache_node {
char ip[INET_ADDRSTRLEN]; // 存储 IP 地址
time_t timestamp; // 记录缓存时间
struct ip_cache_node *next; // 指向下一个节点
};
extern void add_ip_to_cache(const char *ip);
extern int is_ip_in_cache(const char *ip);
extern void free_ip_cache();
extern char (*cn_ip)[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);
extern int truncate_file(const char *path);
#endif

453
cap.c
View File

@@ -1,135 +1,47 @@
#include "cap.h" #include "cap.h"
#include "common.h" #include "common.h"
#include "libipset.h" #include "libipset.h"
#include "libcurl.h"
#include "cache.h"
#include "leak_detector_c/leak_detector_c.h"
pcap_if_t *alldevs, *device;
pcap_if_t *alldevs, *device; pcap_t *handle; // 会话句柄
pcap_t *handle; // 会话句柄 struct bpf_program fp; // 编译后的过滤器
struct bpf_program fp; // 编译后的过滤器
pid_t pid = -1; // 子进程全局PID pid_t pids[MAX_CHILDREN] = {-1}; // 子进程全局PID
#define SHM_SIZE 1024 // 共享内存大小 char *ip2region_area = NULL; // ip2region 解析结果
#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; // 执行命令的结果
#define CACHE_TTL 600 // 设定缓存的存活时间为 600 秒 (10 分钟) // 共享内存
#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址 #define SHM_SIZE (MAXIPSET_ * MAXIPLEN)
struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点 int shmid[3] = {-1};
int cache_size = 0; // 当前缓存中的 IP 数量
// 定义链表结构,用于缓存 IP 地址 char (*cn_ip)[MAXIPLEN] = NULL; // 用于存储国内 IP 地址
struct ip_cache_node { char (*whitelist_ip)[MAXIPLEN] = NULL; // 用于存储白名单 IP 地址
char ip[INET_ADDRSTRLEN]; // 存储 IP 地址 char *RULE_NAME = NULL; // 共享内存存储 ipset 规则名称
time_t timestamp; // 记录缓存时间 int RULE_NAME_NUMBER = 0; // ipset 集合集合数
struct ip_cache_node *next; // 指向下一个节点
};
// 检查 IP 是否已在缓存中并是否过期 void Processing_IP_addresses(char *src_ip)
int is_ip_in_cache(const char *ip)
{ {
time_t now = time(NULL); // 获取当前时间 // 地域白名单
struct ip_cache_node *current = ip_cache_head; char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
struct ip_cache_node *prev = NULL; char _REGION_LIST[BUFFER] = { 0 };
const char *REGION_ENV = NULL;
char ipset_query_command[256] = { 0 };
// 定义 Response 结构体
Response response;
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); if (1 == is_ip_in_set(whitelist_ip, src_ip)) {
cache_size--; _printf(RED "IP:%s 白名单IP, 跳过!\n" REDEND, src_ip);
return 0; // IP 过期,不再缓存 //printf("%s %d\n", whitelist_ip[0], cn_ip_len(whitelist_ip));
}
}
prev = current; //del_ip_to_ipset("root0", src_ip); // 删除 ipset 规则
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; 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 地址已在缓存中且未过期,则跳过查询 // 如果 IP 地址已在缓存中且未过期,则跳过查询
@@ -138,6 +50,18 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
return; return;
} }
// 如果ipset规则已经存在则跳过查询
snprintf(ipset_query_command, sizeof(ipset_query_command), "ipset test %s %s 2>/dev/null", RULE_NAME, src_ip);
if (system(ipset_query_command) == 0) {
_printf(RED "Ipset 规则内已经存在 %s\n" REDEND, src_ip);
return;
}
if (1 == is_ip_in_set(cn_ip, src_ip)) {
_printf(RED "IP:%s 已经标记为国内,跳过!\n" REDEND, src_ip);
return;
}
// 执行查询并添加到缓存 // 执行查询并添加到缓存
ip2region_area = ip2region("ip2region/ip2region.xdb", src_ip); ip2region_area = ip2region("ip2region/ip2region.xdb", src_ip);
@@ -145,6 +69,7 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
_printf(RED "ip2region 解析地域错误\n" REDEND); _printf(RED "ip2region 解析地域错误\n" REDEND);
return; return;
} }
// 取环境变量 // 取环境变量
REGION_ENV = getenv("REGION"); REGION_ENV = getenv("REGION");
if (REGION_ENV != NULL) { if (REGION_ENV != NULL) {
@@ -158,42 +83,80 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
if (isregion(ip2region_area, _region_list) == 1) { // 返回1表示在白名单列表 if (isregion(ip2region_area, _region_list) == 1) { // 返回1表示在白名单列表
; ;
} else { } 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数不够预备设定值 if (cache_size < MAX_CACHE_SIZE) // 缓存IP数不够预备设定值
{ {
sleep(1); sleep(1);
_printf("缓存 IP 数 %d\n", cache_size); _printf("缓存 IP 数 %d\n", cache_size);
} }
command_result = _execute_command(ip_query_command); */
if (command_result != NULL) { add_ip_to_cache(src_ip); // 添加到缓存
add_ip_to_cache(src_ip); // 添加 IP 到缓存
char *p = strstr(command_result, "中国"); char *p = CurlGetIpArea(src_ip);
if (p == NULL) { if (parse_json_to_struct(p, &response) == 0) { // 解析 JSON 到结构体
_printf(RED "%s %s\n" REDEND, src_ip, command_result);
r = add_ip_to_ipset(RULE_NAME, src_ip); if (NULL == strstr(response.continent_country, "中国")) { // 这时是国外IP
_printf("add_ip_to_ipset() return %d\n", r); _printf(RED "CurlGetIpArea(): %s %s\r\n" REDEND, src_ip, response.continent_country);
add_ip_to_ipset(RULE_NAME, src_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) {
_printf("append_string_to_file() Error!!!\n");
}
} }
free(command_result);
command_result = NULL;
} else { } else {
; fprintf(stderr, "Failed to parse JSON.\n");
}
if (p != NULL) {
free(p);
} }
if (command_result != NULL)
free(command_result);
} }
if (ip2region_area != NULL) if (ip2region_area != NULL) {
{
free(ip2region_area); free(ip2region_area);
ip2region_area = NULL; ip2region_area = NULL;
} }
return ;
// 实时检测内存泄漏
dump_mem_leak();
return;
}
// 回调函数,在捕获到每个数据包时调用
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
// 定义以太网帧头部的长度 (目标 MAC 6字节 + 源 MAC 6字节 + 类型 2字节 = 14字节)
int ethernet_header_len = 14;
// 假设数据包是 Ethernet II 帧封装的 IP 包
// 计算 IP 头部的起始位置:跳过以太网头部
// 将该位置的指针强制转换为 struct ip 指针
struct ip *ip_header = (struct ip *)(packet + ethernet_header_len);
// 检查 IP 协议版本号
// ip_v 是 struct ip 结构中的版本号字段 (通常占 4 bits)
if (ip_header->ip_v != 4)
return; // 只处理 IPv4
// 定义一个字符数组用于存储点分十进制格式的源 IP 地址字符串
// INET_ADDRSTRLEN 是 <arpa/inet.h> 中定义的足够存储 IPv4 地址字符串的最大长度 (包括结尾的 '\0')
char src_ip[INET_ADDRSTRLEN] = { 0 };
// 将网络字节序 (二进制) 的 IPv4 源地址转换为点分十进制表示的字符串
// AF_INET: 指定地址族为 IPv4
// &(ip_header->ip_src): 指向 struct ip 结构中源地址字段 (struct in_addr 类型) 的指针
// src_ip: 存储转换后字符串的缓冲区
// INET_ADDRSTRLEN: 缓冲区的长度
inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN);
Processing_IP_addresses(src_ip);
return;
} }
void usage() void usage()
@@ -205,6 +168,7 @@ void usage()
puts(" Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]"); puts(" Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]");
puts(" -d --daemon Daemon mode"); puts(" -d --daemon Daemon mode");
puts(" -i --interface interface (default eth0)"); puts(" -i --interface interface (default eth0)");
puts(" -f --protocol 过滤器 [\"tcp\" | \"udp\" | \"tcp or udp\"] (default \"tcp\")");
puts(" -l print iptables rule"); puts(" -l print iptables rule");
puts(" -s --signal regular signal (default start|stop) "); puts(" -s --signal regular signal (default start|stop) ");
puts(" start Enable Iptables rule"); puts(" start Enable Iptables rule");
@@ -215,21 +179,36 @@ void usage()
exit(0); exit(0);
} }
void detach_and_delete_shm(void *addr, int shmid, int delete_flag) {
if (addr && addr != (void *)-1) {
shmdt(addr);
}
if (delete_flag && shmid >= 0) {
shmctl(shmid, IPC_RMID, NULL);
}
}
void cleanup_(int signum) void cleanup_(int signum)
{ {
_printf("Received signal %d, cleaning up...\n", signum); _printf("Received signal %d, cleaning up...\n", signum);
// 终止子进程 // 终止子进程
if (pid > 0) { for (int i = 0; i < MAX_CHILDREN; i++) {
kill(pid, SIGTERM); if (pids[i] > 0) {
printf("Terminating child process %d...\n", pids[i]);
kill(pids[i], SIGTERM); // 优雅终止
sleep(1); // 等待其响应
kill(pids[i], SIGKILL); // 若仍未结束,强制终止
waitpid(pids[i], NULL, 0); // 回收资源
}
} }
// 释放共享内存 // 释放共享内存
if (RULE_NAME != NULL) { detach_and_delete_shm(RULE_NAME, shmid[0], 1);
shmdt(RULE_NAME); detach_and_delete_shm(whitelist_ip, shmid[1], 1);
shmctl(shmid, IPC_RMID, NULL); detach_and_delete_shm(cn_ip, shmid[2], 1);
}
// 在程序结束时,清理缓存链表 // 在程序结束时,清理缓存链表
free_ip_cache(); free_ip_cache();
@@ -238,34 +217,57 @@ void cleanup_(int signum)
free(ip2region_area); free(ip2region_area);
ip2region_area = NULL; ip2region_area = NULL;
} }
if (command_result != NULL) {
free(command_result);
command_result = NULL;
}
// 清理 // 清理
pcap_freecode(&fp); pcap_freecode(&fp);
pcap_freealldevs(alldevs); // 释放设备列表 pcap_freealldevs(alldevs); // 释放设备列表
//pcap_close(handle); // 关闭会话句柄 if (handle)
pcap_close(handle);
// 退出主进程
// 退出主进程
exit(0); exit(0);
return; return;
} }
void *create_and_attach_shm(const char *path, int proj_id, size_t size, int *shmid_out) {
key_t key = ftok(path, proj_id);
if (key == -1) {
perror("ftok");
exit(1);
}
int shmid = shmget(key, size, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget");
exit(1);
}
void *addr = shmat(shmid, NULL, 0);
if (addr == (void *)-1) {
perror("shmat");
exit(1);
}
if (shmid_out) *shmid_out = shmid;
return addr;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
atexit(report_mem_leak);
// 注册 SIGTERM 信号处理函数 // 注册 SIGTERM 信号处理函数
signal(SIGINT, cleanup_);
signal(SIGTERM, cleanup_); signal(SIGTERM, cleanup_);
int opt; int opt;
char errbuf[PCAP_ERRBUF_SIZE]; // 错误缓冲区 char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; // 错误缓冲区
char protocol[] = "tcp"; char protocol[256] = "tcp";
char interface[256] = "{ 0 }"; char interface[256] = "{ 0 }";
char Ipset_Command[BUFFER]; char Ipset_Command[BUFFER] = { 0 };
strcpy(interface, "eth0"); strcpy(interface, "eth0");
memset(&alldevs, 0, sizeof(alldevs)); memset(&alldevs, 0, sizeof(alldevs));
@@ -273,9 +275,10 @@ int main(int argc, char **argv)
memset(errbuf, 0, PCAP_ERRBUF_SIZE); memset(errbuf, 0, PCAP_ERRBUF_SIZE);
int longindex = 0; int longindex = 0;
char optstring[] = "di:s:lh?"; char optstring[] = "di:f:s:lh?";
static struct option longopts[] = { static struct option longopts[] = {
{ "interface", required_argument, 0, 'i' }, { "interface", required_argument, 0, 'i' },
{ "protocol", required_argument, 0, 'f' },
{ "signal", required_argument, 0, 's' }, { "signal", required_argument, 0, 's' },
{ "daemon", no_argument, 0, 'd' }, { "daemon", no_argument, 0, 'd' },
{ "l", no_argument, 0, 'l' }, { "l", no_argument, 0, 'l' },
@@ -284,8 +287,7 @@ int main(int argc, char **argv)
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
while (-1 != (opt = getopt_long(argc, argv, optstring, longopts, &longindex))) while (-1 != (opt = getopt_long(argc, argv, optstring, longopts, &longindex))) {
{
switch (opt) { switch (opt) {
case 'd': case 'd':
if (daemon(1, 1)) { if (daemon(1, 1)) {
@@ -295,6 +297,9 @@ int main(int argc, char **argv)
case 'i': case 'i':
strcpy(interface, optarg); strcpy(interface, optarg);
break; break;
case 'f':
strcpy(protocol, optarg);
break;
case 'l': case 'l':
system("iptables -L -v -n --line-numbers"); system("iptables -L -v -n --line-numbers");
exit(0); exit(0);
@@ -303,17 +308,13 @@ int main(int argc, char **argv)
if (strcmp(optarg, "start") == 0) { if (strcmp(optarg, "start") == 0) {
memset(Ipset_Command, 0, BUFFER); memset(Ipset_Command, 0, BUFFER);
// 将 MAXIPSET_RULT_NAME_NUM 替换为实际值 // 将 MAXIPSET_RULT_NAME_NUM 替换为实际值
snprintf(Ipset_Command, sizeof(Ipset_Command), 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);
"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(Ipset_Command);
exit(0); exit(0);
} else if (strcmp(optarg, "stop") == 0) { } else if (strcmp(optarg, "stop") == 0) {
memset(Ipset_Command, 0, BUFFER); memset(Ipset_Command, 0, BUFFER);
// 将 MAXIPSET_RULT_NAME_NUM 替换为实际值 // 将 MAXIPSET_RULT_NAME_NUM 替换为实际值
snprintf(Ipset_Command, sizeof(Ipset_Command), 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);
"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(Ipset_Command);
exit(0); exit(0);
} else { } else {
@@ -334,27 +335,100 @@ int main(int argc, char **argv)
} }
} }
// 创建共享内存 // 创建共享内存
shmid = shmget(SHM_KEY, SHM_SIZE, IPC_CREAT | 0666); RULE_NAME = (char *)create_and_attach_shm("/tmp", 'A', 1024, &shmid[0]);
if (shmid < 0) { whitelist_ip = (char (*)[MAXIPLEN])create_and_attach_shm("/tmp", 'B', SHM_SIZE, &shmid[1]);
perror("shmget"); cn_ip = (char (*)[MAXIPLEN])create_and_attach_shm("/tmp", 'C', SHM_SIZE, &shmid[2]);
exit(1);
// 读取白名单
if (1 == file_exists_access("whitelist.txt")) {
int line_count = 0;
int result = read_file_to_array("whitelist.txt", whitelist_ip, &line_count);
if (result != 0) {
fprintf(stderr, "Failed to read file with error code: %d\n", result);
return 1;
}
for (int i = 0; i < line_count; i++) {
printf("Line %d: %s\n", i + 1, whitelist_ip[i]);
}
} }
// 连接共享内存到进程地址空间 // 读取缓存
RULE_NAME = (char *)shmat(shmid, NULL, 0); if (1 == file_exists_access("cn.txt")) {
if (RULE_NAME == (char *)-1) { int line_count = 0;
perror("shmat"); int result = read_file_to_array("cn.txt", cn_ip, &line_count);
exit(1); if (result != 0) {
fprintf(stderr, "Failed to read file with error code: %d\n", result);
return 1;
}
char *local_addr = GetLocalAddr("https://inet-ip.aixiao.me/");
if (local_addr == NULL) {
perror("GetLocalAddr()");
return 1;
}
remove_char(local_addr, '\n');
printf("Local Address: %s\n", local_addr);
strcpy(cn_ip[line_count], local_addr);
line_count++;
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]);
}
free(local_addr);
} }
pid = fork(); // 创建子进程 pids[0] = fork();
if (pid == 0) // 子进程 if ( 0 == pids[0] ) // 子进程
{ {
while(1)
int count = 0; {
// 重新加载白名单Ip
if (1 == file_exists_access("whitelist.txt")) {
clear_ip_set(whitelist_ip); // 清空白名单IP集合
int line_count = 0;
int result = read_file_to_array("whitelist.txt", whitelist_ip, &line_count);
if (result != 0) {
fprintf(stderr, "Failed to read file with error code: %d\n", result);
return 1;
}
printf("White list IPs: \n ");
for (int i = 0; i < line_count; i++) {
printf("%s ", whitelist_ip[i]);
}
printf("\n");
}
// 打印国内IP集合
for (int i = 0; i < MAXIPSET_; i++) {
if (cn_ip[i][0] != '\0') {
printf("%s ", cn_ip[i]);
}
}
printf("cn_ip_len(cn_ip): %d\n", cn_ip_len(cn_ip));
// 如果国内IP数量超过100清理集合
if (cn_ip_len(cn_ip) >= 100) { // 清理集合
clear_ip_set(cn_ip);
truncate_file("cn.txt"); // 清空文件
}
sleep(30); // 每 60 秒检查一次
}
}
pids[1] = fork();
if ( 0 == pids[1] ) // 子进程
{
int count = 0;
snprintf(RULE_NAME, BUFFER, "root%d", RULE_NAME_NUMBER); snprintf(RULE_NAME, BUFFER, "root%d", RULE_NAME_NUMBER);
if (create_ipset(RULE_NAME) != 0) { if (create_ipset(RULE_NAME) != 0) {
@@ -363,11 +437,9 @@ int main(int argc, char **argv)
while (1) while (1)
{ {
_printf("子进程当前 Ipset Rule 名 %s\n", RULE_NAME);
count = get_ip_count_in_ipset(RULE_NAME); count = get_ip_count_in_ipset(RULE_NAME);
if (count >= 0) { if (count >= 0) {
_printf("IPSet %s 中的 IP 数量: %d\n", RULE_NAME, count); _printf("子进程当前 Ipset Rule 名 %s, 数量: %d \n", RULE_NAME, count);
if (count >= MAXIPSET && RULE_NAME_NUMBER <= MAXIPSET_RULT_NAME_NUM) // RULE_中的IP数量不超过MAXIPSET并且集合不能超过 MAXIPSET_RULT_NAME_NUM 个 if (count >= MAXIPSET && RULE_NAME_NUMBER <= MAXIPSET_RULT_NAME_NUM) // RULE_中的IP数量不超过MAXIPSET并且集合不能超过 MAXIPSET_RULT_NAME_NUM 个
{ {
RULE_NAME_NUMBER++; RULE_NAME_NUMBER++;
@@ -377,11 +449,13 @@ int main(int argc, char **argv)
if (create_ipset(RULE_NAME) != 0) { if (create_ipset(RULE_NAME) != 0) {
_printf("创建 IPSet %s 失败\n", RULE_NAME); _printf("创建 IPSet %s 失败\n", RULE_NAME);
} else { } else {
char iptables_command[256]; /*
sprintf(iptables_command, "iptables -I INPUT -m set --match-set %s src -j DROP", RULE_NAME); char iptables_command[256];
system(iptables_command); sprintf(iptables_command, "iptables -I INPUT -m set --match-set %s src -j DROP", RULE_NAME);
system(iptables_command);
*/
add_iptables_rule(RULE_NAME);
} }
} }
if (RULE_NAME_NUMBER == MAXIPSET_RULT_NAME_NUM) { if (RULE_NAME_NUMBER == MAXIPSET_RULT_NAME_NUM) {
@@ -390,10 +464,9 @@ int main(int argc, char **argv)
} }
} }
sleep(3); // 每 3 秒检查一次 sleep(7); // 每 3 秒检查一次
} }
} }
// 查找可用的网络设备 // 查找可用的网络设备
if (pcap_findalldevs(&alldevs, errbuf) == -1) { if (pcap_findalldevs(&alldevs, errbuf) == -1) {

4
cap.h
View File

@@ -24,7 +24,9 @@
#define REDEND "\033[0m" #define REDEND "\033[0m"
#define MAXIPSET 65535 #define MAXIPSET 65535
#define MAXIPSET_RULT_NAME_NUM 26 #define MAXIPSET_RULT_NAME_NUM 32
#define MAX_CHILDREN 2
#define _VERSION "0.2" #define _VERSION "0.2"

View File

@@ -1,7 +1,8 @@
#include "common.h" #include "common.h"
// 计算字符串长度 // 计算字符串长度
int _strlen(const char *str) { int _strlen(const char *str)
{
if (str == NULL) if (str == NULL)
return 0; return 0;
@@ -9,7 +10,6 @@ int _strlen(const char *str) {
return _p - str; return _p - str;
} }
// 自定义 printf 函数 // 自定义 printf 函数
void _printf(const char *format, ...) void _printf(const char *format, ...)
{ {
@@ -20,13 +20,13 @@ void _printf(const char *format, ...)
time_t now = time(NULL); time_t now = time(NULL);
struct tm local_time; struct tm local_time;
localtime_r(&now, &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); strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &local_time);
// 打印时间戳到控制台 // 打印时间戳到控制台
printf("[%s] ", time_str); printf("[%s] ", time_str);
vprintf(format, args); // 打印内容到控制台 vprintf(format, args); // 打印内容到控制台
va_end(args); // 结束对变参列表的处理 va_end(args); // 结束对变参列表的处理
// 重新启动变参列表 // 重新启动变参列表
va_start(args, format); va_start(args, format);
@@ -46,24 +46,23 @@ void _printf(const char *format, ...)
perror("Unable to open log file"); 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]) void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM])
{ {
int i = 0; int i = 0;
char *result = NULL; char *result = NULL;
char temp[WHITELIST_IP_NUM]; // 创建一个足够大的副本缓冲区 char temp[WHITELIST_IP_NUM]; // 创建一个足够大的副本缓冲区
// 复制原始字符串到副本 // 复制原始字符串到副本
strncpy(temp, string, sizeof(temp) - 1); strncpy(temp, string, sizeof(temp) - 1);
temp[sizeof(temp) - 1] = '\0'; // 确保字符串以 '\0' 结尾 temp[sizeof(temp) - 1] = '\0'; // 确保字符串以 '\0' 结尾
result = strtok(temp, delims); // 使用副本进行拆分 result = strtok(temp, delims); // 使用副本进行拆分
while (result != NULL && i < WHITELIST_IP_NUM) while (result != NULL && i < WHITELIST_IP_NUM) {
{
strncpy(whitelist_ip[i], result, WHITELIST_IP_NUM - 1); 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++; i++;
result = strtok(NULL, delims); result = strtok(NULL, delims);
} }
@@ -74,19 +73,18 @@ int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM])
{ {
int i; int i;
for (i = 0; i < WHITELIST_IP_NUM; i++) { // 从 i = 0 开始 for (i = 0; i < WHITELIST_IP_NUM; i++) { // 从 i = 0 开始
// 如果白名单 IP 是空字符串,跳出循环 // 如果白名单 IP 是空字符串,跳出循环
if (whitelist_ip[i][0] == '\0') { if (whitelist_ip[i][0] == '\0') {
break; break;
} }
// 对比 client_ip 的前缀是否与白名单中的IP段匹配 // 对比 client_ip 的前缀是否与白名单中的IP段匹配
if (strncmp(client_ip, whitelist_ip[i], strlen(whitelist_ip[i])) == 0) { 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') { if (region_list[i][0] == '\0') {
break; break;
} }
// 在str中查找 region_list[i] // 在str中查找 region_list[i]
p = strstr(str, region_list[i]); p = strstr(str, region_list[i]);
if (p != NULL) { 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) 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]; static char temp[BUFFER];
const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
time_t t = time(NULL); time_t t = time(NULL);
@@ -134,11 +132,9 @@ char *_time() {
return NULL; return NULL;
} }
snprintf(temp, sizeof(temp), "[%d/%02d/%02d %s %02d:%02d:%02d]", 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);
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地址 // 将字符串转换为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()); int oldprio = getpriority(PRIO_PROCESS, getpid());
if (oldprio == -1 && errno != 0) { if (oldprio == -1 && errno != 0) {
@@ -163,12 +160,10 @@ int _nice(int increment) {
printf("Current priority: %d\n", oldprio); printf("Current priority: %d\n", oldprio);
// 检查是否溢出 // 检查是否溢出
if ((increment > 0 && oldprio > INT_MAX - increment) || if ((increment > 0 && oldprio > INT_MAX - increment) || (increment < 0 && oldprio < INT_MIN - increment)) {
(increment < 0 && oldprio < INT_MIN - increment)) {
fprintf(stderr, "Priority overflow error\n"); fprintf(stderr, "Priority overflow error\n");
return -1; return -1;
} }
// 计算新的优先级 // 计算新的优先级
int newprio = oldprio + increment; 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); fprintf(stderr, "New priority out of range: %d (valid range is %d to %d)\n", newprio, PRIO_MIN, PRIO_MAX);
return -1; return -1;
} }
// 设置新的优先级 // 设置新的优先级
if (setpriority(PRIO_PROCESS, getpid(), newprio) == -1) { if (setpriority(PRIO_PROCESS, getpid(), newprio) == -1) {
perror("setpriority failed"); 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"); const char *path_env = getenv("PATH");
if (!path_env) { if (!path_env) {
return 0; // 如果 PATH 不存在,返回不存在 return 0; // 如果 PATH 不存在,返回不存在
} }
char filepath[1024]; // 缓冲区大小 char filepath[1024]; // 缓冲区大小
const char *dir = path_env; const char *dir = path_env;
while (dir && *dir) { 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)) { if (snprintf(filepath, sizeof(filepath), "%.*s/%s", (int)len, dir, command) >= (int)sizeof(filepath)) {
return 0; // 缓冲区溢出,返回不存在 return 0; // 缓冲区溢出,返回不存在
} }
// 检查文件是否存在且可执行 // 检查文件是否存在且可执行
if (access(filepath, X_OK) == 0) { if (access(filepath, X_OK) == 0) {
puts(filepath); puts(filepath);
return 1; // 命令存在 return 1; // 命令存在
} }
// 更新 dir 指针 // 更新 dir 指针
dir = end ? end + 1 : NULL; dir = end ? end + 1 : NULL;
} }
return 0; // 命令不存在 return 0; // 命令不存在
} }
// 定义一个函数,执行命令并返回输出 // 执行命令并返回输出
char *_execute_command(const char *command) { char *_execute_command(const char *command)
{
FILE *fp; FILE *fp;
char buffer[1024]; char buffer[1024];
char *output = NULL; char *output = NULL;
@@ -235,7 +229,6 @@ char *_execute_command(const char *command) {
perror("popen"); perror("popen");
return NULL; return NULL;
} }
// 读取命令的输出 // 读取命令的输出
while (fgets(buffer, sizeof(buffer), fp) != NULL) { while (fgets(buffer, sizeof(buffer), fp) != NULL) {
size_t len = strlen(buffer); size_t len = strlen(buffer);
@@ -244,7 +237,7 @@ char *_execute_command(const char *command) {
char *new_output = realloc(output, output_size); char *new_output = realloc(output, output_size);
if (new_output == NULL) { if (new_output == NULL) {
perror("realloc"); perror("realloc");
free(output); // 释放已分配的内存 free(output); // 释放已分配的内存
pclose(fp); // 关闭管道 pclose(fp); // 关闭管道
return NULL; return NULL;
} }
@@ -259,14 +252,24 @@ char *_execute_command(const char *command) {
if (output_size > 0) { if (output_size > 0) {
output[total_read] = '\0'; output[total_read] = '\0';
} }
// 关闭管道 // 关闭管道
if (pclose(fp) == -1) { if (pclose(fp) == -1) {
perror("pclose"); perror("pclose");
free(output); // pclose 失败时释放内存 free(output); // pclose 失败时释放内存
return NULL; return NULL;
} }
return output; return output;
} }
void remove_char(char *str, char c)
{
int i = 0, j = 0;
while (str[i]) {
if (str[i] != c) {
str[j++] = str[i];
}
i++;
}
str[j] = '\0';
}

View File

@@ -27,7 +27,6 @@
#define BUFFER 1024 #define BUFFER 1024
#define WHITELIST_IP_NUM 1024 #define WHITELIST_IP_NUM 1024
extern char *_time(); extern char *_time();
extern int _strlen(const char *str); extern int _strlen(const char *str);
extern void _printf(const char *format, ...); extern void _printf(const char *format, ...);
@@ -43,4 +42,6 @@ extern int is_valid_ip(const char *ip);
extern int _command_exists(const char *command); extern int _command_exists(const char *command);
extern char *_execute_command(const char *command); extern char *_execute_command(const char *command);
extern void remove_char(char *str, char c);
#endif #endif

BIN
ip2region/a.out Normal file

Binary file not shown.

17
ip2region/a.out.valgrind Normal file
View File

@@ -0,0 +1,17 @@
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP/ip2region# /usr/bin/valgrind --tool=memcheck --leak-check=full --show-reachable=yes --main-stacksize=8388608 --track-origins=yes ./a.out
==239839== Memcheck, a memory error detector
==239839== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==239839== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==239839== Command: ./a.out
==239839==
澳大利亚|0|0|0|0
==239839==
==239839== HEAP SUMMARY:
==239839== in use at exit: 0 bytes in 0 blocks
==239839== total heap usage: 7 allocs, 7 frees, 534,473 bytes allocated
==239839==
==239839== All heap blocks were freed -- no leaks are possible
==239839==
==239839== For lists of detected and suppressed errors, rerun with: -s
==239839== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
root@NIUYULING:/mnt/c/Users/root/Desktop/git.aixiao.me/DenyIP/ip2region#

View File

@@ -6,7 +6,7 @@
int main() int main()
{ {
// 执行查询并添加到缓存 // 执行查询并添加到缓存
char *area = ip2region("ip2region.xdb", "1.1.1.1"); char *area = ip2region("ip2region.xdb", "199.45.154.152");
if (area == NULL) { if (area == NULL) {
return -1; return -1;
} }

BIN
leak_detector_c/a.out Normal file

Binary file not shown.

View File

@@ -0,0 +1,197 @@
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "leak_detector_c.h"
// 取消宏定义,使用原始 malloc/calloc/free
#undef malloc
#undef calloc
#undef free
// 全局链表起始与当前位置指针
static MEM_LEAK *ptr_start = NULL;
static MEM_LEAK *ptr_next = NULL;
/*
* 将分配的内存信息添加到链表中
*/
void add(MEM_INFO alloc_info)
{
MEM_LEAK *mem_leak_info = NULL;
// 分配一个新的链表节点
mem_leak_info = (MEM_LEAK *) malloc(sizeof(MEM_LEAK));
mem_leak_info->mem_info.address = alloc_info.address;
mem_leak_info->mem_info.size = alloc_info.size;
strcpy(mem_leak_info->mem_info.file_name, alloc_info.file_name);
mem_leak_info->mem_info.line = alloc_info.line;
mem_leak_info->next = NULL;
// 如果是第一个节点
if (ptr_start == NULL) {
ptr_start = mem_leak_info;
ptr_next = ptr_start;
} else {
// 添加到链表末尾
ptr_next->next = mem_leak_info;
ptr_next = ptr_next->next;
}
}
/*
* 根据位置索引从链表中删除内存记录
*/
void erase(unsigned pos)
{
unsigned index = 0;
MEM_LEAK *alloc_info, *temp;
// 删除第一个节点
if (pos == 0) {
MEM_LEAK *temp = ptr_start;
ptr_start = ptr_start->next;
free(temp);
} else {
// 删除中间或最后一个节点
for (index = 0, alloc_info = ptr_start; index < pos; alloc_info = alloc_info->next, ++index) {
if (pos == index + 1) {
temp = alloc_info->next;
alloc_info->next = temp->next;
free(temp);
break;
}
}
}
}
/*
* 清空链表中所有内存记录
*/
void clear()
{
MEM_LEAK *temp = ptr_start;
MEM_LEAK *alloc_info = ptr_start;
while (alloc_info != NULL) {
alloc_info = alloc_info->next;
free(temp);
temp = alloc_info;
}
}
/*
* 自定义 malloc 函数:分配内存并记录来源信息
*/
void *xmalloc(unsigned int size, const char *file, unsigned int line)
{
void *ptr = malloc(size);
if (ptr != NULL) {
add_mem_info(ptr, size, file, line);
}
return ptr;
}
/*
* 自定义 calloc 函数:分配并初始化内存,同时记录信息
*/
void *xcalloc(unsigned int elements, unsigned int size, const char *file, unsigned int line)
{
unsigned total_size;
void *ptr = calloc(elements, size);
if (ptr != NULL) {
total_size = elements * size;
add_mem_info(ptr, total_size, file, line);
}
return ptr;
}
/*
* 自定义 free 函数:释放内存前先移除记录
*/
void xfree(void *mem_ref)
{
remove_mem_info(mem_ref); // 移除记录
free(mem_ref); // 实际释放
}
/*
* 创建内存分配信息并添加到链表中
*/
void add_mem_info(void *mem_ref, unsigned int size, const char *file, unsigned int line)
{
MEM_INFO mem_alloc_info;
// 清空结构体,确保初始化干净
memset(&mem_alloc_info, 0, sizeof(mem_alloc_info));
mem_alloc_info.address = mem_ref;
mem_alloc_info.size = size;
strncpy(mem_alloc_info.file_name, file, FILE_NAME_LENGTH);
mem_alloc_info.line = line;
// 添加到链表中
add(mem_alloc_info);
}
/*
* 从链表中移除某段已释放的内存记录
*/
void remove_mem_info(void *mem_ref)
{
unsigned short index;
MEM_LEAK *leak_info = ptr_start;
// 遍历链表查找目标地址
for (index = 0; leak_info != NULL; ++index, leak_info = leak_info->next) {
if (leak_info->mem_info.address == mem_ref) {
erase(index); // 找到后删除
break;
}
}
}
/*
* 将所有未释放的内存信息写入输出文件
*/
void report_mem_leak(void)
{
MEM_LEAK *leak_info;
FILE *fp_write = fopen(OUTPUT_FILE, "wt");
if (fp_write != NULL) {
fprintf(fp_write, "Memory Leak Summary\n");
fprintf(fp_write, "-----------------------------------\n");
// 遍历所有未释放的记录,写入文件
for (leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) {
fprintf(fp_write, "address : %p\n", leak_info->mem_info.address);
fprintf(fp_write, "size : %d bytes\n", leak_info->mem_info.size);
fprintf(fp_write, "file : %s\n", leak_info->mem_info.file_name);
fprintf(fp_write, "line : %d\n", leak_info->mem_info.line);
fprintf(fp_write, "-----------------------------------\n");
}
fclose(fp_write); // 关闭输出文件
}
clear(); // 清空链表,释放资源
}
void dump_mem_leak(void)
{
MEM_LEAK *leak_info;
leak_info = ptr_start;
if (leak_info != NULL) {
fprintf(stderr, "Memory Leak Snapshot\n");
fprintf(stderr, "-----------------------------------\n");
for (; leak_info != NULL; leak_info = leak_info->next) {
fprintf(stderr, "address : %p\n", leak_info->mem_info.address);
fprintf(stderr, "size : %d bytes\n", leak_info->mem_info.size);
fprintf(stderr, "file : %s\n", leak_info->mem_info.file_name);
fprintf(stderr, "line : %d\n", leak_info->mem_info.line);
fprintf(stderr, "-----------------------------------\n");
}
}
}

View File

@@ -0,0 +1,61 @@
#ifndef LEAK_DETECTOR_C_H
#define LEAK_DETECTOR_C_H
// 文件名最大长度
#define FILE_NAME_LENGTH 256
// 内存泄漏信息输出文件
#define OUTPUT_FILE "leak_info.txt"
// 用宏重定义 malloc、calloc 和 free为其添加文件名和行号信息
#define malloc(size) xmalloc (size, __FILE__, __LINE__)
#define calloc(elements, size) xcalloc (elements, size, __FILE__, __LINE__)
#define free(mem_ref) xfree(mem_ref)
// 用于记录每一次内存分配的信息结构体
struct _MEM_INFO {
void *address; // 分配的内存地址
unsigned int size; // 分配的大小
char file_name[FILE_NAME_LENGTH]; // 分配发生的文件名
unsigned int line; // 分配发生的代码行号
};
typedef struct _MEM_INFO MEM_INFO;
// 内存泄漏记录结构体,使用链表形式组织
struct _MEM_LEAK {
MEM_INFO mem_info; // 内存信息
struct _MEM_LEAK *next; // 指向下一个节点的指针
};
typedef struct _MEM_LEAK MEM_LEAK;
// 添加一条内存分配信息记录
void add(MEM_INFO alloc_info);
// 删除某个位置的内存记录
void erase(unsigned pos);
// 清空所有内存记录
void clear(void);
// 自定义 malloc记录内存分配位置
void *xmalloc(unsigned int size, const char *file, unsigned int line);
// 自定义 calloc记录内存分配位置
void *xcalloc(unsigned int elements, unsigned int size, const char *file, unsigned int line);
// 自定义 free在释放内存时移除记录
void xfree(void *mem_ref);
// 添加一条内存分配记录
void add_mem_info(void *mem_ref, unsigned int size, const char *file, unsigned int line);
// 移除某个内存记录(在调用 free 时使用)
void remove_mem_info(void *mem_ref);
// 生成内存泄漏报告
extern void report_mem_leak(void);
extern void dump_mem_leak(void);
#endif

View File

@@ -0,0 +1,12 @@
Memory Leak Summary
-----------------------------------
address : 0x7fffe6d502a0
size : 1 bytes
file : test.c
line : 8
-----------------------------------
address : 0x7fffe6d50520
size : 60 bytes
file : test.c
line : 14
-----------------------------------

20
leak_detector_c/test.c Normal file
View File

@@ -0,0 +1,20 @@
#include <malloc.h>
#include <stdlib.h>
#include "leak_detector_c.h"
int main()
{
atexit(report_mem_leak);
char *ptr1 = (char *)malloc(1);
int *ptr2 = (int *)calloc(1, sizeof(int));
float * ptr3 = (float *) calloc(15, sizeof(float));
free(ptr2);
dump_mem_leak();
return 0;
}

View File

@@ -0,0 +1,306 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,88 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON_Utils__h
#define cJSON_Utils__h
#ifdef __cplusplus
extern "C"
{
#endif
#include "cJSON.h"
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer);
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer);
/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to);
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to);
/* Utility for generating patch array entries. */
CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value);
/* Returns 0 for success. */
CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches);
CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches);
/*
// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches)
//{
// cJSON *modme = cJSON_Duplicate(*object, 1);
// int error = cJSONUtils_ApplyPatches(modme, patches);
// if (!error)
// {
// cJSON_Delete(*object);
// *object = modme;
// }
// else
// {
// cJSON_Delete(modme);
// }
//
// return error;
//}
// Code not added to library since this strategy is a LOT slower.
*/
/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
/* target will be modified by patch. return value is new ptr for target. */
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch);
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch);
/* generates a patch to move from -> to */
/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to);
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to);
/* Given a root object and a target object, construct a pointer from one to the other. */
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target);
/* Sorts the members of the object into alphabetical order. */
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,29 @@
# Whether the utils lib was build.
set(CJSON_UTILS_FOUND On)
# The include directories used by cJSON
set(CJSON_INCLUDE_DIRS "/opt/libcjson/include")
set(CJSON_INCLUDE_DIR "/opt/libcjson/include")
get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
# The cJSON library
set(CJSON_LIBRARY "cjson")
if(ON)
# Include the target
include("${_dir}/cjson.cmake")
endif()
if(CJSON_UTILS_FOUND)
# The cJSON utils library
set(CJSON_UTILS_LIBRARY cjson_utils)
# All cJSON libraries
set(CJSON_LIBRARIES "cjson_utils" "cjson")
if(ON)
# Include the target
include("${_dir}/cjson_utils.cmake")
endif()
else()
# All cJSON libraries
set(CJSON_LIBRARIES "cjson")
endif()

View File

@@ -0,0 +1,11 @@
set(PACKAGE_VERSION "1.7.18")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()

View File

@@ -0,0 +1,29 @@
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------
# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)
# Import target "cjson" for configuration ""
set_property(TARGET cjson APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(cjson PROPERTIES
IMPORTED_LOCATION_NOCONFIG "/opt/libcjson/lib/libcjson.so.1.7.18"
IMPORTED_SONAME_NOCONFIG "libcjson.so.1"
)
list(APPEND _cmake_import_check_targets cjson )
list(APPEND _cmake_import_check_files_for_cjson "/opt/libcjson/lib/libcjson.so.1.7.18" )
# Import target "cjson-static" for configuration ""
set_property(TARGET cjson-static APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(cjson-static PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "C"
IMPORTED_LOCATION_NOCONFIG "/opt/libcjson/lib/libcjson.a"
)
list(APPEND _cmake_import_check_targets cjson-static )
list(APPEND _cmake_import_check_files_for_cjson-static "/opt/libcjson/lib/libcjson.a" )
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)

View File

@@ -0,0 +1,108 @@
# Generated by CMake
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
message(FATAL_ERROR "CMake >= 2.8.12 required")
endif()
if(CMAKE_VERSION VERSION_LESS "2.8.12")
message(FATAL_ERROR "CMake >= 2.8.12 required")
endif()
cmake_policy(PUSH)
cmake_policy(VERSION 2.8.12...3.29)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------
# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
set(_cmake_targets_defined "")
set(_cmake_targets_not_defined "")
set(_cmake_expected_targets "")
foreach(_cmake_expected_target IN ITEMS cjson cjson-static)
list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
if(TARGET "${_cmake_expected_target}")
list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
else()
list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
endif()
endforeach()
unset(_cmake_expected_target)
if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
unset(_cmake_targets_defined)
unset(_cmake_targets_not_defined)
unset(_cmake_expected_targets)
unset(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)
return()
endif()
if(NOT _cmake_targets_defined STREQUAL "")
string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
endif()
unset(_cmake_targets_defined)
unset(_cmake_targets_not_defined)
unset(_cmake_expected_targets)
# The installation prefix configured by this project.
set(_IMPORT_PREFIX "/opt/libcjson")
# Create imported target cjson
add_library(cjson SHARED IMPORTED)
set_target_properties(cjson PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "/opt/libcjson/include"
INTERFACE_LINK_LIBRARIES "m"
)
# Create imported target cjson-static
add_library(cjson-static STATIC IMPORTED)
set_target_properties(cjson-static PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "/opt/libcjson/include"
)
# Load information for each installed configuration.
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/cjson-*.cmake")
foreach(_cmake_config_file IN LISTS _cmake_config_files)
include("${_cmake_config_file}")
endforeach()
unset(_cmake_config_file)
unset(_cmake_config_files)
# Cleanup temporary variables.
set(_IMPORT_PREFIX)
# Loop over all imported files and verify that they actually exist
foreach(_cmake_target IN LISTS _cmake_import_check_targets)
if(CMAKE_VERSION VERSION_LESS "3.28"
OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
if(NOT EXISTS "${_cmake_file}")
message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
\"${_cmake_file}\"
but this file does not exist. Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
\"${CMAKE_CURRENT_LIST_FILE}\"
but not all the files it references.
")
endif()
endforeach()
endif()
unset(_cmake_file)
unset("_cmake_import_check_files_for_${_cmake_target}")
endforeach()
unset(_cmake_target)
unset(_cmake_import_check_targets)
# This file does not depend on other imported targets which have
# been exported from the same project but in a separate export set.
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)

View File

@@ -0,0 +1,29 @@
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------
# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)
# Import target "cjson_utils" for configuration ""
set_property(TARGET cjson_utils APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(cjson_utils PROPERTIES
IMPORTED_LOCATION_NOCONFIG "/opt/libcjson/lib/libcjson_utils.so.1.7.18"
IMPORTED_SONAME_NOCONFIG "libcjson_utils.so.1"
)
list(APPEND _cmake_import_check_targets cjson_utils )
list(APPEND _cmake_import_check_files_for_cjson_utils "/opt/libcjson/lib/libcjson_utils.so.1.7.18" )
# Import target "cjson_utils-static" for configuration ""
set_property(TARGET cjson_utils-static APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(cjson_utils-static PROPERTIES
IMPORTED_LINK_INTERFACE_LANGUAGES_NOCONFIG "C"
IMPORTED_LOCATION_NOCONFIG "/opt/libcjson/lib/libcjson_utils.a"
)
list(APPEND _cmake_import_check_targets cjson_utils-static )
list(APPEND _cmake_import_check_files_for_cjson_utils-static "/opt/libcjson/lib/libcjson_utils.a" )
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)

View File

@@ -0,0 +1,125 @@
# Generated by CMake
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.8)
message(FATAL_ERROR "CMake >= 2.8.12 required")
endif()
if(CMAKE_VERSION VERSION_LESS "2.8.12")
message(FATAL_ERROR "CMake >= 2.8.12 required")
endif()
cmake_policy(PUSH)
cmake_policy(VERSION 2.8.12...3.29)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------
# Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1)
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
set(_cmake_targets_defined "")
set(_cmake_targets_not_defined "")
set(_cmake_expected_targets "")
foreach(_cmake_expected_target IN ITEMS cjson_utils cjson_utils-static)
list(APPEND _cmake_expected_targets "${_cmake_expected_target}")
if(TARGET "${_cmake_expected_target}")
list(APPEND _cmake_targets_defined "${_cmake_expected_target}")
else()
list(APPEND _cmake_targets_not_defined "${_cmake_expected_target}")
endif()
endforeach()
unset(_cmake_expected_target)
if(_cmake_targets_defined STREQUAL _cmake_expected_targets)
unset(_cmake_targets_defined)
unset(_cmake_targets_not_defined)
unset(_cmake_expected_targets)
unset(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)
return()
endif()
if(NOT _cmake_targets_defined STREQUAL "")
string(REPLACE ";" ", " _cmake_targets_defined_text "${_cmake_targets_defined}")
string(REPLACE ";" ", " _cmake_targets_not_defined_text "${_cmake_targets_not_defined}")
message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_cmake_targets_defined_text}\nTargets not yet defined: ${_cmake_targets_not_defined_text}\n")
endif()
unset(_cmake_targets_defined)
unset(_cmake_targets_not_defined)
unset(_cmake_expected_targets)
# The installation prefix configured by this project.
set(_IMPORT_PREFIX "/opt/libcjson")
# Create imported target cjson_utils
add_library(cjson_utils SHARED IMPORTED)
set_target_properties(cjson_utils PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "/opt/libcjson/include"
INTERFACE_LINK_LIBRARIES "cjson"
)
# Create imported target cjson_utils-static
add_library(cjson_utils-static STATIC IMPORTED)
set_target_properties(cjson_utils-static PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "/opt/libcjson/include"
INTERFACE_LINK_LIBRARIES "cjson-static"
)
# Load information for each installed configuration.
file(GLOB _cmake_config_files "${CMAKE_CURRENT_LIST_DIR}/cjson_utils-*.cmake")
foreach(_cmake_config_file IN LISTS _cmake_config_files)
include("${_cmake_config_file}")
endforeach()
unset(_cmake_config_file)
unset(_cmake_config_files)
# Cleanup temporary variables.
set(_IMPORT_PREFIX)
# Loop over all imported files and verify that they actually exist
foreach(_cmake_target IN LISTS _cmake_import_check_targets)
if(CMAKE_VERSION VERSION_LESS "3.28"
OR NOT DEFINED _cmake_import_check_xcframework_for_${_cmake_target}
OR NOT IS_DIRECTORY "${_cmake_import_check_xcframework_for_${_cmake_target}}")
foreach(_cmake_file IN LISTS "_cmake_import_check_files_for_${_cmake_target}")
if(NOT EXISTS "${_cmake_file}")
message(FATAL_ERROR "The imported target \"${_cmake_target}\" references the file
\"${_cmake_file}\"
but this file does not exist. Possible reasons include:
* The file was deleted, renamed, or moved to another location.
* An install or uninstall procedure did not complete successfully.
* The installation package was faulty and contained
\"${CMAKE_CURRENT_LIST_FILE}\"
but not all the files it references.
")
endif()
endforeach()
endif()
unset(_cmake_file)
unset("_cmake_import_check_files_for_${_cmake_target}")
endforeach()
unset(_cmake_target)
unset(_cmake_import_check_targets)
# Make sure the targets which have been exported in some other
# export set exist.
unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)
foreach(_target "cjson" "cjson-static" )
if(NOT TARGET "${_target}" )
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}")
endif()
endforeach()
if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)
if(CMAKE_FIND_PACKAGE_NAME)
set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "The following imported targets are referenced, but are missing: ${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}")
else()
message(FATAL_ERROR "The following imported targets are referenced, but are missing: ${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}")
endif()
endif()
unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)
# Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP)

BIN
libcjson/lib/libcjson.a Normal file

Binary file not shown.

1
libcjson/lib/libcjson.so Symbolic link
View File

@@ -0,0 +1 @@
libcjson.so.1

1
libcjson/lib/libcjson.so.1 Symbolic link
View File

@@ -0,0 +1 @@
libcjson.so.1.7.18

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
libcjson_utils.so.1

View File

@@ -0,0 +1 @@
libcjson_utils.so.1.7.18

Binary file not shown.

View File

@@ -0,0 +1,10 @@
libdir=/opt/libcjson/lib
includedir=/opt/libcjson/include
Name: libcjson
Version: 1.7.18
Description: Ultralightweight JSON parser in ANSI C
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson
Libs.private: -lm
Cflags: -I${includedir} -I${includedir}/cjson

View File

@@ -0,0 +1,10 @@
libdir=/opt/libcjson/lib
includedir=/opt/libcjson/include
Name: libcjson_utils
Version: 1.7.18
Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON.
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson_utils
Cflags: -I${includedir} -I${includedir}/cjson
Requires: libcjson

259
libcurl.c Normal file
View File

@@ -0,0 +1,259 @@
#include "libcurl.h"
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
// 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if (ptr == NULL) {
/* 内存不足! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
char *GetLocalAddr(char *url)
{
CURL *curl_handle;
CURLcode res;
struct curl_slist *headers = NULL;
struct MemoryStruct chunk;
chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */
chunk.size = 0; /* 此时没有数据 */
curl_global_init(CURL_GLOBAL_ALL);
/* 初始化curl会话 */
curl_handle = curl_easy_init();
char *p = NULL;
char *buff;
p = strstr(url, "-H");
if (p) {
buff = (char *)alloca(p - url + 1);
if (buff == NULL)
perror("out of memory.");
memset(buff, 0, p - url + 1);
memcpy(buff, url, (int)(p - url - 1));
// 赋值header值
headers = curl_slist_append(headers, p + 3);
// 设置header
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_URL, buff);
} else {
/* 指定要获取的URL */
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
}
/* 将所有数据发送到此函数 */
//对于同一次阻塞的curl_easy_perform而言在写完获取的数据之前会多次调用 WriteMemoryCallback
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* 将"chunk"结构传递给回调函数 */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
//对于同一次阻塞的curl_easy_perform而言在写完获取的数据之前会多次调用 WriteMemoryCallback
res = curl_easy_perform(curl_handle);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {
//printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
//printf("%s", chunk.memory);
;
}
curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return chunk.memory;
}
// 获取公网IP
char *CurlGetIpArea(char *ip)
{
char url[256] = { 0 };
snprintf(url, sizeof(url), "https://qifu-api.baidubce.com/ip/geo/v1/district?ip=%s", ip);
CURL *curl_handle;
CURLcode res;
struct curl_slist *headers = NULL;
struct MemoryStruct chunk;
chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */
chunk.size = 0; /* 此时没有数据 */
curl_global_init(CURL_GLOBAL_ALL);
/* 初始化curl会话 */
curl_handle = curl_easy_init();
char *p = NULL;
char *buff;
p = strstr(url, "-H");
if (p) {
buff = (char *)alloca(p - url + 1);
if (buff == NULL)
perror("out of memory.");
memset(buff, 0, p - url + 1);
memcpy(buff, url, (int)(p - url - 1));
// 赋值header值
headers = curl_slist_append(headers, p + 3);
// 设置header
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl_handle, CURLOPT_URL, buff);
} else {
/* 指定要获取的URL */
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
}
/* 将所有数据发送到此函数 */
//对于同一次阻塞的curl_easy_perform而言在写完获取的数据之前会多次调用 WriteMemoryCallback
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* 将"chunk"结构传递给回调函数 */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
//对于同一次阻塞的curl_easy_perform而言在写完获取的数据之前会多次调用 WriteMemoryCallback
res = curl_easy_perform(curl_handle);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {
//printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
//printf("%s", chunk.memory);
;
}
curl_easy_cleanup(curl_handle);
curl_global_cleanup();
return chunk.memory;
}
// 函数用于从 cJSON 对象提取字段内容
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'; // 如果字段不存在或不是字符串,设置为空字符串
}
}
// 函数用于从 JSON 字符串解析为结构体
int parse_json_to_struct(const char *json_string, Response *response)
{
if (!json_string || !response) {
fprintf(stderr, "Invalid input parameters!\n");
return -1;
}
// 初始化结构体
memset(response, 0, sizeof(Response));
// 解析 JSON 字符串
cJSON *root = cJSON_Parse(json_string);
if (!root) {
fprintf(stderr, "Error parsing JSON: %s\n", cJSON_GetErrorPtr());
printf("%s\n", json_string);
return -1;
}
// 解析字段
parse_string_field(root, "code", response->code, sizeof(response->code));
parse_string_field(root, "ip", response->ip, sizeof(response->ip));
// 如果 code 不是 "Success",直接返回
if (strcmp(response->code, "Success") != 0) {
fprintf(stderr, "Invalid code: %s\n", response->code);
cJSON_Delete(root);
return -1;
}
// 解析 data 对象
cJSON *data_item = cJSON_GetObjectItemCaseSensitive(root, "data");
if (cJSON_IsObject(data_item)) {
parse_string_field(data_item, "continent", response->data.continent, sizeof(response->data.continent));
parse_string_field(data_item, "country", response->data.country, sizeof(response->data.country));
parse_string_field(data_item, "zipcode", response->data.zipcode, sizeof(response->data.zipcode));
parse_string_field(data_item, "owner", response->data.owner, sizeof(response->data.owner));
parse_string_field(data_item, "isp", response->data.isp, sizeof(response->data.isp));
parse_string_field(data_item, "adcode", response->data.adcode, sizeof(response->data.adcode));
parse_string_field(data_item, "prov", response->data.prov, sizeof(response->data.prov));
parse_string_field(data_item, "city", response->data.city, sizeof(response->data.city));
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[])
{
char *p = curl_get_area("1.1.1.1");
puts(p);
// 定义 Response 结构体
Response response;
// 解析 JSON 到结构体
if (parse_json_to_struct(p, &response) == 0) {
// 输出解析结果
printf("Code: %s\n", response.code);
printf("IP: %s\n", response.ip);
printf("Continent: %s\n", response.data.continent);
printf("Country: %s\n", response.data.country);
printf("ISP: %s\n", response.data.isp);
printf("Region: %s\n", response.data.region);
} else {
fprintf(stderr, "Failed to parse JSON.\n");
}
free(p);
}
*/

49
libcurl.h Normal file
View File

@@ -0,0 +1,49 @@
#ifndef LIBCURL_H
#define LIBCURL_H
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <assert.h>
#include <limits.h>
#include <stdarg.h>
#include <cjson/cJSON.h>
// 定义嵌套的数据结构
typedef struct {
char continent[64];
char country[64];
char zipcode[64];
char owner[64];
char isp[64];
char adcode[64];
char prov[64];
char city[64];
char district[64];
char region[64];
} Data;
// 定义主结构
typedef struct {
char code[32];
Data data;
char ip[64];
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);
#endif

BIN
libcurl/bin/curl Normal file

Binary file not shown.

195
libcurl/bin/curl-config Normal file
View File

@@ -0,0 +1,195 @@
#!/bin/sh
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# shellcheck disable=SC2006
prefix='/opt/libcurl'
# Used in 'libdir'
# shellcheck disable=SC2034
exec_prefix="${prefix}"
# shellcheck disable=SC2034
includedir="${prefix}/include"
cppflag_curl_staticlib='-DCURL_STATICLIB'
usage()
{
cat <<EOF
Usage: curl-config [OPTION]
Available values for OPTION include:
--built-shared says 'yes' if libcurl was built shared
--ca CA bundle install path
--cc compiler
--cflags preprocessor and compiler flags
--checkfor [version] check for (lib)curl of the specified version
--configure the arguments given to configure when building curl
--features newline separated list of enabled features
--help display this help and exit
--libs library linking information
--prefix curl install prefix
--protocols newline separated list of enabled protocols
--ssl-backends output the SSL backends libcurl was built to support
--static-libs static libcurl library linking information
--version output version information
--vernum output version as a hexadecimal number
EOF
exit "$1"
}
if test "$#" -eq 0; then
usage 1
fi
while test "$#" -gt 0; do
case "$1" in
--built-shared)
echo 'no'
;;
--ca)
echo '/etc/ssl/certs/ca-certificates.crt'
;;
--cc)
echo 'clang'
;;
--prefix)
echo "$prefix"
;;
--feature|--features)
for feature in alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets zstd ''; do
test -n "$feature" && echo "$feature"
done
;;
--protocols)
# shellcheck disable=SC2043
for protocol in DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS IPFS IPNS MQTT POP3 POP3S RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP WS WSS; do
echo "$protocol"
done
;;
--version)
echo 'libcurl 8.11.1'
exit 0
;;
--checkfor)
checkfor="$2"
cmajor=`echo "$checkfor" | cut -d. -f1`
cminor=`echo "$checkfor" | cut -d. -f2`
# when extracting the patch part we strip off everything after a
# dash as that's used for things like version 1.2.3-pre1
cpatch=`echo "$checkfor" | cut -d. -f3 | cut -d- -f1`
vmajor=`echo '8.11.1' | cut -d. -f1`
vminor=`echo '8.11.1' | cut -d. -f2`
# when extracting the patch part we strip off everything after a
# dash as that's used for things like version 1.2.3-pre1
vpatch=`echo '8.11.1' | cut -d. -f3 | cut -d- -f1`
if test "$vmajor" -gt "$cmajor"; then
exit 0
fi
if test "$vmajor" -eq "$cmajor"; then
if test "$vminor" -gt "$cminor"; then
exit 0
fi
if test "$vminor" -eq "$cminor"; then
if test "$cpatch" -le "$vpatch"; then
exit 0
fi
fi
fi
echo "requested version $checkfor is newer than existing 8.11.1"
exit 1
;;
--vernum)
echo '080b01'
exit 0
;;
--help)
usage 0
;;
--cflags)
if test "X$cppflag_curl_staticlib" = 'X-DCURL_STATICLIB'; then
CPPFLAG_CURL_STATICLIB='-DCURL_STATICLIB '
else
CPPFLAG_CURL_STATICLIB=''
fi
if test "X${prefix}/include" = 'X/usr/include'; then
echo "${CPPFLAG_CURL_STATICLIB}"
else
echo "${CPPFLAG_CURL_STATICLIB}-I${prefix}/include"
fi
;;
--libs)
if test "X${exec_prefix}/lib" != 'X/usr/lib' -a "X${exec_prefix}/lib" != 'X/usr/lib64'; then
CURLLIBDIR="-L${exec_prefix}/lib "
else
CURLLIBDIR=''
fi
if test 'Xno' = 'Xno'; then
echo "${CURLLIBDIR}-lcurl -lssh2 -lssh2 -lgpg-error -lssl -ldl -lcrypto -ldl -lz -lssl -lcrypto -lssl -ldl -pthread -lcrypto -ldl -pthread -lzstd -lz"
else
echo "${CURLLIBDIR}-lcurl"
fi
;;
--ssl-backends)
echo 'OpenSSL v3+'
;;
--static-libs)
if test 'Xyes' != 'Xno'; then
echo "${exec_prefix}/lib/libcurl.a -lssh2 -lssh2 -lgpg-error -lssl -ldl -lcrypto -ldl -lz -lssl -lcrypto -lssl -ldl -pthread -lcrypto -ldl -pthread -lzstd -lz"
else
echo 'curl was built with static libraries disabled' >&2
exit 1
fi
;;
--configure)
echo " '--prefix=/opt/libcurl' '--disable-shared' '--enable-static' '--disable-ldap' '--enable-ipv6' '--enable-unix-sockets' '--with-ssl' '--with-libssh2' '--disable-docs' '--disable-manual' '--without-libpsl' '--without-brotli' 'CC=clang' 'LDFLAGS=-static'"
;;
*)
echo "unknown option: $1"
usage 1
;;
esac
shift
done
exit 0

3266
libcurl/include/curl/curl.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
#ifndef CURLINC_CURLVER_H
#define CURLINC_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
#define LIBCURL_COPYRIGHT "Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "8.11.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 8
#define LIBCURL_VERSION_MINOR 11
#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal (using 8 bits each). All three numbers are always represented
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
appears as "0x090b07".
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
Note: This define is the full hex number and _does not_ use the
CURL_VERSION_BITS() macro since curl's own configure script greps for it
and needs it to contain the full number.
*/
#define LIBCURL_VERSION_NUM 0x080b01
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in git, as the timestamp is properly set in the
* tarballs by the maketgz script.
*
* The format of the date follows this template:
*
* "2007-11-23"
*/
#define LIBCURL_TIMESTAMP "2024-12-11"
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
#define CURL_AT_LEAST_VERSION(x,y,z) \
(LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
#endif /* CURLINC_CURLVER_H */

125
libcurl/include/curl/easy.h Normal file
View File

@@ -0,0 +1,125 @@
#ifndef CURLINC_EASY_H
#define CURLINC_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/* Flag bits in the curl_blob struct: */
#define CURL_BLOB_COPY 1 /* tell libcurl to copy the data */
#define CURL_BLOB_NOCOPY 0 /* tell libcurl to NOT copy the data */
struct curl_blob {
void *data;
size_t len;
unsigned int flags; /* bit 0 is defined, the rest are reserved and should be
left zeroes */
};
CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
/*
* NAME curl_easy_getinfo()
*
* DESCRIPTION
*
* Request internal information from the curl session with this function.
* The third argument MUST be pointing to the specific type of the used option
* which is documented in each manpage of the option. The data pointed to
* will be filled in accordingly and can be relied upon only if the function
* returns CURLE_OK. This function is intended to get used *AFTER* a performed
* transfer, all results from this function are undefined until the transfer
* is completed.
*/
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
/*
* NAME curl_easy_duphandle()
*
* DESCRIPTION
*
* Creates a new curl session handle with the same options set for the handle
* passed in. Duplicating a handle could only be a matter of cloning data and
* options, internal state info and things like persistent connections cannot
* be transferred. It is useful in multithreaded applications when you can run
* curl_easy_duphandle() for each new thread to avoid a series of identical
* curl_easy_setopt() invokes in every thread.
*/
CURL_EXTERN CURL *curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
*
* DESCRIPTION
*
* Re-initializes a CURL handle to the default values. This puts back the
* handle to the same state as it was in when it was just created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
*/
CURL_EXTERN void curl_easy_reset(CURL *curl);
/*
* NAME curl_easy_recv()
*
* DESCRIPTION
*
* Receives data from the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
size_t *n);
/*
* NAME curl_easy_send()
*
* DESCRIPTION
*
* Sends data over the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
size_t buflen, size_t *n);
/*
* NAME curl_easy_upkeep()
*
* DESCRIPTION
*
* Performs connection upkeep for the given session handle.
*/
CURL_EXTERN CURLcode curl_easy_upkeep(CURL *curl);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

View File

@@ -0,0 +1,74 @@
#ifndef CURLINC_HEADER_H
#define CURLINC_HEADER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
struct curl_header {
char *name; /* this might not use the same case */
char *value;
size_t amount; /* number of headers using this name */
size_t index; /* ... of this instance, 0 or higher */
unsigned int origin; /* see bits below */
void *anchor; /* handle privately used by libcurl */
};
/* 'origin' bits */
#define CURLH_HEADER (1<<0) /* plain server header */
#define CURLH_TRAILER (1<<1) /* trailers */
#define CURLH_CONNECT (1<<2) /* CONNECT headers */
#define CURLH_1XX (1<<3) /* 1xx headers */
#define CURLH_PSEUDO (1<<4) /* pseudo headers */
typedef enum {
CURLHE_OK,
CURLHE_BADINDEX, /* header exists but not with this index */
CURLHE_MISSING, /* no such header exists */
CURLHE_NOHEADERS, /* no headers at all exist (yet) */
CURLHE_NOREQUEST, /* no request with this number was used */
CURLHE_OUT_OF_MEMORY, /* out of memory while processing */
CURLHE_BAD_ARGUMENT, /* a function argument was not okay */
CURLHE_NOT_BUILT_IN /* if API was disabled in the build */
} CURLHcode;
CURL_EXTERN CURLHcode curl_easy_header(CURL *easy,
const char *name,
size_t index,
unsigned int origin,
int request,
struct curl_header **hout);
CURL_EXTERN struct curl_header *curl_easy_nextheader(CURL *easy,
unsigned int origin,
int request,
struct curl_header *prev);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_HEADER_H */

View File

@@ -0,0 +1,85 @@
#ifndef CURLINC_MPRINTF_H
#define CURLINC_MPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include <stdarg.h>
#include <stdio.h> /* needed for FILE */
#include "curl.h" /* for CURL_EXTERN */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CURL_TEMP_PRINTF
#if (defined(__GNUC__) || defined(__clang__) || \
defined(__IAR_SYSTEMS_ICC__)) && \
defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
!defined(CURL_NO_FMT_CHECKS)
#if defined(__MINGW32__) && !defined(__clang__)
#if defined(__MINGW_PRINTF_FORMAT) /* mingw-w64 3.0.0+. Needs stdio.h. */
#define CURL_TEMP_PRINTF(fmt, arg) \
__attribute__((format(__MINGW_PRINTF_FORMAT, fmt, arg)))
#else
#define CURL_TEMP_PRINTF(fmt, arg)
#endif
#else
#define CURL_TEMP_PRINTF(fmt, arg) \
__attribute__((format(printf, fmt, arg)))
#endif
#else
#define CURL_TEMP_PRINTF(fmt, arg)
#endif
#endif
CURL_EXTERN int curl_mprintf(const char *format, ...)
CURL_TEMP_PRINTF(1, 2);
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...)
CURL_TEMP_PRINTF(2, 3);
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...)
CURL_TEMP_PRINTF(2, 3);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
const char *format, ...)
CURL_TEMP_PRINTF(3, 4);
CURL_EXTERN int curl_mvprintf(const char *format, va_list args)
CURL_TEMP_PRINTF(1, 0);
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args)
CURL_TEMP_PRINTF(2, 0);
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args)
CURL_TEMP_PRINTF(2, 0);
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
const char *format, va_list args)
CURL_TEMP_PRINTF(3, 0);
CURL_EXTERN char *curl_maprintf(const char *format, ...)
CURL_TEMP_PRINTF(1, 2);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args)
CURL_TEMP_PRINTF(1, 0);
#undef CURL_TEMP_PRINTF
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_MPRINTF_H */

View File

@@ -0,0 +1,481 @@
#ifndef CURLINC_MULTI_H
#define CURLINC_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
This is an "external" header file. Do not give away any internals here!
GOALS
o Enable a "pull" interface. The application that uses libcurl decides where
and when to ask libcurl to get/send data.
o Enable multiple simultaneous transfers in the same thread without making it
complicated for the application.
o Enable the application to select() on its own file descriptors and curl's
file descriptors simultaneous easily.
*/
/*
* This header file should not really need to include "curl.h" since curl.h
* itself includes this file and we expect user applications to do #include
* <curl/curl.h> without the need for especially including multi.h.
*
* For some reason we added this include here at one point, and rather than to
* break existing (wrongly written) libcurl applications, we leave it as-is
* but with this warning attached.
*/
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void CURLM;
typedef enum {
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
curl_multi_socket*() soon */
CURLM_OK,
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
CURLM_OUT_OF_MEMORY, /* if you ever get this, you are in deep sh*t */
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_ADDED_ALREADY, /* an easy handle already added to a multi handle was
attempted to get added - again */
CURLM_RECURSIVE_API_CALL, /* an api function was called from inside a
callback */
CURLM_WAKEUP_FAILURE, /* wakeup is unavailable or failed */
CURLM_BAD_FUNCTION_ARGUMENT, /* function called with a bad parameter */
CURLM_ABORTED_BY_CALLBACK,
CURLM_UNRECOVERABLE_POLL,
CURLM_LAST
} CURLMcode;
/* just to make code nicer when using curl_multi_socket() you can now check
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
/* bitmask bits for CURLMOPT_PIPELINING */
#define CURLPIPE_NOTHING 0L
#define CURLPIPE_HTTP1 1L
#define CURLPIPE_MULTIPLEX 2L
typedef enum {
CURLMSG_NONE, /* first, not used */
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
the CURLcode of the transfer */
CURLMSG_LAST /* last, not used */
} CURLMSG;
struct CURLMsg {
CURLMSG msg; /* what this message means */
CURL *easy_handle; /* the handle it concerns */
union {
void *whatever; /* message-specific data */
CURLcode result; /* return code for transfer */
} data;
};
typedef struct CURLMsg CURLMsg;
/* Based on poll(2) structure and values.
* We do not use pollfd and POLL* constants explicitly
* to cover platforms without poll(). */
#define CURL_WAIT_POLLIN 0x0001
#define CURL_WAIT_POLLPRI 0x0002
#define CURL_WAIT_POLLOUT 0x0004
struct curl_waitfd {
curl_socket_t fd;
short events;
short revents;
};
/*
* Name: curl_multi_init()
*
* Desc: initialize multi-style curl usage
*
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
CURL_EXTERN CURLM *curl_multi_init(void);
/*
* Name: curl_multi_add_handle()
*
* Desc: add a standard curl handle to the multi stack
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_remove_handle()
*
* Desc: removes a curl handle from the multi stack again
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_fdset()
*
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
* poll() on. We want curl_multi_perform() called as soon as one of
* them are ready.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
/*
* Name: curl_multi_wait()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_wait(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_poll()
*
* Desc: Poll on all fds within a CURLM set as well as any
* additional fds passed to the function.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle,
struct curl_waitfd extra_fds[],
unsigned int extra_nfds,
int timeout_ms,
int *ret);
/*
* Name: curl_multi_wakeup()
*
* Desc: wakes up a sleeping curl_multi_poll call.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle);
/*
* Name: curl_multi_perform()
*
* Desc: When the app thinks there is data available for curl it calls this
* function to read/write whatever there is right now. This returns
* as soon as the reads and writes are done. This function does not
* require that there actually is data available for reading or that
* data can be written, it can be called just in case. It returns
* the number of handles that still transfer data in the second
* argument's integer-pointer.
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
* still have occurred problems on individual transfers even when
* this returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
/*
* Name: curl_multi_cleanup()
*
* Desc: Cleans up and removes a whole multi stack. It does not free or
* touch any individual easy handles in any way. We need to define
* in what state those handles will be if this function is called
* in the middle of a transfer.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
/*
* Name: curl_multi_info_read()
*
* Desc: Ask the multi handle if there is any messages/informationals from
* the individual transfers. Messages include informationals such as
* error code from the transfer or just the fact that a transfer is
* completed. More details on these should be written down as well.
*
* Repeated calls to this function will return a new struct each
* time, until a special "end of msgs" struct is returned as a signal
* that there is no more to get at this point.
*
* The data the returned pointer points to will not survive calling
* curl_multi_cleanup().
*
* The 'CURLMsg' struct is meant to be simple and only contain basic
* information. If more involved information is wanted, we will
* provide the particular "transfer handle" in that struct and that
* should/could/would be used in subsequent curl_easy_getinfo() calls
* (or similar). The point being that we must never expose complex
* structs to applications, as then we will undoubtably get backwards
* compatibility problems in the future.
*
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
* of structs. It also writes the number of messages left in the
* queue (after this read) in the integer the second argument points
* to.
*/
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
/*
* Name: curl_multi_strerror()
*
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
* value into the equivalent human readable error string. This is
* useful for printing meaningful error messages.
*
* Returns: A pointer to a null-terminated error message.
*/
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
/*
* Name: curl_multi_socket() and
* curl_multi_socket_all()
*
* Desc: An alternative version of curl_multi_perform() that allows the
* application to pass in one of the file descriptors that have been
* detected to have "action" on them and let libcurl perform.
* See manpage for details.
*/
#define CURL_POLL_NONE 0
#define CURL_POLL_IN 1
#define CURL_POLL_OUT 2
#define CURL_POLL_INOUT 3
#define CURL_POLL_REMOVE 4
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
#define CURL_CSELECT_IN 0x01
#define CURL_CSELECT_OUT 0x02
#define CURL_CSELECT_ERR 0x04
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
void *userp, /* private callback
pointer */
void *socketp); /* private socket
pointer */
/*
* Name: curl_multi_timer_callback
*
* Desc: Called by libcurl whenever the library detects a change in the
* maximum number of milliseconds the app is allowed to wait before
* curl_multi_socket() or curl_multi_perform() must be called
* (to allow libcurl's timed events to take place).
*
* Returns: The callback should return zero.
*/
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
long timeout_ms, /* see above */
void *userp); /* private callback
pointer */
CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
curl_multi_socket(CURLM *multi_handle, curl_socket_t s, int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s,
int ev_bitmask,
int *running_handles);
CURL_EXTERN CURLMcode CURL_DEPRECATED(7.19.5, "Use curl_multi_socket_action()")
curl_multi_socket_all(CURLM *multi_handle, int *running_handles);
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
/* This macro below was added in 7.16.3 to push users who recompile to use
the new curl_multi_socket_action() instead of the old curl_multi_socket()
*/
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
#endif
/*
* Name: curl_multi_timeout()
*
* Desc: Returns the maximum number of milliseconds the app is allowed to
* wait before curl_multi_socket() or curl_multi_perform() must be
* called (to allow libcurl's timed events to take place).
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
long *milliseconds);
typedef enum {
/* This is the socket callback function pointer */
CURLOPT(CURLMOPT_SOCKETFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 1),
/* This is the argument passed to the socket callback */
CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2),
/* set to 1 to enable pipelining for this multi handle */
CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3),
/* This is the timer callback function pointer */
CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4),
/* This is the argument passed to the timer callback */
CURLOPT(CURLMOPT_TIMERDATA, CURLOPTTYPE_OBJECTPOINT, 5),
/* maximum number of entries in the connection cache */
CURLOPT(CURLMOPT_MAXCONNECTS, CURLOPTTYPE_LONG, 6),
/* maximum number of (pipelining) connections to one host */
CURLOPT(CURLMOPT_MAX_HOST_CONNECTIONS, CURLOPTTYPE_LONG, 7),
/* maximum number of requests in a pipeline */
CURLOPT(CURLMOPT_MAX_PIPELINE_LENGTH, CURLOPTTYPE_LONG, 8),
/* a connection with a content-length longer than this
will not be considered for pipelining */
CURLOPT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 9),
/* a connection with a chunk length longer than this
will not be considered for pipelining */
CURLOPT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE, CURLOPTTYPE_OFF_T, 10),
/* a list of site names(+port) that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SITE_BL, CURLOPTTYPE_OBJECTPOINT, 11),
/* a list of server types that are blocked from pipelining */
CURLOPT(CURLMOPT_PIPELINING_SERVER_BL, CURLOPTTYPE_OBJECTPOINT, 12),
/* maximum number of open connections in total */
CURLOPT(CURLMOPT_MAX_TOTAL_CONNECTIONS, CURLOPTTYPE_LONG, 13),
/* This is the server push callback function pointer */
CURLOPT(CURLMOPT_PUSHFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 14),
/* This is the argument passed to the server push callback */
CURLOPT(CURLMOPT_PUSHDATA, CURLOPTTYPE_OBJECTPOINT, 15),
/* maximum number of concurrent streams to support on a connection */
CURLOPT(CURLMOPT_MAX_CONCURRENT_STREAMS, CURLOPTTYPE_LONG, 16),
CURLMOPT_LASTENTRY /* the last unused */
} CURLMoption;
/*
* Name: curl_multi_setopt()
*
* Desc: Sets options for the multi handle.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURLMoption option, ...);
/*
* Name: curl_multi_assign()
*
* Desc: This function sets an association in the multi handle between the
* given socket and a private pointer of the application. This is
* (only) useful for curl_multi_socket uses.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t sockfd, void *sockp);
/*
* Name: curl_multi_get_handles()
*
* Desc: Returns an allocated array holding all handles currently added to
* the multi handle. Marks the final entry with a NULL pointer. If
* there is no easy handle added to the multi handle, this function
* returns an array with the first entry as a NULL pointer.
*
* Returns: NULL on failure, otherwise a CURL **array pointer
*/
CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle);
/*
* Name: curl_push_callback
*
* Desc: This callback gets called when a new stream is being pushed by the
* server. It approves or denies the new stream. It can also decide
* to completely fail the connection.
*
* Returns: CURL_PUSH_OK, CURL_PUSH_DENY or CURL_PUSH_ERROROUT
*/
#define CURL_PUSH_OK 0
#define CURL_PUSH_DENY 1
#define CURL_PUSH_ERROROUT 2 /* added in 7.72.0 */
struct curl_pushheaders; /* forward declaration only */
CURL_EXTERN char *curl_pushheader_bynum(struct curl_pushheaders *h,
size_t num);
CURL_EXTERN char *curl_pushheader_byname(struct curl_pushheaders *h,
const char *name);
typedef int (*curl_push_callback)(CURL *parent,
CURL *easy,
size_t num_headers,
struct curl_pushheaders *headers,
void *userp);
/*
* Name: curl_multi_waitfds()
*
* Desc: Ask curl for fds for polling. The app can use these to poll on.
* We want curl_multi_perform() called as soon as one of them are
* ready. Passing zero size allows to get just a number of fds.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_waitfds(CURLM *multi,
struct curl_waitfd *ufds,
unsigned int size,
unsigned int *fd_count);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

View File

@@ -0,0 +1,70 @@
#ifndef CURLINC_OPTIONS_H
#define CURLINC_OPTIONS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
CURLOT_LONG, /* long (a range of values) */
CURLOT_VALUES, /* (a defined set or bitmask) */
CURLOT_OFF_T, /* curl_off_t (a range of values) */
CURLOT_OBJECT, /* pointer (void *) */
CURLOT_STRING, /* (char * to null-terminated buffer) */
CURLOT_SLIST, /* (struct curl_slist *) */
CURLOT_CBPTR, /* (void * passed as-is to a callback) */
CURLOT_BLOB, /* blob (struct curl_blob *) */
CURLOT_FUNCTION /* function pointer */
} curl_easytype;
/* Flag bits */
/* "alias" means it is provided for old programs to remain functional,
we prefer another name */
#define CURLOT_FLAG_ALIAS (1<<0)
/* The CURLOPTTYPE_* id ranges can still be used to figure out what type/size
to use for curl_easy_setopt() for the given id */
struct curl_easyoption {
const char *name;
CURLoption id;
curl_easytype type;
unsigned int flags;
};
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_name(const char *name);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_by_id(CURLoption id);
CURL_EXTERN const struct curl_easyoption *
curl_easy_option_next(const struct curl_easyoption *prev);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_OPTIONS_H */

View File

@@ -0,0 +1,35 @@
#ifndef CURLINC_STDCHEADERS_H
#define CURLINC_STDCHEADERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include <sys/types.h>
size_t fread(void *, size_t, size_t, FILE *);
size_t fwrite(const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
#endif /* CURLINC_STDCHEADERS_H */

View File

@@ -0,0 +1,496 @@
#ifndef CURLINC_SYSTEM_H
#define CURLINC_SYSTEM_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/*
* Try to keep one section per platform, compiler and architecture, otherwise,
* if an existing section is reused for a different one and later on the
* original is adjusted, probably the piggybacking one can be adversely
* changed.
*
* In order to differentiate between platforms/compilers/architectures use
* only compiler built-in predefined preprocessor symbols.
*
* curl_off_t
* ----------
*
* For any given platform/compiler curl_off_t must be typedef'ed to a 64-bit
* wide signed integral data type. The width of this data type must remain
* constant and independent of any possible large file support settings.
*
* As an exception to the above, curl_off_t shall be typedef'ed to a 32-bit
* wide signed integral data type if there is no 64-bit type.
*
* As a general rule, curl_off_t shall not be mapped to off_t. This rule shall
* only be violated if off_t is the only 64-bit data type available and the
* size of off_t is independent of large file support settings. Keep your
* build on the safe side avoiding an off_t gating. If you have a 64-bit
* off_t then take for sure that another 64-bit data type exists, dig deeper
* and you will find it.
*
*/
#if defined(__DJGPP__) || defined(__GO32__)
# if defined(__DJGPP__) && (__DJGPP__ > 1)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__SALFORDC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__BORLANDC__)
# if (__BORLANDC__ < 0x520)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TURBOC__)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__POCC__)
# if (__POCC__ < 280)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# elif defined(_MSC_VER)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__LCC__)
# if defined(__MCST__) /* MCST eLbrus Compiler Collection */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# else /* Local (or Little) C Compiler */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(macintosh)
# include <ConditionalMacros.h>
# if TYPE_LONGLONG
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__TANDEM)
# if ! defined(__LP64)
/* Required for 32-bit NonStop builds only. */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# endif
#elif defined(_WIN32_WCE)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__MINGW32__)
# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T PRId64
# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
# define CURL_PULL_SYS_TYPES_H 1
#elif defined(__VMS)
# if defined(__VAX)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T unsigned int
#elif defined(__OS400__)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__MVS__)
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__370__)
# if defined(__IBMC__) || defined(__IBMCPP__)
# if defined(_ILP32)
# elif defined(_LP64)
# endif
# if defined(_LONG_LONG)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
# endif
#elif defined(TPF)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#elif defined(__TINYC__) /* also known as tcc */
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Oracle Solaris Studio */
# if !defined(__LP64) && (defined(__ILP32) || \
defined(__i386) || \
defined(__sparcv8) || \
defined(__sparcv8plus))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64) || \
defined(__amd64) || defined(__sparcv9)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__xlc__) /* IBM xlc compiler */
# if !defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#elif defined(__hpux) /* HP aCC compiler */
# if !defined(_LP64)
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
/* ===================================== */
/* KEEP MSVC THE PENULTIMATE ENTRY */
/* ===================================== */
#elif defined(_MSC_VER)
# if (_MSC_VER >= 1800)
# include <inttypes.h>
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T PRId64
# define CURL_FORMAT_CURL_OFF_TU PRIu64
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# elif (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64)
# define CURL_TYPEOF_CURL_OFF_T __int64
# define CURL_FORMAT_CURL_OFF_T "I64d"
# define CURL_FORMAT_CURL_OFF_TU "I64u"
# define CURL_SUFFIX_CURL_OFF_T i64
# define CURL_SUFFIX_CURL_OFF_TU ui64
# else
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T int
/* ===================================== */
/* KEEP GENERIC GCC THE LAST ENTRY */
/* ===================================== */
#elif defined(__GNUC__) && !defined(_SCO_DS)
# if !defined(__LP64__) && \
(defined(__ILP32__) || defined(__i386__) || defined(__hppa__) || \
defined(__ppc__) || defined(__powerpc__) || defined(__arm__) || \
defined(__sparc__) || defined(__mips__) || defined(__sh__) || \
defined(__XTENSA__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 4) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 2147483647L))
# define CURL_TYPEOF_CURL_OFF_T long long
# define CURL_FORMAT_CURL_OFF_T "lld"
# define CURL_FORMAT_CURL_OFF_TU "llu"
# define CURL_SUFFIX_CURL_OFF_T LL
# define CURL_SUFFIX_CURL_OFF_TU ULL
# elif defined(__LP64__) || \
defined(__x86_64__) || defined(__ppc64__) || defined(__sparc64__) || \
defined(__e2k__) || \
(defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ == 8) || \
(defined(__LONG_MAX__) && __LONG_MAX__ == 9223372036854775807L)
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# endif
# define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
# define CURL_PULL_SYS_TYPES_H 1
# define CURL_PULL_SYS_SOCKET_H 1
#else
/* generic "safe guess" on old 32-bit style */
# define CURL_TYPEOF_CURL_OFF_T long
# define CURL_FORMAT_CURL_OFF_T "ld"
# define CURL_FORMAT_CURL_OFF_TU "lu"
# define CURL_SUFFIX_CURL_OFF_T L
# define CURL_SUFFIX_CURL_OFF_TU UL
# define CURL_TYPEOF_CURL_SOCKLEN_T int
#endif
#ifdef _AIX
/* AIX needs <sys/poll.h> */
#define CURL_PULL_SYS_POLL_H
#endif
/* CURL_PULL_SYS_TYPES_H is defined above when inclusion of header file */
/* sys/types.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_TYPES_H
# include <sys/types.h>
#endif
/* CURL_PULL_SYS_SOCKET_H is defined above when inclusion of header file */
/* sys/socket.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* CURL_PULL_SYS_POLL_H is defined above when inclusion of header file */
/* sys/poll.h is required here to properly make type definitions below. */
#ifdef CURL_PULL_SYS_POLL_H
# include <sys/poll.h>
#endif
/* Data type definition of curl_socklen_t. */
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
#endif
/* Data type definition of curl_off_t. */
#ifdef CURL_TYPEOF_CURL_OFF_T
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
#endif
/*
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
* these to be visible and exported by the external libcurl interface API,
* while also making them visible to the library internals, simply including
* curl_setup.h, without actually needing to include curl.h internally.
* If some day this section would grow big enough, all this should be moved
* to its own header file.
*/
/*
* Figure out if we can use the ## preprocessor operator, which is supported
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
* or __cplusplus so we need to carefully check for them too.
*/
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
defined(__ILEC400__)
/* This compiler is believed to have an ISO compatible preprocessor */
#define CURL_ISOCPP
#else
/* This compiler is believed NOT to have an ISO compatible preprocessor */
#undef CURL_ISOCPP
#endif
/*
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
*/
#if defined(__BORLANDC__) && (__BORLANDC__ == 0x0551)
# define CURLINC_OFF_T_C_HLPR2(x) x
# define CURLINC_OFF_T_C_HLPR1(x) CURLINC_OFF_T_C_HLPR2(x)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val) ## \
CURLINC_OFF_T_C_HLPR1(CURL_SUFFIX_CURL_OFF_TU)
#else
# ifdef CURL_ISOCPP
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val ## Suffix
# else
# define CURLINC_OFF_T_C_HLPR2(Val,Suffix) Val/**/Suffix
# endif
# define CURLINC_OFF_T_C_HLPR1(Val,Suffix) CURLINC_OFF_T_C_HLPR2(Val,Suffix)
# define CURL_OFF_T_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_T)
# define CURL_OFF_TU_C(Val) CURLINC_OFF_T_C_HLPR1(Val,CURL_SUFFIX_CURL_OFF_TU)
#endif
#endif /* CURLINC_SYSTEM_H */

View File

@@ -0,0 +1,718 @@
#ifndef CURLINC_TYPECHECK_GCC_H
#define CURLINC_TYPECHECK_GCC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
/* wraps curl_easy_setopt() with typechecking */
/* To add a new kind of warning, add an
* if(curlcheck_sometype_option(_curl_opt))
* if(!curlcheck_sometype(value))
* _curl_easy_setopt_err_sometype();
* block and define curlcheck_sometype_option, curlcheck_sometype and
* _curl_easy_setopt_err_sometype below
*
* NOTE: We use two nested 'if' statements here instead of the && operator, in
* order to work around gcc bug #32061. It affects only gcc 4.3.x/4.4.x
* when compiling with -Wlogical-op.
*
* To add an option that uses the same type as an existing option, you will
* just need to extend the appropriate _curl_*_option macro
*/
#define curl_easy_setopt(handle, option, value) \
__extension__({ \
CURLoption _curl_opt = (option); \
if(__builtin_constant_p(_curl_opt)) { \
CURL_IGNORE_DEPRECATION( \
if(curlcheck_long_option(_curl_opt)) \
if(!curlcheck_long(value)) \
_curl_easy_setopt_err_long(); \
if(curlcheck_off_t_option(_curl_opt)) \
if(!curlcheck_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if(curlcheck_string_option(_curl_opt)) \
if(!curlcheck_string(value)) \
_curl_easy_setopt_err_string(); \
if(curlcheck_write_cb_option(_curl_opt)) \
if(!curlcheck_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if((_curl_opt) == CURLOPT_RESOLVER_START_FUNCTION) \
if(!curlcheck_resolver_start_callback(value)) \
_curl_easy_setopt_err_resolver_start_callback(); \
if((_curl_opt) == CURLOPT_READFUNCTION) \
if(!curlcheck_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if((_curl_opt) == CURLOPT_IOCTLFUNCTION) \
if(!curlcheck_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if((_curl_opt) == CURLOPT_SOCKOPTFUNCTION) \
if(!curlcheck_sockopt_cb(value)) \
_curl_easy_setopt_err_sockopt_cb(); \
if((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION) \
if(!curlcheck_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if((_curl_opt) == CURLOPT_PROGRESSFUNCTION) \
if(!curlcheck_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if((_curl_opt) == CURLOPT_DEBUGFUNCTION) \
if(!curlcheck_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION) \
if(!curlcheck_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if(curlcheck_conv_cb_option(_curl_opt)) \
if(!curlcheck_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if((_curl_opt) == CURLOPT_SEEKFUNCTION) \
if(!curlcheck_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if(curlcheck_cb_data_option(_curl_opt)) \
if(!curlcheck_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if((_curl_opt) == CURLOPT_ERRORBUFFER) \
if(!curlcheck_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if((_curl_opt) == CURLOPT_STDERR) \
if(!curlcheck_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if(curlcheck_postfields_option(_curl_opt)) \
if(!curlcheck_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if((_curl_opt) == CURLOPT_HTTPPOST) \
if(!curlcheck_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if((_curl_opt) == CURLOPT_MIMEPOST) \
if(!curlcheck_ptr((value), curl_mime)) \
_curl_easy_setopt_err_curl_mimepost(); \
if(curlcheck_slist_option(_curl_opt)) \
if(!curlcheck_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if((_curl_opt) == CURLOPT_SHARE) \
if(!curlcheck_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
) \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
#define curl_easy_getinfo(handle, info, arg) \
__extension__({ \
CURLINFO _curl_info = (info); \
if(__builtin_constant_p(_curl_info)) { \
CURL_IGNORE_DEPRECATION( \
if(curlcheck_string_info(_curl_info)) \
if(!curlcheck_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if(curlcheck_long_info(_curl_info)) \
if(!curlcheck_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if(curlcheck_double_info(_curl_info)) \
if(!curlcheck_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if(curlcheck_slist_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
if(curlcheck_tlssessioninfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_tlssessioninfo *)) \
_curl_easy_getinfo_err_curl_tlssesssioninfo(); \
if(curlcheck_certinfo_info(_curl_info)) \
if(!curlcheck_arr((arg), struct curl_certinfo *)) \
_curl_easy_getinfo_err_curl_certinfo(); \
if(curlcheck_socket_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_socket_t)) \
_curl_easy_getinfo_err_curl_socket(); \
if(curlcheck_off_t_info(_curl_info)) \
if(!curlcheck_arr((arg), curl_off_t)) \
_curl_easy_getinfo_err_curl_off_t(); \
) \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/*
* For now, just make sure that the functions are called with three arguments
*/
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
* functions */
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
#define CURLWARNING(id, message) \
static void __attribute__((__warning__(message))) \
__attribute__((__unused__)) __attribute__((__noinline__)) \
id(void) { __asm__(""); }
CURLWARNING(_curl_easy_setopt_err_long,
"curl_easy_setopt expects a long argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
CURLWARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a "
"string ('char *' or char[]) argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_resolver_start_callback,
"curl_easy_setopt expects a "
"curl_resolver_start_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_ioctl_cb,
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_sockopt_cb,
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_opensocket_cb,
"curl_easy_setopt expects a "
"curl_opensocket_callback argument for this option"
)
CURLWARNING(_curl_easy_setopt_err_progress_cb,
"curl_easy_setopt expects a curl_progress_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_debug_cb,
"curl_easy_setopt expects a curl_debug_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_ssl_ctx_cb,
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_conv_cb,
"curl_easy_setopt expects a curl_conv_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_seek_cb,
"curl_easy_setopt expects a curl_seek_callback argument for this option")
CURLWARNING(_curl_easy_setopt_err_cb_data,
"curl_easy_setopt expects a "
"private data pointer as argument for this option")
CURLWARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a "
"char buffer of CURL_ERROR_SIZE as argument for this option")
CURLWARNING(_curl_easy_setopt_err_FILE,
"curl_easy_setopt expects a 'FILE *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_postfields,
"curl_easy_setopt expects a 'void *' or 'char *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_httpost,
"curl_easy_setopt expects a 'struct curl_httppost *' "
"argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_mimepost,
"curl_easy_setopt expects a 'curl_mime *' "
"argument for this option")
CURLWARNING(_curl_easy_setopt_err_curl_slist,
"curl_easy_setopt expects a 'struct curl_slist *' argument for this option")
CURLWARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
CURLWARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to 'char *' for this info")
CURLWARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
CURLWARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_tlssessioninfo *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_certinfo,
"curl_easy_getinfo expects a pointer to "
"'struct curl_certinfo *' for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_socket,
"curl_easy_getinfo expects a pointer to curl_socket_t for this info")
CURLWARNING(_curl_easy_getinfo_err_curl_off_t,
"curl_easy_getinfo expects a pointer to curl_off_t for this info")
/* groups of curl_easy_setops options that take the same type of argument */
/* To add a new option to one of the groups, just add
* (option) == CURLOPT_SOMETHING
* to the or-expression. If the option takes a long or curl_off_t, you do not
* have to do anything
*/
/* evaluates to true if option takes a long argument */
#define curlcheck_long_option(option) \
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define curlcheck_off_t_option(option) \
(((option) > CURLOPTTYPE_OFF_T) && ((option) < CURLOPTTYPE_BLOB))
/* evaluates to true if option takes a char* argument */
#define curlcheck_string_option(option) \
((option) == CURLOPT_ABSTRACT_UNIX_SOCKET || \
(option) == CURLOPT_ACCEPT_ENCODING || \
(option) == CURLOPT_ALTSVC || \
(option) == CURLOPT_CAINFO || \
(option) == CURLOPT_CAPATH || \
(option) == CURLOPT_COOKIE || \
(option) == CURLOPT_COOKIEFILE || \
(option) == CURLOPT_COOKIEJAR || \
(option) == CURLOPT_COOKIELIST || \
(option) == CURLOPT_CRLFILE || \
(option) == CURLOPT_CUSTOMREQUEST || \
(option) == CURLOPT_DEFAULT_PROTOCOL || \
(option) == CURLOPT_DNS_INTERFACE || \
(option) == CURLOPT_DNS_LOCAL_IP4 || \
(option) == CURLOPT_DNS_LOCAL_IP6 || \
(option) == CURLOPT_DNS_SERVERS || \
(option) == CURLOPT_DOH_URL || \
(option) == CURLOPT_ECH || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_HSTS || \
(option) == CURLOPT_HAPROXY_CLIENT_IP || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_ISSUERCERT || \
(option) == CURLOPT_KEYPASSWD || \
(option) == CURLOPT_KRBLEVEL || \
(option) == CURLOPT_LOGIN_OPTIONS || \
(option) == CURLOPT_MAIL_AUTH || \
(option) == CURLOPT_MAIL_FROM || \
(option) == CURLOPT_NETRC_FILE || \
(option) == CURLOPT_NOPROXY || \
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \
(option) == CURLOPT_PRE_PROXY || \
(option) == CURLOPT_PROTOCOLS_STR || \
(option) == CURLOPT_PROXY || \
(option) == CURLOPT_PROXY_CAINFO || \
(option) == CURLOPT_PROXY_CAPATH || \
(option) == CURLOPT_PROXY_CRLFILE || \
(option) == CURLOPT_PROXY_ISSUERCERT || \
(option) == CURLOPT_PROXY_KEYPASSWD || \
(option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
(option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
(option) == CURLOPT_PROXY_SSLCERT || \
(option) == CURLOPT_PROXY_SSLCERTTYPE || \
(option) == CURLOPT_PROXY_SSLKEY || \
(option) == CURLOPT_PROXY_SSLKEYTYPE || \
(option) == CURLOPT_PROXY_TLS13_CIPHERS || \
(option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
(option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_REDIR_PROTOCOLS_STR || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_REQUEST_TARGET || \
(option) == CURLOPT_RTSP_SESSION_ID || \
(option) == CURLOPT_RTSP_STREAM_URI || \
(option) == CURLOPT_RTSP_TRANSPORT || \
(option) == CURLOPT_SASL_AUTHZID || \
(option) == CURLOPT_SERVICE_NAME || \
(option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256 || \
(option) == CURLOPT_SSH_KNOWNHOSTS || \
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
(option) == CURLOPT_SSLCERT || \
(option) == CURLOPT_SSLCERTTYPE || \
(option) == CURLOPT_SSLENGINE || \
(option) == CURLOPT_SSLKEY || \
(option) == CURLOPT_SSLKEYTYPE || \
(option) == CURLOPT_SSL_CIPHER_LIST || \
(option) == CURLOPT_TLS13_CIPHERS || \
(option) == CURLOPT_TLSAUTH_PASSWORD || \
(option) == CURLOPT_TLSAUTH_TYPE || \
(option) == CURLOPT_TLSAUTH_USERNAME || \
(option) == CURLOPT_UNIX_SOCKET_PATH || \
(option) == CURLOPT_URL || \
(option) == CURLOPT_USERAGENT || \
(option) == CURLOPT_USERNAME || \
(option) == CURLOPT_AWS_SIGV4 || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_XOAUTH2_BEARER || \
(option) == CURLOPT_SSL_EC_CURVES || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
#define curlcheck_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \
(option) == CURLOPT_WRITEFUNCTION)
/* evaluates to true if option takes a curl_conv_callback argument */
#define curlcheck_conv_cb_option(option) \
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
/* evaluates to true if option takes a data argument to pass to a callback */
#define curlcheck_cb_data_option(option) \
((option) == CURLOPT_CHUNK_DATA || \
(option) == CURLOPT_CLOSESOCKETDATA || \
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_FNMATCH_DATA || \
(option) == CURLOPT_HEADERDATA || \
(option) == CURLOPT_HSTSREADDATA || \
(option) == CURLOPT_HSTSWRITEDATA || \
(option) == CURLOPT_INTERLEAVEDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
(option) == CURLOPT_PREREQDATA || \
(option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_READDATA || \
(option) == CURLOPT_SEEKDATA || \
(option) == CURLOPT_SOCKOPTDATA || \
(option) == CURLOPT_SSH_KEYDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_RESOLVER_START_DATA || \
(option) == CURLOPT_TRAILERDATA || \
(option) == CURLOPT_SSH_HOSTKEYDATA || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
#define curlcheck_postfields_option(option) \
((option) == CURLOPT_POSTFIELDS || \
(option) == CURLOPT_COPYPOSTFIELDS || \
0)
/* evaluates to true if option takes a struct curl_slist * argument */
#define curlcheck_slist_option(option) \
((option) == CURLOPT_HTTP200ALIASES || \
(option) == CURLOPT_HTTPHEADER || \
(option) == CURLOPT_MAIL_RCPT || \
(option) == CURLOPT_POSTQUOTE || \
(option) == CURLOPT_PREQUOTE || \
(option) == CURLOPT_PROXYHEADER || \
(option) == CURLOPT_QUOTE || \
(option) == CURLOPT_RESOLVE || \
(option) == CURLOPT_TELNETOPTIONS || \
(option) == CURLOPT_CONNECT_TO || \
0)
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
#define curlcheck_string_info(info) \
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG && \
(info) != CURLINFO_PRIVATE)
/* evaluates to true if info expects a pointer to long argument */
#define curlcheck_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
#define curlcheck_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
#define curlcheck_slist_info(info) \
(((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
#define curlcheck_tlssessioninfo_info(info) \
(((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
/* true if info expects a pointer to struct curl_certinfo * argument */
#define curlcheck_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
/* true if info expects a pointer to struct curl_socket_t argument */
#define curlcheck_socket_info(info) \
(CURLINFO_SOCKET < (info) && (info) < CURLINFO_OFF_T)
/* true if info expects a pointer to curl_off_t argument */
#define curlcheck_off_t_info(info) \
(CURLINFO_OFF_T < (info))
/* typecheck helpers -- check whether given expression has requested type */
/* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros,
* otherwise define a new macro. Search for __builtin_types_compatible_p
* in the GCC manual.
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
* the actual expression passed to the curl_easy_setopt macro. This
* means that you can only apply the sizeof and __typeof__ operators, no
* == or whatsoever.
*/
/* XXX: should evaluate to true if expr is a pointer */
#define curlcheck_any_ptr(expr) \
(sizeof(expr) == sizeof(void *))
/* evaluates to true if expr is NULL */
/* XXX: must not evaluate expr, so this check is not accurate */
#define curlcheck_NULL(expr) \
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
/* evaluates to true if expr is type*, const type* or NULL */
#define curlcheck_ptr(expr, type) \
(curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), type *) || \
__builtin_types_compatible_p(__typeof__(expr), const type *))
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
#define curlcheck_arr(expr, type) \
(curlcheck_ptr((expr), type) || \
__builtin_types_compatible_p(__typeof__(expr), type []))
/* evaluates to true if expr is a string */
#define curlcheck_string(expr) \
(curlcheck_arr((expr), char) || \
curlcheck_arr((expr), signed char) || \
curlcheck_arr((expr), unsigned char))
/* evaluates to true if expr is a long (no matter the signedness)
* XXX: for now, int is also accepted (and therefore short and char, which
* are promoted to int when passed to a variadic function) */
#define curlcheck_long(expr) \
(__builtin_types_compatible_p(__typeof__(expr), long) || \
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
__builtin_types_compatible_p(__typeof__(expr), int) || \
__builtin_types_compatible_p(__typeof__(expr), signed int) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
__builtin_types_compatible_p(__typeof__(expr), short) || \
__builtin_types_compatible_p(__typeof__(expr), signed short) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
__builtin_types_compatible_p(__typeof__(expr), char) || \
__builtin_types_compatible_p(__typeof__(expr), signed char) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
/* evaluates to true if expr is of type curl_off_t */
#define curlcheck_off_t(expr) \
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
/* XXX: also check size of an char[] array? */
#define curlcheck_error_buffer(expr) \
(curlcheck_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), char *) || \
__builtin_types_compatible_p(__typeof__(expr), char[]))
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
#if 0
#define curlcheck_cb_data(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_ptr((expr), FILE))
#else /* be less strict */
#define curlcheck_cb_data(expr) \
curlcheck_any_ptr(expr)
#endif
/* evaluates to true if expr is of type FILE* */
#define curlcheck_FILE(expr) \
(curlcheck_NULL(expr) || \
(__builtin_types_compatible_p(__typeof__(expr), FILE *)))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define curlcheck_postfields(expr) \
(curlcheck_ptr((expr), void) || \
curlcheck_arr((expr), char) || \
curlcheck_arr((expr), unsigned char))
/* helper: __builtin_types_compatible_p distinguishes between functions and
* function pointers, hide it */
#define curlcheck_cb_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func) *, type))
/* evaluates to true if expr is of type curl_resolver_start_callback */
#define curlcheck_resolver_start_callback(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_resolver_start_callback))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define curlcheck_read_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fread) *) || \
curlcheck_cb_compatible((expr), curl_read_callback) || \
curlcheck_cb_compatible((expr), _curl_read_callback1) || \
curlcheck_cb_compatible((expr), _curl_read_callback2) || \
curlcheck_cb_compatible((expr), _curl_read_callback3) || \
curlcheck_cb_compatible((expr), _curl_read_callback4) || \
curlcheck_cb_compatible((expr), _curl_read_callback5) || \
curlcheck_cb_compatible((expr), _curl_read_callback6))
typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_write_callback or "similar" */
#define curlcheck_write_cb(expr) \
(curlcheck_read_cb(expr) || \
curlcheck_cb_compatible((expr), __typeof__(fwrite) *) || \
curlcheck_cb_compatible((expr), curl_write_callback) || \
curlcheck_cb_compatible((expr), _curl_write_callback1) || \
curlcheck_cb_compatible((expr), _curl_write_callback2) || \
curlcheck_cb_compatible((expr), _curl_write_callback3) || \
curlcheck_cb_compatible((expr), _curl_write_callback4) || \
curlcheck_cb_compatible((expr), _curl_write_callback5) || \
curlcheck_cb_compatible((expr), _curl_write_callback6))
typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
const void *);
typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
const void *);
typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define curlcheck_ioctl_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ioctl_callback) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback1) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback2) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback3) || \
curlcheck_cb_compatible((expr), _curl_ioctl_callback4))
typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define curlcheck_sockopt_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_sockopt_callback) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback1) || \
curlcheck_cb_compatible((expr), _curl_sockopt_callback2))
typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or
"similar" */
#define curlcheck_opensocket_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_opensocket_callback) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback1) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback2) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback3) || \
curlcheck_cb_compatible((expr), _curl_opensocket_callback4))
typedef curl_socket_t (*_curl_opensocket_callback1)
(void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback2)
(void *, curlsocktype, const struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback3)
(const void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (*_curl_opensocket_callback4)
(const void *, curlsocktype, const struct curl_sockaddr *);
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
#define curlcheck_progress_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_progress_callback) || \
curlcheck_cb_compatible((expr), _curl_progress_callback1) || \
curlcheck_cb_compatible((expr), _curl_progress_callback2))
typedef int (*_curl_progress_callback1)(void *,
double, double, double, double);
typedef int (*_curl_progress_callback2)(const void *,
double, double, double, double);
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
#define curlcheck_debug_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_debug_callback) || \
curlcheck_cb_compatible((expr), _curl_debug_callback1) || \
curlcheck_cb_compatible((expr), _curl_debug_callback2) || \
curlcheck_cb_compatible((expr), _curl_debug_callback3) || \
curlcheck_cb_compatible((expr), _curl_debug_callback4) || \
curlcheck_cb_compatible((expr), _curl_debug_callback5) || \
curlcheck_cb_compatible((expr), _curl_debug_callback6) || \
curlcheck_cb_compatible((expr), _curl_debug_callback7) || \
curlcheck_cb_compatible((expr), _curl_debug_callback8))
typedef int (*_curl_debug_callback1) (CURL *,
curl_infotype, char *, size_t, void *);
typedef int (*_curl_debug_callback2) (CURL *,
curl_infotype, char *, size_t, const void *);
typedef int (*_curl_debug_callback3) (CURL *,
curl_infotype, const char *, size_t, void *);
typedef int (*_curl_debug_callback4) (CURL *,
curl_infotype, const char *, size_t, const void *);
typedef int (*_curl_debug_callback5) (CURL *,
curl_infotype, unsigned char *, size_t, void *);
typedef int (*_curl_debug_callback6) (CURL *,
curl_infotype, unsigned char *, size_t, const void *);
typedef int (*_curl_debug_callback7) (CURL *,
curl_infotype, const unsigned char *, size_t, void *);
typedef int (*_curl_debug_callback8) (CURL *,
curl_infotype, const unsigned char *, size_t, const void *);
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
/* this is getting even messier... */
#define curlcheck_ssl_ctx_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_ssl_ctx_callback) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback1) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback2) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback3) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback4) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback5) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback6) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback7) || \
curlcheck_cb_compatible((expr), _curl_ssl_ctx_callback8))
typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
const void *);
#ifdef HEADER_SSL_H
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
* this will of course break if we are included before OpenSSL headers...
*/
typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX *, const void *);
typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX *, void *);
typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX *,
const void *);
#else
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
#endif
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
#define curlcheck_conv_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_conv_callback) || \
curlcheck_cb_compatible((expr), _curl_conv_callback1) || \
curlcheck_cb_compatible((expr), _curl_conv_callback2) || \
curlcheck_cb_compatible((expr), _curl_conv_callback3) || \
curlcheck_cb_compatible((expr), _curl_conv_callback4))
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
#define curlcheck_seek_cb(expr) \
(curlcheck_NULL(expr) || \
curlcheck_cb_compatible((expr), curl_seek_callback) || \
curlcheck_cb_compatible((expr), _curl_seek_callback1) || \
curlcheck_cb_compatible((expr), _curl_seek_callback2))
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
#endif /* CURLINC_TYPECHECK_GCC_H */

View File

@@ -0,0 +1,155 @@
#ifndef CURLINC_URLAPI_H
#define CURLINC_URLAPI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
/* the error codes for the URL API */
typedef enum {
CURLUE_OK,
CURLUE_BAD_HANDLE, /* 1 */
CURLUE_BAD_PARTPOINTER, /* 2 */
CURLUE_MALFORMED_INPUT, /* 3 */
CURLUE_BAD_PORT_NUMBER, /* 4 */
CURLUE_UNSUPPORTED_SCHEME, /* 5 */
CURLUE_URLDECODE, /* 6 */
CURLUE_OUT_OF_MEMORY, /* 7 */
CURLUE_USER_NOT_ALLOWED, /* 8 */
CURLUE_UNKNOWN_PART, /* 9 */
CURLUE_NO_SCHEME, /* 10 */
CURLUE_NO_USER, /* 11 */
CURLUE_NO_PASSWORD, /* 12 */
CURLUE_NO_OPTIONS, /* 13 */
CURLUE_NO_HOST, /* 14 */
CURLUE_NO_PORT, /* 15 */
CURLUE_NO_QUERY, /* 16 */
CURLUE_NO_FRAGMENT, /* 17 */
CURLUE_NO_ZONEID, /* 18 */
CURLUE_BAD_FILE_URL, /* 19 */
CURLUE_BAD_FRAGMENT, /* 20 */
CURLUE_BAD_HOSTNAME, /* 21 */
CURLUE_BAD_IPV6, /* 22 */
CURLUE_BAD_LOGIN, /* 23 */
CURLUE_BAD_PASSWORD, /* 24 */
CURLUE_BAD_PATH, /* 25 */
CURLUE_BAD_QUERY, /* 26 */
CURLUE_BAD_SCHEME, /* 27 */
CURLUE_BAD_SLASHES, /* 28 */
CURLUE_BAD_USER, /* 29 */
CURLUE_LACKS_IDN, /* 30 */
CURLUE_TOO_LARGE, /* 31 */
CURLUE_LAST
} CURLUcode;
typedef enum {
CURLUPART_URL,
CURLUPART_SCHEME,
CURLUPART_USER,
CURLUPART_PASSWORD,
CURLUPART_OPTIONS,
CURLUPART_HOST,
CURLUPART_PORT,
CURLUPART_PATH,
CURLUPART_QUERY,
CURLUPART_FRAGMENT,
CURLUPART_ZONEID /* added in 7.65.0 */
} CURLUPart;
#define CURLU_DEFAULT_PORT (1<<0) /* return default port number */
#define CURLU_NO_DEFAULT_PORT (1<<1) /* act as if no port number was set,
if the port number matches the
default for the scheme */
#define CURLU_DEFAULT_SCHEME (1<<2) /* return default scheme if
missing */
#define CURLU_NON_SUPPORT_SCHEME (1<<3) /* allow non-supported scheme */
#define CURLU_PATH_AS_IS (1<<4) /* leave dot sequences */
#define CURLU_DISALLOW_USER (1<<5) /* no user+password allowed */
#define CURLU_URLDECODE (1<<6) /* URL decode on get */
#define CURLU_URLENCODE (1<<7) /* URL encode on set */
#define CURLU_APPENDQUERY (1<<8) /* append a form style part */
#define CURLU_GUESS_SCHEME (1<<9) /* legacy curl-style guessing */
#define CURLU_NO_AUTHORITY (1<<10) /* Allow empty authority when the
scheme is unknown. */
#define CURLU_ALLOW_SPACE (1<<11) /* Allow spaces in the URL */
#define CURLU_PUNYCODE (1<<12) /* get the hostname in punycode */
#define CURLU_PUNY2IDN (1<<13) /* punycode => IDN conversion */
#define CURLU_GET_EMPTY (1<<14) /* allow empty queries and fragments
when extracting the URL or the
components */
#define CURLU_NO_GUESS_SCHEME (1<<15) /* for get, do not accept a guess */
typedef struct Curl_URL CURLU;
/*
* curl_url() creates a new CURLU handle and returns a pointer to it.
* Must be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url(void);
/*
* curl_url_cleanup() frees the CURLU handle and related resources used for
* the URL parsing. It will not free strings previously returned with the URL
* API.
*/
CURL_EXTERN void curl_url_cleanup(CURLU *handle);
/*
* curl_url_dup() duplicates a CURLU handle and returns a new copy. The new
* handle must also be freed with curl_url_cleanup().
*/
CURL_EXTERN CURLU *curl_url_dup(const CURLU *in);
/*
* curl_url_get() extracts a specific part of the URL from a CURLU
* handle. Returns error code. The returned pointer MUST be freed with
* curl_free() afterwards.
*/
CURL_EXTERN CURLUcode curl_url_get(const CURLU *handle, CURLUPart what,
char **part, unsigned int flags);
/*
* curl_url_set() sets a specific part of the URL in a CURLU handle. Returns
* error code. The passed in string will be copied. Passing a NULL instead of
* a part string, clears that part.
*/
CURL_EXTERN CURLUcode curl_url_set(CURLU *handle, CURLUPart what,
const char *part, unsigned int flags);
/*
* curl_url_strerror() turns a CURLUcode value into the equivalent human
* readable error string. This is useful for printing meaningful error
* messages.
*/
CURL_EXTERN const char *curl_url_strerror(CURLUcode);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif /* CURLINC_URLAPI_H */

View File

@@ -0,0 +1,84 @@
#ifndef CURLINC_WEBSOCKETS_H
#define CURLINC_WEBSOCKETS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
struct curl_ws_frame {
int age; /* zero */
int flags; /* See the CURLWS_* defines */
curl_off_t offset; /* the offset of this data into the frame */
curl_off_t bytesleft; /* number of pending bytes left of the payload */
size_t len; /* size of the current data chunk */
};
/* flag bits */
#define CURLWS_TEXT (1<<0)
#define CURLWS_BINARY (1<<1)
#define CURLWS_CONT (1<<2)
#define CURLWS_CLOSE (1<<3)
#define CURLWS_PING (1<<4)
#define CURLWS_OFFSET (1<<5)
/*
* NAME curl_ws_recv()
*
* DESCRIPTION
*
* Receives data from the websocket connection. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen,
size_t *recv,
const struct curl_ws_frame **metap);
/* flags for curl_ws_send() */
#define CURLWS_PONG (1<<6)
/*
* NAME curl_ws_send()
*
* DESCRIPTION
*
* Sends data over the websocket connection. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_ws_send(CURL *curl, const void *buffer,
size_t buflen, size_t *sent,
curl_off_t fragsize,
unsigned int flags);
/* bits for the CURLOPT_WS_OPTIONS bitmask: */
#define CURLWS_RAW_MODE (1<<0)
CURL_EXTERN const struct curl_ws_frame *curl_ws_meta(CURL *curl);
#ifdef __cplusplus
}
#endif
#endif /* CURLINC_WEBSOCKETS_H */

BIN
libcurl/lib/libcurl.a Normal file

Binary file not shown.

41
libcurl/lib/libcurl.la Normal file
View File

@@ -0,0 +1,41 @@
# libcurl.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.7 Debian-2.4.7-7~deb12u1
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname=''
# Names of this library.
library_names=''
# The name of the static archive.
old_library='libcurl.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' -pthread'
# Libraries that this one depends upon.
dependency_libs=' -lssh2 -lgpg-error -lssl -lcrypto -ldl -lzstd -lz'
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libcurl.
current=12
age=8
revision=0
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/opt/libcurl/lib'

View File

@@ -0,0 +1,41 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
prefix=/opt/libcurl
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
supported_protocols="DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS IPFS IPNS MQTT POP3 POP3S RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP WS WSS"
supported_features="alt-svc AsynchDNS HSTS HTTPS-proxy IPv6 Largefile libz NTLM SSL threadsafe TLS-SRP UnixSockets zstd"
Name: libcurl
URL: https://curl.se/
Description: Library to transfer files with HTTP, FTP, etc.
Version: 8.11.1
Requires: zlib,libzstd,openssl,libssh2
Requires.private: zlib,libzstd,openssl,libssh2
Libs: -L${libdir} -lcurl -lssh2 -lssh2 -lgpg-error -lssl -ldl -lcrypto -ldl -lz -lssl -lcrypto -lssl -ldl -pthread -lcrypto -ldl -pthread -lzstd -lz
Libs.private: -lssh2 -lssh2 -lgpg-error -lssl -ldl -lcrypto -ldl -lz -lssl -lcrypto -lssl -ldl -pthread -lcrypto -ldl -pthread -lzstd -lz
Cflags: -I${includedir} -DCURL_STATICLIB
Cflags.private: -DCURL_STATICLIB

View File

@@ -0,0 +1,274 @@
#***************************************************************************
# _ _ ____ _
# Project ___| | | | _ \| |
# / __| | | | |_) | |
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) David Shaw <dshaw@jabberwocky.com>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at https://curl.se/docs/copyright.html.
#
# You may opt to use, copy, modify, merge, publish, distribute and/or sell
# copies of the Software, and permit persons to whom the Software is
# furnished to do so, under the terms of the COPYING file.
#
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# SPDX-License-Identifier: curl
#
###########################################################################
# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
# [ACTION-IF-YES], [ACTION-IF-NO])
# ----------------------------------------------------------
# David Shaw <dshaw@jabberwocky.com> May-09-2006
#
# Checks for libcurl. DEFAULT-ACTION is the string yes or no to
# specify whether to default to --with-libcurl or --without-libcurl.
# If not supplied, DEFAULT-ACTION is yes. MINIMUM-VERSION is the
# minimum version of libcurl to accept. Pass the version as a regular
# version number like 7.10.1. If not supplied, any version is
# accepted. ACTION-IF-YES is a list of shell commands to run if
# libcurl was successfully found and passed the various tests.
# ACTION-IF-NO is a list of shell commands that are run otherwise.
# Note that using --without-libcurl does run ACTION-IF-NO.
#
# This macro #defines HAVE_LIBCURL if a working libcurl setup is
# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary
# values. Other useful defines are LIBCURL_FEATURE_xxx where xxx are
# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
# where yyy are the various protocols supported by libcurl. Both xxx
# and yyy are capitalized. See the list of AH_TEMPLATEs at the top of
# the macro for the complete list of possible defines. Shell
# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
# defined to 'yes' for those features and protocols that were found.
# Note that xxx and yyy keep the same capitalization as in the
# curl-config list (e.g. it's "HTTP" and not "http").
#
# Users may override the detected values by doing something like:
# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
#
# For the sake of sanity, this macro assumes that any libcurl that is found is
# after version 7.7.2, the first version that included the curl-config script.
# Note that it is important for people packaging binary versions of libcurl to
# include this script! Without curl-config, we can only guess what protocols
# are available, or use curl_version_info to figure it out at runtime.
AC_DEFUN([LIBCURL_CHECK_CONFIG],
[
AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
AC_ARG_WITH(libcurl,
AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]),
[_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
if test "$_libcurl_with" != "no" ; then
AC_PROG_AWK
_libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
_libcurl_try_link=yes
if test -d "$_libcurl_with" ; then
LIBCURL_CPPFLAGS="-I$withval/include"
_libcurl_ldflags="-L$withval/lib"
AC_PATH_PROG([_libcurl_config],[curl-config],[],
["$withval/bin"])
else
AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH])
fi
if test x$_libcurl_config != "x" ; then
AC_CACHE_CHECK([for the version of libcurl],
[libcurl_cv_lib_curl_version],
[libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
_libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
_libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
if test $_libcurl_wanted -gt 0 ; then
AC_CACHE_CHECK([for libcurl >= version $2],
[libcurl_cv_lib_version_ok],
[
if test $_libcurl_version -ge $_libcurl_wanted ; then
libcurl_cv_lib_version_ok=yes
else
libcurl_cv_lib_version_ok=no
fi
])
fi
if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then
if test x"$LIBCURL_CPPFLAGS" = "x" ; then
LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
fi
if test x"$LIBCURL" = "x" ; then
LIBCURL=`$_libcurl_config --libs`
# This is so silly, but Apple actually has a bug in their
# curl-config script. Fixed in Tiger, but there are still
# lots of Panther installs around.
case "${host}" in
powerpc-apple-darwin7*)
LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'`
;;
esac
fi
# All curl-config scripts support --feature
_libcurl_features=`$_libcurl_config --feature`
# Is it modern enough to have --protocols? (7.12.4)
if test $_libcurl_version -ge 461828 ; then
_libcurl_protocols=`$_libcurl_config --protocols`
fi
else
_libcurl_try_link=no
fi
unset _libcurl_wanted
fi
if test $_libcurl_try_link = yes ; then
# we did not find curl-config, so let's see if the user-supplied
# link line (or failing that, "-lcurl") is enough.
LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"}
AC_CACHE_CHECK([whether libcurl is usable],
[libcurl_cv_lib_curl_usable],
[
_libcurl_save_cppflags=$CPPFLAGS
CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
_libcurl_save_libs=$LIBS
LIBS="$LIBCURL $LIBS"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[
/* Try to use a few common options to force a failure if we are
missing symbols or cannot link. */
int x;
curl_easy_setopt(NULL,CURLOPT_URL,NULL);
x=CURL_ERROR_SIZE;
x=CURLOPT_WRITEFUNCTION;
x=CURLOPT_WRITEDATA;
x=CURLOPT_ERRORBUFFER;
x=CURLOPT_STDERR;
x=CURLOPT_VERBOSE;
if (x) {;}
]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
CPPFLAGS=$_libcurl_save_cppflags
LIBS=$_libcurl_save_libs
unset _libcurl_save_cppflags
unset _libcurl_save_libs
])
if test $libcurl_cv_lib_curl_usable = yes ; then
# Does curl_free() exist in this version of libcurl?
# If not, fake it with free()
_libcurl_save_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
_libcurl_save_libs=$LIBS
LIBS="$LIBS $LIBCURL"
AC_CHECK_DECL([curl_free],[],
[AC_DEFINE([curl_free],[free],
[Define curl_free() as free() if our version of curl lacks curl_free.])],
[[#include <curl/curl.h>]])
CPPFLAGS=$_libcurl_save_cppflags
LIBS=$_libcurl_save_libs
unset _libcurl_save_cppflags
unset _libcurl_save_libs
AC_DEFINE(HAVE_LIBCURL,1,
[Define to 1 if you have a functional curl library.])
AC_SUBST(LIBCURL_CPPFLAGS)
AC_SUBST(LIBCURL)
for _libcurl_feature in $_libcurl_features ; do
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
done
if test "x$_libcurl_protocols" = "x" ; then
# We do not have --protocols, so just assume that all
# protocols are available
_libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
if test x$libcurl_feature_SSL = xyes ; then
_libcurl_protocols="$_libcurl_protocols HTTPS"
# FTPS was not standards-compliant until version
# 7.11.0 (0x070b00 == 461568)
if test $_libcurl_version -ge 461568; then
_libcurl_protocols="$_libcurl_protocols FTPS"
fi
fi
# RTSP, IMAP, POP3 and SMTP were added in
# 7.20.0 (0x071400 == 463872)
if test $_libcurl_version -ge 463872; then
_libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
fi
fi
for _libcurl_protocol in $_libcurl_protocols ; do
AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
done
else
unset LIBCURL
unset LIBCURL_CPPFLAGS
fi
fi
unset _libcurl_try_link
unset _libcurl_version_parse
unset _libcurl_config
unset _libcurl_feature
unset _libcurl_features
unset _libcurl_protocol
unset _libcurl_protocols
unset _libcurl_version
unset _libcurl_ldflags
fi
if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then
# This is the IF-NO path
ifelse([$4],,:,[$4])
else
# This is the IF-YES path
ifelse([$3],,:,[$3])
fi
unset _libcurl_with
])

View File

@@ -86,14 +86,12 @@ int create_ipset(char *set_name)
ipset_fini(ipset); ipset_fini(ipset);
return -1; return -1;
} }
// 设置自定义错误和输出处理函数 // 设置自定义错误和输出处理函数
if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) { if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) {
fprintf(stderr, "设置自定义打印函数失败。\n"); fprintf(stderr, "设置自定义打印函数失败。\n");
ipset_fini(ipset); ipset_fini(ipset);
return -1; return -1;
} }
// 创建集合 // 创建集合
char *args[] = { "ipset", "create", set_name, "hash:ip", NULL }; char *args[] = { "ipset", "create", set_name, "hash:ip", NULL };
if (ipset_parse_argv(ipset, 4, args) != 0) { if (ipset_parse_argv(ipset, 4, args) != 0) {
@@ -101,7 +99,6 @@ int create_ipset(char *set_name)
return -1; return -1;
} }
ipset_fini(ipset); ipset_fini(ipset);
return 0; return 0;
@@ -135,14 +132,12 @@ int add_ip_to_ipset(char *set_name, char *ip)
ipset_fini(ipset); ipset_fini(ipset);
return -1; // 返回 -1但不退出 return -1; // 返回 -1但不退出
} }
// 设置自定义错误和输出处理函数 // 设置自定义错误和输出处理函数
if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) { if (ipset_custom_printf(ipset, custom_error_handler, NULL, custom_output_handler_, NULL) != 0) {
fprintf(stderr, "设置自定义打印函数失败。\n"); fprintf(stderr, "设置自定义打印函数失败。\n");
ipset_fini(ipset); ipset_fini(ipset);
return -1; return -1;
} }
// 将ip添加到集合 // 将ip添加到集合
char *args[] = { "ipset", "add", set_name, ip, NULL }; char *args[] = { "ipset", "add", set_name, ip, NULL };
if (ipset_parse_argv(ipset, 4, args) != 0) { if (ipset_parse_argv(ipset, 4, args) != 0) {
@@ -150,7 +145,53 @@ int add_ip_to_ipset(char *set_name, char *ip)
return -1; return -1;
} }
ipset_fini(ipset);
return 0; // 始终返回 0表示执行成功
}
// 向指定的 ipset 删除 IP
int del_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", "del", set_name, ip, NULL };
if (ipset_parse_argv(ipset, 4, args) != 0) {
ipset_fini(ipset);
return -1;
}
ipset_session_fini(session);
ipset_fini(ipset); ipset_fini(ipset);
return 0; // 始终返回 0表示执行成功 return 0; // 始终返回 0表示执行成功
@@ -173,7 +214,6 @@ int flush_ipset(char *set_name)
ipset_fini(ipset); ipset_fini(ipset);
return -1; return -1;
} }
// 清空集合 // 清空集合
char *args[] = { "ipset", "flush", set_name, NULL }; char *args[] = { "ipset", "flush", set_name, NULL };
if (ipset_parse_argv(ipset, 3, args) != 0) { if (ipset_parse_argv(ipset, 3, args) != 0) {
@@ -204,19 +244,36 @@ int get_ip_count_in_ipset(char *set_name)
ipset_fini(ipset); ipset_fini(ipset);
return -1; return -1;
} }
// 列出集合 // 列出集合
char *args[] = { "ipset", "list", set_name, NULL }; char *args[] = { "ipset", "list", set_name, NULL };
if (ipset_parse_argv(ipset, 3, args) != 0) { if (ipset_parse_argv(ipset, 3, args) != 0) {
ipset_fini(ipset); ipset_fini(ipset);
return -1; return -1;
} }
// 释放资源 // 释放资源
ipset_fini(ipset); ipset_fini(ipset);
return ip_count; return ip_count;
} }
void add_iptables_rule(const char *rule_name)
{
char iptables_command[256];
// 使用 snprintf 避免溢出
int written = snprintf(iptables_command, sizeof(iptables_command),
"iptables -I INPUT -m set --match-set %s src -j DROP", rule_name);
if (written < 0 || written >= sizeof(iptables_command)) {
fprintf(stderr, "Error: iptables command is too long.\n");
return;
}
// 执行命令并检查返回值
int ret = system(iptables_command);
if (ret != 0) {
fprintf(stderr, "Failed to execute iptables command: %s\n", iptables_command);
}
}
/* /*
int main() int main()
{ {

View File

@@ -5,13 +5,15 @@
#include <libipset/ipset.h> #include <libipset/ipset.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <arpa/inet.h> // 包含 inet_pton 函数 #include <arpa/inet.h> // 包含 inet_pton 函数
#define BUFFER 1024 #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 add_ip_to_ipset(char *set_name, char *ip);
extern int get_ip_count_in_ipset(char *set_name); extern int get_ip_count_in_ipset(char *set_name);
extern void add_iptables_rule(const char *rule_name);
extern int del_ip_to_ipset(char *set_name, char *ip);
#endif #endif

4
whitelist.txt Normal file
View File

@@ -0,0 +1,4 @@
127.0.0.1
13.125.223.189
158.101.117.243
52.221.186.101