svn commit: r303267 - in stable/11: sys/netinet usr.bin/netstat

Michael Tuexen tuexen at FreeBSD.org
Sun Jul 24 14:50:18 UTC 2016


Author: tuexen
Date: Sun Jul 24 14:50:16 2016
New Revision: 303267
URL: https://svnweb.freebsd.org/changeset/base/303267

Log:
  MFC r302904:
  Fix a bug which results in a core dump when running netstat with
  the -W option and having a listening SCTP socket.
  The bug was introduced in r279122 when adding support for libxo.
  
  MFC r302907:
  When calling netstat -Laptcp the local address values are not aligned
  with the corresponding entry in the table header. r295136
  increased the value width from 14 to 32 without the corresponding
  change to the table header. This commit adds the change to the table
  header width.
  
  MFC r302917:
  Ensure that the -a, -W, -L options for SCTP behave similar
  as for TCP.
  
  MFC r302928:
  Address a potential memory leak found a the clang static code analyzer
  running on the userland stack.
  
  MFC r302930:
  Don't free a data chunk twice.
  Found by the clang static code analyzer running for the userland stack.
  
  MFC r302935:
  Deal with a portential memory allocation failure, which was reported
  by the clang static code analyzer.
  Joint work with rrs at .
  
  MFC r302942:
  Add missing sctps_reasmusrmsgs counter.
  Joint work with rrs at .
  
  MFC r302945:
  Don't duplicate code for SCTP, just use the ones used for UDP and TCP.
  This fixes a bug with link local addresses. This will require and
  upcoming change in the kernel to bring SCTP to the same behaviour
  as UDP and TCP.
  
  MFC r302949:
  Fix the PR-SCTP behaviour.
  This is done by rrs at .
  
  MFC r302950:
  Add a constant required by RFC 7496.
  
  MFC r303024:
  netstat and sockstat expect the IPv6 link local addresses to
  have an embedded scope. So don't recover.
  
  MFC r303025:
  Use correct order of conditions to avoid NULL deref.
  
  MFC r303073:
  Fix a bug in deferred stream reset processing which results
  in using a length field before it is set.
  Thanks to Taylor Brandstetter for reporting the issue and
  providing a fix.
  
  Approved by:	re (kib)

Modified:
  stable/11/sys/netinet/sctp_auth.c
  stable/11/sys/netinet/sctp_constants.h
  stable/11/sys/netinet/sctp_header.h
  stable/11/sys/netinet/sctp_indata.c
  stable/11/sys/netinet/sctp_output.c
  stable/11/sys/netinet/sctp_sysctl.c
  stable/11/sys/netinet/sctp_uio.h
  stable/11/usr.bin/netstat/inet.c
  stable/11/usr.bin/netstat/sctp.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet/sctp_auth.c
==============================================================================
--- stable/11/sys/netinet/sctp_auth.c	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_auth.c	Sun Jul 24 14:50:16 2016	(r303267)
@@ -542,7 +542,7 @@ sctp_insert_sharedkey(struct sctp_keyhea
 		}
 	}
 	/* shouldn't reach here */
-	return (0);
+	return (EINVAL);
 }
 
 void
