Reputation: 213
I have a program that attempts to use raw sockets to send an ICMP packet in C. However, everytime I send an ICMP packet, I receive an error from sendto
stating, Invalid argument.
Here's the main portion:
int main(int argc, char *argv[])
{
if (argc != 3)
{
fprintf(stderr, "Usage: ./main [src] [dst]\n");
return -1;
}
struct sockaddr_in src, dst;
memset(&src, 0, sizeof(struct sockaddr_in));
memset(&dst, 0, sizeof(struct sockaddr_in));
inet_pton(AF_INET, argv[1], &src.sin_addr);
inet_pton(AF_INET, argv[2], &dst.sin_addr);
int s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == -1)
{
perror("socket");
return -1;
}
void *pkt = create_pkt(&src, &dst, IPPROTO_ICMP);
if (!pkt)
{
close(s);
return -1;
}
send_pkt(s, pkt, sizeof(ICMP) + sizeof(IP), &dst);
return 0;
}
Here's the function where the error happens:
void send_pkt(int s, void *pkt,
int size, struct sockaddr_in *dst)
{
if (sendto(s, pkt, size, 0,
(struct sockaddr *) dst, sizeof(struct sockaddr)) == -1)
{
perror("sendto");
return;
}
}
I know I have raw sockets enabled on my system (I'm using Ubuntu 16.04) and I've also experimented with the values in dst
including the IP destination address, but nothing has resulted in significant change. As a result, I've left dst->sin_port = 0
and dst->sin_family = 0
.
If anyone could shed light as to why this isn't working, I would appreciate it.
Upvotes: 0
Views: 1057
Reputation: 213
Turns out, with raw sockets, that sendto
will return an error if any of the fields in the IP header are incorrect. In my case, I switched the positioning of the IHL and the version (I had combined them into one field because of endian issues). So, moral of the story: If you receive a sendto: Invalid argument
error for a raw socket, be sure to check the IP header, not just your destination structure for sendto
.
Upvotes: 2