2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 /* UNIX SMBlib NetBIOS implementation
12 SMBlib Utility Routines
14 Copyright (C) Richard Sharpe 1996
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 2 of the License, or
21 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 #include "rfcnb/rfcnb.h"
35 #include "smblib/smblib-priv.h"
36 #include "smblib/smblib.h"
42 int SMB_Types
[] = {SMB_P_Core
,
58 char *SMB_DOSTimToStr(int DOS_time
);
59 char *SMB_AtrToStr(int attribs
, BOOL verbose
);
60 int SMB_Get_Tree_MBS(SMB_Tree_Handle tree
);
61 int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle
);
62 int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle
);
63 #endif /* UNDEFINED */
64 int SMB_Get_Protocol(SMB_Handle_Type Con_Handle
);
65 int SMB_Figure_Protocol(const char *dialects
[], int prot_index
);
66 int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle
, BOOL discard
);
69 /* Print out an SMB pkt in all its gory detail ... */
71 void SMB_Print_Pkt(FILE fd
, RFCNB_Pkt
*pkt
, BOOL command
, int Offset
, int Len
)
75 /* Well, just how do we do this ... print it I suppose */
77 /* Print out the SMB header ... */
79 /* Print the command */
81 /* Print the other bits in the header */
88 /* Convert a DOS Date_Time to a local host type date time for printing */
91 char *SMB_DOSTimToStr(int DOS_time
)
94 static char SMB_Time_Temp
[48];
95 int DOS_sec
, DOS_min
, DOS_hour
, DOS_day
, DOS_month
, DOS_year
;
99 DOS_sec
= (DOS_time
& 0x001F) * 2;
100 DOS_min
= (DOS_time
& 0x07E0) >> 5;
101 DOS_hour
= ((DOS_time
& 0xF800) >> 11);
103 DOS_day
= (DOS_time
& 0x001F0000) >> 16;
104 DOS_month
= (DOS_time
& 0x01E00000) >> 21;
105 DOS_year
= ((DOS_time
& 0xFE000000) >> 25) + 80;
107 snprintf(SMB_Time_Temp
, 48, "%2d/%02d/%2d %2d:%02d:%02d", DOS_day
, DOS_month
,
108 DOS_year
, DOS_hour
, DOS_min
, DOS_sec
);
110 return(SMB_Time_Temp
);
114 /* Convert an attribute byte/word etc to a string ... We return a pointer
115 to a static string which we guarantee is long enough. If verbose is
116 true, we print out long form of strings ... */
118 char *SMB_AtrToStr(int attribs
, BOOL verbose
)
121 static char SMB_Attrib_Temp
[128];
123 SMB_Attrib_Temp
[0] = 0;
125 if (attribs
& SMB_FA_ROF
)
126 strcat(SMB_Attrib_Temp
, (verbose
?"Read Only ":"R"));
128 if (attribs
& SMB_FA_HID
)
129 strcat(SMB_Attrib_Temp
, (verbose
?"Hidden ":"H"));
131 if (attribs
& SMB_FA_SYS
)
132 strcat(SMB_Attrib_Temp
, (verbose
?"System ":"S"));
134 if (attribs
& SMB_FA_VOL
)
135 strcat(SMB_Attrib_Temp
, (verbose
?"Volume ":"V"));
137 if (attribs
& SMB_FA_DIR
)
138 strcat(SMB_Attrib_Temp
, (verbose
?"Directory ":"D"));
140 if (attribs
& SMB_FA_ARC
)
141 strcat(SMB_Attrib_Temp
, (verbose
?"Archive ":"A"));
143 return(SMB_Attrib_Temp
);
147 /* Pick up the Max Buffer Size from the Tree Structure ... */
149 int SMB_Get_Tree_MBS(SMB_Tree_Handle tree
)
159 /* Pick up the Max buffer size */
161 int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle
)
164 if (Con_Handle
!= NULL
) {
165 return(Con_Handle
-> max_xmit
);
171 /* Pickup the protocol index from the connection structure */
173 int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle
)
176 if (Con_Handle
!= NULL
) {
177 return(Con_Handle
-> prot_IDX
);
179 return(0xFFFF); /* Invalid protocol */
183 #endif /* UNDEFINED */
185 /* Pick up the protocol from the connection structure */
187 int SMB_Get_Protocol(SMB_Handle_Type Con_Handle
)
190 if (Con_Handle
!= NULL
) {
191 return(Con_Handle
-> protocol
);
193 return(0xFFFF); /* Invalid protocol */
198 /* Figure out what protocol was accepted, given the list of dialect strings */
199 /* We offered, and the index back from the server. We allow for a user */
200 /* supplied list, and assume that it is a subset of our list */
202 int SMB_Figure_Protocol(const char *dialects
[], int prot_index
)
207 // prot_index may be a value outside the table SMB_Types[]
208 // which holds data at offsets 0 to 11
209 int ourType
= (prot_index
< 0 || prot_index
> 11);
211 if (ourType
&& dialects
== SMB_Prots
) { /* The jobs is easy, just index into table */
213 return(SMB_Types
[prot_index
]);
214 } else { /* Search through SMB_Prots looking for a match */
216 for (i
= 0; SMB_Prots
[i
] != NULL
; i
++) {
218 if (strcmp(dialects
[prot_index
], SMB_Prots
[i
]) == 0) { /* A match */
220 return(SMB_Types
[i
]);
226 /* If we got here, then we are in trouble, because the protocol was not */
227 /* One we understand ... */
229 return(SMB_P_Unknown
);
235 /* Negotiate the protocol we will use from the list passed in Prots */
236 /* we return the index of the accepted protocol in NegProt, -1 indicates */
237 /* none acceptible, and our return value is 0 if ok, <0 if problems */
239 int SMB_Negotiate(SMB_Handle_Type Con_Handle
, const char *Prots
[])
242 // struct SMB_Neg_Prot_Def *prot_pkt;
243 // struct SMB_Neg_Prot_Resp_Def *resp_pkt;
244 struct RFCNB_Pkt
*pkt
;
245 int prots_len
, i
, pkt_len
, prot
, alloc_len
;
248 /* Figure out how long the prot list will be and allocate space for it */
252 for (i
= 0; Prots
[i
] != NULL
; i
++) {
254 prots_len
= prots_len
+ strlen(Prots
[i
]) + 2; /* Account for null etc */
258 /* The -1 accounts for the one byte smb_buf we have because some systems */
259 /* don't like char msg_buf[] */
261 pkt_len
= SMB_negp_len
+ prots_len
;
263 /* Make sure that the pkt len is long enough for the max response ... */
264 /* Which is a problem, because the encryption key len eec may be long */
266 if (pkt_len
< (SMB_hdr_wct_offset
+ (19 * 2) + 40)) {
268 alloc_len
= SMB_hdr_wct_offset
+ (19 * 2) + 40;
276 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(alloc_len
);
280 SMBlib_errno
= SMBlibE_NoSpace
;
285 /* Now plug in the bits we need */
287 memset(SMB_Hdr(pkt
), 0, SMB_negp_len
);
288 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
289 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBnegprot
;
290 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Con_Handle
-> pid
);
291 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, 0);
292 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Con_Handle
-> mid
);
293 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Con_Handle
-> uid
);
294 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
296 SSVAL(SMB_Hdr(pkt
), SMB_negp_bcc_offset
, prots_len
);
298 /* Now copy the prot strings in with the right stuff */
300 p
= (char *)(SMB_Hdr(pkt
) + SMB_negp_buf_offset
);
302 for (i
= 0; Prots
[i
] != NULL
; i
++) {
305 strcpy(p
+ 1, Prots
[i
]);
306 p
= p
+ strlen(Prots
[i
]) + 2; /* Adjust len of p for null plus dialectID */
310 /* Now send the packet and sit back ... */
312 if (RFCNB_Send(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
315 fprintf(stderr
, "Error sending negotiate protocol\n");
319 SMBlib_errno
= -SMBlibE_SendFailed
; /* Failed, check lower layer errno */
324 /* Now get the response ... */
326 if (RFCNB_Recv(Con_Handle
-> Trans_Connect
, pkt
, alloc_len
) < 0) {
329 fprintf(stderr
, "Error receiving response to negotiate\n");
333 SMBlib_errno
= -SMBlibE_RecvFailed
; /* Failed, check lower layer errno */
338 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
341 fprintf(stderr
, "SMB_Negotiate failed with errorclass = %i, Error Code = %i\n",
342 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
343 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
346 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
348 SMBlib_errno
= SMBlibE_Remote
;
353 if (SVAL(SMB_Hdr(pkt
), SMB_negrCP_idx_offset
) == 0xFFFF) {
356 fprintf(stderr
, "None of our protocols was accepted ... ");
360 SMBlib_errno
= SMBlibE_NegNoProt
;
365 /* Now, unpack the info from the response, if any and evaluate the proto */
366 /* selected. We must make sure it is one we like ... */
368 Con_Handle
-> prot_IDX
= prot
= SVAL(SMB_Hdr(pkt
), SMB_negrCP_idx_offset
);
369 Con_Handle
-> protocol
= SMB_Figure_Protocol(Prots
, prot
);
371 if (Con_Handle
-> protocol
== SMB_P_Unknown
) { /* No good ... */
374 SMBlib_errno
= SMBlibE_ProtUnknown
;
379 switch (CVAL(SMB_Hdr(pkt
), SMB_hdr_wct_offset
)) {
381 case 0x01: /* No more info ... */
385 case 13: /* Up to and including LanMan 2.1 */
387 Con_Handle
-> Security
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_sec_offset
);
388 Con_Handle
-> encrypt_passwords
= ((Con_Handle
-> Security
& SMB_sec_encrypt_mask
) != 0x00);
389 Con_Handle
-> Security
= Con_Handle
-> Security
& SMB_sec_user_mask
;
391 Con_Handle
-> max_xmit
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_mbs_offset
);
392 Con_Handle
-> MaxMPX
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_mmc_offset
);
393 Con_Handle
-> MaxVC
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_mnv_offset
);
394 Con_Handle
-> Raw_Support
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_rm_offset
);
395 Con_Handle
-> SessionKey
= IVAL(SMB_Hdr(pkt
), SMB_negrLM_sk_offset
);
396 Con_Handle
-> SvrTZ
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_stz_offset
);
397 Con_Handle
-> Encrypt_Key_Len
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_ekl_offset
);
399 p
= (SMB_Hdr(pkt
) + SMB_negrLM_buf_offset
);
400 memcpy(Con_Handle
->Encrypt_Key
, p
, 8);
402 p
= (SMB_Hdr(pkt
) + SMB_negrLM_buf_offset
+ Con_Handle
-> Encrypt_Key_Len
);
404 strncpy(p
, Con_Handle
-> Svr_PDom
, sizeof(Con_Handle
-> Svr_PDom
) - 1);
408 case 17: /* NT LM 0.12 and LN LM 1.0 */
410 Con_Handle
-> Security
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_sec_offset
);
411 Con_Handle
-> encrypt_passwords
= ((Con_Handle
-> Security
& SMB_sec_encrypt_mask
) != 0x00);
412 Con_Handle
-> Security
= Con_Handle
-> Security
& SMB_sec_user_mask
;
414 Con_Handle
-> max_xmit
= IVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mbs_offset
);
415 Con_Handle
-> MaxMPX
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mmc_offset
);
416 Con_Handle
-> MaxVC
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mnv_offset
);
417 Con_Handle
-> MaxRaw
= IVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mrs_offset
);
418 Con_Handle
-> SessionKey
= IVAL(SMB_Hdr(pkt
), SMB_negrNTLM_sk_offset
);
419 Con_Handle
-> SvrTZ
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_stz_offset
);
420 Con_Handle
-> Encrypt_Key_Len
= CVAL(SMB_Hdr(pkt
), SMB_negrNTLM_ekl_offset
);
422 p
= (SMB_Hdr(pkt
) + SMB_negrNTLM_buf_offset
);
423 memcpy(Con_Handle
->Encrypt_Key
, p
, 8);
425 p
= (SMB_Hdr(pkt
) + SMB_negrLM_buf_offset
+ Con_Handle
-> Encrypt_Key_Len
);
427 strncpy(p
, Con_Handle
-> Svr_PDom
, sizeof(Con_Handle
-> Svr_PDom
) - 1);
434 fprintf(stderr
, "Unknown NegProt response format ... Ignored\n");
435 fprintf(stderr
, " wct = %i\n", CVAL(SMB_Hdr(pkt
), SMB_hdr_wct_offset
));
442 fprintf(stderr
, "Protocol selected is: %i:%s\n", prot
, Prots
[prot
]);
450 /* Get our hostname */
452 void SMB_Get_My_Name(char *name
, int len
)
455 if (gethostname(name
, len
) < 0) { /* Error getting name */
457 strncpy(name
, "unknown", len
);
459 /* Should check the error */
462 fprintf(stderr
, "gethostname in SMB_Get_My_Name returned error:");
468 /* only keep the portion up to the first "." */
469 if (NULL
!= (address
= strchr(name
, '.'))) {
470 *address
= '\0'; /* truncate at first '.' */
475 /* Send a TCON to the remote server ... */
477 SMB_Tree_Handle
SMB_TreeConnect(SMB_Handle_Type Con_Handle
,
478 SMB_Tree_Handle Tree_Handle
,
480 const char *password
,
484 struct RFCNB_Pkt
*pkt
;
485 int param_len
, pkt_len
;
487 SMB_Tree_Handle tree
;
489 /* Figure out how much space is needed for path, password, dev ... */
491 if ((path
== NULL
) | (password
== NULL
) | (device
== NULL
)) {
494 fprintf(stderr
, "Bad parameter passed to SMB_TreeConnect\n");
497 SMBlib_errno
= SMBlibE_BadParam
;
502 /* The + 2 is because of the \0 and the marker ... */
504 param_len
= strlen(path
) + 2 + strlen(password
) + 2 + strlen(device
) + 2;
506 /* The -1 accounts for the one byte smb_buf we have because some systems */
507 /* don't like char msg_buf[] */
509 pkt_len
= SMB_tcon_len
+ param_len
;
511 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
515 SMBlib_errno
= SMBlibE_NoSpace
;
516 return(NULL
); /* Should handle the error */
520 /* Now allocate a tree for this to go into ... */
522 if (Tree_Handle
== NULL
) {
524 tree
= (SMB_Tree_Handle
)malloc(sizeof(struct SMB_Tree_Structure
));
529 SMBlib_errno
= SMBlibE_NoSpace
;
539 tree
-> next
= tree
-> prev
= NULL
;
540 tree
-> con
= Con_Handle
;
541 strncpy(tree
-> path
, path
, sizeof(tree
-> path
));
542 strncpy(tree
-> device_type
, device
, sizeof(tree
-> device_type
));
544 /* Now plug in the values ... */
546 memset(SMB_Hdr(pkt
), 0, SMB_tcon_len
);
547 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
548 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBtcon
;
549 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Con_Handle
-> pid
);
550 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, 0);
551 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Con_Handle
-> mid
);
552 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Con_Handle
-> uid
);
553 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
555 SSVAL(SMB_Hdr(pkt
), SMB_tcon_bcc_offset
, param_len
);
557 /* Now copy the param strings in with the right stuff */
559 p
= (char *)(SMB_Hdr(pkt
) + SMB_tcon_buf_offset
);
562 p
= p
+ strlen(path
) + 2;
564 strcpy(p
+ 1, password
);
565 p
= p
+ strlen(password
) + 2;
567 strcpy(p
+ 1, device
);
569 /* Now send the packet and sit back ... */
571 if (RFCNB_Send(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
574 fprintf(stderr
, "Error sending TCon request\n");
577 if (Tree_Handle
== NULL
)
580 SMBlib_errno
= -SMBlibE_SendFailed
;
585 /* Now get the response ... */
587 if (RFCNB_Recv(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
590 fprintf(stderr
, "Error receiving response to TCon\n");
593 if (Tree_Handle
== NULL
)
596 SMBlib_errno
= -SMBlibE_RecvFailed
;
601 /* Check out the response type ... */
603 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
606 fprintf(stderr
, "SMB_TCon failed with errorclass = %i, Error Code = %i\n",
607 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
608 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
611 if (Tree_Handle
== NULL
)
613 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
615 SMBlib_errno
= SMBlibE_Remote
;
620 tree
-> tid
= SVAL(SMB_Hdr(pkt
), SMB_tconr_tid_offset
);
621 tree
-> mbs
= SVAL(SMB_Hdr(pkt
), SMB_tconr_mbs_offset
);
624 fprintf(stderr
, "TConn succeeded, with TID=%i, Max Xmit=%i\n",
625 tree
-> tid
, tree
-> mbs
);
628 /* Now link the Tree to the Server Structure ... */
630 if (Con_Handle
-> first_tree
== NULL
) {
632 Con_Handle
-> first_tree
= tree
;
633 Con_Handle
-> last_tree
= tree
;
637 Con_Handle
-> last_tree
-> next
= tree
;
638 tree
-> prev
= Con_Handle
-> last_tree
;
639 Con_Handle
-> last_tree
= tree
;
648 int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle
, BOOL discard
)
651 struct RFCNB_Pkt
*pkt
;
654 pkt_len
= SMB_tdis_len
;
656 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
660 SMBlib_errno
= SMBlibE_NoSpace
;
661 return(SMBlibE_BAD
); /* Should handle the error */
665 /* Now plug in the values ... */
667 memset(SMB_Hdr(pkt
), 0, SMB_tdis_len
);
668 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
669 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBtdis
;
670 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Tree_Handle
-> con
-> pid
);
671 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Tree_Handle
-> con
-> mid
);
672 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Tree_Handle
-> con
-> uid
);
673 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
675 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, Tree_Handle
-> tid
);
676 SSVAL(SMB_Hdr(pkt
), SMB_tcon_bcc_offset
, 0);
678 /* Now send the packet and sit back ... */
680 if (RFCNB_Send(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
683 fprintf(stderr
, "Error sending TDis request\n");
687 SMBlib_errno
= -SMBlibE_SendFailed
;
692 /* Now get the response ... */
694 if (RFCNB_Recv(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
697 fprintf(stderr
, "Error receiving response to TCon\n");
701 SMBlib_errno
= -SMBlibE_RecvFailed
;
706 /* Check out the response type ... */
708 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
711 fprintf(stderr
, "SMB_TDis failed with errorclass = %i, Error Code = %i\n",
712 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
713 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
716 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
718 SMBlib_errno
= SMBlibE_Remote
;
723 Tree_Handle
-> tid
= 0xFFFF; /* Invalid TID */
724 Tree_Handle
-> mbs
= 0; /* Invalid */
728 fprintf(stderr
, "Tree disconnect successful ...\n");
732 /* What about the tree handle ? */
734 if (discard
== TRUE
) { /* Unlink it and free it ... */
736 if (Tree_Handle
-> next
== NULL
)
737 Tree_Handle
-> con
-> first_tree
= Tree_Handle
-> prev
;
739 Tree_Handle
-> next
-> prev
= Tree_Handle
-> prev
;
741 if (Tree_Handle
-> prev
== NULL
)
742 Tree_Handle
-> con
-> last_tree
= Tree_Handle
-> next
;
744 Tree_Handle
-> prev
-> next
= Tree_Handle
-> next
;
753 /* Pick up the last LMBlib error ... */
755 int SMB_Get_Last_Error()
759 return(SMBlib_errno
);
763 /* Pick up the last error returned in an SMB packet */
764 /* We will need macros to extract error class and error code */
766 int SMB_Get_Last_SMB_Err()
770 return(SMBlib_SMB_Error
);
774 /* Pick up the error message associated with an error from SMBlib */
776 /* Keep this table in sync with the message codes in smblib-common.h */
778 static const char *SMBlib_Error_Messages
[] = {
780 "Request completed successfully.",
781 "Server returned a non-zero SMB Error Class and Code.",
782 "A lower layer protocol error occurred.",
783 "Function not yet implemented.",
784 "The protocol negotiated does not support the request.",
785 "No space available for operation.",
786 "One or more bad parameters passed.",
787 "None of the protocols we offered were accepted.",
788 "The attempt to send an SMB request failed. See protocol error info.",
789 "The attempt to get an SMB response failed. See protocol error info.",
790 "The logon request failed, but you were logged in as guest.",
791 "The attempt to call the remote server failed. See protocol error info.",
792 "The protocol dialect specified in a NegProt and accepted by the server is unknown.",
793 /* This next one simplifies error handling */
794 "No such error code.",
798 void SMB_Get_Error_Msg(int msg
, char *msgbuf
, int len
)
805 SMBlib_Error_Messages
[msg
>SMBlibE_NoSuchMsg
?SMBlibE_NoSuchMsg
:msg
],
807 msgbuf
[len
- 1] = 0; /* Make sure it is a string */
808 } else { /* Add the lower layer message ... */
812 msg
= -msg
; /* Make it positive */
815 SMBlib_Error_Messages
[msg
>SMBlibE_NoSuchMsg
?SMBlibE_NoSuchMsg
:msg
],
818 msgbuf
[len
- 1] = 0; /* make sure it is a string */
820 if (strlen(msgbuf
) < len
) { /* If there is space, put rest in */
822 strncat(msgbuf
, "\n\t", len
- strlen(msgbuf
));
824 RFCNB_Get_Error(prot_msg
, sizeof(prot_msg
) - 1);
826 strncat(msgbuf
, prot_msg
, len
- strlen(msgbuf
));