Receiving Data for Multiple Hosts via Linux Sockets - c++

I have a rather strange question. Lately, I have been tasked with developing software to simulate a large (hundreds of nodes and up) network. To make a long story short, we have a head-end server that communicates with each host through a predictable IP addressing scheme via Linux sockets using a mixture of broadcast and unicast. The head-end will issue a request to a given client and will (sometimes) receive data pertaining to the command executed. All data / commands are sent via UDP on a well-defined port.
Now, for testing purposes, we would like to use the original server binary in a virtual environment an still receive reasonable data. For example, we would like to issue a reset command to a particular node and receive a fake notification back. The broadcast bit is easy, as I simply have to listen in on the proper broadcast address and act accordingly. The unicast is what has me stuck.
The Question
Is it possible to receive UDP requests for a large number of discrete hosts via a single (or a reduced) number of Linux sockets? All hosts are on the same subnet and all IP addresses / hosts / network topology are known ahead of time.
Desired Output
Ultimately, we would like to have an app that runs on a host on the network and responds as if it were each of these discrete 'virtualized' hosts based on input datagrams.
Do note that I am not asking for someone to write me a program. I am just simply looking for some direction as to the 'vehicle' by which this can be accomplished.
Possible Solutions
RAW Sockets: This has promise as I can trap all inbound data via a
single socket and punt it off to a worker thread for processing and
response. Unfortunately, I only receive packets that are
destined for my host IP and none of the 'fake' IPs.
Abuse IP aliases on Linux, one for each host: This seems to be the most direct approach but it feels like duck hunting with a bazooka. It has the added benefit of appearing to 'be' the host for any other forms of communication, I just worry that creating 400+ aliases might be a bit much for our bastard-child of a Linux environment. As an added complication, the hosts do change based on configuration and can be in any manner of states (up, down, command processing, etc.).
The source code of the server is to be treated as immutable for the purpose of our testing. I fully expect this will be impossible with the constraints given, but someone may have an idea of how to accomplish this as, quite frankly, I have never done anything of this sort before.
Thank you in advance for any assistance.

Personally, I would use your second option - add all the IP addresses to the host, then bind to INADDR_ANY address. This would mean you could use just one socket.
An alternative is to set the IP_TRANSPARENT socket option on your socket, which will then allow your application to bind to non-local addresses (you would route the networks containing those addresses through the machine that your application is running on). This method does require one socket per address, though.

