Skip to content

Commit

Permalink
added libcap based log file writing
Browse files Browse the repository at this point in the history
  • Loading branch information
g3gg0 committed May 8, 2024
1 parent 12ea08e commit b7a1bc7
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 2 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ ifneq ($(NO_SANITIZERS),1)
CFLAGS_linux += -fsanitize=undefined -fsanitize=address -fno-omit-frame-pointer
LFLAGS_linux += -fsanitize=undefined -fsanitize=address -static-libasan
endif


CFLAGS_linux += $(OPTI_LEVEL)

## win32 specific headers/sources
Expand Down Expand Up @@ -368,7 +370,6 @@ CFLAGS += $(INCLUDES)
CFLAGS += -DUSE_ALLOCA -DOPUS_BUILD
CFLAGS_linux += -Wno-error=stringop-overflow= -Wno-error=stringop-overread


THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))

# Location of your .proto files
Expand Down
1 change: 1 addition & 0 deletions include/mutex_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ typedef enum
MUTEX_MQTT_TX_BUFFER,
MUTEX_MQTT_BOX,
MUTEX_TONIES_JSON_CACHE,
MUTEX_PCAPLOG_FILE,
MUTEX_LAST
} mutex_id_t;

Expand Down
7 changes: 6 additions & 1 deletion include/net_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

#include "settings.h"
#include "toniebox_state_type.h"
#include "pcaplog_types.h"

#define TONIE_AUTH_TOKEN_LENGTH 32
#define JWT_AUTH_TOKEN_LENGTH 32
Expand All @@ -48,7 +49,11 @@ typedef struct
{
uint8_t authentication_token[TONIE_AUTH_TOKEN_LENGTH];
client_ctx_t client_ctx;

pcaplog_t pcap_data;
uint32_t hostIpAddr;
uint32_t clientIpAddr;
uint16_t hostPort;
uint16_t clientPort;
} http_connection_private_t;

#define CONTENT_LENGTH_MAX (INT32_MAX)
Expand Down
97 changes: 97 additions & 0 deletions include/pcap_dump.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
* pcap_dump aims to provide some basic functions to write a packet data into a pcap file
*/
#ifndef PCAP_DUMP_H_
#define PCAP_DUMP_H_
#include <stdint.h>
#include "fs_port.h"

struct pd_timeval
{
uint32_t tv_sec; /* seconds */
uint32_t tv_usec; /* microseconds */
};

struct pd_pcap_file_header
{
uint32_t magic;
uint16_t version_major;
uint16_t version_minor;
int32_t thiszone; /* gmt to local correction */
uint32_t sigfigs; /* accuracy of timestamps */
uint32_t snaplen; /* max length saved portion of each pkt */
uint32_t linktype; /* data link type (LINKTYPE_*) */
};

struct pd_pcap_pkthdr
{
struct pd_timeval ts; /* time stamp using 32 bits fields */
uint32_t caplen; /* length of portion present */
uint32_t len; /* length this packet (off wire) */
};

static inline uint16_t bswap16(uint16_t x)
{
return (uint16_t)(((x & 0x00ffU) << 8) |
((x & 0xff00U) >> 8));
}
static inline uint32_t bswap32(uint32_t x)
{
return ((x & 0x000000ffUL) << 24) |
((x & 0x0000ff00UL) << 8) |
((x & 0x00ff0000UL) >> 8) |
((x & 0xff000000UL) >> 24);
}
static inline uint64_t bswap64(uint64_t x)
{
return ((x & 0x00000000000000ffULL) << 56) |
((x & 0x000000000000ff00ULL) << 40) |
((x & 0x0000000000ff0000ULL) << 24) |
((x & 0x00000000ff000000ULL) << 8) |
((x & 0x000000ff00000000ULL) >> 8) |
((x & 0x0000ff0000000000ULL) >> 24) |
((x & 0x00ff000000000000ULL) >> 40) |
((x & 0xff00000000000000ULL) >> 56);
}

/**
* Create a new pcap file and write pcap file with the default configuration:
* - linktype : DLT_EN10MB,
* - timezone : 0
* - snaplen : 65535
*
* If the pcap file already exists then open and points to the end of the file to continue writting data
*
* @param path path to the pcap file
* @return pointer points to the file
*/
FsFile *pd_open(const char *path);

