nfs-ganesha 1.4

exports.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 License
00011  * as published by the Free Software Foundation; either version 3 of
00012  * the License, or (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful, but
00015  * 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
00022  * 02110-1301 USA
00023  *
00024  * ---------------------------------------
00025  */
00026 
00034 #ifdef HAVE_CONFIG_H
00035 #include "config.h"
00036 #endif
00037 
00038 #ifdef _SOLARIS
00039 #include "solaris_port.h"
00040 #define USHRT_MAX       6553
00041 #endif
00042 
00043 #include "cidr.h"
00044 #include "ganesha_rpc.h"
00045 #include "log.h"
00046 #include "fsal.h"
00047 #include "nfs23.h"
00048 #include "nfs4.h"
00049 #include "mount.h"
00050 #include "nfs_core.h"
00051 #include "cache_inode.h"
00052 #include "nfs_file_handle.h"
00053 #include "nfs_exports.h"
00054 #include "nfs_tools.h"
00055 #include "nfs_proto_functions.h"
00056 #include "nfs_dupreq.h"
00057 #include "config_parsing.h"
00058 #include "common_utils.h"
00059 #include "nodelist.h"
00060 #include <stdlib.h>
00061 #include <fnmatch.h>
00062 #include <sys/socket.h>
00063 #include <netinet/in.h>
00064 #include <arpa/inet.h>
00065 #include <string.h>
00066 #include <ctype.h>
00067 
00068 #define LASTDEFAULT 1048576
00069 
00070 #define STRCMP strcasecmp
00071 
00072 #define CONF_LABEL_EXPORT "EXPORT"
00073 
00074 /* Labels in the export file */
00075 #define CONF_EXPORT_ID                 "Export_id"
00076 #define CONF_EXPORT_PATH               "Path"
00077 #define CONF_EXPORT_ROOT               "Root_Access"
00078 #define CONF_EXPORT_ACCESS             "Access"
00079 #define CONF_EXPORT_READ_ACCESS        "R_Access"
00080 #define CONF_EXPORT_READWRITE_ACCESS   "RW_Access"
00081 #define CONF_EXPORT_MD_ACCESS          "MDONLY_Access"
00082 #define CONF_EXPORT_MD_RO_ACCESS       "MDONLY_RO_Access"
00083 #define CONF_EXPORT_PSEUDO             "Pseudo"
00084 #define CONF_EXPORT_ACCESSTYPE         "Access_Type"
00085 #define CONF_EXPORT_ANON_USER          "Anonymous_uid"
00086 #define CONF_EXPORT_ANON_ROOT          "Anonymous_root_uid"
00087 #define CONF_EXPORT_ALL_ANON           "Make_All_Users_Anonymous"
00088 #define CONF_EXPORT_ANON_GROUP         "Anonymous_gid"
00089 #define CONF_EXPORT_NFS_PROTO          "NFS_Protocols"
00090 #define CONF_EXPORT_TRANS_PROTO        "Transport_Protocols"
00091 #define CONF_EXPORT_SECTYPE            "SecType"
00092 #define CONF_EXPORT_MAX_READ           "MaxRead"
00093 #define CONF_EXPORT_MAX_WRITE          "MaxWrite"
00094 #define CONF_EXPORT_PREF_READ          "PrefRead"
00095 #define CONF_EXPORT_PREF_WRITE         "PrefWrite"
00096 #define CONF_EXPORT_PREF_READDIR       "PrefReaddir"
00097 #define CONF_EXPORT_FSID               "Filesystem_id"
00098 #define CONF_EXPORT_NOSUID             "NOSUID"
00099 #define CONF_EXPORT_NOSGID             "NOSGID"
00100 #define CONF_EXPORT_PRIVILEGED_PORT    "PrivilegedPort"
00101 #define CONF_EXPORT_USE_DATACACHE      "Cache_Data"
00102 #define CONF_EXPORT_FS_SPECIFIC        "FS_Specific"
00103 #define CONF_EXPORT_FS_TAG             "Tag"
00104 #define CONF_EXPORT_MAX_OFF_WRITE      "MaxOffsetWrite"
00105 #define CONF_EXPORT_MAX_OFF_READ       "MaxOffsetRead"
00106 #define CONF_EXPORT_MAX_CACHE_SIZE     "MaxCacheSize"
00107 #define CONF_EXPORT_REFERRAL           "Referral"
00108 #define CONF_EXPORT_PNFS               "Use_pNFS"
00109 #define CONF_EXPORT_UQUOTA             "User_Quota"
00110 #define CONF_EXPORT_USE_COMMIT                  "Use_NFS_Commit"
00111 #define CONF_EXPORT_USE_GANESHA_WRITE_BUFFER    "Use_Ganesha_Write_Buffer"
00112 #define CONF_EXPORT_USE_FSAL_UP        "Use_FSAL_UP"
00113 #define CONF_EXPORT_FSAL_UP_FILTERS    "FSAL_UP_Filters"
00114 #define CONF_EXPORT_FSAL_UP_TIMEOUT    "FSAL_UP_Timeout"
00115 #define CONF_EXPORT_FSAL_UP_TYPE       "FSAL_UP_Type"
00116 #define CONF_EXPORT_USE_COOKIE_VERIFIER "UseCookieVerifier"
00117 
00120 /* Internal identifiers */
00121 #define FLAG_EXPORT_ID            0x000000001
00122 #define FLAG_EXPORT_PATH          0x000000002
00123 
00124 #define FLAG_EXPORT_ROOT_OR_ACCESS 0x000000004
00125 
00126 #define FLAG_EXPORT_PSEUDO          0x000000010
00127 #define FLAG_EXPORT_ACCESSTYPE      0x000000020
00128 #define FLAG_EXPORT_ANON_ROOT       0x000000040
00129 #define FLAG_EXPORT_NFS_PROTO       0x000000080
00130 #define FLAG_EXPORT_TRANS_PROTO     0x000000100
00131 #define FLAG_EXPORT_SECTYPE         0x000000200
00132 #define FLAG_EXPORT_MAX_READ        0x000000400
00133 #define FLAG_EXPORT_MAX_WRITE       0x000000800
00134 #define FLAG_EXPORT_PREF_READ       0x000001000
00135 #define FLAG_EXPORT_PREF_WRITE      0x000002000
00136 #define FLAG_EXPORT_PREF_READDIR    0x000004000
00137 #define FLAG_EXPORT_FSID            0x000008000
00138 #define FLAG_EXPORT_NOSUID          0x000010000
00139 #define FLAG_EXPORT_NOSGID          0x000020000
00140 #define FLAG_EXPORT_PRIVILEGED_PORT 0x000040000
00141 #define FLAG_EXPORT_USE_DATACACHE   0x000080000
00142 #define FLAG_EXPORT_FS_SPECIFIC     0x000100000
00143 #define FLAG_EXPORT_FS_TAG          0x000200000
00144 #define FLAG_EXPORT_MAX_OFF_WRITE   0x000400000
00145 #define FLAG_EXPORT_MAX_OFF_READ    0x000800000
00146 #define FLAG_EXPORT_MAX_CACHE_SIZE  0x001000000
00147 #define FLAG_EXPORT_USE_PNFS        0x002000000
00148 #define FLAG_EXPORT_ACCESS_LIST     0x004000000
00149 #define FLAG_EXPORT_ACCESSTYPE_LIST 0x008000000
00150 #define FLAG_EXPORT_ANON_GROUP      0x010000000
00151 #define FLAG_EXPORT_ALL_ANON        0x020000000
00152 #define FLAG_EXPORT_ANON_USER       0x040000000
00153 #define FLAG_EXPORT_CACHE_POLICY    0x080000000
00154 #define FLAG_EXPORT_USE_UQUOTA      0x100000000
00155 
00156 /* limites for nfs_ParseConfLine */
00157 /* Used in BuildExportEntry() */
00158 #define EXPORT_MAX_CLIENTS   EXPORTS_NB_MAX_CLIENTS     /* number of clients */
00159 #define EXPORT_MAX_CLIENTLEN 256        /* client name len */
00160 
00175 int nfs_ParseConfLine(char *Argv[],
00176                       int nbArgv,
00177                       char *line,
00178                       int (*separator_function) (char), int (*endLine_func) (char))
00179 {
00180   int output_value = 0;
00181   int endLine = FALSE;
00182 
00183   char *p1 = line;              /* Pointeur sur le debut du token */
00184   char *p2 = NULL;              /* Pointeur sur la fin du token   */
00185 
00186   /* iteration and checking for array bounds */
00187   for(; output_value < nbArgv;)
00188     {
00189 
00190       if(*p1 == '\0')
00191         return output_value;
00192 
00193       /* Je recherche le premier caractere valide */
00194       for(; *p1 == ' ' || *p1 == '\t'; p1++) ;
00195 
00196       /* p1 pointe sur un debut de token, je cherche la fin */
00197       /* La fin est un blanc, une fin de chaine ou un CR    */
00198       for(p2 = p1; !separator_function(*p2) && !endLine_func(*p2); p2++) ;
00199 
00200       /* Possible arret a cet endroit */
00201       if(endLine_func(*p2))
00202         endLine = TRUE;
00203 
00204       /* je valide la lecture du token */
00205       *p2 = '\0';
00206       strcpy(Argv[output_value++], p1);
00207 
00208       /* Je me prepare pour la suite */
00209       if(!endLine)
00210         {
00211           p2 += 1;
00212           p1 = p2;
00213         }
00214       else
00215         return output_value;
00216 
00217     }                           /* for( ; ; ) */
00218 
00219   /* out of bounds */
00220   if(output_value >= nbArgv)
00221     return -1;
00222 
00223   return -2;
00224 
00225 }                               /* nfs_ParseConfLine */
00226 
00248 #if 0
00249 static struct hostent *nfs_LookupHostAddr(char *host)
00250 {
00251   struct hostent *output;
00252   unsigned long hostaddr;
00253   int length = sizeof(hostaddr);
00254 
00255 #ifdef _USE_TIRPC_IPV6
00256   struct sockaddr_storage addrv6;
00257   struct sockaddr_in6 *paddrv6 = (struct sockaddr_in6 *)&addrv6;
00258 #endif
00259 
00260   hostaddr = inet_addr(host);
00261   /* is it a dotted IP? */
00262   if (hostaddr == INADDR_NONE)
00263   {
00264      /* Nope. Try to resolve name */
00265      output = gethostbyname(host);
00266   }
00267   else
00268   {
00269       /* yes, this is an IP, try to get hostent */
00270       output = gethostbyaddr((char *)&hostaddr, length, AF_INET);
00271   }
00272 
00273 #ifdef _USE_TIRPC_IPV6
00274   /* if output == NULL it may be an IPv6 address */
00275   if(output == NULL)
00276     {
00277       if((output = gethostbyname2(host, AF_INET6)) == NULL)
00278         {
00279           /* Maybe an address in the ASCII format */
00280           if(inet_pton(AF_INET6, host, paddrv6->sin6_addr.s6_addr))
00281             {
00282               output = gethostbyaddr(paddrv6->sin6_addr.s6_addr,
00283                                      sizeof(paddrv6->sin6_addr.s6_addr), AF_INET6);
00284             }
00285         }
00286     }
00287 #endif
00288 
00289   return output;
00290 }                               /* nfs_LookupHostAddr */
00291 #endif
00292 
00317 inline static int string_contains_slash( char* host )
00318 {
00319   char * c ;
00320 
00321   for( c = host ; *c != '\0' ; c++ ) 
00322     if( *c == '/' ) 
00323       return 1 ;
00324 
00325   return 0 ;
00326 }
00327 
00328 int nfs_LookupNetworkAddr(char *host,   /* [IN] host/address specifier */
00329                           unsigned long *netAddr,       /* [OUT] return address       */
00330                           unsigned long *netMask)       /* [OUT] return address mask  */
00331 {
00332   CIDR * pcidr = NULL ;
00333 
00334   if( ( pcidr = cidr_from_str( host ) ) == NULL )
00335     return 1 ;
00336 
00337   memcpy( netAddr, pcidr->addr, sizeof( unsigned long ) ) ;
00338   memcpy( netMask, pcidr->mask, sizeof( unsigned long ) ) ; 
00339   
00340   /* BE CAREFUL !! The following lines are specific to IPv4. The libcidr support IPv6 as well */
00341   memset( netAddr, 0, sizeof( unsigned long ) ) ;
00342   memcpy( netAddr, &pcidr->addr[12], 4 ) ;
00343   *netAddr = ntohl( *netAddr ) ;
00344 
00345   memset( netMask, 0, sizeof( unsigned long ) ) ;
00346   memcpy( netMask, &pcidr->mask[12], 4 ) ;
00347   *netMask = ntohl( *netMask ) ;
00348 
00349   return 0 ; 
00350 } /* nfs_LookupNetworkAddr */
00351 
00352 int nfs_AddClientsToClientArray(exportlist_client_t *clients,
00353                                 int new_clients_number,
00354                                 char **new_clients_name, int option)
00355 {
00356   int i = 0;
00357   int j = 0;
00358   unsigned int l = 0;
00359   char *client_hostname;
00360   struct addrinfo *info;
00361   exportlist_client_entry_t *p_clients;
00362   int is_wildcarded_host = FALSE;
00363   unsigned long netMask;
00364   unsigned long netAddr;
00365 
00366   /* How many clients are there already? */
00367   j = (*clients).num_clients;
00368 
00369   p_clients = (*clients).clientarray;
00370 
00371   if(p_clients == NULL)
00372     return ENOMEM;
00373 
00374   /* It's now time to set the information related to the new clients */
00375   for(i = j; i < j + new_clients_number; i++)
00376     {
00377       /* cleans the export entry */
00378       memset(&p_clients[i], 0, sizeof(exportlist_client_entry_t));
00379 
00380       netMask = 0;              /* default value for a host */
00381       client_hostname = new_clients_name[i - j];
00382 
00383       /* Set client options */
00384       p_clients[i].options |= option;
00385 
00386       /* using netdb to get information about the hostname */
00387       if(client_hostname[0] == '@')
00388         {
00389 
00390           /* Entry is a netgroup definition */
00391           strncpy(p_clients[i].client.netgroup.netgroupname,
00392                   (char *)(client_hostname + 1), MAXHOSTNAMELEN);
00393 
00394           p_clients[i].options |= EXPORT_OPTION_NETGRP;
00395           p_clients[i].type = NETGROUP_CLIENT;
00396 
00397           LogDebug(COMPONENT_CONFIG,
00398                    "----------------- %s to netgroup %s",
00399                    (option == EXPORT_OPTION_ROOT ? "Root-access" : "Access"),
00400                    p_clients[i].client.netgroup.netgroupname);
00401         }
00402       else if( string_contains_slash( client_hostname ) &&
00403                ( nfs_LookupNetworkAddr( (char *)( client_hostname ),
00404                                          (unsigned long *)&netAddr,
00405                                          (unsigned long *)&netMask) == 0 ) )
00406         {
00407           /* Entry is a network definition */
00408           p_clients[i].client.network.netaddr = netAddr;
00409           p_clients[i].options |= EXPORT_OPTION_NETENT;
00410           p_clients[i].client.network.netmask = netMask;
00411           p_clients[i].type = NETWORK_CLIENT;
00412 
00413           LogDebug(COMPONENT_CONFIG,
00414                    "----------------- %s to network %s = %d.%d.%d.%d netmask=%x",
00415                    (option == EXPORT_OPTION_ROOT ? "Root-access" : "Access"),
00416                    client_hostname,
00417                    (unsigned int)(p_clients[i].client.network.netaddr >> 24),
00418                    (unsigned int)((p_clients[i].client.network.netaddr >> 16) & 0xFF),
00419                    (unsigned int)((p_clients[i].client.network.netaddr >> 8) & 0xFF),
00420                    (unsigned int)(p_clients[i].client.network.netaddr & 0xFF),
00421                    (unsigned int)(p_clients[i].client.network.netmask));
00422         }
00423       else if( getaddrinfo(client_hostname, NULL, NULL, &info) == 0)
00424         {
00425           /* Entry is a hostif */
00426           if(info->ai_family == AF_INET)
00427             {
00428               struct in_addr infoaddr = ((struct sockaddr_in *)info->ai_addr)->sin_addr;
00429               memcpy(&(p_clients[i].client.hostif.clientaddr), &infoaddr,
00430                      sizeof(struct in_addr));
00431               p_clients[i].type = HOSTIF_CLIENT;
00432               LogDebug(COMPONENT_CONFIG,
00433                        "----------------- %s to client %s = %d.%d.%d.%d",
00434                        (option == EXPORT_OPTION_ROOT ? "Root-access" : "Access"),
00435                        client_hostname, 
00436                        (unsigned int)(p_clients[i].client.hostif.clientaddr >> 24),
00437                        (unsigned int)((p_clients[i].client.hostif.clientaddr >> 16) & 0xFF),
00438                        (unsigned int)((p_clients[i].client.hostif.clientaddr >> 8) & 0xFF),
00439                        (unsigned int)(p_clients[i].client.hostif.clientaddr & 0xFF));
00440             }
00441        else /* AF_INET6 */
00442             {
00443               struct in6_addr infoaddr = ((struct sockaddr_in6 *)info->ai_addr)->sin6_addr;
00444               /* IPv6 address */
00445               memcpy(&(p_clients[i].client.hostif.clientaddr6), &infoaddr,
00446                      sizeof(struct in6_addr));
00447               p_clients[i].type = HOSTIF_CLIENT_V6;
00448             }
00449           freeaddrinfo(info);
00450         }
00451      else
00452         {
00453           /* this may be  a wildcarded host */
00454           /* Lookup into the string to see if it contains '*' or '?' */
00455           is_wildcarded_host = FALSE;
00456           for(l = 0; l < strlen(client_hostname); l++)
00457             {
00458               if((client_hostname[l] == '*') || (client_hostname[l] == '?'))
00459                 {
00460                   is_wildcarded_host = TRUE;
00461                   break;
00462                 }
00463             }
00464 
00465           if(is_wildcarded_host == TRUE)
00466             {
00467               p_clients[i].type = WILDCARDHOST_CLIENT;
00468               strncpy(p_clients[i].client.wildcard.wildcard, client_hostname,
00469                       MAXHOSTNAMELEN);
00470 
00471               LogFullDebug(COMPONENT_CONFIG,
00472                            "----------------- %s to wildcard %s",
00473                            (option == EXPORT_OPTION_ROOT ? "Root-access" : "Access"),
00474                            client_hostname);
00475             }
00476           else
00477             {
00478               p_clients[i].type = BAD_CLIENT;
00479               /* Last case: type for client could not be identified. This should not occur */
00480               LogCrit(COMPONENT_CONFIG,
00481                       "Unsupported type for client %s", client_hostname);
00482             }
00483         }
00484     }                           /* for i */
00485 
00486   /* Before we finish, do not forget to set the new number of clients
00487    * and the new pointer to client array.
00488    */
00489   (*clients).num_clients += new_clients_number;
00490 
00491   return 0;                     /* success !! */
00492 }                               /* nfs_AddClientsToClientArray */
00493 
00494 
00504 static int nfs_AddClientsToExportList(exportlist_t * ExportEntry,
00505                                       int new_clients_number,
00506                                       char **new_clients_name, int option)
00507 {
00508   /*
00509    * Notifying the export list structure that another option is to be
00510    * handled
00511    */
00512   ExportEntry->options |= option;
00513   nfs_AddClientsToClientArray( &ExportEntry->clients, new_clients_number,
00514                                new_clients_name, option);
00515   return 0;
00516 }                               /* nfs_AddClientsToExportList */
00517 
00518 #define DEFINED_TWICE_WARNING( _str_ ) \
00519   LogWarn(COMPONENT_CONFIG,            \
00520           "NFS READ_EXPORT: WARNING: %s defined twice !!! (ignored)", _str_ )
00521 
00522 int parseAccessParam(char *var_name, char *var_value,
00523                             exportlist_t *p_entry, int access_option) {
00524   int rc;
00525   char *expended_node_list;
00526 
00527   /* temp array of clients */
00528   char *client_list[EXPORT_MAX_CLIENTS];
00529   int idx;
00530   int count;
00531 
00532   /* expends host[n-m] notations */
00533   count =
00534     nodelist_common_condensed2extended_nodelist(var_value, &expended_node_list);
00535 
00536   if(count <= 0)
00537     {
00538       LogCrit(COMPONENT_CONFIG,
00539               "NFS READ_EXPORT: ERROR: Invalid format for client list in EXPORT::%s definition",
00540               var_name);
00541 
00542       return -1;
00543     }
00544   else if(count > EXPORT_MAX_CLIENTS)
00545     {
00546       LogCrit(COMPONENT_CONFIG,
00547               "NFS READ_EXPORT: ERROR: Client list too long (%d>%d)",
00548               count, EXPORT_MAX_CLIENTS);
00549       return -1;
00550     }
00551 
00552   /* allocate clients strings  */
00553   for(idx = 0; idx < count; idx++)
00554     {
00555       client_list[idx] = gsh_malloc(EXPORT_MAX_CLIENTLEN);
00556       client_list[idx][0] = '\0';
00557     }
00558 
00559   /*
00560    * Search for coma-separated list of hosts, networks and netgroups
00561    */
00562   rc = nfs_ParseConfLine(client_list, count,
00563                          expended_node_list, find_comma, find_endLine);
00564 
00565   /* free the buffer the nodelist module has allocated */
00566   free(expended_node_list);
00567 
00568   if(rc < 0)
00569     {
00570       LogCrit(COMPONENT_CONFIG,
00571               "NFS READ_EXPORT: ERROR: Client list too long (>%d)", count);
00572 
00573       /* free client strings */
00574       for(idx = 0; idx < count; idx++)
00575         gsh_free(client_list[idx]);
00576 
00577       return rc;
00578     }
00579 
00580   rc = nfs_AddClientsToExportList(p_entry,
00581                                   rc, (char **)client_list, access_option);
00582 
00583   if(rc != 0)
00584     {
00585       LogCrit(COMPONENT_CONFIG,
00586               "NFS READ_EXPORT: ERROR: Invalid client found in \"%s\"",
00587               var_value);
00588 
00589       /* free client strings */
00590       for(idx = 0; idx < count; idx++)
00591         gsh_free(client_list[idx]);
00592 
00593       return rc;
00594     }
00595 
00596   /* everything is OK */
00597 
00598   /* free client strings */
00599   for(idx = 0; idx < count; idx++)
00600     gsh_free(client_list[idx]);
00601 
00602   return rc;
00603 }
00604 
00605 bool_t fsal_specific_checks(exportlist_t *p_entry)
00606 {
00607   #ifdef _USE_GPFS
00608   p_entry->use_fsal_up = TRUE;
00609 
00610   if (strncmp(p_entry->fsal_up_type, "DUMB", 4) != 0)
00611     {
00612       LogWarn(COMPONENT_CONFIG,
00613               "NFS READ_EXPORT: ERROR: %s must be \"DUMB\" when using GPFS."
00614               " Setting it to \"DUMB\"", CONF_EXPORT_FSAL_UP_TYPE);
00615       strncpy(p_entry->fsal_up_type,"DUMB", 4);
00616     }
00617   if (p_entry->use_ganesha_write_buffer != FALSE)
00618     {
00619       LogWarn(COMPONENT_CONFIG,
00620               "NFS READ_EXPORT: ERROR: %s must be FALSE when using GPFS. "
00621               "Setting it to FALSE.", CONF_EXPORT_USE_GANESHA_WRITE_BUFFER);
00622       p_entry->use_ganesha_write_buffer = FALSE;
00623     }
00624   #endif
00625 
00626   return TRUE;
00627 }
00628 
00634 static int BuildExportEntry(config_item_t block, exportlist_t ** pp_export)
00635 {
00636   exportlist_t *p_entry;
00637   int i, rc;
00638   char *var_name;
00639   char *var_value;
00640 
00641   /* the mandatory options */
00642 
00643   unsigned int mandatory_options =
00644       (FLAG_EXPORT_ID | FLAG_EXPORT_PATH |
00645        FLAG_EXPORT_ROOT_OR_ACCESS | FLAG_EXPORT_PSEUDO);
00646 
00647   /* the given options */
00648 
00649   unsigned int set_options = 0;
00650 
00651   int err_flag   = FALSE;
00652 
00653   /* allocates export entry */
00654   p_entry = gsh_calloc(1, sizeof(exportlist_t));
00655 
00656   if(p_entry == NULL)
00657     return ENOMEM;
00658 
00659   p_entry->status = EXPORTLIST_OK;
00660   p_entry->access_type = ACCESSTYPE_RW;
00661   p_entry->anonymous_uid = (uid_t) ANON_UID;
00662   p_entry->anonymous_gid = (gid_t) ANON_GID;
00663   p_entry->use_commit = TRUE;
00664   p_entry->use_ganesha_write_buffer = FALSE;
00665   p_entry->UseCookieVerifier = TRUE;
00666 
00667   /* Defaults for FSAL_UP. It is ok to leave the filter list NULL
00668    * even if we enable the FSAL_UP. */
00669   #ifdef _USE_FSAL_UP
00670   p_entry->use_fsal_up = FALSE;
00671   p_entry->fsal_up_filter_list = NULL;
00672   p_entry->fsal_up_timeout.seconds = 30;
00673   p_entry->fsal_up_timeout.nseconds = 0;
00674   strncpy(p_entry->fsal_up_type,"DUMB", 4);
00675   /* We don't create the thread until all exports are parsed. */
00676   memset(&p_entry->fsal_up_thr, 0, sizeof(pthread_t));
00677 #endif /* _USE_FSAL_UP */
00678 
00679   p_entry->worker_stats = gsh_calloc(nfs_param.core_param.nb_worker,
00680                                      sizeof(nfs_worker_stat_t));
00681 
00682   /* by default, we support auth_none and auth_sys */
00683   p_entry->options |= EXPORT_OPTION_AUTH_NONE | EXPORT_OPTION_AUTH_UNIX;
00684 
00685   /* by default, we support all NFS versions supported by the core and
00686      both transport protocols */
00687   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) != 0)
00688     p_entry->options |= EXPORT_OPTION_NFSV2;
00689   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) != 0)
00690     p_entry->options |= EXPORT_OPTION_NFSV3;
00691   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV4) != 0)
00692     p_entry->options |= EXPORT_OPTION_NFSV4;
00693   p_entry->options |= EXPORT_OPTION_UDP | EXPORT_OPTION_TCP;
00694 
00695   p_entry->filesystem_id.major = 666;
00696   p_entry->filesystem_id.minor = 666;
00697 
00698   p_entry->MaxWrite = 16384;
00699   p_entry->MaxRead = 16384;
00700   p_entry->PrefWrite = 16384;
00701   p_entry->PrefRead = 16384;
00702   p_entry->PrefReaddir = 16384;
00703 
00704   init_glist(&p_entry->exp_state_list);
00705 #ifdef _USE_NLM
00706   init_glist(&p_entry->exp_lock_list);
00707 #endif
00708 
00709   if(pthread_mutex_init(&p_entry->exp_state_mutex, NULL) == -1)
00710     {
00711       gsh_free(p_entry);
00712       LogCrit(COMPONENT_CONFIG,
00713               "NFS READ_EXPORT: ERROR: could not initialize exp_state_mutex");
00714       /* free the entry before exiting */
00715       return -1;
00716     }
00717 
00718   strcpy(p_entry->FS_specific, "");
00719   strcpy(p_entry->FS_tag, "");
00720   strcpy(p_entry->fullpath, "/");
00721   strcpy(p_entry->dirname, "/");
00722   strcpy(p_entry->fsname, "");
00723   strcpy(p_entry->pseudopath, "/");
00724   strcpy(p_entry->referral, "");
00725 
00726   /* parse options for this export entry */
00727 
00728   for(i = 0; i < config_GetNbItems(block); i++)
00729     {
00730       config_item_t item;
00731 
00732       item = config_GetItemByIndex(block, i);
00733 
00734       /* get var name and value */
00735       rc = config_GetKeyValue(item, &var_name, &var_value);
00736 
00737       if((rc != 0) || (var_value == NULL))
00738         {
00739           gsh_free(p_entry);
00740           LogCrit(COMPONENT_CONFIG,
00741                   "NFS READ_EXPORT: ERROR: internal error %d", rc);
00742           /* free the entry before exiting */
00743           return -1;
00744         }
00745 
00746       if(!STRCMP(var_name, CONF_EXPORT_ID))
00747         {
00748 
00749           long int export_id;
00750           char *end_ptr;
00751 
00752           /* check if it has not already been set */
00753           if((set_options & FLAG_EXPORT_ID) == FLAG_EXPORT_ID)
00754             {
00755               DEFINED_TWICE_WARNING(CONF_EXPORT_ID);
00756               continue;
00757             }
00758 
00759           /* parse and check export_id */
00760           errno = 0;
00761           export_id = strtol(var_value, &end_ptr, 10);
00762 
00763           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
00764             {
00765               LogCrit(COMPONENT_CONFIG,
00766                       "NFS READ_EXPORT: ERROR: Invalid export_id: \"%s\"",
00767                       var_value);
00768               err_flag = TRUE;
00769               continue;
00770             }
00771 
00772           if(export_id <= 0 || export_id > USHRT_MAX)
00773             {
00774               LogCrit(COMPONENT_CONFIG,
00775                       "NFS READ_EXPORT: ERROR: Export_id out of range: \"%ld\"",
00776                       export_id);
00777               err_flag = TRUE;
00778               continue;
00779             }
00780 
00781           /* set export_id */
00782 
00783           p_entry->id = (unsigned short)export_id;
00784           set_options |= FLAG_EXPORT_ID;
00785 
00786         }
00787       else if(!STRCMP(var_name, CONF_EXPORT_PATH))
00788         {
00789           /* check if it has not already been set */
00790           if((set_options & FLAG_EXPORT_PATH) == FLAG_EXPORT_PATH)
00791             {
00792               DEFINED_TWICE_WARNING(CONF_EXPORT_PATH);
00793               continue;
00794             }
00795 
00796           if(*var_value == '\0')
00797             {
00798               LogCrit(COMPONENT_CONFIG,
00799                       "NFS READ_EXPORT: ERROR: Empty export path");
00800               err_flag = TRUE;
00801               continue;
00802             }
00803 
00806           strncpy(p_entry->fullpath, var_value, MAXPATHLEN);
00807 
00809           strncpy(p_entry->dirname, var_value, MAXNAMLEN);
00810           strncpy(p_entry->fsname, "", MAXNAMLEN);
00811 
00812           set_options |= FLAG_EXPORT_PATH;
00813 
00814         }
00815       else if(!STRCMP(var_name, CONF_EXPORT_ROOT))
00816         {
00817           if(*var_value == '\0')
00818             {
00819               continue;
00820             }
00821           parseAccessParam(var_name, var_value, p_entry,
00822                            EXPORT_OPTION_ROOT);
00823           /* Notice that as least one of the three options
00824            * Root_Access, R_Access, or RW_Access has been specified.
00825            */
00826           set_options |= FLAG_EXPORT_ROOT_OR_ACCESS;
00827 
00828         }
00829       else if(!STRCMP(var_name, CONF_EXPORT_ACCESS))
00830         {
00831           if(*var_value == '\0')
00832             {
00833               continue;
00834             }
00835           parseAccessParam(var_name, var_value, p_entry,
00836                            EXPORT_OPTION_READ_ACCESS | EXPORT_OPTION_WRITE_ACCESS);
00837           /* Notice that as least one of the three options
00838            * Root_Access, R_Access, or RW_Access has been specified.
00839            */
00840           set_options |= FLAG_EXPORT_ROOT_OR_ACCESS | FLAG_EXPORT_ACCESS_LIST;
00841         }
00842       else if(!STRCMP(var_name, CONF_EXPORT_MD_ACCESS))
00843         {
00844           if(*var_value == '\0')
00845             {
00846               continue;
00847             }
00848           parseAccessParam(var_name, var_value, p_entry,
00849                            EXPORT_OPTION_MD_WRITE_ACCESS | EXPORT_OPTION_MD_READ_ACCESS);
00850           /* Notice that as least one of the three options
00851            * Root_Access, R_Access, or RW_Access has been specified.
00852            */
00853           set_options |= FLAG_EXPORT_ROOT_OR_ACCESS | FLAG_EXPORT_ACCESSTYPE_LIST;
00854         }
00855       else if(!STRCMP(var_name, CONF_EXPORT_MD_RO_ACCESS))
00856         {
00857           if(*var_value == '\0')
00858             {
00859               continue;
00860             }
00861           parseAccessParam(var_name, var_value, p_entry,
00862                            EXPORT_OPTION_MD_READ_ACCESS);
00863           /* Notice that as least one of the three options
00864            * Root_Access, R_Access, or RW_Access has been specified.
00865            */
00866           set_options |= FLAG_EXPORT_ROOT_OR_ACCESS | FLAG_EXPORT_ACCESSTYPE_LIST;
00867         }
00868       else if(!STRCMP(var_name, CONF_EXPORT_READ_ACCESS))
00869         {
00870           if(*var_value == '\0')
00871             {
00872               continue;
00873             }
00874           parseAccessParam(var_name, var_value, p_entry,
00875                            EXPORT_OPTION_READ_ACCESS);
00876           /* Notice that as least one of the three options
00877            * Root_Access, R_Access, or RW_Access has been specified.
00878            */
00879           set_options |= FLAG_EXPORT_ROOT_OR_ACCESS | FLAG_EXPORT_ACCESSTYPE_LIST;
00880         }
00881       else if(!STRCMP(var_name, CONF_EXPORT_READWRITE_ACCESS))
00882         {
00883           if(*var_value == '\0')
00884             {
00885               continue;
00886             }
00887           parseAccessParam(var_name, var_value, p_entry,
00888                            EXPORT_OPTION_READ_ACCESS | EXPORT_OPTION_WRITE_ACCESS);
00889           /* Notice that as least one of the three options
00890            * Root_Access, R_Access, or RW_Access has been specified.
00891            */
00892           set_options |= FLAG_EXPORT_ROOT_OR_ACCESS | FLAG_EXPORT_ACCESSTYPE_LIST;
00893         }
00894       else if(!STRCMP(var_name, CONF_EXPORT_PSEUDO))
00895         {
00896 
00897           /* check if it has not already been set */
00898           if((set_options & FLAG_EXPORT_PSEUDO) == FLAG_EXPORT_PSEUDO)
00899             {
00900               DEFINED_TWICE_WARNING(CONF_EXPORT_PSEUDO);
00901               continue;
00902             }
00903 
00904           if(*var_value != '/')
00905             {
00906               LogCrit(COMPONENT_CONFIG,
00907                       "NFS READ_EXPORT: ERROR: Pseudo path must begin with a slash (invalid pseudo path: %s).",
00908                       var_value);
00909               err_flag = TRUE;
00910               continue;
00911             }
00912 
00913           strncpy(p_entry->pseudopath, var_value, MAXPATHLEN);
00914 
00915           set_options |= FLAG_EXPORT_PSEUDO;
00916           p_entry->options |= EXPORT_OPTION_PSEUDO;
00917 
00918         }
00919       else if(!STRCMP(var_name, CONF_EXPORT_REFERRAL))
00920         {
00921           strncpy(p_entry->referral, var_value, MAXPATHLEN);
00922         }
00923       else if(!STRCMP(var_name, CONF_EXPORT_ACCESSTYPE))
00924         {
00925           // check if it has not already been set
00926           if((set_options & FLAG_EXPORT_ACCESSTYPE) == FLAG_EXPORT_ACCESSTYPE)
00927             {
00928               DEFINED_TWICE_WARNING(CONF_EXPORT_ACCESSTYPE);
00929               continue;
00930             }
00931 
00932           if(!STRCMP(var_value, "RW"))
00933             {
00934               p_entry->access_type = ACCESSTYPE_RW;
00935             }
00936           else if(!STRCMP(var_value, "RO"))
00937             {
00938               p_entry->access_type = ACCESSTYPE_RO;
00939             }
00940           else if(!STRCMP(var_value, "MDONLY"))
00941             {
00942               p_entry->access_type = ACCESSTYPE_MDONLY;
00943             }
00944           else if(!STRCMP(var_value, "MDONLY_RO"))
00945             {
00946               p_entry->access_type = ACCESSTYPE_MDONLY_RO;
00947             }
00948           else
00949             {
00950               LogCrit(COMPONENT_CONFIG,
00951                       "NFS READ_EXPORT: ERROR: Invalid access type \"%s\". Values can be: RW, RO, MDONLY, MDONLY_RO.",
00952                       var_value);
00953               err_flag = TRUE;
00954               continue;
00955             }
00956 
00957           set_options |= FLAG_EXPORT_ACCESSTYPE;
00958 
00959         }
00960       else if(!STRCMP(var_name, CONF_EXPORT_NFS_PROTO))
00961         {
00962 
00963 #     define MAX_NFSPROTO      10       /* large enough !!! */
00964 #     define MAX_NFSPROTO_LEN  256      /* so is it !!! */
00965 
00966           char *nfsvers_list[MAX_NFSPROTO];
00967           int idx, count;
00968 
00969           /* check if it has not already been set */
00970           if((set_options & FLAG_EXPORT_NFS_PROTO) == FLAG_EXPORT_NFS_PROTO)
00971             {
00972               DEFINED_TWICE_WARNING(CONF_EXPORT_NFS_PROTO);
00973               continue;
00974             }
00975 
00976           /* reset nfs proto flags (clean defaults) */
00977           p_entry->options &= ~(EXPORT_OPTION_NFSV2
00978                                 | EXPORT_OPTION_NFSV3 | EXPORT_OPTION_NFSV4);
00979 
00980           /* allocate nfs vers strings */
00981           for(idx = 0; idx < MAX_NFSPROTO; idx++)
00982             nfsvers_list[idx] = gsh_malloc(MAX_NFSPROTO_LEN);
00983 
00984           /*
00985            * Search for coma-separated list of nfsprotos
00986            */
00987           count = nfs_ParseConfLine(nfsvers_list, MAX_NFSPROTO,
00988                                     var_value, find_comma, find_endLine);
00989 
00990           if(count < 0)
00991             {
00992               err_flag = TRUE;
00993               LogCrit(COMPONENT_CONFIG,
00994                       "NFS READ_EXPORT: ERROR: NFS protocols list too long (>%d)",
00995                       MAX_NFSPROTO);
00996 
00997               /* free sec strings */
00998               for(idx = 0; idx < MAX_NFSPROTO; idx++)
00999                 gsh_free(nfsvers_list[idx]);
01000 
01001               continue;
01002             }
01003 
01004           /* add each Nfs protocol flag to the option field.  */
01005 
01006           for(idx = 0; idx < count; idx++)
01007             {
01008               if(!STRCMP(nfsvers_list[idx], "2"))
01009                 {
01010                   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) != 0)
01011                     p_entry->options |= EXPORT_OPTION_NFSV2;
01012                   else
01013                     {
01014                       LogInfo(COMPONENT_CONFIG,
01015                               "NFS READ_EXPORT:NFS version 2 is disabled in NFS_Core_Param.");
01016                     }
01017                 }
01018               else if(!STRCMP(nfsvers_list[idx], "3"))
01019                 {
01020                   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) != 0)
01021                     p_entry->options |= EXPORT_OPTION_NFSV3;
01022                   else
01023                     {
01024                       LogInfo(COMPONENT_CONFIG,
01025                               "NFS READ_EXPORT:NFS version 3 is disabled in NFS_Core_Param.");
01026                     }
01027                 }
01028               else if(!STRCMP(nfsvers_list[idx], "4"))
01029                 {
01030                   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV4) != 0)
01031                     p_entry->options |= EXPORT_OPTION_NFSV4;
01032                   else
01033                     {
01034                       LogInfo(COMPONENT_CONFIG,
01035                               "NFS READ_EXPORT:NFS version 4 is disabled in NFS_Core_Param.");
01036                     }
01037                 }
01038               else
01039                 {
01040                   LogCrit(COMPONENT_CONFIG,
01041                           "NFS READ_EXPORT: ERROR: Invalid NFS version \"%s\". Values can be: 2, 3, 4.",
01042                           nfsvers_list[idx]);
01043                   err_flag = TRUE;
01044                 }
01045             }
01046 
01047           /* free sec strings */
01048           for(idx = 0; idx < MAX_NFSPROTO; idx++)
01049             gsh_free(nfsvers_list[idx]);
01050 
01051           /* check that at least one nfs protocol has been specified */
01052           if((p_entry->options & (EXPORT_OPTION_NFSV2
01053                                   | EXPORT_OPTION_NFSV3 | EXPORT_OPTION_NFSV4)) == 0)
01054             {
01055               LogCrit(COMPONENT_CONFIG,
01056                       "NFS READ_EXPORT: WARNING: /!\\ Empty NFS_protocols list");
01057               err_flag = TRUE;
01058             }
01059 
01060           set_options |= FLAG_EXPORT_NFS_PROTO;
01061 
01062         }
01063       else if(!STRCMP(var_name, CONF_EXPORT_TRANS_PROTO))
01064         {
01065 
01066 #     define MAX_TRANSPROTO      10     /* large enough !!! */
01067 #     define MAX_TRANSPROTO_LEN  256    /* so is it !!! */
01068 
01069           char *transproto_list[MAX_TRANSPROTO];
01070           int idx, count;
01071 
01072           /* check if it has not already been set */
01073           if((set_options & FLAG_EXPORT_TRANS_PROTO) == FLAG_EXPORT_TRANS_PROTO)
01074             {
01075               DEFINED_TWICE_WARNING(CONF_EXPORT_TRANS_PROTO);
01076               continue;
01077             }
01078 
01079           /* reset TRANS proto flags (clean defaults) */
01080           p_entry->options &= ~(EXPORT_OPTION_UDP | EXPORT_OPTION_TCP);
01081 
01082           /* allocate TRANS vers strings */
01083           for(idx = 0; idx < MAX_TRANSPROTO; idx++)
01084             transproto_list[idx] = gsh_malloc(MAX_TRANSPROTO_LEN);
01085 
01086           /*
01087            * Search for coma-separated list of TRANSprotos
01088            */
01089           count = nfs_ParseConfLine(transproto_list, MAX_TRANSPROTO,
01090                                     var_value, find_comma, find_endLine);
01091 
01092           if(count < 0)
01093             {
01094               err_flag = TRUE;
01095               LogCrit(COMPONENT_CONFIG,
01096                       "NFS READ_EXPORT: ERROR: Protocol list too long (>%d)",
01097                       MAX_TRANSPROTO);
01098 
01099               /* free sec strings */
01100               for(idx = 0; idx < MAX_TRANSPROTO; idx++)
01101                 gsh_free(transproto_list[idx]);
01102 
01103               continue;
01104             }
01105 
01106           /* add each TRANS protocol flag to the option field.  */
01107 
01108           for(idx = 0; idx < count; idx++)
01109             {
01110               if(!STRCMP(transproto_list[idx], "UDP"))
01111                 {
01112                   p_entry->options |= EXPORT_OPTION_UDP;
01113                 }
01114               else if(!STRCMP(transproto_list[idx], "TCP"))
01115                 {
01116                   p_entry->options |= EXPORT_OPTION_TCP;
01117                 }
01118               else
01119                 {
01120                   LogCrit(COMPONENT_CONFIG,
01121                           "NFS READ_EXPORT: ERROR: Invalid protocol \"%s\". Values can be: UDP, TCP.",
01122                           transproto_list[idx]);
01123                   err_flag = TRUE;
01124                 }
01125             }
01126 
01127           /* free sec strings */
01128           for(idx = 0; idx < MAX_TRANSPROTO; idx++)
01129             gsh_free(transproto_list[idx]);
01130 
01131           /* check that at least one TRANS protocol has been specified */
01132           if((p_entry->options & (EXPORT_OPTION_UDP | EXPORT_OPTION_TCP)) == 0)
01133             LogCrit(COMPONENT_CONFIG,
01134                     "TRANS READ_EXPORT: WARNING: /!\\ Empty protocol list");
01135 
01136           set_options |= FLAG_EXPORT_TRANS_PROTO;
01137 
01138         }
01139       else if(!STRCMP(var_name, CONF_EXPORT_ALL_ANON))
01140         {
01141           /* check if it has not already been set */
01142           if((set_options & FLAG_EXPORT_ALL_ANON) == FLAG_EXPORT_ALL_ANON)
01143             {
01144               DEFINED_TWICE_WARNING(CONF_EXPORT_ALL_ANON);
01145               continue;
01146             }
01147 
01148           if (StrToBoolean(var_value))
01149             p_entry->all_anonymous = TRUE;
01150 
01151           set_options |= FLAG_EXPORT_ANON_USER;
01152         }
01153       else if(!STRCMP(var_name, CONF_EXPORT_ANON_ROOT))
01154         {
01155           long int anon_uid;
01156           char *end_ptr;
01157 
01158           /* check if it has not already been set */
01159           if((set_options & FLAG_EXPORT_ANON_ROOT) == FLAG_EXPORT_ANON_ROOT)
01160             {
01161               DEFINED_TWICE_WARNING(CONF_EXPORT_ANON_USER);
01162               continue;
01163             }
01164 
01165           if((set_options & FLAG_EXPORT_ANON_USER) == FLAG_EXPORT_ANON_USER)
01166             {
01167               DEFINED_TWICE_WARNING(CONF_EXPORT_ANON_ROOT);
01168               continue;
01169             }
01170 
01171           /* parse and check anon_uid */
01172           errno = 0;
01173 
01174           anon_uid = strtol(var_value, &end_ptr, 10);
01175 
01176           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01177             {
01178               LogCrit(COMPONENT_CONFIG,
01179                       "NFS READ_EXPORT: ERROR: Invalid Anonymous_uid: \"%s\"",
01180                       var_value);
01181               err_flag = TRUE;
01182               continue;
01183             }
01184 
01185           /* set anon_uid */
01186           p_entry->anonymous_uid = (uid_t) anon_uid;
01187 
01188           set_options |= FLAG_EXPORT_ANON_ROOT;
01189 
01190         }
01191       else if(!STRCMP(var_name, CONF_EXPORT_ANON_USER))
01192         {
01193           long int anon_uid;
01194           char *end_ptr;
01195 
01196           /* check if it has not already been set */
01197           if((set_options & FLAG_EXPORT_ANON_USER) == FLAG_EXPORT_ANON_USER)
01198             {
01199               DEFINED_TWICE_WARNING(CONF_EXPORT_ANON_USER);
01200               continue;
01201             }
01202 
01203           if((set_options & FLAG_EXPORT_ANON_ROOT) == FLAG_EXPORT_ANON_ROOT)
01204             {
01205               DEFINED_TWICE_WARNING(CONF_EXPORT_ANON_ROOT);
01206               continue;
01207             }
01208 
01209           /* parse and check anon_uid */
01210           errno = 0;
01211 
01212           anon_uid = strtol(var_value, &end_ptr, 10);
01213 
01214           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01215             {
01216               LogCrit(COMPONENT_CONFIG,
01217                       "NFS READ_EXPORT: ERROR: Invalid Anonymous_uid: \"%s\"",
01218                       var_value);
01219               err_flag = TRUE;
01220               continue;
01221             }
01222 
01223           /* set anon_uid */
01224 
01225           p_entry->anonymous_uid = (uid_t) anon_uid;
01226 
01227           set_options |= FLAG_EXPORT_ANON_USER;
01228 
01229         }
01230       else if(!STRCMP(var_name, CONF_EXPORT_ANON_GROUP))
01231         {
01232 
01233           long int anon_gid;
01234           char *end_ptr;
01235 
01236           /* check if it has not already been set */
01237           if((set_options & FLAG_EXPORT_ANON_GROUP) == FLAG_EXPORT_ANON_GROUP)
01238             {
01239               DEFINED_TWICE_WARNING(CONF_EXPORT_ANON_GROUP);
01240               continue;
01241             }
01242 
01243           /* parse and check anon_uid */
01244           errno = 0;
01245 
01246           anon_gid = strtol(var_value, &end_ptr, 10);
01247 
01248           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01249             {
01250               LogCrit(COMPONENT_CONFIG,
01251                       "NFS READ_EXPORT: ERROR: Invalid Anonymous_gid: \"%s\"",
01252                       var_value);
01253               err_flag = TRUE;
01254               continue;
01255             }
01256 
01257           /* set anon_uid */
01258 
01259           p_entry->anonymous_gid = (gid_t) anon_gid;
01260 
01261           set_options |= FLAG_EXPORT_ANON_GROUP;
01262 
01263         }
01264       else if(!STRCMP(var_name, CONF_EXPORT_SECTYPE))
01265         {
01266 #     define MAX_SECTYPE      10        /* large enough !!! */
01267 #     define MAX_SECTYPE_LEN  256       /* so is it !!! */
01268 
01269           char *sec_list[MAX_SECTYPE];
01270           int idx, count;
01271 
01272           /* check if it has not already been set */
01273           if((set_options & FLAG_EXPORT_SECTYPE) == FLAG_EXPORT_SECTYPE)
01274             {
01275               DEFINED_TWICE_WARNING(CONF_EXPORT_SECTYPE);
01276               continue;
01277             }
01278 
01279           /* reset security flags (clean defaults) */
01280           p_entry->options &= ~(EXPORT_OPTION_AUTH_NONE
01281                                 | EXPORT_OPTION_AUTH_UNIX
01282                                 | EXPORT_OPTION_RPCSEC_GSS_NONE
01283                                 | EXPORT_OPTION_RPCSEC_GSS_INTG
01284                                 | EXPORT_OPTION_RPCSEC_GSS_PRIV);
01285 
01286           /* allocate sec strings */
01287           for(idx = 0; idx < MAX_SECTYPE; idx++)
01288             sec_list[idx] = gsh_malloc(MAX_SECTYPE_LEN);
01289 
01290           /*
01291            * Search for coma-separated list of sectypes
01292            */
01293           count = nfs_ParseConfLine(sec_list, MAX_SECTYPE,
01294                                     var_value, find_comma, find_endLine);
01295 
01296           if(count < 0)
01297             {
01298               err_flag = TRUE;
01299               LogCrit(COMPONENT_CONFIG,
01300                       "NFS READ_EXPORT: ERROR: SecType list too long (>%d)",
01301                       MAX_SECTYPE);
01302 
01303               /* free sec strings */
01304               for(idx = 0; idx < MAX_SECTYPE; idx++)
01305                 gsh_free(sec_list[idx]);
01306 
01307               continue;
01308             }
01309 
01310           /* add each sectype flag to the option field.  */
01311 
01312           for(idx = 0; idx < count; idx++)
01313             {
01314               if(!STRCMP(sec_list[idx], "none"))
01315                 {
01316                   p_entry->options |= EXPORT_OPTION_AUTH_NONE;
01317                 }
01318               else if(!STRCMP(sec_list[idx], "sys"))
01319                 {
01320                   p_entry->options |= EXPORT_OPTION_AUTH_UNIX;
01321                 }
01322               else if(!STRCMP(sec_list[idx], "krb5"))
01323                 {
01324                   p_entry->options |= EXPORT_OPTION_RPCSEC_GSS_NONE;
01325                 }
01326               else if(!STRCMP(sec_list[idx], "krb5i"))
01327                 {
01328                   p_entry->options |= EXPORT_OPTION_RPCSEC_GSS_INTG;
01329                 }
01330               else if(!STRCMP(sec_list[idx], "krb5p"))
01331                 {
01332                   p_entry->options |= EXPORT_OPTION_RPCSEC_GSS_PRIV;
01333                 }
01334               else
01335                 {
01336                   LogCrit(COMPONENT_CONFIG,
01337                           "NFS READ_EXPORT: ERROR: Invalid SecType \"%s\". Values can be: none, sys, krb5, krb5i, krb5p.",
01338                           sec_list[idx]);
01339                   err_flag = TRUE;
01340                 }
01341             }
01342 
01343           /* free sec strings */
01344           for(idx = 0; idx < MAX_SECTYPE; idx++)
01345             gsh_free(sec_list[idx]);
01346 
01347           /* check that at least one sectype has been specified */
01348           if((p_entry->options & (EXPORT_OPTION_AUTH_NONE
01349                                   | EXPORT_OPTION_AUTH_UNIX
01350                                   | EXPORT_OPTION_RPCSEC_GSS_NONE
01351                                   | EXPORT_OPTION_RPCSEC_GSS_INTG
01352                                   | EXPORT_OPTION_RPCSEC_GSS_PRIV)) == 0)
01353             LogCrit(COMPONENT_CONFIG,
01354                     "NFS READ_EXPORT: WARNING: /!\\ Empty SecType");
01355 
01356           set_options |= FLAG_EXPORT_SECTYPE;
01357 
01358         }
01359       else if(!STRCMP(var_name, CONF_EXPORT_MAX_READ))
01360         {
01361           long long int size;
01362           char *end_ptr;
01363 
01364           /* check if it has not already been set */
01365           if((set_options & FLAG_EXPORT_MAX_READ) == FLAG_EXPORT_MAX_READ)
01366             {
01367               DEFINED_TWICE_WARNING(CONF_EXPORT_MAX_READ);
01368               continue;
01369             }
01370 
01371           errno = 0;
01372           size = strtoll(var_value, &end_ptr, 10);
01373 
01374           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01375             {
01376               LogCrit(COMPONENT_CONFIG,
01377                       "NFS READ_EXPORT: ERROR: Invalid MaxRead: \"%s\"",
01378                       var_value);
01379               err_flag = TRUE;
01380               continue;
01381             }
01382 
01383           if(size < 0)
01384             {
01385               LogCrit(COMPONENT_CONFIG,
01386                       "NFS READ_EXPORT: ERROR: MaxRead out of range: %lld",
01387                       size);
01388               err_flag = TRUE;
01389               continue;
01390             }
01391 
01392           /* set filesystem_id */
01393 
01394           p_entry->MaxRead = (fsal_size_t) size;
01395           p_entry->options |= EXPORT_OPTION_MAXREAD;
01396 
01397           set_options |= FLAG_EXPORT_MAX_READ;
01398         }
01399       else if(!STRCMP(var_name, CONF_EXPORT_MAX_WRITE))
01400         {
01401           long long int size;
01402           char *end_ptr;
01403 
01404           /* check if it has not already been set */
01405           if((set_options & FLAG_EXPORT_MAX_WRITE) == FLAG_EXPORT_MAX_WRITE)
01406             {
01407               DEFINED_TWICE_WARNING(CONF_EXPORT_MAX_WRITE);
01408               continue;
01409             }
01410 
01411           errno = 0;
01412           size = strtoll(var_value, &end_ptr, 10);
01413 
01414           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01415             {
01416               LogCrit(COMPONENT_CONFIG,
01417                       "NFS READ_EXPORT: ERROR: Invalid MaxWrite: \"%s\"",
01418                       var_value);
01419               err_flag = TRUE;
01420               continue;
01421             }
01422 
01423           if(size < 0)
01424             {
01425               LogCrit(COMPONENT_CONFIG,
01426                       "NFS READ_EXPORT: ERROR: MaxWrite out of range: %lld",
01427                       size);
01428               err_flag = TRUE;
01429               continue;
01430             }
01431 
01432           /* set filesystem_id */
01433 
01434           p_entry->MaxWrite = (fsal_size_t) size;
01435           p_entry->options |= EXPORT_OPTION_MAXWRITE;
01436 
01437           set_options |= FLAG_EXPORT_MAX_WRITE;
01438         }
01439       else if(!STRCMP(var_name, CONF_EXPORT_PREF_READ))
01440         {
01441           long long int size;
01442           char *end_ptr;
01443 
01444           /* check if it has not already been set */
01445           if((set_options & FLAG_EXPORT_PREF_READ) == FLAG_EXPORT_PREF_READ)
01446             {
01447               DEFINED_TWICE_WARNING(CONF_EXPORT_PREF_READ);
01448               continue;
01449             }
01450 
01451           errno = 0;
01452           size = strtoll(var_value, &end_ptr, 10);
01453 
01454           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01455             {
01456               LogCrit(COMPONENT_CONFIG,
01457                       "NFS READ_EXPORT: ERROR: Invalid PrefRead: \"%s\"",
01458                       var_value);
01459               err_flag = TRUE;
01460               continue;
01461             }
01462 
01463           if(size < 0)
01464             {
01465               LogCrit(COMPONENT_CONFIG,
01466                       "NFS READ_EXPORT: ERROR: PrefRead out of range: %lld",
01467                       size);
01468               err_flag = TRUE;
01469               continue;
01470             }
01471 
01472           /* set filesystem_id */
01473 
01474           p_entry->PrefRead = (fsal_size_t) size;
01475           p_entry->options |= EXPORT_OPTION_PREFREAD;
01476 
01477           set_options |= FLAG_EXPORT_PREF_READ;
01478         }
01479       else if(!STRCMP(var_name, CONF_EXPORT_PREF_WRITE))
01480         {
01481           long long int size;
01482           char *end_ptr;
01483 
01484           /* check if it has not already been set */
01485           if((set_options & FLAG_EXPORT_PREF_WRITE) == FLAG_EXPORT_PREF_WRITE)
01486             {
01487               DEFINED_TWICE_WARNING(CONF_EXPORT_PREF_WRITE);
01488               continue;
01489             }
01490 
01491           errno = 0;
01492           size = strtoll(var_value, &end_ptr, 10);
01493 
01494           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01495             {
01496               LogCrit(COMPONENT_CONFIG,
01497                       "NFS READ_EXPORT: ERROR: Invalid PrefWrite: \"%s\"",
01498                       var_value);
01499               err_flag = TRUE;
01500               continue;
01501             }
01502 
01503           if(size < 0)
01504             {
01505               LogCrit(COMPONENT_CONFIG,
01506                       "NFS READ_EXPORT: ERROR: PrefWrite out of range: %lld",
01507                       size);
01508               err_flag = TRUE;
01509               continue;
01510             }
01511 
01512           /* set filesystem_id */
01513 
01514           p_entry->PrefWrite = (fsal_size_t) size;
01515           p_entry->options |= EXPORT_OPTION_PREFWRITE;
01516 
01517           set_options |= FLAG_EXPORT_PREF_WRITE;
01518         }
01519       else if(!STRCMP(var_name, CONF_EXPORT_PREF_READDIR))
01520         {
01521           long long int size;
01522           char *end_ptr;
01523 
01524           /* check if it has not already been set */
01525           if((set_options & FLAG_EXPORT_PREF_READDIR) == FLAG_EXPORT_PREF_READDIR)
01526             {
01527               DEFINED_TWICE_WARNING(CONF_EXPORT_PREF_READDIR);
01528               continue;
01529             }
01530 
01531           errno = 0;
01532           size = strtoll(var_value, &end_ptr, 10);
01533 
01534           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01535             {
01536               LogCrit(COMPONENT_CONFIG,
01537                       "NFS READ_EXPORT: ERROR: Invalid PrefReaddir: \"%s\"",
01538                       var_value);
01539               err_flag = TRUE;
01540               continue;
01541             }
01542 
01543           if(size < 0)
01544             {
01545               LogCrit(COMPONENT_CONFIG,
01546                       "NFS READ_EXPORT: ERROR: PrefReaddir out of range: %lld",
01547                       size);
01548               err_flag = TRUE;
01549               continue;
01550             }
01551 
01552           /* set filesystem_id */
01553 
01554           p_entry->PrefReaddir = (fsal_size_t) size;
01555           p_entry->options |= EXPORT_OPTION_PREFRDDIR;
01556 
01557           set_options |= FLAG_EXPORT_PREF_READDIR;
01558         }
01559       else if(!STRCMP(var_name, CONF_EXPORT_PREF_WRITE))
01560         {
01561           long long int size;
01562           char *end_ptr;
01563 
01564           /* check if it has not already been set */
01565           if((set_options & FLAG_EXPORT_PREF_WRITE) == FLAG_EXPORT_PREF_WRITE)
01566             {
01567               DEFINED_TWICE_WARNING(CONF_EXPORT_PREF_WRITE);
01568               continue;
01569             }
01570 
01571           errno = 0;
01572           size = strtoll(var_value, &end_ptr, 10);
01573 
01574           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01575             {
01576               LogCrit(COMPONENT_CONFIG,
01577                       "NFS READ_EXPORT: ERROR: Invalid PrefWrite: \"%s\"",
01578                       var_value);
01579               err_flag = TRUE;
01580               continue;
01581             }
01582 
01583           if(size < 0)
01584             {
01585               LogCrit(COMPONENT_CONFIG,
01586                       "NFS READ_EXPORT: ERROR: PrefWrite out of range: %lld",
01587                       size);
01588               err_flag = TRUE;
01589               continue;
01590             }
01591 
01592           /* set filesystem_id */
01593 
01594           p_entry->PrefWrite = (fsal_size_t) size;
01595           p_entry->options |= EXPORT_OPTION_PREFWRITE;
01596 
01597           set_options |= FLAG_EXPORT_PREF_WRITE;
01598 
01599         }
01600       else if(!STRCMP(var_name, CONF_EXPORT_FSID))
01601         {
01602           long long int major, minor;
01603           char *end_ptr;
01604 
01605           /* check if it has not already been set */
01606           if((set_options & FLAG_EXPORT_FSID) == FLAG_EXPORT_FSID)
01607             {
01608               DEFINED_TWICE_WARNING(CONF_EXPORT_FSID);
01609               continue;
01610             }
01611 
01612           /* parse and check filesystem id */
01613           errno = 0;
01614           major = strtoll(var_value, &end_ptr, 10);
01615 
01616           if(end_ptr == NULL || *end_ptr != '.' || errno != 0)
01617             {
01618               LogCrit(COMPONENT_CONFIG,
01619                       "NFS READ_EXPORT: ERROR: Invalid filesystem_id: \"%s\"",
01620                       var_value);
01621               err_flag = TRUE;
01622               continue;
01623             }
01624 
01625           end_ptr++;            /* the first character after the dot */
01626 
01627           errno = 0;
01628           minor = strtoll(end_ptr, &end_ptr, 10);
01629 
01630           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01631             {
01632               LogCrit(COMPONENT_CONFIG,
01633                       "NFS READ_EXPORT: ERROR: Invalid filesystem_id: \"%s\"",
01634                       var_value);
01635               err_flag = TRUE;
01636               continue;
01637             }
01638 
01639           if(major < 0 || minor < 0)
01640             {
01641               LogCrit(COMPONENT_CONFIG,
01642                       "NFS READ_EXPORT: ERROR: filesystem_id out of range: %lld.%lld",
01643                       major, minor);
01644               err_flag = TRUE;
01645               continue;
01646             }
01647 
01648           /* set filesystem_id */
01649 
01650           p_entry->filesystem_id.major = (fsal_u64_t) major;
01651           p_entry->filesystem_id.minor = (fsal_u64_t) minor;
01652 
01653           set_options |= FLAG_EXPORT_FSID;
01654 
01655         }
01656       else if(!STRCMP(var_name, CONF_EXPORT_NOSUID))
01657         {
01658           /* check if it has not already been set */
01659           if((set_options & FLAG_EXPORT_NOSUID) == FLAG_EXPORT_NOSUID)
01660             {
01661               DEFINED_TWICE_WARNING(CONF_EXPORT_NOSUID);
01662               continue;
01663             }
01664 
01665           switch (StrToBoolean(var_value))
01666             {
01667             case 1:
01668               p_entry->options |= EXPORT_OPTION_NOSUID;
01669               break;
01670 
01671             case 0:
01672               /*default (false) */
01673               break;
01674 
01675             default:           /* error */
01676               {
01677                 LogCrit(COMPONENT_CONFIG,
01678                         "NFS READ_EXPORT: ERROR: Invalid value for %s (%s): TRUE or FALSE expected.",
01679                         var_name, var_value);
01680                 err_flag = TRUE;
01681                 continue;
01682               }
01683             }
01684 
01685           set_options |= FLAG_EXPORT_NOSUID;
01686 
01687         }
01688       else if(!STRCMP(var_name, CONF_EXPORT_NOSGID))
01689         {
01690           /* check if it has not already been set */
01691           if((set_options & FLAG_EXPORT_NOSGID) == FLAG_EXPORT_NOSGID)
01692             {
01693               DEFINED_TWICE_WARNING(CONF_EXPORT_NOSGID);
01694               continue;
01695             }
01696 
01697           switch (StrToBoolean(var_value))
01698             {
01699             case 1:
01700               p_entry->options |= EXPORT_OPTION_NOSGID;
01701               break;
01702 
01703             case 0:
01704               /*default (false) */
01705               break;
01706 
01707             default:           /* error */
01708               LogCrit(COMPONENT_CONFIG,
01709                       "NFS READ_EXPORT: ERROR: Invalid value for %s (%s): TRUE or FALSE expected.",
01710                       var_name, var_value);
01711               err_flag = TRUE;
01712               continue;
01713             }
01714 
01715           set_options |= FLAG_EXPORT_NOSGID;
01716         }
01717       else if(!STRCMP(var_name, CONF_EXPORT_PRIVILEGED_PORT))
01718         {
01719           /* check if it has not already been set */
01720           if((set_options & FLAG_EXPORT_PRIVILEGED_PORT) == FLAG_EXPORT_PRIVILEGED_PORT)
01721             {
01722               DEFINED_TWICE_WARNING("FLAG_EXPORT_PRIVILEGED_PORT");
01723               continue;
01724             }
01725 
01726           switch (StrToBoolean(var_value))
01727             {
01728             case 1:
01729               p_entry->options |= EXPORT_OPTION_PRIVILEGED_PORT;
01730               break;
01731 
01732             case 0:
01733               /*default (false) */
01734               break;
01735 
01736             default:           /* error */
01737               LogCrit(COMPONENT_CONFIG,
01738                       "NFS READ_EXPORT: ERROR: Invalid value for '%s' (%s): TRUE or FALSE expected.",
01739                       var_name, var_value);
01740               err_flag = TRUE;
01741               continue;
01742             }
01743           set_options |= FLAG_EXPORT_PRIVILEGED_PORT;
01744         }
01745       else if(!STRCMP(var_name, CONF_EXPORT_USE_DATACACHE))
01746         {
01747           /* check if it has not already been set */
01748           if((set_options & FLAG_EXPORT_USE_DATACACHE) == FLAG_EXPORT_USE_DATACACHE)
01749             {
01750               DEFINED_TWICE_WARNING("FLAG_EXPORT_USE_DATACACHE");
01751               continue;
01752             }
01753 
01754           switch (StrToBoolean(var_value))
01755             {
01756             case 1:
01757               p_entry->options |= EXPORT_OPTION_USE_DATACACHE;
01758               break;
01759 
01760             case 0:
01761               /*default (false) */
01762               break;
01763 
01764             default:           /* error */
01765               LogCrit(COMPONENT_CONFIG,
01766                       "NFS READ_EXPORT: ERROR: Invalid value for '%s' (%s): TRUE or FALSE expected.",
01767                       var_name, var_value);
01768               err_flag = TRUE;
01769               continue;
01770             }
01771           set_options |= FLAG_EXPORT_USE_DATACACHE;
01772         }
01773       else if(!STRCMP(var_name, CONF_EXPORT_PNFS))
01774         {
01775           /* check if it has not already been set */
01776           if((set_options & FLAG_EXPORT_USE_PNFS) == FLAG_EXPORT_USE_PNFS)
01777             {
01778               DEFINED_TWICE_WARNING("FLAG_EXPORT_USE_PNFS");
01779               continue;
01780             }
01781 
01782           switch (StrToBoolean(var_value))
01783             {
01784             case 1:
01785               p_entry->options |= EXPORT_OPTION_USE_PNFS;
01786               break;
01787 
01788             case 0:
01789               /*default (false) */
01790               break;
01791 
01792             default:           /* error */
01793               LogCrit(COMPONENT_CONFIG,
01794                       "NFS READ_EXPORT: ERROR: Invalid value for '%s' (%s): TRUE or FALSE expected.",
01795                       var_name, var_value);
01796               err_flag = TRUE;
01797               continue;
01798             }
01799           set_options |= EXPORT_OPTION_USE_PNFS;
01800         }
01801       else if(!STRCMP(var_name, CONF_EXPORT_UQUOTA ) )
01802         {
01803           /* check if it has not already been set */
01804           if((set_options & FLAG_EXPORT_USE_UQUOTA) == FLAG_EXPORT_USE_UQUOTA)
01805             {
01806               DEFINED_TWICE_WARNING("FLAG_EXPORT_USE_UQUOTA");
01807               continue;
01808             }
01809 
01810           switch (StrToBoolean(var_value))
01811             {
01812             case 1:
01813               p_entry->options |= EXPORT_OPTION_USE_UQUOTA;
01814               break;
01815 
01816             case 0:
01817               /*default (false) */
01818               break;
01819 
01820             default:           /* error */
01821               LogCrit(COMPONENT_CONFIG,
01822                       "NFS READ_EXPORT: ERROR: Invalid value for '%s' (%s): TRUE or FALSE expected.",
01823                       var_name, var_value);
01824               err_flag = TRUE;
01825               continue;
01826             }
01827           set_options |= EXPORT_OPTION_USE_UQUOTA;
01828 
01829         }
01830       else if(!STRCMP(var_name, CONF_EXPORT_FS_SPECIFIC))
01831         {
01832           /* check if it has not already been set */
01833           if((set_options & FLAG_EXPORT_FS_SPECIFIC) == FLAG_EXPORT_FS_SPECIFIC)
01834             {
01835               DEFINED_TWICE_WARNING(CONF_EXPORT_FS_SPECIFIC);
01836               continue;
01837             }
01838 
01839           strncpy(p_entry->FS_specific, var_value, MAXPATHLEN);
01840 
01841           set_options |= FLAG_EXPORT_FS_SPECIFIC;
01842 
01843         }
01844       else if(!STRCMP(var_name, CONF_EXPORT_FS_TAG))
01845         {
01846           /* check if it has not already been set */
01847           if((set_options & FLAG_EXPORT_FS_TAG) == FLAG_EXPORT_FS_TAG)
01848             {
01849               DEFINED_TWICE_WARNING(CONF_EXPORT_FS_TAG);
01850               continue;
01851             }
01852 
01853           strncpy(p_entry->FS_tag, var_value, MAXPATHLEN);
01854 
01855           set_options |= FLAG_EXPORT_FS_TAG;
01856 
01857         }
01858       else if(!STRCMP(var_name, CONF_EXPORT_MAX_OFF_WRITE))
01859         {
01860           long long int offset;
01861           char *end_ptr;
01862 
01863           errno = 0;
01864           offset = strtoll(var_value, &end_ptr, 10);
01865 
01866           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01867             {
01868               LogCrit(COMPONENT_CONFIG,
01869                       "NFS READ_EXPORT: ERROR: Invalid MaxOffsetWrite: \"%s\"",
01870                       var_value);
01871               err_flag = TRUE;
01872               continue;
01873             }
01874 
01875           /* set filesystem_id */
01876 
01877           p_entry->MaxOffsetWrite = (fsal_size_t) offset;
01878           p_entry->options |= EXPORT_OPTION_MAXOFFSETWRITE;
01879 
01880           set_options |= FLAG_EXPORT_MAX_OFF_WRITE;
01881 
01882         }
01883       else if(!STRCMP(var_name, CONF_EXPORT_MAX_CACHE_SIZE))
01884         {
01885           long long int offset;
01886           char *end_ptr;
01887 
01888           errno = 0;
01889           offset = strtoll(var_value, &end_ptr, 10);
01890 
01891           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01892             {
01893               LogCrit(COMPONENT_CONFIG,
01894                       "NFS READ_EXPORT: ERROR: Invalid MaxCacheSize: \"%s\"",
01895                       var_value);
01896               err_flag = TRUE;
01897               continue;
01898             }
01899 
01900           /* set filesystem_id */
01901 
01902           p_entry->MaxCacheSize = (fsal_size_t) offset;
01903           p_entry->options |= EXPORT_OPTION_MAXCACHESIZE;
01904 
01905           set_options |= FLAG_EXPORT_MAX_CACHE_SIZE;
01906 
01907         }
01908       else if(!STRCMP(var_name, CONF_EXPORT_MAX_OFF_READ))
01909         {
01910           long long int offset;
01911           char *end_ptr;
01912 
01913           errno = 0;
01914           offset = strtoll(var_value, &end_ptr, 10);
01915 
01916           if(end_ptr == NULL || *end_ptr != '\0' || errno != 0)
01917             {
01918               LogCrit(COMPONENT_CONFIG,
01919                       "NFS READ_EXPORT: ERROR: Invalid MaxOffsetRead: \"%s\"",
01920                       var_value);
01921               err_flag = TRUE;
01922               continue;
01923             }
01924 
01925           /* set filesystem_id */
01926 
01927           p_entry->MaxOffsetRead = (fsal_size_t) offset;
01928           p_entry->options |= EXPORT_OPTION_MAXOFFSETREAD;
01929 
01930           set_options |= FLAG_EXPORT_MAX_OFF_READ;
01931 
01932         }
01933       else if(!STRCMP(var_name, CONF_EXPORT_USE_COMMIT))
01934         {
01935           switch (StrToBoolean(var_value))
01936             {
01937             case 1:
01938               p_entry->use_commit = TRUE;
01939               break;
01940 
01941             case 0:
01942               p_entry->use_commit = FALSE;
01943               break;
01944 
01945             default:           /* error */
01946               {
01947                 LogCrit(COMPONENT_CONFIG,
01948                         "NFS READ_EXPORT: ERROR: Invalid value for %s (%s): TRUE or FALSE expected.",
01949                         var_name, var_value);
01950                 err_flag = TRUE;
01951                 continue;
01952               }
01953             }
01954         }
01955       else if(!STRCMP(var_name, CONF_EXPORT_USE_GANESHA_WRITE_BUFFER))
01956         {
01957           switch (StrToBoolean(var_value))
01958             {
01959             case 1:
01960               p_entry->use_ganesha_write_buffer = TRUE;
01961               break;
01962 
01963             case 0:
01964               p_entry->use_ganesha_write_buffer = FALSE;
01965               break;
01966 
01967             default:           /* error */
01968               {
01969                 LogCrit(COMPONENT_CONFIG,
01970                         "NFS READ_EXPORT: ERROR: Invalid value for %s (%s): TRUE or FALSE expected.",
01971                         var_name, var_value);
01972                 err_flag = TRUE;
01973                 continue;
01974               }
01975             }
01976         }
01977 #ifdef _USE_FSAL_UP
01978       else if(!STRCMP(var_name, CONF_EXPORT_FSAL_UP_TYPE))
01979         {
01980           strncpy(p_entry->fsal_up_type,var_value,sizeof(var_value));
01981         }
01982       else if(!STRCMP(var_name, CONF_EXPORT_FSAL_UP_TIMEOUT))
01983         {
01984           /* Right now we are expecting seconds ... we should support
01985            * nseconds as well! */
01986           p_entry->fsal_up_timeout.seconds = atoi(var_value);
01987           if (p_entry->fsal_up_timeout.seconds < 0
01988               || p_entry->fsal_up_timeout.nseconds < 0)
01989             {
01990               p_entry->fsal_up_timeout.seconds = 0;
01991               p_entry->fsal_up_timeout.nseconds = 0;
01992             }
01993         }
01994       else if(!STRCMP(var_name, CONF_EXPORT_FSAL_UP_FILTERS))
01995         {
01996           /* TODO: Parse the strings and form a list.
01997            * Later each name will match a predefined filter
01998            * in the FSAL UP interface. */
01999           p_entry->fsal_up_filter_list = NULL;
02000         }
02001       else if(!STRCMP(var_name, CONF_EXPORT_USE_FSAL_UP))
02002         {
02003           switch (StrToBoolean(var_value))
02004             {
02005             case 1:
02006               p_entry->use_fsal_up = TRUE;
02007               break;
02008             case 0:
02009               p_entry->use_fsal_up = FALSE;
02010               break;
02011             default:           /* error */
02012               {
02013                 LogCrit(COMPONENT_CONFIG,
02014                         "USR_FSAL_UP: ERROR: Invalid value for %s (%s): TRUE or FALSE expected.",
02015                         var_name, var_value);
02016                 err_flag = TRUE;
02017                 continue;
02018               }
02019             }
02020         }
02021 #endif /* _USE_FSAL_UP */
02022       else if(!STRCMP(var_name, CONF_EXPORT_USE_COOKIE_VERIFIER))
02023         {
02024           switch (StrToBoolean(var_value))
02025             {
02026             case 1:
02027               p_entry->UseCookieVerifier = TRUE;
02028               break;
02029 
02030             case 0:
02031               p_entry->UseCookieVerifier = FALSE;
02032               break;
02033 
02034             default:           /* error */
02035               {
02036                 LogCrit(COMPONENT_CONFIG,
02037                         "NFS READ_EXPORT: ERROR: Invalid value for %s (%s): TRUE or FALSE expected.",
02038                         var_name, var_value);
02039                 err_flag = TRUE;
02040                 continue;
02041               }
02042             }
02043         }
02044       else
02045         {
02046           LogCrit(COMPONENT_CONFIG,
02047                   "NFS READ_EXPORT: WARNING: Unknown option: %s",
02048                   var_name);
02049         }
02050 
02051     }
02052 
02054   if((set_options & mandatory_options) != mandatory_options)
02055     {
02056       if((set_options & FLAG_EXPORT_ID) != FLAG_EXPORT_ID)
02057         LogCrit(COMPONENT_CONFIG,
02058                 "NFS READ_EXPORT: ERROR: Missing mandatory parameter %s",
02059                 CONF_EXPORT_ID );
02060 
02061       if((set_options & FLAG_EXPORT_PATH) != FLAG_EXPORT_PATH)
02062         LogCrit(COMPONENT_CONFIG,
02063                 "NFS READ_EXPORT: ERROR: Missing mandatory parameter %s",
02064                 CONF_EXPORT_PATH);
02065 
02066       if((set_options & FLAG_EXPORT_ROOT_OR_ACCESS) != FLAG_EXPORT_ROOT_OR_ACCESS)
02067         LogCrit(COMPONENT_CONFIG,
02068                 "NFS READ_EXPORT: ERROR: Missing mandatory parameter %s or %s or %s",
02069                 CONF_EXPORT_ROOT, CONF_EXPORT_READ_ACCESS,
02070                 CONF_EXPORT_READWRITE_ACCESS);
02071 
02072       if((set_options & FLAG_EXPORT_PSEUDO) != FLAG_EXPORT_PSEUDO)
02073         LogCrit(COMPONENT_CONFIG,
02074                 "NFS READ_EXPORT: ERROR: Missing mandatory parameter %s",
02075                 CONF_EXPORT_PSEUDO);
02076 
02077       err_flag = TRUE;
02078     }
02079 
02080   if (
02081       ((set_options & FLAG_EXPORT_ACCESSTYPE) || (set_options & FLAG_EXPORT_ACCESS_LIST)) &&
02082       (set_options & FLAG_EXPORT_ACCESSTYPE_LIST))
02083     {
02084       LogCrit(COMPONENT_CONFIG,
02085               "NFS READ_EXPORT: ERROR: %s list cannot be used when %s and/or %s are used in the same export entry config.",
02086               CONF_EXPORT_READWRITE_ACCESS, CONF_EXPORT_ACCESSTYPE,
02087               CONF_EXPORT_ACCESS);
02088       err_flag = TRUE;
02089     }
02090 
02091   if ((set_options & FLAG_EXPORT_ACCESSTYPE) || (set_options & FLAG_EXPORT_ACCESS_LIST))
02092     p_entry->new_access_list_version = FALSE;
02093   else
02094     p_entry->new_access_list_version = TRUE;
02095 
02096   /* check if there had any error.
02097    * if so, free the p_entry and return an error.
02098    */
02099   if(err_flag)
02100     {
02101       gsh_free(p_entry);
02102       return -1;
02103     }
02104 
02105   /* Here we can make sure certain options are turned on for specific FSALs */
02106   if (!fsal_specific_checks(p_entry))
02107     {
02108       LogCrit(COMPONENT_CONFIG,
02109                "NFS READ_EXPORT: ERROR: Found conflicts in export entry.");
02110       return -1;
02111     }
02112 
02113   *pp_export = p_entry;
02114 
02115   LogEvent(COMPONENT_CONFIG,
02116            "NFS READ_EXPORT: Export %d (%s) successfully parsed",
02117            p_entry->id, p_entry->fullpath);
02118 
02119   return 0;
02120 
02121 }
02122 
02128 static char *client_root_access[] = { "*" };
02129 
02130 exportlist_t *BuildDefaultExport()
02131 {
02132   exportlist_t *p_entry;
02133   int rc;
02134 
02135   /* allocates new export entry */
02136   p_entry = gsh_malloc(sizeof(exportlist_t));
02137 
02138   if(p_entry == NULL)
02139     return NULL;
02140 
02143   p_entry->next = NULL;
02144   p_entry->options = 0;
02145   p_entry->status = EXPORTLIST_OK;
02146   p_entry->clients.num_clients = 0;
02147   p_entry->access_type = ACCESSTYPE_RW;
02148   p_entry->anonymous_uid = (uid_t) ANON_UID;
02149   p_entry->MaxOffsetWrite = (fsal_off_t) 0;
02150   p_entry->MaxOffsetRead = (fsal_off_t) 0;
02151   p_entry->MaxCacheSize = (fsal_off_t) 0;
02152 
02153   /* by default, we support auth_none and auth_sys */
02154   p_entry->options |= EXPORT_OPTION_AUTH_NONE | EXPORT_OPTION_AUTH_UNIX;
02155 
02156   /* by default, we support all NFS versions supported by the core and both transport protocols */
02157   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) != 0)
02158     p_entry->options |= EXPORT_OPTION_NFSV2;
02159   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) != 0)
02160     p_entry->options |= EXPORT_OPTION_NFSV3;
02161   if((nfs_param.core_param.core_options & CORE_OPTION_NFSV4) != 0)
02162     p_entry->options |= EXPORT_OPTION_NFSV4;
02163   p_entry->options |= EXPORT_OPTION_UDP | EXPORT_OPTION_TCP;
02164 
02165   p_entry->filesystem_id.major = (fsal_u64_t) 101;
02166   p_entry->filesystem_id.minor = (fsal_u64_t) 101;
02167 
02168   p_entry->MaxWrite = (fsal_size_t) 16384;
02169   p_entry->MaxRead = (fsal_size_t) 16384;
02170   p_entry->PrefWrite = (fsal_size_t) 16384;
02171   p_entry->PrefRead = (fsal_size_t) 16384;
02172   p_entry->PrefReaddir = (fsal_size_t) 16384;
02173 
02174   strcpy(p_entry->FS_specific, "");
02175   strcpy(p_entry->FS_tag, "ganesha");
02176 
02177   p_entry->id = 1;
02178 
02179   strcpy(p_entry->fullpath, "/");
02180   strcpy(p_entry->dirname, "/");
02181   strcpy(p_entry->fsname, "");
02182   strcpy(p_entry->pseudopath, "/");
02183   strcpy(p_entry->referral, "");
02184 
02185   p_entry->UseCookieVerifier = TRUE;
02186 
02190   rc = nfs_AddClientsToExportList(p_entry, 1, client_root_access, EXPORT_OPTION_ROOT);
02191 
02192   if(rc != 0)
02193     {
02194       LogCrit(COMPONENT_CONFIG,
02195               "NFS READ_EXPORT: ERROR: Invalid client \"%s\"",
02196               (char *)client_root_access);
02197       return NULL;
02198     }
02199 
02200   LogEvent(COMPONENT_CONFIG,
02201            "NFS READ_EXPORT: Export %d (%s) successfully parsed",
02202            p_entry->id, p_entry->fullpath);
02203 
02204   return p_entry;
02205 
02206 }                               /* BuildDefaultExport */
02207 
02214 int ReadExports(config_file_t in_config,        /* The file that contains the export list */
02215                 exportlist_t ** ppexportlist)   /* Pointer to the export list */
02216 {
02217 
02218   int nb_blk, rc, i;
02219   char *blk_name;
02220   int err_flag = FALSE;
02221 
02222   exportlist_t *p_export_item = NULL;
02223   exportlist_t *p_export_last = NULL;
02224 
02225   int nb_entries = 0;
02226 
02227   if(!ppexportlist)
02228     return -EFAULT;
02229 
02230   *ppexportlist = NULL;
02231 
02232   /* get the number of blocks in the configuration file */
02233   nb_blk = config_GetNbBlocks(in_config);
02234 
02235   if(nb_blk < 0)
02236     return -1;
02237 
02238   /* Iteration on config file blocks. */
02239   for(i = 0; i < nb_blk; i++)
02240     {
02241       config_item_t block;
02242 
02243       block = config_GetBlockByIndex(in_config, i);
02244 
02245       if(block == NULL)
02246         return -1;
02247 
02248       /* get the name of the block */
02249       blk_name = config_GetBlockName(block);
02250 
02251       if(blk_name == NULL)
02252         return -1;
02253 
02254       if(!STRCMP(blk_name, CONF_LABEL_EXPORT))
02255         {
02256 
02257           rc = BuildExportEntry(block, &p_export_item);
02258 
02259           /* If the entry is errorneous, ignore it
02260            * and continue checking syntax of other entries.
02261            */
02262           if(rc != 0)
02263             {
02264               err_flag = TRUE;
02265               continue;
02266             }
02267 
02268           p_export_item->next = NULL;
02269 
02270           if(*ppexportlist == NULL)
02271             {
02272               *ppexportlist = p_export_item;
02273             }
02274           else
02275             {
02276               p_export_last->next = p_export_item;
02277             }
02278           p_export_last = p_export_item;
02279 
02280           nb_entries++;
02281 
02282         }
02283 
02284     }
02285 
02286   if(err_flag)
02287     {
02288       return -1;
02289     }
02290   else
02291     return nb_entries;
02292 }
02293 
02297 int export_client_match(sockaddr_t *hostaddr,
02298                         char *ipstring,
02299                         exportlist_client_t *clients,
02300                         exportlist_client_entry_t * pclient_found,
02301                         unsigned int export_option)
02302 {
02303   unsigned int i;
02304   int rc;
02305   char hostname[MAXHOSTNAMELEN];
02306   in_addr_t addr = get_in_addr(hostaddr);
02307 
02308   if(export_option & EXPORT_OPTION_ROOT)
02309     LogFullDebug(COMPONENT_DISPATCH,
02310                  "Looking for root access entries");
02311 
02312   if(export_option & EXPORT_OPTION_READ_ACCESS)
02313     LogFullDebug(COMPONENT_DISPATCH,
02314                   "Looking for nonroot access read entries");
02315 
02316   if(export_option & EXPORT_OPTION_WRITE_ACCESS)
02317     LogFullDebug(COMPONENT_DISPATCH,
02318                  "Looking for nonroot access write entries");
02319 
02320   for(i = 0; i < clients->num_clients; i++)
02321     {
02322       /* Make sure the client entry has the permission flags we're looking for
02323        * Also make sure we aren't looking at a root client entry when we're not root. */
02324       if(((clients->clientarray[i].options & export_option) == 0) ||
02325          ((clients->clientarray[i].options & EXPORT_OPTION_ROOT) != (export_option & EXPORT_OPTION_ROOT)))
02326         continue;
02327 
02328       switch (clients->clientarray[i].type)
02329         {
02330         case HOSTIF_CLIENT:
02331           if(clients->clientarray[i].client.hostif.clientaddr == addr)
02332             {
02333               LogFullDebug(COMPONENT_DISPATCH, "This matches host address");
02334               *pclient_found = clients->clientarray[i];
02335               return TRUE;
02336             }
02337           break;
02338 
02339         case NETWORK_CLIENT:
02340           LogDebug( COMPONENT_DISPATCH, "test NETWORK_CLIENT: addr=%#.08X, netmask=%#.08X, match with %#.08X",
02341                     clients->clientarray[i].client.network.netaddr,
02342                     clients->clientarray[i].client.network.netmask, ntohl(addr));
02343           LogFullDebug(COMPONENT_DISPATCH,
02344                        "Test net %d.%d.%d.%d in %d.%d.%d.%d ??",
02345                        (unsigned int)(clients->clientarray[i].client.network.netaddr >> 24),
02346                        (unsigned int)((clients->clientarray[i].client.network.netaddr >> 16) & 0xFF),
02347                        (unsigned int)((clients->clientarray[i].client.network.netaddr >> 8) & 0xFF),
02348                        (unsigned int)(clients->clientarray[i].client.network.netaddr & 0xFF),
02349                        (unsigned int)(addr >> 24),
02350                        (unsigned int)(addr >> 16) & 0xFF,
02351                        (unsigned int)(addr >> 8) & 0xFF,
02352                        (unsigned int)(addr & 0xFF));
02353 
02354           if((clients->clientarray[i].client.network.netmask & ntohl(addr)) ==
02355              clients->clientarray[i].client.network.netaddr)
02356             {
02357               LogFullDebug(COMPONENT_DISPATCH, "This matches network address");
02358               *pclient_found = clients->clientarray[i];
02359               return TRUE;
02360             }
02361           break;
02362 
02363         case NETGROUP_CLIENT:
02364           /* Try to get the entry from th IP/name cache */
02365           if((rc = nfs_ip_name_get(hostaddr, hostname)) != IP_NAME_SUCCESS)
02366             {
02367               if(rc == IP_NAME_NOT_FOUND)
02368                 {
02369                   /* IPaddr was not cached, add it to the cache */
02370                   if(nfs_ip_name_add(hostaddr, hostname) != IP_NAME_SUCCESS)
02371                     {
02372                       /* Major failure, name could not be resolved */
02373                       break;
02374                     }
02375                 }
02376             }
02377 
02378           /* At this point 'hostname' should contain the name that was found */
02379           if(innetgr
02380              (clients->clientarray[i].client.netgroup.netgroupname, hostname,
02381               NULL, NULL) == 1)
02382             {
02383               *pclient_found = clients->clientarray[i];
02384               return TRUE;
02385             }
02386           break;
02387 
02388         case WILDCARDHOST_CLIENT:
02389           /* Now checking for IP wildcards */
02390           if(fnmatch
02391              (clients->clientarray[i].client.wildcard.wildcard, ipstring,
02392               FNM_PATHNAME) == 0)
02393             {
02394               *pclient_found = clients->clientarray[i];
02395               return TRUE;
02396             }
02397 
02398           LogFullDebug(COMPONENT_DISPATCH,
02399                        "Did not match the ip address with a wildcard.");
02400 
02401           /* Try to get the entry from th IP/name cache */
02402           if((rc = nfs_ip_name_get(hostaddr, hostname)) != IP_NAME_SUCCESS)
02403             {
02404               if(rc == IP_NAME_NOT_FOUND)
02405                 {
02406                   /* IPaddr was not cached, add it to the cache */
02407                   if(nfs_ip_name_add(hostaddr, hostname) != IP_NAME_SUCCESS)
02408                     {
02409                       /* Major failure, name could not be resolved */
02410                       LogFullDebug(COMPONENT_DISPATCH,
02411                                    "Could not resolve hostame for addr %u.%u.%u.%u ... not checking if a hostname wildcard matches",
02412                                    (unsigned int)(addr & 0xFF),
02413                                    (unsigned int)(addr >> 8) & 0xFF,
02414                                    (unsigned int)(addr >> 16) & 0xFF,
02415                                    (unsigned int)(addr >> 24));
02416                       break;
02417                     }
02418                 }
02419             }
02420           LogFullDebug(COMPONENT_DISPATCH,
02421                        "Wildcarded hostname: testing if '%s' matches '%s'",
02422                        hostname, clients->clientarray[i].client.wildcard.wildcard);
02423 
02424           /* At this point 'hostname' should contain the name that was found */
02425           if(fnmatch
02426              (clients->clientarray[i].client.wildcard.wildcard, hostname,
02427               FNM_PATHNAME) == 0)
02428             {
02429               *pclient_found = clients->clientarray[i];
02430               return TRUE;
02431             }
02432           LogFullDebug(COMPONENT_DISPATCH, "'%s' not matching '%s'",
02433                        hostname, clients->clientarray[i].client.wildcard.wildcard);
02434           break;
02435 
02436         case GSSPRINCIPAL_CLIENT:
02438           LogFullDebug(COMPONENT_DISPATCH,
02439                        "----------> Unsupported type GSS_PRINCIPAL_CLIENT");
02440           return FALSE;
02441           break;
02442 
02443        case BAD_CLIENT:
02444           LogDebug(COMPONENT_DISPATCH,
02445                   "Bad client in position %u seen in export list", i );
02446           continue ;
02447 
02448         default:
02449            LogCrit(COMPONENT_DISPATCH,
02450                    "Unsupported client in position %u in export list with type %u", i, clients->clientarray[i].type);
02451            continue ;
02452         }                       /* switch */
02453     }                           /* for */
02454 
02455   /* no export found for this option */
02456   return FALSE;
02457 
02458 }                               /* export_client_match */
02459 
02460 int export_client_matchv6(struct in6_addr *paddrv6,
02461                           exportlist_client_t *clients,
02462                           exportlist_client_entry_t * pclient_found,
02463                           unsigned int export_option)
02464 {
02465   unsigned int i;
02466 
02467   if(export_option & EXPORT_OPTION_ROOT)
02468     LogFullDebug(COMPONENT_DISPATCH,
02469                  "Looking for root access entries");
02470 
02471   if(export_option & EXPORT_OPTION_READ_ACCESS)
02472     LogFullDebug(COMPONENT_DISPATCH,
02473                  "Looking for nonroot access read entries");
02474 
02475   if(export_option & EXPORT_OPTION_WRITE_ACCESS)
02476     LogFullDebug(COMPONENT_DISPATCH,
02477                  "Looking for nonroot access write entries");
02478 
02479   for(i = 0; i < clients->num_clients; i++)
02480     {
02481       /* Make sure the client entry has the permission flags we're looking for
02482        * Also make sure we aren't looking at a root client entry when we're not root. */
02483       if(((clients->clientarray[i].options & export_option) == 0) ||
02484          ((clients->clientarray[i].options & EXPORT_OPTION_ROOT) != (export_option & EXPORT_OPTION_ROOT)))
02485         continue;
02486 
02487       switch (clients->clientarray[i].type)
02488         {
02489         case HOSTIF_CLIENT:
02490         case NETWORK_CLIENT:
02491         case NETGROUP_CLIENT:
02492         case WILDCARDHOST_CLIENT:
02493         case GSSPRINCIPAL_CLIENT:
02494           break;
02495 
02496         case HOSTIF_CLIENT_V6:
02497           if(!memcmp(clients->clientarray[i].client.hostif.clientaddr6.s6_addr, paddrv6->s6_addr, 16))  /* Remember that IPv6 address are 128 bits = 16 bytes long */
02498             {
02499               LogFullDebug(COMPONENT_DISPATCH,
02500                            "This matches host adress in IPv6");
02501               *pclient_found = clients->clientarray[i];
02502               return TRUE;
02503             }
02504           break;
02505 
02506         default:
02507           return FALSE;         /* Should never occurs */
02508           break;
02509         }                       /* switch */
02510     }                           /* for */
02511 
02512   /* no export found for this option */
02513   return FALSE;
02514 }                               /* export_client_matchv6 */
02515 
02528 int nfs_export_check_security(struct svc_req *req, exportlist_t * pexport)
02529 {
02530   switch (req->rq_cred.oa_flavor)
02531     {
02532       case AUTH_NONE:
02533         if((pexport->options & EXPORT_OPTION_AUTH_NONE) == 0)
02534           {
02535             LogInfo(COMPONENT_DISPATCH,
02536                     "Export %s does not support AUTH_NONE",
02537                     pexport->dirname);
02538             return FALSE;
02539           }
02540         break;
02541 
02542       case AUTH_UNIX:
02543         if((pexport->options & EXPORT_OPTION_AUTH_UNIX) == 0)
02544           {
02545             LogInfo(COMPONENT_DISPATCH,
02546                     "Export %s does not support AUTH_UNIX",
02547                     pexport->dirname);
02548             return FALSE;
02549           }
02550         break;
02551 
02552 #ifdef _HAVE_GSSAPI
02553       case RPCSEC_GSS:
02554         if((pexport->options &
02555            (EXPORT_OPTION_RPCSEC_GSS_NONE |
02556             EXPORT_OPTION_RPCSEC_GSS_INTG |
02557             EXPORT_OPTION_RPCSEC_GSS_PRIV)) == 0)
02558           {
02559             LogInfo(COMPONENT_DISPATCH,
02560                     "Export %s does not support RPCSEC_GSS",
02561                     pexport->dirname);
02562             return FALSE;
02563           }
02564         else
02565           {
02566             struct svc_rpc_gss_data *gd;
02567             rpc_gss_svc_t svc;
02568             gd = SVCAUTH_PRIVATE(req->rq_xprt->xp_auth);
02569             svc = gd->sec.svc;
02570             LogFullDebug(COMPONENT_DISPATCH,
02571                          "Testing svc %d", (int) svc);
02572             switch(svc)
02573               {
02574                 case RPCSEC_GSS_SVC_NONE:
02575                   if((pexport->options &
02576                       EXPORT_OPTION_RPCSEC_GSS_NONE) == 0)
02577                     {
02578                       LogInfo(COMPONENT_DISPATCH,
02579                               "Export %s does not support "
02580                               "RPCSEC_GSS_SVC_NONE",
02581                               pexport->dirname);
02582                       return FALSE;
02583                     }
02584                   break;
02585 
02586                 case RPCSEC_GSS_SVC_INTEGRITY:
02587                   if((pexport->options &
02588                       EXPORT_OPTION_RPCSEC_GSS_INTG) == 0)
02589                     {
02590                       LogInfo(COMPONENT_DISPATCH,
02591                               "Export %s does not support "
02592                               "RPCSEC_GSS_SVC_INTEGRITY",
02593                               pexport->dirname);
02594                       return FALSE;
02595                     }
02596                   break;
02597 
02598                 case RPCSEC_GSS_SVC_PRIVACY:
02599                   if((pexport->options &
02600                       EXPORT_OPTION_RPCSEC_GSS_PRIV) == 0)
02601                     {
02602                       LogInfo(COMPONENT_DISPATCH,
02603                               "Export %s does not support "
02604                               "RPCSEC_GSS_SVC_PRIVACY",
02605                               pexport->dirname);
02606                       return FALSE;
02607                     }
02608                   break;
02609 
02610                   default:
02611                     LogInfo(COMPONENT_DISPATCH,
02612                             "Export %s does not support unknown "
02613                             "RPCSEC_GSS_SVC %d",
02614                             pexport->dirname, (int) svc);
02615                     return FALSE;
02616               }
02617           }
02618       break;
02619 #endif
02620       default:
02621         LogInfo(COMPONENT_DISPATCH,
02622                 "Export %s does not support unknown oa_flavor %d",
02623                 pexport->dirname, (int) req->rq_cred.oa_flavor);
02624         return FALSE;
02625     }
02626 
02627   return TRUE;
02628 }
02629 
02650 int nfs_export_check_access(sockaddr_t *hostaddr,
02651                             struct svc_req *ptr_req,
02652                             exportlist_t * pexport,
02653                             unsigned int nfs_prog,
02654                             unsigned int mnt_prog,
02655                             hash_table_t * ht_ip_stats,
02656                             pool_t *ip_stats_pool,
02657                             exportlist_client_entry_t * pclient_found,
02658                             struct user_cred *user_credentials,
02659                             bool_t proc_makes_write)
02660 {
02661   int rc;
02662   char ipstring[SOCK_NAME_MAX];
02663   int ipvalid;
02664 
02665   if (pexport != NULL)
02666     {
02667       if(proc_makes_write && (pexport->access_type == ACCESSTYPE_RO))
02668         return EXPORT_WRITE_ATTEMPT_WHEN_RO;
02669       else if(proc_makes_write && (pexport->access_type == ACCESSTYPE_MDONLY_RO))
02670         return EXPORT_WRITE_ATTEMPT_WHEN_MDONLY_RO;
02671     }
02672 
02673   ipstring[0] = '\0';
02674   ipvalid = sprint_sockip(hostaddr, ipstring, sizeof(ipstring));
02675   LogFullDebug(COMPONENT_DISPATCH,
02676                "nfs_export_check_access for address %s", ipstring);
02677 
02678   /* For now, no matching client is found */
02679   memset(pclient_found, 0, sizeof(exportlist_client_entry_t));
02680 
02681   /* PROC NULL is always authorized, in all protocols */
02682   if(ptr_req->rq_proc == 0)
02683     {
02684       LogFullDebug(COMPONENT_DISPATCH,
02685                    "Granted NULL proc");
02686       return EXPORT_PERMISSION_GRANTED;
02687     }
02688 
02689 #ifdef _USE_TIPRC_IPV6
02690   if(hostaddr->ss_family == AF_INET)
02691 #endif
02692     /* Increment the stats per client address (for IPv4 Only) */
02693     if((rc =
02694         nfs_ip_stats_incr(ht_ip_stats, hostaddr, nfs_prog, mnt_prog,
02695                           ptr_req)) == IP_STATS_NOT_FOUND)
02696       {
02697         if(nfs_ip_stats_add(ht_ip_stats, hostaddr, ip_stats_pool) ==
02698            IP_STATS_SUCCESS)
02699           rc = nfs_ip_stats_incr(ht_ip_stats, hostaddr, nfs_prog,
02700                                  mnt_prog, ptr_req);
02701       }
02702 
02703 #ifdef _USE_TIRPC_IPV6
02704   if(hostaddr->ss_family == AF_INET)
02705     {
02706 #endif                          /* _USE_TIRPC_IPV6 */
02707 
02708       /* Use IP address as a string for wild character access checks. */
02709       if(!ipvalid)
02710         {
02711           LogCrit(COMPONENT_DISPATCH,
02712                   "Could not convert the IPv4 address to a character string.");
02713           return EXPORT_PERMISSION_DENIED;
02714         }
02715 
02716       if(pexport == NULL)
02717         {
02718           LogCrit(COMPONENT_DISPATCH,
02719                   "Error: no export to verify permissions against.");
02720           return EXPORT_PERMISSION_DENIED;
02721         }
02722 
02723       /* check if any root access export matches this client */
02724       if(user_credentials->caller_uid == 0)
02725         {
02726           if(export_client_match(hostaddr,
02727                                  ipstring,
02728                                  &(pexport->clients),
02729                                  pclient_found,
02730                                  EXPORT_OPTION_ROOT))
02731             {
02732               if(pexport->access_type == ACCESSTYPE_MDONLY_RO ||
02733                  pexport->access_type == ACCESSTYPE_MDONLY)
02734                 {
02735                   LogFullDebug(COMPONENT_DISPATCH,
02736                                "Root granted MDONLY export permission");
02737                   return EXPORT_MDONLY_GRANTED;
02738                 }
02739               else
02740                 {
02741                   LogFullDebug(COMPONENT_DISPATCH,
02742                                "Root granted export permission");
02743                   return EXPORT_PERMISSION_GRANTED;
02744                 }
02745             }
02746         }
02747       /* else, check if any access only export matches this client */
02748       if(proc_makes_write)
02749         {
02750           if(export_client_match(hostaddr,
02751                                  ipstring,
02752                                  &(pexport->clients),
02753                                  pclient_found,
02754                                  EXPORT_OPTION_WRITE_ACCESS))
02755             {
02756               LogFullDebug(COMPONENT_DISPATCH,
02757                            "Write permission to export granted");
02758               return EXPORT_PERMISSION_GRANTED;
02759             }
02760           else if(pexport->new_access_list_version &&
02761                   export_client_match(hostaddr,
02762                                       ipstring,
02763                                       &(pexport->clients),
02764                                       pclient_found,
02765                                       EXPORT_OPTION_MD_WRITE_ACCESS))
02766             {
02767               pexport->access_type = ACCESSTYPE_MDONLY;
02768               LogFullDebug(COMPONENT_DISPATCH,
02769                            "MDONLY export permission granted");
02770               return EXPORT_MDONLY_GRANTED;
02771             }
02772         }
02773       else
02774         {
02775           /* request will not write anything */
02776           if(export_client_match(hostaddr,
02777                                  ipstring,
02778                                  &(pexport->clients),
02779                                  pclient_found,
02780                                  EXPORT_OPTION_READ_ACCESS))
02781             {
02782               if(pexport->access_type == ACCESSTYPE_MDONLY_RO ||
02783                  pexport->access_type == ACCESSTYPE_MDONLY)
02784                 {
02785                   LogFullDebug(COMPONENT_DISPATCH,
02786                                "MDONLY export permission granted - no write");
02787                   return EXPORT_MDONLY_GRANTED;
02788                 }
02789               else
02790                 {
02791                   LogFullDebug(COMPONENT_DISPATCH,
02792                                "Read export permission granted");
02793                   return EXPORT_PERMISSION_GRANTED;
02794                 }
02795             }
02796           else if(pexport->new_access_list_version &&
02797                   export_client_match(hostaddr,
02798                                       ipstring,
02799                                       &(pexport->clients),
02800                                       pclient_found,
02801                                       EXPORT_OPTION_MD_READ_ACCESS))
02802             {
02803               pexport->access_type = ACCESSTYPE_MDONLY_RO;
02804               LogFullDebug(COMPONENT_DISPATCH,
02805                            "MDONLY export permission granted new access list");
02806               return EXPORT_MDONLY_GRANTED;
02807             }
02808         }
02809       LogFullDebug(COMPONENT_DISPATCH,
02810                    "export permission denied");
02811       return EXPORT_PERMISSION_DENIED;
02812 
02813 #ifdef _USE_TIRPC_IPV6
02814     }
02815   else if(hostaddr->ss_family == AF_INET6)
02816     {
02817       static char ten_bytes_all_0[10];
02818       static unsigned two_bytes_all_1 = 0xFFFF;
02819       memset(ten_bytes_all_0, 0, 10);
02820       struct sockaddr_in6 *psockaddr_in6 = (struct sockaddr_in6 *)hostaddr;
02821 
02822       // if(isFulldebug(COMPONENT_DISPATCH))
02823         {
02824           char txtaddrv6[100];
02825 
02826           inet_ntop(psockaddr_in6->sin6_family,
02827                     psockaddr_in6->sin6_addr.s6_addr, txtaddrv6, 100);
02828           LogFullDebug(COMPONENT_DISPATCH,
02829                        "Client has IPv6 adress = %s", txtaddrv6);
02830         }
02831 
02832       /* If the client socket is IPv4, then it is wrapped into a   ::ffff:a.b.c.d IPv6 address. We check this here
02833        * This kind of adress is shaped like this:
02834        * |---------------------------------------------------------------|
02835        * |   80 bits = 10 bytes  | 16 bits = 2 bytes | 32 bits = 4 bytes |
02836        * |---------------------------------------------------------------|
02837        * |            0          |        FFFF       |    IPv4 address   |
02838        * |---------------------------------------------------------------|   */
02839       if(!memcmp(psockaddr_in6->sin6_addr.s6_addr, ten_bytes_all_0, 10) &&
02840          !memcmp((psockaddr_in6->sin6_addr.s6_addr + 10),
02841                  &two_bytes_all_1, 2))
02842         {
02843           /* Use IP address as a string for wild character access checks. */
02844           if(!ipvalid)
02845             {
02846               LogCrit(COMPONENT_DISPATCH,
02847                       "Error: Could not convert the IPv6 address to a character string.");
02848               return EXPORT_PERMISSION_DENIED;
02849             }
02850 
02851           /* This is an IPv4 address mapped to an IPv6 one. Extract the IPv4 address and proceed with IPv4 autentication */
02852           memcpy(&hostaddr, (psockaddr_in6->sin6_addr.s6_addr + 12), 4);
02853 
02854           /* Proceed with IPv4 dedicated function */
02855           /* check if any root access export matches this client */
02856           if((user_credentials->caller_uid == 0) &&
02857              export_client_match(hostaddr, ipstring, &(pexport->clients),
02858                                  pclient_found, EXPORT_OPTION_ROOT))
02859             return EXPORT_PERMISSION_GRANTED;
02860           /* else, check if any access only export matches this client */
02861           if(proc_makes_write)
02862             {
02863               if (export_client_match(hostaddr, ipstring, &(pexport->clients), pclient_found, EXPORT_OPTION_WRITE_ACCESS))
02864                 return EXPORT_PERMISSION_GRANTED;
02865               else if (pexport->new_access_list_version &&
02866                        export_client_match(hostaddr, ipstring,
02867                                            &(pexport->clients), pclient_found, EXPORT_OPTION_MD_WRITE_ACCESS))
02868                 {
02869                   pexport->access_type = ACCESSTYPE_MDONLY;
02870                   return EXPORT_MDONLY_GRANTED;
02871                 }
02872             } else { /* request will not write anything */
02873             if (export_client_match(hostaddr, ipstring, &(pexport->clients), pclient_found, EXPORT_OPTION_READ_ACCESS))
02874               return EXPORT_PERMISSION_GRANTED;
02875             else if (pexport->new_access_list_version &&
02876                      export_client_match(hostaddr, ipstring,
02877                                          &(pexport->clients), pclient_found, EXPORT_OPTION_MD_READ_ACCESS))
02878               {
02879                 pexport->access_type = ACCESSTYPE_MDONLY_RO;
02880                 return EXPORT_MDONLY_GRANTED;
02881               }
02882           }
02883         }
02884 
02885       if((user_credentials->caller_uid == 0) &&
02886          export_client_matchv6(&(psockaddr_in6->sin6_addr), &(pexport->clients),
02887                                pclient_found, EXPORT_OPTION_ROOT))
02888         return EXPORT_PERMISSION_GRANTED;
02889       /* else, check if any access only export matches this client */
02890       if(proc_makes_write)
02891         {
02892           if (export_client_matchv6(&(psockaddr_in6->sin6_addr), &(pexport->clients), pclient_found, EXPORT_OPTION_WRITE_ACCESS))
02893             return EXPORT_PERMISSION_GRANTED;
02894           else if (pexport->new_access_list_version && export_client_matchv6(&(psockaddr_in6->sin6_addr),
02895                                        &(pexport->clients), pclient_found, EXPORT_OPTION_MD_WRITE_ACCESS))
02896             {
02897               pexport->access_type = ACCESSTYPE_MDONLY;
02898               return EXPORT_MDONLY_GRANTED;
02899             }
02900         }
02901       else
02902         { /* request will not write anything */
02903           if (export_client_matchv6(&(psockaddr_in6->sin6_addr), &(pexport->clients), pclient_found, EXPORT_OPTION_READ_ACCESS))
02904             return EXPORT_PERMISSION_GRANTED;
02905           else if (pexport->new_access_list_version && export_client_matchv6(&(psockaddr_in6->sin6_addr),
02906                                          &(pexport->clients), pclient_found, EXPORT_OPTION_MD_READ_ACCESS))
02907             {
02908               pexport->access_type = ACCESSTYPE_MDONLY_RO;
02909               return EXPORT_MDONLY_GRANTED;
02910             }
02911         }
02912     }
02913 #endif                          /* _USE_TIRPC_IPV6 */
02914 
02915   /* If this point is reached, no matching entry was found */
02916   LogFullDebug(COMPONENT_DISPATCH,
02917                "export permission denied - no matching entry");
02918   return EXPORT_PERMISSION_DENIED;
02919 
02920 }                               /* nfs_export_check_access */
02921 
02933 int nfs_export_create_root_entry(exportlist_t * pexportlist)
02934 {
02935       exportlist_t *pcurrent = NULL;
02936       cache_inode_status_t cache_status;
02937 #ifdef _CRASH_RECOVERY_AT_STARTUP
02938       cache_content_status_t cache_content_status;
02939 #endif
02940       fsal_status_t fsal_status;
02941       cache_inode_fsal_data_t fsdata;
02942       fsal_handle_t fsal_handle;
02943       fsal_path_t exportpath_fsal;
02944       fsal_mdsize_t strsize = MNTPATHLEN + 1;
02945       cache_entry_t *pentry = NULL;
02946 
02947       fsal_op_context_t context;
02948       fsal_staticfsinfo_t *pstaticinfo = NULL;
02949       fsal_export_context_t *export_context = NULL;
02950 
02951       /* Get the context for FSAL super user */
02952       fsal_status = FSAL_InitClientContext(&context);
02953       if(FSAL_IS_ERROR(fsal_status))
02954         {
02955           LogCrit(COMPONENT_INIT,
02956                   "Couldn't get the context for FSAL super user");
02957           return FALSE;
02958         }
02959 
02960       /* loop the export list */
02961 
02962       for(pcurrent = pexportlist; pcurrent != NULL; pcurrent = pcurrent->next)
02963         {
02964 
02965           /* Build the FSAL path */
02966           if(FSAL_IS_ERROR((fsal_status = FSAL_str2path(pcurrent->fullpath,
02967                                                         strsize, &exportpath_fsal))))
02968             return FALSE;
02969 
02970           /* inits context for the current export entry */
02971 
02972           fsal_status =
02973               FSAL_BuildExportContext(&pcurrent->FS_export_context, &exportpath_fsal,
02974                                       pcurrent->FS_specific);
02975 
02976           if(FSAL_IS_ERROR(fsal_status))
02977             {
02978               LogCrit(COMPONENT_INIT,
02979                       "Couldn't build export context for %s",
02980                       pcurrent->fullpath);
02981               return FALSE;
02982             }
02983 
02984           /* get the related client context */
02985           fsal_status = FSAL_GetClientContext(&context, &pcurrent->FS_export_context, 0, 0, NULL, 0 ) ;
02986 
02987           if(FSAL_IS_ERROR(fsal_status))
02988             {
02989               LogCrit(COMPONENT_INIT,
02990                       "Couldn't get the credentials for FSAL super user");
02991               return FALSE;
02992             }
02993 
02994           /* Lookup for the FSAL Path */
02995           if(FSAL_IS_ERROR((fsal_status = FSAL_lookupPath(&exportpath_fsal, &context, &fsal_handle, NULL))))
02996             {
02997               LogCrit(COMPONENT_INIT,
02998                       "Couldn't access the root of the exported namespace, ExportId=%u Path=%s FSAL_ERROR=(%u,%u)",
02999                       pcurrent->id, pcurrent->fullpath, fsal_status.major,
03000                       fsal_status.minor);
03001               return FALSE;
03002             }
03003 
03004           /* stores handle to the export entry */
03005 
03006           pcurrent->proot_handle = gsh_malloc(sizeof(fsal_handle_t));
03007 
03008           if(FSAL_IS_ERROR(fsal_status))
03009             {
03010               LogCrit(COMPONENT_INIT,
03011                       "Couldn't allocate memory");
03012               return FALSE;
03013             }
03014 
03015           *pcurrent->proot_handle = fsal_handle;
03016           export_context = &pcurrent->FS_export_context;
03017           pstaticinfo = export_context->fe_static_fs_info;
03018           if( ((pcurrent->options & EXPORT_OPTION_MAXREAD) != EXPORT_OPTION_MAXREAD )) 
03019              {
03020                if ( pstaticinfo && pstaticinfo->maxread )
03021                   pcurrent->MaxRead = pstaticinfo->maxread;
03022                else
03023                   pcurrent->MaxRead = LASTDEFAULT;
03024              }
03025           if( ((pcurrent->options & EXPORT_OPTION_MAXWRITE) != EXPORT_OPTION_MAXWRITE )) 
03026              {
03027                if ( pstaticinfo && pstaticinfo->maxwrite )
03028                   pcurrent->MaxWrite = pstaticinfo->maxwrite;
03029                else
03030                   pcurrent->MaxWrite = LASTDEFAULT;
03031              }
03032           LogFullDebug(COMPONENT_INIT,
03033                       "Set MaxRead MaxWrite for Path=%s Options = 0x%x MaxRead = 0x%llX MaxWrite = 0x%llX",
03034                       pcurrent->fullpath, pcurrent->options,
03035                       (long long) pcurrent->MaxRead,
03036                       (long long) pcurrent->MaxWrite);
03037              
03038           /* Add this entry to the Cache Inode as a "root" entry */
03039           fsdata.fh_desc.start = (caddr_t) &fsal_handle;
03040           fsdata.fh_desc.len = 0;
03041           (void) FSAL_ExpandHandle(
03042 #ifdef _USE_SHARED_FSAL
03043                                    context[pcurrent->fsalid].export_context,
03044 #else
03045                                    context.export_context,
03046 #endif
03047                                    FSAL_DIGEST_SIZEOF,
03048                                    &fsdata.fh_desc);
03049 
03050           /* cache_inode_make_root returns a cache_entry with
03051              reference count of 2, where 1 is the sentinel value of
03052              a cache entry in the hash table.  The export list in
03053              this case owns the extra reference, but other users of
03054              cache_inode_make_root MUST put the entry.  In the future
03055              if functionality is added to dynamically add and remove
03056              export entries, then the function to remove an export
03057              entry MUST put the extra reference. */
03058 
03059           if((pentry = cache_inode_make_root(&fsdata,
03060                                              &context,
03061                                              &cache_status)) == NULL)
03062             {
03063               LogCrit(COMPONENT_INIT,
03064                       "Error when creating root cached entry for %s, export_id=%d, cache_status=%d",
03065                       pcurrent->fullpath, pcurrent->id, cache_status);
03066               return FALSE;
03067             }
03068           else
03069             LogInfo(COMPONENT_INIT,
03070                     "Added root entry for path %s on export_id=%d",
03071                     pcurrent->fullpath, pcurrent->id);
03072 
03073           /* Set the pentry as a referral if needed */
03074           if(strcmp(pcurrent->referral, ""))
03075             {
03076               /* Set the cache_entry object as a referral by setting the 'referral' field */
03077               pentry->object.dir.referral = pcurrent->referral;
03078               LogInfo(COMPONENT_INIT, "A referral is set : %s",
03079                       pentry->object.dir.referral);
03080             }
03081         }
03082 
03083   /* Note: As mentioned above, we are returning with an extra
03084      reference to the root entry.  This reference is owned by the
03085      export list.  If we ever have a function to remove objects from
03086      the export list, it must return this extra reference. */
03087 
03088   return TRUE;
03089 
03090 } /* nfs_export_create_root_entry */
03091 
03092 /* cleans up the export content */
03093 int CleanUpExportContext(fsal_export_context_t * p_export_context)
03094 {
03095 
03096   FSAL_CleanUpExportContext(p_export_context);
03097 
03098   return TRUE;
03099 }
03100 
03101 
03102 /* Frees current export entry and returns next export entry. */
03103 exportlist_t *RemoveExportEntry(exportlist_t * exportEntry)
03104 {
03105   exportlist_t *next;
03106 
03107   if (exportEntry == NULL)
03108     return NULL;
03109 
03110   next = exportEntry->next;
03111 
03112   if (exportEntry->proot_handle != NULL)
03113     gsh_free(exportEntry->proot_handle);
03114 
03115   if (exportEntry->worker_stats != NULL)
03116     gsh_free(exportEntry->worker_stats);
03117 
03118   gsh_free(exportEntry);
03119   return next;
03120 }
03121 
03122 exportlist_t *GetExportEntry(char *exportPath)
03123 {
03124   exportlist_t *pexport = NULL;
03125   exportlist_t *p_current_item = NULL;
03126   char tmplist_path[MAXPATHLEN];
03127   char tmpexport_path[MAXPATHLEN];
03128   int found = 0;
03129 
03130   pexport = nfs_param.pexportlist;
03131 
03132   /*
03133    * Find the export for the dirname (using as well Path or Tag )
03134    */
03135   for(p_current_item = pexport; p_current_item != NULL;
03136       p_current_item = p_current_item->next)
03137   {
03138     LogDebug(COMPONENT_CONFIG, "full path %s, export path %s",
03139              p_current_item->fullpath, exportPath);
03140 
03141     /* Make sure the path in export entry ends with a '/', if not adds one */
03142     if(p_current_item->fullpath[strlen(p_current_item->fullpath) - 1] == '/')
03143       strncpy(tmplist_path, p_current_item->fullpath, MAXPATHLEN);
03144     else
03145       snprintf(tmplist_path, MAXPATHLEN, "%s/", p_current_item->fullpath);
03146 
03147     /* Make sure that the argument from MNT ends with a '/', if not adds one */
03148     if(exportPath[strlen(exportPath) - 1] == '/')
03149       strncpy(tmpexport_path, exportPath, MAXPATHLEN);
03150     else
03151       snprintf(tmpexport_path, MAXPATHLEN, "%s/", exportPath);
03152 
03153     /* Is tmplist_path a subdirectory of tmpexport_path ? */
03154     if(!strncmp(tmplist_path, tmpexport_path, strlen(tmplist_path)))
03155     {
03156       found = 1;
03157       break;
03158     }
03159   }
03160 
03161   if(found)
03162     {
03163       LogDebug(COMPONENT_CONFIG, "returning export %s", p_current_item->fullpath);
03164       return p_current_item;
03165     }
03166   else
03167     {
03168       LogDebug(COMPONENT_CONFIG, "returning export NULL");
03169       return NULL;
03170     }
03171 }