Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-skinny.c.in
bloba8c8740b693d880bc8175d3de92189c6bcdd01d8
1 /* Do not modify this file. Changes will be overwritten */
2 /* Generated Automatically */
3 /* packet-skinny.c */
5 /* packet-skinny.c
6 * Dissector for the Skinny Client Control Protocol
7 * (The "D-Channel"-Protocol for Cisco Systems' IP-Phones)
9 * Author: Diederik de Groot <ddegroot@user.sf.net>, Copyright 2014
10 * Rewritten to support newer skinny protocolversions (V0-V22)
11 * Based on previous versions/contributions:
12 * - Joerg Mayer <jmayer@loplof.de>, Copyright 2001
13 * - Paul E. Erkkila (pee@erkkila.org) - fleshed out the decode
14 * skeleton to report values for most message/message fields.
15 * Much help from Guy Harris on figuring out the wireshark api.
16 * - packet-aim.c by Ralf Hoelzer <ralf@well.com>, Copyright 2000
17 * - Wireshark - Network traffic analyzer,
18 * By Gerald Combs <gerald@wireshark.org>, Copyright 1998
20 * SPDX-License-Identifier: GPL-2.0-or-later
23 /* [[[cog
25 # Using Cog.py Inplace Code Generator
27 # Dependencies:
28 # - python2.x
29 # - cog.py: (pip install cogapp / http://nedbatchelder.com/code/cog/)
30 # - python.xml
31 # - python.xml.sax
33 cog.out('/*\n')
34 cog.out(' * Generated automatically Using (from wireshark base directory):\n')
35 cog.out(' * cog.py -D xmlfile=tools/SkinnyProtocolOptimized.xml -d -c -o epan/dissectors/packet-skinny.c epan/dissectors/packet-skinny.c.in\n')
36 cog.out(' */\n')
37 /*]]]*/
38 /*[[[end]]]*/
40 /* c-basic-offset: 2; tab-width: 8; indent-tabs-mode: nil
41 * vi: set shiftwidth=2 tabstop=8 expandtab:
42 * :indentSize=2:tabSize=8:noTabs=true:
46 #include "config.h"
48 #include <epan/packet.h>
49 #include <epan/prefs.h>
50 #include <epan/conversation.h>
51 #include <epan/wmem_scopes.h>
52 #include <epan/to_str.h>
53 #include <epan/reassemble.h>
54 #include <epan/tap.h>
55 #include <epan/ptvcursor.h>
57 #include "packet-rtp.h"
58 #include "packet-tcp.h"
59 #include "packet-tls.h"
60 #include "packet-skinny.h"
62 /* un-comment the following as well as this line in conversation.c, to enable debug printing */
63 /* #define DEBUG_CONVERSATION */
64 #include "conversation_debug.h"
66 void proto_register_skinny(void);
67 void proto_reg_handoff_skinny(void);
69 #define TCP_PORT_SKINNY 2000 /* Not IANA registered */
70 #define SSL_PORT_SKINNY 2443 /* IANA assigned to PowerClient Central Storage Facility */
72 #define BASIC_MSG_TYPE 0x00
73 #define V10_MSG_TYPE 0x0A
74 #define V11_MSG_TYPE 0x0B
75 #define V15_MSG_TYPE 0x0F
76 #define V16_MSG_TYPE 0x10
77 #define V17_MSG_TYPE 0x11
78 #define V18_MSG_TYPE 0x12
79 #define V19_MSG_TYPE 0x13
80 #define V20_MSG_TYPE 0x14
81 #define V21_MSG_TYPE 0x15
82 #define V22_MSG_TYPE 0x16
84 static const value_string header_version[] = {
85 { BASIC_MSG_TYPE, "Basic" },
86 { V10_MSG_TYPE, "V10" },
87 { V11_MSG_TYPE, "V11" },
88 { V15_MSG_TYPE, "V15" },
89 { V16_MSG_TYPE, "V16" },
90 { V17_MSG_TYPE, "V17" },
91 { V18_MSG_TYPE, "V18" },
92 { V19_MSG_TYPE, "V19" },
93 { V20_MSG_TYPE, "V20" },
94 { V21_MSG_TYPE, "V21" },
95 { V22_MSG_TYPE, "V22" },
96 { 0 , NULL }
99 /* Declare MessageId */
100 /* [[[cog
101 import sys
102 sys.path.append('tools/')
104 import parse_xml2skinny_dissector as xml2skinny
105 global skinny
106 global message_dissector_functions
108 message_dissector_functions = ''
109 skinny = xml2skinny.xml2obj(xmlfile)
111 cog.out('static const value_string message_id[] = {\n')
112 for message in skinny.message:
113 message_dissector_functions += '%s' %message.dissect()
114 cog.out(' { %s, "%s" },\n' %(message.opcode, message.name.replace('Message','')))
115 cog.out(' {0 , NULL}\n')
116 cog.out('};\n')
117 cog.out('static value_string_ext message_id_ext = VALUE_STRING_EXT_INIT(message_id);\n')
118 /*]]]*/
119 /*[[[end]]]*/
121 /* Declare Enums and Defines */
122 /* [[[cog
123 for enum in skinny.enum:
124 name = enum.name[0].upper() + enum.name[1:]
125 if enum.define == "yes":
126 for entries in enum.entries:
127 for entry in sorted(entries.entry, key=lambda x: int(x['value'],0)):
128 if entries.type is not None:
129 cog.out('#define {0:38} 0x{1:05x} /* {2} */\n' .format(entry.name.upper(), int(entry.value,0), entries.type))
130 else:
131 cog.out('#define {0:38} 0x{1:05x}\n' .format(entry.name.upper(), int(entry.value,0)))
132 cog.out('\n')
133 cog.out('static const value_string %s[] = {\n' %(name))
134 for entries in enum.entries:
135 for entry in sorted(entries.entry, key=lambda x: int(x['value'],0)):
136 if enum.define == "yes":
137 cog.out(' { %s, "%s" },\n' %(entry.name.upper(), entry.text))
138 else:
139 cog.out(' { 0x%05x, "%s" },\n' %(int(entry.value,0), entry.text))
140 cog.out(' { 0x00000, NULL }\n')
141 cog.out('};\n')
142 cog.out('static value_string_ext %s_ext = VALUE_STRING_EXT_INIT(%s);\n\n' %(name, name))
143 /*]]]*/
144 /*[[[end]]]*/
146 /* Staticly Declared Variables */
147 static int proto_skinny;
148 static int hf_skinny_messageId;
149 static int hf_skinny_data_length;
150 static int hf_skinny_hdr_version;
151 static int hf_skinny_xmlData;
152 static int hf_skinny_ipv4or6;
153 static int hf_skinny_response_in;
154 static int hf_skinny_response_to;
155 static int hf_skinny_response_time;
157 /* [[[cog
158 for key in sorted(xml2skinny.fieldsArray.keys()):
159 cog.out('static int hf_skinny_%s;\n' %key)
160 ]]]*/
161 /*[[[end]]]*/
163 static dissector_handle_t xml_handle;
165 /* Initialize the subtree pointers */
166 static int ett_skinny;
167 static int ett_skinny_tree;
169 /* preference globals */
170 static bool global_skinny_desegment = true;
172 /* tap register id */
173 static int skinny_tap;
175 /* skinny protocol tap info */
176 #define MAX_SKINNY_MESSAGES_IN_PACKET 10
177 static skinny_info_t pi_arr[MAX_SKINNY_MESSAGES_IN_PACKET];
178 static int pi_current;
179 static skinny_info_t *si;
181 dissector_handle_t skinny_handle;
183 /* Get the length of a single SKINNY PDU */
184 static unsigned
185 get_skinny_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
187 uint32_t hdr_data_length;
189 /* Get the length of the SKINNY packet. */
190 hdr_data_length = tvb_get_letohl(tvb, offset);
192 /* That length doesn't include the length of the header itself. */
193 return hdr_data_length + 8;
196 static void
197 dissect_skinny_xml(ptvcursor_t *cursor, int hfindex, packet_info *pinfo, uint32_t length, uint32_t maxlength)
199 proto_item *item = NULL;
200 proto_tree *subtree = NULL;
201 proto_tree *tree = ptvcursor_tree(cursor);
202 uint32_t offset = ptvcursor_current_offset(cursor);
203 tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
204 tvbuff_t *next_tvb;
206 if (length == 0) {
207 length = tvb_strnlen(tvb, offset, -1);
209 if (length >= maxlength) {
210 length = maxlength;
213 ptvcursor_add_no_advance(cursor, hfindex, length, ENC_ASCII);
215 item = proto_tree_add_item(tree, hf_skinny_xmlData, tvb, offset, length, ENC_ASCII);
216 subtree = proto_item_add_subtree(item, 0);
217 next_tvb = tvb_new_subset_length_caplen(tvb, offset, length, -1);
218 if (xml_handle != NULL) {
219 call_dissector(xml_handle, next_tvb, pinfo, subtree);
221 ptvcursor_advance(cursor, maxlength);
224 static void
225 dissect_skinny_ipv4or6(ptvcursor_t *cursor, int hfindex_ipv4, int hfindex_ipv6)
227 uint32_t ipversion = 0;
228 uint32_t offset = ptvcursor_current_offset(cursor);
229 tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
230 uint32_t hdr_version = tvb_get_letohl(tvb, 4);
232 /* ProtocolVersion > 18 include and extra field to declare IPv4 (0) / IPv6 (1) */
233 if (hdr_version >= V17_MSG_TYPE) {
234 ipversion = tvb_get_letohl(tvb, offset);
235 ptvcursor_add(cursor, hf_skinny_ipv4or6, 4, ENC_LITTLE_ENDIAN);
237 if (ipversion == IPADDRTYPE_IPV4) {
238 ptvcursor_add(cursor, hfindex_ipv4, 4, ENC_BIG_ENDIAN);
239 if (hdr_version >= V17_MSG_TYPE) {
240 /* skip over the extra room for ipv6 addresses */
241 ptvcursor_advance(cursor, 12);
243 } else if (ipversion == IPADDRTYPE_IPV6 || ipversion == IPADDRTYPE_IPV4_V6) {
244 ptvcursor_add(cursor, hfindex_ipv6, 16, ENC_NA);
245 } else {
246 /* Invalid : skip over ipv6 space completely */
247 ptvcursor_advance(cursor, 16);
251 /* Reads address to provided variable */
252 static void
253 read_skinny_ipv4or6(ptvcursor_t *cursor, address *media_addr)
255 uint32_t ipversion = IPADDRTYPE_IPV4;
256 uint32_t offset = ptvcursor_current_offset(cursor);
257 uint32_t offset2 = 0;
258 tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
259 uint32_t hdr_version = tvb_get_letohl(tvb, 4);
261 /* ProtocolVersion > 18 include and extra field to declare IPv4 (0) / IPv6 (1) */
262 if (hdr_version >= V17_MSG_TYPE) {
263 ipversion = tvb_get_letohl(tvb, offset);
264 offset2 = 4;
266 if (ipversion == IPADDRTYPE_IPV4) {
267 set_address_tvb(media_addr, AT_IPv4, 4, tvb, offset+offset2);
268 } else if (ipversion == IPADDRTYPE_IPV6 || ipversion == IPADDRTYPE_IPV4_V6) {
269 set_address_tvb(media_addr, AT_IPv6, 16, tvb, offset+offset2);
270 } else {
271 clear_address(media_addr);
276 * Parse a displayLabel string and check if it is using any embedded labels, if so lookup the label and add a user readable translation to the item_tree
278 static void
279 dissect_skinny_displayLabel(ptvcursor_t *cursor, packet_info *pinfo, int hfindex, int length)
281 proto_item *item = NULL;
282 proto_tree *tree = ptvcursor_tree(cursor);
283 uint32_t offset = ptvcursor_current_offset(cursor);
284 tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
285 wmem_strbuf_t *wmem_new = NULL;
286 char *disp_string = NULL;
287 const char *replacestr = NULL;
288 bool show_replaced_str = false;
289 int x = 0;
291 if (length == 0) {
292 length = tvb_strnlen(tvb, offset, -1);
293 if (length == -1) {
294 /* did not find end of string */
295 length = tvb_captured_length_remaining(tvb, offset);
299 item = proto_tree_add_item(tree, hfindex, tvb, offset, length, ENC_ASCII);
301 wmem_new = wmem_strbuf_new_sized(pinfo->pool, length + 1);
302 disp_string = (char*) wmem_alloc(pinfo->pool, length + 1);
303 disp_string[length] = '\0';
304 tvb_memcpy(tvb, (void*)disp_string, offset, length);
306 for (x = 0; x < length && disp_string[x] != '\0'; x++) {
307 replacestr = NULL;
308 if (x + 1 < length) {
309 if (disp_string[x] == '\36') {
310 replacestr = try_val_to_str_ext(disp_string[x + 1], &DisplayLabels_36_ext);
311 } else if (disp_string[x] == '\200') {
312 replacestr = try_val_to_str_ext(disp_string[x + 1], &DisplayLabels_200_ext);
315 if (replacestr) {
316 x++; /* swallow replaced characters */
317 wmem_strbuf_append(wmem_new, replacestr);
318 show_replaced_str = true;
319 } else if (disp_string[x] & 0x80) {
320 wmem_strbuf_append_unichar_repl(wmem_new);
321 } else {
322 wmem_strbuf_append_c(wmem_new, disp_string[x]);
325 if (show_replaced_str) {
326 si->additionalInfo = ws_strdup_printf("\"%s\"", wmem_strbuf_get_str(wmem_new));
327 proto_item_append_text(item, " => \"%s\"" , wmem_strbuf_get_str(wmem_new));
329 ptvcursor_advance(cursor, length);
332 /*** Request / Response helper functions */
333 static void skinny_reqrep_add_request(ptvcursor_t *cursor, packet_info * pinfo, skinny_conv_info_t * skinny_conv, const int request_key)
335 proto_tree *tree = ptvcursor_tree(cursor);
336 tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
337 skinny_req_resp_t *req_resp = NULL;
339 if (!PINFO_FD_VISITED(pinfo)) {
340 req_resp = wmem_new0(wmem_file_scope(), skinny_req_resp_t);
341 req_resp->request_frame = pinfo->num;
342 req_resp->response_frame = 0;
343 req_resp->request_time = pinfo->abs_ts;
344 wmem_map_insert(skinny_conv->pending_req_resp, GINT_TO_POINTER(request_key), (void *)req_resp);
345 DPRINT(("SKINNY: setup_request: frame=%d add key=%d to map\n", pinfo->num, request_key));
348 req_resp = (skinny_req_resp_t *) wmem_map_lookup(skinny_conv->requests, GUINT_TO_POINTER(pinfo->num));
349 if (req_resp && req_resp->response_frame) {
350 DPRINT(("SKINNY: show request in tree: frame/key=%d\n", pinfo->num));
351 proto_item *it;
352 it = proto_tree_add_uint(tree, hf_skinny_response_in, tvb, 0, 0, req_resp->response_frame);
353 proto_item_set_generated(it);
354 } else {
355 DPRINT(("SKINNY: no request found for frame/key=%d\n", pinfo->num));
360 static void skinny_reqrep_add_response(ptvcursor_t *cursor, packet_info * pinfo, skinny_conv_info_t * skinny_conv, const int request_key)
362 proto_tree *tree = ptvcursor_tree(cursor);
363 tvbuff_t *tvb = ptvcursor_tvbuff(cursor);
364 skinny_req_resp_t *req_resp = NULL;
366 if (!PINFO_FD_VISITED(pinfo)) {
367 req_resp = (skinny_req_resp_t *) wmem_map_remove(skinny_conv->pending_req_resp, GINT_TO_POINTER(request_key));
368 if (req_resp) {
369 DPRINT(("SKINNY: match request:%d with response:%d for key=%d\n", req_resp->request_frame, pinfo->num, request_key));
370 req_resp->response_frame = pinfo->num;
371 wmem_map_insert(skinny_conv->requests, GUINT_TO_POINTER(req_resp->request_frame), (void *)req_resp);
372 wmem_map_insert(skinny_conv->responses, GUINT_TO_POINTER(pinfo->num), (void *)req_resp);
373 } else {
374 DPRINT(("SKINNY: no match found for response frame=%d and key=%d\n", pinfo->num, request_key));
378 req_resp = (skinny_req_resp_t *) wmem_map_lookup(skinny_conv->responses, GUINT_TO_POINTER(pinfo->num));
379 if (req_resp && req_resp->request_frame) {
380 DPRINT(("SKINNY: show response in tree: frame/key=%d\n", pinfo->num));
381 proto_item *it;
382 nstime_t ns;
383 it = proto_tree_add_uint(tree, hf_skinny_response_to, tvb, 0, 0, req_resp->request_frame);
384 proto_item_set_generated(it);
386 nstime_delta(&ns, &pinfo->abs_ts, &req_resp->request_time);
387 it = proto_tree_add_time(tree, hf_skinny_response_time, tvb, 0, 0, &ns);
388 proto_item_set_generated(it);
389 } else {
390 DPRINT(("SKINNY: no response found for frame/key=%d\n", pinfo->num));
394 /*** Messages Handlers ***/
395 /* [[[cog
396 cog.out(message_dissector_functions)
397 ]]]*/
398 /*[[[end]]]*/
400 typedef void (*message_handler) (ptvcursor_t * cursor, packet_info *pinfo, skinny_conv_info_t * skinny_conv);
402 typedef struct _skinny_opcode_map_t {
403 uint32_t opcode;
404 message_handler handler;
405 skinny_message_type_t type;
406 const char *name;
407 } skinny_opcode_map_t;
409 /* Messages Handler Array */
410 /* [[[cog
411 cog.out('static const skinny_opcode_map_t skinny_opcode_map[] = {\n')
412 for message in skinny.message:
413 msg_type = "SKINNY_MSGTYPE_EVENT"
414 if message.msgtype == "request":
415 msg_type = "SKINNY_MSGTYPE_REQUEST"
416 if message.msgtype == "response" and message.request is not None:
417 msg_type = "SKINNY_MSGTYPE_RESPONSE"
418 cog.out(' {%-6s, %-47s, %-24s, "%s"},\n' %(message.opcode, message.gen_handler(), msg_type, message.name))
419 cog.out('};\n')
420 ]]]*/
421 /*[[[end]]]*/
423 /* Dissect a single SKINNY PDU */
424 static int dissect_skinny_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
426 unsigned offset = 0;
427 /*bool is_video = false;*/ /* FIX ME: need to indicate video or not */
428 ptvcursor_t* cursor;
429 conversation_t *conversation;
430 skinny_conv_info_t *skinny_conv;
431 const skinny_opcode_map_t *opcode_entry = NULL;
433 /* Header fields */
434 uint32_t hdr_data_length;
435 uint32_t hdr_version;
436 uint32_t hdr_opcode;
437 uint16_t i;
439 /* Set up structures we will need to add the protocol subtree and manage it */
440 proto_tree *skinny_tree = NULL;
441 proto_item *ti = NULL;
443 /* Initialization */
444 hdr_data_length = tvb_get_letohl(tvb, 0);
445 hdr_version = tvb_get_letohl(tvb, 4);
446 hdr_opcode = tvb_get_letohl(tvb, 8);
448 for (i = 0; i < array_length(skinny_opcode_map); i++) {
449 if (skinny_opcode_map[i].opcode == hdr_opcode) {
450 opcode_entry = &skinny_opcode_map[i];
454 conversation = find_or_create_conversation(pinfo);
455 skinny_conv = (skinny_conv_info_t *)conversation_get_proto_data(conversation, proto_skinny);
456 if (!skinny_conv) {
457 skinny_conv = wmem_new0(wmem_file_scope(), skinny_conv_info_t);
458 //skinny_conv->pending_req_resp = wmem_map_new(wmem_file_scope(), wmem_str_hash, g_str_equal);
459 skinny_conv->pending_req_resp = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
460 skinny_conv->requests = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
461 skinny_conv->responses = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
462 skinny_conv->lineId = -1;
463 skinny_conv->mtype = SKINNY_MSGTYPE_EVENT;
464 conversation_add_proto_data(conversation, proto_skinny, skinny_conv);
467 /* Initialise stat info for passing to tap */
468 /* WIP: will be (partially) replaced in favor of conversionation, dependents: ui/voip_calls.c */
469 pi_current++;
470 if (pi_current == MAX_SKINNY_MESSAGES_IN_PACKET)
472 /* Overwrite info in first struct if run out of space... */
473 pi_current = 0;
475 si = &pi_arr[pi_current];
476 si->messId = hdr_opcode;
477 si->messageName = val_to_str_ext(hdr_opcode, &message_id_ext, "0x%08X (Unknown)");
478 si->callId = 0;
479 si->lineId = 0;
480 si->passThroughPartyId = 0;
481 si->callState = 0;
482 g_free(si->callingParty);
483 si->callingParty = NULL;
484 g_free(si->calledParty);
485 si->calledParty = NULL;
486 si->mediaReceptionStatus = -1;
487 si->mediaTransmissionStatus = -1;
488 si->multimediaReceptionStatus = -1;
489 si->multimediaTransmissionStatus = -1;
490 si->multicastReceptionStatus = -1;
491 g_free(si->additionalInfo);
492 si->additionalInfo = NULL;
494 col_add_fstr(pinfo->cinfo, COL_INFO,"%s ", si->messageName);
495 col_set_fence(pinfo->cinfo, COL_INFO);
497 if (tree) {
498 ti = proto_tree_add_item(tree, proto_skinny, tvb, offset, hdr_data_length+8, ENC_NA);
499 skinny_tree = proto_item_add_subtree(ti, ett_skinny);
502 if (opcode_entry && opcode_entry->type != SKINNY_MSGTYPE_EVENT) {
503 skinny_conv->mtype = opcode_entry->type;
504 if (opcode_entry->type == SKINNY_MSGTYPE_REQUEST) {
505 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY/REQ");
506 } else {
507 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY/RESP");
511 if (skinny_tree) {
512 proto_tree_add_uint(skinny_tree, hf_skinny_data_length, tvb, offset , 4, hdr_data_length);
513 proto_tree_add_uint(skinny_tree, hf_skinny_hdr_version, tvb, offset+4, 4, hdr_version);
514 proto_tree_add_uint(skinny_tree, hf_skinny_messageId, tvb, offset+8, 4, hdr_opcode );
516 offset += 12;
518 cursor = ptvcursor_new(pinfo->pool, skinny_tree, tvb, offset);
519 if (opcode_entry && opcode_entry->handler) {
520 opcode_entry->handler(cursor, pinfo, skinny_conv);
522 ptvcursor_free(cursor);
524 tap_queue_packet(skinny_tap, pinfo, si);
526 return tvb_captured_length(tvb);
529 /* Code to actually dissect the packets */
530 static int
531 dissect_skinny(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
533 /* The general structure of a packet: {IP-Header|TCP-Header|n*SKINNY}
534 * SKINNY-Packet: {Header(Size, Reserved)|Data(MessageID, Message-Data)}
536 /* Header fields */
537 uint32_t hdr_data_length;
538 uint32_t hdr_version;
540 /* check, if this is really an SKINNY packet, they start with a length + 0 */
542 if (tvb_captured_length(tvb) < 8)
544 return 0;
546 /* get relevant header information */
547 hdr_data_length = tvb_get_letohl(tvb, 0);
548 hdr_version = tvb_get_letohl(tvb, 4);
550 /* data_size = MIN(8+hdr_data_length, tvb_length(tvb)) - 0xC; */
552 if (
553 (hdr_data_length < 4) ||
554 ((hdr_version != BASIC_MSG_TYPE) &&
555 (hdr_version != V10_MSG_TYPE) &&
556 (hdr_version != V11_MSG_TYPE) &&
557 (hdr_version != V15_MSG_TYPE) &&
558 (hdr_version != V16_MSG_TYPE) &&
559 (hdr_version != V17_MSG_TYPE) &&
560 (hdr_version != V18_MSG_TYPE) &&
561 (hdr_version != V19_MSG_TYPE) &&
562 (hdr_version != V20_MSG_TYPE) &&
563 (hdr_version != V21_MSG_TYPE) &&
564 (hdr_version != V22_MSG_TYPE))
567 /* Not an SKINNY packet, just happened to use the same port */
568 return 0;
571 /* Make entries in Protocol column and Info column on summary display */
572 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SKINNY");
574 col_set_str(pinfo->cinfo, COL_INFO, "Skinny Client Control Protocol");
576 tcp_dissect_pdus(tvb, pinfo, tree, global_skinny_desegment, 4, get_skinny_pdu_len, dissect_skinny_pdu, data);
578 return tvb_captured_length(tvb);
581 /* Register the protocol with Wireshark */
582 void
583 proto_register_skinny(void)
585 /* Setup list of header fields */
586 static hf_register_info hf[] = {
587 { &hf_skinny_data_length,
589 "Data length", "skinny.data_length", FT_UINT32, BASE_DEC, NULL, 0x0,
590 "Number of bytes in the data portion.", HFILL }},
591 { &hf_skinny_hdr_version,
593 "Header version", "skinny.hdr_version", FT_UINT32, BASE_HEX, VALS(header_version), 0x0,
594 NULL, HFILL }},
595 { &hf_skinny_messageId,
597 "Message ID", "skinny.messageId", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &message_id_ext, 0x0,
598 NULL, HFILL }},
599 { &hf_skinny_xmlData,
601 "XML data", "skinny.xmlData", FT_STRING, BASE_NONE, NULL, 0x0,
602 NULL, HFILL }},
603 { &hf_skinny_ipv4or6,
605 "IPv4or6", "skinny.ipv4or6", FT_UINT32, BASE_DEC|BASE_EXT_STRING, &IpAddrType_ext, 0x0,
606 NULL, HFILL }},
607 { &hf_skinny_response_in,
609 "Response In", "skinny.response_in", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
610 "The response to this SKINNY request is in this frame", HFILL }},
611 { &hf_skinny_response_to,
613 "Request In", "skinny.response_to", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
614 "This is a response to the SKINNY request in this frame", HFILL }},
615 { &hf_skinny_response_time,
617 "Response Time", "skinny.response_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0,
618 "The time between the Call and the Reply", HFILL }},
619 /* [[[cog
620 for valuestr in sorted(xml2skinny.fieldsArray.values()):
621 cog.out('%s' %valuestr)
622 ]]]*/
623 /*[[[end]]]*/
626 /* Setup protocol subtree array */
627 static int *ett[] = {
628 &ett_skinny,
629 &ett_skinny_tree,
632 module_t *skinny_module;
634 /* Register the protocol name and description */
635 proto_skinny = proto_register_protocol("Skinny Client Control Protocol",
636 "SKINNY", "skinny");
638 /* Required function calls to register the header fields and subtrees used */
639 proto_register_field_array(proto_skinny, hf, array_length(hf));
640 proto_register_subtree_array(ett, array_length(ett));
642 skinny_module = prefs_register_protocol(proto_skinny, NULL);
643 prefs_register_bool_preference(skinny_module, "desegment",
644 "Reassemble SKINNY messages spanning multiple TCP segments",
645 "Whether the SKINNY dissector should reassemble messages spanning multiple TCP segments."
646 " To use this option, you must also enable"
647 " \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
648 &global_skinny_desegment);
650 skinny_handle = register_dissector("skinny", dissect_skinny, proto_skinny);
652 skinny_tap = register_tap("skinny");
655 void
656 proto_reg_handoff_skinny(void)
658 /* Skinny content type and internet media type used by other dissectors are the same */
659 xml_handle = find_dissector_add_dependency("xml", proto_skinny);
660 dissector_add_uint_with_preference("tcp.port", TCP_PORT_SKINNY, skinny_handle);
661 ssl_dissector_add(SSL_PORT_SKINNY, skinny_handle);
665 * Editor modelines - https://www.wireshark.org/tools/modelines.html
667 * Local variables:
668 * c-basic-offset: 2
669 * tab-width: 8
670 * indent-tabs-mode: nil
671 * End:
673 * vi: set shiftwidth=2 tabstop=8 expandtab:
674 * :indentSize=2:tabSize=8:noTabs=true: