Date: Sat, 13 Oct 2001 13:58:42 +0300 From: Valentin Nechayev <netch@segfault.kiev.ua> To: hackers@freebsd.org Subject: sin_zero & bind problems Message-ID: <20011013135842.A415@iv.nn.kiev.ua>
next in thread | raw e-mail | index | archive | help
The following was initially formatted as PR, but I suppose it is reasonable to discuss first here. There were some vague mentions that sin_zero field of struct sockaddr_in may be used in future for some extensions; but this future is already expired;) without any real step. If the verdict will be to keep current behavior, it should be strictly documented to remove this permanent rake field. >Description: If bind() syscall is called for PF_INET socket with address another than INADDR_ANY, and sin_zero field in addr parameter is not filled with zero (this is common programming problem), bind() will fail. Source of failure is ifa_ifwithaddr() in src/sys/net/if.c, which compares structure contents for all their length (determined from sa_len field). ifa_ifwithaddr() is called by in_pcbbind(), which performs all work of comparing addresses and ports. The good programming style requires filling of all structures, passed to kernel or any subsystem with non-transparent behavoir, with null bytes. Stevens' examples also performs zero-filling before use. But I never saw an _explicit_ rule to perform such filling (all in /usr/share/doc/ and Stevens' books were specially searched). During last month, I saw 4 complaints to opaque and misunderstandable behavior of FreeBSD kernel in this place - 2 from Usenet and 2 from my workmates; in each case, complainer was totally confused: he fills all described fields - sin_family, sin_port and sin_addr - and what hell? ;| The needed fix is too simple, and I supposed it is better to apply it once, than continue to confuse people. That's why I also consider this as software bug, and tagged this report as sw-bug, not change-request. Another mentions found with Google: ==={{{ freebsd-current archive FROM: Mike Smith DATE: 11/25/1997 20:31:19 SUBJECT: RE: tcp/ip buglet ? ===}}} FreeBSD PR kern/9309 by ru@ NetBSD PR kern/2972 >How-To-Repeat: #define FILLER 0xDE #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <err.h> #include <stdio.h> #include <string.h> int main() { int s; struct sockaddr_in sia; s = socket( PF_INET, SOCK_STREAM, 0 ); if( s == -1 ) err( 1, "socket()" ); memset( &sia, FILLER, sizeof sia ); sia.sin_family = AF_INET; sia.sin_port = htons( 4455 ); sia.sin_addr.s_addr = htonl( 0x7f000001 ); if( bind( s, ( struct sockaddr* ) &sia, sizeof sia ) < 0 ) err( 1, "bind()" ); puts( "all ok" ); return 0; } With any FILLER value other than 0, bind() will fail with EADDRNOTAVAIL. Also note than sin_len field is refilled in getsockaddr(), and garbage in it in userland copy does not matter. >Fix: --- src/sys/netinet/in_pcb.c.0 Sat Sep 22 17:41:17 2001 +++ src/sys/netinet/in_pcb.c Sat Sep 22 17:44:59 2001 @@ -198,6 +198,7 @@ sin = (struct sockaddr_in *)nam; if (nam->sa_len != sizeof (*sin)) return (EINVAL); + bzero(&sin->sin_zero, sizeof(sin->sin_zero)); #ifdef notdef /* * We should check the family, but old programs /netch 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?20011013135842.A415>