]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust: Add DCERPC parser
authorShivani Bhardwaj <shivanib134@gmail.com>
Tue, 21 Apr 2020 08:55:43 +0000 (14:25 +0530)
committerVictor Julien <victor@inliniac.net>
Tue, 19 May 2020 17:58:12 +0000 (19:58 +0200)
This parser rewrites the DCE/RPC protocol implementation of Suricata
in Rust. More tests have been added to improve the coverage and some
fixes have been made to the tests already written in C. Most of the
valid tests from C have been imported to Rust.

File anatomy

src/dcerpc.rs
This file contains the implementation of single transactions in DCE/RPC
over TCP. It takes care of REQUEST, RESPONSE, BIND and BINDACK business
logic before and after the data parsing. DCERPCState holds the state
corresponding to a particular transaction and handles all important
aspects. It also defines any common structures and constants required
for DCE/RPC parsing irrespective of the carrier protocol.

src/dcerpc_udp.rs
This file contains the implementation of single transactions in DCE/RPC
over UDP. It takes care of REQUEST and RESPONSE parsing. It borrows the
Request and Response structs from src/dcerpc.rs.

src/detect.rs
This file contains the implementation of dce_iface and opnum detect
keywords. Both the parsing and the matching is taken care of by
functions in this file. Tests have been rewritten with the test data
from C.

src/parser.rs
This file contains all the nom parsers written for DCERPCRequest,
DCERPCResponse, DCERPCBind, DCERPCBindAck, DCERPCHeader, DCERPCHdrUdp.
It also implements functions to assemble and convert UUIDs. All the
fields have their endianness defined unless its an 8bit field or an
unusable one, then it's little endian but it won't make any difference.

src/mod.rs
This file contains all the modules of dcerpc folder which should be
taken into account during compilation.

Function calls

This is a State-wise implementation of the protocol for single
transaction only i.e. a valid state object is required to parse any
record. Function calls start with the app layer parser in C which
detects the application layer protocol to be DCE/RPC and calls the
appropriate functions in C which in turn make a call to these functions
in Rust using FFI. All the necessary information is passed from C to the
parsers and handlers in Rust.

Implementation

When a batch of input comes in, there is an analysis of whether the
input header and the direction is appropriate. Next check is about the
size of fragment. If it is as defined by the header, process goes
through else the data is buffered and more data is awaited. After this,
type of record as indicated by the header is checked. A call to the
appropriate handler is made. After the handling, State is updated with
the latest information about whatever record came in.
AppLayerResult::ok() is returned in case all went well else
AppLayerResult::err() is returned indicating something went wrong.

rust/src/dcerpc/dcerpc.rs [new file with mode: 0644]
rust/src/dcerpc/dcerpc_udp.rs [new file with mode: 0644]
rust/src/dcerpc/detect.rs [new file with mode: 0644]
rust/src/dcerpc/mod.rs [new file with mode: 0644]
rust/src/dcerpc/parser.rs [new file with mode: 0644]