/**
* Create a new pcap file with given linktype, timezone and snaplen
* - write a pcap header to a new file. Called by openPcapFile. Shouldn't be used outside pcap_dump.c
* @param path path to the pcap file
* @param linktype link type
* @param thiszone timezone
* @param snaplen snaplen
* @return pointer points to the file
*/
FsFile *pd_create(const char *path, int linktype, int thiszone, int snaplen);

/**
* Write a buffer into a pcap file with given timestamp
*
* @param fd points to the pcap file
* @param buf packet data
* @param len length of packet
* @param tv timestamp
* @return
*/
int pd_write(FsFile *fd, uint8_t *buf, int len, struct timeval tv);
/**
* Close a pcap file after finish writing
* @param fd points to pcap file
*/
void pd_close(FsFile *fd);

#endif // end of pcap_dump.h
10 changes: 10 additions & 0 deletions include/pcaplog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>

#include "pcaplog_types.h"
#include "net_config.h"

void pcaplog_open();
void pcaplog_close();
void pcaplog_write(http_connection_private_t *ctx, bool is_tx, const uint8_t *http_data, size_t http_len);
8 changes: 8 additions & 0 deletions include/pcaplog_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>

typedef struct
{
uint32_t seq_rx;
uint32_t seq_tx;
} pcaplog_t;
7 changes: 7 additions & 0 deletions include/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ typedef struct
char *logHumanFile;
} settings_rtnl_t;

typedef struct
{
bool enabled;
char *filename;
} settings_pcap_t;

typedef struct
{
uint32_t configVersion;
Expand All @@ -293,6 +299,7 @@ typedef struct
settings_internal_t internal;
settings_log_t log;
settings_rtnl_t rtnl;
settings_pcap_t pcap;
} settings_t;

typedef enum
Expand Down
6 changes: 6 additions & 0 deletions src/cyclone/cyclone_tcp/http/http_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,12 @@ void httpListenerTask(void *param)
// Reference to the new socket
connection->socket = socket;

/* store information for pcap */
connection->private.clientIpAddr = clientIpAddr.ipv4Addr;
connection->private.clientPort = clientPort;
connection->private.hostIpAddr = connection->settings->ipAddr.ipv4Addr;
connection->private.hostPort = connection->settings->port;

// Set timeout for blocking functions
socketSetTimeout(connection->socket, HTTP_SERVER_TIMEOUT);

Expand Down
5 changes: 5 additions & 0 deletions src/cyclone/cyclone_tcp/http/http_server_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "str.h"
#include "path.h"
#include "debug.h"
#include "pcaplog.h"

//Check TCP/IP stack configuration
#if (HTTP_SERVER_SUPPORT == ENABLED)
Expand Down Expand Up @@ -984,6 +985,8 @@ error_t httpSend(HttpConnection *connection,
//Transmit data to the client
error = socketSend(connection->socket, data, length, NULL, flags);
}

pcaplog_write(&connection->private, true, (const uint8_t *)data, length);

//Return status code
return error;
Expand Down Expand Up @@ -1032,6 +1035,8 @@ error_t httpReceive(HttpConnection *connection,
//Receive data from the client
error = socketReceive(connection->socket, data, size, received, flags);
}

pcaplog_write(&connection->private, true, (const uint8_t *)data, *received);

//Return status code
return error;
Expand Down
61 changes: 61 additions & 0 deletions src/pcap_dump.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* based on https://github.com/luongnv89/pcap-dump */

#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>

#include "pcap_dump.h"
#include "fs_port.h"

int pd_write_header(FsFile *fd, int linktype, int thiszone, int snaplen)
{
struct pd_pcap_file_header hdr;

hdr.magic = 0xa1b2c3d4;
hdr.version_major = 2;
hdr.version_minor = 4;
hdr.thiszone = thiszone;
hdr.snaplen = snaplen;
hdr.sigfigs = 0;
hdr.linktype = linktype;

fsWriteFile(fd, (char *)&hdr, sizeof(hdr));

return 0;
}

