#!/usr/bin/ruby
#
# Details: Fgen subsystem, Huawei rule generator
# Authors: Dmitry Maksyoma <dmaksema@allot.com>
# Started: 11/2009

$:.insert(-2, File.join(File.dirname(File.expand_path($0)), '../lib'))
require 'pattern/entities'
require 'fgen/formatters'
require 'fgen/common'
include Entities

SUPPORTED_PROTOCOL_NAMES = {}
%w(gre icmp igmp ipip ospf tcp udp).each { |p|
  id = IPHeader.desc_proto[p]
  SUPPORTED_PROTOCOL_NAMES[id] = p if id
}
SUPPORTED_PROTOCOL_NAMES[94] = SUPPORTED_PROTOCOL_NAMES['ipip']

def format_pattern pattern, name, src_ips, dst_ips
  return unless pattern.ip

  res = ['acl 3999']

  unless src_ips || dst_ips
    ips = [pattern.ip[:srcip], pattern.ip[:dstip]].map { |ip|
      next if !ip[0] || ip.join.empty?

      gotNil, i, mask = false, 0, [0, 0, 0, 0]
      ip.map! { |o|
	gotNil = true unless o

	ret = unless gotNil
	  o
	else
	  mask[i] = 255
	  0
	end
	i += 1
	ret
      }.join('.') << ' ' << (gotNil ? mask.join('.') : '0')
    }
    res << make_stmt(pattern, *ips)
  else
    if src_ips
      src_ips.map! { |ip| ip + ' 0' }
    else 
      src_ips = [nil]
    end
    if dst_ips
      dst_ips.map! { |ip| ip + ' 0' }
    else 
      dst_ips = [nil]
    end
    src_ips.each { |src_ip|
      dst_ips.each { |dst_ip| res << make_stmt(pattern, src_ip, dst_ip) }
    }
  end
  res.join("\n")
end

def make_stmt pattern, src_ip=nil, dst_ip=nil
  ipl, ippl = pattern.ip, pattern.ipp
  res = ["rule deny #{SUPPORTED_PROTOCOL_NAMES[ipl.proto] || ipl.proto || 'ip'}"]

  if ipl.proto_icmp
    res << "source #{src_ip}" if src_ip
    res << "destination #{dst_ip}" if dst_ip
    res << "icmp-type #{ippl.itype} #{ippl.icode}" \
      if ippl && ippl.itype && ippl.icode
  elsif ipl.proto_tcp || ipl.proto_udp
    res << "source #{src_ip}" if src_ip
    res << "source-port eq #{ippl.srcport}" if ippl && ippl.srcport
    res << "destination #{dst_ip}" if dst_ip
    res << "destination-port eq #{ippl.dstport}" if ippl && ippl.dstport
  else
    res << "source #{src_ip}" if src_ip
    res << "destination #{dst_ip}" if dst_ip
    res << "dscp #{ipl.dscp}" if ipl.dscp
  end
  res << 'fragment' if ipl.frag_offset && ipl.frag_offset > 0
  res.join ' '
end

do_format