diff --git a/rust/src/dcerpc/dcerpc.rs b/rust/src/dcerpc/dcerpc.rs
new file mode 100644 (file)
index 0000000..e414be1
--- /dev/null
@@ -0,0 +1,2124 @@
+/* Copyright (C) 2020 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use std::mem::transmute;
+
+use crate::applayer::AppLayerResult;
+use crate::core;
+use crate::dcerpc::parser;
+use crate::log::*;
+use nom::error::ErrorKind;
+use nom::number::Endianness;
+use std::cmp;
+
+// Constant DCERPC UDP Header length
+pub const DCERPC_HDR_LEN: u16 = 16;
+// FIRST flag set on the packet
+pub const DCERPC_UUID_ENTRY_FLAG_FF: u16 = 0x0001;
+
+// Value to indicate first fragment
+pub const PFC_FIRST_FRAG: u8 = 0x01;
+// Value to indicate last fragment
+pub const PFC_LAST_FRAG: u8 = 0x02;
+// Cancel was pending at sender
+pub const PFC_PENDING_CANCEL: u8 = 0x04;
+pub const PFC_RESERVED_1: u8 = 0x08;
+// supports concurrent multiplexing of a single connection.
+pub const PFC_CONC_MPX: u8 = 0x10;
+// only meaningful on `fault' packet; if true, guaranteed
+//  call did not execute.
+pub const PFC_DID_NOT_EXECUTE: u8 = 0x20;
+// `maybe' call semantics requested
+pub const PFC_MAYBE: u8 = 0x40;
+// if true, a non-nil object UUID was specified in the handle, and
+//  is present in the optional object field. If false, the object field
+// is omitted.
+pub const PFC_OBJECT_UUID: u8 = 0x80;
+
+pub const REASON_NOT_SPECIFIED: u8 = 0;
+pub const TEMPORARY_CONGESTION: u8 = 1;
+pub const LOCAL_LIMIT_EXCEEDED: u8 = 2;
+pub const CALLED_PADDR_UNKNOWN: u8 = 3; /* not used */
+pub const PROTOCOL_VERSION_NOT_SUPPORTED: u8 = 4;
+pub const DEFAULT_CONTEXT_NOT_SUPPORTED: u8 = 5; /* not used */
+pub const USER_DATA_NOT_READABLE: u8 = 6; /* not used */
+pub const NO_PSAP_AVAILABLE: u8 = 7; /* not used */
+
+// DCERPC Header packet types
+pub const DCERPC_TYPE_REQUEST: u8 = 0;
+pub const DCERPC_TYPE_PING: u8 = 1;
+pub const DCERPC_TYPE_RESPONSE: u8 = 2;
+pub const DCERPC_TYPE_FAULT: u8 = 3;
+pub const DCERPC_TYPE_WORKING: u8 = 4;
+pub const DCERPC_TYPE_NOCALL: u8 = 5;
+pub const DCERPC_TYPE_REJECT: u8 = 6;
+pub const DCERPC_TYPE_ACK: u8 = 7;
+pub const DCERPC_TYPE_CL_CANCEL: u8 = 8;
+pub const DCERPC_TYPE_FACK: u8 = 9;
+pub const DCERPC_TYPE_CANCEL_ACK: u8 = 10;
+pub const DCERPC_TYPE_BIND: u8 = 11;
+pub const DCERPC_TYPE_BINDACK: u8 = 12;
+pub const DCERPC_TYPE_BINDNAK: u8 = 13;
+pub const DCERPC_TYPE_ALTER_CONTEXT: u8 = 14;
+pub const DCERPC_TYPE_ALTER_CONTEXT_RESP: u8 = 15;
+pub const DCERPC_TYPE_AUTH3: u8 = 16;
+pub const DCERPC_TYPE_SHUTDOWN: u8 = 17;
+pub const DCERPC_TYPE_CO_CANCEL: u8 = 18;
+pub const DCERPC_TYPE_ORPHANED: u8 = 19;
+pub const DCERPC_TYPE_RTS: u8 = 20;
+
+pub fn dcerpc_type_string(t: u8) -> String {
+    match t {
+        DCERPC_TYPE_REQUEST => "REQUEST",
+        DCERPC_TYPE_PING => "PING",
+        DCERPC_TYPE_RESPONSE => "RESPONSE",
+        DCERPC_TYPE_FAULT => "FAULT",
+        DCERPC_TYPE_WORKING => "WORKING",
+        DCERPC_TYPE_NOCALL => "NOCALL",
+        DCERPC_TYPE_REJECT => "REJECT",
+        DCERPC_TYPE_ACK => "ACK",
+        DCERPC_TYPE_CL_CANCEL => "CL_CANCEL",
+        DCERPC_TYPE_FACK => "FACK",
+        DCERPC_TYPE_CANCEL_ACK => "CANCEL_ACK",
+        DCERPC_TYPE_BIND => "BIND",
+        DCERPC_TYPE_BINDACK => "BINDACK",
+        DCERPC_TYPE_BINDNAK => "BINDNAK",
+        DCERPC_TYPE_ALTER_CONTEXT => "ALTER_CONTEXT",
+        DCERPC_TYPE_ALTER_CONTEXT_RESP => "ALTER_CONTEXT_RESP",
+        DCERPC_TYPE_AUTH3 => "AUTH3",
+        DCERPC_TYPE_SHUTDOWN => "SHUTDOWN",
+        DCERPC_TYPE_CO_CANCEL => "CO_CANCEL",
+        DCERPC_TYPE_ORPHANED => "ORPHANED",
+        DCERPC_TYPE_RTS => "RTS",
+        _ => {
+            return (t).to_string();
+        }
+    }
+    .to_string()
+}
+
+#[derive(Debug)]
+pub struct DCERPCRequest {
+    pub ctxid: u16,
+    pub opnum: u16,
+    pub first_request_seen: u8,
+    pub stub_data_buffer: Vec<u8>,
+    pub stub_data_buffer_len: u16,
+    pub stub_data_buffer_reset: bool,
+    pub cmd: u8,
+}
+
+impl DCERPCRequest {
+    pub fn new() -> DCERPCRequest {
+        return DCERPCRequest {
+            ctxid: 0,
+            opnum: 0,
+            first_request_seen: 0,
+            stub_data_buffer: Vec::new(),
+            stub_data_buffer_len: 0,
+            stub_data_buffer_reset: false,
+            cmd: DCERPC_TYPE_REQUEST,
+        };
+    }
+}
+
+#[derive(Debug)]
+pub struct DCERPCResponse {
+    pub stub_data_buffer: Vec<u8>,
+    pub stub_data_buffer_len: u16,
+    pub stub_data_buffer_reset: bool,
+    pub cmd: u8,
+}
+
+impl DCERPCResponse {
+    pub fn new() -> DCERPCResponse {
+        return DCERPCResponse {
+            stub_data_buffer: Vec::new(),
+            stub_data_buffer_len: 0,
+            stub_data_buffer_reset: false,
+            cmd: DCERPC_TYPE_RESPONSE,
+        };
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct DCERPCUuidEntry {
+    pub ctxid: u16,
+    pub internal_id: u16,
+    pub result: u16,
+    pub uuid: Vec<u8>,
+    pub version: u16,
+    pub versionminor: u16,
+    pub flags: u16,
+}
+
+impl DCERPCUuidEntry {
+    pub fn new() -> DCERPCUuidEntry {
+        return DCERPCUuidEntry {
+            ctxid: 0,
+            internal_id: 0,
+            result: 0,
+            uuid: Vec::new(),
+            version: 0,
+            versionminor: 0,
+            flags: 0,
+        };
+    }
+}
+
+#[derive(Debug, PartialEq)]
+pub struct Uuid {
+    pub time_low: Vec<u8>,
+    pub time_mid: Vec<u8>,
+    pub time_hi_and_version: Vec<u8>,
+    pub clock_seq_hi_and_reserved: u8,
+    pub clock_seq_low: u8,
+    pub node: Vec<u8>,
+}
+
+#[derive(Debug)]
+pub struct DCERPCHdr {
+    pub rpc_vers: u8,
+    pub rpc_vers_minor: u8,
+    pub hdrtype: u8,
+    pub pfc_flags: u8,
+    pub packed_drep: Vec<u8>,
+    pub frag_length: u16,
+    pub auth_length: u16,
+    pub call_id: u32,
+}
+
+#[derive(Debug)]
+pub struct DCERPCBind {
+    pub numctxitems: u8,
+    pub uuid_list: Vec<DCERPCUuidEntry>,
+}
+
+#[derive(Debug)]
+pub struct BindCtxItem {
+    pub ctxid: u16,
+    pub uuid: Vec<u8>,
+    pub version: u16,
+    pub versionminor: u16,
+}
+
+#[derive(Debug, PartialEq)]
+pub struct DCERPCBindAckResult {
+    pub ack_result: u16,
+    pub ack_reason: u16,
+    pub transfer_syntax: Vec<u8>,
+    pub syntax_version: u32,
+}
+
+#[derive(Debug)]
+pub struct DCERPCBindAck {
+    pub accepted_uuid_list: Vec<DCERPCUuidEntry>,
+    pub sec_addr_len: u16,
+    pub numctxitems: u8,
+    pub ctxitems: Vec<DCERPCBindAckResult>,
+}
+
+#[derive(Debug)]
+pub struct DCERPCState {
+    pub header: Option<DCERPCHdr>,
+    pub bind: Option<DCERPCBind>,
+    pub bindack: Option<DCERPCBindAck>,
+    pub request: Option<DCERPCRequest>,
+    pub response: Option<DCERPCResponse>,
+    pub buffer_ts: Vec<u8>,
+    pub buffer_tc: Vec<u8>,
+    pub pad: u8,
+    pub padleft: u16,
+    pub bytes_consumed: u16,
+    pub tx_id: u16,
+    pub query_completed: bool,
+    pub data_needed_for_dir: u8,
+    pub prev_dir: u8,
+    pub detect_flags_ts: u64,
+    pub detect_flags_tc: u64,
+    pub de_state: Option<*mut core::DetectEngineState>,
+}
+
+impl DCERPCState {
+    pub fn new() -> DCERPCState {
+        return DCERPCState {
+            header: None,
+            bind: None,
+            bindack: None,
+            request: None,
+            response: None,
+            buffer_ts: Vec::new(),
+            buffer_tc: Vec::new(),
+            pad: 0,
+            padleft: 0,
+            bytes_consumed: 0,
+            tx_id: 0,
+            query_completed: false,
+            data_needed_for_dir: core::STREAM_TOSERVER,
+            prev_dir: core::STREAM_TOSERVER,
+            detect_flags_ts: 0,
+            detect_flags_tc: 0,
+            de_state: None,
+        };
+    }
+
+    fn get_hdr_drep_0(&self) -> u8 {
+        if let Some(ref hdr) = &self.header {
+            return hdr.packed_drep[0];
+        }
+        0
+    }
+
+    fn get_endianness(&self) -> Endianness {
+        let drep_0 = self.get_hdr_drep_0();
+        if drep_0 & 0x10 == 0 {
+            return Endianness::Big;
+        }
+        Endianness::Little
+    }
+
+    fn get_hdr_fraglen(&self) -> Option<u16> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = self.header {
+            return Some(hdr.frag_length);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    fn get_hdr_pfcflags(&self) -> Option<u8> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = self.header {
+            return Some(hdr.pfc_flags);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn get_hdr_type(&self) -> Option<u8> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = self.header {
+            return Some(hdr.hdrtype);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn get_hdr_rpc_vers(&self) -> Option<u8> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = self.header {
+            return Some(hdr.rpc_vers);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn get_req_ctxid(&self) -> Option<u16> {
+        debug_validate_bug_on!(self.request.is_none());
+        if let Some(ref req) = self.request {
+            return Some(req.ctxid);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn get_first_req_seen(&self) -> Option<u8> {
+        debug_validate_bug_on!(self.request.is_none());
+        if let Some(ref req) = self.request {
+            return Some(req.first_request_seen);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn get_req_opnum(&self) -> Option<u16> {
+        debug_validate_bug_on!(self.request.is_none());
+        if let Some(ref req) = self.request {
+            return Some(req.opnum);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn handle_gap_ts(&mut self) -> u8 {
+        if self.buffer_ts.len() > 0 {
+            self.buffer_ts.clear();
+        }
+        return 0;
+    }
+
+    pub fn handle_gap_tc(&mut self) -> u8 {
+        if self.buffer_tc.len() > 0 {
+            self.buffer_tc.clear();
+        }
+        return 0;
+    }
+
+    pub fn clean_buffer(&mut self, direction: u8) {
+        match direction {
+            core::STREAM_TOSERVER => {
+                self.buffer_ts.clear();
+            }
+            _ => {
+                self.buffer_tc.clear();
+            }
+        }
+        self.bytes_consumed = 0;
+    }
+
+    pub fn extend_buffer(&mut self, buffer: &[u8], direction: u8) {
+        match direction {
+            core::STREAM_TOSERVER => {
+                self.buffer_ts.extend_from_slice(buffer);
+            }
+            _ => {
+                self.buffer_tc.extend_from_slice(buffer);
+            }
+        }
+        self.data_needed_for_dir = direction;
+    }
+
+    pub fn reset_direction(&mut self, direction: u8) {
+        if direction == core::STREAM_TOSERVER {
+            self.data_needed_for_dir = core::STREAM_TOCLIENT;
+        } else {
+            self.data_needed_for_dir = core::STREAM_TOSERVER;
+        }
+    }
+
+    /// Makes a call to the nom parser for parsing DCERPC Header.
+    ///
+    /// Arguments:
+    /// * `input`:
+    ///           type: u8 vector slice.
+    ///    description: bytes from the beginning of the buffer.
+    ///
+    /// Return value:
+    /// * Success: Number of bytes successfully parsed.
+    /// * Failure: -1 in case of Incomplete data or Eof.
+    ///            -2 in case of Error while parsing.
+    pub fn process_header(&mut self, input: &[u8]) -> i32 {
+        match parser::parse_dcerpc_header(input) {
+            Ok((leftover_bytes, header)) => {
+                if header.rpc_vers != 5
+                    || (header.rpc_vers_minor != 0 && header.rpc_vers_minor != 1)
+                {
+                    SCLogDebug!(
+                        "DCERPC Header did not validate. Major version: {:?} Minor version: {:?}",
+                        header.rpc_vers,
+                        header.rpc_vers_minor
+                    );
+                    return -1;
+                }
+                self.header = Some(header);
+                (input.len() - leftover_bytes.len()) as i32
+            }
+            Err(nom::Err::Incomplete(_)) => {
+                // Insufficient data.
+                SCLogDebug!("Insufficient data while parsing DCERPC header");
+                -1
+            }
+            Err(nom::Err::Error(([], ErrorKind::Eof))) => {
+                SCLogDebug!("EoF reached while parsing DCERPC header");
+                -1
+            }
+            Err(_) => {
+                // Error, probably malformed data.
+                SCLogDebug!("An error occured while parsing DCERPC header");
+                -2
+            }
+        }
+    }
+
+    pub fn handle_bindctxitem(&mut self, input: &[u8], uuid_internal_id: u16) -> i32 {
+        let endianness = self.get_endianness();
+        match parser::parse_bindctx_item(input, endianness) {
+            Ok((leftover_bytes, ctxitem)) => {
+                let mut uuidentry = DCERPCUuidEntry::new();
+                uuidentry.uuid = ctxitem.uuid;
+                uuidentry.internal_id = uuid_internal_id;
+                uuidentry.ctxid = ctxitem.ctxid;
+                uuidentry.version = ctxitem.version;
+                uuidentry.versionminor = ctxitem.versionminor;
+                let pfcflags = self.get_hdr_pfcflags().unwrap_or(0);
+                // Store the first frag flag in the uuid as pfc_flags will
+                // be overwritten by new packets
+                if pfcflags & PFC_FIRST_FRAG > 0 {
+                    uuidentry.flags |= DCERPC_UUID_ENTRY_FLAG_FF;
+                }
+                if let Some(ref mut bind) = self.bind {
+                    SCLogDebug!("DCERPC BIND CtxItem: Pushing uuid: {:?}", uuidentry);
+                    bind.uuid_list.push(uuidentry);
+                }
+                (input.len() - leftover_bytes.len()) as i32
+            }
+            Err(nom::Err::Incomplete(_)) => {
+                // Insufficient data.
+                SCLogDebug!("Insufficient data while parsing DCERPC BIND CTXItem");
+                -1
+            }
+            Err(_) => {
+                // Error, probably malformed data.
+                SCLogDebug!("An error occurred while parsing DCERPC BIND CTXItem");
+                -1
+            }
+        }
+    }
+
+    pub fn process_bind_pdu(&mut self, input: &[u8]) -> i32 {
+        let mut retval = 0;
+        let mut idx = 12; // Bytes consumed if parser returns OK would be 12
+        match parser::parse_dcerpc_bind(input) {
+            Ok((leftover_bytes, header)) => {
+                let numctxitems = header.numctxitems;
+                self.bind = Some(header);
+                for i in 0..numctxitems {
+                    retval = self.handle_bindctxitem(&input[idx as usize..], i as u16);
+                    if retval == -1 {
+                        return -1;
+                    }
+                    idx = retval + idx;
+                }
+                // Bytes parsed with `parse_dcerpc_bind` + (bytes parsed per bindctxitem [44] * number
+                // of bindctxitems)
+                (input.len() - leftover_bytes.len()) as i32 + retval * numctxitems as i32
+            }
+            Err(nom::Err::Incomplete(_)) => {
+                // Insufficient data.
+                SCLogDebug!("Insufficient data while parsing DCERPC BIND header");
+                -1
+            }
+            Err(_) => {
+                // Error, probably malformed data.
+                SCLogDebug!("An error occurred while parsing DCERPC BIND header");
+                -1
+            }
+        }
+    }
+
+    pub fn process_bindack_pdu(&mut self, input: &[u8]) -> i32 {
+        match parser::parse_dcerpc_bindack(input) {
+            Ok((leftover_bytes, mut back)) => {
+                if let Some(ref mut bind) = self.bind {
+                    let mut uuid_internal_id = 0;
+                    for r in back.ctxitems.iter() {
+                        for mut uuid in bind.uuid_list.iter_mut() {
+                            if uuid.internal_id == uuid_internal_id {
+                                uuid.result = r.ack_result;
+                                if uuid.result != 0 {
+                                    break;
+                                }
+                                back.accepted_uuid_list.push(uuid.clone());
+                                SCLogDebug!("DCERPC BINDACK accepted UUID: {:?}", uuid);
+                            }
+                        }
+                        uuid_internal_id += 1;
+                    }
+                    self.bindack = Some(back);
+                }
+                (input.len() - leftover_bytes.len()) as i32
+            }
+            Err(nom::Err::Incomplete(_)) => {
+                // Insufficient data.
+                SCLogDebug!("Insufficient data while parsing DCERPC BINDACK");
+                -1
+            }
+            Err(_) => {
+                // Error, probably malformed data.
+                SCLogDebug!("An error occurred while parsing DCERPC BINDACK");
+                -1
+            }
+        }
+    }
+
+    pub fn handle_stub_data(&mut self, input: &[u8], input_len: u16) -> u16 {
+        let mut retval: u16 = 0;
+        let hdrpfcflags = self.get_hdr_pfcflags().unwrap_or(0);
+        let padleft = self.padleft;
+        // Update the stub params based on the packet type
+        match self.get_hdr_type() {
+            Some(x) => match x {
+                DCERPC_TYPE_REQUEST => {
+                    if let Some(ref mut req) = self.request {
+                        retval = evaluate_stub_params(
+                            input,
+                            input_len,
+                            hdrpfcflags,
+                            padleft,
+                            &mut req.stub_data_buffer,
+                            &mut req.stub_data_buffer_len,
+                            &mut req.stub_data_buffer_reset,
+                        );
+                    }
+                }
+                DCERPC_TYPE_RESPONSE => {
+                    if let Some(ref mut resp) = self.response {
+                        retval = evaluate_stub_params(
+                            input,
+                            input_len,
+                            hdrpfcflags,
+                            padleft,
+                            &mut resp.stub_data_buffer,
+                            &mut resp.stub_data_buffer_len,
+                            &mut resp.stub_data_buffer_reset,
+                        );
+                    }
+                }
+                _ => {
+                    SCLogDebug!("Unrecognized packet type");
+                    return 0;
+                }
+            },
+            None => {
+                return 0;
+            }
+        }
+        // Update the remaining fragment length
+        self.padleft -= retval;
+
+        retval
+    }
+
+    /// Handles stub data for both request and response.
+    ///
+    /// Arguments:
+    /// * `input`:
+    ///           type: u8 vector slice.
+    ///    description: bytes left *after* parsing header.
+    /// * `bytes_consumed`:
+    ///           type: 16 bit unsigned integer.
+    ///    description: bytes consumed *after* parsing header.
+    /// * `dir`:
+    ///           type: 8 bit unsigned integer.
+    ///    description: direction whose stub is supposed to be handled.
+    ///
+    /// Return value:
+    /// * Success: Number of bytes successfully parsed.
+    /// * Failure: -1 in case fragment length defined by header mismatches the data.
+    pub fn handle_common_stub(&mut self, input: &[u8], bytes_consumed: u16, dir: u8) -> i32 {
+        let fraglen = self.get_hdr_fraglen().unwrap_or(0);
+        if fraglen < bytes_consumed as u16 + DCERPC_HDR_LEN {
+            return -1;
+        }
+        self.padleft = fraglen - DCERPC_HDR_LEN - bytes_consumed;
+        let mut input_left = input.len() as u16 - bytes_consumed;
+        let mut parsed = bytes_consumed;
+        while input_left > 0 && parsed < fraglen {
+            let retval = self.handle_stub_data(&input[parsed as usize..], input_left);
+            if retval > 0 && retval <= input_left {
+                parsed += retval;
+                input_left -= retval;
+            } else if input_left > 0 {
+                SCLogDebug!(
+                    "Error parsing DCERPC {} stub data",
+                    if dir == core::STREAM_TOSERVER {
+                        "request"
+                    } else {
+                        "response"
+                    }
+                );
+                parsed -= input_left;
+                input_left = 0;
+            }
+        }
+        parsed as i32
+    }
+
+    pub fn process_request_pdu(&mut self, input: &[u8]) -> i32 {
+        let endianness = self.get_endianness();
+        match parser::parse_dcerpc_request(input, endianness) {
+            Ok((leftover_input, mut request)) => {
+                request.cmd = self.get_hdr_type().unwrap_or(0);
+                self.request = Some(request);
+                let parsed = self.handle_common_stub(
+                    &input,
+                    (input.len() - leftover_input.len()) as u16,
+                    core::STREAM_TOSERVER,
+                );
+                parsed
+            }
+            Err(nom::Err::Incomplete(_)) => {
+                // Insufficient data.
+                SCLogDebug!("Insufficient data while parsing DCERPC REQUEST");
+                -1
+            }
+            Err(_) => {
+                // Error, probably malformed data.
+                SCLogDebug!("An error occurred while parsing DCERPC REQUEST");
+                -1
+            }
+        }
+    }
+
+    pub fn handle_input_data(&mut self, input: &[u8], direction: u8) -> AppLayerResult {
+        let mut parsed;
+        let retval;
+        let input_len = input.len();
+        let mut v: Vec<u8>;
+        // Set any query's completion status to false in the beginning
+        self.query_completed = false;
+        // Overwrite the dcerpc_state data in case of multiple complete queries in the
+        // same direction
+        if self.prev_dir == direction {
+            self.data_needed_for_dir = direction;
+        }
+
+        let buffer = match direction {
+            core::STREAM_TOSERVER => {
+                if self.buffer_ts.len() + input_len > 1024 * 1024 {
+                    SCLogDebug!("DCERPC TOSERVER stream: Buffer Overflow");
+                    return AppLayerResult::err();
+                }
+                v = self.buffer_ts.split_off(0);
+                v.extend_from_slice(input);
+                v.as_slice()
+            }
+            _ => {
+                if self.buffer_tc.len() + input_len > 1024 * 1024 {
+                    SCLogDebug!("DCERPC TOCLIENT stream: Buffer Overflow");
+                    return AppLayerResult::err();
+                }
+                v = self.buffer_tc.split_off(0);
+                v.extend_from_slice(input);
+                v.as_slice()
+            }
+        };
+
+        if self.data_needed_for_dir != direction && buffer.len() != 0 {
+            return AppLayerResult::err();
+        }
+
+        // Set data_needed_for_dir in the same direction in case there is an issue with upcoming parsing
+        self.data_needed_for_dir = direction;
+
+        // Check if header data was complete. In case of EoF or incomplete data, wait for more
+        // data else return error
+        if self.bytes_consumed < DCERPC_HDR_LEN && input_len > 0 {
+            parsed = self.process_header(&buffer);
+            if parsed == -1 {
+                self.extend_buffer(buffer, direction);
+                return AppLayerResult::ok();
+            }
+            if parsed == -2 {
+                return AppLayerResult::err();
+            }
+            self.bytes_consumed += parsed as u16;
+        }
+
+        let fraglen = self.get_hdr_fraglen().unwrap_or(0);
+
+        if (buffer.len() as u16) < fraglen {
+            SCLogDebug!("Possibly fragmented data, waiting for more..");
+            self.extend_buffer(buffer, direction);
+            return AppLayerResult::ok();
+        } else {
+            self.query_completed = true;
+        }
+        // TODO buffer extra data when input length is more than fraglen
+        parsed = self.bytes_consumed as i32;
+
+        match self.get_hdr_type() {
+            Some(x) => match x {
+                DCERPC_TYPE_BIND | DCERPC_TYPE_ALTER_CONTEXT => {
+                    retval = self.process_bind_pdu(&buffer[parsed as usize..]);
+                    if retval == -1 {
+                        return AppLayerResult::err();
+                    }
+                }
+                DCERPC_TYPE_BINDACK | DCERPC_TYPE_ALTER_CONTEXT_RESP => {
+                    retval = self.process_bindack_pdu(&buffer[parsed as usize..]);
+                    if retval == -1 {
+                        return AppLayerResult::err();
+                    }
+                }
+                DCERPC_TYPE_REQUEST => {
+                    retval = self.process_request_pdu(&buffer[parsed as usize..]);
+                    if retval == -1 {
+                        return AppLayerResult::err();
+                    }
+                }
+                DCERPC_TYPE_RESPONSE => {
+                    let mut response = DCERPCResponse::new();
+                    response.cmd = self.get_hdr_type().unwrap_or(DCERPC_TYPE_RESPONSE);
+                    self.response = Some(response);
+                    retval = self.handle_common_stub(
+                        &buffer[parsed as usize..],
+                        0,
+                        core::STREAM_TOCLIENT,
+                    );
+                    if retval == -1 {
+                        return AppLayerResult::err();
+                    }
+                    self.tx_id += 1; // Complete response, maybe to be used in future?
+                }
+                _ => {
+                    SCLogDebug!("Unrecognized packet type");
+                    self.clean_buffer(direction);
+                    return AppLayerResult::err();
+                }
+            },
+            None => {
+                return AppLayerResult::err();
+            }
+        }
+        self.bytes_consumed += retval as u16;
+
+        // If the query has been completed, clean the buffer and reset the direction
+        if self.query_completed == true {
+            self.clean_buffer(direction);
+            self.reset_direction(direction);
+        }
+        self.prev_dir = direction;
+        return AppLayerResult::ok();
+    }
+}
+
+fn evaluate_stub_params(
+    input: &[u8],
+    input_len: u16,
+    hdrflags: u8,
+    lenleft: u16,
+    stub_data_buffer: &mut Vec<u8>,
+    stub_data_buffer_len: &mut u16,
+    stub_data_buffer_reset: &mut bool,
+) -> u16 {
+    let stub_len: u16;
+    let fragtype = hdrflags & (PFC_FIRST_FRAG | PFC_LAST_FRAG);
+    stub_len = cmp::min(lenleft, input_len);
+    if stub_len == 0 {
+        return 0;
+    }
+    if stub_len == lenleft && (fragtype == 0 || (fragtype & PFC_LAST_FRAG > 0)) {
+        *stub_data_buffer_reset = true;
+    }
+
+    let input_slice = &input[..stub_len as usize];
+    stub_data_buffer.extend_from_slice(&input_slice);
+    *stub_data_buffer_len += stub_len;
+
+    stub_len
+}
+
+#[no_mangle]
+pub extern "C" fn rs_parse_dcerpc_request_gap(
+    state: &mut DCERPCState,
+    _input_len: u32,
+) -> AppLayerResult {
+    if state.handle_gap_ts() == 0 {
+        return AppLayerResult::ok();
+    }
+    AppLayerResult::err()
+}
+
+#[no_mangle]
+pub extern "C" fn rs_parse_dcerpc_response_gap(
+    state: &mut DCERPCState,
+    _input_len: u32,
+) -> AppLayerResult {
+    if state.handle_gap_tc() == 0 {
+        return AppLayerResult::ok();
+    }
+    AppLayerResult::err()
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_parse_request(
+    _flow: *mut core::Flow,
+    state: &mut DCERPCState,
+    _pstate: *mut std::os::raw::c_void,
+    input: *const u8,
+    input_len: u32,
+    _data: *mut std::os::raw::c_void,
+    flags: u8,
+) -> AppLayerResult {
+    if input_len > 0 && input != std::ptr::null_mut() {
+        let buf = build_slice!(input, input_len as usize);
+        return state.handle_input_data(buf, flags);
+    }
+    AppLayerResult::err()
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_parse_response(
+    _flow: *mut core::Flow,
+    state: &mut DCERPCState,
+    _pstate: *mut std::os::raw::c_void,
+    input: *const u8,
+    input_len: u32,
+    _data: *mut std::os::raw::c_void,
+    flags: u8,
+) -> AppLayerResult {
+    if input_len > 0 {
+        if input != std::ptr::null_mut() {
+            let buf = build_slice!(input, input_len as usize);
+            return state.handle_input_data(buf, flags);
+        }
+    }
+    AppLayerResult::err()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_state_new() -> *mut std::os::raw::c_void {
+    let state = DCERPCState::new();
+    let boxed = Box::new(state);
+    transmute(boxed)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_state_free(state: *mut std::os::raw::c_void) {
+    let _drop: Box<DCERPCState> = transmute(state);
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_state_transaction_free(_state: *mut std::os::raw::c_void, _tx_id: u64) {
+    // do nothing
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_get_tx_detect_state(
+    vtx: *mut std::os::raw::c_void,
+) -> *mut core::DetectEngineState {
+    let dce_state = cast_pointer!(vtx, DCERPCState);
+    match dce_state.de_state {
+        Some(ds) => ds,
+        None => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_set_tx_detect_state(
+    vtx: *mut std::os::raw::c_void,
+    de_state: *mut core::DetectEngineState,
+) -> u8 {
+    let dce_state = cast_pointer!(vtx, DCERPCState);
+    dce_state.de_state = Some(de_state);
+    0
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_get_tx(
+    state: *mut std::os::raw::c_void,
+    _tx_id: u64,
+) -> *mut DCERPCState {
+    let dce_state = cast_pointer!(state, DCERPCState);
+    dce_state
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_get_tx_cnt(_state: *mut std::os::raw::c_void) -> u8 {
+    1
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_get_alstate_progress(
+    _tx: *mut std::os::raw::c_void,
+    _direction: u8,
+) -> u8 {
+    0
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_get_alstate_progress_completion_status(_direction: u8) -> u8 {
+    1
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_get_tx_detect_flags(vtx: *mut std::os::raw::c_void, dir: u8) -> u64 {
+    let state = cast_pointer!(vtx, DCERPCState);
+    if dir & core::STREAM_TOSERVER != 0 {
+        return state.detect_flags_ts;
+    }
+    state.detect_flags_tc
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_set_tx_detect_flags(
+    vtx: *mut std::os::raw::c_void,
+    dir: u8,
+    flags: u64,
+) {
+    let state = cast_pointer!(vtx, DCERPCState);
+    if dir & core::STREAM_TOSERVER != 0 {
+        state.detect_flags_ts = flags;
+    } else {
+        state.detect_flags_tc = flags;
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_get_stub_data(
+    state: &mut DCERPCState,
+    buf: *mut *const u8,
+    len: *mut u32,
+    endianness: *mut u8,
+    dir: u8,
+) {
+    match dir {
+        core::STREAM_TOSERVER => {
+            if let Some(ref req) = state.request {
+                *len = req.stub_data_buffer_len as u32;
+                *buf = req.stub_data_buffer.as_ptr();
+                SCLogDebug!("DCERPC Request stub buffer: Setting buffer to: {:?}", *buf);
+            }
+        }
+        _ => {
+            if let Some(ref resp) = state.response {
+                *len = resp.stub_data_buffer_len as u32;
+                *buf = resp.stub_data_buffer.as_ptr();
+                SCLogDebug!("DCERPC Response stub buffer: Setting buffer to: {:?}", *buf);
+            }
+        }
+    }
+    *endianness = state.get_hdr_drep_0() & 0x10;
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::applayer::AppLayerResult;
+    use crate::core;
+    use crate::dcerpc::dcerpc::DCERPCState;
+    use std::cmp;
+
+    #[test]
+    fn test_process_header() {
+        let request: &[u8] = &[
+            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(16, dcerpc_state.process_header(request));
+    }
+
+    #[test]
+    fn test_process_bind_pdu() {
+        let bind: &[u8] = &[
+            0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f, 0xbf, 0x85,
+            0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x01, 0x00, 0x2c, 0x75, 0xce, 0x7e, 0x82, 0x3b, 0x06, 0xac, 0x1b, 0xf0,
+            0xf5, 0xb7, 0xa7, 0xf7, 0x28, 0xaf, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xe3, 0xb2, 0x10, 0xd1, 0xd0, 0x0c, 0xcc, 0x3d,
+            0x2f, 0x80, 0x20, 0x7c, 0xef, 0xe7, 0x09, 0xe0, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xde, 0x85, 0x70, 0xc4, 0x02, 0x7c,
+            0x60, 0x23, 0x67, 0x0c, 0x22, 0xbf, 0x18, 0x36, 0x79, 0x17, 0x01, 0x00, 0x02, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x41, 0x65, 0x29, 0x51,
+            0xaa, 0xe7, 0x7b, 0xa8, 0xf2, 0x37, 0x0b, 0xd0, 0x3f, 0xb3, 0x36, 0xed, 0x05, 0x00,
+            0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x14, 0x96,
+            0x80, 0x01, 0x2e, 0x78, 0xfb, 0x5d, 0xb4, 0x3c, 0x14, 0xb3, 0x3d, 0xaa, 0x02, 0xfb,
+            0x06, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00,
+            0x3b, 0x04, 0x68, 0x3e, 0x63, 0xfe, 0x9f, 0xd8, 0x64, 0x55, 0xcd, 0xe7, 0x39, 0xaf,
+            0x98, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00,
+            0x01, 0x00, 0x16, 0x7a, 0x4f, 0x1b, 0xdb, 0x25, 0x92, 0x55, 0xdd, 0xae, 0x9e, 0x5b,
+            0x3e, 0x93, 0x66, 0x93, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x08, 0x00, 0x01, 0x00, 0xe8, 0xa4, 0x8a, 0xcf, 0x95, 0x6c, 0xc7, 0x8f, 0x14, 0xcc,
+            0x56, 0xfc, 0x7b, 0x5f, 0x4f, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xd8, 0xda, 0xfb, 0xbc, 0xa2, 0x55, 0x6f, 0x5d,
+            0xc0, 0x2d, 0x88, 0x6f, 0x00, 0x17, 0x52, 0x8d, 0x06, 0x00, 0x03, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x3f, 0x17, 0x55, 0x0c, 0xf4, 0x23,
+            0x3c, 0xca, 0xe6, 0xa0, 0xaa, 0xcc, 0xb5, 0xe3, 0xf9, 0xce, 0x04, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x6a, 0x28, 0x19, 0x39,
+            0x0c, 0xb1, 0xd0, 0x11, 0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5, 0x00, 0x00,
+            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0xc9, 0x9f,
+            0x3e, 0x6e, 0x82, 0x0a, 0x2b, 0x28, 0x37, 0x78, 0xe1, 0x13, 0x70, 0x05, 0x38, 0x4d,
+            0x01, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x01, 0x00,
+            0x11, 0xaa, 0x4b, 0x15, 0xdf, 0xa6, 0x86, 0x3f, 0xfb, 0xe0, 0x09, 0xb7, 0xf8, 0x56,
+            0xd2, 0x3f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00,
+            0x01, 0x00, 0xee, 0x99, 0xc4, 0x25, 0x11, 0xe4, 0x95, 0x62, 0x29, 0xfa, 0xfd, 0x26,
+            0x57, 0x02, 0xf1, 0xce, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x0f, 0x00, 0x01, 0x00, 0xba, 0x81, 0x9e, 0x1a, 0xdf, 0x2b, 0xba, 0xe4, 0xd3, 0x17,
+            0x41, 0x60, 0x6d, 0x2d, 0x9e, 0x28, 0x03, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0xa0, 0x24, 0x03, 0x9a, 0xa9, 0x99, 0xfb, 0xbe,
+            0x49, 0x11, 0xad, 0x77, 0x30, 0xaa, 0xbc, 0xb6, 0x02, 0x00, 0x03, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x32, 0x04, 0x7e, 0xae, 0xec, 0x28,
+            0xd1, 0x55, 0x83, 0x4e, 0xc3, 0x47, 0x5d, 0x1d, 0xc6, 0x65, 0x02, 0x00, 0x03, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0xc6, 0xa4, 0x81, 0x48,
+            0x66, 0x2a, 0x74, 0x7d, 0x56, 0x6e, 0xc5, 0x1d, 0x19, 0xf2, 0xb5, 0xb6, 0x03, 0x00,
+            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00, 0xcb, 0xae,
+            0xb3, 0xc0, 0x0c, 0xf4, 0xa4, 0x5e, 0x91, 0x72, 0xdd, 0x53, 0x24, 0x70, 0x89, 0x02,
+            0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00,
+            0xb8, 0xd0, 0xa0, 0x1a, 0x5e, 0x7a, 0x2d, 0xfe, 0x35, 0xc6, 0x7d, 0x08, 0x0d, 0x33,
+            0x73, 0x18, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00,
+            0x01, 0x00, 0x21, 0xd3, 0xaa, 0x09, 0x03, 0xa7, 0x0b, 0xc2, 0x06, 0x45, 0xd9, 0x6c,
+            0x75, 0xc2, 0x15, 0xa8, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x16, 0x00, 0x01, 0x00, 0xe1, 0xbd, 0x59, 0xfc, 0xbc, 0xa9, 0x95, 0xc2, 0x68, 0x79,
+            0xf3, 0x75, 0xe0, 0xae, 0x6c, 0xe5, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x06, 0x52, 0xb4, 0x71, 0x70, 0x15, 0x4e, 0xf5,
+            0x7f, 0x08, 0x86, 0x14, 0xe6, 0x17, 0xd5, 0x97, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(1068, dcerpc_state.process_bind_pdu(bind));
+    }
+
+    #[test]
+    fn test_handle_bindctxitem() {
+        let bind: &[u8] = &[
+            0x00, 0x00, 0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f,
+            0xbf, 0x85, 0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(44, dcerpc_state.handle_bindctxitem(bind, 0));
+    }
+
+    #[test]
+    fn test_process_bindack_pdu() {
+        let bind: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f,
+            0xbf, 0x85, 0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x2c, 0x75, 0xce, 0x7e, 0x82, 0x3b, 0x06, 0xac,
+            0x1b, 0xf0, 0xf5, 0xb7, 0xa7, 0xf7, 0x28, 0xaf, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xe3, 0xb2, 0x10, 0xd1, 0xd0, 0x0c,
+            0xcc, 0x3d, 0x2f, 0x80, 0x20, 0x7c, 0xef, 0xe7, 0x09, 0xe0, 0x04, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xde, 0x85, 0x70, 0xc4,
+            0x02, 0x7c, 0x60, 0x23, 0x67, 0x0c, 0x22, 0xbf, 0x18, 0x36, 0x79, 0x17, 0x01, 0x00,
+            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x41, 0x65,
+            0x29, 0x51, 0xaa, 0xe7, 0x7b, 0xa8, 0xf2, 0x37, 0x0b, 0xd0, 0x3f, 0xb3, 0x36, 0xed,
+            0x05, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
+            0x14, 0x96, 0x80, 0x01, 0x2e, 0x78, 0xfb, 0x5d, 0xb4, 0x3c, 0x14, 0xb3, 0x3d, 0xaa,
+            0x02, 0xfb, 0x06, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
+            0x01, 0x00, 0x3b, 0x04, 0x68, 0x3e, 0x63, 0xfe, 0x9f, 0xd8, 0x64, 0x55, 0xcd, 0xe7,
+            0x39, 0xaf, 0x98, 0x9f, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x07, 0x00, 0x01, 0x00, 0x16, 0x7a, 0x4f, 0x1b, 0xdb, 0x25, 0x92, 0x55, 0xdd, 0xae,
+            0x9e, 0x5b, 0x3e, 0x93, 0x66, 0x93, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0xe8, 0xa4, 0x8a, 0xcf, 0x95, 0x6c, 0xc7, 0x8f,
+            0x14, 0xcc, 0x56, 0xfc, 0x7b, 0x5f, 0x4f, 0xe8, 0x04, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xd8, 0xda, 0xfb, 0xbc, 0xa2, 0x55,
+            0x6f, 0x5d, 0xc0, 0x2d, 0x88, 0x6f, 0x00, 0x17, 0x52, 0x8d, 0x06, 0x00, 0x03, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x3f, 0x17, 0x55, 0x0c,
+            0xf4, 0x23, 0x3c, 0xca, 0xe6, 0xa0, 0xaa, 0xcc, 0xb5, 0xe3, 0xf9, 0xce, 0x04, 0x00,
+            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x6a, 0x28,
+            0x19, 0x39, 0x0c, 0xb1, 0xd0, 0x11, 0x9b, 0xa8, 0x00, 0xc0, 0x4f, 0xd9, 0x2e, 0xf5,
+            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
+            0xc9, 0x9f, 0x3e, 0x6e, 0x82, 0x0a, 0x2b, 0x28, 0x37, 0x78, 0xe1, 0x13, 0x70, 0x05,
+            0x38, 0x4d, 0x01, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00,
+            0x01, 0x00, 0x11, 0xaa, 0x4b, 0x15, 0xdf, 0xa6, 0x86, 0x3f, 0xfb, 0xe0, 0x09, 0xb7,
+            0xf8, 0x56, 0xd2, 0x3f, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x0e, 0x00, 0x01, 0x00, 0xee, 0x99, 0xc4, 0x25, 0x11, 0xe4, 0x95, 0x62, 0x29, 0xfa,
+            0xfd, 0x26, 0x57, 0x02, 0xf1, 0xce, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xba, 0x81, 0x9e, 0x1a, 0xdf, 0x2b, 0xba, 0xe4,
+            0xd3, 0x17, 0x41, 0x60, 0x6d, 0x2d, 0x9e, 0x28, 0x03, 0x00, 0x03, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0xa0, 0x24, 0x03, 0x9a, 0xa9, 0x99,
+            0xfb, 0xbe, 0x49, 0x11, 0xad, 0x77, 0x30, 0xaa, 0xbc, 0xb6, 0x02, 0x00, 0x03, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x32, 0x04, 0x7e, 0xae,
+            0xec, 0x28, 0xd1, 0x55, 0x83, 0x4e, 0xc3, 0x47, 0x5d, 0x1d, 0xc6, 0x65, 0x02, 0x00,
+            0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x01, 0x00, 0xc6, 0xa4,
+            0x81, 0x48, 0x66, 0x2a, 0x74, 0x7d, 0x56, 0x6e, 0xc5, 0x1d, 0x19, 0xf2, 0xb5, 0xb6,
+            0x03, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x01, 0x00,
+            0xcb, 0xae, 0xb3, 0xc0, 0x0c, 0xf4, 0xa4, 0x5e, 0x91, 0x72, 0xdd, 0x53, 0x24, 0x70,
+            0x89, 0x02, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00,
+            0x01, 0x00, 0xb8, 0xd0, 0xa0, 0x1a, 0x5e, 0x7a, 0x2d, 0xfe, 0x35, 0xc6, 0x7d, 0x08,
+            0x0d, 0x33, 0x73, 0x18, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x15, 0x00, 0x01, 0x00, 0x21, 0xd3, 0xaa, 0x09, 0x03, 0xa7, 0x0b, 0xc2, 0x06, 0x45,
+            0xd9, 0x6c, 0x75, 0xc2, 0x15, 0xa8, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x16, 0x00, 0x01, 0x00, 0xe1, 0xbd, 0x59, 0xfc, 0xbc, 0xa9, 0x95, 0xc2,
+            0x68, 0x79, 0xf3, 0x75, 0xe0, 0xae, 0x6c, 0xe5, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, 0x06, 0x52, 0xb4, 0x71, 0x70, 0x15,
+            0x4e, 0xf5, 0x7f, 0x08, 0x86, 0x14, 0xe6, 0x17, 0xd5, 0x97, 0x04, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let bindack: &[u8] = &[
+            0xb8, 0x10, 0xb8, 0x10, 0xce, 0x47, 0x00, 0x00, 0x0c, 0x00, 0x5c, 0x50, 0x49, 0x50,
+            0x45, 0x5c, 0x6c, 0x73, 0x61, 0x73, 0x73, 0x00, 0xf6, 0x6e, 0x18, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(16, dcerpc_state.process_header(bind));
+        assert_eq!(1068, dcerpc_state.process_bind_pdu(&bind[16..]));
+        assert_eq!(604, dcerpc_state.process_bindack_pdu(bindack));
+        if let Some(back) = dcerpc_state.bindack {
+            assert_eq!(1, back.accepted_uuid_list.len());
+            assert_eq!(
+                vec!(57, 25, 40, 106, 177, 12, 17, 208, 155, 168, 0, 192, 79, 217, 46, 245),
+                back.accepted_uuid_list[0].uuid
+            );
+            assert_eq!(11, back.accepted_uuid_list[0].internal_id);
+        }
+    }
+
+    #[test]
+    pub fn test_process_request_pdu() {
+        let request: &[u8] = &[
+            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x45, 0x00, 0x2c, 0x00,
+            0x4d, 0x00, 0x73, 0x00, 0x53, 0x00, 0x59, 0x00, 0x2a, 0x00, 0x4a, 0x00, 0x7a, 0x00,
+            0x3e, 0x00, 0x58, 0x00, 0x21, 0x00, 0x4a, 0x00, 0x30, 0x00, 0x41, 0x00, 0x4b, 0x00,
+            0x4b, 0x00, 0x3c, 0x00, 0x48, 0x00, 0x24, 0x00, 0x38, 0x00, 0x54, 0x00, 0x60, 0x00,
+            0x2d, 0x00, 0x29, 0x00, 0x64, 0x00, 0x5b, 0x00, 0x77, 0x00, 0x3a, 0x00, 0x4c, 0x00,
+            0x24, 0x00, 0x23, 0x00, 0x66, 0x00, 0x43, 0x00, 0x68, 0x00, 0x22, 0x00, 0x55, 0x00,
+            0x29, 0x00, 0x2c, 0x00, 0x4f, 0x00, 0x5a, 0x00, 0x50, 0x00, 0x61, 0x00, 0x2a, 0x00,
+            0x6f, 0x00, 0x2f, 0x00, 0x4d, 0x00, 0x68, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x67, 0x00,
+            0x68, 0x00, 0x68, 0x00, 0x49, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x72, 0x00, 0x53, 0x00,
+            0x4c, 0x00, 0x25, 0x00, 0x4d, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x4f, 0x00, 0x64, 0x00,
+            0x61, 0x00, 0x73, 0x00, 0x24, 0x00, 0x46, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x45, 0x00,
+            0x6f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x33, 0x00, 0x38, 0x00, 0x47, 0x00, 0x71, 0x00,
+            0x5a, 0x00, 0x37, 0x00, 0x7a, 0x00, 0x35, 0x00, 0x6b, 0x00, 0x3c, 0x00, 0x26, 0x00,
+            0x37, 0x00, 0x69, 0x00, 0x75, 0x00, 0x36, 0x00, 0x37, 0x00, 0x47, 0x00, 0x21, 0x00,
+            0x2d, 0x00, 0x69, 0x00, 0x37, 0x00, 0x78, 0x00, 0x5f, 0x00, 0x72, 0x00, 0x4b, 0x00,
+            0x5c, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x52, 0x00, 0x7a, 0x00, 0x49, 0x00, 0x31, 0x00,
+            0x5a, 0x00, 0x7b, 0x00, 0x29, 0x00, 0x3b, 0x00, 0x78, 0x00, 0x3b, 0x00, 0x55, 0x00,
+            0x3e, 0x00, 0x35, 0x00, 0x2b, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x59, 0x00, 0x38, 0x00,
+            0x2a, 0x00, 0x59, 0x00, 0x6b, 0x00, 0x42, 0x00, 0x4c, 0x00, 0x3e, 0x00, 0x6a, 0x00,
+            0x49, 0x00, 0x2c, 0x00, 0x79, 0x00, 0x6e, 0x00, 0x35, 0x00, 0x4f, 0x00, 0x49, 0x00,
+            0x55, 0x00, 0x35, 0x00, 0x61, 0x00, 0x72, 0x00, 0x77, 0x00, 0x38, 0x00, 0x32, 0x00,
+            0x24, 0x00, 0x46, 0x00, 0x32, 0x00, 0x32, 0x00, 0x27, 0x00, 0x64, 0x00, 0x5a, 0x00,
+            0x77, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x77, 0x00, 0x2e, 0x00, 0x28, 0x00, 0x63, 0x00,
+            0x4f, 0x00, 0x67, 0x00, 0x64, 0x00, 0x39, 0x00, 0x37, 0x00, 0x31, 0x00, 0x30, 0x00,
+            0x28, 0x00, 0x2e, 0x00, 0x6f, 0x00, 0x3e, 0x00, 0x59, 0x00, 0x28, 0x00, 0x67, 0x00,
+            0x52, 0x00, 0x35, 0x00, 0x5a, 0x00, 0x7c, 0x00, 0x56, 0x00, 0x6a, 0x00, 0x5c, 0x00,
+            0x3c, 0x00, 0x30, 0x00, 0x59, 0x00, 0x5c, 0x00, 0x5e, 0x00, 0x38, 0x00, 0x54, 0x00,
+            0x5c, 0x00, 0x5b, 0x00, 0x42, 0x00, 0x62, 0x00, 0x70, 0x00, 0x34, 0x00, 0x5c, 0x00,
+            0x57, 0x00, 0x7a, 0x00, 0x4b, 0x00, 0x2f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x4f, 0x00,
+            0x41, 0x00, 0x33, 0x00, 0x52, 0x00, 0x36, 0x00, 0x27, 0x00, 0x30, 0x00, 0x6d, 0x00,
+            0x4a, 0x00, 0x30, 0x00, 0x78, 0x00, 0x46, 0x00, 0x65, 0x00, 0x4e, 0x00, 0x29, 0x00,
+            0x66, 0x00, 0x3f, 0x00, 0x72, 0x00, 0x71, 0x00, 0x75, 0x00, 0x4c, 0x00, 0x2b, 0x00,
+            0x5c, 0x00, 0x46, 0x00, 0x52, 0x00, 0x7b, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x66, 0x00,
+            0x56, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x72, 0x00, 0x61, 0x00, 0x68, 0x00, 0x28, 0x00,
+            0x7d, 0x00, 0x58, 0x00, 0x2a, 0x00, 0x7b, 0x00, 0x28, 0x00, 0x5b, 0x00, 0x54, 0x00,
+            0x3a, 0x00, 0x26, 0x00, 0x52, 0x00, 0x44, 0x00, 0x60, 0x00, 0x50, 0x00, 0x65, 0x00,
+            0x48, 0x00, 0x7d, 0x00, 0x2a, 0x00, 0x74, 0x00, 0x49, 0x00, 0x7b, 0x00, 0x21, 0x00,
+            0x61, 0x00, 0x52, 0x00, 0x43, 0x00, 0x5f, 0x00, 0x5a, 0x00, 0x74, 0x00, 0x5c, 0x00,
+            0x62, 0x00, 0x68, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x2b, 0x00, 0x6f, 0x00, 0x7c, 0x00,
+            0x42, 0x00, 0x67, 0x00, 0x32, 0x00, 0x58, 0x00, 0x35, 0x00, 0x30, 0x00, 0x2f, 0x00,
+            0x2d, 0x00, 0x60, 0x00, 0x62, 0x00, 0x51, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x31, 0x00,
+            0x48, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0x25, 0x00, 0x58, 0x00, 0x4a, 0x00,
+            0x76, 0x00, 0x32, 0x00, 0x62, 0x00, 0x27, 0x00, 0x42, 0x00, 0x40, 0x00, 0x53, 0x00,
+            0x7c, 0x00, 0x7d, 0x00, 0x50, 0x00, 0x3d, 0x00, 0x40, 0x00, 0x76, 0x00, 0x38, 0x00,
+            0x58, 0x00, 0x39, 0x00, 0x63, 0x00, 0x3c, 0x00, 0x5b, 0x00, 0x23, 0x00, 0x53, 0x00,
+            0x7a, 0x00, 0x54, 0x00, 0x74, 0x00, 0x61, 0x00, 0x76, 0x00, 0x4a, 0x00, 0x3e, 0x00,
+            0x33, 0x00, 0x75, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x48, 0x00, 0x33, 0x00, 0x71, 0x00,
+            0x76, 0x00, 0x48, 0x00, 0x71, 0x00, 0x41, 0x00, 0x6f, 0x00, 0x2a, 0x00, 0x67, 0x00,
+            0x70, 0x00, 0x21, 0x00, 0x70, 0x00, 0x4b, 0x00, 0x52, 0x00, 0x58, 0x00, 0x68, 0x00,
+            0x23, 0x00, 0x39, 0x00, 0x46, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x57, 0x00, 0x3a, 0x00,
+            0x79, 0x00, 0x7b, 0x00, 0x6c, 0x00, 0x55, 0x00, 0x33, 0x00, 0x65, 0x00, 0x49, 0x00,
+            0x72, 0x00, 0x30, 0x00, 0x4f, 0x00, 0x41, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x4a, 0x00,
+            0x60, 0x00, 0x79, 0x00, 0x70, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x75, 0x00, 0x44, 0x00,
+            0x59, 0x00, 0x58, 0x00, 0x46, 0x00, 0x3d, 0x00, 0x46, 0x00, 0x74, 0x00, 0x51, 0x00,
+            0x57, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x23, 0x00, 0x45, 0x00, 0x60, 0x00,
+            0x4c, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x74, 0x00, 0x40, 0x00, 0x76, 0x00, 0x75, 0x00,
+            0x74, 0x00, 0x56, 0x00, 0x44, 0x00, 0x29, 0x00, 0x62, 0x00, 0x58, 0x00, 0x31, 0x00,
+            0x78, 0x00, 0x32, 0x00, 0x52, 0x00, 0x4a, 0x00, 0x6b, 0x00, 0x55, 0x00, 0x72, 0x00,
+            0x6f, 0x00, 0x6f, 0x00, 0x4a, 0x00, 0x54, 0x00, 0x7d, 0x00, 0x68, 0x00, 0x3f, 0x00,
+            0x28, 0x00, 0x21, 0x00, 0x53, 0x00, 0x48, 0x00, 0x5a, 0x00, 0x34, 0x00, 0x36, 0x00,
+            0x35, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x75, 0x00, 0x69, 0x00, 0x23, 0x00, 0x75, 0x00,
+            0x55, 0x00, 0x43, 0x00, 0x75, 0x00, 0x2f, 0x00, 0x73, 0x00, 0x62, 0x00, 0x6f, 0x00,
+            0x37, 0x00, 0x4e, 0x00, 0x25, 0x00, 0x25, 0x00, 0x21, 0x00, 0x3d, 0x00, 0x3c, 0x00,
+            0x71, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x36, 0x00, 0x62, 0x00, 0x63, 0x00,
+            0x53, 0x00, 0x54, 0x00, 0x5d, 0x00, 0x61, 0x00, 0x4c, 0x00, 0x28, 0x00, 0x2b, 0x00,
+            0x4c, 0x00, 0x4e, 0x00, 0x66, 0x00, 0x5f, 0x00, 0x4b, 0x00, 0x43, 0x00, 0x75, 0x00,
+            0x45, 0x00, 0x37, 0x00, 0x28, 0x00, 0x56, 0x00, 0x36, 0x00, 0x6a, 0x00, 0x3e, 0x00,
+            0x64, 0x00, 0x34, 0x00, 0x6a, 0x00, 0x7d, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x7a, 0x00,
+            0x3e, 0x00, 0x75, 0x00, 0x38, 0x00, 0x7b, 0x00, 0x42, 0x00, 0x76, 0x00, 0x29, 0x00,
+            0x4c, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x2b, 0x00, 0x51, 0x00,
+            0x47, 0x00, 0x22, 0x00, 0x48, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x44, 0x00, 0x5d, 0x00,
+            0x59, 0x00, 0x63, 0x00, 0x5c, 0x00, 0x24, 0x00, 0x35, 0x00, 0x34, 0x00, 0x70, 0x00,
+            0x69, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(16, dcerpc_state.process_header(&request));
+        assert_eq!(1008, dcerpc_state.process_request_pdu(&request[16..]));
+    }
+
+    #[test]
+    pub fn test_parse_dcerpc() {
+        let request: &[u8] = &[
+            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x45, 0x00, 0x2c, 0x00,
+            0x4d, 0x00, 0x73, 0x00, 0x53, 0x00, 0x59, 0x00, 0x2a, 0x00, 0x4a, 0x00, 0x7a, 0x00,
+            0x3e, 0x00, 0x58, 0x00, 0x21, 0x00, 0x4a, 0x00, 0x30, 0x00, 0x41, 0x00, 0x4b, 0x00,
+            0x4b, 0x00, 0x3c, 0x00, 0x48, 0x00, 0x24, 0x00, 0x38, 0x00, 0x54, 0x00, 0x60, 0x00,
+            0x2d, 0x00, 0x29, 0x00, 0x64, 0x00, 0x5b, 0x00, 0x77, 0x00, 0x3a, 0x00, 0x4c, 0x00,
+            0x24, 0x00, 0x23, 0x00, 0x66, 0x00, 0x43, 0x00, 0x68, 0x00, 0x22, 0x00, 0x55, 0x00,
+            0x29, 0x00, 0x2c, 0x00, 0x4f, 0x00, 0x5a, 0x00, 0x50, 0x00, 0x61, 0x00, 0x2a, 0x00,
+            0x6f, 0x00, 0x2f, 0x00, 0x4d, 0x00, 0x68, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x67, 0x00,
+            0x68, 0x00, 0x68, 0x00, 0x49, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x72, 0x00, 0x53, 0x00,
+            0x4c, 0x00, 0x25, 0x00, 0x4d, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x4f, 0x00, 0x64, 0x00,
+            0x61, 0x00, 0x73, 0x00, 0x24, 0x00, 0x46, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x45, 0x00,
+            0x6f, 0x00, 0x40, 0x00, 0x41, 0x00, 0x33, 0x00, 0x38, 0x00, 0x47, 0x00, 0x71, 0x00,
+            0x5a, 0x00, 0x37, 0x00, 0x7a, 0x00, 0x35, 0x00, 0x6b, 0x00, 0x3c, 0x00, 0x26, 0x00,
+            0x37, 0x00, 0x69, 0x00, 0x75, 0x00, 0x36, 0x00, 0x37, 0x00, 0x47, 0x00, 0x21, 0x00,
+            0x2d, 0x00, 0x69, 0x00, 0x37, 0x00, 0x78, 0x00, 0x5f, 0x00, 0x72, 0x00, 0x4b, 0x00,
+            0x5c, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x52, 0x00, 0x7a, 0x00, 0x49, 0x00, 0x31, 0x00,
+            0x5a, 0x00, 0x7b, 0x00, 0x29, 0x00, 0x3b, 0x00, 0x78, 0x00, 0x3b, 0x00, 0x55, 0x00,
+            0x3e, 0x00, 0x35, 0x00, 0x2b, 0x00, 0x4e, 0x00, 0x4f, 0x00, 0x59, 0x00, 0x38, 0x00,
+            0x2a, 0x00, 0x59, 0x00, 0x6b, 0x00, 0x42, 0x00, 0x4c, 0x00, 0x3e, 0x00, 0x6a, 0x00,
+            0x49, 0x00, 0x2c, 0x00, 0x79, 0x00, 0x6e, 0x00, 0x35, 0x00, 0x4f, 0x00, 0x49, 0x00,
+            0x55, 0x00, 0x35, 0x00, 0x61, 0x00, 0x72, 0x00, 0x77, 0x00, 0x38, 0x00, 0x32, 0x00,
+            0x24, 0x00, 0x46, 0x00, 0x32, 0x00, 0x32, 0x00, 0x27, 0x00, 0x64, 0x00, 0x5a, 0x00,
+            0x77, 0x00, 0x2e, 0x00, 0x37, 0x00, 0x77, 0x00, 0x2e, 0x00, 0x28, 0x00, 0x63, 0x00,
+            0x4f, 0x00, 0x67, 0x00, 0x64, 0x00, 0x39, 0x00, 0x37, 0x00, 0x31, 0x00, 0x30, 0x00,
+            0x28, 0x00, 0x2e, 0x00, 0x6f, 0x00, 0x3e, 0x00, 0x59, 0x00, 0x28, 0x00, 0x67, 0x00,
+            0x52, 0x00, 0x35, 0x00, 0x5a, 0x00, 0x7c, 0x00, 0x56, 0x00, 0x6a, 0x00, 0x5c, 0x00,
+            0x3c, 0x00, 0x30, 0x00, 0x59, 0x00, 0x5c, 0x00, 0x5e, 0x00, 0x38, 0x00, 0x54, 0x00,
+            0x5c, 0x00, 0x5b, 0x00, 0x42, 0x00, 0x62, 0x00, 0x70, 0x00, 0x34, 0x00, 0x5c, 0x00,
+            0x57, 0x00, 0x7a, 0x00, 0x4b, 0x00, 0x2f, 0x00, 0x6b, 0x00, 0x6a, 0x00, 0x4f, 0x00,
+            0x41, 0x00, 0x33, 0x00, 0x52, 0x00, 0x36, 0x00, 0x27, 0x00, 0x30, 0x00, 0x6d, 0x00,
+            0x4a, 0x00, 0x30, 0x00, 0x78, 0x00, 0x46, 0x00, 0x65, 0x00, 0x4e, 0x00, 0x29, 0x00,
+            0x66, 0x00, 0x3f, 0x00, 0x72, 0x00, 0x71, 0x00, 0x75, 0x00, 0x4c, 0x00, 0x2b, 0x00,
+            0x5c, 0x00, 0x46, 0x00, 0x52, 0x00, 0x7b, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x66, 0x00,
+            0x56, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x72, 0x00, 0x61, 0x00, 0x68, 0x00, 0x28, 0x00,
+            0x7d, 0x00, 0x58, 0x00, 0x2a, 0x00, 0x7b, 0x00, 0x28, 0x00, 0x5b, 0x00, 0x54, 0x00,
+            0x3a, 0x00, 0x26, 0x00, 0x52, 0x00, 0x44, 0x00, 0x60, 0x00, 0x50, 0x00, 0x65, 0x00,
+            0x48, 0x00, 0x7d, 0x00, 0x2a, 0x00, 0x74, 0x00, 0x49, 0x00, 0x7b, 0x00, 0x21, 0x00,
+            0x61, 0x00, 0x52, 0x00, 0x43, 0x00, 0x5f, 0x00, 0x5a, 0x00, 0x74, 0x00, 0x5c, 0x00,
+            0x62, 0x00, 0x68, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x2b, 0x00, 0x6f, 0x00, 0x7c, 0x00,
+            0x42, 0x00, 0x67, 0x00, 0x32, 0x00, 0x58, 0x00, 0x35, 0x00, 0x30, 0x00, 0x2f, 0x00,
+            0x2d, 0x00, 0x60, 0x00, 0x62, 0x00, 0x51, 0x00, 0x2a, 0x00, 0x30, 0x00, 0x31, 0x00,
+            0x48, 0x00, 0x5b, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0x25, 0x00, 0x58, 0x00, 0x4a, 0x00,
+            0x76, 0x00, 0x32, 0x00, 0x62, 0x00, 0x27, 0x00, 0x42, 0x00, 0x40, 0x00, 0x53, 0x00,
+            0x7c, 0x00, 0x7d, 0x00, 0x50, 0x00, 0x3d, 0x00, 0x40, 0x00, 0x76, 0x00, 0x38, 0x00,
+            0x58, 0x00, 0x39, 0x00, 0x63, 0x00, 0x3c, 0x00, 0x5b, 0x00, 0x23, 0x00, 0x53, 0x00,
+            0x7a, 0x00, 0x54, 0x00, 0x74, 0x00, 0x61, 0x00, 0x76, 0x00, 0x4a, 0x00, 0x3e, 0x00,
+            0x33, 0x00, 0x75, 0x00, 0x66, 0x00, 0x2d, 0x00, 0x48, 0x00, 0x33, 0x00, 0x71, 0x00,
+            0x76, 0x00, 0x48, 0x00, 0x71, 0x00, 0x41, 0x00, 0x6f, 0x00, 0x2a, 0x00, 0x67, 0x00,
+            0x70, 0x00, 0x21, 0x00, 0x70, 0x00, 0x4b, 0x00, 0x52, 0x00, 0x58, 0x00, 0x68, 0x00,
+            0x23, 0x00, 0x39, 0x00, 0x46, 0x00, 0x4d, 0x00, 0x51, 0x00, 0x57, 0x00, 0x3a, 0x00,
+            0x79, 0x00, 0x7b, 0x00, 0x6c, 0x00, 0x55, 0x00, 0x33, 0x00, 0x65, 0x00, 0x49, 0x00,
+            0x72, 0x00, 0x30, 0x00, 0x4f, 0x00, 0x41, 0x00, 0x6e, 0x00, 0x31, 0x00, 0x4a, 0x00,
+            0x60, 0x00, 0x79, 0x00, 0x70, 0x00, 0x4f, 0x00, 0x58, 0x00, 0x75, 0x00, 0x44, 0x00,
+            0x59, 0x00, 0x58, 0x00, 0x46, 0x00, 0x3d, 0x00, 0x46, 0x00, 0x74, 0x00, 0x51, 0x00,
+            0x57, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x23, 0x00, 0x45, 0x00, 0x60, 0x00,
+            0x4c, 0x00, 0x72, 0x00, 0x4e, 0x00, 0x74, 0x00, 0x40, 0x00, 0x76, 0x00, 0x75, 0x00,
+            0x74, 0x00, 0x56, 0x00, 0x44, 0x00, 0x29, 0x00, 0x62, 0x00, 0x58, 0x00, 0x31, 0x00,
+            0x78, 0x00, 0x32, 0x00, 0x52, 0x00, 0x4a, 0x00, 0x6b, 0x00, 0x55, 0x00, 0x72, 0x00,
+            0x6f, 0x00, 0x6f, 0x00, 0x4a, 0x00, 0x54, 0x00, 0x7d, 0x00, 0x68, 0x00, 0x3f, 0x00,
+            0x28, 0x00, 0x21, 0x00, 0x53, 0x00, 0x48, 0x00, 0x5a, 0x00, 0x34, 0x00, 0x36, 0x00,
+            0x35, 0x00, 0x64, 0x00, 0x4e, 0x00, 0x75, 0x00, 0x69, 0x00, 0x23, 0x00, 0x75, 0x00,
+            0x55, 0x00, 0x43, 0x00, 0x75, 0x00, 0x2f, 0x00, 0x73, 0x00, 0x62, 0x00, 0x6f, 0x00,
+            0x37, 0x00, 0x4e, 0x00, 0x25, 0x00, 0x25, 0x00, 0x21, 0x00, 0x3d, 0x00, 0x3c, 0x00,
+            0x71, 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x30, 0x00, 0x36, 0x00, 0x62, 0x00, 0x63, 0x00,
+            0x53, 0x00, 0x54, 0x00, 0x5d, 0x00, 0x61, 0x00, 0x4c, 0x00, 0x28, 0x00, 0x2b, 0x00,
+            0x4c, 0x00, 0x4e, 0x00, 0x66, 0x00, 0x5f, 0x00, 0x4b, 0x00, 0x43, 0x00, 0x75, 0x00,
+            0x45, 0x00, 0x37, 0x00, 0x28, 0x00, 0x56, 0x00, 0x36, 0x00, 0x6a, 0x00, 0x3e, 0x00,
+            0x64, 0x00, 0x34, 0x00, 0x6a, 0x00, 0x7d, 0x00, 0x4a, 0x00, 0x66, 0x00, 0x7a, 0x00,
+            0x3e, 0x00, 0x75, 0x00, 0x38, 0x00, 0x7b, 0x00, 0x42, 0x00, 0x76, 0x00, 0x29, 0x00,
+            0x4c, 0x00, 0x65, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x2b, 0x00, 0x51, 0x00,
+            0x47, 0x00, 0x22, 0x00, 0x48, 0x00, 0x3d, 0x00, 0x49, 0x00, 0x44, 0x00, 0x5d, 0x00,
+            0x59, 0x00, 0x63, 0x00, 0x5c, 0x00, 0x24, 0x00, 0x35, 0x00, 0x34, 0x00, 0x70, 0x00,
+            0x69, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request, core::STREAM_TOSERVER)
+        );
+        if let Some(hdr) = dcerpc_state.header {
+            assert_eq!(0, hdr.hdrtype);
+            assert_eq!(5, hdr.rpc_vers);
+            assert_eq!(1024, hdr.frag_length);
+        }
+        if let Some(req) = dcerpc_state.request {
+            assert_eq!(11, req.ctxid);
+            assert_eq!(9, req.opnum);
+            assert_eq!(1, req.first_request_seen);
+            assert_eq!(1000, req.stub_data_buffer_len);
+            assert_eq!(true, req.stub_data_buffer_reset);
+        }
+    }
+
+    #[test]
+    pub fn test_parse_bind_pdu() {
+        let bind1: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x01, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e,
+            0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let bind2: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x02, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x01, 0x00, 0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e,
+            0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x67, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(), // TODO ASK if this is correct?
+            dcerpc_state.handle_input_data(&bind2, core::STREAM_TOSERVER)
+        );
+    }
+
+    #[test]
+    pub fn test_parse_bind_frag_1() {
+        let bind1: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0xc7, 0x70, 0x0d, 0x3e, 0x71, 0x37, 0x39, 0x0d, 0x3a, 0x4f,
+            0xd3, 0xdc, 0xca, 0x49, 0xe8, 0xa3, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x84, 0xb6, 0x55, 0x75, 0xdb, 0x9e, 0xba, 0x54,
+            0x56, 0xd3, 0x45, 0x10, 0xb7, 0x7a, 0x2a, 0xe2, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6e, 0x39, 0x21, 0x24, 0x70, 0x6f,
+            0x41, 0x57, 0x54, 0x70, 0xb8, 0xc3, 0x5e, 0x89, 0x3b, 0x43, 0x03, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x39, 0x6a, 0x86, 0x5d,
+            0x24, 0x0f, 0xd2, 0xf7, 0xb6, 0xce, 0x95, 0x9c, 0x54, 0x1d, 0x3a, 0xdb, 0x02, 0x00,
+            0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x12, 0xa5,
+            0xdd, 0xc5, 0x55, 0xce, 0xc3, 0x46, 0xbd, 0xa0, 0x94, 0x39, 0x3c, 0x0d, 0x9b, 0x5b,
+            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
+            0x87, 0x1c, 0x8b, 0x6e, 0x11, 0xa8, 0x67, 0x98, 0xd4, 0x5d, 0xf6, 0x8a, 0x2f, 0x33,
+            0x24, 0x7b, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
+            0x01, 0x00, 0x9b, 0x82, 0x13, 0xd1, 0x28, 0xe0, 0x63, 0xf3, 0x62, 0xee, 0x76, 0x73,
+            0xf9, 0xac, 0x3d, 0x2e, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x07, 0x00, 0x01, 0x00, 0xa9, 0xd4, 0x73, 0xf2, 0xed, 0xad, 0xe8, 0x82, 0xf8, 0xcf,
+            0x9d, 0x9f, 0x66, 0xe6, 0x43, 0x37, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x2b, 0x85, 0x38, 0x4f, 0x73, 0x96, 0xb1,
+            0x73, 0xe1, 0x59, 0xbe, 0x9d, 0xe2, 0x6c, 0x07, 0x05, 0x00, 0x01, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+        ];
+        let bind2: &[u8] = &[
+            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xbf, 0xfa, 0xbb, 0xa4, 0x9e, 0x5c,
+            0x80, 0x61, 0xb5, 0x8b, 0x79, 0x69, 0xa6, 0x32, 0x88, 0x77, 0x01, 0x00, 0x01, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x39, 0xa8, 0x2c, 0x39,
+            0x73, 0x50, 0x06, 0x8d, 0xf2, 0x37, 0x1e, 0x1e, 0xa8, 0x8f, 0x46, 0x98, 0x02, 0x00,
+            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x91, 0x13,
+            0xd0, 0xa7, 0xef, 0xc4, 0xa7, 0x96, 0x0c, 0x4a, 0x0d, 0x29, 0x80, 0xd3, 0xfe, 0xbf,
+            0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
+            0xcc, 0x2b, 0x55, 0x1d, 0xd4, 0xa4, 0x0d, 0xfb, 0xcb, 0x6f, 0x86, 0x36, 0xa6, 0x57,
+            0xc3, 0x21, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00,
+            0x01, 0x00, 0x43, 0x7b, 0x07, 0xee, 0x85, 0xa8, 0xb9, 0x3a, 0x0f, 0xf9, 0x83, 0x70,
+            0xe6, 0x0b, 0x4f, 0x33, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x0e, 0x00, 0x01, 0x00, 0x9c, 0x6a, 0x15, 0x8c, 0xd6, 0x9c, 0xa6, 0xc3, 0xb2, 0x9e,
+            0x62, 0x9f, 0x3d, 0x8e, 0x47, 0x73, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
+            0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind2, core::STREAM_TOSERVER)
+        );
+        if let Some(ref bind) = dcerpc_state.bind {
+            assert_eq!(16, bind.numctxitems);
+            assert_eq!(0, dcerpc_state.bytes_consumed); // because the buffer is cleared after a query is complete
+        }
+    }
+
+    #[test]
+    pub fn test_parse_bind_frag_2() {
+        let request1: &[u8] = &[
+            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
+            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+        ];
+        let request2: &[u8] = &[0x0D, 0x0E];
+        let request3: &[u8] = &[0x0F, 0x10, 0x11, 0x12, 0x13, 0x14];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request2, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request3, core::STREAM_TOSERVER)
+        );
+        if let Some(ref req) = dcerpc_state.request {
+            assert_eq!(20, req.stub_data_buffer_len);
+        }
+    }
+
+    #[test]
+    pub fn test_parse_bind_frag_3() {
+        let request1: &[u8] = &[
+            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
+            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
+        );
+    }
+
+    #[test]
+    pub fn test_parse_bind_frag_4() {
+        let request1: &[u8] = &[
+            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
+            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
+        );
+    }
+
+    #[test]
+    pub fn test_parse_dcerpc_frag_1() {
+        let fault: &[u8] = &[
+            0x05, 0x00, 0x03, 0x03, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xf7, 0x06, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00,
+        ];
+        let request1: &[u8] = &[0x05, 0x00];
+        let request2: &[u8] = &[
+            0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+            0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::err(),
+            dcerpc_state.handle_input_data(&fault, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request2, core::STREAM_TOSERVER)
+        );
+        if let Some(ref req) = dcerpc_state.request {
+            assert_eq!(12, req.stub_data_buffer_len);
+        }
+    }
+
+    #[test]
+    pub fn test_parse_dcerpc_frag_2() {
+        let request1: &[u8] = &[
+            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04,
+            0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+        ];
+        let request2: &[u8] = &[0x05, 0x00];
+        let request3: &[u8] = &[
+            0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+            0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request2, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&request3, core::STREAM_TOSERVER)
+        );
+    }
+
+    #[test]
+    pub fn test_parse_dcerpc_back_frag() {
+        let bind_ack1: &[u8] = &[
+            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x48, 0x1a, 0x00, 0x00,
+        ];
+        let bind_ack2: &[u8] = &[
+            0x0c, 0x00, 0x5c, 0x50, 0x49, 0x50, 0x45, 0x5c, 0x6c, 0x73, 0x61, 0x73, 0x73, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        dcerpc_state.data_needed_for_dir = core::STREAM_TOCLIENT;
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind_ack1, core::STREAM_TOCLIENT)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind_ack2, core::STREAM_TOCLIENT)
+        );
+    }
+
+    #[test]
+    // Check if the parser accepts bind pdus that have context ids starting
+    // from a non-zero value.
+    pub fn test_parse_bind_pdu_ctx_id_non_zero() {
+        let bindbuf: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x7f, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        let expected_uuid: &[u8] = &[
+            0x00, 0x00, 0x01, 0xa0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x46,
+        ];
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bindbuf, core::STREAM_TOSERVER)
+        );
+        if let Some(ref bind) = dcerpc_state.bind {
+            let bind_uuid = &bind.uuid_list[0].uuid;
+            assert_eq!(1, bind.uuid_list.len());
+            assert_eq!(
+                cmp::Ordering::Equal,
+                bind_uuid
+                    .iter()
+                    .zip(expected_uuid)
+                    .map(|(x, y)| x.cmp(y))
+                    .find(|&ord| ord != cmp::Ordering::Equal)
+                    .unwrap_or(bind_uuid.len().cmp(&expected_uuid.len()))
+            );
+        }
+    }
+
+    #[test]
+    // Check for endless loop with bind PDUs (Imported from C code)
+    pub fn test_parse_bind_pdu_infinite_loop() {
+        let bindbuf: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x7f, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04,
+            0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02,
+            0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+            0x01, 0x02, 0x03, 0x04, 0xFF, /* ka boom - endless loop */
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bindbuf, core::STREAM_TOSERVER)
+        );
+    }
+
+    #[test]
+    // Check for endless loop with bind_ack PDUs (Imported from C code)
+    pub fn test_parse_bindack_pdu_infinite_loop() {
+        let bind_ack: &[u8] = &[
+            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7f, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0xfd, 0x04, 0x01, 0x00, 0x04, 0x00, 0x31, 0x33,
+            0x35, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x01, 0x02, 0x03, 0x04,
+            0xFF,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        dcerpc_state.data_needed_for_dir = core::STREAM_TOCLIENT;
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind_ack, core::STREAM_TOCLIENT)
+        );
+    }
+
+    #[test]
+    // Check for correct internal ids for bind_acks
+    pub fn test_parse_bindack_internal_ids() {
+        let bind1: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x50, 0x08, 0x43, 0x95, 0x43, 0x5a, 0x8b, 0xb2, 0xf4, 0xc5,
+            0xb9, 0xee, 0x67, 0x55, 0x7c, 0x19, 0x00, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xda, 0xc2, 0xbc, 0x9b, 0x35, 0x2e, 0xd4, 0xc9,
+            0x1f, 0x85, 0x01, 0xe6, 0x4e, 0x5a, 0x5e, 0xd4, 0x04, 0x00, 0x03, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0xb2, 0x97, 0xcc, 0x14, 0x6f, 0x70,
+            0x0d, 0xa5, 0x33, 0xd7, 0xf4, 0xe3, 0x8e, 0xb2, 0x2a, 0x1e, 0x05, 0x00, 0x02, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x96, 0x4e, 0xa6, 0xf6,
+            0xb2, 0x4b, 0xae, 0xb3, 0x21, 0xf4, 0x97, 0x7c, 0xcd, 0xa7, 0x08, 0xb0, 0x00, 0x00,
+            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0xbc, 0xc0,
+            0xf7, 0x71, 0x3f, 0x71, 0x54, 0x44, 0x22, 0xa8, 0x55, 0x0f, 0x98, 0x83, 0x1f, 0xfe,
+            0x04, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
+            0xbe, 0x52, 0xf2, 0x58, 0x4a, 0xc3, 0xb5, 0xd0, 0xba, 0xac, 0xda, 0xf0, 0x12, 0x99,
+            0x38, 0x6e, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
+            0x01, 0x00, 0xdb, 0xfa, 0x73, 0x01, 0xb3, 0x81, 0x01, 0xd4, 0x7f, 0xa0, 0x36, 0xb1,
+            0x97, 0xae, 0x29, 0x7f, 0x01, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x07, 0x00, 0x01, 0x00, 0x89, 0xbe, 0x41, 0x1d, 0x38, 0x75, 0xf5, 0xb5, 0xad, 0x27,
+            0x73, 0xf1, 0xb0, 0x7a, 0x28, 0x82, 0x05, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0xf6, 0x87, 0x09, 0x93, 0xb8, 0xa8, 0x20, 0xc4,
+            0xb8, 0x63, 0xe6, 0x95, 0xed, 0x59, 0xee, 0x3f, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0x92, 0x77, 0x92, 0x68, 0x3e, 0xa4,
+            0xbc, 0x3f, 0x44, 0x33, 0x0e, 0xb8, 0x33, 0x0a, 0x2f, 0xdf, 0x01, 0x00, 0x02, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0xa1, 0x03, 0xd2, 0xa9,
+            0xd2, 0x16, 0xc9, 0x89, 0x67, 0x18, 0x3e, 0xb1, 0xee, 0x6b, 0xf9, 0x18, 0x02, 0x00,
+            0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x2f, 0x09,
+            0x5e, 0x74, 0xec, 0xa0, 0xbb, 0xc1, 0x60, 0x18, 0xf1, 0x93, 0x04, 0x17, 0x11, 0xf9,
+            0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
+            0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e,
+            0xe1, 0x88, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let bind_ack1: &[u8] = &[
+            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0xc1, 0x2b, 0x00, 0x00, 0x0e, 0x00, 0x5c, 0x50,
+            0x49, 0x50, 0x45, 0x5c, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x00, 0x0d, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let bind2: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0xc7, 0x70, 0x0d, 0x3e, 0x71, 0x37, 0x39, 0x0d, 0x3a, 0x4f,
+            0xd3, 0xdc, 0xca, 0x49, 0xe8, 0xa3, 0x05, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x84, 0xb6, 0x55, 0x75, 0xdb, 0x9e, 0xba, 0x54,
+            0x56, 0xd3, 0x45, 0x10, 0xb7, 0x7a, 0x2a, 0xe2, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x6e, 0x39, 0x21, 0x24, 0x70, 0x6f,
+            0x41, 0x57, 0x54, 0x70, 0xb8, 0xc3, 0x5e, 0x89, 0x3b, 0x43, 0x03, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x39, 0x6a, 0x86, 0x5d,
+            0x24, 0x0f, 0xd2, 0xf7, 0xb6, 0xce, 0x95, 0x9c, 0x54, 0x1d, 0x3a, 0xdb, 0x02, 0x00,
+            0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x12, 0xa5,
+            0xdd, 0xc5, 0x55, 0xce, 0xc3, 0x46, 0xbd, 0xa0, 0x94, 0x39, 0x3c, 0x0d, 0x9b, 0x5b,
+            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
+            0x87, 0x1c, 0x8b, 0x6e, 0x11, 0xa8, 0x67, 0x98, 0xd4, 0x5d, 0xf6, 0x8a, 0x2f, 0x33,
+            0x24, 0x7b, 0x05, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
+            0x01, 0x00, 0x9b, 0x82, 0x13, 0xd1, 0x28, 0xe0, 0x63, 0xf3, 0x62, 0xee, 0x76, 0x73,
+            0xf9, 0xac, 0x3d, 0x2e, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x07, 0x00, 0x01, 0x00, 0xa9, 0xd4, 0x73, 0xf2, 0xed, 0xad, 0xe8, 0x82, 0xf8, 0xcf,
+            0x9d, 0x9f, 0x66, 0xe6, 0x43, 0x37, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x06, 0x2b, 0x85, 0x38, 0x4f, 0x73, 0x96, 0xb1,
+            0x73, 0xe1, 0x59, 0xbe, 0x9d, 0xe2, 0x6c, 0x07, 0x05, 0x00, 0x01, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xbf, 0xfa, 0xbb, 0xa4, 0x9e, 0x5c,
+            0x80, 0x61, 0xb5, 0x8b, 0x79, 0x69, 0xa6, 0x32, 0x88, 0x77, 0x01, 0x00, 0x01, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x39, 0xa8, 0x2c, 0x39,
+            0x73, 0x50, 0x06, 0x8d, 0xf2, 0x37, 0x1e, 0x1e, 0xa8, 0x8f, 0x46, 0x98, 0x02, 0x00,
+            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x91, 0x13,
+            0xd0, 0xa7, 0xef, 0xc4, 0xa7, 0x96, 0x0c, 0x4a, 0x0d, 0x29, 0x80, 0xd3, 0xfe, 0xbf,
+            0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00,
+            0xcc, 0x2b, 0x55, 0x1d, 0xd4, 0xa4, 0x0d, 0xfb, 0xcb, 0x6f, 0x86, 0x36, 0xa6, 0x57,
+            0xc3, 0x21, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00,
+            0x01, 0x00, 0x43, 0x7b, 0x07, 0xee, 0x85, 0xa8, 0xb9, 0x3a, 0x0f, 0xf9, 0x83, 0x70,
+            0xe6, 0x0b, 0x4f, 0x33, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x0e, 0x00, 0x01, 0x00, 0x9c, 0x6a, 0x15, 0x8c, 0xd6, 0x9c, 0xa6, 0xc3, 0xb2, 0x9e,
+            0x62, 0x9f, 0x3d, 0x8e, 0x47, 0x73, 0x02, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x0f, 0x00, 0x01, 0x00, 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
+            0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88, 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00,
+        ];
+        let bind_ack2: &[u8] = &[
+            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0xc2, 0x2b, 0x00, 0x00, 0x0e, 0x00, 0x5c, 0x50,
+            0x49, 0x50, 0x45, 0x5c, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x00, 0x10, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let bind3: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0xa4, 0x7f, 0x8e, 0xc6, 0xef, 0x56, 0x9b, 0x63, 0x92, 0xfa,
+            0x08, 0xb3, 0x35, 0xe2, 0xa5, 0x81, 0x00, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x9f, 0xfc, 0x78, 0xd2, 0x5f, 0x16, 0x0b, 0xbc,
+            0xc6, 0xdb, 0x5d, 0xef, 0xde, 0x54, 0xa2, 0x6f, 0x04, 0x00, 0x01, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x78, 0xb8, 0x96, 0xc7, 0x2f, 0xda,
+            0x11, 0x6b, 0xd1, 0x28, 0x68, 0xe1, 0xd6, 0x71, 0xac, 0x9d, 0x03, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0xcf, 0xf4, 0xd7, 0x37,
+            0x03, 0xda, 0xcc, 0xe3, 0x3e, 0x34, 0x7f, 0x67, 0x99, 0x91, 0x41, 0x3d, 0x01, 0x00,
+            0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x48, 0xeb,
+            0x32, 0xf0, 0x27, 0xd5, 0x9d, 0xd0, 0x1e, 0xc6, 0x48, 0x46, 0x97, 0xe9, 0xdb, 0x09,
+            0x05, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00,
+            0x82, 0xec, 0x0d, 0x08, 0xf2, 0x8f, 0x22, 0x57, 0x42, 0x9b, 0xce, 0xa8, 0x74, 0x16,
+            0xc6, 0xec, 0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00,
+            0x01, 0x00, 0x2e, 0x00, 0x70, 0x44, 0xee, 0xc9, 0x30, 0x6b, 0xf4, 0x34, 0x1e, 0x3d,
+            0x35, 0x0f, 0xf7, 0xf7, 0x00, 0x00, 0x01, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+            0x07, 0x00, 0x01, 0x00, 0x59, 0x04, 0x39, 0x3f, 0x59, 0x87, 0x14, 0x0e, 0x76, 0x8d,
+            0x17, 0xc2, 0x47, 0xfa, 0x67, 0x7f, 0x04, 0x00, 0x02, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x30, 0xd6, 0xed, 0x2e, 0x57, 0xfa, 0xf4, 0x72,
+            0x6c, 0x10, 0x0d, 0xe5, 0x51, 0x7f, 0xd0, 0x39, 0x02, 0x00, 0x01, 0x00, 0x04, 0x5d,
+            0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60,
+            0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x01, 0x00, 0xea, 0x8b, 0x84, 0x4d, 0x44, 0x43,
+            0xc1, 0x94, 0x75, 0xe2, 0x81, 0x48, 0xd8, 0x77, 0xd9, 0xce, 0x05, 0x00, 0x00, 0x00,
+            0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10,
+            0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x01, 0x00, 0x89, 0x4f, 0xe7, 0x95,
+            0xa3, 0xc1, 0x62, 0x36, 0x26, 0x9e, 0x67, 0xdb, 0x2c, 0x52, 0x89, 0xd3, 0x01, 0x00,
+            0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
+            0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x78, 0x56,
+            0x34, 0x12, 0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab,
+            0x01, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let bind_ack3: &[u8] = &[
+            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x1a, 0x33, 0x00, 0x00, 0x0e, 0x00, 0x5c, 0x70,
+            0x69, 0x70, 0x65, 0x5c, 0x73, 0x70, 0x6f, 0x6f, 0x6c, 0x73, 0x73, 0x00, 0x0c, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8,
+            0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        let expected_uuid1 = vec![
+            0x4b, 0x32, 0x4f, 0xc8, 0x16, 0x70, 0x01, 0xd3, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e,
+            0xe1, 0x88,
+        ];
+        let expected_uuid2 = vec![
+            0x4b, 0x32, 0x4f, 0xc8, 0x16, 0x70, 0x01, 0xd3, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e,
+            0xe1, 0x88,
+        ];
+        let expected_uuid3 = vec![
+            0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0xab, 0xcd, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67,
+            0x89, 0xab,
+        ];
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind_ack1, core::STREAM_TOCLIENT)
+        );
+        if let Some(ref back) = dcerpc_state.bindack {
+            assert_eq!(1, back.accepted_uuid_list.len());
+            assert_eq!(12, back.accepted_uuid_list[0].ctxid);
+            assert_eq!(expected_uuid1, back.accepted_uuid_list[0].uuid);
+        }
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind2, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind_ack2, core::STREAM_TOCLIENT)
+        );
+        if let Some(ref back) = dcerpc_state.bindack {
+            assert_eq!(1, back.accepted_uuid_list.len());
+            assert_eq!(15, back.accepted_uuid_list[0].ctxid);
+            assert_eq!(expected_uuid2, back.accepted_uuid_list[0].uuid);
+        }
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind3, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(&bind_ack3, core::STREAM_TOCLIENT)
+        );
+        if let Some(ref back) = dcerpc_state.bindack {
+            assert_eq!(1, back.accepted_uuid_list.len());
+            dcerpc_state.data_needed_for_dir = core::STREAM_TOSERVER;
+            assert_eq!(11, back.accepted_uuid_list[0].ctxid);
+            assert_eq!(expected_uuid3, back.accepted_uuid_list[0].uuid);
+        }
+    }
+
+    #[test]
+    pub fn test_bind_acks_alter_contexts_internal_ids() {
+        let bind: &[u8] = &[
+            0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x40, 0xfd, 0x2c, 0x34, 0x6c, 0x3c, 0xce, 0x11, 0xa8, 0x93,
+            0x08, 0x00, 0x2b, 0x2e, 0x9c, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let bindack: &[u8] = &[
+            0x05, 0x00, 0x0c, 0x03, 0x10, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x7d, 0xd8, 0x00, 0x00, 0x0d, 0x00, 0x5c, 0x70,
+            0x69, 0x70, 0x65, 0x5c, 0x6c, 0x6c, 0x73, 0x72, 0x70, 0x63, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
+            0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+        let alter_context: &[u8] = &[
+            0x05, 0x00, 0x0e, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+            0x01, 0x00, 0x01, 0x00, 0xd0, 0x4c, 0x67, 0x57, 0x00, 0x52, 0xce, 0x11, 0xa8, 0x97,
+            0x08, 0x00, 0x2b, 0x2e, 0x9c, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let alter_context_resp: &[u8] = &[
+            0x05, 0x00, 0x0f, 0x03, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x7d, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c,
+            0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00,
+        ];
+
+        let mut dcerpc_state = DCERPCState::new();
+        let expected_uuid1 = vec![
+            0x34, 0x2c, 0xfd, 0x40, 0x3c, 0x6c, 0x11, 0xce, 0xa8, 0x93, 0x08, 0x00, 0x2b, 0x2e,
+            0x9c, 0x6d,
+        ];
+        let expected_uuid2 = vec![
+            0x57, 0x67, 0x4c, 0xd0, 0x52, 0x00, 0x11, 0xce, 0xa8, 0x97, 0x08, 0x00, 0x2b, 0x2e,
+            0x9c, 0x6d,
+        ];
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(bind, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(bindack, core::STREAM_TOCLIENT)
+        );
+        if let Some(ref back) = dcerpc_state.bindack {
+            assert_eq!(1, back.accepted_uuid_list.len());
+            assert_eq!(0, back.accepted_uuid_list[0].ctxid);
+            assert_eq!(expected_uuid1, back.accepted_uuid_list[0].uuid);
+        }
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(alter_context, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(alter_context_resp, core::STREAM_TOCLIENT)
+        );
+        if let Some(ref back) = dcerpc_state.bindack {
+            assert_eq!(1, back.accepted_uuid_list.len());
+            assert_eq!(1, back.accepted_uuid_list[0].ctxid);
+            assert_eq!(expected_uuid2, back.accepted_uuid_list[0].uuid);
+        }
+    }
+
+    #[test]
+    pub fn test_parse_dcerpc_frag_3() {
+        let request1: &[u8] = &[
+            0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x0c, 0x00,
+        ];
+        let request2: &[u8] = &[
+            0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+            0x09, 0x0A, 0x0B, 0x0C, 0xFF, 0xFF,
+        ];
+        let mut dcerpc_state = DCERPCState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(request1, core::STREAM_TOSERVER)
+        );
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpc_state.handle_input_data(request2, core::STREAM_TOSERVER)
+        );
+        if let Some(ref req) = dcerpc_state.request {
+            assert_eq!(2, req.opnum);
+            assert_eq!(0, req.ctxid);
+            assert_eq!(14, req.stub_data_buffer_len);
+        }
+    }
+}
diff --git a/rust/src/dcerpc/dcerpc_udp.rs b/rust/src/dcerpc/dcerpc_udp.rs
new file mode 100644 (file)
index 0000000..bf69611
--- /dev/null
@@ -0,0 +1,512 @@
+/* Copyright (C) 2020 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use std::mem::transmute;
+
+use crate::applayer::AppLayerResult;
+use crate::core;
+use crate::dcerpc::dcerpc::{
+    DCERPCRequest, DCERPCResponse, DCERPCUuidEntry, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE,
+    PFC_FIRST_FRAG,
+};
+use crate::dcerpc::parser;
+use crate::log::*;
+use std::cmp;
+
+// Constant DCERPC UDP Header length
+pub const DCERPC_UDP_HDR_LEN: i32 = 80;
+
+#[derive(Debug)]
+pub struct DCERPCHdrUdp {
+    pub rpc_vers: u8,
+    pub pkt_type: u8,
+    pub flags1: u8,
+    pub flags2: u8,
+    pub drep: Vec<u8>,
+    pub serial_hi: u8,
+    pub objectuuid: Vec<u8>,
+    pub interfaceuuid: Vec<u8>,
+    pub activityuuid: Vec<u8>,
+    pub server_boot: u32,
+    pub if_vers: u32,
+    pub seqnum: u32,
+    pub opnum: u16,
+    pub ihint: u16,
+    pub ahint: u16,
+    pub fraglen: u16,
+    pub fragnum: u16,
+    pub auth_proto: u8,
+    pub serial_lo: u8,
+}
+
+#[derive(Debug)]
+pub struct DCERPCUDPState {
+    pub header: Option<DCERPCHdrUdp>,
+    pub request: Option<DCERPCRequest>,
+    pub response: Option<DCERPCResponse>,
+    pub fraglenleft: u16,
+    pub uuid_entry: Option<DCERPCUuidEntry>,
+    pub uuid_list: Vec<DCERPCUuidEntry>,
+    pub de_state: Option<*mut core::DetectEngineState>,
+}
+
+impl DCERPCUDPState {
+    pub fn new() -> DCERPCUDPState {
+        return DCERPCUDPState {
+            header: None,
+            request: None,
+            response: None,
+            fraglenleft: 0,
+            uuid_entry: None,
+            uuid_list: Vec::new(),
+            de_state: None,
+        };
+    }
+
+    fn new_request(&mut self) {
+        let request = DCERPCRequest::new();
+        self.request = Some(request);
+    }
+
+    fn new_response(&mut self) {
+        let response = DCERPCResponse::new();
+        self.response = Some(response);
+    }
+    fn create_new_query(&mut self, pkt_type: u8) {
+        match pkt_type {
+            DCERPC_TYPE_REQUEST => {
+                self.new_request();
+            }
+            DCERPC_TYPE_RESPONSE => {
+                self.new_response();
+            }
+            _ => {
+                SCLogDebug!("Unrecognized packet type");
+            }
+        }
+    }
+
+    fn get_hdr_pkt_type(&self) -> Option<u8> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = &self.header {
+            return Some(hdr.pkt_type);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    fn get_hdr_flags1(&self) -> Option<u8> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = &self.header {
+            return Some(hdr.flags1);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn get_hdr_fraglen(&self) -> Option<u16> {
+        debug_validate_bug_on!(self.header.is_none());
+        if let Some(ref hdr) = &self.header {
+            return Some(hdr.fraglen);
+        }
+        // Shouldn't happen
+        None
+    }
+
+    pub fn handle_fragment_data(&mut self, input: &[u8], input_len: u16) -> u16 {
+        let mut retval: u16 = 0;
+        let hdrflags1 = self.get_hdr_flags1().unwrap_or(0);
+        let fraglenleft = self.fraglenleft;
+
+        // Update the stub params based on the packet type
+        match self.get_hdr_pkt_type().unwrap_or(0) {
+            DCERPC_TYPE_REQUEST => {
+                if let Some(ref mut req) = self.request {
+                    retval = evaluate_stub_params(
+                        input,
+                        input_len,
+                        hdrflags1,
+                        fraglenleft,
+                        &mut req.stub_data_buffer,
+                        &mut req.stub_data_buffer_len,
+                    );
+                }
+            }
+            DCERPC_TYPE_RESPONSE => {
+                if let Some(ref mut resp) = self.response {
+                    retval = evaluate_stub_params(
+                        input,
+                        input_len,
+                        hdrflags1,
+                        fraglenleft,
+                        &mut resp.stub_data_buffer,
+                        &mut resp.stub_data_buffer_len,
+                    );
+                }
+            }
+            _ => {
+                SCLogDebug!("Unrecognized packet type");
+                return 0;
+            }
+        }
+        // Update the remaining fragment length
+        self.fraglenleft -= retval;
+
+        retval
+    }
+
+    pub fn process_header(&mut self, input: &[u8]) -> i32 {
+        match parser::parse_dcerpc_udp_header(input) {
+            Ok((leftover_bytes, header)) => {
+                if header.rpc_vers != 4 {
+                    SCLogDebug!("DCERPC UDP Header did not validate.");
+                    return -1;
+                }
+                let mut uuidentry = DCERPCUuidEntry::new();
+                let auuid = header.activityuuid.to_vec();
+                uuidentry.uuid = auuid;
+                self.uuid_list.push(uuidentry);
+                self.header = Some(header);
+                (input.len() - leftover_bytes.len()) as i32
+            }
+            Err(nom::Err::Incomplete(_)) => {
+                // Insufficient data.
+                SCLogDebug!("Insufficient data while parsing DCERPC request");
+                -1
+            }
+            Err(_) => {
+                // Error, probably malformed data.
+                SCLogDebug!("An error occurred while parsing DCERPC request");
+                -1
+            }
+        }
+    }
+
+    pub fn handle_input_data(&mut self, input: &[u8]) -> AppLayerResult {
+        // Input length should at least be header length
+        if (input.len() as i32) < DCERPC_UDP_HDR_LEN {
+            return AppLayerResult::err();
+        }
+        // Call header parser first
+        let mut parsed = self.process_header(input);
+        if parsed == -1 {
+            return AppLayerResult::err();
+        }
+
+        let mut input_left = input.len() as i32 - parsed;
+        let pkt_type = self.get_hdr_pkt_type().unwrap_or(0);
+        let fraglen = self.get_hdr_fraglen().unwrap_or(0);
+        self.fraglenleft = fraglen;
+        self.create_new_query(pkt_type);
+        // Parse rest of the body
+        while parsed >= DCERPC_UDP_HDR_LEN && parsed < fraglen as i32 && input_left > 0 {
+            let retval = self.handle_fragment_data(&input[parsed as usize..], input_left as u16);
+            if retval > 0 && retval <= input_left as u16 {
+                parsed += retval as i32;
+                input_left -= retval as i32;
+            } else if input_left > 0 {
+                SCLogDebug!("Error parsing DCERPC UDP Fragment Data");
+                parsed -= input_left;
+                input_left = 0;
+            }
+        }
+        return AppLayerResult::ok();
+    }
+}
+
+fn evaluate_stub_params(
+    input: &[u8],
+    input_len: u16,
+    hdrflags: u8,
+    lenleft: u16,
+    stub_data_buffer: &mut Vec<u8>,
+    stub_data_buffer_len: &mut u16,
+) -> u16 {
+    let stub_len: u16;
+    stub_len = cmp::min(lenleft, input_len);
+    if stub_len == 0 {
+        return 0;
+    }
+    // If the UDP frag is the the first frag irrespective of it being a part of
+    // a multi frag PDU or not, it indicates the previous PDU's stub would
+    // have been buffered and processed and we can use the buffer to hold
+    // frags from a fresh request/response
+    if hdrflags & PFC_FIRST_FRAG > 0 {
+        *stub_data_buffer_len = 0;
+    }
+
+    let input_slice = &input[..stub_len as usize];
+    stub_data_buffer.extend_from_slice(&input_slice);
+    *stub_data_buffer_len += stub_len;
+
+    stub_len
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_parse(
+    _flow: *mut core::Flow,
+    state: &mut DCERPCUDPState,
+    _pstate: *mut std::os::raw::c_void,
+    input: *const u8,
+    input_len: u32,
+    _data: *mut std::os::raw::c_void,
+    _flags: u8,
+) -> AppLayerResult {
+    if input_len > 0 && input != std::ptr::null_mut() {
+        let buf = build_slice!(input, input_len as usize);
+        return state.handle_input_data(buf);
+    }
+    AppLayerResult::err()
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_state_free(state: *mut std::os::raw::c_void) {
+    let _drop: Box<DCERPCUDPState> = unsafe { transmute(state) };
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_udp_state_new() -> *mut std::os::raw::c_void {
+    let state = DCERPCUDPState::new();
+    let boxed = Box::new(state);
+    transmute(boxed)
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_state_transaction_free(
+    _state: *mut std::os::raw::c_void,
+    _tx_id: u64,
+) {
+    // do nothing
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_get_tx_detect_state(
+    vtx: *mut std::os::raw::c_void,
+) -> *mut core::DetectEngineState {
+    let dce_state = cast_pointer!(vtx, DCERPCUDPState);
+    match dce_state.de_state {
+        Some(ds) => ds,
+        None => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_set_tx_detect_state(
+    vtx: *mut std::os::raw::c_void,
+    de_state: *mut core::DetectEngineState,
+) -> u8 {
+    let dce_state = cast_pointer!(vtx, DCERPCUDPState);
+    dce_state.de_state = Some(de_state);
+    0
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_get_tx(
+    state: *mut std::os::raw::c_void,
+    _tx_id: u64,
+) -> *mut DCERPCUDPState {
+    let dce_state = cast_pointer!(state, DCERPCUDPState);
+    dce_state
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_get_tx_cnt(_state: *mut std::os::raw::c_void) -> u8 {
+    1
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_get_alstate_progress(
+    _tx: *mut std::os::raw::c_void,
+    _direction: u8,
+) -> u8 {
+    0
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_udp_get_alstate_progress_completion_status(_direction: u8) -> u8 {
+    1
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::applayer::AppLayerResult;
+    use crate::dcerpc::dcerpc_udp::DCERPCUDPState;
+
+    #[test]
+    fn test_process_header_udp_incomplete_hdr() {
+        let request: &[u8] = &[
+            0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x4a, 0x9f, 0x4d,
+            0x1c, 0x7d, 0xcf, 0x11,
+        ];
+
+        let mut dcerpcudp_state = DCERPCUDPState::new();
+        assert_eq!(-1, dcerpcudp_state.process_header(request));
+    }
+
+    #[test]
+    fn test_process_header_udp_perfect_hdr() {
+        let request: &[u8] = &[
+            0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x4a, 0x9f, 0x4d,
+            0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57, 0x86, 0xc2,
+            0x37, 0x67, 0xf7, 0x1e, 0xd1, 0x11, 0xbc, 0xd9, 0x00, 0x60, 0x97, 0x92, 0xd2, 0x6c,
+            0x79, 0xbe, 0x01, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xff, 0xff, 0xff, 0xff, 0x68, 0x00, 0x00, 0x00, 0x0a, 0x00,
+        ];
+        let mut dcerpcudp_state = DCERPCUDPState::new();
+        assert_eq!(80, dcerpcudp_state.process_header(request));
+    }
+
+    #[test]
+    fn test_handle_fragment_data_udp_no_body() {
+        let request: &[u8] = &[
+            0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x4a, 0x9f, 0x4d,
+            0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57, 0x86, 0xc2,
+            0x37, 0x67, 0xf7, 0x1e, 0xd1, 0x11, 0xbc, 0xd9, 0x00, 0x60, 0x97, 0x92, 0xd2, 0x6c,
+            0x79, 0xbe, 0x01, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xff, 0xff, 0xff, 0xff, 0x68, 0x00, 0x00, 0x00, 0x0a, 0x00,
+        ];
+        let mut dcerpcudp_state = DCERPCUDPState::new();
+        assert_eq!(
+            0,
+            dcerpcudp_state.handle_fragment_data(request, request.len() as u16)
+        );
+    }
+
+    #[test]
+    fn test_handle_input_data_udp_full_body() {
+        let request: &[u8] = &[
+            0x04, 0x00, 0x2c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x3f, 0x98,
+            0xf0, 0x5c, 0xd9, 0x63, 0xcc, 0x46, 0xc2, 0x74, 0x51, 0x6c, 0x8a, 0x53, 0x7d, 0x6f,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+            0xff, 0xff, 0xff, 0xff, 0x70, 0x05, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x24, 0x58, 0xfd, 0xcc, 0x45,
+            0x64, 0x49, 0xb0, 0x70, 0xdd, 0xae, 0x74, 0x2c, 0x96, 0xd2, 0x60, 0x5e, 0x0d, 0x00,
+            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x5e, 0x0d, 0x00, 0x02, 0x00,
+            0x00, 0x00, 0x7c, 0x5e, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+            0x80, 0x96, 0xf1, 0xf1, 0x2a, 0x4d, 0xce, 0x11, 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e,
+            0x72, 0xf4, 0x0c, 0x00, 0x00, 0x00, 0x4d, 0x41, 0x52, 0x42, 0x01, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x0d, 0xf0, 0xad, 0xba, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xf4,
+            0x0b, 0x00, 0x10, 0x09, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0x4d, 0x45, 0x4f, 0x57,
+            0x04, 0x00, 0x00, 0x00, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x38, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x08,
+            0x00, 0x00, 0xd8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00,
+            0xcc, 0xcc, 0xcc, 0xcc, 0xc8, 0x00, 0x00, 0x00, 0x4d, 0x45, 0x4f, 0x57, 0xd8, 0x08,
+            0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+            0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0x28, 0xcd, 0x00, 0x64, 0x29, 0xcd, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xb9, 0x01, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xab, 0x01, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xa5, 0x01,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+            0xa6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x46, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x46, 0xad, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xaa, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07, 0x00, 0x00, 0x00, 0x60, 0x00,
+            0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+            0x20, 0x00, 0x00, 0x00, 0x28, 0x06, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00,
+            0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x50, 0x00, 0x00, 0x00,
+            0x4f, 0xb6, 0x88, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x00, 0x00, 0x00, 0x07, 0x00,
+            0x66, 0x00, 0x06, 0x09, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x19, 0x0c, 0x00,
+            0x58, 0x00, 0x00, 0x00, 0x05, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0xd8,
+            0x98, 0x93, 0x98, 0x4f, 0xd2, 0x11, 0xa9, 0x3d, 0xbe, 0x57, 0xb2, 0x00, 0x00, 0x00,
+            0x32, 0x00, 0x31, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x80, 0x00,
+            0x00, 0x00, 0x0d, 0xf0, 0xad, 0xba, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x43, 0x14, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x4d, 0x45, 0x4f, 0x57,
+            0x04, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x3b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
+            0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x81, 0xc5, 0x17, 0x03, 0x80, 0x0e, 0xe9, 0x4a,
+            0x99, 0x99, 0xf1, 0x8a, 0x50, 0x6f, 0x7a, 0x85, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc,
+            0xcc, 0xcc, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xd8, 0xda, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x2f,
+            0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x00, 0x58, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x10, 0x00, 0x00, 0x00,
+            0x30, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc,
+            0x68, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xff, 0xff, 0x68, 0x8b, 0x0b, 0x00, 0x02, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x00, 0x00, 0x5c, 0x00, 0x5c, 0x00, 0x31, 0x00,
+            0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00,
+            0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x31, 0x00,
+            0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x9d, 0x13, 0x00, 0x01, 0xcc, 0xe0, 0xfd, 0x7f,
+            0xcc, 0xe0, 0xfd, 0x7f, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+            0x90, 0x90,
+        ];
+        let mut dcerpcudp_state = DCERPCUDPState::new();
+        assert_eq!(
+            AppLayerResult::ok(),
+            dcerpcudp_state.handle_input_data(request)
+        );
+        assert_eq!(0, dcerpcudp_state.fraglenleft);
+        if let Some(req) = dcerpcudp_state.request {
+            assert_eq!(1392, req.stub_data_buffer_len);
+        }
+    }
+}
diff --git a/rust/src/dcerpc/detect.rs b/rust/src/dcerpc/detect.rs
new file mode 100644 (file)
index 0000000..5d798a6
--- /dev/null
@@ -0,0 +1,504 @@
+/* Copyright (C) 2020 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+use super::dcerpc::{
+    DCERPCState, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, DCERPC_UUID_ENTRY_FLAG_FF,
+};
+use crate::log::*;
+use std::ffi::CStr;
+use std::os::raw::{c_char, c_void};
+use uuid::Uuid;
+
+pub const DETECT_DCE_IFACE_OP_NONE: u8 = 0;
+pub const DETECT_DCE_IFACE_OP_LT: u8 = 1;
+pub const DETECT_DCE_IFACE_OP_GT: u8 = 2;
+pub const DETECT_DCE_IFACE_OP_EQ: u8 = 3;
+pub const DETECT_DCE_IFACE_OP_NE: u8 = 4;
+
+pub const DETECT_DCE_OPNUM_RANGE_UNINITIALIZED: u32 = 100000;
+
+#[derive(Debug)]
+pub struct DCEIfaceData {
+    pub if_uuid: Vec<u8>,
+    pub op: u8,
+    pub version: u16,
+    pub any_frag: u8,
+}
+
+#[derive(Debug)]
+pub struct DCEOpnumRange {
+    pub range1: u32,
+    pub range2: u32,
+}
+
+impl DCEOpnumRange {
+    pub fn new() -> DCEOpnumRange {
+        return DCEOpnumRange {
+            range1: DETECT_DCE_OPNUM_RANGE_UNINITIALIZED,
+            range2: DETECT_DCE_OPNUM_RANGE_UNINITIALIZED,
+        };
+    }
+}
+
+#[derive(Debug)]
+pub struct DCEOpnumData {
+    pub data: Vec<DCEOpnumRange>,
+}
+
+fn extract_op_version(opver: &str) -> Result<(u8, u16), ()> {
+    let (op, version) = opver.split_at(1);
+    let opval: u8 = match op {
+        ">" => DETECT_DCE_IFACE_OP_GT,
+        "<" => DETECT_DCE_IFACE_OP_LT,
+        "=" => DETECT_DCE_IFACE_OP_EQ,
+        "!" => DETECT_DCE_IFACE_OP_NE,
+        _ => DETECT_DCE_IFACE_OP_NONE,
+    };
+
+    let version: u16 = match version.parse::<u16>() {
+        Ok(res) => res,
+        _ => {
+            return Err(());
+        }
+    };
+    if opval == DETECT_DCE_IFACE_OP_NONE
+        || (opval == DETECT_DCE_IFACE_OP_LT && version == std::u16::MIN)
+        || (opval == DETECT_DCE_IFACE_OP_GT && version == std::u16::MAX)
+    {
+        return Err(());
+    }
+
+    Ok((opval, version))
+}
+
+fn match_iface_version(version: u16, if_data: &DCEIfaceData) -> bool {
+    match if_data.op {
+        DETECT_DCE_IFACE_OP_LT => version < if_data.version,
+        DETECT_DCE_IFACE_OP_GT => version > if_data.version,
+        DETECT_DCE_IFACE_OP_EQ => version == if_data.version,
+        DETECT_DCE_IFACE_OP_NE => version != if_data.version,
+        _ => {
+            return true;
+        }
+    }
+}
+
+fn match_backuuid(state: &mut DCERPCState, if_data: &mut DCEIfaceData) -> u8 {
+    let mut ret = 1;
+    if let Some(ref bindack) = state.bindack {
+        for uuidentry in bindack.accepted_uuid_list.iter() {
+            ret = 1;
+            // if any_frag is not enabled, we need to match only against the first fragment
+            if if_data.any_frag == 0 && (uuidentry.flags & DCERPC_UUID_ENTRY_FLAG_FF == 0) {
+                SCLogDebug!("any frag not enabled");
+                continue;
+            }
+            // if the uuid has been rejected(uuidentry->result == 1), we skip to the next uuid
+            if uuidentry.result != 0 {
+                SCLogDebug!("Skipping to next UUID");
+                continue;
+            }
+
+            for i in 0..16 {
+                if if_data.if_uuid[i] != uuidentry.uuid[i] {
+                    SCLogDebug!("Iface UUID and BINDACK Accepted UUID does not match");
+                    ret = 0;
+                    break;
+                }
+            }
+            let ctxid = state.get_req_ctxid().unwrap_or(0);
+            ret = ret & ((uuidentry.ctxid == ctxid) as u8);
+            if ret == 0 {
+                SCLogDebug!("CTX IDs/UUIDs do not match");
+                continue;
+            }
+
+            if if_data.op != DETECT_DCE_IFACE_OP_NONE
+                && !match_iface_version(uuidentry.version, if_data)
+            {
+                SCLogDebug!("Interface version did not match");
+                ret &= 0;
+            }
+
+            if ret == 1 {
+                return 1;
+            }
+        }
+    }
+
+    return ret;
+}
+
+fn parse_iface_data(arg: &str) -> Result<DCEIfaceData, ()> {
+    let split_args: Vec<&str> = arg.split(',').collect();
+    let mut op_version = (0, 0);
+    let mut any_frag: u8 = 0;
+    let if_uuid = match Uuid::parse_str(split_args[0]) {
+        Ok(res) => res.as_bytes().to_vec(),
+        _ => {
+            return Err(());
+        }
+    };
+
+    match split_args.len() {
+        1 => {}
+        2 => match split_args[1] {
+            "any_frag" => {
+                any_frag = 1;
+            }
+            _ => {
+                op_version = match extract_op_version(split_args[1]) {
+                    Ok((op, ver)) => (op, ver),
+                    _ => {
+                        return Err(());
+                    }
+                };
+            }
+        },
+        3 => {
+            op_version = match extract_op_version(split_args[1]) {
+                Ok((op, ver)) => (op, ver),
+                _ => {
+                    return Err(());
+                }
+            };
+            if split_args[2] != "any_frag" {
+                return Err(());
+            }
+            any_frag = 1;
+        }
+        _ => {
+            return Err(());
+        }
+    }
+
+    Ok(DCEIfaceData {
+        if_uuid: if_uuid,
+        op: op_version.0,
+        version: op_version.1,
+        any_frag: any_frag,
+    })
+}
+
+fn convert_str_to_u32(arg: &str) -> Result<u32, ()> {
+    match arg.parse::<u32>() {
+        Ok(res) => Ok(res),
+        _ => Err(()),
+    }
+}
+
+fn parse_opnum_data(arg: &str) -> Result<DCEOpnumData, ()> {
+    let split_args: Vec<&str> = arg.split(',').collect();
+    let mut dce_opnum_data: Vec<DCEOpnumRange> = Vec::new();
+    for range in split_args.iter() {
+        let mut opnum_range = DCEOpnumRange::new();
+        let split_range: Vec<&str> = range.split('-').collect();
+        let split_len = split_range.len();
+
+        if (split_len > 0 && convert_str_to_u32(split_range[0]).is_err())
+            || (split_len > 1 && convert_str_to_u32(split_range[1]).is_err())
+        {
+            return Err(());
+        }
+        match split_len {
+            1 => {
+                opnum_range.range1 = convert_str_to_u32(split_range[0]).unwrap();
+            }
+            2 => {
+                let range1 = convert_str_to_u32(split_range[0]).unwrap();
+                let range2 = convert_str_to_u32(split_range[1]).unwrap();
+                if range2 < range1 {
+                    return Err(());
+                }
+                opnum_range.range1 = range1;
+                opnum_range.range2 = range2;
+            }
+            _ => {
+                return Err(());
+            }
+        }
+        dce_opnum_data.push(opnum_range);
+    }
+
+    Ok(DCEOpnumData {
+        data: dce_opnum_data,
+    })
+}
+
+#[no_mangle]
+pub extern "C" fn rs_dcerpc_iface_match(state: &mut DCERPCState, if_data: &mut DCEIfaceData) -> u8 {
+    let first_req_seen = state.get_first_req_seen().unwrap_or(0);
+    if first_req_seen == 0 {
+        return 0;
+    }
+
+    match state.get_hdr_type() {
+        Some(x) => match x {
+            DCERPC_TYPE_REQUEST | DCERPC_TYPE_RESPONSE => {
+            }
+            _ => {
+                return 0;
+            }
+        },
+        None => {
+            return 0;
+        }
+    };
+
+    return match_backuuid(state, if_data);
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_iface_parse(carg: *const c_char) -> *mut c_void {
+    if carg.is_null() {
+        return std::ptr::null_mut();
+    }
+    let arg = match CStr::from_ptr(carg).to_str() {
+        Ok(arg) => arg,
+        _ => {
+            return std::ptr::null_mut();
+        }
+    };
+
+    match parse_iface_data(&arg) {
+        Ok(detect) => std::mem::transmute(Box::new(detect)),
+        Err(_) => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_iface_free(ptr: *mut c_void) {
+    if ptr != std::ptr::null_mut() {
+        let _: Box<DCEIfaceData> = std::mem::transmute(ptr);
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_opnum_match(
+    state: &mut DCERPCState,
+    opnum_data: &mut DCEOpnumData,
+) -> u8 {
+    let opnum = state.get_req_opnum().unwrap_or(0);  // TODO is the default to 0 OK?
+    for range in opnum_data.data.iter() {
+        if range.range2 == DETECT_DCE_OPNUM_RANGE_UNINITIALIZED {
+            if range.range1 == opnum as u32 {
+                return 1;
+            }
+        } else if range.range1 <= opnum as u32 && range.range2 >= opnum as u32 {
+            return 1;
+        }
+    }
+
+    0
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_opnum_parse(carg: *const c_char) -> *mut c_void {
+    if carg.is_null() {
+        return std::ptr::null_mut();
+    }
+    let arg = match CStr::from_ptr(carg).to_str() {
+        Ok(arg) => arg,
+        _ => {
+            return std::ptr::null_mut();
+        }
+    };
+
+    match parse_opnum_data(&arg) {
+        Ok(detect) => std::mem::transmute(Box::new(detect)),
+        Err(_) => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rs_dcerpc_opnum_free(ptr: *mut c_void) {
+    if ptr != std::ptr::null_mut() {
+        let _: Box<DCEOpnumData> = std::mem::transmute(ptr);
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_extract_op_version() {
+        let op_version = "<1";
+        assert_eq!(
+            Ok((DETECT_DCE_IFACE_OP_LT, 1)),
+            extract_op_version(op_version)
+        );
+
+        let op_version = ">10";
+        assert_eq!(
+            Ok((DETECT_DCE_IFACE_OP_GT, 10)),
+            extract_op_version(op_version)
+        );
+
+        let op_version = "=45";
+        assert_eq!(
+            Ok((DETECT_DCE_IFACE_OP_EQ, 45)),
+            extract_op_version(op_version)
+        );
+
+        let op_version = "!0";
+        assert_eq!(
+            Ok((DETECT_DCE_IFACE_OP_NE, 0)),
+            extract_op_version(op_version)
+        );
+
+        let op_version = "@1";
+        assert_eq!(true, extract_op_version(op_version).is_err());
+    }
+
+    #[test]
+    fn test_match_iface_version() {
+        let iface_data = DCEIfaceData {
+            if_uuid: Vec::new(),
+            op: 3,
+            version: 10,
+            any_frag: 0,
+        };
+        let version = 10;
+        assert_eq!(true, match_iface_version(version, &iface_data));
+
+        let version = 2;
+        assert_eq!(false, match_iface_version(version, &iface_data));
+    }
+
+    #[test]
+    fn test_parse_iface_data() {
+        let arg = "12345678-1234-1234-1234-123456789ABC";
+        let iface_data = parse_iface_data(arg).unwrap();
+        let expected_uuid = Ok(String::from("12345678-1234-1234-1234-123456789ABC").to_lowercase());
+        let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
+        let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
+        assert_eq!(expected_uuid, uuid);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,>1";
+        let iface_data = parse_iface_data(arg).unwrap();
+        let expected_uuid = Ok(String::from("12345678-1234-1234-1234-123456789ABC").to_lowercase());
+        let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
+        let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
+        assert_eq!(expected_uuid, uuid);
+        assert_eq!(DETECT_DCE_IFACE_OP_GT, iface_data.op);
+        assert_eq!(1, iface_data.version);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,any_frag";
+        let iface_data = parse_iface_data(arg).unwrap();
+        let expected_uuid = Ok(String::from("12345678-1234-1234-1234-123456789ABC").to_lowercase());
+        let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
+        let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
+        assert_eq!(expected_uuid, uuid);
+        assert_eq!(DETECT_DCE_IFACE_OP_NONE, iface_data.op);
+        assert_eq!(1, iface_data.any_frag);
+        assert_eq!(0, iface_data.version);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,!10,any_frag";
+        let iface_data = parse_iface_data(arg).unwrap();
+        let expected_uuid = Ok(String::from("12345678-1234-1234-1234-123456789ABC").to_lowercase());
+        let uuid = Uuid::from_slice(iface_data.if_uuid.as_slice());
+        let uuid = uuid.map(|uuid| uuid.to_hyphenated().to_string());
+        assert_eq!(expected_uuid, uuid);
+        assert_eq!(DETECT_DCE_IFACE_OP_NE, iface_data.op);
+        assert_eq!(1, iface_data.any_frag);
+        assert_eq!(10, iface_data.version);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,>1,ay_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-1234-1234-1234-12345679ABC,>1,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-1234-1234-134-123456789ABC,>1,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-123-124-1234-123456789ABC,>1,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "1234568-1234-1234-1234-123456789ABC,>1,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,>65536,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,>=1,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,<0,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+
+        let arg = "12345678-1234-1234-1234-123456789ABC,>65535,any_frag";
+        let iface_data = parse_iface_data(arg);
+        assert_eq!(iface_data.is_err(), true);
+    }
+
+    #[test]
+    fn test_parse_opnum_data() {
+        let arg = "12";
+        let opnum_data = parse_opnum_data(arg).unwrap();
+        assert_eq!(1, opnum_data.data.len());
+        assert_eq!(12, opnum_data.data[0].range1);
+        assert_eq!(
+            DETECT_DCE_OPNUM_RANGE_UNINITIALIZED,
+            opnum_data.data[0].range2
+        );
+
+        let arg = "12,24";
+        let opnum_data = parse_opnum_data(arg).unwrap();
+        assert_eq!(2, opnum_data.data.len());
+        assert_eq!(12, opnum_data.data[0].range1);
+        assert_eq!(24, opnum_data.data[1].range1);
+
+        let arg = "12,12-24";
+        let opnum_data = parse_opnum_data(arg).unwrap();
+        assert_eq!(2, opnum_data.data.len());
+        assert_eq!(12, opnum_data.data[0].range1);
+        assert_eq!(12, opnum_data.data[1].range1);
+        assert_eq!(24, opnum_data.data[1].range2);
+
+        let arg = "12-14,12,121,62-78";
+        let opnum_data = parse_opnum_data(arg).unwrap();
+        assert_eq!(4, opnum_data.data.len());
+        assert_eq!(12, opnum_data.data[0].range1);
+        assert_eq!(14, opnum_data.data[0].range2);
+        assert_eq!(121, opnum_data.data[2].range1);
+        assert_eq!(78, opnum_data.data[3].range2);
+
+        let arg = "12,26,62,61,6513-6666";
+        let opnum_data = parse_opnum_data(arg).unwrap();
+        assert_eq!(5, opnum_data.data.len());
+        assert_eq!(61, opnum_data.data[3].range1);
+        assert_eq!(6513, opnum_data.data[4].range1);
+
+        let arg = "12,26,62,61,6513--";
+        let opnum_data = parse_opnum_data(arg);
+        assert_eq!(true, opnum_data.is_err());
+
+        let arg = "12-14,12,121,62-8";
+        let opnum_data = parse_opnum_data(arg);
+        assert_eq!(true, opnum_data.is_err());
+    }
+}
diff --git a/rust/src/dcerpc/mod.rs b/rust/src/dcerpc/mod.rs
new file mode 100644 (file)
index 0000000..6b17244
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 2020 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+pub mod dcerpc;
+pub mod dcerpc_udp;
+pub mod parser;
+pub mod detect;
diff --git a/rust/src/dcerpc/parser.rs b/rust/src/dcerpc/parser.rs
new file mode 100644 (file)
index 0000000..0356479
--- /dev/null
@@ -0,0 +1,371 @@
+/* Copyright (C) 2020 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * 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
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+use crate::dcerpc::dcerpc::{
+    BindCtxItem, DCERPCBind, DCERPCBindAck, DCERPCBindAckResult, DCERPCHdr, DCERPCRequest, Uuid,
+};
+use crate::dcerpc::dcerpc_udp::DCERPCHdrUdp;
+use crate::log::*;
+use nom::number::complete::{le_u16, le_u32, le_u8};
+use nom::number::Endianness;
+
+fn uuid_to_vec(uuid: Uuid) -> Vec<u8> {
+    let mut uuidtmp = uuid;
+    let mut vect: Vec<u8> = Vec::new();
+    vect.append(&mut uuidtmp.time_low);
+    vect.append(&mut uuidtmp.time_mid);
+    vect.append(&mut uuidtmp.time_hi_and_version);
+    vect.push(uuidtmp.clock_seq_hi_and_reserved);
+    vect.push(uuidtmp.clock_seq_low);
+    vect.append(&mut uuidtmp.node);
+    vect
+}
+
+fn assemble_uuid(uuid: Uuid) -> Vec<u8> {
+    let mut uuidtmp = uuid;
+    let mut vect: Vec<u8> = Vec::new();
+    uuidtmp.time_low.reverse();
+    uuidtmp.time_mid.reverse();
+    uuidtmp.time_hi_and_version.reverse();
+    vect.append(&mut uuidtmp.time_low);
+    vect.append(&mut uuidtmp.time_mid);
+    vect.append(&mut uuidtmp.time_hi_and_version);
+    vect.push(uuidtmp.clock_seq_hi_and_reserved);
+    vect.push(uuidtmp.clock_seq_low);
+    vect.append(&mut uuidtmp.node);
+
+    vect
+}
+
+named!(pub parse_uuid<Uuid>,
+    do_parse!(
+        time_low: take!(4)
+        >> time_mid: take!(2)
+        >> time_hi_and_version: take!(2)
+        >> clock_seq_hi_and_reserved: le_u8
+        >> clock_seq_low: le_u8
+        >> node: take!(6)
+        >> (
+             Uuid {
+                time_low: time_low.to_vec(),
+                time_mid: time_mid.to_vec(),
+                time_hi_and_version: time_hi_and_version.to_vec(),
+                clock_seq_hi_and_reserved: clock_seq_hi_and_reserved,
+                clock_seq_low: clock_seq_low,
+                node: node.to_vec(),
+            }
+        )
+    )
+);
+
+named!(pub parse_dcerpc_udp_header<DCERPCHdrUdp>,
+    do_parse!(
+        rpc_vers: le_u8
+        >> pkt_type: le_u8
+        >> flags1: le_u8
+        >> flags2: le_u8
+        >> drep: take!(3)
+        >> endianness: value!(if drep[0] == 0 { Endianness::Big } else { Endianness::Little })
+        >> serial_hi: le_u8
+        >> objectuuid: take!(16)
+        >> interfaceuuid: take!(16)
+        >> activityuuid: take!(16)
+        >> server_boot: u32!(endianness)
+        >> if_vers: u32!(endianness)
+        >> seqnum: u32!(endianness)
+        >> opnum: u16!(endianness)
+        >> ihint: u16!(endianness)
+        >> ahint: u16!(endianness)
+        >> fraglen: u16!(endianness)
+        >> fragnum: u16!(endianness)
+        >> auth_proto: le_u8
+        >> serial_lo: le_u8
+        >> (
+             DCERPCHdrUdp {
+                rpc_vers: rpc_vers,
+                pkt_type: pkt_type,
+                flags1: flags1,
+                flags2: flags2,
+                drep: drep.to_vec(),
+                serial_hi: serial_hi,
+                objectuuid: match parse_uuid(objectuuid) {
+                    Ok((_, vect)) => assemble_uuid(vect),
+                    Err(e) => {
+                        SCLogDebug!("{}", e);
+                        vec![0]
+                    },
+                },
+                interfaceuuid: match parse_uuid(interfaceuuid) {
+                    Ok((_, vect)) => assemble_uuid(vect),
+                    Err(e) => {
+                        SCLogDebug!("{}", e);
+                        vec![0]
+                    },
+                },
+                activityuuid: match parse_uuid(activityuuid){
+                    Ok((_, vect)) => assemble_uuid(vect),
+                    Err(e) => {
+                        SCLogDebug!("{}", e);
+                        vec![0]
+                    },
+                },
+                server_boot: server_boot,
+                if_vers: if_vers,
+                seqnum: seqnum,
+                opnum: opnum,
+                ihint: ihint,
+                ahint: ahint,
+                fraglen: fraglen,
+                fragnum: fragnum,
+                auth_proto: auth_proto,
+                serial_lo: serial_lo,
+            }
+        )
+    )
+);
+
+named!(pub parse_dcerpc_bindack_result<DCERPCBindAckResult>,
+    do_parse!(
+        ack_result: le_u16
+        >>  ack_reason: le_u16
+        >>  transfer_syntax: take!(16)
+        >>  syntax_version: le_u32
+        >> (
+             DCERPCBindAckResult {
+                ack_result:ack_result,
+                ack_reason:ack_reason,
+                transfer_syntax:transfer_syntax.to_vec(),
+                syntax_version:syntax_version,
+            }
+        )
+    )
+);
+
+named!(pub parse_dcerpc_bindack<DCERPCBindAck>,
+    do_parse!(
+        _max_xmit_frag: le_u16
+        >> _max_recv_frag: le_u16
+        >> _assoc_group: take!(4)
+        >> sec_addr_len: le_u16
+        >> take!(sec_addr_len)
+        >> cond!((sec_addr_len + 2) % 4 != 0, take!(4 - (sec_addr_len + 2) % 4))
+        >> numctxitems: le_u8
+        >> take!(3) // Padding
+        >> ctxitems: count!(parse_dcerpc_bindack_result, numctxitems as usize)
+        >> (
+             DCERPCBindAck {
+                accepted_uuid_list: Vec::new(),
+                sec_addr_len: sec_addr_len,
+                numctxitems: numctxitems,
+                ctxitems: ctxitems,
+            }
+        )
+    )
+);
+
+named_args!(pub parse_bindctx_item(endianness: Endianness) <BindCtxItem>,
+    do_parse!(
+        ctxid: u16!(endianness)
+        >> _num_trans_items: le_u8
+        >> take!(1) // Reservid bit
+        >> uuid: take!(16)
+        >> version: u16!(endianness)
+        >> versionminor: u16!(endianness)
+        >> take!(20)
+        >> (
+             BindCtxItem {
+                ctxid: ctxid,
+                // UUID parsing for TCP seems to change as per endianness
+                uuid: match parse_uuid(uuid) {
+                    Ok((_, vect)) => match endianness {
+                        Endianness::Little => assemble_uuid(vect),
+                        _ => uuid_to_vec(vect),
+                    },
+                    // Shouldn't happen
+                    Err(_e) => {vec![0]},
+                },
+                version: version,
+                versionminor: versionminor,
+            }
+        )
+    )
+);
+
+named!(pub parse_dcerpc_bind<DCERPCBind>,
+    do_parse!(
+        _max_xmit_frag: le_u16
+        >> _max_recv_frag: le_u16
+        >> _assoc_group_id: le_u32
+        >> numctxitems: le_u8
+        >> take!(3)
+        >> (
+             DCERPCBind {
+                numctxitems: numctxitems,
+                uuid_list: Vec::new(),
+            }
+        )
+    )
+);
+
+named!(pub parse_dcerpc_header<DCERPCHdr>,
+    do_parse!(
+        rpc_vers: le_u8
+        >> rpc_vers_minor: le_u8
+        >> hdrtype: le_u8
+        >> pfc_flags: le_u8
+        >> packed_drep: take!(4)
+        >> endianness: value!(if packed_drep[0] & 0x10 == 0 { Endianness::Big } else { Endianness::Little })
+        >> frag_length: u16!(endianness)
+        >> auth_length: u16!(endianness)
+        >> call_id: u32!(endianness)
+        >> (
+             DCERPCHdr {
+                rpc_vers: rpc_vers,
+                rpc_vers_minor: rpc_vers_minor,
+                hdrtype: hdrtype,
+                pfc_flags: pfc_flags,
+                packed_drep: packed_drep.to_vec(),
+                frag_length: frag_length,
+                auth_length: auth_length,
+                call_id: call_id,
+            }
+        )
+    )
+);
+
+named_args!(pub parse_dcerpc_request(endianness: Endianness) <DCERPCRequest>,
+    do_parse!(
+        _pad: take!(4)
+        >> ctxid: u16!(endianness)
+        >> opnum: u16!(endianness)
+        >> (
+             DCERPCRequest {
+                ctxid: ctxid,
+                opnum: opnum,
+                first_request_seen: 1,
+                stub_data_buffer: Vec::new(),
+                stub_data_buffer_len: 0,
+                stub_data_buffer_reset: false,
+                cmd: 0,
+            }
+        )
+    )
+);
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_parse_uuid() {
+        let uuid: &[u8] = &[
+            0xb8, 0x4a, 0x9f, 0x4d, 0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e,
+            0x7c, 0x57,
+        ];
+        let expected_uuid = Uuid {
+            time_low: vec![0xb8, 0x4a, 0x9f, 0x4d],
+            time_mid: vec![0x1c, 0x7d],
+            time_hi_and_version: vec![0xcf, 0x11],
+            clock_seq_hi_and_reserved: 0x86,
+            clock_seq_low: 0x1e,
+            node: vec![0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57],
+        };
+        let (_remainder, parsed_uuid) = parse_uuid(uuid).unwrap();
+        assert_eq!(expected_uuid, parsed_uuid);
+    }
+
+    #[test]
+    fn test_assemble_uuid() {
+        let uuid = Uuid {
+            time_low: vec![0xb8, 0x4a, 0x9f, 0x4d],
+            time_mid: vec![0x1c, 0x7d],
+            time_hi_and_version: vec![0xcf, 0x11],
+            clock_seq_hi_and_reserved: 0x86,
+            clock_seq_low: 0x1e,
+            node: vec![0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57],
+        };
+        let expected_val = vec![
+            0x4d, 0x9f, 0x4a, 0xb8, 0x7d, 0x1c, 0x11, 0xcf, 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e,
+            0x7c, 0x57,
+        ];
+        assert_eq!(expected_val, assemble_uuid(uuid));
+    }
+
+    #[test]
+    fn test_parse_dcerpc_udp_header() {
+        let dcerpcheader: &[u8] = &[
+            0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x4a, 0x9f, 0x4d,
+            0x1c, 0x7d, 0xcf, 0x11, 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57, 0x86, 0xc2,
+            0x37, 0x67, 0xf7, 0x1e, 0xd1, 0x11, 0xbc, 0xd9, 0x00, 0x60, 0x97, 0x92, 0xd2, 0x6c,
+            0x79, 0xbe, 0x01, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0xff, 0xff, 0xff, 0xff, 0x68, 0x00, 0x00, 0x00, 0x0a, 0x00,
+        ];
+        let (_remainder, header) = parse_dcerpc_udp_header(dcerpcheader).unwrap();
+        let expected_activityuuid = vec![
+            0x67, 0x37, 0xc2, 0x86, 0x1e, 0xf7, 0x11, 0xd1, 0xbc, 0xd9, 0x00, 0x60, 0x97, 0x92,
+            0xd2, 0x6c,
+        ];
+        assert_eq!(0x04, header.rpc_vers);
+        assert_eq!(0x00, header.pkt_type);
+        assert_eq!(0x08, header.flags1);
+        assert_eq!(0x00, header.flags2);
+        assert_eq!(vec!(0x10, 0x00, 0x00), header.drep);
+        assert_eq!(0x00, header.serial_hi);
+        assert_eq!(expected_activityuuid, header.activityuuid);
+        assert_eq!(0x3401be79, header.server_boot);
+        assert_eq!(0x00000000, header.seqnum);
+        assert_eq!(0xffff, header.ihint);
+        assert_eq!(0x0068, header.fraglen);
+        assert_eq!(0x0a, header.auth_proto);
+    }
+
+    #[test]
+    fn test_parse_dcerpc_header() {
+        let dcerpcheader: &[u8] = &[
+            0x05, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00,
+        ];
+        let (_remainder, header) = parse_dcerpc_header(dcerpcheader).unwrap();
+        assert_eq!(5, header.rpc_vers);
+        assert_eq!(0, header.rpc_vers_minor);
+        assert_eq!(0, header.hdrtype);
+        assert_eq!(1024, header.frag_length);
+    }
+
+    #[test]
+    fn test_parse_dcerpc_bind() {
+        let dcerpcbind: &[u8] = &[
+            0xd0, 0x16, 0xd0, 0x16, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+        ];
+        let (_remainder, bind) = parse_dcerpc_bind(dcerpcbind).unwrap();
+        assert_eq!(24, bind.numctxitems);
+    }
+
+    #[test]
+    fn test_parse_bindctx_item() {
+        let dcerpcbind: &[u8] = &[
+            0x00, 0x00, 0x01, 0x00, 0x2c, 0xd0, 0x28, 0xda, 0x76, 0x91, 0xf6, 0x6e, 0xcb, 0x0f,
+            0xbf, 0x85, 0xcd, 0x9b, 0xf6, 0x39, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5d, 0x88, 0x8a,
+            0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
+            0x00, 0x00,
+        ];
+        let (_remainder, ctxitem) = parse_bindctx_item(dcerpcbind, Endianness::Little).unwrap();
+        assert_eq!(0, ctxitem.ctxid);
+        assert_eq!(1, ctxitem.version);
+        assert_eq!(3, ctxitem.versionminor);
+    }
+}