]> The Tcpdump Group git mirrors - tcpdump/commitdiff
ICMPv6: print RFC8335 PROBE extended echo/reply messages
authorBill Fenner <[email protected]>
Mon, 5 Feb 2024 05:13:09 +0000 (21:13 -0800)
committerfxlb <[email protected]>
Tue, 6 Aug 2024 07:34:48 +0000 (07:34 +0000)
The ICMP types are different, but everything else about
PROBE, including the RFC4884-based parsing, is the same,
so we share the implementation from print-icmp.c using the
new icmp.h.

Makefile.in
icmp.h [new file with mode: 0644]
print-icmp.c
print-icmp6.c
tests/TESTLIST
tests/icmp6-rfc8335-v.out [new file with mode: 0644]
tests/icmp6-rfc8335.out [new file with mode: 0644]
tests/icmp6-rfc8335.pcap [new file with mode: 0644]

index cad9e4bbe3e152a41887477b65f07b78009f977a..7046a020ca4085f3a61be7934b87f16a45d1ab62 100644 (file)
@@ -282,6 +282,7 @@ HDR = \
        getservent.h \
        gmpls.h \
        gre.h \
+       icmp.h \
        interface.h \
        ip.h \
        ip6.h \
diff --git a/icmp.h b/icmp.h
new file mode 100644 (file)
index 0000000..1e7b12e
--- /dev/null
+++ b/icmp.h
@@ -0,0 +1,34 @@
+/*
+ * 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 and functions to be shared between ICMP and ICMPv6 */
+
+/*
+ * RFC8335 - PROBE
+ */
+void
+print_icmp_rfc8335(netdissect_options *, uint8_t, int, uint8_t, const uint8_t *);
+
+#endif /* netdissect_icmp_h */
+
index b4b50ea4caf688909d8c08432f05df21cfecc4ce..771cb6e8a7e129d8cd3b459241ff67d340187092 100644 (file)
@@ -34,6 +34,7 @@
 #include "extract.h"
 
 #include "ip.h"
+#include "icmp.h"
 #include "udp.h"
 #include "ipproto.h"
 #include "mpls.h"
@@ -584,6 +585,44 @@ print_icmp_multipart_ext_object(netdissect_options *ndo, const uint8_t *obj_tptr
        return obj_tlen + sizeof(struct icmp_multipart_ext_object_header_t);
 }
 
+void
+print_icmp_rfc8335(netdissect_options *ndo, uint8_t xinfo, int isrequest, uint8_t icmp_code, const uint8_t *data) {
+       struct cksum_vec vec[1];
+
+       if (isrequest) {
+               ND_PRINT("\n\t%s Interface", xinfo & 1 ? "Local" : "Remote");
+               if (ICMP_EXT_EXTRACT_VERSION(GET_U_1(data)) != 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(data + 2);
+                   uint16_t len = GET_BE_U_2(data + 4);
+                   // The checksum is over the extended header and the single
+                   // object
+                   len += 4;
+                   vec[0].ptr = data;
+                   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, data + 4);
+               }
+       } else {
+                   int state = ( xinfo & 0xe0 ) >> 5;
+                   ND_PRINT("\n\tCode %d (%s), State %d (%s), active %d ipv4 %d ipv6 %d",
+                           icmp_code, tok2str(icmp_extended_echo_reply_code_str, "Unknown", icmp_code),
+                           state, tok2str(icmp_extended_echo_reply_state_str, "Unknown", state),
+                           xinfo & 4 ? 1 : 0,
+                           xinfo & 2 ? 1 : 0,
+                           xinfo & 1 ? 1 : 0);
+       }
+}
+
 void
 icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen,
            int fragmented)
