0
votes

I am trying to send and receive raw ethernet frames to include a network device as a media access controller in a simulation environment. Therefore it is important that the receiving of the packets works through nonblocking statements.

Now the sending of the raw ethernet frames works fine but there's one thing about the receive path that is confusing me: How do I know where the one frame ends and the other frame begins.

What I fundamentally do is to open a raw socket:

device.socket = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);

setting it up as non blocking:

flags = fcntl(s,F_GETFL,0);
assert(flags != -1);
fcntl(s, F_SETFL, flags | O_NONBLOCK);

and then call the recv() function cyclical to get the data from the socket:

length = recv(s, buffer, ETH_FRAME_LEN_MY, 0);

But as far as I know the recv() function only returns the amount of bytes, that is currently availible in the receive buffer and therefore I do not know if another frame starts or if I am still reading the "old" packet.

And because of the fact, that the length of the ethernet frame is not included in the header I can not do this on my own.

Thank you in advance!

1
I know how the Ethernet protocol is working but how will this help me? The only information in the header is the type which can contain the length of the frame but not necessary will!S.Lever
The EtherType field has two octets with the pay load length. With that you can determine the total frame size.Paul Ogilvie
"The EtherType field is two octets long and it can be used for two different purposes. Values of 1500 and below mean that it is used to indicate the size of the payload in octets, while values of 1536 and above indicate that it is used as an EtherType, to indicate which protocol is encapsulated in the payload of the frame. When used as EtherType, the length of the frame is determined by the location of the interpacket gap and valid frame check sequence (FCS)."Paul Ogilvie
The problem is, that when I read from the socket the data I receive only contains the header and the data of the ethernet frame. Preamble CRC and FCS is already removed within the mac.S.Lever

1 Answers

0
votes

If anyone runs into the same problem here's a possible solution:

You can use the libpcap library(in windows winpcap) to open the device as a capture device:

char errbuf[PCAP_ERRBUF_SIZE];      /* error buffer */
Pcap_t *handle;                     /* packet capture handle */

/* open capture device*/ 
/* max possible length, not in promiscous mode, no timeout!*/
handle = pcap_open_live(dev, 65536, 0, 0, errbuf);
if (handle == NULL) {
  fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
}

/* set capture device to non blocking*/
if(pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)){
   fprintf("Could not set pcap interface in non blocking mode: %s \n", errbuf);
}

Now you can cyclic call the pcap_dispatch function to receive packet(s):

int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user);

You have to provide a callback function in which the data is handled. See https://www.freebsd.org/cgi/man.cgi?query=pcap_dispatch&apropos=0&sektion=3&manpath=FreeBSD+11-current&format=html for further information.

You can send raw ethernet frames by using the inject function:

pcap_inject(pcap,frame,sizeof(frame));