Class: Rex::Socket::SwitchBoard

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Singleton
Defined in:
lib/rex/socket/switch_board.rb

Overview

This class provides a global routing table that associates subnets with Comm classes. Comm classes are used to instantiate objects that are tied to remote network entities. For example, the Local Comm class is used to building network connections directly from the local machine whereas, for instance, a Meterpreter Comm would build a local socket pair that is associated with a connection established by a remote entity. This can be seen as a uniform way of communicating with hosts through arbitrary channels.

Defined Under Namespace

Classes: Route

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSwitchBoard

Returns a new instance of SwitchBoard


26
27
28
# File 'lib/rex/socket/switch_board.rb', line 26

def initialize
  @_initialized = false
end

Instance Attribute Details

#mutexObject

The mutex protecting the routes array.


269
270
271
# File 'lib/rex/socket/switch_board.rb', line 269

def mutex
  @mutex
end

#routesObject

The routes array.


265
266
267
# File 'lib/rex/socket/switch_board.rb', line 265

def routes
  @routes
end

Class Method Details

.add_route(subnet, mask, comm) ⇒ Object

Adds a route to the switch board routing table using the supplied Comm instance.


77
78
79
80
81
82
83
# File 'lib/rex/socket/switch_board.rb', line 77

def self.add_route(subnet, mask, comm)
  ret = self.instance.add_route(subnet, mask, comm)
  if ret && comm.respond_to?(:routes) && comm.routes.kind_of?(Array)
    comm.routes << "#{subnet}/#{mask}"
  end
  ret
end

.best_comm(addr) ⇒ Object

Returns the Comm instance that should be used for the supplied address. If no comm can be found, the default Local Comm is returned.


126
127
128
# File 'lib/rex/socket/switch_board.rb', line 126

def self.best_comm(addr)
  self.instance.best_comm(addr)
end

.each(&block) ⇒ Object

Enumerate each route in the routing table.


107
108
109
# File 'lib/rex/socket/switch_board.rb', line 107

def self.each(&block)
  self.instance.each(&block)
end

.flush_routesObject

Flush all the routes from the switch board routing table.


100
101
102
# File 'lib/rex/socket/switch_board.rb', line 100

def self.flush_routes
  ret = self.instance.flush_routes
end

.remove_by_comm(comm) ⇒ Object

Removes all routes that go through the supplied Comm.


133
134
135
# File 'lib/rex/socket/switch_board.rb', line 133

def self.remove_by_comm(comm)
  self.instance.remove_by_comm(comm)
end

.remove_route(subnet, mask, comm) ⇒ Object

Removes a route from the switch board routing table for the supplied subnet routing through the supplied Comm instance.


89
90
91
92
93
94
95
# File 'lib/rex/socket/switch_board.rb', line 89

def self.remove_route(subnet, mask, comm)
  ret = self.instance.remove_route(subnet, mask, comm)
  if ret && comm.respond_to?(:routes) && comm.routes.kind_of?(Array)
    comm.routes.delete "#{subnet}/#{mask}"
  end
  ret
end

.route_exists?(subnet, mask) ⇒ Boolean

Returns:

  • (Boolean)

118
119
120
# File 'lib/rex/socket/switch_board.rb', line 118

def self.route_exists?(subnet, mask)
  self.instance.route_exists?(subnet, mask)
end

.routesObject

Returns the array of routes.


114
115
116
# File 'lib/rex/socket/switch_board.rb', line 114

def self.routes
  self.instance.routes
end

Instance Method Details

#add_route(subnet, mask, comm) ⇒ Object

Adds a route for a given subnet and netmask destined through a given comm instance.


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/rex/socket/switch_board.rb', line 147

def add_route(subnet, mask, comm)
  # If a bitmask was supplied, convert it.
  netmask = (mask.to_s =~ /^\d+$/) ? Rex::Socket.bit2netmask(mask.to_i) : mask
  rv      = true

  _init

  mutex.synchronize {
    # If the route already exists, return false to the caller.
    if (route_exists?(subnet, netmask) == false)
      self.routes << Route.new(subnet, netmask, comm)
    else
      rv = false
    end
  }

  rv
end

#best_comm(addr) ⇒ Object

Finds the best possible comm for the supplied target address.


231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/rex/socket/switch_board.rb', line 231

def best_comm(addr)

  addr_nbo = Socket.resolv_nbo_i(addr)
  comm     = nil
  msb      = 0

  each { |route|
    if ((route.subnet_nbo & route.netmask_nbo) ==
        (addr_nbo & route.netmask_nbo))
      if (route.bitmask >= msb)
        comm = route.comm
        msb  = route.bitmask
      end
    end
  }

  comm
end

#each(&block) ⇒ Object

Enumerates each entry in the routing table.


222
223
224
225
226
# File 'lib/rex/socket/switch_board.rb', line 222

def each(&block)
  _init

  routes.each(&block)
end

#flush_routesObject

Flushes all established routes.


193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/rex/socket/switch_board.rb', line 193

def flush_routes
  _init

  # Remove each of the individual routes so the comms don't think they're
  # still routing after a flush.
  self.routes.each { |r|
    if r.comm.respond_to? :routes
      r.comm.routes.delete("#{r.subnet}/#{r.netmask}")
    end
  }
  # Re-initialize to an empty array
  self.routes = Array.new
end

#remove_by_comm(comm) ⇒ Object

Remove all routes that go through the supplied comm.


253
254
255
256
257
258
259
260
# File 'lib/rex/socket/switch_board.rb', line 253

def remove_by_comm(comm)
  _init
  mutex.synchronize {
    routes.delete_if { |route|
      route.comm == comm
    }
  }
end

#remove_route(subnet, mask, comm) ⇒ Object

Removes a route for a given subnet and netmask destined through a given comm instance.


170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/rex/socket/switch_board.rb', line 170

def remove_route(subnet, mask, comm)
  # If a bitmask was supplied, convert it.
  netmask = (mask.to_s =~ /^\d+$/) ? Rex::Socket.bit2netmask(mask.to_i) : mask
  rv      = false

  _init

  mutex.synchronize {
    self.routes.delete_if { |route|
      if (route.subnet == subnet and route.netmask == netmask and route.comm == comm)
        rv = true
      else
        false
      end
    }
  }

  rv
end

#route_exists?(subnet, netmask) ⇒ Boolean

Checks to see if a route already exists for the supplied subnet and netmask.

Returns:

  • (Boolean)

211
212
213
214
215
216
217
# File 'lib/rex/socket/switch_board.rb', line 211

def route_exists?(subnet, netmask)
  each { |route|
    return true if (route.subnet == subnet and route.netmask == netmask)
  }

  false
end