/src/wireshark/epan/dissectors/packet-rx.c
Line | Count | Source |
1 | | /* packet-rx.c |
2 | | * Routines for RX packet dissection |
3 | | * Copyright 1999, Nathan Neulinger <nneul@umr.edu> |
4 | | * Based on routines from tcpdump patches by |
5 | | * Ken Hornstein <kenh@cmf.nrl.navy.mil> |
6 | | * |
7 | | * Wireshark - Network traffic analyzer |
8 | | * By Gerald Combs <gerald@wireshark.org> |
9 | | * Copyright 1998 Gerald Combs |
10 | | * |
11 | | * Copied from packet-tftp.c |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | */ |
15 | | |
16 | | #include "config.h" |
17 | | |
18 | | #include <epan/packet.h> |
19 | | #include "packet-rx.h" |
20 | | #include <epan/addr_resolv.h> |
21 | | |
22 | | /* |
23 | | * See |
24 | | * |
25 | | * http://web.mit.edu/kolya/afs/rx/rx-spec |
26 | | * |
27 | | * XXX - is the "Epoch" really a UN*X time? The high-order bit, according |
28 | | * to that spec, is a flag bit. |
29 | | */ |
30 | | void proto_register_rx(void); |
31 | | void proto_reg_handoff_rx(void); |
32 | | |
33 | | static dissector_handle_t rx_handle; |
34 | | |
35 | 16 | #define UDP_PORT_RX_RANGE "7000-7009,7021" |
36 | | |
37 | | static const value_string rx_types[] = { |
38 | | { RX_PACKET_TYPE_DATA, "data" }, |
39 | | { RX_PACKET_TYPE_ACK, "ack" }, |
40 | | { RX_PACKET_TYPE_BUSY, "busy" }, |
41 | | { RX_PACKET_TYPE_ABORT, "abort" }, |
42 | | { RX_PACKET_TYPE_ACKALL, "ackall" }, |
43 | | { RX_PACKET_TYPE_CHALLENGE, "challenge" }, |
44 | | { RX_PACKET_TYPE_RESPONSE, "response" }, |
45 | | { RX_PACKET_TYPE_DEBUG, "debug" }, |
46 | | { RX_PACKET_TYPE_PARAMS, "params" }, |
47 | | { RX_PACKET_TYPE_VERSION, "version" }, |
48 | | { 0, NULL }, |
49 | | }; |
50 | | |
51 | | static const value_string rx_reason[] = { |
52 | | { RX_ACK_REQUESTED, "Ack Requested" }, |
53 | | { RX_ACK_DUPLICATE, "Duplicate Packet" }, |
54 | | { RX_ACK_OUT_OF_SEQUENCE, "Out Of Sequence" }, |
55 | | { RX_ACK_EXEEDS_WINDOW, "Exceeds Window" }, |
56 | | { RX_ACK_NOSPACE, "No Space" }, |
57 | | { RX_ACK_PING, "Ping" }, |
58 | | { RX_ACK_PING_RESPONSE, "Ping Response" }, |
59 | | { RX_ACK_DELAY, "Delay" }, |
60 | | { RX_ACK_IDLE, "Idle" }, |
61 | | { 0, NULL } |
62 | | }; |
63 | | |
64 | | static const value_string rx_ack_type[] = { |
65 | | { RX_ACK_TYPE_NACK, "NACK" }, |
66 | | { RX_ACK_TYPE_ACK, "ACK" }, |
67 | | { 0, NULL } |
68 | | }; |
69 | | |
70 | | static int proto_rx; |
71 | | static int hf_rx_epoch; |
72 | | static int hf_rx_cid; |
73 | | static int hf_rx_seq; |
74 | | static int hf_rx_serial; |
75 | | static int hf_rx_callnumber; |
76 | | static int hf_rx_type; |
77 | | static int hf_rx_flags; |
78 | | static int hf_rx_flags_clientinit; |
79 | | static int hf_rx_flags_request_ack; |
80 | | static int hf_rx_flags_last_packet; |
81 | | static int hf_rx_flags_more_packets; |
82 | | static int hf_rx_flags_free_packet; |
83 | | static int hf_rx_userstatus; |
84 | | static int hf_rx_securityindex; |
85 | | static int hf_rx_spare; |
86 | | static int hf_rx_serviceid; |
87 | | static int hf_rx_bufferspace; |
88 | | static int hf_rx_maxskew; |
89 | | static int hf_rx_first_packet; |
90 | | static int hf_rx_prev_packet; |
91 | | static int hf_rx_reason; |
92 | | static int hf_rx_numacks; |
93 | | static int hf_rx_ack_type; |
94 | | static int hf_rx_ack; |
95 | | static int hf_rx_challenge; |
96 | | static int hf_rx_version; |
97 | | static int hf_rx_nonce; |
98 | | static int hf_rx_inc_nonce; |
99 | | static int hf_rx_min_level; |
100 | | static int hf_rx_level; |
101 | | static int hf_rx_response; |
102 | | static int hf_rx_encrypted; |
103 | | static int hf_rx_kvno; |
104 | | static int hf_rx_ticket_len; |
105 | | static int hf_rx_ticket; |
106 | | static int hf_rx_ifmtu; |
107 | | static int hf_rx_maxmtu; |
108 | | static int hf_rx_rwind; |
109 | | static int hf_rx_maxpackets; |
110 | | static int hf_rx_abort; |
111 | | static int hf_rx_abortcode; |
112 | | |
113 | | static int ett_rx; |
114 | | static int ett_rx_flags; |
115 | | static int ett_rx_ack; |
116 | | static int ett_rx_challenge; |
117 | | static int ett_rx_response; |
118 | | static int ett_rx_encrypted; |
119 | | static int ett_rx_abort; |
120 | | |
121 | | static dissector_handle_t afs_handle; |
122 | | |
123 | | static int |
124 | | dissect_rx_response_encrypted(tvbuff_t *tvb, proto_tree *parent_tree, int offset) |
125 | 0 | { |
126 | 0 | proto_tree *tree; |
127 | 0 | proto_item *item; |
128 | 0 | int old_offset=offset; |
129 | 0 | int i; |
130 | 0 | uint32_t callnumber; |
131 | |
|
132 | 0 | item = proto_tree_add_item(parent_tree, hf_rx_encrypted, tvb, offset, -1, ENC_NA); |
133 | 0 | tree = proto_item_add_subtree(item, ett_rx_encrypted); |
134 | | |
135 | | /* epoch : 4 bytes */ |
136 | 0 | proto_tree_add_item(tree, hf_rx_epoch, tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN); |
137 | 0 | offset += 4; |
138 | | |
139 | | /* cid : 4 bytes */ |
140 | 0 | proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, ENC_BIG_ENDIAN); |
141 | 0 | offset += 4; |
142 | | |
143 | | /*FIXME don't know how to handle this checksum, skipping it */ |
144 | 0 | offset += 4; |
145 | | |
146 | | /* securityindex : 1 byte */ |
147 | 0 | proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, ENC_BIG_ENDIAN); |
148 | 0 | offset += 4; |
149 | |
|
150 | 0 | for (i=0; i<RX_MAXCALLS; i++) { |
151 | | /* callnumber : 4 bytes */ |
152 | 0 | callnumber = tvb_get_ntohl(tvb, offset); |
153 | 0 | proto_tree_add_uint(tree, hf_rx_callnumber, tvb, |
154 | 0 | offset, 4, callnumber); |
155 | 0 | offset += 4; |
156 | 0 | } |
157 | | |
158 | | /* inc nonce : 4 bytes */ |
159 | 0 | proto_tree_add_item(tree, hf_rx_inc_nonce, tvb, offset, 4, ENC_BIG_ENDIAN); |
160 | 0 | offset += 4; |
161 | | |
162 | | /* level : 4 bytes */ |
163 | 0 | proto_tree_add_item(tree, hf_rx_level, tvb, offset, 4, ENC_BIG_ENDIAN); |
164 | 0 | offset += 4; |
165 | |
|
166 | 0 | proto_item_set_len(item, offset-old_offset); |
167 | 0 | return offset; |
168 | 0 | } |
169 | | |
170 | | |
171 | | static int |
172 | | dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, uint32_t seq, uint32_t callnumber) |
173 | 1 | { |
174 | 1 | proto_tree *tree; |
175 | 1 | proto_item *item; |
176 | 1 | uint32_t version, tl; |
177 | 1 | int old_offset=offset; |
178 | | |
179 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, |
180 | 1 | "RESPONSE Seq: %lu Call: %lu Source Port: %s Destination Port: %s ", |
181 | 1 | (unsigned long)seq, |
182 | 1 | (unsigned long)callnumber, |
183 | 1 | udp_port_to_display(pinfo->pool, pinfo->srcport), |
184 | 1 | udp_port_to_display(pinfo->pool, pinfo->destport) |
185 | 1 | ); |
186 | | |
187 | 1 | item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, -1, ENC_NA); |
188 | 1 | tree = proto_item_add_subtree(item, ett_rx_response); |
189 | | |
190 | 1 | version = tvb_get_ntohl(tvb, offset); |
191 | 1 | proto_tree_add_uint(tree, hf_rx_version, tvb, |
192 | 1 | offset, 4, version); |
193 | 1 | offset += 4; |
194 | | |
195 | 1 | if (version==2) { |
196 | | /* skip unused */ |
197 | 0 | offset += 4; |
198 | | |
199 | | /* encrypted : struct */ |
200 | 0 | offset = dissect_rx_response_encrypted(tvb, tree, offset); |
201 | | |
202 | | /* kvno */ |
203 | 0 | proto_tree_add_item(tree, hf_rx_kvno, tvb, offset, 4, ENC_BIG_ENDIAN); |
204 | 0 | offset += 4; |
205 | | |
206 | | /* ticket_len */ |
207 | 0 | tl = tvb_get_ntohl(tvb, offset); |
208 | 0 | proto_tree_add_uint(tree, hf_rx_ticket_len, tvb, |
209 | 0 | offset, 4, tl); |
210 | 0 | offset += 4; |
211 | |
|
212 | 0 | proto_tree_add_item(tree, hf_rx_ticket, tvb, offset, tl, ENC_NA); |
213 | 0 | offset += tl; |
214 | 0 | } |
215 | | |
216 | 1 | proto_item_set_len(item, offset-old_offset); |
217 | 1 | return offset; |
218 | 1 | } |
219 | | |
220 | | static int |
221 | | dissect_rx_abort(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, uint32_t seq, uint32_t callnumber) |
222 | 1 | { |
223 | 1 | proto_tree *tree; |
224 | 1 | proto_item *item; |
225 | 1 | int old_offset=offset; |
226 | | |
227 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, |
228 | 1 | "ABORT Seq: %lu Call: %lu Source Port: %s Destination Port: %s ", |
229 | 1 | (unsigned long)seq, |
230 | 1 | (unsigned long)callnumber, |
231 | 1 | udp_port_to_display(pinfo->pool, pinfo->srcport), |
232 | 1 | udp_port_to_display(pinfo->pool, pinfo->destport) |
233 | 1 | ); |
234 | | |
235 | 1 | item = proto_tree_add_item(parent_tree, hf_rx_abort, tvb, offset, -1, ENC_NA); |
236 | 1 | tree = proto_item_add_subtree(item, ett_rx_abort); |
237 | | |
238 | | /* abort code */ |
239 | 1 | proto_tree_add_item(tree, hf_rx_abortcode, tvb, offset, 4, ENC_BIG_ENDIAN); |
240 | 1 | offset += 4; |
241 | | |
242 | 1 | proto_item_set_len(item, offset-old_offset); |
243 | 1 | return offset; |
244 | 1 | } |
245 | | |
246 | | |
247 | | static int |
248 | | dissect_rx_challenge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, uint32_t seq, uint32_t callnumber) |
249 | 1 | { |
250 | 1 | proto_tree *tree; |
251 | 1 | proto_item *item; |
252 | 1 | uint32_t version; |
253 | 1 | int old_offset=offset; |
254 | | |
255 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, |
256 | 1 | "CHALLENGE Seq: %lu Call: %lu Source Port: %s Destination Port: %s ", |
257 | 1 | (unsigned long)seq, |
258 | 1 | (unsigned long)callnumber, |
259 | 1 | udp_port_to_display(pinfo->pool, pinfo->srcport), |
260 | 1 | udp_port_to_display(pinfo->pool, pinfo->destport) |
261 | 1 | ); |
262 | | |
263 | 1 | item = proto_tree_add_item(parent_tree, hf_rx_challenge, tvb, offset, -1, ENC_NA); |
264 | 1 | tree = proto_item_add_subtree(item, ett_rx_challenge); |
265 | | |
266 | 1 | version = tvb_get_ntohl(tvb, offset); |
267 | 1 | proto_tree_add_uint(tree, hf_rx_version, tvb, |
268 | 1 | offset, 4, version); |
269 | 1 | offset += 4; |
270 | | |
271 | 1 | if (version==2) { |
272 | 0 | proto_tree_add_item(tree, hf_rx_nonce, tvb, offset, 4, ENC_BIG_ENDIAN); |
273 | 0 | offset += 4; |
274 | |
|
275 | 0 | proto_tree_add_item(tree, hf_rx_min_level, tvb, offset, 4, ENC_BIG_ENDIAN); |
276 | 0 | offset += 4; |
277 | 0 | } |
278 | | |
279 | 1 | proto_item_set_len(item, offset-old_offset); |
280 | 1 | return offset; |
281 | 1 | } |
282 | | |
283 | | static int |
284 | | dissect_rx_acks(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, uint32_t seq, uint32_t callnumber) |
285 | 12 | { |
286 | 12 | proto_tree *tree; |
287 | 12 | proto_item *item; |
288 | 12 | uint8_t num, reason; |
289 | 12 | int old_offset = offset; |
290 | | |
291 | | |
292 | | |
293 | 12 | item = proto_tree_add_item(parent_tree, hf_rx_ack, tvb, offset, -1, ENC_NA); |
294 | 12 | tree = proto_item_add_subtree(item, ett_rx_ack); |
295 | | |
296 | | |
297 | | /* bufferspace: 2 bytes*/ |
298 | 12 | proto_tree_add_item(tree, hf_rx_bufferspace, tvb, offset, 2, ENC_BIG_ENDIAN); |
299 | 12 | offset += 2; |
300 | | |
301 | | /* maxskew: 2 bytes*/ |
302 | 12 | proto_tree_add_item(tree, hf_rx_maxskew, tvb, offset, 2, ENC_BIG_ENDIAN); |
303 | 12 | offset += 2; |
304 | | |
305 | | /* first packet: 4 bytes*/ |
306 | 12 | proto_tree_add_item(tree, hf_rx_first_packet, tvb, offset, 4, ENC_BIG_ENDIAN); |
307 | 12 | offset += 4; |
308 | | |
309 | | /* prev packet: 4 bytes*/ |
310 | 12 | proto_tree_add_item(tree, hf_rx_prev_packet, tvb, offset, 4, ENC_BIG_ENDIAN); |
311 | 12 | offset += 4; |
312 | | |
313 | | /* serial : 4 bytes */ |
314 | 12 | proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, ENC_BIG_ENDIAN); |
315 | 12 | offset += 4; |
316 | | |
317 | | /* reason : 1 byte */ |
318 | 12 | proto_tree_add_item_ret_uint8(tree, hf_rx_reason, tvb, offset, 1, ENC_BIG_ENDIAN, &reason); |
319 | 12 | offset += 1; |
320 | | |
321 | | /* nACKs */ |
322 | 12 | proto_tree_add_item_ret_uint8(tree, hf_rx_numacks, tvb, offset, 1, ENC_NA, &num); |
323 | 12 | offset += 1; |
324 | | |
325 | 228 | while(num--){ |
326 | 216 | proto_tree_add_item(tree, hf_rx_ack_type, tvb, offset, 1, |
327 | 216 | ENC_BIG_ENDIAN); |
328 | 216 | offset += 1; |
329 | 216 | } |
330 | | |
331 | | /* Some implementations add some extra fields. |
332 | | * As far as I can see, these first add 3 padding bytes and then |
333 | | * up to 4 32-bit values. (0,3,4 have been witnessed) |
334 | | * |
335 | | * RX as a protocol seems to be completely undefined and seems to lack |
336 | | * any sort of documentation other than "read the source of any of the |
337 | | * (compatible?) implementations. The OpenAFS source indicates that |
338 | | * 3 bytes of padding are written after the acks. |
339 | | */ |
340 | 12 | if (tvb_reported_length_remaining(tvb, offset)>3) { |
341 | 5 | offset += 3; /* guess. some implementations add 3 bytes */ |
342 | | |
343 | 5 | if (tvb_reported_length_remaining(tvb, offset) >= 4){ |
344 | 3 | proto_tree_add_item(tree, hf_rx_maxmtu, tvb, offset, 4, |
345 | 3 | ENC_BIG_ENDIAN); |
346 | 3 | offset += 4; |
347 | 3 | } |
348 | 5 | if (tvb_reported_length_remaining(tvb, offset) >= 4){ |
349 | 3 | proto_tree_add_item(tree, hf_rx_ifmtu, tvb, offset, 4, |
350 | 3 | ENC_BIG_ENDIAN); |
351 | 3 | offset += 4; |
352 | 3 | } |
353 | 5 | if (tvb_reported_length_remaining(tvb, offset) >= 4){ |
354 | 2 | proto_tree_add_item(tree, hf_rx_rwind, tvb, offset, 4, |
355 | 2 | ENC_BIG_ENDIAN); |
356 | 2 | offset += 4; |
357 | 2 | } |
358 | 5 | if (tvb_reported_length_remaining(tvb, offset) >= 4){ |
359 | 2 | proto_tree_add_item(tree, hf_rx_maxpackets, tvb, offset, 4, |
360 | 2 | ENC_BIG_ENDIAN); |
361 | 2 | offset += 4; |
362 | 2 | } |
363 | 5 | } |
364 | | |
365 | 12 | col_add_fstr(pinfo->cinfo, COL_INFO, |
366 | 12 | "ACK %s " |
367 | 12 | "Seq: %lu " |
368 | 12 | "Call: %lu " |
369 | 12 | "Source Port: %s " |
370 | 12 | "Destination Port: %s ", |
371 | 12 | val_to_str(pinfo->pool, reason, rx_reason, "%d"), |
372 | 12 | (unsigned long)seq, |
373 | 12 | (unsigned long)callnumber, |
374 | 12 | udp_port_to_display(pinfo->pool, pinfo->srcport), |
375 | 12 | udp_port_to_display(pinfo->pool, pinfo->destport) |
376 | 12 | ); |
377 | | |
378 | 12 | proto_item_set_len(item, offset-old_offset); |
379 | 12 | return offset; |
380 | 12 | } |
381 | | |
382 | | |
383 | | static int |
384 | | dissect_rx_flags(tvbuff_t *tvb, struct rxinfo *rxinfo, proto_tree *parent_tree, int offset) |
385 | 35 | { |
386 | 35 | static int * const flags[] = { |
387 | 35 | &hf_rx_flags_free_packet, |
388 | 35 | &hf_rx_flags_more_packets, |
389 | 35 | &hf_rx_flags_last_packet, |
390 | 35 | &hf_rx_flags_request_ack, |
391 | 35 | &hf_rx_flags_clientinit, |
392 | 35 | NULL |
393 | 35 | }; |
394 | | |
395 | 35 | rxinfo->flags = tvb_get_uint8(tvb, offset); |
396 | | |
397 | 35 | proto_tree_add_bitmask(parent_tree, tvb, offset, hf_rx_flags, ett_rx_flags, flags, ENC_NA); |
398 | | |
399 | 35 | offset += 1; |
400 | 35 | return offset; |
401 | 35 | } |
402 | | |
403 | | static int |
404 | | dissect_rx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_) |
405 | 53 | { |
406 | 53 | proto_tree *tree; |
407 | 53 | proto_item *item; |
408 | 53 | const char *version_type; |
409 | 53 | unsigned offset = 0; |
410 | 53 | struct rxinfo rxinfo; |
411 | 53 | uint8_t type; |
412 | 53 | nstime_t ts; |
413 | 53 | uint32_t seq, callnumber; |
414 | 53 | uint16_t serviceid; |
415 | | |
416 | | /* Ensure we have enough data */ |
417 | 53 | if (tvb_captured_length(tvb) < 28) |
418 | 9 | return 0; |
419 | | |
420 | | /* Make sure it's a known type */ |
421 | 44 | type = tvb_get_uint8(tvb, 20); |
422 | 44 | if (!try_val_to_str(type, rx_types)) |
423 | 9 | return 0; |
424 | | |
425 | 35 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "RX"); |
426 | 35 | col_clear(pinfo->cinfo, COL_INFO); |
427 | | |
428 | 35 | item = proto_tree_add_protocol_format(parent_tree, proto_rx, tvb, |
429 | 35 | offset, 28, "RX Protocol"); |
430 | 35 | tree = proto_item_add_subtree(item, ett_rx); |
431 | | |
432 | | /* epoch : 4 bytes */ |
433 | 35 | rxinfo.epoch = tvb_get_ntohl(tvb, offset); |
434 | 35 | ts.secs = rxinfo.epoch; |
435 | 35 | ts.nsecs = 0; |
436 | 35 | proto_tree_add_time(tree, hf_rx_epoch, tvb, offset, 4, &ts); |
437 | 35 | offset += 4; |
438 | | |
439 | | /* cid : 4 bytes */ |
440 | 35 | rxinfo.cid = tvb_get_ntohl(tvb, offset); |
441 | 35 | proto_tree_add_item(tree, hf_rx_cid, tvb, offset, 4, ENC_BIG_ENDIAN); |
442 | 35 | offset += 4; |
443 | | |
444 | | /* callnumber : 4 bytes */ |
445 | 35 | callnumber = tvb_get_ntohl(tvb, offset); |
446 | 35 | proto_tree_add_uint(tree, hf_rx_callnumber, tvb, |
447 | 35 | offset, 4, callnumber); |
448 | 35 | offset += 4; |
449 | 35 | rxinfo.callnumber = callnumber; |
450 | | |
451 | | /* seq : 4 bytes */ |
452 | 35 | seq = tvb_get_ntohl(tvb, offset); |
453 | 35 | proto_tree_add_uint(tree, hf_rx_seq, tvb, |
454 | 35 | offset, 4, seq); |
455 | 35 | offset += 4; |
456 | 35 | rxinfo.seq = seq; |
457 | | |
458 | | /* serial : 4 bytes */ |
459 | 35 | proto_tree_add_item(tree, hf_rx_serial, tvb, offset, 4, ENC_BIG_ENDIAN); |
460 | 35 | offset += 4; |
461 | | |
462 | | /* type : 1 byte */ |
463 | 35 | type = tvb_get_uint8(tvb, offset); |
464 | 35 | proto_tree_add_uint(tree, hf_rx_type, tvb, |
465 | 35 | offset, 1, type); |
466 | 35 | offset += 1; |
467 | 35 | rxinfo.type = type; |
468 | | |
469 | | /* flags : 1 byte */ |
470 | 35 | offset = dissect_rx_flags(tvb, &rxinfo, tree, offset); |
471 | | |
472 | | /* userstatus : 1 byte */ |
473 | 35 | proto_tree_add_item(tree, hf_rx_userstatus, tvb, offset, 1, ENC_BIG_ENDIAN); |
474 | 35 | offset += 1; |
475 | | |
476 | | /* securityindex : 1 byte */ |
477 | 35 | proto_tree_add_item(tree, hf_rx_securityindex, tvb, offset, 1, ENC_BIG_ENDIAN); |
478 | 35 | offset += 1; |
479 | | |
480 | | /* |
481 | | * How clever: even though the AFS header files indicate that the |
482 | | * serviceId is first, it's really encoded _after_ the spare field. |
483 | | * I wasted a day figuring that out! |
484 | | */ |
485 | | |
486 | | /* spare */ |
487 | 35 | proto_tree_add_item(tree, hf_rx_spare, tvb, offset, 2, ENC_BIG_ENDIAN); |
488 | 35 | offset += 2; |
489 | | |
490 | | /* service id : 2 bytes */ |
491 | 35 | serviceid = tvb_get_ntohs(tvb, offset); |
492 | 35 | proto_tree_add_uint(tree, hf_rx_serviceid, tvb, |
493 | 35 | offset, 2, serviceid); |
494 | 35 | offset += 2; |
495 | 35 | rxinfo.serviceid = serviceid; |
496 | | |
497 | 35 | switch (type) { |
498 | 12 | case RX_PACKET_TYPE_ACK: |
499 | | /*dissect_rx_acks(tvb, pinfo, parent_tree, offset, |
500 | | can't create it in a parallel tree, then ett search |
501 | | won't work */ |
502 | 12 | dissect_rx_acks(tvb, pinfo, tree, offset, |
503 | 12 | seq, callnumber); |
504 | 12 | break; |
505 | 1 | case RX_PACKET_TYPE_ACKALL: |
506 | | /* does not contain any payload */ |
507 | 1 | col_add_fstr(pinfo->cinfo, COL_INFO, |
508 | 1 | "ACKALL Seq: %lu Call: %lu Source Port: %s Destination Port: %s ", |
509 | 1 | (unsigned long)seq, |
510 | 1 | (unsigned long)callnumber, |
511 | 1 | udp_port_to_display(pinfo->pool, pinfo->srcport), |
512 | 1 | udp_port_to_display(pinfo->pool, pinfo->destport) |
513 | 1 | ); |
514 | 1 | break; |
515 | 2 | case RX_PACKET_TYPE_VERSION: |
516 | | /* does not contain any payload */ |
517 | 2 | if (rxinfo.cid == 0) |
518 | 1 | version_type = "NAT ping"; |
519 | 1 | else |
520 | 1 | version_type = "request"; |
521 | | |
522 | 2 | col_add_fstr(pinfo->cinfo, COL_INFO, |
523 | 2 | "VERSION %s Seq: %lu Call: %lu Source Port: %s Destination Port: %s ", |
524 | 2 | version_type, |
525 | 2 | (unsigned long)seq, |
526 | 2 | (unsigned long)callnumber, |
527 | 2 | udp_port_to_display(pinfo->pool, pinfo->srcport), |
528 | 2 | udp_port_to_display(pinfo->pool, pinfo->destport) |
529 | 2 | ); |
530 | 2 | break; |
531 | 1 | case RX_PACKET_TYPE_CHALLENGE: |
532 | 1 | dissect_rx_challenge(tvb, pinfo, tree, offset, seq, callnumber); |
533 | 1 | break; |
534 | 1 | case RX_PACKET_TYPE_RESPONSE: |
535 | 1 | dissect_rx_response(tvb, pinfo, tree, offset, seq, callnumber); |
536 | 1 | break; |
537 | 16 | case RX_PACKET_TYPE_DATA: { |
538 | 16 | tvbuff_t *next_tvb; |
539 | | |
540 | 16 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
541 | 16 | call_dissector_with_data(afs_handle, next_tvb, pinfo, parent_tree, &rxinfo); |
542 | 16 | }; |
543 | 16 | break; |
544 | 1 | case RX_PACKET_TYPE_ABORT: |
545 | 1 | dissect_rx_abort(tvb, pinfo, tree, offset, seq, callnumber); |
546 | 1 | break; |
547 | 35 | } |
548 | | |
549 | 28 | return tvb_captured_length(tvb); |
550 | 35 | } |
551 | | |
552 | | void |
553 | | proto_register_rx(void) |
554 | 16 | { |
555 | 16 | static hf_register_info hf[] = { |
556 | 16 | { &hf_rx_epoch, { |
557 | 16 | "Epoch", "rx.epoch", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, |
558 | 16 | NULL, 0, NULL, HFILL }}, |
559 | | |
560 | 16 | { &hf_rx_cid, { |
561 | 16 | "CID", "rx.cid", FT_UINT32, BASE_DEC, |
562 | 16 | NULL, 0, NULL, HFILL }}, |
563 | | |
564 | 16 | { &hf_rx_callnumber, { |
565 | 16 | "Call Number", "rx.callnumber", FT_UINT32, BASE_DEC, |
566 | 16 | NULL, 0, NULL, HFILL }}, |
567 | | |
568 | 16 | { &hf_rx_seq, { |
569 | 16 | "Sequence Number", "rx.seq", FT_UINT32, BASE_DEC, |
570 | 16 | NULL, 0, NULL, HFILL }}, |
571 | | |
572 | 16 | { &hf_rx_serial, { |
573 | 16 | "Serial", "rx.serial", FT_UINT32, BASE_DEC, |
574 | 16 | NULL, 0, NULL, HFILL }}, |
575 | | |
576 | 16 | { &hf_rx_type, { |
577 | 16 | "Type", "rx.type", FT_UINT8, BASE_DEC, |
578 | 16 | VALS(rx_types), 0, NULL, HFILL }}, |
579 | | |
580 | 16 | { &hf_rx_flags, { |
581 | 16 | "Flags", "rx.flags", FT_UINT8, BASE_HEX, |
582 | 16 | NULL, 0, NULL, HFILL }}, |
583 | | |
584 | 16 | { &hf_rx_flags_clientinit, { |
585 | 16 | "Client Initiated", "rx.flags.client_init", FT_BOOLEAN, 8, |
586 | 16 | NULL, RX_CLIENT_INITIATED, NULL, HFILL }}, |
587 | | |
588 | 16 | { &hf_rx_flags_request_ack, { |
589 | 16 | "Request Ack", "rx.flags.request_ack", FT_BOOLEAN, 8, |
590 | 16 | NULL, RX_REQUEST_ACK, NULL, HFILL }}, |
591 | | |
592 | 16 | { &hf_rx_flags_last_packet, { |
593 | 16 | "Last Packet", "rx.flags.last_packet", FT_BOOLEAN, 8, |
594 | 16 | NULL, RX_LAST_PACKET, NULL, HFILL }}, |
595 | | |
596 | 16 | { &hf_rx_flags_more_packets, { |
597 | 16 | "More Packets", "rx.flags.more_packets", FT_BOOLEAN, 8, |
598 | 16 | NULL, RX_MORE_PACKETS, NULL, HFILL }}, |
599 | | |
600 | 16 | { &hf_rx_flags_free_packet, { |
601 | 16 | "Free Packet", "rx.flags.free_packet", FT_BOOLEAN, 8, |
602 | 16 | NULL, RX_FREE_PACKET, NULL, HFILL }}, |
603 | | |
604 | | /* XXX - what about RX_SLOW_START_OR_JUMBO? */ |
605 | | |
606 | 16 | { &hf_rx_userstatus, { |
607 | 16 | "User Status", "rx.userstatus", FT_UINT32, BASE_DEC, |
608 | 16 | NULL, 0, NULL, HFILL }}, |
609 | | |
610 | 16 | { &hf_rx_securityindex, { |
611 | 16 | "Security Index", "rx.securityindex", FT_UINT32, BASE_DEC, |
612 | 16 | NULL, 0, NULL, HFILL }}, |
613 | | |
614 | 16 | { &hf_rx_spare, { |
615 | 16 | "Spare/Checksum", "rx.spare", FT_UINT16, BASE_DEC, |
616 | 16 | NULL, 0, NULL, HFILL }}, |
617 | | |
618 | 16 | { &hf_rx_serviceid, { |
619 | 16 | "Service ID", "rx.serviceid", FT_UINT16, BASE_DEC, |
620 | 16 | NULL, 0, NULL, HFILL }}, |
621 | | |
622 | 16 | { &hf_rx_bufferspace, { |
623 | 16 | "Bufferspace", "rx.bufferspace", FT_UINT16, BASE_DEC, |
624 | 16 | NULL, 0, "Number Of Packets Available", HFILL }}, |
625 | | |
626 | 16 | { &hf_rx_maxskew, { |
627 | 16 | "Max Skew", "rx.maxskew", FT_UINT16, BASE_DEC, |
628 | 16 | NULL, 0, NULL, HFILL }}, |
629 | | |
630 | 16 | { &hf_rx_first_packet, { |
631 | 16 | "First Packet", "rx.first", FT_UINT32, BASE_DEC, |
632 | 16 | NULL, 0, NULL, HFILL }}, |
633 | | |
634 | 16 | { &hf_rx_prev_packet, { |
635 | 16 | "Prev Packet", "rx.prev", FT_UINT32, BASE_DEC, |
636 | 16 | NULL, 0, "Previous Packet", HFILL }}, |
637 | | |
638 | 16 | { &hf_rx_reason, { |
639 | 16 | "Reason", "rx.reason", FT_UINT8, BASE_DEC, |
640 | 16 | VALS(rx_reason), 0, "Reason For This ACK", HFILL }}, |
641 | | |
642 | 16 | { &hf_rx_numacks, { |
643 | 16 | "Num ACKs", "rx.num_acks", FT_UINT8, BASE_DEC, |
644 | 16 | NULL, 0, "Number Of ACKs", HFILL }}, |
645 | | |
646 | 16 | { &hf_rx_ack_type, { |
647 | 16 | "ACK Type", "rx.ack_type", FT_UINT8, BASE_DEC, |
648 | 16 | VALS(rx_ack_type), 0, "Type Of ACKs", HFILL }}, |
649 | | |
650 | 16 | { &hf_rx_ack, { |
651 | 16 | "ACK Packet", "rx.ack", FT_NONE, BASE_NONE, |
652 | 16 | NULL, 0, NULL, HFILL }}, |
653 | | |
654 | 16 | { &hf_rx_challenge, { |
655 | 16 | "CHALLENGE Packet", "rx.challenge", FT_NONE, BASE_NONE, |
656 | 16 | NULL, 0, NULL, HFILL }}, |
657 | | |
658 | 16 | { &hf_rx_version, { |
659 | 16 | "Version", "rx.version", FT_UINT32, BASE_DEC, |
660 | 16 | NULL, 0, "Version Of Challenge/Response", HFILL }}, |
661 | | |
662 | 16 | { &hf_rx_nonce, { |
663 | 16 | "Nonce", "rx.nonce", FT_UINT32, BASE_HEX, |
664 | 16 | NULL, 0, NULL, HFILL }}, |
665 | | |
666 | 16 | { &hf_rx_inc_nonce, { |
667 | 16 | "Inc Nonce", "rx.inc_nonce", FT_UINT32, BASE_HEX, |
668 | 16 | NULL, 0, "Incremented Nonce", HFILL }}, |
669 | | |
670 | 16 | { &hf_rx_min_level, { |
671 | 16 | "Min Level", "rx.min_level", FT_UINT32, BASE_DEC, |
672 | 16 | NULL, 0, NULL, HFILL }}, |
673 | | |
674 | 16 | { &hf_rx_level, { |
675 | 16 | "Level", "rx.level", FT_UINT32, BASE_DEC, |
676 | 16 | NULL, 0, NULL, HFILL }}, |
677 | | |
678 | 16 | { &hf_rx_response, { |
679 | 16 | "RESPONSE Packet", "rx.response", FT_NONE, BASE_NONE, |
680 | 16 | NULL, 0, NULL, HFILL }}, |
681 | | |
682 | 16 | { &hf_rx_abort, { |
683 | 16 | "ABORT Packet", "rx.abort", FT_NONE, BASE_NONE, |
684 | 16 | NULL, 0, NULL, HFILL }}, |
685 | | |
686 | 16 | { &hf_rx_encrypted, { |
687 | 16 | "Encrypted", "rx.encrypted", FT_NONE, BASE_NONE, |
688 | 16 | NULL, 0, "Encrypted part of response packet", HFILL }}, |
689 | | |
690 | 16 | { &hf_rx_kvno, { |
691 | 16 | "kvno", "rx.kvno", FT_UINT32, BASE_DEC, |
692 | 16 | NULL, 0, NULL, HFILL }}, |
693 | | |
694 | 16 | { &hf_rx_ticket_len, { |
695 | 16 | "Ticket len", "rx.ticket_len", FT_UINT32, BASE_DEC, |
696 | 16 | NULL, 0, "Ticket Length", HFILL }}, |
697 | | |
698 | 16 | { &hf_rx_ticket, { |
699 | 16 | "ticket", "rx.ticket", FT_BYTES, BASE_NONE, |
700 | 16 | NULL, 0, NULL, HFILL }}, |
701 | | |
702 | 16 | { &hf_rx_ifmtu, { |
703 | 16 | "Interface MTU", "rx.if_mtu", FT_UINT32, BASE_DEC, |
704 | 16 | NULL, 0, NULL, HFILL }}, |
705 | | |
706 | 16 | { &hf_rx_maxmtu, { |
707 | 16 | "Max MTU", "rx.max_mtu", FT_UINT32, BASE_DEC, |
708 | 16 | NULL, 0, NULL, HFILL }}, |
709 | | |
710 | 16 | { &hf_rx_rwind, { |
711 | 16 | "rwind", "rx.rwind", FT_UINT32, BASE_DEC, |
712 | 16 | NULL, 0, NULL, HFILL }}, |
713 | | |
714 | 16 | { &hf_rx_maxpackets, { |
715 | 16 | "Max Packets", "rx.max_packets", FT_UINT32, BASE_DEC, |
716 | 16 | NULL, 0, NULL, HFILL }}, |
717 | | |
718 | 16 | { &hf_rx_abortcode, { |
719 | 16 | "Abort Code", "rx.abort_code", FT_INT32, BASE_DEC, |
720 | 16 | NULL, 0, NULL, HFILL }}, |
721 | | |
722 | 16 | }; |
723 | 16 | static int *ett[] = { |
724 | 16 | &ett_rx, |
725 | 16 | &ett_rx_flags, |
726 | 16 | &ett_rx_ack, |
727 | 16 | &ett_rx_challenge, |
728 | 16 | &ett_rx_response, |
729 | 16 | &ett_rx_encrypted, |
730 | 16 | &ett_rx_abort |
731 | 16 | }; |
732 | | |
733 | 16 | proto_rx = proto_register_protocol("RX Protocol", "RX", "rx"); |
734 | 16 | proto_register_field_array(proto_rx, hf, array_length(hf)); |
735 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
736 | | |
737 | 16 | rx_handle = register_dissector("rx", dissect_rx, proto_rx); |
738 | 16 | } |
739 | | |
740 | | void |
741 | | proto_reg_handoff_rx(void) |
742 | 16 | { |
743 | | /* |
744 | | * Get handle for the AFS dissector. |
745 | | */ |
746 | 16 | afs_handle = find_dissector_add_dependency("afs", proto_rx); |
747 | | |
748 | 16 | dissector_add_uint_range_with_preference("udp.port", UDP_PORT_RX_RANGE, rx_handle); |
749 | 16 | } |
750 | | |
751 | | /* |
752 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
753 | | * |
754 | | * Local variables: |
755 | | * c-basic-offset: 8 |
756 | | * tab-width: 8 |
757 | | * indent-tabs-mode: t |
758 | | * End: |
759 | | * |
760 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
761 | | * :indentSize=8:tabSize=8:noTabs=yes: |
762 | | */ |