int pd_write(FsFile *fd, uint8_t *buf, int len, struct timeval tv)
{
struct pd_pcap_pkthdr h;

if (len > 65535)
{
len = 65535;
}

h.ts.tv_sec = (uint32_t)tv.tv_sec;
h.ts.tv_usec = (uint32_t)tv.tv_usec;

h.caplen = len;
h.len = len;

fsWriteFile(fd, (char *)&h, sizeof(h));
fsWriteFile(fd, buf, len);
return 0;
}

FsFile *pd_create(const char *path, int linktype, int thiszone, int snaplen)
{
FsFile *fd = fsOpenFile(path, FS_FILE_MODE_WRITE);
if (!fd)
return NULL;

pd_write_header(fd, linktype, thiszone, snaplen);

return fd;
}

void pd_close(FsFile *fd)
{
fsCloseFile(fd);
}
109 changes: 109 additions & 0 deletions src/pcaplog.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@


#include <pcap.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <sys/time.h>

#include "settings.h"
#include "pcaplog.h"
#include "pcap_dump.h"
#include "mutex_manager.h"

static FsFile *pcap = NULL;

void pcaplog_open()
{
if (!settings_get_bool("pcap.enabled"))
{
return;
}

const char *filename = settings_get_string("pcap.filename");

TRACE_WARNING("pcap dump is enabled - this will cause the file '%s' to grow indefinitely!\r\n", filename);

pcap = pd_create(filename, 101, 0, 65535);
if (!pcap)
{
fprintf(stderr, "Error opening pcap file\n");
return;
}
}

void pcaplog_close()
{
if (!pcap)
{
return;
}

pd_close(pcap);

pcap = 0;
}

void pcaplog_write(http_connection_private_t *ctx, bool is_tx, const uint8_t *payload, size_t payload_len)
{
if (!pcap || !payload_len || !ctx)
{
return;
}

size_t packet_len = sizeof(struct ip) + sizeof(struct tcphdr) + payload_len;
uint8_t *packet = malloc(packet_len);

struct ip ip_header;
ip_header.ip_hl = 5;
ip_header.ip_v = 4;
ip_header.ip_tos = 0;
ip_header.ip_len = htons(packet_len);
ip_header.ip_id = 0;
ip_header.ip_off = 0;
ip_header.ip_ttl = 64;
ip_header.ip_p = IPPROTO_TCP;
ip_header.ip_sum = 0;
ip_header.ip_src.s_addr = is_tx ? ctx->hostIpAddr : ctx->clientIpAddr;
ip_header.ip_dst.s_addr = !is_tx ? ctx->hostIpAddr : ctx->clientIpAddr;

struct tcphdr tcp_header;
tcp_header.th_sport = htons(is_tx ? ctx->hostPort : ctx->clientPort);
tcp_header.th_dport = htons(!is_tx ? ctx->hostPort : ctx->clientPort);
tcp_header.th_ack = htonl(!is_tx ? ctx->pcap_data.seq_tx : ctx->pcap_data.seq_rx);
tcp_header.th_seq = htonl(is_tx ? ctx->pcap_data.seq_tx : ctx->pcap_data.seq_rx);
tcp_header.th_x2 = 0;
tcp_header.th_off = 5;
tcp_header.th_flags = TH_ACK;
tcp_header.th_win = htons(65535);
tcp_header.th_sum = 0;
tcp_header.th_urp = 0;
tcp_header.th_sum = 0xFFFF;

if (is_tx)
{
ctx->pcap_data.seq_tx += payload_len;
}
else
{
ctx->pcap_data.seq_rx += payload_len;
}

memcpy(packet, &ip_header, sizeof(ip_header));
memcpy(packet + sizeof(ip_header), &tcp_header, sizeof(tcp_header));
memcpy(packet + sizeof(ip_header) + sizeof(tcp_header), payload, payload_len);

struct timeval tv;
gettimeofday(&tv, NULL);

mutex_lock(MUTEX_PCAPLOG_FILE);
pd_write(pcap, packet, packet_len, tv);
mutex_unlock(MUTEX_PCAPLOG_FILE);

free(packet);
}
Loading

0 comments on commit b7a1bc7

Please sign in to comment.