Commit 8914f4ba authored by Marcelo Ricardo Leitner's avatar Marcelo Ricardo Leitner Committed by David S. Miller

sctp: add sctp_make_op_error_limited and reuse inner functions

The idea is quite similar to the old functions, but note that the _fixed
function wasn't "fixed" as in that it would generate a packet with a fixed
size, but rather limited/bounded to PMTU.

Also, now with sctp_mtu_payload(), we have a more accurate limit.
Signed-off-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6d3e8aa8
...@@ -81,8 +81,6 @@ static int sctp_process_param(struct sctp_association *asoc, ...@@ -81,8 +81,6 @@ static int sctp_process_param(struct sctp_association *asoc,
gfp_t gfp); gfp_t gfp);
static void *sctp_addto_param(struct sctp_chunk *chunk, int len, static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
const void *data); const void *data);
static void *sctp_addto_chunk_fixed(struct sctp_chunk *, int len,
const void *data);
/* Control chunk destructor */ /* Control chunk destructor */
static void sctp_control_release_owner(struct sk_buff *skb) static void sctp_control_release_owner(struct sk_buff *skb)
...@@ -154,9 +152,8 @@ static const struct sctp_paramhdr prsctp_param = { ...@@ -154,9 +152,8 @@ static const struct sctp_paramhdr prsctp_param = {
cpu_to_be16(sizeof(struct sctp_paramhdr)), cpu_to_be16(sizeof(struct sctp_paramhdr)),
}; };
/* A helper to initialize an op error inside a /* A helper to initialize an op error inside a provided chunk, as most
* provided chunk, as most cause codes will be embedded inside an * cause codes will be embedded inside an abort chunk.
* abort chunk.
*/ */
int sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, int sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
size_t paylen) size_t paylen)
...@@ -177,29 +174,6 @@ int sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, ...@@ -177,29 +174,6 @@ int sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
return 0; return 0;
} }
/* A helper to initialize an op error inside a
* provided chunk, as most cause codes will be embedded inside an
* abort chunk. Differs from sctp_init_cause in that it won't oops
* if there isn't enough space in the op error chunk
*/
static int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code,
size_t paylen)
{
struct sctp_errhdr err;
__u16 len;
/* Cause code constants are now defined in network order. */
err.cause = cause_code;
len = sizeof(err) + paylen;
err.length = htons(len);
if (skb_tailroom(chunk->skb) < len)
return -ENOSPC;
chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk, sizeof(err), &err);
return 0;
}
/* 3.3.2 Initiation (INIT) (1) /* 3.3.2 Initiation (INIT) (1)
* *
* This chunk is used to initiate a SCTP association between two * This chunk is used to initiate a SCTP association between two
...@@ -1263,20 +1237,26 @@ static struct sctp_chunk *sctp_make_op_error_space( ...@@ -1263,20 +1237,26 @@ static struct sctp_chunk *sctp_make_op_error_space(
return retval; return retval;
} }
/* Create an Operation Error chunk of a fixed size, /* Create an Operation Error chunk of a fixed size, specifically,
* specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT) * min(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT) - overheads.
* This is a helper function to allocate an error chunk for * This is a helper function to allocate an error chunk for for those
* for those invalid parameter codes in which we may not want * invalid parameter codes in which we may not want to report all the
* to report all the errors, if the incoming chunk is large * errors, if the incoming chunk is large. If it can't fit in a single
* packet, we ignore it.
*/ */
static inline struct sctp_chunk *sctp_make_op_error_fixed( static inline struct sctp_chunk *sctp_make_op_error_limited(
const struct sctp_association *asoc, const struct sctp_association *asoc,
const struct sctp_chunk *chunk) const struct sctp_chunk *chunk)
{ {
size_t size = asoc ? asoc->pathmtu : 0; size_t size = SCTP_DEFAULT_MAXSEGMENT;
struct sctp_sock *sp = NULL;
if (asoc) {
size = min_t(size_t, size, asoc->pathmtu);
sp = sctp_sk(asoc->base.sk);
}
if (!size) size = sctp_mtu_payload(sp, size, sizeof(struct sctp_errhdr));
size = SCTP_DEFAULT_MAXSEGMENT;
return sctp_make_op_error_space(asoc, chunk, size); return sctp_make_op_error_space(asoc, chunk, size);
} }
...@@ -1528,18 +1508,6 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) ...@@ -1528,18 +1508,6 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
return target; return target;
} }
/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
* space in the chunk
*/
static void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
int len, const void *data)
{
if (skb_tailroom(chunk->skb) >= len)
return sctp_addto_chunk(chunk, len, data);
else
return NULL;
}
/* Append bytes from user space to the end of a chunk. Will panic if /* Append bytes from user space to the end of a chunk. Will panic if
* chunk is not big enough. * chunk is not big enough.
* Returns a kernel err value. * Returns a kernel err value.
...@@ -1834,6 +1802,9 @@ struct sctp_association *sctp_unpack_cookie( ...@@ -1834,6 +1802,9 @@ struct sctp_association *sctp_unpack_cookie(
kt = ktime_get_real(); kt = ktime_get_real();
if (!asoc && ktime_before(bear_cookie->expiration, kt)) { if (!asoc && ktime_before(bear_cookie->expiration, kt)) {
suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration));
__be32 n = htonl(usecs);
/* /*
* Section 3.3.10.3 Stale Cookie Error (3) * Section 3.3.10.3 Stale Cookie Error (3)
* *
...@@ -1842,17 +1813,12 @@ struct sctp_association *sctp_unpack_cookie( ...@@ -1842,17 +1813,12 @@ struct sctp_association *sctp_unpack_cookie(
* Stale Cookie Error: Indicates the receipt of a valid State * Stale Cookie Error: Indicates the receipt of a valid State
* Cookie that has expired. * Cookie that has expired.
*/ */
len = ntohs(chunk->chunk_hdr->length); *errp = sctp_make_op_error(asoc, chunk,
*errp = sctp_make_op_error_space(asoc, chunk, len); SCTP_ERROR_STALE_COOKIE, &n,
if (*errp) { sizeof(n), 0);
suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration)); if (*errp)
__be32 n = htonl(usecs);
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
sizeof(n));
sctp_addto_chunk(*errp, sizeof(n), &n);
*error = -SCTP_IERROR_STALE_COOKIE; *error = -SCTP_IERROR_STALE_COOKIE;
} else else
*error = -SCTP_IERROR_NOMEM; *error = -SCTP_IERROR_NOMEM;
goto fail; goto fail;
...@@ -2003,12 +1969,8 @@ static int sctp_process_hn_param(const struct sctp_association *asoc, ...@@ -2003,12 +1969,8 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
if (*errp) if (*errp)
sctp_chunk_free(*errp); sctp_chunk_free(*errp);
*errp = sctp_make_op_error_space(asoc, chunk, len); *errp = sctp_make_op_error(asoc, chunk, SCTP_ERROR_DNS_FAILED,
param.v, len, 0);
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
sctp_addto_chunk(*errp, len, param.v);
}
/* Stop processing this chunk. */ /* Stop processing this chunk. */
return 0; return 0;
...@@ -2133,23 +2095,23 @@ static enum sctp_ierror sctp_process_unk_param( ...@@ -2133,23 +2095,23 @@ static enum sctp_ierror sctp_process_unk_param(
/* Make an ERROR chunk, preparing enough room for /* Make an ERROR chunk, preparing enough room for
* returning multiple unknown parameters. * returning multiple unknown parameters.
*/ */
if (NULL == *errp) if (!*errp) {
*errp = sctp_make_op_error_fixed(asoc, chunk); *errp = sctp_make_op_error_limited(asoc, chunk);
if (!*errp) {
if (*errp) { /* If there is no memory for generating the
if (!sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM, * ERROR report as specified, an ABORT will be
SCTP_PAD4(ntohs(param.p->length)))) * triggered to the peer and the association
sctp_addto_chunk_fixed(*errp, * won't be established.
SCTP_PAD4(ntohs(param.p->length)), */
param.v); retval = SCTP_IERROR_NOMEM;
} else { break;
/* If there is no memory for generating the ERROR }
* report as specified, an ABORT will be triggered
* to the peer and the association won't be
* established.
*/
retval = SCTP_IERROR_NOMEM;
} }
if (!sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
ntohs(param.p->length)))
sctp_addto_chunk(*errp, ntohs(param.p->length),
param.v);
break; break;
default: default:
break; break;
...@@ -2225,10 +2187,10 @@ static enum sctp_ierror sctp_verify_param(struct net *net, ...@@ -2225,10 +2187,10 @@ static enum sctp_ierror sctp_verify_param(struct net *net,
* MUST be aborted. The ABORT chunk SHOULD contain the error * MUST be aborted. The ABORT chunk SHOULD contain the error
* cause 'Protocol Violation'. * cause 'Protocol Violation'.
*/ */
if (SCTP_AUTH_RANDOM_LENGTH != if (SCTP_AUTH_RANDOM_LENGTH != ntohs(param.p->length) -
ntohs(param.p->length) - sizeof(struct sctp_paramhdr)) { sizeof(struct sctp_paramhdr)) {
sctp_process_inv_paramlength(asoc, param.p, sctp_process_inv_paramlength(asoc, param.p,
chunk, err_chunk); chunk, err_chunk);
retval = SCTP_IERROR_ABORT; retval = SCTP_IERROR_ABORT;
} }
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment