持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
简介
上一篇中,我们知道可以建立unix sock tcp与audispd建立通讯,但是我们只知道可以收到消息,我们还不知道消息的内容,这期中我们将会开始使用自己编写的代码与audispd建立通讯,并且初步了解audispd发送过来的消息格式
创建unix域套接字接收消息
- 示例程序中出现过的头文件
#include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/un.h> #include <unistd.h> #include <libaudit.h>
创建unix sock
struct sockaddr_un server_addr;
server_addr.sun_family = AF_UNIX;
//此处的路径是配置中的路径
strcpy(server_addr.sun_path, "/var/run/theMessage_audispd");
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if(sockfd < 0)
return -1;
//本地通信 连接audisp启动的服务端
int result = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(result < 0)
{
close(sockfd);
return -1;
}
while(1)
{
memset(buff, 0, sizeof(buff));
int len;
if((len = read(sockfd, buff, sizeof(buff))) > 0)
printf("%s\n", buff);
}
当我们看到程序顺利执行,可以收到消息,或者阻塞等待收到消息,就算是成功的第一步了,我们接收到了audisptd分发的消息了,但是有一个问题,我们这篇需要使用的二进制来接收消息,直接按字符串打印保不齐会出现啥,接下来,我们从源码角度分析接收到的消息是什么内容
源码分析通讯数据报
-
这个loop函数,是循环收消息的函数,也就是audispd的主要任务函数
/home/kira/rpmbuild/BUILD/audit-3.0.1/audisp/audispd.c static int event_loop(void) -
这个函数里,就出现了发送二进制的函数
/* Now send the event to the right child */ if (conf->p->type == S_AF_UNIX) { if (conf->p->format == F_STRING) send_af_unix_string(v, len); else send_af_unix_binary(e); } -
看一下
send_af_unix_binary这个函数的内容void send_af_unix_binary(event_t *e) { if (sock < 0) return; if (conn >= 0) { int rc; struct iovec vec[2]; vec[0].iov_base = &e->hdr; vec[0].iov_len = sizeof(struct audit_dispatcher_header); vec[1].iov_base = e->data; vec[1].iov_len = MAX_AUDIT_MESSAGE_LENGTH; do { rc = writev(conn, vec, 2); } while (rc < 0 && errno == EINTR); if (rc < 0 && errno == EPIPE) { close(conn); conn = -1; stop_watching(); start_watching(); } } } -
啊哈,是调用
writev发送了两段东西,分别是一个结构体,一个data数组,大小是MAX_AUDIT_MESSAGE_LENGTH + sizeof(struct audit_dispatcher_header) -
到这里可以看到,其实每次从unix tcp sock接收到的消息,都是固定的大小,那么我们做audispd观察者的时候,就可以设定这个固定大小的数组来接收消息,audispd这样处理有好处有坏处
- 好处是每条消息的大小一致,不需要考虑消息对齐
- 坏处是这个大小很大,后续可以看到其实很多消息的长度小得多,不足这个消息最大长度的1/10,造成一定的空间浪费
完结,撒花
本期中,我们初探了audispd的源码,看到了真正audispd发送消息的函数位置,只有发送了一个结构体,一个字符数组,下一章节中,我们将会更加深入audispd的源码,探索audispd的消息是怎么组合的,这个结构体的每一个字段的含义。