diff --git a/README.md b/README.md index cea3cc5..8478182 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,8 @@ How does that affect `pfs`? The directory `sample` contains a full blown application that calls all(!) the supported APIs and prints all the information gathered. When compiling the library, the sample applications is compiled as well. +You can find a basic implementation of `netstat` (see `sample/tool_netstat.cpp`) and `lsmod` (see `sample/tool_lsmod.cpp`) that you can easily reuse in your projects. + Anyway, here are some cool (and concise) examples: **Example 1:** Iterater over all the loaded unsigned or out-of-tree kernel modules diff --git a/sample/sample.cpp b/sample/sample.cpp index 751b200..4c032ad 100644 --- a/sample/sample.cpp +++ b/sample/sample.cpp @@ -37,12 +37,20 @@ int main(int argc, char** argv) // clang-format off auto commands = std::vector{ - {command("system", "", "Enumerate system-wide information", enum_system)}, - {command("net", "", "Enumerate network information", enum_net)}, - {command("tasks", "[task-id]...", "Enumerate running tasks", enum_tasks)}, - {command("fds", "[task-id]...", "Enumerate fds for a specific task", enum_fds)}, - {command("lsmod", "[filter]", "Enumerate all loaded modules that match the filter", tool_lsmod)}, - {command("blocks", "[block-name]...", "Enumerate block devices", enum_blocks)}, + {command("system", "", + "Enumerate system-wide information", enum_system)}, + {command("net", "", + "Enumerate network information", enum_net)}, + {command("tasks", "[task-id]...", + "Enumerate running tasks", enum_tasks)}, + {command("fds", "[task-id]...", + "Enumerate fds for a specific task", enum_fds)}, + {command("blocks", "[block-name]...", + "Enumerate block devices", enum_blocks)}, + {command("lsmod", "[filter]", + "Enumerate all loaded modules that match the filter", tool_lsmod)}, + {command("netstat", "[type] [task-id]", + "Enumerate all sockets of said type for task id", tool_netstat)}, }; // clang-format on diff --git a/sample/tool.hpp b/sample/tool.hpp index 67aa16e..94b0b6c 100644 --- a/sample/tool.hpp +++ b/sample/tool.hpp @@ -18,5 +18,6 @@ #define SAMPLE_TOOL_HPP int tool_lsmod(std::vector&& args); +int tool_netstat(std::vector&& args); #endif // SAMPLE_TOOL_HPP diff --git a/sample/tool_netstat.cpp b/sample/tool_netstat.cpp new file mode 100644 index 0000000..8b9e200 --- /dev/null +++ b/sample/tool_netstat.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2020-present Daniel Trugman + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "format.hpp" +#include "log.hpp" +#include "tool.hpp" + +void usage() +{ + LOG("Usage: [type] [task-id]"); + LOG(""); + LOG(" type Socket type: tcp, udp, unix"); + LOG(" task-id The ID of the task to enumerate"); + LOG(""); +} + +int tool_netstat(std::vector&& args) +{ + if (args.size() != 2) + { + usage(); + return 1; + } + + try + { + LOG("========================================================="); + LOG("netstat"); + LOG("========================================================="); + + static const std::string TCP("tcp"); + static const std::string UDP("udp"); + + std::string type(args[0]); + auto id = std::stoi(args[1]); + + pfs::procfs pfs; + auto task = pfs.get_task(id); + + // Get all inodes for the given task + std::set inodes; + auto fds = task.get_fds(); + for (auto& fd : fds) + { + inodes.insert(fd.second.get_target_stat().st_ino); + } + + auto net = task.get_net(); + std::vector sockets; + if (type == TCP) + { + sockets = net.get_tcp(); + } + else if (type == UDP) + { + sockets = net.get_udp(); + } + else + { + usage(); + return 1; + } + + std::vector task_sockets; + for (auto& socket : sockets) + { + if (inodes.find(socket.inode) != inodes.end()) + { + task_sockets.push_back(socket); + } + } + + print(task_sockets); + } + catch (const std::runtime_error& ex) + { + LOG("Error when printing netstat:"); + LOG(TAB << ex.what()); + } + + return 0; +}