2005-04-17 02:20:36 +04:00
/*
* linux / fs / lockd / xdr . c
*
* XDR support for lockd and the lock client .
*
* Copyright ( C ) 1995 , 1996 Olaf Kirch < okir @ monad . swb . de >
*/
# 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
s32_to_loff_t ( __s32 offset )
{
return ( loff_t ) offset ;
}
static inline __s32
loff_t_to_s32 ( loff_t offset )
{
__s32 res ;
if ( offset > = NLM_OFFSET_MAX )
res = NLM_OFFSET_MAX ;
else if ( offset < = - NLM_OFFSET_MAX )
res = - NLM_OFFSET_MAX ;
else
res = offset ;
return res ;
}
/*
* XDR functions for basic NLM types
*/
2006-10-20 10:28:46 +04:00
static __be32 * nlm_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 inline __be32 *
nlm_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 *
nlm_decode_fh ( __be32 * p , struct nfs_fh * f )
2005-04-17 02:20:36 +04:00
{
unsigned int len ;
if ( ( len = ntohl ( * p + + ) ) ! = NFS2_FHSIZE ) {
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
len , NFS2_FHSIZE ) ;
return NULL ;
}
f - > size = NFS2_FHSIZE ;
memset ( f - > data , 0 , sizeof ( f - > data ) ) ;
memcpy ( f - > data , p , NFS2_FHSIZE ) ;
return p + XDR_QUADLEN ( NFS2_FHSIZE ) ;
}
2006-10-20 10:28:46 +04:00
static inline __be32 *
nlm_encode_fh ( __be32 * p , struct nfs_fh * f )
2005-04-17 02:20:36 +04:00
{
* p + + = htonl ( NFS2_FHSIZE ) ;
memcpy ( p , f - > data , NFS2_FHSIZE ) ;
return p + XDR_QUADLEN ( NFS2_FHSIZE ) ;
}
/*
* Encode and decode owner handle
*/
2006-10-20 10:28:46 +04:00
static inline __be32 *
nlm_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 inline __be32 *
nlm_encode_oh ( __be32 * p , struct xdr_netobj * oh )
2005-04-17 02:20:36 +04:00
{
return xdr_encode_netobj ( p , oh ) ;
}
2006-10-20 10:28:46 +04:00
static __be32 *
nlm_decode_lock ( __be32 * p , struct nlm_lock * lock )
2005-04-17 02:20:36 +04:00
{
struct file_lock * fl = & lock - > fl ;
s32 start , len , end ;
if ( ! ( p = xdr_decode_string_inplace ( p , & lock - > caller ,
& lock - > len ,
NLM_MAXSTRLEN ) )
| | ! ( p = nlm_decode_fh ( p , & lock - > fh ) )
| | ! ( p = nlm_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 */
start = ntohl ( * p + + ) ;
len = ntohl ( * p + + ) ;
end = start + len - 1 ;
fl - > fl_start = s32_to_loff_t ( start ) ;
if ( len = = 0 | | end < 0 )
fl - > fl_end = OFFSET_MAX ;
else
fl - > fl_end = s32_to_loff_t ( end ) ;
return p ;
}
/*
* Encode result of a TEST / TEST_MSG call
*/
2006-10-20 10:28:46 +04:00
static __be32 *
nlm_encode_testres ( __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
s32 start , len ;
if ( ! ( p = nlm_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_s32 ( fl - > fl_start ) ;
if ( fl - > fl_end = = OFFSET_MAX )
len = 0 ;
else
len = loff_t_to_s32 ( fl - > fl_end - fl - > fl_start + 1 ) ;
* p + + = htonl ( start ) ;
* p + + = htonl ( len ) ;
}
return p ;
}
/*
* First , the server side XDR functions
*/
int
2006-10-20 10:28:46 +04:00
nlmsvc_decode_testargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
u32 exclusive ;
if ( ! ( p = nlm_decode_cookie ( p , & argp - > cookie ) ) )
return 0 ;
exclusive = ntohl ( * p + + ) ;
if ( ! ( p = nlm_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
nlmsvc_encode_testres ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm_encode_testres ( p , resp ) ) )
return 0 ;
return xdr_ressize_check ( rqstp , p ) ;
}
int
2006-10-20 10:28:46 +04:00
nlmsvc_decode_lockargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
u32 exclusive ;
if ( ! ( p = nlm_decode_cookie ( p , & argp - > cookie ) ) )
return 0 ;
argp - > block = ntohl ( * p + + ) ;
exclusive = ntohl ( * p + + ) ;
if ( ! ( p = nlm_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
nlmsvc_decode_cancargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
u32 exclusive ;
if ( ! ( p = nlm_decode_cookie ( p , & argp - > cookie ) ) )
return 0 ;
argp - > block = ntohl ( * p + + ) ;
exclusive = ntohl ( * p + + ) ;
if ( ! ( p = nlm_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
nlmsvc_decode_unlockargs ( struct svc_rqst * rqstp , __be32 * p , nlm_args * argp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm_decode_cookie ( p , & argp - > cookie ) )
| | ! ( p = nlm_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
nlmsvc_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 = nlm_decode_cookie ( p , & argp - > cookie ) )
| | ! ( p = xdr_decode_string_inplace ( p , & lock - > caller ,
& lock - > len , NLM_MAXSTRLEN ) )
| | ! ( p = nlm_decode_fh ( p , & lock - > fh ) )
| | ! ( p = nlm_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
nlmsvc_encode_shareres ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm_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
nlmsvc_encode_res ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm_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
nlmsvc_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
nlmsvc_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
nlmsvc_decode_res ( struct svc_rqst * rqstp , __be32 * p , struct nlm_res * resp )
2005-04-17 02:20:36 +04:00
{
if ( ! ( p = nlm_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
nlmsvc_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
nlmsvc_encode_void ( struct svc_rqst * rqstp , __be32 * p , void * dummy )
2005-04-17 02:20:36 +04:00
{
return xdr_ressize_check ( rqstp , p ) ;
}