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
46static const char tstr[] = " [|loopback]";
47
48#define LOOPBACK_REPLY   1
49#define LOOPBACK_FWDDATA 2
50
51static const struct tok fcode_str[] = {
52	{ LOOPBACK_REPLY,   "Reply"        },
53	{ LOOPBACK_FWDDATA, "Forward Data" },
54	{ 0, NULL }
55};
56
57static void
58loopback_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
100invalid:
101	ND_PRINT((ndo, "%s", istr));
102	ND_TCHECK2(*cp, ep - cp);
103	return;
104trunc:
105	ND_PRINT((ndo, "%s", tstr));
106}
107
108void
109loopback_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
129invalid:
130	ND_PRINT((ndo, "%s", istr));
131	ND_TCHECK2(*cp, ep - cp);
132	return;
133trunc:
134	ND_PRINT((ndo, "%s", tstr));
135}
136
137