So, using a combination of both of caf's solutions, I was able to have my cake and eat it too. I was also heavily influenced by
Python/iptables: Capturing all UDP packets and their original destination
which is a Python example, but does show how I can 'cheat' the packets back to a single interface, negating the need for maintenance of many sockets. That question is well worth the read and contains a lot of good information. For compactness, though, I will restate part of it below.
Hopefully it can help someone else down the road.
Part 1 - Host Configuration
As stated in the above question, we can use a combination of iptables and ip routes to redirect the packets to loopback for processing. This was not stated in my original question, but it is acceptable for the 'simulator' to run on the head-end host itself and not be a discrete node on the network. To do this, we mark each packet via iptables and then route it to lo based on said mark.
iptables -A OUTPUT -t mangle -p udp --dport 27333 -j MARK --set-mark 1
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
In my case, I only need traffic to a certain port so my iptables rule has been adjusted accordingly from the original.
Part 2 - Software
As caf stated in his post, the real trick is to use IP_TRANSPARENT and a raw socket. Raw sockets are necessary in order to get the original source / destination IP addresses. One gotchya that took me a while was the use of IPPROTO_UDP in the call to socket(). Even though this is a raw socket, it will strip out the Ethernet header. A lot of code online shows the calculation of the IP header offset using something similar to the following:
struct iphdr* ipHeader = (struct iphdr *)(buf + sizeof(ethhdr));
Offsetting by ethhdr (which is stripped) will give you some rather entertaining garbage data. With that particular header removed, the necessary IP header is simply the first structure in the buffer.
The Test Code
Below you will find a proof-of-concept example. It is no way fully functional or complete. In particular, no checking in done on the incoming packets for malicious data (ex. format string exploits in the payload, pointer math problems, malformed / malicious packets, etc).
Note that the code binds to lo specifically. This does not mean that we will only get packets destined for one of our 'fake' hosts (other services use loobpack, too). Additional checking / filtering is required to get only the packets we want.
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string>
int main(int argc, char *argv[]) {
//Set up listening socket
struct sockaddr_in serverAddr;
struct iphdr* ipHeader;
struct udphdr* udpHeader;
int listenSock = 0;
char data[65536];
static int is_transparent = 1;
std::string device = "lo";
//Initialize listening socket
if ((listenSock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0) {
printf("Error creating socket\n");
return 1;
}
setsockopt(listenSock, SOL_IP, IP_TRANSPARENT, &is_transparent, sizeof(is_transparent));
setsockopt(listensock, SOL_SOCKET, SO_BINDTO_DEVICE, device.c_str(), device.size());
memset(&serverAddr, 0x00, sizeof(serverAddr));
memset(&data, 0x00, sizeof(data));
//Setup server address
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverAddr.sin_port = htons(27333);
//Bind and listen
if (bind(listenSock, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
printf("Error binding socket\n");
return 1;
}
while (1) {
//Accept connection
recv(listenSock, data, 65536, 0);
//Get IP header
ipHeader = (struct iphdr*)(data);
//Only grab UDP packets (17 is the magic number for UDP protocol)
if ((unsigned int)ipHeader->protocol == 17) {
//Get UDP header information
udpHeader = (struct udphdr*)(data + (ipHeader->ihl * 4));
//DEBUG
struct sockaddr_in tempDest;
struct sockaddr_in tempSource;
char* payload = (char*)(data + ipHeader->ihl * 4) + sizeof(struct udphdr));
memset(&tempSource, 0x00, sizeof(tempSource));
memset(&tempDest, 0x00, sizeof(tempDest));
tempSource.sin_addr.s_addr = ipHeader->saddr;
tempDest.sin_addr.s_addr = ipHeader->daddr;
printf("Datagram received\n");
printf("Source IP: %s\n", inet_ntoa(tempSource.sin_addr));
printf("Dest IP : %s\n", inet_ntoa(tempDest.sin_addr));
printf("Data : %s\n", payload);
printf("Port : %d\n\n", ntohs(udpHeader->dest));
}
}
}
Further Reading
Some very helpful links are below.
http://www.binarytides.com/packet-sniffer-code-in-c-using-linux-sockets-bsd-part-2/
http://bert-hubert.blogspot.com/2012/10/on-binding-datagram-udp-sockets-to-any.html

Related

Linux socket C/C++ - What is the best way to check if ip/port is already in use?

I have a system that can start multiple instances.
Every instance has a client and a server.
They are connected over socket/TCP
Every instance is started by starting a client.
The client starts (checks if IP is available, if not increase the IP by 1, checks again ...) -
The client starts the server with the free IP and connects to it. (for legacy reasons has to be like this)
Instance numbers 2, 3, 4, 5 work without issues.
...
Instance number 6. -> Fails on checking if the first IP in the range is available.
To check if IP is already in use, I do not close the socket on the server side so that it can accept the additional connection.
On the client-side, I check if I can connect to the server-side with the following code:
bool CheckIPInUse(char *ip)
{
bool ret = false;
int port = 12345;
int sock;
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
// **non blocking** because I want the check to be fast.
sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
inet_pton(AF_INET, ip, &serv_addr.sin_addr);
int ret_conn = connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (ret_conn == 0){
fprintf(stdout, "connected");
ret = true;
}
else if (ret_conn < 0 && (errno != EINPROGRESS)){
fprintf(stdout, "failed to connect");
}
else
{
int check_if_connected = 10;
while (check_if_connected--)
{
socklen_t len = sizeof(serv_addr);
int ret_getpeer = getpeername(sock, (struct sockaddr *)&serv_addr, &len);
if (ret_getpeer == 0)
{
fprintf(stdout, "connected");
ret = true;
break;
}
usleep(100000);
}
}
close(sock);
return ret;
}
This works for the first 5 instances.
6th instance fails to connect to the first IP in range and tries to start the server with IP which is already in use. (always the 6th).
Is there any better way to check programmatically if IP/Port is already busy?
Any ideas on what to check. for failure in the instance number 6?
The only way to check if an ip/port on a server is available is to bind() to it. If it worked, it was available (but not any more).
Any approach that involves a test connect()ion first, to see if it fails, or anything along the lines of poking somewhere in /proc to see which IPs and ports are in use -- nothing along these lines will ever be 100% foolproof. That's because even if you reach the conclusion that the port is available, it may no longer be by the time you get around to try to bind() to it.
Now, you can take, as a starting position, that a particular IP and/or port range is reserved for your application's use, and you only wish to arbitrate IP/port allocation between different instances of your application. In that case you can do that pretty much whatever you want, you're not limited to attempting to actually start instances of your application, and hope for the best. One simplistic approach is to use lock files in /var/tmp to represent all possible IP/port combination, and have your application try, in turn, to acquire a lock on the corresponding lock file, first, and once it's official, and the lock file is acquired, then the corresponding IP/port then can be established at your leisure, but the lock file must remain locked until the IP/port is no longer in use.
But in terms of attempting to check if a socket port is available, or not, the only way to do it is to bind() it, because that, by definition, is what it does. You could attempt to implement a multi-layered approach, like trying to connect() first, and then attempt to bind() it, and if the bind() fails, then keep looking for a free port. But that's creating extra complexity, without much of a benefit.
Did you check that the server did not meet its maximum backlog length ?
You may be getting "connection refused" if the server you are trying to connect to
has more pending connections then the defined backlog.
So if multiple clients are testing at the same time, one of them may encounter this.
The most probable cause of your problem is that your client is getting a connect from the server due to the listen queue. The best way to avoid this problem is to close the socket on which you call accept(2) once all the instances are in use, and reopen it again when any of the server instances are finished.
The listen queue makes the kernel to accept (send the SYN/ACK segment) connections on the otherwise not yet open socket waiting, and this will make the connection establishment quicker for the next server instances if many such connections are entering in the system. All those connections are handled in the accept(2) socket, so the best way to accept five such connections is to close the accept socket as soon as the last connection has been established (this will not avoid the problem if a connection happens to enter the server in the time between one accept(2) and the next, but the connection so established will be closed as soon as the accept socket is still open)
In my opinion, you should have a master server process that forks new processes to handle the different connection and closes the accept socket as soon as it reaches the full capacity. Once one of the servers attending the connections closes one of them, it should reopen the accept socket and accept a new connection.
IMHO, also the most robust way of implementing such a system is to allow the extra connections to get in, but not attend them, so the connection remains open in case a new client happens to enter, and it can close it if the server doesn't attend it in a timeout interval. Having a sixth client already connected, but waiting for the server to say hello, will leave you in a state in which you can start talking to the server as soon as the last service ends.

get SOCK_RAW frames with different rate [duplicate]

I'm writing code to send raw Ethernet frames between two Linux boxes. To test this I just want to get a simple client-send and server-receive.
I have the client correctly making packets (I can see them using a packet sniffer).
On the server side I initialize the socket like so:
fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL));
where MY_ETH_PROTOCOL is a 2 byte constant I use as an ethertype so I don't hear extraneous network traffic.
when I bind this socket to my interface I must pass it a protocol again in the socket_addr struct:
socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
If I compile and run the code like this then it fails. My server does not see the packet. However if I change the code like so:
socket_address.sll_protocol = htons(ETH_P_ALL);
The server then can see the packet sent from the client (as well as many other packets) so I have to do some checking of the packet to see that it matches MY_ETH_PROTOCOL.
But I don't want my server to hear traffic that isn't being sent on the specified protocol so this isn't a solution. How do I do this?
I have resolved the issue.
According to http://linuxreviews.org/dictionary/Ethernet/ referring to the 2 byte field following the MAC addresses:
"values of that field between 64 and 1522 indicated the use of the new 802.3 Ethernet format with a length field, while values of 1536 decimal (0600 hexadecimal) and greater indicated the use of the original DIX or Ethernet II frame format with an EtherType sub-protocol identifier."
so I have to make sure my ethertype is >= 0x0600.
According to http://standards.ieee.org/regauth/ethertype/eth.txt use of 0x88b5 and 0x88b6 is "available for public use for prototype and vendor-specific protocol development." So this is what I am going to use as an ethertype. I shouldn't need any further filtering as the kernel should make sure to only pick up ethernet frames with the right destination MAC address and using that protocol.
I've worked around this problem in the past by using a packet filter.
Hand Waving (untested pseudocode)
struct bpf_insn my_filter[] = {
...
}
s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol));
struct sock_fprog pf;
pf.filter = my_filter;
pf.len = my_filter_len;
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf));
sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(protocol);
sll.sll_ifindex = if_nametoindex("eth0");
bind(s, &sll, sizeof(sll));
Error checking and getting the packet filter right is left as an exercise for the reader...
Depending on your application, an alternative that may be easier to get working is libpcap.

