print-loopback.c revision 1.4
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#include <sys/cdefs.h>
29#ifndef lint
30__RCSID("$NetBSD: print-loopback.c,v 1.4 2017/02/05 04:05:05 spz Exp $");
31#endif
32
33/* \summary: Loopback Protocol printer */
34
35/*
36 * originally defined as the Ethernet Configuration Testing Protocol.
37 * specification: http://www.mit.edu/people/jhawk/ctp.pdf
38 */
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#include <netdissect-stdinc.h>
45
46#include "netdissect.h"
47#include "extract.h"
48#include "ether.h"
49#include "addrtoname.h"
50
51static const char tstr[] = " [|loopback]";
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 invalid;
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 invalid;
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 invalid;
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
105invalid:
106	ND_PRINT((ndo, "%s", istr));
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 invalid;
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 invalid;
131	loopback_message_print(ndo, cp + skipCount, len - 2 - skipCount);
132	return;
133
134invalid:
135	ND_PRINT((ndo, "%s", istr));
136	ND_TCHECK2(*cp, ep - cp);
137	return;
138trunc:
139	ND_PRINT((ndo, "%s", tstr));
140}
141
142