0

I am running the ethersend.c program at http://hacked10bits.blogspot.co.uk/2011/12/sending-raw-ethernet-frames-in-6-easy.html on Ubuntu 17.04 installed on VirtualBox.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>    /* Must precede if*.h */
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>

union ethframe
{
  struct
  {
    struct ethhdr    header;
    unsigned char    data[ETH_DATA_LEN];
  } field;
  unsigned char    buffer[ETH_FRAME_LEN];
};

int main(int argc, char **argv) {
  char *iface = "enp0s3";
  unsigned char dest[ETH_ALEN]
           = { 0x08, 0x00, 0x27, 0x1e, 0x7f, 0x5c };
  unsigned short proto = 0x1234;
  unsigned char *data = "hi";
  unsigned short data_len = strlen(data);

  int s;
  if ((s = socket(AF_PACKET, SOCK_RAW, htons(proto))) < 0) {
    printf("Error: could not open socket\n");
    return -1;
  }

  struct ifreq buffer;
  int ifindex;
  memset(&buffer, 0x00, sizeof(buffer));
  strncpy(buffer.ifr_name, iface, IFNAMSIZ);
  if (ioctl(s, SIOCGIFINDEX, &buffer) < 0) {
    printf("Error: could not get interface index\n");
    close(s);
    return -1;
  }
  ifindex = buffer.ifr_ifindex;

  unsigned char source[ETH_ALEN];
  if (ioctl(s, SIOCGIFHWADDR, &buffer) < 0) {
    printf("Error: could not get interface address\n");
    close(s);
    return -1;
  }
  memcpy((void*)source, (void*)(buffer.ifr_hwaddr.sa_data),
         ETH_ALEN);

  union ethframe frame;
  memcpy(frame.field.header.h_dest, dest, ETH_ALEN);
  memcpy(frame.field.header.h_source, source, ETH_ALEN);
  frame.field.header.h_proto = htons(proto);
  memcpy(frame.field.data, data, data_len);

  unsigned int frame_len = data_len + ETH_HLEN;

  struct sockaddr_ll saddrll;
  memset((void*)&saddrll, 0, sizeof(saddrll));
  saddrll.sll_family = PF_PACKET;   
  saddrll.sll_ifindex = ifindex;
  saddrll.sll_halen = ETH_ALEN;
  memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);

  if (sendto(s, frame.buffer, frame_len, 0,
             (struct sockaddr*)&saddrll, sizeof(saddrll)) > 0)
    printf("Success!\n");
  else
    printf("Error, could not send\n");

  close(s);

  return 0;
}

The VM has two interfaces with MAC addresses as mentioned below:

enp0s3 08:00:27:1f:fc:2b
enp0s8 08:00:27:1e:7f:5c

I am sending the frame from enp0s3 to destination 08:00:27:1e:7f:5c, that is, to enp0s8.

When I listen on enp0s3 using tcpdump I can see the packet:

sam@sam:~$ sudo tcpdump -A -i enp0s3
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
16:04:55.868207 08:00:27:1f:fc:2b (oui Unknown) > 08:00:27:1e:7f:5c (oui 
Unknown), ethertype Unknown (0x1234), length 16: 
0x0000:  6869                                     hi
hi

However, when I listen on enp0s8 using tcpdump (where the packet should reach) I can see no output in tcpdump.

Why is the packet not reaching enp0s8?

Edit: enp0s3 was a NAT adapter and enp0s8 was a host-only adapter. Possibly that was causing the problem. Now I added another host-only adapter called enp0s9 and now the communication works intermittently. Why does it not work always?

  • what happens when you use real machines? – old_timer Dec 18 '17 at 18:41
  • are you sending only 16 bytes? what if you send 64 (just pad it with whatever)? – old_timer Dec 18 '17 at 18:43
  • @old_timer I don't have any spare machines to install Linux currently so can't try on a real machine at the moment. I actually made some progress. enp0s3 was a NAT adapter and enp0s8 was a host-only adapter in VirtualBox which I think was the main problem. So I added another host-only adapter called enp0s9. Now communication from enp0s8 to enp0s9 works intermittently. Not sure why it doesn't work always. Will try your padding suggestions and will debug further. – Sumeet Sarkar Dec 18 '17 at 21:09
  • @old_timer And I am sending "hi" which is 2 bytes. 14 bytes is the header( 2 proto, 6 source MAC address and 6 destination MAC address). – Sumeet Sarkar Dec 18 '17 at 21:19
  • the stack should pad to 64 for you but just curious. these packages arent guaranteed so loss would be expected, but being on the same machine...also you dont need to start with two vms, on the same single primary os you can send to yourself. it wont go out on the wire (well not in linux in general) so shouldnt get lost. – old_timer Dec 18 '17 at 21:38

0 Answers0