Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44ba0698 authored by David Howells's avatar David Howells
Browse files

RxRPC: Handle VERSION Rx protocol packets



Handle VERSION Rx protocol packets.  We should respond to a VERSION packet
with a string indicating the Rx version.  This is a maximum of 64 characters
and is padded out to 65 chars with NUL bytes.

Note that other AFS clients use the version request as a NAT keepalive so we
need to handle it rather than returning an abort.

The standard formulation seems to be:

	<project> <version> built <yyyy>-<mm>-<dd>

for example:

	" OpenAFS 1.6.2 built  2013-05-07 "

(note the three extra spaces) as obtained with:

	rxdebug grand.mit.edu -version

from the openafs package.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent bfd4e956
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -47,7 +47,8 @@ struct rxrpc_header {
#define RXRPC_PACKET_TYPE_CHALLENGE	6	/* connection security challenge (SRVR->CLNT) */
#define RXRPC_PACKET_TYPE_CHALLENGE	6	/* connection security challenge (SRVR->CLNT) */
#define RXRPC_PACKET_TYPE_RESPONSE	7	/* connection secutity response (CLNT->SRVR) */
#define RXRPC_PACKET_TYPE_RESPONSE	7	/* connection secutity response (CLNT->SRVR) */
#define RXRPC_PACKET_TYPE_DEBUG		8	/* debug info request */
#define RXRPC_PACKET_TYPE_DEBUG		8	/* debug info request */
#define RXRPC_N_PACKET_TYPES		9	/* number of packet types (incl type 0) */
#define RXRPC_PACKET_TYPE_VERSION	13	/* version string request */
#define RXRPC_N_PACKET_TYPES		14	/* number of packet types (incl type 0) */


	uint8_t		flags;		/* packet flags */
	uint8_t		flags;		/* packet flags */
#define RXRPC_CLIENT_INITIATED	0x01		/* signifies a packet generated by a client */
#define RXRPC_CLIENT_INITIATED	0x01		/* signifies a packet generated by a client */
+22 −1
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@
const char *rxrpc_pkts[] = {
const char *rxrpc_pkts[] = {
	"?00",
	"?00",
	"DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG",
	"DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG",
	"?09", "?10", "?11", "?12", "?13", "?14", "?15"
	"?09", "?10", "?11", "?12", "VERSION", "?14", "?15"
};
};


/*
/*
@@ -593,6 +593,20 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
	rxrpc_queue_conn(conn);
	rxrpc_queue_conn(conn);
}
}


/*
 * post endpoint-level events to the local endpoint
 * - this includes debug and version messages
 */
static void rxrpc_post_packet_to_local(struct rxrpc_local *local,
				       struct sk_buff *skb)
{
	_enter("%p,%p", local, skb);

	atomic_inc(&local->usage);
	skb_queue_tail(&local->event_queue, skb);
	rxrpc_queue_work(&local->event_processor);
}

static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local,
					       struct sk_buff *skb,
					       struct sk_buff *skb,
					       struct rxrpc_skb_priv *sp)
					       struct rxrpc_skb_priv *sp)
@@ -699,6 +713,11 @@ void rxrpc_data_ready(struct sock *sk)
		goto bad_message;
		goto bad_message;
	}
	}


	if (sp->hdr.type == RXRPC_PACKET_TYPE_VERSION) {
		rxrpc_post_packet_to_local(local, skb);
		goto out;
	}
	
	if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
	if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA &&
	    (sp->hdr.callNumber == 0 || sp->hdr.seq == 0))
	    (sp->hdr.callNumber == 0 || sp->hdr.seq == 0))
		goto bad_message;
		goto bad_message;
@@ -731,6 +750,8 @@ void rxrpc_data_ready(struct sock *sk)
		else
		else
			goto cant_route_call;
			goto cant_route_call;
	}
	}

out:
	rxrpc_put_local(local);
	rxrpc_put_local(local);
	return;
	return;


