#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" },
/* lengths (fixed or minimal) of particular protocol structures */
#define OF_PHY_PORT_FIXLEN 48
-#define OF_ACTION_MINLEN 8
+#define OF_ACTION_MINLEN 8U
#define OF_MATCH_FIXLEN 40
#define OF_DESC_STATS_REPLY_FIXLEN 1056
#define OF_FLOW_STATS_REQUEST_FIXLEN 44
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:
}
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;
}
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(len, <, alen - 4U);
/*
* After validating the basic length constraint it will be safe
* to skip the current action if the action size is not valid
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 */
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(len, <, entry_len);
OF_FWD(2);
/* table_id */
ND_PRINT(", table_id %s",
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(len, <, actions_len);
/* actions */
of10_actions_print(ndo, "\n\t ", cp, actions_len);
OF_FWD(actions_len);