X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/e17e42550af9159faf1b27f203797af780de25c1..f5877da285f3e030d59a28236295573f27e344bc:/print-openflow.c diff --git a/print-openflow.c b/print-openflow.c index 699ebe88..82eeda0c 100644 --- a/print-openflow.c +++ b/print-openflow.c @@ -32,9 +32,7 @@ /* \summary: version-independent OpenFlow printer */ -#ifdef HAVE_CONFIG_H #include -#endif #include "netdissect-stdinc.h" @@ -45,13 +43,6 @@ #include "oui.h" -#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" }, @@ -71,6 +62,9 @@ const struct tok onf_exp_str[] = { { ONF_EXP_WMOB, "Wireless and Mobility Extensions" }, { ONF_EXP_FABS, "Forwarding Abstractions Extensions" }, { ONF_EXP_OTRANS, "Optical Transport Extensions" }, + { ONF_EXP_NBLNCTU, "Network Benchmarking Lab, NCTU" }, + { ONF_EXP_MPCE, "Mobile Packet Core Extensions" }, + { ONF_EXP_MPLSTPSPTN, "MPLS-TP OpenFlow Extensions for SPTN" }, { 0, NULL } }; @@ -83,20 +77,14 @@ of_vendor_name(const uint32_t vendor) void of_bitmap_print(netdissect_options *ndo, - const struct tok *t, const uint32_t v, const uint32_t u) + const struct tok *t, const uint32_t v, const uint32_t u) { - const char *sep = " ("; - - if (v == 0) - return; - /* assigned bits */ - for (; t->s != NULL; t++) - if (v & t->v) { - ND_PRINT("%s%s", sep, t->s); - sep = ", "; - } - /* unassigned bits? */ - ND_PRINT((v & u) ? ") (bogus)" : ")"); + /* Assigned bits? */ + if (v & ~u) + ND_PRINT(" (%s)", bittok2str(t, "", v)); + /* Unassigned bits? */ + if (v & u) + ND_PRINT(" (bogus)"); } void @@ -113,6 +101,41 @@ of_data_print(netdissect_options *ndo, ND_TCHECK_LEN(cp, len); } +static void +of_message_print(netdissect_options *ndo, + const u_char *cp, uint16_t len, + const struct of_msgtypeinfo *mti) +{ + /* + * 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 (REQ_FIXLEN), otherwise check that the message is + * long enough to begin the decoding (REQ_MINLEN) and have the + * type-specific function do any remaining validation. + */ + + if (!mti) + goto tcheck_remainder; + + if ((mti->req_what == REQ_FIXLEN && len != mti->req_value) || + (mti->req_what == REQ_MINLEN && len < mti->req_value)) + goto invalid; + + if (!ndo->ndo_vflag || !mti->decoder) + goto tcheck_remainder; + + mti->decoder(ndo, cp, len); + return; + +invalid: + nd_print_invalid(ndo); +tcheck_remainder: + ND_TCHECK_LEN(cp, len); +} + /* Print a TCP segment worth of OpenFlow messages presuming the segment begins * on a message boundary. */ void @@ -124,8 +147,7 @@ openflow_print(netdissect_options *ndo, const u_char *cp, u_int len) /* Print a single OpenFlow message. */ uint8_t version, type; uint16_t length; - void (*decoder)(struct netdissect_options *, - const u_char *, uint16_t, const uint8_t) = NULL; + const struct of_msgtypeinfo *mti; /* version */ version = GET_U_1(cp); @@ -137,18 +159,14 @@ openflow_print(netdissect_options *ndo, const u_char *cp, u_int len) 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; - case OF_VER_1_3: - ND_PRINT(", type %s", of13_msgtype_str(type)); - decoder = of13_message_print; - break; - default: + mti = + version == OF_VER_1_0 ? of10_identify_msgtype(type) : + version == OF_VER_1_3 ? of13_identify_msgtype(type) : + NULL; + if (mti && mti->name) + ND_PRINT(", type %s", mti->name); + else ND_PRINT(", type unknown (0x%02x)", type); - } /* length */ if (len < 2) goto partial_header; @@ -191,10 +209,7 @@ openflow_print(netdissect_options *ndo, const u_char *cp, u_int len) if (length < OF_HEADER_FIXLEN) goto invalid; - if (decoder != NULL) - decoder(ndo, cp, length - OF_HEADER_FIXLEN, type); - else - ND_TCHECK_LEN(cp, length - OF_HEADER_FIXLEN); + of_message_print(ndo, cp, length - OF_HEADER_FIXLEN, mti); if (length - OF_HEADER_FIXLEN > len) break; OF_FWD(length - OF_HEADER_FIXLEN);