class Puffy::RuleFactory

Puffy::Rule factory

Public Class Methods

new() click to toggle source

Initialize a Puffy::Rule factory.

# File lib/puffy/rule_factory.rb, line 7
def initialize
  @af = nil
  @resolver = Resolver.instance
  load_services
end

Public Instance Methods

build(options = {}) click to toggle source

Return an Array of Puffy::Rule for the provided options. @param [Hash] options @return [Array<Puffy::Rule>]

# File lib/puffy/rule_factory.rb, line 34
def build(options = {})
  return [] if options == {}

  options = { action: nil, return: false, dir: nil, af: nil, proto: nil, on: nil, from: { host: nil, port: nil }, to: { host: nil, port: nil }, nat_to: nil, rdr_to: { host: nil, port: nil } }.merge(options)

  options = resolv_hostnames_and_ports(options)
  instanciate_rules(options)
end
ipv4() { || ... } click to toggle source

Limit the scope of a set of rules to IPv4 only.

# File lib/puffy/rule_factory.rb, line 14
def ipv4
  raise 'Address familly already scopped' if @af

  @af = :inet
  yield
  @af = nil
end
ipv6() { || ... } click to toggle source

Limit the scope of a set of rules to IPv6 only.

# File lib/puffy/rule_factory.rb, line 23
def ipv6
  raise 'Address familly already scopped' if @af

  @af = :inet6
  yield
  @af = nil
end

Private Instance Methods

af_match_policy?(af) click to toggle source
# File lib/puffy/rule_factory.rb, line 77
def af_match_policy?(af)
  @af.nil? || af.nil? || af == @af
end
host_lookup(host) click to toggle source
# File lib/puffy/rule_factory.rb, line 81
def host_lookup(host)
  case host
  when nil    then nil
  when IPAddr then host
  when String then @resolver.resolv(host)
  when Array  then host.map { |x| @resolver.resolv(x) }.flatten
  else
    raise "Unexpected #{host.class.name}"
  end
end
instanciate_rules(options) click to toggle source
# File lib/puffy/rule_factory.rb, line 54
def instanciate_rules(options)
  options.expand.map do |hash|
    rule = Rule.new(hash)
    rule if af_match_policy?(rule.af)
  rescue AddressFamilyConflict
    nil
  end.compact
end
load_services() click to toggle source
# File lib/puffy/rule_factory.rb, line 63
def load_services
  @services = {}
  File.readlines('/etc/services').each do |line|
    line.sub!(/#.*/, '')
    pieces = line.split
    next if pieces.count < 2

    port = pieces.delete_at(1).to_i
    pieces.each do |piece|
      @services[piece] = port
    end
  end
end
port_is_a_number(port) click to toggle source
# File lib/puffy/rule_factory.rb, line 111
def port_is_a_number(port)
  Integer(port)
rescue ArgumentError
  nil
end
port_lookup(port) click to toggle source
# File lib/puffy/rule_factory.rb, line 92
def port_lookup(port)
  case port
  when nil then nil
  when Integer, Range then port
  when String         then real_port_lookup(port)
  when Array          then port.map { |x| port_lookup(x) }
  else
    raise "Unexpected #{port.class.name}"
  end
end
real_port_lookup(port) click to toggle source
# File lib/puffy/rule_factory.rb, line 103
def real_port_lookup(port)
  res = port_is_a_number(port) || @services[port]

  raise "unknown service \"#{port}\"" unless res

  res
end
resolv_hostnames_and_ports(options) click to toggle source
# File lib/puffy/rule_factory.rb, line 45
def resolv_hostnames_and_ports(options)
  %i[from to rdr_to].each do |endpoint|
    options[endpoint][:host] = host_lookup(options[endpoint][:host])
    options[endpoint][:port] = port_lookup(options[endpoint][:port])
  end
  options[:nat_to] = host_lookup(options[:nat_to])
  options
end