0

I'm trying to send a frame Ethernet in a Linux system by the C function sendto(). The frame does not contain any IP level information because the IP protocol is not used in my application.
The sendto() documentation provides the following information:

Signature of the function sendto()

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

The buffer to transmit

For send() and sendto(), the message is found in buf and has length len.

The destination address

If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET) socket, the arguments dest_addr and addrlen are ignored (and the error EISCONN may be returned when they are not NULL and 0), and the error ENOTCONN is returned when the socket was not actually connected. Otherwise, the address of the target is given by dest_addr with addrlen specifying its size.

In my case the socket is created by the following instruction (see here for manual Linux manual page dedicated to socket() function):

int sck_dgram = socket(AF_PACKET, SOCK_DGRAM, 0);

and so it is NOT a connection-mode socket. To set the destination address I use the following instructions:

struct sockaddr_ll dest_addr = {0};
dest_addr.sll_family = AF_PACKET;
dest_addr.sll_ifindex = ifindex;
dest_addr.sll_halen = ETHER_ADDR_LEN;
memcpy(dest_addr.sll_addr, mac_dest, ETHER_ADDR_LEN);

where mac_dest is an array that contains the MAC address destination and ifindex is the index of the ethernet interface used for the send.

My sendto() instruction

In conclusion, to send the buf[BUFFSIZE] array of data I use the following sendto() instruction:

sendto(sck_dgram, buf, BUFFSIZE, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr))

With the previous instruction I can set only the target MAC address (bytes from 0 to 5 of the frame) by dest_addr but not the source MAC address of the frame (the bytes from 6 to 11 of the frame). The source MAC address is automatically set equal to MAC address of the Ethernet Interface used for the send.

My question

Is it possible send a frame Ethernet with a source MAC address different from the MAC address of the Ethernet Interface used for the send?


EDIT: The solution of the problem is the modification of the instruction which creates the socket by the substitution of SOCK_DGRAM with SOCK_RAW. The right instruction is:

int sck_raw = socket(AF_PACKET, SOCK_RAW, 0);

According to the previous instruction I have to modify the sendto() instruction so that the buf[] include 14 octets with the destination mac address, source mac address and ether type. This data must be place in the first 14 bytes of buf[]. So I have to increase the size of buf as followed:

char buf[BUFFSIZE+14];

// set buf[0] .. buf[5] with mac dest
// set buf[6] .. buf[11] with mac source
// set buf[12] and buf[13] with ether type (set to 0x0200 and this is the data lenght)

// sendto() becomes:
sendto(sck_raw, buf, BUFFSIZE+14, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr))

This Wikipedia link explains the ethernet frame structure.

frankfalse
  • 1,553
  • 1
  • 4
  • 17
  • 1
    You may want to dig into `SOCK_RAW` instead of `SOCK_DGRAM`. See [this answer](https://stackoverflow.com/a/30780905/6782754) for some more hints. This might require root privileges to execute. – Gerhardh Mar 09 '23 at 09:07
  • @Gerhardh Thank you very much. To solve my problem it is enough to change the socket creation and substitute `SOCK_DGRAM` with `SOCK_RAW`. If you can write a complete answer please. – frankfalse Mar 09 '23 at 10:06
  • 1
    I'm glad it helped. I am not deep enough into raw sockets to provide a solid answer. Using that other question should be sufficient. – Gerhardh Mar 09 '23 at 10:11

1 Answers1

0

The simplest solution is to change mac-address on ethernet-card.

If you want you can use tc & iptables solution. iptables to set class of packet based e.g on udp port then you can use tc to change source mac address for class of packet.

nonamenick
  • 33
  • 6
  • Changing MAC address will probably break all the other communication. – Gerhardh Mar 09 '23 at 09:10
  • because this is udp packet source mac address can be used for example by virtual functions of ethernet card and it should not break all other communication if one class of packets has different smac (this solution will not affect other traffic) – nonamenick Mar 09 '23 at 09:13
  • So you mean to add a virtual network card with that new MAC address? – Gerhardh Mar 09 '23 at 09:15