cifs: get rid of smb_vol->UNCip and smb_vol->port
authorJeff Layton <jlayton@redhat.com>
Mon, 26 Nov 2012 16:09:55 +0000 (11:09 -0500)
committerSteve French <smfrench@gmail.com>
Wed, 5 Dec 2012 19:27:30 +0000 (13:27 -0600)
Passing this around as a string is contorted and painful. Instead, just
convert these to a sockaddr as soon as possible, since that's how we're
going to work with it later anyway.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/netmisc.c

index ac66409fb9d38b02c037e2982e773b084114c37f..052d85b333f3cd44195e92083c3611dba488b1f7 100644 (file)
@@ -394,7 +394,6 @@ struct smb_vol {
        char *password;
        char *domainname;
        char *UNC;
-       char *UNCip;
        char *iocharset;  /* local code page for mapping to and from Unicode */
        char source_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* clnt nb name */
        char target_rfc1001_name[RFC1001_NAME_LEN_WITH_NULL]; /* srvr nb name */
@@ -442,11 +441,11 @@ struct smb_vol {
        unsigned int rsize;
        unsigned int wsize;
        bool sockopt_tcp_nodelay:1;
-       unsigned short int port;
        unsigned long actimeo; /* attribute cache timeout (jiffies) */
        struct smb_version_operations *ops;
        struct smb_version_values *vals;
        char *prepath;
+       struct sockaddr_storage dstaddr; /* destination address */
        struct sockaddr_storage srcaddr; /* allow binding to a local IP */
        struct nls_table *local_nls;
 };
index 7494358ba533f0127613b1d5935c213beb96095e..15a8cb66a07bf7ad3625bf06f32514b0287321ea 100644 (file)
@@ -110,9 +110,7 @@ extern unsigned int smbCalcSize(void *buf);
 extern int decode_negTokenInit(unsigned char *security_blob, int length,
                        struct TCP_Server_Info *server);
 extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
-extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);
-extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
-                               const unsigned short int port);
+extern void cifs_set_port(struct sockaddr *addr, const unsigned short int port);
 extern int map_smb_to_linux_error(char *buf, bool logErr);
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
                            const struct cifs_tcon *, int /* length of
index dec7c15d886a1df0a19051d7b30059068ac85906..428d8a12b8274a0e336f0d0a8ad89ccf8ab0d6fd 100644 (file)
@@ -1114,6 +1114,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
        char *string = NULL;
        char *tmp_end, *value;
        char delim;
+       bool got_ip = false;
+       unsigned short port = 0;
+       struct sockaddr *dstaddr = (struct sockaddr *)&vol->dstaddr;
 
        separator[0] = ',';
        separator[1] = 0;
@@ -1422,12 +1425,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        vol->dir_mode = option;
                        break;
                case Opt_port:
-                       if (get_option_ul(args, &option)) {
-                               cERROR(1, "%s: Invalid port value",
-                                       __func__);
+                       if (get_option_ul(args, &option) ||
+                           option > USHRT_MAX) {
+                               cERROR(1, "%s: Invalid port value", __func__);
                                goto cifs_parse_mount_err;
                        }
-                       vol->port = option;
+                       port = (unsigned short)option;
                        break;
                case Opt_rsize:
                        if (get_option_ul(args, &option)) {
@@ -1543,25 +1546,21 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        vol->password[j] = '\0';
                        break;
                case Opt_blank_ip:
-                       vol->UNCip = NULL;
+                       /* FIXME: should this be an error instead? */
+                       got_ip = false;
                        break;
                case Opt_ip:
                        string = match_strdup(args);
                        if (string == NULL)
                                goto out_nomem;
 
-                       if (strnlen(string, INET6_ADDRSTRLEN) >
-                                               INET6_ADDRSTRLEN) {
-                               printk(KERN_WARNING "CIFS: ip address "
-                                                   "too long\n");
-                               goto cifs_parse_mount_err;
-                       }
-                       vol->UNCip = kstrdup(string, GFP_KERNEL);
-                       if (!vol->UNCip) {
-                               printk(KERN_WARNING "CIFS: no memory "
-                                                   "for UNC IP\n");
+                       if (!cifs_convert_address(dstaddr, string,
+                                       strlen(string))) {
+                               printk(KERN_ERR "CIFS: bad ip= option (%s).\n",
+                                       string);
                                goto cifs_parse_mount_err;
                        }
+                       got_ip = true;
                        break;
                case Opt_unc:
                        string = match_strdup(args);
@@ -1811,8 +1810,18 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                goto cifs_parse_mount_err;
        }
 
-       if (vol->UNCip == NULL)
-               vol->UNCip = &vol->UNC[2];
+       if (!got_ip) {
+               /* No ip= option specified? Try to get it from UNC */
+               if (!cifs_convert_address(dstaddr, &vol->UNC[2],
+                                               strlen(&vol->UNC[2]))) {
+                       printk(KERN_ERR "Unable to determine destination "
+                                       "address.\n");
+                       goto cifs_parse_mount_err;
+               }
+       }
+
+       /* set the port that we got earlier */
+       cifs_set_port(dstaddr, port);
 
        if (uid_specified)
                vol->override_uid = override_uid;
