Don't guard col_set_str (COL_PROTOCOL) with col_check
[obnox/wireshark/wip.git] / epan / dissectors / packet-manolito.c
1 /* packet-manolito.c
2  * Routines for Blubster/Piolet Manolito Protocol dissection
3  * Copyright 2003-2004, Jeff Connelly <shellreef+mp2p@gmail.com>
4  *
5  * Official home page: http://openlito.sourceforge.net/
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <glib.h>
37
38 #include <epan/packet.h>
39 #include <epan/emem.h>
40
41 /* Initialize the protocol and registered fields */
42 static int proto_manolito = -1;
43 static int hf_manolito_checksum = -1;
44 static int hf_manolito_seqno = -1;
45 static int hf_manolito_src = -1;
46 static int hf_manolito_dest = -1;
47 static int hf_manolito_options = -1;
48
49 /* Initialize the subtree pointers */
50 static gint ett_manolito = -1;
51
52 struct MANOLITO_HEADER {
53         guint32 checksum;
54         guint32 seqno;
55         guint32 src;
56         guint32 dest;
57         guint32 options;
58 };
59
60 /* Code to actually dissect the packets */
61 static void
62 dissect_manolito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
63 {
64         struct MANOLITO_HEADER header;
65         unsigned int offset;
66
67         /* Set up structures needed to add the protocol subtree and manage it */
68         proto_item *ti;
69         proto_tree *manolito_tree;
70         const char* packet_type = 0;
71
72         /* Make entries in Protocol column and Info column on summary display */
73         col_set_str(pinfo->cinfo, COL_PROTOCOL, "MANOLITO");
74     
75         ti = proto_tree_add_item(tree, proto_manolito, tvb, 0, -1, FALSE);
76
77         manolito_tree = proto_item_add_subtree(ti, ett_manolito);
78
79         /* MANOLITO packet header (network byte order) */
80         header.checksum = tvb_get_ntohl(tvb, 0);
81         header.seqno = tvb_get_ntohl(tvb, 4);
82         header.src = tvb_get_ipv4(tvb, 8);
83         header.dest = tvb_get_ipv4(tvb, 12);
84         if (tvb_reported_length(tvb) == 19)
85         {
86                 header.options = (tvb_get_ntohs(tvb, 16) << 8) +
87                                 tvb_get_guint8(tvb, 18);
88                 packet_type = "Ping (truncated)";
89         } else {
90                 header.options = tvb_get_ntohl(tvb, 16);
91         }
92
93         proto_tree_add_item(manolito_tree,
94             hf_manolito_checksum, tvb, 0, 4, header.checksum);
95         proto_tree_add_item(manolito_tree,
96             hf_manolito_seqno, tvb, 4, 4, header.seqno);
97
98         proto_tree_add_ipv4(manolito_tree,
99             hf_manolito_src, tvb, 8, 4, header.src);
100
101         proto_tree_add_ipv4(manolito_tree,
102             hf_manolito_dest, tvb, 12, 4, header.dest);
103
104         proto_tree_add_item(manolito_tree,
105             hf_manolito_options, tvb, 16, 4, header.options);
106
107
108         if (tvb_reported_length(tvb) <= 20)      /* no payload, just headers */
109         {
110                 if (check_col(pinfo->cinfo, COL_INFO)) 
111                 {
112                         col_set_str(pinfo->cinfo, COL_INFO, "Ping");
113                 }
114         } else {
115                 offset = 20;            /* fields start here */
116
117                 /* fields format: 2-byte name, optional NULL, 1-byte lenlen, */
118                 /* that many bytes(len or data), for NI,CN,VL is len, more */
119                 /* (that many bytes) data follows; else is raw data. */
120                 do 
121                 {
122                         guint16 field_name;      /* 16-bit field name */
123                         guint8 dtype;            /* data-type */
124                         guint8 length;           /* length */
125                         guint8* data;            /* payload */
126                         int start;               /* field starting location */
127                         char field_name_str[3];  /* printable name */
128                         const char* longname;    /* human-friendly field name */
129
130                         start = offset;
131
132                         /* 2-byte field name */
133                         field_name = tvb_get_ntohs(tvb, offset);
134                         offset += 2;
135
136                         /* Identify the packet based on existing fields */
137                         /* Maybe using the options fields is a better idea...*/
138                         if (field_name == 0x434b)    /* CK */
139                                 packet_type = "Search Hit";
140                         if (field_name == 0x4e43)    /* NC */
141                                 packet_type = "User Information";
142                         if (field_name == 0x464e)    /* FN - if only field */
143                                 packet_type = "Search Query";
144                         if (field_name == 0x4944)    /* ID ?? search by CK? */
145                                 packet_type = "Search Query (by hash)";
146                         if (field_name == 0x5054)    /* PT */
147                                 packet_type = "Download Request";
148                         if (field_name == 0x4d45)    /* ME */
149                                 packet_type = "Chat";
150
151                         if (tvb_reported_length(tvb) == 20)   /* no fields */
152                                 packet_type = "Ping";
153
154                         /* Find the long name of the field */
155                         switch(field_name)
156                         {
157                         case 0x5346: longname = "Shared Files"; break;    /* SF */
158                         case 0x534b: longname = "Shared Kilobytes";break; /* SK */
159                         case 0x4e49: longname = "Network ID"; break;      /* NI */
160                         case 0x4e43: longname = "Num. Connections";break; /* NC */
161                         case 0x4356: longname = "Client Version"; break;  /* CV */
162                         case 0x564c: longname = "Velocity"; break;        /* VL */
163                         case 0x464e: longname = "Filename"; break;        /* FN */
164                         case 0x464c: longname = "File Length"; break;     /* FL */
165                         case 0x4252: longname = "Bit Rate"; break;        /* BR */
166                         case 0x4643: longname = "Frequency"; break;       /* FC */
167                         case 0x5354: longname = "???"; break;             /* ST */
168                         case 0x534c: longname = "Song Length (s)"; break; /* SL */
169                         case 0x434b: longname = "Checksum"; break;    /* CK */
170                         case 0x4e4e: longname = "Nickname"; break;        /* NN */
171                         case 0x434e: longname = "Client Name"; break;     /* CN */
172                         case 0x5054: longname = "Port"; break;            /* PT */
173                         case 0x484e: longname = "???"; break;             /* HN */
174                         case 0x4d45: longname = "Message"; break;         /* ME */
175                         case 0x4944: longname = "Identification"; break;  /* ID */
176                         case 0x4144: longname = "???"; break;             /* AD */
177                         default: longname = "unknown"; break;
178                         }
179
180                         /* 1-byte data type */
181 #define MANOLITO_STRING         1
182 #define MANOLITO_INTEGER        0
183                         dtype = tvb_get_guint8(tvb, offset);
184                         length = tvb_get_guint8(tvb, ++offset);
185
186                         /*
187                          * Get the payload.
188                          *
189                          * XXX - is the cast necessary?  I think the
190                          * "usual arithmetic conversions" should
191                          * widen it past 8 bits, so there shouldn't
192                          * be an overflow.
193                          */
194                         data = ep_alloc((guint)length + 1);
195                         tvb_memcpy(tvb, data, ++offset, length);
196                         offset += length; 
197
198                         /* convert the 16-bit integer field name to a string */
199                         /* XXX: changed this to use g_htons */
200                         field_name_str[0] = g_htons(field_name) & 0x00ff;
201                         field_name_str[1] = (g_htons(field_name) & 0xff00) >> 8;
202                         field_name_str[2] = 0;
203
204                         if (dtype == MANOLITO_STRING) 
205                         {
206                                 data[length] = 0;
207                                 proto_tree_add_text(manolito_tree, tvb, start,
208                                         offset - start, "%s (%s): %s",
209                                         (char*)field_name_str, longname, data);
210                         } else if (dtype == MANOLITO_INTEGER) {
211                                 int n = 0;
212
213                                 /* integers can be up to 5 bytes */
214                                 switch(length)
215                                 {
216                                 case 5: n += data[4] << ((length - 5) * 8);
217                                 case 4: n += data[3] << ((length - 4) * 8);
218                                 case 3: n += data[2] << ((length - 3) * 8);
219                                 case 2: n += data[1] << ((length - 2) * 8);
220                                 case 1: n += data[0] << ((length - 1) * 8);
221                                 }
222                                 proto_tree_add_text(manolito_tree, tvb, start,
223                                         offset - start, "%s (%s): %d",
224                                         (char*)field_name_str, longname, n);
225                         } else {
226                                 proto_tree_add_text(manolito_tree, tvb, start,
227                                         offset - start, "unknown type %d", dtype);
228                         }
229
230                 } while(offset < tvb_reported_length(tvb));
231
232         }
233
234         if (packet_type && check_col(pinfo->cinfo, COL_INFO))
235         {
236                 col_set_str(pinfo->cinfo, COL_INFO, packet_type);
237         }
238 }
239
240
241 /* Register the protocol with Wireshark */
242
243 void
244 proto_register_manolito(void)
245 {                 
246
247 /* Setup list of header fields  See Section 1.6.1 for details*/
248         static hf_register_info hf[] = {
249                 { &hf_manolito_checksum,
250                         { "Checksum",           "manolito.checksum",
251                         FT_UINT32, BASE_HEX, NULL, 0,         
252                         "Checksum used for verifying integrity", HFILL }
253                 },
254                 { &hf_manolito_seqno,
255                         { "Sequence Number",      "manolito.seqno",
256                         FT_UINT32, BASE_HEX, NULL, 0,
257                         "Incremental sequence number", HFILL }
258                 },
259                 { &hf_manolito_src,
260                         { "Forwarded IP Address",    "manolito.src",
261                         FT_IPv4, BASE_NONE, NULL, 0,
262                         "Host packet was forwarded from (or 0)", HFILL }
263                 },
264                 { &hf_manolito_dest,
265                         { "Destination IP Address","manolito.dest",
266                         FT_IPv4, BASE_NONE, NULL, 0,
267                        "Destination IPv4 address", HFILL }
268                 },
269                 { &hf_manolito_options,
270                         { "Options", "manolito.options",
271                         FT_UINT32, BASE_HEX, NULL, 0, 
272                        "Packet-dependent data", HFILL }
273                 }, 
274         };
275
276         static gint *ett[] = {
277                 &ett_manolito,
278         };
279
280         proto_manolito = proto_register_protocol("Blubster/Piolet MANOLITO Protocol",
281             "Manolito", "manolito");
282
283         proto_register_field_array(proto_manolito, hf, array_length(hf));
284         proto_register_subtree_array(ett, array_length(ett));
285 }
286
287
288 /* If this dissector uses sub-dissector registration add a registration routine.
289    This format is required because a script is used to find these routines and
290    create the code that calls these routines.
291 */
292 void
293 proto_reg_handoff_manolito(void)
294 {
295         dissector_handle_t manolito_handle;
296
297         manolito_handle = create_dissector_handle(dissect_manolito,
298             proto_manolito);
299         dissector_add("udp.port", 41170, manolito_handle);
300 }
301