Port to Port data transfer with UDP

I'm working on this project where the source and destination ports are specified for sending a message via a UDP socket in C++. I've got the TCP portion of the project working fine, but I don't understand how to specify both the source and destination ports when setting this up.
The way I would know how to do it is the "receiver" sets up a recvfrom() call, with the port that the "sender" will also use in the sendto() command... but it would need to be the same port.
So, given that I need port x on the "receiver" to talk to port y on the "sender", how would I do that?
Thanks
You can define a source port when you call bind on the sender side. For instance:
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) { /*error*/}
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(source_port); // here
int res = bind(sockfd,(struct sockaddr*)&sin, sizeof(sin));
if (res < 0) { /*error*/}
And the destination port goes into the sockaddr parameter passed to sendto.
If this is one-to-one mapping, i.e. one source talks to one destination, then simply bind(2) the local port and connect(2) to the remote IP and port (contrary to common misconception you can connect UDP sockets). Do that on both sides (with appropriate remote and local IPs/ports of course), and now you can just use recv(2) and send(2) without explicit addressing.
If one side needs to wait for the other to send the first packet, then extract source address/port received with recvfrom(2), and then connect(2) to it.
If, on the other hand, one side acts as a multi-client server, then do same bind(2)/connect(2) dance on the client, but only do bind(2) to local port and then use recvfrom(2)/sendto(2) on the server.
If you need simultaneous duplex communication, then you should use sockets in blocking mode -- fcntl(...O_NONBLOCK...), and use select() to determine if your socket is writable or readable or both. Here is a nice example on how this can be done http://www.lowtek.com/sockets/select.html

