various code cleanup:
[obnox/wireshark/wip.git] / epan / dissectors / packet-ccsds.c
1 /* packet-ccsds.c
2  * Routines for CCSDS dissection
3  * Copyright 2000, Scott Hovis scott.hovis@ums.msfc.nasa.gov
4  *
5  * $Id$
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  * 
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.
20  * 
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <glib.h>
35
36 #include <epan/packet.h>
37
38 /*
39  * See
40  *
41  *      http://stationpayloads.jsc.nasa.gov/J-reference/documents/ssp57002B.pdf
42  */
43
44 /* Initialize the protocol and registered fields */
45 static int proto_ccsds = -1;
46 static int hf_ccsds_apid = -1;
47 static int hf_ccsds_version = -1;
48 static int hf_ccsds_secheader = -1;
49 static int hf_ccsds_type = -1;
50 static int hf_ccsds_seqnum = -1;
51 static int hf_ccsds_seqflag = -1;
52 static int hf_ccsds_length = -1;
53 static int hf_ccsds_time = -1;
54 static int hf_ccsds_timeid = -1;
55 static int hf_ccsds_checkword = -1;
56 static int hf_ccsds_zoe = -1;
57 static int hf_ccsds_packtype = -1;
58 static int hf_ccsds_vid = -1;
59 static int hf_ccsds_dcc = -1;
60
61 /* Initialize the subtree pointers */
62 static gint ett_ccsds = -1;
63 static gint ett_header = -1;
64 static gint ett_header2 = -1;
65
66 /*
67  * Bits in the first 16-bit header word
68  */
69 #define HDR_VERSION     0xe000
70 #define HDR_TYPE        0x1000
71 #define HDR_SECHDR      0x0800
72 #define HDR_APID        0x07ff
73
74 /* Code to actually dissect the packets */
75 static void
76 dissect_ccsds(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
77 {
78         int offset = 0;
79         proto_item *ti;
80         proto_tree *ccsds_tree;
81         proto_item *header;
82         proto_tree *header_tree;
83         guint16 first_word;
84         proto_item *header2;
85         proto_tree *header2_tree;
86         
87         if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
88                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CCSDS");
89         if (check_col(pinfo->cinfo, COL_INFO)) 
90                 col_set_str(pinfo->cinfo, COL_INFO, "CCSDS Packet");
91
92         if (tree) {
93                 ti = proto_tree_add_item(tree, proto_ccsds, tvb, 0, -1, FALSE);
94                 ccsds_tree = proto_item_add_subtree(ti, ett_ccsds);
95
96                 header=proto_tree_add_text(ccsds_tree, tvb, 0, -1,
97                     "Primary CCSDS Header");
98                 header_tree=proto_item_add_subtree(header, ett_header);
99                 
100                 first_word=tvb_get_ntohs(tvb, offset);
101                 proto_tree_add_uint(header_tree, hf_ccsds_version, tvb, offset, 2, first_word);
102                 proto_tree_add_uint(header_tree, hf_ccsds_type, tvb, offset, 2, first_word);
103                 proto_tree_add_boolean(header_tree, hf_ccsds_secheader, tvb, offset, 2, first_word);
104                 proto_tree_add_uint(header_tree, hf_ccsds_apid, tvb, offset, 2, first_word);
105                 offset += 2;
106
107                 proto_tree_add_item(header_tree, hf_ccsds_seqflag, tvb, offset, 2, FALSE);
108                 proto_tree_add_item(header_tree, hf_ccsds_seqnum, tvb, offset, 2, FALSE);
109                 offset += 2;
110
111                 proto_tree_add_item(header_tree, hf_ccsds_length, tvb, offset, 2, FALSE);
112                 offset += 2;
113                 proto_item_set_end(header, tvb, offset);
114
115                 if(first_word&HDR_SECHDR)
116                 {
117                         header2=proto_tree_add_text(ccsds_tree, tvb, offset, -1,
118                             "Secondary CCSDS Header");
119                         header2_tree=proto_item_add_subtree(header2, ett_header2);
120
121                         proto_tree_add_item(header2_tree, hf_ccsds_time, tvb, offset, 5, FALSE);
122                         offset += 5;
123
124                         proto_tree_add_item(header2_tree, hf_ccsds_timeid, tvb, offset, 1, FALSE);
125                         proto_tree_add_item(header2_tree, hf_ccsds_checkword, tvb, offset, 1, FALSE);
126                         proto_tree_add_item(header2_tree, hf_ccsds_zoe, tvb, offset, 1, FALSE);
127                         proto_tree_add_item(header2_tree, hf_ccsds_packtype, tvb, offset, 1, FALSE);
128                         offset += 1;
129
130                         proto_tree_add_item(header2_tree, hf_ccsds_vid, tvb, offset, 2, FALSE);
131                         offset += 2;
132
133                         proto_tree_add_item(header2_tree, hf_ccsds_dcc, tvb, offset, 2, FALSE);
134                         offset += 2;
135                         proto_item_set_end(header2, tvb, offset);
136                 }
137
138                 proto_tree_add_text(ccsds_tree, tvb, offset, -1,
139                     "Data");
140         }
141 }
142
143
144 /* Register the protocol with Ethereal */
145 /* this format is require because a script is used to build the C function
146    that calls all the protocol registration.
147 */
148 void
149 proto_register_ccsds(void)
150 {                 
151
152 /* Setup list of header fields  See Section 1.6.1 for details*/
153         static hf_register_info hf[] = {
154                 { &hf_ccsds_version,
155                         { "version",           "ccsds.version",
156                         FT_UINT16, BASE_DEC, NULL, HDR_VERSION,
157                         "version", HFILL }
158                 },
159                 { &hf_ccsds_type,
160                         { "type",           "ccsds.type",
161                         FT_UINT16, BASE_DEC, NULL, HDR_TYPE,          
162                         "type", HFILL }
163                 },
164                 { &hf_ccsds_secheader,
165                         { "secondary header",           "ccsds.secheader",
166                         FT_BOOLEAN, 16, NULL, HDR_SECHDR,
167                         "secondary header present", HFILL }
168                 },
169                 { &hf_ccsds_apid,
170                         { "APID",           "ccsds.apid",
171                         FT_UINT16, BASE_DEC, NULL, HDR_APID,
172                         "Represents APID", HFILL }
173                 },
174                 { &hf_ccsds_seqflag,
175                         { "sequence flags",           "ccsds.seqflag",
176                         FT_UINT16, BASE_DEC, NULL, 0xc000,
177                         "sequence flags", HFILL }
178                 },
179                 { &hf_ccsds_seqnum,
180                         { "sequence number",           "ccsds.seqnum",
181                         FT_UINT16, BASE_DEC, NULL, 0x3fff,          
182                         "sequence number", HFILL }
183                 },
184                 { &hf_ccsds_length,
185                         { "packet length",           "ccsds.length",
186                         FT_UINT16, BASE_DEC, NULL, 0xffff,          
187                         "packet length", HFILL }
188                 },
189                 { &hf_ccsds_time,
190                         { "time",           "ccsds.time",
191                         FT_BYTES, BASE_HEX, NULL, 0x0,          
192                         "time", HFILL }
193                 },
194                 { &hf_ccsds_timeid,
195                         { "time identifier",           "ccsds.timeid",
196                         FT_UINT8, BASE_DEC, NULL, 0xC0,
197                         "time identifier", HFILL }
198                 },
199                 { &hf_ccsds_checkword,
200                         { "checkword indicator",           "ccsds.checkword",
201                         FT_UINT8, BASE_DEC, NULL, 0x20,          
202                         "checkword indicator", HFILL }
203                 },
204                 { &hf_ccsds_zoe,
205                         { "ZOE TLM",           "ccsds.zoe",
206                         FT_UINT8, BASE_DEC, NULL, 0x10,          
207                         "CONTAINS S-BAND ZOE PACKETS", HFILL }
208                 },
209                 { &hf_ccsds_packtype,
210                         { "packet type",           "ccsds.packtype",
211                         FT_UINT8, BASE_DEC, NULL, 0x0f,          
212                         "Packet Type - Unused in Ku-Band", HFILL }
213                 },
214                 { &hf_ccsds_vid,
215                         { "version identifier",           "ccsds.vid",
216                         FT_UINT16, BASE_DEC, NULL, 0x0,
217                         "version identifier", HFILL }
218                 },
219                 { &hf_ccsds_dcc,
220                         { "Data Cycle Counter",           "ccsds.dcc",
221                         FT_UINT16, BASE_DEC, NULL, 0x0,
222                         "Data Cycle Counter", HFILL }
223                 },
224         };
225
226 /* Setup protocol subtree array */
227         static gint *ett[] = {
228                 &ett_ccsds,
229                 &ett_header,
230                 &ett_header2,
231         };
232
233 /* Register the protocol name and description */
234         proto_ccsds = proto_register_protocol("CCSDS", "CCSDS", "ccsds");
235
236 /* Required function calls to register the header fields and subtrees used */
237         proto_register_field_array(proto_ccsds, hf, array_length(hf));
238         proto_register_subtree_array(ett, array_length(ett));
239
240 }
241
242
243 /* If this dissector uses sub-dissector registration add a registration routine.
244    This format is required because a script is used to find these routines and
245    create the code that calls these routines.
246 */
247 void
248 proto_reg_handoff_ccsds(void)
249 {
250         dissector_handle_t ccsds_handle;
251
252         ccsds_handle = create_dissector_handle(dissect_ccsds,
253             proto_ccsds);
254         dissector_add_handle("udp.port", ccsds_handle);
255 }