Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
 */