From 3e4e29568dc5fb5a31d4396e29f5b7911330aab4 Mon Sep 17 00:00:00 2001
From: =?iso-8859-15?q?Beno=EEt=20Ganne?= <benoit.ganne@gmail.com>
Date: Sun, 30 Sep 2007 19:53:10 +0200
Subject: [PATCH 2/3] add support for mod-ipv4

This patch modifies the kernel code in order to allow to compile ipv4
as a module.
Most of the modifications are EXPORT_SYMBOL additions and init/exit
functions reordering but there are 2 main issues :
 - net/ipv4/ip_modglue.c: this contains 4 stub functions which are too
tight to the built-in kernel to be easily worked around (mainly arp_find),
the stubs are then replaced on ipv4 module load with the real ipv4 functions
 - mm/page_alloc.c: I had to remove the __init specifier for
alloc_large_system_hash() and to modifie it to be able to call it after
bootmem as it is used by tcp code, and to remove __meminitdata specifiers
from nr_all_pages and nr_kernel_pages as they are used inside
alloc_large_system_hash(), and to EXPORT_SYMBOL nr_all_pages as it is used
in ipv4 code.
---
 arch/um/drivers/net_kern.c             |    3 +-
 include/linux/bootmem.h                |    4 +-
 include/net/cipso_ipv4.h               |    5 ++
 include/net/ip.h                       |   10 ++++-
 include/net/ip_modglue.h               |   24 +++++++++++
 include/net/tcp.h                      |    6 +++
 include/net/xfrm.h                     |    2 +
 mm/page_alloc.c                        |   16 +++++---
 net/8021q/vlan_dev.c                   |    5 +-
 net/core/neighbour.c                   |    3 +
 net/core/request_sock.c                |    3 +
 net/core/sock.c                        |    4 +-
 net/ethernet/eth.c                     |    3 +-
 net/ipv4/af_inet.c                     |   46 ++++++++++++++++++++-
 net/ipv4/cipso_ipv4.c                  |    3 +-
 net/ipv4/ip_modglue.c                  |   70 ++++++++++++++++++++++++++++++++
 net/ipv4/netfilter.c                   |   10 +----
 net/ipv4/syncookies.c                  |    3 +-
 net/ipv4/sysctl_net_ipv4.c             |   34 +++++++++++++++-
 net/ipv4/tcp.c                         |    4 ++
 net/ipv4/tcp_cong.c                    |    4 +-
 net/ipv4/xfrm4_policy.c                |    5 ++
 net/ipv4/xfrm4_state.c                 |    2 -
 net/netfilter/nf_conntrack_h323_main.c |    2 +
 net/packet/af_packet.c                 |    3 +-
 net/socket.c                           |    3 +
 net/sysctl_net.c                       |   12 -----
 net/xfrm/xfrm_input.c                  |    2 +-
 net/xfrm/xfrm_policy.c                 |    8 +++-
 net/xfrm/xfrm_state.c                  |    2 +-
 30 files changed, 249 insertions(+), 52 deletions(-)
 create mode 100644 include/net/ip_modglue.h
 create mode 100644 net/ipv4/ip_modglue.c

diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 72773dd..1f1a957 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -20,6 +20,7 @@
 #include "linux/bootmem.h"
 #include "linux/ethtool.h"
 #include "linux/platform_device.h"
+#include "net/ip_modglue.h"
 #include "asm/uaccess.h"
 #include "kern_util.h"
 #include "net_kern.h"
@@ -766,7 +767,7 @@ static int uml_net_init(void)
 	struct in_ifaddr *in;
 
 	mconsole_register_dev(&net_mc);
-	register_inetaddr_notifier(&uml_inetaddr_notifier);
+	ip_mod_register_inetaddr_notifier(&uml_inetaddr_notifier);
 
 	/* Devices may have been opened already, so the uml_inetaddr_notifier
 	 * didn't get a chance to run for them.  This fakes it so that
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index c83534e..caa887e 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -108,8 +108,8 @@ static inline void *alloc_remap(int nid, unsigned long size)
 }
 #endif /* CONFIG_HAVE_ARCH_ALLOC_REMAP */
 
