I'm trying to use C to send raw ethernet packets via sendmsg()
. This code successfully opens a raw packet socket, attempts to fill a struct iovec
with a single array of bytes (char message[]
), then fills a struct msghdr
with the destination address, the address length, and a pointer to the struct iovec
containing the message. sendmsg()
returns EINVAL
for every call but I have no idea which arguments are invalid. (I've deleted some perror()
calls to make this code simpler to read; the output is Invalid argument
.)
I haven't been able to find any examples of how sendmsg()
would work with raw sockets, but similar code using sendto()
works as expected. In that code, I form the Ethernet frame explicitly, including headers and protocol information, but to my understanding that's not necessary with a sendmsg()
call? I've also attempted to have message.iov_base
point to a buffer containing that explicitly-formed Ethernet frame including the 14-byte header, but sendmsg()
also balks at that.
Can sendmsg()
and sendmmsg()
work with raw Ethernet frames? Is there something I'm missing about the iovec
that is making it invalid?
30 int main(void) {
32 unsigned char dest[ETH_ALEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; // destination MAC address
33
34 // Socket variables
35 int s;
36 unsigned short protocol = htons(ETH_P_802_EX1);
38
39 // Message variables
40 char message[] = {"Test message. Test message. Test message!\n"};
41 size_t msg_len = strlen(message) + 1; // Message length includes null terminator
42 int e; // Error code
43 struct msghdr msg;
44 struct iovec msgvec;
45
46 // Setup source-side socket
47 s = socket(AF_PACKET, SOCK_RAW, protocol);
48 if (s < 0) { printf("%d: %s\n", errno, strerror(errno)); return EXIT_FAILURE; }
49
50 msgvec.iov_base = message;
51 msgvec.iov_len = msg_len;
52 memset(&msg, 0, sizeof(msg));
53 msg.msg_name = dest;
54 msg.msg_namelen = ETH_ALEN;
55 msg.msg_control = NULL;
56 msg.msg_controllen = 0;
57 msg.msg_flags = 0;
65 msg.msg_iov = &msgvec;
66 msg.msg_iovlen = 1;
67
68 for (int i=0; i<10; i++) {
69 e = sendmsg(s, &msg, 0);
73 }
79 close(s);
80 return EXIT_SUCCESS;
81 }