Esempio n. 1
0
/**
 * @brief Display an NLM client
 *
 * @param[in/out] dspbuf display_buffer describing output string
 * @param[in]     key    The NLM client
 *
 * @return the bytes remaining in the buffer.
 */
int display_nlm_client(struct display_buffer *dspbuf, state_nlm_client_t *key)
{
	int b_left;

	if (key == NULL)
		return display_printf(dspbuf, "NLM Client <NULL>");

	b_left = display_printf(dspbuf, "NLM Client %p: {", key);

	if (b_left <= 0)
		return b_left;

	b_left = display_nsm_client(dspbuf, key->slc_nsm_client);

	if (b_left <= 0)
		return b_left;

	b_left = display_printf(dspbuf, "} caller_name=");

	if (b_left <= 0)
		return b_left;

	b_left = display_len_cat(dspbuf,
				 key->slc_nlm_caller_name,
				 key->slc_nlm_caller_name_len);

	if (b_left <= 0)
		return b_left;

	return display_printf(dspbuf, " type=%s refcount=%d",
			      xprt_type_to_str(key->slc_client_type),
			      atomic_fetch_int32_t(&key->slc_refcount));
}
Esempio n. 2
0
int display_nlm_client(state_nlm_client_t *pkey, char *str)
{
  char *strtmp = str;

  if(pkey == NULL)
    return sprintf(str, "<NULL>");

  strtmp += sprintf(strtmp, "%p: NSM Client {", pkey);
  strtmp += display_nsm_client(pkey->slc_nsm_client, strtmp);
  strtmp += sprintf(strtmp, "} caller_name=");
  strncpy(strtmp, pkey->slc_nlm_caller_name, pkey->slc_nlm_caller_name_len);
  strtmp += pkey->slc_nlm_caller_name_len;
  strtmp += sprintf(strtmp, " type=%s", xprt_type_to_str(pkey->slc_client_type));
  strtmp += sprintf(strtmp, " refcount=%d", pkey->slc_refcount);

  return strtmp - str;
}
Esempio n. 3
0
int display_nlm_client(state_nlm_client_t *pkey, char *str)
{
  char *strtmp = str;

  if(pkey == NULL)
    return sprintf(str, "NLM Client <NULL>");

  strtmp += sprintf(strtmp, "NLM Client %p: {", pkey);
  strtmp += display_nsm_client(pkey->slc_nsm_client, strtmp);
  strtmp += sprintf(strtmp, "} caller_name=");
  memcpy(strtmp, pkey->slc_nlm_caller_name, pkey->slc_nlm_caller_name_len);
  strtmp += pkey->slc_nlm_caller_name_len;
  strtmp += sprintf(strtmp, " type=%s",
                    xprt_type_to_str(pkey->slc_client_type));
  strtmp += sprintf(strtmp, " refcount=%d",
                    atomic_fetch_int32_t(&pkey->slc_refcount));

  return strtmp - str;
}
Esempio n. 4
0
/**
 * @brief Validate export permissions
 *
 * @param[in]  req              Incoming request.
 *
 * @return NFS4_OK if successful, NFS4ERR_ACCESS or NFS4ERR_WRONGSEC otherwise.
 *
 */
