2 * Routines for Frame Relay MPLS PW dissection as per RFC4619.
3 * Copyright 2009, Dmitry Trebich, Artem Tamazov <artem.tamazov@tellabs.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * ---------------------------------
27 * 18.03.2009 initial implementation
30 * - Correct FR decode for encapsulations which contain fragmented FR frames.
31 * - FR DLCI Martini (legacy) mode (i.e. legacy CW).
37 #include <epan/packet.h>
38 #include <epan/expert.h>
40 #include "packet-mpls.h"
42 static gint proto_encaps
= -1;
43 static gint ett_encaps
= -1;
45 /* static int hf_pw_fr = -1; */
46 static int hf_cw_bits03
= -1;
47 static int hf_cw_fecn
= -1;
48 static int hf_cw_becn
= -1;
49 static int hf_cw_de
= -1;
50 static int hf_cw_cr
= -1;
51 static int hf_cw_frg
= -1;
52 static int hf_cw_len
= -1;
53 static int hf_cw_seq
= -1;
55 static expert_field ei_payload_size_invalid
= EI_INIT
;
56 static expert_field ei_cw_bits03
= EI_INIT
;
57 static expert_field ei_cw_packet_size_too_small
= EI_INIT
;
59 static const value_string vals_frg
[] = {
60 { 0x0, "Unfragmented" },
61 { 0x1, "First fragment" },
62 { 0x2, "Last fragment" },
63 { 0x3, "Intermediate fragment" },
68 static dissector_handle_t fr_stripped_address_handle
;
72 dissect_pw_fr( tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
)
77 const int encaps_size
= 4; /*encapsulation consists of mandatory CW only*/
80 ,PQ_CW_BAD_BITS03
= 0x002
81 ,PQ_CW_BAD_LEN_GT_PACKET
= 0x004
82 ,PQ_CW_BAD_LEN_MUST_BE_ZERO
= 0x008
83 ,PQ_CW_BAD_LEN_MUST_BE_NONZERO
= 0x010
84 ,PQ_PAYLOAD_SIZE_ZERO
= 0x020
88 packet_size
= tvb_reported_length_remaining(tvb
, 0);
89 if (packet_size
< encaps_size
)
93 item
= proto_tree_add_item(tree
, proto_encaps
, tvb
, 0, -1, ENC_NA
);
94 expert_add_info_format(pinfo
, item
, &ei_cw_packet_size_too_small
,
95 "PW packet (%d) is smaller than PW encapsulation header (%d)",
96 (int)packet_size
,(int)encaps_size
);
98 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FR PW");
99 col_set_str(pinfo
->cinfo
, COL_INFO
, "Malformed: PW packet < PW encapsulation header");
103 if (dissect_try_cw_first_nibble(tvb
,pinfo
,tree
))
108 /* check how "good" is this packet */
109 /* also decide payload length from packet size and CW */
111 if (0 != (tvb_get_guint8(tvb
, 0) & 0xf0 /*bits03*/))
113 packet_quality
|= PQ_CW_BAD
+ PQ_CW_BAD_BITS03
;
117 * [ If the frame's length (defined as the
118 * length of the layer 2 payload plus the length of the control word)
119 * is less than 64 octets, the length field MUST be set to the PW
120 * payload length. Otherwise, the length field MUST be set to zero. ]
122 * Note difference from RFC4385 which states that:
123 * [..the length field MUST be set to the length of the PW payload
124 * *plus* the length of the *PWMCW*. ]
127 gint payload_size_packet
; /*derived from packet size*/
129 cw_len
= tvb_get_guint8(tvb
, 1) & 0x3f;
130 payload_size_packet
= packet_size
- encaps_size
;
133 * Initial assumptions.
135 payload_size
= payload_size_packet
;
138 if (payload_size_packet
< 64)
140 gint payload_size_cw
; /*derived from cw*/
141 payload_size_cw
= cw_len
; /*RFC4619-specific*/
142 if (payload_size_cw
== 0)
144 packet_quality
|= PQ_CW_BAD
+ PQ_CW_BAD_LEN_MUST_BE_NONZERO
;
146 else if (payload_size_cw
> payload_size_packet
)
148 packet_quality
|= PQ_CW_BAD
+ PQ_CW_BAD_LEN_GT_PACKET
;
152 payload_size
= payload_size_cw
;
153 payload_padding
= payload_size_packet
- payload_size_cw
; /* >=0 */
156 else /* payload_size_packet >= 64 */
160 packet_quality
|= PQ_CW_BAD
+ PQ_CW_BAD_LEN_MUST_BE_ZERO
;
164 if (payload_size
== 0)
166 packet_quality
|= PQ_PAYLOAD_SIZE_ZERO
;
169 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FR PW");
170 col_clear(pinfo
->cinfo
, COL_INFO
);
171 if (packet_quality
& PQ_CW_BAD
)
173 col_set_str(pinfo
->cinfo
, COL_INFO
, "CW:Malformed, ");
175 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%d payload octets", (int)payload_size
);
177 if (payload_padding
!= 0)
179 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", %d padding", (int)payload_padding
);
184 proto_item
* item_headline
;
187 item_headline
= proto_tree_add_item(tree
, proto_encaps
, tvb
, 0, 4, ENC_NA
);
188 proto_item_append_text(item_headline
, ": 0x%.8" G_GINT32_MODIFIER
"x", tvb_get_ntohl(tvb
, 0));
189 subtree
= proto_item_add_subtree(item_headline
, ett_encaps
);
191 if (packet_quality
& PQ_CW_BAD_BITS03
) /*display only if value is wrong*/
193 item
= proto_tree_add_item(subtree
, hf_cw_bits03
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
194 expert_add_info(pinfo
, item
, &ei_cw_bits03
);
197 (void)proto_tree_add_item( subtree
, hf_cw_fecn
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
198 (void)proto_tree_add_item( subtree
, hf_cw_becn
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
199 (void)proto_tree_add_item( subtree
, hf_cw_de
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
200 (void)proto_tree_add_item( subtree
, hf_cw_cr
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
201 (void)proto_tree_add_item( subtree
, hf_cw_frg
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
203 item
= proto_tree_add_item( subtree
, hf_cw_len
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
204 if (packet_quality
& PQ_CW_BAD_LEN_GT_PACKET
)
206 expert_add_info_format(pinfo
, item
, &ei_payload_size_invalid
,
207 "Bad Length: greater than FR payload size (%d)",
210 if (packet_quality
& PQ_CW_BAD_LEN_MUST_BE_NONZERO
)
212 expert_add_info_format(pinfo
, item
, &ei_payload_size_invalid
,
213 "Bad Length: must be non-zero if FR PW packet size (%d) is < 64",
214 (int)(payload_size
+encaps_size
));
216 if (packet_quality
& PQ_CW_BAD_LEN_MUST_BE_ZERO
)
218 expert_add_info_format(pinfo
, item
, &ei_payload_size_invalid
,
219 "Bad Length: must be 0 if FR PW packet size (%d) is >= 64",
220 (int)(payload_size
+encaps_size
));
223 proto_tree_add_item( subtree
, hf_cw_seq
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
225 if (payload_padding
> 0)
227 proto_tree_add_text(subtree
, tvb
,
228 encaps_size
+payload_size
, payload_padding
,
229 "[Padding: %d octets]",(int)payload_padding
);
232 if (packet_quality
& PQ_PAYLOAD_SIZE_ZERO
)
234 expert_add_info_format(pinfo
, item_headline
, &ei_payload_size_invalid
,
235 "FR payload size must be non-zero");
239 if (payload_size
> 0)
241 tvbuff_t
*tvb_payload
;
242 tvb_payload
= tvb_new_subset(tvb
, encaps_size
, payload_size
, payload_size
);
243 call_dissector( fr_stripped_address_handle
, tvb_payload
, pinfo
, tree
);
250 proto_register_pw_fr(void)
252 static hf_register_info hf
[] = {
253 {&hf_cw_bits03
,{"Bits 0 to 3" ,"pwfr.bits03" ,FT_UINT8
,BASE_HEX
257 {&hf_cw_fecn
,{"FR FECN" ,"pwfr.fecn" ,FT_UINT8
,BASE_DEC
258 ,NULL
,0x08 ,"FR Forward Explicit Congestion Notification bit"
261 {&hf_cw_becn
,{"FR BECN" ,"pwfr.becn" ,FT_UINT8
,BASE_DEC
262 ,NULL
,0x04 ,"FR Backward Explicit Congestion Notification bit"
265 {&hf_cw_de
,{"FR DE bit" ,"pwfr.de" ,FT_UINT8
,BASE_DEC
266 ,NULL
,0x02 ,"FR Discard Eligibility bit"
269 {&hf_cw_cr
,{"FR Frame C/R" ,"pwfr.cr" ,FT_UINT8
,BASE_DEC
270 ,NULL
,0x01 ,"FR frame Command/Response bit"
273 {&hf_cw_frg
,{"Fragmentation" ,"pwfr.frag" ,FT_UINT8
,BASE_DEC
274 ,vals_frg
,0xc0 ,NULL
277 {&hf_cw_len
,{"Length" ,"pwfr.length" ,FT_UINT8
,BASE_DEC
281 {&hf_cw_seq
,{"Sequence number" ,"pwfr.length" ,FT_UINT16
,BASE_DEC
286 static gint
*ett
[] = {
290 static ei_register_info ei
[] = {
291 { &ei_cw_packet_size_too_small
, { "pwfr.packet_size_too_small", PI_MALFORMED
, PI_ERROR
, "PW packet is smaller than PW encapsulation header", EXPFILL
}},
292 { &ei_cw_bits03
, { "pwfr.cw.bits03.not_zero", PI_MALFORMED
, PI_ERROR
, "Bits 0..3 of Control Word must be 0", EXPFILL
}},
293 { &ei_payload_size_invalid
, { "pwfr.payload.size_invalid", PI_MALFORMED
, PI_ERROR
, "Bad Length: greater than FR payload size", EXPFILL
}},
295 expert_module_t
* expert_pwfr
;
297 proto_encaps
= proto_register_protocol( "PW Frame Relay DLCI Control Word",
298 "Frame Relay DLCI PW",
300 proto_register_field_array(proto_encaps
, hf
, array_length(hf
));
301 proto_register_subtree_array(ett
, array_length(ett
));
302 expert_pwfr
= expert_register_protocol(proto_encaps
);
303 expert_register_field_array(expert_pwfr
, ei
, array_length(ei
));
304 register_dissector("pw_fr", dissect_pw_fr
, proto_encaps
);
309 proto_reg_handoff_pw_fr(void)
311 dissector_handle_t h
;
312 h
= find_dissector("pw_fr");
313 dissector_add_uint("mpls.label", MPLS_LABEL_INVALID
, h
);
314 fr_stripped_address_handle
= find_dissector("fr_stripped_address");