2 Unix SMB/Netbios implementation.
4 SMB client generic functions
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 extern int DEBUGLEVEL;
31 /****************************************************************************
33 ****************************************************************************/
34 static BOOL cli_receive_smb(struct cli_state *cli)
36 return client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
39 /****************************************************************************
40 send an smb to a fd and re-establish if necessary
41 ****************************************************************************/
42 static BOOL cli_send_smb(struct cli_state *cli)
47 BOOL reestablished=False;
49 len = smb_len(cli->outbuf) + 4;
51 while (nwritten < len) {
52 ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
53 if (ret <= 0 && errno == EPIPE && !reestablished) {
54 if (cli_reestablish_connection(cli)) {
61 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",
72 /*****************************************************
73 RAP error codes - a small start but will be extended.
74 *******************************************************/
82 {5, "User has insufficient privilege" },
83 {86, "The specified password is invalid" },
84 {2226, "Operation only permitted on a Primary Domain Controller" },
85 {2242, "The password of this user has expired." },
86 {2243, "The password of this user cannot change." },
87 {2244, "This password cannot be used now (password history conflict)." },
88 {2245, "The password is shorter than required." },
89 {2246, "The password of this user is too recent to change."},
93 /****************************************************************************
94 return a description of an SMB error
95 ****************************************************************************/
96 static char *cli_smb_errstr(struct cli_state *cli)
98 return smb_errstr(cli->inbuf);
101 /******************************************************
102 Return an error message - either an SMB error or a RAP
104 *******************************************************/
106 char *cli_errstr(struct cli_state *cli)
108 static fstring error_message;
114 * Errors are of three kinds - smb errors,
115 * dealt with by cli_smb_errstr, NT errors,
116 * whose code is in cli.nt_error, and rap
117 * errors, whose error code is in cli.rap_error.
120 cli_error(cli, &errclass, &errnum);
124 return cli_smb_errstr(cli);
128 * Was it an NT error ?
133 char *nt_msg = get_nt_error_msg(cli->nt_error);
137 slprintf(error_message, sizeof(fstring) - 1, "NT code %d", cli->nt_error);
141 fstrcpy(error_message, nt_msg);
144 return error_message;
148 * Must have been a rap error.
151 slprintf(error_message, sizeof(error_message) - 1, "code %d", cli->rap_error);
153 for (i = 0; rap_errmap[i].message != NULL; i++)
155 if (rap_errmap[i].err == cli->rap_error)
157 fstrcpy( error_message, rap_errmap[i].message);
162 return error_message;
165 /****************************************************************************
166 setup basics in a outgoing packet
167 ****************************************************************************/
168 static void cli_setup_packet(struct cli_state *cli)
172 SSVAL(cli->outbuf,smb_pid,cli->pid);
173 SSVAL(cli->outbuf,smb_uid,cli->vuid);
174 SSVAL(cli->outbuf,smb_mid,cli->mid);
175 if (cli->protocol > PROTOCOL_CORE) {
176 SCVAL(cli->outbuf,smb_flg,0x8);
177 SSVAL(cli->outbuf,smb_flg2,0x1);
182 /*****************************************************************************
183 Convert a character pointer in a cli_call_api() response to a form we can use.
184 This function contains code to prevent core dumps if the server returns
186 *****************************************************************************/
187 static char *fix_char_ptr(unsigned int datap, unsigned int converter,
188 char *rdata, int rdrcnt)
190 if (datap == 0) { /* turn NULL pointers into zero length strings */
193 unsigned int offset = datap - converter;
195 if (offset >= rdrcnt) {
196 DEBUG(1,("bad char ptr: datap=%u, converter=%u rdrcnt=%d>",
197 datap, converter, rdrcnt));
200 return &rdata[offset];
205 /****************************************************************************
206 send a SMB trans or trans2 request
207 ****************************************************************************/
208 static BOOL cli_send_trans(struct cli_state *cli, int trans,
209 char *name, int pipe_name_len,
211 uint16 *setup, int lsetup, int msetup,
212 char *param, int lparam, int mparam,
213 char *data, int ldata, int mdata)
216 int this_ldata,this_lparam;
217 int tot_data=0,tot_param=0;
218 char *outdata,*outparam;
221 this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
222 this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
224 bzero(cli->outbuf,smb_size);
225 set_message(cli->outbuf,14+lsetup,0,True);
226 CVAL(cli->outbuf,smb_com) = trans;
227 SSVAL(cli->outbuf,smb_tid, cli->cnum);
228 cli_setup_packet(cli);
230 outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len+1 : 3);
231 outdata = outparam+this_lparam;
233 /* primary request */
234 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
235 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
236 SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */
237 SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */
238 SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */
239 SSVAL(cli->outbuf,smb_flags,flags); /* flags */
240 SIVAL(cli->outbuf,smb_timeout,0); /* timeout */
241 SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */
242 SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */
243 SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */
244 SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
245 SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
246 for (i=0;i<lsetup;i++) /* setup[] */
247 SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
248 p = smb_buf(cli->outbuf);
249 if (trans==SMBtrans) {
250 memcpy(p,name, pipe_name_len + 1); /* name[] */
252 *p++ = 0; /* put in a null smb_name */
253 *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */
255 if (this_lparam) /* param[] */
256 memcpy(outparam,param,this_lparam);
257 if (this_ldata) /* data[] */
258 memcpy(outdata,data,this_ldata);
259 set_message(cli->outbuf,14+lsetup, /* wcnt, bcc */
260 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
262 show_msg(cli->outbuf);
265 if (this_ldata < ldata || this_lparam < lparam) {
266 /* receive interim response */
267 if (!cli_receive_smb(cli) ||
268 CVAL(cli->inbuf,smb_rcls) != 0) {
272 tot_data = this_ldata;
273 tot_param = this_lparam;
275 while (tot_data < ldata || tot_param < lparam) {
276 this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */
277 this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam));
279 set_message(cli->outbuf,trans==SMBtrans?8:9,0,True);
280 CVAL(cli->outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
282 outparam = smb_buf(cli->outbuf);
283 outdata = outparam+this_lparam;
285 /* secondary request */
286 SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */
287 SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */
288 SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */
289 SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */
290 SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */
291 SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */
292 SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
293 SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
294 if (trans==SMBtrans2)
295 SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
296 if (this_lparam) /* param[] */
297 memcpy(outparam,param,this_lparam);
298 if (this_ldata) /* data[] */
299 memcpy(outdata,data,this_ldata);
300 set_message(cli->outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
301 PTR_DIFF(outdata+this_ldata,smb_buf(cli->outbuf)),False);
303 show_msg(cli->outbuf);
306 tot_data += this_ldata;
307 tot_param += this_lparam;
315 /****************************************************************************
316 receive a SMB trans or trans2 response allocating the necessary memory
317 ****************************************************************************/
318 static BOOL cli_receive_trans(struct cli_state *cli,int trans,
319 char **param, int *param_len,
320 char **data, int *data_len)
324 int this_data,this_param;
326 *data_len = *param_len = 0;
328 if (!cli_receive_smb(cli))
331 show_msg(cli->inbuf);
334 if (CVAL(cli->inbuf,smb_com) != trans) {
335 DEBUG(0,("Expected %s response, got command 0x%02x\n",
336 trans==SMBtrans?"SMBtrans":"SMBtrans2",
337 CVAL(cli->inbuf,smb_com)));
341 if (cli_error(cli, NULL, NULL))
346 /* parse out the lengths */
347 total_data = SVAL(cli->inbuf,smb_tdrcnt);
348 total_param = SVAL(cli->inbuf,smb_tprcnt);
351 *data = Realloc(*data,total_data);
352 *param = Realloc(*param,total_param);
355 this_data = SVAL(cli->inbuf,smb_drcnt);
356 this_param = SVAL(cli->inbuf,smb_prcnt);
358 if (this_data + *data_len > total_data ||
359 this_param + *param_len > total_param) {
360 DEBUG(1,("Data overflow in cli_receive_trans\n"));
365 memcpy(*data + SVAL(cli->inbuf,smb_drdisp),
366 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_droff),
369 memcpy(*param + SVAL(cli->inbuf,smb_prdisp),
370 smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_proff),
372 *data_len += this_data;
373 *param_len += this_param;
375 /* parse out the total lengths again - they can shrink! */
376 total_data = SVAL(cli->inbuf,smb_tdrcnt);
377 total_param = SVAL(cli->inbuf,smb_tprcnt);
379 if (total_data <= *data_len && total_param <= *param_len)
382 if (!cli_receive_smb(cli))
385 show_msg(cli->inbuf);
388 if (CVAL(cli->inbuf,smb_com) != trans) {
389 DEBUG(0,("Expected %s response, got command 0x%02x\n",
390 trans==SMBtrans?"SMBtrans":"SMBtrans2",
391 CVAL(cli->inbuf,smb_com)));
394 if (cli_error(cli, NULL, NULL))
403 /****************************************************************************
404 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
405 ****************************************************************************/
406 BOOL cli_api_pipe(struct cli_state *cli, char *pipe_name, int pipe_name_len,
407 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
408 char *params, uint32 param_count, uint32 max_param_count,
409 char *data, uint32 data_count, uint32 max_data_count,
410 char **rparam, uint32 *rparam_count,
411 char **rdata, uint32 *rdata_count)
413 if (pipe_name_len == 0)
414 pipe_name_len = strlen(pipe_name);
416 cli_send_trans(cli, SMBtrans,
417 pipe_name, pipe_name_len,
418 0,0, /* fid, flags */
419 setup, setup_count, max_setup_count,
420 params, param_count, max_param_count,
421 data, data_count, max_data_count);
423 return (cli_receive_trans(cli, SMBtrans,
424 rparam, (int *)rparam_count,
425 rdata, (int *)rdata_count));
428 /****************************************************************************
430 ****************************************************************************/
431 BOOL cli_api(struct cli_state *cli,
432 char *param, int prcnt, int mprcnt,
433 char *data, int drcnt, int mdrcnt,
434 char **rparam, int *rprcnt,
435 char **rdata, int *rdrcnt)
437 cli_send_trans(cli,SMBtrans,
438 PIPE_LANMAN,strlen(PIPE_LANMAN), /* Name, length */
439 0,0, /* fid, flags */
440 NULL,0,0, /* Setup, length, max */
441 param, prcnt, mprcnt, /* Params, length, max */
442 data, drcnt, mdrcnt /* Data, length, max */
445 return (cli_receive_trans(cli,SMBtrans,
451 /****************************************************************************
452 perform a NetWkstaUserLogon
453 ****************************************************************************/
454 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
462 memset(param, 0, sizeof(param));
464 /* send a SMBtrans command with api NetWkstaUserLogon */
466 SSVAL(p,0,132); /* api number */
468 pstrcpy(p,"OOWb54WrLh");
469 p = skip_string(p,1);
470 pstrcpy(p,"WB21BWDWWDDDDDDDzzzD");
471 p = skip_string(p,1);
480 pstrcpy(p, workstation);
483 SSVAL(p, 0, CLI_BUFFER_SIZE);
485 SSVAL(p, 0, CLI_BUFFER_SIZE);
489 param, PTR_DIFF(p,param),1024, /* param, length, max */
490 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
491 &rparam, &rprcnt, /* return params, return size */
492 &rdata, &rdrcnt /* return data, return size */
494 cli->rap_error = SVAL(rparam,0);
497 if (cli->rap_error == 0) {
498 DEBUG(4,("NetWkstaUserLogon success\n"));
499 cli->privilages = SVAL(p, 24);
500 fstrcpy(cli->eff_name,p+2);
502 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
510 return (cli->rap_error == 0);
513 /****************************************************************************
514 call a NetShareEnum - try and browse available connections on a host
515 ****************************************************************************/
516 BOOL cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *))
525 /* now send a SMBtrans command with api RNetShareEnum */
527 SSVAL(p,0,0); /* api number */
530 p = skip_string(p,1);
532 p = skip_string(p,1);
538 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
539 NULL, 0, 0xFFFF, /* data, length, maxlen */
540 &rparam, &rprcnt, /* return params, length */
541 &rdata, &rdrcnt)) /* return data, length */
543 int res = SVAL(rparam,0);
544 int converter=SVAL(rparam,2);
547 if (res == 0 || res == ERRmoredata) {
548 count=SVAL(rparam,4);
551 for (i=0;i<count;i++,p+=20) {
553 int type = SVAL(p,14);
554 int comment_offset = IVAL(p,16) & 0xFFFF;
555 char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
556 fn(sname, type, cmnt);
559 DEBUG(4,("NetShareEnum res=%d\n", res));
562 DEBUG(4,("NetShareEnum failed\n"));
574 /****************************************************************************
575 call a NetServerEnum for the specified workgroup and servertype mask.
576 This function then calls the specified callback function for each name returned.
578 The callback function takes 3 arguments: the machine name, the server type and
580 ****************************************************************************/
581 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
582 void (*fn)(const char *, uint32, const char *))
592 /* send a SMBtrans command with api NetServerEnum */
594 SSVAL(p,0,0x68); /* api number */
596 pstrcpy(p,"WrLehDz");
597 p = skip_string(p,1);
599 pstrcpy(p,"B16BBDz");
601 p = skip_string(p,1);
603 SSVAL(p,2,CLI_BUFFER_SIZE);
608 pstrcpy(p, workgroup);
609 p = skip_string(p,1);
612 param, PTR_DIFF(p,param), 8, /* params, length, max */
613 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
614 &rparam, &rprcnt, /* return params, return size */
615 &rdata, &rdrcnt /* return data, return size */
617 int res = SVAL(rparam,0);
618 int converter=SVAL(rparam,2);
621 if (res == 0 || res == ERRmoredata) {
622 count=SVAL(rparam,4);
625 for (i = 0;i < count;i++, p += 26) {
627 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
628 char *cmnt = comment_offset?(rdata+comment_offset):"";
629 if (comment_offset < 0 || comment_offset > rdrcnt) continue;
631 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
633 fn(sname, stype, cmnt);
655 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
656 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
657 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
658 {PROTOCOL_LANMAN1,"LANMAN1.0"},
659 {PROTOCOL_LANMAN2,"LM1.2X002"},
660 {PROTOCOL_LANMAN2,"Samba"},
661 {PROTOCOL_NT1,"NT LANMAN 1.0"},
662 {PROTOCOL_NT1,"NT LM 0.12"},
667 /****************************************************************************
669 ****************************************************************************/
670 BOOL cli_session_setup(struct cli_state *cli,
672 char *pass, int passlen,
673 char *ntpass, int ntpasslen,
677 fstring pword, ntpword;
679 if (cli->protocol < PROTOCOL_LANMAN1)
682 if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
686 if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
687 /* Null session connect. */
691 if ((cli->sec_mode & 2) && passlen != 24) {
694 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
695 SMBNTencrypt((uchar *)ntpass,(uchar *)cli->cryptkey,(uchar *)ntpword);
697 fstrcpy(pword, pass);
698 fstrcpy(ntpword, "");
703 /* if in share level security then don't send a password now */
704 if (!(cli->sec_mode & 1)) {
707 fstrcpy(ntpword, "");
711 /* send a session setup command */
712 bzero(cli->outbuf,smb_size);
714 if (cli->protocol < PROTOCOL_NT1)
716 set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
717 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
718 cli_setup_packet(cli);
720 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
721 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
722 SSVAL(cli->outbuf,smb_vwv3,2);
723 SSVAL(cli->outbuf,smb_vwv4,1);
724 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
725 SSVAL(cli->outbuf,smb_vwv7,passlen);
726 p = smb_buf(cli->outbuf);
727 memcpy(p,pword,passlen);
734 set_message(cli->outbuf,13,0,True);
735 CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
736 cli_setup_packet(cli);
738 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
739 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
740 SSVAL(cli->outbuf,smb_vwv3,2);
741 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
742 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
743 SSVAL(cli->outbuf,smb_vwv7,passlen);
744 SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
745 SSVAL(cli->outbuf,smb_vwv11,0);
746 p = smb_buf(cli->outbuf);
747 memcpy(p,pword,passlen);
748 p += SVAL(cli->outbuf,smb_vwv7);
749 memcpy(p,ntpword,ntpasslen);
750 p += SVAL(cli->outbuf,smb_vwv8);
753 p = skip_string(p,1);
754 pstrcpy(p,workgroup);
756 p = skip_string(p,1);
757 pstrcpy(p,"Unix");p = skip_string(p,1);
758 pstrcpy(p,"Samba");p = skip_string(p,1);
759 set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
763 if (!cli_receive_smb(cli))
766 show_msg(cli->inbuf);
768 if (CVAL(cli->inbuf,smb_rcls) != 0) {
772 /* use the returned vuid from now on */
773 cli->vuid = SVAL(cli->inbuf,smb_uid);
775 if (cli->protocol >= PROTOCOL_NT1) {
777 * Save off some of the connected server
780 char *server_domain,*server_os,*server_type;
781 server_os = smb_buf(cli->inbuf);
782 server_type = skip_string(server_os,1);
783 server_domain = skip_string(server_type,1);
784 fstrcpy(cli->server_os, server_os);
785 fstrcpy(cli->server_type, server_type);
786 fstrcpy(cli->server_domain, server_domain);
789 fstrcpy(cli->user_name, user);
794 /****************************************************************************
796 *****************************************************************************/
798 BOOL cli_ulogoff(struct cli_state *cli)
800 bzero(cli->outbuf,smb_size);
801 set_message(cli->outbuf,2,0,True);
802 CVAL(cli->outbuf,smb_com) = SMBulogoffX;
803 cli_setup_packet(cli);
804 SSVAL(cli->outbuf,smb_vwv0,0xFF);
805 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
808 if (!cli_receive_smb(cli))
811 return CVAL(cli->inbuf,smb_rcls) == 0;
814 /****************************************************************************
816 ****************************************************************************/
817 BOOL cli_send_tconX(struct cli_state *cli,
818 char *share, char *dev, char *pass, int passlen)
820 fstring fullshare, pword;
822 bzero(cli->outbuf,smb_size);
823 bzero(cli->inbuf,smb_size);
825 fstrcpy(cli->share, share);
827 /* in user level security don't send a password now */
828 if (cli->sec_mode & 1) {
833 if ((cli->sec_mode & 2) && *pass && passlen != 24) {
835 SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
837 memcpy(pword, pass, passlen);
840 slprintf(fullshare, sizeof(fullshare)-1,
841 "\\\\%s\\%s", cli->desthost, share);
843 set_message(cli->outbuf,4,
844 2 + strlen(fullshare) + passlen + strlen(dev),True);
845 CVAL(cli->outbuf,smb_com) = SMBtconX;
846 cli_setup_packet(cli);
848 SSVAL(cli->outbuf,smb_vwv0,0xFF);
849 SSVAL(cli->outbuf,smb_vwv3,passlen);
851 p = smb_buf(cli->outbuf);
852 memcpy(p,pword,passlen);
854 fstrcpy(p,fullshare);
855 p = skip_string(p,1);
858 SCVAL(cli->inbuf,smb_rcls, 1);
861 if (!cli_receive_smb(cli))
864 if (CVAL(cli->inbuf,smb_rcls) != 0) {
868 fstrcpy(cli->dev, "A:");
870 if (cli->protocol >= PROTOCOL_NT1) {
871 fstrcpy(cli->dev, smb_buf(cli->inbuf));
874 if (strcasecmp(share,"IPC$")==0) {
875 fstrcpy(cli->dev, "IPC");
878 /* only grab the device if we have a recent protocol level */
879 if (cli->protocol >= PROTOCOL_NT1 &&
880 smb_buflen(cli->inbuf) == 3) {
881 /* almost certainly win95 - enable bug fixes */
885 cli->cnum = SVAL(cli->inbuf,smb_tid);
890 /****************************************************************************
891 send a tree disconnect
892 ****************************************************************************/
893 BOOL cli_tdis(struct cli_state *cli)
895 bzero(cli->outbuf,smb_size);
896 set_message(cli->outbuf,0,0,True);
897 CVAL(cli->outbuf,smb_com) = SMBtdis;
898 SSVAL(cli->outbuf,smb_tid,cli->cnum);
899 cli_setup_packet(cli);
902 if (!cli_receive_smb(cli))
905 return CVAL(cli->inbuf,smb_rcls) == 0;
908 /****************************************************************************
910 ****************************************************************************/
911 BOOL cli_rename(struct cli_state *cli, char *fname_src, char *fname_dst)
915 bzero(cli->outbuf,smb_size);
916 bzero(cli->inbuf,smb_size);
918 set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
920 CVAL(cli->outbuf,smb_com) = SMBmv;
921 SSVAL(cli->outbuf,smb_tid,cli->cnum);
922 cli_setup_packet(cli);
924 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
926 p = smb_buf(cli->outbuf);
928 pstrcpy(p,fname_src);
929 p = skip_string(p,1);
931 pstrcpy(p,fname_dst);
934 if (!cli_receive_smb(cli)) {
938 if (CVAL(cli->inbuf,smb_rcls) != 0) {
945 /****************************************************************************
947 ****************************************************************************/
948 BOOL cli_unlink(struct cli_state *cli, char *fname)
952 bzero(cli->outbuf,smb_size);
953 bzero(cli->inbuf,smb_size);
955 set_message(cli->outbuf,1, 2 + strlen(fname),True);
957 CVAL(cli->outbuf,smb_com) = SMBunlink;
958 SSVAL(cli->outbuf,smb_tid,cli->cnum);
959 cli_setup_packet(cli);
961 SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
963 p = smb_buf(cli->outbuf);
968 if (!cli_receive_smb(cli)) {
972 if (CVAL(cli->inbuf,smb_rcls) != 0) {
979 /****************************************************************************
981 ****************************************************************************/
982 BOOL cli_mkdir(struct cli_state *cli, char *dname)
986 bzero(cli->outbuf,smb_size);
987 bzero(cli->inbuf,smb_size);
989 set_message(cli->outbuf,0, 2 + strlen(dname),True);
991 CVAL(cli->outbuf,smb_com) = SMBmkdir;
992 SSVAL(cli->outbuf,smb_tid,cli->cnum);
993 cli_setup_packet(cli);
995 p = smb_buf(cli->outbuf);
1000 if (!cli_receive_smb(cli)) {
1004 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1011 /****************************************************************************
1013 ****************************************************************************/
1014 BOOL cli_rmdir(struct cli_state *cli, char *dname)
1018 bzero(cli->outbuf,smb_size);
1019 bzero(cli->inbuf,smb_size);
1021 set_message(cli->outbuf,0, 2 + strlen(dname),True);
1023 CVAL(cli->outbuf,smb_com) = SMBrmdir;
1024 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1025 cli_setup_packet(cli);
1027 p = smb_buf(cli->outbuf);
1032 if (!cli_receive_smb(cli)) {
1036 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1045 /****************************************************************************
1047 ****************************************************************************/
1048 int cli_nt_create(struct cli_state *cli, char *fname)
1052 bzero(cli->outbuf,smb_size);
1053 bzero(cli->inbuf,smb_size);
1055 set_message(cli->outbuf,24,1 + strlen(fname),True);
1057 CVAL(cli->outbuf,smb_com) = SMBntcreateX;
1058 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1059 cli_setup_packet(cli);
1061 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1062 SIVAL(cli->outbuf,smb_ntcreate_Flags, 0x06);
1063 SIVAL(cli->outbuf,smb_ntcreate_RootDirectoryFid, 0x0);
1064 SIVAL(cli->outbuf,smb_ntcreate_DesiredAccess, 0x2019f);
1065 SIVAL(cli->outbuf,smb_ntcreate_FileAttributes, 0x0);
1066 SIVAL(cli->outbuf,smb_ntcreate_ShareAccess, 0x03);
1067 SIVAL(cli->outbuf,smb_ntcreate_CreateDisposition, 0x01);
1068 SIVAL(cli->outbuf,smb_ntcreate_CreateOptions, 0x0);
1069 SIVAL(cli->outbuf,smb_ntcreate_ImpersonationLevel, 0x02);
1070 SSVAL(cli->outbuf,smb_ntcreate_NameLength, strlen(fname));
1072 p = smb_buf(cli->outbuf);
1074 p = skip_string(p,1);
1077 if (!cli_receive_smb(cli)) {
1081 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1085 return SVAL(cli->inbuf,smb_vwv2 + 1);
1089 /****************************************************************************
1091 ****************************************************************************/
1092 int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
1096 unsigned accessmode=0;
1098 /* you must open for RW not just write - otherwise getattrE doesn't
1100 if ((flags & O_ACCMODE) == O_WRONLY && strncmp(cli->dev, "LPT", 3)) {
1101 flags = (flags & ~O_ACCMODE) | O_RDWR;
1104 if (flags & O_CREAT)
1106 if (!(flags & O_EXCL)) {
1107 if (flags & O_TRUNC)
1113 accessmode = (share_mode<<4);
1115 if ((flags & O_ACCMODE) == O_RDWR) {
1117 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1122 if ((flags & O_SYNC) == O_SYNC) {
1123 accessmode |= (1<<14);
1127 bzero(cli->outbuf,smb_size);
1128 bzero(cli->inbuf,smb_size);
1130 set_message(cli->outbuf,15,1 + strlen(fname),True);
1132 CVAL(cli->outbuf,smb_com) = SMBopenX;
1133 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1134 cli_setup_packet(cli);
1136 SSVAL(cli->outbuf,smb_vwv0,0xFF);
1137 SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
1138 SSVAL(cli->outbuf,smb_vwv3,accessmode);
1139 SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
1140 SSVAL(cli->outbuf,smb_vwv5,0);
1141 SSVAL(cli->outbuf,smb_vwv8,openfn);
1143 p = smb_buf(cli->outbuf);
1145 p = skip_string(p,1);
1148 if (!cli_receive_smb(cli)) {
1152 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1156 return SVAL(cli->inbuf,smb_vwv2);
1162 /****************************************************************************
1164 ****************************************************************************/
1165 BOOL cli_close(struct cli_state *cli, int fnum)
1167 bzero(cli->outbuf,smb_size);
1168 bzero(cli->inbuf,smb_size);
1170 set_message(cli->outbuf,3,0,True);
1172 CVAL(cli->outbuf,smb_com) = SMBclose;
1173 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1174 cli_setup_packet(cli);
1176 SSVAL(cli->outbuf,smb_vwv0,fnum);
1177 SIVALS(cli->outbuf,smb_vwv1,-1);
1180 if (!cli_receive_smb(cli)) {
1184 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1192 /****************************************************************************
1194 ****************************************************************************/
1195 BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1198 int saved_timeout = cli->timeout;
1200 bzero(cli->outbuf,smb_size);
1201 bzero(cli->inbuf,smb_size);
1203 set_message(cli->outbuf,8,10,True);
1205 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1206 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1207 cli_setup_packet(cli);
1209 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1210 SSVAL(cli->outbuf,smb_vwv2,fnum);
1211 CVAL(cli->outbuf,smb_vwv3) = 0;
1212 SIVALS(cli->outbuf, smb_vwv4, timeout);
1213 SSVAL(cli->outbuf,smb_vwv6,0);
1214 SSVAL(cli->outbuf,smb_vwv7,1);
1216 p = smb_buf(cli->outbuf);
1217 SSVAL(p, 0, cli->pid);
1218 SIVAL(p, 2, offset);
1222 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : timeout;
1224 if (!cli_receive_smb(cli)) {
1225 cli->timeout = saved_timeout;
1229 cli->timeout = saved_timeout;
1231 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1238 /****************************************************************************
1240 ****************************************************************************/
1241 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
1245 bzero(cli->outbuf,smb_size);
1246 bzero(cli->inbuf,smb_size);
1248 set_message(cli->outbuf,8,10,True);
1250 CVAL(cli->outbuf,smb_com) = SMBlockingX;
1251 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1252 cli_setup_packet(cli);
1254 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1255 SSVAL(cli->outbuf,smb_vwv2,fnum);
1256 CVAL(cli->outbuf,smb_vwv3) = 0;
1257 SIVALS(cli->outbuf, smb_vwv4, timeout);
1258 SSVAL(cli->outbuf,smb_vwv6,1);
1259 SSVAL(cli->outbuf,smb_vwv7,0);
1261 p = smb_buf(cli->outbuf);
1262 SSVAL(p, 0, cli->pid);
1263 SIVAL(p, 2, offset);
1267 if (!cli_receive_smb(cli)) {
1271 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1280 /****************************************************************************
1281 issue a single SMBread and don't wait for a reply
1282 ****************************************************************************/
1283 static void cli_issue_read(struct cli_state *cli, int fnum, off_t offset,
1286 bzero(cli->outbuf,smb_size);
1287 bzero(cli->inbuf,smb_size);
1289 set_message(cli->outbuf,10,0,True);
1291 CVAL(cli->outbuf,smb_com) = SMBreadX;
1292 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1293 cli_setup_packet(cli);
1295 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1296 SSVAL(cli->outbuf,smb_vwv2,fnum);
1297 SIVAL(cli->outbuf,smb_vwv3,offset);
1298 SSVAL(cli->outbuf,smb_vwv5,size);
1299 SSVAL(cli->outbuf,smb_vwv6,size);
1300 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1305 /****************************************************************************
1307 ****************************************************************************/
1308 size_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_t size)
1314 int mpx = MAX(cli->max_mux-1, 1);
1315 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1317 int blocks = (size + (block-1)) / block;
1319 if (size == 0) return 0;
1321 while (received < blocks) {
1324 while (issued - received < mpx && issued < blocks) {
1325 int size1 = MIN(block, size-issued*block);
1326 cli_issue_read(cli, fnum, offset+issued*block, size1, issued);
1330 if (!cli_receive_smb(cli)) {
1335 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1336 size2 = SVAL(cli->inbuf, smb_vwv5);
1338 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1339 blocks = MIN(blocks, mid-1);
1344 blocks = MIN(blocks, mid-1);
1345 /* this distinguishes EOF from an error */
1346 total = MAX(total, 0);
1350 if (size2 > block) {
1351 DEBUG(0,("server returned more than we wanted!\n"));
1354 if (mid >= issued) {
1355 DEBUG(0,("invalid mid from server!\n"));
1358 p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
1360 memcpy(buf+mid*block, p, size2);
1362 total = MAX(total, mid*block + size2);
1365 while (received < issued) {
1366 cli_receive_smb(cli);
1374 /****************************************************************************
1375 issue a single SMBwrite and don't wait for a reply
1376 ****************************************************************************/
1377 static void cli_issue_write(struct cli_state *cli, int fnum, off_t offset, uint16 mode, char *buf,
1382 bzero(cli->outbuf,smb_size);
1383 bzero(cli->inbuf,smb_size);
1385 set_message(cli->outbuf,12,size,True);
1387 CVAL(cli->outbuf,smb_com) = SMBwriteX;
1388 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1389 cli_setup_packet(cli);
1391 CVAL(cli->outbuf,smb_vwv0) = 0xFF;
1392 SSVAL(cli->outbuf,smb_vwv2,fnum);
1394 SIVAL(cli->outbuf,smb_vwv3,offset);
1395 SIVAL(cli->outbuf,smb_vwv5,IS_BITS_SET_ALL(mode, 0x0008) ? 0xFFFFFFFF : 0);
1396 SSVAL(cli->outbuf,smb_vwv7,mode);
1398 SSVAL(cli->outbuf,smb_vwv8,IS_BITS_SET_ALL(mode, 0x0008) ? size : 0);
1399 SSVAL(cli->outbuf,smb_vwv10,size);
1400 SSVAL(cli->outbuf,smb_vwv11,
1401 smb_buf(cli->outbuf) - smb_base(cli->outbuf));
1403 p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
1404 memcpy(p, buf, size);
1406 SSVAL(cli->outbuf,smb_mid,cli->mid + i);
1408 show_msg(cli->outbuf);
1412 /****************************************************************************
1414 write_mode: 0x0001 disallow write cacheing
1415 0x0002 return bytes remaining
1416 0x0004 use raw named pipe protocol
1417 0x0008 start of message mode named pipe protocol
1418 ****************************************************************************/
1419 ssize_t cli_write(struct cli_state *cli,
1420 int fnum, uint16 write_mode,
1421 char *buf, off_t offset, size_t size)
1426 int mpx = MAX(cli->max_mux-1, 1);
1427 int block = (cli->max_xmit - (smb_size+32)) & ~1023;
1429 int blocks = (size + (block-1)) / block;
1431 if (size == 0) return 0;
1433 while (received < blocks) {
1436 while (issued - received < mpx && issued < blocks) {
1437 int size1 = MIN(block, size-issued*block);
1438 cli_issue_write(cli, fnum, offset+issued*block,
1445 if (!cli_receive_smb(cli)) {
1450 mid = SVAL(cli->inbuf, smb_mid) - cli->mid;
1451 size2 = SVAL(cli->inbuf, smb_vwv2);
1453 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1454 blocks = MIN(blocks, mid-1);
1459 blocks = MIN(blocks, mid-1);
1460 /* this distinguishes EOF from an error */
1461 total = MAX(total, 0);
1467 total = MAX(total, mid*block + size2);
1470 while (received < issued) {
1471 cli_receive_smb(cli);
1479 /****************************************************************************
1480 do a SMBgetattrE call
1481 ****************************************************************************/
1482 BOOL cli_getattrE(struct cli_state *cli, int fd,
1483 uint16 *attr, size_t *size,
1484 time_t *c_time, time_t *a_time, time_t *m_time)
1486 bzero(cli->outbuf,smb_size);
1487 bzero(cli->inbuf,smb_size);
1489 set_message(cli->outbuf,2,0,True);
1491 CVAL(cli->outbuf,smb_com) = SMBgetattrE;
1492 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1493 cli_setup_packet(cli);
1495 SSVAL(cli->outbuf,smb_vwv0,fd);
1498 if (!cli_receive_smb(cli)) {
1502 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1507 *size = IVAL(cli->inbuf, smb_vwv6);
1511 *attr = SVAL(cli->inbuf,smb_vwv10);
1515 *c_time = make_unix_date3(cli->inbuf+smb_vwv0);
1519 *a_time = make_unix_date3(cli->inbuf+smb_vwv2);
1523 *m_time = make_unix_date3(cli->inbuf+smb_vwv4);
1530 /****************************************************************************
1532 ****************************************************************************/
1533 BOOL cli_getatr(struct cli_state *cli, char *fname,
1534 uint16 *attr, size_t *size, time_t *t)
1538 bzero(cli->outbuf,smb_size);
1539 bzero(cli->inbuf,smb_size);
1541 set_message(cli->outbuf,0,strlen(fname)+2,True);
1543 CVAL(cli->outbuf,smb_com) = SMBgetatr;
1544 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1545 cli_setup_packet(cli);
1547 p = smb_buf(cli->outbuf);
1549 pstrcpy(p+1, fname);
1552 if (!cli_receive_smb(cli)) {
1556 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1561 *size = IVAL(cli->inbuf, smb_vwv3);
1565 *t = make_unix_date3(cli->inbuf+smb_vwv1);
1569 *attr = SVAL(cli->inbuf,smb_vwv0);
1577 /****************************************************************************
1579 ****************************************************************************/
1580 BOOL cli_setatr(struct cli_state *cli, char *fname, uint16 attr, time_t t)
1584 bzero(cli->outbuf,smb_size);
1585 bzero(cli->inbuf,smb_size);
1587 set_message(cli->outbuf,8,strlen(fname)+4,True);
1589 CVAL(cli->outbuf,smb_com) = SMBsetatr;
1590 SSVAL(cli->outbuf,smb_tid,cli->cnum);
1591 cli_setup_packet(cli);
1593 SSVAL(cli->outbuf,smb_vwv0, attr);
1594 put_dos_date3(cli->outbuf,smb_vwv1, t);
1596 p = smb_buf(cli->outbuf);
1598 pstrcpy(p+1, fname);
1599 p = skip_string(p,1);
1603 if (!cli_receive_smb(cli)) {
1607 if (CVAL(cli->inbuf,smb_rcls) != 0) {
1614 /****************************************************************************
1615 send a qpathinfo call
1616 ****************************************************************************/
1617 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
1618 time_t *c_time, time_t *a_time, time_t *m_time,
1619 size_t *size, uint16 *mode)
1623 uint16 setup = TRANSACT2_QPATHINFO;
1625 char *rparam=NULL, *rdata=NULL;
1628 time_t (*date_fn)(void *);
1630 param_len = strlen(fname) + 7;
1632 memset(param, 0, param_len);
1633 SSVAL(param, 0, SMB_INFO_STANDARD);
1634 pstrcpy(¶m[6], fname);
1637 ret = (cli_send_trans(cli, SMBtrans2,
1638 NULL, 0, /* Name, length */
1639 -1, 0, /* fid, flags */
1640 &setup, 1, 0, /* setup, length, max */
1641 param, param_len, 10, /* param, length, max */
1642 NULL, data_len, cli->max_xmit /* data, length, max */
1644 cli_receive_trans(cli, SMBtrans2,
1645 &rparam, ¶m_len,
1646 &rdata, &data_len));
1648 /* we need to work around a Win95 bug - sometimes
1649 it gives ERRSRV/ERRerror temprarily */
1652 cli_error(cli, &eclass, &ecode);
1653 if (eclass != ERRSRV || ecode != ERRerror) break;
1656 } while (count-- && ret==False);
1658 if (!ret || !rdata || data_len < 22) {
1663 date_fn = make_unix_date;
1665 date_fn = make_unix_date2;
1669 *c_time = date_fn(rdata+0);
1672 *a_time = date_fn(rdata+4);
1675 *m_time = date_fn(rdata+8);
1678 *size = IVAL(rdata, 12);
1681 *mode = SVAL(rdata,l1_attrFile);
1684 if (rdata) free(rdata);
1685 if (rparam) free(rparam);
1689 /****************************************************************************
1690 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
1691 ****************************************************************************/
1692 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
1693 time_t *c_time, time_t *a_time, time_t *m_time,
1694 time_t *w_time, size_t *size, uint16 *mode,
1699 uint16 setup = TRANSACT2_QPATHINFO;
1701 char *rparam=NULL, *rdata=NULL;
1703 param_len = strlen(fname) + 7;
1705 memset(param, 0, param_len);
1706 SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
1707 pstrcpy(¶m[6], fname);
1709 if (!cli_send_trans(cli, SMBtrans2,
1710 NULL, 0, /* name, length */
1711 -1, 0, /* fid, flags */
1712 &setup, 1, 0, /* setup, length, max */
1713 param, param_len, 10, /* param, length, max */
1714 NULL, data_len, cli->max_xmit /* data, length, max */
1719 if (!cli_receive_trans(cli, SMBtrans2,
1720 &rparam, ¶m_len,
1721 &rdata, &data_len)) {
1725 if (!rdata || data_len < 22) {
1730 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1733 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1736 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1739 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1742 *mode = SVAL(rdata, 32);
1745 *size = IVAL(rdata, 40);
1748 *ino = IVAL(rdata, 64);
1751 if (rdata) free(rdata);
1752 if (rparam) free(rparam);
1757 /****************************************************************************
1758 send a qfileinfo call
1759 ****************************************************************************/
1760 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
1761 uint16 *mode, size_t *size,
1762 time_t *c_time, time_t *a_time, time_t *m_time,
1763 time_t *w_time, SMB_INO_T *ino)
1767 uint16 setup = TRANSACT2_QFILEINFO;
1769 char *rparam=NULL, *rdata=NULL;
1771 /* if its a win95 server then fail this - win95 totally screws it
1773 if (cli->win95) return False;
1777 memset(param, 0, param_len);
1778 SSVAL(param, 0, fnum);
1779 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
1781 if (!cli_send_trans(cli, SMBtrans2,
1782 NULL, 0, /* name, length */
1783 -1, 0, /* fid, flags */
1784 &setup, 1, 0, /* setup, length, max */
1785 param, param_len, 2, /* param, length, max */
1786 NULL, data_len, cli->max_xmit /* data, length, max */
1791 if (!cli_receive_trans(cli, SMBtrans2,
1792 &rparam, ¶m_len,
1793 &rdata, &data_len)) {
1797 if (!rdata || data_len < 68) {
1802 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
1805 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
1808 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
1811 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
1814 *mode = SVAL(rdata, 32);
1817 *size = IVAL(rdata, 40);
1820 *ino = IVAL(rdata, 64);
1823 if (rdata) free(rdata);
1824 if (rparam) free(rparam);
1829 /****************************************************************************
1830 interpret a long filename structure - this is mostly guesses at the moment
1831 The length of the structure is returned
1832 The structure of a long filename depends on the info level. 260 is used
1833 by NT and 2 is used by OS/2
1834 ****************************************************************************/
1835 static int interpret_long_filename(int level,char *p,file_info *finfo)
1837 extern file_info def_finfo;
1840 memcpy(finfo,&def_finfo,sizeof(*finfo));
1844 case 1: /* OS/2 understands this */
1846 /* these dates are converted to GMT by make_unix_date */
1847 finfo->ctime = make_unix_date2(p+4);
1848 finfo->atime = make_unix_date2(p+8);
1849 finfo->mtime = make_unix_date2(p+12);
1850 finfo->size = IVAL(p,16);
1851 finfo->mode = CVAL(p,24);
1852 pstrcpy(finfo->name,p+27);
1854 return(28 + CVAL(p,26));
1856 case 2: /* this is what OS/2 uses mostly */
1858 /* these dates are converted to GMT by make_unix_date */
1859 finfo->ctime = make_unix_date2(p+4);
1860 finfo->atime = make_unix_date2(p+8);
1861 finfo->mtime = make_unix_date2(p+12);
1862 finfo->size = IVAL(p,16);
1863 finfo->mode = CVAL(p,24);
1864 pstrcpy(finfo->name,p+31);
1866 return(32 + CVAL(p,30));
1868 /* levels 3 and 4 are untested */
1871 /* these dates are probably like the other ones */
1872 finfo->ctime = make_unix_date2(p+8);
1873 finfo->atime = make_unix_date2(p+12);
1874 finfo->mtime = make_unix_date2(p+16);
1875 finfo->size = IVAL(p,20);
1876 finfo->mode = CVAL(p,28);
1877 pstrcpy(finfo->name,p+33);
1879 return(SVAL(p,4)+4);
1883 /* these dates are probably like the other ones */
1884 finfo->ctime = make_unix_date2(p+8);
1885 finfo->atime = make_unix_date2(p+12);
1886 finfo->mtime = make_unix_date2(p+16);
1887 finfo->size = IVAL(p,20);
1888 finfo->mode = CVAL(p,28);
1889 pstrcpy(finfo->name,p+37);
1891 return(SVAL(p,4)+4);
1893 case 260: /* NT uses this, but also accepts 2 */
1895 int ret = SVAL(p,0);
1897 p += 4; /* next entry offset */
1898 p += 4; /* fileindex */
1900 /* these dates appear to arrive in a
1901 weird way. It seems to be localtime
1902 plus the serverzone given in the
1903 initial connect. This is GMT when
1904 DST is not in effect and one hour
1905 from GMT otherwise. Can this really
1908 I suppose this could be called
1909 kludge-GMT. Is is the GMT you get
1910 by using the current DST setting on
1911 a different localtime. It will be
1912 cheap to calculate, I suppose, as
1913 no DST tables will be needed */
1915 finfo->ctime = interpret_long_date(p); p += 8;
1916 finfo->atime = interpret_long_date(p); p += 8;
1917 finfo->mtime = interpret_long_date(p); p += 8; p += 8;
1918 finfo->size = IVAL(p,0); p += 8;
1919 p += 8; /* alloc size */
1920 finfo->mode = CVAL(p,0); p += 4;
1921 namelen = IVAL(p,0); p += 4;
1922 p += 4; /* EA size */
1923 p += 2; /* short name len? */
1924 p += 24; /* short name? */
1925 StrnCpy(finfo->name,p,namelen);
1931 DEBUG(1,("Unknown long filename format %d\n",level));
1936 /****************************************************************************
1937 do a directory listing, calling fn on each file found
1938 ****************************************************************************/
1939 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute,
1940 void (*fn)(file_info *, const char *))
1942 int max_matches = 512;
1943 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1944 int info_level = cli->protocol<PROTOCOL_NT1?1:260;
1949 char *dirlist = NULL;
1950 int dirlist_len = 0;
1951 int total_received = -1;
1953 int ff_resume_key = 0;
1954 int ff_searchcount=0;
1957 int ff_dir_handle=0;
1959 char *rparam=NULL, *rdata=NULL;
1960 int param_len, data_len;
1967 while (ff_eos == 0) {
1969 if (loop_count > 200) {
1970 DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
1974 param_len = 12+strlen(mask)+1;
1977 setup = TRANSACT2_FINDFIRST;
1978 SSVAL(param,0,attribute); /* attribute */
1979 SSVAL(param,2,max_matches); /* max count */
1980 SSVAL(param,4,8+4+2); /* resume required + close on end + continue */
1981 SSVAL(param,6,info_level);
1983 pstrcpy(param+12,mask);
1985 setup = TRANSACT2_FINDNEXT;
1986 SSVAL(param,0,ff_dir_handle);
1987 SSVAL(param,2,max_matches); /* max count */
1988 SSVAL(param,4,info_level);
1989 SIVAL(param,6,ff_resume_key); /* ff_resume_key */
1990 SSVAL(param,10,8+4+2); /* resume required + close on end + continue */
1991 pstrcpy(param+12,mask);
1993 DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1994 ff_dir_handle,ff_resume_key,ff_lastname,mask));
1997 if (!cli_send_trans(cli, SMBtrans2,
1998 NULL, 0, /* Name, length */
1999 -1, 0, /* fid, flags */
2000 &setup, 1, 0, /* setup, length, max */
2001 param, param_len, 10, /* param, length, max */
2003 cli->max_xmit /* data, length, max */
2008 if (!cli_receive_trans(cli, SMBtrans2,
2009 &rparam, ¶m_len,
2010 &rdata, &data_len)) {
2011 /* we need to work around a Win95 bug - sometimes
2012 it gives ERRSRV/ERRerror temprarily */
2015 cli_error(cli, &eclass, &ecode);
2016 if (eclass != ERRSRV || ecode != ERRerror) break;
2021 if (total_received == -1) total_received = 0;
2023 /* parse out some important return info */
2026 ff_dir_handle = SVAL(p,0);
2027 ff_searchcount = SVAL(p,2);
2029 ff_lastname = SVAL(p,8);
2031 ff_searchcount = SVAL(p,0);
2033 ff_lastname = SVAL(p,6);
2036 if (ff_searchcount == 0)
2039 /* point to the data bytes */
2042 /* we might need the lastname for continuations */
2043 if (ff_lastname > 0) {
2048 StrnCpy(mask,p+ff_lastname,
2049 data_len-ff_lastname);
2052 pstrcpy(mask,p + ff_lastname + 1);
2060 /* and add them to the dirlist pool */
2061 dirlist = Realloc(dirlist,dirlist_len + data_len);
2064 DEBUG(0,("Failed to expand dirlist\n"));
2068 /* put in a length for the last entry, to ensure we can chain entries
2069 into the next packet */
2070 for (p2=p,i=0;i<(ff_searchcount-1);i++)
2071 p2 += interpret_long_filename(info_level,p2,NULL);
2072 SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
2074 /* grab the data for later use */
2075 memcpy(dirlist+dirlist_len,p,data_len);
2076 dirlist_len += data_len;
2078 total_received += ff_searchcount;
2080 if (rdata) free(rdata); rdata = NULL;
2081 if (rparam) free(rparam); rparam = NULL;
2083 DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
2084 ff_searchcount,ff_eos,ff_resume_key));
2089 for (p=dirlist,i=0;i<total_received;i++) {
2090 p += interpret_long_filename(info_level,p,&finfo);
2094 /* free up the dirlist buffer */
2095 if (dirlist) free(dirlist);
2096 return(total_received);
2100 /****************************************************************************
2101 Send a SamOEMChangePassword command
2102 ****************************************************************************/
2104 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
2105 const char *old_password)
2107 char param[16+sizeof(fstring)];
2110 fstring upper_case_old_pw;
2111 fstring upper_case_new_pw;
2112 unsigned char old_pw_hash[16];
2113 unsigned char new_pw_hash[16];
2116 char *rparam = NULL;
2120 if (strlen(user) >= sizeof(fstring)-1) {
2121 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
2125 SSVAL(p,0,214); /* SamOEMChangePassword command. */
2128 p = skip_string(p,1);
2129 pstrcpy(p, "B516B16");
2130 p = skip_string(p,1);
2132 p = skip_string(p,1);
2136 param_len = PTR_DIFF(p,param);
2139 * Get the Lanman hash of the old password, we
2140 * use this as the key to make_oem_passwd_hash().
2142 memset(upper_case_old_pw, '\0', sizeof(upper_case_old_pw));
2143 fstrcpy(upper_case_old_pw, old_password);
2144 strupper(upper_case_old_pw);
2145 E_P16((uchar *)upper_case_old_pw, old_pw_hash);
2147 if (!make_oem_passwd_hash( data, new_password, old_pw_hash, False))
2153 * Now place the old password hash in the data.
2155 memset(upper_case_new_pw, '\0', sizeof(upper_case_new_pw));
2156 fstrcpy(upper_case_new_pw, new_password);
2157 strupper(upper_case_new_pw);
2159 E_P16((uchar *)upper_case_new_pw, new_pw_hash);
2161 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
2165 if (cli_send_trans(cli,SMBtrans,
2166 PIPE_LANMAN,strlen(PIPE_LANMAN), /* name, length */
2167 0,0, /* fid, flags */
2168 NULL,0,0, /* setup, length, max */
2169 param,param_len,2, /* param, length, max */
2170 data,data_len,0 /* data, length, max */
2172 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
2177 if (cli_receive_trans(cli,SMBtrans,
2181 cli->rap_error = SVAL(rparam,0);
2189 return (cli->rap_error == 0);
2192 /****************************************************************************
2193 send a negprot command
2194 ****************************************************************************/
2195 BOOL cli_negprot(struct cli_state *cli)
2201 bzero(cli->outbuf,smb_size);
2203 /* setup the protocol strings */
2204 for (plength=0,numprots=0;
2205 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2207 plength += strlen(prots[numprots].name)+2;
2209 set_message(cli->outbuf,0,plength,True);
2211 p = smb_buf(cli->outbuf);
2213 prots[numprots].name && prots[numprots].prot<=cli->protocol;
2216 pstrcpy(p,prots[numprots].name);
2220 CVAL(cli->outbuf,smb_com) = SMBnegprot;
2221 cli_setup_packet(cli);
2223 CVAL(smb_buf(cli->outbuf),0) = 2;
2226 if (!cli_receive_smb(cli))
2229 show_msg(cli->inbuf);
2231 if (CVAL(cli->inbuf,smb_rcls) != 0 ||
2232 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
2236 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
2239 if (cli->protocol >= PROTOCOL_NT1) {
2241 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
2242 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
2243 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
2244 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
2245 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1)*60;
2246 /* this time arrives in real GMT */
2247 cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
2248 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2249 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
2250 if (cli->capabilities & 1) {
2251 cli->readbraw_supported = True;
2252 cli->writebraw_supported = True;
2254 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
2255 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
2256 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
2257 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
2258 cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
2259 /* this time is converted to GMT by make_unix_date */
2260 cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
2261 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
2262 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
2263 memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
2265 /* the old core protocol */
2267 cli->serverzone = TimeDiff(time(NULL));
2270 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
2276 /****************************************************************************
2277 send a session request. see rfc1002.txt 4.3 and 4.3.2
2278 ****************************************************************************/
2279 BOOL cli_session_request(struct cli_state *cli,
2280 struct nmb_name *calling, struct nmb_name *called)
2284 /* send a session request (RFC 1002) */
2286 memcpy(&(cli->calling), calling, sizeof(*calling));
2287 memcpy(&(cli->called ), called , sizeof(*called ));
2289 /* put in the destination name */
2290 p = cli->outbuf+len;
2291 name_mangle(cli->called .name, p, cli->called .name_type);
2295 p = cli->outbuf+len;
2296 name_mangle(cli->calling.name, p, cli->calling.name_type);
2299 /* setup the packet length */
2300 _smb_setlen(cli->outbuf,len);
2301 CVAL(cli->outbuf,0) = 0x81;
2305 #endif /* WITH_SSL */
2308 DEBUG(5,("Sent session request\n"));
2310 if (!cli_receive_smb(cli))
2314 if (CVAL(cli->inbuf,0) == 0x83 && CVAL(cli->inbuf,4) == 0x8e){ /* use ssl */
2315 if (!sslutil_fd_is_ssl(cli->fd)){
2316 if (sslutil_connect(cli->fd) == 0)
2320 #endif /* WITH_SSL */
2322 if (CVAL(cli->inbuf,0) != 0x82) {
2323 /* This is the wrong place to put the error... JRA. */
2324 cli->rap_error = CVAL(cli->inbuf,0);
2331 /****************************************************************************
2332 open the client sockets
2333 ****************************************************************************/
2334 BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
2336 extern struct in_addr ipzero;
2338 fstrcpy(cli->desthost, host);
2340 if (!ip || ip_equal(*ip, ipzero)) {
2341 if (!resolve_name( cli->desthost, &cli->dest_ip, 0x20)) {
2344 if (ip) *ip = cli->dest_ip;
2350 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
2359 /****************************************************************************
2360 initialise a client structure
2361 ****************************************************************************/
2362 struct cli_state *cli_initialise(struct cli_state *cli)
2365 cli = (struct cli_state *)malloc(sizeof(*cli));
2371 if (cli->initialised) {
2379 cli->pid = (uint16)getpid();
2381 cli->vuid = UID_FIELD_INVALID;
2382 cli->protocol = PROTOCOL_NT1;
2383 cli->timeout = 20000;
2384 cli->bufsize = CLI_BUFFER_SIZE+4;
2385 cli->max_xmit = cli->bufsize;
2386 cli->outbuf = (char *)malloc(cli->bufsize);
2387 cli->inbuf = (char *)malloc(cli->bufsize);
2388 if (!cli->outbuf || !cli->inbuf)
2393 cli->initialised = 1;
2398 /****************************************************************************
2399 shutdown a client structure
2400 ****************************************************************************/
2401 void cli_shutdown(struct cli_state *cli)
2413 sslutil_disconnect(cli->fd);
2414 #endif /* WITH_SSL */
2417 memset(cli, 0, sizeof(*cli));
2421 /****************************************************************************
2422 return error codes for the last packet
2423 returns 0 if there was no error and the best approx of a unix errno
2426 for 32 bit "warnings", a return code of 0 is expected.
2428 ****************************************************************************/
2429 int cli_error(struct cli_state *cli, uint8 *eclass, uint32 *num)
2431 int flgs2 = SVAL(cli->inbuf,smb_flg2);
2435 if (eclass) *eclass = 0;
2438 if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
2439 /* 32 bit error codes detected */
2440 uint32 nt_err = IVAL(cli->inbuf,smb_rcls);
2441 if (num) *num = nt_err;
2442 DEBUG(10,("cli_error: 32 bit codes: code=%08x\n", nt_err));
2443 if (!IS_BITS_SET_ALL(nt_err, 0xc0000000)) return 0;
2445 switch (nt_err & 0xFFFFFF) {
2446 case NT_STATUS_ACCESS_VIOLATION: return EACCES;
2447 case NT_STATUS_NO_SUCH_FILE: return ENOENT;
2448 case NT_STATUS_NO_SUCH_DEVICE: return ENODEV;
2449 case NT_STATUS_INVALID_HANDLE: return EBADF;
2450 case NT_STATUS_NO_MEMORY: return ENOMEM;
2451 case NT_STATUS_ACCESS_DENIED: return EACCES;
2452 case NT_STATUS_OBJECT_NAME_NOT_FOUND: return ENOENT;
2453 case NT_STATUS_SHARING_VIOLATION: return EBUSY;
2454 case NT_STATUS_OBJECT_PATH_INVALID: return ENOTDIR;
2455 case NT_STATUS_OBJECT_NAME_COLLISION: return EEXIST;
2458 /* for all other cases - a default code */
2462 rcls = CVAL(cli->inbuf,smb_rcls);
2463 code = SVAL(cli->inbuf,smb_err);
2464 if (rcls == 0) return 0;
2466 if (eclass) *eclass = rcls;
2467 if (num ) *num = code;
2469 if (rcls == ERRDOS) {
2471 case ERRbadfile: return ENOENT;
2472 case ERRbadpath: return ENOTDIR;
2473 case ERRnoaccess: return EACCES;
2474 case ERRfilexists: return EEXIST;
2475 case ERRrename: return EEXIST;
2476 case ERRbadshare: return EBUSY;
2477 case ERRlock: return EBUSY;
2480 if (rcls == ERRSRV) {
2482 case ERRbadpw: return EPERM;
2483 case ERRaccess: return EACCES;
2484 case ERRnoresource: return ENOMEM;
2485 case ERRinvdevice: return ENODEV;
2486 case ERRinvnetname: return ENODEV;
2489 /* for other cases */
2493 /****************************************************************************
2494 set socket options on a open connection
2495 ****************************************************************************/
2496 void cli_sockopt(struct cli_state *cli, char *options)
2498 set_socket_options(cli->fd, options);
2501 /****************************************************************************
2502 set the PID to use for smb messages. Return the old pid.
2503 ****************************************************************************/
2504 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
2506 uint16 ret = cli->pid;
2511 /****************************************************************************
2512 re-establishes a connection
2513 ****************************************************************************/
2514 BOOL cli_reestablish_connection(struct cli_state *cli)
2516 struct nmb_name calling;
2517 struct nmb_name called;
2521 BOOL do_tcon = False;
2522 int oldfd = cli->fd;
2524 if (!cli->initialised || cli->fd == -1)
2526 DEBUG(3,("cli_reestablish_connection: not connected\n"));
2530 /* copy the parameters necessary to re-establish the connection */
2534 fstrcpy(share, cli->share);
2535 fstrcpy(dev , cli->dev);
2539 memcpy(&called , &(cli->called ), sizeof(called ));
2540 memcpy(&calling, &(cli->calling), sizeof(calling));
2541 fstrcpy(dest_host, cli->full_dest_host_name);
2543 DEBUG(5,("cli_reestablish_connection: %s connecting to %s (ip %s) - %s [%s]\n",
2544 nmb_namestr(&calling), nmb_namestr(&called),
2545 inet_ntoa(cli->dest_ip),
2546 cli->user_name, cli->domain));
2550 if (cli_establish_connection(cli,
2551 dest_host, &cli->dest_ip,
2553 share, dev, False, do_tcon)) {
2554 if (cli->fd != oldfd) {
2555 if (dup2(cli->fd, oldfd) == oldfd) {
2564 /****************************************************************************
2565 establishes a connection right up to doing tconX, reading in a password.
2566 ****************************************************************************/
2567 BOOL cli_establish_connection(struct cli_state *cli,
2568 char *dest_host, struct in_addr *dest_ip,
2569 struct nmb_name *calling, struct nmb_name *called,
2570 char *service, char *service_type,
2571 BOOL do_shutdown, BOOL do_tcon)
2573 DEBUG(5,("cli_establish_connection: %s connecting to %s (%s) - %s [%s]\n",
2574 nmb_namestr(calling), nmb_namestr(called), inet_ntoa(*dest_ip),
2575 cli->user_name, cli->domain));
2577 /* establish connection */
2579 if ((!cli->initialised))
2586 if (!cli_connect(cli, dest_host, dest_ip))
2588 DEBUG(1,("cli_establish_connection: failed to connect to %s (%s)\n",
2589 nmb_namestr(calling), inet_ntoa(*dest_ip)));
2594 if (!cli_session_request(cli, calling, called))
2596 DEBUG(1,("failed session request\n"));
2602 if (!cli_negprot(cli))
2604 DEBUG(1,("failed negprot\n"));
2610 if (cli->pwd.cleartext || cli->pwd.null_pwd)
2615 if (cli->pwd.null_pwd)
2617 /* attempt null session */
2623 /* attempt clear-text session */
2624 pwd_get_cleartext(&(cli->pwd), passwd);
2625 pass_len = strlen(passwd);
2628 /* attempt clear-text session */
2629 if (!cli_session_setup(cli, cli->user_name,
2634 DEBUG(1,("failed session setup\n"));
2643 if (!cli_send_tconX(cli, service, service_type,
2644 (char*)passwd, strlen(passwd)))
2646 DEBUG(1,("failed tcon_X\n"));
2657 /* attempt encrypted session */
2658 unsigned char nt_sess_pwd[24];
2659 unsigned char lm_sess_pwd[24];
2661 /* creates (storing a copy of) and then obtains a 24 byte password OWF */
2662 pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
2663 pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
2665 /* attempt encrypted session */
2666 if (!cli_session_setup(cli, cli->user_name,
2667 (char*)lm_sess_pwd, sizeof(lm_sess_pwd),
2668 (char*)nt_sess_pwd, sizeof(nt_sess_pwd),
2671 DEBUG(1,("failed session setup\n"));
2679 if (!cli_send_tconX(cli, service, service_type,
2680 (char*)nt_sess_pwd, sizeof(nt_sess_pwd)))
2682 DEBUG(1,("failed tcon_X\n"));
2697 /****************************************************************************
2699 ****************************************************************************/
2700 int cli_printjob_del(struct cli_state *cli, int job)
2702 char *rparam = NULL;
2705 int rdrcnt,rprcnt, ret = -1;
2708 bzero(param,sizeof(param));
2711 SSVAL(p,0,81); /* DosPrintJobDel() */
2714 p = skip_string(p,1);
2716 p = skip_string(p,1);
2721 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2722 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2723 &rparam, &rprcnt, /* return params, length */
2724 &rdata, &rdrcnt)) { /* return data, length */
2725 ret = SVAL(rparam,0);
2728 if (rparam) free(rparam);
2729 if (rdata) free(rdata);
2735 /****************************************************************************
2736 call fn() on each entry in a print queue
2737 ****************************************************************************/
2738 int cli_print_queue(struct cli_state *cli,
2739 void (*fn)(struct print_job_info *))
2741 char *rparam = NULL;
2749 bzero(param,sizeof(param));
2752 SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */
2754 pstrcpy(p,"zWrLeh"); /* parameter description? */
2755 p = skip_string(p,1);
2756 pstrcpy(p,"WWzWWDDzz"); /* returned data format */
2757 p = skip_string(p,1);
2758 pstrcpy(p,cli->share); /* name of queue */
2759 p = skip_string(p,1);
2760 SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */
2761 SSVAL(p,2,1000); /* size of bytes of returned data buffer */
2763 pstrcpy(p,""); /* subformat */
2764 p = skip_string(p,1);
2766 DEBUG(4,("doing cli_print_queue for %s\n", cli->share));
2769 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2770 NULL, 0, CLI_BUFFER_SIZE, /* data, length, maxlen */
2771 &rparam, &rprcnt, /* return params, length */
2772 &rdata, &rdrcnt)) { /* return data, length */
2774 result_code = SVAL(rparam,0);
2775 converter = SVAL(rparam,2); /* conversion factor */
2777 if (result_code == 0) {
2778 struct print_job_info job;
2782 for (i = 0; i < SVAL(rparam,4); ++i) {
2784 job.priority = SVAL(p,2);
2786 fix_char_ptr(SVAL(p,4), converter,
2788 job.t = make_unix_date3(p + 12);
2789 job.size = IVAL(p,16);
2790 fstrcpy(job.name,fix_char_ptr(SVAL(p,24),
2799 /* If any parameters or data were returned, free the storage. */
2800 if(rparam) free(rparam);
2801 if(rdata) free(rdata);
2806 /****************************************************************************
2807 check for existance of a dir
2808 ****************************************************************************/
2809 BOOL cli_chkpath(struct cli_state *cli, char *path)
2814 fstrcpy(path2,path);
2815 trim_string(path2,NULL,"\\");
2816 if (!*path2) *path2 = '\\';
2818 bzero(cli->outbuf,smb_size);
2819 set_message(cli->outbuf,0,4 + strlen(path2),True);
2820 SCVAL(cli->outbuf,smb_com,SMBchkpth);
2821 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2822 cli_setup_packet(cli);
2824 p = smb_buf(cli->outbuf);
2829 if (!cli_receive_smb(cli)) {
2833 if (cli_error(cli, NULL, NULL)) return False;
2839 /****************************************************************************
2840 start a message sequence
2841 ****************************************************************************/
2842 BOOL cli_message_start(struct cli_state *cli, char *host, char *username,
2847 /* send a SMBsendstrt command */
2848 bzero(cli->outbuf,smb_size);
2849 set_message(cli->outbuf,0,0,True);
2850 CVAL(cli->outbuf,smb_com) = SMBsendstrt;
2851 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2852 cli_setup_packet(cli);
2854 p = smb_buf(cli->outbuf);
2856 pstrcpy(p,username);
2857 p = skip_string(p,1);
2860 p = skip_string(p,1);
2862 set_message(cli->outbuf,0,PTR_DIFF(p,smb_buf(cli->outbuf)),False);
2866 if (!cli_receive_smb(cli)) {
2870 if (cli_error(cli, NULL, NULL)) return False;
2872 *grp = SVAL(cli->inbuf,smb_vwv0);
2878 /****************************************************************************
2880 ****************************************************************************/
2881 BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp)
2885 bzero(cli->outbuf,smb_size);
2886 set_message(cli->outbuf,1,len+3,True);
2887 CVAL(cli->outbuf,smb_com) = SMBsendtxt;
2888 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2889 cli_setup_packet(cli);
2891 SSVAL(cli->outbuf,smb_vwv0,grp);
2893 p = smb_buf(cli->outbuf);
2896 memcpy(p+3,msg,len);
2899 if (!cli_receive_smb(cli)) {
2903 if (cli_error(cli, NULL, NULL)) return False;
2908 /****************************************************************************
2910 ****************************************************************************/
2911 BOOL cli_message_end(struct cli_state *cli, int grp)
2913 bzero(cli->outbuf,smb_size);
2914 set_message(cli->outbuf,1,0,True);
2915 CVAL(cli->outbuf,smb_com) = SMBsendend;
2916 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2918 SSVAL(cli->outbuf,smb_vwv0,grp);
2920 cli_setup_packet(cli);
2924 if (!cli_receive_smb(cli)) {
2928 if (cli_error(cli, NULL, NULL)) return False;
2934 /****************************************************************************
2936 ****************************************************************************/
2937 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
2939 bzero(cli->outbuf,smb_size);
2940 set_message(cli->outbuf,0,0,True);
2941 CVAL(cli->outbuf,smb_com) = SMBdskattr;
2942 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2943 cli_setup_packet(cli);
2946 if (!cli_receive_smb(cli)) {
2950 *bsize = SVAL(cli->inbuf,smb_vwv1)*SVAL(cli->inbuf,smb_vwv2);
2951 *total = SVAL(cli->inbuf,smb_vwv0);
2952 *avail = SVAL(cli->inbuf,smb_vwv3);