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 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/addr_resolv.h>
32 #include <epan/strutil.h>
34 void proto_register_redbackli(void);
35 void proto_reg_handoff_redbackli(void);
37 static int proto_redbackli = -1;
39 static int hf_redbackli_seqno = -1; /* Sequence No */
40 static int hf_redbackli_liid = -1; /* LI Id */
41 static int hf_redbackli_sessid = -1; /* Session Id */
42 static int hf_redbackli_label = -1; /* Label */
43 static int hf_redbackli_acctid = -1; /* Accounting Session Id */
44 static int hf_redbackli_dir = -1; /* Direction */
45 static int hf_redbackli_eohpad = -1; /* End Of Header Padding */
46 static int hf_redbackli_unknownavp = -1; /* Unknown AVP */
48 static int ett_redbackli = -1;
50 static dissector_handle_t ip_handle;
52 #define RB_AVP_SEQNO 1
54 #define RB_AVP_SESSID 3
56 #define RB_AVP_LABEL 20
57 #define RB_AVP_ACCTID 40
60 static const value_string avp_names[] = {
61 {RB_AVP_SEQNO, "Sequence No"},
62 {RB_AVP_LIID, "Lawful Intercept Id"},
63 {RB_AVP_SESSID, "Session Id"},
64 {RB_AVP_LABEL, "Label"},
65 {RB_AVP_ACCTID, "Accounting Session Id"},
66 {RB_AVP_DIR, "Direction"},
67 {RB_AVP_EOH, "End Of Header"},
72 redbackli_dissect_avp(guint8 avptype, guint8 avplen, tvbuff_t *tvb, gint offset, proto_tree *tree)
75 proto_tree *ti, *st = NULL;
77 avpname = val_to_str_const(avptype, avp_names, "Unknown");
79 ti = proto_tree_add_text(tree, tvb, offset, avplen+2, "%s AVP", avpname);
80 st = proto_item_add_subtree(ti, ett_redbackli);
82 proto_tree_add_text(st, tvb, offset, 1, "AVP Type: %d", avptype);
83 proto_tree_add_text(st, tvb, offset+1, 1, "AVP Length: %d", avplen);
88 /* XXX: ToDo: Validate the length (avplen) of the fixed length fields
89 before calling proto_tree_add_item().
90 Note that the field lengths have been validated when
91 dissect_avp() is called from redbackli_dissect_heur().
96 proto_tree_add_item(st, hf_redbackli_seqno, tvb,
97 offset+2, avplen, ENC_BIG_ENDIAN);
100 proto_tree_add_item(st, hf_redbackli_liid, tvb,
101 offset+2, avplen, ENC_BIG_ENDIAN);
104 proto_tree_add_item(st, hf_redbackli_sessid, tvb,
105 offset+2, avplen, ENC_BIG_ENDIAN);
108 proto_tree_add_item(st, hf_redbackli_label, tvb,
109 offset+2, avplen, ENC_ASCII|ENC_NA);
112 proto_tree_add_item(st, hf_redbackli_eohpad, tvb,
113 offset+2, avplen, ENC_NA);
116 proto_tree_add_item(st, hf_redbackli_dir, tvb,
117 offset+2, avplen, ENC_NA);
120 proto_tree_add_item(st, hf_redbackli_acctid, tvb,
121 offset+2, avplen, ENC_NA);
124 proto_tree_add_item(st, hf_redbackli_unknownavp, tvb,
125 offset+2, avplen, ENC_NA);
133 redbackli_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
135 guint8 avptype, avplen;
136 gint len, offset = 0;
138 proto_tree *ti, *redbackli_tree = NULL;
141 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RBLI");
144 ti = proto_tree_add_item(tree, proto_redbackli,
146 redbackli_tree = proto_item_add_subtree(ti, ett_redbackli);
149 len = tvb_length(tvb);
152 while (!eoh && (len > 2)) {
153 avptype = tvb_get_guint8(tvb, offset+0);
154 avplen = tvb_get_guint8(tvb, offset+1);
156 if ((len-2) < avplen) /* AVP Complete ? */
160 redbackli_dissect_avp(avptype, avplen, tvb, offset, redbackli_tree);
162 if (avptype == RB_AVP_EOH)
165 offset += 2 + avplen;
169 next_tvb = tvb_new_subset_remaining(tvb, offset);
170 call_dissector(ip_handle, next_tvb, pinfo, tree);
174 #define REDBACKLI_INTSIZE 6
175 #define REDBACKLI_EOHSIZE 2
176 #define MIN_REDBACKLI_SIZE (3*REDBACKLI_INTSIZE+REDBACKLI_EOHSIZE)
179 redbackli_dissect_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
181 gint len, offset = 0;
182 gboolean eoh = FALSE;
183 guint8 avptype, avplen;
184 guint32 avpfound = 0;
186 len = tvb_length(tvb);
187 if (len < MIN_REDBACKLI_SIZE)
191 * We scan the possible AVPs and look out for mismatches.
192 * An int AVP needs to be 4 byte long, and the eoh must be 0 or 1
193 * long .. Unknown AVPs also mean not for us ...
196 while ((len > 2) && !eoh) {
197 avptype = tvb_get_guint8(tvb, offset+0);
198 avplen = tvb_get_guint8(tvb, offset+1);
206 avpfound |= 1<<avptype;
209 if (avplen > 1 || offset == 0)
214 case(RB_AVP_DIR): /* Is this correct? the hf_ originally had FT_UINT8 for DIR */
220 offset += 2 + avplen;
224 if (!(avpfound & (1<<RB_AVP_SEQNO)))
226 if (!(avpfound & (1<<RB_AVP_SESSID)))
228 if (!(avpfound & (1<<RB_AVP_LIID)))
231 redbackli_dissect(tvb, pinfo, tree);
235 void proto_register_redbackli(void) {
236 static hf_register_info hf[] = {
237 { &hf_redbackli_seqno,
238 { "Sequence No", "redbackli.seqno", FT_UINT32, BASE_DEC, NULL, 0x0,
240 { &hf_redbackli_liid,
241 { "Lawful Intercept Id", "redbackli.liid", FT_UINT32, BASE_DEC, NULL, 0x0,
242 "LI Identifier", HFILL }},
243 { &hf_redbackli_sessid,
244 { "Session Id", "redbackli.sessid", FT_UINT32, BASE_DEC, NULL, 0x0,
245 "Session Identifier", HFILL }},
246 #if 0 /* XXX: If one goes by the heuristic then this field can be variable length ??
247 In the absence of any documentation We'll assume that's the case
248 (even though 'direction' sounds like a fixed length field */
250 { "Direction", "redbackli.dir", FT_UINT8, BASE_DEC, NULL, 0x0,
254 { "Direction", "redbackli.dir", FT_BYTES, BASE_NONE, NULL, 0x0,
257 { &hf_redbackli_label,
258 { "Label", "redbackli.label", FT_STRING, BASE_NONE, NULL, 0x0,
260 { &hf_redbackli_acctid,
261 { "Acctid", "redbackli.acctid", FT_BYTES, BASE_NONE, NULL, 0x0,
263 { &hf_redbackli_eohpad,
264 { "End of Header Padding", "redbackli.eohpad", FT_BYTES, BASE_NONE, NULL, 0x0,
266 { &hf_redbackli_unknownavp,
267 { "Unknown AVP", "redbackli.unknownavp", FT_BYTES, BASE_NONE, NULL, 0x0,
271 static gint *ett[] = {
275 proto_redbackli = proto_register_protocol("Redback Lawful Intercept",
276 "RedbackLI", "redbackli");
278 proto_register_field_array(proto_redbackli, hf, array_length(hf));
279 proto_register_subtree_array(ett, array_length(ett));
281 register_dissector("redbackli", redbackli_dissect, proto_redbackli);
284 void proto_reg_handoff_redbackli(void) {
285 dissector_handle_t redbackli_handle;
287 ip_handle = find_dissector("ip");
289 redbackli_handle = find_dissector("redbackli");
290 dissector_add_handle("udp.port", redbackli_handle); /* for 'decode-as' */
292 heur_dissector_add("udp", redbackli_dissect_heur, proto_redbackli);
297 * Editor modelines - http://www.wireshark.org/tools/modelines.html
302 * indent-tabs-mode: t
305 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
306 * :indentSize=8:tabSize=8:noTabs=false: