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