jeudi 23 juin 2016

Using sendmsg/sendmmsg with raw ethernet frames

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: %sn", 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 }

Aucun commentaire:

Enregistrer un commentaire