예제 #1
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 */
예제 #2
0
/*
 * Given a (possibly unqualified) hostname,
 * return the fully qualified (lower-case!) hostname
 */
static int get_full_hostname(const char *inhost, char *outhost, int outhostlen)
{
	struct addrinfo *addrs = NULL;
	struct addrinfo hints;
	int retval;
	char *c;

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_CANONNAME;

	/* Get full target hostname */
	retval = getaddrinfo(inhost, NULL, &hints, &addrs);
	if (retval) {
		printerr(1, "%s while getting full hostname for '%s'\n",
			 gai_strerror(retval), inhost);
		goto out;
	}
	strmaxcpy(outhost, addrs->ai_canonname, outhostlen);
	freeaddrinfo(addrs);
	for (c = outhost; *c != '\0'; c++)
		*c = tolower(*c);

	printerr(3, "Full hostname for '%s' is '%s'\n", inhost, outhost);
	retval = 0;
 out:
	return retval;
}
예제 #3
0
void nfs_set_client_location(nfs_client_id_t *pclientid, const clientaddr4 *addr4)
{
    pclientid->cid_cb.cid_addr.nc = nfs_netid_to_nc(addr4->r_netid);
    if(strmaxcpy(pclientid->cid_cb.cid_client_r_addr,
                 addr4->r_addr,
                 sizeof(pclientid->cid_cb.cid_client_r_addr)) == -1) {
        LogCrit(COMPONENT_NFS_CB,
                "cid_client_r_addr %s too long",
                pclientid->cid_cb.cid_client_r_addr);
    }
    setup_client_saddr(pclientid, pclientid->cid_cb.cid_client_r_addr);
}
예제 #4
0
/*
 * Initialize subsystem
 */
void nfs_rpc_cb_pkginit(void)
{
    char localmachine[MAXHOSTNAMELEN];

    /* Create a pool of rpc_call_t */
    rpc_call_pool = pool_init("RPC Call Pool",
                              sizeof(rpc_call_t),
                              pool_basic_substrate,
                              NULL,
                              nfs_rpc_init_call,
                              NULL);
    if(!(rpc_call_pool)) {
        LogCrit(COMPONENT_INIT,
                "Error while allocating rpc call pool");
        LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno);
        Fatal();
    }

    /* get host name */
    if(gethostname(localmachine, sizeof(localmachine)) != 0) {
        LogCrit(COMPONENT_INIT, "Failed to get local host name");
    }
    else
        if(strmaxcpy(host_name, localmachine, sizeof(host_name)) == -1) {
            LogCrit(COMPONENT_INIT,
                    "local host name %s too long",
                    localmachine);
        }

    /* ccache */
    nfs_rpc_cb_init_ccache(nfs_param.krb5_param.ccache_dir);

    /* sanity check GSSAPI */
    if (gssd_check_mechs() != 0)
        LogCrit(COMPONENT_INIT,  "sanity check: gssd_check_mechs() failed");

    return;
}
예제 #5
0
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;
}
예제 #6
0
/**
 *
 * nfs_Add_MountList_Entry: Adds a client to the mount list.
 *
 * Adds a client to the mount list.
 *
 * @param hostname [IN] the hostname for the client
 * @param dirpath [IN] the mounted path 
 *
 * @return 1 if successful, 0 otherwise
 *
 */
int nfs_Add_MountList_Entry(char *hostname, char *dirpath)
{
#ifndef _NO_MOUNT_LIST
  mountlist pnew_mnt_list_entry;
#endif

  /* Sanity check */
  if(hostname == NULL || dirpath == NULL)
    return 0;

#ifndef _NO_MOUNT_LIST

  /* Allocate the new entry */
  if((pnew_mnt_list_entry = gsh_calloc(1, sizeof(struct mountbody))) == NULL)
    return 0;

  if((pnew_mnt_list_entry->ml_hostname
      = gsh_calloc(1, MAXHOSTNAMELEN + 1)) == NULL)
    {
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }

  if((pnew_mnt_list_entry->ml_directory
      = gsh_calloc(1, MAXPATHLEN + 1)) == NULL)
    {
      gsh_free(pnew_mnt_list_entry->ml_hostname);
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }
  /* Copy the data */
  if (strmaxcpy(pnew_mnt_list_entry->ml_hostname, hostname,
		MAXHOSTNAMELEN) == -1)
    {
      gsh_free(pnew_mnt_list_entry->ml_directory);
      gsh_free(pnew_mnt_list_entry->ml_hostname);
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }
  if (strmaxcpy(pnew_mnt_list_entry->ml_directory, dirpath,
		MAXPATHLEN) == -1)
    {
      gsh_free(pnew_mnt_list_entry->ml_directory);
      gsh_free(pnew_mnt_list_entry->ml_hostname);
      gsh_free(pnew_mnt_list_entry);
      return 0;
    }

  /* initialize next pointer */
  pnew_mnt_list_entry->ml_next = NULL;

  /* This should occur only for the first mount */
  if(MNT_List_head == NULL)
    {
      MNT_List_head = pnew_mnt_list_entry;
    }

  /* Append to the tail of the list */
  if(MNT_List_tail == NULL)
    MNT_List_tail = pnew_mnt_list_entry;
  else
    {
      MNT_List_tail->ml_next = pnew_mnt_list_entry;
      MNT_List_tail = pnew_mnt_list_entry;
    }

  if(isFullDebug(COMPONENT_NFSPROTO))
    nfs_Print_MountList();

#endif

  return 1;
}
예제 #7
0
int
main(int argc, char *argv[])
{
	int fg = 0;
	int verbosity = 0;
	int rpc_verbosity = 0;
	int opt;
	int i;
	extern char *optarg;
	char *progname;

	memset(ccachesearch, 0, sizeof(ccachesearch));
	while ((opt = getopt(argc, argv, "fvrmnMp:k:d:t:R:")) != -1) {
		switch (opt) {
			case 'f':
				fg = 1;
				break;
			case 'm':
				/* Accept but ignore this. Now the default. */
				break;
			case 'M':
				use_memcache = 1;
				break;
			case 'n':
				root_uses_machine_creds = 0;
				break;
			case 'v':
				verbosity++;
				break;
			case 'r':
				rpc_verbosity++;
				break;
			case 'p':
				strmaxcpy(pipefs_dir, optarg, sizeof(pipefs_dir));
				if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0')
					errx(1, "pipefs path name too long");
				break;
			case 'k':
				strmaxcpy(keytabfile, optarg, sizeof(keytabfile));
				if (keytabfile[sizeof(keytabfile)-1] != '\0')
					errx(1, "keytab path name too long");
				break;
			case 'd':
				strmaxcpy(ccachedir, optarg, sizeof(ccachedir));
				if (ccachedir[sizeof(ccachedir)-1] != '\0')
					errx(1, "ccachedir path name too long");
				break;
			case 't':
				context_timeout = atoi(optarg);
				break;
			case 'R':
				preferred_realm = strdup(optarg);
				break;
			default:
				usage(argv[0]);
				break;
		}
	}

	i = 0;
	ccachesearch[i++] = strtok(ccachedir, ":");
	do {
		ccachesearch[i++] = strtok(NULL, ":");
	} while (ccachesearch[i-1] != NULL && i < GSSD_MAX_CCACHE_SEARCH);

	if (preferred_realm == NULL)
		gssd_k5_get_default_realm(&preferred_realm);

	if ((progname = strrchr(argv[0], '/')))
		progname++;
	else
		progname = argv[0];

	initerr(progname, verbosity, fg);
#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL
	if (verbosity && rpc_verbosity == 0)
		rpc_verbosity = verbosity;
	authgss_set_debug_level(rpc_verbosity);
#else
        if (rpc_verbosity > 0)
		printerr(0, "Warning: rpcsec_gss library does not "
			    "support setting debug level\n");
#endif

	if (gssd_check_mechs() != 0)
		errx(1, "Problem with gssapi library");

	if (!fg && daemon(0, 0) < 0)
		errx(1, "fork");

	signal(SIGINT, sig_die);
	signal(SIGTERM, sig_die);
	signal(SIGHUP, sig_hup);

	gssd_run();
	printerr(0, "gssd_run returned!\n");
	abort();
}
예제 #8
0
/*
 * Create, initialize, and add a new ple structure to the global list
 */
static struct gssd_k5_kt_princ *new_ple(krb5_context context,
					krb5_principal princ)
{
	struct gssd_k5_kt_princ *ple = NULL, *p;
	krb5_error_code code;
	char *default_realm;
	int is_default_realm = 0;

	ple = gsh_malloc(sizeof(struct gssd_k5_kt_princ));
	if (ple == NULL)
		goto outerr;
	memset(ple, 0, sizeof(*ple));

#ifdef HAVE_KRB5
	ple->realm = gsh_malloc(princ->realm.length + 1);
	if (ple->realm == NULL)
		goto outerr;
	strmaxcpy(ple->realm, princ->realm.data, princ->realm.length);
	ple->realm[princ->realm.length] = '\0';
#else
	ple->realm = gsh_strdup(princ->realm);
	if (ple->realm == NULL)
		goto outerr;
#endif
	code = krb5_copy_principal(context, princ, &ple->princ);
	if (code)
		goto outerr;

	/*
	 * Add new entry onto the list (if this is the default
	 * realm, always add to the front of the list)
	 */

	code = krb5_get_default_realm(context, &default_realm);
	if (code == 0) {
		if (strcmp(ple->realm, default_realm) == 0)
			is_default_realm = 1;
		k5_free_default_realm(context, default_realm);
	}

	if (is_default_realm) {
		ple->next = gssd_k5_kt_princ_list;
		gssd_k5_kt_princ_list = ple;
	} else {
		p = gssd_k5_kt_princ_list;
		while (p != NULL && p->next != NULL)
			p = p->next;
		if (p == NULL)
			gssd_k5_kt_princ_list = ple;
		else
			p->next = ple;
	}

	return ple;
 outerr:
	if (ple) {
		if (ple->realm)
			gsh_free(ple->realm);
		gsh_free(ple);
	}
	return NULL;
}
예제 #9
0
/**
 *
 * nfs_read_gidmap_conf: reads the configuration for the GID_MAPPER Cache
 *
 * Reads the configuration for the GID_MAPPER Cache
 *
 * @param in_config [IN] configuration file handle
 * @param pparam [OUT] read parameters
 *
 * @return 0 if ok,  -1 if not, 1 is stanza is not there.
 *
 */
