Print this page
6198 Let's EOL cachefs


  80 #include <sys/sockio.h>
  81 #include <net/if.h>
  82 #include <rpcsvc/daemon_utils.h>
  83 #include <pwd.h>
  84 #include <strings.h>
  85 #include <tsol/label.h>
  86 #include <zone.h>
  87 #include <limits.h>
  88 #include <libscf.h>
  89 #include <libshare.h>
  90 #include "smfcfg.h"
  91 
  92 extern void set_nfsv4_ephemeral_mount_to(void);
  93 
  94 extern char *nfs_get_qop_name();
  95 extern AUTH *nfs_create_ah();
  96 extern enum snego_stat nfs_sec_nego();
  97 
  98 #define MAXHOSTS        512
  99 
 100 #define MNTTYPE_CACHEFS "cachefs"
 101 
 102 /*
 103  * host cache states
 104  */
 105 #define NOHOST          0
 106 #define GOODHOST        1
 107 #define DEADHOST        2
 108 
 109 #define NFS_ARGS_EXTB_secdata(args, secdata) \
 110         { (args).nfs_args_ext = NFS_ARGS_EXTB, \
 111         (args).nfs_ext_u.nfs_extB.secdata = secdata; }
 112 
 113 struct cache_entry {
 114         struct  cache_entry *cache_next;
 115         char    *cache_host;
 116         time_t  cache_time;
 117         int     cache_state;
 118         rpcvers_t cache_reqvers;
 119         rpcvers_t cache_outvers;
 120         char    *cache_proto;
 121 };
 122 
 123 struct mfs_snego_t {
 124         int sec_opt;
 125         bool_t snego_done;
 126         char *nfs_flavor;
 127         seconfig_t nfs_sec;
 128 };
 129 typedef struct mfs_snego_t mfs_snego_t;
 130 
 131 static struct cache_entry *cache_head = NULL;
 132 rwlock_t cache_lock;    /* protect the cache chain */
 133 
 134 static enum nfsstat nfsmount(struct mapfs *, char *, char *, int, int, uid_t,
 135         action_list *);
 136 static int is_nfs_port(char *);
 137 
 138 static void netbuf_free(struct netbuf *);
 139 static int get_pathconf(CLIENT *, char *, char *, struct pathcnf **, int);
 140 static struct mapfs *enum_servers(struct mapent *, char *);
 141 static struct mapfs *get_mysubnet_servers(struct mapfs *);
 142 static int subnet_test(int af, struct sioc_addrreq *);
 143 static  struct  netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
 144         struct netconfig **, char *, ushort_t, struct t_info *);
 145 
 146 static  struct  netbuf *get_pubfh(char *, rpcvers_t, mfs_snego_t *,
 147         struct netconfig **, char *, ushort_t, struct t_info *, caddr_t *,
 148         bool_t, char *);
 149 
 150 static int create_homedir(const char *, const char *);
 151 
 152 enum type_of_stuff {
 153         SERVER_ADDR = 0,
 154         SERVER_PING = 1,


 219  * list of support services needed
 220  */
 221 static char     *service_list[] = { STATD, LOCKD, NULL };
 222 static char     *service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL };
 223 
 224 static void read_default_nfs(void);
 225 static int is_v4_mount(char *);
 226 static void start_nfs4cbd(void);
 227 
 228 int
 229 mount_nfs(
 230         struct mapent *me,
 231         char *mntpnt,
 232         char *prevhost,
 233         int overlay,
 234         uid_t uid,
 235         action_list **alpp)
 236 {
 237         struct mapfs *mfs, *mp;
 238         int err = -1;
 239         int cached;
 240         action_list *alp;
 241         char *dir;
 242 
 243 
 244         alp = *alpp;
 245 
 246         read_default_nfs();
 247 
 248         mfs = enum_servers(me, prevhost);
 249         if (mfs == NULL)
 250                 return (ENOENT);
 251 
 252         /*
 253          * Try loopback if we have something on localhost; if nothing
 254          * works, we will fall back to NFS
 255          */
 256         if (is_nfs_port(me->map_mntopts)) {
 257                 for (mp = mfs; mp; mp = mp->mfs_next) {
 258                         if (self_check(mp->mfs_host)) {
 259                                 err = loopbackmount(mp->mfs_dir,


 261                                 if (err) {
 262                                         mp->mfs_ignore = 1;
 263                                 } else {
 264                                         /*
 265                                          * Free action_list if there
 266                                          * is one as it is not needed.
 267                                          * Make sure to set alpp to null
 268                                          * so caller doesn't try to free it
 269                                          * again.
 270                                          */
 271                                         if (*alpp) {
 272                                                 free(*alpp);
 273                                                 *alpp = NULL;
 274                                         }
 275                                         break;
 276                                 }
 277                         }
 278                 }
 279         }
 280         if (err) {
 281                 cached = strcmp(me->map_mounter, MNTTYPE_CACHEFS) == 0;
 282                 dir = strdup(mfs->mfs_dir);
 283                 err = nfsmount(mfs, mntpnt, me->map_mntopts,
 284                     cached, overlay, uid, alp);
 285                 if (err && trace > 1) {
 286                         trace_prt(1, "  Couldn't mount %s:%s, err=%d\n",
 287                             mfs->mfs_host ? mfs->mfs_host : "",
 288                             mfs->mfs_dir ? mfs->mfs_dir : dir, err);
 289                 }
 290                 free(dir);
 291         }
 292         free_mfs(mfs);
 293         return (err);
 294 }
 295 
 296 
 297 /*
 298  * Using the new ioctl SIOCTONLINK to determine if a host is on the same
 299  * subnet. Remove the old network, subnet check.
 300  */
 301 
 302 static struct mapfs *
 303 get_mysubnet_servers(struct mapfs *mfs_in)
 304 {


 622         if (m1)
 623                 free_mfs(m1);
 624         m1 = m2;
 625         for (m2 = m1; m2; m2 = m2->mfs_next) {
 626                 p = add_mfs(m2, DIST_OTHER, &mfs_head, &mfs_tail);
 627                 if (!p)
 628                         return (NULL);
 629         }
 630         if (m1)
 631                 free_mfs(m1);
 632 
 633 done:
 634         dump_mfs(mfs_head, "  enum_servers: output: ", 1);
 635         return (mfs_head);
 636 }
 637 
 638 static enum nfsstat
 639 nfsmount(
 640         struct mapfs *mfs_in,
 641         char *mntpnt, char *opts,
 642         int cached, int overlay,
 643         uid_t uid,
 644         action_list *alp)
 645 {
 646         CLIENT *cl;
 647         char remname[MAXPATHLEN], *mnttabtext = NULL;
 648         char mopts[MAX_MNTOPT_STR];
 649         char netname[MAXNETNAMELEN+1];
 650         char    *mntopts = NULL;
 651         int mnttabcnt = 0;
 652         int loglevel;
 653         struct mnttab m;
 654         struct nfs_args *argp = NULL, *head = NULL, *tail = NULL,
 655             *prevhead, *prevtail;
 656         int flags;
 657         struct fhstatus fhs;
 658         struct timeval timeout;
 659         enum clnt_stat rpc_stat;
 660         enum nfsstat status;
 661         struct stat stbuf;
 662         struct netconfig *nconf;


 698         ushort_t thisport;
 699         int got_val;
 700         mfs_snego_t mfssnego_init, mfssnego;
 701 
 702         dump_mfs(mfs_in, "  nfsmount: input: ", 2);
 703         replicated = (mfs_in->mfs_next != NULL);
 704         m.mnt_mntopts = opts;
 705         if (replicated && hasmntopt(&m, MNTOPT_SOFT)) {
 706                 if (verbose)
 707                         syslog(LOG_WARNING,
 708                     "mount on %s is soft and will not be replicated.", mntpnt);
 709                 replicated = 0;
 710         }
 711         if (replicated && !hasmntopt(&m, MNTOPT_RO)) {
 712                 if (verbose)
 713                         syslog(LOG_WARNING,
 714                     "mount on %s is not read-only and will not be replicated.",
 715                             mntpnt);
 716                 replicated = 0;
 717         }
 718         if (replicated && cached) {
 719                 if (verbose)
 720                         syslog(LOG_WARNING,
 721                     "mount on %s is cached and will not be replicated.",
 722                             mntpnt);
 723                 replicated = 0;
 724         }
 725         if (replicated)
 726                 loglevel = LOG_WARNING;
 727         else
 728                 loglevel = LOG_ERR;
 729 
 730         if (trace > 1) {
 731                 if (replicated)
 732                         trace_prt(1, "  nfsmount: replicated mount on %s %s:\n",
 733                             mntpnt, opts);
 734                 else
 735                         trace_prt(1, "  nfsmount: standard mount on %s %s:\n",
 736                             mntpnt, opts);
 737                 for (mfs = mfs_in; mfs; mfs = mfs->mfs_next)
 738                         trace_prt(1, "    %s:%s\n",
 739                             mfs->mfs_host, mfs->mfs_dir);
 740         }
 741 
 742         /*
 743          * Make sure mountpoint is safe to mount on
 744          */


1163                 host = mfs->mfs_host;
1164                 dir = mfs->mfs_dir;
1165 
1166                 /*
1167                  * Remember the possible '[a:d:d:r:e:s:s]' as the address to be
1168                  * later passed to mount(2) and used in the mnttab line, but
1169                  * only use 'a:d:d:r:e:s:s' for communication
1170                  */
1171                 rhost = strdup(host);
1172                 if (rhost == NULL) {
1173                         syslog(LOG_ERR, "nfsmount: no memory");
1174                         last_error = NFSERR_IO;
1175                         goto out;
1176                 }
1177                 unbracket(&host);
1178 
1179                 (void) sprintf(remname, "%s:%s", rhost, dir);
1180                 if (trace > 4 && replicated)
1181                         trace_prt(1, "  nfsmount: examining %s\n", remname);
1182 
1183                 /*
1184                  * If it's cached we need to get cachefs to mount it.
1185                  */
1186                 if (cached) {
1187                         char *copts = opts;
1188 
1189                         /*
1190                          * If we started with a URL we need to turn on
1191                          * -o public if not on already
1192                          */
1193                         if (use_pubfh == FALSE &&
1194                             (mfs->mfs_flags & MFS_FH_VIA_WEBNFS)) {
1195 
1196                                 copts = malloc(strlen(opts) +
1197                                     strlen(",public")+1);
1198 
1199                                 if (copts == NULL) {
1200                                         syslog(LOG_ERR, "nfsmount: no memory");
1201                                         last_error = NFSERR_IO;
1202                                         goto out;
1203                                 }
1204 
1205                                 strcpy(copts, opts);
1206 
1207                                 if (strlen(copts) != 0)
1208                                         strcat(copts, ",");
1209 
1210                                 strcat(copts, "public");
1211                         }
1212 
1213                         last_error = mount_generic(remname, MNTTYPE_CACHEFS,
1214                             copts, mntpnt, overlay);
1215 
1216                         if (copts != opts)
1217                                 free(copts);
1218 
1219                         if (last_error) {
1220                                 skipentry = 1;
1221                                 mfs->mfs_ignore = 1;
1222                                 continue;
1223                         }
1224                         goto out;
1225                 }
1226 
1227                 if (mfs->mfs_args == NULL) {
1228 
1229                         /*
1230                          * Allocate nfs_args structure
1231                          */
1232                         argp = (struct nfs_args *)
1233                             malloc(sizeof (struct nfs_args));
1234 
1235                         if (!argp) {
1236                                 syslog(LOG_ERR, "nfsmount: no memory");
1237                                 last_error = NFSERR_IO;
1238                                 goto out;
1239                         }
1240 
1241                         (void) memset(argp, 0, sizeof (*argp));
1242 
1243                         /*
1244                          * RDMA support
1245                          * By now Mount argument struct has been allocated,
1246                          * either a pub_fh path will be taken or the regular




  80 #include <sys/sockio.h>
  81 #include <net/if.h>
  82 #include <rpcsvc/daemon_utils.h>
  83 #include <pwd.h>
  84 #include <strings.h>
  85 #include <tsol/label.h>
  86 #include <zone.h>
  87 #include <limits.h>
  88 #include <libscf.h>
  89 #include <libshare.h>
  90 #include "smfcfg.h"
  91 
  92 extern void set_nfsv4_ephemeral_mount_to(void);
  93 
  94 extern char *nfs_get_qop_name();
  95 extern AUTH *nfs_create_ah();
  96 extern enum snego_stat nfs_sec_nego();
  97 
  98 #define MAXHOSTS        512
  99 


 100 /*
 101  * host cache states
 102  */
 103 #define NOHOST          0
 104 #define GOODHOST        1
 105 #define DEADHOST        2
 106 
 107 #define NFS_ARGS_EXTB_secdata(args, secdata) \
 108         { (args).nfs_args_ext = NFS_ARGS_EXTB, \
 109         (args).nfs_ext_u.nfs_extB.secdata = secdata; }
 110 
 111 struct cache_entry {
 112         struct  cache_entry *cache_next;
 113         char    *cache_host;
 114         time_t  cache_time;
 115         int     cache_state;
 116         rpcvers_t cache_reqvers;
 117         rpcvers_t cache_outvers;
 118         char    *cache_proto;
 119 };
 120 
 121 struct mfs_snego_t {
 122         int sec_opt;
 123         bool_t snego_done;
 124         char *nfs_flavor;
 125         seconfig_t nfs_sec;
 126 };
 127 typedef struct mfs_snego_t mfs_snego_t;
 128 
 129 static struct cache_entry *cache_head = NULL;
 130 rwlock_t cache_lock;    /* protect the cache chain */
 131 
 132 static enum nfsstat nfsmount(struct mapfs *, char *, char *, int, uid_t,
 133         action_list *);
 134 static int is_nfs_port(char *);
 135 
 136 static void netbuf_free(struct netbuf *);
 137 static int get_pathconf(CLIENT *, char *, char *, struct pathcnf **, int);
 138 static struct mapfs *enum_servers(struct mapent *, char *);
 139 static struct mapfs *get_mysubnet_servers(struct mapfs *);
 140 static int subnet_test(int af, struct sioc_addrreq *);
 141 static  struct  netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
 142         struct netconfig **, char *, ushort_t, struct t_info *);
 143 
 144 static  struct  netbuf *get_pubfh(char *, rpcvers_t, mfs_snego_t *,
 145         struct netconfig **, char *, ushort_t, struct t_info *, caddr_t *,
 146         bool_t, char *);
 147 
 148 static int create_homedir(const char *, const char *);
 149 
 150 enum type_of_stuff {
 151         SERVER_ADDR = 0,
 152         SERVER_PING = 1,


 217  * list of support services needed
 218  */
 219 static char     *service_list[] = { STATD, LOCKD, NULL };
 220 static char     *service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL };
 221 
 222 static void read_default_nfs(void);
 223 static int is_v4_mount(char *);
 224 static void start_nfs4cbd(void);
 225 
 226 int
 227 mount_nfs(
 228         struct mapent *me,
 229         char *mntpnt,
 230         char *prevhost,
 231         int overlay,
 232         uid_t uid,
 233         action_list **alpp)
 234 {
 235         struct mapfs *mfs, *mp;
 236         int err = -1;

 237         action_list *alp;
 238         char *dir;
 239 
 240 
 241         alp = *alpp;
 242 
 243         read_default_nfs();
 244 
 245         mfs = enum_servers(me, prevhost);
 246         if (mfs == NULL)
 247                 return (ENOENT);
 248 
 249         /*
 250          * Try loopback if we have something on localhost; if nothing
 251          * works, we will fall back to NFS
 252          */
 253         if (is_nfs_port(me->map_mntopts)) {
 254                 for (mp = mfs; mp; mp = mp->mfs_next) {
 255                         if (self_check(mp->mfs_host)) {
 256                                 err = loopbackmount(mp->mfs_dir,


 258                                 if (err) {
 259                                         mp->mfs_ignore = 1;
 260                                 } else {
 261                                         /*
 262                                          * Free action_list if there
 263                                          * is one as it is not needed.
 264                                          * Make sure to set alpp to null
 265                                          * so caller doesn't try to free it
 266                                          * again.
 267                                          */
 268                                         if (*alpp) {
 269                                                 free(*alpp);
 270                                                 *alpp = NULL;
 271                                         }
 272                                         break;
 273                                 }
 274                         }
 275                 }
 276         }
 277         if (err) {

 278                 dir = strdup(mfs->mfs_dir);
 279                 err = nfsmount(mfs, mntpnt, me->map_mntopts,
 280                     overlay, uid, alp);
 281                 if (err && trace > 1) {
 282                         trace_prt(1, "  Couldn't mount %s:%s, err=%d\n",
 283                             mfs->mfs_host ? mfs->mfs_host : "",
 284                             mfs->mfs_dir ? mfs->mfs_dir : dir, err);
 285                 }
 286                 free(dir);
 287         }
 288         free_mfs(mfs);
 289         return (err);
 290 }
 291 
 292 
 293 /*
 294  * Using the new ioctl SIOCTONLINK to determine if a host is on the same
 295  * subnet. Remove the old network, subnet check.
 296  */
 297 
 298 static struct mapfs *
 299 get_mysubnet_servers(struct mapfs *mfs_in)
 300 {


 618         if (m1)
 619                 free_mfs(m1);
 620         m1 = m2;
 621         for (m2 = m1; m2; m2 = m2->mfs_next) {
 622                 p = add_mfs(m2, DIST_OTHER, &mfs_head, &mfs_tail);
 623                 if (!p)
 624                         return (NULL);
 625         }
 626         if (m1)
 627                 free_mfs(m1);
 628 
 629 done:
 630         dump_mfs(mfs_head, "  enum_servers: output: ", 1);
 631         return (mfs_head);
 632 }
 633 
 634 static enum nfsstat
 635 nfsmount(
 636         struct mapfs *mfs_in,
 637         char *mntpnt, char *opts,
 638         int overlay,
 639         uid_t uid,
 640         action_list *alp)
 641 {
 642         CLIENT *cl;
 643         char remname[MAXPATHLEN], *mnttabtext = NULL;
 644         char mopts[MAX_MNTOPT_STR];
 645         char netname[MAXNETNAMELEN+1];
 646         char    *mntopts = NULL;
 647         int mnttabcnt = 0;
 648         int loglevel;
 649         struct mnttab m;
 650         struct nfs_args *argp = NULL, *head = NULL, *tail = NULL,
 651             *prevhead, *prevtail;
 652         int flags;
 653         struct fhstatus fhs;
 654         struct timeval timeout;
 655         enum clnt_stat rpc_stat;
 656         enum nfsstat status;
 657         struct stat stbuf;
 658         struct netconfig *nconf;


 694         ushort_t thisport;
 695         int got_val;
 696         mfs_snego_t mfssnego_init, mfssnego;
 697 
 698         dump_mfs(mfs_in, "  nfsmount: input: ", 2);
 699         replicated = (mfs_in->mfs_next != NULL);
 700         m.mnt_mntopts = opts;
 701         if (replicated && hasmntopt(&m, MNTOPT_SOFT)) {
 702                 if (verbose)
 703                         syslog(LOG_WARNING,
 704                     "mount on %s is soft and will not be replicated.", mntpnt);
 705                 replicated = 0;
 706         }
 707         if (replicated && !hasmntopt(&m, MNTOPT_RO)) {
 708                 if (verbose)
 709                         syslog(LOG_WARNING,
 710                     "mount on %s is not read-only and will not be replicated.",
 711                             mntpnt);
 712                 replicated = 0;
 713         }







 714         if (replicated)
 715                 loglevel = LOG_WARNING;
 716         else
 717                 loglevel = LOG_ERR;
 718 
 719         if (trace > 1) {
 720                 if (replicated)
 721                         trace_prt(1, "  nfsmount: replicated mount on %s %s:\n",
 722                             mntpnt, opts);
 723                 else
 724                         trace_prt(1, "  nfsmount: standard mount on %s %s:\n",
 725                             mntpnt, opts);
 726                 for (mfs = mfs_in; mfs; mfs = mfs->mfs_next)
 727                         trace_prt(1, "    %s:%s\n",
 728                             mfs->mfs_host, mfs->mfs_dir);
 729         }
 730 
 731         /*
 732          * Make sure mountpoint is safe to mount on
 733          */


1152                 host = mfs->mfs_host;
1153                 dir = mfs->mfs_dir;
1154 
1155                 /*
1156                  * Remember the possible '[a:d:d:r:e:s:s]' as the address to be
1157                  * later passed to mount(2) and used in the mnttab line, but
1158                  * only use 'a:d:d:r:e:s:s' for communication
1159                  */
1160                 rhost = strdup(host);
1161                 if (rhost == NULL) {
1162                         syslog(LOG_ERR, "nfsmount: no memory");
1163                         last_error = NFSERR_IO;
1164                         goto out;
1165                 }
1166                 unbracket(&host);
1167 
1168                 (void) sprintf(remname, "%s:%s", rhost, dir);
1169                 if (trace > 4 && replicated)
1170                         trace_prt(1, "  nfsmount: examining %s\n", remname);
1171 












































1172                 if (mfs->mfs_args == NULL) {
1173 
1174                         /*
1175                          * Allocate nfs_args structure
1176                          */
1177                         argp = (struct nfs_args *)
1178                             malloc(sizeof (struct nfs_args));
1179 
1180                         if (!argp) {
1181                                 syslog(LOG_ERR, "nfsmount: no memory");
1182                                 last_error = NFSERR_IO;
1183                                 goto out;
1184                         }
1185 
1186                         (void) memset(argp, 0, sizeof (*argp));
1187 
1188                         /*
1189                          * RDMA support
1190                          * By now Mount argument struct has been allocated,
1191                          * either a pub_fh path will be taken or the regular