summaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_make_chunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r--net/sctp/sm_make_chunk.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index e45be4e3f80..81b606424e1 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1782,7 +1782,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
struct sctp_chunk **errp)
{
- char error[] = "The following parameter had invalid length:";
+ static const char error[] = "The following parameter had invalid length:";
size_t payload_len = WORD_ROUND(sizeof(error)) +
sizeof(sctp_paramhdr_t);
@@ -1982,7 +1982,10 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
struct sctp_chunk *chunk,
struct sctp_chunk **err_chunk)
{
+ struct sctp_hmac_algo_param *hmacs;
int retval = SCTP_IERROR_NO_ERROR;
+ __u16 n_elt, id = 0;
+ int i;
/* FIXME - This routine is not looking at each parameter per the
* chunk type, i.e., unrecognized parameters should be further
@@ -2056,9 +2059,29 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
break;
case SCTP_PARAM_HMAC_ALGO:
- if (sctp_auth_enable)
- break;
- /* Fall Through */
+ if (!sctp_auth_enable)
+ goto fallthrough;
+
+ hmacs = (struct sctp_hmac_algo_param *)param.p;
+ n_elt = (ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) >> 1;
+
+ /* SCTP-AUTH: Section 6.1
+ * The HMAC algorithm based on SHA-1 MUST be supported and
+ * included in the HMAC-ALGO parameter.
+ */
+ for (i = 0; i < n_elt; i++) {
+ id = ntohs(hmacs->hmac_ids[i]);
+
+ if (id == SCTP_AUTH_HMAC_ID_SHA1)
+ break;
+ }
+
+ if (id != SCTP_AUTH_HMAC_ID_SHA1) {
+ sctp_process_inv_paramlength(asoc, param.p, chunk,
+ err_chunk);
+ retval = SCTP_IERROR_ABORT;
+ }
+ break;
fallthrough:
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
@@ -2246,8 +2269,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* high (for example, implementations MAY use the size of the receiver
* advertised window).
*/
- list_for_each(pos, &asoc->peer.transport_addr_list) {
- transport = list_entry(pos, struct sctp_transport, transports);
+ list_for_each_entry(transport, &asoc->peer.transport_addr_list,
+ transports) {
transport->ssthresh = asoc->peer.i.a_rwnd;
}
@@ -2375,6 +2398,14 @@ static int sctp_process_param(struct sctp_association *asoc,
asoc->peer.ipv4_address = 0;
asoc->peer.ipv6_address = 0;
+ /* Assume that peer supports the address family
+ * by which it sends a packet.
+ */
+ if (peer_addr->sa.sa_family == AF_INET6)
+ asoc->peer.ipv6_address = 1;
+ else if (peer_addr->sa.sa_family == AF_INET)
+ asoc->peer.ipv4_address = 1;
+
/* Cycle through address types; avoid divide by 0. */
sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
if (sat)
@@ -3035,7 +3066,6 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
union sctp_addr addr;
struct sctp_bind_addr *bp = &asoc->base.bind_addr;
union sctp_addr_param *addr_param;
- struct list_head *pos;
struct sctp_transport *transport;
struct sctp_sockaddr_entry *saddr;
int retval = 0;
@@ -3063,9 +3093,8 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
local_bh_disable();
retval = sctp_del_bind_addr(bp, &addr);
local_bh_enable();
- list_for_each(pos, &asoc->peer.transport_addr_list) {
- transport = list_entry(pos, struct sctp_transport,
- transports);
+ list_for_each_entry(transport, &asoc->peer.transport_addr_list,
+ transports) {
dst_release(transport->dst);
sctp_transport_route(transport, NULL,
sctp_sk(asoc->base.sk));