diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/associola.c | 82 | ||||
-rw-r--r-- | net/sctp/auth.c | 17 | ||||
-rw-r--r-- | net/sctp/endpointola.c | 3 | ||||
-rw-r--r-- | net/sctp/protocol.c | 9 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 32 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 7 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 8 | ||||
-rw-r--r-- | net/sctp/socket.c | 60 | ||||
-rw-r--r-- | net/sctp/sysctl.c | 36 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 8 |
10 files changed, 173 insertions, 89 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 4f6d6f9d1274..39579c3e0d14 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -1395,35 +1395,44 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc) | |||
1395 | return false; | 1395 | return false; |
1396 | } | 1396 | } |
1397 | 1397 | ||
1398 | /* Update asoc's rwnd for the approximated state in the buffer, | 1398 | /* Increase asoc's rwnd by len and send any window update SACK if needed. */ |
1399 | * and check whether SACK needs to be sent. | 1399 | void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) |
1400 | */ | ||
1401 | void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) | ||
1402 | { | 1400 | { |
1403 | int rx_count; | ||
1404 | struct sctp_chunk *sack; | 1401 | struct sctp_chunk *sack; |
1405 | struct timer_list *timer; | 1402 | struct timer_list *timer; |
1406 | 1403 | ||
1407 | if (asoc->ep->rcvbuf_policy) | 1404 | if (asoc->rwnd_over) { |
1408 | rx_count = atomic_read(&asoc->rmem_alloc); | 1405 | if (asoc->rwnd_over >= len) { |
1409 | else | 1406 | asoc->rwnd_over -= len; |
1410 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); | 1407 | } else { |
1408 | asoc->rwnd += (len - asoc->rwnd_over); | ||
1409 | asoc->rwnd_over = 0; | ||
1410 | } | ||
1411 | } else { | ||
1412 | asoc->rwnd += len; | ||
1413 | } | ||
1411 | 1414 | ||
1412 | if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) | 1415 | /* If we had window pressure, start recovering it |
1413 | asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; | 1416 | * once our rwnd had reached the accumulated pressure |
1414 | else | 1417 | * threshold. The idea is to recover slowly, but up |
1415 | asoc->rwnd = 0; | 1418 | * to the initial advertised window. |
1419 | */ | ||
1420 | if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { | ||
1421 | int change = min(asoc->pathmtu, asoc->rwnd_press); | ||
1422 | asoc->rwnd += change; | ||
1423 | asoc->rwnd_press -= change; | ||
1424 | } | ||
1416 | 1425 | ||
1417 | pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n", | 1426 | pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", |
1418 | __func__, asoc, asoc->rwnd, rx_count, | 1427 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, |
1419 | asoc->base.sk->sk_rcvbuf); | 1428 | asoc->a_rwnd); |
1420 | 1429 | ||
1421 | /* Send a window update SACK if the rwnd has increased by at least the | 1430 | /* Send a window update SACK if the rwnd has increased by at least the |
1422 | * minimum of the association's PMTU and half of the receive buffer. | 1431 | * minimum of the association's PMTU and half of the receive buffer. |
1423 | * The algorithm used is similar to the one described in | 1432 | * The algorithm used is similar to the one described in |
1424 | * Section 4.2.3.3 of RFC 1122. | 1433 | * Section 4.2.3.3 of RFC 1122. |
1425 | */ | 1434 | */ |
1426 | if (update_peer && sctp_peer_needs_update(asoc)) { | 1435 | if (sctp_peer_needs_update(asoc)) { |
1427 | asoc->a_rwnd = asoc->rwnd; | 1436 | asoc->a_rwnd = asoc->rwnd; |
1428 | 1437 | ||
1429 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " | 1438 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " |
@@ -1445,6 +1454,45 @@ void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) | |||
1445 | } | 1454 | } |
1446 | } | 1455 | } |
1447 | 1456 | ||
1457 | /* Decrease asoc's rwnd by len. */ | ||
1458 | void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) | ||
1459 | { | ||
1460 | int rx_count; | ||
1461 | int over = 0; | ||
1462 | |||
1463 | if (unlikely(!asoc->rwnd || asoc->rwnd_over)) | ||
1464 | pr_debug("%s: association:%p has asoc->rwnd:%u, " | ||
1465 | "asoc->rwnd_over:%u!\n", __func__, asoc, | ||
1466 | asoc->rwnd, asoc->rwnd_over); | ||
1467 | |||
1468 | if (asoc->ep->rcvbuf_policy) | ||
1469 | rx_count = atomic_read(&asoc->rmem_alloc); | ||
1470 | else | ||
1471 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); | ||
1472 | |||
1473 | /* If we've reached or overflowed our receive buffer, announce | ||
1474 | * a 0 rwnd if rwnd would still be positive. Store the | ||
1475 | * the potential pressure overflow so that the window can be restored | ||
1476 | * back to original value. | ||
1477 | */ | ||
1478 | if (rx_count >= asoc->base.sk->sk_rcvbuf) | ||
1479 | over = 1; | ||
1480 | |||
1481 | if (asoc->rwnd >= len) { | ||
1482 | asoc->rwnd -= len; | ||
1483 | if (over) { | ||
1484 | asoc->rwnd_press += asoc->rwnd; | ||
1485 | asoc->rwnd = 0; | ||
1486 | } | ||
1487 | } else { | ||
1488 | asoc->rwnd_over = len - asoc->rwnd; | ||
1489 | asoc->rwnd = 0; | ||
1490 | } | ||
1491 | |||
1492 | pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", | ||
1493 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, | ||
1494 | asoc->rwnd_press); | ||
1495 | } | ||
1448 | 1496 | ||
1449 | /* Build the bind address list for the association based on info from the | 1497 | /* Build the bind address list for the association based on info from the |
1450 | * local endpoint and the remote peer. | 1498 | * local endpoint and the remote peer. |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 683c7d1b1306..0e8529113dc5 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -386,14 +386,13 @@ nomem: | |||
386 | */ | 386 | */ |
387 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) | 387 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) |
388 | { | 388 | { |
389 | struct net *net = sock_net(asoc->base.sk); | ||
390 | struct sctp_auth_bytes *secret; | 389 | struct sctp_auth_bytes *secret; |
391 | struct sctp_shared_key *ep_key; | 390 | struct sctp_shared_key *ep_key; |
392 | 391 | ||
393 | /* If we don't support AUTH, or peer is not capable | 392 | /* If we don't support AUTH, or peer is not capable |
394 | * we don't need to do anything. | 393 | * we don't need to do anything. |
395 | */ | 394 | */ |
396 | if (!net->sctp.auth_enable || !asoc->peer.auth_capable) | 395 | if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) |
397 | return 0; | 396 | return 0; |
398 | 397 | ||
399 | /* If the key_id is non-zero and we couldn't find an | 398 | /* If the key_id is non-zero and we couldn't find an |
@@ -440,16 +439,16 @@ struct sctp_shared_key *sctp_auth_get_shkey( | |||
440 | */ | 439 | */ |
441 | int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) | 440 | int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) |
442 | { | 441 | { |
443 | struct net *net = sock_net(ep->base.sk); | ||
444 | struct crypto_hash *tfm = NULL; | 442 | struct crypto_hash *tfm = NULL; |
445 | __u16 id; | 443 | __u16 id; |
446 | 444 | ||
447 | /* if the transforms are already allocted, we are done */ | 445 | /* If AUTH extension is disabled, we are done */ |
448 | if (!net->sctp.auth_enable) { | 446 | if (!ep->auth_enable) { |
449 | ep->auth_hmacs = NULL; | 447 | ep->auth_hmacs = NULL; |
450 | return 0; | 448 | return 0; |
451 | } | 449 | } |
452 | 450 | ||
451 | /* If the transforms are already allocated, we are done */ | ||
453 | if (ep->auth_hmacs) | 452 | if (ep->auth_hmacs) |
454 | return 0; | 453 | return 0; |
455 | 454 | ||
@@ -665,12 +664,10 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) | |||
665 | /* Check if peer requested that this chunk is authenticated */ | 664 | /* Check if peer requested that this chunk is authenticated */ |
666 | int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | 665 | int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) |
667 | { | 666 | { |
668 | struct net *net; | ||
669 | if (!asoc) | 667 | if (!asoc) |
670 | return 0; | 668 | return 0; |
671 | 669 | ||
672 | net = sock_net(asoc->base.sk); | 670 | if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) |
673 | if (!net->sctp.auth_enable || !asoc->peer.auth_capable) | ||
674 | return 0; | 671 | return 0; |
675 | 672 | ||
676 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); | 673 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); |
@@ -679,12 +676,10 @@ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | |||
679 | /* Check if we requested that peer authenticate this chunk. */ | 676 | /* Check if we requested that peer authenticate this chunk. */ |
680 | int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | 677 | int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) |
681 | { | 678 | { |
682 | struct net *net; | ||
683 | if (!asoc) | 679 | if (!asoc) |
684 | return 0; | 680 | return 0; |
685 | 681 | ||
686 | net = sock_net(asoc->base.sk); | 682 | if (!asoc->ep->auth_enable) |
687 | if (!net->sctp.auth_enable) | ||
688 | return 0; | 683 | return 0; |
689 | 684 | ||
690 | return __sctp_auth_cid(chunk, | 685 | return __sctp_auth_cid(chunk, |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 8e5fdea05216..3d9f429858dc 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -68,7 +68,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
68 | if (!ep->digest) | 68 | if (!ep->digest) |
69 | return NULL; | 69 | return NULL; |
70 | 70 | ||
71 | if (net->sctp.auth_enable) { | 71 | ep->auth_enable = net->sctp.auth_enable; |
72 | if (ep->auth_enable) { | ||
72 | /* Allocate space for HMACS and CHUNKS authentication | 73 | /* Allocate space for HMACS and CHUNKS authentication |
73 | * variables. There are arrays that we encode directly | 74 | * variables. There are arrays that we encode directly |
74 | * into parameters to make the rest of the operations easier. | 75 | * into parameters to make the rest of the operations easier. |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 4e1d0fcb028e..44cbb54c8574 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -491,8 +491,13 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
491 | continue; | 491 | continue; |
492 | if ((laddr->state == SCTP_ADDR_SRC) && | 492 | if ((laddr->state == SCTP_ADDR_SRC) && |
493 | (AF_INET == laddr->a.sa.sa_family)) { | 493 | (AF_INET == laddr->a.sa.sa_family)) { |
494 | fl4->saddr = laddr->a.v4.sin_addr.s_addr; | ||
495 | fl4->fl4_sport = laddr->a.v4.sin_port; | 494 | fl4->fl4_sport = laddr->a.v4.sin_port; |
495 | flowi4_update_output(fl4, | ||
496 | asoc->base.sk->sk_bound_dev_if, | ||
497 | RT_CONN_FLAGS(asoc->base.sk), | ||
498 | daddr->v4.sin_addr.s_addr, | ||
499 | laddr->a.v4.sin_addr.s_addr); | ||
500 | |||
496 | rt = ip_route_output_key(sock_net(sk), fl4); | 501 | rt = ip_route_output_key(sock_net(sk), fl4); |
497 | if (!IS_ERR(rt)) { | 502 | if (!IS_ERR(rt)) { |
498 | dst = &rt->dst; | 503 | dst = &rt->dst; |
@@ -957,7 +962,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
957 | 962 | ||
958 | SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); | 963 | SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); |
959 | 964 | ||
960 | return ip_queue_xmit(skb, &transport->fl); | 965 | return ip_queue_xmit(&inet->sk, skb, &transport->fl); |
961 | } | 966 | } |
962 | 967 | ||
963 | static struct sctp_af sctp_af_inet; | 968 | static struct sctp_af sctp_af_inet; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 3a1767ef3201..fee5552ddf92 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -219,6 +219,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
219 | gfp_t gfp, int vparam_len) | 219 | gfp_t gfp, int vparam_len) |
220 | { | 220 | { |
221 | struct net *net = sock_net(asoc->base.sk); | 221 | struct net *net = sock_net(asoc->base.sk); |
222 | struct sctp_endpoint *ep = asoc->ep; | ||
222 | sctp_inithdr_t init; | 223 | sctp_inithdr_t init; |
223 | union sctp_params addrs; | 224 | union sctp_params addrs; |
224 | size_t chunksize; | 225 | size_t chunksize; |
@@ -278,7 +279,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
278 | chunksize += vparam_len; | 279 | chunksize += vparam_len; |
279 | 280 | ||
280 | /* Account for AUTH related parameters */ | 281 | /* Account for AUTH related parameters */ |
281 | if (net->sctp.auth_enable) { | 282 | if (ep->auth_enable) { |
282 | /* Add random parameter length*/ | 283 | /* Add random parameter length*/ |
283 | chunksize += sizeof(asoc->c.auth_random); | 284 | chunksize += sizeof(asoc->c.auth_random); |
284 | 285 | ||
@@ -363,7 +364,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
363 | } | 364 | } |
364 | 365 | ||
365 | /* Add SCTP-AUTH chunks to the parameter list */ | 366 | /* Add SCTP-AUTH chunks to the parameter list */ |
366 | if (net->sctp.auth_enable) { | 367 | if (ep->auth_enable) { |
367 | sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), | 368 | sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), |
368 | asoc->c.auth_random); | 369 | asoc->c.auth_random); |
369 | if (auth_hmacs) | 370 | if (auth_hmacs) |
@@ -2010,7 +2011,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
2010 | /* if the peer reports AUTH, assume that he | 2011 | /* if the peer reports AUTH, assume that he |
2011 | * supports AUTH. | 2012 | * supports AUTH. |
2012 | */ | 2013 | */ |
2013 | if (net->sctp.auth_enable) | 2014 | if (asoc->ep->auth_enable) |
2014 | asoc->peer.auth_capable = 1; | 2015 | asoc->peer.auth_capable = 1; |
2015 | break; | 2016 | break; |
2016 | case SCTP_CID_ASCONF: | 2017 | case SCTP_CID_ASCONF: |
@@ -2102,6 +2103,7 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, | |||
2102 | * SCTP_IERROR_NO_ERROR - continue with the chunk | 2103 | * SCTP_IERROR_NO_ERROR - continue with the chunk |
2103 | */ | 2104 | */ |
2104 | static sctp_ierror_t sctp_verify_param(struct net *net, | 2105 | static sctp_ierror_t sctp_verify_param(struct net *net, |
2106 | const struct sctp_endpoint *ep, | ||
2105 | const struct sctp_association *asoc, | 2107 | const struct sctp_association *asoc, |
2106 | union sctp_params param, | 2108 | union sctp_params param, |
2107 | sctp_cid_t cid, | 2109 | sctp_cid_t cid, |
@@ -2152,7 +2154,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, | |||
2152 | goto fallthrough; | 2154 | goto fallthrough; |
2153 | 2155 | ||
2154 | case SCTP_PARAM_RANDOM: | 2156 | case SCTP_PARAM_RANDOM: |
2155 | if (!net->sctp.auth_enable) | 2157 | if (!ep->auth_enable) |
2156 | goto fallthrough; | 2158 | goto fallthrough; |
2157 | 2159 | ||
2158 | /* SCTP-AUTH: Secion 6.1 | 2160 | /* SCTP-AUTH: Secion 6.1 |
@@ -2169,7 +2171,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, | |||
2169 | break; | 2171 | break; |
2170 | 2172 | ||
2171 | case SCTP_PARAM_CHUNKS: | 2173 | case SCTP_PARAM_CHUNKS: |
2172 | if (!net->sctp.auth_enable) | 2174 | if (!ep->auth_enable) |
2173 | goto fallthrough; | 2175 | goto fallthrough; |
2174 | 2176 | ||
2175 | /* SCTP-AUTH: Section 3.2 | 2177 | /* SCTP-AUTH: Section 3.2 |
@@ -2185,7 +2187,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, | |||
2185 | break; | 2187 | break; |
2186 | 2188 | ||
2187 | case SCTP_PARAM_HMAC_ALGO: | 2189 | case SCTP_PARAM_HMAC_ALGO: |
2188 | if (!net->sctp.auth_enable) | 2190 | if (!ep->auth_enable) |
2189 | goto fallthrough; | 2191 | goto fallthrough; |
2190 | 2192 | ||
2191 | hmacs = (struct sctp_hmac_algo_param *)param.p; | 2193 | hmacs = (struct sctp_hmac_algo_param *)param.p; |
@@ -2220,10 +2222,9 @@ fallthrough: | |||
2220 | } | 2222 | } |
2221 | 2223 | ||
2222 | /* Verify the INIT packet before we process it. */ | 2224 | /* Verify the INIT packet before we process it. */ |
2223 | int sctp_verify_init(struct net *net, const struct sctp_association *asoc, | 2225 | int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep, |
2224 | sctp_cid_t cid, | 2226 | const struct sctp_association *asoc, sctp_cid_t cid, |
2225 | sctp_init_chunk_t *peer_init, | 2227 | sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk, |
2226 | struct sctp_chunk *chunk, | ||
2227 | struct sctp_chunk **errp) | 2228 | struct sctp_chunk **errp) |
2228 | { | 2229 | { |
2229 | union sctp_params param; | 2230 | union sctp_params param; |
@@ -2264,8 +2265,8 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc, | |||
2264 | 2265 | ||
2265 | /* Verify all the variable length parameters */ | 2266 | /* Verify all the variable length parameters */ |
2266 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2267 | sctp_walk_params(param, peer_init, init_hdr.params) { |
2267 | 2268 | result = sctp_verify_param(net, ep, asoc, param, cid, | |
2268 | result = sctp_verify_param(net, asoc, param, cid, chunk, errp); | 2269 | chunk, errp); |
2269 | switch (result) { | 2270 | switch (result) { |
2270 | case SCTP_IERROR_ABORT: | 2271 | case SCTP_IERROR_ABORT: |
2271 | case SCTP_IERROR_NOMEM: | 2272 | case SCTP_IERROR_NOMEM: |
@@ -2497,6 +2498,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
2497 | struct sctp_af *af; | 2498 | struct sctp_af *af; |
2498 | union sctp_addr_param *addr_param; | 2499 | union sctp_addr_param *addr_param; |
2499 | struct sctp_transport *t; | 2500 | struct sctp_transport *t; |
2501 | struct sctp_endpoint *ep = asoc->ep; | ||
2500 | 2502 | ||
2501 | /* We maintain all INIT parameters in network byte order all the | 2503 | /* We maintain all INIT parameters in network byte order all the |
2502 | * time. This allows us to not worry about whether the parameters | 2504 | * time. This allows us to not worry about whether the parameters |
@@ -2636,7 +2638,7 @@ do_addr_param: | |||
2636 | goto fall_through; | 2638 | goto fall_through; |
2637 | 2639 | ||
2638 | case SCTP_PARAM_RANDOM: | 2640 | case SCTP_PARAM_RANDOM: |
2639 | if (!net->sctp.auth_enable) | 2641 | if (!ep->auth_enable) |
2640 | goto fall_through; | 2642 | goto fall_through; |
2641 | 2643 | ||
2642 | /* Save peer's random parameter */ | 2644 | /* Save peer's random parameter */ |
@@ -2649,7 +2651,7 @@ do_addr_param: | |||
2649 | break; | 2651 | break; |
2650 | 2652 | ||
2651 | case SCTP_PARAM_HMAC_ALGO: | 2653 | case SCTP_PARAM_HMAC_ALGO: |
2652 | if (!net->sctp.auth_enable) | 2654 | if (!ep->auth_enable) |
2653 | goto fall_through; | 2655 | goto fall_through; |
2654 | 2656 | ||
2655 | /* Save peer's HMAC list */ | 2657 | /* Save peer's HMAC list */ |
@@ -2665,7 +2667,7 @@ do_addr_param: | |||
2665 | break; | 2667 | break; |
2666 | 2668 | ||
2667 | case SCTP_PARAM_CHUNKS: | 2669 | case SCTP_PARAM_CHUNKS: |
2668 | if (!net->sctp.auth_enable) | 2670 | if (!ep->auth_enable) |
2669 | goto fall_through; | 2671 | goto fall_through; |
2670 | 2672 | ||
2671 | asoc->peer.peer_chunks = kmemdup(param.p, | 2673 | asoc->peer.peer_chunks = kmemdup(param.p, |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 5d6883ff00c3..fef2acdf4a2e 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -496,11 +496,10 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands, | |||
496 | 496 | ||
497 | /* If the transport error count is greater than the pf_retrans | 497 | /* If the transport error count is greater than the pf_retrans |
498 | * threshold, and less than pathmaxrtx, and if the current state | 498 | * threshold, and less than pathmaxrtx, and if the current state |
499 | * is not SCTP_UNCONFIRMED, then mark this transport as Partially | 499 | * is SCTP_ACTIVE, then mark this transport as Partially Failed, |
500 | * Failed, see SCTP Quick Failover Draft, section 5.1 | 500 | * see SCTP Quick Failover Draft, section 5.1 |
501 | */ | 501 | */ |
502 | if ((transport->state != SCTP_PF) && | 502 | if ((transport->state == SCTP_ACTIVE) && |
503 | (transport->state != SCTP_UNCONFIRMED) && | ||
504 | (asoc->pf_retrans < transport->pathmaxrxt) && | 503 | (asoc->pf_retrans < transport->pathmaxrxt) && |
505 | (transport->error_count > asoc->pf_retrans)) { | 504 | (transport->error_count > asoc->pf_retrans)) { |
506 | 505 | ||
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 01e002430c85..5170a1ff95a1 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -357,7 +357,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net, | |||
357 | 357 | ||
358 | /* Verify the INIT chunk before processing it. */ | 358 | /* Verify the INIT chunk before processing it. */ |
359 | err_chunk = NULL; | 359 | err_chunk = NULL; |
360 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, | 360 | if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, |
361 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 361 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
362 | &err_chunk)) { | 362 | &err_chunk)) { |
363 | /* This chunk contains fatal error. It is to be discarded. | 363 | /* This chunk contains fatal error. It is to be discarded. |
@@ -524,7 +524,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, | |||
524 | 524 | ||
525 | /* Verify the INIT chunk before processing it. */ | 525 | /* Verify the INIT chunk before processing it. */ |
526 | err_chunk = NULL; | 526 | err_chunk = NULL; |
527 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, | 527 | if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, |
528 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 528 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
529 | &err_chunk)) { | 529 | &err_chunk)) { |
530 | 530 | ||
@@ -1430,7 +1430,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1430 | 1430 | ||
1431 | /* Verify the INIT chunk before processing it. */ | 1431 | /* Verify the INIT chunk before processing it. */ |
1432 | err_chunk = NULL; | 1432 | err_chunk = NULL; |
1433 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, | 1433 | if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, |
1434 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 1434 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
1435 | &err_chunk)) { | 1435 | &err_chunk)) { |
1436 | /* This chunk contains fatal error. It is to be discarded. | 1436 | /* This chunk contains fatal error. It is to be discarded. |
@@ -6178,7 +6178,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
6178 | * PMTU. In cases, such as loopback, this might be a rather | 6178 | * PMTU. In cases, such as loopback, this might be a rather |
6179 | * large spill over. | 6179 | * large spill over. |
6180 | */ | 6180 | */ |
6181 | if ((!chunk->data_accepted) && (!asoc->rwnd || | 6181 | if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || |
6182 | (datalen > asoc->rwnd + asoc->frag_point))) { | 6182 | (datalen > asoc->rwnd + asoc->frag_point))) { |
6183 | 6183 | ||
6184 | /* If this is the next TSN, consider reneging to make | 6184 | /* If this is the next TSN, consider reneging to make |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e13519e9df80..fee06b99a4da 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2115,6 +2115,12 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
2115 | sctp_skb_pull(skb, copied); | 2115 | sctp_skb_pull(skb, copied); |
2116 | skb_queue_head(&sk->sk_receive_queue, skb); | 2116 | skb_queue_head(&sk->sk_receive_queue, skb); |
2117 | 2117 | ||
2118 | /* When only partial message is copied to the user, increase | ||
2119 | * rwnd by that amount. If all the data in the skb is read, | ||
2120 | * rwnd is updated when the event is freed. | ||
2121 | */ | ||
2122 | if (!sctp_ulpevent_is_notification(event)) | ||
2123 | sctp_assoc_rwnd_increase(event->asoc, copied); | ||
2118 | goto out; | 2124 | goto out; |
2119 | } else if ((event->msg_flags & MSG_NOTIFICATION) || | 2125 | } else if ((event->msg_flags & MSG_NOTIFICATION) || |
2120 | (event->msg_flags & MSG_EOR)) | 2126 | (event->msg_flags & MSG_EOR)) |
@@ -3315,10 +3321,10 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, | |||
3315 | char __user *optval, | 3321 | char __user *optval, |
3316 | unsigned int optlen) | 3322 | unsigned int optlen) |
3317 | { | 3323 | { |
3318 | struct net *net = sock_net(sk); | 3324 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
3319 | struct sctp_authchunk val; | 3325 | struct sctp_authchunk val; |
3320 | 3326 | ||
3321 | if (!net->sctp.auth_enable) | 3327 | if (!ep->auth_enable) |
3322 | return -EACCES; | 3328 | return -EACCES; |
3323 | 3329 | ||
3324 | if (optlen != sizeof(struct sctp_authchunk)) | 3330 | if (optlen != sizeof(struct sctp_authchunk)) |
@@ -3335,7 +3341,7 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, | |||
3335 | } | 3341 | } |
3336 | 3342 | ||
3337 | /* add this chunk id to the endpoint */ | 3343 | /* add this chunk id to the endpoint */ |
3338 | return sctp_auth_ep_add_chunkid(sctp_sk(sk)->ep, val.sauth_chunk); | 3344 | return sctp_auth_ep_add_chunkid(ep, val.sauth_chunk); |
3339 | } | 3345 | } |
3340 | 3346 | ||
3341 | /* | 3347 | /* |
@@ -3348,12 +3354,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
3348 | char __user *optval, | 3354 | char __user *optval, |
3349 | unsigned int optlen) | 3355 | unsigned int optlen) |
3350 | { | 3356 | { |
3351 | struct net *net = sock_net(sk); | 3357 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
3352 | struct sctp_hmacalgo *hmacs; | 3358 | struct sctp_hmacalgo *hmacs; |
3353 | u32 idents; | 3359 | u32 idents; |
3354 | int err; | 3360 | int err; |
3355 | 3361 | ||
3356 | if (!net->sctp.auth_enable) | 3362 | if (!ep->auth_enable) |
3357 | return -EACCES; | 3363 | return -EACCES; |
3358 | 3364 | ||
3359 | if (optlen < sizeof(struct sctp_hmacalgo)) | 3365 | if (optlen < sizeof(struct sctp_hmacalgo)) |
@@ -3370,7 +3376,7 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
3370 | goto out; | 3376 | goto out; |
3371 | } | 3377 | } |
3372 | 3378 | ||
3373 | err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs); | 3379 | err = sctp_auth_ep_set_hmacs(ep, hmacs); |
3374 | out: | 3380 | out: |
3375 | kfree(hmacs); | 3381 | kfree(hmacs); |
3376 | return err; | 3382 | return err; |
@@ -3386,12 +3392,12 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
3386 | char __user *optval, | 3392 | char __user *optval, |
3387 | unsigned int optlen) | 3393 | unsigned int optlen) |
3388 | { | 3394 | { |
3389 | struct net *net = sock_net(sk); | 3395 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
3390 | struct sctp_authkey *authkey; | 3396 | struct sctp_authkey *authkey; |
3391 | struct sctp_association *asoc; | 3397 | struct sctp_association *asoc; |
3392 | int ret; | 3398 | int ret; |
3393 | 3399 | ||
3394 | if (!net->sctp.auth_enable) | 3400 | if (!ep->auth_enable) |
3395 | return -EACCES; | 3401 | return -EACCES; |
3396 | 3402 | ||
3397 | if (optlen <= sizeof(struct sctp_authkey)) | 3403 | if (optlen <= sizeof(struct sctp_authkey)) |
@@ -3412,7 +3418,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
3412 | goto out; | 3418 | goto out; |
3413 | } | 3419 | } |
3414 | 3420 | ||
3415 | ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); | 3421 | ret = sctp_auth_set_key(ep, asoc, authkey); |
3416 | out: | 3422 | out: |
3417 | kzfree(authkey); | 3423 | kzfree(authkey); |
3418 | return ret; | 3424 | return ret; |
@@ -3428,11 +3434,11 @@ static int sctp_setsockopt_active_key(struct sock *sk, | |||
3428 | char __user *optval, | 3434 | char __user *optval, |
3429 | unsigned int optlen) | 3435 | unsigned int optlen) |
3430 | { | 3436 | { |
3431 | struct net *net = sock_net(sk); | 3437 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
3432 | struct sctp_authkeyid val; | 3438 | struct sctp_authkeyid val; |
3433 | struct sctp_association *asoc; | 3439 | struct sctp_association *asoc; |
3434 | 3440 | ||
3435 | if (!net->sctp.auth_enable) | 3441 | if (!ep->auth_enable) |
3436 | return -EACCES; | 3442 | return -EACCES; |
3437 | 3443 | ||
3438 | if (optlen != sizeof(struct sctp_authkeyid)) | 3444 | if (optlen != sizeof(struct sctp_authkeyid)) |
@@ -3444,8 +3450,7 @@ static int sctp_setsockopt_active_key(struct sock *sk, | |||
3444 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | 3450 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
3445 | return -EINVAL; | 3451 | return -EINVAL; |
3446 | 3452 | ||
3447 | return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc, | 3453 | return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); |
3448 | val.scact_keynumber); | ||
3449 | } | 3454 | } |
3450 | 3455 | ||
3451 | /* | 3456 | /* |
@@ -3457,11 +3462,11 @@ static int sctp_setsockopt_del_key(struct sock *sk, | |||
3457 | char __user *optval, | 3462 | char __user *optval, |
3458 | unsigned int optlen) | 3463 | unsigned int optlen) |
3459 | { | 3464 | { |
3460 | struct net *net = sock_net(sk); | 3465 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
3461 | struct sctp_authkeyid val; | 3466 | struct sctp_authkeyid val; |
3462 | struct sctp_association *asoc; | 3467 | struct sctp_association *asoc; |
3463 | 3468 | ||
3464 | if (!net->sctp.auth_enable) | 3469 | if (!ep->auth_enable) |
3465 | return -EACCES; | 3470 | return -EACCES; |
3466 | 3471 | ||
3467 | if (optlen != sizeof(struct sctp_authkeyid)) | 3472 | if (optlen != sizeof(struct sctp_authkeyid)) |
@@ -3473,8 +3478,7 @@ static int sctp_setsockopt_del_key(struct sock *sk, | |||
3473 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) | 3478 | if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) |
3474 | return -EINVAL; | 3479 | return -EINVAL; |
3475 | 3480 | ||
3476 | return sctp_auth_del_key_id(sctp_sk(sk)->ep, asoc, | 3481 | return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); |
3477 | val.scact_keynumber); | ||
3478 | 3482 | ||
3479 | } | 3483 | } |
3480 | 3484 | ||
@@ -5381,16 +5385,16 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, | |||
5381 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | 5385 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, |
5382 | char __user *optval, int __user *optlen) | 5386 | char __user *optval, int __user *optlen) |
5383 | { | 5387 | { |
5384 | struct net *net = sock_net(sk); | 5388 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5385 | struct sctp_hmacalgo __user *p = (void __user *)optval; | 5389 | struct sctp_hmacalgo __user *p = (void __user *)optval; |
5386 | struct sctp_hmac_algo_param *hmacs; | 5390 | struct sctp_hmac_algo_param *hmacs; |
5387 | __u16 data_len = 0; | 5391 | __u16 data_len = 0; |
5388 | u32 num_idents; | 5392 | u32 num_idents; |
5389 | 5393 | ||
5390 | if (!net->sctp.auth_enable) | 5394 | if (!ep->auth_enable) |
5391 | return -EACCES; | 5395 | return -EACCES; |
5392 | 5396 | ||
5393 | hmacs = sctp_sk(sk)->ep->auth_hmacs_list; | 5397 | hmacs = ep->auth_hmacs_list; |
5394 | data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); | 5398 | data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); |
5395 | 5399 | ||
5396 | if (len < sizeof(struct sctp_hmacalgo) + data_len) | 5400 | if (len < sizeof(struct sctp_hmacalgo) + data_len) |
@@ -5411,11 +5415,11 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | |||
5411 | static int sctp_getsockopt_active_key(struct sock *sk, int len, | 5415 | static int sctp_getsockopt_active_key(struct sock *sk, int len, |
5412 | char __user *optval, int __user *optlen) | 5416 | char __user *optval, int __user *optlen) |
5413 | { | 5417 | { |
5414 | struct net *net = sock_net(sk); | 5418 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5415 | struct sctp_authkeyid val; | 5419 | struct sctp_authkeyid val; |
5416 | struct sctp_association *asoc; | 5420 | struct sctp_association *asoc; |
5417 | 5421 | ||
5418 | if (!net->sctp.auth_enable) | 5422 | if (!ep->auth_enable) |
5419 | return -EACCES; | 5423 | return -EACCES; |
5420 | 5424 | ||
5421 | if (len < sizeof(struct sctp_authkeyid)) | 5425 | if (len < sizeof(struct sctp_authkeyid)) |
@@ -5430,7 +5434,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
5430 | if (asoc) | 5434 | if (asoc) |
5431 | val.scact_keynumber = asoc->active_key_id; | 5435 | val.scact_keynumber = asoc->active_key_id; |
5432 | else | 5436 | else |
5433 | val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; | 5437 | val.scact_keynumber = ep->active_key_id; |
5434 | 5438 | ||
5435 | len = sizeof(struct sctp_authkeyid); | 5439 | len = sizeof(struct sctp_authkeyid); |
5436 | if (put_user(len, optlen)) | 5440 | if (put_user(len, optlen)) |
@@ -5444,7 +5448,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
5444 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | 5448 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, |
5445 | char __user *optval, int __user *optlen) | 5449 | char __user *optval, int __user *optlen) |
5446 | { | 5450 | { |
5447 | struct net *net = sock_net(sk); | 5451 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5448 | struct sctp_authchunks __user *p = (void __user *)optval; | 5452 | struct sctp_authchunks __user *p = (void __user *)optval; |
5449 | struct sctp_authchunks val; | 5453 | struct sctp_authchunks val; |
5450 | struct sctp_association *asoc; | 5454 | struct sctp_association *asoc; |
@@ -5452,7 +5456,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | |||
5452 | u32 num_chunks = 0; | 5456 | u32 num_chunks = 0; |
5453 | char __user *to; | 5457 | char __user *to; |
5454 | 5458 | ||
5455 | if (!net->sctp.auth_enable) | 5459 | if (!ep->auth_enable) |
5456 | return -EACCES; | 5460 | return -EACCES; |
5457 | 5461 | ||
5458 | if (len < sizeof(struct sctp_authchunks)) | 5462 | if (len < sizeof(struct sctp_authchunks)) |
@@ -5489,7 +5493,7 @@ num: | |||
5489 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | 5493 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, |
5490 | char __user *optval, int __user *optlen) | 5494 | char __user *optval, int __user *optlen) |
5491 | { | 5495 | { |
5492 | struct net *net = sock_net(sk); | 5496 | struct sctp_endpoint *ep = sctp_sk(sk)->ep; |
5493 | struct sctp_authchunks __user *p = (void __user *)optval; | 5497 | struct sctp_authchunks __user *p = (void __user *)optval; |
5494 | struct sctp_authchunks val; | 5498 | struct sctp_authchunks val; |
5495 | struct sctp_association *asoc; | 5499 | struct sctp_association *asoc; |
@@ -5497,7 +5501,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | |||
5497 | u32 num_chunks = 0; | 5501 | u32 num_chunks = 0; |
5498 | char __user *to; | 5502 | char __user *to; |
5499 | 5503 | ||
5500 | if (!net->sctp.auth_enable) | 5504 | if (!ep->auth_enable) |
5501 | return -EACCES; | 5505 | return -EACCES; |
5502 | 5506 | ||
5503 | if (len < sizeof(struct sctp_authchunks)) | 5507 | if (len < sizeof(struct sctp_authchunks)) |
@@ -5514,7 +5518,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | |||
5514 | if (asoc) | 5518 | if (asoc) |
5515 | ch = (struct sctp_chunks_param *)asoc->c.auth_chunks; | 5519 | ch = (struct sctp_chunks_param *)asoc->c.auth_chunks; |
5516 | else | 5520 | else |
5517 | ch = sctp_sk(sk)->ep->auth_chunk_list; | 5521 | ch = ep->auth_chunk_list; |
5518 | 5522 | ||
5519 | if (!ch) | 5523 | if (!ch) |
5520 | goto num; | 5524 | goto num; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 35c8923b5554..c82fdc1eab7c 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -64,6 +64,9 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, | |||
64 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | 64 | static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, |
65 | void __user *buffer, size_t *lenp, | 65 | void __user *buffer, size_t *lenp, |
66 | loff_t *ppos); | 66 | loff_t *ppos); |
67 | static int proc_sctp_do_auth(struct ctl_table *ctl, int write, | ||
68 | void __user *buffer, size_t *lenp, | ||
69 | loff_t *ppos); | ||
67 | 70 | ||
68 | static struct ctl_table sctp_table[] = { | 71 | static struct ctl_table sctp_table[] = { |
69 | { | 72 | { |
@@ -266,7 +269,7 @@ static struct ctl_table sctp_net_table[] = { | |||
266 | .data = &init_net.sctp.auth_enable, | 269 | .data = &init_net.sctp.auth_enable, |
267 | .maxlen = sizeof(int), | 270 | .maxlen = sizeof(int), |
268 | .mode = 0644, | 271 | .mode = 0644, |
269 | .proc_handler = proc_dointvec, | 272 | .proc_handler = proc_sctp_do_auth, |
270 | }, | 273 | }, |
271 | { | 274 | { |
272 | .procname = "addr_scope_policy", | 275 | .procname = "addr_scope_policy", |
@@ -400,6 +403,37 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, | |||
400 | return ret; | 403 | return ret; |
401 | } | 404 | } |
402 | 405 | ||
406 | static int proc_sctp_do_auth(struct ctl_table *ctl, int write, | ||
407 | void __user *buffer, size_t *lenp, | ||
408 | loff_t *ppos) | ||
409 | { | ||
410 | struct net *net = current->nsproxy->net_ns; | ||
411 | struct ctl_table tbl; | ||
412 | int new_value, ret; | ||
413 | |||
414 | memset(&tbl, 0, sizeof(struct ctl_table)); | ||
415 | tbl.maxlen = sizeof(unsigned int); | ||
416 | |||
417 | if (write) | ||
418 | tbl.data = &new_value; | ||
419 | else | ||
420 | tbl.data = &net->sctp.auth_enable; | ||
421 | |||
422 | ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); | ||
423 | |||
424 | if (write) { | ||
425 | struct sock *sk = net->sctp.ctl_sock; | ||
426 | |||
427 | net->sctp.auth_enable = new_value; | ||
428 | /* Update the value in the control socket */ | ||
429 | lock_sock(sk); | ||
430 | sctp_sk(sk)->ep->auth_enable = new_value; | ||
431 | release_sock(sk); | ||
432 | } | ||
433 | |||
434 | return ret; | ||
435 | } | ||
436 | |||
403 | int sctp_sysctl_net_register(struct net *net) | 437 | int sctp_sysctl_net_register(struct net *net) |
404 | { | 438 | { |
405 | struct ctl_table *table = sctp_net_table; | 439 | struct ctl_table *table = sctp_net_table; |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 8d198ae03606..85c64658bd0b 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | |||
989 | skb = sctp_event2skb(event); | 989 | skb = sctp_event2skb(event); |
990 | /* Set the owner and charge rwnd for bytes received. */ | 990 | /* Set the owner and charge rwnd for bytes received. */ |
991 | sctp_ulpevent_set_owner(event, asoc); | 991 | sctp_ulpevent_set_owner(event, asoc); |
992 | sctp_assoc_rwnd_update(asoc, false); | 992 | sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); |
993 | 993 | ||
994 | if (!skb->data_len) | 994 | if (!skb->data_len) |
995 | return; | 995 | return; |
@@ -1011,7 +1011,6 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
1011 | { | 1011 | { |
1012 | struct sk_buff *skb, *frag; | 1012 | struct sk_buff *skb, *frag; |
1013 | unsigned int len; | 1013 | unsigned int len; |
1014 | struct sctp_association *asoc; | ||
1015 | 1014 | ||
1016 | /* Current stack structures assume that the rcv buffer is | 1015 | /* Current stack structures assume that the rcv buffer is |
1017 | * per socket. For UDP style sockets this is not true as | 1016 | * per socket. For UDP style sockets this is not true as |
@@ -1036,11 +1035,8 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
1036 | } | 1035 | } |
1037 | 1036 | ||
1038 | done: | 1037 | done: |
1039 | asoc = event->asoc; | 1038 | sctp_assoc_rwnd_increase(event->asoc, len); |
1040 | sctp_association_hold(asoc); | ||
1041 | sctp_ulpevent_release_owner(event); | 1039 | sctp_ulpevent_release_owner(event); |
1042 | sctp_assoc_rwnd_update(asoc, true); | ||
1043 | sctp_association_put(asoc); | ||
1044 | } | 1040 | } |
1045 | 1041 | ||
1046 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) | 1042 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) |