linux/net/sunrpc/xprtsock.c

// SPDX-License-Identifier: GPL-2.0
/*
 * linux/net/sunrpc/xprtsock.c
 *
 * Client-side transport implementation for sockets.
 *
 * TCP callback races fixes (C) 1998 Red Hat
 * TCP send fixes (C) 1998 Red Hat
 * TCP NFS related read + write fixes
 *  (C) 1999 Dave Airlie, University of Limerick, Ireland <[email protected]>
 *
 * Rewrite of larges part of the code in order to stabilize TCP stuff.
 * Fix behaviour when socket buffer is full.
 *  (C) 1999 Trond Myklebust <[email protected]>
 *
 * IP socket transport implementation, (C) 2005 Chuck Lever <[email protected]>
 *
 * IPv6 support contributed by Gilles Quillard, Bull Open Source, 2005.
 *   <[email protected]>
 */

#include <linux/types.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/capability.h>
#include <linux/pagemap.h>
#include <linux/errno.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/net.h>
#include <linux/mm.h>
#include <linux/un.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/addr.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/xprtsock.h>
#include <linux/file.h>
#ifdef CONFIG_SUNRPC_BACKCHANNEL
#include <linux/sunrpc/bc_xprt.h>
#endif

#include <net/sock.h>
#include <net/checksum.h>
#include <net/udp.h>
#include <net/tcp.h>
#include <net/tls_prot.h>
#include <net/handshake.h>

#include <linux/bvec.h>
#include <linux/highmem.h>
#include <linux/uio.h>
#include <linux/sched/mm.h>

#include <trace/events/sock.h>
#include <trace/events/sunrpc.h>

#include "socklib.h"
#include "sunrpc.h"

static void xs_close(struct rpc_xprt *xprt);
static void xs_reset_srcport(struct sock_xprt *transport);
static void xs_set_srcport(struct sock_xprt *transport, struct socket *sock);
static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
		struct socket *sock);

/*
 * xprtsock tunables
 */
static unsigned int xprt_udp_slot_table_entries =;
static unsigned int xprt_tcp_slot_table_entries =;
static unsigned int xprt_max_tcp_slot_table_entries =;

static unsigned int xprt_min_resvport =;
static unsigned int xprt_max_resvport =;

#define XS_TCP_LINGER_TO
static unsigned int xs_tcp_fin_timeout __read_mostly =;

/*
 * We can register our own files under /proc/sys/sunrpc by
 * calling register_sysctl() again.  The files in that
 * directory become the union of all files registered there.
 *
 * We simply need to make sure that we don't collide with
 * someone else's file names!
 */

static unsigned int min_slot_table_size =;
static unsigned int max_slot_table_size =;
static unsigned int max_tcp_slot_table_limit =;
static unsigned int xprt_min_resvport_limit =;
static unsigned int xprt_max_resvport_limit =;

static struct ctl_table_header *sunrpc_table_header;

static struct xprt_class xs_local_transport;
static struct xprt_class xs_udp_transport;
static struct xprt_class xs_tcp_transport;
static struct xprt_class xs_tcp_tls_transport;
static struct xprt_class xs_bc_tcp_transport;

/*
 * FIXME: changing the UDP slot table size should also resize the UDP
 *        socket buffers for existing UDP transports
 */
static struct ctl_table xs_tunables_table[] =;

/*
 * Wait duration for a reply from the RPC portmapper.
 */
#define XS_BIND_TO

/*
 * Delay if a UDP socket connect error occurs.  This is most likely some
 * kind of resource problem on the local host.
 */
#define XS_UDP_REEST_TO

/*
 * The reestablish timeout allows clients to delay for a bit before attempting
 * to reconnect to a server that just dropped our connection.
 *
 * We implement an exponential backoff when trying to reestablish a TCP
 * transport connection with the server.  Some servers like to drop a TCP
 * connection when they are overworked, so we start with a short timeout and
 * increase over time if the server is down or not responding.
 */
