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