#! /usr/bin/env python
# 
# DLSw Query Tool
# Public Release 1.0 (Defcon 14)
# Written by: Martyn Ruks, MWR InfoSecurity, Copyright 2006
#
# This tool is released for educational purposes only and the author is not responsible for any damage it causes.
# 
# Greetz to B-r00t, m1nx, haggis, marshal-l, mark@vulndev.org
#
# Thanks to Phillipe Biondi <phil@secdev.org> for Scapy
#
# For usage: ./dlsw_query-1.0.py --help
#

# Add various required functions
import time
import binascii
import socket
import optparse

# Set log level to benefit from Scapy warnings
import logging
logging.getLogger("scapy").setLevel(1)

from BitVector import *
from scapy import *
from optparse import OptionParser

#
# Extend optparse to make target options required
#

class OptionParser (optparse.OptionParser):

    def check_required (self, opt):
        option = self.get_option(opt)

        if getattr(self.values, option.dest) is None:
            self.error("%s option not supplied" % option)

#
# Packet Arrays
#

# Public version contains static arrays
# future versions will include Packet Class Definitions for use with Scapy

dlsw_response = '\x31\x48\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x42\x01\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x15\x21' 

dlsw_request_v1 = '\x31\x48\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x42\x01\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x81\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x15\x20\x05\x81\x00\x00\x0c\x04\x82\x01\x00\x04\x83\x00\x14\x12\x86\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\x84\x43\x69\x73\x63\x6f\x03\x87\x01\x03\x85\x00\x03\x88\x00\x05\x8b\x00\x00\x0c'

dlsw_request_v2 = '\x31\x48\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x42\x01\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x81\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x15\x20\x05\x81\x00\x00\x0c\x04\x82\x02\x00\x04\x83\x00\x14\x12\x86\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x07\x84\x43\x69\x73\x63\x6f\x03\x87\x01\x03\x85\x00\x03\x88\x00\x05\x8b\x00\x00\x0c'

#
# Packet Handling Functions
#

# Reads a DLSw packet from a socket
def packet_read(channel1,fileHandle,filewrite):
    response = channel1.recv (4)

    # Now get the packet information
    dlsw_version = get_length(response,0,1)
    header_length_bytes = get_length(response,1,2)
    message_length_bytes = get_length(response,2,4)
    header_length_hex = get_hex_length(response,1,2)
    message_length_hex = get_hex_length(response,2,4)
    print ''

    # Check the DLSw version
    if dlsw_version != 49:
        text = '*** WARNING *** Does not look like a DLSw packet'
        print text
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

    text = 'Header length 0x'+header_length_hex+' or '+str(header_length_bytes)+' bytes'
    print text
    if filewrite == 1:
            fileHandle.write ( text+'\n' )

    text = 'Message length 0x'+message_length_hex+' or '+str(message_length_bytes)+' bytes'
    print text
    if filewrite == 1:
            fileHandle.write ( text+'\n' )

    # Calculate first packet size
    response_size = message_length_bytes + header_length_bytes
    text = 'Packet is '+str(response_size)+' bytes'
    print text
    if filewrite == 1:
            fileHandle.write ( text+'\n' )

    # Check whether we have read enough data from the socket
    if response_size > 4:
        response2 = channel1.recv (response_size-4)
    
    # Join all the bits together
    response = response+response2

    # Return the packet itself
    return response

# Returns a decimal integer between two specified positions in a string
def get_length(response,start,end):
    header_length = response[start:end]
    header_length_hex = binascii.hexlify(header_length)
    header_length_bytes = string.atoi(str(header_length_hex),16)
    return header_length_bytes

# Returns a hex value as an integer between two specified positions in a string
def get_hex_length(response,start,end):
    header_length = response[start:end]
    header_length_hex = binascii.hexlify(header_length)
    return header_length_hex

#
# Functions to parse response data
#

