void ipv6print() { char buf[SOCK_NAME_MAX]; sprint_sockip(&ipv6a, buf, sizeof(buf)); // printf("Value = %s\n", buf); CMP("2001::1", buf, strlen("2001::1"), "ipv6a has the wrong ip value"); sprint_sockip(&ipv6b, buf, sizeof(buf)); // printf("Value = %s\n", buf); CMP("2001::1", buf, strlen("2001::1"), "ipv6b has the wrong ip value"); sprint_sockip(&ipv6c, buf, sizeof(buf)); // printf("Value = %s\n", buf); CMP("2001::f:1", buf, strlen("2001::f:1"), "ipv6c has the wrong ip value"); }
void ipv4print() { char buf[SOCK_NAME_MAX]; sprint_sockip(&ipv4a, buf, sizeof(buf)); // printf("Value = %s\n", buf); CMP("10.10.5.1", buf, strlen("10.10.5.1"), "ipv4a has the wrong ip value"); sprint_sockip(&ipv4b, buf, sizeof(buf)); // printf("Value = %s\n", buf); CMP("10.10.5.1", buf, strlen("10.10.5.1"), "ipv4b has the wrong ip value"); sprint_sockip(&ipv4c, buf, sizeof(buf)); // printf("Value = %s\n", buf); CMP("10.10.5.2", buf, strlen("10.10.5.2"), "ipv4c has the wrong ip value"); }
/** * * nfs_ip_name_remove: Tries to remove an entry for ip_name cache * * Tries to remove an entry for ip_name cache. * * @param ipaddr [IN] the ip address to be uncached. * * @return the result previously set if *pstatus == IP_NAME_SUCCESS * */ int nfs_ip_name_remove(sockaddr_t *ipaddr) { struct gsh_buffdesc buffkey, old_value; nfs_ip_name_t *nfs_ip_name = NULL; char ipstring[SOCK_NAME_MAX + 1]; sprint_sockip(ipaddr, ipstring, sizeof(ipstring)); buffkey.addr = ipaddr; buffkey.len = sizeof(sockaddr_t); if (HashTable_Del(ht_ip_name, &buffkey, NULL, &old_value) == HASHTABLE_SUCCESS) { nfs_ip_name = (nfs_ip_name_t *) old_value.addr; LogFullDebug(COMPONENT_DISPATCH, "Cache remove hit for %s->%s", ipstring, nfs_ip_name->hostname); gsh_free(nfs_ip_name); return IP_NAME_SUCCESS; } LogFullDebug(COMPONENT_DISPATCH, "Cache remove miss for %s", ipstring); return IP_NAME_NOT_FOUND; } /* nfs_ip_name_remove */
/** * * nfs_ip_name_get: Tries to get an entry for ip_name cache. * * Tries to get an entry for ip_name cache. * * @param ipaddr [IN] the ip address requested * @param hostname [OUT] the hostname * * @return the result previously set if *pstatus == IP_NAME_SUCCESS * */ int nfs_ip_name_get(sockaddr_t *ipaddr, char *hostname, size_t size) { struct gsh_buffdesc buffkey; struct gsh_buffdesc buffval; nfs_ip_name_t *nfs_ip_name; char ipstring[SOCK_NAME_MAX + 1]; sprint_sockip(ipaddr, ipstring, sizeof(ipstring)); buffkey.addr = ipaddr; buffkey.len = sizeof(sockaddr_t); if (HashTable_Get(ht_ip_name, &buffkey, &buffval) == HASHTABLE_SUCCESS) { nfs_ip_name = buffval.addr; strmaxcpy(hostname, nfs_ip_name->hostname, size); LogFullDebug(COMPONENT_DISPATCH, "Cache get hit for %s->%s", ipstring, nfs_ip_name->hostname); return IP_NAME_SUCCESS; } LogFullDebug(COMPONENT_DISPATCH, "Cache get miss for %s", ipstring); return IP_NAME_NOT_FOUND; } /* nfs_ip_name_get */
/** * @brief Display the ip_name stored in the buffer * * @param[in] pbuff Buffer to display * @param[out] str Output string * * @return number of character written. */ int display_ip_name_key(struct gsh_buffdesc *pbuff, char *str) { sockaddr_t *addr = (sockaddr_t *) (pbuff->addr); sprint_sockip(addr, str, HASHTABLE_DISPLAY_STRLEN); return strlen(str); }
int nfs4_op_setclientid(struct nfs_argop4 *op, compound_data_t *data, struct nfs_resop4 *resp) { SETCLIENTID4args * const arg_SETCLIENTID4 = &op->nfs_argop4_u.opsetclientid; SETCLIENTID4res * const res_SETCLIENTID4 = &resp->nfs_resop4_u.opsetclientid; clientaddr4 * const res_SETCLIENTID4_INUSE = &resp->nfs_resop4_u.opsetclientid.SETCLIENTID4res_u.client_using; char str_verifier[NFS4_VERIFIER_SIZE * 2 + 1]; char str_client[NFS4_OPAQUE_LIMIT * 2 + 1]; char str_client_addr[SOCK_NAME_MAX + 1]; nfs_client_record_t *client_record; nfs_client_id_t *conf; nfs_client_id_t *unconf; clientid4 clientid; verifier4 verifier; sockaddr_t client_addr; int rc; resp->resop = NFS4_OP_SETCLIENTID; if (data->minorversion > 0) { res_SETCLIENTID4->status = NFS4ERR_NOTSUPP; return res_SETCLIENTID4->status; } copy_xprt_addr(&client_addr, data->req->rq_xprt); if (isDebug(COMPONENT_CLIENTID)) { sprint_sockip(&client_addr, str_client_addr, sizeof(str_client_addr)); DisplayOpaqueValue(arg_SETCLIENTID4->client.id.id_val, arg_SETCLIENTID4->client.id.id_len, str_client); sprint_mem(str_verifier, arg_SETCLIENTID4->client.verifier, NFS4_VERIFIER_SIZE); } LogDebug(COMPONENT_CLIENTID, "SETCLIENTID Client addr=%s id=%s verf=%s callback={program=%u r_addr=%s r_netid=%s} ident=%u", str_client_addr, str_client, str_verifier, arg_SETCLIENTID4->callback.cb_program, arg_SETCLIENTID4->callback.cb_location.r_addr, arg_SETCLIENTID4->callback.cb_location.r_netid, arg_SETCLIENTID4->callback_ident); /* Do we already have one or more records for client id (x)? */ client_record = get_client_record(arg_SETCLIENTID4->client.id.id_val, arg_SETCLIENTID4->client.id.id_len, 0, 0); if (client_record == NULL) { /* Some major failure */ LogCrit(COMPONENT_CLIENTID, "SETCLIENTID failed"); res_SETCLIENTID4->status = NFS4ERR_SERVERFAULT; return res_SETCLIENTID4->status; } /* The following checks are based on RFC3530bis draft 16 * * This attempts to implement the logic described in * 15.35.5. IMPLEMENTATION Consider the major bullets as CASE * 1, CASE 2, CASE 3, CASE 4, and CASE 5. */ pthread_mutex_lock(&client_record->cr_mutex); if (isFullDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_client_record(client_record, str); LogFullDebug(COMPONENT_CLIENTID, "Client Record %s cr_confirmed_rec=%p " "cr_unconfirmed_rec=%p", str, client_record->cr_confirmed_rec, client_record->cr_unconfirmed_rec); } conf = client_record->cr_confirmed_rec; if (conf != NULL) { /* Need a reference to the confirmed record for below */ inc_client_id_ref(conf); if (!nfs_compare_clientcred(&conf->cid_credential, &data->credential) || !cmp_sockaddr(&conf->cid_client_addr, &client_addr, true)) { /* CASE 1: * * Confirmed record exists and not the same principal */ if (isDebug(COMPONENT_CLIENTID)) { char confirmed_addr[SOCK_NAME_MAX + 1]; sprint_sockip(&conf->cid_client_addr, confirmed_addr, sizeof(confirmed_addr)); LogDebug(COMPONENT_CLIENTID, "Confirmed ClientId %" PRIx64 "->'%s': Principals do not match... confirmed addr=%s Return NFS4ERR_CLID_INUSE", conf->cid_clientid, str_client, confirmed_addr); } res_SETCLIENTID4->status = NFS4ERR_CLID_INUSE; res_SETCLIENTID4_INUSE->r_netid = (char *)netid_nc_table[conf->cid_cb.v40.cb_addr.nc] .netid; res_SETCLIENTID4_INUSE->r_addr = gsh_strdup(conf->cid_cb.v40.cb_client_r_addr); /* Release our reference to the confirmed clientid. */ dec_client_id_ref(conf); goto out; } /* Check if confirmed record is for (v, x, c, l, s) */ if (memcmp (arg_SETCLIENTID4->client.verifier, conf->cid_incoming_verifier, NFS4_VERIFIER_SIZE) == 0) { /* CASE 2: * * A confirmed record exists for this long * form client id and verifier. * * Consider this to be a possible update of * the call-back information. * * Remove any pre-existing unconfirmed record * for (v, x, c). * * Return the same short form client id (c), * but a new setclientid_confirm verifier (t). */ LogFullDebug(COMPONENT_CLIENTID, "Update ClientId %" PRIx64 "->%s", conf->cid_clientid, str_client); clientid = conf->cid_clientid; new_clientid_verifier(verifier); } else { /* Must be CASE 3 or CASE 4 * * Confirmed record is for (u, x, c, l, s). * * These are actually the same, doesn't really * matter if an unconfirmed record exists or * not. Any existing unconfirmed record will * be removed and a new unconfirmed record * added. * * Return a new short form clientid (d) and a * new setclientid_confirm verifier (t). (Note * the spec calls the values e and r for CASE * 4). */ LogFullDebug(COMPONENT_CLIENTID, "Replace ClientId %" PRIx64 "->%s", conf->cid_clientid, str_client); clientid = new_clientid(); new_clientid_verifier(verifier); } /* Release our reference to the confirmed clientid. */ dec_client_id_ref(conf); } else { /* CASE 5: * * * Remove any existing unconfirmed record. * * Return a new short form clientid (d) and a new * setclientid_confirm verifier (t). */ LogFullDebug(COMPONENT_CLIENTID, "New client"); clientid = new_clientid(); new_clientid_verifier(verifier); } /* At this point, no matter what the case was above, we should * remove any pre-existing unconfirmed record. */ unconf = client_record->cr_unconfirmed_rec; if (unconf != NULL) { /* Delete the unconfirmed clientid record. Because we * have the cr_mutex, we have won any race to deal * with this clientid record (whether we raced with a * SETCLIENTID_CONFIRM or the reaper thread (if either * of those operations had won the race, * cr_punconfirmed_id would have been NULL). */ if (isDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_client_id_rec(unconf, str); LogDebug(COMPONENT_CLIENTID, "Replacing %s", str); } /* unhash the clientid record */ remove_unconfirmed_client_id(unconf); unconf = NULL; } /* Now we can proceed to build the new unconfirmed record. We * have determined the clientid and setclientid_confirm values * above. */ unconf = create_client_id(clientid, client_record, &client_addr, &data->credential, 0); if (unconf == NULL) { /* Error already logged, return */ res_SETCLIENTID4->status = NFS4ERR_RESOURCE; goto out; } if (strmaxcpy(unconf->cid_cb.v40.cb_client_r_addr, arg_SETCLIENTID4->callback.cb_location.r_addr, sizeof(unconf->cid_cb.v40.cb_client_r_addr)) == -1) { LogCrit(COMPONENT_CLIENTID, "Callback r_addr %s too long", arg_SETCLIENTID4->callback.cb_location.r_addr); res_SETCLIENTID4->status = NFS4ERR_INVAL; goto out; } nfs_set_client_location(unconf, &arg_SETCLIENTID4->callback.cb_location); memcpy(unconf->cid_incoming_verifier, arg_SETCLIENTID4->client.verifier, NFS4_VERIFIER_SIZE); memcpy(unconf->cid_verifier, verifier, sizeof(NFS4_write_verifier)); unconf->cid_cb.v40.cb_program = arg_SETCLIENTID4->callback.cb_program; unconf->cid_cb.v40.cb_callback_ident = arg_SETCLIENTID4->callback_ident; rc = nfs_client_id_insert(unconf); if (rc != CLIENT_ID_SUCCESS) { /* Record is already freed, return. */ res_SETCLIENTID4->status = clientid_error_to_nfsstat(rc); goto out; } if (isDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; sprint_mem(str_verifier, verifier, NFS4_VERIFIER_SIZE); display_client_id_rec(unconf, str); LogDebug(COMPONENT_CLIENTID, "SETCLIENTID reply Verifier=%s %s", str_verifier, str); } res_SETCLIENTID4->status = NFS4_OK; res_SETCLIENTID4->SETCLIENTID4res_u.resok4.clientid = clientid; memcpy(res_SETCLIENTID4->SETCLIENTID4res_u.resok4.setclientid_confirm, &verifier, NFS4_VERIFIER_SIZE); out: pthread_mutex_unlock(&client_record->cr_mutex); /* Release our reference to the client record */ dec_client_record_ref(client_record); return res_SETCLIENTID4->status; }
int nfs41_op_exchange_id(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) { char str_verifier[NFS4_VERIFIER_SIZE * 2 + 1]; char str_client[NFS4_OPAQUE_LIMIT * 2 + 1]; nfs_client_record_t * pclient_record; nfs_client_id_t * pconf; nfs_client_id_t * punconf; int rc; int len; char * temp; bool_t update; const char * update_str; log_components_t component = COMPONENT_CLIENTID; #if 0 /** @todo: 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 if(isDebug(COMPONENT_SESSIONS)) component = COMPONENT_SESSIONS; #define arg_EXCHANGE_ID4 op->nfs_argop4_u.opexchange_id #define res_EXCHANGE_ID4 resp->nfs_resop4_u.opexchange_id #define res_EXCHANGE_ID4_ok resp->nfs_resop4_u.opexchange_id.EXCHANGE_ID4res_u.eir_resok4 resp->resop = NFS4_OP_EXCHANGE_ID; update = (arg_EXCHANGE_ID4.eia_flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) != 0; if(isDebug(component)) { DisplayOpaqueValue(arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_val, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len, str_client); sprint_mem(str_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, NFS4_VERIFIER_SIZE); update_str = update ? "UPDATE" : "NO UPDATE"; } LogDebug(component, "EXCHANGE_ID Client addr=%s id=%s verf=%s %s --------------------", data->pworker->hostaddr_str, str_client, str_verifier, update_str); /* Do we already have one or more records for client id (x)? */ pclient_record = get_client_record(arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_val, arg_EXCHANGE_ID4.eia_clientowner.co_ownerid.co_ownerid_len); if(pclient_record == NULL) { /* Some major failure */ LogCrit(component, "EXCHANGE_ID failed"); res_EXCHANGE_ID4.eir_status = NFS4ERR_SERVERFAULT; return res_EXCHANGE_ID4.eir_status; } /* * The following checks are based on RFC5661 * * This attempts to implement the logic described in 18.35.4. IMPLEMENTATION */ P(pclient_record->cr_mutex); if(isFullDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_client_record(pclient_record, str); LogFullDebug(COMPONENT_CLIENTID, "Client Record %s cr_pconfirmed_id=%p cr_punconfirmed_id=%p", str, pclient_record->cr_pconfirmed_id, pclient_record->cr_punconfirmed_id); } pconf = pclient_record->cr_pconfirmed_id; if(pconf != NULL) { /* Need a reference to the confirmed record for below */ inc_client_id_ref(pconf); } if(pconf != NULL && !update) { /* EXCHGID4_FLAG_UPD_CONFIRMED_REC_A not set */ /** @todo FSF: old code ifdefed out nfs_compare_clientcred with _NFSV4_COMPARE_CRED_IN_EXCHANGE_ID */ if(!nfs_compare_clientcred(&pconf->cid_credential, &data->credential) || !cmp_sockaddr(&pconf->cid_client_addr, &data->pworker->hostaddr, IGNORE_PORT)) { /** @todo FSF: should also check if there is no state */ P(pconf->cid_mutex); if(valid_lease(pconf)) { V(pconf->cid_mutex); /* CASE 3, client collisions, old clientid is expired */ if(isDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_client_id_rec(pconf, str); LogDebug(COMPONENT_CLIENTID, "Expiring %s", str); } /* Expire clientid and release our reference. */ nfs_client_id_expire(pconf); dec_client_id_ref(pconf); pconf = NULL; } else { V(pconf->cid_mutex); /* CASE 3, client collisions, old clientid is not expired */ if(isDebug(component)) { char confirmed_addr[SOCK_NAME_MAX]; sprint_sockip(&pconf->cid_client_addr, confirmed_addr, sizeof(confirmed_addr)); LogDebug(component, "Confirmed ClientId %"PRIx64"->'%s': Principals do not match... confirmed addr=%s Return NFS4ERR_CLID_INUSE", pconf->cid_clientid, str_client, confirmed_addr); } res_EXCHANGE_ID4.eir_status = NFS4ERR_CLID_INUSE; /* Release our reference to the confirmed clientid. */ dec_client_id_ref(pconf); goto out; } } else if(memcmp(arg_EXCHANGE_ID4.eia_clientowner.co_verifier, pconf->cid_incoming_verifier, NFS4_VERIFIER_SIZE) == 0) { /* CASE 2, Non-Update on Existing Client ID */ /* Return what was last returned without changing any refcounts */ LogDebug(COMPONENT_CLIENTID, "Non-update of confirmed ClientId %"PRIx64"->%s", pconf->cid_clientid, str_client); punconf = pconf; goto return_ok; } else { /* CASE 5, client restart */ /** @todo FSF: expire old clientid? */ LogDebug(component, "Restarted ClientId %"PRIx64"->%s", pconf->cid_clientid, str_client); } } else if(pconf != NULL) { /* EXCHGID4_FLAG_UPD_CONFIRMED_REC_A set */ if(memcmp(arg_EXCHANGE_ID4.eia_clientowner.co_verifier, pconf->cid_incoming_verifier, NFS4_VERIFIER_SIZE) == 0) { /** @todo FSF: old code ifdefed out nfs_compare_clientcred with _NFSV4_COMPARE_CRED_IN_EXCHANGE_ID */ if(!nfs_compare_clientcred(&pconf->cid_credential, &data->credential) || !cmp_sockaddr(&pconf->cid_client_addr, &data->pworker->hostaddr, IGNORE_PORT)) { /* CASE 9, Update but wrong principal */ if(isDebug(component)) { char confirmed_addr[SOCK_NAME_MAX]; sprint_sockip(&pconf->cid_client_addr, confirmed_addr, sizeof(confirmed_addr)); LogDebug(component, "Confirmed ClientId %"PRIx64"->'%s': Principals do not match... confirmed addr=%s Return NFS4ERR_PERM", pconf->cid_clientid, str_client, confirmed_addr); } res_EXCHANGE_ID4.eir_status = NFS4ERR_PERM; } else { /* CASE 6, Update */ /** @todo: this is not implemented, the things it updates aren't even tracked */ LogMajor(component, "EXCHANGE_ID Update not supported"); res_EXCHANGE_ID4.eir_status = NFS4ERR_NOTSUPP; } } else { /* CASE 8, Update but wrong verifier */ if(isDebug(component)) { char str_old_verifier[NFS4_VERIFIER_SIZE * 2 + 1]; sprint_mem(str_old_verifier, pconf->cid_incoming_verifier, NFS4_VERIFIER_SIZE); LogDebug(component, "Confirmed clientid %"PRIx64"->'%s': Verifiers do not match... confirmed verifier=%s", pconf->cid_clientid, str_client, str_old_verifier); } res_EXCHANGE_ID4.eir_status = NFS4ERR_NOT_SAME; } /* Release our reference to the confirmed clientid. */ dec_client_id_ref(pconf); goto out; } else if(pconf == NULL && update) { LogDebug(component, "No confirmed clientid to update for %s", str_client); res_EXCHANGE_ID4.eir_status = NFS4ERR_NOENT; goto out; } /* At this point, no matter what the case was above, we should remove any * pre-existing unconfirmed record. */ punconf = pclient_record->cr_punconfirmed_id; if(punconf != NULL) { /* CASE 4, replacement of unconfirmed record */ /* Delete the unconfirmed clientid record */ if(isDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_client_id_rec(punconf, str); LogDebug(COMPONENT_CLIENTID, "Replacing %s", str); } /* unhash the clientid record */ remove_unconfirmed_client_id(punconf); } /* Now we can proceed to build the new unconfirmed record. We have determined * the clientid and setclientid_confirm values above. */ punconf = create_client_id(0, pclient_record, &data->pworker->hostaddr, &data->credential); if(punconf == NULL) { /* Error already logged, return */ res_EXCHANGE_ID4.eir_status = NFS4ERR_RESOURCE; goto out; } memcpy(punconf->cid_incoming_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, NFS4_VERIFIER_SIZE); if(gethostname(punconf->cid_server_owner, sizeof(punconf->cid_server_owner)) == -1) { /* Free the clientid record and return */ free_client_id(punconf); res_EXCHANGE_ID4.eir_status = NFS4ERR_SERVERFAULT; goto out; } snprintf(punconf->cid_server_scope, sizeof(punconf->cid_server_scope), "%s_NFS-Ganesha", punconf->cid_server_owner); rc = nfs_client_id_insert(punconf); if(rc != CLIENT_ID_SUCCESS) { /* Record is already freed, return. */ res_EXCHANGE_ID4.eir_status = clientid_error_to_nfsstat(rc); goto out; } return_ok: /* Build the reply */ res_EXCHANGE_ID4_ok.eir_clientid = punconf->cid_clientid; res_EXCHANGE_ID4_ok.eir_sequenceid = punconf->cid_create_session_sequence; #if defined(_USE_FSALMDS) && defined(_USE_FSALDS) res_EXCHANGE_ID4_ok.eir_flags = EXCHGID4_FLAG_USE_PNFS_MDS | EXCHGID4_FLAG_USE_PNFS_DS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #elif defined(_USE_FSALMDS) res_EXCHANGE_ID4_ok.eir_flags = EXCHGID4_FLAG_USE_PNFS_MDS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #elif defined(_USE_FSALDS) res_EXCHANGE_ID4_ok.eir_flags = EXCHGID4_FLAG_USE_PNFS_DS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #elif defined(_USE_DS) res_EXCHANGE_ID4_ok.eir_flags = EXCHGID4_FLAG_USE_PNFS_MDS | EXCHGID4_FLAG_USE_PNFS_DS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #else res_EXCHANGE_ID4_ok.eir_flags = EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_SUPP_MOVED_REFER; #endif res_EXCHANGE_ID4_ok.eir_state_protect.spr_how = SP4_NONE; len = strlen(punconf->cid_server_owner); temp = gsh_malloc(len); if(temp == NULL) { LogDebug(component, "Could not allocate memory for so_major_id in response"); /** @todo FSF: not the best way to handle this but keeps from crashing */ len = 0; } else memcpy(temp, punconf->cid_server_owner, len); res_EXCHANGE_ID4_ok.eir_server_owner.so_major_id.so_major_id_len = len; res_EXCHANGE_ID4_ok.eir_server_owner.so_major_id.so_major_id_val = temp; res_EXCHANGE_ID4_ok.eir_server_owner.so_minor_id = 0; len = strlen(punconf->cid_server_scope); temp = gsh_malloc(len); if(temp == NULL) { LogDebug(component, "Could not allocate memory for eir_server_scope in response"); /** @todo FSF: not the best way to handle this but keeps from crashing */ len = 0; } else memcpy(temp, punconf->cid_server_scope, len); res_EXCHANGE_ID4_ok.eir_server_scope.eir_server_scope_len = len; res_EXCHANGE_ID4_ok.eir_server_scope.eir_server_scope_val = temp; res_EXCHANGE_ID4_ok.eir_server_impl_id.eir_server_impl_id_len = 0; res_EXCHANGE_ID4_ok.eir_server_impl_id.eir_server_impl_id_val = NULL; if(isDebug(COMPONENT_CLIENTID)) { char str[HASHTABLE_DISPLAY_STRLEN]; sprint_mem(str_verifier, arg_EXCHANGE_ID4.eia_clientowner.co_verifier, NFS4_VERIFIER_SIZE); display_client_id_rec(punconf, str); LogDebug(COMPONENT_CLIENTID, "EXCHANGE_ID reply Verifier=%s %s", str_verifier, str); } res_EXCHANGE_ID4.eir_status = NFS4_OK; out: V(pclient_record->cr_mutex); /* Release our reference to the client record */ dec_client_record_ref(pclient_record); return res_EXCHANGE_ID4.eir_status; } /* nfs41_op_exchange_id */
state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT * xprt, char * caller_name) { state_nsm_client_t key; state_nsm_client_t * pclient; char sock_name[SOCK_NAME_MAX]; char str[HASHTABLE_DISPLAY_STRLEN]; struct hash_latch latch; hash_error_t rc; hash_buffer_t buffkey; hash_buffer_t buffval; if(caller_name == NULL) return NULL; memset(&key, 0, sizeof(key)); if(nfs_param.core_param.nsm_use_caller_name) { key.ssc_nlm_caller_name_len = strlen(caller_name); if(key.ssc_nlm_caller_name_len > LM_MAXSTRLEN) { return NULL; } key.ssc_nlm_caller_name = caller_name; } else if(xprt == NULL) { int rc = ipstring_to_sockaddr(caller_name, &key.ssc_client_addr); if(rc != 0) { LogEvent(COMPONENT_STATE, "Error %s, converting caller_name %s to an ipaddress", gai_strerror(rc), caller_name); return NULL; } key.ssc_nlm_caller_name_len = strlen(caller_name); if(key.ssc_nlm_caller_name_len > LM_MAXSTRLEN) { return NULL; } key.ssc_nlm_caller_name = caller_name; } else { key.ssc_nlm_caller_name = sock_name; if(copy_xprt_addr(&key.ssc_client_addr, xprt) == 0) { LogCrit(COMPONENT_STATE, "Error converting caller_name %s to an ipaddress", caller_name); return NULL; } if(sprint_sockip(&key.ssc_client_addr, key.ssc_nlm_caller_name, sizeof(sock_name)) == 0) { LogCrit(COMPONENT_STATE, "Error converting caller_name %s to an ipaddress", caller_name); return NULL; } key.ssc_nlm_caller_name_len = strlen(key.ssc_nlm_caller_name); } if(isFullDebug(COMPONENT_STATE)) { display_nsm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.pdata = &key; buffkey.len = sizeof(key); rc = HashTable_GetLatch(ht_nsm_client, &buffkey, &buffval, TRUE, &latch); /* If we found it, return it */ if(rc == HASHTABLE_SUCCESS) { pclient = buffval.pdata; /* Return the found NSM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Found {%s}", str); } /* Increment refcount under hash latch. * This prevents dec ref from removing this entry from hash if a race * occurs. */ inc_nsm_client_ref(pclient); HashTable_ReleaseLatched(ht_nsm_client, &latch); if(care == CARE_MONITOR && !nsm_monitor(pclient)) { dec_nsm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if(rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nsm_client(&key, str); LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}", hash_table_err_to_str(rc), str); return NULL; } /* Not found, but we don't care, return NULL */ if(care == CARE_NOT) { /* Return the found NSM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nsm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } HashTable_ReleaseLatched(ht_nsm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if(pclient == NULL) { display_nsm_client(&key, str); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); if(pthread_mutex_init(&pclient->ssc_mutex, NULL) == -1) { /* Mutex initialization failed, free the created client */ display_nsm_client(&key, str); LogCrit(COMPONENT_STATE, "Could not init mutex for {%s}", str); gsh_free(pclient); return NULL; } pclient->ssc_nlm_caller_name = gsh_strdup(key.ssc_nlm_caller_name); if(pclient->ssc_nlm_caller_name == NULL) { /* Discard the created client */ free_nsm_client(pclient); return NULL; } init_glist(&pclient->ssc_lock_list); init_glist(&pclient->ssc_share_list); pclient->ssc_refcount = 1; if(isFullDebug(COMPONENT_STATE)) { display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "New {%s}", str); } buffkey.pdata = pclient; buffkey.len = sizeof(*pclient); buffval.pdata = pclient; buffval.len = sizeof(*pclient); rc = HashTable_SetLatched(ht_nsm_client, &buffval, &buffval, &latch, FALSE, NULL, NULL); /* An error occurred, return NULL */ if(rc != HASHTABLE_SUCCESS) { display_nsm_client(pclient, str); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); free_nsm_client(pclient); return NULL; } if(care != CARE_MONITOR || nsm_monitor(pclient)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nsm_client_ref(pclient); return NULL; }
state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT * xprt, const char * caller_name) { state_nsm_client_t *pkey, *pclient; if(caller_name == NULL) return NULL; pkey = (state_nsm_client_t *)Mem_Alloc(sizeof(*pkey)); if(pkey == NULL) return NULL; memset(pkey, 0, sizeof(*pkey)); pkey->ssc_refcount = 1; if(nfs_param.core_param.nsm_use_caller_name) { pkey->ssc_nlm_caller_name_len = strlen(caller_name); if(pkey->ssc_nlm_caller_name_len > LM_MAXSTRLEN) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } pkey->ssc_nlm_caller_name = Mem_Alloc(pkey->ssc_nlm_caller_name_len + 1); if(pkey->ssc_nlm_caller_name == NULL) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } memcpy(pkey->ssc_nlm_caller_name, caller_name, pkey->ssc_nlm_caller_name_len); pkey->ssc_nlm_caller_name[pkey->ssc_nlm_caller_name_len] = '\0'; } else { pkey->ssc_nlm_caller_name_len = SOCK_NAME_MAX; pkey->ssc_nlm_caller_name = Mem_Alloc(SOCK_NAME_MAX); if(pkey->ssc_nlm_caller_name == NULL) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } if(copy_xprt_addr(&pkey->ssc_client_addr, xprt) == 0) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } if(sprint_sockip(&pkey->ssc_client_addr, pkey->ssc_nlm_caller_name, SOCK_NAME_MAX) == 0) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } pkey->ssc_nlm_caller_name_len = strlen(pkey->ssc_nlm_caller_name); } if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pkey, str); LogFullDebug(COMPONENT_STATE, "Find NSM Client pkey {%s}", str); } /* If we found it, return it, if we don't care, return NULL */ if(nsm_client_Get_Pointer(pkey, &pclient) == 1 || care == CARE_NOT) { /* Discard the key we created and return the found NSM Client */ free_nsm_client(pkey); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Found NSM Client {%s}", str); } if(care == CARE_MONITOR) if(!nsm_monitor(pclient)) { dec_nsm_client_ref(pclient); return NULL; } return pclient; } pclient = (state_nsm_client_t *)Mem_Alloc(sizeof(*pkey)); if(pclient == NULL) { free_nsm_client(pkey); return NULL; } /* Copy everything over */ *pclient = *pkey; pclient->ssc_nlm_caller_name = Mem_Alloc(pkey->ssc_nlm_caller_name_len + 1); if(pclient->ssc_nlm_caller_name == NULL) { /* Discard the key and created client */ free_nsm_client(pkey); free_nsm_client(pclient); return NULL; } memcpy(pclient->ssc_nlm_caller_name, pkey->ssc_nlm_caller_name, pclient->ssc_nlm_caller_name_len); pclient->ssc_nlm_caller_name[pclient->ssc_nlm_caller_name_len] = '\0'; init_glist(&pclient->ssc_lock_list); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "New NSM Client {%s}", str); } if(pthread_mutex_init(&pclient->ssc_mutex, NULL) == -1) { /* Mutex initialization failed, free the key and created client */ free_nsm_client(pkey); free_nsm_client(pclient); return NULL; } if(nsm_client_Set(pkey, pclient) == 1) { if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Set NSM Client {%s}", str); } if(care != CARE_MONITOR || nsm_monitor(pclient)) return pclient; dec_nsm_client_ref(pclient); return NULL; } free_nsm_client(pkey); free_nsm_client(pclient); return NULL; }
int stat_export_check_access(struct sockaddr_storage *pssaddr, exportlist_client_t *clients, exportlist_client_entry_t * pclient_found) { sockaddr_t *psockaddr_in; #ifdef _USE_TIRPC_IPV6 struct sockaddr_in6 *psockaddr_in6; static char ten_bytes_all_0[10]; static unsigned two_bytes_all_1 = 0xFFFF; char ip6string[MAXHOSTNAMELEN]; memset(ten_bytes_all_0, 0, 10); #endif char ipstring[SOCK_NAME_MAX]; psockaddr_in = (sockaddr_t *)pssaddr; /* For now, no matching client is found */ memset(pclient_found, 0, sizeof(exportlist_client_entry_t)); #ifdef _USE_TIPRC_IPV6 if(psockaddr_in->sin_family == AF_INET) { #endif /* _USE_TIRPC_IPV6 */ /* Convert IP address into a string for wild character access checks. */ sprint_sockip(psockaddr_in, ipstring, sizeof(ipstring)); if(ipstring == NULL) { LogCrit(COMPONENT_MAIN, "Stat Export Check Access: Could not convert the IPv4 address to a character string."); return FALSE; } if(export_client_match (psockaddr_in, ipstring, clients, pclient_found, EXPORT_OPTION_READ_ACCESS | EXPORT_OPTION_WRITE_ACCESS)) return TRUE; #ifdef _USE_TIRPC_IPV6 } else { psockaddr_in6 = (struct sockaddr_in6 *)pssaddr; if(isFulldebug(COMPONENT_MAIN)) { char txtaddrv6[100]; inet_ntop(psockaddr_in6->sin6_family, psockaddr_in6->sin6_addr.s6_addr, txtaddrv6, 100); LogFullDebug(COMPONENT_MAIN, "Client has IPv6 adress = %s", txtaddrv6); } /* If the client socket is IPv4, then it is wrapped into a ::ffff:a.b.c.d IPv6 address. We check this here * This kind of adress is shaped like this: * |---------------------------------------------------------------| * | 80 bits = 10 bytes | 16 bits = 2 bytes | 32 bits = 4 bytes | * |---------------------------------------------------------------| * | 0 | FFFF | IPv4 address | * |---------------------------------------------------------------| */ if(!memcmp(psockaddr_in6->sin6_addr.s6_addr, ten_bytes_all_0, 10) && !memcmp((char *)(psockaddr_in6->sin6_addr.s6_addr + 10), (char *)&two_bytes_all_1, 2)) { /* Convert IP address into a string for wild character access checks. */ inet_ntop(psockaddr_in->sin6_family, &psockaddr_in->sin6_addr, ip6string, INET6_ADDRSTRLEN); if(ip6string == NULL) { LogCrit(COMPONENT_MAIN, "Error: Could not convert the IPv6 address to a character string."); return FALSE; } /* This is an IPv4 address mapped to an IPv6 one. Extract the IPv4 address and proceed with IPv4 autentication */ memcpy((char *)&addr, (char *)(psockaddr_in6->sin6_addr.s6_addr + 12), 4); /* Proceed with IPv4 dedicated function */ /* else, check if any access only export matches this client */ if(export_client_match (addr, ip6string, clients, pclient_found, EXPORT_OPTION_READ_ACCESS | EXPORT_OPTION_WRITE_ACCESS)) return TRUE; } if(export_client_matchv6 (&(psockaddr_in6->sin6_addr), clients, pclient_found, EXPORT_OPTION_READ_ACCESS | EXPORT_OPTION_WRITE_ACCESS)) return TRUE; } #endif /* _USE_TIRPC_IPV6 */ /* If this point is reached, no matching entry was found */ return FALSE; } /* stat_export_check_access */
void *stat_exporter_thread(void *addr) { int sockfd, new_fd; struct addrinfo hints, *servinfo, *p; struct sockaddr_storage their_addr; socklen_t sin_size; int yes = 1; char s[INET6_ADDRSTRLEN]; int rc; exportlist_client_entry_t pclient_found; SetNameFunction("statistics_exporter"); memset(&hints, 0, sizeof hints); #ifndef _USE_TIRPC_IPV6 hints.ai_family = AF_INET; #else hints.ai_family = AF_INET6; #endif hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if((rc = getaddrinfo(NULL, nfs_param.extern_param.stat_export.export_stat_port, &hints, &servinfo)) != 0) { LogCrit(COMPONENT_MAIN, "getaddrinfo: %s", gai_strerror(rc)); return NULL; } for(p = servinfo; p != NULL; p = p->ai_next) { if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { LogError(COMPONENT_MAIN, ERR_SYS, errno, sockfd); continue; } if((rc = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int))) == -1) { LogError(COMPONENT_MAIN, ERR_SYS, errno, rc); return NULL; } if((rc = bind(sockfd, p->ai_addr, p->ai_addrlen)) == -1) { close(sockfd); LogError(COMPONENT_MAIN, ERR_SYS, errno, rc); continue; } break; } if(p == NULL) { LogCrit(COMPONENT_MAIN, "server: failed to bind"); return NULL; } freeaddrinfo(servinfo); if((rc = listen(sockfd, BACKLOG)) == -1) { LogError(COMPONENT_MAIN, ERR_SYS, errno, rc); return NULL; } LogInfo(COMPONENT_MAIN, "Stat export server: Waiting for connections..."); while(1) { sin_size = sizeof their_addr; new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size); if(new_fd == -1) { LogError(COMPONENT_MAIN, ERR_SYS, errno, new_fd); continue; } sprint_sockip((sockaddr_t *)&their_addr, s, sizeof s); if (stat_export_check_access(&their_addr, &(nfs_param.extern_param.stat_export.allowed_clients), &pclient_found)) { LogDebug(COMPONENT_MAIN, "Stat export server: Access granted to %s", s); process_stat_request(addr, new_fd); } else { LogWarn(COMPONENT_MAIN, "Stat export server: Access denied to %s", s); } } /* while ( 1 ) */ return NULL; } /* stat_exporter_thread */
int nfs_ip_name_add(sockaddr_t *ipaddr, char *hostname, size_t size) { struct gsh_buffdesc buffkey; struct gsh_buffdesc buffdata; nfs_ip_name_t *nfs_ip_name = NULL; sockaddr_t *pipaddr = NULL; struct timeval tv0, tv1, dur; int rc; char ipstring[SOCK_NAME_MAX + 1]; nfs_ip_name = gsh_malloc(sizeof(nfs_ip_name_t)); pipaddr = gsh_malloc(sizeof(sockaddr_t)); /* I have to keep an integer as key, I wil use the pointer buffkey->addr * for this, this also means that buffkey->len will be 0 */ memcpy(pipaddr, ipaddr, sizeof(sockaddr_t)); buffkey.addr = pipaddr; buffkey.len = sizeof(sockaddr_t); gettimeofday(&tv0, NULL); rc = getnameinfo((struct sockaddr *)pipaddr, sizeof(sockaddr_t), nfs_ip_name->hostname, sizeof(nfs_ip_name->hostname), NULL, 0, 0); gettimeofday(&tv1, NULL); timersub(&tv1, &tv0, &dur); sprint_sockip(pipaddr, ipstring, sizeof(ipstring)); /* display warning if DNS resolution took more that 1.0s */ if (dur.tv_sec >= 1) { LogEvent(COMPONENT_DISPATCH, "Warning: long DNS query for %s: %u.%06u sec", ipstring, (unsigned int)dur.tv_sec, (unsigned int)dur.tv_usec); } /* Ask for the name to be cached */ if (rc != 0) { strmaxcpy(nfs_ip_name->hostname, ipstring, sizeof(nfs_ip_name->hostname)); LogEvent(COMPONENT_DISPATCH, "Cannot resolve address %s, error %s, using %s as hostname", ipstring, gai_strerror(rc), nfs_ip_name->hostname); } LogDebug(COMPONENT_DISPATCH, "Inserting %s->%s to addr cache", ipstring, nfs_ip_name->hostname); /* I build the data with the request pointer * that should be in state 'IN USE' */ nfs_ip_name->timestamp = time(NULL); buffdata.addr = nfs_ip_name; buffdata.len = sizeof(nfs_ip_name_t); if (HashTable_Set(ht_ip_name, &buffkey, &buffdata) != HASHTABLE_SUCCESS) return IP_NAME_INSERT_MALLOC_ERROR; /* Copy the value for the caller */ strmaxcpy(hostname, nfs_ip_name->hostname, size); return IP_NAME_SUCCESS; } /* nfs_ip_name_add */