#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" },
{
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:
/*
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 8)
- goto invalid;
+ ND_ICHECK_U(len, !=, 8);
/* index */
ND_PRINT(", index %u", GET_U_1(cp));
OF_FWD(1);
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 8)
- goto invalid;
+ ND_ICHECK_U(len, !=, 8);
/* index */
ND_PRINT(", index %u", GET_U_1(cp));
OF_FWD(1);
* +---------------+---------------+---------------+---------------+
*
*/
- 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)));
* +---------------+---------------+---------------+---------------+
*
*/
- if (len)
- goto invalid;
+ ND_ICHECK_U(len, !=, 0);
break;
case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
/*
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 4)
- goto invalid;
+ ND_ICHECK_U(len, !=, 4);
/* vport_no */
ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
break;
* +---------------+---------------+--------
*
*/
- 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 '");
- (void)nd_printn(ndo, cp, len, NULL);
+ nd_printjn(ndo, cp, len);
ND_PRINT("'");
break;
case BSN_SHELL_OUTPUT:
/* already checked that len >= 4 */
/* data */
ND_PRINT(", data '");
- (void)nd_printn(ndo, cp, len, NULL);
+ nd_printjn(ndo, cp, len);
ND_PRINT("'");
break;
case BSN_SHELL_STATUS:
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 4)
- goto invalid;
+ ND_ICHECK_U(len, !=, 4);
/* status */
ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
break;
{
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:
/*
* +---------------+---------------+---------------+---------------+
*
*/
- 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);
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);
{
uint32_t vendor;
- if (len < 4)
- goto invalid;
+ ND_ICHECK_U(len, <, 4);
/* vendor */
vendor = GET_BE_U_4(cp);
OF_FWD(4);
}
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;
}
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;
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);
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);
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);
*/
/* 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
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);
}
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 */
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);
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)));
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)));
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;
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",
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));
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 */
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) {
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 */
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);