Date: Thu, 19 Feb 1998 18:21:04 +0500 From: Konstantin Chuguev <joy@urc.ac.ru> To: freebsd-hackers@FreeBSD.ORG Subject: Re: Some problems with raw IP programming Message-ID: <34EC31C0.7D68062F@urc.ac.ru> References: <199802182119.NAA24361@bubba.whistle.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Archie Cobbs wrote: > > Konstantin Chuguev writes: > ? 2. When I receive IPIP (ICMP-in-IP, pinging through a tunnel) packets > ? from the raw socket: > ? --- > ? size = recv( raw_ip, buffer, sizeof( buffer ), 0 ) ; > ? if( is_syserror( size ? 0, LOG_CRIT, "Can't read from %s", > ? "raw socket" ) ) > ? return ; > ? h_len = (unsigned)( ((struct ip *)buffer)-?ip_hl ) ?? 2 ; > ? /* log_printf( LOG_INFO, "Size=%d, ip_len=%d, h_len=%d\n", > ? size, ((struct ip *)buffer)-?ip_len, h_len ) ; */ > ? size = write( tunnel, buffer + h_len, > ? /* ((struct ip *)buffer)-?ip_len */ size - h_len ) ; > ? --- > ? h_len is equal to 20 (the correct size of the IP packet without any options); > ? size (the result of recv() or read()) is equal to 104 (20 bytes for > ? the envelope IP header, other 20 ones for the internal IP (ICMP) header, > ? other 64 for the ICMP body); > ? the ICMP packet INSIDE the IPIP header looks pretty good, BUT: > ? ((struct ip *)buffer)-?ip_len is 84 !!! i.e. EXACTLY 20 less then > ? the "size" variable and always EQUAL TO the size of the ENCLOSED IP > ? packet. > > Also, check for ntohs() and htons() as required. > Checked, got yet more strange results: --- size = read( raw_ip, buffer, sizeof( buffer ) ) ; ip_len = ((struct ip *)buffer)->ip_len ; h_len = (u_short)( ((struct ip *)buffer)->ip_hl ) << 2 ; log_printf( LOG_INFO, "Size=%d, ip_len=%d, h_len=%d, " "enc_ip_len=%d\n", size, ip_len, h_len, ((struct ip *)(buffer + h_len))->ip_len ) ; --- The result for ICMP-in-IP packet is: Feb 19 17:45:50 y ipipd[555]: Size=104, ip_len=84, h_len=20, enc_ip_len=21504 It is OK with size, h_len and enclosed_ip_len. The latter is so large because it needs to be converted from the network short format to the Intel one. After conversion it becomes 84, the real size of the default ICMP message. But the ip_len of the envelope IP header is not 104, nor it's network equivalent. It seems like the kernel itself converts that field and then subtracts the header length from it. Or the kernel just copies that field from the enclosed packet for IPPROTO_IPIP sockets. Too smart kernel, eh? :-) Is it a feature or a bug? > ? 3. Sometimes (very seldom, can happen once a week), I get a message in syslog: > ? > ? Feb 11 03:50:05 Chelyabinsk-RNOC-RR03 ipipd[6835]: Can't write to raw socket: > ? No > ? buffer space available > ? or > ? Feb 18 22:13:45 Chelyabinsk-RNOC-RR03 ipipd[17393]: Can't write to raw socket: > ? N > ? o route to host > > This is normal; you're simply writing packets faster then the kernel can > forward them. Don't know why it confuses ping though. > As I see the packets continue to pass from the tunnel to other interfaces of the router, I can be sure my read() from the raw_ip and write() to the tunnel file work. The loop and select() work as well then. But no one packet comes to the tunnel (from the /dev/tun* device, being encapsulated, to the raw IP socket). So it seems like there are no more packets from the /dev/tun* device or, more likely, packets written to the raw IP socket go to a blackhole... Sometimes temporarily, sometimes forever. Though the socket is "connected", it is not TCP, there are no timeouts, and I think, routing loss or IP buffer overflow should not cause such permanent error. -- Konstantin V. Chuguev. System administrator of Ural Regional Center of FREEnet, Joy@urc.ac.ru Chelyabinsk, Russia. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?34EC31C0.7D68062F>