From netch@segfault.kiev.ua  Fri Sep 17 10:30:52 2010
Return-Path: <netch@segfault.kiev.ua>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id BD51F1065670
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 17 Sep 2010 10:30:52 +0000 (UTC)
	(envelope-from netch@segfault.kiev.ua)
Received: from segfault.kiev.ua (segfault.kiev.ua [193.193.193.4])
	by mx1.freebsd.org (Postfix) with ESMTP id 337818FC1A
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 17 Sep 2010 10:30:51 +0000 (UTC)
Received: from segfault.kiev.ua (localhost.segfault.kiev.ua [127.0.0.1])
	by segfault.kiev.ua (8.14.4/8.14.4/8.Who.Cares) with ESMTP id o8HAICes071066;
	Fri, 17 Sep 2010 13:18:12 +0300 (EEST)
	(envelope-from netch@segfault.kiev.ua)
Received: (from netch@localhost)
	by segfault.kiev.ua (8.14.4/8.14.4/Submit) id o8HAI7QC071063;
	Fri, 17 Sep 2010 13:18:07 +0300 (EEST)
	(envelope-from netch)
Message-Id: <201009171018.o8HAI7QC071063@segfault.kiev.ua>
Date: Fri, 17 Sep 2010 13:18:07 +0300 (EEST)
From: Valentin Nechayev <netch@netch.kiev.ua>
Reply-To: Valentin Nechayev <netch@netch.kiev.ua>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: netstat doesn't print anything for SCTP sockets
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         150642
>Category:       bin
>Synopsis:       netstat(1) doesn't print anything for SCTP sockets
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-net
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 17 10:40:01 UTC 2010
>Closed-Date:    Mon Jul 25 14:24:47 UTC 2011
>Last-Modified:  Mon Jul 25 14:24:47 UTC 2011
>Originator:     Valentin Nechayev
>Release:        FreeBSD 8.1-RELEASE i386
>Organization:
Dark side of coredump
>Environment:
System: FreeBSD segfault.kiev.ua 8.1-RELEASE FreeBSD 8.1-RELEASE #0: Tue Jul 27 16:32:08 EEST 2010 root@segfault.kiev.ua:/usr/BSD/obj/usr/BSD/src/sys/sf81 i386

I was also told that the same on 7.2 and 9.0, so this is old problem.

>Description:

netstat (with mode to print sockets, either with or without -a) doesn't print
anything for active SCTP sockets.

>How-To-Repeat:

I use Python to line-by-line show though the same result is when using C.

Check before starting with socket:

$ fstat | fgrep sctp; netstat -anAW -p sctp; netstat -anAW | grep sctp
$ 

$ sysctl -b net.inet.sctp.assoclist | hd | less
00000000  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000a0

Create socket:

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 132)

Check in other terminal:

$ fstat | fgrep sctp; netstat -anAW -p sctp; netstat -anAW | grep sctp
netch    python     70548    3* internet stream sctp c58ada14
$

$ sysctl -b net.inet.sctp.assoclist | hd | less
00000000  00 00 00 00 12 00 00 00  08 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  ff ff 00 00 00 00 00 00  |..............|
00000020  00 00 dd c4 f8 18 83 e7  f7 26 84 c0 10 19 83 e7  |...&..|

[...skip rest - the only thing I shall demonstrate here there is new data]

Binding of the socket changes nothing in the fact of netstat
output absense itself.

>Fix:

>Release-Note:
>Audit-Trail:

From: Valentin Nechayev <netch@netch.kiev.ua>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/150642: netstat doesn't print anything for SCTP sockets
Date: Fri, 17 Sep 2010 13:48:35 +0300

 BTW, it prints stream socket in listening state. But I'm unable to see
 seqpacket sockets in such output:(
 
 
 -netch-
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: brucec 
Responsible-Changed-When: Sat Nov 13 08:42:55 UTC 2010 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=150642 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/150642: commit references a PR
Date: Fri, 22 Jul 2011 16:42:26 +0000 (UTC)

 Author: tuexen
 Date: Fri Jul 22 16:42:12 2011
 New Revision: 224271
 URL: http://svn.freebsd.org/changeset/base/224271
 
 Log:
   Fix the following bugs related to the SCTP support of netstat:
   * Correctly handle -a.
   * -A isn't supported.
   * Show all closed 1-to-1 and 1-to-many style sockets.
   * Show all listening 1-to-many style sockets.
   * Use consistent formatting for -W.
   
   PR: 150642
   Approved by: re@
   MFC after: 4 weeks.
 
 Modified:
   head/usr.bin/netstat/sctp.c
 
 Modified: head/usr.bin/netstat/sctp.c
 ==============================================================================
 --- head/usr.bin/netstat/sctp.c	Fri Jul 22 16:37:04 2011	(r224270)
 +++ head/usr.bin/netstat/sctp.c	Fri Jul 22 16:42:12 2011	(r224271)
 @@ -1,5 +1,6 @@
  /*-
   * Copyright (c) 2001-2007, by Weongyo Jeong. All rights reserved.
 + * Copyright (c) 2011, by Michael Tuexen. All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
 @@ -63,7 +64,6 @@ __FBSDID("$FreeBSD$");
  
  #ifdef SCTP
  
 -void	inetprint(struct in_addr *, int, const char *, int);
  static void sctp_statesprint(uint32_t state);
  
  #define	NETSTAT_SCTP_STATES_CLOSED		0x0
 @@ -102,6 +102,124 @@ struct xraddr_entry {
          LIST_ENTRY(xraddr_entry) xraddr_entries;
  };
  
 +/*
 + * Construct an Internet address representation.
 + * If numeric_addr has been supplied, give
 + * numeric value, otherwise try for symbolic name.
 + */
 +static char *
 +inetname(struct in_addr *inp)
 +{
 +	char *cp;
 +	static char line[MAXHOSTNAMELEN];
 +	struct hostent *hp;
 +	struct netent *np;
 +
 +	cp = 0;
 +	if (!numeric_addr && inp->s_addr != INADDR_ANY) {
 +		int net = inet_netof(*inp);
 +		int lna = inet_lnaof(*inp);
 +
 +		if (lna == INADDR_ANY) {
 +			np = getnetbyaddr(net, AF_INET);
 +			if (np)
 +				cp = np->n_name;
 +		}
 +		if (cp == 0) {
 +			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
 +			if (hp) {
 +				cp = hp->h_name;
 +				trimdomain(cp, strlen(cp));
 +			}
 +		}
 +	}
 +	if (inp->s_addr == INADDR_ANY)
 +		strcpy(line, "*");
 +	else if (cp) {
 +		strlcpy(line, cp, sizeof(line));
 +	} else {
 +		inp->s_addr = ntohl(inp->s_addr);
 +#define	C(x)	((u_int)((x) & 0xff))
 +		sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
 +		    C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
 +		inp->s_addr = htonl(inp->s_addr);
 +	}
 +	return (line);
 +}
 +
 +#ifdef INET6
 +static char ntop_buf[INET6_ADDRSTRLEN];
 +
 +static char *
 +inet6name(struct in6_addr *in6p)
 +{
 +	char *cp;
 +	static char line[50];
 +	struct hostent *hp;
 +	static char domain[MAXHOSTNAMELEN];
 +	static int first = 1;
 +
 +	if (first && !numeric_addr) {
 +		first = 0;
 +		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
 +		    (cp = index(domain, '.')))
 +			(void) strcpy(domain, cp + 1);
 +		else
 +			domain[0] = 0;
 +	}
 +	cp = 0;
 +	if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
 +		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
 +		if (hp) {
 +			if ((cp = index(hp->h_name, '.')) &&
 +			    !strcmp(cp + 1, domain))
 +				*cp = 0;
 +			cp = hp->h_name;
 +		}
 +	}
 +	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
 +		strcpy(line, "*");
 +	else if (cp)
 +		strcpy(line, cp);
 +	else
 +		sprintf(line, "%s",
 +			inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
 +				sizeof(ntop_buf)));
 +	return (line);
 +}
 +#endif
 +
 +static void
 +sctp_print_address(union sctp_sockstore *address, int port, int num_port)
 +{
 +	struct servent *sp = 0;
 +	char line[80], *cp;
 +	int width;
 +
 +	switch (address->sa.sa_family) {
 +	case AF_INET:
 +		sprintf(line, "%.*s.", Wflag ? 39 : 16, inetname(&address->sin.sin_addr));
 +		break;
 +#ifdef INET6
 +	case AF_INET6:
 +		sprintf(line, "%.*s.", Wflag ? 39 : 16, inet6name(&address->sin6.sin6_addr));
 +		break;
 +#endif
 +	default:
 +		sprintf(line, "%.*s.", Wflag ? 39 : 16, "");
 +		break;
 +	}
 +	cp = index(line, '\0');
 +	if (!num_port && port)
 +		sp = getservbyport((int)port, "sctp");
 +	if (sp || port == 0)
 +		sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
 +	else
 +		sprintf(cp, "%d ", ntohs((u_short)port));
 +	width = Wflag ? 45 : 22;
 +	printf("%-*.*s ", width, width, line);
 +}
 +
  static int
  sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
  {
 @@ -150,18 +268,14 @@ sctp_skip_xinpcb_ifneed(char *buf, const
  }
  
  static void
 -sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
 +sctp_process_tcb(struct xsctp_tcb *xstcb,
      char *buf, const size_t buflen, size_t *offset, int *indent)
  {
  	int i, xl_total = 0, xr_total = 0, x_max;
 -	struct sockaddr *sa;
  	struct xsctp_raddr *xraddr;
  	struct xsctp_laddr *xladdr;
  	struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
  	struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
 -#ifdef INET6
 -	struct sockaddr_in6 *in6;
 -#endif
  
  	LIST_INIT(&xladdr_head);
  	LIST_INIT(&xraddr_head);
 @@ -220,38 +334,22 @@ sctp_process_tcb(struct xsctp_tcb *xstcb
  	x_max = (xl_total > xr_total) ? xl_total : xr_total;
  	for (i = 0; i < x_max; i++) {
  		if (((*indent == 0) && i > 0) || *indent > 0)
 -			printf("%-11s ", " ");
 +			printf("%-12s ", " ");
  
  		if (xl != NULL) {
 -			sa = &(xl->xladdr->address.sa);
 -			if ((sa->sa_family) == AF_INET)
 -				inetprint(&((struct sockaddr_in *)sa)->sin_addr,
 -				    htons(xstcb->local_port),
 -				    name, numeric_port);
 -#ifdef INET6
 -			else {
 -				in6 = (struct sockaddr_in6 *)sa;
 -				inet6print(&in6->sin6_addr,
 -				    htons(xstcb->local_port),
 -				    name, numeric_port);
 +			sctp_print_address(&(xl->xladdr->address),
 +			    htons(xstcb->local_port), numeric_port);
 +		} else {
 +			if (Wflag) {
 +				printf("%-45s ", " ");
 +			} else {
 +				printf("%-22s ", " ");
  			}
 -#endif
  		}
  
  		if (xr != NULL && !Lflag) {
 -			sa = &(xr->xraddr->address.sa);
 -			if ((sa->sa_family) == AF_INET)
 -				inetprint(&((struct sockaddr_in *)sa)->sin_addr,
 -				    htons(xstcb->remote_port),
 -				    name, numeric_port);
 -#ifdef INET6
 -			else {
 -				in6 = (struct sockaddr_in6 *)sa;
 -				inet6print(&in6->sin6_addr,
 -				    htons(xstcb->remote_port),
 -				    name, numeric_port);
 -			}
 -#endif
 +			sctp_print_address(&(xr->xraddr->address),
 +			    htons(xstcb->remote_port), numeric_port);
  		}
  
  		if (xl != NULL)
 @@ -285,53 +383,21 @@ out:
  	}
  }
  
 -#ifdef SCTP_DEBUG
 -uint32_t sctp_pdup[64];
 -int sctp_pcnt = 0;
 -#endif
 -
  static void
 -sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
 +sctp_process_inpcb(struct xsctp_inpcb *xinpcb,
      char *buf, const size_t buflen, size_t *offset)
  {
 -	int offset_backup, indent = 0, xladdr_total = 0, is_listening = 0;
 +	int indent = 0, xladdr_total = 0, is_listening = 0;
  	static int first = 1;
 -	char *tname;
 +	char *tname, *pname;
  	struct xsctp_tcb *xstcb;
  	struct xsctp_laddr *xladdr;
 -	struct sockaddr *sa;
 -#ifdef INET6
 -	struct sockaddr_in6 *in6;
 -#endif
 +	size_t offset_laddr;
 +	int process_closed;
  
 -	if ((xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE) ==
 -	    SCTP_PCB_FLAGS_TCPTYPE && xinpcb->maxqlen > 0)
 +	if (xinpcb->maxqlen > 0)
  		is_listening = 1;
  
 -	if (!Lflag && !is_listening &&
 -	    !(xinpcb->flags & SCTP_PCB_FLAGS_CONNECTED)) {
 -#ifdef SCTP_DEBUG
 -		int i, found = 0;
 -
 -		for (i = 0; i < sctp_pcnt; i++) {
 -			if (sctp_pdup[i] == xinpcb->flags) {
 -				found = 1;
 -				break;
 -			}
 -		}
 -		if (!found) {
 -			sctp_pdup[sctp_pcnt++] = xinpcb->flags;
 -			if (sctp_pcnt >= 64)
 -				sctp_pcnt = 0;
 -			printf("[0x%08x]", xinpcb->flags);
 -		}
 -#endif
 -		offset_backup = *offset;
 -		if (!sctp_skip_xinpcb_ifneed(buf, buflen, offset))
 -			return;
 -		*offset = offset_backup;
 -	}
 -
  	if (first) {
  		if (!Lflag) {
  			printf("Active SCTP associations");
 @@ -340,90 +406,115 @@ sctp_process_inpcb(struct xsctp_inpcb *x
  		} else
  			printf("Current listen queue sizes (qlen/maxqlen)");
  		putchar('\n');
 -		if (Aflag)
 -			printf("%-8.8s ", "Socket");
  		if (Lflag)
 -			printf("%-5.5s %-5.5s %-8.8s %-22.22s\n",
 +			printf("%-6.6s %-5.5s %-8.8s %-22.22s\n",
  			    "Proto", "Type", "Listen", "Local Address");
  		else
 -			printf((Aflag && !Wflag) ?
 -			    "%-5.5s %-5.5s %-18.18s %-18.18s %s\n" :
 -			    "%-5.5s %-5.5s %-22.22s %-22.22s %s\n",
 -			    "Proto", "Type",
 -			    "Local Address", "Foreign Address",
 -			    "(state)");
 +			if (Wflag)
 +				printf("%-6.6s %-5.5s %-45.45s %-45.45s %s\n",
 +				    "Proto", "Type",
 +				    "Local Address", "Foreign Address",
 +				    "(state)");
 +			else
 +				printf("%-6.6s %-5.5s %-22.22s %-22.22s %s\n",
 +				    "Proto", "Type",
 +				    "Local Address", "Foreign Address",
 +				    "(state)");
  		first = 0;
  	}
 -	if (Lflag && xinpcb->maxqlen == 0) {
 +	xladdr = (struct xsctp_laddr *)(buf + *offset);
 +	if (Lflag && !is_listening) {
  		sctp_skip_xinpcb_ifneed(buf, buflen, offset);
  		return;
  	}
 -	if (Aflag)
 -		printf("%8lx ", (u_long)xinpcb);
  
 -	printf("%-5.5s ", name);
 +	if (xinpcb->flags & SCTP_PCB_FLAGS_BOUND_V6) {
 +		/* Can't distinguish between sctp46 and sctp6 */
 +		pname = "sctp46";
 +	} else {
 +		pname = "sctp4";
 +	}
  
  	if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
  		tname = "1to1";
  	else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
  		tname = "1toN";
  	else
 -		return;
 -
 -	printf("%-5.5s ", tname);
 +		tname = "????";
  
  	if (Lflag) {
  		char buf1[9];
  
  		snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
 +		printf("%-6.6s %-5.5s ", pname, tname);
  		printf("%-8.8s ", buf1);
  	}
 -	/*
 -	 * process the local address.  This routine are used for Lflag.
 -	 */
 +
 +	offset_laddr = *offset;
 +	process_closed = 0;
 +retry:
  	while (*offset < buflen) {
  		xladdr = (struct xsctp_laddr *)(buf + *offset);
  		*offset += sizeof(struct xsctp_laddr);
 -		if (xladdr->last == 1)
 +		if (xladdr->last) {
 +			if (aflag && !Lflag && (xladdr_total == 0) && process_closed) {
 +				printf("%-6.6s %-5.5s ", pname, tname);
 +				if (Wflag) {
 +					printf("%-91.91s CLOSED", " ");
 +				} else {
 +					printf("%-45.45s CLOSED", " ");
 +				}
 +			}
 +			if (process_closed || is_listening) {
 +				putchar('\n');
 +			}
  			break;
 +		}
  
 -		if (!Lflag && !is_listening)
 +		if (!Lflag && !is_listening && !process_closed)
  			continue;
  
 -		if (xladdr_total != 0)
 +		if (xladdr_total == 0) {
 +			printf("%-6.6s %-5.5s ", pname, tname);
 +		} else {
  			putchar('\n');
 -		if (xladdr_total > 0)
  			printf((Lflag) ?
 -			    "%-20.20s " : "%-11.11s ", " ");
 -
 -		sa = &(xladdr->address.sa);
 -		if ((sa->sa_family) == AF_INET)
 -			inetprint(&((struct sockaddr_in *)sa)->sin_addr,
 -			    htons(xinpcb->local_port), name, numeric_port);
 -#ifdef INET6
 -		else {
 -			in6 = (struct sockaddr_in6 *)sa;
 -			inet6print(&in6->sin6_addr,
 -			    htons(xinpcb->local_port), name, numeric_port);
 +			    "%-21.21s " : "%-12.12s ", " ");
 +		}
 +		sctp_print_address(&(xladdr->address),
 +		    htons(xinpcb->local_port), numeric_port);
 +		if (aflag && !Lflag && xladdr_total == 0) {
 +			if (Wflag) {
 +				if (process_closed) {
 +					printf("%-45.45s CLOSED", " ");
 +				} else {
 +					printf("%-45.45s LISTEN", " ");
 +				}
 +			} else {
 +				if (process_closed) {
 +					printf("%-22.22s CLOSED", " ");
 +				} else {
 +					printf("%-22.22s LISTEN", " ");
 +				}
 +			}
  		}
 -#endif
 -
 -		if (!Lflag && xladdr_total == 0 && is_listening == 1)
 -			printf("%-22.22s LISTEN", " ");
 -
  		xladdr_total++;
  	}
  
  	xstcb = (struct xsctp_tcb *)(buf + *offset);
  	*offset += sizeof(struct xsctp_tcb);
 +	if (aflag && (xladdr_total == 0) && xstcb->last && !process_closed) {
 +		process_closed = 1;
 +		*offset = offset_laddr;
 +		goto retry;
 +	}
  	while (xstcb->last == 0 && *offset < buflen) {
 -		sctp_process_tcb(xstcb, name, buf, buflen, offset, &indent);
 +		printf("%-6.6s %-5.5s ", pname, tname);
 +		sctp_process_tcb(xstcb, buf, buflen, offset, &indent);
  		indent++;
  		xstcb = (struct xsctp_tcb *)(buf + *offset);
  		*offset += sizeof(struct xsctp_tcb);
  	}
 -
 -	putchar('\n');
  }
  
  /*
 @@ -461,7 +552,7 @@ sctp_protopr(u_long off __unused,
  	xinpcb = (struct xsctp_inpcb *)(buf + offset);
  	offset += sizeof(struct xsctp_inpcb);
  	while (xinpcb->last == 0 && offset < len) {
 -		sctp_process_inpcb(xinpcb, name, buf, (const size_t)len,
 +		sctp_process_inpcb(xinpcb, buf, (const size_t)len,
  		    &offset);
  
  		xinpcb = (struct xsctp_inpcb *)(buf + offset);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->closed 
State-Changed-By: tuexen 
State-Changed-When: Mon Jul 25 14:23:48 UTC 2011 
State-Changed-Why:  
Fixed in  http://svn.freebsd.org/changeset/base/224271 

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