aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/ipv6.c2
-rw-r--r--net/sctp/proc.c10
-rw-r--r--net/sctp/protocol.c46
-rw-r--r--net/sctp/socket.c9
4 files changed, 52 insertions, 15 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index ec529121f38a..ce46f1c7f133 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -526,6 +526,8 @@ static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
526 } 526 }
527 return 0; 527 return 0;
528 } 528 }
529 if (addr1->v6.sin6_port != addr2->v6.sin6_port)
530 return 0;
529 if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) 531 if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
530 return 0; 532 return 0;
531 /* If this is a linklocal address, compare the scope_id. */ 533 /* If this is a linklocal address, compare the scope_id. */
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index ded7d931a6a5..963dffcc2618 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -482,7 +482,7 @@ static void sctp_remaddr_seq_stop(struct seq_file *seq, void *v)
482static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) 482static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
483{ 483{
484 struct sctp_association *assoc; 484 struct sctp_association *assoc;
485 struct sctp_transport *tsp; 485 struct sctp_transport *transport, *tsp;
486 486
487 if (v == SEQ_START_TOKEN) { 487 if (v == SEQ_START_TOKEN) {
488 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX " 488 seq_printf(seq, "ADDR ASSOC_ID HB_ACT RTO MAX_PATH_RTX "
@@ -490,10 +490,10 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
490 return 0; 490 return 0;
491 } 491 }
492 492
493 tsp = (struct sctp_transport *)v; 493 transport = (struct sctp_transport *)v;
494 if (!sctp_transport_hold(tsp)) 494 if (!sctp_transport_hold(transport))
495 return 0; 495 return 0;
496 assoc = tsp->asoc; 496 assoc = transport->asoc;
497 497
498 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list, 498 list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
499 transports) { 499 transports) {
@@ -546,7 +546,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
546 seq_printf(seq, "\n"); 546 seq_printf(seq, "\n");
547 } 547 }
548 548
549 sctp_transport_put(tsp); 549 sctp_transport_put(transport);
550 550
551 return 0; 551 return 0;
552} 552}
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index ab0d538a74ed..1099e99a53c4 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -60,6 +60,8 @@
60#include <net/inet_common.h> 60#include <net/inet_common.h>
61#include <net/inet_ecn.h> 61#include <net/inet_ecn.h>
62 62
63#define MAX_SCTP_PORT_HASH_ENTRIES (64 * 1024)
64
63/* Global data structures. */ 65/* Global data structures. */
64struct sctp_globals sctp_globals __read_mostly; 66struct sctp_globals sctp_globals __read_mostly;
65 67
@@ -1355,6 +1357,8 @@ static __init int sctp_init(void)
1355 unsigned long limit; 1357 unsigned long limit;
1356 int max_share; 1358 int max_share;
1357 int order; 1359 int order;
1360 int num_entries;
1361 int max_entry_order;
1358 1362
1359 sock_skb_cb_check_size(sizeof(struct sctp_ulpevent)); 1363 sock_skb_cb_check_size(sizeof(struct sctp_ulpevent));
1360 1364
@@ -1407,14 +1411,24 @@ static __init int sctp_init(void)
1407 1411
1408 /* Size and allocate the association hash table. 1412 /* Size and allocate the association hash table.
1409 * The methodology is similar to that of the tcp hash tables. 1413 * The methodology is similar to that of the tcp hash tables.
1414 * Though not identical. Start by getting a goal size
1410 */ 1415 */
1411 if (totalram_pages >= (128 * 1024)) 1416 if (totalram_pages >= (128 * 1024))
1412 goal = totalram_pages >> (22 - PAGE_SHIFT); 1417 goal = totalram_pages >> (22 - PAGE_SHIFT);
1413 else 1418 else
1414 goal = totalram_pages >> (24 - PAGE_SHIFT); 1419 goal = totalram_pages >> (24 - PAGE_SHIFT);
1415 1420
1416 for (order = 0; (1UL << order) < goal; order++) 1421 /* Then compute the page order for said goal */
1417 ; 1422 order = get_order(goal);
1423
1424 /* Now compute the required page order for the maximum sized table we
1425 * want to create
1426 */
1427 max_entry_order = get_order(MAX_SCTP_PORT_HASH_ENTRIES *
1428 sizeof(struct sctp_bind_hashbucket));
1429
1430 /* Limit the page order by that maximum hash table size */
1431 order = min(order, max_entry_order);
1418 1432
1419 /* Allocate and initialize the endpoint hash table. */ 1433 /* Allocate and initialize the endpoint hash table. */
1420 sctp_ep_hashsize = 64; 1434 sctp_ep_hashsize = 64;
@@ -1430,20 +1444,35 @@ static __init int sctp_init(void)
1430 INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain); 1444 INIT_HLIST_HEAD(&sctp_ep_hashtable[i].chain);
1431 } 1445 }
1432 1446
1433 /* Allocate and initialize the SCTP port hash table. */ 1447 /* Allocate and initialize the SCTP port hash table.
1448 * Note that order is initalized to start at the max sized
1449 * table we want to support. If we can't get that many pages
1450 * reduce the order and try again
1451 */
1434 do { 1452 do {
1435 sctp_port_hashsize = (1UL << order) * PAGE_SIZE /
1436 sizeof(struct sctp_bind_hashbucket);
1437 if ((sctp_port_hashsize > (64 * 1024)) && order > 0)
1438 continue;
1439 sctp_port_hashtable = (struct sctp_bind_hashbucket *) 1453 sctp_port_hashtable = (struct sctp_bind_hashbucket *)
1440 __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order); 1454 __get_free_pages(GFP_KERNEL | __GFP_NOWARN, order);
1441 } while (!sctp_port_hashtable && --order > 0); 1455 } while (!sctp_port_hashtable && --order > 0);
1456
1442 if (!sctp_port_hashtable) { 1457 if (!sctp_port_hashtable) {
1443 pr_err("Failed bind hash alloc\n"); 1458 pr_err("Failed bind hash alloc\n");
1444 status = -ENOMEM; 1459 status = -ENOMEM;
1445 goto err_bhash_alloc; 1460 goto err_bhash_alloc;
1446 } 1461 }
1462
1463 /* Now compute the number of entries that will fit in the
1464 * port hash space we allocated
1465 */
1466 num_entries = (1UL << order) * PAGE_SIZE /
1467 sizeof(struct sctp_bind_hashbucket);
1468
1469 /* And finish by rounding it down to the nearest power of two
1470 * this wastes some memory of course, but its needed because
1471 * the hash function operates based on the assumption that
1472 * that the number of entries is a power of two
1473 */
1474 sctp_port_hashsize = rounddown_pow_of_two(num_entries);
1475
1447 for (i = 0; i < sctp_port_hashsize; i++) { 1476 for (i = 0; i < sctp_port_hashsize; i++) {
1448 spin_lock_init(&sctp_port_hashtable[i].lock); 1477 spin_lock_init(&sctp_port_hashtable[i].lock);
1449 INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain); 1478 INIT_HLIST_HEAD(&sctp_port_hashtable[i].chain);
@@ -1452,7 +1481,8 @@ static __init int sctp_init(void)
1452 if (sctp_transport_hashtable_init()) 1481 if (sctp_transport_hashtable_init())
1453 goto err_thash_alloc; 1482 goto err_thash_alloc;
1454 1483
1455 pr_info("Hash tables configured (bind %d)\n", sctp_port_hashsize); 1484 pr_info("Hash tables configured (bind %d/%d)\n", sctp_port_hashsize,
1485 num_entries);
1456 1486
1457 sctp_sysctl_register(); 1487 sctp_sysctl_register();
1458 1488
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5ca2ebfe0be8..e878da0949db 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5538,6 +5538,7 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
5538 struct sctp_hmac_algo_param *hmacs; 5538 struct sctp_hmac_algo_param *hmacs;
5539 __u16 data_len = 0; 5539 __u16 data_len = 0;
5540 u32 num_idents; 5540 u32 num_idents;
5541 int i;
5541 5542
5542 if (!ep->auth_enable) 5543 if (!ep->auth_enable)
5543 return -EACCES; 5544 return -EACCES;
@@ -5555,8 +5556,12 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
5555 return -EFAULT; 5556 return -EFAULT;
5556 if (put_user(num_idents, &p->shmac_num_idents)) 5557 if (put_user(num_idents, &p->shmac_num_idents))
5557 return -EFAULT; 5558 return -EFAULT;
5558 if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len)) 5559 for (i = 0; i < num_idents; i++) {
5559 return -EFAULT; 5560 __u16 hmacid = ntohs(hmacs->hmac_ids[i]);
5561
5562 if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
5563 return -EFAULT;
5564 }
5560 return 0; 5565 return 0;
5561} 5566}
5562 5567