root/sys/fs/p9fs/p9_protocol.h
/*-
 * Copyright (c) 2017 Juniper Networks, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/* File contains 9P protocol definitions */

#ifndef FS_P9FS_P9_PROTOCOL_H
#define FS_P9FS_P9_PROTOCOL_H

#include <sys/types.h>

/* 9P message types */
enum p9_cmds_t {
        P9PROTO_TLERROR = 6,    /* not used */
        P9PROTO_RLERROR,        /* response for any failed request */
        P9PROTO_TSTATFS = 8,    /* file system status request */
        P9PROTO_RSTATFS,        /* file system status response */
        P9PROTO_TLOPEN = 12,    /* open a file (9P2000.L) */
        P9PROTO_RLOPEN,         /* response to opne request (9P2000.L) */
        P9PROTO_TLCREATE = 14,  /* prepare for handle for I/O on a new file (9P2000.L) */
        P9PROTO_RLCREATE,       /* response with file access information (9P2000.L) */
        P9PROTO_TSYMLINK = 16,  /* symlink creation request */
        P9PROTO_RSYMLINK,       /* symlink creation response */
        P9PROTO_TMKNOD = 18,    /* create a special file object request */
        P9PROTO_RMKNOD,         /* create a special file object response */
        P9PROTO_TRENAME = 20,   /* rename a file request */
        P9PROTO_RRENAME,        /* rename a file response */
        P9PROTO_TREADLINK = 22, /* request to read value of symbolic link */
        P9PROTO_RREADLINK,      /* response to read value of symbolic link request */
        P9PROTO_TGETATTR = 24,  /* get file attributes request */
        P9PROTO_RGETATTR,       /* get file attributes response */
        P9PROTO_TSETATTR = 26,  /* set file attributes request */
        P9PROTO_RSETATTR,       /* set file attributes response */
        P9PROTO_TXATTRWALK = 30,/* request to read extended attributes */
        P9PROTO_RXATTRWALK,     /* response from server with attributes */
        P9PROTO_TXATTRCREATE = 32,/* request to set extended attribute */
        P9PROTO_RXATTRCREATE,   /* response from server for setting extended attribute */
        P9PROTO_TREADDIR = 40,  /* request to read a directory */
        P9PROTO_RREADDIR,       /* response from server for read request */
        P9PROTO_TFSYNC = 50,    /* request to flush an cached data to disk */
        P9PROTO_RFSYNC,         /* response when cache dat is flushed */
        P9PROTO_TLOCK = 52,     /* acquire or release a POSIX record lock */
        P9PROTO_RLOCK,          /* response with the status of the lock */
        P9PROTO_TGETLOCK = 54,  /* request to check for presence of a POSIX record lock */
        P9PROTO_RGETLOCK,       /* response with the details of the lock if acquired */
        P9PROTO_TLINK = 70,     /* request to create hard link */
        P9PROTO_RLINK,          /* create hard link response */
        P9PROTO_TMKDIR = 72,    /* create a directory request */
        P9PROTO_RMKDIR,         /* create a directory response */
        P9PROTO_TRENAMEAT = 74, /* request to rename a file or directory */
        P9PROTO_RRENAMEAT,      /* reponse to rename request */
        P9PROTO_TUNLINKAT = 76, /* unlink a file or directory */
        P9PROTO_RUNLINKAT,      /* reponse to unlink request */
        P9PROTO_TVERSION = 100, /* request for version handshake */
        P9PROTO_RVERSION,       /* response for version handshake */
        P9PROTO_TAUTH = 102,    /* request to establish authentication channel */
        P9PROTO_RAUTH,          /* response with authentication information */
        P9PROTO_TATTACH = 104,  /* establish a user access to a file system*/
        P9PROTO_RATTACH,        /* response with top level handle to file hierarchy */
        P9PROTO_TERROR = 106,   /* not used */
        P9PROTO_RERROR,         /* response for any failed request */
        P9PROTO_TFLUSH = 108,   /* request to abort a previous request */
        P9PROTO_RFLUSH,         /* response when previous request has been cancelled */
        P9PROTO_TWALK = 110,    /* descend a directory hierarchy */
        P9PROTO_RWALK,          /* response with new handle for position within hierarchy */
        P9PROTO_TOPEN = 112,    /* prepare file handle for I/O for an existing file */
        P9PROTO_ROPEN,          /* response with file access information */
        P9PROTO_TCREATE = 114,  /* prepare for handle for I/O on a new file */
        P9PROTO_RCREATE,        /* response with file access information */
        P9PROTO_TREAD = 116,    /* request to transfer data from a file */
        P9PROTO_RREAD,          /* response with data requested */
        P9PROTO_TWRITE = 118,   /* request to transfer data to a file */
        P9PROTO_RWRITE,         /* response with how much data was written to the file */
        P9PROTO_TCLUNK = 120,   /* forget about a handle to a file within the File System */
        P9PROTO_RCLUNK,         /* response from the server for forgetting the file handle */
        P9PROTO_TREMOVE = 122,  /* request to remove a file */
        P9PROTO_RREMOVE,        /* response when server has removed the file */
        P9PROTO_TSTAT = 124,    /* request file entity attributes */
        P9PROTO_RSTAT,          /* response with file entity attributes */
        P9PROTO_TWSTAT = 126,   /* request to update file entity attributes */
        P9PROTO_RWSTAT,         /* response when file entity attributes are updated */
};

/* File Open Modes */
enum p9_open_mode_t {
        P9PROTO_OREAD = 0x00,   /* open file for reading only */
        P9PROTO_OWRITE = 0x01,  /* open file for writing only */
        P9PROTO_ORDWR = 0x02,   /* open file for both reading and writing */
        P9PROTO_OEXEC = 0x03,   /* open file for execution */
        P9PROTO_OTRUNC = 0x10,  /* truncate file to zero length  before opening it */
        P9PROTO_OREXEC = 0x20,  /* close the file when exec system call is made */
        P9PROTO_ORCLOSE = 0x40, /* remove the file when it is closed */
        P9PROTO_OAPPEND = 0x80, /* open the file and seek to the end of the file */
        P9PROTO_OEXCL = 0x1000, /* only create a file and not open it */
};

/* FIle Permissions */
enum p9_perm_t {
        P9PROTO_DMDIR = 0x80000000,     /* permission  bit for directories */
        P9PROTO_DMAPPEND = 0x40000000,  /* permission bit  for is append-only */
        P9PROTO_DMEXCL = 0x20000000,    /* permission  bit for exclusive use (only one open handle allowed) */
        P9PROTO_DMMOUNT = 0x10000000,   /* permission  bit for mount points */
        P9PROTO_DMAUTH = 0x08000000,    /* permission  bit for authentication file */
        P9PROTO_DMTMP = 0x04000000,     /* permission bit for non-backed-up files */
        P9PROTO_DMSYMLINK = 0x02000000, /* permission bit for symbolic link (9P2000.u) */
        P9PROTO_DMLINK = 0x01000000,    /* permission bit for hard-link (9P2000.u) */
        P9PROTO_DMDEVICE = 0x00800000,  /* permission bit for device files (9P2000.u) */
        P9PROTO_DMNAMEDPIPE = 0x00200000,/* permission bit for named pipe (9P2000.u) */
        P9PROTO_DMSOCKET = 0x00100000,  /* permission bit for socket (9P2000.u) */
        P9PROTO_DMSETUID = 0x00080000,  /* permission bit for setuid (9P2000.u) */
        P9PROTO_DMSETGID = 0x00040000,  /* permission bit for setgid (9P2000.u) */
        P9PROTO_DMSETVTX = 0x00010000,  /* permission bit for sticky bit (9P2000.u) */
};

/*
 * QID types - they are primarly used to
 * differentiate semantics for a file system
 */
enum p9_qid_t {
        P9PROTO_QTDIR = 0x80,           /* directory */
        P9PROTO_QTAPPEND = 0x40,        /* append-only */
        P9PROTO_QTEXCL = 0x20,          /* exclusive use (only one open handle allowed)*/
        P9PROTO_QTMOUNT = 0x10,         /* mount points */
        P9PROTO_QTAUTH = 0x08,          /* authentication file */
        P9PROTO_QTTMP = 0x04,           /* non-backed-up files */
        P9PROTO_QTSYMLINK = 0x02,       /* symbolic links */
        P9PROTO_QTLINK = 0x01,          /* hard link */
        P9PROTO_QTFILE = 0x00,          /* normal files */
};

/* P9 Magic Numbers */
#define P9PROTO_NOFID   (uint32_t)(~0)
#define P9_DEFUNAME     "nobody"
#define P9_DEFANAME     ""
#define P9_NONUNAME     (uint32_t)(~0)
#define P9_MAXWELEM     16

/* Exchange unit between Qemu and Client */
struct p9_qid {
        uint8_t type;           /* the type of the file */
        uint32_t version;       /* version number for given path */
        uint64_t path;          /* the file servers unique id for file */
};

/* FS information stat structure */
struct p9_statfs {
        uint32_t type;          /* type of file system */
        uint32_t bsize;         /* optimal transfer block size */
        uint64_t blocks;        /* total data blocks in file system */
        uint64_t bfree;         /* free blocks in fs */
        uint64_t bavail;        /* free blocks avail to non-superuser */
        uint64_t files;         /* total file nodes in file system */
        uint64_t ffree;         /* free file nodes in fs */
        uint64_t fsid;          /* file system id */
        uint32_t namelen;       /* maximum length of filenames */
};


