Home | History | Annotate | Download | only in tcpdump
      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 malformed 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 #define NETDISSECT_REWORKED
     60 #ifdef HAVE_CONFIG_H
     61 #include "config.h"
     62 #endif
     63 
     64 #include <tcpdump-stdinc.h>
     65 
     66 #include "interface.h"
     67 #include "extract.h"
     68 #include "addrtoname.h"
     69 #include "ether.h"
     70 #include "ethertype.h"
     71 #include "ipproto.h"
     72 #include "oui.h"
     73 #include "openflow.h"
     74 
     75 static const char tstr[] = " [|openflow]";
     76 static const char cstr[] = " (corrupt)";
     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 corrupt;
    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 corrupt;
    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 corrupt;
    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 corrupt;
    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 corrupt;
    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 corrupt;
    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 corrupt;
    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 corrupt;
    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 corrupt: /* skip the undersized data */
    952 	ND_PRINT((ndo, "%s", cstr));
    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 corrupt;
    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 corrupt;
    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 corrupt:
   1026 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized data */
   1055 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized data */
   1084 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized data */
   1110 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized trailing data */
   1207 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt;
   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 corrupt: /* skip the rest of queue properties */
   1283 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt;
   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 corrupt: /* skip the rest of queues */
   1331 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt;
   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 corrupt: /* skip the rest of actions */
   1602 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   1770 		return cp;
   1771 	case OFPST_FLOW:
   1772 	case OFPST_AGGREGATE:
   1773 		if (len != OF_FLOW_STATS_REQUEST_LEN)
   1774 			goto corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt: /* skip the message body */
   1819 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the message body */
   1866 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt;
   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 corrupt: /* skip the rest of flow statistics entries */
   1947 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the message body */
   1980 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized trailing data */
   2039 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized trailing data */
   2124 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the undersized trailing data */
   2172 	ND_PRINT((ndo, "%s", cstr));
   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 corrupt;
   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 corrupt: /* skip the rest of the message body */
   2250 	ND_PRINT((ndo, "%s", cstr));
   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 	 * corrupt, 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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt;
   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 corrupt: /* skip the message body */
   2553 	ND_PRINT((ndo, "%s", cstr));
   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