************************************************************************
Modifying the linux kernel to get proper SOCK_RAW IPPROTO_RAW behaviour.
************************************************************************

This is fairly trivial, AFAIK the only reason that linux doesn't do the
same as BSD 4.4lite in this respect, is because the lack of documention
describing what *should* actually be done.  Now that I have pointed out
that linux shouldn't overwrite the source address I hope that future
linux kernels should behave properly, however in the meantime, one of
the linux authors kindly told me how I could modify the kernel in order
to get the behaviour I wanted.

The only problem with this mod is that some (very stupid) linux programs,
namely traceroute, will still expect the linux kernel to (incorrectly)
overwrite certain IP fields (such as the total length field an the source
IP address) - In short: traceroute wont work.

The latest kernels at the time of writing are 1.2.13 and 1.3.53, if
you have later kernels than these it is work checking that the problem
hasn't already been fixed.

OK, on to the mod, this should work fine for 1.3.14, I expect other
versions should be similar......

Firstly save a copy of raw.c, just incase you want to put things back
to how they were:

	cd /usr/src/linux/net/ipv4
	cp raw.c raw.c.old

Then edit raw.c.............

The offending function is raw_getrawfrag(), all it really needs to do is
what raw_getfrag() does (i.e. the 'memcpy_fromfs'), although I've filled
in some of the fields like BSD would.

Simply replace the raw_getrawfrag() function with:

 
static void raw_getrawfrag(void *p, int saddr, char *to, unsigned int offset, unsigned int fraglen)
{
	memcpy_fromfs(to, (unsigned char *)p+offset, fraglen);
	if(offset==0)
	{
		struct iphdr *iph=(struct iphdr *)to;

		/* if source address is 0 (or INADDR_ANY), should the source address be filled in???? - Arny */
		if(iph->saddr==0) iph->saddr=saddr;

		/*
	 	 *	Deliberate breach of modularity to keep 
	 	 *	ip_build_xmit clean (well less messy).
		 */
		/* if id is 0 kernel fills in id, this is definately what BSD4.4lite does - Arny */
		if(iph->id==0) iph->id = htons(ip_id_count++);

		/* if checksum is 0 kernel calculates and fills in checksum, I'm not sure but I think this the proper thing to do - Arny */
		if(iph->check==0) iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
	}
}


Then recompile the kernel (although make sure that this part *is* actually
recompiled).  Like I say this should work for 1.3.14, I've not tried it
with any other versions yet (perhaps I should, libpcap seems to crash
1.3.14 when I use it).

Many thanks to the aforementioned linux author.

Finally, I'm not responsible for anything this does.

Arny - cs6171@scitsc.wlv.ac.uk

			http://www.scit.wlv.ac.uk/~cs6171/hack/index.html

