3 * Redback Lawful Intercept Packet dissector
5 * Copyright 2008 Florian Lohoff <flo[AT]rfc822.org>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald[AT]wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
16 #include <epan/packet.h>
18 void proto_register_redbackli(void);
19 void proto_reg_handoff_redbackli(void);
21 static int proto_redbackli
;
23 static int hf_redbackli_avptype
;
24 static int hf_redbackli_avplen
;
25 static int hf_redbackli_seqno
; /* Sequence No */
26 static int hf_redbackli_liid
; /* LI Id */
27 static int hf_redbackli_sessid
; /* Session Id */
28 static int hf_redbackli_label
; /* Label */
29 static int hf_redbackli_acctid
; /* Accounting Session Id */
30 static int hf_redbackli_dir
; /* Direction */
31 static int hf_redbackli_eohpad
; /* End Of Header Padding */
32 static int hf_redbackli_unknownavp
; /* Unknown AVP */
34 static int ett_redbackli
;
36 static dissector_handle_t ip_handle
;
37 static dissector_handle_t redbackli_handle
;
40 #define RB_AVP_SEQNO 1
42 #define RB_AVP_SESSID 3
44 #define RB_AVP_LABEL 20
45 #define RB_AVP_ACCTID 40
48 static const value_string avp_names
[] = {
49 {RB_AVP_SEQNO
, "Sequence No"},
50 {RB_AVP_LIID
, "Lawful Intercept Id"},
51 {RB_AVP_SESSID
, "Session Id"},
52 {RB_AVP_LABEL
, "Label"},
53 {RB_AVP_ACCTID
, "Accounting Session Id"},
54 {RB_AVP_DIR
, "Direction"},
55 {RB_AVP_EOH
, "End Of Header"},
60 redbackli_dissect_avp(uint8_t avptype
, uint8_t avplen
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
)
63 proto_tree
*st
= NULL
;
65 avpname
= val_to_str_const(avptype
, avp_names
, "Unknown");
67 st
= proto_tree_add_subtree_format(tree
, tvb
, offset
, avplen
+2, ett_redbackli
, NULL
, "%s AVP", avpname
);
69 proto_tree_add_uint(st
, hf_redbackli_avptype
, tvb
, offset
, 1, avptype
);
70 proto_tree_add_uint(st
, hf_redbackli_avplen
, tvb
, offset
+1, 1, avplen
);
75 /* XXX: ToDo: Validate the length (avplen) of the fixed length fields
76 before calling proto_tree_add_item().
77 Note that the field lengths have been validated when
78 dissect_avp() is called from redbackli_dissect_heur().
83 proto_tree_add_item(st
, hf_redbackli_seqno
, tvb
,
84 offset
+2, avplen
, ENC_BIG_ENDIAN
);
87 proto_tree_add_item(st
, hf_redbackli_liid
, tvb
,
88 offset
+2, avplen
, ENC_BIG_ENDIAN
);
91 proto_tree_add_item(st
, hf_redbackli_sessid
, tvb
,
92 offset
+2, avplen
, ENC_BIG_ENDIAN
);
95 proto_tree_add_item(st
, hf_redbackli_label
, tvb
,
96 offset
+2, avplen
, ENC_ASCII
);
99 proto_tree_add_item(st
, hf_redbackli_eohpad
, tvb
,
100 offset
+2, avplen
, ENC_NA
);
103 proto_tree_add_item(st
, hf_redbackli_dir
, tvb
,
104 offset
+2, avplen
, ENC_NA
);
107 proto_tree_add_item(st
, hf_redbackli_acctid
, tvb
,
108 offset
+2, avplen
, ENC_NA
);
111 proto_tree_add_item(st
, hf_redbackli_unknownavp
, tvb
,
112 offset
+2, avplen
, ENC_NA
);
120 redbackli_dissect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
122 uint8_t avptype
, avplen
;
126 proto_tree
*redbackli_tree
= NULL
;
129 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RBLI");
131 ti
= proto_tree_add_item(tree
, proto_redbackli
,
133 redbackli_tree
= proto_item_add_subtree(ti
, ett_redbackli
);
135 len
= tvb_reported_length(tvb
);
138 while (!eoh
&& (len
> 2)) {
139 avptype
= tvb_get_uint8(tvb
, offset
+0);
140 avplen
= tvb_get_uint8(tvb
, offset
+1);
142 if ((len
-2) < avplen
) /* AVP Complete ? */
146 redbackli_dissect_avp(avptype
, avplen
, tvb
, offset
, redbackli_tree
);
148 if (avptype
== RB_AVP_EOH
)
151 offset
+= 2 + avplen
;
155 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
156 call_dissector(ip_handle
, next_tvb
, pinfo
, tree
);
158 return tvb_captured_length(tvb
);
162 #define REDBACKLI_INTSIZE 6
163 #define REDBACKLI_EOHSIZE 2
164 #define MIN_REDBACKLI_SIZE (3*REDBACKLI_INTSIZE+REDBACKLI_EOHSIZE)
167 redbackli_dissect_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
171 uint8_t avptype
, avplen
;
172 uint32_t avpfound
= 0;
174 len
= tvb_captured_length(tvb
);
175 if (len
< MIN_REDBACKLI_SIZE
)
179 * We scan the possible AVPs and look out for mismatches.
180 * An int AVP needs to be 4 byte long, and the eoh must be 0 or 1
181 * long .. Unknown AVPs also mean not for us ...
184 while ((len
> 2) && !eoh
) {
185 avptype
= tvb_get_uint8(tvb
, offset
+0);
186 avplen
= tvb_get_uint8(tvb
, offset
+1);
194 avpfound
|= 1<<avptype
;
197 if (avplen
> 1 || offset
== 0)
202 case(RB_AVP_DIR
): /* Is this correct? the hf_ originally had FT_UINT8 for DIR */
208 offset
+= 2 + avplen
;
212 if (!(avpfound
& (1<<RB_AVP_SEQNO
)))
214 if (!(avpfound
& (1<<RB_AVP_SESSID
)))
216 if (!(avpfound
& (1<<RB_AVP_LIID
)))
219 redbackli_dissect(tvb
, pinfo
, tree
, data
);
223 void proto_register_redbackli(void) {
224 static hf_register_info hf
[] = {
225 { &hf_redbackli_avptype
,
226 { "AVP Type", "redbackli.avptype", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
228 { &hf_redbackli_avplen
,
229 { "AVP Length", "redbackli.avplen", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
231 { &hf_redbackli_seqno
,
232 { "Sequence No", "redbackli.seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
234 { &hf_redbackli_liid
,
235 { "Lawful Intercept Id", "redbackli.liid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
236 "LI Identifier", HFILL
}},
237 { &hf_redbackli_sessid
,
238 { "Session Id", "redbackli.sessid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
239 "Session Identifier", HFILL
}},
240 /* XXX: If one goes by the heuristic then this field can be variable length ??
241 * In the absence of any documentation We'll assume that's the case
242 * (even though 'direction' sounds like a fixed length field
245 { "Direction", "redbackli.dir", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
247 { &hf_redbackli_label
,
248 { "Label", "redbackli.label", FT_STRING
, BASE_NONE
, NULL
, 0x0,
250 { &hf_redbackli_acctid
,
251 { "Acctid", "redbackli.acctid", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
253 { &hf_redbackli_eohpad
,
254 { "End of Header Padding", "redbackli.eohpad", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
256 { &hf_redbackli_unknownavp
,
257 { "Unknown AVP", "redbackli.unknownavp", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
261 static int *ett
[] = {
265 proto_redbackli
= proto_register_protocol("Redback Lawful Intercept", "RedbackLI", "redbackli");
267 proto_register_field_array(proto_redbackli
, hf
, array_length(hf
));
268 proto_register_subtree_array(ett
, array_length(ett
));
270 redbackli_handle
= register_dissector("redbackli", redbackli_dissect
, proto_redbackli
);
273 void proto_reg_handoff_redbackli(void) {
274 ip_handle
= find_dissector_add_dependency("ip", proto_redbackli
);
276 dissector_add_for_decode_as_with_preference("udp.port", redbackli_handle
);
278 heur_dissector_add("udp", redbackli_dissect_heur
, "Redback Lawful Intercept over UDP", "redbackli_udp", proto_redbackli
, HEURISTIC_ENABLE
);
283 * Editor modelines - https://www.wireshark.org/tools/modelines.html
288 * indent-tabs-mode: t
291 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
292 * :indentSize=8:tabSize=8:noTabs=false: