X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/140fac9cf1cc24d15f47d8edf06277781301e8cd..refs/pull/1034/head:/print-openflow-1.0.c?ds=inline diff --git a/print-openflow-1.0.c b/print-openflow-1.0.c index 9001476f..00c4fdd3 100644 --- a/print-openflow-1.0.c +++ b/print-openflow-1.0.c @@ -97,31 +97,7 @@ #define OFPT_BARRIER_REPLY 0x13 #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14 #define OFPT_QUEUE_GET_CONFIG_REPLY 0x15 -static const struct tok ofpt_str[] = { - { OFPT_HELLO, "HELLO" }, - { OFPT_ERROR, "ERROR" }, - { OFPT_ECHO_REQUEST, "ECHO_REQUEST" }, - { OFPT_ECHO_REPLY, "ECHO_REPLY" }, - { OFPT_VENDOR, "VENDOR" }, - { OFPT_FEATURES_REQUEST, "FEATURES_REQUEST" }, - { OFPT_FEATURES_REPLY, "FEATURES_REPLY" }, - { OFPT_GET_CONFIG_REQUEST, "GET_CONFIG_REQUEST" }, - { OFPT_GET_CONFIG_REPLY, "GET_CONFIG_REPLY" }, - { OFPT_SET_CONFIG, "SET_CONFIG" }, - { OFPT_PACKET_IN, "PACKET_IN" }, - { OFPT_FLOW_REMOVED, "FLOW_REMOVED" }, - { OFPT_PORT_STATUS, "PORT_STATUS" }, - { OFPT_PACKET_OUT, "PACKET_OUT" }, - { OFPT_FLOW_MOD, "FLOW_MOD" }, - { OFPT_PORT_MOD, "PORT_MOD" }, - { OFPT_STATS_REQUEST, "STATS_REQUEST" }, - { OFPT_STATS_REPLY, "STATS_REPLY" }, - { OFPT_BARRIER_REQUEST, "BARRIER_REQUEST" }, - { OFPT_BARRIER_REPLY, "BARRIER_REPLY" }, - { OFPT_QUEUE_GET_CONFIG_REQUEST, "QUEUE_GET_CONFIG_REQUEST" }, - { OFPT_QUEUE_GET_CONFIG_REPLY, "QUEUE_GET_CONFIG_REPLY" }, - { 0, NULL } -}; +#define OFPT_MAX OFPT_QUEUE_GET_CONFIG_REPLY #define OFPPC_PORT_DOWN (1U <<0) #define OFPPC_NO_STP (1U <<1) @@ -342,7 +318,6 @@ static const struct tok ofp_capabilities_bm[] = { #define OFPC_FRAG_NORMAL 0x0000U #define OFPC_FRAG_DROP 0x0001U #define OFPC_FRAG_REASM 0x0002U -#define OFPC_FRAG_MASK 0x0003U static const struct tok ofp_config_str[] = { { OFPC_FRAG_NORMAL, "FRAG_NORMAL" }, { OFPC_FRAG_DROP, "FRAG_DROP" }, @@ -697,12 +672,6 @@ 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) { @@ -730,12 +699,12 @@ of10_bsn_message_print(netdissect_options *ndo, { uint32_t subtype; - if (len < 4) - goto invalid; + ND_PRINT("\n\t"); + ND_ICHECK_U(len, <, 4); /* subtype */ subtype = GET_BE_U_4(cp); OF_FWD(4); - ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype)); + ND_PRINT(" subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype)); switch (subtype) { case BSN_GET_IP_MASK_REQUEST: /* @@ -750,8 +719,7 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len != 8) - goto invalid; + ND_ICHECK_U(len, !=, 8); /* index */ ND_PRINT(", index %u", GET_U_1(cp)); OF_FWD(1); @@ -773,8 +741,7 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len != 8) - goto invalid; + ND_ICHECK_U(len, !=, 8); /* index */ ND_PRINT(", index %u", GET_U_1(cp)); OF_FWD(1); @@ -796,8 +763,7 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len != 4) - goto invalid; + ND_ICHECK_U(len, !=, 4); /* report_mirror_ports */ ND_PRINT(", report_mirror_ports %s", tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp))); @@ -819,8 +785,7 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len) - goto invalid; + ND_ICHECK_U(len, !=, 0); break; case BSN_VIRTUAL_PORT_REMOVE_REQUEST: /* @@ -833,8 +798,7 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len != 4) - goto invalid; + ND_ICHECK_U(len, !=, 4); /* vport_no */ ND_PRINT(", vport_no %u", GET_BE_U_4(cp)); break; @@ -851,14 +815,13 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+-------- * */ - if (len < 4) - goto invalid; + ND_ICHECK_U(len, <, 4); /* service */ ND_PRINT(", service %u", GET_BE_U_4(cp)); OF_FWD(4); /* data */ ND_PRINT(", data '"); - nd_printn(ndo, cp, len, NULL); + nd_printjn(ndo, cp, len); ND_PRINT("'"); break; case BSN_SHELL_OUTPUT: @@ -875,7 +838,7 @@ of10_bsn_message_print(netdissect_options *ndo, /* already checked that len >= 4 */ /* data */ ND_PRINT(", data '"); - nd_printn(ndo, cp, len, NULL); + nd_printjn(ndo, cp, len); ND_PRINT("'"); break; case BSN_SHELL_STATUS: @@ -889,8 +852,7 @@ of10_bsn_message_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len != 4) - goto invalid; + ND_ICHECK_U(len, !=, 4); /* status */ ND_PRINT(", status 0x%08x", GET_BE_U_4(cp)); break; @@ -910,12 +872,12 @@ of10_bsn_actions_print(netdissect_options *ndo, { uint32_t subtype, vlan_tag; - if (len < 4) - goto invalid; + ND_PRINT("\n\t "); + ND_ICHECK_U(len, <, 4); /* subtype */ subtype = GET_BE_U_4(cp); OF_FWD(4); - ND_PRINT("\n\t subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype)); + ND_PRINT(" subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype)); switch (subtype) { case BSN_ACTION_MIRROR: /* @@ -932,8 +894,7 @@ of10_bsn_actions_print(netdissect_options *ndo, * +---------------+---------------+---------------+---------------+ * */ - if (len != 12) - goto invalid; + ND_ICHECK_U(len, !=, 12); /* dest_port */ ND_PRINT(", dest_port %u", GET_BE_U_4(cp)); OF_FWD(4); @@ -975,8 +936,7 @@ of10_vendor_action_print(netdissect_options *ndo, uint32_t vendor; void (*decoder)(netdissect_options *, const u_char *, u_int); - if (len < 4) - goto invalid; + ND_ICHECK_U(len, <, 4); /* vendor */ vendor = GET_BE_U_4(cp); OF_FWD(4); @@ -1019,8 +979,7 @@ of10_vendor_data_print(netdissect_options *ndo, { uint32_t vendor; - if (len < 4) - goto invalid; + ND_ICHECK_U(len, <, 4); /* vendor */ vendor = GET_BE_U_4(cp); OF_FWD(4); @@ -1048,7 +1007,18 @@ of10_packet_data_print(netdissect_options *ndo, } ndo->ndo_vflag -= 3; ND_PRINT(", frame decoding below\n"); + /* + * The encapsulated Ethernet frame is not necessarily the last + * data of this packet (i.e. there may be more OpenFlow messages + * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in + * which case the current (outer) packet's snapshot end is not + * what ether_print() needs to decode an Ethernet frame nested in + * the middle of a TCP payload. + */ + const u_char *snapend_save = ndo->ndo_snapend; + ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend); ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL); + ndo->ndo_snapend = snapend_save; ndo->ndo_vflag += 3; } @@ -1068,7 +1038,7 @@ of10_phy_port_print(netdissect_options *ndo, cp += MAC_ADDR_LEN; /* name */ ND_PRINT(", name '"); - (void)nd_print(ndo, cp, cp + OFP_MAX_PORT_NAME_LEN); + nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN); ND_PRINT("'"); cp += OFP_MAX_PORT_NAME_LEN; @@ -1118,18 +1088,18 @@ of10_queue_props_print(netdissect_options *ndo, uint16_t property, plen; u_char plen_bogus = 0, skip = 0; - if (len < OF_QUEUE_PROP_MINLEN) - goto invalid; + ND_PRINT("\n\t "); + ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_PROP_MINLEN); /* property */ property = GET_BE_U_2(cp); OF_FWD(2); - ND_PRINT("\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property)); + ND_PRINT(" property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property)); /* len */ plen = GET_BE_U_2(cp); OF_FWD(2); ND_PRINT(", len %u", plen); - if (plen < OF_QUEUE_PROP_MINLEN || plen > len + 4) - goto invalid; + ND_ICHECKMSG_U("property length", plen, <, OF_QUEUE_PROP_MINLEN); + ND_ICHECKMSG_U("property length", plen, >, len + 4); /* pad */ /* Sometimes the last field, check bounds. */ OF_CHK_FWD(4); @@ -1184,17 +1154,17 @@ of10_queues_print(netdissect_options *ndo, while (len) { uint16_t desclen; - if (len < OF_PACKET_QUEUE_MINLEN) - goto invalid; + ND_PRINT("\n\t "); + ND_ICHECKMSG_U("remaining length", len, <, OF_PACKET_QUEUE_MINLEN); /* queue_id */ - ND_PRINT("\n\t queue_id %u", GET_BE_U_4(cp)); + ND_PRINT(" queue_id %u", GET_BE_U_4(cp)); OF_FWD(4); /* len */ desclen = GET_BE_U_2(cp); OF_FWD(2); ND_PRINT(", len %u", desclen); - if (desclen < OF_PACKET_QUEUE_MINLEN || desclen > len + 6) - goto invalid; + ND_ICHECKMSG_U("prop. desc. length", desclen, <, OF_PACKET_QUEUE_MINLEN); + ND_ICHECKMSG_U("prop. desc. length", desclen, >, len + 6); /* pad */ /* Sometimes the last field, check bounds. */ OF_CHK_FWD(2); @@ -1309,12 +1279,12 @@ of10_actions_print(netdissect_options *ndo, uint16_t type, alen, output_port; u_char alen_bogus = 0, skip = 0; - if (len < OF_ACTION_MINLEN) - goto invalid; + ND_PRINT("%saction", pfx); + ND_ICHECKMSG_U("remaining length", len, <, OF_ACTION_MINLEN); /* type */ type = GET_BE_U_2(cp); OF_FWD(2); - ND_PRINT("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type)); + ND_PRINT(" type %s", tok2str(ofpat_str, "invalid (0x%04x)", type)); /* length */ alen = GET_BE_U_2(cp); OF_FWD(2); @@ -1327,8 +1297,8 @@ of10_actions_print(netdissect_options *ndo, */ /* On action size underrun/overrun skip the rest of the action list. */ - if (alen < OF_ACTION_MINLEN || alen > len + 4) - goto invalid; + ND_ICHECK_U(alen, <, OF_ACTION_MINLEN); + ND_ICHECK_U(alen, >, len + 4); /* * After validating the basic length constraint it will be safe * to skip the current action if the action size is not valid @@ -1487,8 +1457,7 @@ of10_features_reply_print(netdissect_options *ndo, OF_FWD(4); /* ports */ while (len) { - if (len < OF_PHY_PORT_FIXLEN) - goto invalid; + ND_ICHECKMSG_U("\n\t port def. length", len, <, OF_PHY_PORT_FIXLEN); of10_phy_port_print(ndo, cp); OF_FWD(OF_PHY_PORT_FIXLEN); } @@ -1572,15 +1541,15 @@ of10_port_mod_print(netdissect_options *ndo, ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); cp += MAC_ADDR_LEN; /* config */ - ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); + ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); cp += 4; /* mask */ - ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp)); + ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp)); of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); cp += 4; /* advertise */ - ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp)); + ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp)); of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); cp += 4; /* pad */ @@ -1636,13 +1605,11 @@ of10_stats_request_print(netdissect_options *ndo, switch(type) { case OFPST_DESC: case OFPST_TABLE: - if (len) - goto invalid; + ND_ICHECK_U(len, !=, 0); return; case OFPST_FLOW: case OFPST_AGGREGATE: - if (len != OF_FLOW_STATS_REQUEST_FIXLEN) - goto invalid; + ND_ICHECK_U(len, !=, OF_FLOW_STATS_REQUEST_FIXLEN); /* match */ of10_match_print(ndo, "\n\t ", cp); OF_FWD(OF_MATCH_FIXLEN); @@ -1657,8 +1624,7 @@ of10_stats_request_print(netdissect_options *ndo, tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); return; case OFPST_PORT: - if (len != OF_PORT_STATS_REQUEST_FIXLEN) - goto invalid; + ND_ICHECK_U(len, !=, OF_PORT_STATS_REQUEST_FIXLEN); /* port_no */ ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); @@ -1668,8 +1634,7 @@ of10_stats_request_print(netdissect_options *ndo, OF_CHK_FWD(6); return; case OFPST_QUEUE: - if (len != OF_QUEUE_STATS_REQUEST_FIXLEN) - goto invalid; + ND_ICHECK_U(len, !=, OF_QUEUE_STATS_REQUEST_FIXLEN); /* port_no */ ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); @@ -1696,31 +1661,31 @@ static void of10_desc_stats_reply_print(netdissect_options *ndo, const u_char *cp, u_int len) { - if (len != OF_DESC_STATS_REPLY_FIXLEN) - goto invalid; + ND_PRINT("\n\t "); + ND_ICHECK_U(len, !=, OF_DESC_STATS_REPLY_FIXLEN); /* mfr_desc */ - ND_PRINT("\n\t mfr_desc '"); - (void)nd_print(ndo, cp, cp + DESC_STR_LEN); + ND_PRINT(" mfr_desc '"); + nd_printjnp(ndo, cp, DESC_STR_LEN); ND_PRINT("'"); OF_FWD(DESC_STR_LEN); /* hw_desc */ ND_PRINT("\n\t hw_desc '"); - (void)nd_print(ndo, cp, cp + DESC_STR_LEN); + nd_printjnp(ndo, cp, DESC_STR_LEN); ND_PRINT("'"); OF_FWD(DESC_STR_LEN); /* sw_desc */ ND_PRINT("\n\t sw_desc '"); - (void)nd_print(ndo, cp, cp + DESC_STR_LEN); + nd_printjnp(ndo, cp, DESC_STR_LEN); ND_PRINT("'"); OF_FWD(DESC_STR_LEN); /* serial_num */ ND_PRINT("\n\t serial_num '"); - (void)nd_print(ndo, cp, cp + SERIAL_NUM_LEN); + nd_printjnp(ndo, cp, SERIAL_NUM_LEN); ND_PRINT("'"); OF_FWD(SERIAL_NUM_LEN); /* dp_desc */ ND_PRINT("\n\t dp_desc '"); - (void)nd_print(ndo, cp, cp + DESC_STR_LEN); + nd_printjnp(ndo, cp, DESC_STR_LEN); ND_PRINT("'"); return; @@ -1737,13 +1702,13 @@ of10_flow_stats_reply_print(netdissect_options *ndo, while (len) { uint16_t entry_len; - if (len < OF_FLOW_STATS_REPLY_MINLEN) - goto invalid; + ND_PRINT("\n\t"); + ND_ICHECKMSG_U("remaining length", len, <, OF_FLOW_STATS_REPLY_MINLEN); /* length */ entry_len = GET_BE_U_2(cp); - ND_PRINT("\n\t length %u", entry_len); - if (entry_len < OF_FLOW_STATS_REPLY_MINLEN || entry_len > len) - goto invalid; + ND_PRINT(" length %u", entry_len); + ND_ICHECK_U(entry_len, <, OF_FLOW_STATS_REPLY_MINLEN); + ND_ICHECK_U(entry_len, >, len); OF_FWD(2); /* table_id */ ND_PRINT(", table_id %s", @@ -1796,10 +1761,10 @@ static void of10_aggregate_stats_reply_print(netdissect_options *ndo, const u_char *cp, u_int len) { - if (len != OF_AGGREGATE_STATS_REPLY_FIXLEN) - goto invalid; + ND_PRINT("\n\t"); + ND_ICHECKMSG_U("remaining length", len, !=, OF_AGGREGATE_STATS_REPLY_FIXLEN); /* packet_count */ - ND_PRINT("\n\t packet_count %" PRIu64, GET_BE_U_8(cp)); + ND_PRINT(" packet_count %" PRIu64, GET_BE_U_8(cp)); OF_FWD(8); /* byte_count */ ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); @@ -1823,17 +1788,17 @@ of10_table_stats_reply_print(netdissect_options *ndo, const u_char *cp, u_int len) { while (len) { - if (len < OF_TABLE_STATS_REPLY_FIXLEN) - goto invalid; + ND_PRINT("\n\t"); + ND_ICHECKMSG_U("remaining length", len, <, OF_TABLE_STATS_REPLY_FIXLEN); /* table_id */ - ND_PRINT("\n\t table_id %s", + ND_PRINT(" table_id %s", tok2str(tableid_str, "%u", GET_U_1(cp))); OF_FWD(1); /* pad */ OF_FWD(3); /* name */ ND_PRINT(", name '"); - (void)nd_print(ndo, cp, cp + OFP_MAX_TABLE_NAME_LEN); + nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN); ND_PRINT("'"); OF_FWD(OFP_MAX_TABLE_NAME_LEN); /* wildcards */ @@ -1866,10 +1831,10 @@ of10_port_stats_reply_print(netdissect_options *ndo, const u_char *cp, u_int len) { while (len) { - if (len < OF_PORT_STATS_REPLY_FIXLEN) - goto invalid; + ND_PRINT("\n\t "); + ND_ICHECKMSG_U("remaining length", len, <, OF_PORT_STATS_REPLY_FIXLEN); /* port_no */ - ND_PRINT("\n\t port_no %s", + ND_PRINT(" port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); OF_FWD(2); if (ndo->ndo_vflag < 2) { @@ -1928,10 +1893,10 @@ of10_queue_stats_reply_print(netdissect_options *ndo, const u_char *cp, u_int len) { while (len) { - if (len < OF_QUEUE_STATS_REPLY_FIXLEN) - goto invalid; + ND_PRINT("\n\t "); + ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_STATS_REPLY_FIXLEN); /* port_no */ - ND_PRINT("\n\t port_no %s", + ND_PRINT(" port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); OF_FWD(2); /* pad */ @@ -2005,9 +1970,9 @@ of10_packet_out_print(netdissect_options *ndo, OF_FWD(2); /* actions_len */ actions_len = GET_BE_U_2(cp); + ND_PRINT(", actions_len %u", actions_len); OF_FWD(2); - if (actions_len > len) - goto invalid; + ND_ICHECK_U(actions_len, >, len); /* actions */ of10_actions_print(ndo, "\n\t ", cp, actions_len); OF_FWD(actions_len); @@ -2127,169 +2092,191 @@ of10_error_print(netdissect_options *ndo, of_data_print(ndo, cp, len); } -void -of10_message_print(netdissect_options *ndo, - const u_char *cp, uint16_t len, const uint8_t type) -{ +static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = { /* - * Here "cp" and "len" stand for the message part beyond the common - * OpenFlow 1.0 header, if any. - * - * Most message types are longer than just the header, and the length - * constraints may be complex. When possible, validate the constraint - * completely here, otherwise check that the message is long enough to - * begin the decoding and let the lower-layer function do any remaining - * validation. + * [OF10] Section 5.5.1 + * Variable-size data. */ - switch (type) { - /* OpenFlow header only. */ - case OFPT_FEATURES_REQUEST: /* [OF10] Section 5.3.1 */ - case OFPT_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.2 */ - case OFPT_BARRIER_REQUEST: /* [OF10] Section 5.3.7 */ - case OFPT_BARRIER_REPLY: /* ibid */ - if (len) - goto invalid; - return; - - /* OpenFlow header and fixed-size message body. */ - case OFPT_SET_CONFIG: /* [OF10] Section 5.3.2 */ - case OFPT_GET_CONFIG_REPLY: /* ibid */ - if (len != OF_SWITCH_CONFIG_FIXLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_switch_config_msg_print(ndo, cp, len); - return; - case OFPT_PORT_MOD: - if (len != OF_PORT_MOD_FIXLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_port_mod_print(ndo, cp, len); - return; - case OFPT_QUEUE_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.4 */ - if (len != OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_queue_get_config_request_print(ndo, cp, len); - return; - case OFPT_FLOW_REMOVED: - if (len != OF_FLOW_REMOVED_FIXLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_flow_removed_print(ndo, cp, len); - return; - case OFPT_PORT_STATUS: /* [OF10] Section 5.4.3 */ - if (len != OF_PORT_STATUS_FIXLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_port_status_print(ndo, cp, len); - return; - - /* OpenFlow header, fixed-size message body and n * fixed-size data units. */ - case OFPT_FEATURES_REPLY: - if (len < OF_FEATURES_REPLY_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_features_reply_print(ndo, cp, len); - return; - - /* OpenFlow header and variable-size data. */ - case OFPT_HELLO: /* [OF10] Section 5.5.1 */ - case OFPT_ECHO_REQUEST: /* [OF10] Section 5.5.2 */ - case OFPT_ECHO_REPLY: /* [OF10] Section 5.5.3 */ - if (ndo->ndo_vflag < 1) - break; - of_data_print(ndo, cp, len); - return; - - /* OpenFlow header, fixed-size message body and variable-size data. */ - case OFPT_ERROR: - if (len < OF_ERROR_MSG_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_error_print(ndo, cp, len); - return; - case OFPT_VENDOR: - /* [OF10] Section 5.5.4 */ - if (len < OF_VENDOR_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_vendor_message_print(ndo, cp, len); - return; - case OFPT_PACKET_IN: - /* 2 mock octets count in OF_PACKET_IN_MINLEN but not in len */ - if (len < OF_PACKET_IN_MINLEN - 2) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_packet_in_print(ndo, cp, len); - return; - - /* a. OpenFlow header. */ - /* b. OpenFlow header and one of the fixed-size message bodies. */ - /* c. OpenFlow header, fixed-size message body and variable-size data. */ - case OFPT_STATS_REQUEST: - if (len < OF_STATS_REQUEST_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_stats_request_print(ndo, cp, len); - return; - - /* a. OpenFlow header and fixed-size message body. */ - /* b. OpenFlow header and n * fixed-size data units. */ - /* c. OpenFlow header and n * variable-size data units. */ - /* d. OpenFlow header, fixed-size message body and variable-size data. */ - case OFPT_STATS_REPLY: - if (len < OF_STATS_REPLY_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_stats_reply_print(ndo, cp, len); - return; - - /* OpenFlow header and n * variable-size data units and variable-size data. */ - case OFPT_PACKET_OUT: - if (len < OF_PACKET_OUT_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_packet_out_print(ndo, cp, len); - return; - - /* OpenFlow header, fixed-size message body and n * variable-size data units. */ - case OFPT_FLOW_MOD: - if (len < OF_FLOW_MOD_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_flow_mod_print(ndo, cp, len); - return; - - /* OpenFlow header, fixed-size message body and n * variable-size data units. */ - case OFPT_QUEUE_GET_CONFIG_REPLY: /* [OF10] Section 5.3.4 */ - if (len < OF_QUEUE_GET_CONFIG_REPLY_MINLEN) - goto invalid; - if (ndo->ndo_vflag < 1) - break; - of10_queue_get_config_reply_print(ndo, cp, len); - return; - } /* switch (type) */ + { + "HELLO", of_data_print, + REQ_MINLEN, 0 + }, /* - * Not a recognised type or did not print the details, fall back to - * a bounds check. + * [OF10] Section 5.4.4 + * A fixed-size message body and variable-size data. */ - ND_TCHECK_LEN(cp, len); - return; + { + "ERROR", of10_error_print, + REQ_MINLEN, OF_ERROR_MSG_MINLEN + }, + /* + * [OF10] Section 5.5.2 + * Variable-size data. + */ + { + "ECHO_REQUEST", of_data_print, + REQ_MINLEN, 0 + }, + /* + * [OF10] Section 5.5.3 + * Variable-size data. + */ + { + "ECHO_REPLY", of_data_print, + REQ_MINLEN, 0 + }, + /* + * [OF10] Section 5.5.4 + * A fixed-size message body and variable-size data. + */ + { + "VENDOR", of10_vendor_message_print, + REQ_MINLEN, OF_VENDOR_MINLEN + }, + /* + * [OF10] Section 5.3.1 + * No message body. + */ + { + "FEATURES_REQUEST", NULL, + REQ_FIXLEN, 0 + }, + /* + * [OF10] Section 5.3.1 + * A fixed-size message body and n * fixed-size data units. + */ + { + "FEATURES_REPLY", of10_features_reply_print, + REQ_MINLEN, OF_FEATURES_REPLY_MINLEN + }, + /* + * [OF10] Section 5.3.2 + * No message body. + */ + { + "GET_CONFIG_REQUEST", NULL, + REQ_FIXLEN, 0 + }, + /* + * [OF10] Section 5.3.2 + * A fixed-size message body. + */ + { + "GET_CONFIG_REPLY", of10_switch_config_msg_print, + REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN + }, + /* + * [OF10] Section 5.3.2 + * A fixed-size message body. + */ + { + "SET_CONFIG", of10_switch_config_msg_print, + REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN + }, + /* + * [OF10] Section 5.4.1 + * A fixed-size message body and variable-size data. + * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.) + */ + { + "PACKET_IN", of10_packet_in_print, + REQ_MINLEN, OF_PACKET_IN_MINLEN - 2 + }, + /* + * [OF10] Section 5.4.2 + * A fixed-size message body. + */ + { + "FLOW_REMOVED", of10_flow_removed_print, + REQ_FIXLEN, OF_FLOW_REMOVED_FIXLEN + }, + /* + * [OF10] Section 5.4.3 + * A fixed-size message body. + */ + { + "PORT_STATUS", of10_port_status_print, + REQ_FIXLEN, OF_PORT_STATUS_FIXLEN + }, + /* + * [OF10] Section 5.3.6 + * A fixed-size message body, n * variable-size data units and + * variable-size data. + */ + { + "PACKET_OUT", of10_packet_out_print, + REQ_MINLEN, OF_PACKET_OUT_MINLEN + }, + /* + * [OF10] Section 5.3.3 + * A fixed-size message body and n * variable-size data units. + */ + { + "FLOW_MOD", of10_flow_mod_print, + REQ_MINLEN, OF_FLOW_MOD_MINLEN + }, + /* + * [OF10] Section 5.3.3 + * A fixed-size message body. + */ + { + "PORT_MOD", of10_port_mod_print, + REQ_FIXLEN, OF_PORT_MOD_FIXLEN + }, + /* + * [OF10] Section 5.3.5 + * A fixed-size message body and possibly more data of varying size + * and structure. + */ + { + "STATS_REQUEST", of10_stats_request_print, + REQ_MINLEN, OF_STATS_REQUEST_MINLEN + }, + /* + * [OF10] Section 5.3.5 + * A fixed-size message body and possibly more data of varying size + * and structure. + */ + { + "STATS_REPLY", of10_stats_reply_print, + REQ_MINLEN, OF_STATS_REPLY_MINLEN + }, + /* + * [OF10] Section 5.3.7 + * No message body. + */ + { + "BARRIER_REQUEST", NULL, + REQ_FIXLEN, 0 + }, + /* + * [OF10] Section 5.3.7 + * No message body. + */ + { + "BARRIER_REPLY", NULL, + REQ_FIXLEN, 0 + }, + /* + * [OF10] Section 5.3.4 + * A fixed-size message body. + */ + { + "QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print, + REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN + }, + /* + * [OF10] Section 5.3.4 + * A fixed-size message body and n * variable-size data units. + */ + { + "QUEUE_GET_CONFIG_REPLY", of10_queue_get_config_reply_print, + REQ_MINLEN, OF_QUEUE_GET_CONFIG_REPLY_MINLEN + }, +}; -invalid: /* skip the message body */ - nd_print_invalid(ndo); - ND_TCHECK_LEN(cp, len); +const struct of_msgtypeinfo * +of10_identify_msgtype(const uint8_t type) +{ + return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL; }