From 7309a906d0b898464432d284bf581a133dfded86 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 1 Jun 2011 14:04:22 +0200 Subject: osmo-pcap-server: Write the pcap files to disk, roll them over --- src/osmo_server_main.c | 1 - src/osmo_server_network.c | 122 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/src/osmo_server_main.c b/src/osmo_server_main.c index 54a5f00..5c1ad58 100644 --- a/src/osmo_server_main.c +++ b/src/osmo_server_main.c @@ -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); diff --git a/src/osmo_server_network.c b/src/osmo_server_network.c index 19e5c3c..fb08722 100644 --- a/src/osmo_server_network.c +++ b/src/osmo_server_network.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -30,6 +31,7 @@ #include #include +#include #include #include #include @@ -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; } -- cgit v1.2.3