diff --git a/.github/actions/build-release/action.yml b/.github/actions/build-release/action.yml index 7cc1beb..2fc6502 100644 --- a/.github/actions/build-release/action.yml +++ b/.github/actions/build-release/action.yml @@ -30,11 +30,6 @@ runs: go-version: ${{ inputs.go-version }} cache: true - - name: 安装 C 编译工具 - shell: bash - run: | - sudo apt-get update -qq - sudo apt-get install -y gcc make mingw-w64 gcc-multilib g++-multilib - name: 下载依赖 shell: bash @@ -66,9 +61,7 @@ runs: if: always() with: name: build-${{ inputs.mode }}-${{ github.run_id }} - path: | - dist/ - dist-lite/ + path: dist/ retention-days: ${{ inputs.retention-days }} - name: 生成报告 @@ -87,7 +80,6 @@ runs: ## 构建产物 - ### fscan (Go 版本) $(if [ -d "dist" ]; then echo "- 文件数: $(find dist -type f 2>/dev/null | wc -l)" echo "- 大小: $(du -sh dist 2>/dev/null | cut -f1)" @@ -95,13 +87,5 @@ runs: echo "- 无产物" fi) - ### fscan-lite (C 版本) - $(if [ -d "dist-lite" ]; then - echo "- 文件数: $(find dist-lite -type f 2>/dev/null | wc -l)" - echo "- 大小: $(du -sh dist-lite 2>/dev/null | cut -f1)" - else - echo "- 无产物" - fi) - [查看产物](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) EOF diff --git a/.github/conf/.goreleaser.yml b/.github/conf/.goreleaser.yml index 9187500..18ebff3 100644 --- a/.github/conf/.goreleaser.yml +++ b/.github/conf/.goreleaser.yml @@ -4,8 +4,6 @@ before: hooks: - go mod tidy - go mod download - - chmod +x .github/scripts/build-lite.sh - - bash .github/scripts/build-lite.sh {{ .Version }} builds: # 标准版 - 全部插件(全架构) @@ -238,8 +236,6 @@ release: | Solaris | x64 | footer: | **完整更新日志**: https://github.com/{{ .Env.GITHUB_OWNER }}/{{ .Env.GITHUB_REPO }}/compare/{{ .PreviousTag }}...{{ .Tag }} - extra_files: - - glob: ./dist-lite/* snapshot: name_template: "{{ incpatch .Version }}-dev-{{ .ShortCommit }}" diff --git a/.github/release-notes/v2.2.0-rc.md b/.github/release-notes/v2.2.0-rc.md index d74c837..269b7ad 100644 --- a/.github/release-notes/v2.2.0-rc.md +++ b/.github/release-notes/v2.2.0-rc.md @@ -103,4 +103,4 @@ | Windows | x64, x32 | | macOS | x64 (Intel), arm64 (Apple Silicon) | | FreeBSD | x64, x32, arm64, armv5/6/7 | -| Solaris | x64 | +| Solaris | X64n | diff --git a/.github/scripts/build-lite.sh b/.github/scripts/build-lite.sh deleted file mode 100644 index e280334..0000000 --- a/.github/scripts/build-lite.sh +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/bash -# 构建 fscan-lite 并准备发布产物 - -set -e - -VERSION="${1:-dev}" -LITE_DIR="fscan-lite" -OUTPUT_DIR="dist-lite" - -echo "==> 构建 fscan-lite (版本: $VERSION)" - -# 清理旧产物 -rm -rf "$OUTPUT_DIR" -mkdir -p "$OUTPUT_DIR" - -# 进入 lite 目录 -cd "$LITE_DIR" - -# 源文件 -SOURCES="src/main.c src/scanner.c src/platform.c" -INCLUDE="-Iinclude" -CFLAGS_BASE="-std=c89 -Wall -O2" - -# 构建 Linux 版本 -echo "==> 构建 Linux 版本..." - -# Linux x64 -echo " - Linux x64" -mkdir -p bin -gcc $CFLAGS_BASE $INCLUDE -o bin/fscan-lite $SOURCES -lpthread -cp bin/fscan-lite "../$OUTPUT_DIR/fscan-lite_${VERSION}_linux_x64" -rm -rf bin - -# Linux x32 -echo " - Linux x32" -mkdir -p bin -gcc $CFLAGS_BASE -m32 $INCLUDE -o bin/fscan-lite $SOURCES -lpthread 2>/dev/null || echo " (跳过: 缺少 32-bit 支持)" -if [ -f bin/fscan-lite ]; then - cp bin/fscan-lite "../$OUTPUT_DIR/fscan-lite_${VERSION}_linux_x32" -fi -rm -rf bin - -# 构建 Windows 版本 -echo "==> 构建 Windows 版本..." - -# Windows x64 -echo " - Windows x64" -mkdir -p bin -x86_64-w64-mingw32-gcc $CFLAGS_BASE $INCLUDE -o bin/fscan-lite.exe $SOURCES -lws2_32 -static -if [ -f bin/fscan-lite.exe ]; then - cp bin/fscan-lite.exe "../$OUTPUT_DIR/fscan-lite_${VERSION}_windows_x64.exe" - echo " ✓ 编译成功" -else - echo " ✗ 编译失败" -fi -rm -rf bin - -# Windows x32 -echo " - Windows x32" -mkdir -p bin -i686-w64-mingw32-gcc $CFLAGS_BASE $INCLUDE -o bin/fscan-lite.exe $SOURCES -lws2_32 -static -if [ -f bin/fscan-lite.exe ]; then - cp bin/fscan-lite.exe "../$OUTPUT_DIR/fscan-lite_${VERSION}_windows_x32.exe" - echo " ✓ 编译成功" -else - echo " ✗ 编译失败" -fi -rm -rf bin - -cd .. - -# 统计产物 -echo "" -echo "==> 构建完成!" -echo "产物列表:" -if [ -d "$OUTPUT_DIR" ]; then - ls -lh "$OUTPUT_DIR" 2>/dev/null || echo " (无产物)" - echo "" - FILECOUNT=$(ls "$OUTPUT_DIR" 2>/dev/null | wc -l) - echo "总计: $FILECOUNT 个文件" -fi diff --git a/fscan-lite/README.md b/fscan-lite/README.md deleted file mode 100644 index 945465a..0000000 --- a/fscan-lite/README.md +++ /dev/null @@ -1,126 +0,0 @@ -# fscan-lite - -极简但极致兼容的TCP内网端口扫描器 - -## 设计理念 - -**兼容性第一,简洁至上** - -- 支持从 Windows 98 到 Windows 11 -- 支持从 Ubuntu 8.04 到最新版本 -- 使用 C89 标准,最大兼容性 -- 静态编译,零依赖运行 -- 单个可执行文件 < 1MB - -## 功能特性 - -- ✅ TCP端口连接扫描 -- ✅ 支持端口范围 (1-65535, 80,443) -- ✅ 可配置超时时间 -- ✅ 静态编译,零依赖 -- ✅ 跨平台兼容 - -## 编译 - -### Linux/Unix - -```bash -# 动态编译 -make - -# 静态编译(推荐) -make static - -# 最小化编译 -make small -``` - -### Windows - -```bash -# MinGW 编译 -mingw32-make -f Makefile - -# 或使用MSVC -cl /TC src/*.c /Febin/fscan-lite.exe ws2_32.lib -``` - -## 使用方法 - -```bash -# 基本用法 -./bin/fscan-lite -h 192.168.1.1 -p 22,80,443 - -# 扫描端口范围 -./bin/fscan-lite -h 10.0.0.1 -p 1-1000 - -# 自定义超时 -./bin/fscan-lite -h 192.168.1.100 -p 80,443 -t 2 -``` - -## 参数说明 - -| 参数 | 说明 | 示例 | -|------|------|------| -| -h HOST | 目标主机IP | -h 192.168.1.1 | -| -p PORTS | 端口列表 | -p 80,443,8000-8080 | -| -t TIMEOUT | 超时时间(秒) | -t 3 | -| --help | 显示帮助 | --help | -| --version | 显示版本 | --version | - -## 二进制大小对比 - -| 版本 | 大小 | 说明 | -|------|------|------| -| fscan (Go) | ~30MB | 包含运行时 | -| fscan-lite | ~900KB | 静态编译 | -| fscan-lite (strip) | ~700KB | 去除调试信息 | - -## 兼容性测试 - -### Linux 发行版 -- ✅ Ubuntu 8.04 - 24.04 -- ✅ CentOS 5 - 9 -- ✅ Debian 5 - 12 -- ✅ RHEL 5 - 9 - -### Windows 版本 -- ✅ Windows 98 SE -- ✅ Windows XP -- ✅ Windows 7/8/10/11 -- ✅ Windows Server 2003-2022 - -## 技术实现 - -- **语言**: C89 (最大兼容性) -- **网络**: 原生socket API -- **编译**: GCC/MSVC/Clang -- **链接**: 静态链接,零依赖 -- **大小**: < 1MB 单文件 - -## 性能对比 - -| 指标 | fscan | fscan-lite | -|------|-------|------------| -| 启动时间 | ~50ms | ~5ms | -| 内存占用 | ~20MB | ~2MB | -| 扫描速度 | 1000 ports/s | 1000 ports/s | -| 兼容性 | 现代系统 | 25年跨度 | - -## 构建配置 - -```bash -# 查看构建信息 -make info - -# 所有构建选项 -make help -``` - -## 许可证 - -与 fscan 主项目保持一致 - ---- - -**理念**: 一个工具应该在它设计的任何系统上都能运行,而不需要用户去寻找依赖项。 \ No newline at end of file diff --git a/fscan-lite/include/platform.h b/fscan-lite/include/platform.h deleted file mode 100644 index 5d60f9f..0000000 --- a/fscan-lite/include/platform.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef PLATFORM_H -#define PLATFORM_H - -/* - * platform.h - 极致兼容性的平台抽象层 - * - * 支持范围: - * Windows: 98/ME/NT4/2000/XP/Vista/7/8/10/11 - * Linux: glibc 2.3+ (2003年后的所有发行版) - * 编译器: MSVC 6.0+, GCC 3.0+, Clang 3.0+ - */ - -/* C89兼容性 - 最古老但最可靠的标准 */ -#ifndef __STDC__ -#define __STDC__ 1 -#endif - -/* 平台检测 */ -#ifdef _WIN32 - #define PLATFORM_WINDOWS - #ifdef _WIN64 - #define PLATFORM_WIN64 - #else - #define PLATFORM_WIN32 - #endif -#else - #define PLATFORM_UNIX - #ifdef __linux__ - #define PLATFORM_LINUX - #elif defined(__APPLE__) - #define PLATFORM_MACOS - #endif -#endif - -/* Windows头文件包含 - 兼容Win98 */ -#ifdef PLATFORM_WINDOWS - /* 定义最低Windows版本 - Win98 */ - #ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0410 /* Windows 98 */ - #endif - #ifndef WINVER - #define WINVER 0x0410 - #endif - - /* 必须先包含winsock2.h,否则windows.h会包含旧版winsock.h导致冲突 */ - #include - #include - - /* 老版本Windows兼容性 */ - #ifdef _MSC_VER - #if _MSC_VER < 1300 /* MSVC 6.0 */ - #pragma comment(lib, "wsock32.lib") - #else - #pragma comment(lib, "ws2_32.lib") - #endif - #endif - - /* Windows类型定义 */ - typedef SOCKET socket_t; - typedef int socklen_t; - #define INVALID_SOCKET_VALUE INVALID_SOCKET - #define close_socket closesocket - #define socket_errno WSAGetLastError() - - /* Windows错误码转换 - 使用ifndef避免与errno.h冲突 */ - #ifndef EWOULDBLOCK - #define EWOULDBLOCK WSAEWOULDBLOCK - #endif - #ifndef EINPROGRESS - #define EINPROGRESS WSAEINPROGRESS - #endif - #ifndef ECONNREFUSED - #define ECONNREFUSED WSAECONNREFUSED - #endif - -#else - /* Unix/Linux头文件 */ - #include - #include - #include - #include - #include - #include - #include - #include - - /* Unix类型定义 */ - typedef int socket_t; - #define INVALID_SOCKET_VALUE (-1) - #define close_socket close - #define socket_errno errno - -#endif - -/* 标准C头文件 */ -#include -#include -#include -#include - -/* 线程抽象 - 最简单的实现 */ -#ifdef PLATFORM_WINDOWS - typedef HANDLE thread_t; - typedef DWORD thread_id_t; - typedef unsigned (__stdcall *thread_func_t)(void *); - - #define CREATE_THREAD(func, arg) \ - (HANDLE)_beginthreadex(NULL, 0, (thread_func_t)(func), (arg), 0, NULL) - #define WAIT_THREAD(handle) WaitForSingleObject((handle), INFINITE) - #define CLOSE_THREAD(handle) CloseHandle(handle) - -#else - #include - #include - typedef pthread_t thread_t; - typedef pthread_t thread_id_t; - typedef void* (*thread_func_t)(void *); - - #define CREATE_THREAD(func, arg) ({ \ - pthread_t t; \ - pthread_create(&t, NULL, (thread_func_t)(func), (arg)) == 0 ? t : 0; \ - }) - #define WAIT_THREAD(handle) pthread_join((handle), NULL) - #define CLOSE_THREAD(handle) /* pthread handles are auto-cleaned */ - -#endif - -/* 时间函数抽象 */ -#ifdef PLATFORM_WINDOWS - #define sleep_ms(ms) Sleep(ms) -#else - #define sleep_ms(ms) usleep((ms) * 1000) -#endif - -/* 编译器特定定义 */ -#ifdef _MSC_VER - /* MSVC特定 */ - #define snprintf _snprintf - #define vsnprintf _vsnprintf - #define strcasecmp _stricmp - #define strncasecmp _strnicmp -#endif - -/* 常用常量 */ -#define MAX_HOST_LEN 256 -#define MAX_PORT_COUNT 65536 -#define DEFAULT_TIMEOUT 3 -#define DEFAULT_THREAD_COUNT 100 - -/* 函数声明 */ -int platform_init(void); -void platform_cleanup(void); -int set_socket_timeout(socket_t sock, int timeout_seconds); -int make_socket_nonblocking(socket_t sock); - -#endif /* PLATFORM_H */ \ No newline at end of file diff --git a/fscan-lite/src/main.c b/fscan-lite/src/main.c deleted file mode 100644 index 5b1a268..0000000 --- a/fscan-lite/src/main.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * main.c - fscan-lite 主程序 - * - * 极简的TCP内网端口扫描器 - * 目标:最大兼容性,最小复杂度 - */ - -#include "../include/platform.h" - -/* 函数声明 */ -int tcp_connect_test(const char* host, int port, int timeout); -int scan_host_ports(const char* host, const int* ports, int port_count, int timeout); -int parse_ports(const char* port_str, int* ports, int max_ports); -int parse_hosts(const char* host_str, char hosts[][MAX_HOST_LEN], int max_hosts); - -/* 显示版本信息 */ -void show_version(void) { - printf("fscan-lite v1.0 - Lightweight TCP Port Scanner\n"); - printf("Built for maximum compatibility (Windows 98 - Windows 11, Linux glibc 2.3+)\n"); - printf("Copyright (c) 2024\n"); -} - -/* 显示使用帮助 */ -void show_usage(const char* program_name) { - printf("Usage: %s [OPTIONS]\n", program_name); - printf("\n"); - printf("Options:\n"); - printf(" -h HOST Target host (IP address)\n"); - printf(" -p PORTS Ports to scan (e.g. 80,443 or 1-1000)\n"); - printf(" -t TIMEOUT Connection timeout in seconds (default: 3)\n"); - printf(" --help Show this help message\n"); - printf(" --version Show version information\n"); - printf("\n"); - printf("Examples:\n"); - printf(" %s -h 192.168.1.1 -p 22,80,443\n", program_name); - printf(" %s -h 10.0.0.1 -p 1-1000 -t 2\n", program_name); - printf("\n"); -} - -/* 主函数 */ -int main(int argc, char* argv[]) { - char* target_host = NULL; - char* port_string = NULL; - int timeout = DEFAULT_TIMEOUT; - int ports[1000]; /* 支持最多1000个端口 */ - int port_count = 0; - int i; - int result; - - /* 参数解析 */ - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-h") == 0 && i + 1 < argc) { - target_host = argv[++i]; - } - else if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) { - port_string = argv[++i]; - } - else if (strcmp(argv[i], "-t") == 0 && i + 1 < argc) { - timeout = atoi(argv[++i]); - if (timeout <= 0) timeout = DEFAULT_TIMEOUT; - } - else if (strcmp(argv[i], "--help") == 0) { - show_usage(argv[0]); - return 0; - } - else if (strcmp(argv[i], "--version") == 0) { - show_version(); - return 0; - } - else { - printf("Unknown option: %s\n", argv[i]); - show_usage(argv[0]); - return 1; - } - } - - /* 验证必需参数 */ - if (!target_host) { - printf("Error: Target host (-h) is required\n"); - show_usage(argv[0]); - return 1; - } - - if (!port_string) { - printf("Error: Ports (-p) are required\n"); - show_usage(argv[0]); - return 1; - } - - /* 初始化平台 */ - if (platform_init() != 0) { - printf("Error: Failed to initialize platform\n"); - return 1; - } - - /* 解析端口 */ - port_count = parse_ports(port_string, ports, sizeof(ports) / sizeof(ports[0])); - if (port_count == 0) { - printf("Error: No valid ports specified\n"); - platform_cleanup(); - return 1; - } - - printf("fscan-lite - Starting scan\n"); - printf("Target: %s\n", target_host); - printf("Ports: %d ports to scan\n", port_count); - printf("Timeout: %d seconds\n", timeout); - printf("=================================\n"); - - /* 执行扫描 */ - result = scan_host_ports(target_host, ports, port_count, timeout); - - printf("=================================\n"); - printf("Scan completed: %d open ports found\n", result); - - /* 清理资源 */ - platform_cleanup(); - - return 0; -} \ No newline at end of file diff --git a/fscan-lite/src/platform.c b/fscan-lite/src/platform.c deleted file mode 100644 index 8d280f2..0000000 --- a/fscan-lite/src/platform.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * platform.c - 平台抽象层实现 - * - * 实现最基础但最可靠的平台相关功能 - */ - -#include "../include/platform.h" - -/* 全局初始化标志 */ -static int platform_initialized = 0; - -/* - * 平台初始化 - * Windows: 初始化Winsock - * Unix: 无需特殊初始化 - */ -int platform_init(void) { - if (platform_initialized) { - return 0; - } - -#ifdef PLATFORM_WINDOWS - WSADATA wsaData; - int result; - - /* 初始化Winsock - 请求版本2.0,兼容Win98 */ - result = WSAStartup(MAKEWORD(2, 0), &wsaData); - if (result != 0) { - /* 如果2.0失败,尝试1.1(Win95/NT兼容) */ - result = WSAStartup(MAKEWORD(1, 1), &wsaData); - if (result != 0) { - return -1; - } - } -#endif - - platform_initialized = 1; - return 0; -} - -/* - * 平台清理 - */ -void platform_cleanup(void) { - if (!platform_initialized) { - return; - } - -#ifdef PLATFORM_WINDOWS - WSACleanup(); -#endif - - platform_initialized = 0; -} - -/* - * 设置socket超时 - * 兼容所有平台的最可靠方法 - */ -int set_socket_timeout(socket_t sock, int timeout_seconds) { -#ifdef PLATFORM_WINDOWS - DWORD timeout_ms = timeout_seconds * 1000; - - if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, - (char*)&timeout_ms, sizeof(timeout_ms)) != 0) { - return -1; - } - - if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, - (char*)&timeout_ms, sizeof(timeout_ms)) != 0) { - return -1; - } -#else - struct timeval tv; - tv.tv_sec = timeout_seconds; - tv.tv_usec = 0; - - if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, - (void*)&tv, sizeof(tv)) != 0) { - return -1; - } - - if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, - (void*)&tv, sizeof(tv)) != 0) { - return -1; - } -#endif - - return 0; -} - -/* - * 设置socket为非阻塞模式 - * 跨平台兼容实现 - */ -int make_socket_nonblocking(socket_t sock) { -#ifdef PLATFORM_WINDOWS - u_long mode = 1; - return ioctlsocket(sock, FIONBIO, &mode); -#else - int flags; - - flags = fcntl(sock, F_GETFL, 0); - if (flags == -1) { - return -1; - } - - flags |= O_NONBLOCK; - return fcntl(sock, F_SETFL, flags); -#endif -} \ No newline at end of file diff --git a/fscan-lite/src/scanner.c b/fscan-lite/src/scanner.c deleted file mode 100644 index 87f8cec..0000000 --- a/fscan-lite/src/scanner.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * scanner.c - 核心TCP端口扫描实现 - * - * 极简但可靠的端口扫描逻辑,专注于内网环境 - */ - -#include "../include/platform.h" - -/* - * 基础TCP连接测试 - * 返回: 1=端口开放, 0=端口关闭, -1=错误 - */ -int tcp_connect_test(const char* host, int port, int timeout) { - socket_t sock; - struct sockaddr_in addr; - int result; - - /* 参数验证 */ - if (!host || port <= 0 || port > 65535) { - return -1; - } - - /* 创建socket */ - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == INVALID_SOCKET_VALUE) { - return -1; - } - - /* 设置超时 */ - if (set_socket_timeout(sock, timeout) != 0) { - close_socket(sock); - return -1; - } - - /* 设置目标地址 */ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons((unsigned short)port); - - /* 转换IP地址 */ - addr.sin_addr.s_addr = inet_addr(host); - if (addr.sin_addr.s_addr == INADDR_NONE) { - /* 如果不是有效IP,当作域名处理 */ - struct hostent* he; - he = gethostbyname(host); - if (!he) { - close_socket(sock); - return -1; - } - memcpy(&addr.sin_addr, he->h_addr_list[0], he->h_length); - } - - /* 执行连接测试 */ - result = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); - - /* 关闭socket */ - close_socket(sock); - - /* 返回结果 */ - return (result == 0) ? 1 : 0; -} - -/* - * 扫描单个主机的多个端口 - */ -int scan_host_ports(const char* host, const int* ports, int port_count, int timeout) { - int i; - int open_count = 0; - - if (!host || !ports || port_count <= 0) { - return 0; - } - - printf("Scanning %s...\n", host); - - for (i = 0; i < port_count; i++) { - int result = tcp_connect_test(host, ports[i], timeout); - - if (result == 1) { - printf("%s:%d open\n", host, ports[i]); - open_count++; - } else if (result == -1) { - /* 静默处理错误,继续扫描 */ - } - - /* 简单的进度指示 */ - if ((i + 1) % 100 == 0 || i == port_count - 1) { - printf("Progress: %d/%d ports scanned\n", i + 1, port_count); - } - } - - return open_count; -} - -/* - * 解析端口范围字符串 - * 支持: "80", "80,443", "1-1000", "80,443,8000-8080" - */ -int parse_ports(const char* port_str, int* ports, int max_ports) { - char* str_copy; - char* token; - int count = 0; - - if (!port_str || !ports || max_ports <= 0) { - return 0; - } - - /* 复制字符串以便修改 */ - str_copy = malloc(strlen(port_str) + 1); - if (!str_copy) { - return 0; - } - strcpy(str_copy, port_str); - - /* 使用strtok(兼容性更好) */ - token = strtok(str_copy, ","); - - while (token && count < max_ports) { - char* dash = strchr(token, '-'); - - if (dash) { - /* 处理范围 "start-end" */ - int start, end, i; - *dash = '\0'; - start = atoi(token); - end = atoi(dash + 1); - - if (start > 0 && end > 0 && start <= end && end <= 65535) { - for (i = start; i <= end && count < max_ports; i++) { - ports[count++] = i; - } - } - } else { - /* 处理单个端口 */ - int port = atoi(token); - if (port > 0 && port <= 65535) { - ports[count++] = port; - } - } - - token = strtok(NULL, ","); - } - - free(str_copy); - return count; -} - -/* - * 简单的IP范围解析 - * 目前只支持单个IP,后续可扩展 - */ -int parse_hosts(const char* host_str, char hosts[][MAX_HOST_LEN], int max_hosts) { - if (!host_str || !hosts || max_hosts <= 0) { - return 0; - } - - /* 目前简化实现:只处理单个主机 */ - if (strlen(host_str) < MAX_HOST_LEN) { - strcpy(hosts[0], host_str); - return 1; - } - - return 0; -} \ No newline at end of file