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