|
13 | 13 | * FOR A PARTICULAR PURPOSE. |
14 | 14 | * |
15 | 15 | * Reference documentation: |
16 | | - * http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml |
17 | | - * http://www.cisco.com/warp/public/473/21.html |
18 | | - * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm |
| 16 | + * http://www.cisco.com/c/en/us/support/docs/lan-switching/vtp/10558-21.html |
| 17 | + * http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm |
19 | 18 | * |
20 | 19 | * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com> |
21 | 20 | */ |
|
36 | 35 | #define VTP_DOMAIN_NAME_LEN 32 |
37 | 36 | #define VTP_MD5_DIGEST_LEN 16 |
38 | 37 | #define VTP_UPDATE_TIMESTAMP_LEN 12 |
39 | | -#define VTP_VLAN_INFO_OFFSET 12 |
| 38 | +#define VTP_VLAN_INFO_FIXED_PART_LEN 12 /* length of VLAN info before VLAN name */ |
40 | 39 |
|
41 | 40 | #define VTP_SUMMARY_ADV 0x01 |
42 | 41 | #define VTP_SUBSET_ADV 0x02 |
@@ -252,89 +251,108 @@ vtp_print (netdissect_options *ndo, |
252 | 251 | ND_TCHECK2(*tptr, len); |
253 | 252 |
|
254 | 253 | vtp_vlan = (const struct vtp_vlan_*)tptr; |
| 254 | + if (len < VTP_VLAN_INFO_FIXED_PART_LEN) |
| 255 | + goto trunc; |
255 | 256 | ND_TCHECK(*vtp_vlan); |
256 | 257 | ND_PRINT((ndo, "\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name ", |
257 | 258 | tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), |
258 | 259 | tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type), |
259 | 260 | EXTRACT_16BITS(&vtp_vlan->vlanid), |
260 | 261 | EXTRACT_16BITS(&vtp_vlan->mtu), |
261 | 262 | EXTRACT_32BITS(&vtp_vlan->index))); |
262 | | - fn_printzp(ndo, tptr + VTP_VLAN_INFO_OFFSET, vtp_vlan->name_len, NULL); |
263 | | - |
264 | | - /* |
265 | | - * Vlan names are aligned to 32-bit boundaries. |
266 | | - */ |
267 | | - len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); |
268 | | - tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); |
| 263 | + len -= VTP_VLAN_INFO_FIXED_PART_LEN; |
| 264 | + tptr += VTP_VLAN_INFO_FIXED_PART_LEN; |
| 265 | + if (len < 4*((vtp_vlan->name_len + 3)/4)) |
| 266 | + goto trunc; |
| 267 | + ND_TCHECK2(*tptr, vtp_vlan->name_len); |
| 268 | + fn_printzp(ndo, tptr, vtp_vlan->name_len, NULL); |
| 269 | + |
| 270 | + /* |
| 271 | + * Vlan names are aligned to 32-bit boundaries. |
| 272 | + */ |
| 273 | + len -= 4*((vtp_vlan->name_len + 3)/4); |
| 274 | + tptr += 4*((vtp_vlan->name_len + 3)/4); |
269 | 275 |
|
270 | 276 | /* TLV information follows */ |
271 | 277 |
|
272 | 278 | while (len > 0) { |
273 | 279 |
|
274 | 280 | /* |
275 | | - * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1 |
276 | | - * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm |
| 281 | + * Cisco specs say 2 bytes for type + 2 bytes for length; |
| 282 | + * see http://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm |
| 283 | + * However, actual packets on the wire appear to use 1 |
| 284 | + * byte for the type and 1 byte for the length, so that's |
| 285 | + * what we do. |
277 | 286 | */ |
| 287 | + if (len < 2) |
| 288 | + goto trunc; |
| 289 | + ND_TCHECK2(*tptr, 2); |
278 | 290 | type = *tptr; |
279 | 291 | tlv_len = *(tptr+1); |
280 | 292 |
|
281 | 293 | ND_PRINT((ndo, "\n\t\t%s (0x%04x) TLV", |
282 | 294 | tok2str(vtp_vlan_tlv_values, "Unknown", type), |
283 | 295 | type)); |
284 | 296 |
|
285 | | - /* |
286 | | - * infinite loop check |
287 | | - */ |
288 | | - if (type == 0 || tlv_len == 0) { |
| 297 | + if (len < tlv_len * 2 + 2) { |
| 298 | + ND_PRINT((ndo, " (TLV goes past the end of the packet)")); |
289 | 299 | return; |
290 | 300 | } |
291 | | - |
292 | 301 | ND_TCHECK2(*tptr, tlv_len * 2 +2); |
293 | 302 |
|
294 | | - tlv_value = EXTRACT_16BITS(tptr+2); |
295 | | - |
296 | | - switch (type) { |
297 | | - case VTP_VLAN_STE_HOP_COUNT: |
298 | | - ND_PRINT((ndo, ", %u", tlv_value)); |
299 | | - break; |
300 | | - |
301 | | - case VTP_VLAN_PRUNING: |
302 | | - ND_PRINT((ndo, ", %s (%u)", |
303 | | - tlv_value == 1 ? "Enabled" : "Disabled", |
304 | | - tlv_value)); |
305 | | - break; |
306 | | - |
307 | | - case VTP_VLAN_STP_TYPE: |
308 | | - ND_PRINT((ndo, ", %s (%u)", |
309 | | - tok2str(vtp_stp_type_values, "Unknown", tlv_value), |
310 | | - tlv_value)); |
311 | | - break; |
312 | | - |
313 | | - case VTP_VLAN_BRIDGE_TYPE: |
314 | | - ND_PRINT((ndo, ", %s (%u)", |
315 | | - tlv_value == 1 ? "SRB" : "SRT", |
316 | | - tlv_value)); |
317 | | - break; |
318 | | - |
319 | | - case VTP_VLAN_BACKUP_CRF_MODE: |
320 | | - ND_PRINT((ndo, ", %s (%u)", |
321 | | - tlv_value == 1 ? "Backup" : "Not backup", |
322 | | - tlv_value)); |
323 | | - break; |
324 | | - |
325 | | - /* |
326 | | - * FIXME those are the defined TLVs that lack a decoder |
327 | | - * you are welcome to contribute code ;-) |
328 | | - */ |
329 | | - |
330 | | - case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: |
331 | | - case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: |
332 | | - case VTP_VLAN_PARENT_VLAN: |
333 | | - case VTP_VLAN_TRANS_BRIDGED_VLAN: |
334 | | - case VTP_VLAN_ARP_HOP_COUNT: |
335 | | - default: |
336 | | - print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2); |
337 | | - break; |
| 303 | + /* |
| 304 | + * We assume the value is a 2-byte integer; the length is |
| 305 | + * in units of 16-bit words. |
| 306 | + */ |
| 307 | + if (tlv_len != 1) { |
| 308 | + ND_PRINT((ndo, " (invalid TLV length %u != 1)", tlv_len)); |
| 309 | + return; |
| 310 | + } else { |
| 311 | + tlv_value = EXTRACT_16BITS(tptr+2); |
| 312 | + |
| 313 | + switch (type) { |
| 314 | + case VTP_VLAN_STE_HOP_COUNT: |
| 315 | + ND_PRINT((ndo, ", %u", tlv_value)); |
| 316 | + break; |
| 317 | + |
| 318 | + case VTP_VLAN_PRUNING: |
| 319 | + ND_PRINT((ndo, ", %s (%u)", |
| 320 | + tlv_value == 1 ? "Enabled" : "Disabled", |
| 321 | + tlv_value)); |
| 322 | + break; |
| 323 | + |
| 324 | + case VTP_VLAN_STP_TYPE: |
| 325 | + ND_PRINT((ndo, ", %s (%u)", |
| 326 | + tok2str(vtp_stp_type_values, "Unknown", tlv_value), |
| 327 | + tlv_value)); |
| 328 | + break; |
| 329 | + |
| 330 | + case VTP_VLAN_BRIDGE_TYPE: |
| 331 | + ND_PRINT((ndo, ", %s (%u)", |
| 332 | + tlv_value == 1 ? "SRB" : "SRT", |
| 333 | + tlv_value)); |
| 334 | + break; |
| 335 | + |
| 336 | + case VTP_VLAN_BACKUP_CRF_MODE: |
| 337 | + ND_PRINT((ndo, ", %s (%u)", |
| 338 | + tlv_value == 1 ? "Backup" : "Not backup", |
| 339 | + tlv_value)); |
| 340 | + break; |
| 341 | + |
| 342 | + /* |
| 343 | + * FIXME those are the defined TLVs that lack a decoder |
| 344 | + * you are welcome to contribute code ;-) |
| 345 | + */ |
| 346 | + |
| 347 | + case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: |
| 348 | + case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: |
| 349 | + case VTP_VLAN_PARENT_VLAN: |
| 350 | + case VTP_VLAN_TRANS_BRIDGED_VLAN: |
| 351 | + case VTP_VLAN_ARP_HOP_COUNT: |
| 352 | + default: |
| 353 | + print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2); |
| 354 | + break; |
| 355 | + } |
338 | 356 | } |
339 | 357 | len -= 2 + tlv_len*2; |
340 | 358 | tptr += 2 + tlv_len*2; |
|
0 commit comments