gprs: Add a custom GPRS filter

Allow to inspect UDP messages and check for GPRS, NS, BSSGP
and then filter LLC frames. Parsing the vL datastructure with
the libpcap syntax is a pain. It could be done using BPF but
we do not want to use bpf asm to specify the entire ruleset.

I looked into using libepan/libwireshark but this has memory
issues and is painful too. So let's parse UDP, NS, BSSGP using
the info we already have. I tried a bit of editcap to generate
a bit of broken data. The length check might still be bad.

I used my crash_20100602.pcap file to count the LLC frames we
detect and compare that to wireshark it ended with the right
number.

  pcap add-filter gprs

can be used to enable the new filtering option after the OS
has received the packet.

Fixes: ONW#1314
diff --git a/src/osmo_client_vty.c b/src/osmo_client_vty.c
index 0b30eb7..a8739b1 100644
--- a/src/osmo_client_vty.c
+++ b/src/osmo_client_vty.c
@@ -59,6 +59,8 @@
 			pcap_client->filter_string, VTY_NEWLINE);
 	vty_out(vty, " pcap detect-loop %d%s",
 		pcap_client->filter_itself, VTY_NEWLINE);
+	if (pcap_client->gprs_filtering)
+		vty_out(vty, " pcap add-filter gprs%s", VTY_NEWLINE);
 
 	if (pcap_client->srv_ip)
 		vty_out(vty, " server ip %s%s",
@@ -80,6 +82,24 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_client_add_gprs,
+      cfg_client_add_gprs_cmd,
+      "pcap add-filter gprs",
+      PCAP_STRING "Add-filter\n" "Custom filtering for GPRS\n")
+{
+	pcap_client->gprs_filtering = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_client_del_gprs,
+      cfg_client_del_gprs_cmd,
+      "no pcap add-filter gprs",
+      NO_STR PCAP_STRING "Add-filter\n" "Custom filter for GPRS\n")
+{
+	pcap_client->gprs_filtering = 0;
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_client_filter,
       cfg_client_filter_cmd,
       "pcap filter .NAME",
@@ -144,5 +164,8 @@
 	install_element(CLIENT_NODE, &cfg_server_ip_cmd);
 	install_element(CLIENT_NODE, &cfg_server_port_cmd);
 
+	install_element(CLIENT_NODE, &cfg_client_add_gprs_cmd);
+	install_element(CLIENT_NODE, &cfg_client_del_gprs_cmd);
+
 	return 0;
 }