nfs-ganesha 1.4
|
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 <stdio.h> 00045 #include <string.h> 00046 #include <pthread.h> 00047 #include <fcntl.h> 00048 #include <sys/file.h> /* for having FNDELAY */ 00049 #include "HashData.h" 00050 #include "HashTable.h" 00051 #include "log.h" 00052 #include "nfs23.h" 00053 #include "nfs4.h" 00054 #include "nfs_core.h" 00055 #include "cache_inode.h" 00056 #include "nfs_exports.h" 00057 #include "nfs_creds.h" 00058 #include "nfs_tools.h" 00059 #include "mount.h" 00060 #include "nfs_proto_functions.h" 00061 #include "nfs_proto_tools.h" 00062 00077 int mnt_Mnt(nfs_arg_t *parg, 00078 exportlist_t *pexport, 00079 fsal_op_context_t *pcontext, 00080 nfs_worker_data_t *pworker, 00081 struct svc_req *preq, 00082 nfs_res_t *pres) 00083 { 00084 00085 char exportPath[MNTPATHLEN + 1]; 00086 exportlist_t *p_current_item; 00087 00088 fsal_handle_t pfsal_handle; 00089 00090 int auth_flavor[NB_AUTH_FLAVOR]; 00091 int index_auth = 0; 00092 int i = 0; 00093 00094 char exported_path[MAXPATHLEN]; 00095 char tmplist_path[MAXPATHLEN]; 00096 char tmpexport_path[MAXPATHLEN]; 00097 char *hostname; 00098 fsal_path_t fsal_path; 00099 unsigned int bytag = FALSE; 00100 00101 LogDebug(COMPONENT_NFSPROTO, "REQUEST PROCESSING: Calling mnt_Mnt path=%s", 00102 parg->arg_mnt); 00103 00104 /* Paranoid command to clean the result struct. */ 00105 memset(pres, 0, sizeof(nfs_res_t)); 00106 00107 if(parg->arg_mnt == NULL) 00108 { 00109 LogCrit(COMPONENT_NFSPROTO, 00110 "MOUNT: NULL path passed as Mount argument !!!"); 00111 return NFS_REQ_DROP; 00112 } 00113 00114 /* Retrieving arguments */ 00115 strncpy(exportPath, parg->arg_mnt, MNTPATHLEN + 1); 00116 00117 /* 00118 * Find the export for the dirname (using as well Path or Tag ) 00119 */ 00120 for(p_current_item = pexport; p_current_item != NULL; 00121 p_current_item = p_current_item->next) 00122 { 00123 if(exportPath[0] != '/') 00124 { 00125 /* The input value may be a "Tag" */ 00126 if(!strcmp(exportPath, p_current_item->FS_tag)) 00127 { 00128 strncpy(exported_path, p_current_item->fullpath, MAXPATHLEN); 00129 bytag = TRUE; 00130 break; 00131 } 00132 } 00133 else 00134 { 00135 /* Make sure the path in export entry ends with a '/', if not adds one */ 00136 if(p_current_item->fullpath[strlen(p_current_item->fullpath) - 1] == '/') 00137 strncpy(tmplist_path, p_current_item->fullpath, MAXPATHLEN); 00138 else 00139 snprintf(tmplist_path, MAXPATHLEN, "%s/", p_current_item->fullpath); 00140 00141 /* Make sure that the argument from MNT ends with a '/', if not adds one */ 00142 if(exportPath[strlen(exportPath) - 1] == '/') 00143 strncpy(tmpexport_path, exportPath, MAXPATHLEN); 00144 else 00145 snprintf(tmpexport_path, MAXPATHLEN, "%s/", exportPath); 00146 00147 /* Is tmplist_path a subdirectory of tmpexport_path ? */ 00148 if(!strncmp(tmplist_path, tmpexport_path, strlen(tmplist_path))) 00149 { 00150 strncpy(exported_path, p_current_item->fullpath, MAXPATHLEN); 00151 break; 00152 } 00153 } 00154 } 00155 00156 /* if p_current_item is not null, 00157 * it points to the asked export entry. 00158 */ 00159 00160 if(!p_current_item) 00161 { 00162 LogCrit(COMPONENT_NFSPROTO, "MOUNT: Export entry %s not found", 00163 exportPath); 00164 00165 /* entry not found. */ 00166 /* @todo : not MNT3ERR_NOENT => ok */ 00167 switch (preq->rq_vers) 00168 { 00169 case MOUNT_V1: 00170 pres->res_mnt1.status = NFSERR_ACCES; 00171 break; 00172 00173 case MOUNT_V3: 00174 pres->res_mnt3.fhs_status = MNT3ERR_ACCES; 00175 break; 00176 } 00177 return NFS_REQ_OK; 00178 } 00179 00180 LogDebug(COMPONENT_NFSPROTO, 00181 "MOUNT: Export entry Path=%s Tag=%s matches %s, export_id=%u", 00182 exported_path, p_current_item->FS_tag, exportPath, 00183 p_current_item->id); 00184 00185 /* @todo : check wether mount is allowed. 00186 * to do so, retrieve client identifier from the credential. 00187 */ 00188 00189 switch (preq->rq_vers) 00190 { 00191 case MOUNT_V1: 00192 if((p_current_item->options & EXPORT_OPTION_NFSV2) != 0) 00193 break; 00194 pres->res_mnt1.status = NFSERR_ACCES; 00195 return NFS_REQ_OK; 00196 00197 case MOUNT_V3: 00198 if((p_current_item->options & EXPORT_OPTION_NFSV3) != 0) 00199 break; 00200 pres->res_mnt3.fhs_status = MNT3ERR_ACCES; 00201 return NFS_REQ_OK; 00202 } 00203 00204 00205 /* 00206 * retrieve the associated NFS handle 00207 */ 00208 00209 pfsal_handle = *p_current_item->proot_handle; 00210 if(!(bytag == TRUE || !strncmp(tmpexport_path, tmplist_path, MAXPATHLEN))) 00211 { 00212 if(FSAL_IS_ERROR(FSAL_str2path(tmpexport_path, MAXPATHLEN, &fsal_path))) 00213 { 00214 switch (preq->rq_vers) 00215 { 00216 case MOUNT_V1: 00217 pres->res_mnt1.status = NFSERR_IO; 00218 break; 00219 00220 case MOUNT_V3: 00221 pres->res_mnt3.fhs_status = MNT3ERR_IO; 00222 break; 00223 } 00224 return NFS_REQ_OK; 00225 } 00226 00227 LogEvent(COMPONENT_NFSPROTO, 00228 "MOUNT: Performance warning: Export entry is not cached"); 00229 if(FSAL_IS_ERROR(FSAL_lookupPath(&fsal_path, pcontext, &pfsal_handle, NULL))) 00230 { 00231 switch (preq->rq_vers) 00232 { 00233 case MOUNT_V1: 00234 pres->res_mnt1.status = NFSERR_ACCES; 00235 break; 00236 00237 case MOUNT_V3: 00238 pres->res_mnt3.fhs_status = MNT3ERR_ACCES; 00239 break; 00240 } 00241 return NFS_REQ_OK; 00242 } 00243 00244 } 00245 /* convert the fsal_handle to a file handle */ 00246 switch (preq->rq_vers) 00247 { 00248 case MOUNT_V1: 00249 if(!nfs2_FSALToFhandle(&(pres->res_mnt1.fhstatus2_u.directory), 00250 &pfsal_handle, p_current_item)) 00251 { 00252 pres->res_mnt1.status = NFSERR_IO; 00253 } 00254 else 00255 { 00256 pres->res_mnt1.status = NFS_OK; 00257 } 00258 break; 00259 00260 case MOUNT_V3: 00261 /* FIXME: The mountinfo.fhandle definition is an overlay on/of nfs_fh3. 00262 * redefine and eliminate one or the other. 00263 */ 00264 pres->res_mnt3.fhs_status = 00265 nfs3_AllocateFH((nfs_fh3 *) &pres->res_mnt3.mountres3_u.mountinfo.fhandle); 00266 if(pres->res_mnt3.fhs_status == MNT3_OK) 00267 { 00268 if(!nfs3_FSALToFhandle 00269 ((nfs_fh3 *) & (pres->res_mnt3.mountres3_u.mountinfo.fhandle), &pfsal_handle, 00270 p_current_item)) 00271 { 00272 pres->res_mnt3.fhs_status = MNT3ERR_INVAL; 00273 } 00274 else 00275 { 00276 pres->res_mnt3.fhs_status = MNT3_OK; 00277 00278 /* Auth et nfs_SetPostOpAttr ici */ 00279 } 00280 } 00281 00282 break; 00283 } 00284 00285 /* Return the supported authentication flavor in V3 */ 00286 if(preq->rq_vers == MOUNT_V3) 00287 { 00288 if(p_current_item->options & EXPORT_OPTION_AUTH_NONE) 00289 auth_flavor[index_auth++] = AUTH_NONE; 00290 if(p_current_item->options & EXPORT_OPTION_AUTH_UNIX) 00291 auth_flavor[index_auth++] = AUTH_UNIX; 00292 #ifdef _HAVE_GSSAPI 00293 if(nfs_param.krb5_param.active_krb5 == TRUE) 00294 { 00295 if(p_current_item->options & EXPORT_OPTION_RPCSEC_GSS_NONE) 00296 auth_flavor[index_auth++] = MNT_RPC_GSS_NONE; 00297 if(p_current_item->options & EXPORT_OPTION_RPCSEC_GSS_INTG) 00298 auth_flavor[index_auth++] = MNT_RPC_GSS_INTEGRITY; 00299 if(p_current_item->options & EXPORT_OPTION_RPCSEC_GSS_PRIV) 00300 auth_flavor[index_auth++] = MNT_RPC_GSS_PRIVACY; 00301 } 00302 #endif 00303 00304 LogDebug(COMPONENT_NFSPROTO, 00305 "MOUNT: Entry support %d different flavours", index_auth); 00306 00307 #define RES_MOUNTINFO pres->res_mnt3.mountres3_u.mountinfo 00308 if((RES_MOUNTINFO.auth_flavors.auth_flavors_val = 00309 gsh_calloc(index_auth, sizeof(int))) == NULL) 00310 return NFS_REQ_DROP; 00311 00312 RES_MOUNTINFO.auth_flavors.auth_flavors_len = index_auth; 00313 for(i = 0; i < index_auth; i++) 00314 RES_MOUNTINFO.auth_flavors.auth_flavors_val[i] = auth_flavor[i]; 00315 } 00316 00317 /* Add the client to the mount list */ 00318 /* @todo: BUGAZOMEU; seul AUTHUNIX est supporte */ 00319 hostname = ((struct authunix_parms *)(preq->rq_clntcred))->aup_machname; 00320 00321 if(!nfs_Add_MountList_Entry(hostname, exportPath)) 00322 { 00323 LogCrit(COMPONENT_NFSPROTO, 00324 "MOUNT: Error when adding entry (%s,%s) to the mount list, Mount command will be successfull anyway", 00325 hostname, exportPath); 00326 } 00327 else 00328 LogFullDebug(COMPONENT_NFSPROTO, 00329 "MOUNT: mount list entry (%s,%s) added", hostname, exportPath); 00330 00331 return NFS_REQ_OK; 00332 00333 } /* mnt_Mnt */ 00334 00344 void mnt1_Mnt_Free(nfs_res_t * pres) 00345 { 00346 return; 00347 } /* mnt_Mnt_Free */ 00348 00349 void mnt3_Mnt_Free(nfs_res_t * pres) 00350 { 00351 if(pres->res_mnt3.fhs_status == MNT3_OK) 00352 { 00353 gsh_free(pres->res_mnt3.mountres3_u.mountinfo. 00354 auth_flavors.auth_flavors_val); 00355 gsh_free(pres->res_mnt3.mountres3_u.mountinfo.fhandle.fhandle3_val); 00356 } 00357 return; 00358 } /* mnt_Mnt_Free */