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