aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h7
-rw-r--r--include/uapi/linux/rtnetlink.h2
-rw-r--r--net/core/rtnetlink.c15
-rw-r--r--net/decnet/dn_fib.c3
-rw-r--r--net/decnet/dn_table.c4
-rw-r--r--net/ipv4/fib_semantics.c14
-rw-r--r--net/ipv6/route.c17
7 files changed, 54 insertions, 8 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 135b70c9a734..95bb237152e0 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -846,7 +846,14 @@ extern struct tcp_congestion_ops tcp_reno;
846 846
847struct tcp_congestion_ops *tcp_ca_find_key(u32 key); 847struct tcp_congestion_ops *tcp_ca_find_key(u32 key);
848u32 tcp_ca_get_key_by_name(const char *name); 848u32 tcp_ca_get_key_by_name(const char *name);
849#ifdef CONFIG_INET
849char *tcp_ca_get_name_by_key(u32 key, char *buffer); 850char *tcp_ca_get_name_by_key(u32 key, char *buffer);
851#else
852static inline char *tcp_ca_get_name_by_key(u32 key, char *buffer)
853{
854 return NULL;
855}
856#endif
850 857
851static inline bool tcp_ca_needs_ecn(const struct sock *sk) 858static inline bool tcp_ca_needs_ecn(const struct sock *sk)
852{ 859{
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 9c9b8b4480cd..d81f22d5b390 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -389,6 +389,8 @@ enum {
389#define RTAX_INITRWND RTAX_INITRWND 389#define RTAX_INITRWND RTAX_INITRWND
390 RTAX_QUICKACK, 390 RTAX_QUICKACK,
391#define RTAX_QUICKACK RTAX_QUICKACK 391#define RTAX_QUICKACK RTAX_QUICKACK
392 RTAX_CC_ALGO,
393#define RTAX_CC_ALGO RTAX_CC_ALGO
392 __RTAX_MAX 394 __RTAX_MAX
393}; 395};
394 396
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index da983d4bac02..6a6cdade1676 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -50,6 +50,7 @@
50#include <net/arp.h> 50#include <net/arp.h>
51#include <net/route.h> 51#include <net/route.h>
52#include <net/udp.h> 52#include <net/udp.h>
53#include <net/tcp.h>
53#include <net/sock.h> 54#include <net/sock.h>
54#include <net/pkt_sched.h> 55#include <net/pkt_sched.h>
55#include <net/fib_rules.h> 56#include <net/fib_rules.h>
@@ -669,9 +670,19 @@ int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics)
669 670
670 for (i = 0; i < RTAX_MAX; i++) { 671 for (i = 0; i < RTAX_MAX; i++) {
671 if (metrics[i]) { 672 if (metrics[i]) {
673 if (i == RTAX_CC_ALGO - 1) {
674 char tmp[TCP_CA_NAME_MAX], *name;
675
676 name = tcp_ca_get_name_by_key(metrics[i], tmp);
677 if (!name)
678 continue;
679 if (nla_put_string(skb, i + 1, name))
680 goto nla_put_failure;
681 } else {
682 if (nla_put_u32(skb, i + 1, metrics[i]))
683 goto nla_put_failure;
684 }
672 valid++; 685 valid++;
673 if (nla_put_u32(skb, i+1, metrics[i]))
674 goto nla_put_failure;
675 } 686 }
676 } 687 }
677 688
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index d332aefb0846..df4803437888 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -298,7 +298,8 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct nlattr *att
298 int type = nla_type(attr); 298 int type = nla_type(attr);
299 299
300 if (type) { 300 if (type) {
301 if (type > RTAX_MAX || nla_len(attr) < 4) 301 if (type > RTAX_MAX || type == RTAX_CC_ALGO ||
302 nla_len(attr) < 4)
302 goto err_inval; 303 goto err_inval;
303 304
304 fi->fib_metrics[type-1] = nla_get_u32(attr); 305 fi->fib_metrics[type-1] = nla_get_u32(attr);
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 86e3807052e9..3f19fcbf126d 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -29,6 +29,7 @@
29#include <linux/route.h> /* RTF_xxx */ 29#include <linux/route.h> /* RTF_xxx */
30#include <net/neighbour.h> 30#include <net/neighbour.h>
31#include <net/netlink.h> 31#include <net/netlink.h>
32#include <net/tcp.h>
32#include <net/dst.h> 33#include <net/dst.h>
33#include <net/flow.h> 34#include <net/flow.h>
34#include <net/fib_rules.h> 35#include <net/fib_rules.h>
@@ -273,7 +274,8 @@ static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi)
273 size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg)) 274 size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
274 + nla_total_size(4) /* RTA_TABLE */ 275 + nla_total_size(4) /* RTA_TABLE */
275 + nla_total_size(2) /* RTA_DST */ 276 + nla_total_size(2) /* RTA_DST */
276 + nla_total_size(4); /* RTA_PRIORITY */ 277 + nla_total_size(4) /* RTA_PRIORITY */
278 + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
277 279
278 /* space for nested metrics */ 280 /* space for nested metrics */
279 payload += nla_total_size((RTAX_MAX * nla_total_size(4))); 281 payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index f99f41bd15b8..d2b7b5521b1b 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -360,7 +360,8 @@ static inline size_t fib_nlmsg_size(struct fib_info *fi)
360 + nla_total_size(4) /* RTA_TABLE */ 360 + nla_total_size(4) /* RTA_TABLE */
361 + nla_total_size(4) /* RTA_DST */ 361 + nla_total_size(4) /* RTA_DST */
362 + nla_total_size(4) /* RTA_PRIORITY */ 362 + nla_total_size(4) /* RTA_PRIORITY */
363 + nla_total_size(4); /* RTA_PREFSRC */ 363 + nla_total_size(4) /* RTA_PREFSRC */
364 + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
364 365
365 /* space for nested metrics */ 366 /* space for nested metrics */
366 payload += nla_total_size((RTAX_MAX * nla_total_size(4))); 367 payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
@@ -859,7 +860,16 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
859 860
860 if (type > RTAX_MAX) 861 if (type > RTAX_MAX)
861 goto err_inval; 862 goto err_inval;
862 val = nla_get_u32(nla); 863 if (type == RTAX_CC_ALGO) {
864 char tmp[TCP_CA_NAME_MAX];
865
866 nla_strlcpy(tmp, nla, sizeof(tmp));
867 val = tcp_ca_get_key_by_name(tmp);
868 if (val == TCP_CA_UNSPEC)
869 goto err_inval;
870 } else {
871 val = nla_get_u32(nla);
872 }
863 if (type == RTAX_ADVMSS && val > 65535 - 40) 873 if (type == RTAX_ADVMSS && val > 65535 - 40)
864 val = 65535 - 40; 874 val = 65535 - 40;
865 if (type == RTAX_MTU && val > 65535 - 15) 875 if (type == RTAX_MTU && val > 65535 - 15)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 454771d20b21..34dcbb59df75 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1488,10 +1488,22 @@ static int ip6_convert_metrics(struct mx6_config *mxc,
1488 int type = nla_type(nla); 1488 int type = nla_type(nla);
1489 1489
1490 if (type) { 1490 if (type) {
1491 u32 val;
1492
1491 if (unlikely(type > RTAX_MAX)) 1493 if (unlikely(type > RTAX_MAX))
1492 goto err; 1494 goto err;
1495 if (type == RTAX_CC_ALGO) {
1496 char tmp[TCP_CA_NAME_MAX];
1497
1498 nla_strlcpy(tmp, nla, sizeof(tmp));
1499 val = tcp_ca_get_key_by_name(tmp);
1500 if (val == TCP_CA_UNSPEC)
1501 goto err;
1502 } else {
1503 val = nla_get_u32(nla);
1504 }
1493 1505
1494 mp[type - 1] = nla_get_u32(nla); 1506 mp[type - 1] = val;
1495 __set_bit(type - 1, mxc->mx_valid); 1507 __set_bit(type - 1, mxc->mx_valid);
1496 } 1508 }
1497 } 1509 }
@@ -2571,7 +2583,8 @@ static inline size_t rt6_nlmsg_size(void)
2571 + nla_total_size(4) /* RTA_OIF */ 2583 + nla_total_size(4) /* RTA_OIF */
2572 + nla_total_size(4) /* RTA_PRIORITY */ 2584 + nla_total_size(4) /* RTA_PRIORITY */
2573 + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */ 2585 + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
2574 + nla_total_size(sizeof(struct rta_cacheinfo)); 2586 + nla_total_size(sizeof(struct rta_cacheinfo))
2587 + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
2575} 2588}
2576 2589
2577static int rt6_fill_node(struct net *net, 2590static int rt6_fill_node(struct net *net,