nfs-ganesha 1.4

nfs41_op_create_session.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  *
00023  * ---------------------------------------
00024  */
00025 
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039 
00040 #ifdef _SOLARIS
00041 #include "solaris_port.h"
00042 #endif
00043 
00044 #include <pthread.h>
00045 #include "log.h"
00046 #include "nfs4.h"
00047 #include "nfs_core.h"
00048 #include "nfs_exports.h"
00049 #include "nfs_proto_functions.h"
00050 #include "sal_functions.h"
00051 
00068 int nfs41_op_create_session(struct nfs_argop4 *op,
00069                             compound_data_t * data, struct nfs_resop4 *resp)
00070 {
00071   nfs_client_id_t     * pconf   = NULL;
00072   nfs_client_id_t     * punconf = NULL;
00073   nfs_client_id_t     * pfound  = NULL;
00074   nfs_client_record_t * pclient_record;
00075   nfs41_session_t     * nfs41_session = NULL;
00076   clientid4             clientid = 0;
00077   sockaddr_t            client_addr;
00078   char                  str_client_addr[SOCK_NAME_MAX];
00079   char                  str_client[NFS4_OPAQUE_LIMIT * 2 + 1];
00080   int                   rc;
00081   log_components_t      component = COMPONENT_CLIENTID;
00082 
00083   if(isDebug(COMPONENT_SESSIONS))
00084     component = COMPONENT_SESSIONS;
00085 
00086 #define arg_CREATE_SESSION4 op->nfs_argop4_u.opcreate_session
00087 #define res_CREATE_SESSION4 resp->nfs_resop4_u.opcreate_session
00088 #define res_CREATE_SESSION4ok res_CREATE_SESSION4.CREATE_SESSION4res_u.csr_resok4
00089 
00090   resp->resop = NFS4_OP_CREATE_SESSION;
00091   res_CREATE_SESSION4.csr_status = NFS4_OK;
00092   clientid = arg_CREATE_SESSION4.csa_clientid;
00093 
00094   copy_xprt_addr(&client_addr, data->reqp->rq_xprt);
00095 
00096   if(isDebug(component))
00097     sprint_sockip(&client_addr, str_client_addr, sizeof(str_client_addr));
00098 
00099   LogDebug(component,
00100            "CREATE_SESSION client addr=%s clientid=%"PRIx64" -------------------",
00101            str_client_addr,
00102            clientid);
00103 
00104   /* First try to look up unconfirmed record */
00105   rc = nfs_client_id_get_unconfirmed(clientid, &punconf);
00106 
00107   if(rc == CLIENT_ID_SUCCESS)
00108     {
00109       pclient_record = punconf->cid_client_record;
00110       pfound         = punconf;
00111     }
00112   else
00113     {
00114       rc = nfs_client_id_get_confirmed(clientid, &pconf);
00115       if(rc != CLIENT_ID_SUCCESS)
00116         {
00117           /* No record whatsoever of this clientid */
00118           LogDebug(component,
00119                    "Stale clientid = %"PRIx64,
00120                    clientid);
00121           res_CREATE_SESSION4.csr_status = NFS4ERR_STALE_CLIENTID;
00122 
00123           return res_CREATE_SESSION4.csr_status;
00124         }
00125       pclient_record = pconf->cid_client_record;
00126       pfound         = pconf;
00127     }
00128 
00129   P(pclient_record->cr_mutex);
00130 
00131   inc_client_record_ref(pclient_record);
00132 
00133   if(isFullDebug(component))
00134     {
00135       char str[HASHTABLE_DISPLAY_STRLEN];
00136 
00137       display_client_record(pclient_record, str);
00138 
00139       LogFullDebug(component,
00140                    "Client Record %s cr_pconfirmed_id=%p cr_punconfirmed_id=%p",
00141                    str,
00142                    pclient_record->cr_pconfirmed_id,
00143                    pclient_record->cr_punconfirmed_id);
00144     }
00145 
00146   /* At this point one and only one of pconf and punconf is non-NULL, and pfound
00147    * also references the single clientid record that was found.
00148    */
00149 
00150   LogDebug(component,
00151            "CREATE_SESSION clientid=%"PRIx64" csa_sequence=%"PRIu32
00152            " clientid_cs_seq=%" PRIu32" data_oppos=%d data_use_drc=%d",
00153            clientid,
00154            arg_CREATE_SESSION4.csa_sequence,
00155            pfound->cid_create_session_sequence,
00156            data->oppos,
00157            data->use_drc);
00158 
00159   if(isFullDebug(component))
00160     {
00161       char str[HASHTABLE_DISPLAY_STRLEN];
00162 
00163       display_client_id_rec(pfound, str);
00164       LogFullDebug(component,
00165                    "Found %s",
00166                    str);
00167     }
00168 
00169   data->use_drc = FALSE;
00170 
00171   if(data->oppos == 0)
00172     {
00173       /* Special case : the request is used without use of OP_SEQUENCE */
00174       if((arg_CREATE_SESSION4.csa_sequence + 1 == pfound->cid_create_session_sequence)
00175          && (pfound->cid_create_session_slot.cache_used == TRUE))
00176         {
00177           data->use_drc = TRUE;
00178           data->pcached_res = &pfound->cid_create_session_slot.cached_result;
00179 
00180           res_CREATE_SESSION4.csr_status = NFS4_OK;
00181 
00182           dec_client_id_ref(pfound);
00183 
00184           LogDebug(component, "CREATE_SESSION replay=%p special case", data->pcached_res);
00185 
00186           goto out;
00187         }
00188       else if(arg_CREATE_SESSION4.csa_sequence != pfound->cid_create_session_sequence)
00189         {
00190           res_CREATE_SESSION4.csr_status = NFS4ERR_SEQ_MISORDERED;
00191 
00192           dec_client_id_ref(pfound);
00193 
00194           LogDebug(component, "CREATE_SESSION returning NFS4ERR_SEQ_MISORDERED");
00195 
00196           goto out;
00197         }
00198 
00199     }
00200 
00201   if(punconf != NULL)
00202     {
00203       /* First must match principal */
00204       if(!nfs_compare_clientcred(&punconf->cid_credential, &data->credential) ||
00205          !cmp_sockaddr(&punconf->cid_client_addr, &client_addr, IGNORE_PORT))
00206         {
00207           if(isDebug(component))
00208             {
00209               char unconfirmed_addr[SOCK_NAME_MAX];
00210 
00211               sprint_sockip(&punconf->cid_client_addr, unconfirmed_addr, sizeof(unconfirmed_addr));
00212 
00213               LogDebug(component,
00214                        "Unconfirmed ClientId %"PRIx64"->'%s': Principals do not match... unconfirmed addr=%s Return NFS4ERR_CLID_INUSE",
00215                        clientid, str_client_addr, unconfirmed_addr);
00216             }
00217 
00218           dec_client_id_ref(punconf);
00219 
00220           res_CREATE_SESSION4.csr_status = NFS4ERR_CLID_INUSE;
00221 
00222           goto out;
00223         }
00224     }
00225 
00226   if(pconf != NULL)
00227     {
00228       if(isDebug(component) && pconf != NULL)
00229         display_clientid_name(pconf, str_client);
00230 
00231       /* First must match principal */
00232       if(!nfs_compare_clientcred(&pconf->cid_credential, &data->credential) ||
00233          !cmp_sockaddr(&pconf->cid_client_addr, &client_addr, IGNORE_PORT))
00234         {
00235           if(isDebug(component))
00236             {
00237               char confirmed_addr[SOCK_NAME_MAX];
00238 
00239               sprint_sockip(&pconf->cid_client_addr, confirmed_addr, sizeof(confirmed_addr));
00240 
00241               LogDebug(component,
00242                        "Confirmed ClientId %"PRIx64"->%s addr=%s: Principals do not match... confirmed addr=%s Return NFS4ERR_CLID_INUSE",
00243                        clientid, str_client, str_client_addr, confirmed_addr);
00244             }
00245 
00246           /* Release our reference to the confirmed clientid. */
00247           dec_client_id_ref(pconf);
00248 
00249           res_CREATE_SESSION4.csr_status = NFS4ERR_CLID_INUSE;
00250 
00251           goto out;
00252         }
00253 
00254       /* In this case, the record was confirmed proceed with CREATE_SESSION */
00255     }
00256 
00257   /* We don't need to do any further principal checks, we can't have a confirmed
00258    * clientid record with a different principal than the unconfirmed record.
00259    */
00260 
00261   /* At this point, we need to try and create the session before we modify the
00262    * confirmed and/or unconfirmed clientid records.
00263    */
00264 
00267   /* Check flags value (test CSESS15) */
00268   if(arg_CREATE_SESSION4.csa_flags > CREATE_SESSION4_FLAG_CONN_RDMA)
00269     {
00270       LogDebug(component,
00271                "Invalid create session flags %"PRIu32,
00272                arg_CREATE_SESSION4.csa_flags);
00273 
00274       dec_client_id_ref(pfound);
00275 
00276       res_CREATE_SESSION4.csr_status = NFS4ERR_INVAL;
00277 
00278       goto out;
00279     }
00280 
00281   /* Record session related information at the right place */
00282   nfs41_session = pool_alloc(nfs41_session_pool, NULL);
00283 
00284   if(nfs41_session == NULL)
00285     {
00286       LogDebug(component,
00287                "Could not allocate memory for a session");
00288 
00289       dec_client_id_ref(pfound);
00290 
00291       res_CREATE_SESSION4.csr_status = NFS4ERR_SERVERFAULT;
00292 
00293       goto out;
00294     }
00295 
00296   nfs41_session->clientid           = clientid;
00297   nfs41_session->pclientid_record   = pfound;
00298   nfs41_session->sequence           = arg_CREATE_SESSION4.csa_sequence;
00299   nfs41_session->session_flags      = CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
00300   nfs41_session->fore_channel_attrs = arg_CREATE_SESSION4.csa_fore_chan_attrs;
00301   nfs41_session->back_channel_attrs = arg_CREATE_SESSION4.csa_back_chan_attrs;
00302 
00303   /* Take reference to clientid record */
00304   inc_client_id_ref(pfound);
00305 
00306   /* Set ca_maxrequests */
00307   nfs41_session->fore_channel_attrs.ca_maxrequests = NFS41_NB_SLOTS;
00308   nfs41_session->fore_channel_attrs.ca_maxrequests = NFS41_NB_SLOTS;
00309 
00310   nfs41_Build_sessionid(&clientid, nfs41_session->session_id);
00311 
00312   res_CREATE_SESSION4ok.csr_sequence = nfs41_session->sequence;
00313   res_CREATE_SESSION4ok.csr_flags    = CREATE_SESSION4_FLAG_CONN_BACK_CHAN;
00314 
00315   /* return the input for wanting of something better (will change in
00316      later versions) */
00317   res_CREATE_SESSION4ok.csr_fore_chan_attrs
00318        = nfs41_session->fore_channel_attrs;
00319   res_CREATE_SESSION4ok.csr_back_chan_attrs
00320        = nfs41_session->back_channel_attrs;
00321 
00322   memcpy(res_CREATE_SESSION4ok.csr_sessionid,
00323          nfs41_session->session_id,
00324          NFS4_SESSIONID_SIZE);
00325 
00326   /* Create Session replay cache */
00327   data->pcached_res = &pfound->cid_create_session_slot.cached_result;
00328   pfound->cid_create_session_slot.cache_used = TRUE;
00329 
00330   LogDebug(component, "CREATE_SESSION replay=%p", data->pcached_res);
00331 
00332   if(!nfs41_Session_Set(nfs41_session->session_id, nfs41_session))
00333     {
00334       LogDebug(component,
00335                "Could not insert session into table");
00336 
00337       /* Decrement our reference to the clientid record and the one for the session */
00338       dec_client_id_ref(pfound);
00339       dec_client_id_ref(pfound);
00340 
00341       /* Free the memory for the session */
00342       pool_free(nfs41_session_pool, nfs41_session);
00343 
00344       res_CREATE_SESSION4.csr_status = NFS4ERR_SERVERFAULT;     /* Maybe a more precise status would be better */
00345 
00346       goto out;
00347     }
00348 
00349   /* Make sure we have a reference to the confirmed clientid record if any */
00350   if(pconf == NULL)
00351     {
00352       pconf = pclient_record->cr_pconfirmed_id;
00353 
00354       if(isDebug(component) && pconf != NULL)
00355         display_clientid_name(pconf, str_client);
00356 
00357       /* Need a reference to the confirmed record for below */
00358       if(pconf != NULL)
00359         inc_client_id_ref(pconf);
00360     }
00361 
00362   if(pconf != NULL && pconf->cid_clientid != clientid)
00363     {
00364       /* Old confirmed record - need to expire it */
00365       if(isDebug(component))
00366         {
00367           char str[HASHTABLE_DISPLAY_STRLEN];
00368 
00369           display_client_id_rec(pconf, str);
00370           LogDebug(component,
00371                    "Expiring %s",
00372                    str);
00373         }
00374 
00375       /* Expire clientid and release our reference. */
00376       nfs_client_id_expire(pconf);
00377 
00378       dec_client_id_ref(pconf);
00379 
00380       pconf = NULL;
00381     }
00382 
00383   if(pconf != NULL)
00384     {
00385       /* At this point we are updating the confirmed clientid.
00386        * Update the confirmed record from the unconfirmed record.
00387        */
00388       LogDebug(component,
00389                "Updating clientid %"PRIx64"->%s cb_program=%u",
00390                pconf->cid_clientid,
00391                str_client,
00392                arg_CREATE_SESSION4.csa_cb_program);
00393 
00394       pconf->cid_cb.cid_program = arg_CREATE_SESSION4.csa_cb_program;
00395 
00396       if(punconf != NULL)
00397         {
00398 
00399           /* unhash the unconfirmed clientid record */
00400           remove_unconfirmed_client_id(punconf);
00401 
00402           /* Release our reference to the unconfirmed entry */
00403           dec_client_id_ref(punconf);
00404         }
00405 
00406       if(isDebug(component))
00407         {
00408           char str[HASHTABLE_DISPLAY_STRLEN];
00409 
00410           display_client_id_rec(pconf, str);
00411           LogDebug(component,
00412                    "Updated %s",
00413                    str);
00414         }
00415 
00416       /* Release our reference to the confirmed clientid. */
00417       dec_client_id_ref(pconf);
00418     }
00419   else
00420     {
00421       /* This is a new clientid */
00422       if(isFullDebug(component))
00423         {
00424           char str[HASHTABLE_DISPLAY_STRLEN];
00425 
00426           display_client_id_rec(punconf, str);
00427 
00428           LogFullDebug(component,
00429                        "Confirming new %s",
00430                        str);
00431         }
00432 
00433       punconf->cid_cb.cid_program = arg_CREATE_SESSION4.csa_cb_program;
00434 
00435       rc = nfs_client_id_confirm(punconf, component);
00436 
00437       if(rc != CLIENT_ID_SUCCESS)
00438         {
00439           if(rc == CLIENT_ID_INVALID_ARGUMENT)
00440             res_CREATE_SESSION4.csr_status = NFS4ERR_SERVERFAULT;
00441           else
00442             res_CREATE_SESSION4.csr_status = NFS4ERR_RESOURCE;
00443 
00444           /* Need to destroy the session */
00445           if(!nfs41_Session_Del(nfs41_session->session_id))
00446             LogDebug(component,
00447                      "Oops nfs41_Session_Del failed");
00448 
00449           /* Release our reference to the unconfirmed record */
00450           dec_client_id_ref(punconf);
00451 
00452           goto out;
00453         }
00454 
00455       pconf   = punconf;
00456       punconf = NULL;
00457 
00458       if(isDebug(component))
00459         {
00460           char str[HASHTABLE_DISPLAY_STRLEN];
00461 
00462           display_client_id_rec(pconf, str);
00463 
00464           LogDebug(component,
00465                    "Confirmed %s",
00466                    str);
00467         }
00468     }
00469 
00470   pconf->cid_create_session_sequence++;
00471 
00472   /* Release our reference to the confirmed record */
00473   dec_client_id_ref(pconf);
00474 
00475   if(isFullDebug(component))
00476     {
00477       char str[HASHTABLE_DISPLAY_STRLEN];
00478 
00479       display_client_record(pclient_record, str);
00480 
00481       LogFullDebug(component,
00482                    "Client Record %s cr_pconfirmed_id=%p cr_punconfirmed_id=%p",
00483                    str,
00484                    pclient_record->cr_pconfirmed_id,
00485                    pclient_record->cr_punconfirmed_id);
00486     }
00487 
00488   LogDebug(component,
00489            "CREATE_SESSION success");
00490 
00491   /* Successful exit */
00492   res_CREATE_SESSION4.csr_status = NFS4_OK;
00493 
00494  out:
00495 
00496   V(pclient_record->cr_mutex);
00497 
00498   /* Release our reference to the client record and return */
00499   dec_client_record_ref(pclient_record);
00500 
00501   return res_CREATE_SESSION4.csr_status;
00502 }                               /* nfs41_op_create_session */
00503 
00514 void nfs41_op_create_session_Free(CREATE_SESSION4res * resp)
00515 {
00516   /* To be completed */
00517   return;
00518 }                               /* nfs41_op_create_session_Free */