|
@@ -252,6 +252,7 @@
|
|
|
#include <linux/types.h>
|
|
|
#include <linux/fcntl.h>
|
|
|
#include <linux/poll.h>
|
|
|
+#include <linux/inet_diag.h>
|
|
|
#include <linux/init.h>
|
|
|
#include <linux/fs.h>
|
|
|
#include <linux/skbuff.h>
|
|
@@ -2739,6 +2740,26 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
|
|
|
return -EFAULT;
|
|
|
return 0;
|
|
|
}
|
|
|
+ case TCP_CC_INFO: {
|
|
|
+ const struct tcp_congestion_ops *ca_ops;
|
|
|
+ union tcp_cc_info info;
|
|
|
+ size_t sz = 0;
|
|
|
+ int attr;
|
|
|
+
|
|
|
+ if (get_user(len, optlen))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ ca_ops = icsk->icsk_ca_ops;
|
|
|
+ if (ca_ops && ca_ops->get_info)
|
|
|
+ sz = ca_ops->get_info(sk, ~0U, &attr, &info);
|
|
|
+
|
|
|
+ len = min_t(unsigned int, len, sz);
|
|
|
+ if (put_user(len, optlen))
|
|
|
+ return -EFAULT;
|
|
|
+ if (copy_to_user(optval, &info, len))
|
|
|
+ return -EFAULT;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
case TCP_QUICKACK:
|
|
|
val = !icsk->icsk_ack.pingpong;
|
|
|
break;
|