]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-openflow-1.0.c
OpenFlow 1.3: Add initial partial support.
[tcpdump] / print-openflow-1.0.c
index 567a89533ff73068b9452a03d798f9dd58fca21c..ed9c2b4ca88de0ae031215c625de0f97a703fe85 100644 (file)
@@ -456,6 +456,7 @@ static const struct tok ofpet_str[] = {
        { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
        { 0, NULL }
 };
+#define OFPET_MAX OFPET_QUEUE_OP_FAILED /* for of10_error_print() */
 
 #define OFPHFC_INCOMPATIBLE 0x0000U
 #define OFPHFC_EPERM        0x0001U
@@ -543,10 +544,6 @@ static const struct tok ofpqofc_str[] = {
        { 0, NULL }
 };
 
-static const struct tok empty_str[] = {
-       { 0, NULL }
-};
-
 /* lengths (fixed or minimal) of particular protocol structures */
 #define OF_SWITCH_CONFIG_FIXLEN               12
 #define OF_PHY_PORT_FIXLEN                    48
@@ -685,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)
 {
@@ -724,20 +727,6 @@ of10_bitmap_print(netdissect_options *ndo,
        ND_PRINT((v & u) ? ") (bogus)" : ")");
 }
 
-static void
-of10_data_print(netdissect_options *ndo,
-                const u_char *cp, const u_int len)
-{
-       if (len == 0)
-               return;
-       /* data */
-       ND_PRINT("\n\t data (%u octets)", len);
-       if (ndo->ndo_vflag >= 2)
-               hex_and_ascii_print(ndo, "\n\t  ", cp, len);
-       else
-               ND_TCHECK_LEN(cp, len);
-}
-
 static void
 of10_bsn_message_print(netdissect_options *ndo,
                        const u_char *cp, u_int len)
@@ -998,7 +987,7 @@ of10_vendor_action_print(netdissect_options *ndo,
        /* data */
        decoder =
                vendor == OUI_BSN         ? of10_bsn_actions_print         :
-               of10_data_print;
+               of_data_print;
        decoder(ndo, cp, len);
        return;
 
@@ -1023,7 +1012,7 @@ of10_vendor_message_print(netdissect_options *ndo,
        /* data */
        decoder =
                vendor == OUI_BSN         ? of10_bsn_message_print         :
-               of10_data_print;
+               of_data_print;
        decoder(ndo, cp, len);
        return;
 
@@ -1046,7 +1035,7 @@ of10_vendor_data_print(netdissect_options *ndo,
        OF_FWD(4);
        ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
        /* data */
-       of10_data_print(ndo, cp, len);
+       of_data_print(ndo, cp, len);
        return;
 
 invalid: /* skip the undersized data */
@@ -2060,41 +2049,42 @@ static void
 of10_error_print(netdissect_options *ndo,
                  const u_char *cp, u_int len)
 {
-       uint16_t type;
-       const struct tok *code_str;
+       uint16_t type, code;
+       const struct tok *code_str[OFPET_MAX + 1] = {
+               /* [OFPET_HELLO_FAILED   ] = */ ofphfc_str,
+               /* [OFPET_BAD_REQUEST    ] = */ ofpbrc_str,
+               /* [OFPET_BAD_ACTION     ] = */ ofpbac_str,
+               /* [OFPET_FLOW_MOD_FAILED] = */ ofpfmfc_str,
+               /* [OFPET_PORT_MOD_FAILED] = */ ofppmfc_str,
+               /* [OFPET_QUEUE_OP_FAILED] = */ ofpqofc_str,
+       };
 
        /* type */
        type = GET_BE_U_2(cp);
        OF_FWD(2);
        ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
        /* code */
-       code_str =
-               type == OFPET_HELLO_FAILED    ? ofphfc_str  :
-               type == OFPET_BAD_REQUEST     ? ofpbrc_str  :
-               type == OFPET_BAD_ACTION      ? ofpbac_str  :
-               type == OFPET_FLOW_MOD_FAILED ? ofpfmfc_str :
-               type == OFPET_PORT_MOD_FAILED ? ofppmfc_str :
-               type == OFPET_QUEUE_OP_FAILED ? ofpqofc_str :
-               empty_str;
-       ND_PRINT(", code %s",
-                tok2str(code_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
+       code = GET_BE_U_2(cp);
        OF_FWD(2);
+       if (type <= OFPET_MAX && code_str[type] != NULL)
+               ND_PRINT(", code %s",
+                        tok2str(code_str[type], "invalid (0x%04x)", code));
+       else
+               ND_PRINT(", code invalid (0x%04x)", code);
        /* data */
-       of10_data_print(ndo, cp, len);
+       of_data_print(ndo, cp, len);
 }
 
 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
@@ -2102,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 */
@@ -2115,7 +2100,7 @@ of10_header_body_print(netdissect_options *ndo,
        case OFPT_BARRIER_REPLY: /* ibid */
                if (len)
                        goto invalid;
-               break;
+               return;
 
        /* OpenFlow header and fixed-size message body. */
        case OFPT_SET_CONFIG: /* [OF10] Section 5.3.2 */
@@ -2123,7 +2108,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len != OF_SWITCH_CONFIG_FIXLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                /* flags */
                ND_PRINT("\n\t flags %s",
                         tok2str(ofp_config_str, "invalid (0x%04x)",
@@ -2136,16 +2121,16 @@ of10_header_body_print(netdissect_options *ndo,
                if (len != OF_PORT_MOD_FIXLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_port_mod_print(ndo, cp);
                return;
        case OFPT_QUEUE_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.4 */
                if (len != OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                /* port */
-               ND_PRINT("\n\t port_no %s",
+               ND_PRINT("\n\t port %s",
                         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
                OF_FWD(2);
                /* pad */
@@ -2156,14 +2141,14 @@ of10_header_body_print(netdissect_options *ndo,
                if (len != OF_FLOW_REMOVED_FIXLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_flow_removed_print(ndo, cp);
                return;
        case OFPT_PORT_STATUS: /* [OF10] Section 5.4.3 */
                if (len != OF_PORT_STATUS_FIXLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                /* reason */
                ND_PRINT("\n\t reason %s",
                         tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp)));
@@ -2180,7 +2165,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_FEATURES_REPLY_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_features_reply_print(ndo, cp, len);
                return;
 
@@ -2189,8 +2174,8 @@ of10_header_body_print(netdissect_options *ndo,
        case OFPT_ECHO_REQUEST: /* [OF10] Section 5.5.2 */
        case OFPT_ECHO_REPLY: /* [OF10] Section 5.5.3 */
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
-               of10_data_print(ndo, cp, len);
+                       break;
+               of_data_print(ndo, cp, len);
                return;
 
        /* OpenFlow header, fixed-size message body and variable-size data. */
@@ -2198,7 +2183,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_ERROR_MSG_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_error_print(ndo, cp, len);
                return;
        case OFPT_VENDOR:
@@ -2206,7 +2191,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_VENDOR_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_vendor_message_print(ndo, cp, len);
                return;
        case OFPT_PACKET_IN:
@@ -2214,7 +2199,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_PACKET_IN_MINLEN - 2 - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_packet_in_print(ndo, cp, len);
                return;
 
@@ -2225,7 +2210,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_STATS_REQUEST_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_stats_request_print(ndo, cp, len);
                return;
 
@@ -2237,7 +2222,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_STATS_REPLY_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_stats_reply_print(ndo, cp, len);
                return;
 
@@ -2246,7 +2231,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_PACKET_OUT_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_packet_out_print(ndo, cp, len);
                return;
 
@@ -2255,7 +2240,7 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_FLOW_MOD_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                of10_flow_mod_print(ndo, cp, len);
                return;
 
@@ -2264,9 +2249,9 @@ of10_header_body_print(netdissect_options *ndo,
                if (len < OF_QUEUE_GET_CONFIG_REPLY_MINLEN - OF_HEADER_FIXLEN)
                        goto invalid;
                if (ndo->ndo_vflag < 1)
-                       goto next_message;
+                       break;
                /* port */
-               ND_PRINT("\n\t port_no %s",
+               ND_PRINT("\n\t port %s",
                         tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
                OF_FWD(2);
                /* pad */
@@ -2276,10 +2261,14 @@ of10_header_body_print(netdissect_options *ndo,
                of10_queues_print(ndo, cp, len);
                return;
        } /* switch (type) */
-       goto next_message;
+       /*
+        * Not a recognised type or did not print the details, fall back to
+        * a bounds check.
+        */
+       ND_TCHECK_LEN(cp, len);
+       return;
 
 invalid: /* skip the message body */
        nd_print_invalid(ndo);
-next_message:
        ND_TCHECK_LEN(cp, len);
 }