3 /* UNIX SMBlib NetBIOS implementation
6 SMBlib Utility Routines
8 Copyright (C) Richard Sharpe 1996
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "smblib/smblib.h"
29 #include "smblib/smblib-priv.h"
30 #include "rfcnb/rfcnb.h"
36 int SMB_Types
[] = {SMB_P_Core
,
52 char *SMB_DOSTimToStr(int DOS_time
);
53 char *SMB_AtrToStr(int attribs
, BOOL verbose
);
54 int SMB_Get_Tree_MBS(SMB_Tree_Handle tree
);
55 int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle
);
56 int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle
);
57 #endif /* UNDEFINED */
58 int SMB_Get_Protocol(SMB_Handle_Type Con_Handle
);
59 int SMB_Figure_Protocol(const char *dialects
[], int prot_index
);
60 int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle
, BOOL discard
);
63 /* Print out an SMB pkt in all its gory detail ... */
65 void SMB_Print_Pkt(FILE fd
, RFCNB_Pkt
*pkt
, BOOL command
, int Offset
, int Len
)
69 /* Well, just how do we do this ... print it I suppose */
71 /* Print out the SMB header ... */
73 /* Print the command */
75 /* Print the other bits in the header */
83 /* Convert a DOS Date_Time to a local host type date time for printing */
86 char *SMB_DOSTimToStr(int DOS_time
)
89 static char SMB_Time_Temp
[48];
90 int DOS_sec
, DOS_min
, DOS_hour
, DOS_day
, DOS_month
, DOS_year
;
94 DOS_sec
= (DOS_time
& 0x001F) * 2;
95 DOS_min
= (DOS_time
& 0x07E0) >> 5;
96 DOS_hour
= ((DOS_time
& 0xF800) >> 11);
98 DOS_day
= (DOS_time
& 0x001F0000) >> 16;
99 DOS_month
= (DOS_time
& 0x01E00000) >> 21;
100 DOS_year
= ((DOS_time
& 0xFE000000) >> 25) + 80;
102 snprintf(SMB_Time_Temp
, 48, "%2d/%02d/%2d %2d:%02d:%02d", DOS_day
, DOS_month
,
103 DOS_year
, DOS_hour
, DOS_min
, DOS_sec
);
105 return(SMB_Time_Temp
);
109 /* Convert an attribute byte/word etc to a string ... We return a pointer
110 to a static string which we guarantee is long enough. If verbose is
111 true, we print out long form of strings ... */
113 char *SMB_AtrToStr(int attribs
, BOOL verbose
)
116 static char SMB_Attrib_Temp
[128];
118 SMB_Attrib_Temp
[0] = 0;
120 if (attribs
& SMB_FA_ROF
)
121 strcat(SMB_Attrib_Temp
, (verbose
?"Read Only ":"R"));
123 if (attribs
& SMB_FA_HID
)
124 strcat(SMB_Attrib_Temp
, (verbose
?"Hidden ":"H"));
126 if (attribs
& SMB_FA_SYS
)
127 strcat(SMB_Attrib_Temp
, (verbose
?"System ":"S"));
129 if (attribs
& SMB_FA_VOL
)
130 strcat(SMB_Attrib_Temp
, (verbose
?"Volume ":"V"));
132 if (attribs
& SMB_FA_DIR
)
133 strcat(SMB_Attrib_Temp
, (verbose
?"Directory ":"D"));
135 if (attribs
& SMB_FA_ARC
)
136 strcat(SMB_Attrib_Temp
, (verbose
?"Archive ":"A"));
138 return(SMB_Attrib_Temp
);
142 /* Pick up the Max Buffer Size from the Tree Structure ... */
144 int SMB_Get_Tree_MBS(SMB_Tree_Handle tree
)
154 /* Pick up the Max buffer size */
156 int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle
)
159 if (Con_Handle
!= NULL
) {
160 return(Con_Handle
-> max_xmit
);
166 /* Pickup the protocol index from the connection structure */
168 int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle
)
171 if (Con_Handle
!= NULL
) {
172 return(Con_Handle
-> prot_IDX
);
174 return(0xFFFF); /* Invalid protocol */
178 #endif /* UNDEFINED */
180 /* Pick up the protocol from the connection structure */
182 int SMB_Get_Protocol(SMB_Handle_Type Con_Handle
)
185 if (Con_Handle
!= NULL
) {
186 return(Con_Handle
-> protocol
);
188 return(0xFFFF); /* Invalid protocol */
193 /* Figure out what protocol was accepted, given the list of dialect strings */
194 /* We offered, and the index back from the server. We allow for a user */
195 /* supplied list, and assume that it is a subset of our list */
197 int SMB_Figure_Protocol(const char *dialects
[], int prot_index
)
202 if (dialects
== SMB_Prots
) { /* The jobs is easy, just index into table */
204 return(SMB_Types
[prot_index
]);
205 } else { /* Search through SMB_Prots looking for a match */
207 for (i
= 0; SMB_Prots
[i
] != NULL
; i
++) {
209 if (strcmp(dialects
[prot_index
], SMB_Prots
[i
]) == 0) { /* A match */
211 return(SMB_Types
[i
]);
217 /* If we got here, then we are in trouble, because the protocol was not */
218 /* One we understand ... */
220 return(SMB_P_Unknown
);
227 /* Negotiate the protocol we will use from the list passed in Prots */
228 /* we return the index of the accepted protocol in NegProt, -1 indicates */
229 /* none acceptible, and our return value is 0 if ok, <0 if problems */
231 int SMB_Negotiate(SMB_Handle_Type Con_Handle
, const char *Prots
[])
234 // struct SMB_Neg_Prot_Def *prot_pkt;
235 // struct SMB_Neg_Prot_Resp_Def *resp_pkt;
236 struct RFCNB_Pkt
*pkt
;
237 int prots_len
, i
, pkt_len
, prot
, alloc_len
;
240 /* Figure out how long the prot list will be and allocate space for it */
244 for (i
= 0; Prots
[i
] != NULL
; i
++) {
246 prots_len
= prots_len
+ strlen(Prots
[i
]) + 2; /* Account for null etc */
250 /* The -1 accounts for the one byte smb_buf we have because some systems */
251 /* don't like char msg_buf[] */
253 pkt_len
= SMB_negp_len
+ prots_len
;
255 /* Make sure that the pkt len is long enough for the max response ... */
256 /* Which is a problem, because the encryption key len eec may be long */
258 if (pkt_len
< (SMB_hdr_wct_offset
+ (19 * 2) + 40)) {
260 alloc_len
= SMB_hdr_wct_offset
+ (19 * 2) + 40;
268 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(alloc_len
);
272 SMBlib_errno
= SMBlibE_NoSpace
;
277 /* Now plug in the bits we need */
279 memset(SMB_Hdr(pkt
), 0, SMB_negp_len
);
280 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
281 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBnegprot
;
282 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Con_Handle
-> pid
);
283 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, 0);
284 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Con_Handle
-> mid
);
285 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Con_Handle
-> uid
);
286 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
288 SSVAL(SMB_Hdr(pkt
), SMB_negp_bcc_offset
, prots_len
);
290 /* Now copy the prot strings in with the right stuff */
292 p
= (char *)(SMB_Hdr(pkt
) + SMB_negp_buf_offset
);
294 for (i
= 0; Prots
[i
] != NULL
; i
++) {
297 strcpy(p
+ 1, Prots
[i
]);
298 p
= p
+ strlen(Prots
[i
]) + 2; /* Adjust len of p for null plus dialectID */
302 /* Now send the packet and sit back ... */
304 if (RFCNB_Send(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
308 fprintf(stderr
, "Error sending negotiate protocol\n");
312 SMBlib_errno
= -SMBlibE_SendFailed
; /* Failed, check lower layer errno */
317 /* Now get the response ... */
319 if (RFCNB_Recv(Con_Handle
-> Trans_Connect
, pkt
, alloc_len
) < 0) {
322 fprintf(stderr
, "Error receiving response to negotiate\n");
326 SMBlib_errno
= -SMBlibE_RecvFailed
; /* Failed, check lower layer errno */
331 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
334 fprintf(stderr
, "SMB_Negotiate failed with errorclass = %i, Error Code = %i\n",
335 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
336 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
339 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
341 SMBlib_errno
= SMBlibE_Remote
;
346 if (SVAL(SMB_Hdr(pkt
), SMB_negrCP_idx_offset
) == 0xFFFF) {
349 fprintf(stderr
, "None of our protocols was accepted ... ");
353 SMBlib_errno
= SMBlibE_NegNoProt
;
358 /* Now, unpack the info from the response, if any and evaluate the proto */
359 /* selected. We must make sure it is one we like ... */
361 Con_Handle
-> prot_IDX
= prot
= SVAL(SMB_Hdr(pkt
), SMB_negrCP_idx_offset
);
362 Con_Handle
-> protocol
= SMB_Figure_Protocol(Prots
, prot
);
364 if (Con_Handle
-> protocol
== SMB_P_Unknown
) { /* No good ... */
367 SMBlib_errno
= SMBlibE_ProtUnknown
;
372 switch (CVAL(SMB_Hdr(pkt
), SMB_hdr_wct_offset
)) {
374 case 0x01: /* No more info ... */
378 case 13: /* Up to and including LanMan 2.1 */
380 Con_Handle
-> Security
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_sec_offset
);
381 Con_Handle
-> encrypt_passwords
= ((Con_Handle
-> Security
& SMB_sec_encrypt_mask
) != 0x00);
382 Con_Handle
-> Security
= Con_Handle
-> Security
& SMB_sec_user_mask
;
384 Con_Handle
-> max_xmit
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_mbs_offset
);
385 Con_Handle
-> MaxMPX
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_mmc_offset
);
386 Con_Handle
-> MaxVC
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_mnv_offset
);
387 Con_Handle
-> Raw_Support
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_rm_offset
);
388 Con_Handle
-> SessionKey
= IVAL(SMB_Hdr(pkt
), SMB_negrLM_sk_offset
);
389 Con_Handle
-> SvrTZ
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_stz_offset
);
390 Con_Handle
-> Encrypt_Key_Len
= SVAL(SMB_Hdr(pkt
), SMB_negrLM_ekl_offset
);
392 p
= (SMB_Hdr(pkt
) + SMB_negrLM_buf_offset
);
393 memcpy(Con_Handle
->Encrypt_Key
, p
, 8);
395 p
= (SMB_Hdr(pkt
) + SMB_negrLM_buf_offset
+ Con_Handle
-> Encrypt_Key_Len
);
397 strncpy(p
, Con_Handle
-> Svr_PDom
, sizeof(Con_Handle
-> Svr_PDom
) - 1);
401 case 17: /* NT LM 0.12 and LN LM 1.0 */
403 Con_Handle
-> Security
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_sec_offset
);
404 Con_Handle
-> encrypt_passwords
= ((Con_Handle
-> Security
& SMB_sec_encrypt_mask
) != 0x00);
405 Con_Handle
-> Security
= Con_Handle
-> Security
& SMB_sec_user_mask
;
407 Con_Handle
-> max_xmit
= IVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mbs_offset
);
408 Con_Handle
-> MaxMPX
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mmc_offset
);
409 Con_Handle
-> MaxVC
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mnv_offset
);
410 Con_Handle
-> MaxRaw
= IVAL(SMB_Hdr(pkt
), SMB_negrNTLM_mrs_offset
);
411 Con_Handle
-> SessionKey
= IVAL(SMB_Hdr(pkt
), SMB_negrNTLM_sk_offset
);
412 Con_Handle
-> SvrTZ
= SVAL(SMB_Hdr(pkt
), SMB_negrNTLM_stz_offset
);
413 Con_Handle
-> Encrypt_Key_Len
= CVAL(SMB_Hdr(pkt
), SMB_negrNTLM_ekl_offset
);
415 p
= (SMB_Hdr(pkt
) + SMB_negrNTLM_buf_offset
);
416 memcpy(Con_Handle
->Encrypt_Key
, p
, 8);
418 p
= (SMB_Hdr(pkt
) + SMB_negrLM_buf_offset
+ Con_Handle
-> Encrypt_Key_Len
);
420 strncpy(p
, Con_Handle
-> Svr_PDom
, sizeof(Con_Handle
-> Svr_PDom
) - 1);
427 fprintf(stderr
, "Unknown NegProt response format ... Ignored\n");
428 fprintf(stderr
, " wct = %i\n", CVAL(SMB_Hdr(pkt
), SMB_hdr_wct_offset
));
435 fprintf(stderr
, "Protocol selected is: %i:%s\n", prot
, Prots
[prot
]);
443 /* Get our hostname */
445 void SMB_Get_My_Name(char *name
, int len
)
448 if (gethostname(name
, len
) < 0) { /* Error getting name */
450 strncpy(name
, "unknown", len
);
452 /* Should check the error */
455 fprintf(stderr
, "gethostname in SMB_Get_My_Name returned error:");
461 /* only keep the portion up to the first "." */
462 if (NULL
!= (address
= strchr(name
, '.'))) {
463 *address
= '\0'; /* truncate at first '.' */
468 /* Send a TCON to the remote server ... */
470 SMB_Tree_Handle
SMB_TreeConnect(SMB_Handle_Type Con_Handle
,
471 SMB_Tree_Handle Tree_Handle
,
473 const char *password
,
477 struct RFCNB_Pkt
*pkt
;
478 int param_len
, pkt_len
;
480 SMB_Tree_Handle tree
;
482 /* Figure out how much space is needed for path, password, dev ... */
484 if ((path
== NULL
) | (password
== NULL
) | (device
== NULL
)) {
487 fprintf(stderr
, "Bad parameter passed to SMB_TreeConnect\n");
490 SMBlib_errno
= SMBlibE_BadParam
;
495 /* The + 2 is because of the \0 and the marker ... */
497 param_len
= strlen(path
) + 2 + strlen(password
) + 2 + strlen(device
) + 2;
499 /* The -1 accounts for the one byte smb_buf we have because some systems */
500 /* don't like char msg_buf[] */
502 pkt_len
= SMB_tcon_len
+ param_len
;
504 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
508 SMBlib_errno
= SMBlibE_NoSpace
;
509 return(NULL
); /* Should handle the error */
513 /* Now allocate a tree for this to go into ... */
515 if (Tree_Handle
== NULL
) {
517 tree
= (SMB_Tree_Handle
)malloc(sizeof(struct SMB_Tree_Structure
));
522 SMBlib_errno
= SMBlibE_NoSpace
;
532 tree
-> next
= tree
-> prev
= NULL
;
533 tree
-> con
= Con_Handle
;
534 strncpy(tree
-> path
, path
, sizeof(tree
-> path
));
535 strncpy(tree
-> device_type
, device
, sizeof(tree
-> device_type
));
537 /* Now plug in the values ... */
539 memset(SMB_Hdr(pkt
), 0, SMB_tcon_len
);
540 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
541 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBtcon
;
542 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Con_Handle
-> pid
);
543 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, 0);
544 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Con_Handle
-> mid
);
545 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Con_Handle
-> uid
);
546 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
548 SSVAL(SMB_Hdr(pkt
), SMB_tcon_bcc_offset
, param_len
);
550 /* Now copy the param strings in with the right stuff */
552 p
= (char *)(SMB_Hdr(pkt
) + SMB_tcon_buf_offset
);
555 p
= p
+ strlen(path
) + 2;
557 strcpy(p
+ 1, password
);
558 p
= p
+ strlen(password
) + 2;
560 strcpy(p
+ 1, device
);
562 /* Now send the packet and sit back ... */
564 if (RFCNB_Send(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
567 fprintf(stderr
, "Error sending TCon request\n");
570 if (Tree_Handle
== NULL
)
573 SMBlib_errno
= -SMBlibE_SendFailed
;
578 /* Now get the response ... */
580 if (RFCNB_Recv(Con_Handle
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
583 fprintf(stderr
, "Error receiving response to TCon\n");
586 if (Tree_Handle
== NULL
)
589 SMBlib_errno
= -SMBlibE_RecvFailed
;
594 /* Check out the response type ... */
596 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
599 fprintf(stderr
, "SMB_TCon failed with errorclass = %i, Error Code = %i\n",
600 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
601 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
604 if (Tree_Handle
== NULL
)
606 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
608 SMBlib_errno
= SMBlibE_Remote
;
613 tree
-> tid
= SVAL(SMB_Hdr(pkt
), SMB_tconr_tid_offset
);
614 tree
-> mbs
= SVAL(SMB_Hdr(pkt
), SMB_tconr_mbs_offset
);
617 fprintf(stderr
, "TConn succeeded, with TID=%i, Max Xmit=%i\n",
618 tree
-> tid
, tree
-> mbs
);
621 /* Now link the Tree to the Server Structure ... */
623 if (Con_Handle
-> first_tree
== NULL
) {
625 Con_Handle
-> first_tree
= tree
;
626 Con_Handle
-> last_tree
= tree
;
630 Con_Handle
-> last_tree
-> next
= tree
;
631 tree
-> prev
= Con_Handle
-> last_tree
;
632 Con_Handle
-> last_tree
= tree
;
641 int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle
, BOOL discard
)
644 struct RFCNB_Pkt
*pkt
;
647 pkt_len
= SMB_tdis_len
;
649 pkt
= (struct RFCNB_Pkt
*)RFCNB_Alloc_Pkt(pkt_len
);
653 SMBlib_errno
= SMBlibE_NoSpace
;
654 return(SMBlibE_BAD
); /* Should handle the error */
658 /* Now plug in the values ... */
660 memset(SMB_Hdr(pkt
), 0, SMB_tdis_len
);
661 SIVAL(SMB_Hdr(pkt
), SMB_hdr_idf_offset
, SMB_DEF_IDF
); /* Plunk in IDF */
662 *(SMB_Hdr(pkt
) + SMB_hdr_com_offset
) = SMBtdis
;
663 SSVAL(SMB_Hdr(pkt
), SMB_hdr_pid_offset
, Tree_Handle
-> con
-> pid
);
664 SSVAL(SMB_Hdr(pkt
), SMB_hdr_mid_offset
, Tree_Handle
-> con
-> mid
);
665 SSVAL(SMB_Hdr(pkt
), SMB_hdr_uid_offset
, Tree_Handle
-> con
-> uid
);
666 *(SMB_Hdr(pkt
) + SMB_hdr_wct_offset
) = 0;
668 SSVAL(SMB_Hdr(pkt
), SMB_hdr_tid_offset
, Tree_Handle
-> tid
);
669 SSVAL(SMB_Hdr(pkt
), SMB_tcon_bcc_offset
, 0);
671 /* Now send the packet and sit back ... */
673 if (RFCNB_Send(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
676 fprintf(stderr
, "Error sending TDis request\n");
680 SMBlib_errno
= -SMBlibE_SendFailed
;
685 /* Now get the response ... */
687 if (RFCNB_Recv(Tree_Handle
-> con
-> Trans_Connect
, pkt
, pkt_len
) < 0) {
690 fprintf(stderr
, "Error receiving response to TCon\n");
694 SMBlib_errno
= -SMBlibE_RecvFailed
;
699 /* Check out the response type ... */
701 if (CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
) != SMBC_SUCCESS
) { /* Process error */
704 fprintf(stderr
, "SMB_TDis failed with errorclass = %i, Error Code = %i\n",
705 CVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
),
706 SVAL(SMB_Hdr(pkt
), SMB_hdr_err_offset
));
709 SMBlib_SMB_Error
= IVAL(SMB_Hdr(pkt
), SMB_hdr_rcls_offset
);
711 SMBlib_errno
= SMBlibE_Remote
;
716 Tree_Handle
-> tid
= 0xFFFF; /* Invalid TID */
717 Tree_Handle
-> mbs
= 0; /* Invalid */
721 fprintf(stderr
, "Tree disconnect successful ...\n");
725 /* What about the tree handle ? */
727 if (discard
== TRUE
) { /* Unlink it and free it ... */
729 if (Tree_Handle
-> next
== NULL
)
730 Tree_Handle
-> con
-> first_tree
= Tree_Handle
-> prev
;
732 Tree_Handle
-> next
-> prev
= Tree_Handle
-> prev
;
734 if (Tree_Handle
-> prev
== NULL
)
735 Tree_Handle
-> con
-> last_tree
= Tree_Handle
-> next
;
737 Tree_Handle
-> prev
-> next
= Tree_Handle
-> next
;
746 /* Pick up the last LMBlib error ... */
748 int SMB_Get_Last_Error()
752 return(SMBlib_errno
);
756 /* Pick up the last error returned in an SMB packet */
757 /* We will need macros to extract error class and error code */
759 int SMB_Get_Last_SMB_Err()
763 return(SMBlib_SMB_Error
);
767 /* Pick up the error message associated with an error from SMBlib */
769 /* Keep this table in sync with the message codes in smblib-common.h */
771 static const char *SMBlib_Error_Messages
[] = {
773 "Request completed sucessfully.",
774 "Server returned a non-zero SMB Error Class and Code.",
775 "A lower layer protocol error occurred.",
776 "Function not yet implemented.",
777 "The protocol negotiated does not support the request.",
778 "No space available for operation.",
779 "One or more bad parameters passed.",
780 "None of the protocols we offered were accepted.",
781 "The attempt to send an SMB request failed. See protocol error info.",
782 "The attempt to get an SMB response failed. See protocol error info.",
783 "The logon request failed, but you were logged in as guest.",
784 "The attempt to call the remote server failed. See protocol error info.",
785 "The protocol dialect specified in a NegProt and accepted by the server is unknown.",
786 /* This next one simplifies error handling */
787 "No such error code.",
791 void SMB_Get_Error_Msg(int msg
, char *msgbuf
, int len
)
798 SMBlib_Error_Messages
[msg
>SMBlibE_NoSuchMsg
?SMBlibE_NoSuchMsg
:msg
],
800 msgbuf
[len
- 1] = 0; /* Make sure it is a string */
801 } else { /* Add the lower layer message ... */
805 msg
= -msg
; /* Make it positive */
808 SMBlib_Error_Messages
[msg
>SMBlibE_NoSuchMsg
?SMBlibE_NoSuchMsg
:msg
],
811 msgbuf
[len
- 1] = 0; /* make sure it is a string */
813 if (strlen(msgbuf
) < len
) { /* If there is space, put rest in */
815 strncat(msgbuf
, "\n\t", len
- strlen(msgbuf
));
817 RFCNB_Get_Error(prot_msg
, sizeof(prot_msg
) - 1);
819 strncat(msgbuf
, prot_msg
, len
- strlen(msgbuf
));