conn_event.c 10.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/* connection-level event handling
 *
 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * 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.
 */

12 13
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

14 15 16 17 18 19 20 21 22
#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/errqueue.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include <net/ip.h>
#include "ar-internal.h"

23 24 25
/*
 * Retransmit terminal ACK or ABORT of the previous call.
 */
26 27
static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
				       struct sk_buff *skb)
28 29 30 31 32 33 34 35 36 37 38 39 40
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct rxrpc_channel *chan;
	struct msghdr msg;
	struct kvec iov;
	struct {
		struct rxrpc_wire_header whdr;
		union {
			struct {
				__be32 code;
			} abort;
			struct {
				struct rxrpc_ackpacket ack;
D
David Howells 已提交
41
				u8 padding[3];
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
				struct rxrpc_ackinfo info;
			};
		};
	} __attribute__((packed)) pkt;
	size_t len;
	u32 serial, mtu, call_id;

	_enter("%d", conn->debug_id);

	chan = &conn->channels[sp->hdr.cid & RXRPC_CHANNELMASK];

	/* If the last call got moved on whilst we were waiting to run, just
	 * ignore this packet.
	 */
	call_id = READ_ONCE(chan->last_call);
	/* Sync with __rxrpc_disconnect_call() */
	smp_rmb();
	if (call_id != sp->hdr.callNumber)
		return;

	msg.msg_name	= &conn->params.peer->srx.transport;
	msg.msg_namelen	= conn->params.peer->srx.transport_len;
	msg.msg_control	= NULL;
	msg.msg_controllen = 0;
	msg.msg_flags	= 0;

	pkt.whdr.epoch		= htonl(sp->hdr.epoch);
	pkt.whdr.cid		= htonl(sp->hdr.cid);
	pkt.whdr.callNumber	= htonl(sp->hdr.callNumber);
	pkt.whdr.seq		= 0;
	pkt.whdr.type		= chan->last_type;
	pkt.whdr.flags		= conn->out_clientflag;
	pkt.whdr.userStatus	= 0;
	pkt.whdr.securityIndex	= conn->security_ix;
	pkt.whdr._rsvd		= 0;
	pkt.whdr.serviceId	= htons(chan->last_service_id);

	len = sizeof(pkt.whdr);
	switch (chan->last_type) {
	case RXRPC_PACKET_TYPE_ABORT:
		pkt.abort.code	= htonl(chan->last_abort);
		len += sizeof(pkt.abort);
		break;

	case RXRPC_PACKET_TYPE_ACK:
		mtu = conn->params.peer->if_mtu;
		mtu -= conn->params.peer->hdrsize;
		pkt.ack.bufferSpace	= 0;
		pkt.ack.maxSkew		= htons(skb->priority);
		pkt.ack.firstPacket	= htonl(chan->last_seq);
		pkt.ack.previousPacket	= htonl(chan->last_seq - 1);
		pkt.ack.serial		= htonl(sp->hdr.serial);
		pkt.ack.reason		= RXRPC_ACK_DUPLICATE;
		pkt.ack.nAcks		= 0;
		pkt.info.rxMTU		= htonl(rxrpc_rx_mtu);
		pkt.info.maxMTU		= htonl(mtu);
		pkt.info.rwind		= htonl(rxrpc_rx_window_size);
		pkt.info.jumbo_max	= htonl(rxrpc_rx_jumbo_max);
D
David Howells 已提交
100
		pkt.whdr.flags		|= RXRPC_SLOW_START_OK;
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
		len += sizeof(pkt.ack) + sizeof(pkt.info);
		break;
	}

	/* Resync with __rxrpc_disconnect_call() and check that the last call
	 * didn't get advanced whilst we were filling out the packets.
	 */
	smp_rmb();
	if (READ_ONCE(chan->last_call) != call_id)
		return;

	iov.iov_base	= &pkt;
	iov.iov_len	= len;

	serial = atomic_inc_return(&conn->serial);
	pkt.whdr.serial = htonl(serial);

	switch (chan->last_type) {
	case RXRPC_PACKET_TYPE_ABORT:
		_proto("Tx ABORT %%%u { %d } [re]", serial, conn->local_abort);
		break;
	case RXRPC_PACKET_TYPE_ACK:
123 124
		trace_rxrpc_tx_ack(NULL, serial, chan->last_seq, 0,
				   RXRPC_ACK_DUPLICATE, 0);
125 126 127 128 129 130 131 132 133
		_proto("Tx ACK %%%u [re]", serial);
		break;
	}

	kernel_sendmsg(conn->params.local->socket, &msg, &iov, 1, len);
	_leave("");
	return;
}

134 135 136
/*
 * pass a connection-level abort onto all calls on that connection
 */
