You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmyfirewall/kmyfirewall/core/iptrule.cpp

548 lines
17 KiB

/***************************************************************************
begin : Mon Feb 4 2002
copyright : (C) 2002 by Christian Hubinger
email : chubinger@irrsinnig.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
//project includes
#include "iptrule.h"
// #include "iptruleoption.h"
#include "iptchain.h"
#include "iptable.h"
#include "kmfdoc.h"
#include "kmferror.h"
#include "kmfcheckinput.h"
#include "xmlnames.h"
//TQt includes
#include "tqstring.h"
#include "tqdict.h"
// kde includes
#include <kdebug.h>
#include <tdelocale.h>
namespace KMF {
IPTRule::IPTRule( IPTChain* tmp_chain, const char *name, const TQString& tmp_name, const TQString& tmp_target ) : NetfilterObject( tmp_chain, name ) {
// m_object_type = NetfilterObject::RULE;
setName( XML::Undefined_Value );
m_target = XML::Undefined_Value;
m_check_input = new KMFCheckInput();
m_err = new KMFError();
setChain( tmp_chain );
setTable( tmp_chain->table() );
setName( tmp_name );
setTarget( tmp_target );
setCustomRule( false );
m_enabled = true;
m_log_rule = false;
m_options.setAutoDelete( false );
ipt_cmd = "$IPT";
tab = "-t";
ap = "-A";
ws = " ";
post = "-j";
}
IPTRule::~IPTRule() {
// kdDebug() << "\nIPTRule::~IPTRule()" << endl;
delete m_check_input;
delete m_err;
clear();
}
int IPTRule::type() {
// kdDebug() << "IPTRule::type()" << endl;
return NetfilterObject::RULE;
}
void IPTRule::clear() {
m_options.setAutoDelete( true );
m_options.clear();
m_options.setAutoDelete( false );
}
KMFError* IPTRule::setRuleName( const TQString& tmp_name ) {
kdDebug() << "IPTRule::setName( const TQString& tmp_name )" << endl;
TQString inp = tmp_name;
m_check_input->checkInput( inp, "RULENAME", m_err );
if ( m_err->errType() != KMFError::OK ) {
kdDebug() << "-- Name unchanged: invalid name" << tmp_name << endl;
return m_err;
}
NetfilterObject::setName( tmp_name );
changed();
return m_err;
}
void IPTRule::setChain( IPTChain* ch ) {
setParent( ch );
m_chain = ch;
changed();
}
void IPTRule::setTable( IPTable* tmp_table ) {
m_table = tmp_table;
changed();
// kdDebug() << "Rule Table: " << *m_table->name() << endl;
}
void IPTRule::setEnabled( bool on ) {
m_enabled = on;
changed();
}
void IPTRule::setLogging( bool on ) {
m_log_rule = on;
changed();
}
void IPTRule::setTarget( const TQString& tmp_target ) {
if ( !tmp_target.isNull() ) {
m_target = tmp_target;
}
TQPtrList<TQString>* available_options = IPTRuleOption::getAvailableOptionTypes();
for ( uint j = 0;j < available_options->count();j++ ) {
TQString type = *available_options->at( j );
IPTRuleOption* opt = 0;
opt = getOptionForName( type );
if ( opt && opt->isTargetOption() ) {
TQStringList args;
opt->loadValues( args );
}
}
changed();
}
void IPTRule::setCustomRule( bool on ) {
m_custom_rule = on;
changed();
}
int IPTRule::ruleNum() const {
return chain()->indexOf( *this );
//return m_rule_num;
}
const TQString& IPTRule::target() const {
return m_target;
}
bool IPTRule::isForward() const {
//FIXME: Is that sematically correct???
if ( m_target == "ACCEPT" || m_target == "DROP" ||
m_target == "LOG" || m_target == "QUEUE" ||
m_target == "RETURN" || m_target == "REJECT" ||
m_target == "MIRROR" || m_target == "SNAT" ||
m_target == "DNAT" || m_target == "REDIRECT" ||
m_target == "MASQUERADE" || m_target == "MARK" ||
m_target == "TOS" ) {
return true;
} else {
return false;
}
}
TQStringList IPTRule::availableTargets() const {
kdDebug() << "TQStringList availableTargets() const {" << endl;
TQStringList targets;
TQString table = chain() ->table() ->name();
TQString name = chain() ->name();
if ( table.isEmpty() || name.isEmpty() ) {
kdDebug() << "KMFRuleEdit::slotAddValidTargets( const IPTChain& chain ): ERROR: name or table not found in table" << endl;
return *( new TQStringList() );
}
// general Targets
targets << "ACCEPT" << "DROP" << "LOG" << "QUEUE" << "RETURN";
if ( name == Constants::InputChain_Name || name == Constants::OutputChain_Name || name == Constants::ForwardChain_Name )
targets << "REJECT";
if ( name == Constants::InputChain_Name || name == Constants::OutputChain_Name || name == Constants::PreRoutingChain_Name )
targets << "MIRROR";
if ( table == Constants::NatTable_Name && name == Constants::PostRoutingChain_Name )
targets << "SNAT";
if ( table == Constants::NatTable_Name && ( name == Constants::PreRoutingChain_Name || name == Constants::OutputChain_Name ) ) {
targets << "DNAT" << "REDIRECT";
}
if ( table == Constants::NatTable_Name && name == Constants::PostRoutingChain_Name )
targets << "MASQUERADE";
if ( table == Constants::MangleTable_Name ) {
targets << "MARK" << "TOS";
}
if ( table == Constants::FilterTable_Name || table == Constants::NatTable_Name || table == Constants::MangleTable_Name ) {
TQPtrList<IPTChain> tmp_chains = chain() ->table() ->chains();
TQPtrListIterator<IPTChain> it( tmp_chains );
while ( it.current() ) {
IPTChain * tmp_ch = it.current();
++it;
if ( !tmp_ch->isBuildIn() && tmp_ch->name() != name ) {
// kdDebug() << "Adding Chain: " << tmp_ch->name() << " to Targets. " << endl;
targets << tmp_ch->name();
}
}
}
return targets;
}
IPTRuleOption* IPTRule::getOptionForName( const TQString& type ) {
IPTRuleOption * option_obj;
option_obj = m_options.find( type );
if ( option_obj == 0 && !type.stripWhiteSpace().isEmpty() ) {
// kdDebug() << "Creating new IPTRuleOption( IPTRule* )" << endl;
option_obj = new IPTRuleOption( this, type.latin1() );
option_obj->setOptionType( type );
m_options.insert( type, option_obj );
return option_obj;
} else {
return option_obj;
}
}
bool IPTRule::addRuleOption( TQString& par_name, TQPtrList<TQString>& cmds ) {
//############# start new implementation ##################//
TQString new_par_name = "";
if ( par_name == "src_ip" || par_name == "dest_ip" ) {
// kdDebug() << "Translating to new option name: " << par_name << " -> ip_opt" << endl;
new_par_name = "ip_opt";
} else if ( par_name == "mac" ) {
// kdDebug() << "Translating to new option name: " << par_name << " -> mac_opt" << endl;
new_par_name = "mac_opt";
} else {
new_par_name = par_name;
}
if ( new_par_name.stripWhiteSpace().isEmpty() ) {
return false;
}
IPTRuleOption * option_obj;
option_obj = m_options.find( new_par_name );
if ( option_obj == 0 ) {
// kdDebug() << "Creating new IPTRuleOption( IPTRule* )" << endl;
option_obj = new IPTRuleOption( this, new_par_name.latin1() );
m_options.insert( new_par_name, option_obj );
} else {
// kdDebug() << "Option: " << new_par_name << "Allready in Dict" << endl;
}
kdDebug() << "+ Adding Opiton: " << new_par_name << endl;
option_obj->setOptionType( new_par_name );
if ( ! cmds.isEmpty() ) {
TQStringList args;
for ( uint i = 0; i < cmds.count(); i++ )
args << *( new TQString( *cmds.at( i ) ) );
option_obj->loadValues( args );
} else {
option_obj->reset();
}
// kdDebug() << "Rule->getXMLSniplet(): " << getXMLSniplet() << endl;
changed();
return true;
}
bool IPTRule::addTargetOption( TQString& par_name, TQPtrList<TQString>& cmds ) {
//############# start new implementation ##################//
TQString new_par_name = "";
new_par_name = par_name;
if ( new_par_name.stripWhiteSpace().isEmpty() ) {
return false;
}
IPTRuleOption * option_obj;
option_obj = m_options.find( new_par_name );
if ( option_obj == 0 ) {
// kdDebug() << "Creating new IPTRuleOption( IPTRule* )" << endl;
option_obj = new IPTRuleOption( this, par_name.latin1() );
m_options.insert( new_par_name, option_obj );
option_obj->setTargetOption( true );
} else {
// kdDebug() << "Option: " << new_par_name << "Allready in Dict" << endl;
option_obj->setTargetOption( true );
}
option_obj->setOptionType( new_par_name );
option_obj->setTargetOption( true );
if ( ! cmds.isEmpty() ) {
TQStringList args;
for ( uint i = 0; i < cmds.count(); i++ )
args << *( new TQString( *cmds.at( i ) ) );
option_obj->loadValues( args );
} else {
option_obj->reset();
}
// kdDebug() << "Rule->getXMLSniplet(): " << getXMLSniplet() << endl;
changed();
return true;
}
const TQString& IPTRule::toString() {
// kdDebug() << "\nconst TQString& IPTRule::toString()" << endl;
option_cmd = "";
option_cmd.append( ipt_cmd ); // $IPT
option_cmd.append( ws );
option_cmd.append( tab ); // -t
option_cmd.append( ws );
option_cmd.append( m_table->name() ); // <TABLE>
option_cmd.append( ws );
option_cmd.append( ap ); // -A
option_cmd.append( ws );
option_cmd.append( m_chain->name() ); // <CHAIN>
option_cmd.append( ws );
// append all normal rule options
TQPtrList<TQString>* known_types = 0;
known_types = IPTRuleOption::getAvailableOptionTypes();
if ( known_types == 0 ) {
kdDebug() << "ERROR: IPTRuleOption::getAvailableOptionTypes() == 0\n" << endl;
} else {
// kdDebug() << "Found Number of Types: " << known_types->count() << endl;
for ( uint i = 0; i < known_types->count(); i++ ) {
TQString* option_name = 0;
option_name = known_types->at( i );
if ( option_name == 0 ) {
kdDebug() << "ERROR: option_name == 0" << endl;
} else {
// kdDebug() << "Searching for Option: " << *option_name << endl;
IPTRuleOption* opt = 0;
opt = m_options.find( *option_name );
if ( opt && ! opt->isEmpty() && ! opt->isTargetOption() ) {
TQString option = opt->toString();
// kdDebug() << "Add Option: " << opt->toString() << endl;
if ( !option.isEmpty() ) {
option_cmd.append( opt->toString() );
option_cmd.append( ws );
}
}
}
}
}
option_cmd. append( post );
option_cmd. append( ws );
option_cmd.simplifyWhiteSpace();
if ( logging() ) {
TQString new_line = option_cmd;
new_line. append( "LOG" );
new_line. append( " --log-prefix \"Rule " + name() + ": \"" );
new_line.simplifyWhiteSpace();
new_line.append( "\n" );
option_cmd.prepend( new_line );
}
option_cmd. append( m_target );
option_cmd. append( ws );
TQString target_options = "";
if ( known_types == 0 ) {
kdDebug() << "ERROR: IPTRuleOption::getAvailableOptionTypes() == 0\n" << endl;
} else {
// kdDebug() << "Found Number of Types: " << known_types->count() << endl;
for ( uint i = 0; i < known_types->count(); i++ ) {
TQString* option_name = 0;
option_name = known_types->at( i );
if ( option_name == 0 ) {
kdDebug() << "ERROR: option_name == 0" << endl;
} else {
// kdDebug() << "Searching for Option: " << *option_name << endl;
IPTRuleOption* opt = 0;
opt = m_options.find( *option_name );
if ( opt && opt->isTargetOption() && ! opt->isEmpty() ) {
// kdDebug() << "Add Option: " << opt->toString() << endl;
TQString option = "";
option = opt->toString();
if ( !option.isEmpty() ) {
target_options.append( opt->toString() );
target_options.append( ws );
target_options.simplifyWhiteSpace();
}
}
}
}
}
option_cmd.append( target_options );
// kdDebug() << "Rule Cmd Line for Rule " << m_name << ": " << option_cmd << endl;
if ( ! logging() )
option_cmd.simplifyWhiteSpace();
return *( new TQString( option_cmd ) );
}
const TQDomDocument& IPTRule::getDOMTree( ) {
// kdDebug() << "const TQString& IPTRule::getDOMTree( )" << endl;
TQDomDocument doc;
TQDomElement root = doc.createElement( XML::Rule_Element );
NetfilterObject::saveUuid( root );
root.setAttribute( XML::Num_Attribute, ruleNum() );
root.setAttribute( XML::Name_Attribute, name() );
root.setAttribute( XML::Target_Attribute, m_target );
root.setAttribute( XML::Description_Attribute, description() );
if ( enabled() ) {
root.setAttribute( XML::Enabled_Attribute, XML::Yes_Value );
} else {
root.setAttribute( XML::Enabled_Attribute, XML::No_Value );
}
if ( customRule() ) {
root.setAttribute( XML::CustomRule_Attribute, XML::Yes_Value );
} else {
root.setAttribute( XML::CustomRule_Attribute, XML::No_Value );
}
if ( logging() ) {
root.setAttribute( XML::Logging_Attribute, XML::Yes_Value );
} else {
root.setAttribute( XML::Logging_Attribute, XML::No_Value );
}
TQPtrList<TQString>* available_options = 0;
available_options = IPTRuleOption::getAvailableOptionTypes();
if ( available_options ) {
TQPtrListIterator<TQString> it ( *available_options );
TQString *type = 0;
while ( ( type = it.current() ) != 0 ) {
++it;
if ( type ) {
IPTRuleOption * opt = 0;
opt = m_options.find( *type );
if ( opt ) {
root.appendChild( opt->getDOMTree( ) );
// kdDebug() << "Got XML for Rule Option Type: " << *type << endl;
} else {
// kdDebug() << "No option with type: " << *type << " found. " << endl;
}
}
}
}
doc.appendChild( root );
return *( new TQDomDocument( doc ) );
}
void IPTRule::loadXML( const TQDomDocument& doc, TQStringList& errors ) {
kdDebug() << "void IPTRule::loadXML( const TQDomDocument& )" << endl;
TQDomElement root = doc.documentElement();
loadXML( root, errors );
}
void IPTRule::loadXML( TQDomNode root, TQStringList& errors ) {
// void IPTRule::loadXML( const TQDomDocument& doc ) {
// kdDebug() << "void IPTRule::loadXML( const TQDomDocument& doc )" << endl;
// kdDebug() << "Parsing XML:\n" << doc.toString() << endl;
// TQDomElement root = doc.documentElement();
NetfilterObject::loadUuid ( root, errors );
TQString name = "";
TQString num = "";
TQString logging = "";
TQString desc = "";
TQString target = "";
TQString custom = "";
TQString enabled = "";
name = root.toElement().attribute( XML::Name_Attribute );
num = root.toElement().attribute( XML::Num_Attribute );
logging = root.toElement().attribute( XML::Logging_Attribute );
custom = root.toElement().attribute( XML::CustomRule_Attribute );
target = root.toElement().attribute( XML::Target_Attribute );
desc = root.toElement().attribute( XML::Description_Attribute );
enabled = root.toElement().attribute( XML::Enabled_Attribute );
if ( logging == XML::Yes_Value ) {
setLogging( true );
} else {
setLogging( false );
}
if ( enabled == XML::Yes_Value ) {
setEnabled( true );
} else {
setEnabled( false );
}
if ( custom == XML::Yes_Value ) {
setCustomRule( true );
} else {
setCustomRule( false );
}
setTarget( *( new TQString( target ) ) );
setDescription( *( new TQString( desc ) ) );
setName( *( new TQString( name ) ) );
/* bool ok;
int rule_number = num.toInt( &ok );
if ( ok )
setRuleNum( rule_number );*/
TQPtrList<TQString> *avail_opts = IPTRuleOption::getAvailableOptionTypes();
TQPtrListIterator<TQString> it ( *avail_opts );
while ( it.current() ) {
TQString name = *it.current();
++it;
IPTRuleOption *opt = getOptionForName( name );
if ( opt )
opt->reset();
}
TQDomNode curr = root.firstChild();
while ( !curr.isNull() ) {
// kdDebug() << "IPTRule: Parsing Node: " << curr.nodeName() << endl;
if ( curr.isElement() && curr.nodeName() == XML::RuleOption_Element ) {
TQString type = curr.toElement().attribute( XML::Type_Attribute );
// kdDebug() << "IPTRule: Start Parsing Option: " << type << endl;
TQDomDocument opt_xml;
opt_xml.appendChild( curr.cloneNode( true ) );
IPTRuleOption* opt = 0;
opt = m_options.find( *( new TQString( type ) ) );
if ( opt == 0 ) {
TQPtrList<TQString> list;
list.append( new TQString( "" ) );
addRuleOption( type, list );
opt = m_options.find( *( new TQString( type ) ) );
if ( ! opt ) {
kdDebug() << "ERROR: Couldn't create Option: " << type << endl;
return ;
}
// kdDebug() << "IPTRule: Created Option: " << type << endl;
}
opt->loadXML( opt_xml, errors );
// kdDebug() << "IPTRule: Finished Parsing Option: " << type << endl;
}
curr = curr.nextSibling();
}
changed();
}
void IPTRule::createRuleClone( IPTRule* new_rule ) {
// kdDebug() << "IPTRule& IPTRule::createRuleClone()" << endl;
TQString na = name();
if ( na.length() > 15 ) {
na = na.left( 15 ) ;
}
new_rule->setCustomRule( m_custom_rule );
new_rule->setDescription( description() );
new_rule->setLogging( logging() );
new_rule->setEnabled( enabled() );
new_rule->setTarget( target() );
TQPtrList<TQString>* available_types = IPTRuleOption::getAvailableOptionTypes();
TQString type = "";
TQPtrListIterator<TQString> it( *available_types );
while ( it.current() ) {
type = *it.current();
++it;
IPTRuleOption* opt = getOptionForName( type );
IPTRuleOption* clone_opt = new_rule->getOptionForName( type );
// FIXME: Check For Error
TQStringList *errors = new TQStringList();
clone_opt->loadXML( opt->getDOMTree(), *errors );
}
}
}