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