我正在实施一个简单的ICMP ping,在线路上发送IP数据包给我“无效的参数”。
以下是代码:
/* Create IP Packet */
int packet_size = IPv4_HDRLEN + (int)sizeof(ICMPHeader) + (int)[payload length];
char *packet = (char *) malloc (packet_size);
if (!packet)
{
perror("out of memory");
return;
}
//zero out the packet buffer
memset (packet, 0, packet_size);
//ip header
struct ip *iphdr = (struct ip *) packet;
iphdr->ip_v = 4;
iphdr->ip_hl = 5;
iphdr->ip_tos = 0;
iphdr->ip_len = htons(packet_size);
iphdr->ip_id = (ushort) rand();
iphdr->ip_off = 0;
iphdr->ip_ttl = 255;
iphdr->ip_p = IPPROTO_ICMP;
iphdr->ip_sum = in_cksum((uint16_t *)iphdr, IPv4_HDRLEN);
int status = 0;
char *src_ip = (char *) [@"127.0.0.1" UTF8String];
char *dst_ip = (char *) [@"2.3.4.5" UTF8String];
// Source IPv4 address (32 bits)
if ((status = inet_pton (AF_INET, src_ip, &(iphdr->ip_src))) != 1) {
fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
exit (EXIT_FAILURE);
}
// Destination IPv4 address (32 bits)
if ((status = inet_pton (AF_INET, dst_ip, &(iphdr->ip_dst))) != 1) {
fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
exit (EXIT_FAILURE);
}
icmpPacket = [NSMutableData dataWithLength:sizeof(*icmpPtr) + [payload length]];
assert(icmpPacket != nil);
icmpPtr = [icmpPacket mutableBytes];
icmpPtr->type = kICMPTypeEchoRequest;
icmpPtr->code = 0;
icmpPtr->checksum = 0;
icmpPtr->identifier = OSSwapHostToBigInt16(self.identifier);
icmpPtr->sequenceNumber = OSSwapHostToBigInt16(self.nextSequenceNumber);
memcpy(&icmpPtr[1], [payload bytes], [payload length]);
icmpPtr->checksum = in_cksum([icmpPacket bytes], [icmpPacket length]);
int on = 1;
/* Copy icmp and data into the packet */
memcpy(packet + IPv4_HDRLEN, icmpPtr, [icmpPacket length]);
// Set flag so socket expects us to provide IPv4 header.
if (setsockopt (CFSocketGetNative(self->_socket), IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) {
perror ("setsockopt() failed to set IP_HDRINCL ");
exit (EXIT_FAILURE);
}
/* Send the packet */
if (self->_socket == NULL) {
bytesSent = -1;
err = EBADF;
} else {
bytesSent = sendto(
CFSocketGetNative(self->_socket),
packet,
packet_size,
0,
(struct sockaddr *) &sin,
sizeof (struct sockaddr)
);
err = 0;
if (bytesSent < 0) {
err = errno;
}
}
这实际上是Apple简单ping的扩展:https://developer.apple.com/library/mac/samplecode/SimplePing/Listings/SimplePing_m.html#//apple_ref/doc/uid/DTS10000716-SimplePing_m-DontLinkElementID_5
正在构建的IP数据包看起来很直接但由于某种原因,它总是给出错误22.我不确定该代码还有什么问题。
使用以下命令创建套接字:
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
我无法使用原始套接字,因为我正在为iOS应用程序构建它。
由于