int nfs4_op_setclientid(struct nfs_argop4 *op,
                        compound_data_t * data, struct nfs_resop4 *resp)
{
  char __attribute__ ((__unused__)) funcname[] = "nfs4_op_setclientid";
  char str_verifier[MAXNAMLEN];
  char str_client[MAXNAMLEN];

#define arg_SETCLIENTID4  op->nfs_argop4_u.opsetclientid
#define res_SETCLIENTID4  resp->nfs_resop4_u.opsetclientid

  clientid4 clientid;
  nfs_client_id_t * nfs_clientid;
  nfs_client_id_t   new_nfs_clientid;
  nfs_worker_data_t *pworker = NULL;

  pworker = (nfs_worker_data_t *) data->pclient->pworker;

  strncpy(str_verifier, arg_SETCLIENTID4.client.verifier, MAXNAMLEN);
  strncpy(str_client, arg_SETCLIENTID4.client.id.id_val,
          arg_SETCLIENTID4.client.id.id_len);
  str_client[arg_SETCLIENTID4.client.id.id_len] = '\0';

  LogDebug(COMPONENT_NFS_V4,
           "SETCLIENTID Client id len = %u",
           arg_SETCLIENTID4.client.id.id_len);
  LogDebug(COMPONENT_NFS_V4,
           "SETCLIENTID Client name = #%s#", str_client);
  /*LogDebug(COMPONENT_NFS_V4,
             "SETCLIENTID Verifier = #%s#", str_verifier ) ; */
  LogDebug(COMPONENT_NFS_V4,
           "SETCLIENTID Callback: cb_program = %u|0x%x, cb_location = { r_addr = %s   r_netid = %s }",
           arg_SETCLIENTID4.callback.cb_program,
           arg_SETCLIENTID4.callback.cb_program,
#ifdef _USE_NFS4_1
           arg_SETCLIENTID4.callback.cb_location.na_r_addr,
           arg_SETCLIENTID4.callback.cb_location.na_r_netid);
#else
           arg_SETCLIENTID4.callback.cb_location.r_addr,
           arg_SETCLIENTID4.callback.cb_location.r_netid);
#endif

  LogDebug(COMPONENT_NFS_V4,
           "SETCLIENTID callback_ident : %u",
           arg_SETCLIENTID4.callback_ident);

  /* First build the clientid4 nickname */

  /* There was no pb, returns the clientid */
  resp->resop = NFS4_OP_SETCLIENTID;
  res_SETCLIENTID4.status = NFS4_OK;

  /* Compute the client id */
  if(nfs_client_id_basic_compute(str_client, &clientid) != CLIENT_ID_SUCCESS)
    {
      res_SETCLIENTID4.status = NFS4ERR_SERVERFAULT;
      return res_SETCLIENTID4.status;
    }
  LogDebug(COMPONENT_NFS_V4,
           "SETCLIENTID computed clientid4=%"PRIx64" for name='%s'",
           clientid, str_client);

