1 // 2 // Copyright (C) 2013 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/socket_info_reader.h" 18 19 #include <algorithm> 20 #include <limits> 21 22 #include <base/strings/string_number_conversions.h> 23 #include <base/strings/string_split.h> 24 #include <base/strings/string_util.h> 25 26 #include "shill/file_reader.h" 27 #include "shill/logging.h" 28 29 using base::FilePath; 30 using std::string; 31 using std::vector; 32 33 namespace shill { 34 35 namespace Logging { 36 static auto kModuleLogScope = ScopeLogger::kLink; 37 static string ObjectID(SocketInfoReader* s) { return "(socket_info_reader)"; } 38 } 39 40 namespace { 41 42 const char kTcpv4SocketInfoFilePath[] = "/proc/net/tcp"; 43 const char kTcpv6SocketInfoFilePath[] = "/proc/net/tcp6"; 44 45 } // namespace 46 47 SocketInfoReader::SocketInfoReader() {} 48 49 SocketInfoReader::~SocketInfoReader() {} 50 51 FilePath SocketInfoReader::GetTcpv4SocketInfoFilePath() const { 52 return FilePath(kTcpv4SocketInfoFilePath); 53 } 54 55 FilePath SocketInfoReader::GetTcpv6SocketInfoFilePath() const { 56 return FilePath(kTcpv6SocketInfoFilePath); 57 } 58 59 bool SocketInfoReader::LoadTcpSocketInfo(vector<SocketInfo>* info_list) { 60 info_list->clear(); 61 bool v4_loaded = AppendSocketInfo(GetTcpv4SocketInfoFilePath(), info_list); 62 bool v6_loaded = AppendSocketInfo(GetTcpv6SocketInfoFilePath(), info_list); 63 // Return true if we can load either /proc/net/tcp or /proc/net/tcp6 64 // successfully. 65 return v4_loaded || v6_loaded; 66 } 67 68 bool SocketInfoReader::AppendSocketInfo(const FilePath& info_file_path, 69 vector<SocketInfo>* info_list) { 70 FileReader file_reader; 71 if (!file_reader.Open(info_file_path)) { 72 SLOG(this, 2) << __func__ << ": Failed to open '" 73 << info_file_path.value() << "'."; 74 return false; 75 } 76 77 string line; 78 while (file_reader.ReadLine(&line)) { 79 SocketInfo socket_info; 80 if (ParseSocketInfo(line, &socket_info)) 81 info_list->push_back(socket_info); 82 } 83 return true; 84 } 85 86 bool SocketInfoReader::ParseSocketInfo(const string& input, 87 SocketInfo* socket_info) { 88 vector<string> tokens = base::SplitString(input, base::kWhitespaceASCII, 89 base::KEEP_WHITESPACE, 90 base::SPLIT_WANT_NONEMPTY); 91 if (tokens.size() < 10) { 92 return false; 93 } 94 95 IPAddress ip_address(IPAddress::kFamilyUnknown); 96 uint16_t port = 0; 97 98 if (!ParseIPAddressAndPort(tokens[1], &ip_address, &port)) { 99 return false; 100 } 101 socket_info->set_local_ip_address(ip_address); 102 socket_info->set_local_port(port); 103 104 if (!ParseIPAddressAndPort(tokens[2], &ip_address, &port)) { 105 return false; 106 } 107 socket_info->set_remote_ip_address(ip_address); 108 socket_info->set_remote_port(port); 109 110 SocketInfo::ConnectionState connection_state = 111 SocketInfo::kConnectionStateUnknown; 112 if (!ParseConnectionState(tokens[3], &connection_state)) { 113 return false; 114 } 115 socket_info->set_connection_state(connection_state); 116 117 uint64_t transmit_queue_value = 0, receive_queue_value = 0; 118 if (!ParseTransimitAndReceiveQueueValues( 119 tokens[4], &transmit_queue_value, &receive_queue_value)) { 120 return false; 121 } 122 socket_info->set_transmit_queue_value(transmit_queue_value); 123 socket_info->set_receive_queue_value(receive_queue_value); 124 125 SocketInfo::TimerState timer_state = SocketInfo::kTimerStateUnknown; 126 if (!ParseTimerState(tokens[5], &timer_state)) { 127 return false; 128 } 129 socket_info->set_timer_state(timer_state); 130 131 return true; 132 } 133 134 bool SocketInfoReader::ParseIPAddressAndPort( 135 const string& input, IPAddress* ip_address, uint16_t* port) { 136 vector<string> tokens = base::SplitString( 137 input, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 138 if (tokens.size() != 2 || 139 !ParseIPAddress(tokens[0], ip_address) || 140 !ParsePort(tokens[1], port)) { 141 return false; 142 } 143 144 return true; 145 } 146 147 bool SocketInfoReader::ParseIPAddress(const string& input, 148 IPAddress* ip_address) { 149 ByteString byte_string = ByteString::CreateFromHexString(input); 150 if (byte_string.IsEmpty()) 151 return false; 152 153 IPAddress::Family family; 154 if (byte_string.GetLength() == 155 IPAddress::GetAddressLength(IPAddress::kFamilyIPv4)) { 156 family = IPAddress::kFamilyIPv4; 157 } else if (byte_string.GetLength() == 158 IPAddress::GetAddressLength(IPAddress::kFamilyIPv6)) { 159 family = IPAddress::kFamilyIPv6; 160 } else { 161 return false; 162 } 163 164 // Linux kernel prints out IP addresses in network order via 165 // /proc/net/tcp{,6}. 166 byte_string.ConvertFromNetToCPUUInt32Array(); 167 168 *ip_address = IPAddress(family, byte_string); 169 return true; 170 } 171 172 bool SocketInfoReader::ParsePort(const string& input, uint16_t* port) { 173 int result = 0; 174 175 if (input.size() != 4 || !base::HexStringToInt(input, &result) || 176 result < 0 || result > std::numeric_limits<uint16_t>::max()) { 177 return false; 178 } 179 180 *port = result; 181 return true; 182 } 183 184 bool SocketInfoReader::ParseTransimitAndReceiveQueueValues( 185 const string& input, 186 uint64_t* transmit_queue_value, uint64_t* receive_queue_value) { 187 int64_t signed_transmit_queue_value = 0, signed_receive_queue_value = 0; 188 189 vector<string> tokens = base::SplitString( 190 input, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 191 if (tokens.size() != 2 || 192 !base::HexStringToInt64(tokens[0], &signed_transmit_queue_value) || 193 !base::HexStringToInt64(tokens[1], &signed_receive_queue_value)) { 194 return false; 195 } 196 197 *transmit_queue_value = static_cast<uint64_t>(signed_transmit_queue_value); 198 *receive_queue_value = static_cast<uint64_t>(signed_receive_queue_value); 199 return true; 200 } 201 202 bool SocketInfoReader::ParseConnectionState( 203 const string& input, SocketInfo::ConnectionState* connection_state) { 204 int result = 0; 205 206 if (input.size() != 2 || !base::HexStringToInt(input, &result)) { 207 return false; 208 } 209 210 if (result > 0 && result < SocketInfo::kConnectionStateMax) { 211 *connection_state = static_cast<SocketInfo::ConnectionState>(result); 212 } else { 213 *connection_state = SocketInfo::kConnectionStateUnknown; 214 } 215 return true; 216 } 217 218 bool SocketInfoReader::ParseTimerState( 219 const string& input, SocketInfo::TimerState* timer_state) { 220 int result = 0; 221 222 vector<string> tokens = base::SplitString( 223 input, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 224 if (tokens.size() != 2 || tokens[0].size() != 2 || 225 !base::HexStringToInt(tokens[0], &result)) { 226 return false; 227 } 228 229 if (result < SocketInfo::kTimerStateMax) { 230 *timer_state = static_cast<SocketInfo::TimerState>(result); 231 } else { 232 *timer_state = SocketInfo::kTimerStateUnknown; 233 } 234 return true; 235 } 236 237 } // namespace shill 238