2 * Routines for OpenFlow dissection
3 * Copyright 2013, Anders Broman <anders.broman@ericsson.com>
4 * Copyright 2013, Zoltan Lajos Kis <zoltan.lajos.kis@ericsson.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Ref https://www.opennetworking.org/sdn-resources/onf-specifications/openflow
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/prefs.h>
21 #include "packet-tcp.h"
23 void proto_register_openflow(void);
24 void proto_reg_handoff_openflow(void);
26 #define OFP_LEGACY_PORT 6633
27 #define OFP_LEGACY2_PORT 6634
28 #define OFP_IANA_PORT 6653
29 static range_t
*g_openflow_ports
;
31 static dissector_handle_t openflow_handle
;
32 static dissector_handle_t openflow_v1_handle
;
33 static dissector_handle_t openflow_v4_handle
;
34 static dissector_handle_t openflow_v5_handle
;
35 static dissector_handle_t openflow_v6_handle
;
37 /* Initialize the protocol and registered fields */
38 static int proto_openflow
;
39 static int hf_openflow_version
;
41 static expert_field ei_openflow_version
;
43 static bool openflow_desegment
= true;
45 #define OFP_VERSION_1_0 1
46 #define OFP_VERSION_1_1 2
47 #define OFP_VERSION_1_2 3
48 #define OFP_VERSION_1_3 4
49 #define OFP_VERSION_1_4 5
50 #define OFP_VERSION_1_5 6
52 static const value_string openflow_version_values
[] = {
53 { OFP_VERSION_1_0
, "1.0" },
54 { OFP_VERSION_1_1
, "1.1" },
55 { OFP_VERSION_1_2
, "1.2" },
56 { OFP_VERSION_1_3
, "1.3" },
57 { OFP_VERSION_1_4
, "1.4" },
58 { OFP_VERSION_1_5
, "1.5" },
63 get_openflow_pdu_length(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
64 int offset
, void *data _U_
)
66 return tvb_get_ntohs(tvb
, offset
+ 2);
70 dissect_openflow_tcp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
76 version
= tvb_get_uint8(tvb
, 0);
77 /* Set the Protocol column to the constant string of openflow */
78 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "OpenFlow");
79 col_clear(pinfo
->cinfo
,COL_INFO
);
83 call_dissector(openflow_v1_handle
, tvb
, pinfo
, tree
);
86 call_dissector(openflow_v4_handle
, tvb
, pinfo
, tree
);
89 call_dissector(openflow_v5_handle
, tvb
, pinfo
, tree
);
92 call_dissector(openflow_v6_handle
, tvb
, pinfo
, tree
);
95 ti
= proto_tree_add_item(tree
, hf_openflow_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
96 expert_add_info(pinfo
, ti
, &ei_openflow_version
);
99 return tvb_reported_length(tvb
);
102 #define OFP_HEADER_LEN 8
104 dissect_openflow(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
106 tcp_dissect_pdus(tvb
, pinfo
, tree
, openflow_desegment
, OFP_HEADER_LEN
,
107 get_openflow_pdu_length
, dissect_openflow_tcp_pdu
, data
);
108 return tvb_captured_length(tvb
);
112 dissect_openflow_heur(tvbuff_t
*tvb
, packet_info
*pinfo
,
113 proto_tree
*tree
, void *data
)
115 conversation_t
*conversation
= NULL
;
117 if ((pinfo
->destport
!= OFP_LEGACY_PORT
) &&
118 (pinfo
->destport
!= OFP_LEGACY2_PORT
) &&
119 (pinfo
->destport
!= OFP_IANA_PORT
) &&
120 (!value_is_in_range(g_openflow_ports
, pinfo
->destport
))) {
124 conversation
= find_or_create_conversation(pinfo
);
125 conversation_set_dissector(conversation
, openflow_handle
);
127 dissect_openflow(tvb
, pinfo
, tree
, data
);
132 apply_openflow_prefs(void)
134 /* Openflow uses the port preference for heuristics */
135 g_openflow_ports
= prefs_get_range_value("openflow", "tcp.port");
139 * Register the protocol with Wireshark.
142 proto_register_openflow(void)
144 static hf_register_info hf
[] = {
145 { &hf_openflow_version
,
146 { "Version", "openflow.version",
147 FT_UINT8
, BASE_HEX
, VALS(openflow_version_values
), 0x7f,
152 static ei_register_info ei
[] = {
153 { &ei_openflow_version
, { "openflow.version.unknown", PI_UNDECODED
, PI_WARN
, "Unsupported version not dissected", EXPFILL
}},
156 module_t
*openflow_module
;
157 expert_module_t
* expert_openflow
;
159 /* Register the protocol name and description */
160 proto_openflow
= proto_register_protocol("OpenFlow", "OpenFlow", "openflow");
162 openflow_handle
= register_dissector("openflow", dissect_openflow
, proto_openflow
);
164 /* Required function calls to register the header fields and subtrees */
165 proto_register_field_array(proto_openflow
, hf
, array_length(hf
));
166 expert_openflow
= expert_register_protocol(proto_openflow
);
167 expert_register_field_array(expert_openflow
, ei
, array_length(ei
));
169 openflow_module
= prefs_register_protocol(proto_openflow
, apply_openflow_prefs
);
171 /* Register heuristic preference */
172 prefs_register_obsolete_preference(openflow_module
, "heuristic");
174 /* Register desegment preference */
175 prefs_register_bool_preference(openflow_module
, "desegment",
176 "Reassemble OpenFlow messages spanning multiple TCP segments",
177 "Whether the OpenFlow dissector should reassemble messages spanning multiple TCP segments."
178 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
179 &openflow_desegment
);
183 proto_reg_handoff_openflow(void)
185 heur_dissector_add("tcp", dissect_openflow_heur
, "OpenFlow over TCP", "openflow_tcp", proto_openflow
, HEURISTIC_ENABLE
);
187 dissector_add_uint_with_preference("tcp.port", OFP_IANA_PORT
, openflow_handle
);
189 openflow_v1_handle
= find_dissector_add_dependency("openflow_v1", proto_openflow
);
190 openflow_v4_handle
= find_dissector_add_dependency("openflow_v4", proto_openflow
);
191 openflow_v5_handle
= find_dissector_add_dependency("openflow_v5", proto_openflow
);
192 openflow_v6_handle
= find_dissector_add_dependency("openflow_v6", proto_openflow
);
193 apply_openflow_prefs();
197 * Editor modelines - https://www.wireshark.org/tools/modelines.html
202 * indent-tabs-mode: nil
205 * vi: set shiftwidth=4 tabstop=8 expandtab:
206 * :indentSize=4:tabSize=8:noTabs=true: