Introduce struct of_msgtypeinfo and convert all the case blocks in
of10_message_print() and of13_message_print() together with ofpt_str[]
and the associated wrapper functions into array elements of this type.
Convert the code remaining of both functions into a short generic
of_message_print() function.
Refer to the latest OpenFlow 1.3 PDF and update comments to use section
numbers from that document.
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.
In openflow_print() terminate the loop if the downstream code managed
to run off the TCP payload end without running off the packet buffer
end (that's how the pointers worked before commit ad69daa2, but I got
the recent conversion to a decrementing unsigned length wrong in commit
4e2e9c24). Expand the comment further.
Declare OF_HEADER_FIXLEN as unsigned to squelch a signedness warning.
Most OpenFlow functions operated on the (cp, ep, len) tuple, returned a
pointer to tell the calling function where to decode next (which was not
a good idea because the calling functions had the values of cp and len in
the first place) and set the pointer to ep to indicate truncated data.
Change them to use the (cp, len) tuple, to be void and to use nd_trunc().
Update the header comment to explain this new convention.
Now if a low-level function gets an offset wrong, as in the bug recently
fixed in of10_queue_props_print(), and manages to return, the error will
not propagate into the calling function, which will be able to continue
the decoding.
Since cp does not have to be current anymore when the [void] function
returns, remove a number of cp increments just before the return.
Introduce OF_FWD(), which modifies both cp and len in sync, and
OF_CHK_FWD(), which also does a bounds check, and use these macros
instead of incrementing cp directly in every function that has both cp
and len arguments. Update the code to account for len that is
decrementing as cp is incrementing.
Commit ad69daa2 was fine for its time, but the introduction of the GET
macros had made it obsolete. Instead of reintroducing ep back merge
of_header_body_print() into openflow_print() to simplify the handling of
pointers, sizes and error conditions, all in the style above.
While at it, subtract OF_HEADER_FIXLEN from the declared OpenFlow message
length before passing it to of10_header_body_print() and make the latter
the only function that has to know about the common header size (clarify
it in the comment). This and the sufficiently current cp and len
disencumber the following functions of type-specific length calculations:
of10_features_reply_print(), of10_flow_mod_print(),
of10_stats_request_print(), of10_stats_reply_print(),
of10_packet_out_print(), of10_packet_in_print() and of10_error_print().
The resulting code in most cases addresses the not yet processed part of
the declared structure with just cp and len: nextfunc(ndo, cp, len) and
ND_TCHECK_LEN(cp, len) do the right thing regardless of how far the
current decoder has made it into the current structure. This makes all
the cp0 and len0 snapshot variables obsolete, so remove them too.
Update a test case output: the missing closing quote now correctly means
that the snapshot end is inside the "data" field of a BSN_SHELL_COMMAND
vendor message, not after it.
Lose unused items, lose _HEADER_ in all names except the common OpenFlow
header, always spell _REQUEST_ and _REPLY_ where they belong, spell
either _MINLEN or _FIXLEN everywhere. Denote the 2 mock octets once
again.
The new function goes into print-openflow.c as vendor name decoding is
the same in all versions of OpenFlow (although in 1.0 it is "vendor"
and in subsequent versions it is "experimenter"). The mapping is from:
https://rs.opennetworking.org/wiki/display/PUBLIC/ONF+Registry
openflow.h in tcpdump doesn't belong to the openflow distribution and
shouldn't be attributed to stanford.edu (probably a copy-and-paste
case). Replace with 2-clause BSD.