ICMP->linux c PING功能实现

本文详细介绍了如何在Linux环境下使用C语言编程实现ICMP协议的PING功能,内容涵盖ICMP报文格式及代码实现关键部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

报文格式:

\

代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip_icmp.h> //struct icmp
#include <netinet/in.h> //sockaddr_in
#include <netinet/ip.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>

//校验和计算
unsigned short calc_cksum(char *buff,int len)
{
    int blen = len;
    unsigned short *mid = (unsigned short*)buff;
    unsigned short te = 0;
    unsigned int sum = 0;

    while(blen > 1)
    {
       sum += *mid++;
       blen -= 2; 
    }
    //数据长度为奇数比如65 上面的while是按16计算的 最后就会剩下一字节不能计算 	
    if(blen == 1)
    {  
       //将多出的一字节放入short类型的高位 低8位置0 加入到sum中
       te = *(uns
#include <linux/module.h> #include <linux/kernel.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/ip.h> #include <linux/icmp.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/version.h> #include <linux/time.h> #include <linux/time64.h> #define MAX_ENTRIES 1000 static unsigned int n = 100; module_param(n, uint, 0); MODULE_PARM_DESC(n, "ICMP data size (100-1000 bytes)"); struct ping_stat_entry { struct timespec64 timestamp; __be32 src_ip; struct list_head list; }; static LIST_HEAD(ping_stat_list); static DEFINE_SPINLOCK(stat_lock); static unsigned int entry_count = 0; // 修改后的钩子函数 static unsigned int ping_stat_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { // 所有声明放在函数开头 struct iphdr *ip_header; struct icmphdr *icmp_header; unsigned int data_len; struct ping_stat_entry *entry = NULL; // 声明指针但不初始化 // 检查是否为IPv4包 if (!skb || skb->protocol != htons(ETH_P_IP)) return NF_ACCEPT; ip_header = ip_hdr(skb); // 检查是否为ICMP包 if (ip_header->protocol != IPPROTO_ICMP) return NF_ACCEPT; // 检查ICMP头是否完整 if (skb->len < ip_header->ihl * 4 + sizeof(struct icmphdr)) return NF_ACCEPT; icmp_header = (struct icmphdr *)(skb->data + ip_header->ihl * 4); // 检查是否为ECHO请求 if (icmp_header->type != ICMP_ECHO) return NF_ACCEPT; // 计算数据部分长度 data_len = skb->len - ip_header->ihl * 4 - sizeof(struct icmphdr); // 检查数据长度 if (data_len != n) return NF_ACCEPT; // 现在创建新条目 - 使用正确的sizeof entry = kmalloc(sizeof(*entry), GFP_ATOMIC); // 注意:sizeof(*entry)不是sizeof(entry) if (!entry) return NF_ACCEPT; // 记录时间和源IP ktime_get_real_ts64(&entry->timestamp); entry->src_ip = ip_header->saddr; INIT_LIST_HEAD(&entry->list); // 加锁保护链表 spin_lock(&stat_lock); // 添加到链表头部 list_add(&entry->list, &ping_stat_list); entry_count++; // 移除旧条目(如果超过最大限制) if (entry_count > MAX_ENTRIES) { struct ping_stat_entry *old_entry = list_last_entry(&ping_stat_list, struct ping_stat_entry, list); list_del(&old_entry->list); kfree(old_entry); entry_count--; } spin_unlock(&stat_lock); return NF_ACCEPT; } // 其余代码保持不变...
最新发布
08-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值