-extern unsigned long __meminitdata nr_kernel_pages;
-extern unsigned long __meminitdata nr_all_pages;
+extern unsigned long nr_kernel_pages;
+extern unsigned long nr_all_pages;
 
 extern void *alloc_large_system_hash(const char *tablename,
 				     unsigned long bucketsize,
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h
index a6bb945..0111870 100644
--- a/include/net/cipso_ipv4.h
+++ b/include/net/cipso_ipv4.h
@@ -116,6 +116,11 @@ extern int cipso_v4_rbm_strictvalid;
 #endif
 
 /*
+ * init function
+ */
+extern int cipso_v4_init(void);
+
+/*
  * Helper Functions
  */
 
diff --git a/include/net/ip.h b/include/net/ip.h
index 93e7766..a8a12db 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -391,7 +391,15 @@ int ipv4_doint_and_flush_strategy(ctl_table *table, int __user *name, int nlen,
 extern int ip_misc_proc_init(void);
 #endif
 
-extern struct ctl_table ipv4_table[];
+#ifdef CONFIG_SYSCTL
+extern void ipv4_sysctl_register(void);
+extern void ipv4_sysctl_unregister(void);
+#endif
+
+#ifdef CONFIG_NETFILTER
+extern int ipv4_netfilter_init(void);
+extern void ipv4_netfilter_fini(void);
+#endif
 
 /*
  * Functions provided by random.c
diff --git a/include/net/ip_modglue.h b/include/net/ip_modglue.h
new file mode 100644
index 0000000..39be913
--- /dev/null
+++ b/include/net/ip_modglue.h
@@ -0,0 +1,24 @@
+/* linux/net/ip_mod_glue.h */
+#ifndef _IP_MODGLUE_H
+#define _IP_MODGLUE_H
+
+/* only used in pointer form */
+struct sk_buff;
+struct notifier_block;
+
+struct ip_mod_ops {
+        int (*arp_find) (unsigned char *, struct sk_buff *);
+        int (*inet_ioctl) (struct socket *, unsigned int, unsigned long);
+        int (*register_inetaddr_notifier) (struct notifier_block *);
+        void (*tcp_set_keepalive)(struct sock *, int);
+};
+
+extern struct ip_mod_ops default_ip_mod_ops;
+
+extern int ip_mod_arp_find(unsigned char *haddr, struct sk_buff *skb);
+extern int ip_mod_inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
+extern int ip_mod_register_inetaddr_notifier(struct notifier_block *nb);
+extern void ip_mod_tcp_set_keepalive(struct sock *sk, int val);
+
+extern int ip_mod_register(struct ip_mod_ops *ops);
+#endif /* ! _IP_MODGLUE_H */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 06827e3..dd6f988 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -669,6 +669,11 @@ struct tcp_congestion_ops {
 	struct module 	*owner;
 };
 
+/*
+ * init function
+ */
+extern int tcp_congestion_default(void);
+
 extern int tcp_register_congestion_control(struct tcp_congestion_ops *type);
 extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
 
@@ -1348,5 +1353,6 @@ struct tcp_request_sock_ops {
 
 extern void tcp_v4_init(struct net_proto_family *ops);
 extern void tcp_init(void);
+extern int init_syncookies(void);
 
 #endif	/* _TCP_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4d56e16..d4b0a3a 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -906,10 +906,12 @@ struct xfrm6_tunnel {
 
 extern void xfrm_init(void);
 extern void xfrm4_init(void);
+extern void xfrm4_fini(void);
 extern void xfrm6_init(void);
 extern void xfrm6_fini(void);
 extern void xfrm_state_init(void);
 extern void xfrm4_state_init(void);
+extern void xfrm4_state_fini(void);
 extern void xfrm6_state_init(void);
 extern void xfrm6_state_fini(void);
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 05ace44..26fba01 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -101,8 +101,9 @@ static char * const zone_names[MAX_NR_ZONES] = {
 
 int min_free_kbytes = 1024;
 
-unsigned long __meminitdata nr_kernel_pages;
-unsigned long __meminitdata nr_all_pages;
+unsigned long nr_kernel_pages;
+unsigned long nr_all_pages;
+EXPORT_SYMBOL(nr_all_pages);
 static unsigned long __meminitdata dma_reserve;
 
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
@@ -3300,7 +3301,7 @@ __setup("hashdist=", set_hashdist);
  *   quantity of entries
  * - limit is the number of hash buckets, not the total allocation size
  */
-void *__init alloc_large_system_hash(const char *tablename,
+void * alloc_large_system_hash(const char *tablename,
 				     unsigned long bucketsize,
 				     unsigned long numentries,
 				     int scale,
@@ -3346,11 +3347,13 @@ void *__init alloc_large_system_hash(const char *tablename,
 
 	do {
 		size = bucketsize << log2qty;
-		if (flags & HASH_EARLY)
+		if (flags & HASH_EARLY) {
+                        /* we can only call alloc_bootmem on boot */
+                        BUG_ON(SYSTEM_BOOTING != system_state);
 			table = alloc_bootmem(size);
-		else if (hashdist)
+                } else if (hashdist) {
 			table = __vmalloc(size, GFP_ATOMIC, PAGE_KERNEL);
-		else {
+                } else {
 			unsigned long order;
 			for (order = 0; ((1UL << order) << PAGE_SHIFT) < size; order++)
 				;
@@ -3374,6 +3377,7 @@ void *__init alloc_large_system_hash(const char *tablename,
 
 	return table;
 }
+EXPORT_SYMBOL(alloc_large_system_hash);
 
 #ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
 struct page *pfn_to_page(unsigned long pfn)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index ec46084..efb3f20 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -36,6 +36,7 @@
 #include "vlanproc.h"
 #include <linux/if_vlan.h>
 #include <net/ip.h>
+#include <net/ip_modglue.h>
 
 /*
  *	Rebuild the Ethernet MAC header. This is called after an ARP
@@ -53,11 +54,11 @@ int vlan_dev_rebuild_header(struct sk_buff *skb)
 	struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data);
 
 	switch (veth->h_vlan_encapsulated_proto) {
-#ifdef CONFIG_INET
+#if defined(CONFIG_IPV4) || defined(CONFIG_IPV4_MODULE)
 	case __constant_htons(ETH_P_IP):
 
 		/* TODO:  Confirm this will work with VLAN headers... */
-		return arp_find(veth->h_dest, skb);
+		return ip_mod_arp_find(veth->h_dest, skb);
 #endif
 	default:
 		printk(VLAN_DBG
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 9df26a0..ede7753 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2780,6 +2780,9 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink);
 EXPORT_SYMBOL(neigh_update);
 EXPORT_SYMBOL(pneigh_enqueue);
 EXPORT_SYMBOL(pneigh_lookup);
+#if defined(CONFIG_IPV4_MODULE)
+EXPORT_SYMBOL(pneigh_delete);
+#endif
 
 #ifdef CONFIG_ARPD
 EXPORT_SYMBOL(neigh_app_ns);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 5f0818d..31047c5 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -33,6 +33,9 @@
  * Note : Dont forget somaxconn that may limit backlog too.
  */
 int sysctl_max_syn_backlog = 256;
+#if defined(CONFIG_IPV4_MODULE)
+EXPORT_SYMBOL(sysctl_max_syn_backlog);
+#endif
 
 int reqsk_queue_alloc(struct request_sock_queue *queue,
 		      unsigned int nr_table_entries)
diff --git a/net/core/sock.c b/net/core/sock.c
index c14ce01..da52946 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -127,7 +127,7 @@
 #include <linux/filter.h>
 
 #ifdef CONFIG_INET
-#include <net/tcp.h>
+#include <net/ip_modglue.h>
 #endif
 
 /*
@@ -481,7 +481,7 @@ set_rcvbuf:
 	case SO_KEEPALIVE:
 #ifdef CONFIG_INET
 		if (sk->sk_protocol == IPPROTO_TCP)
-			tcp_set_keepalive(sk, valbool);
+			ip_mod_tcp_set_keepalive(sk, valbool);
 #endif
 		sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
 		break;
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 0ac2524..d6092bc 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -57,6 +57,7 @@
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <net/ip.h>
+#include <net/ip_modglue.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
@@ -128,7 +129,7 @@ int eth_rebuild_header(struct sk_buff *skb)
 	switch (eth->h_proto) {
 #ifdef CONFIG_INET
 	case __constant_htons(ETH_P_IP):
-		return arp_find(eth->h_dest, skb);
+		return ip_mod_arp_find(eth->h_dest, skb);
 #endif
 	default:
 		printk(KERN_DEBUG
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 90b241c..68ea808 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -110,12 +110,18 @@
 #include <net/raw.h>
 #include <net/icmp.h>
 #include <net/ipip.h>
+#include <net/ipconfig.h>
 #include <net/inet_common.h>
 #include <net/xfrm.h>
+#include <net/ip_modglue.h>
 #ifdef CONFIG_IP_MROUTE
 #include <linux/mroute.h>
 #endif
 
+MODULE_AUTHOR("Cast of dozens");
+MODULE_DESCRIPTION("IPv4 protocol stack for Linux");
+MODULE_LICENSE("GPL");
+
 DEFINE_SNMP_STAT(struct linux_mib, net_statistics) __read_mostly;
 
 extern void ip_mc_drop_socket(struct sock *sk);
@@ -1340,6 +1346,13 @@ static struct packet_type ip_packet_type = {
 	.gso_segment = inet_gso_segment,
 };
 
+static struct ip_mod_ops ip_mod_ops = {
+        .arp_find = arp_find,
+        .inet_ioctl = inet_ioctl,
+        .register_inetaddr_notifier = register_inetaddr_notifier,
+        .tcp_set_keepalive = tcp_set_keepalive,
+};
+
 static int __init inet_init(void)
 {
 	struct sk_buff *dummy_skb;
@@ -1349,6 +1362,12 @@ static int __init inet_init(void)
 
 	BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
 
+        ip_mod_register(&ip_mod_ops);
+
+#ifdef CONFIG_NETLABEL
+        cipso_v4_init();
+#endif
+
 	rc = proto_register(&tcp_prot, 1);
 	if (rc)
 		goto out;
@@ -1428,12 +1447,22 @@ static int __init inet_init(void)
 	if (init_ipv4_mibs())
 		printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ;
 
+#ifdef CONFIG_SYSCTL
+	ipv4_sysctl_register();
+#endif
+
 	ipv4_proc_init();
 
 	ipfrag_init();
 
 	dev_add_pack(&ip_packet_type);
 
+        tcp_congestion_default();
+
+#ifdef CONFIG_NETFILTER
+        ipv4_netfilter_init();
+#endif
+
 	rc = 0;
 out:
 	return rc;
@@ -1443,8 +1472,7 @@ out_unregister_tcp_proto:
 	proto_unregister(&tcp_prot);
 	goto out;
 }
-
-fs_initcall(inet_init);
+module_init(inet_init);
 
 /* ------------------------------------------------------------------------ */
 
@@ -1485,6 +1513,20 @@ static int __init ipv4_proc_init(void)
 }
 #endif /* CONFIG_PROC_FS */
 
+static void __exit inet_exit(void)
+{
+#ifdef CONFIG_NETFILTER
+        ipv4_netfilter_fini();
+#endif
+
+#ifdef CONFIG_SYSCTL
+	ipv4_sysctl_unregister();
+#endif
+
+        ip_mod_register(&default_ip_mod_ops);
+}
+module_exit(inet_exit);
+
 MODULE_ALIAS_NETPROTO(PF_INET);
 
 EXPORT_SYMBOL(inet_accept);
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index ab56a05..834a5ba 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -1958,7 +1958,7 @@ skbuff_getattr_return:
  * and negative values on failure.
  *
  */
-static int __init cipso_v4_init(void)
+int __init cipso_v4_init(void)
 {
 	int ret_val;
 
@@ -1970,4 +1970,3 @@ static int __init cipso_v4_init(void)
 	return 0;
 }
 
-subsys_initcall(cipso_v4_init);
diff --git a/net/ipv4/ip_modglue.c b/net/ipv4/ip_modglue.c
new file mode 100644
index 0000000..d1c7555
--- /dev/null
+++ b/net/ipv4/ip_modglue.c
@@ -0,0 +1,70 @@
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <net/ip_modglue.h>
+
+static int default_arp_find(unsigned char *haddr, struct sk_buff *skb)
+{
+        kfree_skb(skb);
+        return -1;
+}
+
+static int default_inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+        return -ENOIOCTLCMD;
+}
+
+static int default_register_inetaddr_notifier(struct notifier_block *nb)
+{
+        return -1;
+}
+
+static void default_tcp_set_keepalive(struct sock *sk, int val)
+{
+        return;
+}
+
+struct ip_mod_ops default_ip_mod_ops = {
+        .arp_find = default_arp_find,
+        .inet_ioctl = default_inet_ioctl,
+        .register_inetaddr_notifier = default_register_inetaddr_notifier,
+        .tcp_set_keepalive = default_tcp_set_keepalive,
+};
+EXPORT_SYMBOL(default_ip_mod_ops);
+
+static struct ip_mod_ops *mod_ops;
+
+inline int ip_mod_arp_find(unsigned char *haddr, struct sk_buff *skb)
+{
+        return mod_ops->arp_find(haddr, skb);
+}
+EXPORT_SYMBOL(ip_mod_arp_find);
+
+inline int ip_mod_inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+        return mod_ops->inet_ioctl(sock, cmd, arg);
+}
+
+inline int ip_mod_register_inetaddr_notifier(struct notifier_block *nb)
+{
+        return mod_ops->register_inetaddr_notifier(nb);
+}
+
+inline void ip_mod_tcp_set_keepalive(struct sock *sk, int val)
+{
+        mod_ops->tcp_set_keepalive(sk, val);
+}
+
+int ip_mod_register(struct ip_mod_ops *ops)
+{
+        mod_ops = ops;
+        return 0;
+}
+EXPORT_SYMBOL(ip_mod_register);
+
+static int __init mod_ops_init(void)
+{
+        return ip_mod_register(&default_ip_mod_ops);
+}
+subsys_initcall(mod_ops_init);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b441929..3d425df 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -123,9 +123,6 @@ int ip_xfrm_me_harder(struct sk_buff **pskb)
 EXPORT_SYMBOL(ip_xfrm_me_harder);
 #endif
 
-void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
-EXPORT_SYMBOL(ip_nat_decode_session);
-
 /*
  * Extra routing may needed on local out, as the QUEUE target never
  * returns control to the table.
@@ -205,15 +202,12 @@ static struct nf_afinfo nf_ip_afinfo = {
 	.route_key_size	= sizeof(struct ip_rt_info),
 };
 
-static int ipv4_netfilter_init(void)
+int __init ipv4_netfilter_init(void)
 {
 	return nf_register_afinfo(&nf_ip_afinfo);
 }
 
-static void ipv4_netfilter_fini(void)
+void __exit ipv4_netfilter_fini(void)
 {
 	nf_unregister_afinfo(&nf_ip_afinfo);
 }
-
-module_init(ipv4_netfilter_init);
-module_exit(ipv4_netfilter_fini);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 2da1be0..4152dd0 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -25,12 +25,11 @@ extern int sysctl_tcp_syncookies;
 
 static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS];
 
-static __init int init_syncookies(void)
+int __init init_syncookies(void)
 {
 	get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
 	return 0;
 }
-module_init(init_syncookies);
 
 #define COOKIEBITS 24	/* Upper bits store count */
 #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 53ef0f4..9780503 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -186,7 +186,7 @@ static int strategy_allowed_congestion_control(ctl_table *table, int __user *nam
 
 }
 
-ctl_table ipv4_table[] = {
+static ctl_table ipv4_table[] = {
 	{
 		.ctl_name	= NET_IPV4_TCP_TIMESTAMPS,
 		.procname	= "tcp_timestamps",
@@ -822,6 +822,38 @@ ctl_table ipv4_table[] = {
 	{ .ctl_name = 0 }
 };
 
+static ctl_table ipv4_net_table[] = {
+	{
+		.ctl_name	= NET_IPV4,
+		.procname	= "ipv4",
+		.mode		= 0555,
+		.child		= ipv4_table
+	},
+	{ .ctl_name = 0 }
+};
+
+static ctl_table ipv4_root_table[] = {
+	{
+		.ctl_name	= CTL_NET,
+		.procname	= "net",
+		.mode		= 0555,
+		.child		= ipv4_net_table
+	},
+	{ .ctl_name = 0 }
+};
+
+static struct ctl_table_header *ipv4_sysctl_header;
+
+void __init ipv4_sysctl_register(void)
+{
+	ipv4_sysctl_header = register_sysctl_table(ipv4_root_table);
+}
+
+void __exit ipv4_sysctl_unregister(void)
+{
+	unregister_sysctl_table(ipv4_sysctl_header);
+}
+
 #endif /* CONFIG_SYSCTL */
 
 EXPORT_SYMBOL(ipv4_config);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 11ff182..56c1adf 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2506,6 +2506,10 @@ void __init tcp_init(void)
 	       tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
 
 	tcp_register_congestion_control(&tcp_reno);
+
+#ifdef CONFIG_SYN_COOKIES
+        init_syncookies();
+#endif
 }
 
 EXPORT_SYMBOL(tcp_close);
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 1260e52..87eac3f 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -136,12 +136,10 @@ int tcp_set_default_congestion_control(const char *name)
 }
 
 /* Set default value from kernel configuration at bootup */
-static int __init tcp_congestion_default(void)
+int __init tcp_congestion_default(void)
 {
 	return tcp_set_default_congestion_control(CONFIG_DEFAULT_TCP_CONG);
 }
-late_initcall(tcp_congestion_default);
-
 
 /* Build string with list of available congestion control values */
 void tcp_get_available_congestion_control(char *buf, size_t maxlen)
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 4ff8ed3..3155e82 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -359,3 +359,8 @@ void __init xfrm4_init(void)
 	xfrm4_policy_init();
 }
 
+void __exit xfrm4_exit(void)
+{
+        xfrm4_policy_fini();
+	xfrm4_state_fini();
+}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 93e2c06..7032c11 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -59,10 +59,8 @@ void __init xfrm4_state_init(void)
 	xfrm_state_register_afinfo(&xfrm4_state_afinfo);
 }
 
-#if 0
 void __exit xfrm4_state_fini(void)
 {
 	xfrm_state_unregister_afinfo(&xfrm4_state_afinfo);
 }
-#endif  /*  0  */
 
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index a1b95ac..23aec66 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -726,6 +726,7 @@ static int callforward_do_filter(union nf_conntrack_address *src,
 	memset(&fl2, 0, sizeof(fl2));
 
 	switch (family) {
+#if defined(CONFIG_IPV4) || defined(CONFIG_IPV4_MODULE)
 	case AF_INET: {
 		struct rtable *rt1, *rt2;
 
@@ -742,6 +743,7 @@ static int callforward_do_filter(union nf_conntrack_address *src,
 		}
 		break;
 	}
+#endif
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6: {
 		struct rt6_info *rt1, *rt2;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f8b8301..d7ea292 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -80,6 +80,7 @@
 #include <linux/init.h>
 
 #ifdef CONFIG_INET
+#include <net/ip_modglue.h>
 #include <net/inet_common.h>
 #endif
 
@@ -1553,7 +1554,7 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd,
 		case SIOCGIFDSTADDR:
 		case SIOCSIFDSTADDR:
 		case SIOCSIFFLAGS:
-			return inet_dgram_ops.ioctl(sock, cmd, arg);
+			return ip_mod_inet_ioctl(sock, cmd, arg);
 #endif
 
 		default:
diff --git a/net/socket.c b/net/socket.c
index 0010da0..737830c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2197,6 +2197,9 @@ void socket_seq_show(struct seq_file *seq)
 
 	seq_printf(seq, "sockets: used %d\n", counter);
 }
+#if defined(CONFIG_IPV4_MODULE)
+EXPORT_SYMBOL(socket_seq_show);
+#endif
 #endif				/* CONFIG_PROC_FS */
 
 #ifdef CONFIG_COMPAT
diff --git a/net/sysctl_net.c b/net/sysctl_net.c
index cd4eafb..4733d85 100644
--- a/net/sysctl_net.c
+++ b/net/sysctl_net.c
@@ -17,10 +17,6 @@
 
 #include <net/sock.h>
 
-#ifdef CONFIG_INET
-#include <net/ip.h>
-#endif
-
 #ifdef CONFIG_NET
 #include <linux/if_ether.h>
 #endif
@@ -36,14 +32,6 @@ struct ctl_table net_table[] = {
 		.mode		= 0555,
 		.child		= core_table,
 	},
-#ifdef CONFIG_INET
-	{
-		.ctl_name	= NET_IPV4,
-		.procname	= "ipv4",
-		.mode		= 0555,
-		.child		= ipv4_table
-	},
-#endif
 #ifdef CONFIG_TR
 	{
 		.ctl_name	= NET_TR,
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 5c46958..d3d4eee 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -78,7 +78,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
 }
 EXPORT_SYMBOL(xfrm_parse_spi);
 
-void __init xfrm_input_init(void)
+void xfrm_input_init(void)
 {
 	secpath_cachep = kmem_cache_create("secpath_cache",
 					   sizeof(struct sec_path),
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b48f06f..933b6ed 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1780,6 +1780,9 @@ static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp
 	return 0;
 }
 
+void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
+EXPORT_SYMBOL(ip_nat_decode_session);
+
 int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
 			unsigned short family)
 {
@@ -2370,7 +2373,7 @@ static struct notifier_block xfrm_dev_notifier = {
 	0
 };
 
-static void __init xfrm_policy_init(void)
+static void xfrm_policy_init(void)
 {
 	unsigned int hmask, sz;
 	int dir;
@@ -2404,12 +2407,13 @@ static void __init xfrm_policy_init(void)
 	register_netdevice_notifier(&xfrm_dev_notifier);
 }
 
-void __init xfrm_init(void)
+void xfrm_init(void)
 {
 	xfrm_state_init();
 	xfrm_policy_init();
 	xfrm_input_init();
 }
+EXPORT_SYMBOL(xfrm_init);
 
 #ifdef CONFIG_XFRM_MIGRATE
 static int xfrm_migrate_selector_match(struct xfrm_selector *sel_cmp,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index dfacb9c..02427ed 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -1775,7 +1775,7 @@ error:
 
 EXPORT_SYMBOL(xfrm_init_state);
 
-void __init xfrm_state_init(void)
+void xfrm_state_init(void)
 {
 	unsigned int sz;
 
-- 
1.5.2.5


