Harald Welte has submitted this change and it was merged.

Change subject: Add support for generating IPIP to osmo-pcap-client
......................................................................


Add support for generating IPIP to osmo-pcap-client

This allows the user to change the configuration between either using

a) the classic OsmoPCAP protocol (over TCP with or without TLS)
   which is used when you want to talk to an osmo-pcap-server

b) the (new) IPIP encapsulation, which will simply take the IP
   packet (without Ethernet or pcap header) and transmit it inside IPIP
   to the specified server IP address.  This is useful for gettin
   real-time streaming into wireshark.

Change-Id: I8056fc163ac2f15adcb964d867dd5e51df4e4710
---
M include/osmo-pcap/osmo_pcap_client.h
M src/osmo_client_network.c
M src/osmo_client_vty.c
3 files changed, 121 insertions(+), 17 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



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 @@
        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 @@
        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 @@
        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 @@
                return;
        }
 
-       om_hdr = (struct osmo_pcap_data *) msgb_put(msg, sizeof(*om_hdr));
-       om_hdr->type = PKT_LINK_DATA;
+       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->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);
+               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]);
+               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);
 }
@@ -196,6 +229,10 @@
        struct pcap_file_header *hdr;
        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,
@@ -229,6 +266,8 @@
 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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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;
 }

-- 
To view, visit https://gerrit.osmocom.org/6345
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I8056fc163ac2f15adcb964d867dd5e51df4e4710
Gerrit-PatchSet: 1
Gerrit-Project: osmo-pcap
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder

Reply via email to