Fix for bug 5422:
[obnox/wireshark/wip.git] / epan / dissectors / packet-paltalk.c
1 /* packet-paltalk.c
2  * Routines for Paltalk dissection
3  * Copyright 2005, Tim Hentenaar < tim at hentenaar dot com >
4  * Copyright 2008, Mohammad Ebrahim Mohammadi Panah < mebrahim at gmail dot com >
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <string.h>
32
33 #include <gmodule.h>
34 #include <epan/packet.h>
35
36 #include "packet-tcp.h"
37
38 #define INET_IPV4_ADDRESS_FROM_BYTES(a,b,c,d) g_htonl(((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) /* *network* order */
39
40 #define PALTALK_SERVERS_ADDRESS INET_IPV4_ADDRESS_FROM_BYTES(199,106,0,0)      /* 199.106.0.0 in *network* order */
41 #define PALTALK_SERVERS_NETMASK INET_IPV4_ADDRESS_FROM_BYTES(0xFF, 0xFE, 0x00, 0x00)  /* /15  in *network* order */
42
43 #define PALTALK_HEADER_LENGTH 6
44
45 /* forward reference */
46 static guint dissect_paltalk_get_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset);
47 static void dissect_paltalk_desegmented(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
48
49 static int proto_paltalk = -1;
50
51 static int hf_paltalk_pdu_type = -1;
52 static int hf_paltalk_version = -1;
53 static int hf_paltalk_length = -1;
54 static int hf_paltalk_content = -1;
55
56 static gint ett_paltalk = -1;
57
58 static gboolean
59 dissect_paltalk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
60 {
61         guint32 src32, dst32;
62
63         /* Detect if this TCP session is a Paltalk one */
64         /* TODO: Optimize detection logic if possible */
65
66         if ((pinfo->net_src.type != AT_IPv4) 
67             || (pinfo->net_dst.type != AT_IPv4)
68             || (pinfo->net_src.len != 4)
69             || (pinfo->net_dst.len != 4)
70             || !pinfo->net_src.data 
71             || !pinfo->net_dst.data)
72                 return FALSE;
73
74         memcpy((guint8 *)&src32, pinfo->net_src.data, 4); /* *Network* order */
75         memcpy((guint8 *)&dst32, pinfo->net_dst.data, 4); /* *Network* order */
76
77         if ( ((src32 & PALTALK_SERVERS_NETMASK) != PALTALK_SERVERS_ADDRESS) 
78              &&
79              ((dst32 & PALTALK_SERVERS_NETMASK) != PALTALK_SERVERS_ADDRESS))
80                 return FALSE;
81
82         /* Dissect result of desegmented TCP data */
83         tcp_dissect_pdus(tvb, pinfo, tree, TRUE, PALTALK_HEADER_LENGTH
84                         , dissect_paltalk_get_len, dissect_paltalk_desegmented);
85         return TRUE;
86 }
87
88 static guint
89 dissect_paltalk_get_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
90 {
91         return tvb_get_ntohs(tvb, offset + 4) + PALTALK_HEADER_LENGTH;
92 }
93
94 static void
95 dissect_paltalk_desegmented(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
96 {
97         proto_item *ti = NULL;
98         proto_tree *pt_tree = NULL;
99
100         col_set_str(pinfo->cinfo, COL_PROTOCOL, "Paltalk");
101         col_clear(pinfo->cinfo, COL_INFO);
102
103         if (tree)               /* we are being asked for details */
104         {
105                 ti = proto_tree_add_item(tree, proto_paltalk, tvb, 0, -1, FALSE);
106                 pt_tree = proto_item_add_subtree(ti, ett_paltalk);
107                 proto_tree_add_item(pt_tree, hf_paltalk_pdu_type, tvb, 0, 2, FALSE);
108                 proto_tree_add_item(pt_tree, hf_paltalk_version, tvb, 2, 2, FALSE);
109                 proto_tree_add_item(pt_tree, hf_paltalk_length, tvb, 4, 2, FALSE);
110                 proto_tree_add_item(pt_tree, hf_paltalk_content, tvb, 6, tvb_get_ntohs(tvb, 4), FALSE);
111         }
112 }
113
114 void
115 proto_register_paltalk(void)
116 {
117         static hf_register_info hf[] = {
118                 { &hf_paltalk_pdu_type, { "Packet Type", "paltalk.type", 
119                                           FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
120                 { &hf_paltalk_version,  { "Protocol Version", "paltalk.version",
121                                           FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
122                 { &hf_paltalk_length,   { "Payload Length", "paltalk.length",
123                                           FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
124                 { &hf_paltalk_content,  { "Payload Content", "paltalk.content",
125                                           FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }}
126         };
127
128         static gint *ett[] = { &ett_paltalk };
129
130         proto_paltalk = proto_register_protocol("Paltalk Messenger Protocol", "Paltalk", "paltalk");
131         proto_register_field_array(proto_paltalk, hf, array_length(hf));
132         proto_register_subtree_array(ett, array_length(ett));
133 }
134
135 void
136 proto_reg_handoff_paltalk(void)
137 {
138         heur_dissector_add("tcp", dissect_paltalk, proto_paltalk);
139 }
140