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