epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-redbackli.c
blob33157c60cffa24f7ec173572564375f4f3c55b03
1 /* packet-redbackli.c
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
14 #include "config.h"
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
41 #define RB_AVP_LIID 2
42 #define RB_AVP_SESSID 3
43 #define RB_AVP_DIR 4
44 #define RB_AVP_LABEL 20
45 #define RB_AVP_ACCTID 40
46 #define RB_AVP_EOH 0
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"},
56 {0, NULL}
59 static void
60 redbackli_dissect_avp(uint8_t avptype, uint8_t avplen, tvbuff_t *tvb, int offset, proto_tree *tree)
62 const char *avpname;
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);
72 if (!avplen)
73 return;
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().
81 switch (avptype) {
82 case(RB_AVP_SEQNO):
83 proto_tree_add_item(st, hf_redbackli_seqno, tvb,
84 offset+2, avplen, ENC_BIG_ENDIAN);
85 break;
86 case(RB_AVP_LIID):
87 proto_tree_add_item(st, hf_redbackli_liid, tvb,
88 offset+2, avplen, ENC_BIG_ENDIAN);
89 break;
90 case(RB_AVP_SESSID):
91 proto_tree_add_item(st, hf_redbackli_sessid, tvb,
92 offset+2, avplen, ENC_BIG_ENDIAN);
93 break;
94 case(RB_AVP_LABEL):
95 proto_tree_add_item(st, hf_redbackli_label, tvb,
96 offset+2, avplen, ENC_ASCII);
97 break;
98 case(RB_AVP_EOH):
99 proto_tree_add_item(st, hf_redbackli_eohpad, tvb,
100 offset+2, avplen, ENC_NA);
101 break;
102 case(RB_AVP_DIR):
103 proto_tree_add_item(st, hf_redbackli_dir, tvb,
104 offset+2, avplen, ENC_NA);
105 break;
106 case(RB_AVP_ACCTID):
107 proto_tree_add_item(st, hf_redbackli_acctid, tvb,
108 offset+2, avplen, ENC_NA);
109 break;
110 default:
111 proto_tree_add_item(st, hf_redbackli_unknownavp, tvb,
112 offset+2, avplen, ENC_NA);
113 break;
116 return;
119 static int
120 redbackli_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
122 uint8_t avptype, avplen;
123 int len, offset = 0;
124 bool eoh;
125 proto_item *ti;
126 proto_tree *redbackli_tree = NULL;
127 tvbuff_t *next_tvb;
129 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RBLI");
131 ti = proto_tree_add_item(tree, proto_redbackli,
132 tvb, 0, -1, ENC_NA);
133 redbackli_tree = proto_item_add_subtree(ti, ett_redbackli);
135 len = tvb_reported_length(tvb);
136 offset = 0;
137 eoh = false;
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 ? */
143 break;
145 if (tree)
146 redbackli_dissect_avp(avptype, avplen, tvb, offset, redbackli_tree);
148 if (avptype == RB_AVP_EOH)
149 eoh = true;
151 offset += 2 + avplen;
152 len -= 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)
166 static bool
167 redbackli_dissect_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
169 int len, offset = 0;
170 bool eoh = false;
171 uint8_t avptype, avplen;
172 uint32_t avpfound = 0;
174 len = tvb_captured_length(tvb);
175 if (len < MIN_REDBACKLI_SIZE)
176 return false;
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);
188 switch (avptype) {
189 case(RB_AVP_SEQNO):
190 case(RB_AVP_LIID):
191 case(RB_AVP_SESSID):
192 if (avplen != 4)
193 return false;
194 avpfound |= 1<<avptype;
195 break;
196 case(RB_AVP_EOH):
197 if (avplen > 1 || offset == 0)
198 return false;
199 eoh = true;
200 break;
201 case(RB_AVP_LABEL):
202 case(RB_AVP_DIR): /* Is this correct? the hf_ originally had FT_UINT8 for DIR */
203 case(RB_AVP_ACCTID):
204 break;
205 default:
206 return false;
208 offset += 2 + avplen;
209 len -= 2 + avplen;
212 if (!(avpfound & (1<<RB_AVP_SEQNO)))
213 return false;
214 if (!(avpfound & (1<<RB_AVP_SESSID)))
215 return false;
216 if (!(avpfound & (1<<RB_AVP_LIID)))
217 return false;
219 redbackli_dissect(tvb, pinfo, tree, data);
221 return true;
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,
227 NULL, HFILL }},
228 { &hf_redbackli_avplen,
229 { "AVP Length", "redbackli.avplen", FT_UINT8, BASE_DEC, NULL, 0x0,
230 NULL, HFILL }},
231 { &hf_redbackli_seqno,
232 { "Sequence No", "redbackli.seqno", FT_UINT32, BASE_DEC, NULL, 0x0,
233 NULL, HFILL }},
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
244 { &hf_redbackli_dir,
245 { "Direction", "redbackli.dir", FT_BYTES, BASE_NONE, NULL, 0x0,
246 NULL, HFILL }},
247 { &hf_redbackli_label,
248 { "Label", "redbackli.label", FT_STRING, BASE_NONE, NULL, 0x0,
249 NULL, HFILL }},
250 { &hf_redbackli_acctid,
251 { "Acctid", "redbackli.acctid", FT_BYTES, BASE_NONE, NULL, 0x0,
252 NULL, HFILL }},
253 { &hf_redbackli_eohpad,
254 { "End of Header Padding", "redbackli.eohpad", FT_BYTES, BASE_NONE, NULL, 0x0,
255 NULL, HFILL }},
256 { &hf_redbackli_unknownavp,
257 { "Unknown AVP", "redbackli.unknownavp", FT_BYTES, BASE_NONE, NULL, 0x0,
258 NULL, HFILL }}
261 static int *ett[] = {
262 &ett_redbackli
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
285 * Local variables:
286 * c-basic-offset: 8
287 * tab-width: 8
288 * indent-tabs-mode: t
289 * End:
291 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
292 * :indentSize=8:tabSize=8:noTabs=false: