Blame view

net/dccp/probe.c 4.88 KB
e41542f51   Ian McDonald   [DCCP]: Introduce...
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
  /*
   * dccp_probe - Observe the DCCP flow with kprobes.
   *
   * The idea for this came from Werner Almesberger's umlsim
   * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
   *
   * Modified for DCCP from Stephen Hemminger's code
   * Copyright (C) 2006, Ian McDonald <ian.mcdonald@jandi.co.nz>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
  #include <linux/kernel.h>
  #include <linux/kprobes.h>
  #include <linux/socket.h>
  #include <linux/dccp.h>
  #include <linux/proc_fs.h>
  #include <linux/module.h>
  #include <linux/kfifo.h>
  #include <linux/vmalloc.h>
1032a6687   Tina Ruchandani   Use 64-bit timeke...
33
  #include <linux/time64.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
34
  #include <linux/gfp.h>
457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
35
  #include <net/net_namespace.h>
e41542f51   Ian McDonald   [DCCP]: Introduce...
36
37
38
39
40
41
42
43
44
45
  
  #include "dccp.h"
  #include "ccid.h"
  #include "ccids/ccid3.h"
  
  static int port;
  
  static int bufsize = 64 * 1024;
  
  static const char procname[] = "dccpprobe";
1e2f0e5e8   Gerrit Renker   dccp: Fix sparse ...
46
  static struct {
454654878   Stefani Seibold   kfifo: move struc...
47
  	struct kfifo	  fifo;
e41542f51   Ian McDonald   [DCCP]: Introduce...
48
49
  	spinlock_t	  lock;
  	wait_queue_head_t wait;
1032a6687   Tina Ruchandani   Use 64-bit timeke...
50
  	struct timespec64 tstart;
e41542f51   Ian McDonald   [DCCP]: Introduce...
51
52
53
54
55
56
  } dccpw;
  
  static void printl(const char *fmt, ...)
  {
  	va_list args;
  	int len;
1032a6687   Tina Ruchandani   Use 64-bit timeke...
57
  	struct timespec64 now;
e41542f51   Ian McDonald   [DCCP]: Introduce...
58
59
60
  	char tbuf[256];
  
  	va_start(args, fmt);
1032a6687   Tina Ruchandani   Use 64-bit timeke...
61
  	getnstimeofday64(&now);
e41542f51   Ian McDonald   [DCCP]: Introduce...
62

1032a6687   Tina Ruchandani   Use 64-bit timeke...
63
  	now = timespec64_sub(now, dccpw.tstart);
e41542f51   Ian McDonald   [DCCP]: Introduce...
64
65
66
  
  	len = sprintf(tbuf, "%lu.%06lu ",
  		      (unsigned long) now.tv_sec,
cdd04d98f   YOSHIFUJI Hideaki   [DCCP]: Convert d...
67
  		      (unsigned long) now.tv_nsec / NSEC_PER_USEC);
e41542f51   Ian McDonald   [DCCP]: Introduce...
68
69
  	len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
  	va_end(args);
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
70
  	kfifo_in_locked(&dccpw.fifo, tbuf, len, &dccpw.lock);
e41542f51   Ian McDonald   [DCCP]: Introduce...
71
72
  	wake_up(&dccpw.wait);
  }
1b7841404   Ying Xue   net: Remove iocb ...
73
  static int jdccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
e41542f51   Ian McDonald   [DCCP]: Introduce...
74
  {
e41542f51   Ian McDonald   [DCCP]: Introduce...
75
  	const struct inet_sock *inet = inet_sk(sk);
996ccf490   Gerrit Renker   dccp ccid-3: Remo...
76
  	struct ccid3_hc_tx_sock *hc = NULL;
e41542f51   Ian McDonald   [DCCP]: Introduce...
77

71c262a3d   Gerrit Renker   dccp: API to quer...
78
  	if (ccid_get_current_tx_ccid(dccp_sk(sk)) == DCCPC_CCID3)
996ccf490   Gerrit Renker   dccp ccid-3: Remo...
79
  		hc = ccid3_hc_tx_sk(sk);
e41542f51   Ian McDonald   [DCCP]: Introduce...
80

c720c7e83   Eric Dumazet   inet: rename some...
81
82
  	if (port == 0 || ntohs(inet->inet_dport) == port ||
  	    ntohs(inet->inet_sport) == port) {
996ccf490   Gerrit Renker   dccp ccid-3: Remo...
83
  		if (hc)
388d5e990   Gerrit Renker   dccp ccid-3: Over...
84
85
  			printl("%pI4:%u %pI4:%u %d %d %d %d %u %llu %llu %d
  ",
c720c7e83   Eric Dumazet   inet: rename some...
86
87
  			       &inet->inet_saddr, ntohs(inet->inet_sport),
  			       &inet->inet_daddr, ntohs(inet->inet_dport), size,
996ccf490   Gerrit Renker   dccp ccid-3: Remo...
88
89
90
  			       hc->tx_s, hc->tx_rtt, hc->tx_p,
  			       hc->tx_x_calc, hc->tx_x_recv >> 6,
  			       hc->tx_x >> 6, hc->tx_t_ipi);
e41542f51   Ian McDonald   [DCCP]: Introduce...
91
  		else
21454aaad   Harvey Harrison   net: replace NIPQ...
92
93
  			printl("%pI4:%u %pI4:%u %d
  ",
c720c7e83   Eric Dumazet   inet: rename some...
94
95
96
  			       &inet->inet_saddr, ntohs(inet->inet_sport),
  			       &inet->inet_daddr, ntohs(inet->inet_dport),
  			       size);
e41542f51   Ian McDonald   [DCCP]: Introduce...
97
98
99
100
101
102
103
  	}
  
  	jprobe_return();
  	return 0;
  }
  
  static struct jprobe dccp_send_probe = {
e1b7441e8   Ian McDonald   [DCCP]: Make dccp...
104
105
106
  	.kp	= {
  		.symbol_name = "dccp_sendmsg",
  	},
9e367d859   Michael Ellerman   jprobes: remove J...
107
  	.entry	= jdccp_sendmsg,
e41542f51   Ian McDonald   [DCCP]: Introduce...
108
109
110
111
  };
  
  static int dccpprobe_open(struct inode *inode, struct file *file)
  {
454654878   Stefani Seibold   kfifo: move struc...
112
  	kfifo_reset(&dccpw.fifo);
1032a6687   Tina Ruchandani   Use 64-bit timeke...
113
  	getnstimeofday64(&dccpw.tstart);
e41542f51   Ian McDonald   [DCCP]: Introduce...
114
115
116
117
118
119
120
121
  	return 0;
  }
  
  static ssize_t dccpprobe_read(struct file *file, char __user *buf,
  			      size_t len, loff_t *ppos)
  {
  	int error = 0, cnt = 0;
  	unsigned char *tbuf;
75202e768   Bill Nottingham   [NET]: Fix compar...
122
  	if (!buf)
e41542f51   Ian McDonald   [DCCP]: Introduce...
123
124
125
126
127
128
129
130
131
132
  		return -EINVAL;
  
  	if (len == 0)
  		return 0;
  
  	tbuf = vmalloc(len);
  	if (!tbuf)
  		return -ENOMEM;
  
  	error = wait_event_interruptible(dccpw.wait,
e64c026dd   Stefani Seibold   kfifo: cleanup na...
133
  					 kfifo_len(&dccpw.fifo) != 0);
e41542f51   Ian McDonald   [DCCP]: Introduce...
134
135
  	if (error)
  		goto out_free;
7acd72eb8   Stefani Seibold   kfifo: rename kfi...
136
  	cnt = kfifo_out_locked(&dccpw.fifo, tbuf, len, &dccpw.lock);
653252c23   Pavel Emelyanov   net: Fix wrong in...
137
  	error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0;
e41542f51   Ian McDonald   [DCCP]: Introduce...
138
139
140
141
142
143
  
  out_free:
  	vfree(tbuf);
  
  	return error ? error : cnt;
  }
9a32144e9   Arjan van de Ven   [PATCH] mark stru...
144
  static const struct file_operations dccpprobe_fops = {
e41542f51   Ian McDonald   [DCCP]: Introduce...
145
146
147
  	.owner	 = THIS_MODULE,
  	.open	 = dccpprobe_open,
  	.read    = dccpprobe_read,
6038f373a   Arnd Bergmann   llseek: automatic...
148
  	.llseek  = noop_llseek,
e41542f51   Ian McDonald   [DCCP]: Introduce...
149
150
151
152
153
154
155
156
  };
  
  static __init int dccpprobe_init(void)
  {
  	int ret = -ENOMEM;
  
  	init_waitqueue_head(&dccpw.wait);
  	spin_lock_init(&dccpw.lock);
c1e13f256   Stefani Seibold   kfifo: move out s...
157
  	if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL))
454654878   Stefani Seibold   kfifo: move struc...
158
  		return ret;
d4beaa66a   Gao feng   net: proc: change...
159
  	if (!proc_create(procname, S_IRUSR, init_net.proc_net, &dccpprobe_fops))
e41542f51   Ian McDonald   [DCCP]: Introduce...
160
  		goto err0;
965cdea82   Wang Weidong   dccp: catch faile...
161
162
163
164
165
166
  	ret = register_jprobe(&dccp_send_probe);
  	if (ret) {
  		ret = request_module("dccp");
  		if (!ret)
  			ret = register_jprobe(&dccp_send_probe);
  	}
e41542f51   Ian McDonald   [DCCP]: Introduce...
167
168
169
170
171
172
173
  	if (ret)
  		goto err1;
  
  	pr_info("DCCP watch registered (port=%d)
  ", port);
  	return 0;
  err1:
ece31ffd5   Gao feng   net: proc: change...
174
  	remove_proc_entry(procname, init_net.proc_net);
e41542f51   Ian McDonald   [DCCP]: Introduce...
175
  err0:
454654878   Stefani Seibold   kfifo: move struc...
176
  	kfifo_free(&dccpw.fifo);
e41542f51   Ian McDonald   [DCCP]: Introduce...
177
178
179
180
181
182
  	return ret;
  }
  module_init(dccpprobe_init);
  
  static __exit void dccpprobe_exit(void)
  {
454654878   Stefani Seibold   kfifo: move struc...
183
  	kfifo_free(&dccpw.fifo);
ece31ffd5   Gao feng   net: proc: change...
184
  	remove_proc_entry(procname, init_net.proc_net);
e41542f51   Ian McDonald   [DCCP]: Introduce...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
  	unregister_jprobe(&dccp_send_probe);
  
  }
  module_exit(dccpprobe_exit);
  
  MODULE_PARM_DESC(port, "Port to match (0=all)");
  module_param(port, int, 0);
  
  MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
  module_param(bufsize, int, 0);
  
  MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>");
  MODULE_DESCRIPTION("DCCP snooper");
  MODULE_LICENSE("GPL");