forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
kernel/net/ipv4/metrics.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 #include <linux/netlink.h>
23 #include <linux/rtnetlink.h>
34 #include <linux/types.h>
....@@ -5,8 +6,9 @@
56 #include <net/net_namespace.h>
67 #include <net/tcp.h>
78
8
-int ip_metrics_convert(struct net *net, struct nlattr *fc_mx, int fc_mx_len,
9
- u32 *metrics)
9
+static int ip_metrics_convert(struct net *net, struct nlattr *fc_mx,
10
+ int fc_mx_len, u32 *metrics,
11
+ struct netlink_ext_ack *extack)
1012 {
1113 bool ecn_ca = false;
1214 struct nlattr *nla;
....@@ -21,19 +23,26 @@
2123
2224 if (!type)
2325 continue;
24
- if (type > RTAX_MAX)
26
+ if (type > RTAX_MAX) {
27
+ NL_SET_ERR_MSG(extack, "Invalid metric type");
2528 return -EINVAL;
29
+ }
2630
2731 if (type == RTAX_CC_ALGO) {
2832 char tmp[TCP_CA_NAME_MAX];
2933
3034 nla_strlcpy(tmp, nla, sizeof(tmp));
3135 val = tcp_ca_get_key_by_name(net, tmp, &ecn_ca);
32
- if (val == TCP_CA_UNSPEC)
36
+ if (val == TCP_CA_UNSPEC) {
37
+ NL_SET_ERR_MSG(extack, "Unknown tcp congestion algorithm");
3338 return -EINVAL;
39
+ }
3440 } else {
35
- if (nla_len(nla) != sizeof(u32))
41
+ if (nla_len(nla) != sizeof(u32)) {
42
+ NL_SET_ERR_MSG_ATTR(extack, nla,
43
+ "Invalid attribute in metrics");
3644 return -EINVAL;
45
+ }
3746 val = nla_get_u32(nla);
3847 }
3948 if (type == RTAX_ADVMSS && val > 65535 - 40)
....@@ -42,8 +51,10 @@
4251 val = 65535 - 15;
4352 if (type == RTAX_HOPLIMIT && val > 255)
4453 val = 255;
45
- if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK))
54
+ if (type == RTAX_FEATURES && (val & ~RTAX_FEATURE_MASK)) {
55
+ NL_SET_ERR_MSG(extack, "Unknown flag set in feature mask in metrics attribute");
4656 return -EINVAL;
57
+ }
4758 metrics[type - 1] = val;
4859 }
4960
....@@ -52,4 +63,30 @@
5263
5364 return 0;
5465 }
55
-EXPORT_SYMBOL_GPL(ip_metrics_convert);
66
+
67
+struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
68
+ int fc_mx_len,
69
+ struct netlink_ext_ack *extack)
70
+{
71
+ struct dst_metrics *fib_metrics;
72
+ int err;
73
+
74
+ if (!fc_mx)
75
+ return (struct dst_metrics *)&dst_default_metrics;
76
+
77
+ fib_metrics = kzalloc(sizeof(*fib_metrics), GFP_KERNEL);
78
+ if (unlikely(!fib_metrics))
79
+ return ERR_PTR(-ENOMEM);
80
+
81
+ err = ip_metrics_convert(net, fc_mx, fc_mx_len, fib_metrics->metrics,
82
+ extack);
83
+ if (!err) {
84
+ refcount_set(&fib_metrics->refcnt, 1);
85
+ } else {
86
+ kfree(fib_metrics);
87
+ fib_metrics = ERR_PTR(err);
88
+ }
89
+
90
+ return fib_metrics;
91
+}
92
+EXPORT_SYMBOL_GPL(ip_fib_metrics_init);