使用套接字实现ICMP协议

//ip协议 结构头部定义


#pragma once
#include "stdafx.h"
#ifdef  USING_IP_HEADER
typedef struct   _ipheader
	{  
#if LITTLE_ENDIAN  
	unsigned char ihl:4;     //首部长度  
	unsigned char version:4; //版本   
#else  
	unsigned char version:4 ;//版本  
	unsigned char ihl:4 ;    //首部长度  
#endif  
	unsigned char tos;       //服务类型  
	unsigned short tot_len;  //总长度  
	unsigned short id;       //标志  
	unsigned short frag_off; //分片偏移  
	unsigned char ttl;       //生存时间  
	unsigned char protocol;  //协议  
	unsigned short chk_sum;  //检验和  
//	struct in_addr src_addr;  //源IP地址   /*unsigned int srcaddr;/*减少导入库,需要在引用的地方 转换为in_addr*/	  
	//struct in_addr dest_addr;  //目的IP地址   /*unsigned int destaddr;/*减少导入库,需要在引用的地方 转换为in_addr*/
    unsigned long src_addr;
    unsigned long dest_addr;
}IP_HEADER,*PIP_HEADER;
#endif //USING_IP_HEADER
#ifdef USING_IP_ICMP_HEADER
//ICMP 结构头
typedef struct _icmp_header{
	/*类型*/
	unsigned char icmp_type;
	/*代码*/
	unsigned char icmp_code;
	/*校检和*/
	unsigned short icmp_checksum;
	/*标识符,一般以进程号作为标识*/
	unsigned short icmp_id;
	/*序列号*/
	unsigned short icmp_seq;
    /*时间戳*/
	unsigned long  icmp_timestamp;
	}ICMP_HEADER,*PICMP_HEADER;

//ICMP 协议函数定义 头文件

 //解析ICMP协议包数据
  BOOL __stdcall Nw_ParseIcmp4PacketData(
	  /*ICMP协议数据包*/
	  __in void* pIcmpData,
	  /*pIcmpData的长度,长度必须匹配pIcmpData,否则导致内存访问越界*/
	  __in size_t IcmpDataLen,
	  /*ip结构*/
	  /*
#ifdef USING_IP_HEADER
	  __out_opt IP_HEADER* pIpHdr,
#else*/
	  __out_opt void** ppIpHdr,
//#endif
	  /*icmp结构*/
/*#ifdef USING_IP_ICMP_HEADER
	  __out_opt ICMP_HEADER* pIcmpH
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux系统中,可以使用原始套接字实现ICMP协议的收发。以下是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <arpa/inet.h> #define PACKET_SIZE 4096 #define ICMP_PACKET_SIZE 64 unsigned short checksum(unsigned short *buf, int len) { unsigned long sum = 0; while (len > 1) { sum += *buf++; len -= 2; } if (len == 1) { sum += *(unsigned char *)buf; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return ~sum; } int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s <destination_ip>\n", argv[0]); exit(1); } char buf[PACKET_SIZE]; memset(buf, 0, sizeof(buf)); int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock < 0) { perror("socket"); exit(1); } struct sockaddr_in dest_addr; memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = inet_addr(argv[1]); struct icmp *icmp_packet = (struct icmp *)buf; icmp_packet->icmp_type = ICMP_ECHO; icmp_packet->icmp_code = 0; icmp_packet->icmp_id = getpid() & 0xffff; icmp_packet->icmp_seq = 0; memset(icmp_packet->icmp_data, 0, ICMP_PACKET_SIZE); icmp_packet->icmp_cksum = checksum((unsigned short *)icmp_packet, ICMP_PACKET_SIZE); int sent_bytes = sendto(sock, buf, sizeof(struct icmp), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); if (sent_bytes < 0) { perror("sendto"); exit(1); } printf("Sent %d bytes to %s\n", sent_bytes, argv[1]); int recv_bytes = recv(sock, buf, PACKET_SIZE, 0); if (recv_bytes < 0) { perror("recv"); exit(1); } struct iphdr *ip_packet = (struct iphdr *)buf; struct icmp *icmp_reply = (struct icmp *)(buf + (ip_packet->ihl << 2)); printf("Received ICMP reply from %s\n", inet_ntoa(dest_addr.sin_addr)); printf("ICMP type: %d, ICMP code: %d\n", icmp_reply->icmp_type, icmp_reply->icmp_code); close(sock); return 0; } ``` 该程序中,首先创建一个原始套接字,然后构造一个ICMP报文,发送到目标IP地址。接着等待接收ICMP回复报文,并解析其中的类型和代码。最后关闭套接字。需要注意的是,使用原始套接字需要root权限。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值