ping命令的发送过程,是从用户态到网卡。接收过程,是从网卡到用户态。下面以ip发送函数ip_output和ip接收函数ip_rcv为例来跟踪特定的ping数据包。执行命令的环境为虚拟机,ip地址为192.168.122.33,目标机器为宿主机,ip地址为10.63.8.161。
global TARGET_IP = "10.63.8.161"
%{
#include <linux/ip.h>
#include <linux/skbuff.h>
#include <linux/inet.h>
%}
# --------- Helper Functions ---------#
#将IP字符串转换为整数
function ip_to_int(ip_str) %{
struct in_addr addr;
int ret = in4_pton(STAP_ARG_ip_str, -1, (u8*)&addr, '\0', NULL);
if (ret >0) {
STAP_RETURN(ntohl(addr.s_addr));
} else {
STAP_RETURN(0);
}
%}
#获取IP协议、源地址、目标地址(返回多个值)
function get_ip_protocol:long(skb) %{
struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
struct iphdr *iph = ip_hdr(skb);
STAP_RETURN(iph->protocol);
%}
function get_saddr:long(skb) %{
struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
struct iphdr *iph = ip_hdr(skb);
STAP_RETURN(ntohl(iph->saddr));
%}
function get_daddr:long(skb) %{
struct sk_buff *skb = (struct sk_buff *)STAP_ARG_skb;
struct iphdr *iph = ip_hdr(skb);
STAP_RETURN(ntohl(iph->daddr));
%}
# --------- Probe Handlers ---------#
probe kernel.function("ip_rcv") {
skb = $skb
protocol = get_ip_protocol(skb)
saddr = get_saddr(skb)
daddr = get_daddr(skb)
target = ip_to_int(TARGET_IP)
if (protocol ==1 && (saddr == target || daddr == target)) {
printf("[RCV %05d] %s ICMP %s -> %s\n", pid(), ctime(gettimeofday_s()),
ip_ntop(htonl(saddr)), ip_ntop(htonl(daddr)))
}
}
probe kernel.function("ip_output") {
skb = $skb
protocol = get_ip_protocol(skb)
saddr = get_saddr(skb)
daddr = get_daddr(skb)
target = ip_to_int(TARGET_IP)
if (protocol ==1 && (saddr == target || daddr == target)) {
printf("[SND %05d] %s ICMP %s -> %s\n",
pid(), ctime(gettimeofday_s()),
ip_ntop(htonl(saddr)), ip_ntop(htonl(daddr)))
}
}
probe begin {
println("[+] Tracing ICMP to/from: ", TARGET_IP)
}
脚本执行结果
[root@localhost ~]# stap -g ping_trace/ping_ip_filter_v6.stp
[+] Tracing ICMP to/from: 10.63.8.161
[SND 14453] Wed Feb 12 10:58:42 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:42 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:43 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:43 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:44 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:44 2025 ICMP 10.63.8.161 -> 192.168.122.33
[SND 14453] Wed Feb 12 10:58:45 2025 ICMP 192.168.122.33 -> 10.63.8.161
[RCV 00000] Wed Feb 12 10:58:45 2025 ICMP 10.63.8.161 -> 192.168.122.33