aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmo-pcap/osmo_pcap_client.h6
-rw-r--r--src/osmo_client_network.c98
-rw-r--r--src/osmo_client_vty.c40
3 files changed, 124 insertions, 20 deletions
diff --git a/include/osmo-pcap/osmo_pcap_client.h b/include/osmo-pcap/osmo_pcap_client.h
index b4dda78..7888dfe 100644
--- a/include/osmo-pcap/osmo_pcap_client.h
+++ b/include/osmo-pcap/osmo_pcap_client.h
@@ -46,6 +46,11 @@ enum {
CLIENT_CTR_P_IFDROP,
};
+enum osmo_pcap_protocol {
+ PROTOCOL_OSMOPCAP,
+ PROTOCOL_IPIP,
+};
+
struct osmo_pcap_client_conn {
struct llist_head entry;
const char *name;
@@ -55,6 +60,7 @@ struct osmo_pcap_client_conn {
char *source_ip;
struct osmo_wqueue wqueue;
struct osmo_timer_list timer;
+ enum osmo_pcap_protocol protocol;
/* TLS handling */
bool tls_on;
diff --git a/src/osmo_client_network.c b/src/osmo_client_network.c
index 402e1cb..ec03b09 100644
--- a/src/osmo_client_network.c
+++ b/src/osmo_client_network.c
@@ -150,12 +150,25 @@ int conn_cb(struct osmo_fd *fd, unsigned int what)
return 0;
}
+static int get_iphdr_offset(int dlt)
+{
+ switch (dlt) {
+ case DLT_EN10MB:
+ return 14;
+ case DLT_LINUX_SLL:
+ return 16;
+ default:
+ return -1;
+ }
+}
+
void osmo_client_send_data(struct osmo_pcap_client_conn *conn,
struct pcap_pkthdr *in_hdr, const uint8_t *data)
{
struct osmo_pcap_data *om_hdr;
struct osmo_pcap_pkthdr *hdr;
struct msgb *msg;
+ int offset, ip_len;
if (in_hdr->caplen > 9000) {
LOGP(DCLIENT, LOGL_ERROR,
@@ -171,22 +184,42 @@ void osmo_client_send_data(struct osmo_pcap_client_conn *conn,
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 osmo_pcap_pkthdr *) msg->l2h;
- hdr->ts_sec = in_hdr->ts.tv_sec;
- hdr->ts_usec = in_hdr->ts.tv_usec;
- hdr->caplen = in_hdr->caplen;
- hdr->len = in_hdr->len;
-
- msg->l3h = msgb_put(msg, in_hdr->caplen);
- memcpy(msg->l3h, data, in_hdr->caplen);
-
- om_hdr->len = htons(msgb_l2len(msg));
- rate_ctr_add(&conn->client->ctrg->ctr[CLIENT_CTR_BYTES], hdr->caplen);
- rate_ctr_inc(&conn->client->ctrg->ctr[CLIENT_CTR_PKTS]);
+ switch (conn->protocol) {
+ case PROTOCOL_OSMOPCAP:
+ 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 osmo_pcap_pkthdr *) msg->l2h;
+ hdr->ts_sec = in_hdr->ts.tv_sec;
+ hdr->ts_usec = in_hdr->ts.tv_usec;
+ hdr->caplen = in_hdr->caplen;
+ hdr->len = in_hdr->len;
+
+ msg->l3h = msgb_put(msg, in_hdr->caplen);
+ memcpy(msg->l3h, data, in_hdr->caplen);
+
+ om_hdr->len = htons(msgb_l2len(msg));
+ rate_ctr_add(&conn->client->ctrg->ctr[CLIENT_CTR_BYTES], hdr->caplen);
+ rate_ctr_inc(&conn->client->ctrg->ctr[CLIENT_CTR_PKTS]);
+ break;
+ case PROTOCOL_IPIP:
+ offset = get_iphdr_offset(pcap_datalink(conn->client->handle));
+ if (offset < 0) {
+ msgb_free(msg);
+ return;
+ }
+ ip_len = in_hdr->caplen - offset;
+ if (ip_len < 0) {
+ msgb_free(msg);
+ return;
+ }
+ msg->l2h = msgb_put(msg, ip_len);
+ memcpy(msg->l2h, data+offset, ip_len);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
write_data(conn, msg);
}
@@ -197,6 +230,10 @@ void osmo_client_send_link(struct osmo_pcap_client_conn *conn)
struct osmo_pcap_data *om_hdr;
struct msgb *msg;
+ /* IPIP encapsulation has no linktype header */
+ if (conn->protocol == PROTOCOL_IPIP)
+ return;
+
if (!conn->client->handle) {
LOGP(DCLIENT, LOGL_ERROR,
"No pcap_handle not sending link info to conn=%s\n", conn->name);
@@ -229,6 +266,8 @@ void osmo_client_send_link(struct osmo_pcap_client_conn *conn)
void osmo_client_connect(struct osmo_pcap_client_conn *conn)
{
int rc;
+ uint16_t srv_port;
+ int sock_type, sock_proto;
osmo_client_disconnect(conn);
@@ -236,9 +275,25 @@ void osmo_client_connect(struct osmo_pcap_client_conn *conn)
conn->wqueue.write_cb = write_cb;
osmo_wqueue_clear(&conn->wqueue);
- rc = osmo_sock_init2_ofd(&conn->wqueue.bfd, AF_INET, SOCK_STREAM, IPPROTO_TCP,
- conn->source_ip, 0,
- conn->srv_ip, conn->srv_port,
+ switch (conn->protocol) {
+ case PROTOCOL_OSMOPCAP:
+ srv_port = conn->srv_port;
+ sock_type = SOCK_STREAM;
+ sock_proto = IPPROTO_TCP;
+ break;
+ case PROTOCOL_IPIP:
+ srv_port = 0;
+ sock_type = SOCK_RAW;
+ sock_proto = IPPROTO_IPIP;
+ conn->wqueue.bfd.when = BSC_FD_WRITE;
+ break;
+ default:
+ OSMO_ASSERT(0);
+ break;
+ }
+
+ rc = osmo_sock_init2_ofd(&conn->wqueue.bfd, AF_INET, sock_type, sock_proto,
+ conn->source_ip, 0, conn->srv_ip, srv_port,
OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_NONBLOCK);
if (rc < 0) {
LOGP(DCLIENT, LOGL_ERROR,
@@ -251,7 +306,10 @@ void osmo_client_connect(struct osmo_pcap_client_conn *conn)
rate_ctr_inc(&conn->client->ctrg->ctr[CLIENT_CTR_CONNECT]);
conn->wqueue.bfd.cb = conn_cb;
conn->wqueue.bfd.data = conn;
- conn->wqueue.bfd.when = BSC_FD_READ | BSC_FD_WRITE;
+ if (conn->protocol == PROTOCOL_IPIP)
+ conn->wqueue.bfd.when = BSC_FD_WRITE;
+ else
+ conn->wqueue.bfd.when = BSC_FD_READ | BSC_FD_WRITE;
}
void osmo_client_reconnect(struct osmo_pcap_client_conn *conn)
diff --git a/src/osmo_client_vty.c b/src/osmo_client_vty.c
index 4cd2908..29f7051 100644
--- a/src/osmo_client_vty.c
+++ b/src/osmo_client_vty.c
@@ -31,6 +31,12 @@
#define PCAP_STRING "PCAP related functions\n"
#define SERVER_STRING "Server string\n"
+static const struct value_string osmopcap_protocol_names[] = {
+ { PROTOCOL_OSMOPCAP, "osmo-pcap" },
+ { PROTOCOL_IPIP, "ipip" },
+ { 0, NULL }
+};
+
static struct osmo_pcap_client_conn *get_conn(struct vty *vty)
{
if (vty->node == CLIENT_NODE)
@@ -94,6 +100,10 @@ static void write_client_conn_data(
if (conn->source_ip)
vty_out(vty, "%s source ip %s%s", indent,
conn->source_ip, VTY_NEWLINE);
+
+ if (conn->protocol != PROTOCOL_OSMOPCAP)
+ vty_out(vty, "%s protocol %s%s", indent,
+ get_value_string(osmopcap_protocol_names, conn->protocol), VTY_NEWLINE);
}
static int config_write_server(struct vty *vty)
@@ -466,6 +476,34 @@ DEFUN(cfg_client_disconnect,
return CMD_SUCCESS;
}
+#define PROTOCOL_STR "protocol (osmo-pcap|ipip)"
+#define PROTOCOL_HELP "Configure the Protocol used for transfer\n" \
+ "OsmoPCAP protocol (over TCP)\n" \
+ "IPIP encapsulation (for real-time streaming to wireshark)\n"
+
+DEFUN(cfg_protocol,
+ cfg_protocol_cmd,
+ PROTOCOL_STR,
+ PROTOCOL_HELP)
+{
+ struct osmo_pcap_client_conn *conn = get_conn(vty);
+
+ conn->protocol = get_string_value(osmopcap_protocol_names, argv[0]);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_client_protocol,
+ cfg_client_protocol_cmd,
+ PROTOCOL_STR,
+ PROTOCOL_HELP)
+{
+ struct osmo_pcap_client_conn *conn = get_conn(vty);
+
+ conn->protocol = get_string_value(osmopcap_protocol_names, argv[0]);
+ return CMD_SUCCESS;
+}
+
+
int vty_client_init(struct osmo_pcap_client *pcap)
{
install_element(CONFIG_NODE, &cfg_client_cmd);
@@ -482,6 +520,7 @@ int vty_client_init(struct osmo_pcap_client *pcap)
install_element(CLIENT_NODE, &cfg_server_ip_cmd);
install_element(CLIENT_NODE, &cfg_server_port_cmd);
install_element(CLIENT_NODE, &cfg_source_ip_cmd);
+ install_element(CLIENT_NODE, &cfg_protocol_cmd);
install_element(CLIENT_NODE, &cfg_enable_tls_cmd);
install_element(CLIENT_NODE, &cfg_disable_tls_cmd);
@@ -526,6 +565,7 @@ int vty_client_init(struct osmo_pcap_client *pcap)
install_element(CLIENT_SERVER_NODE, &cfg_tls_log_level_cmd);
install_element(CLIENT_SERVER_NODE, &cfg_client_connect_cmd);
install_element(CLIENT_SERVER_NODE, &cfg_client_disconnect_cmd);
+ install_element(CLIENT_SERVER_NODE, &cfg_client_protocol_cmd);
return 0;
}