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