Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.git] / source3 / client / client.c
index 6514dc76afe1ba962057d446b98530f36420956e..c88b918dc8c0eba265cb384d57668b621fe434ba 100644 (file)
 #define REGISTER 0
 #endif
 
+extern int do_smb_browse(void); /* mDNS browsing */
+
 extern bool AllowDebugChange;
 extern bool override_logfile;
 extern char tar_type;
-extern bool in_client;
+
 static int port = 0;
 static char *service;
 static char *desthost;
 static char *calling_name;
 static bool grepable = false;
 static char *cmdstr = NULL;
+const char *cmd_ptr = NULL;
 
-static int io_bufsize = 64512;
+static int io_bufsize = 524288;
 
 static int name_type = 0x20;
 extern int max_protocol;
@@ -81,14 +84,17 @@ static struct sockaddr_storage dest_ss;
 static bool abort_mget = true;
 
 /* timing globals */
-SMB_BIG_UINT get_total_size = 0;
+uint64_t get_total_size = 0;
 unsigned int get_total_time_ms = 0;
-static SMB_BIG_UINT put_total_size = 0;
+static uint64_t put_total_size = 0;
 static unsigned int put_total_time_ms = 0;
 
 /* totals globals */
 static double dir_total;
 
+/* encrypted state. */
+static bool smb_encrypt;
+
 /* root cli_state connection */
 
 struct cli_state *cli;
@@ -212,13 +218,12 @@ static int readfile(char *b, int n, XFILE *f)
  Send a message.
 ****************************************************************************/
 
-static void send_message(void)
+static void send_message(const char *username)
 {
        int total_len = 0;
        int grp_id;
 
-       if (!cli_message_start(cli, desthost,
-                               get_cmdline_auth_info_username(), &grp_id)) {
+       if (!cli_message_start(cli, desthost, username, &grp_id)) {
                d_printf("message start: %s\n", cli_errstr(cli));
                return;
        }
@@ -301,6 +306,17 @@ static int cmd_pwd(void)
        return 0;
 }
 
+/****************************************************************************
+ Ensure name has correct directory separators.
+****************************************************************************/
+
+static void normalize_name(char *newdir)
+{
+       if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
+               string_replace(newdir,'/','\\');
+       }
+}
+
 /****************************************************************************
  Change directory - inner section.
 ****************************************************************************/
@@ -322,7 +338,8 @@ static int do_cd(const char *new_dir)
                TALLOC_FREE(ctx);
                return 1;
        }
-       string_replace(newdir,'/','\\');
+
+       normalize_name(newdir);
 
        /* Save the current directory in case the new directory is invalid */
 
@@ -342,17 +359,16 @@ static int do_cd(const char *new_dir)
                if (!new_cd) {
                        goto out;
                }
-               if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
-                       new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR);
-                       if (!new_cd) {
-                               goto out;
-                       }
-               }
-               client_set_cur_dir(new_cd);
        }
-       if (!new_cd) {
-               goto out;
+
+       /* Ensure cur_dir ends in a DIRSEP */
+       if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
+               new_cd = talloc_asprintf_append(new_cd, CLI_DIRSEP_STR);
+               if (!new_cd) {
+                       goto out;
+               }
        }
+       client_set_cur_dir(new_cd);
 
        new_cd = clean_name(ctx, new_cd);
        client_set_cur_dir(new_cd);
@@ -422,7 +438,7 @@ static int cmd_cd(void)
        char *buf = NULL;
        int rc = 0;
 
-       if (next_token_nr_talloc(talloc_tos(), NULL, &buf,NULL)) {
+       if (next_token_talloc(talloc_tos(), &cmd_ptr, &buf,NULL)) {
                rc = do_cd(buf);
        } else {
                d_printf("Current directory is %s\n",client_get_cur_dir());
@@ -504,14 +520,14 @@ static void display_finfo(file_info *finfo, const char *dir)
                /* create absolute filename for cli_nt_create() FIXME */
                afname = talloc_asprintf(ctx,
                                        "%s%s%s",
-                                       client_get_cwd(),
+                                       dir,
                                        CLI_DIRSEP_STR,
                                        finfo->name);
                if (!afname) {
                        return;
                }
                /* print file meta date header */
-               d_printf( "FILENAME:%s\n", afname);
+               d_printf( "FILENAME:%s\n", finfo->name);
                d_printf( "MODE:%s\n", attrib_string(finfo->mode));
                d_printf( "SIZE:%.0f\n", (double)finfo->size);
                d_printf( "MTIME:%s", time_to_asc(t));
@@ -844,26 +860,15 @@ static int cmd_dir(void)
        int rc = 1;
 
        dir_total = 0;
-       if (strcmp(client_get_cur_dir(), CLI_DIRSEP_STR) != 0) {
-               mask = talloc_strdup(ctx, client_get_cur_dir());
-               if (!mask) {
-                       return 1;
-               }
-               if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
-                       mask = talloc_asprintf_append(mask, CLI_DIRSEP_STR);
-               }
-       } else {
-               mask = talloc_strdup(ctx, CLI_DIRSEP_STR);
-       }
-
+       mask = talloc_strdup(ctx, client_get_cur_dir());
        if (!mask) {
                return 1;
        }
 
-       if (next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
-               string_replace(buf,'/','\\');
+       if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
+               normalize_name(buf);
                if (*buf == CLI_DIRSEP_CHAR) {
-                       mask = talloc_strdup(ctx, buf + 1);
+                       mask = talloc_strdup(ctx, buf);
                } else {
                        mask = talloc_asprintf_append(mask, buf);
                }
@@ -912,8 +917,8 @@ static int cmd_du(void)
                }
        }
 
-       if (next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
-               string_replace(buf,'/','\\');
+       if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
+               normalize_name(buf);
                if (*buf == CLI_DIRSEP_CHAR) {
                        mask = talloc_strdup(ctx, buf);
                } else {
@@ -937,16 +942,18 @@ static int cmd_echo(void)
        TALLOC_CTX *ctx = talloc_tos();
        char *num;
        char *data;
+       NTSTATUS status;
 
-       if (!next_token_nr_talloc(ctx, NULL, &num, NULL)
-           || !next_token_nr_talloc(ctx, NULL, &data, NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
+           || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
                d_printf("echo <num> <data>\n");
                return 1;
        }
 
-       if (!cli_echo(cli, atoi(num), (uint8 *)data, strlen(data))) {
-               d_printf("echo failed: %s\n",
-                        nt_errstr(cli_get_nt_error(cli)));
+       status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("echo failed: %s\n", nt_errstr(status));
                return 1;
        }
 
@@ -957,22 +964,30 @@ static int cmd_echo(void)
  Get a file from rname to lname
 ****************************************************************************/
 
+static NTSTATUS writefile_sink(char *buf, size_t n, void *priv)
+{
+       int *pfd = (int *)priv;
+       if (writefile(*pfd, buf, n) == -1) {
+               return map_nt_error_from_unix(errno);
+       }
+       return NT_STATUS_OK;
+}
+
 static int do_get(const char *rname, const char *lname_in, bool reget)
 {
        TALLOC_CTX *ctx = talloc_tos();
        int handle = 0, fnum;
        bool newhandle = false;
-       char *data = NULL;
        struct timeval tp_start;
-       int read_size = io_bufsize;
        uint16 attr;
        SMB_OFF_T size;
        off_t start = 0;
-       off_t nread = 0;
+       SMB_OFF_T nread = 0;
        int rc = 0;
        struct cli_state *targetcli = NULL;
        char *targetname = NULL;
        char *lname = NULL;
+       NTSTATUS status;
 
        lname = talloc_strdup(ctx, lname_in);
        if (!lname) {
@@ -1031,36 +1046,15 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
        DEBUG(1,("getting file %s of size %.0f as %s ",
                 rname, (double)size, lname));
 
-       if(!(data = (char *)SMB_MALLOC(read_size))) {
-               d_printf("malloc fail for size %d\n", read_size);
+       status = cli_pull(targetcli, fnum, start, size, io_bufsize,
+                         writefile_sink, (void *)&handle, &nread);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "parallel_read returned %s\n",
+                         nt_errstr(status));
                cli_close(targetcli, fnum);
                return 1;
        }
 
-       while (1) {
-               int n = cli_read(targetcli, fnum, data, nread + start, read_size);
-
-               if (n <= 0)
-                       break;
-
-               if (writefile(handle,data, n) != n) {
-                       d_printf("Error writing local file\n");
-                       rc = 1;
-                       break;
-               }
-
-               nread += n;
-       }
-
-       if (nread + start < size) {
-               DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
-                           rname, (long)nread));
-
-               rc = 1;
-       }
-
-       SAFE_FREE(data);
-
        if (!cli_close(targetcli, fnum)) {
                d_printf("Error %s closing remote file\n",cli_errstr(cli));
                rc = 1;
@@ -1085,7 +1079,7 @@ static int do_get(const char *rname, const char *lname_in, bool reget)
                get_total_time_ms += this_time;
                get_total_size += nread;
 
-               DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
+               DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
                         nread / (1.024*this_time + 1.0e-4),
                         get_total_size / (1.024*get_total_time_ms)));
        }
@@ -1105,15 +1099,12 @@ static int cmd_get(void)
        char *rname = NULL;
        char *fname = NULL;
 
-       rname = talloc_asprintf(ctx,
-                       "%s%s",
-                       client_get_cur_dir(),
-                       CLI_DIRSEP_STR);
+       rname = talloc_strdup(ctx, client_get_cur_dir());
        if (!rname) {
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx, NULL,&fname,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
                d_printf("get <filename> [localname]\n");
                return 1;
        }
@@ -1126,7 +1117,7 @@ static int cmd_get(void)
                return 1;
        }
 
-       next_token_nr_talloc(ctx, NULL,&lname,NULL);
+       next_token_talloc(ctx, &cmd_ptr,&lname,NULL);
        if (!lname) {
                lname = fname;
        }
@@ -1211,7 +1202,7 @@ static void do_mget(file_info *finfo, const char *dir)
                strlower_m(finfo->name);
        }
 
