aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-11-09 11:43:41 -0500
committerVlad Yasevich <vladislav.yasevich@hp.com>2007-11-09 11:43:41 -0500
commit7ab9080467040054e27ae54d67cc185f24d881ae (patch)
tree7364119d931501db9d8794294d037096a48d0863 /net/sctp
parentd970dbf8455eb1b8cebd3cde6e18f73dd1b3ce38 (diff)
SCTP: Make sctp_verify_param return multiple indications.
SCTP-AUTH and future ADD-IP updates have a requirement to do additional verification of parameters and an ability to ABORT the association if verification fails. So, introduce additional return code so that we can clear signal a required action. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/sm_make_chunk.c149
1 files changed, 75 insertions, 74 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 43e8de1228f9..5a9783c38de1 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1788,9 +1788,14 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
1788 sizeof(sctp_paramhdr_t); 1788 sizeof(sctp_paramhdr_t);
1789 1789
1790 1790
1791 /* This is a fatal error. Any accumulated non-fatal errors are
1792 * not reported.
1793 */
1794 if (*errp)
1795 sctp_chunk_free(*errp);
1796
1791 /* Create an error chunk and fill it in with our payload. */ 1797 /* Create an error chunk and fill it in with our payload. */
1792 if (!*errp) 1798 *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
1793 *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
1794 1799
1795 if (*errp) { 1800 if (*errp) {
1796 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, 1801 sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,
@@ -1813,9 +1818,15 @@ static int sctp_process_hn_param(const struct sctp_association *asoc,
1813{ 1818{
1814 __u16 len = ntohs(param.p->length); 1819 __u16 len = ntohs(param.p->length);
1815 1820
1816 /* Make an ERROR chunk. */ 1821 /* Processing of the HOST_NAME parameter will generate an
1817 if (!*errp) 1822 * ABORT. If we've accumulated any non-fatal errors, they
1818 *errp = sctp_make_op_error_space(asoc, chunk, len); 1823 * would be unrecognized parameters and we should not include
1824 * them in the ABORT.
1825 */
1826 if (*errp)
1827 sctp_chunk_free(*errp);
1828
1829 *errp = sctp_make_op_error_space(asoc, chunk, len);
1819 1830
1820 if (*errp) { 1831 if (*errp) {
1821 sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len); 1832 sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);
@@ -1862,56 +1873,40 @@ static void sctp_process_ext_param(struct sctp_association *asoc,
1862 * taken if the processing endpoint does not recognize the 1873 * taken if the processing endpoint does not recognize the
1863 * Parameter Type. 1874 * Parameter Type.
1864 * 1875 *
1865 * 00 - Stop processing this SCTP chunk and discard it, 1876 * 00 - Stop processing this parameter; do not process any further
1866 * do not process any further chunks within it. 1877 * parameters within this chunk
1867 * 1878 *
1868 * 01 - Stop processing this SCTP chunk and discard it, 1879 * 01 - Stop processing this parameter, do not process any further
1869 * do not process any further chunks within it, and report 1880 * parameters within this chunk, and report the unrecognized
1870 * the unrecognized parameter in an 'Unrecognized 1881 * parameter in an 'Unrecognized Parameter' ERROR chunk.
1871 * Parameter Type' (in either an ERROR or in the INIT ACK).
1872 * 1882 *
1873 * 10 - Skip this parameter and continue processing. 1883 * 10 - Skip this parameter and continue processing.
1874 * 1884 *
1875 * 11 - Skip this parameter and continue processing but 1885 * 11 - Skip this parameter and continue processing but
1876 * report the unrecognized parameter in an 1886 * report the unrecognized parameter in an
1877 * 'Unrecognized Parameter Type' (in either an ERROR or in 1887 * 'Unrecognized Parameter' ERROR chunk.
1878 * the INIT ACK).
1879 * 1888 *
1880 * Return value: 1889 * Return value:
1881 * 0 - discard the chunk 1890 * SCTP_IERROR_NO_ERROR - continue with the chunk
1882 * 1 - continue with the chunk 1891 * SCTP_IERROR_ERROR - stop and report an error.
1892 * SCTP_IERROR_NOMEME - out of memory.
1883 */ 1893 */
1884static int sctp_process_unk_param(const struct sctp_association *asoc, 1894static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,
1885 union sctp_params param, 1895 union sctp_params param,
1886 struct sctp_chunk *chunk, 1896 struct sctp_chunk *chunk,
1887 struct sctp_chunk **errp) 1897 struct sctp_chunk **errp)
1888{ 1898{
1889 int retval = 1; 1899 int retval = SCTP_IERROR_NO_ERROR;
1890 1900
1891 switch (param.p->type & SCTP_PARAM_ACTION_MASK) { 1901 switch (param.p->type & SCTP_PARAM_ACTION_MASK) {
1892 case SCTP_PARAM_ACTION_DISCARD: 1902 case SCTP_PARAM_ACTION_DISCARD:
1893 retval = 0; 1903 retval = SCTP_IERROR_ERROR;
1894 break;
1895 case SCTP_PARAM_ACTION_DISCARD_ERR:
1896 retval = 0;
1897 /* Make an ERROR chunk, preparing enough room for
1898 * returning multiple unknown parameters.
1899 */
1900 if (NULL == *errp)
1901 *errp = sctp_make_op_error_space(asoc, chunk,
1902 ntohs(chunk->chunk_hdr->length));
1903
1904 if (*errp) {
1905 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,
1906 WORD_ROUND(ntohs(param.p->length)));
1907 sctp_addto_chunk(*errp,
1908 WORD_ROUND(ntohs(param.p->length)),
1909 param.v);
1910 }
1911
1912 break; 1904 break;
1913 case SCTP_PARAM_ACTION_SKIP: 1905 case SCTP_PARAM_ACTION_SKIP:
1914 break; 1906 break;
1907 case SCTP_PARAM_ACTION_DISCARD_ERR:
1908 retval = SCTP_IERROR_ERROR;
1909 /* Fall through */
1915 case SCTP_PARAM_ACTION_SKIP_ERR: 1910 case SCTP_PARAM_ACTION_SKIP_ERR:
1916 /* Make an ERROR chunk, preparing enough room for 1911 /* Make an ERROR chunk, preparing enough room for
1917 * returning multiple unknown parameters. 1912 * returning multiple unknown parameters.
@@ -1932,9 +1927,8 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
1932 * to the peer and the association won't be 1927 * to the peer and the association won't be
1933 * established. 1928 * established.
1934 */ 1929 */
1935 retval = 0; 1930 retval = SCTP_IERROR_NOMEM;
1936 } 1931 }
1937
1938 break; 1932 break;
1939 default: 1933 default:
1940 break; 1934 break;
@@ -1943,18 +1937,20 @@ static int sctp_process_unk_param(const struct sctp_association *asoc,
1943 return retval; 1937 return retval;
1944} 1938}
1945 1939
1946/* Find unrecognized parameters in the chunk. 1940/* Verify variable length parameters
1947 * Return values: 1941 * Return values:
1948 * 0 - discard the chunk 1942 * SCTP_IERROR_ABORT - trigger an ABORT
1949 * 1 - continue with the chunk 1943 * SCTP_IERROR_NOMEM - out of memory (abort)
1944 * SCTP_IERROR_ERROR - stop processing, trigger an ERROR
1945 * SCTP_IERROR_NO_ERROR - continue with the chunk
1950 */ 1946 */
1951static int sctp_verify_param(const struct sctp_association *asoc, 1947static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc,
1952 union sctp_params param, 1948 union sctp_params param,
1953 sctp_cid_t cid, 1949 sctp_cid_t cid,
1954 struct sctp_chunk *chunk, 1950 struct sctp_chunk *chunk,
1955 struct sctp_chunk **err_chunk) 1951 struct sctp_chunk **err_chunk)
1956{ 1952{
1957 int retval = 1; 1953 int retval = SCTP_IERROR_NO_ERROR;
1958 1954
1959 /* FIXME - This routine is not looking at each parameter per the 1955 /* FIXME - This routine is not looking at each parameter per the
1960 * chunk type, i.e., unrecognized parameters should be further 1956 * chunk type, i.e., unrecognized parameters should be further
@@ -1976,7 +1972,9 @@ static int sctp_verify_param(const struct sctp_association *asoc,
1976 1972
1977 case SCTP_PARAM_HOST_NAME_ADDRESS: 1973 case SCTP_PARAM_HOST_NAME_ADDRESS:
1978 /* Tell the peer, we won't support this param. */ 1974 /* Tell the peer, we won't support this param. */
1979 return sctp_process_hn_param(asoc, param, chunk, err_chunk); 1975 sctp_process_hn_param(asoc, param, chunk, err_chunk);
1976 retval = SCTP_IERROR_ABORT;
1977 break;
1980 1978
1981 case SCTP_PARAM_FWD_TSN_SUPPORT: 1979 case SCTP_PARAM_FWD_TSN_SUPPORT:
1982 if (sctp_prsctp_enable) 1980 if (sctp_prsctp_enable)
@@ -1993,9 +1991,11 @@ static int sctp_verify_param(const struct sctp_association *asoc,
1993 * cause 'Protocol Violation'. 1991 * cause 'Protocol Violation'.
1994 */ 1992 */
1995 if (SCTP_AUTH_RANDOM_LENGTH != 1993 if (SCTP_AUTH_RANDOM_LENGTH !=
1996 ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) 1994 ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) {
1997 return sctp_process_inv_paramlength(asoc, param.p, 1995 sctp_process_inv_paramlength(asoc, param.p,
1998 chunk, err_chunk); 1996 chunk, err_chunk);
1997 retval = SCTP_IERROR_ABORT;
1998 }
1999 break; 1999 break;
2000 2000
2001 case SCTP_PARAM_CHUNKS: 2001 case SCTP_PARAM_CHUNKS:
@@ -2007,9 +2007,11 @@ static int sctp_verify_param(const struct sctp_association *asoc,
2007 * INIT-ACK chunk if the sender wants to receive authenticated 2007 * INIT-ACK chunk if the sender wants to receive authenticated
2008 * chunks. Its maximum length is 260 bytes. 2008 * chunks. Its maximum length is 260 bytes.
2009 */ 2009 */
2010 if (260 < ntohs(param.p->length)) 2010 if (260 < ntohs(param.p->length)) {
2011 return sctp_process_inv_paramlength(asoc, param.p, 2011 sctp_process_inv_paramlength(asoc, param.p,
2012 chunk, err_chunk); 2012 chunk, err_chunk);
2013 retval = SCTP_IERROR_ABORT;
2014 }
2013 break; 2015 break;
2014 2016
2015 case SCTP_PARAM_HMAC_ALGO: 2017 case SCTP_PARAM_HMAC_ALGO:
@@ -2020,8 +2022,7 @@ fallthrough:
2020 default: 2022 default:
2021 SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", 2023 SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
2022 ntohs(param.p->type), cid); 2024 ntohs(param.p->type), cid);
2023 return sctp_process_unk_param(asoc, param, chunk, err_chunk); 2025 retval = sctp_process_unk_param(asoc, param, chunk, err_chunk);
2024
2025 break; 2026 break;
2026 } 2027 }
2027 return retval; 2028 return retval;
@@ -2036,6 +2037,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
2036{ 2037{
2037 union sctp_params param; 2038 union sctp_params param;
2038 int has_cookie = 0; 2039 int has_cookie = 0;
2040 int result;
2039 2041
2040 /* Verify stream values are non-zero. */ 2042 /* Verify stream values are non-zero. */
2041 if ((0 == peer_init->init_hdr.num_outbound_streams) || 2043 if ((0 == peer_init->init_hdr.num_outbound_streams) ||
@@ -2043,8 +2045,7 @@ int sctp_verify_init(const struct sctp_association *asoc,
2043 (0 == peer_init->init_hdr.init_tag) || 2045 (0 == peer_init->init_hdr.init_tag) ||
2044 (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) { 2046 (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {
2045 2047
2046 sctp_process_inv_mandatory(asoc, chunk, errp); 2048 return sctp_process_inv_mandatory(asoc, chunk, errp);
2047 return 0;
2048 } 2049 }
2049 2050
2050 /* Check for missing mandatory parameters. */ 2051 /* Check for missing mandatory parameters. */
@@ -2062,29 +2063,29 @@ int sctp_verify_init(const struct sctp_association *asoc,
2062 * VIOLATION error. We build the ERROR chunk here and let the normal 2063 * VIOLATION error. We build the ERROR chunk here and let the normal
2063 * error handling code build and send the packet. 2064 * error handling code build and send the packet.
2064 */ 2065 */
2065 if (param.v != (void*)chunk->chunk_end) { 2066 if (param.v != (void*)chunk->chunk_end)
2066 sctp_process_inv_paramlength(asoc, param.p, chunk, errp); 2067 return sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
2067 return 0;
2068 }
2069 2068
2070 /* The only missing mandatory param possible today is 2069 /* The only missing mandatory param possible today is
2071 * the state cookie for an INIT-ACK chunk. 2070 * the state cookie for an INIT-ACK chunk.
2072 */ 2071 */
2073 if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) { 2072 if ((SCTP_CID_INIT_ACK == cid) && !has_cookie)
2074 sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE, 2073 return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
2075 chunk, errp); 2074 chunk, errp);
2076 return 0;
2077 }
2078
2079 /* Find unrecognized parameters. */
2080 2075
2076 /* Verify all the variable length parameters */
2081 sctp_walk_params(param, peer_init, init_hdr.params) { 2077 sctp_walk_params(param, peer_init, init_hdr.params) {
2082 2078
2083 if (!sctp_verify_param(asoc, param, cid, chunk, errp)) { 2079 result = sctp_verify_param(asoc, param, cid, chunk, errp);
2084 if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type) 2080 switch (result) {
2081 case SCTP_IERROR_ABORT:
2082 case SCTP_IERROR_NOMEM:
2085 return 0; 2083 return 0;
2086 else 2084 case SCTP_IERROR_ERROR:
2087 return 1; 2085 return 1;
2086 case SCTP_IERROR_NO_ERROR:
2087 default:
2088 break;
2088 } 2089 }
2089 2090
2090 } /* for (loop through all parameters) */ 2091 } /* for (loop through all parameters) */