@@ -622,8 +622,11 @@ sctp_copy_skeylist(const struct sctp_key
 	LIST_FOREACH(skey, src, next) {
 		new_skey = sctp_copy_sharedkey(skey);
 		if (new_skey != NULL) {
-			(void)sctp_insert_sharedkey(dest, new_skey);
-			count++;
+			if (sctp_insert_sharedkey(dest, new_skey)) {
+				sctp_free_sharedkey(new_skey);
+			} else {
+				count++;
+			}
 		}
 	}
 	return (count);

Modified: stable/11/sys/netinet/sctp_constants.h
==============================================================================
--- stable/11/sys/netinet/sctp_constants.h	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_constants.h	Sun Jul 24 14:50:16 2016	(r303267)
@@ -345,6 +345,7 @@ __FBSDID("$FreeBSD$");
 #define SCTP_RTT_FROM_NON_DATA 0
 #define SCTP_RTT_FROM_DATA     1
 
+#define PR_SCTP_UNORDERED_FLAG 0x0001
 
 /* IP hdr (20/40) + 12+2+2 (enet) + sctp common 12 */
 #define SCTP_FIRST_MBUF_RESV 68

Modified: stable/11/sys/netinet/sctp_header.h
==============================================================================
--- stable/11/sys/netinet/sctp_header.h	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_header.h	Sun Jul 24 14:50:16 2016	(r303267)
@@ -397,7 +397,7 @@ struct sctp_strseq {
 
 struct sctp_strseq_mid {
 	uint16_t stream;
-	uint16_t reserved;
+	uint16_t flags;
 	uint32_t msg_id;
 };
 

Modified: stable/11/sys/netinet/sctp_indata.c
==============================================================================
--- stable/11/sys/netinet/sctp_indata.c	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_indata.c	Sun Jul 24 14:50:16 2016	(r303267)
@@ -753,7 +753,7 @@ sctp_handle_old_data(struct sctp_tcb *st
 	 */
 	struct sctp_tmit_chunk *chk, *lchk, *tchk;
 	uint32_t fsn;
-	struct sctp_queued_to_read *nc = NULL;
+	struct sctp_queued_to_read *nc;
 	int cnt_added;
 
 	if (control->first_frag_seen == 0) {
@@ -768,6 +768,11 @@ restart:
 	TAILQ_FOREACH_SAFE(chk, &control->reasm, sctp_next, lchk) {
 		if (chk->rec.data.fsn_num == fsn) {
 			/* Ok lets add it */
+			sctp_alloc_a_readq(stcb, nc);
+			if (nc == NULL) {
+				break;
+			}
+			memset(nc, 0, sizeof(struct sctp_queued_to_read));
 			TAILQ_REMOVE(&control->reasm, chk, sctp_next);
 			sctp_add_chk_to_control(control, strm, stcb, asoc, chk);
 			fsn++;
@@ -781,7 +786,6 @@ restart:
 					 * on the control queue to a new
 					 * control.
 					 */
-					sctp_alloc_a_readq(stcb, nc);
 					sctp_build_readq_entry_from_ctl(nc, control);
 					tchk = TAILQ_FIRST(&control->reasm);
 					if (tchk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG) {
@@ -819,6 +823,7 @@ restart:
 				if (control->on_strm_q) {
 					TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
 					control->on_strm_q = 0;
+					SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
 				}
 				if (control->on_read_q == 0) {
 					sctp_add_to_readq(stcb->sctp_ep, stcb, control,
@@ -826,16 +831,19 @@ restart:
 					    SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
 				}
 				sctp_wakeup_the_read_socket(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
-				if ((nc) && (nc->first_frag_seen)) {
+				if ((nc->first_frag_seen) && !TAILQ_EMPTY(&nc->reasm)) {
 					/*
 					 * Switch to the new guy and
 					 * continue
 					 */
 					control = nc;
-					nc = NULL;
 					goto restart;
+				} else {
+					sctp_free_a_readq(stcb, nc);
 				}
 				return (1);
+			} else {
+				sctp_free_a_readq(stcb, nc);
 			}
 		} else {
 			/* Can't add more */
@@ -961,11 +969,6 @@ place_chunk:
 			 * should not happen since the FSN is a TSN and it
 			 * should have been dropped earlier.
 			 */
-			if (chk->data) {
-				sctp_m_freem(chk->data);
-				chk->data = NULL;
-			}
-			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
 			sctp_abort_in_reasm(stcb, control, chk,
 			    abort_flag,
 			    SCTP_FROM_SCTP_INDATA + SCTP_LOC_5);
@@ -1026,6 +1029,7 @@ sctp_deliver_reasm_check(struct sctp_tcb
 					    control, control->on_strm_q);
 				}
 #endif
+				SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
 				TAILQ_REMOVE(&strm->uno_inqueue, control, next_instrm);
 				control->on_strm_q = 0;
 			}
@@ -1080,6 +1084,7 @@ done_un:
 					    control, control->on_strm_q);
 				}
 #endif
+				SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
 				TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
 				control->on_strm_q = 0;
 			}
@@ -1125,6 +1130,7 @@ deliver_more:
 						    control, control->on_strm_q);
 					}
 #endif
+					SCTP_STAT_INCR_COUNTER64(sctps_reasmusrmsgs);
 					TAILQ_REMOVE(&strm->inqueue, control, next_instrm);
 					control->on_strm_q = 0;
 				}
@@ -5277,10 +5283,11 @@ sctp_kick_prsctp_reorder_queue(struct sc
 	}
 }
 
+
 static void
 sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
     struct sctp_association *asoc,
