1// NetFSServer.cpp
2
3#include <errno.h>
4#include <netdb.h>
5#include <new>
6#include <stdio.h>
7#include <string.h>
8
9#ifdef HAIKU_TARGET_PLATFORM_BEOS
10#	include <socket.h>
11#else
12#	include <unistd.h>
13#	include <netinet/in.h>
14#	include <sys/socket.h>
15#endif
16
17#include <Directory.h>
18#include <File.h>
19#include <FindDirectory.h>
20#include <Node.h>
21#include <Path.h>
22
23#include "AutoDeleter.h"
24#include "AutoLocker.h"
25#include "Connection.h"
26#include "ConnectionListener.h"
27#include "Debug.h"
28#include "DLList.h"
29#include "DriverSettings.h"
30#include "FDManager.h"
31#include "InsecureChannel.h"
32#include "NetFSDefs.h"
33#include "NetFSServer.h"
34#include "NetFSServerRosterDefs.h"
35#include "RequestChannel.h"
36#include "Requests.h"
37#include "SecurityContext.h"
38#include "StatisticsManager.h"
39#include "TaskManager.h"
40#include "Utils.h"
41#include "VolumeManager.h"
42
43static const char* kSettingsDirName		= "netfs";
44static const char* kSettingsFileName	= "NetFSServer";
45
46// usage
47static const char* kUsage =
48"Usage: NetFSServer <options>\n"
49"options:\n"
50"  --dont-broadcast  - don't use broadcasting to announce the server's\n"
51"                      availability to clients\n"
52"  -h, --help        - print this text\n"
53;
54
55// ConnectionInitializer
56class NetFSServer::ConnectionInitializer {
57public:
58	ConnectionInitializer(NetFSServer* server,
59		ConnectionListener* connectionListener, Connection* connection)
60		: fServer(server),
61		  fConnectionListener(connectionListener),
62		  fConnection(connection),
63		  fThread(-1)
64	{
65	}
66
67	~ConnectionInitializer()
68	{
69		delete fConnection;
70	}
71
72	status_t Run()
73	{
74		fThread = spawn_thread(&_ThreadEntry, "connection initializer",
75			B_NORMAL_PRIORITY, this);
76		if (fThread < 0)
77			return fThread;
78		resume_thread(fThread);
79		return B_OK;
80	}
81
82private:
83	static int32 _ThreadEntry(void* data)
84	{
85		return ((ConnectionInitializer*)data)->_Thread();
86	}
87
88	int32 _Thread()
89	{
90		// finish connection initialization
91		User* user = NULL;
92		status_t error = fConnectionListener->FinishInitialization(
93			fConnection, fServer->GetSecurityContext(), &user);
94		// create a client connection
95		ClientConnection* clientConnection = NULL;
96		if (error == B_OK) {
97			clientConnection = new(nothrow) ClientConnection(fConnection,
98				fServer->GetSecurityContext(), user, fServer);
99			if (!clientConnection)
100				error = B_NO_MEMORY;
101		}
102		if (error == B_OK) {
103			fConnection = NULL;	// connection belongs to client connection now
104			error = clientConnection->Init();
105		}
106		// add the client connection to the server
107		if (error == B_OK)
108			error = fServer->_AddClientConnection(clientConnection);
109		// cleanup on error
110		if (error != B_OK)
111			delete clientConnection;
112		delete this;
113		return 0;
114	}
115
116private:
117	NetFSServer*		fServer;
118	ConnectionListener*	fConnectionListener;
119	Connection*			fConnection;
120	thread_id			fThread;
121};
122
123
124// ServerInfoSender
125class NetFSServer::ServerInfoSender : public Task {
126public:
127	ServerInfoSender(int socket, const ServerInfo& serverInfo)
128		: Task("server info sender"),
129		  fChannel(new(nothrow) InsecureChannel(socket)),
130		  fServerInfo(serverInfo)
131	{
132		if (!fChannel)
133			closesocket(socket);
134	}
135
136	~ServerInfoSender()
137	{
138		delete fChannel;
139	}
140
141	status_t Init()
142	{
143		if (!fChannel)
144			return B_NO_MEMORY;
145
146		return B_OK;
147	}
148
149	virtual void Stop()
150	{
151		if (fChannel)
152			fChannel->Close();
153	}
154
155	virtual status_t Execute()
156	{
157		if (!fChannel) {
158			SetDone(true);
159			return B_NO_INIT;
160		}
161
162		RequestChannel requestChannel(fChannel);
163
164		// create the server info request
165		ServerInfoRequest request;
166		request.serverInfo = fServerInfo;
167
168		// send the request
169		status_t error = requestChannel.SendRequest(&request);
170		if (error != B_OK) {
171			ERROR(("ServerInfoSender: ERROR: Failed to send request: %s\n",
172				strerror(error)));
173		}
174
175		SetDone(true);
176		return B_OK;
177	}
178
179private:
180	Channel*		fChannel;
181	ServerInfo		fServerInfo;
182};
183
184
185// NetFSServer
186
187// constructor
188NetFSServer::NetFSServer(bool useBroadcasting)
189	: BApplication(kNetFSServerSignature),
190	  fSecurityContext(NULL),
191	  fConnectionListenerFactory(),
192	  fConnectionListener(NULL),
193	  fLock("netfs server"),
194	  fClientConnections(),
195	  fVolumeManager(NULL),
196	  fClosedConnections(),
197	  fClosedConnectionsSemaphore(-1),
198	  fConnectionListenerThread(-1),
199	  fConnectionDeleter(-1),
200	  fBroadcaster(-1),
201	  fBroadcastingSocket(-1),
202	  fBroadcasterSemaphore(-1),
203	  fServerInfoConnectionListener(-1),
204	  fServerInfoConnectionListenerSocket(-1),
205	  fServerInfoUpdated(0),
206	  fUseBroadcasting(useBroadcasting),
207	  fTerminating(false)
208{
209}
210
211// destructor
212NetFSServer::~NetFSServer()
213{
214	fTerminating = true;
215	// stop the connection listener
216	if (fConnectionListener)
217		fConnectionListener->StopListening();
218	if (fConnectionListenerThread >= 0) {
219		int32 result;
220		wait_for_thread(fConnectionListenerThread, &result);
221	}
222	delete fConnectionListener;
223
224	// delete the broadcaster semaphore
225	if (fBroadcasterSemaphore >= 0)
226		delete_sem(fBroadcasterSemaphore);
227
228	// terminate the broadcaster
229	if (fBroadcaster >= 0) {
230		safe_closesocket(fBroadcastingSocket);
231
232		// interrupt the thread in case it is currently snoozing
233		suspend_thread(fBroadcaster);
234		int32 result;
235		wait_for_thread(fBroadcaster, &result);
236	}
237
238	// terminate the server info connection listener
239	_ExitServerInfoConnectionListener();
240
241	// terminate the connection deleter
242	if (fClosedConnectionsSemaphore >= 0)
243		delete_sem(fClosedConnectionsSemaphore);
244	if (fConnectionDeleter >= 0) {
245		int32 result;
246		wait_for_thread(fConnectionDeleter, &result);
247	}
248
249	// blow away all remaining connections
250	AutoLocker<Locker> _(fLock);
251	// open connections
252	for (int32 i = 0;
253		 ClientConnection* connection
254		 	= (ClientConnection*)fClientConnections.ItemAt(i);
255		 i++) {
256		connection->Close();
257		delete connection;
258	}
259
260	// closed connections
261	for (int32 i = 0;
262		 ClientConnection* connection
263		 	= (ClientConnection*)fClosedConnections.ItemAt(i);
264		 i++) {
265		delete connection;
266	}
267	VolumeManager::DeleteDefault();
268	FDManager::DeleteDefault();
269	delete fSecurityContext;
270}
271
272// Init
273status_t
274NetFSServer::Init()
275{
276	// init the settings
277	status_t error = _InitSettings();
278	if (error != B_OK)
279		return error;
280
281	// create the FD manager
282	error = FDManager::CreateDefault();
283	if (error != B_OK)
284		return error;
285
286	// create the volume manager
287	error = VolumeManager::CreateDefault();
288	if (error != B_OK)
289		return error;
290	fVolumeManager = VolumeManager::GetDefault();
291
292	// create a connection listener
293//	error = fConnectionListenerFactory.CreateConnectionListener(
294//		"port", NULL, &fConnectionListener);
295	error = fConnectionListenerFactory.CreateConnectionListener(
296		"insecure", NULL, &fConnectionListener);
297	if (error != B_OK)
298		return error;
299
300	// spawn the connection listener thread
301	fConnectionListenerThread = spawn_thread(&_ConnectionListenerEntry,
302		"connection listener", B_NORMAL_PRIORITY, this);
303	if (fConnectionListenerThread < 0)
304		return fConnectionListenerThread;
305
306	// create the closed connections semaphore
307	fClosedConnectionsSemaphore = create_sem(0, "closed connections");
308	if (fClosedConnectionsSemaphore < 0)
309		return fClosedConnectionsSemaphore;
310
311	// spawn the connection deleter
312	fConnectionDeleter = spawn_thread(&_ConnectionDeleterEntry,
313		"connection deleter", B_NORMAL_PRIORITY, this);
314	if (fConnectionDeleter < 0)
315		return fConnectionDeleter;
316
317	// init the server info connection listener
318	error = _InitServerInfoConnectionListener();
319	if (error != B_OK)
320		return error;
321
322	// create the broadcaster semaphore
323	fBroadcasterSemaphore = create_sem(0, "broadcaster snooze");
324
325	// spawn the broadcaster
326	if (fUseBroadcasting) {
327		fBroadcaster = spawn_thread(&_BroadcasterEntry, "broadcaster",
328			B_NORMAL_PRIORITY, this);
329		if (fBroadcaster < 0) {
330			WARN(("NetFSServer::Init(): Failed to spawn broadcaster thread "
331				"(%s). Continuing anyway.\n", strerror(fBroadcaster)));
332		}
333	}
334	return B_OK;
335}
336
337// Run
338thread_id
339NetFSServer::Run()
340{
341	// start the connection listener
342	resume_thread(fConnectionListenerThread);
343
344	// start the connection deleter
345	resume_thread(fConnectionDeleter);
346
347	// start the server info connection listener
348	resume_thread(fServerInfoConnectionListener);
349
350	// start the broadcaster
351	resume_thread(fBroadcaster);
352
353	return BApplication::Run();
354}
355
356// MessageReceived
357void
358NetFSServer::MessageReceived(BMessage* message)
359{
360	switch (message->what) {
361		case NETFS_REQUEST_GET_MESSENGER:
362		{
363			// for the time being we process all requests here
364			BMessage reply;
365			reply.AddMessenger("messenger", be_app_messenger);
366			_SendReply(message, &reply);
367			break;
368		}
369
370		case NETFS_REQUEST_ADD_USER:
371		{
372			// get user name and password
373			const char* user;
374			const char* password;
375			if (message->FindString("user", &user) != B_OK) {
376				_SendReply(message, B_BAD_VALUE);
377				break;
378			}
379			if (message->FindString("password", &password) != B_OK)
380				password = NULL;
381
382			// add the user
383			status_t error = fSecurityContext->AddUser(user, password);
384			_SendReply(message, error);
385			break;
386		}
387
388		case NETFS_REQUEST_REMOVE_USER:
389		{
390			// get user name
391			const char* userName;
392			if (message->FindString("user", &userName) != B_OK) {
393				_SendReply(message, B_BAD_VALUE);
394				break;
395			}
396
397			// remove the user
398			User* user;
399			status_t error = fSecurityContext->RemoveUser(userName, &user);
400			if (error == B_OK) {
401				// propagate the information to the client connections
402				AutoLocker<Locker> _(fLock);
403				for (int32 i = 0;
404					 ClientConnection* connection
405					 	= (ClientConnection*)fClientConnections.ItemAt(i);
406					 i++) {
407					connection->UserRemoved(user);
408				}
409
410				user->RemoveReference();
411			}
412
413			_SendReply(message, error);
414			break;
415		}
416
417		case NETFS_REQUEST_GET_USERS:
418		{
419			// get the users
420			BMessage reply;
421			BMessage users;
422			status_t error = fSecurityContext->GetUsers(&users);
423			if (error == B_OK)
424				error = reply.AddMessage("users", &users);
425
426			if (error == B_OK)
427				_SendReply(message, &reply);
428			else
429				_SendReply(message, error);
430			break;
431		}
432
433		case NETFS_REQUEST_GET_USER_STATISTICS:
434		{
435			// get user name
436			const char* userName;
437			if (message->FindString("user", &userName) != B_OK) {
438				_SendReply(message, B_BAD_VALUE);
439				break;
440			}
441
442			// get the user
443			User* user = fSecurityContext->FindUser(userName);
444			if (!user) {
445				_SendReply(message, B_ENTRY_NOT_FOUND);
446				break;
447			}
448			Reference<User> userReference(user, true);
449
450			// get the statistics
451			BMessage statistics;
452			status_t error = StatisticsManager::GetDefault()
453				->GetUserStatistics(user, &statistics);
454
455			// prepare the reply
456			BMessage reply;
457			if (error == B_OK)
458				error = reply.AddMessage("statistics", &statistics);
459
460			// send the reply
461			if (error == B_OK)
462				_SendReply(message, &reply);
463			else
464				_SendReply(message, error);
465			break;
466		}
467
468		case NETFS_REQUEST_ADD_SHARE:
469		{
470			// get share name and path
471			const char* share;
472			const char* path;
473			if (message->FindString("share", &share) != B_OK
474				|| message->FindString("path", &path) != B_OK) {
475				_SendReply(message, B_BAD_VALUE);
476				break;
477			}
478
479			// add the share
480			status_t error = fSecurityContext->AddShare(share, path);
481
482			if (error == B_OK)
483				_ServerInfoUpdated();
484
485			_SendReply(message, error);
486			break;
487		}
488
489		case NETFS_REQUEST_REMOVE_SHARE:
490		{
491			// get share name
492			const char* shareName;
493			if (message->FindString("share", &shareName) != B_OK) {
494				_SendReply(message, B_BAD_VALUE);
495				break;
496			}
497
498			// remove the share
499			Share* share;
500			status_t error = fSecurityContext->RemoveShare(shareName, &share);
501			if (error == B_OK) {
502				// propagate the information to the client connections
503				AutoLocker<Locker> _(fLock);
504				for (int32 i = 0;
505					 ClientConnection* connection
506					 	= (ClientConnection*)fClientConnections.ItemAt(i);
507					 i++) {
508					connection->ShareRemoved(share);
509				}
510
511				share->RemoveReference();
512			}
513
514			if (error == B_OK)
515				_ServerInfoUpdated();
516
517			_SendReply(message, error);
518			break;
519		}
520
521		case NETFS_REQUEST_GET_SHARES:
522		{
523			// get the shares
524			BMessage reply;
525			BMessage shares;
526			status_t error = fSecurityContext->GetShares(&shares);
527			if (error == B_OK)
528				error = reply.AddMessage("shares", &shares);
529
530			if (error == B_OK)
531				_SendReply(message, &reply);
532			else
533				_SendReply(message, error);
534			break;
535		}
536
537		case NETFS_REQUEST_GET_SHARE_USERS:
538		{
539			// get share name
540			const char* shareName;
541			if (message->FindString("share", &shareName) != B_OK) {
542				_SendReply(message, B_BAD_VALUE);
543				break;
544			}
545
546			AutoLocker<Locker> securityContextLocker(fSecurityContext);
547
548			// get the share
549			Share* share = fSecurityContext->FindShare(shareName);
550			if (!share) {
551				_SendReply(message, B_ENTRY_NOT_FOUND);
552				break;
553			}
554			Reference<Share> shareReference(share, true);
555
556			// get all users
557			BMessage allUsers;
558			status_t error = fSecurityContext->GetUsers(&allUsers);
559			if (error != B_OK) {
560				_SendReply(message, error);
561				break;
562			}
563
564			// filter the users with mount permission
565			BMessage users;
566			const char* userName;
567			for (int32 i = 0;
568				 allUsers.FindString("users", i, &userName) == B_OK;
569				 i++) {
570				if (User* user = fSecurityContext->FindUser(userName)) {
571					// get the user's permissions
572					Permissions permissions = fSecurityContext
573						->GetNodePermissions(share->GetPath(), user);
574					user->RemoveReference();
575
576					// add the user, if they have the permission to mount the
577					// share
578					if (permissions.ImpliesMountSharePermission()) {
579						error = users.AddString("users", userName);
580						if (error != B_OK) {
581							_SendReply(message, error);
582							break;
583						}
584					}
585				}
586			}
587
588			securityContextLocker.Unlock();
589
590			// prepare the reply
591			BMessage reply;
592			if (error == B_OK)
593				error = reply.AddMessage("users", &users);
594
595			// send the reply
596			if (error == B_OK)
597				_SendReply(message, &reply);
598			else
599				_SendReply(message, error);
600			break;
601		}
602
603		case NETFS_REQUEST_GET_SHARE_STATISTICS:
604		{
605			// get share name
606			const char* shareName;
607			if (message->FindString("share", &shareName) != B_OK) {
608				_SendReply(message, B_BAD_VALUE);
609				break;
610			}
611
612			// get the share
613			Share* share = fSecurityContext->FindShare(shareName);
614			if (!share) {
615				_SendReply(message, B_ENTRY_NOT_FOUND);
616				break;
617			}
618			Reference<Share> shareReference(share, true);
619
620			// get the statistics
621			BMessage statistics;
622			status_t error = StatisticsManager::GetDefault()
623				->GetShareStatistics(share, &statistics);
624
625			// prepare the reply
626			BMessage reply;
627			if (error == B_OK)
628				error = reply.AddMessage("statistics", &statistics);
629
630			// send the reply
631			if (error == B_OK)
632				_SendReply(message, &reply);
633			else
634				_SendReply(message, error);
635			break;
636		}
637
638		case NETFS_REQUEST_SET_USER_PERMISSIONS:
639		{
640			// get share and user name, and the permissions
641			const char* shareName;
642			const char* userName;
643			uint32 permissions;
644			if (message->FindString("share", &shareName) != B_OK
645				|| message->FindString("user", &userName) != B_OK
646				|| message->FindInt32("permissions", (int32*)&permissions)
647					!= B_OK) {
648				_SendReply(message, B_BAD_VALUE);
649				break;
650			}
651
652			// get the share and the user
653			Share* share = fSecurityContext->FindShare(shareName);
654			User* user = fSecurityContext->FindUser(userName);
655			Reference<Share> shareReference(share);
656			Reference<User> userReference(user);
657			if (!share || !user) {
658				_SendReply(message, B_ENTRY_NOT_FOUND);
659				break;
660			}
661
662			// set the permissions
663			status_t error = B_OK;
664			if (permissions == 0) {
665				fSecurityContext->ClearNodePermissions(share->GetPath(), user);
666			} else {
667				error = fSecurityContext->SetNodePermissions(share->GetPath(),
668					user, permissions);
669			}
670
671			if (error == B_OK) {
672				// propagate the information to the client connections
673				AutoLocker<Locker> _(fLock);
674				for (int32 i = 0;
675					 ClientConnection* connection
676					 	= (ClientConnection*)fClientConnections.ItemAt(i);
677					 i++) {
678					connection->UserPermissionsChanged(share, user,
679						permissions);
680				}
681			}
682
683			_SendReply(message, error);
684			break;
685		}
686
687		case NETFS_REQUEST_GET_USER_PERMISSIONS:
688		{
689			// get share and user name
690			const char* shareName;
691			const char* userName;
692			if (message->FindString("share", &shareName) != B_OK
693				|| message->FindString("user", &userName) != B_OK) {
694				_SendReply(message, B_BAD_VALUE);
695				break;
696			}
697
698			// get the share and the user
699			Share* share = fSecurityContext->FindShare(shareName);
700			User* user = fSecurityContext->FindUser(userName);
701			Reference<Share> shareReference(share);
702			Reference<User> userReference(user);
703			if (!share || !user) {
704				_SendReply(message, B_ENTRY_NOT_FOUND);
705				break;
706			}
707
708			// get the permissions
709			Permissions permissions = fSecurityContext->GetNodePermissions(
710				share->GetPath(), user);
711
712			// prepare the reply
713			BMessage reply;
714			status_t error = reply.AddInt32("permissions",
715				(int32)permissions.GetPermissions());
716
717			// send it
718			if (error == B_OK)
719				_SendReply(message, &reply);
720			else
721				_SendReply(message, error);
722			break;
723		}
724
725		case NETFS_REQUEST_SAVE_SETTINGS:
726		{
727			status_t error = _SaveSettings();
728
729			// send a reply
730			_SendReply(message, error);
731			break;
732		}
733	}
734}
735
736// GetVolumeManager
737VolumeManager*
738NetFSServer::GetVolumeManager() const
739{
740	return fVolumeManager;
741}
742
743// GetSecurityContext
744SecurityContext*
745NetFSServer::GetSecurityContext() const
746{
747	return fSecurityContext;
748}
749
750// _AddClientConnection
751status_t
752NetFSServer::_AddClientConnection(ClientConnection* clientConnection)
753{
754	if (!clientConnection)
755		return B_BAD_VALUE;
756	AutoLocker<Locker> locker(fLock);
757	if (!fClientConnections.AddItem(clientConnection))
758		return B_NO_MEMORY;
759	return B_OK;
760}
761
762// ClientConnectionClosed
763void
764NetFSServer::ClientConnectionClosed(ClientConnection* connection, bool broken)
765{
766PRINT(("NetFSServer::ClientConnectionClosed(%d)\n", broken));
767	if (!connection)
768		return;
769	AutoLocker<Locker> locker(fLock);
770	if (!fClientConnections.RemoveItem(connection))
771		return;
772	if (!fClosedConnections.AddItem(connection)) {
773		// out of memory: Try to delete the connection right now.,
774		// There's a certain chance that we'll access free()d memory in the
775		// process, but things are apparently bad enough, anyway.
776		locker.Unlock();
777		delete connection;
778		return;
779	}
780	release_sem(fClosedConnectionsSemaphore);
781}
782
783// _LoadSecurityContext
784status_t
785NetFSServer::_LoadSecurityContext(SecurityContext** _securityContext)
786{
787	// create a security context
788	SecurityContext* securityContext = new(nothrow) SecurityContext;
789	if (!securityContext)
790		return B_NO_MEMORY;
791	status_t error = securityContext->InitCheck();
792	if (error != B_OK)
793		return error;
794	ObjectDeleter<SecurityContext> securityContextDeleter(securityContext);
795
796	// load from driver settings for the time being
797	DriverSettings settings;
798	error = settings.Load("netfs-server");
799	if (error != B_OK)
800		return error;
801
802	// load users
803	DriverParameter parameter;
804	for (DriverParameterIterator it = settings.GetParameterIterator("user");
805		 it.GetNext(&parameter);) {
806		const char* userName = parameter.ValueAt(0);
807		const char* password = parameter.GetParameterValue("password");
808		if (!userName) {
809			WARN(("Skipping nameless user settings entry.\n"));
810			continue;
811		}
812//		PRINT(("user: %s, password: %s\n", parameter.ValueAt(0),
813//			parameter.GetParameterValue("password")));
814		error = securityContext->AddUser(userName, password);
815		if (error != B_OK)
816			ERROR(("ERROR: Failed to add user `%s'\n", userName));
817	}
818
819	// load shares
820	for (DriverParameterIterator it = settings.GetParameterIterator("share");
821		 it.GetNext(&parameter);) {
822		const char* shareName = parameter.ValueAt(0);
823		const char* path = parameter.GetParameterValue("path");
824		if (!shareName || !path) {
825			WARN(("settings: Skipping invalid share settings entry (no name"
826				" or no path).\n"));
827			continue;
828		}
829//		PRINT(("share: %s, path: %s\n", parameter.ValueAt(0),
830//			parameter.GetParameterValue("path")));
831		Share* share;
832		error = securityContext->AddShare(shareName, path, &share);
833		if (error != B_OK) {
834			ERROR(("ERROR: Failed to add share `%s'\n", shareName));
835			continue;
836		}
837		Reference<Share> shareReference(share, true);
838		DriverParameter userParameter;
839		// iterate through the share users
840		for (DriverParameterIterator userIt
841				= parameter.GetParameterIterator("user");
842			 userIt.GetNext(&userParameter);) {
843			const char* userName = userParameter.ValueAt(0);
844//			PRINT(("  user: %s\n", userName));
845			User* user = securityContext->FindUser(userName);
846			if (!user) {
847				ERROR(("ERROR: Undefined user `%s'.\n", userName));
848				continue;
849			}
850			Reference<User> userReference(user, true);
851			DriverParameter permissionsParameter;
852			if (!userParameter.FindParameter("permissions",
853					&permissionsParameter)) {
854				continue;
855			}
856			Permissions permissions;
857			for (int32 i = 0; i < permissionsParameter.CountValues(); i++) {
858				const char* permission = permissionsParameter.ValueAt(i);
859//				PRINT(("    permission: %s\n", permission));
860				if (strcmp(permission, "mount") == 0) {
861					permissions.AddPermissions(MOUNT_SHARE_PERMISSION);
862				} else if (strcmp(permission, "query") == 0) {
863					permissions.AddPermissions(QUERY_SHARE_PERMISSION);
864				} else if (strcmp(permission, "read") == 0) {
865					permissions.AddPermissions(READ_PERMISSION
866						| READ_DIR_PERMISSION | RESOLVE_DIR_ENTRY_PERMISSION);
867				} else if (strcmp(permission, "write") == 0) {
868					permissions.AddPermissions(WRITE_PERMISSION
869						| WRITE_DIR_PERMISSION);
870				} else if (strcmp(permission, "all") == 0) {
871					permissions.AddPermissions(ALL_PERMISSIONS);
872				}
873			}
874			error = securityContext->SetNodePermissions(share->GetPath(), user,
875				permissions);
876			if (error != B_OK) {
877				ERROR(("ERROR: Failed to set permissions for share `%s'\n",
878					share->GetName()));
879			}
880		}
881	}
882
883	securityContextDeleter.Detach();
884	*_securityContext = securityContext;
885	return B_OK;
886}
887
888// _InitSettings
889status_t
890NetFSServer::_InitSettings()
891{
892	status_t error = _LoadSettings();
893	if (error != B_OK) {
894		WARN(("NetFSServer::_InitSettings(): WARNING: Failed to load settings "
895			"file: %s\n", strerror(error)));
896
897		// fall back to the driver settings file
898		error = _LoadSecurityContext(&fSecurityContext);
899		if (error != B_OK) {
900			WARN(("NetFSServer::_InitSettings(): WARNING: Failed to load "
901				"settings from driver settings: %s\n", strerror(error)));
902
903			// use defaults
904			// create a security context
905			fSecurityContext = new(nothrow) SecurityContext;
906			if (!fSecurityContext)
907				return B_NO_MEMORY;
908			error = fSecurityContext->InitCheck();
909			if (error != B_OK)
910				return error;
911		}
912	}
913
914	return B_OK;
915}
916
917// _LoadSettings
918status_t
919NetFSServer::_LoadSettings()
920{
921	// get the settings file path
922	BPath filePath;
923	status_t error = _GetSettingsFilePath(&filePath, false);
924	if (error != B_OK)
925		RETURN_ERROR(error);
926
927	// if existing load the settings
928	BEntry bEntry;
929	if (FDManager::SetEntry(&bEntry, filePath.Path()) == B_OK
930		&& bEntry.Exists()) {
931		return B_ENTRY_NOT_FOUND;
932	}
933
934	// open the settings file
935	BFile file;
936	error = FDManager::SetFile(&file, filePath.Path(), B_READ_ONLY);
937	if (error != B_OK)
938		RETURN_ERROR(error);
939
940	// read the settings
941	BMessage settings;
942	error = settings.Unflatten(&file);
943	if (error != B_OK)
944		RETURN_ERROR(error);
945
946	// get the security context archive
947	BMessage securityContextArchive;
948	error = settings.FindMessage("security context",
949		&securityContextArchive);
950	if (error != B_OK)
951		RETURN_ERROR(error);
952
953	// create a security context
954	SecurityContext* securityContext
955		= new(nothrow) SecurityContext(&securityContextArchive);
956	if (!securityContext)
957		RETURN_ERROR(B_NO_MEMORY);
958	ObjectDeleter<SecurityContext> securityContextDeleter(securityContext);
959	error = securityContext->InitCheck();
960	if (error != B_OK) {
961		delete securityContext;
962		RETURN_ERROR(error);
963	}
964
965	// set it
966	delete fSecurityContext;
967	fSecurityContext = securityContext;
968	securityContextDeleter.Detach();
969
970	return B_OK;
971}
972
973// _SaveSettings
974status_t
975NetFSServer::_SaveSettings()
976{
977	AutoLocker<Locker> locker(fSecurityContext);
978
979	// create the settings archive
980	BMessage settings;
981
982	// archive the security context
983	BMessage securityContextArchive;
984	status_t error = fSecurityContext->Archive(&securityContextArchive, true);
985	if (error != B_OK)
986		RETURN_ERROR(error);
987
988	// add it to the settings archive
989	error = settings.AddMessage("security context", &securityContextArchive);
990	if (error != B_OK)
991		RETURN_ERROR(error);
992
993	// open the settings file
994	BPath filePath;
995	error = _GetSettingsFilePath(&filePath, true);
996	if (error != B_OK)
997		RETURN_ERROR(error);
998	BFile file;
999	error = FDManager::SetFile(&file, filePath.Path(),
1000		B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
1001	if (error != B_OK)
1002		RETURN_ERROR(error);
1003
1004	// write to the settings file
1005	error = settings.Flatten(&file);
1006	if (error != B_OK)
1007		RETURN_ERROR(error);
1008
1009	return B_OK;
1010}
1011
1012// _GetSettingsDirPath
1013status_t
1014NetFSServer::_GetSettingsDirPath(BPath* path, bool create)
1015{
1016	// get the user settings directory
1017	BPath settingsDir;
1018	status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsDir,
1019		create);
1020	if (error != B_OK)
1021		RETURN_ERROR(error);
1022
1023	// create our subdir, if not existing and desired
1024	error = path->SetTo(settingsDir.Path(), kSettingsDirName);
1025	if (error != B_OK)
1026		RETURN_ERROR(error);
1027	BEntry bEntry;
1028	if (create
1029		&& (FDManager::SetEntry(&bEntry, settingsDir.Path()) != B_OK
1030			|| !bEntry.Exists())) {
1031		error = create_directory(path->Path(), S_IRWXU | S_IRWXG | S_IRWXO);
1032		if (error != B_OK)
1033			RETURN_ERROR(error);
1034	}
1035
1036	return B_OK;
1037}
1038
1039// _GetSettingsFilePath
1040status_t
1041NetFSServer::_GetSettingsFilePath(BPath* path, bool createDir)
1042{
1043	// get settings dir
1044	BPath dirPath;
1045	status_t error = _GetSettingsDirPath(&dirPath, createDir);
1046	if (error != B_OK)
1047		return error;
1048
1049	// construct the file path
1050	return path->SetTo(dirPath.Path(), kSettingsFileName);
1051}
1052
1053// _InitServerInfoConnectionListener
1054status_t
1055NetFSServer::_InitServerInfoConnectionListener()
1056{
1057	// spawn the listener thread
1058	fServerInfoConnectionListener = spawn_thread(
1059		&_ServerInfoConnectionListenerEntry,
1060		"server info connection listener", B_NORMAL_PRIORITY, this);
1061	if (fServerInfoConnectionListener < 0)
1062		return fServerInfoConnectionListener;
1063	// create a listener socket
1064	fServerInfoConnectionListenerSocket = socket(AF_INET, SOCK_STREAM, 0);
1065	if (fServerInfoConnectionListenerSocket < 0)
1066		return errno;
1067	// bind it to the port
1068	sockaddr_in addr;
1069	addr.sin_family = AF_INET;
1070	addr.sin_port = htons(kDefaultServerInfoPort);
1071	addr.sin_addr.s_addr = INADDR_ANY;
1072	if (bind(fServerInfoConnectionListenerSocket, (sockaddr*)&addr,
1073		sizeof(addr)) < 0) {
1074		return errno;
1075	}
1076	// start listening
1077	if (listen(fServerInfoConnectionListenerSocket, 5) < 0)
1078		return errno;
1079	return B_OK;
1080}
1081
1082// _ExitServerInfoConnectionListener
1083void
1084NetFSServer::_ExitServerInfoConnectionListener()
1085{
1086	// close the socket
1087	safe_closesocket(fServerInfoConnectionListenerSocket);
1088	// wait for the listener
1089	if (fServerInfoConnectionListener >= 0) {
1090		int32 result;
1091		wait_for_thread(fServerInfoConnectionListener, &result);
1092	}
1093}
1094
1095// _ConnectionListenerEntry
1096int32
1097NetFSServer::_ConnectionListenerEntry(void* data)
1098{
1099	return ((NetFSServer*)data)->_ConnectionListener();
1100}
1101
1102// _ConnectionListener
1103int32
1104NetFSServer::_ConnectionListener()
1105{
1106	// start listening for connections
1107	Connection* connection = NULL;
1108	status_t error = B_OK;
1109	do {
1110		error = fConnectionListener->Listen(&connection);
1111		if (error == B_OK) {
1112			ConnectionInitializer* initializer
1113				= new(nothrow) ConnectionInitializer(this, fConnectionListener,
1114					connection);
1115			if (initializer) {
1116				if (initializer->Run() != B_OK) {
1117					ERROR(("Failed to run connection initializer.\n"))
1118					delete initializer;
1119				}
1120			} else {
1121				ERROR(("Failed to create connection initializer.\n"))
1122				delete connection;
1123			}
1124
1125		}
1126	} while (error == B_OK && !fTerminating);
1127
1128	return 0;
1129}
1130
1131// _ConnectionDeleterEntry
1132int32
1133NetFSServer::_ConnectionDeleterEntry(void* data)
1134{
1135	return ((NetFSServer*)data)->_ConnectionDeleter();
1136}
1137
1138// _ConnectionDeleter
1139int32
1140NetFSServer::_ConnectionDeleter()
1141{
1142	while (!fTerminating) {
1143		status_t error = acquire_sem(fClosedConnectionsSemaphore);
1144		ClientConnection* connection = NULL;
1145		if (error == B_OK) {
1146			AutoLocker<Locker> _(fLock);
1147			connection = (ClientConnection*)fClosedConnections.RemoveItem(0L);
1148		}
1149		if (connection)
1150			delete connection;
1151	}
1152	return 0;
1153}
1154
1155// _BroadcasterEntry
1156int32
1157NetFSServer::_BroadcasterEntry(void* data)
1158{
1159	return ((NetFSServer*)data)->_Broadcaster();
1160}
1161
1162// _Broadcaster
1163int32
1164NetFSServer::_Broadcaster()
1165{
1166	// create the socket
1167	fBroadcastingSocket = socket(AF_INET, SOCK_DGRAM, 0);
1168	if (fBroadcastingSocket < 0) {
1169		WARN(("NetFSServer::_Broadcaster(): WARN: Failed to init broadcasting: "
1170			"%s.\n", strerror(errno)));
1171		return errno;
1172	}
1173
1174	// set the socket broadcast option
1175	#ifndef HAIKU_TARGET_PLATFORM_BEOS
1176		int soBroadcastValue = 1;
1177		if (setsockopt(fBroadcastingSocket, SOL_SOCKET, SO_BROADCAST,
1178			&soBroadcastValue, sizeof(soBroadcastValue)) < 0) {
1179			WARN(("NetFSServer::_Broadcaster(): WARN: Failed to set "
1180				"SO_BROADCAST on socket: %s.\n", strerror(errno)));
1181		}
1182	#endif
1183
1184	// prepare the broadcast message
1185	BroadcastMessage message;
1186	message.magic = B_HOST_TO_BENDIAN_INT32(BROADCAST_MESSAGE_MAGIC);
1187	message.protocolVersion = B_HOST_TO_BENDIAN_INT32(NETFS_PROTOCOL_VERSION);
1188
1189	bool update = false;
1190	while (!fTerminating) {
1191		// set tick/update
1192		uint32 messageCode = (update ? BROADCAST_MESSAGE_SERVER_UPDATE
1193			: BROADCAST_MESSAGE_SERVER_TICK);
1194		message.message = B_HOST_TO_BENDIAN_INT32(messageCode);
1195
1196		// send broadcasting message
1197		sockaddr_in addr;
1198		addr.sin_family = AF_INET;
1199		addr.sin_port = htons(kDefaultBroadcastPort);
1200		addr.sin_addr.s_addr = INADDR_BROADCAST;
1201		int addrSize = sizeof(addr);
1202		ssize_t bytesSent = sendto(fBroadcastingSocket, &message,
1203			sizeof(message), 0, (sockaddr*)&addr, addrSize);
1204		if (bytesSent < 0) {
1205			WARN(("NetFSServer::_Broadcaster(): WARN: sending failed: %s.\n",
1206				strerror(errno)));
1207			return errno;
1208		}
1209
1210		// snooze a bit
1211		// we snooze a minimal interval to avoid shooting updates like a
1212		// machine gun
1213		snooze(kMinBroadcastingInterval);
1214		bigtime_t remainingTime = kBroadcastingInterval
1215			- kMinBroadcastingInterval;
1216
1217		// snooze the rest blocking on our semaphore (if it exists)
1218		if (fBroadcasterSemaphore >= 0) {
1219			status_t snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1,
1220				B_RELATIVE_TIMEOUT, remainingTime);
1221
1222			// set the semaphore count back to zero
1223			while (snoozeError == B_OK) {
1224				snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1,
1225					B_RELATIVE_TIMEOUT, 0);
1226			}
1227		} else
1228			snooze(remainingTime);
1229
1230		update = atomic_and(&fServerInfoUpdated, 0);
1231	}
1232
1233	// close the socket
1234	safe_closesocket(fBroadcastingSocket);
1235	return B_OK;
1236}
1237
1238// _ServerInfoConnectionListenerEntry
1239int32
1240NetFSServer::_ServerInfoConnectionListenerEntry(void* data)
1241{
1242	return ((NetFSServer*)data)->_ServerInfoConnectionListener();
1243}
1244
1245// _ServerInfoConnectionListener
1246int32
1247NetFSServer::_ServerInfoConnectionListener()
1248{
1249	if (fServerInfoConnectionListenerSocket < 0)
1250		return B_BAD_VALUE;
1251
1252	TaskManager taskManager;
1253
1254	// accept a incoming connection
1255	while (!fTerminating) {
1256		int fd = -1;
1257		do {
1258			taskManager.RemoveDoneTasks();
1259
1260			fd = accept(fServerInfoConnectionListenerSocket, NULL, 0);
1261			if (fd < 0) {
1262				status_t error = errno;
1263				if (error != B_INTERRUPTED)
1264					return error;
1265				if (fTerminating)
1266					return B_OK;
1267			}
1268		} while (fd < 0);
1269
1270		// get a fresh server info
1271		ServerInfo info;
1272		status_t error = _GetServerInfo(info);
1273		if (error != B_OK) {
1274			closesocket(fd);
1275			return error;
1276		}
1277
1278		// create a server info sender thread
1279		ServerInfoSender* sender = new(nothrow) ServerInfoSender(fd, info);
1280		if (!sender || sender->Init() != B_OK) {
1281			closesocket(fd);
1282			delete sender;
1283		}
1284		taskManager.RunTask(sender);
1285	}
1286
1287	return B_OK;
1288}
1289
1290// _GetServerInfo
1291status_t
1292NetFSServer::_GetServerInfo(ServerInfo& serverInfo)
1293{
1294	// set the server name and the connection method
1295	char hostName[1024];
1296	if (gethostname(hostName, sizeof(hostName)) < 0) {
1297		ERROR(("NetFSServer::_GetServerInfo(): ERROR: Failed to get host "
1298			"name."));
1299		return B_ERROR;
1300	}
1301	status_t error = serverInfo.SetServerName(hostName);
1302// TODO: Set the actually used connection method!
1303	if (error == B_OK)
1304		error = serverInfo.SetConnectionMethod("insecure");
1305	if (error != B_OK)
1306		return error;
1307
1308	// get the shares from the security context
1309	BMessage shares;
1310	error = fSecurityContext->GetShares(&shares);
1311	if (error != B_OK)
1312		return error;
1313
1314	// add the shares
1315	const char* shareName;
1316	for (int32 i = 0; shares.FindString("shares", i, &shareName) == B_OK; i++) {
1317		error = serverInfo.AddShare(shareName);
1318		if (error != B_OK)
1319			return error;
1320	}
1321	return B_OK;
1322}
1323
1324// _ServerInfoUpdated
1325void
1326NetFSServer::_ServerInfoUpdated()
1327{
1328	atomic_or(&fServerInfoUpdated, 1);
1329	release_sem(fBroadcasterSemaphore);
1330}
1331
1332// _SendReply
1333void
1334NetFSServer::_SendReply(BMessage* message, BMessage* reply, status_t error)
1335{
1336	// no reply is specified, if no data have to be sent
1337	BMessage stackReply;
1338	if (!reply)
1339		reply = &stackReply;
1340
1341	reply->AddInt32("error", error);
1342	message->SendReply(reply, (BHandler*)NULL, 0LL);
1343}
1344
1345// _SendReply
1346void
1347NetFSServer::_SendReply(BMessage* message, status_t error)
1348{
1349	_SendReply(message, NULL, error);
1350}
1351
1352
1353// #pragma mark -
1354
1355// print_usage
1356static
1357void
1358print_usage(bool error)
1359{
1360	fprintf((error ? stderr : stdout), kUsage);
1361}
1362
1363// main
1364int
1365main(int argc, char** argv)
1366{
1367	#ifdef DEBUG_OBJECT_TRACKING
1368		ObjectTracker::InitDefault();
1369	#endif
1370
1371	// parse the arguments
1372	bool broadcast = true;
1373	for (int argi = 1; argi < argc; argi++) {
1374		const char* arg = argv[argi];
1375		if (strcmp(arg, "--dont-broadcast") == 0) {
1376			broadcast = false;
1377		} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
1378			print_usage(false);
1379			return 0;
1380		} else {
1381			print_usage(true);
1382			return 1;
1383		}
1384	}
1385
1386	// create the statistics manager
1387	status_t error = StatisticsManager::CreateDefault();
1388	if (error != B_OK) {
1389		fprintf(stderr, "Failed to create statistics manager: %s\n",
1390			strerror(error));
1391		return 1;
1392	}
1393
1394	// init and run the server
1395	{
1396		NetFSServer server(broadcast);
1397		error = server.Init();
1398		if (error != B_OK) {
1399			fprintf(stderr, "Failed to initialize server: %s\n",
1400				strerror(error));
1401			return 1;
1402		}
1403		server.Run();
1404	}
1405
1406	// delete the statistics manager
1407	StatisticsManager::DeleteDefault();
1408
1409	#ifdef DEBUG_OBJECT_TRACKING
1410		ObjectTracker::ExitDefault();
1411	#endif
1412
1413	return 0;
1414}
1415
1416