linux内核驱动程序读取ICMP数据

本文介绍了一种在Linux内核中编写驱动程序的方法,该程序能够捕获并解析ICMP协议数据包,实现对数据包内容的打印。通过详细展示驱动代码及编译、挂载步骤,帮助读者理解如何在内核层面处理网络数据。

目的:编写linux kernel驱动程序,在挂载点上读取icmp协议数据,打印icmp数据包内容。

 

//icmp头部结构
struct icmphdr {
  __u8          type;    //8位类型
  __u8          code;    //8位代码
  __sum16       checksum;    //16位校验和
  union {
        struct {
                __be16  id;    //16位id
                __be16  sequence;    //16位序号
        } echo;
        __be32  gateway;
        struct {
                __be16  __unused;
                __be16  mtu;
        } frag;
  } un;
};
//驱动代码
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/icmp.h>

static struct nf_hook_ops nfho;

static unsigned int ptcp_hook_func(const struct nf_hook_ops *ops,
                                   struct sk_buff *skb,
                                   const struct net_device *in,
                                   const struct net_device *out,
                                   int (*okfn)(struct sk_buff *))
{
    struct iphdr *iph;          /* IPv4 header */
    struct icmphdr *icmph;      /*icmp header*/
    //struct tcphdr *tcph;        /* TCP header */
    //u16 sport, dport;           /* Source and destination ports */
    //u32 saddr, daddr;           /* Source and destination addresses */
    unsigned char *user_data;   /* TCP data begin pointer */
    unsigned char *tail;        /* TCP data end pointer */
    unsigned char *it;          /* TCP data iterator */
    int length;

    /* Network packet is empty, seems like some problem occurred. Skip it */
    if (!skb)
        return NF_ACCEPT;

    iph = ip_hdr(skb);          /* get IP header */

    /* Skip if it's not ICMP packet */
    if (iph->protocol != IPPROTO_ICMP)
        return NF_ACCEPT;
        
    //tcph = tcp_hdr(skb);        /* get TCP header */
    icmph = icmp_hdr(skb);

    length = sizeof(struct icmphdr);
    printk("length:%d\n", length);

    /* Calculate pointers for begin and end of TCP packet data */
    //user_data = (unsigned char *)((unsigned char *)tcph + (tcph->doff * 4));
    user_data = (unsigned char *)((unsigned char *)icmph + length);
    tail = skb_tail_pointer(skb);

    /* Print ICMP packet data (payload) */
    printk("print_tcp: data:\n");
    for (it = user_data; it != tail; ++it) {
        char c = *(char *)it;

        if (c == '\0')
            break;

        printk("%c", c);
    }
    printk("\n\n");

    return NF_ACCEPT;
}
static int __init ptcp_init(void)
{
    int res;

    nfho.hook = (nf_hookfn *)ptcp_hook_func;    /* hook function */
    nfho.hooknum = NF_INET_PRE_ROUTING;         /* received packets */
    nfho.pf = PF_INET;                          /* IPv4 */
    nfho.priority = NF_IP_PRI_FIRST;            /* max hook priority */

    res = nf_register_hook(&nfho);
    if (res < 0) {
        pr_err("print_tcp: error in nf_register_hook()\n");
        return res;
    }

    pr_debug("print_tcp: loaded\n");
    return 0;
}

static void __exit ptcp_exit(void)
{
    nf_unregister_hook(&nfho);
    pr_debug("print_tcp: unloaded\n");
}
module_init(ptcp_init);
module_exit(ptcp_exit);
MODULE_LICENSE("GPL");
//Makefile
ifneq ($(KERNELRELEASE),)
obj-m:=print_tcp.o
else
PWD:=$(shell pwd)
KDIR:=/usr/lib/modules/$(shell uname -r)/build
all:
        $(MAKE) -C $(KDIR) M=$(PWD)
clean:
        rm -rf *.o *.mod.c *.ko *.symvers *.order *.markers
endif

 

1、编译:

 

生成print_tcp.ko驱动文件。

2、挂载驱动

insmod print_tcp.ko

 3、测试

 图中标红的打印出来的就是ICMP协议传输的数据。

 抓包也可以看到,数据部分也是这些数据。

 

4、卸载驱动

rmmod print_tcp

5、完。

 

参考:

https://codeday.me/bug/20190325/825084.html

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值