-   Programming (
-   -   send packets with kernel routing and without kernel messing with headers (

bassdemon 02-07-2005 04:42 PM

send packets with kernel routing and without kernel messing with headers
Hey everyone. Ok I'm trying to send a packet and have the kernel do the routing for me. I have completely built the specified packet and it could be TCP, UDP, ICMP, etc...just anything on top of IP. All the headers have been created except for the ethernet layer. I want to send this to a socket and have it figure out the routing (if necessary). So if the packet is outbound it'll go to the default gateway and if it's on the internal net it'll just be send directly to the specified machine. Ok so here's what I've been doing.


if((fs=socket (PF_INET, SOCK_RAW, IPPROTO_TCP))<0)
int one = 1;
const int *val = &one;
if(setsockopt (fs, IPPROTO_IP, IP_HDRINCL, val, sizeof (one))<0)

sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = dest;
int ret=sendto(fs,data,len,0,(struct sockaddr *) &sin,sizeof (sin));

ok so basically that should create a raw socket and tell the kernel that the ip header is already done. then it'll get the previously supplied destination and send the packet. This seems to work from the program, the return value from sendto gives a positive number of the packet length indicating that it has been sent. At the same time I'm monitoring the network from my machine with Ethereal and no packet is in fact sent. If I don't include the setsockopt call I actually do get a packet on the network but it's header has been tampered with. Changing IPPROTO_TCP to IPPROTO_UDP has no same effect. And using IPPROTO_IP gives an error with setsockopt. Does anyone know what's going on here or how to do this? Any help would be appreciated. Also...what is the difference between protocol family and address family. AF_INET PF_INET etc...they seem interchangeable.


jtshaw 02-08-2005 12:25 AM

I'll try my best to answer some of your questions. I'll start off with the easy one. PF_INET is defined as AF_INET in linux/socket.h so it is in fact the same value. The comment above the PF_* defs is "/* Protocol families, same as address families. */".

I'm a bit confused by the rest... how can you send a packet with missing routing information and expect it to go anywhere? When you get the packet on the network what part of the header did it change?

obashir 02-08-2005 04:56 AM


An interesting tutorial on this at

Also you may want to look at libnet as a more convinient alternative to SOCK_RAW


bassdemon 02-08-2005 09:01 AM

that's actually the exact tutorial i've been using to get this far. And the problems I've run into are listed above. Ok as for the missing routing information question...the only information I want the kernel to fill in is the immediate destination...the ethernet layer. It has all the other routing information it needs. All IP's and ports are filled in. I just need the kernel to decide if it needs to go to the default gateway or not. So it has all the routing information. If the gateway MAC or the target machines MAC is put in the ethernet header then it will go where it needs to go. It will get dropped on the network and the MAC addr will send it to the gateway which would route it based on the IP or it will be sent immediately to the target system.

When I do get it on the network and I don't use the setsockopt for the IP header it changes a number of fields. Using IPPROTO_UDP for example changes the protocol field in IP to UDP. So the rest of the packet is interpreted as UDP even if it's not really a UDP packet. And then it would go ahead and change some data to fill in the UDP ports as it saw fit.

Yeah I didn't really want to use libnet. I've already reconstructed some of their methods. This is more for a learning exercise. I'd like to learn how to do it without relying on a library like libnet.


obashir 02-08-2005 10:42 AM


I may be able to spend some time on your code and troubleshoot if you are willing to send it across,


bassdemon 02-08-2005 06:29 PM

hey all. thanks for all the help. Also, thanks for the offer obashir. I found the problem, though. Before I was trying this I was working on the routing myself. So those packets still had an ethernet layer already on them. I bet the socket was sending the packet properly to the kernel (hence the positive value for sendto) but with the extra 14 bytes the IP header would be fubar. So the kernel was dropping the packet on the way out. That's my hypothesis anyways. Stupid mistake. Removing the first 14 bytes (the erroneous eth layer) solved the problem.


All times are GMT -5. The time now is 05:42 PM.