@@ -57,12 +57,19 @@ struct icmp {
5757 nd_uint16_t icd_id ;
5858 nd_uint16_t icd_seq ;
5959 } ih_idseq ;
60+ struct ih_idseqx { /* RFC8335 */
61+ nd_uint16_t icdx_id ;
62+ nd_uint8_t icdx_seq ;
63+ nd_uint8_t icdx_info ;
64+ } ih_idseqx ;
6065 nd_uint32_t ih_void ;
6166 } icmp_hun ;
6267#define icmp_pptr icmp_hun.ih_pptr
6368#define icmp_gwaddr icmp_hun.ih_gwaddr
6469#define icmp_id icmp_hun.ih_idseq.icd_id
6570#define icmp_seq icmp_hun.ih_idseq.icd_seq
71+ #define icmp_xseq icmp_hun.ih_idseqx.icdx_seq
72+ #define icmp_xinfo icmp_hun.ih_idseqx.icdx_info
6673#define icmp_void icmp_hun.ih_void
6774 union {
6875 struct id_ts {
@@ -140,7 +147,12 @@ struct icmp {
140147#define ICMP_MASKREQ 17 /* address mask request */
141148#define ICMP_MASKREPLY 18 /* address mask reply */
142149
143- #define ICMP_MAXTYPE 18
150+ #define ICMP_EXTENDED_ECHO_REQUEST 42 /* extended echo request */
151+ #define ICMP_EXTENDED_ECHO_REPLY 43 /* extended echo reply */
152+ #define ICMP_ECHO_X_MALFORMED_QUERY 1 /* malformed query */
153+ #define ICMP_ECHO_X_NO_SUCH_INTERFACE 2 /* no such interface */
154+ #define ICMP_ECHO_X_NO_SUCH_TABLE_ENTRY 3 /* no such table entry */
155+ #define ICMP_ECHO_X_MULTIPLE_INTERFACES 4 /* multiple interfaces satisfy query */
144156
145157#define ICMP_ERRTYPE (type ) \
146158 ((type) == ICMP_UNREACH || (type) == ICMP_SOURCEQUENCH || \
@@ -150,6 +162,9 @@ struct icmp {
150162 ((type) == ICMP_UNREACH || \
151163 (type) == ICMP_TIMXCEED || \
152164 (type) == ICMP_PARAMPROB)
165+ #define ICMP_EXTENDED_ECHO_TYPE (type ) \
166+ ((type) == ICMP_EXTENDED_ECHO_REQUEST || \
167+ (type) == ICMP_EXTENDED_ECHO_REPLY)
153168/* rfc1700 */
154169#ifndef ICMP_UNREACH_NET_UNKNOWN
155170#define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */
@@ -195,6 +210,28 @@ static const struct tok icmp2str[] = {
195210 { ICMP_IREQ , "information request" },
196211 { ICMP_IREQREPLY , "information reply" },
197212 { ICMP_MASKREQ , "address mask request" },
213+ { ICMP_EXTENDED_ECHO_REQUEST , "extended echo request" },
214+ { ICMP_EXTENDED_ECHO_REPLY , "extended echo reply" },
215+ { 0 , NULL }
216+ };
217+
218+ static const struct tok icmp_extended_echo_reply_code_str [] = {
219+ { 0 , "No error" },
220+ { ICMP_ECHO_X_MALFORMED_QUERY , "Malformed Query" },
221+ { ICMP_ECHO_X_NO_SUCH_INTERFACE , "No Such Interface" },
222+ { ICMP_ECHO_X_NO_SUCH_TABLE_ENTRY , "No Such Table Entry" },
223+ { ICMP_ECHO_X_MULTIPLE_INTERFACES , "Multiple Interfaces Satisfy Query" },
224+ { 0 , NULL }
225+ };
226+
227+ static const struct tok icmp_extended_echo_reply_state_str [] = {
228+ { 0 , "Reserved" },
229+ { 1 , "Incomplete" },
230+ { 2 , "Reachable" },
231+ { 3 , "Stale" },
232+ { 4 , "Delay" },
233+ { 5 , "Probe" },
234+ { 6 , "Failed" },
198235 { 0 , NULL }
199236};
200237
@@ -278,12 +315,16 @@ struct icmp_ext_t {
278315 * contained bytes of the payload beyond the first 128 bytes, in
279316 * draft-bonica-icmp-mpls-02; it was reassigned to an "Interface
280317 * Information Object" in RFC 5837.
318+ *
319+ * Class 3 is defined by RFC8335.
281320 */
282321
283322/* rfc4950 */
284323#define MPLS_STACK_ENTRY_OBJECT_CLASS 1
285324/* rfc5837 */
286325#define INTERFACE_INFORMATION_OBJECT_CLASS 2
326+ /* rfc8335 */
327+ #define INTERFACE_IDENTIFICATION_OBJECT_CLASS 3
287328
288329struct icmp_multipart_ext_object_header_t {
289330 nd_uint16_t length ;
@@ -292,8 +333,9 @@ struct icmp_multipart_ext_object_header_t {
292333};
293334
294335static const struct tok icmp_multipart_ext_obj_values [] = {
295- { 1 , "MPLS Stack Entry Object" },
296- { 2 , "Interface Information Object" },
336+ { MPLS_STACK_ENTRY_OBJECT_CLASS , "MPLS Stack Entry Object" },
337+ { INTERFACE_INFORMATION_OBJECT_CLASS , "Interface Information Object" },
338+ { INTERFACE_IDENTIFICATION_OBJECT_CLASS , "Interface Identification Object" },
297339 { 0 , NULL }
298340};
299341
@@ -332,6 +374,22 @@ struct icmp_interface_information_ifname_subobject_t {
332374 nd_byte if_name [63 ];
333375};
334376
377+ /*
378+ * Interface Identification IP Address Sub-Object
379+ * 0 1 2 3
380+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
381+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
382+ * | AFI | Address Length| Reserved |
383+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
384+ * | Address ....
385+ */
386+ struct icmp_interface_identification_ipaddr_subobject_t {
387+ nd_uint16_t afi ;
388+ nd_uint8_t addrlen ;
389+ nd_uint8_t reserved ;
390+ nd_byte ip_addr [1 ];
391+ };
392+
335393/* prototypes */
336394const char * icmp_tstamp_print (u_int );
337395
@@ -480,6 +538,45 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
480538 break ;
481539 }
482540
541+ case INTERFACE_IDENTIFICATION_OBJECT_CLASS :
542+ switch (obj_ctype ) {
543+ case 1 :
544+ ND_PRINT ("\n\t Interface Name, length %d: " , obj_tlen );
545+ nd_printjnp (ndo , obj_tptr , obj_tlen );
546+ break ;
547+ case 2 :
548+ ND_PRINT ("\n\t Interface Index: %u" , GET_BE_U_4 (obj_tptr ));
549+ break ;
550+ case 3 :
551+ {
552+ const struct icmp_interface_identification_ipaddr_subobject_t * id_ipaddr_subobj ;
553+ ND_PRINT ("\n\t IP Address sub-object: " );
554+ id_ipaddr_subobj = (const struct icmp_interface_identification_ipaddr_subobject_t * ) obj_tptr ;
555+ switch (GET_BE_U_2 (id_ipaddr_subobj -> afi )) {
556+ case 1 :
557+ if (GET_U_1 (id_ipaddr_subobj -> addrlen ) != 4 ) {
558+ ND_PRINT ("[length %d != 4] " , GET_U_1 (id_ipaddr_subobj -> addrlen ));
559+ }
560+ ND_PRINT ("%s" , GET_IPADDR_STRING (id_ipaddr_subobj -> ip_addr ));
561+ break ;
562+ case 2 :
563+ if (GET_U_1 (id_ipaddr_subobj -> addrlen ) != 16 ) {
564+ ND_PRINT ("[length %d != 16] " , GET_U_1 (id_ipaddr_subobj -> addrlen ));
565+ }
566+ ND_PRINT ("%s" , GET_IP6ADDR_STRING (id_ipaddr_subobj -> ip_addr ));
567+ break ;
568+ default :
569+ ND_PRINT ("Unknown Address Family Identifier" );
570+ return -1 ;
571+ }
572+ break ;
573+ }
574+ default :
575+ print_unknown_data (ndo , obj_tptr , "\n\t " , obj_tlen );
576+ break ;
577+ }
578+ break ;
579+
483580 default :
484581 print_unknown_data (ndo , obj_tptr , "\n\t " , obj_tlen );
485582 break ;
@@ -818,6 +915,16 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen,
818915 icmp_tstamp_print (GET_BE_U_4 (dp -> icmp_ttime )));
819916 break ;
820917
918+ case ICMP_EXTENDED_ECHO_REQUEST :
919+ case ICMP_EXTENDED_ECHO_REPLY :
920+ /* brief info here due to limited buf; more info below */
921+ (void )snprintf (buf , sizeof (buf ), "extended echo %s, id %u, seq %u" ,
922+ icmp_type == ICMP_EXTENDED_ECHO_REQUEST ?
923+ "request" : "reply" ,
924+ GET_BE_U_2 (dp -> icmp_id ),
925+ GET_U_1 (dp -> icmp_xseq ));
926+ break ;
927+
821928 default :
822929 str = tok2str (icmp2str , "type-#%u" , icmp_type );
823930 break ;
@@ -927,4 +1034,47 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen,
9271034 obj_tptr += obj_tlen ;
9281035 }
9291036 }
1037+
1038+ if (ndo -> ndo_vflag >= 1 && ICMP_EXTENDED_ECHO_TYPE (icmp_type )) {
1039+ int xinfo = GET_U_1 (dp -> icmp_xinfo );
1040+ switch (icmp_type ) {
1041+ case ICMP_EXTENDED_ECHO_REQUEST :
1042+ ND_PRINT ("\n\t%s Interface" , xinfo & 1 ? "Local" : "Remote" );
1043+ if (ICMP_EXT_EXTRACT_VERSION (GET_U_1 (dp -> icmp_data )) != ICMP_EXT_VERSION ) {
1044+ nd_print_invalid (ndo );
1045+ } else {
1046+ // A single extended object. The extended header is not
1047+ // located at offset 128 in this case, so we can not use
1048+ // icmp_ext_checksum.
1049+ uint16_t sum = GET_BE_U_2 (dp -> icmp_data + 2 );
1050+ uint16_t len = GET_BE_U_2 (dp -> icmp_data + 4 );
1051+ // The checksum is over the extended header and the single
1052+ // object
1053+ len += 4 ;
1054+ vec [0 ].ptr = dp -> icmp_data ;
1055+ vec [0 ].len = len ;
1056+ if (ND_TTEST_LEN (vec [0 ].ptr , vec [0 ].len )) {
1057+ ND_PRINT (", checksum 0x%04x (%scorrect), length %u" ,
1058+ sum ,
1059+ in_cksum (vec , 1 ) ? "in" : "" ,
1060+ len );
1061+ }
1062+ print_icmp_multipart_ext_object (ndo , dp -> icmp_data + 4 );
1063+ }
1064+ break ;
1065+ case ICMP_EXTENDED_ECHO_REPLY :
1066+ {
1067+ int state = ( xinfo & 0xe0 ) >> 5 ;
1068+ ND_PRINT ("\n\tCode %d (%s), State %d (%s), active %d ipv4 %d ipv6 %d" ,
1069+ icmp_code , tok2str (icmp_extended_echo_reply_code_str , "Unknown" , icmp_code ),
1070+ state , tok2str (icmp_extended_echo_reply_state_str , "Unknown" , state ),
1071+ xinfo & 4 ? 1 : 0 ,
1072+ xinfo & 2 ? 1 : 0 ,
1073+ xinfo & 1 ? 1 : 0 );
1074+ }
1075+ break ;
1076+ }
1077+ }
1078+
1079+ return ;
9301080}
0 commit comments