新增成功获取到 MAC 后写入 Redis 的审计日志,记录批次、MAC 和时间

This commit is contained in:
zzh 2025-11-06 10:53:53 +08:00
parent a0090010f0
commit c9088e147d
2 changed files with 103 additions and 4 deletions

View File

@ -7,6 +7,7 @@
#include <linux/input.h>
#include <poll.h>
#include <pthread.h>
#include <time.h>
#include "hiredis.h"
// 前置声明:黄灯控制接口
@ -339,6 +340,100 @@ static int redis_query_mac(const char* host_opt, const char* port_opt, const cha
return -1;
}
// 审计在Redis记录每次使用的MAC、批次与时间
static int redis_audit_log(const char* host_opt, const char* port_opt, const char* db_opt,
const char* audit_key_opt, const char* batch, const char* mac, const char* note_opt) {
if (!batch || !*batch || !mac || !*mac) return -1;
const char* host = host_opt ? host_opt : (getenv("REDIS_HOST") ? getenv("REDIS_HOST") : "180.163.74.83");
int port = port_opt ? atoi(port_opt) : (getenv("REDIS_PORT") ? atoi(getenv("REDIS_PORT")) : 6379);
int db = db_opt ? atoi(db_opt) : (getenv("REDIS_DB") ? atoi(getenv("REDIS_DB")) : 0);
const char* auth = getenv("REDIS_AUTH");
if (!auth || !*auth) auth = "Zzh08165511";
const char* audit_key = audit_key_opt ? audit_key_opt : (getenv("REDIS_AUDIT_KEY") ? getenv("REDIS_AUDIT_KEY") : "mac_batch_audit_pdd");
struct timeval tv; tv.tv_sec = 3; tv.tv_usec = 0;
redisContext* c = redisConnectWithTimeout(host, port, tv);
if (!c || c->err) {
fprintf(stderr, "[redis-audit] connect error: %s\n", c ? c->errstr : "unknown");
if (c) redisFree(c);
return -1;
}
if (auth && *auth) {
redisReply* ra = (redisReply*)redisCommand(c, "AUTH %s", auth);
if (!ra || (ra->type == REDIS_REPLY_ERROR)) {
fprintf(stderr, "[redis-audit] AUTH error: %s\n", ra && ra->str ? ra->str : "no-reply");
if (ra) freeReplyObject(ra);
redisFree(c);
return -1;
}
freeReplyObject(ra);
}
if (db > 0) {
redisReply* rs = (redisReply*)redisCommand(c, "SELECT %d", db);
if (!rs || (rs->type == REDIS_REPLY_ERROR)) {
fprintf(stderr, "[redis-audit] SELECT %d error: %s\n", db, rs && rs->str ? rs->str : "no-reply");
if (rs) freeReplyObject(rs);
redisFree(c);
return -1;
}
freeReplyObject(rs);
}
// 优先使用 Redis 服务器时间,避免设备本地时间不准
long long sv_secs = -1;
{
redisReply* tr = (redisReply*)redisCommand(c, "TIME");
if (tr && tr->type == REDIS_REPLY_ARRAY && tr->elements >= 2 &&
tr->element[0] && tr->element[0]->str) {
sv_secs = atoll(tr->element[0]->str);
} else {
fprintf(stderr, "[redis-audit] TIME failed, fallback to local time\n");
}
if (tr) freeReplyObject(tr);
}
time_t base = (sv_secs > 0) ? (time_t)sv_secs : time(NULL);
// 中国时区(+08:00不依赖设备TZ格式为 YYYY-MM-DD HH:MM:SS
time_t base_cn = base + 8 * 3600;
struct tm tm_sv_cn; gmtime_r(&base_cn, &tm_sv_cn);
char ts_cn[24];
strftime(ts_cn, sizeof(ts_cn), "%Y-%m-%d %H:%M:%S", &tm_sv_cn);
char val[320];
snprintf(val, sizeof(val), "ts_cn=%s batch=%s mac=%s%s%s", ts_cn, batch, mac,
(note_opt && *note_opt) ? " note=" : "",
(note_opt && *note_opt) ? note_opt : "");
// 写入总审计列表
redisReply* r = (redisReply*)redisCommand(c, "LPUSH %s %s", audit_key, val);
if (!r || r->type == REDIS_REPLY_ERROR) {
fprintf(stderr, "[redis-audit] LPUSH %s failed: %s\n", audit_key, r && r->str ? r->str : "no-reply");
if (r) freeReplyObject(r);
redisFree(c);
return -1;
}
freeReplyObject(r);
// 同时按批次维度记录key为 <audit_key>:<batch>
char batch_key[128];
snprintf(batch_key, sizeof(batch_key), "%s:%s", audit_key, batch);
r = (redisReply*)redisCommand(c, "LPUSH %s %s", batch_key, val);
if (!r || r->type == REDIS_REPLY_ERROR) {
fprintf(stderr, "[redis-audit] LPUSH %s failed: %s\n", batch_key, r && r->str ? r->str : "no-reply");
if (r) freeReplyObject(r);
redisFree(c);
return -1;
}
freeReplyObject(r);
redisFree(c);
fprintf(stderr, "[redis-audit] logged: %s | %s\n", batch, mac);
return 0;
}
static int read_file(const char* path, char** out_buf, size_t* out_len) {
FILE* f = fopen(path, "rb");
if (!f) return -1;
@ -583,6 +678,8 @@ int main(int argc, char** argv) {
if (update_hwaddress_in_interfaces(interfaces_path, mac_from_redis) == 0) {
stop_yellow_blink();
fprintf(stdout, "已更新MAC为: %s\n", mac_from_redis);
// 记录审计批次、MAC、时间
redis_audit_log(NULL, NULL, NULL, NULL, batch, mac_from_redis, "auto-loop");
sync();
char verify_mac[64] = {0};
if (get_hw_mac_from_interfaces(interfaces_path, verify_mac, sizeof(verify_mac)) == 0) {
@ -656,6 +753,8 @@ int main(int argc, char** argv) {
if (update_hwaddress_in_interfaces(interfaces_path, mac_from_redis) != 0) {
return 3;
}
// 记录审计批次、MAC、时间
redis_audit_log(NULL, NULL, NULL, NULL, batch, mac_from_redis, "legacy");
char verify_mac[64] = {0};
if (get_hw_mac_from_interfaces(interfaces_path, verify_mac, sizeof(verify_mac)) == 0) {
to_upper_str(verify_mac);
@ -698,10 +797,10 @@ static pthread_t led_thread;
static void gpio_init_yellow(void) {
int fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd >= 0) {
write(fd, "114", 3);
write(fd, "113", 3);
close(fd);
}
fd = open("/sys/class/gpio/gpio114/direction", O_WRONLY);
fd = open("/sys/class/gpio/gpio113/direction", O_WRONLY);
if (fd >= 0) {
write(fd, "out", 3);
close(fd);
@ -709,7 +808,7 @@ static void gpio_init_yellow(void) {
}
static void* led_blink_thread(void* arg) {
int fd = open("/sys/class/gpio/gpio114/value", O_WRONLY);
int fd = open("/sys/class/gpio/gpio113/value", O_WRONLY);
if (fd < 0) return NULL;
while (led_running) {
write(fd, "1", 1);
@ -742,7 +841,7 @@ static void set_yellow_on(void) {
stop_yellow_blink();
// 初始化GPIO并置为高电平
gpio_init_yellow();
int fd = open("/sys/class/gpio/gpio114/value", O_WRONLY);
int fd = open("/sys/class/gpio/gpio113/value", O_WRONLY);
if (fd < 0) return;
write(fd, "1", 1);
close(fd);

Binary file not shown.