Skip to content

Commit

Permalink
ICMPv6: Parse RFC8335 (PROBE)
Browse files Browse the repository at this point in the history
The ICMP types are different, but everything else about
PROBE, including the RFC4884-based parsing, is the same,
so we share some code from print-icmp.c using the new
icmp.h.
  • Loading branch information
fenner committed Feb 5, 2024
1 parent 6d8b972 commit 8590ce9
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 13 deletions.
51 changes: 51 additions & 0 deletions icmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifndef netdissect_icmp_h
#define netdissect_icmp_h

/* common data structures to be shared between ICMP and ICMPv6 */

/*
* RFC 4884 - Extended ICMP to Support Multi-Part Messages
*/

/*
* Extract version from the first octet of icmp_ext_version_res.
*/
#define ICMP_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4)

/*
* Current version.
*/
#define ICMP_EXT_VERSION 2

extern int
print_icmp_multipart_ext_object(netdissect_options *, const uint8_t *);

/*
* RFC8335 - PROBE
*/
extern const struct tok icmp_extended_echo_reply_code_str[];
extern const struct tok icmp_extended_echo_reply_state_str[];

#endif /* netdissect_icmp_h */

17 changes: 4 additions & 13 deletions print-icmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "extract.h"

#include "ip.h"
#include "icmp.h"
#include "udp.h"
#include "ipproto.h"
#include "mpls.h"
Expand Down Expand Up @@ -217,7 +218,7 @@ static const struct tok icmp2str[] = {
{ 0, NULL }
};

