Commit d979fc87 authored by Jon Grimm's avatar Jon Grimm

[SCTP] More param handling, mostly handling hostname parm (jgrimm)

Per RFC, ABORT the peer if you don't want to support hostname parm.
Found/fixed potential div by zero.
Changed process_init to return error code, so its clients can do error handling.
parent e9499fc9
...@@ -3,41 +3,41 @@ ...@@ -3,41 +3,41 @@
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 International Business Machines, Corp. * Copyright (c) 2001 International Business Machines, Corp.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* The base lksctp header. * The base lksctp header.
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email address(es): * email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org> * La Monte H.P. Yarroll <piggy@acm.org>
* Xingang Guo <xingang.guo@intel.com> * Xingang Guo <xingang.guo@intel.com>
* Jon Grimm <jgrimm@us.ibm.com> * Jon Grimm <jgrimm@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -52,10 +52,10 @@ ...@@ -52,10 +52,10 @@
* structs * structs
* prototypes * prototypes
* macros, externs, and inlines * macros, externs, and inlines
* *
* Move test_frame specific items out of the kernel headers * Move test_frame specific items out of the kernel headers
* and into the test frame headers. This is not perfect in any sense * and into the test frame headers. This is not perfect in any sense
* and will continue to evolve. * and will continue to evolve.
*/ */
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/ip6_route.h> #include <net/ip6_route.h>
#endif #endif
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -105,19 +105,19 @@ ...@@ -105,19 +105,19 @@
#endif #endif
/* Certain internal static functions need to be exported when /* Certain internal static functions need to be exported when
* compiled into the test frame. * compiled into the test frame.
*/ */
#ifndef SCTP_STATIC #ifndef SCTP_STATIC
#define SCTP_STATIC static #define SCTP_STATIC static
#endif #endif
/* /*
* Function declarations. * Function declarations.
*/ */
/* /*
* sctp_protocol.c * sctp_protocol.c
*/ */
extern sctp_protocol_t sctp_proto; extern sctp_protocol_t sctp_proto;
extern struct sock *sctp_get_ctl_sock(void); extern struct sock *sctp_get_ctl_sock(void);
...@@ -421,14 +421,15 @@ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) ...@@ -421,14 +421,15 @@ static inline size_t get_user_iov_size(struct iovec *iov, int iovlen)
/* Walk through a list of TLV parameters. Don't trust the /* Walk through a list of TLV parameters. Don't trust the
* individual parameter lengths and instead depend on * individual parameter lengths and instead depend on
* the chunk length to indicate when to stop. Make sure * the chunk length to indicate when to stop. Make sure
* there is room for a param header too. * there is room for a param header too.
*/ */
#define sctp_walk_params(pos, chunk, member)\ #define sctp_walk_params(pos, chunk, member)\
_sctp_walk_params(((union sctp_params)(pos)), (chunk), member) _sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member)
#define _sctp_walk_params(pos, chunk, member)\ #define _sctp_walk_params(pos, chunk, end, member)\
for (pos.v = (void *)&chunk->member;\ for (pos.v = chunk->member;\
pos.v <= (void *)chunk + ntohs(chunk->chunk_hdr.length) - sizeof(sctp_paramhdr_t);\ pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\
pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \
pos.v += WORD_ROUND(ntohs(pos.p->length))) pos.v += WORD_ROUND(ntohs(pos.p->length)))
/* Round an int up to the next multiple of 4. */ /* Round an int up to the next multiple of 4. */
......
...@@ -3,34 +3,34 @@ ...@@ -3,34 +3,34 @@
* Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 1999-2001 Motorola, Inc.
* Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Intel Corp.
* Copyright (c) 2001 International Business Machines Corp. * Copyright (c) 2001 International Business Machines Corp.
* *
* This file is part of the SCTP kernel reference Implementation * This file is part of the SCTP kernel reference Implementation
* *
* The SCTP reference implementation is free software; * The SCTP reference implementation is free software;
* you can redistribute it and/or modify it under the terms of * you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by * the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option) * the Free Software Foundation; either version 2, or (at your option)
* any later version. * any later version.
* *
* The SCTP reference implementation is distributed in the hope that it * The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied * will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************ * ************************
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to * along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330, * the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
* *
* Please send any bug reports or fixes you make to the * Please send any bug reports or fixes you make to the
* email addresses: * email addresses:
* lksctp developers <lksctp-developers@lists.sourceforge.net> * lksctp developers <lksctp-developers@lists.sourceforge.net>
* *
* Or submit a bug report through the following website: * Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp * http://www.sf.net/projects/lksctp
* *
* Written or modified by: * Written or modified by:
* Randall Stewart <randall@sctp.chicago.il.us> * Randall Stewart <randall@sctp.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com> * Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@email.mot.com> * Qiaobing Xie <qxie1@email.mot.com>
...@@ -41,8 +41,8 @@ ...@@ -41,8 +41,8 @@
* Hui Huang <hui.huang@nokia.com> * Hui Huang <hui.huang@nokia.com>
* Sridhar Samudrala <sri@us.ibm.com> * Sridhar Samudrala <sri@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com> * Daisy Chang <daisyc@us.ibm.com>
* Dajiang Zhang <dajiang.zhang@nokia.com> * Dajiang Zhang <dajiang.zhang@nokia.com>
* *
* Any bugs reported given to us we will try to fix... any fixes shared will * Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release. * be incorporated into the next SCTP release.
*/ */
...@@ -250,7 +250,7 @@ typedef struct sctp_func { ...@@ -250,7 +250,7 @@ typedef struct sctp_func {
sockaddr_storage_t *saddr); sockaddr_storage_t *saddr);
int (*cmp_saddr) (struct dst_entry *dst, int (*cmp_saddr) (struct dst_entry *dst,
sockaddr_storage_t *saddr); sockaddr_storage_t *saddr);
__u16 net_header_len; __u16 net_header_len;
int sockaddr_len; int sockaddr_len;
sa_family_t sa_family; sa_family_t sa_family;
struct list_head list; struct list_head list;
...@@ -374,7 +374,7 @@ typedef union { ...@@ -374,7 +374,7 @@ typedef union {
*/ */
union sctp_params { union sctp_params {
void *v; void *v;
sctp_paramhdr_t *p; sctp_paramhdr_t *p;
sctp_cookie_preserve_param_t *life; sctp_cookie_preserve_param_t *life;
sctp_hostname_param_t *dns; sctp_hostname_param_t *dns;
sctp_cookie_param_t *cookie; sctp_cookie_param_t *cookie;
...@@ -475,7 +475,7 @@ struct SCTP_chunk { ...@@ -475,7 +475,7 @@ struct SCTP_chunk {
__u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */
__u8 pdiscard; /* Discard the whole packet now? */ __u8 pdiscard; /* Discard the whole packet now? */
__u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */
__u8 fast_retransmit; /* Is this chunk fast retransmitted? */ __u8 fast_retransmit; /* Is this chunk fast retransmitted? */
__u8 tsn_missing_report; /* Data chunk missing counter. */ __u8 tsn_missing_report; /* Data chunk missing counter. */
/* What is the origin IP address for this chunk? */ /* What is the origin IP address for this chunk? */
...@@ -914,7 +914,7 @@ int sctp_addr_is_valid(const sockaddr_storage_t *addr); ...@@ -914,7 +914,7 @@ int sctp_addr_is_valid(const sockaddr_storage_t *addr);
typedef enum { typedef enum {
SCTP_EP_TYPE_SOCKET, SCTP_EP_TYPE_SOCKET,
SCTP_EP_TYPE_ASSOCIATION, SCTP_EP_TYPE_ASSOCIATION,
} sctp_endpoint_type_t; } sctp_endpoint_type_t;
/* /*
* A common base class to bridge the implmentation view of a * A common base class to bridge the implmentation view of a
...@@ -1062,22 +1062,11 @@ int sctp_verify_init(const sctp_association_t *asoc, ...@@ -1062,22 +1062,11 @@ int sctp_verify_init(const sctp_association_t *asoc,
sctp_init_chunk_t *peer_init, sctp_init_chunk_t *peer_init,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chunk); sctp_chunk_t **err_chunk);
int sctp_verify_param(const sctp_association_t *asoc, int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
union sctp_params param, const sockaddr_storage_t *peer_addr,
sctp_cid_t cid, sctp_init_chunk_t *peer_init, int priority);
sctp_chunk_t *chunk, int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
sctp_chunk_t **err_chunk); const sockaddr_storage_t *peer_addr, int priority);
int sctp_process_unk_param(const sctp_association_t *asoc,
union sctp_params param,
sctp_chunk_t *chunk,
sctp_chunk_t **err_chunk);
void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
const sockaddr_storage_t *peer_addr,
sctp_init_chunk_t *peer_init, int priority);
int sctp_process_param(sctp_association_t *asoc,
union sctp_params param,
const sockaddr_storage_t *peer_addr,
sctp_cid_t cid, int priority);
__u32 sctp_generate_tag(const sctp_endpoint_t *ep); __u32 sctp_generate_tag(const sctp_endpoint_t *ep);
__u32 sctp_generate_tsn(const sctp_endpoint_t *ep); __u32 sctp_generate_tsn(const sctp_endpoint_t *ep);
...@@ -1164,10 +1153,10 @@ struct SCTP_association { ...@@ -1164,10 +1153,10 @@ struct SCTP_association {
sctp_transport_t *primary_path; sctp_transport_t *primary_path;
/* Cache the primary path address here, when we /* Cache the primary path address here, when we
* need a an address for msg_name. * need a an address for msg_name.
*/ */
sockaddr_storage_t primary_addr; sockaddr_storage_t primary_addr;
/* active_path /* active_path
* The path that we are currently using to * The path that we are currently using to
* transmit new data and most control chunks. * transmit new data and most control chunks.
...@@ -1268,7 +1257,7 @@ struct SCTP_association { ...@@ -1268,7 +1257,7 @@ struct SCTP_association {
/* Overall : The threshold for this association that if /* Overall : The threshold for this association that if
* Error : the Overall Error Count reaches will cause * Error : the Overall Error Count reaches will cause
* Threshold : this association to be torn down. * Threshold : this association to be torn down.
*/ */
int overall_error_threshold; int overall_error_threshold;
...@@ -1314,13 +1303,13 @@ struct SCTP_association { ...@@ -1314,13 +1303,13 @@ struct SCTP_association {
*/ */
__u32 next_tsn; __u32 next_tsn;
/* /*
* Last Rcvd : This is the last TSN received in sequence. This value * Last Rcvd : This is the last TSN received in sequence. This value
* TSN : is set initially by taking the peer's Initial TSN, * TSN : is set initially by taking the peer's Initial TSN,
* : received in the INIT or INIT ACK chunk, and * : received in the INIT or INIT ACK chunk, and
* : subtracting one from it. * : subtracting one from it.
* *
* Most of RFC 2960 refers to this as the Cumulative TSN Ack Point. * Most of RFC 2960 refers to this as the Cumulative TSN Ack Point.
*/ */
__u32 ctsn_ack_point; __u32 ctsn_ack_point;
......
...@@ -568,7 +568,7 @@ sctp_association_t *sctp_lookup_association(const sockaddr_storage_t *laddr, ...@@ -568,7 +568,7 @@ sctp_association_t *sctp_lookup_association(const sockaddr_storage_t *laddr,
sctp_local_bh_disable(); sctp_local_bh_disable();
asoc = __sctp_lookup_association(laddr, paddr, transportp); asoc = __sctp_lookup_association(laddr, paddr, transportp);
sctp_local_bh_enable(); sctp_local_bh_enable();
return asoc; return asoc;
} }
...@@ -614,13 +614,11 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb, ...@@ -614,13 +614,11 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb,
sockaddr_storage_t *paddr = &addr; sockaddr_storage_t *paddr = &addr;
struct sctphdr *sh = (struct sctphdr *) skb->h.raw; struct sctphdr *sh = (struct sctphdr *) skb->h.raw;
sctp_chunkhdr_t *ch; sctp_chunkhdr_t *ch;
__u8 *ch_end, *data; union sctp_params params;
sctp_paramhdr_t *parm; sctp_init_chunk_t *init;
ch = (sctp_chunkhdr_t *) skb->data; ch = (sctp_chunkhdr_t *) skb->data;
ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
/* If this is INIT/INIT-ACK look inside the chunk too. */ /* If this is INIT/INIT-ACK look inside the chunk too. */
switch (ch->type) { switch (ch->type) {
case SCTP_CID_INIT: case SCTP_CID_INIT:
...@@ -646,24 +644,17 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb, ...@@ -646,24 +644,17 @@ static sctp_association_t *__sctp_rcv_initack_lookup(struct sk_buff *skb,
/* Find the start of the TLVs and the end of the chunk. This is /* Find the start of the TLVs and the end of the chunk. This is
* the region we search for address parameters. * the region we search for address parameters.
*/ */
data = skb->data + sizeof(sctp_init_chunk_t); init = (sctp_init_chunk_t *)skb->data;
/* See sctp_process_init() for how to go thru TLVs. */
while (data < ch_end) {
parm = (sctp_paramhdr_t *)data;
if (!parm->length)
break;
data += WORD_ROUND(ntohs(parm->length)); /* Walk the parameters looking for embedded addresses. */
sctp_walk_params(params, init, init_hdr.params) {
/* Note: Ignoring hostname addresses. */ /* Note: Ignoring hostname addresses. */
if ((SCTP_PARAM_IPV4_ADDRESS != parm->type) && if ((SCTP_PARAM_IPV4_ADDRESS != params.p->type) &&
(SCTP_PARAM_IPV6_ADDRESS != parm->type)) (SCTP_PARAM_IPV6_ADDRESS != params.p->type))
continue; continue;
sctp_param2sockaddr(paddr, (sctp_addr_param_t *)parm, sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source));
ntohs(sh->source));
asoc = __sctp_lookup_association(laddr, paddr, transportp); asoc = __sctp_lookup_association(laddr, paddr, transportp);
if (asoc) if (asoc)
return asoc; return asoc;
......
...@@ -1482,74 +1482,28 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep, ...@@ -1482,74 +1482,28 @@ sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
* 3rd Level Abstractions * 3rd Level Abstractions
********************************************************************/ ********************************************************************/
/* Verify the INIT packet before we process it. */ /* Do not attempt to handle the HOST_NAME parm. However, do
int sctp_verify_init(const sctp_association_t *asoc, * send back an indicator to the peer.
sctp_cid_t cid,
sctp_init_chunk_t *peer_init,
sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p)
{
union sctp_params param;
/* FIXME - Verify the fixed fields of the INIT chunk. Also, verify
* the mandatory parameters somewhere here and generate either the
* "Missing mandatory parameter" error or the "Invalid mandatory
* parameter" error.
*/
/* Find unrecognized parameters. */
sctp_walk_params(param, peer_init, init_hdr.params) {
if (!sctp_verify_param(asoc, param, cid, chunk, err_chk_p))
return 0;
} /* for (loop through all parameters) */
return 1;
}
/* Find unrecognized parameters in the chunk.
* Return values:
* 0 - discard the chunk
* 1 - continue with the chunk
*/ */
int sctp_verify_param(const sctp_association_t *asoc, static int sctp_process_hn_param(const sctp_association_t *asoc,
union sctp_params param, union sctp_params param,
sctp_cid_t cid, sctp_chunk_t *chunk,
sctp_chunk_t *chunk, sctp_chunk_t **err_chk_p)
sctp_chunk_t **err_chk_p)
{ {
int retval = 1; __u16 len = ntohs(param.p->length);
/* FIXME - This routine is not looking at each parameter per the /* Make an ERROR chunk, preparing enough room for
* chunk type, i.e., unrecognized parameters should be further * returning multiple unknown parameters.
* identified based on the chunk id.
*/ */
if (!*err_chk_p)
*err_chk_p = sctp_make_op_error_space(asoc, chunk, len);
switch (param.p->type) { if (*err_chk_p)
case SCTP_PARAM_IPV4_ADDRESS: sctp_init_cause(*err_chk_p, SCTP_ERROR_DNS_FAILED,
case SCTP_PARAM_IPV6_ADDRESS: param.v, len);
case SCTP_PARAM_COOKIE_PRESERVATIVE:
/* FIXME - If we don't support the host name parameter, we should
* generate an error for this - Unresolvable address.
*/
case SCTP_PARAM_HOST_NAME_ADDRESS:
case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
case SCTP_PARAM_STATE_COOKIE:
case SCTP_PARAM_HEARTBEAT_INFO:
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
break;
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
ntohs(param.p->type), cid);
return sctp_process_unk_param(asoc, param, chunk, err_chk_p);
break; /* Stop processing this chunk. */
} return 0;
return retval;
} }
/* RFC 3.2.1 & the Implementers Guide 2.2. /* RFC 3.2.1 & the Implementers Guide 2.2.
...@@ -1578,10 +1532,10 @@ int sctp_verify_param(const sctp_association_t *asoc, ...@@ -1578,10 +1532,10 @@ int sctp_verify_param(const sctp_association_t *asoc,
* 0 - discard the chunk * 0 - discard the chunk
* 1 - continue with the chunk * 1 - continue with the chunk
*/ */
int sctp_process_unk_param(const sctp_association_t *asoc, static int sctp_process_unk_param(const sctp_association_t *asoc,
union sctp_params param, union sctp_params param,
sctp_chunk_t *chunk, sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p) sctp_chunk_t **err_chk_p)
{ {
int retval = 1; int retval = 1;
...@@ -1600,7 +1554,7 @@ int sctp_process_unk_param(const sctp_association_t *asoc, ...@@ -1600,7 +1554,7 @@ int sctp_process_unk_param(const sctp_association_t *asoc,
if (*err_chk_p) if (*err_chk_p)
sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM, sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM,
(const void *)param.p, param.v,
WORD_ROUND(ntohs(param.p->length))); WORD_ROUND(ntohs(param.p->length)));
break; break;
...@@ -1616,7 +1570,7 @@ int sctp_process_unk_param(const sctp_association_t *asoc, ...@@ -1616,7 +1570,7 @@ int sctp_process_unk_param(const sctp_association_t *asoc,
if (*err_chk_p) { if (*err_chk_p) {
sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM, sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM,
(const void *)param.p, param.v,
WORD_ROUND(ntohs(param.p->length))); WORD_ROUND(ntohs(param.p->length)));
} else { } else {
/* If there is no memory for generating the ERROR /* If there is no memory for generating the ERROR
...@@ -1634,14 +1588,82 @@ int sctp_process_unk_param(const sctp_association_t *asoc, ...@@ -1634,14 +1588,82 @@ int sctp_process_unk_param(const sctp_association_t *asoc,
return retval; return retval;
} }
/* Unpack the parameters in an INIT packet. /* Find unrecognized parameters in the chunk.
* FIXME: There is no return status to allow callers to do * Return values:
* error handling. * 0 - discard the chunk
* 1 - continue with the chunk
*/ */
void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, static int sctp_verify_param(const sctp_association_t *asoc,
const sockaddr_storage_t *peer_addr, union sctp_params param,
sctp_init_chunk_t *peer_init, sctp_cid_t cid,
int priority) sctp_chunk_t *chunk,
sctp_chunk_t **err_chunk)
{
int retval = 1;
/* FIXME - This routine is not looking at each parameter per the
* chunk type, i.e., unrecognized parameters should be further
* identified based on the chunk id.
*/
switch (param.p->type) {
case SCTP_PARAM_IPV4_ADDRESS:
case SCTP_PARAM_IPV6_ADDRESS:
case SCTP_PARAM_COOKIE_PRESERVATIVE:
case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
case SCTP_PARAM_STATE_COOKIE:
case SCTP_PARAM_HEARTBEAT_INFO:
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
/* Tell the peer, we won't support this param. */
return sctp_process_hn_param(asoc, param, chunk, err_chunk);
default:
SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
ntohs(param.p->type), cid);
return sctp_process_unk_param(asoc, param, chunk, err_chunk);
break;
}
return retval;
}
/* Verify the INIT packet before we process it. */
int sctp_verify_init(const sctp_association_t *asoc,
sctp_cid_t cid,
sctp_init_chunk_t *peer_init,
sctp_chunk_t *chunk,
sctp_chunk_t **err_chk_p)
{
union sctp_params param;
/* FIXME - Verify the fixed fields of the INIT chunk. Also, verify
* the mandatory parameters somewhere here and generate either the
* "Missing mandatory parameter" error or the "Invalid mandatory
* parameter" error.
*/
/* Find unrecognized parameters. */
sctp_walk_params(param, peer_init, init_hdr.params) {
if (!sctp_verify_param(asoc, param, cid, chunk, err_chk_p))
return 0;
} /* for (loop through all parameters) */
return 1;
}
/* Unpack the parameters in an INIT packet into an association.
* Returns 0 on failure, else success.
*/
int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
const sockaddr_storage_t *peer_addr,
sctp_init_chunk_t *peer_init,
int priority)
{ {
union sctp_params param; union sctp_params param;
sctp_transport_t *transport; sctp_transport_t *transport;
...@@ -1659,14 +1681,14 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1659,14 +1681,14 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* be a a better choice than any of the embedded addresses. * be a a better choice than any of the embedded addresses.
*/ */
if (peer_addr) if (peer_addr)
sctp_assoc_add_peer(asoc, peer_addr, priority); if(!sctp_assoc_add_peer(asoc, peer_addr, priority))
goto nomem;
/* Process the initialization parameters. */ /* Process the initialization parameters. */
sctp_walk_params(param, peer_init, init_hdr.params) { sctp_walk_params(param, peer_init, init_hdr.params) {
if (!sctp_process_param(asoc, param, peer_addr, cid, if (!sctp_process_param(asoc, param, peer_addr, priority))
priority))
goto clean_up; goto clean_up;
} }
...@@ -1732,7 +1754,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1732,7 +1754,7 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* association to the same value as the Initial TSN. * association to the same value as the Initial TSN.
*/ */
asoc->peer.addip_serial = asoc->peer.i.initial_tsn - 1; asoc->peer.addip_serial = asoc->peer.i.initial_tsn - 1;
return; return 1;
clean_up: clean_up:
/* Release the transport structures. */ /* Release the transport structures. */
...@@ -1741,8 +1763,11 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1741,8 +1763,11 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
list_del(pos); list_del(pos);
sctp_transport_free(transport); sctp_transport_free(transport);
} }
nomem:
return 0;
} }
/* Update asoc with the option described in param. /* Update asoc with the option described in param.
* *
* RFC2960 3.3.2.1 Optional/Variable Length Parameters in INIT * RFC2960 3.3.2.1 Optional/Variable Length Parameters in INIT
...@@ -1755,13 +1780,11 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid, ...@@ -1755,13 +1780,11 @@ void sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
* structures for the addresses. * structures for the addresses.
*/ */
int sctp_process_param(sctp_association_t *asoc, union sctp_params param, int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
const sockaddr_storage_t *peer_addr, const sockaddr_storage_t *peer_addr, int priority)
sctp_cid_t cid, int priority)
{ {
sockaddr_storage_t addr; sockaddr_storage_t addr;
sctp_addr_param_t *addrparm;
int j;
int i; int i;
__u16 sat;
int retval = 1; int retval = 1;
sctp_scope_t scope; sctp_scope_t scope;
...@@ -1770,25 +1793,16 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param, ...@@ -1770,25 +1793,16 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
* came from a fresh INIT, and INIT ACK, or were stored in a cookie. * came from a fresh INIT, and INIT ACK, or were stored in a cookie.
*/ */
switch (param.p->type) { switch (param.p->type) {
case SCTP_PARAM_IPV6_ADDRESS:
if( PF_INET6 != asoc->base.sk->family)
break;
/* Fall through. */
case SCTP_PARAM_IPV4_ADDRESS: case SCTP_PARAM_IPV4_ADDRESS:
addrparm = (sctp_addr_param_t *)param.v; sctp_param2sockaddr(&addr, param.addr, asoc->peer.port);
sctp_param2sockaddr(&addr, addrparm, asoc->peer.port);
scope = sctp_scope(peer_addr); scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope)) if (sctp_in_scope(&addr, scope))
sctp_assoc_add_peer(asoc, &addr, priority); if (!sctp_assoc_add_peer(asoc, &addr, priority))
break; return 0;
case SCTP_PARAM_IPV6_ADDRESS:
/* Rethink this as we may need to keep for
* restart considerations.
*/
if (PF_INET6 == asoc->base.sk->family) {
addrparm = (sctp_addr_param_t *)param.v;
sctp_param2sockaddr(&addr, addrparm, asoc->peer.port);
scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope))
sctp_assoc_add_peer(asoc, &addr, priority);
}
break; break;
case SCTP_PARAM_COOKIE_PRESERVATIVE: case SCTP_PARAM_COOKIE_PRESERVATIVE:
...@@ -1807,10 +1821,12 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param, ...@@ -1807,10 +1821,12 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
asoc->peer.ipv4_address = 0; asoc->peer.ipv4_address = 0;
asoc->peer.ipv6_address = 0; asoc->peer.ipv6_address = 0;
j = (ntohs(param.p->length) - /* Cycle through address types; avoid divide by 0. */
sizeof(sctp_paramhdr_t)) / sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
sizeof(__u16); if (sat)
for (i = 0; i < j; ++i) { sat /= sizeof(__u16);
for (i = 0; i < sat; ++i) {
switch (param.sat->types[i]) { switch (param.sat->types[i]) {
case SCTP_PARAM_IPV4_ADDRESS: case SCTP_PARAM_IPV4_ADDRESS:
asoc->peer.ipv4_address = 1; asoc->peer.ipv4_address = 1;
...@@ -1837,13 +1853,11 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param, ...@@ -1837,13 +1853,11 @@ int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
break; break;
case SCTP_PARAM_HEARTBEAT_INFO: case SCTP_PARAM_HEARTBEAT_INFO:
SCTP_DEBUG_PRINTK("unimplemented " /* Would be odd to receive, but it causes no problems. */
"SCTP_PARAM_HEARTBEAT_INFO\n");
break; break;
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS: case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
SCTP_DEBUG_PRINTK("unimplemented " /* Rejected during verify stage. */
"SCTP_PARAM_UNRECOGNIZED_PARAMETERS\n");
break; break;
case SCTP_PARAM_ECN_CAPABLE: case SCTP_PARAM_ECN_CAPABLE:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment