nfs-ganesha 1.4
|
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 */