5 * Redback Lawful Intercept Packet dissector
7 * Copyright 2008 Florian Lohoff <flo[AT]rfc822.org>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald[AT]wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet.h>
38 #include <epan/addr_resolv.h>
39 #include <epan/strutil.h>
41 static int proto_redbackli = -1;
43 static int hf_redbackli_seqno = -1; /* Sequence No */
44 static int hf_redbackli_liid = -1; /* LI Id */
45 static int hf_redbackli_sessid = -1; /* Session Id */
46 static int hf_redbackli_label = -1; /* Label */
47 static int hf_redbackli_acctid = -1; /* Accounting Session Id */
48 static int hf_redbackli_dir = -1; /* Direction */
49 static int hf_redbackli_eohpad = -1; /* End Of Header Padding */
50 static int hf_redbackli_unknownavp = -1; /* Unknown AVP */
52 static int ett_redbackli = -1;
54 static dissector_handle_t ip_handle;
56 #define RB_AVP_SEQNO 1
58 #define RB_AVP_SESSID 3
60 #define RB_AVP_LABEL 20
61 #define RB_AVP_ACCTID 40
64 static const value_string avp_names[] = {
65 {RB_AVP_SEQNO, "Sequence No"},
66 {RB_AVP_LIID, "Lawful Intercept Id"},
67 {RB_AVP_SESSID, "Session Id"},
68 {RB_AVP_LABEL, "Label"},
69 {RB_AVP_ACCTID, "Accounting Session Id"},
70 {RB_AVP_DIR, "Direction"},
71 {RB_AVP_EOH, "End Of Header"},
76 redbackli_dissect_avp(guint8 avptype, guint8 avplen, tvbuff_t *tvb, gint offset, proto_tree *tree)
79 proto_tree *ti, *st=NULL;
81 avpname=val_to_str(avptype, avp_names, "Unknown");
83 ti = proto_tree_add_text(tree, tvb, offset, avplen+2, "%s AVP", avpname);
84 st = proto_item_add_subtree(ti, ett_redbackli);
86 proto_tree_add_text(st, tvb, offset, 1, "AVP Type: %d", avptype);
87 proto_tree_add_text(st, tvb, offset+1, 1, "AVP Length: %d", avplen);
92 /* XXX: ToDo: Validate the length (avplen) of the fixed length fields
93 before calling proto_tree_add_item().
94 Note that the field lengths have been validated when
95 dissect_avp() is called from redbackli_dissect_heur().
100 proto_tree_add_item(st, hf_redbackli_seqno, tvb,
101 offset+2, avplen, FALSE);
104 proto_tree_add_item(st, hf_redbackli_liid, tvb,
105 offset+2, avplen, FALSE);
108 proto_tree_add_item(st, hf_redbackli_sessid, tvb,
109 offset+2, avplen, FALSE);
112 proto_tree_add_item(st, hf_redbackli_label, tvb,
113 offset+2, avplen, FALSE);
116 proto_tree_add_item(st, hf_redbackli_eohpad, tvb,
117 offset+2, avplen, FALSE);
120 proto_tree_add_item(st, hf_redbackli_dir, tvb,
121 offset+2, avplen, FALSE);
124 proto_tree_add_item(st, hf_redbackli_acctid, tvb,
125 offset+2, avplen, FALSE);
128 proto_tree_add_item(st, hf_redbackli_unknownavp, tvb,
129 offset+2, avplen, FALSE);
137 redbackli_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
139 guint8 avptype, avplen;
142 proto_tree *ti, *redbackli_tree=NULL;
145 col_set_str(pinfo->cinfo,COL_PROTOCOL,"RBLI");
148 ti = proto_tree_add_item(tree, proto_redbackli,
150 redbackli_tree = proto_item_add_subtree(ti, ett_redbackli);
156 while(!eoh && (len > 2)) {
157 avptype = tvb_get_guint8(tvb, offset+0);
158 avplen = tvb_get_guint8(tvb, offset+1);
160 if ((len-2) < avplen) /* AVP Complete ? */
164 redbackli_dissect_avp(avptype, avplen, tvb, offset, redbackli_tree);
166 if (avptype == RB_AVP_EOH)
173 next_tvb = tvb_new_subset_remaining(tvb, offset);
174 call_dissector(ip_handle, next_tvb, pinfo, tree);
178 #define REDBACKLI_INTSIZE 6
179 #define REDBACKLI_EOHSIZE 2
180 #define MIN_REDBACKLI_SIZE (3*REDBACKLI_INTSIZE+REDBACKLI_EOHSIZE)
183 redbackli_dissect_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
187 guint8 avptype, avplen;
191 if (len < MIN_REDBACKLI_SIZE)
195 * We scan the possible AVPs and look out for mismatches.
196 * An int AVP needs to be 4 byte long, and the eoh must be 0 or 1
197 * long .. Unknown AVPs also mean not for us ...
200 while((len > 2) && !eoh) {
201 avptype = tvb_get_guint8(tvb, offset+0);
202 avplen = tvb_get_guint8(tvb, offset+1);
210 avpfound|=1<<avptype;
213 if (avplen > 1 || offset == 0)
218 case(RB_AVP_DIR): /* Is this correct? the hf_ originally had FT_UINT8 for DIR */
228 if (!(avpfound & (1<<RB_AVP_SEQNO)))
230 if (!(avpfound & (1<<RB_AVP_SESSID)))
232 if (!(avpfound & (1<<RB_AVP_LIID)))
235 redbackli_dissect(tvb, pinfo, tree);
239 void proto_register_redbackli(void) {
240 static hf_register_info hf[] = {
241 { &hf_redbackli_seqno,
242 { "Sequence No", "redbackli.seqno", FT_UINT32, BASE_DEC, NULL, 0x0,
244 { &hf_redbackli_liid,
245 { "Lawful Intercept Id", "redbackli.liid", FT_UINT32, BASE_DEC, NULL, 0x0,
246 "LI Identifier", HFILL }},
247 { &hf_redbackli_sessid,
248 { "Session Id", "redbackli.sessid", FT_UINT32, BASE_DEC, NULL, 0x0,
249 "Session Identifier", HFILL }},
251 #if 0 /* XXX: If one goes by the heuristic then this field can be variable length ??
252 In the absence of any documentation We'll assume that's the case
253 (even though 'direction' sounds like a fixed length field */
254 { "Direction", "redbackli.dir", FT_UINT8, BASE_DEC, NULL, 0x0,
256 { "Direction", "redbackli.dir", FT_BYTES, BASE_NONE, NULL, 0x0,
258 { &hf_redbackli_label,
259 { "Label", "redbackli.label", FT_STRING, BASE_NONE, NULL, 0x0,
261 { &hf_redbackli_acctid,
262 { "Acctid", "redbackli.acctid", FT_BYTES, BASE_NONE, NULL, 0x0,
264 { &hf_redbackli_eohpad,
265 { "End of Header Padding", "redbackli.eohpad", FT_BYTES, BASE_NONE, NULL, 0x0,
267 { &hf_redbackli_unknownavp,
268 { "Unknown AVP", "redbackli.unknownavp", FT_BYTES, BASE_NONE, NULL, 0x0,
272 static gint *ett[] = {
276 proto_redbackli = proto_register_protocol("Redback Lawful Intercept",
277 "RedbackLI","redbackli");
279 proto_register_field_array(proto_redbackli,hf,array_length(hf));
280 proto_register_subtree_array(ett,array_length(ett));
282 register_dissector("redbackli", redbackli_dissect, proto_redbackli);
285 void proto_reg_handoff_redbackli(void) {
286 dissector_handle_t redbackli_handle;
288 ip_handle = find_dissector("ip");
290 redbackli_handle = find_dissector("redbackli");
291 dissector_add_handle("udp.port", redbackli_handle); /* for 'decode-as' */
293 heur_dissector_add("udp", redbackli_dissect_heur, proto_redbackli);