]> The Tcpdump Group git mirrors - tcpdump/commitdiff
OpenFlow: Improve the common header dissection.
authorDenis Ovsienko <[email protected]>
Sun, 27 Sep 2020 22:07:40 +0000 (23:07 +0100)
committerDenis Ovsienko <[email protected]>
Mon, 28 Sep 2020 12:58:12 +0000 (13:58 +0100)
of_header_print() printed any version as "unknown", always printed the
type in hex only and printed the length with no remarks. If the header
was not good enough to proceed, openflow_print() would just print
"(invalid)" after it and be done with it.

Introduce of10_msgtype_str(). Rename of10_header_body_print() to
of10_message_print() and unburden it of all common header details. Add a
registry of all known OpenFlow version numbers. Merge of_header_print()
into openflow_print() and take the header apart one field at a time with
the captured and the declared lengths in mind, and indicate any anomalies
in version, type and length independently. Try to print the transaction
ID too before giving up on the header.

Among other changes, the header now shows the type as "unknown" when the
decoder does not know which types are valid for the version, and as
"invalid" when the type is definitely not valid for the version. Update
two tests.

openflow.h
print-openflow-1.0.c
print-openflow.c
tests/of10_p3295-vv.out
tests/of10_s4810-vvvv.out

index 0b89008ecef3ffaf231ca83a525b51d6633780b3..106a4809777ccbaefa8b41b9e32ff92cd49b3aca 100644 (file)
@@ -58,7 +58,14 @@ extern void of_data_print(netdissect_options *ndo,
        const u_char *, const u_int);
 
 /*
- * Routines to print packets for various versions of OpenFlow.
+ * Routines to handle various versions of OpenFlow.
  */
-extern void of10_header_body_print(netdissect_options *ndo,
-       const u_char *, const uint8_t, uint16_t, const uint32_t);
+extern void of10_message_print(netdissect_options *ndo,
+       const u_char *, uint16_t, const uint8_t);
+
+/*
+ * Use this instead of ofpt_str[] and OFPT_ constants because OpenFlow
+ * specifications define protocol encoding in C syntax, and different
+ * versions clash on many names, including the OFPT_ constants.
+ */
+extern const char * of10_msgtype_str(const uint8_t);
index 473a8dc31a9342bdac744f9a18a79ec523401b14..ed9c2b4ca88de0ae031215c625de0f97a703fe85 100644 (file)
@@ -682,6 +682,12 @@ static const struct tok bsn_onoff_str[] = {
        { 0, NULL },
 };
 
