1 /* 2 * This module implements decoding of OpenFlow protocol version 1.0 (wire 3 * protocol 0x01). The decoder implements terse (default), detailed (-v) and 4 * full (-vv) output formats and, as much as each format implies, detects and 5 * tries to work around sizing anomalies inside the messages. The decoder marks 6 * up bogus values of selected message fields and decodes partially captured 7 * messages up to the snapshot end. It is based on the specification below: 8 * 9 * [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf 10 * 11 * Most functions in this file take the following arguments: 12 * * cp -- the pointer to the first octet to decode 13 * * len -- the declared length of the structure to decode 14 * The convention is that a printer function returns iff the given structure is 15 * completely within the packet buffer; otherwise it processes the part that is 16 * within the buffer, sooner of later takes the "truncated packet" shortcut via 17 * longjmp() and never returns. With that in mind, the function may return 18 * without printing the structure completely if it is invalid or the ndo_vflag 19 * value is not high enough. This way the calling function can try to decode 20 * the next data item. 21 * 22 * Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT 23 * messages is done only when the verbosity level set by command-line argument 24 * is "-vvv" or higher. In that case the verbosity level is temporarily 25 * decremented by 3 during the nested frame decoding. For example, running 26 * tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of 27 * the nested frames. 28 * 29 * Partial decoding of Big Switch Networks vendor extensions is done after the 30 * oftest (OpenFlow Testing Framework) and Loxigen (library generator) source 31 * code. 32 * 33 * 34 * Copyright (c) 2013 The TCPDUMP project 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 47 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 48 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 49 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 50 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 52 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 53 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 54 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 56 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 * POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60 /* \summary: OpenFlow protocol version 1.0 printer */ 61 62 #ifdef HAVE_CONFIG_H 63 #include <config.h> 64 #endif 65 66 #include "netdissect-stdinc.h" 67 68 #define ND_LONGJMP_FROM_TCHECK 69 #include "netdissect.h" 70 #include "extract.h" 71 #include "addrtoname.h" 72 #include "ethertype.h" 73 #include "ipproto.h" 74 #include "oui.h" 75 #include "openflow.h" 76 77 78 #define OFPT_HELLO 0x00 79 #define OFPT_ERROR 0x01 80 #define OFPT_ECHO_REQUEST 0x02 81 #define OFPT_ECHO_REPLY 0x03 82 #define OFPT_VENDOR 0x04 83 #define OFPT_FEATURES_REQUEST 0x05 84 #define OFPT_FEATURES_REPLY 0x06 85 #define OFPT_GET_CONFIG_REQUEST 0x07 86 #define OFPT_GET_CONFIG_REPLY 0x08 87 #define OFPT_SET_CONFIG 0x09 88 #define OFPT_PACKET_IN 0x0a 89 #define OFPT_FLOW_REMOVED 0x0b 90 #define OFPT_PORT_STATUS 0x0c 91 #define OFPT_PACKET_OUT 0x0d 92 #define OFPT_FLOW_MOD 0x0e 93 #define OFPT_PORT_MOD 0x0f 94 #define OFPT_STATS_REQUEST 0x10 95 #define OFPT_STATS_REPLY 0x11 96 #define OFPT_BARRIER_REQUEST 0x12 97 #define OFPT_BARRIER_REPLY 0x13 98 #define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14 99 #define OFPT_QUEUE_GET_CONFIG_REPLY 0x15 100 #define OFPT_MAX OFPT_QUEUE_GET_CONFIG_REPLY 101 102 #define OFPPC_PORT_DOWN (1U <<0) 103 #define OFPPC_NO_STP (1U <<1) 104 #define OFPPC_NO_RECV (1U <<2) 105 #define OFPPC_NO_RECV_STP (1U <<3) 106 #define OFPPC_NO_FLOOD (1U <<4) 107 #define OFPPC_NO_FWD (1U <<5) 108 #define OFPPC_NO_PACKET_IN (1U <<6) 109 static const struct tok ofppc_bm[] = { 110 { OFPPC_PORT_DOWN, "PORT_DOWN" }, 111 { OFPPC_NO_STP, "NO_STP" }, 112 { OFPPC_NO_RECV, "NO_RECV" }, 113 { OFPPC_NO_RECV_STP, "NO_RECV_STP" }, 114 { OFPPC_NO_FLOOD, "NO_FLOOD" }, 115 { OFPPC_NO_FWD, "NO_FWD" }, 116 { OFPPC_NO_PACKET_IN, "NO_PACKET_IN" }, 117 { 0, NULL } 118 }; 119 #define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \ 120 OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \ 121 OFPPC_NO_PACKET_IN)) 122 123 /* 124 * [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap 125 * in the least significant octet and a 2-bit code point in the next octet. 126 * Remember to mix or to separate these two parts as the context requires. 127 */ 128 #define OFPPS_LINK_DOWN (1U << 0) /* bitmap */ 129 #define OFPPS_STP_LISTEN (0U << 8) /* code point */ 130 #define OFPPS_STP_LEARN (1U << 8) /* code point */ 131 #define OFPPS_STP_FORWARD (2U << 8) /* code point */ 132 #define OFPPS_STP_BLOCK (3U << 8) /* code point */ 133 #define OFPPS_STP_MASK (3U << 8) /* code point bitmask */ 134 static const struct tok ofpps_stp_str[] = { 135 { OFPPS_STP_LISTEN, "STP_LISTEN" }, 136 { OFPPS_STP_LEARN, "STP_LEARN" }, 137 { OFPPS_STP_FORWARD, "STP_FORWARD" }, 138 { OFPPS_STP_BLOCK, "STP_BLOCK" }, 139 { 0, NULL } 140 }; 141 #define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \ 142 OFPPS_STP_FORWARD | OFPPS_STP_BLOCK)) 143 144 #define OFPP_MAX 0xff00U 145 #define OFPP_IN_PORT 0xfff8U 146 #define OFPP_TABLE 0xfff9U 147 #define OFPP_NORMAL 0xfffaU 148 #define OFPP_FLOOD 0xfffbU 149 #define OFPP_ALL 0xfffcU 150 #define OFPP_CONTROLLER 0xfffdU 151 #define OFPP_LOCAL 0xfffeU 152 #define OFPP_NONE 0xffffU 153 static const struct tok ofpp_str[] = { 154 { OFPP_MAX, "MAX" }, 155 { OFPP_IN_PORT, "IN_PORT" }, 156 { OFPP_TABLE, "TABLE" }, 157 { OFPP_NORMAL, "NORMAL" }, 158 { OFPP_FLOOD, "FLOOD" }, 159 { OFPP_ALL, "ALL" }, 160 { OFPP_CONTROLLER, "CONTROLLER" }, 161 { OFPP_LOCAL, "LOCAL" }, 162 { OFPP_NONE, "NONE" }, 163 { 0, NULL } 164 }; 165 166 #define OFPPF_10MB_HD (1U << 0) 167 #define OFPPF_10MB_FD (1U << 1) 168 #define OFPPF_100MB_HD (1U << 2) 169 #define OFPPF_100MB_FD (1U << 3) 170 #define OFPPF_1GB_HD (1U << 4) 171 #define OFPPF_1GB_FD (1U << 5) 172 #define OFPPF_10GB_FD (1U << 6) 173 #define OFPPF_COPPER (1U << 7) 174 #define OFPPF_FIBER (1U << 8) 175 #define OFPPF_AUTONEG (1U << 9) 176 #define OFPPF_PAUSE (1U <<10) 177 #define OFPPF_PAUSE_ASYM (1U <<11) 178 static const struct tok ofppf_bm[] = { 179 { OFPPF_10MB_HD, "10MB_HD" }, 180 { OFPPF_10MB_FD, "10MB_FD" }, 181 { OFPPF_100MB_HD, "100MB_HD" }, 182 { OFPPF_100MB_FD, "100MB_FD" }, 183 { OFPPF_1GB_HD, "1GB_HD" }, 184 { OFPPF_1GB_FD, "1GB_FD" }, 185 { OFPPF_10GB_FD, "10GB_FD" }, 186 { OFPPF_COPPER, "COPPER" }, 187 { OFPPF_FIBER, "FIBER" }, 188 { OFPPF_AUTONEG, "AUTONEG" }, 189 { OFPPF_PAUSE, "PAUSE" }, 190 { OFPPF_PAUSE_ASYM, "PAUSE_ASYM" }, 191 { 0, NULL } 192 }; 193 #define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \ 194 OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \ 195 OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \ 196 OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM)) 197 198 #define OFPQT_NONE 0x0000 199 #define OFPQT_MIN_RATE 0x0001 200 static const struct tok ofpqt_str[] = { 201 { OFPQT_NONE, "NONE" }, 202 { OFPQT_MIN_RATE, "MIN_RATE" }, 203 { 0, NULL } 204 }; 205 206 #define OFPFW_IN_PORT (1U <<0) 207 #define OFPFW_DL_VLAN (1U <<1) 208 #define OFPFW_DL_SRC (1U <<2) 209 #define OFPFW_DL_DST (1U <<3) 210 #define OFPFW_DL_TYPE (1U <<4) 211 #define OFPFW_NW_PROTO (1U <<5) 212 #define OFPFW_TP_SRC (1U <<6) 213 #define OFPFW_TP_DST (1U <<7) 214 #define OFPFW_NW_SRC_SHIFT 8 215 #define OFPFW_NW_SRC_BITS 6 216 #define OFPFW_NW_SRC_MASK (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT) 217 #define OFPFW_NW_DST_SHIFT 14 218 #define OFPFW_NW_DST_BITS 6 219 #define OFPFW_NW_DST_MASK (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT) 220 #define OFPFW_DL_VLAN_PCP (1U <<20) 221 #define OFPFW_NW_TOS (1U <<21) 222 #define OFPFW_ALL ((1U <<22) - 1) 223 static const struct tok ofpfw_bm[] = { 224 { OFPFW_IN_PORT, "IN_PORT" }, 225 { OFPFW_DL_VLAN, "DL_VLAN" }, 226 { OFPFW_DL_SRC, "DL_SRC" }, 227 { OFPFW_DL_DST, "DL_DST" }, 228 { OFPFW_DL_TYPE, "DL_TYPE" }, 229 { OFPFW_NW_PROTO, "NW_PROTO" }, 230 { OFPFW_TP_SRC, "TP_SRC" }, 231 { OFPFW_TP_DST, "TP_DST" }, 232 { OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" }, 233 { OFPFW_NW_TOS, "NW_TOS" }, 234 { 0, NULL } 235 }; 236 /* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19 237 * (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding 238 * other than that of tok2str(). The macro below includes these bits such that 239 * they are not reported as bogus in the decoding. */ 240 #define OFPFW_U (~(OFPFW_ALL)) 241 242 #define OFPAT_OUTPUT 0x0000U 243 #define OFPAT_SET_VLAN_VID 0x0001U 244 #define OFPAT_SET_VLAN_PCP 0x0002U 245 #define OFPAT_STRIP_VLAN 0x0003U 246 #define OFPAT_SET_DL_SRC 0x0004U 247 #define OFPAT_SET_DL_DST 0x0005U 248 #define OFPAT_SET_NW_SRC 0x0006U 249 #define OFPAT_SET_NW_DST 0x0007U 250 #define OFPAT_SET_NW_TOS 0x0008U 251 #define OFPAT_SET_TP_SRC 0x0009U 252 #define OFPAT_SET_TP_DST 0x000aU 253 #define OFPAT_ENQUEUE 0x000bU 254 #define OFPAT_VENDOR 0xffffU 255 static const struct tok ofpat_str[] = { 256 { OFPAT_OUTPUT, "OUTPUT" }, 257 { OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, 258 { OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, 259 { OFPAT_STRIP_VLAN, "STRIP_VLAN" }, 260 { OFPAT_SET_DL_SRC, "SET_DL_SRC" }, 261 { OFPAT_SET_DL_DST, "SET_DL_DST" }, 262 { OFPAT_SET_NW_SRC, "SET_NW_SRC" }, 263 { OFPAT_SET_NW_DST, "SET_NW_DST" }, 264 { OFPAT_SET_NW_TOS, "SET_NW_TOS" }, 265 { OFPAT_SET_TP_SRC, "SET_TP_SRC" }, 266 { OFPAT_SET_TP_DST, "SET_TP_DST" }, 267 { OFPAT_ENQUEUE, "ENQUEUE" }, 268 { OFPAT_VENDOR, "VENDOR" }, 269 { 0, NULL } 270 }; 271 272 /* bit-shifted, w/o vendor action */ 273 static const struct tok ofpat_bm[] = { 274 { 1U <<OFPAT_OUTPUT, "OUTPUT" }, 275 { 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, 276 { 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, 277 { 1U <<OFPAT_STRIP_VLAN, "STRIP_VLAN" }, 278 { 1U <<OFPAT_SET_DL_SRC, "SET_DL_SRC" }, 279 { 1U <<OFPAT_SET_DL_DST, "SET_DL_DST" }, 280 { 1U <<OFPAT_SET_NW_SRC, "SET_NW_SRC" }, 281 { 1U <<OFPAT_SET_NW_DST, "SET_NW_DST" }, 282 { 1U <<OFPAT_SET_NW_TOS, "SET_NW_TOS" }, 283 { 1U <<OFPAT_SET_TP_SRC, "SET_TP_SRC" }, 284 { 1U <<OFPAT_SET_TP_DST, "SET_TP_DST" }, 285 { 1U <<OFPAT_ENQUEUE, "ENQUEUE" }, 286 { 0, NULL } 287 }; 288 #define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \ 289 1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \ 290 1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \ 291 1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \ 292 1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \ 293 1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE)) 294 295 #define OFPC_FLOW_STATS (1U <<0) 296 #define OFPC_TABLE_STATS (1U <<1) 297 #define OFPC_PORT_STATS (1U <<2) 298 #define OFPC_STP (1U <<3) 299 #define OFPC_RESERVED (1U <<4) 300 #define OFPC_IP_REASM (1U <<5) 301 #define OFPC_QUEUE_STATS (1U <<6) 302 #define OFPC_ARP_MATCH_IP (1U <<7) 303 static const struct tok ofp_capabilities_bm[] = { 304 { OFPC_FLOW_STATS, "FLOW_STATS" }, 305 { OFPC_TABLE_STATS, "TABLE_STATS" }, 306 { OFPC_PORT_STATS, "PORT_STATS" }, 307 { OFPC_STP, "STP" }, 308 { OFPC_RESERVED, "RESERVED" }, /* not in the mask below */ 309 { OFPC_IP_REASM, "IP_REASM" }, 310 { OFPC_QUEUE_STATS, "QUEUE_STATS" }, 311 { OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" }, 312 { 0, NULL } 313 }; 314 #define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \ 315 OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \ 316 OFPC_ARP_MATCH_IP)) 317 318 #define OFPC_FRAG_NORMAL 0x0000U 319 #define OFPC_FRAG_DROP 0x0001U 320 #define OFPC_FRAG_REASM 0x0002U 321 #define OFPC_FRAG_MASK 0x0003U 322 static const struct tok ofp_config_str[] = { 323 { OFPC_FRAG_NORMAL, "FRAG_NORMAL" }, 324 { OFPC_FRAG_DROP, "FRAG_DROP" }, 325 { OFPC_FRAG_REASM, "FRAG_REASM" }, 326 { 0, NULL } 327 }; 328 329 #define OFPFC_ADD 0x0000U 330 #define OFPFC_MODIFY 0x0001U 331 #define OFPFC_MODIFY_STRICT 0x0002U 332 #define OFPFC_DELETE 0x0003U 333 #define OFPFC_DELETE_STRICT 0x0004U 334 static const struct tok ofpfc_str[] = { 335 { OFPFC_ADD, "ADD" }, 336 { OFPFC_MODIFY, "MODIFY" }, 337 { OFPFC_MODIFY_STRICT, "MODIFY_STRICT" }, 338 { OFPFC_DELETE, "DELETE" }, 339 { OFPFC_DELETE_STRICT, "DELETE_STRICT" }, 340 { 0, NULL } 341 }; 342 343 static const struct tok bufferid_str[] = { 344 { 0xffffffff, "NONE" }, 345 { 0, NULL } 346 }; 347 348 #define OFPFF_SEND_FLOW_REM (1U <<0) 349 #define OFPFF_CHECK_OVERLAP (1U <<1) 350 #define OFPFF_EMERG (1U <<2) 351 static const struct tok ofpff_bm[] = { 352 { OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" }, 353 { OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" }, 354 { OFPFF_EMERG, "EMERG" }, 355 { 0, NULL } 356 }; 357 #define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG)) 358 359 #define OFPST_DESC 0x0000U 360 #define OFPST_FLOW 0x0001U 361 #define OFPST_AGGREGATE 0x0002U 362 #define OFPST_TABLE 0x0003U 363 #define OFPST_PORT 0x0004U 364 #define OFPST_QUEUE 0x0005U 365 #define OFPST_VENDOR 0xffffU 366 static const struct tok ofpst_str[] = { 367 { OFPST_DESC, "DESC" }, 368 { OFPST_FLOW, "FLOW" }, 369 { OFPST_AGGREGATE, "AGGREGATE" }, 370 { OFPST_TABLE, "TABLE" }, 371 { OFPST_PORT, "PORT" }, 372 { OFPST_QUEUE, "QUEUE" }, 373 { OFPST_VENDOR, "VENDOR" }, 374 { 0, NULL } 375 }; 376 377 static const struct tok tableid_str[] = { 378 { 0xfeU, "EMERG" }, 379 { 0xffU, "ALL" }, 380 { 0, NULL } 381 }; 382 383 #define OFPQ_ALL 0xffffffffU 384 static const struct tok ofpq_str[] = { 385 { OFPQ_ALL, "ALL" }, 386 { 0, NULL } 387 }; 388 389 #define OFPSF_REPLY_MORE 0x0001U 390 static const struct tok ofpsf_reply_bm[] = { 391 { OFPSF_REPLY_MORE, "MORE" }, 392 { 0, NULL } 393 }; 394 #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE)) 395 396 #define OFPR_NO_MATCH 0x00U 397 #define OFPR_ACTION 0x01U 398 static const struct tok ofpr_str[] = { 399 { OFPR_NO_MATCH, "NO_MATCH" }, 400 { OFPR_ACTION, "ACTION" }, 401 { 0, NULL } 402 }; 403 404 #define OFPRR_IDLE_TIMEOUT 0x00U 405 #define OFPRR_HARD_TIMEOUT 0x01U 406 #define OFPRR_DELETE 0x02U 407 static const struct tok ofprr_str[] = { 408 { OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" }, 409 { OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" }, 410 { OFPRR_DELETE, "DELETE" }, 411 { 0, NULL } 412 }; 413 414 #define OFPPR_ADD 0x00U 415 #define OFPPR_DELETE 0x01U 416 #define OFPPR_MODIFY 0x02U 417 static const struct tok ofppr_str[] = { 418 { OFPPR_ADD, "ADD" }, 419 { OFPPR_DELETE, "DELETE" }, 420 { OFPPR_MODIFY, "MODIFY" }, 421 { 0, NULL } 422 }; 423 424 #define OFPET_HELLO_FAILED 0x0000U 425 #define OFPET_BAD_REQUEST 0x0001U 426 #define OFPET_BAD_ACTION 0x0002U 427 #define OFPET_FLOW_MOD_FAILED 0x0003U 428 #define OFPET_PORT_MOD_FAILED 0x0004U 429 #define OFPET_QUEUE_OP_FAILED 0x0005U 430 static const struct tok ofpet_str[] = { 431 { OFPET_HELLO_FAILED, "HELLO_FAILED" }, 432 { OFPET_BAD_REQUEST, "BAD_REQUEST" }, 433 { OFPET_BAD_ACTION, "BAD_ACTION" }, 434 { OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" }, 435 { OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" }, 436 { OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" }, 437 { 0, NULL } 438 }; 439 440 #define OFPHFC_INCOMPATIBLE 0x0000U 441 #define OFPHFC_EPERM 0x0001U 442 static const struct tok ofphfc_str[] = { 443 { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" }, 444 { OFPHFC_EPERM, "EPERM" }, 445 { 0, NULL } 446 }; 447 448 #define OFPBRC_BAD_VERSION 0x0000U 449 #define OFPBRC_BAD_TYPE 0x0001U 450 #define OFPBRC_BAD_STAT 0x0002U 451 #define OFPBRC_BAD_VENDOR 0x0003U 452 #define OFPBRC_BAD_SUBTYPE 0x0004U 453 #define OFPBRC_EPERM 0x0005U 454 #define OFPBRC_BAD_LEN 0x0006U 455 #define OFPBRC_BUFFER_EMPTY 0x0007U 456 #define OFPBRC_BUFFER_UNKNOWN 0x0008U 457 static const struct tok ofpbrc_str[] = { 458 { OFPBRC_BAD_VERSION, "BAD_VERSION" }, 459 { OFPBRC_BAD_TYPE, "BAD_TYPE" }, 460 { OFPBRC_BAD_STAT, "BAD_STAT" }, 461 { OFPBRC_BAD_VENDOR, "BAD_VENDOR" }, 462 { OFPBRC_BAD_SUBTYPE, "BAD_SUBTYPE" }, 463 { OFPBRC_EPERM, "EPERM" }, 464 { OFPBRC_BAD_LEN, "BAD_LEN" }, 465 { OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" }, 466 { OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" }, 467 { 0, NULL } 468 }; 469 470 #define OFPBAC_BAD_TYPE 0x0000U 471 #define OFPBAC_BAD_LEN 0x0001U 472 #define OFPBAC_BAD_VENDOR 0x0002U 473 #define OFPBAC_BAD_VENDOR_TYPE 0x0003U 474 #define OFPBAC_BAD_OUT_PORT 0x0004U 475 #define OFPBAC_BAD_ARGUMENT 0x0005U 476 #define OFPBAC_EPERM 0x0006U 477 #define OFPBAC_TOO_MANY 0x0007U 478 #define OFPBAC_BAD_QUEUE 0x0008U 479 static const struct tok ofpbac_str[] = { 480 { OFPBAC_BAD_TYPE, "BAD_TYPE" }, 481 { OFPBAC_BAD_LEN, "BAD_LEN" }, 482 { OFPBAC_BAD_VENDOR, "BAD_VENDOR" }, 483 { OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" }, 484 { OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" }, 485 { OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" }, 486 { OFPBAC_EPERM, "EPERM" }, 487 { OFPBAC_TOO_MANY, "TOO_MANY" }, 488 { OFPBAC_BAD_QUEUE, "BAD_QUEUE" }, 489 { 0, NULL } 490 }; 491 492 #define OFPFMFC_ALL_TABLES_FULL 0x0000U 493 #define OFPFMFC_OVERLAP 0x0001U 494 #define OFPFMFC_EPERM 0x0002U 495 #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U 496 #define OFPFMFC_BAD_COMMAND 0x0004U 497 #define OFPFMFC_UNSUPPORTED 0x0005U 498 static const struct tok ofpfmfc_str[] = { 499 { OFPFMFC_ALL_TABLES_FULL, "ALL_TABLES_FULL" }, 500 { OFPFMFC_OVERLAP, "OVERLAP" }, 501 { OFPFMFC_EPERM, "EPERM" }, 502 { OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" }, 503 { OFPFMFC_BAD_COMMAND, "BAD_COMMAND" }, 504 { OFPFMFC_UNSUPPORTED, "UNSUPPORTED" }, 505 { 0, NULL } 506 }; 507 508 #define OFPPMFC_BAD_PORT 0x0000U 509 #define OFPPMFC_BAD_HW_ADDR 0x0001U 510 static const struct tok ofppmfc_str[] = { 511 { OFPPMFC_BAD_PORT, "BAD_PORT" }, 512 { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" }, 513 { 0, NULL } 514 }; 515 516 #define OFPQOFC_BAD_PORT 0x0000U 517 #define OFPQOFC_BAD_QUEUE 0x0001U 518 #define OFPQOFC_EPERM 0x0002U 519 static const struct tok ofpqofc_str[] = { 520 { OFPQOFC_BAD_PORT, "BAD_PORT" }, 521 { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" }, 522 { OFPQOFC_EPERM, "EPERM" }, 523 { 0, NULL } 524 }; 525 526 static const struct uint_tokary of10_ofpet2tokary[] = { 527 { OFPET_HELLO_FAILED, ofphfc_str }, 528 { OFPET_BAD_REQUEST, ofpbrc_str }, 529 { OFPET_BAD_ACTION, ofpbac_str }, 530 { OFPET_FLOW_MOD_FAILED, ofpfmfc_str }, 531 { OFPET_PORT_MOD_FAILED, ofppmfc_str }, 532 { OFPET_QUEUE_OP_FAILED, ofpqofc_str }, 533 /* uint2tokary() does not use array termination. */ 534 }; 535 536 /* lengths (fixed or minimal) of particular message types, where not 0 */ 537 #define OF_SWITCH_CONFIG_FIXLEN (12U - OF_HEADER_FIXLEN) 538 #define OF_FEATURES_REPLY_MINLEN (32U - OF_HEADER_FIXLEN) 539 #define OF_PORT_STATUS_FIXLEN (64U - OF_HEADER_FIXLEN) 540 #define OF_PORT_MOD_FIXLEN (32U - OF_HEADER_FIXLEN) 541 #define OF_PACKET_IN_MINLEN (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */ 542 #define OF_PACKET_OUT_MINLEN (16U - OF_HEADER_FIXLEN) 543 #define OF_FLOW_MOD_MINLEN (72U - OF_HEADER_FIXLEN) 544 #define OF_FLOW_REMOVED_FIXLEN (88U - OF_HEADER_FIXLEN) 545 #define OF_ERROR_MSG_MINLEN (12U - OF_HEADER_FIXLEN) 546 #define OF_STATS_REQUEST_MINLEN (12U - OF_HEADER_FIXLEN) 547 #define OF_STATS_REPLY_MINLEN (12U - OF_HEADER_FIXLEN) 548 #define OF_VENDOR_MINLEN (12U - OF_HEADER_FIXLEN) 549 #define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN) 550 #define OF_QUEUE_GET_CONFIG_REPLY_MINLEN (16U - OF_HEADER_FIXLEN) 551 552 /* lengths (fixed or minimal) of particular protocol structures */ 553 #define OF_PHY_PORT_FIXLEN 48 554 #define OF_ACTION_MINLEN 8 555 #define OF_MATCH_FIXLEN 40 556 #define OF_DESC_STATS_REPLY_FIXLEN 1056 557 #define OF_FLOW_STATS_REQUEST_FIXLEN 44 558 #define OF_FLOW_STATS_REPLY_MINLEN 88 559 #define OF_AGGREGATE_STATS_REPLY_FIXLEN 24 560 #define OF_TABLE_STATS_REPLY_FIXLEN 64 561 #define OF_PORT_STATS_REQUEST_FIXLEN 8 562 #define OF_PORT_STATS_REPLY_FIXLEN 104 563 #define OF_QUEUE_PROP_MINLEN 8 564 #define OF_QUEUE_PROP_MIN_RATE_FIXLEN 16 565 #define OF_PACKET_QUEUE_MINLEN 8 566 #define OF_QUEUE_STATS_REQUEST_FIXLEN 8 567 #define OF_QUEUE_STATS_REPLY_FIXLEN 32 568 569 /* miscellaneous constants from [OF10] */ 570 #define OFP_MAX_TABLE_NAME_LEN 32 571 #define OFP_MAX_PORT_NAME_LEN 16 572 #define DESC_STR_LEN 256 573 #define SERIAL_NUM_LEN 32 574 #define OFP_VLAN_NONE 0xffffU 575 576 /* vendor extensions */ 577 #define BSN_SET_IP_MASK 0 578 #define BSN_GET_IP_MASK_REQUEST 1 579 #define BSN_GET_IP_MASK_REPLY 2 580 #define BSN_SET_MIRRORING 3 581 #define BSN_GET_MIRRORING_REQUEST 4 582 #define BSN_GET_MIRRORING_REPLY 5 583 #define BSN_SHELL_COMMAND 6 584 #define BSN_SHELL_OUTPUT 7 585 #define BSN_SHELL_STATUS 8 586 #define BSN_GET_INTERFACES_REQUEST 9 587 #define BSN_GET_INTERFACES_REPLY 10 588 #define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11 589 #define BSN_SET_L2_TABLE_REQUEST 12 590 #define BSN_GET_L2_TABLE_REQUEST 13 591 #define BSN_GET_L2_TABLE_REPLY 14 592 #define BSN_VIRTUAL_PORT_CREATE_REQUEST 15 593 #define BSN_VIRTUAL_PORT_CREATE_REPLY 16 594 #define BSN_VIRTUAL_PORT_REMOVE_REQUEST 17 595 #define BSN_BW_ENABLE_SET_REQUEST 18 596 #define BSN_BW_ENABLE_GET_REQUEST 19 597 #define BSN_BW_ENABLE_GET_REPLY 20 598 #define BSN_BW_CLEAR_DATA_REQUEST 21 599 #define BSN_BW_CLEAR_DATA_REPLY 22 600 #define BSN_BW_ENABLE_SET_REPLY 23 601 #define BSN_SET_L2_TABLE_REPLY 24 602 #define BSN_SET_PKTIN_SUPPRESSION_REPLY 25 603 #define BSN_VIRTUAL_PORT_REMOVE_REPLY 26 604 #define BSN_HYBRID_GET_REQUEST 27 605 #define BSN_HYBRID_GET_REPLY 28 606 /* 29 */ 607 /* 30 */ 608 #define BSN_PDU_TX_REQUEST 31 609 #define BSN_PDU_TX_REPLY 32 610 #define BSN_PDU_RX_REQUEST 33 611 #define BSN_PDU_RX_REPLY 34 612 #define BSN_PDU_RX_TIMEOUT 35 613 614 static const struct tok bsn_subtype_str[] = { 615 { BSN_SET_IP_MASK, "SET_IP_MASK" }, 616 { BSN_GET_IP_MASK_REQUEST, "GET_IP_MASK_REQUEST" }, 617 { BSN_GET_IP_MASK_REPLY, "GET_IP_MASK_REPLY" }, 618 { BSN_SET_MIRRORING, "SET_MIRRORING" }, 619 { BSN_GET_MIRRORING_REQUEST, "GET_MIRRORING_REQUEST" }, 620 { BSN_GET_MIRRORING_REPLY, "GET_MIRRORING_REPLY" }, 621 { BSN_SHELL_COMMAND, "SHELL_COMMAND" }, 622 { BSN_SHELL_OUTPUT, "SHELL_OUTPUT" }, 623 { BSN_SHELL_STATUS, "SHELL_STATUS" }, 624 { BSN_GET_INTERFACES_REQUEST, "GET_INTERFACES_REQUEST" }, 625 { BSN_GET_INTERFACES_REPLY, "GET_INTERFACES_REPLY" }, 626 { BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" }, 627 { BSN_SET_L2_TABLE_REQUEST, "SET_L2_TABLE_REQUEST" }, 628 { BSN_GET_L2_TABLE_REQUEST, "GET_L2_TABLE_REQUEST" }, 629 { BSN_GET_L2_TABLE_REPLY, "GET_L2_TABLE_REPLY" }, 630 { BSN_VIRTUAL_PORT_CREATE_REQUEST, "VIRTUAL_PORT_CREATE_REQUEST" }, 631 { BSN_VIRTUAL_PORT_CREATE_REPLY, "VIRTUAL_PORT_CREATE_REPLY" }, 632 { BSN_VIRTUAL_PORT_REMOVE_REQUEST, "VIRTUAL_PORT_REMOVE_REQUEST" }, 633 { BSN_BW_ENABLE_SET_REQUEST, "BW_ENABLE_SET_REQUEST" }, 634 { BSN_BW_ENABLE_GET_REQUEST, "BW_ENABLE_GET_REQUEST" }, 635 { BSN_BW_ENABLE_GET_REPLY, "BW_ENABLE_GET_REPLY" }, 636 { BSN_BW_CLEAR_DATA_REQUEST, "BW_CLEAR_DATA_REQUEST" }, 637 { BSN_BW_CLEAR_DATA_REPLY, "BW_CLEAR_DATA_REPLY" }, 638 { BSN_BW_ENABLE_SET_REPLY, "BW_ENABLE_SET_REPLY" }, 639 { BSN_SET_L2_TABLE_REPLY, "SET_L2_TABLE_REPLY" }, 640 { BSN_SET_PKTIN_SUPPRESSION_REPLY, "SET_PKTIN_SUPPRESSION_REPLY" }, 641 { BSN_VIRTUAL_PORT_REMOVE_REPLY, "VIRTUAL_PORT_REMOVE_REPLY" }, 642 { BSN_HYBRID_GET_REQUEST, "HYBRID_GET_REQUEST" }, 643 { BSN_HYBRID_GET_REPLY, "HYBRID_GET_REPLY" }, 644 { BSN_PDU_TX_REQUEST, "PDU_TX_REQUEST" }, 645 { BSN_PDU_TX_REPLY, "PDU_TX_REPLY" }, 646 { BSN_PDU_RX_REQUEST, "PDU_RX_REQUEST" }, 647 { BSN_PDU_RX_REPLY, "PDU_RX_REPLY" }, 648 { BSN_PDU_RX_TIMEOUT, "PDU_RX_TIMEOUT" }, 649 { 0, NULL } 650 }; 651 652 #define BSN_ACTION_MIRROR 1 653 #define BSN_ACTION_SET_TUNNEL_DST 2 654 /* 3 */ 655 #define BSN_ACTION_CHECKSUM 4 656 657 static const struct tok bsn_action_subtype_str[] = { 658 { BSN_ACTION_MIRROR, "MIRROR" }, 659 { BSN_ACTION_SET_TUNNEL_DST, "SET_TUNNEL_DST" }, 660 { BSN_ACTION_CHECKSUM, "CHECKSUM" }, 661 { 0, NULL } 662 }; 663 664 static const struct tok bsn_mirror_copy_stage_str[] = { 665 { 0, "INGRESS" }, 666 { 1, "EGRESS" }, 667 { 0, NULL }, 668 }; 669 670 static const struct tok bsn_onoff_str[] = { 671 { 0, "OFF" }, 672 { 1, "ON" }, 673 { 0, NULL }, 674 }; 675 676 static const char * 677 vlan_str(const uint16_t vid) 678 { 679 static char buf[sizeof("65535 (bogus)")]; 680 681 if (vid == OFP_VLAN_NONE) 682 return "NONE"; 683 snprintf(buf, sizeof(buf), "%u%s", vid, 684 (vid > 0 && vid < 0x0fff) ? "" : " (bogus)"); 685 return buf; 686 } 687 688 static const char * 689 pcp_str(const uint8_t pcp) 690 { 691 static char buf[sizeof("255 (bogus)")]; 692 snprintf(buf, sizeof(buf), "%u%s", pcp, 693 pcp <= 7 ? "" : " (bogus)"); 694 return buf; 695 } 696 697 static void 698 of10_bsn_message_print(netdissect_options *ndo, 699 const u_char *cp, u_int len) 700 { 701 uint32_t subtype; 702 703 if (len < 4) 704 goto invalid; 705 /* subtype */ 706 subtype = GET_BE_U_4(cp); 707 OF_FWD(4); 708 ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype)); 709 switch (subtype) { 710 case BSN_GET_IP_MASK_REQUEST: 711 /* 712 * 0 1 2 3 713 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 714 * +---------------+---------------+---------------+---------------+ 715 * | subtype | 716 * +---------------+---------------+---------------+---------------+ 717 * | index | pad | 718 * +---------------+---------------+---------------+---------------+ 719 * | pad | 720 * +---------------+---------------+---------------+---------------+ 721 * 722 */ 723 if (len != 8) 724 goto invalid; 725 /* index */ 726 ND_PRINT(", index %u", GET_U_1(cp)); 727 OF_FWD(1); 728 /* pad */ 729 /* Always the last field, check bounds. */ 730 ND_TCHECK_7(cp); 731 break; 732 case BSN_SET_IP_MASK: 733 case BSN_GET_IP_MASK_REPLY: 734 /* 735 * 0 1 2 3 736 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 737 * +---------------+---------------+---------------+---------------+ 738 * | subtype | 739 * +---------------+---------------+---------------+---------------+ 740 * | index | pad | 741 * +---------------+---------------+---------------+---------------+ 742 * | mask | 743 * +---------------+---------------+---------------+---------------+ 744 * 745 */ 746 if (len != 8) 747 goto invalid; 748 /* index */ 749 ND_PRINT(", index %u", GET_U_1(cp)); 750 OF_FWD(1); 751 /* pad */ 752 OF_FWD(3); 753 /* mask */ 754 ND_PRINT(", mask %s", GET_IPADDR_STRING(cp)); 755 break; 756 case BSN_SET_MIRRORING: 757 case BSN_GET_MIRRORING_REQUEST: 758 case BSN_GET_MIRRORING_REPLY: 759 /* 760 * 0 1 2 3 761 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 762 * +---------------+---------------+---------------+---------------+ 763 * | subtype | 764 * +---------------+---------------+---------------+---------------+ 765 * | report m. p. | pad | 766 * +---------------+---------------+---------------+---------------+ 767 * 768 */ 769 if (len != 4) 770 goto invalid; 771 /* report_mirror_ports */ 772 ND_PRINT(", report_mirror_ports %s", 773 tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp))); 774 OF_FWD(1); 775 /* pad */ 776 /* Always the last field, check bounds. */ 777 ND_TCHECK_3(cp); 778 break; 779 case BSN_GET_INTERFACES_REQUEST: 780 case BSN_GET_L2_TABLE_REQUEST: 781 case BSN_BW_ENABLE_GET_REQUEST: 782 case BSN_BW_CLEAR_DATA_REQUEST: 783 case BSN_HYBRID_GET_REQUEST: 784 /* 785 * 0 1 2 3 786 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 787 * +---------------+---------------+---------------+---------------+ 788 * | subtype | 789 * +---------------+---------------+---------------+---------------+ 790 * 791 */ 792 if (len) 793 goto invalid; 794 break; 795 case BSN_VIRTUAL_PORT_REMOVE_REQUEST: 796 /* 797 * 0 1 2 3 798 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 799 * +---------------+---------------+---------------+---------------+ 800 * | subtype | 801 * +---------------+---------------+---------------+---------------+ 802 * | vport_no | 803 * +---------------+---------------+---------------+---------------+ 804 * 805 */ 806 if (len != 4) 807 goto invalid; 808 /* vport_no */ 809 ND_PRINT(", vport_no %u", GET_BE_U_4(cp)); 810 break; 811 case BSN_SHELL_COMMAND: 812 /* 813 * 0 1 2 3 814 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 815 * +---------------+---------------+---------------+---------------+ 816 * | subtype | 817 * +---------------+---------------+---------------+---------------+ 818 * | service | 819 * +---------------+---------------+---------------+---------------+ 820 * | data ... 821 * +---------------+---------------+-------- 822 * 823 */ 824 if (len < 4) 825 goto invalid; 826 /* service */ 827 ND_PRINT(", service %u", GET_BE_U_4(cp)); 828 OF_FWD(4); 829 /* data */ 830 ND_PRINT(", data '"); 831 (void)nd_printn(ndo, cp, len, NULL); 832 ND_PRINT("'"); 833 break; 834 case BSN_SHELL_OUTPUT: 835 /* 836 * 0 1 2 3 837 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 838 * +---------------+---------------+---------------+---------------+ 839 * | subtype | 840 * +---------------+---------------+---------------+---------------+ 841 * | data ... 842 * +---------------+---------------+-------- 843 * 844 */ 845 /* already checked that len >= 4 */ 846 /* data */ 847 ND_PRINT(", data '"); 848 (void)nd_printn(ndo, cp, len, NULL); 849 ND_PRINT("'"); 850 break; 851 case BSN_SHELL_STATUS: 852 /* 853 * 0 1 2 3 854 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 855 * +---------------+---------------+---------------+---------------+ 856 * | subtype | 857 * +---------------+---------------+---------------+---------------+ 858 * | status | 859 * +---------------+---------------+---------------+---------------+ 860 * 861 */ 862 if (len != 4) 863 goto invalid; 864 /* status */ 865 ND_PRINT(", status 0x%08x", GET_BE_U_4(cp)); 866 break; 867 default: 868 ND_TCHECK_LEN(cp, len); 869 } 870 return; 871 872 invalid: /* skip the undersized data */ 873 nd_print_invalid(ndo); 874 ND_TCHECK_LEN(cp, len); 875 } 876 877 static void 878 of10_bsn_actions_print(netdissect_options *ndo, 879 const u_char *cp, u_int len) 880 { 881 uint32_t subtype, vlan_tag; 882 883 if (len < 4) 884 goto invalid; 885 /* subtype */ 886 subtype = GET_BE_U_4(cp); 887 OF_FWD(4); 888 ND_PRINT("\n\t subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype)); 889 switch (subtype) { 890 case BSN_ACTION_MIRROR: 891 /* 892 * 0 1 2 3 893 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 894 * +---------------+---------------+---------------+---------------+ 895 * | subtype | 896 * +---------------+---------------+---------------+---------------+ 897 * | dest_port | 898 * +---------------+---------------+---------------+---------------+ 899 * | vlan_tag | 900 * +---------------+---------------+---------------+---------------+ 901 * | copy_stage | pad | 902 * +---------------+---------------+---------------+---------------+ 903 * 904 */ 905 if (len != 12) 906 goto invalid; 907 /* dest_port */ 908 ND_PRINT(", dest_port %u", GET_BE_U_4(cp)); 909 OF_FWD(4); 910 /* vlan_tag */ 911 vlan_tag = GET_BE_U_4(cp); 912 OF_FWD(4); 913 switch (vlan_tag >> 16) { 914 case 0: 915 ND_PRINT(", vlan_tag none"); 916 break; 917 case ETHERTYPE_8021Q: 918 ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff)); 919 break; 920 default: 921 ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16); 922 } 923 /* copy_stage */ 924 ND_PRINT(", copy_stage %s", 925 tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp))); 926 OF_FWD(1); 927 /* pad */ 928 /* Always the last field, check bounds. */ 929 ND_TCHECK_3(cp); 930 break; 931 default: 932 ND_TCHECK_LEN(cp, len); 933 } 934 return; 935 936 invalid: 937 nd_print_invalid(ndo); 938 ND_TCHECK_LEN(cp, len); 939 } 940 941 static void 942 of10_vendor_action_print(netdissect_options *ndo, 943 const u_char *cp, u_int len) 944 { 945 uint32_t vendor; 946 void (*decoder)(netdissect_options *, const u_char *, u_int); 947 948 if (len < 4) 949 goto invalid; 950 /* vendor */ 951 vendor = GET_BE_U_4(cp); 952 OF_FWD(4); 953 ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)); 954 /* data */ 955 decoder = 956 vendor == OUI_BSN ? of10_bsn_actions_print : 957 of_data_print; 958 decoder(ndo, cp, len); 959 return; 960 961 invalid: /* skip the undersized data */ 962 nd_print_invalid(ndo); 963 ND_TCHECK_LEN(cp, len); 964 } 965 966 /* [OF10] Section 5.5.4 */ 967 static void 968 of10_vendor_message_print(netdissect_options *ndo, 969 const u_char *cp, u_int len) 970 { 971 uint32_t vendor; 972 void (*decoder)(netdissect_options *, const u_char *, u_int); 973 974 /* vendor */ 975 vendor = GET_BE_U_4(cp); 976 OF_FWD(4); 977 ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)); 978 /* data */ 979 decoder = 980 vendor == OUI_BSN ? of10_bsn_message_print : 981 of_data_print; 982 decoder(ndo, cp, len); 983 } 984 985 /* Vendor ID is mandatory, data is optional. */ 986 static void 987 of10_vendor_data_print(netdissect_options *ndo, 988 const u_char *cp, u_int len) 989 { 990 uint32_t vendor; 991 992 if (len < 4) 993 goto invalid; 994 /* vendor */ 995 vendor = GET_BE_U_4(cp); 996 OF_FWD(4); 997 ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor)); 998 /* data */ 999 of_data_print(ndo, cp, len); 1000 return; 1001 1002 invalid: /* skip the undersized data */ 1003 nd_print_invalid(ndo); 1004 ND_TCHECK_LEN(cp, len); 1005 } 1006 1007 static void 1008 of10_packet_data_print(netdissect_options *ndo, 1009 const u_char *cp, const u_int len) 1010 { 1011 if (len == 0) 1012 return; 1013 /* data */ 1014 ND_PRINT("\n\t data (%u octets)", len); 1015 if (ndo->ndo_vflag < 3) { 1016 ND_TCHECK_LEN(cp, len); 1017 return; 1018 } 1019 ndo->ndo_vflag -= 3; 1020 ND_PRINT(", frame decoding below\n"); 1021 /* 1022 * The encapsulated Ethernet frame is not necessarily the last 1023 * data of this packet (i.e. there may be more OpenFlow messages 1024 * after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in 1025 * which case the current (outer) packet's snapshot end is not 1026 * what ether_print() needs to decode an Ethernet frame nested in 1027 * the middle of a TCP payload. 1028 */ 1029 const u_char *snapend_save = ndo->ndo_snapend; 1030 ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend); 1031 ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL); 1032 ndo->ndo_snapend = snapend_save; 1033 ndo->ndo_vflag += 3; 1034 } 1035 1036 /* [OF10] Section 5.2.1 */ 1037 static void 1038 of10_phy_port_print(netdissect_options *ndo, 1039 const u_char *cp) 1040 { 1041 uint32_t state; 1042 1043 /* port_no */ 1044 ND_PRINT("\n\t port_no %s", 1045 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1046 cp += 2; 1047 /* hw_addr */ 1048 ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); 1049 cp += MAC_ADDR_LEN; 1050 /* name */ 1051 ND_PRINT(", name '"); 1052 nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN); 1053 ND_PRINT("'"); 1054 cp += OFP_MAX_PORT_NAME_LEN; 1055 1056 if (ndo->ndo_vflag < 2) { 1057 ND_TCHECK_LEN(cp, 24); 1058 return; 1059 } 1060 /* config */ 1061 ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); 1062 of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 1063 cp += 4; 1064 /* state */ 1065 state = GET_BE_U_4(cp); 1066 /* 1067 * Decode the code point and the single bit separately, but 1068 * format the result as a single sequence of comma-separated 1069 * strings (see the comments at the OFPPS_ props). 1070 */ 1071 ND_PRINT("\n\t state 0x%08x (%s%s)%s", state, 1072 tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK), 1073 state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "", 1074 state & OFPPS_U ? " (bogus)" : ""); 1075 cp += 4; 1076 /* curr */ 1077 ND_PRINT("\n\t curr 0x%08x", GET_BE_U_4(cp)); 1078 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1079 cp += 4; 1080 /* advertised */ 1081 ND_PRINT("\n\t advertised 0x%08x", GET_BE_U_4(cp)); 1082 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1083 cp += 4; 1084 /* supported */ 1085 ND_PRINT("\n\t supported 0x%08x", GET_BE_U_4(cp)); 1086 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1087 cp += 4; 1088 /* peer */ 1089 ND_PRINT("\n\t peer 0x%08x", GET_BE_U_4(cp)); 1090 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1091 } 1092 1093 /* [OF10] Section 5.2.2 */ 1094 static void 1095 of10_queue_props_print(netdissect_options *ndo, 1096 const u_char *cp, u_int len) 1097 { 1098 while (len) { 1099 uint16_t property, plen; 1100 u_char plen_bogus = 0, skip = 0; 1101 1102 if (len < OF_QUEUE_PROP_MINLEN) 1103 goto invalid; 1104 /* property */ 1105 property = GET_BE_U_2(cp); 1106 OF_FWD(2); 1107 ND_PRINT("\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property)); 1108 /* len */ 1109 plen = GET_BE_U_2(cp); 1110 OF_FWD(2); 1111 ND_PRINT(", len %u", plen); 1112 if (plen < OF_QUEUE_PROP_MINLEN || plen > len + 4) 1113 goto invalid; 1114 /* pad */ 1115 /* Sometimes the last field, check bounds. */ 1116 OF_CHK_FWD(4); 1117 /* property-specific constraints and decoding */ 1118 switch (property) { 1119 case OFPQT_NONE: 1120 plen_bogus = plen != OF_QUEUE_PROP_MINLEN; 1121 break; 1122 case OFPQT_MIN_RATE: 1123 plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN; 1124 break; 1125 default: 1126 skip = 1; 1127 } 1128 if (plen_bogus) { 1129 ND_PRINT(" (bogus)"); 1130 skip = 1; 1131 } 1132 if (skip) { 1133 /* 1134 * plen >= OF_QUEUE_PROP_MINLEN 1135 * cp is OF_QUEUE_PROP_MINLEN bytes in 1136 */ 1137 OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN); 1138 continue; 1139 } 1140 if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */ 1141 /* rate */ 1142 uint16_t rate = GET_BE_U_2(cp); 1143 OF_FWD(2); 1144 if (rate > 1000) 1145 ND_PRINT(", rate disabled"); 1146 else 1147 ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10); 1148 /* pad */ 1149 /* Sometimes the last field, check bounds. */ 1150 OF_CHK_FWD(6); 1151 } 1152 } /* while */ 1153 return; 1154 1155 invalid: /* skip the rest of queue properties */ 1156 nd_print_invalid(ndo); 1157 ND_TCHECK_LEN(cp, len); 1158 } 1159 1160 /* ibid */ 1161 static void 1162 of10_queues_print(netdissect_options *ndo, 1163 const u_char *cp, u_int len) 1164 { 1165 while (len) { 1166 uint16_t desclen; 1167 1168 if (len < OF_PACKET_QUEUE_MINLEN) 1169 goto invalid; 1170 /* queue_id */ 1171 ND_PRINT("\n\t queue_id %u", GET_BE_U_4(cp)); 1172 OF_FWD(4); 1173 /* len */ 1174 desclen = GET_BE_U_2(cp); 1175 OF_FWD(2); 1176 ND_PRINT(", len %u", desclen); 1177 if (desclen < OF_PACKET_QUEUE_MINLEN || desclen > len + 6) 1178 goto invalid; 1179 /* pad */ 1180 /* Sometimes the last field, check bounds. */ 1181 OF_CHK_FWD(2); 1182 /* properties */ 1183 if (ndo->ndo_vflag >= 2) 1184 of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN); 1185 else 1186 ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN); 1187 OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN); 1188 } /* while */ 1189 return; 1190 1191 invalid: /* skip the rest of queues */ 1192 nd_print_invalid(ndo); 1193 ND_TCHECK_LEN(cp, len); 1194 } 1195 1196 /* [OF10] Section 5.2.3 */ 1197 static void 1198 of10_match_print(netdissect_options *ndo, 1199 const char *pfx, const u_char *cp) 1200 { 1201 uint32_t wildcards; 1202 uint16_t dl_type; 1203 uint8_t nw_proto; 1204 u_int nw_bits; 1205 const char *field_name; 1206 1207 /* wildcards */ 1208 wildcards = GET_BE_U_4(cp); 1209 if (wildcards & OFPFW_U) 1210 ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards); 1211 cp += 4; 1212 /* in_port */ 1213 if (! (wildcards & OFPFW_IN_PORT)) 1214 ND_PRINT("%smatch in_port %s", pfx, 1215 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1216 cp += 2; 1217 /* dl_src */ 1218 if (! (wildcards & OFPFW_DL_SRC)) 1219 ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp)); 1220 cp += MAC_ADDR_LEN; 1221 /* dl_dst */ 1222 if (! (wildcards & OFPFW_DL_DST)) 1223 ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp)); 1224 cp += MAC_ADDR_LEN; 1225 /* dl_vlan */ 1226 if (! (wildcards & OFPFW_DL_VLAN)) 1227 ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp))); 1228 cp += 2; 1229 /* dl_vlan_pcp */ 1230 if (! (wildcards & OFPFW_DL_VLAN_PCP)) 1231 ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp))); 1232 cp += 1; 1233 /* pad1 */ 1234 cp += 1; 1235 /* dl_type */ 1236 dl_type = GET_BE_U_2(cp); 1237 cp += 2; 1238 if (! (wildcards & OFPFW_DL_TYPE)) 1239 ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type); 1240 /* nw_tos */ 1241 if (! (wildcards & OFPFW_NW_TOS)) 1242 ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp)); 1243 cp += 1; 1244 /* nw_proto */ 1245 nw_proto = GET_U_1(cp); 1246 cp += 1; 1247 if (! (wildcards & OFPFW_NW_PROTO)) { 1248 field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP 1249 ? "arp_opcode" : "nw_proto"; 1250 ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto); 1251 } 1252 /* pad2 */ 1253 cp += 2; 1254 /* nw_src */ 1255 nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT; 1256 if (nw_bits < 32) 1257 ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits); 1258 cp += 4; 1259 /* nw_dst */ 1260 nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT; 1261 if (nw_bits < 32) 1262 ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits); 1263 cp += 4; 1264 /* tp_src */ 1265 if (! (wildcards & OFPFW_TP_SRC)) { 1266 field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP 1267 && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP 1268 ? "icmp_type" : "tp_src"; 1269 ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp)); 1270 } 1271 cp += 2; 1272 /* tp_dst */ 1273 /* The last unconditional check was at nw_proto, so have an "else" here. */ 1274 if (! (wildcards & OFPFW_TP_DST)) { 1275 field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP 1276 && ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP 1277 ? "icmp_code" : "tp_dst"; 1278 ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp)); 1279 } 1280 else 1281 ND_TCHECK_2(cp); 1282 } 1283 1284 /* [OF10] Section 5.2.4 */ 1285 static void 1286 of10_actions_print(netdissect_options *ndo, 1287 const char *pfx, const u_char *cp, u_int len) 1288 { 1289 while (len) { 1290 uint16_t type, alen, output_port; 1291 u_char alen_bogus = 0, skip = 0; 1292 1293 if (len < OF_ACTION_MINLEN) 1294 goto invalid; 1295 /* type */ 1296 type = GET_BE_U_2(cp); 1297 OF_FWD(2); 1298 ND_PRINT("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type)); 1299 /* length */ 1300 alen = GET_BE_U_2(cp); 1301 OF_FWD(2); 1302 ND_PRINT(", len %u", alen); 1303 /* 1304 * The 4-byte "pad" in the specification is not a field of the 1305 * action header, but a placeholder to illustrate the 64-bit 1306 * alignment requirement. Action type specific case blocks 1307 * below fetch these 4 bytes. 1308 */ 1309 1310 /* On action size underrun/overrun skip the rest of the action list. */ 1311 if (alen < OF_ACTION_MINLEN || alen > len + 4) 1312 goto invalid; 1313 /* 1314 * After validating the basic length constraint it will be safe 1315 * to skip the current action if the action size is not valid 1316 * for the type or the type is invalid. 1317 */ 1318 switch (type) { 1319 case OFPAT_OUTPUT: 1320 case OFPAT_SET_VLAN_VID: 1321 case OFPAT_SET_VLAN_PCP: 1322 case OFPAT_STRIP_VLAN: 1323 case OFPAT_SET_NW_SRC: 1324 case OFPAT_SET_NW_DST: 1325 case OFPAT_SET_NW_TOS: 1326 case OFPAT_SET_TP_SRC: 1327 case OFPAT_SET_TP_DST: 1328 alen_bogus = alen != 8; 1329 break; 1330 case OFPAT_SET_DL_SRC: 1331 case OFPAT_SET_DL_DST: 1332 case OFPAT_ENQUEUE: 1333 alen_bogus = alen != 16; 1334 break; 1335 case OFPAT_VENDOR: 1336 alen_bogus = alen % 8 != 0; /* already >= 8 so far */ 1337 break; 1338 default: 1339 skip = 1; 1340 } 1341 if (alen_bogus) { 1342 ND_PRINT(" (bogus)"); 1343 skip = 1; 1344 } 1345 if (skip) { 1346 /* 1347 * alen >= OF_ACTION_MINLEN 1348 * cp is 4 bytes in 1349 */ 1350 OF_CHK_FWD(alen - 4); 1351 continue; 1352 } 1353 /* OK to decode the rest of the action structure */ 1354 switch (type) { 1355 case OFPAT_OUTPUT: 1356 /* port */ 1357 output_port = GET_BE_U_2(cp); 1358 OF_FWD(2); 1359 ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port)); 1360 /* max_len */ 1361 if (output_port == OFPP_CONTROLLER) 1362 ND_PRINT(", max_len %u", GET_BE_U_2(cp)); 1363 else 1364 ND_TCHECK_2(cp); 1365 OF_FWD(2); 1366 break; 1367 case OFPAT_SET_VLAN_VID: 1368 /* vlan_vid */ 1369 ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp))); 1370 OF_FWD(2); 1371 /* pad */ 1372 /* Sometimes the last field, check bounds. */ 1373 OF_CHK_FWD(2); 1374 break; 1375 case OFPAT_SET_VLAN_PCP: 1376 /* vlan_pcp */ 1377 ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp))); 1378 OF_FWD(1); 1379 /* pad */ 1380 /* Sometimes the last field, check bounds. */ 1381 OF_CHK_FWD(3); 1382 break; 1383 case OFPAT_SET_DL_SRC: 1384 case OFPAT_SET_DL_DST: 1385 /* dl_addr */ 1386 ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp)); 1387 OF_FWD(MAC_ADDR_LEN); 1388 /* pad */ 1389 /* Sometimes the last field, check bounds. */ 1390 OF_CHK_FWD(6); 1391 break; 1392 case OFPAT_SET_NW_SRC: 1393 case OFPAT_SET_NW_DST: 1394 /* nw_addr */ 1395 ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp)); 1396 OF_FWD(4); 1397 break; 1398 case OFPAT_SET_NW_TOS: 1399 /* nw_tos */ 1400 ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp)); 1401 OF_FWD(1); 1402 /* pad */ 1403 /* Sometimes the last field, check bounds. */ 1404 OF_CHK_FWD(3); 1405 break; 1406 case OFPAT_SET_TP_SRC: 1407 case OFPAT_SET_TP_DST: 1408 /* nw_tos */ 1409 ND_PRINT(", tp_port %u", GET_BE_U_2(cp)); 1410 OF_FWD(2); 1411 /* pad */ 1412 /* Sometimes the last field, check bounds. */ 1413 OF_CHK_FWD(2); 1414 break; 1415 case OFPAT_ENQUEUE: 1416 /* port */ 1417 ND_PRINT(", port %s", 1418 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1419 OF_FWD(2); 1420 /* pad */ 1421 OF_FWD(6); 1422 /* queue_id */ 1423 ND_PRINT(", queue_id %s", 1424 tok2str(ofpq_str, "%u", GET_BE_U_4(cp))); 1425 OF_FWD(4); 1426 break; 1427 case OFPAT_VENDOR: 1428 of10_vendor_action_print(ndo, cp, alen - 4); 1429 OF_FWD(alen - 4); 1430 break; 1431 case OFPAT_STRIP_VLAN: 1432 /* pad */ 1433 /* Sometimes the last field, check bounds. */ 1434 OF_CHK_FWD(4); 1435 break; 1436 } /* switch */ 1437 } /* while */ 1438 return; 1439 1440 invalid: /* skip the rest of actions */ 1441 nd_print_invalid(ndo); 1442 ND_TCHECK_LEN(cp, len); 1443 } 1444 1445 /* [OF10] Section 5.3.1 */ 1446 static void 1447 of10_features_reply_print(netdissect_options *ndo, 1448 const u_char *cp, u_int len) 1449 { 1450 /* datapath_id */ 1451 ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp)); 1452 OF_FWD(8); 1453 /* n_buffers */ 1454 ND_PRINT(", n_buffers %u", GET_BE_U_4(cp)); 1455 OF_FWD(4); 1456 /* n_tables */ 1457 ND_PRINT(", n_tables %u", GET_U_1(cp)); 1458 OF_FWD(1); 1459 /* pad */ 1460 OF_FWD(3); 1461 /* capabilities */ 1462 ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp)); 1463 of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U); 1464 OF_FWD(4); 1465 /* actions */ 1466 ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp)); 1467 of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U); 1468 OF_FWD(4); 1469 /* ports */ 1470 while (len) { 1471 if (len < OF_PHY_PORT_FIXLEN) 1472 goto invalid; 1473 of10_phy_port_print(ndo, cp); 1474 OF_FWD(OF_PHY_PORT_FIXLEN); 1475 } 1476 return; 1477 1478 invalid: /* skip the undersized trailing data */ 1479 nd_print_invalid(ndo); 1480 ND_TCHECK_LEN(cp, len); 1481 } 1482 1483 /* [OF10] Section 5.3.2 */ 1484 static void 1485 of10_switch_config_msg_print(netdissect_options *ndo, 1486 const u_char *cp, u_int len _U_) 1487 { 1488 /* flags */ 1489 ND_PRINT("\n\t flags %s", 1490 tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp))); 1491 cp += 2; 1492 /* miss_send_len */ 1493 ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp)); 1494 } 1495 1496 /* [OF10] Section 5.3.3 */ 1497 static void 1498 of10_flow_mod_print(netdissect_options *ndo, 1499 const u_char *cp, u_int len) 1500 { 1501 uint16_t command; 1502 1503 /* match */ 1504 of10_match_print(ndo, "\n\t ", cp); 1505 OF_FWD(OF_MATCH_FIXLEN); 1506 /* cookie */ 1507 ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp)); 1508 OF_FWD(8); 1509 /* command */ 1510 command = GET_BE_U_2(cp); 1511 ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command)); 1512 OF_FWD(2); 1513 /* idle_timeout */ 1514 if (GET_BE_U_2(cp)) 1515 ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp)); 1516 OF_FWD(2); 1517 /* hard_timeout */ 1518 if (GET_BE_U_2(cp)) 1519 ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp)); 1520 OF_FWD(2); 1521 /* priority */ 1522 if (GET_BE_U_2(cp)) 1523 ND_PRINT(", priority %u", GET_BE_U_2(cp)); 1524 OF_FWD(2); 1525 /* buffer_id */ 1526 if (command == OFPFC_ADD || command == OFPFC_MODIFY || 1527 command == OFPFC_MODIFY_STRICT) 1528 ND_PRINT(", buffer_id %s", 1529 tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp))); 1530 OF_FWD(4); 1531 /* out_port */ 1532 if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT) 1533 ND_PRINT(", out_port %s", 1534 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1535 OF_FWD(2); 1536 /* flags */ 1537 ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp)); 1538 of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U); 1539 OF_FWD(2); 1540 /* actions */ 1541 of10_actions_print(ndo, "\n\t ", cp, len); 1542 } 1543 1544 /* ibid */ 1545 static void 1546 of10_port_mod_print(netdissect_options *ndo, 1547 const u_char *cp, u_int len _U_) 1548 { 1549 /* port_no */ 1550 ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1551 cp += 2; 1552 /* hw_addr */ 1553 ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp)); 1554 cp += MAC_ADDR_LEN; 1555 /* config */ 1556 ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp)); 1557 of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 1558 cp += 4; 1559 /* mask */ 1560 ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp)); 1561 of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U); 1562 cp += 4; 1563 /* advertise */ 1564 ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp)); 1565 of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U); 1566 cp += 4; 1567 /* pad */ 1568 /* Always the last field, check bounds. */ 1569 ND_TCHECK_4(cp); 1570 } 1571 1572 /* [OF10] Section 5.3.4 */ 1573 static void 1574 of10_queue_get_config_request_print(netdissect_options *ndo, 1575 const u_char *cp, u_int len _U_) 1576 { 1577 /* port */ 1578 ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1579 cp += 2; 1580 /* pad */ 1581 /* Always the last field, check bounds. */ 1582 ND_TCHECK_2(cp); 1583 } 1584 1585 /* ibid */ 1586 static void 1587 of10_queue_get_config_reply_print(netdissect_options *ndo, 1588 const u_char *cp, u_int len) 1589 { 1590 /* port */ 1591 ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1592 OF_FWD(2); 1593 /* pad */ 1594 /* Sometimes the last field, check bounds. */ 1595 OF_CHK_FWD(6); 1596 /* queues */ 1597 of10_queues_print(ndo, cp, len); 1598 } 1599 1600 /* [OF10] Section 5.3.5 */ 1601 static void 1602 of10_stats_request_print(netdissect_options *ndo, 1603 const u_char *cp, u_int len) 1604 { 1605 uint16_t type; 1606 1607 /* type */ 1608 type = GET_BE_U_2(cp); 1609 OF_FWD(2); 1610 ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)); 1611 /* flags */ 1612 ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp)); 1613 if (GET_BE_U_2(cp)) 1614 ND_PRINT(" (bogus)"); 1615 OF_FWD(2); 1616 /* type-specific body of one of fixed lengths */ 1617 switch(type) { 1618 case OFPST_DESC: 1619 case OFPST_TABLE: 1620 if (len) 1621 goto invalid; 1622 return; 1623 case OFPST_FLOW: 1624 case OFPST_AGGREGATE: 1625 if (len != OF_FLOW_STATS_REQUEST_FIXLEN) 1626 goto invalid; 1627 /* match */ 1628 of10_match_print(ndo, "\n\t ", cp); 1629 OF_FWD(OF_MATCH_FIXLEN); 1630 /* table_id */ 1631 ND_PRINT("\n\t table_id %s", 1632 tok2str(tableid_str, "%u", GET_U_1(cp))); 1633 OF_FWD(1); 1634 /* pad */ 1635 OF_FWD(1); 1636 /* out_port */ 1637 ND_PRINT(", out_port %s", 1638 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1639 return; 1640 case OFPST_PORT: 1641 if (len != OF_PORT_STATS_REQUEST_FIXLEN) 1642 goto invalid; 1643 /* port_no */ 1644 ND_PRINT("\n\t port_no %s", 1645 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1646 OF_FWD(2); 1647 /* pad */ 1648 /* Always the last field, check bounds. */ 1649 OF_CHK_FWD(6); 1650 return; 1651 case OFPST_QUEUE: 1652 if (len != OF_QUEUE_STATS_REQUEST_FIXLEN) 1653 goto invalid; 1654 /* port_no */ 1655 ND_PRINT("\n\t port_no %s", 1656 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1657 OF_FWD(2); 1658 /* pad */ 1659 OF_FWD(2); 1660 /* queue_id */ 1661 ND_PRINT(", queue_id %s", 1662 tok2str(ofpq_str, "%u", GET_BE_U_4(cp))); 1663 return; 1664 case OFPST_VENDOR: 1665 of10_vendor_data_print(ndo, cp, len); 1666 return; 1667 } 1668 return; 1669 1670 invalid: /* skip the message body */ 1671 nd_print_invalid(ndo); 1672 ND_TCHECK_LEN(cp, len); 1673 } 1674 1675 /* ibid */ 1676 static void 1677 of10_desc_stats_reply_print(netdissect_options *ndo, 1678 const u_char *cp, u_int len) 1679 { 1680 if (len != OF_DESC_STATS_REPLY_FIXLEN) 1681 goto invalid; 1682 /* mfr_desc */ 1683 ND_PRINT("\n\t mfr_desc '"); 1684 nd_printjnp(ndo, cp, DESC_STR_LEN); 1685 ND_PRINT("'"); 1686 OF_FWD(DESC_STR_LEN); 1687 /* hw_desc */ 1688 ND_PRINT("\n\t hw_desc '"); 1689 nd_printjnp(ndo, cp, DESC_STR_LEN); 1690 ND_PRINT("'"); 1691 OF_FWD(DESC_STR_LEN); 1692 /* sw_desc */ 1693 ND_PRINT("\n\t sw_desc '"); 1694 nd_printjnp(ndo, cp, DESC_STR_LEN); 1695 ND_PRINT("'"); 1696 OF_FWD(DESC_STR_LEN); 1697 /* serial_num */ 1698 ND_PRINT("\n\t serial_num '"); 1699 nd_printjnp(ndo, cp, SERIAL_NUM_LEN); 1700 ND_PRINT("'"); 1701 OF_FWD(SERIAL_NUM_LEN); 1702 /* dp_desc */ 1703 ND_PRINT("\n\t dp_desc '"); 1704 nd_printjnp(ndo, cp, DESC_STR_LEN); 1705 ND_PRINT("'"); 1706 return; 1707 1708 invalid: /* skip the message body */ 1709 nd_print_invalid(ndo); 1710 ND_TCHECK_LEN(cp, len); 1711 } 1712 1713 /* ibid */ 1714 static void 1715 of10_flow_stats_reply_print(netdissect_options *ndo, 1716 const u_char *cp, u_int len) 1717 { 1718 while (len) { 1719 uint16_t entry_len; 1720 1721 if (len < OF_FLOW_STATS_REPLY_MINLEN) 1722 goto invalid; 1723 /* length */ 1724 entry_len = GET_BE_U_2(cp); 1725 ND_PRINT("\n\t length %u", entry_len); 1726 if (entry_len < OF_FLOW_STATS_REPLY_MINLEN || entry_len > len) 1727 goto invalid; 1728 OF_FWD(2); 1729 /* table_id */ 1730 ND_PRINT(", table_id %s", 1731 tok2str(tableid_str, "%u", GET_U_1(cp))); 1732 OF_FWD(1); 1733 /* pad */ 1734 OF_FWD(1); 1735 /* match */ 1736 of10_match_print(ndo, "\n\t ", cp); 1737 OF_FWD(OF_MATCH_FIXLEN); 1738 /* duration_sec */ 1739 ND_PRINT("\n\t duration_sec %u", GET_BE_U_4(cp)); 1740 OF_FWD(4); 1741 /* duration_nsec */ 1742 ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp)); 1743 OF_FWD(4); 1744 /* priority */ 1745 ND_PRINT(", priority %u", GET_BE_U_2(cp)); 1746 OF_FWD(2); 1747 /* idle_timeout */ 1748 ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp)); 1749 OF_FWD(2); 1750 /* hard_timeout */ 1751 ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp)); 1752 OF_FWD(2); 1753 /* pad2 */ 1754 OF_FWD(6); 1755 /* cookie */ 1756 ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp)); 1757 OF_FWD(8); 1758 /* packet_count */ 1759 ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp)); 1760 OF_FWD(8); 1761 /* byte_count */ 1762 ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); 1763 OF_FWD(8); 1764 /* actions */ 1765 of10_actions_print(ndo, "\n\t ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN); 1766 OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN); 1767 } /* while */ 1768 return; 1769 1770 invalid: /* skip the rest of flow statistics entries */ 1771 nd_print_invalid(ndo); 1772 ND_TCHECK_LEN(cp, len); 1773 } 1774 1775 /* ibid */ 1776 static void 1777 of10_aggregate_stats_reply_print(netdissect_options *ndo, 1778 const u_char *cp, u_int len) 1779 { 1780 if (len != OF_AGGREGATE_STATS_REPLY_FIXLEN) 1781 goto invalid; 1782 /* packet_count */ 1783 ND_PRINT("\n\t packet_count %" PRIu64, GET_BE_U_8(cp)); 1784 OF_FWD(8); 1785 /* byte_count */ 1786 ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); 1787 OF_FWD(8); 1788 /* flow_count */ 1789 ND_PRINT(", flow_count %u", GET_BE_U_4(cp)); 1790 OF_FWD(4); 1791 /* pad */ 1792 /* Always the last field, check bounds. */ 1793 ND_TCHECK_4(cp); 1794 return; 1795 1796 invalid: /* skip the message body */ 1797 nd_print_invalid(ndo); 1798 ND_TCHECK_LEN(cp, len); 1799 } 1800 1801 /* ibid */ 1802 static void 1803 of10_table_stats_reply_print(netdissect_options *ndo, 1804 const u_char *cp, u_int len) 1805 { 1806 while (len) { 1807 if (len < OF_TABLE_STATS_REPLY_FIXLEN) 1808 goto invalid; 1809 /* table_id */ 1810 ND_PRINT("\n\t table_id %s", 1811 tok2str(tableid_str, "%u", GET_U_1(cp))); 1812 OF_FWD(1); 1813 /* pad */ 1814 OF_FWD(3); 1815 /* name */ 1816 ND_PRINT(", name '"); 1817 nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN); 1818 ND_PRINT("'"); 1819 OF_FWD(OFP_MAX_TABLE_NAME_LEN); 1820 /* wildcards */ 1821 ND_PRINT("\n\t wildcards 0x%08x", GET_BE_U_4(cp)); 1822 of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U); 1823 OF_FWD(4); 1824 /* max_entries */ 1825 ND_PRINT("\n\t max_entries %u", GET_BE_U_4(cp)); 1826 OF_FWD(4); 1827 /* active_count */ 1828 ND_PRINT(", active_count %u", GET_BE_U_4(cp)); 1829 OF_FWD(4); 1830 /* lookup_count */ 1831 ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp)); 1832 OF_FWD(8); 1833 /* matched_count */ 1834 ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp)); 1835 OF_FWD(8); 1836 } /* while */ 1837 return; 1838 1839 invalid: /* skip the undersized trailing data */ 1840 nd_print_invalid(ndo); 1841 ND_TCHECK_LEN(cp, len); 1842 } 1843 1844 /* ibid */ 1845 static void 1846 of10_port_stats_reply_print(netdissect_options *ndo, 1847 const u_char *cp, u_int len) 1848 { 1849 while (len) { 1850 if (len < OF_PORT_STATS_REPLY_FIXLEN) 1851 goto invalid; 1852 /* port_no */ 1853 ND_PRINT("\n\t port_no %s", 1854 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1855 OF_FWD(2); 1856 if (ndo->ndo_vflag < 2) { 1857 OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2); 1858 continue; 1859 } 1860 /* pad */ 1861 OF_FWD(6); 1862 /* rx_packets */ 1863 ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp)); 1864 OF_FWD(8); 1865 /* tx_packets */ 1866 ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp)); 1867 OF_FWD(8); 1868 /* rx_bytes */ 1869 ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp)); 1870 OF_FWD(8); 1871 /* tx_bytes */ 1872 ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp)); 1873 OF_FWD(8); 1874 /* rx_dropped */ 1875 ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp)); 1876 OF_FWD(8); 1877 /* tx_dropped */ 1878 ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp)); 1879 OF_FWD(8); 1880 /* rx_errors */ 1881 ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp)); 1882 OF_FWD(8); 1883 /* tx_errors */ 1884 ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp)); 1885 OF_FWD(8); 1886 /* rx_frame_err */ 1887 ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp)); 1888 OF_FWD(8); 1889 /* rx_over_err */ 1890 ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp)); 1891 OF_FWD(8); 1892 /* rx_crc_err */ 1893 ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp)); 1894 OF_FWD(8); 1895 /* collisions */ 1896 ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp)); 1897 OF_FWD(8); 1898 } /* while */ 1899 return; 1900 1901 invalid: /* skip the undersized trailing data */ 1902 nd_print_invalid(ndo); 1903 ND_TCHECK_LEN(cp, len); 1904 } 1905 1906 /* ibid */ 1907 static void 1908 of10_queue_stats_reply_print(netdissect_options *ndo, 1909 const u_char *cp, u_int len) 1910 { 1911 while (len) { 1912 if (len < OF_QUEUE_STATS_REPLY_FIXLEN) 1913 goto invalid; 1914 /* port_no */ 1915 ND_PRINT("\n\t port_no %s", 1916 tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1917 OF_FWD(2); 1918 /* pad */ 1919 OF_FWD(2); 1920 /* queue_id */ 1921 ND_PRINT(", queue_id %u", GET_BE_U_4(cp)); 1922 OF_FWD(4); 1923 /* tx_bytes */ 1924 ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp)); 1925 OF_FWD(8); 1926 /* tx_packets */ 1927 ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp)); 1928 OF_FWD(8); 1929 /* tx_errors */ 1930 ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp)); 1931 OF_FWD(8); 1932 } /* while */ 1933 return; 1934 1935 invalid: /* skip the undersized trailing data */ 1936 nd_print_invalid(ndo); 1937 ND_TCHECK_LEN(cp, len); 1938 } 1939 1940 /* ibid */ 1941 static void 1942 of10_stats_reply_print(netdissect_options *ndo, 1943 const u_char *cp, u_int len) 1944 { 1945 uint16_t type; 1946 1947 /* type */ 1948 type = GET_BE_U_2(cp); 1949 ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type)); 1950 OF_FWD(2); 1951 /* flags */ 1952 ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp)); 1953 of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U); 1954 OF_FWD(2); 1955 1956 if (ndo->ndo_vflag > 0) { 1957 void (*decoder)(netdissect_options *, const u_char *, u_int) = 1958 type == OFPST_DESC ? of10_desc_stats_reply_print : 1959 type == OFPST_FLOW ? of10_flow_stats_reply_print : 1960 type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print : 1961 type == OFPST_TABLE ? of10_table_stats_reply_print : 1962 type == OFPST_PORT ? of10_port_stats_reply_print : 1963 type == OFPST_QUEUE ? of10_queue_stats_reply_print : 1964 type == OFPST_VENDOR ? of10_vendor_data_print : 1965 NULL; 1966 if (decoder != NULL) { 1967 decoder(ndo, cp, len); 1968 return; 1969 } 1970 } 1971 ND_TCHECK_LEN(cp, len); 1972 } 1973 1974 /* [OF10] Section 5.3.6 */ 1975 static void 1976 of10_packet_out_print(netdissect_options *ndo, 1977 const u_char *cp, u_int len) 1978 { 1979 uint16_t actions_len; 1980 1981 /* buffer_id */ 1982 ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp)); 1983 OF_FWD(4); 1984 /* in_port */ 1985 ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 1986 OF_FWD(2); 1987 /* actions_len */ 1988 actions_len = GET_BE_U_2(cp); 1989 OF_FWD(2); 1990 if (actions_len > len) 1991 goto invalid; 1992 /* actions */ 1993 of10_actions_print(ndo, "\n\t ", cp, actions_len); 1994 OF_FWD(actions_len); 1995 /* data */ 1996 of10_packet_data_print(ndo, cp, len); 1997 return; 1998 1999 invalid: /* skip the rest of the message body */ 2000 nd_print_invalid(ndo); 2001 ND_TCHECK_LEN(cp, len); 2002 } 2003 2004 /* [OF10] Section 5.4.1 */ 2005 static void 2006 of10_packet_in_print(netdissect_options *ndo, 2007 const u_char *cp, u_int len) 2008 { 2009 /* buffer_id */ 2010 ND_PRINT("\n\t buffer_id %s", 2011 tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp))); 2012 OF_FWD(4); 2013 /* total_len */ 2014 ND_PRINT(", total_len %u", GET_BE_U_2(cp)); 2015 OF_FWD(2); 2016 /* in_port */ 2017 ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp))); 2018 OF_FWD(2); 2019 /* reason */ 2020 ND_PRINT(", reason %s", 2021 tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp))); 2022 OF_FWD(1); 2023 /* pad */ 2024 /* Sometimes the last field, check bounds. */ 2025 OF_CHK_FWD(1); 2026 /* data */ 2027 of10_packet_data_print(ndo, cp, len); 2028 } 2029 2030 /* [OF10] Section 5.4.2 */ 2031 static void 2032 of10_flow_removed_print(netdissect_options *ndo, 2033 const u_char *cp, u_int len _U_) 2034 { 2035 /* match */ 2036 of10_match_print(ndo, "\n\t ", cp); 2037 cp += OF_MATCH_FIXLEN; 2038 /* cookie */ 2039 ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp)); 2040 cp += 8; 2041 /* priority */ 2042 if (GET_BE_U_2(cp)) 2043 ND_PRINT(", priority %u", GET_BE_U_2(cp)); 2044 cp += 2; 2045 /* reason */ 2046 ND_PRINT(", reason %s", 2047 tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp))); 2048 cp += 1; 2049 /* pad */ 2050 cp += 1; 2051 /* duration_sec */ 2052 ND_PRINT(", duration_sec %u", GET_BE_U_4(cp)); 2053 cp += 4; 2054 /* duration_nsec */ 2055 ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp)); 2056 cp += 4; 2057 /* idle_timeout */ 2058 if (GET_BE_U_2(cp)) 2059 ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp)); 2060 cp += 2; 2061 /* pad2 */ 2062 cp += 2; 2063 /* packet_count */ 2064 ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp)); 2065 cp += 8; 2066 /* byte_count */ 2067 ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp)); 2068 } 2069 2070 /* [OF10] Section 5.4.3 */ 2071 static void 2072 of10_port_status_print(netdissect_options *ndo, 2073 const u_char *cp, u_int len _U_) 2074 { 2075 /* reason */ 2076 ND_PRINT("\n\t reason %s", 2077 tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp))); 2078 cp += 1; 2079 /* pad */ 2080 /* No need to check bounds, more data follows. */ 2081 cp += 7; 2082 /* desc */ 2083 of10_phy_port_print(ndo, cp); 2084 } 2085 2086 /* [OF10] Section 5.4.4 */ 2087 static void 2088 of10_error_print(netdissect_options *ndo, 2089 const u_char *cp, u_int len) 2090 { 2091 uint16_t type, code; 2092 const struct tok *code_str; 2093 2094 /* type */ 2095 type = GET_BE_U_2(cp); 2096 OF_FWD(2); 2097 ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type)); 2098 /* code */ 2099 code = GET_BE_U_2(cp); 2100 OF_FWD(2); 2101 code_str = uint2tokary(of10_ofpet2tokary, type); 2102 if (code_str != NULL) 2103 ND_PRINT(", code %s", 2104 tok2str(code_str, "invalid (0x%04x)", code)); 2105 else 2106 ND_PRINT(", code invalid (0x%04x)", code); 2107 /* data */ 2108 of_data_print(ndo, cp, len); 2109 } 2110 2111 static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = { 2112 /* 2113 * [OF10] Section 5.5.1 2114 * Variable-size data. 2115 */ 2116 { 2117 "HELLO", of_data_print, 2118 REQ_MINLEN, 0 2119 }, 2120 /* 2121 * [OF10] Section 5.4.4 2122 * A fixed-size message body and variable-size data. 2123 */ 2124 { 2125 "ERROR", of10_error_print, 2126 REQ_MINLEN, OF_ERROR_MSG_MINLEN 2127 }, 2128 /* 2129 * [OF10] Section 5.5.2 2130 * Variable-size data. 2131 */ 2132 { 2133 "ECHO_REQUEST", of_data_print, 2134 REQ_MINLEN, 0 2135 }, 2136 /* 2137 * [OF10] Section 5.5.3 2138 * Variable-size data. 2139 */ 2140 { 2141 "ECHO_REPLY", of_data_print, 2142 REQ_MINLEN, 0 2143 }, 2144 /* 2145 * [OF10] Section 5.5.4 2146 * A fixed-size message body and variable-size data. 2147 */ 2148 { 2149 "VENDOR", of10_vendor_message_print, 2150 REQ_MINLEN, OF_VENDOR_MINLEN 2151 }, 2152 /* 2153 * [OF10] Section 5.3.1 2154 * No message body. 2155 */ 2156 { 2157 "FEATURES_REQUEST", NULL, 2158 REQ_FIXLEN, 0 2159 }, 2160 /* 2161 * [OF10] Section 5.3.1 2162 * A fixed-size message body and n * fixed-size data units. 2163 */ 2164 { 2165 "FEATURES_REPLY", of10_features_reply_print, 2166 REQ_MINLEN, OF_FEATURES_REPLY_MINLEN 2167 }, 2168 /* 2169 * [OF10] Section 5.3.2 2170 * No message body. 2171 */ 2172 { 2173 "GET_CONFIG_REQUEST", NULL, 2174 REQ_FIXLEN, 0 2175 }, 2176 /* 2177 * [OF10] Section 5.3.2 2178 * A fixed-size message body. 2179 */ 2180 { 2181 "GET_CONFIG_REPLY", of10_switch_config_msg_print, 2182 REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN 2183 }, 2184 /* 2185 * [OF10] Section 5.3.2 2186 * A fixed-size message body. 2187 */ 2188 { 2189 "SET_CONFIG", of10_switch_config_msg_print, 2190 REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN 2191 }, 2192 /* 2193 * [OF10] Section 5.4.1 2194 * A fixed-size message body and variable-size data. 2195 * (The 2 mock octets count in OF_PACKET_IN_MINLEN only.) 2196 */ 2197 { 2198 "PACKET_IN", of10_packet_in_print, 2199 REQ_MINLEN, OF_PACKET_IN_MINLEN - 2 2200 }, 2201 /* 2202 * [OF10] Section 5.4.2 2203 * A fixed-size message body. 2204 */ 2205 { 2206 "FLOW_REMOVED", of10_flow_removed_print, 2207 REQ_FIXLEN, OF_FLOW_REMOVED_FIXLEN 2208 }, 2209 /* 2210 * [OF10] Section 5.4.3 2211 * A fixed-size message body. 2212 */ 2213 { 2214 "PORT_STATUS", of10_port_status_print, 2215 REQ_FIXLEN, OF_PORT_STATUS_FIXLEN 2216 }, 2217 /* 2218 * [OF10] Section 5.3.6 2219 * A fixed-size message body, n * variable-size data units and 2220 * variable-size data. 2221 */ 2222 { 2223 "PACKET_OUT", of10_packet_out_print, 2224 REQ_MINLEN, OF_PACKET_OUT_MINLEN 2225 }, 2226 /* 2227 * [OF10] Section 5.3.3 2228 * A fixed-size message body and n * variable-size data units. 2229 */ 2230 { 2231 "FLOW_MOD", of10_flow_mod_print, 2232 REQ_MINLEN, OF_FLOW_MOD_MINLEN 2233 }, 2234 /* 2235 * [OF10] Section 5.3.3 2236 * A fixed-size message body. 2237 */ 2238 { 2239 "PORT_MOD", of10_port_mod_print, 2240 REQ_FIXLEN, OF_PORT_MOD_FIXLEN 2241 }, 2242 /* 2243 * [OF10] Section 5.3.5 2244 * A fixed-size message body and possibly more data of varying size 2245 * and structure. 2246 */ 2247 { 2248 "STATS_REQUEST", of10_stats_request_print, 2249 REQ_MINLEN, OF_STATS_REQUEST_MINLEN 2250 }, 2251 /* 2252 * [OF10] Section 5.3.5 2253 * A fixed-size message body and possibly more data of varying size 2254 * and structure. 2255 */ 2256 { 2257 "STATS_REPLY", of10_stats_reply_print, 2258 REQ_MINLEN, OF_STATS_REPLY_MINLEN 2259 }, 2260 /* 2261 * [OF10] Section 5.3.7 2262 * No message body. 2263 */ 2264 { 2265 "BARRIER_REQUEST", NULL, 2266 REQ_FIXLEN, 0 2267 }, 2268 /* 2269 * [OF10] Section 5.3.7 2270 * No message body. 2271 */ 2272 { 2273 "BARRIER_REPLY", NULL, 2274 REQ_FIXLEN, 0 2275 }, 2276 /* 2277 * [OF10] Section 5.3.4 2278 * A fixed-size message body. 2279 */ 2280 { 2281 "QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print, 2282 REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN 2283 }, 2284 /* 2285 * [OF10] Section 5.3.4 2286 * A fixed-size message body and n * variable-size data units. 2287 */ 2288 { 2289 "QUEUE_GET_CONFIG_REPLY", of10_queue_get_config_reply_print, 2290 REQ_MINLEN, OF_QUEUE_GET_CONFIG_REPLY_MINLEN 2291 }, 2292 }; 2293 2294 const struct of_msgtypeinfo * 2295 of10_identify_msgtype(const uint8_t type) 2296 { 2297 return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL; 2298 } 2299