/src/wireshark/epan/dissectors/packet-fr.c
Line | Count | Source |
1 | | /* packet-fr.c |
2 | | * Routines for Frame Relay dissection |
3 | | * |
4 | | * Copyright 2001, Paul Ionescu <paul@acorp.ro> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | * |
12 | | * References: |
13 | | * |
14 | | * https://web.archive.org/web/20150510093619/http://www.protocols.com/pbook/frame.htm |
15 | | * https://www.broadband-forum.org/wp-content/uploads/2018/12/FRF.3.2.pdf |
16 | | * ITU Recommendations Q.922 and Q.933 |
17 | | * RFC-1490 |
18 | | * RFC-2427 |
19 | | * Cisco encapsulation |
20 | | * https://web.archive.org/web/20030422173700/https://www.trillium.com/assets/legacyframe/white_paper/8771019.pdf |
21 | | */ |
22 | | |
23 | | #include "config.h" |
24 | | |
25 | | #include <epan/packet.h> |
26 | | #include <epan/capture_dissectors.h> |
27 | | #include <epan/prefs.h> |
28 | | #include <epan/expert.h> |
29 | | #include <epan/conversation.h> |
30 | | #include <epan/arptypes.h> |
31 | | #include <epan/tfs.h> |
32 | | |
33 | | #include "packet-xdlc.h" |
34 | | #include "packet-llc.h" |
35 | | #include "packet-chdlc.h" |
36 | | #include "packet-juniper.h" |
37 | | #include "packet-sflow.h" |
38 | | #include "packet-l2tp.h" |
39 | | #include "packet-osi.h" |
40 | | #include <epan/etypes.h> |
41 | | |
42 | | void proto_register_fr(void); |
43 | | void proto_reg_handoff_fr(void); |
44 | | |
45 | | /* |
46 | | * Bits in the address field. |
47 | | */ |
48 | 1.76k | #define FRELAY_EA 0x01 /* Address field extension bit */ |
49 | | |
50 | 315 | #define FRELAY_UPPER_DLCI 0xFC /* Upper DLCI */ |
51 | 315 | #define FRELAY_CR 0x02 /* Command/response bit in first octet */ |
52 | | |
53 | 315 | #define FRELAY_SECOND_DLCI 0xF0 /* DLCI bits in FECN/BECN/DE octet */ |
54 | 14 | #define FRELAY_FECN 0x08 /* Forward Explicit Congestion Notification */ |
55 | 14 | #define FRELAY_BECN 0x04 /* Backward Explicit Congestion Notification */ |
56 | 14 | #define FRELAY_DE 0x02 /* Discard Eligibility */ |
57 | | |
58 | 81 | #define FRELAY_THIRD_DLCI 0xFE /* DLCI bits in third octet, if any */ |
59 | | |
60 | 70 | #define FRELAY_LOWER_DLCI 0xFC /* Lower DLCI */ |
61 | 108 | #define FRELAY_DC 0x02 /* DLCI or DL-CORE control indicator in last octet */ |
62 | | |
63 | 0 | #define FROM_DCE 0x80 /* for direction setting */ |
64 | | |
65 | | static int proto_fr; |
66 | | static int ett_fr; |
67 | | static int ett_fr_address; |
68 | | static int ett_fr_control; |
69 | | static int hf_fr_ea; |
70 | | static int hf_fr_upper_dlci; |
71 | | static int hf_fr_cr; |
72 | | static int hf_fr_second_dlci; |
73 | | static int hf_fr_fecn; |
74 | | static int hf_fr_becn; |
75 | | static int hf_fr_de; |
76 | | static int hf_fr_third_dlci; |
77 | | static int hf_fr_dlcore_control; |
78 | | static int hf_fr_lower_dlci; |
79 | | static int hf_fr_dc; |
80 | | static int hf_fr_dlci; |
81 | | static int hf_fr_control; |
82 | | static int hf_fr_n_r; |
83 | | static int hf_fr_n_s; |
84 | | static int hf_fr_p; |
85 | | static int hf_fr_p_ext; |
86 | | static int hf_fr_f; |
87 | | static int hf_fr_f_ext; |
88 | | static int hf_fr_s_ftype; |
89 | | static int hf_fr_u_modifier_cmd; |
90 | | static int hf_fr_u_modifier_resp; |
91 | | static int hf_fr_ftype_i; |
92 | | static int hf_fr_ftype_s_u; |
93 | | static int hf_fr_ftype_s_u_ext; |
94 | | static int hf_fr_nlpid; |
95 | | static int hf_fr_oui; |
96 | | static int hf_fr_pid; |
97 | | static int hf_fr_snaptype; |
98 | | static int hf_fr_chdlctype; |
99 | | static int hf_fr_first_addr_octet; |
100 | | static int hf_fr_second_addr_octet; |
101 | | static int hf_fr_third_addr_octet; |
102 | | |
103 | | static expert_field ei_fr_bogus_address; |
104 | | static expert_field ei_fr_frame_relay_lapf; |
105 | | static expert_field ei_fr_frame_relay_xid; |
106 | | |
107 | | static dissector_handle_t eth_withfcs_handle; |
108 | | static dissector_handle_t gprs_ns_handle; |
109 | | static dissector_handle_t lapb_handle; |
110 | | static dissector_handle_t data_handle; |
111 | | static dissector_handle_t fr_handle; |
112 | | |
113 | | static capture_dissector_handle_t chdlc_cap_handle; |
114 | | static capture_dissector_handle_t eth_cap_handle; |
115 | | |
116 | | static dissector_table_t chdlc_subdissector_table; |
117 | | static dissector_table_t osinl_incl_subdissector_table; |
118 | | static dissector_table_t ethertype_subdissector_table; |
119 | | |
120 | | /* |
121 | | * Encapsulation type. |
122 | | * XXX - this should be per-DLCI as well. |
123 | | */ |
124 | 317 | #define FRF_3_2 0 /* FRF 3.2 or Cisco HDLC */ |
125 | 14 | #define GPRS_NS 1 /* GPRS Network Services (3GPP TS 08.16) */ |
126 | 14 | #define RAW_ETHER 2 /* Raw Ethernet */ |
127 | 14 | #define LAPB 3 /* T.617a-1994 Annex G encapsulation of LAPB */ |
128 | | |
129 | | static int fr_encap = FRF_3_2; |
130 | | |
131 | | static const true_false_string ctrl_string = { |
132 | | "DLCI Address", |
133 | | "Control" |
134 | | }; |
135 | | static const true_false_string ea_string = { |
136 | | "Last Octet", |
137 | | "More Follows" |
138 | | }; |
139 | | |
140 | | /* |
141 | | * This isn't the same as "nlpid_vals[]"; 0x08 is Q.933, not Q.931, |
142 | | * and 0x09 is LMI, not Q.2931, and we assume that it's an initial |
143 | | * protocol identifier, so 0x01 is T.70, not X.29. |
144 | | */ |
145 | | static const value_string fr_nlpid_vals[] = { |
146 | | { NLPID_NULL, "NULL" }, |
147 | | { NLPID_IPI_T_70, "T.70" }, /* XXX - IPI, or SPI? */ |
148 | | { NLPID_X_633, "X.633" }, |
149 | | { NLPID_Q_931, "Q.933" }, |
150 | | { NLPID_LMI, "LMI" }, |
151 | | { NLPID_Q_2119, "Q.2119" }, |
152 | | { NLPID_SNAP, "SNAP" }, |
153 | | { NLPID_ISO8473_CLNP, "CLNP" }, |
154 | | { NLPID_ISO9542_ESIS, "ESIS" }, |
155 | | { NLPID_ISO10589_ISIS, "ISIS" }, |
156 | | { NLPID_ISO10747_IDRP, "IDRP" }, |
157 | | { NLPID_ISO9542X25_ESIS, "ESIS (X.25)" }, |
158 | | { NLPID_ISO10030, "ISO 10030" }, |
159 | | { NLPID_ISO11577, "ISO 11577" }, |
160 | | { NLPID_COMPRESSED, "Data compression protocol" }, |
161 | | { NLPID_IP, "IP" }, |
162 | | { NLPID_IP6, "IPv6" }, |
163 | | { NLPID_PPP, "PPP" }, |
164 | | { 0, NULL }, |
165 | | }; |
166 | | |
167 | | static dissector_table_t fr_subdissector_table; |
168 | | static dissector_table_t fr_osinl_subdissector_table; |
169 | | |
170 | | static void dissect_fr_nlpid(tvbuff_t *tvb, int offset, packet_info *pinfo, |
171 | | proto_tree *tree, proto_item *ti, |
172 | | proto_tree *fr_tree, uint8_t fr_ctrl); |
173 | | static void dissect_lapf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); |
174 | | static void dissect_fr_xid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); |
175 | | |
176 | | /* Used only for U frames */ |
177 | | static const xdlc_cf_items fr_cf_items = { |
178 | | NULL, |
179 | | NULL, |
180 | | &hf_fr_p, |
181 | | &hf_fr_f, |
182 | | NULL, |
183 | | &hf_fr_u_modifier_cmd, |
184 | | &hf_fr_u_modifier_resp, |
185 | | NULL, |
186 | | &hf_fr_ftype_s_u |
187 | | }; |
188 | | |
189 | | /* Used only for I and S frames */ |
190 | | static const xdlc_cf_items fr_cf_items_ext = { |
191 | | &hf_fr_n_r, |
192 | | &hf_fr_n_s, |
193 | | &hf_fr_p_ext, |
194 | | &hf_fr_f_ext, |
195 | | &hf_fr_s_ftype, |
196 | | NULL, |
197 | | NULL, |
198 | | &hf_fr_ftype_i, |
199 | | &hf_fr_ftype_s_u_ext |
200 | | }; |
201 | | |
202 | | static bool |
203 | | capture_fr(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header) |
204 | 0 | { |
205 | 0 | uint8_t fr_octet; |
206 | 0 | uint32_t addr; |
207 | 0 | uint8_t fr_ctrl; |
208 | 0 | uint8_t fr_nlpid; |
209 | | |
210 | | /* |
211 | | * OK, fetch the address field - keep going until we get an EA bit. |
212 | | */ |
213 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
214 | 0 | return false; |
215 | | |
216 | 0 | fr_octet = pd[offset]; |
217 | 0 | if (fr_octet & FRELAY_EA) { |
218 | | /* |
219 | | * Bogus! There should be at least 2 octets. |
220 | | * XXX - is this FRF.12 frame relay fragmentation? If so, can |
221 | | * we handle that? |
222 | | */ |
223 | 0 | return false; |
224 | 0 | } |
225 | | /* |
226 | | * The first octet contains the upper 6 bits of the DLCI, as well |
227 | | * as the C/R bit. |
228 | | */ |
229 | 0 | addr = (fr_octet & FRELAY_UPPER_DLCI) >> 2; |
230 | 0 | offset++; |
231 | | |
232 | | /* |
233 | | * The second octet contains 4 more bits of DLCI, as well as FECN, |
234 | | * BECN, and DE. |
235 | | */ |
236 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
237 | 0 | return false; |
238 | | |
239 | 0 | fr_octet = pd[offset]; |
240 | 0 | addr = (addr << 4) | ((fr_octet & FRELAY_SECOND_DLCI) >> 4); |
241 | 0 | offset++; |
242 | |
|
243 | 0 | if (!(fr_octet & FRELAY_EA)) { |
244 | | /* |
245 | | * We have 3 or more address octets. |
246 | | * |
247 | | * The third octet contains 7 more bits of DLCI if EA isn't set, |
248 | | * and lower DLCI or DL-CORE control plus the DLCI or DL-CORE |
249 | | * control indicator flag if EA is set. |
250 | | */ |
251 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
252 | 0 | return false; |
253 | | |
254 | 0 | fr_octet = pd[offset]; |
255 | 0 | if (!(fr_octet & FRELAY_EA)) { |
256 | | /* |
257 | | * 7 more bits of DLCI. |
258 | | */ |
259 | 0 | addr = (addr << 7) | ((fr_octet & FRELAY_THIRD_DLCI) >> 1); |
260 | 0 | offset++; |
261 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
262 | 0 | return false; |
263 | | |
264 | 0 | fr_octet = pd[offset]; |
265 | 0 | while (!(fr_octet & FRELAY_EA)) { |
266 | | /* |
267 | | * Bogus! More than 4 octets of address. |
268 | | */ |
269 | 0 | offset++; |
270 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
271 | 0 | return false; |
272 | | |
273 | 0 | fr_octet = pd[offset]; |
274 | 0 | } |
275 | 0 | } |
276 | | |
277 | | /* |
278 | | * Last octet - contains lower DLCI or DL-CORE control, DLCI or |
279 | | * DL-CORE control indicator flag. |
280 | | */ |
281 | 0 | if (fr_octet & FRELAY_DC) { |
282 | | /* |
283 | | * DL-CORE. |
284 | | */ |
285 | 0 | } else { |
286 | | /* |
287 | | * Last 6 bits of DLCI. |
288 | | */ |
289 | 0 | addr = (addr << 6) | ((fr_octet & FRELAY_LOWER_DLCI) >> 2); |
290 | 0 | } |
291 | 0 | } |
292 | | |
293 | 0 | switch (fr_encap) { |
294 | | |
295 | 0 | case FRF_3_2: |
296 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
297 | 0 | return false; |
298 | | |
299 | 0 | fr_ctrl = pd[offset]; |
300 | 0 | if (fr_ctrl == XDLC_U) { |
301 | 0 | offset++; |
302 | | |
303 | | /* |
304 | | * XXX - treat DLCI 0 specially? On DLCI 0, an NLPID of 0x08 |
305 | | * means Q.933, but on other circuits it could be the "for |
306 | | * protocols which do not have an NLPID assigned or do not |
307 | | * have a SNAP encapsulation" stuff from RFC 2427. |
308 | | */ |
309 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
310 | 0 | return false; |
311 | | |
312 | 0 | fr_nlpid = pd[offset]; |
313 | 0 | if (fr_nlpid == 0) { |
314 | 0 | offset++; |
315 | 0 | if (!BYTES_ARE_IN_FRAME(offset, len, 1)) |
316 | 0 | return false; |
317 | | |
318 | 0 | fr_nlpid = pd[offset]; |
319 | 0 | } |
320 | 0 | offset++; |
321 | 0 | return try_capture_dissector("fr.nlpid", fr_nlpid, pd, offset, len, cpinfo, pseudo_header); |
322 | 0 | } else { |
323 | 0 | if (addr == 0) { |
324 | | /* |
325 | | * This must be some sort of LAPF on DLCI 0 for SVC |
326 | | * because DLCI 0 is reserved for LMI and SVC signaling |
327 | | * encapsulated in LAPF, and LMI is transmitted in |
328 | | * unnumbered information (03), so this must be LAPF |
329 | | * (guessing). |
330 | | * |
331 | | * XXX - but what is it? Is Q.933 carried inside UI |
332 | | * frames or other types of frames or both? |
333 | | */ |
334 | 0 | return false; |
335 | 0 | } |
336 | 0 | if (fr_ctrl == (XDLC_U|XDLC_XID)) { |
337 | | /* |
338 | | * XID. |
339 | | */ |
340 | 0 | return false; |
341 | 0 | } |
342 | | |
343 | | /* |
344 | | * If the data does not start with unnumbered information (03) and |
345 | | * the DLCI# is not 0, then there may be Cisco Frame Relay encapsulation. |
346 | | */ |
347 | 0 | return call_capture_dissector(chdlc_cap_handle, pd, offset, len, cpinfo, pseudo_header); |
348 | 0 | } |
349 | 0 | break; |
350 | | |
351 | 0 | case GPRS_NS: |
352 | 0 | return false; |
353 | | |
354 | 0 | case RAW_ETHER: |
355 | 0 | if (addr != 0) |
356 | 0 | return call_capture_dissector(eth_cap_handle, pd, offset, len, cpinfo, pseudo_header); |
357 | | |
358 | 0 | return false; |
359 | 0 | } |
360 | | |
361 | 0 | return false; |
362 | 0 | } |
363 | | |
364 | | static void |
365 | | dissect_fr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
366 | | bool has_direction, bool decode_address ) |
367 | 304 | { |
368 | 304 | int offset = 0; |
369 | 304 | proto_item *ti = NULL; |
370 | 304 | proto_tree *fr_tree = NULL; |
371 | 304 | proto_tree *octet_tree = NULL; |
372 | 304 | uint8_t fr_octet; |
373 | 304 | bool is_response = false; |
374 | 304 | uint32_t addr = 0; |
375 | 304 | bool encap_is_frf_3_2; |
376 | 304 | uint8_t fr_ctrl; |
377 | 304 | uint16_t fr_type; |
378 | 304 | int nlpid_offset; |
379 | 304 | uint8_t fr_nlpid; |
380 | 304 | int control; |
381 | 304 | dissector_handle_t sub_dissector; |
382 | 304 | tvbuff_t *next_tvb; |
383 | | |
384 | 304 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "FR"); |
385 | 304 | col_clear(pinfo->cinfo, COL_INFO); |
386 | | |
387 | 304 | if (has_direction) { |
388 | 0 | if (pinfo->pseudo_header->dte_dce.flags & FROM_DCE) { |
389 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE"); |
390 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE"); |
391 | 0 | } else { |
392 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE"); |
393 | 0 | col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE"); |
394 | 0 | } |
395 | 0 | } |
396 | | |
397 | 304 | if (tree) { |
398 | 304 | ti = proto_tree_add_protocol_format(tree, proto_fr, tvb, 0, -1, "Frame Relay"); |
399 | 304 | fr_tree = proto_item_add_subtree(ti, ett_fr); |
400 | 304 | } |
401 | | |
402 | 304 | if (decode_address) |
403 | 304 | { |
404 | | /* |
405 | | * OK, fetch the address field - keep going until we get an EA bit. |
406 | | */ |
407 | 304 | fr_octet = tvb_get_uint8(tvb, offset); |
408 | | |
409 | 304 | if (fr_octet & FRELAY_EA) { |
410 | | /* |
411 | | * Bogus! There should be at least 2 octets. |
412 | | * XXX - is this FRF.12 frame relay fragmentation? If so, we |
413 | | * should dissect it as such, if possible. |
414 | | */ |
415 | 3 | addr = 0; |
416 | 3 | proto_tree_add_expert_format(fr_tree, pinfo, &ei_fr_bogus_address, tvb, offset, 1, |
417 | 3 | "Bogus 1-octet address field"); |
418 | 3 | offset++; |
419 | 301 | } else { |
420 | 301 | static int * const first_address_bits[] = {&hf_fr_upper_dlci, &hf_fr_cr, &hf_fr_ea, NULL}; |
421 | 301 | static int * const second_address_bits[] = {&hf_fr_second_dlci, &hf_fr_fecn, |
422 | 301 | &hf_fr_becn, &hf_fr_de, &hf_fr_ea, NULL}; |
423 | 301 | static int * const third_address_bits[] = {&hf_fr_third_dlci, &hf_fr_ea, NULL}; |
424 | | |
425 | | /* |
426 | | * The first octet contains the upper 6 bits of the DLCI, as well |
427 | | * as the C/R bit. |
428 | | */ |
429 | 301 | addr = (fr_octet & FRELAY_UPPER_DLCI) >> 2; |
430 | 301 | is_response = (fr_octet & FRELAY_CR); |
431 | | |
432 | 301 | proto_tree_add_bitmask(fr_tree, tvb, offset, hf_fr_first_addr_octet, |
433 | 301 | ett_fr_address, first_address_bits, ENC_NA); |
434 | 301 | offset++; |
435 | | |
436 | | /* |
437 | | * The second octet contains 4 more bits of DLCI, as well as FECN, |
438 | | * BECN, and DE. |
439 | | */ |
440 | 301 | fr_octet = tvb_get_uint8(tvb, offset); |
441 | 301 | addr = (addr << 4) | ((fr_octet & FRELAY_SECOND_DLCI) >> 4); |
442 | 301 | proto_tree_add_bitmask(fr_tree, tvb, offset, hf_fr_second_addr_octet, |
443 | 301 | ett_fr_address, second_address_bits, ENC_NA); |
444 | 301 | offset++; |
445 | | |
446 | 301 | if (!(fr_octet & FRELAY_EA)) { |
447 | | /* |
448 | | * We have 3 or more address octets. |
449 | | * |
450 | | * The third octet contains 7 more bits of DLCI if EA isn't set, |
451 | | * and lower DLCI or DL-CORE control plus the DLCI or DL-CORE |
452 | | * control indicator flag if EA is set. |
453 | | */ |
454 | 94 | fr_octet = tvb_get_uint8(tvb, offset); |
455 | 94 | if (!(fr_octet & FRELAY_EA)) { |
456 | | /* |
457 | | * 7 more bits of DLCI. |
458 | | */ |
459 | 67 | addr = (addr << 7) | ((fr_octet & FRELAY_THIRD_DLCI) >> 1); |
460 | 67 | proto_tree_add_bitmask(fr_tree, tvb, offset, hf_fr_third_addr_octet, |
461 | 67 | ett_fr_address, third_address_bits, ENC_NA); |
462 | 67 | offset++; |
463 | 67 | fr_octet = tvb_get_uint8(tvb, offset); |
464 | 1.05k | while (!(fr_octet & FRELAY_EA)) { |
465 | | /* |
466 | | * Bogus! More than 4 octets of address. |
467 | | */ |
468 | 984 | proto_tree_add_expert_format(fr_tree, pinfo, &ei_fr_bogus_address, tvb, offset, 1, |
469 | 984 | "Bogus extra address octet"); |
470 | 984 | offset++; |
471 | 984 | fr_octet = tvb_get_uint8(tvb, offset); |
472 | 984 | } |
473 | 67 | } |
474 | | |
475 | 94 | octet_tree = proto_tree_add_subtree_format(fr_tree, tvb, offset, 1, |
476 | 94 | ett_fr_address, NULL, "Final address octet: 0x%02x", |
477 | 94 | fr_octet); |
478 | | |
479 | | /* |
480 | | * Last octet - contains lower DLCI or DL-CORE control, DLCI or |
481 | | * DL-CORE control indicator flag. |
482 | | */ |
483 | 94 | if (fr_octet & FRELAY_DC) { |
484 | | /* |
485 | | * DL-CORE. |
486 | | */ |
487 | 52 | proto_tree_add_uint(octet_tree, hf_fr_dlcore_control, tvb, offset, 1, fr_octet); |
488 | 52 | } else { |
489 | | /* |
490 | | * Last 6 bits of DLCI. |
491 | | */ |
492 | 42 | addr = (addr << 6) | ((fr_octet & FRELAY_LOWER_DLCI) >> 2); |
493 | 42 | proto_tree_add_uint(octet_tree, hf_fr_lower_dlci, tvb, offset, 1, fr_octet); |
494 | 42 | } |
495 | 94 | proto_tree_add_boolean(octet_tree, hf_fr_dc, tvb, offset, 1, fr_octet); |
496 | 94 | proto_tree_add_boolean(octet_tree, hf_fr_ea, tvb, offset, 1, fr_octet); |
497 | | |
498 | 94 | offset++; |
499 | 94 | } |
500 | 301 | } |
501 | 304 | if (tree) { |
502 | | /* Put the full DLCI into the protocol tree. */ |
503 | 303 | proto_tree_add_uint(fr_tree, hf_fr_dlci, tvb, 0, offset, addr); |
504 | 303 | } |
505 | | |
506 | 304 | conversation_set_elements_by_id(pinfo, CONVERSATION_DLCI, addr); |
507 | 304 | col_add_fstr(pinfo->cinfo, COL_INFO, "DLCI %u", addr); |
508 | 304 | } |
509 | | |
510 | 304 | switch (fr_encap) { |
511 | | |
512 | 303 | case FRF_3_2: |
513 | 303 | encap_is_frf_3_2 = false; |
514 | 303 | fr_ctrl = tvb_get_uint8(tvb, offset); |
515 | 303 | if (fr_ctrl == XDLC_U) { |
516 | | /* |
517 | | * It looks like an RFC 2427-encapsulation frame, with the |
518 | | * default UI control field. |
519 | | */ |
520 | 2 | encap_is_frf_3_2 = true; |
521 | 301 | } else { |
522 | 301 | if (addr == 0) { |
523 | | /* |
524 | | * This must be some sort of LAPF on DLCI 0 for SVC |
525 | | * because DLCI 0 is reserved for LMI and SVC signaling |
526 | | * encapsulated in LAPF, and LMI is transmitted in |
527 | | * unnumbered information (03), so this must be LAPF |
528 | | * (guessing). |
529 | | * |
530 | | * XXX - but what is it? Is Q.933 carried inside UI |
531 | | * frames or other types of frames or both? |
532 | | */ |
533 | 4 | dissect_xdlc_control(tvb, offset, pinfo, fr_tree, |
534 | 4 | hf_fr_control, ett_fr_control, |
535 | 4 | &fr_cf_items, &fr_cf_items_ext, |
536 | 4 | NULL, NULL, is_response, true, true); |
537 | 4 | dissect_lapf(tvb_new_subset_remaining(tvb,offset),pinfo,tree); |
538 | 4 | return; |
539 | 4 | } |
540 | 297 | if (fr_ctrl == (XDLC_U|XDLC_XID)) { |
541 | | /* |
542 | | * It looks like an RFC 2427-encapsulation frame, with the |
543 | | * a UI control field and an XID command. |
544 | | */ |
545 | 0 | dissect_xdlc_control(tvb, offset, pinfo, fr_tree, |
546 | 0 | hf_fr_control, ett_fr_control, |
547 | 0 | &fr_cf_items, &fr_cf_items_ext, |
548 | 0 | NULL, NULL, is_response, true, true); |
549 | 0 | dissect_fr_xid(tvb_new_subset_remaining(tvb,offset),pinfo,tree); |
550 | 0 | return; |
551 | 0 | } |
552 | | |
553 | | /* |
554 | | * If the data does not start with unnumbered information (03) and |
555 | | * the DLCI# is not 0, then there may be Cisco Frame Relay encapsulation. |
556 | | * See if, were we to treat the two octets after the DLCI as a Cisco |
557 | | * HDLC type, we have a dissector for it. |
558 | | */ |
559 | 297 | if (tvb_bytes_exist(tvb, offset, 2)) { |
560 | 296 | fr_type = tvb_get_ntohs(tvb, offset); |
561 | 296 | sub_dissector = dissector_get_uint_handle(chdlc_subdissector_table, |
562 | 296 | fr_type); |
563 | 296 | if (sub_dissector != NULL) { |
564 | | /* We have a dissector, so assume it's Cisco encapsulation. */ |
565 | 3 | if (ti != NULL) { |
566 | | /* Include the Cisco HDLC type in the top-level protocol |
567 | | tree item. */ |
568 | 3 | proto_item_set_end(ti, tvb, offset+2); |
569 | 3 | } |
570 | 3 | chdlctype(sub_dissector, fr_type, tvb, offset+2, pinfo, tree, fr_tree, |
571 | 3 | hf_fr_chdlctype); |
572 | 3 | return; |
573 | 3 | } |
574 | | |
575 | | /* |
576 | | * We don't have a dissector; this might be an RFC 2427-encapsulated |
577 | | * See if we have a dissector for the putative NLPID. |
578 | | */ |
579 | 293 | nlpid_offset = offset; |
580 | 293 | control = tvb_get_uint8(tvb, nlpid_offset); |
581 | 293 | if (control == 0) { |
582 | | /* Presumably a padding octet; the NLPID would be in the next octet. */ |
583 | 3 | nlpid_offset++; |
584 | 3 | control = tvb_get_uint8(tvb, nlpid_offset); |
585 | 3 | } |
586 | 293 | switch (control & 0x03) { |
587 | | |
588 | 224 | case XDLC_S: |
589 | | /* |
590 | | * Supervisory frame. |
591 | | * We assume we're in extended mode, with 2-octet supervisory |
592 | | * control fields. |
593 | | */ |
594 | 224 | nlpid_offset += 2; |
595 | 224 | break; |
596 | | |
597 | 10 | case XDLC_U: |
598 | | /* |
599 | | * Unnumbered frame. |
600 | | * |
601 | | * XXX - one octet or 2 in extended mode? |
602 | | */ |
603 | 10 | nlpid_offset++; |
604 | 10 | break; |
605 | | |
606 | 59 | default: |
607 | | /* |
608 | | * Information frame. |
609 | | * We assume we're in extended mode, with 2-octet supervisory |
610 | | * control fields. |
611 | | */ |
612 | 59 | nlpid_offset += 2; |
613 | 59 | break; |
614 | 293 | } |
615 | 293 | if (tvb_bytes_exist(tvb, nlpid_offset, 1)) { |
616 | 291 | fr_nlpid = tvb_get_uint8(tvb, nlpid_offset); |
617 | 291 | sub_dissector = dissector_get_uint_handle(fr_osinl_subdissector_table, |
618 | 291 | fr_nlpid); |
619 | 291 | if (sub_dissector != NULL) |
620 | 244 | encap_is_frf_3_2 = true; |
621 | 47 | else { |
622 | 47 | sub_dissector = dissector_get_uint_handle(osinl_incl_subdissector_table, |
623 | 47 | fr_nlpid); |
624 | 47 | if (sub_dissector != NULL) |
625 | 9 | encap_is_frf_3_2 = true; |
626 | 38 | else { |
627 | 38 | if (fr_nlpid == NLPID_SNAP) |
628 | 1 | encap_is_frf_3_2 = true; |
629 | 37 | else { |
630 | 37 | sub_dissector = dissector_get_uint_handle(fr_subdissector_table, |
631 | 37 | fr_nlpid); |
632 | 37 | if (sub_dissector != NULL) |
633 | 20 | encap_is_frf_3_2 = true; |
634 | 37 | } |
635 | 38 | } |
636 | 47 | } |
637 | 291 | } |
638 | 293 | } |
639 | 297 | } |
640 | | |
641 | 296 | if (encap_is_frf_3_2) { |
642 | | /* |
643 | | * We appear to have an NLPID for this dissector, so dissect |
644 | | * it as RFC 2427. |
645 | | */ |
646 | 276 | control = dissect_xdlc_control(tvb, offset, pinfo, fr_tree, |
647 | 276 | hf_fr_control, ett_fr_control, |
648 | 276 | &fr_cf_items, &fr_cf_items_ext, |
649 | 276 | NULL, NULL, is_response, true, true); |
650 | 276 | offset += XDLC_CONTROL_LEN(control, true); |
651 | | |
652 | | /* |
653 | | * XXX - treat DLCI 0 specially? On DLCI 0, an NLPID of 0x08 |
654 | | * means Q.933, but on other circuits it could be the "for |
655 | | * protocols which do not have an NLPID assigned or do not |
656 | | * have a SNAP encapsulation" stuff from RFC 2427. |
657 | | */ |
658 | 276 | dissect_fr_nlpid(tvb, offset, pinfo, tree, ti, fr_tree, fr_ctrl); |
659 | 276 | } else { |
660 | | /* |
661 | | * See if it looks like raw Ethernet. |
662 | | */ |
663 | 20 | uint16_t type_length; |
664 | | |
665 | 20 | if (tvb_bytes_exist(tvb, offset + 12, 2) && |
666 | 14 | ((type_length = tvb_get_ntohs(tvb, offset + 12)) <= IEEE_802_3_MAX_LEN || |
667 | 11 | dissector_get_uint_handle(ethertype_subdissector_table, type_length) != NULL)) { |
668 | | /* It looks like a length or is a known Ethertype; dissect as raw Ethernet */ |
669 | 11 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
670 | 11 | call_dissector(eth_withfcs_handle, next_tvb, pinfo, tree); |
671 | 11 | return; |
672 | 11 | } else { |
673 | | /* It doesn't - just dissect it as data. */ |
674 | 9 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
675 | 9 | call_data_dissector(next_tvb, pinfo, tree); |
676 | 9 | } |
677 | 20 | } |
678 | 285 | break; |
679 | | |
680 | 285 | case GPRS_NS: |
681 | 0 | if (addr == 0) { |
682 | 0 | fr_ctrl = tvb_get_uint8(tvb, offset); |
683 | 0 | control = dissect_xdlc_control(tvb, offset, pinfo, fr_tree, |
684 | 0 | hf_fr_control, ett_fr_control, |
685 | 0 | &fr_cf_items, &fr_cf_items_ext, |
686 | 0 | NULL, NULL, is_response, true, true); |
687 | 0 | offset += XDLC_CONTROL_LEN(control, true); |
688 | 0 | dissect_fr_nlpid(tvb, offset, pinfo, tree, ti, fr_tree, fr_ctrl); |
689 | 0 | } else { |
690 | 0 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
691 | 0 | call_dissector(gprs_ns_handle, next_tvb, pinfo, tree); |
692 | 0 | } |
693 | 0 | break; |
694 | | |
695 | 0 | case RAW_ETHER: |
696 | 0 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
697 | 0 | if (addr != 0) |
698 | 0 | call_dissector(eth_withfcs_handle, next_tvb, pinfo, tree); |
699 | 0 | else |
700 | 0 | dissect_lapf(next_tvb, pinfo, tree); |
701 | 0 | break; |
702 | | |
703 | 0 | case LAPB: |
704 | 0 | next_tvb = tvb_new_subset_remaining(tvb, offset); |
705 | 0 | if (addr != 0) |
706 | 0 | call_dissector(lapb_handle, next_tvb, pinfo, tree); |
707 | 0 | else |
708 | 0 | dissect_lapf(next_tvb, pinfo, tree); |
709 | 0 | break; |
710 | 304 | } |
711 | 304 | } |
712 | | |
713 | | static int |
714 | | dissect_fr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
715 | 304 | { |
716 | 304 | dissect_fr_common(tvb, pinfo, tree, false, true ); |
717 | 304 | return tvb_captured_length(tvb); |
718 | 304 | } |
719 | | |
720 | | static int |
721 | | dissect_fr_phdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
722 | 0 | { |
723 | 0 | dissect_fr_common(tvb, pinfo, tree, true, true ); |
724 | 0 | return tvb_captured_length(tvb); |
725 | 0 | } |
726 | | |
727 | | static int |
728 | | dissect_fr_stripped_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
729 | 0 | { |
730 | 0 | dissect_fr_common(tvb, pinfo, tree, true, false ); |
731 | 0 | return tvb_captured_length(tvb); |
732 | 0 | } |
733 | | |
734 | | static int |
735 | | dissect_fr_uncompressed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
736 | 241 | { |
737 | 241 | proto_item *ti; |
738 | 241 | proto_tree *fr_tree; |
739 | | |
740 | 241 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "FR"); |
741 | 241 | col_clear(pinfo->cinfo, COL_INFO); |
742 | | |
743 | 241 | ti = proto_tree_add_protocol_format(tree, proto_fr, tvb, 0, -1, "Frame Relay"); |
744 | 241 | fr_tree = proto_item_add_subtree(ti, ett_fr); |
745 | | |
746 | 241 | dissect_fr_nlpid(tvb, 0, pinfo, tree, ti, fr_tree, XDLC_U); |
747 | 241 | return tvb_captured_length(tvb); |
748 | 241 | } |
749 | | |
750 | | static void |
751 | | dissect_fr_nlpid(tvbuff_t *tvb, int offset, packet_info *pinfo, |
752 | | proto_tree *tree, proto_item *ti, |
753 | | proto_tree *fr_tree, uint8_t fr_ctrl) |
754 | 517 | { |
755 | 517 | uint8_t fr_nlpid; |
756 | 517 | tvbuff_t *next_tvb; |
757 | | |
758 | | /* |
759 | | * Tentatively set the Frame Relay item not to include the NLPID, |
760 | | * as OSI network layer protocols consider it to be part of |
761 | | * the OSI PDU. |
762 | | */ |
763 | 517 | proto_item_set_end(ti, tvb, offset); |
764 | 517 | fr_nlpid = tvb_get_uint8 (tvb,offset); |
765 | 517 | if (fr_nlpid == 0) { |
766 | 49 | proto_tree_add_uint_format(fr_tree, hf_fr_nlpid, tvb, offset, 1, fr_nlpid, "Padding"); |
767 | 49 | offset++; |
768 | 49 | if (ti != NULL) { |
769 | | /* Include the padding in the top-level protocol tree item. */ |
770 | 49 | proto_item_set_end(ti, tvb, offset); |
771 | 49 | } |
772 | 49 | fr_nlpid=tvb_get_uint8( tvb,offset); |
773 | 49 | } |
774 | | |
775 | | /* |
776 | | * OSI network layer protocols consider the NLPID to be part |
777 | | * of the frame, so we'll pass it as part of the payload and, |
778 | | * if the protocol is one of those, add it as a hidden item here. |
779 | | * We check both the generic OSI NLPID dissector table and |
780 | | * the Frame Relay OSI NLPID dissector table - the latter is for |
781 | | * NLPID's such as 0x08, which is Q.933 in Frame Relay but |
782 | | * other protocols (e.g., Q.931) on other network layers. |
783 | | * |
784 | | * "OSI network layer protocols" includes Q.933. |
785 | | * |
786 | | * We check the Frame Relay table first, so that protocols for which |
787 | | * the NLPID means something different on Frame Relay, i.e. Q.933 vs. |
788 | | * Q.931, are handled appropriately for Frame Relay. |
789 | | * |
790 | | * XXX - note that an NLPID of 0x08 for Q.933 could either be a |
791 | | * Q.933 signaling message or a message for a protocol |
792 | | * identified by a 2-octet layer 2 protocol type and a |
793 | | * 2-octet layer 3 protocol type, those protocol type |
794 | | * octets having the values from octets 6, 6a, 7, and 7a |
795 | | * of a Q.931 low layer compatibility information element |
796 | | * (section 4.5.19 of Q.931; Q.933 says they have the values |
797 | | * from a Q.933 low layer compatibility information element, |
798 | | * but Q.933 low layer compatibility information elements |
799 | | * don't have protocol values in them). |
800 | | * |
801 | | * Assuming that, as Q.933 seems to imply, that Q.933 messages |
802 | | * look just like Q.931 messages except where it explicitly |
803 | | * says they differ, then the octet after the NLPID would, |
804 | | * in a Q.933 message, have its upper 4 bits zero (that's |
805 | | * the length of the call reference value, in Q.931, and |
806 | | * is limited to 15 or fewer octets). As appears to be the case, |
807 | | * octet 6 of a Q.931 low layer compatibility element has the |
808 | | * 0x40 bit set, so you can distinguish between a Q.933 |
809 | | * message and an encapsulated packet by checking whether |
810 | | * the upper 4 bits of the octet after the NLPID are zero. |
811 | | * |
812 | | * Either that, or it's Q.933 iff the DLCI is 0. |
813 | | */ |
814 | 517 | next_tvb = tvb_new_subset_remaining(tvb,offset); |
815 | 517 | if (dissector_try_uint(fr_osinl_subdissector_table, fr_nlpid, next_tvb, |
816 | 517 | pinfo, tree) || |
817 | 83 | dissector_try_uint(osinl_incl_subdissector_table, fr_nlpid, next_tvb, |
818 | 122 | pinfo, tree)) { |
819 | | /* |
820 | | * Yes, we got a match. Add the NLPID as a hidden item, |
821 | | * so you can, at least, filter on it. |
822 | | */ |
823 | 122 | if (tree) { |
824 | 122 | proto_item *hidden_item; |
825 | 122 | hidden_item = proto_tree_add_uint(fr_tree, hf_fr_nlpid, |
826 | 122 | tvb, offset, 1, fr_nlpid ); |
827 | 122 | proto_item_set_hidden(hidden_item); |
828 | 122 | } |
829 | 122 | return; |
830 | 122 | } |
831 | | |
832 | | /* |
833 | | * All other protocols don't. |
834 | | * |
835 | | * XXX - what about Cisco/Gang-of-Four LMI? Is the 0x09 considered |
836 | | * to be part of the LMI PDU? |
837 | | */ |
838 | 395 | if (tree) |
839 | 63 | proto_tree_add_uint(fr_tree, hf_fr_nlpid, tvb, offset, 1, fr_nlpid ); |
840 | 395 | offset++; |
841 | | |
842 | 395 | switch (fr_nlpid) { |
843 | | |
844 | 2 | case NLPID_SNAP: |
845 | 2 | if (ti != NULL) { |
846 | | /* Include the NLPID and SNAP header in the top-level |
847 | | protocol tree item. */ |
848 | 2 | proto_item_set_end(ti, tvb, offset+5); |
849 | 2 | } |
850 | 2 | dissect_snap(tvb, offset, pinfo, tree, fr_tree, fr_ctrl, |
851 | 2 | hf_fr_oui, hf_fr_snaptype, hf_fr_pid, 0); |
852 | 2 | return; |
853 | | |
854 | 61 | default: |
855 | 61 | if (ti != NULL) { |
856 | | /* Include the NLPID in the top-level protocol tree item. */ |
857 | 61 | proto_item_set_end(ti, tvb, offset); |
858 | 61 | } |
859 | 61 | next_tvb = tvb_new_subset_remaining(tvb,offset); |
860 | 61 | if (!dissector_try_uint(fr_subdissector_table,fr_nlpid, |
861 | 61 | next_tvb, pinfo, tree)) |
862 | 11 | call_dissector(data_handle,next_tvb, pinfo, tree); |
863 | 61 | break; |
864 | 395 | } |
865 | 395 | } |
866 | | |
867 | | static void |
868 | | dissect_lapf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
869 | 4 | { |
870 | 4 | proto_tree_add_expert(tree, pinfo, &ei_fr_frame_relay_lapf, tvb, 0, 0); |
871 | 4 | call_dissector(data_handle,tvb_new_subset_remaining(tvb,0),pinfo,tree); |
872 | 4 | } |
873 | | |
874 | | static void |
875 | | dissect_fr_xid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
876 | 0 | { |
877 | 0 | proto_tree_add_expert(tree, pinfo, &ei_fr_frame_relay_xid, tvb, 0, 0); |
878 | 0 | call_dissector(data_handle,tvb_new_subset_remaining(tvb,0),pinfo,tree); |
879 | 0 | } |
880 | | |
881 | | /* Register the protocol with Wireshark */ |
882 | | void |
883 | | proto_register_fr(void) |
884 | 14 | { |
885 | 14 | static hf_register_info hf[] = { |
886 | 14 | { &hf_fr_ea, |
887 | 14 | { "EA", "fr.ea", |
888 | 14 | FT_BOOLEAN, 8, TFS(&ea_string), FRELAY_EA, |
889 | 14 | "Extended Address", HFILL }}, |
890 | | |
891 | 14 | { &hf_fr_upper_dlci, |
892 | 14 | { "Upper DLCI", "fr.upper_dlci", |
893 | 14 | FT_UINT8, BASE_HEX, NULL, FRELAY_UPPER_DLCI, |
894 | 14 | "Upper bits of DLCI", HFILL }}, |
895 | | |
896 | 14 | { &hf_fr_cr, |
897 | 14 | { "CR", "fr.cr", |
898 | 14 | FT_BOOLEAN, 8, TFS(&tfs_command_response), FRELAY_CR, |
899 | 14 | "Command/Response", HFILL }}, |
900 | | |
901 | 14 | { &hf_fr_second_dlci, |
902 | 14 | { "Second DLCI", "fr.second_dlci", |
903 | 14 | FT_UINT8, BASE_HEX, NULL, FRELAY_SECOND_DLCI, |
904 | 14 | "Bits below upper bits of DLCI", HFILL }}, |
905 | | |
906 | 14 | { &hf_fr_fecn, |
907 | 14 | { "FECN", "fr.fecn", |
908 | 14 | FT_BOOLEAN, 8, NULL, FRELAY_FECN, |
909 | 14 | "Forward Explicit Congestion Notification", HFILL }}, |
910 | | |
911 | 14 | { &hf_fr_becn, |
912 | 14 | { "BECN", "fr.becn", |
913 | 14 | FT_BOOLEAN, 8, NULL, FRELAY_BECN, |
914 | 14 | "Backward Explicit Congestion Notification", HFILL }}, |
915 | | |
916 | 14 | { &hf_fr_de, |
917 | 14 | { "DE", "fr.de", |
918 | 14 | FT_BOOLEAN, 8, NULL, FRELAY_DE, |
919 | 14 | "Discard Eligibility", HFILL }}, |
920 | | |
921 | 14 | { &hf_fr_third_dlci, |
922 | 14 | { "Third DLCI", "fr.third_dlci", |
923 | 14 | FT_UINT8, BASE_HEX, NULL, FRELAY_THIRD_DLCI, |
924 | 14 | "Additional bits of DLCI", HFILL }}, |
925 | | |
926 | 14 | { &hf_fr_dlcore_control, |
927 | 14 | { "DL-CORE Control", "fr.dlcore_control", |
928 | 14 | FT_UINT8, BASE_HEX, NULL, FRELAY_LOWER_DLCI, |
929 | 14 | "DL-Core control bits", HFILL }}, |
930 | | |
931 | 14 | { &hf_fr_lower_dlci, |
932 | 14 | { "Lower DLCI", "fr.lower_dlci", |
933 | 14 | FT_UINT8, BASE_HEX, NULL, FRELAY_LOWER_DLCI, |
934 | 14 | "Lower bits of DLCI", HFILL }}, |
935 | | |
936 | 14 | { &hf_fr_dc, |
937 | 14 | { "DC", "fr.dc", |
938 | 14 | FT_BOOLEAN, 8, TFS(&ctrl_string), FRELAY_DC, |
939 | 14 | "Address/Control", HFILL }}, |
940 | | |
941 | 14 | { &hf_fr_dlci, |
942 | 14 | { "DLCI", "fr.dlci", |
943 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
944 | 14 | "Data-Link Connection Identifier", HFILL }}, |
945 | | |
946 | 14 | { &hf_fr_control, |
947 | 14 | { "Control Field", "fr.control", |
948 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
949 | 14 | NULL, HFILL }}, |
950 | | |
951 | 14 | { &hf_fr_n_r, |
952 | 14 | { "N(R)", "fr.control.n_r", |
953 | 14 | FT_UINT16, BASE_DEC, NULL, XDLC_N_R_EXT_MASK, |
954 | 14 | NULL, HFILL }}, |
955 | | |
956 | 14 | { &hf_fr_n_s, |
957 | 14 | { "N(S)", "fr.control.n_s", |
958 | 14 | FT_UINT16, BASE_DEC, NULL, XDLC_N_S_EXT_MASK, |
959 | 14 | NULL, HFILL }}, |
960 | | |
961 | 14 | { &hf_fr_p, |
962 | 14 | { "Poll", "fr.control.p", |
963 | 14 | FT_BOOLEAN, 8, TFS(&tfs_set_notset), XDLC_P_F, |
964 | 14 | NULL, HFILL }}, |
965 | | |
966 | 14 | { &hf_fr_p_ext, |
967 | 14 | { "Poll", "fr.control.p", |
968 | 14 | FT_BOOLEAN, 16, TFS(&tfs_set_notset), XDLC_P_F_EXT, |
969 | 14 | NULL, HFILL }}, |
970 | | |
971 | 14 | { &hf_fr_f, |
972 | 14 | { "Final", "fr.control.f", |
973 | 14 | FT_BOOLEAN, 8, TFS(&tfs_set_notset), XDLC_P_F, |
974 | 14 | NULL, HFILL }}, |
975 | | |
976 | 14 | { &hf_fr_f_ext, |
977 | 14 | { "Final", "fr.control.f", |
978 | 14 | FT_BOOLEAN, 16, TFS(&tfs_set_notset), XDLC_P_F_EXT, |
979 | 14 | NULL, HFILL }}, |
980 | | |
981 | 14 | { &hf_fr_s_ftype, |
982 | 14 | { "Supervisory frame type", "fr.control.s_ftype", |
983 | 14 | FT_UINT16, BASE_HEX, VALS(stype_vals), XDLC_S_FTYPE_MASK, |
984 | 14 | NULL, HFILL }}, |
985 | | |
986 | 14 | { &hf_fr_u_modifier_cmd, |
987 | 14 | { "Command", "fr.control.u_modifier_cmd", |
988 | 14 | FT_UINT8, BASE_HEX, VALS(modifier_vals_cmd), XDLC_U_MODIFIER_MASK, |
989 | 14 | NULL, HFILL }}, |
990 | | |
991 | 14 | { &hf_fr_u_modifier_resp, |
992 | 14 | { "Response", "fr.control.u_modifier_resp", |
993 | 14 | FT_UINT8, BASE_HEX, VALS(modifier_vals_resp), XDLC_U_MODIFIER_MASK, |
994 | 14 | NULL, HFILL }}, |
995 | | |
996 | 14 | { &hf_fr_ftype_i, |
997 | 14 | { "Frame type", "fr.control.ftype", |
998 | 14 | FT_UINT16, BASE_HEX, VALS(ftype_vals), XDLC_I_MASK, |
999 | 14 | NULL, HFILL }}, |
1000 | | |
1001 | 14 | { &hf_fr_ftype_s_u, |
1002 | 14 | { "Frame type", "fr.control.ftype", |
1003 | 14 | FT_UINT8, BASE_HEX, VALS(ftype_vals), XDLC_S_U_MASK, |
1004 | 14 | NULL, HFILL }}, |
1005 | | |
1006 | 14 | { &hf_fr_ftype_s_u_ext, |
1007 | 14 | { "Frame type", "fr.control.ftype", |
1008 | 14 | FT_UINT16, BASE_HEX, VALS(ftype_vals), XDLC_S_U_MASK, |
1009 | 14 | NULL, HFILL }}, |
1010 | | |
1011 | 14 | { &hf_fr_nlpid, |
1012 | 14 | { "NLPID", "fr.nlpid", |
1013 | 14 | FT_UINT8, BASE_HEX, VALS(fr_nlpid_vals), 0x0, |
1014 | 14 | "Frame Relay Encapsulated Protocol NLPID", HFILL }}, |
1015 | | |
1016 | 14 | { &hf_fr_oui, |
1017 | 14 | { "Organization Code", "fr.snap.oui", |
1018 | 14 | FT_UINT24, BASE_OUI, NULL, 0x0, |
1019 | 14 | NULL, HFILL }}, |
1020 | | |
1021 | 14 | { &hf_fr_pid, |
1022 | 14 | { "Protocol ID", "fr.snap.pid", |
1023 | 14 | FT_UINT16, BASE_HEX, NULL, 0x0, |
1024 | 14 | NULL, HFILL }}, |
1025 | | |
1026 | 14 | { &hf_fr_snaptype, |
1027 | 14 | { "Type", "fr.snaptype", |
1028 | 14 | FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, |
1029 | 14 | "Frame Relay SNAP Encapsulated Protocol", HFILL }}, |
1030 | | |
1031 | 14 | { &hf_fr_chdlctype, |
1032 | 14 | { "Type", "fr.chdlctype", |
1033 | 14 | FT_UINT16, BASE_HEX, VALS(chdlc_vals), 0x0, |
1034 | 14 | "Frame Relay Cisco HDLC Encapsulated Protocol", HFILL }}, |
1035 | | |
1036 | 14 | { &hf_fr_first_addr_octet, |
1037 | 14 | { "First address octet", "fr.first_addr_octet", |
1038 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
1039 | 14 | NULL, HFILL }}, |
1040 | | |
1041 | 14 | { &hf_fr_second_addr_octet, |
1042 | 14 | { "Second address octet", "fr.second_addr_octet", |
1043 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
1044 | 14 | NULL, HFILL }}, |
1045 | | |
1046 | 14 | { &hf_fr_third_addr_octet, |
1047 | 14 | { "Third address octet", "fr.third_addr_octet", |
1048 | 14 | FT_UINT8, BASE_HEX, NULL, 0x0, |
1049 | 14 | NULL, HFILL }}, |
1050 | | |
1051 | 14 | }; |
1052 | | |
1053 | | /* Setup protocol subtree array */ |
1054 | 14 | static int *ett[] = { |
1055 | 14 | &ett_fr, |
1056 | 14 | &ett_fr_address, |
1057 | 14 | &ett_fr_control, |
1058 | 14 | }; |
1059 | 14 | static ei_register_info ei[] = { |
1060 | 14 | { &ei_fr_bogus_address, { "fr.bogus_address", PI_PROTOCOL, PI_WARN, "Bogus address", EXPFILL }}, |
1061 | 14 | { &ei_fr_frame_relay_lapf, { "fr.frame_relay.lapf", PI_UNDECODED, PI_WARN, "Frame relay lapf not yet implemented", EXPFILL }}, |
1062 | 14 | { &ei_fr_frame_relay_xid, { "fr.frame_relay.xid", PI_UNDECODED, PI_WARN, "Frame relay xid not yet implemented", EXPFILL }}, |
1063 | 14 | }; |
1064 | | |
1065 | 14 | static const enum_val_t fr_encap_options[] = { |
1066 | 14 | { "frf-3.2", "FRF 3.2/Cisco HDLC", FRF_3_2 }, |
1067 | 14 | { "gprs-ns", "GPRS Network Service", GPRS_NS }, |
1068 | 14 | { "ethernet", "Raw Ethernet", RAW_ETHER }, |
1069 | 14 | { "lapb", "LAPB (T1.617a-1994 Annex G)", LAPB }, |
1070 | 14 | { NULL, NULL, 0 }, |
1071 | 14 | }; |
1072 | 14 | module_t *frencap_module; |
1073 | 14 | expert_module_t* expert_fr; |
1074 | | |
1075 | 14 | proto_fr = proto_register_protocol("Frame Relay", "FR", "fr"); |
1076 | 14 | proto_register_field_array(proto_fr, hf, array_length(hf)); |
1077 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1078 | 14 | expert_fr = expert_register_protocol(proto_fr); |
1079 | 14 | expert_register_field_array(expert_fr, ei, array_length(ei)); |
1080 | | |
1081 | 14 | fr_subdissector_table = register_dissector_table("fr.nlpid", |
1082 | 14 | "Frame Relay NLPID", proto_fr, FT_UINT8, BASE_HEX); |
1083 | 14 | fr_osinl_subdissector_table = register_dissector_table("fr.osinl", |
1084 | 14 | "Frame Relay OSI NLPID", proto_fr, FT_UINT8, BASE_HEX); |
1085 | | |
1086 | 14 | register_dissector("fr_uncompressed", dissect_fr_uncompressed, proto_fr); |
1087 | 14 | fr_handle = register_dissector("fr", dissect_fr, proto_fr); |
1088 | 14 | register_dissector("fr_stripped_address", dissect_fr_stripped_address, proto_fr); |
1089 | | |
1090 | 14 | frencap_module = prefs_register_protocol(proto_fr, NULL); |
1091 | | /* |
1092 | | * XXX - this should really be per-circuit - I've seen at least one |
1093 | | * capture where different DLCIs have different encapsulations - but |
1094 | | * we don't yet have any support for per-circuit encapsulations. |
1095 | | * |
1096 | | * Even with that, though, we might want a default encapsulation, |
1097 | | * so that people dealing with GPRS can make gprs-ns the default. |
1098 | | */ |
1099 | 14 | prefs_register_enum_preference(frencap_module, "encap", "Encapsulation", |
1100 | 14 | "Encapsulation", &fr_encap, |
1101 | 14 | fr_encap_options, false); |
1102 | | |
1103 | 14 | register_capture_dissector_table("fr.nlpid", "Frame Relay NLPID"); |
1104 | 14 | } |
1105 | | |
1106 | | void |
1107 | | proto_reg_handoff_fr(void) |
1108 | 14 | { |
1109 | 14 | dissector_handle_t fr_phdr_handle; |
1110 | 14 | capture_dissector_handle_t fr_cap_handle; |
1111 | | |
1112 | 14 | dissector_add_uint("gre.proto", ETHERTYPE_RAW_FR, fr_handle); |
1113 | 14 | dissector_add_uint("wtap_encap", WTAP_ENCAP_FRELAY, fr_handle); |
1114 | 14 | dissector_add_uint("juniper.proto", JUNIPER_PROTO_FRELAY, fr_handle); |
1115 | 14 | dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_FRAME_RELAY, fr_handle); |
1116 | 14 | dissector_add_uint("atm.aal5.type", TRAF_FR, fr_handle); |
1117 | 14 | dissector_add_uint("l2tp.pw_type", L2TPv3_PW_FR, fr_handle); |
1118 | 14 | dissector_add_uint("sll.hatype", ARPHRD_FRAD, fr_handle); |
1119 | | |
1120 | 14 | fr_phdr_handle = create_dissector_handle(dissect_fr_phdr, proto_fr); |
1121 | 14 | dissector_add_uint("wtap_encap", WTAP_ENCAP_FRELAY_WITH_PHDR, fr_phdr_handle); |
1122 | | |
1123 | 14 | fr_cap_handle = create_capture_dissector_handle(capture_fr, proto_fr); |
1124 | 14 | capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_FRELAY, fr_cap_handle); |
1125 | 14 | capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_FRELAY_WITH_PHDR, fr_cap_handle); |
1126 | | |
1127 | 14 | eth_withfcs_handle = find_dissector_add_dependency("eth_withfcs", proto_fr); |
1128 | 14 | gprs_ns_handle = find_dissector_add_dependency("gprs_ns", proto_fr); |
1129 | 14 | lapb_handle = find_dissector_add_dependency("lapb", proto_fr); |
1130 | 14 | data_handle = find_dissector_add_dependency("data", proto_fr); |
1131 | | |
1132 | 14 | chdlc_subdissector_table = find_dissector_table("chdlc.protocol"); |
1133 | 14 | osinl_incl_subdissector_table = find_dissector_table("osinl.incl"); |
1134 | 14 | ethertype_subdissector_table = find_dissector_table("ethertype"); |
1135 | | |
1136 | 14 | chdlc_cap_handle = find_capture_dissector("chdlc"); |
1137 | 14 | eth_cap_handle = find_capture_dissector("eth"); |
1138 | 14 | } |
1139 | | |
1140 | | /* |
1141 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1142 | | * |
1143 | | * Local Variables: |
1144 | | * c-basic-offset: 2 |
1145 | | * tab-width: 8 |
1146 | | * indent-tabs-mode: nil |
1147 | | * End: |
1148 | | * |
1149 | | * ex: set shiftwidth=2 tabstop=8 expandtab: |
1150 | | * :indentSize=2:tabSize=8:noTabs=true: |
1151 | | */ |