Move 3 ASN1 dissectors to 'clean' group; move 1 PIDL dissector to 'dirty' group.
[metze/wireshark/wip.git] / epan / dissectors / packet-pktgen.c
1 /* packet-pktgen.c
2  * Routines for "Linux pktgen" dissection
3  * Copyright 2006 _FF_
4  * Francesco Fondelli <francesco dot fondelli, 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 /* FF:
28  * The linux packet generator is a tool to generate packets at very high speed in the kernel.
29  * See linux/net/core/pktgen.c and linux/Documentation/networking/pktgen.txt for more info.
30  */
31
32 #include "config.h"
33
34 #include <glib.h>
35
36 #include <epan/packet.h>
37
38 /* magic num used for heuristic */
39 static const guint8 pktgen_magic[] = { 0xbe, 0x9b, 0xe9, 0x55 };
40
41 /* Initialize the protocol and registered fields */
42 static int proto_pktgen = -1;
43
44 /* pktgen header */
45 static int hf_pktgen_magic = -1;
46 static int hf_pktgen_seqnum = -1;
47 static int hf_pktgen_tvsec = -1;
48 static int hf_pktgen_tvusec = -1;
49 static int hf_pktgen_timestamp = -1;
50
51 /* Initialize the subtree pointer */
52 static gint ett_pktgen = -1;
53
54 /* data dissector handle */
55 static dissector_handle_t data_handle;
56
57 /* entry point */
58 static gboolean dissect_pktgen(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
59 {
60     proto_item *ti = NULL;
61     proto_item *tmp = NULL;
62     proto_tree *pktgen_tree = NULL;
63     guint32 offset = 0;
64     nstime_t tstamp;
65
66     /* check for min size */
67     if(tvb_length(tvb) < 16) {  /* Not a PKTGEN packet. */
68         return FALSE;
69     }
70
71     /* check for magic number */
72     if(tvb_memeql(tvb, 0, pktgen_magic, 4) == -1) { /* Not a PKTGEN packet. */
73         return FALSE;
74     }
75
76     /* Make entries in Protocol column and Info column on summary display */
77
78     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PKTGEN");
79
80     if(check_col(pinfo->cinfo, COL_INFO)) {
81         col_add_fstr(pinfo->cinfo, COL_INFO, "Seq: %u", tvb_get_ntohl(tvb, 4));
82     }
83
84     if(tree) {
85
86         /* create display subtree for the protocol */
87
88         ti = proto_tree_add_item(tree, proto_pktgen, tvb, 0, -1, ENC_NA);
89
90         pktgen_tree = proto_item_add_subtree(ti, ett_pktgen);
91
92         /* add items to the subtree */
93
94         proto_tree_add_item(pktgen_tree, hf_pktgen_magic, tvb, offset, 4, ENC_BIG_ENDIAN);
95         offset+=4;
96
97         proto_tree_add_item(pktgen_tree, hf_pktgen_seqnum, tvb, offset, 4, ENC_BIG_ENDIAN);
98         offset+=4;
99
100         tstamp.secs = tvb_get_ntohl(tvb, offset);
101         tmp = proto_tree_add_item(pktgen_tree, hf_pktgen_tvsec, tvb, offset, 4, ENC_BIG_ENDIAN);
102         PROTO_ITEM_SET_GENERATED(tmp);
103         offset+=4;
104
105         tstamp.nsecs = tvb_get_ntohl(tvb, offset) /* microsecond on the wire so... */ * 1000;
106         tmp = proto_tree_add_item(pktgen_tree, hf_pktgen_tvusec, tvb, offset, 4, ENC_BIG_ENDIAN);
107         PROTO_ITEM_SET_GENERATED(tmp);
108         offset+=4;
109
110         proto_tree_add_time(pktgen_tree, hf_pktgen_timestamp, tvb, offset - 8, 8, &tstamp);
111
112 #if 0
113         if(tvb_length_remaining(tvb, offset)) /* random data */
114             proto_tree_add_text(pktgen_tree, tvb, offset, -1, "Data (%u bytes)",
115                                 tvb_length_remaining(tvb, offset));
116 #else
117         if(tvb_length_remaining(tvb, offset)) /* random data */
118             call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
119                 pktgen_tree);
120 #endif
121     }
122
123     return TRUE;
124 }
125
126
127 /* Register the protocol with Wireshark */
128 void proto_register_pktgen(void)
129 {
130     /* Setup list of header fields */
131
132     static hf_register_info hf[] = {
133
134         { &hf_pktgen_magic,
135           {
136               "Magic number", "pktgen.magic",
137               FT_UINT32, BASE_HEX, NULL, 0x0,
138               "The pktgen magic number", HFILL
139           }
140         },
141
142         { &hf_pktgen_seqnum,
143           {
144               "Sequence number", "pktgen.seqnum",
145               FT_UINT32, BASE_DEC, NULL, 0x0,
146               NULL, HFILL
147           }
148         },
149
150         { &hf_pktgen_tvsec,
151           {
152               "Timestamp tvsec", "pktgen.tvsec",
153               FT_UINT32, BASE_DEC, NULL, 0x0,
154               "Timestamp tvsec part", HFILL
155           }
156         },
157
158         { &hf_pktgen_tvusec,
159           {
160               "Timestamp tvusec", "pktgen.tvusec",
161               FT_UINT32, BASE_DEC, NULL, 0x0,
162               "Timestamp tvusec part", HFILL
163           }
164         },
165
166         { &hf_pktgen_timestamp,
167           {
168               "Timestamp", "pktgen.timestamp",
169               FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
170               NULL, HFILL
171           }
172         }
173     };
174
175     /* Setup protocol subtree array */
176
177     static gint *ett[] = {
178         &ett_pktgen
179     };
180
181     /* Register the protocol name and description */
182
183     proto_pktgen = proto_register_protocol("Linux Kernel Packet Generator", "PKTGEN", "pktgen");
184
185     /* Required function calls to register the header fields and subtrees used */
186
187     proto_register_field_array(proto_pktgen, hf, array_length(hf));
188     proto_register_subtree_array(ett, array_length(ett));
189 }
190
191
192 void proto_reg_handoff_pktgen(void)
193 {
194     /* Register as a heuristic UDP dissector */
195     heur_dissector_add("udp", dissect_pktgen, proto_pktgen);
196
197     /* Find data dissector handle */
198     data_handle = find_dissector("data");
199 }