# Check packet type
def check_cap_packet_type(response,fileHandle,filewrite):
    query_type = response[14:15]
    query_type = binascii.hexlify(query_type)
    if query_type != '20':
        text = '*** WARNING *** Not a Capabilities Exchange Packet'
        print text
        if filewrite == 1:
            fileHandle.write ( text+'\n' )
    query_direction = response[38:39]
    query_direction = binascii.hexlify(query_direction)
    header_length = get_length(response,1,2)
    gds_value = response[header_length+2:header_length+4]
    gds_value = binascii.hexlify(gds_value)
    if query_direction == '01':
        if gds_value == '1520':
            text = '*** NOTE *** Packet passed the tests for a Request'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n\n' )
        else:
            text = '*** WARNING *** Not a valid Request Packet'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n\n' )
    elif query_direction == '02':
        if gds_value == '1521':
            text = '*** NOTE *** Packet passed the tests for a Response'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n\n' )
        elif gds_value == '1522':
            text = '*** NOTE *** Target refused our Capabilities'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n\n' )
            # ADD REASON DISSECTION HERE
        else:
            text = '*** WARNING *** Not a valid Response Packet'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n\n' )

# Get the advertised DLSw version
def get_dlsw_version(response,header_length,fileHandle,filewrite):

    # Search for the version string
    dlsw_version = re.search('\x82',response)

    if dlsw_version:
        # Check the data is in the message not the header
        version_length_pos = dlsw_version.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 4:
                # Get the string itself
                dlsw_string1 = response[version_length_pos+1:version_length_pos+2]
                dlsw_string2 = response[version_length_pos+2:version_length_pos+3]

                dlsw_string1 = binascii.hexlify(dlsw_string1)
                dlsw_string2 = binascii.hexlify(dlsw_string2)

                dlsw_string1 = string.atoi(str(dlsw_string1),10)
                text = 'DLSw Version: '+str(dlsw_string1)+'.'+str(dlsw_string2)
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
                text = '*** WARNING *** The version string is not in the correct format'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

        else:
            text = '*** WARNING *** The DLSw version was not in the correct place'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The DLSw version data was not present'
        print text
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get the TCP connections number
def get_tcp_connections(response,header_length,fileHandle,filewrite):

    # Search for the number of supported TCP connections
    tcp_connections = re.search('\x87',response)

    if tcp_connections:
        # Check the data is in the message not the header
        version_length_pos = tcp_connections.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 3:
                # Get the string itself
                tcp_connections = response[version_length_pos+1:version_length_pos+2]

                tcp_connections = binascii.hexlify(tcp_connections)

                tcp_connections = string.atoi(str(tcp_connections),10)
                text = 'TCP Connections: '+str(tcp_connections)
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
                text = '*** WARNING *** The TCP connections data is not in the correct format'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

        else:
            text = '*** WARNING *** The TCP connections data was not in the correct place'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The TCP connections data was not present'
        print text
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get the vendor OUI
def get_vendor_oui(response,header_length,fileHandle,filewrite):

    # Search for the Vendor OUI value
    vendor_oui = re.search('\x8b',response)

    if vendor_oui:
        # Check the data is in the message not the header
        version_length_pos = vendor_oui.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 5:
                # Get the string itself
                vendor_oui = response[version_length_pos+1:version_length_pos+4]

                vendor_oui = binascii.hexlify(vendor_oui)
                if vendor_oui == '00000c':
                    vendor_name = "Cisco"
                else:
                    vendor_name = "Unknown"

                text = 'Vendor OUI: 0x'+str(vendor_oui)+' '+vendor_name
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
            
                text = '*** WARNING *** The vendor OUI data is not in the correct format'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' ) 

        else:
            text = '*** WARNING *** The vendor OUI data was not in the correct place'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The vendor OUI string was not present'
        print text
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get Multicast support
def get_multicast(response,header_length,fileHandle,filewrite):

    # Search for the MAC exclusivity value
    multicast = re.search('\x8c',response)

    if multicast:
        # Check the data is in the message not the header
        version_length_pos = multicast.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 3:
                # Get the string itself
                multicast = response[version_length_pos+1:version_length_pos+2]

                multicast = binascii.hexlify(multicast)
                if multicast == '00':
                    multicast = "No"
                elif multicast == '01':
                    multicast = "Yes"
                else:
                    multicast = "Unknown"

                text = 'Multicast: '+str(multicast)
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
                text = '*** WARNING *** The Multicast support data is not in the correct format'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

        else:
            text = '*** WARNING *** The Multicast support data was not in the correct place'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The Multicast support data was not present'
        print text
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get Initial Pacing
def get_pacing(response,header_length,fileHandle,filewrite):

    # Search for the Initial Pacing value
    pacing = re.search('\x83',response)

    if pacing:
        # Check the data is in the message not the header
        version_length_pos = pacing.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 4:
                # Get the string itself
                pacing = response[version_length_pos+1:version_length_pos+3]

                pacing = binascii.hexlify(pacing)
                pacing = string.atoi(str(pacing),16)

                text = 'Initial Pacing: '+str(pacing)
                print text
                print ''
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
                text = '*** WARNING *** The initial pacing data is not in the correct format'
                print text
                print ''
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

        else:
            text = '*** WARNING *** The initial pacing data was not in the correct place'
            print text
            print ''
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The initial pacing data was not present'
        print text
        print ''
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get the version string information
def get_version_string(response,header_length,fileHandle,filewrite):

    # Search for the version string
    version_string = re.search('\x84',response)

    if version_string:
        # Check the data is in the message not the header
        version_length_pos = version_string.start()

        if version_length_pos > header_length+4:

            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            # Get the string itself
            version_string = response[version_length_pos+1:version_length_bytes+version_length_pos-1]
            text = 'Version String:'
            print ''
            print text
            print version_string
            print ''
            if filewrite == 1:
                fileHandle.write ( '\n'+text+'\n'+version_string+'\n' )

        else:
            text = '*** WARNING *** The version string was not in the correct place'
            print text
            print ''
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The version string was not present'
        print text
        print ''
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get the MAC address exclusivity
def get_mac_exclusivity(response,header_length,fileHandle,filewrite):

    # Search for the MAC exclusivity value
    mac_exclusive = re.search('\x85',response)

    if mac_exclusive:
        # Check the data is in the message not the header
        version_length_pos = mac_exclusive.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 3:
                # Get the string itself
                mac_exclusive = response[version_length_pos+1:version_length_pos+2]

                mac_exclusive = binascii.hexlify(mac_exclusive)
                if mac_exclusive == '00':
                    mac_exclusive = "No"
                elif mac_exclusive == '01':
                    mac_exclusive = "Yes"
                else:
                    vendor_name = "Unknown"

                text = 'Mac Address Info:'
                print text
                if filewrite == 1:
                    fileHandle.write ( '\n'+text+'\n' )
                text = 'Exclusivity: '+str(mac_exclusive)
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
                text = '*** WARNING *** The Mac address exclusivity data is not in the correct format'
                print text
                print ''
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

        else:
            text = '*** WARNING *** The Mac address exclusivity data was not in the correct place'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The Mac address exclusivity data was not present'
        print text
        print ''
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get the MAC address information
def get_mac_addresses(response,header_length,fileHandle,filewrite):

    # Set counters and get working data
    message_length = get_length(response,2,4)
    mac_count = 0
    current_length = message_length
    working_response = response[header_length:header_length+message_length]

    # Work throught the data
    while current_length > 0:

        # Search for the MAC Address information
        mac_address = re.search('\x89',working_response)
        if mac_address != None:
            mac_length_pos = mac_address.start()

            # Get the length of the string in the right format
            mac_length = working_response[mac_length_pos-1:mac_length_pos]
            mac_length_hex = binascii.hexlify(mac_length)
            mac_length_bytes = string.atoi(str(mac_length_hex),16)

            # Get the string itself
            mac_addresses = working_response[mac_length_pos+1:mac_length_bytes+mac_length_pos-1]
            mac_addresses = binascii.hexlify(mac_addresses)

            text = 'Address: '+mac_addresses[0:4]+'.'+mac_addresses[4:8]+'.'+mac_addresses[8:12]+' Mask: '+mac_addresses[12:16]+'.'+mac_addresses[16:20]+'.'+mac_addresses[20:24]
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' ) 

            working_response = working_response[mac_length_pos+mac_length_bytes-1:current_length]
            current_length = current_length-mac_length_bytes
            mac_count = mac_count+1
        else:
            current_length = 0
            if mac_count < 1:
                text = '*** NOTE *** No MAC address data was present'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

