Skip site navigation (1)Skip section navigation (2)
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>