xref: /minix3/external/bsd/tcpdump/dist/print-openflow.c (revision b636d99d91c3d54204248f643c14627405d4afd1)
1*b636d99dSDavid van Moolenbroek /*
2*b636d99dSDavid van Moolenbroek  * This module implements printing of the very basic (version-independent)
3*b636d99dSDavid van Moolenbroek  * OpenFlow header and iteration over OpenFlow messages. It is intended for
4*b636d99dSDavid van Moolenbroek  * dispatching of version-specific OpenFlow message decoding.
5*b636d99dSDavid van Moolenbroek  *
6*b636d99dSDavid van Moolenbroek  *
7*b636d99dSDavid van Moolenbroek  * Copyright (c) 2013 The TCPDUMP project
8*b636d99dSDavid van Moolenbroek  * All rights reserved.
9*b636d99dSDavid van Moolenbroek  *
10*b636d99dSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
11*b636d99dSDavid van Moolenbroek  * modification, are permitted provided that the following conditions
12*b636d99dSDavid van Moolenbroek  * are met:
13*b636d99dSDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
14*b636d99dSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
15*b636d99dSDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
16*b636d99dSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
17*b636d99dSDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
18*b636d99dSDavid van Moolenbroek  *
19*b636d99dSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*b636d99dSDavid van Moolenbroek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*b636d99dSDavid van Moolenbroek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22*b636d99dSDavid van Moolenbroek  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23*b636d99dSDavid van Moolenbroek  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24*b636d99dSDavid van Moolenbroek  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25*b636d99dSDavid van Moolenbroek  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26*b636d99dSDavid van Moolenbroek  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27*b636d99dSDavid van Moolenbroek  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28*b636d99dSDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29*b636d99dSDavid van Moolenbroek  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30*b636d99dSDavid van Moolenbroek  * POSSIBILITY OF SUCH DAMAGE.
31*b636d99dSDavid van Moolenbroek  */
32*b636d99dSDavid van Moolenbroek 
33*b636d99dSDavid van Moolenbroek #define NETDISSECT_REWORKED
34*b636d99dSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
35*b636d99dSDavid van Moolenbroek #include "config.h"
36*b636d99dSDavid van Moolenbroek #endif
37*b636d99dSDavid van Moolenbroek 
38*b636d99dSDavid van Moolenbroek #include <tcpdump-stdinc.h>
39*b636d99dSDavid van Moolenbroek 
40*b636d99dSDavid van Moolenbroek #include "interface.h"
41*b636d99dSDavid van Moolenbroek #include "extract.h"
42*b636d99dSDavid van Moolenbroek #include "openflow.h"
43*b636d99dSDavid van Moolenbroek #include "oui.h"
44*b636d99dSDavid van Moolenbroek 
45*b636d99dSDavid van Moolenbroek static const char tstr[] = " [|openflow]";
46*b636d99dSDavid van Moolenbroek static const char cstr[] = " (corrupt)";
47*b636d99dSDavid van Moolenbroek 
48*b636d99dSDavid van Moolenbroek #define OF_VER_1_0    0x01
49*b636d99dSDavid van Moolenbroek 
50*b636d99dSDavid van Moolenbroek const struct tok onf_exp_str[] = {
51*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_ONF,               "ONF Extensions"                                  },
52*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_BUTE,              "Budapest University of Technology and Economics" },
53*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_NOVIFLOW,          "NoviFlow"                                        },
54*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_L3,                "L3+ Extensions, Vendor Neutral"                  },
55*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_L4L7,              "L4-L7 Extensions"                                },
56*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_WMOB,              "Wireless and Mobility Extensions"                },
57*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_FABS,              "Forwarding Abstractions Extensions"              },
58*b636d99dSDavid van Moolenbroek 	{ ONF_EXP_OTRANS,            "Optical Transport Extensions"                    },
59*b636d99dSDavid van Moolenbroek 	{ 0, NULL }
60*b636d99dSDavid van Moolenbroek };
61*b636d99dSDavid van Moolenbroek 
62*b636d99dSDavid van Moolenbroek const char *
of_vendor_name(const uint32_t vendor)63*b636d99dSDavid van Moolenbroek of_vendor_name(const uint32_t vendor)
64*b636d99dSDavid van Moolenbroek {
65*b636d99dSDavid van Moolenbroek 	const struct tok *table = (vendor & 0xff000000) == 0 ? oui_values : onf_exp_str;
66*b636d99dSDavid van Moolenbroek 	return tok2str(table, "unknown", vendor);
67*b636d99dSDavid van Moolenbroek }
68*b636d99dSDavid van Moolenbroek 
69*b636d99dSDavid van Moolenbroek static void
of_header_print(netdissect_options * ndo,const uint8_t version,const uint8_t type,const uint16_t length,const uint32_t xid)70*b636d99dSDavid van Moolenbroek of_header_print(netdissect_options *ndo, const uint8_t version, const uint8_t type,
71*b636d99dSDavid van Moolenbroek                       const uint16_t length, const uint32_t xid)
72*b636d99dSDavid van Moolenbroek {
73*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "\n\tversion unknown (0x%02x), type 0x%02x, length %u, xid 0x%08x",
74*b636d99dSDavid van Moolenbroek 	       version, type, length, xid));
75*b636d99dSDavid van Moolenbroek }
76*b636d99dSDavid van Moolenbroek 
77*b636d99dSDavid van Moolenbroek /* Print a single OpenFlow message. */
78*b636d99dSDavid van Moolenbroek static const u_char *
of_header_body_print(netdissect_options * ndo,const u_char * cp,const u_char * ep)79*b636d99dSDavid van Moolenbroek of_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
80*b636d99dSDavid van Moolenbroek {
81*b636d99dSDavid van Moolenbroek 	uint8_t version, type;
82*b636d99dSDavid van Moolenbroek 	uint16_t length;
83*b636d99dSDavid van Moolenbroek 	uint32_t xid;
84*b636d99dSDavid van Moolenbroek 
85*b636d99dSDavid van Moolenbroek 	if (ep < cp + OF_HEADER_LEN)
86*b636d99dSDavid van Moolenbroek 		goto corrupt;
87*b636d99dSDavid van Moolenbroek 	/* version */
88*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*cp, 1);
89*b636d99dSDavid van Moolenbroek 	version = *cp;
90*b636d99dSDavid van Moolenbroek 	cp += 1;
91*b636d99dSDavid van Moolenbroek 	/* type */
92*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*cp, 1);
93*b636d99dSDavid van Moolenbroek 	type = *cp;
94*b636d99dSDavid van Moolenbroek 	cp += 1;
95*b636d99dSDavid van Moolenbroek 	/* length */
96*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*cp, 2);
97*b636d99dSDavid van Moolenbroek 	length = EXTRACT_16BITS(cp);
98*b636d99dSDavid van Moolenbroek 	cp += 2;
99*b636d99dSDavid van Moolenbroek 	/* xid */
100*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*cp, 4);
101*b636d99dSDavid van Moolenbroek 	xid = EXTRACT_32BITS(cp);
102*b636d99dSDavid van Moolenbroek 	cp += 4;
103*b636d99dSDavid van Moolenbroek 	/* Message length includes the header length and a message always includes
104*b636d99dSDavid van Moolenbroek 	 * the basic header. A message length underrun fails decoding of the rest of
105*b636d99dSDavid van Moolenbroek 	 * the current packet. At the same time, try decoding as much of the current
106*b636d99dSDavid van Moolenbroek 	 * message as possible even when it does not end within the current TCP
107*b636d99dSDavid van Moolenbroek 	 * segment. */
108*b636d99dSDavid van Moolenbroek 	if (length < OF_HEADER_LEN) {
109*b636d99dSDavid van Moolenbroek 		of_header_print(ndo, version, type, length, xid);
110*b636d99dSDavid van Moolenbroek 		goto corrupt;
111*b636d99dSDavid van Moolenbroek 	}
112*b636d99dSDavid van Moolenbroek 	/* Decode known protocol versions further without printing the header (the
113*b636d99dSDavid van Moolenbroek 	 * type decoding is version-specific. */
114*b636d99dSDavid van Moolenbroek 	switch (version) {
115*b636d99dSDavid van Moolenbroek 	case OF_VER_1_0:
116*b636d99dSDavid van Moolenbroek 		return of10_header_body_print(ndo, cp, ep, type, length, xid);
117*b636d99dSDavid van Moolenbroek 	default:
118*b636d99dSDavid van Moolenbroek 		of_header_print(ndo, version, type, length, xid);
119*b636d99dSDavid van Moolenbroek 		ND_TCHECK2(*cp, length - OF_HEADER_LEN);
120*b636d99dSDavid van Moolenbroek 		return cp + length - OF_HEADER_LEN; /* done with current message */
121*b636d99dSDavid van Moolenbroek 	}
122*b636d99dSDavid van Moolenbroek 
123*b636d99dSDavid van Moolenbroek corrupt: /* fail current packet */
124*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s", cstr));
125*b636d99dSDavid van Moolenbroek 	ND_TCHECK2(*cp, ep - cp);
126*b636d99dSDavid van Moolenbroek 	return ep;
127*b636d99dSDavid van Moolenbroek trunc:
128*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, "%s", tstr));
129*b636d99dSDavid van Moolenbroek 	return ep;
130*b636d99dSDavid van Moolenbroek }
131*b636d99dSDavid van Moolenbroek 
132*b636d99dSDavid van Moolenbroek /* Print a TCP segment worth of OpenFlow messages presuming the segment begins
133*b636d99dSDavid van Moolenbroek  * on a message boundary. */
134*b636d99dSDavid van Moolenbroek void
openflow_print(netdissect_options * ndo,const u_char * cp,const u_int len)135*b636d99dSDavid van Moolenbroek openflow_print(netdissect_options *ndo, const u_char *cp, const u_int len)
136*b636d99dSDavid van Moolenbroek {
137*b636d99dSDavid van Moolenbroek 	const u_char *ep = cp + len;
138*b636d99dSDavid van Moolenbroek 
139*b636d99dSDavid van Moolenbroek 	ND_PRINT((ndo, ": OpenFlow"));
140*b636d99dSDavid van Moolenbroek 	while (cp < ep)
141*b636d99dSDavid van Moolenbroek 		cp = of_header_body_print(ndo, cp, ep);
142*b636d99dSDavid van Moolenbroek }
143