nfsstat4 nfs4_export_check_access(struct svc_req *req)
{
	xprt_type_t xprt_type = svc_get_xprt_type(req->rq_xprt);
	int port = get_port(op_ctx->caller_addr);

	LogMidDebugAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT,
		    "nfs4_export_check_access about to call export_check_access");
	export_check_access();

	/* Check if any access at all */
	if ((op_ctx->export_perms->options &
	     EXPORT_OPTION_ACCESS_MASK) == 0) {
		LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT,
			"Access not allowed on Export_Id %d %s for client %s",
			op_ctx->ctx_export->export_id,
			op_ctx->ctx_export->fullpath,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");
		return NFS4ERR_ACCESS;
	}

	/* Check protocol version */
	if ((op_ctx->export_perms->options & EXPORT_OPTION_NFSV4) == 0) {
		LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT,
			"NFS4 not allowed on Export_Id %d %s for client %s",
			op_ctx->ctx_export->export_id,
			op_ctx->ctx_export->fullpath,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");
		return NFS4ERR_ACCESS;
	}

	/* Check transport type */
	if (((xprt_type == XPRT_UDP) &&
	    ((op_ctx->export_perms->options &
	      EXPORT_OPTION_UDP) == 0))
	    ||
	    ((xprt_type == XPRT_TCP) &&
	    ((op_ctx->export_perms->options &
	      EXPORT_OPTION_TCP) == 0))) {
		LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT,
			"NFS4 over %s not allowed on Export_Id %d %s for client %s",
			xprt_type_to_str(xprt_type),
			op_ctx->ctx_export->export_id,
			op_ctx->ctx_export->fullpath,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");
		return NFS4ERR_ACCESS;
	}

	/* Check if client is using a privileged port. */
	if (((op_ctx->export_perms->options &
	      EXPORT_OPTION_PRIVILEGED_PORT) != 0)
	    && (port >= IPPORT_RESERVED)) {
		LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT,
			"Non-reserved Port %d is not allowed on Export_Id %d %s for client %s",
			port, op_ctx->ctx_export->export_id,
			op_ctx->ctx_export->fullpath,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");
		return NFS4ERR_ACCESS;
	}

	/* Test if export allows the authentication provided */
	if (export_check_security(req) == false) {
		LogInfoAlt(COMPONENT_NFS_V4, COMPONENT_EXPORT,
			"NFS4 auth not allowed on Export_Id %d %s for client %s",
			op_ctx->ctx_export->export_id,
			op_ctx->ctx_export->fullpath,
			op_ctx->client
				? op_ctx->client->hostaddr_str
				: "unknown client");
		return NFS4ERR_WRONGSEC;
	}

	/* Get creds */
	return nfs_req_creds(req);
}
Esempio n. 5
0
/* Client routine  to send the asynchrnous response,
 * key is used to wait for a response
 */
