aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-09-16 18:53:56 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:51:23 -0400
commit131a47e31ab1a9defd50ff16b04008ab94c21c0d (patch)
tree8ac3eb522333d1b6f9bd5741a8decbfb4220f432
parent76c72d4f44ec5fb7f88eda8a0d3aa30922c891d1 (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>
-rw-r--r--include/linux/sctp.h9
-rw-r--r--include/net/sctp/structs.h1
-rw-r--r--net/sctp/sm_make_chunk.c91
3 files changed, 99 insertions, 2 deletions
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index d70df61a029f..f4d717b72ddd 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -180,6 +180,9 @@ typedef enum {
180 SCTP_PARAM_SUPPORTED_ADDRESS_TYPES = __constant_htons(12), 180 SCTP_PARAM_SUPPORTED_ADDRESS_TYPES = __constant_htons(12),
181 SCTP_PARAM_ECN_CAPABLE = __constant_htons(0x8000), 181 SCTP_PARAM_ECN_CAPABLE = __constant_htons(0x8000),
182 182
183 /* Add-IP: Supported Extensions, Section 4.2 */
184 SCTP_PARAM_SUPPORTED_EXT = __constant_htons(0x8008),
185
183 /* PR-SCTP Sec 3.1 */ 186 /* PR-SCTP Sec 3.1 */
184 SCTP_PARAM_FWD_TSN_SUPPORT = __constant_htons(0xc000), 187 SCTP_PARAM_FWD_TSN_SUPPORT = __constant_htons(0xc000),
185 188
@@ -296,6 +299,12 @@ typedef struct sctp_adaptation_ind_param {
296 __be32 adaptation_ind; 299 __be32 adaptation_ind;
297} __attribute__((packed)) sctp_adaptation_ind_param_t; 300} __attribute__((packed)) sctp_adaptation_ind_param_t;
298 301
302/* ADDIP Section 4.2.7 Supported Extensions Parameter */
303typedef struct sctp_supported_ext_param {
304 struct sctp_paramhdr param_hdr;
305 __u8 chunks[0];
306} __attribute__((packed)) sctp_supported_ext_param_t;
307
299/* RFC 2960. Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2): 308/* RFC 2960. Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
300 * The INIT ACK chunk is used to acknowledge the initiation of an SCTP 309 * The INIT ACK chunk is used to acknowledge the initiation of an SCTP
301 * association. 310 * association.
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 67c91d01b635..b4812a2d3bb0 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -440,6 +440,7 @@ union sctp_params {
440 struct sctp_ipv6addr_param *v6; 440 struct sctp_ipv6addr_param *v6;
441 union sctp_addr_param *addr; 441 union sctp_addr_param *addr;
442 struct sctp_adaptation_ind_param *aind; 442 struct sctp_adaptation_ind_param *aind;
443 struct sctp_supported_ext_param *ext;
443}; 444};
444 445
445/* RFC 2960. Section 3.3.5 Heartbeat. 446/* RFC 2960. Section 3.3.5 Heartbeat.
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
250nodata: 288nodata:
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
1726static 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;