diff -Nur mipv6-daemon-umip-0.3/AUTHORS mipv6-daemon-umip-0.3-nepl/AUTHORS --- mipv6-daemon-umip-0.3/AUTHORS 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/AUTHORS 2007-06-13 11:01:14.000000000 +0200 @@ -5,3 +5,7 @@ Petander. Code has been contributed by several individuals. See THANKS for listing. See libnetlink/README for information regarding libnetlink. + +The NEMO Basic support code is developed by Ville Nuorvala + in co-operation with the Nautilus6/WIDE +project (http://www.nautilus6.org). diff -Nur mipv6-daemon-umip-0.3/BUGS mipv6-daemon-umip-0.3-nepl/BUGS --- mipv6-daemon-umip-0.3/BUGS 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/BUGS 2007-06-13 11:01:14.000000000 +0200 @@ -17,3 +17,11 @@ * Multihoming support hasn't been very thoroughly tested and should therefore be considered developmental code. However, it is a lot more stable than in the Release Candidates. + +NEMO issues +----------- + +* The Mobile Router's home address may only be on the egress interface. + +* Dynamic routing protocols between the Home Agent and Mobile Router + are not yet supported. diff -Nur mipv6-daemon-umip-0.3/COPYING.NEMO mipv6-daemon-umip-0.3-nepl/COPYING.NEMO --- mipv6-daemon-umip-0.3/COPYING.NEMO 1970-01-01 01:00:00.000000000 +0100 +++ mipv6-daemon-umip-0.3-nepl/COPYING.NEMO 2007-06-13 11:01:14.000000000 +0200 @@ -0,0 +1,12 @@ +Cisco and Nokia have both published IPR notices regarding RFC 3963 +"Network Mobility (NEMO) Basic Support Protocol." + +Cisco has agreed not to assert its patents against any party agreeing with the +terms in its IPR notice. + +Likewise, Nokia has agreed not to assert its patents against Open Source +implementations of the specification. + +For further information, please read +licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt and +licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt. diff -Nur mipv6-daemon-umip-0.3/extras/example-nemo-ha.conf mipv6-daemon-umip-0.3-nepl/extras/example-nemo-ha.conf --- mipv6-daemon-umip-0.3/extras/example-nemo-ha.conf 1970-01-01 01:00:00.000000000 +0100 +++ mipv6-daemon-umip-0.3-nepl/extras/example-nemo-ha.conf 2007-06-13 11:01:14.000000000 +0200 @@ -0,0 +1,86 @@ +# This is an example of NEMO-enabled Home Agent configuration file + +NodeConfig HA; + +## If set to > 0, will not detach from tty +DebugLevel 10; + +## List of interfaces where we serve as Home Agent +Interface "eth0"; +#Interface "eth1"; + +HaAcceptMobRtr enabled; + +HaServedPrefix 3ffe:2620:6::/48; + +DefaultBindingAclPolicy deny; + +BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) allow; +BindingAclPolicy 3ffe:2620:6:1::1235 allow; + + +## +## IPsec configuration +## + +UseMnHaIPsec enabled; + +## Key Management Mobility Capability +#KeyMngMobCapability disabled; + +IPsecPolicySet { + HomeAgentAddress 3ffe:2620:6:1::1; + + HomeAddress 3ffe:2620:6:1::1234/64; + HomeAddress 3ffe:2620:6:1::1235/64; + + IPsecPolicy Mh UseESP; + IPsecPolicy TunnelMh UseESP; + +# IPsecPolicy Mh UseESP 1 2; +# IPsecPolicy ICMP UseESP 5; +# IPsecPolicy TunnelMh UseESP 3 4; +} + +## +## It is possible to specify multiple IPsecPolicySet in order to configure +## different value for such address. +#IPsecPolicySet { +# +## One HA is for one IPsecPolicySet. +# HomeAgentAddress 3ffe:2620:6:1::1; +# +## It is possible to specify multiple home addresses when they use +## the same configuration. +# HomeAddress 3ffe:2620:6:1::1236/64; +# HomeAddress 3ffe:2620:6:1::1237/64; +# +## IPsec protocol syntax: IPsecPolicy TYPE IPSEC_PROTO [ REQID_SET ] [ ACTION ] +## TYPE (for transport) := Mh | HomeRegBinding | ICMP | MobPfxDisc | any +## TYPE (for tunnel) := TunnelMh | TunnelHomeTesting | TunnelPayload +## IPSEC_PROTO := UseESP (UseAH and UseIPCOMP aren't currently supported) +## REQID_SET := REQID(both-dir) | REQID(to-HA-dir) REQID(to-MN-dir) +## +## REQID is a number. "to-HA-dir" is for packet from MN to HA e.g. +## BU, MPS, or HoTI (it depends on TYPE). +## REQID should be used when more than one configuration for transport +## and tunnel respectively. The default value is zero. +# +## Transport MH protection +# IPsecPolicy Mh UseESP 1 2; +# ## To protect only BU/BA exactly in MH, use below instead. +# #IPsecPolicy HomeRegBinding UseESP 1 2; +# +## Transport ICMP protection +# IPsecPolicy ICMP UseESP 5 6; +# ## To protect only MPD exactly in ICMP, use below instead. +# #IPsecPolicy MobPfxDisc UseESP 5 6; +# +## Tunnel HoTI/HoT protection +# IPsecPolicy TunnelMh UseESP 3 4; +# ## To protect only HoTI/HoT exactly in MH, use below instead. +# #IPsecPolicy TunnelHomeTesting UseESP 3 4; +# +## Tunnel payload protection +# #IPsecPolicy TunnelPayload UseESP 7 8; +#} diff -Nur mipv6-daemon-umip-0.3/extras/example-nemo-mn.conf mipv6-daemon-umip-0.3-nepl/extras/example-nemo-mn.conf --- mipv6-daemon-umip-0.3/extras/example-nemo-mn.conf 1970-01-01 01:00:00.000000000 +0100 +++ mipv6-daemon-umip-0.3-nepl/extras/example-nemo-mn.conf 2007-06-13 11:01:14.000000000 +0200 @@ -0,0 +1,51 @@ +# This is an example of NEMO Mobile Router configuration file + +NodeConfig MN; + +## If set to > 0, will not detach from tty +DebugLevel 10; + +## Support route optimization with other MNs +DoRouteOptimizationCN enabled; + +## Use route optimization with CNs +DoRouteOptimizationMN enabled; + +UseCnBuAck disabled; + +MnDiscardHaParamProb enabled; + +Interface "eth0"; + +#Interface "eth1" { +# MnIfPreference 2; +#} + +MnRouterProbes 1; + +MnHomeLink "eth0" { + IsMobRtr enabled; + HomeAgentAddress 3ffe:2620:6:1::1; + HomeAddress 3ffe:2620:6:1::1234/64 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64); +} + +## +## IPsec configuration +## + +UseMnHaIPsec enabled; + +## Key Management Mobility Capability +KeyMngMobCapability disabled; + +IPsecPolicySet { + HomeAgentAddress 3ffe:2620:6:1::1; + HomeAddress 3ffe:2620:6:1::1234/64; + + IPsecPolicy Mh UseESP; + IPsecPolicy TunnelMh UseESP; + +# IPsecPolicy Mh UseESP 1 2; +# IPsecPolicy ICMP UseESP 5; +# IPsecPolicy TunnelMh UseESP 3 4; +} diff -Nur mipv6-daemon-umip-0.3/include/netinet/icmp6.h mipv6-daemon-umip-0.3-nepl/include/netinet/icmp6.h --- mipv6-daemon-umip-0.3/include/netinet/icmp6.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/include/netinet/icmp6.h 2007-06-13 11:01:14.000000000 +0200 @@ -27,7 +27,13 @@ #define mip_dhreq_code mip_dhreq_hdr.icmp6_code #define mip_dhreq_cksum mip_dhreq_hdr.icmp6_cksum #define mip_dhreq_id mip_dhreq_hdr.icmp6_data16[0] -#define mip_dhreq_reserved mip_dhreq_hdr.icmp6_data16[1] +#define mip_dhreq_flags_reserved mip_dhreq_hdr.icmp6_data16[1] + +#if BYTE_ORDER == BIG_ENDIAN +#define MIP_DHREQ_FLAG_SUPPORT_MR 0x8000 +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define MIP_DHREQ_FLAG_SUPPORT_MR 0x0080 +#endif #endif #ifndef HAVE_STRUCT_MIP_DHAAD_REP @@ -40,7 +46,13 @@ #define mip_dhrep_code mip_dhrep_hdr.icmp6_code #define mip_dhrep_cksum mip_dhrep_hdr.icmp6_cksum #define mip_dhrep_id mip_dhrep_hdr.icmp6_data16[0] -#define mip_dhrep_reserved mip_dhrep_hdr.icmp6_data16[1] +#define mip_dhrep_flags_reserved mip_dhrep_hdr.icmp6_data16[1] + +#if BYTE_ORDER == BIG_ENDIAN +#define MIP_DHREP_FLAG_SUPPORT_MR 0x8000 +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define MIP_DHREP_FLAG_SUPPORT_MR 0x0080 +#endif #endif #ifndef HAVE_STRUCT_MIP_PREFIX_SOLICIT @@ -89,10 +101,20 @@ struct nd_opt_homeagent_info { /* Home Agent information */ uint8_t nd_opt_hai_type; uint8_t nd_opt_hai_len; - uint16_t nd_opt_hai_reserved; + uint16_t nd_opt_hai_flags_reserved; uint16_t nd_opt_hai_preference; uint16_t nd_opt_hai_lifetime; }; #endif +#define nd_opt_hai_reserved nd_opt_hai_flags_reserved + +#ifndef ND_OPT_HAI_FLAG_SUPPORT_MR +#if BYTE_ORDER == BIG_ENDIAN +#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x8000 +#else /* BYTE_ORDER == LITTLE_ENDIAN */ +#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x0080 +#endif +#endif + #endif /* netinet/icmp6.h */ diff -Nur mipv6-daemon-umip-0.3/INSTALL mipv6-daemon-umip-0.3-nepl/INSTALL --- mipv6-daemon-umip-0.3/INSTALL 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/INSTALL 2007-06-13 11:01:14.000000000 +0200 @@ -45,6 +45,8 @@ further information on how to configure your node. Also take a look at the example configuration files in the extras directory. + For comments about NEMO check README.NEMO. + For comments about IPsec support check README.IPsec. 5. A startup script diff -Nur mipv6-daemon-umip-0.3/licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt mipv6-daemon-umip-0.3-nepl/licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt --- mipv6-daemon-umip-0.3/licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt 1970-01-01 01:00:00.000000000 +0100 +++ mipv6-daemon-umip-0.3-nepl/licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt 2007-06-13 11:01:14.000000000 +0200 @@ -0,0 +1,41 @@ +Title: Cisco Systems' Updated Statement about IPR claimed in + draft-ietf-nemo-basic-support-03.txt +Received 25 October 2004 +From: Robert Barr + +This statement updates the IPR statement filed by Cisco on June 20, 2003 for +draft-ietf-nemo-basic-support-00.txt. + +Cisco is the owner of US Patent No. 6,636,498 and at least one pending +patent application +relating to the subject matter of draft-ietf-nemo-basic-support-03.txt +"Network Mobility (NEMO) Basic Support Protocol" . +If a standard relating to this subject matter is adopted by IETF and any +claims +of any issued Cisco patents are necessary for practicing this standard, any +party will be able to obtain a license from Cisco to use any such patent +claims under openly specified, reasonable, non-discriminatory terms, with +reciprocity, to implement and fully comply with the standard. + +The reasonable non-discriminatory terms are: + +If this standard is adopted, Cisco will not assert any patents owned or +controlled by Cisco against any party for making, using, selling, importing +or offering for sale a product that implements the standard, provided, +however that Cisco retains the right to assert its patents (including the +right to claim past royalties) against any party that asserts a patent it +owns or controls (either directly or indirectly) against Cisco or any of +Cisco's affiliates or successors in title; and Cisco retains the right to +assert its patents against any product or portion thereof that is not +necessary for compliance with the standard. + +Royalty-bearing licenses will be available to anyone who prefers that +option. + +For information contact: + +Robert Barr +Worldwide Patent Counsel +Cisco Systems +408-525-9706 +rbarr@cisco.com diff -Nur mipv6-daemon-umip-0.3/licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt mipv6-daemon-umip-0.3-nepl/licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt --- mipv6-daemon-umip-0.3/licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt 1970-01-01 01:00:00.000000000 +0100 +++ mipv6-daemon-umip-0.3-nepl/licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt 2007-06-13 11:01:14.000000000 +0200 @@ -0,0 +1,26 @@ +Title: Nokia Corporation's statement about IPR claimed in draft-ietf-nemo-basic-support +Received: July 1, 2003 +From: Heikki Huttunen + +This is to advise the IETF that Nokia believes the Nokia patent application "Mobile Router +Support for IPv6", US10/295014, WO03/043226 may be relevant to Nemo Basic Support Protocol +. + +Regarding internet draft "draft-ietf-nemo-basic-support", to the extent this draft is +included into final IETF standard specification, Nokia agrees not to assert those claims +in Nokia patents that apply to this draft and that are technically necessary to implement +the IETF standard specification against any other party in respect of its implementation of +the specification, if only practiced under any software distributed under the present terms +of GNU GENERAL PUBLIC LICENSE (http://www.fsf.org/copyleft/gpl.html) or under license terms +that conform to the present open source definition (http://www.opensource.org/osd.html) and +provided that the party relying on this commitment does not assert its patents against Nokia. + +Otherwise general Nokia Statement on Patent Licensing (http://www.ietf.org/ietf/IPR/NOKIA) +applies to this submission. + + +Heikki Huttunen +Director, Licensing +Nokia Corporation +P.O Box 86, FIN-24101 Salo, Finland +Phone: +358 (0) 7180 41202, Fax: +358 (0) 7180 44275 diff -Nur mipv6-daemon-umip-0.3/man/mip6d.conf.tmpl mipv6-daemon-umip-0.3-nepl/man/mip6d.conf.tmpl --- mipv6-daemon-umip-0.3/man/mip6d.conf.tmpl 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/man/mip6d.conf.tmpl 2007-06-13 11:01:14.000000000 +0200 @@ -1,12 +1,12 @@ .\" $Id: mip6d.conf.tmpl 1.33 06/05/12 11:48:36+03:00 vnuorval@tcs.hut.fi $ -.TH mip6d.conf 5 "January 31, 2006" "" "Mobile IPv6 Daemon Configuration" +.TH mip6d.conf 5 "January 31, 2006" "" "Mobile IPv6 and NEMO Daemon Configuration" .SH NAME -mip6d.conf \- MIPL Mobile IPv6 Configuration file +mip6d.conf \- MIPL Mobile IPv6 and NEMO Configuration file .SH SYNOPSIS .B %etc%/mip6d.conf .sp .SH DESCRIPTION -MIPL Mobile IPv6 daemon's configuration file +MIPL Mobile IPv6 and NEMO daemon's configuration file .P Below is a list of currently supported configuration options. All configuration lines are terminated with a semicolon. Sub-sections are @@ -184,10 +184,29 @@ Default: 86400 .TP -.BR "BindingAclPolicy " "address " "allow | deny" +.BR "HaAcceptMobRtr enabled | disabled" -Defines if a MN is allowed to register with the HA or not. The MN home address -of the MN is given in the address field." +Indicates if the HA accepts Mobile Router bindings. + +Default: disabled; + +.TP +.BR "HaServedPrefix " "prefix/length" ";" + +Prefix is an IPv6 prefix and length is the prefix length. Defines the whole +aggregated or extended prefix the HA serves. This option is only used for MR +bindings and is only needed if the MRs derive their Home Addresses from their +Mobile Network Prefixes, instead of one of the home link prefixes. + +.TP +.BR "BindingAclPolicy " "address MNP list " "allow | deny" + +Defines if a MN is allowed to register with the HA or not. The home address +of the MN is given in the address field. The mobile network prefixes +belonging a NEMO Mobile Router are listed in the MNP list. The list can either +be an empty string or a comma separated list of network prefixes +enclosed in braces, for example: +.B "(3ffe:2620:6:3::/64, 3ffe:2620:6:4::/64)" .TP .BR "DefaultBindingAclPolicy allow | deny" @@ -254,6 +273,13 @@ Default: disabled .TP +.BR "MobRtrUseExplicitMode enabled | disabled" + +Toggles between explicit or implicit mode home registrations in the MR. + +Default: enabled + +.TP .BR "UseCnBuAck " "boolean" ";" Indicates if the Acknowledge bit should be set in Binding Updates sent to @@ -299,7 +325,7 @@ .TP .nf .BR "MnHomeLink " "name " "{" -.BR " HomeAddress " "address/length" ";" +.BR " HomeAddress " "address/length MNP list" ";" .BR " HomeAgentAddress " "address" ";" .BR " MnRoPolicy ..." .BR " ..." @@ -317,11 +343,14 @@ definitions. All the home link specific definitions are detailed below: .TP -.BR "HomeAddress " "address/length" ";" +.BR "HomeAddress " "address/length MNP list" ";" Address is an IPv6 address, and length the prefix length of the -address, usually 64. This option must be included in a home link -definition. +address, usually 64. The MNP list contains the mobile network prefixes +belonging to that particular NEMO Mobile Router. The MNP list is of the +same format as in +.B "BindingAclPolicy." +This option must be included in a home link definition. .TP .BR "HomeAgentAddress " "address" ";" @@ -332,6 +361,13 @@ Default: :: .TP +.BR "IsMobRtr enabled | disabled" + +Defines if the MN is a NEMO MR. + +Default: disabled + +.TP The route optimization policies are of the form: .TP @@ -353,6 +389,49 @@ .SH EXAMPLES .TP +.BR "A NEMO Home Agent example:" + +.nf +NodeConfig HA; + +Interface "eth0"; + +HaAcceptMobRtr enabled; + +HaServedPrefix 3ffe:2620:6::/48; + +DefaultBindingAclPolicy deny; +BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) allow; +BindingAclPolicy 3ffe:2620:6:1::1235 allow; + +UseMnHaIPsec disabled; +.fi + +.TP +.BR "A NEMO Mobile Router example:" + +.nf +NodeConfig MN; + +DoRouteOptimizationCN disabled; +DoRouteOptimizationMN disabled; + +Interface "eth0"; + +MnRouterProbes 1; + +MobRtrUseExplicitMode enabled; + +MnHomeLink "eth0" { + IsMobRtr enabled; + HomeAgentAddress 3ffe:2620:6:1::1; + HomeAddress 3ffe:2620:6:1::1234/64 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64); +} + +UseMnHaIPsec disabled; +.fi + +.TP .BR "A Correspondent Node example:" .nf diff -Nur mipv6-daemon-umip-0.3/man/mip6d.tmpl mipv6-daemon-umip-0.3-nepl/man/mip6d.tmpl --- mipv6-daemon-umip-0.3/man/mip6d.tmpl 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/man/mip6d.tmpl 2007-06-13 11:01:14.000000000 +0200 @@ -1,13 +1,13 @@ .\" $Id: mip6d.tmpl 1.4 05/05/16 13:13:41+03:00 anttit@tcs.hut.fi $ -.TH mip6d 1 "May 16, 2005" "" "Mobile IPv6 Daemon" +.TH mip6d 1 "May 16, 2005" "" "Mobile IPv6 and NEMO Daemon" .SH NAME -mip6d \- MIPL Mobile IPv6 protocol implementation +mip6d \- MIPL Mobile IPv6 and NEMO Basic Support protocol implementation .SH SYNOPSIS .B mip6d [options] .sp .SH DESCRIPTION -Mobile IPv6 implementation +Mobile IPv6 and NEMO Basic Support implementation .SH OPTIONS .IP "\fB\-V, \-\-version\fP" @@ -41,3 +41,5 @@ .PP RFC3776: Using IPsec to Protect Mobile IPv6 Signaling Between Mobile Nodes and Home Agents +.PP +RFC3963: Network Mobility (NEMO) Basic Support Protocol diff -Nur mipv6-daemon-umip-0.3/README mipv6-daemon-umip-0.3-nepl/README --- mipv6-daemon-umip-0.3/README 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/README 2007-06-13 11:01:14.000000000 +0200 @@ -2,6 +2,9 @@ MIPL Mobile IPv6 for Linux is an implementation of the Mobility Support in IP version 6 (RFC 3775). + + It also supports Network Mobility with the NEMO Basic Support + implementation (RFC 3963). This user space part works together with Mobile IPv6 enabled Linux kernels. See INSTALL and any other documents referred there for diff -Nur mipv6-daemon-umip-0.3/README.NEMO mipv6-daemon-umip-0.3-nepl/README.NEMO --- mipv6-daemon-umip-0.3/README.NEMO 1970-01-01 01:00:00.000000000 +0100 +++ mipv6-daemon-umip-0.3-nepl/README.NEMO 2007-06-13 11:01:14.000000000 +0200 @@ -0,0 +1,18 @@ +README for NEMO Basic Support +----------------------------- + +Here are a few things you need to keep in mind when setting up Network +Mobility: + +The MR is a router so you need to set +/proc/sys/net/ipv6/conf/all/forwarding to 1 to make sure it will forward +packets between its ingress and egress interfaces. + +With static routing the HA and other routers on the home link might need some +additional boot-strapping. If the MR has a physical home link that it may be +attached to, the other routers must be pre-configured with routes to the MR's +Mobile Network Prefixes via the MR's home address. This ensures packets will +be forwarded correctly also when the MR is at home. + +To be able to support NEMO DHAAD the HA needs to have AdvHomeAgentInfo and +AdvMobRtrSupportFlag turned on in radvd.conf. diff -Nur mipv6-daemon-umip-0.3/src/bcache.c mipv6-daemon-umip-0.3-nepl/src/bcache.c --- mipv6-daemon-umip-0.3/src/bcache.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/bcache.c 2007-06-13 11:01:14.000000000 +0200 @@ -144,6 +144,7 @@ } memset(tmp, 0, sizeof(*tmp)); INIT_LIST_HEAD(&tmp->tqe.list); + INIT_LIST_HEAD(&tmp->mob_net_prefixes); return tmp; } diff -Nur mipv6-daemon-umip-0.3/src/bcache.h mipv6-daemon-umip-0.3-nepl/src/bcache.h --- mipv6-daemon-umip-0.3/src/bcache.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/bcache.h 2007-06-13 11:01:14.000000000 +0200 @@ -18,7 +18,8 @@ uint16_t nonce_coa; uint16_t nonce_hoa; - int type; /* Entry type */ + uint16_t type; /* Entry type */ + uint16_t nemo_type; /* NEMO registration type */ int unreach; /* ICMP dest unreach count */ int tunnel; /* Tunnel interface index */ int link; /* Home link interface index */ @@ -33,6 +34,8 @@ struct tq_elem tqe; /* Timer queue entry for expire */ void (*cleanup)(struct bcentry *bce); /* Clean up bce data */ + + struct list_head mob_net_prefixes; }; #define BCE_NONCE_BLOCK 0 @@ -41,6 +44,10 @@ #define BCE_CACHE_DYING 3 #define BCE_DAD 4 +#define BCE_NEMO_EXPLICIT 1 +#define BCE_NEMO_IMPLICIT 2 +#define BCE_NEMO_DYNAMIC 3 + struct bcentry *bcache_alloc(int type); void bcache_free(struct bcentry *bce); diff -Nur mipv6-daemon-umip-0.3/src/bul.c mipv6-daemon-umip-0.3-nepl/src/bul.c --- mipv6-daemon-umip-0.3/src/bul.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/bul.c 2007-06-13 11:01:14.000000000 +0200 @@ -184,7 +184,8 @@ goto home_bul_free; } else if (bule->type == NON_MIP_CN_ENTRY) { if (bule->flags & IP6_MH_BU_HOME) { - if (xfrm_block_hoa(hai) < 0) + if (xfrm_block_hoa(hai) < 0 || + (hai->mob_rtr && xfrm_block_ra(hai) < 0)) goto home_bul_free; } } @@ -231,6 +232,10 @@ xfrm_unblock_link(hai); if (hai->home_block & HOME_ADDR_BLOCK) xfrm_unblock_hoa(hai); + if (hai->home_block & NEMO_RA_BLOCK) + xfrm_unblock_ra(hai); + if (hai->home_block & NEMO_FWD_BLOCK) + xfrm_unblock_fwd(hai); } } while (bule->ext_cleanup) diff -Nur mipv6-daemon-umip-0.3/src/cn.c mipv6-daemon-umip-0.3-nepl/src/cn.c --- mipv6-daemon-umip-0.3/src/cn.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/cn.c 2007-06-13 11:01:14.000000000 +0200 @@ -177,8 +177,8 @@ non_ind = mh_opt(&bu->ip6mhbu_hdr, &mh_opts, IP6_MHOPT_NONCEID); bce = bcache_get(out.src, out.dst); if (bce) { - if ((bce->flags^bu_flags) & IP6_MH_BU_HOME) { - /* H-bit mismatch, flags changed */ + if ((bce->flags^bu_flags) & (IP6_MH_BU_HOME|IP6_MH_BU_MR)) { + /* H-bit or R-bit mismatch, flags changed */ bcache_release_entry(bce); bce = NULL; status = IP6_MH_BAS_REG_NOT_ALLOWED; @@ -221,9 +221,15 @@ /* else get rid of it */ bcache_delete(out.src, out.dst); } - } else if (bu_flags & IP6_MH_BU_HOME) { - status = IP6_MH_BAS_HA_NOT_SUPPORTED; - goto send_nack; + } else { + if (bu_flags & IP6_MH_BU_HOME) { + status = IP6_MH_BAS_HA_NOT_SUPPORTED; + goto send_nack; + } + if (bu_flags & IP6_MH_BU_MR) { + status = IP6_MH_BAS_MR_OP_NOT_PERMITTED; + goto send_nack; + } } status = conf.pmgr.discard_binding(out.dst, out.bind_coa, out.src, bu, len); diff -Nur mipv6-daemon-umip-0.3/src/conf.c mipv6-daemon-umip-0.3-nepl/src/conf.c --- mipv6-daemon-umip-0.3/src/conf.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/conf.c 2007-06-13 11:01:14.000000000 +0200 @@ -212,6 +212,7 @@ INIT_LIST_HEAD(&c->home_addrs); c->MoveModulePath = NULL; /* internal */ c->DoRouteOptimizationMN = 1; + c->MobRtrUseExplicitMode = 1; c->SendMobPfxSols = 1; c->OptimisticHandoff = 0; @@ -221,6 +222,7 @@ c->MaxMobPfxAdvInterval = 86400; /* seconds */ c->MinMobPfxAdvInterval = 600; /* seconds */ c->HaMaxBindingLife = MAX_BINDING_LIFETIME; + INIT_LIST_HEAD(&c->nemo_ha_served_prefixes); /* CN bindings */ c->DoRouteOptimizationCN = 1; diff -Nur mipv6-daemon-umip-0.3/src/conf.h mipv6-daemon-umip-0.3-nepl/src/conf.h --- mipv6-daemon-umip-0.3/src/conf.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/conf.h 2007-06-13 11:01:14.000000000 +0200 @@ -39,6 +39,7 @@ struct list_head home_addrs; char *MoveModulePath; uint16_t CnBuAck; + char MobRtrUseExplicitMode; char DoRouteOptimizationMN; char MnUseAllInterfaces; char MnDiscardHaParamProb; @@ -46,15 +47,16 @@ char OptimisticHandoff; /* HA options */ + char HaAcceptMobRtr; char SendMobPfxAdvs; char SendUnsolMobPfxAdvs; unsigned int MaxMobPfxAdvInterval; unsigned int MinMobPfxAdvInterval; unsigned int HaMaxBindingLife; + struct list_head nemo_ha_served_prefixes; /* CN options */ char DoRouteOptimizationCN; - }; struct net_iface { diff -Nur mipv6-daemon-umip-0.3/src/dhaad_ha.c mipv6-daemon-umip-0.3-nepl/src/dhaad_ha.c --- mipv6-daemon-umip-0.3/src/dhaad_ha.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/dhaad_ha.c 2007-06-13 11:01:14.000000000 +0200 @@ -83,8 +83,8 @@ pthread_rwlock_unlock(&ha_lock); } -void dhaad_insert_halist(struct ha_interface *i, - uint16_t key, uint16_t life_sec, +void dhaad_insert_halist(struct ha_interface *i, uint16_t key, + uint16_t life_sec, uint16_t flags, struct nd_opt_prefix_info *pinfo, const struct in6_addr *lladdr) { @@ -110,6 +110,7 @@ return; } memset(ha, 0, sizeof(*ha)); + ha->flags = flags; ha->iface = i; ha->addr = *addr; INIT_LIST_HEAD(&ha->tqe.list); @@ -136,18 +137,22 @@ return; } -static int dhaad_get_halist(struct ha_interface *i, int max, struct iovec *iov) +static int dhaad_get_halist(struct ha_interface *i, uint16_t flags, + int max, struct iovec *iov) { struct list_head *lp; int n = 0; list_for_each(lp, &i->ha_list) { struct home_agent *h; h = list_entry(lp, struct home_agent, list); - n++; - iov[n].iov_len = sizeof(struct in6_addr); - iov[n].iov_base = &h->addr; - if (n >= max) - break; + if (!(flags & MIP_DHREQ_FLAG_SUPPORT_MR) || + h->flags & ND_OPT_HAI_FLAG_SUPPORT_MR) { + n++; + iov[n].iov_len = sizeof(struct in6_addr); + iov[n].iov_base = &h->addr; + if (n >= max) + break; + } } return n; } @@ -177,8 +182,12 @@ rph->mip_dhrep_id = rqh->mip_dhreq_id; + if (rqh->mip_dhreq_flags_reserved & MIP_DHREQ_FLAG_SUPPORT_MR) + rph->mip_dhrep_flags_reserved = MIP_DHREP_FLAG_SUPPORT_MR; + pthread_rwlock_rdlock(&ha_lock); - iovlen = dhaad_get_halist(i, MAX_HOME_AGENTS, iov); + iovlen = dhaad_get_halist(i, rqh->mip_dhreq_flags_reserved, + MAX_HOME_AGENTS, iov); icmp6_send(i->ifindex, 64, ha_addr, src, iov, iovlen + 1); pthread_rwlock_unlock(&ha_lock); free_iov_data(&iov[0], 1); diff -Nur mipv6-daemon-umip-0.3/src/dhaad_ha.h mipv6-daemon-umip-0.3-nepl/src/dhaad_ha.h --- mipv6-daemon-umip-0.3/src/dhaad_ha.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/dhaad_ha.h 2007-06-13 11:01:14.000000000 +0200 @@ -17,8 +17,8 @@ int (* func)(int, void *, void *), void *arg); #endif -void dhaad_insert_halist(struct ha_interface *i, - uint16_t key, uint16_t life_sec, +void dhaad_insert_halist(struct ha_interface *i, uint16_t key, + uint16_t life_sec, uint16_t flags, struct nd_opt_prefix_info *pinfo, const struct in6_addr *lladdr); diff -Nur mipv6-daemon-umip-0.3/src/dhaad_mn.c mipv6-daemon-umip-0.3-nepl/src/dhaad_mn.c --- mipv6-daemon-umip-0.3/src/dhaad_mn.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/dhaad_mn.c 2007-06-13 11:01:14.000000000 +0200 @@ -86,7 +86,8 @@ } static int dhaad_send_request(int oif, struct in6_addr *src, - struct in6_addr *pfx, int plen) + struct in6_addr *pfx, int plen, + uint16_t flags) { struct mip_dhaad_req *ih; struct iovec iov; @@ -98,6 +99,7 @@ return -1; id = dhaad_id++; ih->mip_dhreq_id = htons(id); + ih->mip_dhreq_flags_reserved = flags; dhaad_gen_ha_anycast(&dst, pfx, plen); icmp6_send(oif, 0, src, &dst, &iov, 1); free_iov_data(&iov, 1); @@ -121,7 +123,9 @@ t->dhaad_id = dhaad_send_request(hai->primary_coa.iif, &hai->primary_coa.addr, &hai->home_prefix, - hai->home_plen); + hai->home_plen, + hai->mob_rtr? + MIP_DHREQ_FLAG_SUPPORT_MR:0); t->dhaad_resends++; tsadd(t->dhaad_delay, t->dhaad_delay, t->dhaad_delay); add_task_rel(&t->dhaad_delay, &t->tqe, dhaad_resend); @@ -139,11 +143,15 @@ t->dhaad_resends == DHAAD_RETRIES))) { if (!(hai->home_block & HOME_ADDR_BLOCK)) xfrm_block_hoa(hai); + if (hai->mob_rtr && !(hai->home_block & NEMO_RA_BLOCK)) + xfrm_block_ra(hai); t->dhaad_resends = 0; t->dhaad_id = dhaad_send_request(hai->primary_coa.iif, &hai->primary_coa.addr, &hai->home_prefix, - hai->home_plen); + hai->home_plen, + hai->mob_rtr? + MIP_DHREQ_FLAG_SUPPORT_MR:0); t->dhaad_delay = INITIAL_DHAAD_TIMEOUT_TS; add_task_rel(&t->dhaad_delay, &t->tqe, dhaad_resend); } @@ -165,6 +173,8 @@ tsclear(t->dhaad_delay); if (hai->home_block & HOME_ADDR_BLOCK) xfrm_unblock_hoa(hai); + if (hai->home_block & NEMO_RA_BLOCK) + xfrm_unblock_ra(hai); } void dhaad_stop(struct home_addr_info *hai) @@ -245,6 +255,12 @@ pthread_rwlock_unlock(&mn_lock); return; } + if (hai->mob_rtr && + !(rph->mip_dhrep_flags_reserved & MIP_DHREP_FLAG_SUPPORT_MR)) { + dbg("HA doesn't support MR\n"); + pthread_rwlock_unlock(&mn_lock); + return; + } ha = (struct in6_addr *)(ih + 1); dhaad_flush_candidates(&hai->ha_list); diff -Nur mipv6-daemon-umip-0.3/src/gram.y mipv6-daemon-umip-0.3-nepl/src/gram.y --- mipv6-daemon-umip-0.3/src/gram.y 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/gram.y 2007-06-13 11:01:14.000000000 +0200 @@ -30,10 +30,10 @@ #ifdef HAVE_CONFIG_H #include #endif +#include #include #include #include -#include #include #include #include @@ -54,9 +54,24 @@ }; struct home_addr_info hai = { - .ro_policies = LIST_HEAD_INIT(hai.ro_policies) + .ro_policies = LIST_HEAD_INIT(hai.ro_policies), + .mob_net_prefixes = LIST_HEAD_INIT(hai.mob_net_prefixes) }; +LIST_HEAD(prefixes); + +int mv_prefixes(struct list_head *list) +{ + struct list_head *l, *n; + int res = 0; + list_for_each_safe(l, n, &prefixes) { + list_del(l); + list_add_tail(l, list); + res++; + } + return res; +} + struct policy_bind_acl_entry *bae = NULL; struct ipsec_policy_set { @@ -165,6 +180,11 @@ %token MNROUTERPROBETIMEOUT %token MNDISCARDHAPARAMPROB %token OPTIMISTICHANDOFF +%token HOMEPREFIX +%token HAACCEPTMOBRTR +%token ISMOBRTR +%token HASERVEDPREFIX +%token MOBRTRUSEEXPLICITMODE %token INV_TOKEN @@ -282,6 +302,19 @@ { conf.DefaultBindingAclPolicy = $2; } + | HAACCEPTMOBRTR BOOL ';' + { + conf.HaAcceptMobRtr = $2; + } + | HASERVEDPREFIX prefixlistentry ';' + { + list_splice(&prefixes, + conf.nemo_ha_served_prefixes.prev); + } + | MOBRTRUSEEXPLICITMODE BOOL ';' + { + conf.MobRtrUseExplicitMode = $2; + } | BINDINGACLPOLICY bindaclpolicy ';' { bae = NULL; @@ -398,12 +431,16 @@ memcpy(nhai, &hai, sizeof(struct home_addr_info)); INIT_LIST_HEAD(&nhai->ro_policies); INIT_LIST_HEAD(&nhai->ha_list.home_agents); + INIT_LIST_HEAD(&nhai->mob_net_prefixes); nhai->ha_list.dhaad_id = -1; list_splice(&hai.ro_policies, &nhai->ro_policies); + list_splice(&hai.mob_net_prefixes, + &nhai->mob_net_prefixes); list_add_tail(&nhai->list, &conf.home_addrs); memset(&hai, 0, sizeof(struct home_addr_info)); INIT_LIST_HEAD(&hai.ro_policies); + INIT_LIST_HEAD(&hai.mob_net_prefixes); } ; @@ -415,16 +452,35 @@ { memcpy(&hai.ha_addr, &$2, sizeof(struct in6_addr)); } - | HOMEADDRESS ADDR '/' prefixlen ';' - { - hai.hoa.addr = $2; - hai.plen = $4; - } + | HOMEADDRESS homeaddress ';' | USEALTCOA BOOL ';' { hai.altcoa = $2; } | MNROPOLICY mnropolicy ';' + | ISMOBRTR BOOL ';' + { + if ($2) + hai.mob_rtr = IP6_MH_BU_MR; + } + | HOMEPREFIX ADDR '/' prefixlen ';' + { + ipv6_addr_prefix(&hai.home_prefix, &$2, $4); + hai.home_plen = $4; + } + ; + +homeaddress : homeaddrdef prefixlistsub + { + hai.mnp_count = mv_prefixes(&hai.mob_net_prefixes); + } + ; + +homeaddrdef : ADDR '/' prefixlen + { + hai.hoa.addr = $1; + hai.plen = $3; + } ; ipsecpolicyset : ipsechaaddrdef ipsecmnaddrdefs ipsecpolicydefs @@ -639,7 +695,7 @@ | NUMBER { $$ = $1; } ; -bindaclpolicy : ADDR bindaclpolval +bindaclpolicy : ADDR prefixlistsub bindaclpolval { bae = malloc(sizeof(struct policy_bind_acl_entry)); if (bae == NULL) { @@ -649,7 +705,9 @@ memset(bae, 0, sizeof(struct policy_bind_acl_entry)); bae->hoa = $1; bae->plen = 128; - bae->bind_policy = $2; + INIT_LIST_HEAD(&bae->mob_net_prefixes); + bae->mnp_count = mv_prefixes(&bae->mob_net_prefixes); + bae->bind_policy = $3; list_add_tail(&bae->list, &conf.bind_acl); } ; @@ -664,4 +722,27 @@ } ; +prefixlistsub : + | '(' prefixlist ')' + ; + +prefixlist : prefixlistentry + | prefixlist ',' prefixlistentry + ; + +prefixlistentry : ADDR '/' prefixlen + { + struct prefix_list_entry *p; + p = malloc(sizeof(struct prefix_list_entry)); + if (p == NULL) { + fprintf(stderr, + "%s: out of memory\n", __FUNCTION__); + return -1; + } + memset(p, 0, sizeof(struct prefix_list_entry)); + p->ple_prefix = $1; + p->ple_plen = $3; + list_add_tail(&p->list, &prefixes); + } + ; %% diff -Nur mipv6-daemon-umip-0.3/src/ha.c mipv6-daemon-umip-0.3-nepl/src/ha.c --- mipv6-daemon-umip-0.3/src/ha.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/ha.c 2007-06-13 11:01:14.000000000 +0200 @@ -79,6 +79,7 @@ struct ha_interface *iface; uint16_t pref = 0; uint16_t life = 0; + uint16_t flags = 0; /* validity checks */ if (hoplimit < 255 || !IN6_IS_ADDR_LINKLOCAL(src) || @@ -120,6 +121,7 @@ hainfo = (struct nd_opt_homeagent_info *)opt; pref = ntohs(hainfo->nd_opt_hai_preference); life = ntohs(hainfo->nd_opt_hai_lifetime); + flags = hainfo->nd_opt_hai_flags_reserved; } optlen -= olen; opt += olen; @@ -129,7 +131,7 @@ if (pinfo[i]->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_RADDR) { dhaad_insert_halist(iface, pref, life, - pinfo[i], src); + flags, pinfo[i], src); } } mpd_del_expired_pinfos(iface); @@ -499,9 +501,47 @@ } #endif + +static void nemo_ha_del_mnp_routes(struct list_head *old_mnps, + struct list_head *new_mnps, + int ifindex, int all) +{ + struct list_head *list; + list_for_each(list, old_mnps) { + struct prefix_list_entry *p; + p = list_entry(list, struct prefix_list_entry, list); + if (!all && + prefix_list_find(new_mnps, &p->ple_prefix, p->ple_plen)) + continue; + + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD, + NULL, 0, &p->ple_prefix, p->ple_plen, NULL); + } +} + +static int nemo_ha_add_mnp_routes(struct list_head *old_mnps, + struct list_head *new_mnps, + int ifindex, int all) +{ + struct list_head *list; + list_for_each(list, new_mnps) { + struct prefix_list_entry *p; + p = list_entry(list, struct prefix_list_entry, list); + if (!all && + prefix_list_find(old_mnps, &p->ple_prefix, p->ple_plen)) + continue; + if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP, + 0, IP6_RT_PRIO_MIP6_FWD, + NULL, 0, &p->ple_prefix, p->ple_plen, NULL) < 0) + return -1; + } + return 0; +} + struct home_tnl_ops_parm { struct bcentry *bce; int ba_status; + struct list_head mob_net_prefixes; }; static int home_tnl_del(int old_if, int new_if, struct home_tnl_ops_parm *p) @@ -525,6 +565,10 @@ /* delete HoA route */ route_del(old_if, RT6_TABLE_MAIN, IP6_RT_PRIO_MIP6_FWD, NULL, 0, peer_addr, 128, NULL); + + /* delete MNP routes */ + nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes, + &p->mob_net_prefixes, old_if, 1); /* update tunnel interface */ p->bce->tunnel = new_if; @@ -545,6 +589,15 @@ /* update tunnel interface */ p->bce->tunnel = new_if; + /* add MNP routes */ + if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes, + &p->mob_net_prefixes, new_if, 1) < 0) { + if (p->bce->nemo_type == BCE_NEMO_EXPLICIT) + p->ba_status = IP6_MH_BAS_INVAL_PRFX; + else + p->ba_status = IP6_MH_BAS_FWDING_FAILED; + goto err; + } /* add HoA route */ if (route_add(new_if, RT6_TABLE_MAIN, RTPROT_MIP, 0, IP6_RT_PRIO_MIP6_FWD, @@ -584,6 +637,23 @@ coa = &p->bce->coa; old_coa = &p->bce->old_coa; + /* if interface hasn't changed, at least check if the + MR's MNPs have changed */ + if (prefix_list_cmp(&p->bce->mob_net_prefixes, + &p->mob_net_prefixes)) { + nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes, + &p->mob_net_prefixes, + old_if, 0); + if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes, + &p->mob_net_prefixes, + new_if, 0) < 0) { + if (p->bce->nemo_type == BCE_NEMO_EXPLICIT) + p->ba_status = IP6_MH_BAS_INVAL_PRFX; + else + p->ba_status = IP6_MH_BAS_FWDING_FAILED; + return -1; + } + } /* migrate */ if (conf.UseMnHaIPsec && !IN6_ARE_ADDR_EQUAL(old_coa, coa) && @@ -634,6 +704,61 @@ } } + +static int ha_extract_mnps(const struct ip6_mh_binding_update *bu, + const struct mh_options *opts, + struct list_head *mob_net_prefixes) +{ + struct ip6_mh_opt_mob_net_prefix *op; + int prefix_count = 0; + for (op = mh_opt(&bu->ip6mhbu_hdr, opts, IP6_MHOPT_MOB_NET_PRFX); + op != NULL; + op = mh_opt_next(&bu->ip6mhbu_hdr, opts, op)) { + struct prefix_list_entry *p; + p = malloc(sizeof(struct prefix_list_entry)); + if (p == NULL) { + prefix_list_free(mob_net_prefixes); + return -1; + } + memset(p, 0, sizeof(struct prefix_list_entry)); + p->ple_plen = op->ip6mnp_prefix_len; + p->ple_prefix = op->ip6mnp_prefix; + list_add_tail(&p->list, mob_net_prefixes); + prefix_count++; + } + return prefix_count; +} + +static int ha_get_mnps(const struct in6_addr *hoa, + struct list_head *mob_net_prefixes) +{ + struct nd_opt_prefix_info *mnps; + int mnp_count = conf.pmgr.get_mnp_count(hoa); + int i; + + if (mnp_count <= 0) + return mnp_count; + + mnps = calloc(mnp_count, sizeof(struct nd_opt_prefix_info)); + if (mnps == NULL) + return -1; + + mnp_count = conf.pmgr.get_mnps(hoa, mnp_count, mnps); + for (i = 0; i < mnp_count; i++) { + struct prefix_list_entry *p; + p = malloc(sizeof(struct prefix_list_entry)); + if (p == NULL) { + prefix_list_free(mob_net_prefixes); + free(mnps); + return -1; + } + p->pinfo = *(mnps + i); + list_add_tail(&p->list, mob_net_prefixes); + } + free(mnps); + return mnp_count; +} + struct ha_recv_bu_args { struct list_head list; struct in6_addr src; @@ -684,8 +809,9 @@ bce = bcache_get(out.src, out.dst); if (bce) { if (bce->type != BCE_NONCE_BLOCK) { - if (!(bce->flags & IP6_MH_BU_HOME)) { - /* H-bit mismatch, flags changed */ + /* H-bit or R-bit mismatch, flags changed */ + if ((bce->flags ^ bu_flags) & + (IP6_MH_BU_HOME | IP6_MH_BU_MR)) { bcache_release_entry(bce); bce = NULL; status = IP6_MH_BAS_REG_NOT_ALLOWED; @@ -733,9 +859,14 @@ } if ((status = mpd_prefix_check(out.src, out.dst, &lft, &home_ifindex, new)) < 0) { - /* not home agent for this subnet */ - status = IP6_MH_BAS_NOT_HOME_SUBNET; - goto send_nack; + if (!(bu_flags & IP6_MH_BU_MR) || + !prefix_list_find(&conf.nemo_ha_served_prefixes, + out.dst, 0)) { + /* not home agent for this subnet */ + status = IP6_MH_BAS_NOT_HOME_SUBNET; + goto send_nack; + } + status = IP6_MH_BAS_ACCEPTED; } status = conf.pmgr.discard_binding(out.dst, out.bind_coa, out.src, arg->bu, arg->len); @@ -787,6 +918,25 @@ } new = 1; } + INIT_LIST_HEAD(&p.mob_net_prefixes); + if (bu_flags & IP6_MH_BU_MR && tsisset(lft)) { + if (mh_opt(&arg->bu->ip6mhbu_hdr, + &arg->mh_opts, IP6_MHOPT_MOB_NET_PRFX) != NULL) { + if (ha_extract_mnps(arg->bu, + &arg->mh_opts, + &p.mob_net_prefixes) < 0) { + status = IP6_MH_BAS_INVAL_PRFX; + goto send_nack; + } + bce->nemo_type = BCE_NEMO_EXPLICIT; + } else if (ha_get_mnps(out.dst, &p.mob_net_prefixes) > 0) { + bce->nemo_type = BCE_NEMO_IMPLICIT; + } else { + /* Todo: dynamic routing */ + status = IP6_MH_BAS_FWDING_FAILED; + goto send_nack; + } + } p.bce = bce; p.ba_status = status; bce->seqno = seqno; @@ -855,6 +1005,9 @@ * have a binding before sending this Binding Update, * discard the connections to the home address. */ } + if (status < IP6_MH_BAS_UNSPECIFIED && bu_flags & IP6_MH_BU_MR) + ba_flags |= IP6_MH_BA_MR; + if (!(arg->flags & HA_BU_F_SKIP_BA)) mh_send_ba(&out, status, ba_flags, seqno, &lft, NULL, iif); if (new && tsisset(lft)) diff -Nur mipv6-daemon-umip-0.3/src/ha.h mipv6-daemon-umip-0.3-nepl/src/ha.h --- mipv6-daemon-umip-0.3/src/ha.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/ha.h 2007-06-13 11:01:14.000000000 +0200 @@ -23,6 +23,7 @@ struct list_head list; struct in6_addr addr; uint16_t preference; + uint16_t flags; struct timespec lifetime; struct ha_interface *iface; struct tq_elem tqe; diff -Nur mipv6-daemon-umip-0.3/src/mh.c mipv6-daemon-umip-0.3-nepl/src/mh.c --- mipv6-daemon-umip-0.3/src/mh.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/mh.c 2007-06-13 11:01:14.000000000 +0200 @@ -51,6 +51,7 @@ #include "conf.h" #include "bcache.h" #include "keygen.h" +#include "prefix.h" #define MH_DEBUG_LEVEL 1 @@ -75,6 +76,7 @@ 0, /* Alternate CoA */ 0, /* Nonce Index */ 0, /* Binding Auth Data */ + 1, /* Mobile Network Prefix */ }; #define __MH_SENTINEL (IP6_MH_TYPE_MAX + 1) @@ -401,6 +403,46 @@ return 0; } +int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count, + struct list_head *mnps) +{ + int optlen = (mnp_count * sizeof(struct ip6_mh_opt_mob_net_prefix) + + (mnp_count - 1) * sizeof(_pad4)); + struct list_head *l; + int i = 0; + uint8_t *data; + iov->iov_base = malloc(optlen); + iov->iov_len = optlen; + + if (iov->iov_base == NULL) + return -ENOMEM; + + memset(iov->iov_base, 0, iov->iov_len); + data = (uint8_t *)iov->iov_base; + + list_for_each(l, mnps) { + struct prefix_list_entry *p; + struct ip6_mh_opt_mob_net_prefix *mnp; + + p = list_entry(l, struct prefix_list_entry, list); + mnp = (struct ip6_mh_opt_mob_net_prefix *)data; + + mnp->ip6mnp_type = IP6_MHOPT_MOB_NET_PRFX; + mnp->ip6mnp_len = 18; + mnp->ip6mnp_prefix_len = p->ple_plen; + mnp->ip6mnp_prefix = p->ple_prefix; + + data += sizeof(struct ip6_mh_opt_mob_net_prefix); + + /* do internal padding here, so one iovec for MNPs is enough */ + if (++i < mnp_count) { + memcpy(data, _pad4, sizeof(_pad4)); + data += sizeof(_pad4); + } + } + return 0; +} + static size_t mh_length(struct iovec *vec, int count) { size_t len = 0; @@ -442,6 +484,9 @@ case IP6_MHOPT_BAUTH: pad = optpad(8, 2, len); /* 8n+2 */ break; + case IP6_MHOPT_MOB_NET_PRFX: + pad = optpad(8, 4, len); /* 8n+4 */ + break; } if (pad > 0) { create_opt_pad(&out[n++], pad); @@ -694,6 +739,8 @@ return len != sizeof(struct ip6_mh_opt_nonce_index); case IP6_MHOPT_BAUTH: return len != sizeof(struct ip6_mh_opt_auth_data); + case IP6_MHOPT_MOB_NET_PRFX: + return len != sizeof(struct ip6_mh_opt_mob_net_prefix); case IP6_MHOPT_PADN: default: return 0; diff -Nur mipv6-daemon-umip-0.3/src/mh.h mipv6-daemon-umip-0.3-nepl/src/mh.h --- mipv6-daemon-umip-0.3/src/mh.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/mh.h 2007-06-13 11:01:14.000000000 +0200 @@ -10,7 +10,7 @@ /* If new types or options appear, these should be updated. */ #define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR -#define IP6_MHOPT_MAX IP6_MHOPT_BAUTH +#define IP6_MHOPT_MAX IP6_MHOPT_MOB_NET_PRFX struct in6_addr_bundle { struct in6_addr *src; @@ -74,6 +74,11 @@ int mh_create_opt_auth_data(struct iovec *iov); +struct list_head; + +int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count, + struct list_head *mnps); + static inline void *mh_opt(const struct ip6_mh *mh, const struct mh_options *mh_opts, uint8_t type) { diff -Nur mipv6-daemon-umip-0.3/src/mn.c mipv6-daemon-umip-0.3-nepl/src/mn.c --- mipv6-daemon-umip-0.3/src/mn.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/mn.c 2007-06-13 11:01:14.000000000 +0200 @@ -326,7 +326,17 @@ free_iov_data(iov, iov_ind); return -ENOMEM; } - if (!(bule->flags & IP6_MH_BU_HOME)) { + if (bule->flags & IP6_MH_BU_HOME) { + struct home_addr_info *hai = bule->home; + if (bule->flags & IP6_MH_BU_MR && bu->ip6mhbu_lifetime && + bule->home->mnp_count > 0 && conf.MobRtrUseExplicitMode && + mh_create_opt_mob_net_prefix(&iov[iov_ind++], + hai->mnp_count, + &hai->mob_net_prefixes) < 0) { + free_iov_data(iov, iov_ind); + return -ENOMEM; + } + } else { if (mh_create_opt_nonce_index(&iov[iov_ind++], bule->rr.ho_ni, bule->rr.co_ni) || mh_create_opt_auth_data(&iov[iov_ind++])) { @@ -616,6 +626,34 @@ return 0; } +int nemo_mr_tnl_routes_add(struct home_addr_info *hai, int ifindex) +{ + struct list_head *l; + struct prefix_list_entry *pe; + list_for_each(l, &hai->mob_net_prefixes) { + struct prefix_list_entry *p; + p = list_entry(l, struct prefix_list_entry, list); + if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP, + 0, IP6_RT_PRIO_MIP6_FWD, + &p->ple_prefix, p->ple_plen, + &in6addr_any, 0, NULL) < 0) { + pe = p; + goto undo; + } + } + return 0; +undo: + list_for_each(l, &hai->mob_net_prefixes) { + struct prefix_list_entry *p; + p = list_entry(l, struct prefix_list_entry, list); + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD, + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL); + if (p == pe) + break; + } + return -1; +} + static int mn_tnl_state_add(struct home_addr_info *hai, int ifindex, int all) { int err = 0; @@ -628,12 +666,31 @@ mn_ro_pol_del(hai, ifindex, all); } } + if (hai->mob_rtr && + (err = nemo_mr_tnl_routes_add(hai, ifindex)) < 0) { + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT, + &hai->hoa.addr, 128, &in6addr_any, 0, NULL); + mn_ro_pol_del(hai, ifindex, all); + } return err; } +static void nemo_mr_tnl_routes_del(struct home_addr_info *hai, int ifindex) +{ + struct list_head *l; + list_for_each(l, &hai->mob_net_prefixes) { + struct prefix_list_entry *p; + p = list_entry(l, struct prefix_list_entry, list); + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD, + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL); + } +} + static void mn_tnl_state_del(struct home_addr_info *hai, int ifindex, int all) { if (hai->home_reg_status != HOME_REG_NONE) { + if (hai->mob_rtr) + nemo_mr_tnl_routes_del(hai, ifindex); route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT, &hai->hoa.addr, 128, &in6addr_any, 0, NULL); mn_ro_pol_del(hai, ifindex, all); @@ -674,7 +731,8 @@ { int err = 0; bule->type = BUL_ENTRY; - bule->flags = IP6_MH_BU_HOME | IP6_MH_BU_ACK | hai->lladdr_comp; + bule->flags = (IP6_MH_BU_HOME | IP6_MH_BU_ACK | + hai->lladdr_comp | hai->mob_rtr); bule->coa_changed = -1; bule->coa = hai->primary_coa.addr; bule->if_coa = hai->primary_coa.iif; @@ -1084,6 +1142,18 @@ if (bule->flags & IP6_MH_BU_HOME) { struct home_addr_info *hai = bule->home; struct ip6_mh_opt_refresh_advice *bra; + + if (bule->flags & IP6_MH_BU_MR && + !(ba->ip6mhba_flags & IP6_MH_BA_MR)) { + if (hai->use_dhaad) { + mn_change_ha(hai); + } else { + int one = 1; + bul_iterate(&hai->bul, mn_dereg, &one); + } + pthread_rwlock_unlock(&mn_lock); + return; + } if (!tsisset(ba_lifetime)) { int type = FLUSH_FAILED; mn_dereg_home(hai); @@ -1251,12 +1321,73 @@ return 0; } +static void nemo_mr_rules_del(struct home_addr_info *hinfo) +{ + struct list_head *l; + + list_for_each(l, &hinfo->mob_net_prefixes) { + struct prefix_list_entry *p = NULL; + p = list_entry(l, struct prefix_list_entry, list); + rule_del(NULL, RT6_TABLE_MIP6, + IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST, + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0); + rule_del(NULL, RT6_TABLE_MAIN, + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST, + &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0); + } +} + +static int nemo_mr_rules_add(struct home_addr_info *hinfo) +{ + struct prefix_list_entry *pe = NULL; + struct list_head *l; + + list_for_each(l, &hinfo->mob_net_prefixes) { + struct prefix_list_entry *p = NULL; + p = list_entry(l, struct prefix_list_entry, list); + if (rule_add(NULL, RT6_TABLE_MAIN, + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST, + &in6addr_any, 0, + &p->ple_prefix, p->ple_plen, 0) < 0) { + pe = p; + goto undo; + } + if (rule_add(NULL, RT6_TABLE_MIP6, + IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST, + &p->ple_prefix, p->ple_plen, + &in6addr_any, 0, 0) < 0) { + rule_del(NULL, RT6_TABLE_MAIN, + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST, + &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0); + pe = p; + goto undo; + } + } + return 0; +undo: + list_for_each(l, &hinfo->mob_net_prefixes) { + struct prefix_list_entry *p = NULL; + p = list_entry(l, struct prefix_list_entry, list); + rule_del(NULL, RT6_TABLE_MIP6, + IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST, + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0); + rule_del(NULL, RT6_TABLE_MAIN, + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST, + &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0); + if (p == pe) + break; + } + return -1; +} + static void clean_home_addr_info(struct home_addr_info *hai) { struct flag_hoa_args arg; int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen); list_del(&hai->list); + if (hai->mob_rtr) + nemo_mr_rules_del(hai); arg.target = hai; arg.flag = 0; addr_do(&hai->hoa.addr, plen, @@ -1310,13 +1441,23 @@ if (pthread_mutex_init(&hai->ha_list.c_lock, NULL)) goto undo; + + INIT_LIST_HEAD(&hai->mob_net_prefixes); + if (hai->mob_rtr && + prefix_list_copy(&conf_hai->mob_net_prefixes, + &hai->mob_net_prefixes) < 0) + goto mutex_undo; + INIT_LIST_HEAD(&hai->ro_policies); if (rpl_copy(&conf_hai->ro_policies, &hai->ro_policies) < 0) - goto mutex_undo; + goto mnp_undo; + INIT_LIST_HEAD(&hai->ha_list.tqe.list); INIT_LIST_HEAD(&hai->ha_list.home_agents); } return hai; +mnp_undo: + prefix_list_free(&hai->mob_net_prefixes); mutex_undo: pthread_mutex_destroy(&hai->ha_list.c_lock); undo: @@ -1337,6 +1478,15 @@ if ((hai = hai_copy(conf_hai)) == NULL) goto err; + if (hai->mob_rtr) { + MDBG("is Mobile Router\n"); + list_for_each(list, &hai->mob_net_prefixes) { + struct prefix_list_entry *p; + p = list_entry(list, struct prefix_list_entry, list); + MDBG("Mobile Network Prefix %x:%x:%x:%x:%x:%x:%x:%x/%d\n", + NIP6ADDR(&p->ple_prefix), p->ple_plen); + } + } if (IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) { hai->use_dhaad = 1; } else { @@ -1381,6 +1531,9 @@ hai->if_tunnel, &arg, flag_hoa) < 0) { goto clean_err; } + if (hai->mob_rtr && nemo_mr_rules_add(hai) < 0) { + goto clean_err; + } hai->at_home = hai->hoa.iif == hai->if_home; pthread_rwlock_wrlock(&mn_lock); list_add(&hai->list, &home_addr_list); diff -Nur mipv6-daemon-umip-0.3/src/mn.h mipv6-daemon-umip-0.3-nepl/src/mn.h --- mipv6-daemon-umip-0.3/src/mn.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/mn.h 2007-06-13 11:01:14.000000000 +0200 @@ -45,9 +45,11 @@ pthread_mutex_t c_lock; }; -#define HOME_LINK_BLOCK 0x1 -#define HOME_ADDR_BLOCK 0x2 -#define HOME_ADDR_RULE_BLOCK 0x4 +#define HOME_LINK_BLOCK 0x01 +#define HOME_ADDR_BLOCK 0x02 +#define HOME_ADDR_RULE_BLOCK 0x04 +#define NEMO_RA_BLOCK 0x08 +#define NEMO_FWD_BLOCK 0x10 struct mn_addr { struct in6_addr addr; @@ -84,7 +86,10 @@ int if_block; short hwalen; uint8_t altcoa; + uint8_t mob_rtr; char name[IF_NAMESIZE]; + int mnp_count; + struct list_head mob_net_prefixes; }; enum { diff -Nur mipv6-daemon-umip-0.3/src/movement.c mipv6-daemon-umip-0.3-nepl/src/movement.c --- mipv6-daemon-umip-0.3/src/movement.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/movement.c 2007-06-13 11:01:14.000000000 +0200 @@ -80,6 +80,7 @@ static int conf_default_rs = 3; static int conf_default_rs_ival = 4; +static int conf_forwarding = 0; static int conf_autoconf = 1; /*static int conf_ra = 1;*/ /*static int conf_ra_pinfo = 1;*/ @@ -181,6 +182,12 @@ route_del(rtr->ifindex, RT_TABLE_MAIN, 0, &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr); + + /* delete default route for the packets coming from the + * Mobile Network + */ + route_del(rtr->ifindex, RT6_TABLE_MIP6, 0, + &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr); } list_for_each_safe(l, n, &rtr->prefixes) { struct prefix_list_entry *p; @@ -235,8 +242,31 @@ list_add_tail(&coa->list, &iface->expired_coas); } +static void md_reset_egress_forward(void) +{ + struct list_head *l; + int forward = 0;; + + if (list_empty(&ifaces)) + return; + + list_for_each(l, &ifaces) { + struct md_inet6_iface *i; + i = list_entry(l, struct md_inet6_iface, list); + forward |= i->home_link; + } + list_for_each(l, &ifaces) { + struct md_inet6_iface *i; + i = list_entry(l, struct md_inet6_iface, list); + set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, + i->name, forward); + } +} + static void md_reset_home_link(struct md_inet6_iface *i) { + if (i->home_link) + md_reset_egress_forward(); i->home_link = 0; i->ll_dad_unsafe = 0; } @@ -652,6 +682,8 @@ static void iface_proc_entries_init(struct md_inet6_iface *iface) { + set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, iface->name, + conf_forwarding); set_iface_proc_entry(PROC_SYS_IP6_AUTOCONF, iface->name, conf_autoconf); set_iface_proc_entry(PROC_SYS_IP6_ACCEPT_RA_DEFRTR, iface->name, conf_ra_defrtr); @@ -882,6 +914,8 @@ ll_dad_unsafe |= hai->lladdr_comp; } } + if (i->home_link != home_link) + md_reset_egress_forward(); i->home_link = home_link; i->ll_dad_unsafe = ll_dad_unsafe; } @@ -1193,6 +1227,11 @@ RTF_DEFAULT|RTF_ADDRCONF, 1024, &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr); + /* default route for the packet coming from the Mobile Network */ + route_add(rtr->ifindex, RT6_TABLE_MIP6, RTPROT_MIP, + 0, IP6_RT_PRIO_MIP6_FWD, + &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr); + list_for_each(list, &rtr->prefixes) { struct prefix_list_entry *p; p = list_entry(list, struct prefix_list_entry, list); @@ -1741,6 +1780,8 @@ static void iface_proc_entries_cleanup(struct md_inet6_iface *iface) { + set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, iface->name, + iface->devconf[DEVCONF_FORWARDING]); set_iface_proc_entry(PROC_SYS_IP6_AUTOCONF, iface->name, iface->devconf[DEVCONF_AUTOCONF]); set_iface_proc_entry(PROC_SYS_IP6_ACCEPT_RA_DEFRTR, iface->name, diff -Nur mipv6-daemon-umip-0.3/src/ndisc.c mipv6-daemon-umip-0.3-nepl/src/ndisc.c --- mipv6-daemon-umip-0.3/src/ndisc.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/ndisc.c 2007-06-13 11:01:14.000000000 +0200 @@ -106,7 +106,7 @@ { struct in6_addr lladdr; int err; - int nd_flags = 0; + int nd_flags = bu_flags&IP6_MH_BU_MR ? NTF_ROUTER : 0; err = pneigh_add(ifindex, nd_flags, target); @@ -117,7 +117,9 @@ pneigh_del(ifindex, target); } if (!err) { - uint32_t na_flags = ND_NA_FLAG_OVERRIDE; + uint32_t na_flags = (ND_NA_FLAG_OVERRIDE | + nd_flags ? ND_NA_FLAG_ROUTER : 0); + ndisc_send_na(ifindex, src, &in6addr_all_nodes_mc, target, na_flags); diff -Nur mipv6-daemon-umip-0.3/src/policy.c mipv6-daemon-umip-0.3-nepl/src/policy.c --- mipv6-daemon-umip-0.3/src/policy.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/policy.c 2007-06-13 11:01:14.000000000 +0200 @@ -107,6 +107,23 @@ return 0; } +static inline int +policy_check_mob_net_prefix(const struct policy_bind_acl_entry *acl, + const struct ip6_mh_binding_update *bu, + const struct mh_options *opts) +{ + struct ip6_mh_opt_mob_net_prefix *op; + for (op = mh_opt(&bu->ip6mhbu_hdr, opts, IP6_MHOPT_MOB_NET_PRFX); + op != NULL; + op = mh_opt_next(&bu->ip6mhbu_hdr, opts, op)) { + if (!prefix_list_get(&acl->mob_net_prefixes, + &op->ip6mnp_prefix, + op->ip6mnp_prefix_len)) + return IP6_MH_BAS_NOT_AUTH_FOR_PRFX; + } + return IP6_MH_BAS_ACCEPTED; +} + /** * default_discard_binding - check for discard policy * @remote_hoa: remote MN's home address @@ -127,10 +144,20 @@ int ret = def_bind_policy; struct policy_bind_acl_entry *acl; + if (bu->ip6mhbu_flags & IP6_MH_BU_MR && !conf.HaAcceptMobRtr) + return IP6_MH_BAS_MR_OP_NOT_PERMITTED; + pthread_rwlock_rdlock(&policy_lock); acl = hash_get(&policy_bind_acl_hash, NULL, remote_hoa); if (acl != NULL) { ret = acl->bind_policy; + if (ret < IP6_MH_BAS_UNSPECIFIED && + bu->ip6mhbu_flags & IP6_MH_BU_MR) { + struct mh_options opts; + mh_opt_parse(&bu->ip6mhbu_hdr, len, + sizeof(*bu), &opts); + ret = policy_check_mob_net_prefix(acl, bu, &opts); + } } pthread_rwlock_unlock(&policy_lock); return ret; @@ -227,6 +254,42 @@ return 0; } +int default_get_mnp_count(const struct in6_addr *hoa) +{ + int ret = 0; + struct policy_bind_acl_entry *acl; + pthread_rwlock_rdlock(&policy_lock); + acl = hash_get(&policy_bind_acl_hash, NULL, hoa); + if (acl != NULL) + ret = acl->mnp_count; + pthread_rwlock_unlock(&policy_lock); + return ret; + +} + +int default_get_mnps(const struct in6_addr *hoa, + const int mnp_count, + struct nd_opt_prefix_info *mnps) +{ + int i = 0; + struct policy_bind_acl_entry *acl; + + pthread_rwlock_rdlock(&policy_lock); + acl = hash_get(&policy_bind_acl_hash, NULL, hoa); + if (acl != NULL) { + struct list_head *l; + list_for_each(l, &acl->mob_net_prefixes) { + struct prefix_list_entry *e; + if (i >= mnp_count) + break; + e = list_entry(l, struct prefix_list_entry, list); + mnps[i++] = e->pinfo; + } + } + pthread_rwlock_unlock(&policy_lock); + return i; +} + static int policy_bind_acle_cleanup(void *data, void *arg) { struct policy_bind_acl_entry *acl = data; diff -Nur mipv6-daemon-umip-0.3/src/policy.h mipv6-daemon-umip-0.3-nepl/src/policy.h --- mipv6-daemon-umip-0.3/src/policy.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/policy.h 2007-06-13 11:01:14.000000000 +0200 @@ -10,12 +10,15 @@ struct ip6_mh_binding_update; struct nd_router_advert; +struct nd_opt_prefix_info; struct policy_bind_acl_entry { struct list_head list; struct in6_addr hoa; int plen; int bind_policy; + int mnp_count; + struct list_head mob_net_prefixes; }; /** @@ -147,6 +150,12 @@ const struct in6_addr *cn, struct in6_addr *coa); +int default_get_mnp_count(const struct in6_addr *hoa); + +int default_get_mnps(const struct in6_addr *hoa, + const int mnp_count, + struct nd_opt_prefix_info *mnps); + void policy_cleanup(void); int policy_init(void); diff -Nur mipv6-daemon-umip-0.3/src/proc_sys.h mipv6-daemon-umip-0.3-nepl/src/proc_sys.h --- mipv6-daemon-umip-0.3/src/proc_sys.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/proc_sys.h 2007-06-13 11:01:14.000000000 +0200 @@ -14,6 +14,7 @@ #define PROC_SYS_IP6_APP_SOLICIT "/proc/sys/net/ipv6/neigh/%s/app_solicit" #define PROC_SYS_IP6_BASEREACHTIME_MS "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms" #define PROC_SYS_IP6_RETRANSTIMER_MS "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms" +#define PROC_SYS_IP6_FORWARDING "/proc/sys/net/ipv6/conf/%s/forwarding" int set_iface_proc_entry(const char *tmpl, const char *if_name, int val); diff -Nur mipv6-daemon-umip-0.3/src/rtnl.h mipv6-daemon-umip-0.3-nepl/src/rtnl.h --- mipv6-daemon-umip-0.3/src/rtnl.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/rtnl.h 2007-06-13 11:01:14.000000000 +0200 @@ -16,6 +16,7 @@ #define IP6_RT_PRIO_MIP6_FWD 192 #define IP6_RT_PRIO_ADDRCONF 256 +#define IP6_RULE_PRIO_MIP6_MNP_IN 1000 #define IP6_RULE_PRIO_MIP6_HOA_OUT 1001 #define IP6_RULE_PRIO_MIP6_COA_OUT 1002 #define IP6_RULE_PRIO_MIP6_BLOCK 1003 diff -Nur mipv6-daemon-umip-0.3/src/scan.l mipv6-daemon-umip-0.3-nepl/src/scan.l --- mipv6-daemon-umip-0.3/src/scan.l 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/scan.l 2007-06-13 11:01:14.000000000 +0200 @@ -136,6 +136,11 @@ MnRouterProbeTimeout { return MNROUTERPROBETIMEOUT; } MnDiscardHaParamProb { return MNDISCARDHAPARAMPROB; } OptimisticHandoff { return OPTIMISTICHANDOFF; } +HaAcceptMobRtr { return HAACCEPTMOBRTR; } +IsMobRtr { return ISMOBRTR; } +HaServedPrefix { return HASERVEDPREFIX; } +HomePrefix { return HOMEPREFIX; } +MobRtrUseExplicitMode { return MOBRTRUSEEXPLICITMODE; } internal { return INTERNAL; } {addr} { diff -Nur mipv6-daemon-umip-0.3/src/xfrm.c mipv6-daemon-umip-0.3-nepl/src/xfrm.c --- mipv6-daemon-umip-0.3/src/xfrm.c 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/xfrm.c 2007-06-13 11:01:14.000000000 +0200 @@ -1676,6 +1676,8 @@ if (hai->home_block & HOME_LINK_BLOCK) xfrm_unblock_link(hai); xfrm_block_link(hai); + if (hai->mob_rtr && !(hai->home_block & NEMO_FWD_BLOCK)) + xfrm_block_fwd(hai); } if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) { if (rdata) @@ -1740,6 +1742,8 @@ struct home_addr_info *hai = bule->home; if (hai->home_block & HOME_LINK_BLOCK) xfrm_unblock_link(hai); + if (hai->home_block & NEMO_FWD_BLOCK) + xfrm_unblock_fwd(hai); } /* check if XFRM policies and states have already been cleaned up */ if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) @@ -2028,6 +2032,50 @@ hai->home_block &= ~HOME_ADDR_BLOCK; } +/* block all RA messages sent by MR */ +int xfrm_block_ra(struct home_addr_info *hai) +{ + int ret = 0; + struct xfrm_selector sel; + hai->home_block |= NEMO_RA_BLOCK; + set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6, + ND_ROUTER_ADVERT, 0, 0, &sel); + if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_OUT, XFRM_POLICY_BLOCK, + MIP6_PRIO_HOME_BLOCK, NULL, 0))) + return ret; + return ret; +} + +void xfrm_unblock_ra(struct home_addr_info *hai) +{ + struct xfrm_selector sel; + set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6, + ND_ROUTER_ADVERT, 0, 0, &sel); + xfrm_mip_policy_del(&sel, XFRM_POLICY_OUT); + hai->home_block &= ~NEMO_RA_BLOCK; +} + +/* block all forwarded packets */ +int xfrm_block_fwd(struct home_addr_info *hai) +{ + int ret = 0; + struct xfrm_selector sel; + hai->home_block |= NEMO_FWD_BLOCK; + set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, 0, &sel); + if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_FWD, XFRM_POLICY_BLOCK, + MIP6_PRIO_HOME_BLOCK, NULL, 0))) + return ret; + return ret; +} + +void xfrm_unblock_fwd(struct home_addr_info *hai) +{ + struct xfrm_selector sel; + set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, 0, &sel); + xfrm_mip_policy_del(&sel, XFRM_POLICY_FWD); + hai->home_block &= ~NEMO_FWD_BLOCK; +} + int mn_ipsec_recv_bu_tnl_pol_add(struct bulentry *bule, int ifindex, struct ipsec_policy_entry *e) { diff -Nur mipv6-daemon-umip-0.3/src/xfrm.h mipv6-daemon-umip-0.3-nepl/src/xfrm.h --- mipv6-daemon-umip-0.3/src/xfrm.h 2007-06-13 11:01:08.000000000 +0200 +++ mipv6-daemon-umip-0.3-nepl/src/xfrm.h 2007-06-13 11:01:14.000000000 +0200 @@ -87,6 +87,12 @@ int xfrm_block_hoa(struct home_addr_info *hai); void xfrm_unblock_hoa(struct home_addr_info *hai); +int xfrm_block_ra(struct home_addr_info *hai); +void xfrm_unblock_ra(struct home_addr_info *hai); + +int xfrm_block_fwd(struct home_addr_info *hai); +void xfrm_unblock_fwd(struct home_addr_info *hai); + int ha_mn_ipsec_pol_mod(struct in6_addr *haaddr, struct in6_addr *hoa);