Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-h1.c
blobbcc0de5fd4da29ba2333b8b6580424247a0012f9
1 /* packet-h1.c
2 * Routines for Sinec H1 packet disassembly
3 * Gerrit Gehnen <G.Gehnen@atrie.de>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/exceptions.h>
17 void proto_register_h1(void);
18 void proto_reg_handoff_h1(void);
20 static int proto_h1;
21 static int hf_h1_header;
22 static int hf_h1_len;
23 static int hf_h1_block_type;
24 static int hf_h1_block_len;
25 static int hf_h1_opcode;
26 static int hf_h1_dbnr;
27 static int hf_h1_dwnr;
28 static int hf_h1_dlen;
29 static int hf_h1_org;
30 static int hf_h1_response_value;
33 #define EMPTY_BLOCK 0xFF
34 #define OPCODE_BLOCK 0x01
35 #define REQUEST_BLOCK 0x03
36 #define RESPONSE_BLOCK 0x0F
38 static const value_string block_type_vals[] = {
39 { EMPTY_BLOCK, "Empty Block" },
40 { OPCODE_BLOCK, "Opcode Block" },
41 { REQUEST_BLOCK, "Request Block" },
42 { RESPONSE_BLOCK, "Response Block" },
43 {0, NULL}
47 static const value_string opcode_vals[] = {
48 {3, "Write Request"},
49 {4, "Write Response"},
50 {5, "Read Request"},
51 {6, "Read Response"},
52 {0, NULL}
55 static const value_string org_vals[] = {
56 {0x01, "DB"},
57 {0x02, "MB"},
58 {0x03, "EB"},
59 {0x04, "AB"},
60 {0x05, "PB"},
61 {0x06, "ZB"},
62 {0x07, "TB"},
63 {0x08, "BS"},
64 {0x09, "AS"},
65 {0x0a, "DX"},
66 {0x10, "DE"},
67 {0x11, "QB"},
68 {0, NULL}
71 static const value_string returncode_vals[] = {
72 {0x00, "No error"},
73 {0x02, "Requested block does not exist"},
74 {0x03, "Requested block too small"},
75 {0xFF, "Error, reason unknown"},
76 {0, NULL}
79 static int ett_h1;
80 static int ett_block;
82 static bool dissect_h1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
84 proto_tree *h1_tree, *block_tree;
85 proto_item *h1_ti, *block_ti;
86 int offset = 0, offset_block_start;
87 uint8_t h1_len;
88 uint8_t block_type, block_len;
89 tvbuff_t *next_tvb;
91 if (tvb_captured_length(tvb) < 2) {
92 /* Not enough data captured to hold the "S5" header; don't try
93 to interpret it as H1. */
94 return false;
97 if (!(tvb_get_uint8(tvb, 0) == 'S' && tvb_get_uint8(tvb, 1) == '5')) {
98 return false;
101 col_set_str (pinfo->cinfo, COL_PROTOCOL, "H1");
102 col_set_str(pinfo->cinfo, COL_INFO, "S5: ");
104 h1_ti = proto_tree_add_item(tree, proto_h1, tvb, offset, -1, ENC_NA);
105 h1_tree = proto_item_add_subtree(h1_ti, ett_h1);
107 proto_tree_add_item(h1_tree, hf_h1_header, tvb, offset, 2, ENC_BIG_ENDIAN);
108 offset += 2;
110 h1_len = tvb_get_uint8(tvb, offset);
111 proto_tree_add_item(h1_tree, hf_h1_len, tvb, offset, 1, ENC_BIG_ENDIAN);
112 proto_item_set_len(h1_ti, h1_len);
113 offset++;
115 while (offset < h1_len) {
116 offset_block_start = offset;
118 block_type = tvb_get_uint8(tvb, offset);
119 block_len = tvb_get_uint8(tvb, offset+1);
121 if (!try_val_to_str(block_type, block_type_vals)) {
122 /* XXX - should we skip unknown blocks? */
123 return false;
125 if (block_len == 0) {
126 /* XXX - expert info */
127 break;
130 block_tree = proto_tree_add_subtree_format(h1_tree,
131 tvb, offset, -1, ett_block, &block_ti, "%s",
132 val_to_str_const(block_type, block_type_vals, "Unknown block"));
134 proto_tree_add_item(block_tree, hf_h1_block_type,
135 tvb, offset, 1, ENC_BIG_ENDIAN);
136 /* we keep increasing offset as we go though the block
137 however, to find the beginning of the next block,
138 we use the current block's start offset and its length field */
139 offset++;
140 proto_tree_add_item(block_tree, hf_h1_block_len,
141 tvb, offset, 1, ENC_BIG_ENDIAN);
142 proto_item_set_len(block_ti, block_len);
143 offset++;
145 switch (block_type) {
146 case OPCODE_BLOCK:
147 proto_tree_add_item(block_tree, hf_h1_opcode,
148 tvb, offset, 1, ENC_BIG_ENDIAN);
149 col_append_str (pinfo->cinfo, COL_INFO,
150 val_to_str (tvb_get_uint8(tvb, offset),
151 opcode_vals, "Unknown Opcode (0x%2.2x)"));
152 break;
154 case REQUEST_BLOCK:
155 proto_tree_add_item(block_tree, hf_h1_org, tvb,
156 offset, 1, ENC_BIG_ENDIAN);
157 col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
158 val_to_str (tvb_get_uint8(tvb, offset),
159 org_vals,"Unknown Type (0x%2.2x)"));
160 offset++;
162 proto_tree_add_item(block_tree, hf_h1_dbnr, tvb,
163 offset, 1, ENC_BIG_ENDIAN);
164 col_append_fstr(pinfo->cinfo, COL_INFO, " %d",
165 tvb_get_uint8(tvb, offset));
166 offset++;
168 proto_tree_add_item(block_tree, hf_h1_dwnr, tvb,
169 offset, 2, ENC_BIG_ENDIAN);
170 col_append_fstr (pinfo->cinfo, COL_INFO, " DW %d",
171 tvb_get_ntohs(tvb, offset));
172 offset += 2;
174 proto_tree_add_item(block_tree, hf_h1_dlen, tvb,
175 offset, 2, ENC_BIG_ENDIAN);
176 col_append_fstr (pinfo->cinfo, COL_INFO, " Count %d",
177 tvb_get_ntohs(tvb, offset));
178 break;
180 case RESPONSE_BLOCK:
181 proto_tree_add_item(block_tree, hf_h1_response_value,
182 tvb, offset, 1, ENC_BIG_ENDIAN);
183 col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
184 val_to_str (tvb_get_uint8(tvb, offset),
185 returncode_vals,"Unknown Returncode (0x%2.2x"));
186 break;
189 offset = offset_block_start + block_len; /* see the comment above */
192 if (tvb_reported_length_remaining(tvb, offset) > 0) {
193 next_tvb = tvb_new_subset_remaining(tvb, offset);
194 call_data_dissector(next_tvb, pinfo, tree);
197 return true;
201 void
202 proto_register_h1 (void)
204 static hf_register_info hf[] = {
205 {&hf_h1_header,
206 {"H1-Header", "h1.header", FT_UINT16, BASE_HEX, NULL, 0x0,
207 NULL, HFILL }},
208 {&hf_h1_len,
209 {"Length indicator", "h1.len", FT_UINT16, BASE_DEC, NULL, 0x0,
210 NULL, HFILL }},
211 {&hf_h1_block_type,
212 {"Block type", "h1.block_type", FT_UINT8, BASE_HEX, VALS(block_type_vals), 0x0,
213 NULL, HFILL }},
214 {&hf_h1_block_len,
215 {"Block length", "h1.block_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
216 {&hf_h1_opcode,
217 {"Opcode", "h1.opcode", FT_UINT8, BASE_HEX, VALS (opcode_vals), 0x0,
218 NULL, HFILL }},
219 {&hf_h1_org,
220 {"Memory type", "h1.org", FT_UINT8, BASE_HEX, VALS (org_vals), 0x0,
221 NULL, HFILL }},
222 {&hf_h1_dbnr,
223 {"Memory block number", "h1.dbnr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
224 {&hf_h1_dwnr,
225 {"Address within memory block", "h1.dwnr", FT_UINT16, BASE_DEC, NULL, 0x0,
226 NULL, HFILL }},
227 {&hf_h1_dlen,
228 {"Length in words", "h1.dlen", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
229 {&hf_h1_response_value,
230 {"Response value", "h1.resvalue", FT_UINT8, BASE_DEC,
231 VALS (returncode_vals), 0x0, NULL, HFILL }}
234 static int *ett[] = {
235 &ett_h1,
236 &ett_block,
239 proto_h1 = proto_register_protocol ("Sinec H1 Protocol", "H1", "h1");
240 proto_register_field_array (proto_h1, hf, array_length (hf));
241 proto_register_subtree_array (ett, array_length (ett));
244 void
245 proto_reg_handoff_h1(void)
247 heur_dissector_add("cotp", dissect_h1,
248 "Sinec H1 over COTP", "hi_cotp", proto_h1, HEURISTIC_ENABLE);
249 heur_dissector_add("cotp_is", dissect_h1,
250 "Sinec H1 over COTP (inactive subset)", "hi_cotp_is", proto_h1, HEURISTIC_ENABLE);
251 heur_dissector_add("tcp", dissect_h1,
252 "Sinec H1 over TCP", "hi_tcp", proto_h1, HEURISTIC_ENABLE);
256 * Editor modelines - https://www.wireshark.org/tools/modelines.html
258 * Local Variables:
259 * c-basic-offset: 4
260 * tab-width: 8
261 * indent-tabs-mode: nil
262 * End:
264 * ex: set shiftwidth=4 tabstop=8 expandtab:
265 * :indentSize=4:tabSize=8:noTabs=true: