Reference
https://stackoverflow.com/questions/21411851/how-to-send-data-over-a-raw-ethernet-socket-using-sendto-without-using-sockaddr
Example
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
char* ifname = "enp2s0";
unsigned char srcMac[6];
//unsigned char dstMac[6] = {0, 0xDE, 0xAD, 0xBE, 0xEF, 0};
//00:e0:4c:68:3c:3b (enp3s0, 192.168.0.113)
unsigned char dstMac[6] = {0, 0xE0, 0x4C, 0x68, 0x3C, 0x3B};
int fd = socket( PF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) );
/* bind to interface */
struct ifreq req;
memset( &req, 0, sizeof( req ) );
strcpy( (char*)req.ifr_name, (char*)ifname );
if ( ioctl( fd, SIOCGIFINDEX, &req ) < 0 )
{
perror( "init: ioctl" );
close( fd );
return -1;
}
struct sockaddr_ll addr;
memset( &addr, 0, sizeof( addr ) );
addr.sll_family = PF_PACKET;
addr.sll_protocol = 0;
addr.sll_ifindex = req.ifr_ifindex;
if ( bind( fd, (const struct sockaddr*)&addr, sizeof( addr ) ) < 0 )
{
perror( "init: bind fails" );
close( fd );
return -1;
}
if ( ioctl( fd, SIOCGIFHWADDR, &req ) < 0 )
{
perror( "init: ioctl SIOCGIFHWADDR" );
close( fd );
return -1;
}
/* store your mac address somewhere you'll need it! in your packet */
memcpy( srcMac, (unsigned char*)req.ifr_hwaddr.sa_data, ETH_ALEN );
int length = 60;
unsigned char txPkt[ length ];
unsigned char* pkt = txPkt;
memset( txPkt, 0, sizeof( txPkt ) );
//destination mac address
memcpy( pkt, dstMac, 6 );
pkt += 6;
// source mac address
memcpy( pkt, srcMac, 6 );
pkt += 6;
// add more data, like a type field! etc
int bytes = write( fd, txPkt, length );
printf("Sent packet of size:%d\n", bytes);
return 0;
}
/////////////version 2////////////////////////////////
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
char* ifname = "enp2s0";
unsigned char srcMac[6];
//unsigned char dstMac[6] = {0, 0xDE, 0xAD, 0xBE, 0xEF, 0};
//00:e0:4c:68:3c:3b (enp3s0, 192.168.0.113)
unsigned char dstMac[6] = {0, 0xE0, 0x4C, 0x68, 0x3C, 0x3B};
int fd = socket( PF_PACKET, SOCK_RAW, htons( ETH_P_ALL ) );
/* bind to interface */
struct ifreq req;
memset( &req, 0, sizeof( req ) );
strcpy( (char*)req.ifr_name, (char*)ifname );
if ( ioctl( fd, SIOCGIFINDEX, &req ) < 0 )
{
perror( "init: ioctl" );
close( fd );
return -1;
}
struct sockaddr_ll addr;
memset( &addr, 0, sizeof( addr ) );
addr.sll_family = PF_PACKET;
addr.sll_protocol = 0;
addr.sll_ifindex = req.ifr_ifindex;
if ( bind( fd, (const struct sockaddr*)&addr, sizeof( addr ) ) < 0 )
{
perror( "init: bind fails" );
close( fd );
return -1;
}
if ( ioctl( fd, SIOCGIFHWADDR, &req ) < 0 )
{
perror( "init: ioctl SIOCGIFHWADDR" );
close( fd );
return -1;
}
/* store your mac address somewhere you'll need it! in your packet */
memcpy( srcMac, (unsigned char*)req.ifr_hwaddr.sa_data, ETH_ALEN );
int length = 60;
unsigned char txPkt[ length ];
unsigned char* pkt = txPkt;
memset( txPkt, 0, sizeof( txPkt ) );
//destination mac address
memcpy( pkt, dstMac, 6 );
pkt += 6;
// source mac address
memcpy( pkt, srcMac, 6 );
pkt += 6;
// add more data, like a type field! etc
// etherType 0x0800
unsigned char etherType[2] = {0x08, 0};
memcpy( pkt, etherType, 2 );
pkt += 2;
unsigned char ip[20] = {0x45, 0, //ipv
0, 0x2E, //length 46
0x88, 0x1f, //ip-id
0x40, 0, //frag flag
0xf7, 0x11, //ttl, proto udp
0xea, 0x9d, //checksum
0x8, 0, 0, 0x1, // src IP 8.0.0.1
0x9, 0, 0, 0x1}; //dst IP 9.0.0.1
memcpy( pkt, ip, 20 );
pkt += 20;
unsigned char udp[8] = {0x5a, 0x02, //src port
0x14, 0x7f, //dst port
0, 0x1A, //length 26
0, 0}; //checksum
memcpy( pkt, udp, 8 );
pkt += 8;
//udp payload 18 bytes
memset( pkt, 0xa5, 18 );
//send packet
int bytes = write( fd, txPkt, length );
printf("Sent packet of size:%d\n", bytes);
return 0;
}
Compile
gcc -o test raw_pkt.c
Test
sudo ./test
Sent packet of size:60
Tcpdump
09:23:21.663726 40:8d:5c:6f:99:6b > 00:e0:4c:68:3c:3b, 802.3, length 0: LLC, dsap Null (0x00) Individual, ssap Null (0x00) Command, ctrl 0x0000: Information, send seq 0, rcv seq 0, Flags [Command], length 46
0x0000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0020: 0000 0000 0000 0000 0000 0000 0000 ..............
sudo tcpdump -eni enp3s0 ip host 8.0.0.1 -vv
tcpdump: listening on enp3s0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:22:07.215705 40:8d:5c:6f:99:6b > 00:e0:4c:68:3c:3b, ethertype IPv4 (0x0800), length 60: (tos 0x0, ttl 247, id 34847, offset 0, flags [DF], proto UDP (17), length 46)
8.0.0.1.23042 > 9.0.0.1.5247: [no cksum] UDP, length 18