# Get the NetBIOS exclusivity
def get_netbios_exclusivity(response,header_length,fileHandle,filewrite):

    # Search for the NetBIOS exclusivity
    netbios_exclusive = re.search('\x88',response)

    if netbios_exclusive:
        # Check the data is in the message not the header
        version_length_pos = netbios_exclusive.start()

        if version_length_pos > header_length+4:
            # Get the length of the string in the right format
            version_length = response[version_length_pos-1:version_length_pos]
            version_length_hex = binascii.hexlify(version_length)
            version_length_bytes = string.atoi(str(version_length_hex),16)

            if version_length_bytes == 3:
                # Get the string itself
                netbios_exclusive = response[version_length_pos+1:version_length_pos+2]

                netbios_exclusive = binascii.hexlify(netbios_exclusive)
                if netbios_exclusive == '00':
                    netbios_exclusive = "No"
                elif netbios_exclusive == '01':
                    netbios_exclusive = "Yes"
                else:
                    vendor_name = "Unknown"

                text = 'NetBIOS Name Info:'
                print ''
                print text
                if filewrite == 1:
                    fileHandle.write ( '\n'+text+'\n' )
                text = 'Exclusivity: '+str(netbios_exclusive)
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )
            else:
                text = '*** WARNING *** The NetBIOS exclusivity data is not in the correct format'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

        else:
            text = '*** WARNING *** The NetBIOS exclusivity data was not in the correct place'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
    else:
        text = '*** WARNING *** The NetBIOS exclusivity data was not present'
        print text
        print ''
        if filewrite == 1:
            fileHandle.write ( text+'\n' )

