Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

imported experimental ipsecdb update code contributed by Francis Dupont.

  • Loading branch information...
commit 0b17d417f500f3c8205c864cf72128b775663b59 1 parent c2eef72
keiichi authored
View
6 kame/kame/shisad/Makefile.in
@@ -25,7 +25,7 @@
# SUCH DAMAGE.
#
-# $Id: Makefile.in,v 1.5 2007/01/19 11:00:31 keiichi Exp $
+# $Id: Makefile.in,v 1.6 2007/02/27 01:44:12 keiichi Exp $
#
prefix= @prefix@
@@ -57,6 +57,7 @@ MNDOBJS= mnd-binding.o mnd-common.o mnd-hal.o mnd-mh.o mnd-mnd.o \
mnd-nemo_var.o \
fsm.o rr.o \
callout.o command.o config.o fdlist.o network.o util.o \
+ @IPSEC_O@ \
$(GENSRCS:%.c=%.o)
MNDCFLAGS= -DMIP_MN
MNDLIBS= -lcrypto
@@ -76,6 +77,7 @@ BABYMDDOBJS= babymdd.o network.o util.o \
HADOBJS= had-binding.o had-common.o had-had.o had-hal.o had-mh.o \
had-nemo_var.o \
callout.o command.o config.o fdlist.o network.o util.o \
+ @IPSEC_O@ \
$(GENSRCS:%.c=%.o)
HADCFLAGS= -DMIP_HA
#HADCFLAGS+= -DMIP_MCOA
@@ -180,4 +182,4 @@ distclean:: clean
/bin/rm -f Makefile config.cache config.log config.status .depend
depend:
- mkdep ${CFLAGS:M-[ID]*} $(srcdir)/*.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -M $(MNDOBJS:%.o=%c) > .depend
View
5 kame/kame/shisad/auth.c
@@ -1,4 +1,4 @@
-/* $KAME: auth.c,v 1.3 2006/10/20 07:41:15 t-momose Exp $ */
+/* $KAME: auth.c,v 1.4 2007/02/27 01:44:12 keiichi Exp $ */
/*
* Copyright (C) 2006 WIDE Project. All rights reserved.
@@ -453,7 +453,8 @@ aaa_auth_done(success)
bc->bc_authmethod_done |= BC_AUTH_MNAAA;
if ((bc->bc_authmethod ^ bc->bc_authmethod_done) == 0)
bc->bc_state &= ~BC_STATE_UNDER_AUTH;
- mip6_validate_bc(bc);
+ /* XXX is (void) OK? */
+ (void)mip6_validate_bc(bc);
if ((bc->bc_state == BC_STATE_VALID) &&
!IN6_IS_ADDR_LINKLOCAL(&bc->bc_hoa)) {
if (bc->bc_flags & (IP6_MH_BU_ACK | IP6_MH_BU_HOME))
View
167 kame/kame/shisad/binding.c
@@ -1,4 +1,4 @@
-/* $KAME: binding.c,v 1.36 2007/02/13 08:02:22 t-momose Exp $ */
+/* $KAME: binding.c,v 1.37 2007/02/27 01:44:12 keiichi Exp $ */
/*
* Copyright (C) 2004 WIDE Project. All rights reserved.
@@ -120,12 +120,13 @@ mip6_flush_kernel_bc()
mipmsg.miph_type = MIPM_BC_FLUSH;
if (write(mipsock, &mipmsg, sizeof(struct mip_msghdr)) == -1) {
syslog(LOG_ERR,
- "removing all bul entries failed.");
+ "removing all bc entries failed.");
}
}
struct binding_cache *
-mip6_bc_add(hoa, coa, recvaddr, lifetime, flags, seqno, bid, authmethod, authmethod_done, mobility_spi)
+mip6_bc_add(hoa, coa, recvaddr, lifetime, flags, seqno, bid,
+ authmethod, authmethod_done, mobility_spi)
struct in6_addr *hoa, *coa, *recvaddr;
u_int32_t lifetime;
u_int16_t flags;
@@ -163,10 +164,15 @@ mip6_bc_add(hoa, coa, recvaddr, lifetime, flags, seqno, bid, authmethod, authmet
/* update BC in the kernel via mipsock */
mipsock_bc_request(bc, MIPM_BC_ADD);
+#ifdef MIP_IPSEC
+ if (ipsec_bc_request(bc, MIPM_BC_UPDATE) < 0)
+ return (bc);
+#endif /* MIP_IPSEC */
bc->bc_expire = now + bc->bc_lifetime;
- if (!IN6_IS_ADDR_LINKLOCAL(hoa) && !(bc->bc_state & BC_STATE_UNDER_DAD))
+ if (!IN6_IS_ADDR_LINKLOCAL(hoa)
+ && !(bc->bc_state & BC_STATE_UNDER_DAD))
mip6_bc_set_refresh_timer(bc, bc->bc_lifetime / 2);
return (bc);
}
@@ -201,29 +207,34 @@ mip6_bc_add(hoa, coa, recvaddr, lifetime, flags, seqno, bid, authmethod, authmet
bc->bc_bid = bid;
#endif /* MIP_MCOA */
bc->bc_mobility_spi = mobility_spi;
-
if (bc->bc_state & BC_STATE_UNDER_DAD) {
/* do dad start */
mip6_dad_start(hoa);
+ } else if (mip6_validate_bc(bc) < 0) {
+ free(bc);
+ return (NULL);
}
-
- mip6_validate_bc(bc);
- LIST_INSERT_HEAD(&bchead, bc, bc_entry);
+ LIST_INSERT_HEAD(&bchead, bc, bc_entry);
bc->bc_refcnt++;
return (bc);
}
-void
+int
mip6_validate_bc(bc)
struct binding_cache *bc;
{
time_t now;
if (bc->bc_state != BC_STATE_VALID)
- return;
+ return (0);
now = time(0);
+#ifdef MIP_IPSEC
+ /* IPsec can fail: do it first */
+ if (ipsec_bc_request(bc, MIPM_BC_ADD) < 0)
+ return (-1);
+#endif /* MIP_IPSEC */
/* insert the BC into the kernel via mipsock */
mipsock_bc_request(bc, MIPM_BC_ADD);
bc->bc_expire = now + bc->bc_lifetime;
@@ -233,6 +244,7 @@ mip6_validate_bc(bc)
a independent timer. */
if (!IN6_IS_ADDR_LINKLOCAL(&bc->bc_hoa))
mip6_bc_set_refresh_timer(bc, bc->bc_lifetime / 2);
+ return (0);
}
void
@@ -264,6 +276,9 @@ mip6_bc_delete(bcreq)
case BC_STATE_VALID:
/* delete the BCE in the kernel via mipsock */
mipsock_bc_request(bc, MIPM_BC_REMOVE);
+#ifdef MIP_IPSEC
+ (void) ipsec_bc_request(bc, MIPM_BC_REMOVE);
+#endif /* MIP_IPSEC */
/* Fall through */
case BC_STATE_UNDER_DAD:
if (bc->bc_llmbc) {
@@ -283,6 +298,9 @@ mip6_bc_delete(bcreq)
}
/* Fall through */
case BC_STATE_DEPRECATED:
+#ifdef MIP_IPSEC
+ ipsec_bc_data_release(bc);
+#endif /* MIP_IPSEC */
if (--bc->bc_refcnt == 0) {
free(bc);
}
@@ -292,7 +310,7 @@ mip6_bc_delete(bcreq)
return;
}
-/* src can be wildcard */
+/* src and bid can be wildcard */
struct binding_cache *
mip6_bc_lookup(hoa, src, bid)
struct in6_addr *hoa;
@@ -367,7 +385,14 @@ mip6_dad_done(message, addr)
"DAD against the HoA(%s) is suceeded.",
ip6_sprintf(addr));
bc->bc_state &= ~BC_STATE_UNDER_DAD;
- mip6_validate_bc(bc);
+ if (mip6_validate_bc(bc) < 0) {
+ syslog(LOG_INFO,
+ "IPsec init failure after DAD for %s\n",
+ ip6_sprintf(addr));
+ mip6_bc_delete(bc);
+ if (gbc != bc)
+ mip6_bc_delete(gbc);
+ }
if ((bc->bc_state == BC_STATE_VALID) &&
!IN6_IS_ADDR_LINKLOCAL(addr)) {
if (bc->bc_flags & (IP6_MH_BU_ACK | IP6_MH_BU_HOME))
@@ -379,7 +404,7 @@ mip6_dad_done(message, addr)
} else if (message == MIPM_DAD_FAIL) {
/* I got a message the DAD was failed */
syslog(LOG_INFO,
- "DAD aganist the HoA(%s) is failed.",
+ "DAD against the HoA(%s) is failed.",
ip6_sprintf(addr));
if (gbc == NULL || bc == NULL)
@@ -447,7 +472,7 @@ mip6_bc_set_refresh_timer(bc, tick)
{
remove_callout_entry(bc->bc_refresh);
bc->bc_refresh = new_callout_entry(tick, mip6_bc_refresh_timer,
- (void *)bc, "mip6_bc_refresh_timer");
+ (void *)bc, "mip6_bc_refresh_timer");
}
static void
@@ -485,7 +510,8 @@ mip6_bc_refresh_timer(arg)
if (bc->bc_expire < (now + MIP6_BRR_INTERVAL))
mip6_bc_set_refresh_timer(bc, (bc->bc_expire) - now);
else /* set timer with the refresh backoff interval */
- mip6_bc_set_refresh_timer(bc, /*MIP6_BRR_INTERVAL*/(bc->bc_expire - now) / 2);
+ mip6_bc_set_refresh_timer(bc,
+ /*MIP6_BRR_INTERVAL*/(bc->bc_expire - now) / 2);
return;
}
@@ -553,7 +579,8 @@ mipsock_bc_request(bc, command)
default:
break;
}
- syslog(LOG_INFO, "[BC info] HoA %s", ip6_sprintf(&bc->bc_hoa));
+ syslog(LOG_INFO, "[BC info] HoA %s",
+ ip6_sprintf(&bc->bc_hoa));
syslog(LOG_INFO, "\tCoA %s", ip6_sprintf(&bc->bc_coa));
syslog(LOG_INFO, "\tPeer %s", ip6_sprintf(&bc->bc_myaddr));
#ifdef MIP_MCOA
@@ -613,7 +640,7 @@ hoainfo_insert(hoa, ifindex)
if (debug)
syslog(LOG_INFO, "hoainfo entry (HoA %s ifindex %d) is added",
- ip6_sprintf(hoa), ifindex);
+ ip6_sprintf(hoa), ifindex);
return (hoainfo);
}
@@ -693,8 +720,10 @@ bul_insert(hoainfo, peeraddr, coa, flags, bid)
else {
struct binding_update_list *bul2;
- /* if primary bul is active and bul matched with bid is also active */
- bul2 = bul_mcoa_get(&hoainfo->hinfo_hoa, peeraddr, bid);
+ /* if primary bul is active and bul matched
+ with bid is also active */
+ bul2 = bul_mcoa_get(&hoainfo->hinfo_hoa,
+ peeraddr, bid);
if (bul2)
return (bul2);
@@ -705,8 +734,10 @@ bul_insert(hoainfo, peeraddr, coa, flags, bid)
LIST_INSERT_HEAD(&bul->bul_mcoa_head, bul2, bul_entry);
if (debug)
- syslog(LOG_INFO, "insert bul %s w/ %d into hoainfo\n",
- ip6_sprintf(&hoainfo->hinfo_hoa), bul2->bul_bid);
+ syslog(LOG_INFO,
+ "insert bul %s w/ %d into hoainfo\n",
+ ip6_sprintf(&hoainfo->hinfo_hoa),
+ bul2->bul_bid);
return (bul2);
}
#endif /* MIP_MCOA */
@@ -727,8 +758,9 @@ bul_insert(hoainfo, peeraddr, coa, flags, bid)
bul2->bul_bid = bid;
LIST_INSERT_HEAD(&bul->bul_mcoa_head, bul2, bul_entry);
if (debug)
- syslog(LOG_ERR, "insert bul %s w/ %d into hoainfo\n",
- ip6_sprintf(&hoainfo->hinfo_hoa), bul2->bul_bid);
+ syslog(LOG_ERR,
+ "insert bul %s w/ %d into hoainfo\n",
+ ip6_sprintf(&hoainfo->hinfo_hoa), bul2->bul_bid);
return (bul2);
}
#endif /* MIP_MCOA */
@@ -748,9 +780,10 @@ bul_create(peeraddr, coa, flags, hoainfo)
{
struct binding_update_list *bul = NULL;
- bul = (struct binding_update_list *)malloc(sizeof(struct binding_update_list));
+ bul = (struct binding_update_list *)
+ malloc(sizeof(struct binding_update_list));
if (bul == NULL) {
- syslog(LOG_ERR, "Faild to allocate memory for a bul.");
+ syslog(LOG_ERR, "Failed to allocate memory for a bul\n");
return (NULL);
}
@@ -776,6 +809,9 @@ bul_remove(bul)
{
if (bul == NULL)
return;
+#ifdef MIP_IPSEC
+ ipsec_bul_data_release(bul);
+#endif /* MIP_IPSEC */
#ifdef MIP_MCOA
if (!LIST_EMPTY(&bul->bul_mcoa_head)) {
struct binding_update_list *mbul, *mbuln;
@@ -784,6 +820,9 @@ bul_remove(bul)
mbul = mbuln) {
mbuln = LIST_NEXT(mbul, bul_entry);
+#ifdef MIP_IPSEC
+ ipsec_bul_data_release(mbul);
+#endif /* MIP_IPSEC */
LIST_REMOVE(mbul, bul_entry);
free(mbul);
mbul = NULL;
@@ -834,7 +873,7 @@ int bul_check_ifid(hoainfo)
if (getifaddrs(&ifap) != 0) {
syslog(LOG_ERR, "%s\n", strerror(errno));
- return 0;
+ return (0);
}
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
@@ -857,9 +896,9 @@ int bul_check_ifid(hoainfo)
freeifaddrs(ifap);
if (is_same_ifid)
- return 1;
+ return (1);
- return 0;
+ return (0);
}
#ifdef MIP_MCOA
@@ -938,7 +977,8 @@ bul_flush(hoainfo)
buln = LIST_NEXT(bul, bul_entry);
#ifdef TODO
- /* before removing the entry, MUST remove bu entry in the kernel */
+ /* before removing the entry, MUST remove bu entry
+ in the kernel */
#endif
LIST_REMOVE(bul, bul_entry);
free(bul);
@@ -1015,30 +1055,38 @@ command_show_bul_one(s, bul)
command_printf(s, "%s ", ip6_sprintf(&bul->bul_peeraddr));
#ifndef MIP_MCOA
command_printf(s, "%s ",
- ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
#else
if (bul->bul_bid)
command_printf(s, "%s$%d ",
- ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa), bul->bul_bid);
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa), bul->bul_bid);
else
command_printf(s, "%s ",
- ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
#endif /* MIP_MCOA */
- command_printf(s, "%s\n",
- ip6_sprintf(&bul->bul_coa));
+ command_printf(s, "%s\n", ip6_sprintf(&bul->bul_coa));
command_printf(s,
- " lif=%d, ref=%d, seq=%d, %c%c%c%c%c%c, %c, ",
- bul->bul_lifetime,
- bul->bul_refresh,
- bul->bul_seqno,
- (bul->bul_flags & IP6_MH_BU_ACK) ? 'A' : '-',
- (bul->bul_flags & IP6_MH_BU_HOME) ? 'H' : '-',
- (bul->bul_flags & IP6_MH_BU_LLOCAL) ? 'L' : '-',
- (bul->bul_flags & IP6_MH_BU_KEYM) ? 'K' : '-',
- (bul->bul_flags & IP6_MH_BU_ROUTER) ? 'R' : '-',
- (bul->bul_flags & IP6_MH_BU_MCOA) ? 'M' : '-',
- (bul->bul_state & MIP6_BUL_STATE_DISABLE) ? 'D' : '-');
+#ifdef MIP_IPSEC
+ " lif=%d, ref=%d, seq=%d, %c%c%c%c%c%c, %c%c, ",
+#else
+ " lif=%d, ref=%d, seq=%d, %c%c%c%c%c%c, %c, ",
+#endif /* MIP_IPSEC */
+ bul->bul_lifetime,
+ bul->bul_refresh,
+ bul->bul_seqno,
+ (bul->bul_flags & IP6_MH_BU_ACK) ? 'A' : '-',
+ (bul->bul_flags & IP6_MH_BU_HOME) ? 'H' : '-',
+ (bul->bul_flags & IP6_MH_BU_LLOCAL) ? 'L' : '-',
+ (bul->bul_flags & IP6_MH_BU_KEYM) ? 'K' : '-',
+ (bul->bul_flags & IP6_MH_BU_ROUTER) ? 'R' : '-',
+ (bul->bul_flags & IP6_MH_BU_MCOA) ? 'M' : '-',
+ (bul->bul_state & MIP6_BUL_STATE_DISABLE) ? 'D' : '-'
+#ifdef MIP_IPSEC
+ ,
+ (bul->bul_state & MIP6_BUL_STATE_USEIPSEC) ? 'I' : '-'
+#endif /* MIP_IPSEC */
+ );
command_printf(s,
"%s, %s, ret=%ld, exp=%ld\n",
@@ -1072,7 +1120,8 @@ command_show_kbul(s, dummy)
hoainfo = LIST_NEXT(hoainfo, hinfo_entry)) {
memset(&bulreq, 0, sizeof(bulreq));
bulreq.ifbu_count = 0;
- bulreq.ifbu_len = sizeof(struct if_bulreq) + sizeof(struct bul6info) * 10;
+ bulreq.ifbu_len = sizeof(struct if_bulreq)
+ + sizeof(struct bul6info) * 10;
bulreq.ifbu_info = (struct bul6info *)bulinfobuff;
memset(ifname, 0, sizeof(ifname));
@@ -1084,14 +1133,16 @@ command_show_kbul(s, dummy)
if (ioctl(sock, SIOCGBULIST, &bulreq) < 0) {
perror("ioctl");
- command_printf(s, "ioctl to get buls is failed for %s\n", ifname);
+ command_printf(s,
+ "ioctl to get buls is failed for %s\n", ifname);
break;
}
/* dump bul */
for (i = 0; i < bulreq.ifbu_count; i++) {
bul6 = bulreq.ifbu_info + i * sizeof(struct bul6info);
- command_printf(s, "%s ", ip6_sprintf(&bul6->bul_peeraddr));
+ command_printf(s, "%s ",
+ ip6_sprintf(&bul6->bul_peeraddr));
command_printf(s, "%s",
ip6_sprintf(&bul6->bul_hoa));
@@ -1100,18 +1151,18 @@ command_show_kbul(s, dummy)
command_printf(s, "$%d", bul6->bul_bid);
#endif /* MIP_MCOA */
- command_printf(s, " %s\n",
- ip6_sprintf(&bul6->bul_coa));
+ command_printf(s, " %s\n",
+ ip6_sprintf(&bul6->bul_coa));
command_printf(s,
- " %s, %c%c%c%c%c%c\n",
- if_indextoname(bul6->bul_ifindex, ifname),
- (bul6->bul_flags & IP6_MH_BU_ACK) ? 'A' : '-',
- (bul6->bul_flags & IP6_MH_BU_HOME) ? 'H' : '-',
- (bul6->bul_flags & IP6_MH_BU_LLOCAL) ? 'L' : '-',
- (bul6->bul_flags & IP6_MH_BU_KEYM) ? 'K' : '-',
- (bul6->bul_flags & IP6_MH_BU_ROUTER) ? 'R' : '-',
- (bul6->bul_flags & IP6_MH_BU_MCOA) ? 'M' : '-');
+ " %s, %c%c%c%c%c%c\n",
+ if_indextoname(bul6->bul_ifindex, ifname),
+ (bul6->bul_flags & IP6_MH_BU_ACK) ? 'A' : '-',
+ (bul6->bul_flags & IP6_MH_BU_HOME) ? 'H' : '-',
+ (bul6->bul_flags & IP6_MH_BU_LLOCAL) ? 'L' : '-',
+ (bul6->bul_flags & IP6_MH_BU_KEYM) ? 'K' : '-',
+ (bul6->bul_flags & IP6_MH_BU_ROUTER) ? 'R' : '-',
+ (bul6->bul_flags & IP6_MH_BU_MCOA) ? 'M' : '-');
}
}
View
6,331 kame/kame/shisad/configure
1,331 additions, 5,000 deletions not shown
View
13 kame/kame/shisad/configure.in
@@ -27,4 +27,17 @@ AC_FUNC_MEMCMP
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(gettimeofday select socket strdup strerror strtol)
+AC_MSG_CHECKING(--enable-updateipsecdb)
+updateipsecdb="no"
+IPSEC_O=''
+AC_ARG_ENABLE(updateipsecdb,
+ [ --enable-updateipsecdb enable IPsec database update by SHISA],
+ [updateipsecdb="$enableval"])
+AC_MSG_RESULT($updateipsecdb)
+if test x"$updateipsecdb" = x"yes"; then
+ AC_DEFINE(MIP_IPSEC, 1, [define to update IPsec DB by SHISA])
+ IPSEC_O='ipsec.o'
+fi
+AC_SUBST(IPSEC_O)
+
AC_OUTPUT(Makefile)
View
97 kame/kame/shisad/fsm.c
@@ -1,4 +1,4 @@
-/* $KAME: fsm.c,v 1.46 2007/02/19 09:07:00 t-momose Exp $ */
+/* $KAME: fsm.c,v 1.47 2007/02/27 01:44:12 keiichi Exp $ */
/*
* Copyright (C) 2004 WIDE Project. All rights reserved.
@@ -88,6 +88,8 @@ static void dump_ba(struct in6_addr *, struct in6_addr *, struct in6_addr *,
static void bul_print_all(void);
static int bul_send_unsolicited_na(struct binding_update_list *);
+
+
static void bul_stop_retrans_timer(struct binding_update_list *);
static void bul_stop_timers(struct binding_update_list *);
static void bul_stop_expire_timer(struct binding_update_list *);
@@ -410,7 +412,11 @@ bul_reg_fsm(bul, event, data)
bul->bul_lifetime
= set_default_bu_lifetime(bul->bul_hoainfo);
if ((bul->bul_flags & IP6_MH_BU_HOME) != 0) {
- if (!IN6_IS_ADDR_UNSPECIFIED(&bul->bul_peeraddr)) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&bul->bul_peeraddr)
+#ifdef MIP_IPSEC
+ && !ipsec_bul_request(bul, MIPM_BUL_ADD)
+#endif /* MIP_IPSEC */
+ ) {
error = send_bu(bul);
if (error) {
syslog(LOG_ERR,
@@ -910,6 +916,10 @@ bul_reg_fsm(bul, event, data)
bul_set_expire_timer(bul,
bul->bul_lifetime << 2);
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_UPDATE);
+#endif /* MIP_IPSEC */
+
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITA;
} else {
/* XXX no need? */
@@ -949,7 +959,9 @@ bul_reg_fsm(bul, event, data)
bul_set_expire_timer(bul,
bul->bul_lifetime << 2);
-
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_REMOVE);
+#endif /* MIP_IPSEC */
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITD;
} else {
/* XXX no need? */
@@ -1124,6 +1136,10 @@ bul_reg_fsm(bul, event, data)
bul_set_retrans_timer(bul,
bul->bul_retrans_time);
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_UPDATE);
+#endif /* MIP_IPSEC */
+
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITA;
} else {
/* XXX no need? */
@@ -1163,7 +1179,9 @@ bul_reg_fsm(bul, event, data)
= initial_bindack_timeout_first_reg;
bul_set_retrans_timer(bul,
bul->bul_retrans_time);
-
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_REMOVE);
+#endif /* MIP_IPSEC */
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITD;
}
break;
@@ -1319,6 +1337,9 @@ bul_reg_fsm(bul, event, data)
bul_set_expire_timer(bul,
bul->bul_lifetime << 2);
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_UPDATE);
+#endif /* MIP_IPSEC */
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITA;
}
break;
@@ -1526,7 +1547,9 @@ bul_reg_fsm(bul, event, data)
= initial_bindack_timeout_first_reg;
bul_set_retrans_timer(bul,
bul->bul_retrans_time);
-
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_UPDATE);
+#endif /* MIP_IPSEC */
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITA;
}
break;
@@ -1604,7 +1627,9 @@ bul_reg_fsm(bul, event, data)
= initial_bindack_timeout_first_reg;
bul_set_retrans_timer(bul,
bul->bul_retrans_time);
-
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_REMOVE);
+#endif /* MIP_IPSEC */
REGFSMS = MIP6_BUL_REG_FSM_STATE_WAITD;
}
break;
@@ -1779,12 +1804,31 @@ bul_reg_fsm(bul, event, data)
* Start retransmission timer,
* Start expire timer.
*/
+#ifdef MIP_IPSEC
+ next:
+#endif /* MIP_IPSEC */
hal = mip6_find_hal(bul->bul_hoainfo);
if (hal == NULL)
break;
- memcpy(&bul->bul_peeraddr, &hal->hal_ip6addr, sizeof(struct in6_addr));
- syslog(LOG_INFO, "%s peer addd--------> add", ip6_sprintf(&bul->bul_peeraddr));
+ memcpy(&bul->bul_peeraddr, &hal->hal_ip6addr,
+ sizeof(struct in6_addr));
+ syslog(LOG_INFO, "%s peer addd--------> add\n",
+ ip6_sprintf(&bul->bul_peeraddr));
+#ifdef MIP_IPSEC
+ if (ipsec_bul_request(bul, MIPM_BUL_ADD) < 0) {
+ struct mip6_hpfxl *hpfx;
+ struct mip6_mipif *mif;
+
+ mif = mnd_get_mipif(bul->bul_hoainfo->hinfo_ifindex);
+ LIST_FOREACH(hpfx,
+ &mif->mipif_hprefx_head,
+ hpfx_entry)
+ mip6_delete_hal(hpfx,
+ &bul->bul_peeraddr);
+ goto next;
+ }
+#endif /* MIP_IPSEC */
error = send_bu(bul);
if (error) {
syslog(LOG_ERR,
@@ -1804,7 +1848,8 @@ bul_reg_fsm(bul, event, data)
if (!LIST_EMPTY(&bul->bul_mcoa_head)) {
struct binding_update_list *mbul;
- for (mbul = LIST_FIRST(&bul->bul_mcoa_head); mbul;
+ for (mbul = LIST_FIRST(&bul->bul_mcoa_head);
+ mbul;
mbul = LIST_NEXT(mbul, bul_entry)) {
syslog(LOG_INFO, "found multiple BULISTS in kick_fsm");
@@ -1813,8 +1858,10 @@ bul_reg_fsm(bul, event, data)
MIP6_BUL_REG_FSM_STATE_DHAAD)
continue;
#endif
+ /* XXX needs IPsec on MCOA? */
memcpy(&mbul->bul_peeraddr,
- &hal->hal_ip6addr, sizeof(struct in6_addr));
+ &hal->hal_ip6addr,
+ sizeof(struct in6_addr));
error = send_bu(mbul);
if (error) {
syslog(LOG_ERR,
@@ -2520,19 +2567,28 @@ bul_fsm_back_register(bul, data)
#endif
}
+#ifdef MIP_IPSEC
+ if (bul->bul_ipsec_data == NULL &&
+ ipsec_bul_request(bul, MIPM_BUL_ADD | MIPM_BUL_AFTER_BA) < 0)
+ return (-1);
+#endif /* MIP_IPSEC */
/* inject binding information to kernel. */
if (mipsock_bul_request(bul, MIPM_BUL_ADD)) {
syslog(LOG_ERR,
"updating a binding update entry in a kernel failed.");
return (-1);
}
+#ifdef MIP_IPSEC
+ if (ipsec_bul_request(bul, MIPM_BUL_UPDATE | MIPM_BUL_AFTER_BA) < 0)
+ return (-1);
+#endif /* MIP_IPSEC */
#if TODO
/* notify all the CNs that we have a new coa. */
error = mip6_bu_list_notify_binding_change(sc, 0);
if (error) {
syslog(LOG_ERR,
- "updating the bining cache entries of all CNs failed.");
+ "updating the binding cache entries of all CNs failed.\n");
return (error);
}
#endif
@@ -2555,6 +2611,9 @@ bul_fsm_back_deregister(bul, data)
"removing IFF_DEREGISTERING flag failed.");
}
+#ifdef MIP_IPSEC
+ (void)ipsec_bul_request(bul, MIPM_BUL_REMOVE | MIPM_BUL_AFTER_BA);
+#endif /* MIP_IPSEC */
if (bul->bul_flags & IP6_MH_BU_HOME) {
/* send an unsolicited neighbor advertisement message. */
bul_send_unsolicited_na(bul);
@@ -2698,12 +2757,19 @@ bul_fsm_try_other_home_agent(bul)
struct mip6_mipif *mif;
int error;
+#ifdef MIP_IPSEC
+ next:
+#endif /* MIP_IPSEC */
/*
* remove the unavailable home agent from the home agent list.
*/
mif = mnd_get_mipif(bul->bul_hoainfo->hinfo_ifindex);
LIST_FOREACH(hpfx, &mif->mipif_hprefx_head, hpfx_entry) {
mip6_delete_hal(hpfx, &bul->bul_peeraddr);
+#ifdef MIP_IPSEC
+ (void) ipsec_bul_request(bul, MIPM_BUL_REMOVE);
+ bul->bul_peeraddr = in6addr_any;
+#endif /* MIP_IPSEC */
}
/*
@@ -2724,6 +2790,15 @@ bul_fsm_try_other_home_agent(bul)
syslog(LOG_ERR, "bul_peeraddr is set to %s",
ip6_sprintf(&bul->bul_peeraddr));
+#ifdef MIP_IPSEC
+ if (ipsec_bul_request(bul, MIPM_BUL_ADD) < 0) {
+ if (debug)
+ syslog(LOG_INFO,
+ "IPsec drops candidate HA %s\n",
+ ip6_sprintf(&bul->bul_peeraddr));
+ goto next;
+ }
+#endif /* MIP_IPSEC */
error = send_bu(bul);
if (error) {
syslog(LOG_ERR,
View
30 kame/kame/shisad/had.c
@@ -1,4 +1,4 @@
-/* $KAME: had.c,v 1.42 2007/02/06 05:58:52 t-momose Exp $ */
+/* $KAME: had.c,v 1.43 2007/02/27 01:44:12 keiichi Exp $ */
/*
* Copyright (C) 2004 WIDE Project.
@@ -166,10 +166,18 @@ main(argc, argv)
{
int pfds;
int ch = 0;
+#ifdef MIP_IPSEC
+ int fd;
+#endif /* MIP_IPSEC */
char *ifname;
FILE *pidfp;
char *conffile = HAD_CONFFILE;
+#ifdef MIP_IPSEC
+ char *ipsecconffile = IPSEC_CONFFILE;
+ char *options = "fnc:C:";
+#else
char *options = "fnc:";
+#endif /* MIP_IPSEC */
#if 0
/* XXX Is this code needed ? */
@@ -192,6 +200,11 @@ main(argc, argv)
case 'c':
conffile = optarg;
break;
+#ifdef MIP_IPSEC
+ case 'C':
+ ipsecconffile = optarg;
+ break;
+#endif /* MIP_IPSEC */
default:
fprintf(stderr, "unknown option\n");
ha_usage(argv[0]);
@@ -253,6 +266,10 @@ main(argc, argv)
mhsock_open();
icmp6sock_open();
mipsock_open();
+#ifdef MIP_IPSEC
+ if (use_ipsec() && ipsec_init(ipsecconffile) < 0)
+ fprintf(stderr, "IPsec initialization failed\n");
+#endif /* MIP_IPSEC */
#ifdef DSMIP
udp4sock_open();
raw4sock_open();
@@ -261,6 +278,12 @@ main(argc, argv)
new_fd_list(mipsock, POLLIN, mipsock_input_common);
new_fd_list(mhsock, POLLIN, mh_input_common);
new_fd_list(icmp6sock, POLLIN, icmp6_input_common);
+#ifdef MIP_IPSEC
+ if ((fd = sadb_socket()) >= 0)
+ new_fd_list(fd, POLLIN, sadb_poll);
+ if ((fd = spmif_socket()) >= 0)
+ new_fd_list(fd, POLLIN, spmif_poll);
+#endif /* MIP_IPSEC */
#ifdef DSMIP
new_fd_list(udp4sock, POLLIN, udp4_input_common);
#endif /* DSMIP */
@@ -421,7 +444,7 @@ had_init_homeprefix (ifname, preference)
(void)strncpy(ifreq6.ifr_name, ifname, strlen(ifname));
memcpy(&ifreq6.ifr_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len);
- if(ioctl(ioctl_s, SIOCGIFAFLAG_IN6, (caddr_t)&ifreq6) < 0) {
+ if (ioctl(ioctl_s, SIOCGIFAFLAG_IN6, (caddr_t)&ifreq6) < 0) {
close(ioctl_s);
continue;
}
@@ -578,6 +601,9 @@ had_flush_bc(s, line)
char *line;
{
command_printf(s, "-- Clear Binding Cache --\n");
+#ifdef IPsec
+ command_printf(s, "Can junk IPsec state?!\n");
+#endif
flush_bc();
/*mip6_flush_kernel_bc();*/
}
View
1,182 kame/kame/shisad/ipsec.c
@@ -0,0 +1,1182 @@
+/*
+ * ipsec.c: PF_KEY/SPMIF interface with racoon2 framework
+ * Francis.Dupont@fdupont.fr, August 2006
+ */
+
+#define IPSEC_BUL_AFTER_BA
+#undef IPSEC_BUL_IDASAP
+
+#ifdef MIP_IPSEC
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <signal.h>
+#include <stdarg.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/pfkeyv2.h>
+#ifndef SADB_X_MIGRATE
+#error "SADB_X_MIGRATE must be defined!"
+#endif
+
+#include <net/if.h>
+#ifdef __FreeBSD__
+#include <net/if_var.h>
+#endif
+#ifdef __NetBSD__
+#include <net/if_ether.h>
+#endif /* __NetBSD__ */
+#include <net/mipsock.h>
+#include <netinet/in.h>
+#include <netinet/ip6mh.h>
+#include <netinet/ip6.h>
+#include <netinet6/mip6.h>
+#include <netinet/icmp6.h>
+#include <arpa/inet.h>
+
+#include "callout.h"
+#include "stat.h"
+#include "shisad.h"
+#include "fsm.h"
+
+#define HAVE_STDARG_H 1
+#define HAVE_SA_LEN 1
+#define HAVE_FUNC_MACRO 1
+
+#include "racoon.h"
+
+#ifdef MIP_MN
+static int sadb_add_callback(struct rcpfk_msg *);
+#endif
+static int sadb_x_migrate_callback(struct rcpfk_msg *);
+
+#ifdef MIP_HA
+static int is_matching(struct rc_addrlist *, struct in6_addr *);
+static int bc_request_add(struct binding_cache *);
+static int bc_request_remove(struct binding_cache *);
+static int bc_request_update(struct binding_cache *);
+#endif
+#ifdef MIP_MN
+static int bul_request_add(struct binding_update_list *);
+static int bul_request_remove(struct binding_update_list *);
+static int bul_request_update(struct binding_update_list *);
+static int bul_requestaba_add(struct binding_update_list *);
+static int bul_requestaba_remove(struct binding_update_list *);
+static int bul_requestaba_update(struct binding_update_list *);
+#endif
+static void policy_add(struct rcf_selector *);
+static void policy_delete(struct rcf_selector *);
+static void migrate(struct rcf_selector *, struct in6_addr *,
+ struct in6_addr *);
+static int policy_add_callback(void *, int);
+static int policy_delete_callback(void *, int);
+static int migrate_callback(void *, int);
+
+static int sadbsock = 1; /* PF_KEY socket */
+static int spmifsock = 1; /* SPMIF socket */
+
+#ifdef MIP_HA
+LIST_HEAD(, ipsec_mn) ipsec_mn_head; /* IPsec MN info list */
+#endif
+#ifdef MIP_MN
+LIST_HEAD(, ipsec_ha) ipsec_ha_head; /* IPsec HA info list */
+#endif
+
+static struct rcpfk_cb rcpfk_callback = /* PF_KEY callbacks */
+{
+ 0, /* getspi */
+ 0, /* update */
+#ifdef MIP_MN
+ sadb_add_callback,
+#else
+ 0, /* add */
+#endif
+ 0, /* expire */
+ 0, /* acquire */
+ 0, /* delete */
+ 0, /* get */
+ 0, /* spdupdate */
+ 0, /* spdadd */
+ 0, /* spddelete */
+ 0, /* spddelete2 */
+ 0, /* spdexpire */
+ 0, /* spdget */
+ 0, /* spddump */
+ sadb_x_migrate_callback,
+};
+
+/* init */
+
+int
+ipsec_init(char *conffile)
+{
+ struct rcpfk_msg param;
+
+ if (rcf_read(conffile, 0) < 0) {
+ syslog(LOG_ERR, "can't parse ipsecconfigfile %s\n", conffile);
+ return -1;
+ }
+
+ param.flags = 0;
+ if (rcpfk_init(&param, &rcpfk_callback) != 0)
+ return -1;
+ sadbsock = param.so;
+ if (debug)
+ syslog(LOG_INFO, "sadbsock: %d\n", sadbsock);
+
+ spmifsock = spmif_init();
+ if (debug)
+ syslog(LOG_INFO, "spmifsock: %d\n", spmifsock);
+ if (spmifsock < 0)
+ return -1;
+
+#ifdef MIP_HA
+ LIST_INIT(&ipsec_mn_head);
+#endif
+#ifdef MIP_MN
+ LIST_INIT(&ipsec_ha_head);
+#endif
+
+ return 0;
+}
+
+/* fini */
+
+void
+ipsec_clean(void)
+{
+ struct rcpfk_msg param;
+
+ (void)spmif_post_quit(spmifsock);
+ spmif_clean(spmifsock);
+ spmifsock = -1;
+
+ bzero(&param, sizeof(param));
+ param.so = sadbsock;
+ (void) rcpfk_clean(&param);
+ sadbsock = -1;
+
+ (void) rcf_clean();
+}
+
+/* return the PF_KEY socket */
+
+int
+sadb_socket(void)
+{
+ return sadbsock;
+}
+
+/* return the SPMIF socket */
+
+int
+spmif_socket(void)
+{
+ return spmifsock;
+}
+
+/* some input available for PF_KEY */
+
+int
+sadb_poll(int fd)
+{
+ struct rcpfk_msg param;
+
+ if (fd != sadbsock) {
+ syslog(LOG_ERR, "sadb_poll on bad socket\n");
+ return -1;
+ }
+
+ bzero(&param, sizeof(param));
+ param.so = fd;
+#ifdef MIP_MN
+ param.flags = PFK_FLAG_SEEADD;
+#endif
+ if (rcpfk_handler(&param) != 0) {
+ syslog(LOG_ERR, "sadb_poll: %s\n",
+ param.eno ? param.estr : "unknown error");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* some input available for SPMIF */
+
+int
+spmif_poll(int fd)
+{
+ if (fd != spmifsock) {
+ syslog(LOG_ERR, "spmif_poll on bad socket\n");
+ return -1;
+ }
+ if (spmif_handler(fd) != 0) {
+ syslog(LOG_ERR, "spmd I/F broken: fatal!\n");
+ (void) kill(getpid(), SIGTERM);
+ }
+ return 0;
+}
+
+/* check keymanagement get sysctl variable net.inet6.mip6.use_ipsec */
+
+int
+use_ipsec(void)
+{
+ int mib[4], flag;
+ size_t len;
+ extern int keymanagement;
+
+ if (keymanagement == 0) {
+ if (debug)
+ syslog(LOG_INFO, "keymanagement is off\n");
+ return 0;
+ }
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET6;
+ mib[2] = IPPROTO_MH;
+ mib[3] = MIP6CTL_USE_IPSEC;
+
+ if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
+ syslog(LOG_ERR, "%s sysctl() %s",
+ __FUNCTION__, strerror(errno));
+ return 0;
+ }
+ if (len != sizeof(int)) {
+ syslog(LOG_ERR, "%s sysctl() bad length\n", __FUNCTION__);
+ return 0;
+ }
+ if (sysctl(mib, 4, &flag, &len, NULL, 0) < 0) {
+ syslog(LOG_ERR, "%s sysctl() %s",
+ __FUNCTION__, strerror(errno));
+ return 0;
+ }
+ if (len != sizeof(int)) {
+ syslog(LOG_ERR, "%s sysctl() bad length?\n", __FUNCTION__);
+ return 0;
+ }
+ if (flag == 0) {
+ if (debug)
+ syslog(LOG_INFO, "use_ipsec is off\n");
+ return 0;
+ }
+
+ mib[3] = MIP6CTL_USE_MIGRATE;
+
+ if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0) {
+ syslog(LOG_ERR, "%s sysctl() %s",
+ __FUNCTION__, strerror(errno));
+ return 0;
+ }
+ if (len != sizeof(int)) {
+ syslog(LOG_ERR, "%s sysctl() bad length\n", __FUNCTION__);
+ return 0;
+ }
+ if (sysctl(mib, 4, &flag, &len, NULL, 0) < 0) {
+ syslog(LOG_ERR, "%s sysctl() %s",
+ __FUNCTION__, strerror(errno));
+ return 0;
+ }
+ if (len != sizeof(int)) {
+ syslog(LOG_ERR, "%s sysctl() bad length?\n", __FUNCTION__);
+ return 0;
+ }
+ if (flag != 0) {
+ if (debug)
+ syslog(LOG_INFO, "use_migrate is on\n");
+ return 0;
+ }
+ return 1;
+}
+
+#ifdef MIP_MN
+
+/* callback function on SADB_ADD */
+
+static
+int sadb_add_callback(struct rcpfk_msg *rc)
+{
+ /*
+ * The idea is to look at if the new SA is for a pending HRBU
+ */
+ struct binding_update_list *bul;
+ struct in6_addr *sa, *da;
+
+ if (debug)
+ syslog(LOG_INFO, "see an ADD for SPI %d\n", rc->spi);
+
+ /* suitable IPsec SA? */
+ if (!rc || rc->satype != RCT_SATYPE_ESP ||
+ rc->samode == RCT_IPSM_TUNNEL ||
+ !rc->sa_src || rc->sa_src->sa_family != AF_INET6 ||
+ !rc->sa_dst || rc->sa_dst->sa_family != AF_INET6)
+ return 0;
+ sa = &((struct sockaddr_in6 *)rc->sa_src)->sin6_addr;
+ da = &((struct sockaddr_in6 *)rc->sa_src)->sin6_addr;
+
+ if (debug)
+ syslog(LOG_INFO, "SA from %s to %s\n",
+ ip6_sprintf(sa), ip6_sprintf(da));
+
+ /* get the HR BUL from the hoa */
+ bul = bul_get_homeflag(sa);
+ if (bul == NULL || !IN6_ARE_ADDR_EQUAL(da, &bul->bul_peeraddr))
+ return 0;
+
+ /* send the HR BU */
+ if (send_bu(bul) < 0)
+ return 0;
+
+ bul_set_retrans_timer(bul, bul->bul_retrans_time);
+ return 0;
+}
+#endif
+
+/* callback function on SADB_X_MIGRATE */
+
+static int
+sadb_x_migrate_callback(struct rcpfk_msg *rc)
+{
+ struct rcf_selector *s;
+ struct rcf_policy *p;
+ extern struct rcf_selector *rcf_selector_head;
+
+ if (rc->sa_src->sa_family != AF_INET6 ||
+ rc->sa_dst->sa_family != AF_INET6)
+ return 0;
+
+ if ((rcs_cmpsa(rc->sa_src, rc->sa2_src) == 0) &&
+ (rcs_cmpsa(rc->sa_dst, rc->sa2_dst) == 0))
+ return 0;
+
+ /* migrate the primary selector */
+
+ for (s = rcf_selector_head; s; s = s->next) {
+ if (rc->dir != s->direction)
+ continue;
+ /* XXX match only on the reqid! */
+ if (rc->reqid != s->reqid)
+ continue;
+ p = s->pl;
+ if (p == NULL)
+ continue;
+ if (p->my_sa_ipaddr == NULL ||
+ p->my_sa_ipaddr->type != RCT_ADDR_INET)
+ continue;
+ if (p->peers_sa_ipaddr == NULL ||
+ p->peers_sa_ipaddr->type != RCT_ADDR_INET)
+ continue;
+
+ bcopy(&((struct sockaddr_in6 *)rc->sa2_src)->sin6_addr,
+ &((struct sockaddr_in6 *)p->my_sa_ipaddr->a.ipaddr)->sin6_addr,
+ sizeof(struct in6_addr));
+ bcopy(&((struct sockaddr_in6 *)rc->sa2_dst)->sin6_addr,
+ &((struct sockaddr_in6 *)p->peers_sa_ipaddr->a.ipaddr)->sin6_addr,
+ sizeof(struct in6_addr));
+ if (debug)
+ syslog(LOG_INFO,
+ "move selector(%.*s)\n",
+ (int)s->sl_index->l,
+ s->sl_index->v);
+ }
+ return 0;
+}
+
+/* check if an address list matches */
+
+static int
+is_matching(struct rc_addrlist *al, struct in6_addr *addr)
+{
+ struct sockaddr_in6 *sin6;
+
+ if (al->type != RCT_ADDR_INET)
+ return 0;
+ if (al->a.ipaddr->sa_family != AF_INET6)
+ return 0;
+ if (al->prefixlen && al->prefixlen != 128)
+ return 0;
+ sin6 = (struct sockaddr_in6 *)al->a.ipaddr;
+ return IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, addr);
+}
+
+#ifdef MIP_HA
+
+struct ipsec_mn { /* MN related infos */
+ LIST_ENTRY(ipsec_mn) chain; /* chaining */
+ struct rcf_remote *rm_info; /* remote entry */
+ struct rcf_selector *sl_out, *sl_in; /* tunnel selectors */
+ struct binding_cache *back; /* back pointer */
+};
+
+/* IPsec BC/MN request */
+
+int
+ipsec_bc_request(struct binding_cache *bc, int command)
+{
+ switch (command) {
+ case MIPM_BC_ADD:
+ return bc_request_add(bc);
+ case MIPM_BC_UPDATE:
+ return bc_request_update(bc);
+ case MIPM_BC_REMOVE:
+ return bc_request_remove(bc);
+ case MIPM_BC_FLUSH:
+ default:
+ syslog(LOG_ERR, "bad ipsec_bc_request command %d\n", command);
+ return -1;
+ }
+}
+
+/* release IPsec related infos for a MN */
+
+void
+ipsec_bc_data_release(struct binding_cache *bc)
+{
+ struct ipsec_mn *mn;
+
+ mn = (struct ipsec_mn *)bc->bc_ipsec_data;
+ if (mn == NULL)
+ return;
+
+ if (debug)
+ syslog(LOG_INFO, "dangling IPsec for %s\n",
+ ip6_sprintf(&bc->bc_hoa));
+ if (mn->rm_info)
+ rcf_free_remote(mn->rm_info);
+ if (mn->sl_out)
+ rcf_free_selector(mn->sl_out);
+ if (mn->sl_in)
+ rcf_free_selector(mn->sl_in);
+ LIST_REMOVE(mn, chain);
+ bc->bc_ipsec_data = NULL;
+ free(mn);
+}
+
+/* get IPsec stuff for an incoming MN */
+
+static int
+bc_request_add(struct binding_cache *bc)
+{
+ struct ipsec_mn *mn;
+ struct rcf_selector *s, *s_next;
+
+ /* deal only with home registration */
+ if ((bc->bc_flags & IP6_MH_BU_HOME) == 0)
+ return 0;
+ /* XXX not yet MR */
+ if (bc->bc_flags & IP6_MH_BU_ROUTER)
+ return 0;
+#ifdef MIP_MCOA
+ /* XXX not yet MCOA (if there is something to do) */
+ if (bc->bc_bid)
+ return 0;
+#endif
+ /* XXX is it critical? */
+ if (debug && (bc->bc_flags & IP6_MH_BU_KEYM) == 0)
+ syslog(LOG_INFO, "%s HRBU has no K flag\n",
+ ip6_sprintf(&bc->bc_hoa));
+ /* only primary */
+ if (IN6_IS_ADDR_LINKLOCAL(&bc->bc_hoa))
+ return 0;
+
+ /* get the ipsec_mn structure */
+ mn = (struct ipsec_mn *)bc->bc_ipsec_data;
+ if (mn != NULL)
+ return 0;
+ mn = (struct ipsec_mn *)malloc(sizeof(*mn));
+ if (mn == NULL) {
+ syslog(LOG_ERR, "failed to allocate ipsec_mn\n");
+ return -1;
+ }
+ bzero(mn, sizeof(*mn));
+
+ /* get the outbound selector */
+ if (rcf_get_selectorlist(&s)) {
+ syslog(LOG_ERR, "can't get selector list\n");
+ goto bad;
+ }
+ for (; s; s_next = s->next, rcf_free_selector(s), s = s_next) {
+ if (mn->sl_out)
+ continue;
+ if (s->src == NULL || s->dst == NULL)
+ continue;
+ if (s->pl == NULL || s->pl->ips == NULL)
+ continue;
+ if (s->direction != RCT_DIR_OUTBOUND)
+ continue;
+ if (s->reqid == 0 || s->tagged)
+ continue;
+ if (s->pl->action != RCT_ACT_AUTO_IPSEC ||
+ s->pl->ipsec_mode != RCT_IPSM_TUNNEL ||
+ s->pl->ipsec_level != RCT_IPSL_UNIQUE)
+ continue;
+ if (s->pl->my_sa_ipaddr == NULL ||
+ s->pl->peers_sa_ipaddr == NULL)
+ continue;
+ if (s->upper_layer_protocol != IPPROTO_MH &&
+ s->upper_layer_protocol != RC_PROTO_ANY)
+ continue;
+ if (is_matching(s->src, &bc->bc_myaddr) &&
+ is_matching(s->dst, &bc->bc_hoa))
+ mn->sl_out = s;
+ }
+ if (mn->sl_out == NULL) {
+ if (debug)
+ syslog(LOG_INFO,
+ "can't get selector for %s\n",
+ ip6_sprintf(&bc->bc_hoa));
+ goto bad;
+ }
+
+ /* get the inbound selector */
+ if (rcf_get_rvrs_selector(mn->sl_out, &mn->sl_in)) {
+ if (debug)
+ syslog(LOG_INFO,
+ "can't get inbound selector for %s\n",
+ ip6_sprintf(&bc->bc_hoa));
+ goto bad;
+ }
+
+ /* get the remote entry */
+ if (rcf_get_remotebyindex(mn->sl_out->pl->rm_index, &mn->rm_info)) {
+ if (debug)
+ syslog(LOG_INFO,
+ "can't find remote for %s\n",
+ ip6_sprintf(&bc->bc_hoa));
+ goto bad;
+ }
+
+ /* check the remote entry */
+ if (mn->rm_info->ikev1 &&
+ mn->rm_info->ikev1->mobility_role == RCT_MOB_MN)
+ ;
+ else if (mn->rm_info->ikev2 &&
+ mn->rm_info->ikev2->mobility_role == RCT_MOB_MN)
+ ;
+ else if (mn->rm_info->kink &&
+ mn->rm_info->kink->mobility_role == RCT_MOB_MN)
+ ;
+ else {
+ if (debug)
+ syslog(LOG_INFO,
+ "%s remote is not for a MN\n",
+ ip6_sprintf(&bc->bc_hoa));
+ goto bad;
+ }
+
+ /* perform side effects */
+ LIST_INSERT_HEAD(&ipsec_mn_head, mn, chain);
+ bc->bc_ipsec_data = mn;
+ mn->back = bc;
+ if (mn->sl_out->pl->install == RCT_BOOL_OFF)
+ policy_add(mn->sl_out);
+
+ return 0;
+
+ bad:
+ if (mn->rm_info)
+ rcf_free_remote(mn->rm_info);
+ if (mn->sl_out)
+ rcf_free_selector(mn->sl_out);
+ if (mn->sl_in)
+ rcf_free_selector(mn->sl_in);
+ LIST_REMOVE(mn, chain);
+ bc->bc_ipsec_data = NULL;
+ free(mn);
+ return -1;
+}
+
+/* remove IPsec stuff for a leaving MN */
+
+static int
+bc_request_remove(struct binding_cache *bc)
+{
+ struct ipsec_mn *mn;
+ struct rcf_selector *s;
+
+ mn = (struct ipsec_mn *)bc->bc_ipsec_data;
+ if (mn == NULL)
+ return 0;
+
+ /* reget selectors */
+ if (rcf_get_selector(vmem2str(mn->sl_out->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)mn->sl_out->sl_index->l,
+ mn->sl_out->sl_index->v);
+ goto del;
+ }
+ rcf_free_selector(mn->sl_out);
+ mn->sl_out = s;
+ if (rcf_get_selector(vmem2str(mn->sl_in->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)mn->sl_in->sl_index->l,
+ mn->sl_in->sl_index->v);
+ goto del;
+ }
+ rcf_free_selector(mn->sl_in);
+ mn->sl_in = s;
+
+ /* migrate to home */
+ migrate(mn->sl_out, &bc->bc_myaddr, &bc->bc_hoa);
+ migrate(mn->sl_in, &bc->bc_hoa, &bc->bc_myaddr);
+
+ del:
+ if (mn->sl_out->pl->install == RCT_BOOL_OFF) {
+ policy_delete(mn->sl_out);
+ policy_delete(mn->sl_in);
+ }
+ rcf_free_remote(mn->rm_info);
+ rcf_free_selector(mn->sl_out);
+ rcf_free_selector(mn->sl_in);
+ LIST_REMOVE(mn, chain);
+ bc->bc_ipsec_data = NULL;
+ free(mn);
+ return 0;
+}
+
+/* update IPsec stuff for a moving MN */
+
+static int
+bc_request_update(struct binding_cache *bc)
+{
+ struct ipsec_mn *mn;
+ struct rcf_selector *s;
+
+ mn = (struct ipsec_mn *)bc->bc_ipsec_data;
+ if (mn == NULL)
+ return 0;
+
+ /* reget selectors */
+ if (rcf_get_selector(vmem2str(mn->sl_out->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)mn->sl_out->sl_index->l,
+ mn->sl_out->sl_index->v);
+ return -1;
+ }
+ rcf_free_selector(mn->sl_out);
+ mn->sl_out = s;
+ if (rcf_get_selector(vmem2str(mn->sl_in->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)mn->sl_in->sl_index->l,
+ mn->sl_in->sl_index->v);
+ return -1;
+ }
+ rcf_free_selector(mn->sl_in);
+ mn->sl_in = s;
+
+ /* migrate */
+ migrate(mn->sl_out, &bc->bc_myaddr, &bc->bc_coa);
+ migrate(mn->sl_in, &bc->bc_coa, &bc->bc_myaddr);
+
+ return 0;
+}
+
+#endif
+
+#ifdef MIP_MN
+
+struct ipsec_ha { /* HA related infos */
+ LIST_ENTRY(ipsec_ha) chain; /* chaining */
+ struct rcf_remote *rm_info; /* remote entry */
+ struct rcf_selector *sl_out, *sl_in; /* tunnel selectors */
+ struct binding_update_list *back; /* back pointer */
+};
+
+/* IPsec BUL/HA request */
+
+int
+ipsec_bul_request(struct binding_update_list *bul, int command)
+{
+ switch (command) {
+ case MIPM_BUL_ADD:
+ return bul_request_add(bul);
+ case MIPM_BUL_UPDATE:
+ return bul_request_update(bul);
+ case MIPM_BUL_REMOVE:
+ return bul_request_remove(bul);
+ case MIPM_BUL_ADD | MIPM_BUL_AFTER_BA:
+ return bul_requestaba_add(bul);
+ case MIPM_BUL_UPDATE | MIPM_BUL_AFTER_BA:
+ return bul_requestaba_update(bul);
+ case MIPM_BUL_REMOVE | MIPM_BUL_AFTER_BA:
+ return bul_requestaba_remove(bul);
+ case MIPM_BUL_FLUSH:
+ case MIPM_BUL_FLUSH | MIPM_BUL_AFTER_BA:
+ default:
+ syslog(LOG_ERR, "bad ipsec_bul_request command %x\n", command);
+ return -1;
+ }
+}
+
+/* release IPsec related infos for an HA */
+
+void
+ipsec_bul_data_release(struct binding_update_list *bul)
+{
+ struct ipsec_ha *ha;
+
+ ha = (struct ipsec_ha *)bul->bul_ipsec_data;
+ if (ha == NULL)
+ return;
+
+ syslog(LOG_INFO, "dangling IPsec for %s\n",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ if (ha->rm_info)
+ rcf_free_remote(ha->rm_info);
+ if (ha->sl_out)
+ rcf_free_selector(ha->sl_out);
+ if (ha->sl_in)
+ rcf_free_selector(ha->sl_in);
+ LIST_REMOVE(ha, chain);
+ bul->bul_ipsec_data = NULL;
+ free(ha);
+}
+
+/* get IPsec stuff for a new HA */
+
+static int
+#ifdef IPSEC_BUL_AFTER_BA
+bul_request_add(struct binding_update_list *bul)
+#endif
+#ifdef IPSEC_BUL_IDASAP
+bul_requestaba_add(struct binding_update_list *bul)
+#endif
+{
+ return 0;
+}
+
+static int
+#ifdef IPSEC_BUL_AFTER_BA
+bul_requestaba_add(struct binding_update_list *bul)
+#endif
+#ifdef IPSEC_BUL_IDASAP
+bul_request_add(struct binding_update_list *bul)
+#endif
+{
+ struct ipsec_ha *ha;
+ struct rcf_selector *s, *s_next;
+
+ /* deal only with HAs */
+ if ((bul->bul_flags & IP6_MH_BU_HOME) == 0)
+ return 0;
+ /* XXX not yet MR */
+ if (bul->bul_flags & IP6_MH_BU_ROUTER)
+ return 0;
+#ifdef MIP_MCOA
+ /* XXX not yet MCOA (if there is something to do) */
+ if (bul->bul_bid)
+ return 0;
+#endif
+ if (bul->bul_hoainfo == NULL) {
+ syslog(LOG_ERR, "bul without hoainfo?!\n");
+ return -1;
+ }
+ /* XXX is it critical? */
+ if (debug && (bul->bul_flags & IP6_MH_BU_KEYM) == 0)
+ syslog(LOG_INFO, "%s HRBU has no K flag\n",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+
+ /* get the ipsec_ha structure */
+ ha = (struct ipsec_ha *)bul->bul_ipsec_data;
+ if (ha != NULL)
+ return 0;
+ ha = (struct ipsec_ha *)malloc(sizeof(*ha));
+ if (ha == NULL) {
+ syslog(LOG_ERR, "failed to allocate ipsec_ha\n");
+ return -1;
+ }
+ bzero(ha, sizeof(*ha));
+
+ /* get the outbound selector */
+ if (rcf_get_selectorlist(&s)) {
+ syslog(LOG_ERR, "can't get selector list\n");
+ goto bad;
+ }
+ for (; s; s_next = s->next, rcf_free_selector(s), s = s_next) {
+ if (ha->sl_out)
+ continue;
+ if (s->src == NULL || s->dst == NULL)
+ continue;
+ if (s->pl == NULL || s->pl->ips == NULL)
+ continue;
+ if (s->direction != RCT_DIR_OUTBOUND)
+ continue;
+ if (s->reqid == 0 || s->tagged)
+ continue;
+ if (s->pl->action != RCT_ACT_AUTO_IPSEC ||
+ s->pl->ipsec_mode != RCT_IPSM_TUNNEL ||
+ s->pl->ipsec_level != RCT_IPSL_UNIQUE)
+ continue;
+ if (s->pl->my_sa_ipaddr == NULL ||
+ s->pl->peers_sa_ipaddr == NULL)
+ continue;
+ if (s->upper_layer_protocol != IPPROTO_MH &&
+ s->upper_layer_protocol != RC_PROTO_ANY)
+ continue;
+ if (is_matching(s->src, &bul->bul_hoainfo->hinfo_hoa) &&
+ is_matching(s->dst, &bul->bul_peeraddr))
+ ha->sl_out = s;
+ }
+ if (ha->sl_out == NULL) {
+ if (debug)
+ syslog(LOG_INFO,
+ "can't get selector for %s\n",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ goto bad;
+ }
+
+ /* get the inbound selector */
+ if (rcf_get_rvrs_selector(ha->sl_out, &ha->sl_in)) {
+ if (debug)
+ syslog(LOG_INFO,
+ "can't get inbound selector for %s\n",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ goto bad;
+ }
+
+ /* get the remote entry */
+ if (rcf_get_remotebyindex(ha->sl_out->pl->rm_index, &ha->rm_info)) {
+ if (debug)
+ syslog(LOG_INFO,
+ "can't find remote for %s\n",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ goto bad;
+ }
+
+ /* check the remote entry */
+ if (ha->rm_info->ikev1 &&
+ ha->rm_info->ikev1->mobility_role == RCT_MOB_HA)
+ ;
+ else if (ha->rm_info->ikev2 &&
+ ha->rm_info->ikev2->mobility_role == RCT_MOB_HA)
+ ;
+ else if (ha->rm_info->kink &&
+ ha->rm_info->kink->mobility_role == RCT_MOB_HA)
+ ;
+ else {
+ if (debug)
+ syslog(LOG_INFO,
+ "%s remote is not for an HA\n",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ goto bad;
+ }
+
+ /* perform side effects */
+ LIST_INSERT_HEAD(&ipsec_ha_head, ha, chain);
+ bul->bul_ipsec_data = ha;
+ ha->back = bul;
+ if (ha->sl_out->pl->install == RCT_BOOL_OFF)
+ policy_add(ha->sl_out);
+
+ return 0;
+
+ bad:
+ if (ha->rm_info)
+ rcf_free_remote(ha->rm_info);
+ if (ha->sl_out)
+ rcf_free_selector(ha->sl_out);
+ if (ha->sl_in)
+ rcf_free_selector(ha->sl_in);
+ LIST_REMOVE(ha, chain);
+ bul->bul_ipsec_data = NULL;
+ free(ha);
+ return -1;
+}
+
+/* remove IPsec stuff for an unavailable HA */
+
+static int
+#ifdef IPSEC_BUL_AFTER_BA
+bul_request_remove(struct binding_update_list *bul)
+#endif
+#ifdef IPSEC_BUL_IDASAP
+bul_requestaba_remove(struct binding_update_list *bul)
+#endif
+{
+ return 0;
+}
+
+static int
+#ifdef IPSEC_BUL_AFTER_BA
+bul_requestaba_remove(struct binding_update_list *bul)
+#endif
+#ifdef IPSEC_BUL_IDASAP
+bul_request_remove(struct binding_update_list *bul)
+#endif
+{
+ struct ipsec_ha *ha;
+ struct rcf_selector *s;
+
+ ha = (struct ipsec_ha *)bul->bul_ipsec_data;
+ if (ha == NULL)
+ return 0;
+
+ /* reget selectors */
+ if (rcf_get_selector(vmem2str(ha->sl_out->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)ha->sl_out->sl_index->l,
+ ha->sl_out->sl_index->v);
+ goto del;
+ }
+ rcf_free_selector(ha->sl_out);
+ ha->sl_out = s;
+ if (rcf_get_selector(vmem2str(ha->sl_in->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)ha->sl_in->sl_index->l,
+ ha->sl_in->sl_index->v);
+ goto del;
+ }
+ rcf_free_selector(ha->sl_in);
+ ha->sl_in = s;
+
+ /* migrate to home */
+ migrate(ha->sl_out, &bul->bul_hoainfo->hinfo_hoa, &bul->bul_peeraddr);
+ migrate(ha->sl_in, &bul->bul_peeraddr, &bul->bul_hoainfo->hinfo_hoa);
+
+ del:
+ if (ha->sl_out->pl->install == RCT_BOOL_OFF) {
+ policy_delete(ha->sl_out);
+ policy_delete(ha->sl_in);
+ }
+ rcf_free_remote(ha->rm_info);
+ rcf_free_selector(ha->sl_out);
+ rcf_free_selector(ha->sl_in);
+ LIST_REMOVE(ha, chain);
+ bul->bul_ipsec_data = NULL;
+ free(ha);
+ return 0;
+}
+
+/* update IPsec stuff for an HA after a movement */
+
+static int
+#ifdef IPSEC_BUL_AFTER_BA
+bul_request_update(struct binding_update_list *bul)
+#endif
+#ifdef IPSEC_BUL_IDASAP
+bul_requestaba_update(struct binding_update_list *bul)
+#endif
+{
+ return 0;
+}
+
+static int
+#ifdef IPSEC_BUL_AFTER_BA
+bul_requestaba_update(struct binding_update_list *bul)
+#endif
+#ifdef IPSEC_BUL_IDASAP
+bul_request_update(struct binding_update_list *bul)
+#endif
+{
+ struct ipsec_ha *ha;
+ struct rcf_selector *s;
+
+ ha = (struct ipsec_ha *)bul->bul_ipsec_data;
+ if (ha == NULL)
+ return 0;
+
+ /* reget selectors */
+ if (rcf_get_selector(vmem2str(ha->sl_out->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)ha->sl_out->sl_index->l,
+ ha->sl_out->sl_index->v);
+ return -1;
+ }
+ rcf_free_selector(ha->sl_out);
+ ha->sl_out = s;
+ if (rcf_get_selector(vmem2str(ha->sl_in->sl_index), &s) < 0) {
+ syslog(LOG_ERR, "Can't reget my selector %.*s\n",
+ (int)ha->sl_in->sl_index->l,
+ ha->sl_in->sl_index->v);
+ return -1;
+ }
+ rcf_free_selector(ha->sl_in);
+ ha->sl_in = s;
+
+ /* migrate */
+ migrate(ha->sl_out, &bul->bul_coa, &bul->bul_peeraddr);
+ migrate(ha->sl_in, &bul->bul_peeraddr, &bul->bul_coa);
+
+ return 0;
+}
+
+/* check if IPsec is usable for a correspondent */
+
+int
+bul_can_use_ipsec(struct binding_update_list *bul)
+{
+ struct rcf_selector *s;
+ struct rcf_remote *r;
+ extern struct rcf_selector *rcf_selector_head;
+
+ /* already checked */
+ if (bul->bul_state & MIP6_BUL_STATE_USEIPSEC)
+ return 1;
+
+ /* XXX not yet MR */
+ if (bul->bul_flags & IP6_MH_BU_ROUTER)
+ return 0;
+#ifdef MIP_MCOA
+ /* XXX not yet MCOA (if there is something to do) */
+ if (bul->bul_bid)
+ return 0;
+#endif
+ if (bul->bul_hoainfo == NULL)
+ return 0;
+
+ /* get the outbound selector */
+ for (s = rcf_selector_head; s; s = s->next) {
+ if (s->src == NULL || s->dst == NULL)
+ continue;
+ if (s->pl == NULL || s->pl->ips == NULL)
+ continue;
+ if (s->direction != RCT_DIR_OUTBOUND)
+ continue;
+ if (s->tagged)
+ continue;
+ if (s->pl->install != RCT_BOOL_ON &&
+ (bul->bul_flags & IP6_MH_BU_HOME) == 0)
+ continue; /* XXX parano */
+ if (s->pl->action != RCT_ACT_AUTO_IPSEC ||
+ s->pl->ipsec_mode != RCT_IPSM_TRANSPORT)
+ continue;
+ if (s->upper_layer_protocol != IPPROTO_MH &&
+ ((bul->bul_flags & IP6_MH_BU_HOME) ||
+ s->upper_layer_protocol != RC_PROTO_ANY))
+ continue;
+ if (is_matching(s->src, &bul->bul_hoainfo->hinfo_hoa) &&
+ is_matching(s->dst, &bul->bul_peeraddr))
+ break;
+ }
+ if (s == NULL)
+ return 0;
+ if (rcf_get_remotebyindex(s->pl->rm_index, &r))
+ return 0;
+ if (r->ikev1 &&
+ (r->ikev1->mobility_role == RCT_MOB_CN ||
+ r->ikev1->mobility_role == RCT_MOB_HA))
+ ;
+ else if (r->ikev2 &&
+ (r->ikev2->mobility_role == RCT_MOB_CN ||
+ r->ikev2->mobility_role == RCT_MOB_HA))
+ ;
+ else if (r->kink &&
+ (r->kink->mobility_role == RCT_MOB_CN ||
+ r->kink->mobility_role == RCT_MOB_HA))
+ ;
+ else {
+ rcf_free_remote(r);
+ return 0;
+ }
+ rcf_free_remote(r);
+
+#if 0
+ bul->bul_state |= MIP6_BUL_STATE_USEIPSEC;
+#endif
+ return 1;
+}
+
+#endif
+
+/* add policies */
+
+static void
+policy_add(struct rcf_selector *s)
+{
+ (void) spmif_post_policy_add(spmifsock,
+ policy_add_callback,
+ s,
+ s->sl_index,
+ 0L,
+ RCT_IPSM_TUNNEL,
+ s->src->a.ipaddr,
+ s->dst->a.ipaddr,
+ s->pl->my_sa_ipaddr->a.ipaddr,
+ s->pl->peers_sa_ipaddr->a.ipaddr);
+}
+
+/* delete a policy */
+
+static void
+policy_delete(struct rcf_selector *s)
+{
+ (void) spmif_post_policy_delete(spmifsock,
+ policy_delete_callback,
+ s,
+ s->sl_index);
+}
+
+static void
+migrate(struct rcf_selector *s, struct in6_addr *sa, struct in6_addr *da)
+{
+ struct sockaddr_in6 nsrc, ndst;
+
+ bzero(&nsrc, sizeof(nsrc));
+ nsrc.sin6_family = AF_INET6;
+ nsrc.sin6_len = sizeof(nsrc);
+ bcopy(sa, &nsrc.sin6_addr, sizeof(*sa));
+ bzero(&ndst, sizeof(ndst));
+ ndst.sin6_family = AF_INET6;
+ ndst.sin6_len = sizeof(ndst);
+ bcopy(da, &ndst.sin6_addr, sizeof(*da));
+
+ (void) spmif_post_migrate(spmifsock,
+ migrate_callback,
+ s,
+ s->sl_index,
+ s->pl->my_sa_ipaddr->a.ipaddr,
+ s->pl->peers_sa_ipaddr->a.ipaddr,
+ (struct sockaddr *)&nsrc,
+ (struct sockaddr *)&ndst);
+}
+
+/* policy_add callback */
+
+static int
+policy_add_callback(void *tag, int result)
+{
+ struct rcf_selector *s = (struct rcf_selector *)tag;
+
+ if (result < 0 && debug)
+ syslog(LOG_INFO,
+ "policy add failed for selector %.*s\n",
+ (int)s->sl_index->l, s->sl_index->v);
+ return result;
+}
+
+/* policy_delete callback */
+
+static int
+policy_delete_callback(void *tag, int result)
+{
+ struct rcf_selector *s = (struct rcf_selector *)tag;
+
+ if (result < 0 && debug)
+ syslog(LOG_INFO,
+ "policy delete failed for selector %.*s\n",
+ (int)s->sl_index->l, s->sl_index->v);
+ return result;
+}
+
+/* migrate callback */
+
+static int
+migrate_callback(void *tag, int result)
+{
+ struct rcf_selector *s = (struct rcf_selector *)tag;
+
+ if (result < 0 && debug)
+ syslog(LOG_INFO,
+ "x_migrate failed for selector %.*s\n",
+ (int)s->sl_index->l, s->sl_index->v);
+ return result;
+}
+
+#endif
View
69 kame/kame/shisad/ipsec.txt
@@ -0,0 +1,69 @@
+Code comes from the racoon1 (today ipsec-tools) support for exprimental
+shisa (i.e., before it was integrated in the KAME distrib).
+I don't put the MN-CN support because it needs FSM adaptation
+and should conflict with current work on alternative authentication.
+
+Functions are:
+ - int ipsec_int(char *ipsecconffile): read the conf file (racoon2.conf)
+ and open two sockets, one for sadb (aka PF_KEY), the other for spmif
+ (aka interface to SPMD).
+ - void ipsec_clean(void): close sockets, cleanup.
+ - int sadb_socket(void) and int spmif_socket(void): return the file
+ descriptors to make select/poll on them.
+ - int sadb_poll(int fd) and int spmif_poll(int fd): service functions to
+ be called when input is available. The argument is only for compaitbility.
+ - int use_ipsec(void): check if the system context has IPsec support
+ (keymanagement on, net.inet6.mip6.use_ipsec on and use_migrate off).
+ - int ipsec_bc_request(struct binding_cache *bc, int command): add, update
+ and remove the IPsec infos (tunnel SPD and remote) related to a MN.
+ Use on an HA.
+ - void ipsec_bc_data_release(struct binding_cache *bc): delete cached info,
+ to be called before releasing a BC entry to avoid memory leaks.
+ - int ipsec_bul_request(struct binding_update_list *bul, int command):
+ same then ipsec_bc_request() but deals with HAs on a MN.
+ There are two places to call it, current code is compatible the
+ existing implementation but not compliant with Sugimoto's I-D.
+ - void ipsec_bul_data_release(struct binding_update_list *bul):
+ same than ipsec_bc_data_release().
+ - int bul_can_use_ipsec(struct binding_update_list *bul):
+ unused function from the MN-CN IPsec old code, check if a correspondent
+ can get BUs to it protected by IPsec. Should work with HAs too
+ even one relies on config for this (:-).
+
+Racoon2 details:
+ - the tunnel SPD must be auto_ipsec tunnel unique with a reqid,
+ SA src and dst. Traffic selectors must be simple addresses for
+ protocol MH/135 or any, initialized to home address and home agent
+ address. When they are marked dynamic (i.e., install off) add and
+ delete use spmif create and remove them.
+ - the linked required remote entry must have the right mobility role
+ (MN for BCs, HA for BULs).
+ - KINK has no support for migrate,
+ - IMHO the HA should be always passive but it is not checked.
+ - default policy (i.e., when the tunnel is off) for HoTi/HoT should
+ be very restrictive: it is safer even it could kill MN-MN RO.
+
+Other mobility protocols:
+ - K flag is still a problem when it is not set (i.e., possible
+ interop issue: what to do?)
+ - NEMO (flag router in BUs) is not supported
+ - MCOA (bid != 0) is not supported
+ - MN-CN is not support but I had it in my old code and I have copied
+ the main part into bul_can_use_ipsec(). The kernel has to
+ be updated too to accept (mark as verified) IPsec protected HoAs
+ - of course there is nothing particular for FMIP...
+
+Integration details:
+ - the IPsec code is protected by IPSEC ifdefs for the MN and HA parts
+ (nothing yet for the CN).
+ - as the racoon2 library includes a parser yacc and lex have to by
+ prefixed by -p/-P in obj/{had,mnd}/Makefile.in.
+ - as the previous fix leaves a yy* symbol, a sed translates it...
+ - configure stuff (I have no autoconf on my working box and no really
+ working autoconf on others) must be updated to compute the
+ racoon2 path for related Makefiles.
+ - the IPSEC CFLAG should be configurable.
+ - stdarg.h should be added in AC_CHECK_HEADERS.
+ - HAVE_SA_LEN can be computed or simply left as 1 (no Linux here...).
+ - HAVE_FUNC_MACRO stuff should be imported from iked/configure.in.
+ - don't forget OS specific Makefiles (used as alternatives to configure).
View
307 kame/kame/shisad/mh.c
@@ -1,4 +1,4 @@
-/* $KAME: mh.c,v 1.61 2007/02/19 08:13:04 t-momose Exp $ */
+/* $KAME: mh.c,v 1.62 2007/02/27 01:44:12 keiichi Exp $ */
/*
* Copyright (C) 2004 WIDE Project. All rights reserved.
*
@@ -278,7 +278,8 @@ mh_input_common(fd)
mip6stat.mip6s_hao++;
memcpy(&hoa, hoaopt->ip6oh_addr, sizeof(hoa));
} else {
- /* Shisa Statistics: unverified Home Address Option */
+ /* Shisa Statistics:
+ unverified Home Address Option */
mip6stat.mip6s_unverifiedhao++;
}
}
@@ -292,7 +293,8 @@ mh_input_common(fd)
/* Shisa Statistics: Routing Header type 2 */
mip6stat.mip6s_rthdr2++;
- memcpy(&rtaddr, (rthdr2 + 1),sizeof(struct in6_addr));
+ memcpy(&rtaddr, rthdr2 + 1,
+ sizeof(struct in6_addr));
rthdr_on = 1;
}
}
@@ -319,7 +321,8 @@ mh_input_common(fd)
int mhtype;
if ((mhtype = mh->ip6mh_type) > IP6_MH_TYPE_MAX)
- mhtype = IP6_MH_TYPE_MAX + 1; /* '+1' is for 'unknown mh type' message */
+ /* '+ 1' is for 'unknown mh type' message */
+ mhtype = IP6_MH_TYPE_MAX + 1;
syslog(LOG_INFO, "%s is received", mh_name[mhtype]);
syslog(LOG_INFO, " from:[%s] -> dst:[%s]",
ip6_sprintf(&from.sin6_addr), ip6_sprintf(&dst));
@@ -368,11 +371,13 @@ get_mobility_options(ip6mh, hlen, ip6mhlen, mopt)
while (mhopt < mhend) {
if (debug) {
syslog(LOG_INFO, " %s is found",
- mhopt_name[(*mhopt <= IP6_MHOPT_MAX) ? *mhopt : IP6_MHOPT_MAX + 1]);
+ mhopt_name[(*mhopt <= IP6_MHOPT_MAX) ?
+ *mhopt : IP6_MHOPT_MAX + 1]);
}
#ifdef MIP_CN
- if (*mhopt != IP6_MHOPT_BAUTH) /* Always bind. auth. opt. should be the last option */
+ if (*mhopt != IP6_MHOPT_BAUTH)
+ /* Always bind. auth. opt. should be the last option */
check_bauth_last();
#endif /* MIP_CN */
@@ -421,7 +426,8 @@ get_mobility_options(ip6mh, hlen, ip6mhlen, mopt)
break;
case IP6_MHOPT_AUTH_OPT:
- switch (((struct ip6_mh_opt_authentication *)mhopt)->ip6moauth_subtype) {
+ switch (((struct ip6_mh_opt_authentication *)mhopt)
+ ->ip6moauth_subtype) {
case IP6_MH_AUTHOPT_SUBTYPE_MNHA:
mopt->mnha_auth =
(struct ip6_mh_opt_authentication *)mhopt;
@@ -557,7 +563,8 @@ mh_input(src, dst, hoa, rtaddr, mh, mhlen)
/* CN and HA just ignore */
break;
case IP6_MH_TYPE_BU:
- return (receive_bu(src, dst, hoa, rtaddr, (struct ip6_mh_binding_update *)mh, mhlen));
+ return (receive_bu(src, dst, hoa, rtaddr,
+ (struct ip6_mh_binding_update *)mh, mhlen));
break;
case IP6_MH_TYPE_BERROR:
break;
@@ -636,7 +643,8 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
flags = bu->ip6mhbu_flags;
/* retrieve Mobility Options */
- if (get_mobility_options((struct ip6_mh *)bu, sizeof(*bu), mhlen, &mopt)) {
+ if (get_mobility_options((struct ip6_mh *)bu, sizeof(*bu), mhlen,
+ &mopt)) {
mip6stat.mip6s_invalidopt++;
syslog(LOG_ERR, "bad mobility option in BU.");
return (-1);
@@ -697,48 +705,57 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
if (home_nonces == NULL) {
statuscode = IP6_MH_BAS_HOME_NI_EXPIRED;
} else {
- create_keygentoken(hoa, home_nonces, (u_int8_t *)&home_token, 0);
+ create_keygentoken(hoa, home_nonces,
+ (u_int8_t *)&home_token, 0);
}
if (lifetime != 0
&& !IN6_ARE_ADDR_EQUAL(coa, hoa)) {
- careof_nonces = get_nonces(ntohs(mopt.opt_nonce->ip6moni_coa_nonce));
+ careof_nonces = get_nonces(
+ ntohs(mopt.opt_nonce->ip6moni_coa_nonce));
if (careof_nonces == NULL) {
if (home_nonces == NULL)
statuscode = IP6_MH_BAS_NI_EXPIRED;
else
statuscode = IP6_MH_BAS_COA_NI_EXPIRED;
} else {
- create_keygentoken(coa, careof_nonces, (u_int8_t *)careof_token, 1);
+ create_keygentoken(coa, careof_nonces,
+ (u_int8_t *)careof_token, 1);
}
cnnonce = 1;
}
- if ((home_nonces && check_nonce_reuse(home_nonces, hoa, coa)) ||
- (careof_nonces && check_nonce_reuse(careof_nonces, hoa, coa)))
+ if ((home_nonces &&
+ check_nonce_reuse(home_nonces, hoa, coa)) ||
+ (careof_nonces &&
+ check_nonce_reuse(careof_nonces, hoa, coa)))
statuscode = IP6_MH_BAS_NI_EXPIRED;
if (statuscode != IP6_MH_BAS_ACCEPTED)
goto sendba;
- /* Create Kbm = Hash(home keygen token | care-of keygen token) */
+ /* Create
+ Kbm = Hash(home keygen token | care-of keygen token) */
kbm = alloca(sizeof(*kbm));
- mip6_calculate_kbm(&home_token, (cnnonce) ? &careof_token : NULL, kbm);
+ mip6_calculate_kbm(&home_token,
+ (cnnonce) ? &careof_token : NULL, kbm);
- /* Compare Calculated Authentication Data into Authenticator field */
+ /* Compare Calculated Authentication Data to
+ Authenticator field */
cksum = bu->ip6mhbu_hdr.ip6mh_cksum;
bu->ip6mhbu_hdr.ip6mh_cksum = 0;
/* Calculate authenticator */
- mip6_calculate_authenticator(kbm, coa, dst, (caddr_t)bu, mhlen,
- (u_int8_t *)mopt.opt_bauth +
- sizeof(struct ip6_mh_opt_auth_data) - (u_int8_t *)bu,
- MIP6_AUTHENTICATOR_SIZE, &authenticator);
+ mip6_calculate_authenticator(kbm, coa, dst, (caddr_t)bu, mhlen,
+ (u_int8_t *)mopt.opt_bauth
+ + sizeof(struct ip6_mh_opt_auth_data)
+ - (u_int8_t *)bu, MIP6_AUTHENTICATOR_SIZE, &authenticator);
bu->ip6mhbu_hdr.ip6mh_cksum = cksum;
/* Authentication is failed, silently discard */
if (memcmp(&authenticator,
- ((u_int8_t *)mopt.opt_bauth + 2), MIP6_AUTHENTICATOR_SIZE) != 0) {
+ (u_int8_t *)mopt.opt_bauth + 2,
+ MIP6_AUTHENTICATOR_SIZE) != 0) {
syslog(LOG_ERR, "Authenticator comparison failed");
if (debug) {
syslog(LOG_INFO, "HomeIndex 0x%x",
@@ -748,7 +765,8 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
syslog(LOG_INFO, "CareofIndex 0x%x",
ntohs(mopt.opt_nonce->ip6moni_coa_nonce));
syslog(LOG_INFO, "Careof Token= %s",
- hexdump(&careof_token, MIP6_TOKEN_SIZE));
+ hexdump(&careof_token,
+ MIP6_TOKEN_SIZE));
syslog(LOG_INFO, "kbm: %s",
hexdump(kbm, MIP6_KBM_SIZE));
}
@@ -763,7 +781,7 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
#ifdef MIP_CN
/*
* According to the TAHI conformance test tool,
- * the judgement of 'H' bit should be done proior
+ * the judgement of 'H' bit should be done prior
* authentic confirmation.
*/
if (!homeagent_mode && (flags & IP6_MH_BU_HOME)) {
@@ -987,7 +1005,8 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
#endif /* MIP_CN */
mip6_bc_delete(bc);
syslog(LOG_INFO,
- "binding cache has been deleted. HoA:[%s], CoA[%s] lifetime=%d",
+ "binding cache has been deleted. "
+ "HoA:[%s], CoA[%s] lifetime=%d",
ip6_sprintf(hoa), ip6_sprintf(coa), lifetime);
} else {
#ifdef MIP_HA
@@ -1005,8 +1024,9 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
lifetime = 0; /* Returned lifetime in BA must be zero */
} else {
- /* Requesitng to cache binding (registration) */
- bc = mip6_bc_add(hoa, coa, dst, lifetime, flags, seqno, bid, authmethod, authmethod_done, mobility_spi);
+ /* Requesting to cache binding (registration) */
+ bc = mip6_bc_add(hoa, coa, dst, lifetime, flags, seqno, bid,
+ authmethod, authmethod_done, mobility_spi);
if (bc == NULL) {
statuscode = IP6_MH_BAS_INSUFFICIENT;
goto sendba;
@@ -1019,7 +1039,8 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
llhoa.s6_addr[1] = 0x80;
llhoa.s6_addr[3] = ha_if() & 0xff;
memcpy(&llhoa.s6_addr[8], &hoa->s6_addr[8], 8);
- bc->bc_llmbc = mip6_bc_add(&llhoa, coa, dst, lifetime, flags, seqno, bid, authmethod, authmethod_done, 0);
+ bc->bc_llmbc = mip6_bc_add(&llhoa, coa, dst, lifetime,
+ flags, seqno, bid, authmethod, authmethod_done, 0);
bc->bc_llmbc->bc_glmbc = bc;
}
@@ -1032,8 +1053,8 @@ receive_bu(src, dst, hoa, rtaddr, bu, mhlen)
sendba:
if (statuscode != IP6_MH_BAS_ACCEPTED ||
(flags & (IP6_MH_BU_ACK | IP6_MH_BU_HOME))) {
- send_ba(dst, retcoa, coa, hoa, flags, kbm,
- statuscode, seqno, lifetime, 0 /* refresh */, bid, mobility_spi);
+ send_ba(dst, retcoa, coa, hoa, flags, kbm, statuscode, seqno,
+ lifetime, 0 /* refresh */, bid, mobility_spi);
}
return (retcode);
@@ -1061,10 +1082,11 @@ send_brr(src, dst)
brr.ip6mhbr_hdr.ip6mh_proto = IPPROTO_NONE;
brr.ip6mhbr_hdr.ip6mh_len = (sizeof(brr) >> 3) - 1;
brr.ip6mhbr_hdr.ip6mh_type = IP6_MH_TYPE_BRR;
- brr.ip6mhbr_hdr.ip6mh_cksum = checksum_p((u_int16_t *)src, (u_int16_t *)dst,
- (u_int16_t *)&brr, sizeof(brr), IPPROTO_MH);
+ brr.ip6mhbr_hdr.ip6mh_cksum = checksum_p((u_int16_t *)src,
+ (u_int16_t *)dst, (u_int16_t *)&brr, sizeof(brr), IPPROTO_MH);
- error = sendmessage((char *)&brr, sizeof(brr), 0, src, dst, NULL, NULL);
+ error = sendmessage((char *)&brr, sizeof(brr), 0, src, dst, NULL,
+ NULL);
return (error);
}
@@ -1079,8 +1101,10 @@ send_hoti(bul)
if (debug) {
syslog(LOG_INFO, "HoTI is sent");
- syslog(LOG_INFO, " from %s", ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
- syslog(LOG_INFO, " to %s", ip6_sprintf(&bul->bul_peeraddr));
+ syslog(LOG_INFO, " from %s",
+ ip6_sprintf(&bul->bul_hoainfo->hinfo_hoa));
+ syslog(LOG_INFO, " to %s",
+ ip6_sprintf(&bul->bul_peeraddr));
}
memset(&hoti, 0, sizeof(hoti));
@@ -1092,13 +1116,12 @@ send_hoti(bul)
MIP6_COOKIE_SIZE);
memcpy((void *)hoti.ip6mhhti_cookie,
- (const void *)bul->bul_home_cookie,
- sizeof(hoti.ip6mhhti_cookie));
+ (const void *)bul->bul_home_cookie, sizeof(hoti.ip6mhhti_cookie));
hoti.ip6mhhti_hdr.ip6mh_cksum =
- checksum_p((u_int16_t *)&bul->bul_hoainfo->hinfo_hoa,
- (u_int16_t *)&bul->bul_peeraddr, (u_int16_t *)&hoti,
- sizeof(hoti), IPPROTO_MH);
+ checksum_p((u_int16_t *)&bul->bul_hoainfo->hinfo_hoa,
+ (u_int16_t *)&bul->bul_peeraddr, (u_int16_t *)&hoti, sizeof(hoti),
+ IPPROTO_MH);
err = sendmessage((char *)&hoti, sizeof(hoti), 0,
&bul->bul_hoainfo->hinfo_hoa, &bul->bul_peeraddr, NULL, NULL);
@@ -1129,16 +1152,15 @@ send_coti(bul)
MIP6_COOKIE_SIZE);
memcpy((void *)coti.ip6mhcti_cookie,
- (const void *)bul->bul_careof_cookie,
- sizeof(coti.ip6mhcti_cookie));
+ (const void *)bul->bul_careof_cookie,
+ sizeof(coti.ip6mhcti_cookie));
- coti.ip6mhcti_hdr.ip6mh_cksum =
- checksum_p((u_int16_t *)&bul->bul_coa,
- (u_int16_t *)&bul->bul_peeraddr, (u_int16_t *)&coti,
- sizeof(coti), IPPROTO_MH);
+ coti.ip6mhcti_hdr.ip6mh_cksum = checksum_p((u_int16_t *)&bul->bul_coa,
+ (u_int16_t *)&bul->bul_peeraddr, (u_int16_t *)&coti, sizeof(coti),
+ IPPROTO_MH);
- err = sendmessage((char *)&coti, sizeof(coti),
- 0, &bul->bul_coa, &bul->bul_peeraddr, NULL, NULL);
+ err = sendmessage((char *)&coti, sizeof(coti), 0, &bul->bul_coa,
+ &bul->bul_peeraddr, NULL, NULL);
return (err);
}
@@ -1168,7 +1190,8 @@ send_hot(hoti, dst, src)
hot.ip6mhht_hdr.ip6mh_len = (sizeof(hot) >> 3) - 1;
hot.ip6mhht_hdr.ip6mh_type = IP6_MH_TYPE_HOT;
hot.ip6mhht_hdr.ip6mh_reserved = 0;
- bcopy(hoti->ip6mhhti_cookie, hot.ip6mhht_cookie, sizeof(hot.ip6mhht_cookie));
+ bcopy(hoti->ip6mhhti_cookie, hot.ip6mhht_cookie,
+ sizeof(hot.ip6mhht_cookie));
memcpy((void *)hot.ip6mhht_cookie, (const void *)hoti->ip6mhhti_cookie,
sizeof(hot.ip6mhht_cookie));
@@ -1180,10 +1203,8 @@ send_hot(hoti, dst, src)
hot.ip6mhht_nonce_index = htons(nonce->nonce_index);
create_keygentoken(dst, nonce, (u_int8_t *)hot.ip6mhht_keygen, 0);
- hot.ip6mhht_hdr.ip6mh_cksum =
- checksum_p((u_int16_t *)src,
- (u_int16_t *)dst, (u_int16_t *)&hot,
- sizeof(hot), IPPROTO_MH);
+ hot.ip6mhht_hdr.ip6mh_cksum = checksum_p((u_int16_t *)src,
+ (u_int16_t *)dst, (u_int16_t *)&hot, sizeof(hot), IPPROTO_MH);