diff -Nur racoon2-20070817cvs/lib/if_pfkeyv2.c racoon2-patched/lib/if_pfkeyv2.c --- racoon2-20070817cvs/lib/if_pfkeyv2.c 2007-08-17 10:57:42.000000000 +0900 +++ racoon2-patched/lib/if_pfkeyv2.c 2007-08-17 11:52:12.000000000 +0900 @@ -2272,6 +2272,16 @@ rc->seq = base->sadb_msg_seq; rc->slid = xpl->sadb_x_policy_id; + + /* We need also the reqid for matching not-installed selectors */ + rc->reqid = 0; + if (xpl->sadb_x_policy_len > 2) + { + struct sadb_x_ipsecrequest *xisr; + + xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); + rc->reqid = xisr->sadb_x_ipsecrequest_reqid; + } if (cb->cb_spdadd != 0 && cb->cb_spdadd(rc) < 0) return -1; diff -Nur racoon2-20070817cvs/spmd/spmd_pfkey.c racoon2-patched/spmd/spmd_pfkey.c --- racoon2-20070817cvs/spmd/spmd_pfkey.c 2007-08-17 10:57:42.000000000 +0900 +++ racoon2-patched/spmd/spmd_pfkey.c 2007-08-17 11:52:12.000000000 +0900 @@ -141,11 +141,19 @@ #else static int spid_data_add(uint32_t seq, const char *slid); #endif +static int spid_data_add_complete(uint32_t spid, const char *slid); static int spid_data_del(struct spid_data *sd); static int spid_data_del_by_spid(int32_t spid); static int spid_data_dump(void); /*const struct spid_data *spid_data_top(void);*/ + +/************************************************************************ + * Handle SPD entries from other apps (e.g. mobile ipv6) + ************************************************************************/ +static int spmd_handle_external(struct rcpfk_msg *rc); + + /********** SUBSTANCE **********/ @@ -892,24 +900,31 @@ static int spmd_pfkey_spdadd_cb(struct rcpfk_msg *rc) { - if (spid_data_update(rc->seq, rc->slid)<0) { /* returned rc->slid is spid */ - SPMD_PLOG(SPMD_L_INTERR, "Failed to update slid<->spid matching"); - return -1; - } + + + if (spid_data_update(rc->seq, rc->slid)>=0) { /* returned rc->slid is spid */ #ifdef SPMD_DEBUG - { - char *slid = NULL; + { + char *slid = NULL; - get_slid_by_spid(rc->slid, &slid); /* rc->slid is real spid */ - if (slid) { - SPMD_PLOG(SPMD_L_DEBUG, "Updated: slid=%s, spid=%u", slid, rc->slid); - spmd_free(slid); + get_slid_by_spid(rc->slid, &slid); /* rc->slid is real spid */ + if (slid) { + SPMD_PLOG(SPMD_L_DEBUG, "Updated: slid=%s, spid=%u", slid, rc->slid); + spmd_free(slid); + } } - } #endif /* SPMD_DEBUG */ + return 0; + } + + /* Fallback if we have not found a valid spid_data entry yet. */ + if (spmd_handle_external(rc) == 0) + return 0; + + SPMD_PLOG(SPMD_L_INTERR, "Failed to update slid<->spid matching"); + return -1; - return 0; } /* @@ -1783,7 +1798,7 @@ return -1; } if (!sd) { /* NULL */ - SPMD_PLOG(SPMD_L_INTERR, "Can't find spid entry, spid list is nothing"); + SPMD_PLOG(SPMD_L_INTERR, "No spid_data entry with this sequence."); return -1; } @@ -1934,6 +1949,50 @@ } #endif /* NO_SPDUPDATE_BUG */ +/* Add a new entry in one-step, when we already have slid and spid. */ +static int +spid_data_add_complete(uint32_t spid, const char *slid) +{ + struct spid_data *sd = NULL; + struct spid_data *td = NULL; + char *p = NULL; + + if (!slid) { + SPMD_PLOG(SPMD_L_INTERR, "argument slid is NULL"); + return -1; + } + + sd = spmd_calloc(sizeof(struct spid_data)); + if (!sd) { + SPMD_PLOG(SPMD_L_INTERR, "Out of memory"); + return -1; + } + + p = spmd_strdup(slid); + if (!p) { + SPMD_PLOG(SPMD_L_INTERR, "Out of memory"); + spmd_free(sd); + return -1; + } + + sd->seq = 0; /* No update needed afterwards */ + sd->slid = p; + sd->spid = spid; + + if (sd_top==NULL) { + sd_top = sd; + } else { + td = sd_top; + while (td->next) { + td = td->next; + } + td->next = sd; + sd->pre = td; + } + + return 0; +} + /* * Delete an element from SPID<->SLID list */ @@ -2059,3 +2118,63 @@ return sd_top; } + +/************************************************************************ + * Handle SPD entries from other apps (e.g. mobile ipv6) + * Based on: + * -> the policy in the configuration must have flag: install off; + * -> the selector reqid must match sadb message reqid (!= 0). + * This is called on SPDADD messages (what about SPDUPDATE ?) + ************************************************************************/ +static int spmd_handle_external(struct rcpfk_msg *rc) +{ + struct rcf_selector *sl_head = NULL; + struct rcf_selector *sl = NULL; + + /* We should have the reqid of the policy we are adding in rc. */ + if (rc->reqid == 0) + { + SPMD_PLOG(SPMD_L_DEBUG, "spmd_handle_external: reqid=0, skipping."); + return -1; + } + + /* Ok now we need to find in the configuration if we have a selector that was not installed and with matching reqid. */ + if (rcf_get_selectorlist(&sl_head) < 0) { + SPMD_PLOG(SPMD_L_INTERR, + "Can't get Selector list in your configuration file"); + return -1; + } + + for (sl = sl_head;sl;sl=sl->next) { + + /* Ignore selectors without policies */ + if (!sl->pl) + continue; + /* Ignore selectors with installed policies */ + if (sl->pl->install == RCT_BOOL_ON) + continue; + + /* Try and match the reqid */ + if (sl->reqid != rc->reqid) + continue; + + /* We have found a selector */ + SPMD_PLOG(SPMD_L_DEBUG, "Found selector(=%.*s) suitable for the external policy.", + sl->sl_index->l, sl->sl_index->v); + + if (spid_data_add_complete(rc->slid /* this is the spid */, rc_vmem2str(sl->sl_index)) < 0) + { + SPMD_PLOG(SPMD_L_INTERR, "Failed to create spid_data entry..."); + return -1; + } + +#ifdef SPMD_DEBUG + spid_data_dump(); +#endif /* SPMD_DEBUG */ + + return 0; + } + + /* Not found suitable selector */ + return -1; +}