沿着线路发送 ip 数据包抛出 "Invalid argument"
sending ip packet down the wire throws "Invalid argument"
我正在实施一个简单的 ICMP ping,其中通过网络发送 IP 数据包给我 "Invalid argument"。
代码如下:
/* 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 数据包看起来很简单,但出于某种原因,它总是给出 errno 22。我不确定代码还有什么问题。
套接字是使用以下方法创建的:
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
我不能使用原始套接字,因为我正在为 iOS 应用构建它。
谢谢
万一有人遇到同样的问题,这个问题正是post中提到的:Raw socket sendto() failure in OS X
我正在实施一个简单的 ICMP ping,其中通过网络发送 IP 数据包给我 "Invalid argument"。
代码如下:
/* 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 数据包看起来很简单,但出于某种原因,它总是给出 errno 22。我不确定代码还有什么问题。
套接字是使用以下方法创建的:
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
我不能使用原始套接字,因为我正在为 iOS 应用构建它。
谢谢
万一有人遇到同样的问题,这个问题正是post中提到的:Raw socket sendto() failure in OS X