Skip to content

Commit

Permalink
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/…
Browse files Browse the repository at this point in the history
…vxy/lksctp-dev
  • Loading branch information
David S. Miller committed Aug 31, 2007
2 parents 05bb1fa + cb243a1 commit b91ddd8
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 77 deletions.
2 changes: 1 addition & 1 deletion include/net/sctp/sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
const struct sctp_chunk *);
struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
const struct sctp_chunk *);
void sctp_init_cause(struct sctp_chunk *, __be16 cause, const void *, size_t);
void sctp_init_cause(struct sctp_chunk *, __be16 cause, size_t);
struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
const struct sctp_chunk *,
const size_t hint);
Expand Down
1 change: 1 addition & 0 deletions include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
struct iovec *data);
void sctp_chunk_free(struct sctp_chunk *);
void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
void *sctp_addto_param(struct sctp_chunk *, int len, const void *data);
struct sctp_chunk *sctp_chunkify(struct sk_buff *,
const struct sctp_association *,
struct sock *);
Expand Down
1 change: 1 addition & 0 deletions include/net/sctp/ulpqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ int sctp_clear_pd(struct sock *sk, struct sctp_association *asoc);
/* Skip over an SSN. */
void sctp_ulpq_skip(struct sctp_ulpq *ulpq, __u16 sid, __u16 ssn);

void sctp_ulpq_reasm_flushtsn(struct sctp_ulpq *, __u32);
#endif /* __sctp_ulpqueue_h__ */


Expand Down
7 changes: 6 additions & 1 deletion net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
break;

case SCTP_TRANSPORT_DOWN:
transport->state = SCTP_INACTIVE;
/* if the transort was never confirmed, do not transition it
* to inactive state.
*/
if (transport->state != SCTP_UNCONFIRMED)
transport->state = SCTP_INACTIVE;

spc_state = SCTP_ADDR_UNREACHABLE;
break;

Expand Down
7 changes: 7 additions & 0 deletions net/sctp/outqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@ void sctp_retransmit_mark(struct sctp_outq *q,
*/
if ((fast_retransmit && (chunk->fast_retransmit > 0)) ||
(!fast_retransmit && !chunk->tsn_gap_acked)) {
/* If this chunk was sent less then 1 rto ago, do not
* retransmit this chunk, but give the peer time
* to acknowlege it.
*/
if ((jiffies - chunk->sent_at) < transport->rto)
continue;

/* RFC 2960 6.2.1 Processing a Received SACK
*
* C) Any time a DATA chunk is marked for
Expand Down
112 changes: 77 additions & 35 deletions net/sctp/sm_make_chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static const struct sctp_paramhdr prsctp_param = {
* abort chunk.
*/
void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
const void *payload, size_t paylen)
size_t paylen)
{
sctp_errhdr_t err;
__u16 len;
Expand All @@ -120,7 +120,6 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code,
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
sctp_addto_chunk(chunk, paylen, payload);
}

/* 3.3.2 Initiation (INIT) (1)
Expand Down Expand Up @@ -780,8 +779,8 @@ struct sctp_chunk *sctp_make_abort_no_data(

/* Put the tsn back into network byte order. */
payload = htonl(tsn);
sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload,
sizeof(payload));
sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload));
sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload);

/* RFC 2960 6.4 Multi-homed SCTP Endpoints
*
Expand Down Expand Up @@ -823,7 +822,8 @@ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
goto err_copy;
}

sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen);
sctp_addto_chunk(retval, paylen, payload);

if (paylen)
kfree(payload);
Expand All @@ -850,15 +850,17 @@ struct sctp_chunk *sctp_make_abort_violation(
struct sctp_paramhdr phdr;

retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen
+ sizeof(sctp_chunkhdr_t));
+ sizeof(sctp_paramhdr_t));
if (!retval)
goto end;

sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen);
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen
+ sizeof(sctp_paramhdr_t));

phdr.type = htons(chunk->chunk_hdr->type);
phdr.length = chunk->chunk_hdr->length;
sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr);
sctp_addto_chunk(retval, paylen, payload);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr);

end:
return retval;
Expand Down Expand Up @@ -955,7 +957,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc,
if (!retval)
goto nodata;

sctp_init_cause(retval, cause_code, payload, paylen);
sctp_init_cause(retval, cause_code, paylen);
sctp_addto_chunk(retval, paylen, payload);

nodata:
return retval;
Expand Down Expand Up @@ -1128,7 +1131,7 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
void *target;
void *padding;
int chunklen = ntohs(chunk->chunk_hdr->length);
int padlen = chunklen % 4;
int padlen = WORD_ROUND(chunklen) - chunklen;

padding = skb_put(chunk->skb, padlen);
target = skb_put(chunk->skb, len);
Expand All @@ -1143,6 +1146,25 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data)
return target;
}

/* Append bytes to the end of a parameter. Will panic if chunk is not big
* enough.
*/
void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data)
{
void *target;
int chunklen = ntohs(chunk->chunk_hdr->length);

target = skb_put(chunk->skb, len);

memcpy(target, data, len);

/* Adjust the chunk length field. */
chunk->chunk_hdr->length = htons(chunklen + len);
chunk->chunk_end = skb_tail_pointer(chunk->skb);

return target;
}

