]> git.ipfire.org Git - thirdparty/squid.git/blob - lib/smblib/smblib-util.c
merge from trunk
[thirdparty/squid.git] / lib / smblib / smblib-util.c
1 #include "config.h"
2
3 /* UNIX SMBlib NetBIOS implementation
4
5 Version 1.0
6 SMBlib Utility Routines
7
8 Copyright (C) Richard Sharpe 1996
9
10 */
11
12 /*
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.
17
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.
22
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.
26 */
27
28 #include "smblib/smblib.h"
29 #include "smblib/smblib-priv.h"
30 #include "rfcnb/rfcnb.h"
31
32 #if HAVE_STRING_H
33 #include <string.h>
34 #endif
35
36 int SMB_Types[] = {SMB_P_Core,
37 SMB_P_CorePlus,
38 SMB_P_DOSLanMan1,
39 SMB_P_DOSLanMan1,
40 SMB_P_LanMan1,
41 SMB_P_DOSLanMan2,
42 SMB_P_LanMan2,
43 SMB_P_LanMan2_1,
44 SMB_P_LanMan2_1,
45 SMB_P_NT1,
46 SMB_P_NT1,
47 SMB_P_NT1,
48 -1
49 };
50
51 #if UNDEFINED
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);
61
62 #if UNDEFINED
63 /* Print out an SMB pkt in all its gory detail ... */
64
65 void SMB_Print_Pkt(FILE fd, RFCNB_Pkt *pkt, BOOL command, int Offset, int Len)
66
67 {
68
69 /* Well, just how do we do this ... print it I suppose */
70
71 /* Print out the SMB header ... */
72
73 /* Print the command */
74
75 /* Print the other bits in the header */
76
77
78 /* etc */
79
80 }
81 #endif
82
83 /* Convert a DOS Date_Time to a local host type date time for printing */
84
85 #if UNDEFINED
86 char *SMB_DOSTimToStr(int DOS_time)
87
88 {
89 static char SMB_Time_Temp[48];
90 int DOS_sec, DOS_min, DOS_hour, DOS_day, DOS_month, DOS_year;
91
92 SMB_Time_Temp[0] = 0;
93
94 DOS_sec = (DOS_time & 0x001F) * 2;
95 DOS_min = (DOS_time & 0x07E0) >> 5;
96 DOS_hour = ((DOS_time & 0xF800) >> 11);
97
98 DOS_day = (DOS_time & 0x001F0000) >> 16;
99 DOS_month = (DOS_time & 0x01E00000) >> 21;
100 DOS_year = ((DOS_time & 0xFE000000) >> 25) + 80;
101
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);
104
105 return(SMB_Time_Temp);
106
107 }
108
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 ... */
112
113 char *SMB_AtrToStr(int attribs, BOOL verbose)
114
115 {
116 static char SMB_Attrib_Temp[128];
117
118 SMB_Attrib_Temp[0] = 0;
119
120 if (attribs & SMB_FA_ROF)
121 strcat(SMB_Attrib_Temp, (verbose?"Read Only ":"R"));
122
123 if (attribs & SMB_FA_HID)
124 strcat(SMB_Attrib_Temp, (verbose?"Hidden ":"H"));
125
126 if (attribs & SMB_FA_SYS)
127 strcat(SMB_Attrib_Temp, (verbose?"System ":"S"));
128
129 if (attribs & SMB_FA_VOL)
130 strcat(SMB_Attrib_Temp, (verbose?"Volume ":"V"));
131
132 if (attribs & SMB_FA_DIR)
133 strcat(SMB_Attrib_Temp, (verbose?"Directory ":"D"));
134
135 if (attribs & SMB_FA_ARC)
136 strcat(SMB_Attrib_Temp, (verbose?"Archive ":"A"));
137
138 return(SMB_Attrib_Temp);
139
140 }
141
142 /* Pick up the Max Buffer Size from the Tree Structure ... */
143
144 int SMB_Get_Tree_MBS(SMB_Tree_Handle tree)
145
146 {
147 if (tree != NULL) {
148 return(tree -> mbs);
149 } else {
150 return(SMBlibE_BAD);
151 }
152 }
153
154 /* Pick up the Max buffer size */
155
156 int SMB_Get_Max_Buf_Siz(SMB_Handle_Type Con_Handle)
157
158 {
159 if (Con_Handle != NULL) {
160 return(Con_Handle -> max_xmit);
161 } else {
162 return(SMBlibE_BAD);
163 }
164
165 }
166 /* Pickup the protocol index from the connection structure */
167
168 int SMB_Get_Protocol_IDX(SMB_Handle_Type Con_Handle)
169
170 {
171 if (Con_Handle != NULL) {
172 return(Con_Handle -> prot_IDX);
173 } else {
174 return(0xFFFF); /* Invalid protocol */
175 }
176
177 }
178 #endif /* UNDEFINED */
179
180 /* Pick up the protocol from the connection structure */
181
182 int SMB_Get_Protocol(SMB_Handle_Type Con_Handle)
183
184 {
185 if (Con_Handle != NULL) {
186 return(Con_Handle -> protocol);
187 } else {
188 return(0xFFFF); /* Invalid protocol */
189 }
190
191 }
192
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 */
196
197 int SMB_Figure_Protocol(const char *dialects[], int prot_index)
198
199 {
200 int i;
201
202 if (dialects == SMB_Prots) { /* The jobs is easy, just index into table */
203
204 return(SMB_Types[prot_index]);
205 } else { /* Search through SMB_Prots looking for a match */
206
207 for (i = 0; SMB_Prots[i] != NULL; i++) {
208
209 if (strcmp(dialects[prot_index], SMB_Prots[i]) == 0) { /* A match */
210
211 return(SMB_Types[i]);
212
213 }
214
215 }
216
217 /* If we got here, then we are in trouble, because the protocol was not */
218 /* One we understand ... */
219
220 return(SMB_P_Unknown);
221
222 }
223
224 }
225
226
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 */
230
231 int SMB_Negotiate(SMB_Handle_Type Con_Handle, const char *Prots[])
232
233 {
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;
238 char *p;
239
240 /* Figure out how long the prot list will be and allocate space for it */
241
242 prots_len = 0;
243
244 for (i = 0; Prots[i] != NULL; i++) {
245
246 prots_len = prots_len + strlen(Prots[i]) + 2; /* Account for null etc */
247
248 }
249
250 /* The -1 accounts for the one byte smb_buf we have because some systems */
251 /* don't like char msg_buf[] */
252
253 pkt_len = SMB_negp_len + prots_len;
254
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 */
257
258 if (pkt_len < (SMB_hdr_wct_offset + (19 * 2) + 40)) {
259
260 alloc_len = SMB_hdr_wct_offset + (19 * 2) + 40;
261
262 } else {
263
264 alloc_len = pkt_len;
265
266 }
267
268 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(alloc_len);
269
270 if (pkt == NULL) {
271
272 SMBlib_errno = SMBlibE_NoSpace;
273 return(SMBlibE_BAD);
274
275 }
276
277 /* Now plug in the bits we need */
278
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;
287
288 SSVAL(SMB_Hdr(pkt), SMB_negp_bcc_offset, prots_len);
289
290 /* Now copy the prot strings in with the right stuff */
291
292 p = (char *)(SMB_Hdr(pkt) + SMB_negp_buf_offset);
293
294 for (i = 0; Prots[i] != NULL; i++) {
295
296 *p = SMBdialectID;
297 strcpy(p + 1, Prots[i]);
298 p = p + strlen(Prots[i]) + 2; /* Adjust len of p for null plus dialectID */
299
300 }
301
302 /* Now send the packet and sit back ... */
303
304 if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
305
306
307 #ifdef DEBUG
308 fprintf(stderr, "Error sending negotiate protocol\n");
309 #endif
310
311 RFCNB_Free_Pkt(pkt);
312 SMBlib_errno = -SMBlibE_SendFailed; /* Failed, check lower layer errno */
313 return(SMBlibE_BAD);
314
315 }
316
317 /* Now get the response ... */
318
319 if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, alloc_len) < 0) {
320
321 #ifdef DEBUG
322 fprintf(stderr, "Error receiving response to negotiate\n");
323 #endif
324
325 RFCNB_Free_Pkt(pkt);
326 SMBlib_errno = -SMBlibE_RecvFailed; /* Failed, check lower layer errno */
327 return(SMBlibE_BAD);
328
329 }
330
331 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
332
333 #ifdef DEBUG
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));
337 #endif
338
339 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
340 RFCNB_Free_Pkt(pkt);
341 SMBlib_errno = SMBlibE_Remote;
342 return(SMBlibE_BAD);
343
344 }
345
346 if (SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset) == 0xFFFF) {
347
348 #ifdef DEBUG
349 fprintf(stderr, "None of our protocols was accepted ... ");
350 #endif
351
352 RFCNB_Free_Pkt(pkt);
353 SMBlib_errno = SMBlibE_NegNoProt;
354 return(SMBlibE_BAD);
355
356 }
357
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 ... */
360
361 Con_Handle -> prot_IDX = prot = SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset);
362 Con_Handle -> protocol = SMB_Figure_Protocol(Prots, prot);
363
364 if (Con_Handle -> protocol == SMB_P_Unknown) { /* No good ... */
365
366 RFCNB_Free_Pkt(pkt);
367 SMBlib_errno = SMBlibE_ProtUnknown;
368 return(SMBlibE_BAD);
369
370 }
371
372 switch (CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset)) {
373
374 case 0x01: /* No more info ... */
375
376 break;
377
378 case 13: /* Up to and including LanMan 2.1 */
379
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;
383
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);
391
392 p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset);
393 memcpy(Con_Handle->Encrypt_Key, p, 8);
394
395 p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len);
396
397 strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1);
398
399 break;
400
401 case 17: /* NT LM 0.12 and LN LM 1.0 */
402
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;
406
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);
414
415 p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset);
416 memcpy(Con_Handle->Encrypt_Key, p, 8);
417
418 p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len);
419
420 strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1);
421
422 break;
423
424 default:
425
426 #ifdef DEBUG
427 fprintf(stderr, "Unknown NegProt response format ... Ignored\n");
428 fprintf(stderr, " wct = %i\n", CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset));
429 #endif
430
431 break;
432 }
433
434 #ifdef DEBUG
435 fprintf(stderr, "Protocol selected is: %i:%s\n", prot, Prots[prot]);
436 #endif
437
438 RFCNB_Free_Pkt(pkt);
439 return(0);
440
441 }
442
443 /* Get our hostname */
444
445 void SMB_Get_My_Name(char *name, int len)
446
447 {
448 if (gethostname(name, len) < 0) { /* Error getting name */
449
450 strncpy(name, "unknown", len);
451
452 /* Should check the error */
453
454 #ifdef DEBUG
455 fprintf(stderr, "gethostname in SMB_Get_My_Name returned error:");
456 perror("");
457 #endif
458
459 } else {
460 char *address;
461 /* only keep the portion up to the first "." */
462 if (NULL != (address = strchr(name, '.'))) {
463 *address = '\0'; /* truncate at first '.' */
464 }
465 }
466 }
467
468 /* Send a TCON to the remote server ... */
469
470 SMB_Tree_Handle SMB_TreeConnect(SMB_Handle_Type Con_Handle,
471 SMB_Tree_Handle Tree_Handle,
472 const char *path,
473 const char *password,
474 const char *device)
475
476 {
477 struct RFCNB_Pkt *pkt;
478 int param_len, pkt_len;
479 char *p;
480 SMB_Tree_Handle tree;
481
482 /* Figure out how much space is needed for path, password, dev ... */
483
484 if ((path == NULL) | (password == NULL) | (device == NULL)) {
485
486 #ifdef DEBUG
487 fprintf(stderr, "Bad parameter passed to SMB_TreeConnect\n");
488 #endif
489
490 SMBlib_errno = SMBlibE_BadParam;
491 return(NULL);
492
493 }
494
495 /* The + 2 is because of the \0 and the marker ... */
496
497 param_len = strlen(path) + 2 + strlen(password) + 2 + strlen(device) + 2;
498
499 /* The -1 accounts for the one byte smb_buf we have because some systems */
500 /* don't like char msg_buf[] */
501
502 pkt_len = SMB_tcon_len + param_len;
503
504 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
505
506 if (pkt == NULL) {
507
508 SMBlib_errno = SMBlibE_NoSpace;
509 return(NULL); /* Should handle the error */
510
511 }
512
513 /* Now allocate a tree for this to go into ... */
514
515 if (Tree_Handle == NULL) {
516
517 tree = (SMB_Tree_Handle)malloc(sizeof(struct SMB_Tree_Structure));
518
519 if (tree == NULL) {
520
521 RFCNB_Free_Pkt(pkt);
522 SMBlib_errno = SMBlibE_NoSpace;
523 return(NULL);
524
525 }
526 } else {
527
528 tree = Tree_Handle;
529
530 }
531
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));
536
537 /* Now plug in the values ... */
538
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;
547
548 SSVAL(SMB_Hdr(pkt), SMB_tcon_bcc_offset, param_len);
549
550 /* Now copy the param strings in with the right stuff */
551
552 p = (char *)(SMB_Hdr(pkt) + SMB_tcon_buf_offset);
553 *p = SMBasciiID;
554 strcpy(p + 1, path);
555 p = p + strlen(path) + 2;
556 *p = SMBasciiID;
557 strcpy(p + 1, password);
558 p = p + strlen(password) + 2;
559 *p = SMBasciiID;
560 strcpy(p + 1, device);
561
562 /* Now send the packet and sit back ... */
563
564 if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
565
566 #ifdef DEBUG
567 fprintf(stderr, "Error sending TCon request\n");
568 #endif
569
570 if (Tree_Handle == NULL)
571 free(tree);
572 RFCNB_Free_Pkt(pkt);
573 SMBlib_errno = -SMBlibE_SendFailed;
574 return(NULL);
575
576 }
577
578 /* Now get the response ... */
579
580 if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) {
581
582 #ifdef DEBUG
583 fprintf(stderr, "Error receiving response to TCon\n");
584 #endif
585
586 if (Tree_Handle == NULL)
587 free(tree);
588 RFCNB_Free_Pkt(pkt);
589 SMBlib_errno = -SMBlibE_RecvFailed;
590 return(NULL);
591
592 }
593
594 /* Check out the response type ... */
595
596 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
597
598 #ifdef DEBUG
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));
602 #endif
603
604 if (Tree_Handle == NULL)
605 free(tree);
606 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
607 RFCNB_Free_Pkt(pkt);
608 SMBlib_errno = SMBlibE_Remote;
609 return(NULL);
610
611 }
612
613 tree -> tid = SVAL(SMB_Hdr(pkt), SMB_tconr_tid_offset);
614 tree -> mbs = SVAL(SMB_Hdr(pkt), SMB_tconr_mbs_offset);
615
616 #ifdef DEBUG
617 fprintf(stderr, "TConn succeeded, with TID=%i, Max Xmit=%i\n",
618 tree -> tid, tree -> mbs);
619 #endif
620
621 /* Now link the Tree to the Server Structure ... */
622
623 if (Con_Handle -> first_tree == NULL) {
624
625 Con_Handle -> first_tree = tree;
626 Con_Handle -> last_tree = tree;
627
628 } else {
629
630 Con_Handle -> last_tree -> next = tree;
631 tree -> prev = Con_Handle -> last_tree;
632 Con_Handle -> last_tree = tree;
633
634 }
635
636 RFCNB_Free_Pkt(pkt);
637 return(tree);
638
639 }
640
641 int SMB_TreeDisconnect(SMB_Tree_Handle Tree_Handle, BOOL discard)
642
643 {
644 struct RFCNB_Pkt *pkt;
645 int pkt_len;
646
647 pkt_len = SMB_tdis_len;
648
649 pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len);
650
651 if (pkt == NULL) {
652
653 SMBlib_errno = SMBlibE_NoSpace;
654 return(SMBlibE_BAD); /* Should handle the error */
655
656 }
657
658 /* Now plug in the values ... */
659
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;
667
668 SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, Tree_Handle -> tid);
669 SSVAL(SMB_Hdr(pkt), SMB_tcon_bcc_offset, 0);
670
671 /* Now send the packet and sit back ... */
672
673 if (RFCNB_Send(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) {
674
675 #ifdef DEBUG
676 fprintf(stderr, "Error sending TDis request\n");
677 #endif
678
679 RFCNB_Free_Pkt(pkt);
680 SMBlib_errno = -SMBlibE_SendFailed;
681 return(SMBlibE_BAD);
682
683 }
684
685 /* Now get the response ... */
686
687 if (RFCNB_Recv(Tree_Handle -> con -> Trans_Connect, pkt, pkt_len) < 0) {
688
689 #ifdef DEBUG
690 fprintf(stderr, "Error receiving response to TCon\n");
691 #endif
692
693 RFCNB_Free_Pkt(pkt);
694 SMBlib_errno = -SMBlibE_RecvFailed;
695 return(SMBlibE_BAD);
696
697 }
698
699 /* Check out the response type ... */
700
701 if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */
702
703 #ifdef DEBUG
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));
707 #endif
708
709 SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
710 RFCNB_Free_Pkt(pkt);
711 SMBlib_errno = SMBlibE_Remote;
712 return(SMBlibE_BAD);
713
714 }
715
716 Tree_Handle -> tid = 0xFFFF; /* Invalid TID */
717 Tree_Handle -> mbs = 0; /* Invalid */
718
719 #ifdef DEBUG
720
721 fprintf(stderr, "Tree disconnect successful ...\n");
722
723 #endif
724
725 /* What about the tree handle ? */
726
727 if (discard == TRUE) { /* Unlink it and free it ... */
728
729 if (Tree_Handle -> next == NULL)
730 Tree_Handle -> con -> first_tree = Tree_Handle -> prev;
731 else
732 Tree_Handle -> next -> prev = Tree_Handle -> prev;
733
734 if (Tree_Handle -> prev == NULL)
735 Tree_Handle -> con -> last_tree = Tree_Handle -> next;
736 else
737 Tree_Handle -> prev -> next = Tree_Handle -> next;
738
739 }
740
741 RFCNB_Free_Pkt(pkt);
742 return(0);
743
744 }
745
746 /* Pick up the last LMBlib error ... */
747
748 int SMB_Get_Last_Error()
749
750 {
751
752 return(SMBlib_errno);
753
754 }
755
756 /* Pick up the last error returned in an SMB packet */
757 /* We will need macros to extract error class and error code */
758
759 int SMB_Get_Last_SMB_Err()
760
761 {
762
763 return(SMBlib_SMB_Error);
764
765 }
766
767 /* Pick up the error message associated with an error from SMBlib */
768
769 /* Keep this table in sync with the message codes in smblib-common.h */
770
771 static const char *SMBlib_Error_Messages[] = {
772
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.",
788 NULL
789 };
790
791 void SMB_Get_Error_Msg(int msg, char *msgbuf, int len)
792
793 {
794
795 if (msg >= 0) {
796
797 strncpy(msgbuf,
798 SMBlib_Error_Messages[msg>SMBlibE_NoSuchMsg?SMBlibE_NoSuchMsg:msg],
799 len - 1);
800 msgbuf[len - 1] = 0; /* Make sure it is a string */
801 } else { /* Add the lower layer message ... */
802
803 char prot_msg[1024];
804
805 msg = -msg; /* Make it positive */
806
807 strncpy(msgbuf,
808 SMBlib_Error_Messages[msg>SMBlibE_NoSuchMsg?SMBlibE_NoSuchMsg:msg],
809 len - 1);
810
811 msgbuf[len - 1] = 0; /* make sure it is a string */
812
813 if (strlen(msgbuf) < len) { /* If there is space, put rest in */
814
815 strncat(msgbuf, "\n\t", len - strlen(msgbuf));
816
817 RFCNB_Get_Error(prot_msg, sizeof(prot_msg) - 1);
818
819 strncat(msgbuf, prot_msg, len - strlen(msgbuf));
820
821 }
822 }
823
824 }