-    uint16_t stream, uint32_t seq)
+    uint16_t stream, uint32_t seq, int ordered, int old)
 {
 	struct sctp_queued_to_read *control;
 	struct sctp_stream_in *strm;
@@ -5295,7 +5302,7 @@ sctp_flush_reassm_for_str_seq(struct sct
 	 * queue.
 	 */
 	strm = &asoc->strmin[stream];
-	control = find_reasm_entry(strm, (uint32_t) seq, 0, 0);
+	control = find_reasm_entry(strm, (uint32_t) seq, ordered, old);
 	if (control == NULL) {
 		/* Not found */
 		return;
@@ -5427,6 +5434,7 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 		unsigned int num_str;
 		uint32_t sequence;
 		uint16_t stream;
+		uint16_t ordered, flags;
 		int old;
 		struct sctp_strseq *stseq, strseqbuf;
 		struct sctp_strseq_mid *stseq_m, strseqbuf_m;
@@ -5452,6 +5460,12 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 				}
 				stream = ntohs(stseq_m->stream);
 				sequence = ntohl(stseq_m->msg_id);
+				flags = ntohs(stseq_m->flags);
+				if (flags & PR_SCTP_UNORDERED_FLAG) {
+					ordered = 0;
+				} else {
+					ordered = 1;
+				}
 			} else {
 				stseq = (struct sctp_strseq *)sctp_m_getptr(m, offset,
 				    sizeof(struct sctp_strseq),
@@ -5462,6 +5476,7 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 				}
 				stream = ntohs(stseq->stream);
 				sequence = (uint32_t) ntohs(stseq->sequence);
+				ordered = 1;
 			}
 			/* Convert */
 
@@ -5487,7 +5502,7 @@ sctp_handle_forward_tsn(struct sctp_tcb 
 				asoc->fragmented_delivery_inprogress = 0;
 			}
 			strm = &asoc->strmin[stream];
-			sctp_flush_reassm_for_str_seq(stcb, asoc, stream, sequence);
+			sctp_flush_reassm_for_str_seq(stcb, asoc, stream, sequence, ordered, old);
 			TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) {
 				if ((ctl->sinfo_stream == stream) &&
 				    (ctl->sinfo_ssn == sequence)) {

Modified: stable/11/sys/netinet/sctp_output.c
==============================================================================
--- stable/11/sys/netinet/sctp_output.c	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_output.c	Sun Jul 24 14:50:16 2016	(r303267)
@@ -10383,7 +10383,7 @@ sctp_fill_in_rest:
 				/* no more to look at */
 				break;
 			}
-			if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) {
+			if ((at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) && old) {
 				/* We don't report these */
 				continue;
 			}
@@ -10504,7 +10504,7 @@ sctp_fill_in_rest:
 			tp1 = TAILQ_NEXT(at, sctp_next);
 			if (tp1 == NULL)
 				break;
-			if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED) {
+			if (old && (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)) {
 				/* We don't report these */
 				i--;
 				at = tp1;
@@ -10519,8 +10519,11 @@ sctp_fill_in_rest:
 				strseq++;
 			} else {
 				strseq_m->stream = ntohs(at->rec.data.stream_number);
-				strseq_m->reserved = ntohs(0);
 				strseq_m->msg_id = ntohl(at->rec.data.stream_seq);
+				if (at->rec.data.rcv_flags & SCTP_DATA_UNORDERED)
+					strseq_m->flags = ntohs(PR_SCTP_UNORDERED_FLAG);
+				else
+					strseq_m->flags = 0;
 				strseq_m++;
 			}
 			at = tp1;
@@ -11937,7 +11940,6 @@ sctp_send_deferred_reset_response(struct
 		return;
 	}
 	SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
-	sctp_add_stream_reset_result(chk, ent->seq, response);
 	/* setup chunk parameters */
 	chk->sent = SCTP_DATAGRAM_UNSENT;
 	chk->snd_count = 0;
@@ -11952,6 +11954,7 @@ sctp_send_deferred_reset_response(struct
 	ch->chunk_length = htons(chk->book_size);
 	atomic_add_int(&chk->whoTo->ref_count, 1);
 	SCTP_BUF_LEN(chk->data) = chk->send_size;
+	sctp_add_stream_reset_result(chk, ent->seq, response);
 	/* insert the chunk for sending */
 	TAILQ_INSERT_TAIL(&asoc->control_send_queue,
 	    chk,

Modified: stable/11/sys/netinet/sctp_sysctl.c
==============================================================================
--- stable/11/sys/netinet/sctp_sysctl.c	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_sysctl.c	Sun Jul 24 14:50:16 2016	(r303267)
@@ -279,15 +279,6 @@ sctp_sysctl_copy_out_local_addresses(str
 						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
 							if (local_scope == 0)
 								continue;
-							if (sin6->sin6_scope_id == 0) {
-								/*
-								 * bad link
-								 * local
-								 * address
-								 */
-								if (sa6_recoverscope(sin6) != 0)
-									continue;
-							}
 						}
 						if ((site_scope == 0) && (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)))
 							continue;

Modified: stable/11/sys/netinet/sctp_uio.h
==============================================================================
--- stable/11/sys/netinet/sctp_uio.h	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/sys/netinet/sctp_uio.h	Sun Jul 24 14:50:16 2016	(r303267)
@@ -259,7 +259,8 @@ struct sctp_snd_all_completes {
 /* The lower four bits is an enumeration of PR-SCTP policies */
 #define SCTP_PR_SCTP_NONE 0x0000/* Reliable transfer */
 #define SCTP_PR_SCTP_TTL  0x0001/* Time based PR-SCTP */
-#define SCTP_PR_SCTP_BUF  0x0002/* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_PRIO 0x0002/* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_BUF  SCTP_PR_SCTP_PRIO	/* For backwards compatibility */
 #define SCTP_PR_SCTP_RTX  0x0003/* Number of retransmissions based PR-SCTP */
 #define SCTP_PR_SCTP_MAX  SCTP_PR_SCTP_RTX
 #define SCTP_PR_SCTP_ALL  0x000f/* Used for aggregated stats */

Modified: stable/11/usr.bin/netstat/inet.c
==============================================================================
--- stable/11/usr.bin/netstat/inet.c	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/usr.bin/netstat/inet.c	Sun Jul 24 14:50:16 2016	(r303267)
@@ -418,10 +418,10 @@ protopr(u_long off, const char *name, in
 				    "Tcpcb");
 			if (Lflag)
 				xo_emit((Aflag && !Wflag) ?
-				    "{T:/%-5.5s} {T:/%-14.14s} {T:/%-18.18s}" :
+				    "{T:/%-5.5s} {T:/%-32.32s} {T:/%-18.18s}" :
 				    ((!Wflag || af1 == AF_INET) ?
-				    "{T:/%-5.5s} {T:/%-14.14s} {T:/%-22.22s}" :
-				    "{T:/%-5.5s} {T:/%-14.14s} {T:/%-45.45s}"),
+				    "{T:/%-5.5s} {T:/%-32.32s} {T:/%-22.22s}" :
+				    "{T:/%-5.5s} {T:/%-32.32s} {T:/%-45.45s}"),
 				    "Proto", "Listen", "Local Address");
 			else if (Tflag)
 				xo_emit((Aflag && !Wflag) ?

Modified: stable/11/usr.bin/netstat/sctp.c
==============================================================================
--- stable/11/usr.bin/netstat/sctp.c	Sun Jul 24 14:42:11 2016	(r303266)
+++ stable/11/usr.bin/netstat/sctp.c	Sun Jul 24 14:50:16 2016	(r303267)
@@ -104,93 +104,14 @@ 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.
- */
 #ifdef INET
-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 == NULL) {
-			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);
-}
+char *
+inetname(struct in_addr *inp);
 #endif
 
 #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 = strchr(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 = strchr(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);
-}
+char *
+inet6name(struct in6_addr *in6p);
 #endif
 
 static void
