]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #720 in SNORT/snort3 from cut_down to master
authorRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 22 Nov 2016 22:54:41 +0000 (17:54 -0500)
committerRuss Combs (rucombs) <rucombs@cisco.com>
Tue, 22 Nov 2016 22:54:41 +0000 (17:54 -0500)
Squashed commit of the following:

commit f3bb19f43167cdda20698247fa21ba25f77b6dc5
Author: Russ Combs <rucombs@cisco.com>
Date:   Tue Nov 22 14:29:52 2016 -0500

    refactor dce_smb.cc

commit d61f30962fd70cfbb2ec66c0cbe017760f5a42a9
Author: Russ Combs <rucombs@cisco.com>
Date:   Tue Nov 22 12:54:31 2016 -0500

    refactor smb message definitions

commit 806617d70753418e348724443d0b655bc63d91b8
Author: Russ Combs <rucombs@cisco.com>
Date:   Tue Nov 22 11:50:24 2016 -0500

    split hi_client.cc init methods into separate file

12 files changed:
extra/src/inspectors/http_server/CMakeLists.txt
extra/src/inspectors/http_server/Makefile.am
extra/src/inspectors/http_server/hi_client.cc
extra/src/inspectors/http_server/hi_client.h
extra/src/inspectors/http_server/hi_client_init.cc [new file with mode: 0644]
src/service_inspectors/dce_rpc/CMakeLists.txt
src/service_inspectors/dce_rpc/Makefile.am
src/service_inspectors/dce_rpc/dce_smb.cc
src/service_inspectors/dce_rpc/dce_smb.h
src/service_inspectors/dce_rpc/smb_common.h [new file with mode: 0644]
src/service_inspectors/dce_rpc/smb_message.cc [new file with mode: 0644]
src/service_inspectors/dce_rpc/smb_message.h [new file with mode: 0644]

index e66e2b26e849adba5b1345ff35f2d83a89ac026d..ffa5a77316c7929805f2d8a106bc2e24aaabe360 100644 (file)
@@ -6,6 +6,7 @@ set (FILE_LIST
     hi_ad.cc
     hi_ad.h
     hi_client.cc
+    hi_client_init.cc
     hi_client.h
     hi_client_norm.cc
     hi_client_norm.h
index c4fbb75b936e7915a7f9345f110dd2a8e2f3260f..946a9d127f95caba12a4a9685201e63b7814ff49 100644 (file)
@@ -3,7 +3,7 @@ file_list = \
 http_inspect.cc \
 hi_main.cc hi_main.h \
 hi_ad.cc hi_ad.h \
-hi_client.cc hi_client.h \
+hi_client.cc hi_client_init.cc hi_client.h \
 hi_client_norm.cc hi_client_norm.h \
 hi_cmd_lookup.cc hi_cmd_lookup.h \
 hi_events.cc hi_events.h \
index b0eee62d82ef96af222c5332295f072bc6fd99e2..004f542298bfdac7d183308fe15634357dd85a3a 100644 (file)
@@ -96,17 +96,8 @@ const u_char* proxy_end = NULL;
     NULL
 };*/
 
-/**  This makes passing function arguments much more readable and easier
-**  to follow.
-*/
-typedef int (* LOOKUP_FCN)(HI_SESSION*, const u_char*, const u_char*, const u_char**,
-    URI_PTR*);
-
-/*
-**  The lookup table contains functions for different HTTP delimiters
-**  (like whitespace and the HTTP delimiter \r and \n).
-*/
 LOOKUP_FCN lookup_table[256];
+
 /*
 **  NAME
 **    CheckChunkEncoding::
@@ -512,265 +503,6 @@ static inline const u_char* FindPipelineReq(HI_SESSION* session,
     return NULL;
 }
 
-/*
-**  NAME
-**    NextNonWhiteSpace::
-*/
-/**
-**  Update the URI_PTR fields spaces, find the next non-white space char,
-**  and validate the HTTP version identifier after the spaces.
-**
-**  This is the main part of the URI algorithm.  This verifies that there
-**  isn't too many spaces in the data to be a URI, it checks that after the
-**  second space that there is an HTTP identifier or otherwise it's no good.
-**  Also, if we've found an identifier after the first whitespace, and
-**  find another whitespace, there is no URI.
-**
-**  The uri and uri_end pointers are updated in this function depending
-**  on what space we are at, and if the space was followed by the HTTP
-**  identifier.  (NOTE:  the HTTP delimiter is no longer "HTTP/", but
-**  can also be "\r\n", "\n", or "\r".  This is the defunct method, and
-**  we deal with it in the IsHttpVersion and delimiter functions.)
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS       found the next non-whitespace
-**  @retval HI_OUT_OF_BOUNDS whitespace to the end of the buffer
-**  @retval URI_END          delimiter found, end of URI
-**  @retval NO_URI
-*/
-static int NextNonWhiteSpace(HI_SESSION* session, const u_char* start,
-    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    HTTPINSPECT_CONF* ServerConf = session->server_conf;
-    const u_char** start_sp;
-    const u_char** end_sp;
-
-    /*
-    **  Horizontal tab is only accepted by apache web servers, not IIS.
-    **  Some IIS exploits contain a tab (0x09) in the URI, so we don't want
-    **  to treat it as a URI delimiter and cut off the URI.
-    */
-    if ( **ptr == '\t' && !ServerConf->tab_uri_delimiter )
-    {
-        (*ptr)++;
-        return HI_SUCCESS;
-    }
-
-    /*
-    **  Reset the identifier, because we've just seen another space.  We
-    **  should only see the identifier immediately after a space followed
-    **  by a delimiter.
-    */
-    if (uri_ptr->ident)
-    {
-        if (ServerConf->non_strict)
-        {
-            /*
-            **  In non-strict mode it is ok to see spaces after the
-            **  "identifier", so we just increment the ptr and return.
-            */
-            (*ptr)++;
-            return HI_SUCCESS;
-        }
-        else
-        {
-            /*
-            **  This means that we've already seen a space and a version
-            **  identifier, and now that we've seen another space, we know
-            **  that this can't be the URI so we just bail out with no
-            **  URI.
-            */
-            return NO_URI;
-        }
-    }
-
-    uri_ptr->ident = NULL;
-
-    /*
-    **  We only check for one here, because both should be set if one
-    **  is.
-    */
-    if (uri_ptr->first_sp_end)
-    {
-        /*
-        **  If the second space has been set, then this means that we have
-        **  seen a third space, which we shouldn't see in the URI so we
-        **  are now done and know there is no URI in this packet.
-        */
-        if (uri_ptr->second_sp_end)
-        {
-            return NO_URI;
-        }
-
-        /*
-        **  Treat whitespace differently at the end of the URI than we did
-        **  at the beginning.  Ignore and return if special characters are
-        **  not defined as whitespace after the URI.
-        */
-        if (ServerConf->whitespace[**ptr]
-            && !(ServerConf->whitespace[**ptr] & HI_UI_CONFIG_WS_AFTER_URI))
-        {
-            (*ptr)++;
-            return HI_SUCCESS;
-        }
-
-        /*
-        **  Since we've seen the second space, we need to update the uri ptr
-        **  to the end of the first space, since the URI cannot be before the
-        **  first space.
-        */
-        uri_ptr->uri = uri_ptr->first_sp_end;
-
-        uri_ptr->second_sp_start = *ptr;
-        uri_ptr->second_sp_end = NULL;
-
-        start_sp = &uri_ptr->second_sp_start;
-        end_sp = &uri_ptr->second_sp_end;
-    }
-    else
-    {
-        /*
-        **  This means that there is whitespace at the beginning of the line
-        **  and we unset the URI so we can set it later if need be.
-        **
-        **  This is mainly so we handle data that is all spaces correctly.
-        **
-        **  In the normal case where we've seen text and then the first space,
-        **  we leave the uri ptr pointing at the beginning of the data, and
-        **  set the uri end after we've determined where to put it.
-        */
-        if (start == *ptr)
-            uri_ptr->uri = NULL;
-
-        uri_ptr->first_sp_start = *ptr;
-        uri_ptr->first_sp_end = NULL;
-
-        start_sp = &uri_ptr->first_sp_start;
-        end_sp = &uri_ptr->first_sp_end;
-    }
-
-    while (hi_util_in_bounds(start, end, *ptr))
-    {
-        /*
-        **  Check for whitespace
-        */
-        if (**ptr == ' ')
-        {
-            (*ptr)++;
-            continue;
-        }
-        else if (ServerConf->whitespace[**ptr])
-        {
-            if (ServerConf->apache_whitespace.on)
-            {
-                hi_set_event(GID_HTTP_CLIENT, HI_CLIENT_APACHE_WS);
-            }
-            (*ptr)++;
-            continue;
-        }
-        else
-        {
-            /*
-            **  This sets the sp_end for whatever space delimiter we are on,
-            **  whether that is the first space or the second space.
-            */
-            *end_sp = *ptr;
-
-            if (!IsHttpVersion(ptr, end))
-            {
-                /*
-                **  This is the default method and what we've been doing
-                **  since the start of development.
-                */
-                if (uri_ptr->second_sp_start)
-                {
-                    /*
-                    **  There is no HTTP version indentifier at the beginning
-                    **  of the second space, and this means that there is no
-                    **  URI.
-                    */
-                    if (ServerConf->non_strict)
-                    {
-                        /*
-                        **  In non-strict mode, we must assume the URI is
-                        **  between the first and second space, so now
-                        **  that we've seen the second space that's the
-                        **  identifier.
-                        */
-                        uri_ptr->ident  = *end_sp;
-                        uri_ptr->uri_end = *start_sp;
-
-                        return HI_SUCCESS;
-                    }
-                    else
-                    {
-                        /*
-                        **  Since we are in strict mode here, it means that
-                        **  we haven't seen a valid identifier, so there was
-                        **  no URI.
-                        */
-
-                        return NO_URI;
-                    }
-                }
-
-                /*
-                **  RESET NECESSARY URI_PTRs HERE.  This is the place where
-                **  the uri is updated.  It can only happen once, so do it
-                **  right here.
-                **
-                **  When we get here it means that we have found the end of
-                **  the FIRST whitespace, and that there was no delimiter,
-                **  so we reset the uri pointers and other related
-                **  pointers.
-                */
-                uri_ptr->uri      = *end_sp;
-                uri_ptr->uri_end  = end;
-                uri_ptr->norm     = NULL;
-                uri_ptr->last_dir = NULL;
-                uri_ptr->param    = NULL;
-                uri_ptr->proxy    = NULL;
-            }
-            else
-            {
-                /*
-                **  Means we found the HTTP version identifier and we reset
-                **  the uri_end pointer to point to the beginning of the
-                **  whitespace detected.
-                **
-                **  This works for both "uri_is_here HTTP/1.0" and
-                **  "METHOD uri_is_here HTTP/1.0", so it works when the
-                **  identifier is after either the first or the second
-                **  whitespace.
-                */
-                uri_ptr->ident   = *end_sp;
-                uri_ptr->uri_end = *start_sp;
-            }
-
-            /*
-            **  We found a non-whitespace char
-            */
-            return HI_SUCCESS;
-        }
-    }
-
-    /*
-    **  This is the case where we've seen text and found a whitespace until
-    **  the end of the buffer.  In that case, we set the uri_end to the
-    **  beginning of the whitespace.
-    */
-    uri_ptr->uri_end = *start_sp;
-
-    return HI_OUT_OF_BOUNDS;
-}
-
 /*
 **  NAME
 **    IsHttpVersion::
@@ -858,495 +590,6 @@ int IsHttpVersion(const u_char** ptr, const u_char* end)
     return 1;
 }
 
-/*
-**  NAME
-**    find_rfc_delimiter::
-*/
-/**
-**  Check for standard RFC HTTP delimiter.
-**
-**  If we find the delimiter, we return that URI_PTR structures should
-**  be checked, which bails us out of the loop.  If there isn't a RFC
-**  delimiter, then we bail with a no URI.  Otherwise, we check for out
-**  of bounds.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_OUT_OF_BOUNDS
-**  @retval URI_END end of the URI is found, check URI_PTR.
-**  @retval NO_URI  malformed delimiter, no URI.
-*/
-static int find_rfc_delimiter(HI_SESSION* session, const u_char* start,
-    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    if (*ptr == start || !uri_ptr->uri)
-        return NO_URI;
-
-    /*
-    **  This is important to catch the defunct way of getting URIs without
-    **  specifying "HTTP/major.minor\r\n\r\n".  This is a quick way for
-    **  us to tell if we are in that state.
-    **
-    **  We check for a legal identifier to deal with the case of
-    **  "some_of_the_uri_in segmented packet \r\n" in the defunct case.
-    **  Since we find a "valid" (still defunct) delimiter, we account for
-    **  it here, so that we don't set the uri_end to the delimiter.
-    **
-    **  NOTE:
-    **  We now assume that the defunct method is in effect and if there is
-    **  a valid identifier, then we don't update the uri_end because it's
-    **  already been set when the identifier was validated.
-    */
-
-    (*ptr)++;
-    if (!hi_util_in_bounds(start, end, *ptr))
-    {
-        return HI_OUT_OF_BOUNDS;
-    }
-
-    if (**ptr == '\n')
-    {
-        uri_ptr->delimiter = (*ptr)-1;
-
-        if (!uri_ptr->ident)
-            uri_ptr->uri_end = uri_ptr->delimiter;
-
-        return URI_END;
-    }
-
-    return NextNonWhiteSpace(session, start, end, ptr, uri_ptr);
-}
-
-/*
-**  NAME
-**    find_non_rfc_delimiter::
-*/
-/**
-**  Check for non standard delimiter '\n'.
-**
-**  It now appears that apache and iis both take this non-standard
-**  delimiter.  So, we most likely will always look for it, but maybe
-**  give off a special alert or something.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval URI_END delimiter found, end of URI
-**  @retval NO_URI
-*/
-static int find_non_rfc_delimiter(
-    HI_SESSION* session, const u_char* start,
-    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    HTTPINSPECT_CONF* ServerConf = session->server_conf;
-
-    if (*ptr == start || !uri_ptr->uri)
-        return NO_URI;
-
-    /*
-    **  This is important to catch the defunct way of getting URIs without
-    **  specifying "HTTP/major.minor\r\n\r\n".  This is a quick way for
-    **  us to tell if we are in that state.
-    **
-    **  We check for a legal identifier to deal with the case of
-    **  "some_of_the_uri_in segmented packet \r\n" in the defunct case.
-    **  Since we find a "valid" (still defunct) delimiter, we account for
-    **  it here, so that we don't set the uri_end to the delimiter.
-    **
-    **  NOTE:
-    **  We now assume that the defunct method is in effect and if there is
-    **  a valid identifier, then we don't update the uri_end because it's
-    **  already been set when the identifier was validated.
-    */
-    if (ServerConf->iis_delimiter.on)
-    {
-        hi_set_event(GID_HTTP_CLIENT, HI_CLIENT_IIS_DELIMITER);
-
-        uri_ptr->delimiter = *ptr;
-
-        if (!uri_ptr->ident)
-            uri_ptr->uri_end = uri_ptr->delimiter;
-
-        return URI_END;
-    }
-
-    /*
-    **  This allows us to do something if the delimiter check is not turned
-    **  on.  Most likely this is worthy of an alert, IF it's not normal to
-    **  see these requests.
-    **
-    **  But for now, we always return true.
-    */
-    uri_ptr->delimiter = *ptr;
-
-    if (!uri_ptr->ident)
-        uri_ptr->uri_end = uri_ptr->delimiter;
-
-    return URI_END;
-}
-
-/*
-**  NAME
-**    SetPercentNorm::
-*/
-/**
-**  Check for percent normalization in the URI buffer.
-**
-**  We don't do much here besides check the configuration, set the pointer,
-**  and continue processing.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS function successful
-*/
-static int SetPercentNorm(
-    HI_SESSION* session, const u_char*,
-    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    HTTPINSPECT_CONF* ServerConf = session->server_conf;
-
-    if (!uri_ptr->norm && !uri_ptr->ident)
-    {
-        if (ServerConf->ascii.on)
-        {
-            uri_ptr->norm = *ptr;
-        }
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
-/*
-**  NAME
-**    CheckLongDir::
-*/
-/**
-**  We check the directory length against the global config.
-**
-**  @param session pointer to the current session
-**  @param uri_ptr pointer to the URI state
-**  @param ptr     pointer to the current index in buffer
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS
-*/
-static inline int CheckLongDir(HI_SESSION* session, URI_PTR* uri_ptr,
-    const u_char* ptr)
-{
-    int iDirLen;
-
-    /*
-    **  Check for oversize directory
-    */
-    if (session->server_conf->long_dir &&
-        uri_ptr->last_dir && !uri_ptr->param)
-    {
-        iDirLen = ptr - uri_ptr->last_dir;
-
-        if ( iDirLen > session->server_conf->long_dir )
-        {
-            hi_set_event(GID_HTTP_CLIENT, HI_CLIENT_OVERSIZE_DIR);
-        }
-    }
-
-    return HI_SUCCESS;
-}
-
-/*
-**  NAME
-**    SetSlashNorm::
-*/
-/**
-**  Check for any directory traversal or multi-slash normalization.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS       function successful
-**  @retval HI_OUT_OF_BOUNDS reached the end of the buffer
-*/
-static int SetSlashNorm(HI_SESSION* session, const u_char* start,
-    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    HTTPINSPECT_CONF* ServerConf = session->server_conf;
-
-    CheckLongDir(session, uri_ptr, *ptr);
-    if ( proxy_start)
-    {
-        // This is the first dir after http://
-        if (!uri_ptr->ident && !uri_ptr->last_dir)
-            proxy_end = *ptr;
-    }
-    uri_ptr->last_dir = *ptr;
-
-    if (!uri_ptr->norm && !uri_ptr->ident)
-    {
-        uri_ptr->norm = *ptr;
-
-        (*ptr)++;
-
-        if (!hi_util_in_bounds(start,end, *ptr))
-        {
-            /*
-            **  This is the case where there is a slash as the last char
-            **  and we don't want to normalize that since there really
-            **  is nothing to normalize.
-            */
-            uri_ptr->norm = NULL;
-            return HI_OUT_OF_BOUNDS;
-        }
-
-        /*
-        **  Check for directory traversals
-        */
-        if (ServerConf->directory.on)
-        {
-            if (**ptr == '.')
-            {
-                (*ptr)++;
-                if (!hi_util_in_bounds(start, end, *ptr))
-                {
-                    uri_ptr->norm = NULL;
-                    return HI_OUT_OF_BOUNDS;
-                }
-
-                if (**ptr == '.' || **ptr == '/')
-                {
-                    return HI_SUCCESS;
-                }
-            }
-        }
-
-        /*
-        **  Check for multiple slash normalization
-        */
-        if (ServerConf->multiple_slash.on)
-        {
-            if (**ptr == '/')
-            {
-                return HI_SUCCESS;
-            }
-        }
-
-        uri_ptr->norm = NULL;
-        return HI_SUCCESS;
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
-/*
-**  NAME
-**    SetBackSlashNorm::
-*/
-/**
-**  Check for backslashes and if we need to normalize.
-**
-**  This really just checks the configuration option, and sets the norm
-**  variable if applicable.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS       function successful
-*/
-static int SetBackSlashNorm(
-    HI_SESSION* session, const u_char*,
-    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    HTTPINSPECT_CONF* ServerConf = session->server_conf;
-
-    if (!uri_ptr->norm && !uri_ptr->ident)
-    {
-        if (ServerConf->iis_backslash.on)
-        {
-            uri_ptr->norm = *ptr;
-        }
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
-/*
- * **  NAME
- * **    SetPlusNorm::
- * */
-/**
- * **  Check for "+" and if we need to normalize.
- * **
- * **
- * **  @param ServerConf pointer to the server configuration
- * **  @param start      pointer to the start of payload
- * **  @param end        pointer to the end of the payload
- * **  @param ptr        pointer to the pointer of the current index
- * **  @param uri_ptr    pointer to the URI_PTR construct
- * **
- * **  @return integer
- * **
- * **  @retval HI_SUCCESS       function successful
- * */
-
-static int SetPlusNorm(
-    HI_SESSION*, const u_char*,
-    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    if (!uri_ptr->norm && !uri_ptr->ident)
-    {
-        uri_ptr->norm = *ptr;
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
-/*
-**  NAME
-**    SetBinaryNorm::
-*/
-/**
-**  Look for non-ASCII chars in the URI.
-**
-**  We look for these chars in the URI and set the normalization variable
-**  if it's not already set.  I think we really only need this for IIS
-**  servers, but we may want to know if it's in the URI too.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS       function successful
-*/
-static int SetBinaryNorm(
-    HI_SESSION*, const u_char*,
-    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    if (!uri_ptr->norm && !uri_ptr->ident)
-    {
-        uri_ptr->norm = *ptr;
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
-/*
-**  NAME
-**    SetParamField::
-*/
-/**
-**  This function sets the parameter field as the first '?'.  The big thing
-**  is that we set the param value, so we don't false positive long dir
-**  events when it's really just a long parameter field.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS       function successful
-*/
-static int SetParamField(
-    HI_SESSION*, const u_char*,
-    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    if (!uri_ptr->ident)
-    {
-        uri_ptr->param = *ptr;
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
-/*
-**  NAME
-**    SetProxy::
-*/
-/**
-**  This function checks for an absolute URI in the URI.
-**
-**  @param ServerConf pointer to the server configuration
-**  @param start      pointer to the start of payload
-**  @param end        pointer to the end of the payload
-**  @param ptr        pointer to the pointer of the current index
-**  @param uri_ptr    pointer to the URI_PTR construct
-**
-**  @return integer
-**
-**  @retval HI_SUCCESS       function successful
-*/
-static int SetProxy(HI_SESSION* session, const u_char* start,
-    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
-{
-    HTTPINSPECT_CONF* ServerConf = session->server_conf;
-
-    if (!uri_ptr->ident && !uri_ptr->last_dir)
-    {
-        if (hi_util_in_bounds(start, end, ((*ptr)+2)))
-        {
-            if (*((*ptr)+1) == '/' && *((*ptr)+2) == '/')
-            {
-                if (session->global_conf->proxy_alert && !ServerConf->allow_proxy)
-                    uri_ptr->proxy = *ptr;
-                // If we found :// check to see if it is preceeded by http. If so, this is a proxy
-                proxy_start = (u_char*)SnortStrcasestr((const char*)uri_ptr->uri, (*ptr -
-                    uri_ptr->uri), "http");
-                proxy_end = end;
-                (*ptr) = (*ptr) + 3;
-                return HI_SUCCESS;
-            }
-        }
-    }
-
-    (*ptr)++;
-
-    return HI_SUCCESS;
-}
-
 /*
 **  NAME
 **    SetClientVars::
@@ -3048,110 +2291,3 @@ int hi_client_inspection(Packet* p, void* S, HttpSessionData* hsd, int stream_in
     return StatelessInspection(p, session, hsd, stream_ins);
 }
 
-/*
-**  NAME
-**    hi_client_init::
-*/
-/**
-**  Initializes arrays and search algorithms depending on the type of
-**  inspection that we are doing.
-**
-**  @retval HI_SUCCESS function successful.
-*/
-int hi_client_init()
-{
-    int iCtr;
-
-    memset(lookup_table, 0x00, sizeof(lookup_table));
-
-    // Set up the non-ASCII register for processing.
-    for (iCtr = 0x80; iCtr <= 0xff; iCtr++)
-    {
-        lookup_table[iCtr] = SetBinaryNorm;
-    }
-    lookup_table[0x00] = SetBinaryNorm;
-
-    lookup_table[(uint8_t)' ']  = NextNonWhiteSpace;
-    lookup_table[(uint8_t)'\r'] = find_rfc_delimiter;
-    lookup_table[(uint8_t)'\n'] = find_non_rfc_delimiter;
-
-    // ASCII encoding
-    lookup_table[(uint8_t)'%']  = SetPercentNorm;
-
-    // Looking for multiple slashes
-    lookup_table[(uint8_t)'/']  = SetSlashNorm;
-
-    // Looking for backslashs
-    lookup_table[(uint8_t)'\\'] = SetBackSlashNorm;
-
-    lookup_table[(uint8_t)'+'] = SetPlusNorm;
-
-    //  Look up parameter field, so we don't alert on long directory
-    //  strings, when the next slash in the parameter field.
-    lookup_table[(uint8_t)'?'] = SetParamField;
-
-    //  Look for absolute URI and proxy communication.
-    lookup_table[(uint8_t)':'] = SetProxy;
-
-    return HI_SUCCESS;
-}
-
-/**
-**  This was just an initial testing program for these functions.
-*/
-#ifdef TEST_ME
-
-int main(int argc, char** argv)
-{
-    HTTPINSPECT_GLOBAL_CONF GlobalConf;
-    HI_SESSION* session;
-    HI_SI_INPUT SiInput;
-    int iInspectMode = 0;
-    int iRet;
-    char data[] = "Hdslkfjaslfkj    HTTP/00000.111111";
-
-    if ((iRet = hi_ui_config_init_global_conf(&GlobalConf)))
-    {
-        printf("** error during global init.\n");
-        return iRet;
-    }
-
-    if ((iRet = hi_ui_config_default(&GlobalConf)))
-    {
-        printf("** error config default.\n");
-        return iRet;
-    }
-
-    hi_ui_config_print_config(&GlobalConf);
-
-    if ((iRet = hi_client_init()))
-    {
-        printf("** error client init\n");
-        return iRet;
-    }
-
-    SiInput.sip = inet_addr("1.1.1.1");
-    SiInput.sip = inet_addr("1.1.1.2");
-    SiInput.dport = 80;
-    SiInput.sport = 7880;
-
-    if ((iRet = hi_si_session_inspection(&GlobalConf, &session, &SiInput,
-            &iInspectMode)))
-    {
-        printf("** error session inspection\n");
-        return iRet;
-    }
-
-    printf("** iInspectMode = %d\n", iInspectMode);
-    if ((iRet = hi_mi_mode_inspection(session, iInspectMode, data,
-            strlen(data))))
-    {
-        printf("** error mode_inspection\n");
-        return iRet;
-    }
-
-    return 0;
-}
-
-#endif
-
index 7b200b9cb04e93cbc0a4822649e8081493591a84..0e685b9015fefe02f6828a753dfebcfb3f40b6ed 100644 (file)
@@ -171,5 +171,23 @@ char** hi_client_get_field_names();
 extern const u_char* proxy_start;
 extern const u_char* proxy_end;
 
+struct HI_SESSION;
+
+int CheckLongDir(HI_SESSION* session, URI_PTR* uri_ptr, const u_char* ptr);
+
+/**  This makes passing function arguments much more readable and easier
+**  to follow.
+*/
+typedef int (* LOOKUP_FCN)(
+    HI_SESSION*, const u_char* start, const u_char* end, const u_char**, URI_PTR*);
+
+int NextNonWhiteSpace(HI_SESSION*, const u_char*, const u_char*, const u_char**, URI_PTR*);
+
+/*
+**  The lookup table contains functions for different HTTP delimiters
+**  (like whitespace and the HTTP delimiter \r and \n).
+*/
+extern LOOKUP_FCN lookup_table[256];
+
 #endif
 
diff --git a/extra/src/inspectors/http_server/hi_client_init.cc b/extra/src/inspectors/http_server/hi_client_init.cc
new file mode 100644 (file)
index 0000000..53398ed
--- /dev/null
@@ -0,0 +1,832 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2016 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2003-2013 Sourcefire, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// hi_client_init.cc author Russ Combs <rucombs@cisco.com>
+// 
+// this file was split from hi_client.cc; look there for the real
+// culprits ;)
+
+#include "hi_client.h"
+#include "hi_return_codes.h"
+#include "hi_si.h"
+#include "hi_util.h"
+
+//-------------------------------------------------------------------------
+// private methods
+//-------------------------------------------------------------------------
+
+/*
+**  NAME
+**    SetBinaryNorm::
+*/
+/**
+**  Look for non-ASCII chars in the URI.
+**
+**  We look for these chars in the URI and set the normalization variable
+**  if it's not already set.  I think we really only need this for IIS
+**  servers, but we may want to know if it's in the URI too.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS       function successful
+*/
+static int SetBinaryNorm(
+    HI_SESSION*, const u_char*,
+    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    if (!uri_ptr->norm && !uri_ptr->ident)
+    {
+        uri_ptr->norm = *ptr;
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+/*
+**  NAME
+**    find_rfc_delimiter::
+*/
+/**
+**  Check for standard RFC HTTP delimiter.
+**
+**  If we find the delimiter, we return that URI_PTR structures should
+**  be checked, which bails us out of the loop.  If there isn't a RFC
+**  delimiter, then we bail with a no URI.  Otherwise, we check for out
+**  of bounds.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_OUT_OF_BOUNDS
+**  @retval URI_END end of the URI is found, check URI_PTR.
+**  @retval NO_URI  malformed delimiter, no URI.
+*/
+static int find_rfc_delimiter(HI_SESSION* session, const u_char* start,
+    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    if (*ptr == start || !uri_ptr->uri)
+        return NO_URI;
+
+    /*
+    **  This is important to catch the defunct way of getting URIs without
+    **  specifying "HTTP/major.minor\r\n\r\n".  This is a quick way for
+    **  us to tell if we are in that state.
+    **
+    **  We check for a legal identifier to deal with the case of
+    **  "some_of_the_uri_in segmented packet \r\n" in the defunct case.
+    **  Since we find a "valid" (still defunct) delimiter, we account for
+    **  it here, so that we don't set the uri_end to the delimiter.
+    **
+    **  NOTE:
+    **  We now assume that the defunct method is in effect and if there is
+    **  a valid identifier, then we don't update the uri_end because it's
+    **  already been set when the identifier was validated.
+    */
+
+    (*ptr)++;
+    if (!hi_util_in_bounds(start, end, *ptr))
+    {
+        return HI_OUT_OF_BOUNDS;
+    }
+
+    if (**ptr == '\n')
+    {
+        uri_ptr->delimiter = (*ptr)-1;
+
+        if (!uri_ptr->ident)
+            uri_ptr->uri_end = uri_ptr->delimiter;
+
+        return URI_END;
+    }
+
+    return NextNonWhiteSpace(session, start, end, ptr, uri_ptr);
+}
+
+/*
+**  NAME
+**    find_non_rfc_delimiter::
+*/
+/**
+**  Check for non standard delimiter '\n'.
+**
+**  It now appears that apache and iis both take this non-standard
+**  delimiter.  So, we most likely will always look for it, but maybe
+**  give off a special alert or something.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval URI_END delimiter found, end of URI
+**  @retval NO_URI
+*/
+static int find_non_rfc_delimiter(
+    HI_SESSION* session, const u_char* start,
+    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    HTTPINSPECT_CONF* ServerConf = session->server_conf;
+
+    if (*ptr == start || !uri_ptr->uri)
+        return NO_URI;
+
+    /*
+    **  This is important to catch the defunct way of getting URIs without
+    **  specifying "HTTP/major.minor\r\n\r\n".  This is a quick way for
+    **  us to tell if we are in that state.
+    **
+    **  We check for a legal identifier to deal with the case of
+    **  "some_of_the_uri_in segmented packet \r\n" in the defunct case.
+    **  Since we find a "valid" (still defunct) delimiter, we account for
+    **  it here, so that we don't set the uri_end to the delimiter.
+    **
+    **  NOTE:
+    **  We now assume that the defunct method is in effect and if there is
+    **  a valid identifier, then we don't update the uri_end because it's
+    **  already been set when the identifier was validated.
+    */
+    if (ServerConf->iis_delimiter.on)
+    {
+        hi_set_event(GID_HTTP_CLIENT, HI_CLIENT_IIS_DELIMITER);
+
+        uri_ptr->delimiter = *ptr;
+
+        if (!uri_ptr->ident)
+            uri_ptr->uri_end = uri_ptr->delimiter;
+
+        return URI_END;
+    }
+
+    /*
+    **  This allows us to do something if the delimiter check is not turned
+    **  on.  Most likely this is worthy of an alert, IF it's not normal to
+    **  see these requests.
+    **
+    **  But for now, we always return true.
+    */
+    uri_ptr->delimiter = *ptr;
+
+    if (!uri_ptr->ident)
+        uri_ptr->uri_end = uri_ptr->delimiter;
+
+    return URI_END;
+}
+
+/*
+**  NAME
+**    SetPercentNorm::
+*/
+/**
+**  Check for percent normalization in the URI buffer.
+**
+**  We don't do much here besides check the configuration, set the pointer,
+**  and continue processing.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS function successful
+*/
+static int SetPercentNorm(
+    HI_SESSION* session, const u_char*,
+    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    HTTPINSPECT_CONF* ServerConf = session->server_conf;
+
+    if (!uri_ptr->norm && !uri_ptr->ident)
+    {
+        if (ServerConf->ascii.on)
+        {
+            uri_ptr->norm = *ptr;
+        }
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+/*
+**  NAME
+**    SetSlashNorm::
+*/
+/**
+**  Check for any directory traversal or multi-slash normalization.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS       function successful
+**  @retval HI_OUT_OF_BOUNDS reached the end of the buffer
+*/
+static int SetSlashNorm(HI_SESSION* session, const u_char* start,
+    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    HTTPINSPECT_CONF* ServerConf = session->server_conf;
+
+    CheckLongDir(session, uri_ptr, *ptr);
+    if ( proxy_start)
+    {
+        // This is the first dir after http://
+        if (!uri_ptr->ident && !uri_ptr->last_dir)
+            proxy_end = *ptr;
+    }
+    uri_ptr->last_dir = *ptr;
+
+    if (!uri_ptr->norm && !uri_ptr->ident)
+    {
+        uri_ptr->norm = *ptr;
+
+        (*ptr)++;
+
+        if (!hi_util_in_bounds(start,end, *ptr))
+        {
+            /*
+            **  This is the case where there is a slash as the last char
+            **  and we don't want to normalize that since there really
+            **  is nothing to normalize.
+            */
+            uri_ptr->norm = NULL;
+            return HI_OUT_OF_BOUNDS;
+        }
+
+        /*
+        **  Check for directory traversals
+        */
+        if (ServerConf->directory.on)
+        {
+            if (**ptr == '.')
+            {
+                (*ptr)++;
+                if (!hi_util_in_bounds(start, end, *ptr))
+                {
+                    uri_ptr->norm = NULL;
+                    return HI_OUT_OF_BOUNDS;
+                }
+
+                if (**ptr == '.' || **ptr == '/')
+                {
+                    return HI_SUCCESS;
+                }
+            }
+        }
+
+        /*
+        **  Check for multiple slash normalization
+        */
+        if (ServerConf->multiple_slash.on)
+        {
+            if (**ptr == '/')
+            {
+                return HI_SUCCESS;
+            }
+        }
+
+        uri_ptr->norm = NULL;
+        return HI_SUCCESS;
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+/*
+**  NAME
+**    SetBackSlashNorm::
+*/
+/**
+**  Check for backslashes and if we need to normalize.
+**
+**  This really just checks the configuration option, and sets the norm
+**  variable if applicable.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS       function successful
+*/
+static int SetBackSlashNorm(
+    HI_SESSION* session, const u_char*,
+    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    HTTPINSPECT_CONF* ServerConf = session->server_conf;
+
+    if (!uri_ptr->norm && !uri_ptr->ident)
+    {
+        if (ServerConf->iis_backslash.on)
+        {
+            uri_ptr->norm = *ptr;
+        }
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+/*
+ * **  NAME
+ * **    SetPlusNorm::
+ * */
+/**
+ * **  Check for "+" and if we need to normalize.
+ * **
+ * **
+ * **  @param ServerConf pointer to the server configuration
+ * **  @param start      pointer to the start of payload
+ * **  @param end        pointer to the end of the payload
+ * **  @param ptr        pointer to the pointer of the current index
+ * **  @param uri_ptr    pointer to the URI_PTR construct
+ * **
+ * **  @return integer
+ * **
+ * **  @retval HI_SUCCESS       function successful
+ * */
+
+static int SetPlusNorm(
+    HI_SESSION*, const u_char*,
+    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    if (!uri_ptr->norm && !uri_ptr->ident)
+    {
+        uri_ptr->norm = *ptr;
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+/*
+**  NAME
+**    SetParamField::
+*/
+/**
+**  This function sets the parameter field as the first '?'.  The big thing
+**  is that we set the param value, so we don't false positive long dir
+**  events when it's really just a long parameter field.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS       function successful
+*/
+static int SetParamField(
+    HI_SESSION*, const u_char*,
+    const u_char*, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    if (!uri_ptr->ident)
+    {
+        uri_ptr->param = *ptr;
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+/*
+**  NAME
+**    SetProxy::
+*/
+/**
+**  This function checks for an absolute URI in the URI.
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS       function successful
+*/
+static int SetProxy(HI_SESSION* session, const u_char* start,
+    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    HTTPINSPECT_CONF* ServerConf = session->server_conf;
+
+    if (!uri_ptr->ident && !uri_ptr->last_dir)
+    {
+        if (hi_util_in_bounds(start, end, ((*ptr)+2)))
+        {
+            if (*((*ptr)+1) == '/' && *((*ptr)+2) == '/')
+            {
+                if (session->global_conf->proxy_alert && !ServerConf->allow_proxy)
+                    uri_ptr->proxy = *ptr;
+                // If we found :// check to see if it is preceeded by http. If so, this is a proxy
+                proxy_start = (u_char*)SnortStrcasestr((const char*)uri_ptr->uri, (*ptr -
+                    uri_ptr->uri), "http");
+                proxy_end = end;
+                (*ptr) = (*ptr) + 3;
+                return HI_SUCCESS;
+            }
+        }
+    }
+
+    (*ptr)++;
+
+    return HI_SUCCESS;
+}
+
+//-------------------------------------------------------------------------
+// public methods
+//-------------------------------------------------------------------------
+
+/*
+**  NAME
+**    hi_client_init::
+*/
+/**
+**  Initializes arrays and search algorithms depending on the type of
+**  inspection that we are doing.
+**
+**  @retval HI_SUCCESS function successful.
+*/
+int hi_client_init()
+{
+    int iCtr;
+
+    memset(lookup_table, 0x00, sizeof(lookup_table));
+
+    // Set up the non-ASCII register for processing.
+    for (iCtr = 0x80; iCtr <= 0xff; iCtr++)
+    {
+        lookup_table[iCtr] = SetBinaryNorm;
+    }
+    lookup_table[0x00] = SetBinaryNorm;
+
+    lookup_table[(uint8_t)' ']  = NextNonWhiteSpace;
+    lookup_table[(uint8_t)'\r'] = find_rfc_delimiter;
+    lookup_table[(uint8_t)'\n'] = find_non_rfc_delimiter;
+
+    // ASCII encoding
+    lookup_table[(uint8_t)'%']  = SetPercentNorm;
+
+    // Looking for multiple slashes
+    lookup_table[(uint8_t)'/']  = SetSlashNorm;
+
+    // Looking for backslashs
+    lookup_table[(uint8_t)'\\'] = SetBackSlashNorm;
+
+    lookup_table[(uint8_t)'+'] = SetPlusNorm;
+
+    //  Look up parameter field, so we don't alert on long directory
+    //  strings, when the next slash in the parameter field.
+    lookup_table[(uint8_t)'?'] = SetParamField;
+
+    //  Look for absolute URI and proxy communication.
+    lookup_table[(uint8_t)':'] = SetProxy;
+
+    return HI_SUCCESS;
+}
+
+/*
+**  NAME
+**    NextNonWhiteSpace::
+*/
+/**
+**  Update the URI_PTR fields spaces, find the next non-white space char,
+**  and validate the HTTP version identifier after the spaces.
+**
+**  This is the main part of the URI algorithm.  This verifies that there
+**  isn't too many spaces in the data to be a URI, it checks that after the
+**  second space that there is an HTTP identifier or otherwise it's no good.
+**  Also, if we've found an identifier after the first whitespace, and
+**  find another whitespace, there is no URI.
+**
+**  The uri and uri_end pointers are updated in this function depending
+**  on what space we are at, and if the space was followed by the HTTP
+**  identifier.  (NOTE:  the HTTP delimiter is no longer "HTTP/", but
+**  can also be "\r\n", "\n", or "\r".  This is the defunct method, and
+**  we deal with it in the IsHttpVersion and delimiter functions.)
+**
+**  @param ServerConf pointer to the server configuration
+**  @param start      pointer to the start of payload
+**  @param end        pointer to the end of the payload
+**  @param ptr        pointer to the pointer of the current index
+**  @param uri_ptr    pointer to the URI_PTR construct
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS       found the next non-whitespace
+**  @retval HI_OUT_OF_BOUNDS whitespace to the end of the buffer
+**  @retval URI_END          delimiter found, end of URI
+**  @retval NO_URI
+*/
+int NextNonWhiteSpace(HI_SESSION* session, const u_char* start,
+    const u_char* end, const u_char** ptr, URI_PTR* uri_ptr)
+{
+    HTTPINSPECT_CONF* ServerConf = session->server_conf;
+    const u_char** start_sp;
+    const u_char** end_sp;
+
+    /*
+    **  Horizontal tab is only accepted by apache web servers, not IIS.
+    **  Some IIS exploits contain a tab (0x09) in the URI, so we don't want
+    **  to treat it as a URI delimiter and cut off the URI.
+    */
+    if ( **ptr == '\t' && !ServerConf->tab_uri_delimiter )
+    {
+        (*ptr)++;
+        return HI_SUCCESS;
+    }
+
+    /*
+    **  Reset the identifier, because we've just seen another space.  We
+    **  should only see the identifier immediately after a space followed
+    **  by a delimiter.
+    */
+    if (uri_ptr->ident)
+    {
+        if (ServerConf->non_strict)
+        {
+            /*
+            **  In non-strict mode it is ok to see spaces after the
+            **  "identifier", so we just increment the ptr and return.
+            */
+            (*ptr)++;
+            return HI_SUCCESS;
+        }
+        else
+        {
+            /*
+            **  This means that we've already seen a space and a version
+            **  identifier, and now that we've seen another space, we know
+            **  that this can't be the URI so we just bail out with no
+            **  URI.
+            */
+            return NO_URI;
+        }
+    }
+
+    uri_ptr->ident = NULL;
+
+    /*
+    **  We only check for one here, because both should be set if one
+    **  is.
+    */
+    if (uri_ptr->first_sp_end)
+    {
+        /*
+        **  If the second space has been set, then this means that we have
+        **  seen a third space, which we shouldn't see in the URI so we
+        **  are now done and know there is no URI in this packet.
+        */
+        if (uri_ptr->second_sp_end)
+        {
+            return NO_URI;
+        }
+
+        /*
+        **  Treat whitespace differently at the end of the URI than we did
+        **  at the beginning.  Ignore and return if special characters are
+        **  not defined as whitespace after the URI.
+        */
+        if (ServerConf->whitespace[**ptr]
+            && !(ServerConf->whitespace[**ptr] & HI_UI_CONFIG_WS_AFTER_URI))
+        {
+            (*ptr)++;
+            return HI_SUCCESS;
+        }
+
+        /*
+        **  Since we've seen the second space, we need to update the uri ptr
+        **  to the end of the first space, since the URI cannot be before the
+        **  first space.
+        */
+        uri_ptr->uri = uri_ptr->first_sp_end;
+
+        uri_ptr->second_sp_start = *ptr;
+        uri_ptr->second_sp_end = NULL;
+
+        start_sp = &uri_ptr->second_sp_start;
+        end_sp = &uri_ptr->second_sp_end;
+    }
+    else
+    {
+        /*
+        **  This means that there is whitespace at the beginning of the line
+        **  and we unset the URI so we can set it later if need be.
+        **
+        **  This is mainly so we handle data that is all spaces correctly.
+        **
+        **  In the normal case where we've seen text and then the first space,
+        **  we leave the uri ptr pointing at the beginning of the data, and
+        **  set the uri end after we've determined where to put it.
+        */
+        if (start == *ptr)
+            uri_ptr->uri = NULL;
+
+        uri_ptr->first_sp_start = *ptr;
+        uri_ptr->first_sp_end = NULL;
+
+        start_sp = &uri_ptr->first_sp_start;
+        end_sp = &uri_ptr->first_sp_end;
+    }
+
+    while (hi_util_in_bounds(start, end, *ptr))
+    {
+        /*
+        **  Check for whitespace
+        */
+        if (**ptr == ' ')
+        {
+            (*ptr)++;
+            continue;
+        }
+        else if (ServerConf->whitespace[**ptr])
+        {
+            if (ServerConf->apache_whitespace.on)
+            {
+                hi_set_event(GID_HTTP_CLIENT, HI_CLIENT_APACHE_WS);
+            }
+            (*ptr)++;
+            continue;
+        }
+        else
+        {
+            /*
+            **  This sets the sp_end for whatever space delimiter we are on,
+            **  whether that is the first space or the second space.
+            */
+            *end_sp = *ptr;
+
+            if (!IsHttpVersion(ptr, end))
+            {
+                /*
+                **  This is the default method and what we've been doing
+                **  since the start of development.
+                */
+                if (uri_ptr->second_sp_start)
+                {
+                    /*
+                    **  There is no HTTP version indentifier at the beginning
+                    **  of the second space, and this means that there is no
+                    **  URI.
+                    */
+                    if (ServerConf->non_strict)
+                    {
+                        /*
+                        **  In non-strict mode, we must assume the URI is
+                        **  between the first and second space, so now
+                        **  that we've seen the second space that's the
+                        **  identifier.
+                        */
+                        uri_ptr->ident  = *end_sp;
+                        uri_ptr->uri_end = *start_sp;
+
+                        return HI_SUCCESS;
+                    }
+                    else
+                    {
+                        /*
+                        **  Since we are in strict mode here, it means that
+                        **  we haven't seen a valid identifier, so there was
+                        **  no URI.
+                        */
+
+                        return NO_URI;
+                    }
+                }
+
+                /*
+                **  RESET NECESSARY URI_PTRs HERE.  This is the place where
+                **  the uri is updated.  It can only happen once, so do it
+                **  right here.
+                **
+                **  When we get here it means that we have found the end of
+                **  the FIRST whitespace, and that there was no delimiter,
+                **  so we reset the uri pointers and other related
+                **  pointers.
+                */
+                uri_ptr->uri      = *end_sp;
+                uri_ptr->uri_end  = end;
+                uri_ptr->norm     = NULL;
+                uri_ptr->last_dir = NULL;
+                uri_ptr->param    = NULL;
+                uri_ptr->proxy    = NULL;
+            }
+            else
+            {
+                /*
+                **  Means we found the HTTP version identifier and we reset
+                **  the uri_end pointer to point to the beginning of the
+                **  whitespace detected.
+                **
+                **  This works for both "uri_is_here HTTP/1.0" and
+                **  "METHOD uri_is_here HTTP/1.0", so it works when the
+                **  identifier is after either the first or the second
+                **  whitespace.
+                */
+                uri_ptr->ident   = *end_sp;
+                uri_ptr->uri_end = *start_sp;
+            }
+
+            /*
+            **  We found a non-whitespace char
+            */
+            return HI_SUCCESS;
+        }
+    }
+
+    /*
+    **  This is the case where we've seen text and found a whitespace until
+    **  the end of the buffer.  In that case, we set the uri_end to the
+    **  beginning of the whitespace.
+    */
+    uri_ptr->uri_end = *start_sp;
+
+    return HI_OUT_OF_BOUNDS;
+}
+
+/*
+**  NAME
+**    CheckLongDir::
+*/
+/**
+**  We check the directory length against the global config.
+**
+**  @param session pointer to the current session
+**  @param uri_ptr pointer to the URI state
+**  @param ptr     pointer to the current index in buffer
+**
+**  @return integer
+**
+**  @retval HI_SUCCESS
+*/
+int CheckLongDir(HI_SESSION* session, URI_PTR* uri_ptr, const u_char* ptr)
+{
+    int iDirLen;
+
+    /*
+    **  Check for oversize directory
+    */
+    if (session->server_conf->long_dir &&
+        uri_ptr->last_dir && !uri_ptr->param)
+    {
+        iDirLen = ptr - uri_ptr->last_dir;
+
+        if ( iDirLen > session->server_conf->long_dir )
+        {
+            hi_set_event(GID_HTTP_CLIENT, HI_CLIENT_OVERSIZE_DIR);
+        }
+    }
+
+    return HI_SUCCESS;
+}
+
index 32bcb28365fd7fe9f82e0f2649b223a0f2612fae..69126cdb032e747d9221a3aec0a73427ae6d3370 100644 (file)
@@ -1,44 +1,46 @@
 
 set( FILE_LIST
-   dce_co.cc
-   dce_co.h 
-   dce_common.cc 
-   dce_common.h 
-   dce_list.h
-   dce_list.cc
-   dce_smb.cc 
-   dce_smb.h
-   dce_smb2.cc
-   dce_smb2.h
-   dce_smb_commands.cc
-   dce_smb_commands.h 
-   dce_smb_module.cc 
-   dce_smb_module.h 
-   dce_smb_paf.cc 
-   dce_smb_paf.h
-   dce_smb_transaction.cc
-   dce_smb_transaction.h
-   dce_smb_transaction_utils.cc
-   dce_smb_transaction_utils.h
-   dce_smb_utils.cc
-   dce_smb_utils.h
-   dce_tcp.cc
-   dce_tcp.h 
-   dce_tcp_module.cc 
-   dce_tcp_module.h 
-   dce_tcp_paf.cc 
-   dce_tcp_paf.h
-   dce_udp.cc
-   dce_udp.h 
-   dce_udp_module.cc 
-   dce_udp_module.h
-   dce_udp_processing.cc
-   dce_utils.cc
-   dce_utils.h
-   ips_dce_iface.cc
-   ips_dce_opnum.cc
-   ips_dce_stub_data.cc
-
+    dce_co.cc
+    dce_co.h 
+    dce_common.cc 
+    dce_common.h 
+    dce_list.h
+    dce_list.cc
+    dce_smb.cc 
+    dce_smb.h
+    dce_smb2.cc
+    dce_smb2.h
+    dce_smb_commands.cc
+    dce_smb_commands.h 
+    dce_smb_module.cc 
+    dce_smb_module.h 
+    dce_smb_paf.cc 
+    dce_smb_paf.h
+    dce_smb_transaction.cc
+    dce_smb_transaction.h
+    dce_smb_transaction_utils.cc
+    dce_smb_transaction_utils.h
+    dce_smb_utils.cc
+    dce_smb_utils.h
+    dce_tcp.cc
+    dce_tcp.h 
+    dce_tcp_module.cc 
+    dce_tcp_module.h 
+    dce_tcp_paf.cc 
+    dce_tcp_paf.h
+    dce_udp.cc
+    dce_udp.h 
+    dce_udp_module.cc 
+    dce_udp_module.h
+    dce_udp_processing.cc
+    dce_utils.cc
+    dce_utils.h
+    ips_dce_iface.cc
+    ips_dce_opnum.cc
+    ips_dce_stub_data.cc
+    smb_common.h
+    smb_message.cc
+    smb_message.h
 )
 
 if (STATIC_INSPECTORS)
index 3bd481622a7744efa9de0899822e24a3d98655b9..38ce2ea8c89a6354b2edf87a1417a4436f1e573a 100644 (file)
@@ -36,8 +36,10 @@ dce_utils.cc \
 dce_utils.h \
 ips_dce_iface.cc \
 ips_dce_opnum.cc \
-ips_dce_stub_data.cc
-
+ips_dce_stub_data.cc \
+smb_common.h \
+smb_message.cc \
+smb_message.h
 
 if STATIC_INSPECTORS
 noinst_LIBRARIES = libdce_rpc.a
index d03a4f7bfffd526905c907c23a5d5536a35a56dc..f6c3732ac02e3fc6ea92266418b2fa96ab1e413d 100644 (file)
@@ -38,9 +38,13 @@ THREAD_LOCAL dce2SmbStats dce2_smb_stats;
 THREAD_LOCAL Packet* dce2_smb_rpkt[DCE2_SMB_RPKT_TYPE_MAX] = { nullptr, nullptr, nullptr,
                                                                nullptr };
 
+// used here
 THREAD_LOCAL ProfileStats dce2_smb_pstat_main;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_session;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_new_session;
+THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_req;
+
+// used elsewhere
 THREAD_LOCAL ProfileStats dce2_smb_pstat_detect;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_log;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_co_seg;
@@ -48,7 +52,6 @@ THREAD_LOCAL ProfileStats dce2_smb_pstat_co_frag;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_co_reass;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_co_ctx;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_seg;
-THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_req;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_uid;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_tid;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_fid;
@@ -58,21 +61,12 @@ THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_file_api;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_fingerprint;
 THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_negotiate;
 
-/********************************************************************
- * Global variables
- ********************************************************************/
-typedef DCE2_Ret (* DCE2_SmbComFunc)(DCE2_SmbSsnData*, const SmbNtHdr*,
-    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
-
-DCE2_SmbComFunc smb_com_funcs[SMB_MAX_NUM_COMS];
-uint8_t smb_wcts[SMB_MAX_NUM_COMS][2][32];
-uint16_t smb_bccs[SMB_MAX_NUM_COMS][2][2];
-DCE2_SmbComFunc smb_chain_funcs[DCE2_POLICY__MAX][SMB_ANDX_COM__MAX][SMB_MAX_NUM_COMS];
-bool smb_deprecated_coms[SMB_MAX_NUM_COMS];
-bool smb_unusual_coms[SMB_MAX_NUM_COMS];
-SmbAndXCom smb_chain_map[SMB_MAX_NUM_COMS];
+//-------------------------------------------------------------------------
+// debug stuff
+//-------------------------------------------------------------------------
 
-const char* smb_com_strings[SMB_MAX_NUM_COMS] =
+#ifdef DEBUG
+static const char* smb_com_strings[SMB_MAX_NUM_COMS] =
 {
     "Create Directory",            // 0x00
     "Delete Directory",            // 0x01
@@ -332,2621 +326,9 @@ const char* smb_com_strings[SMB_MAX_NUM_COMS] =
     "No AndX Command"              // 0xFF
 };
 
-/********************************************************************
- * Private function prototypes
- ********************************************************************/
-static inline bool DCE2_SmbIsRawData(DCE2_SmbSsnData*);
-static inline uint32_t* DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData*);
-static inline DCE2_SmbDataState* DCE2_SmbGetDataState(DCE2_SmbSsnData*);
-static inline void DCE2_SmbSetValidWordCount(uint8_t, uint8_t, uint8_t);
-static inline bool DCE2_SmbIsValidWordCount(uint8_t, uint8_t, uint8_t);
-static inline void DCE2_SmbSetValidByteCount(uint8_t, uint8_t, uint16_t, uint16_t);
-static inline bool DCE2_SmbIsValidByteCount(uint8_t, uint8_t, uint16_t);
-static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData*, const SmbNtHdr*);
-static uint32_t DCE2_IgnoreJunkData(const uint8_t*, uint16_t, uint32_t);
-static void DCE2_SmbCheckCommand(DCE2_SmbSsnData*,
-    const SmbNtHdr*, const uint8_t, const uint8_t*, uint32_t, DCE2_SmbComInfo&);
-static void DCE2_SmbProcessCommand(DCE2_SmbSsnData*, const SmbNtHdr*, const uint8_t*, uint32_t);
-static DCE2_SmbRequestTracker* DCE2_SmbInspect(DCE2_SmbSsnData*, const SmbNtHdr*);
-static DCE2_SmbRequestTracker* DCE2_SmbFindRequestTracker(DCE2_SmbSsnData*,
-    const SmbNtHdr*);
-static inline DCE2_Ret DCE2_SmbCheckAndXOffset(const uint8_t*,
-    const uint8_t*, const uint32_t);
-static void DCE2_SmbProcessRawData(DCE2_SmbSsnData*, const uint8_t*, uint32_t);
-
-/********************************************************************
- * Function: DCE2_SmbIsRawData()
- *
- * Purpose:
- *  To determine if the current state is such that a raw read or
- *  write is expected.
- *
- * Arguments:
- *  DCE2_SmbSsnData * - Pointer to SMB session data.
- *
- * Returns:
- *  bool -  True if expecting raw data.
- *          False if not.
- *
- ********************************************************************/
-static inline bool DCE2_SmbIsRawData(DCE2_SmbSsnData* ssd)
-{
-    return (ssd->pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA);
-}
-
-/********************************************************************
- * Function: DCE2_SmbCheckAndXOffset()
- *
- * Purpose:
- *  Validates that the AndXOffset is within bounds of the remaining
- *  data we have to work with.
- *
- * Arguments:
- *  uint8_t * - pointer to where the offset would take us.
- *  uint8_t * - pointer to bound offset
- *  uint8_t * - length of data where offset should be within
- *
- * Returns:
- *  DCE2_RET__SUCCESS - Offset is okay.
- *  DCE2_RET__ERROR   - Offset is bad.
- *
- ********************************************************************/
-static inline DCE2_Ret DCE2_SmbCheckAndXOffset(const uint8_t* off_ptr, const uint8_t* start_bound,
-    const uint32_t length)
-{
-    /* Offset should not point within data we just looked at or be equal to
-     * or beyond the length of the NBSS length left */
-    if ((off_ptr < start_bound) ||
-        (off_ptr > (start_bound + length)))
-    {
-        dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats);
-
-        return DCE2_RET__ERROR;
-    }
-
-    return DCE2_RET__SUCCESS;
-}
-
-/********************************************************************
- * Function: DCE2_SmbGetIgnorePtr()
- *
- * Returns a pointer to the bytes we are ignoring on client or
- * server side.  Bytes are ignored if they are associated with
- * data we are not interested in.
- *
- * Arguments:
- *  DCE2_SmbSsnData * - Pointer to SMB session data.
- *
- * Returns:
- *  uint32_t *
- *      Pointer to the client or server ignore bytes.
- *
- ********************************************************************/
-static inline uint32_t* DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData* ssd)
-{
-    if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
-        return &ssd->srv_ignore_bytes;
-    return &ssd->cli_ignore_bytes;
-}
-
-/********************************************************************
- * Function: DCE2_SmbGetDataState()
- *
- * Returns a pointer to the data state of client or server
- *
- * Arguments:
- *  DCE2_SmbSsnData * - Pointer to SMB session data.
- *
- * Returns:
- *  DCE2_SmbDataState *
- *      Pointer to the client or server data state.
- *
- ********************************************************************/
-static inline DCE2_SmbDataState* DCE2_SmbGetDataState(DCE2_SmbSsnData* ssd)
-{
-    if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
-        return &ssd->srv_data_state;
-    return &ssd->cli_data_state;
-}
-
-/********************************************************************
- * Function: DCE2_SmbSetValidWordCount()
- *
- * Purpose:
- *  Initializes global data for valid word counts for supported
- *  SMB command requests and responses.
- *
- * Arguments:
- *  uint8_t - the SMB command code
- *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
- *  uint8_t - the valid word count
- *
- * Returns: None
- *
- ********************************************************************/
-static inline void DCE2_SmbSetValidWordCount(uint8_t com,
-    uint8_t resp, uint8_t wct)
-{
-    smb_wcts[com][resp][wct/8] |= (1 << (wct % 8));
-}
-
-/********************************************************************
- * Function: DCE2_SmbIsValidWordCount()
- *
- * Purpose:
- *  Checks if a word count is valid for a given command request
- *  or response.
- *
- * Arguments:
- *  uint8_t - the SMB command code
- *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
- *  uint8_t - the word count to validate
- *
- * Returns:
- *  bool - true if valid, false if not valid.
- *
- ********************************************************************/
-static inline bool DCE2_SmbIsValidWordCount(uint8_t com,
-    uint8_t resp, uint8_t wct)
-{
-    return (smb_wcts[com][resp][wct/8] & (1 << (wct % 8))) ? true : false;
-}
-
-/********************************************************************
- * Function: DCE2_SmbSetValidByteCount()
- *
- * Purpose:
- *  Initializes global data for valid byte counts as a range for
- *  supported SMB command requests and responses.
- *  Since a byte count is 2 bytes, a 4 byte type is used to store
- *  the range.  The maximum is in the most significant 2 bytes and
- *  the minimum in the least significant 2 bytes.
- *
- * Arguments:
- *  uint8_t - the SMB command code
- *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
- *  uint8_t - the minimum word count that is valid
- *  uint8_t - the maximum word count that is valid
- *
- * Returns: None
- *
- ********************************************************************/
-static inline void DCE2_SmbSetValidByteCount(uint8_t com,
-    uint8_t resp, uint16_t min, uint16_t max)
-{
-    smb_bccs[com][resp][0] = min;
-    smb_bccs[com][resp][1] = max;
-}
-
-/********************************************************************
- * Function: DCE2_SmbIsValidByteCount()
- *
- * Purpose:
- *  Checks if a byte count is valid for a given command request
- *  or response.
- *
- * Arguments:
- *  uint8_t - the SMB command code
- *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
- *  uint8_t - the byte count to validate
- *
- * Returns:
- *  bool - true if valid, false if not valid.
- *
- ********************************************************************/
-static inline bool DCE2_SmbIsValidByteCount(uint8_t com,
-    uint8_t resp, uint16_t bcc)
-{
-    return ((bcc < smb_bccs[com][resp][0])
-           || (bcc > smb_bccs[com][resp][1])) ? false : true;
-}
-
-// This function is obviously deficient.  Need to do a lot more
-// testing, research and reading MS-CIFS, MS-SMB and MS-ERREF.
-static bool SmbError(const SmbNtHdr* hdr)
-{
-    if (SmbStatusNtCodes(hdr))
-    {
-        /* Nt status codes are being used.  First 2 bits indicate
-         * severity. */
-        switch (SmbNtStatusSeverity(hdr))
-        {
-        case SMB_NT_STATUS_SEVERITY__SUCCESS:
-        case SMB_NT_STATUS_SEVERITY__INFORMATIONAL:
-        case SMB_NT_STATUS_SEVERITY__WARNING:
-            return false;
-        case SMB_NT_STATUS_SEVERITY__ERROR:
-        default:
-            break;
-        }
-    }
-    else
-    {
-        switch (SmbStatusClass(hdr))
-        {
-        case SMB_ERROR_CLASS__SUCCESS:
-            return false;
-        case SMB_ERROR_CLASS__ERRDOS:
-            if (SmbStatusCode(hdr) == SMB_ERRDOS__MORE_DATA)
-                return false;
-            break;
-        case SMB_ERROR_CLASS__ERRSRV:
-        case SMB_ERROR_CLASS__ERRHRD:
-        case SMB_ERROR_CLASS__ERRCMD:
-        default:
-            break;
-        }
-    }
-
-    return true;
-}
-
-static bool SmbBrokenPipe(const SmbNtHdr* hdr)
-{
-    if (SmbStatusNtCodes(hdr))
-    {
-        uint32_t nt_status = SmbNtStatus(hdr);
-        if ((nt_status == SMB_NT_STATUS__PIPE_BROKEN)
-            || (nt_status == SMB_NT_STATUS__PIPE_DISCONNECTED))
-            return true;
-    }
-    else
-    {
-        if (SmbStatusClass(hdr) == SMB_ERROR_CLASS__ERRDOS)
-        {
-            uint16_t smb_status = SmbStatusCode(hdr);
-            if ((smb_status == SMB_ERRDOS__BAD_PIPE)
-                || (smb_status == SMB_ERRDOS__PIPE_NOT_CONNECTED))
-                return true;
-        }
-    }
-
-    return false;
-}
-
-/********************************************************************
- * Function: DCE2_IgnoreJunkData()
- *
- * Purpose:
- *   An evasion technique can be to put a bunch of junk data before
- *   the actual SMB request and it seems the MS implementation has
- *   no problem with it and seems to just ignore the data.  This
- *   function attempts to move past all the junk to get to the
- *   actual NetBIOS message request.
- *
- * Arguments:
- *   const uint8_t *  - pointer to the current position in the data
- *      being inspected
- *   uint16_t  -  the amount of data left to look at
- *   uint32_t  -  the amount of data to ignore if there doesn't seem
- *      to be any junk data.  Just use the length as if the bad
- *      NetBIOS header was good.
- *
- * Returns:
- *    uint32_t - the amount of bytes to ignore as junk.
- *
- ********************************************************************/
-static uint32_t DCE2_IgnoreJunkData(const uint8_t* data_ptr, uint16_t data_len,
-    uint32_t assumed_nb_len)
-{
-    const uint8_t* tmp_ptr = data_ptr;
-    uint32_t ignore_bytes = 0;
-
-    /* Try to find \xffSMB and go back 8 bytes to beginning
-     * of what should be a Netbios header with type Session
-     * Message (\x00) - do appropriate buffer checks to make
-     * sure the index is in bounds. Ignore all intervening
-     * bytes */
-
-    while ((tmp_ptr + sizeof(uint32_t)) <= (data_ptr + data_len))
-    {
-        if ((SmbId((SmbNtHdr*)tmp_ptr) == DCE2_SMB_ID)
-            || (SmbId((SmbNtHdr*)tmp_ptr) == DCE2_SMB2_ID))
-        {
-            break;
-        }
-
-        tmp_ptr++;
-    }
-
-    if ((tmp_ptr + sizeof(uint32_t)) > (data_ptr + data_len))
-    {
-        ignore_bytes = data_len;
-    }
-    else
-    {
-        if ((tmp_ptr - sizeof(NbssHdr)) > data_ptr)
-            ignore_bytes = (tmp_ptr - data_ptr) - sizeof(NbssHdr);
-        else  /* Just ignore whatever the bad NB header had as a length */
-            ignore_bytes = assumed_nb_len;
-    }
-
-    return ignore_bytes;
-}
-
-/********************************************************************
- * Function: DCE2_SmbHdrChecks()
- *
- * Checks some relevant fields in the header to make sure they're
- * sane.
- * Side effects are potential alerts for anomolous behavior.
- *
- * Arguments:
- *  DCE2_SmbSsnData *
- *      Pointer to the session data structure.
- *  SmbNtHdr *
- *      Pointer to the header struct layed over the packet data.
- *
- * Returns:
- *  DCE2_Ret
- *      DCE2_RET__IGNORE if we should continue processing, but
- *          ignore data because of the error.
- *      DCE2_RET__SUCCESS if we should continue processing.
- *
- ********************************************************************/
-static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr)
-{
-    Packet* p = ssd->sd.wire_pkt;
-    bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (uint8_t*)smb_hdr);
-
-    if ((DCE2_SsnFromServer(p) && (SmbType(smb_hdr) == SMB_TYPE__REQUEST)) ||
-        (DCE2_SsnFromClient(p) && (SmbType(smb_hdr) == SMB_TYPE__RESPONSE)))
-    {
-        if (is_seg_buf)
-            DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_TYPE);
-        else
-            dce_alert(GID_DCE2, DCE2_SMB_BAD_TYPE, (dce2CommonStats*)&dce2_smb_stats);
-
-        // Continue looking at traffic.  Neither Windows nor Samba seem
-        // to care, or even look at this flag
-    }
-
-    if ((SmbId(smb_hdr) != DCE2_SMB_ID)
-        && (SmbId(smb_hdr) != DCE2_SMB2_ID))
-    {
-        if (is_seg_buf)
-            DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_ID);
-        else
-            dce_alert(GID_DCE2, DCE2_SMB_BAD_ID, (dce2CommonStats*)&dce2_smb_stats);
-
-        return DCE2_RET__IGNORE;
-    }
-
-    return DCE2_RET__SUCCESS;
-}
-
-/********************************************************************
- * Function: DCE2_SmbGetMinByteCount()
- *
- * Purpose:
- *  Returns the minimum byte count for the given command request
- *  or response.
- *
- * Arguments:
- *  uint8_t - the SMB command code
- *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
- *
- * Returns:
- *  uint16_t - the minimum byte count
- *
- ********************************************************************/
-static inline uint16_t DCE2_SmbGetMinByteCount(uint8_t com, uint8_t resp)
-{
-    return smb_bccs[com][resp][0];
-}
-
-static DCE2_SmbRequestTracker* DCE2_SmbFindRequestTracker(DCE2_SmbSsnData* ssd,
-    const SmbNtHdr* smb_hdr)
-{
-    uint16_t uid = SmbUid(smb_hdr);
-    uint16_t tid = SmbTid(smb_hdr);
-    uint16_t pid = SmbPid(smb_hdr);
-    uint16_t mid = SmbMid(smb_hdr);
-
-    Profile profile(dce2_smb_pstat_smb_req);
-
-    DebugFormat(DEBUG_DCE_SMB, "Find request tracker => "
-        "Uid: %hu, Tid: %hu, Pid: %hu, Mid: %hu ... ", uid, tid, pid, mid);
-
-    DCE2_SmbRequestTracker* tmp_rtracker = &ssd->rtracker;
-    int smb_com = SmbCom(smb_hdr);
-    switch (smb_com)
-    {
-    case SMB_COM_TRANSACTION_SECONDARY:
-        smb_com = SMB_COM_TRANSACTION;
-        break;
-    case SMB_COM_TRANSACTION2_SECONDARY:
-        smb_com = SMB_COM_TRANSACTION2;
-        break;
-    case SMB_COM_NT_TRANSACT_SECONDARY:
-        smb_com = SMB_COM_NT_TRANSACT;
-        break;
-    case SMB_COM_WRITE_COMPLETE:
-        smb_com = SMB_COM_WRITE_RAW;
-        break;
-    default:
-        break;
-    }
-
-    DCE2_SmbRequestTracker* first_rtracker = nullptr;
-    DCE2_SmbRequestTracker* win_rtracker = nullptr;
-    DCE2_SmbRequestTracker* first_mid_rtracker = nullptr;
-    DCE2_SmbRequestTracker* ret_rtracker = nullptr;
-    while (tmp_rtracker != nullptr)
-    {
-        if ((tmp_rtracker->mid == (int)mid) && (tmp_rtracker->smb_com == smb_com))
-        {
-            // This is the normal case except for SessionSetupAndX and
-            // TreeConnect/TreeConnectAndX which will fall into the
-            // default case below.
-            if ((tmp_rtracker->pid == pid) && (tmp_rtracker->uid == uid)
-                && (tmp_rtracker->tid == tid))
-            {
-                ret_rtracker = tmp_rtracker;
-            }
-            else
-            {
-                switch (smb_com)
-                {
-                case SMB_COM_TRANSACTION:
-                case SMB_COM_TRANSACTION2:
-                case SMB_COM_NT_TRANSACT:
-                case SMB_COM_TRANSACTION_SECONDARY:
-                case SMB_COM_TRANSACTION2_SECONDARY:
-                case SMB_COM_NT_TRANSACT_SECONDARY:
-                    // These should conform to above
-                    break;
-                default:
-                    if (tmp_rtracker->pid == pid)
-                        ret_rtracker = tmp_rtracker;
-                    break;
-                }
-            }
-
-            if (ret_rtracker != nullptr)
-            {
-                DebugMessage(DEBUG_DCE_SMB, "Found.\n");
-                return ret_rtracker;
-            }
-
-            // Take the first one where the PIDs also match
-            // in the case of the Transacts above
-            if ((tmp_rtracker->pid == pid) && (win_rtracker == nullptr))
-                win_rtracker = tmp_rtracker;
-
-            // Set this to the first matching request in the queue
-            // where the Mid matches.  Don't set for Windows if from
-            // client since PID/MID are necessary
-            if (((DCE2_SmbType(ssd) == SMB_TYPE__RESPONSE)
-                || !DCE2_SsnIsWindowsPolicy(&ssd->sd))
-                && first_mid_rtracker == nullptr)
-            {
-                first_mid_rtracker = tmp_rtracker;
-            }
-        }
-
-        // Set the first one we see for early Samba versions
-        if ((first_rtracker == nullptr) && (tmp_rtracker->mid != DCE2_SENTINEL)
-            && (tmp_rtracker->smb_com == smb_com))
-            first_rtracker = tmp_rtracker;
-
-        // Look at the next request in the queue
-        if (tmp_rtracker == &ssd->rtracker)
-            tmp_rtracker = (DCE2_SmbRequestTracker*)DCE2_QueueFirst(ssd->rtrackers);
-        else
-            tmp_rtracker = (DCE2_SmbRequestTracker*)DCE2_QueueNext(ssd->rtrackers);
-    }
-
-    DCE2_Policy policy = DCE2_SsnGetPolicy(&ssd->sd);
-    switch (policy)
-    {
-    case DCE2_POLICY__SAMBA_3_0_20:
-    case DCE2_POLICY__SAMBA_3_0_22:
-        ret_rtracker = first_rtracker;
-        break;
-    case DCE2_POLICY__SAMBA:
-    case DCE2_POLICY__SAMBA_3_0_37:
-        ret_rtracker = first_mid_rtracker;
-        break;
-    case DCE2_POLICY__WIN2000:
-    case DCE2_POLICY__WINXP:
-    case DCE2_POLICY__WINVISTA:
-    case DCE2_POLICY__WIN2003:
-    case DCE2_POLICY__WIN2008:
-    case DCE2_POLICY__WIN7:
-        if (win_rtracker != nullptr)
-            ret_rtracker = win_rtracker;
-        else
-            ret_rtracker = first_mid_rtracker;
-        break;
-    default:
-        DebugFormat(DEBUG_DCE_SMB, "%s(%d) Invalid policy: %d",
-            __FILE__, __LINE__, policy);
-        break;
-    }
-
-    return ret_rtracker;
-}
-
-/********************************************************************
- * Function: DCE2_SmbCheckCommand()
- *
- * Purpose:
- *  Checks basic validity of an SMB command.
- *
- * Arguments:
- *  DCE2_SmbSsnData * - pointer to session data structure
- *  SmbNtHdr *        - pointer to the SMB header structure
- *  uint8_t           - the SMB command code, i.e. SMB_COM_*
- *  uint8_t *         - current pointer to data, i.e. the command
- *  uint32_t          - the remaining length
- *  DCE2_SmbComInfo & -
- *      Populated structure for command processing
- *
- * Returns: None
- *
- ********************************************************************/
-static void DCE2_SmbCheckCommand(DCE2_SmbSsnData* ssd,
-    const SmbNtHdr* smb_hdr, const uint8_t smb_com,
-    const uint8_t* nb_ptr, uint32_t nb_len, DCE2_SmbComInfo& com_info)
-{
-    // Check for server error response
-    if (com_info.smb_type == SMB_TYPE__RESPONSE)
-    {
-        const SmbEmptyCom* ec = (SmbEmptyCom*)nb_ptr;
-
-        // Verify there is enough data to do checks
-        if (nb_len < sizeof(SmbEmptyCom))
-        {
-            dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats);
-            com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
-            return;
-        }
-
-        // If word and byte counts are zero and there is an error
-        // the server didn't accept client request
-        if ((SmbEmptyComWct(ec) == 0)
-            && (SmbEmptyComBcc(ec) == 0) && SmbError(smb_hdr))
-        {
-            DebugFormat(DEBUG_DCE_SMB,
-                "Response error: 0x%08X\n", SmbNtStatus(smb_hdr));
-
-            // If broken pipe, clean up data associated with open named pipe
-            if (SmbBrokenPipe(smb_hdr))
-            {
-                DebugMessage(DEBUG_DCE_SMB, "Broken or disconnected pipe.\n");
-                DCE2_SmbRemoveFileTracker(ssd, ssd->cur_rtracker->ftracker);
-            }
-
-            com_info.cmd_error |= DCE2_SMB_COM_ERROR__STATUS_ERROR;
-            return;
-        }
-    }
-
-    // Set the header size to the minimum size the command can be
-    // without the byte count to make sure there is enough data to
-    // get the word count.
-    SmbAndXCom andx_com = smb_chain_map[smb_com];
-    int chk_com_size;
-    if (andx_com == SMB_ANDX_COM__NONE)
-        chk_com_size = sizeof(SmbCommon);
-    else
-        chk_com_size = sizeof(SmbAndXCommon);
-
-    // Verify there is enough data to do checks
-    if (nb_len < (uint32_t)chk_com_size)
-    {
-        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats);
-        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
-        return;
-    }
-
-    const SmbCommon* sc = (SmbCommon*)nb_ptr;
-    com_info.word_count = SmbWct(sc);
-
-    // Make sure the word count is a valid one for the command.  If not
-    // testing shows an error will be returned.  And command structures
-    // won't lie on data correctly and out of bounds data accesses are possible.
-    if (!DCE2_SmbIsValidWordCount(smb_com, (uint8_t)com_info.smb_type, com_info.word_count))
-    {
-        dce_alert(GID_DCE2, DCE2_SMB_BAD_WCT, (dce2CommonStats*)&dce2_smb_stats);
-        com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_WORD_COUNT;
-        return;
-    }
-
-    // This gets the size of the SMB command from word count through byte count
-    // using the advertised value in the word count field.
-    com_info.cmd_size = (uint16_t)SMB_COM_SIZE(com_info.word_count);
-    if (nb_len < com_info.cmd_size)
-    {
-        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats);
-        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
-        return;
-    }
-
-    uint16_t smb_bcc = SmbBcc(nb_ptr, com_info.cmd_size);
-
-    // SMB_COM_NT_CREATE_ANDX is a special case.  Who know what's going
-    // on with the word count (see MS-CIFS and MS-SMB).  A 42 word count
-    // command seems to actually have 50 words, so who knows where the
-    // byte count is.  Just set to zero since it's not needed.
-    if ((smb_com == SMB_COM_NT_CREATE_ANDX)
-        && (com_info.smb_type == SMB_TYPE__RESPONSE))
-        smb_bcc = 0;
-
-    // If byte count is deemed invalid, alert but continue processing
-    switch (smb_com)
-    {
-    // Interim responses
-    case SMB_COM_TRANSACTION:
-    case SMB_COM_TRANSACTION2:
-    case SMB_COM_NT_TRANSACT:
-        // If word count is 0, byte count must be 0
-        if ((com_info.word_count == 0) && (com_info.smb_type == SMB_TYPE__RESPONSE))
-        {
-            if (smb_bcc != 0)
-            {
-                dce_alert(GID_DCE2, DCE2_SMB_BAD_BCC, (dce2CommonStats*)&dce2_smb_stats);
-                com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
-            }
-            break;
-        }
-    // Fall through
-    default:
-        if (!DCE2_SmbIsValidByteCount(smb_com, (uint8_t)com_info.smb_type, smb_bcc))
-        {
-            dce_alert(GID_DCE2, DCE2_SMB_BAD_BCC, (dce2CommonStats*)&dce2_smb_stats);
-            com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
-        }
-        break;
-    }
-
-    // Move just past byte count field which is the end of the command
-    DCE2_MOVE(nb_ptr, nb_len, com_info.cmd_size);
-
-    // Validate that there is enough data to be able to process the command
-    if (nb_len < DCE2_SmbGetMinByteCount(smb_com, (uint8_t)com_info.smb_type))
-    {
-        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_BCC, (dce2CommonStats*)&dce2_smb_stats);
-        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
-    }
-
-    // The byte count seems to be ignored by Windows and current Samba (3.5.4)
-    // as long as it is less than the amount of data left.  If more, an error
-    // is returned.
-    // !!!WARNING!!! the byte count should probably never be used.
-    if (smb_bcc > nb_len)
-    {
-        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_BCC, (dce2CommonStats*)&dce2_smb_stats);
-        // Large byte count doesn't seem to matter for early Samba
-        switch (DCE2_SsnGetPolicy(&ssd->sd))
-        {
-        case DCE2_POLICY__SAMBA_3_0_20:
-        case DCE2_POLICY__SAMBA_3_0_22:
-        case DCE2_POLICY__SAMBA_3_0_37:
-            break;
-        default:
-            com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
-            break;
-        }
-    }
-    else if ((smb_bcc == 0) && (SmbCom(smb_hdr) == SMB_COM_TRANSACTION)
-        && (DCE2_SmbType(ssd) == SMB_TYPE__REQUEST)
-        && (DCE2_SsnGetPolicy(&ssd->sd) == DCE2_POLICY__SAMBA))
-    {
-        // Current Samba errors on a zero byte count Transaction because it
-        // uses it to get the Name string and if zero Name will be NULL and
-        // it won't process it.
-        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
-    }
-
-    com_info.byte_count = smb_bcc;
-}
-
-/********************************************************************
- * Function: DCE2_SmbProcessCommand()
- *
- * Purpose:
- *  This is the main function for handling SMB commands and command
- *  chaining.
- *  It does an initial check of the command to determine validity
- *  and gets basic information about the command.  Then it calls the
- *  specific command function (setup in DCE2_SmbInitGlobals).
- *  If there is command chaining, it will do the chaining foo to
- *  get to the next command.
- *
- * Arguments:
- *  DCE2_SmbSsnData * - pointer to session data structure
- *  SmbNtHdr *        - pointer to the SMB header structure
- *  uint8_t *         - current pointer to data, i.e. the command
- *  uint32_t          - the remaining length
- *
- * Returns: None
- *
- ********************************************************************/
-static void DCE2_SmbProcessCommand(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
-    const uint8_t* nb_ptr, uint32_t nb_len)
-{
-    uint8_t smb_com = SmbCom(smb_hdr);
-    DCE2_Ret status = DCE2_RET__ERROR;
-    bool sess_chain = false;
-    bool tree_chain = false;
-    bool open_chain = false;
-    int num_chained = 0;
-
-    while (nb_len > 0)
-    {
-        // Break out if command not supported
-        if (smb_com_funcs[smb_com] == nullptr)
-            break;
-
-        if (smb_deprecated_coms[smb_com])
-        {
-            dce_alert(GID_DCE2, DCE2_SMB_DEPR_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        if (smb_unusual_coms[smb_com])
-        {
-            dce_alert(GID_DCE2, DCE2_SMB_UNUSUAL_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        DCE2_SmbComInfo com_info;
-        com_info.smb_type = DCE2_SmbType(ssd);
-        com_info.cmd_error = DCE2_SMB_COM_ERROR__COMMAND_OK;
-        com_info.word_count = 0;
-        com_info.smb_com = smb_com;
-        com_info.cmd_size = 0;
-        com_info.byte_count = 0;
-        DCE2_SmbCheckCommand(ssd, smb_hdr, smb_com, nb_ptr, nb_len, com_info);
-        DebugFormat(DEBUG_DCE_SMB, "Processing command: %s (0x%02X)\n",
-            smb_com_strings[smb_com], smb_com);
-
-        // Note that even if the command shouldn't be processed, some of
-        // the command functions need to know and do cleanup or some other
-        // processing.
-        status = smb_com_funcs[smb_com](ssd, smb_hdr,
-                &com_info, nb_ptr, nb_len);
-
-        if (status != DCE2_RET__SUCCESS)
-            break;
-
-        // This command is not chainable
-        SmbAndXCom andx_com = smb_chain_map[smb_com];
-        if (andx_com == SMB_ANDX_COM__NONE)
-            break;
-
-        /**********************************************************
-         * AndX Chaining
-         **********************************************************/
-        const SmbAndXCommon* andx_ptr = (SmbAndXCommon*)nb_ptr;
-        uint8_t smb_com2 = SmbAndXCom2(andx_ptr);
-        if (smb_com2 == SMB_COM_NO_ANDX_COMMAND)
-            break;
-
-        DebugFormat(DEBUG_DCE_SMB, "Chained SMB command: %s\n", smb_com_strings[smb_com2]);
-
-        num_chained++;
-        if (DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config) &&
-            (num_chained >= DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config)))
-        {
-            dce_alert(GID_DCE2, DCE2_SMB_EXCESSIVE_CHAINING, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        // Multiple SessionSetupAndX, TreeConnectAndX, OpenAndX and NtCreateAndX
-        // are only allowed by Samba.
-        if (smb_com == SMB_COM_SESSION_SETUP_ANDX)
-            sess_chain = true;
-
-        // Check for multiple chained SessionSetupAndX
-        if ((smb_com2 == SMB_COM_SESSION_SETUP_ANDX) && sess_chain)
-        {
-            // There is only one place to return a uid.
-            dce_alert(GID_DCE2, DCE2_SMB_MULT_CHAIN_SS, (dce2CommonStats*)&dce2_smb_stats);
-            // FIXIT-L Should we continue processing?
-            break;
-        }
-
-        // Check for chained SessionSetupAndX => .? => LogoffAndX
-        if ((smb_com2 == SMB_COM_LOGOFF_ANDX) && sess_chain)
-        {
-            // This essentially deletes the uid created by the login
-            // and doesn't make any sense.
-            dce_alert(GID_DCE2, DCE2_SMB_CHAIN_SS_LOGOFF, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        if (smb_com == SMB_COM_TREE_CONNECT_ANDX)
-            tree_chain = true;
-
-        // Check for multiple chained TreeConnects
-        if (((smb_com2 == SMB_COM_TREE_CONNECT_ANDX)
-            || (smb_com2 == SMB_COM_TREE_CONNECT)) && tree_chain)
-        {
-            // There is only one place to return a tid.
-            dce_alert(GID_DCE2, DCE2_SMB_MULT_CHAIN_TC, (dce2CommonStats*)&dce2_smb_stats);
-            // FIXIT-L Should we continue processing?
-            break;
-        }
-
-        // Check for chained TreeConnectAndX => .? => TreeDisconnect
-        if ((smb_com2 == SMB_COM_TREE_DISCONNECT) && tree_chain)
-        {
-            // This essentially deletes the tid created by the tree connect
-            // and doesn't make any sense.
-            dce_alert(GID_DCE2, DCE2_SMB_CHAIN_TC_TDIS, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        if ((smb_com == SMB_COM_OPEN_ANDX) || (smb_com == SMB_COM_NT_CREATE_ANDX))
-            open_chain = true;
-
-        // Check for chained OpenAndX/NtCreateAndX => .? => Close
-        if ((smb_com2 == SMB_COM_CLOSE) && open_chain)
-        {
-            // This essentially deletes the fid created by the open command
-            // and doesn't make any sense.
-            dce_alert(GID_DCE2, DCE2_SMB_CHAIN_OPEN_CLOSE, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        // Check that policy allows for such chaining
-        DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
-        if (smb_chain_funcs[policy][andx_com][smb_com2] == nullptr)
-            break;
-
-        DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(&com_info));
-
-        // FIXIT-L Need to test out of order chaining
-        const uint8_t* off2_ptr = (uint8_t*)smb_hdr + SmbAndXOff2(andx_ptr);
-        if (DCE2_SmbCheckAndXOffset(off2_ptr, nb_ptr, nb_len) != DCE2_RET__SUCCESS)
-            break;
-
-        DCE2_MOVE(nb_ptr, nb_len, (off2_ptr - nb_ptr));
-
-        // FIXIT-L Need to test more.
-        switch (smb_com)
-        {
-        case SMB_COM_SESSION_SETUP_ANDX:
-        case SMB_COM_TREE_CONNECT_ANDX:
-        case SMB_COM_OPEN_ANDX:
-        case SMB_COM_NT_CREATE_ANDX:
-            switch (smb_com2)
-            {
-            case SMB_COM_WRITE:
-            case SMB_COM_WRITE_ANDX:
-            case SMB_COM_TRANSACTION:
-            case SMB_COM_READ_ANDX:
-                if (DCE2_SsnFromClient(ssd->sd.wire_pkt) && open_chain)
-                {
-                    DCE2_SmbQueueTmpFileTracker(ssd, ssd->cur_rtracker,
-                        SmbUid(smb_hdr), SmbTid(smb_hdr));
-                }
-                break;
-            default:
-                break;
-            }
-            break;
-        default:
-            break;
-        }
-
-        smb_com = smb_com2;
-    }
-
-    int smb_type = DCE2_SmbType(ssd);
-    if (smb_type == SMB_TYPE__RESPONSE)
-    {
-        switch (smb_com)
-        {
-        case SMB_COM_TRANSACTION:
-        case SMB_COM_TRANSACTION2:
-        case SMB_COM_NT_TRANSACT:
-        case SMB_COM_TRANSACTION_SECONDARY:
-        case SMB_COM_TRANSACTION2_SECONDARY:
-        case SMB_COM_NT_TRANSACT_SECONDARY:
-            // This case means there was an error with the initial response
-            // so the tracker isn't yet officially in response mode
-            if (ssd->cur_rtracker->ttracker.smb_type == SMB_TYPE__REQUEST)
-            {
-                // Samba throws out entire transaction and Windows just this request
-                if (DCE2_SsnIsServerSambaPolicy(&ssd->sd) && (status != DCE2_RET__SUCCESS))
-                    break;
-
-                if (!DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
-                    return;
-            }
-            else
-            {
-                if ((status == DCE2_RET__SUCCESS)
-                    && !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
-                    return;
-            }
-            break;
-        case SMB_COM_WRITE_RAW:
-            if ((status == DCE2_RET__SUCCESS)
-                && (ssd->cur_rtracker->writeraw_remaining != 0))
-                return;
-            break;
-        default:
-            break;
-        }
-    }
-    else if (status != DCE2_RET__IGNORE)
-    {
-        switch (smb_com)
-        {
-        case SMB_COM_TRANSACTION:
-        case SMB_COM_TRANSACTION_SECONDARY:
-            if (DCE2_SsnIsWindowsPolicy(&ssd->sd))
-            {
-                if (!ssd->cur_rtracker->ttracker.one_way
-                    || !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
-                    return;
-
-                // Remove the request tracker if transaction is one-way and
-                // all data and parameters have been sent
-                break;
-            }
-        default:
-            // Anything else, keep the request tracker
-            return;
-        }
-    }
-
-    DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
-    ssd->cur_rtracker = nullptr;
-}
-
-/********************************************************************
- * Function: DCE2_SmbInspect()
- *
- * Purpose:
- *  Determines whether the SMB command is something the preprocessor
- *  needs to inspect.
- *  This function returns a DCE2_SmbRequestTracker which tracks command
- *  requests / responses.
- *
- * Arguments:
- *  DCE2_SmbSsnData * - the session data structure.
- *  const SmbNtHdr *  - pointer to the SMB header.
- *
- * Returns:
- *  DCE2_SmbRequestTracker * - nullptr if it's not something we want to or can
- *                     inspect.
- *                     Otherwise an initialized structure if request
- *                     and the found structure if response.
- *
- ********************************************************************/
-static DCE2_SmbRequestTracker* DCE2_SmbInspect(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr)
-{
-    int smb_com = SmbCom(smb_hdr);
-
-    DebugFormat(DEBUG_DCE_SMB, "SMB command: %s (0x%02X)\n",
-        smb_com_strings[smb_com], smb_com);
-
-    if (smb_com_funcs[smb_com] == nullptr)
-    {
-        DebugMessage(DEBUG_DCE_SMB, "Command isn't processed "
-            "by preprocessor.\n");
-        return nullptr;
-    }
-
-    // See if this is something we need to inspect
-    DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
-    DCE2_SmbRequestTracker* rtracker = nullptr;
-    if (DCE2_SmbType(ssd) == SMB_TYPE__REQUEST)
-    {
-        switch (smb_com)
-        {
-        case SMB_COM_NEGOTIATE:
-            if (ssd->ssn_state_flags & DCE2_SMB_SSN_STATE__NEGOTIATED)
-            {
-                dce_alert(GID_DCE2, DCE2_SMB_MULTIPLE_NEGOTIATIONS,
-                    (dce2CommonStats*)&dce2_smb_stats);
-                return nullptr;
-            }
-            break;
-        case SMB_COM_SESSION_SETUP_ANDX:
-            break;
-        case SMB_COM_TREE_CONNECT:
-        case SMB_COM_TREE_CONNECT_ANDX:
-        case SMB_COM_RENAME:
-        case SMB_COM_LOGOFF_ANDX:
-            if (DCE2_SmbFindUid(ssd, SmbUid(smb_hdr)) != DCE2_RET__SUCCESS)
-                return nullptr;
-            break;
-        default:
-            if (DCE2_SmbFindTid(ssd, SmbTid(smb_hdr)) != DCE2_RET__SUCCESS)
-            {
-                DebugFormat(DEBUG_DCE_SMB,
-                    "Couldn't find Tid (%hu)\n", SmbTid(smb_hdr));
-                return nullptr;
-            }
-
-            if (DCE2_SmbIsTidIPC(ssd, SmbTid(smb_hdr)))
-            {
-                switch (smb_com)
-                {
-                case SMB_COM_OPEN:
-                case SMB_COM_CREATE:
-                case SMB_COM_CREATE_NEW:
-                case SMB_COM_WRITE_AND_CLOSE:
-                case SMB_COM_WRITE_AND_UNLOCK:
-                case SMB_COM_READ:
-                    // Samba doesn't allow these commands under an IPC tree
-                    switch (policy)
-                    {
-                    case DCE2_POLICY__SAMBA:
-                    case DCE2_POLICY__SAMBA_3_0_37:
-                    case DCE2_POLICY__SAMBA_3_0_22:
-                    case DCE2_POLICY__SAMBA_3_0_20:
-                        DebugMessage(DEBUG_DCE_SMB, "Samba doesn't "
-                            "process this command under an IPC tree.\n");
-                        return nullptr;
-                    default:
-                        break;
-                    }
-                    break;
-                case SMB_COM_READ_RAW:
-                case SMB_COM_WRITE_RAW:
-                    // Samba and Windows Vista on don't allow these commands
-                    // under an IPC tree, whether or not the raw read/write
-                    // flag is set in the Negotiate capabilities.
-                    // Windows RSTs the connection and Samba FINs it.
-                    switch (policy)
-                    {
-                    case DCE2_POLICY__WINVISTA:
-                    case DCE2_POLICY__WIN2008:
-                    case DCE2_POLICY__WIN7:
-                    case DCE2_POLICY__SAMBA:
-                    case DCE2_POLICY__SAMBA_3_0_37:
-                    case DCE2_POLICY__SAMBA_3_0_22:
-                    case DCE2_POLICY__SAMBA_3_0_20:
-                        DebugMessage(DEBUG_DCE_SMB, "Samba and "
-                            "Windows Vista on don't process this "
-                            "command under an IPC tree.\n");
-                        return nullptr;
-                    default:
-                        break;
-                    }
-                    break;
-                case SMB_COM_LOCK_AND_READ:
-                    // The lock will fail so the read won't happen
-                    return nullptr;
-                default:
-                    break;
-                }
-            }
-            else      // Not IPC
-            {
-                switch (smb_com)
-                {
-                // These commands are only used for IPC
-                case SMB_COM_TRANSACTION:
-                case SMB_COM_TRANSACTION_SECONDARY:
-                    DebugMessage(DEBUG_DCE_SMB, "secondary transaction not IPC.\n");
-                    return nullptr;
-                case SMB_COM_READ_RAW:
-                case SMB_COM_WRITE_RAW:
-                    // Windows Vista on don't seem to support these
-                    // commands, whether or not the raw read/write
-                    // flag is set in the Negotiate capabilities.
-                    // Windows RSTs the connection.
-                    switch (policy)
-                    {
-                    case DCE2_POLICY__WINVISTA:
-                    case DCE2_POLICY__WIN2008:
-                    case DCE2_POLICY__WIN7:
-                        DebugMessage(DEBUG_DCE_SMB,
-                            "Windows Vista on don't process "
-                            "this command.\n");
-                        return nullptr;
-                    default:
-                        break;
-                    }
-                    break;
-                default:
-                    break;
-                }
-            }
-            break;
-        }
-
-        switch (smb_com)
-        {
-        case SMB_COM_TRANSACTION_SECONDARY:
-        case SMB_COM_TRANSACTION2_SECONDARY:
-        case SMB_COM_NT_TRANSACT_SECONDARY:
-            rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
-            break;
-        case SMB_COM_TRANSACTION:
-        case SMB_COM_TRANSACTION2:
-        case SMB_COM_NT_TRANSACT:
-            // If there is already and existing request tracker
-            // and the transaction is not complete, server will
-            // return an error.
-            rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
-            if (rtracker != nullptr)
-                break;
-        // Fall through
-        default:
-            rtracker = DCE2_SmbNewRequestTracker(ssd, smb_hdr);
-            break;
-        }
-    }
-    else
-    {
-        rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
-    }
-
-    return rtracker;
-}
-
-static void DCE2_SmbProcessRawData(DCE2_SmbSsnData* ssd, const uint8_t* nb_ptr, uint32_t nb_len)
-{
-    DCE2_SmbFileTracker* ftracker = ssd->cur_rtracker->ftracker;
-    bool remove_rtracker = false;
-
-    if (ftracker == nullptr)
-    {
-        DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
-        ssd->cur_rtracker = nullptr;
-        return;
-    }
-
-    if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
-    {
-        DebugMessage(DEBUG_DCE_SMB, "Raw data: Write Raw\n");
-        DebugFormat(DEBUG_DCE_SMB, "Request Fid: 0x%04X\n", ftracker->fid_v1);
-
-        if (nb_len > ssd->cur_rtracker->writeraw_remaining)
-        {
-            dce_alert(GID_DCE2, DCE2_SMB_TDCNT_LT_DSIZE, (dce2CommonStats*)&dce2_smb_stats);
-
-            // If this happens, Windows never responds regardless of
-            // WriteThrough flag, so get rid of request tracker
-            remove_rtracker = true;
-        }
-        else if (!ssd->cur_rtracker->writeraw_writethrough)
-        {
-            // If WriteThrough flag was not set on initial request, a
-            // SMB_COM_WRITE_COMPLETE will not be sent so need to get
-            // rid of request tracker.
-            remove_rtracker = true;
-        }
-        else
-        {
-            ssd->cur_rtracker->writeraw_writethrough = false;
-            ssd->cur_rtracker->writeraw_remaining = 0;
-        }
-    }
-    else
-    {
-        DebugMessage(DEBUG_DCE_SMB, "Raw data: Read Raw\n");
-        DebugFormat(DEBUG_DCE_SMB, "Response Fid: 0x%04X\n", ftracker->fid_v1);
-
-        remove_rtracker = true;
-    }
-
-    // Only one raw read/write allowed
-    ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
-
-    if (ftracker->is_ipc)
-    {
-        // Maximum possible fragment length is 16 bit
-        if (nb_len > UINT16_MAX)
-            nb_len = UINT16_MAX;
-
-        DCE2_CoProcess(&ssd->sd, ftracker->fp_co_tracker, nb_ptr, (uint16_t)nb_len);
-    }
-    else
-    {
-        bool upload = DCE2_SsnFromClient(ssd->sd.wire_pkt) ? true : false;
-        DCE2_SmbProcessFileData(ssd, ftracker, nb_ptr, nb_len, upload);
-    }
-
-    if (remove_rtracker)
-    {
-        DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
-        ssd->cur_rtracker = nullptr;
-    }
-}
-
-static void DCE2_SmbDataFree(DCE2_SmbSsnData* ssd)
-{
-    if (ssd == nullptr)
-        return;
-
-    // FIXIT This tries to account for the situation where we never knew the file
-    // size and the TCP session was shutdown before an SMB_COM_CLOSE on the file.
-    // Possibly need to add callback to fileAPI since it may have already
-    // released it's resources.
-    //DCE2_SmbFinishFileAPI(ssd);
-
-    if (ssd->uids != nullptr)
-    {
-        DCE2_ListDestroy(ssd->uids);
-        ssd->uids = nullptr;
-    }
-
-    if (ssd->tids != nullptr)
-    {
-        DCE2_ListDestroy(ssd->tids);
-        ssd->tids = nullptr;
-    }
-
-    DCE2_SmbCleanFileTracker(&ssd->ftracker);
-    if (ssd->ftrackers != nullptr)
-    {
-        DCE2_ListDestroy(ssd->ftrackers);
-        ssd->ftrackers = nullptr;
-    }
-
-    DCE2_SmbCleanRequestTracker(&ssd->rtracker);
-    if (ssd->rtrackers != nullptr)
-    {
-        DCE2_QueueDestroy(ssd->rtrackers);
-        ssd->rtrackers = nullptr;
-    }
-
-    if (ssd->cli_seg != nullptr)
-    {
-        DCE2_BufferDestroy(ssd->cli_seg);
-        ssd->cli_seg = nullptr;
-    }
-
-    if (ssd->srv_seg != nullptr)
-    {
-        DCE2_BufferDestroy(ssd->srv_seg);
-        ssd->srv_seg = nullptr;
-    }
-
-    if (ssd->smb2_requests != nullptr)
-    {
-        DCE2_Smb2CleanRequests(ssd->smb2_requests);
-        ssd->smb2_requests = nullptr;
-    }
-}
-
-Dce2SmbFlowData::Dce2SmbFlowData() : FlowData(flow_id)
-{
-}
-
-Dce2SmbFlowData::~Dce2SmbFlowData()
-{
-    DCE2_SmbDataFree(&dce2_smb_session);
-}
-
-unsigned Dce2SmbFlowData::flow_id = 0;
-
-DCE2_SmbSsnData* get_dce2_smb_session_data(Flow* flow)
-{
-    Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(Dce2SmbFlowData::flow_id);
-    return fd ? &fd->dce2_smb_session : nullptr;
-}
-
-static DCE2_SmbSsnData* set_new_dce2_smb_session(Packet* p)
-{
-    Dce2SmbFlowData* fd = new Dce2SmbFlowData;
-    memset(&fd->dce2_smb_session,0,sizeof(DCE2_SmbSsnData));
-    p->flow->set_flow_data(fd);
-    return(&fd->dce2_smb_session);
-}
-
-static DCE2_SmbSsnData* dce2_create_new_smb_session(Packet* p, dce2SmbProtoConf* config)
-{
-    DCE2_SmbSsnData* dce2_smb_sess = nullptr;
-    Profile profile(dce2_smb_pstat_new_session);
-
-       DebugMessage(DEBUG_DCE_SMB, "DCE over SMB packet detected\n");
-       DebugMessage(DEBUG_DCE_SMB, "Creating new session\n");
-
-       dce2_smb_sess = set_new_dce2_smb_session(p);
-       if ( dce2_smb_sess )
-       {
-               dce2_smb_sess->dialect_index = DCE2_SENTINEL;
-               dce2_smb_sess->max_outstanding_requests = 10;  // Until Negotiate/SessionSetupAndX
-               dce2_smb_sess->cli_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-               dce2_smb_sess->srv_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-               dce2_smb_sess->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
-               dce2_smb_sess->uid = DCE2_SENTINEL;
-               dce2_smb_sess->tid = DCE2_SENTINEL;
-               dce2_smb_sess->ftracker.fid_v1 = DCE2_SENTINEL;
-               dce2_smb_sess->rtracker.mid = DCE2_SENTINEL;
-               dce2_smb_sess->max_file_depth = FileService::get_max_file_depth();
-
-               DCE2_ResetRopts(&dce2_smb_sess->sd.ropts);
-
-               dce2_smb_stats.smb_sessions++;
-               DebugFormat(DEBUG_DCE_SMB,"Created (%p)\n", (void*)dce2_smb_sess);
-
-               dce2_smb_sess->sd.trans = DCE2_TRANS_TYPE__SMB;
-               dce2_smb_sess->sd.server_policy = config->common.policy;
-               dce2_smb_sess->sd.client_policy = DCE2_POLICY__WINXP;
-               dce2_smb_sess->sd.wire_pkt = p;
-               dce2_smb_sess->sd.config = (void*)config;
-       }
-
-    return dce2_smb_sess;
-}
-
-static DCE2_SmbSsnData* dce2_handle_smb_session(Packet* p, dce2SmbProtoConf* config)
-{
-    Profile profile(dce2_smb_pstat_session);
-
-    DCE2_SmbSsnData* dce2_smb_sess =  get_dce2_smb_session_data(p->flow);
-
-    if (dce2_smb_sess == nullptr)
-    {
-        dce2_smb_sess = dce2_create_new_smb_session(p, config);
-    }
-
-    DebugFormat(DEBUG_DCE_SMB, "Session pointer: %p\n", (void*)dce2_smb_sess);
-
-    return dce2_smb_sess;
-}
-
-/********************************************************************
- * Function: DCE2_NbssHdrChecks()
- *
- * Purpose:
- *  Does validation of the NetBIOS header.  SMB will only run over
- *  the Session Message type.  On port 139, there is always an
- *  initial Session Request / Session Positive/Negative response
- *  followed by the normal SMB conversation, i.e. Negotiate,
- *  SessionSetupAndX, etc.
- *  Side effects are potential alerts for anomolous behavior.
- *
- * Arguments:
- *  DCE2_SmbSsnData * - the session data structure.
- *  const NbssHdr *   - pointer to the NetBIOS Session Service
- *                      header structure.  Size is already validated.
- *
- * Returns:
- *  DCE2_Ret  -  DCE2_RET__SUCCESS if all goes well and processing
- *               should continue.
- *               DCE2_RET__IGNORE if it's not something we need to
- *               look at.
- *               DCE2_RET__ERROR if an invalid NetBIOS Session
- *               Service type is found.
- *
- ********************************************************************/
-static DCE2_Ret DCE2_NbssHdrChecks(DCE2_SmbSsnData* ssd, const NbssHdr* nb_hdr)
-{
-    Packet* p = ssd->sd.wire_pkt;
-    bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (uint8_t*)nb_hdr);
-
-    DebugMessage(DEBUG_DCE_SMB, "NetBIOS Session Service type: ");
-
-    switch (NbssType(nb_hdr))
-    {
-    case NBSS_SESSION_TYPE__MESSAGE:
-        /* Only want to look at session messages */
-        DebugMessage(DEBUG_DCE_SMB, "Session Message\n");
-
-        if (!DCE2_SmbIsRawData(ssd))
-        {
-            uint32_t nb_len = NbssLen(nb_hdr);
-
-            if (nb_len == 0)
-                return DCE2_RET__IGNORE;
-
-            if (nb_len < sizeof(SmbNtHdr))
-            {
-                DebugFormat(DEBUG_DCE_SMB, "NetBIOS SS len(%zu) < SMB header len(%zu).\n",
-                    sizeof(SmbNtHdr), sizeof(NbssHdr) + nb_len);
-
-                if (is_seg_buf)
-                    DCE2_SmbSegAlert(ssd, DCE2_SMB_NB_LT_SMBHDR);
-                else
-                    dce_alert(GID_DCE2, DCE2_SMB_NB_LT_SMBHDR, (dce2CommonStats*)&dce2_smb_stats);
-
-                return DCE2_RET__IGNORE;
-            }
-        }
-
-        return DCE2_RET__SUCCESS;
-
-    case NBSS_SESSION_TYPE__REQUEST:
-        DebugMessage(DEBUG_DCE_SMB, "Session Request\n");
-        if (DCE2_SsnFromServer(p))
-        {
-            if (is_seg_buf)
-                DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
-            else
-                dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        break;
-
-    case NBSS_SESSION_TYPE__POS_RESPONSE:
-    case NBSS_SESSION_TYPE__NEG_RESPONSE:
-    case NBSS_SESSION_TYPE__RETARGET_RESPONSE:
-        if (DCE2_SsnFromClient(p))
-        {
-            if (is_seg_buf)
-                DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
-            else
-                dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats);
-        }
-
-        break;
-
-    case NBSS_SESSION_TYPE__KEEP_ALIVE:
-        DebugMessage(DEBUG_DCE_SMB, "Session Keep Alive\n");
-        break;
-
-    default:
-        DebugFormat(DEBUG_DCE_SMB,
-            "Invalid Session Service type: 0x%02X\n", NbssType(nb_hdr));
-
-        if (is_seg_buf)
-            DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
-        else
-            dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats);
-
-        return DCE2_RET__ERROR;
-    }
-
-    return DCE2_RET__IGNORE;
-}
-
-
-// This is the main entry point for SMB1 processing.
-static void DCE2_Smb1Process(DCE2_SmbSsnData* ssd)
-{
-    DebugMessage(DEBUG_DCE_SMB, "Processing SMB packet.\n");
-    dce2_smb_stats.smb_pkts++;
-
-    const Packet* p = ssd->sd.wire_pkt;
-    const uint8_t* data_ptr = p->data;
-    uint16_t data_len = p->dsize;
-    DCE2_Buffer** seg_buf = DCE2_SmbGetSegBuffer(ssd);
-
-    /* Have to account for segmentation.  Even though stream will give
-     * us larger chunks, we might end up in the middle of something */
-    while (data_len > 0)
-    {
-        // We are ignoring an entire PDU or junk data so state should be NETBIOS_HEADER
-        // Note that it could be TCP segmented so ignore_bytes could be greater than
-        // the amount of data we have
-        uint32_t* ignore_bytes = DCE2_SmbGetIgnorePtr(ssd);
-        if (*ignore_bytes)
-        {
-            DebugFormat(DEBUG_DCE_SMB, "Ignoring %u bytes\n", *ignore_bytes);
-
-            if (data_len <= *ignore_bytes)
-            {
-                *ignore_bytes -= data_len;
-                return;
-            }
-            else
-            {
-                /* ignore bytes is less than UINT16_MAX */
-                DCE2_MOVE(data_ptr, data_len, (uint16_t)*ignore_bytes);
-                *ignore_bytes = 0;
-            }
-        }
-
-        DCE2_SmbDataState* data_state = DCE2_SmbGetDataState(ssd);
-        DCE2_SmbRequestTracker* rtracker = nullptr;
-        switch (*data_state)
-        {
-        // This state is to verify it's a NetBIOS Session Message packet
-        // and to get the length of the SMB PDU.  Also does the SMB junk
-        // data check.  If it's not a Session Message the data isn't
-        // processed since it won't be carrying SMB.
-        case DCE2_SMB_DATA_STATE__NETBIOS_HEADER:
-        {
-            uint32_t data_need = sizeof(NbssHdr);
-
-            // See if there is enough data to process the NetBIOS header
-            if (data_len < data_need)
-            {
-                DebugFormat(DEBUG_DCE_SMB, "Data len(%hu) < NetBIOS SS header(%u). "
-                    "Queueing data.\n", data_len, data_need);
-
-                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
-                    data_len, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                }
-
-                return;
-            }
-
-            // Set the NetBIOS header structure
-            NbssHdr* nb_hdr;
-            if (DCE2_BufferIsEmpty(*seg_buf))
-            {
-                nb_hdr = (NbssHdr*)data_ptr;
-            }
-            else
-            {
-                // If data already buffered add the remainder for the
-                // size of the NetBIOS header
-                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
-                    data_need, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                    return;
-                }
-
-                nb_hdr = (NbssHdr*)DCE2_BufferData(*seg_buf);
-            }
-
-            uint32_t nb_len = NbssLen(nb_hdr);
-
-            DebugFormat(DEBUG_DCE_SMB, "NetBIOS PDU length: %u\n", nb_len);
-
-            DCE2_Ret status = DCE2_NbssHdrChecks(ssd, nb_hdr);
-            if (status != DCE2_RET__SUCCESS)
-            {
-                DebugMessage(DEBUG_DCE_SMB, "Not a NetBIOS Session Message.\n");
-
-                if (status == DCE2_RET__IGNORE)
-                {
-                    DebugMessage(DEBUG_DCE_SMB, "Valid NetBIOS header "
-                        "type so ignoring NetBIOS length bytes.\n");
-                    *ignore_bytes = data_need + nb_len;
-                }
-                else      // nb_ret == DCE2_RET__ERROR, i.e. invalid NetBIOS type
-                {
-                    DebugMessage(DEBUG_DCE_SMB, "Not a valid NetBIOS "
-                        "header type so trying to find \\xffSMB to "
-                        "determine how many bytes to ignore.\n");
-                    *ignore_bytes = DCE2_IgnoreJunkData(data_ptr, data_len, data_need + nb_len);
-                }
-
-                DCE2_BufferEmpty(*seg_buf);
-                dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
-                continue;
-            }
-
-            if (!DCE2_BufferIsEmpty(*seg_buf))
-                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
-
-            switch (ssd->pdu_state)
-            {
-            case DCE2_SMB_PDU_STATE__COMMAND:
-                *data_state = DCE2_SMB_DATA_STATE__SMB_HEADER;
-                break;
-            case DCE2_SMB_PDU_STATE__RAW_DATA:
-                *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
-                // Continue here because of fall through below
-                continue;
-            default:
-                DebugFormat(DEBUG_DCE_SMB,"%s(%d) Invalid SMB PDU "
-                    "state: %d\n", __FILE__, __LINE__, ssd->pdu_state);
-                return;
-            }
-        }
-
-        // Fall through for DCE2_SMB_DATA_STATE__SMB_HEADER
-        // This is the normal progression without segmentation.
-
-        // This state is to do validation checks on the SMB header and
-        // more importantly verify it's data that needs to be inspected.
-        // If the TID in the SMB header is not referring to the IPC share
-        // there won't be any DCE/RPC traffic associated with it.
-        case DCE2_SMB_DATA_STATE__SMB_HEADER:
-        {
-            uint32_t data_need = (sizeof(NbssHdr) + sizeof(SmbNtHdr)) - DCE2_BufferLength(
-                *seg_buf);
-
-            // See if there is enough data to process the SMB header
-            if (data_len < data_need)
-            {
-                DebugFormat(DEBUG_DCE_SMB, "Data len (%hu) < "
-                    "NetBIOS SS header + SMB header (%u). Queueing data.\n",
-                    data_len, data_need);
-
-                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
-                    sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                    *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-                }
-
-                return;
-            }
-
-            // Set the SMB header structure
-            SmbNtHdr* smb_hdr;
-            if (DCE2_BufferIsEmpty(*seg_buf))
-            {
-                smb_hdr = (SmbNtHdr*)(data_ptr + sizeof(NbssHdr));
-            }
-            else
-            {
-                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
-                    sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                    *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-                    return;
-                }
-
-                smb_hdr = (SmbNtHdr*)(DCE2_BufferData(*seg_buf) + sizeof(NbssHdr));
-            }
-
-            if (SmbId(smb_hdr) == DCE2_SMB2_ID)
-            {
-                ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
-                if (!DCE2_GcIsLegacyMode((dce2SmbProtoConf*)ssd->sd.config))
-                {
-                    DCE2_Smb2InitFileTracker(&(ssd->ftracker), false, 0);
-                    DCE2_Smb2Process(ssd);
-                }
-                return;
-            }
-
-            // See if this is something we need to inspect
-            rtracker = DCE2_SmbInspect(ssd, smb_hdr);
-            if (rtracker == nullptr)
-            {
-                DebugMessage(DEBUG_DCE_SMB, "Not inspecting SMB packet.\n");
-
-                if (DCE2_BufferIsEmpty(*seg_buf))
-                {
-                    *ignore_bytes = sizeof(NbssHdr) + NbssLen((NbssHdr*)data_ptr);
-                }
-                else
-                {
-                    *ignore_bytes = (NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf))
-                        - sizeof(SmbNtHdr)) + data_need;
-                    DCE2_BufferEmpty(*seg_buf);
-                }
-
-                *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-                dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
-                continue;
-            }
-
-            // Check the SMB header for anomolies
-            if (DCE2_SmbHdrChecks(ssd, smb_hdr) != DCE2_RET__SUCCESS)
-            {
-                DebugMessage(DEBUG_DCE_SMB, "Bad SMB header.\n");
-
-                if (DCE2_BufferIsEmpty(*seg_buf))
-                {
-                    *ignore_bytes = sizeof(NbssHdr) + NbssLen((NbssHdr*)data_ptr);
-                }
-                else
-                {
-                    *ignore_bytes = (NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf))
-                        - sizeof(SmbNtHdr)) + data_need;
-                    DCE2_BufferEmpty(*seg_buf);
-                }
-
-                *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-
-                dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
-                continue;
-            }
-
-            if (!DCE2_BufferIsEmpty(*seg_buf))
-                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
-
-            *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
-        }
-
-        // Fall through
-
-        // This state ensures that we have the entire PDU before continuing
-        // to process.
-        case DCE2_SMB_DATA_STATE__NETBIOS_PDU:
-        {
-            uint32_t nb_len;
-            uint32_t data_need;
-
-            if (DCE2_BufferIsEmpty(*seg_buf))
-            {
-                nb_len = NbssLen((NbssHdr*)data_ptr);
-                data_need = sizeof(NbssHdr) + nb_len;
-            }
-            else
-            {
-                nb_len = NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf));
-                data_need = (sizeof(NbssHdr) + nb_len) - DCE2_BufferLength(*seg_buf);
-            }
-
-            /* It's something we want to inspect so make sure we have the full NBSS packet */
-            if (data_len < data_need)
-            {
-                DebugFormat(DEBUG_DCE_SMB, "Data len(%hu) < "
-                    "NetBIOS SS header + NetBIOS len(%zu). "
-                    "Queueing data.\n", data_len, sizeof(NbssHdr) + nb_len);
-
-                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
-                    sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                    *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-                }
-
-                return;
-            }
-
-            // data_len >= data_need which means data_need <= UINT16_MAX
-            // So casts below of data_need to uint16_t are okay.
-
-            *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
-
-            const uint8_t* nb_ptr;
-            if (DCE2_BufferIsEmpty(*seg_buf))
-            {
-                nb_ptr = data_ptr;
-                nb_len = data_need;
-                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
-            }
-            else
-            {
-                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
-                    sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                    DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
-                    continue;
-                }
-
-                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
-
-                nb_ptr = DCE2_BufferData(*seg_buf);
-                nb_len = DCE2_BufferLength(*seg_buf);
-
-                // Get reassembled packet
-                Packet* rpkt = DCE2_SmbGetRpkt(ssd, &nb_ptr, &nb_len,
-                    DCE2_RPKT_TYPE__SMB_SEG);
-                if (rpkt == nullptr)
-                {
-                    DCE2_BufferEmpty(*seg_buf);
-                    continue;
-                }
-
-                nb_ptr = DCE2_BufferData(*seg_buf);
-                nb_len = DCE2_BufferLength(*seg_buf);
-
-                DebugFormat(DEBUG_DCE_SMB,
-                    "Segmentation buffer: len: %u, size: %u\n",
-                    DCE2_BufferLength(*seg_buf), DCE2_BufferSize(*seg_buf));
-
-                if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
-                    dce2_smb_stats.smb_cli_seg_reassembled++;
-                else
-                    dce2_smb_stats.smb_srv_seg_reassembled++;
-
-                DebugMessage(DEBUG_DCE_SMB, "TCP reassembled SMB PDU\n");
-                DCE2_PrintPktData(rpkt->data, rpkt->dsize);
-            }
-
-            switch (ssd->pdu_state)
-            {
-            case DCE2_SMB_PDU_STATE__COMMAND:
-            {
-                SmbNtHdr* smb_hdr = (SmbNtHdr*)(nb_ptr + sizeof(NbssHdr));
-                DCE2_MOVE(nb_ptr, nb_len, (sizeof(NbssHdr) + sizeof(SmbNtHdr)));
-                ssd->cur_rtracker = (rtracker != nullptr)
-                    ? rtracker : DCE2_SmbFindRequestTracker(ssd, smb_hdr);
-                if (ssd->cur_rtracker != nullptr)
-                    DCE2_SmbProcessCommand(ssd, smb_hdr, nb_ptr, nb_len);
-                break;
-            }
-
-            case DCE2_SMB_PDU_STATE__RAW_DATA:
-                DCE2_MOVE(nb_ptr, nb_len, sizeof(NbssHdr));
-                if (ssd->cur_rtracker != nullptr)
-                    DCE2_SmbProcessRawData(ssd, nb_ptr, nb_len);
-                // Only one raw read or write
-                ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
-                break;
-            default:
-                DebugFormat(DEBUG_DCE_SMB, "%s(%d) Invalid SMB PDU "
-                    "state: %d\n", __FILE__, __LINE__, ssd->pdu_state);
-                return;
-            }
-
-            if (!DCE2_BufferIsEmpty(*seg_buf))
-            {
-                DCE2_SmbReturnRpkt(ssd);
-                DCE2_BufferDestroy(*seg_buf);
-                *seg_buf = nullptr;
-            }
-
-            break;
-        }
-
-        default:
-            DebugFormat(DEBUG_DCE_SMB, "%s(%d) Invalid SMB Data "
-                "state: %d\n", __FILE__, __LINE__, *data_state);
-            return;
-        }
-    }
-}
-
-// This is the main entry point for SMB processing
-static void DCE2_SmbProcess(DCE2_SmbSsnData* ssd)
-{
-    if (DCE2_GcIsLegacyMode((dce2SmbProtoConf*)ssd->sd.config))
-    {
-        DCE2_Smb1Process(ssd);
-        return;
-    }
-
-    Packet* p = ssd->sd.wire_pkt;
-    DCE2_SmbVersion smb_version = DCE2_Smb2Version(p);
-    if (smb_version == DCE2_SMB_VERISON_1)
-    {
-        if ((ssd->sd.flags & DCE2_SSN_FLAG__SMB2))
-        {
-            DebugMessage(DEBUG_DCE_SMB, "SMB1 packet detected!\n");
-            ssd->sd.flags &= ~DCE2_SSN_FLAG__SMB2;
-            DCE2_SmbCleanFileTracker(&(ssd->ftracker));
-            ssd->ftracker.is_smb2 = false;
-        }
-    }
-    else if (smb_version == DCE2_SMB_VERISON_2)
-    {
-        if (!(ssd->sd.flags & DCE2_SSN_FLAG__SMB2))
-        {
-            DebugMessage(DEBUG_DCE_SMB, "SMB2 packet detected!\n");
-            DCE2_SmbCleanFileTracker(&(ssd->ftracker));
-            DCE2_Smb2InitFileTracker(&(ssd->ftracker), 0, 0);
-            ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
-        }
-    }
-
-    if (ssd->sd.flags & DCE2_SSN_FLAG__SMB2)
-        DCE2_Smb2Process(ssd);
-    else
-        DCE2_Smb1Process(ssd);
-}
-
-/********************************************************************
- * Function: DCE2_SmbInitGlobals()
- *
- * Purpose:
- *  Initializes global variables for SMB processing.
- *  Sets up the functions and valid word and byte counts for SMB
- *  commands.
- *  Sets up AndX chain mappings and valid command chaining for
- *  supported policies.
- *
- * Arguments: None
- *
- * Returns: None
- *
- ********************************************************************/
-static void DCE2_SmbInitGlobals()
-{
-    memset(&smb_wcts, 0, sizeof(smb_wcts));
-    memset(&smb_bccs, 0, sizeof(smb_bccs));
-
-    // Sets up the function to call for the command and valid word and byte
-    // counts for the command.  Ensuring valid word and byte counts is very
-    // important to processing the command as it will assume the command is
-    // legitimate and can access data that is acutally there.  Note that
-    // commands with multiple word counts indicate a different command
-    // structure, however most, if not all just have an extended version
-    // of the structure for which the extended part isn't used.  If the
-    // extended part of a command structure needs to be used, be sure to
-    // check the word count in the command function before accessing data
-    // in the extended version of the command structure.
-    for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
-    {
-        switch (com)
-        {
-        case SMB_COM_OPEN:
-            smb_com_funcs[com] = DCE2_SmbOpen;
-
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_CREATE:
-            smb_com_funcs[com] = DCE2_SmbCreate;
-
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_CLOSE:
-            smb_com_funcs[com] = DCE2_SmbClose;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_RENAME:
-            smb_com_funcs[com] = DCE2_SmbRename;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 1);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 4, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_READ:
-            smb_com_funcs[com] = DCE2_SmbRead;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
-            break;
-        case SMB_COM_WRITE:
-            smb_com_funcs[com] = DCE2_SmbWrite;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_CREATE_NEW:
-            smb_com_funcs[com] = DCE2_SmbCreateNew;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_LOCK_AND_READ:
-            smb_com_funcs[com] = DCE2_SmbLockAndRead;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
-            break;
-        case SMB_COM_WRITE_AND_UNLOCK:
-            smb_com_funcs[com] = DCE2_SmbWriteAndUnlock;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_READ_RAW:
-            smb_com_funcs[com] = DCE2_SmbReadRaw;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
-            // With optional OffsetHigh
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            // Response is raw data, i.e. without SMB
-            break;
-        case SMB_COM_WRITE_RAW:
-            smb_com_funcs[com] = DCE2_SmbWriteRaw;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
-            // With optional OffsetHigh
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
-            // Interim server response
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_WRITE_COMPLETE:
-            // Final server response to SMB_COM_WRITE_RAW
-            smb_com_funcs[com] = DCE2_SmbWriteComplete;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_TRANSACTION:
-            smb_com_funcs[com] = DCE2_SmbTransaction;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            // Word count depends on setup count
-            //for (i = 14; i < 256; i++)
-            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
-            // In reality, all subcommands of SMB_COM_TRANSACTION requests
-            // have a setup count of 2 words.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 16);
-
-            // \PIPE\LANMAN
-            // Not something the preprocessor is looking at as it
-            // doesn't carry DCE/RPC but don't want to false positive
-            // on the preprocessor event.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
-
-            // Word count depends on setup count
-            //for (i = 10; i < 256; i++)
-            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
-            // In reality, all subcommands of SMB_COM_TRANSACTION responses
-            // have a setup count of 0 words.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
-
-            // Interim server response
-            // When client sends an incomplete transaction and needs to
-            // send TransactionSecondary requests to complete request.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
-
-            // Exception will be made for Interim responses when
-            // byte count is checked.
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_TRANSACTION_SECONDARY:
-            smb_com_funcs[com] = DCE2_SmbTransactionSecondary;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
-            // Response is an SMB_COM_TRANSACTION
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            break;
-        case SMB_COM_WRITE_AND_CLOSE:
-            smb_com_funcs[com] = DCE2_SmbWriteAndClose;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 6);
-            // For some reason MS-CIFS specifies a version of this command
-            // with 6 extra words (12 bytes) of reserved, i.e. useless data.
-            // Maybe had intentions of extending and defining the data at
-            // some point, but there is no documentation that I could find
-            // that does.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_OPEN_ANDX:
-            smb_com_funcs[com] = DCE2_SmbOpenAndX;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 15);
-            // Extended response
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
-            // MS-SMB says that Windows 2000, XP and Vista set this to
-            // some arbitrary value that is ignored on receipt.
-            //DCE2_SmbSetValidByteCount(com, SMB_TYPE__RESPONSE, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_READ_ANDX:
-            smb_com_funcs[com] = DCE2_SmbReadAndX;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
-            // With optional OffsetHigh
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 12);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_WRITE_ANDX:
-            smb_com_funcs[com] = DCE2_SmbWriteAndX;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
-            // With optional OffsetHigh
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 6);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_TRANSACTION2:
-            smb_com_funcs[com] = DCE2_SmbTransaction2;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            // Word count depends on setup count
-            //for (i = 14; i < 256; i++)
-            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
-            // In reality, all subcommands of SMB_COM_TRANSACTION2
-            // requests have a setup count of 1 word.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
-
-            // Word count depends on setup count
-            //for (i = 10; i < 256; i++)
-            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
-            // In reality, all subcommands of SMB_COM_TRANSACTION2
-            // responses have a setup count of 0 or 1 word.
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 11);
-
-            // Interim server response
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
-
-            // Exception will be made for Interim responses when
-            // byte count is checked.
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_TRANSACTION2_SECONDARY:
-            smb_com_funcs[com] = DCE2_SmbTransaction2Secondary;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 9);
-            // Response is an SMB_COM_TRANSACTION2
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            break;
-        case SMB_COM_TREE_CONNECT:
-            smb_com_funcs[com] = DCE2_SmbTreeConnect;
-            smb_deprecated_coms[com] = true;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 6, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_TREE_DISCONNECT:
-            smb_com_funcs[com] = DCE2_SmbTreeDisconnect;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_NEGOTIATE:
-            smb_com_funcs[com] = DCE2_SmbNegotiate;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 13);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 17);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
-            // This can vary depending on dialect so just set wide.
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_SESSION_SETUP_ANDX:
-            smb_com_funcs[com] = DCE2_SmbSessionSetupAndX;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 13);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 4);
-
-            // These can vary so just set wide.
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_LOGOFF_ANDX:
-            smb_com_funcs[com] = DCE2_SmbLogoffAndX;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
-            // Windows responds to a LogoffAndX => SessionSetupAndX with just a
-            // LogoffAndX and with the word count field containing 3, but only
-            // has 2 words
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            break;
-        case SMB_COM_TREE_CONNECT_ANDX:
-            smb_com_funcs[com] = DCE2_SmbTreeConnectAndX;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 4);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
-            // Extended response
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 2, UINT16_MAX);
-            break;
-        case SMB_COM_NT_TRANSACT:
-            smb_com_funcs[com] = DCE2_SmbNtTransact;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            // Word count depends on setup count
-            // In reality, all subcommands of SMB_COM_NT_TRANSACT
-            // requests have a setup count of 0 or 4 words.
-            //for (i = 19; i < 256; i++)
-            //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, i);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 19);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 23);
-
-            // Word count depends on setup count
-            // In reality, all subcommands of SMB_COM_NT_TRANSACT
-            // responses have a setup count of 0 or 1 word.
-            //for (i = 18; i < 256; i++)
-            //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, i);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 18);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
-
-            // Interim server response
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
-
-            // Exception will be made for Interim responses when
-            // byte count is checked.
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        case SMB_COM_NT_TRANSACT_SECONDARY:
-            smb_com_funcs[com] = DCE2_SmbNtTransactSecondary;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 18);
-            // Response is an SMB_COM_NT_TRANSACT
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            break;
-        case SMB_COM_NT_CREATE_ANDX:
-            smb_com_funcs[com] = DCE2_SmbNtCreateAndX;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 24);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 34);
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 26);
-            // Extended response - though there are actually 50 words
-            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 42);
-
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
-            // MS-SMB indicates that this field should be 0 but may be
-            // sent uninitialized so basically ignore it.
-            //DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        default:
-            smb_com_funcs[com] = nullptr;
-            smb_deprecated_coms[com] = false;
-            smb_unusual_coms[com] = false;
-            // Just set to all valid since the specific command won't
-            // be processed.  Don't want to false positive on these.
-            for (int i = 0; i < 256; i++)
-            {
-                DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, (uint8_t)i);
-                DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, (uint8_t)i);
-            }
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
-            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
-            break;
-        }
-    }
-
-    // Maps commands for use in quickly determining if a command
-    // is chainable and what command it is.
-    for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
-    {
-        switch (com)
-        {
-        case SMB_COM_SESSION_SETUP_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__SESSION_SETUP_ANDX;
-            break;
-        case SMB_COM_LOGOFF_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__LOGOFF_ANDX;
-            break;
-        case SMB_COM_TREE_CONNECT_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__TREE_CONNECT_ANDX;
-            break;
-        case SMB_COM_OPEN_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__OPEN_ANDX;
-            break;
-        case SMB_COM_NT_CREATE_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__NT_CREATE_ANDX;
-            break;
-        case SMB_COM_WRITE_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__WRITE_ANDX;
-            break;
-        case SMB_COM_READ_ANDX:
-            smb_chain_map[com] = SMB_ANDX_COM__READ_ANDX;
-            break;
-        default:
-            smb_chain_map[com] = SMB_ANDX_COM__NONE;
-            break;
-        }
-    }
-
-    // Sets up the valid command chaining combinations per policy
-    for (int policy = 0; policy < DCE2_POLICY__MAX; policy++)
-    {
-        for (int andx = SMB_ANDX_COM__NONE; andx < SMB_ANDX_COM__MAX; andx++)
-        {
-            /* com is the chained command or com2 */
-            for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
-            {
-                DCE2_SmbComFunc com_func = nullptr;
-
-                switch (policy)
-                {
-                case DCE2_POLICY__WIN2000:
-                case DCE2_POLICY__WINXP:
-                case DCE2_POLICY__WINVISTA:
-                case DCE2_POLICY__WIN2003:
-                case DCE2_POLICY__WIN2008:
-                case DCE2_POLICY__WIN7:
-                    switch (andx)
-                    {
-                    case SMB_ANDX_COM__SESSION_SETUP_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_TREE_CONNECT_ANDX:
-                        case SMB_COM_OPEN:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_CREATE:
-                        case SMB_COM_CREATE_NEW:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        case SMB_COM_TRANSACTION:
-                            if (policy == DCE2_POLICY__WIN2000)
-                                com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__LOGOFF_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_TREE_CONNECT_ANDX:               // Only for responses
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__TREE_CONNECT_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_OPEN:
-                        case SMB_COM_CREATE:
-                        case SMB_COM_CREATE_NEW:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        case SMB_COM_TRANSACTION:
-                            if (policy == DCE2_POLICY__WIN2000)
-                                com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__OPEN_ANDX:
-                        break;
-                    case SMB_ANDX_COM__NT_CREATE_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_READ_ANDX:              // Only for normal files
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__WRITE_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_CLOSE:
-                        case SMB_COM_WRITE_ANDX:
-                        case SMB_COM_READ:
-                        case SMB_COM_READ_ANDX:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__READ_ANDX:
-                        break;
-                    default:
-                        break;
-                    }
-                    break;
-                case DCE2_POLICY__SAMBA:
-                case DCE2_POLICY__SAMBA_3_0_37:
-                case DCE2_POLICY__SAMBA_3_0_22:
-                case DCE2_POLICY__SAMBA_3_0_20:
-                    switch (andx)
-                    {
-                    case SMB_ANDX_COM__SESSION_SETUP_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_LOGOFF_ANDX:
-                        case SMB_COM_TREE_CONNECT:
-                        case SMB_COM_TREE_CONNECT_ANDX:
-                        case SMB_COM_TREE_DISCONNECT:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_NT_CREATE_ANDX:
-                        case SMB_COM_CLOSE:
-                        case SMB_COM_READ_ANDX:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        case SMB_COM_WRITE:
-                            if ((policy == DCE2_POLICY__SAMBA_3_0_22)
-                                || (policy == DCE2_POLICY__SAMBA_3_0_20))
-                                com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__LOGOFF_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_TREE_DISCONNECT:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__TREE_CONNECT_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_LOGOFF_ANDX:
-                        case SMB_COM_TREE_DISCONNECT:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_NT_CREATE_ANDX:
-                        case SMB_COM_CLOSE:
-                        case SMB_COM_WRITE:
-                        case SMB_COM_READ_ANDX:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__OPEN_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_LOGOFF_ANDX:
-                        case SMB_COM_TREE_CONNECT:
-                        case SMB_COM_TREE_CONNECT_ANDX:
-                        case SMB_COM_TREE_DISCONNECT:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_NT_CREATE_ANDX:
-                        case SMB_COM_CLOSE:
-                        case SMB_COM_WRITE:
-                        case SMB_COM_READ_ANDX:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__NT_CREATE_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_TREE_CONNECT:
-                        case SMB_COM_TREE_CONNECT_ANDX:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_NT_CREATE_ANDX:
-                        case SMB_COM_WRITE:
-                        case SMB_COM_READ_ANDX:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        case SMB_COM_LOGOFF_ANDX:
-                        case SMB_COM_TREE_DISCONNECT:
-                        case SMB_COM_CLOSE:
-                            if ((policy == DCE2_POLICY__SAMBA)
-                                || (policy == DCE2_POLICY__SAMBA_3_0_37))
-                                com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__WRITE_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_LOGOFF_ANDX:
-                        case SMB_COM_TREE_CONNECT:
-                        case SMB_COM_TREE_CONNECT_ANDX:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_NT_CREATE_ANDX:
-                        case SMB_COM_CLOSE:
-                        case SMB_COM_WRITE:
-                        case SMB_COM_READ_ANDX:
-                        case SMB_COM_WRITE_ANDX:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    case SMB_ANDX_COM__READ_ANDX:
-                        switch (com)
-                        {
-                        case SMB_COM_SESSION_SETUP_ANDX:
-                        case SMB_COM_WRITE:
-                            com_func = smb_com_funcs[com];
-                            break;
-                        case SMB_COM_LOGOFF_ANDX:
-                        case SMB_COM_TREE_CONNECT:
-                        case SMB_COM_TREE_CONNECT_ANDX:
-                        case SMB_COM_TREE_DISCONNECT:
-                        case SMB_COM_OPEN_ANDX:
-                        case SMB_COM_NT_CREATE_ANDX:
-                        case SMB_COM_CLOSE:
-                        case SMB_COM_READ_ANDX:
-                            if ((policy == DCE2_POLICY__SAMBA)
-                                || (policy == DCE2_POLICY__SAMBA_3_0_37))
-                                com_func = smb_com_funcs[com];
-                            break;
-                        default:
-                            break;
-                        }
-                        break;
-                    default:
-                        break;
-                    }
-                    break;
-                default:
-                    break;
-                }
-
-                smb_chain_funcs[policy][andx][com] = com_func;
-            }
-        }
-    }
-}
+const char* get_smb_com_string(uint8_t b)
+{ return smb_com_strings[b]; }
+#endif
 
 //-------------------------------------------------------------------------
 // class stuff
index beaca6bf1041b09762b8e8cb5840991c1510b7bc..9947aef6aad1c1f8f3ef6ce047afaac091036d59 100644 (file)
@@ -16,7 +16,7 @@
 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //--------------------------------------------------------------------------
 
-//dce_smb.h author Rashmi Pitre <rrp@cisco.com>
+// dce_smb.h author Rashmi Pitre <rrp@cisco.com>
 // based on work by Todd Wease
 
 #ifndef DCE_SMB_H
@@ -27,6 +27,8 @@
 #include "profiler/profiler_defs.h"
 
 #include "dce_co.h"
+#include "smb_common.h"
+#include "smb_message.h"
 
 #define DCE2_SMB_NAME "dce_smb"
 #define DCE2_SMB_HELP "dce over smb inspection"
 #define DCE2_SMB_BAD_NEXT_COMMAND_OFFSET_STR \
     "SMB - Next command specified in SMB2 header is beyond payload boundary"
 
-#define SMB_MAX_NUM_COMS   256
-
-#define SMB_FILE_TYPE_DISK               0x0000
-#define SMB_FILE_TYPE_BYTE_MODE_PIPE     0x0001
-#define SMB_FILE_TYPE_MESSAGE_MODE_PIPE  0x0002
-#define SMB_FILE_TYPE_PRINTER            0x0003
-#define SMB_FILE_TYPE_COMMON_DEVICE      0x0004
-
-#define SMB_FILE_ATTRIBUTE_NORMAL       0x0000
-#define SMB_FILE_ATTRIBUTE_READONLY     0x0001
-#define SMB_FILE_ATTRIBUTE_HIDDEN       0x0002
-#define SMB_FILE_ATTRIBUTE_SYSTEM       0x0004
-#define SMB_FILE_ATTRIBUTE_VOLUME       0x0008
-#define SMB_FILE_ATTRIBUTE_DIRECTORY    0x0010
-#define SMB_FILE_ATTRIBUTE_ARCHIVE      0x0020
-#define SMB_SEARCH_ATTRIBUTE_READONLY   0x0100
-#define SMB_SEARCH_ATTRIBUTE_HIDDEN     0x0200
-#define SMB_SEARCH_ATTRIBUTE_SYSTEM     0x0400
-#define SMB_SEARCH_ATTRIBUTE_DIRECTORY  0x1000
-#define SMB_SEARCH_ATTRIBUTE_ARCHIVE    0x2000
-#define SMB_FILE_ATTRIBUTE_OTHER        0xC8C0   // Reserved
-
-#define SMB_EXT_FILE_ATTR_READONLY    0x00000001
-#define SMB_EXT_FILE_ATTR_HIDDEN      0x00000002
-#define SMB_EXT_FILE_ATTR_SYSTEM      0x00000004
-#define SMB_EXT_FILE_ATTR_DIRECTORY   0x00000010
-#define SMB_EXT_FILE_ATTR_ARCHIVE     0x00000020
-#define SMB_EXT_FILE_ATTR_NORMAL      0x00000080
-#define SMB_EXT_FILE_ATTR_TEMPORARY   0x00000100
-#define SMB_EXT_FILE_ATTR_COMPRESSED  0x00000800
-#define SMB_EXT_FILE_POSIX_SEMANTICS  0x01000000
-#define SMB_EXT_FILE_BACKUP_SEMANTICS 0x02000000
-#define SMB_EXT_FILE_DELETE_ON_CLOSE  0x04000000
-#define SMB_EXT_FILE_SEQUENTIAL_SCAN  0x08000000
-#define SMB_EXT_FILE_RANDOM_ACCESS    0x10000000
-#define SMB_EXT_FILE_NO_BUFFERING     0x20000000
-#define SMB_EXT_FILE_WRITE_THROUGH    0x80000000
-
 struct dce2SmbStats
 {
     PegCount events;
@@ -247,178 +211,6 @@ extern THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_file_api;
 extern THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_fingerprint;
 extern THREAD_LOCAL ProfileStats dce2_smb_pstat_smb_negotiate;
 
-#define NBSS_SESSION_TYPE__MESSAGE            0x00
-#define NBSS_SESSION_TYPE__REQUEST            0x81
-#define NBSS_SESSION_TYPE__POS_RESPONSE       0x82
-#define NBSS_SESSION_TYPE__NEG_RESPONSE       0x83
-#define NBSS_SESSION_TYPE__RETARGET_RESPONSE  0x84
-#define NBSS_SESSION_TYPE__KEEP_ALIVE         0x85
-
-#define DCE2_SMB_ID   0xff534d42  /* \xffSMB */
-#define DCE2_SMB2_ID  0xfe534d42  /* \xfeSMB */
-
-// MS-FSCC Section 2.1.5 - Pathname
-#define DCE2_SMB_MAX_PATH_LEN  32760
-#define DCE2_SMB_MAX_COMP_LEN    255
-
-/* SMB command codes */
-#define SMB_COM_CREATE_DIRECTORY 0x00
-#define SMB_COM_DELETE_DIRECTORY 0x01
-#define SMB_COM_OPEN 0x02
-#define SMB_COM_CREATE 0x03
-#define SMB_COM_CLOSE 0x04
-#define SMB_COM_FLUSH 0x05
-#define SMB_COM_DELETE 0x06
-#define SMB_COM_RENAME 0x07
-#define SMB_COM_QUERY_INFORMATION 0x08
-#define SMB_COM_SET_INFORMATION 0x09
-#define SMB_COM_READ 0x0A
-#define SMB_COM_WRITE 0x0B
-#define SMB_COM_LOCK_BYTE_RANGE 0x0C
-#define SMB_COM_UNLOCK_BYTE_RANGE 0x0D
-#define SMB_COM_CREATE_TEMPORARY 0x0E
-#define SMB_COM_CREATE_NEW 0x0F
-#define SMB_COM_CHECK_DIRECTORY 0x10
-#define SMB_COM_PROCESS_EXIT 0x11
-#define SMB_COM_SEEK 0x12
-#define SMB_COM_LOCK_AND_READ 0x13
-#define SMB_COM_WRITE_AND_UNLOCK 0x14
-#define SMB_COM_READ_RAW 0x1A
-#define SMB_COM_READ_MPX 0x1B
-#define SMB_COM_READ_MPX_SECONDARY 0x1C
-#define SMB_COM_WRITE_RAW 0x1D
-#define SMB_COM_WRITE_MPX 0x1E
-#define SMB_COM_WRITE_MPX_SECONDARY 0x1F
-#define SMB_COM_WRITE_COMPLETE 0x20
-#define SMB_COM_QUERY_SERVER 0x21
-#define SMB_COM_SET_INFORMATION2 0x22
-#define SMB_COM_QUERY_INFORMATION2 0x23
-#define SMB_COM_LOCKING_ANDX 0x24
-#define SMB_COM_TRANSACTION 0x25
-#define SMB_COM_TRANSACTION_SECONDARY 0x26
-#define SMB_COM_IOCTL 0x27
-#define SMB_COM_IOCTL_SECONDARY 0x28
-#define SMB_COM_COPY 0x29
-#define SMB_COM_MOVE 0x2A
-#define SMB_COM_ECHO 0x2B
-#define SMB_COM_WRITE_AND_CLOSE 0x2C
-#define SMB_COM_OPEN_ANDX 0x2D
-#define SMB_COM_READ_ANDX 0x2E
-#define SMB_COM_WRITE_ANDX 0x2F
-#define SMB_COM_NEW_FILE_SIZE 0x30
-#define SMB_COM_CLOSE_AND_TREE_DISC 0x31
-#define SMB_COM_TRANSACTION2 0x32
-#define SMB_COM_TRANSACTION2_SECONDARY 0x33
-#define SMB_COM_FIND_CLOSE2 0x34
-#define SMB_COM_FIND_NOTIFY_CLOSE 0x35
-#define SMB_COM_TREE_CONNECT 0x70
-#define SMB_COM_TREE_DISCONNECT 0x71
-#define SMB_COM_NEGOTIATE 0x72
-#define SMB_COM_SESSION_SETUP_ANDX 0x73
-#define SMB_COM_LOGOFF_ANDX 0x74
-#define SMB_COM_TREE_CONNECT_ANDX 0x75
-#define SMB_COM_SECURITY_PACKAGE_ANDX 0x7E
-#define SMB_COM_QUERY_INFORMATION_DISK 0x80
-#define SMB_COM_SEARCH 0x81
-#define SMB_COM_FIND 0x82
-#define SMB_COM_FIND_UNIQUE 0x83
-#define SMB_COM_FIND_CLOSE 0x84
-#define SMB_COM_NT_TRANSACT 0xA0
-#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
-#define SMB_COM_NT_CREATE_ANDX 0xA2
-#define SMB_COM_NT_CANCEL 0xA4
-#define SMB_COM_NT_RENAME 0xA5
-#define SMB_COM_OPEN_PRINT_FILE 0xC0
-#define SMB_COM_WRITE_PRINT_FILE 0xC1
-#define SMB_COM_CLOSE_PRINT_FILE 0xC2
-#define SMB_COM_GET_PRINT_QUEUE 0xC3
-#define SMB_COM_READ_BULK 0xD8
-#define SMB_COM_WRITE_BULK 0xD9
-#define SMB_COM_WRITE_BULK_DATA 0xDA
-#define SMB_COM_INVALID 0xFE
-#define SMB_COM_NO_ANDX_COMMAND 0xFF
-
-/* Size of word count field + Word count * 2 bytes + Size of byte count field */
-#define SMB_COM_SIZE(wct)  (sizeof(uint8_t) + ((wct) * sizeof(uint16_t)) + sizeof(uint16_t))
-
-#define SMB_FLG__TYPE  0x80
-#define SMB_TYPE__REQUEST   0
-#define SMB_TYPE__RESPONSE  1
-
-#define SMB_FLG2__UNICODE      0x8000
-#define SMB_FLG2__NT_CODES     0x4000
-
-#define SMB_NT_STATUS_SEVERITY__SUCCESS        0
-#define SMB_NT_STATUS_SEVERITY__INFORMATIONAL  1
-#define SMB_NT_STATUS_SEVERITY__WARNING        2
-#define SMB_NT_STATUS_SEVERITY__ERROR          3
-
-#define SMB_NT_STATUS__SUCCESS                0x00000000
-#define SMB_NT_STATUS__INVALID_DEVICE_REQUEST 0xc0000010
-#define SMB_NT_STATUS__RANGE_NOT_LOCKED       0xc000007e
-#define SMB_NT_STATUS__PIPE_BROKEN            0xc000014b
-#define SMB_NT_STATUS__PIPE_DISCONNECTED      0xc00000b0
-
-#define SMB_ERROR_CLASS__SUCCESS  0x00
-#define SMB_ERROR_CLASS__ERRDOS   0x01
-#define SMB_ERROR_CLASS__ERRSRV   0x02
-#define SMB_ERROR_CLASS__ERRHRD   0x03
-#define SMB_ERROR_CLASS__ERRXOS   0x04
-#define SMB_ERROR_CLASS__ERRMX1   0xe1
-#define SMB_ERROR_CLASS__ERRMX2   0xe2
-#define SMB_ERROR_CLASS__ERRMX3   0xe3
-#define SMB_ERROR_CLASS__ERRCMD   0xff
-
-#define SMB_ERRSRV__INVALID_DEVICE      0x0007
-#define SMB_ERRDOS__NOT_LOCKED          0x009e
-#define SMB_ERRDOS__BAD_PIPE            0x00e6
-#define SMB_ERRDOS__PIPE_NOT_CONNECTED  0x00e9
-#define SMB_ERRDOS__MORE_DATA           0x00ea
-
-#pragma pack(1)
-
-/********************************************************************
- * NetBIOS Session Service header
- ********************************************************************/
-struct NbssHdr
-{
-    uint8_t type;
-    uint8_t flags;   /* Treat flags as the upper byte to length */
-    uint16_t length;
-};
-
-struct SmbNtHdr
-{
-    uint8_t smb_idf[4];             /* contains 0xFF, 'SMB' */
-    uint8_t smb_com;                /* command code */
-    union
-    {
-        struct
-        {
-            uint8_t smb_class;      /* dos error class */
-            uint8_t smb_res;        /* reserved for future */
-            uint16_t smb_code;      /* dos error code */
-        } smb_status;
-        uint32_t nt_status;         /* nt status */
-    } smb_status;
-    uint8_t smb_flg;                /* flags */
-    uint16_t smb_flg2;              /* flags */
-    uint16_t smb_pid_high;
-    uint64_t smb_signature;
-    uint16_t smb_res;               /* reserved for future */
-    uint16_t smb_tid;               /* tree id */
-    uint16_t smb_pid;               /* caller's process id */
-    uint16_t smb_uid;               /* authenticated user id */
-    uint16_t smb_mid;               /* multiplex id */
-};
-
-/* For server empty respones indicating client error or interim response */
-struct SmbEmptyCom
-{
-    uint8_t smb_wct;     /* value = 0 */
-    uint16_t smb_bcc;    /* value = 0 */
-};
-
 enum DCE2_SmbSsnState
 {
     DCE2_SMB_SSN_STATE__START         = 0x00,
@@ -460,119 +252,6 @@ enum SmbAndXCom
     SMB_ANDX_COM__MAX
 };
 
-enum SmbTransactionSubcommand
-{
-    TRANS_UNKNOWN_0000             = 0x0000,
-    TRANS_SET_NMPIPE_STATE         = 0x0001,
-    TRANS_UNKNOWN_0002             = 0x0002,
-    TRANS_UNKNOWN_0003             = 0x0003,
-    TRANS_UNKNOWN_0004             = 0x0004,
-    TRANS_UNKNOWN_0005             = 0x0005,
-    TRANS_UNKNOWN_0006             = 0x0006,
-    TRANS_UNKNOWN_0007             = 0x0007,
-    TRANS_UNKNOWN_0008             = 0x0008,
-    TRANS_UNKNOWN_0009             = 0x0009,
-    TRANS_UNKNOWN_000A             = 0x000A,
-    TRANS_UNKNOWN_000B             = 0x000B,
-    TRANS_UNKNOWN_000C             = 0x000C,
-    TRANS_UNKNOWN_000D             = 0x000D,
-    TRANS_UNKNOWN_000E             = 0x000E,
-    TRANS_UNKNOWN_000F             = 0x000F,
-    TRANS_UNKNOWN_0010             = 0x0010,
-    TRANS_RAW_READ_NMPIPE          = 0x0011,
-    TRANS_UNKNOWN_0012             = 0x0012,
-    TRANS_UNKNOWN_0013             = 0x0013,
-    TRANS_UNKNOWN_0014             = 0x0014,
-    TRANS_UNKNOWN_0015             = 0x0015,
-    TRANS_UNKNOWN_0016             = 0x0016,
-    TRANS_UNKNOWN_0017             = 0x0017,
-    TRANS_UNKNOWN_0018             = 0x0018,
-    TRANS_UNKNOWN_0019             = 0x0019,
-    TRANS_UNKNOWN_001A             = 0x001A,
-    TRANS_UNKNOWN_001B             = 0x001B,
-    TRANS_UNKNOWN_001C             = 0x001C,
-    TRANS_UNKNOWN_001D             = 0x001D,
-    TRANS_UNKNOWN_001E             = 0x001E,
-    TRANS_UNKNOWN_001F             = 0x001F,
-    TRANS_UNKNOWN_0020             = 0x0020,
-    TRANS_QUERY_NMPIPE_STATE       = 0x0021,
-    TRANS_QUERY_NMPIPE_INFO        = 0x0022,
-    TRANS_PEEK_NMPIPE              = 0x0023,
-    TRANS_UNKNOWN_0024             = 0x0024,
-    TRANS_UNKNOWN_0025             = 0x0025,
-    TRANS_TRANSACT_NMPIPE          = 0x0026,
-    TRANS_UNKNOWN_0027             = 0x0027,
-    TRANS_UNKNOWN_0028             = 0x0028,
-    TRANS_UNKNOWN_0029             = 0x0029,
-    TRANS_UNKNOWN_002A             = 0x002A,
-    TRANS_UNKNOWN_002B             = 0x002B,
-    TRANS_UNKNOWN_002C             = 0x002C,
-    TRANS_UNKNOWN_002D             = 0x002D,
-    TRANS_UNKNOWN_002E             = 0x002E,
-    TRANS_UNKNOWN_002F             = 0x002F,
-    TRANS_UNKNOWN_0030             = 0x0030,
-    TRANS_RAW_WRITE_NMPIPE         = 0x0031,
-    TRANS_UNKNOWN_0032             = 0x0032,
-    TRANS_UNKNOWN_0033             = 0x0033,
-    TRANS_UNKNOWN_0034             = 0x0034,
-    TRANS_UNKNOWN_0035             = 0x0035,
-    TRANS_READ_NMPIPE              = 0x0036,
-    TRANS_WRITE_NMPIPE             = 0x0037,
-    TRANS_UNKNOWN_0038             = 0x0038,
-    TRANS_UNKNOWN_0039             = 0x0039,
-    TRANS_UNKNOWN_003A             = 0x003A,
-    TRANS_UNKNOWN_003B             = 0x003B,
-    TRANS_UNKNOWN_003C             = 0x003C,
-    TRANS_UNKNOWN_003D             = 0x003D,
-    TRANS_UNKNOWN_003E             = 0x003E,
-    TRANS_UNKNOWN_003F             = 0x003F,
-    TRANS_UNKNOWN_0040             = 0x0040,
-    TRANS_UNKNOWN_0041             = 0x0041,
-    TRANS_UNKNOWN_0042             = 0x0042,
-    TRANS_UNKNOWN_0043             = 0x0043,
-    TRANS_UNKNOWN_0044             = 0x0044,
-    TRANS_UNKNOWN_0045             = 0x0045,
-    TRANS_UNKNOWN_0046             = 0x0046,
-    TRANS_UNKNOWN_0047             = 0x0047,
-    TRANS_UNKNOWN_0048             = 0x0048,
-    TRANS_UNKNOWN_0049             = 0x0049,
-    TRANS_UNKNOWN_004A             = 0x004A,
-    TRANS_UNKNOWN_004B             = 0x004B,
-    TRANS_UNKNOWN_004C             = 0x004C,
-    TRANS_UNKNOWN_004D             = 0x004D,
-    TRANS_UNKNOWN_004E             = 0x004E,
-    TRANS_UNKNOWN_004F             = 0x004F,
-    TRANS_UNKNOWN_0050             = 0x0050,
-    TRANS_UNKNOWN_0051             = 0x0051,
-    TRANS_UNKNOWN_0052             = 0x0052,
-    TRANS_WAIT_NMPIPE              = 0x0053,
-    TRANS_CALL_NMPIPE              = 0x0054,
-    TRANS_SUBCOM_MAX               = 0x0055
-};
-
-enum SmbTransaction2Subcommand
-{
-    TRANS2_OPEN2                        = 0x0000,
-    TRANS2_FIND_FIRST2                  = 0x0001,
-    TRANS2_FIND_NEXT2                   = 0x0002,
-    TRANS2_QUERY_FS_INFORMATION         = 0x0003,
-    TRANS2_SET_FS_INFORMATION           = 0x0004,
-    TRANS2_QUERY_PATH_INFORMATION       = 0x0005,
-    TRANS2_SET_PATH_INFORMATION         = 0x0006,
-    TRANS2_QUERY_FILE_INFORMATION       = 0x0007,
-    TRANS2_SET_FILE_INFORMATION         = 0x0008,
-    TRANS2_FSCTL                        = 0x0009,
-    TRANS2_IOCTL2                       = 0x000A,
-    TRANS2_FIND_NOTIFY_FIRST            = 0x000B,
-    TRANS2_FIND_NOTIFY_NEXT             = 0x000C,
-    TRANS2_CREATE_DIRECTORY             = 0x000D,
-    TRANS2_SESSION_SETUP                = 0x000E,
-    TRANS2_UNKNOWN_000F                 = 0x000F,
-    TRANS2_GET_DFS_REFERRAL             = 0x0010,
-    TRANS2_REPORT_DFS_INCONSISTENCY     = 0x0011,
-    TRANS2_SUBCOM_MAX                   = 0x0012
-};
-
 struct DCE2_SmbWriteAndXRaw
 {
     int remaining;  // A signed integer so it can be negative
@@ -586,6 +265,13 @@ struct DCE2_SmbFileChunk
     uint8_t* data;
 };
 
+enum DCE2_SmbVersion
+{
+    DCE2_SMB_VERISON_NULL,
+    DCE2_SMB_VERISON_1,
+    DCE2_SMB_VERISON_2
+};
+
 struct DCE2_SmbFileTracker
 {
     union
@@ -655,13 +341,6 @@ struct DCE2_SmbFileTracker
 #define ff_sequential_only    tracker.file.sequential_only
 };
 
-enum DCE2_SmbVersion
-{
-    DCE2_SMB_VERISON_NULL,
-    DCE2_SMB_VERISON_1,
-    DCE2_SMB_VERISON_2
-};
-
 struct Smb2Request
 {
     uint64_t message_id;   /* identifies a message uniquely on connection */
@@ -722,8 +401,6 @@ struct DCE2_SmbRequestTracker
     bool is_ipc;
 };
 
-#pragma pack()
-
 struct DCE2_SmbSsnData
 {
     DCE2_SsnData sd;  // This member must be first
@@ -779,2261 +456,6 @@ struct DCE2_SmbSsnData
     int64_t max_file_depth;
 };
 
-/********************************************************************
- * Structures and inline accessor functions
- ********************************************************************/
-/* Pack the structs since we'll be laying them on top of packet data */
-#pragma pack(1)
-
-/********************************************************************
- * Common fields to all commands
- ********************************************************************/
-struct SmbCommon
-{
-    uint8_t smb_wct;
-};
-
-inline uint8_t SmbWct(const SmbCommon* hdr)
-{
-    return hdr->smb_wct;
-}
-
-/* Common fields to all AndX commands */
-struct SmbAndXCommon
-{
-    uint8_t smb_wct;
-    uint8_t smb_com2;      /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;      /* reserved (must be zero) */
-    uint16_t smb_off2;     /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-};
-
-inline uint32_t NbssLen(const NbssHdr* nb)
-{
-    /* Treat first bit of flags as the upper byte to length */
-    // The left operand of '&' is a garbage value
-    return ((nb->flags & 0x01) << 16) | ntohs(nb->length);  // ... FIXIT-W
-}
-
-inline uint8_t NbssType(const NbssHdr* nb)
-{
-    return nb->type;
-}
-
-inline uint32_t SmbId(const SmbNtHdr* hdr)
-{
-    uint8_t* idf = (uint8_t*)hdr->smb_idf;
-    return *idf << 24 | *(idf + 1) << 16 | *(idf + 2) << 8 | *(idf + 3);
-}
-
-inline uint8_t SmbEmptyComWct(const SmbEmptyCom* ec)
-{
-    return ec->smb_wct;
-}
-
-inline uint16_t SmbBcc(const uint8_t* ptr, uint16_t com_size)
-{
-    /* com_size must be at least the size of the command encasing */
-    if (com_size < sizeof(SmbEmptyCom))
-        return 0;
-
-    return alignedNtohs((uint16_t*)(ptr + com_size - sizeof(uint16_t)));
-}
-
-inline uint16_t SmbEmptyComBcc(const SmbEmptyCom* ec)
-{
-    return alignedNtohs(&ec->smb_bcc);
-}
-
-inline int SmbType(const SmbNtHdr* hdr)
-{
-    // Access to field 'smb_flg' results in a dereference of a null pointer
-    // (loaded from variable 'hdr')
-    if (hdr->smb_flg & SMB_FLG__TYPE)  // ... FIXIT-W
-        return SMB_TYPE__RESPONSE;
-
-    return SMB_TYPE__REQUEST;
-}
-
-inline uint8_t SmbAndXCom2(const SmbAndXCommon* andx)
-{
-    return andx->smb_com2;
-}
-
-inline uint16_t SmbAndXOff2(const SmbAndXCommon* andx)
-{
-    return alignedNtohs(&andx->smb_off2);
-}
-
-/* SMB formats (smb_fmt) Dialect, Pathname and ASCII are all
- * NULL terminated ASCII strings unless Unicode is specified
- * in the NT LM 1.0 SMB header in which case they are NULL
- * terminated unicode strings
- */
-#define SMB_FMT__DATA_BLOCK  1
-#define SMB_FMT__DIALECT     2
-#define SMB_FMT__ASCII       4
-
-inline bool SmbFmtDataBlock(const uint8_t fmt)
-{
-    return fmt == SMB_FMT__DATA_BLOCK ? true : false;
-}
-
-inline bool SmbFmtDialect(const uint8_t fmt)
-{
-    return fmt == SMB_FMT__DIALECT ? true : false;
-}
-
-inline bool SmbFmtAscii(const uint8_t fmt)
-{
-    return fmt == SMB_FMT__ASCII ? true : false;
-}
-
-/********************************************************************
- * SMB_COM_OPEN
- ********************************************************************/
-struct SmbOpenReq   /* smb_wct = 2 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_mode;    /* r/w/share */
-    uint16_t smb_attr;    /* attribute */
-    uint16_t smb_bcc;     /* min = 2 */
-};
-
-struct SmbOpenResp   /* smb_wct = 7 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;     /* file handle */
-    uint16_t smb_attr;    /* attribute */
-    uint32_t smb_time;    /* time1 low */
-    uint32_t smb_file_size;   /* file size low */
-    uint16_t smb_access;  /* access allowed */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-#define SMB_OPEN_ACCESS_MODE__READ        0x0000
-#define SMB_OPEN_ACCESS_MODE__WRITE       0x0001
-#define SMB_OPEN_ACCESS_MODE__READ_WRITE  0x0002
-#define SMB_OPEN_ACCESS_MODE__EXECUTE     0x0003
-
-inline uint16_t SmbOpenRespFid(const SmbOpenResp* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-inline uint32_t SmbOpenRespFileSize(const SmbOpenResp* resp)
-{
-    return alignedNtohl(&resp->smb_file_size);
-}
-
-inline uint16_t SmbOpenRespFileAttrs(const SmbOpenResp* resp)
-{
-    return alignedNtohs(&resp->smb_attr);
-}
-
-inline bool SmbFileAttrsDirectory(const uint16_t file_attrs)
-{
-    if (file_attrs & SMB_FILE_ATTRIBUTE_DIRECTORY)
-        return true;
-    return false;
-}
-
-inline uint16_t SmbOpenRespAccessMode(const SmbOpenResp* resp)
-{
-    return alignedNtohs(&resp->smb_access);
-}
-
-inline bool SmbOpenForWriting(const uint16_t access_mode)
-{
-    return access_mode == SMB_OPEN_ACCESS_MODE__WRITE;
-}
-
-/********************************************************************
- * SMB_COM_CREATE
- ********************************************************************/
-struct SmbCreateReq   /* smb_wct = 3 */
-{
-    uint8_t smb_wct;
-    uint16_t smb_file_attrs;
-    uint32_t smb_creation_time;
-    uint16_t smb_bcc;
-};
-
-struct SmbCreateResp   /* smb_wct = 1 */
-{
-    uint8_t smb_wct;
-    uint16_t smb_fid;
-    uint16_t smb_bcc;
-};
-
-inline uint16_t SmbCreateReqFileAttrs(const SmbCreateReq* req)
-{
-    return alignedNtohs(&req->smb_file_attrs);
-}
-
-inline bool SmbAttrDirectory(const uint16_t file_attrs)
-{
-    if (file_attrs & SMB_FILE_ATTRIBUTE_DIRECTORY)
-        return true;
-    return false;
-}
-
-inline uint16_t SmbCreateRespFid(const SmbCreateResp* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-/********************************************************************
- * SMB_COM_CLOSE
- ********************************************************************/
-struct SmbCloseReq   /* smb_wct = 3 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;     /* file handle */
-    uint16_t smb_tlow;    /* time low */
-    uint16_t smb_thigh;   /* time high */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-struct SmbCloseResp   /* smb_wct = 0 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-inline uint16_t SmbCloseReqFid(const SmbCloseReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-/********************************************************************
- * SMB_COM_READ
- ********************************************************************/
-struct SmbReadReq   /* smb_wct = 5 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;     /* file handle */
-    uint16_t smb_cnt;     /* count of bytes */
-    uint32_t smb_off;     /* offset */
-    uint16_t smb_left;    /* count left */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-struct SmbReadResp   /* smb_wct = 5 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_cnt;     /* count */
-    uint16_t smb_res[4];  /* reserved (MBZ) */
-    uint16_t smb_bcc;     /* length of data + 3 */
-};
-
-inline uint16_t SmbReadReqFid(const SmbReadReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint32_t SmbReadReqOffset(const SmbReadReq* req)
-{
-    return alignedNtohl(&req->smb_off);
-}
-
-inline uint16_t SmbReadRespCount(const SmbReadResp* resp)
-{
-    return alignedNtohs(&resp->smb_cnt);
-}
-
-/********************************************************************
- * SMB_COM_WRITE
- ********************************************************************/
-struct SmbWriteReq   /* smb_wct = 5 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;     /* file handle */
-    uint16_t smb_cnt;     /* count of bytes */
-    uint32_t smb_offset;  /* file offset in bytes */
-    uint16_t smb_left;    /* count left */
-    uint16_t smb_bcc;     /* length of data + 3 */
-};
-
-struct SmbWriteResp   /* smb_wct = 1 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_cnt;     /* count */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-inline uint16_t SmbWriteReqFid(const SmbWriteReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint16_t SmbWriteReqCount(const SmbWriteReq* req)
-{
-    return alignedNtohs(&req->smb_cnt);
-}
-
-inline uint32_t SmbWriteReqOffset(const SmbWriteReq* req)
-{
-    return alignedNtohl(&req->smb_offset);
-}
-
-inline uint16_t SmbWriteRespCount(const SmbWriteResp* resp)
-{
-    return alignedNtohs(&resp->smb_cnt);
-}
-
-/********************************************************************
- * SMB_COM_CREATE_NEW
- ********************************************************************/
-struct SmbCreateNewReq   /* smb_wct = 3 */
-{
-    uint8_t smb_wct;
-    uint16_t smb_file_attrs;
-    uint32_t smb_creation_time;
-    uint16_t smb_bcc;
-};
-
-struct SmbCreateNewResp   /* smb_wct = 1 */
-{
-    uint8_t smb_wct;
-    uint16_t smb_fid;
-    uint16_t smb_bcc;
-};
-
-inline uint16_t SmbCreateNewReqFileAttrs(const SmbCreateNewReq* req)
-{
-    return alignedNtohs(&req->smb_file_attrs);
-}
-
-inline uint16_t SmbCreateNewRespFid(const SmbCreateNewResp* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-/********************************************************************
- * SMB_COM_LOCK_AND_READ
- ********************************************************************/
-struct SmbLockAndReadReq   /* smb_wct = 5 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;
-    uint16_t smb_cnt;
-    uint32_t smb_read_offset;
-    uint16_t smb_remaining;
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-struct SmbLockAndReadResp   /* smb_wct = 5 */
-{
-    uint8_t smb_wct;
-    uint16_t smb_cnt;
-    uint16_t reserved[4];
-    uint16_t smb_bcc;
-};
-
-inline uint16_t SmbLockAndReadReqFid(const SmbLockAndReadReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint32_t SmbLockAndReadReqOffset(const SmbLockAndReadReq* req)
-{
-    return alignedNtohl(&req->smb_read_offset);
-}
-
-inline uint16_t SmbLockAndReadRespCount(const SmbLockAndReadResp* resp)
-{
-    return alignedNtohs(&resp->smb_cnt);
-}
-
-/********************************************************************
- * SMB_COM_WRITE_AND_UNLOCK
- ********************************************************************/
-struct SmbWriteAndUnlockReq
-{
-    uint8_t smb_wct;
-    uint16_t smb_fid;
-    uint16_t smb_cnt;
-    uint32_t smb_write_offset;
-    uint16_t smb_estimate_of_remaining;
-    uint16_t smb_bcc;
-};
-
-struct SmbWriteAndUnlockResp   /* smb_wct = 1 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_cnt;     /* count */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-inline uint16_t SmbWriteAndUnlockReqFid(const SmbWriteAndUnlockReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint16_t SmbWriteAndUnlockReqCount(const SmbWriteAndUnlockReq* req)
-{
-    return alignedNtohs(&req->smb_cnt);
-}
-
-inline uint32_t SmbWriteAndUnlockReqOffset(const SmbWriteAndUnlockReq* req)
-{
-    return alignedNtohl(&req->smb_write_offset);
-}
-
-/********************************************************************
- * SMB_COM_OPEN_ANDX
- ********************************************************************/
-struct SmbOpenAndXReq   /* smb_wct = 15 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;        /* reserved (must be zero) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_flags;      /* additional information:
-                                bit 0 - if set, return additional information
-                                bit 1 - if set, set single user total file lock (if only access)
-                                bit 2 - if set, the server should notify the consumer on any
-                                        action which can modify the file (delete, setattrib,
-                                        rename, etc.). if not set, the server need only notify
-                                        the consumer on another open request. This bit only has
-                                        meaning if bit 1 is set. */
-    uint16_t smb_mode;       /* file open mode */
-    uint16_t smb_sattr;      /* search attributes */
-    uint16_t smb_attr;       /* file attributes (for create) */
-    uint32_t smb_time;       /* create time */
-    uint16_t smb_ofun;       /* open function */
-    uint32_t smb_size;       /* bytes to reserve on "create" or "truncate" */
-    uint32_t smb_timeout;    /* max milliseconds to wait for resource to open */
-    uint32_t smb_rsvd;       /* reserved (must be zero) */
-    uint16_t smb_bcc;        /* minimum value = 1 */
-};
-
-struct SmbOpenAndXResp   /* smb_wct = 15 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_res2;        /* reserved (pad to word) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_fid;        /* file handle */
-    uint16_t smb_attribute;  /* attributes of file or device */
-    uint32_t smb_time;       /* last modification time */
-    uint32_t smb_size;       /* current file size */
-    uint16_t smb_access;     /* access permissions actually allowed */
-    uint16_t smb_type;       /* file type */
-    uint16_t smb_state;      /* state of IPC device (e.g. pipe) */
-    uint16_t smb_action;     /* action taken */
-    uint32_t smb_fileid;     /* server unique file id */
-    uint16_t smb_rsvd;       /* reserved */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-inline uint32_t SmbOpenAndXReqAllocSize(const SmbOpenAndXReq* req)
-{
-    return alignedNtohl(&req->smb_size);
-}
-
-inline uint16_t SmbOpenAndXReqFileAttrs(const SmbOpenAndXReq* req)
-{
-    return alignedNtohs(&req->smb_attr);
-}
-
-inline uint16_t SmbOpenAndXRespFid(const SmbOpenAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-inline uint16_t SmbOpenAndXRespFileAttrs(const SmbOpenAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_attribute);
-}
-
-inline uint32_t SmbOpenAndXRespFileSize(const SmbOpenAndXResp* resp)
-{
-    return alignedNtohl(&resp->smb_size);
-}
-
-inline uint16_t SmbOpenAndXRespResourceType(const SmbOpenAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_type);
-}
-
-#define SMB_OPEN_RESULT__EXISTED    0x0001
-#define SMB_OPEN_RESULT__CREATED    0x0002
-#define SMB_OPEN_RESULT__TRUNCATED  0x0003
-
-inline uint16_t SmbOpenAndXRespOpenResults(const SmbOpenAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_action);
-}
-
-inline bool SmbOpenResultRead(const uint16_t open_results)
-{
-    return ((open_results & 0x00FF) == SMB_OPEN_RESULT__EXISTED);
-}
-
-inline bool SmbResourceTypeDisk(const uint16_t resource_type)
-{
-    return resource_type == SMB_FILE_TYPE_DISK;
-}
-
-/********************************************************************
- * SMB_COM_READ_ANDX
- ********************************************************************/
-struct SmbReadAndXReq   /* smb_wct = 10 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;        /* reserved (must be zero) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_fid;        /* file handle */
-    uint32_t smb_offset;     /* offset in file to begin read */
-    uint16_t smb_maxcnt;     /* max number of bytes to return */
-    uint16_t smb_mincnt;     /* min number of bytes to return */
-    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
-    uint16_t smb_countleft;  /* bytes remaining to satisfy user’s request */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-struct SmbReadAndXExtReq   /* smb_wct = 12 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;        /* reserved (must be zero) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_fid;        /* file handle */
-    uint32_t smb_offset;     /* low offset in file to begin read */
-    uint16_t smb_maxcnt;     /* max number of bytes to return */
-    uint16_t smb_mincnt;     /* min number of bytes to return */
-    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
-    uint16_t smb_countleft;  /* bytes remaining to satisfy user’s request */
-    uint32_t smb_off_high;   /* high offset in file to begin read */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-struct SmbReadAndXResp    /* smb_wct = 12 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_res2;        /* reserved (pad to word) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_remaining;  /* bytes remaining to be read (pipes/devices only) */
-    uint32_t smb_rsvd;       /* reserved */
-    uint16_t smb_dsize;      /* number of data bytes (minimum value = 0) */
-    uint16_t smb_doff;       /* offset (from start of SMB hdr) to data bytes */
-    uint16_t smb_dsize_high; /* high bytes of data size */
-    uint32_t smb_rsvd1;      /* reserved */
-    uint32_t smb_rsvd2;      /* reserved */
-    uint16_t smb_bcc;        /* total bytes (including pad bytes) following */
-};
-
-inline uint16_t SmbReadAndXReqFid(const SmbReadAndXReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint64_t SmbReadAndXReqOffset(const SmbReadAndXExtReq* req)
-{
-    if (req->smb_wct == 10)
-        return (uint64_t)alignedNtohl(&req->smb_offset);
-    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
-        &req->smb_offset);
-}
-
-inline uint16_t SmbReadAndXRespDataOff(const SmbReadAndXResp* req)
-{
-    return alignedNtohs(&req->smb_doff);
-}
-
-inline uint32_t SmbReadAndXRespDataCnt(const SmbReadAndXResp* resp)
-{
-    return (uint32_t)alignedNtohs(&resp->smb_dsize_high) << 16 | (uint32_t)alignedNtohs(
-        &resp->smb_dsize);
-}
-
-/********************************************************************
- * SMB_COM_WRITE_ANDX
- ********************************************************************/
-struct SmbWriteAndXReq   /* smb_wct = 12 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;        /* reserved (must be zero) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_fid;        /* file handle */
-    uint32_t smb_offset;     /* offset in file to begin write */
-    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
-    uint16_t smb_wmode;      /* write mode:
-                                bit0 - complete write before return (write through)
-                                bit1 - return smb_remaining (pipes/devices only)
-                                bit2 - use WriteRawNamedPipe (pipes only)
-                                bit3 - this is the start of a message (pipes only) */
-    uint16_t smb_countleft;  /* bytes remaining to write to satisfy user’s request */
-    uint16_t smb_dsize_high; /* high bytes of data size */
-    uint16_t smb_dsize;      /* number of data bytes in buffer (min value = 0) */
-    uint16_t smb_doff;       /* offset (from start of SMB hdr) to data bytes */
-    uint16_t smb_bcc;        /* total bytes (including pad bytes) following */
-};
-
-struct SmbWriteAndXExtReq   /* smb_wct = 14 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;        /* reserved (must be zero) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_fid;        /* file handle */
-    uint32_t smb_offset;     /* low offset in file to begin write */
-    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
-    uint16_t smb_wmode;      /* write mode:
-                                bit0 - complete write before return (write through)
-                                bit1 - return smb_remaining (pipes/devices only)
-                                bit2 - use WriteRawNamedPipe (pipes only)
-                                bit3 - this is the start of a message (pipes only) */
-    uint16_t smb_countleft;  /* bytes remaining to write to satisfy user’s request */
-    uint16_t smb_dsize_high; /* high bytes of data size */
-    uint16_t smb_dsize;      /* number of data bytes in buffer (min value = 0) */
-    uint16_t smb_doff;       /* offset (from start of SMB hdr) to data bytes */
-    uint32_t smb_off_high;   /* high offset in file to begin write */
-    uint16_t smb_bcc;        /* total bytes (including pad bytes) following */
-};
-
-struct SmbWriteAndXResp   /* smb_wct = 6 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_res2;        /* reserved (pad to word) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_count;      /* number of bytes written */
-    uint16_t smb_remaining;  /* bytes remaining to be read (pipes/devices only) */
-    uint16_t smb_count_high; /* high order bytes of data count */
-    uint16_t smb_rsvd;       /* reserved */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-inline uint16_t SmbWriteAndXReqFid(const SmbWriteAndXReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint16_t SmbWriteAndXReqDataOff(const SmbWriteAndXReq* req)
-{
-    return alignedNtohs(&req->smb_doff);
-}
-
-inline uint16_t SmbWriteAndXReqRemaining(const SmbWriteAndXReq* req)
-{
-    return alignedNtohs(&req->smb_countleft);
-}
-
-inline uint64_t SmbWriteAndXReqOffset(const SmbWriteAndXExtReq* req)
-{
-    if (req->smb_wct == 12)
-        return (uint64_t)alignedNtohl(&req->smb_offset);
-    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
-        &req->smb_offset);
-}
-
-inline uint32_t SmbWriteAndXReqDataCnt(const SmbWriteAndXReq* req)
-{
-    return (uint32_t)alignedNtohs(&req->smb_dsize_high) << 16 | (uint32_t)alignedNtohs(
-        &req->smb_dsize);
-}
-
-inline uint16_t SmbWriteAndXReqWriteMode(const SmbWriteAndXReq* req)
-{
-    return alignedNtohs(&req->smb_wmode);
-}
-
-inline bool SmbWriteAndXReqStartRaw(const SmbWriteAndXReq* req)
-{
-    return ((alignedNtohs(&req->smb_wmode) & 0x000c) == 0x000c) ? true : false;
-}
-
-inline bool SmbWriteAndXReqRaw(const SmbWriteAndXReq* req)
-{
-    return ((alignedNtohs(&req->smb_wmode) & 0x000c) == 0x0004) ? true : false;
-}
-
-inline uint16_t SmbWriteAndXRespCnt(const SmbWriteAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_count);
-}
-
-/********************************************************************
- * SMB_COM_SESSION_SETUP_ANDX
- ********************************************************************/
-struct SmbLm10_SessionSetupAndXReq   /* smb_wct = 10 */
-{
-    uint8_t smb_wct;       /* count of 16-bit words that follow */
-    uint8_t smb_com2;      /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;      /* reserved (must be zero) */
-    uint16_t smb_off2;     /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_bufsize;  /* the consumers max buffer size */
-    uint16_t smb_mpxmax;   /* actual maximum multiplexed pending requests */
-    uint16_t smb_vc_num;   /* 0 = first (only), non zero - additional VC number */
-    uint32_t smb_sesskey;  /* Session Key (valid only if smb_vc_num != 0) */
-    uint16_t smb_apasslen; /* size of account password (smb_apasswd) */
-    uint32_t smb_rsvd;     /* reserved */
-    uint16_t smb_bcc;      /* minimum value = 0 */
-};
-
-inline uint16_t SmbSessionSetupAndXReqMaxMultiplex(const SmbLm10_SessionSetupAndXReq* req)
-{
-    return alignedNtohs(&req->smb_mpxmax);
-}
-
-/* Extended request as defined in NT LM 1.0 document */
-struct SmbNt10_SessionSetupAndXReq   /* smb_wct = 13 */
-{
-    uint8_t smb_wct;              /* count of 16-bit words that follow */
-    uint8_t smb_com2;             /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;             /* reserved (must be zero) */
-    uint16_t smb_off2;            /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_bufsize;         /* the consumers max buffer size */
-    uint16_t smb_mpxmax;          /* actual maximum multiplexed pending requests */
-    uint16_t smb_vc_num;          /* 0 = first (only), non zero - additional VC number */
-    uint32_t smb_sesskey;         /* Session Key (valid only if smb_vc_num != 0) */
-    uint16_t smb_oem_passlen;     /* case insensitive password length */
-    uint16_t smb_unicode_passlen; /* case sensitive password length */
-    uint32_t smb_rsvd;            /* reserved */
-    uint32_t smb_cap;             /* capabilities */
-    uint16_t smb_bcc;             /* minimum value = 0 */
-};
-
-inline uint16_t SmbNt10SessionSetupAndXReqOemPassLen(const SmbNt10_SessionSetupAndXReq* req)
-{
-    return alignedNtohs(&req->smb_oem_passlen);
-}
-
-inline uint16_t SmbNt10SessionSetupAndXReqUnicodePassLen(const SmbNt10_SessionSetupAndXReq* req)
-{
-    return alignedNtohs(&req->smb_unicode_passlen);
-}
-
-/* Extended request for security blob */
-struct SmbNt10_SessionSetupAndXExtReq   /* smb_wct = 12 */
-{
-    uint8_t smb_wct;          /* count of 16-bit words that follow */
-    uint8_t smb_com2;         /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;         /* reserved (must be zero) */
-    uint16_t smb_off2;        /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_bufsize;     /* the consumers max buffer size */
-    uint16_t smb_mpxmax;      /* actual maximum multiplexed pending requests */
-    uint16_t smb_vc_num;      /* 0 = first (only), non zero - additional VC number */
-    uint32_t smb_sesskey;     /* Session Key (valid only if smb_vc_num != 0) */
-    uint16_t smb_blob_len;    /* length of security blob */
-    uint32_t smb_rsvd;        /* reserved */
-    uint32_t smb_cap;         /* capabilities */
-    uint16_t smb_bcc;         /* minimum value = 0 */
-};
-
-inline uint16_t SmbSessionSetupAndXReqBlobLen(const SmbNt10_SessionSetupAndXExtReq* req)
-{
-    return alignedNtohs(&req->smb_blob_len);
-}
-
-/* Extended response for security blob */
-struct SmbNt10_SessionSetupAndXExtResp   /* smb_wct = 4 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_res2;        /* reserved (pad to word) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_action;     /* request mode:
-                                bit0 = Logged in successfully - BUT as GUEST */
-    uint16_t smb_blob_len;   /* length of security blob */
-    uint16_t smb_bcc;        /* min value = 0 */
-};
-
-inline uint16_t SmbSessionSetupAndXRespBlobLen(const SmbNt10_SessionSetupAndXExtResp* resp)
-{
-    return alignedNtohs(&resp->smb_blob_len);
-}
-
-/********************************************************************
- * SMB_COM_NEGOTIATE
- ********************************************************************/
-/* This is the Lanman response */
-struct SmbLm10_NegotiateProtocolResp   /* smb_wct = 13 */
-{
-    uint8_t smb_wct;        /* count of 16-bit words that follow */
-    uint16_t smb_index;     /* index identifying dialect selected */
-    uint16_t smb_secmode;   /* security mode:
-                               bit 0, 1 = User level, 0 = Share level
-                               bit 1, 1 = encrypt passwords, 0 = do not encrypt passwords */
-    uint16_t smb_maxxmt;    /* max transmit buffer size server supports, 1K min */
-    uint16_t smb_maxmux;    /* max pending multiplexed requests server supports */
-    uint16_t smb_maxvcs;    /* max VCs per server/consumer session supported */
-    uint16_t smb_blkmode;   /* block read/write mode support:
-                               bit 0, Read Block Raw supported (65535 bytes max)
-                               bit 1, Write Block Raw supported (65535 bytes max) */
-    uint32_t smb_sesskey;   /* Session Key (unique token identifying session) */
-    uint16_t smb_srv_time;  /* server's current time (hhhhh mmmmmm xxxxx) */
-    uint16_t smb_srv_tzone; /* server's current data (yyyyyyy mmmm ddddd) */
-    uint32_t smb_rsvd;      /* reserved */
-    uint16_t smb_bcc;       /* value = (size of smb_cryptkey) */
-};
-
-/* This is the NT response */
-struct SmbNt_NegotiateProtocolResp     /* smb_wct = 17 */
-{
-    uint8_t smb_wct;            /* count of 16-bit words that follow */
-    uint16_t smb_index;         /* index identifying dialect selected */
-    uint8_t smb_secmode;        /* security mode:
-                                   bit 0, 1 = User level, 0 = Share level
-                                   bit 1, 1 = encrypt passwords, 0 = do not encrypt passwords */
-    uint16_t smb_maxmux;        /* max pending multiplexed requests server supports */
-    uint16_t smb_maxvcs;        /* max VCs per server/consumer session supported */
-    uint32_t smb_maxbuf;        /* maximum buffer size supported */
-    uint32_t smb_maxraw;        /* maximum raw buffer size supported */
-    uint32_t smb_sesskey;       /* Session Key (unique token identifying session) */
-    uint32_t smb_cap;           /* capabilities */
-    struct
-    {
-        uint32_t low_time;
-        int32_t high_time;
-    } smb_srv_time;             /* server time */
-    uint16_t smb_srv_tzone;     /* server's current data (yyyyyyy mmmm ddddd) */
-    uint8_t smb_challenge_len;  /* Challenge length */
-    uint16_t smb_bcc;           /* value = (size of smb_cryptkey) */
-};
-
-inline uint16_t SmbLm_NegotiateRespMaxMultiplex(const SmbLm10_NegotiateProtocolResp* resp)
-{
-    return alignedNtohs(&resp->smb_maxmux);
-}
-
-inline uint16_t SmbNt_NegotiateRespMaxMultiplex(const SmbNt_NegotiateProtocolResp* resp)
-{
-    return alignedNtohs(&resp->smb_maxmux);
-}
-
-/* This is the Core Protocol response */
-struct SmbCore_NegotiateProtocolResp    /* smb_wct = 1 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_index;   /* index */
-    uint16_t smb_bcc;     /* must be 0 */
-};
-
-inline uint16_t SmbNegotiateRespDialectIndex(const SmbCore_NegotiateProtocolResp* resp)
-{
-    return alignedNtohs(&resp->smb_index);
-}
-
-/*********************************************************************
- * SMB_COM_TREE_CONNECT_ANDX
- *********************************************************************/
-struct SmbTreeConnectAndXReq   /* smb_wct = 4 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
-    uint8_t smb_reh2;        /* reserved (must be zero) */
-    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint16_t smb_flags;      /* additional information:
-                                bit 0 - if set, disconnect TID in current smb_tid */
-    uint16_t smb_spasslen;   /* length of smb_spasswd */
-    uint16_t smb_bcc;        /* minimum value = 3 */
-};
-
-inline uint16_t SmbTreeConnectAndXReqPassLen(const SmbTreeConnectAndXReq* req)
-{
-    return alignedNtohs(&req->smb_spasslen);
-}
-
-/********************************************************************
- * SMB_COM_NT_TRANSACT
- ********************************************************************/
-#define SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY     0x00000004
-
-/********************************************************************
- * SMB_COM_NT_CREATE_ANDX
- ********************************************************************/
-#define SMB_CREATE_DISPOSITSION__FILE_SUPERCEDE      0x00000000
-#define SMB_CREATE_DISPOSITSION__FILE_OPEN           0x00000001
-#define SMB_CREATE_DISPOSITSION__FILE_CREATE         0x00000002
-#define SMB_CREATE_DISPOSITSION__FILE_OPEN_IF        0x00000003
-#define SMB_CREATE_DISPOSITSION__FILE_OVERWRITE      0x00000004
-#define SMB_CREATE_DISPOSITSION__FILE_OVERWRITE_IF   0x00000005
-
-struct SmbNtCreateAndXReq   /* smb_wct = 24 */
-{
-    uint8_t smb_wct;            /* count of 16-bit words that follow */
-    uint8_t smb_com2;           /* secondary (X) command, 0xFF = none */
-    uint8_t smb_res2;           /* reserved (pad to word) */
-    uint16_t smb_off2;          /* offset (from SMB hdr start) to next cmd (@smb_wct) */
-    uint8_t smb_res;            /* reserved */
-    uint16_t smb_name_len;      /* length of name of file */
-    uint32_t smb_flags;         /* flags */
-    uint32_t smb_root_fid;      /* fid for previously opened directory */
-    uint32_t smb_access;        /* specifies the type of file access */
-    uint64_t smb_alloc_size;    /* initial allocation size of the file */
-    uint32_t smb_file_attrs;    /* specifies the file attributes for the file */
-    uint32_t smb_share_access;  /* the type of share access */
-    uint32_t smb_create_disp;   /* actions to take if file does or does not exist */
-    uint32_t smb_create_opts;   /* options used when creating or opening file */
-    uint32_t smb_impersonation_level;  /* security impersonation level */
-    uint8_t smb_security_flags;   /* security flags */
-    uint16_t smb_bcc;           /* byte count */
-};
-
-struct SmbNtCreateAndXResp    /* smb_wct = 34 */
-{
-    uint8_t smb_wct;
-    uint8_t smb_com2;
-    uint8_t smb_res2;
-    uint16_t smb_off2;
-    uint8_t smb_oplock_level;
-    uint16_t smb_fid;
-    uint32_t smb_create_disposition;
-    uint64_t smb_creation_time;
-    uint64_t smb_last_access_time;
-    uint64_t smb_last_write_time;
-    uint64_t smb_change_time;
-    uint32_t smb_file_attrs;
-    uint64_t smb_alloc_size;
-    uint64_t smb_eof;
-    uint16_t smb_resource_type;
-    uint16_t smb_nm_pipe_state;
-    uint8_t smb_directory;
-    uint16_t smb_bcc;
-};
-
-// Word count is always set to 42 though there are actually 50 words
-struct SmbNtCreateAndXExtResp    /* smb_wct = 42 */
-{
-    uint8_t smb_wct;
-    uint8_t smb_com2;
-    uint8_t smb_res2;
-    uint16_t smb_off2;
-    uint8_t smb_oplock_level;
-    uint16_t smb_fid;
-    uint32_t smb_create_disposition;
-    uint64_t smb_creation_time;
-    uint64_t smb_last_access_time;
-    uint64_t smb_last_write_time;
-    uint64_t smb_change_time;
-    uint32_t smb_file_attrs;
-    uint64_t smb_alloc_size;
-    uint64_t smb_eof;
-    uint16_t smb_resource_type;
-    uint16_t smb_nm_pipe_state;
-    uint8_t smb_directory;
-    uint8_t smb_volume_guid[16];
-    uint64_t smb_fileid;
-    uint32_t smb_max_access_rights;
-    uint32_t smb_guest_access_rights;
-    uint16_t smb_bcc;
-};
-
-inline uint16_t SmbNtCreateAndXReqFileNameLen(const SmbNtCreateAndXReq* req)
-{
-    return alignedNtohs(&req->smb_name_len);
-}
-
-inline uint32_t SmbNtCreateAndXReqCreateDisposition(const SmbNtCreateAndXReq* req)
-{
-    return alignedNtohl(&req->smb_create_disp);
-}
-
-inline bool SmbCreateDispositionRead(const uint32_t create_disposition)
-{
-    return (create_disposition == SMB_CREATE_DISPOSITSION__FILE_OPEN)
-           || (create_disposition > SMB_CREATE_DISPOSITSION__FILE_OVERWRITE_IF);
-}
-
-inline uint64_t SmbNtCreateAndXReqAllocSize(const SmbNtCreateAndXReq* req)
-{
-    return alignedNtohq(&req->smb_alloc_size);
-}
-
-inline bool SmbNtCreateAndXReqSequentialOnly(const SmbNtCreateAndXReq* req)
-{
-    return (alignedNtohl(&req->smb_create_opts) & SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY);
-}
-
-inline uint32_t SmbNtCreateAndXReqFileAttrs(const SmbNtCreateAndXReq* req)
-{
-    return alignedNtohl(&req->smb_file_attrs);
-}
-
-inline uint16_t SmbNtCreateAndXRespFid(const SmbNtCreateAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-inline uint32_t SmbNtCreateAndXRespCreateDisposition(const SmbNtCreateAndXResp* resp)
-{
-    return alignedNtohl(&resp->smb_create_disposition);
-}
-
-inline bool SmbNtCreateAndXRespDirectory(const SmbNtCreateAndXResp* resp)
-{
-    return (resp->smb_directory ? true : false);
-}
-
-inline uint16_t SmbNtCreateAndXRespResourceType(const SmbNtCreateAndXResp* resp)
-{
-    return alignedNtohs(&resp->smb_resource_type);
-}
-
-inline uint64_t SmbNtCreateAndXRespEndOfFile(const SmbNtCreateAndXResp* resp)
-{
-    return alignedNtohq(&resp->smb_eof);
-}
-
-/********************************************************************
- * SMB_COM_TRANSACTION
- ********************************************************************/
-struct SmbTransactionReq   /* smb_wct = 14 + value of smb_suwcnt */
-{
-    /* Note all subcommands use a setup count of 2 */
-    uint8_t smb_wct;       /* count of 16-bit words that follow */
-    uint16_t smb_tpscnt;   /* total number of parameter bytes being sent */
-    uint16_t smb_tdscnt;   /* total number of data bytes being sent */
-    uint16_t smb_mprcnt;   /* max number of parameter bytes to return */
-    uint16_t smb_mdrcnt;   /* max number of data bytes to return */
-    uint8_t smb_msrcnt;    /* max number of setup words to return */
-    uint8_t smb_rsvd;      /* reserved (pad above to word) */
-    uint16_t smb_flags;    /* additional information:
-                              bit 0 - if set, also disconnect TID in smb_tid
-                              bit 1 - if set, transaction is one way (no final response) */
-    uint32_t smb_timeout;  /* number of milliseconds to wait for completion */
-    uint16_t smb_rsvd1;    /* reserved */
-    uint16_t smb_pscnt;    /* number of parameter bytes being sent this buffer */
-    uint16_t smb_psoff;    /* offset (from start of SMB hdr) to parameter bytes */
-    uint16_t smb_dscnt;    /* number of data bytes being sent this buffer */
-    uint16_t smb_dsoff;    /* offset (from start of SMB hdr) to data bytes */
-    uint8_t smb_suwcnt;    /* set up word count */
-    uint8_t smb_rsvd2;     /* reserved (pad above to word) */
-    uint16_t smb_setup1;   /* function (see below)
-                                TRANS_SET_NM_PIPE_STATE   = 0x0001
-                                TRANS_RAW_READ_NMPIPE     = 0x0011
-                                TRANS_QUERY_NMPIPE_STATE  = 0x0021
-                                TRANS_QUERY_NMPIPE_INFO   = 0x0022
-                                TRANS_PEEK_NMPIPE         = 0x0023
-                                TRANS_TRANSACT_NMPIPE     = 0x0026
-                                TRANS_RAW_WRITE_NMPIPE    = 0x0031
-                                TRANS_READ_NMPIPE         = 0x0036
-                                TRANS_WRITE_NMPIPE        = 0x0037
-                                TRANS_WAIT_NMPIPE         = 0x0053
-                                TRANS_CALL_NMPIPE         = 0x0054  */
-    uint16_t smb_setup2;   /* FID (handle) of pipe (if needed), or priority */
-    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
-};
-
-struct SmbTransactionInterimResp    /* smb_wct = 0 */
-{
-    uint8_t smb_wct;        /* count of 16-bit words that follow */
-    uint16_t smb_bcc;       /* must be 0 */
-};
-
-struct SmbTransactionResp   /* smb_wct = 10 + value of smb_suwcnt */
-{
-    /* Note all subcommands use a setup count of 0 */
-    uint8_t smb_wct;       /* count of 16-bit words that follow */
-    uint16_t smb_tprcnt;   /* total number of parameter bytes being returned */
-    uint16_t smb_tdrcnt;   /* total number of data bytes being returned */
-    uint16_t smb_rsvd;     /* reserved */
-    uint16_t smb_prcnt;    /* number of parameter bytes being returned this buf */
-    uint16_t smb_proff;    /* offset (from start of SMB hdr) to parameter bytes */
-    uint16_t smb_prdisp;   /* byte displacement for these parameter bytes */
-    uint16_t smb_drcnt;    /* number of data bytes being returned this buffer */
-    uint16_t smb_droff;    /* offset (from start of SMB hdr) to data bytes */
-    uint16_t smb_drdisp;   /* byte displacement for these data bytes */
-    uint8_t smb_suwcnt;    /* set up return word count */
-    uint8_t smb_rsvd1;     /* reserved (pad above to word) */
-    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
-};
-
-inline uint16_t SmbTransactionReqSubCom(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_setup1);
-}
-
-inline uint16_t SmbTransactionReqFid(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_setup2);
-}
-
-inline bool SmbTransactionReqDisconnectTid(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_flags) & 0x0001 ? true : false;
-}
-
-inline bool SmbTransactionReqOneWay(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_flags) & 0x0002 ? true : false;
-}
-
-inline uint8_t SmbTransactionReqSetupCnt(const SmbTransactionReq* req)
-{
-    return req->smb_suwcnt;
-}
-
-inline uint16_t SmbTransactionReqTotalDataCnt(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_tdscnt);
-}
-
-inline uint16_t SmbTransactionReqDataCnt(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_dscnt);
-}
-
-inline uint16_t SmbTransactionReqDataOff(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_dsoff);
-}
-
-inline uint16_t SmbTransactionReqTotalParamCnt(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_tpscnt);
-}
-
-inline uint16_t SmbTransactionReqParamCnt(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_pscnt);
-}
-
-inline uint16_t SmbTransactionReqParamOff(const SmbTransactionReq* req)
-{
-    return alignedNtohs(&req->smb_psoff);
-}
-
-inline uint16_t SmbTransactionRespTotalDataCnt(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_tdrcnt);
-}
-
-inline uint16_t SmbTransactionRespDataCnt(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_drcnt);
-}
-
-inline uint16_t SmbTransactionRespDataOff(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_droff);
-}
-
-inline uint16_t SmbTransactionRespDataDisp(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_drdisp);
-}
-
-inline uint16_t SmbTransactionRespTotalParamCnt(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_tprcnt);
-}
-
-inline uint16_t SmbTransactionRespParamCnt(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_prcnt);
-}
-
-inline uint16_t SmbTransactionRespParamOff(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_proff);
-}
-
-inline uint16_t SmbTransactionRespParamDisp(const SmbTransactionResp* resp)
-{
-    return alignedNtohs(&resp->smb_prdisp);
-}
-
-// Flags for TRANS_SET_NMPIPE_STATE parameters
-#define PIPE_STATE_NON_BLOCKING  0x8000
-#define PIPE_STATE_MESSAGE_MODE  0x0100
-
-/********************************************************************
- * SMB_COM_TRANSACTION2
- ********************************************************************/
-struct SmbTransaction2Req
-{
-    uint8_t smb_wct;
-    uint16_t smb_total_param_count;
-    uint16_t smb_total_data_count;
-    uint16_t smb_max_param_count;
-    uint16_t smb_max_data_count;
-    uint8_t smb_max_setup_count;
-    uint8_t smb_res;
-    uint16_t smb_flags;
-    uint32_t smb_timeout;
-    uint16_t smb_res2;
-    uint16_t smb_param_count;
-    uint16_t smb_param_offset;
-    uint16_t smb_data_count;
-    uint16_t smb_data_offset;
-    uint8_t smb_setup_count;    /* Should be 1 for all subcommands */
-    uint8_t smb_res3;
-    uint16_t smb_setup;  /* This is the subcommand */
-    uint16_t smb_bcc;
-};
-
-struct SmbTransaction2InterimResp
-{
-    uint8_t smb_wct;
-    uint16_t smb_bcc;
-};
-
-struct SmbTransaction2Resp
-{
-    uint8_t smb_wct;
-    uint16_t smb_total_param_count;
-    uint16_t smb_total_data_count;
-    uint16_t smb_res;
-    uint16_t smb_param_count;
-    uint16_t smb_param_offset;
-    uint16_t smb_param_disp;
-    uint16_t smb_data_count;
-    uint16_t smb_data_offset;
-    uint16_t smb_data_disp;
-    uint16_t smb_setup_count;  /* 0 or 1 word */
-    uint8_t smb_res2;
-};
-
-inline uint16_t SmbTransaction2ReqSubCom(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_setup);
-}
-
-inline uint16_t SmbTransaction2ReqTotalParamCnt(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_total_param_count);
-}
-
-inline uint16_t SmbTransaction2ReqParamCnt(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_param_count);
-}
-
-inline uint16_t SmbTransaction2ReqParamOff(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_param_offset);
-}
-
-inline uint16_t SmbTransaction2ReqTotalDataCnt(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_total_data_count);
-}
-
-inline uint16_t SmbTransaction2ReqDataCnt(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_data_count);
-}
-
-inline uint16_t SmbTransaction2ReqDataOff(const SmbTransaction2Req* req)
-{
-    return alignedNtohs(&req->smb_data_offset);
-}
-
-inline uint8_t SmbTransaction2ReqSetupCnt(const SmbTransaction2Req* req)
-{
-    return req->smb_setup_count;
-}
-
-inline uint16_t SmbTransaction2RespTotalParamCnt(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_total_param_count);
-}
-
-inline uint16_t SmbTransaction2RespParamCnt(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_param_count);
-}
-
-inline uint16_t SmbTransaction2RespParamOff(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_param_offset);
-}
-
-inline uint16_t SmbTransaction2RespParamDisp(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_param_disp);
-}
-
-inline uint16_t SmbTransaction2RespTotalDataCnt(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_total_data_count);
-}
-
-inline uint16_t SmbTransaction2RespDataCnt(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_data_count);
-}
-
-inline uint16_t SmbTransaction2RespDataOff(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_data_offset);
-}
-
-inline uint16_t SmbTransaction2RespDataDisp(const SmbTransaction2Resp* resp)
-{
-    return alignedNtohs(&resp->smb_data_disp);
-}
-
-struct SmbTrans2Open2ReqParams
-{
-    uint16_t Flags;
-    uint16_t AccessMode;
-    uint16_t Reserved1;
-    uint16_t FileAttributes;
-    uint32_t CreationTime;
-    uint16_t OpenMode;
-    uint32_t AllocationSize;
-    uint16_t Reserved[5];
-};
-
-typedef SmbTransaction2Req SmbTrans2Open2Req;
-
-inline uint16_t SmbTrans2Open2ReqAccessMode(const SmbTrans2Open2ReqParams* req)
-{
-    return alignedNtohs(&req->AccessMode);
-}
-
-inline uint16_t SmbTrans2Open2ReqFileAttrs(const SmbTrans2Open2ReqParams* req)
-{
-    return alignedNtohs(&req->FileAttributes);
-}
-
-inline uint16_t SmbTrans2Open2ReqOpenMode(const SmbTrans2Open2ReqParams* req)
-{
-    return alignedNtohs(&req->OpenMode);
-}
-
-inline uint32_t SmbTrans2Open2ReqAllocSize(const SmbTrans2Open2ReqParams* req)
-{
-    return alignedNtohl(&req->AllocationSize);
-}
-
-struct SmbTrans2Open2RespParams
-{
-    uint16_t smb_fid;
-    uint16_t file_attributes;
-    uint32_t creation_time;
-    uint32_t file_data_size;
-    uint16_t access_mode;
-    uint16_t resource_type;
-    uint16_t nm_pipe_status;
-    uint16_t action_taken;
-    uint32_t reserved;
-    uint16_t extended_attribute_error_offset;
-    uint32_t extended_attribute_length;
-};
-
-inline uint16_t SmbTrans2Open2RespFid(const SmbTrans2Open2RespParams* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-inline uint16_t SmbTrans2Open2RespFileAttrs(const SmbTrans2Open2RespParams* resp)
-{
-    return alignedNtohs(&resp->file_attributes);
-}
-
-inline uint32_t SmbTrans2Open2RespFileDataSize(const SmbTrans2Open2RespParams* resp)
-{
-    return alignedNtohl(&resp->file_data_size);
-}
-
-inline uint16_t SmbTrans2Open2RespResourceType(const SmbTrans2Open2RespParams* resp)
-{
-    return alignedNtohs(&resp->resource_type);
-}
-
-inline uint16_t SmbTrans2Open2RespActionTaken(const SmbTrans2Open2RespParams* resp)
-{
-    return alignedNtohs(&resp->action_taken);
-}
-
-struct SmbTrans2Open2Resp
-{
-    uint8_t smb_wct;
-    uint16_t smb_total_param_count;
-    uint16_t smb_total_data_count;
-    uint16_t smb_res;
-    uint16_t smb_param_count;
-    uint16_t smb_param_offset;
-    uint16_t smb_param_disp;
-    uint16_t smb_data_count;
-    uint16_t smb_data_offset;
-    uint16_t smb_data_disp;
-    uint16_t smb_setup_count;  /* 0 */
-    uint8_t smb_res2;
-    uint16_t smb_bcc;
-};
-
-// See MS-CIFS Section 2.2.2.3.3
-#define SMB_INFO_STANDARD               0x0001
-#define SMB_INFO_QUERY_EA_SIZE          0x0002
-#define SMB_INFO_QUERY_EAS_FROM_LIST    0x0003
-#define SMB_INFO_QUERY_ALL_EAS          0x0004
-#define SMB_INFO_IS_NAME_VALID          0x0006
-#define SMB_QUERY_FILE_BASIC_INFO       0x0101
-#define SMB_QUERY_FILE_STANDARD_INFO    0x0102
-#define SMB_QUERY_FILE_EA_INFO          0x0103
-#define SMB_QUERY_FILE_NAME_INFO        0x0104
-#define SMB_QUERY_FILE_ALL_INFO         0x0107
-#define SMB_QUERY_FILE_ALT_NAME_INFO    0x0108
-#define SMB_QUERY_FILE_STREAM_INFO      0x0109
-#define SMB_QUERY_FILE_COMPRESSION_INFO 0x010b
-
-// See MS-SMB Section 2.2.2.3.5
-// For added value, see below from MS-FSCC
-#define SMB_INFO_PASSTHROUGH  0x03e8
-#define SMB_INFO_PT_FILE_STANDARD_INFO  SMB_INFO_PASSTHROUGH+5
-#define SMB_INFO_PT_FILE_ALL_INFO       SMB_INFO_PASSTHROUGH+18
-#define SMB_INFO_PT_FILE_STREAM_INFO    SMB_INFO_PASSTHROUGH+22
-#define SMB_INFO_PT_NETWORK_OPEN_INFO   SMB_INFO_PASSTHROUGH+34
-
-struct SmbTrans2QueryFileInfoReqParams
-{
-    uint16_t fid;
-    uint16_t information_level;
-};
-
-inline uint16_t SmbTrans2QueryFileInfoReqFid(const SmbTrans2QueryFileInfoReqParams* req)
-{
-    return alignedNtohs(&req->fid);
-}
-
-inline uint16_t SmbTrans2QueryFileInfoReqInfoLevel(const SmbTrans2QueryFileInfoReqParams* req)
-{
-    return alignedNtohs(&req->information_level);
-}
-
-struct SmbQueryInfoStandard
-{
-    uint16_t CreationDate;
-    uint16_t CreationTime;
-    uint16_t LastAccessDate;
-    uint16_t LastAccessTime;
-    uint16_t LastWriteDate;
-    uint16_t LastWriteTime;
-    uint32_t FileDataSize;
-    uint32_t AllocationSize;
-    uint16_t Attributes;
-};
-
-inline uint32_t SmbQueryInfoStandardFileDataSize(const SmbQueryInfoStandard* q)
-{
-    return alignedNtohl(&q->FileDataSize);
-}
-
-struct SmbQueryInfoQueryEaSize
-{
-    uint16_t CreationDate;
-    uint16_t CreationTime;
-    uint16_t LastAccessDate;
-    uint16_t LastAccessTime;
-    uint16_t LastWriteDate;
-    uint16_t LastWriteTime;
-    uint32_t FileDataSize;
-    uint32_t AllocationSize;
-    uint16_t Attributes;
-    uint32_t EaSize;
-};
-
-inline uint32_t SmbQueryInfoQueryEaSizeFileDataSize(const SmbQueryInfoQueryEaSize* q)
-{
-    return alignedNtohl(&q->FileDataSize);
-}
-
-struct SmbQueryFileStandardInfo
-{
-    uint64_t AllocationSize;
-    uint64_t EndOfFile;
-    uint32_t NumberOfLinks;
-    uint8_t DeletePending;
-    uint8_t Directory;
-    uint16_t Reserved;
-};
-
-inline uint64_t SmbQueryFileStandardInfoEndOfFile(const SmbQueryFileStandardInfo* q)
-{
-    return alignedNtohq(&q->EndOfFile);
-}
-
-struct SmbQueryFileAllInfo
-{
-    // Basic Info
-    uint64_t CreationTime;
-    uint64_t LastAccessTime;
-    uint64_t LastWriteTime;
-    uint64_t LastChangeTime;
-    uint32_t ExtFileAttributes;
-    uint32_t Reserved1;
-    uint64_t AllocationSize;
-    uint64_t EndOfFile;
-    uint32_t NumberOfLinks;
-    uint8_t DeletePending;
-    uint8_t Directory;
-    uint16_t Reserved2;
-    uint32_t EaSize;
-    uint32_t FileNameLength;
-};
-
-inline uint64_t SmbQueryFileAllInfoEndOfFile(const SmbQueryFileAllInfo* q)
-{
-    return alignedNtohq(&q->EndOfFile);
-}
-
-struct SmbQueryPTFileAllInfo
-{
-    // Basic Info
-    uint64_t CreationTime;
-    uint64_t LastAccessTime;
-    uint64_t LastWriteTime;
-    uint64_t LastChangeTime;
-    uint32_t ExtFileAttributes;
-    uint32_t Reserved1;
-
-    // Standard Info
-    uint64_t AllocationSize;
-    uint64_t EndOfFile;
-    uint32_t NumberOfLinks;
-    uint8_t DeletePending;
-    uint8_t Directory;
-    uint16_t Reserved2;
-
-    // Internal Info
-    uint64_t IndexNumber;
-
-    // EA Info
-    uint32_t EaSize;
-
-    // Access Info
-    uint32_t AccessFlags;
-
-    // Position Info
-    uint64_t CurrentByteOffset;
-
-    // Mode Info
-    uint32_t Mode;
-
-    // Alignment Info
-    uint32_t AlignmentRequirement;
-
-    // Name Info
-    uint32_t FileNameLength;
-};
-
-inline uint64_t SmbQueryPTFileAllInfoEndOfFile(const SmbQueryPTFileAllInfo* q)
-{
-    return alignedNtohq(&q->EndOfFile);
-}
-
-struct SmbQueryPTNetworkOpenInfo
-{
-    uint64_t CreationTime;
-    uint64_t LastAccessTime;
-    uint64_t LastWriteTime;
-    uint64_t LastChangeTime;
-    uint64_t AllocationSize;
-    uint64_t EndOfFile;
-    uint32_t FileAttributes;
-    uint32_t Reserved;
-};
-
-inline uint64_t SmbQueryPTNetworkOpenInfoEndOfFile(const SmbQueryPTNetworkOpenInfo* q)
-{
-    return alignedNtohq(&q->EndOfFile);
-}
-
-struct SmbQueryPTFileStreamInfo
-{
-    uint32_t NextEntryOffset;
-    uint32_t StreamNameLength;
-    uint64_t StreamSize;
-    uint64_t StreamAllocationSize;
-};
-
-inline uint64_t SmbQueryPTFileStreamInfoStreamSize(const SmbQueryPTFileStreamInfo* q)
-{
-    return alignedNtohq(&q->StreamSize);
-}
-
-struct SmbTrans2QueryFileInformationResp
-{
-    uint8_t smb_wct;
-    uint16_t smb_total_param_count;
-    uint16_t smb_total_data_count;
-    uint16_t smb_res;
-    uint16_t smb_param_count;
-    uint16_t smb_param_offset;
-    uint16_t smb_param_disp;
-    uint16_t smb_data_count;
-    uint16_t smb_data_offset;
-    uint16_t smb_data_disp;
-    uint16_t smb_setup_count;  /* 0 */
-    uint8_t smb_res2;
-    uint16_t smb_bcc;
-};
-
-#define SMB_INFO_SET_EAS               0x0002
-#define SMB_SET_FILE_BASIC_INFO        0x0101
-#define SMB_SET_FILE_DISPOSITION_INFO  0x0102
-#define SMB_SET_FILE_ALLOCATION_INFO   0x0103
-#define SMB_SET_FILE_END_OF_FILE_INFO  0x0104
-
-// For added value, see above File Information Classes
-#define SMB_INFO_PT_SET_FILE_BASIC_FILE_INFO   SMB_INFO_PASSTHROUGH+4
-#define SMB_INFO_PT_SET_FILE_END_OF_FILE_INFO  SMB_INFO_PASSTHROUGH+20
-
-struct SmbTrans2SetFileInfoReqParams
-{
-    uint16_t fid;
-    uint16_t information_level;
-    uint16_t reserved;
-};
-
-inline uint16_t SmbTrans2SetFileInfoReqFid(const SmbTrans2SetFileInfoReqParams* req)
-{
-    return alignedNtohs(&req->fid);
-}
-
-inline uint16_t SmbTrans2SetFileInfoReqInfoLevel(const SmbTrans2SetFileInfoReqParams* req)
-{
-    return alignedNtohs(&req->information_level);
-}
-
-inline bool SmbSetFileInfoEndOfFile(const uint16_t info_level)
-{
-    return ((info_level == SMB_SET_FILE_END_OF_FILE_INFO)
-           || (info_level == SMB_INFO_PT_SET_FILE_END_OF_FILE_INFO));
-}
-
-struct SmbSetFileBasicInfo
-{
-    uint64_t CreationTime;
-    uint64_t LastAccessTime;
-    uint64_t LastWriteTime;
-    uint64_t ChangeTime;
-    uint32_t ExtFileAttributes;
-    uint32_t Reserved;
-};
-
-inline uint32_t SmbSetFileInfoExtFileAttrs(const SmbSetFileBasicInfo* info)
-{
-    return alignedNtohl(&info->ExtFileAttributes);
-}
-
-inline bool SmbSetFileInfoSetFileBasicInfo(const uint16_t info_level)
-{
-    return ((info_level == SMB_SET_FILE_BASIC_INFO)
-           || (info_level == SMB_INFO_PT_SET_FILE_BASIC_FILE_INFO));
-}
-
-/********************************************************************
- * SMB_COM_NT_TRANSACT
- ********************************************************************/
-#define SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY     0x00000004
-
-struct SmbNtTransactReq
-{
-    uint8_t smb_wct;
-    uint8_t smb_max_setup_count;
-    uint16_t smb_res;
-    uint32_t smb_total_param_count;
-    uint32_t smb_total_data_count;
-    uint32_t smb_max_param_count;
-    uint32_t smb_max_data_count;
-    uint32_t smb_param_count;
-    uint32_t smb_param_offset;
-    uint32_t smb_data_count;
-    uint32_t smb_data_offset;
-    uint8_t smb_setup_count;
-    uint16_t smb_function;
-};
-
-struct SmbNtTransactInterimResp
-{
-    uint8_t smb_wct;
-    uint16_t smb_bcc;
-};
-
-struct SmbNtTransactResp
-{
-    uint8_t smb_wct;
-    uint8_t smb_res[3];
-    uint32_t smb_total_param_count;
-    uint32_t smb_total_data_count;
-    uint32_t smb_param_count;
-    uint32_t smb_param_offset;
-    uint32_t smb_param_disp;
-    uint32_t smb_data_count;
-    uint32_t smb_data_offset;
-    uint32_t smb_data_disp;
-    uint8_t smb_setup_count;
-};
-
-inline uint16_t SmbNtTransactReqSubCom(const SmbNtTransactReq* req)
-{
-    return alignedNtohs(&req->smb_function);
-}
-
-inline uint8_t SmbNtTransactReqSetupCnt(const SmbNtTransactReq* req)
-{
-    return req->smb_setup_count;
-}
-
-inline uint32_t SmbNtTransactReqTotalParamCnt(const SmbNtTransactReq* req)
-{
-    return alignedNtohl(&req->smb_total_param_count);
-}
-
-inline uint32_t SmbNtTransactReqParamCnt(const SmbNtTransactReq* req)
-{
-    return alignedNtohl(&req->smb_param_count);
-}
-
-inline uint32_t SmbNtTransactReqParamOff(const SmbNtTransactReq* req)
-{
-    return alignedNtohl(&req->smb_param_offset);
-}
-
-inline uint32_t SmbNtTransactReqTotalDataCnt(const SmbNtTransactReq* req)
-{
-    return alignedNtohl(&req->smb_total_data_count);
-}
-
-inline uint32_t SmbNtTransactReqDataCnt(const SmbNtTransactReq* req)
-{
-    return alignedNtohl(&req->smb_data_count);
-}
-
-inline uint32_t SmbNtTransactReqDataOff(const SmbNtTransactReq* req)
-{
-    return alignedNtohl(&req->smb_data_offset);
-}
-
-inline uint32_t SmbNtTransactRespTotalParamCnt(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_total_param_count);
-}
-
-inline uint32_t SmbNtTransactRespParamCnt(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_param_count);
-}
-
-inline uint32_t SmbNtTransactRespParamOff(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_param_offset);
-}
-
-inline uint32_t SmbNtTransactRespParamDisp(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_param_disp);
-}
-
-inline uint32_t SmbNtTransactRespTotalDataCnt(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_total_data_count);
-}
-
-inline uint32_t SmbNtTransactRespDataCnt(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_data_count);
-}
-
-inline uint32_t SmbNtTransactRespDataOff(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_data_offset);
-}
-
-inline uint32_t SmbNtTransactRespDataDisp(const SmbNtTransactResp* resp)
-{
-    return alignedNtohl(&resp->smb_data_disp);
-}
-
-struct SmbNtTransactCreateReqParams
-{
-    uint32_t flags;
-    uint32_t root_dir_fid;
-    uint32_t desired_access;
-    uint64_t allocation_size;
-    uint32_t ext_file_attributes;
-    uint32_t share_access;
-    uint32_t create_disposition;
-    uint32_t create_options;
-    uint32_t security_descriptor_length;
-    uint32_t ea_length;
-    uint32_t name_length;
-    uint32_t impersonation_level;
-    uint8_t security_flags;
-};
-
-inline uint64_t SmbNtTransactCreateReqAllocSize(const SmbNtTransactCreateReqParams* req)
-{
-    return alignedNtohq(&req->allocation_size);
-}
-
-inline uint32_t SmbNtTransactCreateReqFileNameLength(const SmbNtTransactCreateReqParams* req)
-{
-    return alignedNtohl(&req->name_length);
-}
-
-inline uint32_t SmbNtTransactCreateReqFileAttrs(const SmbNtTransactCreateReqParams* req)
-{
-    return alignedNtohl(&req->ext_file_attributes);
-}
-
-inline bool SmbNtTransactCreateReqSequentialOnly(const SmbNtTransactCreateReqParams* req)
-{
-    return (alignedNtohl(&req->create_options) & SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY);
-}
-
-struct SmbNtTransactCreateReq
-{
-    uint8_t smb_wct;
-    uint8_t smb_max_setup_count;
-    uint16_t smb_res;
-    uint32_t smb_total_param_count;
-    uint32_t smb_total_data_count;
-    uint32_t smb_max_param_count;
-    uint32_t smb_max_data_count;
-    uint32_t smb_param_count;
-    uint32_t smb_param_offset;
-    uint32_t smb_data_count;
-    uint32_t smb_data_offset;
-    uint8_t smb_setup_count;    /* Must be 0x00 */
-    uint16_t smb_function;      /* NT_TRANSACT_CREATE */
-    uint16_t smb_bcc;
-};
-
-struct SmbNtTransactCreateRespParams
-{
-    uint8_t op_lock_level;
-    uint8_t reserved;
-    uint16_t smb_fid;
-    uint32_t create_action;
-    uint32_t ea_error_offset;
-    uint64_t creation_time;
-    uint64_t last_access_time;
-    uint64_t last_write_time;
-    uint64_t last_change_time;
-    uint32_t ext_file_attributes;
-    uint64_t allocation_size;
-    uint64_t end_of_file;
-    uint16_t resource_type;
-    uint16_t nm_pipe_status;
-    uint8_t directory;
-};
-
-inline uint16_t SmbNtTransactCreateRespFid(const SmbNtTransactCreateRespParams* resp)
-{
-    return alignedNtohs(&resp->smb_fid);
-}
-
-inline uint32_t SmbNtTransactCreateRespCreateAction(const SmbNtTransactCreateRespParams* resp)
-{
-    return alignedNtohl(&resp->create_action);
-}
-
-inline uint64_t SmbNtTransactCreateRespEndOfFile(const SmbNtTransactCreateRespParams* resp)
-{
-    return alignedNtohq(&resp->end_of_file);
-}
-
-inline uint16_t SmbNtTransactCreateRespResourceType(const SmbNtTransactCreateRespParams* resp)
-{
-    return alignedNtohs(&resp->resource_type);
-}
-
-inline bool SmbNtTransactCreateRespDirectory(const SmbNtTransactCreateRespParams* resp)
-{
-    return (resp->directory ? true : false);
-}
-
-struct SmbNtTransactCreateResp
-{
-    uint8_t smb_wct;
-    uint8_t smb_res[3];
-    uint32_t smb_total_param_count;
-    uint32_t smb_total_data_count;
-    uint32_t smb_param_count;
-    uint32_t smb_param_offset;
-    uint32_t smb_param_disp;
-    uint32_t smb_data_count;
-    uint32_t smb_data_offset;
-    uint32_t smb_data_disp;
-    uint8_t smb_setup_count;    /* 0x00 */
-    uint16_t smb_bcc;
-};
-
-/********************************************************************
- * SMB_COM_TRANSACTION_SECONDARY
- *  Continuation command for SMB_COM_TRANSACTION requests if all
- *  data wasn't sent.
- ********************************************************************/
-struct SmbTransactionSecondaryReq   /* smb_wct = 8 */
-{
-    uint8_t smb_wct;       /* count of 16-bit words that follow */
-    uint16_t smb_tpscnt;   /* total number of parameter bytes being sent */
-    uint16_t smb_tdscnt;   /* total number of data bytes being sent */
-    uint16_t smb_pscnt;    /* number of parameter bytes being sent this buffer */
-    uint16_t smb_psoff;    /* offset (from start of SMB hdr) to parameter bytes */
-    uint16_t smb_psdisp;   /* byte displacement for these parameter bytes */
-    uint16_t smb_dscnt;    /* number of data bytes being sent this buffer */
-    uint16_t smb_dsoff;    /* offset (from start of SMB hdr) to data bytes */
-    uint16_t smb_dsdisp;   /* byte displacement for these data bytes */
-    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
-};
-
-inline uint16_t SmbTransactionSecondaryReqTotalDataCnt(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_tdscnt);
-}
-
-inline uint16_t SmbTransactionSecondaryReqDataCnt(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_dscnt);
-}
-
-inline uint16_t SmbTransactionSecondaryReqDataOff(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_dsoff);
-}
-
-inline uint16_t SmbTransactionSecondaryReqDataDisp(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_dsdisp);
-}
-
-inline uint16_t SmbTransactionSecondaryReqTotalParamCnt(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_tpscnt);
-}
-
-inline uint16_t SmbTransactionSecondaryReqParamCnt(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_pscnt);
-}
-
-inline uint16_t SmbTransactionSecondaryReqParamOff(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_psoff);
-}
-
-inline uint16_t SmbTransactionSecondaryReqParamDisp(const SmbTransactionSecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_psdisp);
-}
-
-/********************************************************************
- * SMB_COM_TRANSACTION2_SECONDARY
- *  Continuation command for SMB_COM_TRANSACTION2 requests if all
- *  data wasn't sent.
- ********************************************************************/
-struct SmbTransaction2SecondaryReq
-{
-    uint8_t smb_wct;
-    uint16_t smb_total_param_count;
-    uint16_t smb_total_data_count;
-    uint16_t smb_param_count;
-    uint16_t smb_param_offset;
-    uint16_t smb_param_disp;
-    uint16_t smb_data_count;
-    uint16_t smb_data_offset;
-    uint16_t smb_data_disp;
-    uint16_t smb_fid;
-    uint16_t smb_bcc;
-};
-
-inline uint16_t SmbTransaction2SecondaryReqTotalParamCnt(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_total_param_count);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqParamCnt(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_param_count);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqParamOff(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_param_offset);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqParamDisp(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_param_disp);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqTotalDataCnt(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_total_data_count);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqDataCnt(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_data_count);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqDataOff(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_data_offset);
-}
-
-inline uint16_t SmbTransaction2SecondaryReqDataDisp(const SmbTransaction2SecondaryReq* req)
-{
-    return alignedNtohs(&req->smb_data_disp);
-}
-
-/********************************************************************
- * SMB_COM_NT_TRANSACT_SECONDARY
- ********************************************************************/
-struct SmbNtTransactSecondaryReq
-{
-    uint8_t smb_wct;
-    uint8_t smb_res[3];
-    uint32_t smb_total_param_count;
-    uint32_t smb_total_data_count;
-    uint32_t smb_param_count;
-    uint32_t smb_param_offset;
-    uint32_t smb_param_disp;
-    uint32_t smb_data_count;
-    uint32_t smb_data_offset;
-    uint32_t smb_data_disp;
-    uint8_t smb_res2;
-};
-
-inline uint32_t SmbNtTransactSecondaryReqTotalParamCnt(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_total_param_count);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqParamCnt(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_param_count);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqParamOff(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_param_offset);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqParamDisp(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_param_disp);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqTotalDataCnt(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_total_data_count);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqDataCnt(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_data_count);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqDataOff(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_data_offset);
-}
-
-inline uint32_t SmbNtTransactSecondaryReqDataDisp(const SmbNtTransactSecondaryReq* req)
-{
-    return alignedNtohl(&req->smb_data_disp);
-}
-
-/********************************************************************
- * SMB_COM_READ_RAW
- ********************************************************************/
-struct SmbReadRawReq   /* smb_wct = 8 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint16_t smb_fid;        /* file handle */
-    uint32_t smb_offset;     /* offset in file to begin read */
-    uint16_t smb_maxcnt;     /* max number of bytes to return (max 65,535) */
-    uint16_t smb_mincnt;     /* min number of bytes to return (normally 0) */
-    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
-    uint16_t smb_rsvd;       /* reserved */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-struct SmbReadRawExtReq   /* smb_wct = 10 */
-{
-    uint8_t smb_wct;         /* count of 16-bit words that follow */
-    uint16_t smb_fid;        /* file handle */
-    uint32_t smb_offset;     /* offset in file to begin read */
-    uint16_t smb_maxcnt;     /* max number of bytes to return (max 65,535) */
-    uint16_t smb_mincnt;     /* min number of bytes to return (normally 0) */
-    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
-    uint16_t smb_rsvd;       /* reserved */
-    uint32_t smb_off_high;   /* high offset in file to begin write */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-/* Read Raw response is raw data wrapped in NetBIOS header */
-
-inline uint16_t SmbReadRawReqFid(const SmbReadRawReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint64_t SmbReadRawReqOffset(const SmbReadRawExtReq* req)
-{
-    if (req->smb_wct == 8)
-        return (uint64_t)alignedNtohl(&req->smb_offset);
-    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
-        &req->smb_offset);
-}
-
-/********************************************************************
- * SMB_COM_WRITE_RAW
- ********************************************************************/
-struct SmbWriteRawReq
-{
-    uint8_t smb_wct;       /* value = 12 */
-    uint16_t smb_fid;      /* file handle */
-    uint16_t smb_tcount;   /* total bytes (including this buf, 65,535 max ) */
-    uint16_t smb_rsvd;     /* reserved */
-    uint32_t smb_offset;   /* offset in file to begin write */
-    uint32_t smb_timeout;  /* number of milliseconds to wait for completion */
-    uint16_t smb_wmode;    /* write mode:
-                              bit0 - complete write to disk and send final result response
-                              bit1 - return smb_remaining (pipes/devices only) */
-    uint32_t smb_rsvd2;    /* reserved */
-    uint16_t smb_dsize;    /* number of data bytes this buffer (min value = 0) */
-    uint16_t smb_doff;     /* offset (from start of SMB hdr) to data bytes */
-    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
-};
-
-struct SmbWriteRawExtReq
-{
-    uint8_t smb_wct;       /* value = 14 */
-    uint16_t smb_fid;      /* file handle */
-    uint16_t smb_tcount;   /* total bytes (including this buf, 65,535 max ) */
-    uint16_t smb_rsvd;     /* reserved */
-    uint32_t smb_offset;   /* offset in file to begin write */
-    uint32_t smb_timeout;  /* number of milliseconds to wait for completion */
-    uint16_t smb_wmode;    /* write mode:
-                              bit0 - complete write to disk and send final result response
-                              bit1 - return smb_remaining (pipes/devices only) */
-    uint32_t smb_rsvd2;    /* reserved */
-    uint16_t smb_dsize;    /* number of data bytes this buffer (min value = 0) */
-    uint16_t smb_doff;     /* offset (from start of SMB hdr) to data bytes */
-    uint32_t smb_off_high; /* high offset in file to begin write */
-    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
-};
-
-struct SmbWriteRawInterimResp
-{
-    uint8_t smb_wct;         /* value = 1 */
-    uint16_t smb_remaining;  /* bytes remaining to be read (pipes/devices only) */
-    uint16_t smb_bcc;        /* value = 0 */
-};
-
-inline uint16_t SmbWriteRawReqTotalCount(const SmbWriteRawReq* req)
-{
-    return alignedNtohs(&req->smb_tcount);
-}
-
-inline bool SmbWriteRawReqWriteThrough(const SmbWriteRawReq* req)
-{
-    return alignedNtohs(&req->smb_wmode) & 0x0001;
-}
-
-inline uint16_t SmbWriteRawReqFid(const SmbWriteRawReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint16_t SmbWriteRawReqDataOff(const SmbWriteRawReq* req)
-{
-    return alignedNtohs(&req->smb_doff);
-}
-
-inline uint16_t SmbWriteRawReqDataCnt(const SmbWriteRawReq* req)
-{
-    return alignedNtohs(&req->smb_dsize);
-}
-
-inline uint64_t SmbWriteRawReqOffset(const SmbWriteRawExtReq* req)
-{
-    if (req->smb_wct == 12)
-        return (uint64_t)alignedNtohl(&req->smb_offset);
-    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
-        &req->smb_offset);
-}
-
-inline uint16_t SmbWriteRawInterimRespRemaining(const SmbWriteRawInterimResp* resp)
-{
-    return alignedNtohs(&resp->smb_remaining);
-}
-
-/********************************************************************
- * SMB_COM_WRITE_COMPLETE - final response to an SMB_COM_WRITE_RAW
- ********************************************************************/
-struct SmbWriteCompleteResp
-{
-    uint8_t smb_wct;     /* value = 1 */
-    uint16_t smb_count;  /* total number of bytes written */
-    uint16_t smb_bcc;    /* value = 0 */
-};
-
-inline uint16_t SmbWriteCompleteRespCount(const SmbWriteCompleteResp* resp)
-{
-    return alignedNtohs(&resp->smb_count);
-}
-
-/********************************************************************
- * SMB_COM_WRITE_AND_CLOSE
- ********************************************************************/
-struct SmbWriteAndCloseReq   /* smb_wct = 6 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;     /* file handle (close after write) */
-    uint16_t smb_count;   /* number of bytes to write */
-    uint32_t smb_offset;  /* offset in file to begin write */
-    uint32_t smb_mtime;   /* modification time */
-    uint16_t smb_bcc;     /* 1 (for pad) + value of smb_count */
-};
-
-struct SmbWriteAndCloseExtReq   /* smb_wct = 12 */
-{
-    uint8_t smb_wct;      /* count of 16-bit words that follow */
-    uint16_t smb_fid;     /* file handle (close after write) */
-    uint16_t smb_count;   /* number of bytes to write */
-    uint32_t smb_offset;  /* offset in file to begin write */
-    uint32_t smb_mtime;   /* modification time */
-    uint32_t smb_rsvd1;   /* Optional */
-    uint32_t smb_rsvd2;   /* Optional */
-    uint32_t smb_rsvd3;   /* Optional */
-    uint16_t smb_bcc;     /* 1 (for pad) + value of smb_count */
-};
-
-struct SmbWriteAndCloseResp   /* smb_wct = 1 */
-{
-    uint8_t smb_wct;     /* count of 16-bit words that follow */
-    uint16_t smb_count;  /* number of bytes written */
-    uint16_t smb_bcc;    /* must be 0 */
-};
-
-inline uint16_t SmbWriteAndCloseReqFid(const SmbWriteAndCloseReq* req)
-{
-    return alignedNtohs(&req->smb_fid);
-}
-
-inline uint16_t SmbWriteAndCloseReqCount(const SmbWriteAndCloseReq* req)
-{
-    return alignedNtohs(&req->smb_count);
-}
-
-inline uint32_t SmbWriteAndCloseReqOffset(const SmbWriteAndCloseReq* req)
-{
-    return alignedNtohl(&req->smb_offset);
-}
-
-inline uint16_t SmbWriteAndCloseRespCount(const SmbWriteAndCloseResp* resp)
-{
-    return alignedNtohs(&resp->smb_count);
-}
-
-#pragma pack()
-
 struct DCE2_SmbFsm
 {
     char input;
@@ -3065,5 +487,6 @@ public:
 
 DCE2_SmbSsnData* get_dce2_smb_session_data(Flow*);
 
+const char* get_smb_com_string(uint8_t);
 #endif
 
diff --git a/src/service_inspectors/dce_rpc/smb_common.h b/src/service_inspectors/dce_rpc/smb_common.h
new file mode 100644 (file)
index 0000000..10f39d9
--- /dev/null
@@ -0,0 +1,459 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// smb_common.h author Russ Combs <rucombs@cisco.com>
+
+// extracted from dce_smb.h originally written by Todd Wease
+
+#ifndef SMB_COMMON_H
+#define SMB_COMMON_H
+
+#include <stdint.h>
+
+#define SMB_MAX_NUM_COMS   256
+
+#define SMB_FILE_TYPE_DISK               0x0000
+#define SMB_FILE_TYPE_BYTE_MODE_PIPE     0x0001
+#define SMB_FILE_TYPE_MESSAGE_MODE_PIPE  0x0002
+#define SMB_FILE_TYPE_PRINTER            0x0003
+#define SMB_FILE_TYPE_COMMON_DEVICE      0x0004
+
+#define SMB_FILE_ATTRIBUTE_NORMAL       0x0000
+#define SMB_FILE_ATTRIBUTE_READONLY     0x0001
+#define SMB_FILE_ATTRIBUTE_HIDDEN       0x0002
+#define SMB_FILE_ATTRIBUTE_SYSTEM       0x0004
+#define SMB_FILE_ATTRIBUTE_VOLUME       0x0008
+#define SMB_FILE_ATTRIBUTE_DIRECTORY    0x0010
+#define SMB_FILE_ATTRIBUTE_ARCHIVE      0x0020
+#define SMB_SEARCH_ATTRIBUTE_READONLY   0x0100
+#define SMB_SEARCH_ATTRIBUTE_HIDDEN     0x0200
+#define SMB_SEARCH_ATTRIBUTE_SYSTEM     0x0400
+#define SMB_SEARCH_ATTRIBUTE_DIRECTORY  0x1000
+#define SMB_SEARCH_ATTRIBUTE_ARCHIVE    0x2000
+#define SMB_FILE_ATTRIBUTE_OTHER        0xC8C0   // Reserved
+
+#define SMB_EXT_FILE_ATTR_READONLY    0x00000001
+#define SMB_EXT_FILE_ATTR_HIDDEN      0x00000002
+#define SMB_EXT_FILE_ATTR_SYSTEM      0x00000004
+#define SMB_EXT_FILE_ATTR_DIRECTORY   0x00000010
+#define SMB_EXT_FILE_ATTR_ARCHIVE     0x00000020
+#define SMB_EXT_FILE_ATTR_NORMAL      0x00000080
+#define SMB_EXT_FILE_ATTR_TEMPORARY   0x00000100
+#define SMB_EXT_FILE_ATTR_COMPRESSED  0x00000800
+#define SMB_EXT_FILE_POSIX_SEMANTICS  0x01000000
+#define SMB_EXT_FILE_BACKUP_SEMANTICS 0x02000000
+#define SMB_EXT_FILE_DELETE_ON_CLOSE  0x04000000
+#define SMB_EXT_FILE_SEQUENTIAL_SCAN  0x08000000
+#define SMB_EXT_FILE_RANDOM_ACCESS    0x10000000
+#define SMB_EXT_FILE_NO_BUFFERING     0x20000000
+#define SMB_EXT_FILE_WRITE_THROUGH    0x80000000
+
+#define NBSS_SESSION_TYPE__MESSAGE            0x00
+#define NBSS_SESSION_TYPE__REQUEST            0x81
+#define NBSS_SESSION_TYPE__POS_RESPONSE       0x82
+#define NBSS_SESSION_TYPE__NEG_RESPONSE       0x83
+#define NBSS_SESSION_TYPE__RETARGET_RESPONSE  0x84
+#define NBSS_SESSION_TYPE__KEEP_ALIVE         0x85
+
+#define DCE2_SMB_ID   0xff534d42  /* \xffSMB */
+#define DCE2_SMB2_ID  0xfe534d42  /* \xfeSMB */
+
+// MS-FSCC Section 2.1.5 - Pathname
+#define DCE2_SMB_MAX_PATH_LEN  32760
+#define DCE2_SMB_MAX_COMP_LEN    255
+
+/* SMB command codes */
+#define SMB_COM_CREATE_DIRECTORY 0x00
+#define SMB_COM_DELETE_DIRECTORY 0x01
+#define SMB_COM_OPEN 0x02
+#define SMB_COM_CREATE 0x03
+#define SMB_COM_CLOSE 0x04
+#define SMB_COM_FLUSH 0x05
+#define SMB_COM_DELETE 0x06
+#define SMB_COM_RENAME 0x07
+#define SMB_COM_QUERY_INFORMATION 0x08
+#define SMB_COM_SET_INFORMATION 0x09
+#define SMB_COM_READ 0x0A
+#define SMB_COM_WRITE 0x0B
+#define SMB_COM_LOCK_BYTE_RANGE 0x0C
+#define SMB_COM_UNLOCK_BYTE_RANGE 0x0D
+#define SMB_COM_CREATE_TEMPORARY 0x0E
+#define SMB_COM_CREATE_NEW 0x0F
+#define SMB_COM_CHECK_DIRECTORY 0x10
+#define SMB_COM_PROCESS_EXIT 0x11
+#define SMB_COM_SEEK 0x12
+#define SMB_COM_LOCK_AND_READ 0x13
+#define SMB_COM_WRITE_AND_UNLOCK 0x14
+#define SMB_COM_READ_RAW 0x1A
+#define SMB_COM_READ_MPX 0x1B
+#define SMB_COM_READ_MPX_SECONDARY 0x1C
+#define SMB_COM_WRITE_RAW 0x1D
+#define SMB_COM_WRITE_MPX 0x1E
+#define SMB_COM_WRITE_MPX_SECONDARY 0x1F
+#define SMB_COM_WRITE_COMPLETE 0x20
+#define SMB_COM_QUERY_SERVER 0x21
+#define SMB_COM_SET_INFORMATION2 0x22
+#define SMB_COM_QUERY_INFORMATION2 0x23
+#define SMB_COM_LOCKING_ANDX 0x24
+#define SMB_COM_TRANSACTION 0x25
+#define SMB_COM_TRANSACTION_SECONDARY 0x26
+#define SMB_COM_IOCTL 0x27
+#define SMB_COM_IOCTL_SECONDARY 0x28
+#define SMB_COM_COPY 0x29
+#define SMB_COM_MOVE 0x2A
+#define SMB_COM_ECHO 0x2B
+#define SMB_COM_WRITE_AND_CLOSE 0x2C
+#define SMB_COM_OPEN_ANDX 0x2D
+#define SMB_COM_READ_ANDX 0x2E
+#define SMB_COM_WRITE_ANDX 0x2F
+#define SMB_COM_NEW_FILE_SIZE 0x30
+#define SMB_COM_CLOSE_AND_TREE_DISC 0x31
+#define SMB_COM_TRANSACTION2 0x32
+#define SMB_COM_TRANSACTION2_SECONDARY 0x33
+#define SMB_COM_FIND_CLOSE2 0x34
+#define SMB_COM_FIND_NOTIFY_CLOSE 0x35
+#define SMB_COM_TREE_CONNECT 0x70
+#define SMB_COM_TREE_DISCONNECT 0x71
+#define SMB_COM_NEGOTIATE 0x72
+#define SMB_COM_SESSION_SETUP_ANDX 0x73
+#define SMB_COM_LOGOFF_ANDX 0x74
+#define SMB_COM_TREE_CONNECT_ANDX 0x75
+#define SMB_COM_SECURITY_PACKAGE_ANDX 0x7E
+#define SMB_COM_QUERY_INFORMATION_DISK 0x80
+#define SMB_COM_SEARCH 0x81
+#define SMB_COM_FIND 0x82
+#define SMB_COM_FIND_UNIQUE 0x83
+#define SMB_COM_FIND_CLOSE 0x84
+#define SMB_COM_NT_TRANSACT 0xA0
+#define SMB_COM_NT_TRANSACT_SECONDARY 0xA1
+#define SMB_COM_NT_CREATE_ANDX 0xA2
+#define SMB_COM_NT_CANCEL 0xA4
+#define SMB_COM_NT_RENAME 0xA5
+#define SMB_COM_OPEN_PRINT_FILE 0xC0
+#define SMB_COM_WRITE_PRINT_FILE 0xC1
+#define SMB_COM_CLOSE_PRINT_FILE 0xC2
+#define SMB_COM_GET_PRINT_QUEUE 0xC3
+#define SMB_COM_READ_BULK 0xD8
+#define SMB_COM_WRITE_BULK 0xD9
+#define SMB_COM_WRITE_BULK_DATA 0xDA
+#define SMB_COM_INVALID 0xFE
+#define SMB_COM_NO_ANDX_COMMAND 0xFF
+
+/* Size of word count field + Word count * 2 bytes + Size of byte count field */
+#define SMB_COM_SIZE(wct)  (sizeof(uint8_t) + ((wct) * sizeof(uint16_t)) + sizeof(uint16_t))
+
+#define SMB_FLG__TYPE  0x80
+#define SMB_TYPE__REQUEST   0
+#define SMB_TYPE__RESPONSE  1
+
+#define SMB_FLG2__UNICODE      0x8000
+#define SMB_FLG2__NT_CODES     0x4000
+
+#define SMB_NT_STATUS_SEVERITY__SUCCESS        0
+#define SMB_NT_STATUS_SEVERITY__INFORMATIONAL  1
+#define SMB_NT_STATUS_SEVERITY__WARNING        2
+#define SMB_NT_STATUS_SEVERITY__ERROR          3
+
+#define SMB_NT_STATUS__SUCCESS                0x00000000
+#define SMB_NT_STATUS__INVALID_DEVICE_REQUEST 0xc0000010
+#define SMB_NT_STATUS__RANGE_NOT_LOCKED       0xc000007e
+#define SMB_NT_STATUS__PIPE_BROKEN            0xc000014b
+#define SMB_NT_STATUS__PIPE_DISCONNECTED      0xc00000b0
+
+#define SMB_ERROR_CLASS__SUCCESS  0x00
+#define SMB_ERROR_CLASS__ERRDOS   0x01
+#define SMB_ERROR_CLASS__ERRSRV   0x02
+#define SMB_ERROR_CLASS__ERRHRD   0x03
+#define SMB_ERROR_CLASS__ERRXOS   0x04
+#define SMB_ERROR_CLASS__ERRMX1   0xe1
+#define SMB_ERROR_CLASS__ERRMX2   0xe2
+#define SMB_ERROR_CLASS__ERRMX3   0xe3
+#define SMB_ERROR_CLASS__ERRCMD   0xff
+
+#define SMB_ERRSRV__INVALID_DEVICE      0x0007
+#define SMB_ERRDOS__NOT_LOCKED          0x009e
+#define SMB_ERRDOS__BAD_PIPE            0x00e6
+#define SMB_ERRDOS__PIPE_NOT_CONNECTED  0x00e9
+#define SMB_ERRDOS__MORE_DATA           0x00ea
+
+enum SmbTransactionSubcommand
+{
+    TRANS_UNKNOWN_0000             = 0x0000,
+    TRANS_SET_NMPIPE_STATE         = 0x0001,
+    TRANS_UNKNOWN_0002             = 0x0002,
+    TRANS_UNKNOWN_0003             = 0x0003,
+    TRANS_UNKNOWN_0004             = 0x0004,
+    TRANS_UNKNOWN_0005             = 0x0005,
+    TRANS_UNKNOWN_0006             = 0x0006,
+    TRANS_UNKNOWN_0007             = 0x0007,
+    TRANS_UNKNOWN_0008             = 0x0008,
+    TRANS_UNKNOWN_0009             = 0x0009,
+    TRANS_UNKNOWN_000A             = 0x000A,
+    TRANS_UNKNOWN_000B             = 0x000B,
+    TRANS_UNKNOWN_000C             = 0x000C,
+    TRANS_UNKNOWN_000D             = 0x000D,
+    TRANS_UNKNOWN_000E             = 0x000E,
+    TRANS_UNKNOWN_000F             = 0x000F,
+    TRANS_UNKNOWN_0010             = 0x0010,
+    TRANS_RAW_READ_NMPIPE          = 0x0011,
+    TRANS_UNKNOWN_0012             = 0x0012,
+    TRANS_UNKNOWN_0013             = 0x0013,
+    TRANS_UNKNOWN_0014             = 0x0014,
+    TRANS_UNKNOWN_0015             = 0x0015,
+    TRANS_UNKNOWN_0016             = 0x0016,
+    TRANS_UNKNOWN_0017             = 0x0017,
+    TRANS_UNKNOWN_0018             = 0x0018,
+    TRANS_UNKNOWN_0019             = 0x0019,
+    TRANS_UNKNOWN_001A             = 0x001A,
+    TRANS_UNKNOWN_001B             = 0x001B,
+    TRANS_UNKNOWN_001C             = 0x001C,
+    TRANS_UNKNOWN_001D             = 0x001D,
+    TRANS_UNKNOWN_001E             = 0x001E,
+    TRANS_UNKNOWN_001F             = 0x001F,
+    TRANS_UNKNOWN_0020             = 0x0020,
+    TRANS_QUERY_NMPIPE_STATE       = 0x0021,
+    TRANS_QUERY_NMPIPE_INFO        = 0x0022,
+    TRANS_PEEK_NMPIPE              = 0x0023,
+    TRANS_UNKNOWN_0024             = 0x0024,
+    TRANS_UNKNOWN_0025             = 0x0025,
+    TRANS_TRANSACT_NMPIPE          = 0x0026,
+    TRANS_UNKNOWN_0027             = 0x0027,
+    TRANS_UNKNOWN_0028             = 0x0028,
+    TRANS_UNKNOWN_0029             = 0x0029,
+    TRANS_UNKNOWN_002A             = 0x002A,
+    TRANS_UNKNOWN_002B             = 0x002B,
+    TRANS_UNKNOWN_002C             = 0x002C,
+    TRANS_UNKNOWN_002D             = 0x002D,
+    TRANS_UNKNOWN_002E             = 0x002E,
+    TRANS_UNKNOWN_002F             = 0x002F,
+    TRANS_UNKNOWN_0030             = 0x0030,
+    TRANS_RAW_WRITE_NMPIPE         = 0x0031,
+    TRANS_UNKNOWN_0032             = 0x0032,
+    TRANS_UNKNOWN_0033             = 0x0033,
+    TRANS_UNKNOWN_0034             = 0x0034,
+    TRANS_UNKNOWN_0035             = 0x0035,
+    TRANS_READ_NMPIPE              = 0x0036,
+    TRANS_WRITE_NMPIPE             = 0x0037,
+    TRANS_UNKNOWN_0038             = 0x0038,
+    TRANS_UNKNOWN_0039             = 0x0039,
+    TRANS_UNKNOWN_003A             = 0x003A,
+    TRANS_UNKNOWN_003B             = 0x003B,
+    TRANS_UNKNOWN_003C             = 0x003C,
+    TRANS_UNKNOWN_003D             = 0x003D,
+    TRANS_UNKNOWN_003E             = 0x003E,
+    TRANS_UNKNOWN_003F             = 0x003F,
+    TRANS_UNKNOWN_0040             = 0x0040,
+    TRANS_UNKNOWN_0041             = 0x0041,
+    TRANS_UNKNOWN_0042             = 0x0042,
+    TRANS_UNKNOWN_0043             = 0x0043,
+    TRANS_UNKNOWN_0044             = 0x0044,
+    TRANS_UNKNOWN_0045             = 0x0045,
+    TRANS_UNKNOWN_0046             = 0x0046,
+    TRANS_UNKNOWN_0047             = 0x0047,
+    TRANS_UNKNOWN_0048             = 0x0048,
+    TRANS_UNKNOWN_0049             = 0x0049,
+    TRANS_UNKNOWN_004A             = 0x004A,
+    TRANS_UNKNOWN_004B             = 0x004B,
+    TRANS_UNKNOWN_004C             = 0x004C,
+    TRANS_UNKNOWN_004D             = 0x004D,
+    TRANS_UNKNOWN_004E             = 0x004E,
+    TRANS_UNKNOWN_004F             = 0x004F,
+    TRANS_UNKNOWN_0050             = 0x0050,
+    TRANS_UNKNOWN_0051             = 0x0051,
+    TRANS_UNKNOWN_0052             = 0x0052,
+    TRANS_WAIT_NMPIPE              = 0x0053,
+    TRANS_CALL_NMPIPE              = 0x0054,
+    TRANS_SUBCOM_MAX               = 0x0055
+};
+
+enum SmbTransaction2Subcommand
+{
+    TRANS2_OPEN2                        = 0x0000,
+    TRANS2_FIND_FIRST2                  = 0x0001,
+    TRANS2_FIND_NEXT2                   = 0x0002,
+    TRANS2_QUERY_FS_INFORMATION         = 0x0003,
+    TRANS2_SET_FS_INFORMATION           = 0x0004,
+    TRANS2_QUERY_PATH_INFORMATION       = 0x0005,
+    TRANS2_SET_PATH_INFORMATION         = 0x0006,
+    TRANS2_QUERY_FILE_INFORMATION       = 0x0007,
+    TRANS2_SET_FILE_INFORMATION         = 0x0008,
+    TRANS2_FSCTL                        = 0x0009,
+    TRANS2_IOCTL2                       = 0x000A,
+    TRANS2_FIND_NOTIFY_FIRST            = 0x000B,
+    TRANS2_FIND_NOTIFY_NEXT             = 0x000C,
+    TRANS2_CREATE_DIRECTORY             = 0x000D,
+    TRANS2_SESSION_SETUP                = 0x000E,
+    TRANS2_UNKNOWN_000F                 = 0x000F,
+    TRANS2_GET_DFS_REFERRAL             = 0x0010,
+    TRANS2_REPORT_DFS_INCONSISTENCY     = 0x0011,
+    TRANS2_SUBCOM_MAX                   = 0x0012
+};
+
+/********************************************************************
+ * Structures and inline accessor functions
+ ********************************************************************/
+/* Pack the structs since we'll be laying them on top of packet data */
+#pragma pack(1)
+
+/********************************************************************
+ * NetBIOS Session Service header
+ ********************************************************************/
+struct NbssHdr
+{
+    uint8_t type;
+    uint8_t flags;   /* Treat flags as the upper byte to length */
+    uint16_t length;
+};
+
+struct SmbNtHdr
+{
+    uint8_t smb_idf[4];             /* contains 0xFF, 'SMB' */
+    uint8_t smb_com;                /* command code */
+    union
+    {
+        struct
+        {
+            uint8_t smb_class;      /* dos error class */
+            uint8_t smb_res;        /* reserved for future */
+            uint16_t smb_code;      /* dos error code */
+        } smb_status;
+        uint32_t nt_status;         /* nt status */
+    } smb_status;
+    uint8_t smb_flg;                /* flags */
+    uint16_t smb_flg2;              /* flags */
+    uint16_t smb_pid_high;
+    uint64_t smb_signature;
+    uint16_t smb_res;               /* reserved for future */
+    uint16_t smb_tid;               /* tree id */
+    uint16_t smb_pid;               /* caller's process id */
+    uint16_t smb_uid;               /* authenticated user id */
+    uint16_t smb_mid;               /* multiplex id */
+};
+
+/* For server empty respones indicating client error or interim response */
+struct SmbEmptyCom
+{
+    uint8_t smb_wct;     /* value = 0 */
+    uint16_t smb_bcc;    /* value = 0 */
+};
+
+/********************************************************************
+ * Common fields to all commands
+ ********************************************************************/
+struct SmbCommon
+{
+    uint8_t smb_wct;
+};
+
+inline uint8_t SmbWct(const SmbCommon* hdr)
+{
+    return hdr->smb_wct;
+}
+
+/* Common fields to all AndX commands */
+struct SmbAndXCommon
+{
+    uint8_t smb_wct;
+    uint8_t smb_com2;      /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;      /* reserved (must be zero) */
+    uint16_t smb_off2;     /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+};
+
+inline uint32_t NbssLen(const NbssHdr* nb)
+{
+    /* Treat first bit of flags as the upper byte to length */
+    // The left operand of '&' is a garbage value
+    return ((nb->flags & 0x01) << 16) | ntohs(nb->length);  // ... FIXIT-W
+}
+
+inline uint8_t NbssType(const NbssHdr* nb)
+{
+    return nb->type;
+}
+
+inline uint32_t SmbId(const SmbNtHdr* hdr)
+{
+    uint8_t* idf = (uint8_t*)hdr->smb_idf;
+    return *idf << 24 | *(idf + 1) << 16 | *(idf + 2) << 8 | *(idf + 3);
+}
+
+inline uint8_t SmbEmptyComWct(const SmbEmptyCom* ec)
+{
+    return ec->smb_wct;
+}
+
+inline uint16_t SmbBcc(const uint8_t* ptr, uint16_t com_size)
+{
+    /* com_size must be at least the size of the command encasing */
+    if (com_size < sizeof(SmbEmptyCom))
+        return 0;
+
+    return alignedNtohs((uint16_t*)(ptr + com_size - sizeof(uint16_t)));
+}
+
+inline uint16_t SmbEmptyComBcc(const SmbEmptyCom* ec)
+{
+    return alignedNtohs(&ec->smb_bcc);
+}
+
+inline int SmbType(const SmbNtHdr* hdr)
+{
+    // Access to field 'smb_flg' results in a dereference of a null pointer
+    // (loaded from variable 'hdr')
+    if (hdr->smb_flg & SMB_FLG__TYPE)  // ... FIXIT-W
+        return SMB_TYPE__RESPONSE;
+
+    return SMB_TYPE__REQUEST;
+}
+
+inline uint8_t SmbAndXCom2(const SmbAndXCommon* andx)
+{
+    return andx->smb_com2;
+}
+
+inline uint16_t SmbAndXOff2(const SmbAndXCommon* andx)
+{
+    return alignedNtohs(&andx->smb_off2);
+}
+
+/* SMB formats (smb_fmt) Dialect, Pathname and ASCII are all
+ * NULL terminated ASCII strings unless Unicode is specified
+ * in the NT LM 1.0 SMB header in which case they are NULL
+ * terminated unicode strings
+ */
+#define SMB_FMT__DATA_BLOCK  1
+#define SMB_FMT__DIALECT     2
+#define SMB_FMT__ASCII       4
+
+inline bool SmbFmtDataBlock(const uint8_t fmt)
+{
+    return fmt == SMB_FMT__DATA_BLOCK ? true : false;
+}
+
+inline bool SmbFmtDialect(const uint8_t fmt)
+{
+    return fmt == SMB_FMT__DIALECT ? true : false;
+}
+
+inline bool SmbFmtAscii(const uint8_t fmt)
+{
+    return fmt == SMB_FMT__ASCII ? true : false;
+}
+
+#endif
+
diff --git a/src/service_inspectors/dce_rpc/smb_message.cc b/src/service_inspectors/dce_rpc/smb_message.cc
new file mode 100644 (file)
index 0000000..9157876
--- /dev/null
@@ -0,0 +1,2648 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// smb_message.cc author Rashmi Pitre <rrp@cisco.com>
+
+#include "dce_smb.h"
+
+#include "detection/detect.h"
+#include "file_api/file_service.h"
+#include "protocols/packet.h"
+#include "utils/util.h"
+
+#include "dce_smb_module.h"
+#include "dce_smb_utils.h"
+#include "dce_smb_paf.h"
+#include "dce_smb_commands.h"
+#include "dce_smb_transaction.h"
+#include "dce_smb2.h"
+#include "dce_smb.h"
+
+/********************************************************************
+ * Global variables
+ ********************************************************************/
+typedef DCE2_Ret (* DCE2_SmbComFunc)(DCE2_SmbSsnData*, const SmbNtHdr*,
+    const DCE2_SmbComInfo*, const uint8_t*, uint32_t);
+
+static DCE2_SmbComFunc smb_com_funcs[SMB_MAX_NUM_COMS];
+static uint8_t smb_wcts[SMB_MAX_NUM_COMS][2][32];
+static uint16_t smb_bccs[SMB_MAX_NUM_COMS][2][2];
+static DCE2_SmbComFunc smb_chain_funcs[DCE2_POLICY__MAX][SMB_ANDX_COM__MAX][SMB_MAX_NUM_COMS];
+static bool smb_deprecated_coms[SMB_MAX_NUM_COMS];
+static bool smb_unusual_coms[SMB_MAX_NUM_COMS];
+static SmbAndXCom smb_chain_map[SMB_MAX_NUM_COMS];
+
+/********************************************************************
+ * Function: DCE2_SmbIsRawData()
+ *
+ * Purpose:
+ *  To determine if the current state is such that a raw read or
+ *  write is expected.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - Pointer to SMB session data.
+ *
+ * Returns:
+ *  bool -  True if expecting raw data.
+ *          False if not.
+ *
+ ********************************************************************/
+static inline bool DCE2_SmbIsRawData(DCE2_SmbSsnData* ssd)
+{
+    return (ssd->pdu_state == DCE2_SMB_PDU_STATE__RAW_DATA);
+}
+
+/********************************************************************
+ * Function: DCE2_SmbCheckAndXOffset()
+ *
+ * Purpose:
+ *  Validates that the AndXOffset is within bounds of the remaining
+ *  data we have to work with.
+ *
+ * Arguments:
+ *  uint8_t * - pointer to where the offset would take us.
+ *  uint8_t * - pointer to bound offset
+ *  uint8_t * - length of data where offset should be within
+ *
+ * Returns:
+ *  DCE2_RET__SUCCESS - Offset is okay.
+ *  DCE2_RET__ERROR   - Offset is bad.
+ *
+ ********************************************************************/
+static inline DCE2_Ret DCE2_SmbCheckAndXOffset(const uint8_t* off_ptr, const uint8_t* start_bound,
+    const uint32_t length)
+{
+    /* Offset should not point within data we just looked at or be equal to
+     * or beyond the length of the NBSS length left */
+    if ((off_ptr < start_bound) ||
+        (off_ptr > (start_bound + length)))
+    {
+        dce_alert(GID_DCE2, DCE2_SMB_BAD_OFF, (dce2CommonStats*)&dce2_smb_stats);
+
+        return DCE2_RET__ERROR;
+    }
+
+    return DCE2_RET__SUCCESS;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbGetIgnorePtr()
+ *
+ * Returns a pointer to the bytes we are ignoring on client or
+ * server side.  Bytes are ignored if they are associated with
+ * data we are not interested in.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - Pointer to SMB session data.
+ *
+ * Returns:
+ *  uint32_t *
+ *      Pointer to the client or server ignore bytes.
+ *
+ ********************************************************************/
+static inline uint32_t* DCE2_SmbGetIgnorePtr(DCE2_SmbSsnData* ssd)
+{
+    if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
+        return &ssd->srv_ignore_bytes;
+    return &ssd->cli_ignore_bytes;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbGetDataState()
+ *
+ * Returns a pointer to the data state of client or server
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - Pointer to SMB session data.
+ *
+ * Returns:
+ *  DCE2_SmbDataState *
+ *      Pointer to the client or server data state.
+ *
+ ********************************************************************/
+static inline DCE2_SmbDataState* DCE2_SmbGetDataState(DCE2_SmbSsnData* ssd)
+{
+    if (DCE2_SsnFromServer(ssd->sd.wire_pkt))
+        return &ssd->srv_data_state;
+    return &ssd->cli_data_state;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbSetValidWordCount()
+ *
+ * Purpose:
+ *  Initializes global data for valid word counts for supported
+ *  SMB command requests and responses.
+ *
+ * Arguments:
+ *  uint8_t - the SMB command code
+ *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
+ *  uint8_t - the valid word count
+ *
+ * Returns: None
+ *
+ ********************************************************************/
+static inline void DCE2_SmbSetValidWordCount(uint8_t com,
+    uint8_t resp, uint8_t wct)
+{
+    smb_wcts[com][resp][wct/8] |= (1 << (wct % 8));
+}
+
+/********************************************************************
+ * Function: DCE2_SmbIsValidWordCount()
+ *
+ * Purpose:
+ *  Checks if a word count is valid for a given command request
+ *  or response.
+ *
+ * Arguments:
+ *  uint8_t - the SMB command code
+ *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
+ *  uint8_t - the word count to validate
+ *
+ * Returns:
+ *  bool - true if valid, false if not valid.
+ *
+ ********************************************************************/
+static inline bool DCE2_SmbIsValidWordCount(uint8_t com,
+    uint8_t resp, uint8_t wct)
+{
+    return (smb_wcts[com][resp][wct/8] & (1 << (wct % 8))) ? true : false;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbSetValidByteCount()
+ *
+ * Purpose:
+ *  Initializes global data for valid byte counts as a range for
+ *  supported SMB command requests and responses.
+ *  Since a byte count is 2 bytes, a 4 byte type is used to store
+ *  the range.  The maximum is in the most significant 2 bytes and
+ *  the minimum in the least significant 2 bytes.
+ *
+ * Arguments:
+ *  uint8_t - the SMB command code
+ *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
+ *  uint8_t - the minimum word count that is valid
+ *  uint8_t - the maximum word count that is valid
+ *
+ * Returns: None
+ *
+ ********************************************************************/
+static inline void DCE2_SmbSetValidByteCount(uint8_t com,
+    uint8_t resp, uint16_t min, uint16_t max)
+{
+    smb_bccs[com][resp][0] = min;
+    smb_bccs[com][resp][1] = max;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbIsValidByteCount()
+ *
+ * Purpose:
+ *  Checks if a byte count is valid for a given command request
+ *  or response.
+ *
+ * Arguments:
+ *  uint8_t - the SMB command code
+ *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
+ *  uint8_t - the byte count to validate
+ *
+ * Returns:
+ *  bool - true if valid, false if not valid.
+ *
+ ********************************************************************/
+static inline bool DCE2_SmbIsValidByteCount(uint8_t com,
+    uint8_t resp, uint16_t bcc)
+{
+    return ((bcc < smb_bccs[com][resp][0])
+           || (bcc > smb_bccs[com][resp][1])) ? false : true;
+}
+
+// This function is obviously deficient.  Need to do a lot more
+// testing, research and reading MS-CIFS, MS-SMB and MS-ERREF.
+static bool SmbError(const SmbNtHdr* hdr)
+{
+    if (SmbStatusNtCodes(hdr))
+    {
+        /* Nt status codes are being used.  First 2 bits indicate
+         * severity. */
+        switch (SmbNtStatusSeverity(hdr))
+        {
+        case SMB_NT_STATUS_SEVERITY__SUCCESS:
+        case SMB_NT_STATUS_SEVERITY__INFORMATIONAL:
+        case SMB_NT_STATUS_SEVERITY__WARNING:
+            return false;
+        case SMB_NT_STATUS_SEVERITY__ERROR:
+        default:
+            break;
+        }
+    }
+    else
+    {
+        switch (SmbStatusClass(hdr))
+        {
+        case SMB_ERROR_CLASS__SUCCESS:
+            return false;
+        case SMB_ERROR_CLASS__ERRDOS:
+            if (SmbStatusCode(hdr) == SMB_ERRDOS__MORE_DATA)
+                return false;
+            break;
+        case SMB_ERROR_CLASS__ERRSRV:
+        case SMB_ERROR_CLASS__ERRHRD:
+        case SMB_ERROR_CLASS__ERRCMD:
+        default:
+            break;
+        }
+    }
+
+    return true;
+}
+
+static bool SmbBrokenPipe(const SmbNtHdr* hdr)
+{
+    if (SmbStatusNtCodes(hdr))
+    {
+        uint32_t nt_status = SmbNtStatus(hdr);
+        if ((nt_status == SMB_NT_STATUS__PIPE_BROKEN)
+            || (nt_status == SMB_NT_STATUS__PIPE_DISCONNECTED))
+            return true;
+    }
+    else
+    {
+        if (SmbStatusClass(hdr) == SMB_ERROR_CLASS__ERRDOS)
+        {
+            uint16_t smb_status = SmbStatusCode(hdr);
+            if ((smb_status == SMB_ERRDOS__BAD_PIPE)
+                || (smb_status == SMB_ERRDOS__PIPE_NOT_CONNECTED))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+/********************************************************************
+ * Function: DCE2_IgnoreJunkData()
+ *
+ * Purpose:
+ *   An evasion technique can be to put a bunch of junk data before
+ *   the actual SMB request and it seems the MS implementation has
+ *   no problem with it and seems to just ignore the data.  This
+ *   function attempts to move past all the junk to get to the
+ *   actual NetBIOS message request.
+ *
+ * Arguments:
+ *   const uint8_t *  - pointer to the current position in the data
+ *      being inspected
+ *   uint16_t  -  the amount of data left to look at
+ *   uint32_t  -  the amount of data to ignore if there doesn't seem
+ *      to be any junk data.  Just use the length as if the bad
+ *      NetBIOS header was good.
+ *
+ * Returns:
+ *    uint32_t - the amount of bytes to ignore as junk.
+ *
+ ********************************************************************/
+static uint32_t DCE2_IgnoreJunkData(const uint8_t* data_ptr, uint16_t data_len,
+    uint32_t assumed_nb_len)
+{
+    const uint8_t* tmp_ptr = data_ptr;
+    uint32_t ignore_bytes = 0;
+
+    /* Try to find \xffSMB and go back 8 bytes to beginning
+     * of what should be a Netbios header with type Session
+     * Message (\x00) - do appropriate buffer checks to make
+     * sure the index is in bounds. Ignore all intervening
+     * bytes */
+
+    while ((tmp_ptr + sizeof(uint32_t)) <= (data_ptr + data_len))
+    {
+        if ((SmbId((SmbNtHdr*)tmp_ptr) == DCE2_SMB_ID)
+            || (SmbId((SmbNtHdr*)tmp_ptr) == DCE2_SMB2_ID))
+        {
+            break;
+        }
+
+        tmp_ptr++;
+    }
+
+    if ((tmp_ptr + sizeof(uint32_t)) > (data_ptr + data_len))
+    {
+        ignore_bytes = data_len;
+    }
+    else
+    {
+        if ((tmp_ptr - sizeof(NbssHdr)) > data_ptr)
+            ignore_bytes = (tmp_ptr - data_ptr) - sizeof(NbssHdr);
+        else  /* Just ignore whatever the bad NB header had as a length */
+            ignore_bytes = assumed_nb_len;
+    }
+
+    return ignore_bytes;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbHdrChecks()
+ *
+ * Checks some relevant fields in the header to make sure they're
+ * sane.
+ * Side effects are potential alerts for anomolous behavior.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData *
+ *      Pointer to the session data structure.
+ *  SmbNtHdr *
+ *      Pointer to the header struct layed over the packet data.
+ *
+ * Returns:
+ *  DCE2_Ret
+ *      DCE2_RET__IGNORE if we should continue processing, but
+ *          ignore data because of the error.
+ *      DCE2_RET__SUCCESS if we should continue processing.
+ *
+ ********************************************************************/
+static DCE2_Ret DCE2_SmbHdrChecks(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr)
+{
+    Packet* p = ssd->sd.wire_pkt;
+    bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (uint8_t*)smb_hdr);
+
+    if ((DCE2_SsnFromServer(p) && (SmbType(smb_hdr) == SMB_TYPE__REQUEST)) ||
+        (DCE2_SsnFromClient(p) && (SmbType(smb_hdr) == SMB_TYPE__RESPONSE)))
+    {
+        if (is_seg_buf)
+            DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_TYPE);
+        else
+            dce_alert(GID_DCE2, DCE2_SMB_BAD_TYPE, (dce2CommonStats*)&dce2_smb_stats);
+
+        // Continue looking at traffic.  Neither Windows nor Samba seem
+        // to care, or even look at this flag
+    }
+
+    if ((SmbId(smb_hdr) != DCE2_SMB_ID)
+        && (SmbId(smb_hdr) != DCE2_SMB2_ID))
+    {
+        if (is_seg_buf)
+            DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_ID);
+        else
+            dce_alert(GID_DCE2, DCE2_SMB_BAD_ID, (dce2CommonStats*)&dce2_smb_stats);
+
+        return DCE2_RET__IGNORE;
+    }
+
+    return DCE2_RET__SUCCESS;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbGetMinByteCount()
+ *
+ * Purpose:
+ *  Returns the minimum byte count for the given command request
+ *  or response.
+ *
+ * Arguments:
+ *  uint8_t - the SMB command code
+ *  uint8_t - SMB_TYPE__REQUEST or SMB_TYPE__RESPONSE
+ *
+ * Returns:
+ *  uint16_t - the minimum byte count
+ *
+ ********************************************************************/
+static inline uint16_t DCE2_SmbGetMinByteCount(uint8_t com, uint8_t resp)
+{
+    return smb_bccs[com][resp][0];
+}
+
+static DCE2_SmbRequestTracker* DCE2_SmbFindRequestTracker(DCE2_SmbSsnData* ssd,
+    const SmbNtHdr* smb_hdr)
+{
+    uint16_t uid = SmbUid(smb_hdr);
+    uint16_t tid = SmbTid(smb_hdr);
+    uint16_t pid = SmbPid(smb_hdr);
+    uint16_t mid = SmbMid(smb_hdr);
+
+    Profile profile(dce2_smb_pstat_smb_req);
+
+    DebugFormat(DEBUG_DCE_SMB, "Find request tracker => "
+        "Uid: %hu, Tid: %hu, Pid: %hu, Mid: %hu ... ", uid, tid, pid, mid);
+
+    DCE2_SmbRequestTracker* tmp_rtracker = &ssd->rtracker;
+    int smb_com = SmbCom(smb_hdr);
+    switch (smb_com)
+    {
+    case SMB_COM_TRANSACTION_SECONDARY:
+        smb_com = SMB_COM_TRANSACTION;
+        break;
+    case SMB_COM_TRANSACTION2_SECONDARY:
+        smb_com = SMB_COM_TRANSACTION2;
+        break;
+    case SMB_COM_NT_TRANSACT_SECONDARY:
+        smb_com = SMB_COM_NT_TRANSACT;
+        break;
+    case SMB_COM_WRITE_COMPLETE:
+        smb_com = SMB_COM_WRITE_RAW;
+        break;
+    default:
+        break;
+    }
+
+    DCE2_SmbRequestTracker* first_rtracker = nullptr;
+    DCE2_SmbRequestTracker* win_rtracker = nullptr;
+    DCE2_SmbRequestTracker* first_mid_rtracker = nullptr;
+    DCE2_SmbRequestTracker* ret_rtracker = nullptr;
+    while (tmp_rtracker != nullptr)
+    {
+        if ((tmp_rtracker->mid == (int)mid) && (tmp_rtracker->smb_com == smb_com))
+        {
+            // This is the normal case except for SessionSetupAndX and
+            // TreeConnect/TreeConnectAndX which will fall into the
+            // default case below.
+            if ((tmp_rtracker->pid == pid) && (tmp_rtracker->uid == uid)
+                && (tmp_rtracker->tid == tid))
+            {
+                ret_rtracker = tmp_rtracker;
+            }
+            else
+            {
+                switch (smb_com)
+                {
+                case SMB_COM_TRANSACTION:
+                case SMB_COM_TRANSACTION2:
+                case SMB_COM_NT_TRANSACT:
+                case SMB_COM_TRANSACTION_SECONDARY:
+                case SMB_COM_TRANSACTION2_SECONDARY:
+                case SMB_COM_NT_TRANSACT_SECONDARY:
+                    // These should conform to above
+                    break;
+                default:
+                    if (tmp_rtracker->pid == pid)
+                        ret_rtracker = tmp_rtracker;
+                    break;
+                }
+            }
+
+            if (ret_rtracker != nullptr)
+            {
+                DebugMessage(DEBUG_DCE_SMB, "Found.\n");
+                return ret_rtracker;
+            }
+
+            // Take the first one where the PIDs also match
+            // in the case of the Transacts above
+            if ((tmp_rtracker->pid == pid) && (win_rtracker == nullptr))
+                win_rtracker = tmp_rtracker;
+
+            // Set this to the first matching request in the queue
+            // where the Mid matches.  Don't set for Windows if from
+            // client since PID/MID are necessary
+            if (((DCE2_SmbType(ssd) == SMB_TYPE__RESPONSE)
+                || !DCE2_SsnIsWindowsPolicy(&ssd->sd))
+                && first_mid_rtracker == nullptr)
+            {
+                first_mid_rtracker = tmp_rtracker;
+            }
+        }
+
+        // Set the first one we see for early Samba versions
+        if ((first_rtracker == nullptr) && (tmp_rtracker->mid != DCE2_SENTINEL)
+            && (tmp_rtracker->smb_com == smb_com))
+            first_rtracker = tmp_rtracker;
+
+        // Look at the next request in the queue
+        if (tmp_rtracker == &ssd->rtracker)
+            tmp_rtracker = (DCE2_SmbRequestTracker*)DCE2_QueueFirst(ssd->rtrackers);
+        else
+            tmp_rtracker = (DCE2_SmbRequestTracker*)DCE2_QueueNext(ssd->rtrackers);
+    }
+
+    DCE2_Policy policy = DCE2_SsnGetPolicy(&ssd->sd);
+    switch (policy)
+    {
+    case DCE2_POLICY__SAMBA_3_0_20:
+    case DCE2_POLICY__SAMBA_3_0_22:
+        ret_rtracker = first_rtracker;
+        break;
+    case DCE2_POLICY__SAMBA:
+    case DCE2_POLICY__SAMBA_3_0_37:
+        ret_rtracker = first_mid_rtracker;
+        break;
+    case DCE2_POLICY__WIN2000:
+    case DCE2_POLICY__WINXP:
+    case DCE2_POLICY__WINVISTA:
+    case DCE2_POLICY__WIN2003:
+    case DCE2_POLICY__WIN2008:
+    case DCE2_POLICY__WIN7:
+        if (win_rtracker != nullptr)
+            ret_rtracker = win_rtracker;
+        else
+            ret_rtracker = first_mid_rtracker;
+        break;
+    default:
+        DebugFormat(DEBUG_DCE_SMB, "%s(%d) Invalid policy: %d",
+            __FILE__, __LINE__, policy);
+        break;
+    }
+
+    return ret_rtracker;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbCheckCommand()
+ *
+ * Purpose:
+ *  Checks basic validity of an SMB command.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - pointer to session data structure
+ *  SmbNtHdr *        - pointer to the SMB header structure
+ *  uint8_t           - the SMB command code, i.e. SMB_COM_*
+ *  uint8_t *         - current pointer to data, i.e. the command
+ *  uint32_t          - the remaining length
+ *  DCE2_SmbComInfo & -
+ *      Populated structure for command processing
+ *
+ * Returns: None
+ *
+ ********************************************************************/
+static void DCE2_SmbCheckCommand(DCE2_SmbSsnData* ssd,
+    const SmbNtHdr* smb_hdr, const uint8_t smb_com,
+    const uint8_t* nb_ptr, uint32_t nb_len, DCE2_SmbComInfo& com_info)
+{
+    // Check for server error response
+    if (com_info.smb_type == SMB_TYPE__RESPONSE)
+    {
+        const SmbEmptyCom* ec = (SmbEmptyCom*)nb_ptr;
+
+        // Verify there is enough data to do checks
+        if (nb_len < sizeof(SmbEmptyCom))
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats);
+            com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
+            return;
+        }
+
+        // If word and byte counts are zero and there is an error
+        // the server didn't accept client request
+        if ((SmbEmptyComWct(ec) == 0)
+            && (SmbEmptyComBcc(ec) == 0) && SmbError(smb_hdr))
+        {
+            DebugFormat(DEBUG_DCE_SMB,
+                "Response error: 0x%08X\n", SmbNtStatus(smb_hdr));
+
+            // If broken pipe, clean up data associated with open named pipe
+            if (SmbBrokenPipe(smb_hdr))
+            {
+                DebugMessage(DEBUG_DCE_SMB, "Broken or disconnected pipe.\n");
+                DCE2_SmbRemoveFileTracker(ssd, ssd->cur_rtracker->ftracker);
+            }
+
+            com_info.cmd_error |= DCE2_SMB_COM_ERROR__STATUS_ERROR;
+            return;
+        }
+    }
+
+    // Set the header size to the minimum size the command can be
+    // without the byte count to make sure there is enough data to
+    // get the word count.
+    SmbAndXCom andx_com = smb_chain_map[smb_com];
+    int chk_com_size;
+    if (andx_com == SMB_ANDX_COM__NONE)
+        chk_com_size = sizeof(SmbCommon);
+    else
+        chk_com_size = sizeof(SmbAndXCommon);
+
+    // Verify there is enough data to do checks
+    if (nb_len < (uint32_t)chk_com_size)
+    {
+        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats);
+        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
+        return;
+    }
+
+    const SmbCommon* sc = (SmbCommon*)nb_ptr;
+    com_info.word_count = SmbWct(sc);
+
+    // Make sure the word count is a valid one for the command.  If not
+    // testing shows an error will be returned.  And command structures
+    // won't lie on data correctly and out of bounds data accesses are possible.
+    if (!DCE2_SmbIsValidWordCount(smb_com, (uint8_t)com_info.smb_type, com_info.word_count))
+    {
+        dce_alert(GID_DCE2, DCE2_SMB_BAD_WCT, (dce2CommonStats*)&dce2_smb_stats);
+        com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_WORD_COUNT;
+        return;
+    }
+
+    // This gets the size of the SMB command from word count through byte count
+    // using the advertised value in the word count field.
+    com_info.cmd_size = (uint16_t)SMB_COM_SIZE(com_info.word_count);
+    if (nb_len < com_info.cmd_size)
+    {
+        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_COM, (dce2CommonStats*)&dce2_smb_stats);
+        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
+        return;
+    }
+
+    uint16_t smb_bcc = SmbBcc(nb_ptr, com_info.cmd_size);
+
+    // SMB_COM_NT_CREATE_ANDX is a special case.  Who know what's going
+    // on with the word count (see MS-CIFS and MS-SMB).  A 42 word count
+    // command seems to actually have 50 words, so who knows where the
+    // byte count is.  Just set to zero since it's not needed.
+    if ((smb_com == SMB_COM_NT_CREATE_ANDX)
+        && (com_info.smb_type == SMB_TYPE__RESPONSE))
+        smb_bcc = 0;
+
+    // If byte count is deemed invalid, alert but continue processing
+    switch (smb_com)
+    {
+    // Interim responses
+    case SMB_COM_TRANSACTION:
+    case SMB_COM_TRANSACTION2:
+    case SMB_COM_NT_TRANSACT:
+        // If word count is 0, byte count must be 0
+        if ((com_info.word_count == 0) && (com_info.smb_type == SMB_TYPE__RESPONSE))
+        {
+            if (smb_bcc != 0)
+            {
+                dce_alert(GID_DCE2, DCE2_SMB_BAD_BCC, (dce2CommonStats*)&dce2_smb_stats);
+                com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
+            }
+            break;
+        }
+    // Fall through
+    default:
+        if (!DCE2_SmbIsValidByteCount(smb_com, (uint8_t)com_info.smb_type, smb_bcc))
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_BAD_BCC, (dce2CommonStats*)&dce2_smb_stats);
+            com_info.cmd_error |= DCE2_SMB_COM_ERROR__INVALID_BYTE_COUNT;
+        }
+        break;
+    }
+
+    // Move just past byte count field which is the end of the command
+    DCE2_MOVE(nb_ptr, nb_len, com_info.cmd_size);
+
+    // Validate that there is enough data to be able to process the command
+    if (nb_len < DCE2_SmbGetMinByteCount(smb_com, (uint8_t)com_info.smb_type))
+    {
+        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_BCC, (dce2CommonStats*)&dce2_smb_stats);
+        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
+    }
+
+    // The byte count seems to be ignored by Windows and current Samba (3.5.4)
+    // as long as it is less than the amount of data left.  If more, an error
+    // is returned.
+    // !!!WARNING!!! the byte count should probably never be used.
+    if (smb_bcc > nb_len)
+    {
+        dce_alert(GID_DCE2, DCE2_SMB_NB_LT_BCC, (dce2CommonStats*)&dce2_smb_stats);
+        // Large byte count doesn't seem to matter for early Samba
+        switch (DCE2_SsnGetPolicy(&ssd->sd))
+        {
+        case DCE2_POLICY__SAMBA_3_0_20:
+        case DCE2_POLICY__SAMBA_3_0_22:
+        case DCE2_POLICY__SAMBA_3_0_37:
+            break;
+        default:
+            com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
+            break;
+        }
+    }
+    else if ((smb_bcc == 0) && (SmbCom(smb_hdr) == SMB_COM_TRANSACTION)
+        && (DCE2_SmbType(ssd) == SMB_TYPE__REQUEST)
+        && (DCE2_SsnGetPolicy(&ssd->sd) == DCE2_POLICY__SAMBA))
+    {
+        // Current Samba errors on a zero byte count Transaction because it
+        // uses it to get the Name string and if zero Name will be NULL and
+        // it won't process it.
+        com_info.cmd_error |= DCE2_SMB_COM_ERROR__BAD_LENGTH;
+    }
+
+    com_info.byte_count = smb_bcc;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbProcessCommand()
+ *
+ * Purpose:
+ *  This is the main function for handling SMB commands and command
+ *  chaining.
+ *  It does an initial check of the command to determine validity
+ *  and gets basic information about the command.  Then it calls the
+ *  specific command function (setup in DCE2_SmbInitGlobals).
+ *  If there is command chaining, it will do the chaining foo to
+ *  get to the next command.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - pointer to session data structure
+ *  SmbNtHdr *        - pointer to the SMB header structure
+ *  uint8_t *         - current pointer to data, i.e. the command
+ *  uint32_t          - the remaining length
+ *
+ * Returns: None
+ *
+ ********************************************************************/
+static void DCE2_SmbProcessCommand(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr,
+    const uint8_t* nb_ptr, uint32_t nb_len)
+{
+    uint8_t smb_com = SmbCom(smb_hdr);
+    DCE2_Ret status = DCE2_RET__ERROR;
+    bool sess_chain = false;
+    bool tree_chain = false;
+    bool open_chain = false;
+    int num_chained = 0;
+
+    while (nb_len > 0)
+    {
+        // Break out if command not supported
+        if (smb_com_funcs[smb_com] == nullptr)
+            break;
+
+        if (smb_deprecated_coms[smb_com])
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_DEPR_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        if (smb_unusual_coms[smb_com])
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_UNUSUAL_COMMAND_USED, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        DCE2_SmbComInfo com_info;
+        com_info.smb_type = DCE2_SmbType(ssd);
+        com_info.cmd_error = DCE2_SMB_COM_ERROR__COMMAND_OK;
+        com_info.word_count = 0;
+        com_info.smb_com = smb_com;
+        com_info.cmd_size = 0;
+        com_info.byte_count = 0;
+        DCE2_SmbCheckCommand(ssd, smb_hdr, smb_com, nb_ptr, nb_len, com_info);
+        DebugFormat(DEBUG_DCE_SMB, "Processing command: %s (0x%02X)\n",
+            get_smb_com_string(smb_com), smb_com);
+
+        // Note that even if the command shouldn't be processed, some of
+        // the command functions need to know and do cleanup or some other
+        // processing.
+        status = smb_com_funcs[smb_com](ssd, smb_hdr,
+                &com_info, nb_ptr, nb_len);
+
+        if (status != DCE2_RET__SUCCESS)
+            break;
+
+        // This command is not chainable
+        SmbAndXCom andx_com = smb_chain_map[smb_com];
+        if (andx_com == SMB_ANDX_COM__NONE)
+            break;
+
+        /**********************************************************
+         * AndX Chaining
+         **********************************************************/
+        const SmbAndXCommon* andx_ptr = (SmbAndXCommon*)nb_ptr;
+        uint8_t smb_com2 = SmbAndXCom2(andx_ptr);
+        if (smb_com2 == SMB_COM_NO_ANDX_COMMAND)
+            break;
+
+        DebugFormat(DEBUG_DCE_SMB, "Chained SMB command: %s\n",
+            get_smb_com_string(smb_com2));
+
+        num_chained++;
+        if (DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config) &&
+            (num_chained >= DCE2_ScSmbMaxChain((dce2SmbProtoConf*)ssd->sd.config)))
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_EXCESSIVE_CHAINING, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        // Multiple SessionSetupAndX, TreeConnectAndX, OpenAndX and NtCreateAndX
+        // are only allowed by Samba.
+        if (smb_com == SMB_COM_SESSION_SETUP_ANDX)
+            sess_chain = true;
+
+        // Check for multiple chained SessionSetupAndX
+        if ((smb_com2 == SMB_COM_SESSION_SETUP_ANDX) && sess_chain)
+        {
+            // There is only one place to return a uid.
+            dce_alert(GID_DCE2, DCE2_SMB_MULT_CHAIN_SS, (dce2CommonStats*)&dce2_smb_stats);
+            // FIXIT-L Should we continue processing?
+            break;
+        }
+
+        // Check for chained SessionSetupAndX => .? => LogoffAndX
+        if ((smb_com2 == SMB_COM_LOGOFF_ANDX) && sess_chain)
+        {
+            // This essentially deletes the uid created by the login
+            // and doesn't make any sense.
+            dce_alert(GID_DCE2, DCE2_SMB_CHAIN_SS_LOGOFF, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        if (smb_com == SMB_COM_TREE_CONNECT_ANDX)
+            tree_chain = true;
+
+        // Check for multiple chained TreeConnects
+        if (((smb_com2 == SMB_COM_TREE_CONNECT_ANDX)
+            || (smb_com2 == SMB_COM_TREE_CONNECT)) && tree_chain)
+        {
+            // There is only one place to return a tid.
+            dce_alert(GID_DCE2, DCE2_SMB_MULT_CHAIN_TC, (dce2CommonStats*)&dce2_smb_stats);
+            // FIXIT-L Should we continue processing?
+            break;
+        }
+
+        // Check for chained TreeConnectAndX => .? => TreeDisconnect
+        if ((smb_com2 == SMB_COM_TREE_DISCONNECT) && tree_chain)
+        {
+            // This essentially deletes the tid created by the tree connect
+            // and doesn't make any sense.
+            dce_alert(GID_DCE2, DCE2_SMB_CHAIN_TC_TDIS, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        if ((smb_com == SMB_COM_OPEN_ANDX) || (smb_com == SMB_COM_NT_CREATE_ANDX))
+            open_chain = true;
+
+        // Check for chained OpenAndX/NtCreateAndX => .? => Close
+        if ((smb_com2 == SMB_COM_CLOSE) && open_chain)
+        {
+            // This essentially deletes the fid created by the open command
+            // and doesn't make any sense.
+            dce_alert(GID_DCE2, DCE2_SMB_CHAIN_OPEN_CLOSE, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        // Check that policy allows for such chaining
+        DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
+        if (smb_chain_funcs[policy][andx_com][smb_com2] == nullptr)
+            break;
+
+        DCE2_MOVE(nb_ptr, nb_len, DCE2_ComInfoCommandSize(&com_info));
+
+        // FIXIT-L Need to test out of order chaining
+        const uint8_t* off2_ptr = (uint8_t*)smb_hdr + SmbAndXOff2(andx_ptr);
+        if (DCE2_SmbCheckAndXOffset(off2_ptr, nb_ptr, nb_len) != DCE2_RET__SUCCESS)
+            break;
+
+        DCE2_MOVE(nb_ptr, nb_len, (off2_ptr - nb_ptr));
+
+        // FIXIT-L Need to test more.
+        switch (smb_com)
+        {
+        case SMB_COM_SESSION_SETUP_ANDX:
+        case SMB_COM_TREE_CONNECT_ANDX:
+        case SMB_COM_OPEN_ANDX:
+        case SMB_COM_NT_CREATE_ANDX:
+            switch (smb_com2)
+            {
+            case SMB_COM_WRITE:
+            case SMB_COM_WRITE_ANDX:
+            case SMB_COM_TRANSACTION:
+            case SMB_COM_READ_ANDX:
+                if (DCE2_SsnFromClient(ssd->sd.wire_pkt) && open_chain)
+                {
+                    DCE2_SmbQueueTmpFileTracker(ssd, ssd->cur_rtracker,
+                        SmbUid(smb_hdr), SmbTid(smb_hdr));
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        default:
+            break;
+        }
+
+        smb_com = smb_com2;
+    }
+
+    int smb_type = DCE2_SmbType(ssd);
+    if (smb_type == SMB_TYPE__RESPONSE)
+    {
+        switch (smb_com)
+        {
+        case SMB_COM_TRANSACTION:
+        case SMB_COM_TRANSACTION2:
+        case SMB_COM_NT_TRANSACT:
+        case SMB_COM_TRANSACTION_SECONDARY:
+        case SMB_COM_TRANSACTION2_SECONDARY:
+        case SMB_COM_NT_TRANSACT_SECONDARY:
+            // This case means there was an error with the initial response
+            // so the tracker isn't yet officially in response mode
+            if (ssd->cur_rtracker->ttracker.smb_type == SMB_TYPE__REQUEST)
+            {
+                // Samba throws out entire transaction and Windows just this request
+                if (DCE2_SsnIsServerSambaPolicy(&ssd->sd) && (status != DCE2_RET__SUCCESS))
+                    break;
+
+                if (!DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
+                    return;
+            }
+            else
+            {
+                if ((status == DCE2_RET__SUCCESS)
+                    && !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
+                    return;
+            }
+            break;
+        case SMB_COM_WRITE_RAW:
+            if ((status == DCE2_RET__SUCCESS)
+                && (ssd->cur_rtracker->writeraw_remaining != 0))
+                return;
+            break;
+        default:
+            break;
+        }
+    }
+    else if (status != DCE2_RET__IGNORE)
+    {
+        switch (smb_com)
+        {
+        case SMB_COM_TRANSACTION:
+        case SMB_COM_TRANSACTION_SECONDARY:
+            if (DCE2_SsnIsWindowsPolicy(&ssd->sd))
+            {
+                if (!ssd->cur_rtracker->ttracker.one_way
+                    || !DCE2_SmbIsTransactionComplete(&ssd->cur_rtracker->ttracker))
+                    return;
+
+                // Remove the request tracker if transaction is one-way and
+                // all data and parameters have been sent
+                break;
+            }
+        default:
+            // Anything else, keep the request tracker
+            return;
+        }
+    }
+
+    DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
+    ssd->cur_rtracker = nullptr;
+}
+
+/********************************************************************
+ * Function: DCE2_SmbInspect()
+ *
+ * Purpose:
+ *  Determines whether the SMB command is something the preprocessor
+ *  needs to inspect.
+ *  This function returns a DCE2_SmbRequestTracker which tracks command
+ *  requests / responses.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - the session data structure.
+ *  const SmbNtHdr *  - pointer to the SMB header.
+ *
+ * Returns:
+ *  DCE2_SmbRequestTracker * - nullptr if it's not something we want to or can
+ *                     inspect.
+ *                     Otherwise an initialized structure if request
+ *                     and the found structure if response.
+ *
+ ********************************************************************/
+static DCE2_SmbRequestTracker* DCE2_SmbInspect(DCE2_SmbSsnData* ssd, const SmbNtHdr* smb_hdr)
+{
+    int smb_com = SmbCom(smb_hdr);
+
+    DebugFormat(DEBUG_DCE_SMB, "SMB command: %s (0x%02X)\n",
+        get_smb_com_string(smb_com), smb_com);
+
+    if (smb_com_funcs[smb_com] == nullptr)
+    {
+        DebugMessage(DEBUG_DCE_SMB, "Command isn't processed "
+            "by preprocessor.\n");
+        return nullptr;
+    }
+
+    // See if this is something we need to inspect
+    DCE2_Policy policy = DCE2_SsnGetServerPolicy(&ssd->sd);
+    DCE2_SmbRequestTracker* rtracker = nullptr;
+    if (DCE2_SmbType(ssd) == SMB_TYPE__REQUEST)
+    {
+        switch (smb_com)
+        {
+        case SMB_COM_NEGOTIATE:
+            if (ssd->ssn_state_flags & DCE2_SMB_SSN_STATE__NEGOTIATED)
+            {
+                dce_alert(GID_DCE2, DCE2_SMB_MULTIPLE_NEGOTIATIONS,
+                    (dce2CommonStats*)&dce2_smb_stats);
+                return nullptr;
+            }
+            break;
+        case SMB_COM_SESSION_SETUP_ANDX:
+            break;
+        case SMB_COM_TREE_CONNECT:
+        case SMB_COM_TREE_CONNECT_ANDX:
+        case SMB_COM_RENAME:
+        case SMB_COM_LOGOFF_ANDX:
+            if (DCE2_SmbFindUid(ssd, SmbUid(smb_hdr)) != DCE2_RET__SUCCESS)
+                return nullptr;
+            break;
+        default:
+            if (DCE2_SmbFindTid(ssd, SmbTid(smb_hdr)) != DCE2_RET__SUCCESS)
+            {
+                DebugFormat(DEBUG_DCE_SMB,
+                    "Couldn't find Tid (%hu)\n", SmbTid(smb_hdr));
+                return nullptr;
+            }
+
+            if (DCE2_SmbIsTidIPC(ssd, SmbTid(smb_hdr)))
+            {
+                switch (smb_com)
+                {
+                case SMB_COM_OPEN:
+                case SMB_COM_CREATE:
+                case SMB_COM_CREATE_NEW:
+                case SMB_COM_WRITE_AND_CLOSE:
+                case SMB_COM_WRITE_AND_UNLOCK:
+                case SMB_COM_READ:
+                    // Samba doesn't allow these commands under an IPC tree
+                    switch (policy)
+                    {
+                    case DCE2_POLICY__SAMBA:
+                    case DCE2_POLICY__SAMBA_3_0_37:
+                    case DCE2_POLICY__SAMBA_3_0_22:
+                    case DCE2_POLICY__SAMBA_3_0_20:
+                        DebugMessage(DEBUG_DCE_SMB, "Samba doesn't "
+                            "process this command under an IPC tree.\n");
+                        return nullptr;
+                    default:
+                        break;
+                    }
+                    break;
+                case SMB_COM_READ_RAW:
+                case SMB_COM_WRITE_RAW:
+                    // Samba and Windows Vista on don't allow these commands
+                    // under an IPC tree, whether or not the raw read/write
+                    // flag is set in the Negotiate capabilities.
+                    // Windows RSTs the connection and Samba FINs it.
+                    switch (policy)
+                    {
+                    case DCE2_POLICY__WINVISTA:
+                    case DCE2_POLICY__WIN2008:
+                    case DCE2_POLICY__WIN7:
+                    case DCE2_POLICY__SAMBA:
+                    case DCE2_POLICY__SAMBA_3_0_37:
+                    case DCE2_POLICY__SAMBA_3_0_22:
+                    case DCE2_POLICY__SAMBA_3_0_20:
+                        DebugMessage(DEBUG_DCE_SMB, "Samba and "
+                            "Windows Vista on don't process this "
+                            "command under an IPC tree.\n");
+                        return nullptr;
+                    default:
+                        break;
+                    }
+                    break;
+                case SMB_COM_LOCK_AND_READ:
+                    // The lock will fail so the read won't happen
+                    return nullptr;
+                default:
+                    break;
+                }
+            }
+            else      // Not IPC
+            {
+                switch (smb_com)
+                {
+                // These commands are only used for IPC
+                case SMB_COM_TRANSACTION:
+                case SMB_COM_TRANSACTION_SECONDARY:
+                    DebugMessage(DEBUG_DCE_SMB, "secondary transaction not IPC.\n");
+                    return nullptr;
+                case SMB_COM_READ_RAW:
+                case SMB_COM_WRITE_RAW:
+                    // Windows Vista on don't seem to support these
+                    // commands, whether or not the raw read/write
+                    // flag is set in the Negotiate capabilities.
+                    // Windows RSTs the connection.
+                    switch (policy)
+                    {
+                    case DCE2_POLICY__WINVISTA:
+                    case DCE2_POLICY__WIN2008:
+                    case DCE2_POLICY__WIN7:
+                        DebugMessage(DEBUG_DCE_SMB,
+                            "Windows Vista on don't process "
+                            "this command.\n");
+                        return nullptr;
+                    default:
+                        break;
+                    }
+                    break;
+                default:
+                    break;
+                }
+            }
+            break;
+        }
+
+        switch (smb_com)
+        {
+        case SMB_COM_TRANSACTION_SECONDARY:
+        case SMB_COM_TRANSACTION2_SECONDARY:
+        case SMB_COM_NT_TRANSACT_SECONDARY:
+            rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
+            break;
+        case SMB_COM_TRANSACTION:
+        case SMB_COM_TRANSACTION2:
+        case SMB_COM_NT_TRANSACT:
+            // If there is already and existing request tracker
+            // and the transaction is not complete, server will
+            // return an error.
+            rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
+            if (rtracker != nullptr)
+                break;
+        // Fall through
+        default:
+            rtracker = DCE2_SmbNewRequestTracker(ssd, smb_hdr);
+            break;
+        }
+    }
+    else
+    {
+        rtracker = DCE2_SmbFindRequestTracker(ssd, smb_hdr);
+    }
+
+    return rtracker;
+}
+
+static void DCE2_SmbProcessRawData(DCE2_SmbSsnData* ssd, const uint8_t* nb_ptr, uint32_t nb_len)
+{
+    DCE2_SmbFileTracker* ftracker = ssd->cur_rtracker->ftracker;
+    bool remove_rtracker = false;
+
+    if (ftracker == nullptr)
+    {
+        DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
+        ssd->cur_rtracker = nullptr;
+        return;
+    }
+
+    if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
+    {
+        DebugMessage(DEBUG_DCE_SMB, "Raw data: Write Raw\n");
+        DebugFormat(DEBUG_DCE_SMB, "Request Fid: 0x%04X\n", ftracker->fid_v1);
+
+        if (nb_len > ssd->cur_rtracker->writeraw_remaining)
+        {
+            dce_alert(GID_DCE2, DCE2_SMB_TDCNT_LT_DSIZE, (dce2CommonStats*)&dce2_smb_stats);
+
+            // If this happens, Windows never responds regardless of
+            // WriteThrough flag, so get rid of request tracker
+            remove_rtracker = true;
+        }
+        else if (!ssd->cur_rtracker->writeraw_writethrough)
+        {
+            // If WriteThrough flag was not set on initial request, a
+            // SMB_COM_WRITE_COMPLETE will not be sent so need to get
+            // rid of request tracker.
+            remove_rtracker = true;
+        }
+        else
+        {
+            ssd->cur_rtracker->writeraw_writethrough = false;
+            ssd->cur_rtracker->writeraw_remaining = 0;
+        }
+    }
+    else
+    {
+        DebugMessage(DEBUG_DCE_SMB, "Raw data: Read Raw\n");
+        DebugFormat(DEBUG_DCE_SMB, "Response Fid: 0x%04X\n", ftracker->fid_v1);
+
+        remove_rtracker = true;
+    }
+
+    // Only one raw read/write allowed
+    ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
+
+    if (ftracker->is_ipc)
+    {
+        // Maximum possible fragment length is 16 bit
+        if (nb_len > UINT16_MAX)
+            nb_len = UINT16_MAX;
+
+        DCE2_CoProcess(&ssd->sd, ftracker->fp_co_tracker, nb_ptr, (uint16_t)nb_len);
+    }
+    else
+    {
+        bool upload = DCE2_SsnFromClient(ssd->sd.wire_pkt) ? true : false;
+        DCE2_SmbProcessFileData(ssd, ftracker, nb_ptr, nb_len, upload);
+    }
+
+    if (remove_rtracker)
+    {
+        DCE2_SmbRemoveRequestTracker(ssd, ssd->cur_rtracker);
+        ssd->cur_rtracker = nullptr;
+    }
+}
+
+static void DCE2_SmbDataFree(DCE2_SmbSsnData* ssd)
+{
+    if (ssd == nullptr)
+        return;
+
+    // FIXIT This tries to account for the situation where we never knew the file
+    // size and the TCP session was shutdown before an SMB_COM_CLOSE on the file.
+    // Possibly need to add callback to fileAPI since it may have already
+    // released it's resources.
+    //DCE2_SmbFinishFileAPI(ssd);
+
+    if (ssd->uids != nullptr)
+    {
+        DCE2_ListDestroy(ssd->uids);
+        ssd->uids = nullptr;
+    }
+
+    if (ssd->tids != nullptr)
+    {
+        DCE2_ListDestroy(ssd->tids);
+        ssd->tids = nullptr;
+    }
+
+    DCE2_SmbCleanFileTracker(&ssd->ftracker);
+    if (ssd->ftrackers != nullptr)
+    {
+        DCE2_ListDestroy(ssd->ftrackers);
+        ssd->ftrackers = nullptr;
+    }
+
+    DCE2_SmbCleanRequestTracker(&ssd->rtracker);
+    if (ssd->rtrackers != nullptr)
+    {
+        DCE2_QueueDestroy(ssd->rtrackers);
+        ssd->rtrackers = nullptr;
+    }
+
+    if (ssd->cli_seg != nullptr)
+    {
+        DCE2_BufferDestroy(ssd->cli_seg);
+        ssd->cli_seg = nullptr;
+    }
+
+    if (ssd->srv_seg != nullptr)
+    {
+        DCE2_BufferDestroy(ssd->srv_seg);
+        ssd->srv_seg = nullptr;
+    }
+
+    if (ssd->smb2_requests != nullptr)
+    {
+        DCE2_Smb2CleanRequests(ssd->smb2_requests);
+        ssd->smb2_requests = nullptr;
+    }
+}
+
+Dce2SmbFlowData::Dce2SmbFlowData() : FlowData(flow_id)
+{
+}
+
+Dce2SmbFlowData::~Dce2SmbFlowData()
+{
+    DCE2_SmbDataFree(&dce2_smb_session);
+}
+
+unsigned Dce2SmbFlowData::flow_id = 0;
+
+DCE2_SmbSsnData* get_dce2_smb_session_data(Flow* flow)
+{
+    Dce2SmbFlowData* fd = (Dce2SmbFlowData*)flow->get_flow_data(Dce2SmbFlowData::flow_id);
+    return fd ? &fd->dce2_smb_session : nullptr;
+}
+
+static DCE2_SmbSsnData* set_new_dce2_smb_session(Packet* p)
+{
+    Dce2SmbFlowData* fd = new Dce2SmbFlowData;
+    memset(&fd->dce2_smb_session,0,sizeof(DCE2_SmbSsnData));
+    p->flow->set_flow_data(fd);
+    return(&fd->dce2_smb_session);
+}
+
+static DCE2_SmbSsnData* dce2_create_new_smb_session(Packet* p, dce2SmbProtoConf* config)
+{
+    DCE2_SmbSsnData* dce2_smb_sess = nullptr;
+    Profile profile(dce2_smb_pstat_new_session);
+
+       DebugMessage(DEBUG_DCE_SMB, "DCE over SMB packet detected\n");
+       DebugMessage(DEBUG_DCE_SMB, "Creating new session\n");
+
+       dce2_smb_sess = set_new_dce2_smb_session(p);
+       if ( dce2_smb_sess )
+       {
+               dce2_smb_sess->dialect_index = DCE2_SENTINEL;
+               dce2_smb_sess->max_outstanding_requests = 10;  // Until Negotiate/SessionSetupAndX
+               dce2_smb_sess->cli_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+               dce2_smb_sess->srv_data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+               dce2_smb_sess->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
+               dce2_smb_sess->uid = DCE2_SENTINEL;
+               dce2_smb_sess->tid = DCE2_SENTINEL;
+               dce2_smb_sess->ftracker.fid_v1 = DCE2_SENTINEL;
+               dce2_smb_sess->rtracker.mid = DCE2_SENTINEL;
+               dce2_smb_sess->max_file_depth = FileService::get_max_file_depth();
+
+               DCE2_ResetRopts(&dce2_smb_sess->sd.ropts);
+
+               dce2_smb_stats.smb_sessions++;
+               DebugFormat(DEBUG_DCE_SMB,"Created (%p)\n", (void*)dce2_smb_sess);
+
+               dce2_smb_sess->sd.trans = DCE2_TRANS_TYPE__SMB;
+               dce2_smb_sess->sd.server_policy = config->common.policy;
+               dce2_smb_sess->sd.client_policy = DCE2_POLICY__WINXP;
+               dce2_smb_sess->sd.wire_pkt = p;
+               dce2_smb_sess->sd.config = (void*)config;
+       }
+
+    return dce2_smb_sess;
+}
+
+/********************************************************************
+ * Function: DCE2_NbssHdrChecks()
+ *
+ * Purpose:
+ *  Does validation of the NetBIOS header.  SMB will only run over
+ *  the Session Message type.  On port 139, there is always an
+ *  initial Session Request / Session Positive/Negative response
+ *  followed by the normal SMB conversation, i.e. Negotiate,
+ *  SessionSetupAndX, etc.
+ *  Side effects are potential alerts for anomolous behavior.
+ *
+ * Arguments:
+ *  DCE2_SmbSsnData * - the session data structure.
+ *  const NbssHdr *   - pointer to the NetBIOS Session Service
+ *                      header structure.  Size is already validated.
+ *
+ * Returns:
+ *  DCE2_Ret  -  DCE2_RET__SUCCESS if all goes well and processing
+ *               should continue.
+ *               DCE2_RET__IGNORE if it's not something we need to
+ *               look at.
+ *               DCE2_RET__ERROR if an invalid NetBIOS Session
+ *               Service type is found.
+ *
+ ********************************************************************/
+static DCE2_Ret DCE2_NbssHdrChecks(DCE2_SmbSsnData* ssd, const NbssHdr* nb_hdr)
+{
+    Packet* p = ssd->sd.wire_pkt;
+    bool is_seg_buf = DCE2_SmbIsSegBuffer(ssd, (uint8_t*)nb_hdr);
+
+    DebugMessage(DEBUG_DCE_SMB, "NetBIOS Session Service type: ");
+
+    switch (NbssType(nb_hdr))
+    {
+    case NBSS_SESSION_TYPE__MESSAGE:
+        /* Only want to look at session messages */
+        DebugMessage(DEBUG_DCE_SMB, "Session Message\n");
+
+        if (!DCE2_SmbIsRawData(ssd))
+        {
+            uint32_t nb_len = NbssLen(nb_hdr);
+
+            if (nb_len == 0)
+                return DCE2_RET__IGNORE;
+
+            if (nb_len < sizeof(SmbNtHdr))
+            {
+                DebugFormat(DEBUG_DCE_SMB, "NetBIOS SS len(%zu) < SMB header len(%zu).\n",
+                    sizeof(SmbNtHdr), sizeof(NbssHdr) + nb_len);
+
+                if (is_seg_buf)
+                    DCE2_SmbSegAlert(ssd, DCE2_SMB_NB_LT_SMBHDR);
+                else
+                    dce_alert(GID_DCE2, DCE2_SMB_NB_LT_SMBHDR, (dce2CommonStats*)&dce2_smb_stats);
+
+                return DCE2_RET__IGNORE;
+            }
+        }
+
+        return DCE2_RET__SUCCESS;
+
+    case NBSS_SESSION_TYPE__REQUEST:
+        DebugMessage(DEBUG_DCE_SMB, "Session Request\n");
+        if (DCE2_SsnFromServer(p))
+        {
+            if (is_seg_buf)
+                DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
+            else
+                dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        break;
+
+    case NBSS_SESSION_TYPE__POS_RESPONSE:
+    case NBSS_SESSION_TYPE__NEG_RESPONSE:
+    case NBSS_SESSION_TYPE__RETARGET_RESPONSE:
+        if (DCE2_SsnFromClient(p))
+        {
+            if (is_seg_buf)
+                DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
+            else
+                dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats);
+        }
+
+        break;
+
+    case NBSS_SESSION_TYPE__KEEP_ALIVE:
+        DebugMessage(DEBUG_DCE_SMB, "Session Keep Alive\n");
+        break;
+
+    default:
+        DebugFormat(DEBUG_DCE_SMB,
+            "Invalid Session Service type: 0x%02X\n", NbssType(nb_hdr));
+
+        if (is_seg_buf)
+            DCE2_SmbSegAlert(ssd, DCE2_SMB_BAD_NBSS_TYPE);
+        else
+            dce_alert(GID_DCE2, DCE2_SMB_BAD_NBSS_TYPE, (dce2CommonStats*)&dce2_smb_stats);
+
+        return DCE2_RET__ERROR;
+    }
+
+    return DCE2_RET__IGNORE;
+}
+
+
+// This is the main entry point for SMB1 processing.
+static void DCE2_Smb1Process(DCE2_SmbSsnData* ssd)
+{
+    DebugMessage(DEBUG_DCE_SMB, "Processing SMB packet.\n");
+    dce2_smb_stats.smb_pkts++;
+
+    const Packet* p = ssd->sd.wire_pkt;
+    const uint8_t* data_ptr = p->data;
+    uint16_t data_len = p->dsize;
+    DCE2_Buffer** seg_buf = DCE2_SmbGetSegBuffer(ssd);
+
+    /* Have to account for segmentation.  Even though stream will give
+     * us larger chunks, we might end up in the middle of something */
+    while (data_len > 0)
+    {
+        // We are ignoring an entire PDU or junk data so state should be NETBIOS_HEADER
+        // Note that it could be TCP segmented so ignore_bytes could be greater than
+        // the amount of data we have
+        uint32_t* ignore_bytes = DCE2_SmbGetIgnorePtr(ssd);
+        if (*ignore_bytes)
+        {
+            DebugFormat(DEBUG_DCE_SMB, "Ignoring %u bytes\n", *ignore_bytes);
+
+            if (data_len <= *ignore_bytes)
+            {
+                *ignore_bytes -= data_len;
+                return;
+            }
+            else
+            {
+                /* ignore bytes is less than UINT16_MAX */
+                DCE2_MOVE(data_ptr, data_len, (uint16_t)*ignore_bytes);
+                *ignore_bytes = 0;
+            }
+        }
+
+        DCE2_SmbDataState* data_state = DCE2_SmbGetDataState(ssd);
+        DCE2_SmbRequestTracker* rtracker = nullptr;
+        switch (*data_state)
+        {
+        // This state is to verify it's a NetBIOS Session Message packet
+        // and to get the length of the SMB PDU.  Also does the SMB junk
+        // data check.  If it's not a Session Message the data isn't
+        // processed since it won't be carrying SMB.
+        case DCE2_SMB_DATA_STATE__NETBIOS_HEADER:
+        {
+            uint32_t data_need = sizeof(NbssHdr);
+
+            // See if there is enough data to process the NetBIOS header
+            if (data_len < data_need)
+            {
+                DebugFormat(DEBUG_DCE_SMB, "Data len(%hu) < NetBIOS SS header(%u). "
+                    "Queueing data.\n", data_len, data_need);
+
+                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
+                    data_len, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                }
+
+                return;
+            }
+
+            // Set the NetBIOS header structure
+            NbssHdr* nb_hdr;
+            if (DCE2_BufferIsEmpty(*seg_buf))
+            {
+                nb_hdr = (NbssHdr*)data_ptr;
+            }
+            else
+            {
+                // If data already buffered add the remainder for the
+                // size of the NetBIOS header
+                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr,
+                    data_need, sizeof(NbssHdr)) != DCE2_RET__SUCCESS)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                    return;
+                }
+
+                nb_hdr = (NbssHdr*)DCE2_BufferData(*seg_buf);
+            }
+
+            uint32_t nb_len = NbssLen(nb_hdr);
+
+            DebugFormat(DEBUG_DCE_SMB, "NetBIOS PDU length: %u\n", nb_len);
+
+            DCE2_Ret status = DCE2_NbssHdrChecks(ssd, nb_hdr);
+            if (status != DCE2_RET__SUCCESS)
+            {
+                DebugMessage(DEBUG_DCE_SMB, "Not a NetBIOS Session Message.\n");
+
+                if (status == DCE2_RET__IGNORE)
+                {
+                    DebugMessage(DEBUG_DCE_SMB, "Valid NetBIOS header "
+                        "type so ignoring NetBIOS length bytes.\n");
+                    *ignore_bytes = data_need + nb_len;
+                }
+                else      // nb_ret == DCE2_RET__ERROR, i.e. invalid NetBIOS type
+                {
+                    DebugMessage(DEBUG_DCE_SMB, "Not a valid NetBIOS "
+                        "header type so trying to find \\xffSMB to "
+                        "determine how many bytes to ignore.\n");
+                    *ignore_bytes = DCE2_IgnoreJunkData(data_ptr, data_len, data_need + nb_len);
+                }
+
+                DCE2_BufferEmpty(*seg_buf);
+                dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
+                continue;
+            }
+
+            if (!DCE2_BufferIsEmpty(*seg_buf))
+                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
+
+            switch (ssd->pdu_state)
+            {
+            case DCE2_SMB_PDU_STATE__COMMAND:
+                *data_state = DCE2_SMB_DATA_STATE__SMB_HEADER;
+                break;
+            case DCE2_SMB_PDU_STATE__RAW_DATA:
+                *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
+                // Continue here because of fall through below
+                continue;
+            default:
+                DebugFormat(DEBUG_DCE_SMB,"%s(%d) Invalid SMB PDU "
+                    "state: %d\n", __FILE__, __LINE__, ssd->pdu_state);
+                return;
+            }
+        }
+
+        // Fall through for DCE2_SMB_DATA_STATE__SMB_HEADER
+        // This is the normal progression without segmentation.
+
+        // This state is to do validation checks on the SMB header and
+        // more importantly verify it's data that needs to be inspected.
+        // If the TID in the SMB header is not referring to the IPC share
+        // there won't be any DCE/RPC traffic associated with it.
+        case DCE2_SMB_DATA_STATE__SMB_HEADER:
+        {
+            uint32_t data_need = (sizeof(NbssHdr) + sizeof(SmbNtHdr)) - DCE2_BufferLength(
+                *seg_buf);
+
+            // See if there is enough data to process the SMB header
+            if (data_len < data_need)
+            {
+                DebugFormat(DEBUG_DCE_SMB, "Data len (%hu) < "
+                    "NetBIOS SS header + SMB header (%u). Queueing data.\n",
+                    data_len, data_need);
+
+                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
+                    sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                    *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+                }
+
+                return;
+            }
+
+            // Set the SMB header structure
+            SmbNtHdr* smb_hdr;
+            if (DCE2_BufferIsEmpty(*seg_buf))
+            {
+                smb_hdr = (SmbNtHdr*)(data_ptr + sizeof(NbssHdr));
+            }
+            else
+            {
+                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
+                    sizeof(NbssHdr) + sizeof(SmbNtHdr)) != DCE2_RET__SUCCESS)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                    *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+                    return;
+                }
+
+                smb_hdr = (SmbNtHdr*)(DCE2_BufferData(*seg_buf) + sizeof(NbssHdr));
+            }
+
+            if (SmbId(smb_hdr) == DCE2_SMB2_ID)
+            {
+                ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
+                if (!DCE2_GcIsLegacyMode((dce2SmbProtoConf*)ssd->sd.config))
+                {
+                    DCE2_Smb2InitFileTracker(&(ssd->ftracker), false, 0);
+                    DCE2_Smb2Process(ssd);
+                }
+                return;
+            }
+
+            // See if this is something we need to inspect
+            rtracker = DCE2_SmbInspect(ssd, smb_hdr);
+            if (rtracker == nullptr)
+            {
+                DebugMessage(DEBUG_DCE_SMB, "Not inspecting SMB packet.\n");
+
+                if (DCE2_BufferIsEmpty(*seg_buf))
+                {
+                    *ignore_bytes = sizeof(NbssHdr) + NbssLen((NbssHdr*)data_ptr);
+                }
+                else
+                {
+                    *ignore_bytes = (NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf))
+                        - sizeof(SmbNtHdr)) + data_need;
+                    DCE2_BufferEmpty(*seg_buf);
+                }
+
+                *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+                dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
+                continue;
+            }
+
+            // Check the SMB header for anomolies
+            if (DCE2_SmbHdrChecks(ssd, smb_hdr) != DCE2_RET__SUCCESS)
+            {
+                DebugMessage(DEBUG_DCE_SMB, "Bad SMB header.\n");
+
+                if (DCE2_BufferIsEmpty(*seg_buf))
+                {
+                    *ignore_bytes = sizeof(NbssHdr) + NbssLen((NbssHdr*)data_ptr);
+                }
+                else
+                {
+                    *ignore_bytes = (NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf))
+                        - sizeof(SmbNtHdr)) + data_need;
+                    DCE2_BufferEmpty(*seg_buf);
+                }
+
+                *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+
+                dce2_smb_stats.smb_ignored_bytes += *ignore_bytes;
+                continue;
+            }
+
+            if (!DCE2_BufferIsEmpty(*seg_buf))
+                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
+
+            *data_state = DCE2_SMB_DATA_STATE__NETBIOS_PDU;
+        }
+
+        // Fall through
+
+        // This state ensures that we have the entire PDU before continuing
+        // to process.
+        case DCE2_SMB_DATA_STATE__NETBIOS_PDU:
+        {
+            uint32_t nb_len;
+            uint32_t data_need;
+
+            if (DCE2_BufferIsEmpty(*seg_buf))
+            {
+                nb_len = NbssLen((NbssHdr*)data_ptr);
+                data_need = sizeof(NbssHdr) + nb_len;
+            }
+            else
+            {
+                nb_len = NbssLen((NbssHdr*)DCE2_BufferData(*seg_buf));
+                data_need = (sizeof(NbssHdr) + nb_len) - DCE2_BufferLength(*seg_buf);
+            }
+
+            /* It's something we want to inspect so make sure we have the full NBSS packet */
+            if (data_len < data_need)
+            {
+                DebugFormat(DEBUG_DCE_SMB, "Data len(%hu) < "
+                    "NetBIOS SS header + NetBIOS len(%zu). "
+                    "Queueing data.\n", data_len, sizeof(NbssHdr) + nb_len);
+
+                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_len,
+                    sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                    *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+                }
+
+                return;
+            }
+
+            // data_len >= data_need which means data_need <= UINT16_MAX
+            // So casts below of data_need to uint16_t are okay.
+
+            *data_state = DCE2_SMB_DATA_STATE__NETBIOS_HEADER;
+
+            const uint8_t* nb_ptr;
+            if (DCE2_BufferIsEmpty(*seg_buf))
+            {
+                nb_ptr = data_ptr;
+                nb_len = data_need;
+                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
+            }
+            else
+            {
+                if (DCE2_SmbHandleSegmentation(seg_buf, data_ptr, data_need,
+                    sizeof(NbssHdr) + nb_len) != DCE2_RET__SUCCESS)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                    DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
+                    continue;
+                }
+
+                DCE2_MOVE(data_ptr, data_len, (uint16_t)data_need);
+
+                nb_ptr = DCE2_BufferData(*seg_buf);
+                nb_len = DCE2_BufferLength(*seg_buf);
+
+                // Get reassembled packet
+                Packet* rpkt = DCE2_SmbGetRpkt(ssd, &nb_ptr, &nb_len,
+                    DCE2_RPKT_TYPE__SMB_SEG);
+                if (rpkt == nullptr)
+                {
+                    DCE2_BufferEmpty(*seg_buf);
+                    continue;
+                }
+
+                nb_ptr = DCE2_BufferData(*seg_buf);
+                nb_len = DCE2_BufferLength(*seg_buf);
+
+                DebugFormat(DEBUG_DCE_SMB,
+                    "Segmentation buffer: len: %u, size: %u\n",
+                    DCE2_BufferLength(*seg_buf), DCE2_BufferSize(*seg_buf));
+
+                if (DCE2_SsnFromClient(ssd->sd.wire_pkt))
+                    dce2_smb_stats.smb_cli_seg_reassembled++;
+                else
+                    dce2_smb_stats.smb_srv_seg_reassembled++;
+
+                DebugMessage(DEBUG_DCE_SMB, "TCP reassembled SMB PDU\n");
+                DCE2_PrintPktData(rpkt->data, rpkt->dsize);
+            }
+
+            switch (ssd->pdu_state)
+            {
+            case DCE2_SMB_PDU_STATE__COMMAND:
+            {
+                SmbNtHdr* smb_hdr = (SmbNtHdr*)(nb_ptr + sizeof(NbssHdr));
+                DCE2_MOVE(nb_ptr, nb_len, (sizeof(NbssHdr) + sizeof(SmbNtHdr)));
+                ssd->cur_rtracker = (rtracker != nullptr)
+                    ? rtracker : DCE2_SmbFindRequestTracker(ssd, smb_hdr);
+                if (ssd->cur_rtracker != nullptr)
+                    DCE2_SmbProcessCommand(ssd, smb_hdr, nb_ptr, nb_len);
+                break;
+            }
+
+            case DCE2_SMB_PDU_STATE__RAW_DATA:
+                DCE2_MOVE(nb_ptr, nb_len, sizeof(NbssHdr));
+                if (ssd->cur_rtracker != nullptr)
+                    DCE2_SmbProcessRawData(ssd, nb_ptr, nb_len);
+                // Only one raw read or write
+                ssd->pdu_state = DCE2_SMB_PDU_STATE__COMMAND;
+                break;
+            default:
+                DebugFormat(DEBUG_DCE_SMB, "%s(%d) Invalid SMB PDU "
+                    "state: %d\n", __FILE__, __LINE__, ssd->pdu_state);
+                return;
+            }
+
+            if (!DCE2_BufferIsEmpty(*seg_buf))
+            {
+                DCE2_SmbReturnRpkt(ssd);
+                DCE2_BufferDestroy(*seg_buf);
+                *seg_buf = nullptr;
+            }
+
+            break;
+        }
+
+        default:
+            DebugFormat(DEBUG_DCE_SMB, "%s(%d) Invalid SMB Data "
+                "state: %d\n", __FILE__, __LINE__, *data_state);
+            return;
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+// public methods
+//-------------------------------------------------------------------------
+
+/********************************************************************
+ * Function: DCE2_SmbInitGlobals()
+ *
+ * Purpose:
+ *  Initializes global variables for SMB processing.
+ *  Sets up the functions and valid word and byte counts for SMB
+ *  commands.
+ *  Sets up AndX chain mappings and valid command chaining for
+ *  supported policies.
+ *
+ * Arguments: None
+ *
+ * Returns: None
+ *
+ ********************************************************************/
+void DCE2_SmbInitGlobals()
+{
+    memset(&smb_wcts, 0, sizeof(smb_wcts));
+    memset(&smb_bccs, 0, sizeof(smb_bccs));
+
+    // Sets up the function to call for the command and valid word and byte
+    // counts for the command.  Ensuring valid word and byte counts is very
+    // important to processing the command as it will assume the command is
+    // legitimate and can access data that is acutally there.  Note that
+    // commands with multiple word counts indicate a different command
+    // structure, however most, if not all just have an extended version
+    // of the structure for which the extended part isn't used.  If the
+    // extended part of a command structure needs to be used, be sure to
+    // check the word count in the command function before accessing data
+    // in the extended version of the command structure.
+    for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
+    {
+        switch (com)
+        {
+        case SMB_COM_OPEN:
+            smb_com_funcs[com] = DCE2_SmbOpen;
+
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_CREATE:
+            smb_com_funcs[com] = DCE2_SmbCreate;
+
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_CLOSE:
+            smb_com_funcs[com] = DCE2_SmbClose;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_RENAME:
+            smb_com_funcs[com] = DCE2_SmbRename;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 1);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 4, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_READ:
+            smb_com_funcs[com] = DCE2_SmbRead;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
+            break;
+        case SMB_COM_WRITE:
+            smb_com_funcs[com] = DCE2_SmbWrite;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_CREATE_NEW:
+            smb_com_funcs[com] = DCE2_SmbCreateNew;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 3);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_LOCK_AND_READ:
+            smb_com_funcs[com] = DCE2_SmbLockAndRead;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 5);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 3, UINT16_MAX);
+            break;
+        case SMB_COM_WRITE_AND_UNLOCK:
+            smb_com_funcs[com] = DCE2_SmbWriteAndUnlock;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 5);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_READ_RAW:
+            smb_com_funcs[com] = DCE2_SmbReadRaw;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
+            // With optional OffsetHigh
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            // Response is raw data, i.e. without SMB
+            break;
+        case SMB_COM_WRITE_RAW:
+            smb_com_funcs[com] = DCE2_SmbWriteRaw;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
+            // With optional OffsetHigh
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
+            // Interim server response
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_WRITE_COMPLETE:
+            // Final server response to SMB_COM_WRITE_RAW
+            smb_com_funcs[com] = DCE2_SmbWriteComplete;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_TRANSACTION:
+            smb_com_funcs[com] = DCE2_SmbTransaction;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            // Word count depends on setup count
+            //for (i = 14; i < 256; i++)
+            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
+            // In reality, all subcommands of SMB_COM_TRANSACTION requests
+            // have a setup count of 2 words.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 16);
+
+            // \PIPE\LANMAN
+            // Not something the preprocessor is looking at as it
+            // doesn't carry DCE/RPC but don't want to false positive
+            // on the preprocessor event.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
+
+            // Word count depends on setup count
+            //for (i = 10; i < 256; i++)
+            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
+            // In reality, all subcommands of SMB_COM_TRANSACTION responses
+            // have a setup count of 0 words.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
+
+            // Interim server response
+            // When client sends an incomplete transaction and needs to
+            // send TransactionSecondary requests to complete request.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
+
+            // Exception will be made for Interim responses when
+            // byte count is checked.
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_TRANSACTION_SECONDARY:
+            smb_com_funcs[com] = DCE2_SmbTransactionSecondary;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 8);
+            // Response is an SMB_COM_TRANSACTION
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            break;
+        case SMB_COM_WRITE_AND_CLOSE:
+            smb_com_funcs[com] = DCE2_SmbWriteAndClose;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 6);
+            // For some reason MS-CIFS specifies a version of this command
+            // with 6 extra words (12 bytes) of reserved, i.e. useless data.
+            // Maybe had intentions of extending and defining the data at
+            // some point, but there is no documentation that I could find
+            // that does.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_OPEN_ANDX:
+            smb_com_funcs[com] = DCE2_SmbOpenAndX;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 15);
+            // Extended response
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
+            // MS-SMB says that Windows 2000, XP and Vista set this to
+            // some arbitrary value that is ignored on receipt.
+            //DCE2_SmbSetValidByteCount(com, SMB_TYPE__RESPONSE, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_READ_ANDX:
+            smb_com_funcs[com] = DCE2_SmbReadAndX;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
+            // With optional OffsetHigh
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 12);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_WRITE_ANDX:
+            smb_com_funcs[com] = DCE2_SmbWriteAndX;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
+            // With optional OffsetHigh
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 14);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 6);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 1, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_TRANSACTION2:
+            smb_com_funcs[com] = DCE2_SmbTransaction2;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            // Word count depends on setup count
+            //for (i = 14; i < 256; i++)
+            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__REQUEST, i);
+            // In reality, all subcommands of SMB_COM_TRANSACTION2
+            // requests have a setup count of 1 word.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 15);
+
+            // Word count depends on setup count
+            //for (i = 10; i < 256; i++)
+            //    DCE2_SmbSetValidWordCount(com, SMB_TYPE__RESPONSE, i);
+            // In reality, all subcommands of SMB_COM_TRANSACTION2
+            // responses have a setup count of 0 or 1 word.
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 10);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 11);
+
+            // Interim server response
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
+
+            // Exception will be made for Interim responses when
+            // byte count is checked.
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_TRANSACTION2_SECONDARY:
+            smb_com_funcs[com] = DCE2_SmbTransaction2Secondary;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 9);
+            // Response is an SMB_COM_TRANSACTION2
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            break;
+        case SMB_COM_TREE_CONNECT:
+            smb_com_funcs[com] = DCE2_SmbTreeConnect;
+            smb_deprecated_coms[com] = true;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 6, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_TREE_DISCONNECT:
+            smb_com_funcs[com] = DCE2_SmbTreeDisconnect;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_NEGOTIATE:
+            smb_com_funcs[com] = DCE2_SmbNegotiate;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 0);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 1);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 13);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 17);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
+            // This can vary depending on dialect so just set wide.
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_SESSION_SETUP_ANDX:
+            smb_com_funcs[com] = DCE2_SmbSessionSetupAndX;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 10);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 12);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 13);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 4);
+
+            // These can vary so just set wide.
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_LOGOFF_ANDX:
+            smb_com_funcs[com] = DCE2_SmbLogoffAndX;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 2);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
+            // Windows responds to a LogoffAndX => SessionSetupAndX with just a
+            // LogoffAndX and with the word count field containing 3, but only
+            // has 2 words
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            break;
+        case SMB_COM_TREE_CONNECT_ANDX:
+            smb_com_funcs[com] = DCE2_SmbTreeConnectAndX;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 4);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 2);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 3);
+            // Extended response
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 7);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 3, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 2, UINT16_MAX);
+            break;
+        case SMB_COM_NT_TRANSACT:
+            smb_com_funcs[com] = DCE2_SmbNtTransact;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            // Word count depends on setup count
+            // In reality, all subcommands of SMB_COM_NT_TRANSACT
+            // requests have a setup count of 0 or 4 words.
+            //for (i = 19; i < 256; i++)
+            //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, i);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 19);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 23);
+
+            // Word count depends on setup count
+            // In reality, all subcommands of SMB_COM_NT_TRANSACT
+            // responses have a setup count of 0 or 1 word.
+            //for (i = 18; i < 256; i++)
+            //    DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, i);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 18);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 19);
+
+            // Interim server response
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 0);
+
+            // Exception will be made for Interim responses when
+            // byte count is checked.
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        case SMB_COM_NT_TRANSACT_SECONDARY:
+            smb_com_funcs[com] = DCE2_SmbNtTransactSecondary;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 18);
+            // Response is an SMB_COM_NT_TRANSACT
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            break;
+        case SMB_COM_NT_CREATE_ANDX:
+            smb_com_funcs[com] = DCE2_SmbNtCreateAndX;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, 24);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 34);
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 26);
+            // Extended response - though there are actually 50 words
+            DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, 42);
+
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 2, UINT16_MAX);
+            // MS-SMB indicates that this field should be 0 but may be
+            // sent uninitialized so basically ignore it.
+            //DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, 0);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        default:
+            smb_com_funcs[com] = nullptr;
+            smb_deprecated_coms[com] = false;
+            smb_unusual_coms[com] = false;
+            // Just set to all valid since the specific command won't
+            // be processed.  Don't want to false positive on these.
+            for (int i = 0; i < 256; i++)
+            {
+                DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__REQUEST, (uint8_t)i);
+                DCE2_SmbSetValidWordCount((uint8_t)com, SMB_TYPE__RESPONSE, (uint8_t)i);
+            }
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__REQUEST, 0, UINT16_MAX);
+            DCE2_SmbSetValidByteCount((uint8_t)com, SMB_TYPE__RESPONSE, 0, UINT16_MAX);
+            break;
+        }
+    }
+
+    // Maps commands for use in quickly determining if a command
+    // is chainable and what command it is.
+    for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
+    {
+        switch (com)
+        {
+        case SMB_COM_SESSION_SETUP_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__SESSION_SETUP_ANDX;
+            break;
+        case SMB_COM_LOGOFF_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__LOGOFF_ANDX;
+            break;
+        case SMB_COM_TREE_CONNECT_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__TREE_CONNECT_ANDX;
+            break;
+        case SMB_COM_OPEN_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__OPEN_ANDX;
+            break;
+        case SMB_COM_NT_CREATE_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__NT_CREATE_ANDX;
+            break;
+        case SMB_COM_WRITE_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__WRITE_ANDX;
+            break;
+        case SMB_COM_READ_ANDX:
+            smb_chain_map[com] = SMB_ANDX_COM__READ_ANDX;
+            break;
+        default:
+            smb_chain_map[com] = SMB_ANDX_COM__NONE;
+            break;
+        }
+    }
+
+    // Sets up the valid command chaining combinations per policy
+    for (int policy = 0; policy < DCE2_POLICY__MAX; policy++)
+    {
+        for (int andx = SMB_ANDX_COM__NONE; andx < SMB_ANDX_COM__MAX; andx++)
+        {
+            /* com is the chained command or com2 */
+            for (int com = 0; com < SMB_MAX_NUM_COMS; com++)
+            {
+                DCE2_SmbComFunc com_func = nullptr;
+
+                switch (policy)
+                {
+                case DCE2_POLICY__WIN2000:
+                case DCE2_POLICY__WINXP:
+                case DCE2_POLICY__WINVISTA:
+                case DCE2_POLICY__WIN2003:
+                case DCE2_POLICY__WIN2008:
+                case DCE2_POLICY__WIN7:
+                    switch (andx)
+                    {
+                    case SMB_ANDX_COM__SESSION_SETUP_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_TREE_CONNECT_ANDX:
+                        case SMB_COM_OPEN:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_CREATE:
+                        case SMB_COM_CREATE_NEW:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        case SMB_COM_TRANSACTION:
+                            if (policy == DCE2_POLICY__WIN2000)
+                                com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__LOGOFF_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_TREE_CONNECT_ANDX:               // Only for responses
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__TREE_CONNECT_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_OPEN:
+                        case SMB_COM_CREATE:
+                        case SMB_COM_CREATE_NEW:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        case SMB_COM_TRANSACTION:
+                            if (policy == DCE2_POLICY__WIN2000)
+                                com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__OPEN_ANDX:
+                        break;
+                    case SMB_ANDX_COM__NT_CREATE_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_READ_ANDX:              // Only for normal files
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__WRITE_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_CLOSE:
+                        case SMB_COM_WRITE_ANDX:
+                        case SMB_COM_READ:
+                        case SMB_COM_READ_ANDX:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__READ_ANDX:
+                        break;
+                    default:
+                        break;
+                    }
+                    break;
+                case DCE2_POLICY__SAMBA:
+                case DCE2_POLICY__SAMBA_3_0_37:
+                case DCE2_POLICY__SAMBA_3_0_22:
+                case DCE2_POLICY__SAMBA_3_0_20:
+                    switch (andx)
+                    {
+                    case SMB_ANDX_COM__SESSION_SETUP_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_LOGOFF_ANDX:
+                        case SMB_COM_TREE_CONNECT:
+                        case SMB_COM_TREE_CONNECT_ANDX:
+                        case SMB_COM_TREE_DISCONNECT:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_NT_CREATE_ANDX:
+                        case SMB_COM_CLOSE:
+                        case SMB_COM_READ_ANDX:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        case SMB_COM_WRITE:
+                            if ((policy == DCE2_POLICY__SAMBA_3_0_22)
+                                || (policy == DCE2_POLICY__SAMBA_3_0_20))
+                                com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__LOGOFF_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_TREE_DISCONNECT:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__TREE_CONNECT_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_LOGOFF_ANDX:
+                        case SMB_COM_TREE_DISCONNECT:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_NT_CREATE_ANDX:
+                        case SMB_COM_CLOSE:
+                        case SMB_COM_WRITE:
+                        case SMB_COM_READ_ANDX:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__OPEN_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_LOGOFF_ANDX:
+                        case SMB_COM_TREE_CONNECT:
+                        case SMB_COM_TREE_CONNECT_ANDX:
+                        case SMB_COM_TREE_DISCONNECT:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_NT_CREATE_ANDX:
+                        case SMB_COM_CLOSE:
+                        case SMB_COM_WRITE:
+                        case SMB_COM_READ_ANDX:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__NT_CREATE_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_TREE_CONNECT:
+                        case SMB_COM_TREE_CONNECT_ANDX:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_NT_CREATE_ANDX:
+                        case SMB_COM_WRITE:
+                        case SMB_COM_READ_ANDX:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        case SMB_COM_LOGOFF_ANDX:
+                        case SMB_COM_TREE_DISCONNECT:
+                        case SMB_COM_CLOSE:
+                            if ((policy == DCE2_POLICY__SAMBA)
+                                || (policy == DCE2_POLICY__SAMBA_3_0_37))
+                                com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__WRITE_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_LOGOFF_ANDX:
+                        case SMB_COM_TREE_CONNECT:
+                        case SMB_COM_TREE_CONNECT_ANDX:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_NT_CREATE_ANDX:
+                        case SMB_COM_CLOSE:
+                        case SMB_COM_WRITE:
+                        case SMB_COM_READ_ANDX:
+                        case SMB_COM_WRITE_ANDX:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    case SMB_ANDX_COM__READ_ANDX:
+                        switch (com)
+                        {
+                        case SMB_COM_SESSION_SETUP_ANDX:
+                        case SMB_COM_WRITE:
+                            com_func = smb_com_funcs[com];
+                            break;
+                        case SMB_COM_LOGOFF_ANDX:
+                        case SMB_COM_TREE_CONNECT:
+                        case SMB_COM_TREE_CONNECT_ANDX:
+                        case SMB_COM_TREE_DISCONNECT:
+                        case SMB_COM_OPEN_ANDX:
+                        case SMB_COM_NT_CREATE_ANDX:
+                        case SMB_COM_CLOSE:
+                        case SMB_COM_READ_ANDX:
+                            if ((policy == DCE2_POLICY__SAMBA)
+                                || (policy == DCE2_POLICY__SAMBA_3_0_37))
+                                com_func = smb_com_funcs[com];
+                            break;
+                        default:
+                            break;
+                        }
+                        break;
+                    default:
+                        break;
+                    }
+                    break;
+                default:
+                    break;
+                }
+
+                smb_chain_funcs[policy][andx][com] = com_func;
+            }
+        }
+    }
+}
+
+DCE2_SmbSsnData* dce2_handle_smb_session(Packet* p, dce2SmbProtoConf* config)
+{
+    Profile profile(dce2_smb_pstat_session);
+
+    DCE2_SmbSsnData* dce2_smb_sess =  get_dce2_smb_session_data(p->flow);
+
+    if (dce2_smb_sess == nullptr)
+    {
+        dce2_smb_sess = dce2_create_new_smb_session(p, config);
+    }
+
+    DebugFormat(DEBUG_DCE_SMB, "Session pointer: %p\n", (void*)dce2_smb_sess);
+
+    return dce2_smb_sess;
+}
+
+// This is the main entry point for SMB processing
+void DCE2_SmbProcess(DCE2_SmbSsnData* ssd)
+{
+    if (DCE2_GcIsLegacyMode((dce2SmbProtoConf*)ssd->sd.config))
+    {
+        DCE2_Smb1Process(ssd);
+        return;
+    }
+
+    Packet* p = ssd->sd.wire_pkt;
+    DCE2_SmbVersion smb_version = DCE2_Smb2Version(p);
+    if (smb_version == DCE2_SMB_VERISON_1)
+    {
+        if ((ssd->sd.flags & DCE2_SSN_FLAG__SMB2))
+        {
+            DebugMessage(DEBUG_DCE_SMB, "SMB1 packet detected!\n");
+            ssd->sd.flags &= ~DCE2_SSN_FLAG__SMB2;
+            DCE2_SmbCleanFileTracker(&(ssd->ftracker));
+            ssd->ftracker.is_smb2 = false;
+        }
+    }
+    else if (smb_version == DCE2_SMB_VERISON_2)
+    {
+        if (!(ssd->sd.flags & DCE2_SSN_FLAG__SMB2))
+        {
+            DebugMessage(DEBUG_DCE_SMB, "SMB2 packet detected!\n");
+            DCE2_SmbCleanFileTracker(&(ssd->ftracker));
+            DCE2_Smb2InitFileTracker(&(ssd->ftracker), 0, 0);
+            ssd->sd.flags |= DCE2_SSN_FLAG__SMB2;
+        }
+    }
+
+    if (ssd->sd.flags & DCE2_SSN_FLAG__SMB2)
+        DCE2_Smb2Process(ssd);
+    else
+        DCE2_Smb1Process(ssd);
+}
+
diff --git a/src/service_inspectors/dce_rpc/smb_message.h b/src/service_inspectors/dce_rpc/smb_message.h
new file mode 100644 (file)
index 0000000..f68ebf9
--- /dev/null
@@ -0,0 +1,2179 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2016-2016 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// smb_message.h author Russ Combs <rucombs@cisco.com>
+
+// extracted from dce_smb.h originally written by Todd Wease
+
+#ifndef SMB_MESSAGE_H
+#define SMB_MESSAGE_H
+
+#include <stdint.h>
+
+/********************************************************************
+ * SMB_COM_OPEN
+ ********************************************************************/
+struct SmbOpenReq   /* smb_wct = 2 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_mode;    /* r/w/share */
+    uint16_t smb_attr;    /* attribute */
+    uint16_t smb_bcc;     /* min = 2 */
+};
+
+struct SmbOpenResp   /* smb_wct = 7 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;     /* file handle */
+    uint16_t smb_attr;    /* attribute */
+    uint32_t smb_time;    /* time1 low */
+    uint32_t smb_file_size;   /* file size low */
+    uint16_t smb_access;  /* access allowed */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+#define SMB_OPEN_ACCESS_MODE__READ        0x0000
+#define SMB_OPEN_ACCESS_MODE__WRITE       0x0001
+#define SMB_OPEN_ACCESS_MODE__READ_WRITE  0x0002
+#define SMB_OPEN_ACCESS_MODE__EXECUTE     0x0003
+
+inline uint16_t SmbOpenRespFid(const SmbOpenResp* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+inline uint32_t SmbOpenRespFileSize(const SmbOpenResp* resp)
+{
+    return alignedNtohl(&resp->smb_file_size);
+}
+
+inline uint16_t SmbOpenRespFileAttrs(const SmbOpenResp* resp)
+{
+    return alignedNtohs(&resp->smb_attr);
+}
+
+inline bool SmbFileAttrsDirectory(const uint16_t file_attrs)
+{
+    if (file_attrs & SMB_FILE_ATTRIBUTE_DIRECTORY)
+        return true;
+    return false;
+}
+
+inline uint16_t SmbOpenRespAccessMode(const SmbOpenResp* resp)
+{
+    return alignedNtohs(&resp->smb_access);
+}
+
+inline bool SmbOpenForWriting(const uint16_t access_mode)
+{
+    return access_mode == SMB_OPEN_ACCESS_MODE__WRITE;
+}
+
+/********************************************************************
+ * SMB_COM_CREATE
+ ********************************************************************/
+struct SmbCreateReq   /* smb_wct = 3 */
+{
+    uint8_t smb_wct;
+    uint16_t smb_file_attrs;
+    uint32_t smb_creation_time;
+    uint16_t smb_bcc;
+};
+
+struct SmbCreateResp   /* smb_wct = 1 */
+{
+    uint8_t smb_wct;
+    uint16_t smb_fid;
+    uint16_t smb_bcc;
+};
+
+inline uint16_t SmbCreateReqFileAttrs(const SmbCreateReq* req)
+{
+    return alignedNtohs(&req->smb_file_attrs);
+}
+
+inline bool SmbAttrDirectory(const uint16_t file_attrs)
+{
+    if (file_attrs & SMB_FILE_ATTRIBUTE_DIRECTORY)
+        return true;
+    return false;
+}
+
+inline uint16_t SmbCreateRespFid(const SmbCreateResp* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+/********************************************************************
+ * SMB_COM_CLOSE
+ ********************************************************************/
+struct SmbCloseReq   /* smb_wct = 3 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;     /* file handle */
+    uint16_t smb_tlow;    /* time low */
+    uint16_t smb_thigh;   /* time high */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+struct SmbCloseResp   /* smb_wct = 0 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+inline uint16_t SmbCloseReqFid(const SmbCloseReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+/********************************************************************
+ * SMB_COM_READ
+ ********************************************************************/
+struct SmbReadReq   /* smb_wct = 5 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;     /* file handle */
+    uint16_t smb_cnt;     /* count of bytes */
+    uint32_t smb_off;     /* offset */
+    uint16_t smb_left;    /* count left */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+struct SmbReadResp   /* smb_wct = 5 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_cnt;     /* count */
+    uint16_t smb_res[4];  /* reserved (MBZ) */
+    uint16_t smb_bcc;     /* length of data + 3 */
+};
+
+inline uint16_t SmbReadReqFid(const SmbReadReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint32_t SmbReadReqOffset(const SmbReadReq* req)
+{
+    return alignedNtohl(&req->smb_off);
+}
+
+inline uint16_t SmbReadRespCount(const SmbReadResp* resp)
+{
+    return alignedNtohs(&resp->smb_cnt);
+}
+
+/********************************************************************
+ * SMB_COM_WRITE
+ ********************************************************************/
+struct SmbWriteReq   /* smb_wct = 5 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;     /* file handle */
+    uint16_t smb_cnt;     /* count of bytes */
+    uint32_t smb_offset;  /* file offset in bytes */
+    uint16_t smb_left;    /* count left */
+    uint16_t smb_bcc;     /* length of data + 3 */
+};
+
+struct SmbWriteResp   /* smb_wct = 1 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_cnt;     /* count */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+inline uint16_t SmbWriteReqFid(const SmbWriteReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint16_t SmbWriteReqCount(const SmbWriteReq* req)
+{
+    return alignedNtohs(&req->smb_cnt);
+}
+
+inline uint32_t SmbWriteReqOffset(const SmbWriteReq* req)
+{
+    return alignedNtohl(&req->smb_offset);
+}
+
+inline uint16_t SmbWriteRespCount(const SmbWriteResp* resp)
+{
+    return alignedNtohs(&resp->smb_cnt);
+}
+
+/********************************************************************
+ * SMB_COM_CREATE_NEW
+ ********************************************************************/
+struct SmbCreateNewReq   /* smb_wct = 3 */
+{
+    uint8_t smb_wct;
+    uint16_t smb_file_attrs;
+    uint32_t smb_creation_time;
+    uint16_t smb_bcc;
+};
+
+struct SmbCreateNewResp   /* smb_wct = 1 */
+{
+    uint8_t smb_wct;
+    uint16_t smb_fid;
+    uint16_t smb_bcc;
+};
+
+inline uint16_t SmbCreateNewReqFileAttrs(const SmbCreateNewReq* req)
+{
+    return alignedNtohs(&req->smb_file_attrs);
+}
+
+inline uint16_t SmbCreateNewRespFid(const SmbCreateNewResp* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+/********************************************************************
+ * SMB_COM_LOCK_AND_READ
+ ********************************************************************/
+struct SmbLockAndReadReq   /* smb_wct = 5 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;
+    uint16_t smb_cnt;
+    uint32_t smb_read_offset;
+    uint16_t smb_remaining;
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+struct SmbLockAndReadResp   /* smb_wct = 5 */
+{
+    uint8_t smb_wct;
+    uint16_t smb_cnt;
+    uint16_t reserved[4];
+    uint16_t smb_bcc;
+};
+
+inline uint16_t SmbLockAndReadReqFid(const SmbLockAndReadReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint32_t SmbLockAndReadReqOffset(const SmbLockAndReadReq* req)
+{
+    return alignedNtohl(&req->smb_read_offset);
+}
+
+inline uint16_t SmbLockAndReadRespCount(const SmbLockAndReadResp* resp)
+{
+    return alignedNtohs(&resp->smb_cnt);
+}
+
+/********************************************************************
+ * SMB_COM_WRITE_AND_UNLOCK
+ ********************************************************************/
+struct SmbWriteAndUnlockReq
+{
+    uint8_t smb_wct;
+    uint16_t smb_fid;
+    uint16_t smb_cnt;
+    uint32_t smb_write_offset;
+    uint16_t smb_estimate_of_remaining;
+    uint16_t smb_bcc;
+};
+
+struct SmbWriteAndUnlockResp   /* smb_wct = 1 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_cnt;     /* count */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+inline uint16_t SmbWriteAndUnlockReqFid(const SmbWriteAndUnlockReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint16_t SmbWriteAndUnlockReqCount(const SmbWriteAndUnlockReq* req)
+{
+    return alignedNtohs(&req->smb_cnt);
+}
+
+inline uint32_t SmbWriteAndUnlockReqOffset(const SmbWriteAndUnlockReq* req)
+{
+    return alignedNtohl(&req->smb_write_offset);
+}
+
+/********************************************************************
+ * SMB_COM_OPEN_ANDX
+ ********************************************************************/
+struct SmbOpenAndXReq   /* smb_wct = 15 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;        /* reserved (must be zero) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_flags;      /* additional information:
+                                bit 0 - if set, return additional information
+                                bit 1 - if set, set single user total file lock (if only access)
+                                bit 2 - if set, the server should notify the consumer on any
+                                        action which can modify the file (delete, setattrib,
+                                        rename, etc.). if not set, the server need only notify
+                                        the consumer on another open request. This bit only has
+                                        meaning if bit 1 is set. */
+    uint16_t smb_mode;       /* file open mode */
+    uint16_t smb_sattr;      /* search attributes */
+    uint16_t smb_attr;       /* file attributes (for create) */
+    uint32_t smb_time;       /* create time */
+    uint16_t smb_ofun;       /* open function */
+    uint32_t smb_size;       /* bytes to reserve on "create" or "truncate" */
+    uint32_t smb_timeout;    /* max milliseconds to wait for resource to open */
+    uint32_t smb_rsvd;       /* reserved (must be zero) */
+    uint16_t smb_bcc;        /* minimum value = 1 */
+};
+
+struct SmbOpenAndXResp   /* smb_wct = 15 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_res2;        /* reserved (pad to word) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_fid;        /* file handle */
+    uint16_t smb_attribute;  /* attributes of file or device */
+    uint32_t smb_time;       /* last modification time */
+    uint32_t smb_size;       /* current file size */
+    uint16_t smb_access;     /* access permissions actually allowed */
+    uint16_t smb_type;       /* file type */
+    uint16_t smb_state;      /* state of IPC device (e.g. pipe) */
+    uint16_t smb_action;     /* action taken */
+    uint32_t smb_fileid;     /* server unique file id */
+    uint16_t smb_rsvd;       /* reserved */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+inline uint32_t SmbOpenAndXReqAllocSize(const SmbOpenAndXReq* req)
+{
+    return alignedNtohl(&req->smb_size);
+}
+
+inline uint16_t SmbOpenAndXReqFileAttrs(const SmbOpenAndXReq* req)
+{
+    return alignedNtohs(&req->smb_attr);
+}
+
+inline uint16_t SmbOpenAndXRespFid(const SmbOpenAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+inline uint16_t SmbOpenAndXRespFileAttrs(const SmbOpenAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_attribute);
+}
+
+inline uint32_t SmbOpenAndXRespFileSize(const SmbOpenAndXResp* resp)
+{
+    return alignedNtohl(&resp->smb_size);
+}
+
+inline uint16_t SmbOpenAndXRespResourceType(const SmbOpenAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_type);
+}
+
+#define SMB_OPEN_RESULT__EXISTED    0x0001
+#define SMB_OPEN_RESULT__CREATED    0x0002
+#define SMB_OPEN_RESULT__TRUNCATED  0x0003
+
+inline uint16_t SmbOpenAndXRespOpenResults(const SmbOpenAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_action);
+}
+
+inline bool SmbOpenResultRead(const uint16_t open_results)
+{
+    return ((open_results & 0x00FF) == SMB_OPEN_RESULT__EXISTED);
+}
+
+inline bool SmbResourceTypeDisk(const uint16_t resource_type)
+{
+    return resource_type == SMB_FILE_TYPE_DISK;
+}
+
+/********************************************************************
+ * SMB_COM_READ_ANDX
+ ********************************************************************/
+struct SmbReadAndXReq   /* smb_wct = 10 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;        /* reserved (must be zero) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_fid;        /* file handle */
+    uint32_t smb_offset;     /* offset in file to begin read */
+    uint16_t smb_maxcnt;     /* max number of bytes to return */
+    uint16_t smb_mincnt;     /* min number of bytes to return */
+    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
+    uint16_t smb_countleft;  /* bytes remaining to satisfy user’s request */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+struct SmbReadAndXExtReq   /* smb_wct = 12 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;        /* reserved (must be zero) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_fid;        /* file handle */
+    uint32_t smb_offset;     /* low offset in file to begin read */
+    uint16_t smb_maxcnt;     /* max number of bytes to return */
+    uint16_t smb_mincnt;     /* min number of bytes to return */
+    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
+    uint16_t smb_countleft;  /* bytes remaining to satisfy user’s request */
+    uint32_t smb_off_high;   /* high offset in file to begin read */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+struct SmbReadAndXResp    /* smb_wct = 12 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_res2;        /* reserved (pad to word) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_remaining;  /* bytes remaining to be read (pipes/devices only) */
+    uint32_t smb_rsvd;       /* reserved */
+    uint16_t smb_dsize;      /* number of data bytes (minimum value = 0) */
+    uint16_t smb_doff;       /* offset (from start of SMB hdr) to data bytes */
+    uint16_t smb_dsize_high; /* high bytes of data size */
+    uint32_t smb_rsvd1;      /* reserved */
+    uint32_t smb_rsvd2;      /* reserved */
+    uint16_t smb_bcc;        /* total bytes (including pad bytes) following */
+};
+
+inline uint16_t SmbReadAndXReqFid(const SmbReadAndXReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint64_t SmbReadAndXReqOffset(const SmbReadAndXExtReq* req)
+{
+    if (req->smb_wct == 10)
+        return (uint64_t)alignedNtohl(&req->smb_offset);
+    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
+        &req->smb_offset);
+}
+
+inline uint16_t SmbReadAndXRespDataOff(const SmbReadAndXResp* req)
+{
+    return alignedNtohs(&req->smb_doff);
+}
+
+inline uint32_t SmbReadAndXRespDataCnt(const SmbReadAndXResp* resp)
+{
+    return (uint32_t)alignedNtohs(&resp->smb_dsize_high) << 16 | (uint32_t)alignedNtohs(
+        &resp->smb_dsize);
+}
+
+/********************************************************************
+ * SMB_COM_WRITE_ANDX
+ ********************************************************************/
+struct SmbWriteAndXReq   /* smb_wct = 12 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;        /* reserved (must be zero) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_fid;        /* file handle */
+    uint32_t smb_offset;     /* offset in file to begin write */
+    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
+    uint16_t smb_wmode;      /* write mode:
+                                bit0 - complete write before return (write through)
+                                bit1 - return smb_remaining (pipes/devices only)
+                                bit2 - use WriteRawNamedPipe (pipes only)
+                                bit3 - this is the start of a message (pipes only) */
+    uint16_t smb_countleft;  /* bytes remaining to write to satisfy user’s request */
+    uint16_t smb_dsize_high; /* high bytes of data size */
+    uint16_t smb_dsize;      /* number of data bytes in buffer (min value = 0) */
+    uint16_t smb_doff;       /* offset (from start of SMB hdr) to data bytes */
+    uint16_t smb_bcc;        /* total bytes (including pad bytes) following */
+};
+
+struct SmbWriteAndXExtReq   /* smb_wct = 14 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;        /* reserved (must be zero) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_fid;        /* file handle */
+    uint32_t smb_offset;     /* low offset in file to begin write */
+    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
+    uint16_t smb_wmode;      /* write mode:
+                                bit0 - complete write before return (write through)
+                                bit1 - return smb_remaining (pipes/devices only)
+                                bit2 - use WriteRawNamedPipe (pipes only)
+                                bit3 - this is the start of a message (pipes only) */
+    uint16_t smb_countleft;  /* bytes remaining to write to satisfy user’s request */
+    uint16_t smb_dsize_high; /* high bytes of data size */
+    uint16_t smb_dsize;      /* number of data bytes in buffer (min value = 0) */
+    uint16_t smb_doff;       /* offset (from start of SMB hdr) to data bytes */
+    uint32_t smb_off_high;   /* high offset in file to begin write */
+    uint16_t smb_bcc;        /* total bytes (including pad bytes) following */
+};
+
+struct SmbWriteAndXResp   /* smb_wct = 6 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_res2;        /* reserved (pad to word) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_count;      /* number of bytes written */
+    uint16_t smb_remaining;  /* bytes remaining to be read (pipes/devices only) */
+    uint16_t smb_count_high; /* high order bytes of data count */
+    uint16_t smb_rsvd;       /* reserved */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+inline uint16_t SmbWriteAndXReqFid(const SmbWriteAndXReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint16_t SmbWriteAndXReqDataOff(const SmbWriteAndXReq* req)
+{
+    return alignedNtohs(&req->smb_doff);
+}
+
+inline uint16_t SmbWriteAndXReqRemaining(const SmbWriteAndXReq* req)
+{
+    return alignedNtohs(&req->smb_countleft);
+}
+
+inline uint64_t SmbWriteAndXReqOffset(const SmbWriteAndXExtReq* req)
+{
+    if (req->smb_wct == 12)
+        return (uint64_t)alignedNtohl(&req->smb_offset);
+    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
+        &req->smb_offset);
+}
+
+inline uint32_t SmbWriteAndXReqDataCnt(const SmbWriteAndXReq* req)
+{
+    return (uint32_t)alignedNtohs(&req->smb_dsize_high) << 16 | (uint32_t)alignedNtohs(
+        &req->smb_dsize);
+}
+
+inline uint16_t SmbWriteAndXReqWriteMode(const SmbWriteAndXReq* req)
+{
+    return alignedNtohs(&req->smb_wmode);
+}
+
+inline bool SmbWriteAndXReqStartRaw(const SmbWriteAndXReq* req)
+{
+    return ((alignedNtohs(&req->smb_wmode) & 0x000c) == 0x000c) ? true : false;
+}
+
+inline bool SmbWriteAndXReqRaw(const SmbWriteAndXReq* req)
+{
+    return ((alignedNtohs(&req->smb_wmode) & 0x000c) == 0x0004) ? true : false;
+}
+
+inline uint16_t SmbWriteAndXRespCnt(const SmbWriteAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_count);
+}
+
+/********************************************************************
+ * SMB_COM_SESSION_SETUP_ANDX
+ ********************************************************************/
+struct SmbLm10_SessionSetupAndXReq   /* smb_wct = 10 */
+{
+    uint8_t smb_wct;       /* count of 16-bit words that follow */
+    uint8_t smb_com2;      /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;      /* reserved (must be zero) */
+    uint16_t smb_off2;     /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_bufsize;  /* the consumers max buffer size */
+    uint16_t smb_mpxmax;   /* actual maximum multiplexed pending requests */
+    uint16_t smb_vc_num;   /* 0 = first (only), non zero - additional VC number */
+    uint32_t smb_sesskey;  /* Session Key (valid only if smb_vc_num != 0) */
+    uint16_t smb_apasslen; /* size of account password (smb_apasswd) */
+    uint32_t smb_rsvd;     /* reserved */
+    uint16_t smb_bcc;      /* minimum value = 0 */
+};
+
+inline uint16_t SmbSessionSetupAndXReqMaxMultiplex(const SmbLm10_SessionSetupAndXReq* req)
+{
+    return alignedNtohs(&req->smb_mpxmax);
+}
+
+/* Extended request as defined in NT LM 1.0 document */
+struct SmbNt10_SessionSetupAndXReq   /* smb_wct = 13 */
+{
+    uint8_t smb_wct;              /* count of 16-bit words that follow */
+    uint8_t smb_com2;             /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;             /* reserved (must be zero) */
+    uint16_t smb_off2;            /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_bufsize;         /* the consumers max buffer size */
+    uint16_t smb_mpxmax;          /* actual maximum multiplexed pending requests */
+    uint16_t smb_vc_num;          /* 0 = first (only), non zero - additional VC number */
+    uint32_t smb_sesskey;         /* Session Key (valid only if smb_vc_num != 0) */
+    uint16_t smb_oem_passlen;     /* case insensitive password length */
+    uint16_t smb_unicode_passlen; /* case sensitive password length */
+    uint32_t smb_rsvd;            /* reserved */
+    uint32_t smb_cap;             /* capabilities */
+    uint16_t smb_bcc;             /* minimum value = 0 */
+};
+
+inline uint16_t SmbNt10SessionSetupAndXReqOemPassLen(const SmbNt10_SessionSetupAndXReq* req)
+{
+    return alignedNtohs(&req->smb_oem_passlen);
+}
+
+inline uint16_t SmbNt10SessionSetupAndXReqUnicodePassLen(const SmbNt10_SessionSetupAndXReq* req)
+{
+    return alignedNtohs(&req->smb_unicode_passlen);
+}
+
+/* Extended request for security blob */
+struct SmbNt10_SessionSetupAndXExtReq   /* smb_wct = 12 */
+{
+    uint8_t smb_wct;          /* count of 16-bit words that follow */
+    uint8_t smb_com2;         /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;         /* reserved (must be zero) */
+    uint16_t smb_off2;        /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_bufsize;     /* the consumers max buffer size */
+    uint16_t smb_mpxmax;      /* actual maximum multiplexed pending requests */
+    uint16_t smb_vc_num;      /* 0 = first (only), non zero - additional VC number */
+    uint32_t smb_sesskey;     /* Session Key (valid only if smb_vc_num != 0) */
+    uint16_t smb_blob_len;    /* length of security blob */
+    uint32_t smb_rsvd;        /* reserved */
+    uint32_t smb_cap;         /* capabilities */
+    uint16_t smb_bcc;         /* minimum value = 0 */
+};
+
+inline uint16_t SmbSessionSetupAndXReqBlobLen(const SmbNt10_SessionSetupAndXExtReq* req)
+{
+    return alignedNtohs(&req->smb_blob_len);
+}
+
+/* Extended response for security blob */
+struct SmbNt10_SessionSetupAndXExtResp   /* smb_wct = 4 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_res2;        /* reserved (pad to word) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_action;     /* request mode:
+                                bit0 = Logged in successfully - BUT as GUEST */
+    uint16_t smb_blob_len;   /* length of security blob */
+    uint16_t smb_bcc;        /* min value = 0 */
+};
+
+inline uint16_t SmbSessionSetupAndXRespBlobLen(const SmbNt10_SessionSetupAndXExtResp* resp)
+{
+    return alignedNtohs(&resp->smb_blob_len);
+}
+
+/********************************************************************
+ * SMB_COM_NEGOTIATE
+ ********************************************************************/
+/* This is the Lanman response */
+struct SmbLm10_NegotiateProtocolResp   /* smb_wct = 13 */
+{
+    uint8_t smb_wct;        /* count of 16-bit words that follow */
+    uint16_t smb_index;     /* index identifying dialect selected */
+    uint16_t smb_secmode;   /* security mode:
+                               bit 0, 1 = User level, 0 = Share level
+                               bit 1, 1 = encrypt passwords, 0 = do not encrypt passwords */
+    uint16_t smb_maxxmt;    /* max transmit buffer size server supports, 1K min */
+    uint16_t smb_maxmux;    /* max pending multiplexed requests server supports */
+    uint16_t smb_maxvcs;    /* max VCs per server/consumer session supported */
+    uint16_t smb_blkmode;   /* block read/write mode support:
+                               bit 0, Read Block Raw supported (65535 bytes max)
+                               bit 1, Write Block Raw supported (65535 bytes max) */
+    uint32_t smb_sesskey;   /* Session Key (unique token identifying session) */
+    uint16_t smb_srv_time;  /* server's current time (hhhhh mmmmmm xxxxx) */
+    uint16_t smb_srv_tzone; /* server's current data (yyyyyyy mmmm ddddd) */
+    uint32_t smb_rsvd;      /* reserved */
+    uint16_t smb_bcc;       /* value = (size of smb_cryptkey) */
+};
+
+/* This is the NT response */
+struct SmbNt_NegotiateProtocolResp     /* smb_wct = 17 */
+{
+    uint8_t smb_wct;            /* count of 16-bit words that follow */
+    uint16_t smb_index;         /* index identifying dialect selected */
+    uint8_t smb_secmode;        /* security mode:
+                                   bit 0, 1 = User level, 0 = Share level
+                                   bit 1, 1 = encrypt passwords, 0 = do not encrypt passwords */
+    uint16_t smb_maxmux;        /* max pending multiplexed requests server supports */
+    uint16_t smb_maxvcs;        /* max VCs per server/consumer session supported */
+    uint32_t smb_maxbuf;        /* maximum buffer size supported */
+    uint32_t smb_maxraw;        /* maximum raw buffer size supported */
+    uint32_t smb_sesskey;       /* Session Key (unique token identifying session) */
+    uint32_t smb_cap;           /* capabilities */
+    struct
+    {
+        uint32_t low_time;
+        int32_t high_time;
+    } smb_srv_time;             /* server time */
+    uint16_t smb_srv_tzone;     /* server's current data (yyyyyyy mmmm ddddd) */
+    uint8_t smb_challenge_len;  /* Challenge length */
+    uint16_t smb_bcc;           /* value = (size of smb_cryptkey) */
+};
+
+inline uint16_t SmbLm_NegotiateRespMaxMultiplex(const SmbLm10_NegotiateProtocolResp* resp)
+{
+    return alignedNtohs(&resp->smb_maxmux);
+}
+
+inline uint16_t SmbNt_NegotiateRespMaxMultiplex(const SmbNt_NegotiateProtocolResp* resp)
+{
+    return alignedNtohs(&resp->smb_maxmux);
+}
+
+/* This is the Core Protocol response */
+struct SmbCore_NegotiateProtocolResp    /* smb_wct = 1 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_index;   /* index */
+    uint16_t smb_bcc;     /* must be 0 */
+};
+
+inline uint16_t SmbNegotiateRespDialectIndex(const SmbCore_NegotiateProtocolResp* resp)
+{
+    return alignedNtohs(&resp->smb_index);
+}
+
+/*********************************************************************
+ * SMB_COM_TREE_CONNECT_ANDX
+ *********************************************************************/
+struct SmbTreeConnectAndXReq   /* smb_wct = 4 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint8_t smb_com2;        /* secondary (X) command, 0xFF = none */
+    uint8_t smb_reh2;        /* reserved (must be zero) */
+    uint16_t smb_off2;       /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint16_t smb_flags;      /* additional information:
+                                bit 0 - if set, disconnect TID in current smb_tid */
+    uint16_t smb_spasslen;   /* length of smb_spasswd */
+    uint16_t smb_bcc;        /* minimum value = 3 */
+};
+
+inline uint16_t SmbTreeConnectAndXReqPassLen(const SmbTreeConnectAndXReq* req)
+{
+    return alignedNtohs(&req->smb_spasslen);
+}
+
+/********************************************************************
+ * SMB_COM_NT_TRANSACT
+ ********************************************************************/
+#define SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY     0x00000004
+
+/********************************************************************
+ * SMB_COM_NT_CREATE_ANDX
+ ********************************************************************/
+#define SMB_CREATE_DISPOSITSION__FILE_SUPERCEDE      0x00000000
+#define SMB_CREATE_DISPOSITSION__FILE_OPEN           0x00000001
+#define SMB_CREATE_DISPOSITSION__FILE_CREATE         0x00000002
+#define SMB_CREATE_DISPOSITSION__FILE_OPEN_IF        0x00000003
+#define SMB_CREATE_DISPOSITSION__FILE_OVERWRITE      0x00000004
+#define SMB_CREATE_DISPOSITSION__FILE_OVERWRITE_IF   0x00000005
+
+struct SmbNtCreateAndXReq   /* smb_wct = 24 */
+{
+    uint8_t smb_wct;            /* count of 16-bit words that follow */
+    uint8_t smb_com2;           /* secondary (X) command, 0xFF = none */
+    uint8_t smb_res2;           /* reserved (pad to word) */
+    uint16_t smb_off2;          /* offset (from SMB hdr start) to next cmd (@smb_wct) */
+    uint8_t smb_res;            /* reserved */
+    uint16_t smb_name_len;      /* length of name of file */
+    uint32_t smb_flags;         /* flags */
+    uint32_t smb_root_fid;      /* fid for previously opened directory */
+    uint32_t smb_access;        /* specifies the type of file access */
+    uint64_t smb_alloc_size;    /* initial allocation size of the file */
+    uint32_t smb_file_attrs;    /* specifies the file attributes for the file */
+    uint32_t smb_share_access;  /* the type of share access */
+    uint32_t smb_create_disp;   /* actions to take if file does or does not exist */
+    uint32_t smb_create_opts;   /* options used when creating or opening file */
+    uint32_t smb_impersonation_level;  /* security impersonation level */
+    uint8_t smb_security_flags;   /* security flags */
+    uint16_t smb_bcc;           /* byte count */
+};
+
+struct SmbNtCreateAndXResp    /* smb_wct = 34 */
+{
+    uint8_t smb_wct;
+    uint8_t smb_com2;
+    uint8_t smb_res2;
+    uint16_t smb_off2;
+    uint8_t smb_oplock_level;
+    uint16_t smb_fid;
+    uint32_t smb_create_disposition;
+    uint64_t smb_creation_time;
+    uint64_t smb_last_access_time;
+    uint64_t smb_last_write_time;
+    uint64_t smb_change_time;
+    uint32_t smb_file_attrs;
+    uint64_t smb_alloc_size;
+    uint64_t smb_eof;
+    uint16_t smb_resource_type;
+    uint16_t smb_nm_pipe_state;
+    uint8_t smb_directory;
+    uint16_t smb_bcc;
+};
+
+// Word count is always set to 42 though there are actually 50 words
+struct SmbNtCreateAndXExtResp    /* smb_wct = 42 */
+{
+    uint8_t smb_wct;
+    uint8_t smb_com2;
+    uint8_t smb_res2;
+    uint16_t smb_off2;
+    uint8_t smb_oplock_level;
+    uint16_t smb_fid;
+    uint32_t smb_create_disposition;
+    uint64_t smb_creation_time;
+    uint64_t smb_last_access_time;
+    uint64_t smb_last_write_time;
+    uint64_t smb_change_time;
+    uint32_t smb_file_attrs;
+    uint64_t smb_alloc_size;
+    uint64_t smb_eof;
+    uint16_t smb_resource_type;
+    uint16_t smb_nm_pipe_state;
+    uint8_t smb_directory;
+    uint8_t smb_volume_guid[16];
+    uint64_t smb_fileid;
+    uint32_t smb_max_access_rights;
+    uint32_t smb_guest_access_rights;
+    uint16_t smb_bcc;
+};
+
+inline uint16_t SmbNtCreateAndXReqFileNameLen(const SmbNtCreateAndXReq* req)
+{
+    return alignedNtohs(&req->smb_name_len);
+}
+
+inline uint32_t SmbNtCreateAndXReqCreateDisposition(const SmbNtCreateAndXReq* req)
+{
+    return alignedNtohl(&req->smb_create_disp);
+}
+
+inline bool SmbCreateDispositionRead(const uint32_t create_disposition)
+{
+    return (create_disposition == SMB_CREATE_DISPOSITSION__FILE_OPEN)
+           || (create_disposition > SMB_CREATE_DISPOSITSION__FILE_OVERWRITE_IF);
+}
+
+inline uint64_t SmbNtCreateAndXReqAllocSize(const SmbNtCreateAndXReq* req)
+{
+    return alignedNtohq(&req->smb_alloc_size);
+}
+
+inline bool SmbNtCreateAndXReqSequentialOnly(const SmbNtCreateAndXReq* req)
+{
+    return (alignedNtohl(&req->smb_create_opts) & SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY);
+}
+
+inline uint32_t SmbNtCreateAndXReqFileAttrs(const SmbNtCreateAndXReq* req)
+{
+    return alignedNtohl(&req->smb_file_attrs);
+}
+
+inline uint16_t SmbNtCreateAndXRespFid(const SmbNtCreateAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+inline uint32_t SmbNtCreateAndXRespCreateDisposition(const SmbNtCreateAndXResp* resp)
+{
+    return alignedNtohl(&resp->smb_create_disposition);
+}
+
+inline bool SmbNtCreateAndXRespDirectory(const SmbNtCreateAndXResp* resp)
+{
+    return (resp->smb_directory ? true : false);
+}
+
+inline uint16_t SmbNtCreateAndXRespResourceType(const SmbNtCreateAndXResp* resp)
+{
+    return alignedNtohs(&resp->smb_resource_type);
+}
+
+inline uint64_t SmbNtCreateAndXRespEndOfFile(const SmbNtCreateAndXResp* resp)
+{
+    return alignedNtohq(&resp->smb_eof);
+}
+
+/********************************************************************
+ * SMB_COM_TRANSACTION
+ ********************************************************************/
+struct SmbTransactionReq   /* smb_wct = 14 + value of smb_suwcnt */
+{
+    /* Note all subcommands use a setup count of 2 */
+    uint8_t smb_wct;       /* count of 16-bit words that follow */
+    uint16_t smb_tpscnt;   /* total number of parameter bytes being sent */
+    uint16_t smb_tdscnt;   /* total number of data bytes being sent */
+    uint16_t smb_mprcnt;   /* max number of parameter bytes to return */
+    uint16_t smb_mdrcnt;   /* max number of data bytes to return */
+    uint8_t smb_msrcnt;    /* max number of setup words to return */
+    uint8_t smb_rsvd;      /* reserved (pad above to word) */
+    uint16_t smb_flags;    /* additional information:
+                              bit 0 - if set, also disconnect TID in smb_tid
+                              bit 1 - if set, transaction is one way (no final response) */
+    uint32_t smb_timeout;  /* number of milliseconds to wait for completion */
+    uint16_t smb_rsvd1;    /* reserved */
+    uint16_t smb_pscnt;    /* number of parameter bytes being sent this buffer */
+    uint16_t smb_psoff;    /* offset (from start of SMB hdr) to parameter bytes */
+    uint16_t smb_dscnt;    /* number of data bytes being sent this buffer */
+    uint16_t smb_dsoff;    /* offset (from start of SMB hdr) to data bytes */
+    uint8_t smb_suwcnt;    /* set up word count */
+    uint8_t smb_rsvd2;     /* reserved (pad above to word) */
+    uint16_t smb_setup1;   /* function (see below)
+                                TRANS_SET_NM_PIPE_STATE   = 0x0001
+                                TRANS_RAW_READ_NMPIPE     = 0x0011
+                                TRANS_QUERY_NMPIPE_STATE  = 0x0021
+                                TRANS_QUERY_NMPIPE_INFO   = 0x0022
+                                TRANS_PEEK_NMPIPE         = 0x0023
+                                TRANS_TRANSACT_NMPIPE     = 0x0026
+                                TRANS_RAW_WRITE_NMPIPE    = 0x0031
+                                TRANS_READ_NMPIPE         = 0x0036
+                                TRANS_WRITE_NMPIPE        = 0x0037
+                                TRANS_WAIT_NMPIPE         = 0x0053
+                                TRANS_CALL_NMPIPE         = 0x0054  */
+    uint16_t smb_setup2;   /* FID (handle) of pipe (if needed), or priority */
+    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
+};
+
+struct SmbTransactionInterimResp    /* smb_wct = 0 */
+{
+    uint8_t smb_wct;        /* count of 16-bit words that follow */
+    uint16_t smb_bcc;       /* must be 0 */
+};
+
+struct SmbTransactionResp   /* smb_wct = 10 + value of smb_suwcnt */
+{
+    /* Note all subcommands use a setup count of 0 */
+    uint8_t smb_wct;       /* count of 16-bit words that follow */
+    uint16_t smb_tprcnt;   /* total number of parameter bytes being returned */
+    uint16_t smb_tdrcnt;   /* total number of data bytes being returned */
+    uint16_t smb_rsvd;     /* reserved */
+    uint16_t smb_prcnt;    /* number of parameter bytes being returned this buf */
+    uint16_t smb_proff;    /* offset (from start of SMB hdr) to parameter bytes */
+    uint16_t smb_prdisp;   /* byte displacement for these parameter bytes */
+    uint16_t smb_drcnt;    /* number of data bytes being returned this buffer */
+    uint16_t smb_droff;    /* offset (from start of SMB hdr) to data bytes */
+    uint16_t smb_drdisp;   /* byte displacement for these data bytes */
+    uint8_t smb_suwcnt;    /* set up return word count */
+    uint8_t smb_rsvd1;     /* reserved (pad above to word) */
+    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
+};
+
+inline uint16_t SmbTransactionReqSubCom(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_setup1);
+}
+
+inline uint16_t SmbTransactionReqFid(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_setup2);
+}
+
+inline bool SmbTransactionReqDisconnectTid(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_flags) & 0x0001 ? true : false;
+}
+
+inline bool SmbTransactionReqOneWay(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_flags) & 0x0002 ? true : false;
+}
+
+inline uint8_t SmbTransactionReqSetupCnt(const SmbTransactionReq* req)
+{
+    return req->smb_suwcnt;
+}
+
+inline uint16_t SmbTransactionReqTotalDataCnt(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_tdscnt);
+}
+
+inline uint16_t SmbTransactionReqDataCnt(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_dscnt);
+}
+
+inline uint16_t SmbTransactionReqDataOff(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_dsoff);
+}
+
+inline uint16_t SmbTransactionReqTotalParamCnt(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_tpscnt);
+}
+
+inline uint16_t SmbTransactionReqParamCnt(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_pscnt);
+}
+
+inline uint16_t SmbTransactionReqParamOff(const SmbTransactionReq* req)
+{
+    return alignedNtohs(&req->smb_psoff);
+}
+
+inline uint16_t SmbTransactionRespTotalDataCnt(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_tdrcnt);
+}
+
+inline uint16_t SmbTransactionRespDataCnt(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_drcnt);
+}
+
+inline uint16_t SmbTransactionRespDataOff(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_droff);
+}
+
+inline uint16_t SmbTransactionRespDataDisp(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_drdisp);
+}
+
+inline uint16_t SmbTransactionRespTotalParamCnt(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_tprcnt);
+}
+
+inline uint16_t SmbTransactionRespParamCnt(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_prcnt);
+}
+
+inline uint16_t SmbTransactionRespParamOff(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_proff);
+}
+
+inline uint16_t SmbTransactionRespParamDisp(const SmbTransactionResp* resp)
+{
+    return alignedNtohs(&resp->smb_prdisp);
+}
+
+// Flags for TRANS_SET_NMPIPE_STATE parameters
+#define PIPE_STATE_NON_BLOCKING  0x8000
+#define PIPE_STATE_MESSAGE_MODE  0x0100
+
+/********************************************************************
+ * SMB_COM_TRANSACTION2
+ ********************************************************************/
+struct SmbTransaction2Req
+{
+    uint8_t smb_wct;
+    uint16_t smb_total_param_count;
+    uint16_t smb_total_data_count;
+    uint16_t smb_max_param_count;
+    uint16_t smb_max_data_count;
+    uint8_t smb_max_setup_count;
+    uint8_t smb_res;
+    uint16_t smb_flags;
+    uint32_t smb_timeout;
+    uint16_t smb_res2;
+    uint16_t smb_param_count;
+    uint16_t smb_param_offset;
+    uint16_t smb_data_count;
+    uint16_t smb_data_offset;
+    uint8_t smb_setup_count;    /* Should be 1 for all subcommands */
+    uint8_t smb_res3;
+    uint16_t smb_setup;  /* This is the subcommand */
+    uint16_t smb_bcc;
+};
+
+struct SmbTransaction2InterimResp
+{
+    uint8_t smb_wct;
+    uint16_t smb_bcc;
+};
+
+struct SmbTransaction2Resp
+{
+    uint8_t smb_wct;
+    uint16_t smb_total_param_count;
+    uint16_t smb_total_data_count;
+    uint16_t smb_res;
+    uint16_t smb_param_count;
+    uint16_t smb_param_offset;
+    uint16_t smb_param_disp;
+    uint16_t smb_data_count;
+    uint16_t smb_data_offset;
+    uint16_t smb_data_disp;
+    uint16_t smb_setup_count;  /* 0 or 1 word */
+    uint8_t smb_res2;
+};
+
+inline uint16_t SmbTransaction2ReqSubCom(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_setup);
+}
+
+inline uint16_t SmbTransaction2ReqTotalParamCnt(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_total_param_count);
+}
+
+inline uint16_t SmbTransaction2ReqParamCnt(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_param_count);
+}
+
+inline uint16_t SmbTransaction2ReqParamOff(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_param_offset);
+}
+
+inline uint16_t SmbTransaction2ReqTotalDataCnt(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_total_data_count);
+}
+
+inline uint16_t SmbTransaction2ReqDataCnt(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_data_count);
+}
+
+inline uint16_t SmbTransaction2ReqDataOff(const SmbTransaction2Req* req)
+{
+    return alignedNtohs(&req->smb_data_offset);
+}
+
+inline uint8_t SmbTransaction2ReqSetupCnt(const SmbTransaction2Req* req)
+{
+    return req->smb_setup_count;
+}
+
+inline uint16_t SmbTransaction2RespTotalParamCnt(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_total_param_count);
+}
+
+inline uint16_t SmbTransaction2RespParamCnt(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_param_count);
+}
+
+inline uint16_t SmbTransaction2RespParamOff(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_param_offset);
+}
+
+inline uint16_t SmbTransaction2RespParamDisp(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_param_disp);
+}
+
+inline uint16_t SmbTransaction2RespTotalDataCnt(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_total_data_count);
+}
+
+inline uint16_t SmbTransaction2RespDataCnt(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_data_count);
+}
+
+inline uint16_t SmbTransaction2RespDataOff(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_data_offset);
+}
+
+inline uint16_t SmbTransaction2RespDataDisp(const SmbTransaction2Resp* resp)
+{
+    return alignedNtohs(&resp->smb_data_disp);
+}
+
+struct SmbTrans2Open2ReqParams
+{
+    uint16_t Flags;
+    uint16_t AccessMode;
+    uint16_t Reserved1;
+    uint16_t FileAttributes;
+    uint32_t CreationTime;
+    uint16_t OpenMode;
+    uint32_t AllocationSize;
+    uint16_t Reserved[5];
+};
+
+typedef SmbTransaction2Req SmbTrans2Open2Req;
+
+inline uint16_t SmbTrans2Open2ReqAccessMode(const SmbTrans2Open2ReqParams* req)
+{
+    return alignedNtohs(&req->AccessMode);
+}
+
+inline uint16_t SmbTrans2Open2ReqFileAttrs(const SmbTrans2Open2ReqParams* req)
+{
+    return alignedNtohs(&req->FileAttributes);
+}
+
+inline uint16_t SmbTrans2Open2ReqOpenMode(const SmbTrans2Open2ReqParams* req)
+{
+    return alignedNtohs(&req->OpenMode);
+}
+
+inline uint32_t SmbTrans2Open2ReqAllocSize(const SmbTrans2Open2ReqParams* req)
+{
+    return alignedNtohl(&req->AllocationSize);
+}
+
+struct SmbTrans2Open2RespParams
+{
+    uint16_t smb_fid;
+    uint16_t file_attributes;
+    uint32_t creation_time;
+    uint32_t file_data_size;
+    uint16_t access_mode;
+    uint16_t resource_type;
+    uint16_t nm_pipe_status;
+    uint16_t action_taken;
+    uint32_t reserved;
+    uint16_t extended_attribute_error_offset;
+    uint32_t extended_attribute_length;
+};
+
+inline uint16_t SmbTrans2Open2RespFid(const SmbTrans2Open2RespParams* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+inline uint16_t SmbTrans2Open2RespFileAttrs(const SmbTrans2Open2RespParams* resp)
+{
+    return alignedNtohs(&resp->file_attributes);
+}
+
+inline uint32_t SmbTrans2Open2RespFileDataSize(const SmbTrans2Open2RespParams* resp)
+{
+    return alignedNtohl(&resp->file_data_size);
+}
+
+inline uint16_t SmbTrans2Open2RespResourceType(const SmbTrans2Open2RespParams* resp)
+{
+    return alignedNtohs(&resp->resource_type);
+}
+
+inline uint16_t SmbTrans2Open2RespActionTaken(const SmbTrans2Open2RespParams* resp)
+{
+    return alignedNtohs(&resp->action_taken);
+}
+
+struct SmbTrans2Open2Resp
+{
+    uint8_t smb_wct;
+    uint16_t smb_total_param_count;
+    uint16_t smb_total_data_count;
+    uint16_t smb_res;
+    uint16_t smb_param_count;
+    uint16_t smb_param_offset;
+    uint16_t smb_param_disp;
+    uint16_t smb_data_count;
+    uint16_t smb_data_offset;
+    uint16_t smb_data_disp;
+    uint16_t smb_setup_count;  /* 0 */
+    uint8_t smb_res2;
+    uint16_t smb_bcc;
+};
+
+// See MS-CIFS Section 2.2.2.3.3
+#define SMB_INFO_STANDARD               0x0001
+#define SMB_INFO_QUERY_EA_SIZE          0x0002
+#define SMB_INFO_QUERY_EAS_FROM_LIST    0x0003
+#define SMB_INFO_QUERY_ALL_EAS          0x0004
+#define SMB_INFO_IS_NAME_VALID          0x0006
+#define SMB_QUERY_FILE_BASIC_INFO       0x0101
+#define SMB_QUERY_FILE_STANDARD_INFO    0x0102
+#define SMB_QUERY_FILE_EA_INFO          0x0103
+#define SMB_QUERY_FILE_NAME_INFO        0x0104
+#define SMB_QUERY_FILE_ALL_INFO         0x0107
+#define SMB_QUERY_FILE_ALT_NAME_INFO    0x0108
+#define SMB_QUERY_FILE_STREAM_INFO      0x0109
+#define SMB_QUERY_FILE_COMPRESSION_INFO 0x010b
+
+// See MS-SMB Section 2.2.2.3.5
+// For added value, see below from MS-FSCC
+#define SMB_INFO_PASSTHROUGH  0x03e8
+#define SMB_INFO_PT_FILE_STANDARD_INFO  SMB_INFO_PASSTHROUGH+5
+#define SMB_INFO_PT_FILE_ALL_INFO       SMB_INFO_PASSTHROUGH+18
+#define SMB_INFO_PT_FILE_STREAM_INFO    SMB_INFO_PASSTHROUGH+22
+#define SMB_INFO_PT_NETWORK_OPEN_INFO   SMB_INFO_PASSTHROUGH+34
+
+struct SmbTrans2QueryFileInfoReqParams
+{
+    uint16_t fid;
+    uint16_t information_level;
+};
+
+inline uint16_t SmbTrans2QueryFileInfoReqFid(const SmbTrans2QueryFileInfoReqParams* req)
+{
+    return alignedNtohs(&req->fid);
+}
+
+inline uint16_t SmbTrans2QueryFileInfoReqInfoLevel(const SmbTrans2QueryFileInfoReqParams* req)
+{
+    return alignedNtohs(&req->information_level);
+}
+
+struct SmbQueryInfoStandard
+{
+    uint16_t CreationDate;
+    uint16_t CreationTime;
+    uint16_t LastAccessDate;
+    uint16_t LastAccessTime;
+    uint16_t LastWriteDate;
+    uint16_t LastWriteTime;
+    uint32_t FileDataSize;
+    uint32_t AllocationSize;
+    uint16_t Attributes;
+};
+
+inline uint32_t SmbQueryInfoStandardFileDataSize(const SmbQueryInfoStandard* q)
+{
+    return alignedNtohl(&q->FileDataSize);
+}
+
+struct SmbQueryInfoQueryEaSize
+{
+    uint16_t CreationDate;
+    uint16_t CreationTime;
+    uint16_t LastAccessDate;
+    uint16_t LastAccessTime;
+    uint16_t LastWriteDate;
+    uint16_t LastWriteTime;
+    uint32_t FileDataSize;
+    uint32_t AllocationSize;
+    uint16_t Attributes;
+    uint32_t EaSize;
+};
+
+inline uint32_t SmbQueryInfoQueryEaSizeFileDataSize(const SmbQueryInfoQueryEaSize* q)
+{
+    return alignedNtohl(&q->FileDataSize);
+}
+
+struct SmbQueryFileStandardInfo
+{
+    uint64_t AllocationSize;
+    uint64_t EndOfFile;
+    uint32_t NumberOfLinks;
+    uint8_t DeletePending;
+    uint8_t Directory;
+    uint16_t Reserved;
+};
+
+inline uint64_t SmbQueryFileStandardInfoEndOfFile(const SmbQueryFileStandardInfo* q)
+{
+    return alignedNtohq(&q->EndOfFile);
+}
+
+struct SmbQueryFileAllInfo
+{
+    // Basic Info
+    uint64_t CreationTime;
+    uint64_t LastAccessTime;
+    uint64_t LastWriteTime;
+    uint64_t LastChangeTime;
+    uint32_t ExtFileAttributes;
+    uint32_t Reserved1;
+    uint64_t AllocationSize;
+    uint64_t EndOfFile;
+    uint32_t NumberOfLinks;
+    uint8_t DeletePending;
+    uint8_t Directory;
+    uint16_t Reserved2;
+    uint32_t EaSize;
+    uint32_t FileNameLength;
+};
+
+inline uint64_t SmbQueryFileAllInfoEndOfFile(const SmbQueryFileAllInfo* q)
+{
+    return alignedNtohq(&q->EndOfFile);
+}
+
+struct SmbQueryPTFileAllInfo
+{
+    // Basic Info
+    uint64_t CreationTime;
+    uint64_t LastAccessTime;
+    uint64_t LastWriteTime;
+    uint64_t LastChangeTime;
+    uint32_t ExtFileAttributes;
+    uint32_t Reserved1;
+
+    // Standard Info
+    uint64_t AllocationSize;
+    uint64_t EndOfFile;
+    uint32_t NumberOfLinks;
+    uint8_t DeletePending;
+    uint8_t Directory;
+    uint16_t Reserved2;
+
+    // Internal Info
+    uint64_t IndexNumber;
+
+    // EA Info
+    uint32_t EaSize;
+
+    // Access Info
+    uint32_t AccessFlags;
+
+    // Position Info
+    uint64_t CurrentByteOffset;
+
+    // Mode Info
+    uint32_t Mode;
+
+    // Alignment Info
+    uint32_t AlignmentRequirement;
+
+    // Name Info
+    uint32_t FileNameLength;
+};
+
+inline uint64_t SmbQueryPTFileAllInfoEndOfFile(const SmbQueryPTFileAllInfo* q)
+{
+    return alignedNtohq(&q->EndOfFile);
+}
+
+struct SmbQueryPTNetworkOpenInfo
+{
+    uint64_t CreationTime;
+    uint64_t LastAccessTime;
+    uint64_t LastWriteTime;
+    uint64_t LastChangeTime;
+    uint64_t AllocationSize;
+    uint64_t EndOfFile;
+    uint32_t FileAttributes;
+    uint32_t Reserved;
+};
+
+inline uint64_t SmbQueryPTNetworkOpenInfoEndOfFile(const SmbQueryPTNetworkOpenInfo* q)
+{
+    return alignedNtohq(&q->EndOfFile);
+}
+
+struct SmbQueryPTFileStreamInfo
+{
+    uint32_t NextEntryOffset;
+    uint32_t StreamNameLength;
+    uint64_t StreamSize;
+    uint64_t StreamAllocationSize;
+};
+
+inline uint64_t SmbQueryPTFileStreamInfoStreamSize(const SmbQueryPTFileStreamInfo* q)
+{
+    return alignedNtohq(&q->StreamSize);
+}
+
+struct SmbTrans2QueryFileInformationResp
+{
+    uint8_t smb_wct;
+    uint16_t smb_total_param_count;
+    uint16_t smb_total_data_count;
+    uint16_t smb_res;
+    uint16_t smb_param_count;
+    uint16_t smb_param_offset;
+    uint16_t smb_param_disp;
+    uint16_t smb_data_count;
+    uint16_t smb_data_offset;
+    uint16_t smb_data_disp;
+    uint16_t smb_setup_count;  /* 0 */
+    uint8_t smb_res2;
+    uint16_t smb_bcc;
+};
+
+#define SMB_INFO_SET_EAS               0x0002
+#define SMB_SET_FILE_BASIC_INFO        0x0101
+#define SMB_SET_FILE_DISPOSITION_INFO  0x0102
+#define SMB_SET_FILE_ALLOCATION_INFO   0x0103
+#define SMB_SET_FILE_END_OF_FILE_INFO  0x0104
+
+// For added value, see above File Information Classes
+#define SMB_INFO_PT_SET_FILE_BASIC_FILE_INFO   SMB_INFO_PASSTHROUGH+4
+#define SMB_INFO_PT_SET_FILE_END_OF_FILE_INFO  SMB_INFO_PASSTHROUGH+20
+
+struct SmbTrans2SetFileInfoReqParams
+{
+    uint16_t fid;
+    uint16_t information_level;
+    uint16_t reserved;
+};
+
+inline uint16_t SmbTrans2SetFileInfoReqFid(const SmbTrans2SetFileInfoReqParams* req)
+{
+    return alignedNtohs(&req->fid);
+}
+
+inline uint16_t SmbTrans2SetFileInfoReqInfoLevel(const SmbTrans2SetFileInfoReqParams* req)
+{
+    return alignedNtohs(&req->information_level);
+}
+
+inline bool SmbSetFileInfoEndOfFile(const uint16_t info_level)
+{
+    return ((info_level == SMB_SET_FILE_END_OF_FILE_INFO)
+           || (info_level == SMB_INFO_PT_SET_FILE_END_OF_FILE_INFO));
+}
+
+struct SmbSetFileBasicInfo
+{
+    uint64_t CreationTime;
+    uint64_t LastAccessTime;
+    uint64_t LastWriteTime;
+    uint64_t ChangeTime;
+    uint32_t ExtFileAttributes;
+    uint32_t Reserved;
+};
+
+inline uint32_t SmbSetFileInfoExtFileAttrs(const SmbSetFileBasicInfo* info)
+{
+    return alignedNtohl(&info->ExtFileAttributes);
+}
+
+inline bool SmbSetFileInfoSetFileBasicInfo(const uint16_t info_level)
+{
+    return ((info_level == SMB_SET_FILE_BASIC_INFO)
+           || (info_level == SMB_INFO_PT_SET_FILE_BASIC_FILE_INFO));
+}
+
+/********************************************************************
+ * SMB_COM_NT_TRANSACT
+ ********************************************************************/
+#define SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY     0x00000004
+
+struct SmbNtTransactReq
+{
+    uint8_t smb_wct;
+    uint8_t smb_max_setup_count;
+    uint16_t smb_res;
+    uint32_t smb_total_param_count;
+    uint32_t smb_total_data_count;
+    uint32_t smb_max_param_count;
+    uint32_t smb_max_data_count;
+    uint32_t smb_param_count;
+    uint32_t smb_param_offset;
+    uint32_t smb_data_count;
+    uint32_t smb_data_offset;
+    uint8_t smb_setup_count;
+    uint16_t smb_function;
+};
+
+struct SmbNtTransactInterimResp
+{
+    uint8_t smb_wct;
+    uint16_t smb_bcc;
+};
+
+struct SmbNtTransactResp
+{
+    uint8_t smb_wct;
+    uint8_t smb_res[3];
+    uint32_t smb_total_param_count;
+    uint32_t smb_total_data_count;
+    uint32_t smb_param_count;
+    uint32_t smb_param_offset;
+    uint32_t smb_param_disp;
+    uint32_t smb_data_count;
+    uint32_t smb_data_offset;
+    uint32_t smb_data_disp;
+    uint8_t smb_setup_count;
+};
+
+inline uint16_t SmbNtTransactReqSubCom(const SmbNtTransactReq* req)
+{
+    return alignedNtohs(&req->smb_function);
+}
+
+inline uint8_t SmbNtTransactReqSetupCnt(const SmbNtTransactReq* req)
+{
+    return req->smb_setup_count;
+}
+
+inline uint32_t SmbNtTransactReqTotalParamCnt(const SmbNtTransactReq* req)
+{
+    return alignedNtohl(&req->smb_total_param_count);
+}
+
+inline uint32_t SmbNtTransactReqParamCnt(const SmbNtTransactReq* req)
+{
+    return alignedNtohl(&req->smb_param_count);
+}
+
+inline uint32_t SmbNtTransactReqParamOff(const SmbNtTransactReq* req)
+{
+    return alignedNtohl(&req->smb_param_offset);
+}
+
+inline uint32_t SmbNtTransactReqTotalDataCnt(const SmbNtTransactReq* req)
+{
+    return alignedNtohl(&req->smb_total_data_count);
+}
+
+inline uint32_t SmbNtTransactReqDataCnt(const SmbNtTransactReq* req)
+{
+    return alignedNtohl(&req->smb_data_count);
+}
+
+inline uint32_t SmbNtTransactReqDataOff(const SmbNtTransactReq* req)
+{
+    return alignedNtohl(&req->smb_data_offset);
+}
+
+inline uint32_t SmbNtTransactRespTotalParamCnt(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_total_param_count);
+}
+
+inline uint32_t SmbNtTransactRespParamCnt(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_param_count);
+}
+
+inline uint32_t SmbNtTransactRespParamOff(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_param_offset);
+}
+
+inline uint32_t SmbNtTransactRespParamDisp(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_param_disp);
+}
+
+inline uint32_t SmbNtTransactRespTotalDataCnt(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_total_data_count);
+}
+
+inline uint32_t SmbNtTransactRespDataCnt(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_data_count);
+}
+
+inline uint32_t SmbNtTransactRespDataOff(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_data_offset);
+}
+
+inline uint32_t SmbNtTransactRespDataDisp(const SmbNtTransactResp* resp)
+{
+    return alignedNtohl(&resp->smb_data_disp);
+}
+
+struct SmbNtTransactCreateReqParams
+{
+    uint32_t flags;
+    uint32_t root_dir_fid;
+    uint32_t desired_access;
+    uint64_t allocation_size;
+    uint32_t ext_file_attributes;
+    uint32_t share_access;
+    uint32_t create_disposition;
+    uint32_t create_options;
+    uint32_t security_descriptor_length;
+    uint32_t ea_length;
+    uint32_t name_length;
+    uint32_t impersonation_level;
+    uint8_t security_flags;
+};
+
+inline uint64_t SmbNtTransactCreateReqAllocSize(const SmbNtTransactCreateReqParams* req)
+{
+    return alignedNtohq(&req->allocation_size);
+}
+
+inline uint32_t SmbNtTransactCreateReqFileNameLength(const SmbNtTransactCreateReqParams* req)
+{
+    return alignedNtohl(&req->name_length);
+}
+
+inline uint32_t SmbNtTransactCreateReqFileAttrs(const SmbNtTransactCreateReqParams* req)
+{
+    return alignedNtohl(&req->ext_file_attributes);
+}
+
+inline bool SmbNtTransactCreateReqSequentialOnly(const SmbNtTransactCreateReqParams* req)
+{
+    return (alignedNtohl(&req->create_options) & SMB_CREATE_OPTIONS__FILE_SEQUENTIAL_ONLY);
+}
+
+struct SmbNtTransactCreateReq
+{
+    uint8_t smb_wct;
+    uint8_t smb_max_setup_count;
+    uint16_t smb_res;
+    uint32_t smb_total_param_count;
+    uint32_t smb_total_data_count;
+    uint32_t smb_max_param_count;
+    uint32_t smb_max_data_count;
+    uint32_t smb_param_count;
+    uint32_t smb_param_offset;
+    uint32_t smb_data_count;
+    uint32_t smb_data_offset;
+    uint8_t smb_setup_count;    /* Must be 0x00 */
+    uint16_t smb_function;      /* NT_TRANSACT_CREATE */
+    uint16_t smb_bcc;
+};
+
+struct SmbNtTransactCreateRespParams
+{
+    uint8_t op_lock_level;
+    uint8_t reserved;
+    uint16_t smb_fid;
+    uint32_t create_action;
+    uint32_t ea_error_offset;
+    uint64_t creation_time;
+    uint64_t last_access_time;
+    uint64_t last_write_time;
+    uint64_t last_change_time;
+    uint32_t ext_file_attributes;
+    uint64_t allocation_size;
+    uint64_t end_of_file;
+    uint16_t resource_type;
+    uint16_t nm_pipe_status;
+    uint8_t directory;
+};
+
+inline uint16_t SmbNtTransactCreateRespFid(const SmbNtTransactCreateRespParams* resp)
+{
+    return alignedNtohs(&resp->smb_fid);
+}
+
+inline uint32_t SmbNtTransactCreateRespCreateAction(const SmbNtTransactCreateRespParams* resp)
+{
+    return alignedNtohl(&resp->create_action);
+}
+
+inline uint64_t SmbNtTransactCreateRespEndOfFile(const SmbNtTransactCreateRespParams* resp)
+{
+    return alignedNtohq(&resp->end_of_file);
+}
+
+inline uint16_t SmbNtTransactCreateRespResourceType(const SmbNtTransactCreateRespParams* resp)
+{
+    return alignedNtohs(&resp->resource_type);
+}
+
+inline bool SmbNtTransactCreateRespDirectory(const SmbNtTransactCreateRespParams* resp)
+{
+    return (resp->directory ? true : false);
+}
+
+struct SmbNtTransactCreateResp
+{
+    uint8_t smb_wct;
+    uint8_t smb_res[3];
+    uint32_t smb_total_param_count;
+    uint32_t smb_total_data_count;
+    uint32_t smb_param_count;
+    uint32_t smb_param_offset;
+    uint32_t smb_param_disp;
+    uint32_t smb_data_count;
+    uint32_t smb_data_offset;
+    uint32_t smb_data_disp;
+    uint8_t smb_setup_count;    /* 0x00 */
+    uint16_t smb_bcc;
+};
+
+/********************************************************************
+ * SMB_COM_TRANSACTION_SECONDARY
+ *  Continuation command for SMB_COM_TRANSACTION requests if all
+ *  data wasn't sent.
+ ********************************************************************/
+struct SmbTransactionSecondaryReq   /* smb_wct = 8 */
+{
+    uint8_t smb_wct;       /* count of 16-bit words that follow */
+    uint16_t smb_tpscnt;   /* total number of parameter bytes being sent */
+    uint16_t smb_tdscnt;   /* total number of data bytes being sent */
+    uint16_t smb_pscnt;    /* number of parameter bytes being sent this buffer */
+    uint16_t smb_psoff;    /* offset (from start of SMB hdr) to parameter bytes */
+    uint16_t smb_psdisp;   /* byte displacement for these parameter bytes */
+    uint16_t smb_dscnt;    /* number of data bytes being sent this buffer */
+    uint16_t smb_dsoff;    /* offset (from start of SMB hdr) to data bytes */
+    uint16_t smb_dsdisp;   /* byte displacement for these data bytes */
+    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
+};
+
+inline uint16_t SmbTransactionSecondaryReqTotalDataCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_tdscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqDataCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_dscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqDataOff(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_dsoff);
+}
+
+inline uint16_t SmbTransactionSecondaryReqDataDisp(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_dsdisp);
+}
+
+inline uint16_t SmbTransactionSecondaryReqTotalParamCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_tpscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqParamCnt(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_pscnt);
+}
+
+inline uint16_t SmbTransactionSecondaryReqParamOff(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_psoff);
+}
+
+inline uint16_t SmbTransactionSecondaryReqParamDisp(const SmbTransactionSecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_psdisp);
+}
+
+/********************************************************************
+ * SMB_COM_TRANSACTION2_SECONDARY
+ *  Continuation command for SMB_COM_TRANSACTION2 requests if all
+ *  data wasn't sent.
+ ********************************************************************/
+struct SmbTransaction2SecondaryReq
+{
+    uint8_t smb_wct;
+    uint16_t smb_total_param_count;
+    uint16_t smb_total_data_count;
+    uint16_t smb_param_count;
+    uint16_t smb_param_offset;
+    uint16_t smb_param_disp;
+    uint16_t smb_data_count;
+    uint16_t smb_data_offset;
+    uint16_t smb_data_disp;
+    uint16_t smb_fid;
+    uint16_t smb_bcc;
+};
+
+inline uint16_t SmbTransaction2SecondaryReqTotalParamCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_total_param_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqParamCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_param_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqParamOff(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_param_offset);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqParamDisp(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_param_disp);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqTotalDataCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_total_data_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqDataCnt(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_data_count);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqDataOff(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_data_offset);
+}
+
+inline uint16_t SmbTransaction2SecondaryReqDataDisp(const SmbTransaction2SecondaryReq* req)
+{
+    return alignedNtohs(&req->smb_data_disp);
+}
+
+/********************************************************************
+ * SMB_COM_NT_TRANSACT_SECONDARY
+ ********************************************************************/
+struct SmbNtTransactSecondaryReq
+{
+    uint8_t smb_wct;
+    uint8_t smb_res[3];
+    uint32_t smb_total_param_count;
+    uint32_t smb_total_data_count;
+    uint32_t smb_param_count;
+    uint32_t smb_param_offset;
+    uint32_t smb_param_disp;
+    uint32_t smb_data_count;
+    uint32_t smb_data_offset;
+    uint32_t smb_data_disp;
+    uint8_t smb_res2;
+};
+
+inline uint32_t SmbNtTransactSecondaryReqTotalParamCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_total_param_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqParamCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_param_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqParamOff(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_param_offset);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqParamDisp(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_param_disp);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqTotalDataCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_total_data_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqDataCnt(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_data_count);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqDataOff(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_data_offset);
+}
+
+inline uint32_t SmbNtTransactSecondaryReqDataDisp(const SmbNtTransactSecondaryReq* req)
+{
+    return alignedNtohl(&req->smb_data_disp);
+}
+
+/********************************************************************
+ * SMB_COM_READ_RAW
+ ********************************************************************/
+struct SmbReadRawReq   /* smb_wct = 8 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint16_t smb_fid;        /* file handle */
+    uint32_t smb_offset;     /* offset in file to begin read */
+    uint16_t smb_maxcnt;     /* max number of bytes to return (max 65,535) */
+    uint16_t smb_mincnt;     /* min number of bytes to return (normally 0) */
+    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
+    uint16_t smb_rsvd;       /* reserved */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+struct SmbReadRawExtReq   /* smb_wct = 10 */
+{
+    uint8_t smb_wct;         /* count of 16-bit words that follow */
+    uint16_t smb_fid;        /* file handle */
+    uint32_t smb_offset;     /* offset in file to begin read */
+    uint16_t smb_maxcnt;     /* max number of bytes to return (max 65,535) */
+    uint16_t smb_mincnt;     /* min number of bytes to return (normally 0) */
+    uint32_t smb_timeout;    /* number of milliseconds to wait for completion */
+    uint16_t smb_rsvd;       /* reserved */
+    uint32_t smb_off_high;   /* high offset in file to begin write */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+/* Read Raw response is raw data wrapped in NetBIOS header */
+
+inline uint16_t SmbReadRawReqFid(const SmbReadRawReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint64_t SmbReadRawReqOffset(const SmbReadRawExtReq* req)
+{
+    if (req->smb_wct == 8)
+        return (uint64_t)alignedNtohl(&req->smb_offset);
+    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
+        &req->smb_offset);
+}
+
+/********************************************************************
+ * SMB_COM_WRITE_RAW
+ ********************************************************************/
+struct SmbWriteRawReq
+{
+    uint8_t smb_wct;       /* value = 12 */
+    uint16_t smb_fid;      /* file handle */
+    uint16_t smb_tcount;   /* total bytes (including this buf, 65,535 max ) */
+    uint16_t smb_rsvd;     /* reserved */
+    uint32_t smb_offset;   /* offset in file to begin write */
+    uint32_t smb_timeout;  /* number of milliseconds to wait for completion */
+    uint16_t smb_wmode;    /* write mode:
+                              bit0 - complete write to disk and send final result response
+                              bit1 - return smb_remaining (pipes/devices only) */
+    uint32_t smb_rsvd2;    /* reserved */
+    uint16_t smb_dsize;    /* number of data bytes this buffer (min value = 0) */
+    uint16_t smb_doff;     /* offset (from start of SMB hdr) to data bytes */
+    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
+};
+
+struct SmbWriteRawExtReq
+{
+    uint8_t smb_wct;       /* value = 14 */
+    uint16_t smb_fid;      /* file handle */
+    uint16_t smb_tcount;   /* total bytes (including this buf, 65,535 max ) */
+    uint16_t smb_rsvd;     /* reserved */
+    uint32_t smb_offset;   /* offset in file to begin write */
+    uint32_t smb_timeout;  /* number of milliseconds to wait for completion */
+    uint16_t smb_wmode;    /* write mode:
+                              bit0 - complete write to disk and send final result response
+                              bit1 - return smb_remaining (pipes/devices only) */
+    uint32_t smb_rsvd2;    /* reserved */
+    uint16_t smb_dsize;    /* number of data bytes this buffer (min value = 0) */
+    uint16_t smb_doff;     /* offset (from start of SMB hdr) to data bytes */
+    uint32_t smb_off_high; /* high offset in file to begin write */
+    uint16_t smb_bcc;      /* total bytes (including pad bytes) following */
+};
+
+struct SmbWriteRawInterimResp
+{
+    uint8_t smb_wct;         /* value = 1 */
+    uint16_t smb_remaining;  /* bytes remaining to be read (pipes/devices only) */
+    uint16_t smb_bcc;        /* value = 0 */
+};
+
+inline uint16_t SmbWriteRawReqTotalCount(const SmbWriteRawReq* req)
+{
+    return alignedNtohs(&req->smb_tcount);
+}
+
+inline bool SmbWriteRawReqWriteThrough(const SmbWriteRawReq* req)
+{
+    return alignedNtohs(&req->smb_wmode) & 0x0001;
+}
+
+inline uint16_t SmbWriteRawReqFid(const SmbWriteRawReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint16_t SmbWriteRawReqDataOff(const SmbWriteRawReq* req)
+{
+    return alignedNtohs(&req->smb_doff);
+}
+
+inline uint16_t SmbWriteRawReqDataCnt(const SmbWriteRawReq* req)
+{
+    return alignedNtohs(&req->smb_dsize);
+}
+
+inline uint64_t SmbWriteRawReqOffset(const SmbWriteRawExtReq* req)
+{
+    if (req->smb_wct == 12)
+        return (uint64_t)alignedNtohl(&req->smb_offset);
+    return (uint64_t)alignedNtohl(&req->smb_off_high) << 32 | (uint64_t)alignedNtohl(
+        &req->smb_offset);
+}
+
+inline uint16_t SmbWriteRawInterimRespRemaining(const SmbWriteRawInterimResp* resp)
+{
+    return alignedNtohs(&resp->smb_remaining);
+}
+
+/********************************************************************
+ * SMB_COM_WRITE_COMPLETE - final response to an SMB_COM_WRITE_RAW
+ ********************************************************************/
+struct SmbWriteCompleteResp
+{
+    uint8_t smb_wct;     /* value = 1 */
+    uint16_t smb_count;  /* total number of bytes written */
+    uint16_t smb_bcc;    /* value = 0 */
+};
+
+inline uint16_t SmbWriteCompleteRespCount(const SmbWriteCompleteResp* resp)
+{
+    return alignedNtohs(&resp->smb_count);
+}
+
+/********************************************************************
+ * SMB_COM_WRITE_AND_CLOSE
+ ********************************************************************/
+struct SmbWriteAndCloseReq   /* smb_wct = 6 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;     /* file handle (close after write) */
+    uint16_t smb_count;   /* number of bytes to write */
+    uint32_t smb_offset;  /* offset in file to begin write */
+    uint32_t smb_mtime;   /* modification time */
+    uint16_t smb_bcc;     /* 1 (for pad) + value of smb_count */
+};
+
+struct SmbWriteAndCloseExtReq   /* smb_wct = 12 */
+{
+    uint8_t smb_wct;      /* count of 16-bit words that follow */
+    uint16_t smb_fid;     /* file handle (close after write) */
+    uint16_t smb_count;   /* number of bytes to write */
+    uint32_t smb_offset;  /* offset in file to begin write */
+    uint32_t smb_mtime;   /* modification time */
+    uint32_t smb_rsvd1;   /* Optional */
+    uint32_t smb_rsvd2;   /* Optional */
+    uint32_t smb_rsvd3;   /* Optional */
+    uint16_t smb_bcc;     /* 1 (for pad) + value of smb_count */
+};
+
+struct SmbWriteAndCloseResp   /* smb_wct = 1 */
+{
+    uint8_t smb_wct;     /* count of 16-bit words that follow */
+    uint16_t smb_count;  /* number of bytes written */
+    uint16_t smb_bcc;    /* must be 0 */
+};
+
+inline uint16_t SmbWriteAndCloseReqFid(const SmbWriteAndCloseReq* req)
+{
+    return alignedNtohs(&req->smb_fid);
+}
+
+inline uint16_t SmbWriteAndCloseReqCount(const SmbWriteAndCloseReq* req)
+{
+    return alignedNtohs(&req->smb_count);
+}
+
+inline uint32_t SmbWriteAndCloseReqOffset(const SmbWriteAndCloseReq* req)
+{
+    return alignedNtohl(&req->smb_offset);
+}
+
+inline uint16_t SmbWriteAndCloseRespCount(const SmbWriteAndCloseResp* resp)
+{
+    return alignedNtohs(&resp->smb_count);
+}
+
+#pragma pack()
+
+void DCE2_SmbInitGlobals();
+void DCE2_SmbProcess(struct DCE2_SmbSsnData*);
+DCE2_SmbSsnData* dce2_handle_smb_session(struct Packet*, struct dce2SmbProtoConf*);
+
+#endif
+