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