609 lines
16 KiB
Ruby
609 lines
16 KiB
Ruby
##
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
|
|
class MetasploitModule < Msf::Auxiliary
|
|
|
|
include Msf::Exploit::Remote::Tcp
|
|
include Msf::Auxiliary::Scanner
|
|
include Msf::Auxiliary::Report
|
|
|
|
def initialize
|
|
super(
|
|
'Name' => 'H.323 Version Scanner',
|
|
'Description' => 'Detect H.323 Version.',
|
|
'Author' => 'hdm',
|
|
'License' => MSF_LICENSE
|
|
)
|
|
|
|
register_options(
|
|
[
|
|
Opt::RPORT(1720),
|
|
], self.class)
|
|
end
|
|
|
|
def run_host(ip)
|
|
|
|
remote_display = nil
|
|
remote_product_id = nil
|
|
remote_version_id = nil
|
|
remote_vendor_id = nil
|
|
remote_protocol = nil
|
|
|
|
begin
|
|
|
|
# Wrap this in a timeout to prevent dead services from
|
|
# hanging this thread.
|
|
Timeout.timeout( call_timeout) do
|
|
|
|
connect
|
|
|
|
caller_name = "SYSTEM\x00"
|
|
h323_id = Rex::Text.rand_text_alpha(3)
|
|
vendor_id = Rex::Text.rand_text_alpha(32)
|
|
caller_host = Rex::Socket.source_address( ip )
|
|
caller_port = rand( 32768 ) + 30000
|
|
callee_host = rhost
|
|
callee_port = rport
|
|
conf_guid = Rex::Text.rand_text(16)
|
|
call_guid = Rex::Text.rand_text(16)
|
|
|
|
pkt_setup = h323_setup_call({
|
|
:caller_name => caller_name,
|
|
:h323_id => h323_id,
|
|
:vendor_id => vendor_id,
|
|
:callee_host => callee_host,
|
|
:callee_port => callee_port,
|
|
:caller_host => caller_host,
|
|
:caller_port => caller_port,
|
|
:conf_guid => conf_guid,
|
|
:call_guid => call_guid
|
|
})
|
|
|
|
res = sock.put(pkt_setup) rescue nil
|
|
if not res
|
|
disconnect
|
|
return
|
|
end
|
|
|
|
cnt = 0
|
|
while( true )
|
|
info = read_packet
|
|
break if not info
|
|
|
|
# The remote side of the call disconnected us
|
|
break if info[:type] == @@H323_STATUS_RELEASE_COMPLETE
|
|
|
|
remote_display = info[40].strip if info[40]
|
|
remote_product_id = info[:product_id].strip if info[:product_id]
|
|
remote_version_id = info[:version_id].strip if info[:version_id]
|
|
remote_protocol = info[:protocol_version].strip if info[:protocol_version]
|
|
|
|
if info[:vendor_id] and [nil, "Unknown"].include?( remote_vendor_id )
|
|
remote_vendor_id = info[:vendor_id].strip
|
|
end
|
|
|
|
# Diagnostics
|
|
# print_status("Host: #{rhost}:#{rport} => #{info.inspect}")
|
|
|
|
# The remote side of the call was connected (kill it)
|
|
break if info[:type] == @@H323_STATUS_CONNECT
|
|
|
|
# Exit if we already received 5 packets from the server
|
|
break if (cnt +=1) > 5
|
|
|
|
end
|
|
|
|
# Make sure the call was shut down cleanly
|
|
pkt_release = h323_release_call({
|
|
:caller_name => caller_name,
|
|
:call_guid => call_guid
|
|
})
|
|
sock.put(pkt_release) rescue nil
|
|
|
|
# End timeout block
|
|
end
|
|
|
|
rescue ::Timeout::Error
|
|
rescue ::Interrupt
|
|
raise $!
|
|
rescue ::Rex::ConnectionError, ::IOError, ::Errno::ECONNRESET, ::Errno::ENOPROTOOPT
|
|
rescue ::Exception
|
|
print_error("#{rhost}:#{rport} #{$!.class} #{$!} #{$!.backtrace}")
|
|
ensure
|
|
disconnect
|
|
end
|
|
|
|
if remote_vendor_id
|
|
remote_product_id = remote_product_id.to_s.gsub(/[^\x20-\x7e]/, '')
|
|
remote_version_id = remote_version_id.to_s.gsub(/[^\x20-\x7e]/, '')
|
|
|
|
banner = "Protocol: #{ remote_protocol } VendorID: #{ remote_vendor_id } "
|
|
|
|
if remote_version_id and remote_version_id.length > 0
|
|
banner << "VersionID: #{ remote_version_id } "
|
|
end
|
|
|
|
if remote_product_id and remote_product_id.length > 0
|
|
banner << "ProductID: #{ remote_product_id } "
|
|
end
|
|
|
|
if remote_display and remote_display.length > 0
|
|
remote_display = remote_display.to_s.gsub(/[^\x20-\x7e]/, '')
|
|
banner << "DisplayName: #{ remote_display }"
|
|
end
|
|
|
|
print_status("#{rhost}:#{rport} #{banner}")
|
|
report_service(:host => rhost, :port => rport, :name => "h323", :info => banner)
|
|
end
|
|
|
|
end
|
|
|
|
def read_packet
|
|
begin
|
|
::Timeout.timeout( read_timeout ) do
|
|
ver = sock.read(2)
|
|
return if not (ver and ver == "\x03\x00")
|
|
|
|
bin = sock.read(2)
|
|
return if not bin
|
|
|
|
len = [ bin.unpack("n")[0] - 4, 0 ].max
|
|
return if len == 0
|
|
|
|
bin = sock.read(len)
|
|
return if not bin
|
|
|
|
f_desc, cref_len = bin.unpack("CC")
|
|
cref_val = bin[2, cref_len]
|
|
f_type = bin[2 + cref_len, 1].unpack("C")[0]
|
|
|
|
return { :type => f_type, :call_ref => cref_val }.merge( read_ies(f_type, bin[ 2 + cref_len + 1, bin.length] ) )
|
|
end
|
|
rescue ::Timeout::Error
|
|
end
|
|
nil
|
|
end
|
|
|
|
def read_ies(mtype, data)
|
|
r = { }
|
|
i = 0
|
|
|
|
while( i < (data.length - 1) )
|
|
ie_type = data[i, 1].unpack("C")[0]
|
|
break if not ie_type
|
|
|
|
ie_len = 0
|
|
ie_data = ""
|
|
|
|
case ie_type
|
|
when @@H225_IE_USER_USER
|
|
ie_len = data[i+1, 2].unpack("n")[0]
|
|
break if not ie_len
|
|
|
|
ie_data = data[i+3, ie_len]
|
|
break if not ie_data
|
|
|
|
i = i + 3 + ie_len
|
|
else
|
|
ie_len = data[i+1, 1].unpack("C")[0]
|
|
break if not ie_len
|
|
|
|
ie_data = data[i+2, ie_len]
|
|
break if not ie_data
|
|
|
|
i = i + 2 + ie_len
|
|
end
|
|
|
|
r[ ie_type ] = ie_data
|
|
|
|
if ie_type == @@H225_IE_USER_USER
|
|
r.merge!( ( read_user_user(mtype, ie_data) rescue {} ) )
|
|
end
|
|
end
|
|
r
|
|
end
|
|
|
|
|
|
# This provides a weak method of decoding USER-USER PDUs. These are
|
|
# actually PER-encoded ASN.1, but we take a few shortcuts since PER
|
|
# encoding is such a pain.
|
|
def read_user_user(mtype, data)
|
|
r = {}
|
|
|
|
# Identify the embedded version (2/3/4/5/6 commonly found)
|
|
i = data.index("\x00\x08\x91\x4a\x00")
|
|
return r if not i
|
|
|
|
# Store the protocol version
|
|
pver = data[i + 5, 1].unpack("C")[0]
|
|
|
|
r[:protocol_version] = pver.to_s
|
|
|
|
# Bump the index over the version
|
|
i+= 6
|
|
|
|
# print_line( Rex::Text.to_hex_dump( data[i, 32] ) )
|
|
|
|
# Set a placeholder VendorID so this system will be reported
|
|
r[:vendor_id] = "Unknown"
|
|
|
|
# We use the version offset to identify the destination block location
|
|
# This changes slightly based on the type of packet we receive
|
|
case mtype
|
|
when @@H323_STATUS_ALERTING, @@H323_STATUS_PROCEEDING
|
|
|
|
if pver == 2 and data[i, 2] == "\x20\x00"
|
|
r[ :vendor_id ] = "0x%.8x" % ( data[i + 2, 4].unpack("N")[0] rescue 0 )
|
|
return r
|
|
end
|
|
|
|
# Find the offset to the VendorID
|
|
if data[i + 1, 1] != "\xc0"
|
|
i+= 7
|
|
end
|
|
|
|
# Stop processing if we can't identify a VendorID
|
|
return r if data[i + 1, 1] != "\xc0"
|
|
|
|
# Otherwise just add 2 to the offset of the version
|
|
i += 2
|
|
|
|
when @@H323_STATUS_CONNECT
|
|
|
|
# Bail early in some corner cases
|
|
return r if data[i, 1] == "\x00"
|
|
|
|
# Find the offset to the VendorID
|
|
if data[i + 1, 1] != "\xc0"
|
|
i+= 7
|
|
end
|
|
|
|
# Stop processing if we can't identify a VendorID
|
|
return r if data[i + 1, 1] != "\xc0"
|
|
|
|
i += 2
|
|
|
|
return r
|
|
else
|
|
return r
|
|
end
|
|
|
|
# Extract the manufacturer ID
|
|
r[ :vendor_id ] = "0x%.8x" % ( data[i, 4].unpack("N")[0] rescue 0 )
|
|
i+= 4
|
|
|
|
# No Product ID / Version ID in versions less than 3 (unless special cased above)
|
|
return r if pver < 3
|
|
|
|
# Get the product_id length (-1)
|
|
product_id_length = data[i, 1].unpack("C")[0] + 1
|
|
i+= 1
|
|
|
|
# Extract the product ID
|
|
r[ :product_id ] = data[i, product_id_length]
|
|
i+= product_id_length
|
|
|
|
# Get the version ID length (-1)
|
|
version_id_length = data[i, 1].unpack("C")[0] + 1
|
|
i+= 1
|
|
|
|
# Extract the version ID
|
|
r[ :version_id ] = data[i, version_id_length]
|
|
|
|
# Thats it for now
|
|
|
|
r
|
|
end
|
|
|
|
def read_timeout
|
|
10
|
|
end
|
|
|
|
def call_timeout
|
|
30
|
|
end
|
|
|
|
|
|
@@H225_IE_BEARER_CAP = 0x04
|
|
@@H225_IE_DISPLAY = 0x28
|
|
@@H225_IE_USER_USER = 0x7e # Yes, really User-user
|
|
|
|
|
|
@@H323_STATUS_ALERTING = 0x01
|
|
@@H323_STATUS_PROCEEDING = 0x02
|
|
@@H323_STATUS_SETUP = 0x05
|
|
@@H323_STATUS_SETUP_ACK = 0x0D
|
|
@@H323_STATUS_CONNECT = 0x07
|
|
@@H323_STATUS_RELEASE_COMPLETE = 0x5a
|
|
@@H323_STATUS_FACILITY = 0x62
|
|
|
|
|
|
def encap_tpkt(ver,data)
|
|
[ ver, 0, data.length + 4 ].pack("CCn") + data
|
|
end
|
|
|
|
def encap_q225(desc, cref_value, msg_type, data)
|
|
[ desc, cref_value.length, cref_value, msg_type].pack("CCA*C") + data
|
|
end
|
|
|
|
def encap_q225_standard(msg_type, data)
|
|
encap_q225(0x08, [0x733f].pack("n"), msg_type, data)
|
|
end
|
|
|
|
def encap_q225_setup(data)
|
|
encap_q225_standard(0x05, data)
|
|
end
|
|
|
|
def encap_q225_release(data)
|
|
encap_q225_standard(0x5a, data)
|
|
end
|
|
|
|
def create_ie_byte(ie_type, data)
|
|
[ie_type, data.length].pack("CC") + data
|
|
end
|
|
|
|
def create_ie_short(ie_type, data)
|
|
[ie_type, data.length].pack("Cn") + data
|
|
end
|
|
|
|
def create_ie_bearer_capability(cap = 0x00038893)
|
|
create_ie_byte( @@H225_IE_BEARER_CAP, [cap].pack("N")[0,3] )
|
|
end
|
|
|
|
def create_ie_display(name = "DEBUG\x00")
|
|
create_ie_byte( @@H225_IE_DISPLAY, name )
|
|
end
|
|
|
|
def create_ie_user_user(data)
|
|
create_ie_short( @@H225_IE_USER_USER, data )
|
|
end
|
|
|
|
#
|
|
# This is ugly. Doing it properly requires a PER capable ASN.1 encoder, which is overkill for this task
|
|
#
|
|
def create_user_info(opts = {})
|
|
h323_id = opts[:h323_id]
|
|
vendor_id = opts[:vendor_id]
|
|
callee_host = opts[:callee_host]
|
|
callee_port = opts[:callee_port]
|
|
caller_host = opts[:caller_host]
|
|
caller_port = opts[:caller_port]
|
|
conf_guid = opts[:conf_guid]
|
|
call_guid = opts[:call_guid]
|
|
|
|
buff = "\x05" # Protocol descriminator: X.208/X.209 coded user information
|
|
|
|
buff << "\x20\xa8\x06\x00\x08\x91\x4a\x00\x06\x01\x40\x02"
|
|
|
|
# H323-ID
|
|
buff << h323_id.unpack("C*").pack("n*")
|
|
|
|
buff << "\x22\xc0\x09\x00\x00\x3d\x02\x00\x00\x00\x21"
|
|
|
|
# VENDOR: 32 + 2 null bytes
|
|
buff << [vendor_id].pack("Z32") + "\x00\x00"
|
|
|
|
buff << "\x00"
|
|
|
|
# Remote IP + Remote Port
|
|
buff << ( ::Rex::Socket.addr_aton( callee_host ) + [ callee_port.to_i ].pack("n") )
|
|
|
|
buff << "\x00"
|
|
|
|
# Conference GUID
|
|
buff << conf_guid
|
|
|
|
buff << "\x00\xc5\x1d\x80\x04\x07\x00"
|
|
|
|
# Local IP + Port
|
|
buff << ( ::Rex::Socket.addr_aton( caller_host ) + [ caller_port.to_i ].pack("n") )
|
|
|
|
buff << "\x11\x00"
|
|
|
|
# Call GUID
|
|
buff << call_guid
|
|
|
|
buff <<
|
|
"\x82\x49\x10\x47\x40\x00\x00\x06\x04\x01\x00\x4c\x10\xb5" +
|
|
"\x00\x00\x26\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31" +
|
|
"\x36\x30\x30\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62" +
|
|
"\x72\x3d\x6f\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80" +
|
|
"\x12\x1c\x40\x01\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc6\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x90\x3c\x00\x00\x64\x0c\x10\xb5\x00\x00\x26\x25" +
|
|
"\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30\x30" +
|
|
"\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f\x66" +
|
|
"\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x0b\x0d\x40\x01" +
|
|
"\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x48\x31\x40\x00\x00\x06\x04\x01\x00\x4c\x10\x09" +
|
|
"\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20" +
|
|
"\x57\x69\x64\x65\x36\x80\x12\x1c\x40\x01\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc6\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\xa0\x26\x00\x00\x65\x0c\x10\x09\x00\x00\x3d\x0f" +
|
|
"\x53\x70\x65\x65\x78\x20\x62\x73\x34\x20\x57\x69\x64\x65" +
|
|
"\x36\x80\x0b\x0d\x40\x01\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x50\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x60\x13" +
|
|
"\x80\x11\x1c\x00\x01\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc6\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x13\x00\x00\x66\x0c\x60\x13\x80\x0b\x0d\x00\x01" +
|
|
"\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x00\x1d\x40\x00\x00\x06\x04\x01\x00\x4c\x20\x13" +
|
|
"\x80\x11\x1c\x00\x01\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc6\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x13\x00\x00\x67\x0c\x20\x13\x80\x0b\x0d\x00\x01" +
|
|
"\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc7\x00\x23\x40\x00\x00\x06\x04\x01\x00\x48\x78\x00" +
|
|
"\x4a\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc8\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x19\x00\x00\x68\x08\x78\x00\x4a\xff\x00\x80\x01" +
|
|
"\x00\x80\x0b\x0d\x00\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x68\x4a" +
|
|
"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc8\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x18\x00\x00\x69\x08\x68\x4a\xff\x00\x80\x01\x00" +
|
|
"\x80\x0b\x0d\x00\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x00\x22\x40\x00\x00\x06\x04\x01\x00\x48\x70\x4a" +
|
|
"\xff\x00\x80\x01\x00\x80\x11\x1c\x00\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc8\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x18\x00\x00\x6a\x08\x70\x4a\xff\x00\x80\x01\x00" +
|
|
"\x80\x0b\x0d\x00\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x00\x2c\x40\x00\x00\x06\x04\x01\x00\x48\xee\x00" +
|
|
"\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x17\x1c\x20\x02" +
|
|
"\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc8\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x80\x04\x48\x08\x8d\x44\x22\x00\x00\x6b\x08\xee" +
|
|
"\x00\x00\x20\x9f\xff\x20\x50\x40\x01\x00\x80\x11\x0d\x20" +
|
|
"\x02\x00" +
|
|
|
|
Rex::Socket.addr_aton( caller_host ) +
|
|
|
|
"\x13\xc9\x40\x00\x04\x48\x08\x8d\x44\x01\x00\x01\x00\x01" +
|
|
"\x00\x01\x00\x80\xfa\x02\x80\xef\x02\x70\x01\x06\x00\x08" +
|
|
"\x81\x75\x00\x0d\x80\x1a\x80\x01\xf4\x00\x01\x00\x00\x01" +
|
|
"\x00\x00\x01\x00\x04\x02\x05\x00\x48\x08\x8d\x44\x06\x60" +
|
|
"\x01\x00\x01\x80\x0b\x80\x00\x00\x20\x20\xb5\x00\x00\x26" +
|
|
"\x25\x73\x70\x65\x65\x78\x20\x73\x72\x3d\x31\x36\x30\x30" +
|
|
"\x30\x3b\x6d\x6f\x64\x65\x3d\x36\x3b\x76\x62\x72\x3d\x6f" +
|
|
"\x66\x66\x3b\x63\x6e\x67\x3d\x6f\x66\x66\x80\x00\x01\x20" +
|
|
"\x20\x09\x00\x00\x3d\x0f\x53\x70\x65\x65\x78\x20\x62\x73" +
|
|
"\x34\x20\x57\x69\x64\x65\x36\x80\x00\x02\x20\xc0\xef\x80" +
|
|
"\x00\x03\x20\x40\xef\x80\x00\x04\x08\xf0\x00\x4a\xff\x00" +
|
|
"\x80\x01\x00\x80\x00\x05\x08\xd0\x4a\xff\x00\x80\x01\x00" +
|
|
"\x80\x00\x06\x08\xe0\x4a\xff\x00\x80\x01\x00\x80\x00\x07" +
|
|
"\x09\xdc\x00\x00\x40\x9f\xff\x20\x50\x40\x01\x00\x80\x00" +
|
|
"\x08\x83\x01\x50\x80\x00\x09\x83\x01\x10\x80\x00\x0a\x83" +
|
|
"\x01\x40\x80\x00\x0b\x8a\x0c\x14\x0a\x30\x2d\x31\x36\x2c" +
|
|
"\x33\x32\x2c\x33\x36\x00\x80\x01\x03\x03\x00\x00\x00\x01" +
|
|
"\x00\x02\x00\x03\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00" +
|
|
"\x00\x08\x02\x00\x09\x00\x0a\x00\x0b\x07\x01\x00\x32\x80" +
|
|
"\x96\x61\x41\x02\x80\x01\x80"
|
|
|
|
buff
|
|
end
|
|
|
|
def create_user_release_info(call_guid)
|
|
"\x05" +
|
|
"\x25\x80\x06\x00\x08\x91\x4a\x00\x05\x01\x11\x00" +
|
|
call_guid +
|
|
"\x02\x80\x01\x00"
|
|
end
|
|
|
|
def h323_release_call(opts = {})
|
|
caller_name = opts[:caller_name]
|
|
call_guid = opts[:call_guid]
|
|
|
|
encap_tpkt(3,
|
|
encap_q225_release(
|
|
create_ie_display(caller_name) +
|
|
create_ie_user_user(
|
|
create_user_release_info(call_guid )
|
|
)
|
|
)
|
|
)
|
|
end
|
|
|
|
def h323_setup_call(opts = {})
|
|
caller_name = opts[:caller_name]
|
|
h323_id = opts[:h323_id]
|
|
vendor_id = opts[:vendor_id]
|
|
callee_host = opts[:callee_host]
|
|
callee_port = opts[:callee_port]
|
|
caller_host = opts[:caller_host]
|
|
caller_port = opts[:caller_port]
|
|
conf_guid = opts[:conf_guid]
|
|
call_guid = opts[:call_guid]
|
|
|
|
encap_tpkt(3,
|
|
encap_q225_setup(
|
|
create_ie_bearer_capability() +
|
|
create_ie_display(caller_name) +
|
|
create_ie_user_user(
|
|
create_user_info({
|
|
:h323_id => h323_id,
|
|
:vendor_id => vendor_id,
|
|
:callee_host => callee_host,
|
|
:callee_port => callee_port,
|
|
:caller_host => caller_host,
|
|
:caller_port => caller_port,
|
|
:conf_guid => conf_guid,
|
|
:call_guid => call_guid
|
|
})
|
|
)
|
|
)
|
|
)
|
|
end
|
|
end
|