File: whack_rekey.c

package info (click to toggle)
libreswan 5.2-2.3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 81,644 kB
  • sloc: ansic: 129,988; sh: 32,018; xml: 20,646; python: 10,303; makefile: 3,022; javascript: 1,506; sed: 574; yacc: 511; perl: 264; awk: 52
file content (129 lines) | stat: -rw-r--r-- 3,799 bytes parent folder | download | duplicates (2)
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);
}