# Get the NetBIOS names
def get_netbios_names(response,header_length,fileHandle,filewrite):

    # Set counters and get working data
    message_length = get_length(response,2,4)
    netbios_count = 0
    current_length = message_length
    working_response = response[header_length:header_length+message_length]

    while current_length > 0:
        # Search for the NetBIOS name information
        netbios_name = re.search('\x8A',working_response)
        if netbios_name != None:
            netbios_length_pos = netbios_name.start()

            # Get the length of the string in the right format
            netbios_length = working_response[netbios_length_pos-1:netbios_length_pos]
            netbios_length_hex = binascii.hexlify(netbios_length)
            netbios_length_bytes = string.atoi(str(netbios_length_hex),16)

            # Get the string itself
            netbios_names = working_response[netbios_length_pos+1:netbios_length_bytes+netbios_length_pos-1]

            # Print the result out to screen
            text = 'Name: '+str(netbios_names)
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )

            working_response = working_response[netbios_length_pos+netbios_length_bytes-1:current_length]
            current_length = current_length-netbios_length_bytes
            netbios_count = netbios_count+1
        else:
            current_length = 0
            if netbios_count < 1:
                text = '*** NOTE *** No NetBIOS name data was present'
                print text
                if filewrite == 1:
                    fileHandle.write ( text+'\n' )