Sending files between computers with C++

I am trying to write a program that sends basic text files from one computer to another using C++ over the internet (or a LAN). I was looking into Winsock but everything that I read made it seem like it was only for communication between a server and a client. I am not sure if this is what I am trying to do or if I am looking at a different problem.
EDIT: Thanks for the great answers guys. I kind of feel bad for having to choose a best one out of the lot.
A client-server architecture should be fine for sending files. The "server" is simply the program that starts first, and waits for the other (the client) to connect to it. Past there, there's not a lot of difference between the two. In a lot of cases, it's easiest to write the code so it automatically attempts to contact a server, and if it can't find one, it sets itself up as the server.
Also note that making things work across the internet with (particularly) NAT routers involved can make the code a little trickier. It's not all that tough if you pre-configure the firewall to allow the connection(s), but otherwise you typically end up using UPnP to establish the connection through the firewall. That can easily double the work compared to doing the job locally without NAT involved.
Here is an example of how to copy/transfer files using C/C++ in Linux.The server listens in port 8080. The client transmits a filename. The server receives the filename, open the file and sends its contents to the client. I intentionally used odd or small buffer sizes for illustrative purposes.
The server.c file:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
int main (int argc,char *argv[])
{
struct sockaddr_in p;
struct sockaddr_in q;
int z,s,t,x,n,b = sizeof(q);
char buf[23];
int fd;
s = socket(AF_INET,SOCK_STREAM,0);
bzero (&p,sizeof(p));
p.sin_family = AF_INET;
p.sin_addr.s_addr = INADDR_ANY;
p.sin_port = htons(8080);
bind (s,(struct sockaddr*)&p,sizeof(p));
listen(s,13);
while (1) {
t = accept (s,(struct sockaddr*)&q, &b);
n = read(t,buf,23);
buf[n] = 0;
printf("%s sent: ",buf);
fd = open (buf,O_RDONLY);
z = lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
x = 0;
do {
n = read (fd,buf,23);
write (t,buf,n);
x += n;
} while (x < z);
printf("%d/%d\n",x,z);
close(fd);
close(t);
}
}
The client.c file:
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
void main (int argc, char *argv[])
{
int ret;
char buf[5];
int s,n,fd;
struct sockaddr_in p;
struct hostent *h;
char *str = argv[1];
fd = open (str,O_CREAT | O_WRONLY,S_IRUSR|S_IWUSR);
h = gethostbyname("127.0.0.1");
bzero(&p,sizeof(p));
p.sin_family = AF_INET;
p.sin_addr.s_addr = htonl(INADDR_ANY);
p.sin_addr.s_addr = ((struct in_addr*)(h->h_addr))->s_addr;
p.sin_port = htons(8080);
s = socket (AF_INET,SOCK_STREAM,0);
connect (s,(void*)&p,sizeof(p));
n = write (s,str,strlen(str));
int idx = 0;
do {
n = read (s,buf,5);
idx += n;
printf(".");
fflush(stdout);
write (fd,buf,n);
} while (n > 0);
close (fd);
close (s);
}
To compile:
Open terminal
gcc -o server server.c
gcc -o client client.c
Run the server as ./server. And then to copy rngoidiot.txt, run the client as ./client rngoidiot.txt and the file will be copied using TCP/IP. Simple combination ;-)
In short: Yes, sockets are the way to go.
"Server" and "client" in the sockets sense are generic terms - your system is running a variety of both at any given time. For example, your web browser operates as an HTTP client (where HTTP is a text-bounded mostly-synchronous protocol running over TCP/IP); Windows file sharing and remote desktop are "servers" that other systems connect into.
The distinction between server and client in the sockets sense (really in the TCP/IP sense) is that a "server" socket listens for incoming connections from remote systems (refer to MSDN or man pages on bind(), listen(), accept()) whereas a "client" socket creates outgoing connections to remote systems (connect()).
Beware that sockets programming can be a bit tricky. What you describe is a good learning exercise, but if you're trying to get something done quickly, you might look at existing tools such as netcat.
it seem like it was only for communication between a server and a client
So what? Make one computer (that is about to receive the file) the server. On that computer create a socket and make it listen for a connection on a port. Once a connection arrives, get the data according so some defined structure (see below)
The sender computer (the client, sort of) will connect to the other computer, and it knows the IP address and the port no. (The two must be known to the client for the connection). Once connection is made, it will send the data as a sequence of bytes to the server.
The structure:
The two computers that are communicating here must have a well defined structure that is known and accepted by both. The simplest structure will be:
|Length-Of-Data | Data ...... |
<-- 4 bytes---> <-- n bytes-->
Read the n from the first 4 bytes. The 4 bytes (n) here represent the length of the data and could be different, its your definition.
You could have many more 'fields' (depending on the functionality) for filename, file-type etc..
If you want to send files over internet, you have to use sockets, or better yet other high level library implemented with sockets.
In the TCP sockets terminology, there is no big difference between client and server: the communications is two way. The only difference is in who is listening for incoming connections (bind, listen, accept), and who is initiating the connection (open).
You mentioned Winsock, it means that you are working on Windows. Take a look into the Windows API, probably you can find some high level library that handles the file transfer (like a FTP or HTTP library).
Maybe doesn't fit your requirements, but you can also use a shared folder for a LAN and a folder synchronized by Dropbox for the Internet... then just use standard IO.
Speaking generally, any file transfer requires some sort of server/client connection. One computer needs to initiate a connection, and the other computer needs to be listening for the connection at the other end, and then take the actions it is instructed to by the first computer.
While you can certainly roll out your own client and server software using sockets, depending on what sorts of computers you want to transfer files between, it might make the most sense to leverage some existing client/server protocol. Some of the more popular possibilities include ssh, http, or ftp. I think C/C++ libraries should exist for all of these protocols.
Without more information I would be inclined to use ssh. Installing an ssh server shouldn't be too hard, so you'll only have to write the client software, and I think some pretty good open source libraries exist for that.
EDIT: libssh looks pretty good!

