summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/sctp_auth.c9
-rw-r--r--sys/netinet/sctp_constants.h1
-rw-r--r--sys/netinet/sctp_header.h2
-rw-r--r--sys/netinet/sctp_indata.c39
-rw-r--r--sys/netinet/sctp_output.c11
-rw-r--r--sys/netinet/sctp_sysctl.c9
-rw-r--r--sys/netinet/sctp_uio.h3
-rw-r--r--usr.bin/netstat/inet.c6
-rw-r--r--usr.bin/netstat/sctp.c98
9 files changed, 58 insertions, 120 deletions
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index 07dbf8b..1c9d528 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -542,7 +542,7 @@ sctp_insert_sharedkey(struct sctp_keyhead *shared_keys,
}
}
/* shouldn't reach here */
- return (0);
+ return (EINVAL);
}
void
@@ -622,8 +622,11 @@ sctp_copy_skeylist(const struct sctp_keyhead *src, struct sctp_keyhead *dest)
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);
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index a58c206..ecde4fe 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -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
diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h
index 850290d..3f4948d 100644
--- a/sys/netinet/sctp_header.h
+++ b/sys/netinet/sctp_header.h
@@ -397,7 +397,7 @@ struct sctp_strseq {
struct sctp_strseq_mid {
uint16_t stream;
- uint16_t reserved;
+ uint16_t flags;
uint32_t msg_id;
};
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 7a2f42c..357a047 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -753,7 +753,7 @@ sctp_handle_old_data(struct sctp_tcb *stcb, struct sctp_association *asoc, struc
*/
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 *stcb, struct sctp_association *asoc, s
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 sctp_tcb *stcb,
}
}
+
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 sctp_tcb *stcb,
* 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 *stcb,
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 *stcb,
}
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 *stcb,
}
stream = ntohs(stseq->stream);
sequence = (uint32_t) ntohs(stseq->sequence);
+ ordered = 1;
}
/* Convert */
@@ -5487,7 +5502,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
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)) {
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index d8c3cae..1ad3d0c 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -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 sctp_tcb *stcb,
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 sctp_tcb *stcb,
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,
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index aeb2e10..de21941 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -279,15 +279,6 @@ sctp_sysctl_copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *st
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;
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index c7e441d..e65b7b5 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -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 */
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 54ab56f..6f912ac 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -418,10 +418,10 @@ protopr(u_long off, const char *name, int af1, int proto)
"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) ?
diff --git a/usr.bin/netstat/sctp.c b/usr.bin/netstat/sctp.c
index 0ab933a..fd133e3 100644
--- a/usr.bin/netstat/sctp.c
+++ b/usr.bin/netstat/sctp.c
@@ -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 *xinpcb,
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) {
OpenPOWER on IntegriCloud