2 * Routines for PPP Over Ethernet (PPPoE) packet disassembly (RFC2516)
3 * Up to date with http://www.iana.org/assignments/pppoe-parameters (2008-04-30)
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.
29 #include <epan/packet.h>
30 #include <epan/strutil.h>
31 #include <epan/etypes.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
34 #include <epan/ppptypes.h>
36 static int proto_pppoed
= -1;
38 /* Common to session and discovery protocols */
39 static gint hf_pppoe_version
= -1;
40 static gint hf_pppoe_type
= -1;
41 static gint hf_pppoe_code
= -1;
42 static gint hf_pppoe_session_id
= -1;
43 static gint hf_pppoe_payload_length
= -1;
45 /* Discovery protocol fields */
46 static gint hf_pppoed_tags
= -1;
47 static gint hf_pppoed_tag
= -1;
48 static gint hf_pppoed_tag_length
= -1;
49 static gint hf_pppoed_tag_length_8
= -1;
50 static gint hf_pppoed_tag_unknown_data
= -1;
51 static gint hf_pppoed_tag_service_name
= -1;
52 static gint hf_pppoed_tag_ac_name
= -1;
53 static gint hf_pppoed_tag_host_uniq
= -1;
54 static gint hf_pppoed_tag_ac_cookie
= -1;
55 static gint hf_pppoed_tag_vendor_id
= -1;
56 static gint hf_pppoed_tag_vendor_unspecified
= -1;
57 static gint hf_pppoed_tag_vspec_tags
= -1;
58 static gint hf_pppoed_tag_vspec_tag
= -1;
59 static gint hf_pppoed_tag_vspec_circuit_id
= -1;
60 static gint hf_pppoed_tag_vspec_remote_id
= -1;
61 static gint hf_pppoed_tag_vspec_act_data_rate_up
= -1;
62 static gint hf_pppoed_tag_vspec_act_data_rate_down
= -1;
63 static gint hf_pppoed_tag_vspec_min_data_rate_up
= -1;
64 static gint hf_pppoed_tag_vspec_min_data_rate_down
= -1;
65 static gint hf_pppoed_tag_vspec_attainable_data_rate_up
= -1;
66 static gint hf_pppoed_tag_vspec_attainable_data_rate_down
= -1;
67 static gint hf_pppoed_tag_vspec_max_data_rate_up
= -1;
68 static gint hf_pppoed_tag_vspec_max_data_rate_down
= -1;
69 static gint hf_pppoed_tag_vspec_min_data_rate_up_lp
= -1;
70 static gint hf_pppoed_tag_vspec_min_data_rate_down_lp
= -1;
71 static gint hf_pppoed_tag_vspec_max_int_delay_up
= -1;
72 static gint hf_pppoed_tag_vspec_act_int_delay_up
= -1;
73 static gint hf_pppoed_tag_vspec_max_int_delay_down
= -1;
74 static gint hf_pppoed_tag_vspec_act_int_delay_down
= -1;
75 static gint hf_pppoed_tag_vspec_access_loop_encapsulation
= -1;
76 static gint hf_pppoed_tag_vspec_access_loop_encap_data_link
= -1;
77 static gint hf_pppoed_tag_vspec_access_loop_encap_encap_1
= -1;
78 static gint hf_pppoed_tag_vspec_access_loop_encap_encap_2
= -1;
79 static gint hf_pppoed_tag_credits
= -1;
80 static gint hf_pppoed_tag_credits_fcn
= -1;
81 static gint hf_pppoed_tag_credits_bcn
= -1;
82 static gint hf_pppoed_tag_metrics
= -1;
83 static gint hf_pppoed_tag_metrics_r
= -1;
84 static gint hf_pppoed_tag_metrics_rlq
= -1;
85 static gint hf_pppoed_tag_metrics_resource
= -1;
86 static gint hf_pppoed_tag_metrics_latency
= -1;
87 static gint hf_pppoed_tag_metrics_curr_drate
= -1;
88 static gint hf_pppoed_tag_metrics_max_drate
= -1;
89 static gint hf_pppoed_tag_mdr_units
= -1;
90 static gint hf_pppoed_tag_cdr_units
= -1;
91 static gint hf_pppoed_tag_seq_num
= -1;
92 static gint hf_pppoed_tag_cred_scale
= -1;
93 static gint hf_pppoed_tag_relay_session_id
= -1;
94 static gint hf_pppoed_tag_hurl
= -1;
95 static gint hf_pppoed_tag_motm
= -1;
96 static gint hf_pppoed_tag_max_payload
= -1;
97 static gint hf_pppoed_tag_ip_route_add
= -1;
98 static gint hf_pppoed_tag_service_name_error
= -1;
99 static gint hf_pppoed_tag_ac_system_error
= -1;
100 static gint hf_pppoed_tag_generic_error
= -1;
102 /* Session protocol fields */
103 static gint hf_pppoes_tags
= -1;
104 /* static gint hf_pppoes_tag = -1; */
105 /* static gint hf_pppoes_tag_credits = -1; */
106 static gint hf_pppoes_tag_credits_fcn
= -1;
107 static gint hf_pppoes_tag_credits_bcn
= -1;
109 /* Session protocol fields */
111 static gint ett_pppoed
= -1;
112 static gint ett_pppoed_tags
= -1;
113 static gint ett_pppoed_tag_vspec_dslf_access_loop_encaps
= -1;
115 static int proto_pppoes
= -1;
117 static gint ett_pppoes
= -1;
118 static gint ett_pppoes_tags
= -1;
120 static expert_field ei_pppoe_payload_length
= EI_INIT
;
121 static expert_field ei_pppoe_tag_length
= EI_INIT
;
123 /* PPPoE parent fields */
125 static int proto_pppoe
= -1;
126 static gint ett_pppoe
= -1;
129 /* Handle for calling for ppp dissector to handle session data */
130 static dissector_handle_t ppp_handle
;
133 /* Preference for showing discovery tag values and lengths */
134 static gboolean global_pppoe_show_tags_and_lengths
= FALSE
;
137 #define PPPOE_CODE_SESSION 0x00
138 #define PPPOE_CODE_PADO 0x07
139 #define PPPOE_CODE_PADI 0x09
140 #define PPPOE_CODE_PADG 0x0a
141 #define PPPOE_CODE_PADC 0x0b
142 #define PPPOE_CODE_PADQ 0x0c
143 #define PPPOE_CODE_PADR 0x19
144 #define PPPOE_CODE_PADS 0x65
145 #define PPPOE_CODE_PADT 0xa7
146 #define PPPOE_CODE_PADM 0xd3
147 #define PPPOE_CODE_PADN 0xd4
149 #define PPPOE_TAG_EOL 0x0000
150 #define PPPOE_TAG_SVC_NAME 0x0101
151 #define PPPOE_TAG_AC_NAME 0x0102
152 #define PPPOE_TAG_HOST_UNIQ 0x0103
153 #define PPPOE_TAG_AC_COOKIE 0x0104
154 #define PPPOE_TAG_VENDOR 0x0105
155 #define PPPOE_TAG_CREDITS 0x0106
156 #define PPPOE_TAG_METRICS 0x0107
157 #define PPPOE_TAG_SEQ_NUM 0x0108
158 #define PPPOE_TAG_CRED_SCALE 0x0109
159 #define PPPOE_TAG_RELAY_ID 0x0110
160 #define PPPOE_TAG_HURL 0x0111
161 #define PPPOE_TAG_MOTM 0x0112
162 #define PPPOE_TAG_MAX_PAYLD 0x0120
163 #define PPPOE_TAG_IP_RT_ADD 0x0121
164 #define PPPOE_TAG_SVC_ERR 0x0201
165 #define PPPOE_TAG_AC_ERR 0x0202
166 #define PPPOE_TAG_GENERIC_ERR 0x0203
168 #define PPPOE_VENDOR_ID_DSLF 3561
170 #define PPPOE_TAG_VSPEC_DSLF_CIRCUIT_ID 0x01
171 #define PPPOE_TAG_VSPEC_DSLF_REMOTE_ID 0x02
172 #define PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_UP 0x81
173 #define PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_DOWN 0x82
174 #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP 0x83
175 #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN 0x84
176 #define PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_UP 0x85
177 #define PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_DOWN 0x86
178 #define PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_UP 0x87
179 #define PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_DOWN 0x88
180 #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP_LP 0x89
181 #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN_LP 0x8a
182 #define PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_UP 0x8b
183 #define PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_UP 0x8c
184 #define PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_DOWN 0x8d
185 #define PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_DOWN 0x8e
186 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAPSULATION 0x90
188 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ATM 0x00
189 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ETH 0x01
191 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_NA 0x00
192 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_UNTAGGED_ETH 0x01
193 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_SINLE_TAGGED_ETH 0x02
195 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_NA 0x00
196 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_LLC 0x01
197 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_NULL 0x02
198 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_LLC 0x03
199 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_NULL 0x04
200 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITH_FCS 0x05
201 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITHOUT_FCS 0x06
202 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITH_FCS 0x07
203 #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITHOUT_FCS 0x08
205 #define PPPOE_CDR_MASK 0x06
206 #define PPPOE_MDR_MASK 0x18
207 #define PPPOE_RCV_ONLY_MASK 0x01
209 #define PPPOE_SCALE_KBPS 0x00
210 #define PPPOE_SCALE_MBPS 0x01
211 #define PPPOE_SCALE_GBPS 0x02
212 #define PPPOE_SCALE_TBPS 0x03
215 static const value_string code_vals
[] = {
216 {PPPOE_CODE_SESSION
, "Session Data" },
217 {PPPOE_CODE_PADO
, "Active Discovery Offer (PADO)" },
218 {PPPOE_CODE_PADI
, "Active Discovery Initiation (PADI)" },
219 {PPPOE_CODE_PADG
, "Active Discovery Session-Grant (PADG)" },
220 {PPPOE_CODE_PADC
, "Active Discovery Session-Credit Resp.(PADC)" },
221 {PPPOE_CODE_PADQ
, "Active Discovery Quality (PADQ)" },
222 {PPPOE_CODE_PADR
, "Active Discovery Request (PADR)" },
223 {PPPOE_CODE_PADS
, "Active Discovery Session-confirmation (PADS)"},
224 {PPPOE_CODE_PADT
, "Active Discovery Terminate (PADT)" },
225 {PPPOE_CODE_PADM
, "Active Discovery Message (PADM)" },
226 {PPPOE_CODE_PADN
, "Active Discovery Network (PADN)" },
231 static const value_string tag_vals
[] = {
232 {PPPOE_TAG_EOL
, "End-Of-List" },
233 {PPPOE_TAG_SVC_NAME
, "Service-Name" },
234 {PPPOE_TAG_AC_NAME
, "AC-Name" },
235 {PPPOE_TAG_HOST_UNIQ
, "Host-Uniq" },
236 {PPPOE_TAG_AC_COOKIE
, "AC-Cookie" },
237 {PPPOE_TAG_VENDOR
, "Vendor-Specific" },
238 {PPPOE_TAG_CREDITS
, "Credits" },
239 {PPPOE_TAG_METRICS
, "Metrics" },
240 {PPPOE_TAG_SEQ_NUM
, "Sequence Number" },
241 {PPPOE_TAG_CRED_SCALE
, "Credit Scale Factor"},
242 {PPPOE_TAG_RELAY_ID
, "Relay-Session-Id" },
243 {PPPOE_TAG_HURL
, "HURL" },
244 {PPPOE_TAG_MOTM
, "MOTM" },
245 {PPPOE_TAG_MAX_PAYLD
, "PPP-Max-Payload" },
246 {PPPOE_TAG_IP_RT_ADD
, "IP Route Add" },
247 {PPPOE_TAG_SVC_ERR
, "Service-Name-Error"},
248 {PPPOE_TAG_AC_ERR
, "AC-System-Error" },
249 {PPPOE_TAG_GENERIC_ERR
,"Generic-Error" },
253 static const value_string vspec_tag_vals
[] = {
254 {PPPOE_TAG_VSPEC_DSLF_CIRCUIT_ID
, "Circuit-ID" },
255 {PPPOE_TAG_VSPEC_DSLF_REMOTE_ID
, "Remote-ID" },
256 {PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_UP
, "Actual-Data-Rate-Up" },
257 {PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_DOWN
, "Actual-Data-Rate-Down" },
258 {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP
, "Min-Data-Rate-Up" },
259 {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN
, "Min-Data-Rate-Down" },
260 {PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_UP
, "Attainable-Data-Rate-Up" },
261 {PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_DOWN
, "Attainable-Data-Rate-Down" },
262 {PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_UP
, "Max-Data-Rate-Up" },
263 {PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_DOWN
, "Max-Data-Rate-Down" },
264 {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP_LP
, "Min-Data-Rate-Up-Low-Power" },
265 {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN_LP
, "Min-Data-Rate-Down-Low-Power" },
266 {PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_UP
, "Max-Interleaving-Delay-Up" },
267 {PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_UP
, "Actual-Interleaving-Delay-Up" },
268 {PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_DOWN
, "Max-Interleaving-Delay-Down" },
269 {PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_DOWN
, "Actual-Interleaving-Delay-Down"},
270 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAPSULATION
, "Access-Loop-Encapsulation" },
274 static const value_string vspec_tag_dslf_access_loop_encap_data_link_vals
[] = {
275 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ATM
, "ATM AAL5"},
276 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ETH
, "Ethernet"},
280 static const value_string vspec_tag_dslf_access_loop_encap_encap_1_vals
[] = {
281 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_NA
, "NA" },
282 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_UNTAGGED_ETH
, "Untagged Ethernet" },
283 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_SINLE_TAGGED_ETH
, "Single-tagged Ethernet"},
287 static const value_string vspec_tag_dslf_access_loop_encap_encap_2_vals
[] = {
288 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_NA
, "NA" },
289 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_LLC
, "PPPoA LLC" },
290 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_NULL
, "PPPoA Null" },
291 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_LLC
, "IPoA LLC" },
292 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_NULL
, "IPoA Null" },
293 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITH_FCS
, "Ethernet over AAL5 LLC w FCS" },
294 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITHOUT_FCS
, "Ethernet over AAL5 LLC w/o FCS" },
295 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITH_FCS
, "Ethernet over AAL5 Null w FCS" },
296 {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITHOUT_FCS
,"Ethernet over AAL5 Null w/o FCS"},
300 static const value_string datarate_scale_vals
[] = {
301 {PPPOE_SCALE_KBPS
, "kilobits per second"},
302 {PPPOE_SCALE_MBPS
, "megabits per second"},
303 {PPPOE_SCALE_GBPS
, "gigabits per second"},
304 {PPPOE_SCALE_TBPS
, "terabits per second"},
309 #define CASE_VSPEC_DSLF_TAG_UINT(tag_name, relation, length, hf_var) case tag_name: \
310 if (!(poe_tag_length relation length)) { \
311 expert_add_info_format(pinfo, pppoe_tree, &ei_pppoe_tag_length, \
312 "%s: Wrong length: %u (expected %s %d)", \
313 val_to_str_const(poe_tag, vspec_tag_vals, "Unknown"), poe_tag_length, #relation, length); \
315 proto_tree_add_item(pppoe_tree, hf_var, tvb, \
316 tagstart+2, poe_tag_length, ENC_BIG_ENDIAN); \
320 #define CASE_VSPEC_DSLF_TAG_STRING(tag_name, relation, length, hf_var) case tag_name: \
321 if (!(poe_tag_length relation length)) { \
322 expert_add_info_format(pinfo, pppoe_tree, &ei_pppoe_tag_length, \
323 "%s: Wrong length: %u (expected %s %d)", \
324 val_to_str_const(poe_tag, vspec_tag_vals, "Unknown"), poe_tag_length, #relation, length); \
326 proto_tree_add_item(pppoe_tree, hf_var, tvb, \
327 tagstart+2, poe_tag_length, ENC_ASCII|ENC_NA); \
331 /* Dissect Vendor-Specific Tags introduced by the DSLF */
333 dissect_pppoe_subtags_dslf(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int offset
, proto_tree
*tree
,
337 guint8 poe_tag_length
;
340 proto_tree
*pppoe_tree
, *ti
, *encaps_tree
;
342 /* Start Decoding Here. */
345 /* Create tags subtree */
346 ti
= proto_tree_add_item(tree
, hf_pppoed_tag_vspec_tags
, tvb
, offset
, payload_length
, ENC_NA
);
347 pppoe_tree
= proto_item_add_subtree(ti
, ett_pppoed_tags
);
351 /* Loop until all data seen or End-Of-List tag found */
352 while (tagstart
<= offset
+ payload_length
-2)
354 poe_tag
= tvb_get_guint8(tvb
, tagstart
);
355 poe_tag_length
= tvb_get_guint8(tvb
, tagstart
+ 1);
357 /* Tag value and data length */
358 if (global_pppoe_show_tags_and_lengths
)
360 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_vspec_tag
, tvb
, tagstart
, 1, ENC_BIG_ENDIAN
);
361 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_length_8
, tvb
, tagstart
+1, 1, ENC_BIG_ENDIAN
);
367 CASE_VSPEC_DSLF_TAG_STRING(PPPOE_TAG_VSPEC_DSLF_CIRCUIT_ID
, <=, 63,
368 hf_pppoed_tag_vspec_circuit_id
)
369 CASE_VSPEC_DSLF_TAG_STRING(PPPOE_TAG_VSPEC_DSLF_REMOTE_ID
, <=, 63,
370 hf_pppoed_tag_vspec_remote_id
)
371 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_UP
, ==, 4,
372 hf_pppoed_tag_vspec_act_data_rate_up
)
373 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_DOWN
, ==, 4,
374 hf_pppoed_tag_vspec_act_data_rate_down
)
375 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP
, ==, 4,
376 hf_pppoed_tag_vspec_min_data_rate_up
)
377 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN
, ==, 4,
378 hf_pppoed_tag_vspec_min_data_rate_down
)
379 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_UP
, ==, 4,
380 hf_pppoed_tag_vspec_attainable_data_rate_up
)
381 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_DOWN
, ==, 4,
382 hf_pppoed_tag_vspec_attainable_data_rate_down
)
383 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_UP
, ==, 4,
384 hf_pppoed_tag_vspec_max_data_rate_up
)
385 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_DOWN
, ==, 4,
386 hf_pppoed_tag_vspec_max_data_rate_down
)
387 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP_LP
, ==, 4,
388 hf_pppoed_tag_vspec_min_data_rate_up_lp
)
389 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN_LP
, ==, 4,
390 hf_pppoed_tag_vspec_min_data_rate_down_lp
)
391 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_UP
, ==, 4,
392 hf_pppoed_tag_vspec_max_int_delay_up
)
393 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_UP
, ==, 4,
394 hf_pppoed_tag_vspec_act_int_delay_up
)
395 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_DOWN
, ==, 4,
396 hf_pppoed_tag_vspec_max_int_delay_down
)
397 CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_DOWN
, ==, 4,
398 hf_pppoed_tag_vspec_act_int_delay_down
)
399 case PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAPSULATION
:
400 ti
= proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_vspec_access_loop_encapsulation
, tvb
,
401 tagstart
+2, 3, ENC_NA
);
402 if (poe_tag_length
!= 3) {
403 expert_add_info_format(pinfo
, ti
, &ei_pppoe_tag_length
, "%s: Wrong length: %u (expected 3)", val_to_str_const(poe_tag
, vspec_tag_vals
, "Unknown"), poe_tag_length
);
405 encaps_tree
= proto_item_add_subtree(ti
, ett_pppoed_tag_vspec_dslf_access_loop_encaps
);
406 proto_tree_add_item(encaps_tree
, hf_pppoed_tag_vspec_access_loop_encap_data_link
,
407 tvb
, tagstart
+2, 1, ENC_BIG_ENDIAN
);
408 proto_tree_add_item(encaps_tree
, hf_pppoed_tag_vspec_access_loop_encap_encap_1
,
409 tvb
, tagstart
+3, 1, ENC_BIG_ENDIAN
);
410 proto_tree_add_item(encaps_tree
, hf_pppoed_tag_vspec_access_loop_encap_encap_2
,
411 tvb
, tagstart
+4, 1, ENC_BIG_ENDIAN
);
415 if (poe_tag_length
> 0 )
417 /* Presumably unknown tag;
418 show tag value if we didn't do it above */
419 if (!global_pppoe_show_tags_and_lengths
)
421 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag
, tvb
, tagstart
, 1, ENC_BIG_ENDIAN
);
422 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_length_8
, tvb
, tagstart
+1, 1, ENC_BIG_ENDIAN
);
424 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_unknown_data
, tvb
,
425 tagstart
+1, poe_tag_length
, ENC_NA
);
429 tagstart
+= (2 + poe_tag_length
);
435 /* Dissect discovery protocol tags */
437 dissect_pppoe_tags(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, proto_tree
*tree
,
441 guint16 poe_tag_length
;
445 proto_tree
*pppoe_tree
;
447 proto_item
*pppoe_tree_tag_length_item
= NULL
;
450 /* Start Decoding Here. */
453 /* Create tags subtree */
454 ti
= proto_tree_add_item(tree
, hf_pppoed_tags
, tvb
, offset
, payload_length
-6, ENC_NA
);
455 pppoe_tree
= proto_item_add_subtree(ti
, ett_pppoed_tags
);
459 /* Loop until all data seen or End-Of-List tag found */
460 while (tagstart
<= payload_length
-2)
462 poe_tag
= tvb_get_ntohs(tvb
, tagstart
);
463 poe_tag_length
= tvb_get_ntohs(tvb
, tagstart
+ 2);
465 /* Tag value and data length */
466 if (global_pppoe_show_tags_and_lengths
)
468 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag
, tvb
, tagstart
, 2, ENC_BIG_ENDIAN
);
469 pppoe_tree_tag_length_item
=
470 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_length
, tvb
, tagstart
+2, 2, ENC_BIG_ENDIAN
);
476 case PPPOE_TAG_SVC_NAME
:
477 if (poe_tag_length
> 0)
479 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_service_name
, tvb
,
480 tagstart
+4, poe_tag_length
, ENC_ASCII
|ENC_NA
);
483 case PPPOE_TAG_AC_NAME
:
484 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_ac_name
, tvb
,
485 tagstart
+4, poe_tag_length
, ENC_ASCII
|ENC_NA
);
486 /* Show AC-Name in info column */
487 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " AC-Name='%s'",
488 tvb_get_string(wmem_packet_scope(), tvb
, tagstart
+4, poe_tag_length
));
490 case PPPOE_TAG_HOST_UNIQ
:
491 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_host_uniq
, tvb
,
492 tagstart
+4, poe_tag_length
, ENC_NA
);
494 case PPPOE_TAG_AC_COOKIE
:
495 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_ac_cookie
, tvb
,
496 tagstart
+4, poe_tag_length
, ENC_NA
);
498 case PPPOE_TAG_VENDOR
:
499 if (poe_tag_length
>= 4)
501 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_vendor_id
, tvb
,
502 tagstart
+4, 4, ENC_BIG_ENDIAN
);
504 if (poe_tag_length
> 4)
506 guint32 vendor_id
= tvb_get_ntohl(tvb
, tagstart
+4);
509 case PPPOE_VENDOR_ID_DSLF
:
510 dissect_pppoe_subtags_dslf(tvb
,pinfo
,tagstart
+4+4,pppoe_tree
,poe_tag_length
-4);
513 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_vendor_unspecified
, tvb
,
514 tagstart
+4+4, poe_tag_length
-4, ENC_NA
);
519 case PPPOE_TAG_CREDITS
:
520 if (poe_tag_length
== 4)
522 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_credits_fcn
, tvb
,
523 tagstart
+4, 2, ENC_BIG_ENDIAN
);
524 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_credits_bcn
, tvb
,
525 tagstart
+6, 2, ENC_BIG_ENDIAN
);
527 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_credits
, tvb
,
528 tagstart
+4, poe_tag_length
, ENC_NA
);
531 case PPPOE_TAG_METRICS
:
532 if (poe_tag_length
== 10)
534 poe_rsv
= tvb_get_ntohs(tvb
, tagstart
+4);
536 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_mdr_units
, tvb
,
537 tagstart
+4, 2, ENC_BIG_ENDIAN
);
538 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_cdr_units
, tvb
,
539 tagstart
+4, 2, ENC_BIG_ENDIAN
);
540 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics_r
, tvb
,
541 tagstart
+4, 2, ENC_BIG_ENDIAN
);
542 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics_rlq
, tvb
,
543 tagstart
+6, 1, ENC_BIG_ENDIAN
);
544 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics_resource
, tvb
,
545 tagstart
+7, 1, ENC_BIG_ENDIAN
);
546 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics_latency
, tvb
,
547 tagstart
+8, 2, ENC_BIG_ENDIAN
);
550 ti
= proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics_curr_drate
, tvb
,
551 tagstart
+10, 2, ENC_BIG_ENDIAN
);
553 switch ((poe_rsv
& PPPOE_CDR_MASK
) >> 1)
555 case (PPPOE_SCALE_KBPS
):
556 proto_item_append_text(ti
, " kbps");
558 case (PPPOE_SCALE_MBPS
):
559 proto_item_append_text(ti
, " mbps");
561 case (PPPOE_SCALE_GBPS
):
562 proto_item_append_text(ti
, " gbps");
564 case (PPPOE_SCALE_TBPS
):
565 proto_item_append_text(ti
, " tbps");
570 ti
= proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics_max_drate
, tvb
,
571 tagstart
+12, 2, ENC_BIG_ENDIAN
);
573 switch ((poe_rsv
& PPPOE_MDR_MASK
) >> 3)
575 case (PPPOE_SCALE_KBPS
):
576 proto_item_append_text(ti
, " kbps");
578 case (PPPOE_SCALE_MBPS
):
579 proto_item_append_text(ti
, " mbps");
581 case (PPPOE_SCALE_GBPS
):
582 proto_item_append_text(ti
, " gbps");
584 case (PPPOE_SCALE_TBPS
):
585 proto_item_append_text(ti
, " tbps");
590 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_metrics
, tvb
,
591 tagstart
+4, poe_tag_length
, ENC_NA
);
594 case PPPOE_TAG_SEQ_NUM
:
595 if (poe_tag_length
== 2) {
596 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_seq_num
, tvb
,
597 tagstart
+4, poe_tag_length
, ENC_BIG_ENDIAN
);
599 if (global_pppoe_show_tags_and_lengths
) {
600 proto_item_append_text(pppoe_tree_tag_length_item
, " [Wrong: should be 2]");
601 item
= pppoe_tree_tag_length_item
;
603 item
= proto_tree_add_text(pppoe_tree
, tvb
, tagstart
+4, poe_tag_length
,
604 "%s: Wrong length: %u (expected 2)",
605 proto_registrar_get_name(hf_pppoed_tag_seq_num
),
608 expert_add_info_format(pinfo
, item
, &ei_pppoe_tag_length
, "Sequence Number tag: Wrong length: %u (expected 2)", poe_tag_length
);
611 case PPPOE_TAG_CRED_SCALE
:
612 if (poe_tag_length
== 2) {
613 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_cred_scale
, tvb
,
614 tagstart
+4, poe_tag_length
, ENC_BIG_ENDIAN
);
616 if (global_pppoe_show_tags_and_lengths
) {
617 proto_item_append_text(pppoe_tree_tag_length_item
, " [Wrong: should be 2]");
618 item
= pppoe_tree_tag_length_item
;
620 item
= proto_tree_add_text(pppoe_tree
, tvb
, tagstart
+4, poe_tag_length
,
621 "%s: Wrong length: %u (expected 2)",
622 proto_registrar_get_name(hf_pppoed_tag_cred_scale
),
625 expert_add_info_format(pinfo
, item
, &ei_pppoe_tag_length
, "Credit Scale Factor tag: Wrong length: %u (expected 2)", poe_tag_length
);
628 case PPPOE_TAG_RELAY_ID
:
629 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_relay_session_id
, tvb
,
630 tagstart
+4, poe_tag_length
, ENC_NA
);
633 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_hurl
, tvb
,
634 tagstart
+4, poe_tag_length
, ENC_NA
);
637 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_motm
, tvb
,
638 tagstart
+4, poe_tag_length
, ENC_NA
);
640 case PPPOE_TAG_MAX_PAYLD
:
641 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_max_payload
, tvb
,
642 tagstart
+4, poe_tag_length
, ENC_NA
);
644 case PPPOE_TAG_IP_RT_ADD
:
645 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_ip_route_add
, tvb
,
646 tagstart
+4, poe_tag_length
, ENC_NA
);
649 /* These error tag values should be interpreted as a utf-8 unterminated
651 case PPPOE_TAG_SVC_ERR
:
652 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_service_name_error
, tvb
,
653 tagstart
+4, poe_tag_length
, ENC_ASCII
|ENC_NA
);
655 case PPPOE_TAG_AC_ERR
:
656 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_ac_system_error
, tvb
,
657 tagstart
+4, poe_tag_length
, ENC_ASCII
|ENC_NA
);
659 case PPPOE_TAG_GENERIC_ERR
:
660 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_generic_error
, tvb
,
661 tagstart
+4, poe_tag_length
, ENC_ASCII
|ENC_NA
);
664 /* Get out if see end-of-list tag */
669 if (poe_tag_length
> 0 )
671 /* Presumably unknown tag;
672 show tag value if we didn't
674 if (!global_pppoe_show_tags_and_lengths
)
676 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag
, tvb
, tagstart
, 2, ENC_BIG_ENDIAN
);
677 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_length
, tvb
, tagstart
+2, 2, ENC_BIG_ENDIAN
);
679 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_unknown_data
, tvb
,
680 tagstart
+2, poe_tag_length
, ENC_NA
);
684 tagstart
+= (4 + poe_tag_length
);
690 /* Discovery protocol, i.e. PPP session not yet established */
691 static void dissect_pppoed(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
694 guint16 reported_payload_length
;
696 proto_tree
*pppoe_tree
= NULL
;
699 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PPPoED");
700 col_clear(pinfo
->cinfo
, COL_INFO
);
702 /* Start Decoding Here. */
703 pppoe_code
= tvb_get_guint8(tvb
, 1);
705 col_append_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(pppoe_code
, code_vals
, "Unknown"));
707 /* Read length of payload */
708 reported_payload_length
= tvb_get_ntohs(tvb
, 4);
712 ti
= proto_tree_add_item(tree
, proto_pppoed
, tvb
, 0, reported_payload_length
+6, ENC_NA
);
713 pppoe_tree
= proto_item_add_subtree(ti
, ett_pppoed
);
715 /* Dissect fixed fields */
716 proto_tree_add_item(pppoe_tree
, hf_pppoe_version
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
717 proto_tree_add_item(pppoe_tree
, hf_pppoe_type
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
718 proto_tree_add_item(pppoe_tree
, hf_pppoe_code
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
719 proto_tree_add_item(pppoe_tree
, hf_pppoe_session_id
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
720 proto_tree_add_item(pppoe_tree
, hf_pppoe_payload_length
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
723 /* Now dissect any tags */
724 if (reported_payload_length
> 0)
726 dissect_pppoe_tags(tvb
, pinfo
, 6, pppoe_tree
, 6+reported_payload_length
);
731 void proto_register_pppoed(void)
733 static hf_register_info hf
[] =
735 /* Discovery tag fields */
737 { "PPPoE Tags", "pppoed.tags", FT_NONE
, BASE_NONE
,
738 NULL
, 0x0, NULL
, HFILL
742 { "Tag", "pppoed.tag", FT_UINT16
, BASE_HEX
,
743 VALS(tag_vals
), 0x0, NULL
, HFILL
746 { &hf_pppoed_tag_length
,
747 { "Tag Length", "pppoed.tag_length", FT_UINT16
, BASE_DEC
,
748 NULL
, 0x0, NULL
, HFILL
751 { &hf_pppoed_tag_length_8
,
752 { "Tag Length", "pppoed.tag_length_8", FT_UINT8
, BASE_DEC
,
753 NULL
, 0x0, NULL
, HFILL
756 { &hf_pppoed_tag_unknown_data
,
757 { "Unknown Data", "pppoed.tag.unknown_data", FT_BYTES
, BASE_NONE
,
758 NULL
, 0x0, NULL
, HFILL
761 { &hf_pppoed_tag_service_name
,
762 { "Service-Name", "pppoed.tags.service_name", FT_STRING
, BASE_NONE
,
763 NULL
, 0x0, NULL
, HFILL
766 { &hf_pppoed_tag_ac_name
,
767 { "AC-Name", "pppoed.tags.ac_name", FT_STRING
, BASE_NONE
,
768 NULL
, 0x0, NULL
, HFILL
771 { &hf_pppoed_tag_host_uniq
,
772 { "Host-Uniq", "pppoed.tags.host_uniq", FT_BYTES
, BASE_NONE
,
773 NULL
, 0x0, NULL
, HFILL
776 { &hf_pppoed_tag_ac_cookie
,
777 { "AC-Cookie", "pppoed.tags.ac_cookie", FT_BYTES
, BASE_NONE
,
778 NULL
, 0x0, NULL
, HFILL
781 { &hf_pppoed_tag_vendor_id
,
782 { "Vendor id", "pppoed.tags.vendor_id", FT_UINT32
, BASE_DEC
,
783 NULL
, 0x0, NULL
, HFILL
786 { &hf_pppoed_tag_vendor_unspecified
,
787 { "Vendor unspecified", "pppoed.tags.vendor_unspecified", FT_BYTES
, BASE_NONE
,
788 NULL
, 0x0, NULL
, HFILL
791 { &hf_pppoed_tag_vspec_tags
,
792 { "Vendor Specific PPPoE Tags", "pppoed.tags.vendorspecific.tags", FT_NONE
, BASE_NONE
,
793 NULL
, 0x0, NULL
, HFILL
796 { &hf_pppoed_tag_vspec_tag
,
797 { "Tag", "pppoed.tags.vendorspecific.tag", FT_UINT8
, BASE_HEX
,
798 VALS(vspec_tag_vals
), 0x0, NULL
, HFILL
801 { &hf_pppoed_tag_vspec_circuit_id
,
802 { "Circuit ID", "pppoed.tags.circuit_id", FT_STRING
, BASE_NONE
,
803 NULL
, 0x0, NULL
, HFILL
806 { &hf_pppoed_tag_vspec_remote_id
,
807 { "Remote ID", "pppoed.tags.remote_id", FT_STRING
, BASE_NONE
,
808 NULL
, 0x0, NULL
, HFILL
811 { &hf_pppoed_tag_vspec_act_data_rate_up
,
812 { "Actual Data Rate Upstream", "pppoed.tags.act_data_rate_up", FT_UINT32
, BASE_DEC
,
813 NULL
, 0x0, NULL
, HFILL
816 { &hf_pppoed_tag_vspec_act_data_rate_down
,
817 { "Actual Data Rate Downstream", "pppoed.tags.act_data_rate_down", FT_UINT32
, BASE_DEC
,
818 NULL
, 0x0, NULL
, HFILL
821 { &hf_pppoed_tag_vspec_min_data_rate_up
,
822 { "Minimum Data Rate Upstream", "pppoed.tags.min_data_rate_up", FT_UINT32
, BASE_DEC
,
823 NULL
, 0x0, NULL
, HFILL
826 { &hf_pppoed_tag_vspec_min_data_rate_down
,
827 { "Minimum Data Rate Downstream", "pppoed.tags.min_data_rate_down", FT_UINT32
, BASE_DEC
,
828 NULL
, 0x0, NULL
, HFILL
831 { &hf_pppoed_tag_vspec_attainable_data_rate_up
,
832 { "Attainable DataRate Upstream", "pppoed.tags.attainable_data_rate_up", FT_UINT32
, BASE_DEC
,
833 NULL
, 0x0, NULL
, HFILL
836 { &hf_pppoed_tag_vspec_attainable_data_rate_down
,
837 { "Attainable DataRate Downstream", "pppoed.tags.attainable_data_rate_down", FT_UINT32
, BASE_DEC
,
838 NULL
, 0x0, NULL
, HFILL
841 { &hf_pppoed_tag_vspec_max_data_rate_up
,
842 { "Maximum Data Rate Upstream", "pppoed.tags.max_data_rate_up", FT_UINT32
, BASE_DEC
,
843 NULL
, 0x0, NULL
, HFILL
846 { &hf_pppoed_tag_vspec_max_data_rate_down
,
847 { "Maximum Data Rate Downstream", "pppoed.tags.max_data_rate_down", FT_UINT32
, BASE_DEC
,
848 NULL
, 0x0, NULL
, HFILL
851 { &hf_pppoed_tag_vspec_min_data_rate_up_lp
,
852 { "Min DataRate Upstream in low power state", "pppoed.tags.min_data_rate_up_lp", FT_UINT32
, BASE_DEC
,
853 NULL
, 0x0, NULL
, HFILL
856 { &hf_pppoed_tag_vspec_min_data_rate_down_lp
,
857 { "Minimum Data Rate Downstream in low power state", "pppoed.tags.min_data_rate_down_lp", FT_UINT32
, BASE_DEC
,
858 NULL
, 0x0, NULL
, HFILL
861 { &hf_pppoed_tag_vspec_max_int_delay_up
,
862 { "Max Interleaving Delay Upstream", "pppoed.tags.max_int_delay_up", FT_UINT32
, BASE_DEC
,
863 NULL
, 0x0, NULL
, HFILL
866 { &hf_pppoed_tag_vspec_act_int_delay_up
,
867 { "Actual Interleaving Delay Upstream", "pppoed.tags.act_int_delay_up", FT_UINT32
, BASE_DEC
,
868 NULL
, 0x0, NULL
, HFILL
871 { &hf_pppoed_tag_vspec_max_int_delay_down
,
872 { "Maximum Interleaving Delay Downstream", "pppoed.tags.max_int_delay_down", FT_UINT32
, BASE_DEC
,
873 NULL
, 0x0, NULL
, HFILL
876 { &hf_pppoed_tag_vspec_act_int_delay_down
,
877 { "Actual Interleaving Delay Downstream", "pppoed.tags.act_int_delay_down", FT_UINT32
, BASE_DEC
,
878 NULL
, 0x0, NULL
, HFILL
881 { &hf_pppoed_tag_vspec_access_loop_encapsulation
,
882 { "Access-Loop-Encapsulation", "pppoed.tags.access_loop_encap", FT_NONE
, BASE_NONE
,
883 NULL
, 0x0, NULL
, HFILL
886 { &hf_pppoed_tag_vspec_access_loop_encap_data_link
,
887 { "Data link", "pppoed.tags.access_loop_encap.data_link", FT_UINT8
, BASE_HEX
,
888 VALS(vspec_tag_dslf_access_loop_encap_data_link_vals
), 0x0, NULL
, HFILL
891 { &hf_pppoed_tag_vspec_access_loop_encap_encap_1
,
892 { "Encaps 1", "pppoed.tags.access_loop_encap.encap_1", FT_UINT8
, BASE_HEX
,
893 VALS(vspec_tag_dslf_access_loop_encap_encap_1_vals
), 0x0, NULL
, HFILL
896 { &hf_pppoed_tag_vspec_access_loop_encap_encap_2
,
897 { "Encaps 1", "pppoed.tags.access_loop_encap.encap_2", FT_UINT8
, BASE_HEX
,
898 VALS(vspec_tag_dslf_access_loop_encap_encap_2_vals
), 0x0, NULL
, HFILL
901 { &hf_pppoed_tag_credits
,
902 { "Credits", "pppoed.tags.credits", FT_BYTES
, BASE_NONE
,
903 NULL
, 0x0, NULL
, HFILL
906 { &hf_pppoed_tag_credits_fcn
,
907 { "FCN", "pppoed.tags.credits.fcn", FT_UINT16
, BASE_DEC
,
908 NULL
, 0x0, NULL
, HFILL
911 { &hf_pppoed_tag_credits_bcn
,
912 { "BCN", "pppoed.tags.credits.bcn", FT_UINT16
, BASE_DEC
,
913 NULL
, 0x0, NULL
, HFILL
916 { &hf_pppoed_tag_metrics
,
917 { "Metrics", "pppoed.tags.metrics", FT_BYTES
, BASE_NONE
,
918 NULL
, 0x0, NULL
, HFILL
921 { &hf_pppoed_tag_metrics_r
,
922 { "Receive Only", "pppoed.tags.metrics.r", FT_BOOLEAN
, 16,
923 NULL
, PPPOE_RCV_ONLY_MASK
, NULL
, HFILL
926 { &hf_pppoed_tag_mdr_units
,
927 { "MDR Units", "pppoed.tags.metrics.mdr_units", FT_UINT16
, BASE_HEX
,
928 VALS(datarate_scale_vals
), PPPOE_MDR_MASK
, NULL
, HFILL
931 { &hf_pppoed_tag_cdr_units
,
932 { "CDR Units", "pppoed.tags.metrics.cdr_units", FT_UINT16
, BASE_HEX
,
933 VALS(datarate_scale_vals
), PPPOE_CDR_MASK
, NULL
, HFILL
936 { &hf_pppoed_tag_metrics_rlq
,
937 { "Relative Link Quality", "pppoed.tags.metrics.rlq", FT_UINT8
, BASE_DEC
,
938 NULL
, 0x0, NULL
, HFILL
941 { &hf_pppoed_tag_metrics_resource
,
942 { "Resource", "pppoed.tags.metrics.resource", FT_UINT8
, BASE_DEC
,
943 NULL
, 0x0, NULL
, HFILL
946 { &hf_pppoed_tag_metrics_latency
,
947 { "Latency", "pppoed.tags.metrics.latency", FT_UINT16
, BASE_DEC
,
948 NULL
, 0x0, NULL
, HFILL
951 { &hf_pppoed_tag_metrics_curr_drate
,
952 { "Curr. datarate", "pppoed.tags.metrics.curr_drate", FT_UINT16
, BASE_DEC
,
953 NULL
, 0x0, NULL
, HFILL
956 { &hf_pppoed_tag_metrics_max_drate
,
957 { "Max. datarate", "pppoed.tags.metrics.max_drate", FT_UINT16
, BASE_DEC
,
958 NULL
, 0x0, NULL
, HFILL
961 { &hf_pppoed_tag_seq_num
,
962 { "Sequence Number", "pppoed.tags.seq_num", FT_UINT16
, BASE_HEX
,
963 NULL
, 0x0, NULL
, HFILL
966 { &hf_pppoed_tag_cred_scale
,
967 { "Credit Scale Factor", "pppoed.tags.credit_scale", FT_UINT16
, BASE_DEC
,
968 NULL
, 0x0, NULL
, HFILL
971 { &hf_pppoed_tag_relay_session_id
,
972 { "Relay-Session-Id", "pppoed.tags.relay_session_id", FT_BYTES
, BASE_NONE
,
973 NULL
, 0x0, NULL
, HFILL
976 { &hf_pppoed_tag_hurl
,
977 { "HURL", "pppoed.tags.hurl", FT_BYTES
, BASE_NONE
,
978 NULL
, 0x0, NULL
, HFILL
981 { &hf_pppoed_tag_motm
,
982 { "MOTM", "pppoed.tags.motm", FT_BYTES
, BASE_NONE
,
983 NULL
, 0x0, NULL
, HFILL
986 { &hf_pppoed_tag_max_payload
,
987 { "PPP-Max-Payload", "pppoed.tags.max_payload", FT_BYTES
, BASE_NONE
,
988 NULL
, 0x0, NULL
, HFILL
991 { &hf_pppoed_tag_ip_route_add
,
992 { "IP Route Add", "pppoed.tags.ip_route_add", FT_BYTES
, BASE_NONE
,
993 NULL
, 0x0, NULL
, HFILL
996 { &hf_pppoed_tag_service_name_error
,
997 { "Service-Name-Error", "pppoed.tags.service_name_error", FT_STRING
, BASE_NONE
,
998 NULL
, 0x0, NULL
, HFILL
1001 { &hf_pppoed_tag_ac_system_error
,
1002 { "AC-System-Error", "pppoed.tags.ac_system_error", FT_STRING
, BASE_NONE
,
1003 NULL
, 0x0, NULL
, HFILL
1006 { &hf_pppoed_tag_generic_error
,
1007 { "Generic-Error", "pppoed.tags.generic_error", FT_STRING
, BASE_NONE
,
1008 NULL
, 0x0, NULL
, HFILL
1013 static gint
*ett
[] = {
1016 &ett_pppoed_tag_vspec_dslf_access_loop_encaps
1019 module_t
*pppoed_module
;
1021 /* Register protocol and fields */
1022 proto_pppoed
= proto_register_protocol("PPP-over-Ethernet Discovery",
1023 "PPPoED", "pppoed");
1024 proto_register_subtree_array(ett
, array_length(ett
));
1025 proto_register_field_array(proto_pppoed
, hf
, array_length(hf
));
1027 /* Preference setting */
1028 pppoed_module
= prefs_register_protocol(proto_pppoed
, NULL
);
1029 prefs_register_bool_preference(pppoed_module
, "show_tags_and_lengths",
1030 "Show tag values and lengths",
1031 "Show values of tags and lengths of data fields",
1032 &global_pppoe_show_tags_and_lengths
);
1035 void proto_reg_handoff_pppoed(void)
1037 dissector_handle_t pppoed_handle
;
1039 pppoed_handle
= create_dissector_handle(dissect_pppoed
, proto_pppoed
);
1040 dissector_add_uint("ethertype", ETHERTYPE_PPPOED
, pppoed_handle
);
1044 /* Session protocol, i.e. PPP session established */
1045 static void dissect_pppoes(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1048 guint16 reported_payload_length
;
1049 guint16 poe_tag_length
;
1050 gint actual_payload_length
;
1051 gint length
, reported_length
;
1052 gint credit_offset
= 0, tagstart
= 0;
1055 proto_tree
*pppoe_tree
;
1056 proto_item
*ti
= NULL
;
1059 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "PPPoES");
1060 col_clear(pinfo
->cinfo
, COL_INFO
);
1062 /* Start Decoding Here. */
1063 pppoe_code
= tvb_get_guint8(tvb
, 1);
1065 col_set_str(pinfo
->cinfo
, COL_INFO
,
1066 val_to_str_const(pppoe_code
, code_vals
, "Unknown"));
1068 reported_payload_length
= tvb_get_ntohs(tvb
, 4);
1069 actual_payload_length
= tvb_reported_length_remaining(tvb
, 6);
1073 ti
= proto_tree_add_item(tree
, proto_pppoes
, tvb
, 0, 6, ENC_NA
);
1074 pppoe_tree
= proto_item_add_subtree(ti
, ett_pppoe
);
1076 proto_tree_add_item(pppoe_tree
, hf_pppoe_version
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
1077 proto_tree_add_item(pppoe_tree
, hf_pppoe_type
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
1078 proto_tree_add_item(pppoe_tree
, hf_pppoe_code
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
1079 proto_tree_add_item(pppoe_tree
, hf_pppoe_session_id
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
1080 ti
= proto_tree_add_item(pppoe_tree
, hf_pppoe_payload_length
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
1083 if (PPPOE_TAG_CREDITS
== tvb_get_ntohs(tvb
, 6))
1086 poe_tag_length
= tvb_get_ntohs(tvb
, tagstart
+ 2);
1088 /* Create tags subtree */
1089 ti
= proto_tree_add_item(pppoe_tree
, hf_pppoes_tags
, tvb
, tagstart
, 8, ENC_NA
);
1090 pppoe_tree
= proto_item_add_subtree(ti
, ett_pppoes_tags
);
1093 if (poe_tag_length
== 4)
1095 proto_tree_add_item(pppoe_tree
, hf_pppoes_tag_credits_fcn
, tvb
,
1096 tagstart
+4, 2, ENC_BIG_ENDIAN
);
1097 proto_tree_add_item(pppoe_tree
, hf_pppoes_tag_credits_bcn
, tvb
,
1098 tagstart
+6, 2, ENC_BIG_ENDIAN
);
1100 proto_tree_add_item(pppoe_tree
, hf_pppoed_tag_credits
, tvb
,
1101 tagstart
+4, poe_tag_length
, ENC_NA
);
1109 * The only reason why the payload length from the header
1110 * should differ from the remaining data in the packet
1111 * would be if the total packet length, including Ethernet
1112 * CRC, were < 64 bytes, so that padding was required.
1114 * That means that you have 14 bytes of Ethernet header,
1115 * 4 bytes of FCS, and fewer than 46 bytes of PPPoE packet.
1117 * If that's not the case, we report a difference between
1118 * the payload length in the packet, and the amount of
1119 * data following the PPPoE header, as an error.
1121 if (tvb_reported_length(tvb
) > 46) {
1123 * Be forgiving about a possible trailing FCS.
1125 * XXX - this dissector currently doesn't know
1126 * whether any extra data past the end of the PPP
1127 * payload is an FCS or not.
1129 * If we know that we have an FCS, or that we don't
1130 * have an FCS, we should have been handed a tvbuff
1131 * without the FCS, and we should just do the strict
1134 * If we don't know whether we have an FCS, then:
1136 * if this isn't over Ethernet - the "E" in "PPPoE"
1137 * nonwithstanding, it can also run on top of 802.11,
1138 * for example - there's no trailer, so any data
1139 * past the payload length is either an FCS or
1142 * if this is over Ethernet, there shouldn't be
1143 * a trailer, as the packet is long enough not to
1144 * require a trailer, as per the above;
1146 * so perhaps we should assume that if we have exactly
1147 * 4 bytes of extra information, it's an FCS, otherwise
1150 * Perhaps we need to have a routine to call to
1151 * do all the length checking, etc., and call it
1152 * from here and from other dissectors where the
1153 * protocol has a length field, or have a way to
1154 * tell the dissector that called us which field
1155 * has the length field and have *that* dissector
1156 * do the length checking and add the expert info
1157 * to the length field, *after* it does all the
1161 /* retrieve the control protocol code if it's there */
1162 cp_code
= tvb_get_ntohs(tvb
, 6);
1164 * The session payload length expressly does not include pad bytes
1165 * when LCP or IPCP are present, so avoid the spurious error message
1167 if ((cp_code
!= PPP_LCP
) && (cp_code
!= PPP_IPCP
) &&
1168 (reported_payload_length
!= actual_payload_length
) &&
1169 ((reported_payload_length
+ 4) != actual_payload_length
)) {
1170 proto_item_append_text(ti
, " [incorrect, should be %u]",
1171 actual_payload_length
);
1172 expert_add_info_format(pinfo
, ti
, &ei_pppoe_payload_length
, "Possible bad payload length %u != %u", reported_payload_length
, actual_payload_length
);
1177 * Construct a tvbuff containing the PPP packet.
1179 length
= tvb_length_remaining(tvb
, 6);
1180 reported_length
= tvb_reported_length_remaining(tvb
, 6);
1181 DISSECTOR_ASSERT(length
>= 0);
1182 DISSECTOR_ASSERT(reported_length
>= 0);
1183 if (length
> reported_length
)
1184 length
= reported_length
;
1185 if ((guint
)length
> reported_payload_length
)
1186 length
= reported_payload_length
;
1187 if ((guint
)reported_length
> reported_payload_length
)
1188 reported_length
= reported_payload_length
;
1189 next_tvb
= tvb_new_subset(tvb
,(6 + credit_offset
),
1190 (length
- credit_offset
),
1191 (reported_length
- credit_offset
));
1192 call_dissector(ppp_handle
,next_tvb
,pinfo
,tree
);
1195 void proto_register_pppoes(void)
1198 static hf_register_info hf
[] =
1201 { "PPPoE Tags", "pppoes.tags", FT_NONE
, BASE_NONE
,
1202 NULL
, 0x0, NULL
, HFILL
1207 { "Tag", "pppoes.tag", FT_UINT16
, BASE_HEX
,
1208 VALS(tag_vals
), 0x0, NULL
, HFILL
1213 { &hf_pppoes_tag_credits
,
1214 { "Credits", "pppoes.tags.credits", FT_BYTES
, BASE_NONE
,
1215 NULL
, 0x0, NULL
, HFILL
1219 { &hf_pppoes_tag_credits_fcn
,
1220 { "FCN", "pppoes.tags.credits.fcn", FT_UINT16
, BASE_DEC
,
1221 NULL
, 0x0, NULL
, HFILL
1224 { &hf_pppoes_tag_credits_bcn
,
1225 { "BCN", "pppoes.tags.credits.bcn", FT_UINT16
, BASE_DEC
,
1226 NULL
, 0x0, NULL
, HFILL
1231 static gint
*ett
[] = {
1236 /* Register protocol */
1237 proto_pppoes
= proto_register_protocol("PPP-over-Ethernet Session", "PPPoES", "pppoes");
1239 proto_register_subtree_array(ett
, array_length(ett
));
1240 proto_register_field_array(proto_pppoes
, hf
, array_length(hf
));
1243 void proto_register_pppoe(void)
1245 static hf_register_info hf
[] =
1247 /* These fields common to discovery and session protocols */
1248 { &hf_pppoe_version
,
1249 { "Version", "pppoe.version", FT_UINT8
, BASE_DEC
,
1250 NULL
, 0xf0, NULL
, HFILL
1254 { "Type", "pppoe.type", FT_UINT8
, BASE_DEC
,
1255 NULL
, 0x0f, NULL
, HFILL
1259 { "Code", "pppoe.code", FT_UINT8
, BASE_HEX
,
1260 VALS(code_vals
), 0x0, NULL
, HFILL
1263 { &hf_pppoe_session_id
,
1264 { "Session ID", "pppoe.session_id", FT_UINT16
, BASE_HEX
,
1265 NULL
, 0x0, NULL
, HFILL
1268 { &hf_pppoe_payload_length
,
1269 { "Payload Length", "pppoe.payload_length", FT_UINT16
, BASE_DEC
,
1270 NULL
, 0x0, NULL
, HFILL
1275 static gint
*ett
[] = {
1279 static ei_register_info ei
[] = {
1280 { &ei_pppoe_tag_length
, { "pppoed.tag_length.invalid", PI_MALFORMED
, PI_WARN
, "Wrong length", EXPFILL
}},
1281 { &ei_pppoe_payload_length
, { "pppoe.payload_length.bad", PI_MALFORMED
, PI_WARN
, "Possible bad payload length", EXPFILL
}},
1284 expert_module_t
* expert_pppoe
;
1286 /* Register protocol */
1287 proto_pppoe
= proto_register_protocol("PPP-over-Ethernet", "PPPoE", "pppoe");
1289 proto_register_subtree_array(ett
, array_length(ett
));
1290 proto_register_field_array(proto_pppoe
, hf
, array_length(hf
));
1291 expert_pppoe
= expert_register_protocol(proto_pppoe
);
1292 expert_register_field_array(expert_pppoe
, ei
, array_length(ei
));
1296 void proto_reg_handoff_pppoes(void)
1298 dissector_handle_t pppoes_handle
=
1299 create_dissector_handle(dissect_pppoes
, proto_pppoes
);
1300 dissector_add_uint("ethertype", ETHERTYPE_PPPOES
, pppoes_handle
);
1301 dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP_ETHER
, pppoes_handle
);
1303 /* Get a handle for the PPP dissector */
1304 ppp_handle
= find_dissector("ppp");