2 * Routines for XIP Serval dissection
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
10 * Serval is a service-centric architecture that has been ported to XIA to
11 * allow applications to communicate using service names.
15 #include <epan/packet.h>
16 #include <epan/expert.h>
17 #include <epan/in_cksum.h>
19 #include <epan/unit_strings.h>
21 #include <wsutil/array.h>
24 void proto_register_xip_serval(void);
25 void proto_reg_handoff_xip_serval(void);
27 static dissector_handle_t tcp_handle
;
28 static dissector_handle_t udp_handle
;
30 static int proto_xip_serval
;
32 /* XIP Serval header. */
33 static int hf_xip_serval_hl
;
34 static int hf_xip_serval_proto
;
35 static int hf_xip_serval_check
;
36 static int hf_xip_serval_check_status
;
38 /* XIP Serval general extension header. */
39 static int hf_xip_serval_ext_type
;
40 static int hf_xip_serval_ext_length
;
42 /* XIP Serval control extension header. */
43 static int hf_xip_serval_cext
;
44 static int hf_xip_serval_cext_flags
;
45 static int hf_xip_serval_cext_syn
;
46 static int hf_xip_serval_cext_rsyn
;
47 static int hf_xip_serval_cext_ack
;
48 static int hf_xip_serval_cext_nack
;
49 static int hf_xip_serval_cext_rst
;
50 static int hf_xip_serval_cext_fin
;
51 static int hf_xip_serval_cext_verno
;
52 static int hf_xip_serval_cext_ackno
;
53 static int hf_xip_serval_cext_nonce
;
55 static int ett_xip_serval_tree
;
56 static int ett_xip_serval_cext
;
57 static int ett_xip_serval_cext_flags
;
59 static expert_field ei_xip_serval_bad_len
;
60 static expert_field ei_xip_serval_bad_proto
;
61 static expert_field ei_xip_serval_bad_checksum
;
62 static expert_field ei_xip_serval_bad_ext
;
64 #define XIP_SERVAL_PROTO_DATA 0
65 static const value_string xip_serval_proto_vals
[] = {
66 { XIP_SERVAL_PROTO_DATA
, "Data" },
67 { IP_PROTO_TCP
, "TCP" },
68 { IP_PROTO_UDP
, "UDP" },
72 static int * const xip_serval_cext_flags
[] = {
73 &hf_xip_serval_cext_syn
,
74 &hf_xip_serval_cext_rsyn
,
75 &hf_xip_serval_cext_ack
,
76 &hf_xip_serval_cext_nack
,
77 &hf_xip_serval_cext_rst
,
78 &hf_xip_serval_cext_fin
,
82 #define XIP_SERVAL_MIN_LEN 4
84 #define XIP_SERVAL_EXT_MIN_LEN 2
85 #define XIP_SERVAL_EXT_TYPE_MASK 0xF0
86 #define XIP_SERVAL_EXT_TYPE_CONTROL 0
88 #define XIP_SERVAL_CEXT_FLAGS_WIDTH 8
89 #define XIP_SERVAL_CEXT_NONCE_SIZE 8
90 #define XIP_SERVAL_CEXT_LEN 20
98 display_xip_serval_control_ext(tvbuff_t
*tvb
, proto_tree
*xip_serval_tree
,
99 int offset
, uint8_t type
, uint8_t length
)
101 proto_tree
*cext_tree
;
104 /* Create Serval Control Extension tree. */
105 ti
= proto_tree_add_item(xip_serval_tree
, hf_xip_serval_cext
, tvb
,
106 offset
, length
, ENC_NA
);
107 cext_tree
= proto_item_add_subtree(ti
, ett_xip_serval_cext
);
109 /* Add XIP Serval extension type. */
110 proto_tree_add_uint(cext_tree
, hf_xip_serval_ext_type
, tvb
,
114 /* Add XIP Serval extension length. */
115 proto_tree_add_item(cext_tree
, hf_xip_serval_ext_length
, tvb
,
116 offset
, 1, ENC_BIG_ENDIAN
);
119 /* Create XIP Serval Control Extension flags tree. */
120 proto_tree_add_bitmask(cext_tree
, tvb
, offset
,
121 hf_xip_serval_cext_flags
, ett_xip_serval_cext_flags
,
122 xip_serval_cext_flags
, ENC_BIG_ENDIAN
);
124 /* Skip two bits for res1. */
127 /* Skip a byte for res2. */
130 /* Add verification number. */
131 proto_tree_add_item(cext_tree
, hf_xip_serval_cext_verno
,
132 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
135 /* Add acknowledgement number. */
136 proto_tree_add_item(cext_tree
, hf_xip_serval_cext_ackno
,
137 tvb
, offset
, 4, ENC_BIG_ENDIAN
);
141 proto_tree_add_item(cext_tree
, hf_xip_serval_cext_nonce
,
142 tvb
, offset
, 8, ENC_NA
);
144 /* Displayed XIP_SERVAL_CEXT_LEN bytes. */
145 return XIP_SERVAL_CEXT_LEN
;
149 display_xip_serval_ext(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_item
*ti
,
150 proto_tree
*xip_serval_tree
, int offset
)
152 uint8_t type
= tvb_get_uint8(tvb
, offset
) & XIP_SERVAL_EXT_TYPE_MASK
;
153 uint8_t length
= tvb_get_uint8(tvb
, offset
+ 1);
155 /* For now, the only type of extension header in XIP Serval is
156 * the control extension header.
159 case XIP_SERVAL_EXT_TYPE_CONTROL
:
160 return display_xip_serval_control_ext(tvb
, xip_serval_tree
,
161 offset
, type
, length
);
163 expert_add_info_format(pinfo
, ti
, &ei_xip_serval_bad_ext
,
164 "Unrecognized Serval extension header type: 0x%02x",
171 display_xip_serval(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
173 proto_tree
*xip_serval_tree
;
174 proto_item
*ti
, *hl_ti
;
179 uint8_t xsh_len
, protocol
, bytes_remaining
;
181 /* Get XIP Serval header length, stored as number of 32-bit words. */
182 xsh_len
= tvb_get_uint8(tvb
, XSRVL_LEN
) << 2;
184 /* Create XIP Serval header tree. */
185 ti
= proto_tree_add_item(tree
, proto_xip_serval
, tvb
,
187 xip_serval_tree
= proto_item_add_subtree(ti
, ett_xip_serval_tree
);
189 /* Add XIP Serval header length. */
190 hl_ti
= proto_tree_add_item(xip_serval_tree
, hf_xip_serval_hl
, tvb
,
191 XSRVL_LEN
, 1, ENC_BIG_ENDIAN
);
192 if (tvb_captured_length(tvb
) < xsh_len
)
193 expert_add_info_format(pinfo
, hl_ti
, &ei_xip_serval_bad_len
,
194 "Header Length field (%d bytes) cannot be greater than actual number of bytes left in packet (%d bytes)",
195 xsh_len
, tvb_captured_length(tvb
));
197 /* Add XIP Serval protocol. If it's not data, TCP, or UDP, the
198 * packet is malformed.
200 proto_tree_add_item(xip_serval_tree
, hf_xip_serval_proto
, tvb
,
201 XSRVL_PRO
, 1, ENC_BIG_ENDIAN
);
202 protocol
= tvb_get_uint8(tvb
, XSRVL_PRO
);
203 if (!try_val_to_str(protocol
, xip_serval_proto_vals
))
204 expert_add_info_format(pinfo
, ti
, &ei_xip_serval_bad_proto
,
205 "Unrecognized protocol type: %d", protocol
);
207 /* Compute checksum. */
208 SET_CKSUM_VEC_TVB(cksum_vec
, tvb
, 0, xsh_len
);
210 proto_tree_add_checksum(xip_serval_tree
, tvb
, XSRVL_CHK
, hf_xip_serval_check
, hf_xip_serval_check_status
, &ei_xip_serval_bad_checksum
, pinfo
, in_cksum(&cksum_vec
, 1),
211 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
|PROTO_CHECKSUM_IN_CKSUM
);
214 /* If there's still more room, check for extension headers. */
215 bytes_remaining
= xsh_len
- offset
;
216 while (bytes_remaining
>= XIP_SERVAL_EXT_MIN_LEN
) {
217 int8_t bytes_displayed
= display_xip_serval_ext(tvb
, pinfo
, ti
,
218 xip_serval_tree
, offset
);
220 /* Extension headers are malformed, so we can't say
221 * what the rest of the packet holds. Stop dissecting.
223 if (bytes_displayed
<= 0)
226 offset
+= bytes_displayed
;
227 bytes_remaining
-= bytes_displayed
;
231 case XIP_SERVAL_PROTO_DATA
:
232 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
233 call_data_dissector(next_tvb
, pinfo
, tree
);
236 /* Get the Data Offset field of the TCP header, which is
237 * the high nibble of the 12th octet and represents the
238 * size of the TCP header of 32-bit words.
240 uint8_t tcp_len
= hi_nibble(tvb_get_uint8(tvb
, offset
+ 12))*4;
241 next_tvb
= tvb_new_subset_length(tvb
, offset
, tcp_len
);
242 call_dissector(tcp_handle
, next_tvb
, pinfo
, tree
);
246 /* The UDP header is always 8 bytes. */
247 next_tvb
= tvb_new_subset_length(tvb
, offset
, 8);
248 call_dissector(udp_handle
, next_tvb
, pinfo
, tree
);
256 dissect_xip_serval(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
259 if (tvb_reported_length(tvb
) < XIP_SERVAL_MIN_LEN
)
262 col_append_str(pinfo
->cinfo
, COL_INFO
, " (with Serval)");
264 display_xip_serval(tvb
, pinfo
, tree
);
265 return tvb_captured_length(tvb
);
269 proto_register_xip_serval(void)
271 static hf_register_info hf
[] = {
276 { "Header Length", "xip_serval.hl", FT_UINT8
,
277 BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
279 { &hf_xip_serval_proto
,
280 { "Protocol", "xip_serval.proto", FT_UINT8
,
281 BASE_DEC
, VALS(xip_serval_proto_vals
), 0x0, NULL
, HFILL
}},
283 { &hf_xip_serval_check
,
284 { "Checksum", "xip_serval.check", FT_UINT16
,
285 BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
287 { &hf_xip_serval_check_status
,
288 { "Checksum Status", "xip_serval.check.status", FT_UINT8
,
289 BASE_NONE
, VALS(proto_checksum_vals
), 0x0, NULL
, HFILL
}},
291 /* Serval Extension Header. */
293 { &hf_xip_serval_ext_type
,
294 { "Extension Type", "xip_serval.ext_type", FT_UINT8
,
295 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
297 { &hf_xip_serval_ext_length
,
298 { "Extension Length", "xip_serval.ext_length", FT_UINT8
,
299 BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_byte_bytes
), 0x0, NULL
, HFILL
}},
301 /* Serval Control Extension Header. */
303 { &hf_xip_serval_cext
,
304 { "Serval Control Extension", "xip_serval.cext",
305 FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
307 { &hf_xip_serval_cext_flags
,
308 { "Flags", "xip_serval.cext_flags", FT_UINT8
, BASE_HEX
,
309 NULL
, 0x0, NULL
, HFILL
}},
311 { &hf_xip_serval_cext_syn
,
312 { "SYN", "xip_serval.cext_syn", FT_BOOLEAN
, 8,
313 TFS(&tfs_set_notset
), 0x80, NULL
, HFILL
}},
315 { &hf_xip_serval_cext_rsyn
,
316 { "RSYN", "xip_serval.cext_rsyn", FT_BOOLEAN
, 8,
317 TFS(&tfs_set_notset
), 0x40, NULL
, HFILL
}},
319 { &hf_xip_serval_cext_ack
,
320 { "ACK", "xip_serval.cext_ack", FT_BOOLEAN
, 8,
321 TFS(&tfs_set_notset
), 0x20, NULL
, HFILL
}},
323 { &hf_xip_serval_cext_nack
,
324 { "NACK", "xip_serval.cext_nack", FT_BOOLEAN
, 8,
325 TFS(&tfs_set_notset
), 0x10, NULL
, HFILL
}},
327 { &hf_xip_serval_cext_rst
,
328 { "RST", "xip_serval.cext_rst", FT_BOOLEAN
, 8,
329 TFS(&tfs_set_notset
), 0x08, NULL
, HFILL
}},
331 { &hf_xip_serval_cext_fin
,
332 { "FIN", "xip_serval.cext_fin", FT_BOOLEAN
, 8,
333 TFS(&tfs_set_notset
), 0x04, NULL
, HFILL
}},
335 { &hf_xip_serval_cext_verno
,
336 { "Version Number", "xip_serval.cext_verno", FT_UINT32
,
337 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
339 { &hf_xip_serval_cext_ackno
,
340 { "Acknowledgement Number", "xip_serval.cext_ackno",
341 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
343 { &hf_xip_serval_cext_nonce
,
344 { "Nonce", "xip_serval.cext_nonce", FT_BYTES
,
345 SEP_SPACE
, NULL
, 0x0, NULL
, HFILL
}}
348 static int *ett
[] = {
349 &ett_xip_serval_tree
,
350 &ett_xip_serval_cext
,
351 &ett_xip_serval_cext_flags
354 static ei_register_info ei
[] = {
356 { &ei_xip_serval_bad_len
,
357 { "xip_serval.bad_len", PI_MALFORMED
, PI_ERROR
,
358 "Bad header length", EXPFILL
}},
360 { &ei_xip_serval_bad_ext
,
361 { "xip_serval.bad_ext", PI_MALFORMED
, PI_ERROR
,
362 "Bad extension header type", EXPFILL
}},
364 { &ei_xip_serval_bad_proto
,
365 { "xip_serval.bad_proto", PI_MALFORMED
, PI_ERROR
,
366 "Bad protocol type", EXPFILL
}},
368 { &ei_xip_serval_bad_checksum
,
369 { "xip_serval.bad_checksum", PI_MALFORMED
, PI_ERROR
,
370 "Incorrect checksum", EXPFILL
}}
373 expert_module_t
* expert_xip_serval
;
375 proto_xip_serval
= proto_register_protocol("XIP Serval", "XIP Serval", "xipserval");
376 register_dissector("xipserval", dissect_xip_serval
,
378 proto_register_field_array(proto_xip_serval
, hf
, array_length(hf
));
379 proto_register_subtree_array(ett
, array_length(ett
));
381 expert_xip_serval
= expert_register_protocol(proto_xip_serval
);
382 expert_register_field_array(expert_xip_serval
, ei
, array_length(ei
));
386 proto_reg_handoff_xip_serval(void)
388 tcp_handle
= find_dissector_add_dependency("tcp", proto_xip_serval
);
389 udp_handle
= find_dissector_add_dependency("udp", proto_xip_serval
);
393 * Editor modelines - https://www.wireshark.org/tools/modelines.html
398 * indent-tabs-mode: t
401 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
402 * :indentSize=8:tabSize=8:noTabs=false: