diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-06-01 14:04:22 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-06-01 14:09:26 +0200 |
commit | 7309a906d0b898464432d284bf581a133dfded86 (patch) | |
tree | b9a417eb577c5ce801045a08d3230ee2d7b95497 /src/osmo_server_network.c | |
parent | 88c07f2b7e9ac6a3c3216c00cd3ec8baba070ffe (diff) |
osmo-pcap-server: Write the pcap files to disk, roll them over0.0.1
Diffstat (limited to 'src/osmo_server_network.c')
-rw-r--r-- | src/osmo_server_network.c | 122 |
1 files changed, 119 insertions, 3 deletions
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 <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; } |