Subject: Re: strangeness while using SOCK_RAW
To: Eric Auge <eau@phear.org>
From: Brian Buhrow <buhrow@lothlorien.nfbcal.org>
List: tech-net
Date: 02/09/2007 09:51:27
	Hello.  If it helps, here is some user-space code I'm using under
NetBSD and FreeBSD which uses raw sockets.  With raw sockets, you get the
IP header from the kernel on reception, but it's not required that you
provide a full header on transmission.  In fact, you can't, unless you use
the setsockopt, IP_HDRINCL, to tell the kernel that you, the user, will
provide the full IP header for packets you send.  Even then, the kernel
will calculate the checksum for you, and set the len field on the packet
before it puts it on the wire.
	I very much doubt you need to change things in the kernel to get
openospfd to run under NetBSD, and things should be pretty close to working
with no changes at all to the application code.

Here are my snippets.

I hope they help.

[code to send data to the network]
	bzero(&sin, sizeof(sin));
	sin.sin_family = AF_INET;
	sinlen = sizeof(sin);
	intlen = sizeof(int);
[...]
			if (sendto(tunnelsock, inbuf, bytesread, 0, 
			(struct sockaddr *)&sin, sinlen) != bytesread) {
				syslog(LOG_CRIT,"function: sendto: %m");
			}

[...]

[Code to receive data from the network using raw sockets]
		bzero(&sin, sizeof(sin));
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr = htonl(INADDR_ANY);
		sin.sin_port = htons(0);
		sinlen = sizeof(sin);
		if (bind(tunnelsock, (struct socaddr *)&sin, sinlen) < 0) {
			syslog(LOG_CRIT,"overlan: bind: %m");
			return(1); /*Should never happen*/
		}
	sinlen = sizeof(sin);
	bytesread = recvfrom(tunnelsock, inbuf, 3000, 0, &sin, &sinlen);
	if (bytesread < 0) {
		syslog(LOG_CRIT,"function: %m");
		return(1); /*Should never happen*/
	}
	inlen = bytesread - sizeof(struct ip);
	indata = inbuf + sizeof(struct ip);
 [...]