@@ -360,7 +360,7 @@ Interface IP Address Sub-Object
360360struct icmp_interface_information_ipaddr_subobject_t {
361361 nd_uint16_t afi ;
362362 nd_uint16_t reserved ;
363- nd_byte ip_addr [1 ];
363+ nd_byte ip_addr [];
364364};
365365
366366/*
@@ -388,7 +388,7 @@ struct icmp_interface_identification_ipaddr_subobject_t {
388388 nd_uint16_t afi ;
389389 nd_uint8_t addrlen ;
390390 nd_uint8_t reserved ;
391- nd_byte ip_addr [1 ];
391+ nd_byte ip_addr [];
392392};
393393
394394/* prototypes */
@@ -410,30 +410,45 @@ icmp_tstamp_print(u_int tstamp)
410410 return buf ;
411411}
412412
413+ #define CHECK_TLEN (len ) \
414+ ND_TCHECK_LEN(obj_tptr, len); \
415+ if (obj_tlen < (len)) { \
416+ return obj_len; \
417+ }
418+
419+ #define UPDATE_TLEN (len ) \
420+ obj_tlen -= (len)
421+
422+ #define UPDATE_TPTR_AND_TLEN (len ) \
423+ obj_tptr += (len); \
424+ obj_tlen -= (len)
425+
413426static int
414- print_icmp_multipart_ext_object (netdissect_options * ndo , const uint8_t * obj_tptr )
427+ print_icmp_multipart_ext_object (netdissect_options * ndo , const uint8_t * obj_ptr )
415428{
416- u_int obj_tlen , obj_class_num , obj_ctype ;
429+ u_int obj_len , obj_class_num , obj_ctype ;
417430 const struct icmp_multipart_ext_object_header_t * icmp_multipart_ext_object_header ;
431+ const uint8_t * obj_tptr ;
432+ u_int obj_tlen ;
418433
419- icmp_multipart_ext_object_header = (const struct icmp_multipart_ext_object_header_t * )obj_tptr ;
420- obj_tlen = GET_BE_U_2 (icmp_multipart_ext_object_header -> length );
434+ icmp_multipart_ext_object_header = (const struct icmp_multipart_ext_object_header_t * )obj_ptr ;
435+ obj_len = GET_BE_U_2 (icmp_multipart_ext_object_header -> length );
421436 obj_class_num = GET_U_1 (icmp_multipart_ext_object_header -> class_num );
422437 obj_ctype = GET_U_1 (icmp_multipart_ext_object_header -> ctype );
423- obj_tptr += sizeof (struct icmp_multipart_ext_object_header_t );
424438
425439 ND_PRINT ("\n\t %s (%u), Class-Type: %u, length %u" ,
426440 tok2str (icmp_multipart_ext_obj_values ,"unknown" ,obj_class_num ),
427441 obj_class_num ,
428442 obj_ctype ,
429- obj_tlen );
443+ obj_len );
430444
431445 /* infinite loop protection */
432- if ((obj_class_num == 0 ) ||
433- (obj_tlen < sizeof (struct icmp_multipart_ext_object_header_t ))) {
446+ if ((obj_class_num == 0 ) || /* XXX - why is this necessary? */
447+ (obj_len < sizeof (struct icmp_multipart_ext_object_header_t ))) {
434448 return -1 ;
435449 }
436- obj_tlen -= sizeof (struct icmp_multipart_ext_object_header_t );
450+ obj_tptr = obj_ptr + sizeof (struct icmp_multipart_ext_object_header_t );
451+ obj_tlen = obj_len - sizeof (struct icmp_multipart_ext_object_header_t );
437452
438453 switch (obj_class_num ) {
439454 case MPLS_STACK_ENTRY_OBJECT_CLASS :
@@ -442,6 +457,7 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
442457 {
443458 uint32_t raw_label ;
444459
460+ CHECK_TLEN (4 );
445461 raw_label = GET_BE_U_4 (obj_tptr );
446462 ND_PRINT ("\n\t label %u, tc %u" , MPLS_LABEL (raw_label ), MPLS_TC (raw_label ));
447463 if (MPLS_STACK (raw_label ))
@@ -464,7 +480,6 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
464480 | Interface Role| Rsvd1 | Rsvd2 |ifIndex| IPAddr| name | MTU |
465481 +-------+-------+-------+-------+-------+-------+-------+-------+
466482 */
467- const uint8_t * offset ;
468483 u_int interface_role , if_index_flag , ipaddr_flag , name_flag , mtu_flag ;
469484
470485 interface_role = (obj_ctype & 0xc0 ) >> 6 ;
@@ -477,92 +492,119 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
477492 tok2str (icmp_interface_information_role_values ,
478493 "an unknown interface role" ,interface_role ));
479494
480- offset = obj_tptr ;
481-
482495 if (if_index_flag ) {
483- ND_PRINT ("\n\t Interface Index: %u" , GET_BE_U_4 (offset ));
484- offset += 4 ;
496+ CHECK_TLEN (4 );
497+ ND_PRINT ("\n\t Interface Index: %u" , GET_BE_U_4 (obj_tptr ));
498+ UPDATE_TPTR_AND_TLEN (4 );
485499 }
486500 if (ipaddr_flag ) {
501+ uint16_t afi ;
487502 const struct icmp_interface_information_ipaddr_subobject_t * ipaddr_subobj ;
488503
489504 ND_PRINT ("\n\t IP Address sub-object: " );
490- ipaddr_subobj = (const struct icmp_interface_information_ipaddr_subobject_t * ) offset ;
491- switch (GET_BE_U_2 (ipaddr_subobj -> afi )) {
505+ ipaddr_subobj = (const struct icmp_interface_information_ipaddr_subobject_t * ) obj_tptr ;
506+
507+ CHECK_TLEN (sizeof * ipaddr_subobj );
508+
509+ /* AFI */
510+ afi = GET_BE_U_2 (ipaddr_subobj -> afi );
511+
512+ /* Reserved space */
513+ ND_TCHECK_1 (ipaddr_subobj -> reserved );
514+
515+ UPDATE_TPTR_AND_TLEN (sizeof * ipaddr_subobj );
516+
517+ switch (afi ) {
492518 case 1 :
519+ CHECK_TLEN (4 );
493520 ND_PRINT ("%s" , GET_IPADDR_STRING (ipaddr_subobj -> ip_addr ));
494- offset += 4 ;
521+ UPDATE_TPTR_AND_TLEN ( 4 ) ;
495522 break ;
496523 case 2 :
524+ CHECK_TLEN (16 );
497525 ND_PRINT ("%s" , GET_IP6ADDR_STRING (ipaddr_subobj -> ip_addr ));
498- offset += 16 ;
526+ UPDATE_TPTR_AND_TLEN ( 16 ) ;
499527 break ;
500528 default :
501529 ND_PRINT ("Unknown Address Family Identifier" );
502530 return -1 ;
503531 }
504- offset += 4 ;
505532 }
506533 if (name_flag ) {
507534 uint8_t inft_name_length_field ;
508535 const struct icmp_interface_information_ifname_subobject_t * ifname_subobj ;
509536
510- ifname_subobj = (const struct icmp_interface_information_ifname_subobject_t * ) offset ;
537+ ifname_subobj = (const struct icmp_interface_information_ifname_subobject_t * ) obj_tptr ;
538+ CHECK_TLEN (1 );
511539 inft_name_length_field = GET_U_1 (ifname_subobj -> length );
540+
512541 ND_PRINT ("\n\t Interface Name" );
513- if (inft_name_length_field == 0 ) {
542+ if (inft_name_length_field < 1 ) {
514543 ND_PRINT (" [length %u]" , inft_name_length_field );
515544 nd_print_invalid (ndo );
516545 break ;
517546 }
547+ CHECK_TLEN (inft_name_length_field );
518548 if (inft_name_length_field % 4 != 0 ) {
519549 ND_PRINT (" [length %u != N x 4]" , inft_name_length_field );
520550 nd_print_invalid (ndo );
521- offset += inft_name_length_field ;
551+ UPDATE_TPTR_AND_TLEN ( inft_name_length_field ) ;
522552 break ;
523553 }
524554 if (inft_name_length_field > 64 ) {
525555 ND_PRINT (" [length %u > 64]" , inft_name_length_field );
526556 nd_print_invalid (ndo );
527- offset += inft_name_length_field ;
557+ UPDATE_TPTR_AND_TLEN ( inft_name_length_field ) ;
528558 break ;
529559 }
530560 ND_PRINT (", length %u: " , inft_name_length_field );
531561 nd_printjnp (ndo , ifname_subobj -> if_name ,
532562 inft_name_length_field - 1 );
533- offset += inft_name_length_field ;
563+ UPDATE_TPTR_AND_TLEN ( inft_name_length_field ) ;
534564 }
535565 if (mtu_flag ) {
536- ND_PRINT ("\n\t MTU: %u" , GET_BE_U_4 (offset ));
537- offset += 4 ;
566+ CHECK_TLEN (4 );
567+ ND_PRINT ("\n\t MTU: %u" , GET_BE_U_4 (obj_tptr ));
568+ UPDATE_TPTR_AND_TLEN (4 );
538569 }
539570 break ;
540571 }
541572
542573 case INTERFACE_IDENTIFICATION_OBJECT_CLASS :
543574 switch (obj_ctype ) {
544575 case 1 :
545- ND_PRINT ("\n\t Interface Name, length %d : " , obj_tlen );
576+ ND_PRINT ("\n\t Interface Name, length %u : " , obj_tlen );
546577 nd_printjnp (ndo , obj_tptr , obj_tlen );
547578 break ;
548579 case 2 :
580+ CHECK_TLEN (4 );
549581 ND_PRINT ("\n\t Interface Index: %u" , GET_BE_U_4 (obj_tptr ));
550582 break ;
551583 case 3 :
552584 {
553585 const struct icmp_interface_identification_ipaddr_subobject_t * id_ipaddr_subobj ;
586+ uint16_t afi ;
587+ uint8_t addrlen ;
588+
554589 ND_PRINT ("\n\t IP Address sub-object: " );
555590 id_ipaddr_subobj = (const struct icmp_interface_identification_ipaddr_subobject_t * ) obj_tptr ;
556- switch (GET_BE_U_2 (id_ipaddr_subobj -> afi )) {
591+ CHECK_TLEN (sizeof * id_ipaddr_subobj );
592+ afi = GET_BE_U_2 (id_ipaddr_subobj -> afi );
593+ addrlen = GET_U_1 (id_ipaddr_subobj -> addrlen );
594+ ND_TCHECK_1 (id_ipaddr_subobj -> reserved );
595+ UPDATE_TLEN (sizeof * id_ipaddr_subobj );
596+
597+ CHECK_TLEN (addrlen );
598+ switch (afi ) {
557599 case 1 :
558- if (GET_U_1 ( id_ipaddr_subobj -> addrlen ) != 4 ) {
559- ND_PRINT ("[length %d != 4] " , GET_U_1 ( id_ipaddr_subobj -> addrlen ) );
600+ if (addrlen != 4 ) {
601+ ND_PRINT ("[length %d != 4] " , addrlen );
560602 }
561603 ND_PRINT ("%s" , GET_IPADDR_STRING (id_ipaddr_subobj -> ip_addr ));
562604 break ;
563605 case 2 :
564- if (GET_U_1 ( id_ipaddr_subobj -> addrlen ) != 16 ) {
565- ND_PRINT ("[length %d != 16] " , GET_U_1 ( id_ipaddr_subobj -> addrlen ) );
606+ if (addrlen != 16 ) {
607+ ND_PRINT ("[length %d != 16] " , addrlen );
566608 }
567609 ND_PRINT ("%s" , GET_IP6ADDR_STRING (id_ipaddr_subobj -> ip_addr ));
568610 break ;
@@ -582,7 +624,7 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
582624 print_unknown_data (ndo , obj_tptr , "\n\t " , obj_tlen );
583625 break ;
584626 }
585- return obj_tlen + sizeof ( struct icmp_multipart_ext_object_header_t ) ;
627+ return obj_len ;
586628}
587629
588630void
0 commit comments