Skip to content

Commit 176a9ce

Browse files
committed
Add hw1
1 parent 85f1365 commit 176a9ce

File tree

2 files changed

+258
-0
lines changed

2 files changed

+258
-0
lines changed

hw1/Makefile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CXX = g++
2+
CFLAGS = -Wall -g -std=c++17
3+
4+
PROGS = hw1
5+
6+
all: $(PROGS)
7+
8+
%: %.cpp
9+
$(CXX) -o $@ $(CFLAGS) $< $(LDFLAGS)
10+
11+
.PHONY: clean test
12+
13+
clean:
14+
rm -f *~ $(PROGS)
15+
16+
test: $(PROGS)
17+
sudo ./$<

hw1/hw1.cpp

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
#include <iostream>
2+
#include <iomanip>
3+
#include <fstream>
4+
#include <sstream>
5+
#include <string>
6+
#include <vector>
7+
#include <map>
8+
#include <regex>
9+
#include <getopt.h>
10+
#include <netinet/in.h>
11+
#include <arpa/inet.h>
12+
#include <sys/types.h>
13+
#include <dirent.h>
14+
#include <sys/stat.h>
15+
16+
#define PB push_back
17+
18+
using namespace std;
19+
20+
typedef vector<string> VS;
21+
typedef vector<int> VI;
22+
23+
char optstring[] = "tu";
24+
25+
struct option longopts[] = {
26+
{"tcp", no_argument, NULL, 't'},
27+
{"udp", no_argument, NULL, 'u'},
28+
{NULL, no_argument, NULL, 0}
29+
};
30+
31+
bool is_v6 = false;
32+
bool is_tcp = true;
33+
34+
string nettype[] = {"udp", "udp6", "tcp", "tcp6"};
35+
36+
struct netstat {
37+
int ty;
38+
VS s;
39+
void print() {
40+
cout << setiosflags(ios::left) << setw(6)
41+
<< nettype[ty]
42+
<< setw(24)
43+
<< s[0] + ":" + s[1]
44+
<< setw(24)
45+
<< s[2] + ":" + s[3]
46+
<< s[4] + "/" + s[5] << endl;
47+
}
48+
};
49+
50+
vector<netstat> tcps, udps;
51+
// inode, pid
52+
map<string, string> map2pid;
53+
// pid, cmd
54+
map<string, string> map2cmd;
55+
string filter;
56+
57+
void list(const string name) {
58+
cout << "List of " << name << " connections:" << endl;
59+
cout << setiosflags(ios::left) << setw(6)
60+
<< "Proto" << setw(24)
61+
<< "Local Address" << setw(24)
62+
<< "Foreign Address"
63+
<< "PID/Program name and arguments" << endl;
64+
}
65+
66+
VS split(const string &s, const char d = '\0') {
67+
VS res;
68+
stringstream ss(s);
69+
string item;
70+
if (d)
71+
while (getline(ss, item, d)) res.PB(item);
72+
else
73+
while (ss >> item) res.PB(item);
74+
return res;
75+
}
76+
77+
void h2i(const string &s, auto &x) {
78+
stringstream ss;
79+
ss << hex << s;
80+
ss >> x;
81+
}
82+
83+
bool recmp(const string &s, const string &pat) {
84+
regex re(pat);
85+
return regex_search(s, re);
86+
}
87+
88+
string get_addr(const string &s) {
89+
if (is_v6) {
90+
struct sockaddr_in6 sa;
91+
for (int i = 0; i < 4; i++) {
92+
h2i(s.substr(i * 8, 8), sa.sin6_addr.s6_addr32[i]);
93+
}
94+
char str[INET6_ADDRSTRLEN + 1] = {0};
95+
inet_ntop(AF_INET6, &(sa.sin6_addr), str, INET6_ADDRSTRLEN);
96+
return str;
97+
}
98+
else {
99+
struct sockaddr_in sa;
100+
h2i(s, sa.sin_addr.s_addr);
101+
char str[INET_ADDRSTRLEN + 1] = {0};
102+
inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);
103+
return str;
104+
}
105+
}
106+
107+
string get_port(const string &s) {
108+
int port;
109+
h2i(s, port);
110+
return port ? to_string(port) : "*";
111+
}
112+
113+
VS convert(const string &s) {
114+
VS tmp = split(s, ':'), res;
115+
res.PB(get_addr(tmp[0]));
116+
res.PB(get_port(tmp[1]));
117+
return res;
118+
}
119+
120+
VS list_dir(const string &path) {
121+
VS res;
122+
DIR *dirp = opendir(path.c_str());
123+
if (dirp == NULL) return res;
124+
struct dirent *dp;
125+
while ((dp = readdir(dirp)) != NULL) {
126+
res.PB(dp->d_name);
127+
}
128+
closedir(dirp);
129+
return res;
130+
}
131+
132+
int get_sockinode(const string &path) {
133+
struct stat sb;
134+
if (stat(path.c_str(), &sb) == -1) {
135+
return -1;
136+
}
137+
return (sb.st_mode & S_IFMT) == S_IFSOCK ? sb.st_ino : -1;
138+
}
139+
140+
string get_cmd(const string &path) {
141+
ifstream fin(path);
142+
string cmd;
143+
getline(fin, cmd);
144+
for (auto &x : cmd) {
145+
if (x == '\0') x = ' ';
146+
}
147+
fin.close();
148+
return cmd;
149+
}
150+
151+
void build_map() {
152+
string proc = "/proc/";
153+
VS pids = list_dir(proc);
154+
for (auto &pid : pids) {
155+
string fd_path = proc + pid + "/fd/";
156+
string cmd = get_cmd(proc + pid + "/cmdline");
157+
if (cmd == "") continue;
158+
map2cmd[pid] = cmd;
159+
VS items = list_dir(fd_path);
160+
for (auto &x : items) {
161+
int inode = get_sockinode(fd_path + x);
162+
if (inode != -1) {
163+
map2pid[to_string(inode)] = pid;
164+
}
165+
}
166+
}
167+
}
168+
169+
void parse(const string &path) {
170+
ifstream fin(path);
171+
string tmp;
172+
getline(fin, tmp); // don't need the first line
173+
while (getline(fin, tmp)) {
174+
VS v = split(tmp);
175+
VS lo = convert(v[1]), fo = convert(v[2]);
176+
string pid = map2pid[v[9]];
177+
string cmd = map2cmd[pid];
178+
netstat n{(is_tcp << 1) | is_v6, {lo[0], lo[1], fo[0], fo[1], pid, cmd}};
179+
is_tcp ? tcps.PB(n) : udps.PB(n);
180+
}
181+
fin.close();
182+
}
183+
184+
void list_tcp() {
185+
is_tcp = true;
186+
is_v6 = false;
187+
parse("/proc/net/tcp");
188+
is_v6 = true;
189+
parse("/proc/net/tcp6");
190+
list("TCP");
191+
for (auto &x : tcps) {
192+
if (filter == "" || recmp(x.s[5], filter))
193+
x.print();
194+
}
195+
cout << endl;
196+
}
197+
198+
void list_udp() {
199+
is_tcp = false;
200+
is_v6 = false;
201+
parse("/proc/net/udp");
202+
is_v6 = true;
203+
parse("/proc/net/udp6");
204+
list("UDP");
205+
for (auto &x : udps) {
206+
if (filter == "" || recmp(x.s[5], filter))
207+
x.print();
208+
}
209+
cout << endl;
210+
}
211+
212+
int main(int argc, char* argv[]) {
213+
bool list_t = false, list_u = false;
214+
int c;
215+
while ((c = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) {
216+
switch (c) {
217+
case 't':
218+
list_t = true;
219+
break;
220+
case 'u':
221+
list_u = true;
222+
break;
223+
default:
224+
cout << "Usage: ./hw1 [-t|--tcp] [-u|--udp] [filter-string]" << endl;
225+
return 1;
226+
}
227+
}
228+
argc -= optind;
229+
argv += optind;
230+
if (argv[0] != NULL) filter = argv[0];
231+
build_map();
232+
if (list_t | list_u) {
233+
if (list_t) list_tcp();
234+
if (list_u) list_udp();
235+
}
236+
else {
237+
list_tcp();
238+
list_udp();
239+
}
240+
return 0;
241+
}

0 commit comments

Comments
 (0)