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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
33 #include <epan/addr_resolv.h>
34 #include <epan/strutil.h>
36 static int proto_redbackli
= -1;
38 static int hf_redbackli_seqno
= -1; /* Sequence No */
39 static int hf_redbackli_liid
= -1; /* LI Id */
40 static int hf_redbackli_sessid
= -1; /* Session Id */
41 static int hf_redbackli_label
= -1; /* Label */
42 static int hf_redbackli_acctid
= -1; /* Accounting Session Id */
43 static int hf_redbackli_dir
= -1; /* Direction */
44 static int hf_redbackli_eohpad
= -1; /* End Of Header Padding */
45 static int hf_redbackli_unknownavp
= -1; /* Unknown AVP */
47 static int ett_redbackli
= -1;
49 static dissector_handle_t ip_handle
;
51 #define RB_AVP_SEQNO 1
53 #define RB_AVP_SESSID 3
55 #define RB_AVP_LABEL 20
56 #define RB_AVP_ACCTID 40
59 static const value_string avp_names
[] = {
60 {RB_AVP_SEQNO
, "Sequence No"},
61 {RB_AVP_LIID
, "Lawful Intercept Id"},
62 {RB_AVP_SESSID
, "Session Id"},
63 {RB_AVP_LABEL
, "Label"},
64 {RB_AVP_ACCTID
, "Accounting Session Id"},
65 {RB_AVP_DIR
, "Direction"},
66 {RB_AVP_EOH
, "End Of Header"},
71 redbackli_dissect_avp(guint8 avptype
, guint8 avplen
, tvbuff_t
*tvb
, gint offset
, proto_tree
*tree
)
74 proto_tree
*ti
, *st
=NULL
;
76 avpname
=val_to_str_const(avptype
, avp_names
, "Unknown");
78 ti
= proto_tree_add_text(tree
, tvb
, offset
, avplen
+2, "%s AVP", avpname
);
79 st
= proto_item_add_subtree(ti
, ett_redbackli
);
81 proto_tree_add_text(st
, tvb
, offset
, 1, "AVP Type: %d", avptype
);
82 proto_tree_add_text(st
, tvb
, offset
+1, 1, "AVP Length: %d", avplen
);
87 /* XXX: ToDo: Validate the length (avplen) of the fixed length fields
88 before calling proto_tree_add_item().
89 Note that the field lengths have been validated when
90 dissect_avp() is called from redbackli_dissect_heur().
95 proto_tree_add_item(st
, hf_redbackli_seqno
, tvb
,
96 offset
+2, avplen
, ENC_BIG_ENDIAN
);
99 proto_tree_add_item(st
, hf_redbackli_liid
, tvb
,
100 offset
+2, avplen
, ENC_BIG_ENDIAN
);
103 proto_tree_add_item(st
, hf_redbackli_sessid
, tvb
,
104 offset
+2, avplen
, ENC_BIG_ENDIAN
);
107 proto_tree_add_item(st
, hf_redbackli_label
, tvb
,
108 offset
+2, avplen
, ENC_ASCII
|ENC_NA
);
111 proto_tree_add_item(st
, hf_redbackli_eohpad
, tvb
,
112 offset
+2, avplen
, ENC_NA
);
115 proto_tree_add_item(st
, hf_redbackli_dir
, tvb
,
116 offset
+2, avplen
, ENC_NA
);
119 proto_tree_add_item(st
, hf_redbackli_acctid
, tvb
,
120 offset
+2, avplen
, ENC_NA
);
123 proto_tree_add_item(st
, hf_redbackli_unknownavp
, tvb
,
124 offset
+2, avplen
, ENC_NA
);
132 redbackli_dissect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
134 guint8 avptype
, avplen
;
137 proto_tree
*ti
, *redbackli_tree
=NULL
;
140 col_set_str(pinfo
->cinfo
,COL_PROTOCOL
,"RBLI");
143 ti
= proto_tree_add_item(tree
, proto_redbackli
,
145 redbackli_tree
= proto_item_add_subtree(ti
, ett_redbackli
);
151 while(!eoh
&& (len
> 2)) {
152 avptype
= tvb_get_guint8(tvb
, offset
+0);
153 avplen
= tvb_get_guint8(tvb
, offset
+1);
155 if ((len
-2) < avplen
) /* AVP Complete ? */
159 redbackli_dissect_avp(avptype
, avplen
, tvb
, offset
, redbackli_tree
);
161 if (avptype
== RB_AVP_EOH
)
168 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
169 call_dissector(ip_handle
, next_tvb
, pinfo
, tree
);
173 #define REDBACKLI_INTSIZE 6
174 #define REDBACKLI_EOHSIZE 2
175 #define MIN_REDBACKLI_SIZE (3*REDBACKLI_INTSIZE+REDBACKLI_EOHSIZE)
178 redbackli_dissect_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
182 guint8 avptype
, avplen
;
186 if (len
< MIN_REDBACKLI_SIZE
)
190 * We scan the possible AVPs and look out for mismatches.
191 * An int AVP needs to be 4 byte long, and the eoh must be 0 or 1
192 * long .. Unknown AVPs also mean not for us ...
195 while((len
> 2) && !eoh
) {
196 avptype
= tvb_get_guint8(tvb
, offset
+0);
197 avplen
= tvb_get_guint8(tvb
, offset
+1);
205 avpfound
|=1<<avptype
;
208 if (avplen
> 1 || offset
== 0)
213 case(RB_AVP_DIR
): /* Is this correct? the hf_ originally had FT_UINT8 for DIR */
223 if (!(avpfound
& (1<<RB_AVP_SEQNO
)))
225 if (!(avpfound
& (1<<RB_AVP_SESSID
)))
227 if (!(avpfound
& (1<<RB_AVP_LIID
)))
230 redbackli_dissect(tvb
, pinfo
, tree
);
234 void proto_register_redbackli(void) {
235 static hf_register_info hf
[] = {
236 { &hf_redbackli_seqno
,
237 { "Sequence No", "redbackli.seqno", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
239 { &hf_redbackli_liid
,
240 { "Lawful Intercept Id", "redbackli.liid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
241 "LI Identifier", HFILL
}},
242 { &hf_redbackli_sessid
,
243 { "Session Id", "redbackli.sessid", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
244 "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 */
249 { "Direction", "redbackli.dir", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
251 { "Direction", "redbackli.dir", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
253 { &hf_redbackli_label
,
254 { "Label", "redbackli.label", FT_STRING
, BASE_NONE
, NULL
, 0x0,
256 { &hf_redbackli_acctid
,
257 { "Acctid", "redbackli.acctid", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
259 { &hf_redbackli_eohpad
,
260 { "End of Header Padding", "redbackli.eohpad", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
262 { &hf_redbackli_unknownavp
,
263 { "Unknown AVP", "redbackli.unknownavp", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
267 static gint
*ett
[] = {
271 proto_redbackli
= proto_register_protocol("Redback Lawful Intercept",
272 "RedbackLI","redbackli");
274 proto_register_field_array(proto_redbackli
,hf
,array_length(hf
));
275 proto_register_subtree_array(ett
,array_length(ett
));
277 register_dissector("redbackli", redbackli_dissect
, proto_redbackli
);
280 void proto_reg_handoff_redbackli(void) {
281 dissector_handle_t redbackli_handle
;
283 ip_handle
= find_dissector("ip");
285 redbackli_handle
= find_dissector("redbackli");
286 dissector_add_handle("udp.port", redbackli_handle
); /* for 'decode-as' */
288 heur_dissector_add("udp", redbackli_dissect_heur
, proto_redbackli
);