Module: Rex::Socket::Udp

Includes:
Rex::Socket
Defined in:
lib/rex/socket/udp.rb

Overview

This class provides methods for interacting with a UDP socket.

Constant Summary

Constants included from Rex::Socket

LogSource, MATCH_DNS_NAME, MATCH_IPV4, MATCH_IPV4_PRIVATE, MATCH_IPV6, MATCH_MAC_ADDR, VERSION

Instance Attribute Summary

Attributes included from Rex::Socket

#context, #ipv, #localhost, #localport, #peerhost, #peerhostname, #peerport, #sslkeylogfile

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Rex::Socket

_install_global_resolver, addr_atoc, addr_atoi, addr_atoi_list, addr_aton, addr_ctoa, addr_itoa, addr_iton, addr_ntoa, addr_ntoi, bit2netmask, cidr_crack, compress_address, create_ip, create_tcp, create_tcp_server, create_udp, dotted_ip?, eth_aton, eth_ntoa, #fd, from_sockaddr, getaddress, getaddresses, gethostbyname, #getlocalname, #getpeername_as_array, getresources, #getsockname, #initsock, ipv6_link_address, ipv6_mac, is_internal?, is_ip_addr?, is_ipv4?, is_ipv6?, is_mac_addr?, is_name?, #localinfo, net2bitmask, #peerinfo, portlist_to_portspec, portspec_crack, portspec_to_portlist, resolv_nbo, resolv_nbo_i, resolv_nbo_i_list, resolv_nbo_list, resolv_to_dotted, rex_getaddrinfo, rex_gethostbyname, rex_getresources, rex_resolve_hostname, source_address, support_ipv6?, tcp_socket_pair, to_authority, to_sockaddr, udp_socket_pair

Class Method Details

.create(hash = {}) ⇒ Object

Creates the client using the supplied hash.



22
23
24
25
26
27
28
29
30
31
# File 'lib/rex/socket/udp.rb', line 22

def self.create(hash = {})
  hash['Proto'] = 'udp'
  # If we have are to bind to a LocalHost we must be a Server to avail of pivoting.
  # Rex::Socket::Parameters will subsequently turn off the sever flag after the correct
  # comm has been chosen.
  if( hash['LocalHost'] )
    hash['Server'] = true
  end
  self.create_param(Rex::Socket::Parameters.from_hash(hash))
end

.create_param(param) ⇒ Object

Wrapper around the base socket class’ creation method that automatically sets the parameter’s protocol to UDP.



37
38
39
40
# File 'lib/rex/socket/udp.rb', line 37

def self.create_param(param)
  param.proto = 'udp'
  Rex::Socket.create_param(param)
end

Instance Method Details

#def_read_timeoutObject

The default number of seconds to wait for a read operation to timeout.



197
198
199
# File 'lib/rex/socket/udp.rb', line 197

def def_read_timeout
  10
end

#get(timeout = nil) ⇒ Object

Calls #timed_read and returns the data



190
191
192
# File 'lib/rex/socket/udp.rb', line 190

def get(timeout=nil)
  timed_read(65535, timeout)
end

#read(length = 65535) ⇒ Object

Read a datagram from the UDP socket.



64
65
66
67
68
69
# File 'lib/rex/socket/udp.rb', line 64

def read(length = 65535)
  if length < 0
    length = 65535
  end
  return sysread(length)
end

#recvfrom(maxlen, flags = 0) ⇒ Array(String, Array)

Receives a datagram and returns the data and sender address information as

data, [address_family, port, host, host

], matching stdlib

UDPSocket#recvfrom. Like the stdlib method, this blocks until a datagram is available and has no timeout of its own (see #timed_recvfrom for a variant that does). The host appears in both the hostname and numeric address positions; no reverse-DNS lookup is performed.

Parameters:

  • maxlen (Integer)

    maximum number of bytes to receive

  • flags (Integer) (defaults to: 0)

    flags passed to the underlying recvfrom(2) call (default: 0)

Returns:

  • (Array(String, Array))

    the datagram and the sender address information



149
150
151
152
153
154
155
# File 'lib/rex/socket/udp.rb', line 149

