Skip to content

Commit d76cdfe

Browse files
committed
Add netstat sample application
1 parent 572624f commit d76cdfe

File tree

4 files changed

+112
-5
lines changed

4 files changed

+112
-5
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ How does that affect `pfs`?
9191

9292
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.
9393

94+
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.
95+
9496
Anyway, here are some cool (and concise) examples:
9597

9698
**Example 1:** Iterater over all the loaded unsigned or out-of-tree kernel modules

sample/sample.cpp

+12-5
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,18 @@ int main(int argc, char** argv)
3737

3838
// clang-format off
3939
auto commands = std::vector<command>{
40-
{command("system", "", "Enumerate system-wide information", enum_system)},
41-
{command("net", "", "Enumerate network information", enum_net)},
42-
{command("tasks", "[task-id]...", "Enumerate running tasks", enum_tasks)},
43-
{command("fds", "[task-id]...", "Enumerate fds for a specific task", enum_fds)},
44-
{command("lsmod", "[filter]", "Enumerate all loaded modules that match the filter", tool_lsmod)},
40+
{command("system", "",
41+
"Enumerate system-wide information", enum_system)},
42+
{command("net", "",
43+
"Enumerate network information", enum_net)},
44+
{command("tasks", "[task-id]...",
45+
"Enumerate running tasks", enum_tasks)},
46+
{command("fds", "[task-id]...",
47+
"Enumerate fds for a specific task", enum_fds)},
48+
{command("lsmod", "[filter]",
49+
"Enumerate all loaded modules that match the filter", tool_lsmod)},
50+
{command("netstat", "[type] [task-id]",
51+
"Enumerate all sockets of said type for task id", tool_netstat)},
4552
};
4653
// clang-format on
4754

sample/tool.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818
#define SAMPLE_TOOL_HPP
1919

2020
int tool_lsmod(std::vector<std::string>&& args);
21+
int tool_netstat(std::vector<std::string>&& args);
2122

2223
#endif // SAMPLE_TOOL_HPP

sample/tool_netstat.cpp

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2020-present Daniel Trugman
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 <regex>
18+
19+
#include "format.hpp"
20+
#include "log.hpp"
21+
#include "tool.hpp"
22+
23+
void usage()
24+
{
25+
LOG("Usage: [type] [task-id]");
26+
LOG("");
27+
LOG(" type Socket type: tcp, udp, unix");
28+
LOG(" task-id The ID of the task to enumerate");
29+
LOG("");
30+
}
31+
32+
int tool_netstat(std::vector<std::string>&& args)
33+
{
34+
if (args.size() != 2)
35+
{
36+
usage();
37+
return 1;
38+
}
39+
40+
try
41+
{
42+
LOG("=========================================================");
43+
LOG("netstat");
44+
LOG("=========================================================");
45+
46+
static const std::string TCP("tcp");
47+
static const std::string UDP("udp");
48+
49+
std::string type(args[0]);
50+
auto id = std::stoi(args[1]);
51+
52+
pfs::procfs pfs;
53+
auto task = pfs.get_task(id);
54+
55+
// Get all inodes for the given task
56+
std::set<ino_t> inodes;
57+
auto fds = task.get_fds();
58+
for (auto& fd : fds)
59+
{
60+
inodes.insert(fd.second.get_target_stat().st_ino);
61+
}
62+
63+
auto net = task.get_net();
64+
std::vector<pfs::net_socket> sockets;
65+
if (type == TCP)
66+
{
67+
sockets = net.get_tcp();
68+
}
69+
else if (type == UDP)
70+
{
71+
sockets = net.get_udp();
72+
}
73+
else
74+
{
75+
usage();
76+
return 1;
77+
}
78+
79+
std::vector<pfs::net_socket> task_sockets;
80+
for (auto& socket : sockets)
81+
{
82+
if (inodes.find(socket.inode) != inodes.end())
83+
{
84+
task_sockets.push_back(socket);
85+
}
86+
}
87+
88+
print(task_sockets);
89+
}
90+
catch (const std::runtime_error& ex)
91+
{
92+
LOG("Error when printing netstat:");
93+
LOG(TAB << ex.what());
94+
}
95+
96+
return 0;
97+
}

0 commit comments

Comments
 (0)