int nlm_send_async(int proc, state_nlm_client_t *host, void *inarg, void *key)
{
	struct timeval tout = { 0, 10 };
	int retval, retry;
	struct timeval start, now;
	struct timespec timeout;

	for (retry = 1; retry <= MAX_ASYNC_RETRY; retry++) {
		if (host->slc_callback_clnt == NULL) {
			LogFullDebug(COMPONENT_NLM,
				     "gsh_clnt_create %s",
				     host->slc_nsm_client->ssc_nlm_caller_name);

			if (host->slc_client_type == XPRT_TCP) {
				int fd;
				struct sockaddr_in6 server_addr;
				struct netbuf *buf, local_buf;
				struct addrinfo *result;
				struct addrinfo hints;
				char port_str[20];

				fd = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
				if (fd < 0)
					return -1;

				memcpy(&server_addr,
				       &(host->slc_server_addr),
				       sizeof(struct sockaddr_in6));
				server_addr.sin6_port = 0;

				if (bind(fd,
					 (struct sockaddr *)&server_addr,
					  sizeof(server_addr)) == -1) {
					LogMajor(COMPONENT_NLM, "Cannot bind");
					close(fd);
					return -1;
				}

				buf = rpcb_find_mapped_addr(
				     (char *) xprt_type_to_str(
							host->slc_client_type),
				     NLMPROG, NLM4_VERS,
				     host->slc_nsm_client->ssc_nlm_caller_name);
				/* handle error here, for example,
				 * client side blocking rpc call
				 */
				if (buf == NULL) {
					LogMajor(COMPONENT_NLM,
						 "Cannot create NLM async %s connection to client %s",
						 xprt_type_to_str(
							host->slc_client_type),
						 host->slc_nsm_client->
						 ssc_nlm_caller_name);
					close(fd);
					return -1;
				}

				memset(&hints, 0, sizeof(struct addrinfo));
				hints.ai_family = AF_INET6;	/* only INET6 */
				hints.ai_socktype = SOCK_STREAM; /* TCP */
				hints.ai_protocol = 0;	/* Any protocol */
				hints.ai_canonname = NULL;
				hints.ai_addr = NULL;
				hints.ai_next = NULL;

				/* convert port to string format */
				sprintf(port_str, "%d",
					htons(((struct sockaddr_in *)
						buf->buf)->sin_port));

				/* buf with inet is only needed for the port */
				gsh_free(buf->buf);
				gsh_free(buf);

				/* get the IPv4 mapped IPv6 address */
				getaddrinfo(host->slc_nsm_client->
					    ssc_nlm_caller_name,
					    port_str,
					    &hints,
					    &result);

				/* setup the netbuf with in6 address */
				local_buf.buf = result->ai_addr;
				local_buf.len = local_buf.maxlen =
				    result->ai_addrlen;

				host->slc_callback_clnt =
				    clnt_vc_ncreate(fd, &local_buf, NLMPROG,
						    NLM4_VERS, 0, 0);
				freeaddrinfo(result);
			} else {

				host->slc_callback_clnt = gsh_clnt_create(
				    host->slc_nsm_client->ssc_nlm_caller_name,
				    NLMPROG,
				    NLM4_VERS,
				    (char *) xprt_type_to_str(
						host->slc_client_type));
			}

			if (host->slc_callback_clnt == NULL) {
				LogMajor(COMPONENT_NLM,
					 "Cannot create NLM async %s connection to client %s",
					 xprt_type_to_str(host->
							  slc_client_type),
					 host->slc_nsm_client->
					 ssc_nlm_caller_name);
				return -1;
			}

			/* split auth (for authnone, idempotent) */
			host->slc_callback_auth = authnone_create();
		}

		PTHREAD_MUTEX_lock(&nlm_async_resp_mutex);
		resp_key = key;
		PTHREAD_MUTEX_unlock(&nlm_async_resp_mutex);

		LogFullDebug(COMPONENT_NLM, "About to make clnt_call");

		retval = clnt_call(host->slc_callback_clnt,
				   host->slc_callback_auth,
				   proc,
				   nlm_reply_proc[proc],
				   inarg,
				   (xdrproc_t) xdr_void,
				   NULL,
				   tout);

		LogFullDebug(COMPONENT_NLM, "Done with clnt_call");

		if (retval == RPC_TIMEDOUT || retval == RPC_SUCCESS) {
			retval = RPC_SUCCESS;
			break;
		}

		LogCrit(COMPONENT_NLM,
			"NLM async Client procedure call %d failed with return code %d %s",
			proc, retval,
			clnt_sperror(host->slc_callback_clnt, ""));

		gsh_clnt_destroy(host->slc_callback_clnt);
		host->slc_callback_clnt = NULL;

		if (retry == MAX_ASYNC_RETRY) {
			LogMajor(COMPONENT_NLM,
				 "NLM async Client exceeded retry count %d",
				 MAX_ASYNC_RETRY);
			PTHREAD_MUTEX_lock(&nlm_async_resp_mutex);
			resp_key = NULL;
			PTHREAD_MUTEX_unlock(&nlm_async_resp_mutex);
			return retval;
		}
	}

	PTHREAD_MUTEX_lock(&nlm_async_resp_mutex);

	if (resp_key != NULL) {
		/* Wait for 5 seconds or a signal */
		gettimeofday(&start, NULL);
		gettimeofday(&now, NULL);
		timeout.tv_sec = 5 + start.tv_sec;
		timeout.tv_nsec = 0;

		LogFullDebug(COMPONENT_NLM,
			     "About to wait for signal for key %p", resp_key);

		while (resp_key != NULL && now.tv_sec < (start.tv_sec + 5)) {
			int rc;
			rc = pthread_cond_timedwait(&nlm_async_resp_cond,
						    &nlm_async_resp_mutex,
						    &timeout);
			LogFullDebug(COMPONENT_NLM,
				     "pthread_cond_timedwait returned %d",
				     rc);
			gettimeofday(&now, NULL);
		}
		LogFullDebug(COMPONENT_NLM, "Done waiting");
	}

	PTHREAD_MUTEX_unlock(&nlm_async_resp_mutex);

	return retval;
}
Esempio n. 6
0
/* Client routine  to send the asynchrnous response, key is used to wait for a response */
int nlm_send_async(int                  proc,
                   state_nlm_client_t * host,
                   void               * inarg,
                   void               * key)
{
  struct timeval  tout = { 0, 10 };
  int             retval, retry;
  struct timeval  start, now;
  struct timespec timeout;

  for(retry = 1; retry <= MAX_ASYNC_RETRY; retry++)
    {
      if(host->slc_callback_clnt == NULL)
        {
          LogFullDebug(COMPONENT_NLM,
                       "Clnt_create %s",
                       host->slc_nsm_client->ssc_nlm_caller_name);

          host->slc_callback_clnt = Clnt_create(host->slc_nsm_client->ssc_nlm_caller_name,
                                                NLMPROG,
                                                NLM4_VERS,
                                                (char *)xprt_type_to_str(host->slc_client_type));

          if(host->slc_callback_clnt == NULL)
            {
              LogMajor(COMPONENT_NLM,
                       "Cannot create NLM async %s connection to client %s",
                       xprt_type_to_str(host->slc_client_type),
                       host->slc_nsm_client->ssc_nlm_caller_name);
              return -1;
            }
        }

      pthread_mutex_lock(&nlm_async_resp_mutex);
      resp_key = key;
      pthread_mutex_unlock(&nlm_async_resp_mutex);

      LogFullDebug(COMPONENT_NLM, "About to make clnt_call");
      retval = clnt_call(host->slc_callback_clnt,
                         proc,
                         nlm_reply_proc[proc],
                         inarg,
                         (xdrproc_t) xdr_void,
                         NULL,
                         tout);
      LogFullDebug(COMPONENT_NLM, "Done with clnt_call");

      if(retval == RPC_TIMEDOUT || retval == RPC_SUCCESS)
        {
          retval = RPC_SUCCESS;
          break;
        }

      LogDebug(COMPONENT_NLM,
               "NLM async Client procedure call %d failed with return code %d %s",
               proc, retval, clnt_sperror(host->slc_callback_clnt, ""));

      Clnt_destroy(host->slc_callback_clnt);
      host->slc_callback_clnt = NULL;

      if(retry == MAX_ASYNC_RETRY)
        {
          LogMajor(COMPONENT_NLM,
                   "NLM async Client exceeded retry count %d",
                   MAX_ASYNC_RETRY);
          pthread_mutex_lock(&nlm_async_resp_mutex);
          resp_key = NULL;
          pthread_mutex_unlock(&nlm_async_resp_mutex);
          return retval;
        }
    }

  pthread_mutex_lock(&nlm_async_resp_mutex);
  if(resp_key != NULL)
    {
      /* Wait for 5 seconds or a signal */
      gettimeofday(&start, NULL);
      gettimeofday(&now, NULL);
      timeout.tv_sec = 5 + start.tv_sec;
      timeout.tv_nsec = 0;
      LogFullDebug(COMPONENT_NLM,
                   "About to wait for signal for key %p",
                   resp_key);
      while(resp_key != NULL && now.tv_sec < (start.tv_sec + 5))
        {
          int rc = pthread_cond_timedwait(&nlm_async_resp_cond, &nlm_async_resp_mutex, &timeout);
          LogFullDebug(COMPONENT_NLM,
                       "pthread_cond_timedwait returned %d", rc);
          gettimeofday(&now, NULL);
        }
      LogFullDebug(COMPONENT_NLM, "Done waiting");
    }
  pthread_mutex_unlock(&nlm_async_resp_mutex);

  return retval;
}