How do I receive raw, layer 2 packets in C/C++?

How do I receive layer 2 packets in POSIXy C++? The packets only have src and dst MAC address, type/length, and custom formatted data. They're not TCP or UDP or IP or IGMP or ARP or whatever - they're a home-brewed format given unto me by the Hardware guys.
My socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW) never returns from its recvfrom().
I can send fine, I just can't receive no matter what options I fling at the network stack.
(Platform is VxWorks, but I can translate POSIX or Linux or whatever...)
receive code (current incarnation):
int s;
if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) {
printf("socket create error.");
return -1;
}
struct ifreq _ifr;
strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0"));
ioctl(s, IP_SIOCGIFINDEX, &_ifr);
struct sockaddr_ll _sockAttrib;
memset(&_sockAttrib, 0, sizeof(_sockAttrib));
_sockAttrib.sll_len = sizeof(_sockAttrib);
_sockAttrib.sll_family = AF_PACKET;
_sockAttrib.sll_protocol = IFT_ETHER;
_sockAttrib.sll_ifindex = _ifr.ifr_ifindex;
_sockAttrib.sll_hatype = 0xFFFF;
_sockAttrib.sll_pkttype = PACKET_HOST;
_sockAttrib.sll_halen = 6;
_sockAttrib.sll_addr[0] = 0x00;
_sockAttrib.sll_addr[1] = 0x02;
_sockAttrib.sll_addr[2] = 0x03;
_sockAttrib.sll_addr[3] = 0x12;
_sockAttrib.sll_addr[4] = 0x34;
_sockAttrib.sll_addr[5] = 0x56;
int _sockAttribLen = sizeof(_sockAttrib);
char packet[64];
memset(packet, 0, sizeof(packet));
if (recvfrom(s, (char *)packet, sizeof(packet), 0,
(struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0)
{
printf("packet receive error.");
}
// code never reaches here
I think the way to do this is to write your own Network Service that binds to the MUX layer in the VxWorks network stack. This is reasonably well documented in the VxWorks Network Programmer's Guide and something I have done a number of times.
A custom Network Service can be configured to see all layer 2 packets received on a network interface using the MUX_PROTO_SNARF service type, which is how Wind River's own WDB protocol works, or packets with a specific protocol type.
It is also possible to add a socket interface to your custom Network Service by writing a custom socket back-end that sits between the Network Service and the socket API. This is not required if you are happy to do the application processing in the Network Service.
You haven't said which version of VxWorks you are using but I think the above holds for VxWorks 5.5.x and 6.x
Have you tried setting the socket protocol to htons(ETH_P_ALL) as prescribed in packet(7)? What you're doing doesn't have much to do with IP (although IPPROTO_RAW may be some wildcard value, dunno)
I think this is going to be a bit tougher problem to solve than you expect. Given that it's not IP at all (or apparently any other protocol anything will recognize), I don't think you'll be able to solve your problem(s) entirely with user-level code. On Linux, I think you'd need to write your own device agnostic interface driver (probably using NAPI). Getting it to work under VxWorks will almost certainly be non-trivial (more like a complete rewrite from the ground-up than what most people would think of as a port).
Have you tried confirming via Wireshark that a packet has actually been sent from the other end?
Also, for debugging, ask your hardware guys if they have a debug pin (you can attach to a logic analyzer) that they can assert when it receives a packet. Just to make sure that the hardware is getting the packets fine.
First you need to specify the protocol as ETH_P_ALL so that your interface gets all the packet. Set your socket to be on promiscuous mode. Then bind your RAW socket to an interface before you perform a receive.