retry:

  /* Does this id already exists ? */
  if(nfs_client_id_Get_Pointer(clientid, &nfs_clientid) == CLIENT_ID_SUCCESS)
    {
      /* Client id already in use */
      LogDebug(COMPONENT_NFS_V4,
               "SETCLIENTID ClientId %"PRIx64" already in use for client '%s', check if same",
               clientid, nfs_clientid->client_name);

      P(nfs_clientid->clientid_mutex);
      /* Is existing client id confirmed? */
      if(nfs_clientid->confirmed == CONFIRMED_CLIENT_ID)
        {
          /* Check if client id has same credentials */
          if(nfs_compare_clientcred(&(nfs_clientid->credential), &(data->credential)) ==
             FALSE)
            {
              LogDebug(COMPONENT_NFS_V4,
                       "SETCLIENTID Confirmed ClientId %"PRIx64" -> '%s': Credential do not match... Return NFS4ERR_CLID_INUSE",
                       clientid, nfs_clientid->client_name);

              res_SETCLIENTID4.status = NFS4ERR_CLID_INUSE;
#ifdef _USE_NFS4_1
              res_SETCLIENTID4.SETCLIENTID4res_u.client_using.na_r_netid =
                  nfs_clientid->client_r_netid;
              res_SETCLIENTID4.SETCLIENTID4res_u.client_using.na_r_addr =
                  nfs_clientid->client_r_addr;
#else
              res_SETCLIENTID4.SETCLIENTID4res_u.client_using.r_netid =
                  nfs_clientid->client_r_netid;
              res_SETCLIENTID4.SETCLIENTID4res_u.client_using.r_addr =
                  nfs_clientid->client_r_addr;
#endif
              V(nfs_clientid->clientid_mutex);
              return res_SETCLIENTID4.status;
            }
          else
            LogDebug(COMPONENT_NFS_V4,
                     "SETCLIENTID ClientId %"PRIx64" is set again by same principal",
                     clientid);

          /* We have a confirmed client record, is it expired? */
          if (nfs4_is_lease_expired(nfs_clientid))
            {
              LogDebug(COMPONENT_NFS_V4,
                  "SETCLIENTID Existing ClientId %"PRIx64" is expired",
                   clientid);
              V(nfs_clientid->clientid_mutex);
              nfs_client_id_expire(nfs_clientid);
              goto retry;
            }


          /* Ask for a different client with the same client id... returns an error if different client */
          LogDebug(COMPONENT_NFS_V4,
                   "SETCLIENTID Confirmed ClientId %"PRIx64" already in use for client '%s'",
                   clientid, nfs_clientid->client_name);

          if(strncmp
             (nfs_clientid->incoming_verifier, arg_SETCLIENTID4.client.verifier,
              NFS4_VERIFIER_SIZE))
            {
              LogDebug(COMPONENT_NFS_V4,
                       "SETCLIENTID Confirmed ClientId %"PRIx64" already in use for client '%s', verifier do not match...",
                       clientid, nfs_clientid->client_name);

              /* A client has rebooted and rebuilds its state */
              LogDebug(COMPONENT_NFS_V4,
                       "SETCLIENTID: a client has rebooted. Remove the record for this client and create a new one.");
              V(nfs_clientid->clientid_mutex);
              nfs_client_id_expire(nfs_clientid);
              goto retry;
            }
          else
            {
              LogDebug(COMPONENT_NFS_V4,
                       "SETCLIENTID Confirmed ClientId %"PRIx64" already in use for client '%s', verifier matches. Now check callback",
                       clientid, nfs_clientid->client_name);

              LogDebug(COMPONENT_NFS_V4,
                       "SETCLIENTID '%s' will set the client UNCONFIRMED and returns NFS4_OK",
                       nfs_clientid->client_name);

              /* TODO: update callback program here. */

              /* Set the client UNCONFIRMED */
              nfs_clientid->confirmed = UNCONFIRMED_CLIENT_ID;

              res_SETCLIENTID4.status = NFS4_OK;

            }
        }
      else
        {
          LogDebug(COMPONENT_NFS_V4,
                   "SETCLIENTID ClientId %"PRIx64" already in use for client '%s', but unconfirmed",
                   clientid, nfs_clientid->client_name);
          V(nfs_clientid->clientid_mutex);
          nfs_client_id_expire(nfs_clientid);
          goto retry;
              
        }
      V(nfs_clientid->clientid_mutex);
    }
  else
    {
      /* Client record did not exist, build the client record */
      nfs_clientid = &new_nfs_clientid;
      strncpy(nfs_clientid->client_name, arg_SETCLIENTID4.client.id.id_val,
              arg_SETCLIENTID4.client.id.id_len);
      nfs_clientid->client_name[arg_SETCLIENTID4.client.id.id_len] = '\0';
#ifdef _USE_NFS4_1
      strncpy(nfs_clientid->client_r_addr, arg_SETCLIENTID4.callback.cb_location.na_r_addr,
              SOCK_NAME_MAX);
      strncpy(nfs_clientid->client_r_netid,
              arg_SETCLIENTID4.callback.cb_location.na_r_netid, MAXNAMLEN);
#else
      strncpy(nfs_clientid->client_r_addr, arg_SETCLIENTID4.callback.cb_location.r_addr,
              SOCK_NAME_MAX);
      strncpy(nfs_clientid->client_r_netid, arg_SETCLIENTID4.callback.cb_location.r_netid,
              MAXNAMLEN);
#endif
      strncpy(nfs_clientid->incoming_verifier, arg_SETCLIENTID4.client.verifier,
              NFS4_VERIFIER_SIZE);
      snprintf(nfs_clientid->verifier, NFS4_VERIFIER_SIZE, "%u",
               (unsigned int)ServerBootTime);

      nfs_clientid->confirmed = UNCONFIRMED_CLIENT_ID;
      nfs_clientid->cb_program = arg_SETCLIENTID4.callback.cb_program;
      nfs_clientid->clientid = clientid;
      nfs_clientid->last_renew = time(NULL);
      nfs_clientid->credential = data->credential;
      nfs_clientid->create_session_sequence = 0;
      if(pthread_mutex_init(&nfs_clientid->clientid_mutex, NULL) == -1)
      {
        res_SETCLIENTID4.status = NFS4ERR_SERVERFAULT;
        return res_SETCLIENTID4.status;
      }

      if(nfs_client_id_add(clientid, *nfs_clientid, data->pclient) !=
         CLIENT_ID_SUCCESS)
        {
          res_SETCLIENTID4.status = NFS4ERR_SERVERFAULT;
          return res_SETCLIENTID4.status;
        }
    }

  res_SETCLIENTID4.SETCLIENTID4res_u.resok4.clientid = clientid;
  memset(res_SETCLIENTID4.SETCLIENTID4res_u.resok4.setclientid_confirm, 0,
         NFS4_VERIFIER_SIZE);
  snprintf(res_SETCLIENTID4.SETCLIENTID4res_u.resok4.setclientid_confirm,
           NFS4_VERIFIER_SIZE, "%u", (unsigned int)ServerBootTime);

  /* LogDebug(COMPONENT_NFS_V4,
              "SETCLIENTID reply :ClientId=%llx Verifier=%s",  
              res_SETCLIENTID4.SETCLIENTID4res_u.resok4.clientid ,
              res_SETCLIENTID4.SETCLIENTID4res_u.resok4.setclientid_confirm ) ; */

  res_SETCLIENTID4.status = NFS4_OK;
  return res_SETCLIENTID4.status;
}                               /* nfs4_op_setclientid */
int nfs4_op_setclientid_confirm(struct nfs_argop4 *op,
                                compound_data_t * data, struct nfs_resop4 *resp)
{
  nfs_client_id_t * nfs_clientid;
  clientid4 clientid = 0;
  nfs_worker_data_t *pworker = NULL;

  pworker = (nfs_worker_data_t *) data->pclient->pworker;

#define arg_SETCLIENTID_CONFIRM4 op->nfs_argop4_u.opsetclientid_confirm
#define res_SETCLIENTID_CONFIRM4 resp->nfs_resop4_u.opsetclientid_confirm

  resp->resop = NFS4_OP_SETCLIENTID_CONFIRM;
  res_SETCLIENTID_CONFIRM4.status = NFS4_OK;
  clientid = arg_SETCLIENTID_CONFIRM4.clientid;

  LogDebug(COMPONENT_NFS_V4,
           "SETCLIENTID_CONFIRM clientid = %"PRIx64, clientid);
  /* LogDebug(COMPONENT_NFS_V4,
              "SETCLIENTID_CONFIRM Verifier = #%s#",
              arg_SETCLIENTID_CONFIRM4.setclientid_confirm ) ; */

  /* Does this id already exists ? */
  if(nfs_client_id_Get_Pointer(clientid, &nfs_clientid) == CLIENT_ID_SUCCESS)
    {
      /* The client id should not be confirmed */
      P(nfs_clientid->clientid_mutex);
      if(nfs_clientid->confirmed == CONFIRMED_CLIENT_ID)
        {
          LogDebug(COMPONENT_NFS_V4,
                   "SETCLIENTID_CONFIRM clientid is already confirmed");
          /* Client id was already confirmed and is then in use, this is NFS4ERR_CLID_INUSE if not same client */

          /* Check the verifier */
          if(strncmp
             (nfs_clientid->verifier, arg_SETCLIENTID_CONFIRM4.setclientid_confirm,
              NFS4_VERIFIER_SIZE))
            {
              /* Bad verifier */
              V(nfs_clientid->clientid_mutex);
              res_SETCLIENTID_CONFIRM4.status = NFS4ERR_CLID_INUSE;
              return res_SETCLIENTID_CONFIRM4.status;
            }
        }
      else
        {
          if(nfs_clientid->confirmed == REBOOTED_CLIENT_ID)
            {
              LogDebug(COMPONENT_NFS_V4,
                       "SETCLIENTID_CONFIRM clientid = %"PRIx64", client was rebooted, getting ride of old state from previous client instance",
                       clientid);
            }

          /* Regular situation, set the client id confirmed and returns */
          nfs_clientid->confirmed = CONFIRMED_CLIENT_ID;

          /* add this clientID to stable storage */
          nfs4_create_clid_name(nfs_clientid, data->reqp);
          nfs4_add_clid(nfs_clientid);

          /* Set the time for the client id */
          nfs_clientid->last_renew = time(NULL);

          /* check if the client can perform reclaims */
          nfs4_chk_clid(nfs_clientid);

#if 0
          /* Set the new value */
          if(nfs_client_id_set(clientid, nfs_clientid, &pworker->clientid_pool) !=
             CLIENT_ID_SUCCESS)
            {
              res_SETCLIENTID_CONFIRM4.status = NFS4ERR_SERVERFAULT;
              return res_SETCLIENTID_CONFIRM4.status;
            }
#endif
        }
      V(nfs_clientid->clientid_mutex);
    }
  else
    {
      /* The client id does not exist: stale client id */
      res_SETCLIENTID_CONFIRM4.status = NFS4ERR_STALE_CLIENTID;
      return res_SETCLIENTID_CONFIRM4.status;
    }

  /* Successful exit */
  res_SETCLIENTID_CONFIRM4.status = NFS4_OK;
  return res_SETCLIENTID_CONFIRM4.status;
}                               /* nfs4_op_setclientid_confirm */
Beispiel #3
0
int nfs41_op_create_session(struct nfs_argop4 *op,
                            compound_data_t * data, struct nfs_resop4 *resp)
{
    nfs_client_id_t *pnfs_clientid;
    nfs41_session_t *pnfs41_session = NULL;
    clientid4 clientid = 0;

#define arg_CREATE_SESSION4 op->nfs_argop4_u.opcreate_session
#define res_CREATE_SESSION4 resp->nfs_resop4_u.opcreate_session

    resp->resop = NFS4_OP_CREATE_SESSION;
    res_CREATE_SESSION4.csr_status = NFS4_OK;
    clientid = arg_CREATE_SESSION4.csa_clientid;

    /* Does this id already exists ? */
    if(nfs_client_id_Get_Pointer(clientid, &pnfs_clientid) != CLIENT_ID_SUCCESS)
    {
        /* The client id does not exist: stale client id */
        res_CREATE_SESSION4.csr_status = NFS4ERR_STALE_CLIENTID;
        return res_CREATE_SESSION4.csr_status;
    }

    LogDebug(COMPONENT_NFS_V4,
             "CREATE_SESSION clientid=%lld csa_sequence=%"PRIu32
             " clientid_cs_seq=%" PRIu32" data_oppos=%d data_use_drc=%d\n",
             (long long unsigned int) clientid,
             arg_CREATE_SESSION4.csa_sequence,
             pnfs_clientid->create_session_sequence,
             data->oppos,
             data->use_drc);

    data->use_drc = FALSE;

    if(data->oppos == 0)
    {
        /* Special case : the request is used without use of OP_SEQUENCE */
        if((arg_CREATE_SESSION4.csa_sequence + 1 == pnfs_clientid->create_session_sequence)
                && (pnfs_clientid->create_session_slot.cache_used == TRUE))
        {
            data->use_drc = TRUE;
            data->pcached_res = pnfs_clientid->create_session_slot.cached_result;

            res_CREATE_SESSION4.csr_status = NFS4_OK;
            return res_CREATE_SESSION4.csr_status;
        }
        else if(arg_CREATE_SESSION4.csa_sequence != pnfs_clientid->create_session_sequence)
        {
            res_CREATE_SESSION4.csr_status = NFS4ERR_SEQ_MISORDERED;
            return res_CREATE_SESSION4.csr_status;
        }

    }

    pnfs_clientid->confirmed = CONFIRMED_CLIENT_ID;
    pnfs_clientid->cb_program = arg_CREATE_SESSION4.csa_cb_program;

    pnfs_clientid->create_session_sequence += 1;
    /** @todo: BUGAZOMEU Gerer les parametres de secu */

    /* Record session related information at the right place */
    GetFromPool(pnfs41_session, &data->pclient->pool_session, nfs41_session_t);

    if(pnfs41_session == NULL)
    {
        res_CREATE_SESSION4.csr_status = NFS4ERR_SERVERFAULT;
        return res_CREATE_SESSION4.csr_status;
    }

    /* Check flags value (test CSESS15) */
    if(arg_CREATE_SESSION4.csa_flags > CREATE_SESSION4_FLAG_CONN_RDMA)
    {
        res_CREATE_SESSION4.csr_status = NFS4ERR_INVAL;
        return res_CREATE_SESSION4.csr_status;
    }

    memset((char *)pnfs41_session, 0, sizeof(nfs41_session_t));
    pnfs41_session->clientid = clientid;

    pnfs41_session->sequence = arg_CREATE_SESSION4.csa_sequence;
    pnfs41_session->session_flags = CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
    pnfs41_session->fore_channel_attrs = arg_CREATE_SESSION4.csa_fore_chan_attrs;
    pnfs41_session->back_channel_attrs = arg_CREATE_SESSION4.csa_back_chan_attrs;

    /* Set ca_maxrequests */
    pnfs41_session->fore_channel_attrs.ca_maxrequests = NFS41_NB_SLOTS;
    pnfs41_session->fore_channel_attrs.ca_maxrequests = NFS41_NB_SLOTS;

    if(nfs41_Build_sessionid(&clientid, pnfs41_session->session_id) != 1)
    {
        res_CREATE_SESSION4.csr_status = NFS4ERR_SERVERFAULT;
        return res_CREATE_SESSION4.csr_status;
    }

    res_CREATE_SESSION4.CREATE_SESSION4res_u.csr_resok4.csr_sequence =
        pnfs41_session->sequence;
    res_CREATE_SESSION4.CREATE_SESSION4res_u.csr_resok4.csr_flags =
        CREATE_SESSION4_FLAG_CONN_BACK_CHAN;

    /* return the input for wantinf of something better (will change in later versions) */
    res_CREATE_SESSION4.CREATE_SESSION4res_u.csr_resok4.csr_fore_chan_attrs =
        pnfs41_session->fore_channel_attrs;
    res_CREATE_SESSION4.CREATE_SESSION4res_u.csr_resok4.csr_back_chan_attrs =
        pnfs41_session->back_channel_attrs;

    memcpy(res_CREATE_SESSION4.CREATE_SESSION4res_u.csr_resok4.csr_sessionid,
           pnfs41_session->session_id, NFS4_SESSIONID_SIZE);

    /* Create Session replay cache */
    data->pcached_res = pnfs_clientid->create_session_slot.cached_result;
    pnfs_clientid->create_session_slot.cache_used = TRUE;

    if(!nfs41_Session_Set(pnfs41_session->session_id, pnfs41_session))
    {
        res_CREATE_SESSION4.csr_status = NFS4ERR_SERVERFAULT;     /* Maybe a more precise status would be better */
        return res_CREATE_SESSION4.csr_status;
    }

    /* Successful exit */
    res_CREATE_SESSION4.csr_status = NFS4_OK;
    return res_CREATE_SESSION4.csr_status;
}                               /* nfs41_op_create_session */