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