-       if (!directory_exist(finfo->name,NULL) &&
+       if (!directory_exist(finfo->name) &&
            mkdir(finfo->name,0777) != 0) {
                d_printf("failed to create directory %s\n",finfo->name);
                client_set_cur_dir(saved_curdir);
@@ -1255,10 +1246,7 @@ static int cmd_more(void)
        int fd;
        int rc = 0;
 
-       rname = talloc_asprintf(ctx,
-                       "%s%s",
-                       client_get_cur_dir(),
-                       CLI_DIRSEP_STR);
+       rname = talloc_strdup(ctx, client_get_cur_dir());
        if (!rname) {
                return 1;
        }
@@ -1274,7 +1262,7 @@ static int cmd_more(void)
        }
        close(fd);
 
-       if (!next_token_nr_talloc(ctx,NULL,&fname,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
                d_printf("more <filename>\n");
                unlink(lname);
                return 1;
@@ -1322,20 +1310,11 @@ static int cmd_mget(void)
 
        abort_mget = false;
 
-       while (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                mget_mask = talloc_strdup(ctx, client_get_cur_dir());
                if (!mget_mask) {
                        return 1;
                }
-               if ((mget_mask[0] != '\0') &&
-                               (mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR)) {
-                       mget_mask = talloc_asprintf_append(mget_mask,
-                                                       CLI_DIRSEP_STR);
-                       if (!mget_mask) {
-                               return 1;
-                       }
-               }
-
                if (*buf == CLI_DIRSEP_CHAR) {
                        mget_mask = talloc_strdup(ctx, buf);
                } else {
@@ -1349,18 +1328,9 @@ static int cmd_mget(void)
        }
 
        if (!*mget_mask) {
-               mget_mask = talloc_strdup(ctx, client_get_cur_dir());
-               if (!mget_mask) {
-                       return 1;
-               }
-               if(mget_mask[strlen(mget_mask)-1]!=CLI_DIRSEP_CHAR) {
-                       mget_mask = talloc_asprintf_append(mget_mask,
-                                                       CLI_DIRSEP_STR);
-                       if (!mget_mask) {
-                               return 1;
-                       }
-               }
-               mget_mask = talloc_asprintf_append(mget_mask, "*");
+               mget_mask = talloc_asprintf(ctx,
+                                       "%s*",
+                                       client_get_cur_dir());
                if (!mget_mask) {
                        return 1;
                }
@@ -1439,7 +1409,7 @@ static int cmd_mkdir(void)
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                if (!recurse) {
                        d_printf("mkdir <dirname>\n");
                }
@@ -1456,6 +1426,7 @@ static int cmd_mkdir(void)
                struct cli_state *targetcli;
                char *targetname = NULL;
                char *p = NULL;
+               char *saveptr;
 
                ddir2 = talloc_strdup(ctx, "");
                if (!ddir2) {
@@ -1471,7 +1442,7 @@ static int cmd_mkdir(void)
                        return 1;
                }
                trim_char(ddir,'.','\0');
-               p = strtok(ddir,"/\\");
+               p = strtok_r(ddir, "/\\", &saveptr);
                while (p) {
                        ddir2 = talloc_asprintf_append(ddir2, p);
                        if (!ddir2) {
@@ -1484,7 +1455,7 @@ static int cmd_mkdir(void)
                        if (!ddir2) {
                                return 1;
                        }
-                       p = strtok(NULL,"/\\");
+                       p = strtok_r(NULL, "/\\", &saveptr);
                }
        } else {
                do_mkdir(mask);
@@ -1508,7 +1479,7 @@ static int cmd_altname(void)
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx, NULL, &buf, NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
                d_printf("altname <file>\n");
                return 1;
        }
@@ -1520,6 +1491,92 @@ static int cmd_altname(void)
        return 0;
 }
 
+/****************************************************************************
+ Show all info we can get
+****************************************************************************/
+
+static int do_allinfo(const char *name)
+{
+       fstring altname;
+       struct timespec b_time, a_time, m_time, c_time;
+       SMB_OFF_T size;
+       uint16_t mode;
+       SMB_INO_T ino;
+       NTTIME tmp;
+       unsigned int num_streams;
+       struct stream_struct *streams;
+       unsigned int i;
+
+       if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
+               d_printf("%s getting alt name for %s\n",
+                        cli_errstr(cli),name);
+               return false;
+       }
+       d_printf("altname: %s\n", altname);
+
+       if (!cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time,
+                           &size, &mode, &ino)) {
+               d_printf("%s getting pathinfo for %s\n",
+                        cli_errstr(cli),name);
+               return false;
+       }
+
+       unix_timespec_to_nt_time(&tmp, b_time);
+       d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
+
+       unix_timespec_to_nt_time(&tmp, a_time);
+       d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
+
+       unix_timespec_to_nt_time(&tmp, m_time);
+       d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
+
+       unix_timespec_to_nt_time(&tmp, c_time);
+       d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
+
+       if (!cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
+                                  &streams)) {
+               d_printf("%s getting streams for %s\n",
+                        cli_errstr(cli),name);
+               return false;
+       }
+
+       for (i=0; i<num_streams; i++) {
+               d_printf("stream: [%s], %lld bytes\n", streams[i].name,
+                        (unsigned long long)streams[i].size);
+       }
+
+       return 0;
+}
+
+/****************************************************************************
+ Show all info we can get
+****************************************************************************/
+
+static int cmd_allinfo(void)
+{
+       TALLOC_CTX *ctx = talloc_tos();
+       char *name;
+       char *buf;
+
+       name = talloc_strdup(ctx, client_get_cur_dir());
+       if (!name) {
+               return 1;
+       }
+
+       if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
+               d_printf("allinfo <file>\n");
+               return 1;
+       }
+       name = talloc_asprintf_append(name, buf);
+       if (!name) {
+               return 1;
+       }
+
+       do_allinfo(name);
+
+       return 0;
+}
+
 /****************************************************************************
  Put a single file.
 ****************************************************************************/
@@ -1594,6 +1651,9 @@ static int do_put(const char *rname, const char *lname, bool reput)
                d_printf("ERROR: Not enough memory!\n");
                return 1;
        }
+
+       x_setvbuf(f, NULL, X_IOFBF, maxwrite);
+
        while (!x_feof(f)) {
                int n = maxwrite;
                int ret;
@@ -1666,20 +1726,17 @@ static int cmd_put(void)
        char *rname;
        char *buf;
 
-       rname = talloc_asprintf(ctx,
-                       "%s%s",
-                       client_get_cur_dir(),
-                       CLI_DIRSEP_STR);
+       rname = talloc_strdup(ctx, client_get_cur_dir());
        if (!rname) {
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx,NULL,&lname,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&lname,NULL)) {
                d_printf("put <filename>\n");
                return 1;
        }
 
