Skip to content

Commit 498f33b

Browse files
fennerfxlb
authored andcommitted
ICMP: print RFC8335 PROBE extended echo/reply messages
Add interface name, ifindex and IP address printing for Interface Information Object, and use the newly-refactored object printing to print the single object included in an RFC8335 PROBE message. Include a test with several well-formed packets, and one test with a truncated packet (truncated packet supplied by fuzzer).
1 parent 605654a commit 498f33b

File tree

7 files changed

+213
-3
lines changed

7 files changed

+213
-3
lines changed

print-icmp.c

Lines changed: 153 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

288329
struct icmp_multipart_ext_object_header_t {
289330
nd_uint16_t length;
@@ -292,8 +333,9 @@ struct icmp_multipart_ext_object_header_t {
292333
};
293334

294335
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" },
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 */
336394
const 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
}

tests/TESTLIST

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ dvmrp mrinfo_query.pcap dvmrp.out
221221
# ICMPv4 -- pcap from https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6632
222222
rfc5837 icmp-rfc5837.pcap icmp-rfc5837.out -v
223223
icmp_inft_name_length_zero icmp_inft_name_length_zero.pcap icmp_inft_name_length_zero.out -v
224+
rfc8335 rfc8335.pcap icmp-rfc8335.out
225+
rfc8335-v rfc8335.pcap icmp-rfc8335-v.out -v
226+
rfc8335-missing-bytes rfc8335-missing-bytes.pcap icmp-rfc8335-missing-bytes.out -v
224227

225228
# ICMPv6
226229
icmpv6 icmpv6.pcap icmpv6.out -vv

tests/icmp-rfc8335-missing-bytes.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
1 2024-01-22 18:23:52.186004 IP [total length 84 > length 35] (invalid) (tos 0x0, ttl 64, id 53536, offset 0, flags [DF], proto ICMP (1), length 84, bad cksum 22 (->cdef)!)
2+
35.36.42.37 > 38.39.40.41: ICMP extended echo request, id 11823, seq 48, length 64
3+
Local Interface [|icmp]

tests/icmp-rfc8335-v.out

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
1 2024-01-01 22:21:42.293205 IP (tos 0x0, ttl 54, id 10659, offset 0, flags [none], proto ICMP (1), length 48)
2+
204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63210, seq 0, length 28
3+
Local Interface, checksum 0xdcf4 (correct), length 12
4+
Interface Identification Object (3), Class-Type: 2, length 8
5+
Interface Index: 1
6+
2 2024-01-01 22:22:02.791281 IP (tos 0x0, ttl 54, id 11917, offset 0, flags [none], proto ICMP (1), length 50)
7+
204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63239, seq 0, length 30
8+
Local Interface, checksum 0x9424 (correct), length 14
9+
Interface Identification Object (3), Class-Type: 1, length 10
10+
Interface Name, length 6: enp1s0
11+
3 2024-01-01 22:22:49.391909 IP (tos 0x0, ttl 54, id 14708, offset 0, flags [none], proto ICMP (1), length 52)
12+
204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63269, seq 0, length 32
13+
Local Interface, checksum 0xf8e5 (correct), length 16
14+
Interface Identification Object (3), Class-Type: 3, length 12
15+
IP Address sub-object: 149.28.74.237
16+
4 2024-01-01 22:23:14.907148 IP (tos 0x0, ttl 54, id 16258, offset 0, flags [none], proto ICMP (1), length 52)
17+
204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63274, seq 0, length 32
18+
Remote Interface, checksum 0xf9d1 (correct), length 16
19+
Interface Identification Object (3), Class-Type: 3, length 12
20+
IP Address sub-object: 149.28.74.1
21+
5 2024-01-01 22:36:36.688455 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto ICMP (1), length 52)
22+
149.28.74.237 > 204.194.23.128: ICMP extended echo request, id 42, seq 42, length 32
23+
Local Interface, checksum 0xd819 (correct), length 16
24+
Interface Identification Object (3), Class-Type: 1, length 12
25+
Interface Name, length 8: fxp0.0
26+
6 2024-01-01 22:36:36.750419 IP (tos 0x0, ttl 245, id 63324, offset 0, flags [DF], proto ICMP (1), length 52)
27+
204.194.23.128 > 149.28.74.237: ICMP extended echo reply, id 42, seq 42, length 32
28+
Code 0 (No error), State 0 (Reserved), active 1 ipv4 1 ipv6 1
29+
7 2024-01-01 22:36:44.864530 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto ICMP (1), length 44)
30+
149.28.74.237 > 204.194.23.128: ICMP extended echo request, id 42, seq 42, length 24
31+
Local Interface, checksum 0xd819 (correct), length 16
32+
Interface Identification Object (3), Class-Type: 1, length 12
33+
Interface Name, length 8: fxp0.0
34+
8 2024-01-01 22:36:44.926583 IP (tos 0x0, ttl 245, id 63780, offset 0, flags [DF], proto ICMP (1), length 44)
35+
204.194.23.128 > 149.28.74.237: ICMP extended echo reply, id 42, seq 42, length 24
36+
Code 1 (Malformed Query), State 0 (Reserved), active 0 ipv4 0 ipv6 0
37+
9 2024-01-01 22:37:03.384499 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto ICMP (1), length 48)
38+
149.28.74.237 > 204.194.23.128: ICMP extended echo request, id 42, seq 42, length 28
39+
Local Interface, checksum 0xdccb (correct), length 12
40+
Interface Identification Object (3), Class-Type: 2, length 8
41+
Interface Index: 42
42+
10 2024-01-01 22:37:03.446572 IP (tos 0x0, ttl 245, id 64921, offset 0, flags [DF], proto ICMP (1), length 48)
43+
204.194.23.128 > 149.28.74.237: ICMP extended echo reply, id 42, seq 42, length 28
44+
Code 2 (No Such Interface), State 0 (Reserved), active 0 ipv4 0 ipv6 0

tests/icmp-rfc8335.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
1 2024-01-01 22:21:42.293205 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63210, seq 0, length 28
2+
2 2024-01-01 22:22:02.791281 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63239, seq 0, length 30
3+
3 2024-01-01 22:22:49.391909 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63269, seq 0, length 32
4+
4 2024-01-01 22:23:14.907148 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo request, id 63274, seq 0, length 32
5+
5 2024-01-01 22:36:36.688455 IP 149.28.74.237 > 204.194.23.128: ICMP extended echo request, id 42, seq 42, length 32
6+
6 2024-01-01 22:36:36.750419 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo reply, id 42, seq 42, length 32
7+
7 2024-01-01 22:36:44.864530 IP 149.28.74.237 > 204.194.23.128: ICMP extended echo request, id 42, seq 42, length 24
8+
8 2024-01-01 22:36:44.926583 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo reply, id 42, seq 42, length 24
9+
9 2024-01-01 22:37:03.384499 IP 149.28.74.237 > 204.194.23.128: ICMP extended echo request, id 42, seq 42, length 28
10+
10 2024-01-01 22:37:03.446572 IP 204.194.23.128 > 149.28.74.237: ICMP extended echo reply, id 42, seq 42, length 28

tests/rfc8335-missing-bytes.pcap

121 Bytes
Binary file not shown.

tests/rfc8335.pcap

814 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)