diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/ipv6.c | 2 | ||||
-rw-r--r-- | net/sctp/proc.c | 10 | ||||
-rw-r--r-- | net/sctp/protocol.c | 46 | ||||
-rw-r--r-- | net/sctp/socket.c | 9 |
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) | |||
482 | static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | 482 | static 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. */ |
64 | struct sctp_globals sctp_globals __read_mostly; | 66 | struct 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 | ||