-       if (next_token_nr_talloc(ctx, NULL,&buf,NULL)) {
+       if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                rname = talloc_asprintf_append(rname, buf);
        } else {
                rname = talloc_asprintf_append(rname, lname);
@@ -1697,7 +1754,7 @@ static int cmd_put(void)
                SMB_STRUCT_STAT st;
                /* allow '-' to represent stdin
                   jdblair, 24.jun.98 */
-               if (!file_exist(lname,&st) &&
+               if (!file_exist_stat(lname,&st) &&
                    (strcmp(lname,"-"))) {
                        d_printf("%s does not exist\n",lname);
                        return 1;
@@ -1759,7 +1816,7 @@ static int cmd_select(void)
 {
        TALLOC_CTX *ctx = talloc_tos();
        char *new_fs = NULL;
-       next_token_nr_talloc(ctx, NULL,&new_fs,NULL)
+       next_token_talloc(ctx, &cmd_ptr,&new_fs,NULL)
                ;
        if (new_fs) {
                client_set_fileselection(new_fs);
@@ -1845,7 +1902,7 @@ static int cmd_mput(void)
        TALLOC_CTX *ctx = talloc_tos();
        char *p = NULL;
 
-       while (next_token_nr_talloc(ctx, NULL,&p,NULL)) {
+       while (next_token_talloc(ctx, &cmd_ptr,&p,NULL)) {
                int ret;
                struct file_list *temp_list;
                char *quest, *lname, *rname;
@@ -1886,10 +1943,10 @@ static int cmd_mput(void)
                                                break;
                                } else { /* Yes */
                                        SAFE_FREE(rname);
-                                       if(asprintf(&rname, "%s%s", cur_dir, lname) < 0) {
+                                       if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
                                                break;
                                        }
-                                       string_replace(rname,'/','\\');
+                                       normalize_name(rname);
                                        if (!cli_chkpath(cli, rname) &&
                                            !do_mkdir(rname)) {
                                                DEBUG (0, ("Unable to make dir, skipping..."));
@@ -1913,12 +1970,12 @@ static int cmd_mput(void)
 
                                /* Yes */
                                SAFE_FREE(rname);
-                               if (asprintf(&rname, "%s%s", cur_dir, lname) < 0) {
+                               if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
                                        break;
                                }
                        }
 
-                       string_replace(rname,'/','\\');
+                       normalize_name(rname);
 
                        do_put(rname, lname, false);
                }
@@ -1956,14 +2013,14 @@ static int cmd_cancel(void)
        char *buf = NULL;
        int job;
 
-       if (!next_token_nr_talloc(ctx, NULL, &buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr, &buf,NULL)) {
                d_printf("cancel <jobid> ...\n");
                return 1;
        }
        do {
                job = atoi(buf);
                do_cancel(job);
-       } while (next_token_nr_talloc(ctx,NULL,&buf,NULL));
+       } while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL));
 
        return 0;
 }
@@ -1979,7 +2036,7 @@ static int cmd_print(void)
        char *rname = NULL;
        char *p = NULL;
 
-       if (!next_token_nr_talloc(ctx, NULL, &lname,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr, &lname,NULL)) {
                d_printf("print <filename>\n");
                return 1;
        }
@@ -2075,7 +2132,7 @@ static int cmd_del(void)
        if (!mask) {
                return 1;
        }
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("del <filename>\n");
                return 1;
        }
@@ -2101,14 +2158,14 @@ static int cmd_wdel(void)
        struct cli_state *targetcli;
        char *targetname = NULL;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("wdel 0x<attrib> <wcard>\n");
                return 1;
        }
 
        attribute = (uint16)strtol(buf, (char **)NULL, 16);
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("wdel 0x<attrib> <wcard>\n");
                return 1;
        }
@@ -2143,7 +2200,7 @@ static int cmd_open(void)
        struct cli_state *targetcli;
        int fnum;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("open <filename>\n");
                return 1;
        }
@@ -2174,6 +2231,49 @@ static int cmd_open(void)
        return 0;
 }
 
+static int cmd_posix_encrypt(void)
+{
+       TALLOC_CTX *ctx = talloc_tos();
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+
+       if (cli->use_kerberos) {
+               status = cli_gss_smb_encryption_start(cli);
+       } else {
+               char *domain = NULL;
+               char *user = NULL;
+               char *password = NULL;
+
+               if (!next_token_talloc(ctx, &cmd_ptr,&domain,NULL)) {
+                       d_printf("posix_encrypt domain user password\n");
+                       return 1;
+               }
+
+               if (!next_token_talloc(ctx, &cmd_ptr,&user,NULL)) {
+                       d_printf("posix_encrypt domain user password\n");
+                       return 1;
+               }
+
+               if (!next_token_talloc(ctx, &cmd_ptr,&password,NULL)) {
+                       d_printf("posix_encrypt domain user password\n");
+                       return 1;
+               }
+
+               status = cli_raw_ntlm_smb_encryption_start(cli,
+                                                       user,
+                                                       password,
+                                                       domain);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
+       } else {
+               d_printf("encryption on\n");
+               smb_encrypt = true;
+       }
+
+       return 0;
+}
+
 /****************************************************************************
 ****************************************************************************/
 
@@ -2187,7 +2287,7 @@ static int cmd_posix_open(void)
        mode_t mode;
        int fnum;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("posix_open <filename> 0<mode>\n");
                return 1;
        }
@@ -2199,7 +2299,7 @@ static int cmd_posix_open(void)
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("posix_open <filename> 0<mode>\n");
                return 1;
        }
@@ -2235,7 +2335,7 @@ static int cmd_posix_mkdir(void)
        mode_t mode;
        int fnum;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("posix_mkdir <filename> 0<mode>\n");
                return 1;
        }
@@ -2247,7 +2347,7 @@ static int cmd_posix_mkdir(void)
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("posix_mkdir <filename> 0<mode>\n");
                return 1;
        }
@@ -2275,7 +2375,7 @@ static int cmd_posix_unlink(void)
        char *targetname = NULL;
        struct cli_state *targetcli;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("posix_unlink <filename>\n");
                return 1;
        }
@@ -2309,7 +2409,7 @@ static int cmd_posix_rmdir(void)
        char *targetname = NULL;
        struct cli_state *targetcli;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("posix_rmdir <filename>\n");
                return 1;
        }
@@ -2341,7 +2441,7 @@ static int cmd_close(void)
        char *buf = NULL;
        int fnum;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("close <fnum>\n");
                return 1;
        }
@@ -2420,17 +2520,30 @@ static int cmd_posix(void)
                        return 1;
                }
        }
+       if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) {
+               caps = talloc_asprintf_append(caps, "posix_encrypt ");
+               if (!caps) {
+                       return 1;
+               }
+       }
+       if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) {
+               caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt ");
+               if (!caps) {
+                       return 1;
+               }
+       }
 
        if (*caps && caps[strlen(caps)-1] == ' ') {
                caps[strlen(caps)-1] = '\0';
        }
+
+       d_printf("Server supports CIFS capabilities %s\n", caps);
+
        if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
                d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
                return 1;
        }
 
-       d_printf("Selecting server supported CIFS capabilities %s\n", caps);
-
        if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
                CLI_DIRSEP_CHAR = '/';
                *CLI_DIRSEP_STR = '/';
@@ -2444,17 +2557,17 @@ static int cmd_lock(void)
 {
        TALLOC_CTX *ctx = talloc_tos();
        char *buf = NULL;
-       SMB_BIG_UINT start, len;
+       uint64_t start, len;
        enum brl_type lock_type;
        int fnum;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
                return 1;
        }
        fnum = atoi(buf);
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
                return 1;
        }
@@ -2468,19 +2581,19 @@ static int cmd_lock(void)
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
                return 1;
        }
 
-       start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       start = (uint64_t)strtol(buf, (char **)NULL, 16);
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
                return 1;
        }
 
