在线路上发送ip数据包抛出"无效的参数"

时间:2015-03-17 07:38:23

标签: c ip ping

我正在实施一个简单的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应用程序构建它。

由于

1 个答案:

答案 0 :(得分:0)

如果有人遇到同样的问题,问题就像在这篇文章中提到的那样:Raw socket sendto() failure in OS X