nfs-ganesha 1.4

fsal_proxy_clientid.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  */
00004 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #ifdef _SOLARIS
00019 #include "solaris_port.h"
00020 #endif                          /* _SOLARIS */
00021 
00022 #include <string.h>
00023 #ifdef _USE_GSSRPC
00024 #include <gssrpc/rpc.h>
00025 #include <gssrpc/xdr.h>
00026 #else
00027 #include <rpc/rpc.h>
00028 #include <rpc/xdr.h>
00029 #endif
00030 #include <arpa/inet.h>
00031 #include <pthread.h>
00032 #include "nfs4.h"
00033 
00034 #include "fsal_internal.h"
00035 #include "fsal_convert.h"
00036 #include "fsal_common.h"
00037 
00038 #include "nfs_proto_functions.h"
00039 #include "fsal_nfsv4_macros.h"
00040 
00041 extern time_t ServerBootTime;
00042 
00043 clientid4 fsal_clientid;
00044 time_t     clientid_renewed ;
00045 pthread_mutex_t fsal_clientid_mutex = PTHREAD_MUTEX_INITIALIZER;
00046 pthread_mutex_t fsal_clientid_mutex_renew = PTHREAD_MUTEX_INITIALIZER;
00047 unsigned int done = 0;
00048 
00062 static fsal_status_t FSAL_proxy_setclientid_force(proxyfsal_op_context_t * p_context)
00063 {
00064   int rc;
00065   COMPOUND4args argnfs4;
00066   COMPOUND4res resnfs4;
00067 
00068 #define FSAL_CLIENTID_NB_OP_ALLOC 1
00069   nfs_argop4 argoparray[FSAL_CLIENTID_NB_OP_ALLOC];
00070   nfs_resop4 resoparray[FSAL_CLIENTID_NB_OP_ALLOC];
00071 
00072   nfs_client_id4 nfsclientid;
00073   cb_client4 cbproxy;
00074   char clientid_name[MAXNAMLEN];
00075   char cbaddr[MAXNAMLEN];
00076   char cbnetid[MAXNAMLEN];
00077   struct timeval timeout = TIMEOUTRPC;
00078   int fd;
00079   struct sockaddr_in sin;
00080   socklen_t l = sizeof(sin);
00081 
00082   LogEvent( COMPONENT_FSAL, "Negotiating a new ClientId with the remote server" ) ;
00083 
00084   /* sanity checks.
00085    */
00086   if(!p_context)
00087     ReturnCode(ERR_FSAL_FAULT, 0);
00088   if(!CLNT_CONTROL(p_context->rpc_client, CLGET_FD, &fd))
00089     ReturnCode(ERR_FSAL_FAULT, EBADF);
00090 
00091   if(getsockname(fd, &sin, &l))
00092     ReturnCode(ERR_FSAL_FAULT, errno);
00093 
00094   /* Client id negociation is to be done only one time for the whole FSAL */
00095   P(fsal_clientid_mutex_renew);
00096 
00097   /* Setup results structures */
00098   argnfs4.argarray.argarray_val = argoparray;
00099   resnfs4.resarray.resarray_val = resoparray;
00100   argnfs4.minorversion = 0;
00101   argnfs4.tag.utf8string_val = NULL;
00102   argnfs4.tag.utf8string_len = 0;
00103   argnfs4.argarray.argarray_len = 0;
00104 
00105   snprintf(clientid_name, MAXNAMLEN, "%s(%d) - GANESHA NFSv4 Proxy",
00106            inet_ntop(AF_INET, &sin.sin_addr, cbaddr, sizeof(cbaddr)),
00107            getpid());
00108 
00109   nfsclientid.id.id_len = strlen(clientid_name);
00110   nfsclientid.id.id_val = clientid_name;
00111   snprintf(nfsclientid.verifier, NFS4_VERIFIER_SIZE, "%x", (int)ServerBootTime);
00112 
00113   cbproxy.cb_program = 0;
00114   strncpy(cbnetid, "tcp", MAXNAMLEN);
00115   strncpy(cbaddr, "127.0.0.1", MAXNAMLEN);
00116   cbproxy.cb_location.r_netid = cbnetid;
00117   cbproxy.cb_location.r_addr = cbaddr;
00118 
00119   COMPOUNDV4_ARG_ADD_OP_SETCLIENTID(argnfs4, nfsclientid, cbproxy);
00120 
00121   TakeTokenFSCall();
00122 
00123   p_context->credential.user = 0;
00124   p_context->credential.group = 0;
00125   p_context->credential.nbgroups = 0;
00126 
00127   /* Call the NFSv4 function */
00128   rc = COMPOUNDV4_EXECUTE_SIMPLE(p_context, argnfs4, resnfs4);
00129   if(rc != RPC_SUCCESS)
00130     {
00131       ReleaseTokenFSCall();
00132 
00133       V(fsal_clientid_mutex_renew);
00134 
00135       ReturnCode(ERR_FSAL_IO, rc);
00136     }
00137 
00138   ReleaseTokenFSCall();
00139 
00140   if(resnfs4.status != NFS4_OK)
00141     {
00142       V(fsal_clientid_mutex_renew);
00143       return fsal_internal_proxy_error_convert(resnfs4.status,
00144                                                INDEX_FSAL_InitClientContext);
00145     }
00146 
00147   /* Step 2: Confirm the client id */
00148   argnfs4.minorversion = 0;
00149   argnfs4.tag.utf8string_val = NULL;
00150   argnfs4.tag.utf8string_len = 0;
00151   argnfs4.argarray.argarray_len = 0;
00152 
00153   argnfs4.argarray.argarray_val[0].argop = NFS4_OP_SETCLIENTID_CONFIRM;
00154   argnfs4.argarray.argarray_val[0].nfs_argop4_u.opsetclientid_confirm.clientid =
00155       resnfs4.resarray.resarray_val[0].nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.
00156       resok4.clientid;
00157   memcpy((char *)argnfs4.argarray.argarray_val[0].nfs_argop4_u.opsetclientid_confirm.
00158          setclientid_confirm,
00159          (char *)resnfs4.resarray.resarray_val[0].nfs_resop4_u.opsetclientid.
00160          SETCLIENTID4res_u.resok4.setclientid_confirm, NFS4_VERIFIER_SIZE);
00161   argnfs4.argarray.argarray_len = 1;
00162 
00163   /* Call the NFSv4 function */
00164   TakeTokenFSCall();
00165   rc = COMPOUNDV4_EXECUTE_SIMPLE(p_context, argnfs4, resnfs4);
00166   if(rc != RPC_SUCCESS)
00167     {
00168       ReleaseTokenFSCall();
00169 
00170       V(fsal_clientid_mutex_renew);
00171 
00172       ReturnCode(ERR_FSAL_IO, rc);
00173     }
00174 
00175   ReleaseTokenFSCall();
00176 
00177   if(resnfs4.status != NFS4_OK)
00178     {
00179       V(fsal_clientid_mutex_renew);
00180       return fsal_internal_proxy_error_convert(resnfs4.status,
00181                                                INDEX_FSAL_InitClientContext);
00182     }
00183 
00184   /* Keep the confirmed client id */
00185   fsal_clientid =
00186       argnfs4.argarray.argarray_val[0].nfs_argop4_u.opsetclientid_confirm.clientid;
00187   clientid_renewed = time( NULL ) ;
00188 
00189   V(fsal_clientid_mutex_renew);
00190 
00191   p_context->clientid = fsal_clientid;
00192   p_context->last_lease_renewal = 0;    /* Needs to be renewed */
00193 
00194   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00195 }                               /* FSAL_proxy_setclientid_force */
00196 
00209 fsal_status_t FSAL_proxy_setclientid_renego(proxyfsal_op_context_t * p_context)
00210 {
00211   time_t now = time( NULL ) ;
00212 
00213   /* The first to come is the only one to do the clientid renegociation */
00214   if( ( p_context->clientid_renewed <  now ) && (p_context->clientid == fsal_clientid ) )
00215     return FSAL_proxy_setclientid_force( p_context ) ;
00216   else
00217    {
00218         p_context->clientid = fsal_clientid ;
00219         p_context->clientid_renewed = clientid_renewed ;
00220         
00221         Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_InitClientContext);
00222    }
00223 } /* FSAL_proxy_setclientid_renego */
00224 
00238 fsal_status_t FSAL_proxy_setclientid(proxyfsal_op_context_t * p_context)
00239 {
00240   fsal_status_t fsal_status ;
00241 
00242   /* sanity checks.
00243    */
00244   if(!p_context)
00245     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_InitClientContext);
00246 
00247   P(fsal_clientid_mutex);
00248   if(done == 0)
00249     {
00250       fsal_status = FSAL_proxy_setclientid_force( p_context ) ;
00251 
00252       done = 1 ;
00253       V(fsal_clientid_mutex);
00254 
00255       p_context->clientid = fsal_clientid;
00256       p_context->last_lease_renewal = 0;    /* Needs to be renewed */
00257 
00258       return fsal_status;
00259     }
00260   V(fsal_clientid_mutex);
00261 
00262   p_context->clientid = fsal_clientid;
00263   p_context->clientid_renewed = clientid_renewed ;
00264   p_context->last_lease_renewal = 0;    /* Needs to be renewed */
00265   
00266   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_InitClientContext);
00267 }                               /* FSAL_proxy_setclientid */
00268 
00277 void *FSAL_proxy_clientid_renewer_thread(void *Arg)
00278 {
00279   int rc;
00280 
00281   COMPOUND4args argnfs4;
00282   COMPOUND4res resnfs4;
00283   struct timeval timeout = TIMEOUTRPC;
00284   fsal_status_t fsal_status;
00285   proxyfsal_op_context_t fsal_context;
00286   proxyfsal_op_context_t *p_context = &fsal_context;
00287 #define FSAL_RENEW_LEASE_NB_OP_ALLOC 1
00288   nfs_argop4 argoparray[FSAL_RENEW_LEASE_NB_OP_ALLOC];
00289   nfs_resop4 resoparray[FSAL_RENEW_LEASE_NB_OP_ALLOC];
00290 
00291   LogEvent(COMPONENT_FSAL, "FSAL_proxy_clientid_refresher_thread: starting...");
00292 
00293   sleep(6);    
00295   memset(&fsal_context, 0, sizeof(proxyfsal_op_context_t));
00296   fsal_status = PROXYFSAL_InitClientContext((fsal_op_context_t *)p_context);
00297 
00298   if(FSAL_IS_ERROR(fsal_status))
00299     {
00300       LogCrit(COMPONENT_FSAL,
00301            "FSAL_proxy_clientid_refresher_thread: FSAL error(%u,%u) during init... exiting",
00302            fsal_status.major, fsal_status.minor);
00303       exit(1);
00304     }
00305 
00306   /* Setup results structures */
00307   argnfs4.argarray.argarray_val = argoparray;
00308   resnfs4.resarray.resarray_val = resoparray;
00309   argnfs4.minorversion = 0;
00310   argnfs4.tag.utf8string_val = NULL;
00311   argnfs4.tag.utf8string_len = 0;
00312   argnfs4.argarray.argarray_len = 0;
00313 
00314   argnfs4.argarray.argarray_val[0].argop = NFS4_OP_RENEW;
00315   argnfs4.argarray.argarray_len = 1;
00316 
00317   while(1)
00318     {
00319       sleep(60);  
00321       /* Call the NFSv4 function */
00322       TakeTokenFSCall();
00323 
00324       argoparray[0].nfs_argop4_u.oprenew.clientid = fsal_clientid;
00325       COMPOUNDV4_EXECUTE(p_context, argnfs4, resnfs4, rc);
00326       if(rc != RPC_SUCCESS)
00327         {
00328           ReleaseTokenFSCall();
00329 
00330           LogCrit(COMPONENT_FSAL, "FSAL_PROXY: /!\\ RPC error when connecting to the server");
00331 
00332         }
00333 
00334       ReleaseTokenFSCall();
00335 
00336       if(resnfs4.status != NFS4_OK)
00337         LogCrit(COMPONENT_FSAL,
00338                 "FSAL_PROXY: /!\\ NFSv4 error %u occured when trying to renew client id %16llx",
00339                 resnfs4.status, (long long)argoparray[0].nfs_argop4_u.oprenew.clientid);
00340 
00341     }                           /* while( 1 ) */
00342 }                               /* FSAL_proxy_clientid_renewer_thread */