1 /* packet-nt-tpcp.c
2  * Routines for Transparent Proxy Cache Protocol packet disassembly
3  * (c) Copyright Giles Scott <giles.scott1 [AT] btinternet.com>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 #include "config.h"
13 
14 
15 #include <epan/packet.h>
16 #include <epan/addr_resolv.h> /* this is for get_hostname and udp_port_to_display */
17 
18 void proto_register_tpcp(void);
19 void proto_reg_handoff_tpcp(void);
20 
21 #define UDP_PORT_TPCP   3121 /* Not IANA registered */
22 
23 /* TPCP version1/2 PDU format */
24 typedef struct _tpcppdu_t {
25 	guint8	version;     /* PDU version 1 */
26 	guint8	type;	     /* PDU type: 1=request, 2=reply, 3=add filter, 4=rem  filter */
27 	                     /* Version 2 adds 5=add session 6= remove session */
28 	guint16	flags;	     /* 0x0001: 0=UDP, 1=TCP*/
29 	                     /* 0x0002: 0=NONE, 1=DONT_REDIRECT */
30 	                     /* 0x0004: 0=NONE, 1=Xon */
31 	                     /* 0x0008: 0=NONE, 1=Xoff */
32 	guint16	id;	     /* request/response identification or TTL */
33 	guint16	cport;	     /* client UDP or TCP port number */
34 	guint32	caddr;	     /* client IPv4 address */
35 	guint32	saddr;	     /* server IPV4 address */
36 	/* tpcp version 2 only*/
37 	guint32 vaddr;	     /* Virtual Server IPv4 address */
38 	guint32 rasaddr;     /* RAS server IPv4 address */
39 	guint32 signature;   /* 0x74706370 - tpcp */
40 } tpcpdu_t;
41 
42 
43 static const value_string type_vals[] = {
44 	{ 1, "Request" },
45 	{ 2, "Reply" },
46 	{ 3, "Add Filter" },
47 	{ 4, "Remove Filter" },
48 	/* 5 and 6 are for version 2 only */
49 	{ 5, "Add Session" },
50 	{ 6, "Remove Session" },
51 	{ 0,  NULL }
52 };
53 
54 /* TPCP Flags */
55 #define TF_TPCP_UDPTCP 0x0001
56 #define TF_TPCP_DONTREDIRECT 0x0002
57 #define TF_TPCP_XON 0x0004
58 #define TF_TPCP_XOFF 0x0008
59 
60 
61 /* Version info */
62 #define TPCP_VER_1 1
63 #define TPCP_VER_2 2
64 
65 #define TPCP_VER_1_LENGTH 16
66 #define TPCP_VER_2_LENGTH 28
67 
68 /* things we can do filters on */
69 static int hf_tpcp_version = -1;
70 static int hf_tpcp_type = -1;
71 static int hf_tpcp_flags = -1;
72 static int hf_tpcp_flags_tcp = -1;
73 static int hf_tpcp_flags_redir = -1;
74 static int hf_tpcp_flags_xon = -1;
75 static int hf_tpcp_flags_xoff = -1;
76 static int hf_tpcp_id = -1;
77 static int hf_tpcp_cport = -1;
78 static int hf_tpcp_caddr = -1;
79 static int hf_tpcp_saddr = -1;
80 static int hf_tpcp_vaddr = -1;
81 static int hf_tpcp_rasaddr = -1;
82 static int hf_tpcp_signature = -1;
83 
84 static int proto_tpcp = -1;
85 
86 static gint ett_tpcp = -1;
87 static gint ett_tpcp_flags = -1;
88 
89 
90 static int
dissect_tpcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)91 dissect_tpcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
92 {
93 	proto_tree *tpcp_tree = NULL;
94 	proto_item *ti;
95 	guint8	version, type;
96 	guint16	id, cport;
97 
98 	static int * const tpcp_flags[] = {
99 		&hf_tpcp_flags_tcp,
100 		&hf_tpcp_flags_redir,
101 		&hf_tpcp_flags_xon,
102 		&hf_tpcp_flags_xoff,
103 		NULL
104 		};
105 
106 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPCP");
107 	col_clear(pinfo->cinfo, COL_INFO);
108 
109 	/* need to find out which version!! */
110 	version = tvb_get_guint8(tvb, 0);
111 	if ((version != TPCP_VER_1) && (version != TPCP_VER_2)) {
112 		/* Not us */
113 		return 0;
114 	}
115 
116 	ti = proto_tree_add_protocol_format(tree, proto_tpcp, tvb, 0, -1,
117 					    "Alteon WebSystems - Transparent Proxy Cache Protocol");
118 
119 	tpcp_tree = proto_item_add_subtree(ti, ett_tpcp);
120 
121 	proto_tree_add_item(tpcp_tree, hf_tpcp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
122 	type = tvb_get_guint8(tvb, 1);
123 	proto_tree_add_item(tpcp_tree, hf_tpcp_type, tvb, 1, 1, ENC_BIG_ENDIAN);
124 
125 	proto_tree_add_bitmask(tpcp_tree, tvb, 2, hf_tpcp_flags, ett_tpcp_flags, tpcp_flags, ENC_NA);
126 
127 	id = tvb_get_ntohs(tvb, 4);
128 	proto_tree_add_item(tpcp_tree, hf_tpcp_id, tvb, 4, 2, ENC_BIG_ENDIAN);
129 
130 	cport = tvb_get_ntohs(tvb, 6);
131 	proto_tree_add_uint_format_value(tpcp_tree, hf_tpcp_cport, tvb, 6, 2, cport,
132 					 "%s", udp_port_to_display(pinfo->pool, cport));
133 
134 	proto_tree_add_item(tpcp_tree, hf_tpcp_caddr, tvb, 8, 4, ENC_BIG_ENDIAN);
135 	proto_tree_add_item(tpcp_tree, hf_tpcp_saddr, tvb, 12, 4, ENC_BIG_ENDIAN);
136 
137 	if (version == TPCP_VER_2) {
138 		proto_tree_add_item(tpcp_tree, hf_tpcp_vaddr, tvb, 16, 4, ENC_BIG_ENDIAN);
139 		proto_tree_add_item(tpcp_tree, hf_tpcp_rasaddr, tvb, 20, 4, ENC_BIG_ENDIAN);
140 		proto_tree_add_item(tpcp_tree, hf_tpcp_signature, tvb, 24, 4, ENC_BIG_ENDIAN);
141 	}
142 
143 	col_add_fstr(pinfo->cinfo, COL_INFO,"%s id %d CPort %s CIP %s SIP %s",
144 			val_to_str_const(type, type_vals, "Unknown"),
145 			id,
146 			udp_port_to_display(pinfo->pool, cport),
147 			tvb_ip_to_str(pinfo->pool, tvb, 8),
148 			tvb_ip_to_str(pinfo->pool, tvb, 12));
149 
150 	if (version == TPCP_VER_1)
151 		return TPCP_VER_1_LENGTH;
152 
153 	return TPCP_VER_2_LENGTH;
154 }
155 
156 void
proto_register_tpcp(void)157 proto_register_tpcp(void)
158 {
159 	static hf_register_info hf[] = {
160 		{ &hf_tpcp_version,
161 		{ "Version",		"tpcp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
162 		"TPCP version", HFILL }},
163 
164 		{ &hf_tpcp_type,
165 		{ "Type",		"tpcp.type", FT_UINT8, BASE_DEC, VALS(type_vals), 0x0,
166 		"PDU type", HFILL }},
167 
168 		{ &hf_tpcp_flags,
169 		{ "Flags",		"tpcp.flags", FT_UINT16, BASE_HEX, NULL, 0x0,
170 		NULL, HFILL }},
171 
172 		{ &hf_tpcp_flags_tcp,
173 		{ "UDP/TCP",		"tpcp.flags.tcp", FT_BOOLEAN, 8, TFS(&tfs_set_notset), TF_TPCP_UDPTCP,
174 		"Protocol type", HFILL }},
175 
176 		{ &hf_tpcp_flags_redir,
177 		{ "No Redirect",	"tpcp.flags.redir", FT_BOOLEAN, 8, TFS(&tfs_set_notset), TF_TPCP_DONTREDIRECT,
178 		"Don't redirect client", HFILL }},
179 
180 		{ &hf_tpcp_flags_xon,
181 		{ "XON",		"tpcp.flags.xon", FT_BOOLEAN, 8, TFS(&tfs_set_notset), TF_TPCP_XON,
182 		NULL, HFILL }},
183 
184 		{ &hf_tpcp_flags_xoff,
185 		{ "XOFF",		"tpcp.flags.xoff", FT_BOOLEAN, 8, TFS(&tfs_set_notset), TF_TPCP_XOFF,
186 		NULL, HFILL }},
187 
188 		{ &hf_tpcp_id,
189 		{ "Client indent",	"tpcp.cid", FT_UINT16, BASE_DEC, NULL, 0x0,
190 		NULL, HFILL }},
191 
192 		{ &hf_tpcp_cport,
193 		{ "Client Source Port",	"tpcp.cport", FT_UINT16, BASE_DEC, NULL, 0x0,
194 		NULL, HFILL }},
195 
196 		{ &hf_tpcp_caddr,
197 		{ "Client Source IP address",	"tpcp.caddr", FT_IPv4, BASE_NONE, NULL, 0x0,
198 		NULL, HFILL }},
199 
200 		{ &hf_tpcp_saddr,
201 		{ "Server IP address",	"tpcp.saddr", FT_IPv4, BASE_NONE, NULL, 0x0,
202 		NULL, HFILL }},
203 
204 		{ &hf_tpcp_vaddr,
205 		{ "Virtual Server IP address", "tpcp.vaddr", FT_IPv4, BASE_NONE, NULL, 0x0,
206 		NULL, HFILL }},
207 
208 		{ &hf_tpcp_rasaddr,
209 		{ "RAS server IP address", "tpcp.rasaddr", FT_IPv4, BASE_NONE, NULL, 0x0,
210 		NULL, HFILL }},
211 
212 		{ &hf_tpcp_signature,
213 		{ "Signature",	"tpcp.signature", FT_UINT32, BASE_DEC, NULL, 0x0,
214 		NULL, HFILL }},
215 	};
216 
217 
218 	static gint *ett[] = {
219 		&ett_tpcp,
220 		&ett_tpcp_flags,
221 	};
222 
223 	proto_tpcp = proto_register_protocol("Alteon - Transparent Proxy Cache Protocol", "TPCP", "tpcp");
224 	proto_register_field_array(proto_tpcp, hf, array_length(hf));
225 	proto_register_subtree_array(ett, array_length(ett));
226 }
227 
228 void
proto_reg_handoff_tpcp(void)229 proto_reg_handoff_tpcp(void)
230 {
231 	dissector_handle_t tpcp_handle;
232 
233 	tpcp_handle = create_dissector_handle(dissect_tpcp, proto_tpcp);
234 	dissector_add_uint_with_preference("udp.port", UDP_PORT_TPCP, tpcp_handle);
235 }
236 
237 /*
238  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
239  *
240  * Local variables:
241  * c-basic-offset: 8
242  * tab-width: 8
243  * indent-tabs-mode: t
244  * End:
245  *
246  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
247  * :indentSize=8:tabSize=8:noTabs=false:
248  */
249