1*c47fd378Schristos /* 2*c47fd378Schristos * This module implements decoding of the Loopback Protocol, originally 3*c47fd378Schristos * defined as the Configuration Testing Protocol. It is based on the following 4*c47fd378Schristos * specification: 5*c47fd378Schristos * http://www.mit.edu/people/jhawk/ctp.pdf 6*c47fd378Schristos * 7*c47fd378Schristos * Copyright (c) 2014 The TCPDUMP project 8*c47fd378Schristos * All rights reserved. 9*c47fd378Schristos * 10*c47fd378Schristos * Redistribution and use in source and binary forms, with or without 11*c47fd378Schristos * modification, are permitted provided that the following conditions 12*c47fd378Schristos * are met: 13*c47fd378Schristos * 1. Redistributions of source code must retain the above copyright 14*c47fd378Schristos * notice, this list of conditions and the following disclaimer. 15*c47fd378Schristos * 2. Redistributions in binary form must reproduce the above copyright 16*c47fd378Schristos * notice, this list of conditions and the following disclaimer in the 17*c47fd378Schristos * documentation and/or other materials provided with the distribution. 18*c47fd378Schristos * 19*c47fd378Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*c47fd378Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*c47fd378Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22*c47fd378Schristos * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23*c47fd378Schristos * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24*c47fd378Schristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25*c47fd378Schristos * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26*c47fd378Schristos * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27*c47fd378Schristos * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*c47fd378Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29*c47fd378Schristos * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30*c47fd378Schristos * POSSIBILITY OF SUCH DAMAGE. 31*c47fd378Schristos */ 32*c47fd378Schristos 33*c47fd378Schristos #define NETDISSECT_REWORKED 34*c47fd378Schristos #ifdef HAVE_CONFIG_H 35*c47fd378Schristos #include "config.h" 36*c47fd378Schristos #endif 37*c47fd378Schristos 38*c47fd378Schristos #include <tcpdump-stdinc.h> 39*c47fd378Schristos 40*c47fd378Schristos #include "interface.h" 41*c47fd378Schristos #include "extract.h" 42*c47fd378Schristos #include "ether.h" 43*c47fd378Schristos #include "addrtoname.h" 44*c47fd378Schristos 45*c47fd378Schristos static const char tstr[] = " [|loopback]"; 46*c47fd378Schristos static const char cstr[] = " (corrupt)"; 47*c47fd378Schristos 48*c47fd378Schristos #define LOOPBACK_REPLY 1 49*c47fd378Schristos #define LOOPBACK_FWDDATA 2 50*c47fd378Schristos 51*c47fd378Schristos static const struct tok fcode_str[] = { 52*c47fd378Schristos { LOOPBACK_REPLY, "Reply" }, 53*c47fd378Schristos { LOOPBACK_FWDDATA, "Forward Data" }, 54*c47fd378Schristos { 0, NULL } 55*c47fd378Schristos }; 56*c47fd378Schristos 57*c47fd378Schristos static void 58*c47fd378Schristos loopback_message_print(netdissect_options *ndo, const u_char *cp, const u_int len) 59*c47fd378Schristos { 60*c47fd378Schristos const u_char *ep = cp + len; 61*c47fd378Schristos uint16_t function; 62*c47fd378Schristos 63*c47fd378Schristos if (len < 2) 64*c47fd378Schristos goto corrupt; 65*c47fd378Schristos /* function */ 66*c47fd378Schristos ND_TCHECK2(*cp, 2); 67*c47fd378Schristos function = EXTRACT_LE_16BITS(cp); 68*c47fd378Schristos cp += 2; 69*c47fd378Schristos ND_PRINT((ndo, ", %s", tok2str(fcode_str, " invalid (%u)", function))); 70*c47fd378Schristos 71*c47fd378Schristos switch (function) { 72*c47fd378Schristos case LOOPBACK_REPLY: 73*c47fd378Schristos if (len < 4) 74*c47fd378Schristos goto corrupt; 75*c47fd378Schristos /* receipt number */ 76*c47fd378Schristos ND_TCHECK2(*cp, 2); 77*c47fd378Schristos ND_PRINT((ndo, ", receipt number %u", EXTRACT_LE_16BITS(cp))); 78*c47fd378Schristos cp += 2; 79*c47fd378Schristos /* data */ 80*c47fd378Schristos ND_PRINT((ndo, ", data (%u octets)", len - 4)); 81*c47fd378Schristos ND_TCHECK2(*cp, len - 4); 82*c47fd378Schristos break; 83*c47fd378Schristos case LOOPBACK_FWDDATA: 84*c47fd378Schristos if (len < 8) 85*c47fd378Schristos goto corrupt; 86*c47fd378Schristos /* forwarding address */ 87*c47fd378Schristos ND_TCHECK2(*cp, ETHER_ADDR_LEN); 88*c47fd378Schristos ND_PRINT((ndo, ", forwarding address %s", etheraddr_string(ndo, cp))); 89*c47fd378Schristos cp += ETHER_ADDR_LEN; 90*c47fd378Schristos /* data */ 91*c47fd378Schristos ND_PRINT((ndo, ", data (%u octets)", len - 8)); 92*c47fd378Schristos ND_TCHECK2(*cp, len - 8); 93*c47fd378Schristos break; 94*c47fd378Schristos default: 95*c47fd378Schristos ND_TCHECK2(*cp, len - 2); 96*c47fd378Schristos break; 97*c47fd378Schristos } 98*c47fd378Schristos return; 99*c47fd378Schristos 100*c47fd378Schristos corrupt: 101*c47fd378Schristos ND_PRINT((ndo, "%s", cstr)); 102*c47fd378Schristos ND_TCHECK2(*cp, ep - cp); 103*c47fd378Schristos return; 104*c47fd378Schristos trunc: 105*c47fd378Schristos ND_PRINT((ndo, "%s", tstr)); 106*c47fd378Schristos } 107*c47fd378Schristos 108*c47fd378Schristos void 109*c47fd378Schristos loopback_print(netdissect_options *ndo, const u_char *cp, const u_int len) 110*c47fd378Schristos { 111*c47fd378Schristos const u_char *ep = cp + len; 112*c47fd378Schristos uint16_t skipCount; 113*c47fd378Schristos 114*c47fd378Schristos ND_PRINT((ndo, "Loopback")); 115*c47fd378Schristos if (len < 2) 116*c47fd378Schristos goto corrupt; 117*c47fd378Schristos /* skipCount */ 118*c47fd378Schristos ND_TCHECK2(*cp, 2); 119*c47fd378Schristos skipCount = EXTRACT_LE_16BITS(cp); 120*c47fd378Schristos cp += 2; 121*c47fd378Schristos ND_PRINT((ndo, ", skipCount %u", skipCount)); 122*c47fd378Schristos if (skipCount % 8) 123*c47fd378Schristos ND_PRINT((ndo, " (bogus)")); 124*c47fd378Schristos if (skipCount > len - 2) 125*c47fd378Schristos goto corrupt; 126*c47fd378Schristos loopback_message_print(ndo, cp + skipCount, len - 2 - skipCount); 127*c47fd378Schristos return; 128*c47fd378Schristos 129*c47fd378Schristos corrupt: 130*c47fd378Schristos ND_PRINT((ndo, "%s", cstr)); 131*c47fd378Schristos ND_TCHECK2(*cp, ep - cp); 132*c47fd378Schristos return; 133*c47fd378Schristos trunc: 134*c47fd378Schristos ND_PRINT((ndo, "%s", tstr)); 135*c47fd378Schristos } 136*c47fd378Schristos 137