Confdump Agent
1.4.0
|
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 }