xref: /plan9/sys/src/cmd/aquarela/smbconnect.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include "headers.h"
2*8ccd4a63SDavid du Colombier 
3*8ccd4a63SDavid du Colombier SmbClient *
smbconnect(char * to,char * share,char ** errmsgp)4*8ccd4a63SDavid du Colombier smbconnect(char *to, char *share, char **errmsgp)
5*8ccd4a63SDavid du Colombier {
6*8ccd4a63SDavid du Colombier 	NbSession *nbs;
7*8ccd4a63SDavid du Colombier 	SmbBuffer *b;
8*8ccd4a63SDavid du Colombier 	SmbHeader h, rh;
9*8ccd4a63SDavid du Colombier 	long n;
10*8ccd4a63SDavid du Colombier 	ushort bytecountfixupoffset;
11*8ccd4a63SDavid du Colombier 	ushort andxfixupoffset;
12*8ccd4a63SDavid du Colombier 	uchar *pdata;
13*8ccd4a63SDavid du Colombier 	SmbPeerInfo peerinfo;
14*8ccd4a63SDavid du Colombier 	ushort index;
15*8ccd4a63SDavid du Colombier 	vlong utcintenthsofaus;
16*8ccd4a63SDavid du Colombier 	ulong secssince1970;
17*8ccd4a63SDavid du Colombier 	ushort bytecount;
18*8ccd4a63SDavid du Colombier 	int x;
19*8ccd4a63SDavid du Colombier 	MSchapreply mschapreply;
20*8ccd4a63SDavid du Colombier 	NbName nbto;
21*8ccd4a63SDavid du Colombier 	SmbClient *c;
22*8ccd4a63SDavid du Colombier 	char namebuf[100];
23*8ccd4a63SDavid du Colombier 	ushort ipctid, sharetid;
24*8ccd4a63SDavid du Colombier 
25*8ccd4a63SDavid du Colombier 	nbmknamefromstringandtype(nbto, to, 0x20);
26*8ccd4a63SDavid du Colombier 
27*8ccd4a63SDavid du Colombier 	peerinfo.encryptionkey = nil;
28*8ccd4a63SDavid du Colombier 	peerinfo.oemdomainname = nil;
29*8ccd4a63SDavid du Colombier 	assert(smbglobals.nbname[0] != 0);
30*8ccd4a63SDavid du Colombier 	nbs = nbssconnect(nbto, smbglobals.nbname);
31*8ccd4a63SDavid du Colombier 	if (nbs == nil)
32*8ccd4a63SDavid du Colombier 		return nil;
33*8ccd4a63SDavid du Colombier print("netbios session established\n");
34*8ccd4a63SDavid du Colombier 	b = smbbuffernew(65535);
35*8ccd4a63SDavid du Colombier 	memset(&h, 0, sizeof(h));
36*8ccd4a63SDavid du Colombier 	h.command = SMB_COM_NEGOTIATE;
37*8ccd4a63SDavid du Colombier 	h.flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES | SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_UNICODE;
38*8ccd4a63SDavid du Colombier 	h.wordcount = 0;
39*8ccd4a63SDavid du Colombier 	h.pid = 42;
40*8ccd4a63SDavid du Colombier 	smbbufferputheader(b, &h, &peerinfo);
41*8ccd4a63SDavid du Colombier 	bytecountfixupoffset = smbbufferwriteoffset(b);
42*8ccd4a63SDavid du Colombier 	smbbufferputbytes(b, nil, 2);
43*8ccd4a63SDavid du Colombier 	smbbufferputb(b, 2);
44*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, nil, SMB_STRING_ASCII, "NT LM 0.12");
45*8ccd4a63SDavid du Colombier 	smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
46*8ccd4a63SDavid du Colombier 	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
47*8ccd4a63SDavid du Colombier 	nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
48*8ccd4a63SDavid du Colombier 	/*
49*8ccd4a63SDavid du Colombier 	 * now receive a reply
50*8ccd4a63SDavid du Colombier 	 */
51*8ccd4a63SDavid du Colombier 	smbbufferreset(b);
52*8ccd4a63SDavid du Colombier 	n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
53*8ccd4a63SDavid du Colombier 	if (n < 0) {
54*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "smbconnect: read error: %r");
55*8ccd4a63SDavid du Colombier 		goto fail;
56*8ccd4a63SDavid du Colombier 	}
57*8ccd4a63SDavid du Colombier 	smbbuffersetreadlen(b, n);
58*8ccd4a63SDavid du Colombier 	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
59*8ccd4a63SDavid du Colombier 	if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp))
60*8ccd4a63SDavid du Colombier 		goto fail;
61*8ccd4a63SDavid du Colombier 	if (!smbsuccess(&rh, errmsgp))
62*8ccd4a63SDavid du Colombier 		goto fail;
63*8ccd4a63SDavid du Colombier 	if (rh.wordcount == 0) {
64*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "no parameters in negotiate response");
65*8ccd4a63SDavid du Colombier 		goto fail;
66*8ccd4a63SDavid du Colombier 	}
67*8ccd4a63SDavid du Colombier 	index = smbnhgets(pdata); pdata += 2;
68*8ccd4a63SDavid du Colombier 	if (index != 0) {
69*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "no agreement on protocol");
70*8ccd4a63SDavid du Colombier 		goto fail;
71*8ccd4a63SDavid du Colombier 	}
72*8ccd4a63SDavid du Colombier 	if (rh.wordcount != 17) {
73*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "wrong number of parameters for negotiate response");
74*8ccd4a63SDavid du Colombier 		goto fail;
75*8ccd4a63SDavid du Colombier 	}
76*8ccd4a63SDavid du Colombier 	peerinfo.securitymode = *pdata++;
77*8ccd4a63SDavid du Colombier 	peerinfo.maxmpxcount = smbnhgets(pdata); pdata += 2;
78*8ccd4a63SDavid du Colombier 	peerinfo.maxnumbervcs = smbnhgets(pdata); pdata += 2;
79*8ccd4a63SDavid du Colombier 	peerinfo.maxbuffersize = smbnhgetl(pdata); pdata += 4;
80*8ccd4a63SDavid du Colombier 	peerinfo.maxrawsize = smbnhgetl(pdata); pdata += 4;
81*8ccd4a63SDavid du Colombier 	peerinfo.sessionkey = smbnhgets(pdata); pdata += 4;
82*8ccd4a63SDavid du Colombier 	peerinfo.capabilities = smbnhgets(pdata); pdata += 4;
83*8ccd4a63SDavid du Colombier 	utcintenthsofaus = smbnhgetv(pdata); pdata += 8;
84*8ccd4a63SDavid du Colombier 	secssince1970 = utcintenthsofaus / 10000000 - 11644473600LL;
85*8ccd4a63SDavid du Colombier 	peerinfo.utc =  (vlong)secssince1970 * (vlong)1000000000 + (utcintenthsofaus % 10000000) * 100;
86*8ccd4a63SDavid du Colombier 	peerinfo.tzoff = -smbnhgets(pdata) * 60; pdata += 2;
87*8ccd4a63SDavid du Colombier 	peerinfo.encryptionkeylength = *pdata++;
88*8ccd4a63SDavid du Colombier 	print("securitymode: 0x%.2ux\n", peerinfo.securitymode);
89*8ccd4a63SDavid du Colombier 	print("maxmpxcount: 0x%.4ux\n", peerinfo.maxmpxcount);
90*8ccd4a63SDavid du Colombier 	print("maxnumbervcs: 0x%.4ux\n", peerinfo.maxnumbervcs);
91*8ccd4a63SDavid du Colombier 	print("maxbuffersize: 0x%.8lux\n", peerinfo.maxbuffersize);
92*8ccd4a63SDavid du Colombier 	print("maxrawsize: 0x%.8lux\n", peerinfo.maxrawsize);
93*8ccd4a63SDavid du Colombier 	print("sessionkey: 0x%.8lux\n", peerinfo.sessionkey);
94*8ccd4a63SDavid du Colombier 	print("capabilities: 0x%.8lux\n", peerinfo.capabilities);
95*8ccd4a63SDavid du Colombier 	print("utc: %s(and %lld μs)\n", asctime(gmtime(peerinfo.utc / 1000000000)), peerinfo.utc % 1000000000);
96*8ccd4a63SDavid du Colombier 	print("tzoff: %d\n", peerinfo.tzoff);
97*8ccd4a63SDavid du Colombier 	print("encryptionkeylength: %d\n", peerinfo.encryptionkeylength);
98*8ccd4a63SDavid du Colombier 	smberealloc(&peerinfo.encryptionkey, peerinfo.encryptionkeylength);
99*8ccd4a63SDavid du Colombier 	if (!smbbuffergetbytes(b, peerinfo.encryptionkey, peerinfo.encryptionkeylength)) {
100*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "not enough data for encryption key");
101*8ccd4a63SDavid du Colombier 		goto fail;
102*8ccd4a63SDavid du Colombier 	}
103*8ccd4a63SDavid du Colombier 	print("encryptionkey: ");
104*8ccd4a63SDavid du Colombier 	for (x = 0; x < peerinfo.encryptionkeylength; x++)
105*8ccd4a63SDavid du Colombier 		print("%.2ux", peerinfo.encryptionkey[x]);
106*8ccd4a63SDavid du Colombier 	print("\n");
107*8ccd4a63SDavid du Colombier 	if (!smbbuffergetucs2(b, 0, &peerinfo.oemdomainname)) {
108*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "not enough data for oemdomainname");
109*8ccd4a63SDavid du Colombier 		goto fail;
110*8ccd4a63SDavid du Colombier 	}
111*8ccd4a63SDavid du Colombier 	print("oemdomainname: %s\n", peerinfo.oemdomainname);
112*8ccd4a63SDavid du Colombier 	if (peerinfo.capabilities & CAP_EXTENDED_SECURITY) {
113*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "server wants extended security");
114*8ccd4a63SDavid du Colombier 		goto fail;
115*8ccd4a63SDavid du Colombier 	}
116*8ccd4a63SDavid du Colombier 	/*
117*8ccd4a63SDavid du Colombier 	 * ok - now send SMB_COM_SESSION_SETUP_ANDX
118*8ccd4a63SDavid du Colombier 	 * fix the flags to reflect what the peer can do
119*8ccd4a63SDavid du Colombier 	 */
120*8ccd4a63SDavid du Colombier 	smbbufferreset(b);
121*8ccd4a63SDavid du Colombier 	h.command = SMB_COM_SESSION_SETUP_ANDX;
122*8ccd4a63SDavid du Colombier 	h.wordcount = 13;
123*8ccd4a63SDavid du Colombier 	h.flags2 &= ~SMB_FLAGS2_UNICODE;
124*8ccd4a63SDavid du Colombier 	if (smbsendunicode(&peerinfo))
125*8ccd4a63SDavid du Colombier 		h.flags2 |= SMB_FLAGS2_UNICODE;
126*8ccd4a63SDavid du Colombier 	smbbufferputheader(b, &h, &peerinfo);
127*8ccd4a63SDavid du Colombier 	smbbufferputb(b, SMB_COM_TREE_CONNECT_ANDX);
128*8ccd4a63SDavid du Colombier 	smbbufferputb(b, 0);
129*8ccd4a63SDavid du Colombier 	andxfixupoffset = smbbufferwriteoffset(b);
130*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
131*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0xffff);
132*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 1);
133*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
134*8ccd4a63SDavid du Colombier 	smbbufferputl(b, peerinfo.sessionkey);
135*8ccd4a63SDavid du Colombier 	smbbufferputs(b, sizeof(mschapreply.LMresp));
136*8ccd4a63SDavid du Colombier 	smbbufferputs(b, sizeof(mschapreply.NTresp));
137*8ccd4a63SDavid du Colombier 	smbbufferputl(b, 0);
138*8ccd4a63SDavid du Colombier 	smbbufferputl(b, CAP_UNICODE | CAP_LARGE_FILES);
139*8ccd4a63SDavid du Colombier 	bytecountfixupoffset = smbbufferwriteoffset(b);
140*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
141*8ccd4a63SDavid du Colombier 	if (auth_respond(peerinfo.encryptionkey, peerinfo.encryptionkeylength,
142*8ccd4a63SDavid du Colombier 		nil, 0,
143*8ccd4a63SDavid du Colombier 		&mschapreply, sizeof(mschapreply), auth_getkey,
144*8ccd4a63SDavid du Colombier 		"proto=mschap role=client server=%s", "cher") != sizeof(mschapreply)) {
145*8ccd4a63SDavid du Colombier 		print("auth_respond failed: %r\n");
146*8ccd4a63SDavid du Colombier 		goto fail;
147*8ccd4a63SDavid du Colombier 	}
148*8ccd4a63SDavid du Colombier 	smbbufferputbytes(b, &mschapreply, sizeof(mschapreply));
149*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, &peerinfo, 0, smbglobals.accountname);
150*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, &peerinfo, 0, smbglobals.primarydomain);
151*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, &peerinfo, 0, smbglobals.nativeos);
152*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, &peerinfo, 0, "");
153*8ccd4a63SDavid du Colombier 	smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
154*8ccd4a63SDavid du Colombier 	smbbufferalignl2(b, 2);
155*8ccd4a63SDavid du Colombier 	smbbufferoffsetputs(b, andxfixupoffset, smbbufferwriteoffset(b));
156*8ccd4a63SDavid du Colombier 	smbbufferputb(b, 4);
157*8ccd4a63SDavid du Colombier 	smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND);
158*8ccd4a63SDavid du Colombier 	smbbufferputb(b, 0);
159*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
160*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
161*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
162*8ccd4a63SDavid du Colombier 	bytecountfixupoffset = smbbufferwriteoffset(b);
163*8ccd4a63SDavid du Colombier 	smbbufferputs(b, 0);
164*8ccd4a63SDavid du Colombier 	strcpy(namebuf, "\\\\");
165*8ccd4a63SDavid du Colombier 	strcat(namebuf, to);
166*8ccd4a63SDavid du Colombier 	strcat(namebuf, "\\IPC$");
167*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf);
168*8ccd4a63SDavid du Colombier 	smbbufferputstring(b, nil, SMB_STRING_ASCII, "?????");
169*8ccd4a63SDavid du Colombier 	smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
170*8ccd4a63SDavid du Colombier 	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
171*8ccd4a63SDavid du Colombier 	nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
172*8ccd4a63SDavid du Colombier 	smbbufferreset(b);
173*8ccd4a63SDavid du Colombier 	n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
174*8ccd4a63SDavid du Colombier 	if (n < 0) {
175*8ccd4a63SDavid du Colombier 		smbstringprint(errmsgp, "read error: %r");
176*8ccd4a63SDavid du Colombier 		goto fail;
177*8ccd4a63SDavid du Colombier 	}
178*8ccd4a63SDavid du Colombier 	smbbuffersetreadlen(b, n);
179*8ccd4a63SDavid du Colombier 	nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
180*8ccd4a63SDavid du Colombier 	if (!smbbuffergetandcheckheader(b, &rh, h.command, 1, &pdata, &bytecount, errmsgp))
181*8ccd4a63SDavid du Colombier 		goto fail;
182*8ccd4a63SDavid du Colombier 	if (!smbsuccess(&rh, errmsgp))
183*8ccd4a63SDavid du Colombier 		goto fail;
184*8ccd4a63SDavid du Colombier 	h.uid = rh.uid;
185*8ccd4a63SDavid du Colombier 	ipctid = rh.tid;
186*8ccd4a63SDavid du Colombier 	/*
187*8ccd4a63SDavid du Colombier 	 * now do another TREE_CONNECT if needed
188*8ccd4a63SDavid du Colombier 	 */
189*8ccd4a63SDavid du Colombier 	if (share) {
190*8ccd4a63SDavid du Colombier 		smbbufferreset(b);
191*8ccd4a63SDavid du Colombier 		h.command = SMB_COM_TREE_CONNECT_ANDX;
192*8ccd4a63SDavid du Colombier 		h.wordcount = 4;
193*8ccd4a63SDavid du Colombier 		h.tid = 0;
194*8ccd4a63SDavid du Colombier 		smbbufferputheader(b, &h, &peerinfo);
195*8ccd4a63SDavid du Colombier 		smbbufferputb(b, SMB_COM_NO_ANDX_COMMAND);
196*8ccd4a63SDavid du Colombier 		smbbufferputb(b, 0);
197*8ccd4a63SDavid du Colombier 		smbbufferputs(b, 0);
198*8ccd4a63SDavid du Colombier 		smbbufferputs(b, 0);
199*8ccd4a63SDavid du Colombier 		smbbufferputs(b, 0);
200*8ccd4a63SDavid du Colombier 		bytecountfixupoffset = smbbufferwriteoffset(b);
201*8ccd4a63SDavid du Colombier 		smbbufferputs(b, 0);
202*8ccd4a63SDavid du Colombier 		strcpy(namebuf, "\\\\");
203*8ccd4a63SDavid du Colombier 		strcat(namebuf, to);
204*8ccd4a63SDavid du Colombier 		strcat(namebuf, "\\");
205*8ccd4a63SDavid du Colombier 		strcat(namebuf, share);
206*8ccd4a63SDavid du Colombier 		smbbufferputstring(b, &peerinfo, SMB_STRING_UPCASE, namebuf);
207*8ccd4a63SDavid du Colombier 		smbbufferputstring(b, nil, SMB_STRING_ASCII, "A:");
208*8ccd4a63SDavid du Colombier 		smbbufferoffsetputs(b, bytecountfixupoffset, smbbufferwriteoffset(b) - bytecountfixupoffset - 2);
209*8ccd4a63SDavid du Colombier 		nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
210*8ccd4a63SDavid du Colombier 		nbsswrite(nbs, smbbufferreadpointer(b), smbbufferwriteoffset(b));
211*8ccd4a63SDavid du Colombier 		smbbufferreset(b);
212*8ccd4a63SDavid du Colombier 		n = nbssread(nbs, smbbufferwritepointer(b), smbbufferwritespace(b));
213*8ccd4a63SDavid du Colombier 		if (n < 0) {
214*8ccd4a63SDavid du Colombier 			smbstringprint(errmsgp, "read error: %r");
215*8ccd4a63SDavid du Colombier 			goto fail;
216*8ccd4a63SDavid du Colombier 		}
217*8ccd4a63SDavid du Colombier 		smbbuffersetreadlen(b, n);
218*8ccd4a63SDavid du Colombier 		nbdumpdata(smbbufferreadpointer(b), smbbufferwriteoffset(b));
219*8ccd4a63SDavid du Colombier 		if (!smbbuffergetandcheckheader(b, &rh, h.command, 3, &pdata, &bytecount, errmsgp))
220*8ccd4a63SDavid du Colombier 			goto fail;
221*8ccd4a63SDavid du Colombier 		if (!smbsuccess(&rh, errmsgp))
222*8ccd4a63SDavid du Colombier 			goto fail;
223*8ccd4a63SDavid du Colombier 		sharetid = rh.tid;
224*8ccd4a63SDavid du Colombier 	}
225*8ccd4a63SDavid du Colombier 	else
226*8ccd4a63SDavid du Colombier 		sharetid = -2;
227*8ccd4a63SDavid du Colombier 	c = smbemalloc(sizeof(*c));
228*8ccd4a63SDavid du Colombier 	c->peerinfo = peerinfo;
229*8ccd4a63SDavid du Colombier 	c->ipctid = ipctid;
230*8ccd4a63SDavid du Colombier 	c->sharetid = sharetid;
231*8ccd4a63SDavid du Colombier 	c->b = b;
232*8ccd4a63SDavid du Colombier 	c->protoh = h;
233*8ccd4a63SDavid du Colombier 	c->nbss = nbs;
234*8ccd4a63SDavid du Colombier 	return c;
235*8ccd4a63SDavid du Colombier fail:
236*8ccd4a63SDavid du Colombier 	smbbufferfree(&b);
237*8ccd4a63SDavid du Colombier 	free(peerinfo.encryptionkey);
238*8ccd4a63SDavid du Colombier 	free(peerinfo.oemdomainname);
239*8ccd4a63SDavid du Colombier 	return nil;
240*8ccd4a63SDavid du Colombier }
241*8ccd4a63SDavid du Colombier 
242*8ccd4a63SDavid du Colombier void
smbclientfree(SmbClient * c)243*8ccd4a63SDavid du Colombier smbclientfree(SmbClient *c)
244*8ccd4a63SDavid du Colombier {
245*8ccd4a63SDavid du Colombier 	if (c) {
246*8ccd4a63SDavid du Colombier 		free(c->peerinfo.encryptionkey);
247*8ccd4a63SDavid du Colombier 		free(c->peerinfo.oemdomainname);
248*8ccd4a63SDavid du Colombier 		free(c);
249*8ccd4a63SDavid du Colombier 		smbbufferfree(&c->b);
250*8ccd4a63SDavid du Colombier 	}
251*8ccd4a63SDavid du Colombier }
252*8ccd4a63SDavid du Colombier 
253*8ccd4a63SDavid du Colombier int
smbtransactionclientsend(void * magic,SmbBuffer * ob,char **)254*8ccd4a63SDavid du Colombier smbtransactionclientsend(void *magic, SmbBuffer *ob, char **)
255*8ccd4a63SDavid du Colombier {
256*8ccd4a63SDavid du Colombier 	SmbClient *c = magic;
257*8ccd4a63SDavid du Colombier smblogprint(-1, "sending:\n");
258*8ccd4a63SDavid du Colombier smblogdata(-1, smblogprint, smbbufferreadpointer(ob), smbbufferwriteoffset(ob), 256);
259*8ccd4a63SDavid du Colombier 	return nbsswrite(c->nbss, smbbufferreadpointer(ob), smbbufferwriteoffset(ob)) == 0;
260*8ccd4a63SDavid du Colombier }
261*8ccd4a63SDavid du Colombier 
262*8ccd4a63SDavid du Colombier int
smbtransactionclientreceive(void * magic,SmbBuffer * ib,char **)263*8ccd4a63SDavid du Colombier smbtransactionclientreceive(void *magic, SmbBuffer *ib, char **)
264*8ccd4a63SDavid du Colombier {
265*8ccd4a63SDavid du Colombier 	long n;
266*8ccd4a63SDavid du Colombier 	SmbClient *c = magic;
267*8ccd4a63SDavid du Colombier 	smbbufferreset(ib);
268*8ccd4a63SDavid du Colombier 	n = nbssread(c->nbss, smbbufferwritepointer(ib), smbbufferwritespace(ib));
269*8ccd4a63SDavid du Colombier 	if (n >= 0) {
270*8ccd4a63SDavid du Colombier 		assert(smbbufferputbytes(ib, nil, n));
271*8ccd4a63SDavid du Colombier 		return 1;
272*8ccd4a63SDavid du Colombier 	}
273*8ccd4a63SDavid du Colombier 	return 0;
274*8ccd4a63SDavid du Colombier }
275*8ccd4a63SDavid du Colombier 
276