aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2017-12-01 03:31:20 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2017-12-01 03:31:20 +0100
commitce28c210871a248ec6d836adeaa75e2c3c665faf (patch)
tree2d9adb780ac3dadf064b9f0e32e811939bb4859a /contrib
parent0af6a32d98640742c14cb7ea3506c3070e25b9f0 (diff)
DROP openbsc PATH ELEMENT FOR MERGING
Diffstat (limited to 'contrib')
-rw-r--r--contrib/a-link/sccp-split-by-con.lua170
-rw-r--r--contrib/bsc-test/README1
-rw-r--r--contrib/bsc-test/all_dial8
-rwxr-xr-xcontrib/bsc-test/dial.sh11
-rwxr-xr-xcontrib/bsc-test/drop-oml.sh6
-rwxr-xr-xcontrib/bsc-test/drop.sh8
-rw-r--r--contrib/bsc-test/hangup4
-rwxr-xr-xcontrib/bsc-test/msc.sh8
-rwxr-xr-xcontrib/bsc_control.py104
-rwxr-xr-xcontrib/bt.py33
-rwxr-xr-xcontrib/convert_to_enum.py37
-rwxr-xr-xcontrib/gprs/gb-proxy-unblock-bug.py58
-rw-r--r--contrib/gprs/gprs-bssgp-histogram.lua78
-rw-r--r--contrib/gprs/gprs-buffer-count.lua80
-rw-r--r--contrib/gprs/gprs-split-trace-by-tlli.lua46
-rw-r--r--contrib/gprs/gprs-verify-nu.lua59
-rw-r--r--contrib/hlr-remove-old.sql18
-rwxr-xr-xcontrib/mgcp_server.py60
-rw-r--r--contrib/nat/test_regexp.c30
-rw-r--r--contrib/rtp/rtp_replay.st17
-rw-r--r--contrib/rtp/rtp_replay_shared.st108
-rw-r--r--contrib/rtp/rtp_replay_sip.st87
-rw-r--r--contrib/rtp/timestamp_rtp.lua28
-rw-r--r--contrib/sms/fill-hlr.st66
-rw-r--r--contrib/sms/hlr-query.st10
-rw-r--r--contrib/sms/sqlite-probe.tap.d5
-rw-r--r--contrib/systemd/osmo-bsc-mgcp.service9
-rw-r--r--contrib/systemd/osmo-bsc.service10
-rw-r--r--contrib/systemd/osmo-nitb.service9
29 files changed, 1168 insertions, 0 deletions
diff --git a/contrib/a-link/sccp-split-by-con.lua b/contrib/a-link/sccp-split-by-con.lua
new file mode 100644
index 000000000..f5d5502ae
--- /dev/null
+++ b/contrib/a-link/sccp-split-by-con.lua
@@ -0,0 +1,170 @@
+-- Split trace based on SCCP Source
+-- There are still bugs to find... bugs bugs bugs... hmm
+do
+ local function init_listener()
+ print("CREATED LISTENER")
+ local tap = Listener.new("ip", "sccp && (ip.src == 172.16.1.81 || ip.dst == 172.16.1.81)")
+ local sccp_type_field = Field.new("sccp.message_type")
+ local sccp_src_field = Field.new("sccp.slr")
+ local sccp_dst_field = Field.new("sccp.dlr")
+ local msg_type_field = Field.new("gsm_a.dtap_msg_mm_type")
+ local lu_rej_field = Field.new("gsm_a.dtap.rej_cause")
+ local ip_src_field = Field.new("ip.src")
+ local ip_dst_field = Field.new("ip.dst")
+
+ --
+ local bssmap_msgtype_field = Field.new("gsm_a.bssmap_msgtype")
+ -- assignment failure 0x03
+ --
+
+ --
+ local dtap_cause_field = Field.new("gsm_a_dtap.cause")
+ local dtap_cc_field = Field.new("gsm_a.dtap_msg_cc_type")
+
+ local connections = {}
+
+ function check_failure(con)
+ check_lu_reject(con)
+ check_disconnect(con)
+ check_failures(con)
+ end
+
+ -- cipher mode reject
+ function check_failures(con)
+ local msgtype = bssmap_msgtype_field()
+ if not msgtype then
+ return
+ end
+
+ msgtype = tonumber(msgtype)
+ if msgtype == 89 then
+ print("Cipher mode reject")
+ con[4] = true
+ elseif msgtype == 0x03 then
+ print("Assignment failure")
+ con[4] = true
+ elseif msgtype == 0x22 then
+ print("Clear Request... RF failure?")
+ con[4] = true
+ end
+ end
+
+ -- check if a DISCONNECT is normal
+ function check_disconnect(con)
+ local msg_type = dtap_cc_field()
+ if not msg_type then
+ return
+ end
+
+ if tonumber(msg_type) ~= 0x25 then
+ return
+ end
+
+ local cause = dtap_cause_field()
+ if not cause then
+ return
+ end
+
+ cause = tonumber(cause)
+ if cause ~= 0x10 then
+ print("DISCONNECT != Normal")
+ con[4] = true
+ end
+ end
+
+ -- check if we have a LU Reject
+ function check_lu_reject(con)
+ local msg_type = msg_type_field()
+ if not msg_type then
+ return
+ end
+
+ msg_type = tonumber(tostring(msg_type))
+ if msg_type == 0x04 then
+ print("LU REJECT with " .. tostring(lu_rej_field()))
+ con[4] = true
+ end
+ end
+
+ function tap.packet(pinfo,tvb,ip)
+ local ip_src = tostring(ip_src_field())
+ local ip_dst = tostring(ip_dst_field())
+ local sccp_type = tonumber(tostring(sccp_type_field()))
+ local sccp_src = sccp_src_field()
+ local sccp_dst = sccp_dst_field()
+
+ local con
+
+ if sccp_type == 0x01 then
+ elseif sccp_type == 0x2 then
+ local src = string.format("%s-%s", ip_src, tostring(sccp_src))
+ local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
+ local datestring = os.date("%Y%m%d%H%M%S")
+ local pcap_name = string.format("alink_trace_%s-%s_%s.pcap", src, dst, datestring)
+ local dumper = Dumper.new_for_current(pcap_name)
+
+ local con = { ip_src, tostring(sccp_src), tostring(sccp_dst), false, dumper, pcap_name }
+
+ dumper:dump_current()
+ connections[src] = con
+ connections[dst] = con
+ elseif sccp_type == 0x4 then
+ -- close a connection... remove it from the list
+ local src = string.format("%s-%s", ip_src, tostring(sccp_src))
+ local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
+
+ local con = connections[src]
+ if not con then
+ return
+ end
+
+ con[5]:dump_current()
+ con[5]:flush()
+
+ -- this causes a crash on unpacted wireshark
+ con[5]:close()
+
+ -- the connection had a failure
+ if con[4] == true then
+ local datestring = os.date("%Y%m%d%H%M%S")
+ local new_name = string.format("alink_failure_%s_%s-%s.pcap", datestring, con[2], con[3])
+ os.rename(con[6], new_name)
+ else
+ os.remove(con[6])
+ end
+
+
+ -- clear the old connection
+ connections[src] = nil
+ connections[dst] = nil
+
+ elseif sccp_type == 0x5 then
+ -- not handled yet... we should verify stuff here...
+ local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
+ local con = connections[dst]
+ if not con then
+ return
+ end
+ con[5]:dump_current()
+ elseif sccp_type == 0x6 then
+ local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
+ local con = connections[dst]
+ if not con then
+ print("DON'T KNOW THIS CONNECTION for " .. ip_dst)
+ return
+ end
+ con[5]:dump_current()
+ check_failure(con)
+ end
+
+ end
+ function tap.draw()
+ print("DRAW")
+ end
+ function tap.reset()
+ print("RESET")
+ end
+ end
+
+ init_listener()
+end
diff --git a/contrib/bsc-test/README b/contrib/bsc-test/README
new file mode 100644
index 000000000..adb222e21
--- /dev/null
+++ b/contrib/bsc-test/README
@@ -0,0 +1 @@
+Some crazy scripts call testing... and MSC link failure simulation
diff --git a/contrib/bsc-test/all_dial b/contrib/bsc-test/all_dial
new file mode 100644
index 000000000..96e5f00b3
--- /dev/null
+++ b/contrib/bsc-test/all_dial
@@ -0,0 +1,8 @@
+ABORT BUSY
+ABORT 'NO CARRIER'
+ABORT 'OK'
+
+'' AT
+SAY "Dialing a number\n"
+'OK' ATD05660066;
+
diff --git a/contrib/bsc-test/dial.sh b/contrib/bsc-test/dial.sh
new file mode 100755
index 000000000..e5e19f63e
--- /dev/null
+++ b/contrib/bsc-test/dial.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Evil dial script..
+
+while true;
+do
+ chat -v -f all_dial < /dev/ttyACM0 > /dev/ttyACM0
+ sleep 5s
+ chat -v -f hangup < /dev/ttyACM0 > /dev/ttyACM0
+ sleep 2s
+done
+
diff --git a/contrib/bsc-test/drop-oml.sh b/contrib/bsc-test/drop-oml.sh
new file mode 100755
index 000000000..84eead7b7
--- /dev/null
+++ b/contrib/bsc-test/drop-oml.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+sleep 3
+echo "enable"
+sleep 1
+echo "drop bts connection 0 oml"
+sleep 1
diff --git a/contrib/bsc-test/drop.sh b/contrib/bsc-test/drop.sh
new file mode 100755
index 000000000..c7b66ba72
--- /dev/null
+++ b/contrib/bsc-test/drop.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+while true;
+do
+ echo "Going to drop the OML connection"
+ ./drop-oml.sh | telnet 127.0.0.1 4242
+ sleep 58m
+done
diff --git a/contrib/bsc-test/hangup b/contrib/bsc-test/hangup
new file mode 100644
index 000000000..cad6870fd
--- /dev/null
+++ b/contrib/bsc-test/hangup
@@ -0,0 +1,4 @@
+TIMEOUT 10
+'' ^Z
+SAY "Waiting for hangup confirm\n"
+'' ATH;
diff --git a/contrib/bsc-test/msc.sh b/contrib/bsc-test/msc.sh
new file mode 100755
index 000000000..bec011d4c
--- /dev/null
+++ b/contrib/bsc-test/msc.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+while true;
+do
+ echo "Kill the osmo-bsc"
+ /usr/bin/kill -s SIGUSR2 `pidof osmo-bsc`
+ sleep 58s
+done
diff --git a/contrib/bsc_control.py b/contrib/bsc_control.py
new file mode 100755
index 000000000..9dc01e3bf
--- /dev/null
+++ b/contrib/bsc_control.py
@@ -0,0 +1,104 @@
+#!/usr/bin/python
+
+import sys,os
+from optparse import OptionParser
+import socket
+import struct
+
+verbose = False
+
+def prefix_ipa_ctrl_header(data):
+ return struct.pack(">HBB", len(data)+1, 0xee, 0) + data
+
+def remove_ipa_ctrl_header(data):
+ if (len(data) < 4):
+ raise BaseException("Answer too short!")
+ (plen, ipa_proto, osmo_proto) = struct.unpack(">HBB", data[:4])
+ if (plen + 3 > len(data)):
+ print "Warning: Wrong payload length (expected %i, got %i)" % (plen, len(data) - 3)
+ if (ipa_proto != 0xee or osmo_proto != 0):
+ raise BaseException("Wrong protocol in answer!")
+
+ return data[4:plen+3], data[plen+3:]
+
+def connect(host, port):
+ if verbose:
+ print "Connecting to host %s:%i" % (host, port)
+
+ sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sck.setblocking(1)
+ sck.connect((host, port))
+ return sck
+
+def send(sck, data):
+ if verbose:
+ print "Sending \"%s\"" %(data)
+ data = prefix_ipa_ctrl_header(data)
+ sck.send(data)
+
+def do_set(var, value, id, sck):
+ setmsg = "SET %s %s %s" %(options.id, var, value)
+ send(sck, setmsg)
+
+def do_get(var, id, sck):
+ getmsg = "GET %s %s" %(options.id, var)
+ send(sck, getmsg)
+
+parser = OptionParser("Usage: %prog [options] var [value]")
+parser.add_option("-d", "--host", dest="host",
+ help="connect to HOST", metavar="HOST")
+parser.add_option("-p", "--port", dest="port", type="int",
+ help="use PORT", metavar="PORT", default=4249)
+parser.add_option("-g", "--get", action="store_true",
+ dest="cmd_get", help="perform GET operation")
+parser.add_option("-s", "--set", action="store_true",
+ dest="cmd_set", help="perform SET operation")
+parser.add_option("-i", "--id", dest="id", default="1",
+ help="set id manually", metavar="ID")
+parser.add_option("-v", "--verbose", action="store_true",
+ dest="verbose", help="be verbose", default=False)
+parser.add_option("-m", "--monitor", action="store_true",
+ dest="monitor", help="monitor the connection for traps", default=False)
+
+(options, args) = parser.parse_args()
+
+verbose = options.verbose
+
+if options.cmd_set and options.cmd_get:
+ parser.error("Get and set options are mutually exclusive!")
+
+if not (options.cmd_get or options.cmd_set or options.monitor):
+ parser.error("One of -m, -g, or -s must be set")
+
+if not (options.host):
+ parser.error("Destination host and port required!")
+
+sock = connect(options.host, options.port)
+
+if options.cmd_set:
+ if len(args) < 2:
+ parser.error("Set requires var and value arguments")
+ do_set(args[0], ' '.join(args[1:]), options.id, sock)
+
+if options.cmd_get:
+ if len(args) != 1:
+ parser.error("Get requires the var argument")
+ do_get(args[0], options.id, sock)
+
+data = sock.recv(1024)
+while (len(data)>0):
+ (answer, data) = remove_ipa_ctrl_header(data)
+ print "Got message:", answer
+
+if options.monitor:
+ while (True):
+ data = sock.recv(1024)
+ if len(data) == 0:
+ print "Connection is gone."
+ break
+
+ while (len(data)>0):
+ (answer, data) = remove_ipa_ctrl_header(data)
+ print "Got message:", answer
+
+sock.close()
diff --git a/contrib/bt.py b/contrib/bt.py
new file mode 100755
index 000000000..1b111efc8
--- /dev/null
+++ b/contrib/bt.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+
+import os
+
+f = open("unbalanced")
+lines = []
+for line in f:
+ lines.append(line)
+
+filenames = {}
+
+output = []
+for line in lines:
+ if "[0x" in line:
+ start = line.find("[")
+ end = line.find("]")
+ addr = line[start+1:end]
+ try:
+ file = filenames[addr]
+ except KeyError:
+ r = os.popen("addr2line -fs -e ./bsc_hack %s" % addr)
+ all = r.read().replace("\n", ",")
+ file = all
+ filenames[addr] = file
+
+ line = line.replace(addr, file)
+ output.append(line)
+
+g = open("unbalanced.2", "w")
+g.write("".join(output))
+
+
+
diff --git a/contrib/convert_to_enum.py b/contrib/convert_to_enum.py
new file mode 100755
index 000000000..bcd6f2cee
--- /dev/null
+++ b/contrib/convert_to_enum.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+
+#
+# Convert ETSI documents to an enum
+#
+
+import re, sys
+
+def convert(string):
+ string = string.strip().replace(" ", "").rjust(8, "0")
+ var = 0
+ offset = 7
+ for char in string:
+ assert offset >= 0
+ var = var | (int(char) << offset)
+ offset = offset - 1
+
+ return var
+
+def string(name):
+ name = name.replace(" ", "_")
+ name = name.replace('"', "")
+ name = name.replace('/', '_')
+ name = name.replace('(', '_')
+ name = name.replace(')', '_')
+ return "%s_%s" % (sys.argv[2], name.upper())
+
+file = open(sys.argv[1])
+
+
+for line in file:
+ m = re.match(r"[ \t]*(?P<value>[01 ]+)[ ]+(?P<name>[a-zA-Z /0-9()]+)", line[:-1])
+
+ if m:
+ print "\t%s\t\t= %d," % (string(m.groupdict()["name"]), convert(m.groupdict()["value"]))
+ else:
+ print line[:-1]
diff --git a/contrib/gprs/gb-proxy-unblock-bug.py b/contrib/gprs/gb-proxy-unblock-bug.py
new file mode 100755
index 000000000..0cd4b871f
--- /dev/null
+++ b/contrib/gprs/gb-proxy-unblock-bug.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+"""
+demonstrate a unblock bug on the GB Proxy..
+"""
+
+bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
+ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
+
+bts_ns_unblock = "\x06"
+ns_unblock_ack = "\x07"
+
+bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02"
+ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00"
+
+bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40"
+
+
+import socket
+socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+socket.bind(("0.0.0.0", 0))
+socket.setblocking(1)
+
+
+import sys
+port = int(sys.argv[1])
+print "Sending data to port: %d" % port
+
+def send_and_receive(packet):
+ socket.sendto(packet, ("127.0.0.1", port))
+
+ try:
+ data, addr = socket.recvfrom(4096)
+ except socket.error, e:
+ print "ERROR", e
+ import sys
+ sys.exit(0)
+ return data
+
+#send stuff once
+
+to_send = [
+ (bts_ns_reset, ns_reset_ack, "reset ack"),
+ (bts_ns_unblock, ns_unblock_ack, "unblock ack"),
+ (bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"),
+]
+
+
+for (out, inp, type) in to_send:
+ res = send_and_receive(out)
+ if res != inp:
+ print "Failed to get the %s" % type
+ sys.exit(-1)
+
+import time
+time.sleep(3)
+res = send_and_receive(bts_bvc_reset_8167)
+print "Sent all messages... check wireshark for the last response"
diff --git a/contrib/gprs/gprs-bssgp-histogram.lua b/contrib/gprs/gprs-bssgp-histogram.lua
new file mode 100644
index 000000000..b1ab5df7f
--- /dev/null
+++ b/contrib/gprs/gprs-bssgp-histogram.lua
@@ -0,0 +1,78 @@
+-- Simple LUA script to print the size of BSSGP messages over their type...
+
+do
+ local ip_bucket = {}
+
+ local pdu_types = {}
+ pdu_types[ 6] = "PAGING"
+ pdu_types[11] = "SUSPEND"
+ pdu_types[12] = "SUSPEND-ACK"
+ pdu_types[32] = "BVC-BLOCK"
+ pdu_types[33] = "BVC-BLOCK-ACK"
+ pdu_types[34] = "BVC-RESET"
+ pdu_types[35] = "BVC-RESET-ACK"
+ pdu_types[36] = "UNBLOCK"
+ pdu_types[37] = "UNBLOCK-ACK"
+ pdu_types[38] = "FLOW-CONTROL-BVC"
+ pdu_types[39] = "FLOW-CONTROL-BVC-ACK"
+ pdu_types[40] = "FLOW-CONTROL-MS"
+ pdu_types[41] = "FLOW-CONTROL-MS-ACK"
+ pdu_types[44] = "LLC-DISCARDED"
+
+ local function init_listener()
+ -- handle the port as NS over IP
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ -- bssgp filters
+ local bssgp_pdu_get = Field.new("bssgp.pdu_type")
+ local udp_length_get = Field.new("udp.length")
+
+ local tap = Listener.new("ip", "udp.port == 23000")
+ function tap.packet(pinfo,tvb,ip)
+ local pdu = bssgp_pdu_get()
+ local len = udp_length_get()
+
+ -- only handle bssgp, but we also want the IP frame
+ if not pdu then
+ return
+ end
+
+ pdu = tostring(pdu)
+ if tonumber(pdu) == 0 or tonumber(pdu) == 1 then
+ return
+ end
+
+ local ip_src = tostring(ip.ip_src)
+ local bssgp_histo = ip_bucket[ip_src]
+ if not bssgp_histo then
+ bssgp_histo = {}
+ ip_bucket[ip_src] = bssgp_histo
+ end
+
+ local key = pdu
+ local bucket = bssgp_histo[key]
+ if not bucket then
+ bucket = {}
+ bssgp_histo[key] = bucket
+ end
+
+ table.insert(bucket, tostring(len))
+ print("IP: " .. ip_src .. " PDU: " .. pdu_types[tonumber(pdu)] .. " Length: " .. tostring(len))
+ end
+
+ function tap.draw()
+ -- well... this will not be called...
+-- for ip,bssgp_histo in pairs(dumpers) do
+-- print("IP " .. ip)
+-- end
+ end
+
+ function tap.reset()
+ -- well... this will not be called...
+ end
+ end
+
+ init_listener()
+end
diff --git a/contrib/gprs/gprs-buffer-count.lua b/contrib/gprs/gprs-buffer-count.lua
new file mode 100644
index 000000000..ca8864ad1
--- /dev/null
+++ b/contrib/gprs/gprs-buffer-count.lua
@@ -0,0 +1,80 @@
+-- I count the buffer space needed for LLC PDUs in the worse case and print it
+
+do
+ local function init_listener()
+ -- handle the port as NS over IP
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ -- bssgp filters
+ local bssgp_pdu_get = Field.new("bssgp.pdu_type")
+ local bssgp_delay_get = Field.new("bssgp.delay_val")
+ local llcgprs_get = Field.new("llcgprs")
+ local pdus = nil
+
+ print("START...")
+
+ local tap = Listener.new("ip", "udp.port == 23000 && bssgp.pdu_type == 0")
+ function tap.packet(pinfo,tvb,ip)
+ local pdu = bssgp_pdu_get()
+ local len = llcgprs_get().len
+ local delay = bssgp_delay_get()
+
+ -- only handle bssgp, but we also want the IP frame
+ if not pdu then
+ return
+ end
+
+ if tonumber(tostring(delay)) == 65535 then
+ pdus = { next = pdus,
+ len = len,
+ expires = -1 }
+ else
+ local off = tonumber(tostring(delay)) / 100.0
+ pdus = { next = pdus,
+ len = len,
+ expires = pinfo.rel_ts + off }
+ end
+ local now_time = tonumber(tostring(pinfo.rel_ts))
+ local now_size = 0
+ local l = pdus
+ local prev = nil
+ local count = 0
+ while l do
+ if now_time < l.expires or l.expires == -1 then
+ now_size = now_size + l.len
+ prev = l
+ l = l.next
+ count = count + 1
+ else
+ -- delete things
+ if prev == nil then
+ pdus = nil
+ l = nil
+ else
+ prev.next = l.next
+ l = l.next
+ end
+ end
+ end
+-- print("TOTAL: " .. now_time .. " PDU_SIZE: " .. now_size)
+ print(now_time .. " " .. now_size / 1024.0 .. " " .. count)
+-- print("NOW: " .. tostring(pinfo.rel_ts) .. " Delay: " .. tostring(delay) .. " Length: " .. tostring(len))
+ end
+
+ function tap.draw()
+ -- well... this will not be called...
+-- for ip,bssgp_histo in pairs(dumpers) do
+-- print("IP " .. ip)
+-- end
+ print("END")
+ end
+
+ function tap.reset()
+ -- well... this will not be called...
+ end
+ end
+
+ init_listener()
+end
diff --git a/contrib/gprs/gprs-split-trace-by-tlli.lua b/contrib/gprs/gprs-split-trace-by-tlli.lua
new file mode 100644
index 000000000..018c377c5
--- /dev/null
+++ b/contrib/gprs/gprs-split-trace-by-tlli.lua
@@ -0,0 +1,46 @@
+-- Create a file named by_ip/''ip_addess''.cap with all ip traffic of each ip host. (works for tshark only)
+-- Dump files are created for both source and destination hosts
+do
+ local dir = "by_tlli"
+ local dumpers = {}
+ local function init_listener()
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ local field_tlli = Field.new("bssgp.tlli")
+ local tap = Listener.new("ip", "udp.port == 23000")
+
+ -- we will be called once for every IP Header.
+ -- If there's more than one IP header in a given packet we'll dump the packet once per every header
+ function tap.packet(pinfo,tvb,ip)
+ local tlli = field_tlli()
+ if not tlli then
+ return
+ end
+
+ local tlli_str = tostring(tlli)
+ tlli_dmp = dumpers[tlli_str]
+ if not tlli_dmp then
+ local tlli_hex = string.format("0x%x", tonumber(tlli_str))
+ print("Creating dump for TLLI " .. tlli_hex)
+ tlli_dmp = Dumper.new_for_current(dir .. "/" .. tlli_hex .. ".pcap")
+ dumpers[tlli_str] = tlli_dmp
+ end
+ tlli_dmp:dump_current()
+ tlli_dmp:flush()
+ end
+ function tap.draw()
+ for tlli,dumper in pairs(dumpers) do
+ dumper:flush()
+ end
+ end
+ function tap.reset()
+ for tlli,dumper in pairs(dumpers) do
+ dumper:close()
+ end
+ dumpers = {}
+ end
+ end
+ init_listener()
+end
diff --git a/contrib/gprs/gprs-verify-nu.lua b/contrib/gprs/gprs-verify-nu.lua
new file mode 100644
index 000000000..e44fdd16f
--- /dev/null
+++ b/contrib/gprs/gprs-verify-nu.lua
@@ -0,0 +1,59 @@
+-- This script verifies that the N(U) is increasing...
+--
+do
+ local nu_state_src = {}
+
+ local function init_listener()
+ -- handle the port as NS over IP
+ local udp_port_table = DissectorTable.get("udp.port")
+ local gprs_ns_dis = Dissector.get("gprs_ns")
+ udp_port_table:add(23000,gprs_ns_dis)
+
+ -- we want to look here...
+ local llc_sapi_get = Field.new("llcgprs.sapib")
+ local llc_nu_get = Field.new("llcgprs.nu")
+ local bssgp_tlli_get = Field.new("bssgp.tlli")
+
+ local tap = Listener.new("ip", "udp.port == 23000")
+ function tap.packet(pinfo,tvb,ip)
+ local llc_sapi = llc_sapi_get()
+ local llc_nu = llc_nu_get()
+ local bssgp_tlli = bssgp_tlli_get()
+
+ if not llc_sapi or not llc_nu or not bssgp_tlli then
+ return
+ end
+
+ local ip_src = tostring(ip.ip_src)
+ local bssgp_tlli = tostring(bssgp_tlli)
+ local llc_nu = tostring(llc_nu)
+ local llc_sapi = tostring(llc_sapi)
+
+ local src_key = ip_src .. "-" .. bssgp_tlli .. "-" .. llc_sapi
+ local last_nu = nu_state_src[src_key]
+ if not last_nu then
+ -- print("Establishing mapping for " .. src_key)
+ nu_state_src[src_key] = llc_nu
+ return
+ end
+
+ local function tohex(number)
+ return string.format("0x%x", tonumber(number))
+ end
+
+ nu_state_src[src_key] = llc_nu
+ if tonumber(last_nu) + 1 ~= tonumber(llc_nu) then
+ print("JUMP in N(U) on TLLI " .. tohex(bssgp_tlli) .. " and SAPI: " .. llc_sapi .. " src: " .. ip_src)
+ print("\t last: " .. last_nu .. " now: " .. llc_nu)
+ end
+ end
+
+ function tap.draw()
+ end
+
+ function tap.reset()
+ end
+ end
+ init_listener()
+end
+
diff --git a/contrib/hlr-remove-old.sql b/contrib/hlr-remove-old.sql
new file mode 100644
index 000000000..626a331e1
--- /dev/null
+++ b/contrib/hlr-remove-old.sql
@@ -0,0 +1,18 @@
+-- Remove old data from the database
+DELETE FROM Subscriber
+ WHERE id != 1 AND datetime('now', '-10 days') > updated AND authorized != 1;
+DELETE FROM Equipment
+ WHERE datetime('now', '-10 days') > updated;
+DELETE FROM EquipmentWatch
+ WHERE datetime('now', '-10 days') > updated;
+DELETE FROM SMS
+ WHERE datetime('now', '-10 days') > created;
+DELETE FROM VLR
+ WHERE datetime('now', '-10 days') > updated;
+DELETE FROM ApduBlobs
+ WHERE datetime('now', '-10 days') > created;
+DELETE FROM Counters
+ WHERE datetime('now', '-10 days') > timestamp;
+DELETE FROM RateCounters
+ WHERE datetime('now', '-10 days') > timestamp;
+VACUUM;
diff --git a/contrib/mgcp_server.py b/contrib/mgcp_server.py
new file mode 100755
index 000000000..05c489db5
--- /dev/null
+++ b/contrib/mgcp_server.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+# Simple server for mgcp... send audit, receive response..
+
+import socket, time
+
+MGCP_GATEWAY_PORT = 2427
+MGCP_CALLAGENT_PORT = 2727
+
+rsip_resp = """200 321321332\r\n"""
+audit_packet = """AUEP %d 13@mgw MGCP 1.0\r\n"""
+crcx_packet = """CRCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n"""
+dlcx_packet = """DLCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\n"""
+mdcx_packet = """MDCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 258696477 0 IN IP4 172.16.1.107\r\ns=-\r\nc=IN IP4 172.16.1.107\r\nt=0 0\r\nm=audio 6666 RTP/AVP 127\r\na=rtpmap:127 GSM-EFR/8000/1\r\na=ptime:20\r\na=recvonly\r\nm=image 4402 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n"""
+
+def hexdump(src, length=8):
+ """Recipe is from http://code.activestate.com/recipes/142812/"""
+ result = []
+ digits = 4 if isinstance(src, unicode) else 2
+ for i in xrange(0, len(src), length):
+ s = src[i:i+length]
+ hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s])
+ text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
+ result.append( b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text) )
+ return b'\n'.join(result)
+
+server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+server_socket.bind(("127.0.0.1", MGCP_CALLAGENT_PORT))
+server_socket.setblocking(1)
+
+last_ci = 1
+def send_and_receive(packet):
+ global last_ci
+ server_socket.sendto(packet, ("127.0.0.1", MGCP_GATEWAY_PORT))
+ try:
+ data, addr = server_socket.recvfrom(4096)
+
+ # attempt to store the CI of the response
+ list = data.split("\n")
+ for item in list:
+ if item.startswith("I: "):
+ last_ci = int(item[3:])
+
+ print hexdump(data), addr
+ except socket.error, e:
+ print e
+ pass
+
+def generate_tid():
+ import random
+ return random.randint(0, 65123)
+
+
+
+while True:
+ send_and_receive(audit_packet % generate_tid())
+ send_and_receive(crcx_packet % generate_tid() )
+ send_and_receive(mdcx_packet % (generate_tid(), last_ci))
+ send_and_receive(dlcx_packet % (generate_tid(), last_ci))
+
+ time.sleep(3)
diff --git a/contrib/nat/test_regexp.c b/contrib/nat/test_regexp.c
new file mode 100644
index 000000000..808a703ca
--- /dev/null
+++ b/contrib/nat/test_regexp.c
@@ -0,0 +1,30 @@
+/* make test_regexp */
+#include <sys/types.h>
+#include <regex.h>
+#include <stdio.h>
+
+
+int main(int argc, char **argv)
+{
+ regex_t reg;
+ regmatch_t matches[2];
+
+ if (argc != 4) {
+ printf("Invoke with: test_regexp REGEXP REPLACE NR\n");
+ return -1;
+ }
+
+ if (regcomp(&reg, argv[1], REG_EXTENDED) != 0) {
+ fprintf(stderr, "Regexp '%s' is not valid.\n", argv[1]);
+ return -1;
+ }
+
+ if (regexec(&reg, argv[3], 2, matches, 0) == 0 && matches[1].rm_eo != -1)
+ printf("New Number: %s%s\n", argv[2], &argv[3][matches[1].rm_so]);
+ else
+ printf("No match.\n");
+
+ regfree(&reg);
+
+ return 0;
+}
diff --git a/contrib/rtp/rtp_replay.st b/contrib/rtp/rtp_replay.st
new file mode 100644
index 000000000..a281570cf
--- /dev/null
+++ b/contrib/rtp/rtp_replay.st
@@ -0,0 +1,17 @@
+"
+Simple UDP replay from the state files
+"
+
+PackageLoader fileInPackage: #Sockets.
+FileStream fileIn: 'rtp_replay_shared.st'.
+
+
+Eval [
+ | replay |
+
+
+ replay := RTPReplay on: 'rtp_ssrc6976010.240.240.1_to_10.240.240.50.state'.
+
+ Transcript nextPutAll: 'Going to stream now'; nl.
+ replay streamAudio: '127.0.0.1' port: 4000.
+]
diff --git a/contrib/rtp/rtp_replay_shared.st b/contrib/rtp/rtp_replay_shared.st
new file mode 100644
index 000000000..dd32aed7a
--- /dev/null
+++ b/contrib/rtp/rtp_replay_shared.st
@@ -0,0 +1,108 @@
+"
+Simple UDP replay from the state files
+"
+
+PackageLoader fileInPackage: #Sockets.
+
+Object subclass: SDPUtils [
+ "Look into using PetitParser."
+ SDPUtils class >> findPort: aSDP [
+ aSDP linesDo: [:line |
+ (line startsWith: 'm=audio ') ifTrue: [
+ | stream |
+ stream := line readStream
+ skip: 'm=audio ' size;
+ yourself.
+ ^ Number readFrom: stream.
+ ]
+ ].
+
+ ^ self error: 'Not found'.
+ ]
+
+ SDPUtils class >> findHost: aSDP [
+ aSDP linesDo: [:line |
+ (line startsWith: 'c=IN IP4 ') ifTrue: [
+ | stream |
+ ^ stream := line readStream
+ skip: 'c=IN IP4 ' size;
+ upToEnd.
+ ]
+ ].
+
+ ^ self error: 'Not found'.
+ ]
+]
+
+Object subclass: RTPReplay [
+ | filename socket |
+ RTPReplay class >> on: aFile [
+ ^ self new
+ initialize;
+ file: aFile; yourself
+ ]
+
+ initialize [
+ socket := Sockets.DatagramSocket new.
+ ]
+
+ file: aFile [
+ filename := aFile
+ ]
+
+ localPort [
+ ^ socket port
+ ]
+
+ streamAudio: aHost port: aPort [
+ | file last_time last_image udp_send dest |
+
+ last_time := nil.
+ last_image := nil.
+ file := FileStream open: filename.
+
+ "Send the payload"
+ dest := Sockets.SocketAddress byName: aHost.
+ udp_send := [:payload | | datagram |
+ datagram := Sockets.Datagram data: payload contents address: dest port: aPort.
+ socket nextPut: datagram
+ ].
+
+ [file atEnd] whileFalse: [
+ | lineStream time data now_image |
+ lineStream := file nextLine readStream.
+
+ "Read the time, skip the blank, parse the data"
+ time := Number readFrom: lineStream.
+ lineStream skip: 1.
+
+ data := WriteStream on: (ByteArray new: 30).
+ [lineStream atEnd] whileFalse: [
+ | hex |
+ hex := lineStream next: 2.
+ data nextPut: (Number readFrom: hex readStream radix: 16).
+ ].
+
+ last_time isNil
+ ifTrue: [
+ "First time, send it right now"
+ last_time := time.
+ last_image := Time millisecondClockValue.
+ udp_send value: data.
+ ]
+ ifFalse: [
+ | wait_image new_image_time |
+
+ "How long to wait?"
+ wait_image := last_image + ((time - last_time) * 1000).
+ [ wait_image > Time millisecondClockValue ]
+ whileTrue: [Processor yield].
+
+ udp_send value: data.
+ last_time := time.
+ last_image := wait_image.
+ ]
+ ]
+ ]
+]
+
diff --git a/contrib/rtp/rtp_replay_sip.st b/contrib/rtp/rtp_replay_sip.st
new file mode 100644
index 000000000..5f844df1d
--- /dev/null
+++ b/contrib/rtp/rtp_replay_sip.st
@@ -0,0 +1,87 @@
+"""
+Create a SIP connection and then stream...
+"""
+
+PackageLoader
+ fileInPackage: #OsmoSIP.
+
+"Load for the replay code"
+FileStream fileIn: 'rtp_replay_shared.st'.
+
+
+Osmo.SIPCall subclass: StreamCall [
+ | sem stream |
+
+ createCall: aSDP [
+ | sdp |
+ stream := RTPReplay on: 'rtp_ssrc6976010.240.240.1_to_10.240.240.50.state'.
+ sdp := aSDP % {stream localPort}.
+ ^ super createCall: sdp.
+ ]
+
+ sem: aSemaphore [
+ sem := aSemaphore
+ ]
+
+ sessionNew [
+ | host port |
+ Transcript nextPutAll: 'The call has started'; nl.
+ Transcript nextPutAll: sdp_result; nl.
+
+ host := SDPUtils findHost: sdp_result.
+ port := SDPUtils findPort: sdp_result.
+
+ [
+ stream streamAudio: host port: port.
+ Transcript nextPutAll: 'Streaming has finished.'; nl.
+ ] fork.
+ ]
+
+ sessionFailed [
+ sem signal
+ ]
+
+ sessionEnd [
+ sem signal
+ ]
+]
+
+Eval [
+ | transport agent call sem sdp_fr sdp_amr |
+
+
+ sdp_fr := (WriteStream on: String new)
+ nextPutAll: 'v=0'; cr; nl;
+ nextPutAll: 'o=twinkle 1739517580 1043400482 IN IP4 127.0.0.1'; cr; nl;
+ nextPutAll: 's=-'; cr; nl;
+ nextPutAll: 'c=IN IP4 127.0.0.1'; cr; nl;
+ nextPutAll: 't=0 0'; cr; nl;
+ nextPutAll: 'm=audio %1 RTP/AVP 0 101'; cr; nl;
+ nextPutAll: 'a=rtpmap:0 PCMU/8000'; cr; nl;
+ nextPutAll: 'a=rtpmap:101 telephone-event/8000'; cr; nl;
+ nextPutAll: 'a=fmtp:101 0-15'; cr; nl;
+ nextPutAll: 'a=ptime:20'; cr; nl;
+ contents.
+
+ sem := Semaphore new.
+ transport := Osmo.SIPUdpTransport
+ startOn: '0.0.0.0' port: 5066.
+ agent := Osmo.SIPUserAgent createOn: transport.
+ transport start.
+
+ call := (StreamCall
+ fromUser: 'sip:1000@sip.zecke.osmocom.org'
+ host: '127.0.0.1'
+ port: 5060
+ to: 'sip:123456@127.0.0.1'
+ on: agent)
+ sem: sem; yourself.
+
+ call createCall: sdp_fr.
+
+
+ "Wait for the stream to have ended"
+ sem wait.
+
+ (Delay forSeconds: 4) wait.
+]
diff --git a/contrib/rtp/timestamp_rtp.lua b/contrib/rtp/timestamp_rtp.lua
new file mode 100644
index 000000000..c18a06bed
--- /dev/null
+++ b/contrib/rtp/timestamp_rtp.lua
@@ -0,0 +1,28 @@
+print("Ni hao")
+
+
+do
+ local tap = Listener.new("ip", "rtp")
+ local rtp_ssrc = Field.new("rtp.ssrc")
+ local frame_time = Field.new("frame.time_relative")
+ local rtp = Field.new("rtp")
+
+ function tap.packet(pinfo, tvb, ip)
+ local ip_src, ip_dst = tostring(ip.ip_src), tostring(ip.ip_dst)
+ local rtp_data = rtp()
+ local filename = "rtp_ssrc" .. rtp_ssrc() "_src_" .. ip_src .. "_to_" .. ip_dst .. ".state"
+ local f = io.open(filename, "a")
+
+ f:write(tostring(frame_time()) .. " ")
+ f:write(tostring(rtp_data.value))
+ f:write("\n")
+ f:close()
+ end
+
+ function tap.draw()
+ print("DRAW")
+ end
+ function tap.reset()
+ print("RESET")
+ end
+end
diff --git a/contrib/sms/fill-hlr.st b/contrib/sms/fill-hlr.st
new file mode 100644
index 000000000..da0643ecf
--- /dev/null
+++ b/contrib/sms/fill-hlr.st
@@ -0,0 +1,66 @@
+"I create output for some simple SQL statements for the HLR db"
+
+
+Eval [
+
+"Create tables if they don't exist"
+Transcript show: 'CREATE TABLE SMS (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ created TIMESTAMP NOT NULL,
+ sent TIMESTAMP,
+ sender_id INTEGER NOT NULL,
+ receiver_id INTEGER NOT NULL,
+ deliver_attempts INTEGER NOT NULL DEFAULT 0,
+ valid_until TIMESTAMP,
+ reply_path_req INTEGER NOT NULL,
+ status_rep_req INTEGER NOT NULL,
+ protocol_id INTEGER NOT NULL,
+ data_coding_scheme INTEGER NOT NULL,
+ ud_hdr_ind INTEGER NOT NULL,
+ dest_addr TEXT,
+ user_data BLOB,
+ header BLOB,
+ text TEXT);'; nl;
+ show: 'CREATE TABLE Subscriber (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ created TIMESTAMP NOT NULL,
+ updated TIMESTAMP NOT NULL,
+ imsi NUMERIC UNIQUE NOT NULL,
+ name TEXT,
+ extension TEXT UNIQUE,
+ authorized INTEGER NOT NULL DEFAULT 0,
+ tmsi TEXT UNIQUE,
+ lac INTEGER NOT NULL DEFAULT 0);'; nl.
+
+"Create some dummy subscribers"
+num_sub := 1000.
+num_sms := 30.
+lac := 1.
+
+Transcript show: 'BEGIN;'; nl.
+
+1 to: num_sub do: [:each |
+ Transcript show: 'INSERT INTO Subscriber
+ (imsi, created, updated, authorized, lac, extension)
+ VALUES
+ (%1, datetime(''now''), datetime(''now''), 1, %2, %3);' %
+ {(274090000000000 + each). lac. each}; nl.
+].
+
+1 to: num_sms do: [:sms |
+ 1 to: num_sub do: [:sub |
+ Transcript show: 'INSERT INTO SMS
+ (created, sender_id, receiver_id, valid_until,
+ reply_path_req, status_rep_req, protocol_id,
+ data_coding_scheme, ud_hdr_ind, dest_addr,
+ text) VALUES
+ (datetime(''now''), 1, %1, ''2222-2-2'',
+ 0, 0, 0,
+ 0, 0, ''123456'',
+ ''abc'');' % {sub}; nl.
+ ]
+].
+
+Transcript show: 'COMMIT;'; nl.
+
+]
diff --git a/contrib/sms/hlr-query.st b/contrib/sms/hlr-query.st
new file mode 100644
index 000000000..bd3f97a4a
--- /dev/null
+++ b/contrib/sms/hlr-query.st
@@ -0,0 +1,10 @@
+"Query for one SMS"
+
+Eval [
+1 to: 100 do: [:each |
+ Transcript show: 'SELECT SMS.* FROM SMS
+ JOIN Subscriber ON SMS.receiver_id = Subscriber.id
+ WHERE SMS.id >= 1 AND SMS.sent IS NULL AND Subscriber.lac > 0
+ ORDER BY SMS.id LIMIT 1;'; nl.
+].
+]
diff --git a/contrib/sms/sqlite-probe.tap.d b/contrib/sms/sqlite-probe.tap.d
new file mode 100644
index 000000000..e75cdfcfa
--- /dev/null
+++ b/contrib/sms/sqlite-probe.tap.d
@@ -0,0 +1,5 @@
+probe process("/usr/lib/libsqlite3.so.0.8.6").function("sqlite3_get_table")
+{
+ a = user_string($zSql);
+ printf("sqlite3_get_table called '%s'\n", a);
+}
diff --git a/contrib/systemd/osmo-bsc-mgcp.service b/contrib/systemd/osmo-bsc-mgcp.service
new file mode 100644
index 000000000..4b3df2c06
--- /dev/null
+++ b/contrib/systemd/osmo-bsc-mgcp.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=OpenBSC MGCP
+
+[Service]
+Type=simple
+Restart=always
+ExecStart=/usr/bin/osmo-bsc_mgcp -s -c /etc/osmocom/osmo-bsc-mgcp.cfg
+Restart=always
+RestartSec=2
diff --git a/contrib/systemd/osmo-bsc.service b/contrib/systemd/osmo-bsc.service
new file mode 100644
index 000000000..772d472a3
--- /dev/null
+++ b/contrib/systemd/osmo-bsc.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=OpenBSC BSC
+Requires=osmo-bsc-mgcp.service
+
+[Service]
+Type=simple
+Restart=always
+ExecStart=/usr/bin/osmo-bsc -c /etc/osmocom/osmo-bsc.cfg -s
+Restart=always
+RestartSec=2
diff --git a/contrib/systemd/osmo-nitb.service b/contrib/systemd/osmo-nitb.service
new file mode 100644
index 000000000..203aeb15c
--- /dev/null
+++ b/contrib/systemd/osmo-nitb.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=OpenBSC Network In the Box (NITB)
+
+[Service]
+Type=simple
+Restart=always
+ExecStart=/usr/bin/osmo-nitb -s -C -c /etc/osmocom/osmo-nitb.cfg -l /var/lib/osmocom/hlr.sqlite3
+Restart=always
+RestartSec=2