aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2007-06-27 02:56:32 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:15:42 -0400
commit59fbb3a61e02deaeaa4fb50792217921f3002d64 (patch)
tree7455815c2566ba9b898cd6ea2c710159bbeb624f
parent136ebf08b46f839e2dc9db34322b654e5d9b9936 (diff)
[IPV6] MIP6: Loadable module support for MIPv6.
This patch makes MIPv6 loadable module named "mip6". Here is a modprobe.conf(5) example to load it automatically when user application uses XFRM state for MIPv6: alias xfrm-type-10-43 mip6 alias xfrm-type-10-60 mip6 Some MIPv6 feature is not included by this modular, however, it should not be affected to other features like either IPsec or IPv6 with and without the patch. We may discuss XFRM, MH (RAW socket) and ancillary data/sockopt separately for future work. Loadable features: * MH receiving check (to send ICMP error back) * RO header parsing and building (i.e. RH2 and HAO in DSTOPTS) * XFRM policy/state database handling for RO These are NOT covered as loadable: * Home Address flags and its rule on source address selection * XFRM sub policy (depends on its own kernel option) * XFRM functions to receive RO as IPv6 extension header * MH sending/receiving through raw socket if user application opens it (since raw socket allows to do so) * RH2 sending as ancillary data * RH2 operation with setsockopt(2) Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/ipv6.h2
-rw-r--r--include/net/addrconf.h2
-rw-r--r--include/net/mip6.h4
-rw-r--r--include/net/rawv6.h9
-rw-r--r--net/ipv6/Kconfig2
-rw-r--r--net/ipv6/Makefile2
-rw-r--r--net/ipv6/addrconf.c4
-rw-r--r--net/ipv6/af_inet6.c10
-rw-r--r--net/ipv6/ah6.c8
-rw-r--r--net/ipv6/datagram.c2
-rw-r--r--net/ipv6/exthdrs.c19
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/mip6.c22
-rw-r--r--net/ipv6/raw.c34
-rw-r--r--net/ipv6/xfrm6_policy.c4
-rw-r--r--net/ipv6/xfrm6_state.c4
18 files changed, 88 insertions, 46 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 648bd1f0912d..213b63be3c8f 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -247,7 +247,7 @@ struct inet6_skb_parm {
247 __u16 lastopt; 247 __u16 lastopt;
248 __u32 nhoff; 248 __u32 nhoff;
249 __u16 flags; 249 __u16 flags;
250#ifdef CONFIG_IPV6_MIP6 250#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
251 __u16 dsthao; 251 __u16 dsthao;
252#endif 252#endif
253 253
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f3531d0bcd05..33b593e17441 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -61,7 +61,7 @@ extern int addrconf_set_dstaddr(void __user *arg);
61extern int ipv6_chk_addr(struct in6_addr *addr, 61extern int ipv6_chk_addr(struct in6_addr *addr,
62 struct net_device *dev, 62 struct net_device *dev,
63 int strict); 63 int strict);
64#ifdef CONFIG_IPV6_MIP6 64#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
65extern int ipv6_chk_home_addr(struct in6_addr *addr); 65extern int ipv6_chk_home_addr(struct in6_addr *addr);
66#endif 66#endif
67extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, 67extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr,
diff --git a/include/net/mip6.h b/include/net/mip6.h
index 68263c6d9996..63272610a24a 100644
--- a/include/net/mip6.h
+++ b/include/net/mip6.h
@@ -54,8 +54,4 @@ struct ip6_mh {
54#define IP6_MH_TYPE_BERROR 7 /* Binding Error */ 54#define IP6_MH_TYPE_BERROR 7 /* Binding Error */
55#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR 55#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
56 56
57extern int mip6_init(void);
58extern void mip6_fini(void);
59extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb);
60
61#endif 57#endif
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index af8960878ef4..a5819891d525 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -3,6 +3,8 @@
3 3
4#ifdef __KERNEL__ 4#ifdef __KERNEL__
5 5
6#include <net/protocol.h>
7
6#define RAWV6_HTABLE_SIZE MAX_INET_PROTOS 8#define RAWV6_HTABLE_SIZE MAX_INET_PROTOS
7extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; 9extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
8extern rwlock_t raw_v6_lock; 10extern rwlock_t raw_v6_lock;
@@ -23,6 +25,13 @@ extern void rawv6_err(struct sock *sk,
23 int type, int code, 25 int type, int code,
24 int offset, __be32 info); 26 int offset, __be32 info);
25 27
28#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
29int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
30 struct sk_buff *skb));
31int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
32 struct sk_buff *skb));
33#endif
34
26#endif 35#endif
27 36
28#endif 37#endif
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 8e5d54f23b49..eb0b8085949b 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -109,7 +109,7 @@ config INET6_IPCOMP
109 If unsure, say Y. 109 If unsure, say Y.
110 110
111config IPV6_MIP6 111config IPV6_MIP6
112 bool "IPv6: Mobility (EXPERIMENTAL)" 112 tristate "IPv6: Mobility (EXPERIMENTAL)"
113 depends on IPV6 && EXPERIMENTAL 113 depends on IPV6 && EXPERIMENTAL
114 select XFRM 114 select XFRM
115 ---help--- 115 ---help---
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index bb33309044c9..87c23a73d284 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -14,7 +14,6 @@ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \
14 xfrm6_output.o 14 xfrm6_output.o
15ipv6-$(CONFIG_NETFILTER) += netfilter.o 15ipv6-$(CONFIG_NETFILTER) += netfilter.o
16ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o 16ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o
17ipv6-$(CONFIG_IPV6_MIP6) += mip6.o
18ipv6-$(CONFIG_PROC_FS) += proc.o 17ipv6-$(CONFIG_PROC_FS) += proc.o
19 18
20ipv6-objs += $(ipv6-y) 19ipv6-objs += $(ipv6-y)
@@ -28,6 +27,7 @@ obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
28obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o 27obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
29obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o 28obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
30obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o 29obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
30obj-$(CONFIG_IPV6_MIP6) += mip6.o
31obj-$(CONFIG_NETFILTER) += netfilter/ 31obj-$(CONFIG_NETFILTER) += netfilter/
32 32
33obj-$(CONFIG_IPV6_SIT) += sit.o 33obj-$(CONFIG_IPV6_SIT) += sit.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 79b79f3de24c..11c0028863b0 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1034,7 +1034,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
1034 } 1034 }
1035 1035
1036 /* Rule 4: Prefer home address */ 1036 /* Rule 4: Prefer home address */
1037#ifdef CONFIG_IPV6_MIP6 1037#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
1038 if (hiscore.rule < 4) { 1038 if (hiscore.rule < 4) {
1039 if (ifa_result->flags & IFA_F_HOMEADDRESS) 1039 if (ifa_result->flags & IFA_F_HOMEADDRESS)
1040 hiscore.attrs |= IPV6_SADDR_SCORE_HOA; 1040 hiscore.attrs |= IPV6_SADDR_SCORE_HOA;
@@ -2835,7 +2835,7 @@ void if6_proc_exit(void)
2835} 2835}
2836#endif /* CONFIG_PROC_FS */ 2836#endif /* CONFIG_PROC_FS */
2837 2837
2838#ifdef CONFIG_IPV6_MIP6 2838#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
2839/* Check if address is a home address configured on any interface. */ 2839/* Check if address is a home address configured on any interface. */
2840int ipv6_chk_home_addr(struct in6_addr *addr) 2840int ipv6_chk_home_addr(struct in6_addr *addr)
2841{ 2841{
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 6dd377253cf7..eed09373a45d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -58,9 +58,6 @@
58#ifdef CONFIG_IPV6_TUNNEL 58#ifdef CONFIG_IPV6_TUNNEL
59#include <net/ip6_tunnel.h> 59#include <net/ip6_tunnel.h>
60#endif 60#endif
61#ifdef CONFIG_IPV6_MIP6
62#include <net/mip6.h>
63#endif
64 61
65#include <asm/uaccess.h> 62#include <asm/uaccess.h>
66#include <asm/system.h> 63#include <asm/system.h>
@@ -853,9 +850,6 @@ static int __init inet6_init(void)
853 ipv6_frag_init(); 850 ipv6_frag_init();
854 ipv6_nodata_init(); 851 ipv6_nodata_init();
855 ipv6_destopt_init(); 852 ipv6_destopt_init();
856#ifdef CONFIG_IPV6_MIP6
857 mip6_init();
858#endif
859 853
860 /* Init v6 transport protocols. */ 854 /* Init v6 transport protocols. */
861 udpv6_init(); 855 udpv6_init();
@@ -921,9 +915,7 @@ static void __exit inet6_exit(void)
921 915
922 /* Cleanup code parts. */ 916 /* Cleanup code parts. */
923 ipv6_packet_cleanup(); 917 ipv6_packet_cleanup();
924#ifdef CONFIG_IPV6_MIP6 918
925 mip6_fini();
926#endif
927 addrconf_cleanup(); 919 addrconf_cleanup();
928 ip6_flowlabel_cleanup(); 920 ip6_flowlabel_cleanup();
929 ip6_route_cleanup(); 921 ip6_route_cleanup();
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 01fa302d281e..cc6884a40be4 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -74,7 +74,7 @@ bad:
74 return 0; 74 return 0;
75} 75}
76 76
77#ifdef CONFIG_IPV6_MIP6 77#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
78/** 78/**
79 * ipv6_rearrange_destopt - rearrange IPv6 destination options header 79 * ipv6_rearrange_destopt - rearrange IPv6 destination options header
80 * @iph: IPv6 header 80 * @iph: IPv6 header
@@ -228,7 +228,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
228 u8 nexthdr; 228 u8 nexthdr;
229 char tmp_base[8]; 229 char tmp_base[8];
230 struct { 230 struct {
231#ifdef CONFIG_IPV6_MIP6 231#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
232 struct in6_addr saddr; 232 struct in6_addr saddr;
233#endif 233#endif
234 struct in6_addr daddr; 234 struct in6_addr daddr;
@@ -255,7 +255,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
255 err = -ENOMEM; 255 err = -ENOMEM;
256 goto error; 256 goto error;
257 } 257 }
258#ifdef CONFIG_IPV6_MIP6 258#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
259 memcpy(tmp_ext, &top_iph->saddr, extlen); 259 memcpy(tmp_ext, &top_iph->saddr, extlen);
260#else 260#else
261 memcpy(tmp_ext, &top_iph->daddr, extlen); 261 memcpy(tmp_ext, &top_iph->daddr, extlen);
@@ -294,7 +294,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
294 294
295 memcpy(top_iph, tmp_base, sizeof(tmp_base)); 295 memcpy(top_iph, tmp_base, sizeof(tmp_base));
296 if (tmp_ext) { 296 if (tmp_ext) {
297#ifdef CONFIG_IPV6_MIP6 297#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
298 memcpy(&top_iph->saddr, tmp_ext, extlen); 298 memcpy(&top_iph->saddr, tmp_ext, extlen);
299#else 299#else
300 memcpy(&top_iph->daddr, tmp_ext, extlen); 300 memcpy(&top_iph->daddr, tmp_ext, extlen);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index b1fe7ac5dc90..ba1386dd4168 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -658,7 +658,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
658 658
659 switch (rthdr->type) { 659 switch (rthdr->type) {
660 case IPV6_SRCRT_TYPE_0: 660 case IPV6_SRCRT_TYPE_0:
661#ifdef CONFIG_IPV6_MIP6 661#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
662 case IPV6_SRCRT_TYPE_2: 662 case IPV6_SRCRT_TYPE_2:
663#endif 663#endif
664 break; 664 break;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 14be0b9b77a5..173a4bb52255 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -42,7 +42,7 @@
42#include <net/ndisc.h> 42#include <net/ndisc.h>
43#include <net/ip6_route.h> 43#include <net/ip6_route.h>
44#include <net/addrconf.h> 44#include <net/addrconf.h>
45#ifdef CONFIG_IPV6_MIP6 45#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
46#include <net/xfrm.h> 46#include <net/xfrm.h>
47#endif 47#endif
48 48
@@ -90,6 +90,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
90 bad: 90 bad:
91 return -1; 91 return -1;
92} 92}
93EXPORT_SYMBOL_GPL(ipv6_find_tlv);
93 94
94/* 95/*
95 * Parsing tlv encoded headers. 96 * Parsing tlv encoded headers.
@@ -196,7 +197,7 @@ bad:
196 Destination options header. 197 Destination options header.
197 *****************************/ 198 *****************************/
198 199
199#ifdef CONFIG_IPV6_MIP6 200#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
200static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) 201static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
201{ 202{
202 struct sk_buff *skb = *skbp; 203 struct sk_buff *skb = *skbp;
@@ -270,7 +271,7 @@ static int ipv6_dest_hao(struct sk_buff **skbp, int optoff)
270#endif 271#endif
271 272
272static struct tlvtype_proc tlvprocdestopt_lst[] = { 273static struct tlvtype_proc tlvprocdestopt_lst[] = {
273#ifdef CONFIG_IPV6_MIP6 274#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
274 { 275 {
275 .type = IPV6_TLV_HAO, 276 .type = IPV6_TLV_HAO,
276 .func = ipv6_dest_hao, 277 .func = ipv6_dest_hao,
@@ -283,7 +284,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
283{ 284{
284 struct sk_buff *skb = *skbp; 285 struct sk_buff *skb = *skbp;
285 struct inet6_skb_parm *opt = IP6CB(skb); 286 struct inet6_skb_parm *opt = IP6CB(skb);
286#ifdef CONFIG_IPV6_MIP6 287#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
287 __u16 dstbuf; 288 __u16 dstbuf;
288#endif 289#endif
289 struct dst_entry *dst; 290 struct dst_entry *dst;
@@ -298,7 +299,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
298 } 299 }
299 300
300 opt->lastopt = opt->dst1 = skb_network_header_len(skb); 301 opt->lastopt = opt->dst1 = skb_network_header_len(skb);
301#ifdef CONFIG_IPV6_MIP6 302#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
302 dstbuf = opt->dst1; 303 dstbuf = opt->dst1;
303#endif 304#endif
304 305
@@ -308,7 +309,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp)
308 skb = *skbp; 309 skb = *skbp;
309 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; 310 skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
310 opt = IP6CB(skb); 311 opt = IP6CB(skb);
311#ifdef CONFIG_IPV6_MIP6 312#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
312 opt->nhoff = dstbuf; 313 opt->nhoff = dstbuf;
313#else 314#else
314 opt->nhoff = opt->dst1; 315 opt->nhoff = opt->dst1;
@@ -427,7 +428,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
427looped_back: 428looped_back:
428 if (hdr->segments_left == 0) { 429 if (hdr->segments_left == 0) {
429 switch (hdr->type) { 430 switch (hdr->type) {
430#ifdef CONFIG_IPV6_MIP6 431#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
431 case IPV6_SRCRT_TYPE_2: 432 case IPV6_SRCRT_TYPE_2:
432 /* Silently discard type 2 header unless it was 433 /* Silently discard type 2 header unless it was
433 * processed by own 434 * processed by own
@@ -463,7 +464,7 @@ looped_back:
463 return -1; 464 return -1;
464 } 465 }
465 break; 466 break;
466#ifdef CONFIG_IPV6_MIP6 467#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
467 case IPV6_SRCRT_TYPE_2: 468 case IPV6_SRCRT_TYPE_2:
468 /* Silently discard invalid RTH type 2 */ 469 /* Silently discard invalid RTH type 2 */
469 if (hdr->hdrlen != 2 || hdr->segments_left != 1) { 470 if (hdr->hdrlen != 2 || hdr->segments_left != 1) {
@@ -520,7 +521,7 @@ looped_back:
520 addr += i - 1; 521 addr += i - 1;
521 522
522 switch (hdr->type) { 523 switch (hdr->type) {
523#ifdef CONFIG_IPV6_MIP6 524#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
524 case IPV6_SRCRT_TYPE_2: 525 case IPV6_SRCRT_TYPE_2:
525 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, 526 if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
526 (xfrm_address_t *)&ipv6_hdr(skb)->saddr, 527 (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index e9bcce9e7bdf..4765a29f98a8 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -272,7 +272,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
272 return 0; 272 return 0;
273} 273}
274 274
275#ifdef CONFIG_IPV6_MIP6 275#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
276static void mip6_addr_swap(struct sk_buff *skb) 276static void mip6_addr_swap(struct sk_buff *skb)
277{ 277{
278 struct ipv6hdr *iph = ipv6_hdr(skb); 278 struct ipv6hdr *iph = ipv6_hdr(skb);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4704b5fc3085..31dafaf0b652 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -543,7 +543,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
543 found_rhdr = 1; 543 found_rhdr = 1;
544 break; 544 break;
545 case NEXTHDR_DEST: 545 case NEXTHDR_DEST:
546#ifdef CONFIG_IPV6_MIP6 546#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
547 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) 547 if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
548 break; 548 break;
549#endif 549#endif
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index aa3d07c52a8f..b636c38411fb 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -417,7 +417,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
417 struct ipv6_rt_hdr *rthdr = opt->srcrt; 417 struct ipv6_rt_hdr *rthdr = opt->srcrt;
418 switch (rthdr->type) { 418 switch (rthdr->type) {
419 case IPV6_SRCRT_TYPE_0: 419 case IPV6_SRCRT_TYPE_0:
420#ifdef CONFIG_IPV6_MIP6 420#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
421 case IPV6_SRCRT_TYPE_2: 421 case IPV6_SRCRT_TYPE_2:
422#endif 422#endif
423 break; 423 break;
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 13b7160fb892..20c78ecff6a1 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -30,6 +30,7 @@
30#include <net/sock.h> 30#include <net/sock.h>
31#include <net/ipv6.h> 31#include <net/ipv6.h>
32#include <net/ip6_checksum.h> 32#include <net/ip6_checksum.h>
33#include <net/rawv6.h>
33#include <net/xfrm.h> 34#include <net/xfrm.h>
34#include <net/mip6.h> 35#include <net/mip6.h>
35 36
@@ -86,7 +87,7 @@ static int mip6_mh_len(int type)
86 return len; 87 return len;
87} 88}
88 89
89int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) 90static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
90{ 91{
91 struct ip6_mh *mh; 92 struct ip6_mh *mh;
92 93
@@ -471,7 +472,7 @@ static struct xfrm_type mip6_rthdr_type =
471 .remote_addr = mip6_xfrm_addr, 472 .remote_addr = mip6_xfrm_addr,
472}; 473};
473 474
474int __init mip6_init(void) 475static int __init mip6_init(void)
475{ 476{
476 printk(KERN_INFO "Mobile IPv6\n"); 477 printk(KERN_INFO "Mobile IPv6\n");
477 478
@@ -483,18 +484,33 @@ int __init mip6_init(void)
483 printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); 484 printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__);
484 goto mip6_rthdr_xfrm_fail; 485 goto mip6_rthdr_xfrm_fail;
485 } 486 }
487 if (rawv6_mh_filter_register(mip6_mh_filter) < 0) {
488 printk(KERN_INFO "%s: can't add rawv6 mh filter\n", __FUNCTION__);
489 goto mip6_rawv6_mh_fail;
490 }
491
492
486 return 0; 493 return 0;
487 494
495 mip6_rawv6_mh_fail:
496 xfrm_unregister_type(&mip6_rthdr_type, AF_INET6);
488 mip6_rthdr_xfrm_fail: 497 mip6_rthdr_xfrm_fail:
489 xfrm_unregister_type(&mip6_destopt_type, AF_INET6); 498 xfrm_unregister_type(&mip6_destopt_type, AF_INET6);
490 mip6_destopt_xfrm_fail: 499 mip6_destopt_xfrm_fail:
491 return -EAGAIN; 500 return -EAGAIN;
492} 501}
493 502
494void __exit mip6_fini(void) 503static void __exit mip6_fini(void)
495{ 504{
505 if (rawv6_mh_filter_unregister(mip6_mh_filter) < 0)
506 printk(KERN_INFO "%s: can't remove rawv6 mh filter\n", __FUNCTION__);
496 if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) 507 if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0)
497 printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); 508 printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__);
498 if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) 509 if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0)
499 printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); 510 printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__);
500} 511}
512
513module_init(mip6_init);
514module_exit(mip6_fini);
515
516MODULE_LICENSE("GPL");
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a22c9c93d931..aac6aeb8de8c 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -49,7 +49,7 @@
49#include <net/udp.h> 49#include <net/udp.h>
50#include <net/inet_common.h> 50#include <net/inet_common.h>
51#include <net/tcp_states.h> 51#include <net/tcp_states.h>
52#ifdef CONFIG_IPV6_MIP6 52#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
53#include <net/mip6.h> 53#include <net/mip6.h>
54#endif 54#endif
55 55
@@ -137,6 +137,28 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
137 return 0; 137 return 0;
138} 138}
139 139
140#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
141static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
142
143int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
144 struct sk_buff *skb))
145{
146 rcu_assign_pointer(mh_filter, filter);
147 return 0;
148}
149EXPORT_SYMBOL(rawv6_mh_filter_register);
150
151int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
152 struct sk_buff *skb))
153{
154 rcu_assign_pointer(mh_filter, NULL);
155 synchronize_rcu();
156 return 0;
157}
158EXPORT_SYMBOL(rawv6_mh_filter_unregister);
159
160#endif
161
140/* 162/*
141 * demultiplex raw sockets. 163 * demultiplex raw sockets.
142 * (should consider queueing the skb in the sock receive_queue 164 * (should consider queueing the skb in the sock receive_queue
@@ -178,16 +200,22 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
178 case IPPROTO_ICMPV6: 200 case IPPROTO_ICMPV6:
179 filtered = icmpv6_filter(sk, skb); 201 filtered = icmpv6_filter(sk, skb);
180 break; 202 break;
181#ifdef CONFIG_IPV6_MIP6 203
204#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
182 case IPPROTO_MH: 205 case IPPROTO_MH:
206 {
183 /* XXX: To validate MH only once for each packet, 207 /* XXX: To validate MH only once for each packet,
184 * this is placed here. It should be after checking 208 * this is placed here. It should be after checking
185 * xfrm policy, however it doesn't. The checking xfrm 209 * xfrm policy, however it doesn't. The checking xfrm
186 * policy is placed in rawv6_rcv() because it is 210 * policy is placed in rawv6_rcv() because it is
187 * required for each socket. 211 * required for each socket.
188 */ 212 */
189 filtered = mip6_mh_filter(sk, skb); 213 int (*filter)(struct sock *sock, struct sk_buff *skb);
214
215 filter = rcu_dereference(mh_filter);
216 filtered = filter ? filter(sk, skb) : 0;
190 break; 217 break;
218 }
191#endif 219#endif
192 default: 220 default:
193 filtered = 0; 221 filtered = 0;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 1faa2ea80afc..3ec0c4770ee3 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -18,7 +18,7 @@
18#include <net/ip.h> 18#include <net/ip.h>
19#include <net/ipv6.h> 19#include <net/ipv6.h>
20#include <net/ip6_route.h> 20#include <net/ip6_route.h>
21#ifdef CONFIG_IPV6_MIP6 21#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
22#include <net/mip6.h> 22#include <net/mip6.h>
23#endif 23#endif
24 24
@@ -318,7 +318,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl)
318 fl->proto = nexthdr; 318 fl->proto = nexthdr;
319 return; 319 return;
320 320
321#ifdef CONFIG_IPV6_MIP6 321#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
322 case IPPROTO_MH: 322 case IPPROTO_MH:
323 if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) { 323 if (pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
324 struct ip6_mh *mh; 324 struct ip6_mh *mh;
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index baa461b9f74e..cdadb4847469 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -65,7 +65,7 @@ __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
65 goto end; 65 goto end;
66 66
67 /* Rule 2: select MIPv6 RO or inbound trigger */ 67 /* Rule 2: select MIPv6 RO or inbound trigger */
68#ifdef CONFIG_IPV6_MIP6 68#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
69 for (i = 0; i < n; i++) { 69 for (i = 0; i < n; i++) {
70 if (src[i] && 70 if (src[i] &&
71 (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || 71 (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION ||
@@ -130,7 +130,7 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
130 goto end; 130 goto end;
131 131
132 /* Rule 2: select MIPv6 RO or inbound trigger */ 132 /* Rule 2: select MIPv6 RO or inbound trigger */
133#ifdef CONFIG_IPV6_MIP6 133#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
134 for (i = 0; i < n; i++) { 134 for (i = 0; i < n; i++) {
135 if (src[i] && 135 if (src[i] &&
136 (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || 136 (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION ||