Get rid of get_ber_last_reated_item() and fix dissection of wIN-TriggerList.
[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         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
74                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MANOLITO");
75     
76         ti = proto_tree_add_item(tree, proto_manolito, tvb, 0, -1, FALSE);
77
78         manolito_tree = proto_item_add_subtree(ti, ett_manolito);
79
80         /* MANOLITO packet header (network byte order) */
81         header.checksum = tvb_get_ntohl(tvb, 0);
82         header.seqno = tvb_get_ntohl(tvb, 4);
83         header.src = tvb_get_ipv4(tvb, 8);
84         header.dest = tvb_get_ipv4(tvb, 12);
85         if (tvb_reported_length(tvb) == 19)
86         {
87                 header.options = (tvb_get_ntohs(tvb, 16) << 8) +
88                                 tvb_get_guint8(tvb, 18);
89                 packet_type = "Ping (truncated)";
90         } else {
91                 header.options = tvb_get_ntohl(tvb, 16);
92         }
93
94         proto_tree_add_item(manolito_tree,
95             hf_manolito_checksum, tvb, 0, 4, header.checksum);
96         proto_tree_add_item(manolito_tree,
97             hf_manolito_seqno, tvb, 4, 4, header.seqno);
98
99         proto_tree_add_ipv4(manolito_tree,
100             hf_manolito_src, tvb, 8, 4, header.src);
101
102         proto_tree_add_ipv4(manolito_tree,
103             hf_manolito_dest, tvb, 12, 4, header.dest);
104
105         proto_tree_add_item(manolito_tree,
106             hf_manolito_options, tvb, 16, 4, header.options);
107
108
109         if (tvb_reported_length(tvb) <= 20)      /* no payload, just headers */
110         {
111                 if (check_col(pinfo->cinfo, COL_INFO)) 
112                 {
113                         col_set_str(pinfo->cinfo, COL_INFO, "Ping");
114                 }
115         } else {
116                 offset = 20;            /* fields start here */
117
118                 /* fields format: 2-byte name, optional NULL, 1-byte lenlen, */
119                 /* that many bytes(len or data), for NI,CN,VL is len, more */
120                 /* (that many bytes) data follows; else is raw data. */
121                 do 
122                 {
123                         guint16 field_name;      /* 16-bit field name */
124                         guint8 dtype;            /* data-type */
125                         guint8 length;           /* length */
126                         guint8* data;            /* payload */
127                         int start;               /* field starting location */
128                         char field_name_str[3];  /* printable name */
129                         const char* longname;    /* human-friendly field name */
130
131                         start = offset;
132
133                         /* 2-byte field name */
134                         field_name = tvb_get_ntohs(tvb, offset);
135                         offset += 2;
136
137                         /* Identify the packet based on existing fields */
138                         /* Maybe using the options fields is a better idea...*/
139                         if (field_name == 0x434b)    /* CK */
140                                 packet_type = "Search Hit";
141                         if (field_name == 0x4e43)    /* NC */
142                                 packet_type = "User Information";
143                         if (field_name == 0x464e)    /* FN - if only field */
144                                 packet_type = "Search Query";
145                         if (field_name == 0x4944)    /* ID ?? search by CK? */
146                                 packet_type = "Search Query (by hash)";
147                         if (field_name == 0x5054)    /* PT */
148                                 packet_type = "Download Request";
149                         if (field_name == 0x4d45)    /* ME */
150                                 packet_type = "Chat";
151
152                         if (tvb_reported_length(tvb) == 20)   /* no fields */
153                                 packet_type = "Ping";
154
155                         /* Find the long name of the field */
156                         switch(field_name)
157                         {
158                         case 0x5346: longname = "Shared Files"; break;    /* SF */
159                         case 0x534b: longname = "Shared Kilobytes";break; /* SK */
160                         case 0x4e49: longname = "Network ID"; break;      /* NI */
161                         case 0x4e43: longname = "Num. Connections";break; /* NC */
162                         case 0x4356: longname = "Client Version"; break;  /* CV */
163                         case 0x564c: longname = "Velocity"; break;        /* VL */
164                         case 0x464e: longname = "Filename"; break;        /* FN */
165                         case 0x464c: longname = "File Length"; break;     /* FL */
166                         case 0x4252: longname = "Bit Rate"; break;        /* BR */
167                         case 0x4643: longname = "Frequency"; break;       /* FC */
168                         case 0x5354: longname = "???"; break;             /* ST */
169                         case 0x534c: longname = "Song Length (s)"; break; /* SL */
170                         case 0x434b: longname = "Checksum"; break;    /* CK */
171                         case 0x4e4e: longname = "Nickname"; break;        /* NN */
172                         case 0x434e: longname = "Client Name"; break;     /* CN */
173                         case 0x5054: longname = "Port"; break;            /* PT */
174                         case 0x484e: longname = "???"; break;             /* HN */
175                         case 0x4d45: longname = "Message"; break;         /* ME */
176                         case 0x4944: longname = "Identification"; break;  /* ID */
177                         case 0x4144: longname = "???"; break;             /* AD */
178                         default: longname = "unknown"; break;
179                         }
180
181                         /* 1-byte data type */
182 #define MANOLITO_STRING         1
183 #define MANOLITO_INTEGER        0
184                         dtype = tvb_get_guint8(tvb, offset);
185                         length = tvb_get_guint8(tvb, ++offset);
186
187                         /*
188                          * Get the payload.
189                          *
190                          * XXX - is the cast necessary?  I think the
191                          * "usual arithmetic conversions" should
192                          * widen it past 8 bits, so there shouldn't
193                          * be an overflow.
194                          */
195                         data = ep_alloc((guint)length + 1);
196                         tvb_memcpy(tvb, data, ++offset, length);
197                         offset += length; 
198
199                         /* convert the 16-bit integer field name to a string */
200                         /* XXX: changed this to use g_htons */
201                         field_name_str[0] = g_htons(field_name) & 0x00ff;
202                         field_name_str[1] = (g_htons(field_name) & 0xff00) >> 8;
203                         field_name_str[2] = 0;
204
205                         if (dtype == MANOLITO_STRING) 
206                         {
207                                 data[length] = 0;
208                                 proto_tree_add_text(manolito_tree, tvb, start,
209                                         offset - start, "%s (%s): %s",
210                                         (char*)field_name_str, longname, data);
211                         } else if (dtype == MANOLITO_INTEGER) {
212                                 int n = 0;
213
214                                 /* integers can be up to 5 bytes */
215                                 switch(length)
216                                 {
217                                 case 5: n += data[4] << ((length - 5) * 8);
218                                 case 4: n += data[3] << ((length - 4) * 8);
219                                 case 3: n += data[2] << ((length - 3) * 8);
220                                 case 2: n += data[1] << ((length - 2) * 8);
221                                 case 1: n += data[0] << ((length - 1) * 8);
222                                 }
223                                 proto_tree_add_text(manolito_tree, tvb, start,
224                                         offset - start, "%s (%s): %d",
225                                         (char*)field_name_str, longname, n);
226                         } else {
227                                 proto_tree_add_text(manolito_tree, tvb, start,
228                                         offset - start, "unknown type %d", dtype);
229                         }
230
231                 } while(offset < tvb_reported_length(tvb));
232
233         }
234
235         if (packet_type && check_col(pinfo->cinfo, COL_INFO))
236         {
237                 col_set_str(pinfo->cinfo, COL_INFO, packet_type);
238         }
239 }
240
241
242 /* Register the protocol with Wireshark */
243
244 void
245 proto_register_manolito(void)
246 {                 
247
248 /* Setup list of header fields  See Section 1.6.1 for details*/
249         static hf_register_info hf[] = {
250                 { &hf_manolito_checksum,
251                         { "Checksum",           "manolito.checksum",
252                         FT_UINT32, BASE_HEX, NULL, 0,         
253                         "Checksum used for verifying integrity", HFILL }
254                 },
255                 { &hf_manolito_seqno,
256                         { "Sequence Number",      "manolito.seqno",
257                         FT_UINT32, BASE_HEX, NULL, 0,
258                         "Incremental sequence number", HFILL }
259                 },
260                 { &hf_manolito_src,
261                         { "Forwarded IP Address",    "manolito.src",
262                         FT_IPv4, BASE_NONE, NULL, 0,
263                         "Host packet was forwarded from (or 0)", HFILL }
264                 },
265                 { &hf_manolito_dest,
266                         { "Destination IP Address","manolito.dest",
267                         FT_IPv4, BASE_NONE, NULL, 0,
268                        "Destination IPv4 address", HFILL }
269                 },
270                 { &hf_manolito_options,
271                         { "Options", "manolito.options",
272                         FT_UINT32, BASE_HEX, NULL, 0, 
273                        "Packet-dependent data", HFILL }
274                 }, 
275         };
276
277         static gint *ett[] = {
278                 &ett_manolito,
279         };
280
281         proto_manolito = proto_register_protocol("Blubster/Piolet MANOLITO Protocol",
282             "Manolito", "manolito");
283
284         proto_register_field_array(proto_manolito, hf, array_length(hf));
285         proto_register_subtree_array(ett, array_length(ett));
286 }
287
288
289 /* If this dissector uses sub-dissector registration add a registration routine.
290    This format is required because a script is used to find these routines and
291    create the code that calls these routines.
292 */
293 void
294 proto_reg_handoff_manolito(void)
295 {
296         dissector_handle_t manolito_handle;
297
298         manolito_handle = create_dissector_handle(dissect_manolito,
299             proto_manolito);
300         dissector_add("udp.port", 41170, manolito_handle);
301 }
302