Linux c原始套接字实现icmp
时间: 2023-07-15 10:15:59 浏览: 61
在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权限。