static const struct tok icmp_extended_echo_reply_code_str[] = {
const struct tok icmp_extended_echo_reply_code_str[] = {
{ 0, "No error" },
{ ICMP_ECHO_X_MALFORMED_QUERY, "Malformed Query" },
{ ICMP_ECHO_X_NO_SUCH_INTERFACE, "No Such Interface" },
Expand All @@ -226,7 +227,7 @@ static const struct tok icmp_extended_echo_reply_code_str[] = {
{ 0, NULL }
};

static const struct tok icmp_extended_echo_reply_state_str[] = {
const struct tok icmp_extended_echo_reply_state_str[] = {
{ 0, "Reserved" },
{ 1, "Incomplete" },
{ 2, "Reachable" },
Expand Down Expand Up @@ -298,16 +299,6 @@ struct icmp_ext_t {
nd_byte icmp_ext_data[1];
};

/*
* Extract version from the first octet of icmp_ext_version_res.
*/
#define ICMP_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4)

/*
* Current version.
*/
#define ICMP_EXT_VERSION 2

/*
* Extension object class numbers.
*
Expand Down Expand Up @@ -411,7 +402,7 @@ icmp_tstamp_print(u_int tstamp)
return buf;
}

static int
int
print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr)
{
u_int obj_tlen, obj_class_num, obj_ctype;
Expand Down
50 changes: 50 additions & 0 deletions print-icmp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include "ip6.h"
#include "ipproto.h"
#include "icmp.h"

#include "udp.h"
#include "ah.h"
Expand Down Expand Up @@ -94,6 +95,8 @@ struct icmp6_hdr {
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
#define icmp6_xseq icmp6_data8[2] /* extended echo request/reply */
#define icmp6_xinfo icmp6_data8[3] /* extended echo request/reply */

#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */
#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */
Expand Down Expand Up @@ -132,6 +135,8 @@ struct icmp6_hdr {
#define ICMP6_HADISCOV_REPLY 145
#define ICMP6_MOBILEPREFIX_SOLICIT 146
#define ICMP6_MOBILEPREFIX_ADVERT 147
#define ICMP6_EXTENDED_ECHO_REQUEST 160 /* extended echo request */
#define ICMP6_EXTENDED_ECHO_REPLY 161 /* extended echo reply */

#define MLD6_MTRACE_RESP 200 /* mtrace response(to sender) */
#define MLD6_MTRACE 201 /* mtrace messages */
Expand Down Expand Up @@ -668,6 +673,8 @@ static const struct tok icmp6_type_values[] = {
{ MLD6_MTRACE, "mtrace message"},
{ MLD6_MTRACE_RESP, "mtrace response"},
{ ND_RPL_MESSAGE, "RPL"},
{ ICMP6_EXTENDED_ECHO_REQUEST, "extended echo request"},
{ ICMP6_EXTENDED_ECHO_REPLY, "extended echo reply"},
{ 0, NULL }
};

Expand Down Expand Up @@ -1284,6 +1291,49 @@ icmp6_print(netdissect_options *ndo,
/* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */
rpl_print(ndo, icmp6_code, dp->icmp6_data, length-sizeof(struct icmp6_hdr)+4);
break;
case ICMP6_EXTENDED_ECHO_REQUEST:
case ICMP6_EXTENDED_ECHO_REPLY:
ND_PRINT(", id %u, seq %u", GET_BE_U_2(dp->icmp6_id),
GET_U_1(dp->icmp6_xseq));
// The code below is largely identical to the same handling
// in print-icmp.c
if (ndo->ndo_vflag) {
int xinfo = GET_U_1(dp->icmp6_xinfo);
if ( icmp6_type == ICMP6_EXTENDED_ECHO_REQUEST ) {
ND_PRINT("\n\t%s Interface", xinfo & 1 ? "Local" : "Remote");
if (ICMP_EXT_EXTRACT_VERSION(GET_U_1(dp->icmp6_data + 4)) != ICMP_EXT_VERSION) {
nd_print_invalid(ndo);
} else {
// A single extended object. The extended header is not
// located at offset 128 in this case, so we can not use
// icmp_ext_checksum.
uint16_t sum = GET_BE_U_2(dp->icmp6_data + 6);
uint16_t len = GET_BE_U_2(dp->icmp6_data + 8);
// The checksum is over the extended header and the single
// object
len += 4;
struct cksum_vec vec[1];
vec[0].ptr = dp->icmp6_data + 4;
vec[0].len = len;
if (ND_TTEST_LEN(vec[0].ptr, vec[0].len)) {
ND_PRINT(", checksum 0x%04x (%scorrect), length %u",
sum,
in_cksum(vec, 1) ? "in" : "",
len);
}
print_icmp_multipart_ext_object(ndo, dp->icmp6_data + 8);
}
} else {
int state = ( xinfo & 0xe0 ) >> 5;
ND_PRINT("\n\tCode %d (%s), State %d (%s), active %d ipv4 %d ipv6 %d",
icmp6_code, tok2str(icmp_extended_echo_reply_code_str, "Unknown", icmp6_code),
state, tok2str(icmp_extended_echo_reply_state_str, "Unknown", state),
xinfo & 4 ? 1 : 0,
xinfo & 2 ? 1 : 0,
xinfo & 1 ? 1 : 0);
}
}
break;
default:
ND_PRINT(", length %u", length);
if (ndo->ndo_vflag <= 1)
Expand Down
2 changes: 2 additions & 0 deletions tests/TESTLIST
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ icmp_inft_name_length_zero icmp_inft_name_length_zero.pcap icmp_inft_name_length
rfc8335 rfc8335.pcap icmp-rfc8335.out
rfc8335-v rfc8335.pcap icmp-rfc8335-v.out -v
rfc8335-missing-bytes rfc8335-missing-bytes.pcap icmp-rfc8335-missing-bytes.out -v
icmp6-rfc8335 icmp6-rfc8335.pcap icmp6-rfc8335.out
icmp6-rfc8335-v icmp6-rfc8335.pcap icmp6-rfc8335-v.out -v

# ICMPv6
icmpv6 icmpv6.pcap icmpv6.out -vv
Expand Down
18 changes: 18 additions & 0 deletions tests/icmp6-rfc8335-v.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
1 05:10:17.314281 IP6 (flowlabel 0xf260b, hlim 255, next-header ICMPv6 (58) payload length: 28) fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b > fdfd:5c41:712d:d0aa:225:90ff:fea8:8686: [icmp6 sum ok] ICMP6, extended echo request, id 64353, seq 0
Local Interface, checksum 0xdcf4 (correct), length 12
Interface Identification Object (3), Class-Type: 2, length 8
Interface Index: 1
2 05:10:17.314546 IP6 (flowlabel 0x618d4, hlim 59, next-header ICMPv6 (58) payload length: 28) fdfd:5c41:712d:d0aa:225:90ff:fea8:8686 > fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b: [icmp6 sum ok] ICMP6, extended echo reply, id 64353, seq 0
Code 0 (No error), State 0 (Reserved), active 1 ipv4 1 ipv6 1
3 05:10:46.267725 IP6 (flowlabel 0xf260b, hlim 255, next-header ICMPv6 (58) payload length: 32) fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b > fdfd:5c41:712d:d0aa:225:90ff:fea8:8686: [icmp6 sum ok] ICMP6, extended echo request, id 64356, seq 0
Local Interface, checksum 0x2df1 (correct), length 16
Interface Identification Object (3), Class-Type: 1, length 12
Interface Name, length 8: enp2s0f0
4 05:10:46.267887 IP6 (flowlabel 0x618d4, hlim 59, next-header ICMPv6 (58) payload length: 32) fdfd:5c41:712d:d0aa:225:90ff:fea8:8686 > fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b: [icmp6 sum ok] ICMP6, extended echo reply, id 64356, seq 0
Code 0 (No error), State 0 (Reserved), active 1 ipv4 0 ipv6 0
5 05:11:07.324173 IP6 (flowlabel 0xf260b, hlim 255, next-header ICMPv6 (58) payload length: 32) fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b > fdfd:5c41:712d:d0aa:225:90ff:fea8:8686: [icmp6 sum ok] ICMP6, extended echo request, id 64359, seq 0
Local Interface, checksum 0x9eb5 (correct), length 16
Interface Identification Object (3), Class-Type: 1, length 12
Interface Name, length 8: george
6 05:11:07.324377 IP6 (flowlabel 0x618d4, hlim 59, next-header ICMPv6 (58) payload length: 32) fdfd:5c41:712d:d0aa:225:90ff:fea8:8686 > fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b: [icmp6 sum ok] ICMP6, extended echo reply, id 64359, seq 0
Code 2 (No Such Interface), State 0 (Reserved), active 0 ipv4 0 ipv6 0
6 changes: 6 additions & 0 deletions tests/icmp6-rfc8335.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
1 05:10:17.314281 IP6 fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b > fdfd:5c41:712d:d0aa:225:90ff:fea8:8686: ICMP6, extended echo request, id 64353, seq 0, length 28
2 05:10:17.314546 IP6 fdfd:5c41:712d:d0aa:225:90ff:fea8:8686 > fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b: ICMP6, extended echo reply, id 64353, seq 0, length 28
3 05:10:46.267725 IP6 fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b > fdfd:5c41:712d:d0aa:225:90ff:fea8:8686: ICMP6, extended echo request, id 64356, seq 0, length 32
4 05:10:46.267887 IP6 fdfd:5c41:712d:d0aa:225:90ff:fea8:8686 > fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b: ICMP6, extended echo reply, id 64356, seq 0, length 32
5 05:11:07.324173 IP6 fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b > fdfd:5c41:712d:d0aa:225:90ff:fea8:8686: ICMP6, extended echo request, id 64359, seq 0, length 32
6 05:11:07.324377 IP6 fdfd:5c41:712d:d0aa:225:90ff:fea8:8686 > fdfd:5c41:712d:d05a:d0dd:22ff:feac:5c6b: ICMP6, extended echo reply, id 64359, seq 0, length 32
Binary file added tests/icmp6-rfc8335.pcap
Binary file not shown.

0 comments on commit 8590ce9

Please sign in to comment.