# Get the supported SAP values
def get_sap_support(response,header_length,fileHandle,filewrite):

    # Search for the SAP support
    sap_support = re.search('\x86',response)

    # Check the data is in the message not the header
    version_length_pos = sap_support.start()

    if version_length_pos > header_length+4:
        # Get the length of the string in the right format
        version_length = response[version_length_pos-1:version_length_pos]
        version_length_hex = binascii.hexlify(version_length)
        version_length_bytes = string.atoi(str(version_length_hex),16)

        if version_length_bytes == 18:
            print ''
            text = 'SAP Support:'
            print text
            if filewrite == 1:
                fileHandle.write ( '\n'+text+'\n' )
            # Get the string itself
            sap_support = response[version_length_pos+1:version_length_pos+17]
            sap_number = 0
            counter = 0
            total = 0
            while counter < 16:
                sap_supported = sap_support[counter:counter+1]
                sap_supported = binascii.hexlify(sap_supported)
                sap_supported = string.atoi(str(sap_supported),16)
                total = (sap_supported+1)/32 + total
                saparray = BitVector( intVal = sap_supported )
                counter2 = 0
                outputstring = ''
                while counter2 < 8:
                    sapsupport = str(hex(sap_number))
                    if saparray[counter2] == 0:
                        sapvalue = "Off"
                    else:
                        sapvalue = "On"
                    outputstring = outputstring+sapsupport+'='+sapvalue+' '
                    if sap_number < 16:
                        outputstring = outputstring+' '
                    counter2 = counter2 + 1
                    sap_number = sap_number + 2
                print outputstring
                if filewrite == 1:
                    fileHandle.write ( outputstring+'\n' )
                counter = counter + 1

            text = 'Total SAPs allowed: '+str(total)+' / 128'
            print text
            if filewrite == 1:
                fileHandle.write ( text+'\n' )
        else:
            text = '*** WARNING *** The SAP support data is not in the correct format'
            print text
            print ''
            fileHandle.write ( text+'\n\n' )

    else:
        text = '*** WARNING *** The SAP support data was not in the correct place'
        print text
        print ''
        fileHandle.write ( text+'\n\n' )


#
# Command Line Options
#

parser = OptionParser()
parser.add_option("-t", "--target", action="store", dest="target", metavar="TARGET", help="Target IP address or hostname (required)")
parser.add_option("-o", "--outputfile", action="store", dest="outputfile", metavar="OUTPUTFILE", default="temp", help="Output file to write data to (defaults to dlsw_<target>.txt)")
parser.add_option("-p", "--port", action="store", dest="port", type="int", default="2065", help="Port number to connect to and listen on (defaults to 2065)")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="Display more verbose informtaion")
parser.add_option("-V", "--version", action="store", dest="version", default=1, type="choice", choices=["1","2"], help="Version to try 1 or 2 (defaults to version 2)")
parser.add_option("-c", action="store_true", dest="complete", default=False, help="Attempt to complete the Capabilities Exchange (defaults to no)")

# Get the command line options
(options, args) = parser.parse_args()

# Assign the rest of the inputs
port = options.port
version = options.version
verbose = options.verbose
complete = options.complete

# Mandate the use of a target
parser.check_required("-t")

if options.target:
    target = options.target
    if verbose == True:
        print 'TARGET:', target
else:
    sys.exit(0)

if port >= 0 and port < 65536:
    pass
else:
    print 'Error, port number must be between 0 and 65535'
    sys.exit(0)

# REVIEW THE USE OF THIS
if options.outputfile != "temp":
    outputfile = options.outputfile
    filewrite = 1
else:
    outputfile = 'dlsw_'+target+'.txt'
    filewrite = 0

# Open logfile for writing
if filewrite == 1:
    # SANITISE INPUT
    # Open the log file for writing
    try:
        fileHandle = open ( outputfile, 'a' )
        if verbose == True:
            print 'Output will be written to logfile', outputfile
    except Exception:
        print 'Error opening output file', outputfile, 'for writing'
        sys.exit(0)
else:
    fileHandle = 0

# Get the local time first
datestring = time.ctime()

if filewrite == 1:
    fileHandle.write ( '####################################################################\n' )
    fileHandle.write ( 'TARGET: '+target+'\n' )
    fileHandle.write ( 'PORT: '+str(port)+'\n' )
    fileHandle.write ( 'DATE: '+datestring+'\n' )
    fileHandle.write ( '####################################################################\n\n' )

# Set version to either 1 or 2
#if version != 1:
#    version = 2

