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