/*
* Here's a sample kernel module showing the use of jprobes to dump
* the arguments of do_fork().
*
* For more information on theory of operation of jprobes, see
* Documentation/kprobes.txt
*
* Build and insert the kernel module as done in the kprobe example.
* You will see the trace data in /var/log/messages and on the
* console whenever do_fork() is invoked to create a new process.
* (Some messages may be suppressed if syslogd is configured to
* eliminate duplicate messages.)
*/
#include <linux/kprobes.h>
#include <linux/tcp.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/kernel.h>
#include <net/dst.h>
#include <net/tcp.h>
#include <net/inet_common.h>
#include <linux/ipsec.h>
#include <asm/unaligned.h>
#include <net/netdma.h>
#include <linux/skbtrace.h>
#include <linux/skbuff.h>
int all_enable1 = 0;
module_param(all_enable1, int, 0644);
int all_enable2 = 0;
module_param(all_enable2, int, 0644);
void jtcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
u32 saddr, daddr, seq, end_seq;
unsigned short source, dest;
struct inet_sock *inet = inet_sk(sk);
if (sk == NULL || skb == NULL)
goto drop;
saddr = inet->inet_saddr;
daddr = inet->inet_daddr;
source = ntohs(inet->inet_sport);
dest = ntohs(inet->inet_dport);
seq = TCP_SKB_CB(skb)->seq;
end_seq = TCP_SKB_CB(skb)->end_seq;
if (all_enable1 && (source == 80 || dest == 80))
printk("%s %s %pI4 %u -> %pI4 %u seq %u-%u lost %u sck %u paout %u\n",
__func__, end_seq < tp->snd_nxt ? "R":"N", &saddr, source, &daddr, dest, seq, end_seq,
tp->lost_out, tp->sacked_out, tp->packets_out);
if (end_seq < tp->snd_nxt && all_enable2 && (source == 80 || dest == 80)) {
printk("%s %s %pI4 %u -> %pI4 %u seq %u-%u lost %u sck %u paout %u\n",
__func__, end_seq < tp->snd_nxt ? "R":"N", &saddr, source, &daddr, dest, seq, end_seq,
tp->lost_out, tp->sacked_out, tp->packets_out);
dump_stack();
}
drop:
jprobe_return();
return ;
}
int jtcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
{
struct tcp_sock *tp = tcp_sk(sk);
u32 saddr, daddr, seq, end_seq, ack_seq;
unsigned short source, dest;
struct inet_sock *inet = inet_sk(sk);
int i = 0;
int len = 0;
char pf_buffer[1024] = {0};
const unsigned char *ptr = NULL;
struct tcp_sack_block_wire *sp_wire = NULL;
struct tcp_sack_block sp[TCP_NUM_SACKS] ={{0,0},{0,0},{0,0},{0,0}};
int num_sacks;
if (sk == NULL || skb == NULL)
goto drop;
saddr = inet->inet_saddr;
daddr = inet->inet_daddr;
source = ntohs(inet->inet_sport);
dest = ntohs(inet->inet_dport);
seq = TCP_SKB_CB(skb)->seq;
end_seq = TCP_SKB_CB(skb)->end_seq;
ack_seq = TCP_SKB_CB(skb)->ack_seq;
ptr = (skb_transport_header(skb) + TCP_SKB_CB(skb)->sacked);
sp_wire = (struct tcp_sack_block_wire *)(ptr+2);
num_sacks = min(TCP_NUM_SACKS, (ptr[1] - TCPOLEN_SACK_BASE) >> 3);
if (TCP_SKB_CB(skb)->sacked) {
for (i = 0; i < num_sacks; i++) {
sp[i].start_seq = get_unaligned_be32(&sp_wire[i].start_seq);
sp[i].end_seq = get_unaligned_be32(&sp_wire[i].end_seq);
if (len >= sizeof(pf_buffer) )
break;
sprintf(pf_buffer + len, "%u-%u,", sp[i].start_seq, sp[i].end_seq);
len += strlen(pf_buffer);
}
}
if (all_enable1 && (source == 80 || dest == 80))
printk("%s %pI4 %u -> %pI4 %u %u seq %u lost %u sck %u paout %u sack %s\n",
__func__, &saddr, source, &daddr, dest, ack_seq, seq,
tp->lost_out, tp->sacked_out, tp->packets_out, i ? pf_buffer : "");
drop:
jprobe_return();
return 0;
}
void jtcp_enter_loss(struct sock *sk, int how)
{
printk("%s\n", __func__);
jprobe_return();
return;
}
static struct jprobe my_jprobe3 = {
.entry = jtcp_enter_loss,
.kp = {
.symbol_name = "tcp_enter_loss",
},
};
static struct jprobe my_jprobe1 = {
.entry = jtcp_v4_send_check,
.kp = {
.symbol_name = "tcp_v4_send_check",
},
};
static struct jprobe my_jprobe2 = {
.entry = jtcp_ack,
.kp = {
.symbol_name = "tcp_ack",
},
};
struct jprobe *my_jprobes[3] = {NULL, NULL, NULL};
static int __init jprobe_init(void)
{
int ret;
my_jprobes[0] = &my_jprobe1;
my_jprobes[1] = &my_jprobe2;
my_jprobes[2] = &my_jprobe3;
ret = register_jprobes(my_jprobes, 3);
if (ret < 0) {
printk(KERN_INFO "1 register_jprobe failed, returned %d\n", ret);
return -1;
}
printk(KERN_INFO "Planted jprobe at %p, handler addr %p\n",
my_jprobe1.kp.addr, my_jprobe1.entry);
return 0;
}
static void __exit jprobe_exit(void)
{
unregister_jprobes(my_jprobes, 3);
printk(KERN_INFO "jprobe at %p unregistered\n", my_jprobe1.kp.addr);
}
module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");
tcp jprobe 利用问题定位
最新推荐文章于 2022-03-06 18:42:24 发布