# Add output for added verbosity
if verbose == True:
    print 'Verbose output selected'
    if complete == True:
        print 'DLSw handhsake will be completed'
    else:
        print 'DLSw handhsake will not be completed'

    print 'Version '+str(version)+' selected'
    if filewrite == 1:
        fileHandle.write ( 'Version '+str(version)+' selected' )

#
# Socket definitions
#

# Define socket for incoming data
incoming = socket.socket ( socket.AF_INET,socket.SOCK_STREAM )
try:
    incoming.bind ( ( '', port ) )
    incoming.listen ( 1 )
except Exception:
    print ''
    print 'Error, cannot bind to local TCP port', port
    if verbose == True:
        print 'May need to wait for kernel to release socket'
    print ''
    sys.exit(0)
else:
    if verbose == True:
        print 'Successfully bound to local TCP port', port
        if filewrite == 1:
            fileHandle.write ( 'Successfully bound to local TCP port '+str(port)+'\n' )

# Define socket for outgoing data
outgoing = socket.socket ( socket.AF_INET,socket.SOCK_STREAM )
try:
    outgoing.connect ( ( target, port ) )
except Exception:
    print 'Error, cannot connect to host', target, 'on port', port
    sys.exit(0)
else:
    if verbose == True:
        print 'Connection suceeded to target host', target, 'on port', port
        if filewrite == 1:
            fileHandle.write ( 'Connection suceeded to target host '+target+' on port '+str(port)+'\n' )

#
# Main program starts here
#

# Get ready to receive response
channel1, details = incoming.accept()

# Send Request to start the transaction
if version == "1":
    outgoing.send ( str(dlsw_request_v1) )
else:
    outgoing.send ( str(dlsw_request_v2) )

# Get ready to receive response
#channel1, details = incoming.accept()

# Get the incoming Request from the target
print 'Capabilities Exchange Request has been sent'


if complete == True:

    # Send Response to peer down the incoming connection
    channel1.send ( str(dlsw_response) )
    print 'Capabilities Exchange Response has been sent'
    if filewrite == 1:
        fileHandle.write ( 'Full exchange was attempted\n\n' )
else:
    print 'Capabilities Exchange Response not sent'
    if filewrite == 1:
        fileHandle.write ( 'Full exchange was not attempted\n\n' )

# Close socket depending on version
if version == "1":
    pass
#    channel1.close()
elif version == "2":
    outgoing.close()
else:
    channel1.close()
    outgoing.close()
    print 'Invalid version selected!'
    sys.exit(1)

# Read in the Response packet
response = packet_read(channel1,fileHandle,filewrite)

header_length = get_length(response,1,2)

# Check the packet is a Capabilities Exchange Response
check_cap_packet_type(response,fileHandle,filewrite)

# Read in the Request packet
response = packet_read(channel1,fileHandle,filewrite)

header_length = get_length(response,1,2)

# Check the packet is a Capabilities Exchange Request
check_cap_packet_type(response,fileHandle,filewrite)
print ''

# Parse and output all the data from the target
get_dlsw_version(response,header_length,fileHandle,filewrite)
get_tcp_connections(response,header_length,fileHandle,filewrite)
get_vendor_oui(response,header_length,fileHandle,filewrite)
get_multicast(response,header_length,fileHandle,filewrite)
get_pacing(response,header_length,fileHandle,filewrite)
get_mac_exclusivity(response,header_length,fileHandle,filewrite)
get_mac_addresses(response,header_length,fileHandle,filewrite)
get_netbios_exclusivity(response,header_length,fileHandle,filewrite)
get_netbios_names(response,header_length,fileHandle,filewrite)
get_sap_support(response,header_length,fileHandle,filewrite)

if filewrite == 1:
    # Close the log file
    fileHandle.close()

# Close socket depending on version
if version == "1":
     pass
#    outgoing.close()
elif version == "2":
    channel1.close()
else:
    outgoing.close()
    channel1.close()
    sys.exit(1)

# Explicit exit call
sys.exit(0)

