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);
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
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",
* 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;
}
break;
case SCTP_PARAM_IPV6_ADDRESS:
- asoc->peer.ipv6_address = 1;
+ if (PF_INET6 == asoc->base.sk->sk_family)
+ asoc->peer.ipv6_address = 1;
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
addr_param = (union sctp_addr_param *)
((void *)asconf_param + sizeof(sctp_addip_param_t));
+ switch (addr_param->v4.param_hdr.type) {
+ case SCTP_PARAM_IPV6_ADDRESS:
+ if (!asoc->peer.ipv6_address)
+ return SCTP_ERROR_INV_PARAM;
+ break;
+ case SCTP_PARAM_IPV4_ADDRESS:
+ if (!asoc->peer.ipv4_address)
+ return SCTP_ERROR_INV_PARAM;
+ break;
+ default:
+ return SCTP_ERROR_INV_PARAM;
+ }
+
af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
if (unlikely(!af))
return SCTP_ERROR_INV_PARAM;
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;
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));