#define XS_TCP_INIT_REEST_TO

/*
 * TCP idle timeout; client drops the transport socket if it is idle
 * for this long.  Note that we also timeout UDP sockets to prevent
 * holding port numbers when there is no RPC traffic.
 */
#define XS_IDLE_DISC_TO

/*
 * TLS handshake timeout.
 */
#define XS_TLS_HANDSHAKE_TO

#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# undef  RPC_DEBUG_DATA
#define RPCDBG_FACILITY
#endif

#ifdef RPC_DEBUG_DATA
static void xs_pktdump(char *msg, u32 *packet, unsigned int count)
{
	u8 *buf = (u8 *) packet;
	int j;

	dprintk("RPC:       %s\n", msg);
	for (j = 0; j < count && j < 128; j += 4) {
		if (!(j & 31)) {
			if (j)
				dprintk("\n");
			dprintk("0x%04x ", j);
		}
		dprintk("%02x%02x%02x%02x ",
			buf[j], buf[j+1], buf[j+2], buf[j+3]);
	}
	dprintk("\n");
}
#else
static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count)
{}
#endif

static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
{}

static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
{}

static inline struct sockaddr_un *xs_addr_un(struct rpc_xprt *xprt)
{}

static inline struct sockaddr_in *xs_addr_in(struct rpc_xprt *xprt)
{}

static inline struct sockaddr_in6 *xs_addr_in6(struct rpc_xprt *xprt)
{}

static void xs_format_common_peer_addresses(struct rpc_xprt *xprt)
{}

static void xs_format_common_peer_ports(struct rpc_xprt *xprt)
{}

static void xs_format_peer_addresses(struct rpc_xprt *xprt,
				     const char *protocol,
				     const char *netid)
{}

static void xs_update_peer_port(struct rpc_xprt *xprt)
{}

static void xs_free_peer_addresses(struct rpc_xprt *xprt)
{}

static size_t
xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp)
{}

static int
xs_sock_process_cmsg(struct socket *sock, struct msghdr *msg,
		     struct cmsghdr *cmsg, int ret)
{}

static int
xs_sock_recv_cmsg(struct socket *sock, struct msghdr *msg, int flags)
{}

static ssize_t
xs_sock_recvmsg(struct socket *sock, struct msghdr *msg, int flags, size_t seek)
{}

static ssize_t
xs_read_kvec(struct socket *sock, struct msghdr *msg, int flags,
		struct kvec *kvec, size_t count, size_t seek)
{}

static ssize_t
xs_read_bvec(struct socket *sock, struct msghdr *msg, int flags,
		struct bio_vec *bvec, unsigned long nr, size_t count,
		size_t seek)
{}

static ssize_t
xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
		size_t count)
{}

#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
static void
xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
{
	struct bvec_iter bi = {
		.bi_size = count,
	};
	struct bio_vec bv;

	bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
	for_each_bvec(bv, bvec, bi, bi)
		flush_dcache_page(bv.bv_page);
}
#else
static inline void
xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
{}
#endif

static ssize_t
xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
		struct xdr_buf *buf, size_t count, size_t seek, size_t *read)
{}

static void
xs_read_header(struct sock_xprt *transport, struct xdr_buf *buf)
{}

static bool
xs_read_stream_request_done(struct sock_xprt *transport)
{}

static void
xs_read_stream_check_eor(struct sock_xprt *transport,
		struct msghdr *msg)
{}

static ssize_t
xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg,
		int flags, struct rpc_rqst *req)
{}

static size_t
xs_read_stream_headersize(bool isfrag)
{}

static ssize_t
xs_read_stream_header(struct sock_xprt *transport, struct msghdr *msg,
		int flags, size_t want, size_t seek)
{}

#if defined(CONFIG_SUNRPC_BACKCHANNEL)
static ssize_t
xs_read_stream_call(struct sock_xprt *transport, struct msghdr *msg, int flags)
{}
#else /* CONFIG_SUNRPC_BACKCHANNEL */
static ssize_t
xs_read_stream_call(struct sock_xprt *transport, struct msghdr *msg, int flags)
{
	return -ESHUTDOWN;
}
#endif /* CONFIG_SUNRPC_BACKCHANNEL */

static ssize_t
xs_read_stream_reply(struct sock_xprt *transport, struct msghdr *msg, int flags)
{}

static ssize_t
xs_read_stream(struct sock_xprt *transport, int flags)
{}

static __poll_t xs_poll_socket(struct sock_xprt *transport)
{}

static bool xs_poll_socket_readable(struct sock_xprt *transport)
{}

static void xs_poll_check_readable(struct sock_xprt *transport)
{}

static void xs_stream_data_receive(struct sock_xprt *transport)
{}

static void xs_stream_data_receive_workfn(struct work_struct *work)
{}

static void
xs_stream_reset_connect(struct sock_xprt *transport)
{}

static void
xs_stream_start_connect(struct sock_xprt *transport)
{}

#define XS_SENDMSG_FLAGS

/**
 * xs_nospace - handle transmit was incomplete
 * @req: pointer to RPC request
 * @transport: pointer to struct sock_xprt
 *
 */
static int xs_nospace(struct rpc_rqst *req, struct sock_xprt *transport)
{}

static int xs_sock_nospace(struct rpc_rqst *req)
{}

static int xs_stream_nospace(struct rpc_rqst *req, bool vm_wait)
{}

static int xs_stream_prepare_request(struct rpc_rqst *req, struct xdr_buf *buf)
{}

static void xs_stream_abort_send_request(struct rpc_rqst *req)
{}

/*
 * Determine if the previous message in the stream was aborted before it
 * could complete transmission.
 */
static bool
xs_send_request_was_aborted(struct sock_xprt *transport, struct rpc_rqst *req)
{}

/*
 * Return the stream record marker field for a record of length < 2^31-1
 */
static rpc_fraghdr
xs_stream_record_marker(struct xdr_buf *xdr)
{}

/**
 * xs_local_send_request - write an RPC request to an AF_LOCAL socket
 * @req: pointer to RPC request
 *
 * Return values:
 *        0:	The request has been sent
 *   EAGAIN:	The socket was blocked, please call again later to
 *		complete the request
 * ENOTCONN:	Caller needs to invoke connect logic then call again
 *    other:	Some other error occurred, the request was not sent
 */
static int xs_local_send_request(struct rpc_rqst *req)
{}

/**
 * xs_udp_send_request - write an RPC request to a UDP socket
 * @req: pointer to RPC request
 *
 * Return values:
 *        0:	The request has been sent
 *   EAGAIN:	The socket was blocked, please call again later to
 *		complete the request
 * ENOTCONN:	Caller needs to invoke connect logic then call again
 *    other:	Some other error occurred, the request was not sent
 */
static int xs_udp_send_request(struct rpc_rqst *req)
{}

/**
 * xs_tcp_send_request - write an RPC request to a TCP socket
 * @req: pointer to RPC request
 *
 * Return values:
 *        0:	The request has been sent
 *   EAGAIN:	The socket was blocked, please call again later to
 *		complete the request
 * ENOTCONN:	Caller needs to invoke connect logic then call again
 *    other:	Some other error occurred, the request was not sent
 *
 * XXX: In the case of soft timeouts, should we eventually give up
 *	if sendmsg is not able to make progress?
 */
static int xs_tcp_send_request(struct rpc_rqst *req)
{}

static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
{}

static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
{}

static void xs_sock_reset_state_flags(struct rpc_xprt *xprt)
{}

static void xs_run_error_worker(struct sock_xprt *transport, unsigned int nr)
{}

static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
{}

/**
 * xs_error_report - callback to handle TCP socket state errors
 * @sk: socket
 *
 * Note: we don't call sock_error() since there may be a rpc_task
 * using the socket, and so we don't want to clear sk->sk_err.
 */
static void xs_error_report(struct sock *sk)
{}

static void xs_reset_transport(struct sock_xprt *transport)
{}

/**
 * xs_close - close a socket
 * @xprt: transport
 *
 * This is used when all requests are complete; ie, no DRC state remains
 * on the server we want to save.
 *
 * The caller _must_ be holding XPRT_LOCKED in order to avoid issues with
 * xs_reset_transport() zeroing the socket from underneath a writer.
 */
static void xs_close(struct rpc_xprt *xprt)
{}

static void xs_inject_disconnect(struct rpc_xprt *xprt)
{}

static void xs_xprt_free(struct rpc_xprt *xprt)
{}

/**
 * xs_destroy - prepare to shutdown a transport
 * @xprt: doomed transport
 *
 */
static void xs_destroy(struct rpc_xprt *xprt)
{}

/**
 * xs_udp_data_read_skb - receive callback for UDP sockets
 * @xprt: transport
 * @sk: socket
 * @skb: skbuff
 *
 */
static void xs_udp_data_read_skb(struct rpc_xprt *xprt,
		struct sock *sk,
		struct sk_buff *skb)
{}

static void xs_udp_data_receive(struct sock_xprt *transport)
{}

static void xs_udp_data_receive_workfn(struct work_struct *work)
{}

/**
 * xs_data_ready - "data ready" callback for sockets
 * @sk: socket with data to read
 *
 */
static void xs_data_ready(struct sock *sk)
{}

/*
 * Helper function to force a TCP close if the server is sending
 * junk and/or it has put us in CLOSE_WAIT
 */
static void xs_tcp_force_close(struct rpc_xprt *xprt)
{}

#if defined(CONFIG_SUNRPC_BACKCHANNEL)
static size_t xs_tcp_bc_maxpayload(struct rpc_xprt *xprt)
{}
#endif /* CONFIG_SUNRPC_BACKCHANNEL */

/**
 * xs_local_state_change - callback to handle AF_LOCAL socket state changes
 * @sk: socket whose state has changed
 *
 */
static void xs_local_state_change(struct sock *sk)
{}

/**
 * xs_tcp_state_change - callback to handle TCP socket state changes
 * @sk: socket whose state has changed
 *
 */
static void xs_tcp_state_change(struct sock *sk)
{}

static void xs_write_space(struct sock *sk)
{}

/**
 * xs_udp_write_space - callback invoked when socket buffer space
 *                             becomes available
 * @sk: socket whose state has changed
 *
 * Called when more output buffer space is available for this socket.
 * We try not to wake our writers until they can make "significant"
 * progress, otherwise we'll waste resources thrashing kernel_sendmsg
 * with a bunch of small requests.
 */
static void xs_udp_write_space(struct sock *sk)
{}

/**
 * xs_tcp_write_space - callback invoked when socket buffer space
 *                             becomes available
 * @sk: socket whose state has changed
 *
 * Called when more output buffer space is available for this socket.
 * We try not to wake our writers until they can make "significant"
 * progress, otherwise we'll waste resources thrashing kernel_sendmsg
 * with a bunch of small requests.
 */
static void xs_tcp_write_space(struct sock *sk)
{}

static void xs_udp_do_set_buffer_size(struct rpc_xprt *xprt)
{}

/**
 * xs_udp_set_buffer_size - set send and receive limits
 * @xprt: generic transport
 * @sndsize: requested size of send buffer, in bytes
 * @rcvsize: requested size of receive buffer, in bytes
 *
 * Set socket send and receive buffer size limits.
 */
static void xs_udp_set_buffer_size(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize)
{}

/**
 * xs_udp_timer - called when a retransmit timeout occurs on a UDP transport
 * @xprt: controlling transport
 * @task: task that timed out
 *
 * Adjust the congestion window after a retransmit timeout has occurred.
 */
static void xs_udp_timer(struct rpc_xprt *xprt, struct rpc_task *task)
{}

static int xs_get_random_port(void)
{}

static unsigned short xs_sock_getport(struct socket *sock)
{}

/**
 * xs_set_port - reset the port number in the remote endpoint address
 * @xprt: generic transport
 * @port: new port number
 *
 */
static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
{}

static void xs_reset_srcport(struct sock_xprt *transport)
{}

static void xs_set_srcport(struct sock_xprt *transport, struct socket *sock)
{}

static int xs_get_srcport(struct sock_xprt *transport)
{}

static unsigned short xs_sock_srcport(struct rpc_xprt *xprt)
{}

static int xs_sock_srcaddr(struct rpc_xprt *xprt, char *buf, size_t buflen)
{}

static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port)
{}
static int xs_bind(struct sock_xprt *transport, struct socket *sock)
{}

/*
 * We don't support autobind on AF_LOCAL sockets
 */
static void xs_local_rpcbind(struct rpc_task *task)
{}

static void xs_local_set_port(struct rpc_xprt *xprt, unsigned short port)
{}

#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key xs_key[3];
static struct lock_class_key xs_slock_key[3];

static inline void xs_reclassify_socketu(struct socket *sock)
{}

static inline void xs_reclassify_socket4(struct socket *sock)
{}

static inline void xs_reclassify_socket6(struct socket *sock)
{}

static inline void xs_reclassify_socket(int family, struct socket *sock)
{}
#else
static inline void xs_reclassify_socket(int family, struct socket *sock)
{
}
#endif

static void xs_dummy_setup_socket(struct work_struct *work)
{}

static struct socket *xs_create_sock(struct rpc_xprt *xprt,
		struct sock_xprt *transport, int family, int type,
		int protocol, bool reuseport)
{}

static int xs_local_finish_connecting(struct rpc_xprt *xprt,
				      struct socket *sock)
{}

/**
 * xs_local_setup_socket - create AF_LOCAL socket, connect to a local endpoint
 * @transport: socket transport to connect
 */
static int xs_local_setup_socket(struct sock_xprt *transport)
{}

static void xs_local_connect(struct rpc_xprt *xprt, struct rpc_task *task)
{}

#if IS_ENABLED(CONFIG_SUNRPC_SWAP)
/*
 * Note that this should be called with XPRT_LOCKED held, or recv_mutex
 * held, or when we otherwise know that we have exclusive access to the
 * socket, to guard against races with xs_reset_transport.
 */
static void xs_set_memalloc(struct rpc_xprt *xprt)
{}

/**
 * xs_enable_swap - Tag this transport as being used for swap.
 * @xprt: transport to tag
 *
 * Take a reference to this transport on behalf of the rpc_clnt, and
 * optionally mark it for swapping if it wasn't already.
 */
static int
xs_enable_swap(struct rpc_xprt *xprt)
{}

/**
 * xs_disable_swap - Untag this transport as being used for swap.
 * @xprt: transport to tag
 *
 * Drop a "swapper" reference to this xprt on behalf of the rpc_clnt. If the
 * swapper refcount goes to 0, untag the socket as a memalloc socket.
 */
static void
xs_disable_swap(struct rpc_xprt *xprt)
{}
#else
static void xs_set_memalloc(struct rpc_xprt *xprt)
{
}

static int
xs_enable_swap(struct rpc_xprt *xprt)
{
	return -EINVAL;
}

static void
xs_disable_swap(struct rpc_xprt *xprt)
{
}
#endif

static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
{}

static void xs_udp_setup_socket(struct work_struct *work)
{}

/**
 * xs_tcp_shutdown - gracefully shut down a TCP socket
 * @xprt: transport
 *
 * Initiates a graceful shutdown of the TCP socket by calling the
 * equivalent of shutdown(SHUT_RDWR);
 */
static void xs_tcp_shutdown(struct rpc_xprt *xprt)
{}

