summaryrefslogtreecommitdiff
path: root/socket-info
blob: 5c066ea4ec0cf4c6af96c9a4ecd6de81e8e0d815 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/bash
# Prints information about a file descriptor socket
# Author: Peter Wu <lekensteyn@gmail.com>
# Date: 2013-02-06

rootcmd=sudo

sockno=$1
pipeno=

sockfd=$(readlink "$1")
if [[ $sockfd =~ ^socket:\[[0-9]+\]$ ]]; then
	sockno=${sockfd#socket:[}
	sockno=${sockno%]}
fi

# not a socket but a pipe
if [[ $sockfd =~ ^pipe:\[[0-9]+\]$ ]]; then
	pipeno=${sockfd#pipe:[}
	pipeno=${pipeno%]}
	find /proc/[0-9]*/fd -lname "pipe:\\[$pipeno\\]" -ls 2>/dev/null | \
	awk -F/ '{
		pid=$3;
		print "";
		print;
		system("ps huwwp " pid);
	}'
	exit
fi

if ! [[ $sockno =~ ^[0-9]+$ ]]; then
	echo "Numeric socket number required" >&2
	exit 1
fi

# expects: $prot $sockno
# arg1: field index for inode
find_by_inode() {
	</proc/net/$prot awk "{if (\$$1 == $sockno)print}"
}

# arg1: inode of one socket endpoint
find_other_sock() {
	local addr=$1
	local vmlinux=/usr/src/linux-$(uname -r)/vmlinux
	local file

	for file in "$vmlinux" /proc/kcore; do
		if [ ! -e "$file" ]; then
			echo "$file: not found" >&2
			return 1
		fi
	done

	$rootcmd gdb -q "$vmlinux" /proc/kcore \
		-ex "p ((struct	unix_sock*)0x$addr)->peer" -ex q \
	| grep -Po '\(struct sock \*\) 0x\K[0-9a-f]+'
}

line=
for prot in udp tcp; do
	line=$(find_by_inode 10)
	[ -z "$line" ] || break
done

if [ -z "$line" ]; then
	prot=unix
	line=$(find_by_inode 7)
	addr=$(cut -d: -f1 <<<"$line")
	find_by_inode 7
	if [[ $addr =~ ^[0-9a-f]+$ ]]; then
		addr2=$(find_other_sock $addr)
		line2=$(grep "^$addr2:" /proc/net/$prot)
		[ -z "$line2" ] || line="$line"$'\n'"$line2"
	fi
fi

if [ -n "$line" ]; then
	(head -1 /proc/net/$prot;
	echo "$line") | column -t
	exit 0
fi

echo "No info found for $sockno [$sockfd]"