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/iptable.cpp

379 lines
13 KiB

/***************************************************************************
begin : Tue Aug 20 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. *
* *
***************************************************************************/
#include "iptable.h"
// TQt includes
#include <tqstring.h>
#include <tqregexp.h>
// kde includes
#include <kdebug.h>
#include <tdelocale.h>
// project includes
#include "kmfcheckinput.h"
#include "iptchain.h"
#include "kmferror.h"
#include "kmfiptdoc.h"
#include "xmlnames.h"
namespace KMF {
IPTable::IPTable( KMFIPTDoc* doc, const char* name, const TQString& tableName ) : NetfilterObject( doc, name ) {
// kdDebug() << "IPTable::IPTable(TQString& name)" << endl;
kmfdoc = doc;
// m_object_type = NetfilterObject::TABLE;
m_err = new KMFError();
m_chains.setAutoDelete( false );
setName( tableName );
}
IPTable::~IPTable() {
kdDebug() << "\n\nIPTable::~IPTable() : " << name() << endl;
clear();
}
int IPTable::type() {
// kdDebug() << "IPTable::type()" << endl;
return NetfilterObject::TABLE;
}
void IPTable::clear() {
m_chains.setAutoDelete( true );
m_chains.clear();
m_chains.setAutoDelete( false );
}
void IPTable::reset() {
// kdDebug() << "void IPTable::resetTable()" << endl;
TQPtrListIterator<IPTChain> it ( m_chains );
while ( it.current() ) {
IPTChain* chain = it.current();
if ( chain->isBuildIn() ) {
chain->reset();
++it;
} else {
m_chains.remove( chain );
}
}
changed();
}
void IPTable::settupDefaultChains() {
// kdDebug() << "void IPTable::settupDefaultChains()" << endl;
TQString target = "ACCEPT";
IPTChain* chain = 0;
if ( name() == Constants::FilterTable_Name ) {
setDescription( i18n("This table is the main table for filtering\n"
"packets. Here you may define your\n"
"access control rules") );
chain = addChain( Constants::InputChain_Name, target, true, m_err );
// if ( chain ) {
chain->setDescription( i18n( "In this chain you can filter packets that\n"
"are addressed directly to this computer." ) );
// }
chain = addChain( Constants::OutputChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "In this chain you can decide which\n"
"packets are allowed to be sent away\n"
"from this computer." ) );
}
chain = addChain( Constants::ForwardChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "In this chain you can filter the packets\n"
"that are routed to other hosts by this\n"
"computer." ) );
}
} else if ( name() == Constants::NatTable_Name ) {
setDescription( i18n("This table is made for every kind of\n"
"NAT (Network Address Translation).") );
chain = addChain( Constants::OutputChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "In this chain you can decide which\n"
"packets are allowed to be sent away\n"
"from this computer." ) );
}
chain = addChain( Constants::PreRoutingChain_Name, target, true, m_err );
if ( chain )
chain->setDescription( i18n( "..." ) );
chain = addChain( Constants::PostRoutingChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "..." ) );
}
} else if ( name() == Constants::MangleTable_Name ) {
setDescription( i18n("This table is made for altering packets.") );
chain = addChain( Constants::InputChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "In this chain you can filter packets that\n"
"are addressed directly to this compter." ) );
}
chain = addChain( Constants::OutputChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "In this chain you can decide which\n"
"packets are allowed to be sent away\n"
"from this computer." ) );
}
chain = addChain( Constants::ForwardChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "In this chain you can filter the packets\n"
"that are routed to other hosts by this\n"
"computer." ) );
}
chain = addChain( Constants::PreRoutingChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "..." ) );
}
chain = addChain( Constants::PostRoutingChain_Name, target, true, m_err );
if ( chain ) {
chain->setDescription( i18n( "..." ) );
}
}
}
IPTChain* IPTable::chainForName( const TQString& name ) {
IPTChain * tmp_chain;
for ( tmp_chain = m_chains.first();tmp_chain; tmp_chain = m_chains.next() ) {
if ( tmp_chain->name() == name )
return tmp_chain;
}
return 0;
}
IPTChain* IPTable::chainForUuid( const TQUuid& id ) {
IPTChain * tmp_chain;
for ( tmp_chain = m_chains.first(); tmp_chain; tmp_chain = m_chains.next() ) {
if ( tmp_chain->uuid() == id )
return tmp_chain;
}
return 0;
}
TQPtrList<IPTChain>& IPTable::chains() const {
TQPtrList<IPTChain>* ret_val = new TQPtrList<IPTChain>;
*ret_val = m_chains;
return *ret_val;
}
IPTChain* IPTable::addChain( const TQString& chain_name, const TQString& chain_target, bool builtin, KMFError *err ) {
// kdDebug() << "KMFError* IPTable::addChain( TQString& chain_name,TQString& chain_table,TQString& chain_target,bool builtin )" << endl;
KMFCheckInput* check = new KMFCheckInput();
check->checkInput( chain_name, "CHAINNAME", err );
if ( err->errNum() != 0 ) {
return 0;
}
TQPtrListIterator<IPTChain> it ( m_chains );
while ( it.current() ) {
IPTChain* tmp_chain = it.current();
++it;
TQString found_name = tmp_chain->name();
if ( found_name == chain_name ) {
const TQString msg = i18n( "<qt><p>Chain: <b>%1</b> already exists in table: <b>%2</b>.<br>"
"Please try again with another name. A chain name must be unique in a table.</p></qt>" ).arg( found_name ).arg( name() );
err->setErrType( KMFError::NORMAL );
err->setErrMsg( msg );
kdDebug() << "\n\nWARNING: Couldn't add chain because of dupilcate name\n\n" << endl;
return 0;
}
}
IPTChain * chain = new IPTChain( this, chain_name.latin1(), chain_name, builtin );
if ( builtin && chain_target != TQString() )
chain->setDefaultTarget( chain_target );
// kdDebug() << "Adding Chain: " << chain->name() << endl;
m_chains.append( chain );
changed();
err->setErrType( KMFError::OK );
return chain;
}
KMFError* IPTable::delChain( IPTChain *chain ) {
// kdDebug() << "KMFError* IPTable::delChain( IPTChain *chain )" << endl;
m_err = new KMFError();
TQString name = chain->name();
if ( chain->isBuildIn() ) {
const TQString msg = i18n( "Cannot delete built-in chain: %1" ).arg( name );
m_err->setErrMsg( msg );
m_err->setErrType( KMFError::NORMAL );
return m_err;
}
int index = m_chains.find( chain );
// kdDebug() << "fount chain nr: " << index << endl;
if ( index < 0 ) {
chain->deleteLater();
const TQString msg = i18n( "Cannot delete nonexistent chain" );
m_err->setErrMsg( msg );
m_err->setErrType( KMFError::NORMAL );
return m_err;
} else {
m_chains.remove( index );
chain->deleteLater();
const TQString msg = "";
m_err->setErrMsg( msg );
m_err->setErrType( KMFError::OK );
changed();
return m_err;
}
}
KMFError* IPTable::moveRuleToChain( IPTRule* rule, IPTChain *target_chain ) {
// kdDebug() << "KMFError* IPTable::moveRuleToChain(IPTRule* rule, IPTChain *target_chain )" << endl;
if ( rule == 0 ) {
m_err->setErrType( KMFError::FATAL );
const TQString& msg = i18n( "IPTable::moveRuleToChain(IPTRule* rule, IPTChain *target_chain"
"rule == 0. This is a bug." );
m_err->setErrMsg( msg );
return m_err;
}
if ( target_chain == 0 ) {
m_err->setErrType( KMFError::FATAL );
const TQString& msg = i18n( "IPTable::moveRuleToChain(IPTRule* rule, IPTChain *target_chain"
"target_chain == 0. This is a bug." );
m_err->setErrMsg( msg );
return m_err;
}
// kdDebug() << "Move Rule: " << rule->name() <<" from Chain: " << rule->chain() ->name() << "to chain" << target_chain->name() << endl;
IPTRule* new_rule = target_chain->addRule( i18n( "%1_Copy" ).arg( rule->name() ), m_err );
if ( m_err->errNum() == 0 ) {
rule->createRuleClone( new_rule );
IPTRule* ru = rule;
rule->chain()->delRule( ru );
}
return m_err;
}
KMFError* IPTable::copyRuleToChain( IPTRule* rule, IPTChain *target_chain ) {
// kdDebug() << "KMFError* IPTable::copyRuleToChain(IPTRule* rule, IPTChain *target_chain )" << endl;
if ( rule == 0 ) {
m_err->setErrType( KMFError::FATAL );
const TQString& msg = i18n( "IPTable::moveRuleToChain(IPTRule* rule, IPTChain *target_chain"
"rule == 0. This is a bug " );
m_err->setErrMsg( msg );
return m_err;
}
if ( target_chain == 0 ) {
m_err->setErrType( KMFError::FATAL );
const TQString& msg = i18n( "IPTable::moveRuleToChain(IPTRule* rule, IPTChain *target_chain"
"target_chain == 0. This is a bug " );
m_err->setErrMsg( msg );
return m_err;
}
// kdDebug() << "Copy Rule: " << rule->name() << " from Chain: " << rule->chain() ->name() << "to chain" << target_chain->name() << endl;
IPTRule* new_rule = target_chain->addRule( i18n( "%1_Copy" ).arg( rule->name() ), m_err );
if ( m_err->errNum() == 0 ) {
rule->createRuleClone( new_rule );
}
return m_err;
}
const TQDomDocument& IPTable::getDOMTree() {
// kdDebug() << "const TQString& IPTChain::getIDOMree( )" << endl;
TQDomDocument doc;
TQDomElement root = doc.createElement( XML::Table_Element );
NetfilterObject::saveUuid( root );
root.setAttribute( XML::Name_Attribute, name() );
root.setAttribute( XML::Description_Attribute, description() );
TQPtrListIterator<IPTChain> it ( m_chains );
IPTChain *chain = 0;
while ( ( chain = it.current() ) != 0 ) {
++it;
if ( chain ) {
root.appendChild( chain->getDOMTree( ) );
// kdDebug() << "Got XML for Rule: " << *chain->name() << endl;
} else {
kdDebug() << "Rule == 0"<< endl;
}
}
doc.appendChild( root );
return *( new TQDomDocument( doc ) );
}
void IPTable::loadXML( const TQDomDocument& doc, TQStringList& errors ) {
kdDebug() << "void IPTable::loadXML( const TQDomDocument& )" << endl;
TQDomElement root = doc.documentElement();
loadXML( root, errors );
}
void IPTable::loadXML( TQDomNode root, TQStringList& errors ) {
setName( name() );
NetfilterObject::loadUuid ( root, errors );
// TQDomElement root = doc.documentElement();
TQDomNode curr = root.firstChild();
TQPtrList<IPTChain> used_chains;
while ( !curr.isNull() ) {
// kdDebug() << "Parsing Node: " << curr.nodeName() << endl;
if ( curr.isElement() && curr.nodeName() == XML::Chain_Element ) {
TQString name = curr.toElement().attribute( XML::Name_Attribute );
TQString uuid = curr.toElement().attribute( XML::Uuid_Attribute );
TQUuid chain_uuid( uuid );
// kdDebug() << "IPTable: Start Parsing Chain: " << name << endl;
TQDomDocument chain_xml;
chain_xml.appendChild( curr.cloneNode(true) );
IPTChain* chain = 0;
chain = chainForUuid( chain_uuid );
if ( ! chain ) {
chain = chainForName( name );
if ( ! chain ) {
chain = addChain( name ,*( new TQString( "ACCEPT" ) ), false, m_err );
if ( m_err->errNum() != 0 ) {
kdDebug() << "ERROR: Couldn't create Chain: " << name << endl;
return;
}
}
}
chain->loadXML( chain_xml, errors );
used_chains.append( chain );
// kdDebug() << "IPTable: Finished Parsing Chain: " << name << endl;
}
curr = curr.nextSibling();
}
TQPtrListIterator<IPTChain> it ( m_chains );
while ( it.current() ) {
// kdDebug() << "IPTChain::xloadXML() cleanup loop." << endl;
IPTChain *chain = it.current();
TQPtrListIterator<IPTChain> it2 ( used_chains );
bool found = false;
while ( it2.current() ) {
IPTChain *chain2 = it2.current();
++it2;
if ( chain2 == chain )
found = true;
}
if ( ! found ) {
m_err = delChain( chain );
if ( m_err->errNum() != 0 )
++it;
} else {
++it;
}
}
changed();
}
}