osmo-pcap-server: Write the pcap files to disk, roll them over

This commit is contained in:
Holger Hans Peter Freyther 2011-06-01 14:04:22 +02:00
parent 88c07f2b7e
commit 7309a906d0
2 changed files with 119 additions and 4 deletions

View File

@ -171,7 +171,6 @@ int main(int argc, char **argv)
/* seed the PRNG */
srand(time(NULL));
signal(SIGINT, &signal_handler);
signal(SIGABRT, &signal_handler);
signal(SIGUSR1, &signal_handler);

View File

@ -22,6 +22,7 @@
#include <osmo-pcap/osmo_pcap_server.h>
#include <osmo-pcap/common.h>
#include <osmo-pcap/wireformat.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/talloc.h>
@ -30,6 +31,7 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
@ -48,6 +50,96 @@ static void close_connection(struct osmo_pcap_conn *conn)
}
}
static void restart_pcap(struct osmo_pcap_conn *conn)
{
time_t now = time(NULL);
struct tm *tm = localtime(&now);
char *filename;
int rc;
if (conn->local_fd >= 0) {
close(conn->local_fd);
conn->local_fd = -1;
}
filename = talloc_asprintf(conn, "%s/trace-%s-%d%.2d%.2d_%.2d%.2d%.2d.pcap",
conn->server->base_path, conn->name,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
conn->local_fd = creat(filename, S_IRUSR);
if (conn->local_fd < 0) {
LOGP(DSERVER, LOGL_ERROR, "Failed to file: '%s'\n", filename);
return;
}
rc = write(conn->local_fd, &conn->file_hdr, sizeof(conn->file_hdr));
if (rc != sizeof(conn->file_hdr)) {
LOGP(DSERVER, LOGL_ERROR, "Failed to write the header: %d\n", errno);
close(conn->local_fd);
conn->local_fd = -1;
return;
}
conn->last_write = *tm;
talloc_free(filename);
}
static void link_data(struct osmo_pcap_conn *conn, struct osmo_pcap_data *data)
{
struct pcap_file_header *hdr;
if (data->len != sizeof(*hdr)) {
LOGP(DSERVER, LOGL_ERROR, "The pcap_file_header does not fit.\n");
close_connection(conn);
return;
}
hdr = (struct pcap_file_header *) &data->data[0];
if (conn->local_fd < 0) {
conn->file_hdr = *hdr;
restart_pcap(conn);
} else if (memcmp(&conn->file_hdr, hdr, sizeof(*hdr)) != 0) {
conn->file_hdr = *hdr;
restart_pcap(conn);
}
}
/*
* Check if we are past the limit or on a day change
*/
static void write_data(struct osmo_pcap_conn *conn, struct osmo_pcap_data *data)
{
time_t now = time(NULL);
struct tm *tm = localtime(&now);
int rc;
if (conn->local_fd < -1) {
LOGP(DSERVER, LOGL_ERROR, "No file is open. close connection.\n");
close_connection(conn);
return;
}
off_t cur = lseek(conn->local_fd, 0, SEEK_CUR);
if (cur > conn->server->max_size) {
LOGP(DSERVER, LOGL_NOTICE, "Rolling over file for %s\n", conn->name);
restart_pcap(conn);
} else if (conn->last_write.tm_mday != tm->tm_mday ||
conn->last_write.tm_mon != tm->tm_mon ||
conn->last_write.tm_year != tm->tm_year) {
LOGP(DSERVER, LOGL_NOTICE, "Rolling over file for %s\n", conn->name);
restart_pcap(conn);
}
conn->last_write = *tm;
rc = write(conn->local_fd, &data->data[0], data->len);
if (rc != data->len) {
LOGP(DSERVER, LOGL_ERROR, "Failed to write for %s\n", conn->name);
close_connection(conn);
}
}
void osmo_pcap_server_delete(struct osmo_pcap_conn *conn)
{
close_connection(conn);
@ -55,7 +147,6 @@ void osmo_pcap_server_delete(struct osmo_pcap_conn *conn)
talloc_free(conn);
}
struct osmo_pcap_conn *osmo_pcap_server_find(struct osmo_pcap_server *server,
const char *name)
{
@ -81,18 +172,43 @@ struct osmo_pcap_conn *osmo_pcap_server_find(struct osmo_pcap_server *server,
static int read_cb(struct osmo_fd *fd, unsigned int what)
{
struct osmo_pcap_data *data;
struct osmo_pcap_conn *conn;
char buf[4096];
int rc;
conn = fd->data;
rc = read(fd->fd, buf, sizeof(buf));
if (rc < 0) {
data = (struct osmo_pcap_data *) &buf[0];
rc = read(fd->fd, buf, sizeof(*data));
if (rc != sizeof(*data)) {
LOGP(DSERVER, LOGL_ERROR, "Failed to read from %s\n", conn->name);
close_connection(conn);
return -1;
}
if (data->len > 2000) {
LOGP(DSERVER, LOGL_ERROR, "Unplausible result %u\n", data->len);
close_connection(conn);
return -1;
}
rc = read(fd->fd, &data->data[0], data->len);
if (rc != data->len) {
LOGP(DSERVER, LOGL_ERROR, "Two short packet %d\n", rc);
close_connection(conn);
return -1;
}
switch (data->type) {
case PKT_LINK_HDR:
link_data(conn, data);
break;
case PKT_LINK_DATA:
write_data(conn, data);
break;
}
return 0;
}