/src/wireshark/epan/dissectors/packet-pppoe.c
Line | Count | Source |
1 | | /* packet-pppoe.c |
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) |
4 | | * |
5 | | * Wireshark - Network traffic analyzer |
6 | | * By Gerald Combs <gerald@wireshark.org> |
7 | | * Copyright 1998 Gerald Combs |
8 | | * |
9 | | * SPDX-License-Identifier: GPL-2.0-or-later |
10 | | */ |
11 | | |
12 | | #include "config.h" |
13 | | |
14 | | #include <epan/packet.h> |
15 | | #include <epan/etypes.h> |
16 | | #include <epan/prefs.h> |
17 | | #include <epan/expert.h> |
18 | | #include <wiretap/wtap.h> |
19 | | #include "packet-ppp.h" |
20 | | |
21 | | |
22 | | void proto_register_pppoed(void); |
23 | | void proto_reg_handoff_pppoed(void); |
24 | | void proto_register_pppoes(void); |
25 | | void proto_register_pppoe(void); |
26 | | void proto_reg_handoff_pppoes(void); |
27 | | |
28 | | static dissector_handle_t pppoed_handle; |
29 | | static dissector_handle_t pppoes_handle; |
30 | | |
31 | | static int proto_pppoed; |
32 | | |
33 | | /* Common to session and discovery protocols */ |
34 | | static int hf_pppoe_version; |
35 | | static int hf_pppoe_type; |
36 | | static int hf_pppoe_code; |
37 | | static int hf_pppoe_session_id; |
38 | | static int hf_pppoe_payload_length; |
39 | | |
40 | | /* Discovery protocol fields */ |
41 | | static int hf_pppoed_tags; |
42 | | static int hf_pppoed_tag; |
43 | | static int hf_pppoed_tag_length; |
44 | | static int hf_pppoed_tag_length_8; |
45 | | static int hf_pppoed_tag_unknown_data; |
46 | | static int hf_pppoed_tag_service_name; |
47 | | static int hf_pppoed_tag_ac_name; |
48 | | static int hf_pppoed_tag_host_uniq; |
49 | | static int hf_pppoed_tag_ac_cookie; |
50 | | static int hf_pppoed_tag_vendor_id; |
51 | | static int hf_pppoed_tag_vendor_unspecified; |
52 | | static int hf_pppoed_tag_vspec_tags; |
53 | | static int hf_pppoed_tag_vspec_tag; |
54 | | static int hf_pppoed_tag_vspec_circuit_id; |
55 | | static int hf_pppoed_tag_vspec_remote_id; |
56 | | static int hf_pppoed_tag_vspec_act_data_rate_up; |
57 | | static int hf_pppoed_tag_vspec_act_data_rate_down; |
58 | | static int hf_pppoed_tag_vspec_min_data_rate_up; |
59 | | static int hf_pppoed_tag_vspec_min_data_rate_down; |
60 | | static int hf_pppoed_tag_vspec_attainable_data_rate_up; |
61 | | static int hf_pppoed_tag_vspec_attainable_data_rate_down; |
62 | | static int hf_pppoed_tag_vspec_max_data_rate_up; |
63 | | static int hf_pppoed_tag_vspec_max_data_rate_down; |
64 | | static int hf_pppoed_tag_vspec_min_data_rate_up_lp; |
65 | | static int hf_pppoed_tag_vspec_min_data_rate_down_lp; |
66 | | static int hf_pppoed_tag_vspec_max_int_delay_up; |
67 | | static int hf_pppoed_tag_vspec_act_int_delay_up; |
68 | | static int hf_pppoed_tag_vspec_max_int_delay_down; |
69 | | static int hf_pppoed_tag_vspec_act_int_delay_down; |
70 | | static int hf_pppoed_tag_vspec_access_loop_encapsulation; |
71 | | static int hf_pppoed_tag_vspec_access_loop_encap_data_link; |
72 | | static int hf_pppoed_tag_vspec_access_loop_encap_encap_1; |
73 | | static int hf_pppoed_tag_vspec_access_loop_encap_encap_2; |
74 | | static int hf_pppoed_tag_credits; |
75 | | static int hf_pppoed_tag_credits_fcn; |
76 | | static int hf_pppoed_tag_credits_bcn; |
77 | | static int hf_pppoed_tag_metrics; |
78 | | static int hf_pppoed_tag_metrics_r; |
79 | | static int hf_pppoed_tag_metrics_rlq; |
80 | | static int hf_pppoed_tag_metrics_resource; |
81 | | static int hf_pppoed_tag_metrics_latency; |
82 | | static int hf_pppoed_tag_metrics_curr_drate; |
83 | | static int hf_pppoed_tag_metrics_max_drate; |
84 | | static int hf_pppoed_tag_mdr_units; |
85 | | static int hf_pppoed_tag_cdr_units; |
86 | | static int hf_pppoed_tag_seq_num; |
87 | | static int hf_pppoed_tag_cred_scale; |
88 | | static int hf_pppoed_tag_relay_session_id; |
89 | | static int hf_pppoed_tag_hurl; |
90 | | static int hf_pppoed_tag_motm; |
91 | | static int hf_pppoed_tag_max_payload; |
92 | | static int hf_pppoed_tag_ip_route_add; |
93 | | static int hf_pppoed_tag_service_name_error; |
94 | | static int hf_pppoed_tag_ac_system_error; |
95 | | static int hf_pppoed_tag_generic_error; |
96 | | |
97 | | /* Session protocol fields */ |
98 | | static int hf_pppoes_tags; |
99 | | /* static int hf_pppoes_tag; */ |
100 | | /* static int hf_pppoes_tag_credits; */ |
101 | | static int hf_pppoes_tag_credits_fcn; |
102 | | static int hf_pppoes_tag_credits_bcn; |
103 | | |
104 | | /* Session protocol fields */ |
105 | | |
106 | | static int ett_pppoed; |
107 | | static int ett_pppoed_tags; |
108 | | static int ett_pppoed_tag_vspec_dslf_access_loop_encaps; |
109 | | |
110 | | static int proto_pppoes; |
111 | | |
112 | | static int ett_pppoes; |
113 | | static int ett_pppoes_tags; |
114 | | |
115 | | static expert_field ei_pppoe_payload_length; |
116 | | static expert_field ei_pppoe_tag_length; |
117 | | |
118 | | /* PPPoE parent fields */ |
119 | | |
120 | | static int proto_pppoe; |
121 | | static int ett_pppoe; |
122 | | |
123 | | |
124 | | /* Handle for calling for ppp dissector to handle session data */ |
125 | | static dissector_handle_t ppp_handle; |
126 | | |
127 | | |
128 | | /* Preference for showing discovery tag values and lengths */ |
129 | | static bool global_pppoe_show_tags_and_lengths; |
130 | | |
131 | | |
132 | | #define PPPOE_CODE_SESSION 0x00 |
133 | | #define PPPOE_CODE_PADO 0x07 |
134 | | #define PPPOE_CODE_PADI 0x09 |
135 | | #define PPPOE_CODE_PADG 0x0a |
136 | | #define PPPOE_CODE_PADC 0x0b |
137 | | #define PPPOE_CODE_PADQ 0x0c |
138 | | #define PPPOE_CODE_PADR 0x19 |
139 | | #define PPPOE_CODE_PADS 0x65 |
140 | | #define PPPOE_CODE_PADT 0xa7 |
141 | | #define PPPOE_CODE_PADM 0xd3 |
142 | | #define PPPOE_CODE_PADN 0xd4 |
143 | | |
144 | 8 | #define PPPOE_TAG_EOL 0x0000 |
145 | 0 | #define PPPOE_TAG_SVC_NAME 0x0101 |
146 | 0 | #define PPPOE_TAG_AC_NAME 0x0102 |
147 | 0 | #define PPPOE_TAG_HOST_UNIQ 0x0103 |
148 | 0 | #define PPPOE_TAG_AC_COOKIE 0x0104 |
149 | 0 | #define PPPOE_TAG_VENDOR 0x0105 |
150 | 42 | #define PPPOE_TAG_CREDITS 0x0106 |
151 | 0 | #define PPPOE_TAG_METRICS 0x0107 |
152 | 0 | #define PPPOE_TAG_SEQ_NUM 0x0108 |
153 | 0 | #define PPPOE_TAG_CRED_SCALE 0x0109 |
154 | 0 | #define PPPOE_TAG_RELAY_ID 0x0110 |
155 | 0 | #define PPPOE_TAG_HURL 0x0111 |
156 | 0 | #define PPPOE_TAG_MOTM 0x0112 |
157 | 0 | #define PPPOE_TAG_MAX_PAYLD 0x0120 |
158 | 0 | #define PPPOE_TAG_IP_RT_ADD 0x0121 |
159 | 0 | #define PPPOE_TAG_SVC_ERR 0x0201 |
160 | 0 | #define PPPOE_TAG_AC_ERR 0x0202 |
161 | 0 | #define PPPOE_TAG_GENERIC_ERR 0x0203 |
162 | | |
163 | 0 | #define PPPOE_VENDOR_ID_DSLF 3561 |
164 | | |
165 | | #define PPPOE_TAG_VSPEC_DSLF_CIRCUIT_ID 0x01 |
166 | | #define PPPOE_TAG_VSPEC_DSLF_REMOTE_ID 0x02 |
167 | | #define PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_UP 0x81 |
168 | | #define PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_DOWN 0x82 |
169 | | #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP 0x83 |
170 | | #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN 0x84 |
171 | | #define PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_UP 0x85 |
172 | | #define PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_DOWN 0x86 |
173 | | #define PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_UP 0x87 |
174 | | #define PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_DOWN 0x88 |
175 | | #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP_LP 0x89 |
176 | | #define PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN_LP 0x8a |
177 | | #define PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_UP 0x8b |
178 | | #define PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_UP 0x8c |
179 | | #define PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_DOWN 0x8d |
180 | | #define PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_DOWN 0x8e |
181 | 0 | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAPSULATION 0x90 |
182 | | |
183 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ATM 0x00 |
184 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ETH 0x01 |
185 | | |
186 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_NA 0x00 |
187 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_UNTAGGED_ETH 0x01 |
188 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_SINGLE_TAGGED_ETH 0x02 |
189 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_DOUBLE_TAGGED_ETH 0x03 |
190 | | |
191 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_NA 0x00 |
192 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_LLC 0x01 |
193 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_NULL 0x02 |
194 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_LLC 0x03 |
195 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_NULL 0x04 |
196 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITH_FCS 0x05 |
197 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITHOUT_FCS 0x06 |
198 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITH_FCS 0x07 |
199 | | #define PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITHOUT_FCS 0x08 |
200 | | |
201 | 14 | #define PPPOE_CDR_MASK 0x0006 |
202 | 14 | #define PPPOE_MDR_MASK 0x0018 |
203 | 14 | #define PPPOE_RCV_ONLY_MASK 0x0001 |
204 | | |
205 | 0 | #define PPPOE_SCALE_KBPS 0x00 |
206 | 0 | #define PPPOE_SCALE_MBPS 0x01 |
207 | 0 | #define PPPOE_SCALE_GBPS 0x02 |
208 | 0 | #define PPPOE_SCALE_TBPS 0x03 |
209 | | |
210 | | |
211 | | static const value_string code_vals[] = { |
212 | | {PPPOE_CODE_SESSION, "Session Data" }, |
213 | | {PPPOE_CODE_PADO, "Active Discovery Offer (PADO)" }, |
214 | | {PPPOE_CODE_PADI, "Active Discovery Initiation (PADI)" }, |
215 | | {PPPOE_CODE_PADG, "Active Discovery Session-Grant (PADG)" }, |
216 | | {PPPOE_CODE_PADC, "Active Discovery Session-Credit Resp.(PADC)" }, |
217 | | {PPPOE_CODE_PADQ, "Active Discovery Quality (PADQ)" }, |
218 | | {PPPOE_CODE_PADR, "Active Discovery Request (PADR)" }, |
219 | | {PPPOE_CODE_PADS, "Active Discovery Session-confirmation (PADS)"}, |
220 | | {PPPOE_CODE_PADT, "Active Discovery Terminate (PADT)" }, |
221 | | {PPPOE_CODE_PADM, "Active Discovery Message (PADM)" }, |
222 | | {PPPOE_CODE_PADN, "Active Discovery Network (PADN)" }, |
223 | | {0, NULL } |
224 | | }; |
225 | | |
226 | | |
227 | | static const value_string tag_vals[] = { |
228 | | {PPPOE_TAG_EOL, "End-Of-List" }, |
229 | | {PPPOE_TAG_SVC_NAME, "Service-Name" }, |
230 | | {PPPOE_TAG_AC_NAME, "AC-Name" }, |
231 | | {PPPOE_TAG_HOST_UNIQ, "Host-Uniq" }, |
232 | | {PPPOE_TAG_AC_COOKIE, "AC-Cookie" }, |
233 | | {PPPOE_TAG_VENDOR, "Vendor-Specific" }, |
234 | | {PPPOE_TAG_CREDITS, "Credits" }, |
235 | | {PPPOE_TAG_METRICS, "Metrics" }, |
236 | | {PPPOE_TAG_SEQ_NUM, "Sequence Number" }, |
237 | | {PPPOE_TAG_CRED_SCALE, "Credit Scale Factor"}, |
238 | | {PPPOE_TAG_RELAY_ID, "Relay-Session-Id" }, |
239 | | {PPPOE_TAG_HURL, "HURL" }, |
240 | | {PPPOE_TAG_MOTM, "MOTM" }, |
241 | | {PPPOE_TAG_MAX_PAYLD, "PPP-Max-Payload" }, |
242 | | {PPPOE_TAG_IP_RT_ADD, "IP Route Add" }, |
243 | | {PPPOE_TAG_SVC_ERR, "Service-Name-Error"}, |
244 | | {PPPOE_TAG_AC_ERR, "AC-System-Error" }, |
245 | | {PPPOE_TAG_GENERIC_ERR,"Generic-Error" }, |
246 | | {0, NULL } |
247 | | }; |
248 | | |
249 | | static const value_string vspec_tag_vals[] = { |
250 | | {PPPOE_TAG_VSPEC_DSLF_CIRCUIT_ID, "Circuit-ID" }, |
251 | | {PPPOE_TAG_VSPEC_DSLF_REMOTE_ID, "Remote-ID" }, |
252 | | {PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_UP, "Actual-Data-Rate-Up" }, |
253 | | {PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_DOWN, "Actual-Data-Rate-Down" }, |
254 | | {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP, "Min-Data-Rate-Up" }, |
255 | | {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN, "Min-Data-Rate-Down" }, |
256 | | {PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_UP, "Attainable-Data-Rate-Up" }, |
257 | | {PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_DOWN, "Attainable-Data-Rate-Down" }, |
258 | | {PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_UP, "Max-Data-Rate-Up" }, |
259 | | {PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_DOWN, "Max-Data-Rate-Down" }, |
260 | | {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP_LP, "Min-Data-Rate-Up-Low-Power" }, |
261 | | {PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN_LP, "Min-Data-Rate-Down-Low-Power" }, |
262 | | {PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_UP, "Max-Interleaving-Delay-Up" }, |
263 | | {PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_UP, "Actual-Interleaving-Delay-Up" }, |
264 | | {PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_DOWN, "Max-Interleaving-Delay-Down" }, |
265 | | {PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_DOWN, "Actual-Interleaving-Delay-Down"}, |
266 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAPSULATION, "Access-Loop-Encapsulation" }, |
267 | | {0, NULL } |
268 | | }; |
269 | | |
270 | | static const value_string vspec_tag_dslf_access_loop_encap_data_link_vals[] = { |
271 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ATM, "ATM AAL5"}, |
272 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_DATA_LINK_ETH, "Ethernet"}, |
273 | | {0, NULL } |
274 | | }; |
275 | | |
276 | | static const value_string vspec_tag_dslf_access_loop_encap_encap_1_vals[] = { |
277 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_NA, "NA" }, |
278 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_UNTAGGED_ETH, "Untagged Ethernet" }, |
279 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_SINGLE_TAGGED_ETH, "Single-tagged Ethernet"}, |
280 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_1_DOUBLE_TAGGED_ETH, "Double-tagged Ethernet"}, |
281 | | {0, NULL } |
282 | | }; |
283 | | |
284 | | static const value_string vspec_tag_dslf_access_loop_encap_encap_2_vals[] = { |
285 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_NA, "NA" }, |
286 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_LLC, "PPPoA LLC" }, |
287 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_PPPOA_NULL, "PPPoA Null" }, |
288 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_LLC, "IPoA LLC" }, |
289 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_IPOA_NULL, "IPoA Null" }, |
290 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITH_FCS, "Ethernet over AAL5 LLC w FCS" }, |
291 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_LLC_WITHOUT_FCS, "Ethernet over AAL5 LLC w/o FCS" }, |
292 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITH_FCS, "Ethernet over AAL5 Null w FCS" }, |
293 | | {PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAP_ENCAPS_2_ETH_OVER_AAL5_NULL_WITHOUT_FCS,"Ethernet over AAL5 Null w/o FCS"}, |
294 | | {0, NULL } |
295 | | }; |
296 | | |
297 | | static const value_string datarate_scale_vals[] = { |
298 | | {PPPOE_SCALE_KBPS, "kilobits per second"}, |
299 | | {PPPOE_SCALE_MBPS, "megabits per second"}, |
300 | | {PPPOE_SCALE_GBPS, "gigabits per second"}, |
301 | | {PPPOE_SCALE_TBPS, "terabits per second"}, |
302 | | {0, NULL } |
303 | | }; |
304 | | |
305 | | |
306 | 0 | #define CASE_VSPEC_DSLF_TAG_UINT(tag_name, relation, length, hf_var) case tag_name: \ |
307 | 0 | if (!(poe_tag_length relation length)) { \ |
308 | 0 | expert_add_info_format(pinfo, pppoe_tree, &ei_pppoe_tag_length, \ |
309 | 0 | "%s: Wrong length: %u (expected %s %d)", \ |
310 | 0 | val_to_str_const(poe_tag, vspec_tag_vals, "Unknown"), poe_tag_length, #relation, length); \ |
311 | 0 | } else { \ |
312 | 0 | proto_tree_add_item(pppoe_tree, hf_var, tvb, \ |
313 | 0 | tagstart+2, poe_tag_length, ENC_BIG_ENDIAN); \ |
314 | 0 | } \ |
315 | 0 | break; |
316 | | |
317 | 0 | #define CASE_VSPEC_DSLF_TAG_STRING(tag_name, relation, length, hf_var) case tag_name: \ |
318 | 0 | if (!(poe_tag_length relation length)) { \ |
319 | 0 | expert_add_info_format(pinfo, pppoe_tree, &ei_pppoe_tag_length, \ |
320 | 0 | "%s: Wrong length: %u (expected %s %d)", \ |
321 | 0 | val_to_str_const(poe_tag, vspec_tag_vals, "Unknown"), poe_tag_length, #relation, length); \ |
322 | 0 | } else { \ |
323 | 0 | proto_tree_add_item(pppoe_tree, hf_var, tvb, \ |
324 | 0 | tagstart+2, poe_tag_length, ENC_ASCII|ENC_NA); \ |
325 | 0 | } \ |
326 | 0 | break; |
327 | | |
328 | | /* Dissect Vendor-Specific Tags introduced by the DSLF */ |
329 | | static void |
330 | | dissect_pppoe_subtags_dslf(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, |
331 | | int payload_length) |
332 | 0 | { |
333 | 0 | uint8_t poe_tag; |
334 | 0 | uint8_t poe_tag_length; |
335 | 0 | int tagstart; |
336 | |
|
337 | 0 | proto_tree *pppoe_tree, *ti, *encaps_tree; |
338 | | |
339 | | /* Start Decoding Here. */ |
340 | | /* Create tags subtree */ |
341 | 0 | ti = proto_tree_add_item(tree, hf_pppoed_tag_vspec_tags, tvb, offset, payload_length, ENC_NA); |
342 | 0 | pppoe_tree = proto_item_add_subtree(ti, ett_pppoed_tags); |
343 | |
|
344 | 0 | tagstart = offset; |
345 | | |
346 | | /* Loop until all data seen or End-Of-List tag found */ |
347 | 0 | while (tagstart <= offset + payload_length-2) |
348 | 0 | { |
349 | 0 | poe_tag = tvb_get_uint8(tvb, tagstart); |
350 | 0 | poe_tag_length = tvb_get_uint8(tvb, tagstart + 1); |
351 | | |
352 | | /* Tag value and data length */ |
353 | 0 | if (global_pppoe_show_tags_and_lengths) |
354 | 0 | { |
355 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_vspec_tag, tvb, tagstart, 1, ENC_BIG_ENDIAN); |
356 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_length_8, tvb, tagstart+1, 1, ENC_BIG_ENDIAN); |
357 | 0 | } |
358 | | |
359 | | /* Show tag data */ |
360 | 0 | switch (poe_tag) |
361 | 0 | { |
362 | 0 | CASE_VSPEC_DSLF_TAG_STRING(PPPOE_TAG_VSPEC_DSLF_CIRCUIT_ID, <=, 63, |
363 | 0 | hf_pppoed_tag_vspec_circuit_id) |
364 | 0 | CASE_VSPEC_DSLF_TAG_STRING(PPPOE_TAG_VSPEC_DSLF_REMOTE_ID, <=, 63, |
365 | 0 | hf_pppoed_tag_vspec_remote_id) |
366 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_UP, ==, 4, |
367 | 0 | hf_pppoed_tag_vspec_act_data_rate_up) |
368 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_DATA_RATE_DOWN, ==, 4, |
369 | 0 | hf_pppoed_tag_vspec_act_data_rate_down) |
370 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP, ==, 4, |
371 | 0 | hf_pppoed_tag_vspec_min_data_rate_up) |
372 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN, ==, 4, |
373 | 0 | hf_pppoed_tag_vspec_min_data_rate_down) |
374 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_UP, ==, 4, |
375 | 0 | hf_pppoed_tag_vspec_attainable_data_rate_up) |
376 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ATTAINABLE_DATA_RATE_DOWN, ==, 4, |
377 | 0 | hf_pppoed_tag_vspec_attainable_data_rate_down) |
378 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_UP, ==, 4, |
379 | 0 | hf_pppoed_tag_vspec_max_data_rate_up) |
380 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_DATA_RATE_DOWN, ==, 4, |
381 | 0 | hf_pppoed_tag_vspec_max_data_rate_down) |
382 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_UP_LP, ==, 4, |
383 | 0 | hf_pppoed_tag_vspec_min_data_rate_up_lp) |
384 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MIN_DATA_RATE_DOWN_LP, ==, 4, |
385 | 0 | hf_pppoed_tag_vspec_min_data_rate_down_lp) |
386 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_UP, ==, 4, |
387 | 0 | hf_pppoed_tag_vspec_max_int_delay_up) |
388 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_UP, ==, 4, |
389 | 0 | hf_pppoed_tag_vspec_act_int_delay_up) |
390 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_MAX_INT_DELAY_DOWN, ==, 4, |
391 | 0 | hf_pppoed_tag_vspec_max_int_delay_down) |
392 | 0 | CASE_VSPEC_DSLF_TAG_UINT(PPPOE_TAG_VSPEC_DSLF_ACT_INT_DELAY_DOWN, ==, 4, |
393 | 0 | hf_pppoed_tag_vspec_act_int_delay_down) |
394 | 0 | case PPPOE_TAG_VSPEC_DSLF_ACCESS_LOOP_ENCAPSULATION: |
395 | 0 | ti = proto_tree_add_item(pppoe_tree, hf_pppoed_tag_vspec_access_loop_encapsulation, tvb, |
396 | 0 | tagstart+2, 3, ENC_NA); |
397 | 0 | if (poe_tag_length != 3) { |
398 | 0 | 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); |
399 | 0 | } |
400 | 0 | encaps_tree = proto_item_add_subtree(ti, ett_pppoed_tag_vspec_dslf_access_loop_encaps); |
401 | 0 | proto_tree_add_item(encaps_tree, hf_pppoed_tag_vspec_access_loop_encap_data_link, |
402 | 0 | tvb, tagstart+2, 1, ENC_BIG_ENDIAN); |
403 | 0 | proto_tree_add_item(encaps_tree, hf_pppoed_tag_vspec_access_loop_encap_encap_1, |
404 | 0 | tvb, tagstart+3, 1, ENC_BIG_ENDIAN); |
405 | 0 | proto_tree_add_item(encaps_tree, hf_pppoed_tag_vspec_access_loop_encap_encap_2, |
406 | 0 | tvb, tagstart+4, 1, ENC_BIG_ENDIAN); |
407 | |
|
408 | 0 | break; |
409 | 0 | default: |
410 | 0 | if (poe_tag_length > 0 ) |
411 | 0 | { |
412 | | /* Presumably unknown tag; |
413 | | show tag value if we didn't do it above */ |
414 | 0 | if (!global_pppoe_show_tags_and_lengths) |
415 | 0 | { |
416 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag, tvb, tagstart, 1, ENC_BIG_ENDIAN); |
417 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_length_8, tvb, tagstart+1, 1, ENC_BIG_ENDIAN); |
418 | 0 | } |
419 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_unknown_data, tvb, |
420 | 0 | tagstart+2, poe_tag_length, ENC_NA); |
421 | 0 | } |
422 | 0 | } |
423 | | |
424 | 0 | tagstart += (2 + poe_tag_length); |
425 | 0 | } |
426 | 0 | } |
427 | | |
428 | | |
429 | | /* Dissect discovery protocol tags */ |
430 | | static void |
431 | | dissect_pppoe_tags(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree, |
432 | | int payload_length) |
433 | 9 | { |
434 | 9 | uint16_t poe_tag; |
435 | 9 | uint16_t poe_tag_length; |
436 | 9 | int tagstart; |
437 | 9 | uint16_t poe_rsv = 0; |
438 | | |
439 | 9 | proto_tree *pppoe_tree; |
440 | 9 | proto_item *ti; |
441 | 9 | proto_item *pppoe_tree_tag_length_item = NULL; |
442 | | |
443 | | /* Start Decoding Here. */ |
444 | | /* Create tags subtree */ |
445 | 9 | ti = proto_tree_add_item(tree, hf_pppoed_tags, tvb, offset, payload_length-6, ENC_NA); |
446 | 9 | pppoe_tree = proto_item_add_subtree(ti, ett_pppoed_tags); |
447 | | |
448 | 9 | tagstart = offset; |
449 | | |
450 | | /* Loop until all data seen or End-Of-List tag found */ |
451 | 9 | while (tagstart <= payload_length-2) |
452 | 9 | { |
453 | 9 | poe_tag = tvb_get_ntohs(tvb, tagstart); |
454 | 9 | poe_tag_length = tvb_get_ntohs(tvb, tagstart + 2); |
455 | | |
456 | | /* Tag value and data length */ |
457 | 9 | if (global_pppoe_show_tags_and_lengths) |
458 | 0 | { |
459 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag, tvb, tagstart, 2, ENC_BIG_ENDIAN); |
460 | 0 | pppoe_tree_tag_length_item = |
461 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_length, tvb, tagstart+2, 2, ENC_BIG_ENDIAN); |
462 | 0 | } |
463 | | |
464 | | /* Show tag data */ |
465 | 9 | switch (poe_tag) |
466 | 9 | { |
467 | 0 | case PPPOE_TAG_SVC_NAME: |
468 | 0 | if (poe_tag_length > 0) |
469 | 0 | { |
470 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_service_name, tvb, |
471 | 0 | tagstart+4, poe_tag_length, ENC_ASCII); |
472 | 0 | } |
473 | 0 | break; |
474 | 0 | case PPPOE_TAG_AC_NAME: |
475 | 0 | { |
476 | 0 | const uint8_t* str; |
477 | 0 | proto_tree_add_item_ret_string(pppoe_tree, hf_pppoed_tag_ac_name, tvb, |
478 | 0 | tagstart+4, poe_tag_length, ENC_ASCII|ENC_NA, pinfo->pool, &str); |
479 | | /* Show AC-Name in info column */ |
480 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " AC-Name='%s'", str); |
481 | 0 | } |
482 | 0 | break; |
483 | 0 | case PPPOE_TAG_HOST_UNIQ: |
484 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_host_uniq, tvb, |
485 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
486 | 0 | break; |
487 | 0 | case PPPOE_TAG_AC_COOKIE: |
488 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_ac_cookie, tvb, |
489 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
490 | 0 | break; |
491 | 0 | case PPPOE_TAG_VENDOR: |
492 | 0 | if (poe_tag_length >= 4) |
493 | 0 | { |
494 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_vendor_id, tvb, |
495 | 0 | tagstart+4, 4, ENC_BIG_ENDIAN); |
496 | 0 | } |
497 | 0 | if (poe_tag_length > 4) |
498 | 0 | { |
499 | 0 | uint32_t vendor_id = tvb_get_ntohl(tvb, tagstart+4); |
500 | 0 | switch (vendor_id) |
501 | 0 | { |
502 | 0 | case PPPOE_VENDOR_ID_DSLF: |
503 | 0 | dissect_pppoe_subtags_dslf(tvb,pinfo,tagstart+4+4,pppoe_tree,poe_tag_length-4); |
504 | 0 | break; |
505 | 0 | default: |
506 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_vendor_unspecified, tvb, |
507 | 0 | tagstart+4+4, poe_tag_length-4, ENC_NA); |
508 | |
|
509 | 0 | } |
510 | 0 | } |
511 | 0 | break; |
512 | 0 | case PPPOE_TAG_CREDITS: |
513 | 0 | if (poe_tag_length == 4) |
514 | 0 | { |
515 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_credits_fcn, tvb, |
516 | 0 | tagstart+4, 2, ENC_BIG_ENDIAN); |
517 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_credits_bcn, tvb, |
518 | 0 | tagstart+6, 2, ENC_BIG_ENDIAN); |
519 | 0 | } else { |
520 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_credits, tvb, |
521 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
522 | 0 | } |
523 | 0 | break; |
524 | 0 | case PPPOE_TAG_METRICS: |
525 | 0 | if (poe_tag_length == 10) |
526 | 0 | { |
527 | 0 | poe_rsv = tvb_get_ntohs(tvb, tagstart+4); |
528 | |
|
529 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_mdr_units, tvb, |
530 | 0 | tagstart+4, 2, ENC_BIG_ENDIAN); |
531 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_cdr_units, tvb, |
532 | 0 | tagstart+4, 2, ENC_BIG_ENDIAN); |
533 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics_r, tvb, |
534 | 0 | tagstart+4, 2, ENC_BIG_ENDIAN); |
535 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics_rlq, tvb, |
536 | 0 | tagstart+6, 1, ENC_BIG_ENDIAN); |
537 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics_resource, tvb, |
538 | 0 | tagstart+7, 1, ENC_BIG_ENDIAN); |
539 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics_latency, tvb, |
540 | 0 | tagstart+8, 2, ENC_BIG_ENDIAN); |
541 | | |
542 | | /* CDR */ |
543 | 0 | ti = proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics_curr_drate, tvb, |
544 | 0 | tagstart+10, 2, ENC_BIG_ENDIAN); |
545 | |
|
546 | 0 | switch ((poe_rsv & PPPOE_CDR_MASK) >> 1) |
547 | 0 | { |
548 | 0 | case (PPPOE_SCALE_KBPS): |
549 | 0 | proto_item_append_text(ti, " kbps"); |
550 | 0 | break; |
551 | 0 | case (PPPOE_SCALE_MBPS): |
552 | 0 | proto_item_append_text(ti, " mbps"); |
553 | 0 | break; |
554 | 0 | case (PPPOE_SCALE_GBPS): |
555 | 0 | proto_item_append_text(ti, " gbps"); |
556 | 0 | break; |
557 | 0 | case (PPPOE_SCALE_TBPS): |
558 | 0 | proto_item_append_text(ti, " tbps"); |
559 | 0 | break; |
560 | 0 | } |
561 | | |
562 | | /* MDR */ |
563 | 0 | ti = proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics_max_drate, tvb, |
564 | 0 | tagstart+12, 2, ENC_BIG_ENDIAN); |
565 | |
|
566 | 0 | switch ((poe_rsv & PPPOE_MDR_MASK) >> 3) |
567 | 0 | { |
568 | 0 | case (PPPOE_SCALE_KBPS): |
569 | 0 | proto_item_append_text(ti, " kbps"); |
570 | 0 | break; |
571 | 0 | case (PPPOE_SCALE_MBPS): |
572 | 0 | proto_item_append_text(ti, " mbps"); |
573 | 0 | break; |
574 | 0 | case (PPPOE_SCALE_GBPS): |
575 | 0 | proto_item_append_text(ti, " gbps"); |
576 | 0 | break; |
577 | 0 | case (PPPOE_SCALE_TBPS): |
578 | 0 | proto_item_append_text(ti, " tbps"); |
579 | 0 | break; |
580 | 0 | } |
581 | |
|
582 | 0 | } else { |
583 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_metrics, tvb, |
584 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
585 | 0 | } |
586 | 0 | break; |
587 | 0 | case PPPOE_TAG_SEQ_NUM: |
588 | 0 | if (poe_tag_length == 2) { |
589 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_seq_num, tvb, |
590 | 0 | tagstart+4, poe_tag_length, ENC_BIG_ENDIAN); |
591 | 0 | } else { |
592 | 0 | if (global_pppoe_show_tags_and_lengths) { |
593 | 0 | proto_item_append_text(pppoe_tree_tag_length_item, " [Wrong: should be 2]"); |
594 | 0 | } |
595 | |
|
596 | 0 | proto_tree_add_expert_format(pppoe_tree, pinfo, &ei_pppoe_tag_length, tvb, tagstart+4, poe_tag_length, |
597 | 0 | "Sequence Number tag: Wrong length: %u (expected 2)", poe_tag_length); |
598 | 0 | } |
599 | 0 | break; |
600 | 0 | case PPPOE_TAG_CRED_SCALE: |
601 | 0 | if (poe_tag_length == 2) { |
602 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_cred_scale, tvb, |
603 | 0 | tagstart+4, poe_tag_length, ENC_BIG_ENDIAN); |
604 | 0 | } else { |
605 | 0 | if (global_pppoe_show_tags_and_lengths) { |
606 | 0 | proto_item_append_text(pppoe_tree_tag_length_item, " [Wrong: should be 2]"); |
607 | 0 | } |
608 | 0 | proto_tree_add_expert_format(pppoe_tree, pinfo, &ei_pppoe_tag_length, tvb, tagstart+4, poe_tag_length, |
609 | 0 | "Credit Scale Factor tag: Wrong length: %u (expected 2)", poe_tag_length); |
610 | 0 | } |
611 | 0 | break; |
612 | 0 | case PPPOE_TAG_RELAY_ID: |
613 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_relay_session_id, tvb, |
614 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
615 | 0 | break; |
616 | 0 | case PPPOE_TAG_HURL: |
617 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_hurl, tvb, |
618 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
619 | 0 | break; |
620 | 0 | case PPPOE_TAG_MOTM: |
621 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_motm, tvb, |
622 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
623 | 0 | break; |
624 | 0 | case PPPOE_TAG_MAX_PAYLD: |
625 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_max_payload, tvb, |
626 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
627 | 0 | break; |
628 | 0 | case PPPOE_TAG_IP_RT_ADD: |
629 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_ip_route_add, tvb, |
630 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
631 | 0 | break; |
632 | | |
633 | | /* These error tag values should be interpreted as a utf-8 unterminated |
634 | | strings. */ |
635 | 0 | case PPPOE_TAG_SVC_ERR: |
636 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_service_name_error, tvb, |
637 | 0 | tagstart+4, poe_tag_length, ENC_ASCII); |
638 | 0 | break; |
639 | 0 | case PPPOE_TAG_AC_ERR: |
640 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_ac_system_error, tvb, |
641 | 0 | tagstart+4, poe_tag_length, ENC_ASCII); |
642 | 0 | break; |
643 | 0 | case PPPOE_TAG_GENERIC_ERR: |
644 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_generic_error, tvb, |
645 | 0 | tagstart+4, poe_tag_length, ENC_ASCII); |
646 | 0 | break; |
647 | | |
648 | | /* Get out if see end-of-list tag */ |
649 | 8 | case PPPOE_TAG_EOL: |
650 | 8 | return; |
651 | | |
652 | 1 | default: |
653 | 1 | if (poe_tag_length > 0 ) |
654 | 1 | { |
655 | | /* Presumably unknown tag; |
656 | | show tag value if we didn't |
657 | | do it above */ |
658 | 1 | if (!global_pppoe_show_tags_and_lengths) |
659 | 1 | { |
660 | 1 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag, tvb, tagstart, 2, ENC_BIG_ENDIAN); |
661 | 1 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_length, tvb, tagstart+2, 2, ENC_BIG_ENDIAN); |
662 | 1 | } |
663 | 1 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_unknown_data, tvb, |
664 | 1 | tagstart+2, poe_tag_length, ENC_NA); |
665 | 1 | } |
666 | 9 | } |
667 | | |
668 | 0 | tagstart += (4 + poe_tag_length); |
669 | 0 | } |
670 | 9 | } |
671 | | |
672 | | |
673 | | /* Discovery protocol, i.e. PPP session not yet established */ |
674 | | static int dissect_pppoed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
675 | 17 | { |
676 | 17 | uint8_t pppoe_code; |
677 | 17 | uint16_t reported_payload_length; |
678 | | |
679 | 17 | proto_tree *pppoe_tree = NULL; |
680 | 17 | proto_item *ti; |
681 | | |
682 | 17 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPPoED"); |
683 | 17 | col_clear(pinfo->cinfo, COL_INFO); |
684 | | |
685 | | /* Start Decoding Here. */ |
686 | 17 | pppoe_code = tvb_get_uint8(tvb, 1); |
687 | | |
688 | 17 | col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(pppoe_code, code_vals, "Unknown")); |
689 | | |
690 | | /* Read length of payload */ |
691 | 17 | reported_payload_length = tvb_get_ntohs(tvb, 4); |
692 | | |
693 | 17 | if (tree) |
694 | 17 | { |
695 | 17 | ti = proto_tree_add_item(tree, proto_pppoed, tvb, 0, reported_payload_length+6, ENC_NA); |
696 | 17 | pppoe_tree = proto_item_add_subtree(ti, ett_pppoed); |
697 | | |
698 | | /* Dissect fixed fields */ |
699 | 17 | proto_tree_add_item(pppoe_tree, hf_pppoe_version, tvb, 0, 1, ENC_BIG_ENDIAN); |
700 | 17 | proto_tree_add_item(pppoe_tree, hf_pppoe_type, tvb, 0, 1, ENC_BIG_ENDIAN); |
701 | 17 | proto_tree_add_item(pppoe_tree, hf_pppoe_code, tvb, 1, 1, ENC_BIG_ENDIAN); |
702 | 17 | proto_tree_add_item(pppoe_tree, hf_pppoe_session_id, tvb, 2, 2, ENC_BIG_ENDIAN); |
703 | 17 | proto_tree_add_item(pppoe_tree, hf_pppoe_payload_length, tvb, 4, 2, ENC_BIG_ENDIAN); |
704 | 17 | } |
705 | | |
706 | | /* Now dissect any tags */ |
707 | 17 | if (reported_payload_length > 0) |
708 | 9 | { |
709 | 9 | dissect_pppoe_tags(tvb, pinfo, 6, pppoe_tree, 6+reported_payload_length); |
710 | 9 | } |
711 | | |
712 | 17 | return tvb_captured_length(tvb); |
713 | 17 | } |
714 | | |
715 | | void proto_register_pppoed(void) |
716 | 14 | { |
717 | 14 | static hf_register_info hf[] = |
718 | 14 | { |
719 | | /* Discovery tag fields */ |
720 | 14 | { &hf_pppoed_tags, |
721 | 14 | { "PPPoE Tags", "pppoed.tags", FT_NONE, BASE_NONE, |
722 | 14 | NULL, 0x0, NULL, HFILL |
723 | 14 | } |
724 | 14 | }, |
725 | 14 | { &hf_pppoed_tag, |
726 | 14 | { "Tag", "pppoed.tag", FT_UINT16, BASE_HEX, |
727 | 14 | VALS(tag_vals), 0x0, NULL, HFILL |
728 | 14 | } |
729 | 14 | }, |
730 | 14 | { &hf_pppoed_tag_length, |
731 | 14 | { "Tag Length", "pppoed.tag_length", FT_UINT16, BASE_DEC, |
732 | 14 | NULL, 0x0, NULL, HFILL |
733 | 14 | } |
734 | 14 | }, |
735 | 14 | { &hf_pppoed_tag_length_8, |
736 | 14 | { "Tag Length", "pppoed.tag_length_8", FT_UINT8, BASE_DEC, |
737 | 14 | NULL, 0x0, NULL, HFILL |
738 | 14 | } |
739 | 14 | }, |
740 | 14 | { &hf_pppoed_tag_unknown_data, |
741 | 14 | { "Unknown Data", "pppoed.tag.unknown_data", FT_BYTES, BASE_NONE, |
742 | 14 | NULL, 0x0, NULL, HFILL |
743 | 14 | } |
744 | 14 | }, |
745 | 14 | { &hf_pppoed_tag_service_name, |
746 | 14 | { "Service-Name", "pppoed.tags.service_name", FT_STRING, BASE_NONE, |
747 | 14 | NULL, 0x0, NULL, HFILL |
748 | 14 | } |
749 | 14 | }, |
750 | 14 | { &hf_pppoed_tag_ac_name, |
751 | 14 | { "AC-Name", "pppoed.tags.ac_name", FT_STRING, BASE_NONE, |
752 | 14 | NULL, 0x0, NULL, HFILL |
753 | 14 | } |
754 | 14 | }, |
755 | 14 | { &hf_pppoed_tag_host_uniq, |
756 | 14 | { "Host-Uniq", "pppoed.tags.host_uniq", FT_BYTES, BASE_NONE, |
757 | 14 | NULL, 0x0, NULL, HFILL |
758 | 14 | } |
759 | 14 | }, |
760 | 14 | { &hf_pppoed_tag_ac_cookie, |
761 | 14 | { "AC-Cookie", "pppoed.tags.ac_cookie", FT_BYTES, BASE_NONE, |
762 | 14 | NULL, 0x0, NULL, HFILL |
763 | 14 | } |
764 | 14 | }, |
765 | 14 | { &hf_pppoed_tag_vendor_id, |
766 | 14 | { "Vendor id", "pppoed.tags.vendor_id", FT_UINT32, BASE_DEC, |
767 | 14 | NULL, 0x0, NULL, HFILL |
768 | 14 | } |
769 | 14 | }, |
770 | 14 | { &hf_pppoed_tag_vendor_unspecified, |
771 | 14 | { "Vendor unspecified", "pppoed.tags.vendor_unspecified", FT_BYTES, BASE_NONE, |
772 | 14 | NULL, 0x0, NULL, HFILL |
773 | 14 | } |
774 | 14 | }, |
775 | 14 | { &hf_pppoed_tag_vspec_tags, |
776 | 14 | { "Vendor Specific PPPoE Tags", "pppoed.tags.vendorspecific.tags", FT_NONE, BASE_NONE, |
777 | 14 | NULL, 0x0, NULL, HFILL |
778 | 14 | } |
779 | 14 | }, |
780 | 14 | { &hf_pppoed_tag_vspec_tag, |
781 | 14 | { "Tag", "pppoed.tags.vendorspecific.tag", FT_UINT8, BASE_HEX, |
782 | 14 | VALS(vspec_tag_vals), 0x0, NULL, HFILL |
783 | 14 | } |
784 | 14 | }, |
785 | 14 | { &hf_pppoed_tag_vspec_circuit_id, |
786 | 14 | { "Circuit ID", "pppoed.tags.circuit_id", FT_STRING, BASE_NONE, |
787 | 14 | NULL, 0x0, NULL, HFILL |
788 | 14 | } |
789 | 14 | }, |
790 | 14 | { &hf_pppoed_tag_vspec_remote_id, |
791 | 14 | { "Remote ID", "pppoed.tags.remote_id", FT_STRING, BASE_NONE, |
792 | 14 | NULL, 0x0, NULL, HFILL |
793 | 14 | } |
794 | 14 | }, |
795 | 14 | { &hf_pppoed_tag_vspec_act_data_rate_up, |
796 | 14 | { "Actual Data Rate Upstream", "pppoed.tags.act_data_rate_up", FT_UINT32, BASE_DEC, |
797 | 14 | NULL, 0x0, NULL, HFILL |
798 | 14 | } |
799 | 14 | }, |
800 | 14 | { &hf_pppoed_tag_vspec_act_data_rate_down, |
801 | 14 | { "Actual Data Rate Downstream", "pppoed.tags.act_data_rate_down", FT_UINT32, BASE_DEC, |
802 | 14 | NULL, 0x0, NULL, HFILL |
803 | 14 | } |
804 | 14 | }, |
805 | 14 | { &hf_pppoed_tag_vspec_min_data_rate_up, |
806 | 14 | { "Minimum Data Rate Upstream", "pppoed.tags.min_data_rate_up", FT_UINT32, BASE_DEC, |
807 | 14 | NULL, 0x0, NULL, HFILL |
808 | 14 | } |
809 | 14 | }, |
810 | 14 | { &hf_pppoed_tag_vspec_min_data_rate_down, |
811 | 14 | { "Minimum Data Rate Downstream", "pppoed.tags.min_data_rate_down", FT_UINT32, BASE_DEC, |
812 | 14 | NULL, 0x0, NULL, HFILL |
813 | 14 | } |
814 | 14 | }, |
815 | 14 | { &hf_pppoed_tag_vspec_attainable_data_rate_up, |
816 | 14 | { "Attainable DataRate Upstream", "pppoed.tags.attainable_data_rate_up", FT_UINT32, BASE_DEC, |
817 | 14 | NULL, 0x0, NULL, HFILL |
818 | 14 | } |
819 | 14 | }, |
820 | 14 | { &hf_pppoed_tag_vspec_attainable_data_rate_down, |
821 | 14 | { "Attainable DataRate Downstream", "pppoed.tags.attainable_data_rate_down", FT_UINT32, BASE_DEC, |
822 | 14 | NULL, 0x0, NULL, HFILL |
823 | 14 | } |
824 | 14 | }, |
825 | 14 | { &hf_pppoed_tag_vspec_max_data_rate_up, |
826 | 14 | { "Maximum Data Rate Upstream", "pppoed.tags.max_data_rate_up", FT_UINT32, BASE_DEC, |
827 | 14 | NULL, 0x0, NULL, HFILL |
828 | 14 | } |
829 | 14 | }, |
830 | 14 | { &hf_pppoed_tag_vspec_max_data_rate_down, |
831 | 14 | { "Maximum Data Rate Downstream", "pppoed.tags.max_data_rate_down", FT_UINT32, BASE_DEC, |
832 | 14 | NULL, 0x0, NULL, HFILL |
833 | 14 | } |
834 | 14 | }, |
835 | 14 | { &hf_pppoed_tag_vspec_min_data_rate_up_lp, |
836 | 14 | { "Min DataRate Upstream in low power state", "pppoed.tags.min_data_rate_up_lp", FT_UINT32, BASE_DEC, |
837 | 14 | NULL, 0x0, NULL, HFILL |
838 | 14 | } |
839 | 14 | }, |
840 | 14 | { &hf_pppoed_tag_vspec_min_data_rate_down_lp, |
841 | 14 | { "Minimum Data Rate Downstream in low power state", "pppoed.tags.min_data_rate_down_lp", FT_UINT32, BASE_DEC, |
842 | 14 | NULL, 0x0, NULL, HFILL |
843 | 14 | } |
844 | 14 | }, |
845 | 14 | { &hf_pppoed_tag_vspec_max_int_delay_up, |
846 | 14 | { "Max Interleaving Delay Upstream", "pppoed.tags.max_int_delay_up", FT_UINT32, BASE_DEC, |
847 | 14 | NULL, 0x0, NULL, HFILL |
848 | 14 | } |
849 | 14 | }, |
850 | 14 | { &hf_pppoed_tag_vspec_act_int_delay_up, |
851 | 14 | { "Actual Interleaving Delay Upstream", "pppoed.tags.act_int_delay_up", FT_UINT32, BASE_DEC, |
852 | 14 | NULL, 0x0, NULL, HFILL |
853 | 14 | } |
854 | 14 | }, |
855 | 14 | { &hf_pppoed_tag_vspec_max_int_delay_down, |
856 | 14 | { "Maximum Interleaving Delay Downstream", "pppoed.tags.max_int_delay_down", FT_UINT32, BASE_DEC, |
857 | 14 | NULL, 0x0, NULL, HFILL |
858 | 14 | } |
859 | 14 | }, |
860 | 14 | { &hf_pppoed_tag_vspec_act_int_delay_down, |
861 | 14 | { "Actual Interleaving Delay Downstream", "pppoed.tags.act_int_delay_down", FT_UINT32, BASE_DEC, |
862 | 14 | NULL, 0x0, NULL, HFILL |
863 | 14 | } |
864 | 14 | }, |
865 | 14 | { &hf_pppoed_tag_vspec_access_loop_encapsulation, |
866 | 14 | { "Access-Loop-Encapsulation", "pppoed.tags.access_loop_encap", FT_NONE, BASE_NONE, |
867 | 14 | NULL, 0x0, NULL, HFILL |
868 | 14 | } |
869 | 14 | }, |
870 | 14 | { &hf_pppoed_tag_vspec_access_loop_encap_data_link, |
871 | 14 | { "Data link", "pppoed.tags.access_loop_encap.data_link", FT_UINT8, BASE_HEX, |
872 | 14 | VALS(vspec_tag_dslf_access_loop_encap_data_link_vals), 0x0, NULL, HFILL |
873 | 14 | } |
874 | 14 | }, |
875 | 14 | { &hf_pppoed_tag_vspec_access_loop_encap_encap_1, |
876 | 14 | { "Encaps 1", "pppoed.tags.access_loop_encap.encap_1", FT_UINT8, BASE_HEX, |
877 | 14 | VALS(vspec_tag_dslf_access_loop_encap_encap_1_vals), 0x0, NULL, HFILL |
878 | 14 | } |
879 | 14 | }, |
880 | 14 | { &hf_pppoed_tag_vspec_access_loop_encap_encap_2, |
881 | 14 | { "Encaps 2", "pppoed.tags.access_loop_encap.encap_2", FT_UINT8, BASE_HEX, |
882 | 14 | VALS(vspec_tag_dslf_access_loop_encap_encap_2_vals), 0x0, NULL, HFILL |
883 | 14 | } |
884 | 14 | }, |
885 | 14 | { &hf_pppoed_tag_credits, |
886 | 14 | { "Credits", "pppoed.tags.credits", FT_BYTES, BASE_NONE, |
887 | 14 | NULL, 0x0, NULL, HFILL |
888 | 14 | } |
889 | 14 | }, |
890 | 14 | { &hf_pppoed_tag_credits_fcn, |
891 | 14 | { "FCN", "pppoed.tags.credits.fcn", FT_UINT16, BASE_DEC, |
892 | 14 | NULL, 0x0, NULL, HFILL |
893 | 14 | } |
894 | 14 | }, |
895 | 14 | { &hf_pppoed_tag_credits_bcn, |
896 | 14 | { "BCN", "pppoed.tags.credits.bcn", FT_UINT16, BASE_DEC, |
897 | 14 | NULL, 0x0, NULL, HFILL |
898 | 14 | } |
899 | 14 | }, |
900 | 14 | { &hf_pppoed_tag_metrics, |
901 | 14 | { "Metrics", "pppoed.tags.metrics", FT_BYTES, BASE_NONE, |
902 | 14 | NULL, 0x0, NULL, HFILL |
903 | 14 | } |
904 | 14 | }, |
905 | 14 | { &hf_pppoed_tag_metrics_r, |
906 | 14 | { "Receive Only", "pppoed.tags.metrics.r", FT_BOOLEAN, 16, |
907 | 14 | NULL, PPPOE_RCV_ONLY_MASK, NULL, HFILL |
908 | 14 | } |
909 | 14 | }, |
910 | 14 | { &hf_pppoed_tag_mdr_units, |
911 | 14 | { "MDR Units", "pppoed.tags.metrics.mdr_units", FT_UINT16, BASE_HEX, |
912 | 14 | VALS(datarate_scale_vals), PPPOE_MDR_MASK, NULL, HFILL |
913 | 14 | } |
914 | 14 | }, |
915 | 14 | { &hf_pppoed_tag_cdr_units, |
916 | 14 | { "CDR Units", "pppoed.tags.metrics.cdr_units", FT_UINT16, BASE_HEX, |
917 | 14 | VALS(datarate_scale_vals), PPPOE_CDR_MASK, NULL, HFILL |
918 | 14 | } |
919 | 14 | }, |
920 | 14 | { &hf_pppoed_tag_metrics_rlq, |
921 | 14 | { "Relative Link Quality", "pppoed.tags.metrics.rlq", FT_UINT8, BASE_DEC, |
922 | 14 | NULL, 0x0, NULL, HFILL |
923 | 14 | } |
924 | 14 | }, |
925 | 14 | { &hf_pppoed_tag_metrics_resource, |
926 | 14 | { "Resource", "pppoed.tags.metrics.resource", FT_UINT8, BASE_DEC, |
927 | 14 | NULL, 0x0, NULL, HFILL |
928 | 14 | } |
929 | 14 | }, |
930 | 14 | { &hf_pppoed_tag_metrics_latency, |
931 | 14 | { "Latency", "pppoed.tags.metrics.latency", FT_UINT16, BASE_DEC, |
932 | 14 | NULL, 0x0, NULL, HFILL |
933 | 14 | } |
934 | 14 | }, |
935 | 14 | { &hf_pppoed_tag_metrics_curr_drate, |
936 | 14 | { "Curr. datarate", "pppoed.tags.metrics.curr_drate", FT_UINT16, BASE_DEC, |
937 | 14 | NULL, 0x0, NULL, HFILL |
938 | 14 | } |
939 | 14 | }, |
940 | 14 | { &hf_pppoed_tag_metrics_max_drate, |
941 | 14 | { "Max. datarate", "pppoed.tags.metrics.max_drate", FT_UINT16, BASE_DEC, |
942 | 14 | NULL, 0x0, NULL, HFILL |
943 | 14 | } |
944 | 14 | }, |
945 | 14 | { &hf_pppoed_tag_seq_num, |
946 | 14 | { "Sequence Number", "pppoed.tags.seq_num", FT_UINT16, BASE_HEX, |
947 | 14 | NULL, 0x0, NULL, HFILL |
948 | 14 | } |
949 | 14 | }, |
950 | 14 | { &hf_pppoed_tag_cred_scale, |
951 | 14 | { "Credit Scale Factor", "pppoed.tags.credit_scale", FT_UINT16, BASE_DEC, |
952 | 14 | NULL, 0x0, NULL, HFILL |
953 | 14 | } |
954 | 14 | }, |
955 | 14 | { &hf_pppoed_tag_relay_session_id, |
956 | 14 | { "Relay-Session-Id", "pppoed.tags.relay_session_id", FT_BYTES, BASE_NONE, |
957 | 14 | NULL, 0x0, NULL, HFILL |
958 | 14 | } |
959 | 14 | }, |
960 | 14 | { &hf_pppoed_tag_hurl, |
961 | 14 | { "HURL", "pppoed.tags.hurl", FT_BYTES, BASE_NONE, |
962 | 14 | NULL, 0x0, NULL, HFILL |
963 | 14 | } |
964 | 14 | }, |
965 | 14 | { &hf_pppoed_tag_motm, |
966 | 14 | { "MOTM", "pppoed.tags.motm", FT_BYTES, BASE_NONE, |
967 | 14 | NULL, 0x0, NULL, HFILL |
968 | 14 | } |
969 | 14 | }, |
970 | 14 | { &hf_pppoed_tag_max_payload, |
971 | 14 | { "PPP-Max-Payload", "pppoed.tags.max_payload", FT_BYTES, BASE_NONE, |
972 | 14 | NULL, 0x0, NULL, HFILL |
973 | 14 | } |
974 | 14 | }, |
975 | 14 | { &hf_pppoed_tag_ip_route_add, |
976 | 14 | { "IP Route Add", "pppoed.tags.ip_route_add", FT_BYTES, BASE_NONE, |
977 | 14 | NULL, 0x0, NULL, HFILL |
978 | 14 | } |
979 | 14 | }, |
980 | 14 | { &hf_pppoed_tag_service_name_error, |
981 | 14 | { "Service-Name-Error", "pppoed.tags.service_name_error", FT_STRING, BASE_NONE, |
982 | 14 | NULL, 0x0, NULL, HFILL |
983 | 14 | } |
984 | 14 | }, |
985 | 14 | { &hf_pppoed_tag_ac_system_error, |
986 | 14 | { "AC-System-Error", "pppoed.tags.ac_system_error", FT_STRING, BASE_NONE, |
987 | 14 | NULL, 0x0, NULL, HFILL |
988 | 14 | } |
989 | 14 | }, |
990 | 14 | { &hf_pppoed_tag_generic_error, |
991 | 14 | { "Generic-Error", "pppoed.tags.generic_error", FT_STRING, BASE_NONE, |
992 | 14 | NULL, 0x0, NULL, HFILL |
993 | 14 | } |
994 | 14 | } |
995 | 14 | }; |
996 | | |
997 | 14 | static int *ett[] = { |
998 | 14 | &ett_pppoed, |
999 | 14 | &ett_pppoed_tags, |
1000 | 14 | &ett_pppoed_tag_vspec_dslf_access_loop_encaps |
1001 | 14 | }; |
1002 | | |
1003 | 14 | module_t *pppoed_module; |
1004 | | |
1005 | | /* Register protocol and fields */ |
1006 | 14 | proto_pppoed = proto_register_protocol("PPP-over-Ethernet Discovery", |
1007 | 14 | "PPPoED", "pppoed"); |
1008 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1009 | 14 | proto_register_field_array(proto_pppoed, hf, array_length(hf)); |
1010 | | |
1011 | | /* Register dissector handle */ |
1012 | 14 | pppoed_handle = register_dissector("pppoed", dissect_pppoed, proto_pppoed); |
1013 | | |
1014 | | /* Preference setting */ |
1015 | 14 | pppoed_module = prefs_register_protocol(proto_pppoed, NULL); |
1016 | 14 | prefs_register_bool_preference(pppoed_module, "show_tags_and_lengths", |
1017 | 14 | "Show tag values and lengths", |
1018 | 14 | "Show values of tags and lengths of data fields", |
1019 | 14 | &global_pppoe_show_tags_and_lengths); |
1020 | 14 | } |
1021 | | |
1022 | | void proto_reg_handoff_pppoed(void) |
1023 | 14 | { |
1024 | 14 | dissector_add_uint("ethertype", ETHERTYPE_PPPOED, pppoed_handle); |
1025 | 14 | } |
1026 | | |
1027 | | |
1028 | | /* Session protocol, i.e. PPP session established */ |
1029 | | static int dissect_pppoes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
1030 | 42 | { |
1031 | 42 | uint8_t pppoe_code; |
1032 | 42 | uint16_t reported_payload_length; |
1033 | 42 | uint16_t poe_tag_length; |
1034 | 42 | int actual_payload_length; |
1035 | 42 | int length, reported_length; |
1036 | 42 | int credit_offset = 0, tagstart = 0; |
1037 | 42 | uint16_t cp_code; |
1038 | | |
1039 | 42 | proto_tree *pppoe_tree; |
1040 | 42 | proto_item *ti = NULL; |
1041 | 42 | tvbuff_t *next_tvb; |
1042 | | |
1043 | 42 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPPoES"); |
1044 | 42 | col_clear(pinfo->cinfo, COL_INFO); |
1045 | | |
1046 | | /* Start Decoding Here. */ |
1047 | 42 | pppoe_code = tvb_get_uint8(tvb, 1); |
1048 | | |
1049 | 42 | col_set_str(pinfo->cinfo, COL_INFO, |
1050 | 42 | val_to_str_const(pppoe_code, code_vals, "Unknown")); |
1051 | | |
1052 | 42 | reported_payload_length = tvb_get_ntohs(tvb, 4); |
1053 | 42 | actual_payload_length = tvb_reported_length_remaining(tvb, 6); |
1054 | | |
1055 | 42 | ti = proto_tree_add_item(tree, proto_pppoes, tvb, 0, 6, ENC_NA); |
1056 | 42 | pppoe_tree = proto_item_add_subtree(ti, ett_pppoe); |
1057 | | |
1058 | 42 | proto_tree_add_item(pppoe_tree, hf_pppoe_version, tvb, 0, 1, ENC_BIG_ENDIAN); |
1059 | 42 | proto_tree_add_item(pppoe_tree, hf_pppoe_type, tvb, 0, 1, ENC_BIG_ENDIAN); |
1060 | 42 | proto_tree_add_item(pppoe_tree, hf_pppoe_code, tvb, 1, 1, ENC_BIG_ENDIAN); |
1061 | 42 | proto_tree_add_item(pppoe_tree, hf_pppoe_session_id, tvb, 2, 2, ENC_BIG_ENDIAN); |
1062 | 42 | ti = proto_tree_add_item(pppoe_tree, hf_pppoe_payload_length, tvb, 4, 2, ENC_BIG_ENDIAN); |
1063 | | |
1064 | | |
1065 | 42 | if (PPPOE_TAG_CREDITS == tvb_get_ntohs(tvb, 6)) |
1066 | 0 | { |
1067 | 0 | tagstart = 6; |
1068 | 0 | poe_tag_length = tvb_get_ntohs(tvb, tagstart + 2); |
1069 | | |
1070 | | /* Create tags subtree */ |
1071 | 0 | ti = proto_tree_add_item(pppoe_tree, hf_pppoes_tags, tvb, tagstart, 8, ENC_NA); |
1072 | 0 | pppoe_tree = proto_item_add_subtree(ti, ett_pppoes_tags); |
1073 | | |
1074 | | /* Show tag data */ |
1075 | 0 | if (poe_tag_length == 4) |
1076 | 0 | { |
1077 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoes_tag_credits_fcn, tvb, |
1078 | 0 | tagstart+4, 2, ENC_BIG_ENDIAN); |
1079 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoes_tag_credits_bcn, tvb, |
1080 | 0 | tagstart+6, 2, ENC_BIG_ENDIAN); |
1081 | 0 | } else { |
1082 | 0 | proto_tree_add_item(pppoe_tree, hf_pppoed_tag_credits, tvb, |
1083 | 0 | tagstart+4, poe_tag_length, ENC_NA); |
1084 | 0 | } |
1085 | |
|
1086 | 0 | credit_offset = 8; |
1087 | 0 | } |
1088 | | |
1089 | | /* |
1090 | | * The only reason why the payload length from the header |
1091 | | * should differ from the remaining data in the packet |
1092 | | * would be if the total packet length, including Ethernet |
1093 | | * CRC, were < 64 bytes, so that padding was required. |
1094 | | * |
1095 | | * That means that you have 14 bytes of Ethernet header, |
1096 | | * 4 bytes of FCS, and fewer than 46 bytes of PPPoE packet. |
1097 | | * |
1098 | | * If that's not the case, we report a difference between |
1099 | | * the payload length in the packet, and the amount of |
1100 | | * data following the PPPoE header, as an error. |
1101 | | */ |
1102 | 42 | if (tvb_reported_length(tvb) > 46) { |
1103 | | /* |
1104 | | * Be forgiving about a possible trailing FCS. |
1105 | | * |
1106 | | * XXX - this dissector currently doesn't know |
1107 | | * whether any extra data past the end of the PPP |
1108 | | * payload is an FCS or not. |
1109 | | * |
1110 | | * If we know that we have an FCS, or that we don't |
1111 | | * have an FCS, we should have been handed a tvbuff |
1112 | | * without the FCS, and we should just do the strict |
1113 | | * length check. |
1114 | | * |
1115 | | * If we don't know whether we have an FCS, then: |
1116 | | * |
1117 | | * if this isn't over Ethernet - the "E" in "PPPoE" |
1118 | | * nonwithstanding, it can also run on top of 802.11, |
1119 | | * for example - there's no trailer, so any data |
1120 | | * past the payload length is either an FCS or |
1121 | | * bogus; |
1122 | | * |
1123 | | * if this is over Ethernet, there shouldn't be |
1124 | | * a trailer, as the packet is long enough not to |
1125 | | * require a trailer, as per the above; |
1126 | | * |
1127 | | * so perhaps we should assume that if we have exactly |
1128 | | * 4 bytes of extra information, it's an FCS, otherwise |
1129 | | * it's not. |
1130 | | * |
1131 | | * Perhaps we need to have a routine to call to |
1132 | | * do all the length checking, etc., and call it |
1133 | | * from here and from other dissectors where the |
1134 | | * protocol has a length field, or have a way to |
1135 | | * tell the dissector that called us which field |
1136 | | * has the length field and have *that* dissector |
1137 | | * do the length checking and add the expert info |
1138 | | * to the length field, *after* it does all the |
1139 | | * FCS heuristics. |
1140 | | */ |
1141 | | |
1142 | | /* retrieve the control protocol code if it's there */ |
1143 | 23 | cp_code = tvb_get_ntohs(tvb, 6); |
1144 | | /* |
1145 | | * The session payload length expressly does not include pad bytes |
1146 | | * when LCP or IPCP or IPv6CP are present, so avoid the spurious error message |
1147 | | */ |
1148 | 23 | if ((cp_code != PPP_LCP) && (cp_code != PPP_IPCP) && (cp_code != PPP_IPV6CP) && |
1149 | 23 | (reported_payload_length != actual_payload_length) && |
1150 | 23 | ((reported_payload_length + 4) != actual_payload_length)) { |
1151 | 23 | proto_item_append_text(ti, " [incorrect, should be %u]", |
1152 | 23 | actual_payload_length); |
1153 | 23 | expert_add_info_format(pinfo, ti, &ei_pppoe_payload_length, "Possible bad payload length %u != %u", reported_payload_length, actual_payload_length); |
1154 | 23 | } |
1155 | 23 | } |
1156 | | |
1157 | | /* |
1158 | | * Construct a tvbuff containing the PPP packet. |
1159 | | */ |
1160 | 42 | length = tvb_captured_length_remaining(tvb, 6); |
1161 | 42 | reported_length = tvb_reported_length_remaining(tvb, 6); |
1162 | 42 | DISSECTOR_ASSERT(length >= 0); |
1163 | 42 | DISSECTOR_ASSERT(reported_length >= 0); |
1164 | 42 | if (length > reported_length) |
1165 | 0 | length = reported_length; |
1166 | 42 | if ((unsigned)length > reported_payload_length) |
1167 | 9 | length = reported_payload_length; |
1168 | 42 | if ((unsigned)reported_length > reported_payload_length) |
1169 | 9 | reported_length = reported_payload_length; |
1170 | 42 | next_tvb = tvb_new_subset_length_caplen(tvb,(6 + credit_offset), |
1171 | 42 | (length - credit_offset), |
1172 | 42 | (reported_length - credit_offset)); |
1173 | 42 | call_dissector(ppp_handle,next_tvb,pinfo,tree); |
1174 | 42 | return tvb_captured_length(tvb); |
1175 | 42 | } |
1176 | | |
1177 | | void proto_register_pppoes(void) |
1178 | 14 | { |
1179 | | |
1180 | 14 | static hf_register_info hf[] = |
1181 | 14 | { |
1182 | 14 | { &hf_pppoes_tags, |
1183 | 14 | { "PPPoE Tags", "pppoes.tags", FT_NONE, BASE_NONE, |
1184 | 14 | NULL, 0x0, NULL, HFILL |
1185 | 14 | } |
1186 | 14 | }, |
1187 | | #if 0 |
1188 | | { &hf_pppoes_tag, |
1189 | | { "Tag", "pppoes.tag", FT_UINT16, BASE_HEX, |
1190 | | VALS(tag_vals), 0x0, NULL, HFILL |
1191 | | } |
1192 | | }, |
1193 | | #endif |
1194 | | #if 0 |
1195 | | { &hf_pppoes_tag_credits, |
1196 | | { "Credits", "pppoes.tags.credits", FT_BYTES, BASE_NONE, |
1197 | | NULL, 0x0, NULL, HFILL |
1198 | | } |
1199 | | }, |
1200 | | #endif |
1201 | 14 | { &hf_pppoes_tag_credits_fcn, |
1202 | 14 | { "FCN", "pppoes.tags.credits.fcn", FT_UINT16, BASE_DEC, |
1203 | 14 | NULL, 0x0, NULL, HFILL |
1204 | 14 | } |
1205 | 14 | }, |
1206 | 14 | { &hf_pppoes_tag_credits_bcn, |
1207 | 14 | { "BCN", "pppoes.tags.credits.bcn", FT_UINT16, BASE_DEC, |
1208 | 14 | NULL, 0x0, NULL, HFILL |
1209 | 14 | } |
1210 | 14 | } |
1211 | 14 | }; |
1212 | | |
1213 | 14 | static int *ett[] = { |
1214 | 14 | &ett_pppoes, |
1215 | 14 | &ett_pppoes_tags |
1216 | 14 | }; |
1217 | | |
1218 | | /* Register protocol */ |
1219 | 14 | proto_pppoes = proto_register_protocol("PPP-over-Ethernet Session", "PPPoES", "pppoes"); |
1220 | | |
1221 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1222 | 14 | proto_register_field_array(proto_pppoes, hf, array_length(hf)); |
1223 | | |
1224 | 14 | pppoes_handle = register_dissector("pppoes", dissect_pppoes, proto_pppoes); |
1225 | 14 | } |
1226 | | |
1227 | | void proto_register_pppoe(void) |
1228 | 14 | { |
1229 | 14 | static hf_register_info hf[] = |
1230 | 14 | { |
1231 | | /* These fields common to discovery and session protocols */ |
1232 | 14 | { &hf_pppoe_version, |
1233 | 14 | { "Version", "pppoe.version", FT_UINT8, BASE_DEC, |
1234 | 14 | NULL, 0xf0, NULL, HFILL |
1235 | 14 | } |
1236 | 14 | }, |
1237 | 14 | { &hf_pppoe_type, |
1238 | 14 | { "Type", "pppoe.type", FT_UINT8, BASE_DEC, |
1239 | 14 | NULL, 0x0f, NULL, HFILL |
1240 | 14 | } |
1241 | 14 | }, |
1242 | 14 | { &hf_pppoe_code, |
1243 | 14 | { "Code", "pppoe.code", FT_UINT8, BASE_HEX, |
1244 | 14 | VALS(code_vals), 0x0, NULL, HFILL |
1245 | 14 | } |
1246 | 14 | }, |
1247 | 14 | { &hf_pppoe_session_id, |
1248 | 14 | { "Session ID", "pppoe.session_id", FT_UINT16, BASE_HEX, |
1249 | 14 | NULL, 0x0, NULL, HFILL |
1250 | 14 | } |
1251 | 14 | }, |
1252 | 14 | { &hf_pppoe_payload_length, |
1253 | 14 | { "Payload Length", "pppoe.payload_length", FT_UINT16, BASE_DEC, |
1254 | 14 | NULL, 0x0, NULL, HFILL |
1255 | 14 | } |
1256 | 14 | } |
1257 | 14 | }; |
1258 | | |
1259 | 14 | static int *ett[] = { |
1260 | 14 | &ett_pppoe |
1261 | 14 | }; |
1262 | | |
1263 | 14 | static ei_register_info ei[] = { |
1264 | 14 | { &ei_pppoe_tag_length, { "pppoed.tag_length.invalid", PI_MALFORMED, PI_WARN, "Wrong length", EXPFILL }}, |
1265 | 14 | { &ei_pppoe_payload_length, { "pppoe.payload_length.bad", PI_MALFORMED, PI_WARN, "Possible bad payload length", EXPFILL }}, |
1266 | 14 | }; |
1267 | | |
1268 | 14 | expert_module_t* expert_pppoe; |
1269 | | |
1270 | | /* Register protocol */ |
1271 | 14 | proto_pppoe = proto_register_protocol("PPP-over-Ethernet", "PPPoE", "pppoe"); |
1272 | | |
1273 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1274 | 14 | proto_register_field_array(proto_pppoe, hf, array_length(hf)); |
1275 | 14 | expert_pppoe = expert_register_protocol(proto_pppoe); |
1276 | 14 | expert_register_field_array(expert_pppoe, ei, array_length(ei)); |
1277 | | |
1278 | 14 | } |
1279 | | |
1280 | | void proto_reg_handoff_pppoes(void) |
1281 | 14 | { |
1282 | 14 | dissector_add_uint("ethertype", ETHERTYPE_PPPOES, pppoes_handle); |
1283 | 14 | dissector_add_uint("wtap_encap", WTAP_ENCAP_PPP_ETHER, pppoes_handle); |
1284 | | |
1285 | | /* Get a handle for the PPP dissector */ |
1286 | 14 | ppp_handle = find_dissector_add_dependency("ppp", proto_pppoes); |
1287 | 14 | } |
1288 | | |
1289 | | /* |
1290 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1291 | | * |
1292 | | * Local variables: |
1293 | | * c-basic-offset: 8 |
1294 | | * tab-width: 8 |
1295 | | * indent-tabs-mode: t |
1296 | | * End: |
1297 | | * |
1298 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
1299 | | * :indentSize=8:tabSize=8:noTabs=false: |
1300 | | */ |