1/*
2 * Copyright (c) 1999-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved
25 */
26/*
27 * Copyright (c) 1992, 1993
28 *	The Regents of the University of California.  All rights reserved.
29 *
30 * The NEXTSTEP Software License Agreement specifies the terms
31 * and conditions for redistribution.
32 *
33 *	@(#)webdav.h	8.4 (Berkeley) 1/21/94
34 */
35
36#ifndef _WEBDAV_H_INCLUDE
37#define _WEBDAV_H_INCLUDE
38
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <sys/ucred.h>
42#include <sys/vnode.h>
43#include <sys/mount.h>
44#include <sys/ioccom.h>
45
46#ifdef KERNEL
47#include <libkern/locks.h>
48	#define DEBUG 0
49#else
50	#define DEBUG 0
51#endif
52/* Webdav file operation constants */
53#define WEBDAV_LOOKUP			1
54#define WEBDAV_CREATE			2
55#define WEBDAV_OPEN				3
56#define WEBDAV_CLOSE			4
57#define WEBDAV_GETATTR			5
58#define WEBDAV_SETATTR			6
59#define WEBDAV_READ				7
60#define WEBDAV_WRITE			8
61#define WEBDAV_FSYNC			9
62#define WEBDAV_REMOVE			10
63#define WEBDAV_RENAME			11
64#define WEBDAV_MKDIR			12
65#define WEBDAV_RMDIR			13
66#define WEBDAV_READDIR			14
67#define WEBDAV_STATFS			15
68#define WEBDAV_UNMOUNT			16
69#define WEBDAV_INVALCACHES		17
70/* for the future */
71#define WEBDAV_LINK				18
72#define WEBDAV_SYMLINK			19
73#define WEBDAV_READLINK			20
74#define WEBDAV_MKNOD			21
75#define WEBDAV_GETATTRLIST		22
76#define WEBDAV_SETATTRLIST		23
77#define WEBDAV_EXCHANGE			24
78#define WEBDAV_READDIRATTR		25
79#define WEBDAV_SEARCHFS			26
80#define WEBDAV_COPYFILE			27
81#define WEBDAV_WRITESEQ			28
82#define WEBDAV_DUMP_COOKIES		29
83#define WEBDAV_CLEAR_COOKIES	30
84
85/* Webdav file type constants */
86#define WEBDAV_FILE_TYPE		1
87#define WEBDAV_DIR_TYPE			2
88
89/* The WEBDAV_MAX_IO_BUFFER_SIZE gates how many bytes we
90 * will try to read with a byte range request to the server.
91 * Because sockets are only so big we can't transfer 8192 bytes.
92 * That many bytes won't fit in a buffer so rather than having
93 * webdav_sendmsg wait for all data, it would have to loop.	 Limiting
94 * at 8000 works (based on emprical study on Darwin). If you are porting
95 * this code to another platform or if the default socket buffer size
96 * changes you may need to change this constan to implement the looping.
97 * None of this would be necessary if Darwin's soreserve actually did reserve
98 * space rather than just enforcing limits
99 */
100
101#define WEBDAV_MAX_IO_BUFFER_SIZE 8000	/* Gates byte read optimization */
102
103/* Shared (kernel & processs) WebDAV structures */
104
105typedef int webdav_filetype_t;
106
107// XXX Dependency on __DARWIN_64_BIT_INO_T
108// We cannot pass ino_t back and forth between the kext and
109// webdavfs_agent, because ino_t is in flux right now.
110// In user space ino_t is 64-bits, but 32 bits in kernel space.
111// So we have to define our own type for now (webdav_ino_t).
112//
113// This was the root cause of:
114// <rdar://problem/6491194> 10A245+10A246: WebDAV FS complains about file names being too long.
115//
116// Once ino_t is identical in length for kernel and user space, then
117// we can get rid of webdav_ino_t and just use ino_t exclusively.
118//
119typedef uint32_t webdav_ino_t;
120
121/* Shared (kernel & process) WebDAV defninitions */
122
123/*
124 * An opaque_id is used to find a file system object in userland.
125 * Lookup returns it. The rest of the operations which act upon a file system
126 * object use it. If the file system object in userland goes away, the opaque_id
127 * will be invalidated and messages to userland will fail with ESTALE.
128 * The opaque_id 0 (kInvalidOpaqueID) is never valid.
129 */
130#define kInvalidOpaqueID   0
131typedef uint32_t opaque_id;
132
133/*
134 * IMPORTANT: struct user_webdav_args, struct webdav_args, and webdav_mount()
135 * must all be changed if the structure changes.
136 */
137
138/*
139 * kCurrentWebdavArgsVersion MUST be incremented anytime changes are made in
140 * either the WebDAV file system's kernel or user-land code which require both
141 * executables to be released as a set.
142 */
143#define kCurrentWebdavArgsVersion 5
144
145#pragma options align=packed
146
147struct webdav_vfsstatfs
148{
149	uint32_t	f_bsize;	/* fundamental file system block size */
150	uint32_t	f_iosize;	/* optimal transfer block size */
151	uint64_t	f_blocks;	/* total data blocks in file system */
152	uint64_t	f_bfree;	/* free blocks in fs */
153	uint64_t	f_bavail;	/* free blocks avail to non-superuser */
154	uint64_t	f_files;	/* total file nodes in file system */
155	uint64_t	f_ffree;	/* free file nodes in fs */
156};
157
158struct user_webdav_args
159{
160	user_addr_t pa_mntfromname;					/* mntfromname */
161	int	pa_version;								/* argument struct version */
162	int pa_socket_namelen;						/* Socket to server name length */
163	user_addr_t pa_socket_name;					/* Socket to server name */
164	user_addr_t pa_vol_name;					/* volume name */
165	u_int32_t pa_flags;							/* flag bits for mount */
166	u_int32_t pa_server_ident;					/* identifies some (not all) types of servers we are connected to */
167	opaque_id pa_root_id;						/* root opaque_id */
168	webdav_ino_t pa_root_fileid;				/* root fileid */
169	uid_t		pa_uid;							/* effective uid of the mounting user */
170	gid_t		pa_gid;							/* effective gid of the mounting user */
171	off_t pa_dir_size;							/* size of directories */
172	/* pathconf values: >=0 to return value; -1 if not supported */
173	int pa_link_max;							/* maximum value of a file's link count */
174	int pa_name_max;							/* The maximum number of bytes in a file name (does not include null at end) */
175	int pa_path_max;							/* The maximum number of bytes in a relative pathname (does not include null at end) */
176	int pa_pipe_buf;							/* The maximum number of bytes that can be written atomically to a pipe (usually PIPE_BUF if supported) */
177	int pa_chown_restricted;					/* Return _POSIX_CHOWN_RESTRICTED if appropriate privileges are required for the chown(2) */
178	int pa_no_trunc;							/* Return _POSIX_NO_TRUNC if file names longer than KERN_NAME_MAX are truncated */
179	/* end of webdav_args version 1 */
180	struct webdav_vfsstatfs pa_vfsstatfs;				/* need this to fill out the statfs struct during the mount */
181};
182
183struct webdav_args
184{
185	char *pa_mntfromname;						/* mntfromname */
186	int	pa_version;								/* argument struct version */
187	int pa_socket_namelen;						/* Socket to server name length */
188	struct sockaddr *pa_socket_name;			/* Socket to server name */
189	char *pa_vol_name;							/* volume name */
190	u_int32_t pa_flags;							/* flag bits for mount */
191	u_int32_t pa_server_ident;					/* identifies some (not all) types of servers we are connected to */
192	opaque_id pa_root_id;						/* root opaque_id */
193	webdav_ino_t pa_root_fileid;				/* root fileid */
194	uid_t		pa_uid;							/* effective uid of the mounting user */
195	gid_t		pa_gid;							/* effective gid of the mounting user */
196	off_t pa_dir_size;							/* size of directories */
197	/* pathconf values: >=0 to return value; -1 if not supported */
198	int pa_link_max;							/* maximum value of a file's link count */
199	int pa_name_max;							/* The maximum number of bytes in a file name (does not include null at end) */
200	int pa_path_max;							/* The maximum number of bytes in a relative pathname (does not include null at end) */
201	int pa_pipe_buf;							/* The maximum number of bytes that can be written atomically to a pipe (usually PIPE_BUF if supported) */
202	int pa_chown_restricted;					/* Return _POSIX_CHOWN_RESTRICTED if appropriate privileges are required for the chown(2) */
203	int pa_no_trunc;							/* Return _POSIX_NO_TRUNC if file names longer than KERN_NAME_MAX are truncated */
204	/* end of webdav_args version 1 */
205	struct webdav_vfsstatfs pa_vfsstatfs;				/* need this to fill out the statfs struct during the mount */
206};
207
208
209/* Defines for webdav_args pa_flags field */
210#define WEBDAV_SUPPRESSALLUI	0x00000001		/* SuppressAllUI flag */
211#define WEBDAV_SECURECONNECTION	0x00000002		/* Secure connection flag (the connection to the server is secure) */
212
213/* Defines for webdav_args pa_server_ident field */
214#define WEBDAV_IDISK_SERVER			0x00000001
215#define WEBDAV_MICROSOFT_IIS_SERVER	0x00000002
216
217struct webdav_cred
218{
219	uid_t pcr_uid;								/* From ucred */
220};
221
222/* WEBDAV_LOOKUP */
223struct webdav_request_lookup
224{
225	struct webdav_cred pcr;				/* user and groups */
226	opaque_id		dir_id;				/* directory to search */
227	int				force_lookup;		/* if TRUE, don't use a cached lookup */
228	uint32_t		name_length;		/* length of name */
229	char			name[];				/* filename to find */
230};
231
232struct webdav_timespec64
233{
234	uint64_t	tv_sec;
235	uint64_t	tv_nsec;
236};
237
238struct webdav_reply_lookup
239{
240	opaque_id		obj_id;				/* opaque_id of object corresponding to name */
241	webdav_ino_t	obj_fileid;			/* object's file ID number */
242	webdav_filetype_t obj_type;			/* WEBDAV_FILE_TYPE or WEBDAV_DIR_TYPE */
243	struct webdav_timespec64 obj_atime;		/* time of last access */
244	struct webdav_timespec64 obj_mtime;		/* time of last data modification */
245	struct webdav_timespec64 obj_ctime;		/* time of last file status change */
246	struct webdav_timespec64 obj_createtime; /* file creation time */
247	off_t			obj_filesize;		/* filesize of object */
248};
249
250/* WEBDAV_CREATE */
251struct webdav_request_create
252{
253	struct webdav_cred pcr;				/* user and groups */
254	opaque_id		dir_id;				/* The opaque_id for the directory in which the file is to be created */
255	mode_t			mode;				/* file type and initial file access permissions for the file */
256	uint32_t		name_length;		/* length of name */
257	char			name[];				/* The name that is to be associated with the created file */
258};
259
260struct webdav_reply_create
261{
262	opaque_id		obj_id;				/* opaque_id of file corresponding to name */
263	webdav_ino_t	obj_fileid;			/* file's file ID number */
264};
265
266/* WEBDAV_MKDIR */
267struct webdav_request_mkdir
268{
269	struct webdav_cred pcr;				/* user and groups */
270	opaque_id		dir_id;				/* The opaque_id for the directory in which the file is to be created */
271	mode_t			mode;				/* file type and initial file access permissions for the file */
272	uint32_t		name_length;		/* length of name */
273	char			name[];				/* The name that is to be associated with the created directory */
274};
275
276struct webdav_reply_mkdir
277{
278	opaque_id		obj_id;				/* opaque_id of directory corresponding to name */
279	webdav_ino_t	obj_fileid;			/* directory's file ID number */
280};
281
282/* WEBDAV_OPEN */
283struct webdav_request_open
284{
285	struct webdav_cred pcr;				/* user and groups */
286	opaque_id		obj_id;				/* opaque_id of object */
287	int				flags;				/* file access flags (O_RDONLY, O_WRONLY, etc.) */
288	int				ref;				/* the reference to the webdav object that the cache object should be associated with */
289};
290
291struct webdav_reply_open
292{
293	pid_t			pid;				/* process ID of file system daemon (for matching to ref's pid) */
294};
295
296/* WEBDAV_CLOSE */
297struct webdav_request_close
298{
299	struct webdav_cred pcr;				/* user and groups */
300	opaque_id		obj_id;				/* opaque_id of object */
301};
302
303struct webdav_reply_close
304{
305};
306
307struct webdav_stat {
308	dev_t	 	st_dev;		/* [XSI] ID of device containing file */
309	webdav_ino_t st_ino;	/* [XSI] File serial number */
310	mode_t	 	st_mode;	/* [XSI] Mode of file (see below) */
311	nlink_t		st_nlink;	/* [XSI] Number of hard links */
312	uid_t		st_uid;		/* [XSI] User ID of the file */
313	gid_t		st_gid;		/* [XSI] Group ID of the file */
314	dev_t		st_rdev;	/* [XSI] Device ID */
315	struct	webdav_timespec64 st_atimespec;	/* time of last access */
316	struct	webdav_timespec64 st_mtimespec;	/* time of last data modification */
317	struct	webdav_timespec64 st_ctimespec;	/* time of last status change */
318	struct	webdav_timespec64 st_createtimespec;	/* time file was created */
319	off_t		st_size;	/* [XSI] file size, in bytes */
320	blkcnt_t	st_blocks;	/* [XSI] blocks allocated for file */
321	blksize_t	st_blksize;	/* [XSI] optimal blocksize for I/O */
322	uint32_t	st_flags;	/* user defined flags for file */
323	uint32_t	st_gen;		/* file generation number */
324};
325
326/* WEBDAV_GETATTR */
327struct webdav_request_getattr
328{
329	struct webdav_cred pcr;				/* user and groups */
330	opaque_id		obj_id;				/* opaque_id of object */
331};
332
333struct webdav_reply_getattr
334{
335	struct webdav_stat	obj_attr;			/* attributes for the object */
336};
337
338/* WEBDAV_SETATTR XXX not needed at this time */
339struct webdav_request_setattr
340{
341	struct webdav_cred pcr;				/* user and groups */
342	opaque_id		obj_id;				/* opaque_id of object */
343	struct stat		new_obj_attr;		/* new attributes of the object */
344};
345
346struct webdav_reply_setattr
347{
348};
349
350/* WEBDAV_READ */
351struct webdav_request_read
352{
353	struct webdav_cred pcr;				/* user and groups */
354	opaque_id		obj_id;				/* opaque_id of file object */
355	off_t			offset;				/* position within the file object at which the read is to begin */
356	uint64_t		count;				/* number of bytes of data to be read (limited to WEBDAV_MAX_IO_BUFFER_SIZE (8000-bytes)) */
357};
358
359struct webdav_reply_read
360{
361};
362
363/* WEBDAV_WRITE XXX not needed at this time */
364struct webdav_request_write
365{
366	struct webdav_cred pcr;				/* user and groups */
367	opaque_id		obj_id;				/* opaque_id of file object */
368	off_t			offset;				/* position within the file object at which the write is to begin */
369	uint64_t		count;				/* number of bytes of data to be written (limited to WEBDAV_MAX_IO_BUFFER_SIZE (8000-bytes)) */
370	char			data[];				/* data to be written to the file object */
371};
372
373struct webdav_reply_write
374{
375	uint64_t		count;				/* number of bytes of data written to the file */
376};
377
378/* WEBDAV_FSYNC */
379struct webdav_request_fsync
380{
381	struct webdav_cred pcr;				/* user and groups */
382	opaque_id		obj_id;				/* opaque_id of object */
383};
384
385struct webdav_reply_fsync
386{
387};
388
389/* WEBDAV_REMOVE */
390struct webdav_request_remove
391{
392	struct webdav_cred pcr;				/* user and groups */
393	opaque_id		obj_id;				/* opaque_id of entry to remove */
394};
395
396struct webdav_reply_remove
397{
398};
399
400/* WEBDAV_RMDIR */
401struct webdav_request_rmdir
402{
403	struct webdav_cred pcr;				/* user and groups */
404	opaque_id		obj_id;				/* opaque_id of directory object to remove */
405};
406
407struct webdav_reply_rmdir
408{
409};
410
411/* WEBDAV_RENAME */
412struct webdav_request_rename
413{
414	struct webdav_cred pcr;				/* user and groups */
415	opaque_id		from_dir_id;		/* opaque_id for the directory from which the entry is to be renamed */
416	opaque_id		from_obj_id;		/* opaque_id for the object to be renamed */
417	opaque_id		to_dir_id;			/* opaque_id for the directory to which the object is to be renamed */
418	opaque_id		to_obj_id;			/* opaque_id for the object's new location if it exists (may be NULL) */
419	uint32_t		to_name_length;		/* length of to_name */
420	char			to_name[];			/* new name for the object */
421};
422
423struct webdav_reply_rename
424{
425};
426
427/* WEBDAV_READDIR */
428struct webdav_request_readdir
429{
430	struct webdav_cred pcr;				/* user and groups */
431	opaque_id		obj_id;				/* opaque_id of directory to read */
432	int				cache;				/* if TRUE, perform additional caching */
433};
434
435struct webdav_reply_readdir
436{
437};
438
439/* WEBDAV_STATFS */
440
441struct webdav_statfs {
442	uint64_t	f_bsize;		/* fundamental file system block size */
443	uint64_t	f_iosize;		/* optimal transfer block size */
444	uint64_t	f_blocks;		/* total data blocks in file system */
445	uint64_t	f_bfree;		/* free blocks in fs */
446	uint64_t	f_bavail;		/* free blocks avail to non-superuser */
447	uint64_t	f_files;		/* total file nodes in file system */
448	uint64_t	f_ffree;		/* free file nodes in fs */
449};
450
451struct webdav_request_statfs
452{
453	struct webdav_cred pcr;				/* user and groups */
454	opaque_id	root_obj_id;			/* opaque_id of the root directory */
455};
456
457struct webdav_reply_statfs
458{
459	struct webdav_statfs   fs_attr;		/* file system information */
460										/*
461										 * (required: f_bsize, f_iosize, f_blocks, f_bfree,
462										 * f_bavail, f_files, f_ffree. The kext will either copy
463										 * the remaining info from the mount struct, or the cached
464										 * statfs struct in the mount struct IS the destination.
465										 */
466};
467
468/* WEBDAV_UNMOUNT */
469struct webdav_request_unmount
470{
471	struct webdav_cred pcr;				/* user and groups */
472};
473
474struct webdav_reply_unmount
475{
476};
477
478/* WEBDAV_INVALCACHES */
479struct webdav_request_invalcaches
480{
481	struct webdav_cred pcr;				/* user and groups */
482};
483
484struct webdav_reply_invalcaches
485{
486};
487
488/* WEBDAV_SHOW_COOKIES */
489/* WEBDAV_RESET_COOKIES */
490struct webdav_request_cookies {
491	struct webdav_cred pcr;				/* user and groups */
492};
493
494struct webdav_reply_cookies {
495
496};
497
498struct webdav_request_writeseq
499{
500	struct webdav_cred pcr;				/* user and groups */
501	opaque_id		obj_id;				/* opaque_id of file object */
502	off_t			offset;				/* position within the file object at which the write is to begin */
503	off_t			count;				/* number of bytes of data to be written (limited to WEBDAV_MAX_IO_BUFFER_SIZE (8000-bytes)) */
504	uint64_t		file_len;			/* length of the file after all sequential writes are done */
505	uint32_t		is_retry;			/* non-zero indicates this request is a retry due to an EPIPE */
506};
507
508struct webdav_reply_writeseq
509{
510	uint64_t		count;				/* number of bytes of data written to the file */
511};
512
513union webdav_request
514{
515	struct webdav_request_lookup	lookup;
516	struct webdav_request_create	create;
517	struct webdav_request_open		open;
518	struct webdav_request_close		close;
519	struct webdav_request_getattr   getattr;
520	struct webdav_request_setattr	setattr;
521	struct webdav_request_read		read;
522	struct webdav_request_write		write;
523	struct webdav_request_fsync		fsync;
524	struct webdav_request_remove	remove;
525	struct webdav_request_rmdir		rmdir;
526	struct webdav_request_rename	rename;
527	struct webdav_request_readdir	readdir;
528	struct webdav_request_statfs	statfs;
529	struct webdav_request_invalcaches invalcaches;
530	struct webdav_request_writeseq  writeseq;
531};
532
533union webdav_reply
534{
535	struct webdav_reply_lookup		lookup;
536	struct webdav_reply_create		create;
537	struct webdav_reply_open		open;
538	struct webdav_reply_close		close;
539	struct webdav_reply_getattr		getattr;
540	struct webdav_reply_setattr		setattr;
541	struct webdav_reply_read		read;
542	struct webdav_reply_write		write;
543	struct webdav_reply_fsync		fsync;
544	struct webdav_reply_remove		remove;
545	struct webdav_reply_rmdir		rmdir;
546	struct webdav_reply_rename		rename;
547	struct webdav_reply_readdir		readdir;
548	struct webdav_reply_statfs		statfs;
549	struct webdav_reply_invalcaches	invalcaches;
550	struct webdav_reply_writeseq	writeseq;
551};
552
553#define UNKNOWNUID ((uid_t)99)
554
555/*
556 * The WEBDAV_CONNECTION_DOWN_MASK bit is set by the code in send_reply() in
557 * activate.c in the int result when the mount_webdav daemon determines it cannot
558 * communicate with the remote WebDAV server. webdav_sendmsg() and webdav_open() in
559 * webdav_vnops.c check that bit to determine if the connection is up or down.
560 */
561#define WEBDAV_CONNECTION_DOWN_MASK	0x80000000
562
563/*
564 * fsctl(2) values for WebDAV FS
565 */
566
567/*
568 * WEBDAVIOC_INVALIDATECACHES commmand passed to fsctl(2) causes WebDAV FS to
569 * revalidate cached files with the WebDAV server and to invalidate all
570 * all cached stat data.
571 * example:
572 * result = fsctl(path, WEBDAVIOC_INVALIDATECACHES, NULL, 0);
573 */
574#define	WEBDAVIOC_INVALIDATECACHES	_IO('w', 1)
575#define	WEBDAV_INVALIDATECACHES		IOCBASECMD(WEBDAVIOC_INVALIDATECACHES)
576
577/*
578 * The WEBDAVIOC_WRITE_SEQUENTIAL command passed to fsctl(2) causes WebDAV FS to
579 * enable Write Sequential mode on a vnode that is opened for writing.
580 * The only parameter is a struct WebdavWriteSequential, that has a single field
581 * to indicate the total length in bytes that will be written.
582 *
583 * Example:
584 *
585 *	struct WebdavWriteSequential {
586 *		uint64_t file_len;
587 *	};
588 *
589 *	struct WebdavWriteSequential req;
590 *	req->file_len = 8192; // Will write 8k
591 *	result = fsctl(path, WEBDAVIOC_WRITE_SEQUENTIAL, &req, 0);
592 *
593 *	Return values:
594 *  0	-	Success
595 *	EBUSY	-	File is already in Write Sequential mode.
596 */
597struct WebdavWriteSequential {
598		uint64_t file_len;
599};
600
601#pragma options align=reset
602
603#define WEBDAVIOC_WRITE_SEQUENTIAL	_IOW('z', 19, struct WebdavWriteSequential)
604#define WEBDAV_WRITE_SEQUENTIAL		IOCBASECMD(WEBDAVIOC_WRITE_SEQUENTIAL)
605
606#define WEBDAVIOC_SHOW_COOKIES		_IOW('x', 29, int)
607#define WEBDAV_SHOW_COOKIES			IOCBASECMD(WEBDAVIOC_SHOW_COOKIES)
608
609#define WEBDAVIOC_RESET_COOKIES		_IOW('x', 28, int)
610#define WEBDAV_RESET_COOKIES		IOCBASECMD(WEBDAVIOC_RESET_COOKIES)
611
612/*
613 * Sysctl values for WebDAV FS
614 */
615
616/*
617 * If name[0] is WEBDAV_ASSOCIATECACHEFILE_SYSCTL, then
618 *		name[1] = a pointer to a struct open_associatecachefile
619 *		name[2] = fd of cache file
620 */
621#define WEBDAV_ASSOCIATECACHEFILE_SYSCTL   1
622/*
623 * If name[0] is WEBDAV_NOTIFY_RECONNECTED_SYSCTL, then
624 *		name[1] = fsid.value[0]		// fsid byte 0 of reconnected file system
625 *		name[2] = fsid.value[1]		// fsid byte 1 of reconnected file system
626 */
627#define WEBDAV_NOTIFY_RECONNECTED_SYSCTL   2
628
629#define WEBDAV_MAX_KEXT_CONNECTIONS 128			/* maximum number of open connections to user-land server */
630
631#ifdef KERNEL
632
633struct webdavmount
634{
635	vnode_t pm_root;							/* Root node */
636	u_int32_t pm_status;						/* status bits for this mounted structure */
637	struct mount *pm_mountp;					/* vfs structure for this filesystem */
638	char *pm_vol_name;							/* volume name */
639	struct sockaddr *pm_socket_name;			/* Socket to server name */
640	u_int32_t pm_open_connections;				/* number of connections opened to user-land server */
641	u_int32_t pm_server_ident;					/* identifies some (not all) types of servers we are connected to */
642	off_t pm_dir_size;							/* size of directories */
643	/* pathconf values: >=0 to return value; -1 if not supported */
644	int pm_link_max;							/* maximum value of a file's link count (1 for file systems that do not support link counts) */
645	int pm_name_max;							/* The maximum number of bytes in a file name (does not include null at end) */
646	int pm_path_max;							/* The maximum number of bytes in a relative pathname (does not include null at end) */
647	int pm_pipe_buf;							/* The maximum number of bytes that can be written atomically to a pipe (usually PIPE_BUF if supported) */
648	int pm_chown_restricted;					/* Return _POSIX_CHOWN_RESTRICTED if appropriate privileges are required for the chown(2); otherwise 0 */
649	int pm_no_trunc;							/* Return _POSIX_NO_TRUNC if file names longer than KERN_NAME_MAX are truncated; otherwise 0 */
650	size_t pm_iosize;							/* saved iosize to use */
651	uid_t		pm_uid;						/* effective uid of the mounting user */
652	gid_t		pm_gid;						/* effective gid of the mounting user */
653	lck_mtx_t pm_mutex;							/* Protects pm_status adn pm_open_connections fields */
654	lck_mtx_t pm_renamelock;                    			/* Mount rename lock */
655};
656
657struct webdavnode
658{
659	lck_rw_t pt_rwlock;							/* this webdavnode's lock */
660	LIST_ENTRY(webdavnode) pt_hash;				/* Hash chain. */
661	struct mount *pt_mountp;					/* vfs structure for this filesystem */
662	vnode_t pt_parent;							/* Pointer to parent vnode */
663	vnode_t pt_vnode;							/* Pointer to vnode */
664	vnode_t pt_cache_vnode;						/* Pointer to cached file vnode */
665	opaque_id pt_obj_id;						/* opaque_id from lookup */
666	webdav_ino_t pt_fileid;						/* file id */
667
668	/* timestamp cache */
669	struct webdav_timespec64 pt_atime;					/* time of last access */
670	struct webdav_timespec64 pt_mtime;					/* time of last data modification */
671	struct webdav_timespec64 pt_ctime;					/* time of last file status change */
672	struct webdav_timespec64 pt_createtime;				/* file creation time */
673	struct webdav_timespec64 pt_mtime_old;				/* previous pt_mtime value (directory nodes only, used for negative name cache) */
674	struct webdav_timespec64 pt_timestamp_refresh;		/* time of last timestamp refresh */
675
676	off_t pt_filesize;							/* what we think the filesize is */
677	u_int32_t pt_status;						/* WEBDAV_DIRTY, etc */
678	u_int32_t pt_opencount;						/* reference count of opens */
679
680	/* for Write Sequential mode */
681	u_int32_t pt_opencount_write;				/* count of opens for writing */
682	u_int32_t pt_writeseq_enabled;				/* TRUE if node Write Sequential mode is enabled */
683	off_t pt_writeseq_offset;				/* offset we're expecting for the next write */
684	uint64_t pt_writeseq_len;				/* total length in bytes that will be written in Write Sequential mode */
685
686	/* SMP debug variables */
687	void *pt_lastvop;							/* tracks last operation that locked this webdavnode */
688	void *pt_activation;						/* tracks last thread that locked this webdavnode */
689    u_int32_t pt_lockState;						/* current lock state */
690};
691
692struct open_associatecachefile
693{
694	vnode_t cachevp;
695	pid_t   pid;
696};
697
698/* Defines for webdavnode pt_status field */
699
700#define WEBDAV_DIRTY			0x00000001		/* Indicates webdavnode has data which has not been flushed to cache file */
701#define WEBDAV_ACCESSED			0x00000002		/* Indicates file has been accessed - used by webdav_gettr to determine dates */
702#define WEBDAV_ONHASHLIST		0x00000004		/* Indicates webdavnode is on the hash chain */
703#define WEBDAV_DELETED			0x00000008		/* Indicates that webdav file (which is still referenced) has been deleted */
704#define WEBDAV_DIR_NOT_LOADED   0x00000010		/* Indicates that an open directory is empty and needs to be populated from the server */
705#define WEBDAV_INIT				0x00000020		/* Indicates that the webdavnode is in the process of being initialized */
706#define WEBDAV_WAITINIT			0x00000040		/* Indicates that someone is sleeping (on webdavnode) waiting for initialization to finish */
707#define WEBDAV_ISMAPPED			0x00000080		/* Indicates that the file is mapped */
708#define WEBDAV_WASMAPPED		0x00000100		/* Indicates that the file is or was mapped */
709#define WEBDAV_NEGNCENTRIES		0x00000200		/* Indicates one or more negative name cache entries exist (directory nodes only) */
710
711/* Defines for webdavmount pm_status field */
712
713#define WEBDAV_MOUNT_SUPPORTS_STATFS 0x00000001	/* Indicates that the server supports quata and quota used properties */
714#define WEBDAV_MOUNT_STATFS 0x00000002			/* statfs is in progress */
715#define WEBDAV_MOUNT_STATFS_WANTED 0x00000004	/* statfs wakeup is wanted */
716#define WEBDAV_MOUNT_TIMEO 0x00000008			/* connection to webdav server was lost */
717#define WEBDAV_MOUNT_DEAD 0x00000010			/* file system is dead. */
718#define WEBDAV_MOUNT_SUPPRESS_ALL_UI 0x00000020	/* suppress UI when connection is lost */
719#define WEBDAV_MOUNT_CONNECTION_WANTED 0x000000040 /* wakeup is wanted to start another connection with user-land server */
720#define WEBDAV_MOUNT_SECURECONNECTION 0x000000080 /* the connection to the server is secure */
721
722/* Webdav sizes for statfs */
723
724#define WEBDAV_NUM_BLOCKS -1					/* not supported */
725#define WEBDAV_FREE_BLOCKS	-1					/* not supported */
726#define WEBDAV_NUM_FILES 65535					/* Like HFS */
727#define WEBDAV_FREE_FILES (WEBDAV_NUM_FILES - 2) /* Used a couple */
728
729/* Webdav status macros */
730
731#define VFSTOWEBDAV(mp) ((struct webdavmount *)(vfs_fsprivate(mp)))
732#define VTOWEBDAV(vp) ((struct webdavnode *)(vnode_fsnode(vp)))
733#define WEBDAVTOV(pt) ((pt)->pt_vnode)
734#define WEBDAVTOMP(pt) (vnode_mount(WEBDAVTOV(pt)))
735
736/* Other defines */
737
738
739
740/*
741 * In webdav_read and webdav_pagein, webdav_read_bytes is called if the part of
742 * file we need hasn't been downloaded from the server yet. However, since we're
743 * already downloading the file, there's already data in the stream so reading
744 * a range is counterproductive if we'll have downloaded the part we need (in the
745 * stream) by the time webdav_read_bytes returns the data out of band.
746 * Apache's mod_dav buffers 32K in the stream, so that's we'll use.
747 */
748#define WEBDAV_WAIT_IF_WITHIN	32768
749
750/*
751 * There are several loops where the code waits for a cache file to be downloaded,
752 * or for a specific part of the cache file to be downloaded. This constant controls
753 * how often the cache vnode is polled (with VNOP_GETATTR). The less often we poll,
754 * the higher the latency between getting data and using it.
755 *
756 * A network connection with 35mbps (maximum cable) can give us a page every millisecond.
757 * A network connection with 3mbps (typical capped cable or high speed DSL) can give us a page every 10 milliseconds.
758 * For typical home networks over cable or DSL, 10 ms should be OK. Thus... (10 * 1000 * 1000) nanoseconds.
759 */
760#define WEBDAV_WAIT_FOR_PAGE_TIME (10 * 1000 * 1000)
761
762/* the number of seconds soreceive() should block
763 * before rechecking the server process state
764 */
765#define WEBDAV_SO_RCVTIMEO_SECONDS 10
766
767/* How many times webdav_sendmsg() will block in soreceive()
768 * before timing out the request.  The total
769 * amount of seconds is WEBDAV_SO_RCVTIMEO_SECONDS * WEBDAV_MAX_SOCK_RCV_TIMEOUTS
770 */
771#define WEBDAV_MAX_SOCK_RCV_TIMEOUTS 9
772
773/*
774 * Used only for negative name caching, TIMESTAMP_NEGNCACHE_TIMEOUT is used by the webdav_vnop_lookup routine
775 * to determine how often to fetch attributes from the server to check if a directory has been modified (va_mod_time timestamp).
776 * We purge all negative name cache entries when the modification time of a directory has changed.
777 *
778 */
779#define TIMESTAMP_CACHE_TIMEOUT 10
780
781#if 0
782	#define START_MARKER(str) \
783	{ \
784		log_vnop_start(str); \
785	}
786	#define RET_ERR(str, error) \
787	{ \
788		/*if (error)*/ \
789			log_vnop_error(str, error); \
790		return(error); \
791	}
792extern void log_vnop_start(char *str);
793extern void log_vnop_error(char *str, int error);
794#else
795	#define START_MARKER(str)
796	#define RET_ERR(str, error) return(error)
797#endif
798
799
800extern int( **webdav_vnodeop_p)();
801extern void webdav_hashinit(void);
802extern void webdav_hashdestroy(void);
803extern void webdav_hashrem(struct webdavnode *);
804extern void webdav_hashins(struct webdavnode *);
805extern struct webdavnode *webdav_hashget(struct mount *mp, webdav_ino_t fileid, struct webdavnode *pt_new, uint32_t *inserted);
806
807extern void webdav_copy_creds(vfs_context_t context, struct webdav_cred *dest);
808extern int webdav_sendmsg(int vnop, struct webdavmount *fmp,
809	void *request, size_t requestsize,
810	void *vardata, size_t vardatasize,
811	int *result, void *reply, size_t replysize);
812extern int webdav_get(
813	struct mount *mp,			/* mount point */
814	vnode_t dvp,				/* parent vnode */
815	int markroot,				/* if 1, mark as root vnode */
816	struct componentname *cnp,  /* componentname */
817	opaque_id obj_id,			/* object's opaque_id */
818	webdav_ino_t obj_fileid,	/* object's file ID number */
819	enum vtype obj_vtype,		/* VREG or VDIR */
820	struct webdav_timespec64 obj_atime,  /* time of last access */
821	struct webdav_timespec64 obj_mtime,  /* time of last data modification */
822	struct webdav_timespec64 obj_ctime,  /* time of last file status change */
823	struct webdav_timespec64 obj_createtime,  /* file creation time */
824	off_t obj_filesize,			/* object's filesize */
825	vnode_t *vpp);				/* vnode returned here */
826
827extern int webdav_assign_ref(struct open_associatecachefile *associatecachefile, int *ref);
828extern void webdav_release_ref(int ref);
829extern char webdav_name[MFSNAMELEN];
830
831#endif /* KERNEL */
832
833#endif /*ifndef _WEBDAV_H_INCLUDE */
834
835