]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/nfs4mount.c
umount.nfs: move nfs_call_umount to network.c
[nfs-utils.git] / utils / mount / nfs4mount.c
index b59c27cc319e0d27fd9fcde1dad863ee3fa3bab6..26a6896855db4c5bc4e959ab80fcb28e7f46eebf 100644 (file)
@@ -25,6 +25,7 @@
 #include <netdb.h>
 #include <time.h>
 #include <sys/stat.h>
+#include <sys/mount.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <rpc/auth.h>
 #define nfsstat nfs_stat
 #endif
 
+#include "pseudoflavors.h"
 #include "nls.h"
 #include "conn.h"
 #include "xcommon.h"
 
+#include "mount_constants.h"
 #include "nfs4_mount.h"
 #include "nfs_mount.h"
+#include "error.h"
 
 #if defined(VAR_LOCK_DIR)
 #define DEFAULT_DIR VAR_LOCK_DIR
@@ -49,7 +53,9 @@
 #define DEFAULT_DIR "/var/lock/subsys"
 #endif
 
+extern char *progname;
 extern int verbose;
+extern int sloppy;
 
 char *IDMAPLCK = DEFAULT_DIR "/rpcidmapd";
 #define idmapd_check() do { \
@@ -64,32 +70,12 @@ char *GSSDLCK = DEFAULT_DIR "/rpcgssd";
                if (access(GSSDLCK, F_OK)) { \
                        printf(_("Warning: rpc.gssd appears not to be running.\n")); \
                } \
-} while(0); 
+} while(0);
 
 #ifndef NFS_PORT
 #define NFS_PORT 2049
 #endif
 
-struct {
-       char    *flavour;
-       int     fnum;
-} flav_map[] = {
-       { "krb5",       RPC_AUTH_GSS_KRB5       },
-       { "krb5i",      RPC_AUTH_GSS_KRB5I      },
-       { "krb5p",      RPC_AUTH_GSS_KRB5P      },
-       { "lipkey",     RPC_AUTH_GSS_LKEY       },
-       { "lipkey-i",   RPC_AUTH_GSS_LKEYI      },
-       { "lipkey-p",   RPC_AUTH_GSS_LKEYP      },
-       { "spkm3",      RPC_AUTH_GSS_SPKM       },
-       { "spkm3i",     RPC_AUTH_GSS_SPKMI      },
-       { "spkm3p",     RPC_AUTH_GSS_SPKMP      },
-       { "unix",       AUTH_UNIX               },
-       { "sys",        AUTH_SYS                },
-       { "null",       AUTH_NULL               },
-       { "none",       AUTH_NONE               },
-};
-
-#define FMAPSIZE               (sizeof(flav_map)/sizeof(flav_map[0]))
 #define MAX_USER_FLAVOUR       16
 
 static int parse_sec(char *sec, int *pseudoflavour)
@@ -98,26 +84,25 @@ static int parse_sec(char *sec, int *pseudoflavour)
 
        for (sec = strtok(sec, ":"); sec; sec = strtok(NULL, ":")) {
                if (num_flavour >= MAX_USER_FLAVOUR) {
-                       fprintf(stderr,
-                               _("mount: maximum number of security flavors "
-                                 "exceeded\n"));
+                       nfs_error(_("%s: maximum number of security flavors "
+                                 "exceeded"), progname);
                        return 0;
                }
-               for (i = 0; i < FMAPSIZE; i++) {
+               for (i = 0; i < flav_map_size; i++) {
                        if (strcmp(sec, flav_map[i].flavour) == 0) {
                                pseudoflavour[num_flavour++] = flav_map[i].fnum;
                                break;
                        }
                }
-               if (i == FMAPSIZE) {
-                       fprintf(stderr,
-                               _("mount: unknown security type %s\n"), sec);
+               if (i == flav_map_size) {
+                       nfs_error(_("%s: unknown security type %s\n"),
+                                       progname, sec);
                        return 0;
                }
        }
        if (!num_flavour)
-               fprintf(stderr,
-                       _("mount: no security flavors passed to sec= option\n"));
+               nfs_error(_("%s: no security flavors passed to sec= option"),
+                               progname);
        return num_flavour;
 }
 
@@ -126,9 +111,8 @@ static int parse_devname(char *hostdir, char **hostname, char **dirname)
        char *s;
 
        if (!(s = strchr(hostdir, ':'))) {
-               fprintf(stderr,
-                       _("mount: "
-                         "directory to mount not in host:dir format\n"));
+               nfs_error(_("%s: directory to mount not in host:dir format"),
+                               progname);
                return -1;
        }
        *hostname = hostdir;
@@ -138,9 +122,8 @@ static int parse_devname(char *hostdir, char **hostname, char **dirname)
           until they can be fully supported. (mack@sgi.com) */
        if ((s = strchr(hostdir, ','))) {
                *s = '\0';
-               fprintf(stderr,
-                       _("mount: warning: "
-                         "multiple hostnames not supported\n"));
+               nfs_error(_("%s: warning: multiple hostnames not supported"),
+                               progname);
        }
        return 0;
 }
