3 * Based on the Netware SPX dissector by Gilbert Ramirez <gram@alumni.rice.edu>
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
14 #include <epan/packet.h>
15 #include "packet-idp.h"
17 void proto_register_spp(void);
18 void proto_reg_handoff_spp(void);
19 static dissector_handle_t spp_handle
;
22 static int hf_spp_connection_control
;
23 static int hf_spp_connection_control_sys
;
24 static int hf_spp_connection_control_send_ack
;
25 static int hf_spp_connection_control_attn
;
26 static int hf_spp_connection_control_eom
;
27 static int hf_spp_datastream_type
;
28 static int hf_spp_src_id
;
29 static int hf_spp_dst_id
;
30 static int hf_spp_seq_nr
;
31 static int hf_spp_ack_nr
;
32 static int hf_spp_all_nr
;
33 /* static int hf_spp_rexmt_frame; */
36 static int ett_spp_connctrl
;
38 static dissector_table_t spp_socket_dissector_table
;
43 * "Internet Transport Protocols", XSIS 028112, December 1981
45 * if you can find it; this is based on the headers in the BSD XNS
49 #define SPP_SYS_PACKET 0x80
50 #define SPP_SEND_ACK 0x40
55 spp_conn_ctrl(uint8_t ctrl
)
57 static const value_string conn_vals
[] = {
58 { 0x00, "Data, No Ack Required" },
59 { SPP_EOM
, "End-of-Message" },
60 { SPP_ATTN
, "Attention" },
61 { SPP_SEND_ACK
, "Acknowledgment Required"},
62 { SPP_SEND_ACK
|SPP_EOM
, "Send Ack: End Message"},
63 { SPP_SYS_PACKET
, "System Packet"},
64 { SPP_SYS_PACKET
|SPP_SEND_ACK
, "System Packet: Send Ack"},
68 return val_to_str_const((ctrl
& 0xf0), conn_vals
, "Unknown");
72 spp_datastream(uint8_t type
)
76 return "End-of-Connection";
78 return "End-of-Connection Acknowledgment";
84 #define SPP_HEADER_LEN 12
87 * XXX - do reassembly, using the EOM flag. (Then do that in the Netware
88 * SPX implementation, too.)
90 * XXX - hand off to subdissectors based on the socket number.
93 dissect_spp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
99 uint8_t datastream_type
;
100 const char *datastream_type_string
;
102 const char *spp_msg_string
;
103 uint16_t low_socket
, high_socket
;
104 static int * const ctrl
[] = {
105 &hf_spp_connection_control_sys
,
106 &hf_spp_connection_control_send_ack
,
107 &hf_spp_connection_control_attn
,
108 &hf_spp_connection_control_eom
,
112 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SPP");
113 col_set_str(pinfo
->cinfo
, COL_INFO
, "SPP");
115 ti
= proto_tree_add_item(tree
, proto_spp
, tvb
, 0, SPP_HEADER_LEN
, ENC_NA
);
116 spp_tree
= proto_item_add_subtree(ti
, ett_spp
);
118 conn_ctrl
= tvb_get_uint8(tvb
, 0);
119 spp_msg_string
= spp_conn_ctrl(conn_ctrl
);
120 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " %s", spp_msg_string
);
122 proto_tree_add_bitmask_with_flags(spp_tree
, tvb
, 0, hf_spp_connection_control
, ett_spp_connctrl
,
123 ctrl
, ENC_NA
, BMT_NO_FALSE
);
125 datastream_type
= tvb_get_uint8(tvb
, 1);
126 datastream_type_string
= spp_datastream(datastream_type
);
127 if (datastream_type_string
!= NULL
) {
128 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)", datastream_type_string
);
131 if (datastream_type_string
!= NULL
) {
132 proto_tree_add_uint_format_value(spp_tree
, hf_spp_datastream_type
, tvb
,
133 1, 1, datastream_type
,
135 datastream_type_string
,
138 proto_tree_add_uint(spp_tree
, hf_spp_datastream_type
, tvb
,
139 1, 1, datastream_type
);
141 proto_tree_add_item(spp_tree
, hf_spp_src_id
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
142 proto_tree_add_item(spp_tree
, hf_spp_dst_id
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
144 spp_seq
= tvb_get_ntohs(tvb
, 6);
146 proto_tree_add_uint(spp_tree
, hf_spp_seq_nr
, tvb
, 6, 2, spp_seq
);
147 proto_tree_add_item(spp_tree
, hf_spp_ack_nr
, tvb
, 8, 2, ENC_BIG_ENDIAN
);
148 proto_tree_add_item(spp_tree
, hf_spp_all_nr
, tvb
, 10, 2, ENC_BIG_ENDIAN
);
151 if (tvb_reported_length_remaining(tvb
, SPP_HEADER_LEN
) > 0) {
152 if (pinfo
->srcport
> pinfo
->destport
) {
153 low_socket
= pinfo
->destport
;
154 high_socket
= pinfo
->srcport
;
156 low_socket
= pinfo
->srcport
;
157 high_socket
= pinfo
->destport
;
160 next_tvb
= tvb_new_subset_remaining(tvb
, SPP_HEADER_LEN
);
161 if (dissector_try_uint(spp_socket_dissector_table
, low_socket
,
162 next_tvb
, pinfo
, tree
))
163 return tvb_captured_length(tvb
);
165 if (dissector_try_uint(spp_socket_dissector_table
, high_socket
,
166 next_tvb
, pinfo
, tree
))
167 return tvb_captured_length(tvb
);
169 call_data_dissector(next_tvb
, pinfo
, tree
);
171 return tvb_captured_length(tvb
);
176 proto_register_spp(void)
178 static hf_register_info hf_spp
[] = {
179 { &hf_spp_connection_control
,
180 { "Connection Control", "spp.ctl",
181 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
184 { &hf_spp_connection_control_sys
,
185 { "System Packet", "spp.ctl.sys",
186 FT_BOOLEAN
, 8, NULL
, SPP_SYS_PACKET
,
189 { &hf_spp_connection_control_send_ack
,
190 { "Send Ack", "spp.ctl.send_ack",
191 FT_BOOLEAN
, 8, NULL
, SPP_SEND_ACK
,
194 { &hf_spp_connection_control_attn
,
195 { "Attention", "spp.ctl.attn",
196 FT_BOOLEAN
, 8, NULL
, SPP_ATTN
,
199 { &hf_spp_connection_control_eom
,
200 { "End of Message", "spp.ctl.eom",
201 FT_BOOLEAN
, 8, NULL
, SPP_EOM
,
204 { &hf_spp_datastream_type
,
205 { "Datastream Type", "spp.type",
206 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
210 { "Source Connection ID", "spp.src",
211 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
215 { "Destination Connection ID", "spp.dst",
216 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
220 { "Sequence Number", "spp.seq",
221 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
225 { "Acknowledgment Number", "spp.ack",
226 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
230 { "Allocation Number", "spp.alloc",
231 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
235 { &hf_spp_rexmt_frame
,
236 { "Retransmitted Frame Number", "spp.rexmt_frame",
237 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
242 static int *ett
[] = {
247 proto_spp
= proto_register_protocol("Sequenced Packet Protocol",
249 proto_register_field_array(proto_spp
, hf_spp
, array_length(hf_spp
));
250 proto_register_subtree_array(ett
, array_length(ett
));
251 spp_handle
= register_dissector("spp", dissect_spp
, proto_spp
);
253 spp_socket_dissector_table
= register_dissector_table("spp.socket",
254 "SPP socket", proto_spp
, FT_UINT16
, BASE_HEX
);
258 proto_reg_handoff_spp(void)
260 dissector_add_uint("idp.packet_type", IDP_PACKET_TYPE_SPP
, spp_handle
);
264 * Editor modelines - https://www.wireshark.org/tools/modelines.html
269 * indent-tabs-mode: t
272 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
273 * :indentSize=8:tabSize=8:noTabs=false: