#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <stdarg.h>
#include <arpa/inet.h>
#define LOG_BUFFER_SIZE (10 * 1024)
#define LOG_LINE_SIZE 256
// 定义日志优先级
typedef enum {
LOG_EMERG, // 0: system is unusable
LOG_ALERT, // 1: action must be taken immediately
LOG_CRIT, // 2: critical conditions
LOG_ERR, // 3: error conditions
LOG_WARNING, // 4: warning conditions
LOG_NOTICE, // 5: normal but significant condition
LOG_INFO, // 6: informational
LOG_DEBUG // 7: debug-level messages
} LogLevel;
// 日志条目结构
typedef struct {
LogLevel level;
char module[LOG_LINE_SIZE];
char message[LOG_LINE_SIZE];
struct in_addr src_ip;
struct in_addr dst_ip;
unsigned short src_port;
unsigned short dst_port;
unsigned char protocol;
} LogEntry;
// 日志模块配置
typedef struct {
int dp_debug_cli;
int dp_debug_ha;
int dp_debug_lookup;
int dp_debug_mcast;
int dp_debug_route;
int dp_debug_session;
} LogConfig;
// 全局日志缓冲区
LogEntry log_buffer[LOG_BUFFER_SIZE];
int log_index = 0;
pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
// 模块日志配置
LogConfig log_config = {1, 1, 1, 1, 1, 1}; // 默认打开所有模块的日志
// 报文五元组过滤条件
typedef struct {
struct in_addr src_ip;
struct in_addr dst_ip;
unsigned short src_port;
unsigned short dst_port;
unsigned char protocol;
int enabled;
} FilterConfig;
FilterConfig filter_config = { {0}, {0}, 0, 0, 0, 0 }; // 默认关闭五元组过滤
// 添加日志条目
void add_log(LogLevel level, const char* module, struct in_addr src_ip, struct in_addr dst_ip,
unsigned short src_port, unsigned short dst_port, unsigned char protocol, const char* format, ...) {
pthread_mutex_lock(&log_mutex);
// 检查缓冲区是否已满
if (log_index >= LOG_BUFFER_SIZE) {
pthread_mutex_unlock(&log_mutex);
return;
}
// 检查模块是否启用日志
if ((strcmp(module, "cli") == 0 && !log_config.dp_debug_cli) ||
(strcmp(module, "ha") == 0 && !log_config.dp_debug_ha) ||
(strcmp(module, "lookup") == 0 && !log_config.dp_debug_lookup) ||
(strcmp(module, "mcast") == 0 && !log_config.dp_debug_mcast) ||
(strcmp(module, "route") == 0 && !log_config.dp_debug_route) ||
(strcmp(module, "session") == 0 && !log_config.dp_debug_session)) {
pthread_mutex_unlock(&log_mutex);
return;
}
// 检查报文五元组过滤条件
if (filter_config.enabled) {
if ((filter_config.src_ip.s_addr && filter_config.src_ip.s_addr != src_ip.s_addr) ||
(filter_config.dst_ip.s_addr && filter_config.dst_ip.s_addr != dst_ip.s_addr) ||
(filter_config.src_port && filter_config.src_port != src_port) ||
(filter_config.dst_port && filter_config.dst_port != dst_port) ||
(filter_config.protocol && filter_config.protocol != protocol)) {
pthread_mutex_unlock(&log_mutex);
return;
}
}
va_list args;
va_start(args, format);
time_t now;
time(&now);
struct tm *local = localtime(&now);
char timestamp[20];
strftime(timestamp, 20, "%Y-%m-%d %H:%M:%S", local);
LogEntry* entry = &log_buffer[log_index % LOG_BUFFER_SIZE];
entry->level = level;
snprintf(entry->module, LOG_LINE_SIZE, "%s", module);
snprintf(entry->message, LOG_LINE_SIZE, "[%s] %s: ", timestamp, module);
vsnprintf(entry->message + strlen(entry->message), LOG_LINE_SIZE - strlen(entry->message), format, args);
entry->src_ip = src_ip;
entry->dst_ip = dst_ip;
entry->src_port = src_port;
entry->dst_port = dst_port;
entry->protocol = protocol;
log_index++;
va_end(args);
pthread_mutex_unlock(&log_mutex);
}
// 打印日志缓冲区
void print_logs(const char* module_filter, LogLevel level_filter) {
pthread_mutex_lock(&log_mutex);
for (int i = 0; i < log_index && i < LOG_BUFFER_SIZE; i++) {
LogEntry* entry = &log_buffer[i];
if ((module_filter == NULL || strcmp(entry->module, module_filter) == 0) &&
entry->level <= level_filter) {
printf("Level %d: %s\n", entry->level, entry->message);
}
}
pthread_mutex_unlock(&log_mutex);
}
// 清空日志缓冲区
void clear_logs() {
pthread_mutex_lock(&log_mutex);
log_index = 0;
pthread_mutex_unlock(&log_mutex);
}
// 设置模块日志配置
void set_log_config(const char* module, int enabled) {
pthread_mutex_lock(&log_mutex);
if (strcmp(module, "cli") == 0) {
log_config.dp_debug_cli = enabled;
} else if (strcmp(module, "ha") == 0) {
log_config.dp_debug_ha = enabled;
} else if (strcmp(module, "lookup") == 0) {
log_config.dp_debug_lookup = enabled;
} else if (strcmp(module, "mcast") == 0) {
log_config.dp_debug_mcast = enabled;
} else if (strcmp(module, "route") == 0) {
log_config.dp_debug_route = enabled;
} else if (strcmp(module, "session") == 0) {
log_config.dp_debug_session = enabled;
}
pthread_mutex_unlock(&log_mutex);
}
// 设置五元组过滤配置
void set_filter_config(struct in_addr src_ip, struct in_addr dst_ip,
unsigned short src_port, unsigned short dst_port,
unsigned char protocol, int enabled) {
pthread_mutex_lock(&log_mutex);
filter_config.src_ip = src_ip;
filter_config.dst_ip = dst_ip;
filter_config.src_port = src_port;
filter_config.dst_port = dst_port;
filter_config.protocol = protocol;
filter_config.enabled = enabled;
pthread_mutex_unlock(&log_mutex);
}
// 简单的CLI处理函数
void process_cli_command(const char* command) {
if (strncmp(command, "enable ", 7) == 0) {
const char* module = command + 7;
set_log_config(module, 1);
printf("%s logging enabled.\n", module);
} else if (strncmp(command, "disable ", 8) == 0) {
const char* module = command + 8;
set_log_config(module, 0);
printf("%s logging disabled.\n", module);
} else if (strncmp(command, "print ", 6) == 0) {
const char* args = command + 6;
char module[20];
int level;
if (sscanf(args, "%s %d", module, &level) == 2) {
print_logs(module, level);
} else {
printf("Invalid print command format. Use: print <module> <level>\n");
}
} else if (strcmp(command, "clear") == 0) {
clear_logs();
printf("Log buffer cleared.\n");
} else if (strncmp(command, "filter ", 7) == 0) {
const char* args = command + 7;
char src_ip_str[INET_ADDRSTRLEN], dst_ip_str[INET_ADDRSTRLEN];
unsigned short src_port, dst_port;
unsigned char protocol;
int enabled;
if (sscanf(args, "%s %s %hu %hu %hhu %d", src_ip_str, dst_ip_str, &src_port, &dst_port, &protocol, &enabled) == 6) {
struct in_addr src_ip, dst_ip;
inet_pton(AF_INET, src_ip_str, &src_ip);
inet_pton(AF_INET, dst_ip_str, &dst_ip);
set_filter_config(src_ip, dst_ip, src_port, dst_port, protocol, enabled);
printf("Filter set to src_ip=%s, dst_ip=%s, src_port=%hu, dst_port=%hu, protocol=%hhu, enabled=%d\n",
src_ip_str, dst_ip_str, src_port, dst_port, protocol, enabled);
} else {
printf("Invalid filter command format. Use: filter <src_ip> <dst_ip> <src_port><dst_port><protocol>\n");
} else {
printf("Unknown command.\n");
}
}
// 会话模块示例
void session_start(int session_id) {
add_log(LOG_INFO, "session", "Session started with ID %d", session_id);
}
void session_end(int session_id) {
add_log(LOG_INFO, "session", "Session ended with ID %d", session_id);
}
int main() {
// 添加一些日志示例
add_log(LOG_INFO, "session", "Session started with ID %d", 12345);
add_log(LOG_ERR, "protocol", "Protocol error: %s", "Invalid header");
add_log(LOG_DEBUG, "ddos", "DDoS detection algorithm initialized");
// 会话模块日志示例
session_start(1001);
session_end(1001);
// 模拟CLI输入
process_cli_command("disable session");
session_start(1002); // This log should not appear
process_cli_command("print session 6");
process_cli_command("enable session");
session_start(1003); // This log should appear
process_cli_command("print session 6");
// 清空日志缓冲区
process_cli_command("clear");
process_cli_command("print session 6");
return 0;
}