Linux systetmtap使用

1、安装kernel debug包,(kernel-debuginfo、 kernel-debuginfo-common、kernel-devel    http://debuginfo.centos.org/7/x86_64/)
2、安装systemtap yum install systemtap
3、检查systemtap是否安装成功
   stap -ve 'probe kernel.function("do_fork") { print("hello world\n") exit() }'   
4、执行脚本
   stap -vg xx.stp

 

常用:
1、print_backtrace 打印调用栈
2、$var 打印变量var
3、$$params 打印所有入参
4、打印返回值  $$return

内部变量名    功能    其他
$$locals    探测点上所有的本地变量(含参数)    n/a
$$params    探测点上函数的参数    n/a
$$returns    探测点上所有的返回值    只对return probe生效

systemtap自定义stap:
/usr/share/systemtap/tapset/

例子一:

@__private30 function __mac_addr_to_string:string(addr:long) {
        return sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
                kernel_char(addr)&255, kernel_char(addr+1)&255,
                kernel_char(addr+2)&255, kernel_char(addr+3)&255,
                kernel_char(addr+4)&255, kernel_char(addr+5)&255)
}

probe module("i40e").function("i40e_cleanup_headers") {        
       dst_mac = __mac_addr_to_string(@cast($skb->data, "ethhdr", "kernel<include/linux/if_ether.h>")->h_dest)
       src_mac = __mac_addr_to_string(@cast($skb->data, "ethhdr", "kernel<include/linux/if_ether.h>")->h_source)
       if (dst_mac == "fa:16:3e:6a:1b:10")
               printf("i40e_cleanup_headers dst_mac: %s, src_mac: %s\n", dst_mac, src_mac)
}



probe kernel.function("validate_xmit_skb") {
	family = @const("AF_INET")
	try {
		iphdr = __get_skb_iphdr($skb)
		saddr = format_ipaddr(__ip_skb_saddr(iphdr), @const("AF_INET"))
		daddr = format_ipaddr(__ip_skb_daddr(iphdr), @const("AF_INET"))
		protocol = __ip_skb_proto(iphdr)
	} catch { }

        try {
	        tcphdr = __get_skb_tcphdr($skb)
	        dport = __tcp_skb_dport(tcphdr)
	        sport = __tcp_skb_sport(tcphdr)
	        urg = __tcp_skb_urg(tcphdr)
	        ack = __tcp_skb_ack(tcphdr)
	        psh = __tcp_skb_psh(tcphdr)
	        rst = __tcp_skb_rst(tcphdr)
	        syn = __tcp_skb_syn(tcphdr)
	        fin = __tcp_skb_fin(tcphdr)
		check = __tcp_skb_check(tcphdr)
	} catch { }


	if (saddr == "172.20.30.35") {
		printf("---  validate_xmit_skb saddr:%s, daddr:%s, gso_size: %d, ip_summed: %d, check: %ld \n", saddr, daddr, @cast($skb->head + $skb->end, "skb_shared_info", "kernel<include/linux/skbuff.h>")->gso_size, $skb->ip_summed, check)
	}



probe kernel.function("skb_csum_hwoffload_help") {
	family = @const("AF_INET")
	try {
		iphdr = __get_skb_iphdr($skb)
		saddr = format_ipaddr(__ip_skb_saddr(iphdr), @const("AF_INET"))
		daddr = format_ipaddr(__ip_skb_daddr(iphdr), @const("AF_INET"))
		protocol = __ip_skb_proto(iphdr)
	} catch { }
	if (saddr == "172.20.30.35")
		printf("---- skb_csum_hwoffload_help saddr:%s, daddr:%s ,csum_not_inet %d \n", saddr, daddr, $skb->csum_not_inet)
}

例子二:

利用systemtap简单实现数据包的snat;

安装以下脚本,然后通过ping -I 172.20.21.3 175.43.23.53验证连通性。

#!/usr/bin/stap -g

%{
#include <linux/tcp.h>
#include <linux/ip.h>
%}


function replace_out_src_ip(skb:long)
%{
	struct sk_buff *tmp_skb =  (struct sk_buff *)STAP_ARG_skb;
	struct iphdr *iph = ip_hdr(tmp_skb);
	__be32 old_saddr = iph->saddr;
    //源ip是内网ip:0x031514ac(172.20.21.3), 则将源ip替换成公网ip:0x34172baf(175.43.23.52)
	if (iph->saddr == 0x031514ac) {
		iph->saddr = 0x34172baf;
		inet_proto_csum_replace4(&iph->check, tmp_skb, old_saddr, iph->saddr, true);
	}
%}

function replace_rcv_src_ip(skb:long)
%{
	struct sk_buff *tmp_skb =  (struct sk_buff *)STAP_ARG_skb;
	struct iphdr *iph = ip_hdr(tmp_skb);
	__be32 old_daddr = iph->daddr;
    //源ip是0x35172baf(175.43.23.53),则将目的ip重新修改成内网地址0x031514ac(172.20.21.3)
	if (iph->saddr == 0x35172baf) {
		iph->daddr = 0x031514ac;
		inet_proto_csum_replace4(&iph->check, tmp_skb, old_daddr, iph->daddr, false);
		printk("ip rcv ip_src: %d, ip_dst: %d, type: %d, ip_summed: %d\n", iph->saddr, iph->daddr, tmp_skb->pkt_type, tmp_skb->ip_summed);
	}
%}

function probe_ip_rcv_finish(skb:long)
%{
	struct sk_buff *tmp_skb =  (struct sk_buff *)STAP_ARG_skb;
	struct iphdr *iph = ip_hdr(tmp_skb);
	if (iph->saddr == 0x35172baf) {
		printk("ip_rcv_finish ip_src: %d, ip_dst: %d \n", iph->saddr, iph->daddr);
	}
%}

probe kernel.function("ip_output") {
	replace_out_src_ip($skb)	
}

probe kernel.function("ip_rcv") {
	replace_rcv_src_ip($skb)	
}

probe kernel.function("ip_rcv_finish") {
	probe_ip_rcv_finish($skb)	
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值