编写内核模块是一个复杂的任务,需要对Linux内核和网络协议栈有深入的了解。下面提供的是一个简化的内核模块示例代码,它实现了上述要求的基本功能。请注意,这只是一个示例,实际开发中可能需要更多的错误处理和优化。
### 内核模块代码示例
```c
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <net/icmp.h>
#define ICMP_DATA_SIZE_MIN 100
#define ICMP_DATA_SIZE_MAX 1000
static unsigned int n = 100; // 默认值
static struct proc_dir_entry *proc_entry;
static int count = 0;
static char last_ip[INET_ADDRSTRLEN];
struct ping_packet_info {
u32 packets_count;
unsigned long last_time;
char source_ip[INET_ADDRSTRLEN];
};
static struct ping_packet_info ping_info;
static int check_ping_packet(const struct sk_buff *skb)
{
if (skb->len < n) {
return 0;
}
struct icmphdr *icmph = icmp_hdr(skb);
if (icmph->type == ICMP_ECHO) {
struct in_addr saddr;
memcpy(&saddr, &skb->nh.iph->saddr, sizeof(saddr));
ping_info.packets_count++;
ping_info.last_time = jiffies;
strncpy(ping_info.source_ip, inet_ntoa(saddr), INET_ADDRSTRLEN);
}
return 0;
}
static unsigned int ping_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *))
{
if (skb->protocol == htons(ETH_P_IP) && hook == NF_INET_PRE_ROUTING) {
check_ping_packet(skb);
}
return NF_ACCEPT;
}
static struct nf_hook_ops ping_ops = {
.hook = ping_hook,
.hooknum = NF_INET_PRE_ROUTING,
.pf = PF_INET,
.priority = NF_IP_PRI_FIRST,
};
static int __init ping_module_init(void)
{
proc_entry = proc_create("ping_stats", 0, NULL, &proc_ops);
if (proc_entry == NULL) {
return -ENOMEM;
}
register_netfilter_hook(&ping_ops);
printk(KERN_INFO "Ping packet counter module loaded\n");
return 0;
}
static void __exit ping_module_exit(void)
{
unregister_netfilter_hook(&ping_ops);
remove_proc_entry("ping_stats", NULL);
printk(KERN_INFO "Ping packet counter module unloaded\n");
}
module_param(n, uint, 0644);
MODULE_PARM_DESC(n, "Size of ICMP data in bytes to be counted (100-1000)");
module_init(ping_module_init);
module_exit(ping_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple ICMP ping packet counter module");
```
### 测试用例
1. **加载模块**: 使用 `insmod` 命令加载内核模块。
```bash
sudo insmod ping_module.ko
```
2. **设置模块参数**: 在加载模块之前,可以通过 `echo` 命令设置模块参数。
```bash
echo 500 > /sys/module/ping_module/parameters/n
```
3. **发送 ICMP ECHO 请求**: 使用 `ping` 命令发送ICMP ECHO请求。
```bash
ping -c 10 127.0.0.1
```
4. **查看统计信息**: 通过 `/proc` 文件系统查看统计信息。
```bash
cat /proc/ping_stats
```
请注意,这个示例代码可能需要根据你的具体需求进行调整和完善。在实际部署之前,应该进行充分的测试和验证。