-       len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       len = (uint64_t)strtol(buf, (char **)NULL, 16);
 
        if (!cli_posix_lock(cli, fnum, start, len, true, lock_type)) {
                d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
@@ -2493,28 +2606,28 @@ static int cmd_unlock(void)
 {
        TALLOC_CTX *ctx = talloc_tos();
        char *buf = NULL;
-       SMB_BIG_UINT start, len;
+       uint64_t start, len;
        int fnum;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
                return 1;
        }
        fnum = atoi(buf);
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
                return 1;
        }
 
-       start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       start = (uint64_t)strtol(buf, (char **)NULL, 16);
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("unlock <fnum> <hex-start> <hex-len>\n");
                return 1;
        }
 
-       len = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16);
+       len = (uint64_t)strtol(buf, (char **)NULL, 16);
 
        if (!cli_posix_unlock(cli, fnum, start, len)) {
                d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
@@ -2536,7 +2649,7 @@ static int cmd_rmdir(void)
        char *targetname = NULL;
        struct cli_state *targetcli;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("rmdir <dirname>\n");
                return 1;
        }
@@ -2575,8 +2688,8 @@ static int cmd_link(void)
        char *targetname = NULL;
        struct cli_state *targetcli;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
                d_printf("link <oldname> <newname>\n");
                return 1;
        }
@@ -2626,8 +2739,8 @@ static int cmd_symlink(void)
        char *targetname = NULL;
        struct cli_state *targetcli;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
                d_printf("symlink <oldname> <newname>\n");
                return 1;
        }
@@ -2679,8 +2792,8 @@ static int cmd_chmod(void)
        struct cli_state *targetcli;
        mode_t mode;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
                d_printf("chmod mode file\n");
                return 1;
        }
@@ -2835,7 +2948,7 @@ static int cmd_getfacl(void)
        uint16 num_dir_acls = 0;
        uint16 i;
 
-       if (!next_token_nr_talloc(ctx,NULL,&name,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
                d_printf("getfacl filename\n");
                return 1;
        }
@@ -2927,7 +3040,7 @@ static int cmd_getfacl(void)
                                break;
                        case SMB_POSIX_ACL_GROUP:
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
-                               d_printf("group:%u", uorg);
+                               d_printf("group:%u:", uorg);
                                break;
                        case SMB_POSIX_ACL_MASK:
                                d_printf("mask::");
@@ -2964,7 +3077,7 @@ static int cmd_getfacl(void)
                                break;
                        case SMB_POSIX_ACL_GROUP:
                                uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
-                               d_printf("default:group:%u", uorg);
+                               d_printf("default:group:%u:", uorg);
                                break;
                        case SMB_POSIX_ACL_MASK:
                                d_printf("default:mask::");
@@ -3001,7 +3114,7 @@ static int cmd_stat(void)
        SMB_STRUCT_STAT sbuf;
        struct tm *lt;
 
-       if (!next_token_nr_talloc(ctx,NULL,&name,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
                d_printf("stat file\n");
                return 1;
        }
@@ -3097,9 +3210,9 @@ static int cmd_chown(void)
        struct cli_state *targetcli;
        char *targetname = NULL;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf2,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf3,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf3,NULL)) {
                d_printf("chown uid gid file\n");
                return 1;
        }
@@ -3146,8 +3259,8 @@ static int cmd_rename(void)
        char *targetsrc;
        char *targetdest;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
                d_printf("rename <src> <dest>\n");
                return 1;
        }
@@ -3221,8 +3334,8 @@ static int cmd_hardlink(void)
        struct cli_state *targetcli;
        char *targetname;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL) ||
-           !next_token_nr_talloc(ctx,NULL,&buf2,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
+           !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
                d_printf("hardlink <src> <dest>\n");
                return 1;
        }
@@ -3278,7 +3391,7 @@ static int cmd_newer(void)
        bool ok;
        SMB_STRUCT_STAT sbuf;
 
-       ok = next_token_nr_talloc(ctx,NULL,&buf,NULL);
+       ok = next_token_talloc(ctx, &cmd_ptr,&buf,NULL);
        if (ok && (sys_stat(buf,&sbuf) == 0)) {
                newer_than = sbuf.st_mtime;
                DEBUG(1,("Getting files newer than %s",
@@ -3304,7 +3417,7 @@ static int cmd_archive(void)
        TALLOC_CTX *ctx = talloc_tos();
        char *buf;
 
-       if (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                archive_level = atoi(buf);
        } else {
                d_printf("Archive level is %d\n",archive_level);
@@ -3383,7 +3496,7 @@ static int cmd_lcd(void)
        char *buf;
        char *d;
 
-       if (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                chdir(buf);
        }
        d = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
@@ -3406,15 +3519,12 @@ static int cmd_reget(void)
        char *fname = NULL;
        char *p = NULL;
 
-       remote_name = talloc_asprintf(ctx,
-                               "%s%s",
-                               client_get_cur_dir(),
-                               CLI_DIRSEP_STR);
+       remote_name = talloc_strdup(ctx, client_get_cur_dir());
        if (!remote_name) {
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx, NULL, &fname, NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr, &fname, NULL)) {
                d_printf("reget <filename>\n");
                return 1;
        }
@@ -3428,7 +3538,7 @@ static int cmd_reget(void)
        }
 
        local_name = fname;
-       next_token_nr_talloc(ctx, NULL, &p, NULL);
+       next_token_talloc(ctx, &cmd_ptr, &p, NULL);
        if (p) {
                local_name = p;
        }
@@ -3448,25 +3558,22 @@ static int cmd_reput(void)
        char *buf;
        SMB_STRUCT_STAT st;
 
-       remote_name = talloc_asprintf(ctx,
-                               "%s%s",
-                               client_get_cur_dir(),
-                               CLI_DIRSEP_STR);
+       remote_name = talloc_strdup(ctx, client_get_cur_dir());
        if (!remote_name) {
                return 1;
        }
 
-       if (!next_token_nr_talloc(ctx, NULL, &local_name, NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr, &local_name, NULL)) {
                d_printf("reput <filename>\n");
                return 1;
        }
 
-       if (!file_exist(local_name, &st)) {
+       if (!file_exist_stat(local_name, &st)) {
                d_printf("%s does not exist\n", local_name);
                return 1;
        }
 
-       if (next_token_nr_talloc(ctx, NULL, &buf, NULL)) {
+       if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
                remote_name = talloc_asprintf_append(remote_name,
                                                buf);
        } else {
@@ -3524,42 +3631,49 @@ static bool browse_host_rpc(bool sort)
        NTSTATUS status;
        struct rpc_pipe_client *pipe_hnd;
        TALLOC_CTX *frame = talloc_stackframe();
-       ENUM_HND enum_hnd;
        WERROR werr;
-       SRV_SHARE_INFO_CTR ctr;
+       struct srvsvc_NetShareInfoCtr info_ctr;
+       struct srvsvc_NetShareCtr1 ctr1;
+       uint32_t resume_handle = 0;
+       uint32_t total_entries = 0;
        int i;
 
-       init_enum_hnd(&enum_hnd, 0);
-
-       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &status);
+       status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
+                                         &pipe_hnd);
 
-       if (pipe_hnd == NULL) {
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
                           nt_errstr(status)));
                TALLOC_FREE(frame);
                return false;
        }
 
