2 * Routines for PROTONAME dissection
3 * Copyright 2012, Gregor Beck <gregor.beck@sernet.de>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 /* Include only as needed */
37 #include <epan/packet.h>
38 #include <epan/prefs.h>
40 #include "packet-smb.h"
41 #include "packet-smb2.h"
43 /* IF PROTO exposes code to other dissectors, then it must be exported
44 in a header file. If not, a header file is not needed at all. */
46 * #include "packet-mswsp.h"
51 /* Forward declaration we need below (if using proto_reg_handoff...
52 as a prefs callback) */
53 void proto_reg_handoff_mswsp(void);
55 /* Initialize the protocol and registered fields */
56 static int proto_mswsp
= -1;
57 static int hf_mswsp_msg
= -1;
58 static int hf_mswsp_hdr
= -1;
59 static int hf_mswsp_hdr_msg
= -1;
60 static int hf_mswsp_hdr_status
= -1;
61 static int hf_mswsp_hdr_checksum
= -1;
62 static int hf_mswsp_hdr_reserved
= -1;
63 static int hf_mswsp_msg_ConnectIn_ClientVersion
= -1;
64 static int hf_mswsp_msg_ConnectIn_ClientIsRemote
= -1;
65 static int hf_mswsp_msg_ConnectIn_Blob1
= -1;
66 static int hf_mswsp_msg_ConnectIn_Blob2
= -1;
67 static int hf_mswsp_msg_ConnectIn_MachineName
= -1;
68 static int hf_mswsp_msg_ConnectIn_UserName
= -1;
70 /* Global sample preference ("controls" display of numbers) */
71 static gboolean gPREF_HEX
= FALSE
;
72 /* Global sample port pref */
73 static guint gPORT_PREF
= 1234;
75 /* Initialize the subtree pointers */
76 static gint ett_mswsp
= -1;
77 static gint ett_mswsp_hdr
= -1;
78 static gint ett_mswsp_msg
= -1;
80 /* Code to actually dissect the packets */
82 static int dissect_CPMConnect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, gboolean in
)
84 proto_item
*ti
= proto_tree_add_item(parent_tree
, hf_mswsp_msg
, tvb
, 17, -1, ENC_NA
);
85 proto_tree
*tree
= proto_item_add_subtree(ti
, ett_mswsp_msg
);
88 proto_item_set_text(ti
, "CPMConnect%s", in
? "In" : "Out");
89 col_append_str(pinfo
->cinfo
, COL_INFO
, "Connect");
91 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_ClientVersion
, tvb
,
92 offset
, 4, ENC_LITTLE_ENDIAN
);
95 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_ClientIsRemote
, tvb
,
96 offset
, 4, ENC_LITTLE_ENDIAN
);
99 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_Blob1
, tvb
,
100 offset
, 4, ENC_LITTLE_ENDIAN
);
103 proto_tree_add_text(tree
, tvb
, offset
, 4, "Padding");
106 proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_Blob2
, tvb
,
107 offset
, 4, ENC_LITTLE_ENDIAN
);
110 proto_tree_add_text(tree
, tvb
, offset
, 12, "Padding");
113 len
= tvb_unicode_strsize(tvb
, offset
);
114 ti
= proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_MachineName
, tvb
,
115 offset
, len
, ENC_UTF_16
);
116 /*This shouldnt be necessary, is this a bug or is there some GUI setting I've missed?*/
117 proto_item_set_text(ti
, "Remote machine: %s",
118 tvb_get_unicode_string(tvb
, offset
, len
, ENC_LITTLE_ENDIAN
));
121 len
= tvb_unicode_strsize(tvb
, offset
);
122 ti
= proto_tree_add_item(tree
, hf_mswsp_msg_ConnectIn_UserName
, tvb
,
123 offset
, len
, ENC_UTF_16
);
124 proto_item_set_text(ti
, "User: %s", tvb_get_unicode_string(tvb
, offset
, len
, ENC_LITTLE_ENDIAN
));
128 int pad
= 8 - (offset
% 8);
129 proto_tree_add_text(tree
, tvb
, offset
, pad
, "Padding");
132 DISSECTOR_ASSERT((offset
% 8) == 0);
133 proto_tree_add_text(tree
, tvb
, offset
, -1, "Rest: propsets etc.");
135 return tvb_length(tvb
);
138 static int dissect_CPMDisconnect(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
140 col_append_str(pinfo
->cinfo
, COL_INFO
, "Disconnect");
141 return tvb_length(tvb
);
144 static int dissect_CPMCreateQuery(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
146 col_append_str(pinfo
->cinfo
, COL_INFO
, "CreateQuery");
147 return tvb_length(tvb
);
150 static int dissect_CPMFreeCursor(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
152 col_append_str(pinfo
->cinfo
, COL_INFO
, "FreeCursor");
153 return tvb_length(tvb
);
156 static int dissect_CPMGetRows(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
158 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetRows");
159 return tvb_length(tvb
);
162 static int dissect_CPMRatioFinished(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
164 col_append_str(pinfo
->cinfo
, COL_INFO
, "RatioFinished");
165 return tvb_length(tvb
);
168 static int dissect_CPMCompareBmk(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
170 col_append_str(pinfo
->cinfo
, COL_INFO
, "CompareBmk");
171 return tvb_length(tvb
);
174 static int dissect_CPMGetApproximatePosition(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
176 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetApproximatePosition");
177 return tvb_length(tvb
);
180 static int dissect_CPMSetBindings(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
182 col_append_str(pinfo
->cinfo
, COL_INFO
, "SetBindings");
183 return tvb_length(tvb
);
186 static int dissect_CPMGetNotify(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
188 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetNotify");
189 return tvb_length(tvb
);
192 static int dissect_CPMSendNotifyOut(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
194 col_append_str(pinfo
->cinfo
, COL_INFO
, "SendNotify");
195 return tvb_length(tvb
);
198 static int dissect_CPMGetQueryStatus(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
200 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetQueryStatus");
201 return tvb_length(tvb
);
204 static int dissect_CPMCiState(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
206 col_append_str(pinfo
->cinfo
, COL_INFO
, "CiState");
207 return tvb_length(tvb
);
210 static int dissect_CPMFetchValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
212 col_append_str(pinfo
->cinfo
, COL_INFO
, "FetchValue");
213 return tvb_length(tvb
);
216 static int dissect_CPMGetQueryStatusEx(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
218 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetQueryStatusEx");
219 return tvb_length(tvb
);
222 static int dissect_CPMRestartPosition(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
224 col_append_str(pinfo
->cinfo
, COL_INFO
, "RestartPosition");
225 return tvb_length(tvb
);
228 static int dissect_CPMSetCatState(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
230 col_append_str(pinfo
->cinfo
, COL_INFO
, "SetCatState");
231 return tvb_length(tvb
);
234 static int dissect_CPMGetRowsetNotify(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
236 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetRowsetNotify");
237 return tvb_length(tvb
);
240 static int dissect_CPMFindIndices(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
242 col_append_str(pinfo
->cinfo
, COL_INFO
, "FindIndices");
243 return tvb_length(tvb
);
246 static int dissect_CPMSetScopePrioritization(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
248 col_append_str(pinfo
->cinfo
, COL_INFO
, "SetScopePrioritization");
249 return tvb_length(tvb
);
252 static int dissect_CPMGetScopeStatistics(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, gboolean in _U_
)
254 col_append_str(pinfo
->cinfo
, COL_INFO
, "GetScopeStatistics");
255 return tvb_length(tvb
);
260 dissect_mswsp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gboolean in
)
262 proto_tree
*mswsp_tree
= NULL
;
269 int (*fn
)(tvbuff_t
*, packet_info
*, proto_tree
*, gboolean
);
271 if (tvb_length(tvb
) < 16) {
275 hdr
.msg
= tvb_get_letoh24(tvb
, 0);
279 fn
= dissect_CPMConnect
;
282 fn
= dissect_CPMDisconnect
;
285 fn
= dissect_CPMCreateQuery
;
288 fn
= dissect_CPMFreeCursor
;
291 fn
= dissect_CPMGetRows
;
294 fn
= dissect_CPMRatioFinished
;
297 fn
= dissect_CPMCompareBmk
;
300 fn
= dissect_CPMGetApproximatePosition
;
303 fn
= dissect_CPMSetBindings
;
306 fn
= dissect_CPMGetNotify
;
309 fn
= dissect_CPMSendNotifyOut
;
312 fn
= dissect_CPMGetQueryStatus
;
315 fn
= dissect_CPMCiState
;
318 fn
= dissect_CPMFetchValue
;
321 fn
= dissect_CPMGetQueryStatusEx
;
324 fn
= dissect_CPMRestartPosition
;
327 fn
= dissect_CPMSetCatState
;
330 fn
= dissect_CPMGetRowsetNotify
;
333 fn
= dissect_CPMFindIndices
;
336 fn
= dissect_CPMSetScopePrioritization
;
339 fn
= dissect_CPMGetScopeStatistics
;
345 hdr
.status
= tvb_get_letoh24(tvb
, 4);
346 hdr
.checksum
= tvb_get_letoh24(tvb
, 8);
348 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MS-WSP");
349 /* col_clear(pinfo->cinfo, COL_INFO); */
351 col_set_str(pinfo
->cinfo
, COL_INFO
, "WSP ");
352 col_append_str(pinfo
->cinfo
, COL_INFO
, in
? "Request: " : "Response: ");
355 proto_tree
*hdr_tree
;
356 proto_item
*ti
, *hti
;
358 ti
= proto_tree_add_item(tree
, proto_mswsp
, tvb
, 0, -1, ENC_NA
);
359 mswsp_tree
= proto_item_add_subtree(ti
, ett_mswsp
);
361 hti
= proto_tree_add_item(mswsp_tree
, hf_mswsp_hdr
, tvb
, 0, 16, ENC_NA
);
362 hdr_tree
= proto_item_add_subtree(hti
, ett_mswsp_hdr
);
364 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_msg
, tvb
,
365 0, 4, ENC_LITTLE_ENDIAN
);
366 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_status
,
367 tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
368 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_checksum
,
369 tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
370 proto_tree_add_item(hdr_tree
, hf_mswsp_hdr_reserved
, tvb
,
371 12, 4, ENC_LITTLE_ENDIAN
);
372 /* if (tvb_length(tvb) > 16) { */
373 /* bti = proto_tree_add_item(mswsp_tree, hf_mswsp_bdy, tvb, 17, -1, ENC_NA); */
375 /* mswsp_bdy_tree = proto_item_add_subtree(bti, ett_mswsp_msg); */
379 fn(tvb
, pinfo
, mswsp_tree
, in
);
381 /* Return the amount of data this dissector was able to dissect */
382 return tvb_length(tvb
);
386 /* Register the protocol with Wireshark */
388 /* this format is require because a script is used to build the C function
389 that calls all the protocol registration.
393 proto_register_mswsp(void)
395 module_t
*mswsp_module
;
397 /* Setup list of header fields See Section 1.6.1 for details*/
398 static const value_string msg_ids
[] = {
399 {0x000000C8, "CPMConnect"}, /* In/Out */
400 {0x000000C9, "CPMDisconnect"},
401 {0x000000CA, "CPMCreateQuery"}, /* In/Out */
402 {0x000000CB, "CPMFreeCursor"}, /* In/Out */
403 {0x000000CC, "CPMGetRows"}, /* In/Out */
404 {0x000000CD, "CPMRatioFinished"}, /* In/Out */
405 {0x000000CE, "CPMCompareBmk"}, /* In/Out */
406 {0x000000CF, "CPMGetApproximatePosition"}, /* In/Out */
407 {0x000000D0, "CPMSetBindingsIn"},
408 {0x000000D1, "CPMGetNotify"},
409 {0x000000D2, "CPMSendNotifyOut"},
410 {0x000000D7, "CPMGetQueryStatusIn"}, /* In/Out */
411 {0x000000D9, "CPMCiStateInOut"},
412 {0x000000E4, "CPMFetchValue"}, /* In/Out */
413 {0x000000E7, "CPMGetQueryStatusEx"}, /* In/Out */
414 {0x000000E8, "CPMRestartPositionIn"},
415 {0x000000EC, "CPMSetCatStateIn"}, /* (not supported) */
416 {0x000000F1, "CPMGetRowsetNotify"}, /* In/Out */
417 {0x000000F2, "CPMFindIndices"}, /* In/Out */
418 {0x000000F3, "CPMSetScopePrioritization"}, /* In/Out */
419 {0x000000F4, "CPMGetScopeStatistics"}, /* In/Out */
422 static hf_register_info hf
[] = {
424 { "Header", "mswsp.hdr",
425 FT_NONE
, BASE_NONE
, NULL
, 0,
426 "Message header", HFILL
}
429 { "Msg id", "mswsp.hdr.id",
430 FT_UINT32
, BASE_HEX
, VALS(msg_ids
), 0,
431 "Message id", HFILL
}
433 { &hf_mswsp_hdr_status
,
434 { "Status", "mswsp.hdr.status",
435 FT_UINT32
, BASE_HEX
, NULL
, 0,
438 { &hf_mswsp_hdr_checksum
,
439 { "checksum", "mswsp.hdr.checksum",
440 FT_UINT32
, BASE_HEX
, NULL
, 0,
443 { &hf_mswsp_hdr_reserved
,
444 { "Reserved", "mswsp.hdr.reserved",
445 FT_UINT32
, BASE_HEX
, NULL
, 0,
449 { "msg", "mswsp.msg",
450 FT_NONE
, BASE_NONE
, NULL
, 0,
453 { &hf_mswsp_msg_ConnectIn_ClientVersion
,
454 { "Version", "mswsp.ConnectIn.version",
455 FT_UINT32
, BASE_HEX
, NULL
, 0,
458 { &hf_mswsp_msg_ConnectIn_ClientIsRemote
,
459 { "Remote", "mswsp.ConnectIn.isRemote",
460 FT_BOOLEAN
, BASE_HEX
, NULL
, 0,
461 "Client is remote",HFILL
}
463 { &hf_mswsp_msg_ConnectIn_Blob1
,
464 { "Blob1 size", "mswsp.ConnectIn.blob1",
465 FT_UINT32
, BASE_HEX
, NULL
, 0,
466 "Size of PropSet fields",HFILL
}
468 { &hf_mswsp_msg_ConnectIn_Blob2
,
469 { "Blob2 size", "mswsp.ConnectIn.blob2",
470 FT_UINT32
, BASE_HEX
, NULL
, 0,
471 "Size of ExtPropSet fields",HFILL
}
473 { &hf_mswsp_msg_ConnectIn_MachineName
,
474 { "Remote machine", "mswsp.ConnectIn.machine",
475 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
476 "Name of remote machine",HFILL
}
478 { &hf_mswsp_msg_ConnectIn_UserName
,
479 { "User", "mswsp.ConnectIn.user",
480 FT_STRINGZ
, BASE_NONE
, NULL
, 0,
481 "Name of remote user",HFILL
}
485 /* Setup protocol subtree array */
486 static gint
*ett
[] = {
492 /* Register the protocol name and description */
493 proto_mswsp
= proto_register_protocol("Windows Search Protocol",
496 /* Required function calls to register the header fields and subtrees used */
497 proto_register_field_array(proto_mswsp
, hf
, array_length(hf
));
498 proto_register_subtree_array(ett
, array_length(ett
));
500 /* Register preferences module (See Section 2.6 for more on preferences) */
501 /* (Registration of a prefs callback is not required if there are no */
502 /* prefs-dependent registration functions (eg: a port pref). */
503 /* See proto_reg_handoff below. */
504 /* If a prefs callback is not needed, use NULL instead of */
505 /* proto_reg_handoff_mswsp in the following). */
506 mswsp_module
= prefs_register_protocol(proto_mswsp
,
507 proto_reg_handoff_mswsp
);
509 /* Register preferences module under preferences subtree.
510 Use this function instead of prefs_register_protocol if you want to group
511 preferences of several protocols under one preferences subtree.
512 Argument subtree identifies grouping tree node name, several subnodes can be
513 specified using slash '/' (e.g. "OSI/X.500" - protocol preferences will be
514 accessible under Protocols->OSI->X.500-><PROTOSHORTNAME> preferences node.
516 /* mswsp_module = prefs_register_protocol_subtree(subtree, */
517 /* proto_mswsp, proto_reg_handoff_mswsp); */
519 /* Register a sample preference */
520 prefs_register_bool_preference(mswsp_module
, "show_hex",
521 "Display numbers in Hex",
522 "Enable to display numerical values in hexadecimal.",
525 /* Register a sample port preference */
526 prefs_register_uint_preference(mswsp_module
, "tcp.port", "mswsp TCP Port",
527 " mswsp TCP port if other than the default",
531 static int dissect_mswsp_smb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
532 smb_info_t
*si
= pinfo
->private_data
;
533 gboolean in
= si
->request
;
535 fprintf(stderr
, "dissect_mswsp_smb %d <> %d : op %02x %s %s type: %d\n",
536 pinfo
->fd
->num
, si
->tid
,
538 pinfo
->dcerpc_procedure_name
? pinfo
->dcerpc_procedure_name
: "<NULL>",
539 in
? "Request" : "Response", si
->tid
);
542 if (strcmp(pinfo
->dcerpc_procedure_name
, "File: MsFteWds") != 0) {
546 return dissect_mswsp(tvb
, pinfo
, tree
, in
);
550 static int dissect_mswsp_smb2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
551 smb2_info_t
*si
= pinfo
->private_data
;
552 gboolean in
= !(si
->flags
& SMB2_FLAGS_RESPONSE
);
554 //si->tree->share_type == SMB2_SHARE_TYPE_PIPE
555 //si->tree->connect_frame
557 fprintf(stderr
, "dissect_mswsp %d <> %d : op %02x %s %s type: %d extra_file: %s\n",
558 pinfo
->fd
->num
, si
->tree
? (int)si
->tree
->connect_frame
: -1,
560 pinfo
->dcerpc_procedure_name
? pinfo
->dcerpc_procedure_name
: "<NULL>",
561 in
? "Request" : "Response", si
->tree
? si
->tree
->share_type
: -1,
562 si
->saved
? (si
->saved
->extra_info_type
== SMB2_EI_FILENAME
? (char*)si
->saved
->extra_info
: "<OTHER>") : "<NONE>"
566 if (strcmp(pinfo
->dcerpc_procedure_name
, "File: MsFteWds") != 0) {
570 return dissect_mswsp(tvb
, pinfo
, tree
, in
);
575 /* If this dissector uses sub-dissector registration add a registration routine.
576 This exact format is required because a script is used to find these
577 routines and create the code that calls these routines.
579 If this function is registered as a prefs callback (see prefs_register_protocol
580 above) this function is also called by preferences whenever "Apply" is pressed;
581 In that case, it should accommodate being called more than once.
583 Simple form of proto_reg_handoff_mswsp which can be used if there are
584 no prefs-dependent registration function calls.
588 proto_reg_handoff_mswsp(void)
590 heur_dissector_add("smb_transact", dissect_mswsp_smb
, proto_mswsp
);
591 heur_dissector_add("smb2_heur_subdissectors", dissect_mswsp_smb2
, proto_mswsp
);
596 * Editor modelines - http://www.wireshark.org/tools/modelines.html
601 * indent-tabs-mode: nil
604 * vi: set shiftwidth=4 tabstop=8 expandtab:
605 * :indentSize=4:tabSize=8:noTabs=true: