mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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: David Howells <dhowells@redhat.com>
This commit is contained in:
		
							parent
							
								
									bfd4e9562c
								
							
						
					
					
						commit
						44ba06987c
					
				
					 4 changed files with 124 additions and 2 deletions
				
			
		| 
						 | 
					@ -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 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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("");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue