xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
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	= "NetFSServer";
45 
46 // usage
47 static 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
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 	: 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
212 NetFSServer::~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
273 status_t
274 NetFSServer::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
338 thread_id
339 NetFSServer::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
357 void
358 NetFSServer::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
737 VolumeManager*
738 NetFSServer::GetVolumeManager() const
739 {
740 	return fVolumeManager;
741 }
742 
743 // GetSecurityContext
744 SecurityContext*
745 NetFSServer::GetSecurityContext() const
746 {
747 	return fSecurityContext;
748 }
749 
750 // _AddClientConnection
751 status_t
752 NetFSServer::_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
763 void
764 NetFSServer::ClientConnectionClosed(ClientConnection* connection, bool broken)
765 {
766 PRINT(("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
784 status_t
785 NetFSServer::_LoadSecurityContext(SecurityContext** _securityContext)
786 {
787 	// create a security context
788 	SecurityContext* securityContext = new(std::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
889 status_t
890 NetFSServer::_InitSettings()
891 {
892 	status_t error = _LoadSettings();
893 	if (error != B_OK) {
894 		WARN("NetFSServer::_InitSettings(): WARNING: Failed to load settings "
895 			"file: %s - falling back to driver settings.\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(std::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
918 status_t
919 NetFSServer::_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(std::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
974 status_t
975 NetFSServer::_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
1013 status_t
1014 NetFSServer::_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
1040 status_t
1041 NetFSServer::_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
1054 status_t
1055 NetFSServer::_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
1083 void
1084 NetFSServer::_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
1096 int32
1097 NetFSServer::_ConnectionListenerEntry(void* data)
1098 {
1099 	return ((NetFSServer*)data)->_ConnectionListener();
1100 }
1101 
1102 // _ConnectionListener
1103 int32
1104 NetFSServer::_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(std::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
1132 int32
1133 NetFSServer::_ConnectionDeleterEntry(void* data)
1134 {
1135 	return ((NetFSServer*)data)->_ConnectionDeleter();
1136 }
1137 
1138 // _ConnectionDeleter
1139 int32
1140 NetFSServer::_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
1156 int32
1157 NetFSServer::_BroadcasterEntry(void* data)
1158 {
1159 	return ((NetFSServer*)data)->_Broadcaster();
1160 }
1161 
1162 // _Broadcaster
1163 int32
1164 NetFSServer::_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
1239 int32
1240 NetFSServer::_ServerInfoConnectionListenerEntry(void* data)
1241 {
1242 	return ((NetFSServer*)data)->_ServerInfoConnectionListener();
1243 }
1244 
1245 // _ServerInfoConnectionListener
1246 int32
1247 NetFSServer::_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(std::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
1291 status_t
1292 NetFSServer::_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
1325 void
1326 NetFSServer::_ServerInfoUpdated()
1327 {
1328 	atomic_or(&fServerInfoUpdated, 1);
1329 	release_sem(fBroadcasterSemaphore);
1330 }
1331 
1332 // _SendReply
1333 void
1334 NetFSServer::_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
1346 void
1347 NetFSServer::_SendReply(BMessage* message, status_t error)
1348 {
1349 	_SendReply(message, NULL, error);
1350 }
1351 
1352 
1353 // #pragma mark -
1354 
1355 // print_usage
1356 static
1357 void
1358 print_usage(bool error)
1359 {
1360 	fprintf((error ? stderr : stdout), kUsage);
1361 }
1362 
1363 // main
1364 int
1365 main(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