+/* [OF10] Section 5.1 */
+const char * of10_msgtype_str(const uint8_t type)
+{
+       return tok2str(ofpt_str, "invalid (0x%02x)", type);
+}
+
 static const char *
 vlan_str(const uint16_t vid)
 {
@@ -2070,17 +2076,15 @@ of10_error_print(netdissect_options *ndo,
 }
 
 void
-of10_header_body_print(netdissect_options *ndo,
-                       const u_char *cp, const uint8_t type,
-                       uint16_t len, const uint32_t xid)
+of10_message_print(netdissect_options *ndo,
+                   const u_char *cp, uint16_t len, const uint8_t type)
 {
        /*
         * Here "cp" and "len" stand for the message part beyond the common
-        * OpenFlow 1.0 header, if any. Add OF_HEADER_FIXLEN when printing the
-        * message header. Subtract OF_HEADER_FIXLEN from the type-specific
-        * lengths, which include the header length, when (and only when)
-        * validating the length in this function, which is the only one in
-        * this file that needs to know about OF_HEADER_FIXLEN.
+        * OpenFlow 1.0 header, if any. Subtract OF_HEADER_FIXLEN from the
+        * type-specific lengths, which include the header length, when (and
+        * only when) validating the length in this function. No other code
+        * in this file needs to take OF_HEADER_FIXLEN into account.
         *
         * Most message types are longer than just the header, and the length
         * constraints may be complex. When possible, validate the constraint
@@ -2088,11 +2092,6 @@ of10_header_body_print(netdissect_options *ndo,
         * begin the decoding and let the lower-layer function do any remaining
         * validation.
         */
-
-       /* [OF10] Section 5.1 */
-       ND_PRINT("\n\tversion 1.0, type %s, length %u, xid 0x%08x",
-                tok2str(ofpt_str, "invalid (0x%02x)", type),
-                OF_HEADER_FIXLEN + len, xid);
        switch (type) {
        /* OpenFlow header only. */
        case OFPT_FEATURES_REQUEST: /* [OF10] Section 5.3.1 */
index f6cd31ace99a77572920950261cf8acd38b892d9..fcc952592154b961c5ce05491dbe7e4a2041474d 100644 (file)
 
 
 #define OF_VER_1_0    0x01
+#define OF_VER_1_1    0x02
+#define OF_VER_1_2    0x03
+#define OF_VER_1_3    0x04
+#define OF_VER_1_4    0x05
+#define OF_VER_1_5    0x06
+
+static const struct tok ofver_str[] = {
+       { OF_VER_1_0,   "1.0" },
+       { OF_VER_1_1,   "1.1" },
+       { OF_VER_1_2,   "1.2" },
+       { OF_VER_1_3,   "1.3" },
+       { OF_VER_1_4,   "1.4" },
+       { OF_VER_1_5,   "1.5" },
+       { 0, NULL }
+};
 
 const struct tok onf_exp_str[] = {
        { ONF_EXP_ONF,               "ONF Extensions"                                  },
@@ -80,14 +95,6 @@ of_data_print(netdissect_options *ndo,
                ND_TCHECK_LEN(cp, len);
 }
 
-static void
-of_header_print(netdissect_options *ndo, const uint8_t version, const uint8_t type,
-                      const uint16_t length, const uint32_t xid)
-{
-       ND_PRINT("\n\tversion unknown (0x%02x), type 0x%02x, length %u, xid 0x%08x",
-              version, type, length, xid);
-}
-
 /* Print a TCP segment worth of OpenFlow messages presuming the segment begins
  * on a message boundary. */
 void
@@ -99,22 +106,40 @@ openflow_print(netdissect_options *ndo, const u_char *cp, u_int len)
                /* Print a single OpenFlow message. */
                uint8_t version, type;
                uint16_t length;
-               uint32_t xid;
+               void (*decoder)(struct netdissect_options *,
+                               const u_char *, u_int16_t, const uint8_t) = NULL;
 
-               if (len < OF_HEADER_FIXLEN)
-                       goto invalid;
                /* version */
                version = GET_U_1(cp);
                OF_FWD(1);
+               ND_PRINT("\n\tversion %s",
+                        tok2str(ofver_str, "unknown (0x%02x)", version));
                /* type */
+               if (len < 1)
+                       goto partial_header;
                type = GET_U_1(cp);
                OF_FWD(1);
+               switch (version) {
+               case OF_VER_1_0:
+                       ND_PRINT(", type %s", of10_msgtype_str(type));
+                       decoder = of10_message_print;
+                       break;
+               default:
+                       ND_PRINT(", type unknown (0x%02x)", type);
+               }
                /* length */
+               if (len < 2)
+                       goto partial_header;
                length = GET_BE_U_2(cp);
                OF_FWD(2);
+               ND_PRINT(", length %u%s", length,
+                        length < OF_HEADER_FIXLEN ? " (too short!)" : "");
                /* xid */
-               xid = GET_BE_U_4(cp);
+               if (len < 4)
+                       goto partial_header;
+               ND_PRINT(", xid 0x%08x", GET_BE_U_4(cp));
                OF_FWD(4);
+
                /*
                 * When a TCP packet can contain several protocol messages,
                 * and at the same time a protocol message can span several
@@ -141,29 +166,23 @@ openflow_print(netdissect_options *ndo, const u_char *cp, u_int len)
                 * the captured packet buffer end, but stay safe even when
                 * that's somehow not the case.)
                 */
-               if (length < OF_HEADER_FIXLEN) {
-                       of_header_print(ndo, version, type, length, xid);
+               if (length < OF_HEADER_FIXLEN)
                        goto invalid;
-               }
-               /*
-                * Decode known protocol versions further without printing the
-                * header (the type decoding is version-specific).
-                */
-               switch (version) {
-               case OF_VER_1_0:
-                       of10_header_body_print(ndo, cp, type,
-                                              length - OF_HEADER_FIXLEN, xid);
-                       break;
-               default:
-                       of_header_print(ndo, version, type, length, xid);
+
+               if (decoder != NULL)
+                       decoder(ndo, cp, length - OF_HEADER_FIXLEN, type);
+               else
                        ND_TCHECK_LEN(cp, length - OF_HEADER_FIXLEN);
-               }
                if (length - OF_HEADER_FIXLEN > len)
                        break;
                OF_FWD(length - OF_HEADER_FIXLEN);
        } /* while (len) */
        return;
 
+partial_header:
+       ND_PRINT(" (end of TCP payload)");
+       ND_TCHECK_LEN(cp, len);
+       return;
 invalid: /* fail the current packet */
        nd_print_invalid(ndo);
        ND_TCHECK_LEN(cp, len);
index e4039e82b47c9378ec826925bbe76cbb3fa65766..6e3dc91cfc8728d91e434418952144af021da457 100644 (file)
         match nw_proto 1 [|openflow]
    15  09:45:19.754510 IP (tos 0x0, ttl 64, id 784, offset 0, flags [DF], proto TCP (6), length 740)
     10.0.0.20.6633 > 10.0.0.50.35256: Flags [P.], cksum 0x171c (incorrect -> 0xdfee), seq 1549:2237, ack 2585, win 154, options [nop,nop,TS val 220958532 ecr 194889014], length 688: OpenFlow
-       version unknown (0x00), type 0x00, length 0, xid 0x0003000d (invalid)
+       version unknown (0x00), type unknown (0x00), length 0 (too short!), xid 0x0003000d (invalid)
    16  09:45:19.755256 IP (tos 0x0, ttl 64, id 55503, offset 0, flags [DF], proto TCP (6), length 52)
     10.0.0.50.35256 > 10.0.0.20.6633: Flags [.], cksum 0x9386 (correct), seq 2585, ack 1549, win 273, options [nop,nop,TS val 194889016 ecr 220958532], length 0
    17  09:45:19.755309 IP (tos 0x0, ttl 64, id 55504, offset 0, flags [DF], proto TCP (6), length 52)
     10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x733a), seq 2237, ack 9953, win 248, options [nop,nop,TS val 220958722 ecr 194889063], length 0
    54  09:45:19.945085 IP (tos 0x0, ttl 64, id 55532, offset 0, flags [DF], proto TCP (6), length 2680)
     10.0.0.50.35256 > 10.0.0.20.6633: Flags [P.], cksum 0x1eb0 (incorrect -> 0x561b), seq 9953:12581, ack 2237, win 364, options [nop,nop,TS val 194889063 ecr 220958721], length 2628: OpenFlow
-       version unknown (0x00), type 0x00, length 0, xid 0x00000000 (invalid)
+       version unknown (0x00), type unknown (0x00), length 0 (too short!), xid 0x00000000 (invalid)
    55  09:45:19.945117 IP (tos 0x0, ttl 64, id 796, offset 0, flags [DF], proto TCP (6), length 52)
     10.0.0.20.6633 > 10.0.0.50.35256: Flags [.], cksum 0x146c (incorrect -> 0x68cd), seq 2237, ack 12581, win 289, options [nop,nop,TS val 220958722 ecr 194889063], length 0
    56  09:45:19.945132 IP (tos 0x0, ttl 64, id 55534, offset 0, flags [DF], proto TCP (6), length 64)
index f19959fcf317bb1e7d2119f5fcb581dd3ff041e0..8ce8445fc8ebed7fdca52c5c17a2e368ea89729f 100644 (file)
         match dl_dst 00:11:22:33:00:15 [|openflow]
    20  12:51:39.554402 IP (tos 0x0, ttl 64, id 53104, offset 0, flags [DF], proto TCP (6), length 180)
     10.0.0.20.6633 > 10.0.0.81.56068: Flags [P.], cksum 0x150b (incorrect -> 0x8ec7), seq 4241:4369, ack 677, win 139, options [nop,nop,TS val 47836527 ecr 1], length 128: OpenFlow
-       version unknown (0x00), type 0x00, length 0, xid 0x00000000 (invalid)
+       version unknown (0x00), type unknown (0x00), length 0 (too short!), xid 0x00000000 (invalid)
    21  12:51:39.555118 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)
     10.0.0.81.56068 > 10.0.0.20.6633: Flags [.], cksum 0xfaa7 (correct), seq 677, ack 2873, win 952, options [nop,nop,TS val 1 ecr 47836527], length 0
    22  12:51:39.555156 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)
          duration_sec 0, duration_nsec 0, priority 65535, idle_timeout 0, hard_timeout 0, cookie 0x0000000000000025, packet_count 0 [|openflow]
    41  12:51:40.028159 IP (tos 0x0, ttl 64, id 53582, offset 0, flags [DF], proto TCP (6), length 1040)
     10.0.0.81.56068 > 10.0.0.20.6633: Flags [P.], cksum 0x395e (correct), seq 8113:9101, ack 4545, win 1035, options [nop,nop,TS val 2 ecr 47837000], length 988: OpenFlow
-       version unknown (0x00), type 0x00, length 0, xid 0x00000000 (invalid)
+       version unknown (0x00), type unknown (0x00), length 0 (too short!), xid 0x00000000 (invalid)
    42  12:51:40.028172 IP (tos 0x0, ttl 64, id 53111, offset 0, flags [DF], proto TCP (6), length 52)
     10.0.0.20.6633 > 10.0.0.81.56068: Flags [.], cksum 0x148b (incorrect -> 0xd387), seq 4641, ack 9101, win 302, options [nop,nop,TS val 47837000 ecr 2], length 0
    43  12:51:40.226408 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)