/* 

                          Firewall Builder

                 Copyright (C) 2002 Vadim Kurland

  Author:  Vadim Kurland     vadim@vk.crocodile.org

  $Id: PolicyCompiler.hh,v 1.23 2002/06/06 18:40:43 vkurland Exp $

  This program is free software which we release under the GNU General Public
  License. You may redistribute and/or modify this program under the terms
  of that license as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  To get a copy of the GNU General Public License, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#ifndef __POLICY_COMPILER_HH__
#define __POLICY_COMPILER_HH__

#include "fwcompiler/Compiler.hh"
#include "fwbuilder/Rule.hh"

#include <string>

namespace fwcompiler {


/**
 *  This exception composes simple error message in constructor.
 *  Since this exception is derived from FWException, programs that
 *  catch FWException will simply print that error message. If program
 *  needs to extract more data from both rules, it should catch
 *  FWCompilerRuleShadingException and use getRule1 and getRule2 to
 *  access rules.
 */
    class FWCompilerRuleShadingException : public libfwbuilder::FWException {
	libfwbuilder::Rule *rule1;
	libfwbuilder::Rule *rule2;
	public:
	FWCompilerRuleShadingException(libfwbuilder::Rule *r1,
				       libfwbuilder::Rule *r2);
	libfwbuilder::Rule *getRule1() const { return rule1; }
	libfwbuilder::Rule *getRule2() const { return rule2; }
    };

    #define DECLARE_POLICY_RULE_PROCESSOR(_Name) \
        friend class _Name; \
	class _Name : public PolicyRuleProcessor { \
		public: \
		_Name(const std::string &n) :  \
			PolicyRuleProcessor(n) {}; \
                virtual ~_Name() {}; \
		virtual bool processNext(); \
	};


    class PolicyCompiler : public Compiler {

	protected:

        /**
         * prints rule in some universal format (close to that visible
         * to user in the GUI). Used for debugging purposes
         */
        virtual std::string debugPrintRule(libfwbuilder::Rule *rule);

	
	/**
	 *  this method scans combined_ruleset looking for atomic rule
	 *  which yields non-empty intersection with atomic rule r.
	 *  
	 *  it can start scan either from the beginning of combined_ruleset,
	 *  or from iterator 'start_here'
	 *
	 *  it returns iterator pointing at rule it has found (so we
	 *  can continue search later)
	 *
	 *  if parameter 'intersection' is not NULL, it is assumed to
	 *  be a pointer to a pointer at the object of class Rule. It
	 *  is used to return a pointer at intersection of rule 'rule'
	 *  and rule this function had found
	 */
	std::list<libfwbuilder::FWObject*>::iterator 
	find_more_specific_rule(libfwbuilder::PolicyRule *r,
                                bool check_interface,
                                const std::list<libfwbuilder::FWObject*>::iterator &start_here,
                                const std::list<libfwbuilder::FWObject*>::iterator &stop_here,
                                libfwbuilder::PolicyRule **intersection=NULL);



	public:

	PolicyCompiler(libfwbuilder::FWObjectDatabase *_db,
		       const std::string &fwname,
		       fwcompiler::OSConfigurator *_oscnf)   : Compiler(_db,fwname,_oscnf) {}

	/**
	 * this method substracts atomic rule r2 from atomic rule r1.
	 * Resulting rule may have multiple objects in src,dst or srv,
	 * so converting to atomic may be necessary. If rules can not
	 * be compared, then it throws an exception. If resultant rule
	 * is empty, method returns rule with empty src,dst,srv
	 *
	 * NOT IMPLEMENTED YET 
	 */
	libfwbuilder::Rule* getDifference(const libfwbuilder::PolicyRule &r1,
					  const libfwbuilder::PolicyRule &r2);



	/**
	 * this class expands groups in src,dst,srv. It creates
	 * references to new objects "in place" (that is, it does not
	 * create new rules but rather uses rule elements of the old
	 * ones)
	 */
        DECLARE_POLICY_RULE_PROCESSOR(ExpandGroups);

	/**
	 *  this inspector replaces references to hosts and firewalls
	 *  in src or dst with references to their interfaces
	 *
	 * TODO: move to class Compiler because this might be useful
	 * for both PolicyCompiler and NATCompiler
	 */
        DECLARE_POLICY_RULE_PROCESSOR(ExpandMultipleAddresses);

	/**
	 * this processor splits rule element if src or dst contains
	 * address range
	 */
        DECLARE_POLICY_RULE_PROCESSOR(addressRanges);

	/**
	 * split rules with more than one service object, so that each
	 * rule has services with the same protocol
	 */
        DECLARE_POLICY_RULE_PROCESSOR(splitServices);

	/**
	 * separate TCP services with flags (can't use those in combination
	 * with others in groups of services)
	 */
        DECLARE_POLICY_RULE_PROCESSOR(separateTCPWithFlags);

	/**
	 * verify if custom services used in rules are configured for
	 * this platform
	 */
        DECLARE_POLICY_RULE_PROCESSOR(verifyCustomServices);

	/**
	 * this processor converts to atomic rules using all combinations
	 * of objects in Src,Dst. It ignores Srv.
	 */
        DECLARE_POLICY_RULE_PROCESSOR(ConvertToAtomicForAddresses);

	/**
	 * this processor splits rule so that each atomic rule has
	 * exactly one Interval rule element
	 */
        DECLARE_POLICY_RULE_PROCESSOR(ConvertToAtomicForIntervals);

	/**
	 * this processor converts to atomic rules
	 */
        DECLARE_POLICY_RULE_PROCESSOR(ConvertToAtomic);

        /**
         * this is a base class for the family of rule processors that
         * need to be able to find more general rule rule
         */
        class findMoreGeneralRule : public PolicyRuleProcessor 
        {
            protected:
            /**
             *  this method scans tmp_queue looking for atomic rule
             *  which is more general than atomic rule 'r'. 
             *
             *  it can starts scan at position defined by iterator
             *  start_here and ends it at the position given by
             *  iterator stop_here
             *
             *  it returns iterator pointing at the rule it has found (so we
             *  can continue search later)
             */
            std::deque<libfwbuilder::Rule*>::iterator 
            find_more_general_rule(libfwbuilder::PolicyRule *r,
                                   bool check_interface,
                                   const std::deque<libfwbuilder::Rule*>::iterator &start_here,
                                   const std::deque<libfwbuilder::Rule*>::iterator &stop_here);
            public:
            findMoreGeneralRule(const std::string &n) : PolicyRuleProcessor(n) {}
        };


	/**
	 * this inspector scans rules and detects those which "shade"
	 * other rules below them
	 */
        class DetectShading : public findMoreGeneralRule
        {
            std::deque<libfwbuilder::Rule*> rules_seen_so_far;
            public:
            DetectShading(const std::string &n) : findMoreGeneralRule(n) {}
            virtual bool processNext();
        };


	virtual int prolog();

    };


};

#endif
