socatで装置内通信のデータをのぞき見る
socatを使ってUNIXドメイン通信を中継し通信内容をのぞいてみる。
構成のイメージは下記。
--------------------------------------------------
________ ________ ________
| | | | | |
| Client |--->| socat |--->| Sever |
|________| |________| |________|
|
---> 標準出力に通信内容を表示。
--------------------------------------------------
目次
プログラム
local.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#define MSGID_HELLO_REQUEST (0x0101)
#define MAX_USER (1)
typedef enum {
MSG_KIND_REQUEST = 0,
MSG_KIND_MAX
} msgkind_t;
typedef struct {
uint32_t id;
uint16_t kind;
uint16_t seqno;
} msg_header_t;
client.c
#include "local.h"
#define UNIX_SOCKET_FILEPATH "./usocket.client"
int main(void)
{
int sfd = -1;
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = UNIX_SOCKET_FILEPATH,
};
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
int rc = connect(sfd, (struct sockaddr* )&addr, sizeof(addr));
if (rc < 0) {
perror("connect");
close(sfd);
exit(EXIT_FAILURE);
}
uint16_t seqno = 0;
while(1) {
msg_header_t req = {
.id = MSGID_HELLO_REQUEST,
.kind = MSG_KIND_REQUEST,
.seqno = seqno,
};
ssize_t ss = send(sfd, (void*)&req, sizeof(req), 0);
if (ss < 0) {
perror("send");
close(sfd);
break;
}
if (ss == 0 || ss < 0) {
printf("connection closed.\n");
unlink(UNIX_SOCKET_FILEPATH);
break;
}
printf("sent request, wait 3 sec (-.-)zzZ\n");
sleep(3);
seqno++;
}
return 0;
}
server.c
#include "local.h"
#define UNIX_SOCKET_FILEPATH "./usocket.server"
int main(void)
{
int sfd = -1;
struct sockaddr_un addr = {
.sun_family = AF_UNIX,
.sun_path = UNIX_SOCKET_FILEPATH,
};
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
unlink(UNIX_SOCKET_FILEPATH);
int rc = bind(sfd, (struct sockaddr* )&addr, sizeof(addr));
if (rc < 0) {
perror("bind");
close(sfd);
exit(EXIT_FAILURE);
}
rc = listen(sfd, MAX_USER);
if (rc < 0) {
perror("listen");
close(sfd);
exit(EXIT_FAILURE);
}
socklen_t addrlen;
struct sockaddr_un caddr;
int acsfd = accept(sfd, (struct sockaddr *)&caddr, &addrlen);
if (acsfd < 0) {
perror("accept");
close(sfd);
exit(EXIT_FAILURE);
}
while(1) {
uint16_t seqno = 0;
msg_header_t req;
ssize_t rs = recv(acsfd, (void*)&req, sizeof(req), 0);
if (rs < 0) {
perror("recv");
close(sfd);
break;
}
printf("recv size=%d, id=%#x, kind=%#x, seqno=%d\n",
rs, req.id, req.kind, req.seqno);
if (rs == 0) {
printf("connection closed.\n");
unlink(UNIX_SOCKET_FILEPATH);
break;
}
}
return 0;
}
実行結果
3つの端末を開き各端末で下記コマンドを実行。
$ sudo yum -y install socat
$ socat -x -v UNIX-LISTEN:./usocket.client, UNIX-CONNECT:./usocket.server
$ gcc -o server server.c
$ ./server
$ gcc -o client client.c
$ ./client

コメント