aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/contrib/a-link/sccp-split-by-con.lua
blob: c644d446ad8269211b7fc3fbb0b1e276a07d0f91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
-- Split trace based on SCCP Source
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