diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/Kconfig | 6 | ||||
-rw-r--r-- | net/sctp/auth.c | 4 | ||||
-rw-r--r-- | net/sctp/bind_addr.c | 26 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 25 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 2 | ||||
-rw-r--r-- | net/sctp/socket.c | 18 |
6 files changed, 50 insertions, 31 deletions
diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index 8210f549c492..5390bc792159 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig | |||
@@ -6,9 +6,9 @@ menuconfig IP_SCTP | |||
6 | tristate "The SCTP Protocol (EXPERIMENTAL)" | 6 | tristate "The SCTP Protocol (EXPERIMENTAL)" |
7 | depends on INET && EXPERIMENTAL | 7 | depends on INET && EXPERIMENTAL |
8 | depends on IPV6 || IPV6=n | 8 | depends on IPV6 || IPV6=n |
9 | select CRYPTO if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5 | 9 | select CRYPTO |
10 | select CRYPTO_HMAC if SCTP_HMAC_SHA1 || SCTP_HMAC_MD5 | 10 | select CRYPTO_HMAC |
11 | select CRYPTO_SHA1 if SCTP_HMAC_SHA1 | 11 | select CRYPTO_SHA1 |
12 | select CRYPTO_MD5 if SCTP_HMAC_MD5 | 12 | select CRYPTO_MD5 if SCTP_HMAC_MD5 |
13 | ---help--- | 13 | ---help--- |
14 | Stream Control Transmission Protocol | 14 | Stream Control Transmission Protocol |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 6d5fa6bb371b..97e6ebd14500 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -54,11 +54,13 @@ static struct sctp_hmac sctp_hmac_list[SCTP_AUTH_NUM_HMACS] = { | |||
54 | /* id 2 is reserved as well */ | 54 | /* id 2 is reserved as well */ |
55 | .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, | 55 | .hmac_id = SCTP_AUTH_HMAC_ID_RESERVED_2, |
56 | }, | 56 | }, |
57 | #if defined (CONFIG_CRYPTO_SHA256) || defined (CONFIG_CRYPTO_SHA256_MODULE) | ||
57 | { | 58 | { |
58 | .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, | 59 | .hmac_id = SCTP_AUTH_HMAC_ID_SHA256, |
59 | .hmac_name="hmac(sha256)", | 60 | .hmac_name="hmac(sha256)", |
60 | .hmac_len = SCTP_SHA256_SIG_SIZE, | 61 | .hmac_len = SCTP_SHA256_SIG_SIZE, |
61 | } | 62 | } |
63 | #endif | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | 66 | ||
@@ -631,7 +633,7 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) | |||
631 | int found = 0; | 633 | int found = 0; |
632 | int i; | 634 | int i; |
633 | 635 | ||
634 | if (!param) | 636 | if (!param || param->param_hdr.length == 0) |
635 | return 0; | 637 | return 0; |
636 | 638 | ||
637 | len = ntohs(param->param_hdr.length) - sizeof(sctp_paramhdr_t); | 639 | len = ntohs(param->param_hdr.length) - sizeof(sctp_paramhdr_t); |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index cae95af9a8cc..6a7d01091f0c 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -105,6 +105,32 @@ out: | |||
105 | return error; | 105 | return error; |
106 | } | 106 | } |
107 | 107 | ||
108 | /* Exactly duplicate the address lists. This is necessary when doing | ||
109 | * peer-offs and accepts. We don't want to put all the current system | ||
110 | * addresses into the endpoint. That's useless. But we do want duplicat | ||
111 | * the list of bound addresses that the older endpoint used. | ||
112 | */ | ||
113 | int sctp_bind_addr_dup(struct sctp_bind_addr *dest, | ||
114 | const struct sctp_bind_addr *src, | ||
115 | gfp_t gfp) | ||
116 | { | ||
117 | struct sctp_sockaddr_entry *addr; | ||
118 | struct list_head *pos; | ||
119 | int error = 0; | ||
120 | |||
121 | /* All addresses share the same port. */ | ||
122 | dest->port = src->port; | ||
123 | |||
124 | list_for_each(pos, &src->address_list) { | ||
125 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
126 | error = sctp_add_bind_addr(dest, &addr->a, 1, gfp); | ||
127 | if (error < 0) | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | return error; | ||
132 | } | ||
133 | |||
108 | /* Initialize the SCTP_bind_addr structure for either an endpoint or | 134 | /* Initialize the SCTP_bind_addr structure for either an endpoint or |
109 | * an association. | 135 | * an association. |
110 | */ | 136 | */ |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 5a9783c38de1..f4876291bb5e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -77,6 +77,8 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
77 | union sctp_params param, | 77 | union sctp_params param, |
78 | const union sctp_addr *peer_addr, | 78 | const union sctp_addr *peer_addr, |
79 | gfp_t gfp); | 79 | gfp_t gfp); |
80 | static void *sctp_addto_param(struct sctp_chunk *chunk, int len, | ||
81 | const void *data); | ||
80 | 82 | ||
81 | /* What was the inbound interface for this chunk? */ | 83 | /* What was the inbound interface for this chunk? */ |
82 | int sctp_chunk_iif(const struct sctp_chunk *chunk) | 84 | int sctp_chunk_iif(const struct sctp_chunk *chunk) |
@@ -207,11 +209,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
207 | 209 | ||
208 | chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); | 210 | chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types); |
209 | chunksize += sizeof(ecap_param); | 211 | chunksize += sizeof(ecap_param); |
210 | if (sctp_prsctp_enable) { | 212 | |
211 | chunksize += sizeof(prsctp_param); | ||
212 | extensions[num_ext] = SCTP_CID_FWD_TSN; | ||
213 | num_ext += 1; | ||
214 | } | ||
215 | /* ADDIP: Section 4.2.7: | 213 | /* ADDIP: Section 4.2.7: |
216 | * An implementation supporting this extension [ADDIP] MUST list | 214 | * An implementation supporting this extension [ADDIP] MUST list |
217 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and | 215 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and |
@@ -243,7 +241,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
243 | if (auth_chunks->length) | 241 | if (auth_chunks->length) |
244 | chunksize += ntohs(auth_chunks->length); | 242 | chunksize += ntohs(auth_chunks->length); |
245 | else | 243 | else |
246 | auth_hmacs = NULL; | 244 | auth_chunks = NULL; |
247 | 245 | ||
248 | extensions[num_ext] = SCTP_CID_AUTH; | 246 | extensions[num_ext] = SCTP_CID_AUTH; |
249 | num_ext += 1; | 247 | num_ext += 1; |
@@ -297,7 +295,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
297 | htons(sizeof(sctp_supported_ext_param_t) + num_ext); | 295 | htons(sizeof(sctp_supported_ext_param_t) + num_ext); |
298 | sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), | 296 | sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), |
299 | &ext_param); | 297 | &ext_param); |
300 | sctp_addto_chunk(retval, num_ext, extensions); | 298 | sctp_addto_param(retval, num_ext, extensions); |
301 | } | 299 | } |
302 | 300 | ||
303 | if (sctp_prsctp_enable) | 301 | if (sctp_prsctp_enable) |
@@ -371,20 +369,12 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
371 | if (asoc->peer.ecn_capable) | 369 | if (asoc->peer.ecn_capable) |
372 | chunksize += sizeof(ecap_param); | 370 | chunksize += sizeof(ecap_param); |
373 | 371 | ||
374 | /* Tell peer that we'll do PR-SCTP only if peer advertised. */ | ||
375 | if (asoc->peer.prsctp_capable) { | ||
376 | chunksize += sizeof(prsctp_param); | ||
377 | extensions[num_ext] = SCTP_CID_FWD_TSN; | ||
378 | num_ext += 1; | ||
379 | } | ||
380 | |||
381 | if (sctp_addip_enable) { | 372 | if (sctp_addip_enable) { |
382 | extensions[num_ext] = SCTP_CID_ASCONF; | 373 | extensions[num_ext] = SCTP_CID_ASCONF; |
383 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; | 374 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; |
384 | num_ext += 2; | 375 | num_ext += 2; |
385 | } | 376 | } |
386 | 377 | ||
387 | chunksize += sizeof(ext_param) + num_ext; | ||
388 | chunksize += sizeof(aiparam); | 378 | chunksize += sizeof(aiparam); |
389 | 379 | ||
390 | if (asoc->peer.auth_capable) { | 380 | if (asoc->peer.auth_capable) { |
@@ -407,6 +397,9 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
407 | num_ext += 1; | 397 | num_ext += 1; |
408 | } | 398 | } |
409 | 399 | ||
400 | if (num_ext) | ||
401 | chunksize += sizeof(sctp_supported_ext_param_t) + num_ext; | ||
402 | |||
410 | /* Now allocate and fill out the chunk. */ | 403 | /* Now allocate and fill out the chunk. */ |
411 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); | 404 | retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize); |
412 | if (!retval) | 405 | if (!retval) |
@@ -428,7 +421,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc, | |||
428 | htons(sizeof(sctp_supported_ext_param_t) + num_ext); | 421 | htons(sizeof(sctp_supported_ext_param_t) + num_ext); |
429 | sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), | 422 | sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t), |
430 | &ext_param); | 423 | &ext_param); |
431 | sctp_addto_chunk(retval, num_ext, extensions); | 424 | sctp_addto_param(retval, num_ext, extensions); |
432 | } | 425 | } |
433 | if (asoc->peer.prsctp_capable) | 426 | if (asoc->peer.prsctp_capable) |
434 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); | 427 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index b8bbb960723c..5fb84778846d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -959,7 +959,7 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | |||
959 | { | 959 | { |
960 | struct sctp_transport *transport = (struct sctp_transport *) arg; | 960 | struct sctp_transport *transport = (struct sctp_transport *) arg; |
961 | 961 | ||
962 | if (asoc->overall_error_count >= asoc->max_retrans) { | 962 | if (asoc->overall_error_count > asoc->max_retrans) { |
963 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | 963 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, |
964 | SCTP_ERROR(ETIMEDOUT)); | 964 | SCTP_ERROR(ETIMEDOUT)); |
965 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 965 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ff8bc95670ed..ea9649ca0b2a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -6325,7 +6325,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6325 | struct sctp_endpoint *newep = newsp->ep; | 6325 | struct sctp_endpoint *newep = newsp->ep; |
6326 | struct sk_buff *skb, *tmp; | 6326 | struct sk_buff *skb, *tmp; |
6327 | struct sctp_ulpevent *event; | 6327 | struct sctp_ulpevent *event; |
6328 | int flags = 0; | 6328 | struct sctp_bind_hashbucket *head; |
6329 | 6329 | ||
6330 | /* Migrate socket buffer sizes and all the socket level options to the | 6330 | /* Migrate socket buffer sizes and all the socket level options to the |
6331 | * new socket. | 6331 | * new socket. |
@@ -6342,23 +6342,21 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6342 | newsp->hmac = NULL; | 6342 | newsp->hmac = NULL; |
6343 | 6343 | ||
6344 | /* Hook this new socket in to the bind_hash list. */ | 6344 | /* Hook this new socket in to the bind_hash list. */ |
6345 | head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->num)]; | ||
6346 | sctp_local_bh_disable(); | ||
6347 | sctp_spin_lock(&head->lock); | ||
6345 | pp = sctp_sk(oldsk)->bind_hash; | 6348 | pp = sctp_sk(oldsk)->bind_hash; |
6346 | sk_add_bind_node(newsk, &pp->owner); | 6349 | sk_add_bind_node(newsk, &pp->owner); |
6347 | sctp_sk(newsk)->bind_hash = pp; | 6350 | sctp_sk(newsk)->bind_hash = pp; |
6348 | inet_sk(newsk)->num = inet_sk(oldsk)->num; | 6351 | inet_sk(newsk)->num = inet_sk(oldsk)->num; |
6352 | sctp_spin_unlock(&head->lock); | ||
6353 | sctp_local_bh_enable(); | ||
6349 | 6354 | ||
6350 | /* Copy the bind_addr list from the original endpoint to the new | 6355 | /* Copy the bind_addr list from the original endpoint to the new |
6351 | * endpoint so that we can handle restarts properly | 6356 | * endpoint so that we can handle restarts properly |
6352 | */ | 6357 | */ |
6353 | if (PF_INET6 == assoc->base.sk->sk_family) | 6358 | sctp_bind_addr_dup(&newsp->ep->base.bind_addr, |
6354 | flags = SCTP_ADDR6_ALLOWED; | 6359 | &oldsp->ep->base.bind_addr, GFP_KERNEL); |
6355 | if (assoc->peer.ipv4_address) | ||
6356 | flags |= SCTP_ADDR4_PEERSUPP; | ||
6357 | if (assoc->peer.ipv6_address) | ||
6358 | flags |= SCTP_ADDR6_PEERSUPP; | ||
6359 | sctp_bind_addr_copy(&newsp->ep->base.bind_addr, | ||
6360 | &oldsp->ep->base.bind_addr, | ||
6361 | SCTP_SCOPE_GLOBAL, GFP_KERNEL, flags); | ||
6362 | 6360 | ||
6363 | /* Move any messages in the old socket's receive queue that are for the | 6361 | /* Move any messages in the old socket's receive queue that are for the |
6364 | * peeled off association to the new socket's receive queue. | 6362 | * peeled off association to the new socket's receive queue. |