@@ -447,7 +368,8 @@ sctp_process_inpcb(struct xsctp_inpcb *x
 		first = 0;
 	}
 	xladdr = (struct xsctp_laddr *)(buf + *offset);
-	if (Lflag && !is_listening) {
+	if ((!aflag && is_listening) ||
+	    (Lflag && !is_listening)) {
 		sctp_skip_xinpcb_ifneed(buf, buflen, offset);
 		return;
 	}
@@ -513,8 +435,10 @@ retry:
 		xo_open_instance("local-address");
 
 		if (xladdr_total == 0) {
-			xo_emit("{:protocol/%-6.6s/%s} {:type/%-5.5s/%s} ",
-			    pname, tname);
+			if (!Lflag) {
+				xo_emit("{:protocol/%-6.6s/%s} "
+				    "{:type/%-5.5s/%s} ", pname, tname);
+			}
 		} else {
 			xo_emit("\n");
 			xo_emit(Lflag ? "{P:/%-21.21s} " : "{P:/%-12.12s} ",
@@ -529,7 +453,7 @@ retry:
 					    "{:state/CLOSED}", " ");
 				} else {
 					xo_emit("{P:/%-45.45s} "
-					    "{:state:LISTEN}", " ");
+					    "{:state/LISTEN}", " ");
 				}
 			} else {
 				if (process_closed) {


More information about the svn-src-stable mailing list