2005-04-17 02:20:36 +04:00
/*
* linux / net / sunrpc / svcsock . c
*
* These are the RPC server socket internals .
*
* The server scheduling algorithm does not always distribute the load
* evenly when servicing a single client . May need to modify the
2007-12-31 06:07:57 +03:00
* svc_xprt_enqueue procedure . . .
2005-04-17 02:20:36 +04:00
*
* TCP support is largely untested and may be a little slow . The problem
* is that we currently do two separate recvfrom ' s , one for the 4 - byte
* record length , and the second for the actual record . This could possibly
* be improved by always reading a minimum size of around 100 bytes and
* tucking any superfluous bytes away in a temporary store . Still , that
* leaves write requests out in the rain . An alternative may be to peek at
* the first skb in the queue , and if it matches the next TCP sequence
* number , to extract the record marker . Yuck .
*
* Copyright ( C ) 1995 , 1996 Olaf Kirch < okir @ monad . swb . de >
*/
2007-08-29 02:50:33 +04:00
# include <linux/kernel.h>
2005-04-17 02:20:36 +04:00
# include <linux/sched.h>
2011-05-27 17:12:25 +04:00
# include <linux/module.h>
2005-04-17 02:20:36 +04:00
# include <linux/errno.h>
# include <linux/fcntl.h>
# include <linux/net.h>
# include <linux/in.h>
# include <linux/inet.h>
# include <linux/udp.h>
2005-08-10 07:20:07 +04:00
# include <linux/tcp.h>
2005-04-17 02:20:36 +04:00
# include <linux/unistd.h>
# include <linux/slab.h>
# include <linux/netdevice.h>
# include <linux/skbuff.h>
2006-10-02 13:17:48 +04:00
# include <linux/file.h>
2006-12-07 07:34:23 +03:00
# include <linux/freezer.h>
2005-04-17 02:20:36 +04:00
# include <net/sock.h>
# include <net/checksum.h>
# include <net/ip.h>
2007-02-12 11:53:36 +03:00
# include <net/ipv6.h>
2008-04-14 20:27:01 +04:00
# include <net/tcp.h>
2005-08-10 07:08:28 +04:00
# include <net/tcp_states.h>
2005-04-17 02:20:36 +04:00
# include <asm/uaccess.h>
# include <asm/ioctls.h>
2012-06-27 04:23:44 +04:00
# include <trace/events/skb.h>
2005-04-17 02:20:36 +04:00
# include <linux/sunrpc/types.h>
2007-02-12 11:53:32 +03:00
# include <linux/sunrpc/clnt.h>
2005-04-17 02:20:36 +04:00
# include <linux/sunrpc/xdr.h>
2008-04-14 20:27:30 +04:00
# include <linux/sunrpc/msg_prot.h>
2005-04-17 02:20:36 +04:00
# include <linux/sunrpc/svcsock.h>
# include <linux/sunrpc/stats.h>
2009-09-10 18:32:28 +04:00
# include <linux/sunrpc/xprt.h>
2005-04-17 02:20:36 +04:00
2011-06-21 04:54:51 +04:00
# include "sunrpc.h"
2007-12-31 06:07:17 +03:00
# define RPCDBG_FACILITY RPCDBG_SVCXPRT
2005-04-17 02:20:36 +04:00
static struct svc_sock * svc_setup_socket ( struct svc_serv * , struct socket * ,
2012-08-14 01:46:17 +04:00
int flags ) ;
2005-04-17 02:20:36 +04:00
static int svc_udp_recvfrom ( struct svc_rqst * ) ;
static int svc_udp_sendto ( struct svc_rqst * ) ;
2007-12-31 06:07:27 +03:00
static void svc_sock_detach ( struct svc_xprt * ) ;
2008-12-24 00:30:11 +03:00
static void svc_tcp_sock_detach ( struct svc_xprt * ) ;
2007-12-31 06:07:27 +03:00
static void svc_sock_free ( struct svc_xprt * ) ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:07:42 +03:00
static struct svc_xprt * svc_create_socket ( struct svc_serv * , int ,
2010-09-29 16:04:18 +04:00
struct net * , struct sockaddr * ,
int , int ) ;
2011-07-14 03:20:49 +04:00
# if defined(CONFIG_SUNRPC_BACKCHANNEL)
2011-01-06 05:04:26 +03:00
static struct svc_xprt * svc_bc_create_socket ( struct svc_serv * , int ,
struct net * , struct sockaddr * ,
int , int ) ;
static void svc_bc_sock_free ( struct svc_xprt * xprt ) ;
2011-07-14 03:20:49 +04:00
# endif /* CONFIG_SUNRPC_BACKCHANNEL */
2011-01-06 05:04:26 +03:00
2006-12-07 07:35:24 +03:00
# ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key svc_key [ 2 ] ;
static struct lock_class_key svc_slock_key [ 2 ] ;
2007-12-31 06:08:27 +03:00
static void svc_reclassify_socket ( struct socket * sock )
2006-12-07 07:35:24 +03:00
{
struct sock * sk = sock - > sk ;
2012-10-23 18:43:39 +04:00
2016-04-08 16:11:27 +03:00
if ( WARN_ON_ONCE ( ! sock_allow_reclassification ( sk ) ) )
2012-10-23 18:43:39 +04:00
return ;
2006-12-07 07:35:24 +03:00
switch ( sk - > sk_family ) {
case AF_INET :
sock_lock_init_class_and_name ( sk , " slock-AF_INET-NFSD " ,
2007-12-31 06:08:08 +03:00
& svc_slock_key [ 0 ] ,
" sk_xprt.xpt_lock-AF_INET-NFSD " ,
& svc_key [ 0 ] ) ;
2006-12-07 07:35:24 +03:00
break ;
case AF_INET6 :
sock_lock_init_class_and_name ( sk , " slock-AF_INET6-NFSD " ,
2007-12-31 06:08:08 +03:00
& svc_slock_key [ 1 ] ,
" sk_xprt.xpt_lock-AF_INET6-NFSD " ,
& svc_key [ 1 ] ) ;
2006-12-07 07:35:24 +03:00
break ;
default :
BUG ( ) ;
}
}
# else
2007-12-31 06:08:27 +03:00
static void svc_reclassify_socket ( struct socket * sock )
2006-12-07 07:35:24 +03:00
{
}
# endif
2005-04-17 02:20:36 +04:00
/*
* Release an skbuff after use
*/
2007-12-31 06:07:25 +03:00
static void svc_release_skb ( struct svc_rqst * rqstp )
2005-04-17 02:20:36 +04:00
{
2007-12-31 06:07:25 +03:00
struct sk_buff * skb = rqstp - > rq_xprt_ctxt ;
2005-04-17 02:20:36 +04:00
if ( skb ) {
2007-12-31 06:08:22 +03:00
struct svc_sock * svsk =
container_of ( rqstp - > rq_xprt , struct svc_sock , sk_xprt ) ;
2007-12-31 06:07:25 +03:00
rqstp - > rq_xprt_ctxt = NULL ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: service %p, releasing skb %p \n " , rqstp , skb ) ;
2009-10-30 08:03:53 +03:00
skb_free_datagram_locked ( svsk - > sk_sk , skb ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-02-12 11:53:36 +03:00
union svc_pktinfo_u {
struct in_pktinfo pkti ;
struct in6_pktinfo pkti6 ;
} ;
2007-04-13 00:35:59 +04:00
# define SVC_PKTINFO_SPACE \
CMSG_SPACE ( sizeof ( union svc_pktinfo_u ) )
2007-02-12 11:53:36 +03:00
static void svc_set_cmsg_data ( struct svc_rqst * rqstp , struct cmsghdr * cmh )
{
2007-12-31 06:08:22 +03:00
struct svc_sock * svsk =
container_of ( rqstp - > rq_xprt , struct svc_sock , sk_xprt ) ;
switch ( svsk - > sk_sk - > sk_family ) {
2007-02-12 11:53:36 +03:00
case AF_INET : {
struct in_pktinfo * pki = CMSG_DATA ( cmh ) ;
cmh - > cmsg_level = SOL_IP ;
cmh - > cmsg_type = IP_PKTINFO ;
pki - > ipi_ifindex = 0 ;
2011-08-30 13:18:41 +04:00
pki - > ipi_spec_dst . s_addr =
svc_daddr_in ( rqstp ) - > sin_addr . s_addr ;
2007-02-12 11:53:36 +03:00
cmh - > cmsg_len = CMSG_LEN ( sizeof ( * pki ) ) ;
}
break ;
2007-03-06 12:42:22 +03:00
2007-02-12 11:53:36 +03:00
case AF_INET6 : {
struct in6_pktinfo * pki = CMSG_DATA ( cmh ) ;
2011-08-30 13:18:41 +04:00
struct sockaddr_in6 * daddr = svc_daddr_in6 ( rqstp ) ;
2007-02-12 11:53:36 +03:00
cmh - > cmsg_level = SOL_IPV6 ;
cmh - > cmsg_type = IPV6_PKTINFO ;
2011-08-30 13:18:41 +04:00
pki - > ipi6_ifindex = daddr - > sin6_scope_id ;
2011-11-21 07:39:03 +04:00
pki - > ipi6_addr = daddr - > sin6_addr ;
2007-02-12 11:53:36 +03:00
cmh - > cmsg_len = CMSG_LEN ( sizeof ( * pki ) ) ;
}
break ;
}
}
2005-04-17 02:20:36 +04:00
/*
2009-09-10 18:32:28 +04:00
* send routine intended to be shared by the fore - and back - channel
2005-04-17 02:20:36 +04:00
*/
2009-09-10 18:32:28 +04:00
int svc_send_common ( struct socket * sock , struct xdr_buf * xdr ,
struct page * headpage , unsigned long headoffset ,
struct page * tailpage , unsigned long tailoffset )
2005-04-17 02:20:36 +04:00
{
int result ;
int size ;
struct page * * ppage = xdr - > pages ;
size_t base = xdr - > page_base ;
unsigned int pglen = xdr - > page_len ;
2015-10-07 20:54:42 +03:00
unsigned int flags = MSG_MORE | MSG_SENDPAGE_NOTLAST ;
2009-09-10 18:32:28 +04:00
int slen ;
int len = 0 ;
2005-04-17 02:20:36 +04:00
slen = xdr - > len ;
/* send head */
if ( slen = = xdr - > head [ 0 ] . iov_len )
flags = 0 ;
2009-09-10 18:32:28 +04:00
len = kernel_sendpage ( sock , headpage , headoffset ,
2006-10-04 13:15:46 +04:00
xdr - > head [ 0 ] . iov_len , flags ) ;
2005-04-17 02:20:36 +04:00
if ( len ! = xdr - > head [ 0 ] . iov_len )
goto out ;
slen - = xdr - > head [ 0 ] . iov_len ;
if ( slen = = 0 )
goto out ;
/* send page data */
size = PAGE_SIZE - base < pglen ? PAGE_SIZE - base : pglen ;
while ( pglen > 0 ) {
if ( slen = = size )
flags = 0 ;
2006-08-08 07:58:01 +04:00
result = kernel_sendpage ( sock , * ppage , base , size , flags ) ;
2005-04-17 02:20:36 +04:00
if ( result > 0 )
len + = result ;
if ( result ! = size )
goto out ;
slen - = size ;
pglen - = size ;
size = PAGE_SIZE < pglen ? PAGE_SIZE : pglen ;
base = 0 ;
ppage + + ;
}
2009-09-10 18:32:28 +04:00
2005-04-17 02:20:36 +04:00
/* send tail */
if ( xdr - > tail [ 0 ] . iov_len ) {
2009-09-10 18:32:28 +04:00
result = kernel_sendpage ( sock , tailpage , tailoffset ,
xdr - > tail [ 0 ] . iov_len , 0 ) ;
2005-04-17 02:20:36 +04:00
if ( result > 0 )
len + = result ;
}
2009-09-10 18:32:28 +04:00
out :
return len ;
}
/*
* Generic sendto routine
*/
static int svc_sendto ( struct svc_rqst * rqstp , struct xdr_buf * xdr )
{
struct svc_sock * svsk =
container_of ( rqstp - > rq_xprt , struct svc_sock , sk_xprt ) ;
struct socket * sock = svsk - > sk_sock ;
union {
struct cmsghdr hdr ;
long all [ SVC_PKTINFO_SPACE / sizeof ( long ) ] ;
} buffer ;
struct cmsghdr * cmh = & buffer . hdr ;
int len = 0 ;
unsigned long tailoff ;
unsigned long headoff ;
RPC_IFDEBUG ( char buf [ RPC_MAX_ADDRBUFLEN ] ) ;
if ( rqstp - > rq_prot = = IPPROTO_UDP ) {
struct msghdr msg = {
. msg_name = & rqstp - > rq_addr ,
. msg_namelen = rqstp - > rq_addrlen ,
. msg_control = cmh ,
. msg_controllen = sizeof ( buffer ) ,
. msg_flags = MSG_MORE ,
} ;
svc_set_cmsg_data ( rqstp , cmh ) ;
2014-12-11 08:02:50 +03:00
if ( sock_sendmsg ( sock , & msg ) < 0 )
2009-09-10 18:32:28 +04:00
goto out ;
}
tailoff = ( ( unsigned long ) xdr - > tail [ 0 ] . iov_base ) & ( PAGE_SIZE - 1 ) ;
headoff = 0 ;
len = svc_send_common ( sock , xdr , rqstp - > rq_respages [ 0 ] , headoff ,
rqstp - > rq_respages [ 0 ] , tailoff ) ;
2005-04-17 02:20:36 +04:00
out :
2007-02-12 11:53:32 +03:00
dprintk ( " svc: socket %p sendto([%p %Zu... ], %d) = %d (addr %s) \n " ,
2007-12-31 06:08:22 +03:00
svsk , xdr - > head [ 0 ] . iov_base , xdr - > head [ 0 ] . iov_len ,
2007-02-12 11:53:32 +03:00
xdr - > len , len , svc_print_addr ( rqstp , buf , sizeof ( buf ) ) ) ;
2005-04-17 02:20:36 +04:00
return len ;
}
2006-10-02 13:17:47 +04:00
/*
* Report socket names for nfsdfs
*/
2009-04-24 03:32:48 +04:00
static int svc_one_sock_name ( struct svc_sock * svsk , char * buf , int remaining )
2006-10-02 13:17:47 +04:00
{
2009-04-24 03:33:03 +04:00
const struct sock * sk = svsk - > sk_sk ;
const char * proto_name = sk - > sk_protocol = = IPPROTO_UDP ?
" udp " : " tcp " ;
2006-10-02 13:17:47 +04:00
int len ;
2009-04-24 03:33:03 +04:00
switch ( sk - > sk_family ) {
2009-04-24 03:32:48 +04:00
case PF_INET :
len = snprintf ( buf , remaining , " ipv4 %s %pI4 %d \n " ,
2009-04-24 03:33:03 +04:00
proto_name ,
2009-10-15 10:30:45 +04:00
& inet_sk ( sk ) - > inet_rcv_saddr ,
inet_sk ( sk ) - > inet_num ) ;
2006-10-02 13:17:47 +04:00
break ;
2013-10-09 14:05:48 +04:00
# if IS_ENABLED(CONFIG_IPV6)
2009-04-24 03:32:55 +04:00
case PF_INET6 :
len = snprintf ( buf , remaining , " ipv6 %s %pI6 %d \n " ,
2009-04-24 03:33:03 +04:00
proto_name ,
ipv6: make lookups simpler and faster
TCP listener refactoring, part 4 :
To speed up inet lookups, we moved IPv4 addresses from inet to struct
sock_common
Now is time to do the same for IPv6, because it permits us to have fast
lookups for all kind of sockets, including upcoming SYN_RECV.
Getting IPv6 addresses in TCP lookups currently requires two extra cache
lines, plus a dereference (and memory stall).
inet6_sk(sk) does the dereference of inet_sk(__sk)->pinet6
This patch is way bigger than its IPv4 counter part, because for IPv4,
we could add aliases (inet_daddr, inet_rcv_saddr), while on IPv6,
it's not doable easily.
inet6_sk(sk)->daddr becomes sk->sk_v6_daddr
inet6_sk(sk)->rcv_saddr becomes sk->sk_v6_rcv_saddr
And timewait socket also have tw->tw_v6_daddr & tw->tw_v6_rcv_saddr
at the same offset.
We get rid of INET6_TW_MATCH() as INET6_MATCH() is now the generic
macro.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2013-10-04 02:42:29 +04:00
& sk - > sk_v6_rcv_saddr ,
2009-10-15 10:30:45 +04:00
inet_sk ( sk ) - > inet_num ) ;
2006-10-02 13:17:47 +04:00
break ;
2013-10-09 14:05:48 +04:00
# endif
2006-10-02 13:17:47 +04:00
default :
2009-04-24 03:32:48 +04:00
len = snprintf ( buf , remaining , " *unknown-%d* \n " ,
2009-04-24 03:33:03 +04:00
sk - > sk_family ) ;
2006-10-02 13:17:47 +04:00
}
2009-04-24 03:32:48 +04:00
if ( len > = remaining ) {
* buf = ' \0 ' ;
return - ENAMETOOLONG ;
2006-10-02 13:17:47 +04:00
}
return len ;
}
2005-04-17 02:20:36 +04:00
/*
* Generic recvfrom routine .
*/
2007-12-31 06:08:27 +03:00
static int svc_recvfrom ( struct svc_rqst * rqstp , struct kvec * iov , int nr ,
int buflen )
2005-04-17 02:20:36 +04:00
{
2007-12-31 06:08:22 +03:00
struct svc_sock * svsk =
container_of ( rqstp - > rq_xprt , struct svc_sock , sk_xprt ) ;
2007-02-12 11:53:31 +03:00
struct msghdr msg = {
. msg_flags = MSG_DONTWAIT ,
} ;
int len ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:08:29 +03:00
rqstp - > rq_xprt_hlen = 0 ;
2014-08-03 21:03:13 +04:00
clear_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ;
2007-02-12 11:53:31 +03:00
len = kernel_recvmsg ( svsk - > sk_sock , & msg , iov , nr , buflen ,
msg . msg_flags ) ;
2014-08-03 21:03:13 +04:00
/* If we read a full record, then assume there may be more
* data to read ( stream based sockets only ! )
*/
if ( len = = buflen )
set_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: socket %p recvfrom(%p, %Zu) = %d \n " ,
2007-02-12 11:53:31 +03:00
svsk , iov [ 0 ] . iov_base , iov [ 0 ] . iov_len , len ) ;
2005-04-17 02:20:36 +04:00
return len ;
}
2011-02-24 22:25:33 +03:00
static int svc_partial_recvfrom ( struct svc_rqst * rqstp ,
struct kvec * iov , int nr ,
int buflen , unsigned int base )
{
size_t save_iovlen ;
2012-03-11 23:22:54 +04:00
void * save_iovbase ;
2011-02-24 22:25:33 +03:00
unsigned int i ;
int ret ;
if ( base = = 0 )
return svc_recvfrom ( rqstp , iov , nr , buflen ) ;
for ( i = 0 ; i < nr ; i + + ) {
if ( iov [ i ] . iov_len > base )
break ;
base - = iov [ i ] . iov_len ;
}
save_iovlen = iov [ i ] . iov_len ;
save_iovbase = iov [ i ] . iov_base ;
iov [ i ] . iov_len - = base ;
iov [ i ] . iov_base + = base ;
ret = svc_recvfrom ( rqstp , & iov [ i ] , nr - i , buflen ) ;
iov [ i ] . iov_len = save_iovlen ;
iov [ i ] . iov_base = save_iovbase ;
return ret ;
}
2005-04-17 02:20:36 +04:00
/*
* Set socket snd and rcv buffer lengths
*/
2007-12-31 06:08:27 +03:00
static void svc_sock_setbufsize ( struct socket * sock , unsigned int snd ,
unsigned int rcv )
2005-04-17 02:20:36 +04:00
{
#if 0
mm_segment_t oldfs ;
oldfs = get_fs ( ) ; set_fs ( KERNEL_DS ) ;
sock_setsockopt ( sock , SOL_SOCKET , SO_SNDBUF ,
( char * ) & snd , sizeof ( snd ) ) ;
sock_setsockopt ( sock , SOL_SOCKET , SO_RCVBUF ,
( char * ) & rcv , sizeof ( rcv ) ) ;
# else
/* sock_setsockopt limits use to sysctl_?mem_max,
* which isn ' t acceptable . Until that is made conditional
* on not having CAP_SYS_RESOURCE or similar , we go direct . . .
* DaveM said I could !
*/
lock_sock ( sock - > sk ) ;
sock - > sk - > sk_sndbuf = snd * 2 ;
sock - > sk - > sk_rcvbuf = rcv * 2 ;
2009-05-19 01:47:56 +04:00
sock - > sk - > sk_write_space ( sock - > sk ) ;
2005-04-17 02:20:36 +04:00
release_sock ( sock - > sk ) ;
# endif
}
2014-05-19 21:40:22 +04:00
static int svc_sock_secure_port ( struct svc_rqst * rqstp )
{
return svc_port_is_privileged ( svc_addr ( rqstp ) ) ;
}
2005-04-17 02:20:36 +04:00
/*
* INET callback when data has been received on the socket .
*/
2016-06-24 17:55:48 +03:00
static void svc_data_ready ( struct sock * sk )
2005-04-17 02:20:36 +04:00
{
2005-09-13 12:25:39 +04:00
struct svc_sock * svsk = ( struct svc_sock * ) sk - > sk_user_data ;
2005-04-17 02:20:36 +04:00
2005-09-13 12:25:39 +04:00
if ( svsk ) {
2014-04-12 00:15:36 +04:00
dprintk ( " svc: socket %p(inet %p), busy=%d \n " ,
svsk , sk ,
2007-12-31 06:07:48 +03:00
test_bit ( XPT_BUSY , & svsk - > sk_xprt . xpt_flags ) ) ;
2016-06-24 17:55:48 +03:00
svsk - > sk_odata ( sk ) ;
2016-06-24 17:55:49 +03:00
if ( ! test_and_set_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) )
svc_xprt_enqueue ( & svsk - > sk_xprt ) ;
2005-09-13 12:25:39 +04:00
}
2005-04-17 02:20:36 +04:00
}
/*
* INET callback when space is newly available on the socket .
*/
2007-12-31 06:08:27 +03:00
static void svc_write_space ( struct sock * sk )
2005-04-17 02:20:36 +04:00
{
struct svc_sock * svsk = ( struct svc_sock * ) ( sk - > sk_user_data ) ;
if ( svsk ) {
dprintk ( " svc: socket %p(inet %p), write_space busy=%d \n " ,
2007-12-31 06:07:48 +03:00
svsk , sk , test_bit ( XPT_BUSY , & svsk - > sk_xprt . xpt_flags ) ) ;
2016-06-24 17:55:48 +03:00
svsk - > sk_owspace ( sk ) ;
2007-12-31 06:07:57 +03:00
svc_xprt_enqueue ( & svsk - > sk_xprt ) ;
2005-04-17 02:20:36 +04:00
}
}
2014-07-25 07:59:32 +04:00
static int svc_tcp_has_wspace ( struct svc_xprt * xprt )
{
2016-06-24 17:55:51 +03:00
struct svc_sock * svsk = container_of ( xprt , struct svc_sock , sk_xprt ) ;
2014-07-25 07:59:32 +04:00
if ( test_bit ( XPT_LISTENER , & xprt - > xpt_flags ) )
return 1 ;
2016-06-24 17:55:51 +03:00
return ! test_bit ( SOCK_NOSPACE , & svsk - > sk_sock - > flags ) ;
2014-07-25 07:59:33 +04:00
}
2009-07-13 18:54:26 +04:00
/*
* See net / ipv6 / ip_sockglue . c : ip_cmsg_recv_pktinfo
*/
static int svc_udp_get_dest_address4 ( struct svc_rqst * rqstp ,
struct cmsghdr * cmh )
{
struct in_pktinfo * pki = CMSG_DATA ( cmh ) ;
2011-08-30 13:18:41 +04:00
struct sockaddr_in * daddr = svc_daddr_in ( rqstp ) ;
2009-07-13 18:54:26 +04:00
if ( cmh - > cmsg_type ! = IP_PKTINFO )
return 0 ;
2011-08-30 13:18:41 +04:00
daddr - > sin_family = AF_INET ;
daddr - > sin_addr . s_addr = pki - > ipi_spec_dst . s_addr ;
2009-07-13 18:54:26 +04:00
return 1 ;
}
/*
2013-01-31 05:02:24 +04:00
* See net / ipv6 / datagram . c : ip6_datagram_recv_ctl
2009-07-13 18:54:26 +04:00
*/
static int svc_udp_get_dest_address6 ( struct svc_rqst * rqstp ,
struct cmsghdr * cmh )
{
struct in6_pktinfo * pki = CMSG_DATA ( cmh ) ;
2011-08-30 13:18:41 +04:00
struct sockaddr_in6 * daddr = svc_daddr_in6 ( rqstp ) ;
2009-07-13 18:54:26 +04:00
if ( cmh - > cmsg_type ! = IPV6_PKTINFO )
return 0 ;
2011-08-30 13:18:41 +04:00
daddr - > sin6_family = AF_INET6 ;
2011-11-21 07:39:03 +04:00
daddr - > sin6_addr = pki - > ipi6_addr ;
2011-08-30 13:18:41 +04:00
daddr - > sin6_scope_id = pki - > ipi6_ifindex ;
2009-07-13 18:54:26 +04:00
return 1 ;
}
2007-12-31 06:08:12 +03:00
/*
* Copy the UDP datagram ' s destination address to the rqstp structure .
* The ' destination ' address in this case is the address to which the
* peer sent the datagram , i . e . our local address . For multihomed
* hosts , this can change from msg to msg . Note that only the IP
* address changes , the port number should remain the same .
*/
2009-07-13 18:54:26 +04:00
static int svc_udp_get_dest_address ( struct svc_rqst * rqstp ,
struct cmsghdr * cmh )
2007-02-12 11:53:38 +03:00
{
2009-07-13 18:54:26 +04:00
switch ( cmh - > cmsg_level ) {
case SOL_IP :
return svc_udp_get_dest_address4 ( rqstp , cmh ) ;
case SOL_IPV6 :
return svc_udp_get_dest_address6 ( rqstp , cmh ) ;
2007-02-12 11:53:38 +03:00
}
2009-07-13 18:54:26 +04:00
return 0 ;
2007-02-12 11:53:38 +03:00
}
2005-04-17 02:20:36 +04:00
/*
* Receive a datagram from a UDP socket .
*/
2007-12-31 06:08:27 +03:00
static int svc_udp_recvfrom ( struct svc_rqst * rqstp )
2005-04-17 02:20:36 +04:00
{
2007-12-31 06:08:22 +03:00
struct svc_sock * svsk =
container_of ( rqstp - > rq_xprt , struct svc_sock , sk_xprt ) ;
2007-12-31 06:07:50 +03:00
struct svc_serv * serv = svsk - > sk_xprt . xpt_server ;
2005-04-17 02:20:36 +04:00
struct sk_buff * skb ;
2007-04-13 00:35:59 +04:00
union {
struct cmsghdr hdr ;
long all [ SVC_PKTINFO_SPACE / sizeof ( long ) ] ;
} buffer ;
struct cmsghdr * cmh = & buffer . hdr ;
2007-03-06 12:42:21 +03:00
struct msghdr msg = {
. msg_name = svc_addr ( rqstp ) ,
. msg_control = cmh ,
. msg_controllen = sizeof ( buffer ) ,
. msg_flags = MSG_DONTWAIT ,
} ;
2009-04-24 03:31:25 +04:00
size_t len ;
int err ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:07:48 +03:00
if ( test_and_clear_bit ( XPT_CHNGBUF , & svsk - > sk_xprt . xpt_flags ) )
2005-04-17 02:20:36 +04:00
/* udp sockets need large rcvbuf as all pending
* requests are still in that buffer . sndbuf must
* also be large enough that there is enough space
2006-10-02 13:17:58 +04:00
* for one reply per thread . We count all threads
* rather than threads in a particular pool , which
* provides an upper bound on the number of threads
* which will access the socket .
2005-04-17 02:20:36 +04:00
*/
svc_sock_setbufsize ( svsk - > sk_sock ,
2006-10-06 11:44:05 +04:00
( serv - > sv_nrthreads + 3 ) * serv - > sv_max_mesg ,
( serv - > sv_nrthreads + 3 ) * serv - > sv_max_mesg ) ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:07:48 +03:00
clear_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ;
2007-05-09 13:34:55 +04:00
skb = NULL ;
err = kernel_recvmsg ( svsk - > sk_sock , & msg , NULL ,
0 , 0 , MSG_PEEK | MSG_DONTWAIT ) ;
if ( err > = 0 )
skb = skb_recv_datagram ( svsk - > sk_sk , 0 , 1 , & err ) ;
if ( skb = = NULL ) {
if ( err ! = - EAGAIN ) {
/* possibly an icmp error */
dprintk ( " svc: recvfrom returned error %d \n " , - err ) ;
2007-12-31 06:07:48 +03:00
set_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
}
2012-08-18 05:35:24 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-12-31 06:08:12 +03:00
len = svc_addr_len ( svc_addr ( rqstp ) ) ;
rqstp - > rq_addrlen = len ;
2007-04-20 03:16:32 +04:00
if ( skb - > tstamp . tv64 = = 0 ) {
skb - > tstamp = ktime_get_real ( ) ;
2007-02-10 02:38:13 +03:00
/* Don't enable netstamp, sunrpc doesn't
2005-04-17 02:20:36 +04:00
need that much accuracy */
}
2007-04-20 03:16:32 +04:00
svsk - > sk_sk - > sk_stamp = skb - > tstamp ;
2007-12-31 06:07:48 +03:00
set_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ; /* there may be more data... */
2005-04-17 02:20:36 +04:00
2016-04-07 18:44:58 +03:00
len = skb - > len ;
2005-04-17 02:20:36 +04:00
rqstp - > rq_arg . len = len ;
2007-02-12 11:53:38 +03:00
rqstp - > rq_prot = IPPROTO_UDP ;
2007-02-12 11:53:34 +03:00
2009-07-13 18:54:26 +04:00
if ( ! svc_udp_get_dest_address ( rqstp , cmh ) ) {
2012-05-14 01:56:26 +04:00
net_warn_ratelimited ( " svc: received unknown control message %d/%d; dropping RPC reply datagram \n " ,
cmh - > cmsg_level , cmh - > cmsg_type ) ;
2012-08-18 04:32:27 +04:00
goto out_free ;
2007-03-06 12:42:21 +03:00
}
2011-08-30 13:18:41 +04:00
rqstp - > rq_daddrlen = svc_addr_len ( svc_daddr ( rqstp ) ) ;
2005-04-17 02:20:36 +04:00
if ( skb_is_nonlinear ( skb ) ) {
/* we have to copy */
local_bh_disable ( ) ;
if ( csum_partial_copy_to_xdr ( & rqstp - > rq_arg , skb ) ) {
local_bh_enable ( ) ;
/* checksum error */
2012-06-27 04:23:44 +04:00
goto out_free ;
2005-04-17 02:20:36 +04:00
}
local_bh_enable ( ) ;
2009-10-30 08:03:53 +03:00
skb_free_datagram_locked ( svsk - > sk_sk , skb ) ;
2005-04-17 02:20:36 +04:00
} else {
/* we can use it in-place */
2016-04-07 18:44:58 +03:00
rqstp - > rq_arg . head [ 0 ] . iov_base = skb - > data ;
2005-04-17 02:20:36 +04:00
rqstp - > rq_arg . head [ 0 ] . iov_len = len ;
2012-06-27 04:23:44 +04:00
if ( skb_checksum_complete ( skb ) )
goto out_free ;
2007-12-31 06:07:25 +03:00
rqstp - > rq_xprt_ctxt = skb ;
2005-04-17 02:20:36 +04:00
}
rqstp - > rq_arg . page_base = 0 ;
if ( len < = rqstp - > rq_arg . head [ 0 ] . iov_len ) {
rqstp - > rq_arg . head [ 0 ] . iov_len = len ;
rqstp - > rq_arg . page_len = 0 ;
2006-10-04 13:15:46 +04:00
rqstp - > rq_respages = rqstp - > rq_pages + 1 ;
2005-04-17 02:20:36 +04:00
} else {
rqstp - > rq_arg . page_len = len - rqstp - > rq_arg . head [ 0 ] . iov_len ;
2006-10-04 13:15:46 +04:00
rqstp - > rq_respages = rqstp - > rq_pages + 1 +
2007-08-29 02:50:33 +04:00
DIV_ROUND_UP ( rqstp - > rq_arg . page_len , PAGE_SIZE ) ;
2005-04-17 02:20:36 +04:00
}
2012-12-11 03:01:37 +04:00
rqstp - > rq_next_page = rqstp - > rq_respages + 1 ;
2005-04-17 02:20:36 +04:00
if ( serv - > sv_stats )
serv - > sv_stats - > netudpcnt + + ;
return len ;
2012-08-18 04:32:27 +04:00
out_free :
trace_kfree_skb ( skb , svc_udp_recvfrom ) ;
skb_free_datagram_locked ( svsk - > sk_sk , skb ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
static int
svc_udp_sendto ( struct svc_rqst * rqstp )
{
int error ;
error = svc_sendto ( rqstp , & rqstp - > rq_res ) ;
if ( error = = - ECONNREFUSED )
/* ICMP error on earlier request. */
error = svc_sendto ( rqstp , & rqstp - > rq_res ) ;
return error ;
}
2007-12-31 06:07:29 +03:00
static void svc_udp_prep_reply_hdr ( struct svc_rqst * rqstp )
{
}
2007-12-31 06:07:31 +03:00
static int svc_udp_has_wspace ( struct svc_xprt * xprt )
{
struct svc_sock * svsk = container_of ( xprt , struct svc_sock , sk_xprt ) ;
2007-12-31 06:07:50 +03:00
struct svc_serv * serv = xprt - > xpt_server ;
2007-12-31 06:07:31 +03:00
unsigned long required ;
/*
* Set the SOCK_NOSPACE flag before checking the available
* sock space .
*/
set_bit ( SOCK_NOSPACE , & svsk - > sk_sock - > flags ) ;
2007-12-31 06:07:55 +03:00
required = atomic_read ( & svsk - > sk_xprt . xpt_reserved ) + serv - > sv_max_mesg ;
2007-12-31 06:07:31 +03:00
if ( required * 2 > sock_wspace ( svsk - > sk_sk ) )
return 0 ;
clear_bit ( SOCK_NOSPACE , & svsk - > sk_sock - > flags ) ;
return 1 ;
}
2007-12-31 06:07:36 +03:00
static struct svc_xprt * svc_udp_accept ( struct svc_xprt * xprt )
{
BUG ( ) ;
return NULL ;
}
2007-12-31 06:07:42 +03:00
static struct svc_xprt * svc_udp_create ( struct svc_serv * serv ,
2010-09-29 16:04:18 +04:00
struct net * net ,
2007-12-31 06:07:42 +03:00
struct sockaddr * sa , int salen ,
int flags )
{
2010-09-29 16:04:18 +04:00
return svc_create_socket ( serv , IPPROTO_UDP , net , sa , salen , flags ) ;
2007-12-31 06:07:42 +03:00
}
2007-12-31 06:07:17 +03:00
static struct svc_xprt_ops svc_udp_ops = {
2007-12-31 06:07:42 +03:00
. xpo_create = svc_udp_create ,
2007-12-31 06:07:23 +03:00
. xpo_recvfrom = svc_udp_recvfrom ,
. xpo_sendto = svc_udp_sendto ,
2007-12-31 06:07:25 +03:00
. xpo_release_rqst = svc_release_skb ,
2007-12-31 06:07:27 +03:00
. xpo_detach = svc_sock_detach ,
. xpo_free = svc_sock_free ,
2007-12-31 06:07:29 +03:00
. xpo_prep_reply_hdr = svc_udp_prep_reply_hdr ,
2007-12-31 06:07:31 +03:00
. xpo_has_wspace = svc_udp_has_wspace ,
2007-12-31 06:07:36 +03:00
. xpo_accept = svc_udp_accept ,
2014-05-19 21:40:22 +04:00
. xpo_secure_port = svc_sock_secure_port ,
2007-12-31 06:07:17 +03:00
} ;
static struct svc_xprt_class svc_udp_class = {
. xcl_name = " udp " ,
2007-12-31 06:07:42 +03:00
. xcl_owner = THIS_MODULE ,
2007-12-31 06:07:17 +03:00
. xcl_ops = & svc_udp_ops ,
2007-12-31 06:07:21 +03:00
. xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP ,
2014-07-16 23:38:32 +04:00
. xcl_ident = XPRT_TRANSPORT_UDP ,
2007-12-31 06:07:17 +03:00
} ;
2007-12-31 06:07:50 +03:00
static void svc_udp_init ( struct svc_sock * svsk , struct svc_serv * serv )
2005-04-17 02:20:36 +04:00
{
2009-07-13 18:54:26 +04:00
int err , level , optname , one = 1 ;
2007-03-06 12:42:21 +03:00
2011-12-06 15:19:10 +04:00
svc_xprt_init ( sock_net ( svsk - > sk_sock - > sk ) , & svc_udp_class ,
& svsk - > sk_xprt , serv ) ;
2007-12-31 06:08:08 +03:00
clear_bit ( XPT_CACHE_AUTH , & svsk - > sk_xprt . xpt_flags ) ;
2016-06-24 17:55:48 +03:00
svsk - > sk_sk - > sk_data_ready = svc_data_ready ;
2005-04-17 02:20:36 +04:00
svsk - > sk_sk - > sk_write_space = svc_write_space ;
/* initialise setting must have enough space to
2007-02-10 02:38:13 +03:00
* receive and respond to one request .
2005-04-17 02:20:36 +04:00
* svc_udp_recvfrom will re - adjust if necessary
*/
svc_sock_setbufsize ( svsk - > sk_sock ,
2007-12-31 06:07:50 +03:00
3 * svsk - > sk_xprt . xpt_server - > sv_max_mesg ,
3 * svsk - > sk_xprt . xpt_server - > sv_max_mesg ) ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:08:27 +03:00
/* data might have come in before data_ready set up */
set_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ;
2007-12-31 06:07:48 +03:00
set_bit ( XPT_CHNGBUF , & svsk - > sk_xprt . xpt_flags ) ;
2007-03-06 12:42:21 +03:00
/* make sure we get destination address info */
2009-07-13 18:54:26 +04:00
switch ( svsk - > sk_sk - > sk_family ) {
case AF_INET :
level = SOL_IP ;
optname = IP_PKTINFO ;
break ;
case AF_INET6 :
level = SOL_IPV6 ;
optname = IPV6_RECVPKTINFO ;
break ;
default :
BUG ( ) ;
}
err = kernel_setsockopt ( svsk - > sk_sock , level , optname ,
( char * ) & one , sizeof ( one ) ) ;
dprintk ( " svc: kernel_setsockopt returned %d \n " , err ) ;
2005-04-17 02:20:36 +04:00
}
/*
* A data_ready event on a listening socket means there ' s a connection
* pending . Do not use state_change as a substitute for it .
*/
2014-04-12 00:15:36 +04:00
static void svc_tcp_listen_data_ready ( struct sock * sk )
2005-04-17 02:20:36 +04:00
{
2005-09-13 12:25:39 +04:00
struct svc_sock * svsk = ( struct svc_sock * ) sk - > sk_user_data ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: socket %p TCP (listen) state change %d \n " ,
2005-09-13 12:25:39 +04:00
sk , sk - > sk_state ) ;
2005-04-17 02:20:36 +04:00
2016-06-24 17:55:48 +03:00
if ( svsk )
svsk - > sk_odata ( sk ) ;
2005-09-13 12:25:39 +04:00
/*
* This callback may called twice when a new connection
* is established as a child socket inherits everything
* from a parent LISTEN socket .
* 1 ) data_ready method of the parent socket will be called
* when one of child sockets become ESTABLISHED .
* 2 ) data_ready method of the child socket may be called
* when it receives data before the socket is accepted .
* In case of 2 , we should ignore it silently .
*/
if ( sk - > sk_state = = TCP_LISTEN ) {
if ( svsk ) {
2007-12-31 06:07:48 +03:00
set_bit ( XPT_CONN , & svsk - > sk_xprt . xpt_flags ) ;
2007-12-31 06:07:57 +03:00
svc_xprt_enqueue ( & svsk - > sk_xprt ) ;
2005-09-13 12:25:39 +04:00
} else
printk ( " svc: socket %p: no user data \n " , sk ) ;
2005-04-17 02:20:36 +04:00
}
}
/*
* A state change on a connected socket means it ' s dying or dead .
*/
2007-12-31 06:08:27 +03:00
static void svc_tcp_state_change ( struct sock * sk )
2005-04-17 02:20:36 +04:00
{
2005-09-13 12:25:39 +04:00
struct svc_sock * svsk = ( struct svc_sock * ) sk - > sk_user_data ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: socket %p TCP (connected) state change %d (svsk %p) \n " ,
2005-09-13 12:25:39 +04:00
sk , sk - > sk_state , sk - > sk_user_data ) ;
2005-04-17 02:20:36 +04:00
2005-09-13 12:25:39 +04:00
if ( ! svsk )
2005-04-17 02:20:36 +04:00
printk ( " svc: socket %p: no user data \n " , sk ) ;
2005-09-13 12:25:39 +04:00
else {
2016-06-24 17:55:48 +03:00
svsk - > sk_ostate ( sk ) ;
2016-07-26 16:51:19 +03:00
if ( sk - > sk_state ! = TCP_ESTABLISHED ) {
set_bit ( XPT_CLOSE , & svsk - > sk_xprt . xpt_flags ) ;
svc_xprt_enqueue ( & svsk - > sk_xprt ) ;
}
2005-04-17 02:20:36 +04:00
}
}
/*
* Accept a TCP connection
*/
2007-12-31 06:07:36 +03:00
static struct svc_xprt * svc_tcp_accept ( struct svc_xprt * xprt )
2005-04-17 02:20:36 +04:00
{
2007-12-31 06:07:36 +03:00
struct svc_sock * svsk = container_of ( xprt , struct svc_sock , sk_xprt ) ;
2007-02-12 11:53:38 +03:00
struct sockaddr_storage addr ;
struct sockaddr * sin = ( struct sockaddr * ) & addr ;
2007-12-31 06:07:50 +03:00
struct svc_serv * serv = svsk - > sk_xprt . xpt_server ;
2005-04-17 02:20:36 +04:00
struct socket * sock = svsk - > sk_sock ;
struct socket * newsock ;
struct svc_sock * newsvsk ;
int err , slen ;
2008-02-21 10:57:45 +03:00
RPC_IFDEBUG ( char buf [ RPC_MAX_ADDRBUFLEN ] ) ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: tcp_accept %p sock %p \n " , svsk , sock ) ;
if ( ! sock )
2007-12-31 06:07:36 +03:00
return NULL ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:07:48 +03:00
clear_bit ( XPT_CONN , & svsk - > sk_xprt . xpt_flags ) ;
2006-08-08 07:58:01 +04:00
err = kernel_accept ( sock , & newsock , O_NONBLOCK ) ;
if ( err < 0 ) {
2005-04-17 02:20:36 +04:00
if ( err = = - ENOMEM )
printk ( KERN_WARNING " %s: no more sockets! \n " ,
serv - > sv_name ) ;
2012-05-14 01:56:26 +04:00
else if ( err ! = - EAGAIN )
net_warn_ratelimited ( " %s: accept failed (err %d)! \n " ,
serv - > sv_name , - err ) ;
2007-12-31 06:07:36 +03:00
return NULL ;
2005-04-17 02:20:36 +04:00
}
2007-12-31 06:07:48 +03:00
set_bit ( XPT_CONN , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
2007-02-12 11:53:38 +03:00
err = kernel_getpeername ( newsock , sin , & slen ) ;
2005-04-17 02:20:36 +04:00
if ( err < 0 ) {
2012-05-14 01:56:26 +04:00
net_warn_ratelimited ( " %s: peername failed (err %d)! \n " ,
serv - > sv_name , - err ) ;
2005-04-17 02:20:36 +04:00
goto failed ; /* aborted connection or whatever */
}
/* Ideally, we would want to reject connections from unauthorized
2007-02-12 11:53:32 +03:00
* hosts here , but when we get encryption , the IP of the host won ' t
* tell us anything . For now just warn about unpriv connections .
2005-04-17 02:20:36 +04:00
*/
2007-02-12 11:53:38 +03:00
if ( ! svc_port_is_privileged ( sin ) ) {
2014-05-29 08:18:52 +04:00
dprintk ( " %s: connect from unprivileged port: %s \n " ,
2007-02-10 02:38:13 +03:00
serv - > sv_name ,
2007-02-12 11:53:38 +03:00
__svc_print_addr ( sin , buf , sizeof ( buf ) ) ) ;
2005-04-17 02:20:36 +04:00
}
2007-02-12 11:53:32 +03:00
dprintk ( " %s: connect from %s \n " , serv - > sv_name ,
2007-02-12 11:53:38 +03:00
__svc_print_addr ( sin , buf , sizeof ( buf ) ) ) ;
2005-04-17 02:20:36 +04:00
2016-06-24 17:55:48 +03:00
/* Reset the inherited callbacks before calling svc_setup_socket */
newsock - > sk - > sk_state_change = svsk - > sk_ostate ;
newsock - > sk - > sk_data_ready = svsk - > sk_odata ;
newsock - > sk - > sk_write_space = svsk - > sk_owspace ;
2005-04-17 02:20:36 +04:00
/* make sure that a write doesn't block forever when
* low on memory
*/
newsock - > sk - > sk_sndtimeo = HZ * 30 ;
2012-08-14 01:46:17 +04:00
newsvsk = svc_setup_socket ( serv , newsock ,
( SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY ) ) ;
if ( IS_ERR ( newsvsk ) )
2005-04-17 02:20:36 +04:00
goto failed ;
2007-12-31 06:08:12 +03:00
svc_xprt_set_remote ( & newsvsk - > sk_xprt , sin , slen ) ;
2007-07-10 00:21:39 +04:00
err = kernel_getsockname ( newsock , sin , & slen ) ;
if ( unlikely ( err < 0 ) ) {
dprintk ( " svc_tcp_accept: kernel_getsockname error %d \n " , - err ) ;
slen = offsetof ( struct sockaddr , sa_data ) ;
}
2007-12-31 06:08:12 +03:00
svc_xprt_set_local ( & newsvsk - > sk_xprt , sin , slen ) ;
2007-02-12 11:53:30 +03:00
2014-05-12 05:22:47 +04:00
if ( sock_is_loopback ( newsock - > sk ) )
set_bit ( XPT_LOCAL , & newsvsk - > sk_xprt . xpt_flags ) ;
else
clear_bit ( XPT_LOCAL , & newsvsk - > sk_xprt . xpt_flags ) ;
2007-12-31 06:07:40 +03:00
if ( serv - > sv_stats )
serv - > sv_stats - > nettcpconn + + ;
return & newsvsk - > sk_xprt ;
failed :
sock_release ( newsock ) ;
return NULL ;
}
2011-02-24 22:25:33 +03:00
static unsigned int svc_tcp_restore_pages ( struct svc_sock * svsk , struct svc_rqst * rqstp )
{
unsigned int i , len , npages ;
2012-12-04 01:45:35 +04:00
if ( svsk - > sk_datalen = = 0 )
2011-02-24 22:25:33 +03:00
return 0 ;
2012-12-04 01:45:35 +04:00
len = svsk - > sk_datalen ;
2011-02-24 22:25:33 +03:00
npages = ( len + PAGE_SIZE - 1 ) > > PAGE_SHIFT ;
for ( i = 0 ; i < npages ; i + + ) {
if ( rqstp - > rq_pages [ i ] ! = NULL )
put_page ( rqstp - > rq_pages [ i ] ) ;
BUG_ON ( svsk - > sk_pages [ i ] = = NULL ) ;
rqstp - > rq_pages [ i ] = svsk - > sk_pages [ i ] ;
svsk - > sk_pages [ i ] = NULL ;
}
rqstp - > rq_arg . head [ 0 ] . iov_base = page_address ( rqstp - > rq_pages [ 0 ] ) ;
return len ;
}
static void svc_tcp_save_pages ( struct svc_sock * svsk , struct svc_rqst * rqstp )
{
unsigned int i , len , npages ;
2012-12-04 01:45:35 +04:00
if ( svsk - > sk_datalen = = 0 )
2011-02-24 22:25:33 +03:00
return ;
2012-12-04 01:45:35 +04:00
len = svsk - > sk_datalen ;
2011-02-24 22:25:33 +03:00
npages = ( len + PAGE_SIZE - 1 ) > > PAGE_SHIFT ;
for ( i = 0 ; i < npages ; i + + ) {
svsk - > sk_pages [ i ] = rqstp - > rq_pages [ i ] ;
rqstp - > rq_pages [ i ] = NULL ;
}
}
static void svc_tcp_clear_pages ( struct svc_sock * svsk )
{
unsigned int i , len , npages ;
2012-12-04 01:45:35 +04:00
if ( svsk - > sk_datalen = = 0 )
2011-02-24 22:25:33 +03:00
goto out ;
2012-12-04 01:45:35 +04:00
len = svsk - > sk_datalen ;
2011-02-24 22:25:33 +03:00
npages = ( len + PAGE_SIZE - 1 ) > > PAGE_SHIFT ;
for ( i = 0 ; i < npages ; i + + ) {
2013-06-26 19:09:06 +04:00
if ( svsk - > sk_pages [ i ] = = NULL ) {
WARN_ON_ONCE ( 1 ) ;
continue ;
}
2011-02-24 22:25:33 +03:00
put_page ( svsk - > sk_pages [ i ] ) ;
svsk - > sk_pages [ i ] = NULL ;
}
out :
svsk - > sk_tcplen = 0 ;
2012-12-04 01:45:35 +04:00
svsk - > sk_datalen = 0 ;
2011-02-24 22:25:33 +03:00
}
2005-04-17 02:20:36 +04:00
/*
2012-12-04 01:30:42 +04:00
* Receive fragment record header .
2009-08-20 04:34:19 +04:00
* If we haven ' t gotten the record length yet , get the next four bytes .
2005-04-17 02:20:36 +04:00
*/
2009-08-20 04:34:19 +04:00
static int svc_tcp_recv_record ( struct svc_sock * svsk , struct svc_rqst * rqstp )
2005-04-17 02:20:36 +04:00
{
2007-12-31 06:07:50 +03:00
struct svc_serv * serv = svsk - > sk_xprt . xpt_server ;
2009-05-19 01:47:56 +04:00
unsigned int want ;
2009-08-20 04:34:19 +04:00
int len ;
2005-04-17 02:20:36 +04:00
2008-04-14 20:27:30 +04:00
if ( svsk - > sk_tcplen < sizeof ( rpc_fraghdr ) ) {
2005-04-17 02:20:36 +04:00
struct kvec iov ;
2009-05-19 01:47:56 +04:00
want = sizeof ( rpc_fraghdr ) - svsk - > sk_tcplen ;
2005-04-17 02:20:36 +04:00
iov . iov_base = ( ( char * ) & svsk - > sk_reclen ) + svsk - > sk_tcplen ;
iov . iov_len = want ;
if ( ( len = svc_recvfrom ( rqstp , & iov , 1 , want ) ) < 0 )
goto error ;
svsk - > sk_tcplen + = len ;
if ( len < want ) {
2008-04-14 20:27:30 +04:00
dprintk ( " svc: short recvfrom while reading record "
" length (%d of %d) \n " , len , want ) ;
2011-02-24 22:25:33 +03:00
return - EAGAIN ;
2005-04-17 02:20:36 +04:00
}
2012-12-04 01:11:13 +04:00
dprintk ( " svc: TCP record, %d bytes \n " , svc_sock_reclen ( svsk ) ) ;
2012-12-04 00:50:38 +04:00
if ( svc_sock_reclen ( svsk ) + svsk - > sk_datalen >
serv - > sv_max_mesg ) {
2012-12-11 03:15:07 +04:00
net_notice_ratelimited ( " RPC: fragment too large: %d \n " ,
svc_sock_reclen ( svsk ) ) ;
2005-04-17 02:20:36 +04:00
goto err_delete ;
}
}
2012-12-04 01:11:13 +04:00
return svc_sock_reclen ( svsk ) ;
2011-02-24 22:25:33 +03:00
error :
dprintk ( " RPC: TCP recv_record got %d \n " , len ) ;
2009-08-20 04:34:19 +04:00
return len ;
2011-02-24 22:25:33 +03:00
err_delete :
2009-08-20 04:34:19 +04:00
set_bit ( XPT_CLOSE , & svsk - > sk_xprt . xpt_flags ) ;
return - EAGAIN ;
}
2009-05-19 01:47:56 +04:00
static int receive_cb_reply ( struct svc_sock * svsk , struct svc_rqst * rqstp )
2009-09-10 18:32:28 +04:00
{
2009-05-19 01:47:56 +04:00
struct rpc_xprt * bc_xprt = svsk - > sk_xprt . xpt_bc_xprt ;
2009-09-10 18:32:28 +04:00
struct rpc_rqst * req = NULL ;
2009-05-19 01:47:56 +04:00
struct kvec * src , * dst ;
__be32 * p = ( __be32 * ) rqstp - > rq_arg . head [ 0 ] . iov_base ;
2011-02-14 22:52:03 +03:00
__be32 xid ;
__be32 calldir ;
2009-09-10 18:32:28 +04:00
xid = * p + + ;
calldir = * p ;
2014-11-13 02:04:04 +03:00
if ( ! bc_xprt )
2009-05-19 01:47:56 +04:00
return - EAGAIN ;
2014-11-13 02:04:04 +03:00
spin_lock_bh ( & bc_xprt - > transport_lock ) ;
req = xprt_lookup_rqst ( bc_xprt , xid ) ;
if ( ! req )
goto unlock_notfound ;
2009-05-19 01:47:56 +04:00
memcpy ( & req - > rq_private_buf , & req - > rq_rcv_buf , sizeof ( struct xdr_buf ) ) ;
/*
* XXX ! : cheating for now ! Only copying HEAD .
* But we know this is good enough for now ( in fact , for any
* callback reply in the forseeable future ) .
*/
dst = & req - > rq_private_buf . head [ 0 ] ;
src = & rqstp - > rq_arg . head [ 0 ] ;
if ( dst - > iov_len < src - > iov_len )
2014-11-13 02:04:04 +03:00
goto unlock_eagain ; /* whatever; just giving up. */
2009-05-19 01:47:56 +04:00
memcpy ( dst - > iov_base , src - > iov_base , src - > iov_len ) ;
2012-12-04 01:11:13 +04:00
xprt_complete_rqst ( req - > rq_task , rqstp - > rq_arg . len ) ;
2009-05-19 01:47:56 +04:00
rqstp - > rq_arg . len = 0 ;
2014-11-13 02:04:04 +03:00
spin_unlock_bh ( & bc_xprt - > transport_lock ) ;
2009-05-19 01:47:56 +04:00
return 0 ;
2014-11-13 02:04:04 +03:00
unlock_notfound :
printk ( KERN_NOTICE
" %s: Got unrecognized reply: "
" calldir 0x%x xpt_bc_xprt %p xid %08x \n " ,
__func__ , ntohl ( calldir ) ,
bc_xprt , ntohl ( xid ) ) ;
unlock_eagain :
spin_unlock_bh ( & bc_xprt - > transport_lock ) ;
return - EAGAIN ;
2009-05-19 01:47:56 +04:00
}
static int copy_pages_to_kvecs ( struct kvec * vec , struct page * * pages , int len )
{
int i = 0 ;
int t = 0 ;
while ( t < len ) {
vec [ i ] . iov_base = page_address ( pages [ i ] ) ;
vec [ i ] . iov_len = PAGE_SIZE ;
i + + ;
t + = PAGE_SIZE ;
}
return i ;
2009-09-10 18:32:28 +04:00
}
2012-12-04 00:50:38 +04:00
static void svc_tcp_fragment_received ( struct svc_sock * svsk )
{
/* If we have more data, signal svc_xprt_enqueue() to try again */
dprintk ( " svc: TCP %s record (%d bytes) \n " ,
svc_sock_final_rec ( svsk ) ? " final " : " nonfinal " ,
svc_sock_reclen ( svsk ) ) ;
svsk - > sk_tcplen = 0 ;
svsk - > sk_reclen = 0 ;
}
2011-02-24 22:25:33 +03:00
2009-08-20 04:34:19 +04:00
/*
* Receive data from a TCP socket .
*/
static int svc_tcp_recvfrom ( struct svc_rqst * rqstp )
{
struct svc_sock * svsk =
container_of ( rqstp - > rq_xprt , struct svc_sock , sk_xprt ) ;
struct svc_serv * serv = svsk - > sk_xprt . xpt_server ;
int len ;
struct kvec * vec ;
2011-02-24 22:25:33 +03:00
unsigned int want , base ;
2009-05-19 01:47:56 +04:00
__be32 * p ;
__be32 calldir ;
2009-05-19 01:47:56 +04:00
int pnum ;
2009-08-20 04:34:19 +04:00
dprintk ( " svc: tcp_recv %p data %d conn %d close %d \n " ,
svsk , test_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ,
test_bit ( XPT_CONN , & svsk - > sk_xprt . xpt_flags ) ,
test_bit ( XPT_CLOSE , & svsk - > sk_xprt . xpt_flags ) ) ;
len = svc_tcp_recv_record ( svsk , rqstp ) ;
if ( len < 0 )
goto error ;
2011-02-24 22:25:33 +03:00
base = svc_tcp_restore_pages ( svsk , rqstp ) ;
2012-12-04 00:50:38 +04:00
want = svc_sock_reclen ( svsk ) - ( svsk - > sk_tcplen - sizeof ( rpc_fraghdr ) ) ;
2011-02-24 22:25:33 +03:00
2006-10-04 13:15:47 +04:00
vec = rqstp - > rq_vec ;
2009-09-10 18:32:28 +04:00
2009-05-19 01:47:56 +04:00
pnum = copy_pages_to_kvecs ( & vec [ 0 ] , & rqstp - > rq_pages [ 0 ] ,
2012-12-04 00:50:38 +04:00
svsk - > sk_datalen + want ) ;
2009-05-19 01:47:56 +04:00
2006-10-04 13:15:46 +04:00
rqstp - > rq_respages = & rqstp - > rq_pages [ pnum ] ;
2012-12-11 03:01:37 +04:00
rqstp - > rq_next_page = rqstp - > rq_respages + 1 ;
2005-04-17 02:20:36 +04:00
/* Now receive data */
2011-02-24 22:25:33 +03:00
len = svc_partial_recvfrom ( rqstp , vec , pnum , want , base ) ;
2012-12-04 01:45:35 +04:00
if ( len > = 0 ) {
2011-02-24 22:25:33 +03:00
svsk - > sk_tcplen + = len ;
2012-12-04 01:45:35 +04:00
svsk - > sk_datalen + = len ;
}
2012-12-04 00:50:38 +04:00
if ( len ! = want | | ! svc_sock_final_rec ( svsk ) ) {
2012-08-10 02:12:28 +04:00
svc_tcp_save_pages ( svsk , rqstp ) ;
2011-02-24 22:25:33 +03:00
if ( len < 0 & & len ! = - EAGAIN )
2012-12-04 01:30:42 +04:00
goto err_delete ;
2012-12-04 00:50:38 +04:00
if ( len = = want )
svc_tcp_fragment_received ( svsk ) ;
else
2012-12-11 03:15:07 +04:00
dprintk ( " svc: incomplete TCP record (%d of %d) \n " ,
( int ) ( svsk - > sk_tcplen - sizeof ( rpc_fraghdr ) ) ,
2012-12-04 00:50:38 +04:00
svc_sock_reclen ( svsk ) ) ;
2011-02-24 22:25:33 +03:00
goto err_noclose ;
}
2005-04-17 02:20:36 +04:00
2013-06-26 18:55:40 +04:00
if ( svsk - > sk_datalen < 8 ) {
2013-06-26 19:09:06 +04:00
svsk - > sk_datalen = 0 ;
2012-12-04 01:30:42 +04:00
goto err_delete ; /* client is nuts. */
2013-06-26 19:09:06 +04:00
}
2012-12-04 01:30:42 +04:00
2012-12-04 00:50:38 +04:00
rqstp - > rq_arg . len = svsk - > sk_datalen ;
2005-04-17 02:20:36 +04:00
rqstp - > rq_arg . page_base = 0 ;
2009-05-19 01:47:56 +04:00
if ( rqstp - > rq_arg . len < = rqstp - > rq_arg . head [ 0 ] . iov_len ) {
rqstp - > rq_arg . head [ 0 ] . iov_len = rqstp - > rq_arg . len ;
2005-04-17 02:20:36 +04:00
rqstp - > rq_arg . page_len = 0 ;
2009-05-19 01:47:56 +04:00
} else
rqstp - > rq_arg . page_len = rqstp - > rq_arg . len - rqstp - > rq_arg . head [ 0 ] . iov_len ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:07:25 +03:00
rqstp - > rq_xprt_ctxt = NULL ;
2005-04-17 02:20:36 +04:00
rqstp - > rq_prot = IPPROTO_TCP ;
2014-11-19 15:51:15 +03:00
if ( test_bit ( XPT_LOCAL , & svsk - > sk_xprt . xpt_flags ) )
set_bit ( RQ_LOCAL , & rqstp - > rq_flags ) ;
else
clear_bit ( RQ_LOCAL , & rqstp - > rq_flags ) ;
2005-04-17 02:20:36 +04:00
2009-05-19 01:47:56 +04:00
p = ( __be32 * ) rqstp - > rq_arg . head [ 0 ] . iov_base ;
calldir = p [ 1 ] ;
2011-04-09 18:03:10 +04:00
if ( calldir )
2009-05-19 01:47:56 +04:00
len = receive_cb_reply ( svsk , rqstp ) ;
2005-04-17 02:20:36 +04:00
/* Reset TCP read info */
2012-12-04 01:45:35 +04:00
svsk - > sk_datalen = 0 ;
2012-12-04 00:50:38 +04:00
svc_tcp_fragment_received ( svsk ) ;
2009-05-19 01:47:56 +04:00
2011-04-09 18:03:10 +04:00
if ( len < 0 )
goto error ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:08:12 +03:00
svc_xprt_copy_addrs ( rqstp , & svsk - > sk_xprt ) ;
2005-04-17 02:20:36 +04:00
if ( serv - > sv_stats )
serv - > sv_stats - > nettcpcnt + + ;
2009-05-19 01:47:56 +04:00
return rqstp - > rq_arg . len ;
2005-04-17 02:20:36 +04:00
2009-08-20 04:34:19 +04:00
error :
2011-02-24 22:25:33 +03:00
if ( len ! = - EAGAIN )
2012-12-04 01:30:42 +04:00
goto err_delete ;
2011-02-24 22:25:33 +03:00
dprintk ( " RPC: TCP recvfrom got EAGAIN \n " ) ;
2012-08-18 05:35:24 +04:00
return 0 ;
2012-12-04 01:30:42 +04:00
err_delete :
2011-02-24 22:25:33 +03:00
printk ( KERN_NOTICE " %s: recvfrom returned errno %d \n " ,
svsk - > sk_xprt . xpt_server - > sv_name , - len ) ;
set_bit ( XPT_CLOSE , & svsk - > sk_xprt . xpt_flags ) ;
err_noclose :
2012-08-18 05:35:24 +04:00
return 0 ; /* record not complete */
2005-04-17 02:20:36 +04:00
}
/*
* Send out data on TCP socket .
*/
2007-12-31 06:08:27 +03:00
static int svc_tcp_sendto ( struct svc_rqst * rqstp )
2005-04-17 02:20:36 +04:00
{
struct xdr_buf * xbufp = & rqstp - > rq_res ;
int sent ;
2006-09-27 09:29:38 +04:00
__be32 reclen ;
2005-04-17 02:20:36 +04:00
/* Set up the first element of the reply kvec.
* Any other kvecs that may be in use have been taken
* care of by the server implementation itself .
*/
reclen = htonl ( 0x80000000 | ( ( xbufp - > len ) - 4 ) ) ;
memcpy ( xbufp - > head [ 0 ] . iov_base , & reclen , 4 ) ;
sent = svc_sendto ( rqstp , & rqstp - > rq_res ) ;
if ( sent ! = xbufp - > len ) {
2007-12-31 06:08:27 +03:00
printk ( KERN_NOTICE
" rpc-srv/tcp: %s: %s %d when sending %d bytes "
" - shutting down socket \n " ,
2007-12-31 06:08:22 +03:00
rqstp - > rq_xprt - > xpt_server - > sv_name ,
2005-04-17 02:20:36 +04:00
( sent < 0 ) ? " got error " : " sent only " ,
sent , xbufp - > len ) ;
2007-12-31 06:08:22 +03:00
set_bit ( XPT_CLOSE , & rqstp - > rq_xprt - > xpt_flags ) ;
2007-12-31 06:07:57 +03:00
svc_xprt_enqueue ( rqstp - > rq_xprt ) ;
2005-04-17 02:20:36 +04:00
sent = - EAGAIN ;
}
return sent ;
}
2007-12-31 06:07:29 +03:00
/*
* Setup response header . TCP has a 4 B record length field .
*/
static void svc_tcp_prep_reply_hdr ( struct svc_rqst * rqstp )
{
struct kvec * resv = & rqstp - > rq_res . head [ 0 ] ;
/* tcp needs a space for the record length... */
svc_putnl ( resv , 0 ) ;
}
2007-12-31 06:07:42 +03:00
static struct svc_xprt * svc_tcp_create ( struct svc_serv * serv ,
2010-09-29 16:04:18 +04:00
struct net * net ,
2007-12-31 06:07:42 +03:00
struct sockaddr * sa , int salen ,
int flags )
{
2010-09-29 16:04:18 +04:00
return svc_create_socket ( serv , IPPROTO_TCP , net , sa , salen , flags ) ;
2007-12-31 06:07:42 +03:00
}
2011-07-14 03:20:49 +04:00
# if defined(CONFIG_SUNRPC_BACKCHANNEL)
2011-01-06 05:04:26 +03:00
static struct svc_xprt * svc_bc_create_socket ( struct svc_serv * , int ,
struct net * , struct sockaddr * ,
int , int ) ;
static void svc_bc_sock_free ( struct svc_xprt * xprt ) ;
static struct svc_xprt * svc_bc_tcp_create ( struct svc_serv * serv ,
struct net * net ,
struct sockaddr * sa , int salen ,
int flags )
{
return svc_bc_create_socket ( serv , IPPROTO_TCP , net , sa , salen , flags ) ;
}
static void svc_bc_tcp_sock_detach ( struct svc_xprt * xprt )
{
}
static struct svc_xprt_ops svc_tcp_bc_ops = {
. xpo_create = svc_bc_tcp_create ,
. xpo_detach = svc_bc_tcp_sock_detach ,
. xpo_free = svc_bc_sock_free ,
. xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr ,
2014-05-19 21:40:22 +04:00
. xpo_secure_port = svc_sock_secure_port ,
2011-01-06 05:04:26 +03:00
} ;
static struct svc_xprt_class svc_tcp_bc_class = {
. xcl_name = " tcp-bc " ,
. xcl_owner = THIS_MODULE ,
. xcl_ops = & svc_tcp_bc_ops ,
. xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP ,
} ;
2011-01-06 05:04:27 +03:00
static void svc_init_bc_xprt_sock ( void )
{
svc_reg_xprt_class ( & svc_tcp_bc_class ) ;
}
static void svc_cleanup_bc_xprt_sock ( void )
{
svc_unreg_xprt_class ( & svc_tcp_bc_class ) ;
}
2011-07-14 03:20:49 +04:00
# else /* CONFIG_SUNRPC_BACKCHANNEL */
2011-01-06 05:04:27 +03:00
static void svc_init_bc_xprt_sock ( void )
{
}
static void svc_cleanup_bc_xprt_sock ( void )
{
}
2011-07-14 03:20:49 +04:00
# endif /* CONFIG_SUNRPC_BACKCHANNEL */
2011-01-06 05:04:26 +03:00
2007-12-31 06:07:17 +03:00
static struct svc_xprt_ops svc_tcp_ops = {
2007-12-31 06:07:42 +03:00
. xpo_create = svc_tcp_create ,
2007-12-31 06:07:23 +03:00
. xpo_recvfrom = svc_tcp_recvfrom ,
. xpo_sendto = svc_tcp_sendto ,
2007-12-31 06:07:25 +03:00
. xpo_release_rqst = svc_release_skb ,
2008-12-24 00:30:11 +03:00
. xpo_detach = svc_tcp_sock_detach ,
2007-12-31 06:07:27 +03:00
. xpo_free = svc_sock_free ,
2007-12-31 06:07:29 +03:00
. xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr ,
2007-12-31 06:07:31 +03:00
. xpo_has_wspace = svc_tcp_has_wspace ,
2007-12-31 06:07:36 +03:00
. xpo_accept = svc_tcp_accept ,
2014-05-19 21:40:22 +04:00
. xpo_secure_port = svc_sock_secure_port ,
2007-12-31 06:07:17 +03:00
} ;
static struct svc_xprt_class svc_tcp_class = {
. xcl_name = " tcp " ,
2007-12-31 06:07:42 +03:00
. xcl_owner = THIS_MODULE ,
2007-12-31 06:07:17 +03:00
. xcl_ops = & svc_tcp_ops ,
2007-12-31 06:07:21 +03:00
. xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP ,
2014-07-16 23:38:32 +04:00
. xcl_ident = XPRT_TRANSPORT_TCP ,
2007-12-31 06:07:17 +03:00
} ;
void svc_init_xprt_sock ( void )
{
svc_reg_xprt_class ( & svc_tcp_class ) ;
svc_reg_xprt_class ( & svc_udp_class ) ;
2011-01-06 05:04:27 +03:00
svc_init_bc_xprt_sock ( ) ;
2007-12-31 06:07:17 +03:00
}
void svc_cleanup_xprt_sock ( void )
{
svc_unreg_xprt_class ( & svc_tcp_class ) ;
svc_unreg_xprt_class ( & svc_udp_class ) ;
2011-01-06 05:04:27 +03:00
svc_cleanup_bc_xprt_sock ( ) ;
2007-12-31 06:07:17 +03:00
}
2007-12-31 06:07:50 +03:00
static void svc_tcp_init ( struct svc_sock * svsk , struct svc_serv * serv )
2005-04-17 02:20:36 +04:00
{
struct sock * sk = svsk - > sk_sk ;
2011-12-06 15:19:10 +04:00
svc_xprt_init ( sock_net ( svsk - > sk_sock - > sk ) , & svc_tcp_class ,
& svsk - > sk_xprt , serv ) ;
2007-12-31 06:08:08 +03:00
set_bit ( XPT_CACHE_AUTH , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
if ( sk - > sk_state = = TCP_LISTEN ) {
dprintk ( " setting up TCP socket for listening \n " ) ;
2007-12-31 06:07:48 +03:00
set_bit ( XPT_LISTENER , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
sk - > sk_data_ready = svc_tcp_listen_data_ready ;
2007-12-31 06:07:48 +03:00
set_bit ( XPT_CONN , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
} else {
dprintk ( " setting up TCP socket for reading \n " ) ;
sk - > sk_state_change = svc_tcp_state_change ;
2016-06-24 17:55:48 +03:00
sk - > sk_data_ready = svc_data_ready ;
2016-06-24 17:55:51 +03:00
sk - > sk_write_space = svc_write_space ;
2005-04-17 02:20:36 +04:00
svsk - > sk_reclen = 0 ;
svsk - > sk_tcplen = 0 ;
2012-12-04 01:45:35 +04:00
svsk - > sk_datalen = 0 ;
2011-02-24 22:25:33 +03:00
memset ( & svsk - > sk_pages [ 0 ] , 0 , sizeof ( svsk - > sk_pages ) ) ;
2005-04-17 02:20:36 +04:00
2008-04-14 20:27:01 +04:00
tcp_sk ( sk ) - > nonagle | = TCP_NAGLE_OFF ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:07:48 +03:00
set_bit ( XPT_DATA , & svsk - > sk_xprt . xpt_flags ) ;
2016-07-26 16:51:19 +03:00
switch ( sk - > sk_state ) {
case TCP_SYN_RECV :
case TCP_ESTABLISHED :
break ;
default :
2007-12-31 06:07:48 +03:00
set_bit ( XPT_CLOSE , & svsk - > sk_xprt . xpt_flags ) ;
2016-07-26 16:51:19 +03:00
}
2005-04-17 02:20:36 +04:00
}
}
2007-12-31 06:08:27 +03:00
void svc_sock_update_bufs ( struct svc_serv * serv )
2005-04-17 02:20:36 +04:00
{
/*
* The number of server threads has changed . Update
* rcvbuf and sndbuf accordingly on all sockets
*/
2010-10-05 23:30:19 +04:00
struct svc_sock * svsk ;
2005-04-17 02:20:36 +04:00
spin_lock_bh ( & serv - > sv_lock ) ;
2010-10-05 23:30:19 +04:00
list_for_each_entry ( svsk , & serv - > sv_permsocks , sk_xprt . xpt_list )
2007-12-31 06:07:48 +03:00
set_bit ( XPT_CHNGBUF , & svsk - > sk_xprt . xpt_flags ) ;
2005-04-17 02:20:36 +04:00
spin_unlock_bh ( & serv - > sv_lock ) ;
}
2008-12-24 00:30:12 +03:00
EXPORT_SYMBOL_GPL ( svc_sock_update_bufs ) ;
2005-04-17 02:20:36 +04:00
/*
* Initialize socket for RPC use and create svc_sock struct
*/
2007-02-12 11:53:28 +03:00
static struct svc_sock * svc_setup_socket ( struct svc_serv * serv ,
struct socket * sock ,
2012-08-14 01:46:17 +04:00
int flags )
2005-04-17 02:20:36 +04:00
{
struct svc_sock * svsk ;
struct sock * inet ;
2007-02-12 11:53:28 +03:00
int pmap_register = ! ( flags & SVC_SOCK_ANONYMOUS ) ;
2012-08-14 01:46:17 +04:00
int err = 0 ;
2005-04-17 02:20:36 +04:00
dprintk ( " svc: svc_setup_socket %p \n " , sock ) ;
2012-08-14 01:46:17 +04:00
svsk = kzalloc ( sizeof ( * svsk ) , GFP_KERNEL ) ;
if ( ! svsk )
return ERR_PTR ( - ENOMEM ) ;
2005-04-17 02:20:36 +04:00
inet = sock - > sk ;
/* Register socket with portmapper */
2012-08-14 01:46:17 +04:00
if ( pmap_register )
err = svc_register ( serv , sock_net ( sock - > sk ) , inet - > sk_family ,
2012-01-13 14:02:48 +04:00
inet - > sk_protocol ,
2009-10-15 10:30:45 +04:00
ntohs ( inet_sk ( inet ) - > inet_sport ) ) ;
2005-04-17 02:20:36 +04:00
2012-08-14 01:46:17 +04:00
if ( err < 0 ) {
2005-04-17 02:20:36 +04:00
kfree ( svsk ) ;
2012-08-14 01:46:17 +04:00
return ERR_PTR ( err ) ;
2005-04-17 02:20:36 +04:00
}
inet - > sk_user_data = svsk ;
svsk - > sk_sock = sock ;
svsk - > sk_sk = inet ;
svsk - > sk_ostate = inet - > sk_state_change ;
svsk - > sk_odata = inet - > sk_data_ready ;
svsk - > sk_owspace = inet - > sk_write_space ;
/* Initialize the socket */
if ( sock - > type = = SOCK_DGRAM )
2007-12-31 06:07:50 +03:00
svc_udp_init ( svsk , serv ) ;
2016-06-24 17:55:51 +03:00
else
2007-12-31 06:07:50 +03:00
svc_tcp_init ( svsk , serv ) ;
2005-04-17 02:20:36 +04:00
2016-07-26 16:51:20 +03:00
dprintk ( " svc: svc_setup_socket created %p (inet %p), "
" listen %d close %d \n " ,
svsk , svsk - > sk_sk ,
test_bit ( XPT_LISTENER , & svsk - > sk_xprt . xpt_flags ) ,
test_bit ( XPT_CLOSE , & svsk - > sk_xprt . xpt_flags ) ) ;
2005-04-17 02:20:36 +04:00
return svsk ;
}
2014-02-26 17:50:01 +04:00
bool svc_alien_sock ( struct net * net , int fd )
{
int err ;
struct socket * sock = sockfd_lookup ( fd , & err ) ;
bool ret = false ;
if ( ! sock )
goto out ;
if ( sock_net ( sock - > sk ) ! = net )
ret = true ;
sockfd_put ( sock ) ;
out :
return ret ;
}
EXPORT_SYMBOL_GPL ( svc_alien_sock ) ;
2009-04-24 03:32:33 +04:00
/**
* svc_addsock - add a listener socket to an RPC service
* @ serv : pointer to RPC service to which to add a new listener
* @ fd : file descriptor of the new listener
* @ name_return : pointer to buffer to fill in with name of listener
* @ len : size of the buffer
*
* Fills in socket name and returns positive length of name if successful .
* Name is terminated with ' \n ' . On error , returns a negative errno
* value .
*/
int svc_addsock ( struct svc_serv * serv , const int fd , char * name_return ,
const size_t len )
2006-10-02 13:17:48 +04:00
{
int err = 0 ;
struct socket * so = sockfd_lookup ( fd , & err ) ;
struct svc_sock * svsk = NULL ;
2012-08-14 02:01:03 +04:00
struct sockaddr_storage addr ;
struct sockaddr * sin = ( struct sockaddr * ) & addr ;
int salen ;
2006-10-02 13:17:48 +04:00
if ( ! so )
return err ;
2012-08-14 02:01:03 +04:00
err = - EAFNOSUPPORT ;
2010-01-26 22:03:56 +03:00
if ( ( so - > sk - > sk_family ! = PF_INET ) & & ( so - > sk - > sk_family ! = PF_INET6 ) )
2012-08-14 02:01:03 +04:00
goto out ;
err = - EPROTONOSUPPORT ;
if ( so - > sk - > sk_protocol ! = IPPROTO_TCP & &
2006-10-02 13:17:48 +04:00
so - > sk - > sk_protocol ! = IPPROTO_UDP )
2012-08-14 02:01:03 +04:00
goto out ;
err = - EISCONN ;
if ( so - > state > SS_UNCONNECTED )
goto out ;
err = - ENOENT ;
if ( ! try_module_get ( THIS_MODULE ) )
goto out ;
svsk = svc_setup_socket ( serv , so , SVC_SOCK_DEFAULTS ) ;
if ( IS_ERR ( svsk ) ) {
module_put ( THIS_MODULE ) ;
err = PTR_ERR ( svsk ) ;
goto out ;
2006-10-02 13:17:48 +04:00
}
2012-08-14 02:01:03 +04:00
if ( kernel_getsockname ( svsk - > sk_sock , sin , & salen ) = = 0 )
svc_xprt_set_local ( & svsk - > sk_xprt , sin , salen ) ;
2012-08-14 23:50:34 +04:00
svc_add_new_perm_xprt ( serv , & svsk - > sk_xprt ) ;
2009-04-24 03:32:48 +04:00
return svc_one_sock_name ( svsk , name_return , len ) ;
2012-08-14 02:01:03 +04:00
out :
sockfd_put ( so ) ;
return err ;
2006-10-02 13:17:48 +04:00
}
EXPORT_SYMBOL_GPL ( svc_addsock ) ;
2005-04-17 02:20:36 +04:00
/*
* Create socket for RPC service .
*/
2007-12-31 06:07:42 +03:00
static struct svc_xprt * svc_create_socket ( struct svc_serv * serv ,
int protocol ,
2010-09-29 16:04:18 +04:00
struct net * net ,
2007-12-31 06:07:42 +03:00
struct sockaddr * sin , int len ,
int flags )
2005-04-17 02:20:36 +04:00
{
struct svc_sock * svsk ;
struct socket * sock ;
int error ;
int type ;
2007-12-31 06:08:12 +03:00
struct sockaddr_storage addr ;
struct sockaddr * newsin = ( struct sockaddr * ) & addr ;
int newlen ;
2009-03-31 02:59:17 +04:00
int family ;
int val ;
2008-02-21 10:57:45 +03:00
RPC_IFDEBUG ( char buf [ RPC_MAX_ADDRBUFLEN ] ) ;
2005-04-17 02:20:36 +04:00
2007-02-12 11:53:32 +03:00
dprintk ( " svc: svc_create_socket(%s, %d, %s) \n " ,
serv - > sv_program - > pg_name , protocol ,
2007-02-12 11:53:39 +03:00
__svc_print_addr ( sin , buf , sizeof ( buf ) ) ) ;
2005-04-17 02:20:36 +04:00
if ( protocol ! = IPPROTO_UDP & & protocol ! = IPPROTO_TCP ) {
printk ( KERN_WARNING " svc: only UDP and TCP "
" sockets supported \n " ) ;
2007-12-31 06:07:42 +03:00
return ERR_PTR ( - EINVAL ) ;
2005-04-17 02:20:36 +04:00
}
2009-03-31 02:59:17 +04:00
2005-04-17 02:20:36 +04:00
type = ( protocol = = IPPROTO_UDP ) ? SOCK_DGRAM : SOCK_STREAM ;
2009-03-31 02:59:17 +04:00
switch ( sin - > sa_family ) {
case AF_INET6 :
family = PF_INET6 ;
break ;
case AF_INET :
family = PF_INET ;
break ;
default :
return ERR_PTR ( - EINVAL ) ;
}
2005-04-17 02:20:36 +04:00
2010-09-29 16:06:57 +04:00
error = __sock_create ( net , family , type , protocol , & sock , 1 ) ;
2007-02-12 11:53:39 +03:00
if ( error < 0 )
2007-12-31 06:07:42 +03:00
return ERR_PTR ( error ) ;
2005-04-17 02:20:36 +04:00
2006-12-07 07:35:24 +03:00
svc_reclassify_socket ( sock ) ;
2009-03-31 02:59:17 +04:00
/*
* If this is an PF_INET6 listener , we want to avoid
* getting requests from IPv4 remotes . Those should
* be shunted to a PF_INET listener via rpcbind .
*/
val = 1 ;
if ( family = = PF_INET6 )
kernel_setsockopt ( sock , SOL_IPV6 , IPV6_V6ONLY ,
( char * ) & val , sizeof ( val ) ) ;
2006-09-29 01:37:07 +04:00
if ( type = = SOCK_STREAM )
2012-04-19 07:39:36 +04:00
sock - > sk - > sk_reuse = SK_CAN_REUSE ; /* allow address reuse */
2007-02-12 11:53:39 +03:00
error = kernel_bind ( sock , sin , len ) ;
2006-09-29 01:37:07 +04:00
if ( error < 0 )
goto bummer ;
2005-04-17 02:20:36 +04:00
2007-12-31 06:08:12 +03:00
newlen = len ;
error = kernel_getsockname ( sock , newsin , & newlen ) ;
if ( error < 0 )
goto bummer ;
2005-04-17 02:20:36 +04:00
if ( protocol = = IPPROTO_TCP ) {
2006-08-08 07:58:01 +04:00
if ( ( error = kernel_listen ( sock , 64 ) ) < 0 )
2005-04-17 02:20:36 +04:00
goto bummer ;
}
2012-08-14 01:46:17 +04:00
svsk = svc_setup_socket ( serv , sock , flags ) ;
2012-08-14 02:01:03 +04:00
if ( IS_ERR ( svsk ) ) {
error = PTR_ERR ( svsk ) ;
goto bummer ;
2007-02-12 11:53:30 +03:00
}
2012-08-14 02:01:03 +04:00
svc_xprt_set_local ( & svsk - > sk_xprt , newsin , newlen ) ;
return ( struct svc_xprt * ) svsk ;
2005-04-17 02:20:36 +04:00
bummer :
dprintk ( " svc: svc_create_socket error = %d \n " , - error ) ;
sock_release ( sock ) ;
2007-12-31 06:07:42 +03:00
return ERR_PTR ( error ) ;
2005-04-17 02:20:36 +04:00
}
2007-12-31 06:07:27 +03:00
/*
* Detach the svc_sock from the socket so that no
* more callbacks occur .
*/
static void svc_sock_detach ( struct svc_xprt * xprt )
{
struct svc_sock * svsk = container_of ( xprt , struct svc_sock , sk_xprt ) ;
struct sock * sk = svsk - > sk_sk ;
dprintk ( " svc: svc_sock_detach(%p) \n " , svsk ) ;
/* put back the old socket callbacks */
2016-06-24 17:55:47 +03:00
lock_sock ( sk ) ;
2007-12-31 06:07:27 +03:00
sk - > sk_state_change = svsk - > sk_ostate ;
sk - > sk_data_ready = svsk - > sk_odata ;
sk - > sk_write_space = svsk - > sk_owspace ;
2016-06-24 17:55:47 +03:00
sk - > sk_user_data = NULL ;
release_sock ( sk ) ;
2008-12-24 00:30:11 +03:00
}
/*
* Disconnect the socket , and reset the callbacks
*/
static void svc_tcp_sock_detach ( struct svc_xprt * xprt )
{
struct svc_sock * svsk = container_of ( xprt , struct svc_sock , sk_xprt ) ;
dprintk ( " svc: svc_tcp_sock_detach(%p) \n " , svsk ) ;
svc_sock_detach ( xprt ) ;
2011-02-24 22:25:33 +03:00
if ( ! test_bit ( XPT_LISTENER , & xprt - > xpt_flags ) ) {
svc_tcp_clear_pages ( svsk ) ;
2008-12-24 00:30:11 +03:00
kernel_sock_shutdown ( svsk - > sk_sock , SHUT_RDWR ) ;
2011-02-24 22:25:33 +03:00
}
2007-12-31 06:07:27 +03:00
}
/*
* Free the svc_sock ' s socket resources and the svc_sock itself .
*/
static void svc_sock_free ( struct svc_xprt * xprt )
{
struct svc_sock * svsk = container_of ( xprt , struct svc_sock , sk_xprt ) ;
dprintk ( " svc: svc_sock_free(%p) \n " , svsk ) ;
if ( svsk - > sk_sock - > file )
sockfd_put ( svsk - > sk_sock ) ;
else
sock_release ( svsk - > sk_sock ) ;
kfree ( svsk ) ;
}
2009-04-01 17:23:09 +04:00
2011-07-14 03:20:49 +04:00
# if defined(CONFIG_SUNRPC_BACKCHANNEL)
2009-04-01 17:23:09 +04:00
/*
2011-01-06 05:04:26 +03:00
* Create a back channel svc_xprt which shares the fore channel socket .
2009-04-01 17:23:09 +04:00
*/
2011-01-06 05:04:26 +03:00
static struct svc_xprt * svc_bc_create_socket ( struct svc_serv * serv ,
int protocol ,
struct net * net ,
struct sockaddr * sin , int len ,
int flags )
2009-04-01 17:23:09 +04:00
{
struct svc_sock * svsk ;
2011-01-06 05:04:26 +03:00
struct svc_xprt * xprt ;
if ( protocol ! = IPPROTO_TCP ) {
printk ( KERN_WARNING " svc: only TCP sockets "
" supported on shared back channel \n " ) ;
return ERR_PTR ( - EINVAL ) ;
}
2009-04-01 17:23:09 +04:00
svsk = kzalloc ( sizeof ( * svsk ) , GFP_KERNEL ) ;
if ( ! svsk )
2011-01-06 05:04:26 +03:00
return ERR_PTR ( - ENOMEM ) ;
2009-04-01 17:23:09 +04:00
xprt = & svsk - > sk_xprt ;
2011-12-06 15:19:10 +04:00
svc_xprt_init ( net , & svc_tcp_bc_class , xprt , serv ) ;
2011-01-06 05:04:26 +03:00
2011-01-06 05:04:35 +03:00
serv - > sv_bc_xprt = xprt ;
2011-01-06 05:04:26 +03:00
2009-04-01 17:23:09 +04:00
return xprt ;
}
/*
2011-01-06 05:04:26 +03:00
* Free a back channel svc_sock .
2009-04-01 17:23:09 +04:00
*/
2011-01-06 05:04:26 +03:00
static void svc_bc_sock_free ( struct svc_xprt * xprt )
2009-04-01 17:23:09 +04:00
{
2011-01-25 18:38:01 +03:00
if ( xprt )
2009-04-01 17:23:09 +04:00
kfree ( container_of ( xprt , struct svc_sock , sk_xprt ) ) ;
}
2011-07-14 03:20:49 +04:00
# endif /* CONFIG_SUNRPC_BACKCHANNEL */