I'm writing a simple program that creates an ethernet I frame and sends it through an interface to the specified MAC.
As i have read, the process for connecting to a socket in UNIX goes a bit like:
int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
struct sockaddr_ll sll;
/* populate sll with the target and interface info */
connect(sockfd, (struct sockaddr*)&sll, sizeof(sll));
write(sockfd, stuff, sizeof(stuff));
close(sockfd)
The thing is, for me, stuff is a valid eth frame already containing everything needed to send a packet to its destination. Isn't the connect step redundant then? What am I missing?
Have a nice day.
CodePudding user response:
Not only is the connect "redundant", it is an error -- according to the Linux man page:
The connect(2) operation is not supported on packet sockets.
So the connect is probably failing but not actually doing anything. Since you ignore the return value of connect, you don't notice the failure.
CodePudding user response:
As stated above, the connection step was wrong.
I will give the details of how i solved it in this post in case anyone in need sees this: (this is as i understood it, feel free to correct me)
For a trully raw communication in userspace you have to understand three concepts:
- Sockets are analogous to file descriptors.
- Binding a socket is like opening a file.
- You can not read or write to a socket, just kindly ask the kernel to do it for you.
The process i followed is as follows:
int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
struct sockaddr_ll sll;
sll.sll_family = AF_PACKET;
sll.sll_ifindex = index; //This is the index of your network card
//Can be obtained through ioctl with SIOCGIFINDEX
sll.sll_protocol = htons(ETH_P_ALL);
bind(sockfd, (struct sockaddr*)&sll, sizeof(sll));
size_t send_len = write(sockfd, data, size);
As you can see, we dont really use connect, as it was, indeed, a mistake.
p.s. for a full example: https://github.com/TretornESP/RAWRP