xref: /aosp_15_r20/external/libcap-ng/utils/netcap.c (revision 8dd5e09d5faf27a871e8654ddaa2d2af7c696578)
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