+2 −0
Original line number Original line Diff line number Diff line
@@ -152,11 +152,13 @@ struct rxrpc_local {
	struct work_struct	destroyer;	/* endpoint destroyer */
	struct work_struct	destroyer;	/* endpoint destroyer */
	struct work_struct	acceptor;	/* incoming call processor */
	struct work_struct	acceptor;	/* incoming call processor */
	struct work_struct	rejecter;	/* packet reject writer */
	struct work_struct	rejecter;	/* packet reject writer */
	struct work_struct	event_processor; /* endpoint event processor */
	struct list_head	services;	/* services listening on this endpoint */
	struct list_head	services;	/* services listening on this endpoint */
	struct list_head	link;		/* link in endpoint list */
	struct list_head	link;		/* link in endpoint list */
	struct rw_semaphore	defrag_sem;	/* control re-enablement of IP DF bit */
	struct rw_semaphore	defrag_sem;	/* control re-enablement of IP DF bit */
	struct sk_buff_head	accept_queue;	/* incoming calls awaiting acceptance */
	struct sk_buff_head	accept_queue;	/* incoming calls awaiting acceptance */
	struct sk_buff_head	reject_queue;	/* packets awaiting rejection */
	struct sk_buff_head	reject_queue;	/* packets awaiting rejection */
	struct sk_buff_head	event_queue;	/* endpoint event packets awaiting processing */
	spinlock_t		lock;		/* access lock */
	spinlock_t		lock;		/* access lock */
	rwlock_t		services_lock;	/* lock for services list */
	rwlock_t		services_lock;	/* lock for services list */
	atomic_t		usage;
	atomic_t		usage;
+98 −0
Original line number Original line Diff line number Diff line
@@ -13,16 +13,22 @@
#include <linux/net.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/udp.h>
#include <linux/ip.h>
#include <net/sock.h>
#include <net/sock.h>
#include <net/af_rxrpc.h>
#include <net/af_rxrpc.h>
#include <generated/utsrelease.h>
#include "ar-internal.h"
#include "ar-internal.h"


static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";

static LIST_HEAD(rxrpc_locals);
static LIST_HEAD(rxrpc_locals);
DEFINE_RWLOCK(rxrpc_local_lock);
DEFINE_RWLOCK(rxrpc_local_lock);
static DECLARE_RWSEM(rxrpc_local_sem);
static DECLARE_RWSEM(rxrpc_local_sem);
static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq);
static DECLARE_WAIT_QUEUE_HEAD(rxrpc_local_wq);


static void rxrpc_destroy_local(struct work_struct *work);
static void rxrpc_destroy_local(struct work_struct *work);
static void rxrpc_process_local_events(struct work_struct *work);


