Injecting raw packet onto network in C (Linux)

2k views Asked by At

I am trying to write a function that takes a stream of bytes (including ethernet header and perhaps upper layer protocols encapsulated within the ethernet packet as well) and send it out on the network on a particular interface.

Here is a summary of my code:

// create socket
int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s < 0) {
    // error handling
}

// set up to just receive/send packets on one interface (stored in the variable iface_name e.g. eth0)
struct ifreq ifr;
bzero(&ifr, sizeof(struct ifreq));
strncpy(ifr.ifr_ifrn.ifrn_name, iface_name, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
    // error handling
}

// set up socaddr for write
struct sockaddr sa;
sa.sa_family = PF_PACKET;
sa.sa_data = htons(ETH_P_ALL);

// write to wire
// buf has type char* and len has type int
// buf contains ethernet header, followed by payload (e.g. ARP packet or IP packet)
if ( sendto(s, buf, len, 0, &sa, sizeof(struct sockaddr) ) < 0 ) {
    perror("sendto");
    // more error handling
}

I get the error

sendto: Invalid argument

How can I fix this error?

My initial guess is that this is somehow caused by the sa argument, since all the others are fairly standard and there's not much to go wrong. I could replace this with an argument of sockaddr_ll type as in this example, but this would mean extracting the header information from buf and this seems a little pointless since it's already there, ready to go. There must be a better way? Encapsulate, unencapsulate, re-encapsulate, send seems like it has too many unnecessary steps. I am writing an underlying interface for some pre-existing code, so there is no way I can adapt the input to not already have the data-link layer headers included.

1

There are 1 answers

0
KrisSodroski On

its your libraries:

http://linux.die.net/man/7/raw see the header definition and look at how he makes his socket he's not using htons, but rather: IPPROTO_RAW located in

  #include <netinet/in.h>