@@ -153,13 +136,12 @@ static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
        if (inet_aton(hostname, &addr->sin_addr))
                return 0;
        if ((hp = gethostbyname(hostname)) == NULL) {
-               fprintf(stderr, _("mount: can't get address for %s\n"),
-                       hostname);
+               nfs_error(_("%s: can't get address for %s\n"),
+                               progname, hostname);
                return -1;
        }
        if (hp->h_length > sizeof(struct in_addr)) {
-               fprintf(stderr,
-                       _("mount: got bad hp->h_length\n"));
+               nfs_error(_("%s: got bad hp->h_length"), progname);
                hp->h_length = sizeof(struct in_addr);
        }
        memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
@@ -172,7 +154,8 @@ static int get_my_ipv4addr(char *ip_addr, int len)
        struct sockaddr_in myaddr;
 
        if (gethostname(myname, sizeof(myname))) {
-               fprintf(stderr, _("mount: can't determine client address\n"));
+               nfs_error(_("%s: can't determine client address\n"),
+                               progname);
                return -1;
        }
        if (fill_ipv4_sockaddr(myname, &myaddr))
@@ -182,16 +165,16 @@ static int get_my_ipv4addr(char *ip_addr, int len)
        return 0;
 }
 
-int nfs4mount(const char *spec, const char *node, int *flags,
-             char **extra_opts, char **mount_opts,
-             int running_bg)
+int nfs4mount(const char *spec, const char *node, int flags,
+             char **extra_opts, int fake)
 {
        static struct nfs4_mount_data data;
        static char hostdir[1024];
        static char ip_addr[16] = "127.0.0.1";
-       static struct sockaddr_in server_addr;
+       static struct sockaddr_in server_addr, client_addr;
        static int pseudoflavour[MAX_USER_FLAVOUR];
        int num_flavour = 0;
+       int ip_addr_in_opts = 0;
 
        char *hostname, *dirname, *old_opts;
        char new_opts[1024];
@@ -199,15 +182,15 @@ int nfs4mount(const char *spec, const char *node, int *flags,
        char *s;
        int val;
        int bg, soft, intr;
-       int nocto, noac;
+       int nocto, noac, unshared;
        int retry;
        int retval;
        time_t timeout, t;
 
        retval = EX_FAIL;
        if (strlen(spec) >= sizeof(hostdir)) {
-               fprintf(stderr, _("mount: "
-                                 "excessively long host:dir argument\n"));
+               nfs_error(_("%s: excessively long host:dir argument\n"),
+                               progname);
                goto fail;
        }
        strcpy(hostdir, spec);
@@ -225,8 +208,8 @@ int nfs4mount(const char *spec, const char *node, int *flags,
        if (!old_opts)
                old_opts = "";
        if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
-               fprintf(stderr, _("mount: "
-                                 "excessively long option argument\n"));
+               nfs_error(_("%s: excessively long option argument\n"),
+                               progname);
                goto fail;
        }
        snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
@@ -250,6 +233,7 @@ int nfs4mount(const char *spec, const char *node, int *flags,
        intr = NFS4_MOUNT_INTR;
        nocto = 0;
        noac = 0;
+       unshared = 0;
        retry = 10000;          /* 10000 minutes ~ 1 week */
 
        /*
@@ -302,11 +286,12 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                                                                opteq+1);
                                strncpy(ip_addr,opteq+1, sizeof(ip_addr));
                                ip_addr[sizeof(ip_addr)-1] = '\0';
+                               ip_addr_in_opts = 1;
                        } else if (!strcmp(opt, "sec")) {
                                num_flavour = parse_sec(opteq+1, pseudoflavour);
                                if (!num_flavour)
                                        goto fail;
-                       } else if (!strcmp(opt, "addr")) {
+                       } else if (!strcmp(opt, "addr") || sloppy) {
                                /* ignore */;
                        } else {
                                printf(_("unknown nfs mount parameter: "
@@ -319,9 +304,9 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                                val = 0;
                                opt += 2;
                        }
-                       if (!strcmp(opt, "bg")) 
+                       if (!strcmp(opt, "bg"))
                                bg = val;
-                       else if (!strcmp(opt, "fg")) 
+                       else if (!strcmp(opt, "fg"))
                                bg = !val;
                        else if (!strcmp(opt, "soft"))
                                soft = val;
@@ -333,7 +318,9 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                                nocto = !val;
                        else if (!strcmp(opt, "ac"))
                                noac = !val;
-                       else {
+                       else if (!strcmp(opt, "sharecache"))
+                               unshared = !val;
+                       else if (!sloppy) {
                                printf(_("unknown nfs mount option: "
                                         "%s%s\n"), val ? "" : "no", opt);
                                goto fail;
@@ -344,11 +331,16 @@ int nfs4mount(const char *spec, const char *node, int *flags,
        data.flags = (soft ? NFS4_MOUNT_SOFT : 0)
                | (intr ? NFS4_MOUNT_INTR : 0)
                | (nocto ? NFS4_MOUNT_NOCTO : 0)
-               | (noac ? NFS4_MOUNT_NOAC : 0);
+               | (noac ? NFS4_MOUNT_NOAC : 0)
+               | (unshared ? NFS4_MOUNT_UNSHARED : 0);
 
        /*
         * Give a warning if the rpc.idmapd daemon is not running
         */
+#if 0
+       /* We shouldn't have these checks as nothing in this package
+        * creates the files that are checked
+        */
        idmapd_check();
 
        if (num_flavour == 0)
@@ -359,6 +351,7 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                 */
                gssd_check();
        }
+#endif
        data.auth_flavourlen = num_flavour;
        data.auth_flavours = pseudoflavour;
 
@@ -380,18 +373,20 @@ int nfs4mount(const char *spec, const char *node, int *flags,
               data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
        printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
               ntohs(server_addr.sin_port), bg, retry, data.flags);
-       printf("soft = %d, intr = %d, nocto = %d, noac = %d\n",
+       printf("soft = %d, intr = %d, nocto = %d, noac = %d, "
+              "nosharecache = %d\n",
               (data.flags & NFS4_MOUNT_SOFT) != 0,
               (data.flags & NFS4_MOUNT_INTR) != 0,
               (data.flags & NFS4_MOUNT_NOCTO) != 0,
-              (data.flags & NFS4_MOUNT_NOAC) != 0);
+              (data.flags & NFS4_MOUNT_NOAC) != 0,
+              (data.flags & NFS4_MOUNT_UNSHARED) != 0);
 
        if (num_flavour > 0) {
                int pf_cnt, i;
 
                printf("sec = ");
                for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) {
-                       for (i = 0; i < FMAPSIZE; i++) {
+                       for (i = 0; i < flav_map_size; i++) {
                                if (flav_map[i].fnum == pseudoflavour[pf_cnt]) {
                                        printf("%s", flav_map[i].flavour);
                                        break;
@@ -407,14 +402,24 @@ int nfs4mount(const char *spec, const char *node, int *flags,
        data.version = NFS4_MOUNT_VERSION;
        for (;;) {
                if (verbose) {
-                       fprintf(stderr, 
-                               "mount: pinging: prog %d vers %d prot %s port %d\n", 
-                               NFS_PROGRAM, 4, data.proto == IPPROTO_UDP ? "udp" : "tcp", 
+                       printf(_("%s: pinging: prog %d vers %d prot %s port %d\n"),
+                               progname, NFS_PROGRAM, 4,
+                               data.proto == IPPROTO_UDP ? "udp" : "tcp",
                                ntohs(server_addr.sin_port));
                }
-               clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto);
-               if (rpc_createerr.cf_stat == RPC_SUCCESS)
+               client_addr.sin_family = 0;
+               client_addr.sin_addr.s_addr = 0;
+               clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto, &client_addr);
+               if (rpc_createerr.cf_stat == RPC_SUCCESS) {
+                       if (!ip_addr_in_opts &&
+                           client_addr.sin_family != 0 &&
+                           client_addr.sin_addr.s_addr != 0) {
+                               snprintf(ip_addr, sizeof(ip_addr), "%s",
+                                        inet_ntoa(client_addr.sin_addr));
+                               data.client_addr.len = strlen(ip_addr);
+                       }
                        break;
+               }
 
                switch(rpc_createerr.cf_stat){
                case RPC_TIMEDOUT:
@@ -435,8 +440,14 @@ int nfs4mount(const char *spec, const char *node, int *flags,
                continue;
        }
 
-       *mount_opts = (char *) &data;
-       /* clean up */
+       if (!fake) {
+               if (mount(spec, node, "nfs4",
+                               flags & ~(MS_USER|MS_USERS), &data)) {
+                       mount_error(spec, node, errno);
+                       goto fail;
+               }
+       }
+
        return 0;
 
 fail: