问题描述
我正在使用BSD套接字来构建不需要root特权(例如tracepath)的高级traceroute程序.使用UDP和绑定套接字,我调用:
I'm using BSD sockets to build an advanced traceroute program that doesn't need root privileges (like tracepath). Using UDP and a bound socket, I call:
recvmsg(socket, header, MSG_ERRQUEUE)
我收到有关先前发送的数据包已触发的假定ICMP通知的信息.您是否知道是否可以访问ICMP有效负载(应该是先前发送的数据包)?
I receive info about the supposed ICMP notification that a previously sent packet has triggered. Do you know if it's possible to access the ICMP payload (which should be the previously-sent packet)?
我从recvmsg手册页中阅读:
I read from recvmsg man page:
[..] The payload of the original packet that caused the error
is passed as normal data via msg_iovec. [..]
但是我在那里找不到任何有用的东西,似乎只是随机数据(我使用wireshark来交叉检查数据).
But I can't find anything useful there, it just seems random data (I used wireshark to cross-check data).
推荐答案
您可以使用此示例代码来检查您遇到的ICMP错误并进行处理(该示例包含一些注释和链接):
You can use this sample code to check which ICMP Error you got and handle it (The sample contain some comments and links):
#define BUFFER_MAX_SIZE 1024
int on = 1;
/* Set the option, so we can receive errors */
setsockopt(socket, SOL_IP, IP_RECVERR,(char*)&on, sizeof(on));
/* Other code here */
/* .... */
/* Handle receving ICMP Errors */
int return_status;
char buffer[BUFFER_MAX_SIZE];
struct iovec iov; /* Data array */
struct msghdr msg; /* Message header */
struct cmsghdr *cmsg; /* Control related data */
struct sock_extended_err *sock_err; /* Struct describing the error */
struct icmphdr icmph; /* ICMP header */
struct sockaddr_in remote; /* Our socket */
for (;;)
{
iov.iov_base = &icmph;
iov.iov_len = sizeof(icmph);
msg.msg_name = (void*)&remote;
msg.msg_namelen = sizeof(remote);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
msg.msg_control = buffer;
msg.msg_controllen = sizeof(buffer);
/* Receiving errors flog is set */
return_status = recvmsg(socket, &msg, MSG_ERRQUEUE);
if (return_status < 0)
continue;
/* Control messages are always accessed via some macros
* http://www.kernel.org/doc/man-pages/online/pages/man3/cmsg.3.html
*/
for (cmsg = CMSG_FIRSTHDR(&msg);cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
{
/* Ip level */
if (cmsg->cmsg_level == SOL_IP)
{
/* We received an error */
if (cmsg->cmsg_type == IP_RECVERR)
{
fprintf(stderror, "We got IP_RECVERR message\n");
sock_err = (struct sock_extended_err*)CMSG_DATA(cmsg);
if (sock_err)
{
/* We are intrested in ICMP errors */
if (sock_err->ee_origin == SO_EE_ORIGIN_ICMP)
{
/* Handle ICMP errors types */
switch (sock_err->ee_type)
{
case ICMP_NET_UNREACH:
/* Hendle this error */
fprintf(stderror, "Network Unreachable Error\n");
break;
case ICMP_HOST_UNREACH:
/* Hendle this error */
fprintf(stderror, "Host Unreachable Error\n");
break;
/* Handle all other cases. Find more errors :
* http://lxr.linux.no/linux+v3.5/include/linux/icmp.h#L39
*/
}
}
}
}
}
}
}
这篇关于从带有MSG_ERRQUEUE标志的recvmsg中读取ICMP有效负载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!