2 * Routines for IP Device Control (SS7 over IP) dissection
3 * Copyright Lucent Technologies 2004
4 * Josh Bailey <joshbailey@lucent.com> and Ruud Linders <ruud@lucent.com>
6 * $Id: packet-ipdc.c,v 1.4 2004/03/21 19:57:14 jmayer Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #ifdef NEED_SNPRINTF_H
39 # include "snprintf.h"
42 #include <epan/packet.h>
43 #include "packet-ipdc.h"
44 #include "packet-tcp.h"
45 #include <epan/packet.h>
49 static int proto_ipdc = -1;
50 static int hf_ipdc_nr = -1;
51 static int hf_ipdc_ns = -1;
52 static int hf_ipdc_payload_len = -1;
53 static int hf_ipdc_protocol_id = -1;
54 static int hf_ipdc_trans_id_size = -1;
55 static int hf_ipdc_trans_id = -1;
56 static int hf_ipdc_message_code = -1;
58 static gint ett_ipdc = -1;
59 static gint ett_ipdc_tag = -1;
61 static gboolean ipdc_desegment = TRUE;
62 static gint ipdc_port_pref = TCP_PORT_IPDC;
64 static dissector_handle_t q931_handle;
66 void proto_reg_handoff_ipdc(void);
70 get_ipdc_pdu_len(tvbuff_t *tvb, int offset)
72 return tvb_get_ntohs(tvb,offset+2)+4;
76 dissect_ipdc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
79 proto_tree *ipdc_tree;
87 char tmp_tag_text[255+1];
88 const value_string *val_ptr;
96 gshort nr = tvb_get_guint8(tvb,0);
97 gshort ns = tvb_get_guint8(tvb,1);
98 guint16 payload_len = (guint16) get_ipdc_pdu_len(tvb,0);
101 gshort trans_id_size;
103 guint16 message_code;
106 /* display IPDC protocol ID */
107 if (check_col(pinfo->cinfo, COL_PROTOCOL))
108 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPDC");
114 /* clear info column and display send/receive sequence numbers */
115 if (check_col(pinfo->cinfo, COL_INFO)) {
116 col_set_str(pinfo->cinfo, COL_INFO, "");
117 col_append_fstr(pinfo->cinfo, COL_INFO, "N(r)=%u N(s)=%u ",
121 if (payload_len == 4) {
125 ti = proto_tree_add_item(tree, proto_ipdc, tvb, 0, -1, FALSE);
126 ipdc_tree = proto_item_add_subtree(ti, ett_ipdc);
127 proto_tree_add_item(ipdc_tree, hf_ipdc_nr, tvb, 0, 1, nr);
128 proto_tree_add_item(ipdc_tree, hf_ipdc_ns, tvb, 1, 1, ns);
129 proto_tree_add_uint(ipdc_tree, hf_ipdc_payload_len, tvb, 2, 2,
135 /* IPDC tags present - display message code and trans. ID */
136 protocol_id = tvb_get_guint8(tvb,4);
137 trans_id_size = TRANS_ID_SIZE_IPDC;
138 trans_id = tvb_get_ntohl(tvb,6);
139 message_code = tvb_get_ntohs(tvb,6+trans_id_size);
140 offset = 6 + trans_id_size + 2; /* past message_code */
142 if (check_col(pinfo->cinfo, COL_INFO))
143 col_append_fstr(pinfo->cinfo, COL_INFO,
146 val_to_str(message_code, message_code_vals,
152 ti = proto_tree_add_item(tree, proto_ipdc, tvb, 0, -1, FALSE);
153 ipdc_tree = proto_item_add_subtree(ti, ett_ipdc);
155 proto_tree_add_item(ipdc_tree, hf_ipdc_nr, tvb, 0, 1, nr);
156 proto_tree_add_item(ipdc_tree, hf_ipdc_ns, tvb, 1, 1, ns);
157 proto_tree_add_uint(ipdc_tree, hf_ipdc_payload_len, tvb,
160 proto_tree_add_item(ipdc_tree, hf_ipdc_protocol_id, tvb,
162 proto_tree_add_item(ipdc_tree, hf_ipdc_trans_id_size, tvb,
163 5, 1, trans_id_size);
164 proto_tree_add_item(ipdc_tree, hf_ipdc_trans_id, tvb,
165 6, trans_id_size, trans_id);
166 proto_tree_add_item(ipdc_tree, hf_ipdc_message_code, tvb,
167 6 + trans_id_size + 1, 1, message_code);
169 ipdc_tag = proto_tree_add_text(ipdc_tree, tvb, offset,
170 payload_len - offset, "IPDC tags");
171 tag_tree = proto_item_add_subtree(ipdc_tag, ett_ipdc_tag);
173 /* iterate through tags. first byte is tag, second is length,
174 in bytes, following is tag data. tag of 0x0 should be
177 tag = tvb_get_guint8(tvb, offset);
180 if (offset == payload_len - 1) {
181 proto_tree_add_text(tag_tree, tvb,
182 offset, 1, "end of tags");
184 proto_tree_add_text(tag_tree, tvb,
185 offset, 1, "data trailing end of tags");
191 len = tvb_get_guint8(tvb,offset+1);
192 des = val_to_str(tag, tag_description, TEXT_UNDEFINED);
193 /* lookup tag type */
194 for (i = 0; (ipdc_tag_types[i].tag != tag &&
195 ipdc_tag_types[i].type != IPDC_UNKNOWN); i++)
197 type = ipdc_tag_types[i].type;
202 /* simple IPDC_ASCII strings */
204 tmp_str = tvb_memdup(tvb, offset + 2, len);
205 strncpy(tmp_tag_text, tmp_str, len);
206 tmp_tag_text[len] = 0;
208 proto_tree_add_text(tag_tree, tvb, offset,
209 len + 2, "0x%2.2x: %s: %s", tag, des,
213 /* unsigned integers, or bytes */
216 for (i = 0; i < len; i++)
217 tmp_tag += tvb_get_guint8(tvb,
218 offset + 2 + i) * (guint32)
219 pow(256, len - (i + 1));
223 val_to_str( IPDC_TAG(tag) +
225 tag_enum_type, TEXT_UNDEFINED);
228 strcmp(enum_val, TEXT_UNDEFINED) != 0) {
229 proto_tree_add_text(tag_tree, tvb,
234 proto_tree_add_text(tag_tree, tvb,
244 sprintf(tmp_tag_text, "%u.%u.%u.%u",
245 tvb_get_guint8(tvb, offset + 2),
246 tvb_get_guint8(tvb, offset + 3),
247 tvb_get_guint8(tvb, offset + 4),
248 tvb_get_guint8(tvb, offset + 5));
249 } else if (len == 6) {
250 sprintf(tmp_tag_text, "%u.%u.%u.%u:%u",
251 tvb_get_guint8(tvb, offset + 2),
252 tvb_get_guint8(tvb, offset + 3),
253 tvb_get_guint8(tvb, offset + 4),
254 tvb_get_guint8(tvb, offset + 5),
255 tvb_get_ntohs(tvb, offset + 6));
257 sprintf(tmp_tag_text,
258 "Invalid IP address length %u", len);
261 proto_tree_add_text(tag_tree, tvb,
264 tag, des, tmp_tag_text);
267 /* Line status arrays */
268 case IPDC_LINESTATUS:
269 case IPDC_CHANNELSTATUS:
270 proto_tree_add_text(tag_tree, tvb, offset,
271 len + 2, "0x%2.2x: %s", tag, des);
272 val_ptr = (type == IPDC_LINESTATUS) ?
273 line_status_vals : channel_status_vals;
275 for (i = 0; i < len; i++) {
276 status = tvb_get_guint8(tvb,offset+2+i);
278 proto_tree_add_text(tag_tree, tvb,
290 tvb_new_subset(tvb, offset+2, len, len);
291 call_dissector(q931_handle,q931_tvb,pinfo,tree);
296 proto_tree_add_text(tag_tree, tvb, offset,
297 len + 2, "0x%2.2x: %s", tag, des);
306 dissect_ipdc_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
308 dissect_ipdc_common(tvb, pinfo, tree);
312 dissect_ipdc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
314 tcp_dissect_pdus(tvb, pinfo, tree, ipdc_desegment, 4,
315 get_ipdc_pdu_len, dissect_ipdc_tcp_pdu);
319 proto_register_ipdc(void)
322 static hf_register_info hf[] = {
325 FT_UINT8, BASE_DEC, NULL, 0x0,
326 "Receive sequence number", HFILL }
331 FT_UINT8, BASE_DEC, NULL, 0x0,
332 "Transmit sequence number", HFILL }
335 { &hf_ipdc_payload_len,
336 { "Payload length", "ipdc.length",
337 FT_UINT16, BASE_DEC, NULL, 0x0,
338 "Payload length", HFILL }
341 { &hf_ipdc_protocol_id,
342 { "Protocol ID", "ipdc.protocol_id",
343 FT_UINT8, BASE_HEX, NULL, 0x0,
344 "Protocol ID", HFILL }
347 { &hf_ipdc_trans_id_size,
348 { "Transaction ID size", "ipdc.trans_id_size",
349 FT_UINT8, BASE_DEC, NULL, 0x0,
350 "Transaction ID size", HFILL }
354 { "Transaction ID", "ipdc.trans_id",
355 FT_BYTES, BASE_HEX, NULL, 0x0,
356 "Transaction ID", HFILL }
359 { &hf_ipdc_message_code,
360 { "Message code", "ipdc.message_code",
361 FT_UINT16, BASE_HEX, VALS(message_code_vals), 0x0,
362 "Message Code", HFILL }
366 static gint *ett[] = {
371 module_t *ipdc_module;
373 proto_ipdc = proto_register_protocol("IP Device Control (SS7 over IP)",
375 proto_register_field_array(proto_ipdc, hf, array_length(hf));
376 proto_register_subtree_array(ett, array_length(ett));
378 ipdc_module = prefs_register_protocol(proto_ipdc, proto_reg_handoff_ipdc);
379 prefs_register_bool_preference(ipdc_module, "desegment_ipdc_messages",
380 "Desegment all IPDC messages spanning multiple TCP segments",
381 "Whether the IPDC dissector should desegment all messages spanning multiple TCP segments",
383 prefs_register_uint_preference(ipdc_module, "tcp.port",
384 "IPDC monitoring port",
385 "Set the IPDC monitoring port", 10,
390 proto_reg_handoff_ipdc(void)
392 static gint last_ipdc_port_pref = 0;
393 static dissector_handle_t ipdc_tcp_handle = NULL;
395 if (ipdc_tcp_handle) {
396 dissector_delete("tcp.port", last_ipdc_port_pref,
400 create_dissector_handle(dissect_ipdc_tcp, proto_ipdc);
401 q931_handle = find_dissector("q931");
404 last_ipdc_port_pref = ipdc_port_pref;
405 dissector_add("tcp.port", ipdc_port_pref, ipdc_tcp_handle);