@@ -1036,44 +1075,9 @@ icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen,
         }
 
        if (ndo->ndo_vflag >= 1 && ICMP_EXTENDED_ECHO_TYPE(icmp_type)) {
-           int xinfo = GET_U_1(dp->icmp_xinfo);
-           switch (icmp_type) {
-               case ICMP_EXTENDED_ECHO_REQUEST:
-                   ND_PRINT("\n\t%s Interface", xinfo & 1 ? "Local" : "Remote");
-                   if (ICMP_EXT_EXTRACT_VERSION(GET_U_1(dp->icmp_data)) != 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->icmp_data + 2);
-                       uint16_t len = GET_BE_U_2(dp->icmp_data + 4);
-                       // The checksum is over the extended header and the single
-                       // object
-                       len += 4;
-                       vec[0].ptr = dp->icmp_data;
-                       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->icmp_data + 4);
-                   }
-                   break;
-               case ICMP_EXTENDED_ECHO_REPLY:
-                   {
-                   int state = ( xinfo & 0xe0 ) >> 5;
-                   ND_PRINT("\n\tCode %d (%s), State %d (%s), active %d ipv4 %d ipv6 %d",
-                           icmp_code, tok2str(icmp_extended_echo_reply_code_str, "Unknown", icmp_code),
-                           state, tok2str(icmp_extended_echo_reply_state_str, "Unknown", state),
-                           xinfo & 4 ? 1 : 0,
-                           xinfo & 2 ? 1 : 0,
-                           xinfo & 1 ? 1 : 0);
-                   }
-                   break;
-           }
+           uint8_t xinfo = GET_U_1(dp->icmp_xinfo);
+           // RFC8335 printing is shared between ICMP and ICMPv6
+           print_icmp_rfc8335( ndo, xinfo, icmp_type == ICMP_EXTENDED_ECHO_REQUEST, icmp_code, dp->icmp_data );
        }
 
        return;
index 86083f58a1b2a1531eeaf14b7c87891866a7de70..5ab6a46e770aaebea5c1bb18fe1504b30ecdcc32 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "ip6.h"
 #include "ipproto.h"
+#include "icmp.h"
 
 #include "udp.h"
 #include "ah.h"
@@ -92,6 +93,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 */
@@ -130,6 +133,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 */
@@ -666,6 +671,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 }
 };
 
@@ -1283,6 +1290,17 @@ 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 content of the message is the same as ICMP, so use the
+               // function defined in print-icmp.c
+               if (ndo->ndo_vflag) {
+                       uint8_t xinfo = GET_U_1(dp->icmp6_xinfo);
+                       print_icmp_rfc8335(ndo, xinfo, icmp6_type == ICMP6_EXTENDED_ECHO_REQUEST, icmp6_code, dp->icmp6_data + 4);
+               }
+               break;
        default:
                 ND_PRINT(", length %u", length);
                 if (ndo->ndo_vflag <= 1)
index 47d6dfa0cc52b08e55716ae2039388f28eaaefa2..e1730a933dcebf658d3b24a69f4ae70079fc4ec7 100644 (file)
@@ -224,6 +224,8 @@ icmp_inft_name_length_zero icmp_inft_name_length_zero.pcap icmp_inft_name_length
 icmp-rfc8335   icmp-rfc8335.pcap       icmp-rfc8335.out
 icmp-rfc8335-v icmp-rfc8335.pcap       icmp-rfc8335-v.out      -v
 icmp-rfc8335-missing-bytes     icmp-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
diff --git a/tests/icmp6-rfc8335-v.out b/tests/icmp6-rfc8335-v.out
new file mode 100644 (file)
index 0000000..dcaf3ec
--- /dev/null
@@ -0,0 +1,18 @@
+    1  2024-02-05 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  2024-02-05 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  2024-02-05 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  2024-02-05 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  2024-02-05 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  2024-02-05 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
diff --git a/tests/icmp6-rfc8335.out b/tests/icmp6-rfc8335.out
new file mode 100644 (file)
index 0000000..f5e7b7f
--- /dev/null
@@ -0,0 +1,6 @@
+    1  2024-02-05 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  2024-02-05 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  2024-02-05 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  2024-02-05 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  2024-02-05 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  2024-02-05 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
diff --git a/tests/icmp6-rfc8335.pcap b/tests/icmp6-rfc8335.pcap
new file mode 100644 (file)
index 0000000..30ba2b4
Binary files /dev/null and b/tests/icmp6-rfc8335.pcap differ