2 * Routines for Transparent Proxy Cache Protocol packet disassembly
3 * (c) Copyright Giles Scott <giles.scott1 [AT] btinternet.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
33 #include <epan/addr_resolv.h> /* this is for get_hostname and get_udp_port */
35 #define UDP_PORT_TPCP 3121
37 /* TPCP version1/2 PDU format */
38 typedef struct _tpcppdu_t
{
39 guint8 version
; /* PDU version 1 */
40 guint8 type
; /* PDU type: 1=request, 2=reply, 3=add filter, 4=rem filter */
41 /* Version 2 adds 5=add session 6= remove session */
42 guint16 flags
; /* 0x0001: 0=UDP, 1=TCP*/
43 /* 0x0002: 0=NONE, 1=DONT REDIRECT */
44 /* 0x0004: 0=NONE, 1=Xon */
45 /* 0x0008: 0=NONE, 1=Xoff */
46 guint16 id
; /* request/response identification or TTL */
47 guint16 cport
; /* client UDP or TCP port number */
48 guint32 caddr
; /* client IPv4 address */
49 guint32 saddr
; /* server IPV4 address */
50 /* tpcp version 2 only*/
51 guint32 vaddr
; /* Virtual Server IPv4 address */
52 guint32 rasaddr
; /* RAS server IPv4 address */
53 guint32 signature
; /* 0x74706370 - tpcp */
57 static const value_string type_vals
[] = {
61 { 4, "Remove Filter" },
62 /* 5 and 6 are for version 2 only */
64 { 6, "Remove Session" },
69 #define TF_TPCP_UDPTCP 0x0001
70 #define TF_TPCP_DONTREDIRECT 0x0002
71 #define TF_TPCP_XON 0x0004
72 #define TF_TPCP_XOFF 0x0008
79 #define TPCP_VER_1_LENGTH 16
80 #define TPCP_VER_2_LENGTH 28
82 /* things we can do filters on */
83 static int hf_tpcp_version
= -1;
84 static int hf_tpcp_type
= -1;
85 static int hf_tpcp_flags_tcp
= -1;
86 static int hf_tpcp_flags_redir
= -1;
87 static int hf_tpcp_flags_xon
= -1;
88 static int hf_tpcp_flags_xoff
= -1;
89 static int hf_tpcp_id
= -1;
90 static int hf_tpcp_cport
= -1;
91 static int hf_tpcp_caddr
= -1;
92 static int hf_tpcp_saddr
= -1;
93 static int hf_tpcp_vaddr
= -1;
94 static int hf_tpcp_rasaddr
= -1;
96 static int proto_tpcp
= -1;
98 static gint ett_tpcp
= -1;
99 static gint ett_tpcp_flags
= -1;
103 dissect_tpcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
106 proto_tree
*tpcp_tree
= NULL
, *field_tree
= NULL
;
108 guint8 length
= TPCP_VER_1_LENGTH
;
110 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "TPCP");
111 col_clear(pinfo
->cinfo
, COL_INFO
);
113 /* need to find out which version!! */
114 tpcph
.version
= tvb_get_guint8(tvb
, 0);
115 /* as version 1 and 2 are so similar use the same structure, just don't use as much for version 1*/
116 /* XXX: Doing a memcpy into a struct is *not* kosher */
117 if (tpcph
.version
== TPCP_VER_1
) {
118 length
= TPCP_VER_1_LENGTH
;
119 tvb_memcpy(tvb
, (guint8
*) &tpcph
, 0, length
);
120 } else if (tpcph
.version
== TPCP_VER_2
){
121 length
= TPCP_VER_2_LENGTH
;
122 tvb_memcpy(tvb
, (guint8
*) &tpcph
, 0, length
);
124 memset (&tpcph
, 0, sizeof (tpcph
));
128 tpcph
.id
= g_ntohs(tpcph
.id
);
129 tpcph
.flags
= g_ntohs(tpcph
.flags
);
130 tpcph
.cport
= g_ntohs(tpcph
.cport
);
131 tpcph
.signature
= g_ntohl(tpcph
.signature
);
133 col_add_fstr(pinfo
->cinfo
, COL_INFO
,"%s id %d CPort %s CIP %s SIP %s",
134 val_to_str_const(tpcph
.type
, type_vals
, "Unknown"),
136 get_udp_port(tpcph
.cport
),
137 ip_to_str((guint8
*)&tpcph
.caddr
),
138 ip_to_str((guint8
*)&tpcph
.saddr
));
141 ti
= proto_tree_add_protocol_format(tree
, proto_tpcp
, tvb
, 0, length
,
142 "Alteon WebSystems - Transparent Proxy Cache Protocol");
144 tpcp_tree
= proto_item_add_subtree(ti
, ett_tpcp
);
146 proto_tree_add_uint(tpcp_tree
, hf_tpcp_version
, tvb
, 0, 1, tpcph
.version
);
147 proto_tree_add_uint(tpcp_tree
, hf_tpcp_type
, tvb
, 1, 1, tpcph
.type
);
149 /* flags next , i'll do that when I can work out how to do it :-( */
150 tf
= proto_tree_add_text(tpcp_tree
, tvb
, 2, 2, "Flags: 0x%04x",tpcph
.flags
);
152 field_tree
= proto_item_add_subtree(tf
, ett_tpcp_flags
);
153 proto_tree_add_boolean(field_tree
, hf_tpcp_flags_tcp
, tvb
, 2, 2, tpcph
.flags
);
154 proto_tree_add_boolean(field_tree
, hf_tpcp_flags_redir
, tvb
, 2,2, tpcph
.flags
);
155 proto_tree_add_boolean(field_tree
, hf_tpcp_flags_xon
, tvb
, 2, 2, tpcph
.flags
);
156 proto_tree_add_boolean(field_tree
, hf_tpcp_flags_xoff
, tvb
, 2, 2, tpcph
.flags
);
158 proto_tree_add_uint(tpcp_tree
, hf_tpcp_id
, tvb
, 4, 2, tpcph
.id
);
160 proto_tree_add_uint_format_value(tpcp_tree
, hf_tpcp_cport
, tvb
, 6, 2, tpcph
.cport
,
161 "%s", get_udp_port(tpcph
.cport
));
163 proto_tree_add_ipv4(tpcp_tree
, hf_tpcp_caddr
, tvb
, 8, 4, tpcph
.caddr
);
165 proto_tree_add_ipv4(tpcp_tree
, hf_tpcp_saddr
, tvb
, 12, 4, tpcph
.saddr
);
167 if (tpcph
.version
== TPCP_VER_2
) {
168 proto_tree_add_ipv4(tpcp_tree
, hf_tpcp_vaddr
, tvb
, 16, 4, tpcph
.vaddr
);
169 proto_tree_add_ipv4(tpcp_tree
, hf_tpcp_rasaddr
, tvb
, 20, 4, tpcph
.rasaddr
);
170 proto_tree_add_text(tpcp_tree
, tvb
, 24, 4, "Signature: %u", tpcph
.signature
);
177 proto_register_tpcp(void)
179 static hf_register_info hf
[] = {
181 { "Version", "tpcp.version", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
182 "TPCP version", HFILL
}},
185 { "Type", "tpcp.type", FT_UINT8
, BASE_DEC
, VALS(type_vals
), 0x0,
186 "PDU type", HFILL
}},
188 { &hf_tpcp_flags_tcp
,
189 { "UDP/TCP", "tpcp.flags.tcp", FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), TF_TPCP_UDPTCP
,
190 "Protocol type", HFILL
}},
192 { &hf_tpcp_flags_redir
,
193 { "No Redirect", "tpcp.flags.redir", FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), TF_TPCP_DONTREDIRECT
,
194 "Don't redirect client", HFILL
}},
196 { &hf_tpcp_flags_xon
,
197 { "XON", "tpcp.flags.xon", FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), TF_TPCP_XON
,
200 { &hf_tpcp_flags_xoff
,
201 { "XOFF", "tpcp.flags.xoff", FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), TF_TPCP_XOFF
,
205 { "Client indent", "tpcp.cid", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
209 { "Client Source Port", "tpcp.cport", FT_UINT16
, BASE_DEC
, NULL
, 0x0,
213 { "Client Source IP address", "tpcp.caddr", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
217 { "Server IP address", "tpcp.saddr", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
221 { "Virtual Server IP address", "tpcp.vaddr", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
225 { "RAS server IP address", "tpcp.rasaddr", FT_IPv4
, BASE_NONE
, NULL
, 0x0,
231 static gint
*ett
[] = {
236 proto_tpcp
= proto_register_protocol("Alteon - Transparent Proxy Cache Protocol",
238 proto_register_field_array(proto_tpcp
, hf
, array_length(hf
));
239 proto_register_subtree_array(ett
, array_length(ett
));
243 proto_reg_handoff_tpcp(void)
245 dissector_handle_t tpcp_handle
;
247 tpcp_handle
= create_dissector_handle(dissect_tpcp
, proto_tpcp
);
248 dissector_add_uint("udp.port", UDP_PORT_TPCP
, tpcp_handle
);