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.3 2017/01/24 23:29:14 christos Exp $"); 36 #endif 37 38 #ifdef HAVE_CONFIG_H 39 #include "config.h" 40 #endif 41 42 #include <netdissect-stdinc.h> 43 44 #include "netdissect.h" 45 #include "extract.h" 46 #include "ether.h" 47 #include "addrtoname.h" 48 49 static const char tstr[] = " [|loopback]"; 50 51 #define LOOPBACK_REPLY 1 52 #define LOOPBACK_FWDDATA 2 53 54 static const struct tok fcode_str[] = { 55 { LOOPBACK_REPLY, "Reply" }, 56 { LOOPBACK_FWDDATA, "Forward Data" }, 57 { 0, NULL } 58 }; 59 60 static void 61 loopback_message_print(netdissect_options *ndo, const u_char *cp, const u_int len) 62 { 63 const u_char *ep = cp + len; 64 uint16_t function; 65 66 if (len < 2) 67 goto invalid; 68 /* function */ 69 ND_TCHECK2(*cp, 2); 70 function = EXTRACT_LE_16BITS(cp); 71 cp += 2; 72 ND_PRINT((ndo, ", %s", tok2str(fcode_str, " invalid (%u)", function))); 73 74 switch (function) { 75 case LOOPBACK_REPLY: 76 if (len < 4) 77 goto invalid; 78 /* receipt number */ 79 ND_TCHECK2(*cp, 2); 80 ND_PRINT((ndo, ", receipt number %u", EXTRACT_LE_16BITS(cp))); 81 cp += 2; 82 /* data */ 83 ND_PRINT((ndo, ", data (%u octets)", len - 4)); 84 ND_TCHECK2(*cp, len - 4); 85 break; 86 case LOOPBACK_FWDDATA: 87 if (len < 8) 88 goto invalid; 89 /* forwarding address */ 90 ND_TCHECK2(*cp, ETHER_ADDR_LEN); 91 ND_PRINT((ndo, ", forwarding address %s", etheraddr_string(ndo, cp))); 92 cp += ETHER_ADDR_LEN; 93 /* data */ 94 ND_PRINT((ndo, ", data (%u octets)", len - 8)); 95 ND_TCHECK2(*cp, len - 8); 96 break; 97 default: 98 ND_TCHECK2(*cp, len - 2); 99 break; 100 } 101 return; 102 103 invalid: 104 ND_PRINT((ndo, "%s", istr)); 105 ND_TCHECK2(*cp, ep - cp); 106 return; 107 trunc: 108 ND_PRINT((ndo, "%s", tstr)); 109 } 110 111 void 112 loopback_print(netdissect_options *ndo, const u_char *cp, const u_int len) 113 { 114 const u_char *ep = cp + len; 115 uint16_t skipCount; 116 117 ND_PRINT((ndo, "Loopback")); 118 if (len < 2) 119 goto invalid; 120 /* skipCount */ 121 ND_TCHECK2(*cp, 2); 122 skipCount = EXTRACT_LE_16BITS(cp); 123 cp += 2; 124 ND_PRINT((ndo, ", skipCount %u", skipCount)); 125 if (skipCount % 8) 126 ND_PRINT((ndo, " (bogus)")); 127 if (skipCount > len - 2) 128 goto invalid; 129 loopback_message_print(ndo, cp + skipCount, len - 2 - skipCount); 130 return; 131 132 invalid: 133 ND_PRINT((ndo, "%s", istr)); 134 ND_TCHECK2(*cp, ep - cp); 135 return; 136 trunc: 137 ND_PRINT((ndo, "%s", tstr)); 138 } 139 140