Subject: raw socket at link level
To: 'tech-net@netbsd.org' <tech-net@netbsd.org>
From: James Braswell <James.Braswell@quantum.com>
List: tech-net
Date: 03/08/1999 09:06:05
I am trying to write to a raw socket, providing the ether_header, ip header,
udp header, the usr data.  I make the following function calls to set up and
use the socket:

	if ( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
	{
		syslog (LOG_INFO, "sendraw: socket error %d", errno);
		return;
	}

	if ( setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &optval, sizeof
(optval)) < 0 )
	{
		syslog (LOG_INFO, "sendraw: setsocketopt error %d", errno);
		return;
	}

	bzero ((char*)&name, sizeof (name));
	dpp = (struct sockaddr_in*)&name;
	dpp->sin_family = AF_INET;
	dpp->sin_port = 61166;		// arbitrarily picked
	dpp->sin_len = sizeof(struct sockaddr_in);

	if (bind ( sock, &name, sizeof (struct sockaddr)) < 0)
	{
		syslog (LOG_INFO, "sendraw: bind sock error %d", errno);
		return;
	}

the headers are setup as follows:

ether_header

	for (i = 0; i < ETHER_ADDR_LEN; i++) 
	{
		ep->ether_dhost[i] = 0xff;	// broadcast
		ep->ether_shost[i] = ourhp->our_etherAddr[i];
	}
	ep->ether_type = htons( ETHERTYPE_IP);
ip header
	ip = (struct ip*)(buf + sizeof (struct ether_header));
	ip->ip_v = 4;
//	ip->ip_hl = htons(sizeof (struct ip) >> 2);
	ip->ip_hl = sizeof (struct ip) >> 2;
have tried both of the above

	ip->ip_tos = 0; //IPTOS_LOWDELAY;
//	ip->ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) +
datalen);
	ip->ip_len = sizeof(struct ip) + sizeof(struct udphdr) + datalen;
have tried both of the above

	ip->ip_id = 0;
	ip->ip_off = 0;
	ip->ip_ttl = 16;
	ip->ip_p = IPPROTO_UDP;
	ip->ip_src.s_addr = our_addr->our_ipAddr.s_addr;
// from
	ip->ip_dst.s_addr = 0xffffffff;
// to - broadcast
	/* Checksum the IP header... */
	ip->ip_sum = 0;
	ip->ip_sum = htons(chk_sum ((unsigned char *)ip, sizeof (struct ip),
0));
//	ip->ip_sum = chk_sum ((unsigned char *)ip, sizeof (struct ip), 0);
I have tried both of the above

udp hdr
	udp = (struct udphdr*)(buf + sizeof(struct ether_header) + sizeof
(struct ip));
	udp->uh_sport = src_port;
	udp->uh_dport = dest_port
//	udp->uh_ulen = htons(sizeof(struct udphdr) + datalen);
	udp->uh_ulen = sizeof(struct udphdr) + datalen;
have tried both of the above

	udp->uh_sum = 0;
//	udp->uh_sum = chk_sum ((unsigned char *)udp, sizeof (struct udphdr),
0);
	udp->uh_sum = htons (chk_sum ((unsigned char *)udp, sizeof (struct
udphdr), 0));
have tried both the above

	/* add usr data after headers */
	cp = (char*) (buf + hdrlen);
	bcopy(pData, cp, datalen);

	dpp = (struct sockaddr_in*)&source;
	dpp->sin_addr.s_addr = 0xffffffff;		
	sap = (struct sockaddr*)dpp;
	
	ret = sendto (sock, buf, hdrlen + datalen, 0, sap, sizeof (struct
sockaddr));
	if (ret < 0)
	{
		syslog (LOG_INFO, "sendto error return %d", errno);
	}

the error return is EINVAL (22): "The total length of the I/O is more than
can be expressed by the ssize_t return value."

hdrlen = 42
datalen = 132

Does anyone see the problem(s)??

regards
jim Braswell