From 8574d8c624e1484a6b89c7ff2cf21617b710187c Mon Sep 17 00:00:00 2001 From: Martin Gallo Date: Fri, 28 Mar 2014 09:54:01 -0300 Subject: [PATCH] Initial commit --- CMakeLists.txt | 67 + COPYING | 340 +++++ ChangeLog | 56 + Makefile.am | 134 ++ Makefile.common | 53 + Makefile.nmake | 112 ++ README | 152 ++ hpa101saptype.h | 51 + hpa104CsObject.h | 161 ++ hpa105CsObjInt.h | 516 +++++++ hpa106cslzc.h | 200 +++ hpa107cslzh.h | 90 ++ moduleinfo.h | 17 + moduleinfo.nmake | 28 + packet-sapdiag.c | 3428 ++++++++++++++++++++++++++++++++++++++++++ packet-sapenqueue.c | 413 +++++ packet-sapms.c | 1502 ++++++++++++++++++ packet-sapprotocol.c | 275 ++++ packet-sapprotocol.h | 30 + packet-saprfc.c | 1271 ++++++++++++++++ packet-saprouter.c | 640 ++++++++ packet-sapsnc.c | 139 ++ plugin.rc.in | 34 + sapdecompress.cpp | 146 ++ sapdecompress.h | 70 + saphelpers.h | 47 + vpa105CsObjInt.cpp | 339 +++++ vpa106cslzc.cpp | 942 ++++++++++++ vpa107cslzh.cpp | 1499 ++++++++++++++++++ vpa108csulzh.cpp | 1066 +++++++++++++ wireshark.patch | 121 ++ 31 files changed, 13939 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 Makefile.common create mode 100644 Makefile.nmake create mode 100644 README create mode 100644 hpa101saptype.h create mode 100644 hpa104CsObject.h create mode 100644 hpa105CsObjInt.h create mode 100644 hpa106cslzc.h create mode 100644 hpa107cslzh.h create mode 100644 moduleinfo.h create mode 100644 moduleinfo.nmake create mode 100644 packet-sapdiag.c create mode 100644 packet-sapenqueue.c create mode 100644 packet-sapms.c create mode 100644 packet-sapprotocol.c create mode 100644 packet-sapprotocol.h create mode 100644 packet-saprfc.c create mode 100644 packet-saprouter.c create mode 100644 packet-sapsnc.c create mode 100644 plugin.rc.in create mode 100644 sapdecompress.cpp create mode 100644 sapdecompress.h create mode 100644 saphelpers.h create mode 100644 vpa105CsObjInt.cpp create mode 100644 vpa106cslzc.cpp create mode 100644 vpa107cslzh.cpp create mode 100644 vpa108csulzh.cpp create mode 100644 wireshark.patch diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f90e5e0 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,67 @@ +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== + +set(DISSECTOR_SRC + packet-sapdiag.c + packet-sapenqueue.c + packet-saprouter.c + packet-sapprotocol.c + packet-saprfc.c + packet-sapms.c + packet-sapsnc.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set(CLEAN_FILES + ${PLUGIN_FILES} +) + +if (WERROR) + set_source_files_properties( + ${CLEAN_FILES} + PROPERTIES + COMPILE_FLAGS -Werror + ) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +register_dissector_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_library(sap ${LINK_MODE_MODULE} + ${PLUGIN_FILES} +) +set_target_properties(sap PROPERTIES PREFIX "") +set_target_properties(sap PROPERTIES LINK_FLAGS "${WS_LINK_FLAGS}") + +target_link_libraries(sap epan) + +install(TARGETS sap + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/@CPACK_PACKAGE_NAME@/plugins/${CPACK_PACKAGE_VERSION} NAMELINK_SKIP + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/@CPACK_PACKAGE_NAME@/plugins/${CPACK_PACKAGE_VERSION} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/@CPACK_PACKAGE_NAME@/plugins/${CPACK_PACKAGE_VERSION} +) + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d60c31a --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..897ae19 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,56 @@ +2014-03-25 Martin Gallo + + * - Version v0.1.4 released at Troopers'14. + * - Changelog now in GNU format. + * - Switched to wireshark 1.10 trunk. + * - Moved to the use of the new memory allocation API (wmem) on all + dissectors. + * packet-sapdiag.c: Fixed some support bits and added new ones found on SAP + GUI version 7.30. + * packet-sapdiag.c: Added dissection of new Diag Items: WindowsSize. + * packet-sapenqueue.c: New dissector. Parsing of Enqueue Server packets. + * packet-sapms.c: New dissector. Parsing of Message Server packets. + * packet-sapprotocol.c: Subdissectors tables are now handled only on the + NI Protocol dissector. + * packet-sapprotocol.h: Exported function to look at the NI Protocol + sub-dissector table. + * packet-saprfc.c: The RFC dissector now registeres two separate handlers: + one for internal calls (e.g. from SAP Diag dissector) and another for + external communications (e.g. RFC or Gateway Monitor). + * packet-saprfc.c: Refactored almost all of the dissector code. Added lot + of new fields and fixed some issues. + * packet-saprfc.c: Fixed reassemble of RFC tables. + * packet-saprouter.c: Added dissection of Admin and Control messages. + * packet-saprouter.c: Protocol port preference changed to a range to cover + the port used by niping. + * packet-sapsnc.c: New dissector. Moved dissection of SNC frames to a new + dissector for using it as subdissector of both SAP Router and SAP Diag + packets. + * sapdecompress.h: Exported return code strings for using it in both Diag + and RFC dissectors. + * wireshark.patch: Switched patch file to GIT as the repository isn't + updated on SVN now. + +2013-03-22 Martin Gallo + + * - Version v0.1.3 released. + * packet-sapdiag.c, packet-saprfc.c: Fixed compilations errors on RFC and + Diag dissectors and removed some warnings. + +2012-09-27 Martin Gallo + + * - Version v0.1.2 released at Brucon'12. + * packet-saprouter.c: Fixed minor issues and added dissection of Admin + requests. Thanks Dave (@nmonkee) for the feedback and reporting the issues. + * packet-saprouter.c: Route and Admin passwords are highlighted as Security + via expert warnings. + * packet-sapdiag.c: Added dissection of new Diag Atom types, as used in NW + 7.01 and early versions, and UI Events. + * packet-sapdiag.c: Added a preference setting for enabling highlighting of + unknown Diag Item/Atom types and password fields via expert warnings. + * packet-saprfc.c: Added a preference setting for enabling highlighting of + unknown RFC types via expert warnings. + +2012-07-29 Martin Gallo + + * - Initial version v0.1.1 releaseed at Defcon 20. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..be66b0b --- /dev/null +++ b/Makefile.am @@ -0,0 +1,134 @@ +# Makefile.am +# +# Automake file for SAP Dissector Plugin for Wireshark +# +# $Id$ +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.am.inc + +INCLUDES = -I$(top_srcdir) + +include Makefile.common + +if HAVE_WARNINGS_AS_ERRORS +AM_CFLAGS = -Werror +endif + +plugindir = @plugindir@ + +plugin_LTLIBRARIES = sap.la + +sap_la_SOURCES = \ + plugin.c \ + moduleinfo.h \ + $(DISSECTOR_SRC) \ + $(DISSECTOR_SUPPORT_SRC) \ + $(DISSECTOR_INCLUDES) + +sap_la_LDFLAGS = -module -avoid-version +sap_la_LIBADD = @PLUGIN_LIBS@ + +# Libs must be cleared, or else libtool won't create a shared module. +# If your module needs to be linked against any particular libraries, +# add them here. +LIBS = + +# +# Build plugin.c, which contains the plugin version[] string, a +# function plugin_register() that calls the register routines for all +# protocols, and a function plugin_reg_handoff() that calls the handoff +# registration routines for all protocols. +# +# We do this by scanning sources. If that turns out to be too slow, +# maybe we could just require every .o file to have an register routine +# of a given name (packet-aarp.o -> proto_register_aarp, etc.). +# +# Formatting conventions: The name of the proto_register_* routines an +# proto_reg_handoff_* routines must start in column zero, or must be +# preceded only by "void " starting in column zero, and must not be +# inside #if. +# +# DISSECTOR_SRC is assumed to have all the files that need to be scanned. +# +# For some unknown reason, having a big "for" loop in the Makefile +# to scan all the files doesn't work with some "make"s; they seem to +# pass only the first few names in the list to the shell, for some +# reason. +# +# Therefore, we have a script to generate the plugin.c file. +# The shell script runs slowly, as multiple greps and seds are run +# for each input file; this is especially slow on Windows. Therefore, +# if Python is present (as indicated by PYTHON being defined), we run +# a faster Python script to do that work instead. +# +# The first argument is the directory in which the source files live. +# The second argument is "plugin", to indicate that we should build +# a plugin.c file for a plugin. +# All subsequent arguments are the files to scan. +# +plugin.c: $(DISSECTOR_SRC) $(top_srcdir)/tools/make-dissector-reg \ + $(top_srcdir)/tools/make-dissector-reg.py + @if test -n "$(PYTHON)"; then \ + echo Making plugin.c with python ; \ + $(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \ + plugin $(DISSECTOR_SRC) ; \ + else \ + echo Making plugin.c with shell script ; \ + $(top_srcdir)/tools/make-dissector-reg $(srcdir) \ + $(plugin_src) plugin $(DISSECTOR_SRC) ; \ + fi + +# +# Currently plugin.c can be included in the distribution because +# we always build all protocol dissectors. We used to have to check +# whether or not to build the snmp dissector. If we again need to +# variably build something, making plugin.c non-portable, uncomment +# the dist-hook line below. +# +# Oh, yuk. We don't want to include "plugin.c" in the distribution, as +# its contents depend on the configuration, and therefore we want it +# to be built when the first "make" is done; however, Automake insists +# on putting *all* source into the distribution. +# +# We work around this by having a "dist-hook" rule that deletes +# "plugin.c", so that "dist" won't pick it up. +# +#dist-hook: +# @rm -f $(distdir)/plugin.c + +CLEANFILES = \ + sap \ + *~ + +MAINTAINERCLEANFILES = \ + Makefile.in \ + plugin.c + +EXTRA_DIST = \ + Makefile.common \ + Makefile.nmake \ + moduleinfo.nmake \ + plugin.rc.in \ + CMakeLists.txt + +checkapi: + $(PERL) $(top_srcdir)/tools/checkAPIs.pl -g abort -g termoutput $(DISSECTOR_SRC) $(DISSECTOR_INCLUDES) diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 0000000..92fd645 --- /dev/null +++ b/Makefile.common @@ -0,0 +1,53 @@ +# Makefile.common for SAP Dissector Plugin for Wireshark +# Contains the stuff from Makefile.am and Makefile.nmake that is +# a) common to both files and +# b) portable between both files +# +# $Id: Makefile.common 27491 2009-02-21 16:33:48Z jake $ +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# the name of the plugin +PLUGIN_NAME = sap + +# the dissector sources (without any helpers) +DISSECTOR_SRC = \ + packet-sapdiag.c \ + packet-sapenqueue.c \ + packet-saprouter.c \ + packet-sapprotocol.c \ + packet-saprfc.c \ + packet-sapms.c \ + packet-sapsnc.c + +# corresponding headers +DISSECTOR_INCLUDES = \ + packet-sapprotocol.h + +# Dissector helpers. They're included in the source files in this +# directory, but they're not dissectors themselves, i.e. they're not +# used to generate "plugin.c". +DISSECTOR_SUPPORT_SRC = \ + sapdecompress.cpp \ + vpa105CsObjInt.cpp \ + vpa106cslzc.cpp \ + vpa107cslzh.cpp \ + vpa108csulzh.cpp + +include ../Makefile.common.inc \ No newline at end of file diff --git a/Makefile.nmake b/Makefile.nmake new file mode 100644 index 0000000..64733f6 --- /dev/null +++ b/Makefile.nmake @@ -0,0 +1,112 @@ +# Makefile.nmake +# nmake file for SAP Dissector Plugin for Wireshark +# + +include ..\..\config.nmake +include moduleinfo.nmake + +include Makefile.common + +C_CPP_COMMON_FLAGS=/DHAVE_CONFIG_H /I../.. /I../../wiretap $(GLIB_CFLAGS) \ + /I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS) + +CFLAGS=/WX $(C_CPP_COMMON_FLAGS) + +CPPFLAGS=/EHsc $(C_CPP_COMMON_FLAGS) /DWIRESHARK_VERSION_NUMBER=$(WIRESHARK_VERSION_NUMBER) + +CFLAGS=$(WARNINGS_ARE_ERRORS) $(STANDARD_CFLAGS) \ + /I../.. $(GLIB_CFLAGS) \ + /I$(PCAP_DIR)\include + +.c.obj:: + $(CC) $(CFLAGS) -Fd.\ -c $< + +.cpp.obj:: + $(CC) $(CPPFLAGS) /c $< + +LDFLAGS = $(PLUGIN_LDFLAGS) + +!IFDEF ENABLE_LIBWIRESHARK +LINK_PLUGIN_WITH=..\..\epan\libwireshark.lib +CFLAGS=/D_NEED_VAR_IMPORT_ $(CFLAGS) + +DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj) + +DISSECTOR_SUPPORT_OBJECTS = $(DISSECTOR_SUPPORT_SRC:.cpp=.obj) + +OBJECTS = $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS) plugin.obj + +RESOURCE=$(PLUGIN_NAME).res + +all: $(PLUGIN_NAME).dll + +$(PLUGIN_NAME).rc : moduleinfo.nmake + sed -e s/@PLUGIN_NAME@/$(PLUGIN_NAME)/ \ + -e s/@RC_MODULE_VERSION@/$(RC_MODULE_VERSION)/ \ + -e s/@RC_VERSION@/$(RC_VERSION)/ \ + -e s/@MODULE_VERSION@/$(MODULE_VERSION)/ \ + -e s/@PACKAGE@/$(PACKAGE)/ \ + -e s/@VERSION@/$(VERSION)/ \ + -e s/@MSVC_VARIANT@/$(MSVC_VARIANT)/ \ + < plugin.rc.in > $@ + +$(PLUGIN_NAME).dll $(PLUGIN_NAME).exp $(PLUGIN_NAME).lib : $(OBJECTS) $(LINK_PLUGIN_WITH) $(RESOURCE) + link -dll /out:$(PLUGIN_NAME).dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \ + $(GLIB_LIBS) $(RESOURCE) + +# +# Build plugin.c, which contains the plugin version[] string, a +# function plugin_register() that calls the register routines for all +# protocols, and a function plugin_reg_handoff() that calls the handoff +# registration routines for all protocols. +# +# We do this by scanning sources. If that turns out to be too slow, +# maybe we could just require every .o file to have an register routine +# of a given name (packet-aarp.o -> proto_register_aarp, etc.). +# +# Formatting conventions: The name of the proto_register_* routines an +# proto_reg_handoff_* routines must start in column zero, or must be +# preceded only by "void " starting in column zero, and must not be +# inside #if. +# +# DISSECTOR_SRC is assumed to have all the files that need to be scanned. +# +# For some unknown reason, having a big "for" loop in the Makefile +# to scan all the files doesn't work with some "make"s; they seem to +# pass only the first few names in the list to the shell, for some +# reason. +# +# Therefore, we have a script to generate the plugin.c file. +# The shell script runs slowly, as multiple greps and seds are run +# for each input file; this is especially slow on Windows. Therefore, +# if Python is present (as indicated by PYTHON being defined), we run +# a faster Python script to do that work instead. +# +# The first argument is the directory in which the source files live. +# The second argument is "plugin", to indicate that we should build +# a plugin.c file for a plugin. +# All subsequent arguments are the files to scan. +# +!IFDEF PYTHON +plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg.py + @echo Making plugin.c (using python) + @$(PYTHON) "../../tools/make-dissector-reg.py" . plugin $(DISSECTOR_SRC) +!ELSE +plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg + @echo Making plugin.c (using sh) + @$(SH) ../../tools/make-dissector-reg . plugin $(DISSECTOR_SRC) +!ENDIF + +!ENDIF + +clean: + rm -f $(OBJECTS) $(RESOURCE) plugin.c *.pdb \ + $(PLUGIN_NAME).dll $(PLUGIN_NAME).dll.manifest $(PLUGIN_NAME).lib \ + $(PLUGIN_NAME).exp $(PLUGIN_NAME).rc + +distclean: clean + +maintainer-clean: distclean + +checkapi: + $(PERL) ../../tools/checkAPIs.pl -g abort -g termoutput $(DISSECTOR_SRC) $(DISSECTOR_INCLUDES) diff --git a/README b/README new file mode 100644 index 0000000..94b92e7 --- /dev/null +++ b/README @@ -0,0 +1,152 @@ +SAP Dissector Plugin for Wireshark + +Copyright (C) 2014 Core Security Technologies + +The plugin was designed and developed by Martin Gallo from the Security +Consulting Services team of Core Security Technologies. + +Version 0.1.4 (March 2014) + + +Overview: +======== + +SAP Netweaver [1] is a technology platform for building and integrating SAP +business applications. Communication between components uses different network +protocols. While some of them are standard and well-known protocols, other +are proprietaries and public information is not available. + +This plugin provides dissection on SAP's NI, Message Server, Router, Diag and +Enqueue protocols. The dissectors are based on information acquired at +researching the different protocols and services. Additional experimental +support is included for SAP's RFC and SNC protocols. Detailed information +about the research can be found at [2], [3], [4], [5] and [6]. + + +Features: +======== + +This plugin counts on several different dissectors: + +- SAP NI Protocol dissector + + This is the dissector for SAP's Network Interface (NI) protocol. The + dissector handles the reassemble of fragmented TCP packets and identifies + keep-alive messages (PING/PONG). It also calls the respective subdissector + according to the port being used. + +- SAP Router Protocol dissector + + This dissector includes support for the SAP Router protocol, handling route, + control messages and error information packets. The dissector also calls + the SNC subdissector when SNC frames are found. + +- SAP Diag Protocol dissector + + The main dissector of the plugin. It dissects the main headers used by the + Diag protocol: DP, Diag and Compression headers. The dissector also handles + decompression of the payload data and includes dissection of relevant Diag + payload items, including Support Bits and common APPL/APPL4 items. + Wireshark's expert information capabilities are used to remark malformed or + wrong packets. The dissector also calls the RFC subdissector when an + embedded RFC call is found and the SNC subdissector when SNC frames are + found. + +- SAP Message Server Protocol dissector + + This module dissects the packets used by SAP's Message Server Protocol. + +- SAP Enqueue Protocol dissector + + This module dissects packets used by SAP's Standalone Enqueue and + Replication Servers. + +- SAP RFC (Remote Function Call) Protocol dissector (experimental) + + This dissector perform some basic dissection on the main components of the + RFC protocol. It dissects general items and does some basic reassembling + and decompression of table contents. + +- SAP SNC (Secure Network Connection) Protocol dissector (experimental) + + This dissector perform some basic parsing of SNC frames. + + +Installation & Build: +==================== + +This wireshark plugin is not distributed as part of the Wireshark source. The +following steps are required to compile the plugin: + +1) Download Wireshark version 1.10 source from [7] or checkout the code from + the source repository [8]. + +2) Decompress the package. + +3) Run the auto configuration script (autogen.sh) and compile the source. + +4) Copy the SAP Wireshark Plugin to a new plugins/sap directory. + +5) Windows Build: Add plugins/sap directory to Makefile.nmake and + plugins/Makefile.am. + + Non-Windows Build: Add plugins/sap directory to Makefile.am, configure.in + and plugins/Makefile.am. + + This step can be done using the patch file provided. At the root directory + run: + + git apply plugins/sap/wireshark.patch + +6) Compile and install as described in Wireshark INSTALL file. + +It's worth mentioning that compression libraries for SAP Diag/RFC protocol are +originally written in C++, thus the entire plugin needs to be compiled for C++. +See Wireshark's portability notes for more information [9]. + + +Example uses: +============ + +SAP Diag Gui Logon Password filter: + +DYNT_ATOM items contains data entered into screen fields. The following filter +could be used for identify the packets with filled fields, in search for +interesting data. Early packets in a Diag session probably contains values for +fields username and password. + +sapdiag.item.value.dyntatom.item.type == 130 + + +The same results can be achieved also using expert info (security group): + +sapdiag and expert.group==security + + +License: +======= + +This wireshark plugin is distributed under the GPLv2 license. Check the COPYING +file for more details. + + +References: +========== + +[1] http://www.sap.com/platform/netweaver/index.epx +[2] http://corelabs.coresecurity.com/index.php?module=Wiki&action=view&type=tool&name=SAP_Dissection_plu-gin_for_Wireshark +[3] http://www.coresecurity.com/content/sap-netweaver-dispatcher-multiple-vulnerabilities +[4] http://www.coresecurity.com/content/SAP-netweaver-msg-srv-multiple-vulnerabilities +[5] http://corelabs.coresecurity.com/index.php?module=Wiki&action=view&type=publication&name=Uncovering_SAP_vulnerabilities +[6] http://corelabs.coresecurity.com/index.php?module=Wiki&action=view&type=publication&name=saps_network_protocols_revisited +[7] http://www.wireshark.org/download.html +[8] https://code.wireshark.org/review/wireshark +[9] https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=doc/README.developer;hb=refs/heads/master-1.10 + + +Contact: +======= + +Whether you want to report a bug or give some suggestions on this package, drop +us a few lines at oss@coresecurity.com or contact the author email +mgallo@coresecurity.com. diff --git a/hpa101saptype.h b/hpa101saptype.h new file mode 100644 index 0000000..3b861ef --- /dev/null +++ b/hpa101saptype.h @@ -0,0 +1,51 @@ +/* @(#) saptype.h 20.24 SAP 98/02/12 + + + ========== licence begin GPL + Copyright (c) 2000-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + +*/ +typedef char SAP_CHAR; +typedef unsigned char SAP_BYTE; /* Value range: 0 .. UCHAR_MAX */ +typedef short SAP_SHORT; /* Value range: SHRT_MIN .. SHRT_MAX */ +typedef unsigned short SAP_USHORT; /* Value range: */ +typedef int SAP_INT; /* Value range: */ +typedef unsigned int SAP_UINT; /* Value range: */ + + +/**********************************************************************/ +/* Min/max macros */ +/* To prevent compiler warnings the macros MAX and MIN now have the */ +/* same wording as those in /usr/include/sys/param.h. */ +/**********************************************************************/ +#ifndef MIN + #define MIN(a,b) (((a)<(b))?(a):(b)) +#endif + +#ifndef MAX + #define MAX(a,b) (((a)>(b))?(a):(b)) +#endif + +#define SAPonNT + +#define USE(param) ((param)=(param)) + + diff --git a/hpa104CsObject.h b/hpa104CsObject.h new file mode 100644 index 0000000..7165cdd --- /dev/null +++ b/hpa104CsObject.h @@ -0,0 +1,161 @@ +/* + + + + ========== licence begin GPL + Copyright (c) 2000-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + + +*/ +// CsObject.h: interface for the CsObject class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CSOBJECT_H__2AFFECE5_60FE_11D2_87FA_204C4F4F5020__INCLUDED_) +#define AFX_CSOBJECT_H__2AFFECE5_60FE_11D2_87FA_204C4F4F5020__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#ifndef NEAR +#ifdef SAPonWINDOWS +#define NEAR _near +#else +#define NEAR +#endif +#endif + + +/*--------------------------------------------------------------------*/ +/* Flags for CsCompr and CsDecompr */ +/*--------------------------------------------------------------------*/ +#define CS_LZH_VERSION 1 + +#define CS_LZH1 (1 << 4) +#define CS_LZH2 (2 << 4) +#define CS_LZH3 (3 << 4) +#define CS_LZH4 (4 << 4) +#define CS_LZH5 (5 << 4) +#define CS_LZH6 (6 << 4) +#define CS_LZH7 (7 << 4) +#define CS_LZH8 (8 << 4) +#define CS_LZH9 (9 << 4) + + +/* call flags for compression ........................................*/ +#define CS_NORMAL_COMPRESS 0x0 /* normal .....................*/ +#define CS_INIT_COMPRESS 0x1 /* first call CsCompr..........*/ +#define CS_INIT_DECOMPRESS 0x1 /* first call CsDeCompr........*/ + +#define CS_LZC 0x0 /* use lzc ....................*/ +#define CS_LZH 0x2 /* use lzh ....................*/ +#define CS_GRAPHIC_DATA 0x8 /* not supported now ..........*/ + +/* Header info in compressed file ....................................*/ +#define CS_ALGORITHM_LZC (SAP_BYTE) 1 +#define CS_ALGORITHM_LZH (SAP_BYTE) 2 + +#define CS_HEAD_SIZE 8 /* size of common header ......*/ + +/*--------------------------------------------------------------------*/ +/* Error & Return Codes for CsCompr and CsDecompr */ +/*--------------------------------------------------------------------*/ +#define CS_END_INBUFFER 3 /* End of input buffer ........*/ +#define CS_END_OUTBUFFER 2 /* End of output buffer .......*/ +#define CS_END_OF_STREAM 1 /* End of data ................*/ +#define CS_OK 0 + +#define CS_IEND_OF_STREAM -1 /* End of data (internal) .....*/ +#define CS_IEND_OUTBUFFER -2 /* End of output buffer .......*/ +#define CS_IEND_INBUFFER -3 /* End of input buffer ........*/ + +#define CS_ERROR -10 /* First Error Code ...........*/ +#define CS_E_OUT_BUFFER_LEN -10 /* Invalid output length ......*/ +#define CS_E_IN_BUFFER_LEN -11 /* Invalid input length .......*/ +#define CS_E_NOSAVINGS -12 +#define CS_E_INVALID_SUMLEN -13 /* Invalid len of stream ......*/ +#define CS_E_IN_EQU_OUT -14 /* inbuf == outbuf ............*/ +#define CS_E_INVALID_ADDR -15 /* inbuf == NULL,outbuf == NULL*/ +#define CS_E_FATAL -19 /* Internal Error ! ...........*/ +#define CS_E_BOTH_ZERO -20 /* inlen = outlen = 0 .........*/ +#define CS_E_UNKNOWN_ALG -21 /* unknown algorithm ..........*/ +#define CS_E_UNKNOWN_TYPE -22 + +/* for decompress */ +#define CS_E_FILENOTCOMPRESSED -50 /* Input not compressed .......*/ +#define CS_E_MAXBITS_TOO_BIG -51 /* maxbits to large ...........*/ +#define CS_E_BAD_HUF_TREE -52 /* bad hufman tree ..........*/ +#define CS_E_NO_STACKMEM -53 /* no stack memory in decomp ..*/ +#define CS_E_INVALIDCODE -54 /* invalid code ...............*/ +#define CS_E_BADLENGTH -55 /* bad lengths ................*/ + +#define CS_E_STACK_OVERFLOW -60 /* stack overflow in decomp */ +#define CS_E_STACK_UNDERFLOW -61 /* stack underflow in decomp */ + +/* only Windows */ +#define CS_NOT_INITIALIZED -71 /* storage not allocated ......*/ + + +/* Internal Implementation class */ +class CsObjectInt; + +class CsObject +{ +private: + CsObjectInt * Cs; + +public: + CsObject (); + virtual ~CsObject (); + + virtual int CsCompr (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written); + + virtual int CsDecompr (SAP_BYTE * inbuf, /* ptr input .......*/ + SAP_INT inlen, /* len of input ....*/ + SAP_BYTE * outbuf, /* ptr output ......*/ + SAP_INT outlen, /* len output ......*/ + SAP_INT option, /* decompr. option */ + SAP_INT * bytes_read, /* bytes read ......*/ + SAP_INT * bytes_decompressed); /* bytes decompr. */ + + virtual int CsGetAlgorithm (SAP_BYTE * data); + + virtual SAP_INT CsGetLen (SAP_BYTE * data); + virtual int CsGetVersion (SAP_BYTE * data); + + virtual int CsSetHead (SAP_BYTE * outbuf, + SAP_INT len, + SAP_BYTE veralg, + SAP_BYTE special); + + virtual int CsInitCompr (SAP_BYTE * outbuf, SAP_INT sumlen, SAP_INT option); + virtual int CsInitDecompr (SAP_BYTE * inbuf); +}; + +#endif // !defined(AFX_CSOBJECT_H__2AFFECE5_60FE_11D2_87FA_204C4F4F5020__INCLUDED_) diff --git a/hpa105CsObjInt.h b/hpa105CsObjInt.h new file mode 100644 index 0000000..75e8d9c --- /dev/null +++ b/hpa105CsObjInt.h @@ -0,0 +1,516 @@ +/* + + + + ========== licence begin GPL + Copyright (c) 2000-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + + +*/ +// CsObjectInt.h: interface for the CsObjectInt class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CSOBJECTINT_H__2AFFECE8_60FE_11D2_87FA_204C4F4F5020__INCLUDED_) +#define AFX_CSOBJECTINT_H__2AFFECE8_60FE_11D2_87FA_204C4F4F5020__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#define BUF_SIZE1 (sizeof(COUNT_INT) * HSIZE > 2*WSIZE ? \ + sizeof(COUNT_INT) * HSIZE : 2*WSIZE) + + +/* Not because of Windows 3.1X, but for Windows-Emulation on OS/2 -mt- */ +#ifdef SAPonWINDOWS +#define DUMMY_SIZE 32768U +#else + +#define DUMMY_SIZE (sizeof(HUFTREE) > 8 ? \ + sizeof(HUFTREE) * 0x1E00 : 0xF000) +#endif + +#define BUF_SIZE2 (sizeof(CODE_ENTRY) * CSIZE > DUMMY_SIZE ? \ + sizeof(CODE_ENTRY) * CSIZE : DUMMY_SIZE) + + +/* Constants .........................................................*/ + +#define DEFAULT_LZH_LEVEL 2 + +#define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ + +#define MAX_BL_BITS 7 /* Bit length codes must not exceed MAX_BL_BITS */ + +/* number of length codes, not counting the special END_BLOCK code */ +#define LENGTH_CODES 29 + +#define LITERALS 256 /* number of literal bytes 0..255 */ +#define END_BLOCK 256 /* end of block literal code */ + +/* number of Literal or Length codes, including the END_BLOCK code */ +#define L_CODES (LITERALS+1+LENGTH_CODES) + +#define D_CODES 30 /* number of distance codes */ +#define BL_CODES 19 /* no of codes used to transfer the bit lengths */ + +#define STATIC_TREES 1 +#define DYN_TREES 2 + +/* + * The current code is general and allows CS_DIST_BUFSIZE < CS_LIT_BUFSIZE (to save + * memory at the expense of compression). Some optimizations would be possible + * if we rely on CS_DIST_BUFSIZE == CS_LIT_BUFSIZE. + */ + +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ +#define REP_3_6 16 + +/* repeat a zero length 3-10 times (3 bits of repeat count) */ +#define REPZ_3_10 17 + +/* repeat a zero length 11-138 times (7 bits of repeat count) */ +#define REPZ_11_138 18 + +/* Local data ........................................................*/ + +/* Data structure describing a single value and its code string. */ +typedef struct CT_DATA +{ + union + { + unsigned short freq; /* frequency count */ + unsigned short code; /* bit string */ + } fc; + union + { + unsigned short dad; /* father node in Huffman tree */ + unsigned short len; /* length of bit string */ + } dl; +} CT_DATA; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +struct HUFT +{ + unsigned char e; /* number of extra bits or operation .........*/ + unsigned char b; /* number of bits in this code or subcode ....*/ + union + { + unsigned short n; /* literal, length base, or distance base ....*/ + struct HUFT *t; /* pointer to next level of table ............*/ + } v; +}; + +typedef struct HUFT HUFTREE; +#define DE_STACK_SIZE 0x1000 + +#define HEAP_SIZE (2*L_CODES+1) /* maximum heap size ......*/ + +typedef struct TREE_DESC +{ + CT_DATA *dyn_tree; /* the dynamic tree */ + CT_DATA *static_tree; /* corresponding static tree or NULL */ + int *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ + int max_code; /* largest code with non zero freq. */ +} TREE_DESC; + + + + +typedef struct CSH +{ + int init; + SAP_UINT sum_size; + SAP_UINT sum_in; + SAP_INT in_offset; + SAP_INT out_offset; + unsigned int bytes_pending; + SAP_INT BlockStart; + unsigned StrStart; + unsigned MatchStart; + int MatchAvail; + unsigned MatchLen; + unsigned ins_h; + int PrevLen; + + int eoInput; /* flag set at end of input ...........*/ + int eoData; /* flag set at end of data ............*/ + unsigned Lookahead; /* no of valid bytes ahead in window ..*/ + + int pack_level; /* index into config table ............*/ + CT_DATA dyn_ltree[HEAP_SIZE]; /* literal/len tree */ + CT_DATA dyn_dtree[2*D_CODES+1]; /* distance tree */ + +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree + * (see HufTabInit below). */ + + CT_DATA static_ltree[L_CODES+2]; + +/* The static distance tree. + * (Actually a trivial tree since all codes use 5 bits.) */ + + CT_DATA static_dtree[D_CODES]; + +/* Huffman tree for the bit lengths */ + CT_DATA bl_tree[2*BL_CODES+1]; /*Huffman tree for the bit lens*/ + + TREE_DESC l_desc; + + TREE_DESC d_desc; + + TREE_DESC bl_desc; + + SAP_BYTE window[(BUF_SIZE1)]; + SAP_BYTE InterBuf[(BUF_SIZE2)]; + + unsigned short bl_count[MAX_BITS+1]; + +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused + * bit length codes. */ + + +/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. + heap[0] is not used. The same heap array is used to build + all trees. */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + + +/* Depth of each subtree used as tie breaker for trees of equal freq. */ + unsigned short depth[2*L_CODES+1]; + +/* length code for each normalized match length (0 == MIN_MATCH) */ + unsigned short length_code[MAX_MATCH-MIN_MATCH+1]; + +/* distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. */ + + unsigned short dist_code[512]; + +/* First normalized length for each code (0 = MIN_MATCH) */ + int base_length[LENGTH_CODES]; + +/* First normalized distance for each code (0 = distance of 1) */ + int base_dist[D_CODES]; + +/* flag_buf is a bit array distinguishing literals from lengths in + CsLitLenBuf, and thus indicating the presence or absence + of a distance. */ + + unsigned short flag_buf[(CS_LIT_BUFSIZE/8)]; + + unsigned last_lit; /* running index in CsLitLenBuf */ + unsigned last_dist; /* running index in CsDistBuf */ + unsigned last_flags; /* running index in flag_buf */ + SAP_BYTE flags; /* current flags not yet in flag_buf */ + SAP_BYTE flag_bit; /* current bit used in flags */ + +/* bits are filled in flags starting at bit 0 (least significant). + * Note: these flags are overkill in the current code since we don't + * take advantage of CS_DIST_BUFSIZE == CS_LIT_BUFSIZE. */ + + SAP_UINT opt_len; /* bit len of block with optimal trees */ + SAP_UINT static_len; /* bit len of block with static trees */ + + unsigned bi_buf; + +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) */ + +/* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. */ + int bi_valid; + + +/* Current input and output buffers ..................................*/ + SAP_BYTE *in_buf, *out_buf; + +/* Size of current input and output buffers ..........................*/ + SAP_INT in_size, out_size; + + /* Link to older string with same hash index. + To limit the size of this array to 64K, this link is + maintained only for the last WSIZE strings. + An index in this array is thus a window index modulo WSIZE. */ + + unsigned short CsPrev[WSIZE]; + + /* Heads of the hash chains or NIL .................................*/ + unsigned short CsHead[CS_HASH_SIZE]; + + SAP_BYTE CsLitLenBuf[CS_LIT_BUFSIZE]; /* buffer for literals/lengths */ + unsigned short CsDistBuf[CS_DIST_BUFSIZE]; /* buffer for distances */ + +} CSH; + + + +typedef struct CSHU +{ + SAP_BYTE *OutPtr; + SAP_UINT SumOut; + + SAP_BYTE *MemOutbuffer, *MemInbuffer; + unsigned MemOutoffset, MemOutsize, MemInoffset, MemInsize; + unsigned BytesPending, SlideOffset; + unsigned wp; + + SAP_UINT bb; /* bit buffer ............*/ + unsigned bk; /* bits in bit buffer ....*/ + + SAP_UINT bytebuf; + unsigned AllocStackSize; + + HUFTREE *htp; /* pointer to table entry */ + unsigned save_n, save_d, save_e; + + int lastblockflag; /* last block flag ....................*/ + int staterun; /* state of last run ..................*/ + int NonSenseflag; + SAP_INT OrgLen; + unsigned blocktype; /* block type */ + + HUFTREE *tlitlen; /* literal/length code table */ + HUFTREE *tdistcode; /* distance code table */ + int blitlen; /* lookup bits for tl */ + int bdistlen; /* lookup bits for td */ + + int dd_ii; + unsigned dd_jj; + unsigned dd_lastlen; /* last length */ + unsigned dd_maskbit; /* mask for bit lengths table */ + unsigned dd_nolen; /* number of lengths to get */ + HUFTREE *dd_tl; /* literal/length code table */ + HUFTREE *dd_td; /* distance code table */ + int dd_bl; /* lookup bits for tl */ + int dd_bd; /* lookup bits for td */ + unsigned dd_nb; /* number of bit length codes */ + unsigned dd_nl; /* number of literal/length codes */ + unsigned dd_nd; /* number of distance codes */ + unsigned dd_ll[286+30]; /* literal/length and distance lengths */ + SAP_BYTE Slide[(BUF_SIZE1)]; + HUFTREE InterBuf[DE_STACK_SIZE]; +} CSHU; + + +typedef struct CSC +{ + int n_bits; /* number of bits/code ............*/ + int maxbits; /* user settable max # bits/code ..*/ + CODE_INT maxcode; /* maximum code, given n_bits .....*/ + + /* storage for GETCODE / PUTCODE ..*/ + BYTE_TYP buf1[MAX_CS_BITS]; + + int cs_offset; + int csc_offset; + int put_n_bytes; + + BYTE_TYP *outptr; + BYTE_TYP *end_outbuf; + + /* should never be generated ......*/ + CODE_INT maxmaxcode; /* = (CODE_INT)1 << CS_BITS; */ + + COUNT_INT LARGE_ARRAY htab [HSIZE]; /* hash table ........*/ + CODE_ENTRY LARGE_ARRAY codetab [CSIZE]; /* code table ........*/ + CODE_ENTRY Prefixtab[(BUF_SIZE1)/4]; // = (CODE_ENTRY *) &CsDeWindowBuf[0]; + BYTE_TYP Suffixtab[(BUF_SIZE2)/4]; // = (BYTE_TYP *) &CsDeInterBuf[0]; + CODE_INT hsize; // = HSIZE; /* for dynamic table sizing .......*/ + + + CODE_INT free_ent; /* first unused entry ..........*/ + long int bytes_out; /* length of compressed output .*/ + long int rest_len; /* rest bytes to decompress ....*/ + int block_compress; /* block compression ...........*/ + int clear_flg; /* clear hash table ............*/ + long int ratio; /* compression ratio ...........*/ + COUNT_INT checkpoint; /* ratio check point for compr. */ + +/* states for get_code ...............................................*/ + int get_size, get_r_bits; + + BYTE_TYP * in_ptr; /* global input ptr ............*/ + BYTE_TYP * end_inbuf; /* end of input buffer .........*/ + BYTE_TYP *stack_end; + + int hshift; + CODE_INT ent; + int sflush; + long org_len; + long in_count_sum; + + + BYTE_TYP *sstackp; // = (BYTE_TYP *) 0; + long dorg_len; + CODE_INT scode, soldcode, sincode, sfinchar; + int restart; + +} CSC; + + +class CsObjectInt +{ +public: + CsObjectInt (); + ~CsObjectInt (); + + int CsCompr (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written); + + int CsDecompr (SAP_BYTE * inbuf, /* ptr input .......*/ + SAP_INT inlen, /* len of input ....*/ + SAP_BYTE * outbuf, /* ptr output ......*/ + SAP_INT outlen, /* len output ......*/ + SAP_INT option, /* decompr. option */ + SAP_INT * bytes_read, /* bytes read ......*/ + SAP_INT * bytes_decompressed); /* bytes decompr. */ + + int CsGetAlgorithm (SAP_BYTE * data); + + SAP_INT CsGetLen (SAP_BYTE * data); + int CsGetVersion (SAP_BYTE * data); + int CsSetHead (SAP_BYTE * outbuf, + SAP_INT len, + SAP_BYTE veralg, + SAP_BYTE special); + int CsInitCompr (SAP_BYTE * outbuf, SAP_INT sumlen, SAP_INT option); + int CsInitDecompr (SAP_BYTE * inbuf); + +private: + int algorithm; + + int CsDecomprLZH (SAP_BYTE * inp, /* ptr input .......*/ + SAP_INT inlen, /* len of input ....*/ + SAP_BYTE * outp, /* ptr output ......*/ + SAP_INT outlen, /* len output ......*/ + SAP_INT option, /* decompr. option */ + SAP_INT * bytes_read, /* bytes read ......*/ + SAP_INT * bytes_decompressed); /* bytes decompr. */ + + int CsComprLZH (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written); + + union + { + CSHU cshu; + CSH csh; + CSC csc; + }; + +/* decompress functions in csulzh.cpp */ + int BuildHufTree (unsigned *, unsigned, unsigned, int *, int *, + HUFTREE **, int *); + HUFTREE * AllocHufTree (unsigned size); + int FlushOut (unsigned); + int DecompCodes (int * state, HUFTREE *, HUFTREE *, int, int); + int DecompFixed (int *state); + int DecompDynamic (int *state); + void NoBits (void); + int DecompBlock (int *state, int * x); + void SendBits (unsigned value, int len); + +/* compress functions in cslzh.cpp */ + + void HashInit (void); + void LongestMatchInit (int level, SAP_BYTE *flags); + int LongestMatch (unsigned cur_match); + void FillWindow (void); + int MemRead (SAP_BYTE *buf, unsigned size); + SAP_INT ComprLZH (unsigned opt); + + int ct_tally (int dist, int lc); + void FlushBlock (int eof); + void HufTabInit (void); + + void InitBlock (void); + void pqdownheap (CT_DATA *tree, int k); + void GenBitLen (TREE_DESC *desc); + void GenCodes (CT_DATA *tree, int max_code); + void BuildTree (TREE_DESC *desc); + void ScanTree (CT_DATA *tree, int max_code); + void SendTree (CT_DATA *tree, int max_code); + int BuildBlTree (void); + void SendAllTrees (int lcodes, int dcodes, int blcodes); + void CompressBlock (CT_DATA *ltree, CT_DATA *dtree); + void BitBufInit (void); + void FlushIncomp (void); + unsigned short ReverseCode (unsigned code, int len); + void InitDesc (void); + + /* cslzc.cpp */ + int InitComp (BYTE_TYP * outbuf, + SAP_INT outlen, + SAP_INT sumlen); + + int ClearBlock (SAP_INT in_count, SAP_INT bytes_out); + CODE_INT GetCode (void); + int PutCode (CODE_INT c); + SAP_INT CsGetStorageSize (void); + + int CsComprLZC (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written); + + int CsDecomprLZC (SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written); + +}; + + + +#endif // !defined(AFX_CSOBJECTINT_H__2AFFECE8_60FE_11D2_87FA_204C4F4F5020__INCLUDED_) diff --git a/hpa106cslzc.h b/hpa106cslzc.h new file mode 100644 index 0000000..c287385 --- /dev/null +++ b/hpa106cslzc.h @@ -0,0 +1,200 @@ +/*@(#)cslzc.h 20.8 SAP 97/11/11 + + + ========== licence begin GPL + Copyright (c) 1992-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + +*/ + +/* + * SAP AG Walldorf + * Systeme, Anwendungen und Produkte in der Datenverarbeitung + * + */ + +/*--------------------------------------------------------------------*/ +/* Internal Header File */ +/* */ +/* Definitions for LZC Algorithm */ +/* */ +/*--------------------------------------------------------------------*/ + +#ifndef CSLZC_INCL /* cannot be included twice .................*/ +#define CSLZC_INCL + +/*--------------------------------------------------------------------*/ +/* Macros (internal) */ +/*--------------------------------------------------------------------*/ + /* for 16 Bit OS ................*/ +#if defined ( OS_16 ) +#define LARGE_ARRAY far +#else +#define LARGE_ARRAY +#endif + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef CS_BITS +#define CS_BITS 13 /* max. number of bits (default) ......*/ +#endif + +/* If a new version is added, change CS_VERSION + */ + +#define CS_VERSION (BYTE_TYP) 1 + +#define CS_ALGORITHM (BYTE_TYP) 1 /* never change this ..........*/ + + +#define FIRST 257 /* first free entry ...................*/ +#define CLEAR 256 /* table clear output code ............*/ + /* ratio check interval ...............*/ +#define CHECK_GAP 4096 /* 10000 */ + +/* Defines for 8. byte of header .....................................*/ +#define BIT_MASK 0x1f +#define BLOCK_MASK 0x80 + +/* Masks 0x40 and 0x20 are free. */ + +#define INIT_CS_BITS 9 /* initial number of bits/code ........*/ +#define MAX_CS_BITS 16 /* max. number of bits/code ...........*/ + +#if CS_BITS <= INIT_CS_BITS /* CS_BITS at least INIT_CS_BITS + 1 ..*/ +#undef CS_BITS +#define CS_BITS (INIT_CS_BITS + 1) +#endif + +#if CS_BITS > MAX_CS_BITS /* CS_BITS at most MAX_CS_BITS ........*/ +#undef CS_BITS +#define CS_BITS MAX_CS_BITS +#endif + +/*--------------------------------------------------------------------*/ +/* TYPES (depending on CS_BITS) */ +/*--------------------------------------------------------------------*/ + +typedef SAP_BYTE BYTE_TYP; + +#if CS_BITS > 15 +typedef long int CODE_INT; +#else +typedef int CODE_INT; +#endif + +typedef long int COUNT_INT; +typedef unsigned short CODE_ENTRY; + +/*--------------------------------------------------------------------*/ +/* Size of the hash table depending on CS_BITS .......................*/ +/*--------------------------------------------------------------------*/ + +#if CS_BITS == 16 +#define HSIZE 69001U /* 95% occupancy 65536/69001 .........*/ +#define CSIZE 69001U +#endif +#if CS_BITS == 15 +#define HSIZE 35023U /* 94% occupancy 32768/35023 .........*/ +#define CSIZE 69001U +#endif +#if CS_BITS == 14 +#define HSIZE 18013U /* 91% occupancy 16384/18013 .........*/ +#define CSIZE 35023U +#endif +#if CS_BITS == 13 +#define HSIZE 9001U /* 91% occupancy 8192/9001 .........*/ +#define CSIZE 18013U +#endif +#if CS_BITS <= 12 +#define HSIZE 5003U /* 80% occupancy 4096/5003 .........*/ +#define CSIZE 9001U +#endif + +/*--------------------------------------------------------------------*/ +/* Access Macros for code and hash tables ............................*/ +/*--------------------------------------------------------------------*/ + +#define MAXCODE(n_bits) (((CODE_INT) 1 << (n_bits)) - 1) +#define HTABOF(i) csc.htab[i] +#define CODETABOF(i) csc.codetab[i] + +/* + * To save much memory, we overlay the table used by CsCompr () with + * those used by CsDecompr (). The TAB_PREFIX table is the same size + * and type as the codetab. The TAB_SUFFIX table needs 2^BITS + * characters. We get this from the beginning of htab. + * The output stack uses the rest of htab, and contains characters. + * There is plenty of room for any possible stack (stack used to + * be 8000 characters). + */ + +#define TAB_PREFIXOF(i) csc.Prefixtab[i] +#define TAB_SUFFIXOF(i) csc.Suffixtab[i] + +/* following definition gives a compiler warning on HP 64 bit (2001-05-15) + Maybe this will work again some time later. + +#define DE_STACK &TAB_SUFFIXOF((CODE_INT)1<<(CS_BITS+1)) + + Definition beneath works on HP, too, but requires an extra global var. +*/ + +extern CODE_INT DE_STACK_OFFSET; +#define DE_STACK &TAB_SUFFIXOF(DE_STACK_OFFSET) + +/* Clear Hash Table ..................................................*/ +#define CL_HASH(size) \ + memset (csc.htab, 0xff, (size) * sizeof (COUNT_INT)); + + +#ifdef USE_MEMCPY /* use memcpy to transfer bytes ..........*/ + +#define BYTES_OUT(dst,src,len) \ + memcpy (dst,src,len); dst += len; + +#define BYTES_IN(to,from,len) \ + memcpy (to,from,len); from += len; + +#else /* native copy ...........................*/ + +#define BYTES_OUT(dst,src,len) \ + { \ + register int i_i = len; \ + register BYTE_TYP *bufp = src; \ + while (i_i-- > 0) *dst++ = *bufp++; \ + } + +#define BYTES_IN(to,from,len) \ + { \ + register int i_i = len; \ + register BYTE_TYP *bufp = to; \ + while (i_i-- > 0) *bufp++ = *from++; \ + } + +#endif /* USE_MEMCPY */ + +#endif /* CSLZC_INCL */ diff --git a/hpa107cslzh.h b/hpa107cslzh.h new file mode 100644 index 0000000..65d677e --- /dev/null +++ b/hpa107cslzh.h @@ -0,0 +1,90 @@ +/*@(#)cslzh.h 20.7 SAP 97/11/11 + + + ========== licence begin GPL + Copyright (c) 1994-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + +*/ + +/* + * SAP AG Walldorf + * Systeme, Anwendungen und Produkte in der Datenverarbeitung + * + */ + +/*--------------------------------------------------------------------*/ +/* Internal Header File */ +/* */ +/* Definitions for LZH Algorithm */ +/* Lempel-Ziv-Huffman */ +/*--------------------------------------------------------------------*/ + +#ifndef CSLZH_INCL /* cannot be included twice .................*/ +#define CSLZH_INCL + +#define REGISTER register + +/* The minimum and maximum match lengths .............................*/ +#define MIN_MATCH 3 +#define MAX_MATCH 258 + +/* Minimum amount of lookahead, except at the end of the input file ..*/ +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) + +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. ...............*/ +#define MAX_DIST (WSIZE-MIN_LOOKAHEAD) + +#define NONSENSE_LENBITS 2 + +#define EODATA (-1) + +/* Maximum window size = 32K (must be a power of 2) ..................*/ +#define WSIZE ((unsigned) 0x4000) /* 16K */ + +#define CS_HASH_BITS 14 + +#define CS_HASH_SIZE (unsigned)(1 << CS_HASH_BITS) + +#define CS_LIT_BUFSIZE (unsigned) 0x4000 /* 16K */ +#define CS_DIST_BUFSIZE CS_LIT_BUFSIZE + +#define HASH_MASK (CS_HASH_SIZE-1) +#define WMASK (WSIZE-1) + +/* Configuration parameters ..........................................*/ +/* speed options for the general purpose bit flag */ +#define FAST_PA107 4 +#define SLOW_PA107 0 + +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR*/ +#ifndef TOO_FAR +#define TOO_FAR 4096 +#endif + +/* Types centralized here for easy modification ......................*/ +typedef SAP_BYTE uch; /* unsigned 8-bit value ................*/ +typedef SAP_USHORT ush; /* unsigned 16-bit value ................*/ +typedef SAP_UINT ulg; /* unsigned 32-bit value ................*/ + + +#endif /* CSLZH_INCL */ + diff --git a/moduleinfo.h b/moduleinfo.h new file mode 100644 index 0000000..d19de33 --- /dev/null +++ b/moduleinfo.h @@ -0,0 +1,17 @@ +/* Included *after* config.h, in order to re-define these macros */ + +#ifdef PACKAGE +#undef PACKAGE +#endif + +/* Name of package */ +#define PACKAGE "sap" + + +#ifdef VERSION +#undef VERSION +#endif + +/* Version number of package */ +#define VERSION "0.1.4" + diff --git a/moduleinfo.nmake b/moduleinfo.nmake new file mode 100644 index 0000000..d7474c4 --- /dev/null +++ b/moduleinfo.nmake @@ -0,0 +1,28 @@ +# +# $Id: moduleinfo.nmake 20161 2006-12-19 22:24:40Z jake $ +# + +# The name +PACKAGE=sap + +# The version +MODULE_VERSION_MAJOR=0 +MODULE_VERSION_MINOR=1 +MODULE_VERSION_MICRO=4 +MODULE_VERSION_EXTRA=0 + +# +# The RC_VERSION should be comma-separated, not dot-separated, +# as per Graham Bloice's message in +# +# http://www.ethereal.com/lists/ethereal-dev/200303/msg00283.html +# +# "The RC_VERSION variable in config.nmake should be comma separated. +# This allows the resources to be built correctly and the version +# number to be correctly displayed in the explorer properties dialog +# for the executables, and XP's tooltip, rather than 0.0.0.0." +# + +MODULE_VERSION=$(MODULE_VERSION_MAJOR).$(MODULE_VERSION_MINOR).$(MODULE_VERSION_MICRO).$(MODULE_VERSION_EXTRA) +RC_MODULE_VERSION=$(MODULE_VERSION_MAJOR),$(MODULE_VERSION_MINOR),$(MODULE_VERSION_MICRO),$(MODULE_VERSION_EXTRA) + diff --git a/packet-sapdiag.c b/packet-sapdiag.c new file mode 100644 index 0000000..8aacdb8 --- /dev/null +++ b/packet-sapdiag.c @@ -0,0 +1,3428 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include +#include +#include + +/* Common helpers for adding items */ +#include "saphelpers.h" + +/* SAP Decompression routine */ +#include "sapdecompress.h" + +/* Define default ports. It could be 3200-3299, but 3298 it's usually + * used for the niping tool and 3299 is associated to SAP Router. */ +#define SAPDIAG_PORT_RANGE "3200-3297" + +/* SAP Diag Header Communication Flag values */ +#define SAPDIAG_COM_FLAG_TERM_EOS 0x01 +#define SAPDIAG_COM_FLAG_TERM_EOC 0x02 +#define SAPDIAG_COM_FLAG_TERM_NOP 0x04 +#define SAPDIAG_COM_FLAG_TERM_EOP 0x08 +#define SAPDIAG_COM_FLAG_TERM_INI 0x10 +#define SAPDIAG_COM_FLAG_TERM_CAS 0x20 +#define SAPDIAG_COM_FLAG_TERM_NNM 0x40 +#define SAPDIAG_COM_FLAG_TERM_GRA 0x80 + +/* SAP Diag Header Compression field values */ +static const value_string hf_sapdiag_compress_vals[] = { + { 0x0, "Compression switched off" }, + { 0x1, "Compression switched on" }, + { 0x2, "Data encrypted" }, + { 0x3, "????" } +}; + +/* SAP Diag Header Algorithm field values */ +static const value_string hf_sapdiag_algorithm_vals[] = { + { 0x10, "LZC" }, + { 0x12, "LZH" }, + /* NULL */ + { 0x0, NULL } +}; + + +/* SAP Diag DP Header Request ID values */ +static const value_string hf_sapdiag_dp_request_id_vals[] = { + { 0x00000000, "NOWP" }, + { 0x00000001, "DIA" }, + { 0x00000002, "DUPD" }, + { 0x00000003, "DENQ" }, + { 0x00000004, "DBTC" }, + { 0x00000005, "DSPO" }, + { 0x00000006, "DUP2" }, + /* NULL */ + { 0, NULL} +}; + +/* SAP Diag DP Header Sender ID values */ +static const value_string hf_sapdiag_dp_sender_id_vals[] = { + { 0x01, "DISPATCHER" }, + { 0x02, "WORK_PROCESS" }, + { 0x04, "REMOTE_TERMINAL" }, + { 0x20, "APPC_TERMINAL" }, + { 0x40, "APPC_GATEWAY" }, + { 0xC8, "ICMAN" }, + { 0xC9, "IC_MONITOR" }, + { 0xCB, "LCOM" }, + /* NULL */ + { 0, NULL} +}; + +/* SAP Diag DP Header Action Type values */ +static const value_string hf_sapdiag_dp_action_type_vals[] = { + { 0x01, "SEND_TO_DP" }, + { 0x02, "SEND_TO_WP" }, + { 0x03, "SEND_TO_TM" }, + { 0x04, "SEND_TO_APPC" }, + { 0x05, "SEND_TO_APPCTM" }, + { 0x06, "SEND_MSG_TYPE" }, + { 0x07, "SEND_MSG_REQUES" }, + { 0x08, "SEND_MSG_REPLY" }, + { 0x09, "SEND_MSG_ONEWAY" }, + { 0x0A, "SEND_MSG_ADMIN" }, + { 0x0B, "WAKE_UP_WPS" }, + { 0x0C, "SET_TIMEOUT" }, + { 0x0D, "DEL_SCHEDULE" }, + { 0x0E, "ADD_SOFT_SERV" }, + { 0x0F, "SUB_SOFT_SERV" }, + { 0x10, "SHUTDOWN" }, + { 0x11, "SEND_TO_MSGSERV" }, + { 0x12, "SEND_TO_PLUGIN" }, + /* NULL */ + { 0, NULL} +}; + +/* SAP Diag DP Header Request Info Flag constants */ +#define SAPDIAG_DP_REQ_INFO_UNDEFINED 0x00 +#define SAPDIAG_DP_REQ_INFO_LOGIN 0x01 +#define SAPDIAG_DP_REQ_INFO_LOGOFF 0x02 +#define SAPDIAG_DP_REQ_INFO_SHUTDOWN 0x04 +#define SAPDIAG_DP_REQ_INFO_GRAPHIC_TM 0x08 +#define SAPDIAG_DP_REQ_INFO_ALPHA_TM 0x10 +#define SAPDIAG_DP_REQ_INFO_ERROR_FROM_APPC 0x20 +#define SAPDIAG_DP_REQ_INFO_CANCELMODE 0x40 +#define SAPDIAG_DP_REQ_INFO_MSG_WITH_REQ_BUF 0x80 + +#define SAPDIAG_DP_REQ_INFO_MSG_WITH_OH 0x01 +#define SAPDIAG_DP_REQ_INFO_BUFFER_REFRESH 0x02 +#define SAPDIAG_DP_REQ_INFO_BTC_SCHEDULER 0x04 +#define SAPDIAG_DP_REQ_INFO_APPC_SERVER_DOWN 0x08 +#define SAPDIAG_DP_REQ_INFO_MS_ERROR 0x10 +#define SAPDIAG_DP_REQ_INFO_SET_SYSTEM_USER 0x20 +#define SAPDIAG_DP_REQ_INFO_DP_CANT_HANDLE_REQ 0x40 +#define SAPDIAG_DP_REQ_INFO_DP_AUTO_ABAP 0x80 + +#define SAPDIAG_DP_REQ_INFO_DP_APPL_SERV_INFO 0x01 +#define SAPDIAG_DP_REQ_INFO_DP_ADMIN 0x02 +#define SAPDIAG_DP_REQ_INFO_DP_SPOOL_ALRM 0x04 +#define SAPDIAG_DP_REQ_INFO_DP_HAND_SHAKE 0x08 +#define SAPDIAG_DP_REQ_INFO_DP_CANCEL_PRIV 0x10 +#define SAPDIAG_DP_REQ_INFO_DP_RAISE_TIMEOUT 0x20 +#define SAPDIAG_DP_REQ_INFO_DP_NEW_MODE 0x40 +#define SAPDIAG_DP_REQ_INFO_DP_SOFT_CANCEL 0x80 + +#define SAPDIAG_DP_REQ_INFO_DP_TM_INPUT 0x01 +#define SAPDIAG_DP_REQ_INFO_DP_TM_OUTPUT 0x02 +#define SAPDIAG_DP_REQ_INFO_DP_ASYNC_RFC 0x04 +#define SAPDIAG_DP_REQ_INFO_DP_ICM_EVENT 0x08 +#define SAPDIAG_DP_REQ_INFO_DP_AUTO_TH 0x10 +#define SAPDIAG_DP_REQ_INFO_DP_RFC_CANCEL 0x20 +#define SAPDIAG_DP_REQ_INFO_DP_MS_ADM 0x40 + +/* SAP Diag Support Bits */ +#define SAPDIAG_SUPPORT_BIT_PROGRESS_INDICATOR 0x01 // 0 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_LABELS 0x02 // 1 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_DIAGVERSION 0x04 // 2 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_SELECT_RECT 0x08 // 3 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_SYMBOL_RIGHT 0x10 // 4 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_FONT_METRIC 0x20 // 5 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_COMPR_ENHANCED 0x40 // 6 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_IMODE 0x80 // 7 + +#define SAPDIAG_SUPPORT_BIT_SAPGUI_LONG_MESSAGE 0x01 // 8 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_TABLE 0x02 // 9 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_FOCUS_1 0x04 // 10 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_PUSHBUTTON_1 0x08 // 11 +#define SAPDIAG_SUPPORT_BIT_UPPERCASE 0x10 // 12 +#define SAPDIAG_SUPPORT_BIT_SAPGUI_TABPROPERTY 0x20 // 13 +#define SAPDIAG_SUPPORT_BIT_INPUT_UPPERCASE 0x40 // 14 +#define SAPDIAG_SUPPORT_BIT_RFC_DIALOG 0x80 // 15 + +#define SAPDIAG_SUPPORT_BIT_LIST_HOTSPOT 0x01 // 16 +#define SAPDIAG_SUPPORT_BIT_FKEY_TABLE 0x02 // 17 +#define SAPDIAG_SUPPORT_BIT_MENU_SHORTCUT 0x04 // 18 +#define SAPDIAG_SUPPORT_BIT_STOP_TRANS 0x08 // 19 +#define SAPDIAG_SUPPORT_BIT_FULL_MENU 0x10 // 20 +#define SAPDIAG_SUPPORT_BIT_OBJECT_NAMES 0x20 // 21 +#define SAPDIAG_SUPPORT_BIT_CONTAINER_TYPE 0x40 // 22 +#define SAPDIAG_SUPPORT_BIT_DLGH_FLAGS 0x80 // 23 + +#define SAPDIAG_SUPPORT_BIT_APPL_MNU 0x01 // 24 +#define SAPDIAG_SUPPORT_BIT_MESSAGE_INFO 0x02 // 25 +#define SAPDIAG_SUPPORT_BIT_MESDUM_FLAG1 0x04 // 26 +#define SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB 0x08 // 27 +#define SAPDIAG_SUPPORT_BIT_GUIAPI 0x10 // 28 +#define SAPDIAG_SUPPORT_BIT_NOGRAPH 0x20 // 29 +#define SAPDIAG_SUPPORT_BIT_NOMESSAGES 0x40 // 30 +#define SAPDIAG_SUPPORT_BIT_NORABAX 0x80 // 31 + +#define SAPDIAG_SUPPORT_BIT_NOSYSMSG 0x01 // 32 +#define SAPDIAG_SUPPORT_BIT_NOSAPSCRIPT 0x02 // 33 +#define SAPDIAG_SUPPORT_BIT_NORFC 0x04 // 34 +#define SAPDIAG_SUPPORT_BIT_NEW_BSD_JUSTRIGHT 0x08 // 35 +#define SAPDIAG_SUPPORT_BIT_MESSAGE_VARS 0x10 // 36 +#define SAPDIAG_SUPPORT_BIT_OCX_SUPPORT 0x20 // 37 +#define SAPDIAG_SUPPORT_BIT_SCROLL_INFOS 0x40 // 38 +#define SAPDIAG_SUPPORT_BIT_TABLE_SIZE_OK 0x80 // 39 + +#define SAPDIAG_SUPPORT_BIT_MESSAGE_INFO2 0x01 // 40 +#define SAPDIAG_SUPPORT_BIT_VARINFO_OKCODE 0x02 // 41 +#define SAPDIAG_SUPPORT_BIT_CURR_TCODE 0x04 // 42 +#define SAPDIAG_SUPPORT_BIT_CONN_WSIZE 0x08 // 43 +#define SAPDIAG_SUPPORT_BIT_PUSHBUTTON_2 0x10 // 44 +#define SAPDIAG_SUPPORT_BIT_TABSTRIP 0x20 // 45 +#define SAPDIAG_SUPPORT_BIT_UNKNOWN_1 0x40 // 46 (Unknown support bit) +#define SAPDIAG_SUPPORT_BIT_TABSCROLL_INFOS 0x80 // 47 + +#define SAPDIAG_SUPPORT_BIT_TABLE_FIELD_NAMES 0x01 // 48 +#define SAPDIAG_SUPPORT_BIT_NEW_MODE_REQUEST 0x02 // 49 +#define SAPDIAG_SUPPORT_BIT_RFCBLOB_DIAG_PARSER 0x04 // 50 +#define SAPDIAG_SUPPORT_BIT_MULTI_LOGIN_USER 0x08 // 51 +#define SAPDIAG_SUPPORT_BIT_CONTROL_CONTAINER 0x10 // 52 +#define SAPDIAG_SUPPORT_BIT_APPTOOLBAR_FIXED 0x20 // 53 +#define SAPDIAG_SUPPORT_BIT_R3INFO_USER_CHECKED 0x40 // 54 +#define SAPDIAG_SUPPORT_BIT_NEED_STDDYNPRO 0x80 // 55 + +#define SAPDIAG_SUPPORT_BIT_TYPE_SERVER 0x01 // 56 +#define SAPDIAG_SUPPORT_BIT_COMBOBOX 0x02 // 57 +#define SAPDIAG_SUPPORT_BIT_INPUT_REQUIRED 0x04 // 58 +#define SAPDIAG_SUPPORT_BIT_ISO_LANGUAGE 0x08 // 59 +#define SAPDIAG_SUPPORT_BIT_COMBOBOX_TABLE 0x10 // 60 +#define SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS 0x20 // 61 +#define SAPDIAG_SUPPORT_BIT_CHECKRADIO_EVENTS 0x40 // 62 +#define SAPDIAG_SUPPORT_BIT_R3INFO_USERID 0x80 // 63 + +#define SAPDIAG_SUPPORT_BIT_R3INFO_ROLLCOUNT 0x01 // 64 +#define SAPDIAG_SUPPORT_BIT_USER_TURNTIME2 0x02 // 65 +#define SAPDIAG_SUPPORT_BIT_NUM_FIELD 0x04 // 66 +#define SAPDIAG_SUPPORT_BIT_WIN16 0x08 // 67 +#define SAPDIAG_SUPPORT_BIT_CONTEXT_MENU 0x10 // 68 +#define SAPDIAG_SUPPORT_BIT_SCROLLABLE_TABSTRIP_PAGE 0x20 // 69 +#define SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION 0x40 // 70 +#define SAPDIAG_SUPPORT_BIT_LABEL_OWNER 0x80 // 71 + +#define SAPDIAG_SUPPORT_BIT_CLICKABLE_FIELD 0x01 // 72 +#define SAPDIAG_SUPPORT_BIT_PROPERTY_BAG 0x02 // 73 +#define SAPDIAG_SUPPORT_BIT_UNUSED_1 0x04 // 74 +#define SAPDIAG_SUPPORT_BIT_TABLE_ROW_REFERENCES_2 0x08 // 75 +#define SAPDIAG_SUPPORT_BIT_PROPFONT_VALID 0x10 // 76 +#define SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER 0x20 // 77 +#define SAPDIAG_SUPPORT_BIT_R3INFO_IMODEUUID 0x40 // 78 +#define SAPDIAG_SUPPORT_BIT_NOTGUI 0x80 // 79 + +#define SAPDIAG_SUPPORT_BIT_WAN 0x01 // 80 +#define SAPDIAG_SUPPORT_BIT_XML_BLOBS 0x02 // 81 +#define SAPDIAG_SUPPORT_BIT_RFC_QUEUE 0x04 // 82 +#define SAPDIAG_SUPPORT_BIT_RFC_COMPRESS 0x08 // 83 +#define SAPDIAG_SUPPORT_BIT_JAVA_BEANS 0x10 // 84 +#define SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND 0x20 // 85 +#define SAPDIAG_SUPPORT_BIT_CTL_PROPCACHE 0x40 // 86 +#define SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID 0x80 // 87 + +#define SAPDIAG_SUPPORT_BIT_RFC_ASYNC_BLOB 0x01 // 88 +#define SAPDIAG_SUPPORT_BIT_KEEP_SCROLLPOS 0x02 // 89 +#define SAPDIAG_SUPPORT_BIT_UNUSED_2 0x04 // 90 +#define SAPDIAG_SUPPORT_BIT_UNUSED_3 0x08 // 91 +#define SAPDIAG_SUPPORT_BIT_XML_PROPERTIES 0x10 // 92 +#define SAPDIAG_SUPPORT_BIT_UNUSED_4 0x20 // 93 +#define SAPDIAG_SUPPORT_BIT_HEX_FIELD 0x40 // 94 +#define SAPDIAG_SUPPORT_BIT_HAS_CACHE 0x80 // 95 + +#define SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE 0x01 // 96 +#define SAPDIAG_SUPPORT_BIT_UNUSED_5 0x02 // 97 +#define SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID2 0x04 // 98 +#define SAPDIAG_SUPPORT_BIT_ITS 0x08 // 99 +#define SAPDIAG_SUPPORT_BIT_NO_EASYACCESS 0x10 // 100 +#define SAPDIAG_SUPPORT_BIT_PROPERTYPUMP 0x20 // 101 +#define SAPDIAG_SUPPORT_BIT_COOKIE 0x40 // 102 +#define SAPDIAG_SUPPORT_BIT_UNUSED_6 0x80 // 103 + +#define SAPDIAG_SUPPORT_BIT_SUPPBIT_AREA_SIZE 0x01 // 104 +#define SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND_WRITE 0x02 // 105 +#define SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS 0x04 // 106 +#define SAPDIAG_SUPPORT_BIT_ENTRY_HISTORY 0x08 // 107 +#define SAPDIAG_SUPPORT_BIT_AUTO_CODEPAGE 0x10 // 108 +#define SAPDIAG_SUPPORT_BIT_CACHED_VSETS 0x20 // 109 +#define SAPDIAG_SUPPORT_BIT_EMERGENCY_REPAIR 0x40 // 110 +#define SAPDIAG_SUPPORT_BIT_AREA2FRONT 0x80 // 111 + +#define SAPDIAG_SUPPORT_BIT_SCROLLBAR_WIDTH 0x01 // 112 +#define SAPDIAG_SUPPORT_BIT_AUTORESIZE 0x02 // 113 +#define SAPDIAG_SUPPORT_BIT_EDIT_VARLEN 0x04 // 114 +#define SAPDIAG_SUPPORT_BIT_WORKPLACE 0x08 // 115 +#define SAPDIAG_SUPPORT_BIT_PRINTDATA 0x10 // 116 +#define SAPDIAG_SUPPORT_BIT_UNKNOWN_2 0x20 // 117 (Unknown support bit) +#define SAPDIAG_SUPPORT_BIT_SINGLE_SESSION 0x40 // 118 +#define SAPDIAG_SUPPORT_BIT_NOTIFY_NEWMODE 0x80 // 119 + +#define SAPDIAG_SUPPORT_BIT_TOOLBAR_HEIGHT 0x01 // 120 +#define SAPDIAG_SUPPORT_BIT_XMLPROP_CONTAINER 0x02 // 121 +#define SAPDIAG_SUPPORT_BIT_XMLPROP_DYNPRO 0x04 // 122 +#define SAPDIAG_SUPPORT_BIT_DP_HTTP_PUT 0x08 // 123 +#define SAPDIAG_SUPPORT_BIT_DYNAMIC_PASSPORT 0x10 // 124 +#define SAPDIAG_SUPPORT_BIT_WEBGUI 0x20 // 125 +#define SAPDIAG_SUPPORT_BIT_WEBGUI_HELPMODE 0x40 // 126 +#define SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST 0x80 // 127 + +#define SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_2 0x01 // 128 +#define SAPDIAG_SUPPORT_BIT_EOKDUMMY_1 0x02 // 129 +#define SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING 0x04 // 130 +#define SAPDIAG_SUPPORT_BIT_SLC 0x08 // 131 +#define SAPDIAG_SUPPORT_BIT_ACCESSIBILITY 0x10 // 132 +#define SAPDIAG_SUPPORT_BIT_ECATT 0x20 // 133 +#define SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID3 0x40 // 134 +#define SAPDIAG_SUPPORT_BIT_ENABLE_UTF8 0x80 // 135 + +#define SAPDIAG_SUPPORT_BIT_R3INFO_AUTOLOGOUT_TIME 0x01 // 136 +#define SAPDIAG_SUPPORT_BIT_VARINFO_ICON_TITLE_LIST 0x02 // 137 +#define SAPDIAG_SUPPORT_BIT_ENABLE_UTF16BE 0x04 // 138 +#define SAPDIAG_SUPPORT_BIT_ENABLE_UTF16LE 0x08 // 139 +#define SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP 0x10 // 140 +#define SAPDIAG_SUPPORT_BIT_ENABLE_APPL4 0x20 // 141 +#define SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL 0x40 // 142 +#define SAPDIAG_SUPPORT_BIT_CBURBU_NEW_STATE 0x80 // 143 + +#define SAPDIAG_SUPPORT_BIT_BINARY_EVENTID 0x01 // 144 +#define SAPDIAG_SUPPORT_BIT_GUI_THEME 0x02 // 145 +#define SAPDIAG_SUPPORT_BIT_TOP_WINDOW 0x04 // 146 +#define SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION_1 0x08 // 147 +#define SAPDIAG_SUPPORT_BIT_SPLITTER 0x10 // 148 +#define SAPDIAG_SUPPORT_BIT_VALUE_4_HISTORY 0x20 // 149 +#define SAPDIAG_SUPPORT_BIT_ACC_LIST 0x40 // 150 +#define SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING_INFO 0x80 // 151 + +#define SAPDIAG_SUPPORT_BIT_TEXTEDIT_STREAM 0x01 // 152 +#define SAPDIAG_SUPPORT_BIT_DYNT_NOFOCUS 0x02 // 153 +#define SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP_1 0x04 // 154 +#define SAPDIAG_SUPPORT_BIT_FRAME_1 0x08 // 155 +#define SAPDIAG_SUPPORT_BIT_TICKET4GUI 0x10 // 156 +#define SAPDIAG_SUPPORT_BIT_ACC_LIST_PROPS 0x20 // 157 +#define SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB_INPUT 0x40 // 158 +#define SAPDIAG_SUPPORT_BIT_DEFAULT_TOOLTIP 0x80 // 159 + +#define SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE_2 0x01 // 160 +#define SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_3 0x02 // 161 +#define SAPDIAG_SUPPORT_BIT_CELLINFO 0x04 // 162 +#define SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST_2 0x08 // 163 +#define SAPDIAG_SUPPORT_BIT_TABLE_COLUMNWIDTH_INPUT 0x10 // 164 +#define SAPDIAG_SUPPORT_BIT_ITS_PLUGIN 0x20 // 165 +#define SAPDIAG_SUPPORT_BIT_OBJECT_NAMES_4_LOGIN_PROCESS 0x40 // 166 +#define SAPDIAG_SUPPORT_BIT_RFC_SERVER_4_GUI 0x80 // 167 + +#define SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS_2 0x01 // 168 +#define SAPDIAG_SUPPORT_BIT_RCUI 0x02 // 169 +#define SAPDIAG_SUPPORT_BIT_MENUENTRY_WITH_FCODE 0x04 // 170 +#define SAPDIAG_SUPPORT_BIT_WEBSAPCONSOLE 0x08 // 171 +#define SAPDIAG_SUPPORT_BIT_R3INFO_KERNEL_VERSION 0x10 // 172 +#define SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_LOOP 0x20 // 173 +#define SAPDIAG_SUPPORT_BIT_EOKDUMMY_2 0x40 // 174 +#define SAPDIAG_SUPPORT_BIT_MESSAGE_INFO3 0x80 // 175 + +#define SAPDIAG_SUPPORT_BIT_SBA2 0x01 // 176 +#define SAPDIAG_SUPPORT_BIT_MAINAREA_SIZE 0x02 // 177 +#define SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL_2 0x04 // 178 +#define SAPDIAG_SUPPORT_BIT_DISPLAY_SIZE 0x08 // 179 +#define SAPDIAG_SUPPORT_BIT_GUI_PACKET 0x10 // 180 +#define SAPDIAG_SUPPORT_BIT_DIALOG_STEP_NUMBER 0x20 // 181 +#define SAPDIAG_SUPPORT_BIT_TC_KEEP_SCROLL_POSITION 0x40 // 182 +#define SAPDIAG_SUPPORT_BIT_MESSAGE_SERVICE_REQUEST 0x80 // 183 + +#define SAPDIAG_SUPPORT_BIT_DYNT_FOCUS_FRAME 0x01 // 184 +#define SAPDIAG_SUPPORT_BIT_MAX_STRING_LEN 0x02 // 185 +#define SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_1 0x04 // 186 +#define SAPDIAG_SUPPORT_BIT_STD_TOOLBAR_ITEMS 0x08 // 187 +#define SAPDIAG_SUPPORT_BIT_XMLPROP_LIST_DYNPRO 0x10 // 188 +#define SAPDIAG_SUPPORT_BIT_TRACE_GUI_CONNECT 0x20 // 189 +#define SAPDIAG_SUPPORT_BIT_LIST_FULLWIDTH 0x40 // 190 +#define SAPDIAG_SUPPORT_BIT_ALLWAYS_SEND_CLIENT 0x80 // 191 + +#define SAPDIAG_SUPPORT_BIT_UNKNOWN_3 0x01 // 192 (Unknown support bit) +#define SAPDIAG_SUPPORT_BIT_GUI_SIGNATURE_COLOR 0x02 // 193 +#define SAPDIAG_SUPPORT_BIT_MAX_WSIZE 0x04 // 194 + + +/* SAP Diag DP Header New Status values */ +static const value_string hf_sapdiag_dp_new_stat_vals[] = { + { 0x00, "NO_CHANGE" }, + { 0x01, "WP_SLOT_FREE" }, + { 0x02, "WP_WAIT" }, + { 0x04, "WP_RUN" }, + { 0x08, "WP_HOLD" }, + { 0x10, "WP_KILLED" }, + { 0x20, "WP_SHUTDOWN" }, + { 0x40, "WP_RESTRICTED" }, + { 0x80, "WP_NEW" } +}; + +/* SAP Diag Item Type values */ +static const value_string hf_sapdiag_item_type_vals[] = { + { 0x01, "SES" }, + { 0x02, "ICO" }, + { 0x03, "TIT" }, + { 0x07, "DiagMessage (old format)" }, + { 0x08, "OKC" }, + { 0x09, "CHL" }, + { 0x0b, "SBA/SFE/SLC" }, + { 0x0c, "EOM" }, + { 0x10, "APPL" }, + { 0x11, "DIAG_XMLBLOB" }, + { 0x12, "APPL4" }, + { 0x15, "SBA2" }, + /* NULL */ + { 0, NULL } +}; + +/* SAP Diag Item APPL/APPL4 ID values */ +static const value_string hf_sapdiag_item_id_vals[] = { + { 0x01, "SCRIPT" }, + { 0x02, "GRAPH" }, + { 0x03, "IXOS" }, + { 0x04, "ST_USER" }, + { 0x05, "DYNN" }, + { 0x06, "ST_R3INFO" }, + { 0x07, "POPU" }, + { 0x08, "RFC_TR" }, + { 0x09, "DYNT" }, + { 0x0a, "CONTAINER" }, + { 0x0b, "MNUENTRY" }, + { 0x0c, "VARINFO" }, + { 0x0e, "CONTROL" }, + { 0x0f, "UI_EVENT" }, + { 0x12, "ACC_LIST" }, + { 0x13, "RCUI" }, + { 0x14, "GUI_PACKET" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 SCRIPT SID values */ +static const value_string hf_sapdiag_item_appl_script_vals[] = { + /* SCRIPT */ + { 0x01, "SCRIPT_OTF" }, + { 0x02, "SCRIPT_SCREEN" }, + { 0x03, "SCRIPT_POSTSCRIPT" }, + { 0x04, "SCRIPT_ITF" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 GRAPH SID values */ +static const value_string hf_sapdiag_item_appl_graph_vals[] = { + /* GRAPH */ + { 0x03, "GRAPH RELEASE 3" }, + { 0x05, "GRAPH RELEASE 5" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 IXOS SID values */ +static const value_string hf_sapdiag_item_appl_ixos_vals[] = { + /* IXOS */ + { 0x01, "ABLAGE" }, + { 0x02, "ANZEIGE" }, + { 0x03, "IXOS_COMMAND" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 ST_USER SID values */ +static const value_string hf_sapdiag_item_appl_st_user_vals[] = { + /* ST_USER */ + { 0x01, "V1" }, + { 0x02, "CONNECT" }, + { 0x03, "SELECTEDRECT" }, + { 0x04, "FONTMETRIC" }, + { 0x05, "TABLEMETRIC" }, + { 0x06, "GUITIME" }, + { 0x07, "GUITIMEZONE" }, + { 0x08, "TURNTIME" }, + { 0x09, "GUIVERSION" }, + { 0x0b, "SUPPORTDATA" }, + { 0x0c, "RFC_CONNECT" }, + { 0x0d, "WSIZE" }, + { 0x0e, "V2" }, + { 0x0f, "TURNTIME2" }, + { 0x10, "RFC_PARENT_UUID" }, + { 0x11, "RFC_NEW_UUID" }, + { 0x12, "RFC_UUIDS" }, + { 0x13, "RFC_UUIDS2" }, + { 0x14, "XML_LOGIN" }, + { 0x15, "XML_TRANSACTION" }, + { 0x16, "SCROLLBAR_WIDTH" }, + { 0x17, "TOOLBAR_HEIGHT" }, + { 0x18, "PASSPORT_DATA" }, + { 0x19, "GUI_STATE" }, + { 0x1a, "DECIMALPOINT" }, + { 0x1b, "LANGUAGE" }, + { 0x1c, "USERNAME" }, + { 0x1d, "GUIPATCHLEVEL" }, + { 0x1e, "WSIZE_PIXEL" }, + { 0x1f, "GUI_OS_VERSION" }, + { 0x20, "BROWSER_VERSION" }, + { 0x21, "OFFICE_VERSION" }, + { 0x22, "JDK_VERSION" }, + { 0x23, "GUIXT_VERSION" }, + { 0x24, "DISPLAY_SIZE" }, + { 0x25, "GUI_TYPE" }, + { 0x26, "DIALOG_STEP_NUMBER" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 SYNN SID values */ +static const value_string hf_sapdiag_item_appl_dynn_vals[] = { + /* DYNN */ + { 0x01, "CHL" }, + { 0x03, "XMLPROP DYNPRO" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 ST_R3INFO SID values */ +static const value_string hf_sapdiag_item_appl_st_r3info_vals[] = { + /* ST_R3INFO */ + { 0x01, "MODENUMBER" }, + { 0x02, "DBNAME" }, + { 0x03, "CPUNAME" }, + { 0x04, "RFC_TRIGGER" }, + { 0x05, "GUI_LABEL" }, + { 0x06, "DIAGVERSION" }, + { 0x07, "TCODE" }, + { 0x08, "RFC_WAITING" }, + { 0x09, "RFC_REFRESH" }, + { 0x0a, "IMODENUMBER" }, + { 0x0b, "MESSAGE" }, + { 0x0c, "CLIENT" }, + { 0x0d, "DYNPRONAME" }, + { 0x0e, "DYNPRONUMBER" }, + { 0x0f, "CUANAME" }, + { 0x10, "CUASTATUS" }, + { 0x11, "SUPPORTDATA" }, + { 0x12, "RFC_CONNECT_OK" }, + { 0x13, "GUI_FKEY" }, + { 0x14, "GUI_FKEYT" }, + { 0x15, "STOP_TRANS" }, + { 0x16, "RFC_DIAG_BLOCK_SIZE" }, + { 0x17, "USER_CHECKED" }, + { 0x18, "FLAGS" }, + { 0x19, "USERID" }, + { 0x1a, "ROLLCOUNT" }, + { 0x1b, "GUI_XT_VAR" }, + { 0x1c, "IMODEUUID" }, + { 0x1d, "IMODEUUID_INVALIDATE" }, + { 0x1e, "IMODEUUIDS" }, + { 0x1f, "IMODEUUIDS2" }, + { 0x20, "CODEPAGE" }, + { 0x21, "CONTEXTID" }, + { 0x22, "AUTOLOGOUT_TIME" }, + { 0x23, "CODEPAGE_DIAG_GUI" }, + { 0x24, "CODEPAGE_APP_SERVER" }, + { 0x25, "GUI_THEME" }, + { 0x26, "GUI_USER_SCRIPTING" }, + { 0x27, "CODEPAGE_APP_SERVER_1" }, + { 0x28, "TICKET4GUI" }, + { 0x29, "KERNEL_VERSION" }, + { 0x2a, "STD_TOOLBAR_ITEMS" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 POPU SID values */ +static const value_string hf_sapdiag_item_appl_popu_vals[] = { + /* POPU */ + { 0x02, "DEST" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 RFC_TR SID values */ +static const value_string hf_sapdiag_item_appl_rfc_tr_vals[] = { + /* RFC_TR */ + { 0x00, "RFC_TR_REQ" }, + { 0x01, "RFC_TR_RET" }, + { 0x02, "RFC_TR_ERR" }, + { 0x03, "RFC_TR_RQT" }, + { 0x04, "RFC_TR_MOR" }, + { 0x05, "RFC_TR_MOB" }, + { 0x06, "RFC_TR_RNB" }, + { 0x07, "RFC_TR_RNT" }, + { 0x08, "RFC_TR_DIS" }, + { 0x09, "RFC_TR_CALL" }, + { 0x0a, "RFC_TR_CALL_END" }, + { 0x0b, "RFC_TR_RES" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 DYNT SID values */ +static const value_string hf_sapdiag_item_appl_dynt_vals[] = { + /* DYNT */ + { 0x01, "DYNT_FOCUS" }, + { 0x02, "DYNT_ATOM" }, + { 0x03, "DYNT_EVENT_UNUSED" }, + { 0x04, "TABLE_ROW_REFERENCE" }, + { 0x05, "TABLE_ROW_DAT_INPUT_DUMMY" }, + { 0x06, "TABLE_INPUT_HEADER" }, + { 0x07, "TABLE_OUTPUT_HEADER" }, + { 0x08, "TABLE_ROW_DATA_INPUT" }, + { 0x09, "TABLE_ROW_DATA_OUTPUT" }, + { 0x0a, "DYNT_NOFOCUS" }, + { 0x0b, "DYNT_FOCUS_1" }, + { 0x0c, "TABLE_ROW_REFERENCE_1" }, + { 0x0d, "TABLE_FIELD_NAMES" }, + { 0x0e, "TABLE_HEADER" }, + { 0x0f, "DYNT_TABSTRIP_HEADER" }, + { 0x10, "DYNT_TABSTRIP_BUTTONS" }, + { 0x11, "TABLE_ROW_REFERENCE_2" }, + { 0x12, "DYNT_CONTROL_FOCUS" }, + { 0x13, "TABLE_FIELD_XMLPROP" }, + { 0x14, "DYNT_SPLITTER_HEADER" }, + { 0x15, "DYNT_TC_COLUMN_TITLE_XMLP" }, + { 0x16, "DYNT_TC_ROW_SELECTOR_NAME" }, + { 0x17, "DYNT_FOCUS_FRAME" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 CONTAINER SID values */ +static const value_string hf_sapdiag_item_appl_container_vals[] = { + /* CONTAINTER */ + { 0x01, "RESET" }, + { 0x02, "DEFAULT" }, + { 0x03, "SUBSCREEN" }, + { 0x04, "LOOP" }, + { 0x05, "TABLE" }, + { 0x06, "NAME" }, + { 0x08, "TABSTRIP" }, + { 0x09, "TABSTRIP_PAGE" }, + { 0x0a, "CONTROL" }, + { 0x0c, "XMLPROP" }, + { 0x0d, "SPLITTER" }, + { 0x0e, "SPLITTER_CELL" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 MNUENTRY SID values */ +static const value_string hf_sapdiag_item_appl_mnuentry_vals[] = { + /* MNUENTRY */ + { 0x01, "MENU_ACT" }, + { 0x02, "MENU_MNU" }, + { 0x03, "MENU_PFK" }, + { 0x04, "MENU_KYB" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 VARINFO SID values */ +static const value_string hf_sapdiag_item_appl_varinfo_vals[] = { + /* VARINFO */ + { 0x01, "MESTYPE" }, + { 0x02, "SCROLL_INFOS" }, + { 0x03, "MESTYPE2" }, + { 0x04, "OKCODE" }, + { 0x05, "CONTAINER" }, + { 0x06, "SCROLL_INFOS2" }, + { 0x07, "AREASIZE" }, + { 0x08, "AREA_PIXELSIZE" }, + { 0x09, "SESSION_TITLE" }, + { 0x0a, "SESSION_ICON" }, + { 0x0b, "LIST_CELL_TEXT" }, + { 0x0c, "CONTAINER_LOOP" }, + { 0x0d, "LIST_FOCUS" }, + { 0x0e, "MAINAREA_PIXELSIZE" }, + { 0x0f, "SERVICE_REQUEST" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 CONTROl SID values */ +static const value_string hf_sapdiag_item_appl_control_vals[] = { + /* CONTROL */ + { 0x01, "CONTROL_PROPERTIES" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 UI_EVENT SID values */ +static const value_string hf_sapdiag_item_appl_ui_event_vals[] = { + /* UI_EVENT */ + { 0x01, "UI_EVENT_SOURCE" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 ACC_LIST SID values */ +static const value_string hf_sapdiag_item_appl_acc_list_vals[] = { + /* ACC_LIST */ + { 0x01, "ACC_LIST_INFO4FIELD" }, + { 0x02, "ACC_LIST_CONTAINER" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 RCUI SID values */ +static const value_string hf_sapdiag_item_appl_rcui_vals[] = { + /* RCUI */ + { 0x01, "RCUI_STREAM" }, + { 0x02, "RCUI_SYSTEM_ERROR" }, + { 0x03, "RCUI_SPAGPA" }, + { 0x04, "RCUI_MEMORYID" }, + { 0x05, "RCUI_TXOPTION" }, + { 0x06, "RCUI_VALUE" }, + { 0x07, "RCUI_COMMAND" }, + { 0x08, "RCUI_BDCMSG" }, + { 0x09, "RCUI_CONNECT_DATA" }, + { 0x00, NULL } +}; + +/* SAP Diag Item APPL/APPL4 GUI_PACKET SID values */ +static const value_string hf_sapdiag_item_appl_gui_packet_vals[] = { + /* GUI_PACKET */ + { 0x01, "GUI_PACKET_STATE" }, + { 0x02, "GUI_PACKET_DATA" }, + { 0x00, NULL } +}; + +/* SAP Diag Dynt Atom Etype values */ +static const value_string hf_sapdiag_item_dynt_atom_item_etype_vals[] = { + { 101, "DIAG_DGOTYP_EFIELD" }, + { 102, "DIAG_DGOTYP_OFIELD" }, + { 103, "DIAG_DGOTYP_KEYWORD" }, + { 104, "DIAG_DGOTYP_CHECKBUTTON_4" }, + { 105, "DIAG_DGOTYP_RADIOBUTTON_0" }, + { 106, "DIAG_DGOTYP_PUSHBUTTON_3" }, + { 107, "DIAG_DGOTYP_FRAME_3" }, + { 108, "DIAG_DGOTYP_LOOP_6" }, + { 109, "DIAG_DGOTYP_SUBSCREEN" }, + { 111, "DIAG_DGOTYP_PROPERTY" }, + { 112, "DIAG_DGOTYP_ICON_0" }, + { 113, "DIAG_DGOTYP_PUSHBUTTON_1" }, + { 114, "DIAG_DGOTYP_FNAME" }, + { 115, "DIAG_DGOTYP_PUSHBUTTON_2" }, + { 116, "DIAG_DGOTYP_TABSTRIP_BUTTON" }, + { 117, "DIAG_DGOTYP_COMBOBOX" }, + { 118, "DIAG_DGOTYP_CHECKBUTTON_1" }, + { 119, "DIAG_DGOTYP_RADIOBUTTON_1" }, + { 120, "DIAG_DGOTYP_XMLPROP" }, + { 121, "DIAG_DGOTYP_EFIELD_1" }, + { 122, "DIAG_DGOTYP_OFIELD_1" }, + { 123, "DIAG_DGOTYP_KEYWORD_1_1" }, + { 124, "DIAG_DGOTYP_CHECKBUTTON_2" }, + { 125, "DIAG_DGOTYP_RADIOBUTTON__0" }, + { 126, "DIAG_DGOTYP_COMBOBOX_1" }, + { 127, "DIAG_DGOTYP_FRAME_1" }, + { 128, "DIAG_DGOTYP_CHECKBUTTON_3" }, + { 129, "DIAG_DGOTYP_RADIOBUTTON_3" }, + { 130, "DIAG_DGOTYP_EFIELD_2" }, + { 131, "DIAG_DGOTYP_OFIELD_2" }, + { 132, "DIAG_DGOTYP_KEYWORD_2" }, + { 000, NULL } +}; + +/* SAP Diag UI Event Source Event Type Values */ +static const value_string ht_sapdiag_item_ui_event_event_type_vals[] = { + { 0x01, "SELECT" }, + { 0x02, "HE" }, + { 0x03, "VALUEHELP" }, + { 0x06, "RESIZE" }, + { 0x07, "FUNCTIONKEY" }, + { 0x08, "SCROLL" }, + { 0x09, "BUTTONPRESSED" }, + { 0x0a, "VALUECHANGED" }, + { 0x0b, "STATECHANGED" }, + { 0x0c, "NAVIGATION" }, + { 0, NULL } +}; + +static const value_string ht_sapdiag_item_ui_event_control_type_vals[] = { + { 0x00, "NONE" }, + { 0x01, "FIELD" }, + { 0x02, "RADIOBUTTON" }, + { 0x03, "CHECKBUTTON" }, + { 0x04, "MENUBUTTON" }, + { 0x05, "TOOLBARBUTTON" }, + { 0x06, "STANDARDTOOLBARBUTTON" }, + { 0x07, "PUSHBUTTON" }, + { 0x08, "TABLEVIEW" }, + { 0x09, "TABSTRIP" }, + { 0x0a, "DYNPRO" }, + { 0x0b, "CUSTOM_CONTROL" }, + { 0x0d, "FRAME" }, + { 0x0e, "TABLEVIEW_COLSEL_BUTTON" }, + { 0x0f, "TABLEVIEW_ROWSEL_BUTTON" }, + { 0x10, "TABLEVIEW_CELL" }, + { 0x11, "CONTEXTMENU" }, + { 0x12, "SPLITTER" }, + { 0x13, "MESSAGE" }, + { 0x14, "OKCODE" }, + { 0x15, "ACC_CONTAINER" } +}; + +static const value_string ht_sapdiag_item_ui_event_navigation_data_vals[] = { + { 0x01, "TAB" }, + { 0x02, "TAB_BACK" }, + { 0x03, "JUMP_OVER" }, + { 0x04, "JUMP_OVER_BACK" }, + { 0x05, "JUMP_OUT" }, + { 0x06, "JUMP_OUT_BACK" }, + { 0x07, "JUMP_SECTION" }, + { 0x08, "JUMP_SECTION_BACK" }, + { 0x09, "FIRST_FIELD" }, + { 0x0a, "LAST_FIELD" }, + { 0, NULL } +}; + +/* SAP Diag Dynt Atom Attr flags */ +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_PROTECTED 0x01 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_INVISIBLE 0x02 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_INTENSIFY 0x04 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_JUSTRIGHT 0x08 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_MATCHCODE 0x10 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_PROPFONT 0x20 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_YES3D 0x40 +#define SAPDIAG_ATOM_ATTR_DIAG_BSD_COMBOSTYLE 0x80 + +/* SAP Diag UI Event Source flags */ +#define SAPDIAG_UI_EVENT_VALID_FLAG_MENU_POS 0x01 +#define SAPDIAG_UI_EVENT_VALID_FLAG_CONTROL_POS 0x02 +#define SAPDIAG_UI_EVENT_VALID_FLAG_NAVIGATION_DATA 0x04 +#define SAPDIAG_UI_EVENT_VALID_FLAG_FUNCTIONKEY_DATA 0x08 + +static int proto_sapdiag = -1; + +static int hf_sapdiag_dp = -1; +static int hf_sapdiag_header = -1; +static int hf_sapdiag_payload = -1; + +/* Diag Header */ +static int hf_sapdiag_mode = -1; +static int hf_sapdiag_com_flag = -1; +static int hf_sapdiag_com_flag_TERM_EOS = -1; +static int hf_sapdiag_com_flag_TERM_EOC = -1; +static int hf_sapdiag_com_flag_TERM_NOP = -1; +static int hf_sapdiag_com_flag_TERM_EOP = -1; +static int hf_sapdiag_com_flag_TERM_INI = -1; +static int hf_sapdiag_com_flag_TERM_CAS = -1; +static int hf_sapdiag_com_flag_TERM_NNM = -1; +static int hf_sapdiag_com_flag_TERM_GRA = -1; + +static int hf_sapdiag_mode_stat = -1; +static int hf_sapdiag_err_flag = -1; +static int hf_sapdiag_msg_type = -1; +static int hf_sapdiag_msg_info = -1; +static int hf_sapdiag_msg_rc = -1; +static int hf_sapdiag_compress = -1; + +/* Compression header */ +static int hf_sapdiag_compress_header = -1; +static int hf_sapdiag_uncomplength = -1; +static int hf_sapdiag_algorithm = -1; +static int hf_sapdiag_magic = -1; +static int hf_sapdiag_special = -1; +static int hf_sapdiag_decompress_return_code = -1; + +/* Message Data */ +static int hf_sapdiag_item = -1; +static int hf_sapdiag_item_type = -1; +static int hf_sapdiag_item_id = -1; +static int hf_sapdiag_item_sid = -1; +static int hf_sapdiag_item_length = -1; +static int hf_sapdiag_item_value = -1; + +/* Message DP Header */ +static int hf_sapdiag_dp_request_id = -1; +static int hf_sapdiag_dp_retcode = -1; +static int hf_sapdiag_dp_sender_id = -1; +static int hf_sapdiag_dp_action_type = -1; +static int hf_sapdiag_dp_req_info = -1; + +static int hf_sapdiag_dp_req_info_LOGIN = -1; +static int hf_sapdiag_dp_req_info_LOGOFF = -1; +static int hf_sapdiag_dp_req_info_SHUTDOWN = -1; +static int hf_sapdiag_dp_req_info_GRAPHIC_TM = -1; +static int hf_sapdiag_dp_req_info_ALPHA_TM = -1; +static int hf_sapdiag_dp_req_info_ERROR_FROM_APPC = -1; +static int hf_sapdiag_dp_req_info_CANCELMODE = -1; +static int hf_sapdiag_dp_req_info_MSG_WITH_REQ_BUF = -1; +static int hf_sapdiag_dp_req_info_MSG_WITH_OH = -1; +static int hf_sapdiag_dp_req_info_BUFFER_REFRESH = -1; +static int hf_sapdiag_dp_req_info_BTC_SCHEDULER = -1; +static int hf_sapdiag_dp_req_info_APPC_SERVER_DOWN = -1; +static int hf_sapdiag_dp_req_info_MS_ERROR = -1; +static int hf_sapdiag_dp_req_info_SET_SYSTEM_USER = -1; +static int hf_sapdiag_dp_req_info_DP_CANT_HANDLE_REQ = -1; +static int hf_sapdiag_dp_req_info_DP_AUTO_ABAP = -1; +static int hf_sapdiag_dp_req_info_DP_APPL_SERV_INFO = -1; +static int hf_sapdiag_dp_req_info_DP_ADMIN = -1; +static int hf_sapdiag_dp_req_info_DP_SPOOL_ALRM = -1; +static int hf_sapdiag_dp_req_info_DP_HAND_SHAKE = -1; +static int hf_sapdiag_dp_req_info_DP_CANCEL_PRIV = -1; +static int hf_sapdiag_dp_req_info_DP_RAISE_TIMEOUT = -1; +static int hf_sapdiag_dp_req_info_DP_NEW_MODE = -1; +static int hf_sapdiag_dp_req_info_DP_SOFT_CANCEL = -1; +static int hf_sapdiag_dp_req_info_DP_TM_INPUT = -1; +static int hf_sapdiag_dp_req_info_DP_TM_OUTPUT = -1; +static int hf_sapdiag_dp_req_info_DP_ASYNC_RFC = -1; +static int hf_sapdiag_dp_req_info_DP_ICM_EVENT = -1; +static int hf_sapdiag_dp_req_info_DP_AUTO_TH = -1; +static int hf_sapdiag_dp_req_info_DP_RFC_CANCEL = -1; +static int hf_sapdiag_dp_req_info_DP_MS_ADM = -1; + +static int hf_sapdiag_dp_tid = -1; +static int hf_sapdiag_dp_uid = -1; +static int hf_sapdiag_dp_mode = -1; +static int hf_sapdiag_dp_wp_id = -1; +static int hf_sapdiag_dp_wp_ca_blk = -1; +static int hf_sapdiag_dp_appc_ca_blk = -1; +static int hf_sapdiag_dp_len = -1; /* Length of the SAP Diag Items in the login */ +static int hf_sapdiag_dp_new_stat = -1; +static int hf_sapdiag_dp_rq_id = -1; +static int hf_sapdiag_dp_terminal = -1; + +/* Dynt Atom */ +static int hf_sapdiag_item_dynt_atom = -1; +static int hf_sapdiag_item_dynt_atom_item = -1; +static int hf_sapdiag_item_dynt_atom_item_etype = -1; +static int hf_sapdiag_item_dynt_atom_item_attr = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_COMBOSTYLE = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_YES3D = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_PROPFONT = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_MATCHCODE = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_JUSTRIGHT = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_INTENSIFY = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_INVISIBLE = -1; +static int hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_PROTECTED = -1; + +/* UI Event Source */ +static int ht_sapdiag_item_ui_event_event_type = -1; +static int ht_sapdiag_item_ui_event_control_type = -1; +static int ht_sapdiag_item_ui_event_valid = -1; +static int ht_sapdiag_item_ui_event_valid_MENU_POS = -1; +static int ht_sapdiag_item_ui_event_valid_CONTROL_POS = -1; +static int ht_sapdiag_item_ui_event_valid_NAVIGATION_DATA = -1; +static int ht_sapdiag_item_ui_event_valid_FUNCTIONKEY_DATA = -1; +static int ht_sapdiag_item_ui_event_control_row = -1; +static int ht_sapdiag_item_ui_event_control_col = -1; +static int ht_sapdiag_item_ui_event_data = -1; +static int ht_sapdiag_item_ui_event_navigation_data = -1; +static int ht_sapdiag_item_ui_event_container_nrs = -1; +static int ht_sapdiag_item_ui_event_container = -1; + +/* Menu Entries */ +static int hf_sapdiag_item_menu_entry = -1; + +/* Diag Support Bits */ +static int hf_SAPDIAG_SUPPORT_BIT_PROGRESS_INDICATOR = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_LABELS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_DIAGVERSION = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_SELECT_RECT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_SYMBOL_RIGHT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_FONT_METRIC = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_COMPR_ENHANCED = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_IMODE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_LONG_MESSAGE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_TABLE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_FOCUS_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_PUSHBUTTON_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UPPERCASE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SAPGUI_TABPROPERTY = -1; +static int hf_SAPDIAG_SUPPORT_BIT_INPUT_UPPERCASE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RFC_DIALOG = -1; +static int hf_SAPDIAG_SUPPORT_BIT_LIST_HOTSPOT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_FKEY_TABLE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MENU_SHORTCUT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_STOP_TRANS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_FULL_MENU = -1; +static int hf_SAPDIAG_SUPPORT_BIT_OBJECT_NAMES = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONTAINER_TYPE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DLGH_FLAGS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_APPL_MNU = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MESDUM_FLAG1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUIAPI = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NOGRAPH = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NOMESSAGES = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NORABAX = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NOSYSMSG = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NOSAPSCRIPT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NORFC = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NEW_BSD_JUSTRIGHT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MESSAGE_VARS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_OCX_SUPPORT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SCROLL_INFOS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABLE_SIZE_OK = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_VARINFO_OKCODE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CURR_TCODE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONN_WSIZE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_PUSHBUTTON_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABSTRIP = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABSCROLL_INFOS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABLE_FIELD_NAMES = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NEW_MODE_REQUEST = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RFCBLOB_DIAG_PARSER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MULTI_LOGIN_USER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONTROL_CONTAINER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_APPTOOLBAR_FIXED = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_USER_CHECKED = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NEED_STDDYNPRO = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TYPE_SERVER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_COMBOBOX = -1; +static int hf_SAPDIAG_SUPPORT_BIT_INPUT_REQUIRED = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ISO_LANGUAGE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_COMBOBOX_TABLE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CHECKRADIO_EVENTS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_USERID = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_ROLLCOUNT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_USER_TURNTIME2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NUM_FIELD = -1; +static int hf_SAPDIAG_SUPPORT_BIT_WIN16 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONTEXT_MENU = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SCROLLABLE_TABSTRIP_PAGE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION = -1; +static int hf_SAPDIAG_SUPPORT_BIT_LABEL_OWNER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CLICKABLE_FIELD = -1; +static int hf_SAPDIAG_SUPPORT_BIT_PROPERTY_BAG = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNUSED_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABLE_ROW_REFERENCES_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_PROPFONT_VALID = -1; +static int hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_IMODEUUID = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NOTGUI = -1; +static int hf_SAPDIAG_SUPPORT_BIT_WAN = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XML_BLOBS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RFC_QUEUE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RFC_COMPRESS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_JAVA_BEANS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CTL_PROPCACHE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RFC_ASYNC_BLOB = -1; +static int hf_SAPDIAG_SUPPORT_BIT_KEEP_SCROLLPOS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNUSED_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNUSED_3 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XML_PROPERTIES = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNUSED_4 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_HEX_FIELD = -1; +static int hf_SAPDIAG_SUPPORT_BIT_HAS_CACHE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNUSED_5 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ITS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NO_EASYACCESS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_PROPERTYPUMP = -1; +static int hf_SAPDIAG_SUPPORT_BIT_COOKIE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNUSED_6 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SUPPBIT_AREA_SIZE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND_WRITE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENTRY_HISTORY = -1; +static int hf_SAPDIAG_SUPPORT_BIT_AUTO_CODEPAGE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CACHED_VSETS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_EMERGENCY_REPAIR = -1; +static int hf_SAPDIAG_SUPPORT_BIT_AREA2FRONT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SCROLLBAR_WIDTH = -1; +static int hf_SAPDIAG_SUPPORT_BIT_AUTORESIZE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_EDIT_VARLEN = -1; +static int hf_SAPDIAG_SUPPORT_BIT_WORKPLACE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_PRINTDATA = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SINGLE_SESSION = -1; +static int hf_SAPDIAG_SUPPORT_BIT_NOTIFY_NEWMODE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TOOLBAR_HEIGHT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XMLPROP_CONTAINER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XMLPROP_DYNPRO = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DP_HTTP_PUT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DYNAMIC_PASSPORT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_WEBGUI = -1; +static int hf_SAPDIAG_SUPPORT_BIT_WEBGUI_HELPMODE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_EOKDUMMY_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SLC = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ACCESSIBILITY = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ECATT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID3 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF8 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_AUTOLOGOUT_TIME = -1; +static int hf_SAPDIAG_SUPPORT_BIT_VARINFO_ICON_TITLE_LIST = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF16BE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF16LE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ENABLE_APPL4 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CBURBU_NEW_STATE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_BINARY_EVENTID = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUI_THEME = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TOP_WINDOW = -1; +static int hf_SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SPLITTER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_VALUE_4_HISTORY = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ACC_LIST = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING_INFO = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TEXTEDIT_STREAM = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DYNT_NOFOCUS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_FRAME_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TICKET4GUI = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ACC_LIST_PROPS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB_INPUT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DEFAULT_TOOLTIP = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_3 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CELLINFO = -1; +static int hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TABLE_COLUMNWIDTH_INPUT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ITS_PLUGIN = -1; +static int hf_SAPDIAG_SUPPORT_BIT_OBJECT_NAMES_4_LOGIN_PROCESS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RFC_SERVER_4_GUI = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_RCUI = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MENUENTRY_WITH_FCODE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_WEBSAPCONSOLE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_R3INFO_KERNEL_VERSION = -1; +static int hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_LOOP = -1; +static int hf_SAPDIAG_SUPPORT_BIT_EOKDUMMY_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO3 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_SBA2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MAINAREA_SIZE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL_2 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DISPLAY_SIZE = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUI_PACKET = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DIALOG_STEP_NUMBER = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TC_KEEP_SCROLL_POSITION = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MESSAGE_SERVICE_REQUEST = -1; +static int hf_SAPDIAG_SUPPORT_BIT_DYNT_FOCUS_FRAME = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MAX_STRING_LEN = -1; +static int hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_1 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_STD_TOOLBAR_ITEMS = -1; +static int hf_SAPDIAG_SUPPORT_BIT_XMLPROP_LIST_DYNPRO = -1; +static int hf_SAPDIAG_SUPPORT_BIT_TRACE_GUI_CONNECT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_LIST_FULLWIDTH = -1; +static int hf_SAPDIAG_SUPPORT_BIT_ALLWAYS_SEND_CLIENT = -1; +static int hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_3 = -1; +static int hf_SAPDIAG_SUPPORT_BIT_GUI_SIGNATURE_COLOR = -1; +static int hf_SAPDIAG_SUPPORT_BIT_MAX_WSIZE = -1; + + +static gint ett_sapdiag = -1; + +/* Global decompress preference */ +static gboolean global_sapdiag_decompress = TRUE; + +/* Global RFC dissection preference */ +static gboolean global_sapdiag_rfc_dissection = TRUE; + +/* Global SNC dissection preference */ +static gboolean global_sapdiag_snc_dissection = TRUE; + +/* Global port preference */ +static range_t *global_sapdiag_port_range; + +/* Global highlight preference */ +static gboolean global_sapdiag_highlight_items = TRUE; + +/* Protocol handle */ +static dissector_handle_t sapdiag_handle; + +void proto_reg_handoff_sapdiag(void); + +static void +dissect_sapdiag_dp_req_info(tvbuff_t *tvb, proto_tree *tree, guint32 offset){ + proto_item *ri = NULL; + proto_tree *req_info_tree; + + ri = proto_tree_add_item(tree, hf_sapdiag_dp_req_info, tvb, offset, 4, FALSE); + req_info_tree = proto_item_add_subtree(ri, ett_sapdiag); + + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_LOGIN, tvb, offset, 1, FALSE); /* 0x08 */ + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_LOGOFF, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_SHUTDOWN, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_GRAPHIC_TM, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_ALPHA_TM, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_ERROR_FROM_APPC, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_CANCELMODE, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_MSG_WITH_REQ_BUF, tvb, offset, 1, FALSE); offset++; + + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_MSG_WITH_OH, tvb, offset, 1, FALSE); /* 0x09 */ + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_BUFFER_REFRESH, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_BTC_SCHEDULER, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_APPC_SERVER_DOWN, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_MS_ERROR, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_SET_SYSTEM_USER, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_CANT_HANDLE_REQ, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_AUTO_ABAP, tvb, offset, 1, FALSE); offset++; + + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_APPL_SERV_INFO, tvb, offset, 1, FALSE); /* 0x0a */ + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_ADMIN, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_SPOOL_ALRM, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_HAND_SHAKE, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_CANCEL_PRIV, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_RAISE_TIMEOUT, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_NEW_MODE, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_SOFT_CANCEL, tvb, offset, 1, FALSE); offset++; + + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_TM_INPUT, tvb, offset, 1, FALSE); /* 0x0b */ + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_TM_OUTPUT, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_ASYNC_RFC, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_ICM_EVENT, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_AUTO_TH, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_RFC_CANCEL, tvb, offset, 1, FALSE); + proto_tree_add_item(req_info_tree, hf_sapdiag_dp_req_info_DP_MS_ADM, tvb, offset, 1, FALSE); +} + +static void +dissect_sapdiag_dp(tvbuff_t *tvb, proto_tree *tree, guint32 offset){ + proto_item *dp = NULL; + proto_tree *dp_tree; + + dp = proto_tree_add_item(tree, hf_sapdiag_dp, tvb, offset, 200, FALSE); + dp_tree = proto_item_add_subtree(dp, ett_sapdiag); + + proto_tree_add_item(dp_tree, hf_sapdiag_dp_request_id, tvb, offset, 4, FALSE); offset+=4; /* 0x00 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_retcode, tvb, offset, 1, FALSE); offset++; /* 0x04 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_sender_id, tvb, offset, 1, FALSE); offset++; /* 0x05 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_action_type, tvb, offset, 1, FALSE); offset++; /* 0x06 */ + dissect_sapdiag_dp_req_info(tvb, dp_tree, offset); offset+=4; /* Request info flags */ /* 0x07 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_tid, tvb, offset, 4, FALSE); offset+=4; /* 0x0b */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_uid, tvb, offset, 2, FALSE); offset+=2; /* 0x0f */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_mode, tvb, offset, 1, FALSE); offset++; /* 0x11 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_wp_id, tvb, offset, 4, FALSE); offset+=4; /* 0x12 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_wp_ca_blk, tvb, offset, 4, FALSE); offset+=4; /* 0x16 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_appc_ca_blk, tvb, offset, 4, FALSE); offset+=4; /* 0x1a */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset+=4; /* 0x1e */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_new_stat, tvb, offset, 1, FALSE); offset++; /* 0x22 */ + offset+=4; /* Unknown 4 bytes */ /* 0x23 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_rq_id, tvb, offset, 2, FALSE); offset+=2; /* 0x27 */ + offset+=40; /* Unknown 40 bytes (0x20 * 40) */ /* 0x29 */ + proto_tree_add_item(dp_tree, hf_sapdiag_dp_terminal, tvb, offset, 15, FALSE); offset+=15; /* 0x51 */ + offset+=10; /* Unknown 10 bytes (0x00 * 10) */ /* 0x60 */ + offset+=20; /* Unknown 20 bytes (0x20 * 20) */ /* 0x6a */ + offset+=4; /* Unknown dword (0x00) */ /* 0x7e */ + offset+=4; /* Unknown dword (0x00) */ /* 0x82 */ + offset+=4; /* Unknown dword (0xFF * 4) */ /* 0x86 */ + offset+=4; /* Unknown dword (0x00) */ /* 0x8a */ + offset++; /* Unknown byte (0x01) */ /* 0x8e */ + offset+=57; /* Unknown byte (0x00 * 57) */ /* 0x8f */ + /* 0xc8 */ +} + +static void +dissect_sapdiag_support_bits(tvbuff_t *tvb, proto_tree *tree, guint32 offset){ + + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_PROGRESS_INDICATOR, tvb, offset, 1, FALSE); // 0 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_LABELS, tvb, offset, 1, FALSE); // 1 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_DIAGVERSION, tvb, offset, 1, FALSE); // 2 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_SELECT_RECT, tvb, offset, 1, FALSE); // 3 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_SYMBOL_RIGHT, tvb, offset, 1, FALSE); // 4 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_FONT_METRIC, tvb, offset, 1, FALSE); // 5 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_COMPR_ENHANCED, tvb, offset, 1, FALSE); // 6 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_IMODE, tvb, offset, 1, FALSE); // 7 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_LONG_MESSAGE, tvb, offset, 1, FALSE); // 8 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_TABLE, tvb, offset, 1, FALSE); // 9 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_FOCUS_1, tvb, offset, 1, FALSE); // 10 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_PUSHBUTTON_1, tvb, offset, 1, FALSE); // 11 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UPPERCASE, tvb, offset, 1, FALSE); // 12 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SAPGUI_TABPROPERTY, tvb, offset, 1, FALSE); // 13 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_INPUT_UPPERCASE, tvb, offset, 1, FALSE); // 14 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RFC_DIALOG, tvb, offset, 1, FALSE); // 15 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_LIST_HOTSPOT, tvb, offset, 1, FALSE); // 16 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_FKEY_TABLE, tvb, offset, 1, FALSE); // 17 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MENU_SHORTCUT, tvb, offset, 1, FALSE); // 18 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_STOP_TRANS, tvb, offset, 1, FALSE); // 19 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_FULL_MENU, tvb, offset, 1, FALSE); // 20 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_OBJECT_NAMES, tvb, offset, 1, FALSE); // 21 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONTAINER_TYPE, tvb, offset, 1, FALSE); // 22 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DLGH_FLAGS, tvb, offset, 1, FALSE); // 23 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_APPL_MNU, tvb, offset, 1, FALSE); // 24 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO, tvb, offset, 1, FALSE); // 25 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MESDUM_FLAG1, tvb, offset, 1, FALSE); // 26 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB, tvb, offset, 1, FALSE); // 27 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUIAPI, tvb, offset, 1, FALSE); // 28 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NOGRAPH, tvb, offset, 1, FALSE); // 29 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NOMESSAGES, tvb, offset, 1, FALSE); // 30 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NORABAX, tvb, offset, 1, FALSE); // 31 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NOSYSMSG, tvb, offset, 1, FALSE); // 32 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NOSAPSCRIPT, tvb, offset, 1, FALSE); // 33 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NORFC, tvb, offset, 1, FALSE); // 34 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NEW_BSD_JUSTRIGHT, tvb, offset, 1, FALSE); // 35 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MESSAGE_VARS, tvb, offset, 1, FALSE); // 36 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_OCX_SUPPORT, tvb, offset, 1, FALSE); // 37 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SCROLL_INFOS, tvb, offset, 1, FALSE); // 38 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABLE_SIZE_OK, tvb, offset, 1, FALSE); // 39 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO2, tvb, offset, 1, FALSE); // 40 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_VARINFO_OKCODE, tvb, offset, 1, FALSE); // 41 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CURR_TCODE, tvb, offset, 1, FALSE); // 42 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONN_WSIZE, tvb, offset, 1, FALSE); // 43 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_PUSHBUTTON_2, tvb, offset, 1, FALSE); // 44 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABSTRIP, tvb, offset, 1, FALSE); // 45 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_1, tvb, offset, 1, FALSE); // 46 (Unknown support bit) + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABSCROLL_INFOS, tvb, offset, 1, FALSE); // 47 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABLE_FIELD_NAMES, tvb, offset, 1, FALSE); // 48 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NEW_MODE_REQUEST, tvb, offset, 1, FALSE); // 49 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RFCBLOB_DIAG_PARSER, tvb, offset, 1, FALSE); // 50 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MULTI_LOGIN_USER, tvb, offset, 1, FALSE); // 51 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONTROL_CONTAINER, tvb, offset, 1, FALSE); // 52 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_APPTOOLBAR_FIXED, tvb, offset, 1, FALSE); // 53 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_USER_CHECKED, tvb, offset, 1, FALSE); // 54 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NEED_STDDYNPRO, tvb, offset, 1, FALSE); // 55 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TYPE_SERVER, tvb, offset, 1, FALSE); // 56 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_COMBOBOX, tvb, offset, 1, FALSE); // 57 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_INPUT_REQUIRED, tvb, offset, 1, FALSE); // 58 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ISO_LANGUAGE, tvb, offset, 1, FALSE); // 59 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_COMBOBOX_TABLE, tvb, offset, 1, FALSE); // 60 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS, tvb, offset, 1, FALSE); // 61 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CHECKRADIO_EVENTS, tvb, offset, 1, FALSE); // 62 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_USERID, tvb, offset, 1, FALSE); // 63 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_ROLLCOUNT, tvb, offset, 1, FALSE); // 64 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_USER_TURNTIME2, tvb, offset, 1, FALSE); // 65 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NUM_FIELD, tvb, offset, 1, FALSE); // 66 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_WIN16, tvb, offset, 1, FALSE); // 67 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONTEXT_MENU, tvb, offset, 1, FALSE); // 68 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SCROLLABLE_TABSTRIP_PAGE, tvb, offset, 1, FALSE); // 69 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION, tvb, offset, 1, FALSE); // 70 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_LABEL_OWNER, tvb, offset, 1, FALSE); // 71 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CLICKABLE_FIELD, tvb, offset, 1, FALSE); // 72 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_PROPERTY_BAG, tvb, offset, 1, FALSE); // 73 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNUSED_1, tvb, offset, 1, FALSE); // 74 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABLE_ROW_REFERENCES_2, tvb, offset, 1, FALSE); // 75 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_PROPFONT_VALID, tvb, offset, 1, FALSE); // 76 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER, tvb, offset, 1, FALSE); // 77 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_IMODEUUID, tvb, offset, 1, FALSE); // 78 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NOTGUI, tvb, offset, 1, FALSE); // 79 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_WAN, tvb, offset, 1, FALSE); // 80 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XML_BLOBS, tvb, offset, 1, FALSE); // 81 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RFC_QUEUE, tvb, offset, 1, FALSE); // 82 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RFC_COMPRESS, tvb, offset, 1, FALSE); // 83 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_JAVA_BEANS, tvb, offset, 1, FALSE); // 84 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND, tvb, offset, 1, FALSE); // 85 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CTL_PROPCACHE, tvb, offset, 1, FALSE); // 86 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID, tvb, offset, 1, FALSE); // 87 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RFC_ASYNC_BLOB, tvb, offset, 1, FALSE); // 88 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_KEEP_SCROLLPOS, tvb, offset, 1, FALSE); // 89 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNUSED_2, tvb, offset, 1, FALSE); // 90 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNUSED_3, tvb, offset, 1, FALSE); // 91 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XML_PROPERTIES, tvb, offset, 1, FALSE); // 92 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNUSED_4, tvb, offset, 1, FALSE); // 93 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_HEX_FIELD, tvb, offset, 1, FALSE); // 94 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_HAS_CACHE, tvb, offset, 1, FALSE); // 95 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE, tvb, offset, 1, FALSE); // 96 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNUSED_5, tvb, offset, 1, FALSE); // 97 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID2, tvb, offset, 1, FALSE); // 98 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ITS, tvb, offset, 1, FALSE); // 99 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NO_EASYACCESS, tvb, offset, 1, FALSE); // 100 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_PROPERTYPUMP, tvb, offset, 1, FALSE); // 101 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_COOKIE, tvb, offset, 1, FALSE); // 102 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNUSED_6, tvb, offset, 1, FALSE); // 103 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SUPPBIT_AREA_SIZE, tvb, offset, 1, FALSE); // 104 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND_WRITE, tvb, offset, 1, FALSE); // 105 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS, tvb, offset, 1, FALSE); // 106 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENTRY_HISTORY, tvb, offset, 1, FALSE); // 107 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_AUTO_CODEPAGE, tvb, offset, 1, FALSE); // 108 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CACHED_VSETS, tvb, offset, 1, FALSE); // 109 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_EMERGENCY_REPAIR, tvb, offset, 1, FALSE); // 110 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_AREA2FRONT, tvb, offset, 1, FALSE); // 111 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SCROLLBAR_WIDTH, tvb, offset, 1, FALSE); // 112 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_AUTORESIZE, tvb, offset, 1, FALSE); // 113 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_EDIT_VARLEN, tvb, offset, 1, FALSE); // 114 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_WORKPLACE, tvb, offset, 1, FALSE); // 115 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_PRINTDATA, tvb, offset, 1, FALSE); // 116 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_2, tvb, offset, 1, FALSE); // 117 (Unknown support bit) + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SINGLE_SESSION, tvb, offset, 1, FALSE); // 118 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_NOTIFY_NEWMODE, tvb, offset, 1, FALSE); // 119 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TOOLBAR_HEIGHT, tvb, offset, 1, FALSE); // 120 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XMLPROP_CONTAINER, tvb, offset, 1, FALSE); // 121 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XMLPROP_DYNPRO, tvb, offset, 1, FALSE); // 122 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DP_HTTP_PUT, tvb, offset, 1, FALSE); // 123 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DYNAMIC_PASSPORT, tvb, offset, 1, FALSE); // 124 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_WEBGUI, tvb, offset, 1, FALSE); // 125 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_WEBGUI_HELPMODE, tvb, offset, 1, FALSE); // 126 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST, tvb, offset, 1, FALSE); // 127 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_2, tvb, offset, 1, FALSE); // 128 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_EOKDUMMY_1, tvb, offset, 1, FALSE); // 129 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING, tvb, offset, 1, FALSE); // 130 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SLC, tvb, offset, 1, FALSE); // 131 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ACCESSIBILITY, tvb, offset, 1, FALSE); // 132 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ECATT, tvb, offset, 1, FALSE); // 133 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID3, tvb, offset, 1, FALSE); // 134 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF8, tvb, offset, 1, FALSE); // 135 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_AUTOLOGOUT_TIME, tvb, offset, 1, FALSE); // 136 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_VARINFO_ICON_TITLE_LIST, tvb, offset, 1, FALSE); // 137 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF16BE, tvb, offset, 1, FALSE); // 138 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF16LE, tvb, offset, 1, FALSE); // 139 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP, tvb, offset, 1, FALSE); // 140 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ENABLE_APPL4, tvb, offset, 1, FALSE); // 141 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL, tvb, offset, 1, FALSE); // 142 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CBURBU_NEW_STATE, tvb, offset, 1, FALSE); // 143 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_BINARY_EVENTID, tvb, offset, 1, FALSE); // 144 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUI_THEME, tvb, offset, 1, FALSE); // 145 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TOP_WINDOW, tvb, offset, 1, FALSE); // 146 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION_1, tvb, offset, 1, FALSE); // 147 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SPLITTER, tvb, offset, 1, FALSE); // 148 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_VALUE_4_HISTORY, tvb, offset, 1, FALSE); // 149 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ACC_LIST, tvb, offset, 1, FALSE); // 150 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING_INFO, tvb, offset, 1, FALSE); // 151 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TEXTEDIT_STREAM, tvb, offset, 1, FALSE); // 152 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DYNT_NOFOCUS, tvb, offset, 1, FALSE); // 153 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP_1, tvb, offset, 1, FALSE); // 154 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_FRAME_1, tvb, offset, 1, FALSE); // 155 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TICKET4GUI, tvb, offset, 1, FALSE); // 156 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ACC_LIST_PROPS, tvb, offset, 1, FALSE); // 157 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB_INPUT, tvb, offset, 1, FALSE); // 158 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DEFAULT_TOOLTIP, tvb, offset, 1, FALSE); // 159 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE_2, tvb, offset, 1, FALSE); // 160 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_3, tvb, offset, 1, FALSE); // 161 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CELLINFO, tvb, offset, 1, FALSE); // 162 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST_2, tvb, offset, 1, FALSE); // 163 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TABLE_COLUMNWIDTH_INPUT, tvb, offset, 1, FALSE); // 164 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ITS_PLUGIN, tvb, offset, 1, FALSE); // 165 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_OBJECT_NAMES_4_LOGIN_PROCESS, tvb, offset, 1, FALSE); // 166 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RFC_SERVER_4_GUI, tvb, offset, 1, FALSE); // 167 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS_2, tvb, offset, 1, FALSE); // 168 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_RCUI, tvb, offset, 1, FALSE); // 169 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MENUENTRY_WITH_FCODE, tvb, offset, 1, FALSE); // 170 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_WEBSAPCONSOLE, tvb, offset, 1, FALSE); // 171 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_R3INFO_KERNEL_VERSION, tvb, offset, 1, FALSE); // 172 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_LOOP, tvb, offset, 1, FALSE); // 173 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_EOKDUMMY_2, tvb, offset, 1, FALSE); // 174 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO3, tvb, offset, 1, FALSE); // 175 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_SBA2, tvb, offset, 1, FALSE); // 176 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MAINAREA_SIZE, tvb, offset, 1, FALSE); // 177 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL_2, tvb, offset, 1, FALSE); // 178 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DISPLAY_SIZE, tvb, offset, 1, FALSE); // 179 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUI_PACKET, tvb, offset, 1, FALSE); // 180 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DIALOG_STEP_NUMBER, tvb, offset, 1, FALSE); // 181 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TC_KEEP_SCROLL_POSITION, tvb, offset, 1, FALSE); // 182 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MESSAGE_SERVICE_REQUEST, tvb, offset, 1, FALSE); // 183 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_DYNT_FOCUS_FRAME, tvb, offset, 1, FALSE); // 184 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MAX_STRING_LEN, tvb, offset, 1, FALSE); // 185 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_1, tvb, offset, 1, FALSE); // 186 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_STD_TOOLBAR_ITEMS, tvb, offset, 1, FALSE); // 187 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_XMLPROP_LIST_DYNPRO, tvb, offset, 1, FALSE); // 188 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_TRACE_GUI_CONNECT, tvb, offset, 1, FALSE); // 189 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_LIST_FULLWIDTH, tvb, offset, 1, FALSE); // 190 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_ALLWAYS_SEND_CLIENT, tvb, offset, 1, FALSE); // 191 + offset+=1; + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_3, tvb, offset, 1, FALSE); // 192 (Unknown support bit) + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_GUI_SIGNATURE_COLOR, tvb, offset, 1, FALSE); // 193 + proto_tree_add_item(tree, hf_SAPDIAG_SUPPORT_BIT_MAX_WSIZE, tvb, offset, 1, FALSE); // 194 + +} + +static void +dissect_sapdiag_rfc_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 item_length){ + + tvbuff_t *next_tvb = NULL; + dissector_handle_t rfc_handle; + + /* Call the RFC internal dissector */ + if (global_sapdiag_rfc_dissection == TRUE){ + rfc_handle = find_dissector("saprfcinternal"); + if (rfc_handle){ + /* Set the column to not writable so the RFC dissector doesn't override the Diag info */ + col_set_writable(pinfo->cinfo, FALSE); + /* Create a new tvb buffer and call the dissector */ + next_tvb = tvb_new_subset(tvb, offset, item_length, item_length); + call_dissector(rfc_handle, next_tvb, pinfo, tree); + } else { + expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN, "SAP RFC dissector not found !"); + } + } + +} + + +static void +dissect_sapdiag_snc_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset){ + + tvbuff_t *next_tvb = NULL; + dissector_handle_t snc_handle; + + /* Call the SNC dissector */ + if (global_sapdiag_snc_dissection == TRUE){ + snc_handle = find_dissector("sapsnc"); + if (snc_handle){ + /* Set the column to not writable so the SNC dissector doesn't override the Diag info */ + col_set_writable(pinfo->cinfo, FALSE); + /* Create a new tvb buffer and call the dissector */ + next_tvb = tvb_new_subset(tvb, offset, -1, -1); + call_dissector(snc_handle, next_tvb, pinfo, tree); + } else { + expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN, "SAP SNC dissector not found !"); + } + } + +} + + +gboolean +check_length(packet_info *pinfo, proto_tree *tree, guint32 expected, guint32 real, const char *name_string){ + if (expected != real){ + expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_WARN, "%s length is invalid", name_string); + return (FALSE); + } else return (TRUE); +} + +guint8 +add_item_value_uint8(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text){ + proto_tree_add_none_format(tree, hf_sapdiag_item_value, tvb, offset, length, "%s: %d", text, tvb_get_guint8(tvb, offset)); + proto_item_append_text(item, ", %s=%d", text, tvb_get_guint8(tvb, offset)); + return (tvb_get_guint8(tvb, offset)); +} + +guint16 +add_item_value_uint16(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text){ + proto_tree_add_none_format(tree, hf_sapdiag_item_value, tvb, offset, length, "%s: %d", text, tvb_get_ntohs(tvb, offset)); + proto_item_append_text(item, ", %s=%d", text, tvb_get_ntohs(tvb, offset)); + return (tvb_get_ntohs(tvb, offset)); +} + +guint32 +add_item_value_uint32(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text){ + proto_tree_add_none_format(tree, hf_sapdiag_item_value, tvb, offset, length, "%s: %d", text, tvb_get_ntohl(tvb, offset)); + proto_item_append_text(item, ", %s=%d", text, tvb_get_ntohl(tvb, offset)); + return (tvb_get_ntohl(tvb, offset)); +} + +void +add_item_value_string(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text, int show_in_tree){ + guint8 *string = NULL; + string = tvb_get_ephemeral_string(tvb, offset, length); + proto_tree_add_none_format(tree, hf_sapdiag_item_value, tvb, offset, length, "%s: %s", text, string); + if (show_in_tree) proto_item_append_text(item, ", %s=%s", text, string); +} + +guint32 +add_item_value_stringz(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, const char *text, int show_in_tree){ + guint32 length = tvb_strsize(tvb, offset); + guint8 *string = tvb_get_ephemeral_string(tvb, offset, length - 1); + proto_tree_add_none_format(tree, hf_sapdiag_item_value, tvb, offset, length, "%s: %s", text, string); + if (show_in_tree) proto_item_append_text(item, ", %s=%s", text, string); + return (length); +} + +void +add_item_value_hexstring(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text){ + proto_tree_add_none_format(tree, hf_sapdiag_item_value, tvb, offset, length, "%s: %s", text, tvb_bytes_to_str(tvb, offset, length)); + proto_item_append_text(item, ", %s=%s", text, tvb_bytes_to_str(tvb, offset, length)); +} + +static void +dissect_sapdiag_dyntatom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 length){ + guint32 final = offset + length; + guint16 atom_length = 0, atom_item_length = 0; + guint8 etype = 0, attr = 0; + + proto_item *atom = NULL, *atom_item = NULL, *atom_item_attr = NULL; + proto_tree *atom_tree = NULL, *atom_item_tree = NULL, *atom_item_attr_tree = NULL; + + while (offset < final){ + + etype = tvb_get_guint8(tvb, offset+4); + if ((etype != 114) && (etype != 120)) { + /* Add a new atom subtree */ + atom_length = 0; + atom = proto_tree_add_item(tree, hf_sapdiag_item_dynt_atom, tvb, offset, atom_length, FALSE); + atom_tree = proto_item_add_subtree(atom, ett_sapdiag); + proto_item_append_text(atom, ", Etype=%s", val_to_str(etype, hf_sapdiag_item_dynt_atom_item_etype_vals, "Unknown")); /* Add the Etype to the Atom tree also */ + } + + /* Check the atom_tree for NULL values. If the atom_tree wasn't created at this point, the atom + * starts with an item different to 114 or 120. */ + if (atom_tree == NULL){ + expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_WARN, "The Diag Atom is malformed"); + break; + } + + /* Add the item atom subtree */ + atom_item = proto_tree_add_item(atom_tree, hf_sapdiag_item_dynt_atom_item, tvb, offset, tvb_get_ntohs(tvb, offset), FALSE); + atom_item_tree = proto_item_add_subtree(atom_item, ett_sapdiag); + + /* Get the atom item length */ + atom_item_length = add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Atom Length"); + + /* Adjust the length of the atom tree, adding the new item's length and the length field */ + atom_length+= atom_item_length; + proto_item_set_len(atom_tree, atom_length); + + /* Continue with the dissection */ + offset+=2; atom_item_length-=2; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Dlg Flag 1"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Dlg Flag 2"); offset+=1; atom_item_length-=1; + + proto_tree_add_item(atom_item_tree, hf_sapdiag_item_dynt_atom_item_etype, tvb, offset, 1, FALSE); + proto_item_append_text(atom_item, ", EType=%d", tvb_get_guint8(tvb, offset));offset+=1; atom_item_length-=1; + + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Area"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Block"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Group"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Row"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Col"); offset+=2; atom_item_length-=2; + + atom_item_attr = proto_tree_add_item(atom_item_tree, hf_sapdiag_item_dynt_atom_item_attr, tvb, offset, 1, FALSE); + atom_item_attr_tree = proto_item_add_subtree(atom_item_attr, ett_sapdiag); + + attr = tvb_get_guint8(tvb, offset); + proto_item_append_text(atom_item, ", Attr=%d", attr); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_PROTECTED, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_INVISIBLE, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_INTENSIFY, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_JUSTRIGHT, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_MATCHCODE, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_PROPFONT, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_YES3D, tvb, offset, 1, FALSE); + proto_tree_add_item(atom_item_attr_tree, hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_COMBOSTYLE, tvb, offset, 1, FALSE); + offset+=1; atom_item_length-=1; + + switch (etype){ + case 114:{ /* DIAG_DGOTYP_FNAME */ + add_item_value_string(tvb, atom_item, atom_item_tree, offset, atom_item_length, "Text", 1); + proto_item_append_text(atom, ", Text=%s", tvb_get_ephemeral_string(tvb, offset, atom_item_length)); offset+=atom_item_length; + break; + } case 115:{ /* DIAG_DGOTYP_PUSHBUTTON_2 */ + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "V Length"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "V Height"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Function Code Offset"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Text Offset"); offset+=2; atom_item_length-=2; + offset+=add_item_value_stringz(tvb, atom_item, atom_item_tree, offset, "Text", 1); + offset+=add_item_value_stringz(tvb, atom_item, atom_item_tree, offset, "Function Code", 1); + break; + } case 116:{ /* DIAG_DGOTYP_TABSTRIP_BUTTON */ + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "V Length"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "V Height"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Page Id"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Function Code Offset"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Text Offset"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Id Offset"); offset+=2; atom_item_length-=2; + offset+=add_item_value_stringz(tvb, atom_item, atom_item_tree, offset, "Text", 1); + offset+=add_item_value_stringz(tvb, atom_item, atom_item_tree, offset, "Function Code", 1); + offset+=add_item_value_stringz(tvb, atom_item, atom_item_tree, offset, "ID", 1); + break; + } case 118: /* DIAG_DGOTYP_CHECKBUTTON_1" */ + case 119:{ /* DIAG_DGOTYP_RADIOBUTTON_1 */ + /* If the preference is set, report the item as partially dissected in the expert info */ + if (global_sapdiag_highlight_items){ + expert_add_info_format(pinfo, atom_item, PI_UNDECODED, PI_WARN, "The Diag Atom is dissected partially (0x%.2x)", etype); + } + break; + } case 120:{ /* DIAG_DGOTYP_XMLPROP */ + add_item_value_string(tvb, atom_item, atom_item_tree, offset, atom_item_length, "XMLProp", 1); + proto_item_append_text(atom, ", XMLProp=%s", tvb_get_ephemeral_string(tvb, offset, atom_item_length)); offset+=atom_item_length; + break; + } case 121: /* DIAG_DGOTYP_EFIELD_1 */ + case 122: /* DIAG_DGOTYP_OFIELD_1 */ + case 123:{ /* DIAG_DGOTYP_KEYWORD_1_1 */ + /* Found in NW 7.01 versions */ + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "MLen"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "DLen"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "MaxNrChars"); offset+=2; atom_item_length-=2; + add_item_value_string(tvb, atom_item, atom_item_tree, offset, atom_item_length, "Text", 0); offset+=atom_item_length; + break; + } case 127:{ /* DIAG_DGOTYP_FRAME_1 */ + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "DRows"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "DCols"); offset+=2; atom_item_length-=2; + add_item_value_string(tvb, atom_item, atom_item_tree, offset, atom_item_length, "Text", 1); offset+=atom_item_length; + break; + } case 129:{ /* DIAG_DGOTYP_RADIOBUTTON_3 */ + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "Button"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset,2, "Visible Label Length"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "EventID Off"); offset+=2; atom_item_length-=2; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "EventID Len"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Text Off"); offset+=2; atom_item_length-=2; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Text Length"); offset+=2; atom_item_length-=2; + add_item_value_string(tvb, atom_item, atom_item_tree, offset, atom_item_length, "Text", 1); offset+=atom_item_length; + break; + } case 130: /* DIAG_DGOTYP_EFIELD_2 */ + case 131: /* DIAG_DGOTYP_OFIELD_2 */ + case 132:{ /* DIAG_DGOTYP_KEYWORD_2 */ + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "Flag1"); offset+=2; atom_item_length-=2; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "DLen"); offset+=1; atom_item_length-=1; + add_item_value_uint8(tvb, atom_item, atom_item_tree, offset, 1, "MLen"); offset+=1; atom_item_length-=1; + add_item_value_uint16(tvb, atom_item, atom_item_tree, offset, 2, "MaxNrChars"); offset+=2; atom_item_length-=2; + add_item_value_string(tvb, atom_item, atom_item_tree, offset, atom_item_length, "Text", 0); offset+=atom_item_length; + + /* If the attribute is set to invisible we're dealing probably with a password field */ + if (attr & SAPDIAG_ATOM_ATTR_DIAG_BSD_INVISIBLE) + expert_add_info_format(pinfo, atom_item, PI_SECURITY, PI_WARN, "Password field?"); + + break; + } default: + /* If the preference is set, report the item as unknown in the expert info */ + if (global_sapdiag_highlight_items){ + expert_add_info_format(pinfo, atom_item, PI_UNDECODED, PI_WARN, "The Diag Atom has a unknown type that is not dissected (%d)", etype); + } + offset+=atom_item_length; + break; + } + } + +} + +static void +dissect_sapdiag_menu(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length){ + + guint32 final = offset + length; + + proto_item *menu = NULL; + proto_tree *menu_tree = NULL; + + while (offset < final){ + + /* Add the menu entry subtree */ + menu = proto_tree_add_item(tree, hf_sapdiag_item_menu_entry, tvb, offset, tvb_get_ntohs(tvb, offset), FALSE); + menu_tree = proto_item_add_subtree(menu, ett_sapdiag); + + add_item_value_uint16(tvb, menu, menu_tree, offset, 2, "Length"); offset+=2; + + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Position 1"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Position 2"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Position 3"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Position 4"); offset+=1; + + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Flag"); offset+=1; /* XXX: Add flag values */ + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Virtual Key"); offset+=1; + + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Return Code 1"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Return Code 2"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Return Code 3"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Return Code 4"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Return Code 5"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Return Code 6"); offset+=1; + + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Function Code 1"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Function Code 2"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Function Code 3"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Function Code 4"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Function Code 5"); offset+=1; + add_item_value_uint8(tvb, menu, menu_tree, offset, 1, "Function Code 6"); offset+=1; + + offset+=add_item_value_stringz(tvb, menu, menu_tree, offset, "Text", 1); + offset+=add_item_value_stringz(tvb, menu, menu_tree, offset, "Accelerator", 1); + offset+=add_item_value_stringz(tvb, menu, menu_tree, offset, "Info", 1); + } + +} + +static void +dissect_sapdiag_uievent(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 length){ + + proto_item *event_valid_item = NULL; + proto_tree *event_valid_tree = NULL; + guint8 event_valid = 0; + guint16 container_nrs = 0, i = 0; + + event_valid = tvb_get_guint8(tvb, offset); + event_valid_item = proto_tree_add_item(tree, ht_sapdiag_item_ui_event_valid, tvb, offset, 1, FALSE); + event_valid_tree = proto_item_add_subtree(event_valid_item, ett_sapdiag); + + proto_tree_add_item(event_valid_tree, ht_sapdiag_item_ui_event_valid_MENU_POS, tvb, offset, 1, FALSE); + proto_tree_add_item(event_valid_tree, ht_sapdiag_item_ui_event_valid_CONTROL_POS, tvb, offset, 1, FALSE); + proto_tree_add_item(event_valid_tree, ht_sapdiag_item_ui_event_valid_NAVIGATION_DATA, tvb, offset, 1, FALSE); + proto_tree_add_item(event_valid_tree, ht_sapdiag_item_ui_event_valid_FUNCTIONKEY_DATA, tvb, offset, 1, FALSE); offset+=1;length-=1; + + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_event_type, tvb, offset, 2, FALSE); + proto_item_append_text(tree, ", Event Type=%s", val_to_str(tvb_get_ntohs(tvb, offset), ht_sapdiag_item_ui_event_event_type_vals, "Unknown")); offset+=2;length-=2; + + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_control_type, tvb, offset, 2, FALSE); + proto_item_append_text(tree, ", Control Type=%s", val_to_str(tvb_get_ntohs(tvb, offset), ht_sapdiag_item_ui_event_control_type_vals, "Unknown")); offset+=2;length-=2; + + /* The semantic of the event data changes depending of the event valid flag and are ignored if the + SAPDIAG_UI_EVENT_VALID_FLAG_NAVIGATION_DATA flag or the SAPDIAG_UI_EVENT_VALID_FLAG_FUNCTIONKEY_DATA + flags are not set. We dissect them always. */ + if (event_valid & SAPDIAG_UI_EVENT_VALID_FLAG_NAVIGATION_DATA){ + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_navigation_data, tvb, offset, 1, FALSE); offset+=1;length-=1; + } else { /* SAPDIAG_UI_EVENT_VALID_FLAG_FUNCTIONKEY_DATA */ + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_data, tvb, offset, 1, FALSE); offset+=1;length-=1; + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_data, tvb, offset, 1, FALSE); offset+=1;length-=1; + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_data, tvb, offset, 1, FALSE); offset+=1;length-=1; + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_data, tvb, offset, 1, FALSE); offset+=1;length-=1; + } + + /* These items are ignored if the flag SAPDIAG_UI_EVENT_VALID_FLAG_CONTROL_POS is not set. We dissect them always. */ + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_control_row, tvb, offset, 2, FALSE); offset+=2;length-=2; + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_control_col, tvb, offset, 2, FALSE); offset+=2;length-=2; + + i = container_nrs = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_container_nrs, tvb, offset, 2, FALSE); offset+=2;length-=2; + + while (i>0 && length>0){ + proto_tree_add_item(tree, ht_sapdiag_item_ui_event_container, tvb, offset, 1, FALSE); offset+=1;length-=1; i--; + } + + if (i>0) + expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_WARN, "Number of Container IDs (%d) is invalid", container_nrs); + +} + +static void +dissect_sapdiag_item(tvbuff_t *tvb, packet_info *pinfo, proto_item *item, proto_tree *item_value_tree, proto_tree *parent_tree, guint32 offset, guint8 item_type, guint8 item_id, guint8 item_sid, guint32 item_length){ + guint8 i = 0, eventarray = 0; + guint32 l = 0; + + /* SES item */ + if (item_type==0x01){ /* XXX: Incomplete dissection of this item */ + check_length(pinfo, item_value_tree, 16, item_length, "SES"); + + eventarray = tvb_get_guint8(tvb, offset); + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Event Array");offset+=1; + + if (eventarray == 0){ + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Event ID 1"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Event ID 2"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Event ID 3"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Event ID 4"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Event ID 5"); offset+=1; + } else { + + /* If the preference is set, report the item as partially dissected in the expert info */ + if (global_sapdiag_highlight_items){ + expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "The Diag Item is dissected partially (0x%.2x, 0x%.2x, 0x%.2x)", item_type, item_id, item_sid); + } + offset+=5; + } + + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Screen Flag"); offset+=1; /* XXX: Add flag values */ + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Modal No"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "X Pos"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Y Pos"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "IMode"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Flag 1"); offset+=1; /* XXX: Add flag values */ + offset+=2; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Dim Row"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Dim Col"); offset+=1; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x26){ /* Dialog Step Number */ + check_length(pinfo, item_value_tree, 4, item_length, "Dialog Step Number"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Dialog Step Number"); offset+=4; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x02){ /* Connect */ + check_length(pinfo, item_value_tree, 12, item_length, "Connect"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Protocol Version"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Code Page"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "WS Type"); offset+=4; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x04){ /* Font Metric */ + check_length(pinfo, item_value_tree, 8, item_length, "Font Metric"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Variable font size (y)"); offset+=2; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Variable font size (x)"); offset+=2; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Fixed font size (y)"); offset+=2; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Fixed font size (x)"); offset+=2; + + } else if ((item_type==0x10 && item_id==0x04 && item_sid==0x0b) || /* Support Data */ + (item_type==0x10 && item_id==0x06 && item_sid==0x11)){ + check_length(pinfo, item_value_tree, 32, item_length, "Support Data"); + dissect_sapdiag_support_bits(tvb, item_value_tree, offset); offset+=32; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x0d){ /* Window Size */ + check_length(pinfo, item_value_tree, 16, item_length, "Window Size"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Window Height"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Window Width"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Area Height"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Area Width"); offset+=4; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x0f){ /* Turn Time 2 (Response time) */ + check_length(pinfo, item_value_tree, 4, item_length, "Response time"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Response time"); offset+=4; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x16){ /* Scrollbar Width */ + check_length(pinfo, item_value_tree, 2, item_length, "Scrollbar Width"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Toollbar Width"); offset+=2; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x17){ /* Scrollbar Height */ + check_length(pinfo, item_value_tree, 2, item_length, "Scrollbar Height"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Scrollbar Height"); offset+=2; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x19){ /* Gui State */ + check_length(pinfo, item_value_tree, 2, item_length, "Gui State"); + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Flag 1"); offset+=1; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Flag 2"); offset+=1; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x1d){ /* GUI patch level */ + check_length(pinfo, item_value_tree, 1, item_length, "GUI patch level"); + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "GUI patch level"); offset+=1; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x24){ /* Display Size */ + check_length(pinfo, item_value_tree, 8, item_length, "Display Size"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Height"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Height"); offset+=4; + + } else if (item_type==0x10 && item_id==0x04 && item_sid==0x25){ /* GUI Type */ + check_length(pinfo, item_value_tree, 2, item_length, "GUI Type"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "GUI Type"); offset+=2; + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x01){ /* Mode Number */ + check_length(pinfo, item_value_tree, 2, item_length, "Mode Number"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Mode Number"); offset+=2; + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x06){ /* Diag version */ + check_length(pinfo, item_value_tree, 2, item_length, "Diag version"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Diag version"); offset+=2; + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x0a){ /* Internal Mode Number */ + check_length(pinfo, item_value_tree, 2, item_length, "Internal Mode Number"); + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Internal Mode Number"); offset+=2; + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x13){ /* GUI_FKEY */ + l = offset+item_length; + offset++; + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Virtual key number", 1); + while (offset0;i--){ + add_item_value_hexstring(tvb, item, item_value_tree, offset, 16, "UUID"); offset+=16; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Active context"); offset+=1; + } + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x22){ /* Auto logout time */ + check_length(pinfo, item_value_tree, 4, item_length, "Auto logout time"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Auto logout time"); offset+=4; + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x23){ /* Codepage Diag GUI */ + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Codepage number (numeric representation)"); offset+=4; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Minimum number of bytes per charcter"); offset+=1; + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Codepage number (string representation)", 1); + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Codepage description", 1); + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x27){ /* Codepage App Server */ + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Codepage number (numeric representation)"); offset+=4; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Minimum number of bytes per charcter"); offset+=1; + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Codepage number (string representation)", 1); + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Codepage description", 1); + + } else if (item_type==0x10 && item_id==0x06 && item_sid==0x29){ /* Kernel Version */ + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Database version", 1); + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Kernel version", 1); + offset+=add_item_value_stringz(tvb, item, item_value_tree, offset, "Kernel patch level", 1); + + } else if (item_type==0x10 && item_id==0x09 && item_sid==0x0b){ /* Dynt Focus */ + l=offset+item_length; + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "Focus Num of Area ID"); offset+=1; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Focus Row"); offset+=2; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Focus Col"); offset+=2; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Focus Row Offset"); offset+=2; + add_item_value_uint16(tvb, item, item_value_tree, offset, 2, "Focus Col Offset"); offset+=2; + /* Container IDs up to 30 */ + if (l-offset > 30){ + expert_add_info_format(pinfo, item, PI_MALFORMED, PI_WARN, "The Dynt Focus contains more than 30 Container IDs (%d)", offset); + } + /* Dissect all the remaining container IDs */ + while(offset 0){ + /* Check if the item length is valid */ + if ((guint32)tvb_length_remaining(tvb, offset) < item_value_length){ + expert_add_info_format(pinfo, il, PI_MALFORMED, PI_WARN, "The item length is invalid"); + } + item_value = proto_tree_add_item(item_tree, hf_sapdiag_item_value, tvb, offset, item_value_length, FALSE); + item_value_tree = proto_item_add_subtree(item_value, ett_sapdiag); + dissect_sapdiag_item(tvb, pinfo, item, item_value_tree, parent_tree, offset, item_type, item_id, item_sid, item_value_length); + offset+= item_value_length; + } + } +} + +static int +check_sapdiag_dp(tvbuff_t *tvb, guint32 offset){ + guint8 dp = 0; + + /* Since there's no SAP Diag mode 0xff, if the first byte is a 0xFF the + * packet probably holds an initialization DP Header */ + dp = tvb_get_guint8(tvb, offset); + if (dp == 0xFF){ + return (TRUE); + } + return (FALSE); +} + +static void +dissect_sapdiag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint32 offset = 0, payload_offset = 0; + + /* Add the protocol to the column */ + col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPDIAG"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + if (tree) { /* we are being asked for details */ + + guint8 compress; + proto_item *sapdiag = NULL, *header = NULL, *com_flag = NULL, *compression_header = NULL, *payload = NULL, *rl = NULL; + proto_tree *sapdiag_tree = NULL, *header_tree = NULL, *com_flag_tree = NULL, *compression_header_tree = NULL, *payload_tree = NULL; + tvbuff_t *next_tvb; + + /* Add the main SAPDiag subtree */ + sapdiag = proto_tree_add_item(tree, proto_sapdiag, tvb, 0, -1, FALSE); + sapdiag_tree = proto_item_add_subtree(sapdiag, ett_sapdiag); + + /* Check if the packet holds a DP Header */ + if (check_sapdiag_dp(tvb, offset)){ + dissect_sapdiag_dp(tvb, sapdiag_tree, offset); offset+= 200; + } + + /* Check for fixed error messages */ + if (tvb_strneql(tvb, 0, "**DPTMMSG**\x00\x00\xf8", 14) == 0){ + proto_tree_add_item(sapdiag_tree, hf_sapdiag_payload, tvb, offset, -1, FALSE); + return; + } + + /* Add the header subtree */ + header = proto_tree_add_item(sapdiag_tree, hf_sapdiag_header, tvb, offset, 8, FALSE); + header_tree = proto_item_add_subtree(header, ett_sapdiag); + + /* Add the fields */ + proto_tree_add_item(header_tree, hf_sapdiag_mode, tvb, offset, 1, FALSE); offset++; + + com_flag = proto_tree_add_item(header_tree, hf_sapdiag_com_flag, tvb, offset, 1, FALSE); + com_flag_tree = proto_item_add_subtree(com_flag, ett_sapdiag); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_EOS, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_EOC, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_NOP, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_EOP, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_INI, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_CAS, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_NNM, tvb, offset, 1, FALSE); + proto_tree_add_item(com_flag_tree, hf_sapdiag_com_flag_TERM_GRA, tvb, offset, 1, FALSE);offset++; + + proto_tree_add_item(header_tree, hf_sapdiag_mode_stat, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(header_tree, hf_sapdiag_err_flag, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(header_tree, hf_sapdiag_msg_type, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(header_tree, hf_sapdiag_msg_info, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(header_tree, hf_sapdiag_msg_rc, tvb, offset, 1, FALSE); offset++; + + compress = tvb_get_guint8(tvb, offset); + proto_tree_add_item(header_tree, hf_sapdiag_compress, tvb, offset, 1, FALSE); offset++; + + /* If the message is compressed */ + if ((compress == 0x01)&&(tvb_length_remaining(tvb, offset) > 0)){ + int rt = 0; + guint8 *decompressed_buffer; + guint32 reported_length = 0, uncompress_length = 0; + + /* Add the compression header subtree */ + compression_header = proto_tree_add_item(sapdiag_tree, hf_sapdiag_compress_header, tvb, offset, 8, FALSE); + compression_header_tree = proto_item_add_subtree(compression_header, ett_sapdiag); + + payload_offset = offset; + + /* Add the uncompressed length */ + reported_length = tvb_get_letohl(tvb, offset); + rl = proto_tree_add_uint(compression_header_tree, hf_sapdiag_uncomplength, tvb, offset, 4, reported_length); offset+=4; + proto_item_append_text(sapdiag, ", Uncompressed Len: %u", reported_length); + col_append_fstr(pinfo->cinfo, COL_INFO, " Uncompressed Length=%u ", reported_length); + + /* Add the algorithm */ + proto_tree_add_item(compression_header_tree, hf_sapdiag_algorithm, tvb, offset, 1, FALSE); offset++; + /* Add the magic bytes */ + proto_tree_add_item(compression_header_tree, hf_sapdiag_magic, tvb, offset, 2, FALSE); offset+=2; + /* Add the max bits */ + proto_tree_add_item(compression_header_tree, hf_sapdiag_special, tvb, offset, 1, FALSE); offset++; + + if (global_sapdiag_decompress == TRUE){ + /* Allocate the buffer only in the scope of current packet, using the reported length */ + decompressed_buffer = (guint8 *)wmem_alloc0(wmem_packet_scope(), reported_length); + if (!decompressed_buffer){ + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_ERROR, "Error allocating buffer for decompress the Diag payload"); + return; + } + + uncompress_length = reported_length; + + /* Decompress the payload */ + rt = decompress_packet(tvb_get_ptr(tvb, payload_offset, -1), + tvb_length_remaining(tvb, payload_offset), + decompressed_buffer, + &uncompress_length); + + /* Check the return code and add a expert info warning if an error occurred. The dissector continues trying to add + adding the payload, however the returned size should be 0. */ + if (rt < 0){ + expert_add_info_format(pinfo, compression_header, PI_MALFORMED, PI_WARN, "Decompression of payload failed with return code %d (%s)", rt, val_to_str(rt, hf_decompress_return_code_vals, "Unknown")); + } + + /* Check the length returned for the compression routine. If differs with the reported, use the actual one and add + an expert info warning. */ + if (uncompress_length != reported_length){ + expert_add_info_format(pinfo, rl, PI_MALFORMED, PI_WARN, "The uncompressed payload length (%d) differs with the reported length (%d)", uncompress_length, reported_length); + } + + /* Add the return code to the tree */ + proto_tree_add_int(compression_header_tree, hf_sapdiag_decompress_return_code, tvb, payload_offset, 8, rt); + + if (uncompress_length != 0){ + /* Now re-setup the tvb buffer to have the new data */ + next_tvb = tvb_new_real_data(decompressed_buffer, uncompress_length, uncompress_length); + tvb_set_child_real_data_tvbuff(tvb, next_tvb); + add_new_data_source(pinfo, next_tvb, "Uncompressed Data"); + + /* Add the payload subtree using the new tvb*/ + payload = proto_tree_add_item(sapdiag_tree, hf_sapdiag_payload, next_tvb, 0, -1, FALSE); + payload_tree = proto_item_add_subtree(payload, ett_sapdiag); + + /* Dissect the new uncompressed payload */ + dissect_sapdiag_payload(next_tvb, pinfo, payload_tree, tree, 0); + } else { + + } + } else { + /* Add the payload subtree */ + payload = proto_tree_add_item(sapdiag_tree, hf_sapdiag_payload, tvb, offset, -1, FALSE); + payload_tree = proto_item_add_subtree(payload, ett_sapdiag); + } + + /* Message encrypted with SNC */ + } else if (((compress == 0x02)||(compress == 0x03))&&(tvb_length_remaining(tvb, offset) > 0)){ + + /* Call the SNC dissector */ + dissect_sapdiag_snc_frame(tvb, pinfo, tree, offset); + + /* Uncompressed payload */ + } else { + /* Check the payload length */ + if (tvb_length_remaining(tvb, offset) > 0){ + /* Add the payload subtree */ + payload = proto_tree_add_item(sapdiag_tree, hf_sapdiag_payload, tvb, offset, -1, FALSE); + payload_tree = proto_item_add_subtree(payload, ett_sapdiag); + + /* Dissect the payload */ + dissect_sapdiag_payload(tvb, pinfo, payload_tree, tree, offset); + } + } + + } +} + +void +proto_register_sapdiag(void) +{ + static hf_register_info hf[] = { + { &hf_sapdiag_dp, + { "DP Header", "sapdiag.dp", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Diag DP Header", HFILL }}, + { &hf_sapdiag_header, + { "Header", "sapdiag.header", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Diag Header", HFILL }}, + { &hf_sapdiag_payload, + { "Message", "sapdiag.message", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Diag Message", HFILL }}, + { &hf_sapdiag_mode, + { "Mode", "sapdiag.header.mode", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Diag Mode", HFILL }}, + { &hf_sapdiag_com_flag, + { "Com Flag", "sapdiag.header.comflag", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Diag Com Flag", HFILL }}, + { &hf_sapdiag_com_flag_TERM_EOS, + { "Com Flag TERM_EOS", "sapdiag.header.comflag.TERM_EOS", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_EOS, "SAP Diag Com Flag TERM_EOS", HFILL }}, + { &hf_sapdiag_com_flag_TERM_EOC, + { "Com Flag TERM_EOC", "sapdiag.header.comflag.TERM_EOC", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_EOC, "SAP Diag Com Flag TERM_EOC", HFILL }}, + { &hf_sapdiag_com_flag_TERM_NOP, + { "Com Flag TERM_NOP", "sapdiag.header.comflag.TERM_NOP", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_NOP, "SAP Diag Com Flag TERM_NOP", HFILL }}, + { &hf_sapdiag_com_flag_TERM_EOP, + { "Com Flag TERM_EOP", "sapdiag.header.comflag.TERM_EOP", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_EOP, "SAP Diag Com Flag TERM_EOP", HFILL }}, + { &hf_sapdiag_com_flag_TERM_INI, + { "Com Flag TERM_INI", "sapdiag.header.comflag.TERM_INI", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_INI, "SAP Diag Com Flag TERM_INI", HFILL }}, + { &hf_sapdiag_com_flag_TERM_CAS, + { "Com Flag TERM_CAS", "sapdiag.header.comflag.TERM_CAS", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_CAS, "SAP Diag Com Flag TERM_CAS", HFILL }}, + { &hf_sapdiag_com_flag_TERM_NNM, + { "Com Flag TERM_NNM", "sapdiag.header.comflag.TERM_NNM", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_NNM, "SAP Diag Com Flag TERM_NNM", HFILL }}, + { &hf_sapdiag_com_flag_TERM_GRA, + { "Com Flag TERM_GRA", "sapdiag.header.comflag.TERM_GRA", FT_BOOLEAN, 8, NULL, SAPDIAG_COM_FLAG_TERM_GRA, "SAP Diag Com Flag TERM_GRA", HFILL }}, + + { &hf_sapdiag_mode_stat, + { "Mode Stat", "sapdiag.header.modestat", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Diag Mode Stat", HFILL }}, + { &hf_sapdiag_err_flag, + { "Error Flag", "sapdiag.header.errorflag", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "SAP Diag Error Flag", HFILL }}, + { &hf_sapdiag_msg_type, + { "Message Type", "sapdiag.header.msgtype", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Diag Message Type", HFILL }}, + { &hf_sapdiag_msg_info, + { "Message Info", "sapdiag.header.msginfo", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Diag Message Info", HFILL }}, + { &hf_sapdiag_msg_rc, + { "Message Rc", "sapdiag.header.msgrc", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Diag Message RC", HFILL }}, + { &hf_sapdiag_compress, + { "Compress", "sapdiag.header.compress", FT_UINT8, BASE_HEX, hf_sapdiag_compress_vals, 0x0, "SAP Diag Compress", HFILL }}, + /* Compression header */ + { &hf_sapdiag_compress_header, + { "Compression Header", "sapdiag.header.compression", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Diag Compression Header", HFILL }}, + { &hf_sapdiag_uncomplength, + { "Uncompressed Length", "sapdiag.header.compression.uncomplength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Diag Uncompressed Message Length", HFILL }}, + { &hf_sapdiag_algorithm, + { "Compression Algorithm", "sapdiag.header.compression.algorithm", FT_UINT8, BASE_HEX, hf_sapdiag_algorithm_vals, 0x0, "SAP Diag Compression Algorithm", HFILL }}, + { &hf_sapdiag_magic, + { "Magic Bytes", "sapdiag.header.compression.magic", FT_UINT16, BASE_HEX, NULL, 0x0, "SAP Diag Compression Magic Bytes", HFILL }}, + { &hf_sapdiag_special, + { "Special", "sapdiag.header.compression.special", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Diag Special", HFILL }}, + { &hf_sapdiag_decompress_return_code, + { "Decompress Return Code", "sapdiag.header.compression.returncode", FT_INT8, BASE_DEC, hf_decompress_return_code_vals, 0x0, "SAP Diag Decompression routine return code", HFILL }}, + /* SAPDiag Messages */ + { &hf_sapdiag_item, + { "Item", "sapdiag.item", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Diag Item", HFILL }}, + { &hf_sapdiag_item_type, + { "Type", "sapdiag.item.type", FT_UINT8, BASE_HEX, hf_sapdiag_item_type_vals, 0x0, "SAP Diag Item Type", HFILL }}, + { &hf_sapdiag_item_id, + { "ID", "sapdiag.item.id", FT_UINT8, BASE_HEX, hf_sapdiag_item_id_vals, 0x0, "SAP Diag Item ID", HFILL }}, + { &hf_sapdiag_item_sid, + { "SID", "sapdiag.item.sid", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Diag Item SID", HFILL }}, + { &hf_sapdiag_item_length, + { "Length", "sapdiag.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP Diag Item Length", HFILL }}, + { &hf_sapdiag_item_value, + { "Value", "sapdiag.item.value", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Diag Item Value", HFILL }}, + /* SAPDiag DP Header */ + { &hf_sapdiag_dp_request_id, + { "Request ID", "sapdiag.dp.reqid", FT_INT32, BASE_DEC, hf_sapdiag_dp_request_id_vals, 0x0, "SAP Diag DP Request ID", HFILL }}, + { &hf_sapdiag_dp_retcode, + { "Retcode", "sapdiag.dp.retcode", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Diag DP Retcode", HFILL }}, + { &hf_sapdiag_dp_sender_id, + { "Sender ID", "sapdiag.dp.senderid", FT_UINT8, BASE_HEX, hf_sapdiag_dp_sender_id_vals, 0x0, "SAP Diag DP Sender ID", HFILL }}, + { &hf_sapdiag_dp_action_type, + { "Action type", "sapdiag.dp.actiontype", FT_UINT8, BASE_HEX, hf_sapdiag_dp_action_type_vals, 0x0, "SAP Diag DP Action Type", HFILL }}, + { &hf_sapdiag_dp_req_info, + { "Request Info", "sapdiag.dp.reqinfo", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Diag DP Request Info", HFILL }}, + /* Request Info Flag */ + { &hf_sapdiag_dp_req_info_LOGIN, + { "Login Flag", "sapdiag.dp.reqinfo.login", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_LOGIN, "SAP Diag DP Request Info Login Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_LOGOFF, + { "Logoff Flag", "sapdiag.dp.reqinfo.logoff", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_LOGOFF, "SAP Diag DP Request Info Logoff Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_SHUTDOWN, + { "Shutdown Flag", "sapdiag.dp.reqinfo.shutdown", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_SHUTDOWN, "SAP Diag DP Request Info Shutdown Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_GRAPHIC_TM, + { "Graphic TM Flag", "sapdiag.dp.reqinfo.graphictm", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_GRAPHIC_TM, "SAP Diag DP Request Info Graphic TM Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_ALPHA_TM, + { "Alpha TM Flag", "sapdiag.dp.reqinfo.alphatm", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_ALPHA_TM, "SAP Diag DP Request Info Alpha TM Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_ERROR_FROM_APPC, + { "Error from APPC Flag", "sapdiag.dp.reqinfo.errorfromappc", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_ERROR_FROM_APPC, "SAP Diag DP Request Info Error from APPC Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_CANCELMODE, + { "Cancel Mode Flag", "sapdiag.dp.reqinfo.cancelmode", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_CANCELMODE, "SAP Diag DP Request Info Cancel Mode Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_MSG_WITH_REQ_BUF, + { "Msg with Req Buf Flag", "sapdiag.dp.reqinfo.msg_with_req_buf", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_MSG_WITH_REQ_BUF, "SAP Diag DP Request Info Msg with Req Buf Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_MSG_WITH_OH, + { "Msg with OH Flag", "sapdiag.dp.reqinfo.msg_with_oh", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_MSG_WITH_OH, "SAP Diag DP Request Info Msg with OH Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_BUFFER_REFRESH, + { "Buffer Refresh Flag", "sapdiag.dp.reqinfo.buffer_refresh", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_BUFFER_REFRESH, "SAP Diag DP Request Info Buffer Refresh Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_BTC_SCHEDULER, + { "BTC Scheduler Flag", "sapdiag.dp.reqinfo.btc_scheduler", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_BTC_SCHEDULER, "SAP Diag DP Request Info BTC Scheduler Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_APPC_SERVER_DOWN, + { "APPC Server Down Flag", "sapdiag.dp.reqinfo.appc_server_down", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_APPC_SERVER_DOWN, "SAP Diag DP Request Info APPC Server Down Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_MS_ERROR, + { "MS Error Flag", "sapdiag.dp.reqinfo.ms_error", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_MS_ERROR, "SAP Diag DP Request Info MS Error Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_SET_SYSTEM_USER, + { "Set System User Flag", "sapdiag.dp.reqinfo.set_system_user", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_SET_SYSTEM_USER, "SAP Diag DP Request Info Set System User Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_CANT_HANDLE_REQ, + { "DP Can't handle req Flag", "sapdiag.dp.reqinfo.dp_cant_hanlde_req", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_CANT_HANDLE_REQ, "SAP Diag DP Request DP Can't handle req Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_AUTO_ABAP, + { "DP Auto ABAP Flag", "sapdiag.dp.reqinfo.dp_auto_abap", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_AUTO_ABAP, "SAP Diag DP Request Info DP Auto ABAP Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_APPL_SERV_INFO, + { "DP Appl Serv Info Flag", "sapdiag.dp.reqinfo.dp_appl_serv_info", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_APPL_SERV_INFO, "SAP Diag DP Request Info DP Appl Serv Info Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_ADMIN, + { "DP Admin Flag", "sapdiag.dp.reqinfo.dp_admin", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_ADMIN, "SAP Diag DP Request Info DP Admin Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_SPOOL_ALRM, + { "DP Spool Alrm Flag", "sapdiag.dp.reqinfo.dp_spool_alrm", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_SPOOL_ALRM, "SAP Diag DP Request Info DP Spool Alrm Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_HAND_SHAKE, + { "DP Hand Shake Flag", "sapdiag.dp.reqinfo.dp_hand_shake", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_HAND_SHAKE, "SAP Diag DP Request Info DP Hand Shake Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_CANCEL_PRIV, + { "DP Cancel Privileges Flag", "sapdiag.dp.reqinfo.dp_cancel_priv", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_CANCEL_PRIV, "SAP Diag DP Request Info DP Cancel Privileges Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_RAISE_TIMEOUT, + { "DP Raise Timeout Flag", "sapdiag.dp.reqinfo.dp_raise_timeout", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_RAISE_TIMEOUT, "SAP Diag DP Request Info DP Raise Timeout Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_NEW_MODE, + { "DP New Mode Flag", "sapdiag.dp.reqinfo.dp_new_mode", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_NEW_MODE, "SAP Diag DP Request Info DP New Mode Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_SOFT_CANCEL, + { "DP Soft Cancel Flag", "sapdiag.dp.reqinfo.dp_soft_cancel", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_SOFT_CANCEL, "SAP Diag DP Request Info DP Soft Cancel Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_TM_INPUT, + { "DP TM Input Flag", "sapdiag.dp.reqinfo.dp_tm_input", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_TM_INPUT, "SAP Diag DP Request Info DP TM Input Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_TM_OUTPUT, + { "DP TM Output Flag", "sapdiag.dp.reqinfo.dp_tm_output", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_TM_OUTPUT, "SAP Diag DP Request Info DP TM Output Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_ASYNC_RFC, + { "DP Async RFC Flag", "sapdiag.dp.reqinfo.dp_async_rfc", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_ASYNC_RFC, "SAP Diag DP Request Info DP Async RFC Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_ICM_EVENT, + { "DP ICM Event Flag", "sapdiag.dp.reqinfo.dp_icm_event", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_ICM_EVENT, "SAP Diag DP Request Info DP ICM Event Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_AUTO_TH, + { "DP Auto TH Flag", "sapdiag.dp.reqinfo.dp_auto_th", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_AUTO_TH, "SAP Diag DP Request Info DP Auto TH Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_RFC_CANCEL, + { "DP RFC Cancel Flag", "sapdiag.dp.reqinfo.dp_rfc_cancel", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_RFC_CANCEL, "SAP Diag DP Request Info DP RFC Cancel Flag", HFILL }}, + { &hf_sapdiag_dp_req_info_DP_MS_ADM, + { "DP MS Adm Flag", "sapdiag.dp.reqinfo.dp_ms_adm", FT_BOOLEAN, 8, NULL, SAPDIAG_DP_REQ_INFO_DP_MS_ADM, "SAP Diag DP Request Info DP MS Adm Flag", HFILL }}, + { &hf_sapdiag_dp_tid, + { "TID", "sapdiag.dp.tid", FT_INT32, BASE_DEC, NULL, 0x0, "SAP Diag DP TID", HFILL }}, + { &hf_sapdiag_dp_uid, + { "UID", "sapdiag.dp.uid", FT_INT16, BASE_DEC, NULL, 0x0, "SAP Diag DP UID", HFILL }}, + { &hf_sapdiag_dp_mode, + { "Mode", "sapdiag.dp.mode", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Diag DP Mode", HFILL }}, + { &hf_sapdiag_dp_wp_id, + { "WP Id", "sapdiag.dp.wpid", FT_INT32, BASE_DEC, NULL, 0x0, "SAP Diag DP WP Id", HFILL }}, + { &hf_sapdiag_dp_wp_ca_blk, + { "WP Ca Blk", "sapdiag.dp.wpcablk", FT_INT32, BASE_DEC, NULL, 0x0, "SAP Diag DP WP Ca Blk", HFILL }}, + { &hf_sapdiag_dp_appc_ca_blk, + { "APPC Ca Blk", "sapdiag.dp.appccablk", FT_INT32, BASE_DEC, NULL, 0x0, "SAP Diag DP Appc Ca Blk", HFILL }}, + { &hf_sapdiag_dp_len, + { "Len", "sapdiag.dp.len", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Diag DP Len", HFILL }}, + { &hf_sapdiag_dp_new_stat, + { "New Stat", "sapdiag.dp.newstat", FT_UINT8, BASE_HEX, hf_sapdiag_dp_new_stat_vals, 0x0, "SAP Diag DP New Stat", HFILL }}, + { &hf_sapdiag_dp_rq_id, + { "Request ID", "sapdiag.dp.rqid", FT_INT16, BASE_DEC, NULL, 0x0, "SAP Diag DP Request ID", HFILL }}, + { &hf_sapdiag_dp_terminal, + { "Terminal", "sapdiag.dp.terminal", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Diag DP Terminal", HFILL }}, + + /* SAP Diag Support Bits */ + { &hf_SAPDIAG_SUPPORT_BIT_PROGRESS_INDICATOR, + { "Support Bit PROGRESS_INDICATOR", "sapdiag.diag.supportbits.PROGRESS_INDICATOR", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_PROGRESS_INDICATOR, "SAP Diag Support Bit PROGRESS_INDICATOR", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_LABELS, + { "Support Bit SAPGUI_LABELS", "sapdiag.diag.supportbits.SAPGUI_LABELS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_LABELS, "SAP Diag Support Bit SAPGUI_LABELS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_DIAGVERSION, + { "Support Bit SAPGUI_DIAGVERSION", "sapdiag.diag.supportbits.SAPGUI_DIAGVERSION", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_DIAGVERSION, "SAP Diag Support Bit SAPGUI_DIAGVERSION", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_SELECT_RECT, + { "Support Bit SAPGUI_SELECT_RECT", "sapdiag.diag.supportbits.SAPGUI_SELECT_RECT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_SELECT_RECT, "SAP Diag Support Bit SAPGUI_SELECT_RECT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_SYMBOL_RIGHT, + { "Support Bit SAPGUI_SYMBOL_RIGHT", "sapdiag.diag.supportbits.SAPGUI_SYMBOL_RIGHT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_SYMBOL_RIGHT, "SAP Diag Support Bit SAPGUI_SYMBOL_RIGHT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_FONT_METRIC, + { "Support Bit SAPGUI_FONT_METRIC", "sapdiag.diag.supportbits.SAPGUI_FONT_METRIC", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_FONT_METRIC, "SAP Diag Support Bit SAPGUI_FONT_METRIC", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_COMPR_ENHANCED, + { "Support Bit SAPGUI_COMPR_ENHANCED", "sapdiag.diag.supportbits.SAPGUI_COMPR_ENHANCED", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_COMPR_ENHANCED, "SAP Diag Support Bit SAPGUI_COMPR_ENHANCED", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_IMODE, + { "Support Bit SAPGUI_IMODE", "sapdiag.diag.supportbits.SAPGUI_IMODE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_IMODE, "SAP Diag Support Bit SAPGUI_IMODE", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_LONG_MESSAGE, + { "Support Bit SAPGUI_LONG_MESSAGE", "sapdiag.diag.supportbits.SAPGUI_LONG_MESSAGE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_LONG_MESSAGE, "SAP Diag Support Bit SAPGUI_LONG_MESSAGE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_TABLE, + { "Support Bit SAPGUI_TABLE", "sapdiag.diag.supportbits.SAPGUI_TABLE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_TABLE, "SAP Diag Support Bit SAPGUI_TABLE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_FOCUS_1, + { "Support Bit SAPGUI_FOCUS_1", "sapdiag.diag.supportbits.SAPGUI_FOCUS_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_FOCUS_1, "SAP Diag Support Bit SAPGUI_FOCUS_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_PUSHBUTTON_1, + { "Support Bit SAPGUI_PUSHBUTTON_1", "sapdiag.diag.supportbits.SAPGUI_PUSHBUTTON_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_PUSHBUTTON_1, "SAP Diag Support Bit SAPGUI_PUSHBUTTON_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UPPERCASE, + { "Support Bit UPPERCASE", "sapdiag.diag.supportbits.UPPERCASE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UPPERCASE, "SAP Diag Support Bit UPPERCASE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SAPGUI_TABPROPERTY, + { "Support Bit SAPGUI_TABPROPERTY", "sapdiag.diag.supportbits.SAPGUI_TABPROPERTY", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SAPGUI_TABPROPERTY, "SAP Diag Support Bit SAPGUI_TABPROPERTY", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_INPUT_UPPERCASE, + { "Support Bit INPUT_UPPERCASE", "sapdiag.diag.supportbits.INPUT_UPPERCASE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_INPUT_UPPERCASE, "SAP Diag Support Bit INPUT_UPPERCASE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_RFC_DIALOG, + { "Support Bit RFC_DIALOG", "sapdiag.diag.supportbits.RFC_DIALOG", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RFC_DIALOG, "SAP Diag Support Bit RFC_DIALOG", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_LIST_HOTSPOT, + { "Support Bit LIST_HOTSPOT", "sapdiag.diag.supportbits.LIST_HOTSPOT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_LIST_HOTSPOT, "SAP Diag Support Bit LIST_HOTSPOT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_FKEY_TABLE, + { "Support Bit FKEY_TABLE", "sapdiag.diag.supportbits.FKEY_TABLE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_FKEY_TABLE, "SAP Diag Support Bit FKEY_TABLE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MENU_SHORTCUT, + { "Support Bit MENU_SHORTCUT", "sapdiag.diag.supportbits.MENU_SHORTCUT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MENU_SHORTCUT, "SAP Diag Support Bit MENU_SHORTCUT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_STOP_TRANS, + { "Support Bit STOP_TRANS", "sapdiag.diag.supportbits.STOP_TRANS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_STOP_TRANS, "SAP Diag Support Bit STOP_TRANS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_FULL_MENU, + { "Support Bit FULL_MENU", "sapdiag.diag.supportbits.FULL_MENU", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_FULL_MENU, "SAP Diag Support Bit FULL_MENU", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_OBJECT_NAMES, + { "Support Bit OBJECT_NAMES", "sapdiag.diag.supportbits.OBJECT_NAMES", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_OBJECT_NAMES, "SAP Diag Support Bit OBJECT_NAMES", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONTAINER_TYPE, + { "Support Bit CONTAINER_TYPE", "sapdiag.diag.supportbits.CONTAINER_TYPE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONTAINER_TYPE, "SAP Diag Support Bit CONTAINER_TYPE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DLGH_FLAGS, + { "Support Bit DLGH_FLAGS", "sapdiag.diag.supportbits.DLGH_FLAGS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DLGH_FLAGS, "SAP Diag Support Bit DLGH_FLAGS", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_APPL_MNU, + { "Support Bit APPL_MNU", "sapdiag.diag.supportbits.APPL_MNU", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_APPL_MNU, "SAP Diag Support Bit APPL_MNU", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO, + { "Support Bit MESSAGE_INFO", "sapdiag.diag.supportbits.MESSAGE_INFO", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MESSAGE_INFO, "SAP Diag Support Bit MESSAGE_INFO", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MESDUM_FLAG1, + { "Support Bit MESDUM_FLAG1", "sapdiag.diag.supportbits.MESDUM_FLAG1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MESDUM_FLAG1, "SAP Diag Support Bit MESDUM_FLAG1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB, + { "Support Bit TABSEL_ATTRIB", "sapdiag.diag.supportbits.TABSEL_ATTRIB", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB, "SAP Diag Support Bit TABSEL_ATTRIB", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUIAPI, + { "Support Bit GUIAPI", "sapdiag.diag.supportbits.GUIAPI", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUIAPI, "SAP Diag Support Bit GUIAPI", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NOGRAPH, + { "Support Bit NOGRAPH", "sapdiag.diag.supportbits.NOGRAPH", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NOGRAPH, "SAP Diag Support Bit NOGRAPH", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NOMESSAGES, + { "Support Bit NOMESSAGES", "sapdiag.diag.supportbits.NOMESSAGES", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NOMESSAGES, "SAP Diag Support Bit NOMESSAGES", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NORABAX, + { "Support Bit NORABAX", "sapdiag.diag.supportbits.NORABAX", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NORABAX, "SAP Diag Support Bit NORABAX", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_NOSYSMSG, + { "Support Bit NOSYSMSG", "sapdiag.diag.supportbits.NOSYSMSG", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NOSYSMSG, "SAP Diag Support Bit NOSYSMSG", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NOSAPSCRIPT, + { "Support Bit NOSAPSCRIPT", "sapdiag.diag.supportbits.NOSAPSCRIPT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NOSAPSCRIPT, "SAP Diag Support Bit NOSAPSCRIPT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NORFC, + { "Support Bit NORFC", "sapdiag.diag.supportbits.NORFC", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NORFC, "SAP Diag Support Bit NORFC", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NEW_BSD_JUSTRIGHT, + { "Support Bit NEW_BSD_JUSTRIGHT", "sapdiag.diag.supportbits.NEW_BSD_JUSTRIGHT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NEW_BSD_JUSTRIGHT, "SAP Diag Support Bit NEW_BSD_JUSTRIGHT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MESSAGE_VARS, + { "Support Bit MESSAGE_VARS", "sapdiag.diag.supportbits.MESSAGE_VARS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MESSAGE_VARS, "SAP Diag Support Bit MESSAGE_VARS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_OCX_SUPPORT, + { "Support Bit OCX_SUPPORT", "sapdiag.diag.supportbits.OCX_SUPPORT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_OCX_SUPPORT, "SAP Diag Support Bit OCX_SUPPORT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SCROLL_INFOS, + { "Support Bit SCROLL_INFOS", "sapdiag.diag.supportbits.SCROLL_INFOS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SCROLL_INFOS, "SAP Diag Support Bit SCROLL_INFOS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABLE_SIZE_OK, + { "Support Bit TABLE_SIZE_OK", "sapdiag.diag.supportbits.TABLE_SIZE_OK", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABLE_SIZE_OK, "SAP Diag Support Bit TABLE_SIZE_OK", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO2, + { "Support Bit MESSAGE_INFO2", "sapdiag.diag.supportbits.MESSAGE_INFO2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MESSAGE_INFO2, "SAP Diag Support Bit MESSAGE_INFO2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_VARINFO_OKCODE, + { "Support Bit VARINFO_OKCODE", "sapdiag.diag.supportbits.VARINFO_OKCODE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_VARINFO_OKCODE, "SAP Diag Support Bit VARINFO_OKCODE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CURR_TCODE, + { "Support Bit CURR_TCODE", "sapdiag.diag.supportbits.CURR_TCODE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CURR_TCODE, "SAP Diag Support Bit CURR_TCODE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONN_WSIZE, + { "Support Bit CONN_WSIZE", "sapdiag.diag.supportbits.CONN_WSIZE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONN_WSIZE, "SAP Diag Support Bit CONN_WSIZE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_PUSHBUTTON_2, + { "Support Bit PUSHBUTTON_2", "sapdiag.diag.supportbits.PUSHBUTTON_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_PUSHBUTTON_2, "SAP Diag Support Bit PUSHBUTTON_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABSTRIP, + { "Support Bit TABSTRIP", "sapdiag.diag.supportbits.TABSTRIP", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABSTRIP, "SAP Diag Support Bit TABSTRIP", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_1, + { "Support Bit UNKNOWN_1", "sapdiag.diag.supportbits.UNKNOWN_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNKNOWN_1, "SAP Diag Support Bit UNKNOWN_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABSCROLL_INFOS, + { "Support Bit TABSCROLL_INFOS", "sapdiag.diag.supportbits.TABSCROLL_INFOS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABSCROLL_INFOS, "SAP Diag Support Bit TABSCROLL_INFOS", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_TABLE_FIELD_NAMES, + { "Support Bit TABLE_FIELD_NAMES", "sapdiag.diag.supportbits.TABLE_FIELD_NAMES", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABLE_FIELD_NAMES, "SAP Diag Support Bit TABLE_FIELD_NAMES", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NEW_MODE_REQUEST, + { "Support Bit NEW_MODE_REQUEST", "sapdiag.diag.supportbits.NEW_MODE_REQUEST", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NEW_MODE_REQUEST, "SAP Diag Support Bit NEW_MODE_REQUEST", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_RFCBLOB_DIAG_PARSER, + { "Support Bit RFCBLOB_DIAG_PARSER", "sapdiag.diag.supportbits.RFCBLOB_DIAG_PARSER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RFCBLOB_DIAG_PARSER, "SAP Diag Support Bit RFCBLOB_DIAG_PARSER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MULTI_LOGIN_USER, + { "Support Bit MULTI_LOGIN_USER", "sapdiag.diag.supportbits.MULTI_LOGIN_USER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MULTI_LOGIN_USER, "SAP Diag Support Bit MULTI_LOGIN_USER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONTROL_CONTAINER, + { "Support Bit CONTROL_CONTAINER", "sapdiag.diag.supportbits.CONTROL_CONTAINER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONTROL_CONTAINER, "SAP Diag Support Bit CONTROL_CONTAINER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_APPTOOLBAR_FIXED, + { "Support Bit APPTOOLBAR_FIXED", "sapdiag.diag.supportbits.APPTOOLBAR_FIXED", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_APPTOOLBAR_FIXED, "SAP Diag Support Bit APPTOOLBAR_FIXED", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_USER_CHECKED, + { "Support Bit R3INFO_USER_CHECKED", "sapdiag.diag.supportbits.R3INFO_USER_CHECKED", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_USER_CHECKED, "SAP Diag Support Bit R3INFO_USER_CHECKED", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NEED_STDDYNPRO, + { "Support Bit NEED_STDDYNPRO", "sapdiag.diag.supportbits.NEED_STDDYNPRO", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NEED_STDDYNPRO, "SAP Diag Support Bit NEED_STDDYNPRO", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_TYPE_SERVER, + { "Support Bit TYPE_SERVER", "sapdiag.diag.supportbits.TYPE_SERVER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TYPE_SERVER, "SAP Diag Support Bit TYPE_SERVER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_COMBOBOX, + { "Support Bit COMBOBOX", "sapdiag.diag.supportbits.COMBOBOX", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_COMBOBOX, "SAP Diag Support Bit COMBOBOX", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_INPUT_REQUIRED, + { "Support Bit INPUT_REQUIRED", "sapdiag.diag.supportbits.INPUT_REQUIRED", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_INPUT_REQUIRED, "SAP Diag Support Bit INPUT_REQUIRED", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ISO_LANGUAGE, + { "Support Bit ISO_LANGUAGE", "sapdiag.diag.supportbits.ISO_LANGUAGE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ISO_LANGUAGE, "SAP Diag Support Bit ISO_LANGUAGE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_COMBOBOX_TABLE, + { "Support Bit COMBOBOX_TABLE", "sapdiag.diag.supportbits.COMBOBOX_TABLE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_COMBOBOX_TABLE, "SAP Diag Support Bit COMBOBOX_TABLE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS, + { "Support Bit R3INFO_FLAGS", "sapdiag.diag.supportbits.R3INFO_FLAGS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS, "SAP Diag Support Bit R3INFO_FLAGS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CHECKRADIO_EVENTS, + { "Support Bit CHECKRADIO_EVENTS", "sapdiag.diag.supportbits.CHECKRADIO_EVENTS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CHECKRADIO_EVENTS, "SAP Diag Support Bit CHECKRADIO_EVENTS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_USERID, + { "Support Bit R3INFO_USERID", "sapdiag.diag.supportbits.R3INFO_USERID", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_USERID, "SAP Diag Support Bit R3INFO_USERID", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_ROLLCOUNT, + { "Support Bit R3INFO_ROLLCOUNT", "sapdiag.diag.supportbits.R3INFO_ROLLCOUNT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_ROLLCOUNT, "SAP Diag Support Bit R3INFO_ROLLCOUNT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_USER_TURNTIME2, + { "Support Bit USER_TURNTIME2", "sapdiag.diag.supportbits.USER_TURNTIME2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_USER_TURNTIME2, "SAP Diag Support Bit USER_TURNTIME2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NUM_FIELD, + { "Support Bit NUM_FIELD", "sapdiag.diag.supportbits.NUM_FIELD", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NUM_FIELD, "SAP Diag Support Bit NUM_FIELD", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_WIN16, + { "Support Bit WIN16", "sapdiag.diag.supportbits.WIN16", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_WIN16, "SAP Diag Support Bit WIN16", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONTEXT_MENU, + { "Support Bit CONTEXT_MENU", "sapdiag.diag.supportbits.CONTEXT_MENU", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONTEXT_MENU, "SAP Diag Support Bit CONTEXT_MENU", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SCROLLABLE_TABSTRIP_PAGE, + { "Support Bit SCROLLABLE_TABSTRIP_PAGE", "sapdiag.diag.supportbits.SCROLLABLE_TABSTRIP_PAGE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SCROLLABLE_TABSTRIP_PAGE, "SAP Diag Support Bit SCROLLABLE_TABSTRIP_PAGE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION, + { "Support Bit EVENT_DESCRIPTION", "sapdiag.diag.supportbits.EVENT_DESCRIPTION", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION, "SAP Diag Support Bit EVENT_DESCRIPTION", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_LABEL_OWNER, + { "Support Bit LABEL_OWNER", "sapdiag.diag.supportbits.LABEL_OWNER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_LABEL_OWNER, "SAP Diag Support Bit LABEL_OWNER", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_CLICKABLE_FIELD, + { "Support Bit CLICKABLE_FIELD", "sapdiag.diag.supportbits.CLICKABLE_FIELD", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CLICKABLE_FIELD, "SAP Diag Support Bit CLICKABLE_FIELD", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_PROPERTY_BAG, + { "Support Bit PROPERTY_BAG", "sapdiag.diag.supportbits.PROPERTY_BAG", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_PROPERTY_BAG, "SAP Diag Support Bit PROPERTY_BAG", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNUSED_1, + { "Support Bit UNUSED_1", "sapdiag.diag.supportbits.UNUSED_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNUSED_1, "SAP Diag Support Bit UNUSED_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABLE_ROW_REFERENCES_2, + { "Support Bit TABLE_ROW_REFERENCES_2", "sapdiag.diag.supportbits.TABLE_ROW_REFERENCES_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABLE_ROW_REFERENCES_2, "SAP Diag Support Bit TABLE_ROW_REFERENCES_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_PROPFONT_VALID, + { "Support Bit PROPFONT_VALID", "sapdiag.diag.supportbits.PROPFONT_VALID", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_PROPFONT_VALID, "SAP Diag Support Bit PROPFONT_VALID", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER, + { "Support Bit VARINFO_CONTAINER", "sapdiag.diag.supportbits.VARINFO_CONTAINER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER, "SAP Diag Support Bit VARINFO_CONTAINER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_IMODEUUID, + { "Support Bit R3INFO_IMODEUUID", "sapdiag.diag.supportbits.R3INFO_IMODEUUID", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_IMODEUUID, "SAP Diag Support Bit R3INFO_IMODEUUID", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NOTGUI, + { "Support Bit NOTGUI", "sapdiag.diag.supportbits.NOTGUI", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NOTGUI, "SAP Diag Support Bit NOTGUI", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_WAN, + { "Support Bit WAN", "sapdiag.diag.supportbits.WAN", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_WAN, "SAP Diag Support Bit WAN", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_XML_BLOBS, + { "Support Bit XML_BLOBS", "sapdiag.diag.supportbits.XML_BLOBS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XML_BLOBS, "SAP Diag Support Bit XML_BLOBS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_RFC_QUEUE, + { "Support Bit RFC_QUEUE", "sapdiag.diag.supportbits.RFC_QUEUE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RFC_QUEUE, "SAP Diag Support Bit RFC_QUEUE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_RFC_COMPRESS, + { "Support Bit RFC_COMPRESS", "sapdiag.diag.supportbits.RFC_COMPRESS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RFC_COMPRESS, "SAP Diag Support Bit RFC_COMPRESS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_JAVA_BEANS, + { "Support Bit JAVA_BEANS", "sapdiag.diag.supportbits.JAVA_BEANS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_JAVA_BEANS, "SAP Diag Support Bit JAVA_BEANS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND, + { "Support Bit DPLOADONDEMAND", "sapdiag.diag.supportbits.DPLOADONDEMAND", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND, "SAP Diag Support Bit DPLOADONDEMAND", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CTL_PROPCACHE, + { "Support Bit CTL_PROPCACHE", "sapdiag.diag.supportbits.CTL_PROPCACHE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CTL_PROPCACHE, "SAP Diag Support Bit CTL_PROPCACHE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID, + { "Support Bit ENJOY_IMODEUUID", "sapdiag.diag.supportbits.ENJOY_IMODEUUID", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID, "SAP Diag Support Bit ENJOY_IMODEUUID", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_RFC_ASYNC_BLOB, + { "Support Bit RFC_ASYNC_BLOB", "sapdiag.diag.supportbits.RFC_ASYNC_BLOB", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RFC_ASYNC_BLOB, "SAP Diag Support Bit RFC_ASYNC_BLOB", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_KEEP_SCROLLPOS, + { "Support Bit KEEP_SCROLLPOS", "sapdiag.diag.supportbits.KEEP_SCROLLPOS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_KEEP_SCROLLPOS, "SAP Diag Support Bit KEEP_SCROLLPOS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNUSED_2, + { "Support Bit UNUSED_2", "sapdiag.diag.supportbits.UNUSED_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNUSED_2, "SAP Diag Support Bit UNUSED_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNUSED_3, + { "Support Bit UNUSED_3", "sapdiag.diag.supportbits.UNUSED_3", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNUSED_3, "SAP Diag Support Bit UNUSED_3", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_XML_PROPERTIES, + { "Support Bit XML_PROPERTIES", "sapdiag.diag.supportbits.XML_PROPERTIES", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XML_PROPERTIES, "SAP Diag Support Bit XML_PROPERTIES", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNUSED_4, + { "Support Bit UNUSED_4", "sapdiag.diag.supportbits.UNUSED_4", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNUSED_4, "SAP Diag Support Bit UNUSED_4", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_HEX_FIELD, + { "Support Bit HEX_FIELD", "sapdiag.diag.supportbits.HEX_FIELD", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_HEX_FIELD, "SAP Diag Support Bit HEX_FIELD", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_HAS_CACHE, + { "Support Bit HAS_CACHE", "sapdiag.diag.supportbits.HAS_CACHE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_HAS_CACHE, "SAP Diag Support Bit HAS_CACHE", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE, + { "Support Bit XML_PROP_TABLE", "sapdiag.diag.supportbits.XML_PROP_TABLE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE, "SAP Diag Support Bit XML_PROP_TABLE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNUSED_5, + { "Support Bit UNUSED_5", "sapdiag.diag.supportbits.UNUSED_5", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNUSED_5, "SAP Diag Support Bit UNUSED_5", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID2, + { "Support Bit ENJOY_IMODEUUID2", "sapdiag.diag.supportbits.ENJOY_IMODEUUID2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID2, "SAP Diag Support Bit ENJOY_IMODEUUID2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ITS, + { "Support Bit ITS", "sapdiag.diag.supportbits.ITS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ITS, "SAP Diag Support Bit ITS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NO_EASYACCESS, + { "Support Bit NO_EASYACCESS", "sapdiag.diag.supportbits.NO_EASYACCESS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NO_EASYACCESS, "SAP Diag Support Bit NO_EASYACCESS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_PROPERTYPUMP, + { "Support Bit PROPERTYPUMP", "sapdiag.diag.supportbits.PROPERTYPUMP", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_PROPERTYPUMP, "SAP Diag Support Bit PROPERTYPUMP", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_COOKIE, + { "Support Bit COOKIE", "sapdiag.diag.supportbits.COOKIE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_COOKIE, "SAP Diag Support Bit COOKIE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNUSED_6, + { "Support Bit UNUSED_6", "sapdiag.diag.supportbits.UNUSED_6", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNUSED_6, "SAP Diag Support Bit UNUSED_6", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_SUPPBIT_AREA_SIZE, + { "Support Bit SUPPBIT_AREA_SIZE", "sapdiag.diag.supportbits.SUPPBIT_AREA_SIZE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SUPPBIT_AREA_SIZE, "SAP Diag Support Bit SUPPBIT_AREA_SIZE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND_WRITE, + { "Support Bit DPLOADONDEMAND_WRITE", "sapdiag.diag.supportbits.DPLOADONDEMAND_WRITE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DPLOADONDEMAND_WRITE, "SAP Diag Support Bit DPLOADONDEMAND_WRITE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS, + { "Support Bit CONTROL_FOCUS", "sapdiag.diag.supportbits.CONTROL_FOCUS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS, "SAP Diag Support Bit CONTROL_FOCUS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENTRY_HISTORY, + { "Support Bit ENTRY_HISTORY", "sapdiag.diag.supportbits.ENTRY_HISTORY", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENTRY_HISTORY, "SAP Diag Support Bit ENTRY_HISTORY", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_AUTO_CODEPAGE, + { "Support Bit AUTO_CODEPAGE", "sapdiag.diag.supportbits.AUTO_CODEPAGE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_AUTO_CODEPAGE, "SAP Diag Support Bit AUTO_CODEPAGE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CACHED_VSETS, + { "Support Bit CACHED_VSETS", "sapdiag.diag.supportbits.CACHED_VSETS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CACHED_VSETS, "SAP Diag Support Bit CACHED_VSETS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_EMERGENCY_REPAIR, + { "Support Bit EMERGENCY_REPAIR", "sapdiag.diag.supportbits.EMERGENCY_REPAIR", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_EMERGENCY_REPAIR, "SAP Diag Support Bit EMERGENCY_REPAIR", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_AREA2FRONT, + { "Support Bit AREA2FRONT", "sapdiag.diag.supportbits.AREA2FRONT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_AREA2FRONT, "SAP Diag Support Bit AREA2FRONT", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_SCROLLBAR_WIDTH, + { "Support Bit SCROLLBAR_WIDTH", "sapdiag.diag.supportbits.SCROLLBAR_WIDTH", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SCROLLBAR_WIDTH, "SAP Diag Support Bit SCROLLBAR_WIDTH", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_AUTORESIZE, + { "Support Bit AUTORESIZE", "sapdiag.diag.supportbits.AUTORESIZE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_AUTORESIZE, "SAP Diag Support Bit AUTORESIZE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_EDIT_VARLEN, + { "Support Bit EDIT_VARLEN", "sapdiag.diag.supportbits.EDIT_VARLEN", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_EDIT_VARLEN, "SAP Diag Support Bit EDIT_VARLEN", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_WORKPLACE, + { "Support Bit WORKPLACE", "sapdiag.diag.supportbits.WORKPLACE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_WORKPLACE, "SAP Diag Support Bit WORKPLACE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_PRINTDATA, + { "Support Bit PRINTDATA", "sapdiag.diag.supportbits.PRINTDATA", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_PRINTDATA, "SAP Diag Support Bit PRINTDATA", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_2, + { "Support Bit UNKNOWN_2", "sapdiag.diag.supportbits.UNKNOWN_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNKNOWN_2, "SAP Diag Support Bit UNKNOWN_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SINGLE_SESSION, + { "Support Bit SINGLE_SESSION", "sapdiag.diag.supportbits.SINGLE_SESSION", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SINGLE_SESSION, "SAP Diag Support Bit SINGLE_SESSION", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_NOTIFY_NEWMODE, + { "Support Bit NOTIFY_NEWMODE", "sapdiag.diag.supportbits.NOTIFY_NEWMODE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_NOTIFY_NEWMODE, "SAP Diag Support Bit NOTIFY_NEWMODE", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_TOOLBAR_HEIGHT, + { "Support Bit TOOLBAR_HEIGHT", "sapdiag.diag.supportbits.TOOLBAR_HEIGHT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TOOLBAR_HEIGHT, "SAP Diag Support Bit TOOLBAR_HEIGHT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_XMLPROP_CONTAINER, + { "Support Bit XMLPROP_CONTAINER", "sapdiag.diag.supportbits.XMLPROP_CONTAINER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XMLPROP_CONTAINER, "SAP Diag Support Bit XMLPROP_CONTAINER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_XMLPROP_DYNPRO, + { "Support Bit XMLPROP_DYNPRO", "sapdiag.diag.supportbits.XMLPROP_DYNPRO", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XMLPROP_DYNPRO, "SAP Diag Support Bit XMLPROP_DYNPRO", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DP_HTTP_PUT, + { "Support Bit DP_HTTP_PUT", "sapdiag.diag.supportbits.DP_HTTP_PUT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DP_HTTP_PUT, "SAP Diag Support Bit DP_HTTP_PUT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DYNAMIC_PASSPORT, + { "Support Bit DYNAMIC_PASSPORT", "sapdiag.diag.supportbits.DYNAMIC_PASSPORT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DYNAMIC_PASSPORT, "SAP Diag Support Bit DYNAMIC_PASSPORT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_WEBGUI, + { "Support Bit WEBGUI", "sapdiag.diag.supportbits.WEBGUI", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_WEBGUI, "SAP Diag Support Bit WEBGUI", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_WEBGUI_HELPMODE, + { "Support Bit WEBGUI_HELPMODE", "sapdiag.diag.supportbits.WEBGUI_HELPMODE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_WEBGUI_HELPMODE, "SAP Diag Support Bit WEBGUI_HELPMODE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST, + { "Support Bit CONTROL_FOCUS_ON_LIST", "sapdiag.diag.supportbits.CONTROL_FOCUS_ON_LIST", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST, "SAP Diag Support Bit CONTROL_FOCUS_ON_LIST", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_2, + { "Support Bit CBU_RBUDUMMY_2", "sapdiag.diag.supportbits.CBU_RBUDUMMY_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_2, "SAP Diag Support Bit CBU_RBUDUMMY_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_EOKDUMMY_1, + { "Support Bit EOKDUMMY_1", "sapdiag.diag.supportbits.EOKDUMMY_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_EOKDUMMY_1, "SAP Diag Support Bit EOKDUMMY_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING, + { "Support Bit GUI_USER_SCRIPTING", "sapdiag.diag.supportbits.GUI_USER_SCRIPTING", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING, "SAP Diag Support Bit GUI_USER_SCRIPTING", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SLC, + { "Support Bit SLC", "sapdiag.diag.supportbits.SLC", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SLC, "SAP Diag Support Bit SLC", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ACCESSIBILITY, + { "Support Bit ACCESSIBILITY", "sapdiag.diag.supportbits.ACCESSIBILITY", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ACCESSIBILITY, "SAP Diag Support Bit ACCESSIBILITY", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ECATT, + { "Support Bit ECATT", "sapdiag.diag.supportbits.ECATT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ECATT, "SAP Diag Support Bit ECATT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID3, + { "Support Bit ENJOY_IMODEUUID3", "sapdiag.diag.supportbits.ENJOY_IMODEUUID3", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENJOY_IMODEUUID3, "SAP Diag Support Bit ENJOY_IMODEUUID3", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF8, + { "Support Bit ENABLE_UTF8", "sapdiag.diag.supportbits.ENABLE_UTF8", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENABLE_UTF8, "SAP Diag Support Bit ENABLE_UTF8", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_AUTOLOGOUT_TIME, + { "Support Bit R3INFO_AUTOLOGOUT_TIME", "sapdiag.diag.supportbits.R3INFO_AUTOLOGOUT_TIME", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_AUTOLOGOUT_TIME, "SAP Diag Support Bit R3INFO_AUTOLOGOUT_TIME", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_VARINFO_ICON_TITLE_LIST, + { "Support Bit VARINFO_ICON_TITLE_LIST", "sapdiag.diag.supportbits.VARINFO_ICON_TITLE_LIST", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_VARINFO_ICON_TITLE_LIST, "SAP Diag Support Bit VARINFO_ICON_TITLE_LIST", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF16BE, + { "Support Bit ENABLE_UTF16BE", "sapdiag.diag.supportbits.ENABLE_UTF16BE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENABLE_UTF16BE, "SAP Diag Support Bit ENABLE_UTF16BE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENABLE_UTF16LE, + { "Support Bit ENABLE_UTF16LE", "sapdiag.diag.supportbits.ENABLE_UTF16LE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENABLE_UTF16LE, "SAP Diag Support Bit ENABLE_UTF16LE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP, + { "Support Bit R3INFO_CODEPAGE_APP", "sapdiag.diag.supportbits.R3INFO_CODEPAGE_APP", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP, "SAP Diag Support Bit R3INFO_CODEPAGE_APP", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ENABLE_APPL4, + { "Support Bit ENABLE_APPL4", "sapdiag.diag.supportbits.ENABLE_APPL4", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ENABLE_APPL4, "SAP Diag Support Bit ENABLE_APPL4", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL, + { "Support Bit GUIPATCHLEVEL", "sapdiag.diag.supportbits.GUIPATCHLEVEL", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL, "SAP Diag Support Bit GUIPATCHLEVEL", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CBURBU_NEW_STATE, + { "Support Bit CBURBU_NEW_STATE", "sapdiag.diag.supportbits.CBURBU_NEW_STATE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CBURBU_NEW_STATE, "SAP Diag Support Bit CBURBU_NEW_STATE", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_BINARY_EVENTID, + { "Support Bit BINARY_EVENTID", "sapdiag.diag.supportbits.BINARY_EVENTID", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_BINARY_EVENTID, "SAP Diag Support Bit BINARY_EVENTID", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUI_THEME, + { "Support Bit GUI_THEME", "sapdiag.diag.supportbits.GUI_THEME", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUI_THEME, "SAP Diag Support Bit GUI_THEME", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TOP_WINDOW, + { "Support Bit TOP_WINDOW", "sapdiag.diag.supportbits.TOP_WINDOW", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TOP_WINDOW, "SAP Diag Support Bit TOP_WINDOW", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION_1, + { "Support Bit EVENT_DESCRIPTION_1", "sapdiag.diag.supportbits.EVENT_DESCRIPTION_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_EVENT_DESCRIPTION_1, "SAP Diag Support Bit EVENT_DESCRIPTION_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_SPLITTER, + { "Support Bit SPLITTER", "sapdiag.diag.supportbits.SPLITTER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SPLITTER, "SAP Diag Support Bit SPLITTER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_VALUE_4_HISTORY, + { "Support Bit VALUE_4_HISTORY", "sapdiag.diag.supportbits.VALUE_4_HISTORY", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_VALUE_4_HISTORY, "SAP Diag Support Bit VALUE_4_HISTORY", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ACC_LIST, + { "Support Bit ACC_LIST", "sapdiag.diag.supportbits.ACC_LIST", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ACC_LIST, "SAP Diag Support Bit ACC_LIST", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING_INFO, + { "Support Bit GUI_USER_SCRIPTING_INFO", "sapdiag.diag.supportbits.GUI_USER_SCRIPTING_INFO", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUI_USER_SCRIPTING_INFO, "SAP Diag Support Bit GUI_USER_SCRIPTING_INFO", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_TEXTEDIT_STREAM, + { "Support Bit TEXTEDIT_STREAM", "sapdiag.diag.supportbits.TEXTEDIT_STREAM", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TEXTEDIT_STREAM, "SAP Diag Support Bit TEXTEDIT_STREAM", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DYNT_NOFOCUS, + { "Support Bit DYNT_NOFOCUS", "sapdiag.diag.supportbits.DYNT_NOFOCUS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DYNT_NOFOCUS, "SAP Diag Support Bit DYNT_NOFOCUS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP_1, + { "Support Bit R3INFO_CODEPAGE_APP_1", "sapdiag.diag.supportbits.R3INFO_CODEPAGE_APP_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_CODEPAGE_APP_1, "SAP Diag Support Bit R3INFO_CODEPAGE_APP_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_FRAME_1, + { "Support Bit FRAME_1", "sapdiag.diag.supportbits.FRAME_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_FRAME_1, "SAP Diag Support Bit FRAME_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TICKET4GUI, + { "Support Bit TICKET4GUI", "sapdiag.diag.supportbits.TICKET4GUI", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TICKET4GUI, "SAP Diag Support Bit TICKET4GUI", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ACC_LIST_PROPS, + { "Support Bit ACC_LIST_PROPS", "sapdiag.diag.supportbits.ACC_LIST_PROPS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ACC_LIST_PROPS, "SAP Diag Support Bit ACC_LIST_PROPS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB_INPUT, + { "Support Bit TABSEL_ATTRIB_INPUT", "sapdiag.diag.supportbits.TABSEL_ATTRIB_INPUT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABSEL_ATTRIB_INPUT, "SAP Diag Support Bit TABSEL_ATTRIB_INPUT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DEFAULT_TOOLTIP, + { "Support Bit DEFAULT_TOOLTIP", "sapdiag.diag.supportbits.DEFAULT_TOOLTIP", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DEFAULT_TOOLTIP, "SAP Diag Support Bit DEFAULT_TOOLTIP", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE_2, + { "Support Bit XML_PROP_TABLE_2", "sapdiag.diag.supportbits.XML_PROP_TABLE_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XML_PROP_TABLE_2, "SAP Diag Support Bit XML_PROP_TABLE_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_3, + { "Support Bit CBU_RBUDUMMY_3", "sapdiag.diag.supportbits.CBU_RBUDUMMY_3", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CBU_RBUDUMMY_3, "SAP Diag Support Bit CBU_RBUDUMMY_3", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CELLINFO, + { "Support Bit CELLINFO", "sapdiag.diag.supportbits.CELLINFO", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CELLINFO, "SAP Diag Support Bit CELLINFO", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST_2, + { "Support Bit CONTROL_FOCUS_ON_LIST_2", "sapdiag.diag.supportbits.CONTROL_FOCUS_ON_LIST_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_CONTROL_FOCUS_ON_LIST_2, "SAP Diag Support Bit CONTROL_FOCUS_ON_LIST_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TABLE_COLUMNWIDTH_INPUT, + { "Support Bit TABLE_COLUMNWIDTH_INPUT", "sapdiag.diag.supportbits.TABLE_COLUMNWIDTH_INPUT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TABLE_COLUMNWIDTH_INPUT, "SAP Diag Support Bit TABLE_COLUMNWIDTH_INPUT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ITS_PLUGIN, + { "Support Bit ITS_PLUGIN", "sapdiag.diag.supportbits.ITS_PLUGIN", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ITS_PLUGIN, "SAP Diag Support Bit ITS_PLUGIN", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_OBJECT_NAMES_4_LOGIN_PROCESS, + { "Support Bit OBJECT_NAMES_4_LOGIN_PROCESS", "sapdiag.diag.supportbits.OBJECT_NAMES_4_LOGIN_PROCESS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_OBJECT_NAMES_4_LOGIN_PROCESS, "SAP Diag Support Bit OBJECT_NAMES_4_LOGIN_PROCESS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_RFC_SERVER_4_GUI, + { "Support Bit RFC_SERVER_4_GUI", "sapdiag.diag.supportbits.RFC_SERVER_4_GUI", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RFC_SERVER_4_GUI, "SAP Diag Support Bit RFC_SERVER_4_GUI", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS_2, + { "Support Bit R3INFO_FLAGS_2", "sapdiag.diag.supportbits.R3INFO_FLAGS_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_FLAGS_2, "SAP Diag Support Bit R3INFO_FLAGS_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_RCUI, + { "Support Bit RCUI", "sapdiag.diag.supportbits.RCUI", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_RCUI, "SAP Diag Support Bit RCUI", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MENUENTRY_WITH_FCODE, + { "Support Bit MENUENTRY_WITH_FCODE", "sapdiag.diag.supportbits.MENUENTRY_WITH_FCODE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MENUENTRY_WITH_FCODE, "SAP Diag Support Bit MENUENTRY_WITH_FCODE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_WEBSAPCONSOLE, + { "Support Bit WEBSAPCONSOLE", "sapdiag.diag.supportbits.WEBSAPCONSOLE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_WEBSAPCONSOLE, "SAP Diag Support Bit WEBSAPCONSOLE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_R3INFO_KERNEL_VERSION, + { "Support Bit R3INFO_KERNEL_VERSION", "sapdiag.diag.supportbits.R3INFO_KERNEL_VERSION", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_R3INFO_KERNEL_VERSION, "SAP Diag Support Bit R3INFO_KERNEL_VERSION", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_LOOP, + { "Support Bit VARINFO_CONTAINER_LOOP", "sapdiag.diag.supportbits.VARINFO_CONTAINER_LOOP", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_LOOP, "SAP Diag Support Bit VARINFO_CONTAINER_LOOP", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_EOKDUMMY_2, + { "Support Bit EOKDUMMY_2", "sapdiag.diag.supportbits.EOKDUMMY_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_EOKDUMMY_2, "SAP Diag Support Bit EOKDUMMY_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MESSAGE_INFO3, + { "Support Bit MESSAGE_INFO3", "sapdiag.diag.supportbits.MESSAGE_INFO3", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MESSAGE_INFO3, "SAP Diag Support Bit MESSAGE_INFO3", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_SBA2, + { "Support Bit SBA2", "sapdiag.diag.supportbits.SBA2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_SBA2, "SAP Diag Support Bit SBA2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MAINAREA_SIZE, + { "Support Bit MAINAREA_SIZE", "sapdiag.diag.supportbits.MAINAREA_SIZE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MAINAREA_SIZE, "SAP Diag Support Bit MAINAREA_SIZE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL_2, + { "Support Bit GUIPATCHLEVEL_2", "sapdiag.diag.supportbits.GUIPATCHLEVEL_2", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUIPATCHLEVEL_2, "SAP Diag Support Bit GUIPATCHLEVEL_2", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DISPLAY_SIZE, + { "Support Bit DISPLAY_SIZE", "sapdiag.diag.supportbits.DISPLAY_SIZE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DISPLAY_SIZE, "SAP Diag Support Bit DISPLAY_SIZE", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUI_PACKET, + { "Support Bit GUI_PACKET", "sapdiag.diag.supportbits.GUI_PACKET", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUI_PACKET, "SAP Diag Support Bit GUI_PACKET", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_DIALOG_STEP_NUMBER, + { "Support Bit DIALOG_STEP_NUMBER", "sapdiag.diag.supportbits.DIALOG_STEP_NUMBER", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DIALOG_STEP_NUMBER, "SAP Diag Support Bit DIALOG_STEP_NUMBER", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TC_KEEP_SCROLL_POSITION, + { "Support Bit TC_KEEP_SCROLL_POSITION", "sapdiag.diag.supportbits.TC_KEEP_SCROLL_POSITION", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TC_KEEP_SCROLL_POSITION, "SAP Diag Support Bit TC_KEEP_SCROLL_POSITION", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MESSAGE_SERVICE_REQUEST, + { "Support Bit MESSAGE_SERVICE_REQUEST", "sapdiag.diag.supportbits.MESSAGE_SERVICE_REQUEST", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MESSAGE_SERVICE_REQUEST, "SAP Diag Support Bit MESSAGE_SERVICE_REQUEST", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_DYNT_FOCUS_FRAME, + { "Support Bit DYNT_FOCUS_FRAME", "sapdiag.diag.supportbits.DYNT_FOCUS_FRAME", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_DYNT_FOCUS_FRAME, "SAP Diag Support Bit DYNT_FOCUS_FRAME", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MAX_STRING_LEN, + { "Support Bit MAX_STRING_LEN", "sapdiag.diag.supportbits.MAX_STRING_LEN", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MAX_STRING_LEN, "SAP Diag Support Bit MAX_STRING_LEN", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_1, + { "Support Bit VARINFO_CONTAINER_1", "sapdiag.diag.supportbits.VARINFO_CONTAINER_1", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_VARINFO_CONTAINER_1, "SAP Diag Support Bit VARINFO_CONTAINER_1", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_STD_TOOLBAR_ITEMS, + { "Support Bit STD_TOOLBAR_ITEMS", "sapdiag.diag.supportbits.STD_TOOLBAR_ITEMS", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_STD_TOOLBAR_ITEMS, "SAP Diag Support Bit STD_TOOLBAR_ITEMS", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_XMLPROP_LIST_DYNPRO, + { "Support Bit XMLPROP_LIST_DYNPRO", "sapdiag.diag.supportbits.XMLPROP_LIST_DYNPRO", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_XMLPROP_LIST_DYNPRO, "SAP Diag Support Bit XMLPROP_LIST_DYNPRO", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_TRACE_GUI_CONNECT, + { "Support Bit TRACE_GUI_CONNECT", "sapdiag.diag.supportbits.TRACE_GUI_CONNECT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_TRACE_GUI_CONNECT, "SAP Diag Support Bit TRACE_GUI_CONNECT", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_LIST_FULLWIDTH, + { "Support Bit LIST_FULLWIDTH", "sapdiag.diag.supportbits.LIST_FULLWIDTH", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_LIST_FULLWIDTH, "SAP Diag Support Bit LIST_FULLWIDTH", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_ALLWAYS_SEND_CLIENT, + { "Support Bit ALLWAYS_SEND_CLIENT", "sapdiag.diag.supportbits.ALLWAYS_SEND_CLIENT", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_ALLWAYS_SEND_CLIENT, "SAP Diag Support Bit ALLWAYS_SEND_CLIENT", + HFILL }}, + + { &hf_SAPDIAG_SUPPORT_BIT_UNKNOWN_3, + { "Support Bit UNKNOWN_3", "sapdiag.diag.supportbits.UNKNOWN_3", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_UNKNOWN_3, "SAP Diag Support Bit UNKNOWN_3", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_GUI_SIGNATURE_COLOR, + { "Support Bit GUI_SIGNATURE_COLOR", "sapdiag.diag.supportbits.GUI_SIGNATURE_COLOR", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_GUI_SIGNATURE_COLOR, "SAP Diag Support Bit GUI_SIGNATURE_COLOR", + HFILL }}, + { &hf_SAPDIAG_SUPPORT_BIT_MAX_WSIZE, + { "Support Bit MAX_WSIZE", "sapdiag.diag.supportbits.MAX_WSIZE", FT_BOOLEAN, 8, NULL, SAPDIAG_SUPPORT_BIT_MAX_WSIZE, "SAP Diag Support Bit MAX_WSIZE", + HFILL }}, + + /* Dynt Atom */ + { &hf_sapdiag_item_dynt_atom, + { "Dynt Atom", "sapdiag.item.value.dyntatom", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Dynt Atom", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item, + { "Dynt Atom Item", "sapdiag.item.value.dyntatom.item", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Dynt Atom Item", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_etype, + { "Dynt Atom Item Type", "sapdiag.item.value.dyntatom.item.type", FT_UINT8, BASE_DEC, hf_sapdiag_item_dynt_atom_item_etype_vals, 0x0, "SAP Dynt Atom Item Type", + HFILL }}, + + /* Dynt Atom Attribute Flags */ + { &hf_sapdiag_item_dynt_atom_item_attr, + { "Dynt Atom Item Attributes", "sapdiag.item.value.dyntatom.item.attr", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP Dynt Atom Item Attribute", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_COMBOSTYLE, + { "Dynt Atom Item Attribute Combo Style", "sapdiag.item.value.dyntatom.item.attr.COMBOSTYLE", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_COMBOSTYLE, "SAP Dynt Atom Item Attribute Combo Style", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_YES3D, + { "Dynt Atom Item Attribute Yes3D", "sapdiag.item.value.dyntatom.item.attr.YES3D", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_YES3D, "SAP Dynt Atom Item Attribute Yes3D", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_PROPFONT, + { "Dynt Atom Item Attribute Prop Font", "sapdiag.item.value.dyntatom.item.attr.PROPFONT", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_PROPFONT, "SAP Dynt Atom Item Attribute Prop Font", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_MATCHCODE, + { "Dynt Atom Item Attribute Match Code", "sapdiag.item.value.dyntatom.item.attr.MATCHCODE", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_MATCHCODE, "SAP Dynt Atom Item Attribute Match Code", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_JUSTRIGHT, + { "Dynt Atom Item Attribute Just Right", "sapdiag.item.value.dyntatom.item.attr.JUSTRIGHT", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_JUSTRIGHT, "SAP Dynt Atom Item Attribute Just Right", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_INTENSIFY, + { "Dynt Atom Item Attribute Intensify", "sapdiag.item.value.dyntatom.item.attr.INTENSIFY", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_INTENSIFY, "SAP Dynt Atom Item Attribute Intensify", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_INVISIBLE, + { "Dynt Atom Item Attribute Invisible", "sapdiag.item.value.dyntatom.item.attr.INVISIBLE", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_INVISIBLE, "SAP Dynt Atom Item Attribute Invisible", + HFILL }}, + { &hf_sapdiag_item_dynt_atom_item_attr_DIAG_BSD_PROTECTED, + { "Dynt Atom Item Attribute Protected", "sapdiag.item.value.dyntatom.item.attr.PROTECTED", FT_BOOLEAN, 8, NULL, SAPDIAG_ATOM_ATTR_DIAG_BSD_PROTECTED, "SAP Dynt Atom Item Attribute Protected", + HFILL }}, + + /* UI Event Source fields */ + { &ht_sapdiag_item_ui_event_event_type, + { "UI Event Source Type", "sapdiag.item.value.uievent.type", FT_UINT16, BASE_DEC, ht_sapdiag_item_ui_event_event_type_vals, 0x0, "SAP UI Event Source Type", HFILL }}, + { &ht_sapdiag_item_ui_event_control_type, + { "UI Event Control Type", "sapdiag.item.value.uievent.control", FT_UINT16, BASE_DEC, ht_sapdiag_item_ui_event_control_type_vals, 0x0, "SAP UI Event Source Control Type", HFILL }}, + + { &ht_sapdiag_item_ui_event_valid, + { "UI Event Valid", "sapdiag.item.value.uievent.valid", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP UI Event Source Valid", HFILL }}, + { &ht_sapdiag_item_ui_event_valid_MENU_POS, + { "UI Event Valid Menu Pos", "sapdiag.item.value.uievent.valid.MENU_POS", FT_BOOLEAN, 8, NULL, SAPDIAG_UI_EVENT_VALID_FLAG_MENU_POS, "SAP UI Event Source Valid Menu Pos", HFILL }}, + { &ht_sapdiag_item_ui_event_valid_CONTROL_POS, + { "UI Event Valid Control Pos", "sapdiag.item.value.uievent.valid.CONTROL_POS", FT_BOOLEAN, 8, NULL, SAPDIAG_UI_EVENT_VALID_FLAG_CONTROL_POS, "SAP UI Event Source Valid Control Pos", HFILL }}, + { &ht_sapdiag_item_ui_event_valid_NAVIGATION_DATA, + { "UI Event Valid Navigation Data", "sapdiag.item.value.uievent.valid.NAVIGATION_DATA", FT_BOOLEAN, 8, NULL, SAPDIAG_UI_EVENT_VALID_FLAG_NAVIGATION_DATA, "SAP UI Event Source Valid Navigation Data", HFILL }}, + { &ht_sapdiag_item_ui_event_valid_FUNCTIONKEY_DATA, + { "UI Event Valid Function Key Data", "sapdiag.item.value.uievent.valid.FUNCTIONKEY_DATA", FT_BOOLEAN, 8, NULL, SAPDIAG_UI_EVENT_VALID_FLAG_FUNCTIONKEY_DATA, "SAP UI Event Source Valid Function Key Data", HFILL }}, + + { &ht_sapdiag_item_ui_event_control_row, + { "UI Event Source Control Row", "sapdiag.item.value.uievent.controlrow", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP UI Event Source Control Row", HFILL }}, + { &ht_sapdiag_item_ui_event_control_col, + { "UI Event Source Control Column", "sapdiag.item.value.uievent.controlcol", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP UI Event Source Control Column", HFILL }}, + { &ht_sapdiag_item_ui_event_navigation_data, + { "UI Event Source Navigation Data", "sapdiag.item.value.uievent.navigationdata", FT_UINT32, BASE_DEC, ht_sapdiag_item_ui_event_navigation_data_vals, 0x0, "SAP UI Event Source Navigation Data", HFILL }}, + { &ht_sapdiag_item_ui_event_data, + { "UI Event Source Data", "sapdiag.item.value.uievent.data", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP UI Event Source Data", HFILL }}, + { &ht_sapdiag_item_ui_event_container_nrs, + { "UI Event Source Container IDs Numbers", "sapdiag.item.value.uievent.containernrs", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP UI Event Source Container IDs Numbers", HFILL }}, + { &ht_sapdiag_item_ui_event_container, + { "UI Event Source Container ID", "sapdiag.item.value.uievent.container", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP UI Event Source Container ID", HFILL }}, + + /* Menu Entries */ + { &hf_sapdiag_item_menu_entry, + { "Menu Entry", "sapdiag.item.value.menu", FT_NONE, BASE_NONE, NULL, 0x0, "Menu Entry", + HFILL }}, + + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_sapdiag + }; + + module_t *sapdiag_module; + + /* Register the protocol */ + proto_sapdiag = proto_register_protocol ( + "SAP Diag Protocol", /* name */ + "SAPDIAG", /* short name */ + "sapdiag" /* abbrev */ + ); + + proto_register_field_array(proto_sapdiag, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("sapdiag", dissect_sapdiag, proto_sapdiag); + + /* Register the preferences */ + sapdiag_module = prefs_register_protocol(proto_sapdiag, proto_reg_handoff_sapdiag); + + range_convert_str(&global_sapdiag_port_range, SAPDIAG_PORT_RANGE, MAX_TCP_PORT); + prefs_register_range_preference(sapdiag_module, "tcp_ports", "SAP Diag Protocol TCP port numbers", "Port numbers used for SAP Diag Protocol (default " SAPDIAG_PORT_RANGE ")", &global_sapdiag_port_range, MAX_TCP_PORT); + + prefs_register_bool_preference(sapdiag_module, "decompress", "Decompress SAP Diag Protocol message payloads", "Whether the SAP Diag Protocol dissector should decompress message's payloads.", &global_sapdiag_decompress); + + prefs_register_bool_preference(sapdiag_module, "rfc_dissection", "Dissect embeded SAP RFC calls", "Whether the SAP Diag Protocol dissector should call the SAP RFC dissector for embeded RFC calls", &global_sapdiag_rfc_dissection); + + prefs_register_bool_preference(sapdiag_module, "snc_dissection", "Dissect SAP SNC frames", "Whether the SAP Diag Protocol dissector should call the SAP SNC dissector for SNC frames", &global_sapdiag_snc_dissection); + + prefs_register_bool_preference(sapdiag_module, "highlight_unknown_items", "Highlight unknown SAP Diag Items", "Whether the SAP Diag Protocol dissector should highlight unknown SAP Diag item (migth be noise and generate a lot of expert warnings)", &global_sapdiag_highlight_items); + +} + +/** + * Helpers for dealing with the port range + */ +static void range_delete_callback (guint32 port) +{ + dissector_delete_uint("sapni.port", port, sapdiag_handle); +} + +static void range_add_callback (guint32 port) +{ + dissector_add_uint("sapni.port", port, sapdiag_handle); +} + +/** + * Register Hand off for the SAP Diag Protocol + */ +void +proto_reg_handoff_sapdiag(void) +{ + static range_t *sapdiag_port_range; + static gboolean initialized = FALSE; + + if (!initialized) { + sapdiag_handle = create_dissector_handle(dissect_sapdiag, proto_sapdiag); + initialized = TRUE; + } else { + range_foreach(sapdiag_port_range, range_delete_callback); + g_free(sapdiag_port_range); + } + + sapdiag_port_range = range_copy(global_sapdiag_port_range); + range_foreach(sapdiag_port_range, range_add_callback); +} + diff --git a/packet-sapenqueue.c b/packet-sapenqueue.c new file mode 100644 index 0000000..b9ae83c --- /dev/null +++ b/packet-sapenqueue.c @@ -0,0 +1,413 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include +#include +#include + + +/* Enqueue Server Type values */ +static const value_string hf_sapenqueue_type_vals[] = { + { 0, "SYNC_REQUEST" }, + { 1, "ASYNC_REQUEST" }, + { 2, "RESPONSE" }, +}; + + +/* Enqueue Server Destination values */ +static const value_string hf_sapenqueue_dest_vals[] = { + { 1, "SYNC_ENQUEUE" }, + { 2, "ASYNC_ENQUEUE" }, + { 3, "SERVER_ADMIN" }, + { 5, "STAT_QUERY" }, + { 6, "CONECTION_ADMIN" }, + { 7, "ENQ_TO_REP" }, + { 8, "REP_TO_ENQ" }, + { 0, NULL }, +}; + + +/* Enqueue Server Admin Opcode values */ +static const value_string hf_sapenqueue_server_admin_opcode_vals[] = { + { 1, "EnAdmDummyRequest" }, + { 2, "EnAdmShutdownRequest" }, + { 4, "EnAdmGetReplInfoRequest" }, + { 6, "EnAdmTraceRequest" }, + { 0, NULL }, +}; + + +/* Enqueue Server Connection Admin Opcode values */ +static const value_string hf_sapenqueue_conn_admin_opcode_vals[] = { + { 0, "Loopback packet" }, + { 1, "Parameter Request" }, + { 2, "Parameter Response" }, + { 3, "Shutdown Read" }, + { 4, "Shutdown Write" }, + { 5, "Shutdown Both" }, + { 6, "Keepalive" }, +}; + + +/* Enqueue Server Connection Admin Parameter values */ +static const value_string hf_sapenqueue_conn_admin_param_vals[] = { + { 0, "ENCPARAM_RECV_LEN" }, + { 1, "ENCPARAM_SEND_LEN" }, + { 2, "ENCPARAM_MSG_TYPE" }, + { 3, "ENCPARAM_SET_NAME" }, + { 4, "ENCPARAM_SET_NOSUPP" }, + { 5, "ENCPARAM_SET_VERSION" }, + { 6, "ENCPARAM_SET_UCSUPPORT" }, +}; + +static int proto_sapenqueue = -1; + +static int hf_sapenqueue_magic = -1; +static int hf_sapenqueue_id = -1; +static int hf_sapenqueue_length = -1; +static int hf_sapenqueue_length_frag = -1; +static int hf_sapenqueue_dest = -1; +static int hf_sapenqueue_conn_admin_opcode = -1; +static int hf_sapenqueue_more_frags = -1; +static int hf_sapenqueue_type = -1; + +static int hf_sapenqueue_server_admin = -1; +static int hf_sapenqueue_server_admin_eyecatcher = -1; +static int hf_sapenqueue_server_admin_version = -1; +static int hf_sapenqueue_server_admin_flag = -1; +static int hf_sapenqueue_server_admin_length = -1; +static int hf_sapenqueue_server_admin_opcode = -1; +static int hf_sapenqueue_server_admin_flags = -1; +static int hf_sapenqueue_server_admin_rc = -1; +static int hf_sapenqueue_server_admin_value = -1; + +static int hf_sapenqueue_server_admin_trace_request = -1; + +static int hf_sapenqueue_conn_admin = -1; +static int hf_sapenqueue_conn_admin_params_count = -1; +static int hf_sapenqueue_conn_admin_params = -1; +static int hf_sapenqueue_conn_admin_param = -1; +static int hf_sapenqueue_conn_admin_param_id = -1; +static int hf_sapenqueue_conn_admin_param_len = -1; +static int hf_sapenqueue_conn_admin_param_value = -1; +static int hf_sapenqueue_conn_admin_param_name = -1; + +static gint ett_sapenqueue = -1; + +/* Protocol handle */ +static dissector_handle_t sapenqueue_handle; + + +/* + * + */ +void proto_reg_handoff_sapenqueue(void); + + +static void +dissect_sapenqueue_server_admin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset){ + guint8 opcode = 0; + proto_item *server_admin = NULL; + proto_tree *server_admin_tree = NULL; + + server_admin = proto_tree_add_item(tree, hf_sapenqueue_server_admin, tvb, offset, -1, FALSE); + server_admin_tree = proto_item_add_subtree(server_admin, ett_sapenqueue); + + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_eyecatcher, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_version, tvb, offset, 1, FALSE); offset += 1; + offset += 3; /* Unknown bytes */ + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_eyecatcher, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_flag, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_length, tvb, offset, 4, FALSE); offset += 4; + opcode = tvb_get_guint8(tvb, offset); + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_opcode, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_flags, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_rc, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_eyecatcher, tvb, offset, 4, FALSE); offset += 4; + + if (tvb_length_remaining(tvb, offset) > 0){ + proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_value, tvb, offset, -1, FALSE); + + switch(opcode){ + case 0x06:{ /* EnAdmTraceRequest */ + proto_item *trace_request = NULL; + proto_tree *trace_request_tree = NULL; + + trace_request = proto_tree_add_item(server_admin_tree, hf_sapenqueue_server_admin_trace_request, tvb, offset, -1, FALSE); + trace_request_tree = proto_item_add_subtree(trace_request, ett_sapenqueue); + + /* TODO: Dissect the trace request fields */ + break; + } + } + } + +} + + +static void +dissect_sapenqueue_conn_admin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint8 opcode){ + proto_item *conn_admin = NULL; + proto_tree *conn_admin_tree = NULL; + + conn_admin = proto_tree_add_item(tree, hf_sapenqueue_conn_admin, tvb, offset, -1, FALSE); + conn_admin_tree = proto_item_add_subtree(conn_admin, ett_sapenqueue); + + switch (opcode){ + case 0x01: /* Parameter Request */ + case 0x02:{ /* Parameter Response */ + guint8 length = 0, total_length = 0; + guint32 count = 0, id = 0, name_length = 0; + proto_item *params = NULL, *param = NULL; + proto_tree *params_tree = NULL, *param_tree = NULL; + + count = tvb_get_ntohl(tvb, offset); + proto_tree_add_item(conn_admin_tree, hf_sapenqueue_conn_admin_params_count, tvb, offset, 4, FALSE); offset += 4; + + params = proto_tree_add_item(conn_admin_tree, hf_sapenqueue_conn_admin_params, tvb, offset, 1, FALSE); + params_tree = proto_item_add_subtree(params, ett_sapenqueue); + + while (count > 0 && tvb_offset_exists(tvb, offset)){ + /* As we don't have the right size yet, start with 1 byte */ + param = proto_tree_add_item(params_tree, hf_sapenqueue_conn_admin_param, tvb, offset, 1, FALSE); + param_tree = proto_item_add_subtree(param, ett_sapenqueue); + + id = tvb_get_ntohl(tvb, offset); + proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_id, tvb, offset, 4, FALSE); offset += 4; + length = 4; + + if (id == 0x03){ /* Set Name parameter */ + name_length = tvb_strsize(tvb, offset); + proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_name, tvb, offset, name_length, FALSE); offset += name_length; + length += name_length; + + } else { + if (id == 0x06){ /* Set Unicode Support Parameter */ + proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_len, tvb, offset, 4, FALSE); offset += 4; + length += 4; + } + proto_tree_add_item(param_tree, hf_sapenqueue_conn_admin_param_value, tvb, offset, 4, FALSE); offset += 4; + length += 4; + } + + /* Set the right size for the parameter tree */ + proto_item_set_len(param, length); + + count -= 1; + total_length += length; + } + + proto_item_set_len(params, total_length); + + break; + } + } + +} + + +static void +dissect_sapenqueue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint8 dest = 0, type = 0, opcode = 0; + guint32 offset = 4; + proto_item *ti = NULL; + proto_tree *sapenqueue_tree = NULL; + + /* If the packet has less than 20 bytes we can be sure that is not an + * Enqueue server packet. + */ + if (tvb_length(tvb) < 20){ + return; + } + + /* Add the protocol to the column */ + col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPENQUEUE"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + dest = tvb_get_guint8(tvb, offset + 16); + col_append_fstr(pinfo->cinfo, COL_INFO, "Dest=%s", val_to_str(dest, hf_sapenqueue_dest_vals, "Unknown")); + + opcode = tvb_get_guint8(tvb, offset + 17); + type = tvb_get_guint8(tvb, offset + 19); + col_append_fstr(pinfo->cinfo, COL_INFO, ",Type=%s", val_to_str(type, hf_sapenqueue_type_vals, "Unknown")); + + if (dest == 0x06){ + col_append_fstr(pinfo->cinfo, COL_INFO, ",Opcode=%s", val_to_str(opcode, hf_sapenqueue_conn_admin_opcode_vals, "Unknown")); + } + + + if (tree){ /* we are being asked for details */ + + /* Add the main sapenqueue subtree */ + ti = proto_tree_add_item(tree, proto_sapenqueue, tvb, 0, -1, FALSE); + sapenqueue_tree = proto_item_add_subtree(ti, ett_sapenqueue); + + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_magic, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_id, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_length, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_length_frag, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_dest, tvb, offset, 1, FALSE); offset += 1; + if (dest == 0x06){ // This field is only relevant if the destination is Connection Admin + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_conn_admin_opcode, tvb, offset, 1, FALSE); + } + offset += 1; + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_more_frags, tvb, offset, 1, FALSE); offset += 1; + proto_tree_add_item(sapenqueue_tree, hf_sapenqueue_type, tvb, offset, 1, FALSE); offset += 1; + + switch (dest){ + case 0x03:{ /* Server Admin */ + dissect_sapenqueue_server_admin(tvb, pinfo, sapenqueue_tree, offset); + break; + } + case 0x06:{ /* Connection Admin */ + dissect_sapenqueue_conn_admin(tvb, pinfo, sapenqueue_tree, offset, opcode); + break; + } + } + } + +} + + +static gboolean +dissect_sapenqueue_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data){ + conversation_t *conversation = NULL; + + /* If the first 4 bytes are the magic bytes, we can guess that the + * packet is a Enqueue server packet. + */ + if (tvb_get_ntohl(tvb, 0) != 0xabcde123){ + return (FALSE); + } + + /* From now on this conversation is dissected as SAP Enqueue traffic */ + conversation = find_or_create_conversation(pinfo); + conversation_set_dissector(conversation, sapenqueue_handle); + + /* Now dissect the packet */ + dissect_sapenqueue(tvb, pinfo, tree); + + return (TRUE); +} + + +void +proto_register_sapenqueue(void) +{ + static hf_register_info hf[] = { + /* General Header fields */ + { &hf_sapenqueue_magic, + { "Magic Bytes", "sapenque.magic", FT_BYTES, BASE_NONE, NULL, 0x0, "SAP Enqueue Magic Bytes", HFILL }}, + { &hf_sapenqueue_id, + { "ID", "sapenque.id", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue ID", HFILL }}, + { &hf_sapenqueue_length, + { "Length", "sapenque.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Length", HFILL }}, + { &hf_sapenqueue_length_frag, + { "Fragment Length", "sapenque.fragment_length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Fragment Length", HFILL }}, + { &hf_sapenqueue_dest, + { "Destination", "sapenque.destination", FT_UINT8, BASE_DEC, hf_sapenqueue_dest_vals, 0x0, "SAP Enqueue Destination", HFILL }}, + { &hf_sapenqueue_conn_admin_opcode, + { "Opcode", "sapenque.opcode", FT_UINT8, BASE_DEC, hf_sapenqueue_conn_admin_opcode_vals, 0x0, "SAP Enqueue Opcode", HFILL }}, + { &hf_sapenqueue_more_frags, + { "More Fragments", "sapenque.more_frags", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Enqueue More Fragments", HFILL }}, + { &hf_sapenqueue_type, + { "Type", "sapenque.type", FT_UINT8, BASE_DEC, hf_sapenqueue_type_vals, 0x0, "SAP Enqueue Type", HFILL }}, + + /* Server Admin fields */ + { &hf_sapenqueue_server_admin, + { "Server Admin", "sapenque.server_admin", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Enqueue Server Admin", HFILL }}, + { &hf_sapenqueue_server_admin_eyecatcher, + { "Eye Catcher", "sapenque.server_admin.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Enqueue Server Admin Eye Catcher", HFILL }}, + { &hf_sapenqueue_server_admin_version, + { "Version", "sapenque.server_admin.version", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Enqueue Server Admin Version", HFILL }}, + { &hf_sapenqueue_server_admin_flag, + { "Flag", "sapenque.server_admin.flag", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Enqueue Server Admin Flag", HFILL }}, + { &hf_sapenqueue_server_admin_length, + { "Length", "sapenque.server_admin.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Server Admin Length", HFILL }}, + { &hf_sapenqueue_server_admin_opcode, + { "Opcode", "sapenque.server_admin.opcode", FT_UINT8, BASE_DEC, hf_sapenqueue_server_admin_opcode_vals, 0x0, "SAP Enqueue Server Admin Opcode", HFILL }}, + { &hf_sapenqueue_server_admin_flags, + { "Flags", "sapenque.server_admin.flags", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Enqueue Server Admin Flags", HFILL }}, + { &hf_sapenqueue_server_admin_rc, + { "Return Code", "sapenque.server_admin.rc", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Server Admin Return Code", HFILL }}, + { &hf_sapenqueue_server_admin_value, + { "Value", "sapenque.server_admin.value", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Enqueue Server Admin Value", HFILL }}, + + /* Trace Request fields */ + { &hf_sapenqueue_server_admin_trace_request, + { "Trace Request", "sapenque.server_admin.trace", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Enqueue Server Admin Trace Request", HFILL }}, + + /* Connection Admin fields */ + { &hf_sapenqueue_conn_admin, + { "Connection Admin", "sapenque.conn_admin", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Enqueue Connection Admin", HFILL }}, + { &hf_sapenqueue_conn_admin_params_count, + { "Parameters Count", "sapenque.conn_admin.params.count", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Connection Admin Parameters Count", HFILL }}, + { &hf_sapenqueue_conn_admin_params, + { "Parameters", "sapenque.conn_admin.params", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Enqueue Connection Admin Parameters", HFILL }}, + { &hf_sapenqueue_conn_admin_param, + { "Parameter", "sapenque.conn_admin.params.param", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Enqueue Connection Admin Parameter", HFILL }}, + { &hf_sapenqueue_conn_admin_param_id, + { "Parameter ID", "sapenque.conn_admin.params.param.id", FT_UINT32, BASE_DEC, hf_sapenqueue_conn_admin_param_vals, 0x0, "SAP Enqueue Connection Admin Parameter ID", HFILL }}, + { &hf_sapenqueue_conn_admin_param_len, + { "Parameter Length", "sapenque.conn_admin.params.param.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Connection Admin Parameter Length", HFILL }}, + { &hf_sapenqueue_conn_admin_param_value, + { "Parameter Value", "sapenque.conn_admin.params.param.value", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Enqueue Connection Admin Parameter Value", HFILL }}, + { &hf_sapenqueue_conn_admin_param_name, + { "Parameter Name", "sapenque.conn_admin.params.param.name", FT_STRINGZ, BASE_NONE, NULL, 0x0, "SAP Enqueue Connection Admin Parameter Name", HFILL }}, + + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_sapenqueue + }; + + /* Register the protocol */ + proto_sapenqueue = proto_register_protocol ( + "SAP Enqueue Protocol", /* name */ + "SAPENQUEUE", /* short name */ + "sapenqueue" /* abbrev */ + ); + + proto_register_field_array(proto_sapenqueue, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("sapenqueue", dissect_sapenqueue, proto_sapenqueue); + +} + + +void +proto_reg_handoff_sapenqueue(void) +{ + sapenqueue_handle = create_dissector_handle(dissect_sapenqueue, proto_sapenqueue); + + /* Register the heuristic dissector. We need to use a heuristic dissector + * here as the Enqueue Server uses the same port number that the Dispatcher + * Service (32NN/tcp). */ + heur_dissector_add("sapni", dissect_sapenqueue_heur, proto_sapenqueue); + +} diff --git a/packet-sapms.c b/packet-sapms.c new file mode 100644 index 0000000..1fc61a2 --- /dev/null +++ b/packet-sapms.c @@ -0,0 +1,1502 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include +#include + +/* Define default ports */ +#define SAPMS_PORT_RANGE "3600-3699,3900-3999" + +/* MS Flag values */ +static const value_string hf_sapms_flag_vals[] = { + { 1, "MS_ONE_WAY" }, + { 2, "MS_REQUEST" }, + { 3, "MS_REPLY" }, + { 4, "MS_ADMIN" }, + { 0, NULL } +}; + +/* MS IFlag values */ +static const value_string hf_sapms_iflag_vals[] = { + { 1, "MS_SEND_NAME" }, + { 2, "MS_SEND_TYPE" }, + { 3, "MS_LOGIN" }, + { 4, "MS_LOGOUT" }, + { 5, "MS_ADM_OPCODES" }, + { 6, "MS_MOD_MSGTYPES" }, + { 7, "MS_SEND_TYPE_ONCE" }, + { 8, "MS_LOGIN_2" }, + { 9, "MS_MOD_STATE" }, + { 10, "MS_J2EE_LOGIN" }, + { 12, "MS_J2EE_SEND_TO_CLUSTERID" }, + { 13, "MS_J2EE_SEND_BROADCAST" }, + { 14, "MS_SEND_TYPE_ACK" }, + { 15, "MS_J2EE_LOGIN_2" }, + { 16, "MS_SEND_SERVICE" }, + { 17, "MS_J2EE_LOGIN_3" }, + { 18, "MS_J2EE_LOGIN_4" }, + { 0, NULL } +}; + +/* MS Error number values */ +static const value_string hf_sapms_errorno_vals[] = { + { 0, "MSERECONNECTION" }, + { 1, "MSENISELWRITE" }, + { 2, "MSENISELREAD" }, + { 3, "MSENIQUEUE" }, + { 4, "MSENILAYER" }, + { 71, "MSETESTSOFTSHUTDOWN" }, + { 72, "MSENOTINIT" }, + { 73, "MSEALREADYINIT" }, + { 74, "MSEINVHDL" }, + { 75, "MSEWRONGSERVER" }, + { 76, "MSEMOREDATA" }, + { 77, "MSESNDTYPEFAILED" }, + { 78, "MSEDUPKEY" }, + { 79, "MSESOFTSHUTDOWN" }, + { 81, "MSENOMEM" }, + { 82, "MSEHEADERINCOMPLETE" }, + { 83, "MSETYPESNOTALLOWED" }, + { 84, "MSEACCESSDENIED" }, + { 85, "MSEWRITEINCOMPLETE" }, + { 86, "MSEREADINCOMPLETE" }, + { 87, "MSEADMIN" }, + { 88, "MSESOCKTOOLARGE" }, + { 89, "MSENOSLOTFREE" }, + { 90, "MSESHUTDOWN" }, + { 91, "MSEREPLYTOOLARGE" }, + { 92, "MSEWRONGVERSION" }, + { 93, "MSEMSGDESTROYED" }, + { 94, "MSENOTUNIQUE" }, + { 95, "MSEPARTNERUNKNOWN" }, + { 96, "MSEPARTNERDIED" }, + { 97, "MSEWRONGTYPE" }, + { 98, "MSEWRONGNAME" }, + { 99, "MSEWAKEUP" }, + { 100, "MSENOTFOUND" }, + { 101, "MSEINVAL" }, + { 102, "MSENOMSG" }, + { 103, "MSEINTERN" }, +}; + +/* MS Adm Message Types values */ +static const value_string hf_sapms_adm_msgtype_vals[] = { + { 1, "ADM_REQUEST" }, + { 2, "ADM_REPLY" }, + { 0, NULL } +}; + +/* MS Adm Record Opcode values */ +static const value_string hf_sapms_adm_record_opcode_vals[] = { + { 0x00, "AD_GENERAL" }, + { 0x01, "AD_PROFILE" }, + { 0x02, "AD_WPSTAT" }, + { 0x03, "AD_QUEUE" }, + { 0x04, "AD_STARTSTOP" }, + { 0x05, "AD_WPCONF" }, + { 0x06, "AD_USRLST" }, + { 0x07, "AD_WPKILL" }, + { 0x08, "AD_TIMEINFO" }, + { 0x09, "AD_TM_RECONNECT" }, + { 0x0a, "AD_ALRT_GET_STATE" }, + { 0x0b, "AD_ALRT_OPERATION" }, + { 0x0c, "AD_ALRT_SET_PARAM" }, + { 0x0d, "AD_DB_RECONNECT" }, + { 0x0e, "AD_ECHO" }, + { 0x0f, "AD_MSGSERVER" }, + { 0x10, "AD_WPCONF2" }, + { 0x11, "AD_GENERAL2" }, + { 0x12, "AD_SET_LIST_PARAM" }, + { 0x13, "AD_DUMP_STATUS" }, + { 0x14, "AD_RZL" }, + { 0x15, "AD_RZL_STRG" }, + { 0x16, "AD_COUNT_WPS" }, + { 0x17, "AD_QUEUE2" }, + { 0x19, "AD_EM" }, + { 0x1a, "AD_ES" }, + { 0x1b, "AD_SHUTDOWN_STATE" }, + { 0x1c, "AD_SHUTDOWN_INFO" }, + { 0x1d, "AD_SHUTDOWN_ERROR" }, + { 0x1f, "AD_DISPLACE" }, + { 0x20, "AD_GET_TIMETAB" }, + { 0x21, "AD_SET_TIMETAB" }, + { 0x28, "AD_MSBUF" }, + { 0x29, "AD_ARFC_NOREQ" }, + { 0x2a, "AD_ENQID_INFO" }, + { 0x2b, "AD_DEL_USER" }, + { 0x2c, "AD_SPO_ADM" }, + { 0x2d, "AD_NTAB_SYNC" }, + { 0x2e, "AD_SHARED_PARAMETER" }, + { 0x2f, "AD_RESET_TRACE" }, + { 0x30, "AD_RESET_USR02" }, + { 0x31, "AD_WALL_CREATE" }, + { 0x32, "AD_WALL_DELETE" }, + { 0x33, "AD_WALL_MODIFY" }, + { 0x34, "AD_SERVER_STATE" }, + { 0x3c, "AD_SELFIDENT" }, + { 0x3d, "AD_DP_TRACE_CHANGE" }, + { 0x3e, "AD_DP_DUMP_NIHDL" }, + { 0x3f, "AD_DP_CALL_DELAYED" }, + { 0x40, "AD_GW_ADM" }, + { 0x41, "AD_DP_WAKEUP_MODE" }, + { 0x42, "AD_VMC_SYS_EVENT" }, + { 0x43, "AD_SHARED_PARAM_ALL_WPS" }, + { 0x44, "AD_SECSESSION_UPDATE" }, + { 0x45, "AD_SECSESSION_TERMINATE" }, + { 0x46, "AD_ASRF_REQUEST" }, + { 0x47, "AD_GET_NILIST" }, + { 0x48, "AD_LOAD_INFO" }, + { 0x49, "AD_TEST" }, + { 0x4a, "AD_HANDLE_ACL" }, + { 0x4b, "AD_ENQ_LOG_RESET" }, + { 0, NULL } +}; + +/* MS Adm AD_RZL_STRG Type values */ +static const value_string hf_sapms_adm_rzl_strg_type_vals[] = { + { 10, "STRG_TYPE_READALL" }, + { 11, "STRG_TYPE_READALL_I" }, + { 12, "STRG_TYPE_READALL_C" }, + { 13, "STRG_TYPE_READALL_LC" }, + { 15, "STRG_TYPE_READALL_OFFSET_I" }, + { 16, "STRG_TYPE_READALL_OFFSET_C" }, + { 17, "STRG_TYPE_READALL_OFFSET_LC" }, + { 20, "STRG_TYPE_READALL_OFFSET" }, + { 21, "STRG_TYPE_READ_I" }, + { 22, "STRG_TYPE_READ_C" }, + { 23, "STRG_TYPE_READ_LC" }, + { 31, "STRG_TYPE_WRITE_I" }, + { 32, "STRG_TYPE_WRITE_C" }, + { 33, "STRG_TYPE_WRITE_LC" }, + { 41, "STRG_TYPE_DEL_I" }, + { 42, "STRG_TYPE_DEL_C" }, + { 43, "STRG_TYPE_DEL_LC" }, + { 51, "STRG_TYPE_CREATE_I" }, + { 52, "STRG_TYPE_CREATE_C" }, + { 53, "STRG_TYPE_CREATE_LC" }, + { 90, "STRG_TYPE_DUMP" }, +}; + +/* MS OP Code values */ +static const value_string hf_sapms_opcode_vals[] = { + { 1, "MS_SERVER_CHG" }, + { 2, "MS_SERVER_ADD" }, + { 3, "MS_SERVER_SUB" }, + { 4, "MS_SERVER_MOD" }, + { 5, "MS_SERVER_LST" }, + { 6, "MS_CHANGE_IP" }, + { 7, "MS_SET_SECURITY_KEY" }, + { 8, "MS_GET_SECURITY_KEY" }, + { 9, "MS_GET_SECURITY_KEY2" }, + { 10, "MS_GET_HWID" }, + { 11, "MS_INCRE_TRACE" }, + { 12, "MS_DECRE_TRACE" }, + { 13, "MS_RESET_TRACE" }, + { 14, "MS_ACT_STATISTIC" }, + { 15, "MS_DEACT_STATISTIC" }, + { 16, "MS_RESET_STATISTIC" }, + { 17, "MS_GET_STATISTIC" }, + { 18, "MS_DUMP_NIBUFFER" }, + { 19, "MS_RESET_NIBUFFER" }, + { 20, "MS_OPEN_REQ_LST" }, + { 21, "MS_SERVER_INFO" }, + { 22, "MS_SERVER_LIST" }, + { 23, "MS_SERVER_ENTRY" }, + { 24, "MS_DOMAIN_INFO" }, + { 25, "MS_DOMAIN_LIST" }, + { 26, "MS_DOMAIN_ENTRY" }, + { 27, "MS_MAP_URL_TO_ADDR" }, + { 28, "MS_GET_CODEPAGE" }, + { 29, "MS_SOFT_SHUTDOWN" }, + { 30, "MS_DUMP_INFO" }, + { 31, "MS_FILE_RELOAD" }, + { 32, "MS_RESET_DOMAIN_CONN" }, + { 33, "MS_NOOP" }, + { 34, "MS_SET_TXT" }, + { 35, "MS_GET_TXT" }, + { 36, "MS_COUNTER_CREATE" }, + { 37, "MS_COUNTER_DELETE" }, + { 38, "MS_COUNTER_INCREMENT" }, + { 39, "MS_COUNTER_DECREMENT" }, + { 40, "MS_COUNTER_REGISTER" }, + { 41, "MS_COUNTER_GET" }, + { 42, "MS_COUNTER_LST" }, + { 43, "MS_SET_LOGON" }, + { 44, "MS_GET_LOGON" }, + { 45, "MS_DEL_LOGON" }, + { 46, "MS_SERVER_DISC" }, + { 47, "MS_SERVER_SHUTDOWN" }, + { 48, "MS_SERVER_SOFT_SHUTDOWN" }, + { 49, "MS_J2EE_CLUSTERNODE_CHG" }, + { 50, "MS_J2EE_CLUSTERNODE_ADD" }, + { 51, "MS_J2EE_CLUSTERNODE_SUB" }, + { 52, "MS_J2EE_CLUSTERNODE_MOD" }, + { 53, "MS_J2EE_CLUSTERNODE_LST" }, + { 54, "MS_J2EE_SERVICE_REG" }, + { 55, "MS_J2EE_SERVICE_UNREG" }, + { 56, "MS_J2EE_SERVICE_LST" }, + { 57, "MS_J2EE_SERVICE_ADD" }, + { 58, "MS_J2EE_SERVICE_SUB" }, + { 59, "MS_J2EE_SERVICE_MOD" }, + { 60, "MS_J2EE_MOD_STATE" }, + { 61, "MS_J2EE_SERVICE_GET" }, + { 62, "MS_J2EE_SERVICE_REG2" }, + { 63, "MS_NITRACE_SETGET" }, + { 64, "MS_SERVER_LONG_LIST" }, + { 65, "MS_J2EE_DEBUG_ENABLE" }, + { 66, "MS_J2EE_DEBUG_DISABLE" }, + { 67, "MS_SET_PROPERTY" }, + { 68, "MS_GET_PROPERTY" }, + { 69, "MS_DEL_PROPERTY" }, + { 70, "MS_IP_PORT_TO_NAME" }, + { 71, "MS_CHECK_ACL" }, + { 72, "MS_LICENSE_SRV" }, + { 74, "MS_SERVER_TEST_SOFT_SHUTDOWN" }, + { 75, "MS_J2EE_RECONNECT_P1" }, + { 76, "MS_J2EE_RECONNECT_P2" }, + { 0, NULL }, +}; + +/* MS OP Code Error values */ +static const value_string hf_sapms_opcode_error_vals[] = { + { 0, "MSOP_OK" }, + { 1, "MSOP_UNKNOWN_OPCODE" }, + { 2, "MSOP_NOMEM" }, + { 3, "MSOP_SECURITY_KEY_NOTSET" }, + { 4, "MSOP_UNKNOWN_CLIENT" }, + { 5, "MSOP_ACCESS_DENIED" }, + { 6, "MSOP_REQUEST_REQUIRED" }, + { 7, "MSOP_NAME_REQUIRED" }, + { 8, "MSOP_GET_HWID_FAILED" }, + { 9, "MSOP_SEND_FAILED" }, + { 10, "MSOP_UNKNOWN_DOMAIN" }, + { 11, "MSOP_UNKNOWN_SERVER" }, + { 12, "MSOP_NO_DOMAIN_SERVER" }, + { 13, "MSOP_INVALID_URL" }, + { 14, "MSOP_UNKNOWN_DUMP_REQ" }, + { 15, "MSOP_FILENOTFOUND" }, + { 16, "MSOP_UNKNOWN_RELOAD_REQ" }, + { 17, "MSOP_FILENOTDEFINED" }, + { 18, "MSOP_CONVERT_FAILED" }, + { 19, "MSOP_NOTSET" }, + { 20, "MSOP_COUNTER_EXCEEDED" }, + { 21, "MSOP_COUNTER_NOTFOUND" }, + { 22, "MSOP_COUNTER_DELETED" }, + { 23, "MSOP_COUNTER_EXISTS" }, + { 24, "MSOP_EINVAL" }, + { 25, "MSOP_NO_J2EE_CLUSTERNODE" }, + { 26, "MSOP_UNKNOWN_PROPERTY" }, + { 27, "MSOP_UNKNOWN_VERSION" }, + { 28, "MSOP_ICTERROR" }, + { 29, "MSOP_KERNEL_INCOMPATIBLE" }, + { 30, "MSOP_NIACLCREATE_FAILED" }, + { 31, "MSOP_NIACLSYNTAX_ERROR" }, +}; + +/* MS Set/Get Property ID values */ +static const value_string hf_sapms_property_id_vals[] = { + { 1, "MS_PROPERTY_TEXT" }, + { 2, "MS_PROPERTY_VHOST" }, + { 3, "MS_PROPERTY_IPADR" }, + { 4, "MS_PROPERTY_PARAM" }, + { 5, "MS_PROPERTY_SERVICE" }, + { 6, "MS_PROPERTY_DELALT" }, + { 7, "Release information" }, + { 0, NULL }, +}; + +/* MS Dump Info Dump values */ +static const value_string hf_sapms_dump_command_vals[] = { + { 1, "MS_DUMP_MSADM" }, + { 2, "MS_DUMP_CON" }, + { 3, "MS_DUMP_PARAMS" }, + { 4, "MS_DUMP_ALL_CLIENTS" }, + { 5, "MS_DUMP_ALL_SERVER" }, + { 6, "MS_DUMP_ALL_DOMAIN" }, + { 7, "MS_DUMP_DOMAIN_CONN" }, + { 8, "MS_DUMP_RELEASE" }, + { 9, "MS_DUMP_SIZEOF" }, + { 10, "MS_DUMP_FIADM" }, + { 11, "MS_DUMP_FICON" }, + { 12, "MS_DUMP_COUNTER" }, + { 13, "MS_DUMP_STATISTIC" }, + { 14, "MS_DUMP_NIBUF" }, + { 15, "MS_DUMP_URLMAP" }, + { 16, "MS_DUMP_URLPREFIX" }, + { 17, "MS_DUMP_URLHANDLER" }, + { 18, "MS_DUMP_NOSERVER" }, + { 19, "MS_DUMP_ACLINFO" }, + { 20, "MS_DUMP_PERMISSION_TABLE" }, + { 21, "MS_DUMP_J2EE_CLUSTER_STAT" }, + { 22, "MS_DUMP_ACL_FILE_EXT" }, + { 23, "MS_DUMP_ACL_FILE_INT" }, + { 24, "MS_DUMP_ACL_FILE_ADMIN" }, + { 25, "MS_DUMP_ACL_FILE_EXTBND" }, + { 26, "MS_DUMP_ACL_FILE_HTTP" }, + { 27, "MS_DUMP_ACL_FILE_HTTPS" }, + { 0, NULL }, +}; + +/* MS Reload file values */ +static const value_string hf_sapms_file_reload_vals[] = { + { 1, "MS_RELOAD_CLIENT_TAB" }, + { 2, "MS_RELOAD_SERVER_TAB" }, + { 3, "MS_RELOAD_DOMAIN_TAB" }, + { 4, "MS_RELOAD_URLMAP" }, + { 5, "MS_RELOAD_URLPREFIX" }, + { 6, "MS_RELOAD_ACL_INFO" }, + { 7, "MS_RELOAD_PERMISSION_TABLE" }, + { 8, "MS_RELOAD_STOC" }, + { 9, "MS_RELOAD_ACL_FILE_EXT" }, + { 10, "MS_RELOAD_ACL_FILE_INT" }, + { 11, "MS_RELOAD_ACL_FILE_ADMIN" }, + { 12, "MS_RELOAD_ACL_FILE_EXTBND" }, + { 13, "MS_RELOAD_ACL_FILE_HTTP" }, + { 14, "MS_RELOAD_ACL_FILE_HTTPS" }, + { 0, NULL } +}; + + +/* MS Logon Type values */ +static const value_string hf_sapms_logon_type_vals[] = { + { 0, "MS_LOGON_DIAG_LB" }, + { 1, "MS_LOGON_DIAG_LBS" }, + { 2, "MS_LOGON_DIAG" }, + { 3, "MS_LOGON_DIAGS" }, + { 4, "MS_LOGON_RFC" }, + { 5, "MS_LOGON_RFCS" }, + { 6, "MS_LOGON_HTTP" }, + { 7, "MS_LOGON_HTTPS" }, + { 8, "MS_LOGON_FTP" }, + { 9, "MS_LOGON_SMTP" }, + { 10, "MS_LOGON_NNTP" }, + { 11, "MS_LOGON_DIAG_E" }, + { 12, "MS_LOGON_DIAGS_E" }, + { 13, "MS_LOGON_RFC_E" }, + { 14, "MS_LOGON_RFCS_E" }, + { 15, "MS_LOGON_HTTP_E" }, + { 16, "MS_LOGON_HTTPS_E" }, + { 17, "MS_LOGON_FTP_E" }, + { 18, "MS_LOGON_SMTP_E" }, + { 19, "MS_LOGON_NNTP_E" }, + { 20, "MS_LOGON_J2EE" }, + { 21, "MS_LOGON_J2EES" }, + { 22, "MS_LOGON_J2EE_E" }, + { 23, "MS_LOGON_J2EES_E" }, + { 24, "MS_LOGON_P4" }, + { 25, "MS_LOGON_P4S" }, + { 26, "MS_LOGON_IIOP" }, + { 27, "MS_LOGON_IIOPS" }, + { 28, "MS_LOGON_SDM" }, + { 29, "MS_LOGON_TELNET" }, + { 30, "MS_LOGON_DEBUG" }, + { 31, "MS_LOGON_DPROXY" }, + { 32, "MS_LOGON_P4HTTP" }, + { 33, "MS_LOGON_HTTPRI" }, + { 34, "MS_LOGON_HTTPSRI" }, + { 35, "MS_LOGON_J2EERI" }, + { 36, "MS_LOGON_J2EESRI" }, + { 37, "MS_LOGON_TRXNS" }, +}; + + +/* MS Client Status values */ +static const value_string hf_sapms_server_lst_status_vals[] = { + { 0, "MS_STATE_UNKNOWN" }, + { 1, "ACTIVE" }, + { 2, "INACTIVE" }, + { 3, "MS_STATE_SHUTDOWN" }, + { 4, "MS_STATE_STOP" }, + { 5, "MS_STATE_STARTING" }, + { 6, "MS_STATE_INIT" }, +}; + + +/* Message Type values */ +#define SAPMS_MSG_TYPE_DIA 0x01 +#define SAPMS_MSG_TYPE_UPD 0x02 +#define SAPMS_MSG_TYPE_ENQ 0x04 +#define SAPMS_MSG_TYPE_BTC 0x08 +#define SAPMS_MSG_TYPE_SPO 0x10 +#define SAPMS_MSG_TYPE_UP2 0x20 +#define SAPMS_MSG_TYPE_ATP 0x40 +#define SAPMS_MSG_TYPE_ICM 0x80 + +static int proto_sapms = -1; + +static int hf_sapms_eyecatcher = -1; +static int hf_sapms_version = -1; +static int hf_sapms_errorno = -1; +static int hf_sapms_toname = -1; +static int hf_sapms_msgtypes = -1; +static int hf_sapms_msgtypes_dia = -1; +static int hf_sapms_msgtypes_upd = -1; +static int hf_sapms_msgtypes_enq = -1; +static int hf_sapms_msgtypes_btc = -1; +static int hf_sapms_msgtypes_spo = -1; +static int hf_sapms_msgtypes_up2 = -1; +static int hf_sapms_msgtypes_atp = -1; +static int hf_sapms_msgtypes_icm = -1; +static int hf_sapms_reserved = -1; +static int hf_sapms_key = -1; +static int hf_sapms_flag = -1; +static int hf_sapms_iflag = -1; +static int hf_sapms_fromname = -1; +static int hf_sapms_fromhost = -1; +static int hf_sapms_fromserv = -1; +static int hf_sapms_message = -1; + +static int hf_sapms_adm_eyecatcher = -1; +static int hf_sapms_adm_version = -1; +static int hf_sapms_adm_msgtype = -1; +static int hf_sapms_adm_recsize = -1; +static int hf_sapms_adm_recno = -1; +static int hf_sapms_adm_records = -1; + +static int hf_sapms_adm_record = -1; +static int hf_sapms_adm_record_opcode = -1; +static int hf_sapms_adm_record_serial_number = -1; +static int hf_sapms_adm_record_executed = -1; +static int hf_sapms_adm_record_errorno = -1; +static int hf_sapms_adm_record_value = -1; + +static int hf_sapms_adm_parameter = -1; + +static int hf_sapms_adm_rzl_strg_type = -1; +static int hf_sapms_adm_rzl_strg_name = -1; +static int hf_sapms_adm_rzl_strg_value = -1; +static int hf_sapms_adm_rzl_strg_value_integer = -1; + +static int hf_sapms_opcode = -1; +static int hf_sapms_opcode_error = -1; +static int hf_sapms_opcode_version = -1; +static int hf_sapms_opcode_charset = -1; +static int hf_sapms_opcode_value = -1; + +static int hf_sapms_property_client = -1; +static int hf_sapms_property_id = -1; +static int hf_sapms_property_length = -1; +static int hf_sapms_property_value = -1; + +static int hf_sapms_property_ip_address = -1; +static int hf_sapms_property_ip_address6 = -1; + +static int hf_sapms_property_service = -1; + +static int hf_sapms_property_release = -1; +static int hf_sapms_property_release_patchno = -1; +static int hf_sapms_property_release_supplvl = -1; +static int hf_sapms_property_release_platform = -1; + + +static int hf_sapms_text_name = -1; +static int hf_sapms_text_length = -1; +static int hf_sapms_text_value = -1; + +static int hf_sapms_counter_uuid = -1; +static int hf_sapms_counter_count = -1; +static int hf_sapms_counter_no = -1; + +static int hf_sapms_change_ip_address = -1; +static int hf_sapms_change_ip_address6 = -1; + +static int hf_sapms_security_name = -1; +static int hf_sapms_security_key = -1; +static int hf_sapms_security_port = -1; +static int hf_sapms_security_address = -1; +static int hf_sapms_security_address6 = -1; + +static int hf_sapms_file_reload = -1; +static int hf_sapms_file_filler = -1; + +static int hf_sapms_logon_type = -1; +static int hf_sapms_logon_port = -1; +static int hf_sapms_logon_address = -1; +static int hf_sapms_logon_name_length = -1; +static int hf_sapms_logon_name = -1; +static int hf_sapms_logon_prot_length = -1; +static int hf_sapms_logon_prot = -1; +static int hf_sapms_logon_host_length = -1; +static int hf_sapms_logon_host = -1; +static int hf_sapms_logon_misc_length = -1; +static int hf_sapms_logon_misc = -1; +static int hf_sapms_logon_address6_length = -1; +static int hf_sapms_logon_address6 = -1; + +static int hf_sapms_shutdown_reason_length = -1; +static int hf_sapms_shutdown_reason = -1; + +static int hf_sapms_ip_to_name_address4 = -1; +static int hf_sapms_ip_to_name_address6 = -1; +static int hf_sapms_ip_to_name_port = -1; +static int hf_sapms_ip_to_name_length = -1; +static int hf_sapms_ip_to_name = -1; + +static int hf_sapms_check_acl_error_code = -1; +static int hf_sapms_check_acl_acl = -1; + +static int hf_sapms_codepage = -1; + +static int hf_sapms_dump_dest = -1; +static int hf_sapms_dump_filler = -1; +static int hf_sapms_dump_index = -1; +static int hf_sapms_dump_command = -1; +static int hf_sapms_dump_name = -1; + +static int hf_sapms_server_lst_client = -1; +static int hf_sapms_server_lst_name = -1; +static int hf_sapms_server_lst_host = -1; +static int hf_sapms_server_lst_service = -1; +static int hf_sapms_server_lst_msgtypes = -1; +static int hf_sapms_server_lst_msgtypes_dia = -1; +static int hf_sapms_server_lst_msgtypes_upd = -1; +static int hf_sapms_server_lst_msgtypes_enq = -1; +static int hf_sapms_server_lst_msgtypes_btc = -1; +static int hf_sapms_server_lst_msgtypes_spo = -1; +static int hf_sapms_server_lst_msgtypes_up2 = -1; +static int hf_sapms_server_lst_msgtypes_atp = -1; +static int hf_sapms_server_lst_msgtypes_icm = -1; +static int hf_sapms_server_lst_hostaddr = -1; +static int hf_sapms_server_lst_hostaddrv4 = -1; +static int hf_sapms_server_lst_servno = -1; +static int hf_sapms_server_lst_status = -1; +static int hf_sapms_server_lst_nitrc = -1; +static int hf_sapms_server_lst_sys_service = -1; + +static gint ett_sapms = -1; + +/* Global port preference */ +static range_t *global_sapms_port_range; + +/* Global highlight preference */ +static gboolean global_sapms_highlight_items = TRUE; + +/* Protocol handle */ +static dissector_handle_t sapms_handle; + +void proto_reg_handoff_sapms(void); + + +static void +dissect_sapms_adm_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint32 length){ + + proto_item *record = NULL, *value = NULL; + proto_tree *record_tree = NULL, *value_tree = NULL; + guint8 adm_opcode; + + while (length>=104){ + + record = proto_tree_add_item(tree, hf_sapms_adm_record, tvb, offset, 104, FALSE); + record_tree = proto_item_add_subtree(record, ett_sapms); + + adm_opcode = tvb_get_guint8(tvb, offset); + proto_tree_add_item(record_tree, hf_sapms_adm_record_opcode, tvb, offset, 1, FALSE); + proto_item_append_text(record_tree, ", Adm Opcode=%s", val_to_str(adm_opcode, hf_sapms_adm_record_opcode_vals, "Unknown")); offset+=1; length-=1; + + proto_tree_add_item(record_tree, hf_sapms_adm_record_serial_number, tvb, offset, 1, FALSE); offset+=1; length-=1; + proto_tree_add_item(record_tree, hf_sapms_adm_record_executed, tvb, offset, 1, FALSE); offset+=1; length-=1; + proto_tree_add_item(record_tree, hf_sapms_adm_record_errorno, tvb, offset, 1, FALSE); offset+=1; length-=1; + + /* Dissect the value in function of the opcode */ + switch (adm_opcode){ + case 0x01: /* AD_PROFILE */ + case 0x2e:{ /* AD_SHARED_PARAMETER */ + proto_tree_add_item(record_tree, hf_sapms_adm_parameter, tvb, offset, 100, FALSE); offset+=100; length-=100; + break; + } + case 0x15:{ /* AD_RZL_STRG */ + guint8 strg_type = 0; + strg_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(record_tree, hf_sapms_adm_rzl_strg_type, tvb, offset, 1, FALSE); offset+=1; length-=1; + offset+=3; length-=3; /* Skip 3 bytes */ + proto_tree_add_item(record_tree, hf_sapms_adm_rzl_strg_name, tvb, offset, 20, FALSE); offset+=20; length-=20; + + value = proto_tree_add_item(record_tree, hf_sapms_adm_rzl_strg_value, tvb, offset, 40, FALSE); + value_tree = proto_item_add_subtree(value, ett_sapms); + switch (strg_type){ + case 11: /* STRG_TYPE_READALL_I */ + case 15: /* STRG_TYPE_READALL_OFFSET_I */ + case 21: /* STRG_TYPE_READ_I */ + case 31: /* STRG_TYPE_WRITE_I */ + case 41: /* STRG_TYPE_DEL_I */ + case 51:{ /* STRG_TYPE_CREATE_I */ + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + proto_tree_add_item(value_tree, hf_sapms_adm_rzl_strg_value_integer, tvb, offset, 4, FALSE); offset+=4; length-=4; + break; + } + default:{ + offset+=40; length-=40; + break; + } + } + + offset+=36; length-=36; /* Skip the last 36 bytes */ + break; + } + default:{ + proto_tree_add_item(record_tree, hf_sapms_adm_record_value, tvb, offset, 100, FALSE); offset+=100; length-=100; + if (global_sapms_highlight_items){ + expert_add_info_format(pinfo, record_tree, PI_UNDECODED, PI_WARN, "The ADM opcode is dissected partially (0x%.2x)", adm_opcode); + } + break; + } + } + + } + +} + +static gint +dissect_sapms_client(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint8 opcode_version){ + proto_item *client = NULL, *msg_types = NULL; + proto_tree *client_tree = NULL, *msg_types_tree = NULL; + struct e_in6_addr address_ipv6; + guint32 address_ipv4 = 0; + gint client_length = 0; + + /* Chose the client length according to the version number */ + if (opcode_version == 0x01){ /* This version was seen in the older releases (6.40) */ + client_length = 67; + } else if (opcode_version == 0x02){ /* This version was seen in the older releases (6.40) */ + client_length = 115; + } else if (opcode_version == 0x03){ + client_length = 150; + } else if (opcode_version == 0x04){ /* Version 4 was seen in releases >7.0 */ + client_length = 160; + } else { /* Default to version 4 */ + client_length = 160; + if (global_sapms_highlight_items){ + expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN, "This version has not been seen, dissection of this packet could be wrong for this version (0x%.2x)", opcode_version); + } + } + + if (tvb_length_remaining(tvb, offset) < client_length){ + expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_WARN, "Invalid client length (expected=%d, actual=%d)", client_length, tvb_length_remaining(tvb, offset)); + return (client_length); + } + + /* Add the client tree */ + client = proto_tree_add_item(tree, hf_sapms_server_lst_client, tvb, offset, client_length, FALSE); + client_tree = proto_item_add_subtree(client, ett_sapms); + + /* Client name field */ + if (opcode_version==0x01){ + proto_tree_add_item(client_tree, hf_sapms_server_lst_name, tvb, offset, 20, FALSE); offset+=20; + } else { + proto_tree_add_item(client_tree, hf_sapms_server_lst_name, tvb, offset, 40, FALSE); offset+=40; + } + + /* Host field (version 1 is 20 bytes, 2 is 32 bytes and version 3/4 is 64 bytes) */ + if (opcode_version==0x01){ + proto_tree_add_item(client_tree, hf_sapms_server_lst_host, tvb, offset, 20, FALSE); offset+=20; + } else if (opcode_version==0x02){ + proto_tree_add_item(client_tree, hf_sapms_server_lst_host, tvb, offset, 32, FALSE); offset+=32; + } else { + proto_tree_add_item(client_tree, hf_sapms_server_lst_host, tvb, offset, 64, FALSE); offset+=64; + } + /* Service field */ + proto_tree_add_item(client_tree, hf_sapms_server_lst_service, tvb, offset, 20, FALSE); offset+=20; + + /* Message type flags */ + msg_types = proto_tree_add_item(client_tree, hf_sapms_server_lst_msgtypes, tvb, offset, 1, FALSE); + msg_types_tree = proto_item_add_subtree(msg_types, ett_sapms); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_dia, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_upd, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_enq, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_btc, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_spo, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_up2, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_atp, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_server_lst_msgtypes_icm, tvb, offset, 1, FALSE); offset+=1; + + /* Add the IPv6 address (only for version 3/4) */ + if (opcode_version >= 0x03){ + tvb_get_ipv6(tvb, offset, &address_ipv6); + proto_tree_add_ipv6(client_tree, hf_sapms_server_lst_hostaddr, tvb, offset, 16, (guint8 *)&address_ipv6); offset+=16; + } + + /* Add the IPv4 address */ + address_ipv4 = tvb_get_ipv4(tvb, offset); + proto_tree_add_ipv4(client_tree, hf_sapms_server_lst_hostaddrv4, tvb, offset, 4, address_ipv4); offset+=4; + + /* Service Number field */ + proto_tree_add_item(client_tree, hf_sapms_server_lst_servno, tvb, offset, 2, FALSE); offset+=2; + + /* Other fields only on version 2/3/4 */ + if (opcode_version >= 0x02){ + proto_tree_add_item(client_tree, hf_sapms_server_lst_status, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(client_tree, hf_sapms_server_lst_nitrc, tvb, offset, 1, FALSE); offset+=1; + } + + /* Add the Sys Server field (only for v4) */ + if (opcode_version == 0x04){ + proto_tree_add_item(client_tree, hf_sapms_server_lst_sys_service, tvb, offset, 4, FALSE); offset+=4; + } + + /* Return the client length according to the version */ + return (client_length); +} + + +static void +dissect_sapms_counter(tvbuff_t *tvb, proto_tree *tree, guint32 offset){ + proto_tree_add_item(tree, hf_sapms_counter_uuid, tvb, offset, 40, FALSE); offset+=40; + proto_tree_add_item(tree, hf_sapms_counter_count, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(tree, hf_sapms_counter_no, tvb, offset, 4, FALSE); offset+=4; +} + +static void +dissect_sapms_property(tvbuff_t *tvb, proto_tree *tree, guint32 offset){ + guint32 property_id = 0; + proto_item *value= NULL; + proto_tree *value_tree = NULL; + + proto_tree_add_item(tree, hf_sapms_property_client, tvb, offset, 40, FALSE); offset+=40; + + property_id = tvb_get_ntohl(tvb, offset); + proto_tree_add_item(tree, hf_sapms_property_id, tvb, offset, 4, FALSE); offset+=4; + + /* Check if the property item has a value */ + if (!tvb_offset_exists(tvb, offset)){ + return; + } + + value = proto_tree_add_item(tree, hf_sapms_property_value, tvb, offset, -1, FALSE); + value_tree = proto_item_add_subtree(value, ett_sapms); + + switch (property_id){ + + case 0x03:{ /* MS_PROPERTY_IPADR */ + proto_tree_add_item(value_tree, hf_sapms_property_ip_address, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(value_tree, hf_sapms_property_ip_address6, tvb, offset, 16, FALSE); offset+=16; + break; + } + case 0x05:{ /* MS_PROPERTY_SERVICE */ + proto_tree_add_item(value_tree, hf_sapms_property_service, tvb, offset, 2, FALSE); offset+=2; + break; + } + case 0x07:{ /* Release Information */ + proto_tree_add_item(value_tree, hf_sapms_property_release, tvb, offset, 10, FALSE); offset+=10; + proto_tree_add_item(value_tree, hf_sapms_property_release_patchno, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(value_tree, hf_sapms_property_release_supplvl, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(value_tree, hf_sapms_property_release_platform, tvb, offset, 4, FALSE); offset+=4; + break; + } + } +} + +static void +dissect_sapms_opcode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint8 flag, guint8 opcode, guint8 opcode_version, guint32 length){ + gint client_length = 0; + + switch (opcode){ + case 0x02: /* MS_SERVER_ADD */ + case 0x03: /* MS_SERVER_SUB */ + case 0x04:{ /* MS_SERVER_MOD */ + client_length = dissect_sapms_client(tvb, pinfo, tree, offset, opcode_version); + break; + } + case 0x05:{ /* MS_SERVER_LST */ + if (flag == 0x03){ /* If it's a reply (flag=MS_REPLY) */ + while (tvb_length_remaining(tvb, offset) > 0){ + client_length = dissect_sapms_client(tvb, pinfo, tree, offset, opcode_version); offset += client_length; + } + } + break; + } + case 0x06:{ /* MS_CHANGE_IP */ + proto_tree_add_item(tree, hf_sapms_change_ip_address, tvb, offset, 4, FALSE); offset+=4; length-=4; + + if (opcode_version >= 0x02){ + proto_tree_add_item(tree, hf_sapms_change_ip_address6, tvb, offset, 16, FALSE); offset+=16; length-=16; + } + break; + } + case 0x07: /* MS_SET_SECURITY_KEY */ + case 0x08:{ /* MS_GET_SECURITY_KEY */ + proto_tree_add_item(tree, hf_sapms_security_name, tvb, offset, 40, FALSE); offset+=40; length-=40; + proto_tree_add_item(tree, hf_sapms_security_key, tvb, offset, 256, FALSE); offset+=256; length-=256; + break; + } + case 0x09:{ /* MS_GET_SECURITY_KEY2 */ + guint32 address_ipv4; + struct e_in6_addr address_ipv6; + + address_ipv4 = tvb_get_ipv4(tvb, offset); + proto_tree_add_ipv4(tree, hf_sapms_security_address, tvb, offset, 4, address_ipv4); offset+=4; length-=4; + proto_tree_add_item(tree, hf_sapms_security_port, tvb, offset, 2, FALSE); offset+=2; length-=2; + proto_tree_add_item(tree, hf_sapms_security_key, tvb, offset, 256, FALSE); offset+=256; length-=256; + tvb_get_ipv6(tvb, offset, &address_ipv6); + proto_tree_add_ipv6(tree, hf_sapms_security_address6, tvb, offset, 16, (guint8 *)&address_ipv6); offset+=16; length-=16; + break; + } + case 0x0a:{ /* MS_GET_HWID */ + proto_tree_add_none_format(tree, hf_sapms_opcode_value, tvb, offset, length, "Hardware ID: %s", tvb_get_ephemeral_string(tvb, offset, length)); + break; + } + case 0x11:{ /* MS_GET_STATISTIC */ + // XXX: Fill fields for statistics + break; + } + case 0x1C:{ /* MS_GET_CODEPAGE */ + if (flag == 0x03) + proto_tree_add_item(tree, hf_sapms_codepage, tvb, offset, 4, FALSE); offset+=4; length-=4; + break; + } + case 0x1E:{ /* MS_DUMP_INFO */ + + if (flag == 0x02) { /* If it's a request (flag=MS_REQUEST) */ + proto_tree_add_item(tree, hf_sapms_dump_dest, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(tree, hf_sapms_dump_filler, tvb, offset, 3, FALSE); offset+=3; + proto_tree_add_item(tree, hf_sapms_dump_index, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(tree, hf_sapms_dump_command, tvb, offset, 2, FALSE); offset+=2; + if (length>=48) + proto_tree_add_item(tree, hf_sapms_dump_name, tvb, offset, 40, FALSE); offset+=40; + + } else if (flag == 0x03) { /* If it's a reply (flag=MS_REPLY) */ + guint32 string_length = 0; + length = tvb_strsize(tvb, offset); + /* Add each string in a different item */ + while (length>1){ + string_length = tvb_find_line_end(tvb, offset, -1, NULL, FALSE); + if (string_length>0){ + proto_tree_add_none_format(tree, hf_sapms_opcode_value, tvb, offset, string_length, "%s", tvb_get_ephemeral_string(tvb, offset, string_length)); + offset+=string_length; length-=string_length; + } + offset+=1; length-=1; + } + } + break; + } + case 0x1f:{ /* MS_FILE_RELOAD */ + proto_tree_add_item(tree, hf_sapms_file_reload, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(tree, hf_sapms_file_filler, tvb, offset, 3, FALSE); offset+=3; + break; + } + case 0x22: /* MS_SET_TXT */ + case 0x23:{ /* MS_GET_TXT */ + guint32 text_length = 0; + + proto_tree_add_item(tree, hf_sapms_text_name, tvb, offset, 40, FALSE); offset+=40; length-=40; + text_length = tvb_get_ntohl(tvb, offset); + proto_tree_add_item(tree, hf_sapms_text_length, tvb, offset, 4, FALSE); offset+=4; length-=4; + /* Check length */ + if (text_length != length ){ + expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_WARN, "Invalid length (expected=%d, actual=%d)", text_length, length); + } + proto_tree_add_item(tree, hf_sapms_text_value, tvb, offset, length, FALSE); offset+=length; + break; + } + case 0x24: /* MS_COUNTER_CREATE */ + case 0x25: /* MS_COUNTER_DELETE */ + case 0x26: /* MS_COUNTER_INCREMENT */ + case 0x27: /* MS_COUNTER_DECREMENT */ + case 0x28: /* MS_COUNTER_REGISTER */ + case 0x29:{ /* MS_COUNTER_GET */ + if (tvb_length_remaining(tvb, offset) >= 48){ + dissect_sapms_counter(tvb, tree, offset); offset+=48; + } + break; + } + case 0x2a:{ /* MS_COUNTER_LST */ + while (tvb_length_remaining(tvb, offset) >= 48){ + dissect_sapms_counter(tvb, tree, offset); offset+=48; + } + break; + } + case 0x2b: /* MS_SET_LOGON */ + case 0x2c: /* MS_GET_LOGON */ + case 0x2d:{ /* MS_DEL_LOGON */ + guint16 name_length = 0, prot_length = 0, host_length = 0, misc_length = 0, address6_length = 0; + guint32 address_ipv4; + struct e_in6_addr address_ipv6; + + proto_tree_add_item(tree, hf_sapms_logon_type, tvb, offset, 2, FALSE); offset+=2; length-=2; + proto_tree_add_item(tree, hf_sapms_logon_port, tvb, offset, 2, FALSE); offset+=2; length-=2; + + address_ipv4 = tvb_get_ipv4(tvb, offset); + proto_tree_add_ipv4(tree, hf_sapms_logon_address, tvb, offset, 4, address_ipv4); offset+=4; length-=4; + + name_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_sapms_logon_name_length, tvb, offset, 2, FALSE); offset+=2; length-=2; + if (name_length > 0 && length >= name_length){ + proto_tree_add_item(tree, hf_sapms_logon_name, tvb, offset, name_length, FALSE); offset+=name_length; length-=name_length; + } + + prot_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_sapms_logon_prot_length, tvb, offset, 2, FALSE); offset+=2; length-=2; + if (prot_length > 0 && length >= prot_length){ + proto_tree_add_item(tree, hf_sapms_logon_prot, tvb, offset, prot_length, FALSE); offset+=prot_length; length-=prot_length; + } + + host_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_sapms_logon_host_length, tvb, offset, 2, FALSE); offset+=2; length-=2; + if (host_length > 0 && length >= host_length){ + proto_tree_add_item(tree, hf_sapms_logon_host, tvb, offset, host_length, FALSE); offset+=host_length; length-=host_length; + } + + misc_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_sapms_logon_misc_length, tvb, offset, 2, FALSE); offset+=2; length-=2; + if (misc_length > 0 && length >= misc_length){ + proto_tree_add_item(tree, hf_sapms_logon_misc, tvb, offset, misc_length, FALSE); offset+=misc_length; length-=misc_length; + } + + address6_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_sapms_logon_address6_length, tvb, offset, 2, FALSE); offset+=2; length-=2; + if (address6_length==16 && length >= address6_length){ + tvb_get_ipv6(tvb, offset, &address_ipv6); + proto_tree_add_ipv6(tree, hf_sapms_logon_address6, tvb, offset, 16, (guint8 *)&address_ipv6); offset+=16; length-=16; + } else { /* Add expert info if wrong IPv6 address length */ + expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_WARN, "Invalid length (%d) or data", address6_length); + } + + break; + } + case 0x2e: /* MS_SERVER_DISC */ + case 0x2f: /* MS_SERVER_SHUTDOWN */ + case 0x30: /* MS_SERVER_SOFT_SHUTDOWN */ + case 0x4a:{ /* MS_SERVER_TEST_SOFT_SHUTDOWN */ + guint16 reason_length = 0; + + client_length = dissect_sapms_client(tvb, pinfo, tree, offset, opcode_version); offset += client_length; length -= client_length; + reason_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_sapms_shutdown_reason_length, tvb, offset, 2, FALSE); offset+=2; length-=2; + + if (reason_length > 0 && length > 0){ + reason_length = length < reason_length? length : reason_length; + proto_tree_add_item(tree, hf_sapms_shutdown_reason, tvb, offset, reason_length, FALSE); offset+=reason_length; length-=reason_length; + } + break; + } + case 0x43: /* MS_SET_PROPERTY */ + case 0x44: /* MS_GET_PROPERTY */ + case 0x45:{ /* MS_DEL_PROPERTY */ + dissect_sapms_property(tvb, tree, offset); + break; + } + case 0x46:{ /* MS_IP_PORT_TO_NAME */ + guint32 address_ipv4 = 0, name_length = 0; + struct e_in6_addr address_ipv6; + + if (opcode_version == 0x01){ + address_ipv4 = tvb_get_ipv4(tvb, offset); + proto_tree_add_ipv4(tree, hf_sapms_ip_to_name_address4, tvb, offset, 4, address_ipv4); offset+=4; length-=4; + } else if (opcode_version == 0x02){ + tvb_get_ipv6(tvb, offset, &address_ipv6); + proto_tree_add_ipv6(tree, hf_sapms_ip_to_name_address6, tvb, offset, 16, (guint8 *)&address_ipv6); offset+=16; length-=16; + } + + proto_tree_add_item(tree, hf_sapms_ip_to_name_port, tvb, offset, 2, FALSE); offset+=2; length-=2; + + name_length = tvb_get_ntohl(tvb, offset); + proto_tree_add_item(tree, hf_sapms_ip_to_name_length, tvb, offset, 4, FALSE); offset+=4; length-=4; + if (name_length > 0 && length >= name_length){ + proto_tree_add_item(tree, hf_sapms_ip_to_name, tvb, offset, name_length, FALSE); offset+=name_length; length-=name_length; + } + + break; + } + case 0x47:{ /* MS_CHECK_ACL */ + guint32 string_length = 0; + proto_tree_add_item(tree, hf_sapms_check_acl_error_code, tvb, offset, 2, FALSE); offset+=2; length-=2; + string_length = tvb_strnlen(tvb, offset, length) + 1; + proto_tree_add_item(tree, hf_sapms_check_acl_acl, tvb, offset, string_length, FALSE); offset+=string_length; length-=string_length; + string_length = tvb_strnlen(tvb, offset, length) + 1; + proto_tree_add_item(tree, hf_sapms_check_acl_acl, tvb, offset, string_length, FALSE); offset+=string_length; length-=string_length; + break; + } + default:{ + if (global_sapms_highlight_items){ + expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN, "The opcode is dissected partially (0x%.2x)", opcode); + } + break; + } + + } + +} + + +static void +dissect_sapms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint8 flag=0, iflag = 0, opcode = 0, opcode_version = 0; + guint32 offset = 0, remaining_length = 0; + + /* Add the protocol to the column */ + col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPMS"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + if (tree) { /* we are being asked for details */ + + proto_item *ti = NULL, *oi = NULL, *msg_types = NULL; + proto_tree *sapms_tree = NULL, *sapms_opcode_tree = NULL, *msg_types_tree = NULL; + + /* Add the main sapms subtree */ + ti = proto_tree_add_item(tree, proto_sapms, tvb, 0, -1, FALSE); + sapms_tree = proto_item_add_subtree(ti, ett_sapms); + + /* Check for the eye catcher string */ + if (tvb_strneql(tvb, offset, "**MESSAGE**\00", 12) == 0){ + proto_tree_add_item(sapms_tree, hf_sapms_eyecatcher, tvb, offset, 12, FALSE); offset+=12; + proto_tree_add_item(sapms_tree, hf_sapms_version, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_errorno, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_toname, tvb, offset, 40, FALSE); offset+=40; + msg_types = proto_tree_add_item(sapms_tree, hf_sapms_msgtypes, tvb, offset, 1, FALSE); + msg_types_tree = proto_item_add_subtree(msg_types, ett_sapms); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_dia, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_upd, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_enq, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_btc, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_spo, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_up2, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_atp, tvb, offset, 1, FALSE); + proto_tree_add_item(msg_types_tree, hf_sapms_msgtypes_icm, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_reserved, tvb, offset, 3, FALSE); offset+=3; + proto_tree_add_item(sapms_tree, hf_sapms_key, tvb, offset, 8, FALSE); offset+=8; + + flag = tvb_get_guint8(tvb, offset); + proto_tree_add_item(sapms_tree, hf_sapms_flag, tvb, offset, 1, FALSE); offset+=1; + proto_item_append_text(sapms_tree, ", Flag=%s", val_to_str(flag, hf_sapms_flag_vals, "Unknown")); + + iflag = tvb_get_guint8(tvb, offset); + proto_tree_add_item(sapms_tree, hf_sapms_iflag, tvb, offset, 1, FALSE); offset+=1; + proto_item_append_text(sapms_tree, ", IFlag=%s", val_to_str(iflag, hf_sapms_iflag_vals, "Unknown")); + + col_append_fstr(pinfo->cinfo, COL_INFO, "Flag=%s,IFlag=%s", val_to_str(flag, hf_sapms_flag_vals, "Unknown"), val_to_str(iflag, hf_sapms_iflag_vals, "Unknown")); + + proto_tree_add_item(sapms_tree, hf_sapms_fromname, tvb, offset, 40, FALSE); offset+=40; + + offset+=2; /* Skip 2 bytes */ + + if (!tvb_offset_exists(tvb, offset)){ + return; + } + + /* The remaining of the packet is dissected based on the flag */ + switch (iflag){ + + /* MS_SEND_NAME or unknown (forwarded messages) */ + case 0x00: + case 0x01:{ + opcode = tvb_get_guint8(tvb, offset); + proto_tree_add_item(sapms_tree, hf_sapms_opcode, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_opcode_error, tvb, offset, 1, FALSE); offset+=1; + opcode_version = tvb_get_guint8(tvb, offset); + proto_tree_add_item(sapms_tree, hf_sapms_opcode_version, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_opcode_charset, tvb, offset, 1, FALSE); offset+=1; + + proto_item_append_text(sapms_tree, ", Opcode=%s", val_to_str(opcode, hf_sapms_opcode_vals, "Unknown")); + col_append_fstr(pinfo->cinfo, COL_INFO, ", Opcode=%s", val_to_str(opcode, hf_sapms_opcode_vals, "Unknown")); + + /* Add the opcode value subtree */ + remaining_length = (guint32)tvb_length_remaining(tvb, offset); + if (remaining_length > 0){ + oi = proto_tree_add_item(sapms_tree, hf_sapms_opcode_value, tvb, offset, remaining_length, FALSE); + sapms_opcode_tree = proto_item_add_subtree(oi, ett_sapms); + dissect_sapms_opcode(tvb, pinfo, sapms_opcode_tree, offset, flag, opcode, opcode_version, remaining_length); + } + break; + + /* MS_ADM_OPCODES */ + } case 0x05:{ + proto_tree_add_item(sapms_tree, hf_sapms_adm_eyecatcher, tvb, offset, 12, FALSE); offset+=12; + proto_tree_add_item(sapms_tree, hf_sapms_adm_version, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_adm_msgtype, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(sapms_tree, hf_sapms_adm_recsize, tvb, offset, 11, FALSE); offset+=11; + proto_tree_add_item(sapms_tree, hf_sapms_adm_recno, tvb, offset, 11, FALSE); offset+=11; + + /* Add the records subtree */ + remaining_length = (guint32)tvb_length_remaining(tvb, offset); + if (remaining_length > 0){ + dissect_sapms_adm_record(tvb, pinfo, sapms_tree, offset, remaining_length); + } + break; + } + + } + + } + } +} + +void +proto_register_sapms(void) +{ + static hf_register_info hf[] = { + /* General Header fields */ + { &hf_sapms_eyecatcher, + { "Eye Catcher", "sapms.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Eye Catcher", HFILL }}, + { &hf_sapms_version, + { "Version", "sapms.version", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Version", HFILL }}, + { &hf_sapms_errorno, + { "Error Number", "sapms.errorno", FT_UINT8, BASE_HEX, hf_sapms_errorno_vals, 0x0, "SAP MS Error Number", HFILL }}, + { &hf_sapms_toname, + { "To Name", "sapms.toname", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS To Name", HFILL }}, + { &hf_sapms_msgtypes, + { "Message Type", "sapms.msgtype", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Message Type", HFILL }}, + { &hf_sapms_msgtypes_dia, + { "DIA", "sapms.msgtype.dia", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_DIA, "SAP MS Message Type DIA", + HFILL }}, + { &hf_sapms_msgtypes_upd, + { "UPD", "sapms.msgtype.upd", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_UPD, "SAP MS Message Type UPD", + HFILL }}, + { &hf_sapms_msgtypes_enq, + { "ENQ", "sapms.msgtype.enq", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_ENQ, "SAP MS Message Type ENQ", + HFILL }}, + { &hf_sapms_msgtypes_btc, + { "BTC", "sapms.msgtype.btc", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_BTC, "SAP MS Message Type BTC", + HFILL }}, + { &hf_sapms_msgtypes_spo, + { "SPO", "sapms.msgtype.spo", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_SPO, "SAP MS Message Type SPO", + HFILL }}, + { &hf_sapms_msgtypes_up2, + { "UP2", "sapms.msgtype.up2", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_UP2, "SAP MS Message Type UP2", + HFILL }}, + { &hf_sapms_msgtypes_atp, + { "ATP", "sapms.msgtype.atp", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_ATP, "SAP MS Message Type ATP", + HFILL }}, + { &hf_sapms_msgtypes_icm, + { "ICM", "sapms.msgtype.icm", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_ICM, "SAP MS Message Type ICM", + HFILL }}, + { &hf_sapms_reserved, + { "Reserved", "sapms.reserved", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Reserved", HFILL }}, + { &hf_sapms_key, + { "Key", "sapms.key", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Key", HFILL }}, + { &hf_sapms_flag, + { "Flag", "sapms.flag", FT_UINT8, BASE_HEX, hf_sapms_flag_vals, 0x0, "SAP MS Flag", HFILL }}, + { &hf_sapms_iflag, + { "IFlag", "sapms.iflag", FT_UINT8, BASE_HEX, hf_sapms_iflag_vals, 0x0, "SAP MS IFlag", HFILL }}, + { &hf_sapms_fromname, + { "From Name", "sapms.fromname", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS From Name", HFILL }}, + { &hf_sapms_fromhost, + { "From Host", "sapms.fromhost", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS From Host", HFILL }}, + { &hf_sapms_fromserv, + { "From Service", "sapms.fromserv", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS From Service", HFILL }}, + { &hf_sapms_message, + { "Message", "sapms.message", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Message", HFILL }}, + + /* ADM Message fields */ + { &hf_sapms_adm_eyecatcher, + { "Adm Eye Catcher", "sapms.adm.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Adm Eye Catcher", HFILL }}, + { &hf_sapms_adm_version, + { "Adm Version", "sapms.adm.version", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Adm Version", HFILL }}, + { &hf_sapms_adm_msgtype, + { "Adm Message Type", "sapms.adm.msgtype", FT_UINT8, BASE_HEX, hf_sapms_adm_msgtype_vals, 0x0, "SAP MS Adm Message Type", HFILL }}, + { &hf_sapms_adm_recsize, + { "Adm Record Size", "sapms.adm.recsize", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Adm Record Size", HFILL }}, + { &hf_sapms_adm_recno, + { "Adm Records Number", "sapms.adm.recno", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Adm Records Number", HFILL }}, + { &hf_sapms_adm_records, + { "Adm Records", "sapms.adm.records", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Adm Records", HFILL }}, + + { &hf_sapms_adm_record, + { "Adm Record", "sapms.adm.records", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Adm Record", HFILL }}, + { &hf_sapms_adm_record_opcode, + { "Adm Record Opcode", "sapms.adm.record.opcode", FT_UINT8, BASE_HEX, hf_sapms_adm_record_opcode_vals, 0x0, "SAP MS Adm Record Opcode", HFILL }}, + { &hf_sapms_adm_record_serial_number, + { "Adm Record Serial Number", "sapms.adm.record.serial_number", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Adm Record Serial Number", HFILL }}, + { &hf_sapms_adm_record_executed, + { "Adm Record Executed", "sapms.adm.record.executed", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Adm Record Executed", HFILL }}, + { &hf_sapms_adm_record_errorno, + { "Adm Record Error Number", "sapms.adm.record.errorno", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Adm Record Error Number", HFILL }}, + { &hf_sapms_adm_record_value, + { "Adm Record Value", "sapms.adm.record.value", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Adm Record Value", HFILL }}, + + { &hf_sapms_adm_parameter, + { "Adm Profile Parameter", "sapms.adm.parameter", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Adm Profile Parameter", HFILL }}, + + { &hf_sapms_adm_rzl_strg_type, + { "Adm RZL String Type", "sapms.adm.rzl_strg.type", FT_UINT8, BASE_HEX, hf_sapms_adm_rzl_strg_type_vals, 0x0, "SAP MS Adm RZL String Type", HFILL }}, + { &hf_sapms_adm_rzl_strg_name, + { "Adm RZL String Name", "sapms.adm.rzl_strg.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Adm RZL String Name", HFILL }}, + { &hf_sapms_adm_rzl_strg_value, + { "Adm RZL String Value", "sapms.adm.rzl_strg.value", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Adm RZL String Value", HFILL }}, + { &hf_sapms_adm_rzl_strg_value_integer, + { "Adm RZL String Integer Value", "sapms.adm.rzl_strg.value", FT_INT32, BASE_DEC, NULL, 0x0, "SAP MS Adm RZL String Integer Value", HFILL }}, + + /* OPCODE fields */ + { &hf_sapms_opcode, + { "Opcode", "sapms.opcode", FT_UINT8, BASE_HEX, hf_sapms_opcode_vals, 0x0, "SAP MS Opcode", HFILL }}, + { &hf_sapms_opcode_error, + { "Opcode Error", "sapms.opcode.error", FT_UINT8, BASE_HEX, hf_sapms_opcode_error_vals, 0x0, "SAP MS Opcode Error", HFILL }}, + { &hf_sapms_opcode_version, + { "Opcode Version", "sapms.opcode.version", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP MS Opcode Version", HFILL }}, + { &hf_sapms_opcode_charset, + { "Opcode Character Set", "sapms.opcode.charset", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP MS Opcode Character Set", HFILL }}, + { &hf_sapms_opcode_value, + { "Opcode Value", "sapms.opcode.value", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Opcode Value", HFILL }}, + + /* MS_SET/GET/DEL_PROPERTY opcode fields */ + { &hf_sapms_property_client, + { "Property Client", "sapms.property.client", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Property Client", HFILL }}, + { &hf_sapms_property_id, + { "Property ID", "sapms.property.id", FT_UINT32, BASE_HEX, hf_sapms_property_id_vals, 0x0, "SAP MS Property ID", HFILL }}, + { &hf_sapms_property_length, + { "Property Length", "sapms.property.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP MS Property Length", HFILL }}, + { &hf_sapms_property_value, + { "Property", "sapms.property.value", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Property Value", HFILL }}, + { &hf_sapms_property_ip_address, + { "Property IP Address v4", "sapms.property.ipaddr4", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP MS Property IP Address IPv4", HFILL }}, + { &hf_sapms_property_ip_address6, + { "Property IP Address v6", "sapms.property.ipaddr6", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP MS Property IP Address IPv6", HFILL }}, + { &hf_sapms_property_service, + { "Property Service Number", "sapms.property.servno", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Property Service Number", HFILL }}, + { &hf_sapms_property_release, + { "Property Release", "sapms.property.release", FT_STRINGZ, BASE_NONE, NULL, 0x0, "SAP MS Property Release", HFILL }}, + { &hf_sapms_property_release_patchno, + { "Property Patch Number", "sapms.property.patchno", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Property Patch Number", HFILL }}, + { &hf_sapms_property_release_supplvl, + { "Property Support Level", "sapms.property.supplvl", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Property Support Level", HFILL }}, + { &hf_sapms_property_release_platform, + { "Property Platform", "sapms.property.platform", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Property Platform", HFILL }}, + + /* MS_GET_CODEPAGE */ + { &hf_sapms_codepage, + { "Codepage", "sapms.codepage", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP MS Codepage", HFILL }}, + + /* MS_DUMP fields */ + { &hf_sapms_dump_dest, + { "Dump Dest", "sapms.dump.dest", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Dump Dest", HFILL }}, + { &hf_sapms_dump_filler, + { "Dump Filler", "sapms.dump.filler", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Dump Filler", HFILL }}, + { &hf_sapms_dump_index, + { "Dump Index", "sapms.dump.index", FT_UINT16, BASE_HEX, NULL, 0x0, "SAP MS Dump Index", HFILL }}, + { &hf_sapms_dump_command, + { "Dump Command", "sapms.dump.command", FT_UINT16, BASE_HEX, hf_sapms_dump_command_vals, 0x0, "SAP MS Dump Command", HFILL }}, + { &hf_sapms_dump_name, + { "Dump Name", "sapms.dump.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Dump Name", HFILL }}, + + /* MS_SERVER_LIST fields */ + { &hf_sapms_server_lst_client, + { "Client", "sapms.serverlst.client", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS Client", HFILL }}, + { &hf_sapms_server_lst_name, + { "Client Name", "sapms.serverlst.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Client Name", HFILL }}, + { &hf_sapms_server_lst_host, + { "Host", "sapms.serverlst.host", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Host", HFILL }}, + { &hf_sapms_server_lst_service, + { "Service", "sapms.serverlst.service", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Service", HFILL }}, + { &hf_sapms_server_lst_msgtypes, + { "Message Types", "sapms.serverlst.msgtypes", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS Message Types", HFILL }}, + { &hf_sapms_server_lst_msgtypes_dia, + { "DIA", "sapms.serverlst.msgtype.dia", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_DIA, "SAP MS Message Type DIA", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_upd, + { "UPD", "sapms.serverlst.msgtype.upd", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_UPD, "SAP MS Message Type UPD", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_enq, + { "ENQ", "sapms.serverlst.msgtype.enq", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_ENQ, "SAP MS Message Type ENQ", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_btc, + { "BTC", "sapms.serverlst.msgtype.btc", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_BTC, "SAP MS Message Type BTC", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_spo, + { "SPO", "sapms.serverlst.msgtype.spo", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_SPO, "SAP MS Message Type SPO", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_up2, + { "UP2", "sapms.serverlst.msgtype.up2", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_UP2, "SAP MS Message Type UP2", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_atp, + { "ATP", "sapms.serverlst.msgtype.atp", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_ATP, "SAP MS Message Type ATP", + HFILL }}, + { &hf_sapms_server_lst_msgtypes_icm, + { "ICM", "sapms.serverlst.msgtype.icm", FT_BOOLEAN, 8, NULL, SAPMS_MSG_TYPE_ICM, "SAP MS Message Type ICM", + HFILL }}, + { &hf_sapms_server_lst_hostaddr, + { "Host Address v6", "sapms.serverlst.hostaddr", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP MS Host Address IPv6", HFILL }}, + { &hf_sapms_server_lst_hostaddrv4, + { "Host Address v4", "sapms.serverlst.hostaddr4", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP MS Host Address IPv4", HFILL }}, + { &hf_sapms_server_lst_servno, + { "Service Number", "sapms.serverlst.servno", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Service Number", HFILL }}, + { &hf_sapms_server_lst_status, + { "Status", "sapms.serverlst.status", FT_UINT8, BASE_HEX, hf_sapms_server_lst_status_vals, 0x0, "SAP MS Status", HFILL }}, + { &hf_sapms_server_lst_nitrc, + { "NI Trace", "sapms.serverlst.nitrc", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP MS NI Trace", HFILL }}, + { &hf_sapms_server_lst_sys_service, + { "Sys Service", "sapms.serverlst.sysservice", FT_UINT32, BASE_HEX, NULL, 0x0, "SAP MS Sys Service", HFILL }}, + + /* MS_SET_SECURITY_KEY, MS_GET_SECURITY_KEY and MS_GET_SECURITY_KEY2 fields */ + { &hf_sapms_security_name, + { "Security Name", "sapms.security.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Security Name", HFILL }}, + { &hf_sapms_security_key, + { "Security Key", "sapms.security.key", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Security Key", HFILL }}, + { &hf_sapms_security_port, + { "Security Port", "sapms.security.port", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Security Port", HFILL }}, + { &hf_sapms_security_address, + { "Security Address v4", "sapms.security.addr", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP MS Security Address IPv4", HFILL }}, + { &hf_sapms_security_address6, + { "Security Address v6", "sapms.security.addr6", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP MS Security Address IPv6", HFILL }}, + + /* MS_SET_TEXT, MS_GET_TEXT */ + { &hf_sapms_text_name, + { "Text Name", "sapms.text.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Text Name", HFILL }}, + { &hf_sapms_text_length, + { "Text Length", "sapms.text.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP MS Text Length", HFILL }}, + { &hf_sapms_text_value, + { "Text Value", "sapms.text.value", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Text Value", HFILL }}, + + /* COUNTER fields */ + { &hf_sapms_counter_uuid, + { "Counter UUID", "sapms.counter.uuid", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Counter UUID", HFILL }}, + { &hf_sapms_counter_count, + { "Counter Count", "sapms.counter.count", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP MS Counter Count", HFILL }}, + { &hf_sapms_counter_no, + { "Counter Number", "sapms.counter.no", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP MS Counter Number", HFILL }}, + + /* CHANGE_IP fields */ + { &hf_sapms_change_ip_address, + { "Change IP Address IPv4", "sapms.change.addr", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP MS Change IP Address IPv4", HFILL }}, + { &hf_sapms_change_ip_address6, + { "Change IP Address IPv6", "sapms.change.addr6", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP MS Change IP Address IPv6", HFILL }}, + + /* FILE RELOAD fields */ + { &hf_sapms_file_reload, + { "File Reload Name", "sapms.filereload.name", FT_UINT8, BASE_HEX, hf_sapms_file_reload_vals, 0x0, "SAP MS File Reload Name", HFILL }}, + { &hf_sapms_file_filler, + { "File Reload Filler", "sapms.filereload.filler", FT_NONE, BASE_NONE, NULL, 0x0, "SAP MS File Reload Filler", HFILL }}, + + /* MS_GET_LOGON, MS_SET_LOGON and MS_DEL_LOGON fields */ + { &hf_sapms_logon_type, + { "Logon Type", "sapms.logon.type", FT_UINT16, BASE_HEX, hf_sapms_logon_type_vals, 0x0, "SAP MS Logon Type", HFILL }}, + { &hf_sapms_logon_port, + { "Logon Port", "sapms.logon.port", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Logon Port", HFILL }}, + { &hf_sapms_logon_address, + { "Logon Address IPv4", "sapms.logon.addr", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP MS Logon Address IPv4", HFILL }}, + { &hf_sapms_logon_name_length, + { "Logon Name Length", "sapms.logon.name_length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Logon Name Length", HFILL }}, + { &hf_sapms_logon_name, + { "Logon Name", "sapms.logon.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Logon Name", HFILL }}, + { &hf_sapms_logon_prot_length, + { "Logon Protocol Length", "sapms.logon.prot_length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Logon Protocol Length", HFILL }}, + { &hf_sapms_logon_prot, + { "Logon Protocol", "sapms.logon.prot", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Logon Protocol", HFILL }}, + { &hf_sapms_logon_host_length, + { "Logon Host Length", "sapms.logon.host_length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Logon Host Length", HFILL }}, + { &hf_sapms_logon_host, + { "Logon Host", "sapms.logon.host", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Logon Host", HFILL }}, + { &hf_sapms_logon_misc_length, + { "Logon Misc Length", "sapms.logon.misc_length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Logon Misc Length", HFILL }}, + { &hf_sapms_logon_misc, + { "Logon Misc", "sapms.logon.misc", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Logon Misc", HFILL }}, + { &hf_sapms_logon_address6_length, + { "Logon Address IPv6 Length", "sapms.logon.addr6_length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Logon Address IPv6 Length", HFILL }}, + { &hf_sapms_logon_address6, + { "Logon Address IPv6", "sapms.logon.address6", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Logon Address IPv6", HFILL }}, + + { &hf_sapms_shutdown_reason_length, + { "Shutdown Reason Length", "sapms.shutdown.reason_length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Shutdown Reason Length", HFILL }}, + { &hf_sapms_shutdown_reason, + { "Shutdown Reason", "sapms.shutdown.reason", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS Shutdown Reason", HFILL }}, + + /* MS_IP_PORT_TO_NAME fields */ + { &hf_sapms_ip_to_name_address4, + { "IP to Name Address IPv4", "sapms.ip_to_name.addr4", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP MS IP to Name Address IPv4", HFILL }}, + { &hf_sapms_ip_to_name_address6, + { "IP to Name Address IPv6", "sapms.ip_to_name.addr6", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP MS IP to Name Address IPv6", HFILL }}, + { &hf_sapms_ip_to_name_port, + { "IP to Name Port", "sapms.ip_to_name.port", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS IP to Name Port", HFILL }}, + { &hf_sapms_ip_to_name_length, + { "IP to Name Length", "sapms.ip_to_name.name_length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP MS IP to Name Length", HFILL }}, + { &hf_sapms_ip_to_name, + { "IP to Name", "sapms.ip_to_name.name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP MS IP to Name", HFILL }}, + + /* MS_CHECK_ACL fields */ + { &hf_sapms_check_acl_error_code, + { "Check ACL Error Code", "sapms.check_acl.error_code", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP MS Check ACL Error Code", HFILL }}, + { &hf_sapms_check_acl_acl, + { "Check ACL ACL Entry", "sapms.check_acl.acl", FT_STRINGZ, BASE_NONE, NULL, 0x0, "SAP MS Check ACL ACL Entry", HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_sapms + }; + + module_t *sapms_module; + + /* Register the protocol */ + proto_sapms = proto_register_protocol ( + "SAP Message Server Protocol", /* name */ + "SAPMS", /* short name */ + "sapms" /* abbrev */ + ); + + register_dissector("sapms", dissect_sapms, proto_sapms); + + proto_register_field_array(proto_sapms, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register the preferences */ + sapms_module = prefs_register_protocol(proto_sapms, proto_reg_handoff_sapms); + + range_convert_str(&global_sapms_port_range, SAPMS_PORT_RANGE, MAX_TCP_PORT); + prefs_register_range_preference(sapms_module, "tcp_ports", "SAP MS Protocol TCP port numbers", "Port numbers used for SAP MS Protocol (default " SAPMS_PORT_RANGE ")", &global_sapms_port_range, MAX_TCP_PORT); + + prefs_register_bool_preference(sapms_module, "highlight_unknown_items", "Highlight unknown SAP MS messages", "Whether the SAP MS Protocol dissector should highlight unknown MS messages (migth be noise and generate a lot of expert warnings)", &global_sapms_highlight_items); + +} + +/** + * Helpers for dealing with the port range + */ +static void range_delete_callback (guint32 port) +{ + dissector_delete_uint("sapni.port", port, sapms_handle); +} + +static void range_add_callback (guint32 port) +{ + dissector_add_uint("sapni.port", port, sapms_handle); +} + +/** + * Register Hand off for the SAP MS Protocol + */ +void +proto_reg_handoff_sapms(void) +{ + static range_t *sapms_port_range; + static gboolean initialized = FALSE; + + if (!initialized) { + sapms_handle = create_dissector_handle(dissect_sapms, proto_sapms); + initialized = TRUE; + } else { + range_foreach(sapms_port_range, range_delete_callback); + g_free(sapms_port_range); + } + + sapms_port_range = range_copy(global_sapms_port_range); + range_foreach(sapms_port_range, range_add_callback); +} + diff --git a/packet-sapprotocol.c b/packet-sapprotocol.c new file mode 100644 index 0000000..e86a6ac --- /dev/null +++ b/packet-sapprotocol.c @@ -0,0 +1,275 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "packet-sapprotocol.h" + + +/* Define default ports */ +#define SAP_PROTOCOL_PORT_RANGE "3200-3999" + +/* + * Length of the frame header + */ +#define SAP_PROTOCOL_HEADER_LEN 4 + +static int proto_sap_protocol = -1; + +static int hf_sap_protocol_length = -1; +static int hf_sap_protocol_payload = -1; + +static int hf_sap_protocol_ping = -1; +static int hf_sap_protocol_pong = -1; + +static gint ett_sap_protocol = -1; + +/* Global port preference */ +static range_t *global_sap_protocol_port_range; + +/* Global reassemble preference */ +static gboolean global_sap_protocol_desegment = TRUE; + +/* Protocol handle */ +static dissector_handle_t sap_protocol_handle; + +/* Sub-dissectors table */ +static dissector_table_t sub_dissectors_table; +static heur_dissector_list_t heur_subdissector_list; + +/* + * + */ +void proto_reg_handoff_sap_protocol(void); + +/* + * Get the SAPNI pdu length + */ +static guint +get_sap_protocol_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) +{ + return ((guint)tvb_get_ntohl(tvb, offset - offset) + 4); +} + + +/* + * Dissect the payload of a packet using a registered SAP protocol. It uses + * heuristics as a first try as some protocols uses the same TCP ports + * (e.g. 3200/tcp for Enqueue Server and Diag). + */ +void +dissect_sap_protocol_payload(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, guint16 sport, guint16 dport){ + guint16 low_port = 0, high_port = 0; + tvbuff_t *next_tvb = NULL; + + /* Set the new tvb for further dissection of the payload */ + next_tvb = tvb_new_subset_remaining(tvb, offset); + + /* Determine if this packet is part of a conversation and call dissector + * for the conversation if available. + * TODO: Check for building with conversation.h include */ + /* + if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_TCP, + dport, sport, next_tvb, pinfo, tree)) { + return; + } + */ + + /* Try with the heuristic dissectors first */ + /* TODO: When the protocol is guessed via heuristic dissector (Enqueue + * Server), the NI Protocol tree is missed. */ + if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, NULL)) { + return; + } + + /* Call the dissector in the subdissectors table according to the port number */ + if (sport > dport) { + low_port = dport; high_port = sport; + } else { + low_port = sport; high_port = dport; + } + if ((low_port != 0 && dissector_try_uint(sub_dissectors_table, low_port, next_tvb, pinfo, tree)) || + (high_port != 0 && dissector_try_uint(sub_dissectors_table, high_port, next_tvb, pinfo, tree))){ + return; + } +} + + +/* + * Dissect a SAPNI packet, adding the length field to the protocol tree and + * calling the sub-dissector according to the port number. It also identifies + * PING/PONG packets at the SAPNI layer. + */ +static void +dissect_sap_protocol_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint32 length = 0; + proto_item *ti = NULL, *sap_protocol_length = NULL; + proto_tree *sap_protocol_tree = NULL; + + /* Add the protocol to the column */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SAPNI"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + /* Get the length field */ + length = tvb_get_ntohl(tvb, 0); + + /* Add the payload length to the info column */ + col_add_fstr(pinfo->cinfo, COL_INFO, "Length=%d ", length); + + /* We are being asked for details */ + if (tree) { + /* Add the main SAP Protocol subtree */ + ti = proto_tree_add_item(tree, proto_sap_protocol, tvb, 0, -1, FALSE); + sap_protocol_tree = proto_item_add_subtree(ti, ett_sap_protocol); + + /* Add the length item */ + proto_item_append_text(ti, ", Len: %u", length); + sap_protocol_length = proto_tree_add_item(sap_protocol_tree, hf_sap_protocol_length, tvb, 0, 4, FALSE); + + /* Add expert info in case of no match between the given length and the actual one */ + if (tvb_reported_length(tvb) != length + 4) { + expert_add_info_format(pinfo, sap_protocol_length, PI_MALFORMED, PI_WARN, "The reported length is incorrect"); + } + + /* Add the payload subtree */ + if (length > 0){ + proto_tree_add_item(sap_protocol_tree, hf_sap_protocol_payload, tvb, 4, -1, FALSE); + } + } + + /* Check for NI_PING/NI_PONG values */ + if ((length == 8)&&(tvb_strneql(tvb, 4, "NI_PING\00", 8) == 0)){ + col_set_str(pinfo->cinfo, COL_INFO, "Ping Message"); + if (tree){ + proto_item_append_text(ti, ", Ping Message (keep-alive request)"); + proto_tree_add_item(sap_protocol_tree, hf_sap_protocol_ping, tvb, 4, -1, FALSE); + } + } else if ((length == 8)&&(tvb_strneql(tvb, 4, "NI_PONG\00", 8) == 0)){ + col_set_str(pinfo->cinfo, COL_INFO, "Pong Message"); + if (tree){ + proto_item_append_text(ti, ", Pong Message (keep-alive response / route accepted)"); + proto_tree_add_item(sap_protocol_tree, hf_sap_protocol_pong, tvb, 4, -1, FALSE); + } + + /* Dissect the payload */ + } else if (length > 0){ + dissect_sap_protocol_payload(tvb, 4, pinfo, tree, pinfo->srcport, pinfo->destport); + } +} + +/* + * Performs the TCP reassembling and dissects the packet. + */ +static void +dissect_sap_protocol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + tcp_dissect_pdus(tvb, pinfo, tree, global_sap_protocol_desegment, SAP_PROTOCOL_HEADER_LEN, + get_sap_protocol_pdu_len, dissect_sap_protocol_message); +} + +void +proto_register_sap_protocol(void) +{ + static hf_register_info hf[] = { + { &hf_sap_protocol_length, + { "Length", "sapni.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP NI Protocol Message Length", HFILL }}, + { &hf_sap_protocol_payload, + { "Payload", "sapni.payload", FT_NONE, BASE_NONE, NULL, 0x0, "SAP NI Protocol Payload", HFILL }}, + { &hf_sap_protocol_ping, + { "Ping", "sapni.ping", FT_NONE, BASE_NONE, NULL, 0x0, "SAP NI Ping Message", HFILL }}, + { &hf_sap_protocol_pong, + { "Pong", "sapni.pong", FT_NONE, BASE_NONE, NULL, 0x0, "SAP NI Pong Message", HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_sap_protocol + }; + + module_t *sap_protocol_module; + + /* Register the protocol */ + proto_sap_protocol = proto_register_protocol ( + "SAP NI Protocol", /* name */ + "SAPNI", /* short name */ + "sapni" /* abbrev */ + ); + + proto_register_field_array(proto_sap_protocol, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("sapni", dissect_sap_protocol, proto_sap_protocol); + + /* Sub dissector code */ + sub_dissectors_table = register_dissector_table("sapni.port", "SAP Protocol Port", FT_UINT16, BASE_DEC); + register_heur_dissector_list("sapni", &heur_subdissector_list); + + /* Register the preferences */ + sap_protocol_module = prefs_register_protocol(proto_sap_protocol, proto_reg_handoff_sap_protocol); + + range_convert_str(&global_sap_protocol_port_range, SAP_PROTOCOL_PORT_RANGE, MAX_TCP_PORT); + prefs_register_range_preference(sap_protocol_module, "tcp_ports", "SAP NI Protocol TCP port numbers", "Port numbers used for SAP NI Protocol (default " SAP_PROTOCOL_PORT_RANGE ")", &global_sap_protocol_port_range, MAX_TCP_PORT); + + prefs_register_bool_preference(sap_protocol_module, "desegment", "Reassemble SAP NI Protocol messages spanning multiple TCP segments", "Whether the SAP NI Protocol dissector should reassemble messages spanning multiple TCP segments.", &global_sap_protocol_desegment); +} + +/** + * Helpers for dealing with the port range + */ +static void range_delete_callback (guint32 port) +{ + dissector_delete_uint("tcp.port", port, sap_protocol_handle); +} + +static void range_add_callback (guint32 port) +{ + dissector_add_uint("tcp.port", port, sap_protocol_handle); +} + +/** + * Register Hand off for the SAP NI Protocol + */ +void +proto_reg_handoff_sap_protocol(void) +{ + static range_t *sap_protocol_port_range; + static gboolean initialized = FALSE; + + if (!initialized) { + sap_protocol_handle = find_dissector("sapni"); + initialized = TRUE; + } else { + range_foreach(sap_protocol_port_range, range_delete_callback); + g_free(sap_protocol_port_range); + } + + sap_protocol_port_range = range_copy(global_sap_protocol_port_range); + range_foreach(sap_protocol_port_range, range_add_callback); +} diff --git a/packet-sapprotocol.h b/packet-sapprotocol.h new file mode 100644 index 0000000..f0d2773 --- /dev/null +++ b/packet-sapprotocol.h @@ -0,0 +1,30 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#ifndef __PACKET_SAPPROTOCOL_H__ +#define __PACKET_SAPPROTOCOL_H__ + +#include + +extern void +dissect_sap_protocol_payload(tvbuff_t *tvb, guint32 offset, packet_info *pinfo, proto_tree *tree, guint16 sport, guint16 dport); + +#endif /* __PACKET_SAPPROTOCOL_H__ */ diff --git a/packet-saprfc.c b/packet-saprfc.c new file mode 100644 index 0000000..9bb780c --- /dev/null +++ b/packet-saprfc.c @@ -0,0 +1,1271 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include +#include +#include + +/* Common helpers for adding items */ +#include "saphelpers.h" + +/* SAP Decompression routine */ +#include "sapdecompress.h" + +/* Define default ports */ +#define SAPRFC_PORT_RANGE "3300-3399" + + +/* SAP RFC Request Types field values */ +static const value_string hf_saprfc_reqtype_values[] = { + { 0x00, "GW_UNDEF_TYPE" }, + { 0x01, "GW_CHECK_GATEWAY" }, + { 0x02, "GW_CONNECT_GWWP" }, + { 0x03, "GW_NORMAL_CLIENT" }, + { 0x04, "GW_REMOTE_GATEWAY" }, + { 0x05, "STOP_GATEWAY" }, + { 0x06, "GW_LOCAL_R3" }, + { 0x07, "GW_SEND_INTERNAL_ERROR" }, + { 0x08, "GW_SEND_INFO" }, + { 0x09, "GW_SEND_CMD" }, + { 0x0a, "GW_WORKPROCESS_DIED" }, + { 0x0b, "GW_REGISTER_TP" }, + { 0x0c, "GW_UNREGISTER_TP" }, + { 0x0d, "GW_CONNECT_DISP" }, + { 0x0e, "GW_GET_NO_REGISTER_TP" }, + { 0x0f, "GW_SAP_WP_CLIENT" }, + { 0x10, "GW_CANCEL_REGISTER_TP" }, + { 0x11, "REMOTE_GATEWAY" }, + { 0x12, "GW_CONTAINER_RECEIVED" }, +}; + +/* SAP RFC Monitor Command field values */ +static const value_string hf_saprfc_monitor_cmd_values[] = { + { 0x01, "NOOP" }, + { 0x02, "DELETE_CONN" }, + { 0x03, "CANCEL_CONN" }, + { 0x04, "RST_SINGLE_ERR_CNT" }, + { 0x05, "RST_ALL_ERR_CNT" }, + { 0x06, "INCREASE_TRACE" }, + { 0x07, "DECREASE_TRACE" }, + { 0x08, "READ_SEC_INFO" }, + { 0x09, "REFRESH_SEC_INFO" }, + { 0x0a, "READ_GWSYS_TBL" }, + { 0x0b, "READ_CONN_TBL" }, + { 0x0c, "READ_PROC_TBL" }, + { 0x0d, "READ_CONN_ATTR" }, + { 0x0e, "READ_MEMORY" }, + { 0x0f, "READ_REQ_BLK" }, + { 0x10, "ACT_STATISTIC" }, + { 0x11, "DEACT_STATISTIC" }, + { 0x12, "READ_STATISTIC" }, + { 0x13, "RESET_STATISTIC" }, + { 0x14, "READ_PARAMETER" }, + { 0x19, "DUMP_NIBUFFER" }, + { 0x20, "RESET_NIBUFFER" }, + { 0x21, "ACT_EXTPGM_TRACE" }, + { 0x22, "DEACT_EXTPGM_TRACE" }, + { 0x23, "ACT_CONN_TRACE" }, + { 0x24, "DEACT_CONN_TRACE" }, + { 0x25, "RESET_TRACE" }, + { 0x26, "SUICIDE" }, + { 0x27, "READ_SEC_INFO2" }, + { 0x28, "CANCEL_REG_TP" }, + { 0x29, "DUMP" }, + { 0x2a, "READ_GWSYS_TBL2" }, + { 0x2b, "CHANGE_PARAMETER" }, + { 0x2c, "GET_CONN_PARTNER" }, + { 0x2d, "DELETE_CLIENT" }, + { 0x2e, "DELETE_REMGW" }, + { 0x2f, "DISCONNECT" }, + { 0x30, "ENABLE_RESTART" }, + { 0x31, "DISABLE_RESTART" }, + { 0x32, "NI_TRACE" }, + { 0x33, "CLI_INFO" }, + { 0x34, "GW_INFO" }, + { 0x35, "CONVID_INFO" }, + { 0x36, "GET_NO_REG_TP" }, + { 0x37, "CV_INFO" }, + { 0x38, "SO_KEEPALIVE" }, + { 0x39, "READ_CONN_TBL2" }, + { 0x40, "READ_GWSYS_TBL3" }, + { 0x41, "RELOAD_ACL" }, + { 0x00, NULL } +}; + +/* SAP RFC APPC Header Request Type field values */ +static const value_string hf_saprfc_header_reqtype_values[] = { + { 0x00, "F_NO_REQUEST" }, + { 0x01, "F_INITIALIZE_CONVERSATION" }, + { 0x03, "F_ACCEPT_CONVERSATION" }, + { 0x05, "F_ALLOCATE" }, + { 0x07, "F_SEND_DATA" }, + { 0x08, "F_ASEND_DATA" }, + { 0x09, "F_RECEIVE" }, + { 0x0a, "F_ARECEIVE" }, + { 0x0b, "F_DEALLOCATE" }, + { 0x0d, "F_SET_TP_NAME" }, + { 0x0f, "F_SET_PARTNER_LU_NAME" }, + { 0x11, "F_SET_SECURITY_PASSWORD" }, + { 0x13, "F_SET_SECURITY_USER_ID" }, + { 0x15, "F_SET_SECURITY_TYPE" }, + { 0x17, "F_SET_CONVERSATION_TYPE" }, + { 0x19, "F_EXTRACT_TP_NAME" }, + { 0x1b, "F_FLUSH" }, + { 0xc9, "F_SAP_ALLOCATE" }, + { 0xca, "F_SAP_INIT" }, + { 0xcb, "F_SAP_SEND" }, + { 0xcc, "F_ASAP_SEND" }, + { 0xcd, "F_SAP_SYNC" }, + { 0xce, "F_SAP_PING" }, + { 0xcf, "F_SAP_REGTP" }, + { 0xd0, "F_SAP_UNREGTP" }, + { 0xd1, "F_SAP_ACCPTP" }, + { 0xd2, "F_SAP_UNACCPTP" }, + { 0xd3, "F_SAP_CANCTP" }, + { 0xd4, "F_SAP_SET_UID" }, + { 0xd5, "F_SAP_CANCEL" }, + { 0xd6, "F_SAP_CANCELED" }, +}; + + +/* SAP RFC APPC Header Protocol field values */ +static const value_string hf_saprfc_header_protocol_values[] = { + { 0x00, "R2PR" }, + { 0x01, "INT" }, + { 0x02, "EXT" }, + { 0x03, "CPIC" }, + { 0x05, "NE" }, + { 0x06, "REG" }, + { 0x42, "CPIC" }, + { 0x44, "EXT" }, + { 0x45, "NE" }, + { 0x48, "INT" }, + { 0x61, "REG" }, +}; + +/* SAP RFC APPC Header APPC Return Code field values */ +static const value_string hf_saprfc_header_appc_rc_values[] = { + { 0x00, "CM_OK" }, + { 0x01, "CM_ALLOCATE_FAILURE_NO_RETRY" }, + { 0x02, "CM_ALLOCATE_FAILURE_RETRY" }, + { 0x03, "CM_CONVERSATION_TYPE_MISMATCH" }, + { 0x06, "CM_SECURITY_NOT_VALID" }, + { 0x08, "CM_SYNC_LVL_NOT_SUPPORTED_PGM" }, + { 0x09, "CM_TPN_NOT_RECOGNIZED" }, + { 0x0a, "CM_TP_NOT_AVAILABLE_NO_RETRY" }, + { 0x0b, "CM_TP_NOT_AVAILABLE_RETRY" }, + { 0x11, "CM_DEALLOCATED_ABEND" }, + { 0x12, "CM_DEALLOCATED_NORMAL" }, + { 0x13, "CM_PARAMETER_ERROR" }, + { 0x14, "CM_PRODUCT_SPECIFIC_ERROR" }, + { 0x15, "CM_PROGRAM_ERROR_NO_TRUNC" }, + { 0x16, "CM_PROGRAM_ERROR_PURGING" }, + { 0x17, "CM_PROGRAM_ERROR_TRUNC" }, + { 0x18, "CM_PROGRAM_PARAMETER_CHECK" }, + { 0x19, "CM_PROGRAM_STATE_CHECK" }, + { 0x1a, "CM_RESOURCE_FAILURE_NO_RETRY" }, + { 0x1b, "CM_RESOURCE_FAILURE_RETRY" }, + { 0x1c, "CM_UNSUCCESSFUL" }, + { 0x23, "CM_OPERATION_INCOMPLETE" }, + { 0x24, "CM_SYSTEM_EVENT" }, + { 0x2711, "CM_SAP_TIMEOUT_RETRY" }, + { 0x2712, "CM_CANCEL_REQUEST" }, +}; + +/* SAP RFC APPC Header MCPIC Parameters Client Info values */ +static const value_string hf_saprfc_header_ncpic_parameters_client_info_values[] = { + { 0x00, "GW_NO_CLIENT_INFO" }, + { 0x01, "GW_EXTERNAL_CLIENT" }, + { 0x02, "GW_R3_CLIENT" }, +}; + + +/* SAP RFC Accept Info Flag values */ +#define SAPRFC_ACCEPT_INFO_EINFO 0x01 +#define SAPRFC_ACCEPT_INFO_PING 0x02 +#define SAPRFC_ACCEPT_INFO_SNC 0x04 +#define SAPRFC_ACCEPT_INFO_CONN_EINFO 0x08 +#define SAPRFC_ACCEPT_INFO_CODE_PAGE 0x10 +#define SAPRFC_ACCEPT_INFO_NIPING 0x20 +#define SAPRFC_ACCEPT_INFO_EXTINITOPT 0x40 +#define SAPRFC_ACCEPT_INFO_GW_ACCEPT_DIST_TRACE 0x80 + +/* SAP RFC APPC Header Info Flags values */ +#define SAPRFC_APPCHDR_INFO1_SYNC_CPIC_FUNCTION 0x01 +#define SAPRFC_APPCHDR_INFO1_WITH_HOSTADDR 0x02 +#define SAPRFC_APPCHDR_INFO1_WITH_GW_SAP_PARAMS_HDR 0x04 +#define SAPRFC_APPCHDR_INFO1_CPIC_SYNC_REQ 0x08 +#define SAPRFC_APPCHDR_INFO1_WITH_ERR_INFO 0x10 +#define SAPRFC_APPCHDR_INFO1_DATA_WITH_TERM_OUTPUT 0x20 +#define SAPRFC_APPCHDR_INFO1_DATA_WITH_TERM_INPUT 0x40 +#define SAPRFC_APPCHDR_INFO1_R3_CPIC_LOGIN_WITH_TERM 0x80 + +#define SAPRFC_APPCHDR_INFO2_WITH_LONG_LU_NAME 0x01 +#define SAPRFC_APPCHDR_INFO2_WITH_LONG_HOSTADDR 0x02 +#define SAPRFC_APPCHDR_INFO2_GW_IMMEDIATE 0x04 +#define SAPRFC_APPCHDR_INFO2_GW_SNC_ACTIVE 0x08 +#define SAPRFC_APPCHDR_INFO2_GW_WAIT_LOOK_UP 0x10 +#define SAPRFC_APPCHDR_INFO2_SNC_INIT_PHASE 0x20 +#define SAPRFC_APPCHDR_INFO2_GW_STATELESS 0x40 +#define SAPRFC_APPCHDR_INFO2_GW_NO_STATE_CHECK 0x80 + +#define SAPRFC_APPCHDR_INFO3_GW_WITH_CODE_PAGE 0x01 +#define SAPRFC_APPCHDR_INFO3_GW_ASYNC_RFC 0x02 +#define SAPRFC_APPCHDR_INFO3_GW_CANCEL_HARD 0x04 +#define SAPRFC_APPCHDR_INFO3_GW_CANCEL_SOFT 0x08 +#define SAPRFC_APPCHDR_INFO3_GW_WITH_GUI_TIMEOUT 0x10 +#define SAPRFC_APPCHDR_INFO3_GW_TERMIO_ERROR 0x20 +#define SAPRFC_APPCHDR_INFO3_GW_EXTENDED_INIT_OPTIONS 0x40 +#define SAPRFC_APPCHDR_INFO3_GW_DIST_TRACE 0x80 + +#define SAPRFC_APPCHDR_INFO4_GW_WITH_DBG_CTL 0x01 + +/* SAP RFC APPC Header Request Type 2 Flags values */ +#define SAPRFC_APPCHDR_REQTYPE2_F_V_INITIALIZE_CONVERSATION 0x01 +#define SAPRFC_APPCHDR_REQTYPE2_F_V_ALLOCATE 0x02 +#define SAPRFC_APPCHDR_REQTYPE2_F_V_SEND_DATA 0x04 +#define SAPRFC_APPCHDR_REQTYPE2_F_V_RECEIVE 0x08 +#define SAPRFC_APPCHDR_REQTYPE2_F_V_FLUSH 0x10 + + +static int proto_saprfc = -1; + +static int hf_saprfc_version = -1; +static int hf_saprfc_reqtype = -1; +static int hf_saprfc_address = -1; +static int hf_saprfc_service = -1; +static int hf_saprfc_codepage = -1; +static int hf_saprfc_lu = -1; +static int hf_saprfc_tp = -1; +static int hf_saprfc_conversation_id = -1; +static int hf_saprfc_appc_header_version = -1; +static int hf_saprfc_accept_info = -1; // (EINFO PING CONN_EINFO EXTINITOPT GW_ACCEPT_DIST_TRACE (0xCB)) +static int hf_saprfc_accept_info_EINFO = -1; +static int hf_saprfc_accept_info_PING = -1; +static int hf_saprfc_accept_info_SNC = -1; +static int hf_saprfc_accept_info_CONN_EINFO = -1; +static int hf_saprfc_accept_info_CODE_PAGE = -1; +static int hf_saprfc_accept_info_NIPING = -1; +static int hf_saprfc_accept_info_EXTINITOPT = -1; +static int hf_saprfc_accept_info_GW_ACCEPT_DIST_TRACE = -1; +static int hf_saprfc_idx = -1; +static int hf_saprfc_address6 = -1; +static int hf_saprfc_rc = -1; +static int hf_saprfc_echo_data = -1; +static int hf_saprfc_filler = -1; + +static int hf_saprfc_monitor_cmd = -1; + +static int hf_saprfc_header = -1; +static int hf_saprfc_header_version = -1; +static int hf_saprfc_header_reqtype = -1; +static int hf_saprfc_header_protocol = -1; +static int hf_saprfc_header_mode = -1; +static int hf_saprfc_header_uid = -1; +static int hf_saprfc_header_gw_id = -1; +static int hf_saprfc_header_err_len = -1; +static int hf_saprfc_header_info2 = -1; +static int hf_saprfc_header_info2_WITH_LONG_LU_NAME = -1; +static int hf_saprfc_header_info2_WITH_LONG_HOSTADDR = -1; +static int hf_saprfc_header_info2_GW_IMMEDIATE = -1; +static int hf_saprfc_header_info2_GW_SNC_ACTIVE = -1; +static int hf_saprfc_header_info2_GW_WAIT_LOOK_UP = -1; +static int hf_saprfc_header_info2_SNC_INIT_PHASE = -1; +static int hf_saprfc_header_info2_GW_STATELESS = -1; +static int hf_saprfc_header_info2_GW_NO_STATE_CHECK = -1; +static int hf_saprfc_header_trace_level = -1; +static int hf_saprfc_header_time = -1; +static int hf_saprfc_header_info3 = -1; +static int hf_saprfc_header_info3_GW_WITH_CODE_PAGE = -1; +static int hf_saprfc_header_info3_GW_ASYNC_RFC = -1; +static int hf_saprfc_header_info3_GW_CANCEL_HARD = -1; +static int hf_saprfc_header_info3_GW_CANCEL_SOFT = -1; +static int hf_saprfc_header_info3_GW_WITH_GUI_TIMEOUT = -1; +static int hf_saprfc_header_info3_GW_TERMIO_ERROR = -1; +static int hf_saprfc_header_info3_GW_EXTENDED_INIT_OPTIONS = -1; +static int hf_saprfc_header_info3_GW_DIST_TRACE = -1; +static int hf_saprfc_header_timeout = -1; +static int hf_saprfc_header_info4 = -1; +static int hf_saprfc_header_info4_GW_WITH_DBG_CTL = -1; +static int hf_saprfc_header_sequence_no = -1; +static int hf_saprfc_header_sap_params_len = -1; +static int hf_saprfc_header_info = -1; +static int hf_saprfc_header_info_SYNC_CPIC_FUNCTION = -1; +static int hf_saprfc_header_info_WITH_HOSTADDR = -1; +static int hf_saprfc_header_info_WITH_GW_SAP_PARAMS_HDR = -1; +static int hf_saprfc_header_info_CPIC_SYNC_REQ = -1; +static int hf_saprfc_header_info_WITH_ERR_INFO = -1; +static int hf_saprfc_header_info_DATA_WITH_TERM_OUTPUT = -1; +static int hf_saprfc_header_info_DATA_WITH_TERM_INPUT = -1; +static int hf_saprfc_header_info_R3_CPIC_LOGIN_WITH_TERM = -1; +static int hf_saprfc_header_reqtype2 = -1; +static int hf_saprfc_header_reqtype2_F_V_INITIALIZE_CONVERSATION = -1; +static int hf_saprfc_header_reqtype2_F_V_ALLOCATE = -1; +static int hf_saprfc_header_reqtype2_F_V_SEND_DATA = -1; +static int hf_saprfc_header_reqtype2_F_V_RECEIVE = -1; +static int hf_saprfc_header_reqtype2_F_V_FLUSH = -1; +static int hf_saprfc_header_appc_rc = -1; +static int hf_saprfc_header_sap_rc = -1; // TODO: Add SAP Return values +static int hf_saprfc_header_conversation_id = -1; +static int hf_saprfc_header_ncpic_parameters = -1; +static int hf_saprfc_header_ncpic_parameters_sdest = -1; +static int hf_saprfc_header_ncpic_parameters_lu = -1; +static int hf_saprfc_header_ncpic_parameters_tp = -1; +static int hf_saprfc_header_ncpic_parameters_ctype = -1; +static int hf_saprfc_header_ncpic_parameters_client_info = -1; +static int hf_saprfc_header_ncpic_parameters_lu_name = -1; +static int hf_saprfc_header_ncpic_parameters_lu_name_length = -1; +static int hf_saprfc_header_ncpic_parameters_host_address = -1; +static int hf_saprfc_header_ncpic_parameters_security_password = -1; +static int hf_saprfc_header_ncpic_parameters_security_password_length = -1; + +static int hf_saprfc_header_comm_idx = -1; +static int hf_saprfc_header_conn_idx = -1; + +static int hf_saprfc_rfcheader = -1; + +static int hf_saprfc_ucheader = -1; +static int hf_saprfc_ucheader_codepage = -1; +static int hf_saprfc_ucheader_ce = -1; +static int hf_saprfc_ucheader_et = -1; +static int hf_saprfc_ucheader_cs = -1; +static int hf_saprfc_ucheader_returncode = -1; + +static int hf_saprfc_item = -1; +static int hf_saprfc_item_id1 = -1; +static int hf_saprfc_item_id2 = -1; +static int hf_saprfc_item_id3 = -1; +static int hf_saprfc_item_id4 = -1; +static int hf_saprfc_item_length = -1; +static int hf_saprfc_item_value = -1; + +static int hf_saprfc_table = -1; +static int hf_saprfc_table_length = -1; +static int hf_saprfc_table_compress_header = -1; +static int hf_saprfc_table_uncomplength = -1; +static int hf_saprfc_table_algorithm = -1; +static int hf_saprfc_table_magic = -1; +static int hf_saprfc_table_special = -1; +static int hf_saprfc_table_return_code = -1; +static int hf_saprfc_table_content = -1; + +static int hf_saprfc_payload = -1; + + +/* TODO: Add CPIC error codes (http://service.sap.com/sap/support/notes/63347) */ +/* TODO: Add RFC logon error codes (http://service.sap.com/sap/support/notes/320991) */ + +static gint ett_saprfc = -1; + +/* Global decompress preference */ +static gboolean global_saprfc_decompress = TRUE; + +/* Global table reassembling preference */ +static gboolean global_saprfc_table_reassembly = TRUE; + +/* Global port preference */ +static range_t *global_saprfc_port_range; + +/* Global highlight preference */ +static gboolean global_saprfc_highlight_items = TRUE; + +/* Protocol handles for both external and internal dissectors */ +static dissector_handle_t saprfc_handle; +static dissector_handle_t saprfcinternal_handle; + + +void proto_reg_handoff_saprfc(void); + + +static void +dissect_saprfc_tables_compressed(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){ + + int rt = 0; + guint8 *decompressed_buffer; + guint32 reported_length = 0, uncompress_length = 0, offset = 0, initial_offset = 0; + + proto_item *compression_header = NULL, *rl = NULL; + proto_tree *compression_header_tree = NULL; + + tvbuff_t *next_tvb = NULL; + + /* Skip the first 8 bytes */ + initial_offset = offset = 8; + + /* Add the compression header subtree */ + compression_header = proto_tree_add_item(tree, hf_saprfc_table_compress_header, tvb, offset, 8, FALSE); + compression_header_tree = proto_item_add_subtree(compression_header, ett_saprfc); + + /* Add the uncompressed length */ + reported_length = tvb_get_letohl(tvb, offset); + rl = proto_tree_add_uint(compression_header_tree, hf_saprfc_table_uncomplength, tvb, offset, 4, reported_length); offset+=4; + proto_item_append_text(compression_header, ", Uncompressed Len: %u", reported_length); + + /* Add the algorithm */ + proto_tree_add_item(compression_header_tree, hf_saprfc_table_algorithm, tvb, offset, 1, FALSE); offset++; + /* Add the magic bytes */ + proto_tree_add_item(compression_header_tree, hf_saprfc_table_magic, tvb, offset, 2, FALSE); offset+=2; + /* Add the max bits */ + proto_tree_add_item(compression_header_tree, hf_saprfc_table_special, tvb, offset, 1, FALSE); offset++; + + if (global_saprfc_decompress == TRUE){ + /* Allocate the buffer only in the scope of current packet, using the + * reported length */ + decompressed_buffer = (guint8 *)wmem_alloc0(wmem_packet_scope(), reported_length); + if (!decompressed_buffer){ + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_ERROR, "Error allocating buffer for decompress the RFC table"); + return; + } + + uncompress_length = reported_length; + + /* Decompress the payload */ + rt = decompress_packet(tvb_get_ptr(tvb, initial_offset, -1), + tvb_length_remaining(tvb, initial_offset), + decompressed_buffer, + &uncompress_length); + + /* Check the return code and add a expert info warning if an error + * occurred. The dissector continues trying to add the payload, + * however the returned size should be 0. */ + if (rt < 0){ + expert_add_info_format(pinfo, compression_header, PI_MALFORMED, PI_WARN, "Decompression of payload failed with return code %d (%s)", rt, val_to_str(rt, hf_decompress_return_code_vals, "Unknown")); + } + + /* Check the length returned for the compression routine. If differs + * with the reported, use the actual one and add an expert info + * warning. */ + if (uncompress_length != reported_length){ + expert_add_info_format(pinfo, rl, PI_MALFORMED, PI_WARN, "The uncompressed payload length (%d) differs with the reported length (%d)", uncompress_length, reported_length); + } + + /* TODO: Add the return code to the tree */ + + if (uncompress_length != 0){ + /* Now re-setup the tvb buffer to have the new data */ + next_tvb = tvb_new_real_data(decompressed_buffer, uncompress_length, uncompress_length); + tvb_set_child_real_data_tvbuff(tvb, next_tvb); + add_new_data_source(pinfo, next_tvb, "Uncompressed Table Data"); + + /* Add the payload subtree using the new tvb*/ + proto_tree_add_item(tree, hf_saprfc_table_content, next_tvb, 0, -1, FALSE); + } + + } else { + /* Add the payload subtree */ + proto_tree_add_item(tree, hf_saprfc_table_content, tvb, offset, -1, FALSE); + } + + /* TODO: Dissect saprfc_payload */ +} + +static void +dissect_saprfc_tables(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, guint16 item_length){ + + guint8 *reassemble_buffer = NULL; + guint32 reassemble_length = 0, reassemble_offset = 0, next_item = 0, initial_offset = offset; + + proto_item *table = NULL; + proto_tree *table_tree = NULL; + tvbuff_t *compressed_tvb = NULL; + + /* Get the reassemble length */ + reassemble_length = tvb_get_ntohl(tvb, offset + 4); + if (item_length > (reassemble_length - reassemble_offset)){ + item_length = reassemble_length - reassemble_offset; + } + + /* Allocate the buffer only in the scope of current packet */ + reassemble_buffer = (guint8 *)wmem_alloc(wmem_packet_scope(), reassemble_length); + if (!reassemble_buffer){ + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_ERROR, "Error allocating buffer for reassemble the RFC table"); + return; + } + + /* Perform the reassemble */ + while (tvb_offset_exists(tvb, offset + item_length) && (reassemble_offset <= reassemble_length)){ + tvb_memcpy(tvb, reassemble_buffer + reassemble_offset, offset, item_length); + offset += item_length; reassemble_offset += item_length; + + /* If the table content continues, get the length and advance the offset */ + next_item = tvb_get_ntohl(tvb, offset); offset+=4; + if (next_item == 0x03050305){ + item_length = tvb_get_ntohs(tvb, offset); offset+=2; + + if (item_length > (reassemble_length - reassemble_offset)){ + item_length = reassemble_length - reassemble_offset; + } + + /* If the table content doesn't continue, we've completed */ + } else { + break; + } + } + + /* Now re-setup the tvb buffer to have the new data */ + compressed_tvb = tvb_new_real_data(reassemble_buffer, reassemble_length, reassemble_offset); + tvb_set_child_real_data_tvbuff(tvb, compressed_tvb); + add_new_data_source(pinfo, compressed_tvb, "Compressed Table Data"); + + /* Add the Table subtree */ + table = proto_tree_add_item(tree, hf_saprfc_table, tvb, initial_offset, offset - initial_offset, FALSE); + table_tree = proto_item_add_subtree(table, ett_saprfc); + + /* Now uncompress the table content */ + dissect_saprfc_tables_compressed(compressed_tvb, pinfo, table_tree); + +} + +static void +dissect_saprfc_item(tvbuff_t *tvb, packet_info *pinfo, proto_item *item, proto_tree *item_value_tree, guint32 offset, guint8 item_id1, guint8 item_id2, guint8 item_id3, guint8 item_id4, guint16 item_length){ + + if (item_id1==0x00 && item_id2==0x0b && item_id3==0x01 && item_id4==0x02){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Dispatch call to", 1); offset+=item_length; + + } else if (item_id1==0x02 && item_id2==0x03 && item_id3==0x02 && item_id4==0x01){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Parameter Name", 1); offset+=item_length; + + } else if (item_id1==0x02 && item_id2==0x05 && item_id3==0x02 && item_id4==0x05){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Parameter Name", 1); offset+=item_length; + + } else if (item_id1==0x02 && item_id2==0x05 && item_id3==0x02 && item_id4==0x01){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Parameter Name", 1); offset+=item_length; + + } else if (item_id1==0x02 && item_id2==0x03 && item_id3==0x03 && item_id4==0x01){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Tables Name", 1); offset+=item_length; + + } else if (item_id1==0x02 && item_id2==0x13 && item_id3==0x03 && item_id4==0x01){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Tables Name", 1); offset+=item_length; + + } else if (item_id1==0x03 && item_id2==0x01 && item_id3==0x03 && item_id4==0x02){ + check_length(pinfo, item_value_tree, 8, item_length, "Table length"); + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Fill Length"); offset+=4; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "Width Length"); offset+=4; + + } else if (item_id1==0x03 && item_id2==0x02 && item_id3==0x03 && item_id4==0x05){ + offset += 4; /* Skip the first 4 bytes */ + proto_tree_add_item(item_value_tree, hf_saprfc_table_length, tvb, offset, 4, FALSE); offset += 4; + proto_tree_add_none_format(item_value_tree, hf_saprfc_item_value, tvb, offset, item_length, "Table Content (first)"); + proto_item_append_text(item, ", Table Content (first)"); offset+=item_length; + + } else if (item_id1==0x03 && item_id2==0x05 && item_id3==0x03 && item_id4==0x05){ + proto_tree_add_none_format(item_value_tree, hf_saprfc_item_value, tvb, offset, item_length, "Table Content"); + proto_item_append_text(item, ", Table Content"); offset+=item_length; + + } else if (item_id1==0x03 && item_id2==0x05 && item_id3==0x03 && item_id4==0x06){ + proto_tree_add_none_format(item_value_tree, hf_saprfc_item_value, tvb, offset, item_length, "Table Content (last)"); + proto_item_append_text(item, ", Table Content (last)"); offset+=item_length; + + } else if (item_id1==0x03 && item_id2==0x06 && item_id3==0x03 && item_id4==0x01){ + add_item_value_string(tvb, item, item_value_tree, offset, item_length, "Tables Name", 1); offset+=item_length; + + } else if (item_id1==0x05 && item_id2==0x01 && item_id3==0x01 && item_id4==0x36){ + add_item_value_uint8(tvb, item, item_value_tree, offset, 1, "#"); offset+=1; + add_item_value_hexstring(tvb, item, item_value_tree, offset, 16, "Root-id"); offset+=16; + add_item_value_hexstring(tvb, item, item_value_tree, offset, 16, "Conn-id"); offset+=16; + add_item_value_uint32(tvb, item, item_value_tree, offset, 4, "#"); offset+=4; + + } else { + /* If the preference is set, report the item as unknown in the expert info */ + if (global_saprfc_highlight_items){ + expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "The RFC item has a unknown type that is not dissected (%d %d %d %d)", item_id1, item_id2, item_id3, item_id4); + } + } +} + +static void +dissect_saprfc_payload(tvbuff_t *tvb, packet_info *info, proto_tree *tree, proto_tree *parent_tree, guint32 offset){ + + guint8 item_id1, item_id2, item_id3, item_id4; + guint16 item_length, item_value_length; + + proto_item *item = NULL, *item_value = NULL; + proto_tree *item_tree = NULL, *item_value_tree = NULL; + + while (tvb_offset_exists(tvb, offset)){ + item_id1 = item_id2 = item_id3 = item_id4 = 0; + item_length = item_value_length = 0; + + /* Add the item subtree. We start with a item's length of 1, as we don't have yet the real size of the item */ + item = proto_tree_add_item(tree, hf_saprfc_item, tvb, offset, 1, FALSE); + item_tree = proto_item_add_subtree(item, ett_saprfc); + + /* Get the first identifier */ + item_id1 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(item_tree, hf_saprfc_item_id1, tvb, offset, 1, FALSE); offset+=1; item_length+=1; + proto_item_append_text(item, ": (0x%.2x)", item_id1); + + /* Check if it's an End of message */ + if (item_id1==0x0c){ + item_value_length = 0; + + /* Otherwise follow dissection */ + } else { + + item_id2 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(item_tree, hf_saprfc_item_id2, tvb, offset, 1, FALSE); offset+=1; item_length+=1; + proto_item_append_text(item, ", (0x%.2x)", item_id2); + + if ((item_id1!=0xff) && (item_id2!=0xff)) { + + item_id3 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(item_tree, hf_saprfc_item_id3, tvb, offset, 1, FALSE); offset+=1; item_length+=1; + proto_item_append_text(item, ", (0x%.2x)", item_id3); + + item_id4 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(item_tree, hf_saprfc_item_id4, tvb, offset, 1, FALSE); offset+=1; item_length+=1; + proto_item_append_text(item, ", (0x%.2x)", item_id4); + + item_value_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(item_tree, hf_saprfc_item_length, tvb, offset, 2, FALSE); offset+=2; item_length+=2; + proto_item_append_text(item, ", Length=%d", item_value_length); + } + } + + /* Now we have the real length of the item, set the proper size */ + item_length += item_value_length; + proto_item_set_len(item, item_length); + + /* If the item has content dissect it */ + if (item_value_length>0){ + item_value = proto_tree_add_item(item_tree, hf_saprfc_item_value, tvb, offset, item_value_length, FALSE); + item_value_tree = proto_item_add_subtree(item_value, ett_saprfc); + dissect_saprfc_item(tvb, info, item, item_value_tree, offset, item_id1, item_id2, item_id3, item_id4, item_value_length); + } + + /* Also send the tables items for reassembling */ + if (global_saprfc_table_reassembly && item_id1==0x03 && item_id2==0x02 && item_id3==0x03 && item_id4==0x05){ + dissect_saprfc_tables(tvb, info, parent_tree, offset, item_value_length); + } + + offset+= item_value_length; + } + +} + + +static void +dissect_saprfc_rfcheader(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset){ + proto_item *header = NULL, *header_unicode = NULL, *payload = NULL; + proto_tree *header_tree = NULL, *header_unicode_tree = NULL, *payload_tree = NULL; + + if (tree){ + + /* Add the RFC header subtree */ + header = proto_tree_add_item(tree, hf_saprfc_rfcheader, tvb, offset, 28, FALSE); + header_tree = proto_item_add_subtree(header, ett_saprfc); + offset += 28; + + /* Add the unicode header subtree */ + header_unicode = proto_tree_add_item(tree, hf_saprfc_ucheader, tvb, offset, 11, FALSE); + header_unicode_tree = proto_item_add_subtree(header_unicode, ett_saprfc); + + proto_tree_add_none_format(header_unicode_tree, hf_saprfc_ucheader_codepage, tvb, offset, 4, "Code Page: %s", tvb_bytes_to_str(tvb, offset, 4)); offset+=4; + proto_tree_add_item(header_unicode_tree, hf_saprfc_ucheader_ce, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_unicode_tree, hf_saprfc_ucheader_et, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_unicode_tree, hf_saprfc_ucheader_cs, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_unicode_tree, hf_saprfc_ucheader_returncode, tvb, offset, 4, FALSE); offset+=4; + + /* Check the payload length */ + if (tvb_length_remaining(tvb, offset) > 0){ + /* Add the payload subtree */ + payload = proto_tree_add_item(tree, hf_saprfc_payload, tvb, offset, -1, FALSE); + payload_tree = proto_item_add_subtree(payload, ett_saprfc); + + /* Dissect the payload */ + dissect_saprfc_payload(tvb, pinfo, payload_tree, tree, offset); + } + + } +} + + +static void +dissect_saprfc_monitor_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 version, guint32 offset){ + // TODO: Warning unused version parameter + guint8 opcode; + + opcode = tvb_get_guint8(tvb, offset); + col_append_fstr(pinfo->cinfo, COL_INFO, ", Command=%s", val_to_str(opcode, hf_saprfc_monitor_cmd_values, "Unknown")); + + if (tree){ + proto_tree_add_item(tree, hf_saprfc_monitor_cmd, tvb, offset, 1, FALSE); offset+=1; + proto_item_append_text(tree, ", Command=%s", val_to_str(opcode, hf_saprfc_monitor_cmd_values, "Unknown")); + } + + switch (opcode){ + + }; + +} + + +static void +dissect_saprfc_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset){ + guint8 version = 0, reqtype = 0; + proto_item *header = NULL, *info = NULL, *info2 = NULL, *info3 = NULL, *info4 = NULL, *reqtype2 = NULL, *params = NULL; + proto_tree *header_tree = NULL, *info_tree = NULL, *info2_tree = NULL, *info3_tree = NULL, *info4_tree = NULL, *reqtype2_tree = NULL, *params_tree; + + version = tvb_get_guint8(tvb, offset); + reqtype = tvb_get_guint8(tvb, offset + 1); + + col_append_fstr(pinfo->cinfo, COL_INFO, "APPC Version=%d, Request Type=%s", version, val_to_str(reqtype, hf_saprfc_header_reqtype_values, "Unknown")); + + if (tree){ + /* Add the APPC header subtree */ + header = proto_tree_add_item(tree, hf_saprfc_header, tvb, offset, 28, FALSE); + header_tree = proto_item_add_subtree(header, ett_saprfc); + + proto_item_append_text(header, ", Version=%d, Request Type=%s", version, val_to_str(reqtype, hf_saprfc_header_reqtype_values, "Unknown")); + + proto_tree_add_item(header_tree, hf_saprfc_header_version, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_tree, hf_saprfc_header_reqtype, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_tree, hf_saprfc_header_protocol, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_tree, hf_saprfc_header_mode, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_tree, hf_saprfc_header_uid, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(header_tree, hf_saprfc_header_gw_id, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(header_tree, hf_saprfc_header_err_len, tvb, offset, 2, FALSE); offset+=2; + + info2 = proto_tree_add_item(header_tree, hf_saprfc_header_info2, tvb, offset, 1, FALSE); + info2_tree = proto_item_add_subtree(info2, ett_saprfc); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_WITH_LONG_LU_NAME, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_WITH_LONG_HOSTADDR, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_GW_IMMEDIATE, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_GW_SNC_ACTIVE, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_GW_WAIT_LOOK_UP, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_SNC_INIT_PHASE, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_GW_STATELESS, tvb, offset, 1, FALSE); + proto_tree_add_item(info2_tree, hf_saprfc_header_info2_GW_NO_STATE_CHECK, tvb, offset, 1, FALSE); + offset+=1; + + proto_tree_add_item(header_tree, hf_saprfc_header_trace_level, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(header_tree, hf_saprfc_header_time, tvb, offset, 4, FALSE); offset+=4; + + info3 = proto_tree_add_item(header_tree, hf_saprfc_header_info3, tvb, offset, 1, FALSE); + info3_tree = proto_item_add_subtree(info3, ett_saprfc); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_WITH_CODE_PAGE, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_ASYNC_RFC, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_CANCEL_HARD, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_CANCEL_SOFT, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_WITH_GUI_TIMEOUT, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_TERMIO_ERROR, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_EXTENDED_INIT_OPTIONS, tvb, offset, 1, FALSE); + proto_tree_add_item(info3_tree, hf_saprfc_header_info3_GW_DIST_TRACE, tvb, offset, 1, FALSE); + offset+=1; + + proto_tree_add_item(header_tree, hf_saprfc_header_timeout, tvb, offset, 4, FALSE); offset+=4; + + info4 = proto_tree_add_item(header_tree, hf_saprfc_header_info4, tvb, offset, 1, FALSE); + info4_tree = proto_item_add_subtree(info4, ett_saprfc); + proto_tree_add_item(info4_tree, hf_saprfc_header_info4_GW_WITH_DBG_CTL, tvb, offset, 1, FALSE); + offset+=1; + + proto_tree_add_item(header_tree, hf_saprfc_header_sequence_no, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(header_tree, hf_saprfc_header_sap_params_len, tvb, offset, 2, FALSE); offset+=2; + offset+=2; /* Skip 2 bytes here */ + + info = proto_tree_add_item(header_tree, hf_saprfc_header_info, tvb, offset, 1, FALSE); + info_tree = proto_item_add_subtree(info, ett_saprfc); + proto_tree_add_item(info_tree, hf_saprfc_header_info_SYNC_CPIC_FUNCTION, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_WITH_HOSTADDR, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_WITH_GW_SAP_PARAMS_HDR, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_CPIC_SYNC_REQ, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_WITH_ERR_INFO, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_DATA_WITH_TERM_OUTPUT, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_DATA_WITH_TERM_INPUT, tvb, offset, 1, FALSE); + proto_tree_add_item(info_tree, hf_saprfc_header_info_R3_CPIC_LOGIN_WITH_TERM, tvb, offset, 1, FALSE); + offset+=1; + + reqtype2 = proto_tree_add_item(header_tree, hf_saprfc_header_reqtype2, tvb, offset, 1, FALSE); + reqtype2_tree = proto_item_add_subtree(reqtype2, ett_saprfc); + proto_tree_add_item(reqtype2_tree, hf_saprfc_header_reqtype2_F_V_INITIALIZE_CONVERSATION, tvb, offset, 1, FALSE); + proto_tree_add_item(reqtype2_tree, hf_saprfc_header_reqtype2_F_V_ALLOCATE, tvb, offset, 1, FALSE); + proto_tree_add_item(reqtype2_tree, hf_saprfc_header_reqtype2_F_V_SEND_DATA, tvb, offset, 1, FALSE); + proto_tree_add_item(reqtype2_tree, hf_saprfc_header_reqtype2_F_V_RECEIVE, tvb, offset, 1, FALSE); + proto_tree_add_item(reqtype2_tree, hf_saprfc_header_reqtype2_F_V_FLUSH, tvb, offset, 1, FALSE); + offset+=1; + + proto_tree_add_item(header_tree, hf_saprfc_header_appc_rc, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(header_tree, hf_saprfc_header_sap_rc, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(header_tree, hf_saprfc_header_conversation_id, tvb, offset, 8, FALSE); offset+=8; + + /* Dissect the NCPIC Parameters according to the request type */ + params = proto_tree_add_item(header_tree, hf_saprfc_header_ncpic_parameters, tvb, offset, 28, FALSE); + params_tree = proto_item_add_subtree(params, ett_saprfc); + switch (reqtype){ + case 0x01:{ /* F_INITIALIZE_CONVERSATION */ + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_sdest, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_lu, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_tp, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_ctype, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_client_info, tvb, offset, 1, FALSE); offset+=1; + offset += 2; // Sum remaining bytes + break; + } + case 0x0f:{ /* F_SET_PARTNER_LU_NAME */ + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_lu_name, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_lu_name_length, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_host_address, tvb, offset, 16, FALSE); offset+=16; + break; + } + case 0x17:{ /* F_SET_SECURITY_TYPE */ + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_security_password, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(params_tree, hf_saprfc_header_ncpic_parameters_security_password_length, tvb, offset, 4, FALSE); offset+=4; + offset += 16; // Sum remaining bytes + break; + } + default:{ + offset+=28; + } + }; + + proto_tree_add_item(header_tree, hf_saprfc_header_comm_idx, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(header_tree, hf_saprfc_header_conn_idx, tvb, offset, 2, FALSE); offset+=2; + } +} + +static void +dissect_saprfc_internal(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint32 offset = 0; + proto_item *saprfc = NULL; + proto_tree *saprfc_tree = NULL; + + if (tree) { /* we are being asked for details */ + + /* Add the main saprfc subtree */ + saprfc = proto_tree_add_item(tree, proto_saprfc, tvb, 0, -1, FALSE); + saprfc_tree = proto_item_add_subtree(saprfc, ett_saprfc); + + } + + dissect_saprfc_rfcheader(tvb, pinfo, saprfc_tree, offset); + +} + +static void +dissect_saprfc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint32 offset = 0; + guint8 version = 0, req_type = 0; + proto_item *saprfc = NULL, *accept_info = NULL; + proto_tree *saprfc_tree = NULL, *accept_info_tree = NULL; + + /* Add the protocol to the column */ + col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPRFC"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + + /* Get version and request type values */ + version = tvb_get_guint8(tvb, offset); + req_type = tvb_get_guint8(tvb, offset + 1); + + /* Check if the message is valid or it is an APPC header */ + // TODO: We need to find a way of performing this check, as wireshark is + // stateless seems to be difficult to keep track of the requests/responses. + if (version > 0x03){ + if (tree){ + /* Add the main saprfc subtree */ + saprfc = proto_tree_add_item(tree, proto_saprfc, tvb, 0, -1, FALSE); + saprfc_tree = proto_item_add_subtree(saprfc, ett_saprfc); + } + dissect_saprfc_header(tvb, pinfo, saprfc_tree, offset); + return; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, "Version=%d, Request Type=%s", version, val_to_str(req_type, hf_saprfc_reqtype_values, "Unknown")); + + if (tree) { /* we are being asked for details */ + + /* Add the main saprfc subtree */ + saprfc = proto_tree_add_item(tree, proto_saprfc, tvb, 0, -1, FALSE); + saprfc_tree = proto_item_add_subtree(saprfc, ett_saprfc); + + /* Dissect common fields */ + proto_tree_add_item(saprfc_tree, hf_saprfc_version, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(saprfc_tree, hf_saprfc_reqtype, tvb, offset, 1, FALSE); offset+=1; + proto_item_append_text(saprfc_tree, ", Version=%d, Request Type=%s", version, val_to_str(req_type, hf_saprfc_reqtype_values, "Unknown")); + + } + + /* Dissect the remaining based on the version and request type */ + switch (req_type){ + + case 0x03: /* GW_NORMAL_CLIENT */ + case 0x0b:{ /* GW_REGISTER_TP */ + proto_tree_add_item(saprfc_tree, hf_saprfc_address, tvb, offset, 4, FALSE); offset+=4; + offset+=4; // Skip 4 bytes here + proto_tree_add_item(saprfc_tree, hf_saprfc_service, tvb, offset, 10, FALSE); offset+=10; + proto_tree_add_item(saprfc_tree, hf_saprfc_codepage, tvb, offset, 4, FALSE); offset+=4; + offset+=6; // Skip 6 bytes here + proto_tree_add_item(saprfc_tree, hf_saprfc_lu, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(saprfc_tree, hf_saprfc_tp, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(saprfc_tree, hf_saprfc_conversation_id, tvb, offset, 8, FALSE); offset+=8; + proto_tree_add_item(saprfc_tree, hf_saprfc_appc_header_version, tvb, offset, 1, FALSE); offset+=1; + + accept_info = proto_tree_add_item(saprfc_tree, hf_saprfc_accept_info, tvb, offset, 1, FALSE); + accept_info_tree = proto_item_add_subtree(accept_info, ett_saprfc); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_EINFO, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_PING, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_SNC, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_CONN_EINFO, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_CODE_PAGE, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_NIPING, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_EXTINITOPT, tvb, offset, 1, FALSE); + proto_tree_add_item(accept_info_tree, hf_saprfc_accept_info_GW_ACCEPT_DIST_TRACE, tvb, offset, 1, FALSE); + offset+=1; + + proto_tree_add_item(saprfc_tree, hf_saprfc_idx, tvb, offset, 2, FALSE); offset+=2; + + if (version == 0x03){ + proto_tree_add_item(saprfc_tree, hf_saprfc_address6, tvb, offset, 16, FALSE); offset+=16; + } + + proto_tree_add_item(saprfc_tree, hf_saprfc_rc, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(saprfc_tree, hf_saprfc_echo_data, tvb, offset, 1, FALSE); offset+=1; + proto_tree_add_item(saprfc_tree, hf_saprfc_filler, tvb, offset, 1, FALSE); offset+=1; + break; + } + case 0x09:{ /* GW_SEND_CMD */ + dissect_saprfc_monitor_cmd(tvb, pinfo, saprfc_tree, version, 2); + break; + } + }; + +} + +void +proto_register_saprfc(void) +{ + static hf_register_info hf[] = { + { &hf_saprfc_version, + { "Version", "saprfc.version", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC Version", HFILL }}, + { &hf_saprfc_reqtype, + { "Request Type", "saprfc.reqtype", FT_UINT8, BASE_HEX, hf_saprfc_reqtype_values, 0x0, "SAP RFC Request Type", HFILL }}, + { &hf_saprfc_address, + { "IPv4 Address", "saprfc.addres", FT_IPv4, BASE_NONE, NULL, 0x0, "SAP RFC IPv4 Address", HFILL }}, + { &hf_saprfc_service, + { "Service", "saprfc.service", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC Service", HFILL }}, + { &hf_saprfc_codepage, + { "Codepage", "saprfc.codepage", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC Codepage", HFILL }}, + { &hf_saprfc_lu, + { "LU", "saprfc.lu", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC LU", HFILL }}, + { &hf_saprfc_tp, + { "TP", "saprfc.tp", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC TP", HFILL }}, + { &hf_saprfc_conversation_id, + { "Conversation ID", "saprfc.conversation_id", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC Conversation ID", HFILL }}, + { &hf_saprfc_appc_header_version, + { "APPC Header Version", "saprfc.appc_hd_version", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Version", HFILL }}, + { &hf_saprfc_accept_info, + { "Accept Info Flags", "saprfc.accept_info", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Accept Info Flags", HFILL }}, + { &hf_saprfc_accept_info_EINFO, + { "Accept Info Flag EINFO", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_EINFO, "SAP RFC Accept Info Flag EINFO", HFILL }}, + { &hf_saprfc_accept_info_PING, + { "Accept Info Flag PING", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_PING, "SAP RFC Accept Info Flag PING", HFILL }}, + { &hf_saprfc_accept_info_SNC, + { "Accept Info Flag SNC", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_SNC, "SAP RFC Accept Info Flag SNC", HFILL }}, + { &hf_saprfc_accept_info_CONN_EINFO, + { "Accept Info Flag CONN_EINFO", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_CONN_EINFO, "SAP RFC Accept Info Flag CONN_EINFO", HFILL }}, + { &hf_saprfc_accept_info_CODE_PAGE, + { "Accept Info Flag CODE_PAGE", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_CODE_PAGE, "SAP RFC Accept Info Flag CODE_PAGE", HFILL }}, + { &hf_saprfc_accept_info_NIPING, + { "Accept Info Flag NIPING", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_NIPING, "SAP RFC Accept Info Flag NIPING", HFILL }}, + { &hf_saprfc_accept_info_EXTINITOPT, + { "Accept Info Flag EXTINITOPT", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_EXTINITOPT, "SAP RFC Accept Info Flag EXTINITOPT", HFILL }}, + { &hf_saprfc_accept_info_GW_ACCEPT_DIST_TRACE, + { "Accept Info Flag GW_ACCEPT_DIST_TRACE", "saprfc.accept_info.EINFO", FT_BOOLEAN, 8, NULL, SAPRFC_ACCEPT_INFO_GW_ACCEPT_DIST_TRACE, "SAP RFC Accept Info Flag GW_ACCEPT_DIST_TRACE", HFILL }}, + { &hf_saprfc_idx, + { "Index", "saprfc.index", FT_INT16, BASE_DEC, NULL, 0x0, "SAP RFC Index", HFILL }}, + { &hf_saprfc_address6, + { "IPv6 Address", "saprfc.addres6", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP RFC IPv6 Address", HFILL }}, + { &hf_saprfc_rc, + { "Return Code", "saprfc.rc", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC Return Code", HFILL }}, + { &hf_saprfc_echo_data, + { "Echo Data", "saprfc.echo_data", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC Echo Data", HFILL }}, + { &hf_saprfc_filler, + { "Filler", "saprfc.filler", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC Echo Data", HFILL }}, + + /* Monitor Commands*/ + { &hf_saprfc_monitor_cmd, + { "Command", "saprfc.monitor_cmd", FT_UINT8, BASE_DEC, hf_saprfc_monitor_cmd_values, 0x0, "SAP RFC Monitor Command", HFILL }}, + + /* APPC Header */ + { &hf_saprfc_header, + { "APPC Header", "saprfc.appcheader", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header", HFILL }}, + { &hf_saprfc_header_version, + { "Version", "saprfc.appcheader.version", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Version", HFILL }}, + { &hf_saprfc_header_reqtype, + { "Request Type", "saprfc.appcheader.reqtype", FT_UINT8, BASE_HEX, hf_saprfc_header_reqtype_values, 0x0, "SAP RFC APPC Header Request Type", HFILL }}, + { &hf_saprfc_header_protocol, + { "Protocol", "saprfc.appcheader.protocol", FT_UINT8, BASE_HEX, hf_saprfc_header_protocol_values, 0x0, "SAP RFC APPC Header Protocol", HFILL }}, + { &hf_saprfc_header_mode, + { "Mode", "saprfc.appcheader.mode", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Mode", HFILL }}, + { &hf_saprfc_header_uid, + { "UID", "saprfc.appcheader.uid", FT_INT16, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header UID", HFILL }}, + { &hf_saprfc_header_gw_id, + { "Gateway ID", "saprfc.appcheader.gw_id", FT_UINT16, BASE_HEX, NULL, 0x0, "SAP RFC APPC Header Gateway ID", HFILL }}, + { &hf_saprfc_header_err_len, + { "Error Length", "saprfc.appcheader.err_len", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Error Length", HFILL }}, + { &hf_saprfc_header_info2, + { "Info 2", "saprfc.appcheader.info2", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC APPC Header Info 2", HFILL }}, + { &hf_saprfc_header_info2_WITH_LONG_LU_NAME, + { "Info 2 Flag WITH_LONG_LU_NAME", "saprfc.info2.WITH_LONG_LU_NAME", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_WITH_LONG_LU_NAME, "SAP RFC Info 2 Flag WITH_LONG_LU_NAME", HFILL }}, + { &hf_saprfc_header_info2_WITH_LONG_HOSTADDR, + { "Info 2 Flag WITH_LONG_HOSTADDR", "saprfc.info2.WITH_LONG_HOSTADDR", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_WITH_LONG_HOSTADDR, "SAP RFC Info 2 Flag WITH_LONG_HOSTADDR", HFILL }}, + { &hf_saprfc_header_info2_GW_IMMEDIATE, + { "Info 2 Flag GW_IMMEDIATE", "saprfc.info2.GW_IMMEDIATE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_GW_IMMEDIATE, "SAP RFC Info 2 Flag GW_IMMEDIATE", HFILL }}, + { &hf_saprfc_header_info2_GW_SNC_ACTIVE, + { "Info 2 Flag GW_SNC_ACTIVE", "saprfc.info2.GW_SNC_ACTIVE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_GW_SNC_ACTIVE, "SAP RFC Info 2 Flag GW_SNC_ACTIVE", HFILL }}, + { &hf_saprfc_header_info2_GW_WAIT_LOOK_UP, + { "Info 2 Flag GW_WAIT_LOOK_UP", "saprfc.info2.GW_WAIT_LOOK_UP", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_GW_WAIT_LOOK_UP, "SAP RFC Info 2 Flag GW_WAIT_LOOK_UP", HFILL }}, + { &hf_saprfc_header_info2_SNC_INIT_PHASE, + { "Info 2 Flag SNC_INIT_PHASE", "saprfc.info2.SNC_INIT_PHASE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_SNC_INIT_PHASE, "SAP RFC Info 2 Flag SNC_INIT_PHASE", HFILL }}, + { &hf_saprfc_header_info2_GW_STATELESS, + { "Info 2 Flag GW_STATELESS", "saprfc.info2.GW_STATELESS", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_GW_STATELESS, "SAP RFC Info 2 Flag GW_STATELESS", HFILL }}, + { &hf_saprfc_header_info2_GW_NO_STATE_CHECK, + { "Info 2 Flag GW_NO_STATE_CHECK", "saprfc.info2.GW_NO_STATE_CHECK", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO2_GW_NO_STATE_CHECK, "SAP RFC Info 2 Flag GW_NO_STATE_CHECK", HFILL }}, + { &hf_saprfc_header_trace_level, + { "Trace Level", "saprfc.appcheader.trace_level", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Trace Level", HFILL }}, + { &hf_saprfc_header_time, + { "Time", "saprfc.appcheader.time", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Time", HFILL }}, + { &hf_saprfc_header_info3, + { "Info 3", "saprfc.appcheader.info3", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC APPC Header Info 3", HFILL }}, + { &hf_saprfc_header_info3_GW_WITH_CODE_PAGE, + { "Info 3 Flag GW_WITH_CODE_PAGE", "saprfc.appcheader.info3.GW_WITH_CODE_PAGE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_WITH_CODE_PAGE, "SAP RFC APPC Header Info 3 Flag GW_WITH_CODE_PAGE", HFILL }}, + { &hf_saprfc_header_info3_GW_ASYNC_RFC, + { "Info 3 Flag GW_ASYNC_RFC", "saprfc.appcheader.info3.GW_ASYNC_RFC", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_ASYNC_RFC, "SAP RFC APPC Header Info 3 Flag GW_ASYNC_RFC", HFILL }}, + { &hf_saprfc_header_info3_GW_CANCEL_HARD, + { "Info 3 Flag GW_CANCEL_HARD", "saprfc.appcheader.info3.GW_CANCEL_HARD", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_CANCEL_HARD, "SAP RFC APPC Header Info 3 Flag GW_CANCEL_HARD", HFILL }}, + { &hf_saprfc_header_info3_GW_CANCEL_SOFT, + { "Info 3 Flag GW_CANCEL_SOFT", "saprfc.appcheader.info3.GW_CANCEL_SOFT", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_CANCEL_SOFT, "SAP RFC APPC Header Info 3 Flag GW_CANCEL_SOFT", HFILL }}, + { &hf_saprfc_header_info3_GW_WITH_GUI_TIMEOUT, + { "Info 3 Flag GW_WITH_GUI_TIMEOUT", "saprfc.appcheader.info3.GW_WITH_GUI_TIMEOUT", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_WITH_GUI_TIMEOUT, "SAP RFC APPC Header Info 3 Flag GW_WITH_GUI_TIMEOUT", HFILL }}, + { &hf_saprfc_header_info3_GW_TERMIO_ERROR, + { "Info 3 Flag GW_TERMIO_ERROR", "saprfc.appcheader.info3.GW_TERMIO_ERROR", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_TERMIO_ERROR, "SAP RFC APPC Header Info 3 Flag GW_TERMIO_ERROR", HFILL }}, + { &hf_saprfc_header_info3_GW_EXTENDED_INIT_OPTIONS, + { "Info 3 Flag GW_EXTENDED_INIT_OPTIONS", "saprfc.appcheader.info3.GW_EXTENDED_INIT_OPTIONS", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_EXTENDED_INIT_OPTIONS, "SAP RFC APPC Header Info 3 Flag GW_EXTENDED_INIT_OPTIONS", HFILL }}, + { &hf_saprfc_header_info3_GW_DIST_TRACE, + { "Info 3 Flag GW_DIST_TRACE", "saprfc.appcheader.info3.GW_DIST_TRACE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO3_GW_DIST_TRACE, "SAP RFC APPC Header Info 3 Flag GW_DIST_TRACE", HFILL }}, + { &hf_saprfc_header_timeout, + { "Timeout", "saprfc.appcheader.timeout", FT_INT32, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Timeout", HFILL }}, + { &hf_saprfc_header_info4, + { "Info 4", "saprfc.appcheader.info4", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC APPC Header Info 4", HFILL }}, + { &hf_saprfc_header_info4_GW_WITH_DBG_CTL, + { "Info 4 Flag GW_WITH_DBG_CTL", "saprfc.appcheader.info4.GW_WITH_DBG_CTL", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO4_GW_WITH_DBG_CTL, "SAP RFC APPC Header Info 4 Flag GW_WITH_DBG_CTL", HFILL }}, + { &hf_saprfc_header_sequence_no, + { "Sequence No", "saprfc.appcheader.sequence_no", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Sequence No", HFILL }}, + { &hf_saprfc_header_sap_params_len, + { "SAP Parameters Length", "saprfc.appcheader.sap_params_len", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header SAP Parameters Length", HFILL }}, + { &hf_saprfc_header_info, + { "Info Flags", "saprfc.appcheader.info", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC APPC Header Info Flags", HFILL }}, + { &hf_saprfc_header_info_SYNC_CPIC_FUNCTION, + { "Info Flag SYNC_CPIC_FUNCTION", "saprfc.appcheader.info.SYNC_CPIC_FUNCTION", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_SYNC_CPIC_FUNCTION, "SAP RFC APPC Header Info Flag SYNC_CPIC_FUNCTION", HFILL }}, + { &hf_saprfc_header_info_WITH_HOSTADDR, + { "Info Flag WITH_HOSTADDR", "saprfc.appcheader.info.WITH_HOSTADDR", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_WITH_HOSTADDR, "SAP RFC APPC Header Info Flag WITH_HOSTADDR", HFILL }}, + { &hf_saprfc_header_info_WITH_GW_SAP_PARAMS_HDR, + { "Info Flag WITH_GW_SAP_PARAMS_HDR", "saprfc.appcheader.info.WITH_GW_SAP_PARAMS_HDR", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_WITH_GW_SAP_PARAMS_HDR, "SAP RFC APPC Header Info Flag WITH_GW_SAP_PARAMS_HDR", HFILL }}, + { &hf_saprfc_header_info_CPIC_SYNC_REQ, + { "Info Flag CPIC_SYNC_REQ", "saprfc.appcheader.info.CPIC_SYNC_REQ", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_CPIC_SYNC_REQ, "SAP RFC APPC Header Info Flag CPIC_SYNC_REQ", HFILL }}, + { &hf_saprfc_header_info_WITH_ERR_INFO, + { "Info Flag WITH_ERR_INFO", "saprfc.appcheader.info.WITH_ERR_INFO", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_WITH_ERR_INFO, "SAP RFC APPC Header Info Flag WITH_ERR_INFO", HFILL }}, + { &hf_saprfc_header_info_DATA_WITH_TERM_OUTPUT, + { "Info Flag DATA_WITH_TERM_OUTPUT", "saprfc.appcheader.info.DATA_WITH_TERM_OUTPUT", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_DATA_WITH_TERM_OUTPUT, "SAP RFC APPC Header Info Flag DATA_WITH_TERM_OUTPUT", HFILL }}, + { &hf_saprfc_header_info_DATA_WITH_TERM_INPUT, + { "Info Flag DATA_WITH_TERM_INPUT", "saprfc.appcheader.info.DATA_WITH_TERM_INPUT", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_DATA_WITH_TERM_INPUT, "SAP RFC APPC Header Info Flag DATA_WITH_TERM_INPUT", HFILL }}, + { &hf_saprfc_header_info_R3_CPIC_LOGIN_WITH_TERM, + { "Info Flag R3_CPIC_LOGIN_WITH_TERM", "saprfc.appcheader.info.R3_CPIC_LOGIN_WITH_TERM", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_INFO1_R3_CPIC_LOGIN_WITH_TERM, "SAP RFC APPC Header Info Flag R3_CPIC_LOGIN_WITH_TERM", HFILL }}, + { &hf_saprfc_header_reqtype2, + { "Request Type 2 Flags", "saprfc.appcheader.reqtype2", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC APPC Header Request Type 2", HFILL }}, + { &hf_saprfc_header_reqtype2_F_V_INITIALIZE_CONVERSATION, + { "Request Type 2 Flag F_V_INITIALIZE_CONVERSATION", "saprfc.appcheader.reqtype2.F_V_INITIALIZE_CONVERSATION", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_REQTYPE2_F_V_INITIALIZE_CONVERSATION, "SAP RFC Request Type 2 Flag F_V_INITIALIZE_CONVERSATION", HFILL }}, + { &hf_saprfc_header_reqtype2_F_V_ALLOCATE, + { "Request Type 2 Flag F_V_ALLOCATE", "saprfc.appcheader.reqtype2.F_V_ALLOCATE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_REQTYPE2_F_V_ALLOCATE, "SAP RFC Request Type 2 Flag F_V_ALLOCATE", HFILL }}, + { &hf_saprfc_header_reqtype2_F_V_SEND_DATA, + { "Request Type 2 Flag F_V_SEND_DATA", "saprfc.appcheader.reqtype2.F_V_SEND_DATA", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_REQTYPE2_F_V_SEND_DATA, "SAP RFC Request Type 2 Flag F_V_SEND_DATA", HFILL }}, + { &hf_saprfc_header_reqtype2_F_V_RECEIVE, + { "Request Type 2 Flag F_V_RECEIVE", "saprfc.appcheader.reqtype2.F_V_RECEIVE", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_REQTYPE2_F_V_RECEIVE, "SAP RFC Request Type 2 Flag F_V_RECEIVE", HFILL }}, + { &hf_saprfc_header_reqtype2_F_V_FLUSH, + { "Request Type 2 Flag F_V_FLUSH", "saprfc.appcheader.reqtype2.F_V_FLUSH", FT_BOOLEAN, 8, NULL, SAPRFC_APPCHDR_REQTYPE2_F_V_FLUSH, "SAP RFC Request Type 2 Flag F_V_FLUSH", HFILL }}, + { &hf_saprfc_header_appc_rc, + { "APPC Return Code", "saprfc.appcheader.appc_rc", FT_INT32, BASE_DEC, hf_saprfc_header_appc_rc_values, 0x0, "SAP RFC APPC Header APPC Return Code", HFILL }}, + { &hf_saprfc_header_sap_rc, + { "SAP Return Code", "saprfc.appcheader.sap_rc", FT_INT32, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header SAP Return Code", HFILL }}, + { &hf_saprfc_header_conversation_id, + { "Conversation ID", "saprfc.appcheader.conversation_id", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header Conversation ID", HFILL }}, + { &hf_saprfc_header_ncpic_parameters, + { "NCPIC Parameters", "saprfc.appcheader.ncpic_parameters", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_sdest, + { "SDest", "saprfc.appcheader.ncpic_parameters.sdest", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters SDest", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_lu, + { "LU", "saprfc.appcheader.ncpic_parameters.lu", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters LU", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_tp, + { "TP", "saprfc.appcheader.ncpic_parameters.tp", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters TP", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_ctype, + { "CType", "saprfc.appcheader.ncpic_parameters.ctype", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters CType", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_client_info, + { "Client Info", "saprfc.appcheader.ncpic_parameters.client_info", FT_UINT8, BASE_HEX, hf_saprfc_header_ncpic_parameters_client_info_values, 0x0, "SAP RFC APPC Header NCPIC Parameters Client Info", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_lu_name, + { "LU Name", "saprfc.appcheader.ncpic_parameters.lu_name", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters LU Name", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_lu_name_length, + { "LU Name Length", "saprfc.appcheader.ncpic_parameters.lu_name_length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters LU Name Length", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_host_address, + { "Host Address", "saprfc.appcheader.ncpic_parameters.host_address", FT_IPv6, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters Host Address", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_security_password, + { "Security Password", "saprfc.appcheader.ncpic_parameters.security_password", FT_STRING, BASE_NONE, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters Security Password", HFILL }}, + { &hf_saprfc_header_ncpic_parameters_security_password_length, + { "Security Password Length", "saprfc.appcheader.ncpic_parameters.security_password_length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header NCPIC Parameters Security Password Length", HFILL }}, + + { &hf_saprfc_header_comm_idx, + { "Comm Index", "saprfc.appcheader.comm_idx", FT_INT16, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Comm Index", HFILL }}, + { &hf_saprfc_header_conn_idx, + { "Conn Index", "saprfc.appcheader.conn_idx", FT_INT16, BASE_DEC, NULL, 0x0, "SAP RFC APPC Header Conn Index", HFILL }}, + + /* RFC Header */ + { &hf_saprfc_rfcheader, + { "RFC Header", "saprfc.rfcheader", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Header", HFILL }}, + + /* RFC Unicode Header */ + { &hf_saprfc_ucheader, + { "Unicode Header", "saprfc.ucheader", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Unicode Header", HFILL }}, + { &hf_saprfc_ucheader_codepage, + { "Code Page", "saprfc.ucheader.codepage", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Unicode Header Code Page", HFILL }}, + { &hf_saprfc_ucheader_ce, + { "CE", "saprfc.ucheader.ce", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC Unicode Header CE", HFILL }}, + { &hf_saprfc_ucheader_et, + { "ET", "saprfc.ucheader.et", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC Unicode Header ET", HFILL }}, + { &hf_saprfc_ucheader_cs, + { "CS", "saprfc.ucheader.cs", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP RFC Unicode Header CS", HFILL }}, + { &hf_saprfc_ucheader_returncode, + { "Return Code", "saprfc.ucheader.returncode", FT_UINT32, BASE_HEX, NULL, 0x0, "SAP RFC Unicode Header Return Code", HFILL }}, + + /* Payload */ + { &hf_saprfc_payload, + { "Message", "saprfc.message", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Message", HFILL }}, + + /* Item fields */ + { &hf_saprfc_item, + { "Item", "saprfc.item", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Item", HFILL }}, + { &hf_saprfc_item_id1, + { "ID1", "saprfc.item.id1", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Item ID 1", HFILL }}, + { &hf_saprfc_item_id2, + { "ID2", "saprfc.item.id2", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Item ID 2", HFILL }}, + { &hf_saprfc_item_id3, + { "ID3", "saprfc.item.id3", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Item ID 3", HFILL }}, + { &hf_saprfc_item_id4, + { "ID4", "saprfc.item.id4", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Item ID 4", HFILL }}, + { &hf_saprfc_item_length, + { "Length", "saprfc.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP RFC Item Length", HFILL }}, + { &hf_saprfc_item_value, + { "Value", "saprfc.item.value", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Item Value", HFILL }}, + + /* Table content */ + { &hf_saprfc_table, + { "Table", "saprfc.table", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Table", HFILL }}, + { &hf_saprfc_table_length, + { "Table Content Length", "saprfc.table.length", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC Table Content Length", HFILL }}, + { &hf_saprfc_table_compress_header, + { "Compression Header", "saprfc.table.compression", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Table Compression Header", HFILL }}, + { &hf_saprfc_table_uncomplength, + { "Uncompressed Length", "saprfc.table.compression.uncomplength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP RFC Table Uncompressed Length", HFILL }}, + { &hf_saprfc_table_algorithm, + { "Compression Algorith", "saprfc.table.compression.algorithm", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Table Compression Algorithm", HFILL }}, + { &hf_saprfc_table_magic, + { "Magic Bytes", "saprfc.table.compression.magic", FT_UINT16, BASE_HEX, NULL, 0x0, "SAP RFC Table Compression Magic Bytes", HFILL }}, + { &hf_saprfc_table_special, + { "Special", "saprfc.table.compression.special", FT_UINT8, BASE_HEX, NULL, 0x0, "SAP RFC Table Special", HFILL }}, + { &hf_saprfc_table_return_code, + { "Decompress Return Code", "saprfc.table.compression.returncode", FT_UINT8, BASE_DEC, hf_decompress_return_code_vals, 0x0, "SAP RFC Decompression routine return code", HFILL }}, + { &hf_saprfc_table_content, + { "Content", "saprfc.table.content", FT_NONE, BASE_NONE, NULL, 0x0, "SAP RFC Table Content", HFILL }}, + + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_saprfc + }; + + module_t *saprfc_module; + + /* Register the protocol */ + proto_saprfc = proto_register_protocol ( + "SAP RFC Protocol", /* name */ + "SAPRFC", /* short name */ + "saprfc" /* abbrev */ + ); + + proto_register_field_array(proto_saprfc, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("saprfc", dissect_saprfc, proto_saprfc); + register_dissector("saprfcinternal", dissect_saprfc_internal, proto_saprfc); + + /* Register the preferences */ + saprfc_module = prefs_register_protocol(proto_saprfc, proto_reg_handoff_saprfc); + + range_convert_str(&global_saprfc_port_range, SAPRFC_PORT_RANGE, MAX_TCP_PORT); + prefs_register_range_preference(saprfc_module, "tcp_ports", "SAP RFC Protocol TCP port numbers", "Port numbers used for SAP RFC Protocol (default " SAPRFC_PORT_RANGE ")", &global_saprfc_port_range, MAX_TCP_PORT); + + prefs_register_bool_preference(saprfc_module, "decompress", "Decompress SAP RFC Protocol message payloads", "Whether the SAP RFC Protocol dissector should decompress message's payloads.", &global_saprfc_decompress); + + prefs_register_bool_preference(saprfc_module, "table_reassembly", "Reassemble SAP RFC table content", "Whether the SAP RFC Protocol dissector should reassemble table content included in payloads.", &global_saprfc_table_reassembly); + + prefs_register_bool_preference(saprfc_module, "highlight_unknown_items", "Highlight unknown SAP RFC Items", "Whether the SAP RFC Protocol dissector should highlight unknown RFC items (migth be noise and generate a lot of expert warnings)", &global_saprfc_highlight_items); +} + +/** + * Helpers for dealing with the port range + */ +static void range_delete_callback (guint32 port) +{ + dissector_delete_uint("sapni.port", port, saprfc_handle); +} + +static void range_add_callback (guint32 port) +{ + dissector_add_uint("sapni.port", port, saprfc_handle); +} + +/** + * Register Hand off for the SAP RFC Protocol + */ +void +proto_reg_handoff_saprfc(void) +{ + static range_t *saprfc_port_range; + static gboolean initialized = FALSE; + + if (!initialized) { + saprfc_handle = create_dissector_handle(dissect_saprfc, proto_saprfc); + saprfcinternal_handle = create_dissector_handle(dissect_saprfc_internal, proto_saprfc); + initialized = TRUE; + } else { + range_foreach(saprfc_port_range, range_delete_callback); + g_free(saprfc_port_range); + } + + saprfc_port_range = range_copy(global_saprfc_port_range); + range_foreach(saprfc_port_range, range_add_callback); +} + diff --git a/packet-saprouter.c b/packet-saprouter.c new file mode 100644 index 0000000..0b3921a --- /dev/null +++ b/packet-saprouter.c @@ -0,0 +1,640 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "packet-sapprotocol.h" + + +/* Define default ports */ +#define SAPROUTER_PORT_RANGE "3298-3299" + +/* + * Length of the frame header + */ +#define SAPROUTER_HEADER_LEN 8 + +/* + * Offsets of header fields + */ +#define SAPROUTER_ROUTE_LENGTH_OFFSET 16 +#define SAPROUTER_ROUTE_OFFSET_OFFSET 20 + +/* SAP Router Eye Catcher strings */ +#define SAPROUTER_TYPE_ROUTE_STRING "NI_ROUTE" +#define SAPROUTER_TYPE_ERR_STRING "NI_RTERR" +#define SAPROUTER_TYPE_ADMIN_STRING "ROUTER_ADM" + +/* SAP Router Talk Modes */ +static const value_string hf_saprouter_talk_mode_vals[] = { + { 0, "NI_MSG_IO" }, + { 1, "NI_RAW_IO" }, + { 2, "NI_ROUT_IO" } +}; + +/* SAP Router Operation values */ +static const value_string hf_saprouter_opcode_vals[] = { + { 0, "Error information" }, + { 1, "Version Request" }, + { 2, "Version Response" }, + { 5, "Send Handle (5)" }, // TODO: Check this opcodes + { 6, "Send Handle (6)" }, // TODO: Check this opcodes + { 8, "Send Handle (8)" }, // TODO: Check this opcodes + { 70, "SNC request" }, // TODO: Check this opcodes NiSncOpcode: NISNC_REQ + { 71, "SNC handshake complete" }, // TODO: Check this opcodes NiSncOpcode: NISNC_ACK +}; + +/* SAP Router Return Code values (as per SAP Note 63342 http://service.sap.com/sap/support/notes/63342) */ +static const value_string hf_saprouter_return_code_vals[] = { + { -1, "NI-internal error (NIEINTERN)" }, + { -2, "Host name unknown (NIEHOST_UNKNOWN)" }, + { -3, "Service unknown (NIESERV_UNKNOWN)" }, + { -4, "Service already used (NIESERV_USED)" }, + { -5, "Time limit reached (NIETIMEOUT)" }, + { -6, "Connection to partner broken (NIECONN_BROKEN)" }, + { -7, "Data range too small (NIETOO_SMALL)" }, + { -8, "Invalid parameters (NIEINVAL)" }, + { -9, "Wake-Up (without data) (NIEWAKEUP)" }, + {-10, "Connection setup failed (NIECONN_REFUSED)" }, + {-11, "PING/PONG signal received (NIEPING)" }, + {-12, "Connection to partner via NiRouter not yet set up (NIECONN_PENDING)" }, + {-13, "Invalid version (NIEVERSION)" }, + {-14, "Local hostname cannot be found (NIEMYHOSTNAME)" }, + {-15, "No free port in range (NIENOFREEPORT)" }, + {-16, "Local hostname invalid (NIEMYHOST_VERIFY)" }, + {-17, "Error in the SNC shift in the saprouter ==> (NIESNC_FAILURE)" }, + {-18, "Opcode received (NIEOPCODE)" }, + {-19, "queue limit reached, next package not accepted (NIEQUE_FULL)" }, + {-20, "Requested package too large (NIETOO_BIG)" }, + {-90, "Host name unknown (NIEROUT_HOST_UNKNOWN)" }, + {-91, "Service unknown (NIEROUT_SERV_UNKNOWN)" }, + {-92, "Connection setup failed (NIEROUT_CONN_REFUSED)" }, + {-93, "NI-internal errors (NIEROUT_INTERN)" }, + {-94, "Connect from source to destination not allowed (NIEROUT_PERM_DENIED)" }, + {-95, "Connection terminated (NIEROUT_CONN_BROKEN)" }, + {-96, "Invalid client version (NIEROUT_VERSION)" }, + {-97, "Connection cancelled by administrator (NIEROUT_CANCELED)" }, + {-98, "saprouter shutdown (NIEROUT_SHUTDOWN)" }, + {-99, "Information request refused (NIEROUT_INFO_DENIED)" }, + {-100, "Max. number of clients reached (NIEROUT_OVERFLOW)" }, + {-101, "Talkmode not allowed (NIEROUT_MODE_DENIED)" }, + {-102, "Client not available (NIEROUT_NOCLIENT)" }, + {-103, "Error in external library (NIEROUT_EXTERN)" }, + {-104, "Error in the SNC shift (NIEROUT_SNC_FAILURE)" }, +}; + + +/* SAP Router Admin Command values */ +static const value_string hf_saprouter_admin_command_vals[] = { + { 2, "Information Request" }, + { 3, "New Route Table Request" }, + { 4, "Toggle Trace Request" }, + { 5, "Stop Request" }, + { 6, "Cancel Route Request" }, + { 7, "Dump Buffers Request" }, + { 8, "Flush Buffers Request" }, + { 9, "Soft Shutdown Request" }, + { 10, "Set Trace Peer" }, + { 11, "Clear Trace Peer" }, + { 12, "Trace Connection" }, + { 13, "Trace Connection" }, + { 14, "Hide Error Information Request" }, +}; + + +static int proto_saprouter = -1; + +/* General fields */ +static int hf_saprouter_type = -1; +static int hf_saprouter_ni_version = -1; + +/* Route information */ +static int hf_saprouter_route_version = -1; +static int hf_saprouter_entries = -1; +static int hf_saprouter_talk_mode = -1; +static int hf_saprouter_rest_nodes = -1; +static int hf_saprouter_route_length = -1; +static int hf_saprouter_route_offset = -1; +static int hf_saprouter_route = -1; +static int hf_saprouter_route_string = -1; + +/* Error Information/Control Messages */ +static int hf_saprouter_opcode = -1; +static int hf_saprouter_return_code = -1; + +/* Error Information Messages */ +static int hf_saprouter_error_length = -1; +static int hf_saprouter_error_string = -1; + +/* Control Messages */ +static int hf_saprouter_control_length = -1; +static int hf_saprouter_control_string = -1; + +/* Admin Messages */ +static int hf_saprouter_admin_command = -1; +static int hf_saprouter_admin_password = -1; +static int hf_saprouter_admin_client_count_short = -1; +static int hf_saprouter_admin_client_count_int = -1; +static int hf_saprouter_admin_client_ids = -1; +static int hf_saprouter_admin_client_id = -1; +static int hf_saprouter_admin_address_mask = -1; + +static gint ett_saprouter = -1; + +/* Global port preference */ +static range_t *global_saprouter_port_range; + + +/* Global SNC dissection preference */ +static gboolean global_saprouter_snc_dissection = TRUE; + +/* Protocol handle */ +static dissector_handle_t saprouter_handle; + +/* Session state information being tracked in a SAP Router conversation */ +typedef struct saprouter_session_state { + gboolean route_information; + gboolean route_accepted; + guchar *src_hostname; /* Source hostname (first entry in the route string) */ + guint32 src_port; /* Source port number */ + guchar *src_password; /* Source password XXX: Check if possible */ + guchar *dest_hostname; /* Destination hostname (last entry in the route string) */ + guint32 dest_port; /* Destination port number */ + guchar *dest_password; /* Destination password */ +} saprouter_session_state; + +/* + * + */ +void proto_reg_handoff_saprouter(void); + +static guint32 +dissect_serviceport(guchar *port){ + guint32 portnumber = 0; + + if (g_ascii_isdigit(port[0])){ + portnumber = strtol(port, NULL, 10); + } else if ( (strlen(port)>5) && g_str_has_prefix(port, "sapdp") ){ + portnumber = 3200 + strtol(port+5, NULL, 10); + } else if ( (strlen(port)>5) && g_str_has_prefix(port, "sapgw") ){ + portnumber = 3300 + strtol(port+5, NULL, 10); + } else if ( (strlen(port)>5) && g_str_has_prefix(port, "sapms") ){ + portnumber = 3600 + strtol(port+5, NULL, 10); + } + return (portnumber); +} + +static void +dissect_routestring(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset, saprouter_session_state *session_state){ + int hop = 1; + guint32 len, route_offset, int_port = 0; + guchar *hostname = NULL, *port = NULL, *password = NULL; + proto_item *route_item = NULL; + + while (tvb_offset_exists(tvb, offset)){ + route_offset = offset; hostname = port = password = NULL; + /* Dissect the hostname string */ + len = tvb_strsize(tvb, offset); + hostname = tvb_get_string(tvb, offset, len - 1); offset+=len; + /* Dissect the port string */ + len = tvb_strsize(tvb, offset); + port = tvb_get_string(tvb, offset, len - 1); offset+=len; + /* Dissect the password string */ + len = tvb_strsize(tvb, offset); + password = tvb_get_string(tvb, offset, len - 1); offset+=len; + + /* Get the service port in numeric format */ + int_port = dissect_serviceport(port); + + /* Add the route string to the tree */ + if (tree){ + route_item = proto_tree_add_text(tree, tvb, route_offset, offset - route_offset, "Route Hop %d: Hostname=%s Service=%s Port=%d", hop, hostname, port, int_port); + /* If a password was found, add a expert warning in the security category */ + if (strlen(password)>0){ + proto_item_append_text(route_item, " Password=%s", password); + expert_add_info_format(pinfo, route_item, PI_SECURITY, PI_WARN, "Route password"); + } + } + + /* Add the first hostname/port as source in the conversation state*/ + if ((hop==1) && session_state){ + session_state->src_hostname = hostname; + session_state->src_port = int_port; + session_state->src_password = password; + } + hop++; + } + + /* Add the last hostname/port as destination */ + if ((hop!=1) && session_state){ + session_state->dest_hostname = hostname; + session_state->dest_port = int_port; + session_state->dest_password = password; + } + /* Save the status of the conversation state */ + if (session_state){ + session_state->route_information = TRUE; + session_state->route_accepted = FALSE; + } +} + +static void +dissect_errorstring(tvbuff_t *tvb, proto_tree *tree, guint32 offset) +{ + guint32 len; + while (tvb_offset_exists(tvb, offset)){ + len = tvb_strsize(tvb, offset); + if (len>1){ + proto_tree_add_text(tree, tvb, offset, len, "%s", tvb_get_string(tvb, offset, len - 1)); + } + offset += len; + } +} + + +static void +dissect_saprouter_snc_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset){ + + tvbuff_t *next_tvb = NULL; + dissector_handle_t snc_handle; + + /* Call the SNC dissector */ + if (global_saprouter_snc_dissection == TRUE){ + snc_handle = find_dissector("sapsnc"); + if (snc_handle){ + /* Set the column to not writable so the SNC dissector doesn't override the Diag info */ + col_set_writable(pinfo->cinfo, FALSE); + /* Create a new tvb buffer and call the dissector */ + next_tvb = tvb_new_subset(tvb, offset, -1, -1); + call_dissector(snc_handle, next_tvb, pinfo, tree); + } else { + expert_add_info_format(pinfo, tree, PI_UNDECODED, PI_WARN, "SAP SNC dissector not found !"); + } + } + +} + + +static void +dissect_saprouter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint8 opcode = 0; + guint16 client_count = 0, client_count_actual = 0; + guint32 offset = 0, eyecatcher_length = 0, route_length = 0, route_offset = 0, text_length = 0; + conversation_t *conversation = NULL; + saprouter_session_state *session_state = NULL; + proto_item *ti = NULL, *ri = NULL, *ei = NULL, *ci = NULL, *admin_password = NULL; + proto_tree *saprouter_tree = NULL, *route_tree = NULL, *text_tree = NULL, *clients_tree = NULL; + + /* Search for a conversation */ + conversation = find_or_create_conversation(pinfo); + session_state = (saprouter_session_state *)conversation_get_proto_data(conversation, proto_saprouter); + if (!session_state){ + session_state = (saprouter_session_state *)wmem_alloc(wmem_file_scope(), sizeof(saprouter_session_state)); + if (session_state){ + session_state->route_information = FALSE; + session_state->route_accepted = FALSE; + session_state->src_hostname = NULL; session_state->src_port = 0; session_state->src_password = NULL; + session_state->dest_hostname = NULL; session_state->dest_port = 0; session_state->dest_password = NULL; + conversation_add_proto_data(conversation, proto_saprouter, session_state); + } else{ + expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_ERROR, "Error allocating buffer for tracking Router session"); + } + } + + /* Add the protocol to the column */ + col_add_str(pinfo->cinfo, COL_PROTOCOL, "SAPROUTER"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + /* Add the main SAP Router subtree */ + if (tree) { + ti = proto_tree_add_item(tree, proto_saprouter, tvb, offset, -1, FALSE); + saprouter_tree = proto_item_add_subtree(ti, ett_saprouter); + } + + /* Get the 'eye catcher' length */ + eyecatcher_length = tvb_strsize(tvb, offset); + + /* Admin Message Type */ + if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ADMIN_STRING, eyecatcher_length) == 0){ + col_set_str(pinfo->cinfo, COL_INFO, "Admin Message"); + + proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, offset, eyecatcher_length, FALSE); offset += eyecatcher_length; + proto_item_append_text(ti, ", Admin Message"); + + proto_tree_add_item(saprouter_tree, hf_saprouter_ni_version, tvb, offset, 1, FALSE); offset++; + + opcode = tvb_get_guint8(tvb, offset); + proto_tree_add_item(saprouter_tree, hf_saprouter_admin_command, tvb, offset, 1, FALSE); offset++; + + switch (opcode){ + case 2:{ /* Info request */ + offset+=2; /* Skip 2 bytes */ + /* Check if a password was supplied */ + if (tvb_offset_exists(tvb, offset) && (tvb_strsize(tvb, offset) > 0)){ + admin_password = proto_tree_add_item(saprouter_tree, hf_saprouter_admin_password, tvb, offset, tvb_strsize(tvb, offset), FALSE); + expert_add_info_format(pinfo, admin_password, PI_SECURITY, PI_WARN, "Info request password"); + } + break; + } + case 10: /* Set Peer Trace */ + case 11:{ /* Clear Peer Trace */ + proto_tree_add_item(saprouter_tree, hf_saprouter_admin_address_mask, tvb, offset, 32, FALSE); offset+=32; + break; + } + case 6: /* Cancel Route request */ + case 12: /* Trace Connection */ + case 13: /* Trace Connection */ + { + /* Retrieve the client count first */ + if (opcode == 6){ + offset+=2; /* Skip 2 bytes for Cancel Route request*/ + client_count = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(saprouter_tree, hf_saprouter_admin_client_count_short, tvb, offset, 2, FALSE); offset+=2; + } else { + client_count = tvb_get_ntohl(tvb, offset); + proto_tree_add_item(saprouter_tree, hf_saprouter_admin_client_count_int, tvb, offset, 4, FALSE); offset+=4; + } + + /* Parse the list of client IDs */ + ci = proto_tree_add_item(saprouter_tree, hf_saprouter_admin_client_ids, tvb, offset, 4*client_count, FALSE); + clients_tree = proto_item_add_subtree(ci, ett_saprouter); + while (tvb_offset_exists(tvb, offset) && tvb_length_remaining(tvb, offset)>=4){ + proto_tree_add_item(clients_tree, hf_saprouter_admin_client_id, tvb, offset, 4, FALSE); offset+=4; + client_count_actual+=1; + } + + /* Check if the actual count of IDs differes from the reported number */ + if ((client_count_actual != client_count) || tvb_length_remaining(tvb, offset)>0){ + expert_add_info_format(pinfo, clients_tree, PI_MALFORMED, PI_WARN, "Client IDs list is malformed"); + } + + break; + } + default: { + offset+=2; /* Skip 2 bytes */ + break; + } + } + + /* Route Message Type */ + } else if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ROUTE_STRING, eyecatcher_length) == 0){ + col_set_str(pinfo->cinfo, COL_INFO, "Route Message"); + + /* Get the route length/offset */ + route_length = tvb_get_ntohl(tvb, offset + SAPROUTER_ROUTE_LENGTH_OFFSET); + route_offset = offset + SAPROUTER_ROUTE_OFFSET_OFFSET + 4; + + if (tree){ + proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, 0, eyecatcher_length, FALSE); offset += eyecatcher_length; + proto_item_append_text(ti, ", Route Message"); + /* Add the fields */ + proto_tree_add_item(saprouter_tree, hf_saprouter_route_version, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(saprouter_tree, hf_saprouter_ni_version, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(saprouter_tree, hf_saprouter_entries, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(saprouter_tree, hf_saprouter_talk_mode, tvb, offset, 1, FALSE); offset+=3; /* There're two unused bytes there */ + proto_tree_add_item(saprouter_tree, hf_saprouter_rest_nodes, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(saprouter_tree, hf_saprouter_route_length, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(saprouter_tree, hf_saprouter_route_offset, tvb, offset, 4, FALSE); offset+=4; + /* Add the route tree */ + if ((guint32)tvb_length_remaining(tvb, offset) != route_length){ + expert_add_info_format(pinfo, saprouter_tree, PI_MALFORMED, PI_WARN, "The route length is invalid (remaining=%d, route_length=%d)", tvb_length_remaining(tvb, offset), route_length); + route_length = (guint32)tvb_length_remaining(tvb, offset); + } + ri = proto_tree_add_item(saprouter_tree, hf_saprouter_route, tvb, offset, route_length, FALSE); + route_tree = proto_item_add_subtree(ri, ett_saprouter); + } + + /* Dissect the route string */ + dissect_routestring(tvb, pinfo, route_tree, route_offset, session_state); + + /* Add the route to the colinfo*/ + if (session_state && session_state->src_hostname){ + col_append_fstr(pinfo->cinfo, COL_INFO, ", Source: Hostname=%s Service Port=%d", session_state->src_hostname, session_state->src_port); + if (strlen(session_state->src_password)>0) + col_append_fstr(pinfo->cinfo, COL_INFO, " Password=%s", session_state->src_password); + } + if (session_state && session_state->dest_hostname){ + col_append_fstr(pinfo->cinfo, COL_INFO, ", Destination: Hostname=%s Service Port=%d", session_state->dest_hostname, session_state->dest_port); + if (strlen(session_state->dest_password)>0) + col_append_fstr(pinfo->cinfo, COL_INFO, " Password=%s", session_state->dest_password); + } + + /* Error Information/Control Message Type */ + } else if (tvb_strneql(tvb, offset, SAPROUTER_TYPE_ERR_STRING, eyecatcher_length) == 0){ + opcode = tvb_get_guint8(tvb, offset + 10); + col_set_str(pinfo->cinfo, COL_INFO, (opcode==0)? "Error Information" : "Control Message"); + + if (tree){ + proto_item_append_text(ti, (opcode==0)? ", Error Information" : ", Control Message"); + /* Add the fields */ + proto_tree_add_item(saprouter_tree, hf_saprouter_type, tvb, offset, eyecatcher_length, FALSE); offset += eyecatcher_length; + proto_tree_add_item(saprouter_tree, hf_saprouter_ni_version, tvb, offset, 1, FALSE); offset++; + proto_tree_add_item(saprouter_tree, hf_saprouter_opcode, tvb, offset, 1, FALSE); offset+=2; /* There's a unused byte there */ + proto_tree_add_item(saprouter_tree, hf_saprouter_return_code, tvb, offset, 4, FALSE); offset+=4; + + text_length = tvb_get_ntohl(tvb, offset); + /* Error Information Message */ + if (opcode == 0){ + proto_tree_add_item(saprouter_tree, hf_saprouter_error_length, tvb, offset, 4, FALSE); offset+=4; + if ((text_length > 0) && tvb_offset_exists(tvb, offset+text_length)){ + /* Add the error string tree */ + ei = proto_tree_add_item(saprouter_tree, hf_saprouter_error_string, tvb, offset, text_length, FALSE); + text_tree = proto_item_add_subtree(ei, ett_saprouter); + dissect_errorstring(tvb, text_tree, offset); + } + + /* Control Message */ + } else { + proto_tree_add_item(saprouter_tree, hf_saprouter_control_length, tvb, offset, 4, FALSE); offset+=4; + if ((text_length >0) && tvb_offset_exists(tvb, offset+text_length)){ + /* Add the control string tree */ + proto_tree_add_item(saprouter_tree, hf_saprouter_control_string, tvb, offset, text_length, FALSE); offset+=text_length; + } + + /* Dissect the SNC Frame for SNC opcodes */ + if (opcode == 70 || opcode == 71){ + dissect_saprouter_snc_frame(tvb, pinfo, tree, offset); + } + + } + + } + + /* Uknown Message Type */ + } else { + /* Route information available */ + if (session_state && session_state->route_information){ + /* TODO: Use the route_accepted boolean to track if a route request + * was accepted prior to consider route traffic. The NI Protocol + * dissector should pass NI_PONG packets to the Router dissector. + */ + + /* TODO: Add a link to the packet were the route was requested + * (like TCP reassembled packets). + */ + col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown message or message routed from %s:%d to %s:%d ", session_state->src_hostname, session_state->src_port, session_state->dest_hostname, session_state->dest_port); + if (tree){ + proto_item_append_text(ti, ", Unknown message or message routed from %s:%d to %s:%d ", session_state->src_hostname, session_state->src_port, session_state->dest_hostname, session_state->dest_port); + } + + /* Call the dissector in the NI protocol subdissectors table + * according to the route destination source/port numbers. */ + dissect_sap_protocol_payload(tvb, offset, pinfo, tree, + session_state->src_port, session_state->dest_port); + + /* No route information available */ + } else { + col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown message or message routed to unknown destination"); + if (tree){ + proto_item_append_text(ti, ", Unknown message or message routed to unknown destination"); + } + } + } +} + +void +proto_register_saprouter(void) +{ + static hf_register_info hf[] = { + { &hf_saprouter_type, + { "Type", "saprouter.type", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Router Type", HFILL }}, + /* NI Route messages */ + { &hf_saprouter_route_version, + { "Route version", "saprouter.version", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Router Version", HFILL }}, + { &hf_saprouter_ni_version, + { "NI version", "saprouter.niversion", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Router NI Version", HFILL }}, + { &hf_saprouter_entries, + { "Entries", "saprouter.entries", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Router Total number of entries", HFILL }}, + { &hf_saprouter_talk_mode, + { "Talk Mode", "saprouter.talkmode", FT_UINT8, BASE_DEC, hf_saprouter_talk_mode_vals, 0x0, "SAP Router Talk Mode", HFILL }}, + { &hf_saprouter_rest_nodes, + { "Remaining Hops", "saprouter.restnodes", FT_UINT8, BASE_DEC, NULL, 0x0, "SAP Router Remaining Hops", HFILL }}, + { &hf_saprouter_route_length, + { "Route String Length", "saprouter.routelength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Router Route String Length", HFILL }}, + { &hf_saprouter_route_offset, + { "Route String Offset", "saprouter.routeoffset", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Router Route String Offset", HFILL }}, + { &hf_saprouter_route, + { "Route String", "saprouter.routestring", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Router Route", HFILL }}, + { &hf_saprouter_route_string, + { "Route String", "saprouter.routestring", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Router Route String", HFILL }}, + /* NI error information / Control messages */ + { &hf_saprouter_opcode, + { "Operation Code", "saprouter.opcode", FT_UINT8, BASE_DEC, hf_saprouter_opcode_vals, 0x0, "SAP Router Operation Code", HFILL }}, + { &hf_saprouter_return_code, + { "Return Code", "saprouter.returncode", FT_INT32, BASE_DEC, hf_saprouter_return_code_vals, 0x0, "SAP Router Return Code", HFILL }}, + /* NI Error Information messages */ + { &hf_saprouter_error_length, + { "Error Information Text Length", "saprouter.errorlength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Router Error Information Text length", HFILL }}, + { &hf_saprouter_error_string, + { "Error Information Text", "saprouter.errortext", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Router Error Information Text", HFILL }}, + /* Control messages */ + { &hf_saprouter_control_length, + { "Control Text Length", "saprouter.controllength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Router Control Text length", HFILL }}, + { &hf_saprouter_control_string, + { "Control Text", "saprouter.controltext", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Router Control Text", HFILL }}, + /* Router Admin messages */ + { &hf_saprouter_admin_command, + { "Admin Command", "saprouter.command", FT_UINT8, BASE_DEC, hf_saprouter_admin_command_vals, 0x0, "SAP Router Admin Command", HFILL }}, + { &hf_saprouter_admin_password, + { "Admin Command Info Password", "saprouter.password", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Router Admin Info Password", HFILL }}, + { &hf_saprouter_admin_client_count_short, + { "Admin Command Client Count", "saprouter.client_count", FT_UINT16, BASE_DEC, NULL, 0x0, "SAP Router Admin Client Count", HFILL }}, + { &hf_saprouter_admin_client_count_int, + { "Admin Command Client Count", "saprouter.client_count", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Router Admin Client Count", HFILL }}, + { &hf_saprouter_admin_client_ids, + { "Admin Command Client IDs", "saprouter.client_ids", FT_NONE, BASE_NONE, NULL, 0x0, "SAP Router Admin Client IDs", HFILL }}, + { &hf_saprouter_admin_client_id, + { "Admin Command Client ID", "saprouter.client_id", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP Router Admin Client ID", HFILL }}, + { &hf_saprouter_admin_address_mask, + { "Admin Command Address Mask", "saprouter.address_mask", FT_STRING, BASE_NONE, NULL, 0x0, "SAP Router Admin Address Mask", HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_saprouter + }; + + module_t *saprouter_module; + + /* Register the protocol */ + proto_saprouter = proto_register_protocol ( + "SAP Router Protocol", /* name */ + "SAPROUTER", /* short name */ + "saprouter" /* abbrev */ + ); + + proto_register_field_array(proto_saprouter, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("saprouter", dissect_saprouter, proto_saprouter); + + /* Register the preferences */ + saprouter_module = prefs_register_protocol(proto_saprouter, proto_reg_handoff_saprouter); + + range_convert_str(&global_saprouter_port_range, SAPROUTER_PORT_RANGE, MAX_TCP_PORT); + prefs_register_range_preference(saprouter_module, "tcp_ports", "SAP Router Protocol TCP port numbers", "Port numbers used for SAP Router Protocol (default " SAPROUTER_PORT_RANGE ")", &global_saprouter_port_range, MAX_TCP_PORT); + + prefs_register_bool_preference(saprouter_module, "snc_dissection", "Dissect SAP SNC frames", "Whether the SAP Router Protocol dissector should call the SAP SNC dissector for SNC frames", &global_saprouter_snc_dissection); + +} + + +/** + * Helpers for dealing with the port range + */ +static void range_delete_callback (guint32 port) +{ + dissector_delete_uint("sapni.port", port, saprouter_handle); +} + +static void range_add_callback (guint32 port) +{ + dissector_add_uint("sapni.port", port, saprouter_handle); +} + + +void +proto_reg_handoff_saprouter(void) +{ + static gboolean initialized = FALSE; + static range_t *saprouter_port_range; + + if (!initialized) { + saprouter_handle = create_dissector_handle(dissect_saprouter, proto_saprouter); + initialized = TRUE; + } else { + range_foreach(saprouter_port_range, range_delete_callback); + g_free(saprouter_port_range); + } + + saprouter_port_range = range_copy(global_saprouter_port_range); + range_foreach(saprouter_port_range, range_add_callback); + +} + diff --git a/packet-sapsnc.c b/packet-sapsnc.c new file mode 100644 index 0000000..459f5af --- /dev/null +++ b/packet-sapsnc.c @@ -0,0 +1,139 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include "config.h" + +#include +#include + + +static int proto_sapsnc = -1; + +/* SNC Frame */ +static int hf_sapsnc_frame = -1; +static int hf_sapsnc_eye_catcher = -1; +static int hf_sapsnc_token_length = -1; +static int hf_sapsnc_data_length = -1; +static int hf_sapsnc_flags = -1; +static int hf_sapsnc_extflags = -1; +static int hf_sapsnc_token = -1; +static int hf_sapsnc_data = -1; + +static gint ett_sapsnc = -1; + +/* Protocol handle */ +static dissector_handle_t sapsnc_handle; + +void proto_reg_handoff_sapsnc(void); + + +static void +dissect_sapsnc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint32 offset = 0; + + /* Add the protocol to the column */ + col_add_str(pinfo->cinfo, COL_PROTOCOL, ", SAPSNC"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + if (tree) { /* we are being asked for details */ + + proto_item *sapsnc = NULL, *sapsnc_frame = NULL; + proto_tree *sapsnc_tree = NULL, *sapsnc_frame_tree = NULL; + + /* Add the main SNC subtree */ + sapsnc = proto_tree_add_item(tree, proto_sapsnc, tvb, offset, -1, FALSE); + sapsnc_tree = proto_item_add_subtree(sapsnc, ett_sapsnc); + + /* Add the SNC Frame subtree */ + sapsnc_frame = proto_tree_add_item(sapsnc_tree, hf_sapsnc_frame, tvb, offset, -1, FALSE); + sapsnc_frame_tree = proto_item_add_subtree(sapsnc_frame, ett_sapsnc); + + proto_tree_add_item(sapsnc_frame_tree, hf_sapsnc_eye_catcher, tvb, offset, 8, FALSE); offset+=8; + offset+=4; /* First 4 bytes (Flags ?) */ + proto_tree_add_item(sapsnc_frame_tree, hf_sapsnc_token_length, tvb, offset, 4, FALSE); offset+=4; + proto_tree_add_item(sapsnc_frame_tree, hf_sapsnc_data_length, tvb, offset, 4, FALSE); offset+=4; + offset+=2; /* 2 Bytes */ + proto_tree_add_item(sapsnc_frame_tree, hf_sapsnc_flags, tvb, offset, 2, FALSE); offset+=2; + proto_tree_add_item(sapsnc_frame_tree, hf_sapsnc_extflags, tvb, offset, 4, FALSE); offset+=4; + + } +} + +void +proto_register_sapsnc(void) +{ + static hf_register_info hf[] = { + /* SNC Frame */ + { &hf_sapsnc_frame, + { "SNC Frame", "sapsnc.frame", FT_NONE, BASE_NONE, NULL, 0x0, "SAP SNC Frame", HFILL }}, + { &hf_sapsnc_eye_catcher, + { "SNC Eye Catcher", "sapsnc.eyecatcher", FT_STRING, BASE_NONE, NULL, 0x0, "SAP SNC Eye Catcher", HFILL }}, + { &hf_sapsnc_token_length, + { "SNC Token length", "sapsnc.frame.tokenlength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP SNC Token Length", HFILL }}, + { &hf_sapsnc_data_length, + { "SNC Data length", "sapsnc.frame.datalength", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP SNC Data Length", HFILL }}, + { &hf_sapsnc_flags, + { "SNC Flags", "sapsnc.frame.flags", FT_UINT16, BASE_HEX, NULL, 0x0, "SAP SNC Flags", HFILL }}, + { &hf_sapsnc_extflags, + { "SNC Flags", "sapsnc.frame.extflags", FT_UINT32, BASE_HEX, NULL, 0x0, "SAP SNC Ext Flags", HFILL }}, + { &hf_sapsnc_token, + { "SNC Token", "sapsnc.frame.token", FT_NONE, BASE_NONE, NULL, 0x0, "SAP SNC Token", HFILL }}, + { &hf_sapsnc_data, + { "SNC Data", "sapsnc.frame.data", FT_UINT32, BASE_DEC, NULL, 0x0, "SAP SNC Data", HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_sapsnc + }; + + /* Register the protocol */ + proto_sapsnc = proto_register_protocol ( + "SAP SNC Protocol", /* name */ + "SAPSNC", /* short name */ + "sapsnc" /* abbrev */ + ); + + proto_register_field_array(proto_sapsnc, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("sapsnc", dissect_sapsnc, proto_sapsnc); + +} + + +/** + * Register Hand off for the SAP SNC Protocol + */ +void +proto_reg_handoff_sapsnc(void) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + sapsnc_handle = create_dissector_handle(dissect_sapsnc, proto_sapsnc); + initialized = TRUE; + } + +} + diff --git a/plugin.rc.in b/plugin.rc.in new file mode 100644 index 0000000..5ec37b8 --- /dev/null +++ b/plugin.rc.in @@ -0,0 +1,34 @@ +#include "winver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @RC_MODULE_VERSION@ + PRODUCTVERSION @RC_VERSION@ + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0 +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The Wireshark developer community, http://www.wireshark.org/\0" + VALUE "FileDescription", "@PACKAGE@ dissector\0" + VALUE "FileVersion", "@MODULE_VERSION@\0" + VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0" + VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs , Gilbert Ramirez and others\0" + VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0" + VALUE "ProductName", "Wireshark\0" + VALUE "ProductVersion", "@VERSION@\0" + VALUE "Comments", "Build with @MSVC_VARIANT@\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/sapdecompress.cpp b/sapdecompress.cpp new file mode 100644 index 0000000..6ff9c20 --- /dev/null +++ b/sapdecompress.cpp @@ -0,0 +1,146 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security +## Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#include +#include +#include + +#include "sapdecompress.h" + +#include "hpa101saptype.h" +#include "hpa104CsObject.h" +#include "hpa106cslzc.h" +#include "hpa107cslzh.h" +#include "hpa105CsObjInt.h" + +/* #define DEBUG # Enable this macro if you want some debugging information on the (de)compression functions */ +/* #define DEBUG_TRACE # Enable this macro if you want detailed debugging information (hexdumps) on the (de)compression functions */ + +/* Returns an error strings for compression library return codes */ +const char *error_string(int return_code){ + switch (return_code){ + case CS_IEND_OF_STREAM: return ("end of data (internal)"); + case CS_IEND_OUTBUFFER: return ("end of output buffer"); + case CS_IEND_INBUFFER: return ("end of input buffer"); + case CS_E_OUT_BUFFER_LEN: return ("invalid output length"); + case CS_E_IN_BUFFER_LEN: return ("invalid input length"); + case CS_E_NOSAVINGS: return ("no savings"); + case CS_E_INVALID_SUMLEN: return ("invalid len of stream"); + case CS_E_IN_EQU_OUT: return ("inbuf == outbuf"); + case CS_E_INVALID_ADDR: return ("inbuf == NULL,outbuf == NULL"); + case CS_E_FATAL: return ("internal error !"); + case CS_E_BOTH_ZERO: return ("inlen = outlen = 0"); + case CS_E_UNKNOWN_ALG: return ("unknown algorithm"); + case CS_E_UNKNOWN_TYPE: return ("unknown type"); + /* for decompress */ + case CS_E_FILENOTCOMPRESSED: return ("input not compressed"); + case CS_E_MAXBITS_TOO_BIG: return ("maxbits to large"); + case CS_E_BAD_HUF_TREE: return ("bad hufman tree"); + case CS_E_NO_STACKMEM: return ("no stack memory in decomp"); + case CS_E_INVALIDCODE: return ("invalid code"); + case CS_E_BADLENGTH: return ("bad lengths"); + case CS_E_STACK_OVERFLOW: return ("stack overflow in decomp"); + case CS_E_STACK_UNDERFLOW: return ("stack underflow in decomp"); + /* only Windows */ + case CS_NOT_INITIALIZED: return ("storage not allocated"); + /* non error return codes */ + case CS_END_INBUFFER: return ("end of input buffer"); + case CS_END_OUTBUFFER: return ("end of output buffer"); + case CS_END_OF_STREAM: return ("end of data"); + /* unknown error */ + default: return ("unknown error"); + } +} + +void hexdump(guint8 *address, gint size) +{ + gint i = 0, j = 0, offset = 0; + printf("[%08x] ", offset); + for (; i + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Return code for memory errors */ +#define CS_E_MEMORY_ERROR -99 + +/* SAP Decompression routine return codes */ +static const value_string hf_decompress_return_code_vals[] = { + { 3, "CS_END_INBUFFER (End of input buffer)" }, + { 2, "CS_END_OUTBUFFER (End of output buffer)" }, + { 1, "CS_END_OF_STREAM (End of data)" }, + { 0, "CS_OK" }, + { -1, "CS_IEND_OF_STREAM (End of data (internal) )" }, + { -2, "CS_IEND_OUTBUFFER (End of output buffer)" }, + { -3, "CS_IEND_INBUFFER (End of input buffer)" }, + { -10, "CS_E_OUT_BUFFER_LEN (Invalid output length)" }, + { -11, "CS_E_IN_BUFFER_LEN (Invalid input length)" }, + { -12, "CS_E_NOSAVINGS" }, + { -13, "CS_E_INVALID_SUMLEN (Invalid len of stream)" }, + { -14, "CS_E_IN_EQU_OUT (inbuf == outbuf)" }, + { -15, "CS_E_INVALID_ADDR (inbuf == NULL,outbuf == NULL)" }, + { -19, "CS_E_FATAL (Internal Error !)" }, + { -20, "CS_E_BOTH_ZERO (inlen = outlen = 0)" }, + { -21, "CS_E_UNKNOWN_ALG (unknown algorithm)" }, + { -22, "CS_E_UNKNOWN_TYPE (unknown type)" }, + { -50, "CS_E_FILENOTCOMPRESSED (Input not compressed)" }, + { -51, "CS_E_MAXBITS_TOO_BIG (maxbits to large)" }, + { -52, "CS_E_BAD_HUF_TREE (bad hufman tree)" }, + { -53, "CS_E_NO_STACKMEM (no stack memory in decomp)" }, + { -54, "CS_E_INVALIDCODE (invalid code)" }, + { -55, "CS_E_BADLENGTH (bad lengths)" }, + { -60, "CS_E_STACK_OVERFLOW (stack overflow in decomp)" }, + { -61, "CS_E_STACK_UNDERFLOW (stack underflow in decomp)" }, + {CS_E_MEMORY_ERROR, "CS_E_MEMORY_ERROR (custom error error)" } +}; + +int decompress_packet (const guint8 *in, gint in_length, guint8 *out, guint *out_length); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __PACKET_SAPDECOMPRESS_H__ */ diff --git a/saphelpers.h b/saphelpers.h new file mode 100644 index 0000000..2a4fea4 --- /dev/null +++ b/saphelpers.h @@ -0,0 +1,47 @@ +/* +## =========== +## SAP Dissector Plugin for Wireshark +## +## Copyright (C) 2014 Core Security Technologies +## +## The plugin was designed and developed by Martin Gallo from the Security Consulting Services team of Core Security Technologies. +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +##============== +*/ + +#ifndef __PACKET_SAPHELPERS_H__ +#define __PACKET_SAPHELPERS_H__ + +#include + +gboolean +check_length(packet_info *pinfo, proto_tree *tree, guint32 expected, guint32 real, const char *name_string); + +guint8 +add_item_value_uint8(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text); + +guint16 +add_item_value_uint16(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text); + +guint32 +add_item_value_uint32(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text); + +void +add_item_value_string(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text, int show_in_tree); + +guint32 +add_item_value_stringz(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, const char *text, int show_in_tree); + +void +add_item_value_hexstring(tvbuff_t *tvb, proto_item *item, proto_tree *tree, guint32 offset, guint32 length, const char *text); + +#endif /* __PACKET_SAPHELPERS_H__ */ diff --git a/vpa105CsObjInt.cpp b/vpa105CsObjInt.cpp new file mode 100644 index 0000000..09c551e --- /dev/null +++ b/vpa105CsObjInt.cpp @@ -0,0 +1,339 @@ +/* + + + + ========== licence begin GPL + Copyright (c) 2000-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + + +*/ +// CsObjectInt.cpp: implementation of the CSObjectInt class. +// +////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include "hpa101saptype.h" +// #include "cscompr.h" +#include "hpa106cslzc.h" +#include "hpa107cslzh.h" + +#include "hpa104CsObject.h" +#include "hpa105CsObjInt.h" + + +static SAP_BYTE CsMagicHead[] = { "\037\235" }; /* 1F 9D */ + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +CsObjectInt::CsObjectInt () +{ +} + +CsObjectInt::~CsObjectInt () +{ +} + +int CsObjectInt::CsCompr (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written) +/*--------------------------------------------------------------------*/ +/* Compress a memory segmented */ +/* */ +/* Adaptive Dictionary Compression */ +/* Lempel-Zip */ +/* */ +/* */ +/* Input: */ +/* ----- */ +/* sumlen length of data stream to compress */ +/* inbuf Pointer to input memory */ +/* inlen Length of input memory */ +/* outbuf Pointer to output area */ +/* outlen Length of output area */ +/* option Compress option: */ +/* CS_INIT_COMPRESS initial */ +/* CS_LZC or CS_LZH initial */ +/* initial options have to be or'ed */ +/* CS_NORMAL_COMPRESS */ +/* Output: */ +/* ------ */ +/* bytes_read Bytes read from input buffer */ +/* bytes_compressed Bytes compressed to output buffer */ +/* */ +/* Return Code: */ +/* ----------- */ +/* CS_END_OF_STREAM End of input reached */ +/* CS_END_INBUFFER End of input reached */ +/* CS_END_OUTBUFFER End of output reached */ +/* */ +/* CS_E_IN_BUFFER_LEN Input buffer length to short */ +/* CS_E_OUT_BUFFER_LEN Output Buffer length to short */ +/* CS_E_INVALID_SUMLEN sumlen <= 0 */ +/* CS_E_INVALID_ADDR Invalid addr for input or output buffer*/ +/* CS_E_FATAL internal (should never happen) */ +/* */ +/*--------------------------------------------------------------------*/ +{ + + if (option & CS_INIT_COMPRESS) + { + algorithm = 0; + algorithm = (int) (option & 0xE); + } + + /* Plausibility check for negative input length */ + if (inlen < 0) inlen = 0; + + switch (algorithm) + { + case CS_LZC: + return CsComprLZC (sumlen, inbuf, inlen, outbuf, outlen, + option, bytes_read, bytes_written); + case CS_LZH: + return CsComprLZH (sumlen, inbuf, inlen, outbuf, outlen, + option, bytes_read, bytes_written); + + default: return CS_E_UNKNOWN_ALG; + } +} + + +int CsObjectInt::CsDecompr (SAP_BYTE * inbuf, /* ptr input .......*/ + SAP_INT inlen, /* len of input ....*/ + SAP_BYTE * outbuf, /* ptr output ......*/ + SAP_INT outlen, /* len output ......*/ + SAP_INT option, /* decompr. option */ + SAP_INT * bytes_read, /* bytes read ......*/ + SAP_INT * bytes_decompressed) /* bytes decompr. */ +/*--------------------------------------------------------------------*/ +/* Decompress */ +/* */ +/* Adaptive Dictionary Compression */ +/* Lempel-Zip */ +/* */ +/* Input: */ +/* ----- */ +/* inbuf Pointer to input memory */ +/* inlen Length of input memory */ +/* outbuf Pointer to output area */ +/* outlen Length of output area */ +/* option DeCompress option: */ +/* CS_INIT_DECOMPRESS initial */ +/* CS_NORMAL_COMPRESS */ +/* */ +/* Output: */ +/* ------ */ +/* bytes_read Bytes read from input buffer */ +/* bytes_written Bytes decompressed to output buffer */ +/* */ +/* Return Code: */ +/* ----------- */ +/* CS_END_OF_STREAM End of input stream reached */ +/* CS_END_INBUFFER End of input buffer reached */ +/* CS_END_OUTBUFFER End of output buffer reached */ +/* */ +/* CS_E_OUT_BUFFER_LEN Output buffer length to short */ +/* CS_E_IN_BUFFER_LEN Input buffer length to short */ +/* CS_E_MAXBITS_TOO_BIG No internal memory to decompress */ +/* CS_E_INVALID_LEN inlen < 0 or outlen < CS_BITS */ +/* CS_E_FILENOTCOMPRESSED Input is not compressed */ +/* CS_E_IN_EQU_OUT Same addr for input and output buffer */ +/* CS_E_INVALID_ADDR Invalid addr for input or output buffer*/ +/* CS_E_FATAL Internal (should never happen) */ +/* */ +/*--------------------------------------------------------------------*/ +{ + + if (option & CS_INIT_DECOMPRESS) + { + if (inlen < CS_HEAD_SIZE) return CS_E_IN_BUFFER_LEN; + algorithm = CsGetAlgorithm (inbuf); + } + + switch (algorithm) + { + case CS_ALGORITHM_LZC: + return CsDecomprLZC (inbuf, inlen, outbuf, outlen, + option, bytes_read, bytes_decompressed); + case CS_ALGORITHM_LZH: + return CsDecomprLZH (inbuf, inlen, outbuf, outlen, + option, bytes_read, bytes_decompressed); + + default: return CS_E_UNKNOWN_ALG; + } +} + + +int CsObjectInt::CsGetAlgorithm (SAP_BYTE * data) +/*--------------------------------------------------------------------*/ +/* Get Algorithm number of compressed data */ +/*--------------------------------------------------------------------*/ +{ + return ((int) (data[4] & (unsigned char)0x0F)); +} + + +SAP_INT CsObjectInt::CsGetLen (SAP_BYTE * data) +/*--------------------------------------------------------------------*/ +/* Get the length of the original data stream */ +/* */ +/* Returns CS_E_FILENOT_COMPRESSED if the magic number is */ +/* different from magic header */ +/* else */ +/* Length of org. data stream */ +/*--------------------------------------------------------------------*/ +{ + SAP_INT len; + /* file not compressed !!! .....*/ + if ((CsMagicHead[0] != data[5]) || + (CsMagicHead[1] != data[6])) + { + return ((SAP_INT)CS_E_FILENOTCOMPRESSED); + } + + len = (SAP_INT)data[0] + /* read length from first buf ..*/ + ((SAP_INT)data[1] << 8) + + ((SAP_INT)data[2] << 16) + + ((SAP_INT)data[3] << 24); + + return len; +} + + +int CsObjectInt::CsGetVersion (SAP_BYTE * data) +/*--------------------------------------------------------------------*/ +/* Get version number of compressed data */ +/*--------------------------------------------------------------------*/ +{ + return ((int)data[4] & 0xF0) >> 4; +} + + +int CsObjectInt::CsSetHead (SAP_BYTE * outbuf, + SAP_INT len, + SAP_BYTE veralg, + SAP_BYTE special) +/*--------------------------------------------------------------------*/ +/* Setup length of data stream and header information */ +/*--------------------------------------------------------------------*/ +{ + SAP_UINT l; + + if (len < 0) return CS_E_INVALID_SUMLEN; + + l = (SAP_UINT) len; + + /* set length ......................................................*/ + outbuf[0] = (SAP_BYTE) (l & 0xff); + outbuf[1] = (SAP_BYTE) ((l & 0xff00) >> 8); + outbuf[2] = (SAP_BYTE) ((l & 0xff0000L) >> 16); + outbuf[3] = (SAP_BYTE) ((l & 0xff000000L) >> 24); + + /* setup header - magic number and maxbits .........................*/ + outbuf[4] = veralg; + outbuf[5] = CsMagicHead[0]; + outbuf[6] = CsMagicHead[1]; + outbuf[7] = special; + + return 0; +} + + +int CsObjectInt::CsInitCompr (SAP_BYTE * outbuf, SAP_INT sumlen, SAP_INT option) +/*--------------------------------------------------------------------*/ +/* Only initalize Compression */ +/* outbuf must point to a location which has at least */ +/* CS_HEAD_SIZE bytes left */ +/* */ +/* Input: */ +/* ----- */ +/* outbuf Pointer to output memory */ +/* sumlen length of data stream to compress */ +/* option Compress option CS_LZC, CS_LZH */ +/* */ +/* Return Code: */ +/* ----------- */ +/* 0 OK */ +/* */ +/* CS_E_OUT_BUFFER_LEN Output Buffer length to short */ +/* CS_E_INVALID_SUMLEN sumlen <= 0 */ +/* CS_E_INVALID_ADDR Invalid addr for input or output buffer*/ +/* CS_E_FATAL internal (should never happen) */ +/* */ +/*--------------------------------------------------------------------*/ +{ + SAP_BYTE input_field; + SAP_BYTE *inbuf = &input_field; + SAP_INT bytes_read, bytes_written; + int rc; + + rc = CsCompr (sumlen, inbuf, 0, outbuf, + CS_HEAD_SIZE, option | CS_INIT_COMPRESS, + &bytes_read, &bytes_written); + + if (rc < 0) return rc; + return 0; +} + + +int CsObjectInt::CsInitDecompr (SAP_BYTE * inbuf) +/*--------------------------------------------------------------------*/ +/* Only initalize Decompression */ +/* inbuf must point to a location which has at least */ +/* CS_HEAD_SIZE bytes left */ +/* */ +/* Input: */ +/* ----- */ +/* inbuf Pointer to input memory */ +/* */ +/* Return Code: */ +/* ----------- */ +/* 0 OK */ +/* */ +/* CS_E_IN_BUFFER_LEN Input Buffer length to short */ +/* CS_E_INVALID_ADDR Invalid addr for input */ +/* CS_E_FATAL internal (should never happen) */ +/* */ +/*--------------------------------------------------------------------*/ +{ + SAP_BYTE output_field; + SAP_BYTE * outbuf = &output_field; + SAP_INT bytes_read, bytes_written; + int rc; + + rc = CsDecompr (inbuf, CS_HEAD_SIZE, + outbuf, 0, CS_INIT_DECOMPRESS, + &bytes_read, &bytes_written); + + if (rc < 0) return rc; + return 0; +} diff --git a/vpa106cslzc.cpp b/vpa106cslzc.cpp new file mode 100644 index 0000000..e599813 --- /dev/null +++ b/vpa106cslzc.cpp @@ -0,0 +1,942 @@ +/* static char sccsid[] = "@(#)cslzc 20.10 SAP 97/11/11"; + + + ========== licence begin GPL + Copyright (c) 1992-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + +*/ + +/* + * SAP AG Walldorf + * Systeme, Anwendungen und Produkte in der Datenverarbeitung + * + */ + +/* + * Compress - Decompress Module (LZC Algorithm) + */ + +#include /* C Header Files ........................*/ + +#include "hpa101saptype.h" /* Common SAP Header Files ...............*/ +#include "hpa106cslzc.h" /* Internal Definitions for LZC algorithm */ +#include "hpa107cslzh.h" + +#include "hpa104CsObject.h" +#include "hpa105CsObjInt.h" + + + +/* 2 ** 8 - 2 ** i (i=0..8) ..........................................*/ +static BYTE_TYP lmask[9] = + {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; + +/* 2 ** i - 1 (i=0..8) ...............................................*/ +static BYTE_TYP rmask[9] = + {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + +/* needed for HP 64 compiling. Compare hpa106cslzc.h */ +CODE_INT DE_STACK_OFFSET = 1<<(CS_BITS+1); +// extern int csbufsize2; +// static BYTE_TYP *stack_end; + +// #define CS_STACK_CHECK 1 + +/* Macros for STACK CHECK in CsDecomp */ +#ifdef CS_STACK_CHECK + +/* +#define STACK_OVERFLOW_CHECK(p) ((p) >= ((BYTE_TYP *)&CsDeInterBuf[csbufsize2 / 4 - 1])) +*/ +#define STACK_OVERFLOW_CHECK(p) ((p) >= (csc.stack_end)) + +#define STACK_UNDERFLOW_CHECK(p) ((p) < (DE_STACK)) + +#define OVERFLOW_CHECK \ + if (STACK_OVERFLOW_CHECK(stackp)) \ + { \ + return CS_E_STACK_OVERFLOW; \ + } + +#define UNDERFLOW_CHECK \ + if (STACK_UNDERFLOW_CHECK(stackp)) \ + { \ + return CS_E_STACK_UNDERFLOW; \ + } + +#else + +#define OVERFLOW_CHECK +#define UNDERFLOW_CHECK + +#endif + + +#define PUTCODE(cod) /* PUTCODE Macro -----------------------------*/ \ +/*------------------------------------------------------------------*/ \ +/* Output one code (A maximum of CS_BITS is written) */ \ +/*------------------------------------------------------------------*/ \ +{ \ + register BYTE_TYP * bp = csc.buf1; \ + register int code = cod; \ + register unsigned int r_off, bits = csc.n_bits; \ + \ + if (csc.put_n_bytes) /* put out the rest ........*/ \ + { \ + if (csc.end_outbuf - csc.outptr >= csc.put_n_bytes) \ + { \ + BYTES_OUT (csc.outptr, csc.buf1 + csc.csc_offset, csc.put_n_bytes) \ + csc.put_n_bytes = 0; \ + csc.csc_offset = 0; \ + csc.cs_offset = 0; \ + } \ + else return CS_E_OUT_BUFFER_LEN; \ + } \ + \ + r_off = csc.cs_offset; \ + \ + if (code >= 0) /* valid code...............*/ \ + { \ + /* Get to the first byte ....................................*/ \ + bp += (r_off >> 3); \ + r_off &= 7; \ + \ + /* \ + * Since code is always >= 8 bits, only need to mask the first \ + * hunk on the left. \ + */ \ + \ + *bp = (*bp & rmask[r_off]) | ((code << r_off) & lmask[r_off]); \ + bp++; \ + r_off = 8 - r_off; \ + bits -= r_off; \ + code >>= r_off; \ + \ + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits)..*/ \ + if (bits >= 8) \ + { \ + *bp++ = code; \ + code >>= 8; \ + bits -= 8; \ + } \ + \ + /* Last bits .................................................*/ \ + if (bits) \ + *bp = code; \ + \ + csc.cs_offset += csc.n_bits; \ + if (csc.cs_offset == (csc.n_bits << 3)) \ + { \ + if (csc.end_outbuf - csc.outptr >= csc.n_bits) \ + { \ + BYTES_OUT (csc.outptr, csc.buf1, csc.n_bits) \ + } \ + else \ + { \ + csc.put_n_bytes = (SAP_INT) (csc.end_outbuf - csc.outptr); \ + BYTES_OUT (csc.outptr, csc.buf1, csc.put_n_bytes) \ + csc.csc_offset = csc.put_n_bytes; \ + csc.put_n_bytes = csc.n_bits - csc.put_n_bytes; \ + } \ + csc.cs_offset = 0; \ + } \ + \ + /* \ + * If the next entry is going to be too big for the code size, \ + * then increase it, if possible. \ + */ \ + \ + if (csc.free_ent > csc.maxcode || (csc.clear_flg > 0)) \ + { \ + /* \ + * Write the whole buffer, because the input side won't \ + * discover the size increase until after it has read it. \ + */ \ + \ + if (csc.cs_offset > 0) \ + { \ + if (csc.end_outbuf - csc.outptr >= csc.n_bits) \ + { \ + BYTES_OUT (csc.outptr, csc.buf1, csc.n_bits) \ + } \ + else \ + { \ + csc.put_n_bytes = (SAP_INT) (csc.end_outbuf - csc.outptr); \ + BYTES_OUT (csc.outptr, csc.buf1, csc.put_n_bytes) \ + csc.csc_offset = csc.put_n_bytes; \ + csc.put_n_bytes = csc.n_bits - csc.put_n_bytes; \ + } \ + csc.cs_offset = 0; \ + } \ + \ + if (csc.clear_flg) \ + { \ + csc.maxcode = MAXCODE (csc.n_bits = INIT_CS_BITS); \ + csc.clear_flg = 0; \ + } \ + else \ + { \ + (csc.n_bits)++; \ + if (csc.n_bits == csc.maxbits) \ + csc.maxcode = csc.maxmaxcode; \ + else \ + csc.maxcode = MAXCODE(csc.n_bits); \ + } \ + } \ + } \ + else /* At EOF, write the rest of the buffer .............*/ \ + { \ + if (csc.cs_offset > 0) \ + { \ + csc.n_bits = (csc.cs_offset + 7) / 8; \ + if (csc.end_outbuf - csc.outptr >= csc.n_bits) \ + { \ + BYTES_OUT (csc.outptr, csc.buf1, csc.n_bits) \ + } \ + else \ + { \ + csc.put_n_bytes = (SAP_INT) (csc.end_outbuf - csc.outptr); \ + BYTES_OUT (csc.outptr, csc.buf1, csc.put_n_bytes) \ + csc.csc_offset = csc.put_n_bytes; \ + csc.put_n_bytes = csc.n_bits - csc.put_n_bytes; \ + } \ + csc.cs_offset = 0; \ + } \ + } \ +} /* ------------ End of PUTCODE Macro -----------------------------*/ + + +/*--------------------------------------------------------------------*/ +/* Static functions (prototypes) */ +/*--------------------------------------------------------------------*/ + +SAP_INT CsObjectInt::CsGetStorageSize (void) +/*--------------------------------------------------------------------*/ +/* Get the size for internal storage */ +/*--------------------------------------------------------------------*/ +{ + return ((SAP_INT) sizeof (csc.htab) + (SAP_INT) sizeof (csc.codetab)); +} + + +int CsObjectInt::InitComp (BYTE_TYP * outbuf, + SAP_INT outlen, + SAP_INT sumlen) +/*--------------------------------------------------------------------*/ +/* Setup header info */ +/* Clear hash table */ +/* Initialize static variables for compression */ +/*--------------------------------------------------------------------*/ +{ + if (outlen < CS_HEAD_SIZE) /* too small ......................*/ + return CS_E_OUT_BUFFER_LEN; + + if (sumlen <= 0L) + return CS_E_INVALID_SUMLEN; + + csc.clear_flg = 0; /* init compression states ........*/ + csc.ratio = 0; + + csc.block_compress = BLOCK_MASK; + csc.maxbits = CS_BITS; + + csc.checkpoint = CHECK_GAP; + csc.maxcode = MAXCODE (csc.n_bits = INIT_CS_BITS); + csc.maxmaxcode = (CODE_INT)1 << CS_BITS; + csc.free_ent = ((csc.block_compress) ? FIRST : 256); + csc.hsize = HSIZE; + CL_HASH (csc.hsize); /* clear hash table .......................*/ + /* fill in header informations ............*/ + CsSetHead (outbuf, sumlen, + (BYTE_TYP) ((CS_VERSION << 4) | CS_ALGORITHM), + (BYTE_TYP) (csc.maxbits | csc.block_compress)); + + return 0; +} + + +int CsObjectInt::CsComprLZC (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written) +/*--------------------------------------------------------------------*/ +/* LZC method to compress a file */ +/* */ +/* Adaptive Dictionary Compression */ +/* Lempel-Zip-Thomas */ +/* */ +/* */ +/* Input: */ +/* ----- */ +/* sumlen length of data stream to compress */ +/* inbuf Pointer to input memory */ +/* inlen Length of input memory */ +/* outbuf Pointer to output area */ +/* outlen Length of output area */ +/* option Compress option: */ +/* CS_INIT_COMPRESS initial */ +/* CS_NORMAL_COMPRESS */ +/* Output: */ +/* ------ */ +/* bytes_read Bytes read from input buffer */ +/* bytes_compressed Bytes compressed to output buffer */ +/* */ +/* Internal Functions: */ +/* ------------------ */ +/* InitComp Initialize Compression */ +/* PUTCODE Write Code to output buffer */ +/* */ +/* Return Code: */ +/* ----------- */ +/* CS_END_OF_STREAM End of input reached */ +/* CS_END_INBUFFER End of input reached */ +/* CS_END_OUTBUFFER End of output reached */ +/* */ +/* CS_E_IN_BUFFER_LEN Input buffer length to short */ +/* CS_E_OUT_BUFFER_LEN Output Buffer length to short */ +/* CS_E_INVALID_SUMLEN sumlen <= 0 */ +/* CS_E_INVALID_ADDR Invalid addr for input or output buffer*/ +/* CS_E_FATAL internal (should never happen) */ +/* */ +/*--------------------------------------------------------------------*/ +{ + register SAP_INT fcode; + register CODE_INT i = 0; + register BYTE_TYP *inptr = inbuf; + register int c; + register CODE_INT disp; + + int rc; + + *bytes_read = 0; + *bytes_written = 0; + + /* Check input parameters ..........................................*/ + + if (inlen < 0) return CS_E_IN_BUFFER_LEN; /* return ............*/ + + if (outlen < 0) return CS_E_OUT_BUFFER_LEN; /* return ............*/ + + if (inbuf == (BYTE_TYP *) 0 || outbuf == (BYTE_TYP *) 0) + return CS_E_INVALID_ADDR; /* return ............*/ + + if (inbuf == outbuf) return CS_E_IN_EQU_OUT; /* return ............*/ + + csc.outptr = outbuf; + + if (option & CS_INIT_COMPRESS) /* only initial ................*/ + { + if (sumlen <= 0) return CS_E_INVALID_SUMLEN; /* return ..........*/ + + rc = InitComp (outbuf, outlen, sumlen); + if (rc) return rc; /* return with Error ...............*/ + + csc.cs_offset = 0; + csc.csc_offset = 0; + csc.in_count_sum = 0; + csc.put_n_bytes = 0; + csc.bytes_out = 0; + csc.sflush = 0; + csc.org_len = sumlen; /* save sum length .................*/ + csc.outptr = outbuf + CS_HEAD_SIZE; /* 4 byte length, 4 byte header*/ + + csc.hshift = 0; + for (fcode = (SAP_INT) csc.hsize; fcode < 65536; fcode += fcode) + (csc.hshift)++; + csc.hshift = 8 - csc.hshift; /* set hash code range bound .......*/ + + csc.ent = (CODE_INT) -1; + if (inlen == 0) /* only header .....................*/ + { + *bytes_written = CS_HEAD_SIZE; + csc.bytes_out += *bytes_written; + return CS_END_INBUFFER; + } + } + + if (csc.ent == (CODE_INT) -1) /* get first byte ..................*/ + csc.ent = *inptr++; + + csc.end_inbuf = inbuf + inlen; /* end of input buffer .............*/ + csc.end_outbuf = outbuf + outlen; /* end of output buffer ............*/ + + if (csc.sflush == 1) /* end of outbuf in last run, must output CLEAR .*/ + { + if ((rc = PutCode ((CODE_INT) CLEAR)) < 0) + goto ende; + + if (csc.put_n_bytes) /* no more space in outbuf .........*/ + { + rc = CS_END_OUTBUFFER; + goto ende; + } + csc.sflush = 0; + } + + while (inptr < csc.end_inbuf) /* until end of input ...........*/ + { + c = *inptr++; /* next char ....................*/ + /* hash function ................*/ + fcode = (SAP_INT) (((SAP_INT) c << csc.maxbits) + csc.ent); + i = (((CODE_INT)c << csc.hshift) ^ csc.ent); /* xor hashing ...........*/ + + if (i < 0) return CS_E_FATAL; /* should never happen ..........*/ + + if (HTABOF (i) == fcode) /* found in htab ................*/ + { + csc.ent = CODETABOF (i); + continue; + } + else + if ((SAP_INT)HTABOF (i) < 0) /* empty slot ....................*/ + goto nomatch; + + disp = csc.hsize - i; /* secondary hash (G. Knott) .....*/ + if (i == 0) disp = 1; + +probe: + if ((i -= disp) < 0) + i += csc.hsize; + + if (HTABOF (i) == fcode) /* found in htab .................*/ + { + csc.ent = CODETABOF (i); + continue; /* get next char .................*/ + } + + if ( (SAP_INT)HTABOF (i) > 0 ) + goto probe; /* test again ....................*/ + +nomatch: /* new entry .....................*/ + PUTCODE ((CODE_INT) csc.ent) + + csc.ent = c; + if (csc.free_ent < csc.maxmaxcode) /* enough space in table ? .......*/ + { + CODETABOF (i) = (csc.free_ent)++; /* code -> hashtable .............*/ + HTABOF (i) = fcode; + } + else /* test clear code table .........*/ + if (((SAP_INT)(inptr - inbuf) + csc.in_count_sum >= + csc.checkpoint) && csc.block_compress) + { + rc = ClearBlock (csc.in_count_sum + (SAP_INT)(inptr - inbuf), + csc.bytes_out + (SAP_INT) (csc.outptr - outbuf)); + if (rc) + { + if (csc.put_n_bytes) /* no more space in outbuf .......*/ + { + csc.sflush = 1; + rc = CS_END_OUTBUFFER; + goto ende; + } + if ((rc = PutCode ((CODE_INT) CLEAR)) < 0) + goto ende; + } + } + + if (csc.put_n_bytes) /* not enough space in outbuffer .*/ + { + rc = CS_END_OUTBUFFER; + goto ende; + } + } /* end while ....................................................*/ + + rc = CS_END_INBUFFER; + /* end of stream ....*/ + if (csc.in_count_sum + (SAP_INT)(inptr - inbuf) >= csc.org_len) + { + if (csc.sflush < 3) + { + if ((rc = PutCode ((CODE_INT) csc.ent)) < 0) + goto ende; + if (csc.put_n_bytes) /* not enough space in outbuffer ...*/ + { + csc.sflush = 3; + rc = CS_END_OUTBUFFER; + goto ende; + } + } + + if (csc.sflush != 4) + { + if ((rc = PutCode ((CODE_INT) -1)) < 0) + goto ende; + + if (csc.put_n_bytes) /* not enough space in outbuffer ...*/ + { + csc.sflush = 4; + rc = CS_END_OUTBUFFER; + goto ende; + } + } + else + if ((rc = PutCode ((CODE_INT) -1)) < 0) + goto ende; + + rc = CS_END_OF_STREAM; /* end of data reached ..............*/ + } + +ende: /* set output parameters and save */ + *bytes_written = (SAP_INT) (csc.outptr - outbuf); + *bytes_read = (SAP_INT) (inptr - inbuf); + csc.in_count_sum += *bytes_read; /* the sum of input length .......*/ + csc.bytes_out += *bytes_written; /* the sum of output length ......*/ + + return rc; +} + + +int CsObjectInt::ClearBlock (SAP_INT in_count, SAP_INT bytes_out) +/*--------------------------------------------------------------------*/ +/* table clear for block compress if compression ratio is "bad" */ +/* returns 1: clear block */ +/* returns 0: no clear */ +/*--------------------------------------------------------------------*/ +{ + register SAP_INT rat; + + csc.checkpoint = in_count + CHECK_GAP; + + if (in_count > 0x007fffffL) /* shift will overflow ...............*/ + { + rat = bytes_out >> 8; + if (rat == 0) /* Don't divide by zero ..............*/ + rat = 0x7fffffffL; + else + rat = in_count / rat; + } + else + rat = (in_count << 8) / bytes_out; /* 8 fractional bits .....*/ + + if (rat > csc.ratio) + csc.ratio = rat; + else /* clear hash table ..................*/ + { + csc.ratio = 0; + CL_HASH (csc.hsize); + csc.free_ent = FIRST; + csc.clear_flg = 1; + return 1; /* indicates: flush a CLEAR ...........*/ + } + return 0; /* no CLEAR ...........................*/ +} + + +int CsObjectInt::CsDecomprLZC (SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written) +/*--------------------------------------------------------------------*/ +/* LZC decompress */ +/* */ +/* Adaptive Dictionary Compression */ +/* Lempel-Zip-Welch-Thomas */ +/* */ +/* Input: */ +/* ----- */ +/* inbuf Pointer to input memory */ +/* inlen Length of input memory */ +/* outbuf Pointer to output area */ +/* outlen Length of output area */ +/* option Compress option: */ +/* CS_INIT_COMPRESS initial */ +/* CS_NORMAL_COMPRESS */ +/* */ +/* Output: */ +/* ------ */ +/* bytes_read Bytes read from input buffer */ +/* bytes_written Bytes decompressed to output buffer */ +/* */ +/* Internal Functions: */ +/* ------------------ */ +/* GetCode Get a code from input buffer */ +/* */ +/* Return Code: */ +/* ----------- */ +/* CS_END_OF_STREAM End of input stream reached */ +/* CS_END_INBUFFER End of input buffer reached */ +/* CS_END_OUTBUFFER End of output buffer reached */ +/* */ +/* CS_E_OUT_BUFFER_LEN Output buffer length to short */ +/* CS_E_IN_BUFFER_LEN Input buffer length to short */ +/* CS_E_MAXBITS_TOO_BIG No internal memory to decompress */ +/* CS_E_INVALID_LEN inlen < 0 or outlen < CS_BITS */ +/* CS_E_FILENOTCOMPRESSED Input is not compressed */ +/* CS_E_IN_EQU_OUT Same addr for input and output buffer */ +/* CS_E_INVALID_ADDR Invalid addr for input or output buffer*/ +/* CS_E_FATAL Internal (should never happen) */ +/* */ +/*--------------------------------------------------------------------*/ +{ + register BYTE_TYP *stackp; + register CODE_INT code, oldcode, incode, finchar; + register SAP_INT rest_lenr; +/* + static BYTE_TYP *sstackp = (BYTE_TYP *) 0; + + static long dorg_len; + static CODE_INT scode, soldcode, sincode, sfinchar; + static int restart; +*/ +#ifdef SAPonWINDOWS + Suffixtab = (BYTE_TYP *) CsDeInterBuf; + + Prefixtab = (CODE_ENTRY *) CsDeWindowBuf; +#endif + + *bytes_read = 0; /* init output parameters ...*/ + *bytes_written = 0; + + /* Check input parameters ..........................................*/ + if (inlen < 0) /* invalid len of inbuf .....*/ + return CS_E_IN_BUFFER_LEN; + /* invalid addr .............*/ + if (inbuf == (BYTE_TYP *) 0 || outbuf == (BYTE_TYP *) 0) + return CS_E_INVALID_ADDR; + + if (inbuf == outbuf) /* inbuf == outbuf: invalid !*/ + return CS_E_IN_EQU_OUT; + + csc.end_inbuf = inbuf + inlen; /* set start & end ptrs .....*/ + csc.end_outbuf = outbuf + outlen; + csc.outptr = outbuf; + rest_lenr = csc.rest_len; /* push to register .........*/ + + if (option & CS_INIT_DECOMPRESS) /* only initial .............*/ + { + csc.sstackp = (BYTE_TYP *) 0; + csc.restart = 0; + csc.csc_offset = 0; + csc.get_size = 0; + csc.get_r_bits = -1; +// csc.stack_end = &(csc.Suffixtab[csbufsize2 - 1]); + + if (inlen < CS_HEAD_SIZE) /* input buffer too small ......*/ + return CS_E_IN_BUFFER_LEN; + + csc.dorg_len = CsGetLen (inbuf); /* get sum length */ + + if (csc.dorg_len < 0) /* and check if file is compr. .*/ + return (CS_E_FILENOTCOMPRESSED); + + csc.maxbits = inbuf[7]; /* get max. bits ...............*/ + csc.block_compress = csc.maxbits & BLOCK_MASK; + csc.maxbits &= BIT_MASK; + csc.maxmaxcode = (CODE_INT) 1 << csc.maxbits; + csc.maxcode = MAXCODE(csc.n_bits = INIT_CS_BITS); + + if (csc.maxbits > CS_BITS + 1) /* not enough memory to decompress */ + return CS_E_MAXBITS_TOO_BIG; + + /* get version and algorithm .....................................*/ + /* not supported at the moment ...................................*/ + + for (code = 255; code >= 0; code--) /* init. code table .......*/ + { + TAB_PREFIXOF(code) = 0; + TAB_SUFFIXOF(code) = (BYTE_TYP) code; + } + + csc.free_ent = ((csc.block_compress) ? FIRST : 256); /* first entry ....*/ + + csc.in_ptr = inbuf + CS_HEAD_SIZE; /* skip header .................*/ + csc.rest_len = csc.dorg_len; /* save sum length .............*/ + rest_lenr = csc.rest_len; + stackp = DE_STACK; /* init. stack ptr .............*/ + + if (outlen == 0) /* End of output buffer ........*/ + { + code = CS_END_OUTBUFFER; + goto ende; + } + + if (csc.in_ptr >= csc.end_inbuf) /* End of input buffer .........*/ + { + code = CS_END_INBUFFER; + goto ende; + } + } + else /* not initial .................*/ + { + csc.in_ptr = inbuf; + stackp = csc.sstackp; /* restore states ..............*/ + finchar = csc.sfinchar; + oldcode = csc.soldcode; + + if (outlen <= 0) /* min. size for outbuffer .....*/ + return CS_E_OUT_BUFFER_LEN; + + if (rest_lenr <= 0) /* end of input ................*/ + { + code = CS_END_OF_STREAM; + goto ende; + } + + if (csc.restart) /* output buffer to small in last run ..............*/ + { + /* restore machine state .......................................*/ + code = csc.scode; + incode = csc.sincode; + csc.restart = 0; + goto contin; + } + } + + if (csc.get_r_bits == -1) /* init. decoding ..............*/ + { + finchar = oldcode = (CODE_INT) GetCode (); + csc.get_r_bits = 0; /* not redundant !!! ...........*/ + + if (outlen == 0) /* must have some space ........*/ + { + code = CS_END_OUTBUFFER; + goto ende; + } + + *csc.outptr++ = (BYTE_TYP) finchar; + if (--rest_lenr <= 0) /* End of stream ...............*/ + { + code = CS_END_OF_STREAM; + goto ende; + } + } + + for (;;) /* until not end of inbuf ......*/ + { + code = GetCode (); + if (code < 0) break; + + if ((code == CLEAR) && csc.block_compress) + { + /* clear code table ............................................*/ + memset (csc.Prefixtab, '\0', sizeof (CODE_ENTRY) << 8); + csc.clear_flg = 1; + csc.free_ent = FIRST - 1; + + if ((code = GetCode ()) < 0) + break; + } + + incode = code; + + /* Special case for ababa string .................................*/ + if (code >= csc.free_ent) + { + *stackp++ = (BYTE_TYP) finchar; + OVERFLOW_CHECK + code = oldcode; + } + + /* Generate output characters in reverse order ...................*/ + while (code >= 256) + { + *stackp++ = TAB_SUFFIXOF(code); + OVERFLOW_CHECK + code = TAB_PREFIXOF(code); + } + + finchar = TAB_SUFFIXOF(code); + *stackp++ = (BYTE_TYP) finchar; + OVERFLOW_CHECK + +contin: + /* and put them out in forward order .............................*/ + for (;;) + { + if (csc.outptr >= csc.end_outbuf) /* End of outbuffer ...........*/ + { + csc.scode = code; + csc.sincode = incode; + csc.restart = 1; + code = CS_END_OUTBUFFER; + goto ende; + } + + *csc.outptr++ = *--stackp; + + if (--rest_lenr <= 0) /* End of Stream ..............*/ + { + code = CS_END_OF_STREAM; + goto ende; + } + + if (stackp == DE_STACK) break; /* End of Stack ...............*/ + } /* end for (;;) ...............................................*/ + + /* Generate the new entry ........................................*/ + if ((code = csc.free_ent) < csc.maxmaxcode) + { + TAB_PREFIXOF(code) = (CODE_ENTRY)oldcode; + TAB_SUFFIXOF(code) = (BYTE_TYP) finchar; + csc.free_ent = code + 1; + } + + /* Remember previous code ........................................*/ + oldcode = incode; + + } /* end for (;;) .................................................*/ + +ende: + csc.sstackp = stackp; /* save state of the compressor ...*/ + csc.soldcode = oldcode; + csc.sfinchar = finchar; + csc.rest_len = rest_lenr; + /* set output parameters ..........*/ + *bytes_written = (SAP_INT) (csc.outptr - outbuf); + *bytes_read = (SAP_INT) (csc.in_ptr - inbuf); + + if (code == CS_IEND_INBUFFER) return CS_END_INBUFFER; + else + return code; +} + + +CODE_INT CsObjectInt::GetCode (void) +/*--------------------------------------------------------------------*/ +/* Read the next code from input stream */ +/*--------------------------------------------------------------------*/ +/* Returns: code on default */ +/* CS_IEND_INBUFFER on end of input buffer */ +/* */ +/*--------------------------------------------------------------------*/ +{ + register CODE_INT code; + + register int r_off, bits; + register BYTE_TYP *bp = csc.buf1; + + for (;;) + { + if (csc.get_r_bits > 0) /* does not fit in last run .....*/ + { + csc.get_r_bits = (SAP_INT) MIN (csc.get_r_bits, csc.end_inbuf - csc.in_ptr); + csc.get_r_bits = MAX (0, csc.get_r_bits); + BYTES_IN (csc.buf1 + csc.get_size, csc.in_ptr, csc.get_r_bits) + csc.get_size += csc.get_r_bits; + csc.get_r_bits = 0; + csc.get_size = (csc.get_size << 3) - (csc.n_bits - 1); + csc.csc_offset = 0; + } + else + if (csc.clear_flg > 0 || csc.csc_offset >= csc.get_size || csc.free_ent > csc.maxcode) + { + /* + * If the next entry will be too big for the current code + * get_size, then we must increase the get_size. + * This implies reading a new buffer full, too. + */ + + if (csc.free_ent > csc.maxcode) + { + (csc.n_bits)++; + if (csc.n_bits == csc.maxbits) + csc.maxcode = csc.maxmaxcode; /* won't get any bigger now .....*/ + else + csc.maxcode = MAXCODE(csc.n_bits); + } + + if (csc.clear_flg > 0) + { + csc.maxcode = MAXCODE (csc.n_bits = INIT_CS_BITS); + csc.clear_flg = 0; + } + + csc.get_size = (SAP_INT) (csc.end_inbuf - csc.in_ptr); + if (csc.get_size < csc.n_bits) /* does not fit in buffer .....*/ + { + if (csc.get_size <= 0) + { + code = CS_IEND_INBUFFER; /* end of stream ..............*/ + break; + } + if (csc.get_r_bits < 0) /* initial !!! ................*/ + csc.get_r_bits = 0; + else /* end of input buffer ........*/ + { + BYTES_IN (csc.buf1, csc.in_ptr, csc.get_size) + csc.get_r_bits = csc.n_bits - csc.get_size; + csc.csc_offset = 0; + code = CS_IEND_INBUFFER; + break; + } + } + else /* min (n_bits, get_size) .*/ + csc.get_size = csc.n_bits; + + BYTES_IN (csc.buf1, csc.in_ptr, csc.get_size) + csc.csc_offset = 0; + + /* Round get_size down to integral number of codes ...........*/ + csc.get_size = (csc.get_size << 3) - (csc.n_bits - 1); + } + + /* Do all the terrible bit staff ...............................*/ + r_off = csc.csc_offset; + bits = csc.n_bits; + + bp += (r_off >> 3); + r_off &= 7; + + /* Get first part (low order bits) .............................*/ + code = (int)*bp >> r_off; + bp++; + r_off = 8 - r_off; + bits -= r_off; + + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits) */ + if (bits >= 8) + { + code |= (int) *bp << r_off; + bp++; + r_off += 8; + bits -= 8; + } + + /* high order bits .............................................*/ + code |= ((int)*bp & rmask[bits]) << r_off; + csc.csc_offset += csc.n_bits; + break; + } + + return code; +} + + +int CsObjectInt::PutCode (CODE_INT c) +/*--------------------------------------------------------------------*/ +/* Put out next code to output stream */ +/*--------------------------------------------------------------------*/ +/* Returns: 0 on default */ +/* CS_E_OUT_BUFFER_LEN on end of output buffer */ +/* */ +/*--------------------------------------------------------------------*/ +{ + PUTCODE (c) + return 0; +} diff --git a/vpa107cslzh.cpp b/vpa107cslzh.cpp new file mode 100644 index 0000000..3d2b355 --- /dev/null +++ b/vpa107cslzh.cpp @@ -0,0 +1,1499 @@ +/* + + + + ========== licence begin GPL + Copyright (c) 2000-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + + +*/ +#include +#include + +#include "hpa101saptype.h" /* Common SAP Header Files ...............*/ +#include "hpa106cslzc.h" /* Internal Definitions for LZC algorithm */ +#include "hpa107cslzh.h" + +#include "hpa104CsObject.h" +#include "hpa105CsObjInt.h" + + +#define H_SHIFT ((CS_HASH_BITS+MIN_MATCH-1)/MIN_MATCH) + +typedef struct CONFIG +{ + int good_length; + int max_lazy; + unsigned max_chain; + unsigned char flag; +} CONFIG; + +static CONFIG ConfigTab[10] = +{ + /* good lazy chain flag */ + /* 0 */ {0, 0, 0, 0}, /* store only */ + /* 1 */ {4, 4, 16, FAST_PA107}, /* maximum speed */ + /* 2 */ {6, 8, 16, 0}, + /* 3 */ {8, 16, 32, 0}, + /* 4 */ {8, 32, 64, 0}, + /* 5 */ {8, 64, 128, 0}, + /* 6 */ {8, 128, 256, 0}, + /* 7 */ {8, 128, 512, 0}, + /* 8 */ {32, 258, 1024, 0}, + /* 9 */ {32, 258, 4096, SLOW_PA107} /* maximum compression */ +}; + +/* Note: the current code requires max_lazy >= MIN_MATCH and + max_chain >= 4 but these restrictions can easily be + removed at a small cost. + */ + +#define BIT_BUF_SIZE (8 * 2 * sizeof(char)) + +int NEAR CsExtraLenBits[LENGTH_CODES+2] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,99,99}; + +int NEAR CsExtraDistBits[D_CODES] /* extra bits for each distance code */ += {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + + +static unsigned char bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; + +/* Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(h,c) (h = (((h)< (unsigned)MAX_DIST ? + csh.StrStart - (unsigned)MAX_DIST : 0; + + int good_match = ConfigTab[csh.pack_level].good_length; + /* max hash chain length */ + unsigned chain_length = ConfigTab[csh.pack_level].max_chain; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. */ + + register unsigned char scan_start = *scan; + register unsigned char scan_end1 = scan[best_len-1]; + register unsigned char scan_end = scan[best_len]; + + /* Do not waste too much time if we already have a good match: */ + if (csh.PrevLen >= good_match) + { + chain_length >>= 2; + } + + do + { + match = csh.window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || *match != scan_start) + continue; + + /* It is not necessary to compare scan[1] and match[1] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that h_shift+8 <= CS_HASH_BITS, + * that is, when the last byte is entirely included in the hash key. + * The condition is equivalent to + * (CS_HASH_BITS+2)/3 + 8 <= CS_HASH_BITS + * or: CS_HASH_BITS >= 13 + * Also, we check for a match at best_len-1 to get rid quickly of + * the match with the suffix of the match made at the previous step, + * which is known to fail. */ + +#if CS_HASH_BITS >= 13 + len = 1; +#else + len = 0; +#endif + do {} while (++len < MAX_MATCH && scan[len] == match[len]); + + if (len > best_len) + { + csh.MatchStart = cur_match; + best_len = len; + + if (len == MAX_MATCH) break; + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; + } + } while (--chain_length != 0 && + (cur_match = csh.CsPrev[cur_match & WMASK]) > limit); + + return best_len; +} + + +#else /* UNALIGNED_OK */ + +int CsObjectInt::LongestMatch (unsigned cur_match) /* current match */ +{ + REGISTER uch *scan = csh.window + csh.StrStart; /* current string */ + REGISTER uch *match = scan; /* matched string */ + REGISTER int len; /* length of current match */ + int best_len = csh.PrevLen; /* best match length so far */ + unsigned limit = csh.StrStart > (unsigned)MAX_DIST ? csh.StrStart - (unsigned)MAX_DIST : 0; + int good_match = ConfigTab[csh.pack_level].good_length; + /* max hash chain length */ + unsigned chain_length = ConfigTab[csh.pack_level].max_chain; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. */ + + REGISTER ush scan_start = *(ush*)scan; + REGISTER ush scan_end = *(ush*)(scan+best_len-1); + + /* Do not waste too much time if we already have a good match: */ + if (csh.PrevLen >= good_match) + { + chain_length >>= 2; + } + + do + { + match = csh.window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: */ + + /* This code assumes sizeof(unsigned short) == 2 and + * sizeof(unsigned long) == 4. Do not use UNALIGNED_OK if your + * compiler uses different sizes. */ + + if (*(ush*)(match+best_len-1) != scan_end || + *(ush*)match != scan_start) continue; + + len = MIN_MATCH - 4; + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that CS_HASH_BITS >= 8. + */ + do {} while ((len+=4) < MAX_MATCH-3 && + *(SAP_UINT*)(scan+len) == *(SAP_UINT*)(match+len)); + /* The funny do {} generates better code for most compilers */ + + if (*(ush*)(scan+len) == *(ush*)(match+len)) len += 2; + if (scan[len] == match[len]) len++; + + + if (len > best_len) + { + csh.MatchStart = cur_match; + best_len = len; + + if (len == MAX_MATCH) break; + scan_end = *(ush*)(scan+best_len-1); + } + } while (--chain_length != 0 && + (cur_match = csh.CsPrev[cur_match & WMASK]) > limit); + + return best_len; +} +#endif + + +void CsObjectInt::FillWindow (void) +/*--------------------------------------------------------------------*/ +/* Fill the window when the Lookahead becomes insufficient. */ +/* Updates StrStart and Lookahead, and sets eoInput if end of */ +/* input file. */ +/* IN assertion: Lookahead < MIN_LOOKAHEAD && StrStart + Lookahead>0 */ +/* OUT assertion: at least one byte has been read, or eoInput is set. */ +/*--------------------------------------------------------------------*/ +{ + register unsigned n, m; + unsigned more = (unsigned)((SAP_UINT)2*WSIZE + - (SAP_UINT)csh.Lookahead - (SAP_UINT) csh.StrStart); + int rc; + + csh.eoInput = 0; + + /* If the window is full, move the upper half to the lower one to make + * room in the upper half. */ + if (more == 0) + { + /* By the IN assertion, the window is not empty so we can't confuse + * more == 0 with more == 64K on a 16 bit machine. */ + + memcpy (csh.window, csh.window + WSIZE, (unsigned)WSIZE); + csh.MatchStart -= WSIZE; + csh.StrStart -= WSIZE; + + /* StrStart - WSIZE = WSIZE - Lookahead > WSIZE - MIN_LOOKAHEAD + * so we now have StrStart > MAX_DIST: */ + + csh.BlockStart -= (SAP_INT) WSIZE; + + for (n = 0; n < CS_HASH_SIZE; n++) + { + m = csh.CsHead[n]; + csh.CsHead[n] = (unsigned short)(m >= WSIZE ? m-WSIZE : 0); + } + + for (n = 0; n < WSIZE; n++) + { + m = csh.CsPrev[n]; + csh.CsPrev[n] = (unsigned short)(m >= WSIZE ? m-WSIZE : 0); + + /* If n is not on any hash chain, CsPrev[n] is garbage but + * its value will never be used. */ + } + more = WSIZE; + } + else + if (more == (unsigned)EODATA) + { + /* Very unlikely, but possible on 16 bit machine if StrStart == 0 + * and Lookahead == 1 (input done one byte at time) */ + more--; + } + + rc = MemRead (csh.window + csh.StrStart + csh.Lookahead, more); + + if (rc == -1) csh.eoData = 1; + else + if (rc == 0) csh.eoInput = 1; + else + csh.Lookahead += (unsigned) rc; +} + + +/* + * Processes a new input file and return its compressed length. + * We use a lazy evaluation for matches: + * a match is finally adopted only if there is + * no better match at the next window position. + */ + +SAP_INT CsObjectInt::ComprLZH (unsigned opt) +{ + unsigned short HashHead; /* head of hash chain ..................*/ + unsigned PrevMatch; /* previous match ......................*/ + int flush; /* set if current block must be flushed */ + unsigned eof; + unsigned max_lazy_match = ConfigTab[csh.pack_level].max_lazy; + unsigned init = opt; + + + if (!csh.eoData) /* fill lookahead buffer ...............*/ + { + while (csh.Lookahead < MIN_LOOKAHEAD && !csh.eoData) + { + FillWindow (); + if (init) + { + init = 0; + HashInit (); + } + if (csh.eoInput) return (csh.out_offset); + } + } + + while (csh.Lookahead != 0) /* Process the input block. */ + { + /* Insert the string window[StrStart .. StrStart+2] in the + * dictionary, and set HashHead to the head of the hash chain: */ + INSERT_STRING (csh.StrStart, HashHead); + + /* Find the longest match, discarding those <= PrevLen. */ + csh.PrevLen = (int) csh.MatchLen, PrevMatch = csh.MatchStart; + csh.MatchLen = MIN_MATCH-1; + + if (HashHead != 0 && (unsigned) csh.PrevLen < max_lazy_match && + csh.StrStart - HashHead <= MAX_DIST) + { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). */ + + csh.MatchLen = LongestMatch ((unsigned)HashHead); + /* LongestMatch() sets MatchStart */ + + if (csh.MatchLen > csh.Lookahead) csh.MatchLen = csh.Lookahead; + /* Ignore a length 3 match if it is too distant: */ + + if (csh.MatchLen == MIN_MATCH && csh.StrStart - csh.MatchStart > TOO_FAR) + { + /* If PrevMatch is also MIN_MATCH, MatchStart is garbage + * but we will ignore the current match anyway. */ + csh.MatchLen--; + } + } + + /* If there was a match at the previous step and the current .....*/ + /* match is not better, output the previous match: ...............*/ + + if (csh.PrevLen >= MIN_MATCH && csh.MatchLen <= (unsigned) csh.PrevLen) + { + flush = ct_tally (csh.StrStart - 1 - PrevMatch, csh.PrevLen - MIN_MATCH); + + /* Insert in hash table all strings up to the end of the match..*/ + /* StrStart-1 and StrStart are already inserted. ...............*/ + + csh.Lookahead -= csh.PrevLen-1; + csh.PrevLen -= 2; + do + { + csh.StrStart++; + INSERT_STRING(csh.StrStart, HashHead); + + /* StrStart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. If Lookahead < MIN_MATCH + * these bytes are garbage, but it does not matter since the + * next Lookahead bytes will always be emitted as literals. */ + + } while (--csh.PrevLen != 0); + + csh.MatchAvail = 0; + csh.MatchLen = MIN_MATCH-1; + } + else + if (csh.MatchAvail) + { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. */ + + flush = ct_tally (0, csh.window[csh.StrStart-1]); + (csh.Lookahead)--; + } + else + { + /* There is no previous match to compare with, wait for + * the next step to decide. */ + + csh.MatchAvail = 1; + flush = 0; + (csh.Lookahead)--; + } + + if (flush) + { + FlushBlock (0); + csh.BlockStart = csh.StrStart; + (csh.StrStart)++; + + if (csh.bytes_pending) return csh.out_offset; + } + else + (csh.StrStart)++; + + /* Make sure that we always have enough Lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. */ + + if (!csh.eoData) + { + while (csh.Lookahead < MIN_LOOKAHEAD && !(csh.eoInput)) + { + FillWindow (); + if (csh.eoData) break; + if (csh.eoInput) return (csh.out_offset); + } + } + } + + if (csh.MatchAvail) ct_tally (0, csh.window[csh.StrStart-1]); + + eof = (csh.eoData && (csh.bytes_pending == 0)) ? 1 : 0; + FlushBlock (eof); + + return (csh.out_offset); +} + +#define PUTSHORT(w) \ +{ if (csh.out_offset < csh.out_size-1) \ + { \ + csh.out_buf[csh.out_offset++] = (unsigned char) ((w) & 0xff); \ + csh.out_buf[csh.out_offset++] = (unsigned char) ((unsigned short)(w) >> 8); \ + } \ + else \ + if (csh.out_offset < csh.out_size) \ + { \ + csh.out_buf[csh.out_offset++] = (unsigned char) ((w) & 0xff); \ + csh.InterBuf[csh.bytes_pending++] = (unsigned char) ((unsigned short)(w) >> 8); \ + } \ + else \ + { \ + csh.InterBuf[csh.bytes_pending++] = (unsigned char) ((w) & 0xff); \ + csh.InterBuf[csh.bytes_pending++] = (unsigned char) ((unsigned short)(w) >> 8); \ + } \ +} + +#define PUTBYTE(b) \ + (csh.out_offset < csh.out_size) ? \ + (csh.out_buf[csh.out_offset++] = (unsigned char) (b)) : \ + (csh.InterBuf[csh.bytes_pending++] = (unsigned char) (b)) + + +/* ==================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ + +#define SEND_BITS(value,length) \ +{ \ + if (csh.bi_valid > (int)BIT_BUF_SIZE - (length)) \ + { \ + csh.bi_buf |= ((value) << csh.bi_valid); \ + PUTSHORT(csh.bi_buf); \ + csh.bi_buf = (unsigned short)(value) >> (BIT_BUF_SIZE - csh.bi_valid); \ + csh.bi_valid += (length) - BIT_BUF_SIZE; \ + } \ + else \ + { \ + csh.bi_buf |= (value) << csh.bi_valid; \ + csh.bi_valid += (length); \ + } \ +} + + +/* Send a code of the given tree. c and tree must not have side effects */ +#define SEND_CODE(c,tree) SendBits(tree[c].Code, tree[c].Len) + +#define D_CODE(dist) \ + ((dist) < 256 ? csh.dist_code[dist] : csh.dist_code[256+((dist)>>7)]) + + + +void CsObjectInt::SendBits (unsigned value, int len) +/*--------------------------------------------------------------------*/ +/* Send a value with len bits (len <=16) */ +/*--------------------------------------------------------------------*/ +{ + SEND_BITS (value,len); +} + +void CsObjectInt::HufTabInit (void) +/*--------------------------------------------------------------------*/ +/* Allocate the match buffer, initialize the various tables. */ +/*--------------------------------------------------------------------*/ +{ + int n; /* iterates over tree elements */ + int nend; + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + + /* Initialize the first block of the first file ....................*/ + InitBlock (); +#if 0 + if (csh.static_dtree[0].Len != 0) return; /* HufTabInit already called */ +#endif + /* Initialize the mapping length (0..255) -> length code (0..28) ...*/ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) + { + csh.base_length[code] = length; + nend = (1 << CsExtraLenBits[code]); + for (n = 0; n < nend; n++) + { + csh.length_code[length++] = (unsigned char)code; + } + } + + csh.length_code[length-1] = (unsigned char)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) .......*/ + dist = 0; + for (code = 0; code < 16; code++) + { + csh.base_dist[code] = dist; + nend = (1 << CsExtraDistBits[code]); + for (n = 0; n < nend; n++) + { + csh.dist_code[dist++] = (unsigned char)code; + } + } + + dist >>= 7; /* from now on, all distances are divided by 128 .......*/ + for ( ; code < D_CODES; code++) + { + csh.base_dist[code] = dist << 7; + nend = 1 << (CsExtraDistBits[code]-7); + for (n = 0; n < nend; n++) + { + csh.dist_code[256 + dist++] = (unsigned char)code; + } + } + + /* Construct the codes of the static literal tree ..................*/ + for (bits = 0; bits <= MAX_BITS; bits++) csh.bl_count[bits] = 0; + n = 0; + while (n <= 143) csh.static_ltree[n++].Len = 8, csh.bl_count[8]++; + while (n <= 255) csh.static_ltree[n++].Len = 9, csh.bl_count[9]++; + while (n <= 279) csh.static_ltree[n++].Len = 7, csh.bl_count[7]++; + while (n <= 287) csh.static_ltree[n++].Len = 8, csh.bl_count[8]++; + + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) */ + + GenCodes (csh.static_ltree, L_CODES+1); + + /* The static distance tree is trivial .............................*/ + for (n = 0; n < D_CODES; n++) + { + csh.static_dtree[n].Len = 5; + csh.static_dtree[n].Code = ReverseCode (n, 5); + } +} + + +void CsObjectInt::InitBlock (void) +/*--------------------------------------------------------------------*/ +/* Initialize a new block. */ +/*--------------------------------------------------------------------*/ +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. ...........................................*/ + for (n = 0; n < L_CODES; n++) csh.dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) csh.dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) csh.bl_tree[n].Freq = 0; + + csh.dyn_ltree[END_BLOCK].Freq = 1; + csh.opt_len = csh.static_len = 0L; + csh.last_lit = csh.last_dist = csh.last_flags = 0; + csh.flags = 0; + csh.flag_bit = 1; +} + + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =============================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. */ + +#define PQREMOVE(tree, top) \ +{ \ + top = csh.heap[SMALLEST]; \ + csh.heap[SMALLEST] = csh.heap[csh.heap_len--]; \ + pqdownheap(tree, SMALLEST); \ +} + +/* =============================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. + * This minimizes the worst case length. */ + +#define SMALLER(tree, n, m) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && csh.depth[n] <= csh.depth[m])) + +/* ================================================================ + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ + +void CsObjectInt::pqdownheap ( + CT_DATA *tree, /* the tree to restore .....*/ + int k) /* node to move down .......*/ +{ + int v = csh.heap[k]; + int j = k << 1; /* left son of k ..................................*/ + + while (j <= csh.heap_len) + { + /* Set j to the smallest of the two sons: ........................*/ + if (j < csh.heap_len && SMALLER(tree, csh.heap[j+1], csh.heap[j])) j++; + + /* Exit if v is smaller than both sons ...........................*/ + if (SMALLER(tree, v, csh.heap[j])) break; + + /* Exchange v with the smallest son ..............................*/ + csh.heap[k] = csh.heap[j], k = j; + + /* And continue down the tree, setting j to the left son of k ....*/ + j <<= 1; + } + csh.heap[k] = v; +} + +/* ================================================================= + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; + * static_len is also updated if stree is not null. + */ + +void CsObjectInt::GenBitLen (TREE_DESC *desc) /* the tree descriptor .......*/ +{ + CT_DATA *tree = desc->dyn_tree; + int *extra = desc->extra_bits; + int base = desc->extra_base; + int max_code = desc->max_code; + int max_length = desc->max_length; + CT_DATA *stree = desc->static_tree; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + unsigned short f; /* frequency */ + int overflow = 0; /* # of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) csh.bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case */ + + tree[csh.heap[csh.heap_max]].Len = 0; /* root of the heap */ + + for (h = csh.heap_max+1; h < HEAP_SIZE; h++) + { + n = csh.heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + + /* We overwrite tree[n].Dad which is no longer needed */ + tree[n].Len = (unsigned short) bits; + + if (n > max_code) continue; /* not a leaf node */ + + csh.bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + csh.opt_len += (SAP_UINT)f * (bits + xbits); + if (stree) csh.static_len += (SAP_UINT)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + /* Find the first bit length which could increase: */ + do + { + bits = max_length-1; + while (csh.bl_count[bits] == 0) bits--; + csh.bl_count[bits]--; /* move one leaf down the tree */ + csh.bl_count[bits+1] += 2; /* move one overflow item as its brother */ + csh.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] */ + + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. */ + + for (bits = max_length; bits != 0; bits--) + { + n = csh.bl_count[bits]; + while (n != 0) + { + m = csh.heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) + { + csh.opt_len += + ((SAP_INT)bits - (SAP_INT)tree[m].Len)*(SAP_INT)tree[m].Freq; + tree[m].Len = (unsigned short) bits; + } + n--; + } + } +} + +/* ================================================================ + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: + * the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +void CsObjectInt::GenCodes ( + CT_DATA *tree, /* the tree to decorate */ + int max_code) /* largest code with non zero frequency */ +{ + unsigned short next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned short code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. ...........................................*/ + + for (bits = 1; bits <= MAX_BITS; bits++) + { + next_code[bits] = code = (unsigned short)((code + csh.bl_count[bits-1]) << 1); + } + + for (n = 0; n <= max_code; n++) + { + int len = tree[n].Len; + if (len == 0) continue; + + /* Now reverse the bits ..........................................*/ + tree[n].Code = ReverseCode (next_code[len]++, len); + } +} + +/* ================================================================ + * Construct one Huffman tree and assigns the code bit strings and + lengths. Update the total bit length for the current block. + The field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ + +void CsObjectInt::BuildTree (TREE_DESC *desc) /* the tree descriptor */ +{ + CT_DATA *tree = desc->dyn_tree; + CT_DATA *stree = desc->static_tree; + int elems = desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node = elems; /* next internal node of the tree */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. ............................................*/ + + csh.heap_len = 0, csh.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) + { + if (tree[n].Freq != 0) + { + csh.heap[++(csh.heap_len)] = max_code = n; + csh.depth[n] = 0; + } + else + { + tree[n].Len = 0; + } + } + + /* lzh format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force + * at least two codes of non zero frequency. .......................*/ + + while (csh.heap_len < 2) + { + /* new is 0 or 1 so it does not have extra bits ..................*/ + int new1 = csh.heap[++(csh.heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[new1].Freq = 1; + csh.depth[new1] = 0; + csh.opt_len--; + if (stree) csh.static_len -= stree[new1].Len; + } + + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: ......................*/ + + for (n = csh.heap_len/2; n >= 1; n--) pqdownheap(tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. .................................................*/ + do + { + PQREMOVE(tree, n); /* n = node of least frequency .............*/ + m = csh.heap[SMALLEST]; /* m = node of next least frequency ........*/ + + csh.heap[--(csh.heap_max)] = n; /* keep the nodes sorted by frequency ......*/ + csh.heap[--(csh.heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + csh.depth[node] = (unsigned char) (MAX(csh.depth[n], csh.depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (unsigned short) node; + + /* and insert the new node in the heap ...........................*/ + csh.heap[SMALLEST] = node++; + pqdownheap(tree, SMALLEST); + + } while (csh.heap_len >= 2); + + csh.heap[--(csh.heap_max)] = csh.heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. .......................................*/ + + GenBitLen (desc); + + /* The field len is now set, we can generate the bit codes .........*/ + GenCodes (tree, max_code); +} + + +void CsObjectInt::ScanTree ( + CT_DATA *tree, /* the tree to be scanned .......*/ + int max_code) /* largest code of non zero freq */ +/*--------------------------------------------------------------------*/ +/* Scan a literal or distance tree to determine the frequencies of */ +/* the codes in the bit length tree. Updates opt_len to take into */ +/* account the repeat counts. (The contribution of the bit length */ +/* codes will be added later during the construction of bl_tree.) */ +/*--------------------------------------------------------------------*/ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (unsigned short)-1; /* guard */ + + for (n = 0; n <= max_code; n++) + { + curlen = nextlen; + nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) + { + continue; + } + else if (count < min_count) + { + csh.bl_tree[curlen].Freq += (unsigned short) count; + } + else if (curlen != 0) + { + if (curlen != prevlen) (csh.bl_tree[curlen].Freq)++; + (csh.bl_tree[REP_3_6].Freq)++; + } + else if (count <= 10) + { + (csh.bl_tree[REPZ_3_10].Freq)++; + } + else + { + (csh.bl_tree[REPZ_11_138].Freq)++; + } + + count = 0; + prevlen = curlen; + if (nextlen == 0) + { + max_count = 138, min_count = 3; + } + else if (curlen == nextlen) + { + max_count = 6, min_count = 3; + } + else + { + max_count = 7, min_count = 4; + } + } +} + + +void CsObjectInt::SendTree ( + CT_DATA *tree, /* the tree to be scanned */ + int max_code) /* largest code of freq != 0 */ +/*--------------------------------------------------------------------*/ +/* Send a literal or distance tree in compressed form, using the */ +/* codes in bl_tree. */ +/*--------------------------------------------------------------------*/ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) + { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) + { + continue; + } + else if (count < min_count) + { + do { + SEND_CODE (curlen, csh.bl_tree); + } while (--count != 0); + } + else if (curlen != 0) + { + if (curlen != prevlen) + { + SEND_CODE(curlen, csh.bl_tree); count--; + } + SEND_CODE (REP_3_6, csh.bl_tree); + SendBits (count-3, 2); + } + else if (count <= 10) + { + SEND_CODE (REPZ_3_10, csh.bl_tree); + SendBits (count-3, 3); + } + else + { + SEND_CODE (REPZ_11_138, csh.bl_tree); + SendBits (count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) + { + max_count = 138, min_count = 3; + } + else if (curlen == nextlen) + { + max_count = 6, min_count = 3; + } + else + { + max_count = 7, min_count = 4; + } + } +} + + +int CsObjectInt::BuildBlTree (void) +/*--------------------------------------------------------------------*/ +/* Construct the Huffman tree for the bit lengths and return the */ +/* index in bl_order of the last bit length code to send. */ +/*--------------------------------------------------------------------*/ +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal, distance trees */ + ScanTree (csh.dyn_ltree, csh.l_desc.max_code); + ScanTree (csh.dyn_dtree, csh.d_desc.max_code); + + /* Build the bit length tree: ......................................*/ + BuildTree (&(csh.bl_desc)); + + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for + * the counts. */ + + /* Determine the number of bit length codes to send. The lzh format + * requires that at least 4 bit length codes be sent. ..............*/ + + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) + { + if (csh.bl_tree[bl_order[max_blindex]].Len != 0) break; + } + + /* Update opt_len to include the bit length tree and counts ........*/ + csh.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + + return max_blindex; +} + + +void CsObjectInt::SendAllTrees (int lcodes, int dcodes, int blcodes) + /* number of codes for each tree ..........*/ +/*--------------------------------------------------------------------*/ +/* Send the header for a block using dynamic Huffman trees: */ +/* the counts, the lengths of the bit length codes, the literal */ +/* tree and the distance tree. */ +/* lcodes >= 257, dcodes >= 1, blcodes >= 4. */ +/*--------------------------------------------------------------------*/ +{ + int rank; /* index in bl_order */ + + SendBits (lcodes-257, 5); + SendBits (dcodes-1, 5); + SendBits (blcodes-4, 4); + + for (rank = 0; rank < blcodes; rank++) + { + SendBits (csh.bl_tree[bl_order[rank]].Len, 3); + } + + SendTree (csh.dyn_ltree, lcodes-1); /* send the literal tree */ + SendTree (csh.dyn_dtree, dcodes-1); /* send the distance tree */ +} + + +void CsObjectInt::FlushBlock (int eof) /* true for last block .....*/ +/*--------------------------------------------------------------------*/ +/* Determine the best encoding for the current block: */ +/* dynamic trees or static trees and output the encoded block to */ +/* the zip file. */ +/*--------------------------------------------------------------------*/ +{ + SAP_UINT opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex; /* index of last bit length code of non zero freq */ + + + csh.flag_buf[csh.last_flags] = csh.flags; /* Save the flags for the last 8 items*/ + + /* Construct the literal and distance trees ........................*/ + BuildTree (&(csh.l_desc)); + BuildTree (&(csh.d_desc)); + + /* Build the bit length tree for the above two trees, and get the + index in bl_order of the last bit length code to send. ..........*/ + + max_blindex = BuildBlTree (); + + /* Determine the best encoding. Compute first length in bytes ......*/ + opt_lenb = (csh.opt_len + 3 + 7) >> 3; + static_lenb = (csh.static_len + 3 + 7) >> 3; + + if (static_lenb <= opt_lenb) + { + SendBits ((STATIC_TREES<<1)+eof, 3); + CompressBlock (csh.static_ltree, csh.static_dtree); + } + else + { + SendBits ((DYN_TREES<<1)+eof, 3); + SendAllTrees (csh.l_desc.max_code+1, csh.d_desc.max_code+1, max_blindex+1); + CompressBlock (csh.dyn_ltree, csh.dyn_dtree); + } + + InitBlock (); + + if (eof) FlushIncomp (); +} + + +int CsObjectInt::ct_tally ( + int dist, /* distance of matched string */ + int lc) /* match length-MIN_MATCH or unmatched char (if dist==0) */ +/*--------------------------------------------------------------------*/ +/* Save the match info and tally the frequency counts. Return true if */ +/* the current block must be flushed. */ +/*--------------------------------------------------------------------*/ +{ + csh.CsLitLenBuf[(csh.last_lit)++] = (unsigned char)lc; + + if (dist == 0) + { + (csh.dyn_ltree[lc].Freq)++; /* lc is the unmatched char .*/ + } + else + { + /* Here, lc is the match length - MIN_MATCH ......................*/ + dist--; /* dist = match distance - 1 */ + + (csh.dyn_ltree[csh.length_code[lc]+LITERALS+1].Freq)++; + (csh.dyn_dtree[D_CODE(dist)].Freq)++; + + csh.CsDistBuf[(csh.last_dist)++] = (unsigned short) dist; + csh.flags |= csh.flag_bit; + } + + csh.flag_bit <<= 1; + + if ((csh.last_lit & 7) == 0) /* Output the flags if they fill a byte: */ + { + csh.flag_buf[csh.last_flags++] = csh.flags; + csh.flags = 0, csh.flag_bit = 1; + } + + /* Try to guess if it is profitable to stop the current block here .*/ + if (csh.pack_level > 2 && (csh.last_lit & 0xfff) == 0) + { + /* Compute an upper bound for the compressed length ..............*/ + SAP_UINT out_length = (SAP_UINT)csh.last_lit * 8L; + SAP_UINT in_length = (SAP_UINT)csh.StrStart - csh.BlockStart; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) + { + out_length += (SAP_UINT)csh.dyn_dtree[dcode].Freq * + (5L + CsExtraDistBits[dcode]); + } + out_length >>= 3; + + if (csh.last_dist < csh.last_lit/2 && out_length < in_length/2) return 1; + } + + /* We avoid equality with CS_LIT_BUFSIZE because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. */ + return (csh.last_lit == CS_LIT_BUFSIZE-1 || csh.last_dist == CS_DIST_BUFSIZE); +} + + +void CsObjectInt::CompressBlock ( + CT_DATA *ltree, /* literal tree ......*/ + CT_DATA *dtree ) /* distance tree .....*/ +/*--------------------------------------------------------------------*/ +/* Send the block data compressed using the given Huffman trees */ +/*--------------------------------------------------------------------*/ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist==0) */ + unsigned lx = 0; /* running index in CsLitLenBuf */ + unsigned dx = 0; /* running index in CsDistBuf */ + unsigned fx = 0; /* running index in flag_buf */ + unsigned short flag = 0; /* current flags */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (csh.last_lit != 0) + do + { + if ((lx & 7) == 0) flag = csh.flag_buf[fx++]; + lc = csh.CsLitLenBuf[lx++]; + if ((flag & 1) == 0) + { + SEND_CODE (lc, ltree); /* send a literal byte ......*/ + } + else + { + /* Here, lc is the match length - MIN_MATCH ....................*/ + code = csh.length_code[lc]; + SEND_CODE (code+LITERALS+1, ltree); /* send the length code ....*/ + extra = CsExtraLenBits[code]; + if (extra != 0) + { + lc -= csh.base_length[code]; + SendBits (lc, extra); /* send the extra length bits ....*/ + } + dist = csh.CsDistBuf[dx++]; + + code = D_CODE (dist); /* dist is the match distance - 1 */ + + SEND_CODE (code, dtree); /* send the distance code ........*/ + extra = CsExtraDistBits[code]; + + if (extra != 0) + { + dist -= csh.base_dist[code]; + SendBits (dist, extra); /* send the extra distance bits ..*/ + } + } /* literal or match pair ? */ + + flag >>= 1; + } while (lx < csh.last_lit); + + SEND_CODE (END_BLOCK, ltree); /* end of block ..................*/ +} + + +void CsObjectInt::BitBufInit (void) +/*--------------------------------------------------------------------*/ +/* Initialize the bit string routines. */ +/*--------------------------------------------------------------------*/ +{ + unsigned x, y; + + csh.bi_buf = 0; + csh.bi_valid = 0; + + x = rand () & ((1 << NONSENSE_LENBITS) - 1); + SendBits (x, NONSENSE_LENBITS); + + if (x) + { + y = rand () & ((1 << x) - 1); + SendBits (y, (int) x); + } +} + + +unsigned short CsObjectInt::ReverseCode (unsigned code, /* the value to invert */ + int len) /* its bit length .....*/ +/*--------------------------------------------------------------------*/ +/* Reverse the first len bits of a code, using straightforward code */ +/* (a faster method would use a table) 1 <= len <= 15 */ +/*--------------------------------------------------------------------*/ +{ + register unsigned res = 0; + do + { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return (unsigned short) (res >> 1); +} + + +void CsObjectInt::FlushIncomp (void) +/*--------------------------------------------------------------------*/ +/* Write out any remaining bits in an incomplete byte. */ +/*--------------------------------------------------------------------*/ +{ + if (csh.bi_valid > 8) + { + PUTSHORT(csh.bi_buf); + } + else if (csh.bi_valid > 0) + { + PUTBYTE(csh.bi_buf); + } + + csh.bi_buf = 0; + csh.bi_valid = 0; + + PUTBYTE(csh.bi_buf); /* add a 0x0 to make it easier for decompress ...*/ +} + + +int CsObjectInt::MemRead (unsigned char *buf, unsigned size) +/*--------------------------------------------------------------------*/ +/* Read a memory chunk into buf */ +/*--------------------------------------------------------------------*/ +{ + if (csh.sum_in + csh.in_offset >= csh.sum_size) + return -1; /* end of data ........................................*/ + + if (csh.in_offset < csh.in_size) + { + SAP_UINT block_size = csh.in_size - csh.in_offset; + if (block_size > (SAP_UINT) size) + block_size = (SAP_UINT) size; + + memcpy (buf, csh.in_buf + csh.in_offset, (unsigned) block_size); + csh.in_offset += block_size; + return (int) block_size; + } + else + { + return 0; /* end of input .......................................*/ + } +} + +void CsObjectInt::InitDesc (void) +{ + csh.l_desc.dyn_tree = csh.dyn_ltree; + csh.l_desc.static_tree = csh.static_ltree; + csh.l_desc.extra_bits = CsExtraLenBits; + csh.l_desc.extra_base = LITERALS+1; + csh.l_desc.elems = L_CODES; + csh.l_desc.max_length = MAX_BITS; + csh.l_desc.max_code = 0; + + csh.d_desc.dyn_tree = csh.dyn_dtree; + csh.d_desc.static_tree = csh.static_dtree; + csh.d_desc.extra_bits = CsExtraLenBits; + csh.d_desc.extra_base = 0; + csh.d_desc.elems = D_CODES; + csh.d_desc.max_length = MAX_BITS; + csh.d_desc.max_code = 0; + + csh.bl_desc.dyn_tree = csh.bl_tree; + csh.bl_desc.static_tree = NULL; + csh.bl_desc.extra_bits = extra_blbits; + csh.bl_desc.extra_base = 0; + csh.bl_desc.elems = BL_CODES; + csh.bl_desc.max_length = MAX_BL_BITS; + csh.bl_desc.max_code = 0; +} + + + + +int CsObjectInt::CsComprLZH (SAP_INT sumlen, + SAP_BYTE * inbuf, + SAP_INT inlen, + SAP_BYTE * outbuf, + SAP_INT outlen, + SAP_INT option, + SAP_INT * bytes_read, + SAP_INT * bytes_written) +{ + unsigned char Algo; + SAP_INT rc; + int level; + + if (option & CS_INIT_COMPRESS) + { + InitDesc (); + } + + csh.in_buf = inbuf; + csh.in_size = inlen; + csh.in_offset = 0; + + csh.out_buf = outbuf; + csh.out_size = outlen; + + if (option & CS_INIT_COMPRESS) + { + if (outlen < CS_HEAD_SIZE) + { + return CS_E_OUT_BUFFER_LEN; + } + + csh.sum_size = sumlen; + csh.sum_in = 0; + csh.out_offset = CS_HEAD_SIZE; + + csh.bytes_pending = 0; + + level = (int) (option >> 4); + if (level < 1 || level > 9) level = DEFAULT_LZH_LEVEL; + csh.pack_level = level; + + Algo = (unsigned char)((CS_LZH_VERSION << 4) | CS_ALGORITHM_LZH); + + rc = CsSetHead (outbuf, sumlen, Algo, (unsigned char) level); + if (rc < 0) + { + return (int) rc; + } + + BitBufInit (); + HufTabInit (); + LongestMatchInit (level, &csh.flags); + csh.init = 1; + + if (csh.out_offset == outlen) + { + return CS_END_OUTBUFFER; + } + } + else + { + csh.out_offset = 0; + if (csh.bytes_pending) + { + if (csh.bytes_pending < (unsigned) csh.out_size) + { + memcpy (csh.out_buf, csh.InterBuf, (unsigned) csh.bytes_pending); + csh.out_offset = (unsigned) csh.bytes_pending; + csh.bytes_pending = 0; + } + else + { + memcpy (csh.out_buf, csh.InterBuf, (unsigned) csh.out_size); + if (csh.bytes_pending > (unsigned) csh.out_size) + memmove (csh.InterBuf, csh.InterBuf + csh.out_size, + (unsigned)(csh.bytes_pending - csh.out_size)); + csh.bytes_pending -= (unsigned) csh.out_size; + *bytes_read = 0; + *bytes_written = csh.out_size; + + return CS_END_OUTBUFFER; + } + } + } + + rc = ComprLZH (csh.init); /* !!! Korrektur: ab 21.10.96 */ + csh.init = 0; + if (rc < 0) + { + return (int) rc; + } + + *bytes_read = csh.in_offset; + *bytes_written = rc; + csh.sum_in += csh.in_offset; + + if (csh.bytes_pending) return CS_END_OUTBUFFER; + else + if (csh.sum_in >= csh.sum_size) + { + return CS_END_OF_STREAM; + } + else + return CS_END_INBUFFER; +} + + diff --git a/vpa108csulzh.cpp b/vpa108csulzh.cpp new file mode 100644 index 0000000..fc55baf --- /dev/null +++ b/vpa108csulzh.cpp @@ -0,0 +1,1066 @@ +/* + + + + ========== licence begin GPL + Copyright (c) 2000-2005 SAP AG + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + ========== licence end + + + + + +*/ +#include +#include + +#include "hpa101saptype.h" +#include "hpa106cslzc.h" +#include "hpa107cslzh.h" + +#include "hpa104CsObject.h" +#include "hpa105CsObjInt.h" + + +/* Huffman code lookup table entry--this entry is four bytes for + machines that have 16-bit pointers (e.g. PC's in the small + or medium model). + + + Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16 + means that v is a literal, 16 < e < 32 means that v is a pointer to + the next table, which codes e - 16 bits, and lastly e == 99 indicates + an unused code. If a code with e == 99 is looked up, this implies + an error in the data. */ + +#define EOBCODE 15 +#define LITCODE 16 +#define INVALIDCODE 99 + + + +/* Tables for uncompress .............................................*/ + +extern int NEAR CsExtraLenBits[]; +static int *cplext = &CsExtraLenBits[0]; + + +extern int NEAR CsExtraDistBits[]; +static int * cpdext = &CsExtraDistBits[0]; + +static unsigned short mask_bits[] = +{ + 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +static unsigned border[] = +{ /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 +}; + +static int cplens[] = + { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + /* note: see note #13 above about the 258 in this list. */ + +static int cpdist[] = + { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed, and are initialized at the begining of a + routine that uses these macros from a global bit buffer and count. + + If we assume that EOB will be the longest code, then we will never + ask for bits with NEEDBITS that are beyond the end of the stream. + So, NEEDBITS should not read any more bytes than are needed to + meet the request. Then no bytes need to be "returned" to the buffer + at the end of the last block. + + However, this assumption is not true for fixed blocks--the EOB code + is 7 bits, but the other literal/length codes can be 8 or 9 bits. + (Why PK made the EOB code, which can only occur once in a block, + the *shortest* code in the set, I'll never know.) However, by + making the first table have a lookup of seven bits, the EOB code + will be found in that first lookup, and so will not require that too + many bits be pulled from the stream. + */ + + +#define DUMPBITS(n) { cshu.bb >>= (n); cshu.bk -= (n); } + +#define NEEDBITS(n) \ +{ \ + while (cshu.bk < (n)) \ + { \ + if (cshu.MemInoffset < cshu.MemInsize) \ + { \ + cshu.bytebuf = (unsigned short) cshu.MemInbuffer[(cshu.MemInoffset)++]; \ + bitcount = 8; \ + } \ + else bitcount = 0; \ + if (!bitcount) break; \ + cshu.bb |= (cshu.bytebuf) << cshu.bk; \ + cshu.bk += 8; \ + } \ +} + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the + requested table size, in which case the length of the shortest + code in bits is used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + +#define LBITS 9 +#define DBITS 6 + +/* If BMAX needs to be larger than 16, then h and x[] should be ULONG */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set .............*/ + + + + +int CsObjectInt::BuildHufTree ( + unsigned * b, /* code lengths in bits (all assumed <= BMAX) */ + unsigned n, /* number of codes (assumed <= N_MAX) */ + unsigned s, /* number of simple-valued codes (0..s-1) */ + int * d, /* list of base values for non-simple codes */ + int * e, /* list of extra bits for non-simple codes */ + HUFTREE **t, /* result: starting table */ + int * m) /* maximum lookup bits, returns actual */ + +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX+1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + REGISTER unsigned i; /* counter, current code */ + REGISTER unsigned j; /* counter */ + REGISTER int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + REGISTER unsigned *p; /* pointer into c[], b[], or v[] */ + REGISTER HUFTREE *q; /* points to current table */ + HUFTREE r = {0}; /* table entry for struct assignment */ + HUFTREE *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + REGISTER int w; /* bits before this table == (l * h) */ + unsigned x[BMAX+1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + /* Generate counts for each bit length .............................*/ + memset(c, 0, sizeof(c)); + p = b; i = n; + do + { + c[*p++]++; /* assume all entries <= BMAX .......*/ + } while (--i); + + + if (c[0] == n) /* bad input--all zero length codes .*/ + return CS_E_BAD_HUF_TREE; + + /* Find minimum and maximum length, bound *m by those ..............*/ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) break; + + k = j; /* minimum code length ...............*/ + if ((unsigned)l < j) l = j; + + for (i = BMAX; i; i--) + if (c[i]) break; + + g = i; /* maximum code length ...............*/ + if (( unsigned)l > i) l = i; + *m = l; + + /* Adjust last length count to fill out codes, if needed ...........*/ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return CS_E_BAD_HUF_TREE; /* bad input: more codes than bits ..*/ + + if ((y -= c[i]) < 0) return CS_E_BAD_HUF_TREE; + + c[i] += y; + + /* Generate starting offsets into the value table for each length ..*/ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) /* note that i == g from above ............*/ + { + *xp++ = (j += *p++); + } + + /* Make a table of values in order of bit lengths ..................*/ + p = b; i = 0; + do + { + if ((j = *p++) != 0) v[x[j]++] = i; + } while (++i < n); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (HUFTREE *)NULL; /* just to keep compilers happy */ + q = (HUFTREE *)NULL; /* dito */ + z = 0; /* dito */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned)l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table ............................*/ + q = AllocHufTree (z+1); + + if (q == (HUFTREE *) 0) + { + return CS_E_NO_STACKMEM; /* not enough memory ........*/ + } + + *t = q + 1; + *(t = &(q->v.t)) = (HUFTREE *)NULL; + u[h] = ++q; /* table starts after link ..*/ + + /* connect to last table, if there is one ................... */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (unsigned char)l; /* bits to dump before this .. */ + r.e = (unsigned char)(16 + j); /* bits in this table .......*/ + r.v.t = q; /* pointer to this table ....*/ + j = i >> (w - l); /* (get around Turbo C bug) .*/ + u[h-1][j] = r; /* connect to last table ....*/ + } + } + + /* set up table entry in r .....................................*/ + r.b = (unsigned char)(k - w); + if (p >= v + n) + { + r.e = INVALIDCODE; /* out of values--invalid code */ + } + else if (*p < s) + { /* 256 is end-of-block code */ + r.e = (unsigned char)(*p < 256 ? LITCODE : EOBCODE); + r.v.n = (unsigned short) *p; /* simple code is just the value*/ + p++; + } + else + { + r.e = (unsigned char) e[*p - s]; /*non-simple,look up in lists*/ + r.v.n = (unsigned short) d[*p - s]; + p++; + } + + /* fill code-like entries with r ...............................*/ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i ........................*/ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables .................................*/ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q ............*/ + w -= l; + } + } + } + + /* Return true (1) if we were given an incomplete table ............*/ + return y != 0 && n != 1; +} + + +HUFTREE * CsObjectInt::AllocHufTree (unsigned size) +{ + HUFTREE * p; + + p = cshu.InterBuf + cshu.AllocStackSize; + + cshu.AllocStackSize += size; // * sizeof(HUFTREE); + /* InterBuf is at least 0x1000 in size (5.9.96 ab) .................*/ + if (cshu.AllocStackSize >= DE_STACK_SIZE) return (HUFTREE *) 0; + + return p; +} + + +int CsObjectInt::FlushOut (unsigned w) /* number of bytes to flush */ +/*--------------------------------------------------------------------*/ +/* Do the equivalent of OUTB for the bytes Slide[0..w-1]. ............*/ +/*--------------------------------------------------------------------*/ +{ + unsigned n; + unsigned char *p; + + p = cshu.Slide + cshu.SlideOffset; + if (w) + { /* try to fill up buffer .....*/ + if (cshu.MemOutoffset + (int)w <= cshu.MemOutsize) + { + memcpy (cshu.OutPtr, p, w); + cshu.OutPtr += w; + cshu.BytesPending = 0; + cshu.MemOutoffset += w; + cshu.SumOut += w; + cshu.SlideOffset = 0; + } + else + { + n = (unsigned) (cshu.MemOutsize - cshu.MemOutoffset); + memcpy (cshu.OutPtr, p, n); + cshu.BytesPending = (int)w - (int)n; + cshu.MemOutoffset += n; + cshu.SumOut += n; + cshu.SlideOffset += n; + + return CS_END_OUTBUFFER; + } + } + return 0; +} + + + +int CsObjectInt::DecompCodes ( + int *state, /* state of last run ...............*/ + HUFTREE *tl, /* literal/length decoder tables */ + HUFTREE *td, /* distance decoder tables */ + int bl, /* number of bits decoded by tl[] */ + int bd) /* number of bits decoded by td[] */ + +/* inflate (decompress) the codes in a deflated (compressed) block. + Return an error code or zero if it all goes ok. ...................*/ +{ + REGISTER unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + unsigned ml, md; /* masks for bl and bd bits */ + REGISTER int bitcount; + int rc; + + /* make local copies of globals ....................................*/ + bitcount = 1; + w = cshu.wp; /* initialize window position */ + + /* precompute masks for speed ......................................*/ + ml = mask_bits[bl]; + md = mask_bits[bd]; + + switch (*state) /* depending on state in last run ...............*/ + { + case 2: + n = cshu.save_n; + d = cshu.save_d; + e = cshu.save_e; + *state = 0; + + goto STATE_2; + + case 20: + *state = 0; + break; + + case 21: + *state = 0; + e = cshu.save_e; + goto STATE_21; + + case 22: + *state = 0; + e = cshu.save_e; + goto STATE_22; + + case 23: + n = cshu.save_n; + e = cshu.save_e; + *state = 0; + goto STATE_23; + + case 24: + e = cshu.save_e; + n = cshu.save_n; + *state = 0; + goto STATE_24; + + case 25: + n = cshu.save_n; + e = cshu.save_e; + *state = 0; + goto STATE_25; + + default: break; + } + + *state = 0; + + for (;;) + { + NEEDBITS((unsigned)bl) + if (bitcount == 0) + { + *state = 20; + cshu.wp = w; + + return CS_END_INBUFFER; + } + + if ((e = (cshu.htp = tl + ((unsigned)cshu.bb & ml))->e) > LITCODE) + { + do + { + if (e == INVALIDCODE) return CS_E_INVALIDCODE; + + DUMPBITS(cshu.htp->b) + e -= LITCODE; + + STATE_21: + NEEDBITS(e) + if (bitcount == 0) + { + cshu.wp = w; + cshu.save_e = e; + *state = 21; + + return CS_END_INBUFFER; + } + } + while ((e = (cshu.htp = cshu.htp->v.t + ((unsigned)cshu.bb & mask_bits[e]))->e) > LITCODE); + } + + DUMPBITS(cshu.htp->b) + + if (e == LITCODE) /* then it's a literal ...............*/ + { + cshu.Slide[w++] = (unsigned char)cshu.htp->v.n; + if (w == WSIZE) + { + if ((rc = FlushOut (w)) != 0) + { + cshu.wp = 0; + + *state = 1; + return rc; + } + w = 0; + } + } + else /* it's an EOB or a length ...........*/ + { + /* exit if end of block ........................................*/ + if (e == EOBCODE) + { + break; + } + + /* get length of block to copy .................................*/ + STATE_22: + NEEDBITS(e) + if (bitcount == 0) + { + cshu.wp = w; + cshu.save_e = e; + *state = 22; + return CS_END_INBUFFER; + } + n = cshu.htp->v.n + ((unsigned)cshu.bb & mask_bits[e]); + DUMPBITS(e); + + /* decode distance of block to copy ............................*/ + STATE_23: + NEEDBITS((unsigned)bd) + if (bitcount == 0) + { + cshu.wp = w; + cshu.save_n = n; + cshu.save_e = e; + *state = 23; + return CS_END_INBUFFER; + } + + if ((e = (cshu.htp = td + ((unsigned)cshu.bb & md))->e) > LITCODE) + { + do + { + if (e == INVALIDCODE) return CS_E_INVALIDCODE; + + DUMPBITS(cshu.htp->b) + e -= LITCODE; + STATE_24: + NEEDBITS(e) + if (bitcount == 0) + { + cshu.wp = w; + cshu.save_e = e; + cshu.save_n = n; + *state = 24; + return CS_END_INBUFFER; + } + } + while ((e = (cshu.htp = cshu.htp->v.t + ((unsigned)cshu.bb & mask_bits[e]))->e) > LITCODE); + } + + DUMPBITS(cshu.htp->b) + + STATE_25: + NEEDBITS(e) + if (bitcount == 0) + { + cshu.wp = w; + + cshu.save_e = e; + cshu.save_n = n; + *state = 25; + return CS_END_INBUFFER; + } + + d = w - cshu.htp->v.n - ((unsigned)cshu.bb & mask_bits[e]); + DUMPBITS(e) + + /* do the copy .................................................*/ + do + { + n -= (e = (e = WSIZE - ((d &= WSIZE-1) > w ? d : w)) > n ? n : e); + + if (w - d >= e) /* (this test assumes unsigned comparison) */ + { + memcpy (cshu.Slide + w, cshu.Slide + d, e); + w += e; + d += e; + } + else /* do it slow to avoid memcpy() overlap ..*/ + { + do + { + cshu.Slide[w++] = cshu.Slide[d++]; + } while (--e); + } + + if (w == WSIZE) + { + if ((rc = FlushOut (w)) != 0) + { + cshu.wp = 0; + + cshu.save_n = n; + cshu.save_d = d; + cshu.save_e = e; + *state = 2; + return rc; + } + STATE_2: + w = 0; + } + } while (n); + } + } + + cshu.wp = w; /* restore global window pointer .....*/ + + return 0; +} + + +int CsObjectInt::DecompFixed (int *state) +/*--------------------------------------------------------------------*/ +/* Decompress an fixed Huffman codes block. */ +/*--------------------------------------------------------------------*/ +{ + int i, rc; /* temporary variable */ + unsigned l[288]; /* length list for BuildHufTree */ + + if (*state == 0) + { + /* set up literal table, make a complete, but wrong code set .....*/ + for (i = 0; i < 144; i++) l[i] = 8; + for (; i < 256; i++) l[i] = 9; + for (; i < 280; i++) l[i] = 7; + for (; i < 288; i++) l[i] = 8; + + cshu.blitlen = 7; + rc = BuildHufTree (l, 288, 257, cplens, cplext, &(cshu.tlitlen), &(cshu.blitlen)); + if (rc) + { + cshu.AllocStackSize = 0; + return rc; + } + + /* set up distance table .........................................*/ + for (i = 0; i < 30; i++) l[i] = 5; /* make an incomplete code set */ + + cshu.bdistlen = 5; + if ((rc = BuildHufTree (l, 30, 0, cpdist, cpdext, &(cshu.tdistcode), &(cshu.bdistlen))) < 0) + { + cshu.AllocStackSize = 0; + return rc; + } + } + + /* decompress until an end-of-block code ...........................*/ + if ((rc = DecompCodes (state, cshu.tlitlen, cshu.tdistcode, cshu.blitlen, cshu.bdistlen)) != 0) + return rc; + + /* free the decoding tables, return ................................*/ + cshu.AllocStackSize = 0; + + return 0; +} + + +int CsObjectInt::DecompDynamic (int *state) +/*--------------------------------------------------------------------*/ +/* Decompress an dynamic Huffman Code block. */ +/*--------------------------------------------------------------------*/ +{ + unsigned j; + + REGISTER int bitcount; + int rc; + + bitcount = 1; + + switch (*state) + { + case 0: + case 5: + NEEDBITS(5) + if (bitcount == 0) + { + *state = 5; + return CS_END_INBUFFER; + } + /* number of literal/length codes */ + cshu.dd_nl = 257 + ((unsigned)cshu.bb & 0x1f); + DUMPBITS(5) + + case 6: + NEEDBITS(5) + if (bitcount == 0) + { + *state = 6; + return CS_END_INBUFFER; + } + + cshu.dd_nd = 1 + ((unsigned)cshu.bb & 0x1f); /* number of distance codes ....*/ + DUMPBITS(5) + + case 7: + NEEDBITS(4) + if (bitcount == 0) + { + *state = 7; + return CS_END_INBUFFER; + } + + cshu.dd_nb = 4 + ((unsigned)cshu.bb & 0xf); /* number of bit length codes ..*/ + DUMPBITS(4) + + if (cshu.dd_nl > 286 || cshu.dd_nd > 30) + return CS_E_BADLENGTH; /* bad lengths .................*/ + + *state = 0; + break; + + case 8: + j = cshu.dd_jj; + *state = 0; + goto STATE_8; + + case 9: + *state = 0; + goto STATE_9; + + case 10: + *state = 0; + goto STATE_10; + + case 11: + *state = 0; + goto STATE_11; + + case 12: + *state = 0; + goto STATE_12; + + default: break; + } + + if (*state == 0) + { + cshu.dd_jj = 0; + for (j = cshu.dd_jj; j < cshu.dd_nb; j++) /* read in bit-length-code lengths ....*/ + { + STATE_8: + NEEDBITS(3) + if (bitcount == 0) + { + cshu.dd_jj = j; + *state = 8; + return CS_END_INBUFFER; + } + + cshu.dd_ll[border[j]] = (unsigned)cshu.bb & 7; + DUMPBITS(3) + } + + for (; j < 19; j++) cshu.dd_ll[border[j]] = 0; + + /* build decoding table for trees--single level, 7 bit lookup ....*/ + cshu.dd_bl = 7; + if ((rc = BuildHufTree (cshu.dd_ll, 19, 19, NULL, NULL, &(cshu.dd_tl), &(cshu.dd_bl))) != 0) + { + cshu.AllocStackSize = 0; + return rc; /* incomplete code set ............*/ + } + + cshu.dd_nolen = cshu.dd_nl + cshu.dd_nd; + cshu.dd_maskbit = mask_bits[cshu.dd_bl]; + cshu.dd_ii = cshu.dd_lastlen = 0; + /* read in literal and distance code lengths .....*/ + while ((unsigned)cshu.dd_ii < cshu.dd_nolen) + { + STATE_9: + NEEDBITS((unsigned)cshu.dd_bl) + if (bitcount == 0) + { + *state = 9; + return CS_END_INBUFFER; + } + + j = (cshu.dd_td = cshu.dd_tl + ((unsigned)cshu.bb & cshu.dd_maskbit))->b; + DUMPBITS(j) + j = cshu.dd_td->v.n; + if (j < 16) /* length of code in bits (0..15) ..*/ + cshu.dd_ll[cshu.dd_ii++] = cshu.dd_lastlen = j; /* save last length in l ...........*/ + else if (j == 16) /* repeat last length 3 to 6 times .*/ + { + STATE_10: + NEEDBITS(2) + if (bitcount == 0) + { + *state = 10; + return CS_END_INBUFFER; + } + j = 3 + ((unsigned)cshu.bb & 3); + DUMPBITS(2) + if ((unsigned)cshu.dd_ii + j > cshu.dd_nolen) return CS_E_INVALIDCODE; + while (j--) cshu.dd_ll[cshu.dd_ii++] = cshu.dd_lastlen; + } + else if (j == 17) /* 3 to 10 zero length codes .......*/ + { + STATE_11: + NEEDBITS(3) + if (bitcount == 0) + { + *state = 11; + return CS_END_INBUFFER; + } + + j = 3 + ((unsigned)cshu.bb & 7); + DUMPBITS(3) + if ((unsigned)cshu.dd_ii + j > cshu.dd_nolen) return CS_E_INVALIDCODE; + while (j--) cshu.dd_ll[cshu.dd_ii++] = 0; + cshu.dd_lastlen = 0; + } + else /* j == 18: 11 to 138 zero length codes */ + { + STATE_12: + NEEDBITS(7) + if (bitcount == 0) + { + *state = 12; + return CS_END_INBUFFER; + } + + j = 11 + ((unsigned)cshu.bb & 0x7f); + DUMPBITS(7) + if ((unsigned)cshu.dd_ii + j > cshu.dd_nolen) return CS_E_INVALIDCODE; + while (j--) cshu.dd_ll[cshu.dd_ii++] = 0; + cshu.dd_lastlen = 0; + } + } + + /* build the decoding tables for literal/length and distance codes*/ + cshu.dd_bl = LBITS; + if ((rc = BuildHufTree (cshu.dd_ll, cshu.dd_nl, 257, cplens, cplext, &(cshu.dd_tl), &(cshu.dd_bl))) !=0) + { + cshu.AllocStackSize = 0; + return rc; /* incomplete code set ............*/ + } + + cshu.dd_bd = DBITS; + rc = BuildHufTree (cshu.dd_ll + cshu.dd_nl, cshu.dd_nd, 0, cpdist, cpdext, &(cshu.dd_td), &(cshu.dd_bd)); + if (rc) + { + cshu.AllocStackSize = 0; + return rc; /* incomplete code set or no stack .............*/ + } + } + + /* decompress until an end-of-block code ...........................*/ + if ((rc = DecompCodes (state, cshu.dd_tl, cshu.dd_td, cshu.dd_bl, cshu.dd_bd)) != 0) + return rc; + + /* free the decoding tables, return ................................*/ + cshu.AllocStackSize = 0; + return 0; +} + + +int CsObjectInt::DecompBlock (int *state, int *e) /* state, last block flag */ +/*--------------------------------------------------------------------*/ +/* Decompress a block of codes */ +/*--------------------------------------------------------------------*/ +{ + REGISTER int bitcount; /* bitcount ...........................*/ + + bitcount = 1; + + switch (*state) + { + case 0: + case 3: + /* read in last block bit ............................*/ + NEEDBITS(1) + if (bitcount == 0) + { + *state = 3; + return CS_END_INBUFFER; + } + + *e = (int)cshu.bb & 1; + DUMPBITS(1) + + case 4: /* read in block type ................................*/ + NEEDBITS(2) + if (bitcount == 0) + { + *state = 4; + return CS_END_INBUFFER; + } + + cshu.blocktype = (unsigned)cshu.bb & 3; + DUMPBITS(2) + + *state = 0; + break; + + default: break; + } + + switch (cshu.blocktype) /* inflate that block type ............................*/ + { + case 2: return DecompDynamic (state); + case 1: return DecompFixed (state); + default: return CS_E_UNKNOWN_TYPE; + } +} + + +void CsObjectInt::NoBits (void) +/*--------------------------------------------------------------------*/ +/* */ +/*--------------------------------------------------------------------*/ +{ + unsigned x; /* number of bits in bit buffer ............*/ + int bitcount = 1; /* bitcount ................................*/ + + NEEDBITS(NONSENSE_LENBITS) + x = (unsigned) (cshu.bb & ((1 << NONSENSE_LENBITS) - 1)); + DUMPBITS(NONSENSE_LENBITS) + + if (x) + { + NEEDBITS(x) + DUMPBITS(x) + } +} + + +int CsObjectInt::CsDecomprLZH (SAP_BYTE * inp, /* ptr input .......*/ + SAP_INT inlen, /* len of input ....*/ + SAP_BYTE * outp, /* ptr output ......*/ + SAP_INT outlen, /* len output ......*/ + SAP_INT option, /* decompr. option */ + SAP_INT * bytes_read, /* bytes read ......*/ + SAP_INT * bytes_decompressed) /* bytes decompr. */ +/*--------------------------------------------------------------------*/ +/* Lempel-Ziv-Huffman */ +/*--------------------------------------------------------------------*/ +{ + int rc; + + cshu.MemOutbuffer = outp; + cshu.MemOutoffset = 0; + cshu.MemOutsize = (unsigned) outlen; + + cshu.OutPtr = outp; + + cshu.MemInbuffer = inp; + cshu.MemInoffset = 0; + cshu.MemInsize = (unsigned) inlen; + + if (inlen == 0 && outlen == 0) return CS_E_BOTH_ZERO; + + if (option & CS_INIT_DECOMPRESS) + { + cshu.BytesPending = 0; /* bytes to flush in next run ......*/ + cshu.SlideOffset = 0; /* offset in window ................*/ + cshu.AllocStackSize = 0; /* stack counter for trees .........*/ + cshu.staterun = 0; /* state of uncompress .............*/ + cshu.lastblockflag = 0; /* last block flag (1 = last block) */ + + if (inlen < CS_HEAD_SIZE) return CS_E_IN_BUFFER_LEN; + + cshu.OrgLen = CsGetLen (inp); + if (cshu.OrgLen < 0) + return CS_E_FILENOTCOMPRESSED; /* Input not compressed .......*/ + + cshu.SumOut = 0; + cshu.MemInoffset = CS_HEAD_SIZE; + + /* initialize window, bit buffer .................................*/ + cshu.wp = 0; + cshu.bk = 0; + cshu.bb = 0; + cshu.save_e = cshu.save_n = cshu.save_d = 0; + cshu.NonSenseflag = 0; + if (inlen == CS_HEAD_SIZE) return CS_END_INBUFFER; + } + + if (cshu.NonSenseflag == 0) + { + NoBits (); + cshu.NonSenseflag = 1; + } + + if (cshu.staterun == 1 || cshu.staterun == 2) /* end of outbuffer in last run ....*/ + { + rc = FlushOut (cshu.BytesPending); + if (rc || ((SAP_INT)cshu.SumOut >= cshu.OrgLen)) + { + *bytes_read = cshu.MemInoffset; + *bytes_decompressed = cshu.MemOutoffset; + + if (rc) return rc; + *bytes_read = inlen; + return CS_END_OF_STREAM; + } + } + + do /* decompress until the last block ....*/ + { + rc = DecompBlock (&(cshu.staterun), &(cshu.lastblockflag)); + if (rc) break; + } while (!(cshu.lastblockflag)); + + if ((rc == 0) && (cshu.staterun == 0) && (cshu.lastblockflag)) + { + rc = FlushOut (cshu.wp); /* flush out Slide ....................*/ + if (rc) cshu.staterun = 2; + } + /* set output params ..................*/ + *bytes_read = cshu.MemInoffset; + *bytes_decompressed = cshu.MemOutoffset; + + if (rc) return rc; + *bytes_read = inlen; + return CS_END_OF_STREAM; /* all done ...........................*/ +} + + diff --git a/wireshark.patch b/wireshark.patch new file mode 100644 index 0000000..92155d2 --- /dev/null +++ b/wireshark.patch @@ -0,0 +1,121 @@ +From 9265c779fbb44419f1c2781ebb6de0640472a8de Mon Sep 17 00:00:00 2001 +From: Martin Gallo +Date: Mon, 10 Mar 2014 10:54:56 -0300 +Subject: [PATCH] Configured sap plugin. + +--- + CMakeLists.txt | 1 + + Makefile.am | 1 + + configure.ac | 1 + + epan/Makefile.am | 7 +++++++ + packaging/nsis/Makefile.nmake | 1 + + packaging/nsis/wireshark.nsi | 1 + + plugins/Makefile.am | 1 + + plugins/Makefile.nmake | 1 + + 8 files changed, 14 insertions(+) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9e818df..a785121 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -463,6 +463,7 @@ if(ENABLE_PLUGINS) + plugins/mate + plugins/opcua + plugins/profinet ++ plugins/sap + plugins/stats_tree + plugins/unistim + plugins/wimax +diff --git a/Makefile.am b/Makefile.am +index f3e313c..2269594 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -299,6 +299,7 @@ plugin_ldadd = $(_CUSTOM_plugin_ldadd_) \ + -dlopen plugins/mate/mate.la \ + -dlopen plugins/opcua/opcua.la \ + -dlopen plugins/profinet/profinet.la \ ++ -dlopen plugins/sap/sap.la \ + -dlopen plugins/stats_tree/stats_tree.la \ + -dlopen plugins/unistim/unistim.la \ + -dlopen plugins/wimax/wimax.la \ +diff --git a/configure.ac b/configure.ac +index 59b68e5..076cac0 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2694,6 +2694,7 @@ AC_OUTPUT( + plugins/mate/Makefile + plugins/opcua/Makefile + plugins/profinet/Makefile ++ plugins/sap/Makefile + plugins/stats_tree/Makefile + plugins/unistim/Makefile + plugins/wimax/Makefile +diff --git a/epan/Makefile.am b/epan/Makefile.am +index 9eebe99..10f7bdb 100644 +--- a/epan/Makefile.am ++++ b/epan/Makefile.am +@@ -232,6 +232,13 @@ plugin_src = \ + ../plugins/m2m/wimax_tlv.c \ + ../plugins/mgcp/packet-mgcp.c \ + ../plugins/rdm/packet-rdm.c \ ++ ../plugins/sap/packet-sapdiag.c \ ++ ../plugins/sap/packet-sapenqueue.c \ ++ ../plugins/sap/packet-saprouter.c \ ++ ../plugins/sap/packet-sapprotocol.c \ ++ ../plugins/sap/packet-saprfc.c \ ++ ../plugins/sap/packet-sapms.c \ ++ ../plugins/sap/packet-sapsnc.c \ + ../plugins/sercosiii/packet-sercosiii.c \ + ../plugins/wimax/crc.c \ + ../plugins/wimax/crc_data.c \ +diff --git a/packaging/nsis/Makefile.nmake b/packaging/nsis/Makefile.nmake +index 2a301e6..3e3c9b3 100644 +--- a/packaging/nsis/Makefile.nmake ++++ b/packaging/nsis/Makefile.nmake +@@ -54,6 +54,7 @@ PLUGINS= \ + ../../plugins/mate/mate.dll \ + ../../plugins/opcua/opcua.dll \ + ../../plugins/profinet/profinet.dll \ ++ ../../plugins/sap/sap.dll \ + ../../plugins/stats_tree/stats_tree.dll \ + ../../plugins/unistim/unistim.dll \ + ../../plugins/wimax/wimax.dll \ +diff --git a/packaging/nsis/wireshark.nsi b/packaging/nsis/wireshark.nsi +index cc917b5..0e3d736 100644 +--- a/packaging/nsis/wireshark.nsi ++++ b/packaging/nsis/wireshark.nsi +@@ -850,6 +850,7 @@ File "${STAGING_DIR}\plugins\${VERSION}\irda.dll" + File "${STAGING_DIR}\plugins\${VERSION}\m2m.dll" + File "${STAGING_DIR}\plugins\${VERSION}\opcua.dll" + File "${STAGING_DIR}\plugins\${VERSION}\profinet.dll" ++File "${STAGING_DIR}\plugins\${VERSION}\sap.dll" + File "${STAGING_DIR}\plugins\${VERSION}\unistim.dll" + File "${STAGING_DIR}\plugins\${VERSION}\wimax.dll" + File "${STAGING_DIR}\plugins\${VERSION}\wimaxasncp.dll" +diff --git a/plugins/Makefile.am b/plugins/Makefile.am +index 9058bac..13d8c34 100644 +--- a/plugins/Makefile.am ++++ b/plugins/Makefile.am +@@ -33,6 +33,7 @@ SUBDIRS = $(_CUSTOM_SUBDIRS_) \ + mate \ + opcua \ + profinet \ ++ sap \ + stats_tree \ + unistim \ + wimax \ +diff --git a/plugins/Makefile.nmake b/plugins/Makefile.nmake +index 2415d92..e42a5a0 100644 +--- a/plugins/Makefile.nmake ++++ b/plugins/Makefile.nmake +@@ -16,6 +16,7 @@ PLUGIN_LIST = \ + mate \ + opcua \ + profinet \ ++ sap \ + stats_tree \ + unistim \ + wimax \ +-- +1.7.9.5 +