@@ -57,12 +57,19 @@ struct icmp {
57
57
nd_uint16_t icd_id ;
58
58
nd_uint16_t icd_seq ;
59
59
} 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 ;
60
65
nd_uint32_t ih_void ;
61
66
} icmp_hun ;
62
67
#define icmp_pptr icmp_hun.ih_pptr
63
68
#define icmp_gwaddr icmp_hun.ih_gwaddr
64
69
#define icmp_id icmp_hun.ih_idseq.icd_id
65
70
#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
66
73
#define icmp_void icmp_hun.ih_void
67
74
union {
68
75
struct id_ts {
@@ -140,7 +147,12 @@ struct icmp {
140
147
#define ICMP_MASKREQ 17 /* address mask request */
141
148
#define ICMP_MASKREPLY 18 /* address mask reply */
142
149
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 */
144
156
145
157
#define ICMP_ERRTYPE (type ) \
146
158
((type) == ICMP_UNREACH || (type) == ICMP_SOURCEQUENCH || \
@@ -150,6 +162,9 @@ struct icmp {
150
162
((type) == ICMP_UNREACH || \
151
163
(type) == ICMP_TIMXCEED || \
152
164
(type) == ICMP_PARAMPROB)
165
+ #define ICMP_EXTENDED_ECHO_TYPE (type ) \
166
+ ((type) == ICMP_EXTENDED_ECHO_REQUEST || \
167
+ (type) == ICMP_EXTENDED_ECHO_REPLY)
153
168
/* rfc1700 */
154
169
#ifndef ICMP_UNREACH_NET_UNKNOWN
155
170
#define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */
@@ -195,6 +210,28 @@ static const struct tok icmp2str[] = {
195
210
{ ICMP_IREQ , "information request" },
196
211
{ ICMP_IREQREPLY , "information reply" },
197
212
{ 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" },
198
235
{ 0 , NULL }
199
236
};
200
237
@@ -278,12 +315,16 @@ struct icmp_ext_t {
278
315
* contained bytes of the payload beyond the first 128 bytes, in
279
316
* draft-bonica-icmp-mpls-02; it was reassigned to an "Interface
280
317
* Information Object" in RFC 5837.
318
+ *
319
+ * Class 3 is defined by RFC8335.
281
320
*/
282
321
283
322
/* rfc4950 */
284
323
#define MPLS_STACK_ENTRY_OBJECT_CLASS 1
285
324
/* rfc5837 */
286
325
#define INTERFACE_INFORMATION_OBJECT_CLASS 2
326
+ /* rfc8335 */
327
+ #define INTERFACE_IDENTIFICATION_OBJECT_CLASS 3
287
328
288
329
struct icmp_multipart_ext_object_header_t {
289
330
nd_uint16_t length ;
@@ -292,8 +333,9 @@ struct icmp_multipart_ext_object_header_t {
292
333
};
293
334
294
335
static 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" },
297
339
{ 0 , NULL }
298
340
};
299
341
@@ -332,6 +374,22 @@ struct icmp_interface_information_ifname_subobject_t {
332
374
nd_byte if_name [63 ];
333
375
};
334
376
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
+
335
393
/* prototypes */
336
394
const char * icmp_tstamp_print (u_int );
337
395
@@ -480,6 +538,45 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
480
538
break ;
481
539
}
482
540
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
+
483
580
default :
484
581
print_unknown_data (ndo , obj_tptr , "\n\t " , obj_tlen );
485
582
break ;
@@ -818,6 +915,16 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen,
818
915
icmp_tstamp_print (GET_BE_U_4 (dp -> icmp_ttime )));
819
916
break ;
820
917
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
+
821
928
default :
822
929
str = tok2str (icmp2str , "type-#%u" , icmp_type );
823
930
break ;
@@ -927,4 +1034,47 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen,
927
1034
obj_tptr += obj_tlen ;
928
1035
}
929
1036
}
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 ;
930
1080
}
0 commit comments