/*
/*
 * allocate a new local
 * allocate a new local
@@ -37,11 +43,13 @@ struct rxrpc_local *rxrpc_alloc_local(struct sockaddr_rxrpc *srx)
		INIT_WORK(&local->destroyer, &rxrpc_destroy_local);
		INIT_WORK(&local->destroyer, &rxrpc_destroy_local);
		INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls);
		INIT_WORK(&local->acceptor, &rxrpc_accept_incoming_calls);
		INIT_WORK(&local->rejecter, &rxrpc_reject_packets);
		INIT_WORK(&local->rejecter, &rxrpc_reject_packets);
		INIT_WORK(&local->event_processor, &rxrpc_process_local_events);
		INIT_LIST_HEAD(&local->services);
		INIT_LIST_HEAD(&local->services);
		INIT_LIST_HEAD(&local->link);
		INIT_LIST_HEAD(&local->link);
		init_rwsem(&local->defrag_sem);
		init_rwsem(&local->defrag_sem);
		skb_queue_head_init(&local->accept_queue);
		skb_queue_head_init(&local->accept_queue);
		skb_queue_head_init(&local->reject_queue);
		skb_queue_head_init(&local->reject_queue);
		skb_queue_head_init(&local->event_queue);
		spin_lock_init(&local->lock);
		spin_lock_init(&local->lock);
		rwlock_init(&local->services_lock);
		rwlock_init(&local->services_lock);
		atomic_set(&local->usage, 1);
		atomic_set(&local->usage, 1);
@@ -264,10 +272,12 @@ static void rxrpc_destroy_local(struct work_struct *work)
	ASSERT(list_empty(&local->services));
	ASSERT(list_empty(&local->services));
	ASSERT(!work_pending(&local->acceptor));
	ASSERT(!work_pending(&local->acceptor));
	ASSERT(!work_pending(&local->rejecter));
	ASSERT(!work_pending(&local->rejecter));
	ASSERT(!work_pending(&local->event_processor));


	/* finish cleaning up the local descriptor */
	/* finish cleaning up the local descriptor */
	rxrpc_purge_queue(&local->accept_queue);
	rxrpc_purge_queue(&local->accept_queue);
	rxrpc_purge_queue(&local->reject_queue);
	rxrpc_purge_queue(&local->reject_queue);
	rxrpc_purge_queue(&local->event_queue);
	kernel_sock_shutdown(local->socket, SHUT_RDWR);
	kernel_sock_shutdown(local->socket, SHUT_RDWR);
	sock_release(local->socket);
	sock_release(local->socket);


@@ -308,3 +318,91 @@ void __exit rxrpc_destroy_all_locals(void)


	_leave("");
	_leave("");
}
}

/*
 * Reply to a version request
 */
static void rxrpc_send_version_request(struct rxrpc_local *local,
				       struct rxrpc_header *hdr,
				       struct sk_buff *skb)
{
	struct sockaddr_in sin;
	struct msghdr msg;
	struct kvec iov[2];
	size_t len;
	int ret;

	_enter("");

	sin.sin_family = AF_INET;
	sin.sin_port = udp_hdr(skb)->source;
	sin.sin_addr.s_addr = ip_hdr(skb)->saddr;

	msg.msg_name	= &sin;
	msg.msg_namelen	= sizeof(sin);
	msg.msg_control	= NULL;
	msg.msg_controllen = 0;
	msg.msg_flags	= 0;

	hdr->seq	= 0;
	hdr->serial	= 0;
	hdr->type	= RXRPC_PACKET_TYPE_VERSION;
	hdr->flags	= RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED);
	hdr->userStatus	= 0;
	hdr->_rsvd	= 0;

	iov[0].iov_base	= hdr;
	iov[0].iov_len	= sizeof(*hdr);
	iov[1].iov_base	= (char *)rxrpc_version_string;
	iov[1].iov_len	= sizeof(rxrpc_version_string);

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

	_proto("Tx VERSION (reply)");

	ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
	if (ret < 0)
		_debug("sendmsg failed: %d", ret);

	_leave("");
}

/*
 * Process event packets targetted at a local endpoint.
 */
static void rxrpc_process_local_events(struct work_struct *work)
{
	struct rxrpc_local *local = container_of(work, struct rxrpc_local, event_processor);
	struct sk_buff *skb;
	char v;

	_enter("");

	atomic_inc(&local->usage);
	
	while ((skb = skb_dequeue(&local->event_queue))) {
		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

		kdebug("{%d},{%u}", local->debug_id, sp->hdr.type);

		switch (sp->hdr.type) {
		case RXRPC_PACKET_TYPE_VERSION:
			if (skb_copy_bits(skb, 0, &v, 1) < 0)
				return;
			_proto("Rx VERSION { %02x }", v);
			if (v == 0)
				rxrpc_send_version_request(local, &sp->hdr, skb);
			break;

		default:
			/* Just ignore anything we don't understand */
			break;
		}

		rxrpc_put_local(local);
		rxrpc_free_skb(skb);
	}

	rxrpc_put_local(local);
	_leave("");
}