/*************************************************************************** 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" // qt includes #include #include // kde includes #include #include // 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 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& IPTable::chains() const { TQPtrList* ret_val = new TQPtrList; *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 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( "

Chain: %1 already exists in table: %2.
" "Please try again with another name. A chain name must be unique in a table.

" ).tqarg( found_name ).tqarg( 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" ).tqarg( 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" ).tqarg( 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" ).tqarg( 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 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 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 it ( m_chains ); while ( it.current() ) { // kdDebug() << "IPTChain::xloadXML() cleanup loop." << endl; IPTChain *chain = it.current(); TQPtrListIterator 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(); } }