aboutsummaryrefslogtreecommitdiffstats
path: root/tests/osmo-pcap-test
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2017-04-20 12:44:04 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2017-08-08 20:39:16 +0200
commit6032a35be84c87607e295e46f1e37d3dd4e5f1b1 (patch)
tree1f6adc9e2508132727c9ff839fd7c4ce4f08b69e /tests/osmo-pcap-test
parent76c0acb149a03e6d7945e0ee4f4c6355381b7391 (diff)
tests: osmo-pcap: Allow different l2 pkts
Before this patch, ETH was assumed and other types were not supported. This patch also adds Linux cooked packet support for L2. Change-Id: Ie62fa0a8e45e1e141edb64b116dad185ad9c7a5f
Diffstat (limited to 'tests/osmo-pcap-test')
-rw-r--r--tests/osmo-pcap-test/Makefile.am2
-rw-r--r--tests/osmo-pcap-test/l2_eth.c48
-rw-r--r--tests/osmo-pcap-test/l2_sll.c47
-rw-r--r--tests/osmo-pcap-test/l3_ipv4.c12
-rw-r--r--tests/osmo-pcap-test/l4_tcp.c4
-rw-r--r--tests/osmo-pcap-test/l4_udp.c4
-rw-r--r--tests/osmo-pcap-test/pcap.c50
-rw-r--r--tests/osmo-pcap-test/proto.c36
-rw-r--r--tests/osmo-pcap-test/proto.h36
9 files changed, 189 insertions, 50 deletions
diff --git a/tests/osmo-pcap-test/Makefile.am b/tests/osmo-pcap-test/Makefile.am
index a256005..3e5bdf1 100644
--- a/tests/osmo-pcap-test/Makefile.am
+++ b/tests/osmo-pcap-test/Makefile.am
@@ -3,6 +3,8 @@ include $(top_srcdir)/Make_global.am
check_PROGRAMS = osmo-pcap-test
osmo_pcap_test_SOURCES = proto.c \
+ l2_eth.c \
+ l2_sll.c \
l3_ipv4.c \
l4_tcp.c \
l4_udp.c \
diff --git a/tests/osmo-pcap-test/l2_eth.c b/tests/osmo-pcap-test/l2_eth.c
new file mode 100644
index 0000000..3171fd7
--- /dev/null
+++ b/tests/osmo-pcap-test/l2_eth.c
@@ -0,0 +1,48 @@
+/*
+ * (C) 2012 by Pablo Neira Ayuso <pablo@gnumonks.org>
+ * (C) 2012 by On Waves ehf <http://www.on-waves.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later vers
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <linux/if_ether.h>
+#include <pcap/dlt.h>
+
+#include "proto.h"
+
+#define PRINT_CMP(...)
+
+static int unsigned l2_eth_pkt_l3proto_num(const uint8_t *pkt)
+{
+ const struct ethhdr *eh = (const struct ethhdr *)pkt;
+ switch(ntohs(eh->h_proto)) {
+ case ETH_P_IP:
+ return htons(AF_INET);
+ default:
+ return eh->h_proto;
+ }
+}
+
+static unsigned int l2_eth_pkt_l2hdr_len(const uint8_t *pkt)
+{
+
+ return ETH_HLEN;
+}
+
+static struct osmo_pcap_proto_l2 eth = {
+ //.l2protonum = ETH_P_IP,
+ .l2protonum = DLT_EN10MB,
+ .l2pkt_hdr_len = l2_eth_pkt_l2hdr_len,
+ .l3pkt_proto = l2_eth_pkt_l3proto_num,
+};
+
+void l2_eth_init(void)
+{
+ osmo_pcap_proto_l2_register(&eth);
+}
diff --git a/tests/osmo-pcap-test/l2_sll.c b/tests/osmo-pcap-test/l2_sll.c
new file mode 100644
index 0000000..5a600ff
--- /dev/null
+++ b/tests/osmo-pcap-test/l2_sll.c
@@ -0,0 +1,47 @@
+/*
+ * (C) 2012 by Pablo Neira Ayuso <pablo@gnumonks.org>
+ * (C) 2012 by On Waves ehf <http://www.on-waves.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later vers
+ */
+
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+#include <pcap/sll.h>
+#include <pcap/dlt.h>
+
+#include "proto.h"
+
+#define PRINT_CMP(...)
+
+static unsigned int l2_sll_pkt_l3proto_num(const uint8_t *pkt)
+{
+ const struct sll_header *lh = (const struct sll_header *)pkt;
+ switch(ntohs(lh->sll_protocol)) {
+ case ETH_P_IP:
+ return htons(AF_INET);
+ default:
+ return lh->sll_protocol;
+ }
+}
+
+static unsigned int l2_sll_pkt_l2hdr_len(const uint8_t *pkt)
+{
+
+ return SLL_HDR_LEN;
+}
+
+static struct osmo_pcap_proto_l2 sll = {
+ .l2protonum = DLT_LINUX_SLL,
+ .l2pkt_hdr_len = l2_sll_pkt_l2hdr_len,
+ .l3pkt_proto = l2_sll_pkt_l3proto_num,
+};
+
+void l2_sll_init(void)
+{
+ osmo_pcap_proto_l2_register(&sll);
+}
diff --git a/tests/osmo-pcap-test/l3_ipv4.c b/tests/osmo-pcap-test/l3_ipv4.c
index 83e3479..521a803 100644
--- a/tests/osmo-pcap-test/l3_ipv4.c
+++ b/tests/osmo-pcap-test/l3_ipv4.c
@@ -16,29 +16,27 @@
#define PRINT_CMP(...)
-static int l3_ipv4_pkt_l4proto_num(const uint8_t *pkt)
+static unsigned int l3_ipv4_pkt_l4proto_num(const uint8_t *pkt)
{
const struct iphdr *iph = (const struct iphdr *)pkt;
return iph->protocol;
}
-static int l3_ipv4_pkt_l3hdr_len(const uint8_t *pkt)
+static unsigned int l3_ipv4_pkt_l3hdr_len(const uint8_t *pkt)
{
const struct iphdr *iph = (const struct iphdr *)pkt;
return iph->ihl << 2;
}
-static struct osmo_pcap_proto_l2l3 ipv4 = {
- .l2protonum = ETH_P_IP,
+static struct osmo_pcap_proto_l3 ipv4 = {
.l3protonum = AF_INET,
- .l2hdr_len = ETH_HLEN,
.l3pkt_hdr_len = l3_ipv4_pkt_l3hdr_len,
.l4pkt_proto = l3_ipv4_pkt_l4proto_num,
};
-void l2l3_ipv4_init(void)
+void l3_ipv4_init(void)
{
- osmo_pcap_proto_l2l3_register(&ipv4);
+ osmo_pcap_proto_l3_register(&ipv4);
}
diff --git a/tests/osmo-pcap-test/l4_tcp.c b/tests/osmo-pcap-test/l4_tcp.c
index 1e024b5..f7aedbd 100644
--- a/tests/osmo-pcap-test/l4_tcp.c
+++ b/tests/osmo-pcap-test/l4_tcp.c
@@ -13,14 +13,14 @@
#include "proto.h"
-static int l4_tcp_pkt_hdr_len(const uint8_t *pkt)
+static unsigned int l4_tcp_pkt_hdr_len(const uint8_t *pkt)
{
const struct tcphdr *tcph = (const struct tcphdr *)pkt;
return tcph->doff << 2;
}
-static int l4_tcp_pkt_no_data(const uint8_t *pkt)
+static unsigned int l4_tcp_pkt_no_data(const uint8_t *pkt)
{
const struct tcphdr *tcph = (const struct tcphdr *)pkt;
return tcph->syn || tcph->fin || tcph->rst || !tcph->psh;
diff --git a/tests/osmo-pcap-test/l4_udp.c b/tests/osmo-pcap-test/l4_udp.c
index 9ffa77b..1733908 100644
--- a/tests/osmo-pcap-test/l4_udp.c
+++ b/tests/osmo-pcap-test/l4_udp.c
@@ -13,12 +13,12 @@
#include "proto.h"
-static int l4_udp_pkt_hdr_len(const uint8_t *pkt)
+static unsigned int l4_udp_pkt_hdr_len(const uint8_t *pkt)
{
return sizeof(struct udphdr);
}
-static int l4_udp_pkt_no_data(const uint8_t *pkt)
+static unsigned int l4_udp_pkt_no_data(const uint8_t *pkt)
{
/* UDP has no control packets. */
return 0;
diff --git a/tests/osmo-pcap-test/pcap.c b/tests/osmo-pcap-test/pcap.c
index 61408f8..f9304b9 100644
--- a/tests/osmo-pcap-test/pcap.c
+++ b/tests/osmo-pcap-test/pcap.c
@@ -34,6 +34,7 @@ struct osmo_pcap_test_stats {
uint32_t pkts;
uint32_t skip;
uint32_t processed;
+ uint32_t unsupported_l2;
uint32_t unsupported_l3;
uint32_t unsupported_l4;
} osmo_pcap_test_stats;
@@ -41,21 +42,22 @@ struct osmo_pcap_test_stats {
static int
osmo_pcap_process_packet(struct msgb **msgptr,
const uint8_t *pkt, uint32_t pktlen,
- struct osmo_pcap_proto_l2l3 *l3h,
+ struct osmo_pcap_proto_l2 *l2h,
+ struct osmo_pcap_proto_l3 *l3h,
struct osmo_pcap_proto_l4 *l4h,
int (*cb)(struct msgb *msgb))
{
- unsigned int l3hdr_len, skip_hdr_len;
+ unsigned int l2hdr_len, l3hdr_len, skip_hdr_len;
struct msgb *msgb;
- int ret;
/* skip layer 2, 3 and 4 headers */
- l3hdr_len = l3h->l3pkt_hdr_len(pkt + ETH_HLEN);
- skip_hdr_len = l3h->l2hdr_len + l3hdr_len +
- l4h->l4pkt_hdr_len(pkt + ETH_HLEN + l3hdr_len);
+ l2hdr_len = l2h->l2pkt_hdr_len(pkt);
+ l3hdr_len = l3h->l3pkt_hdr_len(pkt + l2hdr_len);
+ skip_hdr_len = l2hdr_len + l3hdr_len +
+ l4h->l4pkt_hdr_len(pkt + l2hdr_len + l3hdr_len);
/* This packet contains no data, skip it. */
- if (l4h->l4pkt_no_data(pkt + l3hdr_len + ETH_HLEN)) {
+ if (l4h->l4pkt_no_data(pkt + l2hdr_len + l3hdr_len)) {
osmo_pcap_test_stats.skip++;
return -1;
}
@@ -101,10 +103,11 @@ void osmo_pcap_test_close(pcap_t *handle)
int
osmo_pcap_test_run(struct osmo_pcap *p, uint8_t pnum, int (*cb)(struct msgb *msgb))
{
- struct osmo_pcap_proto_l2l3 *l3h;
+ struct osmo_pcap_proto_l2 *l2h;
+ struct osmo_pcap_proto_l3 *l3h;
struct osmo_pcap_proto_l4 *l4h;
struct pcap_pkthdr pcaph;
- const u_char *pkt;
+ const u_char *l2pkt, *l3pkt;
struct timeval res;
uint8_t l4protonum;
@@ -115,26 +118,34 @@ osmo_pcap_test_run(struct osmo_pcap *p, uint8_t pnum, int (*cb)(struct msgb *msg
}
retry:
- pkt = pcap_next(p->h, &pcaph);
- if (pkt == NULL)
+ l2pkt = pcap_next(p->h, &pcaph);
+ if (l2pkt == NULL)
return -1;
osmo_pcap_test_stats.pkts++;
- l3h = osmo_pcap_proto_l2l3_find(pkt);
+ int linktype = pcap_datalink(p->h);
+ l2h = osmo_pcap_proto_l2_find(linktype);
+ if (l2h == NULL) {
+ osmo_pcap_test_stats.unsupported_l2++;
+ goto retry;
+ }
+
+ l3h = osmo_pcap_proto_l3_find(l2h->l3pkt_proto(l2pkt));
if (l3h == NULL) {
osmo_pcap_test_stats.unsupported_l3++;
goto retry;
}
- l4protonum = l3h->l4pkt_proto(pkt + ETH_HLEN);
+ l3pkt = l2pkt + l2h->l2pkt_hdr_len(l2pkt);
+ l4protonum = l3h->l4pkt_proto(l3pkt);
/* filter l4 protocols we are not interested in */
if (l4protonum != pnum) {
osmo_pcap_test_stats.skip++;
goto retry;
}
- l4h = osmo_pcap_proto_l4_find(pkt, l4protonum);
+ l4h = osmo_pcap_proto_l4_find(l4protonum);
if (l4h == NULL) {
osmo_pcap_test_stats.unsupported_l4++;
goto retry;
@@ -145,7 +156,7 @@ retry:
memcpy(&p->last, &pcaph.ts, sizeof(struct timeval));
/* retry with next packet if this has been skipped. */
- if (osmo_pcap_process_packet(&p->deliver_msg, pkt, pcaph.caplen, l3h, l4h, cb) < 0)
+ if (osmo_pcap_process_packet(&p->deliver_msg, l2pkt, pcaph.caplen, l2h, l3h, l4h, cb) < 0)
goto retry;
/* calculate waiting time */
@@ -161,19 +172,22 @@ retry:
void osmo_pcap_stats_printf(void)
{
- printf("pkts=%d processed=%d skip=%d "
+ printf("pkts=%d processed=%d skip=%d unsupported_l2=%d "
"unsupported_l3=%d unsupported_l4=%d\n",
osmo_pcap_test_stats.pkts,
osmo_pcap_test_stats.processed,
osmo_pcap_test_stats.skip,
+ osmo_pcap_test_stats.unsupported_l2,
osmo_pcap_test_stats.unsupported_l3,
osmo_pcap_test_stats.unsupported_l4);
}
void osmo_pcap_init(void)
{
- /* Initialization of supported layer 3 and 4 protocols here. */
- l2l3_ipv4_init();
+ /* Initialization of supported layer 2, 3 and 4 protocols here. */
+ l2_eth_init();
+ l2_sll_init();
+ l3_ipv4_init();
l4_tcp_init();
l4_udp_init();
}
diff --git a/tests/osmo-pcap-test/proto.c b/tests/osmo-pcap-test/proto.c
index f90f07c..085ca25 100644
--- a/tests/osmo-pcap-test/proto.c
+++ b/tests/osmo-pcap-test/proto.c
@@ -15,28 +15,46 @@
#include <osmocom/core/linuxlist.h>
#include "proto.h"
-static LLIST_HEAD(l2l3_proto_list);
+static LLIST_HEAD(l2_proto_list);
+static LLIST_HEAD(l3_proto_list);
static LLIST_HEAD(l4_proto_list);
+#include <stdio.h>
-struct osmo_pcap_proto_l2l3 *osmo_pcap_proto_l2l3_find(const uint8_t *pkt)
+struct osmo_pcap_proto_l2 *osmo_pcap_proto_l2_find(unsigned int pcap_linktype)
{
- const struct ethhdr *eh = (const struct ethhdr *)pkt;
- struct osmo_pcap_proto_l2l3 *cur;
+ struct osmo_pcap_proto_l2 *cur;
- llist_for_each_entry(cur, &l2l3_proto_list, head) {
- if (ntohs(cur->l2protonum) == eh->h_proto)
+ llist_for_each_entry(cur, &l2_proto_list, head) {
+ if (cur->l2protonum == pcap_linktype)
return cur;
}
return NULL;
}
-void osmo_pcap_proto_l2l3_register(struct osmo_pcap_proto_l2l3 *h)
+void osmo_pcap_proto_l2_register(struct osmo_pcap_proto_l2 *h)
{
- llist_add(&h->head, &l2l3_proto_list);
+ llist_add(&h->head, &l2_proto_list);
+}
+
+
+struct osmo_pcap_proto_l3 *osmo_pcap_proto_l3_find(unsigned int l3protocol)
+{
+ struct osmo_pcap_proto_l3 *cur;
+
+ llist_for_each_entry(cur, &l3_proto_list, head) {
+ if (ntohs(cur->l3protonum) == l3protocol)
+ return cur;
+ }
+ return NULL;
+}
+
+void osmo_pcap_proto_l3_register(struct osmo_pcap_proto_l3 *h)
+{
+ llist_add(&h->head, &l3_proto_list);
}
struct osmo_pcap_proto_l4 *
-osmo_pcap_proto_l4_find(const uint8_t *pkt, unsigned int l4protocol)
+osmo_pcap_proto_l4_find(unsigned int l4protocol)
{
struct osmo_pcap_proto_l4 *cur;
diff --git a/tests/osmo-pcap-test/proto.h b/tests/osmo-pcap-test/proto.h
index 8cb41ed..2580058 100644
--- a/tests/osmo-pcap-test/proto.h
+++ b/tests/osmo-pcap-test/proto.h
@@ -10,30 +10,42 @@ struct osmo_pcap_proto_l4 {
unsigned int l4protonum;
- int (*l4pkt_hdr_len)(const uint8_t *pkt);
- int (*l4pkt_no_data)(const uint8_t *pkt);
+ unsigned int (*l4pkt_hdr_len)(const uint8_t *pkt);
+ unsigned int (*l4pkt_no_data)(const uint8_t *pkt);
};
-struct osmo_pcap_proto_l2l3 {
+struct osmo_pcap_proto_l3 {
struct llist_head head;
- unsigned int l2protonum;
- unsigned int l2hdr_len;
-
unsigned int l3protonum;
- int (*l3pkt_hdr_len)(const uint8_t *pkt);
- int (*l4pkt_proto)(const uint8_t *pkt);
+ unsigned int (*l3pkt_hdr_len)(const uint8_t *pkt);
+ unsigned int (*l4pkt_proto)(const uint8_t *pkt);
+};
+
+struct osmo_pcap_proto_l2 {
+ struct llist_head head;
+
+ unsigned int l2protonum;
+
+ unsigned int (*l2pkt_hdr_len)(const uint8_t *pkt);
+ unsigned int (*l3pkt_proto)(const uint8_t *pkt);
};
-struct osmo_pcap_proto_l2l3 *osmo_pcap_proto_l2l3_find(const uint8_t *pkt);
-void osmo_pcap_proto_l2l3_register(struct osmo_pcap_proto_l2l3 *h);
-struct osmo_pcap_proto_l4 *osmo_pcap_proto_l4_find(const uint8_t *pkt, unsigned int l4protonum);
+struct osmo_pcap_proto_l2 *osmo_pcap_proto_l2_find(unsigned int pcap_linktype);
+void osmo_pcap_proto_l2_register(struct osmo_pcap_proto_l2 *h);
+
+struct osmo_pcap_proto_l3 *osmo_pcap_proto_l3_find(unsigned int l3protonum);
+void osmo_pcap_proto_l3_register(struct osmo_pcap_proto_l3 *h);
+
+struct osmo_pcap_proto_l4 *osmo_pcap_proto_l4_find(unsigned int l4protonum);
void osmo_pcap_proto_l4_register(struct osmo_pcap_proto_l4 *h);
/* Initialization of supported protocols here. */
-void l2l3_ipv4_init(void);
+void l2_sll_init(void);
+void l2_eth_init(void);
+void l3_ipv4_init(void);
void l4_tcp_init(void);
void l4_udp_init(void);