1 This patch adds the NEMO basic support.
2 See http://software.nautilus6.org/NEPL-UMIP/ for detail.
6 diff -r c04f74757df5 AUTHORS
7 --- a/AUTHORS Sun Nov 30 23:14:35 2008 +0100
8 +++ b/AUTHORS Sun Nov 30 23:14:48 2008 +0100
10 Petander. Code has been contributed by several individuals. See
11 THANKS for listing. See libnetlink/README for information regarding
14 +The NEMO Basic support code is developed by Ville Nuorvala
15 +<vnuorval@tcs.hut.fi> in co-operation with the Nautilus6/WIDE
16 +project (http://www.nautilus6.org).
18 +The NEMO Basic Support code has been ported to UMIP by Romain KUNTZ
19 +<kuntz@lsiit.u-strasbg.fr> and received contributions from the
21 +- Sebastien DECUGIS (Nautilus6): IPsec support for NEMO
22 +- Arnaud EBALARD (EADS): fixes for Big Endian architectures,
23 + improvements of the NEMO debug messages, improvements in the
24 + IPsec support code for NEMO.
25 diff -r c04f74757df5 BUGS
26 --- a/BUGS Sun Nov 30 23:14:35 2008 +0100
27 +++ b/BUGS Sun Nov 30 23:14:48 2008 +0100
29 * Multihoming support hasn't been very thoroughly tested and should
30 therefore be considered developmental code. However, it is a lot
31 more stable than in the Release Candidates.
36 +* The Mobile Router's home address may only be on the egress interface.
38 +* Dynamic routing protocols between the Home Agent and Mobile Router
39 + are not yet supported.
40 diff -r c04f74757df5 COPYING.NEMO
41 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42 +++ b/COPYING.NEMO Sun Nov 30 23:14:48 2008 +0100
44 +Cisco and Nokia have both published IPR notices regarding RFC 3963
45 +"Network Mobility (NEMO) Basic Support Protocol."
47 +Cisco has agreed not to assert its patents against any party agreeing with the
48 +terms in its IPR notice.
50 +Likewise, Nokia has agreed not to assert its patents against Open Source
51 +implementations of the specification.
53 +For further information, please read
54 +licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt and
55 +licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt.
57 diff -r c04f74757df5 INSTALL
58 --- a/INSTALL Sun Nov 30 23:14:35 2008 +0100
59 +++ b/INSTALL Sun Nov 30 23:14:48 2008 +0100
61 further information on how to configure your node. Also take a
62 look at the example configuration files in the extras directory.
64 + For comments about NEMO check README.NEMO.
66 For comments about IPsec support check README.IPsec.
69 diff -r c04f74757df5 README
70 --- a/README Sun Nov 30 23:14:35 2008 +0100
71 +++ b/README Sun Nov 30 23:14:48 2008 +0100
74 MIPL Mobile IPv6 for Linux is an implementation of the Mobility
75 Support in IP version 6 (RFC 3775).
77 + It also supports Network Mobility with the NEMO Basic Support
78 + implementation (RFC 3963).
80 This user space part works together with Mobile IPv6 enabled Linux
81 kernels. See INSTALL and any other documents referred there for
82 diff -r c04f74757df5 README.NEMO
83 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84 +++ b/README.NEMO Sun Nov 30 23:14:48 2008 +0100
86 +README for NEMO Basic Support
87 +-----------------------------
89 +Here are a few things you need to keep in mind when setting up Network
92 +The MR is a router so you need to set
93 +/proc/sys/net/ipv6/conf/all/forwarding to 1 to make sure it will forward
94 +packets between its ingress and egress interfaces.
96 +With static routing the HA and other routers on the home link might need some
97 +additional boot-strapping. If the MR has a physical home link that it may be
98 +attached to, the other routers must be pre-configured with routes to the MR's
99 +Mobile Network Prefixes via the MR's home address. This ensures packets will
100 +be forwarded correctly also when the MR is at home.
102 +To be able to support NEMO DHAAD the HA needs to have AdvHomeAgentInfo and
103 +AdvMobRtrSupportFlag turned on in radvd.conf.
104 diff -r c04f74757df5 extras/example-nemo-ha.conf
105 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106 +++ b/extras/example-nemo-ha.conf Sun Nov 30 23:14:48 2008 +0100
108 +# This is an example of NEMO-enabled Home Agent configuration file
112 +## If set to > 0, will not detach from tty
115 +## List of interfaces where we serve as Home Agent
119 +HaAcceptMobRtr enabled;
121 +HaServedPrefix 3ffe:2620:6::/48;
123 +DefaultBindingAclPolicy deny;
125 +BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) allow;
126 +BindingAclPolicy 3ffe:2620:6:1::1235 allow;
130 +## IPsec configuration
133 +UseMnHaIPsec enabled;
135 +## Key Management Mobility Capability
136 +#KeyMngMobCapability disabled;
139 + HomeAgentAddress 3ffe:2620:6:1::1;
141 + HomeAddress 3ffe:2620:6:1::1234/64;
142 + HomeAddress 3ffe:2620:6:1::1235/64;
144 + IPsecPolicy Mh UseESP;
145 + IPsecPolicy TunnelMh UseESP;
147 +# IPsecPolicy Mh UseESP 1 2;
148 +# IPsecPolicy ICMP UseESP 5;
149 +# IPsecPolicy TunnelMh UseESP 3 4;
153 +## It is possible to specify multiple IPsecPolicySet in order to configure
154 +## different value for such address.
157 +## One HA is for one IPsecPolicySet.
158 +# HomeAgentAddress 3ffe:2620:6:1::1;
160 +## It is possible to specify multiple home addresses when they use
161 +## the same configuration.
162 +# HomeAddress 3ffe:2620:6:1::1236/64;
163 +# HomeAddress 3ffe:2620:6:1::1237/64;
165 +## IPsec protocol syntax: IPsecPolicy TYPE IPSEC_PROTO [ REQID_SET ] [ ACTION ]
166 +## TYPE (for transport) := Mh | HomeRegBinding | ICMP | MobPfxDisc | any
167 +## TYPE (for tunnel) := TunnelMh | TunnelHomeTesting | TunnelPayload
168 +## IPSEC_PROTO := UseESP (UseAH and UseIPCOMP aren't currently supported)
169 +## REQID_SET := REQID(both-dir) | REQID(to-HA-dir) REQID(to-MN-dir)
171 +## REQID is a number. "to-HA-dir" is for packet from MN to HA e.g.
172 +## BU, MPS, or HoTI (it depends on TYPE).
173 +## REQID should be used when more than one configuration for transport
174 +## and tunnel respectively. The default value is zero.
176 +## Transport MH protection
177 +# IPsecPolicy Mh UseESP 1 2;
178 +# ## To protect only BU/BA exactly in MH, use below instead.
179 +# #IPsecPolicy HomeRegBinding UseESP 1 2;
181 +## Transport ICMP protection
182 +# IPsecPolicy ICMP UseESP 5 6;
183 +# ## To protect only MPD exactly in ICMP, use below instead.
184 +# #IPsecPolicy MobPfxDisc UseESP 5 6;
186 +## Tunnel HoTI/HoT protection
187 +# IPsecPolicy TunnelMh UseESP 3 4;
188 +# ## To protect only HoTI/HoT exactly in MH, use below instead.
189 +# #IPsecPolicy TunnelHomeTesting UseESP 3 4;
191 +## Tunnel payload protection
192 +# #IPsecPolicy TunnelPayload UseESP 7 8;
194 diff -r c04f74757df5 extras/example-nemo-mn.conf
195 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
196 +++ b/extras/example-nemo-mn.conf Sun Nov 30 23:14:48 2008 +0100
198 +# This is an example of NEMO Mobile Router configuration file
202 +## If set to > 0, will not detach from tty
205 +## Support route optimization with other MNs
206 +DoRouteOptimizationCN enabled;
208 +## Use route optimization with CNs
209 +DoRouteOptimizationMN enabled;
211 +UseCnBuAck disabled;
213 +MnDiscardHaParamProb enabled;
225 + HomeAgentAddress 3ffe:2620:6:1::1;
226 + HomeAddress 3ffe:2620:6:1::1234/64 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64);
230 +## IPsec configuration
233 +UseMnHaIPsec enabled;
235 +## Key Management Mobility Capability
236 +KeyMngMobCapability disabled;
239 + HomeAgentAddress 3ffe:2620:6:1::1;
240 + HomeAddress 3ffe:2620:6:1::1234/64;
242 + IPsecPolicy Mh UseESP;
243 + IPsecPolicy TunnelMh UseESP;
245 +# IPsecPolicy Mh UseESP 1 2;
246 +# IPsecPolicy ICMP UseESP 5;
247 +# IPsecPolicy TunnelMh UseESP 3 4;
249 diff -r c04f74757df5 include/netinet/icmp6.h
250 --- a/include/netinet/icmp6.h Sun Nov 30 23:14:35 2008 +0100
251 +++ b/include/netinet/icmp6.h Sun Nov 30 23:14:48 2008 +0100
253 #define mip_dhreq_code mip_dhreq_hdr.icmp6_code
254 #define mip_dhreq_cksum mip_dhreq_hdr.icmp6_cksum
255 #define mip_dhreq_id mip_dhreq_hdr.icmp6_data16[0]
256 -#define mip_dhreq_reserved mip_dhreq_hdr.icmp6_data16[1]
257 +#define mip_dhreq_flags_reserved mip_dhreq_hdr.icmp6_data16[1]
259 +#if BYTE_ORDER == BIG_ENDIAN
260 +#define MIP_DHREQ_FLAG_SUPPORT_MR 0x8000
261 +#else /* BYTE_ORDER == LITTLE_ENDIAN */
262 +#define MIP_DHREQ_FLAG_SUPPORT_MR 0x0080
266 #ifndef HAVE_STRUCT_MIP_DHAAD_REP
268 #define mip_dhrep_code mip_dhrep_hdr.icmp6_code
269 #define mip_dhrep_cksum mip_dhrep_hdr.icmp6_cksum
270 #define mip_dhrep_id mip_dhrep_hdr.icmp6_data16[0]
271 -#define mip_dhrep_reserved mip_dhrep_hdr.icmp6_data16[1]
272 +#define mip_dhrep_flags_reserved mip_dhrep_hdr.icmp6_data16[1]
274 +#if BYTE_ORDER == BIG_ENDIAN
275 +#define MIP_DHREP_FLAG_SUPPORT_MR 0x8000
276 +#else /* BYTE_ORDER == LITTLE_ENDIAN */
277 +#define MIP_DHREP_FLAG_SUPPORT_MR 0x0080
281 #ifndef HAVE_STRUCT_MIP_PREFIX_SOLICIT
283 struct nd_opt_homeagent_info { /* Home Agent information */
284 uint8_t nd_opt_hai_type;
285 uint8_t nd_opt_hai_len;
286 - uint16_t nd_opt_hai_reserved;
287 + uint16_t nd_opt_hai_flags_reserved;
288 uint16_t nd_opt_hai_preference;
289 uint16_t nd_opt_hai_lifetime;
293 +#define nd_opt_hai_reserved nd_opt_hai_flags_reserved
295 +#ifndef ND_OPT_HAI_FLAG_SUPPORT_MR
296 +#if BYTE_ORDER == BIG_ENDIAN
297 +#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x8000
298 +#else /* BYTE_ORDER == LITTLE_ENDIAN */
299 +#define ND_OPT_HAI_FLAG_SUPPORT_MR 0x0080
303 #endif /* netinet/icmp6.h */
304 diff -r c04f74757df5 licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt
305 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
306 +++ b/licenses/cisco-ipr-draft-ietf-nemo-basic-support-03.txt Sun Nov 30 23:14:48 2008 +0100
308 +Title: Cisco Systems' Updated Statement about IPR claimed in
309 + draft-ietf-nemo-basic-support-03.txt
310 +Received 25 October 2004
311 +From: Robert Barr <rbarr@cisco.com>
313 +This statement updates the IPR statement filed by Cisco on June 20, 2003 for
314 +draft-ietf-nemo-basic-support-00.txt.
316 +Cisco is the owner of US Patent No. 6,636,498 and at least one pending
318 +relating to the subject matter of draft-ietf-nemo-basic-support-03.txt
319 +"Network Mobility (NEMO) Basic Support Protocol" .
320 +If a standard relating to this subject matter is adopted by IETF and any
322 +of any issued Cisco patents are necessary for practicing this standard, any
323 +party will be able to obtain a license from Cisco to use any such patent
324 +claims under openly specified, reasonable, non-discriminatory terms, with
325 +reciprocity, to implement and fully comply with the standard.
327 +The reasonable non-discriminatory terms are:
329 +If this standard is adopted, Cisco will not assert any patents owned or
330 +controlled by Cisco against any party for making, using, selling, importing
331 +or offering for sale a product that implements the standard, provided,
332 +however that Cisco retains the right to assert its patents (including the
333 +right to claim past royalties) against any party that asserts a patent it
334 +owns or controls (either directly or indirectly) against Cisco or any of
335 +Cisco's affiliates or successors in title; and Cisco retains the right to
336 +assert its patents against any product or portion thereof that is not
337 +necessary for compliance with the standard.
339 +Royalty-bearing licenses will be available to anyone who prefers that
342 +For information contact:
345 +Worldwide Patent Counsel
349 diff -r c04f74757df5 licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt
350 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
351 +++ b/licenses/nokia-ipr-draft-ietf-nemo-basic-support.txt Sun Nov 30 23:14:48 2008 +0100
353 +Title: Nokia Corporation's statement about IPR claimed in draft-ietf-nemo-basic-support
354 +Received: July 1, 2003
355 +From: Heikki Huttunen <heikki.a.huttunen@nokia.com>
357 +This is to advise the IETF that Nokia believes the Nokia patent application "Mobile Router
358 +Support for IPv6", US10/295014, WO03/043226 may be relevant to Nemo Basic Support Protocol
359 +<draft-ietf-nemo-basic-support>.
361 +Regarding internet draft "draft-ietf-nemo-basic-support", to the extent this draft is
362 +included into final IETF standard specification, Nokia agrees not to assert those claims
363 +in Nokia patents that apply to this draft and that are technically necessary to implement
364 +the IETF standard specification against any other party in respect of its implementation of
365 +the specification, if only practiced under any software distributed under the present terms
366 +of GNU GENERAL PUBLIC LICENSE (http://www.fsf.org/copyleft/gpl.html) or under license terms
367 +that conform to the present open source definition (http://www.opensource.org/osd.html) and
368 +provided that the party relying on this commitment does not assert its patents against Nokia.
370 +Otherwise general Nokia Statement on Patent Licensing (http://www.ietf.org/ietf/IPR/NOKIA)
371 +applies to this submission.
377 +P.O Box 86, FIN-24101 Salo, Finland
378 +Phone: +358 (0) 7180 41202, Fax: +358 (0) 7180 44275
379 diff -r c04f74757df5 man/mip6d.conf.tmpl
380 --- a/man/mip6d.conf.tmpl Sun Nov 30 23:14:35 2008 +0100
381 +++ b/man/mip6d.conf.tmpl Sun Nov 30 23:14:48 2008 +0100
383 .\" $Id: mip6d.conf.tmpl 1.33 06/05/12 11:48:36+03:00 vnuorval@tcs.hut.fi $
384 -.TH mip6d.conf 5 "January 31, 2006" "" "Mobile IPv6 Daemon Configuration"
385 +.TH mip6d.conf 5 "January 31, 2006" "" "Mobile IPv6 and NEMO Daemon Configuration"
387 -mip6d.conf \- MIPL Mobile IPv6 Configuration file
388 +mip6d.conf \- MIPL Mobile IPv6 and NEMO Configuration file
393 -MIPL Mobile IPv6 daemon's configuration file
394 +MIPL Mobile IPv6 and NEMO daemon's configuration file
396 Below is a list of currently supported configuration options. All
397 configuration lines are terminated with a semicolon. Sub-sections are
398 @@ -184,10 +184,29 @@
402 -.BR "BindingAclPolicy " "address " "allow | deny"
403 +.BR "HaAcceptMobRtr enabled | disabled"
405 -Defines if a MN is allowed to register with the HA or not. The MN home address
406 -of the MN is given in the address field."
407 +Indicates if the HA accepts Mobile Router bindings.
412 +.BR "HaServedPrefix " "prefix/length" ";"
414 +Prefix is an IPv6 prefix and length is the prefix length. Defines the whole
415 +aggregated or extended prefix the HA serves. This option is only used for MR
416 +bindings and is only needed if the MRs derive their Home Addresses from their
417 +Mobile Network Prefixes, instead of one of the home link prefixes.
420 +.BR "BindingAclPolicy " "address MNP list " "allow | deny"
422 +Defines if a MN is allowed to register with the HA or not. The home address
423 +of the MN is given in the address field. The mobile network prefixes
424 +belonging a NEMO Mobile Router are listed in the MNP list. The list can either
425 +be an empty string or a comma separated list of network prefixes
426 +enclosed in braces, for example:
427 +.B "(3ffe:2620:6:3::/64, 3ffe:2620:6:4::/64)"
430 .BR "DefaultBindingAclPolicy allow | deny"
435 +.BR "MobRtrUseExplicitMode enabled | disabled"
437 +Toggles between explicit or implicit mode home registrations in the MR.
442 .BR "UseCnBuAck " "boolean" ";"
444 Indicates if the Acknowledge bit should be set in Binding Updates sent to
448 .BR "MnHomeLink " "name " "{"
449 -.BR " HomeAddress " "address/length" ";"
450 +.BR " HomeAddress " "address/length MNP list" ";"
451 .BR " HomeAgentAddress " "address" ";"
452 .BR " MnRoPolicy ..."
454 @@ -317,11 +343,14 @@
455 definitions. All the home link specific definitions are detailed below:
458 -.BR "HomeAddress " "address/length" ";"
459 +.BR "HomeAddress " "address/length MNP list" ";"
461 Address is an IPv6 address, and length the prefix length of the
462 -address, usually 64. This option must be included in a home link
464 +address, usually 64. The MNP list contains the mobile network prefixes
465 +belonging to that particular NEMO Mobile Router. The MNP list is of the
467 +.B "BindingAclPolicy."
468 +This option must be included in a home link definition.
471 .BR "HomeAgentAddress " "address" ";"
476 +.BR "IsMobRtr enabled | disabled"
478 +Defines if the MN is a NEMO MR.
483 The route optimization policies are of the form:
490 +.BR "A NEMO Home Agent example:"
497 +HaAcceptMobRtr enabled;
499 +HaServedPrefix 3ffe:2620:6::/48;
501 +DefaultBindingAclPolicy deny;
502 +BindingAclPolicy 3ffe:2620:6:1::1234 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64) allow;
503 +BindingAclPolicy 3ffe:2620:6:1::1235 allow;
505 +UseMnHaIPsec disabled;
509 +.BR "A NEMO Mobile Router example:"
514 +DoRouteOptimizationCN disabled;
515 +DoRouteOptimizationMN disabled;
521 +MobRtrUseExplicitMode enabled;
525 + HomeAgentAddress 3ffe:2620:6:1::1;
526 + HomeAddress 3ffe:2620:6:1::1234/64 (3ffe:2620:6:2::/64, 3ffe:2620:6:3::/64);
529 +UseMnHaIPsec disabled;
533 .BR "A Correspondent Node example:"
536 diff -r c04f74757df5 man/mip6d.tmpl
537 --- a/man/mip6d.tmpl Sun Nov 30 23:14:35 2008 +0100
538 +++ b/man/mip6d.tmpl Sun Nov 30 23:14:48 2008 +0100
540 .\" $Id: mip6d.tmpl 1.4 05/05/16 13:13:41+03:00 anttit@tcs.hut.fi $
541 -.TH mip6d 1 "May 16, 2005" "" "Mobile IPv6 Daemon"
542 +.TH mip6d 1 "May 16, 2005" "" "Mobile IPv6 and NEMO Daemon"
544 -mip6d \- MIPL Mobile IPv6 protocol implementation
545 +mip6d \- MIPL Mobile IPv6 and NEMO Basic Support protocol implementation
551 -Mobile IPv6 implementation
552 +Mobile IPv6 and NEMO Basic Support implementation
555 .IP "\fB\-V, \-\-version\fP"
558 RFC3776: Using IPsec to Protect Mobile IPv6 Signaling Between Mobile
559 Nodes and Home Agents
561 +RFC3963: Network Mobility (NEMO) Basic Support Protocol
562 diff -r c04f74757df5 src/bcache.c
563 --- a/src/bcache.c Sun Nov 30 23:14:35 2008 +0100
564 +++ b/src/bcache.c Sun Nov 30 23:14:48 2008 +0100
571 #define BCACHE_BUCKETS 32
574 fprintf(out, " lifetime %ld\n ", e->lifetime.tv_sec);
575 fprintf(out, " seqno %d\n", e->seqno);
577 + if (e->flags & IP6_MH_BA_MR) {
578 + struct list_head *list;
581 + /* MR registration type */
582 + fprintf(out, "MR Registration type: ");
583 + switch(e->nemo_type) {
584 + case BCE_NEMO_EXPLICIT:
585 + fprintf(out, "explicit.\n");
587 + case BCE_NEMO_IMPLICIT:
588 + fprintf(out, "implicit.\n");
591 + fprintf(out, "unknown.\n");
594 + /* Mobile Network prefixes */
595 + fprintf(out, "MR Mobile network prefixes: ");
596 + list_for_each(list, &e->mob_net_prefixes) {
597 + struct prefix_list_entry *p;
598 + p = list_entry(list, struct prefix_list_entry, list);
601 + fprintf(out, "%x:%x:%x:%x:%x:%x:%x:%x/%d\n",
602 + NIP6ADDR(&p->ple_prefix), p->ple_plen);
606 + fprintf(out, " none registered.\n");
615 INIT_LIST_HEAD(&tmp->tqe.list);
616 + INIT_LIST_HEAD(&tmp->mob_net_prefixes);
621 /* This function should really return allocated space to free
623 pthread_rwlock_destroy(&bce->lock);
624 + prefix_list_free(&bce->mob_net_prefixes);
628 diff -r c04f74757df5 src/bcache.h
629 --- a/src/bcache.h Sun Nov 30 23:14:35 2008 +0100
630 +++ b/src/bcache.h Sun Nov 30 23:14:48 2008 +0100
635 - int type; /* Entry type */
636 + uint16_t type; /* Entry type */
637 + uint16_t nemo_type; /* NEMO registration type */
638 int unreach; /* ICMP dest unreach count */
639 int tunnel; /* Tunnel interface index */
640 int link; /* Home link interface index */
642 struct tq_elem tqe; /* Timer queue entry for expire */
644 void (*cleanup)(struct bcentry *bce); /* Clean up bce data */
646 + struct list_head mob_net_prefixes;
649 #define BCE_NONCE_BLOCK 0
651 #define BCE_CACHE_DYING 3
654 +#define BCE_NEMO_EXPLICIT 1
655 +#define BCE_NEMO_IMPLICIT 2
656 +#define BCE_NEMO_DYNAMIC 3
658 struct bcentry *bcache_alloc(int type);
660 void bcache_free(struct bcentry *bce);
661 diff -r c04f74757df5 src/bul.c
662 --- a/src/bul.c Sun Nov 30 23:14:35 2008 +0100
663 +++ b/src/bul.c Sun Nov 30 23:14:48 2008 +0100
665 if (e->flags & IP6_MH_BU_ACK)
666 fprintf(out, "IP6_MH_BU_ACK ");
667 if (e->flags & IP6_MH_BU_LLOCAL)
668 - fprintf(out, "IP6_MH_BU_LLOCAL");
669 + fprintf(out, "IP6_MH_BU_LLOCAL ");
670 if (e->flags & IP6_MH_BU_KEYM)
671 - fprintf(out, "IP6_MH_BU_KEYM");
672 + fprintf(out, "IP6_MH_BU_KEYM ");
673 + if (e->flags & IP6_MH_BU_MR)
674 + fprintf(out, "IP6_MH_BU_MR");
680 } else if (bule->type == NON_MIP_CN_ENTRY) {
681 if (bule->flags & IP6_MH_BU_HOME) {
682 - if (xfrm_block_hoa(hai) < 0)
683 + if (xfrm_block_hoa(hai) < 0 ||
684 + (hai->mob_rtr && xfrm_block_ra(hai) < 0))
689 xfrm_unblock_link(hai);
690 if (hai->home_block & HOME_ADDR_BLOCK)
691 xfrm_unblock_hoa(hai);
692 + if (hai->home_block & NEMO_RA_BLOCK)
693 + xfrm_unblock_ra(hai);
694 + if (hai->home_block & NEMO_FWD_BLOCK)
695 + xfrm_unblock_fwd(hai);
698 while (bule->ext_cleanup)
699 diff -r c04f74757df5 src/cn.c
700 --- a/src/cn.c Sun Nov 30 23:14:35 2008 +0100
701 +++ b/src/cn.c Sun Nov 30 23:14:48 2008 +0100
703 non_ind = mh_opt(&bu->ip6mhbu_hdr, &mh_opts, IP6_MHOPT_NONCEID);
704 bce = bcache_get(out.src, out.dst);
706 - if ((bce->flags^bu_flags) & IP6_MH_BU_HOME) {
707 - /* H-bit mismatch, flags changed */
708 + if ((bce->flags^bu_flags) & (IP6_MH_BU_HOME|IP6_MH_BU_MR)) {
709 + /* H-bit or R-bit mismatch, flags changed */
710 bcache_release_entry(bce);
712 status = IP6_MH_BAS_REG_NOT_ALLOWED;
714 /* else get rid of it */
715 bcache_delete(out.src, out.dst);
717 - } else if (bu_flags & IP6_MH_BU_HOME) {
718 - status = IP6_MH_BAS_HA_NOT_SUPPORTED;
721 + if (bu_flags & IP6_MH_BU_HOME) {
722 + status = IP6_MH_BAS_HA_NOT_SUPPORTED;
725 + if (bu_flags & IP6_MH_BU_MR) {
726 + status = IP6_MH_BAS_MR_OP_NOT_PERMITTED;
730 status = conf.pmgr.discard_binding(out.dst, out.bind_coa,
732 diff -r c04f74757df5 src/conf.c
733 --- a/src/conf.c Sun Nov 30 23:14:35 2008 +0100
734 +++ b/src/conf.c Sun Nov 30 23:14:48 2008 +0100
736 INIT_LIST_HEAD(&c->home_addrs);
737 c->MoveModulePath = NULL; /* internal */
738 c->DoRouteOptimizationMN = 1;
739 + c->MobRtrUseExplicitMode = 1;
740 c->SendMobPfxSols = 1;
741 c->OptimisticHandoff = 0;
744 c->MaxMobPfxAdvInterval = 86400; /* seconds */
745 c->MinMobPfxAdvInterval = 600; /* seconds */
746 c->HaMaxBindingLife = MAX_BINDING_LIFETIME;
747 + INIT_LIST_HEAD(&c->nemo_ha_served_prefixes);
750 c->DoRouteOptimizationCN = 1;
752 CONF_BOOL_STR(c->MnDiscardHaParamProb));
753 dbg("SendMobPfxSols = %s\n", CONF_BOOL_STR(c->SendMobPfxSols));
754 dbg("OptimisticHandoff = %s\n", CONF_BOOL_STR(c->OptimisticHandoff));
755 + dbg("MobRtrUseExplicitMode = %s\n",
756 + CONF_BOOL_STR(c->MobRtrUseExplicitMode));
759 dbg("SendMobPfxAdvs = %s\n", CONF_BOOL_STR(c->SendMobPfxAdvs));
761 dbg("MaxMobPfxAdvInterval = %u\n", c->MaxMobPfxAdvInterval);
762 dbg("MinMobPfxAdvInterval = %u\n", c->MinMobPfxAdvInterval);
763 dbg("HaMaxBindingLife = %u\n", c->HaMaxBindingLife);
765 + dbg("HaAcceptMobRtr = %s\n", CONF_BOOL_STR(c->HaAcceptMobRtr));
768 dbg("DoRouteOptimizationCN = %s\n",
769 CONF_BOOL_STR(c->DoRouteOptimizationCN));
770 diff -r c04f74757df5 src/conf.h
771 --- a/src/conf.h Sun Nov 30 23:14:35 2008 +0100
772 +++ b/src/conf.h Sun Nov 30 23:14:48 2008 +0100
774 struct list_head home_addrs;
775 char *MoveModulePath;
777 + char MobRtrUseExplicitMode;
778 char DoRouteOptimizationMN;
779 char MnUseAllInterfaces;
780 char MnDiscardHaParamProb;
782 char OptimisticHandoff;
785 + char HaAcceptMobRtr;
787 char SendUnsolMobPfxAdvs;
788 unsigned int MaxMobPfxAdvInterval;
789 unsigned int MinMobPfxAdvInterval;
790 unsigned int HaMaxBindingLife;
791 + struct list_head nemo_ha_served_prefixes;
794 char DoRouteOptimizationCN;
799 diff -r c04f74757df5 src/dhaad_ha.c
800 --- a/src/dhaad_ha.c Sun Nov 30 23:14:35 2008 +0100
801 +++ b/src/dhaad_ha.c Sun Nov 30 23:14:48 2008 +0100
803 pthread_rwlock_unlock(&ha_lock);
806 -void dhaad_insert_halist(struct ha_interface *i,
807 - uint16_t key, uint16_t life_sec,
808 +void dhaad_insert_halist(struct ha_interface *i, uint16_t key,
809 + uint16_t life_sec, uint16_t flags,
810 struct nd_opt_prefix_info *pinfo,
811 const struct in6_addr *lladdr)
816 memset(ha, 0, sizeof(*ha));
820 INIT_LIST_HEAD(&ha->tqe.list);
821 @@ -136,18 +137,22 @@
825 -static int dhaad_get_halist(struct ha_interface *i, int max, struct iovec *iov)
826 +static int dhaad_get_halist(struct ha_interface *i, uint16_t flags,
827 + int max, struct iovec *iov)
829 struct list_head *lp;
831 list_for_each(lp, &i->ha_list) {
832 struct home_agent *h;
833 h = list_entry(lp, struct home_agent, list);
835 - iov[n].iov_len = sizeof(struct in6_addr);
836 - iov[n].iov_base = &h->addr;
839 + if (!(flags & MIP_DHREQ_FLAG_SUPPORT_MR) ||
840 + h->flags & ND_OPT_HAI_FLAG_SUPPORT_MR) {
842 + iov[n].iov_len = sizeof(struct in6_addr);
843 + iov[n].iov_base = &h->addr;
852 rph->mip_dhrep_id = rqh->mip_dhreq_id;
854 + if (rqh->mip_dhreq_flags_reserved & MIP_DHREQ_FLAG_SUPPORT_MR)
855 + rph->mip_dhrep_flags_reserved = MIP_DHREP_FLAG_SUPPORT_MR;
857 pthread_rwlock_rdlock(&ha_lock);
858 - iovlen = dhaad_get_halist(i, MAX_HOME_AGENTS, iov);
859 + iovlen = dhaad_get_halist(i, rqh->mip_dhreq_flags_reserved,
860 + MAX_HOME_AGENTS, iov);
861 icmp6_send(i->ifindex, 64, ha_addr, src, iov, iovlen + 1);
862 pthread_rwlock_unlock(&ha_lock);
863 free_iov_data(&iov[0], 1);
864 diff -r c04f74757df5 src/dhaad_ha.h
865 --- a/src/dhaad_ha.h Sun Nov 30 23:14:35 2008 +0100
866 +++ b/src/dhaad_ha.h Sun Nov 30 23:14:48 2008 +0100
868 int (* func)(int, void *, void *), void *arg);
871 -void dhaad_insert_halist(struct ha_interface *i,
872 - uint16_t key, uint16_t life_sec,
873 +void dhaad_insert_halist(struct ha_interface *i, uint16_t key,
874 + uint16_t life_sec, uint16_t flags,
875 struct nd_opt_prefix_info *pinfo,
876 const struct in6_addr *lladdr);
878 diff -r c04f74757df5 src/dhaad_mn.c
879 --- a/src/dhaad_mn.c Sun Nov 30 23:14:35 2008 +0100
880 +++ b/src/dhaad_mn.c Sun Nov 30 23:14:48 2008 +0100
884 static int dhaad_send_request(int oif, struct in6_addr *src,
885 - struct in6_addr *pfx, int plen)
886 + struct in6_addr *pfx, int plen,
889 struct mip_dhaad_req *ih;
894 ih->mip_dhreq_id = htons(id);
895 + ih->mip_dhreq_flags_reserved = flags;
896 dhaad_gen_ha_anycast(&dst, pfx, plen);
897 icmp6_send(oif, 0, src, &dst, &iov, 1);
898 free_iov_data(&iov, 1);
900 t->dhaad_id = dhaad_send_request(hai->primary_coa.iif,
901 &hai->primary_coa.addr,
906 + MIP_DHREQ_FLAG_SUPPORT_MR:0);
908 tsadd(t->dhaad_delay, t->dhaad_delay, t->dhaad_delay);
909 add_task_rel(&t->dhaad_delay, &t->tqe, dhaad_resend);
910 @@ -139,11 +143,15 @@
911 t->dhaad_resends == DHAAD_RETRIES))) {
912 if (!(hai->home_block & HOME_ADDR_BLOCK))
914 + if (hai->mob_rtr && !(hai->home_block & NEMO_RA_BLOCK))
915 + xfrm_block_ra(hai);
916 t->dhaad_resends = 0;
917 t->dhaad_id = dhaad_send_request(hai->primary_coa.iif,
918 &hai->primary_coa.addr,
923 + MIP_DHREQ_FLAG_SUPPORT_MR:0);
924 t->dhaad_delay = INITIAL_DHAAD_TIMEOUT_TS;
925 add_task_rel(&t->dhaad_delay, &t->tqe, dhaad_resend);
928 tsclear(t->dhaad_delay);
929 if (hai->home_block & HOME_ADDR_BLOCK)
930 xfrm_unblock_hoa(hai);
931 + if (hai->home_block & NEMO_RA_BLOCK)
932 + xfrm_unblock_ra(hai);
935 void dhaad_stop(struct home_addr_info *hai)
937 pthread_rwlock_unlock(&mn_lock);
940 + if (hai->mob_rtr &&
941 + !(rph->mip_dhrep_flags_reserved & MIP_DHREP_FLAG_SUPPORT_MR)) {
942 + dbg("HA doesn't support MR\n");
943 + pthread_rwlock_unlock(&mn_lock);
946 ha = (struct in6_addr *)(ih + 1);
948 dhaad_flush_candidates(&hai->ha_list);
949 diff -r c04f74757df5 src/gram.y
950 --- a/src/gram.y Sun Nov 30 23:14:35 2008 +0100
951 +++ b/src/gram.y Sun Nov 30 23:14:48 2008 +0100
958 #include <netinet/in.h>
963 #include <netinet/ip6mh.h>
967 struct home_addr_info hai = {
968 - .ro_policies = LIST_HEAD_INIT(hai.ro_policies)
969 + .ro_policies = LIST_HEAD_INIT(hai.ro_policies),
970 + .mob_net_prefixes = LIST_HEAD_INIT(hai.mob_net_prefixes)
973 +LIST_HEAD(prefixes);
975 +int mv_prefixes(struct list_head *list)
977 + struct list_head *l, *n;
979 + list_for_each_safe(l, n, &prefixes) {
981 + list_add_tail(l, list);
987 struct policy_bind_acl_entry *bae = NULL;
989 struct ipsec_policy_set {
991 %token MNROUTERPROBETIMEOUT
992 %token MNDISCARDHAPARAMPROB
993 %token OPTIMISTICHANDOFF
995 +%token HAACCEPTMOBRTR
997 +%token HASERVEDPREFIX
998 +%token MOBRTRUSEEXPLICITMODE
1002 @@ -282,6 +302,19 @@
1004 conf.DefaultBindingAclPolicy = $2;
1006 + | HAACCEPTMOBRTR BOOL ';'
1008 + conf.HaAcceptMobRtr = $2;
1010 + | HASERVEDPREFIX prefixlistentry ';'
1012 + list_splice(&prefixes,
1013 + conf.nemo_ha_served_prefixes.prev);
1015 + | MOBRTRUSEEXPLICITMODE BOOL ';'
1017 + conf.MobRtrUseExplicitMode = $2;
1019 | BINDINGACLPOLICY bindaclpolicy ';'
1022 @@ -398,12 +431,16 @@
1023 memcpy(nhai, &hai, sizeof(struct home_addr_info));
1024 INIT_LIST_HEAD(&nhai->ro_policies);
1025 INIT_LIST_HEAD(&nhai->ha_list.home_agents);
1026 + INIT_LIST_HEAD(&nhai->mob_net_prefixes);
1027 nhai->ha_list.dhaad_id = -1;
1028 list_splice(&hai.ro_policies, &nhai->ro_policies);
1029 + list_splice(&hai.mob_net_prefixes,
1030 + &nhai->mob_net_prefixes);
1031 list_add_tail(&nhai->list, &conf.home_addrs);
1033 memset(&hai, 0, sizeof(struct home_addr_info));
1034 INIT_LIST_HEAD(&hai.ro_policies);
1035 + INIT_LIST_HEAD(&hai.mob_net_prefixes);
1039 @@ -415,16 +452,35 @@
1041 memcpy(&hai.ha_addr, &$2, sizeof(struct in6_addr));
1043 - | HOMEADDRESS ADDR '/' prefixlen ';'
1045 - hai.hoa.addr = $2;
1048 + | HOMEADDRESS homeaddress ';'
1049 | USEALTCOA BOOL ';'
1053 | MNROPOLICY mnropolicy ';'
1054 + | ISMOBRTR BOOL ';'
1057 + hai.mob_rtr = IP6_MH_BU_MR;
1059 + | HOMEPREFIX ADDR '/' prefixlen ';'
1061 + ipv6_addr_prefix(&hai.home_prefix, &$2, $4);
1062 + hai.home_plen = $4;
1066 +homeaddress : homeaddrdef prefixlistsub
1068 + hai.mnp_count = mv_prefixes(&hai.mob_net_prefixes);
1072 +homeaddrdef : ADDR '/' prefixlen
1074 + hai.hoa.addr = $1;
1079 ipsecpolicyset : ipsechaaddrdef ipsecmnaddrdefs ipsecpolicydefs
1081 | NUMBER { $$ = $1; }
1084 -bindaclpolicy : ADDR bindaclpolval
1085 +bindaclpolicy : ADDR prefixlistsub bindaclpolval
1087 bae = malloc(sizeof(struct policy_bind_acl_entry));
1090 memset(bae, 0, sizeof(struct policy_bind_acl_entry));
1093 - bae->bind_policy = $2;
1094 + INIT_LIST_HEAD(&bae->mob_net_prefixes);
1095 + bae->mnp_count = mv_prefixes(&bae->mob_net_prefixes);
1096 + bae->bind_policy = $3;
1097 list_add_tail(&bae->list, &conf.bind_acl);
1100 @@ -664,4 +722,27 @@
1105 + | '(' prefixlist ')'
1108 +prefixlist : prefixlistentry
1109 + | prefixlist ',' prefixlistentry
1112 +prefixlistentry : ADDR '/' prefixlen
1114 + struct prefix_list_entry *p;
1115 + p = malloc(sizeof(struct prefix_list_entry));
1118 + "%s: out of memory\n", __FUNCTION__);
1121 + memset(p, 0, sizeof(struct prefix_list_entry));
1122 + p->ple_prefix = $1;
1124 + list_add_tail(&p->list, &prefixes);
1128 diff -r c04f74757df5 src/ha.c
1129 --- a/src/ha.c Sun Nov 30 23:14:35 2008 +0100
1130 +++ b/src/ha.c Sun Nov 30 23:14:48 2008 +0100
1132 struct ha_interface *iface;
1135 + uint16_t flags = 0;
1137 /* validity checks */
1138 if (hoplimit < 255 || !IN6_IS_ADDR_LINKLOCAL(src) ||
1140 hainfo = (struct nd_opt_homeagent_info *)opt;
1141 pref = ntohs(hainfo->nd_opt_hai_preference);
1142 life = ntohs(hainfo->nd_opt_hai_lifetime);
1143 + flags = hainfo->nd_opt_hai_flags_reserved;
1148 if (pinfo[i]->nd_opt_pi_flags_reserved &
1149 ND_OPT_PI_FLAG_RADDR) {
1150 dhaad_insert_halist(iface, pref, life,
1152 + flags, pinfo[i], src);
1155 mpd_del_expired_pinfos(iface);
1156 @@ -499,14 +501,53 @@
1161 +static void nemo_ha_del_mnp_routes(struct list_head *old_mnps,
1162 + struct list_head *new_mnps,
1163 + int ifindex, int all)
1165 + struct list_head *list;
1166 + list_for_each(list, old_mnps) {
1167 + struct prefix_list_entry *p;
1168 + p = list_entry(list, struct prefix_list_entry, list);
1170 + prefix_list_find(new_mnps, &p->ple_prefix, p->ple_plen))
1173 + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
1174 + NULL, 0, &p->ple_prefix, p->ple_plen, NULL);
1178 +static int nemo_ha_add_mnp_routes(struct list_head *old_mnps,
1179 + struct list_head *new_mnps,
1180 + int ifindex, int all)
1182 + struct list_head *list;
1183 + list_for_each(list, new_mnps) {
1184 + struct prefix_list_entry *p;
1185 + p = list_entry(list, struct prefix_list_entry, list);
1187 + prefix_list_find(old_mnps, &p->ple_prefix, p->ple_plen))
1189 + if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
1190 + 0, IP6_RT_PRIO_MIP6_FWD,
1191 + NULL, 0, &p->ple_prefix, p->ple_plen, NULL) < 0)
1197 struct home_tnl_ops_parm {
1198 struct bcentry *bce;
1200 + struct list_head mob_net_prefixes;
1203 static int home_tnl_del(int old_if, int new_if, struct home_tnl_ops_parm *p)
1205 const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
1206 + struct list_head *mnp;
1210 @@ -514,17 +555,22 @@
1211 peer_addr = &p->bce->peer_addr;
1212 coa = &p->bce->peer_addr;
1213 old_coa = &p->bce->coa;
1214 + mnp = &p->bce->mob_net_prefixes;
1216 if (conf.UseMnHaIPsec) {
1218 ha_ipsec_tnl_update(our_addr, peer_addr,
1219 - coa, old_coa, p->bce->tunnel);
1220 + coa, old_coa, p->bce->tunnel, mnp);
1221 /* delete SP entry */
1222 - ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel);
1223 + ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel, mnp);
1225 /* delete HoA route */
1226 route_del(old_if, RT6_TABLE_MAIN,
1227 IP6_RT_PRIO_MIP6_FWD, NULL, 0, peer_addr, 128, NULL);
1229 + /* delete MNP routes */
1230 + nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes,
1231 + &p->mob_net_prefixes, old_if, 1);
1232 /* update tunnel interface */
1233 p->bce->tunnel = new_if;
1235 @@ -534,17 +580,29 @@
1236 static int home_tnl_add(int old_if, int new_if, struct home_tnl_ops_parm *p)
1238 const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
1239 + struct list_head *mnp;
1243 our_addr = &p->bce->our_addr;
1244 peer_addr = &p->bce->peer_addr;
1246 - old_coa = &p->bce->peer_addr;
1247 + old_coa = IN6_ARE_ADDR_EQUAL(&p->bce->old_coa, &in6addr_any) ?
1248 + &p->bce->peer_addr : &p->bce->old_coa;
1249 + mnp = &p->mob_net_prefixes;
1251 /* update tunnel interface */
1252 p->bce->tunnel = new_if;
1254 + /* add MNP routes */
1255 + if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes,
1256 + &p->mob_net_prefixes, new_if, 1) < 0) {
1257 + if (p->bce->nemo_type == BCE_NEMO_EXPLICIT)
1258 + p->ba_status = IP6_MH_BAS_INVAL_PRFX;
1260 + p->ba_status = IP6_MH_BAS_FWDING_FAILED;
1264 if (route_add(new_if, RT6_TABLE_MAIN,
1265 RTPROT_MIP, 0, IP6_RT_PRIO_MIP6_FWD,
1266 @@ -555,13 +613,13 @@
1268 if (conf.UseMnHaIPsec) {
1269 if (ha_ipsec_tnl_pol_add(our_addr, peer_addr,
1270 - p->bce->tunnel) < 0) {
1271 + p->bce->tunnel, mnp) < 0) {
1272 p->ba_status = IP6_MH_BAS_INSUFFICIENT;
1276 if (ha_ipsec_tnl_update(our_addr, peer_addr, coa, old_coa,
1277 - p->bce->tunnel) < 0) {
1278 + p->bce->tunnel, mnp) < 0) {
1279 p->ba_status = IP6_MH_BAS_INSUFFICIENT;
1282 @@ -578,17 +636,51 @@
1284 if (old_if == new_if) {
1285 const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
1286 + struct list_head *mnp;
1288 our_addr = &p->bce->our_addr;
1289 peer_addr = &p->bce->peer_addr;
1291 old_coa = &p->bce->old_coa;
1292 + mnp = &p->mob_net_prefixes;
1294 + /* if interface hasn't changed, at least check if the
1295 + MR's MNPs have changed */
1296 + if (!prefix_list_cmp(&p->bce->mob_net_prefixes,
1297 + &p->mob_net_prefixes)) {
1299 + /* Remove old policies and install new ones */
1300 + if (conf.UseMnHaIPsec) {
1301 + ha_ipsec_mnp_pol_del(our_addr, peer_addr,
1302 + &p->bce->mob_net_prefixes,
1303 + &p->mob_net_prefixes,
1305 + ha_ipsec_mnp_pol_add(our_addr, peer_addr,
1306 + &p->bce->mob_net_prefixes,
1307 + &p->mob_net_prefixes,
1311 + /* Do the same for routes */
1312 + nemo_ha_del_mnp_routes(&p->bce->mob_net_prefixes,
1313 + &p->mob_net_prefixes,
1315 + if (nemo_ha_add_mnp_routes(&p->bce->mob_net_prefixes,
1316 + &p->mob_net_prefixes,
1318 + if (p->bce->nemo_type == BCE_NEMO_EXPLICIT)
1319 + p->ba_status = IP6_MH_BAS_INVAL_PRFX;
1321 + p->ba_status = IP6_MH_BAS_FWDING_FAILED;
1327 if (conf.UseMnHaIPsec &&
1328 !IN6_ARE_ADDR_EQUAL(old_coa, coa) &&
1329 ha_ipsec_tnl_update(our_addr, peer_addr, coa, old_coa,
1330 - p->bce->tunnel) < 0) {
1331 + p->bce->tunnel, mnp) < 0) {
1335 @@ -634,6 +726,61 @@
1340 +static int ha_extract_mnps(const struct ip6_mh_binding_update *bu,
1341 + const struct mh_options *opts,
1342 + struct list_head *mob_net_prefixes)
1344 + struct ip6_mh_opt_mob_net_prefix *op;
1345 + int prefix_count = 0;
1346 + for (op = mh_opt(&bu->ip6mhbu_hdr, opts, IP6_MHOPT_MOB_NET_PRFX);
1348 + op = mh_opt_next(&bu->ip6mhbu_hdr, opts, op)) {
1349 + struct prefix_list_entry *p;
1350 + p = malloc(sizeof(struct prefix_list_entry));
1352 + prefix_list_free(mob_net_prefixes);
1355 + memset(p, 0, sizeof(struct prefix_list_entry));
1356 + p->ple_plen = op->ip6mnp_prefix_len;
1357 + p->ple_prefix = op->ip6mnp_prefix;
1358 + list_add_tail(&p->list, mob_net_prefixes);
1361 + return prefix_count;
1364 +static int ha_get_mnps(const struct in6_addr *hoa,
1365 + struct list_head *mob_net_prefixes)
1367 + struct nd_opt_prefix_info *mnps;
1368 + int mnp_count = conf.pmgr.get_mnp_count(hoa);
1371 + if (mnp_count <= 0)
1374 + mnps = calloc(mnp_count, sizeof(struct nd_opt_prefix_info));
1378 + mnp_count = conf.pmgr.get_mnps(hoa, mnp_count, mnps);
1379 + for (i = 0; i < mnp_count; i++) {
1380 + struct prefix_list_entry *p;
1381 + p = malloc(sizeof(struct prefix_list_entry));
1383 + prefix_list_free(mob_net_prefixes);
1387 + p->pinfo = *(mnps + i);
1388 + list_add_tail(&p->list, mob_net_prefixes);
1394 struct ha_recv_bu_args {
1395 struct list_head list;
1396 struct in6_addr src;
1398 bce = bcache_get(out.src, out.dst);
1400 if (bce->type != BCE_NONCE_BLOCK) {
1401 - if (!(bce->flags & IP6_MH_BU_HOME)) {
1402 - /* H-bit mismatch, flags changed */
1403 + /* H-bit or R-bit mismatch, flags changed */
1404 + if ((bce->flags ^ bu_flags) &
1405 + (IP6_MH_BU_HOME | IP6_MH_BU_MR)) {
1406 bcache_release_entry(bce);
1408 status = IP6_MH_BAS_REG_NOT_ALLOWED;
1409 @@ -733,9 +881,15 @@
1411 if ((status = mpd_prefix_check(out.src, out.dst,
1412 &lft, &home_ifindex, new)) < 0) {
1413 - /* not home agent for this subnet */
1414 - status = IP6_MH_BAS_NOT_HOME_SUBNET;
1416 + if (!(bu_flags & IP6_MH_BU_MR) ||
1417 + home_ifindex == 0 ||
1418 + !prefix_list_find(&conf.nemo_ha_served_prefixes,
1420 + /* not home agent for this subnet */
1421 + status = IP6_MH_BAS_NOT_HOME_SUBNET;
1424 + status = IP6_MH_BAS_ACCEPTED;
1426 status = conf.pmgr.discard_binding(out.dst, out.bind_coa,
1427 out.src, arg->bu, arg->len);
1428 @@ -787,6 +941,25 @@
1432 + INIT_LIST_HEAD(&p.mob_net_prefixes);
1433 + if (bu_flags & IP6_MH_BU_MR && tsisset(lft)) {
1434 + if (mh_opt(&arg->bu->ip6mhbu_hdr,
1435 + &arg->mh_opts, IP6_MHOPT_MOB_NET_PRFX) != NULL) {
1436 + if (ha_extract_mnps(arg->bu,
1438 + &p.mob_net_prefixes) < 0) {
1439 + status = IP6_MH_BAS_INVAL_PRFX;
1442 + bce->nemo_type = BCE_NEMO_EXPLICIT;
1443 + } else if (ha_get_mnps(out.dst, &p.mob_net_prefixes) > 0) {
1444 + bce->nemo_type = BCE_NEMO_IMPLICIT;
1446 + /* Todo: dynamic routing */
1447 + status = IP6_MH_BAS_FWDING_FAILED;
1452 p.ba_status = status;
1455 status = IP6_MH_BAS_INSUFFICIENT;
1458 + /* Now save the MNP list in the BCE */
1459 + list_splice(&p.mob_net_prefixes, &bce->mob_net_prefixes);
1461 bce->cleanup = home_cleanup;
1463 if (route_add(bce->link, RT6_TABLE_MIP6,
1464 @@ -829,6 +1005,10 @@
1465 status = IP6_MH_BAS_INSUFFICIENT;
1468 + /* Now update the MNP list in the BCE */
1469 + prefix_list_free(&bce->mob_net_prefixes);
1470 + list_splice(&p.mob_net_prefixes, &bce->mob_net_prefixes);
1472 bcache_update_expire(bce);
1474 /* bce is always valid here */
1475 @@ -867,6 +1047,9 @@
1476 * have a binding before sending this Binding Update,
1477 * discard the connections to the home address. */
1479 + if (status < IP6_MH_BAS_UNSPECIFIED && bu_flags & IP6_MH_BU_MR)
1480 + ba_flags |= IP6_MH_BA_MR;
1482 if (!(arg->flags & HA_BU_F_SKIP_BA))
1483 mh_send_ba(&out, status, ba_flags, seqno, &lft, NULL, iif);
1484 if (new && tsisset(lft))
1485 diff -r c04f74757df5 src/ha.h
1486 --- a/src/ha.h Sun Nov 30 23:14:35 2008 +0100
1487 +++ b/src/ha.h Sun Nov 30 23:14:48 2008 +0100
1489 struct list_head list;
1490 struct in6_addr addr;
1491 uint16_t preference;
1493 struct timespec lifetime;
1494 struct ha_interface *iface;
1496 diff -r c04f74757df5 src/ipsec.c
1497 --- a/src/ipsec.c Sun Nov 30 23:14:35 2008 +0100
1498 +++ b/src/ipsec.c Sun Nov 30 23:14:48 2008 +0100
1500 struct ipsec_policy_entry *e,
1502 const struct in6_addr *in6_dst,
1504 const struct in6_addr *in6_src,
1510 sp->action = e->action;
1511 memcpy(&sp->sel.saddr.a6, in6_src, sizeof(sp->sel.saddr.a6));
1512 memcpy(&sp->sel.daddr.a6, in6_dst, sizeof(sp->sel.daddr.a6));
1513 - sp->sel.prefixlen_s = IN6_ARE_ADDR_EQUAL(in6_src, &in6addr_any) ?
1515 - sp->sel.prefixlen_d = IN6_ARE_ADDR_EQUAL(in6_dst, &in6addr_any) ?
1517 + sp->sel.prefixlen_s = src_len;
1518 + if (!src_len && (!IN6_ARE_ADDR_EQUAL(in6_src, &in6addr_any)))
1519 + sp->sel.prefixlen_s = 128;
1520 + sp->sel.prefixlen_d = dst_len;
1521 + if (!dst_len && (!IN6_ARE_ADDR_EQUAL(in6_dst, &in6addr_any)))
1522 + sp->sel.prefixlen_d = 128;
1524 sp->sel.ifindex = 0;
1529 struct in6_addr coa;
1530 struct in6_addr old_coa;
1531 + struct list_head *mnp;
1537 const struct in6_addr *oldcoa, *newcoa;
1538 const struct in6_addr *peer_addr = hoa;
1539 + struct list_head *mnp;
1540 u_int8_t ipsec_proto;
1541 struct xfrm_user_tmpl tmpl;
1542 struct xfrm_userpolicy_info sp;
1543 @@ -399,13 +406,14 @@
1544 oldcoa = IN6_ARE_ADDR_EQUAL(&info->old_coa, &in6addr_any) ?
1545 peer_addr : &info->old_coa;
1546 newcoa = &info->coa;
1549 dump_migrate(ifindex, ipsec_proto, hoa, haaddr, oldcoa, newcoa);
1552 _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1553 haaddr, oldcoa, e->reqid_toha);
1554 - _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, hoa,
1555 + _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, hoa, 0,
1556 ifindex, MIP6_ENTITY_HA);
1557 if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
1558 dbg("migrate for INBOUND policy failed\n");
1561 _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1562 haaddr, oldcoa, e->reqid_toha);
1563 - _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, hoa,
1564 + _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, hoa, 0,
1565 ifindex, MIP6_ENTITY_HA);
1566 if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
1567 dbg("migrate for FORWARD policy failed\n");
1568 @@ -425,13 +433,56 @@
1570 _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1571 oldcoa, haaddr, e->reqid_tomn);
1572 - _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, &in6addr_any,
1573 + _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, 0, &in6addr_any, 0,
1574 ifindex, MIP6_ENTITY_HA);
1575 if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
1576 dbg("migrate for OUTBOUND policy failed\n");
1580 + /* Mobile router case */
1581 + if ( (e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && mnp)
1583 + struct list_head *list;
1585 + /* We have to modify rules to protect traffic to and from MNP's, the same way as HoA */
1586 + list_for_each(list, mnp)
1588 + struct prefix_list_entry *p;
1589 + p = list_entry(list, struct prefix_list_entry, list);
1592 + _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1593 + haaddr, oldcoa, e->reqid_toha);
1594 + _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
1595 + ifindex, MIP6_ENTITY_HA);
1596 + if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
1597 + dbg("migrate for INBOUND policy failed\n");
1602 + _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1603 + haaddr, oldcoa, e->reqid_toha);
1604 + _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
1605 + ifindex, MIP6_ENTITY_HA);
1606 + if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
1607 + dbg("migrate for FORWARD policy failed\n");
1612 + _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1613 + oldcoa, haaddr, e->reqid_tomn);
1614 + _set_sp(&sp, e, XFRM_POLICY_OUT, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
1615 + ifindex, MIP6_ENTITY_HA);
1616 + if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
1617 + dbg("migrate for OUTBOUND policy failed\n");
1626 @@ -440,15 +491,178 @@
1627 const struct in6_addr *hoa,
1628 const struct in6_addr *coa,
1629 const struct in6_addr *old_coa,
1632 + struct list_head *mnp)
1634 struct ha_ipsec_tnl_update b;
1636 b.old_coa = *old_coa;
1639 return ipsec_policy_apply(haaddr, hoa, _ha_tnl_update, &b);
1642 +struct ha_ipsec_mnp_update {
1644 + struct list_head *old_mnps;
1645 + struct list_head *new_mnps;
1649 + * Add/Delete MNP IPsec Security Policy
1651 +static int _ha_mnp_pol_mod(const struct in6_addr *haaddr,
1652 + const struct in6_addr *hoa,
1653 + struct ipsec_policy_entry *e,
1658 + struct ha_ipsec_mnp_update *parms = (struct ha_ipsec_mnp_update *)arg;
1659 + struct xfrm_userpolicy_info sp;
1660 + struct xfrm_user_tmpl tmpl;
1661 + u_int16_t ipsec_proto;
1662 + struct list_head *list, *old_mnps, *new_mnps, *main_mnps, *ref_mnps;
1670 + ifindex = parms->tunnel;
1671 + old_mnps = parms->old_mnps;
1672 + new_mnps = parms->new_mnps;
1674 + if (e->type != IPSEC_POLICY_TYPE_TUNNELPAYLOAD)
1677 + /* XXX Limitation: Single IPsec proto can only be applied */
1678 + if (ipsec_use_esp(e))
1679 + ipsec_proto = IPPROTO_ESP;
1680 + else if (ipsec_use_ah(e))
1681 + ipsec_proto = IPPROTO_AH;
1682 + else if (ipsec_use_ipcomp(e))
1683 + ipsec_proto = IPPROTO_COMP;
1685 + dbg("invalid ipsec proto\n");
1689 + /* Reverse the search logic on lists based on expected
1690 + * action (add/del) */
1691 + main_mnps = add ? new_mnps : old_mnps;
1692 + ref_mnps = add ? old_mnps : new_mnps;
1694 + if (main_mnps == NULL)
1697 + /* We have to add/delete rules to protect traffic to
1698 + and from MNP's, the same way as HoA */
1699 + list_for_each(list, main_mnps) {
1700 + struct prefix_list_entry *p;
1701 + p = list_entry(list, struct prefix_list_entry, list);
1704 + prefix_list_find(ref_mnps, &p->ple_prefix, p->ple_plen))
1708 + _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
1709 + ifindex, MIP6_ENTITY_HA);
1710 + _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1711 + haaddr, hoa, e->reqid_toha);
1712 + if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
1713 + dbg("modifying INBOUND policy failed\n");
1719 + _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
1720 + ifindex, MIP6_ENTITY_HA);
1721 + _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1722 + haaddr, hoa, e->reqid_toha);
1723 + if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
1724 + dbg("modifying FORWARD policy failed\n");
1730 + _set_sp(&sp, e, XFRM_POLICY_OUT, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
1731 + ifindex, MIP6_ENTITY_HA);
1732 + _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1733 + hoa, haaddr, e->reqid_tomn);
1734 + if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
1735 + dbg("modifying OUTBOUND policy failed\n");
1747 + * Add SP entry (for MNP on HA)
1750 + * - This is a hook routine to ipsec_policy_apply()
1752 +static int _ha_mnp_pol_add(const struct in6_addr *haaddr,
1753 + const struct in6_addr *hoa,
1754 + struct ipsec_policy_entry *e,
1757 + return _ha_mnp_pol_mod(haaddr, hoa, e, arg, 1);
1760 +int ha_ipsec_mnp_pol_add(const struct in6_addr *our_addr,
1761 + const struct in6_addr *peer_addr,
1762 + struct list_head *old_mnps,
1763 + struct list_head *new_mnps,
1766 + struct ha_ipsec_mnp_update b;
1767 + b.tunnel = tunnel;
1768 + b.old_mnps = old_mnps;
1769 + b.new_mnps = new_mnps;
1771 + return ipsec_policy_apply(our_addr, peer_addr, _ha_mnp_pol_add, &b);
1775 + * Delete SP entry (for MNP on HA)
1778 + * - This is a hook routine to ipsec_policy_apply()
1780 +static int _ha_mnp_pol_del(const struct in6_addr *haaddr,
1781 + const struct in6_addr *hoa,
1782 + struct ipsec_policy_entry *e,
1785 + return _ha_mnp_pol_mod(haaddr, hoa, e, arg, 0);
1788 +int ha_ipsec_mnp_pol_del(const struct in6_addr *our_addr,
1789 + const struct in6_addr *peer_addr,
1790 + struct list_head *old_mnps,
1791 + struct list_head *new_mnps,
1794 + struct ha_ipsec_mnp_update b;
1795 + b.tunnel = tunnel;
1796 + b.old_mnps = old_mnps;
1797 + b.new_mnps = new_mnps;
1799 + return ipsec_policy_apply(our_addr, peer_addr,
1800 + _ha_mnp_pol_del, &b);
1804 * Add/Delete IPsec Security Policy
1810 - int ifindex = *(int *)arg;
1811 + struct ha_ipsec_tnl_update *parms = (struct ha_ipsec_tnl_update *)arg;
1813 + struct list_head *mnp;
1814 struct xfrm_userpolicy_info sp;
1815 struct xfrm_user_tmpl tmpl;
1816 u_int16_t ipsec_proto;
1821 + ifindex = parms->tunnel;
1825 case IPSEC_POLICY_TYPE_TUNNELHOMETESTING:
1826 case IPSEC_POLICY_TYPE_TUNNELMH:
1828 dump_migrate(ifindex, ipsec_proto, hoa, haaddr, NULL, NULL);
1831 - _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, hoa,
1832 + _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, hoa, 0,
1833 ifindex, MIP6_ENTITY_HA);
1834 _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1835 haaddr, hoa, e->reqid_toha);
1840 - _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, hoa,
1841 + _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, hoa, 0,
1842 ifindex, MIP6_ENTITY_HA);
1843 _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1844 haaddr, hoa, e->reqid_toha);
1849 - _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, &in6addr_any,
1850 + _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, 0, &in6addr_any, 0,
1851 ifindex, MIP6_ENTITY_HA);
1852 _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1853 hoa, haaddr, e->reqid_tomn);
1854 @@ -525,6 +744,16 @@
1858 + /* Mobile Router case */
1859 + if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && mnp) {
1860 + struct ha_ipsec_mnp_update b;
1862 + b.tunnel = ifindex;
1863 + b.old_mnps = add ? NULL : mnp;
1864 + b.new_mnps = add ? mnp : NULL;
1866 + err = _ha_mnp_pol_mod(haaddr, hoa, e, (void *)&b, add);
1871 @@ -545,11 +774,14 @@
1873 int ha_ipsec_tnl_pol_add(const struct in6_addr *our_addr,
1874 const struct in6_addr *peer_addr,
1877 + struct list_head *mnp)
1880 + struct ha_ipsec_tnl_update b;
1881 + b.tunnel = tunnel;
1884 - return ipsec_policy_apply(our_addr, peer_addr, _ha_tnl_pol_add, &t);
1885 + return ipsec_policy_apply(our_addr, peer_addr, _ha_tnl_pol_add, &b);
1889 @@ -568,12 +800,15 @@
1891 int ha_ipsec_tnl_pol_del(const struct in6_addr *our_addr,
1892 const struct in6_addr *peer_addr,
1895 + struct list_head *mnp)
1898 + struct ha_ipsec_tnl_update b;
1899 + b.tunnel = tunnel;
1902 return ipsec_policy_apply(our_addr, peer_addr,
1903 - _ha_tnl_pol_del, &t);
1904 + _ha_tnl_pol_del, &b);
1910 _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1911 haaddr, oldcoa, e->reqid_toha);
1912 - _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, hoa,
1913 + _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, hoa, 0,
1914 ifindex, MIP6_ENTITY_MN);
1915 if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
1916 dbg("migrate for OUTBOUND policy failed\n");
1919 _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1920 oldcoa, haaddr, e->reqid_tomn);
1921 - _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
1922 + _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
1923 ifindex, MIP6_ENTITY_MN);
1924 if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
1925 dbg("migrate for INBOUND policy (1) failed\n");
1928 _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1929 oldcoa, haaddr, e->reqid_tomn);
1930 - _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
1931 + _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
1932 ifindex, MIP6_ENTITY_MN);
1933 /* additional settings */
1934 sp.priority = MIP6_PRIO_RO_SIG_IPSEC;
1935 @@ -669,6 +904,52 @@
1940 + * If we are a Mobile Router, we also need to migrate IN/FWD/OUT rules
1941 + * for forwarded traffic in case we have TUNNELPAYLOAD protection.
1943 + if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && (bule->home->mob_rtr))
1945 + struct list_head *mnp;
1947 + list_for_each(mnp, &bule->home->mob_net_prefixes)
1949 + struct prefix_list_entry *p;
1950 + p = list_entry(mnp, struct prefix_list_entry, list);
1953 + _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1954 + haaddr, oldcoa, e->reqid_toha);
1955 + _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
1956 + ifindex, MIP6_ENTITY_MN);
1957 + if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
1958 + dbg("migrate for OUTBOUND policy failed\n");
1963 + _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1964 + oldcoa, haaddr, e->reqid_tomn);
1965 + _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
1966 + ifindex, MIP6_ENTITY_MN);
1967 + if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
1968 + dbg("migrate for INBOUND policy (1) failed\n");
1973 + _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
1974 + oldcoa, haaddr, e->reqid_tomn);
1975 + _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
1976 + ifindex, MIP6_ENTITY_MN);
1977 + if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
1978 + dbg("migrate for INBOUND policy (1) failed\n");
1988 @@ -724,7 +1005,7 @@
1989 dump_migrate(ifindex, ipsec_proto, hoa, haaddr, NULL, NULL);
1992 - _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
1993 + _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
1994 ifindex, MIP6_ENTITY_MN);
1995 _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
1996 hoa, haaddr, e->reqid_tomn);
1997 @@ -735,7 +1016,7 @@
2001 - _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, hoa,
2002 + _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, hoa, 0,
2003 ifindex, MIP6_ENTITY_MN);
2004 _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
2005 haaddr, hoa, e->reqid_toha);
2006 @@ -761,6 +1042,54 @@
2011 + * If we are a Mobile Router, we also need to create IN/FWD/OUT rules
2012 + * for forwarded traffic in case we have TUNNELPAYLOAD protection.
2014 + if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && (bule->home->mob_rtr))
2016 + struct list_head *mnp;
2018 + list_for_each(mnp, &bule->home->mob_net_prefixes)
2020 + struct prefix_list_entry *p;
2021 + p = list_entry(mnp, struct prefix_list_entry, list);
2024 + _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
2025 + ifindex, MIP6_ENTITY_MN);
2026 + _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
2027 + hoa, haaddr, e->reqid_tomn);
2028 + if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
2029 + dbg("modifying INBOUND policy failed.\n");
2035 + _set_sp(&sp, e, XFRM_POLICY_FWD, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
2036 + ifindex, MIP6_ENTITY_MN);
2037 + _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
2038 + hoa, haaddr, e->reqid_tomn);
2039 + if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
2040 + dbg("modifying INBOUND policy failed.\n");
2046 + _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
2047 + ifindex, MIP6_ENTITY_MN);
2048 + _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
2049 + haaddr, hoa, e->reqid_toha);
2050 + if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
2051 + dbg("modifying OUTBOUND policy failed.\n");
2061 diff -r c04f74757df5 src/ipsec.h
2062 --- a/src/ipsec.h Sun Nov 30 23:14:35 2008 +0100
2063 +++ b/src/ipsec.h Sun Nov 30 23:14:48 2008 +0100
2065 const struct in6_addr *hoa,
2066 const struct in6_addr *coa,
2067 const struct in6_addr *old_coa,
2070 + struct list_head *mnp);
2072 +int ha_ipsec_mnp_pol_del(const struct in6_addr *our_addr,
2073 + const struct in6_addr *peer_addr,
2074 + struct list_head *old_mnps,
2075 + struct list_head *new_mnps,
2078 +int ha_ipsec_mnp_pol_add(const struct in6_addr *our_addr,
2079 + const struct in6_addr *peer_addr,
2080 + struct list_head *old_mnps,
2081 + struct list_head *new_mnps,
2084 int ha_ipsec_tnl_pol_add(const struct in6_addr *our_addr,
2085 const struct in6_addr *peer_addr,
2088 + struct list_head *mnp);
2090 int ha_ipsec_tnl_pol_del(const struct in6_addr *our_addr,
2091 const struct in6_addr *peer_addr,
2094 + struct list_head *mnp);
2096 int mn_ipsec_tnl_update(const struct in6_addr *haaddr,
2097 const struct in6_addr *hoa,
2098 diff -r c04f74757df5 src/mh.c
2099 --- a/src/mh.c Sun Nov 30 23:14:35 2008 +0100
2100 +++ b/src/mh.c Sun Nov 30 23:14:48 2008 +0100
2105 +#include "prefix.h"
2107 #define MH_DEBUG_LEVEL 1
2110 0, /* Alternate CoA */
2111 0, /* Nonce Index */
2112 0, /* Binding Auth Data */
2113 + 1, /* Mobile Network Prefix */
2116 #define __MH_SENTINEL (IP6_MH_TYPE_MAX + 1)
2117 @@ -401,6 +403,46 @@
2121 +int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count,
2122 + struct list_head *mnps)
2124 + int optlen = (mnp_count * sizeof(struct ip6_mh_opt_mob_net_prefix) +
2125 + (mnp_count - 1) * sizeof(_pad4));
2126 + struct list_head *l;
2129 + iov->iov_base = malloc(optlen);
2130 + iov->iov_len = optlen;
2132 + if (iov->iov_base == NULL)
2135 + memset(iov->iov_base, 0, iov->iov_len);
2136 + data = (uint8_t *)iov->iov_base;
2138 + list_for_each(l, mnps) {
2139 + struct prefix_list_entry *p;
2140 + struct ip6_mh_opt_mob_net_prefix *mnp;
2142 + p = list_entry(l, struct prefix_list_entry, list);
2143 + mnp = (struct ip6_mh_opt_mob_net_prefix *)data;
2145 + mnp->ip6mnp_type = IP6_MHOPT_MOB_NET_PRFX;
2146 + mnp->ip6mnp_len = 18;
2147 + mnp->ip6mnp_prefix_len = p->ple_plen;
2148 + mnp->ip6mnp_prefix = p->ple_prefix;
2150 + data += sizeof(struct ip6_mh_opt_mob_net_prefix);
2152 + /* do internal padding here, so one iovec for MNPs is enough */
2153 + if (++i < mnp_count) {
2154 + memcpy(data, _pad4, sizeof(_pad4));
2155 + data += sizeof(_pad4);
2161 static size_t mh_length(struct iovec *vec, int count)
2165 case IP6_MHOPT_BAUTH:
2166 pad = optpad(8, 2, len); /* 8n+2 */
2168 + case IP6_MHOPT_MOB_NET_PRFX:
2169 + pad = optpad(8, 4, len); /* 8n+4 */
2173 create_opt_pad(&out[n++], pad);
2175 return len != sizeof(struct ip6_mh_opt_nonce_index);
2176 case IP6_MHOPT_BAUTH:
2177 return len != sizeof(struct ip6_mh_opt_auth_data);
2178 + case IP6_MHOPT_MOB_NET_PRFX:
2179 + return len != sizeof(struct ip6_mh_opt_mob_net_prefix);
2180 case IP6_MHOPT_PADN:
2183 diff -r c04f74757df5 src/mh.h
2184 --- a/src/mh.h Sun Nov 30 23:14:35 2008 +0100
2185 +++ b/src/mh.h Sun Nov 30 23:14:48 2008 +0100
2188 /* If new types or options appear, these should be updated. */
2189 #define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR
2190 -#define IP6_MHOPT_MAX IP6_MHOPT_BAUTH
2191 +#define IP6_MHOPT_MAX IP6_MHOPT_MOB_NET_PRFX
2193 struct in6_addr_bundle {
2194 struct in6_addr *src;
2197 int mh_create_opt_auth_data(struct iovec *iov);
2201 +int mh_create_opt_mob_net_prefix(struct iovec *iov, int mnp_count,
2202 + struct list_head *mnps);
2204 static inline void *mh_opt(const struct ip6_mh *mh,
2205 const struct mh_options *mh_opts, uint8_t type)
2207 diff -r c04f74757df5 src/mn.c
2208 --- a/src/mn.c Sun Nov 30 23:14:35 2008 +0100
2209 +++ b/src/mn.c Sun Nov 30 23:14:48 2008 +0100
2210 @@ -326,7 +326,17 @@
2211 free_iov_data(iov, iov_ind);
2214 - if (!(bule->flags & IP6_MH_BU_HOME)) {
2215 + if (bule->flags & IP6_MH_BU_HOME) {
2216 + struct home_addr_info *hai = bule->home;
2217 + if (bule->flags & IP6_MH_BU_MR && bu->ip6mhbu_lifetime &&
2218 + bule->home->mnp_count > 0 && conf.MobRtrUseExplicitMode &&
2219 + mh_create_opt_mob_net_prefix(&iov[iov_ind++],
2221 + &hai->mob_net_prefixes) < 0) {
2222 + free_iov_data(iov, iov_ind);
2226 if (mh_create_opt_nonce_index(&iov[iov_ind++], bule->rr.ho_ni,
2228 mh_create_opt_auth_data(&iov[iov_ind++])) {
2229 @@ -616,6 +626,34 @@
2233 +int nemo_mr_tnl_routes_add(struct home_addr_info *hai, int ifindex)
2235 + struct list_head *l;
2236 + struct prefix_list_entry *pe;
2237 + list_for_each(l, &hai->mob_net_prefixes) {
2238 + struct prefix_list_entry *p;
2239 + p = list_entry(l, struct prefix_list_entry, list);
2240 + if (route_add(ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
2241 + 0, IP6_RT_PRIO_MIP6_FWD,
2242 + &p->ple_prefix, p->ple_plen,
2243 + &in6addr_any, 0, NULL) < 0) {
2250 + list_for_each(l, &hai->mob_net_prefixes) {
2251 + struct prefix_list_entry *p;
2252 + p = list_entry(l, struct prefix_list_entry, list);
2253 + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
2254 + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
2261 static int mn_tnl_state_add(struct home_addr_info *hai, int ifindex, int all)
2264 @@ -628,12 +666,31 @@
2265 mn_ro_pol_del(hai, ifindex, all);
2268 + if (hai->mob_rtr &&
2269 + (err = nemo_mr_tnl_routes_add(hai, ifindex)) < 0) {
2270 + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
2271 + &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
2272 + mn_ro_pol_del(hai, ifindex, all);
2277 +static void nemo_mr_tnl_routes_del(struct home_addr_info *hai, int ifindex)
2279 + struct list_head *l;
2280 + list_for_each(l, &hai->mob_net_prefixes) {
2281 + struct prefix_list_entry *p;
2282 + p = list_entry(l, struct prefix_list_entry, list);
2283 + route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_FWD,
2284 + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, NULL);
2288 static void mn_tnl_state_del(struct home_addr_info *hai, int ifindex, int all)
2290 if (hai->home_reg_status != HOME_REG_NONE) {
2292 + nemo_mr_tnl_routes_del(hai, ifindex);
2293 route_del(ifindex, RT6_TABLE_MIP6, IP6_RT_PRIO_MIP6_OUT,
2294 &hai->hoa.addr, 128, &in6addr_any, 0, NULL);
2295 mn_ro_pol_del(hai, ifindex, all);
2299 bule->type = BUL_ENTRY;
2300 - bule->flags = IP6_MH_BU_HOME | IP6_MH_BU_ACK | hai->lladdr_comp;
2301 + bule->flags = (IP6_MH_BU_HOME | IP6_MH_BU_ACK |
2302 + hai->lladdr_comp | hai->mob_rtr);
2303 if (conf.UseMnHaIPsec && conf.KeyMngMobCapability)
2304 bule->flags |= IP6_MH_BU_KEYM;
2305 bule->coa_changed = -1;
2306 @@ -1086,6 +1144,18 @@
2307 if (bule->flags & IP6_MH_BU_HOME) {
2308 struct home_addr_info *hai = bule->home;
2309 struct ip6_mh_opt_refresh_advice *bra;
2311 + if (bule->flags & IP6_MH_BU_MR &&
2312 + !(ba->ip6mhba_flags & IP6_MH_BA_MR)) {
2313 + if (hai->use_dhaad) {
2314 + mn_change_ha(hai);
2317 + bul_iterate(&hai->bul, mn_dereg, &one);
2319 + pthread_rwlock_unlock(&mn_lock);
2322 if (!tsisset(ba_lifetime)) {
2323 int type = FLUSH_FAILED;
2325 @@ -1261,12 +1331,73 @@
2329 +static void nemo_mr_rules_del(struct home_addr_info *hinfo)
2331 + struct list_head *l;
2333 + list_for_each(l, &hinfo->mob_net_prefixes) {
2334 + struct prefix_list_entry *p = NULL;
2335 + p = list_entry(l, struct prefix_list_entry, list);
2336 + rule_del(NULL, RT6_TABLE_MIP6,
2337 + IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
2338 + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
2339 + rule_del(NULL, RT6_TABLE_MAIN,
2340 + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
2341 + &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
2345 +static int nemo_mr_rules_add(struct home_addr_info *hinfo)
2347 + struct prefix_list_entry *pe = NULL;
2348 + struct list_head *l;
2350 + list_for_each(l, &hinfo->mob_net_prefixes) {
2351 + struct prefix_list_entry *p = NULL;
2352 + p = list_entry(l, struct prefix_list_entry, list);
2353 + if (rule_add(NULL, RT6_TABLE_MAIN,
2354 + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
2356 + &p->ple_prefix, p->ple_plen, 0) < 0) {
2360 + if (rule_add(NULL, RT6_TABLE_MIP6,
2361 + IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
2362 + &p->ple_prefix, p->ple_plen,
2363 + &in6addr_any, 0, 0) < 0) {
2364 + rule_del(NULL, RT6_TABLE_MAIN,
2365 + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
2366 + &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
2373 + list_for_each(l, &hinfo->mob_net_prefixes) {
2374 + struct prefix_list_entry *p = NULL;
2375 + p = list_entry(l, struct prefix_list_entry, list);
2376 + rule_del(NULL, RT6_TABLE_MIP6,
2377 + IP6_RULE_PRIO_MIP6_FWD, RTN_UNICAST,
2378 + &p->ple_prefix, p->ple_plen, &in6addr_any, 0, 0);
2379 + rule_del(NULL, RT6_TABLE_MAIN,
2380 + IP6_RULE_PRIO_MIP6_MNP_IN, RTN_UNICAST,
2381 + &in6addr_any, 0, &p->ple_prefix, p->ple_plen, 0);
2388 static void clean_home_addr_info(struct home_addr_info *hai)
2390 struct flag_hoa_args arg;
2391 int plen = (hai->hoa.iif == hai->if_tunnel ? 128 : hai->plen);
2393 list_del(&hai->list);
2395 + nemo_mr_rules_del(hai);
2398 addr_do(&hai->hoa.addr, plen,
2399 @@ -1320,13 +1451,23 @@
2401 if (pthread_mutex_init(&hai->ha_list.c_lock, NULL))
2404 + INIT_LIST_HEAD(&hai->mob_net_prefixes);
2405 + if (hai->mob_rtr &&
2406 + prefix_list_copy(&conf_hai->mob_net_prefixes,
2407 + &hai->mob_net_prefixes) < 0)
2410 INIT_LIST_HEAD(&hai->ro_policies);
2411 if (rpl_copy(&conf_hai->ro_policies, &hai->ro_policies) < 0)
2415 INIT_LIST_HEAD(&hai->ha_list.tqe.list);
2416 INIT_LIST_HEAD(&hai->ha_list.home_agents);
2420 + prefix_list_free(&hai->mob_net_prefixes);
2422 pthread_mutex_destroy(&hai->ha_list.c_lock);
2424 @@ -1347,6 +1488,15 @@
2425 if ((hai = hai_copy(conf_hai)) == NULL)
2428 + if (hai->mob_rtr) {
2429 + MDBG("is Mobile Router\n");
2430 + list_for_each(list, &hai->mob_net_prefixes) {
2431 + struct prefix_list_entry *p;
2432 + p = list_entry(list, struct prefix_list_entry, list);
2433 + MDBG("Mobile Network Prefix %x:%x:%x:%x:%x:%x:%x:%x/%d\n",
2434 + NIP6ADDR(&p->ple_prefix), p->ple_plen);
2437 if (IN6_IS_ADDR_UNSPECIFIED(&hai->ha_addr)) {
2440 @@ -1391,6 +1541,9 @@
2441 hai->if_tunnel, &arg, flag_hoa) < 0) {
2444 + if (hai->mob_rtr && nemo_mr_rules_add(hai) < 0) {
2447 hai->at_home = hai->hoa.iif == hai->if_home;
2448 pthread_rwlock_wrlock(&mn_lock);
2449 list_add(&hai->list, &home_addr_list);
2450 diff -r c04f74757df5 src/mn.h
2451 --- a/src/mn.h Sun Nov 30 23:14:35 2008 +0100
2452 +++ b/src/mn.h Sun Nov 30 23:14:48 2008 +0100
2454 pthread_mutex_t c_lock;
2457 -#define HOME_LINK_BLOCK 0x1
2458 -#define HOME_ADDR_BLOCK 0x2
2459 -#define HOME_ADDR_RULE_BLOCK 0x4
2460 +#define HOME_LINK_BLOCK 0x01
2461 +#define HOME_ADDR_BLOCK 0x02
2462 +#define HOME_ADDR_RULE_BLOCK 0x04
2463 +#define NEMO_RA_BLOCK 0x08
2464 +#define NEMO_FWD_BLOCK 0x10
2467 struct in6_addr addr;
2473 char name[IF_NAMESIZE];
2475 + struct list_head mob_net_prefixes;
2479 diff -r c04f74757df5 src/movement.c
2480 --- a/src/movement.c Sun Nov 30 23:14:35 2008 +0100
2481 +++ b/src/movement.c Sun Nov 30 23:14:48 2008 +0100
2483 static int conf_default_rs = 3;
2484 static int conf_default_rs_ival = 4;
2486 +static int conf_forwarding = 0;
2487 static int conf_autoconf = 1;
2488 static int conf_ra_defrtr = 0;
2489 static int conf_rs = 0;
2490 @@ -177,6 +178,12 @@
2492 route_del(rtr->ifindex, RT_TABLE_MAIN, 0,
2493 &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
2495 + /* delete default route for the packets coming from the
2498 + route_del(rtr->ifindex, RT6_TABLE_MIP6, 0,
2499 + &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
2501 list_for_each_safe(l, n, &rtr->prefixes) {
2502 struct prefix_list_entry *p;
2503 @@ -231,8 +238,31 @@
2504 list_add_tail(&coa->list, &iface->expired_coas);
2507 +static void md_reset_egress_forward(void)
2509 + struct list_head *l;
2512 + if (list_empty(&ifaces))
2515 + list_for_each(l, &ifaces) {
2516 + struct md_inet6_iface *i;
2517 + i = list_entry(l, struct md_inet6_iface, list);
2518 + forward |= i->home_link;
2520 + list_for_each(l, &ifaces) {
2521 + struct md_inet6_iface *i;
2522 + i = list_entry(l, struct md_inet6_iface, list);
2523 + set_iface_proc_entry(PROC_SYS_IP6_FORWARDING,
2524 + i->name, forward);
2528 static void md_reset_home_link(struct md_inet6_iface *i)
2531 + md_reset_egress_forward();
2533 i->ll_dad_unsafe = 0;
2537 static void iface_proc_entries_init(struct md_inet6_iface *iface)
2539 + set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, iface->name,
2541 set_iface_proc_entry(PROC_SYS_IP6_AUTOCONF, iface->name,
2543 set_iface_proc_entry(PROC_SYS_IP6_ACCEPT_RA_DEFRTR, iface->name, conf_ra_defrtr);
2545 ll_dad_unsafe |= hai->lladdr_comp;
2548 + if (i->home_link != home_link)
2549 + md_reset_egress_forward();
2550 i->home_link = home_link;
2551 i->ll_dad_unsafe = ll_dad_unsafe;
2553 @@ -1189,6 +1223,11 @@
2554 RTF_DEFAULT|RTF_ADDRCONF, 1024,
2555 &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
2557 + /* default route for the packet coming from the Mobile Network */
2558 + route_add(rtr->ifindex, RT6_TABLE_MIP6, RTPROT_MIP,
2559 + 0, IP6_RT_PRIO_MIP6_FWD,
2560 + &in6addr_any, 0, &in6addr_any, 0, &rtr->lladdr);
2562 list_for_each(list, &rtr->prefixes) {
2563 struct prefix_list_entry *p;
2564 p = list_entry(list, struct prefix_list_entry, list);
2565 @@ -1737,6 +1776,8 @@
2567 static void iface_proc_entries_cleanup(struct md_inet6_iface *iface)
2569 + set_iface_proc_entry(PROC_SYS_IP6_FORWARDING, iface->name,
2570 + iface->devconf[DEVCONF_FORWARDING]);
2571 set_iface_proc_entry(PROC_SYS_IP6_AUTOCONF, iface->name,
2572 iface->devconf[DEVCONF_AUTOCONF]);
2573 set_iface_proc_entry(PROC_SYS_IP6_ACCEPT_RA_DEFRTR, iface->name,
2574 diff -r c04f74757df5 src/ndisc.c
2575 --- a/src/ndisc.c Sun Nov 30 23:14:35 2008 +0100
2576 +++ b/src/ndisc.c Sun Nov 30 23:14:48 2008 +0100
2579 struct in6_addr lladdr;
2582 + int nd_flags = bu_flags&IP6_MH_BU_MR ? NTF_ROUTER : 0;
2584 err = pneigh_add(ifindex, nd_flags, target);
2587 pneigh_del(ifindex, target);
2590 - uint32_t na_flags = ND_NA_FLAG_OVERRIDE;
2591 + uint32_t na_flags = (ND_NA_FLAG_OVERRIDE |
2592 + nd_flags ? ND_NA_FLAG_ROUTER : 0);
2594 ndisc_send_na(ifindex, src, &in6addr_all_nodes_mc,
2597 diff -r c04f74757df5 src/policy.c
2598 --- a/src/policy.c Sun Nov 30 23:14:35 2008 +0100
2599 +++ b/src/policy.c Sun Nov 30 23:14:48 2008 +0100
2600 @@ -107,6 +107,23 @@
2605 +policy_check_mob_net_prefix(const struct policy_bind_acl_entry *acl,
2606 + const struct ip6_mh_binding_update *bu,
2607 + const struct mh_options *opts)
2609 + struct ip6_mh_opt_mob_net_prefix *op;
2610 + for (op = mh_opt(&bu->ip6mhbu_hdr, opts, IP6_MHOPT_MOB_NET_PRFX);
2612 + op = mh_opt_next(&bu->ip6mhbu_hdr, opts, op)) {
2613 + if (!prefix_list_get(&acl->mob_net_prefixes,
2614 + &op->ip6mnp_prefix,
2615 + op->ip6mnp_prefix_len))
2616 + return IP6_MH_BAS_NOT_AUTH_FOR_PRFX;
2618 + return IP6_MH_BAS_ACCEPTED;
2622 * default_discard_binding - check for discard policy
2623 * @remote_hoa: remote MN's home address
2624 @@ -127,10 +144,20 @@
2625 int ret = def_bind_policy;
2626 struct policy_bind_acl_entry *acl;
2628 + if (bu->ip6mhbu_flags & IP6_MH_BU_MR && !conf.HaAcceptMobRtr)
2629 + return IP6_MH_BAS_MR_OP_NOT_PERMITTED;
2631 pthread_rwlock_rdlock(&policy_lock);
2632 acl = hash_get(&policy_bind_acl_hash, NULL, remote_hoa);
2634 ret = acl->bind_policy;
2635 + if (ret < IP6_MH_BAS_UNSPECIFIED &&
2636 + bu->ip6mhbu_flags & IP6_MH_BU_MR) {
2637 + struct mh_options opts;
2638 + mh_opt_parse(&bu->ip6mhbu_hdr, len,
2639 + sizeof(*bu), &opts);
2640 + ret = policy_check_mob_net_prefix(acl, bu, &opts);
2643 pthread_rwlock_unlock(&policy_lock);
2645 @@ -227,6 +254,42 @@
2649 +int default_get_mnp_count(const struct in6_addr *hoa)
2652 + struct policy_bind_acl_entry *acl;
2653 + pthread_rwlock_rdlock(&policy_lock);
2654 + acl = hash_get(&policy_bind_acl_hash, NULL, hoa);
2656 + ret = acl->mnp_count;
2657 + pthread_rwlock_unlock(&policy_lock);
2662 +int default_get_mnps(const struct in6_addr *hoa,
2663 + const int mnp_count,
2664 + struct nd_opt_prefix_info *mnps)
2667 + struct policy_bind_acl_entry *acl;
2669 + pthread_rwlock_rdlock(&policy_lock);
2670 + acl = hash_get(&policy_bind_acl_hash, NULL, hoa);
2671 + if (acl != NULL) {
2672 + struct list_head *l;
2673 + list_for_each(l, &acl->mob_net_prefixes) {
2674 + struct prefix_list_entry *e;
2675 + if (i >= mnp_count)
2677 + e = list_entry(l, struct prefix_list_entry, list);
2678 + mnps[i++] = e->pinfo;
2681 + pthread_rwlock_unlock(&policy_lock);
2685 static int policy_bind_acle_cleanup(void *data, void *arg)
2687 struct policy_bind_acl_entry *acl = data;
2688 diff -r c04f74757df5 src/policy.h
2689 --- a/src/policy.h Sun Nov 30 23:14:35 2008 +0100
2690 +++ b/src/policy.h Sun Nov 30 23:14:48 2008 +0100
2693 struct ip6_mh_binding_update;
2694 struct nd_router_advert;
2695 +struct nd_opt_prefix_info;
2697 struct policy_bind_acl_entry {
2698 struct list_head list;
2699 struct in6_addr hoa;
2703 + struct list_head mob_net_prefixes;
2707 @@ -147,6 +150,12 @@
2708 const struct in6_addr *cn,
2709 struct in6_addr *coa);
2711 +int default_get_mnp_count(const struct in6_addr *hoa);
2713 +int default_get_mnps(const struct in6_addr *hoa,
2714 + const int mnp_count,
2715 + struct nd_opt_prefix_info *mnps);
2717 void policy_cleanup(void);
2719 int policy_init(void);
2720 diff -r c04f74757df5 src/proc_sys.h
2721 --- a/src/proc_sys.h Sun Nov 30 23:14:35 2008 +0100
2722 +++ b/src/proc_sys.h Sun Nov 30 23:14:48 2008 +0100
2724 #define PROC_SYS_IP6_APP_SOLICIT "/proc/sys/net/ipv6/neigh/%s/app_solicit"
2725 #define PROC_SYS_IP6_BASEREACHTIME_MS "/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms"
2726 #define PROC_SYS_IP6_RETRANSTIMER_MS "/proc/sys/net/ipv6/neigh/%s/retrans_time_ms"
2727 +#define PROC_SYS_IP6_FORWARDING "/proc/sys/net/ipv6/conf/%s/forwarding"
2729 int set_iface_proc_entry(const char *tmpl, const char *if_name, int val);
2731 diff -r c04f74757df5 src/rtnl.h
2732 --- a/src/rtnl.h Sun Nov 30 23:14:35 2008 +0100
2733 +++ b/src/rtnl.h Sun Nov 30 23:14:48 2008 +0100
2735 #define IP6_RT_PRIO_MIP6_FWD 192
2736 #define IP6_RT_PRIO_ADDRCONF 256
2738 +#define IP6_RULE_PRIO_MIP6_MNP_IN 1000
2739 #define IP6_RULE_PRIO_MIP6_HOA_OUT 1001
2740 #define IP6_RULE_PRIO_MIP6_COA_OUT 1002
2741 #define IP6_RULE_PRIO_MIP6_BLOCK 1003
2742 diff -r c04f74757df5 src/scan.l
2743 --- a/src/scan.l Sun Nov 30 23:14:35 2008 +0100
2744 +++ b/src/scan.l Sun Nov 30 23:14:48 2008 +0100
2745 @@ -136,6 +136,11 @@
2746 MnRouterProbeTimeout { return MNROUTERPROBETIMEOUT; }
2747 MnDiscardHaParamProb { return MNDISCARDHAPARAMPROB; }
2748 OptimisticHandoff { return OPTIMISTICHANDOFF; }
2749 +HaAcceptMobRtr { return HAACCEPTMOBRTR; }
2750 +IsMobRtr { return ISMOBRTR; }
2751 +HaServedPrefix { return HASERVEDPREFIX; }
2752 +HomePrefix { return HOMEPREFIX; }
2753 +MobRtrUseExplicitMode { return MOBRTRUSEEXPLICITMODE; }
2754 internal { return INTERNAL; }
2757 diff -r c04f74757df5 src/vt.c
2758 --- a/src/vt.c Sun Nov 30 23:14:35 2008 +0100
2759 +++ b/src/vt.c Sun Nov 30 23:14:48 2008 +0100
2760 @@ -678,6 +678,17 @@
2762 fprintf(vh->vh_stream, "\n");
2764 + /* Dump the registered MNP */
2766 + struct list_head *l;
2767 + list_for_each(l, &bce->mob_net_prefixes) {
2768 + struct prefix_list_entry *p;
2769 + p = list_entry(l, struct prefix_list_entry, list);
2770 + fprintf(vh->vh_stream, " MNP: %x:%x:%x:%x:%x:%x:%x:%x/%d\n",
2771 + NIP6ADDR(&p->ple_prefix), p->ple_plen);
2778 diff -r c04f74757df5 src/xfrm.c
2779 --- a/src/xfrm.c Sun Nov 30 23:14:35 2008 +0100
2780 +++ b/src/xfrm.c Sun Nov 30 23:14:48 2008 +0100
2781 @@ -257,6 +257,30 @@
2782 sel->prefixlen_s = 128;
2785 +/* NEMO specific version of set_selector(): set xfrm_selector
2786 + * fields for IPsec policies and states. If NULL is passed as
2787 + * src or dst prefix, any is used, i.e. ::/0 */
2788 +static void mr_set_selector(const struct prefix_list_entry *src,
2789 + const struct prefix_list_entry *dst,
2790 + uid_t uid, struct xfrm_selector *sel)
2792 + memset(sel, 0, sizeof(*sel));
2793 + sel->family = AF_INET6;
2796 + if (src != NULL) {
2797 + memcpy(&sel->saddr.a6, &src->ple_prefix,
2798 + sizeof(sel->saddr.a6));
2799 + sel->prefixlen_s = src->ple_plen;
2802 + if (dst != NULL) {
2803 + memcpy(&sel->daddr.a6, &dst->ple_prefix,
2804 + sizeof(sel->daddr.a6));
2805 + sel->prefixlen_d = dst->ple_plen;
2810 * xfrm_last_used - when was a binding last used
2811 * @daddr: destination address (home address)
2812 @@ -679,6 +703,56 @@
2816 +static int mr_ipsec_bypass_init(void)
2818 + struct list_head *home;
2819 + struct list_head *mnps;
2822 + /* Loop for each HomeAddress info */
2823 + list_for_each(home, &conf.home_addrs)
2825 + struct home_addr_info *hai;
2826 + hai = list_entry(home, struct home_addr_info, list);
2828 + /* If Mobile Router for this link, loop for each MNP */
2831 + /* Add bypass policies to and from the MNP link */
2832 + list_for_each(mnps, &hai->mob_net_prefixes)
2834 + struct prefix_list_entry * mnp;
2835 + struct xfrm_selector sel;
2836 + uid_t uid = getuid();
2838 + mnp = list_entry(mnps, struct prefix_list_entry, list);
2840 + /* IN, src = MNP , dst = any */
2841 + mr_set_selector(mnp, NULL, uid, &sel);
2842 + err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_IN,
2843 + XFRM_POLICY_ALLOW,
2844 + MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
2847 + /* FWD, src = MNP , dst = any */
2848 + err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_FWD,
2849 + XFRM_POLICY_ALLOW,
2850 + MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
2853 + /* OUT, src = any , dst = MNP */
2854 + mr_set_selector(NULL, mnp, uid, &sel);
2855 + err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_OUT,
2856 + XFRM_POLICY_ALLOW,
2857 + MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
2866 static inline int mn_ha_ipsec_init(void)
2870 /* insert bypass policy */
2871 err = ipsec_policy_walk(_mn_ha_ipsec_bypass_init, NULL);
2873 + /* insert NEMO-related bypass */
2874 + err = mr_ipsec_bypass_init();
2876 err = ipsec_policy_walk(_mn_ha_ipsec_init, NULL);
2879 @@ -787,10 +864,54 @@
2883 +static int mr_ipsec_bypass_cleanup(void)
2885 + struct list_head *home;
2886 + struct list_head *mnps;
2889 + /* Loop for each HomeAddress info */
2890 + list_for_each(home, &conf.home_addrs)
2892 + struct home_addr_info *hai;
2893 + hai = list_entry(home, struct home_addr_info, list);
2895 + /* If Mobile Router for this link, loop for each MNP */
2898 + /* Delete bypass policies to and from the MNP link */
2899 + list_for_each(mnps, &hai->mob_net_prefixes)
2901 + struct prefix_list_entry * mnp;
2902 + struct xfrm_selector sel;
2903 + uid_t uid = getuid();
2905 + mnp = list_entry(mnps, struct prefix_list_entry, list);
2907 + /* IN, src = MNP , dst = any */
2908 + mr_set_selector(mnp, NULL, uid, &sel);
2909 + err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_IN);
2911 + /* FWD, src = MNP , dst = any */
2912 + err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_FWD);
2914 + /* OUT, src = any , dst = MNP */
2915 + mr_set_selector(NULL, mnp, uid, &sel);
2916 + err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_OUT);
2925 static inline void mn_ha_ipsec_cleanup(void)
2927 ipsec_policy_walk(_mn_ha_ipsec_bypass_cleanup, NULL);
2929 + (void)mr_ipsec_bypass_cleanup();
2931 ipsec_policy_walk(_mn_ha_ipsec_cleanup, NULL);
2934 @@ -1719,6 +1840,8 @@
2935 if (hai->home_block & HOME_LINK_BLOCK)
2936 xfrm_unblock_link(hai);
2937 xfrm_block_link(hai);
2938 + if (hai->mob_rtr && !(hai->home_block & NEMO_FWD_BLOCK))
2939 + xfrm_block_fwd(hai);
2941 if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa)) {
2943 @@ -1784,6 +1907,8 @@
2944 struct home_addr_info *hai = bule->home;
2945 if (hai->home_block & HOME_LINK_BLOCK)
2946 xfrm_unblock_link(hai);
2947 + if (hai->home_block & NEMO_FWD_BLOCK)
2948 + xfrm_unblock_fwd(hai);
2950 /* check if XFRM policies and states have already been cleaned up */
2951 if (IN6_ARE_ADDR_EQUAL(&bule->hoa, &bule->coa))
2952 @@ -2058,6 +2183,50 @@
2953 hai->home_block &= ~HOME_ADDR_BLOCK;
2956 +/* block all RA messages sent by MR */
2957 +int xfrm_block_ra(struct home_addr_info *hai)
2960 + struct xfrm_selector sel;
2961 + hai->home_block |= NEMO_RA_BLOCK;
2962 + set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6,
2963 + ND_ROUTER_ADVERT, 0, 0, &sel);
2964 + if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_OUT, XFRM_POLICY_BLOCK,
2965 + MIP6_PRIO_HOME_BLOCK, NULL, 0)))
2970 +void xfrm_unblock_ra(struct home_addr_info *hai)
2972 + struct xfrm_selector sel;
2973 + set_selector(&in6addr_any, &in6addr_any, IPPROTO_ICMPV6,
2974 + ND_ROUTER_ADVERT, 0, 0, &sel);
2975 + xfrm_mip_policy_del(&sel, XFRM_POLICY_OUT);
2976 + hai->home_block &= ~NEMO_RA_BLOCK;
2979 +/* block all forwarded packets */
2980 +int xfrm_block_fwd(struct home_addr_info *hai)
2983 + struct xfrm_selector sel;
2984 + hai->home_block |= NEMO_FWD_BLOCK;
2985 + set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, 0, &sel);
2986 + if ((ret = xfrm_mip_policy_add(&sel, 0, XFRM_POLICY_FWD, XFRM_POLICY_BLOCK,
2987 + MIP6_PRIO_HOME_BLOCK, NULL, 0)))
2992 +void xfrm_unblock_fwd(struct home_addr_info *hai)
2994 + struct xfrm_selector sel;
2995 + set_selector(&in6addr_any, &in6addr_any, 0, 0, 0, 0, &sel);
2996 + xfrm_mip_policy_del(&sel, XFRM_POLICY_FWD);
2997 + hai->home_block &= ~NEMO_FWD_BLOCK;
3000 int mn_ipsec_recv_bu_tnl_pol_add(struct bulentry *bule, int ifindex,
3001 struct ipsec_policy_entry *e)
3003 diff -r c04f74757df5 src/xfrm.h
3004 --- a/src/xfrm.h Sun Nov 30 23:14:35 2008 +0100
3005 +++ b/src/xfrm.h Sun Nov 30 23:14:48 2008 +0100
3007 #define MIP6_PRIO_RO_SIG_IPSEC 7 /* XXX: BU between MN-MN with IPsec */
3008 #define MIP6_PRIO_RO_SIG 8 /* XXX: BU between MN-CN */
3009 #define MIP6_PRIO_RO_SIG_ANY 9
3010 +#define MIP6_PRIO_MR_LOCAL_DATA_BYPASS 9 /* Bypass rule for local traffic in mobile network */
3011 #define MIP6_PRIO_RO_SIG_RR 10 /* XXX: MH(or HoTI/HoT) between MN-CN */
3012 #define MIP6_PRIO_RO_BLOCK 11
3013 #define MIP6_PRIO_NO_RO_SIG_ANY 12
3015 int xfrm_block_hoa(struct home_addr_info *hai);
3016 void xfrm_unblock_hoa(struct home_addr_info *hai);
3018 +int xfrm_block_ra(struct home_addr_info *hai);
3019 +void xfrm_unblock_ra(struct home_addr_info *hai);
3021 +int xfrm_block_fwd(struct home_addr_info *hai);
3022 +void xfrm_unblock_fwd(struct home_addr_info *hai);
3024 int ha_mn_ipsec_pol_mod(struct in6_addr *haaddr,
3025 struct in6_addr *hoa);