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