xref: /plan9/sys/src/cmd/aquarela/aquarela.c (revision 94aa1c4c0955b2b4e990c9f4679be8e9f67a469b)
1 #include "headers.h"
2 #include <pool.h>
3 
4 static void
disconnecttree(void * magic,void * arg)5 disconnecttree(void *magic, void *arg)
6 {
7 	smbtreedisconnect((SmbSession *)magic, (SmbTree *)arg);
8 }
9 
10 static void
closesearch(void * magic,void * arg)11 closesearch(void *magic, void *arg)
12 {
13 	smbsearchclose((SmbSession *)magic, (SmbSearch *)arg);
14 }
15 
16 static void
smbsessionfree(SmbSession * s)17 smbsessionfree(SmbSession *s)
18 {
19 	if (s) {
20 		smbidmapfree(&s->tidmap, disconnecttree, s);
21 		smbidmapfree(&s->sidmap, closesearch, s);
22 		smbbufferfree(&s->response);
23 		free(s->client.accountname);
24 		free(s->client.primarydomain);
25 		free(s->client.nativeos);
26 		free(s->client.nativelanman);
27 		free(s->transaction.in.parameters);
28 		free(s->transaction.in.data);
29 		free(s->transaction.in.setup);
30 		free(s->transaction.in.name);
31 		smbbufferfree(&s->transaction.out.parameters);
32 		smbbufferfree(&s->transaction.out.data);
33 		auth_freechal(s->cs);
34 		free(s);
35 	}
36 }
37 
38 int
smbsessionwrite(SmbSession * smbs,void * p,long n)39 smbsessionwrite(SmbSession *smbs, void *p, long n)
40 {
41 	SmbHeader h;
42 	SmbOpTableEntry *ote;
43 	uchar *pdata;
44 	int rv;
45 	SmbBuffer *b = nil;
46 	ushort bytecount;
47 	SmbProcessResult pr;
48 
49 	if (smbs->response == nil)
50 		smbs->response = smbbuffernew(576);
51 	else
52 		smbresponsereset(smbs);
53 	smbs->errclass = SUCCESS;
54 	smbs->error = SUCCESS;
55 //	print("received %ld bytes\n", n);
56 	if (n <= 0)
57 		goto closedown;
58 	b = smbbufferinit(p, p, n);
59 	if (!smbbuffergetheader(b, &h, &pdata, &bytecount)) {
60 		smblogprint(-1, "smb: invalid header\n");
61 		goto closedown;
62 	}
63 smbloglock();
64 smblogprint(h.command, "received:\n");
65 smblogdata(h.command, smblogprint, p, n, 0x1000);
66 smblogunlock();
67 	ote = smboptable + h.command;
68 	if (ote->name == nil) {
69 		smblogprint(-1, "smb: illegal opcode 0x%.2ux\n", h.command);
70 		goto unimp;
71 	}
72 	if (ote->process == nil) {
73 		smblogprint(-1, "smb: opcode %s unimplemented\n", ote->name);
74 		goto unimp;
75 	}
76 	if (smbs->nextcommand != SMB_COM_NO_ANDX_COMMAND
77 		&& smbs->nextcommand != h.command) {
78 		smblogprint(-1, "smb: wrong command - expected %.2ux\n", smbs->nextcommand);
79 		goto misc;
80 	}
81 	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
82 	switch (h.command) {
83 	case SMB_COM_NEGOTIATE:
84 	case SMB_COM_SESSION_SETUP_ANDX:
85 	case SMB_COM_TREE_CONNECT_ANDX:
86 	case SMB_COM_ECHO:
87 		break;
88 	default:
89 		if (smbs->state != SmbSessionEstablished) {
90 			smblogprint(-1, "aquarela: command %.2ux unexpected\n", h.command);
91 			goto unimp;
92 		}
93 	}
94 	pr = (*ote->process)(smbs, &h, pdata, b);
95 	switch (pr) {
96 	case SmbProcessResultUnimp:
97 	unimp:
98 		smbseterror(smbs, ERRDOS, ERRunsup);
99 		pr = SmbProcessResultError;
100 		break;
101 	case SmbProcessResultFormat:
102 		smbseterror(smbs, ERRSRV, ERRsmbcmd);
103 		pr = SmbProcessResultError;
104 		break;
105 	case SmbProcessResultMisc:
106 	misc:
107 		smbseterror(smbs, ERRSRV, ERRerror);
108 		pr = SmbProcessResultError;
109 		break;
110 	}
111 	if (pr == SmbProcessResultError) {
112 		smblogprint(h.command, "reply: error %d/%d\n", smbs->errclass, smbs->error);
113 		if (!smbresponseputerror(smbs, &h, smbs->errclass, smbs->error))
114 			pr = SmbProcessResultDie;
115 		else
116 			pr = SmbProcessResultReply;
117 	}
118 	else
119 		smblogprint(h.command, "reply: ok\n");
120 	if (pr == SmbProcessResultReply)
121 		rv = smbresponsesend(smbs) == SmbProcessResultOk ? 0 : -1;
122 	else if (pr == SmbProcessResultDie)
123 		rv = -1;
124 	else
125 		rv = 0;
126 	goto done;
127 closedown:
128 	rv = -1;
129 done:
130 	if (rv < 0) {
131 		smblogprintif(smbglobals.log.sessions, "shutting down\n");
132 		smbsessionfree(smbs);
133 	}
134 	smbbufferfree(&b);
135 	if (smbglobals.log.poolparanoia)
136 		poolcheck(mainmem);
137 	return rv;
138 }
139 
140 static int
nbwrite(NbSession * nbss,void * p,long n)141 nbwrite(NbSession *nbss, void *p, long n)
142 {
143 	return smbsessionwrite((SmbSession *)nbss->magic, p, n);
144 }
145 
146 static int
cifswrite(SmbCifsSession * cifs,void * p,long n)147 cifswrite(SmbCifsSession *cifs, void *p, long n)
148 {
149 	return smbsessionwrite((SmbSession *)cifs->magic, p, n);
150 }
151 
152 int
nbssaccept(void *,NbSession * s,NBSSWRITEFN ** writep)153 nbssaccept(void *, NbSession *s, NBSSWRITEFN **writep)
154 {
155 	SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
156 	smbs->nbss = s;
157 	s->magic = smbs;
158 	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
159 	*writep = nbwrite;
160 	smblogprintif(smbglobals.log.sessions, "netbios session started\n");
161 	return 1;
162 }
163 
164 int
cifsaccept(SmbCifsSession * s,SMBCIFSWRITEFN ** writep)165 cifsaccept(SmbCifsSession *s, SMBCIFSWRITEFN **writep)
166 {
167 	SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
168 	smbs->cifss = s;
169 	s->magic = smbs;
170 	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
171 	*writep = cifswrite;
172 	smblogprintif(smbglobals.log.sessions, "cifs session started\n");
173 	return 1;
174 }
175 
176 void
usage(void)177 usage(void)
178 {
179 	fprint(2, "usage: %s [-np] [-d debug] [-u N] [-w workgroup]\n", argv0);
180 	threadexitsall("usage");
181 }
182 
183 static void
logset(char * cmd)184 logset(char *cmd)
185 {
186 	int x;
187 	if (strcmp(cmd, "allcmds") == 0) {
188 		for (x = 0; x < 256; x++)
189 			smboptable[x].debug = 1;
190 		for (x = 0; x < smbtrans2optablesize; x++)
191 			smbtrans2optable[x].debug = 1;
192 		return;
193 	}
194 	if (strcmp(cmd, "tids") == 0) {
195 		smbglobals.log.tids = 1;
196 		return;
197 	}
198 	if (strcmp(cmd, "sids") == 0) {
199 		smbglobals.log.sids = 1;
200 		return;
201 	}
202 	if (strcmp(cmd, "fids") == 0) {
203 		smbglobals.log.fids = 1;
204 		return;
205 	}
206 	if (strcmp(cmd, "rap2") == 0) {
207 		smbglobals.log.rap2 = 1;
208 		return;
209 	}
210 	else if (strcmp(cmd, "find") == 0) {
211 		smbglobals.log.find = 1;
212 		return;
213 	}
214 	if (strcmp(cmd, "query") == 0) {
215 		smbglobals.log.query = 1;
216 		return;
217 	}
218 	if (strcmp(cmd, "sharedfiles") == 0) {
219 		smbglobals.log.sharedfiles = 1;
220 		return;
221 	}
222 	if (strcmp(cmd, "poolparanoia") == 0) {
223 		mainmem->flags |= POOL_PARANOIA;
224 		smbglobals.log.poolparanoia = 1;
225 		return;
226 	}
227 	if (strcmp(cmd, "sessions") == 0) {
228 		smbglobals.log.sessions = 1;
229 		return;
230 	}
231 	if (strcmp(cmd, "rep") == 0) {
232 		smbglobals.log.rep = 1;
233 		return;
234 	}
235 	if (strcmp(cmd, "locks") == 0) {
236 		smbglobals.log.locks = 1;
237 		return;
238 	}
239 
240 	for (x = 0; x < 256; x++)
241 		if (smboptable[x].name && strcmp(smboptable[x].name, cmd) == 0) {
242 			smboptable[x].debug = 1;
243 			return;
244 		}
245 	for (x = 0; x < smbtrans2optablesize; x++)
246 		if (smbtrans2optable[x].name && strcmp(smbtrans2optable[x].name, cmd) == 0) {
247 			smbtrans2optable[x].debug = 1;
248 			return;
249 		}
250 	if (strlen(cmd) == 4 && cmd[0] == '0' && cmd[1] == 'x') {
251 		int c;
252 		c = strtoul(cmd + 2, 0, 16);
253 		if (c >= 0 && c <= 255) {
254 			smboptable[c].debug = 1;
255 			return;
256 		}
257 	}
258 	print("debugging command %s not recognised\n", cmd);
259 }
260 
261 
262 void
threadmain(int argc,char ** argv)263 threadmain(int argc, char **argv)
264 {
265 	NbName from, to;
266 	char *e = nil;
267 	int netbios = 0;
268 	ARGBEGIN {
269 	case 'u':
270 		smbglobals.unicode = strtol(ARGF(), 0, 0) != 0;
271 		break;
272 	case 'p':
273 		smbglobals.log.print = 1;
274 		break;
275 	case 'd':
276 		logset(ARGF());
277 		break;
278 	case 'w':
279 		smbglobals.primarydomain = ARGF();
280 		break;
281 	case 'n':
282 		netbios = 1;
283 		break;
284 	default:
285 		usage();
286 	} ARGEND;
287 	smbglobalsguess(0);
288 	smblistencifs(cifsaccept);
289 	if (netbios) {
290 		nbinit();
291 		nbmknamefromstring(from, "*");
292 		nbmknamefromstring(to, "*smbserver\\x20");
293 		nbsslisten(to, from, nbssaccept, nil);
294 		nbmknamefromstringandtype(to, smbglobals.serverinfo.name, 0x20);
295 		nbsslisten(to, from, nbssaccept, nil);
296 	}
297 	smblogprint(-1, "Aquarela %d.%d running\n", smbglobals.serverinfo.vmaj, smbglobals.serverinfo.vmin);
298 	for (;;) {
299 		if (netbios&& !smbbrowsesendhostannouncement(smbglobals.serverinfo.name, 60 * 1000,
300 			SV_TYPE_SERVER,
301 			smbglobals.serverinfo.remark, &e)) {
302 			smblogprint(-1, "hostannounce failed: %s\n", e);
303 		}
304 		if (sleep(60 * 1000) < 0)
305 			break;
306 	}
307 }
308 
309