-       werr = rpccli_srvsvc_net_share_enum(pipe_hnd, frame, 1, &ctr,
-                                           0xffffffff, &enum_hnd);
+       ZERO_STRUCT(info_ctr);
+       ZERO_STRUCT(ctr1);
+
+       info_ctr.level = 1;
+       info_ctr.ctr.ctr1 = &ctr1;
+
+       status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, frame,
+                                             pipe_hnd->desthost,
+                                             &info_ctr,
+                                             0xffffffff,
+                                             &total_entries,
+                                             &resume_handle,
+                                             &werr);
 
-       if (!W_ERROR_IS_OK(werr)) {
-               cli_rpc_pipe_close(pipe_hnd);
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
+               TALLOC_FREE(pipe_hnd);
                TALLOC_FREE(frame);
                return false;
        }
 
-       for (i=0; i<ctr.num_entries; i++) {
-               SRV_SHARE_INFO_1 *info = &ctr.share.info1[i];
-               char *name, *comment;
-               name = rpcstr_pull_unistr2_talloc(
-                       frame, &info->info_1_str.uni_netname);
-               comment = rpcstr_pull_unistr2_talloc(
-                       frame, &info->info_1_str.uni_remark);
-               browse_fn(name, info->info_1.type, comment, NULL);
+       for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
+               struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
+               browse_fn(info.name, info.type, info.comment, NULL);
        }
 
-       cli_rpc_pipe_close(pipe_hnd);
+       TALLOC_FREE(pipe_hnd);
        TALLOC_FREE(frame);
        return true;
 }
@@ -3640,7 +3754,7 @@ static int cmd_vuid(void)
        TALLOC_CTX *ctx = talloc_tos();
        char *buf;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                d_printf("Current VUID is %d\n", cli->vuid);
                return 0;
        }
@@ -3658,12 +3772,12 @@ static int cmd_logon(void)
        TALLOC_CTX *ctx = talloc_tos();
        char *l_username, *l_password;
 
-       if (!next_token_nr_talloc(ctx,NULL,&l_username,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&l_username,NULL)) {
                d_printf("logon <username> [<password>]\n");
                return 0;
        }
 