/* Append bytes from user space to the end of a chunk. Will panic if
* chunk is not big enough.
* Returns a kernel err value.
Expand Down Expand Up @@ -1174,25 +1196,36 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
*/
void sctp_chunk_assign_ssn(struct sctp_chunk *chunk)
{
struct sctp_datamsg *msg;
struct sctp_chunk *lchunk;
struct sctp_stream *stream;
__u16 ssn;
__u16 sid;

if (chunk->has_ssn)
return;

/* This is the last possible instant to assign a SSN. */
if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
ssn = 0;
} else {
sid = ntohs(chunk->subh.data_hdr->stream);
if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
else
ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
}
/* All fragments will be on the same stream */
sid = ntohs(chunk->subh.data_hdr->stream);
stream = &chunk->asoc->ssnmap->out;

chunk->subh.data_hdr->ssn = htons(ssn);
chunk->has_ssn = 1;
/* Now assign the sequence number to the entire message.
* All fragments must have the same stream sequence number.
*/
msg = chunk->msg;
list_for_each_entry(lchunk, &msg->chunks, frag_list) {
if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
ssn = 0;
} else {
if (lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
ssn = sctp_ssn_next(stream, sid);
else
ssn = sctp_ssn_peek(stream, sid);
}

lchunk->subh.data_hdr->ssn = htons(ssn);
lchunk->has_ssn = 1;
}
}

/* Helper function to assign a TSN if needed. This assumes that both
Expand Down Expand Up @@ -1466,7 +1499,8 @@ struct sctp_association *sctp_unpack_cookie(
__be32 n = htonl(usecs);

sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,
&n, sizeof(n));
sizeof(n));
sctp_addto_chunk(*errp, sizeof(n), &n);
*error = -SCTP_IERROR_STALE_COOKIE;
} else
*error = -SCTP_IERROR_NOMEM;
Expand Down Expand Up @@ -1556,7 +1590,8 @@ static int sctp_process_missing_param(const struct sctp_association *asoc,
report.num_missing = htonl(1);
report.type = paramtype;
sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM,
&report, sizeof(report));
sizeof(report));
sctp_addto_chunk(*errp, sizeof(report), &report);
}

/* Stop processing this chunk. */
Expand All @@ -1574,7 +1609,7 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc,
*errp = sctp_make_op_error_space(asoc, chunk, 0);

if (*errp)
sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0);
sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0);

/* Stop processing this chunk. */
return 0;
Expand All @@ -1595,9 +1630,10 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
*errp = sctp_make_op_error_space(asoc, chunk, payload_len);

if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error,
sizeof(error));
sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param);
sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
sizeof(error) + sizeof(sctp_paramhdr_t));
sctp_addto_chunk(*errp, sizeof(error), error);
sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param);
}

return 0;
Expand All @@ -1618,9 +1654,10 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
if (!*errp)
*errp = sctp_make_op_error_space(asoc, chunk, len);

if (*errp)
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED,
param.v, len);
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
sctp_addto_chunk(*errp, len, param.v);
}

/* Stop processing this chunk. */
return 0;
Expand Down Expand Up @@ -1672,10 +1709,13 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
*errp = sctp_make_op_error_space(asoc, chunk,
ntohs(chunk->chunk_hdr->length));

if (*errp)
if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
param.v,
WORD_ROUND(ntohs(param.p->length)));
sctp_addto_chunk(*errp,
WORD_ROUND(ntohs(param.p->length)),
param.v);
}

break;
case SCTP_PARAM_ACTION_SKIP:
Expand All @@ -1690,8 +1730,10 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,

if (*errp) {
sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
param.v,
WORD_ROUND(ntohs(param.p->length)));
sctp_addto_chunk(*errp,
WORD_ROUND(ntohs(param.p->length)),
param.v);
} else {
/* If there is no memory for generating the ERROR
* report as specified, an ABORT will be triggered
Expand Down Expand Up @@ -1791,7 +1833,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
* VIOLATION error. We build the ERROR chunk here and let the normal
* error handling code build and send the packet.
*/
if (param.v < (void*)chunk->chunk_end - sizeof(sctp_paramhdr_t)) {
if (param.v != (void*)chunk->chunk_end) {
sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
return 0;
}
Expand Down
8 changes: 6 additions & 2 deletions net/sctp/sm_sideeffect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1013,8 +1013,9 @@ static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
break;

case SCTP_DISPOSITION_VIOLATION:
printk(KERN_ERR "sctp protocol violation state %d "
"chunkid %d\n", state, subtype.chunk);
if (net_ratelimit())
printk(KERN_ERR "sctp protocol violation state %d "
"chunkid %d\n", state, subtype.chunk);
break;

case SCTP_DISPOSITION_NOT_IMPL:
Expand Down Expand Up @@ -1130,6 +1131,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
/* Move the Cumulattive TSN Ack ahead. */
sctp_tsnmap_skip(&asoc->peer.tsn_map, cmd->obj.u32);

/* purge the fragmentation queue */
sctp_ulpq_reasm_flushtsn(&asoc->ulpq, cmd->obj.u32);

/* Abort any in progress partial delivery. */
sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
break;
Expand Down
Loading

0 comments on commit b91ddd8

Please sign in to comment.