1-- test script for various Lua functions
2-- use with dhcp.pcap in test/captures directory
3
4
5------------- general test helper funcs ------------
6local FRAME = "frame"
7local ETH = "eth"
8local IP = "ip"
9local DHCP = "dhcp"
10local OTHER = "other"
11local PDISS = "postdissector"
12
13local packet_counts = {}
14local function incPktCount(name)
15    if not packet_counts[name] then
16        packet_counts[name] = 1
17    else
18        packet_counts[name] = packet_counts[name] + 1
19    end
20end
21local function getPktCount(name)
22    return packet_counts[name] or 0
23end
24
25local passed = {}
26local function setPassed(name)
27    if not passed[name] then
28        passed[name] = 1
29    else
30        passed[name] = passed[name] + 1
31    end
32end
33
34-- expected number of runs per type
35-- note ip only runs 3 times because it gets removed
36-- and dhcp only runs twice because the filter makes it run
37-- once and then it gets replaced with a different one for the second time
38local taptests = { [FRAME]=4, [ETH]=4, [IP]=3, [DHCP]=2, [OTHER]=16 }
39local function getResults()
40    print("\n-----------------------------\n")
41    for k,v in pairs(taptests) do
42        if passed[k] ~= v then
43            print("Something didn't run or ran too much... tests failed!")
44            print("Listener type "..k.." expected: "..v..", but got: "..tostring(passed[k]))
45            return false
46        end
47    end
48    print("All tests passed!\n\n")
49    return true
50end
51
52
53local function testing(type,...)
54    print("---- Testing "..type.." ---- "..tostring(...).." for packet # "..getPktCount(type).." ----")
55end
56
57local function test(type,name, ...)
58    io.stdout:write("test "..type.."-->"..name.."-"..getPktCount(type).."...")
59    if (...) == true then
60        io.stdout:write("passed\n")
61        return true
62    else
63        io.stdout:write("failed!\n")
64        error(name.." test failed!")
65    end
66end
67
68local pkt_fields = { [FRAME] = {}, [PDISS] = {} }
69local function getAllFieldInfos(type)
70    local fields = { all_field_infos() }
71    local fieldnames = {}
72    for i,v in ipairs(fields) do
73        fieldnames[i] = v.name
74    end
75    local pktnum = getPktCount(type)
76    pkt_fields[type][pktnum] = { ["num"] = #fields, ["fields"] = fieldnames }
77end
78
79local function dumpAllFieldInfos()
80    for i,v in ipairs(pkt_fields[FRAME]) do
81        print("In frame tap for packet ".. i ..":")
82        print("    number of fields = ".. v.num)
83        for _,name in ipairs(v.fields) do
84            print("    field = ".. name)
85        end
86        local w = pkt_fields[PDISS][i]
87        print("In postdissector for packet ".. i ..":")
88        print("    number of fields = ".. w.num)
89        for _,name in ipairs(w.fields) do
90            print("    field = ".. name)
91        end
92    end
93end
94
95local function checkAllFieldInfos()
96    for i,v in ipairs(pkt_fields[FRAME]) do
97        local numfields = v.num
98        if numfields ~= pkt_fields[PDISS][i].num then
99            print("Tap and postdissector do not have same number of fields!")
100            return false
101        end
102        if numfields < 100 then
103            print("Too few fields!")
104            return false
105        end
106    end
107    return true
108end
109
110
111---------
112-- the following are so we can use pcall (which needs a function to call)
113local function makeListener(...)
114    local foo = Listener.new(...)
115end
116
117local function setListener(tap,name,value)
118    tap[name] = value
119end
120
121local function getListener(tap,name)
122    local foo = tap[name]
123end
124
125------------- test script ------------
126testing(OTHER,"negative tests")
127local orig_test = test
128test = function (...)
129    if orig_test(OTHER,...) then
130        setPassed(OTHER)
131    end
132end
133test("Listener.new-1",not pcall(makeListener,"FooBARhowdy"))
134test("Listener.new-2",not pcall(makeListener,"ip","FooBARhowdy"))
135local tmptap = Listener.new()
136local func = function(...)
137    passed[OTHER] = 0
138    error("This shouldn't be called!")
139end
140test("Listener.set-3",pcall(setListener,tmptap,"packet",func))
141test("Listener.set-4",pcall(setListener,tmptap,"reset",func))
142test("Listener.set-5",pcall(setListener,tmptap,"draw",func))
143test("Listener.set-6",not pcall(setListener,Listener,"packet",func))
144test("Listener.set-7",not pcall(setListener,Listener,"reset",func))
145test("Listener.set-8",not pcall(setListener,Listener,"draw",func))
146test("Listener.set-9",not pcall(setListener,Listener,"foobar",func))
147
148test("Listener.get-10",not pcall(getListener,tmptap,"packet",func))
149test("Listener.get-11",not pcall(getListener,tmptap,"reset",func))
150test("Listener.get-12",not pcall(getListener,tmptap,"draw",func))
151
152print("removing tmptap twice")
153test("Listener.remove-13",pcall(tmptap.remove,tmptap))
154test("Listener.remove-14",pcall(tmptap.remove,tmptap))
155
156test("typeof-15", typeof(tmptap) == "Listener")
157
158-- revert to original test function
159test = orig_test
160
161
162-- declare some field extractors
163local f_eth_src     = Field.new("eth.src")
164local f_eth_dst     = Field.new("eth.dst")
165local f_eth_mac     = Field.new("eth.addr")
166local f_ip_src      = Field.new("ip.src")
167local f_ip_dst      = Field.new("ip.dst")
168local f_dhcp_hw    = Field.new("dhcp.hw.mac_addr")
169local f_dhcp_opt   = Field.new("dhcp.option.type")
170
171local tap_frame = Listener.new(nil,nil,true)
172local tap_eth = Listener.new("eth")
173local tap_ip = Listener.new("ip","dhcp")
174local tap_dhcp = Listener.new("dhcp","dhcp.option.dhcp == 1")
175
176local second_time = false
177
178function tap_frame.packet(pinfo,tvb,frame)
179    incPktCount(FRAME)
180    testing(FRAME,"Frame")
181
182    test(FRAME,"arg-1", typeof(pinfo) == "Pinfo")
183    test(FRAME,"arg-2", typeof(tvb) == "Tvb")
184    test(FRAME,"arg-3", frame == nil)
185
186    test(FRAME,"pinfo.number-1",pinfo.number == getPktCount(FRAME))
187
188    -- check ether addr
189    local eth_src1 = tostring(f_eth_src().range)
190    local eth_src2 = tostring(tvb:range(6,6))
191    test(FRAME,"FieldInfo.range-1", eth_src1 == eth_src2)
192
193    getAllFieldInfos(FRAME)
194
195    setPassed(FRAME)
196end
197
198function tap_eth.packet(pinfo,tvb,eth)
199    incPktCount(ETH)
200
201    -- on the 4th run of eth, remove the ip one and add a new dhcp one
202    if getPktCount(ETH) == 4 then
203        testing(ETH,"removing ip tap, replacing dhcp tap")
204        tap_ip:remove()
205        tap_dhcp:remove()
206        tap_dhcp = Listener.new("dhcp")
207        tap_dhcp.packet = dhcp_packet
208        second_time = true
209    end
210
211    testing(ETH,"Eth")
212
213    test(ETH,"arg-1", typeof(pinfo) == "Pinfo")
214    test(ETH,"arg-2", typeof(tvb) == "Tvb")
215    test(ETH,"arg-3", type(eth) == "table")
216
217    test(ETH,"pinfo.number-1",pinfo.number == getPktCount(ETH))
218
219    -- check ether addr
220    local eth_src1 = tostring(f_eth_src().range)
221    local eth_src2 = tostring(tvb:range(6,6))
222    test(ETH,"FieldInfo.range-1", eth_src1 == eth_src2)
223
224    setPassed(ETH)
225end
226
227function tap_ip.packet(pinfo,tvb,ip)
228    incPktCount(IP)
229    testing(IP,"IP")
230
231    test(IP,"arg-1", typeof(pinfo) == "Pinfo")
232    test(IP,"arg-2", typeof(tvb) == "Tvb")
233    test(IP,"arg-3", type(ip) == "table")
234
235    test(IP,"pinfo.number-1",pinfo.number == getPktCount(IP))
236
237    -- check ether addr
238    local eth_src1 = tostring(f_eth_src().range)
239    local eth_src2 = tostring(tvb:range(6,6))
240    test(IP,"FieldInfo.range-1", eth_src1 == eth_src2)
241
242    setPassed(IP)
243end
244
245dhcp_packet = function (pinfo,tvb,dhcp)
246    incPktCount(DHCP)
247    testing(DHCP,"DHCP")
248
249    test(DHCP,"arg-1", typeof(pinfo) == "Pinfo")
250    test(DHCP,"arg-2", typeof(tvb) == "Tvb")
251    test(DHCP,"arg-3", dhcp == nil)
252
253    if not second_time then
254        test(DHCP,"pinfo.number-1",pinfo.number == getPktCount(DHCP))
255    else
256        test(DHCP,"pinfo.number-1",pinfo.number == 4)
257    end
258
259    -- check ether addr
260    local eth_src1 = tostring(f_eth_src().range)
261    local eth_src2 = tostring(tvb:range(6,6))
262    test(DHCP,"FieldInfo.range-1", eth_src1 == eth_src2)
263
264    setPassed(DHCP)
265end
266tap_dhcp.packet = dhcp_packet
267
268function tap_frame.reset()
269    -- reset never gets called in tshark (sadly)
270    if not GUI_ENABLED then
271        error("reset called!!")
272    end
273end
274
275function tap_frame.draw()
276    test(OTHER,"all_field_infos", checkAllFieldInfos())
277    setPassed(OTHER)
278    getResults()
279end
280
281-- max_gap.lua
282-- create a gap.max field containing the maximum gap between two packets between two ip nodes
283
284-- we create a "protocol" for our tree
285local max_gap_p = Proto("gap","Gap in IP conversations")
286
287-- we create our fields
288local max_gap_field = ProtoField.float("gap.max")
289
290-- we add our fields to the protocol
291max_gap_p.fields = { max_gap_field }
292
293-- then we register max_gap_p as a postdissector
294register_postdissector(max_gap_p,true)
295function max_gap_p.dissector(tvb,pinfo,tree)
296    incPktCount(PDISS)
297    getAllFieldInfos(PDISS)
298end
299
300
301