1026d7285Schristos /* 2026d7285Schristos * This module implements printing of the very basic (version-independent) 3026d7285Schristos * OpenFlow header and iteration over OpenFlow messages. It is intended for 4026d7285Schristos * dispatching of version-specific OpenFlow message decoding. 5026d7285Schristos * 6026d7285Schristos * 7026d7285Schristos * Copyright (c) 2013 The TCPDUMP project 8026d7285Schristos * All rights reserved. 9026d7285Schristos * 10026d7285Schristos * Redistribution and use in source and binary forms, with or without 11026d7285Schristos * modification, are permitted provided that the following conditions 12026d7285Schristos * are met: 13026d7285Schristos * 1. Redistributions of source code must retain the above copyright 14026d7285Schristos * notice, this list of conditions and the following disclaimer. 15026d7285Schristos * 2. Redistributions in binary form must reproduce the above copyright 16026d7285Schristos * notice, this list of conditions and the following disclaimer in the 17026d7285Schristos * documentation and/or other materials provided with the distribution. 18026d7285Schristos * 19026d7285Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20026d7285Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21026d7285Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22026d7285Schristos * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23026d7285Schristos * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24026d7285Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25026d7285Schristos * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26026d7285Schristos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27026d7285Schristos * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28026d7285Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29026d7285Schristos * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30026d7285Schristos * POSSIBILITY OF SUCH DAMAGE. 31026d7285Schristos */ 32026d7285Schristos 33*c47fd378Schristos #define NETDISSECT_REWORKED 34026d7285Schristos #ifdef HAVE_CONFIG_H 35026d7285Schristos #include "config.h" 36026d7285Schristos #endif 37026d7285Schristos 38026d7285Schristos #include <tcpdump-stdinc.h> 39026d7285Schristos 40026d7285Schristos #include "interface.h" 41026d7285Schristos #include "extract.h" 42026d7285Schristos #include "openflow.h" 43026d7285Schristos 44*c47fd378Schristos static const char tstr[] = " [|openflow]"; 45*c47fd378Schristos static const char cstr[] = " (corrupt)"; 46*c47fd378Schristos 47026d7285Schristos #define OF_VER_1_0 0x01 48026d7285Schristos 49026d7285Schristos static void 50*c47fd378Schristos of_header_print(netdissect_options *ndo, const uint8_t version, const uint8_t type, 51026d7285Schristos const uint16_t length, const uint32_t xid) { 52*c47fd378Schristos ND_PRINT((ndo, "\n\tversion unknown (0x%02x), type 0x%02x, length %u, xid 0x%08x", 53*c47fd378Schristos version, type, length, xid)); 54026d7285Schristos } 55026d7285Schristos 56026d7285Schristos /* Print a single OpenFlow message. */ 57026d7285Schristos static const u_char * 58*c47fd378Schristos of_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { 59026d7285Schristos uint8_t version, type; 60026d7285Schristos uint16_t length; 61026d7285Schristos uint32_t xid; 62026d7285Schristos 63026d7285Schristos if (ep < cp + OF_HEADER_LEN) 64026d7285Schristos goto corrupt; 65026d7285Schristos /* version */ 66*c47fd378Schristos ND_TCHECK2(*cp, 1); 67026d7285Schristos version = *cp; 68026d7285Schristos cp += 1; 69026d7285Schristos /* type */ 70*c47fd378Schristos ND_TCHECK2(*cp, 1); 71026d7285Schristos type = *cp; 72026d7285Schristos cp += 1; 73026d7285Schristos /* length */ 74*c47fd378Schristos ND_TCHECK2(*cp, 2); 75026d7285Schristos length = EXTRACT_16BITS(cp); 76026d7285Schristos cp += 2; 77026d7285Schristos /* xid */ 78*c47fd378Schristos ND_TCHECK2(*cp, 4); 79026d7285Schristos xid = EXTRACT_32BITS(cp); 80026d7285Schristos cp += 4; 81026d7285Schristos /* Message length includes the header length and a message always includes 82026d7285Schristos * the basic header. A message length underrun fails decoding of the rest of 83026d7285Schristos * the current packet. At the same time, try decoding as much of the current 84026d7285Schristos * message as possible even when it does not end within the current TCP 85026d7285Schristos * segment. */ 86026d7285Schristos if (length < OF_HEADER_LEN) { 87*c47fd378Schristos of_header_print(ndo, version, type, length, xid); 88026d7285Schristos goto corrupt; 89026d7285Schristos } 90026d7285Schristos /* Decode known protocol versions further without printing the header (the 91026d7285Schristos * type decoding is version-specific. */ 92026d7285Schristos switch (version) { 93026d7285Schristos case OF_VER_1_0: 94*c47fd378Schristos return of10_header_body_print(ndo, cp, ep, type, length, xid); 95026d7285Schristos default: 96*c47fd378Schristos of_header_print(ndo, version, type, length, xid); 97*c47fd378Schristos ND_TCHECK2(*cp, length - OF_HEADER_LEN); 98026d7285Schristos return cp + length - OF_HEADER_LEN; /* done with current message */ 99026d7285Schristos } 100026d7285Schristos 101026d7285Schristos corrupt: /* fail current packet */ 102*c47fd378Schristos ND_PRINT((ndo, "%s", cstr)); 103*c47fd378Schristos ND_TCHECK2(*cp, ep - cp); 104026d7285Schristos return ep; 105026d7285Schristos trunc: 106*c47fd378Schristos ND_PRINT((ndo, "%s", tstr)); 107026d7285Schristos return ep; 108026d7285Schristos } 109026d7285Schristos 110026d7285Schristos /* Print a TCP segment worth of OpenFlow messages presuming the segment begins 111026d7285Schristos * on a message boundary. */ 112026d7285Schristos void 113*c47fd378Schristos openflow_print(netdissect_options *ndo, const u_char *cp, const u_int len) { 114026d7285Schristos const u_char *ep = cp + len; 115026d7285Schristos 116*c47fd378Schristos ND_PRINT((ndo, ": OpenFlow")); 117026d7285Schristos while (cp < ep) 118*c47fd378Schristos cp = of_header_body_print(ndo, cp, ep); 119026d7285Schristos } 120