diff --git a/include/pluto_constants.h b/include/pluto_constants.h index 5e3d67e6437..0e7ac86b976 100644 --- a/include/pluto_constants.h +++ b/include/pluto_constants.h @@ -267,7 +267,7 @@ typedef enum { /* Misc. stuff */ -#define MAXIMUM_v1_ACCEPTED_DUPLICATES 2 +#define MAXIMUM_v1_ACCEPTED_DUPLICATES 4 /* * maximum retransmits per exchange, for IKEv1 (initiator and responder), * IKEv2 initiator diff --git a/programs/pluto/ikev1.c b/programs/pluto/ikev1.c index c2c4aaa7864..08a05fe94ef 100644 --- a/programs/pluto/ikev1.c +++ b/programs/pluto/ikev1.c @@ -543,10 +543,10 @@ static const struct state_v1_microcode v1_state_microcode_table[] = { { STATE_MODE_CFG_R0, STATE_MODE_CFG_R1, SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_REPLY, P(MCFG_ATTR) | P(HASH), P(VID), - EVENT_SA_REPLACE, modecfg_inR0 }, + EVENT_v1_RETRANSMIT, modecfg_inR0 }, { STATE_MODE_CFG_R1, STATE_MODE_CFG_R2, - SMF_ALL_AUTH | SMF_ENCRYPTED, + SMF_ALL_AUTH | SMF_ENCRYPTED | SMF_RETRANSMIT_ON_DUPLICATE, P(MCFG_ATTR) | P(HASH), P(VID), EVENT_SA_REPLACE, modecfg_inR1 }, @@ -1434,6 +1434,10 @@ void process_v1_packet(struct msg_digest **mdp) enum_name(&state_names, st->st_state ))); + } else if (st->st_connection->spd.this.modecfg_server + && STATE_MODE_CFG_R1 == st->st_state) { + from_state = STATE_MODE_CFG_R1; + plog("already in STATE_MODE_CFG_R1, probably a retransmit"); } else if (st->st_connection->spd.this.modecfg_client && IS_PHASE1(st->st_state)) { diff --git a/programs/pluto/ikev1_quick.c b/programs/pluto/ikev1_quick.c index 817e9129519..355b65cd18c 100644 --- a/programs/pluto/ikev1_quick.c +++ b/programs/pluto/ikev1_quick.c @@ -1370,6 +1370,24 @@ static stf_status quick_inI1_outR1_authtail(struct verify_oppo_bundle *b) (hv.st_nat_traversal & NAT_T_WITH_NATOA)) nat_traversal_natoa_lookup(md, &hv); + if (p1st->st_event && EVENT_v1_RETRANSMIT == p1st->st_event->ev_type) { + /* KLUGE: To work around the tablet nots retransmitting their + * ModeCfg IP request, enabled retransmits on + * STATE_MODE_CFG_R0. However, after that retransmit... + * we get forcefully transitioned to STATE_QUICK_R0 and + * suspend the phase1, so the retransmit timer never gets + * cleared. So we clear it here. Otherwise it'll keep + * retransmitting, time out, and fairly soon down the + * connection. + * + * FIXME: But nothing sets back the EVENT_SA_REPLACE timer... + * which is normally done in ikev1.c:2467 ("case + * EVENT_SA_REPLACE:"). Not sure how much it matters, + * since the p2 state gets that event too. + */ + delete_event(p1st); + } + /* now that we are sure of our connection, create our new state */ { struct state *const st = duplicate_state(p1st, IPSEC_SA); diff --git a/programs/pluto/ikev2_spdb_struct.c b/programs/pluto/ikev2_spdb_struct.c index 3fe7546b8cd..90bf7555e54 100644 --- a/programs/pluto/ikev2_spdb_struct.c +++ b/programs/pluto/ikev2_spdb_struct.c @@ -1117,7 +1117,7 @@ stf_status ikev2_process_sa_payload(const char *what, * * Must be freed by this function. */ - stf_status status; + stf_status status = STF_FAIL; LSWBUF(remote_print_buf) { int matching_local_propnum = ikev2_process_proposals(sa_payload, expect_ike, expect_spi,