print-loopback.c revision 1.2
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
50static const char tstr[] = " [|loopback]";
51static const char cstr[] = " (corrupt)";
52
53#define LOOPBACK_REPLY   1
54#define LOOPBACK_FWDDATA 2
55
56static const struct tok fcode_str[] = {
57	{ LOOPBACK_REPLY,   "Reply"        },
58	{ LOOPBACK_FWDDATA, "Forward Data" },
59	{ 0, NULL }
60};
61
62static void
63loopback_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
105corrupt:
106	ND_PRINT((ndo, "%s", cstr));
107	ND_TCHECK2(*cp, ep - cp);
108	return;
109trunc:
110	ND_PRINT((ndo, "%s", tstr));
111}
112
113void
114loopback_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
134corrupt:
135	ND_PRINT((ndo, "%s", cstr));
136	ND_TCHECK2(*cp, ep - cp);
137	return;
138trunc:
139	ND_PRINT((ndo, "%s", tstr));
140}
141
142