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.
39 #include <epan/packet.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/strutil.h>
43 static int proto_redbackli = -1;
45 static int hf_redbackli_seqno = -1; /* Sequence No */
46 static int hf_redbackli_liid = -1; /* LI Id */
47 static int hf_redbackli_sessid = -1; /* Session Id */
48 static int hf_redbackli_label = -1; /* Label */
49 static int hf_redbackli_acctid = -1; /* Accounting Session Id */
50 static int hf_redbackli_dir = -1; /* Direction */
51 static int hf_redbackli_eohpad = -1; /* End Of Header Padding */
52 static int hf_redbackli_unknownavp = -1; /* Unknown AVP */
54 static int ett_redbackli = -1;
56 static dissector_handle_t ip_handle;
58 #define RB_AVP_SEQNO 1
60 #define RB_AVP_SESSID 3
62 #define RB_AVP_LABEL 20
63 #define RB_AVP_ACCTID 40
66 static const value_string avp_names[] = {
67 {RB_AVP_SEQNO, "Sequence No"},
68 {RB_AVP_LIID, "Lawful Intercept Id"},
69 {RB_AVP_SESSID, "Session Id"},
70 {RB_AVP_LABEL, "Label"},
71 {RB_AVP_ACCTID, "Accounting Session Id"},
72 {RB_AVP_DIR, "Direction"},
73 {RB_AVP_EOH, "End Of Header"},
78 redbackli_dissect_avp(guint8 avptype, guint8 avplen, tvbuff_t *tvb, gint offset, proto_tree *tree)
81 proto_tree *ti, *st=NULL;
83 avpname=val_to_str(avptype, avp_names, "Unknown");
85 ti = proto_tree_add_text(tree, tvb, offset, avplen+2, "%s AVP", avpname);
86 st = proto_item_add_subtree(ti, ett_redbackli);
88 proto_tree_add_text(st, tvb, offset, 1, "AVP Type: %d", avptype);
89 proto_tree_add_text(st, tvb, offset+1, 1, "AVP Length: %d", avplen);
94 /* XXX: ToDo: Validate the length (avplen) of the fixed length fields
95 before calling proto_tree_add_item().
96 Note that the field lengths have been validated when
97 dissect_avp() is called from redbackli_dissect_heur().
102 proto_tree_add_item(st, hf_redbackli_seqno, tvb,
103 offset+2, avplen, FALSE);
106 proto_tree_add_item(st, hf_redbackli_liid, tvb,
107 offset+2, avplen, FALSE);
110 proto_tree_add_item(st, hf_redbackli_sessid, tvb,
111 offset+2, avplen, FALSE);
114 proto_tree_add_item(st, hf_redbackli_label, tvb,
115 offset+2, avplen, FALSE);
118 proto_tree_add_item(st, hf_redbackli_eohpad, tvb,
119 offset+2, avplen, FALSE);
122 proto_tree_add_item(st, hf_redbackli_dir, tvb,
123 offset+2, avplen, FALSE);
126 proto_tree_add_item(st, hf_redbackli_acctid, tvb,
127 offset+2, avplen, FALSE);
130 proto_tree_add_item(st, hf_redbackli_unknownavp, tvb,
131 offset+2, avplen, FALSE);
139 redbackli_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
141 guint8 avptype, avplen;
144 proto_tree *ti, *redbackli_tree=NULL;
147 if(check_col(pinfo->cinfo,COL_PROTOCOL))
148 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RBLI");
151 ti = proto_tree_add_item(tree, proto_redbackli,
153 redbackli_tree = proto_item_add_subtree(ti, ett_redbackli);
159 while(!eoh && (len > 2)) {
160 avptype = tvb_get_guint8(tvb, offset+0);
161 avplen = tvb_get_guint8(tvb, offset+1);
163 if ((len-2) < avplen) /* AVP Complete ? */
167 redbackli_dissect_avp(avptype, avplen, tvb, offset, redbackli_tree);
169 if (avptype == RB_AVP_EOH)
176 next_tvb = tvb_new_subset_remaining(tvb, offset);
177 call_dissector(ip_handle, next_tvb, pinfo, tree);
181 #define REDBACKLI_INTSIZE 6
182 #define REDBACKLI_EOHSIZE 2
183 #define MIN_REDBACKLI_SIZE (3*REDBACKLI_INTSIZE+REDBACKLI_EOHSIZE)
186 redbackli_dissect_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
190 guint8 avptype, avplen;
194 if (len < MIN_REDBACKLI_SIZE)
198 * We scan the possible AVPs and look out for mismatches.
199 * An int AVP needs to be 4 byte long, and the eoh must be 0 or 1
200 * long .. Unknown AVPs also mean not for us ...
203 while((len > 2) && !eoh) {
204 avptype = tvb_get_guint8(tvb, offset+0);
205 avplen = tvb_get_guint8(tvb, offset+1);
213 avpfound|=1<<avptype;
216 if (avplen > 1 || offset == 0)
221 case(RB_AVP_DIR): /* Is this correct? the hf_ originally had FT_UINT8 for DIR */
231 if (!(avpfound & (1<<RB_AVP_SEQNO)))
233 if (!(avpfound & (1<<RB_AVP_SESSID)))
235 if (!(avpfound & (1<<RB_AVP_LIID)))
238 redbackli_dissect(tvb, pinfo, tree);
242 void proto_register_redbackli(void) {
243 static hf_register_info hf[] = {
244 { &hf_redbackli_seqno,
245 { "Sequence No", "redbackli.seqno", FT_UINT32, BASE_DEC, NULL, 0x0,
247 { &hf_redbackli_liid,
248 { "Lawful Intercept Id", "redbackli.liid", FT_UINT32, BASE_DEC, NULL, 0x0,
249 "LI Identifier", HFILL }},
250 { &hf_redbackli_sessid,
251 { "Session Id", "redbackli.sessid", FT_UINT32, BASE_DEC, NULL, 0x0,
252 "Session Identifier", HFILL }},
254 #if 0 /* XXX: If one goes by the heuristic then this field can be variable length ??
255 In the absence of any documentation We'll assume that's the case
256 (even though 'direction' sounds like a fixed length field */
257 { "Direction", "redbackli.dir", FT_UINT8, BASE_DEC, NULL, 0x0,
259 { "Direction", "redbackli.dir", FT_BYTES, BASE_NONE, NULL, 0x0,
261 { &hf_redbackli_label,
262 { "Label", "redbackli.label", FT_STRING, BASE_NONE, NULL, 0x0,
264 { &hf_redbackli_acctid,
265 { "Acctid", "redbackli.acctid", FT_BYTES, BASE_NONE, NULL, 0x0,
267 { &hf_redbackli_eohpad,
268 { "End of Header Padding", "redbackli.eohpad", FT_BYTES, BASE_NONE, NULL, 0x0,
270 { &hf_redbackli_unknownavp,
271 { "Unknown AVP", "redbackli.unknownavp", FT_BYTES, BASE_NONE, NULL, 0x0,
275 static gint *ett[] = {
279 proto_redbackli = proto_register_protocol("Redback Lawful Intercept",
280 "RedbackLI","redbackli");
282 proto_register_field_array(proto_redbackli,hf,array_length(hf));
283 proto_register_subtree_array(ett,array_length(ett));
285 register_dissector("redbackli", redbackli_dissect, proto_redbackli);
288 void proto_reg_handoff_redbackli(void) {
289 dissector_handle_t redbackli_handle;
291 ip_handle = find_dissector("ip");
293 redbackli_handle = find_dissector("redbackli");
294 dissector_add_handle("udp.port", redbackli_handle); /* for 'decode-as' */
296 heur_dissector_add("udp", redbackli_dissect_heur, proto_redbackli);