@@ -2062,29 +2071,13 @@ static struct TCP_Server_Info *
 cifs_get_tcp_session(struct smb_vol *volume_info)
 {
        struct TCP_Server_Info *tcp_ses = NULL;
-       struct sockaddr_storage addr;
-       struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr;
-       struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr;
+       struct sockaddr *dstaddr = (struct sockaddr *)&volume_info->dstaddr;
        int rc;
 
-       memset(&addr, 0, sizeof(struct sockaddr_storage));
-
-       cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip);
-
-       if (volume_info->UNCip && volume_info->UNC) {
-               rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
-                                       volume_info->UNCip,
-                                       strlen(volume_info->UNCip),
-                                       volume_info->port);
-               if (!rc) {
-                       /* we failed translating address */
-                       rc = -EINVAL;
-                       goto out_err;
-               }
-       }
+       cFYI(1, "UNC: %s", volume_info->UNC);
 
        /* see if we already have a matching tcp_ses */
-       tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info);
+       tcp_ses = cifs_find_tcp_session(dstaddr, volume_info);
        if (tcp_ses)
                return tcp_ses;
 
@@ -2140,15 +2133,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
               sizeof(tcp_ses->srcaddr));
        ++tcp_ses->srv_count;
 
-       if (addr.ss_family == AF_INET6) {
-               cFYI(1, "attempting ipv6 connect");
-               /* BB should we allow ipv6 on port 139? */
-               /* other OS never observed in Wild doing 139 with v6 */
-               memcpy(&tcp_ses->dstaddr, sin_server6,
-                      sizeof(struct sockaddr_in6));
-       } else
-               memcpy(&tcp_ses->dstaddr, sin_server,
-                      sizeof(struct sockaddr_in));
+       memcpy(&tcp_ses->dstaddr, dstaddr, sizeof(tcp_ses->dstaddr));
 
        rc = ip_connect(tcp_ses);
        if (rc < 0) {
@@ -2708,11 +2693,9 @@ cifs_match_super(struct super_block *sb, void *data)
        struct cifs_ses *ses;
        struct cifs_tcon *tcon;
        struct tcon_link *tlink;
-       struct sockaddr_storage addr;
+       struct sockaddr *dstaddr;
        int rc = 0;
 
-       memset(&addr, 0, sizeof(struct sockaddr_storage));
-
        spin_lock(&cifs_tcp_ses_lock);
        cifs_sb = CIFS_SB(sb);
        tlink = cifs_get_tlink(cifs_sb_master_tlink(cifs_sb));
@@ -2725,15 +2708,9 @@ cifs_match_super(struct super_block *sb, void *data)
        tcp_srv = ses->server;
 
        volume_info = mnt_data->vol;
+       dstaddr = (struct sockaddr *)&volume_info->dstaddr;
 
-       rc = cifs_fill_sockaddr((struct sockaddr *)&addr,
-                               volume_info->UNCip,
-                               strlen(volume_info->UNCip),
-                               volume_info->port);
-       if (!rc)
-               goto out;
-
-       if (!match_server(tcp_srv, (struct sockaddr *)&addr, volume_info) ||
+       if (!match_server(tcp_srv, dstaddr, volume_info) ||
            !match_session(ses, volume_info) ||
            !match_tcon(tcon, volume_info->UNC)) {
                rc = 0;
@@ -3248,8 +3225,6 @@ cleanup_volume_info_contents(struct smb_vol *volume_info)
 {
        kfree(volume_info->username);
        kzfree(volume_info->password);
-       if (volume_info->UNCip != volume_info->UNC + 2)
-               kfree(volume_info->UNCip);
        kfree(volume_info->UNC);
        kfree(volume_info->domainname);
        kfree(volume_info->iocharset);
index d5ce9e26696c3c442cdd84ccc01aa1746f334248..a82bc51fdc82abad102b286399fd037ef10428c5 100644 (file)
@@ -204,7 +204,7 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len)
        return rc;
 }
 
-int
+void
 cifs_set_port(struct sockaddr *addr, const unsigned short int port)
 {
        switch (addr->sa_family) {
@@ -214,19 +214,7 @@ cifs_set_port(struct sockaddr *addr, const unsigned short int port)
        case AF_INET6:
                ((struct sockaddr_in6 *)addr)->sin6_port = htons(port);
                break;
-       default:
-               return 0;
        }
-       return 1;
-}
-
-int
-cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
-                  const unsigned short int port)
-{
-       if (!cifs_convert_address(dst, src, len))
-               return 0;
-       return cifs_set_port(dst, port);
 }
 
 /*****************************************************************************