137 138 139
static void rxrpc_abort_calls(struct rxrpc_connection *conn,
			      enum rxrpc_call_completion compl,
			      u32 abort_code, int error)
140 141
{
	struct rxrpc_call *call;
142
	int i;
143 144 145

	_enter("{%d},%x", conn->debug_id, abort_code);

146
	spin_lock(&conn->channel_lock);
147

148 149 150 151
	for (i = 0; i < RXRPC_MAXCALLS; i++) {
		call = rcu_dereference_protected(
			conn->channels[i].call,
			lockdep_is_held(&conn->channel_lock));
152
		if (call) {
153 154 155 156
			if (compl == RXRPC_CALL_LOCALLY_ABORTED)
				trace_rxrpc_abort("CON", call->cid,
						  call->call_id, 0,
						  abort_code, error);
157 158 159
			if (rxrpc_set_call_completion(call, compl,
						      abort_code, error))
				rxrpc_notify_socket(call);
160 161 162
		}
	}

163
	spin_unlock(&conn->channel_lock);
164 165 166 167 168 169 170
	_leave("");
}

/*
 * generate a connection-level abort
 */
static int rxrpc_abort_connection(struct rxrpc_connection *conn,
171
				  int error, u32 abort_code)
172
{
173
	struct rxrpc_wire_header whdr;
174 175 176 177
	struct msghdr msg;
	struct kvec iov[2];
	__be32 word;
	size_t len;
178
	u32 serial;
179 180 181 182 183 184
	int ret;

	_enter("%d,,%u,%u", conn->debug_id, error, abort_code);

	/* generate a connection-level abort */
	spin_lock_bh(&conn->state_lock);
185
	if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) {
186 187 188 189 190
		spin_unlock_bh(&conn->state_lock);
		_leave(" = 0 [already dead]");
		return 0;
	}

191 192 193 194
	conn->state = RXRPC_CONN_LOCALLY_ABORTED;
	spin_unlock_bh(&conn->state_lock);

	rxrpc_abort_calls(conn, RXRPC_CALL_LOCALLY_ABORTED, abort_code, error);
195

196 197
	msg.msg_name	= &conn->params.peer->srx.transport;
	msg.msg_namelen	= conn->params.peer->srx.transport_len;
198 199 200 201
	msg.msg_control	= NULL;
	msg.msg_controllen = 0;
	msg.msg_flags	= 0;

202 203
	whdr.epoch	= htonl(conn->proto.epoch);
	whdr.cid	= htonl(conn->proto.cid);
204 205 206 207 208 209 210
	whdr.callNumber	= 0;
	whdr.seq	= 0;
	whdr.type	= RXRPC_PACKET_TYPE_ABORT;
	whdr.flags	= conn->out_clientflag;
	whdr.userStatus	= 0;
	whdr.securityIndex = conn->security_ix;
	whdr._rsvd	= 0;
211
	whdr.serviceId	= htons(conn->params.service_id);
212

213
	word		= htonl(conn->local_abort);
214

215 216
	iov[0].iov_base	= &whdr;
	iov[0].iov_len	= sizeof(whdr);
217 218 219 220 221
	iov[1].iov_base	= &word;
	iov[1].iov_len	= sizeof(word);

	len = iov[0].iov_len + iov[1].iov_len;

222 223
	serial = atomic_inc_return(&conn->serial);
	whdr.serial = htonl(serial);
224
	_proto("Tx CONN ABORT %%%u { %d }", serial, conn->local_abort);
225

226
	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
227 228 229 230 231 232 233 234 235 236 237
	if (ret < 0) {
		_debug("sendmsg failed: %d", ret);
		return -EAGAIN;
	}

	_leave(" = 0");
	return 0;
}

/*
 * mark a call as being on a now-secured channel
238
 * - must be called with BH's disabled.
239
 */
R
Roel Kluin 已提交
240
static void rxrpc_call_is_secure(struct rxrpc_call *call)
241 242 243
{
	_enter("%p", call);
	if (call) {
244 245 246 247 248 249
		write_lock_bh(&call->state_lock);
		if (call->state == RXRPC_CALL_SERVER_SECURING) {
			call->state = RXRPC_CALL_SERVER_ACCEPTING;
			rxrpc_notify_socket(call);
		}
		write_unlock_bh(&call->state_lock);
250 251 252 253 254 255 256 257 258 259 260
	}
}

/*
 * connection-level Rx packet processor
 */
static int rxrpc_process_event(struct rxrpc_connection *conn,
			       struct sk_buff *skb,
			       u32 *_abort_code)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
261 262
	__be32 wtmp;
	u32 abort_code;
263 264
	int loop, ret;

265
	if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) {
266
		_leave(" = -ECONNABORTED [%u]", conn->state);
267
		return -ECONNABORTED;
268
	}
269

270
	_enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial);
271

