summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in_pcb.c22
-rw-r--r--sys/netinet/in_pcb.h10
-rw-r--r--sys/netinet/in_pcbgroup.c1
-rw-r--r--sys/netinet/ip_output.c29
-rw-r--r--sys/netinet/sctp_cc_functions.c12
-rw-r--r--sys/netinet/sctp_constants.h2
-rw-r--r--sys/netinet/sctp_indata.c20
-rw-r--r--sys/netinet/sctp_input.c10
-rw-r--r--sys/netinet/sctp_output.c68
-rw-r--r--sys/netinet/sctp_pcb.c4
-rw-r--r--sys/netinet/sctp_ss_functions.c2
-rw-r--r--sys/netinet/sctp_timer.c4
-rw-r--r--sys/netinet/sctp_usrreq.c26
-rw-r--r--sys/netinet/sctputil.c70
-rw-r--r--sys/netinet/sctputil.h5
-rw-r--r--sys/netinet/tcp_input.c29
-rw-r--r--sys/netinet/tcp_lro.c68
-rw-r--r--sys/netinet/tcp_lro.h8
-rw-r--r--sys/netinet/tcp_output.c12
-rw-r--r--sys/netinet/tcp_subr.c24
-rw-r--r--sys/netinet/tcp_syncache.c6
-rw-r--r--sys/netinet/tcp_timer.c2
-rw-r--r--sys/netinet/tcp_timewait.c2
-rw-r--r--sys/netinet/tcp_usrreq.c2
-rw-r--r--sys/netinet/tcp_var.h16
-rw-r--r--sys/netinet/udp_usrreq.c42
26 files changed, 311 insertions, 185 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index ec42e67..50e5d6e 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1298,6 +1298,11 @@ in_pcbfree(struct inpcb *inp)
if (inp->inp_moptions != NULL)
inp_freemoptions(inp->inp_moptions);
#endif
+ if (inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
+
inp->inp_vflag = 0;
inp->inp_flags2 |= INP_FREED;
crfree(inp->inp_cred);
@@ -2225,6 +2230,23 @@ in_pcbremlists(struct inpcb *inp)
}
/*
+ * Check for alternatives when higher level complains
+ * about service problems. For now, invalidate cached
+ * routing information. If the route was created dynamically
+ * (by a redirect), time to try a default gateway again.
+ */
+void
+in_losing(struct inpcb *inp)
+{
+
+ if (inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
+ return;
+}
+
+/*
* A set label operation has occurred at the socket layer, propagate the
* label change into the in_pcb for the socket.
*/
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 54eab88..9c77a51 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -42,6 +42,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/_rwlock.h>
+#include <net/route.h>
#ifdef _KERNEL
#include <sys/lock.h>
@@ -238,8 +239,14 @@ struct inpcb {
#define inp_zero_size offsetof(struct inpcb, inp_gencnt)
inp_gen_t inp_gencnt; /* (c) generation count */
struct llentry *inp_lle; /* cached L2 information */
- struct rtentry *inp_rt; /* cached L3 information */
struct rwlock inp_lock;
+ rt_gen_t inp_rt_cookie; /* generation for route entry */
+ union { /* cached L3 information */
+ struct route inpu_route;
+ struct route_in6 inpu_route6;
+ } inp_rtu;
+#define inp_route inp_rtu.inpu_route
+#define inp_route6 inp_rtu.inpu_route6
};
#define inp_fport inp_inc.inc_fport
#define inp_lport inp_inc.inc_lport
@@ -722,6 +729,7 @@ void in_pcbrehash_mbuf(struct inpcb *, struct mbuf *);
int in_pcbrele(struct inpcb *);
int in_pcbrele_rlocked(struct inpcb *);
int in_pcbrele_wlocked(struct inpcb *);
+void in_losing(struct inpcb *);
void in_pcbsetsolabel(struct socket *so);
int in_getpeeraddr(struct socket *so, struct sockaddr **nam);
int in_getsockaddr(struct socket *so, struct sockaddr **nam);
diff --git a/sys/netinet/in_pcbgroup.c b/sys/netinet/in_pcbgroup.c
index 2d3c136..04a7699 100644
--- a/sys/netinet/in_pcbgroup.c
+++ b/sys/netinet/in_pcbgroup.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/smp.h>
+#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/rss_config.h>
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index fa225fc..afdf1a7 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -282,17 +282,36 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
gw = dst = (struct sockaddr_in *)&ro->ro_dst;
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
rte = ro->ro_rt;
- /*
- * The address family should also be checked in case of sharing
- * the cache with IPv6.
- */
- if (rte == NULL || dst->sin_family != AF_INET) {
+ if (rte == NULL) {
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;
}
again:
+ /*
+ * Validate route against routing table additions;
+ * a better/more specific route might have been added.
+ */
+ if (inp)
+ RT_VALIDATE(ro, &inp->inp_rt_cookie, fibnum);
+ /*
+ * If there is a cached route,
+ * check that it is to the same destination
+ * and is still up. If not, free it and try again.
+ * The address family should also be checked in case of sharing the
+ * cache with IPv6.
+ * Also check whether routing cache needs invalidation.
+ */
+ rte = ro->ro_rt;
+ if (rte && ((rte->rt_flags & RTF_UP) == 0 ||
+ rte->rt_ifp == NULL ||
+ !RT_LINK_IS_UP(rte->rt_ifp) ||
+ dst->sin_family != AF_INET ||
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ RTFREE(rte);
+ rte = ro->ro_rt = (struct rtentry *)NULL;
+ }
ia = NULL;
have_ia_ref = 0;
/*
diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c
index 0bddcfd..0ad3e33 100644
--- a/sys/netinet/sctp_cc_functions.c
+++ b/sys/netinet/sctp_cc_functions.c
@@ -1526,13 +1526,13 @@ sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
struct sctp_hs_raise_drop {
int32_t cwnd;
- int32_t increase;
- int32_t drop_percent;
+ int8_t increase;
+ int8_t drop_percent;
};
#define SCTP_HS_TABLE_SIZE 73
-struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
+static const struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
{38, 1, 50}, /* 0 */
{118, 2, 44}, /* 1 */
{221, 3, 41}, /* 2 */
@@ -1632,7 +1632,7 @@ sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
net->last_hs_used = indx;
- incr = ((sctp_cwnd_adjust[indx].increase) << 10);
+ incr = (((int32_t) sctp_cwnd_adjust[indx].increase) << 10);
net->cwnd += incr;
}
sctp_enforce_cwnd_limit(&stcb->asoc, net);
@@ -1658,7 +1658,7 @@ sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
} else {
/* drop by the proper amount */
net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
- sctp_cwnd_adjust[net->last_hs_used].drop_percent);
+ (int32_t) sctp_cwnd_adjust[net->last_hs_used].drop_percent);
net->cwnd = net->ssthresh;
/* now where are we */
indx = net->last_hs_used;
@@ -2323,7 +2323,7 @@ sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
}
}
-struct sctp_cc_functions sctp_cc_functions[] = {
+const struct sctp_cc_functions sctp_cc_functions[] = {
{
.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
.sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 5837f6f..497dde6 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -68,6 +68,8 @@ __FBSDID("$FreeBSD$");
/* Largest length of a chunk */
#define SCTP_MAX_CHUNK_LENGTH 0xffff
+/* Largest length of an error cause */
+#define SCTP_MAX_CAUSE_LENGTH 0xffff
/* Number of addresses where we just skip the counting */
#define SCTP_COUNT_LIMIT 40
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 75c1ac5..cbc7fb5 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -1948,7 +1948,7 @@ finish_express_del:
return (1);
}
-int8_t sctp_map_lookup_tab[256] = {
+static const int8_t sctp_map_lookup_tab[256] = {
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
@@ -2495,7 +2495,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
if (op_err != NULL) {
cause = mtod(op_err, struct sctp_gen_error_cause *);
cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
- cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause));
+ cause->length = htons((uint16_t) (chk_length + sizeof(struct sctp_gen_error_cause)));
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
if (SCTP_BUF_NEXT(op_err) != NULL) {
@@ -2688,7 +2688,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
@@ -2897,7 +2897,7 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_increase(tp1);
@@ -3211,7 +3211,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND,
(tp1->whoTo ? (tp1->whoTo->flight_size) : 0),
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
if (tp1->whoTo) {
@@ -3523,7 +3523,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
sctp_misc_ints(SCTP_FLIGHT_LOG_DWN_WP_FWD,
tp1->whoTo ? tp1->whoTo->flight_size : 0,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
return;
}
@@ -3542,7 +3542,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
}
@@ -3661,7 +3661,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
@@ -4302,7 +4302,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
@@ -4575,7 +4575,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_increase(tp1);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index a205f2f..c555be2 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2358,7 +2358,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
SCTP_RTT_FROM_NON_DATA);
#if defined(INET) || defined(INET6)
if (((*netp)->port == 0) && (port != 0)) {
- sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr));
+ sctp_pathmtu_adjustment(stcb, (uint16_t) ((*netp)->mtu - sizeof(struct udphdr)));
}
(*netp)->port = port;
#endif
@@ -3339,7 +3339,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) stcb,
+ (uint32_t) (uintptr_t) stcb,
tp1->rec.data.TSN_seq);
}
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
@@ -5596,7 +5596,7 @@ process_control_chunks:
len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset));
cause = mtod(op_err, struct sctp_gen_error_cause *);
cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
- cause->length = htons(len + sizeof(struct sctp_gen_error_cause));
+ cause->length = htons((uint16_t) (len + sizeof(struct sctp_gen_error_cause)));
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
if (SCTP_BUF_NEXT(op_err) != NULL) {
@@ -6033,7 +6033,9 @@ trigger_send:
if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
}
- if (cnt_ctrl_ready || stcb->asoc.trigger_reset ||
+ if (!TAILQ_EMPTY(&stcb->asoc.asconf_send_queue) ||
+ cnt_ctrl_ready ||
+ stcb->asoc.trigger_reset ||
((un_sent) &&
(stcb->asoc.peers_rwnd > 0 ||
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index a900106..8eda473 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -67,7 +67,7 @@ struct sack_track {
struct sctp_gap_ack_block gaps[SCTP_MAX_GAPS_INARRAY];
};
-struct sack_track sack_array[256] = {
+const struct sack_track sack_array[256] = {
{0, 0, 0, 0, /* 0x00 */
{{0, 0},
{0, 0},
@@ -3508,7 +3508,7 @@ sctp_find_cmsg(int c_type, void *data, struct mbuf *control, size_t cpsize)
return (found);
}
/* It is exactly what we want. Copy it out. */
- m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), cpsize, (caddr_t)data);
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), (int)cpsize, (caddr_t)data);
return (1);
} else {
struct sctp_sndrcvinfo *sndrcvinfo;
@@ -4186,7 +4186,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip));
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
- udp->uh_ulen = htons(packet_length - sizeof(struct ip));
+ udp->uh_ulen = htons((uint16_t) (packet_length - sizeof(struct ip)));
if (V_udp_cksum) {
udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
} else {
@@ -4414,7 +4414,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
} else {
ip6h->ip6_nxt = IPPROTO_SCTP;
}
- ip6h->ip6_plen = (packet_length - sizeof(struct ip6_hdr));
+ ip6h->ip6_plen = (uint16_t) (packet_length - sizeof(struct ip6_hdr));
ip6h->ip6_dst = sin6->sin6_addr;
/*
@@ -4533,7 +4533,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
- udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr));
+ udp->uh_ulen = htons((uint16_t) (packet_length - sizeof(struct ip6_hdr)));
udp->uh_sum = 0;
sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
} else {
@@ -6479,10 +6479,10 @@ error_out:
}
}
/* get the new end of length */
- len = M_TRAILINGSPACE(*endofchain);
+ len = (int)M_TRAILINGSPACE(*endofchain);
} else {
/* how much is left at the end? */
- len = M_TRAILINGSPACE(*endofchain);
+ len = (int)M_TRAILINGSPACE(*endofchain);
}
/* Find the end of the data, for appending */
cp = (mtod((*endofchain), caddr_t)+SCTP_BUF_LEN((*endofchain)));
@@ -6636,7 +6636,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
ph = mtod(m, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
- ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen);
+ ph->param_length = htons((uint16_t) (sizeof(struct sctp_paramhdr) + ca->sndlen));
}
/*
* We add one here to keep the assoc from dis-appearing on
@@ -6814,7 +6814,7 @@ sctp_copy_out_all(struct uio *uio, int len)
left = len;
SCTP_BUF_LEN(ret) = 0;
/* save space for the data chunk header */
- cancpy = M_TRAILINGSPACE(ret);
+ cancpy = (int)M_TRAILINGSPACE(ret);
willcpy = min(cancpy, left);
at = ret;
while (left > 0) {
@@ -6835,7 +6835,7 @@ sctp_copy_out_all(struct uio *uio, int len)
}
at = SCTP_BUF_NEXT(at);
SCTP_BUF_LEN(at) = 0;
- cancpy = M_TRAILINGSPACE(at);
+ cancpy = (int)M_TRAILINGSPACE(at);
willcpy = min(cancpy, left);
}
}
@@ -6869,7 +6869,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
ca->sndrcv.sinfo_flags &= ~SCTP_SENDALL;
/* get length and mbuf chain */
if (uio) {
- ca->sndlen = uio->uio_resid;
+ ca->sndlen = (int)uio->uio_resid;
ca->m = sctp_copy_out_all(uio, ca->sndlen);
if (ca->m == NULL) {
SCTP_FREE(ca, SCTP_M_COPYAL);
@@ -7019,7 +7019,7 @@ all_done:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
data_list[i]->whoTo->flight_size,
data_list[i]->book_size,
- (uintptr_t) data_list[i]->whoTo,
+ (uint32_t) (uintptr_t) data_list[i]->whoTo,
data_list[i]->rec.data.TSN_seq);
}
sctp_flight_size_increase(data_list[i]);
@@ -7516,7 +7516,7 @@ dont_do_it:
goto out_of;
}
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
- chk->book_size = chk->send_size = (to_move + sizeof(struct sctp_data_chunk));
+ chk->book_size = chk->send_size = (uint16_t) (to_move + sizeof(struct sctp_data_chunk));
chk->book_size_scale = 0;
chk->sent = SCTP_DATAGRAM_UNSENT;
@@ -7551,7 +7551,7 @@ dont_do_it:
chk->rec.data.TSN_seq = atomic_fetchadd_int(&asoc->sending_seq, 1);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_AT_SEND_2_OUTQ) {
sctp_misc_ints(SCTP_STRMOUT_LOG_SEND,
- (uintptr_t) stcb, sp->length,
+ (uint32_t) (uintptr_t) stcb, sp->length,
(uint32_t) ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq),
chk->rec.data.TSN_seq);
}
@@ -8943,6 +8943,8 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
chk->asoc = &stcb->asoc;
chk->data = op_err;
chk->whoTo = NULL;
+ chk->rec.chunk_id.id = SCTP_OPERATION_ERROR;
+ chk->rec.chunk_id.can_take_data = 0;
hdr = mtod(op_err, struct sctp_chunkhdr *);
hdr->chunk_type = SCTP_OPERATION_ERROR;
hdr->chunk_flags = 0;
@@ -9827,7 +9829,7 @@ one_chunk_around:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_RSND,
data_list[i]->whoTo->flight_size,
data_list[i]->book_size,
- (uintptr_t) data_list[i]->whoTo,
+ (uint32_t) (uintptr_t) data_list[i]->whoTo,
data_list[i]->rec.data.TSN_seq);
}
sctp_flight_size_increase(data_list[i]);
@@ -10288,7 +10290,7 @@ sctp_fill_in_rest:
space_needed = (sizeof(struct sctp_forward_tsn_chunk) +
(cnt_of_skipped * sizeof(struct sctp_strseq)));
- cnt_of_space = M_TRAILINGSPACE(chk->data);
+ cnt_of_space = (unsigned int)M_TRAILINGSPACE(chk->data);
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ovh = SCTP_MIN_OVERHEAD;
@@ -10414,7 +10416,7 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
struct sctp_sack_chunk *sack;
struct sctp_nr_sack_chunk *nr_sack;
struct sctp_gap_ack_block *gap_descriptor;
- struct sack_track *selector;
+ const struct sack_track *selector;
int mergeable = 0;
int offset;
caddr_t limit;
@@ -10546,7 +10548,7 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
}
/* ok, lets go through and fill it in */
SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD);
- space = M_TRAILINGSPACE(a_chk->data);
+ space = (unsigned int)M_TRAILINGSPACE(a_chk->data);
if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) {
space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD);
}
@@ -10760,9 +10762,9 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
* queue.
*/
if (type == SCTP_SELECTIVE_ACK) {
- a_chk->send_size = sizeof(struct sctp_sack_chunk) +
+ a_chk->send_size = (uint16_t) (sizeof(struct sctp_sack_chunk) +
(num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
- num_dups * sizeof(int32_t);
+ num_dups * sizeof(int32_t));
SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
sack->sack.a_rwnd = htonl(asoc->my_rwnd);
@@ -10772,9 +10774,9 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
sack->ch.chunk_flags = flags;
sack->ch.chunk_length = htons(a_chk->send_size);
} else {
- a_chk->send_size = sizeof(struct sctp_nr_sack_chunk) +
+ a_chk->send_size = (uint16_t) (sizeof(struct sctp_nr_sack_chunk) +
(num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
- num_dups * sizeof(int32_t);
+ num_dups * sizeof(int32_t));
SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
nr_sack->nr_sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
nr_sack->nr_sack.a_rwnd = htonl(asoc->my_rwnd);
@@ -11082,10 +11084,10 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
udp->uh_sum = 0;
- udp->uh_ulen = htons(sizeof(struct udphdr) +
+ udp->uh_ulen = htons((uint16_t) (sizeof(struct udphdr) +
sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr) +
- cause_len + padding_len);
+ cause_len + padding_len));
len += sizeof(struct udphdr);
shout = (struct sctphdr *)((caddr_t)shout + sizeof(struct udphdr));
} else {
@@ -11108,7 +11110,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
} else {
ch->chunk_flags = SCTP_HAD_NO_TCB;
}
- ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + cause_len);
+ ch->chunk_length = htons((uint16_t) (sizeof(struct sctp_chunkhdr) + cause_len));
len += sizeof(struct sctp_chunkhdr);
len += cause_len + padding_len;
@@ -11157,7 +11159,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
#endif
#ifdef INET6
case AF_INET6:
- ip6->ip6_plen = len - sizeof(struct ip6_hdr);
+ ip6->ip6_plen = (uint16_t) (len - sizeof(struct ip6_hdr));
if (port) {
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
@@ -11484,7 +11486,7 @@ jump_out:
* Len is already adjusted to size minus overhead above take
* out the pkt_drop chunk itself from it.
*/
- chk->send_size = len - sizeof(struct sctp_pktdrop_chunk);
+ chk->send_size = (uint16_t) (len - sizeof(struct sctp_pktdrop_chunk));
len = chk->send_size;
} else {
/* no truncation needed */
@@ -11624,7 +11626,7 @@ sctp_add_stream_reset_out(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
if (number_entries > SCTP_MAX_STREAMS_AT_ONCE_RESET) {
number_entries = SCTP_MAX_STREAMS_AT_ONCE_RESET;
}
- len = (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries));
+ len = (uint16_t) (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries));
req_out->ph.param_type = htons(SCTP_STR_RESET_OUT_REQUEST);
req_out->ph.param_length = htons(len);
req_out->request_seq = htonl(seq);
@@ -11681,7 +11683,7 @@ sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk,
/* get to new offset for the param. */
req_in = (struct sctp_stream_reset_in_request *)((caddr_t)ch + len);
/* now how long will this param be? */
- len = (sizeof(struct sctp_stream_reset_in_request) + (sizeof(uint16_t) * number_entries));
+ len = (uint16_t) (sizeof(struct sctp_stream_reset_in_request) + (sizeof(uint16_t) * number_entries));
req_in->ph.param_type = htons(SCTP_STR_RESET_IN_REQUEST);
req_in->ph.param_length = htons(len);
req_in->request_seq = htonl(seq);
@@ -12313,7 +12315,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
sp->stream = srcv->sinfo_stream;
- sp->length = min(uio->uio_resid, max_send_len);
+ sp->length = (uint32_t) min(uio->uio_resid, max_send_len);
if ((sp->length == (uint32_t) uio->uio_resid) &&
((user_marks_eor == 0) ||
(srcv->sinfo_flags & SCTP_EOF) ||
@@ -12472,7 +12474,7 @@ sctp_lower_sosend(struct socket *so,
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
- sndlen = uio->uio_resid;
+ sndlen = (unsigned int)uio->uio_resid;
} else {
top = SCTP_HEADER_TO_CHAIN(i_pak);
sndlen = SCTP_HEADER_LEN(i_pak);
@@ -12871,7 +12873,7 @@ sctp_lower_sosend(struct socket *so,
/* now move forward the data pointer */
ph = mtod(mm, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
- ph->param_length = htons(sizeof(struct sctp_paramhdr) + tot_out);
+ ph->param_length = htons((uint16_t) (sizeof(struct sctp_paramhdr) + tot_out));
ph++;
SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr);
if (top == NULL) {
@@ -13291,7 +13293,7 @@ skip_preblock:
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
- asoc, uio->uio_resid);
+ asoc, (size_t)uio->uio_resid);
}
be.error = 0;
stcb->block_entry = &be;
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 7e3218d..12aa145 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -5357,6 +5357,7 @@ void
sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t action)
{
struct sctp_laddr *laddr;
+ struct sctp_tcb *stcb;
int fnd, error = 0;
fnd = 0;
@@ -5402,6 +5403,9 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac
default:
break;
}
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ sctp_add_local_addr_restricted(stcb, ifa);
+ }
}
return;
}
diff --git a/sys/netinet/sctp_ss_functions.c b/sys/netinet/sctp_ss_functions.c
index a2568ad..c4cbb05 100644
--- a/sys/netinet/sctp_ss_functions.c
+++ b/sys/netinet/sctp_ss_functions.c
@@ -822,7 +822,7 @@ default_again:
return (strq);
}
-struct sctp_ss_functions sctp_ss_functions[] = {
+const struct sctp_ss_functions sctp_ss_functions[] = {
/* SCTP_SS_DEFAULT */
{
.sctp_ss_init = sctp_ss_default_init,
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index dec02de..9fa37e7 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -662,7 +662,7 @@ start_again:
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
sctp_flight_size_decrease(chk);
@@ -790,7 +790,7 @@ start_again:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
sctp_flight_size_increase(chk);
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index d11bf20..a75f025 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$");
-extern struct sctp_cc_functions sctp_cc_functions[];
-extern struct sctp_ss_functions sctp_ss_functions[];
+extern const struct sctp_cc_functions sctp_cc_functions[];
+extern const struct sctp_ss_functions sctp_ss_functions[];
void
sctp_init(void)
@@ -132,7 +132,7 @@ sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
/* Clear any time so NO RTT is being done */
@@ -1413,7 +1413,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
int creat_lock_on = 0;
struct sctp_tcb *stcb = NULL;
struct sockaddr *sa;
- int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
+ unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
uint32_t vrf_id;
int bad_addresses = 0;
sctp_assoc_t *a_id;
@@ -1449,10 +1449,10 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
error = EFAULT;
goto out_now;
}
- totaddrp = (int *)optval;
+ totaddrp = (unsigned int *)optval;
totaddr = *totaddrp;
sa = (struct sockaddr *)(totaddrp + 1);
- stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
+ stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (unsigned int)(optsize - sizeof(int)), &bad_addresses);
if ((stcb != NULL) || bad_addresses) {
/* Already have or am bring up an association */
SCTP_ASOC_CREATE_UNLOCK(inp);
@@ -1903,7 +1903,8 @@ flags_out:
case SCTP_GET_ASSOC_ID_LIST:
{
struct sctp_assoc_ids *ids;
- unsigned int at, limit;
+ uint32_t at;
+ size_t limit;
SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
SCTP_INP_RLOCK(inp);
@@ -1919,6 +1920,11 @@ flags_out:
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
if (at < limit) {
ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
+ if (at == 0) {
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
} else {
error = EINVAL;
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
@@ -5810,6 +5816,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
__func__);
continue;
}
+ if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
+ (!sctp_is_addr_pending(stcb, laddr->ifa))) {
+ continue;
+ }
if (laddr->ifa == ifa) {
found = 1;
break;
@@ -5862,7 +5872,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
out_of_it:
SCTP_TCB_UNLOCK(stcb);
} else {
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 4115256..9434f06 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -58,8 +58,8 @@ __FBSDID("$FreeBSD$");
#define KTR_SCTP KTR_SUBSYS
#endif
-extern struct sctp_cc_functions sctp_cc_functions[];
-extern struct sctp_ss_functions sctp_ss_functions[];
+extern const struct sctp_cc_functions sctp_cc_functions[];
+extern const struct sctp_ss_functions sctp_ss_functions[];
void
sctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr)
@@ -503,7 +503,7 @@ sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
}
void
-sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
+sctp_log_block(uint8_t from, struct sctp_association *asoc, size_t sendlen)
{
struct sctp_cwnd_log sctp_clog;
@@ -513,7 +513,7 @@ sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
- sctp_clog.x.blk.sndlen = sendlen;
+ sctp_clog.x.blk.sndlen = (uint32_t) sendlen;
SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_BLOCK,
from,
@@ -2679,7 +2679,8 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
struct mbuf *m_notify;
struct sctp_assoc_change *sac;
struct sctp_queued_to_read *control;
- size_t notif_len, abort_len;
+ unsigned int notif_len;
+ uint16_t abort_len;
unsigned int i;
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -2691,7 +2692,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
return;
}
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
- notif_len = sizeof(struct sctp_assoc_change);
+ notif_len = (unsigned int)sizeof(struct sctp_assoc_change);
if (abort != NULL) {
abort_len = ntohs(abort->ch.chunk_length);
} else {
@@ -2705,7 +2706,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
/* Retry with smaller value. */
- notif_len = sizeof(struct sctp_assoc_change);
+ notif_len = (unsigned int)sizeof(struct sctp_assoc_change);
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
goto set_error;
@@ -3570,7 +3571,8 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
struct mbuf *m_notify;
struct sctp_remote_error *sre;
struct sctp_queued_to_read *control;
- size_t notif_len, chunk_len;
+ unsigned int notif_len;
+ uint16_t chunk_len;
if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
@@ -3581,11 +3583,11 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
} else {
chunk_len = 0;
}
- notif_len = sizeof(struct sctp_remote_error) + chunk_len;
+ notif_len = (unsigned int)(sizeof(struct sctp_remote_error) + chunk_len);
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
/* Retry with smaller value. */
- notif_len = sizeof(struct sctp_remote_error);
+ notif_len = (unsigned int)sizeof(struct sctp_remote_error);
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
return;
@@ -4739,19 +4741,23 @@ sctp_generate_cause(uint16_t code, char *info)
{
struct mbuf *m;
struct sctp_gen_error_cause *cause;
- size_t info_len, len;
+ size_t info_len;
+ uint16_t len;
if ((code == 0) || (info == NULL)) {
return (NULL);
}
info_len = strlen(info);
- len = sizeof(struct sctp_paramhdr) + info_len;
+ if (info_len > (SCTP_MAX_CAUSE_LENGTH - sizeof(struct sctp_paramhdr))) {
+ return (NULL);
+ }
+ len = (uint16_t) (sizeof(struct sctp_paramhdr) + info_len);
m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
if (m != NULL) {
SCTP_BUF_LEN(m) = len;
cause = mtod(m, struct sctp_gen_error_cause *);
cause->code = htons(code);
- cause->length = htons((uint16_t) len);
+ cause->length = htons(len);
memcpy(cause->info, info, info_len);
}
return (m);
@@ -4762,15 +4768,15 @@ sctp_generate_no_user_data_cause(uint32_t tsn)
{
struct mbuf *m;
struct sctp_error_no_user_data *no_user_data_cause;
- size_t len;
+ uint16_t len;
- len = sizeof(struct sctp_error_no_user_data);
+ len = (uint16_t) sizeof(struct sctp_error_no_user_data);
m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
if (m != NULL) {
SCTP_BUF_LEN(m) = len;
no_user_data_cause = mtod(m, struct sctp_error_no_user_data *);
no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA);
- no_user_data_cause->cause.length = htons((uint16_t) len);
+ no_user_data_cause->cause.length = htons(len);
no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */
}
return (m);
@@ -5295,7 +5301,7 @@ sctp_sorecvmsg(struct socket *so,
uint32_t rwnd_req = 0;
int hold_sblock = 0;
int hold_rlock = 0;
- int slen = 0;
+ ssize_t slen = 0;
uint32_t held_length = 0;
int sockbuf_lock = 0;
@@ -5340,11 +5346,11 @@ sctp_sorecvmsg(struct socket *so,
in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
sctp_misc_ints(SCTP_SORECV_ENTER,
- rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
+ rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, (uint32_t) uio->uio_resid);
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
sctp_misc_ints(SCTP_SORECV_ENTERPL,
- rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
+ rwnd_req, block_allowed, so->so_rcv.sb_cc, (uint32_t) uio->uio_resid);
}
error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
if (error) {
@@ -6219,13 +6225,13 @@ out:
if (stcb) {
sctp_misc_ints(SCTP_SORECV_DONE,
freed_so_far,
- ((uio) ? (slen - uio->uio_resid) : slen),
+ (uint32_t) ((uio) ? (slen - uio->uio_resid) : slen),
stcb->asoc.my_rwnd,
so->so_rcv.sb_cc);
} else {
sctp_misc_ints(SCTP_SORECV_DONE,
freed_so_far,
- ((uio) ? (slen - uio->uio_resid) : slen),
+ (uint32_t) ((uio) ? (slen - uio->uio_resid) : slen),
0,
so->so_rcv.sb_cc);
}
@@ -6452,30 +6458,30 @@ out_now:
struct sctp_tcb *
sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
- int *totaddr, int *num_v4, int *num_v6, int *error,
- int limit, int *bad_addr)
+ unsigned int *totaddr,
+ unsigned int *num_v4, unsigned int *num_v6, int *error,
+ unsigned int limit, int *bad_addr)
{
struct sockaddr *sa;
struct sctp_tcb *stcb = NULL;
- size_t incr, at, i;
+ unsigned int incr, at, i;
at = incr = 0;
sa = addr;
-
*error = *num_v6 = *num_v4 = 0;
/* account and validate addresses */
- for (i = 0; i < (size_t)*totaddr; i++) {
+ for (i = 0; i < *totaddr; i++) {
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
- (*num_v4) += 1;
- incr = sizeof(struct sockaddr_in);
if (sa->sa_len != incr) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
}
+ (*num_v4) += 1;
+ incr = (unsigned int)sizeof(struct sockaddr_in);
break;
#endif
#ifdef INET6
@@ -6491,14 +6497,14 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
*bad_addr = 1;
return (NULL);
}
- (*num_v6) += 1;
- incr = sizeof(struct sockaddr_in6);
if (sa->sa_len != incr) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
}
+ (*num_v6) += 1;
+ incr = (unsigned int)sizeof(struct sockaddr_in6);
break;
}
#endif
@@ -6507,7 +6513,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
/* we are done */
break;
}
- if (i == (size_t)*totaddr) {
+ if (i == *totaddr) {
break;
}
SCTP_INP_INCR_REF(inp);
@@ -6518,7 +6524,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
} else {
SCTP_INP_DECR_REF(inp);
}
- if ((at + incr) > (size_t)limit) {
+ if ((at + incr) > limit) {
*totaddr = i;
break;
}
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 354d40e..2d32792 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -220,7 +220,8 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
struct sctp_tcb *
sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
- int *totaddr, int *num_v4, int *num_v6, int *error, int limit, int *bad_addr);
+ unsigned int *totaddr, unsigned int *num_v4, unsigned int *num_v6,
+ int *error, unsigned int limit, int *bad_addr);
int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *);
@@ -376,7 +377,7 @@ void sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc
void sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from);
void sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *, int, int, uint8_t);
-void sctp_log_block(uint8_t, struct sctp_association *, int);
+void sctp_log_block(uint8_t, struct sctp_association *, size_t);
void sctp_log_rwnd(uint8_t, uint32_t, uint32_t, uint32_t);
void sctp_log_rwnd_set(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
int sctp_fill_stat_log(void *, size_t *);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 102430d..7134ce4 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -235,16 +235,39 @@ VNET_DEFINE(struct inpcbhead, tcb);
VNET_DEFINE(struct inpcbinfo, tcbinfo);
/*
- * TCP statistics are stored in an "array" of counter(9)s.
+ * TCP statistics are stored in an array of counter(9)s, which size matches
+ * size of struct tcpstat. TCP running connection count is a regular array.
*/
VNET_PCPUSTAT_DEFINE(struct tcpstat, tcpstat);
-VNET_PCPUSTAT_SYSINIT(tcpstat);
SYSCTL_VNET_PCPUSTAT(_net_inet_tcp, TCPCTL_STATS, stats, struct tcpstat,
tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
+VNET_DEFINE(counter_u64_t, tcps_states[TCP_NSTATES]);
+SYSCTL_COUNTER_U64_ARRAY(_net_inet_tcp, TCPCTL_STATES, states, CTLFLAG_RD |
+ CTLFLAG_VNET, &VNET_NAME(tcps_states)[0], TCP_NSTATES,
+ "TCP connection counts by TCP state");
+
+static void
+tcp_vnet_init(const void *unused)
+{
+
+ COUNTER_ARRAY_ALLOC(VNET(tcps_states), TCP_NSTATES, M_WAITOK);
+ VNET_PCPUSTAT_ALLOC(tcpstat, M_WAITOK);
+}
+VNET_SYSINIT(tcp_vnet_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ tcp_vnet_init, NULL);
#ifdef VIMAGE
-VNET_PCPUSTAT_SYSUNINIT(tcpstat);
+static void
+tcp_vnet_uninit(const void *unused)
+{
+
+ COUNTER_ARRAY_FREE(VNET(tcps_states), TCP_NSTATES);
+ VNET_PCPUSTAT_FREE(tcpstat);
+}
+VNET_SYSUNINIT(tcp_vnet_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ tcp_vnet_uninit, NULL);
#endif /* VIMAGE */
+
/*
* Kernel module interface for updating tcpstat. The argument is an index
* into tcpstat treated as an array.
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index 7067abe..bd323bf 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -67,6 +67,8 @@ static MALLOC_DEFINE(M_LRO, "LRO", "LRO control structures");
#define TCP_LRO_INVALID_CSUM 0x0000
#endif
+static void tcp_lro_rx_done(struct lro_ctrl *lc);
+
int
tcp_lro_init(struct lro_ctrl *lc)
{
@@ -91,8 +93,8 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp,
lc->lro_ackcnt_lim = TCP_LRO_ACKCNT_MAX;
lc->lro_length_lim = TCP_LRO_LENGTH_MAX;
lc->ifp = ifp;
- SLIST_INIT(&lc->lro_free);
- SLIST_INIT(&lc->lro_active);
+ LIST_INIT(&lc->lro_free);
+ LIST_INIT(&lc->lro_active);
/* compute size to allocate */
size = (lro_mbufs * sizeof(struct mbuf *)) +
@@ -111,7 +113,7 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp,
/* setup linked list */
for (i = 0; i != lro_entries; i++)
- SLIST_INSERT_HEAD(&lc->lro_free, le + i, next);
+ LIST_INSERT_HEAD(&lc->lro_free, le + i, next);
return (0);
}
@@ -123,11 +125,11 @@ tcp_lro_free(struct lro_ctrl *lc)
unsigned x;
/* reset LRO free list */
- SLIST_INIT(&lc->lro_free);
+ LIST_INIT(&lc->lro_free);
/* free active mbufs, if any */
- while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lc->lro_active, next);
+ while ((le = LIST_FIRST(&lc->lro_active)) != NULL) {
+ LIST_REMOVE(le, next);
m_freem(le->m_head);
}
@@ -226,20 +228,31 @@ tcp_lro_rx_csum_fixup(struct lro_entry *le, void *l3hdr, struct tcphdr *th,
}
#endif
+static void
+tcp_lro_rx_done(struct lro_ctrl *lc)
+{
+ struct lro_entry *le;
+
+ while ((le = LIST_FIRST(&lc->lro_active)) != NULL) {
+ LIST_REMOVE(le, next);
+ tcp_lro_flush(lc, le);
+ }
+}
+
void
tcp_lro_flush_inactive(struct lro_ctrl *lc, const struct timeval *timeout)
{
struct lro_entry *le, *le_tmp;
struct timeval tv;
- if (SLIST_EMPTY(&lc->lro_active))
+ if (LIST_EMPTY(&lc->lro_active))
return;
getmicrotime(&tv);
timevalsub(&tv, timeout);
- SLIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) {
+ LIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) {
if (timevalcmp(&tv, &le->mtime, >=)) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
}
}
@@ -335,7 +348,7 @@ tcp_lro_flush(struct lro_ctrl *lc, struct lro_entry *le)
lc->lro_queued += le->append_cnt + 1;
lc->lro_flushed++;
bzero(le, sizeof(*le));
- SLIST_INSERT_HEAD(&lc->lro_free, le, next);
+ LIST_INSERT_HEAD(&lc->lro_free, le, next);
}
static int
@@ -362,13 +375,12 @@ done:
void
tcp_lro_flush_all(struct lro_ctrl *lc)
{
- struct lro_entry *le;
uint32_t hashtype;
uint32_t flowid;
unsigned x;
/* check if no mbufs to flush */
- if (__predict_false(lc->lro_mbuf_count == 0))
+ if (lc->lro_mbuf_count == 0)
goto done;
/* sort all mbufs according to stream */
@@ -390,10 +402,7 @@ tcp_lro_flush_all(struct lro_ctrl *lc)
hashtype = M_HASHTYPE_GET(mb);
/* flush active streams */
- while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lc->lro_active, next);
- tcp_lro_flush(lc, le);
- }
+ tcp_lro_rx_done(lc);
}
#ifdef TCP_LRO_RESET_SEQUENCE
/* reset sequence number */
@@ -409,10 +418,8 @@ tcp_lro_flush_all(struct lro_ctrl *lc)
}
done:
/* flush active streams */
- while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lc->lro_active, next);
- tcp_lro_flush(lc, le);
- }
+ tcp_lro_rx_done(lc);
+
lc->lro_mbuf_count = 0;
}
@@ -586,7 +593,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
seq = ntohl(th->th_seq);
/* Try to find a matching previous segment. */
- SLIST_FOREACH(le, &lc->lro_active, next) {
+ LIST_FOREACH(le, &lc->lro_active, next) {
if (le->eh_type != eh_type)
continue;
if (le->source_port != th->th_sport ||
@@ -613,7 +620,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
/* Flush now if appending will result in overflow. */
if (le->p_len > (lc->lro_length_lim - tcp_data_len)) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
break;
}
@@ -622,7 +629,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
if (__predict_false(seq != le->next_seq ||
(tcp_data_len == 0 && le->ack_seq == th->th_ack))) {
/* Out of order packet or duplicate ACK. */
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
return (TCP_LRO_CANNOT);
}
@@ -655,8 +662,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
* be further delayed.
*/
if (le->append_cnt >= lc->lro_ackcnt_lim) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry,
- next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
}
return (0);
@@ -680,7 +686,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
* overflow, pro-actively flush now.
*/
if (le->p_len > (lc->lro_length_lim - lc->ifp->if_mtu)) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
} else
getmicrotime(&le->mtime);
@@ -689,13 +695,13 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
}
/* Try to find an empty slot. */
- if (SLIST_EMPTY(&lc->lro_free))
- return (TCP_LRO_CANNOT);
+ if (LIST_EMPTY(&lc->lro_free))
+ return (TCP_LRO_NO_ENTRIES);
/* Start a new segment chain. */
- le = SLIST_FIRST(&lc->lro_free);
- SLIST_REMOVE_HEAD(&lc->lro_free, next);
- SLIST_INSERT_HEAD(&lc->lro_active, le, next);
+ le = LIST_FIRST(&lc->lro_free);
+ LIST_REMOVE(le, next);
+ LIST_INSERT_HEAD(&lc->lro_active, le, next);
getmicrotime(&le->mtime);
/* Start filling in details. */
diff --git a/sys/netinet/tcp_lro.h b/sys/netinet/tcp_lro.h
index 3fc627c..b81a950 100644
--- a/sys/netinet/tcp_lro.h
+++ b/sys/netinet/tcp_lro.h
@@ -41,9 +41,8 @@
#define TCP_LRO_SEQUENCE(mb) \
(mb)->m_pkthdr.PH_loc.thirtytwo[0]
-struct lro_entry
-{
- SLIST_ENTRY(lro_entry) next;
+struct lro_entry {
+ LIST_ENTRY(lro_entry) next;
struct mbuf *m_head;
struct mbuf *m_tail;
union {
@@ -72,7 +71,7 @@ struct lro_entry
uint16_t timestamp; /* flag, not a TCP hdr field. */
struct timeval mtime;
};
-SLIST_HEAD(lro_head, lro_entry);
+LIST_HEAD(lro_head, lro_entry);
#define le_ip4 leip.ip4
#define le_ip6 leip.ip6
@@ -110,6 +109,7 @@ void tcp_lro_flush_all(struct lro_ctrl *);
int tcp_lro_rx(struct lro_ctrl *, struct mbuf *, uint32_t);
void tcp_lro_queue_mbuf(struct lro_ctrl *, struct mbuf *);
+#define TCP_LRO_NO_ENTRIES -2
#define TCP_LRO_CANNOT -1
#define TCP_LRO_NOT_SUPPORTED 1
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 96a8700..2043fc9 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1379,9 +1379,6 @@ send:
#endif
#ifdef INET
{
- struct route ro;
-
- bzero(&ro, sizeof(ro));
ip->ip_len = htons(m->m_pkthdr.len);
#ifdef INET6
if (tp->t_inpcb->inp_vflag & INP_IPV6PROTO)
@@ -1412,13 +1409,12 @@ send:
tcp_pcap_add(th, m, &(tp->t_outpkts));
#endif
- error = ip_output(m, tp->t_inpcb->inp_options, &ro,
+ error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0,
tp->t_inpcb);
- if (error == EMSGSIZE && ro.ro_rt != NULL)
- mtu = ro.ro_rt->rt_mtu;
- RO_RTFREE(&ro);
+ if (error == EMSGSIZE && tp->t_inpcb->inp_route.ro_rt != NULL)
+ mtu = tp->t_inpcb->inp_route.ro_rt->rt_mtu;
}
#endif /* INET */
@@ -1652,7 +1648,7 @@ tcp_setpersist(struct tcpcb *tp)
int
tcp_addoptions(struct tcpopt *to, u_char *optp)
{
- u_int mask, optlen = 0;
+ u_int32_t mask, optlen = 0;
for (mask = 1; mask < TOF_MAXOPT; mask <<= 1) {
if ((to->to_flags & mask) != mask)
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index ff218dd..33b16ad 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1542,7 +1542,7 @@ tcp_close(struct tcpcb *tp)
#endif
in_pcbdrop(inp);
TCPSTAT_INC(tcps_closed);
- TCPSTAT_DEC(tcps_states[tp->t_state]);
+ TCPSTATES_DEC(tp->t_state);
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
so = inp->inp_socket;
soisdisconnected(so);
@@ -1632,6 +1632,10 @@ tcp_notify(struct inpcb *inp, int error)
if (tp->t_state == TCPS_ESTABLISHED &&
(error == EHOSTUNREACH || error == ENETUNREACH ||
error == EHOSTDOWN)) {
+ if (inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
return (inp);
} else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
tp->t_softerror) {
@@ -1665,7 +1669,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
*/
if (req->oldptr == NULL) {
n = V_tcbinfo.ipi_count +
- TCPSTAT_FETCH(tcps_states[TCPS_SYN_RECEIVED]);
+ counter_u64_fetch(VNET(tcps_states)[TCPS_SYN_RECEIVED]);
n += imax(n / 8, 10);
req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xtcpcb);
return (0);
@@ -1682,7 +1686,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
n = V_tcbinfo.ipi_count;
INP_LIST_RUNLOCK(&V_tcbinfo);
- m = TCPSTAT_FETCH(tcps_states[TCPS_SYN_RECEIVED]);
+ m = counter_u64_fetch(VNET(tcps_states)[TCPS_SYN_RECEIVED]);
error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
+ (n + m) * sizeof(struct xtcpcb));
@@ -1702,8 +1706,6 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
return (error);
inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
- if (inp_list == NULL)
- return (ENOMEM);
INP_INFO_WLOCK(&V_tcbinfo);
for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0;
@@ -1926,11 +1928,11 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
notify = tcp_drop_syn_sent;
- /*
- * Redirects don't need to be handled up here.
- */
- else if (PRC_IS_REDIRECT(cmd))
+ else if (PRC_IS_REDIRECT(cmd)) {
+ /* signal EHOSTDOWN, as it flushes the cached route */
+ in_pcbnotifyall(&V_tcbinfo, faddr, EHOSTDOWN, notify);
return;
+ }
/*
* Hostdead is ugly because it goes linearly through all PCBs.
* XXX: We never get this from ICMP, otherwise it makes an
@@ -2986,8 +2988,8 @@ tcp_state_change(struct tcpcb *tp, int newstate)
int pstate = tp->t_state;
#endif
- TCPSTAT_DEC(tcps_states[tp->t_state]);
- TCPSTAT_INC(tcps_states[newstate]);
+ TCPSTATES_DEC(tp->t_state);
+ TCPSTATES_INC(newstate);
tp->t_state = newstate;
TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 0ff7318..b898c49 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -351,7 +351,7 @@ syncache_insert(struct syncache *sc, struct syncache_head *sch)
SCH_UNLOCK(sch);
- TCPSTAT_INC(tcps_states[TCPS_SYN_RECEIVED]);
+ TCPSTATES_INC(TCPS_SYN_RECEIVED);
TCPSTAT_INC(tcps_sc_added);
}
@@ -365,7 +365,7 @@ syncache_drop(struct syncache *sc, struct syncache_head *sch)
SCH_LOCK_ASSERT(sch);
- TCPSTAT_DEC(tcps_states[TCPS_SYN_RECEIVED]);
+ TCPSTATES_DEC(TCPS_SYN_RECEIVED);
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
sch->sch_length--;
@@ -1003,7 +1003,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* sonewconn->tcp_usr_attach in TCPS_CLOSED state, then
* syncache_socket() will change it to TCPS_SYN_RECEIVED.
*/
- TCPSTAT_DEC(tcps_states[TCPS_SYN_RECEIVED]);
+ TCPSTATES_DEC(TCPS_SYN_RECEIVED);
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
sch->sch_length--;
#ifdef TCP_OFFLOAD
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 046feba..172c394 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -786,7 +786,9 @@ tcp_timer_rexmt(void * xtp)
#ifdef INET6
if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
in6_losing(tp->t_inpcb);
+ else
#endif
+ in_losing(tp->t_inpcb);
tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
tp->t_srtt = 0;
}
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index c98de24..ff36ce7 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -660,7 +660,7 @@ tcp_tw_2msl_stop(struct tcptw *tw, int reuse)
if (!reuse)
uma_zfree(V_tcptw_zone, tw);
- TCPSTAT_DEC(tcps_states[TCPS_TIME_WAIT]);
+ TCPSTATES_DEC(TCPS_TIME_WAIT);
}
struct tcptw *
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 09493f0..6a3cde6 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1883,7 +1883,7 @@ tcp_attach(struct socket *so)
tp->t_state = TCPS_CLOSED;
INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
- TCPSTAT_INC(tcps_states[TCPS_CLOSED]);
+ TCPSTATES_INC(TCPS_CLOSED);
return (0);
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 2f23881..d60ad9f 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -364,7 +364,7 @@ struct tcpcb {
* options in tcp_addoptions.
*/
struct tcpopt {
- u_int64_t to_flags; /* which options are present */
+ u_int32_t to_flags; /* which options are present */
#define TOF_MSS 0x0001 /* maximum segment size */
#define TOF_SCALE 0x0002 /* window scaling */
#define TOF_SACKPERM 0x0004 /* SACK permitted */
@@ -588,9 +588,6 @@ struct tcpstat {
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
- /* Running connection count. */
- uint64_t tcps_states[TCP_NSTATES];
-
uint64_t _pad[12]; /* 6 UTO, 6 TBD */
};
@@ -609,9 +606,6 @@ VNET_PCPUSTAT_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */
#define TCPSTAT_ADD(name, val) \
VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val))
#define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1)
-#define TCPSTAT_DEC(name) TCPSTAT_ADD(name, -1)
-#define TCPSTAT_FETCH(name) VNET_PCPUSTAT_FETCH(struct tcpstat, tcpstat, \
- name)
/*
* Kernel module consumers must use this accessor macro.
@@ -621,6 +615,13 @@ void kmod_tcpstat_inc(int statnum);
kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(uint64_t))
/*
+ * Running TCP connection count by state.
+ */
+VNET_DECLARE(counter_u64_t, tcps_states[TCP_NSTATES]);
+#define TCPSTATES_INC(state) counter_u64_add(VNET(tcps_states)[state], 1)
+#define TCPSTATES_DEC(state) counter_u64_add(VNET(tcps_states)[state], -1)
+
+/*
* TCP specific helper hook point identifiers.
*/
#define HHOOK_TCP_EST_IN 0
@@ -678,6 +679,7 @@ struct xtcpcb {
#define TCPCTL_V6MSSDFLT 13 /* MSS default for IPv6 */
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
#define TCPCTL_DROP 15 /* drop tcp connection */
+#define TCPCTL_STATES 16 /* connection counts by TCP state */
#ifdef _KERNEL
#ifdef SYSCTL_DECL
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index f474a54..56aa56f 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -740,6 +740,11 @@ udp_notify(struct inpcb *inp, int errno)
* or a write lock, but a read lock is sufficient.
*/
INP_LOCK_ASSERT(inp);
+ if ((errno == EHOSTUNREACH || errno == ENETUNREACH ||
+ errno == EHOSTDOWN) && inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
inp->inp_socket->so_error = errno;
sorwakeup(inp->inp_socket);
@@ -761,11 +766,11 @@ udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip,
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
return;
- /*
- * Redirects don't need to be handled up here.
- */
- if (PRC_IS_REDIRECT(cmd))
+ if (PRC_IS_REDIRECT(cmd)) {
+ /* signal EHOSTDOWN, as it flushes the cached route */
+ in_pcbnotifyall(&V_udbinfo, faddr, EHOSTDOWN, udp_notify);
return;
+ }
/*
* Hostdead is ugly because it goes linearly through all PCBs.
@@ -1116,7 +1121,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
int error = 0;
int ipflags;
u_short fport, lport;
- int unlock_udbinfo;
+ int unlock_udbinfo, unlock_inp;
u_char tos;
uint8_t pr;
uint16_t cscov = 0;
@@ -1137,7 +1142,15 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
}
src.sin_family = 0;
- INP_RLOCK(inp);
+ sin = (struct sockaddr_in *)addr;
+ if (sin == NULL ||
+ (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
+ INP_WLOCK(inp);
+ unlock_inp = UH_WLOCKED;
+ } else {
+ INP_RLOCK(inp);
+ unlock_inp = UH_RLOCKED;
+ }
tos = inp->inp_ip_tos;
if (control != NULL) {
/*
@@ -1145,7 +1158,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
* stored in a single mbuf.
*/
if (control->m_next) {
- INP_RUNLOCK(inp);
+ if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
m_freem(control);
m_freem(m);
return (EINVAL);
@@ -1220,7 +1236,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
m_freem(control);
}
if (error) {
- INP_RUNLOCK(inp);
+ if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
m_freem(m);
return (error);
}
@@ -1246,8 +1265,6 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
sin = (struct sockaddr_in *)addr;
if (sin != NULL &&
(inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
- INP_RUNLOCK(inp);
- INP_WLOCK(inp);
INP_HASH_WLOCK(pcbinfo);
unlock_udbinfo = UH_WLOCKED;
} else if ((sin != NULL && (
@@ -1514,9 +1531,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
else if (unlock_udbinfo == UH_RLOCKED)
INP_HASH_RUNLOCK(pcbinfo);
UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u);
- error = ip_output(m, inp->inp_options, NULL, ipflags,
+ error = ip_output(m, inp->inp_options,
+ (unlock_inp == UH_WLOCKED ? &inp->inp_route : NULL), ipflags,
inp->inp_moptions, inp);
- if (unlock_udbinfo == UH_WLOCKED)
+ if (unlock_inp == UH_WLOCKED)
INP_WUNLOCK(inp);
else
INP_RUNLOCK(inp);
OpenPOWER on IntegriCloud