xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/NetFSServer.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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 		RETURN_ERROR(error);
968 
969 	// set it
970 	delete fSecurityContext;
971 	fSecurityContext = securityContext;
972 	securityContextDeleter.Detach();
973 
974 	return B_OK;
975 }
976 
977 // _SaveSettings
978 status_t
979 NetFSServer::_SaveSettings()
980 {
981 	AutoLocker<Locker> locker(fSecurityContext);
982 
983 	// create the settings archive
984 	BMessage settings;
985 
986 	// archive the security context
987 	BMessage securityContextArchive;
988 	status_t error = fSecurityContext->Archive(&securityContextArchive, true);
989 	if (error != B_OK)
990 		RETURN_ERROR(error);
991 
992 	// add it to the settings archive
993 	error = settings.AddMessage("security context", &securityContextArchive);
994 	if (error != B_OK)
995 		RETURN_ERROR(error);
996 
997 	// open the settings file
998 	BPath filePath;
999 	error = _GetSettingsFilePath(&filePath, true);
1000 	if (error != B_OK)
1001 		RETURN_ERROR(error);
1002 	BFile file;
1003 	error = FDManager::SetFile(&file, filePath.Path(),
1004 		B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
1005 	if (error != B_OK)
1006 		RETURN_ERROR(error);
1007 
1008 	// write to the settings file
1009 	error = settings.Flatten(&file);
1010 	if (error != B_OK)
1011 		RETURN_ERROR(error);
1012 
1013 	return B_OK;
1014 }
1015 
1016 // _GetSettingsDirPath
1017 status_t
1018 NetFSServer::_GetSettingsDirPath(BPath* path, bool create)
1019 {
1020 	// get the user settings directory
1021 	BPath settingsDir;
1022 	status_t error = find_directory(B_USER_SETTINGS_DIRECTORY, &settingsDir,
1023 		create);
1024 	if (error != B_OK)
1025 		RETURN_ERROR(error);
1026 
1027 	// create our subdir, if not existing and desired
1028 	error = path->SetTo(settingsDir.Path(), kSettingsDirName);
1029 	if (error != B_OK)
1030 		RETURN_ERROR(error);
1031 	BEntry bEntry;
1032 	if (create
1033 		&& (FDManager::SetEntry(&bEntry, settingsDir.Path()) != B_OK
1034 			|| !bEntry.Exists())) {
1035 		error = create_directory(path->Path(), S_IRWXU | S_IRWXG | S_IRWXO);
1036 		if (error != B_OK)
1037 			RETURN_ERROR(error);
1038 	}
1039 
1040 	return B_OK;
1041 }
1042 
1043 // _GetSettingsFilePath
1044 status_t
1045 NetFSServer::_GetSettingsFilePath(BPath* path, bool createDir)
1046 {
1047 	// get settings dir
1048 	BPath dirPath;
1049 	status_t error = _GetSettingsDirPath(&dirPath, createDir);
1050 	if (error != B_OK)
1051 		return error;
1052 
1053 	// construct the file path
1054 	return path->SetTo(dirPath.Path(), kSettingsFileName);
1055 }
1056 
1057 // _InitServerInfoConnectionListener
1058 status_t
1059 NetFSServer::_InitServerInfoConnectionListener()
1060 {
1061 	// spawn the listener thread
1062 	fServerInfoConnectionListener = spawn_thread(
1063 		&_ServerInfoConnectionListenerEntry,
1064 		"server info connection listener", B_NORMAL_PRIORITY, this);
1065 	if (fServerInfoConnectionListener < 0)
1066 		return fServerInfoConnectionListener;
1067 	// create a listener socket
1068 	fServerInfoConnectionListenerSocket = socket(AF_INET, SOCK_STREAM, 0);
1069 	if (fServerInfoConnectionListenerSocket < 0)
1070 		return errno;
1071 	// bind it to the port
1072 	sockaddr_in addr;
1073 	addr.sin_family = AF_INET;
1074 	addr.sin_port = htons(kDefaultServerInfoPort);
1075 	addr.sin_addr.s_addr = INADDR_ANY;
1076 	if (bind(fServerInfoConnectionListenerSocket, (sockaddr*)&addr,
1077 		sizeof(addr)) < 0) {
1078 		return errno;
1079 	}
1080 	// start listening
1081 	if (listen(fServerInfoConnectionListenerSocket, 5) < 0)
1082 		return errno;
1083 	return B_OK;
1084 }
1085 
1086 // _ExitServerInfoConnectionListener
1087 void
1088 NetFSServer::_ExitServerInfoConnectionListener()
1089 {
1090 	// close the socket
1091 	safe_closesocket(fServerInfoConnectionListenerSocket);
1092 	// wait for the listener
1093 	if (fServerInfoConnectionListener >= 0) {
1094 		int32 result;
1095 		wait_for_thread(fServerInfoConnectionListener, &result);
1096 	}
1097 }
1098 
1099 // _ConnectionListenerEntry
1100 int32
1101 NetFSServer::_ConnectionListenerEntry(void* data)
1102 {
1103 	return ((NetFSServer*)data)->_ConnectionListener();
1104 }
1105 
1106 // _ConnectionListener
1107 int32
1108 NetFSServer::_ConnectionListener()
1109 {
1110 	// start listening for connections
1111 	Connection* connection = NULL;
1112 	status_t error = B_OK;
1113 	do {
1114 		error = fConnectionListener->Listen(&connection);
1115 		if (error == B_OK) {
1116 			ConnectionInitializer* initializer
1117 				= new(std::nothrow) ConnectionInitializer(this, fConnectionListener,
1118 					connection);
1119 			if (initializer) {
1120 				if (initializer->Run() != B_OK) {
1121 					ERROR("Failed to run connection initializer.\n")
1122 					delete initializer;
1123 				}
1124 			} else {
1125 				ERROR("Failed to create connection initializer.\n")
1126 				delete connection;
1127 			}
1128 
1129 		}
1130 	} while (error == B_OK && !fTerminating);
1131 
1132 	return 0;
1133 }
1134 
1135 // _ConnectionDeleterEntry
1136 int32
1137 NetFSServer::_ConnectionDeleterEntry(void* data)
1138 {
1139 	return ((NetFSServer*)data)->_ConnectionDeleter();
1140 }
1141 
1142 // _ConnectionDeleter
1143 int32
1144 NetFSServer::_ConnectionDeleter()
1145 {
1146 	while (!fTerminating) {
1147 		status_t error = acquire_sem(fClosedConnectionsSemaphore);
1148 		ClientConnection* connection = NULL;
1149 		if (error == B_OK) {
1150 			AutoLocker<Locker> _(fLock);
1151 			connection = (ClientConnection*)fClosedConnections.RemoveItem((int32)0);
1152 		}
1153 		if (connection)
1154 			delete connection;
1155 	}
1156 	return 0;
1157 }
1158 
1159 // _BroadcasterEntry
1160 int32
1161 NetFSServer::_BroadcasterEntry(void* data)
1162 {
1163 	return ((NetFSServer*)data)->_Broadcaster();
1164 }
1165 
1166 // _Broadcaster
1167 int32
1168 NetFSServer::_Broadcaster()
1169 {
1170 	// create the socket
1171 	fBroadcastingSocket = socket(AF_INET, SOCK_DGRAM, 0);
1172 	if (fBroadcastingSocket < 0) {
1173 		WARN("NetFSServer::_Broadcaster(): WARN: Failed to init broadcasting: "
1174 			"%s.\n", strerror(errno));
1175 		return errno;
1176 	}
1177 
1178 	// set the socket broadcast option
1179 	#ifndef HAIKU_TARGET_PLATFORM_BEOS
1180 		int soBroadcastValue = 1;
1181 		if (setsockopt(fBroadcastingSocket, SOL_SOCKET, SO_BROADCAST,
1182 			&soBroadcastValue, sizeof(soBroadcastValue)) < 0) {
1183 			WARN("NetFSServer::_Broadcaster(): WARN: Failed to set "
1184 				"SO_BROADCAST on socket: %s.\n", strerror(errno));
1185 		}
1186 	#endif
1187 
1188 	// prepare the broadcast message
1189 	BroadcastMessage message;
1190 	message.magic = B_HOST_TO_BENDIAN_INT32(BROADCAST_MESSAGE_MAGIC);
1191 	message.protocolVersion = B_HOST_TO_BENDIAN_INT32(NETFS_PROTOCOL_VERSION);
1192 
1193 	bool update = false;
1194 	while (!fTerminating) {
1195 		// set tick/update
1196 		uint32 messageCode = (update ? BROADCAST_MESSAGE_SERVER_UPDATE
1197 			: BROADCAST_MESSAGE_SERVER_TICK);
1198 		message.message = B_HOST_TO_BENDIAN_INT32(messageCode);
1199 
1200 		// send broadcasting message
1201 		sockaddr_in addr;
1202 		addr.sin_family = AF_INET;
1203 		addr.sin_port = htons(kDefaultBroadcastPort);
1204 		addr.sin_addr.s_addr = INADDR_BROADCAST;
1205 		int addrSize = sizeof(addr);
1206 		ssize_t bytesSent = sendto(fBroadcastingSocket, &message,
1207 			sizeof(message), 0, (sockaddr*)&addr, addrSize);
1208 		if (bytesSent < 0) {
1209 			WARN("NetFSServer::_Broadcaster(): WARN: sending failed: %s.\n",
1210 				strerror(errno));
1211 			return errno;
1212 		}
1213 
1214 		// snooze a bit
1215 		// we snooze a minimal interval to avoid shooting updates like a
1216 		// machine gun
1217 		snooze(kMinBroadcastingInterval);
1218 		bigtime_t remainingTime = kBroadcastingInterval
1219 			- kMinBroadcastingInterval;
1220 
1221 		// snooze the rest blocking on our semaphore (if it exists)
1222 		if (fBroadcasterSemaphore >= 0) {
1223 			status_t snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1,
1224 				B_RELATIVE_TIMEOUT, remainingTime);
1225 
1226 			// set the semaphore count back to zero
1227 			while (snoozeError == B_OK) {
1228 				snoozeError = acquire_sem_etc(fBroadcasterSemaphore, 1,
1229 					B_RELATIVE_TIMEOUT, 0);
1230 			}
1231 		} else
1232 			snooze(remainingTime);
1233 
1234 		update = atomic_and(&fServerInfoUpdated, 0);
1235 	}
1236 
1237 	// close the socket
1238 	safe_closesocket(fBroadcastingSocket);
1239 	return B_OK;
1240 }
1241 
1242 // _ServerInfoConnectionListenerEntry
1243 int32
1244 NetFSServer::_ServerInfoConnectionListenerEntry(void* data)
1245 {
1246 	return ((NetFSServer*)data)->_ServerInfoConnectionListener();
1247 }
1248 
1249 // _ServerInfoConnectionListener
1250 int32
1251 NetFSServer::_ServerInfoConnectionListener()
1252 {
1253 	if (fServerInfoConnectionListenerSocket < 0)
1254 		return B_BAD_VALUE;
1255 
1256 	TaskManager taskManager;
1257 
1258 	// accept a incoming connection
1259 	while (!fTerminating) {
1260 		int fd = -1;
1261 		do {
1262 			taskManager.RemoveDoneTasks();
1263 
1264 			fd = accept(fServerInfoConnectionListenerSocket, NULL, 0);
1265 			if (fd < 0) {
1266 				status_t error = errno;
1267 				if (error != B_INTERRUPTED)
1268 					return error;
1269 				if (fTerminating)
1270 					return B_OK;
1271 			}
1272 		} while (fd < 0);
1273 
1274 		// get a fresh server info
1275 		ServerInfo info;
1276 		status_t error = _GetServerInfo(info);
1277 		if (error != B_OK) {
1278 			closesocket(fd);
1279 			return error;
1280 		}
1281 
1282 		// create a server info sender thread
1283 		ServerInfoSender* sender = new(std::nothrow) ServerInfoSender(fd, info);
1284 		if (sender == NULL) {
1285 			closesocket(fd);
1286 			delete sender;
1287 			return B_NO_MEMORY;
1288 		}
1289 		if ((error = sender->Init()) != B_OK) {
1290 			closesocket(fd);
1291 			delete sender;
1292 			return error;
1293 		}
1294 		taskManager.RunTask(sender);
1295 	}
1296 
1297 	return B_OK;
1298 }
1299 
1300 // _GetServerInfo
1301 status_t
1302 NetFSServer::_GetServerInfo(ServerInfo& serverInfo)
1303 {
1304 	// set the server name and the connection method
1305 	char hostName[1024];
1306 	if (gethostname(hostName, sizeof(hostName)) < 0) {
1307 		ERROR("NetFSServer::_GetServerInfo(): ERROR: Failed to get host "
1308 			"name.");
1309 		return B_ERROR;
1310 	}
1311 	status_t error = serverInfo.SetServerName(hostName);
1312 // TODO: Set the actually used connection method!
1313 	if (error == B_OK)
1314 		error = serverInfo.SetConnectionMethod("insecure");
1315 	if (error != B_OK)
1316 		return error;
1317 
1318 	// get the shares from the security context
1319 	BMessage shares;
1320 	error = fSecurityContext->GetShares(&shares);
1321 	if (error != B_OK)
1322 		return error;
1323 
1324 	// add the shares
1325 	const char* shareName;
1326 	for (int32 i = 0; shares.FindString("shares", i, &shareName) == B_OK; i++) {
1327 		error = serverInfo.AddShare(shareName);
1328 		if (error != B_OK)
1329 			return error;
1330 	}
1331 	return B_OK;
1332 }
1333 
1334 // _ServerInfoUpdated
1335 void
1336 NetFSServer::_ServerInfoUpdated()
1337 {
1338 	atomic_or(&fServerInfoUpdated, 1);
1339 	release_sem(fBroadcasterSemaphore);
1340 }
1341 
1342 // _SendReply
1343 void
1344 NetFSServer::_SendReply(BMessage* message, BMessage* reply, status_t error)
1345 {
1346 	// no reply is specified, if no data have to be sent
1347 	BMessage stackReply;
1348 	if (!reply)
1349 		reply = &stackReply;
1350 
1351 	reply->AddInt32("error", error);
1352 	message->SendReply(reply, (BHandler*)NULL, 0LL);
1353 }
1354 
1355 // _SendReply
1356 void
1357 NetFSServer::_SendReply(BMessage* message, status_t error)
1358 {
1359 	_SendReply(message, NULL, error);
1360 }
1361 
1362 
1363 // #pragma mark -
1364 
1365 // print_usage
1366 static
1367 void
1368 print_usage(bool error)
1369 {
1370 	fputs(kUsage, (error ? stderr : stdout));
1371 }
1372 
1373 // main
1374 int
1375 main(int argc, char** argv)
1376 {
1377 	#ifdef DEBUG_OBJECT_TRACKING
1378 		ObjectTracker::InitDefault();
1379 	#endif
1380 
1381 	// parse the arguments
1382 	bool broadcast = true;
1383 	for (int argi = 1; argi < argc; argi++) {
1384 		const char* arg = argv[argi];
1385 		if (strcmp(arg, "--dont-broadcast") == 0) {
1386 			broadcast = false;
1387 		} else if (strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) {
1388 			print_usage(false);
1389 			return 0;
1390 		} else {
1391 			print_usage(true);
1392 			return 1;
1393 		}
1394 	}
1395 
1396 	// create the statistics manager
1397 	status_t error = StatisticsManager::CreateDefault();
1398 	if (error != B_OK) {
1399 		fprintf(stderr, "Failed to create statistics manager: %s\n",
1400 			strerror(error));
1401 		return 1;
1402 	}
1403 
1404 	// init and run the server
1405 	{
1406 		NetFSServer server(broadcast);
1407 		error = server.Init();
1408 		if (error != B_OK) {
1409 			fprintf(stderr, "Failed to initialize server: %s\n",
1410 				strerror(error));
1411 			return 1;
1412 		}
1413 		server.Run();
1414 	}
1415 
1416 	// delete the statistics manager
1417 	StatisticsManager::DeleteDefault();
1418 
1419 	#ifdef DEBUG_OBJECT_TRACKING
1420 		ObjectTracker::ExitDefault();
1421 	#endif
1422 
1423 	return 0;
1424 }
1425 
1426