diff options
| author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-09-16 18:53:56 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:51:23 -0400 |
| commit | 131a47e31ab1a9defd50ff16b04008ab94c21c0d (patch) | |
| tree | 8ac3eb522333d1b6f9bd5741a8decbfb4220f432 /net/sctp | |
| parent | 76c72d4f44ec5fb7f88eda8a0d3aa30922c891d1 (diff) | |
[SCTP]: Implement the Supported Extensions Parameter
SCTP Supported Extenions parameter is specified in Section 4.2.7
of the ADD-IP draft (soon to be RFC). The parameter is
encoded as:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Parameter Type = 0x8008 | Parameter Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CHUNK TYPE 1 | CHUNK TYPE 2 | CHUNK TYPE 3 | CHUNK TYPE 4 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CHUNK TYPE N | PAD | PAD | PAD |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
It contains a list of chunks that a particular SCTP extension
uses. Current extensions supported are Partial Reliability
(FWD-TSN) and ADD-IP (ASCONF and ASCONF-ACK).
When implementing new extensions (AUTH, PKT-DROP, etc..), new
chunks need to be added to this parameter. Parameter processing
would be modified to negotiate support for these new features.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 91 |
1 files changed, 89 insertions, 2 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index d84e575f7409..71cc204a9ea5 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -179,6 +179,9 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 179 | sctp_supported_addrs_param_t sat; | 179 | sctp_supported_addrs_param_t sat; |
| 180 | __be16 types[2]; | 180 | __be16 types[2]; |
| 181 | sctp_adaptation_ind_param_t aiparam; | 181 | sctp_adaptation_ind_param_t aiparam; |
| 182 | sctp_supported_ext_param_t ext_param; | ||
| 183 | int num_ext = 0; | ||
| 184 | __u8 extensions[3]; | ||
| 182 | 185 | ||
| 183 | /* RFC 2960 3.3.2 Initiation (INIT) (1) | 186 | /* RFC 2960 3.3.2 Initiation (INIT) (1) |
| 184 | * | 187 | * |
| @@ -202,11 +205,31 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 202 | 205 | ||
| 203 | chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); | 206 | chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); |
| 204 | chunksize += sizeof(ecap_param); | 207 | chunksize += sizeof(ecap_param); |
| 205 | if (sctp_prsctp_enable) | 208 | if (sctp_prsctp_enable) { |
| 206 | chunksize += sizeof(prsctp_param); | 209 | chunksize += sizeof(prsctp_param); |
| 210 | extensions[num_ext] = SCTP_CID_FWD_TSN; | ||
| 211 | num_ext += 1; | ||
| 212 | } | ||
| 213 | /* ADDIP: Section 4.2.7: | ||
| 214 | * An implementation supporting this extension [ADDIP] MUST list | ||
| 215 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and | ||
| 216 | * INIT-ACK parameters. | ||
| 217 | * XXX: We don't support AUTH just yet, so don't list it. AUTH | ||
| 218 | * support should add it. | ||
| 219 | */ | ||
| 220 | if (sctp_addip_enable) { | ||
| 221 | extensions[num_ext] = SCTP_CID_ASCONF; | ||
| 222 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; | ||
| 223 | num_ext += 2; | ||
| 224 | } | ||
| 225 | |||
| 207 | chunksize += sizeof(aiparam); | 226 | chunksize += sizeof(aiparam); |
| 208 | chunksize += vparam_len; | 227 | chunksize += vparam_len; |
| 209 | 228 | ||
| 229 | /* If we have any extensions to report, account for that */ | ||
| 230 | if (num_ext) | ||
| 231 | chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; | ||
| 232 | |||
| 210 | /* RFC 2960 3.3.2 Initiation (INIT) (1) | 233 | /* RFC 2960 3.3.2 Initiation (INIT) (1) |
| 211 | * | 234 | * |
| 212 | * Note 3: An INIT chunk MUST NOT contain more than one Host | 235 | * Note 3: An INIT chunk MUST NOT contain more than one Host |
| @@ -241,12 +264,27 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
| 241 | sctp_addto_chunk(retval, num_types * sizeof(__u16), &types); | 264 | sctp_addto_chunk(retval, num_types * sizeof(__u16), &types); |
| 242 | 265 | ||
| 243 | sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param); | 266 | sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param); |
| 267 | |||
| 268 | /* Add the supported extensions paramter. Be nice and add this | ||
| 269 | * fist before addiding the parameters for the extensions themselves | ||
| 270 | */ | ||
| 271 | if (num_ext) { | ||
| 272 | ext_param.param_hdr.type = SCTP_PARAM_SUPPORTED_EXT; | ||
| 273 | ext_param.param_hdr.length = | ||
| 274 | htons(sizeof(sctp_supported_ext_param_t) + num_ext); | ||
| 275 | sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), | ||
| 276 | &ext_param); | ||
| 277 | sctp_addto_chunk(retval, num_ext, extensions); | ||
| 278 | } | ||
| 279 | |||
| 244 | if (sctp_prsctp_enable) | 280 | if (sctp_prsctp_enable) |
| 245 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); | 281 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); |
| 282 | |||
| 246 | aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; | 283 | aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND; |
| 247 | aiparam.param_hdr.length = htons(sizeof(aiparam)); | 284 | aiparam.param_hdr.length = htons(sizeof(aiparam)); |
| 248 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); | 285 | aiparam.adaptation_ind = htonl(sp->adaptation_ind); |
| 249 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); | 286 | sctp_addto_chunk(retval, sizeof(aiparam), &aiparam); |
| 287 | |||
| 250 | nodata: | 288 | nodata: |
| 251 | kfree(addrs.v); | 289 | kfree(addrs.v); |
| 252 | return retval; | 290 | return retval; |
| @@ -264,6 +302,9 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
| 264 | int cookie_len; | 302 | int cookie_len; |
| 265 | size_t chunksize; | 303 | size_t chunksize; |
| 266 | sctp_adaptation_ind_param_t aiparam; | 304 | sctp_adaptation_ind_param_t aiparam; |
| 305 | sctp_supported_ext_param_t ext_param; | ||
| 306 | int num_ext = 0; | ||
| 307 | __u8 extensions[3]; | ||
| 267 | 308 | ||
| 268 | retval = NULL; | 309 | retval = NULL; |
| 269 | 310 | ||
| @@ -294,9 +335,19 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
| 294 | chunksize += sizeof(ecap_param); | 335 | chunksize += sizeof(ecap_param); |
| 295 | 336 | ||
| 296 | /* Tell peer that we'll do PR-SCTP only if peer advertised. */ | 337 | /* Tell peer that we'll do PR-SCTP only if peer advertised. */ |
| 297 | if (asoc->peer.prsctp_capable) | 338 | if (asoc->peer.prsctp_capable) { |
| 298 | chunksize += sizeof(prsctp_param); | 339 | chunksize += sizeof(prsctp_param); |
| 340 | extensions[num_ext] = SCTP_CID_FWD_TSN; | ||
| 341 | num_ext += 1; | ||
| 342 | } | ||
| 299 | 343 | ||
| 344 | if (sctp_addip_enable) { | ||
| 345 | extensions[num_ext] = SCTP_CID_ASCONF; | ||
| 346 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; | ||
| 347 | num_ext += 2; | ||
| 348 | } | ||
| 349 | |||
| 350 | chunksize += sizeof(ext_param) + num_ext; | ||
| 300 | chunksize += sizeof(aiparam); | 351 | chunksize += sizeof(aiparam); |
| 301 | 352 | ||
| 302 | /* Now allocate and fill out the chunk. */ | 353 | /* Now allocate and fill out the chunk. */ |
| @@ -314,6 +365,14 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
| 314 | sctp_addto_chunk(retval, cookie_len, cookie); | 365 | sctp_addto_chunk(retval, cookie_len, cookie); |
| 315 | if (asoc->peer.ecn_capable) | 366 | if (asoc->peer.ecn_capable) |
| 316 | sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param); | 367 | sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param); |
| 368 | if (num_ext) { | ||
| 369 | ext_param.param_hdr.type = SCTP_PARAM_SUPPORTED_EXT; | ||
| 370 | ext_param.param_hdr.length = | ||
| 371 | htons(sizeof(sctp_supported_ext_param_t) + num_ext); | ||
| 372 | sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), | ||
| 373 | &ext_param); | ||
| 374 | sctp_addto_chunk(retval, num_ext, extensions); | ||
| 375 | } | ||
| 317 | if (asoc->peer.prsctp_capable) | 376 | if (asoc->peer.prsctp_capable) |
| 318 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); | 377 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); |
| 319 | 378 | ||
| @@ -1664,6 +1723,28 @@ static int sctp_process_hn_param(const struct sctp_association *asoc, | |||
| 1664 | return 0; | 1723 | return 0; |
| 1665 | } | 1724 | } |
| 1666 | 1725 | ||
| 1726 | static void sctp_process_ext_param(struct sctp_association *asoc, | ||
| 1727 | union sctp_params param) | ||
| 1728 | { | ||
| 1729 | __u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); | ||
| 1730 | int i; | ||
| 1731 | |||
| 1732 | for (i = 0; i < num_ext; i++) { | ||
| 1733 | switch (param.ext->chunks[i]) { | ||
| 1734 | case SCTP_CID_FWD_TSN: | ||
| 1735 | if (sctp_prsctp_enable && | ||
| 1736 | !asoc->peer.prsctp_capable) | ||
| 1737 | asoc->peer.prsctp_capable = 1; | ||
| 1738 | break; | ||
| 1739 | case SCTP_CID_ASCONF: | ||
| 1740 | case SCTP_CID_ASCONF_ACK: | ||
| 1741 | /* don't need to do anything for ASCONF */ | ||
| 1742 | default: | ||
| 1743 | break; | ||
| 1744 | } | ||
| 1745 | } | ||
| 1746 | } | ||
| 1747 | |||
| 1667 | /* RFC 3.2.1 & the Implementers Guide 2.2. | 1748 | /* RFC 3.2.1 & the Implementers Guide 2.2. |
| 1668 | * | 1749 | * |
| 1669 | * The Parameter Types are encoded such that the | 1750 | * The Parameter Types are encoded such that the |
| @@ -1780,11 +1861,13 @@ static int sctp_verify_param(const struct sctp_association *asoc, | |||
| 1780 | case SCTP_PARAM_UNRECOGNIZED_PARAMETERS: | 1861 | case SCTP_PARAM_UNRECOGNIZED_PARAMETERS: |
| 1781 | case SCTP_PARAM_ECN_CAPABLE: | 1862 | case SCTP_PARAM_ECN_CAPABLE: |
| 1782 | case SCTP_PARAM_ADAPTATION_LAYER_IND: | 1863 | case SCTP_PARAM_ADAPTATION_LAYER_IND: |
| 1864 | case SCTP_PARAM_SUPPORTED_EXT: | ||
| 1783 | break; | 1865 | break; |
| 1784 | 1866 | ||
| 1785 | case SCTP_PARAM_HOST_NAME_ADDRESS: | 1867 | case SCTP_PARAM_HOST_NAME_ADDRESS: |
| 1786 | /* Tell the peer, we won't support this param. */ | 1868 | /* Tell the peer, we won't support this param. */ |
| 1787 | return sctp_process_hn_param(asoc, param, chunk, err_chunk); | 1869 | return sctp_process_hn_param(asoc, param, chunk, err_chunk); |
| 1870 | |||
| 1788 | case SCTP_PARAM_FWD_TSN_SUPPORT: | 1871 | case SCTP_PARAM_FWD_TSN_SUPPORT: |
| 1789 | if (sctp_prsctp_enable) | 1872 | if (sctp_prsctp_enable) |
| 1790 | break; | 1873 | break; |
| @@ -2129,6 +2212,10 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
| 2129 | asoc->peer.adaptation_ind = param.aind->adaptation_ind; | 2212 | asoc->peer.adaptation_ind = param.aind->adaptation_ind; |
| 2130 | break; | 2213 | break; |
| 2131 | 2214 | ||
| 2215 | case SCTP_PARAM_SUPPORTED_EXT: | ||
| 2216 | sctp_process_ext_param(asoc, param); | ||
| 2217 | break; | ||
| 2218 | |||
| 2132 | case SCTP_PARAM_FWD_TSN_SUPPORT: | 2219 | case SCTP_PARAM_FWD_TSN_SUPPORT: |
| 2133 | if (sctp_prsctp_enable) { | 2220 | if (sctp_prsctp_enable) { |
| 2134 | asoc->peer.prsctp_capable = 1; | 2221 | asoc->peer.prsctp_capable = 1; |
