mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1815 commits) mac80211: fix reorder buffer release iwmc3200wifi: Enable wimax core through module parameter iwmc3200wifi: Add wifi-wimax coexistence mode as a module parameter iwmc3200wifi: Coex table command does not expect a response iwmc3200wifi: Update wiwi priority table iwlwifi: driver version track kernel version iwlwifi: indicate uCode type when fail dump error/event log iwl3945: remove duplicated event logging code b43: fix two warnings ipw2100: fix rebooting hang with driver loaded cfg80211: indent regulatory messages with spaces iwmc3200wifi: fix NULL pointer dereference in pmkid update mac80211: Fix TX status reporting for injected data frames ath9k: enable 2GHz band only if the device supports it airo: Fix integer overflow warning rt2x00: Fix padding bug on L2PAD devices. WE: Fix set events not propagated b43legacy: avoid PPC fault during resume b43: avoid PPC fault during resume tcp: fix a timewait refcnt race ... Fix up conflicts due to sysctl cleanups (dead sysctl_check code and CTL_UNNUMBERED removed) in kernel/sysctl_check.c net/ipv4/sysctl_net_ipv4.c net/ipv6/addrconf.c net/sctp/sysctl.c
This commit is contained in:
commit
d7fc02c7ba
1394 changed files with 113445 additions and 70680 deletions
|
|
@ -63,6 +63,12 @@
|
|||
static void sctp_assoc_bh_rcv(struct work_struct *work);
|
||||
static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
|
||||
|
||||
/* Keep track of the new idr low so that we don't re-use association id
|
||||
* numbers too fast. It is protected by they idr spin lock is in the
|
||||
* range of 1 - INT_MAX.
|
||||
*/
|
||||
static u32 idr_low = 1;
|
||||
|
||||
|
||||
/* 1st Level Abstractions. */
|
||||
|
||||
|
|
@ -167,7 +173,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
|
|||
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
|
||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
|
||||
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
|
||||
sp->autoclose * HZ;
|
||||
(unsigned long)sp->autoclose * HZ;
|
||||
|
||||
/* Initilizes the timers */
|
||||
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
|
||||
|
|
@ -512,7 +518,13 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
|
|||
* to this destination address earlier. The sender MUST set
|
||||
* CYCLING_CHANGEOVER to indicate that this switch is a
|
||||
* double switch to the same destination address.
|
||||
*
|
||||
* Really, only bother is we have data queued or outstanding on
|
||||
* the association.
|
||||
*/
|
||||
if (!asoc->outqueue.outstanding_bytes && !asoc->outqueue.out_qlen)
|
||||
return;
|
||||
|
||||
if (transport->cacc.changeover_active)
|
||||
transport->cacc.cycling_changeover = changeover;
|
||||
|
||||
|
|
@ -732,6 +744,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
|
|||
|
||||
peer->partial_bytes_acked = 0;
|
||||
peer->flight_size = 0;
|
||||
peer->burst_limited = 0;
|
||||
|
||||
/* Set the transport's RTO.initial value */
|
||||
peer->rto = asoc->rto_initial;
|
||||
|
|
@ -1377,8 +1390,9 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc)
|
|||
case SCTP_STATE_SHUTDOWN_RECEIVED:
|
||||
case SCTP_STATE_SHUTDOWN_SENT:
|
||||
if ((asoc->rwnd > asoc->a_rwnd) &&
|
||||
((asoc->rwnd - asoc->a_rwnd) >=
|
||||
min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pathmtu)))
|
||||
((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32,
|
||||
(asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift),
|
||||
asoc->pathmtu)))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1545,7 +1559,12 @@ retry:
|
|||
|
||||
spin_lock_bh(&sctp_assocs_id_lock);
|
||||
error = idr_get_new_above(&sctp_assocs_id, (void *)asoc,
|
||||
1, &assoc_id);
|
||||
idr_low, &assoc_id);
|
||||
if (!error) {
|
||||
idr_low = assoc_id + 1;
|
||||
if (idr_low == INT_MAX)
|
||||
idr_low = 1;
|
||||
}
|
||||
spin_unlock_bh(&sctp_assocs_id_lock);
|
||||
if (error == -EAGAIN)
|
||||
goto retry;
|
||||
|
|
|
|||
|
|
@ -263,9 +263,18 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
|||
if (0 == i)
|
||||
frag |= SCTP_DATA_FIRST_FRAG;
|
||||
|
||||
if ((i == (whole - 1)) && !over)
|
||||
if ((i == (whole - 1)) && !over) {
|
||||
frag |= SCTP_DATA_LAST_FRAG;
|
||||
|
||||
/* The application requests to set the I-bit of the
|
||||
* last DATA chunk of a user message when providing
|
||||
* the user message to the SCTP implementation.
|
||||
*/
|
||||
if ((sinfo->sinfo_flags & SCTP_EOF) ||
|
||||
(sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
|
||||
frag |= SCTP_DATA_SACK_IMM;
|
||||
}
|
||||
|
||||
chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
|
||||
|
||||
if (!chunk)
|
||||
|
|
@ -297,6 +306,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
|
|||
else
|
||||
frag = SCTP_DATA_LAST_FRAG;
|
||||
|
||||
if ((sinfo->sinfo_flags & SCTP_EOF) ||
|
||||
(sinfo->sinfo_flags & SCTP_SACK_IMMEDIATELY))
|
||||
frag |= SCTP_DATA_SACK_IMM;
|
||||
|
||||
chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
|
||||
|
||||
if (!chunk)
|
||||
|
|
|
|||
|
|
@ -837,15 +837,16 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
|
|||
if (type & IPV6_ADDR_LINKLOCAL) {
|
||||
if (!addr->v6.sin6_scope_id)
|
||||
return 0;
|
||||
dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
|
||||
if (!dev)
|
||||
return 0;
|
||||
if (!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(&init_net,
|
||||
addr->v6.sin6_scope_id);
|
||||
if (!dev ||
|
||||
!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr,
|
||||
dev, 0)) {
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
} else if (type == IPV6_ADDR_MAPPED) {
|
||||
if (!opt->v4mapped)
|
||||
return 0;
|
||||
|
|
@ -873,10 +874,12 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
|
|||
if (type & IPV6_ADDR_LINKLOCAL) {
|
||||
if (!addr->v6.sin6_scope_id)
|
||||
return 0;
|
||||
dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id);
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(&init_net,
|
||||
addr->v6.sin6_scope_id);
|
||||
rcu_read_unlock();
|
||||
if (!dev)
|
||||
return 0;
|
||||
dev_put(dev);
|
||||
}
|
||||
af = opt->pf->af;
|
||||
}
|
||||
|
|
@ -930,7 +933,6 @@ static struct inet_protosw sctpv6_seqpacket_protosw = {
|
|||
.protocol = IPPROTO_SCTP,
|
||||
.prot = &sctpv6_prot,
|
||||
.ops = &inet6_seqpacket_ops,
|
||||
.capability = -1,
|
||||
.no_check = 0,
|
||||
.flags = SCTP_PROTOSW_FLAG
|
||||
};
|
||||
|
|
@ -939,7 +941,6 @@ static struct inet_protosw sctpv6_stream_protosw = {
|
|||
.protocol = IPPROTO_SCTP,
|
||||
.prot = &sctpv6_prot,
|
||||
.ops = &inet6_seqpacket_ops,
|
||||
.capability = -1,
|
||||
.no_check = 0,
|
||||
.flags = SCTP_PROTOSW_FLAG,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -429,23 +429,22 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|||
list_del_init(&chunk->list);
|
||||
if (sctp_chunk_is_data(chunk)) {
|
||||
|
||||
if (!chunk->has_tsn) {
|
||||
sctp_chunk_assign_ssn(chunk);
|
||||
sctp_chunk_assign_tsn(chunk);
|
||||
if (!chunk->resent) {
|
||||
|
||||
/* 6.3.1 C4) When data is in flight and when allowed
|
||||
* by rule C5, a new RTT measurement MUST be made each
|
||||
* round trip. Furthermore, new RTT measurements
|
||||
* SHOULD be made no more than once per round-trip
|
||||
* for a given destination transport address.
|
||||
*/
|
||||
/* 6.3.1 C4) When data is in flight and when allowed
|
||||
* by rule C5, a new RTT measurement MUST be made each
|
||||
* round trip. Furthermore, new RTT measurements
|
||||
* SHOULD be made no more than once per round-trip
|
||||
* for a given destination transport address.
|
||||
*/
|
||||
|
||||
if (!tp->rto_pending) {
|
||||
chunk->rtt_in_progress = 1;
|
||||
tp->rto_pending = 1;
|
||||
}
|
||||
} else
|
||||
chunk->resent = 1;
|
||||
}
|
||||
|
||||
chunk->resent = 1;
|
||||
|
||||
has_data = 1;
|
||||
}
|
||||
|
|
@ -557,8 +556,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|||
struct timer_list *timer;
|
||||
unsigned long timeout;
|
||||
|
||||
tp->last_time_used = jiffies;
|
||||
|
||||
/* Restart the AUTOCLOSE timer when sending data. */
|
||||
if (sctp_state(asoc, ESTABLISHED) && asoc->autoclose) {
|
||||
timer = &asoc->timers[SCTP_EVENT_TIMEOUT_AUTOCLOSE];
|
||||
|
|
@ -617,7 +614,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
|
|||
sctp_xmit_t retval = SCTP_XMIT_OK;
|
||||
size_t datasize, rwnd, inflight, flight_size;
|
||||
struct sctp_transport *transport = packet->transport;
|
||||
__u32 max_burst_bytes;
|
||||
struct sctp_association *asoc = transport->asoc;
|
||||
struct sctp_outq *q = &asoc->outqueue;
|
||||
|
||||
|
|
@ -650,28 +646,6 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet,
|
|||
}
|
||||
}
|
||||
|
||||
/* sctpimpguide-05 2.14.2
|
||||
* D) When the time comes for the sender to
|
||||
* transmit new DATA chunks, the protocol parameter Max.Burst MUST
|
||||
* first be applied to limit how many new DATA chunks may be sent.
|
||||
* The limit is applied by adjusting cwnd as follows:
|
||||
* if ((flightsize + Max.Burst * MTU) < cwnd)
|
||||
* cwnd = flightsize + Max.Burst * MTU
|
||||
*/
|
||||
max_burst_bytes = asoc->max_burst * asoc->pathmtu;
|
||||
if ((flight_size + max_burst_bytes) < transport->cwnd) {
|
||||
transport->cwnd = flight_size + max_burst_bytes;
|
||||
SCTP_DEBUG_PRINTK("%s: cwnd limited by max_burst: "
|
||||
"transport: %p, cwnd: %d, "
|
||||
"ssthresh: %d, flight_size: %d, "
|
||||
"pba: %d\n",
|
||||
__func__, transport,
|
||||
transport->cwnd,
|
||||
transport->ssthresh,
|
||||
transport->flight_size,
|
||||
transport->partial_bytes_acked);
|
||||
}
|
||||
|
||||
/* RFC 2960 6.1 Transmission of DATA Chunks
|
||||
*
|
||||
* B) At any given time, the sender MUST NOT transmit new data
|
||||
|
|
@ -747,6 +721,8 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
|
|||
/* Has been accepted for transmission. */
|
||||
if (!asoc->peer.prsctp_capable)
|
||||
chunk->msg->can_abandon = 0;
|
||||
sctp_chunk_assign_tsn(chunk);
|
||||
sctp_chunk_assign_ssn(chunk);
|
||||
}
|
||||
|
||||
static sctp_xmit_t sctp_packet_will_fit(struct sctp_packet *packet,
|
||||
|
|
|
|||
|
|
@ -191,8 +191,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary,
|
|||
__u32 tsn)
|
||||
{
|
||||
if (primary->cacc.changeover_active &&
|
||||
(sctp_cacc_skip_3_1(primary, transport, count_of_newacks)
|
||||
|| sctp_cacc_skip_3_2(primary, tsn)))
|
||||
(sctp_cacc_skip_3_1(primary, transport, count_of_newacks) ||
|
||||
sctp_cacc_skip_3_2(primary, tsn)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -921,6 +921,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||
goto sctp_flush_out;
|
||||
}
|
||||
|
||||
/* Apply Max.Burst limitation to the current transport in
|
||||
* case it will be used for new data. We are going to
|
||||
* rest it before we return, but we want to apply the limit
|
||||
* to the currently queued data.
|
||||
*/
|
||||
if (transport)
|
||||
sctp_transport_burst_limited(transport);
|
||||
|
||||
/* Finally, transmit new packets. */
|
||||
while ((chunk = sctp_outq_dequeue_data(q)) != NULL) {
|
||||
/* RFC 2960 6.5 Every DATA chunk MUST carry a valid
|
||||
|
|
@ -966,6 +974,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||
packet = &transport->packet;
|
||||
sctp_packet_config(packet, vtag,
|
||||
asoc->peer.ecn_capable);
|
||||
/* We've switched transports, so apply the
|
||||
* Burst limit to the new transport.
|
||||
*/
|
||||
sctp_transport_burst_limited(transport);
|
||||
}
|
||||
|
||||
SCTP_DEBUG_PRINTK("sctp_outq_flush(%p, %p[%s]), ",
|
||||
|
|
@ -1001,6 +1013,13 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
|
|||
break;
|
||||
|
||||
case SCTP_XMIT_OK:
|
||||
/* The sender is in the SHUTDOWN-PENDING state,
|
||||
* The sender MAY set the I-bit in the DATA
|
||||
* chunk header.
|
||||
*/
|
||||
if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING)
|
||||
chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1053,6 +1072,9 @@ sctp_flush_out:
|
|||
packet = &t->packet;
|
||||
if (!sctp_packet_empty(packet))
|
||||
error = sctp_packet_transmit(packet);
|
||||
|
||||
/* Clear the burst limited state, if any */
|
||||
sctp_transport_burst_reset(t);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
|
|
|||
|
|
@ -205,14 +205,14 @@ static void sctp_get_local_addr_list(void)
|
|||
struct list_head *pos;
|
||||
struct sctp_af *af;
|
||||
|
||||
read_lock(&dev_base_lock);
|
||||
for_each_netdev(&init_net, dev) {
|
||||
rcu_read_lock();
|
||||
for_each_netdev_rcu(&init_net, dev) {
|
||||
__list_for_each(pos, &sctp_address_families) {
|
||||
af = list_entry(pos, struct sctp_af, list);
|
||||
af->copy_addrlist(&sctp_local_addr_list, dev);
|
||||
}
|
||||
}
|
||||
read_unlock(&dev_base_lock);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* Free the existing local addresses. */
|
||||
|
|
@ -296,19 +296,19 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
|
|||
{
|
||||
addr->v4.sin_family = AF_INET;
|
||||
addr->v4.sin_port = 0;
|
||||
addr->v4.sin_addr.s_addr = inet_sk(sk)->rcv_saddr;
|
||||
addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr;
|
||||
}
|
||||
|
||||
/* Initialize sk->sk_rcv_saddr from sctp_addr. */
|
||||
static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
|
||||
{
|
||||
inet_sk(sk)->rcv_saddr = addr->v4.sin_addr.s_addr;
|
||||
inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
/* Initialize sk->sk_daddr from sctp_addr. */
|
||||
static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
|
||||
{
|
||||
inet_sk(sk)->daddr = addr->v4.sin_addr.s_addr;
|
||||
inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
/* Initialize a sctp_addr from an address parameter. */
|
||||
|
|
@ -598,7 +598,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
|
|||
|
||||
newinet = inet_sk(newsk);
|
||||
|
||||
newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
|
||||
newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
|
||||
|
||||
sk_refcnt_debug_inc(newsk);
|
||||
|
||||
|
|
@ -909,7 +909,6 @@ static struct inet_protosw sctp_seqpacket_protosw = {
|
|||
.protocol = IPPROTO_SCTP,
|
||||
.prot = &sctp_prot,
|
||||
.ops = &inet_seqpacket_ops,
|
||||
.capability = -1,
|
||||
.no_check = 0,
|
||||
.flags = SCTP_PROTOSW_FLAG
|
||||
};
|
||||
|
|
@ -918,7 +917,6 @@ static struct inet_protosw sctp_stream_protosw = {
|
|||
.protocol = IPPROTO_SCTP,
|
||||
.prot = &sctp_prot,
|
||||
.ops = &inet_seqpacket_ops,
|
||||
.capability = -1,
|
||||
.no_check = 0,
|
||||
.flags = SCTP_PROTOSW_FLAG
|
||||
};
|
||||
|
|
@ -1260,6 +1258,9 @@ SCTP_STATIC __init int sctp_init(void)
|
|||
/* Set SCOPE policy to enabled */
|
||||
sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE;
|
||||
|
||||
/* Set the default rwnd update threshold */
|
||||
sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT;
|
||||
|
||||
sctp_sysctl_register();
|
||||
|
||||
INIT_LIST_HEAD(&sctp_address_families);
|
||||
|
|
|
|||
|
|
@ -987,7 +987,10 @@ static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
|
|||
|
||||
target = skb_put(chunk->skb, len);
|
||||
|
||||
memcpy(target, data, len);
|
||||
if (data)
|
||||
memcpy(target, data, len);
|
||||
else
|
||||
memset(target, 0, len);
|
||||
|
||||
/* Adjust the chunk length field. */
|
||||
chunk->chunk_hdr->length = htons(chunklen + len);
|
||||
|
|
@ -1129,16 +1132,18 @@ nodata:
|
|||
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
|
||||
const struct sctp_chunk *chunk,
|
||||
__be16 cause_code, const void *payload,
|
||||
size_t paylen)
|
||||
size_t paylen, size_t reserve_tail)
|
||||
{
|
||||
struct sctp_chunk *retval;
|
||||
|
||||
retval = sctp_make_op_error_space(asoc, chunk, paylen);
|
||||
retval = sctp_make_op_error_space(asoc, chunk, paylen + reserve_tail);
|
||||
if (!retval)
|
||||
goto nodata;
|
||||
|
||||
sctp_init_cause(retval, cause_code, paylen);
|
||||
sctp_init_cause(retval, cause_code, paylen + reserve_tail);
|
||||
sctp_addto_chunk(retval, paylen, payload);
|
||||
if (reserve_tail)
|
||||
sctp_addto_param(retval, reserve_tail, NULL);
|
||||
|
||||
nodata:
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -217,8 +217,7 @@ static int sctp_gen_sack(struct sctp_association *asoc, int force,
|
|||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
||||
SCTP_TO(SCTP_EVENT_TIMEOUT_SACK));
|
||||
} else {
|
||||
if (asoc->a_rwnd > asoc->rwnd)
|
||||
asoc->a_rwnd = asoc->rwnd;
|
||||
asoc->a_rwnd = asoc->rwnd;
|
||||
sack = sctp_make_sack(asoc);
|
||||
if (!sack)
|
||||
goto nomem;
|
||||
|
|
@ -1417,6 +1416,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
|
|||
asoc->init_last_sent_to = t;
|
||||
chunk->transport = t;
|
||||
t->init_sent_count++;
|
||||
/* Set the new transport as primary */
|
||||
sctp_assoc_set_primary(asoc, t);
|
||||
break;
|
||||
|
||||
case SCTP_CMD_INIT_RESTART:
|
||||
|
|
|
|||
|
|
@ -996,14 +996,15 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,
|
|||
sctp_sf_heartbeat(ep, asoc, type, arg,
|
||||
commands))
|
||||
return SCTP_DISPOSITION_NOMEM;
|
||||
|
||||
/* Set transport error counter and association error counter
|
||||
* when sending heartbeat.
|
||||
*/
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
|
||||
SCTP_TRANSPORT(transport));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_HB_SENT,
|
||||
SCTP_TRANSPORT(transport));
|
||||
}
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_IDLE,
|
||||
SCTP_TRANSPORT(transport));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,
|
||||
SCTP_TRANSPORT(transport));
|
||||
|
||||
|
|
@ -1720,7 +1721,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,
|
|||
|
||||
err = sctp_make_op_error(asoc, chunk,
|
||||
SCTP_ERROR_COOKIE_IN_SHUTDOWN,
|
||||
NULL, 0);
|
||||
NULL, 0, 0);
|
||||
if (err)
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||
SCTP_CHUNK(err));
|
||||
|
|
@ -2868,6 +2869,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
|
|||
sctp_cmd_seq_t *commands)
|
||||
{
|
||||
struct sctp_chunk *chunk = arg;
|
||||
sctp_arg_t force = SCTP_NOFORCE();
|
||||
int error;
|
||||
|
||||
if (!sctp_vtag_verify(chunk, asoc)) {
|
||||
|
|
@ -2901,6 +2903,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
|
|||
BUG();
|
||||
}
|
||||
|
||||
if (chunk->chunk_hdr->flags & SCTP_DATA_SACK_IMM)
|
||||
force = SCTP_FORCE();
|
||||
|
||||
if (asoc->autoclose) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
|
||||
SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));
|
||||
|
|
@ -2929,7 +2934,7 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep,
|
|||
* more aggressive than the following algorithms allow.
|
||||
*/
|
||||
if (chunk->end_of_packet)
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
|
||||
|
||||
return SCTP_DISPOSITION_CONSUME;
|
||||
|
||||
|
|
@ -2954,7 +2959,7 @@ discard_force:
|
|||
|
||||
discard_noforce:
|
||||
if (chunk->end_of_packet)
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_NOFORCE());
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);
|
||||
|
||||
return SCTP_DISPOSITION_DISCARD;
|
||||
consume:
|
||||
|
|
@ -3973,7 +3978,7 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
|
|||
err_chunk = sctp_make_op_error(asoc, chunk,
|
||||
SCTP_ERROR_UNSUP_HMAC,
|
||||
&auth_hdr->hmac_id,
|
||||
sizeof(__u16));
|
||||
sizeof(__u16), 0);
|
||||
if (err_chunk) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||
SCTP_CHUNK(err_chunk));
|
||||
|
|
@ -4065,7 +4070,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
|
|||
hdr = unk_chunk->chunk_hdr;
|
||||
err_chunk = sctp_make_op_error(asoc, unk_chunk,
|
||||
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
|
||||
WORD_ROUND(ntohs(hdr->length)));
|
||||
WORD_ROUND(ntohs(hdr->length)),
|
||||
0);
|
||||
if (err_chunk) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||
SCTP_CHUNK(err_chunk));
|
||||
|
|
@ -4084,7 +4090,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep,
|
|||
hdr = unk_chunk->chunk_hdr;
|
||||
err_chunk = sctp_make_op_error(asoc, unk_chunk,
|
||||
SCTP_ERROR_UNKNOWN_CHUNK, hdr,
|
||||
WORD_ROUND(ntohs(hdr->length)));
|
||||
WORD_ROUND(ntohs(hdr->length)),
|
||||
0);
|
||||
if (err_chunk) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||
SCTP_CHUNK(err_chunk));
|
||||
|
|
@ -6048,7 +6055,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
|
|||
|
||||
err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
|
||||
&data_hdr->stream,
|
||||
sizeof(data_hdr->stream));
|
||||
sizeof(data_hdr->stream),
|
||||
sizeof(u16));
|
||||
if (err)
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
|
||||
SCTP_CHUNK(err));
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
|
|||
|
||||
/* Refresh ephemeral port. */
|
||||
if (!bp->port)
|
||||
bp->port = inet_sk(sk)->num;
|
||||
bp->port = inet_sk(sk)->inet_num;
|
||||
|
||||
/* Add the address to the bind address list.
|
||||
* Use GFP_ATOMIC since BHs will be disabled.
|
||||
|
|
@ -403,7 +403,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
|
|||
|
||||
/* Copy back into socket for getsockname() use. */
|
||||
if (!ret) {
|
||||
inet_sk(sk)->sport = htons(inet_sk(sk)->num);
|
||||
inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
|
||||
af->to_sk_saddr(addr, sk);
|
||||
}
|
||||
|
||||
|
|
@ -1117,7 +1117,7 @@ static int __sctp_connect(struct sock* sk,
|
|||
}
|
||||
|
||||
/* Initialize sk's dport and daddr for getpeername() */
|
||||
inet_sk(sk)->dport = htons(asoc->peer.port);
|
||||
inet_sk(sk)->inet_dport = htons(asoc->peer.port);
|
||||
af = sctp_get_af_specific(sa_addr->sa.sa_family);
|
||||
af->to_sk_daddr(sa_addr, sk);
|
||||
sk->sk_err = 0;
|
||||
|
|
@ -1968,7 +1968,7 @@ SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|||
if (err)
|
||||
goto out_free;
|
||||
|
||||
sock_recv_timestamp(msg, sk, skb);
|
||||
sock_recv_ts_and_drops(msg, sk, skb);
|
||||
if (sctp_ulpevent_is_notification(event)) {
|
||||
msg->msg_flags |= MSG_NOTIFICATION;
|
||||
sp->pf->event_msgname(event, msg->msg_name, addr_len);
|
||||
|
|
@ -2086,6 +2086,9 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
|
|||
return -EINVAL;
|
||||
if (copy_from_user(&sp->autoclose, optval, optlen))
|
||||
return -EFAULT;
|
||||
/* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */
|
||||
if (sp->autoclose > (MAX_SCHEDULE_TIMEOUT / HZ) )
|
||||
sp->autoclose = (__u32)(MAX_SCHEDULE_TIMEOUT / HZ) ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2311,11 +2314,10 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
|
|||
}
|
||||
}
|
||||
|
||||
/* Note that unless the spp_flag is set to SPP_PMTUD_ENABLE the value
|
||||
* of this field is ignored. Note also that a value of zero
|
||||
* indicates the current setting should be left unchanged.
|
||||
/* Note that a value of zero indicates the current setting should be
|
||||
left unchanged.
|
||||
*/
|
||||
if ((params->spp_flags & SPP_PMTUD_ENABLE) && params->spp_pathmaxrxt) {
|
||||
if (params->spp_pathmaxrxt) {
|
||||
if (trans) {
|
||||
trans->pathmaxrxt = params->spp_pathmaxrxt;
|
||||
} else if (asoc) {
|
||||
|
|
@ -2354,8 +2356,8 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
|
|||
pmtud_change == SPP_PMTUD ||
|
||||
sackdelay_change == SPP_SACKDELAY ||
|
||||
params.spp_sackdelay > 500 ||
|
||||
(params.spp_pathmtu
|
||||
&& params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT))
|
||||
(params.spp_pathmtu &&
|
||||
params.spp_pathmtu < SCTP_DEFAULT_MINSEGMENT))
|
||||
return -EINVAL;
|
||||
|
||||
/* If an address other than INADDR_ANY is specified, and
|
||||
|
|
@ -4349,90 +4351,6 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len,
|
||||
char __user *optval,
|
||||
int __user *optlen)
|
||||
{
|
||||
sctp_assoc_t id;
|
||||
struct sctp_association *asoc;
|
||||
struct list_head *pos;
|
||||
int cnt = 0;
|
||||
|
||||
if (len < sizeof(sctp_assoc_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
|
||||
return -EFAULT;
|
||||
|
||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_NUM_OLD "
|
||||
"socket option deprecated\n");
|
||||
/* For UDP-style sockets, id specifies the association to query. */
|
||||
asoc = sctp_id2assoc(sk, id);
|
||||
if (!asoc)
|
||||
return -EINVAL;
|
||||
|
||||
list_for_each(pos, &asoc->peer.transport_addr_list) {
|
||||
cnt ++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/*
|
||||
* Old API for getting list of peer addresses. Does not work for 32-bit
|
||||
* programs running on a 64-bit kernel
|
||||
*/
|
||||
static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
|
||||
char __user *optval,
|
||||
int __user *optlen)
|
||||
{
|
||||
struct sctp_association *asoc;
|
||||
int cnt = 0;
|
||||
struct sctp_getaddrs_old getaddrs;
|
||||
struct sctp_transport *from;
|
||||
void __user *to;
|
||||
union sctp_addr temp;
|
||||
struct sctp_sock *sp = sctp_sk(sk);
|
||||
int addrlen;
|
||||
|
||||
if (len < sizeof(struct sctp_getaddrs_old))
|
||||
return -EINVAL;
|
||||
|
||||
len = sizeof(struct sctp_getaddrs_old);
|
||||
|
||||
if (copy_from_user(&getaddrs, optval, len))
|
||||
return -EFAULT;
|
||||
|
||||
if (getaddrs.addr_num <= 0) return -EINVAL;
|
||||
|
||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_PEER_ADDRS_OLD "
|
||||
"socket option deprecated\n");
|
||||
|
||||
/* For UDP-style sockets, id specifies the association to query. */
|
||||
asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
|
||||
if (!asoc)
|
||||
return -EINVAL;
|
||||
|
||||
to = (void __user *)getaddrs.addrs;
|
||||
list_for_each_entry(from, &asoc->peer.transport_addr_list,
|
||||
transports) {
|
||||
memcpy(&temp, &from->ipaddr, sizeof(temp));
|
||||
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
|
||||
addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
|
||||
if (copy_to_user(to, &temp, addrlen))
|
||||
return -EFAULT;
|
||||
to += addrlen ;
|
||||
cnt ++;
|
||||
if (cnt >= getaddrs.addr_num) break;
|
||||
}
|
||||
getaddrs.addr_num = cnt;
|
||||
if (put_user(len, optlen))
|
||||
return -EFAULT;
|
||||
if (copy_to_user(optval, &getaddrs, len))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
|
||||
char __user *optval, int __user *optlen)
|
||||
|
|
@ -4485,125 +4403,6 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
|
||||
char __user *optval,
|
||||
int __user *optlen)
|
||||
{
|
||||
sctp_assoc_t id;
|
||||
struct sctp_bind_addr *bp;
|
||||
struct sctp_association *asoc;
|
||||
struct sctp_sockaddr_entry *addr;
|
||||
int cnt = 0;
|
||||
|
||||
if (len < sizeof(sctp_assoc_t))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
|
||||
return -EFAULT;
|
||||
|
||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_NUM_OLD "
|
||||
"socket option deprecated\n");
|
||||
|
||||
/*
|
||||
* For UDP-style sockets, id specifies the association to query.
|
||||
* If the id field is set to the value '0' then the locally bound
|
||||
* addresses are returned without regard to any particular
|
||||
* association.
|
||||
*/
|
||||
if (0 == id) {
|
||||
bp = &sctp_sk(sk)->ep->base.bind_addr;
|
||||
} else {
|
||||
asoc = sctp_id2assoc(sk, id);
|
||||
if (!asoc)
|
||||
return -EINVAL;
|
||||
bp = &asoc->base.bind_addr;
|
||||
}
|
||||
|
||||
/* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
|
||||
* addresses from the global local address list.
|
||||
*/
|
||||
if (sctp_list_single_entry(&bp->address_list)) {
|
||||
addr = list_entry(bp->address_list.next,
|
||||
struct sctp_sockaddr_entry, list);
|
||||
if (sctp_is_any(sk, &addr->a)) {
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(addr,
|
||||
&sctp_local_addr_list, list) {
|
||||
if (!addr->valid)
|
||||
continue;
|
||||
|
||||
if ((PF_INET == sk->sk_family) &&
|
||||
(AF_INET6 == addr->a.sa.sa_family))
|
||||
continue;
|
||||
|
||||
if ((PF_INET6 == sk->sk_family) &&
|
||||
inet_v6_ipv6only(sk) &&
|
||||
(AF_INET == addr->a.sa.sa_family))
|
||||
continue;
|
||||
|
||||
cnt++;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
} else {
|
||||
cnt = 1;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Protection on the bound address list is not needed,
|
||||
* since in the socket option context we hold the socket lock,
|
||||
* so there is no way that the bound address list can change.
|
||||
*/
|
||||
list_for_each_entry(addr, &bp->address_list, list) {
|
||||
cnt ++;
|
||||
}
|
||||
done:
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Helper function that copies local addresses to user and returns the number
|
||||
* of addresses copied.
|
||||
*/
|
||||
static int sctp_copy_laddrs_old(struct sock *sk, __u16 port,
|
||||
int max_addrs, void *to,
|
||||
int *bytes_copied)
|
||||
{
|
||||
struct sctp_sockaddr_entry *addr;
|
||||
union sctp_addr temp;
|
||||
int cnt = 0;
|
||||
int addrlen;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) {
|
||||
if (!addr->valid)
|
||||
continue;
|
||||
|
||||
if ((PF_INET == sk->sk_family) &&
|
||||
(AF_INET6 == addr->a.sa.sa_family))
|
||||
continue;
|
||||
if ((PF_INET6 == sk->sk_family) &&
|
||||
inet_v6_ipv6only(sk) &&
|
||||
(AF_INET == addr->a.sa.sa_family))
|
||||
continue;
|
||||
memcpy(&temp, &addr->a, sizeof(temp));
|
||||
if (!temp.v4.sin_port)
|
||||
temp.v4.sin_port = htons(port);
|
||||
|
||||
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
|
||||
&temp);
|
||||
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
|
||||
memcpy(to, &temp, addrlen);
|
||||
|
||||
to += addrlen;
|
||||
*bytes_copied += addrlen;
|
||||
cnt ++;
|
||||
if (cnt >= max_addrs) break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
|
||||
size_t space_left, int *bytes_copied)
|
||||
{
|
||||
|
|
@ -4647,112 +4446,6 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
|
|||
return cnt;
|
||||
}
|
||||
|
||||
/* Old API for getting list of local addresses. Does not work for 32-bit
|
||||
* programs running on a 64-bit kernel
|
||||
*/
|
||||
static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct sctp_bind_addr *bp;
|
||||
struct sctp_association *asoc;
|
||||
int cnt = 0;
|
||||
struct sctp_getaddrs_old getaddrs;
|
||||
struct sctp_sockaddr_entry *addr;
|
||||
void __user *to;
|
||||
union sctp_addr temp;
|
||||
struct sctp_sock *sp = sctp_sk(sk);
|
||||
int addrlen;
|
||||
int err = 0;
|
||||
void *addrs;
|
||||
void *buf;
|
||||
int bytes_copied = 0;
|
||||
|
||||
if (len < sizeof(struct sctp_getaddrs_old))
|
||||
return -EINVAL;
|
||||
|
||||
len = sizeof(struct sctp_getaddrs_old);
|
||||
if (copy_from_user(&getaddrs, optval, len))
|
||||
return -EFAULT;
|
||||
|
||||
if (getaddrs.addr_num <= 0 ||
|
||||
getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
|
||||
return -EINVAL;
|
||||
|
||||
printk(KERN_WARNING "SCTP: Use of SCTP_GET_LOCAL_ADDRS_OLD "
|
||||
"socket option deprecated\n");
|
||||
|
||||
/*
|
||||
* For UDP-style sockets, id specifies the association to query.
|
||||
* If the id field is set to the value '0' then the locally bound
|
||||
* addresses are returned without regard to any particular
|
||||
* association.
|
||||
*/
|
||||
if (0 == getaddrs.assoc_id) {
|
||||
bp = &sctp_sk(sk)->ep->base.bind_addr;
|
||||
} else {
|
||||
asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
|
||||
if (!asoc)
|
||||
return -EINVAL;
|
||||
bp = &asoc->base.bind_addr;
|
||||
}
|
||||
|
||||
to = getaddrs.addrs;
|
||||
|
||||
/* Allocate space for a local instance of packed array to hold all
|
||||
* the data. We store addresses here first and then put write them
|
||||
* to the user in one shot.
|
||||
*/
|
||||
addrs = kmalloc(sizeof(union sctp_addr) * getaddrs.addr_num,
|
||||
GFP_KERNEL);
|
||||
if (!addrs)
|
||||
return -ENOMEM;
|
||||
|
||||
/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
|
||||
* addresses from the global local address list.
|
||||
*/
|
||||
if (sctp_list_single_entry(&bp->address_list)) {
|
||||
addr = list_entry(bp->address_list.next,
|
||||
struct sctp_sockaddr_entry, list);
|
||||
if (sctp_is_any(sk, &addr->a)) {
|
||||
cnt = sctp_copy_laddrs_old(sk, bp->port,
|
||||
getaddrs.addr_num,
|
||||
addrs, &bytes_copied);
|
||||
goto copy_getaddrs;
|
||||
}
|
||||
}
|
||||
|
||||
buf = addrs;
|
||||
/* Protection on the bound address list is not needed since
|
||||
* in the socket option context we hold a socket lock and
|
||||
* thus the bound address list can't change.
|
||||
*/
|
||||
list_for_each_entry(addr, &bp->address_list, list) {
|
||||
memcpy(&temp, &addr->a, sizeof(temp));
|
||||
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
|
||||
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
|
||||
memcpy(buf, &temp, addrlen);
|
||||
buf += addrlen;
|
||||
bytes_copied += addrlen;
|
||||
cnt ++;
|
||||
if (cnt >= getaddrs.addr_num) break;
|
||||
}
|
||||
|
||||
copy_getaddrs:
|
||||
/* copy the entire address list into the user provided space */
|
||||
if (copy_to_user(to, addrs, bytes_copied)) {
|
||||
err = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* copy the leading structure back to user */
|
||||
getaddrs.addr_num = cnt;
|
||||
if (copy_to_user(optval, &getaddrs, len))
|
||||
err = -EFAULT;
|
||||
|
||||
error:
|
||||
kfree(addrs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
|
||||
char __user *optval, int __user *optlen)
|
||||
|
|
@ -5603,22 +5296,6 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
|
|||
case SCTP_INITMSG:
|
||||
retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
|
||||
break;
|
||||
case SCTP_GET_PEER_ADDRS_NUM_OLD:
|
||||
retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval,
|
||||
optlen);
|
||||
break;
|
||||
case SCTP_GET_LOCAL_ADDRS_NUM_OLD:
|
||||
retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval,
|
||||
optlen);
|
||||
break;
|
||||
case SCTP_GET_PEER_ADDRS_OLD:
|
||||
retval = sctp_getsockopt_peer_addrs_old(sk, len, optval,
|
||||
optlen);
|
||||
break;
|
||||
case SCTP_GET_LOCAL_ADDRS_OLD:
|
||||
retval = sctp_getsockopt_local_addrs_old(sk, len, optval,
|
||||
optlen);
|
||||
break;
|
||||
case SCTP_GET_PEER_ADDRS:
|
||||
retval = sctp_getsockopt_peer_addrs(sk, len, optval,
|
||||
optlen);
|
||||
|
|
@ -5861,7 +5538,7 @@ pp_not_found:
|
|||
*/
|
||||
success:
|
||||
if (!sctp_sk(sk)->bind_hash) {
|
||||
inet_sk(sk)->num = snum;
|
||||
inet_sk(sk)->inet_num = snum;
|
||||
sk_add_bind_node(sk, &pp->owner);
|
||||
sctp_sk(sk)->bind_hash = pp;
|
||||
}
|
||||
|
|
@ -5933,7 +5610,7 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog)
|
|||
if (sctp_autobind(sk))
|
||||
return -EAGAIN;
|
||||
} else {
|
||||
if (sctp_get_port(sk, inet_sk(sk)->num)) {
|
||||
if (sctp_get_port(sk, inet_sk(sk)->inet_num)) {
|
||||
sk->sk_state = SCTP_SS_CLOSED;
|
||||
return -EADDRINUSE;
|
||||
}
|
||||
|
|
@ -6104,14 +5781,14 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
|
|||
static inline void __sctp_put_port(struct sock *sk)
|
||||
{
|
||||
struct sctp_bind_hashbucket *head =
|
||||
&sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
|
||||
&sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)];
|
||||
struct sctp_bind_bucket *pp;
|
||||
|
||||
sctp_spin_lock(&head->lock);
|
||||
pp = sctp_sk(sk)->bind_hash;
|
||||
__sk_del_bind_node(sk);
|
||||
sctp_sk(sk)->bind_hash = NULL;
|
||||
inet_sk(sk)->num = 0;
|
||||
inet_sk(sk)->inet_num = 0;
|
||||
sctp_bucket_destroy(pp);
|
||||
sctp_spin_unlock(&head->lock);
|
||||
}
|
||||
|
|
@ -6138,7 +5815,7 @@ static int sctp_autobind(struct sock *sk)
|
|||
/* Initialize a local sockaddr structure to INADDR_ANY. */
|
||||
af = sctp_sk(sk)->pf->af;
|
||||
|
||||
port = htons(inet_sk(sk)->num);
|
||||
port = htons(inet_sk(sk)->inet_num);
|
||||
af->inaddr_any(&autoaddr, port);
|
||||
|
||||
return sctp_do_bind(sk, &autoaddr, af->sockaddr_len);
|
||||
|
|
@ -6707,12 +6384,12 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
|
|||
/* Initialize sk's sport, dport, rcv_saddr and daddr for
|
||||
* getsockname() and getpeername()
|
||||
*/
|
||||
newinet->sport = inet->sport;
|
||||
newinet->saddr = inet->saddr;
|
||||
newinet->rcv_saddr = inet->rcv_saddr;
|
||||
newinet->dport = htons(asoc->peer.port);
|
||||
newinet->inet_sport = inet->inet_sport;
|
||||
newinet->inet_saddr = inet->inet_saddr;
|
||||
newinet->inet_rcv_saddr = inet->inet_rcv_saddr;
|
||||
newinet->inet_dport = htons(asoc->peer.port);
|
||||
newinet->pmtudisc = inet->pmtudisc;
|
||||
newinet->id = asoc->next_tsn ^ jiffies;
|
||||
newinet->inet_id = asoc->next_tsn ^ jiffies;
|
||||
|
||||
newinet->uc_ttl = inet->uc_ttl;
|
||||
newinet->mc_loop = 1;
|
||||
|
|
@ -6751,13 +6428,13 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
|
|||
newsp->hmac = NULL;
|
||||
|
||||
/* Hook this new socket in to the bind_hash list. */
|
||||
head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->num)];
|
||||
head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)];
|
||||
sctp_local_bh_disable();
|
||||
sctp_spin_lock(&head->lock);
|
||||
pp = sctp_sk(oldsk)->bind_hash;
|
||||
sk_add_bind_node(newsk, &pp->owner);
|
||||
sctp_sk(newsk)->bind_hash = pp;
|
||||
inet_sk(newsk)->num = inet_sk(oldsk)->num;
|
||||
inet_sk(newsk)->inet_num = inet_sk(oldsk)->inet_num;
|
||||
sctp_spin_unlock(&head->lock);
|
||||
sctp_local_bh_enable();
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ static int int_max = INT_MAX;
|
|||
static int sack_timer_min = 1;
|
||||
static int sack_timer_max = 500;
|
||||
static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
|
||||
static int rwnd_scale_max = 16;
|
||||
|
||||
extern int sysctl_sctp_mem[3];
|
||||
extern int sysctl_sctp_rmem[3];
|
||||
|
|
@ -241,7 +242,18 @@ static ctl_table sctp_table[] = {
|
|||
.extra1 = &zero,
|
||||
.extra2 = &addr_scope_max,
|
||||
},
|
||||
{ }
|
||||
{
|
||||
.procname = "rwnd_update_shift",
|
||||
.data = &sctp_rwnd_upd_shift,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = &proc_dointvec_minmax,
|
||||
.strategy = &sysctl_intvec,
|
||||
.extra1 = &one,
|
||||
.extra2 = &rwnd_scale_max,
|
||||
},
|
||||
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct ctl_path sctp_path[] = {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
|
|||
peer->fast_recovery = 0;
|
||||
|
||||
peer->last_time_heard = jiffies;
|
||||
peer->last_time_used = jiffies;
|
||||
peer->last_time_ecne_reduced = jiffies;
|
||||
|
||||
peer->init_sent_count = 0;
|
||||
|
|
@ -564,10 +563,8 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
|
|||
* to be done every RTO interval, we do it every hearbeat
|
||||
* interval.
|
||||
*/
|
||||
if (time_after(jiffies, transport->last_time_used +
|
||||
transport->rto))
|
||||
transport->cwnd = max(transport->cwnd/2,
|
||||
4*transport->asoc->pathmtu);
|
||||
transport->cwnd = max(transport->cwnd/2,
|
||||
4*transport->asoc->pathmtu);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -578,6 +575,43 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
|
|||
transport->cwnd, transport->ssthresh);
|
||||
}
|
||||
|
||||
/* Apply Max.Burst limit to the congestion window:
|
||||
* sctpimpguide-05 2.14.2
|
||||
* D) When the time comes for the sender to
|
||||
* transmit new DATA chunks, the protocol parameter Max.Burst MUST
|
||||
* first be applied to limit how many new DATA chunks may be sent.
|
||||
* The limit is applied by adjusting cwnd as follows:
|
||||
* if ((flightsize+ Max.Burst * MTU) < cwnd)
|
||||
* cwnd = flightsize + Max.Burst * MTU
|
||||
*/
|
||||
|
||||
void sctp_transport_burst_limited(struct sctp_transport *t)
|
||||
{
|
||||
struct sctp_association *asoc = t->asoc;
|
||||
u32 old_cwnd = t->cwnd;
|
||||
u32 max_burst_bytes;
|
||||
|
||||
if (t->burst_limited)
|
||||
return;
|
||||
|
||||
max_burst_bytes = t->flight_size + (asoc->max_burst * asoc->pathmtu);
|
||||
if (max_burst_bytes < old_cwnd) {
|
||||
t->cwnd = max_burst_bytes;
|
||||
t->burst_limited = old_cwnd;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the old cwnd congestion window, after the burst had it's
|
||||
* desired effect.
|
||||
*/
|
||||
void sctp_transport_burst_reset(struct sctp_transport *t)
|
||||
{
|
||||
if (t->burst_limited) {
|
||||
t->cwnd = t->burst_limited;
|
||||
t->burst_limited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* What is the next timeout value for this transport? */
|
||||
unsigned long sctp_transport_timeout(struct sctp_transport *t)
|
||||
{
|
||||
|
|
@ -600,6 +634,7 @@ void sctp_transport_reset(struct sctp_transport *t)
|
|||
* (see Section 6.2.1)
|
||||
*/
|
||||
t->cwnd = min(4*asoc->pathmtu, max_t(__u32, 2*asoc->pathmtu, 4380));
|
||||
t->burst_limited = 0;
|
||||
t->ssthresh = asoc->peer.i.a_rwnd;
|
||||
t->rto = asoc->rto_initial;
|
||||
t->rtt = 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue