diff options
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
-rw-r--r-- | net/sctp/sm_make_chunk.c | 49 |
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)); |