Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rlm.c
Line
Count
Source
1
/* packet-rlm.c
2
 * Routines for RLM dissection
3
 * Copyright 2004, Duncan Sargeant <dunc-ethereal@rcpt.to>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
 * RLM is a proprietary Cisco protocol used for centralling managing
14
 * many redundant NASes.  I don't know much about the format, but you
15
 * can read about the feature here:
16
 *
17
 * http://www.cisco.com/en/US/docs/ios/12_0t/12_0t3/feature/guide/rlm_123.html
18
 *
19
 * RLM runs on a UDP port (default 3000) between the MGC and the NAS.
20
 * On port N+1 (default 3001), a Q.931/LAPD/UDP connection is maintained.
21
 * Both sides use the same local port number for the connection, so source
22
 * and dest port are always the same.
23
 *
24
 * In large networks, the links are typically split onto higher ports,
25
 * so anything up to 3015 (or higher) could either be RLM or Q.931 traffic,
26
 * although always the RLM has the one lower port number for that RLM group.
27
 *
28
 * Multiple RLM groups are possible on a single NAS.
29
 *
30
 * I haven't been able to find the protocol documented, so I've
31
 * guessed some of the fields based on the output of debug commands on
32
 * cisco NASes.
33
 *
34
 */
35
36
#include "config.h"
37
38
#include <epan/packet.h>
39
40
void proto_register_rlm(void);
41
void proto_reg_handoff_rlm(void);
42
43
/* Initialize the protocol and registered fields */
44
static int proto_rlm;
45
46
static int hf_rlm_version;
47
static int hf_rlm_type;
48
static int hf_rlm_unknown;
49
static int hf_rlm_tid;
50
static int hf_rlm_unknown2;
51
52
/* Initialize the subtree pointers */
53
static int ett_rlm;
54
55
56
/* RLM definitions - missing some! */
57
58
0
#define RLM_START_REQUEST 1
59
0
#define RLM_START_ACK   2
60
/* #define ???  3 */
61
/* #define ???  4 */
62
0
#define RLM_ECHO_REQUEST  5
63
0
#define RLM_ECHO_REPLY    6
64
/* #define ???  ?? */
65
66
/* Code to actually dissect the packets */
67
static bool
68
dissect_rlm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
69
1.40k
{
70
1.40k
  proto_item *ti;
71
1.40k
  proto_tree *rlm_tree;
72
1.40k
  uint8_t rlm_type, version;
73
1.40k
  const char *type_str = NULL;
74
75
1.40k
  if (pinfo->srcport < 3000 || pinfo->srcport > 3015
76
13
      || pinfo->destport < 3000 || pinfo->destport > 3015
77
3
      || pinfo->destport != pinfo->srcport)
78
1.40k
    return false;
79
80
2
  if (tvb_captured_length(tvb) < 2)
81
1
    return false;
82
83
1
  version  = tvb_get_uint8(tvb, 0);
84
1
  rlm_type = tvb_get_uint8(tvb, 1);
85
86
  /* we only know about version 2, and I've only seen 8 byte packets */
87
1
  if (tvb_captured_length(tvb) != 8 || version != 2) {
88
1
    return false;
89
1
  }
90
91
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLM");
92
93
0
  switch (rlm_type) {
94
0
    case RLM_START_REQUEST:
95
0
      type_str = "Start request";
96
0
      break;
97
98
0
    case RLM_START_ACK:
99
0
      type_str = "Start acknowledgement";
100
0
      break;
101
102
0
    case RLM_ECHO_REQUEST:
103
0
      type_str = "Echo request";
104
0
      break;
105
106
0
    case RLM_ECHO_REPLY:
107
0
      type_str = "Echo reply";
108
0
      break;
109
110
0
    default:
111
0
      type_str = "Unknown type";
112
0
      break;
113
0
  }
114
115
0
  col_set_str(pinfo->cinfo, COL_INFO, type_str);
116
117
0
  if (tree) {
118
    /* proto_tree_add_protocol_format(tree, proto_rlm, tvb, 0,
119
      16, "Cisco Session Management"); */
120
0
    ti = proto_tree_add_item(tree, proto_rlm, tvb, 0, 8, ENC_NA);
121
0
    rlm_tree = proto_item_add_subtree(ti, ett_rlm);
122
0
    proto_tree_add_item(rlm_tree, hf_rlm_version, tvb, 0, 1, ENC_BIG_ENDIAN);
123
0
    proto_tree_add_uint_format_value(rlm_tree, hf_rlm_type, tvb, 1, 1, rlm_type, "%u (%s)", rlm_type, type_str);
124
0
    proto_tree_add_item(rlm_tree, hf_rlm_unknown, tvb, 2, 2, ENC_BIG_ENDIAN);
125
0
    proto_tree_add_item(rlm_tree, hf_rlm_tid, tvb, 4, 2, ENC_BIG_ENDIAN);
126
0
    proto_tree_add_item(rlm_tree, hf_rlm_unknown2, tvb, 6, 2, ENC_BIG_ENDIAN);
127
0
  }
128
129
0
  return true;
130
0
}
131
132
133
/* Register the protocol with Wireshark */
134
135
/* this format is require because a script is used to build the C function
136
   that calls all the protocol registration.
137
*/
138
139
void
140
proto_reg_handoff_rlm(void)
141
14
{
142
14
  heur_dissector_add("udp", dissect_rlm, "Redundant Link Management over UDP", "rlm_udp", proto_rlm, HEURISTIC_ENABLE);
143
14
}
144
145
void
146
proto_register_rlm(void)
147
14
{
148
149
/* Setup list of header fields  See Section 1.6.1 for details*/
150
14
  static hf_register_info hf[] = {
151
14
    { &hf_rlm_version,
152
14
      { "Version",           "rlm.version",
153
14
      FT_UINT8, BASE_DEC, NULL, 0x0,
154
14
      NULL, HFILL }
155
14
    },
156
14
    { &hf_rlm_type,
157
14
      { "Type",           "rlm.type",
158
14
      FT_UINT8, BASE_DEC, NULL, 0x0,
159
14
      NULL, HFILL }
160
14
    },
161
14
    { &hf_rlm_unknown,
162
14
      { "Unknown",           "rlm.unknown",
163
14
      FT_UINT16, BASE_HEX, NULL, 0x0,
164
14
      NULL, HFILL }
165
14
    },
166
14
    { &hf_rlm_tid,
167
14
      { "Transaction ID",           "rlm.tid",
168
14
      FT_UINT16, BASE_DEC, NULL, 0x0,
169
14
      NULL, HFILL }
170
14
    },
171
14
    { &hf_rlm_unknown2,
172
14
      { "Unknown",           "rlm.unknown2",
173
14
      FT_UINT16, BASE_HEX, NULL, 0x0,
174
14
      NULL, HFILL }
175
14
    },
176
14
  };
177
178
/* Setup protocol subtree array */
179
14
  static int *ett[] = {
180
14
    &ett_rlm,
181
14
  };
182
183
/* Register the protocol name and description */
184
14
  proto_rlm = proto_register_protocol("Redundant Link Management Protocol",
185
14
      "RLM", "rlm");
186
187
/* Required function calls to register the header fields and subtrees used */
188
14
  proto_register_field_array(proto_rlm, hf, array_length(hf));
189
14
  proto_register_subtree_array(ett, array_length(ett));
190
14
}
191
192
/*
193
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
194
 *
195
 * Local variables:
196
 * c-basic-offset: 8
197
 * tab-width: 8
198
 * indent-tabs-mode: t
199
 * End:
200
 *
201
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
202
 * :indentSize=8:tabSize=8:noTabs=false:
203
 */