1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/* rekey connections: IKEv2
*
* Copyright (C) 1998-2002,2013 D. Hugh Redelmeier <hugh@mimosa.com>
* Copyright (C) 2008 Michael Richardson <mcr@xelerance.com>
* Copyright (C) 2009 Paul Wouters <paul@xelerance.com>
* Copyright (C) 2012 Paul Wouters <paul@libreswan.org>
* Copyright (C) 2013-2019 Paul Wouters <pwouters@redhat.com>
* Copyright (C) 2019 Andrew Cagney <cagney@gnu.org>
* Copyright (C) 2019 Antony Antony <antony@phenome.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <https://www.gnu.org/licenses/gpl2.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#include "defs.h"
#include "log.h"
#include "connections.h"
#include "state.h"
#include "timer.h"
#include "whack_rekey.h"
#include "show.h"
#include "whack_connection.h"
static bool rekey_state(const struct whack_message *m, struct show *s,
struct connection *c, enum sa_type sa_type, so_serial_t so)
{
struct logger *logger = show_logger(s);
struct state *st = state_by_serialno(so);
if (st == NULL) {
connection_attach(c, logger);
llog(RC_LOG, c->logger, "connection does not have %s",
connection_sa_name(c, sa_type));
connection_detach(c, logger);
return 0; /* the connection doesn't count */
}
if (!m->whack_async) {
state_attach(st, logger);
}
if (IS_CHILD_SA(st)) {
struct child_sa *child = pexpect_child_sa(st);
struct ike_sa *parent = parent_sa(child);
if (parent == NULL) {
llog_sa(RC_LOG, child,
"can't rekey, %s has no %s",
st->st_connection->config->ike_info->child_sa_name,
st->st_connection->config->ike_info->parent_sa_name);
return 0; /* the connection doesn't count */
}
if (!m->whack_async) {
state_attach(&parent->sa, logger);
}
}
ldbg(logger, "rekeying "PRI_SO, pri_so(so));
event_force(EVENT_v2_REKEY, st);
return 1; /* the connection counts */
}
static unsigned whack_rekey_ike(const struct whack_message *m,
struct show *s,
struct connection *c)
{
struct logger *logger = show_logger(s);
if (!can_have_sa(c, IKE_SA)) {
/* silently skip */
connection_buf cb;
ldbg(logger, "skipping non-parent connection "PRI_CONNECTION,
pri_connection(c, &cb));
return 0; /* the connection doesn't count */
}
return rekey_state(m, s, c, IKE_SA, c->established_ike_sa);
}
static unsigned whack_rekey_child(const struct whack_message *m,
struct show *s,
struct connection *c)
{
struct logger *logger = show_logger(s);
if (!can_have_sa(c, CHILD_SA)) {
/* silently skip */
connection_buf cb;
ldbg(logger, "skipping non-child connection "PRI_CONNECTION,
pri_connection(c, &cb));
return 0; /* the connection doesn't count */
}
return rekey_state(m, s, c, CHILD_SA, c->established_child_sa);
}
void whack_rekey(const struct whack_message *m, struct show *s, enum sa_type sa_type)
{
struct logger *logger = show_logger(s);
if (m->name == NULL) {
/* leave bread crumb */
llog(RC_FATAL, logger,
"received command to rekey connection, but did not receive the connection name - ignored");
return;
}
switch (sa_type) {
case IKE_SA:
whack_connections_bottom_up(m, s, whack_rekey_ike,
(struct each) {
.log_unknown_name = true,
});
return;
case CHILD_SA:
whack_connections_bottom_up(m, s, whack_rekey_child,
(struct each) {
.log_unknown_name = true,
});
return;
}
bad_case(sa_type);
}
|