[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
(usagi-users 03970) Patch for NEMO IPsec
- To: mipl@xxxxxxxxxxxxxxx, usagi-users@xxxxxxxxxxxxxx
- Subject: (usagi-users 03970) Patch for NEMO IPsec
- From: Sebastien Decugis <sdecugis@xxxxxxxxxxxxxxxx>
- Date: Tue, 16 Oct 2007 17:08:00 +0900
- Reply-to: usagi-users@xxxxxxxxxxxxxx
- Resent-date: Thu, 18 Oct 2007 12:08:36 +0900
- Resent-from: nakam@xxxxxxxxxxxxxx
- Resent-message-id: <200710181208.FMLAAB9009.usagi-users@linux-ipv6.org>
- Resent-to: usagi-users@xxxxxxxxxxxxxx (moderated)
- User-agent: Thunderbird 2.0.0.6 (Windows/20070728)
# Sorry for cross-posting, I don't know which list is most appropriate
for NEMO patches.
Hi all,
This is a patch to apply on top of NEMO BS patch [1]. Currently, when
TunnelPayload protection is set in the Mobile Router mip6d.conf file,
the traffic to the MR is protected, but traffic that is directed to a
MNN is sent in clear between MR and HA.
The attached patch fixes this by adding IPsec policies to protect also
the traffic to and from the MNP.
Pre-compiled binaries of the mip6d daemon including this patch (and
others) can be found on the Nautilus6 repository [2].
Best regards,
Sebastien.
[1] NEPL patch http://software.nautilus6.org/NEPL-UMIP/
[2] http://software.nautilus6.org/packages/gutsy/
PS: The patch is splitted in three files:
(NEMO-IPsec-common.patch)
Adds the ability to specify prefix length in selectors in ipsec.c
(NEMO-IPsec-HA.patch)
The modifications needed on the HA to insert the following rules when
a MR registers with some MNP.
prio=10 dir=OUT src=ANY dst=MNP IPsec
prio=10 dir=FWD src=MNP dst=ANY IPsec
prio=10 dir=IN src=MNP dst=ANY IPsec
(NEMO-IPsec-MR.patch)
The modifications needed on the MR to insert the following rules
When the MR starts:
prio=09 dir=OUT src=ANY dst=MNP None (bypass)
prio=09 dir=FWD src=MNP dst=ANY None (bypass)
prio=09 dir=IN src=MNP dst=ANY None (bypass)
When the MR is in foreign link:
prio=10 dir=OUT src=MNP dst=ANY IPsec
prio=10 dir=FWD src=ANY dst=MNP IPsec
prio=10 dir=IN src=ANY dst=MNP IPsec
--
Sebastien Decugis
http://www.nautilus6.org
diff -Nur trunk.ori/src/ipsec.c trunk.common-mod/src/ipsec.c
--- trunk.ori/src/ipsec.c 2007-10-12 16:19:30.000000000 +0900
+++ trunk.common-mod/src/ipsec.c 2007-10-16 11:42:33.000000000 +0900
@@ -81,7 +81,9 @@
struct ipsec_policy_entry *e,
int dir,
const struct in6_addr *in6_dst,
+ int dst_len,
const struct in6_addr *in6_src,
+ int src_len,
int ifindex,
int nodetype)
{
@@ -97,10 +99,13 @@
sp->action = e->action;
memcpy(&sp->sel.saddr.a6, in6_src, sizeof(sp->sel.saddr.a6));
memcpy(&sp->sel.daddr.a6, in6_dst, sizeof(sp->sel.daddr.a6));
- sp->sel.prefixlen_s = IN6_ARE_ADDR_EQUAL(in6_src, &in6addr_any) ?
- 0 : 128;
- sp->sel.prefixlen_d = IN6_ARE_ADDR_EQUAL(in6_dst, &in6addr_any) ?
- 0 : 128;
+ sp->sel.prefixlen_s = src_len;
+ if (!src_len && (!IN6_ARE_ADDR_EQUAL(in6_src, &in6addr_any)))
+ sp->sel.prefixlen_s = 128;
+ sp->sel.prefixlen_d = dst_len;
+ if (!dst_len && (!IN6_ARE_ADDR_EQUAL(in6_dst, &in6addr_any)))
+ sp->sel.prefixlen_d = 128;
+
sp->sel.ifindex = 0;
switch (e->type) {
@@ -405,7 +410,7 @@
/* inbound */
_set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
haaddr, oldcoa, e->reqid_toha);
- _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, hoa,
+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, hoa, 0,
ifindex, MIP6_ENTITY_HA);
if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
dbg("migrate for INBOUND policy failed\n");
@@ -415,7 +420,7 @@
/* forward */
_set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
haaddr, oldcoa, e->reqid_toha);
- _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, hoa,
+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, hoa, 0,
ifindex, MIP6_ENTITY_HA);
if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
dbg("migrate for FORWARD policy failed\n");
@@ -425,7 +430,7 @@
/* outbound */
_set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
oldcoa, haaddr, e->reqid_tomn);
- _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, &in6addr_any,
+ _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, 0, &in6addr_any, 0,
ifindex, MIP6_ENTITY_HA);
if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
dbg("migrate for OUTBOUND policy failed\n");
@@ -493,7 +498,7 @@
dump_migrate(ifindex, ipsec_proto, hoa, haaddr, NULL, NULL);
/* inbound */
- _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, hoa,
+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, hoa, 0,
ifindex, MIP6_ENTITY_HA);
_set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
haaddr, hoa, e->reqid_toha);
@@ -504,7 +509,7 @@
}
/* forward */
- _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, hoa,
+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, hoa, 0,
ifindex, MIP6_ENTITY_HA);
_set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
haaddr, hoa, e->reqid_toha);
@@ -515,7 +520,7 @@
}
/* outbound */
- _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, &in6addr_any,
+ _set_sp(&sp, e, XFRM_POLICY_OUT, hoa, 0, &in6addr_any, 0,
ifindex, MIP6_ENTITY_HA);
_set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
hoa, haaddr, e->reqid_tomn);
@@ -631,7 +636,7 @@
/* outbound */
_set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
haaddr, oldcoa, e->reqid_toha);
- _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, hoa,
+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, hoa, 0,
ifindex, MIP6_ENTITY_MN);
if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
dbg("migrate for OUTBOUND policy failed\n");
@@ -641,7 +646,7 @@
/* inbound */
_set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
oldcoa, haaddr, e->reqid_tomn);
- _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
+ _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
ifindex, MIP6_ENTITY_MN);
if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
dbg("migrate for INBOUND policy (1) failed\n");
@@ -657,7 +662,7 @@
/* template */
_set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
oldcoa, haaddr, e->reqid_tomn);
- _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
+ _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
ifindex, MIP6_ENTITY_MN);
/* additional settings */
sp.priority = MIP6_PRIO_RO_SIG_IPSEC;
@@ -724,7 +729,7 @@
dump_migrate(ifindex, ipsec_proto, hoa, haaddr, NULL, NULL);
/* inbound */
- _set_sp(&sp, e, XFRM_POLICY_IN, hoa, &in6addr_any,
+ _set_sp(&sp, e, XFRM_POLICY_IN, hoa, 0, &in6addr_any, 0,
ifindex, MIP6_ENTITY_MN);
_set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
hoa, haaddr, e->reqid_tomn);
@@ -735,7 +740,7 @@
}
/* outbound */
- _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, hoa,
+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, hoa, 0,
ifindex, MIP6_ENTITY_MN);
_set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
haaddr, hoa, e->reqid_toha);
diff -Nur trunk.common-mod/src/ha.c trunk.ha/src/ha.c
--- trunk.common-mod/src/ha.c 2007-10-15 17:54:32.000000000 +0900
+++ trunk.ha/src/ha.c 2007-10-15 17:45:35.000000000 +0900
@@ -547,6 +547,7 @@
static int home_tnl_del(int old_if, int new_if, struct home_tnl_ops_parm *p)
{
const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
+ struct list_head *mnp;
assert(old_if);
@@ -554,13 +555,14 @@
peer_addr = &p->bce->peer_addr;
coa = &p->bce->peer_addr;
old_coa = &p->bce->coa;
+ mnp = &(p->bce->mob_net_prefixes);
if (conf.UseMnHaIPsec) {
/* migrate */
ha_ipsec_tnl_update(our_addr, peer_addr,
- coa, old_coa, p->bce->tunnel);
+ coa, old_coa, p->bce->tunnel, mnp);
/* delete SP entry */
- ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel);
+ ha_ipsec_tnl_pol_del(our_addr, peer_addr, p->bce->tunnel, mnp);
}
/* delete HoA route */
route_del(old_if, RT6_TABLE_MAIN,
@@ -578,6 +580,7 @@
static int home_tnl_add(int old_if, int new_if, struct home_tnl_ops_parm *p)
{
const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
+ struct list_head *mnp;
assert(new_if);
@@ -585,6 +588,7 @@
peer_addr = &p->bce->peer_addr;
coa = &p->bce->coa;
old_coa = &p->bce->peer_addr;
+ mnp = &(p->mob_net_prefixes);
/* update tunnel interface */
p->bce->tunnel = new_if;
@@ -608,13 +612,13 @@
/* add SP entry */
if (conf.UseMnHaIPsec) {
if (ha_ipsec_tnl_pol_add(our_addr, peer_addr,
- p->bce->tunnel) < 0) {
+ p->bce->tunnel, mnp) < 0) {
p->ba_status = IP6_MH_BAS_INSUFFICIENT;
goto err;
}
/* migrate */
if (ha_ipsec_tnl_update(our_addr, peer_addr, coa, old_coa,
- p->bce->tunnel) < 0) {
+ p->bce->tunnel, mnp) < 0) {
p->ba_status = IP6_MH_BAS_INSUFFICIENT;
goto err;
}
@@ -629,36 +633,23 @@
{
assert(old_if && new_if);
- if (old_if == new_if) {
+ if ((old_if == new_if) && (!prefix_list_cmp(&p->bce->mob_net_prefixes,
+ &p->mob_net_prefixes))) {
const struct in6_addr *our_addr, *peer_addr, *coa, *old_coa;
+ struct list_head *mnp;
+ int mnpdiff = 0;
our_addr = &p->bce->our_addr;
peer_addr = &p->bce->peer_addr;
coa = &p->bce->coa;
old_coa = &p->bce->old_coa;
+ mnp = &(p->mob_net_prefixes);
- /* 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) &&
+ (mnpdiff || !IN6_ARE_ADDR_EQUAL(old_coa, coa)) &&
ha_ipsec_tnl_update(our_addr, peer_addr, coa, old_coa,
- p->bce->tunnel) < 0) {
+ p->bce->tunnel, mnp) < 0) {
return -1;
}
} else {
diff -Nur trunk.common-mod/src/ipsec.c trunk.ha/src/ipsec.c
--- trunk.common-mod/src/ipsec.c 2007-10-16 11:42:33.000000000 +0900
+++ trunk.ha/src/ipsec.c 2007-10-16 11:42:42.000000000 +0900
@@ -352,6 +352,7 @@
int tunnel;
struct in6_addr coa;
struct in6_addr old_coa;
+ struct list_head *mnp;
};
/*
@@ -370,6 +371,7 @@
int ifindex;
const struct in6_addr *oldcoa, *newcoa;
const struct in6_addr *peer_addr = hoa;
+ struct list_head *mnp;
u_int8_t ipsec_proto;
struct xfrm_user_tmpl tmpl;
struct xfrm_userpolicy_info sp;
@@ -404,6 +406,7 @@
oldcoa = IN6_ARE_ADDR_EQUAL(&info->old_coa, &in6addr_any) ?
peer_addr : &info->old_coa;
newcoa = &info->coa;
+ mnp = info->mnp;
dump_migrate(ifindex, ipsec_proto, hoa, haaddr, oldcoa, newcoa);
@@ -436,6 +439,52 @@
dbg("migrate for OUTBOUND policy failed\n");
goto end;
}
+
+ /* Mobile router case */
+ if ( (e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && mnp)
+ {
+ struct list_head *list;
+
+ /* We have to modify rules to protect traffic to and from MNP's, the same way as HoA */
+ list_for_each(list, mnp)
+ {
+ struct prefix_list_entry *p;
+ p = list_entry(list, struct prefix_list_entry, list);
+
+
+ /* inbound */
+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
+ haaddr, oldcoa, e->reqid_toha);
+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
+ ifindex, MIP6_ENTITY_HA);
+ if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
+ dbg("migrate for INBOUND policy failed\n");
+ goto end;
+ }
+
+ /* forward */
+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
+ haaddr, oldcoa, e->reqid_toha);
+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
+ ifindex, MIP6_ENTITY_HA);
+ if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
+ dbg("migrate for FORWARD policy failed\n");
+ goto end;
+ }
+
+ /* outbound */
+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
+ oldcoa, haaddr, e->reqid_tomn);
+ _set_sp(&sp, e, XFRM_POLICY_OUT, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
+ ifindex, MIP6_ENTITY_HA);
+ if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
+ dbg("migrate for OUTBOUND policy failed\n");
+ goto end;
+ }
+
+
+ }
+ }
end:
return err;
@@ -445,12 +494,14 @@
const struct in6_addr *hoa,
const struct in6_addr *coa,
const struct in6_addr *old_coa,
- int tunnel)
+ int tunnel,
+ struct list_head *mnp)
{
struct ha_ipsec_tnl_update b;
b.coa = *coa;
b.old_coa = *old_coa;
b.tunnel = tunnel;
+ b.mnp = mnp;
return ipsec_policy_apply(haaddr, hoa, _ha_tnl_update, &b);
}
@@ -464,7 +515,9 @@
int add)
{
int err = 0;
- int ifindex = *(int *)arg;
+ struct ha_ipsec_tnl_update *parms = (struct ha_ipsec_tnl_update *)arg;
+ int ifindex;
+ struct list_head *mnp;
struct xfrm_userpolicy_info sp;
struct xfrm_user_tmpl tmpl;
u_int16_t ipsec_proto;
@@ -474,6 +527,9 @@
assert(e);
assert(arg);
+ ifindex = parms->tunnel;
+ mnp = parms->mnp;
+
switch (e->type) {
case IPSEC_POLICY_TYPE_TUNNELHOMETESTING:
case IPSEC_POLICY_TYPE_TUNNELMH:
@@ -529,6 +585,52 @@
err = -1;
goto end;
}
+
+ /* Mobile router case */
+ if ( (e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && mnp)
+ {
+ struct list_head *list;
+
+ /* We have to add/delete rules to protect traffic to and from MNP's, the same way as HoA */
+ list_for_each(list, mnp)
+ {
+ struct prefix_list_entry *p;
+ p = list_entry(list, struct prefix_list_entry, list);
+
+ /* inbound */
+ _set_sp(&sp, e, XFRM_POLICY_IN, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
+ ifindex, MIP6_ENTITY_HA);
+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
+ haaddr, hoa, e->reqid_toha);
+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
+ dbg("modifying INBOUND policy failed\n");
+ err = -1;
+ goto end;
+ }
+
+ /* forward */
+ _set_sp(&sp, e, XFRM_POLICY_FWD, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
+ ifindex, MIP6_ENTITY_HA);
+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
+ haaddr, hoa, e->reqid_toha);
+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
+ dbg("modifying FORWARD policy failed\n");
+ err = -1;
+ goto end;
+ }
+
+ /* outbound */
+ _set_sp(&sp, e, XFRM_POLICY_OUT, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
+ ifindex, MIP6_ENTITY_HA);
+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
+ hoa, haaddr, e->reqid_tomn);
+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
+ dbg("modifying OUTBOUND policy failed\n");
+ err = -1;
+ goto end;
+ }
+ }
+ }
end:
return err;
@@ -550,11 +652,14 @@
int ha_ipsec_tnl_pol_add(const struct in6_addr *our_addr,
const struct in6_addr *peer_addr,
- int tunnel)
+ int tunnel,
+ struct list_head *mnp)
{
- int t = tunnel;
+ struct ha_ipsec_tnl_update b;
+ b.tunnel = tunnel;
+ b.mnp = mnp;
- return ipsec_policy_apply(our_addr, peer_addr, _ha_tnl_pol_add, &t);
+ return ipsec_policy_apply(our_addr, peer_addr, _ha_tnl_pol_add, &b);
}
/*
@@ -573,12 +678,15 @@
int ha_ipsec_tnl_pol_del(const struct in6_addr *our_addr,
const struct in6_addr *peer_addr,
- int tunnel)
+ int tunnel,
+ struct list_head *mnp)
{
- int t = tunnel;
+ struct ha_ipsec_tnl_update b;
+ b.tunnel = tunnel;
+ b.mnp = mnp;
return ipsec_policy_apply(our_addr, peer_addr,
- _ha_tnl_pol_del, &t);
+ _ha_tnl_pol_del, &b);
}
/*
diff -Nur trunk.common-mod/src/ipsec.h trunk.ha/src/ipsec.h
--- trunk.common-mod/src/ipsec.h 2007-10-15 17:54:32.000000000 +0900
+++ trunk.ha/src/ipsec.h 2007-10-15 17:45:35.000000000 +0900
@@ -82,15 +82,18 @@
const struct in6_addr *hoa,
const struct in6_addr *coa,
const struct in6_addr *old_coa,
- int tunnel);
+ int tunnel,
+ struct list_head *mnp);
int ha_ipsec_tnl_pol_add(const struct in6_addr *our_addr,
const struct in6_addr *peer_addr,
- int tunnel);
+ int tunnel,
+ struct list_head *mnp);
int ha_ipsec_tnl_pol_del(const struct in6_addr *our_addr,
const struct in6_addr *peer_addr,
- int tunnel);
+ int tunnel,
+ struct list_head *mnp);
int mn_ipsec_tnl_update(const struct in6_addr *haaddr,
const struct in6_addr *hoa,
diff -Nur trunk.common-mod/src/ipsec.c trunk.mr/src/ipsec.c
--- trunk.common-mod/src/ipsec.c 2007-10-16 11:42:33.000000000 +0900
+++ trunk.mr/src/ipsec.c 2007-10-16 11:59:58.000000000 +0900
@@ -673,6 +673,53 @@
goto end;
}
}
+
+ /*
+ * If we are a Mobile Router, we also need to migrate IN/FWD/OUT rules
+ * for forwarded traffic in case we have TUNNELPAYLOAD protection.
+ */
+ if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && (bule->home->mob_rtr))
+ {
+ struct list_head *mnp;
+
+ list_for_each(mnp, &bule->home->mob_net_prefixes)
+ {
+ struct prefix_list_entry *p;
+ p = list_entry(mnp, struct prefix_list_entry, list);
+
+ /* outbound */
+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
+ haaddr, oldcoa, e->reqid_toha);
+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
+ ifindex, MIP6_ENTITY_MN);
+ if ((err = xfrm_sendmigrate(&sp, &tmpl, haaddr, newcoa)) < 0) {
+ dbg("migrate for OUTBOUND policy failed\n");
+ goto end;
+ }
+
+ /* forwarded */
+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
+ oldcoa, haaddr, e->reqid_tomn);
+ _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
+ ifindex, MIP6_ENTITY_MN);
+ if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
+ dbg("migrate for INBOUND policy (1) failed\n");
+ goto end;
+ }
+
+ /* inbound */
+ _set_tmpl(&tmpl, 0, ipsec_proto, XFRM_MODE_TUNNEL,
+ oldcoa, haaddr, e->reqid_tomn);
+ _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
+ ifindex, MIP6_ENTITY_MN);
+ if ((err = xfrm_sendmigrate(&sp, &tmpl, newcoa, haaddr)) < 0) {
+ dbg("migrate for INBOUND policy (1) failed\n");
+ goto end;
+ }
+
+ }
+ }
+
end:
return err;
@@ -765,6 +812,56 @@
err = cn_wildrecv_bu_pol_add();
}
}
+
+ /*
+ * If we are a Mobile Router, we also need to create IN/FWD/OUT rules
+ * for forwarded traffic in case we have TUNNELPAYLOAD protection.
+ */
+ if ((e->type == IPSEC_POLICY_TYPE_TUNNELPAYLOAD) && (bule->home->mob_rtr))
+ {
+ struct list_head *mnp;
+
+ list_for_each(mnp, &bule->home->mob_net_prefixes)
+ {
+ struct prefix_list_entry *p;
+ p = list_entry(mnp, struct prefix_list_entry, list);
+
+ /* inbound */
+ _set_sp(&sp, e, XFRM_POLICY_IN, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
+ ifindex, MIP6_ENTITY_MN);
+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
+ hoa, haaddr, e->reqid_tomn);
+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
+ dbg("modifying INBOUND policy failed.\n");
+ err = -1;
+ goto end;
+ }
+
+ /* forward */
+ _set_sp(&sp, e, XFRM_POLICY_FWD, &p->ple_prefix, p->ple_plen, &in6addr_any, 0,
+ ifindex, MIP6_ENTITY_MN);
+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
+ hoa, haaddr, e->reqid_tomn);
+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
+ dbg("modifying INBOUND policy failed.\n");
+ err = -1;
+ goto end;
+ }
+
+ /* outbound */
+ _set_sp(&sp, e, XFRM_POLICY_OUT, &in6addr_any, 0, &p->ple_prefix, p->ple_plen,
+ ifindex, MIP6_ENTITY_MN);
+ _set_tmpl(&tmpl, AF_INET6, ipsec_proto, XFRM_MODE_TUNNEL,
+ haaddr, hoa, e->reqid_toha);
+ if (xfrm_ipsec_policy_mod(&sp, &tmpl, 1, add) < 0) {
+ dbg("modifying OUTBOUND policy failed.\n");
+ err = -1;
+ goto end;
+ }
+ }
+ }
+
+
end:
return err;
diff -Nur trunk.common-mod/src/xfrm.c trunk.mr/src/xfrm.c
--- trunk.common-mod/src/xfrm.c 2007-10-15 17:54:32.000000000 +0900
+++ trunk.mr/src/xfrm.c 2007-10-16 11:59:58.000000000 +0900
@@ -679,12 +679,76 @@
return err;
}
+static int mr_ipsec_bypass_init(void)
+{
+ struct list_head *home;
+ struct list_head *mnps;
+ int err=0;
+
+ /* Loop for each HomeAddress info */
+ list_for_each(home, &conf_parsed->home_addrs)
+ {
+ struct home_addr_info *hai;
+ hai = list_entry(home, struct home_addr_info, list);
+
+ /* If Mobile Router for this link, loop for each MNP */
+ if (hai->mob_rtr)
+ {
+ /* Add bypass policies to and from the MNP link */
+ list_for_each(mnps, &hai->mob_net_prefixes)
+ {
+ struct prefix_list_entry * mnp;
+ struct xfrm_selector sel;
+
+ mnp = list_entry(mnps, struct prefix_list_entry, list);
+
+ memset(&sel, 0, sizeof(sel));
+ sel.family = AF_INET6;
+ sel.user = getuid();
+
+ /* IN, src = MNP , dst = any */
+ memcpy(&sel.saddr.a6, &mnp->ple_prefix, sizeof(sel.saddr.a6));
+ sel.prefixlen_s = mnp->ple_plen;
+
+ err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_IN,
+ XFRM_POLICY_ALLOW, MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
+ NULL, 0);
+
+ /* XXX: what should we do in case of error? */
+
+ /* FWD, src = MNP , dst = any */
+ err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_FWD,
+ XFRM_POLICY_ALLOW, MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
+ NULL, 0);
+
+
+ /* OUT, src = any , dst = MNP */
+ memset(&sel.saddr.a6, 0, sizeof(sel.saddr.a6));
+ sel.prefixlen_s = 0;
+ memcpy(&sel.daddr.a6, &mnp->ple_prefix, sizeof(sel.daddr.a6));
+ sel.prefixlen_d = mnp->ple_plen;
+
+ err = xfrm_ipsec_policy_add(&sel, 0, XFRM_POLICY_OUT,
+ XFRM_POLICY_ALLOW, MIP6_PRIO_MR_LOCAL_DATA_BYPASS,
+ NULL, 0);
+
+ }
+ }
+ }
+
+ return err;
+
+}
+
static inline int mn_ha_ipsec_init(void)
{
int err;
/* insert bypass policy */
err = ipsec_policy_walk(_mn_ha_ipsec_bypass_init, NULL);
+
+ /* insert NEMO-related bypass */
+ err = mr_ipsec_bypass_init();
err = ipsec_policy_walk(_mn_ha_ipsec_init, NULL);
@@ -787,9 +851,67 @@
return err;
}
+static int mr_ipsec_bypass_cleanup(void)
+{
+ struct list_head *home;
+ struct list_head *mnps;
+ int err=0;
+
+ /* Loop for each HomeAddress info */
+ list_for_each(home, &conf_parsed->home_addrs)
+ {
+ struct home_addr_info *hai;
+ hai = list_entry(home, struct home_addr_info, list);
+
+ /* If Mobile Router for this link, loop for each MNP */
+ if (hai->mob_rtr)
+ {
+ /* Delete bypass policies to and from the MNP link */
+ list_for_each(mnps, &hai->mob_net_prefixes)
+ {
+ struct prefix_list_entry * mnp;
+ struct xfrm_selector sel;
+
+ mnp = list_entry(mnps, struct prefix_list_entry, list);
+
+ memset(&sel, 0, sizeof(sel));
+ sel.family = AF_INET6;
+ sel.user = getuid();
+
+ /* IN, src = MNP , dst = any */
+ memcpy(&sel.saddr.a6, &mnp->ple_prefix, sizeof(sel.saddr.a6));
+ sel.prefixlen_s = mnp->ple_plen;
+
+ err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_IN);
+
+ /* XXX: what should we do in case of error? */
+
+ /* FWD, src = MNP , dst = any */
+ err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_FWD);
+
+
+ /* OUT, src = any , dst = MNP */
+ memset(&sel.saddr.a6, 0, sizeof(sel.saddr.a6));
+ sel.prefixlen_s = 0;
+ memcpy(&sel.daddr.a6, &mnp->ple_prefix, sizeof(sel.daddr.a6));
+ sel.prefixlen_d = mnp->ple_plen;
+
+ err = xfrm_ipsec_policy_del(&sel, XFRM_POLICY_OUT);
+
+ }
+ }
+ }
+
+ return err;
+
+}
+
+
static inline void mn_ha_ipsec_cleanup(void)
{
ipsec_policy_walk(_mn_ha_ipsec_bypass_cleanup, NULL);
+
+ (void)mr_ipsec_bypass_cleanup();
ipsec_policy_walk(_mn_ha_ipsec_cleanup, NULL);
}
diff -Nur trunk.common-mod/src/xfrm.h trunk.mr/src/xfrm.h
--- trunk.common-mod/src/xfrm.h 2007-10-15 17:54:32.000000000 +0900
+++ trunk.mr/src/xfrm.h 2007-10-16 11:59:58.000000000 +0900
@@ -15,6 +15,7 @@
#define MIP6_PRIO_RO_SIG_IPSEC 7 /* XXX: BU between MN-MN with IPsec */
#define MIP6_PRIO_RO_SIG 8 /* XXX: BU between MN-CN */
#define MIP6_PRIO_RO_SIG_ANY 9
+#define MIP6_PRIO_MR_LOCAL_DATA_BYPASS 9 /* Bypass rule for local traffic in mobile network */
#define MIP6_PRIO_RO_SIG_RR 10 /* XXX: MH(or HoTI/HoT) between MN-CN */
#define MIP6_PRIO_RO_BLOCK 11
#define MIP6_PRIO_NO_RO_SIG_ANY 12