diff options
-rw-r--r-- | include/osmo-pcap/osmo_pcap_client.h | 6 | ||||
-rw-r--r-- | src/osmo_client_network.c | 98 | ||||
-rw-r--r-- | src/osmo_client_vty.c | 40 |
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; } |