Confdump Agent  1.4.0
Socket.cpp
Go to the documentation of this file.
00001 /* 
00002  * Confdump-Agent - Dump static and runtime system configuration
00003  * Copyright (C) 2009-2012  Straton IT, SAS
00004  * 
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 3 as
00007  * published by the Free Software Foundation.
00008  * 
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #include <map>
00019 
00020 #include "boost/filesystem.hpp"
00021 #include "boost/bind.hpp"
00022 
00023 #include "QRegExp"
00024 
00025 #include "Confdump/System/FixedTable.hpp"
00026 #include "Confdump/System/LinuxDumper.hpp"
00027 #include "Confdump/System/Linux/Socket.hpp"
00028 
00029 using boost::shared_ptr;
00030 namespace fs = boost::filesystem;
00031 
00032 namespace Confdump
00033 {
00034 
00035 namespace System
00036 {
00037 
00038 namespace Linux
00039 {
00040 
00041 namespace
00042 {
00043 
00044 // Converts strings as found in the system tables to something convenient (1.2.3.4:80)
00045 QString fixIpv4String( QString ip )
00046 {
00047     // The host and port are present (thus layer 4) and in network byte order
00048     QRegExp hexL4( "([0-9A-F]{8}):([0-9A-F]{4})" );
00049     if ( hexL4.exactMatch( ip ) )
00050     {
00051         QString hexAddress = hexL4.cap( 1 );
00052         QString hexPort = hexL4.cap( 2 );
00053         QString result( "%1.%2.%3.%4:%5" );
00054 
00055         for ( unsigned i = 0; i < 4; ++i )
00056         {
00057             quint8 byte = hexAddress.mid( ( 3 - i ) * 2, 2 ).toUInt( NULL, 16 );
00058             result = result.arg( byte );
00059         }
00060 
00061         quint16 port = hexPort.toUInt( NULL, 16 );
00062         result = result.arg( port );
00063 
00064         return result;
00065     }
00066     else // unknown format, leave as is
00067     {
00068         return ip;
00069     }
00070 }
00071 
00072 class SocketListFile
00073 {
00074     SocketListFile();
00075 
00076 public:
00077     SocketListFile( shared_ptr<LinuxDumper> driver, fs::path file )
00078      : file_( file ),
00079        list_( driver->systemContext().slurpConfigurationFile( file, "CD_Socket") ),
00080        ipv6_( file_.string().at( file_.string().size() - 1 ) == '6' )
00081     {
00082         fieldTranslations_["inode"]         = "inode";
00083         fieldTranslations_["local_address"] = "localAddressString";
00084         fieldTranslations_["rem_address"]   = "remoteAddressString";
00085         fieldTranslations_["st"]            = "stateString";
00086         fieldTranslations_["tm->when"]      = "tm_when";
00087     }
00088 
00089     void readAllInto( std::vector< shared_ptr< Socket > > &instances )
00090     {
00091         // Field reference: http://lkml.indiana.edu/hypermail/linux/kernel/0409.1/2166.html
00092         //   sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
00093         //    0: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 6611 1 ffff88011a178000 300 0 0 2 -1
00094         FixedTable::Specification spec;
00095         spec.addColumnHead( "sl",            2,  2 );
00096         spec.addColumnHead( "local_address", 2, 13 );
00097         spec.addColumnHead( "rem_address",   1, 13 );
00098         spec.addColumnHead( "st",            1,  2 );
00099         spec.addColumnHead( "tx_queue",      1,  8 );
00100         spec.addColumnHead( "rx_queue",      1,  8 );
00101         spec.addColumnHead( "tr",            1,  2 );
00102         spec.addColumnHead( "tm->when",      1,  8 );
00103         spec.addColumnHead( "retrnsmt",      1,  8 );
00104         spec.addColumnHead( "uid",           1,  5 );
00105         spec.addColumnHead( "timeout",       1,  8 );
00106         spec.addColumnHead( "inode",         1, 58 ); // there are that many spaces in the input
00107 
00108         FixedTable table;
00109         table.setSpecification( spec );
00110         table.setFieldTranslations( fieldTranslations_ );
00111 
00112         table.readAllInto( list_, instances );
00113     }
00114 
00115 private:
00116     fs::path file_;
00117     QByteArray list_;
00118     std::map<std::string, std::string> fieldTranslations_;
00119     bool ipv6_;
00120 };
00121 
00122 } // ns
00123 
00124 
00125 Socket::Socket()
00126  : inode_( 0 )
00127 {
00128 }
00129 
00130 Socket::~Socket()
00131 {
00132 }
00133 
00134 QString Socket::protocolName() const
00135 {
00136     return protocolName_;
00137 }
00138 
00139 QString Socket::localAddressString() const
00140 {
00141     return localAddressString_;
00142 }
00143 
00144 QString Socket::remoteAddressString() const
00145 {
00146     return remoteAddressString_;
00147 }
00148 
00149 QString Socket::stateString() const
00150 {
00151     return stateString_;
00152 }
00153 
00154 void Socket::setProtocolName( QString protocolName )
00155 {
00156     protocolName_ = protocolName;
00157 }
00158 
00159 void Socket::setLocalAddressString( QString localAddressString )
00160 {
00161     localAddressString_ = fixIpv4String( localAddressString );
00162 }
00163 
00164 void Socket::setRemoteAddressString( QString remoteAddressString )
00165 {
00166     remoteAddressString_ = fixIpv4String( remoteAddressString );
00167 }
00168 
00169 void Socket::setStateString( QString stateString )
00170 {
00171     // According to Linux Kernel 2.6's include/net/tcp_states.h
00172     int state = stateString.toInt( NULL, 16 );
00173     switch ( state )
00174     {
00175     case  1: stateString_ = "ESTABLISHED"; break;
00176     case  2: stateString_ = "SYN_SENT";    break;
00177     case  3: stateString_ = "SYN_RECV";    break;
00178     case  4: stateString_ = "FIN_WAIT1";   break;
00179     case  5: stateString_ = "FIN_WAIT2";   break;
00180     case  6: stateString_ = "TIME_WAIT";   break;
00181     case  7: stateString_ = "CLOSE";       break;
00182     case  8: stateString_ = "CLOSE_WAIT";  break;
00183     case  9: stateString_ = "LAST_ACK";    break;
00184     case 10: stateString_ = "LISTEN";      break;
00185     case 11: stateString_ = "CLOSING";     break;
00186     }
00187 }
00188 
00189 std::vector< shared_ptr< Socket > > Socket::allSystemInstances( boost::shared_ptr<LinuxDumper> driver, QString protocolName )
00190 {
00191     SocketListFile file( driver, fs::path( "/proc/net" ) / protocolName.toStdString() );
00192     std::vector< shared_ptr< Socket > > instances;
00193     file.readAllInto( instances );
00194 
00195     // FIXME: would be cleaner/faster with a factory
00196     for ( size_t i = 0; i < instances.size(); ++i )
00197         instances[i]->setProtocolName( protocolName );
00198 
00199     return instances;
00200 }
00201 
00202 }
00203 }
00204 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends