Skip to content

Commit 8914f4b

Browse files
marceloleitnerdavem330
authored andcommitted
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: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 6d3e8aa commit 8914f4b

File tree

1 file changed

+46
-84
lines changed

1 file changed

+46
-84
lines changed

net/sctp/sm_make_chunk.c

Lines changed: 46 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ static int sctp_process_param(struct sctp_association *asoc,
8181
gfp_t gfp);
8282
static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
8383
const void *data);
84-
static void *sctp_addto_chunk_fixed(struct sctp_chunk *, int len,
85-
const void *data);
8684

8785
/* Control chunk destructor */
8886
static void sctp_control_release_owner(struct sk_buff *skb)
@@ -154,9 +152,8 @@ static const struct sctp_paramhdr prsctp_param = {
154152
cpu_to_be16(sizeof(struct sctp_paramhdr)),
155153
};
156154

157-
/* A helper to initialize an op error inside a
158-
* provided chunk, as most cause codes will be embedded inside an
159-
* abort chunk.
155+
/* A helper to initialize an op error inside a provided chunk, as most
156+
* cause codes will be embedded inside an abort chunk.
160157
*/
161158
int sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
162159
size_t paylen)
@@ -177,29 +174,6 @@ int sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
177174
return 0;
178175
}
179176

180-
/* A helper to initialize an op error inside a
181-
* provided chunk, as most cause codes will be embedded inside an
182-
* abort chunk. Differs from sctp_init_cause in that it won't oops
183-
* if there isn't enough space in the op error chunk
184-
*/
185-
static int sctp_init_cause_fixed(struct sctp_chunk *chunk, __be16 cause_code,
186-
size_t paylen)
187-
{
188-
struct sctp_errhdr err;
189-
__u16 len;
190-
191-
/* Cause code constants are now defined in network order. */
192-
err.cause = cause_code;
193-
len = sizeof(err) + paylen;
194-
err.length = htons(len);
195-
196-
if (skb_tailroom(chunk->skb) < len)
197-
return -ENOSPC;
198-
199-
chunk->subh.err_hdr = sctp_addto_chunk_fixed(chunk, sizeof(err), &err);
200-
201-
return 0;
202-
}
203177
/* 3.3.2 Initiation (INIT) (1)
204178
*
205179
* This chunk is used to initiate a SCTP association between two
@@ -1263,20 +1237,26 @@ static struct sctp_chunk *sctp_make_op_error_space(
12631237
return retval;
12641238
}
12651239

1266-
/* Create an Operation Error chunk of a fixed size,
1267-
* specifically, max(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT)
1268-
* This is a helper function to allocate an error chunk for
1269-
* for those invalid parameter codes in which we may not want
1270-
* to report all the errors, if the incoming chunk is large
1240+
/* Create an Operation Error chunk of a fixed size, specifically,
1241+
* min(asoc->pathmtu, SCTP_DEFAULT_MAXSEGMENT) - overheads.
1242+
* This is a helper function to allocate an error chunk for for those
1243+
* invalid parameter codes in which we may not want to report all the
1244+
* errors, if the incoming chunk is large. If it can't fit in a single
1245+
* packet, we ignore it.
12711246
*/
1272-
static inline struct sctp_chunk *sctp_make_op_error_fixed(
1247+
static inline struct sctp_chunk *sctp_make_op_error_limited(
12731248
const struct sctp_association *asoc,
12741249
const struct sctp_chunk *chunk)
12751250
{
1276-
size_t size = asoc ? asoc->pathmtu : 0;
1251+
size_t size = SCTP_DEFAULT_MAXSEGMENT;
1252+
struct sctp_sock *sp = NULL;
1253+
1254+
if (asoc) {
1255+
size = min_t(size_t, size, asoc->pathmtu);
1256+
sp = sctp_sk(asoc->base.sk);
1257+
}
12771258

1278-
if (!size)
1279-
size = SCTP_DEFAULT_MAXSEGMENT;
1259+
size = sctp_mtu_payload(sp, size, sizeof(struct sctp_errhdr));
12801260

12811261
return sctp_make_op_error_space(asoc, chunk, size);
12821262
}
@@ -1528,18 +1508,6 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
15281508
return target;
15291509
}
15301510

1531-
/* Append bytes to the end of a chunk. Returns NULL if there isn't sufficient
1532-
* space in the chunk
1533-
*/
1534-
static void *sctp_addto_chunk_fixed(struct sctp_chunk *chunk,
1535-
int len, const void *data)
1536-
{
1537-
if (skb_tailroom(chunk->skb) >= len)
1538-
return sctp_addto_chunk(chunk, len, data);
1539-
else
1540-
return NULL;
1541-
}
1542-
15431511
/* Append bytes from user space to the end of a chunk. Will panic if
15441512
* chunk is not big enough.
15451513
* Returns a kernel err value.
@@ -1834,6 +1802,9 @@ struct sctp_association *sctp_unpack_cookie(
18341802
kt = ktime_get_real();
18351803

18361804
if (!asoc && ktime_before(bear_cookie->expiration, kt)) {
1805+
suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration));
1806+
__be32 n = htonl(usecs);
1807+
18371808
/*
18381809
* Section 3.3.10.3 Stale Cookie Error (3)
18391810
*
@@ -1842,17 +1813,12 @@ struct sctp_association *sctp_unpack_cookie(
18421813
* Stale Cookie Error: Indicates the receipt of a valid State
18431814
* Cookie that has expired.
18441815
*/
1845-
len = ntohs(chunk->chunk_hdr->length);
1846-
*errp = sctp_make_op_error_space(asoc, chunk, len);
1847-
if (*errp) {
1848-
suseconds_t usecs = ktime_to_us(ktime_sub(kt, bear_cookie->expiration));
1849-
__be32 n = htonl(usecs);
1850-
1851-
sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
1852-
sizeof(n));
1853-
sctp_addto_chunk(*errp, sizeof(n), &n);
1816+
*errp = sctp_make_op_error(asoc, chunk,
1817+
SCTP_ERROR_STALE_COOKIE, &n,
1818+
sizeof(n), 0);
1819+
if (*errp)
18541820
*error = -SCTP_IERROR_STALE_COOKIE;
1855-
} else
1821+
else
18561822
*error = -SCTP_IERROR_NOMEM;
18571823

18581824
goto fail;
@@ -2003,12 +1969,8 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
20031969
if (*errp)
20041970
sctp_chunk_free(*errp);
20051971

2006-
*errp = sctp_make_op_error_space(asoc, chunk, len);
2007-
2008-
if (*errp) {
2009-
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
2010-
sctp_addto_chunk(*errp, len, param.v);
2011-
}
1972+
*errp = sctp_make_op_error(asoc, chunk, SCTP_ERROR_DNS_FAILED,
1973+
param.v, len, 0);
20121974

20131975
/* Stop processing this chunk. */
20141976
return 0;
@@ -2133,23 +2095,23 @@ static enum sctp_ierror sctp_process_unk_param(
21332095
/* Make an ERROR chunk, preparing enough room for
21342096
* returning multiple unknown parameters.
21352097
*/
2136-
if (NULL == *errp)
2137-
*errp = sctp_make_op_error_fixed(asoc, chunk);
2138-
2139-
if (*errp) {
2140-
if (!sctp_init_cause_fixed(*errp, SCTP_ERROR_UNKNOWN_PARAM,
2141-
SCTP_PAD4(ntohs(param.p->length))))
2142-
sctp_addto_chunk_fixed(*errp,
2143-
SCTP_PAD4(ntohs(param.p->length)),
2144-
param.v);
2145-
} else {
2146-
/* If there is no memory for generating the ERROR
2147-
* report as specified, an ABORT will be triggered
2148-
* to the peer and the association won't be
2149-
* established.
2150-
*/
2151-
retval = SCTP_IERROR_NOMEM;
2098+
if (!*errp) {
2099+
*errp = sctp_make_op_error_limited(asoc, chunk);
2100+
if (!*errp) {
2101+
/* If there is no memory for generating the
2102+
* ERROR report as specified, an ABORT will be
2103+
* triggered to the peer and the association
2104+
* won't be established.
2105+
*/
2106+
retval = SCTP_IERROR_NOMEM;
2107+
break;
2108+
}
21522109
}
2110+
2111+
if (!sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
2112+
ntohs(param.p->length)))
2113+
sctp_addto_chunk(*errp, ntohs(param.p->length),
2114+
param.v);
21532115
break;
21542116
default:
21552117
break;
@@ -2225,10 +2187,10 @@ static enum sctp_ierror sctp_verify_param(struct net *net,
22252187
* MUST be aborted. The ABORT chunk SHOULD contain the error
22262188
* cause 'Protocol Violation'.
22272189
*/
2228-
if (SCTP_AUTH_RANDOM_LENGTH !=
2229-
ntohs(param.p->length) - sizeof(struct sctp_paramhdr)) {
2190+
if (SCTP_AUTH_RANDOM_LENGTH != ntohs(param.p->length) -
2191+
sizeof(struct sctp_paramhdr)) {
22302192
sctp_process_inv_paramlength(asoc, param.p,
2231-
chunk, err_chunk);
2193+
chunk, err_chunk);
22322194
retval = SCTP_IERROR_ABORT;
22332195
}
22342196
break;

0 commit comments

Comments
 (0)