ICMP 套接字(Linux)
- 2024-11-11 08:27:00
- admin 原创
- 30
问题描述:
是否可以在 IP 协议下使用 ICMP 套接字?也许是这样的:
socket(PF_INET, <type>, IPPROTO_ICMP)?
我应该在字段中输入什么<type>
?我看到了一些使用的示例SOCK_RAW
,但这不会妨碍操作系统处理 IP 协议吗?
还有一件事。由于协议不涉及任何端口,操作系统如何知道应该将 ICMP 数据报发送给哪个进程?
解决方案 1:
Linux 有一个特殊的 ICMP 套接字类型,您可以使用它:
socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP);
这允许您仅发送 ICMP 回显请求内核将对其进行特殊处理(匹配请求/响应,填写校验和)。
这仅在设置了特殊 sysctl时才有效。默认情况下,即使是 root 也不能使用这种套接字。您可以指定可以访问它的用户组。要允许 root(组 0)使用 ICMP 套接字,请执行以下操作:
sysctl -w net.ipv4.ping_group_range="0 0"
下面是一个示例程序,演示了发送 ICMP 回显请求的基本用法:
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <sys/select.h>
//note, to allow root to use icmp sockets, run:
//sysctl -w net.ipv4.ping_group_range="0 0"
void ping_it(struct in_addr *dst)
{
struct icmphdr icmp_hdr;
struct sockaddr_in addr;
int sequence = 0;
int sock = socket(AF_INET,SOCK_DGRAM,IPPROTO_ICMP);
if (sock < 0) {
perror("socket");
return ;
}
memset(&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_addr = *dst;
memset(&icmp_hdr, 0, sizeof icmp_hdr);
icmp_hdr.type = ICMP_ECHO;
icmp_hdr.un.echo.id = 1234;//arbitrary id
for (;;) {
unsigned char data[2048];
int rc;
struct timeval timeout = {3, 0}; //wait max 3 seconds for a reply
fd_set read_set;
socklen_t slen;
struct icmphdr rcv_hdr;
icmp_hdr.un.echo.sequence = sequence++;
memcpy(data, &icmp_hdr, sizeof icmp_hdr);
memcpy(data + sizeof icmp_hdr, "hello", 5); //icmp payload
rc = sendto(sock, data, sizeof icmp_hdr + 5,
0, (struct sockaddr*)&addr, sizeof addr);
if (rc <= 0) {
perror("Sendto");
break;
}
puts("Sent ICMP
");
memset(&read_set, 0, sizeof read_set);
FD_SET(sock, &read_set);
//wait for a reply with a timeout
rc = select(sock + 1, &read_set, NULL, NULL, &timeout);
if (rc == 0) {
puts("Got no reply
");
continue;
} else if (rc < 0) {
perror("Select");
break;
}
//we don't care about the sender address in this example..
slen = 0;
rc = recvfrom(sock, data, sizeof data, 0, NULL, &slen);
if (rc <= 0) {
perror("recvfrom");
break;
} else if (rc < sizeof rcv_hdr) {
printf("Error, got short ICMP packet, %d bytes
", rc);
break;
}
memcpy(&rcv_hdr, data, sizeof rcv_hdr);
if (rcv_hdr.type == ICMP_ECHOREPLY) {
printf("ICMP Reply, id=0x%x, sequence = 0x%x
",
icmp_hdr.un.echo.id, icmp_hdr.un.echo.sequence);
} else {
printf("Got ICMP packet with type 0x%x ?!?
", rcv_hdr.type);
}
}
}
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("usage: %s destination_ip
", argv[0]);
return 1;
}
struct in_addr dst;
if (inet_aton(argv[1], &dst) == 0) {
perror("inet_aton");
printf("%s isn't a valid IP address
", argv[1]);
return 1;
}
ping_it(&dst);
return 0;
}
请注意,如果发送的数据没有足够的空间容纳正确的 ICMP 标头,则内核将拒绝并导致 sendto() 调用失败,并且 ICMPtype
必须为 8(ICMP_ECHO)且 ICMP 代码必须为 0。
解决方案 2:
是的,这是可能的,因为该ping
命令执行 ICMP。
要找出所涉及的系统调用,您可以使用strace
该命令(在 root 下)。
您还可以查看该命令的源代码,例如Debian 的 ping
还有liboping库可以帮助您......
相关推荐
热门文章
项目管理软件有哪些?
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
热门标签
云禅道AD