const char *ciphername)
{
- msg(D_DCO_DEBUG, "%s: peer_id=%d keyid=%d", __func__, multi->peer_id,
+ msg(D_DCO_DEBUG, "%s: peer_id=%d keyid=%d", __func__, multi->dco_peer_id,
ks->key_id);
/* Install a key in the PRIMARY slot only when no other key exist.
slot = OVPN_KEY_SLOT_SECONDARY;
}
- int ret = dco_new_key(multi->dco, multi->peer_id, ks->key_id, slot,
+ int ret = dco_new_key(multi->dco, multi->dco_peer_id, ks->key_id, slot,
encrypt_key, encrypt_iv,
decrypt_key, decrypt_iv,
ciphername);
void
dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
{
- msg(D_DCO_DEBUG, "%s: peer_id=%d", __func__, multi->peer_id);
+ msg(D_DCO_DEBUG, "%s: peer_id=%d", __func__, multi->dco_peer_id);
/* this function checks if keys have to be swapped or erased, therefore it
* can't do much if we don't have any key installed
{
msg(D_DCO, "No encryption key found. Purging data channel keys");
- int ret = dco_del_key(dco, multi->peer_id, OVPN_KEY_SLOT_PRIMARY);
+ int ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_PRIMARY);
if (ret < 0)
{
msg(D_DCO, "Cannot delete primary key during wipe: %s (%d)", strerror(-ret), ret);
return;
}
- ret = dco_del_key(dco, multi->peer_id, OVPN_KEY_SLOT_SECONDARY);
+ ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_SECONDARY);
if (ret < 0)
{
msg(D_DCO, "Cannot delete secondary key during wipe: %s (%d)", strerror(-ret), ret);
msg(D_DCO_DEBUG, "Swapping primary and secondary keys, now: id1=%d id2=%d",
primary->key_id, secondary ? secondary->key_id : -1);
- int ret = dco_swap_keys(dco, multi->peer_id);
+ int ret = dco_swap_keys(dco, multi->dco_peer_id);
if (ret < 0)
{
msg(D_DCO, "Cannot swap keys: %s (%d)", strerror(-ret), ret);
/* if we have no secondary key anymore, inform DCO about it */
if (!secondary && multi->dco_keys_installed == 2)
{
- int ret = dco_del_key(dco, multi->peer_id, OVPN_KEY_SLOT_SECONDARY);
+ int ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_SECONDARY);
if (ret < 0)
{
msg(D_DCO, "Cannot delete secondary key: %s (%d)", strerror(-ret), ret);
return ret;
}
- c->c2.tls_multi->dco_peer_added = true;
+ c->c2.tls_multi->dco_peer_id = multi->peer_id;
c->c2.link_socket->info.lsa->actual.dco_installed = true;
return 0;
return;
}
- if (c->c1.tuntap && c->c2.tls_multi && c->c2.tls_multi->dco_peer_added)
+ if (c->c1.tuntap && c->c2.tls_multi && c->c2.tls_multi->dco_peer_id != -1)
{
- dco_del_peer(&c->c1.tuntap->dco, c->c2.tls_multi->peer_id);
- c->c2.tls_multi->dco_peer_added = false;
+ dco_del_peer(&c->c1.tuntap->dco, c->c2.tls_multi->dco_peer_id);
+ c->c2.tls_multi->dco_peer_id = -1;
}
}
return ret;
}
- c->c2.tls_multi->dco_peer_added = true;
+ c->c2.tls_multi->dco_peer_id = peer_id;
if (c->mode == CM_CHILD_TCP)
{
if (should_use_dco_socket(c->c2.to_link_addr))
{
size = dco_do_write(&c->c1.tuntap->dco,
- c->c2.tls_multi->peer_id,
+ c->c2.tls_multi->dco_peer_id,
&c->c2.to_link);
}
else
&& (c->options.ping_send_timeout || c->c2.frame.mss_fix))
{
int ret = dco_set_peer(&c->c1.tuntap->dco,
- c->c2.tls_multi->peer_id,
+ c->c2.tls_multi->dco_peer_id,
c->options.ping_send_timeout,
c->options.ping_rec_timeout,
c->c2.frame.mss_fix);
if (ret < 0)
{
msg(D_DCO, "Cannot set parameters for DCO peer (id=%u): %s",
- c->c2.tls_multi->peer_id, strerror(-ret));
+ c->c2.tls_multi->dco_peer_id, strerror(-ret));
return false;
}
}
return ret;
}
+static bool
+multi_client_setup_dco_initial(struct multi_context *m,
+ struct multi_instance *mi,
+ struct gc_arena *gc)
+{
+ if (!dco_enabled(&mi->context.options))
+ {
+ /* DCO not enabled, nothing to do, return sucess */
+ return true;
+ }
+ int ret = dco_multi_add_new_peer(m, mi);
+ if (ret < 0)
+ {
+ msg(D_DCO, "Cannot add peer to DCO for %s: %s (%d)",
+ multi_instance_string(mi, false, gc), strerror(-ret), ret);
+ return false;
+ }
+
+ if (mi->context.options.ping_send_timeout || mi->context.c2.frame.mss_fix)
+ {
+ ret = dco_set_peer(&mi->context.c1.tuntap->dco,
+ mi->context.c2.tls_multi->dco_peer_id,
+ mi->context.options.ping_send_timeout,
+ mi->context.options.ping_rec_timeout,
+ mi->context.c2.frame.mss_fix);
+ if (ret < 0)
+ {
+ msg(D_DCO, "Cannot set DCO peer parameters for %s (id=%u): %s",
+ multi_instance_string(mi, false, gc),
+ mi->context.c2.tls_multi->dco_peer_id, strerror(-ret));
+ return false;
+ }
+ }
+ return true;
+}
+
/**
* Generates the data channel keys
*/
{
mi->context.c2.tls_multi->multi_state = CAS_FAILED;
}
+ /* only continue if setting protocol options worked */
+ else if (!multi_client_setup_dco_initial(m, mi, &gc))
+ {
+ mi->context.c2.tls_multi->multi_state = CAS_FAILED;
+ }
/* Generate data channel keys only if setting protocol options
- * has not failed */
- else
+ * and DCO initial setup has not failed */
+ else if (!multi_client_generate_tls_keys(&mi->context))
{
- if (dco_enabled(&mi->context.options))
- {
- int ret = dco_multi_add_new_peer(m, mi);
- if (ret < 0)
- {
- msg(D_DCO, "Cannot add peer to DCO: %s (%d)", strerror(-ret), ret);
- mi->context.c2.tls_multi->multi_state = CAS_FAILED;
- }
-
- if (mi->context.options.ping_send_timeout || mi->context.c2.frame.mss_fix)
- {
- int ret = dco_set_peer(&mi->context.c1.tuntap->dco,
- mi->context.c2.tls_multi->peer_id,
- mi->context.options.ping_send_timeout,
- mi->context.options.ping_rec_timeout,
- mi->context.c2.frame.mss_fix);
- if (ret < 0)
- {
- msg(D_DCO, "Cannot set parameters for DCO peer (id=%u): %s",
- mi->context.c2.tls_multi->peer_id, strerror(-ret));
- mi->context.c2.tls_multi->multi_state = CAS_FAILED;
- }
- }
- }
-
- if (!multi_client_generate_tls_keys(&mi->context))
- {
- mi->context.c2.tls_multi->multi_state = CAS_FAILED;
- }
+ mi->context.c2.tls_multi->multi_state = CAS_FAILED;
}
/* send push reply if ready */
{
process_incoming_push_request(&mi->context);
}
-
gc_free(&gc);
}
}
/* When kernel already deleted the peer, the socket is no longer
- * installed and we don't need to cleanup the state in the kernel */
- mi->context.c2.tls_multi->dco_peer_added = false;
+ * installed, and we do not need to clean up the state in the kernel */
+ mi->context.c2.tls_multi->dco_peer_id = -1;
mi->context.sig->signal_text = reason;
multi_signal_instance(m, mi, SIGTERM);
}
/* get command line derived options */
ret->opt = *tls_options;
+ ret->dco_peer_id = -1;
return ret;
}
/* Only used when DCO is used to remember how many keys we installed
* for this session */
int dco_keys_installed;
- bool dco_peer_added;
+ /**
+ * This is the handle that DCO uses to identify this session with the
+ * kernel.
+ *
+ * We keep this separate as the normal peer_id can change during
+ * p2p NCP and we need to track the id that is really used.
+ */
+ int dco_peer_id;
dco_context_t *dco;
};