int nfs_read_gidmap_conf(config_file_t in_config, nfs_idmap_cache_parameter_t * pparam)
{
  int var_max;
  int var_index;
  int err;
  char *key_name;
  char *key_value;
  config_item_t block;

  /* Is the config tree initialized ? */
  if(in_config == NULL || pparam == NULL)
    return -1;

  /* Get the config BLOCK */
  if((block = config_FindItemByName(in_config, CONF_LABEL_GID_MAPPER)) == NULL)
    {
      LogDebug(COMPONENT_CONFIG,
               "Cannot read item \"%s\" from configuration file",
               CONF_LABEL_CLIENT_ID);
      return 1;
    }
  else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
    {
      /* Expected to be a block */
      LogDebug(COMPONENT_CONFIG,
               "Item \"%s\" is expected to be a block",
               CONF_LABEL_CLIENT_ID);
      return 1;
    }

  var_max = config_GetNbItems(block);

  for(var_index = 0; var_index < var_max; var_index++)
    {
      config_item_t item;

      item = config_GetItemByIndex(block, var_index);

      /* Get key's name */
      if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0)
        {
          LogCrit(COMPONENT_CONFIG,
                  "Error reading key[%d] from section \"%s\" of configuration file.",
                  var_index, CONF_LABEL_GID_MAPPER);
          return -1;
        }

      if(!strcasecmp(key_name, "Index_Size"))
        {
          pparam->hash_param.index_size = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Alphabet_Length"))
        {
          pparam->hash_param.alphabet_length = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Map"))
        {
          if(strmaxcpy(pparam->mapfile,
                       key_value,
                       sizeof(pparam->mapfile)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else
        {
          LogCrit(COMPONENT_CONFIG,
                  "Unknown or unsettable key: %s (item %s)",
                  key_name, CONF_LABEL_GID_MAPPER);
          return -1;
        }
    }

  return 0;
}                               /* nfs_read_gidmap_conf */
예제 #10
0
/**
 *
 * nfs_read_core_conf: read the configuration ite; for the worker theads.
 *
 * Reads the configuration ite; for the worker theads.
 *
 * @param in_config [IN] configuration file handle
 * @param pparam [OUT] read parameters
 *
 * @return 0 if ok, -1 if failed, 1 is stanza is not there.
 *
 */
int nfs_read_core_conf(config_file_t in_config, nfs_core_parameter_t * pparam)
{
  int var_max;
  int var_index;
  int err;
  char *key_name;
  char *key_value;
  config_item_t block;

  /* Is the config tree initialized ? */
  if(in_config == NULL || pparam == NULL)
    return CACHE_INODE_INVALID_ARGUMENT;

  /* Get the config BLOCK */
  if((block = config_FindItemByName(in_config, CONF_LABEL_NFS_CORE)) == NULL)
    {
      LogDebug(COMPONENT_CONFIG,
               "Cannot read item \"%s\" from configuration file",
               CONF_LABEL_NFS_CORE);
      return 1;
    }
  else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
    {
      /* Expected to be a block */
      LogDebug(COMPONENT_CONFIG,
               "Item \"%s\" is expected to be a block",
               CONF_LABEL_NFS_CORE);
      return 1;
    }

  var_max = config_GetNbItems(block);

  for(var_index = 0; var_index < var_max; var_index++)
    {
      config_item_t item;

      item = config_GetItemByIndex(block, var_index);

      /* Get key's name */
      if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0)
        {
          LogCrit(COMPONENT_CONFIG,
                  "Error reading key[%d] from section \"%s\" of configuration file.",
                  var_index, CONF_LABEL_NFS_CORE);
          return CACHE_INODE_INVALID_ARGUMENT;
        }

      if(!strcasecmp(key_name, "Nb_Worker"))
        {
          pparam->nb_worker = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Nb_Call_Before_Queue_Avg"))
        {
          pparam->nb_call_before_queue_avg = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_Disabled"))
        {
            pparam->drc.disabled = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Npart"))
        {
          pparam->drc.tcp.npart = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Size"))
        {
          pparam->drc.tcp.size = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Cachesz"))
        {
          pparam->drc.tcp.cachesz = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Hiwat"))
        {
          pparam->drc.tcp.hiwat = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Recycle_Npart"))
        {
          pparam->drc.tcp.recycle_npart = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Recycle_Expire_S"))
        {
          pparam->drc.tcp.recycle_expire_s = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_TCP_Checksum"))
        {
          pparam->drc.tcp.checksum = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_UDP_Npart"))
        {
          pparam->drc.udp.npart = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_UDP_Size"))
        {
          pparam->drc.udp.size = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_UDP_Cachesz"))
        {
          pparam->drc.udp.cachesz = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_UDP_Hiwat"))
        {
          pparam->drc.udp.hiwat = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DRC_UDP_Checksum"))
        {
          pparam->drc.udp.checksum = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "DupReq_Expiration"))
        {
          pparam->expiration_dupreq = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Dispatch_Max_Reqs"))
        {
          pparam->dispatch_max_reqs = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Dispatch_Max_Reqs_Xprt"))
        {
          pparam->dispatch_max_reqs_xprt = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Drop_IO_Errors"))
        {
          pparam->drop_io_errors = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "Drop_Inval_Errors"))
        {
          pparam->drop_inval_errors = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "Drop_Delay_Errors"))
        {
          pparam->drop_delay_errors = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "NFS_Port"))
        {
          pparam->port[P_NFS] = (unsigned short)atoi(key_value);
        }
      else if(!strcasecmp(key_name, "MNT_Port"))
        {
          pparam->port[P_MNT] = (unsigned short)atoi(key_value);
        }
      else if(!strcasecmp(key_name, "NLM_Port"))
        {
#ifdef _USE_NLM
          pparam->port[P_NLM] = (unsigned short)atoi(key_value);
#endif
        }
      else if(!strcasecmp(key_name, "Rquota_Port"))
        {
#ifdef _USE_RQUOTA
          pparam->port[P_RQUOTA] = (unsigned short)atoi(key_value);
#endif
        }
      else if(!strcasecmp(key_name, "NFS_Program"))
        {
          pparam->program[P_NFS] = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "MNT_Program"))
        {
          pparam->program[P_MNT] = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "NLM_Program"))
        {
#ifdef _USE_NLM
          pparam->program[P_NLM] = atoi(key_value);
#endif
        }
      else if(!strcasecmp(key_name, "Rquota_Program"))
        {
#ifdef _USE_RQUOTA
          pparam->program[P_RQUOTA] = atoi(key_value);
#endif
        }
      else if(!strcasecmp(key_name, "NFS_Protocols"))
        {

#     define MAX_NFSPROTO      10       /* large enough !!! */

          char *nfsvers_list[MAX_NFSPROTO];
          int idx, count;

          /* reset nfs versions flags (clean defaults) */
          pparam->core_options &= ~(CORE_OPTION_ALL_VERS);

          /* fill nfs vers list with NULL pointers */
          memset(nfsvers_list, 0, sizeof(nfsvers_list));

          /*
           * Search for coma-separated list of nfsprotos
           */
          count = nfs_ParseConfLine(nfsvers_list,
                                    MAX_NFSPROTO,
                                    0,
                                    key_value,
                                    ',');

          if(count < 0)
            {
              LogCrit(COMPONENT_CONFIG,
                      "NFS_Protocols list too long (>%d)",
                      MAX_NFSPROTO);

              return -1;
            }

          /* add each Nfs protocol flag to the option field.  */

          for(idx = 0; idx < count; idx++)
            {
              if(!strcmp(nfsvers_list[idx], "4"))
                {
                  pparam->core_options |= CORE_OPTION_NFSV4;
                }
              else if(!strcmp(nfsvers_list[idx], "2"))
                {
                  pparam->core_options |= CORE_OPTION_NFSV2;
                }
              else if(!strcmp(nfsvers_list[idx], "3"))
                {
                  pparam->core_options |= CORE_OPTION_NFSV3;
                }
              else
                {
                  LogCrit(COMPONENT_CONFIG,
                          "Invalid NFS Protocol \"%s\". Values can be: 2, 3, 4.",
                          nfsvers_list[idx]);
                  return -1;
                }
            }

          /* check that at least one nfs protocol has been specified */
          if((pparam->core_options & (CORE_OPTION_ALL_VERS)) == 0)
            {
              LogCrit(COMPONENT_CONFIG, "Empty NFS_Protocols list");
              return -1;
            }
        }
      else if(!strcasecmp(key_name, "Bind_Addr"))
        {
          int rc;
          memset(&pparam->bind_addr.sin_addr, 0, sizeof(pparam->bind_addr.sin_addr));
          rc = inet_pton(AF_INET, key_value, &pparam->bind_addr.sin_addr);
          if(rc <= 0)
            {
              /* Revert to INADDR_ANY in case of any error */
              pparam->bind_addr.sin_addr.s_addr = INADDR_ANY;   /* All the interfaces on the machine are used */
            }
        }
      else if(!strcasecmp(key_name, "Core_Dump_Size"))
        {
          pparam->core_dump_size = atol(key_value);
        }
      else if(!strcasecmp(key_name, "Nb_Max_Fd"))
        {
          pparam->nb_max_fd = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Stats_File_Path"))
        {
          if(strmaxcpy(pparam->stats_file_path,
                       key_value,
                       sizeof(pparam->stats_file_path)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else if(!strcasecmp(key_name, "Stats_Update_Delay"))
        {
          pparam->stats_update_delay = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Long_Processing_Threshold"))
        {
          pparam->long_processing_threshold = atoi(key_value);
          pparam->long_processing_threshold_msec = pparam->long_processing_threshold * MSEC_PER_SEC;
        }
      else if(!strcasecmp( key_name, "Decoder_Fridge_Expiration_Delay" ) )
        {
          pparam->decoder_fridge_expiration_delay = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "Dump_Stats_Per_Client"))
        {
          pparam->dump_stats_per_client = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "Stats_Per_Client_Directory"))
        {
          if(strmaxcpy(pparam->stats_per_client_directory,
                       key_value,
                       sizeof(pparam->stats_per_client_directory)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else if(!strcasecmp( key_name, "MaxRPCSendBufferSize" ) )
        {
          pparam->max_send_buffer_size = atoi(key_value);
        }
      else if(!strcasecmp( key_name, "MaxRPCRecvBufferSize" ) )
        {
          pparam->max_recv_buffer_size = atoi(key_value);
        }
#ifdef _USE_NLM
      else if(!strcasecmp( key_name, "NSM_Use_Caller_Name" ) )
        {
          pparam->nsm_use_caller_name = StrToBoolean(key_value);
        }
#endif
      else if(!strcasecmp(key_name, "Clustered"))
        {
          pparam->clustered = StrToBoolean(key_value);
        }
      else
        {
          LogCrit(COMPONENT_CONFIG,
                  "Unknown or unsettable key: %s (item %s)",
                  key_name, CONF_LABEL_NFS_CORE);
          return -1;
        }

    }

  return 0;
}                               /* nfs_read_core_conf */
예제 #11
0
int nfs_get_fsalpathlib_conf(char *configPath, path_str_t * PathLib, unsigned int *plen)
{
  int var_max;
  int var_index;
  int err;
  char *key_name;
  char *key_value;
  config_item_t block;
  unsigned int found = FALSE;
  config_file_t config_struct;
  unsigned int index = 0 ;

  /* Is the config tree initialized ? */
  if(configPath == NULL || PathLib == NULL)
    LogFatal(COMPONENT_CONFIG,
             "nfs_get_fsalpathlib_conf configPath=%p PathLib=%p",
             configPath, PathLib);

  config_struct = config_ParseFile(configPath);

  if(!config_struct)
    LogFatal(COMPONENT_CONFIG,
             "Error while parsing %s: %s",
             configPath, config_GetErrorMsg());

  /* Get the config BLOCK */
  if((block = config_FindItemByName(config_struct, CONF_LABEL_NFS_CORE)) == NULL)
    {
      LogFatal(COMPONENT_CONFIG,
               "Cannot read item \"%s\" from configuration file",
               CONF_LABEL_NFS_CORE);
    }
  else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
    {
      /* Expected to be a block */
      LogFatal(COMPONENT_CONFIG,
               "Item \"%s\" is expected to be a block",
               CONF_LABEL_NFS_CORE);
    }

  var_max = config_GetNbItems(block);

  for(var_index = 0; var_index < var_max; var_index++)
    {
      config_item_t item;

      item = config_GetItemByIndex(block, var_index);

      /* Get key's name */
      if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0)
        {
          LogFatal(COMPONENT_CONFIG,
                   "Error reading key[%d] from section \"%s\" of configuration file.",
                   var_index, CONF_LABEL_NFS_CORE);
        }

      if(!strcasecmp(key_name, "FSAL_Shared_Library"))
        {
          if(strmaxcpy(PathLib[index],
                       key_value,
                       sizeof(PathLib[index])) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
          index += 1 ;

          found = TRUE;

          /* Do not exceed array size */
          if( index == *plen )
            break ;
        }

    }

  if(!found)
   {
    LogFatal(COMPONENT_CONFIG,
             "FSAL_Shared_Library not found");
    return 1;
   }

  *plen = index ;
  return 0;
}                               /* nfs_get_fsalpathlib_conf */
예제 #12
0
/**
 *
 * nfs_read_version4_conf: read the configuration for NFSv4 stuff
 *
 * Read the configuration for NFSv4 stuff.
 *
 * @param in_config [IN] configuration file handle
 * @param pparam [OUT] read parameters
 *
 * @return 0 if ok, -1 if failed,1 is stanza is not there
 *
 */
int nfs_read_version4_conf(config_file_t in_config, nfs_version4_parameter_t * pparam)
{
  int var_max;
  int var_index;
  int err;
  char *key_name;
  char *key_value;
  config_item_t block;

  /* Is the config tree initialized ? */
  if(in_config == NULL || pparam == NULL)
    return -1;

  /* Get the config BLOCK */
  if((block = config_FindItemByName(in_config, CONF_LABEL_NFS_VERSION4)) == NULL)
    {
      LogDebug(COMPONENT_CONFIG,
               "Cannot read item \"%s\" from configuration file",
               CONF_LABEL_NFS_VERSION4);
      return 1;
    }
  else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
    {
      /* Expected to be a block */
      LogDebug(COMPONENT_CONFIG,
               "Item \"%s\" is expected to be a block",
               CONF_LABEL_NFS_VERSION4);
      return 1;
    }

  var_max = config_GetNbItems(block);

  for(var_index = 0; var_index < var_max; var_index++)
    {
      config_item_t item;

      item = config_GetItemByIndex(block, var_index);

      /* Get key's name */
      if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0)
        {
          LogCrit(COMPONENT_CONFIG,
                  "Error reading key[%d] from section \"%s\" of configuration file.",
                  var_index, CONF_LABEL_NFS_VERSION4);
          return -1;
        }

      if(!strcasecmp(key_name, "Lease_Lifetime"))
        {
          pparam->lease_lifetime = atoi(key_value);
        }
      else if(!strcasecmp(key_name, "DomainName"))
        {
          if(strmaxcpy(pparam->domainname,
                       key_value,
                       sizeof(pparam->domainname)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else if(!strcasecmp(key_name, "IdmapConf"))
        {
          if(strmaxcpy(pparam->idmapconf,
                       key_value,
                       sizeof(pparam->idmapconf)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else if(!strcasecmp(key_name, "FH_Expire"))
        {
          pparam->fh_expire = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "Returns_ERR_FH_EXPIRED"))
        {
          pparam->returns_err_fh_expired = StrToBoolean(key_value);
        }
      else if(!strcasecmp(key_name, "Return_Bad_Stateid"))
        {
          pparam->return_bad_stateid = StrToBoolean(key_value);
        }
      else
        {
          LogCrit(COMPONENT_CONFIG,
                  "Unknown or unsettable key: %s (item %s)",
                  key_name, CONF_LABEL_NFS_VERSION4);
          return -1;
        }
    }

  return 0;
}                               /* nfs_read_version4_conf */
예제 #13
0
/**
 *
 * nfs_read_krb5_conf: read the configuration for krb5 stuff
 *
 * Read the configuration for krb5 stuff.
 *
 * @param in_config [IN] configuration file handle
 * @param pparam [OUT] read parameters
 *
 * @return 0 if ok, -1 if failed,1 is stanza is not there
 *
 */
int nfs_read_krb5_conf(config_file_t in_config, nfs_krb5_parameter_t * pparam)
{
  int var_max;
  int var_index;
  int err;
  char *key_name;
  char *key_value;
  config_item_t block;

  /* Is the config tree initialized ? */
  if(in_config == NULL || pparam == NULL)
    return -1;

  /* Get the config BLOCK */
  if((block = config_FindItemByName(in_config, CONF_LABEL_NFS_KRB5)) == NULL)
    {
      LogDebug(COMPONENT_CONFIG,
               "Cannot read item \"%s\" from configuration file",
               CONF_LABEL_NFS_KRB5);
      return 1;
    }
  else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
    {
      /* Expected to be a block */
      LogDebug(COMPONENT_CONFIG,
               "Item \"%s\" is expected to be a block",
               CONF_LABEL_NFS_KRB5);
      return 1;
    }

  var_max = config_GetNbItems(block);

  for(var_index = 0; var_index < var_max; var_index++)
    {
      config_item_t item;

      item = config_GetItemByIndex(block, var_index);

      /* Get key's name */
      if((err = config_GetKeyValue(item, &key_name, &key_value)) != 0)
        {
          LogCrit(COMPONENT_CONFIG,
                  "Error reading key[%d] from section \"%s\" of configuration file.",
                  var_index, CONF_LABEL_NFS_KRB5);
          return -1;
        }

      if(!strcasecmp(key_name, "PrincipalName"))
        {
          if(strmaxcpy(pparam->svc.principal,
                       key_value,
                       sizeof(pparam->svc.principal)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else if(!strcasecmp(key_name, "KeytabPath"))
        {
          if(strmaxcpy(pparam->keytab,
                       key_value,
                       sizeof(pparam->keytab)) == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "%s=\"%s\" too long",
                      key_name, key_value);
            }
        }
      else if(!strcasecmp(key_name, "Active_krb5"))
        {
          pparam->active_krb5 = StrToBoolean(key_value);
        }
      else
        {
          LogCrit(COMPONENT_CONFIG,
                  "Unknown or unsettable key: %s (item %s)",
                  key_name, CONF_LABEL_NFS_KRB5);
          return -1;
        }
    }

  return 0;
}                               /* nfs_read_krb5_conf */
예제 #14
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 */
예제 #15
0
int get_snmpadm_conf(config_file_t in_config, external_tools_parameter_t * out_parameter)
{
  int err;
  int var_max, var_index;
  char *key_name;
  char *key_value;
  config_item_t block;
  config_item_t item;



   /* Get the config BLOCK */
 if((block = config_FindItemByName(in_config, CONF_SNMP_ADM_LABEL)) == NULL)
    {
      /* cannot read item */
      LogCrit(COMPONENT_CONFIG,
              "SNMP_ADM: Cannot read item \"%s\" from configuration file",
              CONF_SNMP_ADM_LABEL);
      /* Expected to be a block */
      return ENOENT;
    }
  else if(config_ItemType(block) != CONFIG_ITEM_BLOCK)
     {
       LogCrit(COMPONENT_CONFIG,
               "SNMP_ADM: Cannot read item \"%s\" from configuration file",
               CONF_SNMP_ADM_LABEL);
      /* Expected to be a block */
       return ENOENT;
     }

  /* makes an iteration on the (key, value) couplets */
  var_max = config_GetNbItems(block);

  for(var_index = 0; var_index < var_max; var_index++)
    {
       /* retrieve key's name */
      item = config_GetItemByIndex(block, var_index);
      err = config_GetKeyValue(item, &key_name, &key_value);

      if(err)
        {
          LogCrit(COMPONENT_CONFIG,
                  "SNMP_ADM: ERROR reading key[%d] from section \"%s\" of configuration file.",
                  var_index, CONF_LABEL_FS_SPECIFIC);
          return err;
        }

      /* what parameter is it ? */

      if(!STRCMP(key_name, "Snmp_Agentx_Socket"))
        {
          if(strmaxcpy(out_parameter->snmp_adm.snmp_agentx_socket,
                       key_value,
                       sizeof(out_parameter->snmp_adm.snmp_agentx_socket)) == -1)
            LogCrit(COMPONENT_CONFIG,
                    "SNMP_ADM: ERROR: value \"%s\" for %s is too long",
                    key_name, key_value);
        }
      else if(!STRCMP(key_name, "Product_Id"))
        {
          out_parameter->snmp_adm.product_id = atoi(key_value);
        }
      else if(!STRCMP(key_name, "Snmp_adm_log"))
        {
          if(strmaxcpy(out_parameter->snmp_adm.snmp_log_file,
                       key_value,
                       sizeof(out_parameter->snmp_adm.snmp_log_file)) == -1)
            LogCrit(COMPONENT_CONFIG,
                    "SNMP_ADM: ERROR: value \"%s\" for %s is too long",
                    key_name, key_value);
        }
      else if(!STRCMP(key_name, "Export_cache_stats"))
        {
          int nbool = StrToBoolean(key_value);
          if(nbool == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "SNMP_ADM: ERROR: Unexpected value for %s: boolean expected.",
                      key_name);
              return EINVAL;
            }
          out_parameter->snmp_adm.export_cache_stats = nbool;
        }
      else if(!STRCMP(key_name, "Export_requests_stats"))
        {
          int nbool = StrToBoolean(key_value);
          if(nbool == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "SNMP_ADM: ERROR: Unexpected value for %s: boolean expected.",
                      key_name);
              return EINVAL;
            }
          out_parameter->snmp_adm.export_requests_stats = nbool;
        }
      else if(!STRCMP(key_name, "Export_maps_stats"))
        {
          int nbool = StrToBoolean(key_value);
          if(nbool == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "SNMP_ADM: ERROR: Unexpected value for %s: boolean expected.",
                      key_name);
              return EINVAL;
            }
          out_parameter->snmp_adm.export_maps_stats = nbool;
        }
      else if(!STRCMP(key_name, "Export_nfs_calls_detail"))
        {
          int nbool = StrToBoolean(key_value);
          if(nbool == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "SNMP_ADM: ERROR: Unexpected value for %s: boolean expected.",
                      key_name);
              return EINVAL;
            }
          out_parameter->snmp_adm.export_nfs_calls_detail = nbool;
        }
      else if(!STRCMP(key_name, "Export_FSAL_calls_detail"))
        {
          int nbool = StrToBoolean(key_value);
          if(nbool == -1)
            {
              LogCrit(COMPONENT_CONFIG,
                      "SNMP_ADM: ERROR: Unexpected value for %s: boolean expected.",
                      key_name);
              return EINVAL;
            }
          out_parameter->snmp_adm.export_fsal_calls_detail = nbool;
        }
      else
        {
          LogCrit(COMPONENT_CONFIG,
                  "SNMP_ADM LOAD PARAMETER: ERROR: Unknown or unsettable key: %s (item %s)",
                  key_name, CONF_LABEL_FS_SPECIFIC);
          return EINVAL;
        }
    }
  config_ok = 1;
  return 0;
}
예제 #16
0
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];
	struct display_buffer dspbuf_verifier = {
			sizeof(str_verifier), str_verifier, str_verifier};
	char str_client[NFS4_OPAQUE_LIMIT * 2 + 1];
	struct display_buffer dspbuf_client = {
			sizeof(str_client), str_client, str_client};
	const char *str_client_addr = "(unknown)";
	/* The clientid4 broken down into fields */
	char str_clientid4[DISPLAY_CLIENTID_SIZE];
	/* Display buffer for clientid4 */
	struct display_buffer dspbuf_clientid4 = {
		sizeof(str_clientid4), str_clientid4, str_clientid4};
	nfs_client_record_t *client_record;
	nfs_client_id_t *conf;
	nfs_client_id_t *unconf;
	clientid4 clientid;
	verifier4 verifier;
	int rc;

	resp->resop = NFS4_OP_SETCLIENTID;

	if (data->minorversion > 0) {
		res_SETCLIENTID4->status = NFS4ERR_NOTSUPP;
		return res_SETCLIENTID4->status;
	}

	if (op_ctx->client != NULL)
		str_client_addr = op_ctx->client->hostaddr_str;

	if (isDebug(COMPONENT_CLIENTID)) {
		display_opaque_value(&dspbuf_client,
				     arg_SETCLIENTID4->client.id.id_val,
				     arg_SETCLIENTID4->client.id.id_len);

		display_opaque_bytes(&dspbuf_verifier,
				     arg_SETCLIENTID4->client.verifier,
				     NFS4_VERIFIER_SIZE);
	} else {
		str_client[0] = '\0';
		str_verifier[0] = '\0';
	}

	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[LOG_BUFF_LEN] = "\0";
		struct display_buffer dspbuf = {sizeof(str), str, str};

		display_client_record(&dspbuf, client_record);

		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) {
		bool credmatch;

		/* Need a reference to the confirmed record for below */
		inc_client_id_ref(conf);

		clientid = conf->cid_clientid;
		display_clientid(&dspbuf_clientid4, clientid);

		credmatch = nfs_compare_clientcred(&conf->cid_credential,
						   &data->credential)
			    && op_ctx->client != NULL
			    && conf->gsh_client != NULL
			    && op_ctx->client == conf->gsh_client;

		/* Only reject if the principal doesn't match and the
		 * clientid has live state associated. Per RFC 7530
		 * Section 9.1.2. Server Release of Client ID.
		 */
		if (!credmatch && clientid_has_state(conf)) {
			/* CASE 1:
			 *
			 * Confirmed record exists and not the same principal
			 */
			if (isDebug(COMPONENT_CLIENTID)) {
				char *confirmed_addr = "(unknown)";

				if (conf->gsh_client != NULL)
					confirmed_addr =
					    conf->gsh_client->hostaddr_str;

				LogDebug(COMPONENT_CLIENTID,
					 "Confirmed ClientId %s->'%s': Principals do not match... confirmed addr=%s Return NFS4ERR_CLID_INUSE",
					 str_clientid4, 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 (credmatch && 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 %s->%s",
				     str_clientid4, str_client);

			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 %s->%s",
				     str_clientid4, 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).
		 */
		clientid = new_clientid();
		display_clientid(&dspbuf_clientid4, clientid);
		LogFullDebug(COMPONENT_CLIENTID,
			     "New client %s", str_clientid4);
		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[LOG_BUFF_LEN] = "\0";
			struct display_buffer dspbuf = {sizeof(str), str, str};

			display_client_id_rec(&dspbuf, unconf);

			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,
				  &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_no_expire(rc);
		goto out;
	}

	if (isDebug(COMPONENT_CLIENTID)) {
		char str[LOG_BUFF_LEN] = "\0";
		struct display_buffer dspbuf = {sizeof(str), str, str};

		sprint_mem(str_verifier, verifier, NFS4_VERIFIER_SIZE);

		display_client_id_rec(&dspbuf, unconf);
		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;
}