2005-04-17 02:20:36 +04:00
/*
* linux / fs / lockd / xdr4 . c
*
* XDR support for lockd and the lock client .
*
* Copyright ( C ) 1995 , 1996 Olaf Kirch < okir @ monad . swb . de >
* Copyright ( C ) 1999 , Trond Myklebust < trond . myklebust @ fys . uio . no >
*/
# include <linux/types.h>
# include <linux/sched.h>
# include <linux/nfs.h>
# include <linux/sunrpc/xdr.h>
# include <linux/sunrpc/clnt.h>
# include <linux/sunrpc/svc.h>
# include <linux/sunrpc/stats.h>
# include <linux/lockd/lockd.h>
# define NLMDBG_FACILITY NLMDBG_XDR
static inline loff_t
s64_to_loff_t ( __s64 offset )
{
return ( loff_t ) offset ;
}
static inline s64
loff_t_to_s64 ( loff_t offset )
{
s64 res ;
if ( offset > NLM4_OFFSET_MAX )
res = NLM4_OFFSET_MAX ;
else if ( offset < - NLM4_OFFSET_MAX )
res = - NLM4_OFFSET_MAX ;
else
res = offset ;
return res ;
}
/*
* XDR functions for basic NLM types
*/
2006-10-20 10:28:46 +04:00
static __be32 *
nlm4_decode_cookie ( __be32 * p , struct nlm_cookie * c )
2005-04-17 02:20:36 +04:00
{
unsigned int len ;
len = ntohl ( * p + + ) ;
if ( len = = 0 )
{
c - > len = 4 ;
memset ( c - > data , 0 , 4 ) ; /* hockeypux brain damage */
}
else if ( len < = NLM_MAXCOOKIELEN )
{
c - > len = len ;
memcpy ( c - > data , p , len ) ;
p + = XDR_QUADLEN ( len ) ;
}
else
{
2007-09-12 02:01:15 +04:00
dprintk ( " lockd: bad cookie size %d (only cookies under "
" %d bytes are supported.) \n " ,
len , NLM_MAXCOOKIELEN ) ;
2005-04-17 02:20:36 +04:00
return NULL ;
}
return p ;
}
2006-10-20 10:28:46 +04:00
static __be32 *
nlm4_encode_cookie ( __be32 * p , struct nlm_cookie * c )
2005-04-17 02:20:36 +04:00
{
* p + + = htonl ( c - > len ) ;
memcpy ( p , c - > data , c - > len ) ;
p + = XDR_QUADLEN ( c - > len ) ;
return p ;
}
2006-10-20 10:28:46 +04:00
static __be32 *
nlm4_decode_fh ( __be32 * p , struct nfs_fh * f )
2005-04-17 02:20:36 +04:00
{
memset ( f - > data , 0 , sizeof ( f - > data ) ) ;
f - > size = ntohl ( * p + + ) ;
if ( f - > size > NFS_MAXFHSIZE ) {
2007-09-12 02:01:15 +04:00
dprintk ( " lockd: bad fhandle size %d (should be <=%d) \n " ,
2005-04-17 02:20:36 +04:00
f - > size , NFS_MAXFHSIZE ) ;
return NULL ;
}
memcpy ( f - > data , p , f - > size ) ;
return p + XDR_QUADLEN ( f - > size ) ;
}
/*
* Encode and decode owner handle
*/
2006-10-20 10:28:46 +04:00
static __be32 *
nlm4_decode_oh ( __be32 * p , struct xdr_netobj * oh )
2005-04-17 02:20:36 +04:00
{
return xdr_decode_netobj ( p , oh ) ;
}
2006-10-20 10:28:46 +04:00
static __be32 *
nlm4_decode_lock ( __be32 * p , struct nlm_lock * lock )
2005-04-17 02:20:36 +04:00
{
struct file_lock * fl = & lock - > fl ;
2007-05-15 01:21:26 +04:00
__u64 len , start ;
__s64 end ;
2005-04-17 02:20:36 +04:00
if ( ! ( p = xdr_decode_string_inplace ( p , & lock - > caller ,
& lock - > len , NLM_MAXSTRLEN ) )
| | ! ( p = nlm4_decode_fh ( p , & lock - > fh ) )
| | ! ( p = nlm4_decode_oh ( p , & lock - > oh ) ) )
return NULL ;
2006-03-20 21:44:06 +03:00
lock - > svid = ntohl ( * p + + ) ;
2005-04-17 02:20:36 +04:00
locks_init_lock ( fl ) ;
fl - > fl_owner = current - > files ;
2006-03-20 21:44:06 +03:00
fl - > fl_pid = ( pid_t ) lock - > svid ;
2005-04-17 02:20:36 +04:00
fl - > fl_flags = FL_POSIX ;
fl - > fl_type = F_RDLCK ; /* as good as anything else */
p = xdr_decode_hyper ( p , & start ) ;
p = xdr_decode_hyper ( p , & len ) ;
end = start + len - 1 ;
fl - > fl_start = s64_to_loff_t ( start ) ;
if ( len = = 0 | | end < 0 )
fl - > fl_end = OFFSET_MAX ;
else
fl - > fl_end = s64_to_loff_t ( end ) ;
return p ;
}
/*
* Encode result of a TEST / TEST_MSG call
*/
2006-10-20 10:28:46 +04:00
static __be32 *
nlm4_encode_testres ( __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
s64 start , len ;
dprintk ( " xdr: before encode_testres (p %p resp %p) \n " , p , resp ) ;
if ( ! ( p = nlm4_encode_cookie ( p , & resp - > cookie ) ) )
return NULL ;
* p + + = resp - > status ;
if ( resp - > status = = nlm_lck_denied ) {
struct file_lock * fl = & resp - > lock . fl ;
* p + + = ( fl - > fl_type = = F_RDLCK ) ? xdr_zero : xdr_one ;
2006-03-20 21:44:06 +03:00
* p + + = htonl ( resp - > lock . svid ) ;
2005-04-17 02:20:36 +04:00
/* Encode owner handle. */
if ( ! ( p = xdr_encode_netobj ( p , & resp - > lock . oh ) ) )
return NULL ;
start = loff_t_to_s64 ( fl - > fl_start ) ;
if ( fl - > fl_end = = OFFSET_MAX )
len = 0 ;
else
len = loff_t_to_s64 ( fl - > fl_end - fl - > fl_start + 1 ) ;
p = xdr_encode_hyper ( p , start ) ;
p = xdr_encode_hyper ( p , len ) ;
2006-03-20 21:44:06 +03:00
dprintk ( " xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld) \n " ,
resp - > status , ( int ) resp - > lock . svid , fl - > fl_type ,
2005-04-17 02:20:36 +04:00
( long long ) fl - > fl_start , ( long long ) fl - > fl_end ) ;
}
dprintk ( " xdr: after encode_testres (p %p resp %p) \n " , p , resp ) ;
return p ;
}
/*
* First , the server side XDR functions
*/
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_testargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
u32 exclusive ;
if ( ! ( p = nlm4_decode_cookie ( p , & argp - > cookie ) ) )
return 0 ;
exclusive = ntohl ( * p + + ) ;
if ( ! ( p = nlm4_decode_lock ( p , & argp - > lock ) ) )
return 0 ;
if ( exclusive )
argp - > lock . fl . fl_type = F_WRLCK ;
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_encode_testres ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm4_encode_testres ( p , resp ) ) )
return 0 ;
return xdr_ressize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_lockargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
u32 exclusive ;
if ( ! ( p = nlm4_decode_cookie ( p , & argp - > cookie ) ) )
return 0 ;
argp - > block = ntohl ( * p + + ) ;
exclusive = ntohl ( * p + + ) ;
if ( ! ( p = nlm4_decode_lock ( p , & argp - > lock ) ) )
return 0 ;
if ( exclusive )
argp - > lock . fl . fl_type = F_WRLCK ;
argp - > reclaim = ntohl ( * p + + ) ;
argp - > state = ntohl ( * p + + ) ;
argp - > monitor = 1 ; /* monitor client by default */
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_cancargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
u32 exclusive ;
if ( ! ( p = nlm4_decode_cookie ( p , & argp - > cookie ) ) )
return 0 ;
argp - > block = ntohl ( * p + + ) ;
exclusive = ntohl ( * p + + ) ;
if ( ! ( p = nlm4_decode_lock ( p , & argp - > lock ) ) )
return 0 ;
if ( exclusive )
argp - > lock . fl . fl_type = F_WRLCK ;
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_unlockargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm4_decode_cookie ( p , & argp - > cookie ) )
| | ! ( p = nlm4_decode_lock ( p , & argp - > lock ) ) )
return 0 ;
argp - > lock . fl . fl_type = F_UNLCK ;
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_shareargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
struct nlm_lock * lock = & argp - > lock ;
memset ( lock , 0 , sizeof ( * lock ) ) ;
locks_init_lock ( & lock - > fl ) ;
2006-03-20 21:44:06 +03:00
lock - > svid = ~ ( u32 ) 0 ;
lock - > fl . fl_pid = ( pid_t ) lock - > svid ;
2005-04-17 02:20:36 +04:00
if ( ! ( p = nlm4_decode_cookie ( p , & argp - > cookie ) )
| | ! ( p = xdr_decode_string_inplace ( p , & lock - > caller ,
& lock - > len , NLM_MAXSTRLEN ) )
| | ! ( p = nlm4_decode_fh ( p , & lock - > fh ) )
| | ! ( p = nlm4_decode_oh ( p , & lock - > oh ) ) )
return 0 ;
argp - > fsm_mode = ntohl ( * p + + ) ;
argp - > fsm_access = ntohl ( * p + + ) ;
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_encode_shareres ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm4_encode_cookie ( p , & resp - > cookie ) ) )
return 0 ;
* p + + = resp - > status ;
* p + + = xdr_zero ; /* sequence argument */
return xdr_ressize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_encode_res ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm4_encode_cookie ( p , & resp - > cookie ) ) )
return 0 ;
* p + + = resp - > status ;
return xdr_ressize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_notify ( struct svc_rqst * rqstp , __be32 * p , struct nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
struct nlm_lock * lock = & argp - > lock ;
if ( ! ( p = xdr_decode_string_inplace ( p , & lock - > caller ,
& lock - > len , NLM_MAXSTRLEN ) ) )
return 0 ;
argp - > state = ntohl ( * p + + ) ;
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_reboot ( struct svc_rqst * rqstp , __be32 * p , struct nlm_reboot * argp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = xdr_decode_string_inplace ( p , & argp - > mon , & argp - > len , SM_MAXSTRLEN ) ) )
return 0 ;
argp - > state = ntohl ( * p + + ) ;
2008-12-06 03:03:39 +03:00
memcpy ( & argp - > priv . data , p , sizeof ( argp - > priv . data ) ) ;
p + = XDR_QUADLEN ( SM_PRIV_SIZE ) ;
2005-04-17 02:20:36 +04:00
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_res ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm4_decode_cookie ( p , & resp - > cookie ) ) )
return 0 ;
2006-12-13 11:35:03 +03:00
resp - > status = * p + + ;
2005-04-17 02:20:36 +04:00
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_decode_void ( struct svc_rqst * rqstp , __be32 * p , void * dummy )
2005-04-17 02:20:36 +04:00
{
return xdr_argsize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlm4svc_encode_void ( struct svc_rqst * rqstp , __be32 * p , void * dummy )
2005-04-17 02:20:36 +04:00
{
return xdr_ressize_check ( rqstp , p ) ;
}