From a2c1623827406667a4f2f058c24f1d971f6627f8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Jun 1996 06:42:03 +0000 Subject: a huge pile of changes :-) The biggest thing is the integration of Lukes new nmbd. Its still largely untested, so we will really need some feedback I've also added auto prototype generation and cleaned up a lot of minor things as a result (This used to be commit 0d8dcfa13c527ec2c8aca39ba49c09e4e694b26c) --- source3/client/client.c | 753 +++++++++++++++---------------- source3/client/clientutil.c | 1029 +++++++++++++++++++++++++++++++++++++++++++ source3/client/clitar.c | 6 - 3 files changed, 1408 insertions(+), 380 deletions(-) create mode 100644 source3/client/clientutil.c (limited to 'source3/client') diff --git a/source3/client/client.c b/source3/client/client.c index a40d377955..3cefbc2284 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -24,7 +24,6 @@ #endif #include "includes.h" -#include "nameserv.h" #ifndef REGISTER #define REGISTER 0 @@ -44,6 +43,7 @@ BOOL connect_as_printer = False; BOOL connect_as_ipc = False; extern struct in_addr bcast_ip; static BOOL got_bcast=False; +struct in_addr ipzero; char cryptkey[8]; BOOL doencrypt=False; @@ -72,16 +72,29 @@ extern int DEBUGLEVEL; BOOL translation = False; + +static BOOL send_trans_request(char *outbuf,int trans, + char *name,int fid,int flags, + char *data,char *param,uint16 *setup, + int ldata,int lparam,int lsetup, + int mdata,int mparam,int msetup); +static BOOL receive_trans_response(char *inbuf,int trans, + int *data_len,int *param_len, + char **data,char **param); +static int interpret_long_filename(int level,char *p,file_info *finfo); +static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir); +static int interpret_short_filename(char *p,file_info *finfo); +static BOOL call_api(int prcnt,int drcnt, + int mprcnt,int mdrcnt, + int *rprcnt,int *rdrcnt, + char *param,char *data, + char **rparam,char **rdata); + + /* clitar bits insert */ -extern void cmd_tar(); -extern void cmd_block(); -extern void cmd_tarmode(); -extern void cmd_setmode(); extern int blocksize; extern BOOL tar_inc; extern BOOL tar_reset; -extern int process_tar(); -extern int tar_parseargs(); /* clitar bits end */ @@ -151,20 +164,6 @@ setup_term_code (char *code) #define CNV_INPUT(s) unix2dos_format(s,True) #endif -static void send_logout(void ); -BOOL reopen_connection(char *inbuf,char *outbuf); -static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); -static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); -static BOOL call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt, - int *rprcnt,int *rdrcnt,char *param,char *data, - char **rparam,char **rdata); -static BOOL send_trans_request(char *outbuf,int trans, - char *name,int fid,int flags, - char *data,char *param,uint16 *setup, - int ldata,int lparam,int lsetup, - int mdata,int mparam,int msetup); - - /**************************************************************************** setup basics in a outgoing packet ****************************************************************************/ @@ -486,6 +485,319 @@ static void display_finfo(file_info *finfo) asctime(LocalTime(&t)))); } + +/**************************************************************************** + do a directory listing, calling fn on each file found. Use the TRANSACT2 + call for long filenames + ****************************************************************************/ +static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) +{ + int max_matches = 512; + int info_level = Protocol 200) + { + DEBUG(0,("ERROR: Looping in FIND_NEXT??\n")); + break; + } + + if (First) + { + setup = TRANSACT2_FINDFIRST; + SSVAL(param,0,attribute); /* attribute */ + SSVAL(param,2,max_matches); /* max count */ + SSVAL(param,4,8+4+2); /* resume required + close on end + continue */ + SSVAL(param,6,info_level); + SIVAL(param,8,0); + strcpy(param+12,mask); + } + else + { + setup = TRANSACT2_FINDNEXT; + SSVAL(param,0,ff_dir_handle); + SSVAL(param,2,max_matches); /* max count */ + SSVAL(param,4,info_level); + SIVAL(param,6,ff_resume_key); /* ff_resume_key */ + SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ + strcpy(param+12,mask); + + DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", + ff_dir_handle,ff_resume_key,ff_lastname,mask)); + } + /* ??? original code added 1 pad byte after param */ + + send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, + NULL,param,&setup, + 0,12+strlen(mask)+1,1, + BUFFER_SIZE,10,0); + + if (!receive_trans_response(inbuf,SMBtrans2, + &resp_data_len,&resp_param_len, + &resp_data,&resp_param)) + { + DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf))); + break; + } + + /* parse out some important return info */ + p = resp_param; + if (First) + { + ff_dir_handle = SVAL(p,0); + ff_searchcount = SVAL(p,2); + ff_eos = SVAL(p,4); + ff_lastname = SVAL(p,8); + } + else + { + ff_searchcount = SVAL(p,0); + ff_eos = SVAL(p,2); + ff_lastname = SVAL(p,6); + } + + if (ff_searchcount == 0) + break; + + /* point to the data bytes */ + p = resp_data; + + /* we might need the lastname for continuations */ + if (ff_lastname > 0) + { + switch(info_level) + { + case 260: + ff_resume_key =0; + StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname); + /* strcpy(mask,p+ff_lastname+94); */ + break; + case 1: + strcpy(mask,p + ff_lastname + 1); + ff_resume_key = 0; + break; + } + } + else + strcpy(mask,""); + + /* and add them to the dirlist pool */ + dirlist = Realloc(dirlist,dirlist_len + resp_data_len); + + if (!dirlist) + { + DEBUG(0,("Failed to expand dirlist\n")); + break; + } + + /* put in a length for the last entry, to ensure we can chain entries + into the next packet */ + { + char *p2; + for (p2=p,i=0;i<(ff_searchcount-1);i++) + p2 += interpret_long_filename(info_level,p2,NULL); + SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p)); + } + + /* grab the data for later use */ + memcpy(dirlist+dirlist_len,p,resp_data_len); + dirlist_len += resp_data_len; + + total_received += ff_searchcount; + + if (resp_data) free(resp_data); resp_data = NULL; + if (resp_param) free(resp_param); resp_param = NULL; + + DEBUG(3,("received %d entries (eos=%d resume=%d)\n", + ff_searchcount,ff_eos,ff_resume_key)); + + First = False; + } + + if (!fn) + for (p=dirlist,i=0;i= PROTOCOL_LANMAN1) + CVAL(outbuf,smb_com) = SMBffirst; + else +#endif + CVAL(outbuf,smb_com) = SMBsearch; + + SSVAL(outbuf,smb_tid,cnum); + setup_pkt(outbuf); + + SSVAL(outbuf,smb_vwv0,num_asked); + SSVAL(outbuf,smb_vwv1,attribute); + + p = smb_buf(outbuf); + *p++ = 4; + + if (first) + strcpy(p,mask); + else + strcpy(p,""); + p += strlen(p) + 1; + + *p++ = 5; + if (first) + SSVAL(p,0,0); + else + { + SSVAL(p,0,21); + p += 2; + memcpy(p,status,21); + } + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + + received = SVAL(inbuf,smb_vwv0); + + DEBUG(5,("dir received %d\n",received)); + + DEBUG(6,("errstr=%s\n",smb_errstr(inbuf))); + + if (received <= 0) break; + + first = False; + + dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE); + + if (!dirlist) + return 0; + + p = smb_buf(inbuf) + 3; + + memcpy(dirlist+num_received*DIR_STRUCT_SIZE, + p,received*DIR_STRUCT_SIZE); + + memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21); + + num_received += received; + + if (CVAL(inbuf,smb_rcls) != 0) break; + } + +#if FFIRST + if (!first && Protocol >= PROTOCOL_LANMAN1) + { + bzero(outbuf,smb_size); + CVAL(outbuf,smb_com) = SMBfclose; + + SSVAL(outbuf,smb_tid,cnum); + setup_pkt(outbuf); + + p = smb_buf(outbuf); + *p++ = 4; + + strcpy(p,""); + p += strlen(p) + 1; + + *p++ = 5; + SSVAL(p,0,21); + p += 2; + memcpy(p,status,21); + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,CLIENT_TIMEOUT,False); + + if (CVAL(inbuf,smb_rcls) != 0) + DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf))); + } +#endif + + if (!fn) + for (p=dirlist,i=0;iname,p,namelen); - return(ret); - } - return(SVAL(p,0)); - } - - DEBUG(1,("Unknown long filename format %d\n",level)); - return(SVAL(p,0)); -} - - - - -/**************************************************************************** - act on the files in a dir listing - ****************************************************************************/ -static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir) -{ - - if (!((finfo->mode & aDIR) == 0 && *fileselection && - !mask_match(finfo->name,fileselection,False,False)) && - !(recurse_dir && (strequal(finfo->name,".") || - strequal(finfo->name,"..")))) - { - if (recurse_dir && (finfo->mode & aDIR)) - { - pstring mask2; - pstring sav_dir; - strcpy(sav_dir,cur_dir); - strcat(cur_dir,finfo->name); - strcat(cur_dir,"\\"); - strcpy(mask2,cur_dir); - - if (!fn) - DEBUG(0,("\n%s\n",CNV_LANG(cur_dir))); - - strcat(mask2,"*"); - - if (longdir) - do_long_dir(inbuf,outbuf,mask2,attribute,fn,True); - else - do_dir(inbuf,outbuf,mask2,attribute,fn,True); - - strcpy(cur_dir,sav_dir); - } - else - { - if (fn && do_this_one(finfo)) - fn(finfo); - } - } -} - - -/**************************************************************************** - do a directory listing, calling fn on each file found - ****************************************************************************/ -static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir) -{ - char *p; - int received = 0; - BOOL first = True; - char status[21]; - int num_asked = (max_xmit - 100)/DIR_STRUCT_SIZE; - int num_received = 0; - int i; - char *dirlist = NULL; - pstring mask; - file_info finfo; - - finfo = def_finfo; - - bzero(status,21); - - strcpy(mask,Mask); - - while (1) - { - bzero(outbuf,smb_size); - if (first) - set_message(outbuf,2,5 + strlen(mask),True); - else - set_message(outbuf,2,5 + 21,True); - -#if FFIRST - if (Protocol >= PROTOCOL_LANMAN1) - CVAL(outbuf,smb_com) = SMBffirst; - else -#endif - CVAL(outbuf,smb_com) = SMBsearch; - - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - SSVAL(outbuf,smb_vwv0,num_asked); - SSVAL(outbuf,smb_vwv1,attribute); - - p = smb_buf(outbuf); - *p++ = 4; - - if (first) - strcpy(p,mask); - else - strcpy(p,""); - p += strlen(p) + 1; - - *p++ = 5; - if (first) - SSVAL(p,0,0); - else - { - SSVAL(p,0,21); - p += 2; - memcpy(p,status,21); - } - - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT); - - received = SVAL(inbuf,smb_vwv0); - - DEBUG(5,("dir received %d\n",received)); - - DEBUG(6,("errstr=%s\n",smb_errstr(inbuf))); - - if (received <= 0) break; - - first = False; - - dirlist = Realloc(dirlist,(num_received + received)*DIR_STRUCT_SIZE); - - if (!dirlist) - return 0; + return(ret); + } + return(SVAL(p,0)); + } - p = smb_buf(inbuf) + 3; + DEBUG(1,("Unknown long filename format %d\n",level)); + return(SVAL(p,0)); +} - memcpy(dirlist+num_received*DIR_STRUCT_SIZE, - p,received*DIR_STRUCT_SIZE); - memcpy(status,p + ((received-1)*DIR_STRUCT_SIZE),21); - num_received += received; - if (CVAL(inbuf,smb_rcls) != 0) break; - } +/**************************************************************************** + act on the files in a dir listing + ****************************************************************************/ +static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir) +{ -#if FFIRST - if (!first && Protocol >= PROTOCOL_LANMAN1) + if (!((finfo->mode & aDIR) == 0 && *fileselection && + !mask_match(finfo->name,fileselection,False,False)) && + !(recurse_dir && (strequal(finfo->name,".") || + strequal(finfo->name,"..")))) { - bzero(outbuf,smb_size); - CVAL(outbuf,smb_com) = SMBfclose; - - SSVAL(outbuf,smb_tid,cnum); - setup_pkt(outbuf); - - p = smb_buf(outbuf); - *p++ = 4; - - strcpy(p,""); - p += strlen(p) + 1; - - *p++ = 5; - SSVAL(p,0,21); - p += 2; - memcpy(p,status,21); + if (recurse_dir && (finfo->mode & aDIR)) + { + pstring mask2; + pstring sav_dir; + strcpy(sav_dir,cur_dir); + strcat(cur_dir,finfo->name); + strcat(cur_dir,"\\"); + strcpy(mask2,cur_dir); - send_smb(Client,outbuf); - receive_smb(Client,inbuf,CLIENT_TIMEOUT,False); + if (!fn) + DEBUG(0,("\n%s\n",CNV_LANG(cur_dir))); - if (CVAL(inbuf,smb_rcls) != 0) - DEBUG(0,("Error closing search: %s\n",smb_errstr(inbuf))); - } -#endif + strcat(mask2,"*"); - if (!fn) - for (p=dirlist,i=0;i 200) - { - DEBUG(0,("ERROR: Looping in FIND_NEXT??\n")); - break; - } - - if (First) - { - setup = TRANSACT2_FINDFIRST; - SSVAL(param,0,attribute); /* attribute */ - SSVAL(param,2,max_matches); /* max count */ - SSVAL(param,4,8+4+2); /* resume required + close on end + continue */ - SSVAL(param,6,info_level); - SIVAL(param,8,0); - strcpy(param+12,mask); - } - else - { - setup = TRANSACT2_FINDNEXT; - SSVAL(param,0,ff_dir_handle); - SSVAL(param,2,max_matches); /* max count */ - SSVAL(param,4,info_level); - SIVAL(param,6,ff_resume_key); /* ff_resume_key */ - SSVAL(param,10,8+4+2); /* resume required + close on end + continue */ - strcpy(param+12,mask); - - DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n", - ff_dir_handle,ff_resume_key,ff_lastname,mask)); - } - /* ??? original code added 1 pad byte after param */ - - send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0, - NULL,param,&setup, - 0,12+strlen(mask)+1,1, - BUFFER_SIZE,10,0); - - if (!receive_trans_response(inbuf,SMBtrans2, - &resp_data_len,&resp_param_len, - &resp_data,&resp_param)) - { - DEBUG(3,("FIND%s gave %s\n",First?"FIRST":"NEXT",smb_errstr(inbuf))); - break; - } - - /* parse out some important return info */ - p = resp_param; - if (First) - { - ff_dir_handle = SVAL(p,0); - ff_searchcount = SVAL(p,2); - ff_eos = SVAL(p,4); - ff_lastname = SVAL(p,8); - } - else - { - ff_searchcount = SVAL(p,0); - ff_eos = SVAL(p,2); - ff_lastname = SVAL(p,6); - } - - if (ff_searchcount == 0) - break; - - /* point to the data bytes */ - p = resp_data; - - /* we might need the lastname for continuations */ - if (ff_lastname > 0) - { - switch(info_level) - { - case 260: - ff_resume_key =0; - StrnCpy(mask,p+ff_lastname,resp_data_len-ff_lastname); - /* strcpy(mask,p+ff_lastname+94); */ - break; - case 1: - strcpy(mask,p + ff_lastname + 1); - ff_resume_key = 0; - break; - } - } - else - strcpy(mask,""); - - /* and add them to the dirlist pool */ - dirlist = Realloc(dirlist,dirlist_len + resp_data_len); - - if (!dirlist) - { - DEBUG(0,("Failed to expand dirlist\n")); - break; - } - - /* put in a length for the last entry, to ensure we can chain entries - into the next packet */ - { - char *p2; - for (p2=p,i=0;i<(ff_searchcount-1);i++) - p2 += interpret_long_filename(info_level,p2,NULL); - SSVAL(p2,0,resp_data_len - PTR_DIFF(p2,p)); - } - - /* grab the data for later use */ - memcpy(dirlist+dirlist_len,p,resp_data_len); - dirlist_len += resp_data_len; - - total_received += ff_searchcount; - - if (resp_data) free(resp_data); resp_data = NULL; - if (resp_param) free(resp_param); resp_param = NULL; - - DEBUG(3,("received %d entries (eos=%d resume=%d)\n", - ff_searchcount,ff_eos,ff_resume_key)); - - First = False; - } - - if (!fn) - for (p=dirlist,i=0;i [-p port] [-d debuglevel] [-l log] ", pname)); @@ -4152,11 +4155,11 @@ void usage(char *pname) /**************************************************************************** main program ****************************************************************************/ -int main(int argc,char *argv[]) + int main(int argc,char *argv[]) { fstring base_directory; char *pname = argv[0]; - int port = 139; + int port = SMB_PORT; int opt; extern FILE *dbf; extern char *optarg; @@ -4175,6 +4178,8 @@ int main(int argc,char *argv[]) TimeInit(); charset_initialise(); + ipzero = *interpret_addr2("0.0.0.0"); + pid = getpid(); uid = getuid(); gid = getgid(); diff --git a/source3/client/clientutil.c b/source3/client/clientutil.c new file mode 100644 index 0000000000..e2427a4099 --- /dev/null +++ b/source3/client/clientutil.c @@ -0,0 +1,1029 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB client + Copyright (C) Andrew Tridgell 1994-1995 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef SYSLOG +#undef SYSLOG +#endif + +#include "includes.h" + +#ifndef REGISTER +#define REGISTER 0 +#endif + +pstring service=""; +pstring desthost=""; +pstring myname = ""; +pstring password = ""; +pstring username=""; +pstring workgroup=WORKGROUP; +BOOL got_pass = False; +BOOL connect_as_printer = False; +BOOL connect_as_ipc = False; + +char cryptkey[8]; +BOOL doencrypt=False; + +extern pstring user_socket_options; + +/* 30 second timeout on most commands */ +#define CLIENT_TIMEOUT (30*1000) +#define SHORT_TIMEOUT (5*1000) + +int name_type = 0x20; + +int max_protocol = PROTOCOL_NT1; + +BOOL readbraw_supported = False; +BOOL writebraw_supported = False; + +extern int DEBUGLEVEL; + +int cnum = 0; +int pid = 0; +int gid = 0; +int uid = 0; +int mid = 0; + +int max_xmit = BUFFER_SIZE; + +BOOL have_ip = False; + +struct in_addr dest_ip; + +extern int Protocol; + +extern int Client; + + +/**************************************************************************** +setup basics in a outgoing packet +****************************************************************************/ +void cli_setup_pkt(char *outbuf) +{ + SSVAL(outbuf,smb_pid,pid); + SSVAL(outbuf,smb_uid,uid); + SSVAL(outbuf,smb_mid,mid); + if (Protocol > PROTOCOL_CORE) + { + SCVAL(outbuf,smb_flg,0x8); + SSVAL(outbuf,smb_flg2,0x1); + } +} + +/**************************************************************************** + receive a SMB trans or trans2 response allocating the necessary memory + ****************************************************************************/ +BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, + int *param_len, char **data,char **param) +{ + int total_data=0; + int total_param=0; + int this_data,this_param; + + *data_len = *param_len = 0; + + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + show_msg(inbuf); + + /* sanity check */ + if (CVAL(inbuf,smb_com) != trans) + { + DEBUG(0,("Expected %s response, got command 0x%02x\n", + trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); + return(False); + } + if (CVAL(inbuf,smb_rcls) != 0) + return(False); + + /* parse out the lengths */ + total_data = SVAL(inbuf,smb_tdrcnt); + total_param = SVAL(inbuf,smb_tprcnt); + + /* allocate it */ + *data = Realloc(*data,total_data); + *param = Realloc(*param,total_param); + + while (1) + { + this_data = SVAL(inbuf,smb_drcnt); + this_param = SVAL(inbuf,smb_prcnt); + if (this_data) + memcpy(*data + SVAL(inbuf,smb_drdisp), + smb_base(inbuf) + SVAL(inbuf,smb_droff), + this_data); + if (this_param) + memcpy(*param + SVAL(inbuf,smb_prdisp), + smb_base(inbuf) + SVAL(inbuf,smb_proff), + this_param); + *data_len += this_data; + *param_len += this_param; + + /* parse out the total lengths again - they can shrink! */ + total_data = SVAL(inbuf,smb_tdrcnt); + total_param = SVAL(inbuf,smb_tprcnt); + + if (total_data <= *data_len && total_param <= *param_len) + break; + + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + show_msg(inbuf); + + /* sanity check */ + if (CVAL(inbuf,smb_com) != trans) + { + DEBUG(0,("Expected %s response, got command 0x%02x\n", + trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com))); + return(False); + } + if (CVAL(inbuf,smb_rcls) != 0) + return(False); + } + + return(True); +} + +/**************************************************************************** +send a session request +****************************************************************************/ +BOOL cli_send_session_request(char *inbuf, char *outbuf) +{ + fstring dest; + char *p; + int len = 4; + /* send a session request (RFC 8002) */ + + strcpy(dest,desthost); + p = strchr(dest,'.'); + if (p) *p = 0; + + /* put in the destination name */ + p = outbuf+len; + name_mangle(dest,p,name_type); + len += name_len(p); + + /* and my name */ + p = outbuf+len; + name_mangle(myname,p,0); + len += name_len(p); + + /* setup the packet length */ + _smb_setlen(outbuf,len); + CVAL(outbuf,0) = 0x81; + + send_smb(Client,outbuf); + DEBUG(5,("Sent session request\n")); + + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + + if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */ + { + /* For information, here is the response structure. + * We do the byte-twiddling to for portability. + struct RetargetResponse{ + unsigned char type; + unsigned char flags; + int16 length; + int32 ip_addr; + int16 port; + }; + */ + extern int Client; + int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9); + /* SESSION RETARGET */ + putip((char *)&dest_ip,inbuf+4); + + close_sockets(); + Client = open_socket_out(SOCK_STREAM, &dest_ip, port); + if (Client == -1) + return False; + + DEBUG(3,("Retargeted\n")); + + set_socket_options(Client,user_socket_options); + + /* Try again */ + return cli_send_session_request(inbuf,outbuf); + } /* C. Hoch 9/14/95 End */ + + + if (CVAL(inbuf,0) != 0x82) + { + int ecode = CVAL(inbuf,4); + DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n", + CVAL(inbuf,0),ecode,myname,desthost)); + switch (ecode) + { + case 0x80: + DEBUG(0,("Not listening on called name\n")); + DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); + DEBUG(0,("You may find the -I option useful for this\n")); + break; + case 0x81: + DEBUG(0,("Not listening for calling name\n")); + DEBUG(0,("Try to connect as another name (instead of %s)\n",myname)); + DEBUG(0,("You may find the -n option useful for this\n")); + break; + case 0x82: + DEBUG(0,("Called name not present\n")); + DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost)); + DEBUG(0,("You may find the -I option useful for this\n")); + break; + case 0x83: + DEBUG(0,("Called name present, but insufficient resources\n")); + DEBUG(0,("Perhaps you should try again later?\n")); + break; + default: + DEBUG(0,("Unspecified error 0x%X\n",ecode)); + DEBUG(0,("Your server software is being unfriendly\n")); + break; + } + return(False); + } + return(True); +} + + +static struct { + int prot; + char *name; + } +prots[] = + { + {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, + {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, + {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, + {PROTOCOL_LANMAN1,"LANMAN1.0"}, + {PROTOCOL_LANMAN2,"LM1.2X002"}, + {PROTOCOL_LANMAN2,"Samba"}, + {PROTOCOL_NT1,"NT LM 0.12"}, + {PROTOCOL_NT1,"NT LANMAN 1.0"}, + {-1,NULL} + }; + +/**************************************************************************** +send a login command +****************************************************************************/ +BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup) +{ + BOOL was_null = (!inbuf && !outbuf); + int sesskey=0; + time_t servertime = 0; + extern int serverzone; + int sec_mode=0; + int crypt_len; + int max_vcs=0; + char *pass = NULL; + pstring dev; + char *p; + int numprots; + + if (was_null) + { + inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + } + + strcpy(dev,"A:"); + if (connect_as_printer) + strcpy(dev,"LPT1:"); + if (connect_as_ipc) + strcpy(dev,"IPC"); + + + if (start_session && !cli_send_session_request(inbuf,outbuf)) + { + if (was_null) + { + free(inbuf); + free(outbuf); + } + return(False); + } + + bzero(outbuf,smb_size); + + /* setup the protocol strings */ + { + int plength; + + for (plength=0,numprots=0; + prots[numprots].name && prots[numprots].prot<=max_protocol; + numprots++) + plength += strlen(prots[numprots].name)+2; + + set_message(outbuf,0,plength,True); + + p = smb_buf(outbuf); + for (numprots=0; + prots[numprots].name && prots[numprots].prot<=max_protocol; + numprots++) + { + *p++ = 2; + strcpy(p,prots[numprots].name); + p += strlen(p) + 1; + } + } + + CVAL(outbuf,smb_com) = SMBnegprot; + cli_setup_pkt(outbuf); + + CVAL(smb_buf(outbuf),0) = 2; + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + + show_msg(inbuf); + + if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots)) + { + DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n", + myname,desthost,smb_errstr(inbuf))); + if (was_null) + { + free(inbuf); + free(outbuf); + } + return(False); + } + + Protocol = prots[SVAL(inbuf,smb_vwv0)].prot; + + + if (Protocol < PROTOCOL_NT1) { + sec_mode = SVAL(inbuf,smb_vwv1); + max_xmit = SVAL(inbuf,smb_vwv2); + sesskey = IVAL(inbuf,smb_vwv6); + serverzone = SVALS(inbuf,smb_vwv10)*60; + /* this time is converted to GMT by make_unix_date */ + servertime = make_unix_date(inbuf+smb_vwv8); + if (Protocol >= PROTOCOL_COREPLUS) { + readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0); + writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0); + } + crypt_len = smb_buflen(inbuf); + memcpy(cryptkey,smb_buf(inbuf),8); + DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3))); + max_vcs = SVAL(inbuf,smb_vwv4); + DEBUG(3,("max vcs %d\n",max_vcs)); + DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5))); + } else { + /* NT protocol */ + sec_mode = CVAL(inbuf,smb_vwv1); + max_xmit = IVAL(inbuf,smb_vwv3+1); + sesskey = IVAL(inbuf,smb_vwv7+1); + serverzone = SVALS(inbuf,smb_vwv15+1)*60; + /* this time arrives in real GMT */ + servertime = interpret_long_date(inbuf+smb_vwv11+1); + crypt_len = CVAL(inbuf,smb_vwv16+1); + memcpy(cryptkey,smb_buf(inbuf),8); + if (IVAL(inbuf,smb_vwv9+1) & 1) + readbraw_supported = writebraw_supported = True; + DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1))); + max_vcs = SVAL(inbuf,smb_vwv2+1); + DEBUG(3,("max vcs %d\n",max_vcs)); + DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1))); + DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1))); + } + + DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1))); + DEBUG(3,("max xmt %d\n",max_xmit)); + DEBUG(3,("Got %d byte crypt key\n",crypt_len)); + DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name)); + + doencrypt = ((sec_mode & 2) != 0); + + if (servertime) { + static BOOL done_time = False; + if (!done_time) { + DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n", + asctime(LocalTime(&servertime)), + -(double)(serverzone/3600.0))); + done_time = True; + } + } + + get_pass: + + if (got_pass) + pass = password; + else + pass = (char *)getpass("Password: "); + + if (Protocol >= PROTOCOL_LANMAN1 && use_setup) + { + fstring pword; + int passlen = strlen(pass)+1; + strcpy(pword,pass); + +#ifdef SMB_PASSWD + if (doencrypt && *pass) { + DEBUG(3,("Using encrypted passwords\n")); + passlen = 24; + SMBencrypt(pass,cryptkey,pword); + } +#else + doencrypt = False; +#endif + + /* if in share level security then don't send a password now */ + if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;} + + /* send a session setup command */ + bzero(outbuf,smb_size); + + if (Protocol < PROTOCOL_NT1) { + set_message(outbuf,10,1 + strlen(username) + passlen,True); + CVAL(outbuf,smb_com) = SMBsesssetupX; + cli_setup_pkt(outbuf); + + CVAL(outbuf,smb_vwv0) = 0xFF; + SSVAL(outbuf,smb_vwv2,max_xmit); + SSVAL(outbuf,smb_vwv3,2); + SSVAL(outbuf,smb_vwv4,max_vcs-1); + SIVAL(outbuf,smb_vwv5,sesskey); + SSVAL(outbuf,smb_vwv7,passlen); + p = smb_buf(outbuf); + memcpy(p,pword,passlen); + p += passlen; + strcpy(p,username); + } else { + if (!doencrypt) passlen--; + /* for Win95 */ + set_message(outbuf,13,0,True); + CVAL(outbuf,smb_com) = SMBsesssetupX; + cli_setup_pkt(outbuf); + + CVAL(outbuf,smb_vwv0) = 0xFF; + SSVAL(outbuf,smb_vwv2,BUFFER_SIZE); + SSVAL(outbuf,smb_vwv3,2); + SSVAL(outbuf,smb_vwv4,getpid()); + SIVAL(outbuf,smb_vwv5,sesskey); + SSVAL(outbuf,smb_vwv7,passlen); + SSVAL(outbuf,smb_vwv8,0); + p = smb_buf(outbuf); + memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7); + strcpy(p,username);p = skip_string(p,1); + strcpy(p,workgroup);p = skip_string(p,1); + strcpy(p,"Unix");p = skip_string(p,1); + strcpy(p,"Samba");p = skip_string(p,1); + set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False); + } + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + + show_msg(inbuf); + + if (CVAL(inbuf,smb_rcls) != 0) + { + if (! *pass && + ((CVAL(inbuf,smb_rcls) == ERRDOS && + SVAL(inbuf,smb_err) == ERRnoaccess) || + (CVAL(inbuf,smb_rcls) == ERRSRV && + SVAL(inbuf,smb_err) == ERRbadpw))) + { + got_pass = False; + DEBUG(3,("resending login\n")); + goto get_pass; + } + + DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n", + username,myname,desthost,smb_errstr(inbuf))); + DEBUG(0,("You might find the -U or -n options useful\n")); + DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n")); + DEBUG(0,("Some servers also insist on uppercase-only passwords\n")); + if (was_null) + { + free(inbuf); + free(outbuf); + } + return(False); + } + + if (Protocol >= PROTOCOL_NT1) { + char *domain,*os,*lanman; + p = smb_buf(inbuf); + os = p; + lanman = skip_string(os,1); + domain = skip_string(lanman,1); + if (*domain || *os || *lanman) + DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman)); + } + + /* use the returned uid from now on */ + if (SVAL(inbuf,smb_uid) != uid) + DEBUG(3,("Server gave us a UID of %d. We gave %d\n", + SVAL(inbuf,smb_uid),uid)); + uid = SVAL(inbuf,smb_uid); + } + + /* now we've got a connection - send a tcon message */ + bzero(outbuf,smb_size); + + if (strncmp(service,"\\\\",2) != 0) + { + DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n")); + DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n")); + } + + + again2: + + { + int passlen = strlen(pass)+1; + fstring pword; + strcpy(pword,pass); + +#ifdef SMB_PASSWD + if (doencrypt && *pass) { + passlen=24; + SMBencrypt(pass,cryptkey,pword); + } +#endif + + /* if in user level security then don't send a password now */ + if ((sec_mode & 1)) { + strcpy(pword, ""); passlen=1; + } + + set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True); + CVAL(outbuf,smb_com) = SMBtconX; + cli_setup_pkt(outbuf); + + SSVAL(outbuf,smb_vwv0,0xFF); + SSVAL(outbuf,smb_vwv3,passlen); + + p = smb_buf(outbuf); + memcpy(p,pword,passlen); + p += passlen; + strcpy(p,service); + p = skip_string(p,1); + strcpy(p,dev); + } + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,CLIENT_TIMEOUT); + + /* trying again with a blank password */ + if (CVAL(inbuf,smb_rcls) != 0 && + (int)strlen(pass) > 0 && + !doencrypt && + Protocol >= PROTOCOL_LANMAN1) + { + DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf))); + strcpy(pass,""); + goto again2; + } + + if (CVAL(inbuf,smb_rcls) != 0) + { + DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf))); + DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n")); + DEBUG(0,("Some servers insist that these be in uppercase\n")); + if (was_null) + { + free(inbuf); + free(outbuf); + } + return(False); + } + + + max_xmit = MIN(max_xmit,BUFFER_SIZE-4); + if (max_xmit <= 0) + max_xmit = BUFFER_SIZE - 4; + + cnum = SVAL(inbuf,smb_tid); + + DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit)); + + if (was_null) + { + free(inbuf); + free(outbuf); + } + return True; +} + + +/**************************************************************************** +send a logout command +****************************************************************************/ +void cli_send_logout(void) +{ + pstring inbuf,outbuf; + + bzero(outbuf,smb_size); + set_message(outbuf,0,0,True); + CVAL(outbuf,smb_com) = SMBtdis; + SSVAL(outbuf,smb_tid,cnum); + cli_setup_pkt(outbuf); + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,SHORT_TIMEOUT); + + if (CVAL(inbuf,smb_rcls) != 0) + { + DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf))); + } + + +#ifdef STATS + stats_report(); +#endif + exit(0); +} + + + +/**************************************************************************** +call a remote api +****************************************************************************/ +BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt, + int *rdrcnt, char *param,char *data, char **rparam,char **rdata) +{ + static char *inbuf=NULL; + static char *outbuf=NULL; + + if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + + cli_send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0, + data,param,NULL, + drcnt,prcnt,0, + mdrcnt,mprcnt,0); + + return (cli_receive_trans_response(inbuf,SMBtrans, + rdrcnt,rprcnt, + rdata,rparam)); +} + +/**************************************************************************** + send a SMB trans or trans2 request + ****************************************************************************/ +BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags, + char *data,char *param,uint16 *setup, int ldata,int lparam, + int lsetup,int mdata,int mparam,int msetup) +{ + int i; + int this_ldata,this_lparam; + int tot_data=0,tot_param=0; + char *outdata,*outparam; + pstring inbuf; + char *p; + + this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */ + this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam)); + + bzero(outbuf,smb_size); + set_message(outbuf,14+lsetup,0,True); + CVAL(outbuf,smb_com) = trans; + SSVAL(outbuf,smb_tid,cnum); + cli_setup_pkt(outbuf); + + outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3); + outdata = outparam+this_lparam; + + /* primary request */ + SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */ + SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */ + SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */ + SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */ + SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */ + SSVAL(outbuf,smb_flags,flags); /* flags */ + SIVAL(outbuf,smb_timeout,0); /* timeout */ + SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */ + SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */ + SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */ + SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */ + SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */ + for (i=0;ih_addr); + } + + Client = open_socket_out(SOCK_STREAM, &dest_ip, port); + if (Client == -1) + return False; + + DEBUG(3,("Connected\n")); + + set_socket_options(Client,user_socket_options); + + return True; +} + +/**************************************************************************** +close and open the connection again +****************************************************************************/ +BOOL cli_reopen_connection(char *inbuf,char *outbuf) +{ + static int open_count=0; + + open_count++; + + if (open_count>5) return(False); + + DEBUG(1,("Trying to re-open connection\n")); + + set_message(outbuf,0,0,True); + SCVAL(outbuf,smb_com,SMBtdis); + SSVAL(outbuf,smb_tid,cnum); + cli_setup_pkt(outbuf); + + send_smb(Client,outbuf); + receive_smb(Client,inbuf,SHORT_TIMEOUT); + + close_sockets(); + if (!cli_open_sockets(0)) return(False); + + return(cli_send_login(inbuf,outbuf,True,True)); +} + +/* error code stuff - put together by Merik Karman + merik@blackadder.dsh.oz.au */ + +typedef struct +{ + char *name; + int code; + char *message; +} err_code_struct; + +/* Dos Error Messages */ +err_code_struct dos_msgs[] = { + {"ERRbadfunc",1,"Invalid function."}, + {"ERRbadfile",2,"File not found."}, + {"ERRbadpath",3,"Directory invalid."}, + {"ERRnofids",4,"No file descriptors available"}, + {"ERRnoaccess",5,"Access denied."}, + {"ERRbadfid",6,"Invalid file handle."}, + {"ERRbadmcb",7,"Memory control blocks destroyed."}, + {"ERRnomem",8,"Insufficient server memory to perform the requested function."}, + {"ERRbadmem",9,"Invalid memory block address."}, + {"ERRbadenv",10,"Invalid environment."}, + {"ERRbadformat",11,"Invalid format."}, + {"ERRbadaccess",12,"Invalid open mode."}, + {"ERRbaddata",13,"Invalid data."}, + {"ERR",14,"reserved."}, + {"ERRbaddrive",15,"Invalid drive specified."}, + {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."}, + {"ERRdiffdevice",17,"Not same device."}, + {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."}, + {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."}, + {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, + {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."}, + {"ERRbadpipe",230,"Pipe invalid."}, + {"ERRpipebusy",231,"All instances of the requested pipe are busy."}, + {"ERRpipeclosing",232,"Pipe close in progress."}, + {"ERRnotconnected",233,"No process on other end of pipe."}, + {"ERRmoredata",234,"There is more data to be returned."}, + {NULL,-1,NULL}}; + +/* Server Error Messages */ +err_code_struct server_msgs[] = { + {"ERRerror",1,"Non-specific error code."}, + {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."}, + {"ERRbadtype",3,"reserved."}, + {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."}, + {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."}, + {"ERRinvnetname",6,"Invalid network name in tree connect."}, + {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."}, + {"ERRqfull",49,"Print queue full (files) -- returned by open print file."}, + {"ERRqtoobig",50,"Print queue full -- no space."}, + {"ERRqeof",51,"EOF on print queue dump."}, + {"ERRinvpfid",52,"Invalid print file FID."}, + {"ERRsmbcmd",64,"The server did not recognize the command received."}, + {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."}, + {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."}, + {"ERRreserved",68,"reserved."}, + {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."}, + {"ERRreserved",70,"reserved."}, + {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."}, + {"ERRpaused",81,"Server is paused."}, + {"ERRmsgoff",82,"Not receiving messages."}, + {"ERRnoroom",83,"No room to buffer message."}, + {"ERRrmuns",87,"Too many remote user names."}, + {"ERRtimeout",88,"Operation timed out."}, + {"ERRnoresource",89,"No resources currently available for request."}, + {"ERRtoomanyuids",90,"Too many UIDs active on this session."}, + {"ERRbaduid",91,"The UID is not known as a valid ID on this session."}, + {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."}, + {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."}, + {"ERRcontmpx",252,"Continue in MPX mode."}, + {"ERRreserved",253,"reserved."}, + {"ERRreserved",254,"reserved."}, + {"ERRnosupport",0xFFFF,"Function not supported."}, + {NULL,-1,NULL}}; + +/* Hard Error Messages */ +err_code_struct hard_msgs[] = { + {"ERRnowrite",19,"Attempt to write on write-protected diskette."}, + {"ERRbadunit",20,"Unknown unit."}, + {"ERRnotready",21,"Drive not ready."}, + {"ERRbadcmd",22,"Unknown command."}, + {"ERRdata",23,"Data error (CRC)."}, + {"ERRbadreq",24,"Bad request structure length."}, + {"ERRseek",25 ,"Seek error."}, + {"ERRbadmedia",26,"Unknown media type."}, + {"ERRbadsector",27,"Sector not found."}, + {"ERRnopaper",28,"Printer out of paper."}, + {"ERRwrite",29,"Write fault."}, + {"ERRread",30,"Read fault."}, + {"ERRgeneral",31,"General failure."}, + {"ERRbadshare",32,"A open conflicts with an existing open."}, + {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."}, + {"ERRwrongdisk",34,"The wrong disk was found in a drive."}, + {"ERRFCBUnavail",35,"No FCBs are available to process request."}, + {"ERRsharebufexc",36,"A sharing buffer has been exceeded."}, + {NULL,-1,NULL}}; + + +struct +{ + int code; + char *class; + err_code_struct *err_msgs; +} err_classes[] = { + {0,"SUCCESS",NULL}, + {0x01,"ERRDOS",dos_msgs}, + {0x02,"ERRSRV",server_msgs}, + {0x03,"ERRHRD",hard_msgs}, + {0x04,"ERRXOS",NULL}, + {0xE1,"ERRRMX1",NULL}, + {0xE2,"ERRRMX2",NULL}, + {0xE3,"ERRRMX3",NULL}, + {0xFF,"ERRCMD",NULL}, + {-1,NULL,NULL}}; + + +/**************************************************************************** +return a SMB error string from a SMB buffer +****************************************************************************/ +char *smb_errstr(char *inbuf) +{ + static pstring ret; + int class = CVAL(inbuf,smb_rcls); + int num = SVAL(inbuf,smb_err); + int i,j; + + for (i=0;err_classes[i].class;i++) + if (err_classes[i].code == class) + { + if (err_classes[i].err_msgs) + { + err_code_struct *err = err_classes[i].err_msgs; + for (j=0;err[j].name;j++) + if (num == err[j].code) + { + if (DEBUGLEVEL > 0) + sprintf(ret,"%s - %s (%s)",err_classes[i].class, + err[j].name,err[j].message); + else + sprintf(ret,"%s - %s",err_classes[i].class,err[j].name); + return ret; + } + } + + sprintf(ret,"%s - %d",err_classes[i].class,num); + return ret; + } + + sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num); + return(ret); +} diff --git a/source3/client/clitar.c b/source3/client/clitar.c index 0701aac1cf..2de09c66c1 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -23,12 +23,6 @@ #include "includes.h" #include "clitar.h" -extern void setup_pkt(char *outbuf); -extern BOOL reopen_connection(char *inbuf,char *outbuf); -extern void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); - -int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind); - extern BOOL recurse; #define SEPARATORS " \t\n\r" -- cgit