272
	switch (sp->hdr.type) {
273 274
	case RXRPC_PACKET_TYPE_DATA:
	case RXRPC_PACKET_TYPE_ACK:
275
		rxrpc_conn_retransmit_call(conn, skb);
276 277
		return 0;

278 279 280 281
	case RXRPC_PACKET_TYPE_BUSY:
		/* Just ignore BUSY packets for now. */
		return 0;

282
	case RXRPC_PACKET_TYPE_ABORT:
283
		if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
284 285 286
				  &wtmp, sizeof(wtmp)) < 0) {
			trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
					      tracepoint_string("bad_abort"));
287
			return -EPROTO;
288
		}
289 290
		abort_code = ntohl(wtmp);
		_proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code);
291 292

		conn->state = RXRPC_CONN_REMOTELY_ABORTED;
293
		rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED,
294
				  abort_code, -ECONNABORTED);
295 296 297
		return -ECONNABORTED;

	case RXRPC_PACKET_TYPE_CHALLENGE:
298 299
		return conn->security->respond_to_challenge(conn, skb,
							    _abort_code);
300 301 302 303 304 305 306 307 308 309

	case RXRPC_PACKET_TYPE_RESPONSE:
		ret = conn->security->verify_response(conn, skb, _abort_code);
		if (ret < 0)
			return ret;

		ret = conn->security->init_connection_security(conn);
		if (ret < 0)
			return ret;

310 311 312 313
		ret = conn->security->prime_packet_security(conn);
		if (ret < 0)
			return ret;

314
		spin_lock(&conn->channel_lock);
315 316
		spin_lock(&conn->state_lock);

317 318
		if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
			conn->state = RXRPC_CONN_SERVICE;
319
			spin_unlock(&conn->state_lock);
320
			for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
321 322
				rxrpc_call_is_secure(
					rcu_dereference_protected(
323 324
						conn->channels[loop].call,
						lockdep_is_held(&conn->channel_lock)));
325 326
		} else {
			spin_unlock(&conn->state_lock);
327 328
		}

329
		spin_unlock(&conn->channel_lock);
330 331 332
		return 0;

	default:
333 334
		trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
				      tracepoint_string("bad_conn_pkt"));
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
		return -EPROTO;
	}
}

/*
 * set up security and issue a challenge
 */
static void rxrpc_secure_connection(struct rxrpc_connection *conn)
{
	u32 abort_code;
	int ret;

	_enter("{%d}", conn->debug_id);

	ASSERT(conn->security_ix != 0);

351
	if (!conn->params.key) {
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
		_debug("set up security");
		ret = rxrpc_init_server_conn_security(conn);
		switch (ret) {
		case 0:
			break;
		case -ENOENT:
			abort_code = RX_CALL_DEAD;
			goto abort;
		default:
			abort_code = RXKADNOAUTH;
			goto abort;
		}
	}

	if (conn->security->issue_challenge(conn) < 0) {
		abort_code = RX_CALL_DEAD;
		ret = -ENOMEM;
		goto abort;
	}

	_leave("");
	return;

abort:
	_debug("abort %d, %d", ret, abort_code);
377
	rxrpc_abort_connection(conn, ret, abort_code);
378 379 380 381 382 383 384 385 386 387 388 389 390 391
	_leave(" [aborted]");
}

/*
 * connection-level event processor
 */
void rxrpc_process_connection(struct work_struct *work)
{
	struct rxrpc_connection *conn =
		container_of(work, struct rxrpc_connection, processor);
	struct sk_buff *skb;
	u32 abort_code = RX_PROTOCOL_ERROR;
	int ret;

392
	rxrpc_see_connection(conn);
393

394
	if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events))
395 396 397 398 399
		rxrpc_secure_connection(conn);

	/* go through the conn-level event packets, releasing the ref on this
	 * connection that each one has when we've finished with it */
	while ((skb = skb_dequeue(&conn->rx_queue))) {
D
David Howells 已提交
400
		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
401 402 403 404 405 406 407 408 409 410
		ret = rxrpc_process_event(conn, skb, &abort_code);
		switch (ret) {
		case -EPROTO:
		case -EKEYEXPIRED:
		case -EKEYREJECTED:
			goto protocol_error;
		case -EAGAIN:
			goto requeue_and_leave;
		case -ECONNABORTED:
		default:
D
David Howells 已提交
411
			rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
412 413 414 415 416 417 418 419 420 421 422 423 424 425
			break;
		}
	}

out:
	rxrpc_put_connection(conn);
	_leave("");
	return;

requeue_and_leave:
	skb_queue_head(&conn->rx_queue, skb);
	goto out;

protocol_error:
426
	if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
427
		goto requeue_and_leave;
D
David Howells 已提交
428
	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
429 430
	goto out;
}