From 77288207fa55e8e5d0b0f986c45b6a33ebaf891c Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Tue, 31 May 2011 21:19:22 +0200 Subject: osmo-pcap-client: Connect to a server, send the data to it --- include/osmo-pcap/osmo_pcap_client.h | 11 ++- include/osmo-pcap/wireformat.h | 46 +++++++++ src/Makefile.am | 3 +- src/osmo_client_core.c | 5 +- src/osmo_client_main.c | 7 ++ src/osmo_client_network.c | 184 +++++++++++++++++++++++++++++++++++ 6 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 include/osmo-pcap/wireformat.h create mode 100644 src/osmo_client_network.c diff --git a/include/osmo-pcap/osmo_pcap_client.h b/include/osmo-pcap/osmo_pcap_client.h index 95302b1..7aae7ca 100644 --- a/include/osmo-pcap/osmo_pcap_client.h +++ b/include/osmo-pcap/osmo_pcap_client.h @@ -20,9 +20,12 @@ * */ +#include #include #include +#include +#include struct osmo_pcap_client { @@ -33,11 +36,12 @@ struct osmo_pcap_client { struct bpf_program bpf; char *filter_string; int filter_itself; - struct osmo_fd fd; char *srv_ip; int srv_port; + struct osmo_wqueue wqueue; + struct osmo_timer_list timer; }; extern struct osmo_pcap_client *pcap_client; @@ -46,3 +50,8 @@ int vty_client_init(struct osmo_pcap_client *); int osmo_client_capture(struct osmo_pcap_client *client, const char *device); int osmo_client_filter(struct osmo_pcap_client *client, const char *filter); + +void osmo_client_send_data(struct osmo_pcap_client *client, + struct pcap_pkthdr *hdr, const uint8_t *data); +void osmo_client_send_link(struct osmo_pcap_client *client); +void osmo_client_connect(struct osmo_pcap_client *); diff --git a/include/osmo-pcap/wireformat.h b/include/osmo-pcap/wireformat.h new file mode 100644 index 0000000..a642bb1 --- /dev/null +++ b/include/osmo-pcap/wireformat.h @@ -0,0 +1,46 @@ +/* + * osmo-pcap wireforat + * + * (C) 2011 by Holger Hans Peter Freyther + * (C) 2011 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef WIREFORMAT_H +#define WIREFORMAT_H + +#include +#include + +/* + * Should send an entire pcap header + */ +#define PKT_LINK_HDR 0 + +/* + * Should send one packet... + */ +#define PKT_LINK_DATA 1 + +struct osmo_pcap_data { + uint8_t type; + uint8_t spare[3]; + uint32_t len; + uint8_t data[0]; +} __attribute__((packed)); + +#endif diff --git a/src/Makefile.am b/src/Makefile.am index bb0bd56..206b167 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,5 +5,6 @@ AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOVTY_LIBS) bin_PROGRAMS = osmo_pcap_client osmo_pcap_client_SOURCES = osmo_client_main.c osmo_common.c \ - osmo_client_core.c osmo_client_vty.c + osmo_client_core.c osmo_client_vty.c \ + osmo_client_network.c osmo_pcap_client_LDADD = $(PCAP_LIBS) diff --git a/src/osmo_client_core.c b/src/osmo_client_core.c index eb9ebcf..04d2d25 100644 --- a/src/osmo_client_core.c +++ b/src/osmo_client_core.c @@ -37,7 +37,8 @@ static int pcap_read_cb(struct osmo_fd *fd, unsigned int what) data = pcap_next(client->handle, &hdr); if (!data) return -1; - printf("GOT a packet: %d %d\n", hdr.caplen, hdr.len); + + osmo_client_send_data(client, &hdr, data); return 0; } @@ -130,6 +131,8 @@ int osmo_client_capture(struct osmo_pcap_client *client, const char *device) return 4; } + osmo_client_send_link(client); + if (client->filter_string) { osmo_install_filter(client); } diff --git a/src/osmo_client_main.c b/src/osmo_client_main.c index 9c889ee..9ea0b66 100644 --- a/src/osmo_client_main.c +++ b/src/osmo_client_main.c @@ -187,6 +187,10 @@ int main(int argc, char **argv) pcap_client->fd.fd = -1; vty_client_init(pcap_client); + /* initialize the queue */ + osmo_wqueue_init(&pcap_client->wqueue, 10); + pcap_client->wqueue.bfd.fd = -1; + if (vty_read_config_file(config_file, NULL) < 0) { LOGP(DCLIENT, LOGL_ERROR, @@ -194,6 +198,9 @@ int main(int argc, char **argv) exit(1); } + /* attempt to connect to the remote */ + osmo_client_connect(pcap_client); + if (daemonize) { rc = osmo_daemonize(); if (rc < 0) { diff --git a/src/osmo_client_network.c b/src/osmo_client_network.c new file mode 100644 index 0000000..60f3216 --- /dev/null +++ b/src/osmo_client_network.c @@ -0,0 +1,184 @@ +/* + * osmo-pcap-client code + * + * (C) 2011 by Holger Hans Peter Freyther + * (C) 2011 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +static void _osmo_client_connect(void *_data) +{ + osmo_client_connect((struct osmo_pcap_client *) _data); +} + +static void lost_connection(struct osmo_pcap_client *client) +{ + if (client->wqueue.bfd.fd >= 0) { + osmo_fd_unregister(&client->wqueue.bfd); + close(client->wqueue.bfd.fd); + client->wqueue.bfd.fd = -1; + } + + + client->timer.cb = _osmo_client_connect; + client->timer.data = client; + osmo_timer_schedule(&client->timer, 2, 0); +} + +static void write_data(struct osmo_pcap_client *client, struct msgb *msg) +{ + if (osmo_wqueue_enqueue(&client->wqueue, msg) != 0) { + LOGP(DCLIENT, LOGL_ERROR, "Failed to enqueue.\n"); + msgb_free(msg); + return; + } +} + +static int read_cb(struct osmo_fd *fd) +{ + char buf[4096]; + int rc; + + rc = read(fd->fd, buf, sizeof(buf)); + if (rc <= 0) { + struct osmo_pcap_client *client = fd->data; + LOGP(DCLIENT, LOGL_ERROR, "Lost connection on read.\n"); + lost_connection(client); + return -1; + } + + return 0; +} + +static int write_cb(struct osmo_fd *fd, struct msgb *msg) +{ + int rc; + + rc = write(fd->fd, msg->data, msg->len); + if (rc < 0) { + struct osmo_pcap_client *client = fd->data; + LOGP(DCLIENT, LOGL_ERROR, "Lost connection on write.\n"); + lost_connection(client); + return -1; + } + + return 0; +} + +void osmo_client_send_data(struct osmo_pcap_client *client, + struct pcap_pkthdr *in_hdr, const uint8_t *data) +{ + struct osmo_pcap_data *om_hdr; + struct pcap_pkthdr *hdr; + struct msgb *msg; + + msg = msgb_alloc(4096, "data-data"); + if (!msg) { + LOGP(DCLIENT, LOGL_ERROR, "Failed to allocate.\n"); + return; + } + + om_hdr = (struct osmo_pcap_data *) msgb_put(msg, sizeof(*om_hdr)); + om_hdr->type = PKT_LINK_DATA; + + msg->l2h = msgb_put(msg, sizeof(*hdr)); + hdr = (struct pcap_pkthdr *) msg->l2h; + *hdr = *in_hdr; + + msg->l3h = msgb_put(msg, in_hdr->caplen); + memcpy(msg->l3h, data, in_hdr->caplen); + + om_hdr->len = msgb_l2len(msg); + + write_data(client, msg); +} + +void osmo_client_send_link(struct osmo_pcap_client *client) +{ + struct pcap_file_header *hdr; + struct osmo_pcap_data *om_hdr; + + struct msgb *msg = msgb_alloc(4096, "link-data"); + if (!msg) { + LOGP(DCLIENT, LOGL_ERROR, "Failed to allocate data.\n"); + return; + } + + + om_hdr = (struct osmo_pcap_data *) msgb_put(msg, sizeof(*om_hdr)); + om_hdr->type = PKT_LINK_HDR; + om_hdr->len = sizeof(*hdr); + + hdr = (struct pcap_file_header *) msgb_put(msg, sizeof(*hdr)); + hdr->magic = 0xa1b2c3d4; + hdr->version_major = 2; + hdr->version_minor = 4; + hdr->thiszone = 0; + hdr->sigfigs = 0; + hdr->snaplen = UINT_MAX; + hdr->linktype = pcap_datalink(client->handle); + + write_data(client, msg); +} + +void osmo_client_connect(struct osmo_pcap_client *client) +{ + int fd; + + client->wqueue.read_cb = read_cb; + client->wqueue.write_cb = write_cb; + client->wqueue.bfd.when = BSC_FD_READ; + client->wqueue.bfd.data = client; + osmo_wqueue_clear(&client->wqueue); + + fd = osmo_sock_init(AF_INET, SOCK_STREAM, IPPROTO_TCP, + client->srv_ip, client->srv_port, 0); + if (fd < 0) { + LOGP(DCLIENT, LOGL_ERROR, + "Failed to connect to %s:%d\n", + client->srv_ip, client->srv_port); + lost_connection(client); + return; + } + + client->wqueue.bfd.fd = fd; + if (osmo_fd_register(&client->wqueue.bfd) != 0) { + LOGP(DCLIENT, LOGL_ERROR, + "Failed to register to BFD.\n"); + lost_connection(client); + return; + } + + osmo_client_send_link(client); +} -- cgit v1.2.3