/* File system metadata information */
struct p9_wstat {
        uint16_t size;          /* total byte count of the following data */
        uint16_t type;          /* type of file */
        uint32_t dev;           /* id of device containing file */
        struct p9_qid qid;      /* identifier used by server for file system entity information */
        uint32_t mode;          /* protection */
        uint32_t atime;         /* time of last access */
        uint32_t mtime;         /* time of last modification */
        uint64_t length;        /* length of file in bytes */
        char *name;             /* file name */
        char *uid;              /* user ID of owner */
        char *gid;              /* group ID of owner */
        char *muid;             /* name of the user who last modified the file */
        char *extension;        /* 9p2000.u extensions */
        uid_t n_uid;            /* 9p2000.u extensions */
        gid_t n_gid;            /* 9p2000.u extensions */
        uid_t n_muid;           /* 9p2000.u extensions */
};

/* The linux version of FS information stat structure*/
struct p9_stat_dotl {
        uint64_t st_result_mask;/* indicates fields that are requested */
        struct p9_qid qid;      /* identifier used by server for file system entity information */
        uint32_t st_mode;       /* protection */
        uid_t st_uid;           /* user ID of owner */
        gid_t st_gid;           /* group ID of owner */
        uint64_t st_nlink;      /* number of hard links */
        uint64_t st_rdev;       /* device ID (if special file) */
        uint64_t st_size;       /* total size, in bytes */
        uint64_t st_blksize;    /* blocksize for file system I/O */
        uint64_t st_blocks;     /* number of 512B blocks allocated */
        uint64_t st_atime_sec;  /* time of last access, seconds */
        uint64_t st_atime_nsec; /* time of last access, nanoseconds */
        uint64_t st_mtime_sec;  /* time of last modification, seconds */
        uint64_t st_mtime_nsec; /* time of last modifictaion, nanoseconds */
        uint64_t st_ctime_sec;  /* time of last status change, seconds*/
        uint64_t st_ctime_nsec; /* time of last status change, nanoseconds*/
        uint64_t st_btime_sec;  /* following memebers are reserved for future use */
        uint64_t st_btime_nsec;
        uint64_t st_gen;
        uint64_t st_data_version;
};

/* P9 inode attribute for setattr */
struct p9_iattr_dotl {
        uint32_t valid;         /* bit fields specifying which fields are valid */
        uint32_t mode;          /* protection */
        uid_t uid;              /* user id of owner */
        gid_t gid;              /* group id */
        uint64_t size;          /* file size */
        uint64_t atime_sec;     /* last access time in seconds */
        uint64_t atime_nsec;    /* last access time in nanoseconds */
        uint64_t mtime_sec;     /* last modification time in seconds */
        uint64_t mtime_nsec;    /* last modification time in nanoseconds */
};

#define P9PROTO_STATS_MODE              0x00000001ULL
#define P9PROTO_STATS_NLINK             0x00000002ULL
#define P9PROTO_STATS_UID               0x00000004ULL
#define P9PROTO_STATS_GID               0x00000008ULL
#define P9PROTO_STATS_RDEV              0x00000010ULL
#define P9PROTO_STATS_ATIME             0x00000020ULL
#define P9PROTO_STATS_MTIME             0x00000040ULL
#define P9PROTO_STATS_CTIME             0x00000080ULL
#define P9PROTO_STATS_INO               0x00000100ULL
#define P9PROTO_STATS_SIZE              0x00000200ULL
#define P9PROTO_STATS_BLOCKS            0x00000400ULL

#define P9PROTO_STATS_BTIME             0x00000800ULL
#define P9PROTO_STATS_GEN               0x00001000ULL
#define P9PROTO_STATS_DATA_VERSION      0x00002000ULL

#define P9PROTO_STATS_BASIC             0x000007ffULL /* Mask for fields up to BLOCKS */
#define P9PROTO_STATS_ALL               0x00003fffULL /* Mask for All fields above */

#define P9PROTO_SETATTR_MODE            0x00000001UL
#define P9PROTO_SETATTR_UID             0x00000002UL
#define P9PROTO_SETATTR_GID             0x00000004UL
#define P9PROTO_SETATTR_SIZE            0x00000008UL
#define P9PROTO_SETATTR_ATIME           0x00000010UL
#define P9PROTO_SETATTR_MTIME           0x00000020UL
#define P9PROTO_SETATTR_CTIME           0x00000040UL
#define P9PROTO_SETATTR_ATIME_SET       0x00000080UL
#define P9PROTO_SETATTR_MTIME_SET       0x00000100UL
#define P9PROTO_SETATTR_MASK            0x000001bfUL

#define P9PROTO_TGETATTR_BLK            512

#define P9PROTO_UNLINKAT_REMOVEDIR      0x200

/* PDU buffer used for SG lists. */
struct p9_buffer {
        uint32_t size;
        uint16_t tag;
        uint8_t id;
        size_t offset;
        size_t capacity;
        uint8_t *sdata;
};

#endif /* FS_P9FS_P9_PROTOCOL_H */