]> git.sur5r.net Git - ngadmin/blob - wireshark/nsdp.lua
Added chained makefiles.
[ngadmin] / wireshark / nsdp.lua
1
2 p_nsdp=Proto("nsdp", "Netgear Switch Description Protocol")
3
4 local f_version=ProtoField.uint8("nsdp.version", "Version", base.DEC)
5 local f_code=ProtoField.uint8("nsdp.code", "Operation Code", base.DEC)
6 local f_error=ProtoField.uint8("nsdp.error", "Error Code", base.DEC)
7 local f_errattr=ProtoField.uint16("nsdp.errattr", "Erroneous Attribute", base.HEX)
8 local f_clientmac=ProtoField.ether("nsdp.clientmac", "Client MAC")
9 local f_switchmac=ProtoField.ether("nsdp.switchmac", "Switch MAC")
10 local f_seqnum=ProtoField.uint32("nsdp.seqnum", "Sequence Number", base.DEC)
11
12 p_nsdp.fields={
13  f_version, f_code, f_error, f_errattr, f_clientmac, f_switchmac, f_seqnum
14 }
15
16
17
18
19
20 local op_codes={
21  [1]="Read Request", 
22  [2]="Read Reply", 
23  [3]="Write Request", 
24  [4]="Write Reply"
25 }
26
27
28 local error_codes={
29  [0]="OK", 
30  [5]="Invalid Value", 
31  [7]="Invalid Password"
32 }
33
34
35 local status_codes={
36  [0]="down", 
37  [4]="100M", 
38  [5]="1000M"
39 }
40
41
42 local bitrates_codes={
43  [0]="unlimited", 
44  [1]="512K", 
45  [2]="1M", 
46  [3]="2M", 
47  [4]="4M", 
48  [5]="8M", 
49  [6]="16M", 
50  [7]="32M", 
51  [8]="64M", 
52  [9]="128M", 
53  [10]="256M", 
54  [11]="512M"
55 }
56
57
58 local vlan_type_codes={
59  [1]="port basic", 
60  [2]="port advanced", 
61  [3]="802.1Q basic", 
62  [4]="802.1Q advanced"
63 }
64
65
66 local qos_type_codes={
67  [1]="port based", 
68  [2]="802.1p"
69 }
70
71
72 local prio_codes={
73  [1]="high", 
74  [2]="medium", 
75  [3]="normal", 
76  [4]="low"
77 }
78
79
80
81
82 local function dissect_port_statistics (buffer, offset, subtree)
83  
84  subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
85  subtree:add(buffer(offset+4+1+8*0, 8), "Received:", tostring(buffer(offset+4+1+8*0, 8):uint64()))
86  subtree:add(buffer(offset+4+1+8*1, 8), "Sent: ", tostring(buffer(offset+4+1+8*1, 8):uint64()))
87  subtree:add(buffer(offset+4+1+8*5, 8), "CRC Errors:", tostring(buffer(offset+4+1+8*5, 8):uint64()))
88  
89 end
90
91
92
93 local function dissect_port_status (buffer, offset, subtree)
94  
95  local st=buffer(offset+5, 1):uint()
96  subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
97  subtree:add(buffer(offset+5, 1), string.format("Status: %i (%s)", st, status_codes[st] or "unk"))
98  
99 end
100
101
102
103 local function dissect_qos_type (buffer, offset, subtree)
104  
105  local t=buffer(offset+4, 1):uint()
106  subtree:add(buffer(offset+4, 1), string.format("QoS Type: %i (%s)", t, qos_type_codes[t] or "unk"))
107  
108 end
109
110
111
112 local function dissect_qos_config (buffer, offset, subtree)
113  
114  local p=buffer(offset+5, 1):uint()
115  subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
116  subtree:add(buffer(offset+5, 1), string.format("Priority: %i (%s)", p, prio_codes[p] or "unk"))
117  
118 end
119
120
121
122 local function dissect_bitrate (buffer, offset, subtree)
123  
124  local sp=buffer(offset+5, 4):uint()
125  subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
126  subtree:add(buffer(offset+5, 4), string.format("Speed: %i (%s)", sp, bitrates_codes[sp] or "unk"))
127  
128 end
129
130
131
132 local function dissect_vlan_type (buffer, offset, subtree)
133  
134  local vt=buffer(offset+4, 1):uint()
135  subtree:add(buffer(offset+4, 1), string.format("VLAN Type: %i (%s)", vt, vlan_type_codes[vt] or "unk"))
136  
137 end
138
139
140
141 local function parse_ports (val)
142  
143  local ports=""
144  
145  for i=8,1,-1 do
146   if ( val%2==1 ) then
147    ports=ports..i.." "
148   end
149   val=math.floor(val/2)
150  end
151  
152  return ports
153  
154 end
155
156
157
158 local function dissect_vlan_port_conf (buffer, offset, subtree)
159  
160  subtree:add(buffer(offset+4, 2), string.format("VLAN: %u", buffer(offset+4, 2):uint()))
161  
162  if ( buffer(offset+2, 2):uint()>=3 ) then
163   subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint()))
164  end
165  
166 end
167
168
169
170 local function dissect_vlan_8021q_conf (buffer, offset, subtree)
171  
172  subtree:add(buffer(offset+4, 2), string.format("VLAN: %u", buffer(offset+4, 2):uint()))
173  
174  if ( buffer(offset+2, 2):uint()>=4 ) then
175   subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint()))
176   subtree:add(buffer(offset+7, 1), "Tagged Ports:", parse_ports(buffer(offset+7, 1):uint()))
177  end
178  
179 end
180
181
182
183 local function dissect_vlan_pvid (buffer, offset, subtree)
184  
185  subtree:add(buffer(offset+4, 1), string.format("Port: %i", buffer(offset+4, 1):uint()))
186  subtree:add(buffer(offset+5, 2), string.format("VLAN: %u", buffer(offset+5, 2):uint()))
187  
188 end
189
190
191
192 local function dissect_mirror (buffer, offset, subtree)
193  
194  local op=buffer(offset+4, 1):uint()
195  
196  if ( op==0 ) then
197   subtree:add(buffer(offset+4, 1), "Disabled")
198  else
199   subtree:add(buffer(offset+4, 1), "Output Port:", op)
200   subtree:add(buffer(offset+6, 1), "Ports:", parse_ports(buffer(offset+6, 1):uint()))
201  end
202  
203 end
204
205
206
207 local function dissect_igmp_enablevlan (buffer, offset, subtree)
208  
209  subtree:add(buffer(offset+4, 2), string.format("Enable: %u", buffer(offset+4, 2):uint()))
210  subtree:add(buffer(offset+6, 2), string.format("VLAN: %u", buffer(offset+6, 2):uint()))
211  
212 end
213
214
215
216
217 local attributes={
218  [0x0001]={name="Product", dissect="string"}, 
219  [0x0003]={name="Name", dissect="string"}, 
220  [0x0004]={name="MAC", dissect="ether"}, 
221  [0x0006]={name="IP", dissect="ipv4"}, 
222  [0x0007]={name="Mask", dissect="ipv4"}, 
223  [0x0008]={name="Gateway", dissect="ipv4"}, 
224  [0x0009]={name="New Password", dissect="string"}, 
225  [0x000A]={name="Password", dissect="string"}, 
226  [0x000B]={name="DHCP", dissect="uint"}, 
227  [0x000D]={name="Firmware Version", dissect="string"}, 
228  [0x0010]={name="Firmware Upgrade", dissect="uint"}, 
229  [0x0013]={name="Restart", dissect="uint"}, 
230  [0x0400]={name="Defaults", dissect="uint"}, 
231  [0x0C00]={name="Port Status", dissect=dissect_port_status}, 
232  [0x1000]={name="Port Statistics", dissect=dissect_port_statistics}, 
233  [0x1400]={name="Reset Ports Statistics", dissect="uint"}, 
234  [0x1800]={name="Cabletest Do", dissect=nil}, 
235  [0x1C00]={name="Cabletest Result", dissect=nil}, 
236  [0x2000]={name="VLAN Type", dissect=dissect_vlan_type}, 
237  [0x2400]={name="VLAN Port Conf", dissect=dissect_vlan_port_conf}, 
238  [0x2800]={name="VLAN 802.1Q Conf", dissect=dissect_vlan_8021q_conf}, 
239  [0x2C00]={name="Destroy VLAN", dissect="uint"}, 
240  [0x3000]={name="VLAN PVID", dissect=dissect_vlan_pvid}, 
241  [0x3400]={name="QoS Type", dissect=dissect_qos_type}, 
242  [0x3800]={name="QoS Config", dissect=dissect_qos_config}, 
243  [0x4C00]={name="Input Bitrate", dissect=dissect_bitrate}, 
244  [0x5000]={name="Output Bitrate", dissect=dissect_bitrate}, 
245  [0x5400]={name="Broadcast Filtering State", dissect="uint"}, 
246  [0x5800]={name="Broadcast Filtering Bitrate", dissect=dissect_bitrate}, 
247  [0x5C00]={name="Mirror", dissect=dissect_mirror}, 
248  [0x6000]={name="Ports Count", dissect="uint"}, 
249  [0x6800]={name="IGMP Enable & VLAN", dissect=dissect_igmp_enablevlan}, 
250  [0x6C00]={name="Block Unknown IGMP Addresses", dissect="uint"}, 
251  [0x7000]={name="Validate IGMPv3 Headers", dissect="uint"}, 
252  [0xFFFF]={name="End", dissect=nil}
253 }
254
255
256
257
258
259
260 local function dissect_header (buffer, subtree)
261  
262  subtree:add(f_version, buffer(0, 1))
263  
264  subtree:add(f_code, buffer(1, 1)):append_text(" ("..(op_codes[buffer(1, 1):uint()] or "unknown")..")")
265  
266  local errcode=buffer(2, 1):uint()
267  subtree:add(f_error, buffer(2, 1)):append_text(" ("..(error_codes[errcode] or "unknown")..")")
268  
269  -- add the erroneous attribute only if an error occurred
270  if ( errcode~=0 ) then
271   local atf=attributes[buffer(4, 2):uint()]
272   subtree:add(f_errattr, buffer(4, 2)):append_text(" ("..(atf and atf.name or "unk")..")")
273  end
274  
275  subtree:add(f_clientmac, buffer(8, 6))
276  
277  subtree:add(f_switchmac, buffer(14, 6))
278  
279  subtree:add(f_seqnum, buffer(20, 4))
280  
281  
282 end
283
284
285
286 local function dissect_attributes (buffer, subtree)
287  
288  local offset=32
289  
290  while ( offset<buffer:len() ) do
291   
292   if ( offset+4>buffer:len() ) then
293    -- no room for an attribute header, it is an error
294    subtree:add(buffer(offset), "Junk"):set_expert_flags(PI_MALFORMED, PI_ERROR)
295    break
296   end
297   
298   local code=buffer(offset, 2):uint()
299   local len=buffer(offset+2, 2):uint()
300   local atf=attributes[code]
301   
302   local attr=subtree:add(buffer(offset, math.min(4+len, buffer:len()-offset)), string.format("Attribute: 0x%04X (%s)", code, atf and atf.name or "unk"))
303   attr:add(buffer(offset, 2), string.format("Code: 0x%04X", code))
304   attr:add(buffer(offset+2, 2), string.format("Length: %u", len))
305   
306   if ( offset+4+len>buffer:len() ) then
307    -- attribute length is bigger than remaining packet size, it is an error
308    attr:append_text(" [malformed]")
309    attr:set_expert_flags(PI_MALFORMED, PI_ERROR)
310    break
311   end
312   
313   
314   if ( len<=0 ) then
315    -- no data, display nothing
316   elseif ( atf==nil or atf.dissect==nil ) then
317    -- unknown attribute, display raw bytes
318    attr:add(buffer(offset+4, len), "Data:", tostring(buffer(offset+4, len):bytes()))
319   elseif ( type(atf.dissect)=="function" ) then
320    -- custom sub-dissector for complex type
321    atf.dissect(buffer, offset, attr)
322   else
323    -- simple type, directly show it
324    local func=assert(loadstring("return function(buffer, offset, len) return tostring(buffer(offset+4, len):"..atf.dissect.."()) end"))() -- ugly, isn't it ?
325    attr:add(buffer(offset+4, len), atf.name..":", func(buffer, offset, len))
326   end
327   
328   offset=offset+4+len
329   
330  end
331  
332 end
333
334
335
336 function p_nsdp.dissector (buffer, pinfo, tree)
337  
338  pinfo.cols.protocol=p_nsdp.name
339  local subtree=tree:add(p_nsdp, buffer())
340  
341  -- stop if the packet is too small to be valid
342  if ( buffer:len()<32 ) then return end
343  
344  dissect_header(buffer, subtree)
345  
346  -- stop if it is just a header
347  if ( buffer:len()==32 ) then return end
348  
349  local attr_list=subtree:add(buffer(32), "Attributes list")
350  dissect_attributes(buffer, attr_list)
351  
352 end
353
354
355
356 function p_nsdp.init ()
357 end
358
359
360
361 local udp_dissector_table=DissectorTable.get("udp.port")
362 dissector=udp_dissector_table:get_dissector(63322)
363 udp_dissector_table:add(63322, p_nsdp)
364
365