X-Git-Url: http://git.samba.org/?p=samba.git;a=blobdiff_plain;f=source3%2Fclient%2Fclient.c;h=da789161c9829869e03fc05cb415ca598e3d0107;hp=2a86035cf0271408ec2f64009d1fb687f5edb003;hb=1eb743ab8e8b1141f99fabd3e4a46895c6dcc17e;hpb=f04daa682acc2a9d5d660760b81dd353081ee84a diff --git a/source3/client/client.c b/source3/client/client.c index 2a86035cf02..da789161c98 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -33,7 +33,6 @@ 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; @@ -41,9 +40,9 @@ static char *desthost; static char *calling_name; static bool grepable = false; static char *cmdstr = NULL; -static const char *cmd_ptr = 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; @@ -85,9 +84,9 @@ 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 */ @@ -308,6 +307,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. ****************************************************************************/ @@ -329,7 +339,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 */ @@ -349,17 +360,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); @@ -511,14 +521,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)); @@ -851,26 +861,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_talloc(ctx, &cmd_ptr,&buf,NULL)) { - string_replace(buf,'/','\\'); + 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); } @@ -920,7 +919,7 @@ static int cmd_du(void) } if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { - string_replace(buf,'/','\\'); + normalize_name(buf); if (*buf == CLI_DIRSEP_CHAR) { mask = talloc_strdup(ctx, buf); } else { @@ -944,6 +943,7 @@ static int cmd_echo(void) TALLOC_CTX *ctx = talloc_tos(); char *num; char *data; + NTSTATUS status; if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL) || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) { @@ -951,9 +951,10 @@ static int cmd_echo(void) 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; } @@ -964,22 +965,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) { @@ -1038,36 +1047,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; @@ -1092,7 +1080,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))); } @@ -1112,10 +1100,7 @@ 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; } @@ -1218,7 +1203,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); @@ -1262,10 +1247,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; } @@ -1334,15 +1316,6 @@ static int cmd_mget(void) 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 { @@ -1356,18 +1329,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; } @@ -1463,6 +1427,7 @@ static int cmd_mkdir(void) struct cli_state *targetcli; char *targetname = NULL; char *p = NULL; + char *saveptr; ddir2 = talloc_strdup(ctx, ""); if (!ddir2) { @@ -1478,7 +1443,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) { @@ -1491,7 +1456,7 @@ static int cmd_mkdir(void) if (!ddir2) { return 1; } - p = strtok(NULL,"/\\"); + p = strtok_r(NULL, "/\\", &saveptr); } } else { do_mkdir(mask); @@ -1527,6 +1492,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\n"); + return 1; + } + name = talloc_asprintf_append(name, buf); + if (!name) { + return 1; + } + + do_allinfo(name); + + return 0; +} + /**************************************************************************** Put a single file. ****************************************************************************/ @@ -1601,6 +1652,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; @@ -1673,10 +1727,7 @@ 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; } @@ -1704,7 +1755,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; @@ -1893,10 +1944,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...")); @@ -1920,12 +1971,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); } @@ -2507,7 +2558,7 @@ 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; @@ -2536,14 +2587,14 @@ static int cmd_lock(void) return 1; } - start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16); + start = (uint64_t)strtol(buf, (char **)NULL, 16); if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { d_printf("lock [r|w] \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)); @@ -2556,7 +2607,7 @@ 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_talloc(ctx, &cmd_ptr,&buf,NULL)) { @@ -2570,14 +2621,14 @@ static int cmd_unlock(void) return 1; } - start = (SMB_BIG_UINT)strtol(buf, (char **)NULL, 16); + start = (uint64_t)strtol(buf, (char **)NULL, 16); if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) { d_printf("unlock \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)); @@ -2990,7 +3041,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::"); @@ -3027,7 +3078,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::"); @@ -3469,10 +3520,7 @@ 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; } @@ -3511,10 +3559,7 @@ 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; } @@ -3524,7 +3569,7 @@ static int cmd_reput(void) 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; } @@ -3587,42 +3632,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; iinfo_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; } @@ -3798,7 +3850,7 @@ int cmd_iosize(void) d_printf("iosize or iosize 0x. " "(Encrypted connection) ," "Minimum is 16384 (0x4000), " - "max is 64512 (0xFC00)\n"); + "max is 130048 (0x1FC00)\n"); } return 1; } @@ -3807,7 +3859,7 @@ int cmd_iosize(void) if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) { d_printf("iosize out of range for encrypted " "connection (min = 16384 (0x4000), " - "max = 64512 (0xFC00)"); + "max = 130048 (0x1FC00)"); return 1; } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) { d_printf("iosize out of range (min = 16384 (0x4000), " @@ -3839,6 +3891,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," show all available info", + {COMPL_NONE,COMPL_NONE}}, {"altname",cmd_altname," show alt name",{COMPL_NONE,COMPL_NONE}}, {"archive",cmd_archive,"\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 (default 20)",{COMPL_NONE,COMPL_NONE}}, @@ -4054,11 +4108,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; @@ -4069,7 +4119,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); @@ -4298,6 +4348,8 @@ cleanup: } } +static bool finished; + /**************************************************************************** Make sure we swallow keepalives during idle time. ****************************************************************************/ @@ -4328,24 +4380,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(); + } } } @@ -4357,7 +4446,7 @@ static int process_stdin(void) { int rc = 0; - while (1) { + while (!finished) { TALLOC_CTX *frame = talloc_stackframe(); char *tok = NULL; char *the_prompt = NULL; @@ -4443,6 +4532,8 @@ static int process(const char *base_directory) static int do_host_query(const char *query_host) { + struct sockaddr_storage ss; + cli = cli_cm_open(talloc_tos(), NULL, query_host, "IPC$", true, smb_encrypt); if (!cli) @@ -4450,6 +4541,12 @@ static int do_host_query(const char *query_host) 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 @@ -4526,7 +4623,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; @@ -4592,7 +4689,6 @@ static int do_message_op(void) { "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" }, - { "encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" }, POPT_COMMON_SAMBA POPT_COMMON_CONNECTION POPT_COMMON_CREDENTIALS @@ -4619,7 +4715,7 @@ 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))) { @@ -4632,7 +4728,7 @@ static int do_message_op(void) pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0); poptSetOtherOptionHelp(pc, "service "); - 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) { @@ -4797,6 +4893,11 @@ static int do_message_op(void) argv[0], get_dyn_CONFIGFILE()); } + if (get_cmdline_auth_info_use_machine_account() && + !set_cmdline_auth_info_machine_account_creds()) { + exit(-1); + } + load_interfaces(); if (service_opt && service) { @@ -4828,7 +4929,11 @@ static int do_message_op(void) calling_name = talloc_strdup(frame, global_myname() ); } - init_names(); + smb_encrypt = get_cmdline_auth_info_smb_encrypt(); + 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);