Beispiel #1
0
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");
}
Beispiel #2
0
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");
}
Beispiel #3
0
/**
 *
 * 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 */
Beispiel #4
0
/**
 *
 * 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 */
Beispiel #5
0
/**
 * @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 */
Beispiel #8
0
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;
}
Beispiel #9
0
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 */
Beispiel #12
0
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 */