static void xs_tcp_set_socket_timeouts(struct rpc_xprt *xprt,
		struct socket *sock)
{}

static void xs_tcp_do_set_connect_timeout(struct rpc_xprt *xprt,
					  unsigned long connect_timeout)
{}

static void xs_tcp_set_connect_timeout(struct rpc_xprt *xprt,
		unsigned long connect_timeout,
		unsigned long reconnect_timeout)
{}

static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
{}

/**
 * xs_tcp_setup_socket - create a TCP socket and connect to a remote endpoint
 * @work: queued work item
 *
 * Invoked by a work queue tasklet.
 */
static void xs_tcp_setup_socket(struct work_struct *work)
{}

/*
 * Transfer the connected socket to @upper_transport, then mark that
 * xprt CONNECTED.
 */
static int xs_tcp_tls_finish_connecting(struct rpc_xprt *lower_xprt,
					struct sock_xprt *upper_transport)
{}

/**
 * xs_tls_handshake_done - TLS handshake completion handler
 * @data: address of xprt to wake
 * @status: status of handshake
 * @peerid: serial number of key containing the remote's identity
 *
 */
static void xs_tls_handshake_done(void *data, int status, key_serial_t peerid)
{}

static int xs_tls_handshake_sync(struct rpc_xprt *lower_xprt, struct xprtsec_parms *xprtsec)
{}

/**
 * xs_tcp_tls_setup_socket - establish a TLS session on a TCP socket
 * @work: queued work item
 *
 * Invoked by a work queue tasklet.
 *
 * For RPC-with-TLS, there is a two-stage connection process.
 *
 * The "upper-layer xprt" is visible to the RPC consumer. Once it has
 * been marked connected, the consumer knows that a TCP connection and
 * a TLS session have been established.
 *
 * A "lower-layer xprt", created in this function, handles the mechanics
 * of connecting the TCP socket, performing the RPC_AUTH_TLS probe, and
 * then driving the TLS handshake. Once all that is complete, the upper
 * layer xprt is marked connected.
 */
static void xs_tcp_tls_setup_socket(struct work_struct *work)
{}

/**
 * xs_connect - connect a socket to a remote endpoint
 * @xprt: pointer to transport structure
 * @task: address of RPC task that manages state of connect request
 *
 * TCP: If the remote end dropped the connection, delay reconnecting.
 *
 * UDP socket connects are synchronous, but we use a work queue anyway
 * to guarantee that even unprivileged user processes can set up a
 * socket on a privileged port.
 *
 * If a UDP socket connect fails, the delay behavior here prevents
 * retry floods (hard mounts).
 */
static void xs_connect(struct rpc_xprt *xprt, struct rpc_task *task)
{}

static void xs_wake_disconnect(struct sock_xprt *transport)
{}

static void xs_wake_write(struct sock_xprt *transport)
{}

static void xs_wake_error(struct sock_xprt *transport)
{}

static void xs_wake_pending(struct sock_xprt *transport)
{}

static void xs_error_handle(struct work_struct *work)
{}

/**
 * xs_local_print_stats - display AF_LOCAL socket-specific stats
 * @xprt: rpc_xprt struct containing statistics
 * @seq: output file
 *
 */
static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{}

/**
 * xs_udp_print_stats - display UDP socket-specific stats
 * @xprt: rpc_xprt struct containing statistics
 * @seq: output file
 *
 */
static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{}

/**
 * xs_tcp_print_stats - display TCP socket-specific stats
 * @xprt: rpc_xprt struct containing statistics
 * @seq: output file
 *
 */
static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
{}

/*
 * Allocate a bunch of pages for a scratch buffer for the rpc code. The reason
 * we allocate pages instead doing a kmalloc like rpc_malloc is because we want
 * to use the server side send routines.
 */
static int bc_malloc(struct rpc_task *task)
{}

/*
 * Free the space allocated in the bc_alloc routine
 */
static void bc_free(struct rpc_task *task)
{}

static int bc_sendto(struct rpc_rqst *req)
{}

