xref: /plan9/sys/src/cmd/aquarela/aquarela.c (revision 94aa1c4c0955b2b4e990c9f4679be8e9f67a469b)
18ccd4a63SDavid du Colombier #include "headers.h"
28ccd4a63SDavid du Colombier #include <pool.h>
38ccd4a63SDavid du Colombier 
48ccd4a63SDavid du Colombier static void
disconnecttree(void * magic,void * arg)58ccd4a63SDavid du Colombier disconnecttree(void *magic, void *arg)
68ccd4a63SDavid du Colombier {
78ccd4a63SDavid du Colombier 	smbtreedisconnect((SmbSession *)magic, (SmbTree *)arg);
88ccd4a63SDavid du Colombier }
98ccd4a63SDavid du Colombier 
108ccd4a63SDavid du Colombier static void
closesearch(void * magic,void * arg)118ccd4a63SDavid du Colombier closesearch(void *magic, void *arg)
128ccd4a63SDavid du Colombier {
138ccd4a63SDavid du Colombier 	smbsearchclose((SmbSession *)magic, (SmbSearch *)arg);
148ccd4a63SDavid du Colombier }
158ccd4a63SDavid du Colombier 
168ccd4a63SDavid du Colombier static void
smbsessionfree(SmbSession * s)178ccd4a63SDavid du Colombier smbsessionfree(SmbSession *s)
188ccd4a63SDavid du Colombier {
198ccd4a63SDavid du Colombier 	if (s) {
208ccd4a63SDavid du Colombier 		smbidmapfree(&s->tidmap, disconnecttree, s);
218ccd4a63SDavid du Colombier 		smbidmapfree(&s->sidmap, closesearch, s);
228ccd4a63SDavid du Colombier 		smbbufferfree(&s->response);
238ccd4a63SDavid du Colombier 		free(s->client.accountname);
248ccd4a63SDavid du Colombier 		free(s->client.primarydomain);
258ccd4a63SDavid du Colombier 		free(s->client.nativeos);
268ccd4a63SDavid du Colombier 		free(s->client.nativelanman);
278ccd4a63SDavid du Colombier 		free(s->transaction.in.parameters);
288ccd4a63SDavid du Colombier 		free(s->transaction.in.data);
298ccd4a63SDavid du Colombier 		free(s->transaction.in.setup);
308ccd4a63SDavid du Colombier 		free(s->transaction.in.name);
318ccd4a63SDavid du Colombier 		smbbufferfree(&s->transaction.out.parameters);
328ccd4a63SDavid du Colombier 		smbbufferfree(&s->transaction.out.data);
338ccd4a63SDavid du Colombier 		auth_freechal(s->cs);
348ccd4a63SDavid du Colombier 		free(s);
358ccd4a63SDavid du Colombier 	}
368ccd4a63SDavid du Colombier }
378ccd4a63SDavid du Colombier 
388ccd4a63SDavid du Colombier int
smbsessionwrite(SmbSession * smbs,void * p,long n)398ccd4a63SDavid du Colombier smbsessionwrite(SmbSession *smbs, void *p, long n)
408ccd4a63SDavid du Colombier {
418ccd4a63SDavid du Colombier 	SmbHeader h;
428ccd4a63SDavid du Colombier 	SmbOpTableEntry *ote;
438ccd4a63SDavid du Colombier 	uchar *pdata;
448ccd4a63SDavid du Colombier 	int rv;
458ccd4a63SDavid du Colombier 	SmbBuffer *b = nil;
468ccd4a63SDavid du Colombier 	ushort bytecount;
478ccd4a63SDavid du Colombier 	SmbProcessResult pr;
488ccd4a63SDavid du Colombier 
498ccd4a63SDavid du Colombier 	if (smbs->response == nil)
508ccd4a63SDavid du Colombier 		smbs->response = smbbuffernew(576);
518ccd4a63SDavid du Colombier 	else
528ccd4a63SDavid du Colombier 		smbresponsereset(smbs);
538ccd4a63SDavid du Colombier 	smbs->errclass = SUCCESS;
548ccd4a63SDavid du Colombier 	smbs->error = SUCCESS;
558ccd4a63SDavid du Colombier //	print("received %ld bytes\n", n);
568ccd4a63SDavid du Colombier 	if (n <= 0)
578ccd4a63SDavid du Colombier 		goto closedown;
588ccd4a63SDavid du Colombier 	b = smbbufferinit(p, p, n);
598ccd4a63SDavid du Colombier 	if (!smbbuffergetheader(b, &h, &pdata, &bytecount)) {
608ccd4a63SDavid du Colombier 		smblogprint(-1, "smb: invalid header\n");
618ccd4a63SDavid du Colombier 		goto closedown;
628ccd4a63SDavid du Colombier 	}
638ccd4a63SDavid du Colombier smbloglock();
648ccd4a63SDavid du Colombier smblogprint(h.command, "received:\n");
658ccd4a63SDavid du Colombier smblogdata(h.command, smblogprint, p, n, 0x1000);
668ccd4a63SDavid du Colombier smblogunlock();
678ccd4a63SDavid du Colombier 	ote = smboptable + h.command;
688ccd4a63SDavid du Colombier 	if (ote->name == nil) {
698ccd4a63SDavid du Colombier 		smblogprint(-1, "smb: illegal opcode 0x%.2ux\n", h.command);
708ccd4a63SDavid du Colombier 		goto unimp;
718ccd4a63SDavid du Colombier 	}
728ccd4a63SDavid du Colombier 	if (ote->process == nil) {
738ccd4a63SDavid du Colombier 		smblogprint(-1, "smb: opcode %s unimplemented\n", ote->name);
748ccd4a63SDavid du Colombier 		goto unimp;
758ccd4a63SDavid du Colombier 	}
768ccd4a63SDavid du Colombier 	if (smbs->nextcommand != SMB_COM_NO_ANDX_COMMAND
778ccd4a63SDavid du Colombier 		&& smbs->nextcommand != h.command) {
788ccd4a63SDavid du Colombier 		smblogprint(-1, "smb: wrong command - expected %.2ux\n", smbs->nextcommand);
798ccd4a63SDavid du Colombier 		goto misc;
808ccd4a63SDavid du Colombier 	}
818ccd4a63SDavid du Colombier 	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
828ccd4a63SDavid du Colombier 	switch (h.command) {
838ccd4a63SDavid du Colombier 	case SMB_COM_NEGOTIATE:
848ccd4a63SDavid du Colombier 	case SMB_COM_SESSION_SETUP_ANDX:
858ccd4a63SDavid du Colombier 	case SMB_COM_TREE_CONNECT_ANDX:
868ccd4a63SDavid du Colombier 	case SMB_COM_ECHO:
878ccd4a63SDavid du Colombier 		break;
888ccd4a63SDavid du Colombier 	default:
898ccd4a63SDavid du Colombier 		if (smbs->state != SmbSessionEstablished) {
908ccd4a63SDavid du Colombier 			smblogprint(-1, "aquarela: command %.2ux unexpected\n", h.command);
918ccd4a63SDavid du Colombier 			goto unimp;
928ccd4a63SDavid du Colombier 		}
938ccd4a63SDavid du Colombier 	}
948ccd4a63SDavid du Colombier 	pr = (*ote->process)(smbs, &h, pdata, b);
958ccd4a63SDavid du Colombier 	switch (pr) {
968ccd4a63SDavid du Colombier 	case SmbProcessResultUnimp:
978ccd4a63SDavid du Colombier 	unimp:
988ccd4a63SDavid du Colombier 		smbseterror(smbs, ERRDOS, ERRunsup);
998ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
1008ccd4a63SDavid du Colombier 		break;
1018ccd4a63SDavid du Colombier 	case SmbProcessResultFormat:
1028ccd4a63SDavid du Colombier 		smbseterror(smbs, ERRSRV, ERRsmbcmd);
1038ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
1048ccd4a63SDavid du Colombier 		break;
1058ccd4a63SDavid du Colombier 	case SmbProcessResultMisc:
1068ccd4a63SDavid du Colombier 	misc:
1078ccd4a63SDavid du Colombier 		smbseterror(smbs, ERRSRV, ERRerror);
1088ccd4a63SDavid du Colombier 		pr = SmbProcessResultError;
1098ccd4a63SDavid du Colombier 		break;
1108ccd4a63SDavid du Colombier 	}
1118ccd4a63SDavid du Colombier 	if (pr == SmbProcessResultError) {
1128ccd4a63SDavid du Colombier 		smblogprint(h.command, "reply: error %d/%d\n", smbs->errclass, smbs->error);
1138ccd4a63SDavid du Colombier 		if (!smbresponseputerror(smbs, &h, smbs->errclass, smbs->error))
1148ccd4a63SDavid du Colombier 			pr = SmbProcessResultDie;
1158ccd4a63SDavid du Colombier 		else
1168ccd4a63SDavid du Colombier 			pr = SmbProcessResultReply;
1178ccd4a63SDavid du Colombier 	}
1188ccd4a63SDavid du Colombier 	else
1198ccd4a63SDavid du Colombier 		smblogprint(h.command, "reply: ok\n");
1208ccd4a63SDavid du Colombier 	if (pr == SmbProcessResultReply)
1218ccd4a63SDavid du Colombier 		rv = smbresponsesend(smbs) == SmbProcessResultOk ? 0 : -1;
1228ccd4a63SDavid du Colombier 	else if (pr == SmbProcessResultDie)
1238ccd4a63SDavid du Colombier 		rv = -1;
1248ccd4a63SDavid du Colombier 	else
1258ccd4a63SDavid du Colombier 		rv = 0;
1268ccd4a63SDavid du Colombier 	goto done;
1278ccd4a63SDavid du Colombier closedown:
1288ccd4a63SDavid du Colombier 	rv = -1;
1298ccd4a63SDavid du Colombier done:
1308ccd4a63SDavid du Colombier 	if (rv < 0) {
1318ccd4a63SDavid du Colombier 		smblogprintif(smbglobals.log.sessions, "shutting down\n");
1328ccd4a63SDavid du Colombier 		smbsessionfree(smbs);
1338ccd4a63SDavid du Colombier 	}
1348ccd4a63SDavid du Colombier 	smbbufferfree(&b);
1358ccd4a63SDavid du Colombier 	if (smbglobals.log.poolparanoia)
1368ccd4a63SDavid du Colombier 		poolcheck(mainmem);
1378ccd4a63SDavid du Colombier 	return rv;
1388ccd4a63SDavid du Colombier }
1398ccd4a63SDavid du Colombier 
1408ccd4a63SDavid du Colombier static int
nbwrite(NbSession * nbss,void * p,long n)1418ccd4a63SDavid du Colombier nbwrite(NbSession *nbss, void *p, long n)
1428ccd4a63SDavid du Colombier {
1438ccd4a63SDavid du Colombier 	return smbsessionwrite((SmbSession *)nbss->magic, p, n);
1448ccd4a63SDavid du Colombier }
1458ccd4a63SDavid du Colombier 
1468ccd4a63SDavid du Colombier static int
cifswrite(SmbCifsSession * cifs,void * p,long n)1478ccd4a63SDavid du Colombier cifswrite(SmbCifsSession *cifs, void *p, long n)
1488ccd4a63SDavid du Colombier {
1498ccd4a63SDavid du Colombier 	return smbsessionwrite((SmbSession *)cifs->magic, p, n);
1508ccd4a63SDavid du Colombier }
1518ccd4a63SDavid du Colombier 
1528ccd4a63SDavid du Colombier int
nbssaccept(void *,NbSession * s,NBSSWRITEFN ** writep)1538ccd4a63SDavid du Colombier nbssaccept(void *, NbSession *s, NBSSWRITEFN **writep)
1548ccd4a63SDavid du Colombier {
1558ccd4a63SDavid du Colombier 	SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
1568ccd4a63SDavid du Colombier 	smbs->nbss = s;
1578ccd4a63SDavid du Colombier 	s->magic = smbs;
1588ccd4a63SDavid du Colombier 	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
1598ccd4a63SDavid du Colombier 	*writep = nbwrite;
1608ccd4a63SDavid du Colombier 	smblogprintif(smbglobals.log.sessions, "netbios session started\n");
1618ccd4a63SDavid du Colombier 	return 1;
1628ccd4a63SDavid du Colombier }
1638ccd4a63SDavid du Colombier 
1648ccd4a63SDavid du Colombier int
cifsaccept(SmbCifsSession * s,SMBCIFSWRITEFN ** writep)1658ccd4a63SDavid du Colombier cifsaccept(SmbCifsSession *s, SMBCIFSWRITEFN **writep)
1668ccd4a63SDavid du Colombier {
1678ccd4a63SDavid du Colombier 	SmbSession *smbs = smbemallocz(sizeof(SmbSession), 1);
1688ccd4a63SDavid du Colombier 	smbs->cifss = s;
1698ccd4a63SDavid du Colombier 	s->magic = smbs;
1708ccd4a63SDavid du Colombier 	smbs->nextcommand = SMB_COM_NO_ANDX_COMMAND;
1718ccd4a63SDavid du Colombier 	*writep = cifswrite;
1728ccd4a63SDavid du Colombier 	smblogprintif(smbglobals.log.sessions, "cifs session started\n");
1738ccd4a63SDavid du Colombier 	return 1;
1748ccd4a63SDavid du Colombier }
1758ccd4a63SDavid du Colombier 
1768ccd4a63SDavid du Colombier void
usage(void)1778ccd4a63SDavid du Colombier usage(void)
1788ccd4a63SDavid du Colombier {
179*94aa1c4cSDavid du Colombier 	fprint(2, "usage: %s [-np] [-d debug] [-u N] [-w workgroup]\n", argv0);
18016a961bdSDavid du Colombier 	threadexitsall("usage");
1818ccd4a63SDavid du Colombier }
1828ccd4a63SDavid du Colombier 
1838ccd4a63SDavid du Colombier static void
logset(char * cmd)1848ccd4a63SDavid du Colombier logset(char *cmd)
1858ccd4a63SDavid du Colombier {
1868ccd4a63SDavid du Colombier 	int x;
1878ccd4a63SDavid du Colombier 	if (strcmp(cmd, "allcmds") == 0) {
1888ccd4a63SDavid du Colombier 		for (x = 0; x < 256; x++)
1898ccd4a63SDavid du Colombier 			smboptable[x].debug = 1;
1908ccd4a63SDavid du Colombier 		for (x = 0; x < smbtrans2optablesize; x++)
1918ccd4a63SDavid du Colombier 			smbtrans2optable[x].debug = 1;
1928ccd4a63SDavid du Colombier 		return;
1938ccd4a63SDavid du Colombier 	}
1948ccd4a63SDavid du Colombier 	if (strcmp(cmd, "tids") == 0) {
1958ccd4a63SDavid du Colombier 		smbglobals.log.tids = 1;
1968ccd4a63SDavid du Colombier 		return;
1978ccd4a63SDavid du Colombier 	}
1988ccd4a63SDavid du Colombier 	if (strcmp(cmd, "sids") == 0) {
1998ccd4a63SDavid du Colombier 		smbglobals.log.sids = 1;
2008ccd4a63SDavid du Colombier 		return;
2018ccd4a63SDavid du Colombier 	}
2028ccd4a63SDavid du Colombier 	if (strcmp(cmd, "fids") == 0) {
2038ccd4a63SDavid du Colombier 		smbglobals.log.fids = 1;
2048ccd4a63SDavid du Colombier 		return;
2058ccd4a63SDavid du Colombier 	}
2068ccd4a63SDavid du Colombier 	if (strcmp(cmd, "rap2") == 0) {
2078ccd4a63SDavid du Colombier 		smbglobals.log.rap2 = 1;
2088ccd4a63SDavid du Colombier 		return;
2098ccd4a63SDavid du Colombier 	}
2108ccd4a63SDavid du Colombier 	else if (strcmp(cmd, "find") == 0) {
2118ccd4a63SDavid du Colombier 		smbglobals.log.find = 1;
2128ccd4a63SDavid du Colombier 		return;
2138ccd4a63SDavid du Colombier 	}
2148ccd4a63SDavid du Colombier 	if (strcmp(cmd, "query") == 0) {
2158ccd4a63SDavid du Colombier 		smbglobals.log.query = 1;
2168ccd4a63SDavid du Colombier 		return;
2178ccd4a63SDavid du Colombier 	}
2188ccd4a63SDavid du Colombier 	if (strcmp(cmd, "sharedfiles") == 0) {
2198ccd4a63SDavid du Colombier 		smbglobals.log.sharedfiles = 1;
2208ccd4a63SDavid du Colombier 		return;
2218ccd4a63SDavid du Colombier 	}
2228ccd4a63SDavid du Colombier 	if (strcmp(cmd, "poolparanoia") == 0) {
2238ccd4a63SDavid du Colombier 		mainmem->flags |= POOL_PARANOIA;
2248ccd4a63SDavid du Colombier 		smbglobals.log.poolparanoia = 1;
2258ccd4a63SDavid du Colombier 		return;
2268ccd4a63SDavid du Colombier 	}
2278ccd4a63SDavid du Colombier 	if (strcmp(cmd, "sessions") == 0) {
2288ccd4a63SDavid du Colombier 		smbglobals.log.sessions = 1;
2298ccd4a63SDavid du Colombier 		return;
2308ccd4a63SDavid du Colombier 	}
2318ccd4a63SDavid du Colombier 	if (strcmp(cmd, "rep") == 0) {
2328ccd4a63SDavid du Colombier 		smbglobals.log.rep = 1;
2338ccd4a63SDavid du Colombier 		return;
2348ccd4a63SDavid du Colombier 	}
2358ccd4a63SDavid du Colombier 	if (strcmp(cmd, "locks") == 0) {
2368ccd4a63SDavid du Colombier 		smbglobals.log.locks = 1;
2378ccd4a63SDavid du Colombier 		return;
2388ccd4a63SDavid du Colombier 	}
2398ccd4a63SDavid du Colombier 
2408ccd4a63SDavid du Colombier 	for (x = 0; x < 256; x++)
2418ccd4a63SDavid du Colombier 		if (smboptable[x].name && strcmp(smboptable[x].name, cmd) == 0) {
2428ccd4a63SDavid du Colombier 			smboptable[x].debug = 1;
2438ccd4a63SDavid du Colombier 			return;
2448ccd4a63SDavid du Colombier 		}
2458ccd4a63SDavid du Colombier 	for (x = 0; x < smbtrans2optablesize; x++)
2468ccd4a63SDavid du Colombier 		if (smbtrans2optable[x].name && strcmp(smbtrans2optable[x].name, cmd) == 0) {
2478ccd4a63SDavid du Colombier 			smbtrans2optable[x].debug = 1;
2488ccd4a63SDavid du Colombier 			return;
2498ccd4a63SDavid du Colombier 		}
2508ccd4a63SDavid du Colombier 	if (strlen(cmd) == 4 && cmd[0] == '0' && cmd[1] == 'x') {
2518ccd4a63SDavid du Colombier 		int c;
2528ccd4a63SDavid du Colombier 		c = strtoul(cmd + 2, 0, 16);
2538ccd4a63SDavid du Colombier 		if (c >= 0 && c <= 255) {
2548ccd4a63SDavid du Colombier 			smboptable[c].debug = 1;
2558ccd4a63SDavid du Colombier 			return;
2568ccd4a63SDavid du Colombier 		}
2578ccd4a63SDavid du Colombier 	}
2588ccd4a63SDavid du Colombier 	print("debugging command %s not recognised\n", cmd);
2598ccd4a63SDavid du Colombier }
2608ccd4a63SDavid du Colombier 
2618ccd4a63SDavid du Colombier 
2628ccd4a63SDavid du Colombier void
threadmain(int argc,char ** argv)2638ccd4a63SDavid du Colombier threadmain(int argc, char **argv)
2648ccd4a63SDavid du Colombier {
2658ccd4a63SDavid du Colombier 	NbName from, to;
2668ccd4a63SDavid du Colombier 	char *e = nil;
2678ccd4a63SDavid du Colombier 	int netbios = 0;
2688ccd4a63SDavid du Colombier 	ARGBEGIN {
2698ccd4a63SDavid du Colombier 	case 'u':
2708ccd4a63SDavid du Colombier 		smbglobals.unicode = strtol(ARGF(), 0, 0) != 0;
2718ccd4a63SDavid du Colombier 		break;
2728ccd4a63SDavid du Colombier 	case 'p':
2738ccd4a63SDavid du Colombier 		smbglobals.log.print = 1;
2748ccd4a63SDavid du Colombier 		break;
2758ccd4a63SDavid du Colombier 	case 'd':
2768ccd4a63SDavid du Colombier 		logset(ARGF());
2778ccd4a63SDavid du Colombier 		break;
2788ccd4a63SDavid du Colombier 	case 'w':
2798ccd4a63SDavid du Colombier 		smbglobals.primarydomain = ARGF();
2808ccd4a63SDavid du Colombier 		break;
2818ccd4a63SDavid du Colombier 	case 'n':
2828ccd4a63SDavid du Colombier 		netbios = 1;
2838ccd4a63SDavid du Colombier 		break;
2848ccd4a63SDavid du Colombier 	default:
2858ccd4a63SDavid du Colombier 		usage();
2868ccd4a63SDavid du Colombier 	} ARGEND;
2878ccd4a63SDavid du Colombier 	smbglobalsguess(0);
2888ccd4a63SDavid du Colombier 	smblistencifs(cifsaccept);
2898ccd4a63SDavid du Colombier 	if (netbios) {
2908ccd4a63SDavid du Colombier 		nbinit();
2918ccd4a63SDavid du Colombier 		nbmknamefromstring(from, "*");
2928ccd4a63SDavid du Colombier 		nbmknamefromstring(to, "*smbserver\\x20");
2938ccd4a63SDavid du Colombier 		nbsslisten(to, from, nbssaccept, nil);
2948ccd4a63SDavid du Colombier 		nbmknamefromstringandtype(to, smbglobals.serverinfo.name, 0x20);
2958ccd4a63SDavid du Colombier 		nbsslisten(to, from, nbssaccept, nil);
2968ccd4a63SDavid du Colombier 	}
2978ccd4a63SDavid du Colombier 	smblogprint(-1, "Aquarela %d.%d running\n", smbglobals.serverinfo.vmaj, smbglobals.serverinfo.vmin);
2988ccd4a63SDavid du Colombier 	for (;;) {
2998ccd4a63SDavid du Colombier 		if (netbios&& !smbbrowsesendhostannouncement(smbglobals.serverinfo.name, 60 * 1000,
3008ccd4a63SDavid du Colombier 			SV_TYPE_SERVER,
3018ccd4a63SDavid du Colombier 			smbglobals.serverinfo.remark, &e)) {
3028ccd4a63SDavid du Colombier 			smblogprint(-1, "hostannounce failed: %s\n", e);
3038ccd4a63SDavid du Colombier 		}
3048ccd4a63SDavid du Colombier 		if (sleep(60 * 1000) < 0)
3058ccd4a63SDavid du Colombier 			break;
3068ccd4a63SDavid du Colombier 	}
3078ccd4a63SDavid du Colombier }
3088ccd4a63SDavid du Colombier 
309