From owner-freebsd-hackers Sat Oct 13 6:26:53 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from segfault.kiev.ua (segfault.kiev.ua [193.193.193.4]) by hub.freebsd.org (Postfix) with ESMTP id 8CDC437B411 for ; Sat, 13 Oct 2001 06:22:43 -0700 (PDT) Received: (from uucp@localhost) by segfault.kiev.ua (8) with UUCP id QIS86992 for hackers@freebsd.org; Sat, 13 Oct 2001 16:22:39 +0300 (EEST) (envelope-from netch@iv.nn.kiev.ua) Received: (from netch@localhost) by iv.nn.kiev.ua (8.11.6/8.11.6) id f9DAwgd07449 for hackers@freebsd.org; Sat, 13 Oct 2001 13:58:42 +0300 (EEST) (envelope-from netch) Date: Sat, 13 Oct 2001 13:58:42 +0300 From: Valentin Nechayev To: hackers@freebsd.org Subject: sin_zero & bind problems Message-ID: <20011013135842.A415@iv.nn.kiev.ua> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-42: On Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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 #include #include #include #include #include #include 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