-       if (!next_token_nr_talloc(ctx,NULL,&l_password,NULL)) {
+       if (!next_token_talloc(ctx, &cmd_ptr,&l_password,NULL)) {
                char *pass = getpass("Password: ");
                if (pass) {
                        l_password = talloc_strdup(ctx,pass);
@@ -3726,17 +3840,29 @@ int cmd_iosize(void)
        char *buf;
        int iosize;
 
-       if (!next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
-               d_printf("iosize <n> or iosize 0x<n>. "
-                       "Minimum is 16384 (0x4000), "
-                       "max is 16776960 (0xFFFF00)\n");
+       if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
+               if (!smb_encrypt) {
+                       d_printf("iosize <n> or iosize 0x<n>. "
+                               "Minimum is 16384 (0x4000), "
+                               "max is 16776960 (0xFFFF00)\n");
+               } else {
+                       d_printf("iosize <n> or iosize 0x<n>. "
+                               "(Encrypted connection) ,"
+                               "Minimum is 16384 (0x4000), "
+                               "max is 130048 (0x1FC00)\n");
+               }
                return 1;
        }
 
        iosize = strtol(buf,NULL,0);
-       if (iosize < 0 || iosize > 0xFFFF00) {
+       if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
+               d_printf("iosize out of range for encrypted "
+                       "connection (min = 16384 (0x4000), "
+                       "max = 130048 (0x1FC00)");
+               return 1;
+       } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
                d_printf("iosize out of range (min = 16384 (0x4000), "
-                       "max = 16776960 (0x0xFFFF00)");
+                       "max = 16776960 (0xFFFF00)");
                return 1;
        }
 
@@ -3764,6 +3890,8 @@ static struct {
        char compl_args[2];      /* Completion argument info */
 } commands[] = {
   {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
+  {"allinfo",cmd_allinfo,"<file> show all available info",
+   {COMPL_NONE,COMPL_NONE}},
   {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
   {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
@@ -3799,6 +3927,7 @@ static struct {
   {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
   {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
   {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
+  {"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
   {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
   {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
@@ -3879,7 +4008,7 @@ static int cmd_help(void)
        int i=0,j;
        char *buf;
 
-       if (next_token_nr_talloc(ctx,NULL,&buf,NULL)) {
+       if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
                if ((i = process_tok(buf)) >= 0)
                        d_printf("HELP %s:\n\t%s\n\n",
                                commands[i].name,commands[i].description);
@@ -3911,7 +4040,8 @@ static int process_command_string(const char *cmd_in)
        /* establish the connection if not already */
 
        if (!cli) {
-               cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+               cli = cli_cm_open(talloc_tos(), NULL, desthost,
+                               service, true, smb_encrypt);
                if (!cli) {
                        return 1;
                }
@@ -3919,7 +4049,6 @@ static int process_command_string(const char *cmd_in)
 
        while (cmd[0] != '\0')    {
                char *line;
-               const char *ptr;
                char *p;
                char *tok;
                int i;
@@ -3934,8 +4063,8 @@ static int process_command_string(const char *cmd_in)
                }
 
                /* and get the first part of the command */
-               ptr = line;
-               if (!next_token_nr_talloc(ctx,&ptr,&tok,NULL)) {
+               cmd_ptr = line;
+               if (!next_token_talloc(ctx, &cmd_ptr,&tok,NULL)) {
                        continue;
                }
 
@@ -3978,11 +4107,7 @@ static void completion_remote_filter(const char *mnt,
                        TALLOC_CTX *ctx = talloc_stackframe();
                        char *tmp;
 
-                       if (info->dirmask && info->dirmask[0] != 0) {
-                               tmp = talloc_strdup(ctx,info->dirmask);
-                       } else {
-                               tmp = talloc_strdup(ctx,"");
-                       }
+                       tmp = talloc_strdup(ctx,info->dirmask);
                        if (!tmp) {
                                TALLOC_FREE(ctx);
                                return;
@@ -3993,7 +4118,7 @@ static void completion_remote_filter(const char *mnt,
                                return;
                        }
                        if (f->mode & aDIR) {
-                               tmp = talloc_asprintf_append(tmp, "/");
+                               tmp = talloc_asprintf_append(tmp, CLI_DIRSEP_STR);
                        }
                        if (!tmp) {
                                TALLOC_FREE(ctx);
@@ -4060,7 +4185,7 @@ static char **remote_completion(const char *text, int len)
        info.samelen = info.len = len-i-1;
 
        if (i > 0) {
-               info.dirmask = SMB_MALLOC(i+2);
+               info.dirmask = SMB_MALLOC_ARRAY(char, i+2);
                if (!info.dirmask) {
                        goto cleanup;
                }
@@ -4222,6 +4347,8 @@ cleanup:
        }
 }
 
+static bool finished;
+
 /****************************************************************************
  Make sure we swallow keepalives during idle time.
 ****************************************************************************/
@@ -4252,24 +4379,61 @@ static void readline_callback(void)
        timeout.tv_usec = 0;
        sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
 
-       /* We deliberately use receive_smb instead of
+       /* We deliberately use receive_smb_raw instead of
           client_receive_smb as we want to receive
           session keepalives and then drop them here.
        */
        if (FD_ISSET(cli->fd,&fds)) {
-               if (!receive_smb(cli->fd,cli->inbuf,0,&cli->smb_rw_error)) {
-                       DEBUG(0, ("Read from server failed, maybe it closed the "
-                               "connection\n"));
+               NTSTATUS status;
+               size_t len;
+
+               set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
+
+               status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, 0, 0, &len);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Read from server failed, maybe it closed "
+                                 "the connection\n"));
+
+                       finished = true;
+                       smb_readline_done();
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
+                               set_smb_read_error(&cli->smb_rw_error,
+                                                  SMB_READ_EOF);
+                               return;
+                       }
+
+                       if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
+                               set_smb_read_error(&cli->smb_rw_error,
+                                                  SMB_READ_TIMEOUT);
+                               return;
+                       }
+
+                       set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
                        return;
                }
+               if(CVAL(cli->inbuf,0) != SMBkeepalive) {
+                       DEBUG(0, ("Read from server "
+                               "returned unexpected packet!\n"));
+                       return;
+               }
+
                goto again;
        }
 
        /* Ping the server to keep the connection alive using SMBecho. */
        {
+               NTSTATUS status;
                unsigned char garbage[16];
                memset(garbage, 0xf0, sizeof(garbage));
-               cli_echo(cli, 1, garbage, sizeof(garbage));
+               status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("SMBecho failed. Maybe server has closed "
+                               "the connection\n"));
+                       finished = true;
+                       smb_readline_done();
+               }
        }
 }
 
@@ -4279,10 +4443,9 @@ static void readline_callback(void)
 
 static int process_stdin(void)
 {
-       const char *ptr;
        int rc = 0;
 
-       while (1) {
+       while (!finished) {
                TALLOC_CTX *frame = talloc_stackframe();
                char *tok = NULL;
                char *the_prompt = NULL;
@@ -4310,8 +4473,8 @@ static int process_stdin(void)
                }
 
                /* and get the first part of the command */
-               ptr = line;
-               if (!next_token_nr_talloc(frame,&ptr,&tok,NULL)) {
+               cmd_ptr = line;
+               if (!next_token_talloc(frame, &cmd_ptr,&tok,NULL)) {
                        TALLOC_FREE(frame);
                        SAFE_FREE(line);
                        continue;
@@ -4338,12 +4501,13 @@ static int process(const char *base_directory)
 {
        int rc = 0;
 
-       cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+       cli = cli_cm_open(talloc_tos(), NULL,
+                       desthost, service, true, smb_encrypt);
        if (!cli) {
                return 1;
        }
 
-       if (*base_directory) {
+       if (base_directory && *base_directory) {
                rc = do_cd(base_directory);
                if (rc) {
                        cli_cm_shutdown();
@@ -4367,12 +4531,21 @@ static int process(const char *base_directory)
 
 static int do_host_query(const char *query_host)
 {
-       cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true);
+       struct sockaddr_storage ss;
+
+       cli = cli_cm_open(talloc_tos(), NULL,
+                       query_host, "IPC$", true, smb_encrypt);
        if (!cli)
                return 1;
 
        browse_host(true);
 
+       if (interpret_string_addr(&ss, query_host, 0) && (ss.ss_family != AF_INET)) {
+               d_printf("%s is an IPv6 address -- no workgroup available\n",
+                       query_host);
+               return 1;
+       }
+
        if (port != 139) {
 
                /* Workgroups simply don't make sense over anything
@@ -4380,7 +4553,8 @@ static int do_host_query(const char *query_host)
 
                cli_cm_shutdown();
                cli_cm_set_port( 139 );
-               cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true);
+               cli = cli_cm_open(talloc_tos(), NULL,
+                               query_host, "IPC$", true, smb_encrypt);
        }
 
        if (cli == NULL) {
@@ -4405,14 +4579,15 @@ static int do_tar_op(const char *base_directory)
 
        /* do we already have a connection? */
        if (!cli) {
-               cli = cli_cm_open(talloc_tos(), NULL, desthost, service, true);
+               cli = cli_cm_open(talloc_tos(), NULL,
+                       desthost, service, true, smb_encrypt);
                if (!cli)
                        return 1;
        }
 
        recurse=true;
 
-       if (*base_directory)  {
+       if (base_directory && *base_directory)  {
                ret = do_cd(base_directory);
                if (ret) {
                        cli_cm_shutdown();
@@ -4431,7 +4606,7 @@ static int do_tar_op(const char *base_directory)
  Handle a message operation.
 ****************************************************************************/
 
-static int do_message_op(void)
+static int do_message_op(struct user_auth_info *auth_info)
 {
        struct sockaddr_storage ss;
        struct nmb_name called, calling;
@@ -4447,7 +4622,7 @@ static int do_message_op(void)
        snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
        fstrcat(server_name, name_type_hex);
 
-        zero_addr(&ss);
+        zero_sockaddr(&ss);
        if (have_ip)
                ss = dest_ss;
 
@@ -4472,7 +4647,7 @@ static int do_message_op(void)
                return 1;
        }
 
-       send_message();
+       send_message(get_cmdline_auth_info_username(auth_info));
        cli_cm_shutdown();
 
        return 0;
@@ -4512,17 +4687,18 @@ static int do_message_op(void)
                { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
                { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
                { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
+                { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" },
                POPT_COMMON_SAMBA
                POPT_COMMON_CONNECTION
                POPT_COMMON_CREDENTIALS
                POPT_TABLEEND
        };
        TALLOC_CTX *frame = talloc_stackframe();
+       struct user_auth_info *auth_info;
 
        if (!client_set_cur_dir("\\")) {
                exit(ENOMEM);
        }
-       load_case_tables();
 
 #ifdef KANJI
        term_code = talloc_strdup(frame,KANJI);
@@ -4539,18 +4715,26 @@ static int do_message_op(void)
        set_global_myworkgroup( "" );
        set_global_myname( "" );
 
-        /* set default debug level to 0 regardless of what smb.conf sets */
+        /* set default debug level to 1 regardless of what smb.conf sets */
        setup_logging( "smbclient", true );
        DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
        if ((dbf = x_fdup(x_stderr))) {
                x_setbuf( dbf, NULL );
        }
 
+       load_case_tables();
+
+       auth_info = user_auth_info_init(frame);
+       if (auth_info == NULL) {
+               exit(1);
+       }
+       popt_common_set_auth_info(auth_info);
+
        /* skip argv(0) */
        pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
        poptSetOtherOptionHelp(pc, "service <password>");
 
-       in_client = true;   /* Make sure that we tell lp_load we are */
+        lp_set_in_client(true); /* Make sure that we tell lp_load we are */
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
 
@@ -4573,8 +4757,11 @@ static int do_message_op(void)
                }
 
                /* if the service has already been retrieved then check if we have also a password */
-               if (service_opt && (!get_cmdline_auth_info_got_pass()) && poptPeekArg(pc)) {
-                       set_cmdline_auth_info_password(poptGetArg(pc));
+               if (service_opt
+                   && (!get_cmdline_auth_info_got_pass(auth_info))
+                   && poptPeekArg(pc)) {
+                       set_cmdline_auth_info_password(auth_info,
+                                                      poptGetArg(pc));
                }
 
                switch (opt) {
@@ -4653,6 +4840,12 @@ static int do_message_op(void)
                case 'g':
                        grepable=true;
                        break;
+               case 'e':
+                       smb_encrypt=true;
+                       break;
+               case 'B':
+                       return(do_smb_browse());
+
                }
        }
 
@@ -4674,8 +4867,11 @@ static int do_message_op(void)
        }
 
        /* if the service has already been retrieved then check if we have also a password */
-       if (service_opt && !get_cmdline_auth_info_got_pass() && poptPeekArg(pc)) {
-               set_cmdline_auth_info_password(poptGetArg(pc));
+       if (service_opt
+           && !get_cmdline_auth_info_got_pass(auth_info)
+           && poptPeekArg(pc)) {
+               set_cmdline_auth_info_password(auth_info,
+                                              poptGetArg(pc));
        }
 
        /* check for the -P option */
@@ -4704,14 +4900,19 @@ static int do_message_op(void)
        if ( override_logfile )
                setup_logging( lp_logfile(), false );
 
-       if (!lp_load(dyn_CONFIGFILE,true,false,false,true)) {
+       if (!lp_load(get_dyn_CONFIGFILE(),true,false,false,true)) {
                fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
-                       argv[0], dyn_CONFIGFILE);
+                       argv[0], get_dyn_CONFIGFILE());
+       }
+
+       if (get_cmdline_auth_info_use_machine_account(auth_info) &&
+           !set_cmdline_auth_info_machine_account_creds(auth_info)) {
+               exit(-1);
        }
 
        load_interfaces();
 
-       if (service_opt) {
+       if (service_opt && service) {
                size_t len;
 
                /* Convert any '/' characters in the service name to '\' characters */
@@ -4740,12 +4941,16 @@ static int do_message_op(void)
                calling_name = talloc_strdup(frame, global_myname() );
        }
 
-       init_names();
+       smb_encrypt = get_cmdline_auth_info_smb_encrypt(auth_info);
+       if (!init_names()) {
+               fprintf(stderr, "init_names() failed\n");
+               exit(1);
+       }
 
        if(new_name_resolve_order)
                lp_set_name_resolve_order(new_name_resolve_order);
 
-       if (!tar_type && !*query_host && !*service && !message) {
+       if (!tar_type && !query_host && !service && !message) {
                poptPrintUsage(pc, stderr, 0);
                exit(1);
        }
@@ -4754,7 +4959,7 @@ static int do_message_op(void)
 
        /* Store the username and password for dfs support */
 
-       cli_cm_set_credentials();
+       cli_cm_set_credentials(auth_info);
 
        DEBUG(3,("Client started (version %s).\n", SAMBA_VERSION_STRING));
 
@@ -4764,7 +4969,7 @@ static int do_message_op(void)
                return do_tar_op(base_directory);
        }
 
-       if (*query_host) {
+       if (query_host && *query_host) {
                char *qhost = query_host;
                char *slash;
 
@@ -4787,7 +4992,7 @@ static int do_message_op(void)
        }
 
        if (message) {
-               return do_message_op();
+               return do_message_op(auth_info);
        }
 
        if (process(base_directory)) {