def recvfrom(maxlen, flags = 0)
  # Block until the socket is readable to mirror the stdlib's blocking
  # UDPSocket#recvfrom; a nil timeout waits indefinitely.
  ::IO.select([ fd ], nil, nil, nil)
  data, saddr = recvfrom_nonblock(maxlen, flags)
  [ data, sender_addr_info(saddr) ]
end

#send(mesg, flags, host = nil, port = nil) ⇒ Object

Sends a datagram using the stdlib 4-arg form send(mesg, flags, host, port).

The 4-arg form handles IPv6/IPv4 address mapping and dispatches via BasicSocket#send with a packed sockaddr, so channel/pivoted sockets that override sendto are not involved. Also accepts the 3-arg sockaddr form used by lower-level callers, and the 2-arg connected-socket form.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/rex/socket/udp.rb', line 116

def send(mesg, flags, host = nil, port = nil)
  if host && port
    # Catch unconnected IPv6 sockets talking to IPv4 addresses
    peer = Rex::Socket.resolv_nbo(host)
    if peer.length == 4 && self.ipv == 6
      host_address = Rex::Socket.getaddress(host, true)
      host = '::ffff:' + host_address unless host_address.downcase.start_with?('::ffff:')
    end
    begin
      super(mesg, flags, Rex::Socket.to_sockaddr(host, port))
    rescue ::Errno::EHOSTUNREACH, ::Errno::ENETDOWN, ::Errno::ENETUNREACH, ::Errno::ENETRESET,
           ::Errno::EHOSTDOWN, ::Errno::EACCES, ::Errno::EINVAL, ::Errno::EADDRNOTAVAIL
      nil
    end
  elsif host
    super(mesg, flags, host)
  else
    super(mesg, flags)
  end
end

#sendto(gram, peerhost, peerport, flags = 0) ⇒ Object

Deprecated.

Use #send with the stdlib 4-arg form send(mesg, flags, host, port) instead. Note the argument order differs: sendto(gram, host, port, flags) vs send(mesg, flags, host, port).

Sends a datagram to the supplied host:port with optional flags.



103
104
105
106
# File 'lib/rex/socket/udp.rb', line 103

def sendto(gram, peerhost, peerport, flags = 0)
  warn "#{self.class}#sendto is deprecated; use send(mesg, flags, host, port) instead", uplevel: 1
  send(gram, flags, peerhost, peerport)
end

#timed_read(length = 65535, timeout = def_read_timeout) ⇒ Object

Read a datagram from the UDP socket with a timeout



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rex/socket/udp.rb', line 74

def timed_read(length = 65535, timeout=def_read_timeout)
  begin
    if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
        (rv[0]) and (rv[0][0] == fd)
       )
        return read(length)
    else
      return ''
    end
  rescue Exception
    return ''
  end
end

#timed_recvfrom(maxlen = 65535, timeout = def_read_timeout) ⇒ Array(String, Array)?

Receives a datagram like #recvfrom but waits at most timeout seconds for one to arrive, returning nil if the timeout elapses first. The return value otherwise matches #recvfrom: [ data, [address_family, port, host, host] ].

Parameters:

  • maxlen (Integer) (defaults to: 65535)

    maximum number of bytes to receive

  • timeout (Numeric) (defaults to: def_read_timeout)

    seconds to wait for a datagram before giving up

Returns:

  • (Array(String, Array), nil)

    the datagram and sender address information, or nil if no datagram arrived within timeout seconds



167
168
169
170
171
172
173
174
# File 'lib/rex/socket/udp.rb', line 167

def timed_recvfrom(maxlen = 65535, timeout = def_read_timeout)
  return nil unless ::IO.select([ fd ], nil, nil, timeout)

  data, saddr = recvfrom_nonblock(maxlen)
  [ data, sender_addr_info(saddr) ]
rescue ::Timeout::Error, ::Errno::ECONNREFUSED
  nil
end

#type?Boolean

Returns:

  • (Boolean)


201
202
203
# File 'lib/rex/socket/udp.rb', line 201

def type?
  return 'udp'
end

#write(gram) ⇒ Object Also known as: put

Write the supplied datagram to the connected UDP socket.



51
52
53
54
55
56
57
# File 'lib/rex/socket/udp.rb', line 51

def write(gram)
  begin
    return syswrite(gram)
  rescue  ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
    return nil
  end
end