/**
 * bc_send_request - Send a backchannel Call on a TCP socket
 * @req: rpc_rqst containing Call message to be sent
 *
 * xpt_mutex ensures @rqstp's whole message is written to the socket
 * without interruption.
 *
 * Return values:
 *   %0 if the message was sent successfully
 *   %ENOTCONN if the message was not sent
 */
static int bc_send_request(struct rpc_rqst *req)
{}

static void bc_close(struct rpc_xprt *xprt)
{}

static void bc_destroy(struct rpc_xprt *xprt)
{}

static const struct rpc_xprt_ops xs_local_ops =;

static const struct rpc_xprt_ops xs_udp_ops =;

static const struct rpc_xprt_ops xs_tcp_ops =;

/*
 * The rpc_xprt_ops for the server backchannel
 */

static const struct rpc_xprt_ops bc_tcp_ops =;

static int xs_init_anyaddr(const int family, struct sockaddr *sap)
{}

static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
				      unsigned int slot_table_size,
				      unsigned int max_slot_table_size)
{}

static const struct rpc_timeout xs_local_default_timeout =;

/**
 * xs_setup_local - Set up transport to use an AF_LOCAL socket
 * @args: rpc transport creation arguments
 *
 * AF_LOCAL is a "tpi_cots_ord" transport, just like TCP
 */
static struct rpc_xprt *xs_setup_local(struct xprt_create *args)
{}

static const struct rpc_timeout xs_udp_default_timeout =;

/**
 * xs_setup_udp - Set up transport to use a UDP socket
 * @args: rpc transport creation arguments
 *
 */
static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
{}

static const struct rpc_timeout xs_tcp_default_timeout =;

/**
 * xs_setup_tcp - Set up transport to use a TCP socket
 * @args: rpc transport creation arguments
 *
 */
static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
{}

/**
 * xs_setup_tcp_tls - Set up transport to use a TCP with TLS
 * @args: rpc transport creation arguments
 *
 */
static struct rpc_xprt *xs_setup_tcp_tls(struct xprt_create *args)
{}

/**
 * xs_setup_bc_tcp - Set up transport to use a TCP backchannel socket
 * @args: rpc transport creation arguments
 *
 */
static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
{}

static struct xprt_class	xs_local_transport =;

static struct xprt_class	xs_udp_transport =;

static struct xprt_class	xs_tcp_transport =;

static struct xprt_class	xs_tcp_tls_transport =;

static struct xprt_class	xs_bc_tcp_transport =;

/**
 * init_socket_xprt - set up xprtsock's sysctls, register with RPC client
 *
 */
int init_socket_xprt(void)
{}

/**
 * cleanup_socket_xprt - remove xprtsock's sysctls, unregister
 *
 */
void cleanup_socket_xprt(void)
{}

static int param_set_portnr(const char *val, const struct kernel_param *kp)
{}

static const struct kernel_param_ops param_ops_portnr =;

#define param_check_portnr(name, p)

module_param_named(min_resvport, xprt_min_resvport, portnr, 0644);
module_param_named(max_resvport, xprt_max_resvport, portnr, 0644);

static int param_set_slot_table_size(const char *val,
				     const struct kernel_param *kp)
{}

static const struct kernel_param_ops param_ops_slot_table_size =;

#define param_check_slot_table_size(name, p)

static int param_set_max_slot_table_size(const char *val,
				     const struct kernel_param *kp)
{}

static const struct kernel_param_ops param_ops_max_slot_table_size =;

#define param_check_max_slot_table_size(name, p)

module_param_named(tcp_slot_table_entries, xprt_tcp_slot_table_entries,
		   slot_table_size, 0644);
module_param_named(tcp_max_slot_table_entries, xprt_max_tcp_slot_table_entries,
		   max_slot_table_size, 0644);
module_param_named(udp_slot_table_entries, xprt_udp_slot_table_entries,
		   slot_table_size, 0644);