diff --git a/include/net/tcp.h b/include/net/tcp.h
index fef122782b44fbbd746302a3c6e9ca47f123e26d..d958260af23cf4612c6f728a59e1a6f356497a32 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -479,7 +479,7 @@ static inline void tcp_clear_xmit_timers(struct sock *sk)
 extern unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
 extern unsigned int tcp_current_mss(struct sock *sk, int large);
 
-/* tcp_diag.c */
+/* tcp.c */
 extern void tcp_get_info(struct sock *, struct tcp_info *);
 
 /* Read 'sendfile()'-style from a TCP socket */
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index efce4f346fd0fb9c438db5dcbd235d9381854a01..6760830c490f6b8f055652724e793cae576322d2 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -19,9 +19,9 @@ config IP_DCCP
 
 	  If in doubt, say N.
 
-config IP_DCCP_DIAG
-	depends on IP_DCCP && IP_INET_DIAG
-	def_tristate y if (IP_DCCP = y && IP_INET_DIAG = y)
+config INET_DCCP_DIAG
+	depends on IP_DCCP && INET_DIAG
+	def_tristate y if (IP_DCCP = y && INET_DIAG = y)
 	def_tristate m
 
 source "net/dccp/ccids/Kconfig"
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index 5741fffc436ffa4f09a558a2770ccb8d37b30b19..44a867f291848e9ad0ad43a6e4938f3e8f9b5fbd 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -3,8 +3,8 @@ obj-$(CONFIG_IP_DCCP) += dccp.o
 dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \
 	  timer.o packet_history.o
 
-obj-$(CONFIG_IP_DCCP_DIAG) += dccp_diag.o
-
-obj-y += ccids/
+obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o
 
 dccp_diag-y := diag.o
+
+obj-y += ccids/
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 019e88d8f29ef14cbfe56b51e4cc0efe6e457e19..e55136ae09f40708bbcdd50004abe97822ba0a71 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -413,8 +413,8 @@ config INET_TUNNEL
 	  
 	  If unsure, say Y.
 
-config IP_INET_DIAG
-	tristate "IP: INET socket monitoring interface"
+config INET_DIAG
+	tristate "INET: socket monitoring interface"
 	default y
 	---help---
 	  Support for INET (TCP, DCCP, etc) socket monitoring interface used by
@@ -423,6 +423,10 @@ config IP_INET_DIAG
 	  
 	  If unsure, say Y.
 
+config INET_TCP_DIAG
+	depends on INET_DIAG
+	def_tristate INET_DIAG
+
 config TCP_CONG_ADVANCED
 	bool "TCP: advanced congestion control"
 	---help---
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index fe5accbb56bfcacd18c5472978f156cf88be38d3..f0435d00db6befe152f8afaf730d6bdf1b975d6b 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -30,8 +30,9 @@ obj-$(CONFIG_IP_ROUTE_MULTIPATH_WRANDOM) += multipath_wrandom.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_DRR) += multipath_drr.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 obj-$(CONFIG_IP_VS) += ipvs/
-obj-$(CONFIG_IP_INET_DIAG) += inet_diag.o 
+obj-$(CONFIG_INET_DIAG) += inet_diag.o 
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
+obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
 obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
 obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 3bd510941da0b2665709ced910b43a274562f329..1880ad8575d8360fe8c56d387654560b20fa2b6e 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -797,25 +797,6 @@ static void inet_diag_rcv(struct sock *sk, int len)
 	}
 }
 
-static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
-			      void *_info)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_info *info = _info;
-
-	r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;
-	r->idiag_wqueue = tp->write_seq - tp->snd_una;
-	if (info != NULL)
-		tcp_get_info(sk, info);
-}
-
-static struct inet_diag_handler tcp_diag_handler = {
-	.idiag_hashinfo	 = &tcp_hashinfo,
-	.idiag_get_info	 = tcp_diag_get_info,
-	.idiag_type	 = TCPDIAG_GETSOCK,
-	.idiag_info_size = sizeof(struct tcp_info),
-};
-
 static DEFINE_SPINLOCK(inet_diag_register_lock);
 
 int inet_diag_register(const struct inet_diag_handler *h)
@@ -864,19 +845,13 @@ static int __init inet_diag_init(void)
 		goto out;
 
 	memset(inet_diag_table, 0, inet_diag_table_size);
-
 	idiagnl = netlink_kernel_create(NETLINK_INET_DIAG, inet_diag_rcv,
 					THIS_MODULE);
 	if (idiagnl == NULL)
 		goto out_free_table;
-
-	err = inet_diag_register(&tcp_diag_handler);
-	if (err)
-		goto out_sock_release;
+	err = 0;
 out:
 	return err;
-out_sock_release:
-	sock_release(idiagnl->sk_socket);
 out_free_table:
 	kfree(inet_diag_table);
 	goto out;
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
new file mode 100644
index 0000000000000000000000000000000000000000..c148c1081880a03aa1a7f24a692cb439f7ee3d70
--- /dev/null
+++ b/net/ipv4/tcp_diag.c
@@ -0,0 +1,54 @@
+/*
+ * tcp_diag.c	Module for monitoring TCP transport protocols sockets.
+ *
+ * Version:	$Id: tcp_diag.c,v 1.3 2002/02/01 22:01:04 davem Exp $
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/inet_diag.h>
+
+#include <linux/tcp.h>
+
+#include <net/tcp.h>
+
+static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+			      void *_info)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	struct tcp_info *info = _info;
+
+	r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq;
+	r->idiag_wqueue = tp->write_seq - tp->snd_una;
+	if (info != NULL)
+		tcp_get_info(sk, info);
+}
+
+static struct inet_diag_handler tcp_diag_handler = {
+	.idiag_hashinfo	 = &tcp_hashinfo,
+	.idiag_get_info	 = tcp_diag_get_info,
+	.idiag_type	 = TCPDIAG_GETSOCK,
+	.idiag_info_size = sizeof(struct tcp_info),
+};
+
+static int __init tcp_diag_init(void)
+{
+	return inet_diag_register(&tcp_diag_handler);
+}
+
+static void __exit tcp_diag_exit(void)
+{
+	inet_diag_unregister(&tcp_diag_handler);
+}
+
+module_init(tcp_diag_init);
+module_exit(tcp_diag_exit);
+MODULE_LICENSE("GPL");