From roam@orbitel.bg  Wed Apr  4 14:07:43 2001
Return-Path: <roam@orbitel.bg>
Received: from ringworld.nanolink.com (ringworld.nanolink.com [195.24.48.13])
	by hub.freebsd.org (Postfix) with SMTP id 8960537B72B
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  4 Apr 2001 14:07:40 -0700 (PDT)
	(envelope-from roam@orbitel.bg)
Received: (qmail 7542 invoked by uid 1000); 4 Apr 2001 21:06:24 -0000
Message-Id: <20010404210624.7541.qmail@ringworld.nanolink.com>
Date: 4 Apr 2001 21:06:24 -0000
From: Peter Pentchev <roam@orbitel.bg>
Reply-To: Peter Pentchev <roam@orbitel.bg>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [PATCH] a minor nit in how netstat detects 'server sockets'
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         26359
>Category:       bin
>Synopsis:       [PATCH] a minor nit in how netstat detects 'server sockets'
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bms
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Apr 04 14:10:01 PDT 2001
>Closed-Date:    Sun Sep 11 16:36:29 GMT 2005
>Last-Modified:  Sun Sep 11 16:36:29 GMT 2005
>Originator:     Peter Pentchev
>Release:        FreeBSD 4.3-RC i386
>Organization:
Orbitel JSCo.
>Environment:
4.3-RC FreeBSD 4.3-RC #43: Wed Apr 4 12:58:23 EEST 2001

>Description:

The netstat(1) manpage, as well as common sense, says that netstat, when
invoked without the -a option, should not show 'server sockets'.

What exactly is a server socket?  Is it a listening socket, or merely
a socket bound to INADDR_ANY on the local side?  If the latter, then
allow me to disagree; a server could just as well only listen on a couple
of the available interfaces.  If the former, read on.

The netstat(1) in both -stable and -current (actually ALL versions of
netstat, ever since it was imported) honors the former definition,
as demonstrated by a quick peek around line 190 of src/usr.bin/netstat/inet.c
- there are all kinds of checks there, all checking if the local address
of the socket is bound to INADDR_ANY.  This causes netstat -n to display
some server sockets, too :)

>How-To-Repeat:

Start an inetd listening on port 7200 of a single interface..

[roam@ref5 ~/fbsd/src/usr.bin/netstat]$ inetd -d -a 216.136.204.102 ~/inetd.conf
ADD : fodms proto=tcp accept=1 max=0 user=roam group=(null)class=daemon builtin=0x0 server=/usr/bin/true policy=""
inetd: fodms/tcp: ipsec initialization failed; in entrust
inetd: fodms/tcp: ipsec initialization failed; out entrust
inetd: enabling fodms, fd 4
inetd: registered /usr/bin/true on 4
^Z
[1]+  Stopped                 inetd -d -a 216.136.204.102 ~/inetd.conf

The 'normal' netstat, even without -a, shows the new server socket..

[roam@ref5 ~/fbsd/src/usr.bin/netstat]$ netstat -n | fgrep tcp4
tcp4       0      0  216.136.204.102.7200   *.*                    LISTEN
tcp4       0     20  216.136.204.102.22     216.136.204.21.3319    ESTABLISHED

A recompiled version, checking against the foreign address, only shows
the 'real' client connection (barring non-sgid-kmem kvm errors ;)

[roam@ref5 ~/fbsd/src/usr.bin/netstat]$ ./netstat -n | fgrep tcp4
netstat: kvm not available
netstat: kvm not available
tcp4       0      0  216.136.204.102.22     216.136.204.21.3319    ESTABLISHED

..and just for completeness, here's the inetd.conf used:

[roam@ref5 ~/fbsd/src/usr.bin/netstat]$ cat ~/inetd.conf
fodms stream tcp nowait roam /usr/bin/true true
[roam@ref5 ~/fbsd/src/usr.bin/netstat]$

>Fix:

Here's a kind of a workaround, not a real fix - check the foreign address
of the socket against INADDR_ANY (a bind() usually produces this kind
of socket).  I know that a 'more correct' fix would check the state
itself for TCP sockets, but for UDP sockets IMHO the correct thing would
still be checking the foreign address against INADDR_ANY.

Index: src/usr.bin/netstat/inet.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/netstat/inet.c,v
retrieving revision 1.41
diff -u -r1.41 inet.c
--- src/usr.bin/netstat/inet.c	2001/03/15 20:46:04	1.41
+++ src/usr.bin/netstat/inet.c	2001/04/04 20:33:51
@@ -189,17 +189,17 @@
 		if (!aflag &&
 		    (
 		     (af == AF_INET &&
-		      inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+		      inet_lnaof(inp->inp_faddr) == INADDR_ANY)
 #ifdef INET6
 		     || (af == AF_INET6 &&
-			 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+			 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
 #endif /* INET6 */
 		     || (af == AF_UNSPEC &&
 			 (((inp->inp_vflag & INP_IPV4) != 0 &&
-			   inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+			   inet_lnaof(inp->inp_faddr) == INADDR_ANY)
 #ifdef INET6
 			  || ((inp->inp_vflag & INP_IPV6) != 0 &&
-			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
 #endif
 			  ))
 		     ))
>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->analyzed 
State-Changed-By: bms 
State-Changed-When: Mon Jun 14 15:24:39 GMT 2004 
State-Changed-Why:  
There's definitely a bug in here somewhere. 

tcpcb->t_state probably needs to be checked for LISTEN; 
for a udp socket, the check probably needs to be for 'unbound 
to a remote address' by looking for INADDR_ANY. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26359 
Responsible-Changed-From-To: freebsd-bugs->bms 
Responsible-Changed-By: bms 
Responsible-Changed-When: Mon Jun 14 15:26:58 GMT 2004 
Responsible-Changed-Why:  
I'll take this 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26359 
State-Changed-From-To: analyzed->patched 
State-Changed-By: bms 
State-Changed-When: Wed Jun 16 07:00:29 GMT 2004 
State-Changed-Why:  
An appropriate fix has been committed to HEAD 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26359 
State-Changed-From-To: patched->closed 
State-Changed-By: rodrigc 
State-Changed-When: Sun Sep 11 16:35:46 GMT 2005 
State-Changed-Why:  
Fixed in FreeBSD 5.x and higher. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26359 
>Unformatted:
