1*8dd5e09dSSadaf Ebrahimi /*
2*8dd5e09dSSadaf Ebrahimi * netcap.c - A program that lists network apps with capabilities
3*8dd5e09dSSadaf Ebrahimi * Copyright (c) 2009-10,2012,2020 Red Hat Inc.
4*8dd5e09dSSadaf Ebrahimi * All Rights Reserved.
5*8dd5e09dSSadaf Ebrahimi *
6*8dd5e09dSSadaf Ebrahimi * This software may be freely redistributed and/or modified under the
7*8dd5e09dSSadaf Ebrahimi * terms of the GNU General Public License as published by the Free
8*8dd5e09dSSadaf Ebrahimi * Software Foundation; either version 2, or (at your option) any
9*8dd5e09dSSadaf Ebrahimi * later version.
10*8dd5e09dSSadaf Ebrahimi *
11*8dd5e09dSSadaf Ebrahimi * This program is distributed in the hope that it will be useful,
12*8dd5e09dSSadaf Ebrahimi * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*8dd5e09dSSadaf Ebrahimi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*8dd5e09dSSadaf Ebrahimi * GNU General Public License for more details.
15*8dd5e09dSSadaf Ebrahimi *
16*8dd5e09dSSadaf Ebrahimi * You should have received a copy of the GNU General Public License
17*8dd5e09dSSadaf Ebrahimi * along with this program; see the file COPYING. If not, write to the
18*8dd5e09dSSadaf Ebrahimi * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor
19*8dd5e09dSSadaf Ebrahimi * Boston, MA 02110-1335, USA.
20*8dd5e09dSSadaf Ebrahimi *
21*8dd5e09dSSadaf Ebrahimi * Authors:
22*8dd5e09dSSadaf Ebrahimi * Steve Grubb <[email protected]>
23*8dd5e09dSSadaf Ebrahimi *
24*8dd5e09dSSadaf Ebrahimi * The /proc/net/tcp|udp|raw parsing code was borrowed from netstat.c
25*8dd5e09dSSadaf Ebrahimi */
26*8dd5e09dSSadaf Ebrahimi
27*8dd5e09dSSadaf Ebrahimi #include "config.h"
28*8dd5e09dSSadaf Ebrahimi #include <stdio.h>
29*8dd5e09dSSadaf Ebrahimi #include <stdio_ext.h>
30*8dd5e09dSSadaf Ebrahimi #include <stdlib.h>
31*8dd5e09dSSadaf Ebrahimi #include <errno.h>
32*8dd5e09dSSadaf Ebrahimi #include <string.h>
33*8dd5e09dSSadaf Ebrahimi #include <dirent.h>
34*8dd5e09dSSadaf Ebrahimi #include <fcntl.h>
35*8dd5e09dSSadaf Ebrahimi #include <pwd.h>
36*8dd5e09dSSadaf Ebrahimi #include "cap-ng.h"
37*8dd5e09dSSadaf Ebrahimi #include "proc-llist.h"
38*8dd5e09dSSadaf Ebrahimi
39*8dd5e09dSSadaf Ebrahimi static llist l;
40*8dd5e09dSSadaf Ebrahimi static int perm_warn = 0, header = 0, last_uid = -1;
41*8dd5e09dSSadaf Ebrahimi static char *tacct = NULL;
42*8dd5e09dSSadaf Ebrahimi
usage(void)43*8dd5e09dSSadaf Ebrahimi static void usage(void)
44*8dd5e09dSSadaf Ebrahimi {
45*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "usage: netcap\n");
46*8dd5e09dSSadaf Ebrahimi exit(1);
47*8dd5e09dSSadaf Ebrahimi }
48*8dd5e09dSSadaf Ebrahimi
collect_process_info(void)49*8dd5e09dSSadaf Ebrahimi static int collect_process_info(void)
50*8dd5e09dSSadaf Ebrahimi {
51*8dd5e09dSSadaf Ebrahimi DIR *d, *f;
52*8dd5e09dSSadaf Ebrahimi struct dirent *ent;
53*8dd5e09dSSadaf Ebrahimi d = opendir("/proc");
54*8dd5e09dSSadaf Ebrahimi if (d == NULL) {
55*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open /proc: %s\n", strerror(errno));
56*8dd5e09dSSadaf Ebrahimi return 1;
57*8dd5e09dSSadaf Ebrahimi }
58*8dd5e09dSSadaf Ebrahimi while (( ent = readdir(d) )) {
59*8dd5e09dSSadaf Ebrahimi FILE *sf;
60*8dd5e09dSSadaf Ebrahimi int pid, ppid;
61*8dd5e09dSSadaf Ebrahimi capng_results_t caps;
62*8dd5e09dSSadaf Ebrahimi char buf[100];
63*8dd5e09dSSadaf Ebrahimi char *tmp, cmd[16], state;
64*8dd5e09dSSadaf Ebrahimi char *text = NULL, *bounds = NULL, *ambient = NULL;
65*8dd5e09dSSadaf Ebrahimi int fd, len, euid = -1;
66*8dd5e09dSSadaf Ebrahimi
67*8dd5e09dSSadaf Ebrahimi // Skip non-process dir entries
68*8dd5e09dSSadaf Ebrahimi if(*ent->d_name<'0' || *ent->d_name>'9')
69*8dd5e09dSSadaf Ebrahimi continue;
70*8dd5e09dSSadaf Ebrahimi errno = 0;
71*8dd5e09dSSadaf Ebrahimi pid = strtol(ent->d_name, NULL, 10);
72*8dd5e09dSSadaf Ebrahimi if (errno)
73*8dd5e09dSSadaf Ebrahimi continue;
74*8dd5e09dSSadaf Ebrahimi
75*8dd5e09dSSadaf Ebrahimi // Parse up the stat file for the proc
76*8dd5e09dSSadaf Ebrahimi snprintf(buf, 32, "/proc/%d/stat", pid);
77*8dd5e09dSSadaf Ebrahimi fd = open(buf, O_RDONLY|O_CLOEXEC, 0);
78*8dd5e09dSSadaf Ebrahimi if (fd < 0)
79*8dd5e09dSSadaf Ebrahimi continue;
80*8dd5e09dSSadaf Ebrahimi len = read(fd, buf, sizeof buf - 1);
81*8dd5e09dSSadaf Ebrahimi close(fd);
82*8dd5e09dSSadaf Ebrahimi if (len < 40)
83*8dd5e09dSSadaf Ebrahimi continue;
84*8dd5e09dSSadaf Ebrahimi buf[len] = 0;
85*8dd5e09dSSadaf Ebrahimi tmp = strrchr(buf, ')');
86*8dd5e09dSSadaf Ebrahimi if (tmp)
87*8dd5e09dSSadaf Ebrahimi *tmp = 0;
88*8dd5e09dSSadaf Ebrahimi else
89*8dd5e09dSSadaf Ebrahimi continue;
90*8dd5e09dSSadaf Ebrahimi memset(cmd, 0, sizeof(cmd));
91*8dd5e09dSSadaf Ebrahimi sscanf(buf, "%d (%15c", &ppid, cmd);
92*8dd5e09dSSadaf Ebrahimi sscanf(tmp+2, "%c %d", &state, &ppid);
93*8dd5e09dSSadaf Ebrahimi
94*8dd5e09dSSadaf Ebrahimi // Skip kthreads
95*8dd5e09dSSadaf Ebrahimi if (pid == 2 || ppid == 2)
96*8dd5e09dSSadaf Ebrahimi continue;
97*8dd5e09dSSadaf Ebrahimi
98*8dd5e09dSSadaf Ebrahimi // now get the capabilities
99*8dd5e09dSSadaf Ebrahimi capng_clear(CAPNG_SELECT_ALL);
100*8dd5e09dSSadaf Ebrahimi capng_setpid(pid);
101*8dd5e09dSSadaf Ebrahimi if (capng_get_caps_process())
102*8dd5e09dSSadaf Ebrahimi continue;
103*8dd5e09dSSadaf Ebrahimi caps = capng_have_capabilities(CAPNG_SELECT_CAPS);
104*8dd5e09dSSadaf Ebrahimi if (caps <= CAPNG_NONE)
105*8dd5e09dSSadaf Ebrahimi continue;
106*8dd5e09dSSadaf Ebrahimi if (caps == CAPNG_FULL) {
107*8dd5e09dSSadaf Ebrahimi text = strdup("full");
108*8dd5e09dSSadaf Ebrahimi if (!text) {
109*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Out of memory\n");
110*8dd5e09dSSadaf Ebrahimi continue;
111*8dd5e09dSSadaf Ebrahimi }
112*8dd5e09dSSadaf Ebrahimi } else {
113*8dd5e09dSSadaf Ebrahimi text = capng_print_caps_text(CAPNG_PRINT_BUFFER,
114*8dd5e09dSSadaf Ebrahimi CAPNG_PERMITTED);
115*8dd5e09dSSadaf Ebrahimi if (text == NULL) {
116*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Out of memory doing pid %d\n",
117*8dd5e09dSSadaf Ebrahimi pid);
118*8dd5e09dSSadaf Ebrahimi continue;
119*8dd5e09dSSadaf Ebrahimi }
120*8dd5e09dSSadaf Ebrahimi }
121*8dd5e09dSSadaf Ebrahimi
122*8dd5e09dSSadaf Ebrahimi // Get the effective uid
123*8dd5e09dSSadaf Ebrahimi snprintf(buf, 32, "/proc/%d/status", pid);
124*8dd5e09dSSadaf Ebrahimi sf = fopen(buf, "rte");
125*8dd5e09dSSadaf Ebrahimi if (sf == NULL)
126*8dd5e09dSSadaf Ebrahimi euid = 0;
127*8dd5e09dSSadaf Ebrahimi else {
128*8dd5e09dSSadaf Ebrahimi int line = 0;
129*8dd5e09dSSadaf Ebrahimi __fsetlocking(sf, FSETLOCKING_BYCALLER);
130*8dd5e09dSSadaf Ebrahimi while (fgets(buf, sizeof(buf), sf)) {
131*8dd5e09dSSadaf Ebrahimi if (line == 0) {
132*8dd5e09dSSadaf Ebrahimi line++;
133*8dd5e09dSSadaf Ebrahimi continue;
134*8dd5e09dSSadaf Ebrahimi }
135*8dd5e09dSSadaf Ebrahimi if (memcmp(buf, "Uid:", 4) == 0) {
136*8dd5e09dSSadaf Ebrahimi int id;
137*8dd5e09dSSadaf Ebrahimi sscanf(buf, "Uid: %d %d",
138*8dd5e09dSSadaf Ebrahimi &id, &euid);
139*8dd5e09dSSadaf Ebrahimi break;
140*8dd5e09dSSadaf Ebrahimi }
141*8dd5e09dSSadaf Ebrahimi }
142*8dd5e09dSSadaf Ebrahimi fclose(sf);
143*8dd5e09dSSadaf Ebrahimi }
144*8dd5e09dSSadaf Ebrahimi
145*8dd5e09dSSadaf Ebrahimi caps = capng_have_capabilities(CAPNG_SELECT_AMBIENT);
146*8dd5e09dSSadaf Ebrahimi if (caps > CAPNG_NONE)
147*8dd5e09dSSadaf Ebrahimi ambient = strdup("@");
148*8dd5e09dSSadaf Ebrahimi else
149*8dd5e09dSSadaf Ebrahimi ambient = strdup("");
150*8dd5e09dSSadaf Ebrahimi if (!ambient) {
151*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Out of memory\n");
152*8dd5e09dSSadaf Ebrahimi free(text);
153*8dd5e09dSSadaf Ebrahimi continue;
154*8dd5e09dSSadaf Ebrahimi }
155*8dd5e09dSSadaf Ebrahimi
156*8dd5e09dSSadaf Ebrahimi // Now record the bounding set information
157*8dd5e09dSSadaf Ebrahimi caps = capng_have_capabilities(CAPNG_SELECT_BOUNDS);
158*8dd5e09dSSadaf Ebrahimi if (caps > CAPNG_NONE)
159*8dd5e09dSSadaf Ebrahimi bounds = strdup("+");
160*8dd5e09dSSadaf Ebrahimi else
161*8dd5e09dSSadaf Ebrahimi bounds = strdup("");
162*8dd5e09dSSadaf Ebrahimi if (!bounds) {
163*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Out of memory\n");
164*8dd5e09dSSadaf Ebrahimi free(text);
165*8dd5e09dSSadaf Ebrahimi free(ambient);
166*8dd5e09dSSadaf Ebrahimi continue;
167*8dd5e09dSSadaf Ebrahimi }
168*8dd5e09dSSadaf Ebrahimi
169*8dd5e09dSSadaf Ebrahimi // Now lets get the inodes each process has open
170*8dd5e09dSSadaf Ebrahimi snprintf(buf, 32, "/proc/%d/fd", pid);
171*8dd5e09dSSadaf Ebrahimi f = opendir(buf);
172*8dd5e09dSSadaf Ebrahimi if (f == NULL) {
173*8dd5e09dSSadaf Ebrahimi if (errno == EACCES) {
174*8dd5e09dSSadaf Ebrahimi if (perm_warn == 0) {
175*8dd5e09dSSadaf Ebrahimi fprintf(stderr,
176*8dd5e09dSSadaf Ebrahimi "You may need to be root to "
177*8dd5e09dSSadaf Ebrahimi "get a full report\n");
178*8dd5e09dSSadaf Ebrahimi perm_warn = 1;
179*8dd5e09dSSadaf Ebrahimi }
180*8dd5e09dSSadaf Ebrahimi } else
181*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open %s: %s\n", buf,
182*8dd5e09dSSadaf Ebrahimi strerror(errno));
183*8dd5e09dSSadaf Ebrahimi free(text);
184*8dd5e09dSSadaf Ebrahimi free(bounds);
185*8dd5e09dSSadaf Ebrahimi free(ambient);
186*8dd5e09dSSadaf Ebrahimi continue;
187*8dd5e09dSSadaf Ebrahimi }
188*8dd5e09dSSadaf Ebrahimi // For each file in the fd dir...
189*8dd5e09dSSadaf Ebrahimi while (( ent = readdir(f) )) {
190*8dd5e09dSSadaf Ebrahimi char line[256], ln[256], *s, *e;
191*8dd5e09dSSadaf Ebrahimi unsigned long inode;
192*8dd5e09dSSadaf Ebrahimi lnode node;
193*8dd5e09dSSadaf Ebrahimi int llen;
194*8dd5e09dSSadaf Ebrahimi
195*8dd5e09dSSadaf Ebrahimi if (ent->d_name[0] == '.')
196*8dd5e09dSSadaf Ebrahimi continue;
197*8dd5e09dSSadaf Ebrahimi snprintf(ln, 256, "%s/%s", buf, ent->d_name);
198*8dd5e09dSSadaf Ebrahimi if ((llen = readlink(ln, line, sizeof(line)-1)) < 0)
199*8dd5e09dSSadaf Ebrahimi continue;
200*8dd5e09dSSadaf Ebrahimi line[llen] = 0;
201*8dd5e09dSSadaf Ebrahimi
202*8dd5e09dSSadaf Ebrahimi // Only look at the socket entries
203*8dd5e09dSSadaf Ebrahimi if (memcmp(line, "socket:", 7) == 0) {
204*8dd5e09dSSadaf Ebrahimi // Type 1 sockets
205*8dd5e09dSSadaf Ebrahimi s = strchr(line+7, '[');
206*8dd5e09dSSadaf Ebrahimi if (s == NULL)
207*8dd5e09dSSadaf Ebrahimi continue;
208*8dd5e09dSSadaf Ebrahimi s++;
209*8dd5e09dSSadaf Ebrahimi e = strchr(s, ']');
210*8dd5e09dSSadaf Ebrahimi if (e == NULL)
211*8dd5e09dSSadaf Ebrahimi continue;
212*8dd5e09dSSadaf Ebrahimi *e = 0;
213*8dd5e09dSSadaf Ebrahimi } else if (memcmp(line, "[0000]:", 7) == 0) {
214*8dd5e09dSSadaf Ebrahimi // Type 2 sockets
215*8dd5e09dSSadaf Ebrahimi s = line + 8;
216*8dd5e09dSSadaf Ebrahimi } else
217*8dd5e09dSSadaf Ebrahimi continue;
218*8dd5e09dSSadaf Ebrahimi errno = 0;
219*8dd5e09dSSadaf Ebrahimi inode = strtoul(s, NULL, 10);
220*8dd5e09dSSadaf Ebrahimi if (errno)
221*8dd5e09dSSadaf Ebrahimi continue;
222*8dd5e09dSSadaf Ebrahimi node.ppid = ppid;
223*8dd5e09dSSadaf Ebrahimi node.pid = pid;
224*8dd5e09dSSadaf Ebrahimi node.uid = euid;
225*8dd5e09dSSadaf Ebrahimi node.cmd = strdup(cmd);
226*8dd5e09dSSadaf Ebrahimi node.inode = inode;
227*8dd5e09dSSadaf Ebrahimi node.capabilities = strdup(text);
228*8dd5e09dSSadaf Ebrahimi node.bounds = strdup(bounds);
229*8dd5e09dSSadaf Ebrahimi node.ambient = strdup(ambient);
230*8dd5e09dSSadaf Ebrahimi if (node.cmd && node.capabilities && node.bounds &&
231*8dd5e09dSSadaf Ebrahimi node.ambient)
232*8dd5e09dSSadaf Ebrahimi // We make one entry for each socket inode
233*8dd5e09dSSadaf Ebrahimi list_append(&l, &node);
234*8dd5e09dSSadaf Ebrahimi else {
235*8dd5e09dSSadaf Ebrahimi free(node.cmd);
236*8dd5e09dSSadaf Ebrahimi free(node.capabilities);
237*8dd5e09dSSadaf Ebrahimi free(node.bounds);
238*8dd5e09dSSadaf Ebrahimi free(node.ambient);
239*8dd5e09dSSadaf Ebrahimi }
240*8dd5e09dSSadaf Ebrahimi }
241*8dd5e09dSSadaf Ebrahimi closedir(f);
242*8dd5e09dSSadaf Ebrahimi free(text);
243*8dd5e09dSSadaf Ebrahimi free(bounds);
244*8dd5e09dSSadaf Ebrahimi free(ambient);
245*8dd5e09dSSadaf Ebrahimi }
246*8dd5e09dSSadaf Ebrahimi closedir(d);
247*8dd5e09dSSadaf Ebrahimi return 0;
248*8dd5e09dSSadaf Ebrahimi }
249*8dd5e09dSSadaf Ebrahimi
report_finding(unsigned int port,const char * type,const char * ifc)250*8dd5e09dSSadaf Ebrahimi static void report_finding(unsigned int port, const char *type, const char *ifc)
251*8dd5e09dSSadaf Ebrahimi {
252*8dd5e09dSSadaf Ebrahimi struct passwd *p;
253*8dd5e09dSSadaf Ebrahimi lnode *n = list_get_cur(&l);
254*8dd5e09dSSadaf Ebrahimi
255*8dd5e09dSSadaf Ebrahimi // And print out anything with capabilities
256*8dd5e09dSSadaf Ebrahimi if (header == 0) {
257*8dd5e09dSSadaf Ebrahimi printf("%-5s %-5s %-10s %-16s %-8s %-6s %s\n",
258*8dd5e09dSSadaf Ebrahimi "ppid", "pid", "acct", "command", "type", "port",
259*8dd5e09dSSadaf Ebrahimi "capabilities");
260*8dd5e09dSSadaf Ebrahimi header = 1;
261*8dd5e09dSSadaf Ebrahimi }
262*8dd5e09dSSadaf Ebrahimi if (n->uid == 0) {
263*8dd5e09dSSadaf Ebrahimi // Take short cut for this one
264*8dd5e09dSSadaf Ebrahimi tacct = "root";
265*8dd5e09dSSadaf Ebrahimi last_uid = 0;
266*8dd5e09dSSadaf Ebrahimi } else if (last_uid != (int)n->uid) {
267*8dd5e09dSSadaf Ebrahimi // Only look up if name changed
268*8dd5e09dSSadaf Ebrahimi p = getpwuid(n->uid);
269*8dd5e09dSSadaf Ebrahimi last_uid = n->uid;
270*8dd5e09dSSadaf Ebrahimi if (p)
271*8dd5e09dSSadaf Ebrahimi tacct = p->pw_name;
272*8dd5e09dSSadaf Ebrahimi // If not taking this branch, use last val
273*8dd5e09dSSadaf Ebrahimi }
274*8dd5e09dSSadaf Ebrahimi if (tacct) {
275*8dd5e09dSSadaf Ebrahimi printf("%-5d %-5d %-10s", n->ppid, n->pid, tacct);
276*8dd5e09dSSadaf Ebrahimi } else
277*8dd5e09dSSadaf Ebrahimi printf("%-5d %-5d %-10d", n->ppid, n->pid, last_uid);
278*8dd5e09dSSadaf Ebrahimi printf(" %-16s %-8s", n->cmd, type);
279*8dd5e09dSSadaf Ebrahimi if (ifc)
280*8dd5e09dSSadaf Ebrahimi printf(" %-6s", ifc);
281*8dd5e09dSSadaf Ebrahimi else
282*8dd5e09dSSadaf Ebrahimi printf(" %-6u", port);
283*8dd5e09dSSadaf Ebrahimi printf(" %s %s%s\n", n->capabilities, n->ambient, n->bounds);
284*8dd5e09dSSadaf Ebrahimi }
285*8dd5e09dSSadaf Ebrahimi
read_tcp(const char * proc,const char * type)286*8dd5e09dSSadaf Ebrahimi static void read_tcp(const char *proc, const char *type)
287*8dd5e09dSSadaf Ebrahimi {
288*8dd5e09dSSadaf Ebrahimi int line = 0;
289*8dd5e09dSSadaf Ebrahimi FILE *f;
290*8dd5e09dSSadaf Ebrahimi char buf[256];
291*8dd5e09dSSadaf Ebrahimi unsigned long rxq, txq, time_len, retr, inode;
292*8dd5e09dSSadaf Ebrahimi unsigned int local_port, rem_port, state, timer_run;
293*8dd5e09dSSadaf Ebrahimi int d, uid, timeout;
294*8dd5e09dSSadaf Ebrahimi char rem_addr[128], local_addr[128], more[512];
295*8dd5e09dSSadaf Ebrahimi
296*8dd5e09dSSadaf Ebrahimi f = fopen(proc, "rte");
297*8dd5e09dSSadaf Ebrahimi if (f == NULL) {
298*8dd5e09dSSadaf Ebrahimi if (errno != ENOENT)
299*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open %s: %s\n",
300*8dd5e09dSSadaf Ebrahimi proc, strerror(errno));
301*8dd5e09dSSadaf Ebrahimi return;
302*8dd5e09dSSadaf Ebrahimi }
303*8dd5e09dSSadaf Ebrahimi __fsetlocking(f, FSETLOCKING_BYCALLER);
304*8dd5e09dSSadaf Ebrahimi while (fgets(buf, sizeof(buf), f)) {
305*8dd5e09dSSadaf Ebrahimi if (line == 0) {
306*8dd5e09dSSadaf Ebrahimi line++;
307*8dd5e09dSSadaf Ebrahimi continue;
308*8dd5e09dSSadaf Ebrahimi }
309*8dd5e09dSSadaf Ebrahimi more[0] = 0;
310*8dd5e09dSSadaf Ebrahimi sscanf(buf, "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X "
311*8dd5e09dSSadaf Ebrahimi "%lX:%lX %X:%lX %lX %d %d %lu %511s\n",
312*8dd5e09dSSadaf Ebrahimi &d, local_addr, &local_port, rem_addr, &rem_port,
313*8dd5e09dSSadaf Ebrahimi &state, &txq, &rxq, &timer_run, &time_len, &retr,
314*8dd5e09dSSadaf Ebrahimi &uid, &timeout, &inode, more);
315*8dd5e09dSSadaf Ebrahimi if (list_find_inode(&l, inode))
316*8dd5e09dSSadaf Ebrahimi report_finding(local_port, type, NULL);
317*8dd5e09dSSadaf Ebrahimi }
318*8dd5e09dSSadaf Ebrahimi fclose(f);
319*8dd5e09dSSadaf Ebrahimi }
320*8dd5e09dSSadaf Ebrahimi
read_udp(const char * proc,const char * type)321*8dd5e09dSSadaf Ebrahimi static void read_udp(const char *proc, const char *type)
322*8dd5e09dSSadaf Ebrahimi {
323*8dd5e09dSSadaf Ebrahimi int line = 0;
324*8dd5e09dSSadaf Ebrahimi FILE *f;
325*8dd5e09dSSadaf Ebrahimi char buf[256];
326*8dd5e09dSSadaf Ebrahimi unsigned long rxq, txq, time_len, retr, inode;
327*8dd5e09dSSadaf Ebrahimi unsigned int local_port, rem_port, state, timer_run;
328*8dd5e09dSSadaf Ebrahimi int d, uid, timeout;
329*8dd5e09dSSadaf Ebrahimi char rem_addr[128], local_addr[128], more[512];
330*8dd5e09dSSadaf Ebrahimi
331*8dd5e09dSSadaf Ebrahimi f = fopen(proc, "rte");
332*8dd5e09dSSadaf Ebrahimi if (f == NULL) {
333*8dd5e09dSSadaf Ebrahimi if (errno != ENOENT)
334*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open %s: %s\n",
335*8dd5e09dSSadaf Ebrahimi proc, strerror(errno));
336*8dd5e09dSSadaf Ebrahimi return;
337*8dd5e09dSSadaf Ebrahimi }
338*8dd5e09dSSadaf Ebrahimi __fsetlocking(f, FSETLOCKING_BYCALLER);
339*8dd5e09dSSadaf Ebrahimi while (fgets(buf, sizeof(buf), f)) {
340*8dd5e09dSSadaf Ebrahimi if (line == 0) {
341*8dd5e09dSSadaf Ebrahimi line++;
342*8dd5e09dSSadaf Ebrahimi continue;
343*8dd5e09dSSadaf Ebrahimi }
344*8dd5e09dSSadaf Ebrahimi more[0] = 0;
345*8dd5e09dSSadaf Ebrahimi sscanf(buf, "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X "
346*8dd5e09dSSadaf Ebrahimi "%lX:%lX %X:%lX %lX %d %d %lu %511s\n",
347*8dd5e09dSSadaf Ebrahimi &d, local_addr, &local_port, rem_addr, &rem_port,
348*8dd5e09dSSadaf Ebrahimi &state, &txq, &rxq, &timer_run, &time_len, &retr,
349*8dd5e09dSSadaf Ebrahimi &uid, &timeout, &inode, more);
350*8dd5e09dSSadaf Ebrahimi if (list_find_inode(&l, inode))
351*8dd5e09dSSadaf Ebrahimi report_finding(local_port, type, NULL);
352*8dd5e09dSSadaf Ebrahimi }
353*8dd5e09dSSadaf Ebrahimi fclose(f);
354*8dd5e09dSSadaf Ebrahimi }
355*8dd5e09dSSadaf Ebrahimi
read_raw(const char * proc,const char * type)356*8dd5e09dSSadaf Ebrahimi static void read_raw(const char *proc, const char *type)
357*8dd5e09dSSadaf Ebrahimi {
358*8dd5e09dSSadaf Ebrahimi int line = 0;
359*8dd5e09dSSadaf Ebrahimi FILE *f;
360*8dd5e09dSSadaf Ebrahimi char buf[256];
361*8dd5e09dSSadaf Ebrahimi unsigned long rxq, txq, time_len, retr, inode;
362*8dd5e09dSSadaf Ebrahimi unsigned int local_port, rem_port, state, timer_run;
363*8dd5e09dSSadaf Ebrahimi int d, uid, timeout;
364*8dd5e09dSSadaf Ebrahimi char rem_addr[128], local_addr[128], more[512];
365*8dd5e09dSSadaf Ebrahimi
366*8dd5e09dSSadaf Ebrahimi f = fopen(proc, "rte");
367*8dd5e09dSSadaf Ebrahimi if (f == NULL) {
368*8dd5e09dSSadaf Ebrahimi if (errno != ENOENT)
369*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open %s: %s\n",
370*8dd5e09dSSadaf Ebrahimi proc, strerror(errno));
371*8dd5e09dSSadaf Ebrahimi return;
372*8dd5e09dSSadaf Ebrahimi }
373*8dd5e09dSSadaf Ebrahimi __fsetlocking(f, FSETLOCKING_BYCALLER);
374*8dd5e09dSSadaf Ebrahimi while (fgets(buf, sizeof(buf), f)) {
375*8dd5e09dSSadaf Ebrahimi if (line == 0) {
376*8dd5e09dSSadaf Ebrahimi line++;
377*8dd5e09dSSadaf Ebrahimi continue;
378*8dd5e09dSSadaf Ebrahimi }
379*8dd5e09dSSadaf Ebrahimi more[0] = 0;
380*8dd5e09dSSadaf Ebrahimi sscanf(buf, "%d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %X "
381*8dd5e09dSSadaf Ebrahimi "%lX:%lX %X:%lX %lX %d %d %lu %511s\n",
382*8dd5e09dSSadaf Ebrahimi &d, local_addr, &local_port, rem_addr, &rem_port,
383*8dd5e09dSSadaf Ebrahimi &state, &txq, &rxq, &timer_run, &time_len, &retr,
384*8dd5e09dSSadaf Ebrahimi &uid, &timeout, &inode, more);
385*8dd5e09dSSadaf Ebrahimi if (list_find_inode(&l, inode))
386*8dd5e09dSSadaf Ebrahimi report_finding(0, type, NULL);
387*8dd5e09dSSadaf Ebrahimi }
388*8dd5e09dSSadaf Ebrahimi fclose(f);
389*8dd5e09dSSadaf Ebrahimi }
390*8dd5e09dSSadaf Ebrahimi
391*8dd5e09dSSadaf Ebrahimi // Caller must have buffer > 16 bytes
get_interface(unsigned int iface,char * ifc)392*8dd5e09dSSadaf Ebrahimi static void get_interface(unsigned int iface, char *ifc)
393*8dd5e09dSSadaf Ebrahimi {
394*8dd5e09dSSadaf Ebrahimi unsigned int line = 0;
395*8dd5e09dSSadaf Ebrahimi FILE *f;
396*8dd5e09dSSadaf Ebrahimi char buf[256], more[256];
397*8dd5e09dSSadaf Ebrahimi
398*8dd5e09dSSadaf Ebrahimi // Terminate the interface in case of error
399*8dd5e09dSSadaf Ebrahimi *ifc = 0;
400*8dd5e09dSSadaf Ebrahimi
401*8dd5e09dSSadaf Ebrahimi // Increment the interface number since header is 2 lines long
402*8dd5e09dSSadaf Ebrahimi iface++;
403*8dd5e09dSSadaf Ebrahimi
404*8dd5e09dSSadaf Ebrahimi f = fopen("/proc/net/dev", "rte");
405*8dd5e09dSSadaf Ebrahimi if (f == NULL) {
406*8dd5e09dSSadaf Ebrahimi if (errno != ENOENT)
407*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open /proc/net/dev: %s\n",
408*8dd5e09dSSadaf Ebrahimi strerror(errno));
409*8dd5e09dSSadaf Ebrahimi return;
410*8dd5e09dSSadaf Ebrahimi }
411*8dd5e09dSSadaf Ebrahimi __fsetlocking(f, FSETLOCKING_BYCALLER);
412*8dd5e09dSSadaf Ebrahimi while (fgets(buf, sizeof(buf), f)) {
413*8dd5e09dSSadaf Ebrahimi if (line == iface) {
414*8dd5e09dSSadaf Ebrahimi char *c;
415*8dd5e09dSSadaf Ebrahimi sscanf(buf, "%16s: %255s\n", ifc, more);
416*8dd5e09dSSadaf Ebrahimi c = strchr(ifc, ':');
417*8dd5e09dSSadaf Ebrahimi if (c)
418*8dd5e09dSSadaf Ebrahimi *c = 0;
419*8dd5e09dSSadaf Ebrahimi fclose(f);
420*8dd5e09dSSadaf Ebrahimi return;
421*8dd5e09dSSadaf Ebrahimi }
422*8dd5e09dSSadaf Ebrahimi line++;
423*8dd5e09dSSadaf Ebrahimi }
424*8dd5e09dSSadaf Ebrahimi fclose(f);
425*8dd5e09dSSadaf Ebrahimi }
426*8dd5e09dSSadaf Ebrahimi
read_packet(void)427*8dd5e09dSSadaf Ebrahimi static void read_packet(void)
428*8dd5e09dSSadaf Ebrahimi {
429*8dd5e09dSSadaf Ebrahimi int line = 0;
430*8dd5e09dSSadaf Ebrahimi FILE *f;
431*8dd5e09dSSadaf Ebrahimi char buf[256];
432*8dd5e09dSSadaf Ebrahimi unsigned long sk, inode;
433*8dd5e09dSSadaf Ebrahimi unsigned int ref_cnt, type, proto, iface, r, rmem, uid;
434*8dd5e09dSSadaf Ebrahimi char more[256], ifc[32];
435*8dd5e09dSSadaf Ebrahimi
436*8dd5e09dSSadaf Ebrahimi f = fopen("/proc/net/packet", "rte");
437*8dd5e09dSSadaf Ebrahimi if (f == NULL) {
438*8dd5e09dSSadaf Ebrahimi if (errno != ENOENT)
439*8dd5e09dSSadaf Ebrahimi fprintf(stderr, "Can't open /proc/net/packet: %s\n",
440*8dd5e09dSSadaf Ebrahimi strerror(errno));
441*8dd5e09dSSadaf Ebrahimi return;
442*8dd5e09dSSadaf Ebrahimi }
443*8dd5e09dSSadaf Ebrahimi __fsetlocking(f, FSETLOCKING_BYCALLER);
444*8dd5e09dSSadaf Ebrahimi while (fgets(buf, sizeof(buf), f)) {
445*8dd5e09dSSadaf Ebrahimi if (line == 0) {
446*8dd5e09dSSadaf Ebrahimi line++;
447*8dd5e09dSSadaf Ebrahimi continue;
448*8dd5e09dSSadaf Ebrahimi }
449*8dd5e09dSSadaf Ebrahimi more[0] = 0;
450*8dd5e09dSSadaf Ebrahimi sscanf(buf, "%lX %u %u %X %u %u %u %u %lu %255s\n",
451*8dd5e09dSSadaf Ebrahimi &sk, &ref_cnt, &type, &proto, &iface,
452*8dd5e09dSSadaf Ebrahimi &r, &rmem, &uid, &inode, more);
453*8dd5e09dSSadaf Ebrahimi get_interface(iface, ifc);
454*8dd5e09dSSadaf Ebrahimi if (list_find_inode(&l, inode))
455*8dd5e09dSSadaf Ebrahimi report_finding(0, "pkt", ifc);
456*8dd5e09dSSadaf Ebrahimi }
457*8dd5e09dSSadaf Ebrahimi fclose(f);
458*8dd5e09dSSadaf Ebrahimi }
459*8dd5e09dSSadaf Ebrahimi
main(int argc,char * argv[])460*8dd5e09dSSadaf Ebrahimi int main(int argc, char __attribute__((unused)) *argv[])
461*8dd5e09dSSadaf Ebrahimi {
462*8dd5e09dSSadaf Ebrahimi if (argc > 1) {
463*8dd5e09dSSadaf Ebrahimi fputs("Too many arguments\n", stderr);
464*8dd5e09dSSadaf Ebrahimi usage();
465*8dd5e09dSSadaf Ebrahimi }
466*8dd5e09dSSadaf Ebrahimi
467*8dd5e09dSSadaf Ebrahimi list_create(&l);
468*8dd5e09dSSadaf Ebrahimi collect_process_info();
469*8dd5e09dSSadaf Ebrahimi
470*8dd5e09dSSadaf Ebrahimi // Now we check the tcp socket list...
471*8dd5e09dSSadaf Ebrahimi read_tcp("/proc/net/tcp", "tcp");
472*8dd5e09dSSadaf Ebrahimi read_tcp("/proc/net/tcp6", "tcp6");
473*8dd5e09dSSadaf Ebrahimi
474*8dd5e09dSSadaf Ebrahimi // Next udp sockets...
475*8dd5e09dSSadaf Ebrahimi read_udp("/proc/net/udp", "udp");
476*8dd5e09dSSadaf Ebrahimi read_udp("/proc/net/udp6", "udp6");
477*8dd5e09dSSadaf Ebrahimi read_udp("/proc/net/udplite", "udplite");
478*8dd5e09dSSadaf Ebrahimi read_udp("/proc/net/udplite6", "udplite6");
479*8dd5e09dSSadaf Ebrahimi
480*8dd5e09dSSadaf Ebrahimi // Next, raw sockets...
481*8dd5e09dSSadaf Ebrahimi read_raw("/proc/net/raw", "raw");
482*8dd5e09dSSadaf Ebrahimi read_raw("/proc/net/raw6", "raw6");
483*8dd5e09dSSadaf Ebrahimi
484*8dd5e09dSSadaf Ebrahimi // And last, read packet sockets
485*8dd5e09dSSadaf Ebrahimi read_packet();
486*8dd5e09dSSadaf Ebrahimi
487*8dd5e09dSSadaf Ebrahimi // Could also do icmp,netlink,unix
488*8dd5e09dSSadaf Ebrahimi
489*8dd5e09dSSadaf Ebrahimi list_clear(&l);
490*8dd5e09dSSadaf Ebrahimi return 0;
491*8dd5e09dSSadaf Ebrahimi }
492*8dd5e09dSSadaf Ebrahimi
493