int nfs4_op_lock(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { char __attribute__ ((__unused__)) funcname[] = "nfs4_op_lock"; #ifndef _WITH_NFSV4_LOCKS /* Lock are not supported */ resp->resop = NFS4_OP_LOCK; res_LOCK4.status = NFS4ERR_LOCK_NOTSUPP; return res_LOCK4.status; #else state_status_t state_status; state_data_t candidate_data; state_type_t candidate_type; int rc = 0; seqid4 seqid; state_t * plock_state; /* state for the lock */ state_t * pstate_open; /* state for the open owner */ state_owner_t * plock_owner; state_owner_t * popen_owner; state_owner_t * presp_owner; /* Owner to store response in */ state_owner_t * conflict_owner = NULL; state_nfs4_owner_name_t owner_name; nfs_client_id_t nfs_client_id; state_lock_desc_t lock_desc, conflict_desc; state_blocking_t blocking = STATE_NON_BLOCKING; const char * tag = "LOCK"; LogDebug(COMPONENT_NFS_V4_LOCK, "Entering NFS v4 LOCK handler -----------------------------------------------------"); /* Initialize to sane starting values */ resp->resop = NFS4_OP_LOCK; /* If there is no FH */ if(nfs4_Is_Fh_Empty(&(data->currentFH))) { res_LOCK4.status = NFS4ERR_NOFILEHANDLE; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed nfs4_Is_Fh_Empty"); return res_LOCK4.status; } /* If the filehandle is invalid */ if(nfs4_Is_Fh_Invalid(&(data->currentFH))) { res_LOCK4.status = NFS4ERR_BADHANDLE; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed nfs4_Is_Fh_Invalid"); return res_LOCK4.status; } /* Tests if the Filehandle is expired (for volatile filehandle) */ if(nfs4_Is_Fh_Expired(&(data->currentFH))) { res_LOCK4.status = NFS4ERR_FHEXPIRED; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed nfs4_Is_Fh_Expired"); return res_LOCK4.status; } /* Lock is done only on a file */ if(data->current_filetype != REGULAR_FILE) { /* Type of the entry is not correct */ switch (data->current_filetype) { case DIRECTORY: res_LOCK4.status = NFS4ERR_ISDIR; break; default: res_LOCK4.status = NFS4ERR_INVAL; break; } LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed wrong file type"); return res_LOCK4.status; } /* Convert lock parameters to internal types */ switch(arg_LOCK4.locktype) { case READ_LT: lock_desc.sld_type = STATE_LOCK_R; blocking = STATE_NON_BLOCKING; break; case WRITE_LT: lock_desc.sld_type = STATE_LOCK_W; blocking = STATE_NON_BLOCKING; break; case READW_LT: lock_desc.sld_type = STATE_LOCK_R; blocking = STATE_NFSV4_BLOCKING; break; case WRITEW_LT: lock_desc.sld_type = STATE_LOCK_W; blocking = STATE_NFSV4_BLOCKING; break; } lock_desc.sld_offset = arg_LOCK4.offset; if(arg_LOCK4.length != STATE_LOCK_OFFSET_EOF) lock_desc.sld_length = arg_LOCK4.length; else lock_desc.sld_length = 0; if(arg_LOCK4.locker.new_lock_owner) { /* New lock owner, Find the open owner */ tag = "LOCK (new owner)"; /* Check stateid correctness and get pointer to state */ if((rc = nfs4_Check_Stateid(&arg_LOCK4.locker.locker4_u.open_owner.open_stateid, data->current_entry, 0LL, &pstate_open, data, STATEID_SPECIAL_FOR_LOCK, tag)) != NFS4_OK) { res_LOCK4.status = rc; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed nfs4_Check_Stateid for open owner"); return res_LOCK4.status; } popen_owner = pstate_open->state_powner; plock_state = NULL; plock_owner = NULL; presp_owner = popen_owner; seqid = arg_LOCK4.locker.locker4_u.open_owner.open_seqid; LogLock(COMPONENT_NFS_V4_LOCK, NIV_FULL_DEBUG, "LOCK New lock owner from open owner", data->current_entry, data->pcontext, popen_owner, &lock_desc); /* Check is the clientid is known or not */ if(nfs_client_id_get(arg_LOCK4.locker.locker4_u.open_owner.lock_owner.clientid, &nfs_client_id) == CLIENT_ID_NOT_FOUND) { res_LOCK4.status = NFS4ERR_STALE_CLIENTID; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed nfs_client_id_get"); return res_LOCK4.status; } /* The related stateid is already stored in pstate_open */ /* An open state has been found. Check its type */ if(pstate_open->state_type != STATE_TYPE_SHARE) { res_LOCK4.status = NFS4ERR_BAD_STATEID; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed open stateid is not a SHARE"); return res_LOCK4.status; } /* Lock seqid (seqid wanted for new lock) should be 0 (see newpynfs test LOCK8c) */ if(arg_LOCK4.locker.locker4_u.open_owner.lock_seqid != 0) { res_LOCK4.status = NFS4ERR_BAD_SEQID; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed new lock stateid is not 0"); return res_LOCK4.status; } /* Is this lock_owner known ? */ convert_nfs4_lock_owner(&arg_LOCK4.locker.locker4_u.open_owner.lock_owner, &owner_name); } else { /* Existing lock owner * Find the lock stateid * From that, get the open_owner */ tag = "LOCK (existing owner)"; /* There was code here before to handle all-0 stateid, but that * really doesn't apply - when we handle temporary locks for * I/O operations (which is where we will see all-0 or all-1 * stateid, those will not come in through nfs4_op_lock. */ /* Check stateid correctness and get pointer to state */ if((rc = nfs4_Check_Stateid(&arg_LOCK4.locker.locker4_u.lock_owner.lock_stateid, data->current_entry, 0LL, &plock_state, data, STATEID_SPECIAL_FOR_LOCK, tag)) != NFS4_OK) { res_LOCK4.status = rc; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed nfs4_Check_Stateid for existing lock owner"); return res_LOCK4.status; } /* An lock state has been found. Check its type */ if(plock_state->state_type != STATE_TYPE_LOCK) { res_LOCK4.status = NFS4ERR_BAD_STATEID; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed existing lock owner, state type is not LOCK"); return res_LOCK4.status; } /* Get the old lockowner. We can do the following 'cast', in NFSv4 lock_owner4 and open_owner4 * are different types but with the same definition*/ plock_owner = plock_state->state_powner; popen_owner = plock_owner->so_owner.so_nfs4_owner.so_related_owner; pstate_open = plock_state->state_data.lock.popenstate; presp_owner = plock_owner; seqid = arg_LOCK4.locker.locker4_u.lock_owner.lock_seqid; LogLock(COMPONENT_NFS_V4_LOCK, NIV_FULL_DEBUG, "LOCK Existing lock owner", data->current_entry, data->pcontext, plock_owner, &lock_desc); #ifdef _CONFORM_TO_TEST_LOCK8c /* Check validity of the seqid */ if(arg_LOCK4.locker.locker4_u.lock_owner.lock_seqid != 0) { res_LOCK4.status = NFS4ERR_BAD_SEQID; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed existing lock owner, lock seqid != 0"); return res_LOCK4.status; } #endif } /* if( arg_LOCK4.locker.new_lock_owner ) */ /* Check seqid (lock_seqid or open_seqid) */ if(!Check_nfs4_seqid(presp_owner, seqid, op, data, resp, tag)) { /* Response is all setup for us and LogDebug told what was wrong */ return res_LOCK4.status; } /* Lock length should not be 0 */ if(arg_LOCK4.length == 0LL) { res_LOCK4.status = NFS4ERR_INVAL; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed length == 0"); /* Save the response in the lock or open owner */ Copy_nfs4_state_req(presp_owner, seqid, op, data, resp, tag); return res_LOCK4.status; } /* Check for range overflow. * Comparing beyond 2^64 is not possible int 64 bits precision, * but off+len > 2^64-1 is equivalent to len > 2^64-1 - off */ if(lock_desc.sld_length > (STATE_LOCK_OFFSET_EOF - lock_desc.sld_offset)) { res_LOCK4.status = NFS4ERR_INVAL; LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed length overflow"); /* Save the response in the lock or open owner */ Copy_nfs4_state_req(presp_owner, seqid, op, data, resp, tag); return res_LOCK4.status; } /* check if open state has correct access for type of lock. * Don't need to check for conflicting states since this open * state assures there are no conflicting states. */ if(((arg_LOCK4.locktype == WRITE_LT || arg_LOCK4.locktype == WRITEW_LT) && ((pstate_open->state_data.share.share_access & OPEN4_SHARE_ACCESS_WRITE) == 0)) || ((arg_LOCK4.locktype == READ_LT || arg_LOCK4.locktype == READW_LT) && ((pstate_open->state_data.share.share_access & OPEN4_SHARE_ACCESS_READ) == 0))) { /* The open state doesn't allow access based on the type of lock */ LogLock(COMPONENT_NFS_V4_LOCK, NIV_DEBUG, "LOCK failed, SHARE doesn't allow access", data->current_entry, data->pcontext, plock_owner, &lock_desc); res_LOCK4.status = NFS4ERR_OPENMODE; /* Save the response in the lock or open owner */ Copy_nfs4_state_req(presp_owner, seqid, op, data, resp, tag); return res_LOCK4.status; } if(arg_LOCK4.locker.new_lock_owner) { /* A lock owner is always associated with a previously made open * which has itself a previously made stateid */ /* Get reference to open owner */ inc_state_owner_ref(popen_owner); if(nfs4_owner_Get_Pointer(&owner_name, &plock_owner)) { /* Lock owner already existsc, check lock_seqid if it's not 0 */ if(!Check_nfs4_seqid(plock_owner, arg_LOCK4.locker.locker4_u.open_owner.lock_seqid, op, data, resp, "LOCK (new owner but owner exists)")) { /* Response is all setup for us and LogDebug told what was wrong */ return res_LOCK4.status; } } else { /* This lock owner is not known yet, allocated and set up a new one */ plock_owner = create_nfs4_owner(data->pclient, &owner_name, STATE_LOCK_OWNER_NFSV4, popen_owner, 0); if(plock_owner == NULL) { res_LOCK4.status = NFS4ERR_RESOURCE; LogLock(COMPONENT_NFS_V4_LOCK, NIV_DEBUG, "LOCK failed to create new lock owner", data->current_entry, data->pcontext, popen_owner, &lock_desc); return res_LOCK4.status; } } /* Prepare state management structure */ memset(&candidate_type, 0, sizeof(candidate_type)); candidate_type = STATE_TYPE_LOCK; candidate_data.lock.popenstate = pstate_open; /* Add the lock state to the lock table */ if(state_add(data->current_entry, candidate_type, &candidate_data, plock_owner, data->pclient, data->pcontext, &plock_state, &state_status) != STATE_SUCCESS) { res_LOCK4.status = NFS4ERR_RESOURCE; LogLock(COMPONENT_NFS_V4_LOCK, NIV_DEBUG, "LOCK failed to add new stateid", data->current_entry, data->pcontext, plock_owner, &lock_desc); dec_state_owner_ref(plock_owner, data->pclient); return res_LOCK4.status; } init_glist(&plock_state->state_data.lock.state_locklist); /* Add lock state to the list of lock states belonging to the open state */ glist_add_tail(&pstate_open->state_data.share.share_lockstates, &plock_state->state_data.lock.state_sharelist); } /* if( arg_LOCK4.locker.new_lock_owner ) */ /* Now we have a lock owner and a stateid. * Go ahead and push lock into SAL (and FSAL). */ if(state_lock(data->current_entry, data->pcontext, plock_owner, plock_state, blocking, NULL, /* No block data for now */ &lock_desc, &conflict_owner, &conflict_desc, data->pclient, &state_status) != STATE_SUCCESS) { if(state_status == STATE_LOCK_CONFLICT) { /* A conflicting lock from a different lock_owner, returns NFS4ERR_DENIED */ Process_nfs4_conflict(&res_LOCK4.LOCK4res_u.denied, conflict_owner, &conflict_desc, data->pclient); } LogDebug(COMPONENT_NFS_V4_LOCK, "LOCK failed with status %s", state_err_str(state_status)); res_LOCK4.status = nfs4_Errno_state(state_status); /* Save the response in the lock or open owner */ if(res_LOCK4.status != NFS4ERR_RESOURCE && res_LOCK4.status != NFS4ERR_BAD_STATEID) Copy_nfs4_state_req(presp_owner, seqid, op, data, resp, tag); if(arg_LOCK4.locker.new_lock_owner) { /* Need to destroy lock owner and state */ if(state_del(plock_state, data->pclient, &state_status) != STATE_SUCCESS) LogDebug(COMPONENT_NFS_V4_LOCK, "state_del failed with status %s", state_err_str(state_status)); } return res_LOCK4.status; } res_LOCK4.status = NFS4_OK; /* Handle stateid/seqid for success */ update_stateid(plock_state, &res_LOCK4.LOCK4res_u.resok4.lock_stateid, data, tag); LogFullDebug(COMPONENT_NFS_V4_LOCK, "LOCK state_seqid = %u, plock_state = %p", plock_state->state_seqid, plock_state); /* Save the response in the lock or open owner */ Copy_nfs4_state_req(presp_owner, seqid, op, data, resp, tag); LogLock(COMPONENT_NFS_V4_LOCK, NIV_FULL_DEBUG, "LOCK applied", data->current_entry, data->pcontext, plock_owner, &lock_desc); return res_LOCK4.status; #endif } /* nfs4_op_lock */
int nfs41_op_exchange_id(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { char __attribute__ ((__unused__)) funcname[] = "nfs4_op_setclientid"; char str_verifier[MAXNAMLEN]; char str_client[MAXNAMLEN]; #define arg_EXCHANGE_ID4 op->nfs_argop4_u.opexchange_id #define res_EXCHANGE_ID4 resp->nfs_resop4_u.opexchange_id clientid4 clientid; nfs_client_id_t nfs_clientid; nfs_worker_data_t *pworker = NULL; pworker = (nfs_worker_data_t *) data->pclient->pworker; strncpy(str_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, MAXNAMLEN); strncpy(str_client, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_val, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len); str_client[arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len] = '\0'; LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Client id len = %u", arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len); LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Client name = #%s#", str_client); //LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Verifier = #%s#", str_verifier ) ; /* There was no pb, returns the clientid */ resp->resop = NFS4_OP_EXCHANGE_ID; res_EXCHANGE_ID4.eir_status = NFS4_OK; /* Compute the client id */ if(nfs_client_id_basic_compute(str_client, &clientid) != CLIENT_ID_SUCCESS) { res_EXCHANGE_ID4.eir_status = NFS4ERR_SERVERFAULT; return res_EXCHANGE_ID4.eir_status; } LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID computed clientid4=%llux for name='%s'", (long long unsigned int)clientid, str_client); #if 0 //plante le client sous windows. Ai-je réellement besoin de cela ???? // /* Check flags value (test EID4) */ if(arg_EXCHANGE_ID4.eia_flags & all_eia_flags != arg_EXCHANGE_ID4.eia_flags) { res_EXCHANGE_ID4.eir_status = NFS4ERR_INVAL; return res_EXCHANGE_ID4.eir_status; } #endif /* Does this id already exists ? */ if(nfs_client_id_get(clientid, &nfs_clientid) == CLIENT_ID_SUCCESS) { /* Client id already in use */ LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID ClientId %llx already in use for client '%s', check if same", (long long unsigned int)clientid, nfs_clientid.client_name); /* Principals are the same, check content of the setclientid request */ if(nfs_clientid.confirmed == CONFIRMED_CLIENT_ID) { #ifdef _NFSV4_COMPARE_CRED_IN_EXCHANGE_ID /* Check if client id has same credentials */ if(nfs_compare_clientcred(&(nfs_clientid.credential), &(data->credential)) == FALSE) { LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Confirmed ClientId %llx -> '%s': Credential do not match... Return NFS4ERR_CLID_INUSE", clientid, nfs_clientid.client_name); res_EXCHANGE_ID4.eir_status = NFS4ERR_CLID_INUSE; #ifdef _USE_NFS4_1 res_EXCHANGE_ID4.EXCHANGE_ID4res_u.client_using.na_r_netid = nfs_clientid.client_r_netid; res_EXCHANGE_ID4.EXCHANGE_ID4res_u.client_using.na_r_addr = nfs_clientid.client_r_addr; #else res_EXCHANGE_ID4.EXCHANGE_ID4res_u.client_using.r_netid = nfs_clientid.client_r_netid; res_EXCHANGE_ID4.EXCHANGE_ID4res_u.client_using.r_addr = nfs_clientid.client_r_addr; #endif /* _USE_NFS4_1 */ return res_EXCHANGE_ID4.eir_status; } else LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID ClientId %llx is set again by same principal", clientid); #endif /* Ask for a different client with the same client id... returns an error if different client */ LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Confirmed ClientId %llx already in use for client '%s'", (long long unsigned int)clientid, nfs_clientid.client_name); if(strncmp (nfs_clientid.incoming_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, NFS4_VERIFIER_SIZE)) { LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Confirmed ClientId %llx already in use for client '%s', verifier do not match...", (long long unsigned int)clientid, nfs_clientid.client_name); /* A client has rebooted and rebuilds its state */ LogDebug(COMPONENT_NFS_V4, "Probably something to be done here: a client has rebooted and try recovering its state. Update the record for this client"); /* Update the record, but set it as REBOOTED */ strncpy(nfs_clientid.client_name, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_val, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len); nfs_clientid.client_name[arg_EXCHANGE_ID4.eia_clientowner.co_ownerid. co_ownerid_len] = '\0'; strncpy(nfs_clientid.incoming_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, NFS4_VERIFIER_SIZE); snprintf(nfs_clientid.verifier, NFS4_VERIFIER_SIZE, "%u", (unsigned int)ServerBootTime); nfs_clientid.confirmed = REBOOTED_CLIENT_ID; nfs_clientid.clientid = clientid; nfs_clientid.last_renew = 0; if(nfs_client_id_set(clientid, nfs_clientid, &pworker->clientid_pool) != CLIENT_ID_SUCCESS) { res_EXCHANGE_ID4.eir_status = NFS4ERR_SERVERFAULT; return res_EXCHANGE_ID4.eir_status; } } else { LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID Confirmed ClientId %llx already in use for client '%s', verifier matches. Now check callback", (long long unsigned int)clientid, nfs_clientid.client_name); } } else { LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID ClientId %llx already in use for client '%s', but unconfirmed", (long long unsigned int)clientid, nfs_clientid.client_name); LogCrit(COMPONENT_NFS_V4, "Reuse of a formerly obtained clientid that is not yet confirmed."); // Code needs to be improved here. } } else { /* Build the client record */ strncpy(nfs_clientid.client_name, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_val, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len); nfs_clientid.client_name[arg_EXCHANGE_ID4.eia_clientowner.co_ownerid. co_ownerid_len] = '\0'; strncpy(nfs_clientid.incoming_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, NFS4_VERIFIER_SIZE); snprintf(nfs_clientid.verifier, NFS4_VERIFIER_SIZE, "%u", (unsigned int)ServerBootTime); nfs_clientid.confirmed = UNCONFIRMED_CLIENT_ID; nfs_clientid.cb_program = 0; /* to be set at create_session time */ nfs_clientid.clientid = clientid; nfs_clientid.last_renew = 0; nfs_clientid.nb_session = 0; nfs_clientid.create_session_sequence = 1; nfs_clientid.credential = data->credential; if(gethostname(nfs_clientid.server_owner, MAXNAMLEN) == -1) { res_EXCHANGE_ID4.eir_status = NFS4ERR_SERVERFAULT; return res_EXCHANGE_ID4.eir_status; } // strncpy(nfs_clientid.server_scope, nfs_clientid.server_owner, MAXNAMLEN); snprintf( nfs_clientid.server_scope, MAXNAMLEN, "%s_NFS-Ganesha", nfs_clientid.server_owner ) ; if(nfs_client_id_add(clientid, nfs_clientid, data->pclient) != CLIENT_ID_SUCCESS) { res_EXCHANGE_ID4.eir_status = NFS4ERR_SERVERFAULT; return res_EXCHANGE_ID4.eir_status; } } res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_clientid = clientid; res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_sequenceid = nfs_clientid.create_session_sequence; #if defined(_USE_FSALMDS) && defined(_USE_FSALDS) res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_flags = EXCHGID4_FLAG_USE_PNFS_MDS | EXCHGID4_FLAG_USE_PNFS_DS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #elif defined(_USE_FSALMDS) res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_flags = EXCHGID4_FLAG_USE_PNFS_MDS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #elif defined(_USE_FSALDS) res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_flags = EXCHGID4_FLAG_USE_PNFS_DS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #elif defined(_USE_DS) res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_flags = EXCHGID4_FLAG_USE_PNFS_MDS | EXCHGID4_FLAG_USE_PNFS_DS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #else res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_flags = EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #endif res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_state_protect.spr_how = SP4_NONE; res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_owner.so_major_id. so_major_id_len = strlen(nfs_clientid.server_owner); res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_owner.so_major_id. so_major_id_val = Mem_Alloc(strlen(nfs_clientid.server_owner)); memcpy(res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_owner.so_major_id. so_major_id_val, nfs_clientid.server_owner, strlen(nfs_clientid.server_owner)); res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_owner.so_minor_id = 0; res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_scope.eir_server_scope_len = strlen(nfs_clientid.server_scope); res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_scope.eir_server_scope_val = Mem_Alloc(strlen(nfs_clientid.server_scope)); memcpy(res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_scope. eir_server_scope_val, nfs_clientid.server_scope, strlen(nfs_clientid.server_scope)); res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_impl_id. eir_server_impl_id_len = 0; res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_server_impl_id. eir_server_impl_id_val = NULL; LogDebug(COMPONENT_NFS_V4, "EXCHANGE_ID reply :ClientId=%llx", (long long unsigned int)res_EXCHANGE_ID4.EXCHANGE_ID4res_u.eir_resok4.eir_clientid); res_EXCHANGE_ID4.eir_status = NFS4_OK; return res_EXCHANGE_ID4.eir_status; } /* nfs41_op_exchange_id */