1// Requests.cpp
2
3#include <limits.h>
4
5#include "Debug.h"
6#include "Requests.h"
7
8#define _ADD_ADDRESS(_address, _flags)				\
9	if (*count >= MAX_REQUEST_ADDRESS_COUNT)		\
10		return B_BAD_VALUE;							\
11	infos[*count].address = &_address;				\
12	infos[*count].flags = _flags;					\
13	infos[(*count)++].max_size = LONG_MAX;	// TODO:...
14
15#define ADD_ADDRESS(address)	_ADD_ADDRESS(address, 0)
16#define ADD_STRING(address)		_ADD_ADDRESS(address, ADDRESS_IS_STRING)
17#define ADD_NON_NULL_ADDRESS(address)	_ADD_ADDRESS(address, ADDRESS_NOT_NULL)
18#define ADD_NON_NULL_STRING(address)	\
19	_ADD_ADDRESS(address, (ADDRESS_IS_STRING | ADDRESS_NOT_NULL))
20
21// FSConnectRequest
22status_t
23FSConnectRequest::GetAddressInfos(AddressInfo* infos, int32* count)
24{
25	ADD_NON_NULL_STRING(fsName);
26	return B_OK;
27}
28
29// FSConnectReply
30status_t
31FSConnectReply::GetAddressInfos(AddressInfo* infos, int32* count)
32{
33	ADD_NON_NULL_ADDRESS(portInfos);
34	return B_OK;
35}
36
37// MountVolumeRequest
38status_t
39MountVolumeRequest::GetAddressInfos(AddressInfo* infos, int32* count)
40{
41	ADD_NON_NULL_STRING(cwd);
42	ADD_STRING(device);
43	ADD_STRING(parameters);
44	return B_OK;
45}
46
47// InitializeVolumeRequest
48status_t
49InitializeVolumeRequest::GetAddressInfos(AddressInfo* infos, int32* count)
50{
51	ADD_STRING(device);
52	ADD_STRING(parameters);
53	return B_OK;
54}
55
56// CreateRequest
57status_t
58CreateRequest::GetAddressInfos(AddressInfo* infos, int32* count)
59{
60	ADD_NON_NULL_STRING(name);
61	return B_OK;
62}
63
64// ReadReply
65status_t
66ReadReply::GetAddressInfos(AddressInfo* infos, int32* count)
67{
68	ADD_ADDRESS(buffer);
69	return B_OK;
70}
71
72// WriteRequest
73status_t
74WriteRequest::GetAddressInfos(AddressInfo* infos, int32* count)
75{
76	ADD_ADDRESS(buffer);
77	return B_OK;
78}
79
80// IOCtlRequest
81status_t
82IOCtlRequest::GetAddressInfos(AddressInfo* infos, int32* count)
83{
84	ADD_ADDRESS(buffer);
85	return B_OK;
86}
87
88// IOCtlReply
89status_t
90IOCtlReply::GetAddressInfos(AddressInfo* infos, int32* count)
91{
92	ADD_ADDRESS(buffer);
93	return B_OK;
94}
95
96// LinkRequest
97status_t
98LinkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
99{
100	ADD_NON_NULL_STRING(name);
101	return B_OK;
102}
103
104// UnlinkRequest
105status_t
106UnlinkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
107{
108	ADD_NON_NULL_STRING(name);
109	return B_OK;
110}
111
112// SymlinkRequest
113status_t
114SymlinkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
115{
116	ADD_NON_NULL_STRING(name);
117	ADD_NON_NULL_STRING(target);
118	return B_OK;
119}
120
121// ReadLinkReply
122status_t
123ReadLinkReply::GetAddressInfos(AddressInfo* infos, int32* count)
124{
125	ADD_STRING(buffer);
126	return B_OK;
127}
128
129// RenameRequest
130status_t
131RenameRequest::GetAddressInfos(AddressInfo* infos, int32* count)
132{
133	ADD_NON_NULL_STRING(oldName);
134	ADD_NON_NULL_STRING(newName);
135	return B_OK;
136}
137
138// MkDirRequest
139status_t
140MkDirRequest::GetAddressInfos(AddressInfo* infos, int32* count)
141{
142	ADD_NON_NULL_STRING(name);
143	return B_OK;
144}
145
146// RmDirRequest
147status_t
148RmDirRequest::GetAddressInfos(AddressInfo* infos, int32* count)
149{
150	ADD_NON_NULL_STRING(name);
151	return B_OK;
152}
153
154// ReadDirReply
155status_t
156ReadDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
157{
158	ADD_ADDRESS(buffer);
159	return B_OK;
160}
161
162// WalkRequest
163status_t
164WalkRequest::GetAddressInfos(AddressInfo* infos, int32* count)
165{
166	ADD_NON_NULL_STRING(entryName);
167	return B_OK;
168}
169
170// WalkReply
171status_t
172WalkReply::GetAddressInfos(AddressInfo* infos, int32* count)
173{
174	ADD_STRING(resolvedPath);
175	return B_OK;
176}
177
178// ReadAttrDirReply
179status_t
180ReadAttrDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
181{
182	ADD_ADDRESS(buffer);
183	return B_OK;
184}
185
186// ReadAttrRequest
187status_t
188ReadAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
189{
190	ADD_NON_NULL_STRING(name);
191	return B_OK;
192}
193
194// ReadAttrReply
195status_t
196ReadAttrReply::GetAddressInfos(AddressInfo* infos, int32* count)
197{
198	ADD_ADDRESS(buffer);
199	return B_OK;
200}
201
202// WriteAttrRequest
203status_t
204WriteAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
205{
206	ADD_NON_NULL_STRING(name);
207	ADD_ADDRESS(buffer);
208	return B_OK;
209}
210
211// RemoveAttrRequest
212status_t
213RemoveAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
214{
215	ADD_NON_NULL_STRING(name);
216	return B_OK;
217}
218
219// RenameAttrRequest
220status_t
221RenameAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
222{
223	ADD_NON_NULL_STRING(oldName);
224	ADD_NON_NULL_STRING(newName);
225	return B_OK;
226}
227
228// StatAttrRequest
229status_t
230StatAttrRequest::GetAddressInfos(AddressInfo* infos, int32* count)
231{
232	ADD_NON_NULL_STRING(name);
233	return B_OK;
234}
235
236// ReadIndexDirReply
237status_t
238ReadIndexDirReply::GetAddressInfos(AddressInfo* infos, int32* count)
239{
240	ADD_ADDRESS(buffer);
241	return B_OK;
242}
243
244// CreateIndexRequest
245status_t
246CreateIndexRequest::GetAddressInfos(AddressInfo* infos, int32* count)
247{
248	ADD_NON_NULL_STRING(name);
249	return B_OK;
250}
251
252// RemoveIndexRequest
253status_t
254RemoveIndexRequest::GetAddressInfos(AddressInfo* infos, int32* count)
255{
256	ADD_NON_NULL_STRING(name);
257	return B_OK;
258}
259
260// RenameIndexRequest
261status_t
262RenameIndexRequest::GetAddressInfos(AddressInfo* infos, int32* count)
263{
264	ADD_NON_NULL_STRING(oldName);
265	ADD_NON_NULL_STRING(newName);
266	return B_OK;
267}
268
269// StatIndexRequest
270status_t
271StatIndexRequest::GetAddressInfos(AddressInfo* infos, int32* count)
272{
273	ADD_NON_NULL_STRING(name);
274	return B_OK;
275}
276
277// OpenQueryRequest
278status_t
279OpenQueryRequest::GetAddressInfos(AddressInfo* infos, int32* count)
280{
281	ADD_NON_NULL_STRING(queryString);
282	return B_OK;
283}
284
285// ReadQueryReply
286status_t
287ReadQueryReply::GetAddressInfos(AddressInfo* infos, int32* count)
288{
289	ADD_ADDRESS(buffer);
290	return B_OK;
291}
292
293// NotifyListenerRequest
294status_t
295NotifyListenerRequest::GetAddressInfos(AddressInfo* infos, int32* count)
296{
297	ADD_STRING(name);
298	return B_OK;
299}
300
301// SendNotificationRequest
302status_t
303SendNotificationRequest::GetAddressInfos(AddressInfo* infos, int32* count)
304{
305	ADD_STRING(name);
306	return B_OK;
307}
308
309
310// #pragma mark -
311
312// RequestAddressInfoGetter
313struct RequestAddressInfoGetter {
314	RequestAddressInfoGetter(AddressInfo* infos, int32* count)
315		: fInfos(infos),
316		  fCount(count)
317	{
318	}
319
320	template<typename R> status_t operator()(R* request)
321	{
322		return request->GetAddressInfos(fInfos, fCount);
323	}
324
325private:
326	AddressInfo*	fInfos;
327	int32*			fCount;
328};
329
330// get_request_address_infos
331status_t
332UserlandFSUtil::get_request_address_infos(Request* request, AddressInfo* infos,
333	int32* count)
334{
335	if (!infos || !count)
336		return B_BAD_VALUE;
337	*count = 0;
338	RequestAddressInfoGetter task(infos, count);
339	return do_for_request(request, task);
340}
341
342// RequestChecker
343struct RequestChecker {
344	template<typename R> status_t operator()(R* request)
345	{
346		return request->Check();
347	}
348};
349
350// check_request
351status_t
352UserlandFSUtil::check_request(Request* request)
353{
354	RequestChecker task;
355	return do_for_request(request, task);
356}
357
358
359// is_error_reply
360static inline
361bool
362is_error_reply(Request* request)
363{
364	return false;
365}
366
367// is_error_reply
368static inline
369bool
370is_error_reply(ReplyRequest* request)
371{
372	return (request->error != B_OK);
373}
374
375// RequestRelocator
376struct RequestRelocator {
377	RequestRelocator(int32 requestBufferSize, area_id* areas, int32* count)
378		: fRequestBufferSize(requestBufferSize),
379		  fAreas(areas),
380		  fAreaCount(count)
381	{
382		*fAreaCount = 0;
383	}
384
385	~RequestRelocator()
386	{
387		if (!fSuccess) {
388			for (int32 i = 0; i < *fAreaCount; i++)
389				delete_area(fAreas[i]);
390		}
391	}
392
393	template<typename R> status_t operator()(R* request)
394	{
395		// check the request buffer size
396		if (fRequestBufferSize < (int32)sizeof(R))
397			RETURN_ERROR(B_BAD_DATA);
398		// no need to relocate the addresses of a reply that indicates an error
399		if (is_error_reply(request)) {
400			fSuccess = true;
401			return B_OK;
402		}
403		// get the address infos
404		AddressInfo infos[MAX_REQUEST_ADDRESS_COUNT];
405		int32 count = 0;
406		status_t error = request->GetAddressInfos(infos, &count);
407		if (error != B_OK)
408			RETURN_ERROR(error);
409		// check and relocate the addresses
410		for (int32 i = 0; i < count; i++) {
411			// check
412			Address* address = infos[i].address;
413			int32 size = address->GetSize();
414			int32 offset = address->GetOffset();
415//PRINT(("  relocating address: area: %ld, offset: %ld, size: %ld...\n",
416//address->GetArea(), offset, size));
417			if (offset < 0 || size < 0 || size > infos[i].max_size)
418				RETURN_ERROR(B_BAD_DATA);
419			if ((infos[i].flags & ADDRESS_NOT_NULL) && size == 0)
420				RETURN_ERROR(B_BAD_DATA);
421			// relocate
422			area_id area = address->GetArea();
423			if (area < 0) {
424				// data in the buffer itself
425				if (offset == 0 && size == 0) {
426//PRINT(("    -> relocated address: NULL\n"));
427					address->SetRelocatedAddress(NULL);
428				} else {
429					if (offset < (int32)sizeof(R)
430						|| offset + size > fRequestBufferSize) {
431						RETURN_ERROR(B_BAD_DATA);
432					}
433//PRINT(("    -> relocated address: %p\n", (uint8*)request + offset));
434					address->SetRelocatedAddress((uint8*)request + offset);
435				}
436			} else {
437				// clone the area
438				void* data;
439				area = clone_area("cloned request data", &data,
440#ifdef _KERNEL_MODE
441					B_ANY_KERNEL_ADDRESS,
442#else
443					B_ANY_ADDRESS,
444#endif
445					B_READ_AREA, area);
446				if (area < 0)
447					RETURN_ERROR(area);
448				fAreas[(*fAreaCount)++] = area;
449				// check offset and size
450				area_info areaInfo;
451				error = get_area_info(area, &areaInfo);
452				if (error != B_OK)
453					RETURN_ERROR(error);
454				if (offset + size > (int32)areaInfo.size)
455					RETURN_ERROR(B_BAD_DATA);
456//PRINT(("    -> relocated address: %p\n", (uint8*)data + offset));
457				address->SetRelocatedAddress((uint8*)data + offset);
458			}
459		}
460		// finally let the request check its integrity
461		error = request->Check();
462		if (error != B_OK)
463			RETURN_ERROR(error);
464		fSuccess = true;
465//PRINT(("RequestRelocator done: success\n"));
466		return B_OK;
467	}
468
469private:
470	int32		fRequestBufferSize;
471	area_id*	fAreas;
472	int32*		fAreaCount;
473	bool		fSuccess;
474};
475
476// relocate_request
477status_t
478UserlandFSUtil::relocate_request(Request* request, int32 requestBufferSize,
479	area_id* areas, int32* count)
480{
481	if (!request || !areas || !count)
482		return B_BAD_VALUE;
483	RequestRelocator task(requestBufferSize, areas, count);
484	return do_for_request(request, task);
485}
486
487// is_kernel_request
488bool
489UserlandFSUtil::is_kernel_request(uint32 type)
490{
491	switch (type) {
492		// kernel -> userland requests
493		// administrative
494		case UFS_DISCONNECT_REQUEST:
495		case FS_CONNECT_REQUEST:
496			return true;
497		case FS_CONNECT_REPLY:
498			return false;
499		// FS
500		case MOUNT_VOLUME_REQUEST:
501		case UNMOUNT_VOLUME_REQUEST:
502		case INITIALIZE_VOLUME_REQUEST:
503		case SYNC_VOLUME_REQUEST:
504		case READ_FS_STAT_REQUEST:
505		case WRITE_FS_STAT_REQUEST:
506			return true;
507		case MOUNT_VOLUME_REPLY:
508		case UNMOUNT_VOLUME_REPLY:
509		case INITIALIZE_VOLUME_REPLY:
510		case SYNC_VOLUME_REPLY:
511		case READ_FS_STAT_REPLY:
512		case WRITE_FS_STAT_REPLY:
513			return false;
514		// vnodes
515		case READ_VNODE_REQUEST:
516		case WRITE_VNODE_REQUEST:
517		case FS_REMOVE_VNODE_REQUEST:
518			return true;
519		case READ_VNODE_REPLY:
520		case WRITE_VNODE_REPLY:
521		case FS_REMOVE_VNODE_REPLY:
522			return false;
523		// nodes
524		case FSYNC_REQUEST:
525		case READ_STAT_REQUEST:
526		case WRITE_STAT_REQUEST:
527		case ACCESS_REQUEST:
528			return true;
529		case FSYNC_REPLY:
530		case READ_STAT_REPLY:
531		case WRITE_STAT_REPLY:
532		case ACCESS_REPLY:
533			return false;
534		// files
535		case CREATE_REQUEST:
536		case OPEN_REQUEST:
537		case CLOSE_REQUEST:
538		case FREE_COOKIE_REQUEST:
539		case READ_REQUEST:
540		case WRITE_REQUEST:
541		case IOCTL_REQUEST:
542		case SET_FLAGS_REQUEST:
543		case SELECT_REQUEST:
544		case DESELECT_REQUEST:
545			return true;
546		case CREATE_REPLY:
547		case OPEN_REPLY:
548		case CLOSE_REPLY:
549		case FREE_COOKIE_REPLY:
550		case READ_REPLY:
551		case WRITE_REPLY:
552		case IOCTL_REPLY:
553		case SET_FLAGS_REPLY:
554		case SELECT_REPLY:
555		case DESELECT_REPLY:
556			return false;
557		// hard links / symlinks
558		case LINK_REQUEST:
559		case UNLINK_REQUEST:
560		case SYMLINK_REQUEST:
561		case READ_LINK_REQUEST:
562		case RENAME_REQUEST:
563			return true;
564		case LINK_REPLY:
565		case UNLINK_REPLY:
566		case SYMLINK_REPLY:
567		case READ_LINK_REPLY:
568		case RENAME_REPLY:
569			return false;
570		// directories
571		case MKDIR_REQUEST:
572		case RMDIR_REQUEST:
573		case OPEN_DIR_REQUEST:
574		case CLOSE_DIR_REQUEST:
575		case FREE_DIR_COOKIE_REQUEST:
576		case READ_DIR_REQUEST:
577		case REWIND_DIR_REQUEST:
578		case WALK_REQUEST:
579			return true;
580		case MKDIR_REPLY:
581		case RMDIR_REPLY:
582		case OPEN_DIR_REPLY:
583		case CLOSE_DIR_REPLY:
584		case FREE_DIR_COOKIE_REPLY:
585		case READ_DIR_REPLY:
586		case REWIND_DIR_REPLY:
587		case WALK_REPLY:
588			return false;
589		// attributes
590		case OPEN_ATTR_DIR_REQUEST:
591		case CLOSE_ATTR_DIR_REQUEST:
592		case FREE_ATTR_DIR_COOKIE_REQUEST:
593		case READ_ATTR_DIR_REQUEST:
594		case REWIND_ATTR_DIR_REQUEST:
595		case READ_ATTR_REQUEST:
596		case WRITE_ATTR_REQUEST:
597		case REMOVE_ATTR_REQUEST:
598		case RENAME_ATTR_REQUEST:
599		case STAT_ATTR_REQUEST:
600			return true;
601		case OPEN_ATTR_DIR_REPLY:
602		case CLOSE_ATTR_DIR_REPLY:
603		case FREE_ATTR_DIR_COOKIE_REPLY:
604		case READ_ATTR_DIR_REPLY:
605		case REWIND_ATTR_DIR_REPLY:
606		case READ_ATTR_REPLY:
607		case WRITE_ATTR_REPLY:
608		case REMOVE_ATTR_REPLY:
609		case RENAME_ATTR_REPLY:
610		case STAT_ATTR_REPLY:
611			return false;
612		// indices
613		case OPEN_INDEX_DIR_REQUEST:
614		case CLOSE_INDEX_DIR_REQUEST:
615		case FREE_INDEX_DIR_COOKIE_REQUEST:
616		case READ_INDEX_DIR_REQUEST:
617		case REWIND_INDEX_DIR_REQUEST:
618		case CREATE_INDEX_REQUEST:
619		case REMOVE_INDEX_REQUEST:
620		case RENAME_INDEX_REQUEST:
621		case STAT_INDEX_REQUEST:
622			return true;
623		case OPEN_INDEX_DIR_REPLY:
624		case CLOSE_INDEX_DIR_REPLY:
625		case FREE_INDEX_DIR_COOKIE_REPLY:
626		case READ_INDEX_DIR_REPLY:
627		case REWIND_INDEX_DIR_REPLY:
628		case CREATE_INDEX_REPLY:
629		case REMOVE_INDEX_REPLY:
630		case RENAME_INDEX_REPLY:
631		case STAT_INDEX_REPLY:
632			return false;
633		// queries
634		case OPEN_QUERY_REQUEST:
635		case CLOSE_QUERY_REQUEST:
636		case FREE_QUERY_COOKIE_REQUEST:
637		case READ_QUERY_REQUEST:
638			return true;
639		case OPEN_QUERY_REPLY:
640		case CLOSE_QUERY_REPLY:
641		case FREE_QUERY_COOKIE_REPLY:
642		case READ_QUERY_REPLY:
643			return false;
644
645		// userland -> kernel requests
646		// notifications
647		case NOTIFY_LISTENER_REQUEST:
648		case NOTIFY_SELECT_EVENT_REQUEST:
649		case SEND_NOTIFICATION_REQUEST:
650			return false;
651		case NOTIFY_LISTENER_REPLY:
652		case NOTIFY_SELECT_EVENT_REPLY:
653		case SEND_NOTIFICATION_REPLY:
654			return true;
655		// vnodes
656		case GET_VNODE_REQUEST:
657		case PUT_VNODE_REQUEST:
658		case NEW_VNODE_REQUEST:
659		case REMOVE_VNODE_REQUEST:
660		case UNREMOVE_VNODE_REQUEST:
661		case IS_VNODE_REMOVED_REQUEST:
662			return false;
663		case GET_VNODE_REPLY:
664		case PUT_VNODE_REPLY:
665		case NEW_VNODE_REPLY:
666		case REMOVE_VNODE_REPLY:
667		case UNREMOVE_VNODE_REPLY:
668		case IS_VNODE_REMOVED_REPLY:
669			return true;
670
671		// general reply
672		case RECEIPT_ACK_REPLY:
673			return true;
674		default:
675			return false;
676	}
677}
678
679// is_userland_request
680bool
681UserlandFSUtil::is_userland_request(uint32 type)
682{
683	switch (type) {
684		// kernel -> userland requests
685		// administrative
686		case UFS_DISCONNECT_REQUEST:
687		case FS_CONNECT_REQUEST:
688			return false;
689		case FS_CONNECT_REPLY:
690			return true;
691		// FS
692		case MOUNT_VOLUME_REQUEST:
693		case UNMOUNT_VOLUME_REQUEST:
694		case INITIALIZE_VOLUME_REQUEST:
695		case SYNC_VOLUME_REQUEST:
696		case READ_FS_STAT_REQUEST:
697		case WRITE_FS_STAT_REQUEST:
698			return false;
699		case MOUNT_VOLUME_REPLY:
700		case UNMOUNT_VOLUME_REPLY:
701		case INITIALIZE_VOLUME_REPLY:
702		case SYNC_VOLUME_REPLY:
703		case READ_FS_STAT_REPLY:
704		case WRITE_FS_STAT_REPLY:
705			return true;
706		// vnodes
707		case READ_VNODE_REQUEST:
708		case WRITE_VNODE_REQUEST:
709		case FS_REMOVE_VNODE_REQUEST:
710			return false;
711		case READ_VNODE_REPLY:
712		case WRITE_VNODE_REPLY:
713		case FS_REMOVE_VNODE_REPLY:
714			return true;
715		// nodes
716		case FSYNC_REQUEST:
717		case READ_STAT_REQUEST:
718		case WRITE_STAT_REQUEST:
719		case ACCESS_REQUEST:
720			return false;
721		case FSYNC_REPLY:
722		case READ_STAT_REPLY:
723		case WRITE_STAT_REPLY:
724		case ACCESS_REPLY:
725			return true;
726		// files
727		case CREATE_REQUEST:
728		case OPEN_REQUEST:
729		case CLOSE_REQUEST:
730		case FREE_COOKIE_REQUEST:
731		case READ_REQUEST:
732		case WRITE_REQUEST:
733		case IOCTL_REQUEST:
734		case SET_FLAGS_REQUEST:
735		case SELECT_REQUEST:
736		case DESELECT_REQUEST:
737			return false;
738		case CREATE_REPLY:
739		case OPEN_REPLY:
740		case CLOSE_REPLY:
741		case FREE_COOKIE_REPLY:
742		case READ_REPLY:
743		case WRITE_REPLY:
744		case IOCTL_REPLY:
745		case SET_FLAGS_REPLY:
746		case SELECT_REPLY:
747		case DESELECT_REPLY:
748			return true;
749		// hard links / symlinks
750		case LINK_REQUEST:
751		case UNLINK_REQUEST:
752		case SYMLINK_REQUEST:
753		case READ_LINK_REQUEST:
754		case RENAME_REQUEST:
755			return false;
756		case LINK_REPLY:
757		case UNLINK_REPLY:
758		case SYMLINK_REPLY:
759		case READ_LINK_REPLY:
760		case RENAME_REPLY:
761			return true;
762		// directories
763		case MKDIR_REQUEST:
764		case RMDIR_REQUEST:
765		case OPEN_DIR_REQUEST:
766		case CLOSE_DIR_REQUEST:
767		case FREE_DIR_COOKIE_REQUEST:
768		case READ_DIR_REQUEST:
769		case REWIND_DIR_REQUEST:
770		case WALK_REQUEST:
771			return false;
772		case MKDIR_REPLY:
773		case RMDIR_REPLY:
774		case OPEN_DIR_REPLY:
775		case CLOSE_DIR_REPLY:
776		case FREE_DIR_COOKIE_REPLY:
777		case READ_DIR_REPLY:
778		case REWIND_DIR_REPLY:
779		case WALK_REPLY:
780			return true;
781		// attributes
782		case OPEN_ATTR_DIR_REQUEST:
783		case CLOSE_ATTR_DIR_REQUEST:
784		case FREE_ATTR_DIR_COOKIE_REQUEST:
785		case READ_ATTR_DIR_REQUEST:
786		case REWIND_ATTR_DIR_REQUEST:
787		case READ_ATTR_REQUEST:
788		case WRITE_ATTR_REQUEST:
789		case REMOVE_ATTR_REQUEST:
790		case RENAME_ATTR_REQUEST:
791		case STAT_ATTR_REQUEST:
792			return false;
793		case OPEN_ATTR_DIR_REPLY:
794		case CLOSE_ATTR_DIR_REPLY:
795		case FREE_ATTR_DIR_COOKIE_REPLY:
796		case READ_ATTR_DIR_REPLY:
797		case REWIND_ATTR_DIR_REPLY:
798		case READ_ATTR_REPLY:
799		case WRITE_ATTR_REPLY:
800		case REMOVE_ATTR_REPLY:
801		case RENAME_ATTR_REPLY:
802		case STAT_ATTR_REPLY:
803			return true;
804		// indices
805		case OPEN_INDEX_DIR_REQUEST:
806		case CLOSE_INDEX_DIR_REQUEST:
807		case FREE_INDEX_DIR_COOKIE_REQUEST:
808		case READ_INDEX_DIR_REQUEST:
809		case REWIND_INDEX_DIR_REQUEST:
810		case CREATE_INDEX_REQUEST:
811		case REMOVE_INDEX_REQUEST:
812		case RENAME_INDEX_REQUEST:
813		case STAT_INDEX_REQUEST:
814			return false;
815		case OPEN_INDEX_DIR_REPLY:
816		case CLOSE_INDEX_DIR_REPLY:
817		case FREE_INDEX_DIR_COOKIE_REPLY:
818		case READ_INDEX_DIR_REPLY:
819		case REWIND_INDEX_DIR_REPLY:
820		case CREATE_INDEX_REPLY:
821		case REMOVE_INDEX_REPLY:
822		case RENAME_INDEX_REPLY:
823		case STAT_INDEX_REPLY:
824			return true;
825		// queries
826		case OPEN_QUERY_REQUEST:
827		case CLOSE_QUERY_REQUEST:
828		case FREE_QUERY_COOKIE_REQUEST:
829		case READ_QUERY_REQUEST:
830			return false;
831		case OPEN_QUERY_REPLY:
832		case CLOSE_QUERY_REPLY:
833		case FREE_QUERY_COOKIE_REPLY:
834		case READ_QUERY_REPLY:
835			return true;
836
837		// userland -> kernel requests
838		// notifications
839		case NOTIFY_LISTENER_REQUEST:
840		case NOTIFY_SELECT_EVENT_REQUEST:
841		case SEND_NOTIFICATION_REQUEST:
842			return true;
843		case NOTIFY_LISTENER_REPLY:
844		case NOTIFY_SELECT_EVENT_REPLY:
845		case SEND_NOTIFICATION_REPLY:
846			return false;
847		// vnodes
848		case GET_VNODE_REQUEST:
849		case PUT_VNODE_REQUEST:
850		case NEW_VNODE_REQUEST:
851		case REMOVE_VNODE_REQUEST:
852		case UNREMOVE_VNODE_REQUEST:
853		case IS_VNODE_REMOVED_REQUEST:
854			return true;
855		case GET_VNODE_REPLY:
856		case PUT_VNODE_REPLY:
857		case NEW_VNODE_REPLY:
858		case REMOVE_VNODE_REPLY:
859		case UNREMOVE_VNODE_REPLY:
860		case IS_VNODE_REMOVED_REPLY:
861			return false;
862
863		// general reply
864		case RECEIPT_ACK_REPLY:
865			return true;
866		default:
867			return false;
868	}
869}
870