Skip to content

Commit

Permalink
Add netstat sample application
Browse files Browse the repository at this point in the history
  • Loading branch information
dtrugman committed Dec 14, 2023
1 parent 572624f commit d76cdfe
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 5 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 12 additions & 5 deletions sample/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,18 @@ int main(int argc, char** argv)

// clang-format off
auto commands = std::vector<command>{
{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("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("netstat", "[type] [task-id]",
"Enumerate all sockets of said type for task id", tool_netstat)},
};
// clang-format on

Expand Down
1 change: 1 addition & 0 deletions sample/tool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
#define SAMPLE_TOOL_HPP

int tool_lsmod(std::vector<std::string>&& args);
int tool_netstat(std::vector<std::string>&& args);

#endif // SAMPLE_TOOL_HPP
97 changes: 97 additions & 0 deletions sample/tool_netstat.cpp
Original file line number Diff line number Diff line change
@@ -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 <regex>

#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<std::string>&& 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<ino_t> 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<pfs::net_socket> sockets;
if (type == TCP)
{
sockets = net.get_tcp();
}
else if (type == UDP)
{
sockets = net.get_udp();
}
else
{
usage();
return 1;
}

std::vector<pfs::net_socket> 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;
}

0 comments on commit d76cdfe

Please sign in to comment.